From d786dc995150b5db59fa264f3ff9e408c089de37 Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Sun, 1 Oct 2017 09:04:44 +0200 Subject: [PATCH 001/705] initial commit --- xbmc/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xbmc/__init__.py b/xbmc/__init__.py index 43b25dcfd..6cbb65fdd 100755 --- a/xbmc/__init__.py +++ b/xbmc/__init__.py @@ -54,7 +54,7 @@ class xbmc(lib.connection.Client): _notification_time = 10000 _listen_keys = ['volume', 'mute', 'title', 'media', 'state'] - _send_keys = {'volume': 'Application.SetVolume', 'mute': 'Application.SetMute', 'shutdown': 'System.Shutdown'} + _send_keys = {'volume': 'Application.SetVolume', 'mute': 'Application.SetMute'} def __init__(self, smarthome, item): if 'xbmc_port' in item.conf: @@ -113,7 +113,7 @@ def _send(self, method, params=None, id=None, wait=True): else: data = {"jsonrpc": "2.0", "id": id, "method": method} self._reply_lock.acquire() - logger.debug("XBMC sending: {0}".format(json.dumps(data, separators=(',', ':')))) + #logger.debug("XBMC sending: {0}".format(json.dumps(data, separators=(',', ':')))) self.send((json.dumps(data, separators=(',', ':')) + '\r\n').encode()) if wait: self._reply_lock.wait(2) @@ -129,7 +129,7 @@ def _set_item(self, key, value): def found_balance(self, data): event = json.loads(data.decode()) - logger.debug("XBMC receiving: {0}".format(event)) + #logger.debug("XBMC receiving: {0}".format(event)) if 'id' in event: if event['id'] == self._rid: self._rid = None From a2f594580e1664dbc1274cd079e9e075d74ba0e2 Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Sun, 5 Nov 2017 07:53:08 +0100 Subject: [PATCH 002/705] renamed folder to kodi --- {xbmc => kodi}/README.md | 0 {xbmc => kodi}/__init__.py | 0 {xbmc => kodi}/plugin.yaml | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename {xbmc => kodi}/README.md (100%) rename {xbmc => kodi}/__init__.py (100%) rename {xbmc => kodi}/plugin.yaml (100%) diff --git a/xbmc/README.md b/kodi/README.md similarity index 100% rename from xbmc/README.md rename to kodi/README.md diff --git a/xbmc/__init__.py b/kodi/__init__.py similarity index 100% rename from xbmc/__init__.py rename to kodi/__init__.py diff --git a/xbmc/plugin.yaml b/kodi/plugin.yaml similarity index 100% rename from xbmc/plugin.yaml rename to kodi/plugin.yaml From ef11545bcae4fadcd94fb178da5b7b8b8a6dc489 Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Sun, 5 Nov 2017 07:57:13 +0100 Subject: [PATCH 003/705] fixed license agreement --- kodi/__init__.py | 78 ++++++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 35 deletions(-) diff --git a/kodi/__init__.py b/kodi/__init__.py index 6cbb65fdd..cd0e935a2 100755 --- a/kodi/__init__.py +++ b/kodi/__init__.py @@ -2,8 +2,10 @@ # vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab ######################################################################### # Copyright 2013 Marcus Popp marcus@popp.mx +# Copyright 2017 Sebastian Sudholt sebastian.sudholt@tu-dortmund.de ######################################################################### -# This file is part of SmartHomeNG. https://github.com/smarthomeNG// + +# This file is part of SmartHomeNG. # # SmartHomeNG is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -16,7 +18,7 @@ # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with SmartHomeNG. If not, see . +# along with SmartHome.py. If not, see . ######################################################################### import logging @@ -27,7 +29,7 @@ logger = logging.getLogger('') -class XBMC(): +class Kodi(): def __init__(self, smarthome): self._sh = smarthome @@ -46,22 +48,24 @@ def notify_all(self, title, message, image=None): box.notify(title, message, image) def parse_item(self, item): - if 'xbmc_host' in item.conf: - self._boxes.append(xbmc(self._sh, item)) + if 'kodi_host' in item.conf: + self._boxes.append(kodi(self._sh, item)) -class xbmc(lib.connection.Client): +class kodi(lib.connection.Client): _notification_time = 10000 _listen_keys = ['volume', 'mute', 'title', 'media', 'state'] - _send_keys = {'volume': 'Application.SetVolume', 'mute': 'Application.SetMute'} + _send_keys = {'volume': 'Application.SetVolume', 'mute': 'Application.SetMute', + 'left': 'Input.Left', 'right': 'Input.Right', 'up': 'Input.Up', 'down': 'Input.Down', + 'home': 'Input.Home', 'back': 'Input.Back', 'select': 'Input.Select'} def __init__(self, smarthome, item): - if 'xbmc_port' in item.conf: - port = int(item.conf['xbmc_port']) + if 'kodi_port' in item.conf: + port = int(item.conf['kodi_port']) else: port = 9090 - host = item.conf['xbmc_host'] + host = item.conf['kodi_host'] lib.connection.Client.__init__(self, host, port, monitor=True) self.terminator = 0 self.balance(b'{', b'}') @@ -72,12 +76,12 @@ def __init__(self, smarthome, item): self._reply_lock = threading.Condition() self._reply = None self._items = {'state': item} - for child in self._sh.find_children(item, 'xbmc_listen'): - listen_to = child.conf['xbmc_listen'] + for child in self._sh.find_children(item, 'kodi_listen'): + listen_to = child.conf['kodi_listen'] if listen_to in self._listen_keys: self._items[listen_to] = child - for child in self._sh.find_children(item, 'xbmc_send'): - send_to = child.conf['xbmc_send'] + for child in self._sh.find_children(item, 'kodi_send'): + send_to = child.conf['kodi_send'] if send_to in self._send_keys: child.add_method_trigger(self._send_value) item.notify = self.notify @@ -89,8 +93,12 @@ def notify(self, title, message, image=None): self._send('GUI.ShowNotification', {'title': title, 'message': message, 'image': image, 'displaytime': self._notification_time}) def _send_value(self, item, caller=None, source=None, dest=None): - if caller != 'XBMC': - self._send(self._send_keys[item.conf['xbmc_send']], {item.conf['xbmc_send']: item()}, wait=False) + if caller != 'Kodi': + if 'kodi_params' not in item.conf or item.conf['kodi_params'] == 'None': + params = None + else: + params = item.conf['kodi_params'] + self._send(self._send_keys[item.conf['kodi_send']], params, wait=False) def run(self): self.alive = True @@ -104,16 +112,12 @@ def _send(self, method, params=None, id=None, wait=True): if id > 100: self._id = 0 self._rid = id - - if method == 'System.Shutdown': - params = None - if params is not None: data = {"jsonrpc": "2.0", "id": id, "method": method, 'params': params} else: data = {"jsonrpc": "2.0", "id": id, "method": method} self._reply_lock.acquire() - #logger.debug("XBMC sending: {0}".format(json.dumps(data, separators=(',', ':')))) + #logger.debug("Kodi sending: {0}".format(json.dumps(data, separators=(',', ':')))) self.send((json.dumps(data, separators=(',', ':')) + '\r\n').encode()) if wait: self._reply_lock.wait(2) @@ -125,11 +129,11 @@ def _send(self, method, params=None, id=None, wait=True): def _set_item(self, key, value): if key in self._items: - self._items[key](value, 'XBMC') + self._items[key](value, 'Kodi') def found_balance(self, data): event = json.loads(data.decode()) - #logger.debug("XBMC receiving: {0}".format(event)) + #logger.debug("Kodi receiving: {0}".format(event)) if 'id' in event: if event['id'] == self._rid: self._rid = None @@ -141,32 +145,36 @@ def found_balance(self, data): if 'method' in event: if event['method'] == 'Player.OnPause': if 'state' in self._items: - self._items['state']('Pause', 'XBMC') + self._items['state']('Pause', 'Kodi') elif event['method'] == 'Player.OnStop': if 'state' in self._items: - self._items['state']('Menu', 'XBMC') + self._items['state']('Menu', 'Kodi') if 'media' in self._items: - self._items['media']('', 'XBMC') + self._items['media']('', 'Kodi') if 'title' in self._items: - self._items['title']('', 'XBMC') + self._items['title']('', 'Kodi') + elif event['method'] == 'GUI.OnScreensaverActivated': + if 'state' in self._items: + self._items['state']('Screensaver', 'Kodi') if event['method'] in ['Player.OnPlay']: # use a different thread for event handling - self._sh.trigger('xbmc-event', self._parse_event, 'XBMC', value={'event': event}) + self._sh.trigger('kodi-event', self._parse_event, 'Kodi', value={'event': event}) elif event['method'] in ['Application.OnVolumeChanged']: if 'mute' in self._items: self._set_item('mute', event['params']['data']['muted']) if 'volume' in self._items: self._set_item('volume', event['params']['data']['volume']) + def _parse_event(self, event): if event['method'] == 'Player.OnPlay': result = self._send('Player.GetActivePlayers')['result'] if len(result) == 0: - logger.info("XBMC: no active player found.") + logger.info("Kodi: no active player found.") return playerid = result[0]['playerid'] typ = result[0]['type'] - self._items['state']('Playing', 'XBMC') + self._items['state']('Playing', 'Kodi') if typ == 'video': result = self._send('Player.GetItem', {"properties": ["title"], "playerid": playerid}, "VideoGetItem")['result'] title = result['item']['title'] @@ -174,10 +182,10 @@ def _parse_event(self, event): title = result['item']['label'] if 'media' in self._items: typ = result['item']['type'] - self._items['media'](typ.capitalize(), 'XBMC') + self._items['media'](typ.capitalize(), 'Kodi') elif typ == 'audio': if 'media' in self._items: - self._items['media'](typ.capitalize(), 'XBMC') + self._items['media'](typ.capitalize(), 'Kodi') result = self._send('Player.GetItem', {"properties": ["title", "artist"], "playerid": playerid}, "AudioGetItem")['result'] if len(result['item']['artist']) == 0: artist = 'unknown' @@ -186,10 +194,10 @@ def _parse_event(self, event): title = artist + ' - ' + result['item']['title'] elif typ == 'picture': if 'media' in self._items: - self._items['media'](typ.capitalize(), 'XBMC') + self._items['media'](typ.capitalize(), 'Kodi') title = '' else: - logger.warning("XBMC: Unknown type: {0}".format(typ)) + logger.warning("Kodi: Unknown type: {0}".format(typ)) return if 'title' in self._items: - self._items['title'](title, 'XBMC') + self._items['title'](title, 'Kodi') From c87c924e1cee1e86f2b578e24dc33799216d0615 Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Sun, 5 Nov 2017 10:06:52 +0100 Subject: [PATCH 004/705] moved kodi to smartplugin (untested yet) --- kodi/__init__.py | 540 +++++++++++++++++++++++++++++++++++++---------- kodi/plugin.yaml | 10 +- 2 files changed, 429 insertions(+), 121 deletions(-) diff --git a/kodi/__init__.py b/kodi/__init__.py index cd0e935a2..4278972e2 100755 --- a/kodi/__init__.py +++ b/kodi/__init__.py @@ -21,183 +21,489 @@ # along with SmartHome.py. If not, see . ######################################################################### +# import logging +# import threading +# import json +# +# import lib.connection +# +# logger = logging.getLogger('') +# +# +# class Kodi(object): +# +# def __init__(self, smarthome, host, port='9090'): +# self._sh = smarthome +# self._boxes = [] +# +# def run(self): +# self.alive = True +# +# def stop(self): +# self.alive = False +# for box in self._boxes: +# box.handle_close() +# +# def notify_all(self, title, message, image=None): +# for box in self._boxes: +# box.notify(title, message, image) +# +# def parse_item(self, item): +# if 'kodi_host' in item.conf: +# self._boxes.append(kodi(self._sh, item)) +# +# +# class kodi(lib.connection.Client): +# +# _notification_time = 10000 +# _listen_keys = ['volume', 'mute', 'title', 'media', 'state'] +# _send_keys = {'volume': 'Application.SetVolume', 'mute': 'Application.SetMute', +# 'left': 'Input.Left', 'right': 'Input.Right', 'up': 'Input.Up', 'down': 'Input.Down', +# 'home': 'Input.Home', 'back': 'Input.Back', 'select': 'Input.Select'} +# +# def __init__(self, smarthome, item): +# if 'kodi_port' in item.conf: +# port = int(item.conf['kodi_port']) +# else: +# port = 9090 +# host = item.conf['kodi_host'] +# lib.connection.Client.__init__(self, host, port, monitor=True) +# self.terminator = 0 +# self.balance(b'{', b'}') +# self._sh = smarthome +# self.message_id = 1 +# self._rid = None +# self._cmd_lock = threading.Lock() +# self._reply_lock = threading.Condition() +# self._reply = None +# self._items = {'state': item} +# for child in self._sh.find_children(item, 'kodi_listen'): +# listen_to = child.conf['kodi_listen'] +# if listen_to in self._listen_keys: +# self._items[listen_to] = child +# for child in self._sh.find_children(item, 'kodi_send'): +# send_to = child.conf['kodi_send'] +# if send_to in self._send_keys: +# child.add_method_trigger(self._send_value) +# item.notify = self.notify +# +# def notify(self, title, message, image=None): +# if image is None: +# self._send('GUI.ShowNotification', {'title': title, 'message': message, 'displaytime': self._notification_time}) +# else: +# self._send('GUI.ShowNotification', {'title': title, 'message': message, 'image': image, 'displaytime': self._notification_time}) +# +# def _send_value(self, item, caller=None, source=None, dest=None): +# if caller != 'Kodi': +# if 'kodi_params' not in item.conf or item.conf['kodi_params'] == 'None': +# params = None +# else: +# params = item.conf['kodi_params'] +# self._send(self._send_keys[item.conf['kodi_send']], params, wait=False) +# +# def run(self): +# self.alive = True +# +# def _send(self, method, params=None, id=None, wait=True): +# self._cmd_lock.acquire() +# self._reply = None +# if id is None: +# self.message_id += 1 +# id = self.message_id +# if id > 100: +# self.message_id = 0 +# self._rid = id +# if params is not None: +# data = {"jsonrpc": "2.0", "id": id, "method": method, 'params': params} +# else: +# data = {"jsonrpc": "2.0", "id": id, "method": method} +# self._reply_lock.acquire() +# #logger.debug("Kodi sending: {0}".format(json.dumps(data, separators=(',', ':')))) +# self.send((json.dumps(data, separators=(',', ':')) + '\r\n').encode()) +# if wait: +# self._reply_lock.wait(2) +# self._reply_lock.release() +# reply = self._reply +# self._reply = None +# self._cmd_lock.release() +# return reply +# +# def _set_item(self, key, value): +# if key in self._items: +# self._items[key](value, 'Kodi') +# +# def found_balance(self, data): +# event = json.loads(data.decode()) +# #logger.debug("Kodi receiving: {0}".format(event)) +# if 'id' in event: +# if event['id'] == self._rid: +# self._rid = None +# self._reply = event +# self._reply_lock.acquire() +# self._reply_lock.notify() +# self._reply_lock.release() +# return +# if 'method' in event: +# if event['method'] == 'Player.OnPause': +# if 'state' in self._items: +# self._items['state']('Pause', 'Kodi') +# elif event['method'] == 'Player.OnStop': +# if 'state' in self._items: +# self._items['state']('Menu', 'Kodi') +# if 'media' in self._items: +# self._items['media']('', 'Kodi') +# if 'title' in self._items: +# self._items['title']('', 'Kodi') +# elif event['method'] == 'GUI.OnScreensaverActivated': +# if 'state' in self._items: +# self._items['state']('Screensaver', 'Kodi') +# if event['method'] in ['Player.OnPlay']: +# # use a different thread for event handling +# self._sh.trigger('kodi-event', self._parse_event, 'Kodi', value={'event': event}) +# elif event['method'] in ['Application.OnVolumeChanged']: +# if 'mute' in self._items: +# self._set_item('mute', event['params']['data']['muted']) +# if 'volume' in self._items: +# self._set_item('volume', event['params']['data']['volume']) +# +# +# def _parse_event(self, event): +# if event['method'] == 'Player.OnPlay': +# result = self._send('Player.GetActivePlayers')['result'] +# if len(result) == 0: +# logger.info("Kodi: no active player found.") +# return +# playerid = result[0]['playerid'] +# typ = result[0]['type'] +# self._items['state']('Playing', 'Kodi') +# if typ == 'video': +# result = self._send('Player.GetItem', {"properties": ["title"], "playerid": playerid}, "VideoGetItem")['result'] +# title = result['item']['title'] +# if not title and 'label' in result['item']: +# title = result['item']['label'] +# if 'media' in self._items: +# typ = result['item']['type'] +# self._items['media'](typ.capitalize(), 'Kodi') +# elif typ == 'audio': +# if 'media' in self._items: +# self._items['media'](typ.capitalize(), 'Kodi') +# result = self._send('Player.GetItem', {"properties": ["title", "artist"], "playerid": playerid}, "AudioGetItem")['result'] +# if len(result['item']['artist']) == 0: +# artist = 'unknown' +# else: +# artist = result['item']['artist'][0] +# title = artist + ' - ' + result['item']['title'] +# elif typ == 'picture': +# if 'media' in self._items: +# self._items['media'](typ.capitalize(), 'Kodi') +# title = '' +# else: +# logger.warning("Kodi: Unknown type: {0}".format(typ)) +# return +# if 'title' in self._items: +# self._items['title'](title, 'Kodi') + + + ### import logging import threading import json -import lib.connection -logger = logging.getLogger('') +from lib.model.smartplugin import SmartPlugin +from lib.connection import Client -class Kodi(): +class Kodi(SmartPlugin, Client): + ''' + Main class of the Plugin. Does all plugin specific stuff and provides + the update functions for the items + ''' + + PLUGIN_VERSION='1.3c.0' + + _listen_keys = ['volume', 'mute', 'title', 'media', 'state'] + _send_keys = {'volume': dict(method='Application.SetVolume', params=dict(volume='ITEM_VALUE')), + 'mute ': dict(method='Application.SetMute', params = dict(mute='ITEM_VALUE')), + 'left' : dict(method='Input.Left', params=None), + 'right' : dict(method='Input.Right', params=None), + 'up' : dict(method='Input.Up', params=None), + 'down' : dict(method='Input.Down', params=None), + 'home' : dict(method='Input.Home', params=None), + 'back' : dict(method='Input.Back', params=None), + 'select': dict(method='Input.Select', params=None)} + + def __init__(self, sh, *args, **kwargs): + ''' + Initalizes the plugin. The parameters describe for this method are pulled from the entry in plugin.conf. + + :param sh: **Deprecated**: The instance of the smarthome object. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! + :param *args: **Deprecated**: Old way of passing parameter values. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! + :param **kwargs:**Deprecated**: Old way of passing parameter values. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! + + If you need the sh object at all, use the method self.get_sh() to get it. There should be almost no need for + a reference to the sh object any more. + + The parameters *args and **kwargs are the old way of passing parameters. They are deprecated. They are implemented + to support oder plugins. Plugins for SmartHomeNG v1.4 and beyond should use the new way of getting parameter values: + use the SmartPlugin method `get_parameter_value(parameter_name)` instead. Anywhere within the Plugin you can get + the configured (and checked) value for a parameter by calling `self.get_parameter_value(parameter_name)`. It + returns the value in the datatype that is defined in the metadata. + ''' + # init logger + self.logger = logging.getLogger(__name__) + self.logger.info('Init Kodi Plugin') + + # setup everything for the connection later +# if 'kodi_port' in item.conf: +# port = int(item.conf['kodi_port']) +# else: +# port = 9090 +# host = item.conf['kodi_host'] + Client.__init__(self, + self.get_parameter_value('host'), + self.get_parameter_value('port'), + monitor=True) + self.terminator = 0 + self.balance(b'{', b'}') +# self._sh = smarthome + self.message_id = 1 + self.response_id = None + self.cmd_lock = threading.Lock() + self.reply_lock = threading.Condition() + self.reply = None + self.registered_items = {key: [] for key in set(Kodi._send_keys.keys() + Kodi._listen_keys)} +# self._items = {'state': item} +# for child in self._sh.find_children(item, 'kodi_listen'): +# listen_to = child.conf['kodi_listen'] +# if listen_to in self._listen_keys: +# self._items[listen_to] = child +# for child in self._sh.find_children(item, 'kodi_send'): +# send_to = child.conf['kodi_send'] +# if send_to in self._send_keys: +# child.add_method_trigger(self._send_value) +# item.notify = self.notify - def __init__(self, smarthome): - self._sh = smarthome - self._boxes = [] def run(self): + ''' + Run method for the plugin + ''' + self.logger.debug('Plugin \'{}\': run method called'.format(self.get_shortname())) self.alive = True def stop(self): + ''' + Stop method for the plugin + ''' + self.logger.debug('Plugin \'{}\': stop method called'.format(self.get_shortname())) self.alive = False - for box in self._boxes: - box.handle_close() - def notify_all(self, title, message, image=None): - for box in self._boxes: - box.notify(title, message, image) def parse_item(self, item): - if 'kodi_host' in item.conf: - self._boxes.append(kodi(self._sh, item)) + ''' + Default plugin parse_item method. Is called when the plugin is initialized. + The plugin can, corresponding to its attribute keywords, decide what to do with + the item in future, like adding it to an internal array for future reference + :param item: The item to process. + :return: If the plugin needs to be informed of an items change you should return a call back function + like the function update_item down below. An example when this is needed is the knx plugin + where parse_item returns the update_item function when the attribute knx_send is found. + This means that when the items value is about to be updated, the call back function is called + with the item, caller, source and dest as arguments and in case of the knx plugin the value + can be sent to the knx with a knx write function within the knx plugin. + ''' + if self.has_iattr(item.conf, 'kodi_item'): + self.logger.debug('Plugin \'{}\': parse item: {}'.format(self.get_shortname(), item)) + if item.name in Kodi._send_keys: + return self.update_item + # todo + # if interesting item for sending values: + # return update_item -class kodi(lib.connection.Client): - _notification_time = 10000 - _listen_keys = ['volume', 'mute', 'title', 'media', 'state'] - _send_keys = {'volume': 'Application.SetVolume', 'mute': 'Application.SetMute', - 'left': 'Input.Left', 'right': 'Input.Right', 'up': 'Input.Up', 'down': 'Input.Down', - 'home': 'Input.Home', 'back': 'Input.Back', 'select': 'Input.Select'} + def parse_logic(self, logic): + ''' + Default plugin parse_logic method + ''' + if 'xxx' in logic.conf: + # self.function(logic['name']) + pass - def __init__(self, smarthome, item): - if 'kodi_port' in item.conf: - port = int(item.conf['kodi_port']) - else: - port = 9090 - host = item.conf['kodi_host'] - lib.connection.Client.__init__(self, host, port, monitor=True) - self.terminator = 0 - self.balance(b'{', b'}') - self._sh = smarthome - self._id = 1 - self._rid = None - self._cmd_lock = threading.Lock() - self._reply_lock = threading.Condition() - self._reply = None - self._items = {'state': item} - for child in self._sh.find_children(item, 'kodi_listen'): - listen_to = child.conf['kodi_listen'] - if listen_to in self._listen_keys: - self._items[listen_to] = child - for child in self._sh.find_children(item, 'kodi_send'): - send_to = child.conf['kodi_send'] - if send_to in self._send_keys: - child.add_method_trigger(self._send_value) - item.notify = self.notify - - def notify(self, title, message, image=None): - if image is None: - self._send('GUI.ShowNotification', {'title': title, 'message': message, 'displaytime': self._notification_time}) - else: - self._send('GUI.ShowNotification', {'title': title, 'message': message, 'image': image, 'displaytime': self._notification_time}) - def _send_value(self, item, caller=None, source=None, dest=None): - if caller != 'Kodi': - if 'kodi_params' not in item.conf or item.conf['kodi_params'] == 'None': - params = None - else: - params = item.conf['kodi_params'] - self._send(self._send_keys[item.conf['kodi_send']], params, wait=False) + def update_item(self, item, caller=None, source=None, dest=None): + ''' + Callback method for sending values to Kodi when a registered item has changed - def run(self): - self.alive = True + :param item: item to be updated towards the plugin + :param caller: if given it represents the callers name + :param source: if given it represents the source + :param dest: if given it represents the dest + ''' + if item(): + if caller != 'Kodi' and self.has_iattr(item.conf, 'kodi_item'): + # update item was triggered from sometthing else then this plugin -> send to Kodi + kodi_item = self.get_iattr_value(item.conf, 'kodi_item') + if kodi_item in Kodi._send_keys: + self.logger.debug('Plugin \'{}\': update_item ws called with item \'{}\' from caller \'{}\', source \'{}\' and dest \'{}\''.format(self.get_shortname(), item, caller, source, dest)) + method = self._send_keys[kodi_item]['method'] + params = self._send_keys[kodi_item]['params'] + if params is not None: + # copy so we don't interfer with the class variable + params = params.copy() + # replace the wild card ITEM_VALUE with the item's value + for key, value in params.items(): + if value == 'ITEM_VALUE': + params[key] = item() + self._send(method, params, wait=False) + else: + self.logger.info('kodi_item \'%s\' not in send_keys, skipping!', kodi_item) + + def notify(self, title, message, image=None, display_time=10000): + ''' + Send a notification to Kodi to be displayed on the screen + + :param title: the title of the message + :param message: the message itself + :param image: an optional image to be displayed alongside the message + :param display_time: how long the message is displayed in milli seconds + ''' + params = dict(title=title, message=message,displaytime=display_time) + if image is not None: + params['image'] = image + self.send_kodi_rpc(method='GUI.ShowNotification', params=params) + +# def _send_value(self, item, caller=None, source=None, dest=None): +# if caller != 'Kodi': +# if 'kodi_params' not in item.conf or item.conf['kodi_params'] == 'None': +# params = None +# else: +# params = item.conf['kodi_params'] +# self.send_kodi_rpc(self._send_keys[item.conf['kodi_send']], params, wait=False) - def _send(self, method, params=None, id=None, wait=True): - self._cmd_lock.acquire() - self._reply = None - if id is None: - self._id += 1 - id = self._id + def send_kodi_rpc(self, method, params=None, message_id=None, wait=True): + self.cmd_lock.acquire() + self.reply = None + if message_id is None: + self.message_id += 1 + message_id = self.message_id if id > 100: - self._id = 0 - self._rid = id + self.message_id = 0 + self.response_id = message_id if params is not None: - data = {"jsonrpc": "2.0", "id": id, "method": method, 'params': params} + data = {'jsonrpc': '2.0', 'id': message_id, 'method': method, 'params': params} else: - data = {"jsonrpc": "2.0", "id": id, "method": method} - self._reply_lock.acquire() - #logger.debug("Kodi sending: {0}".format(json.dumps(data, separators=(',', ':')))) + data = {'jsonrpc': '2.0', 'id': message_id, 'method': method} + self.reply_lock.acquire() + self.logger.debug('Kodi sending: {0}'.format(json.dumps(data, separators=(',', ':')))) self.send((json.dumps(data, separators=(',', ':')) + '\r\n').encode()) if wait: - self._reply_lock.wait(2) - self._reply_lock.release() - reply = self._reply - self._reply = None - self._cmd_lock.release() + self.reply_lock.wait(2) + self.reply_lock.release() + reply = self.reply + self.reply = None + self.cmd_lock.release() return reply - def _set_item(self, key, value): - if key in self._items: - self._items[key](value, 'Kodi') +# def _set_item(self, key, value): +# if key in self._items: +# self._items[key](value, 'Kodi') def found_balance(self, data): event = json.loads(data.decode()) - #logger.debug("Kodi receiving: {0}".format(event)) + self.logger.debug('Kodi receiving: {0}'.format(event)) if 'id' in event: - if event['id'] == self._rid: - self._rid = None - self._reply = event - self._reply_lock.acquire() - self._reply_lock.notify() - self._reply_lock.release() + if event['id'] == self.response_id: + self.response_id = None + self.reply = event + self.reply_lock.acquire() + self.reply_lock.notify() + self.reply_lock.release() return if 'method' in event: if event['method'] == 'Player.OnPause': - if 'state' in self._items: - self._items['state']('Pause', 'Kodi') + for elem in self.registered_items['state']: + elem('Pause', caller='Kodi') +# if 'state' in self._items: +# self._items['state']('Pause', 'Kodi') elif event['method'] == 'Player.OnStop': - if 'state' in self._items: - self._items['state']('Menu', 'Kodi') - if 'media' in self._items: - self._items['media']('', 'Kodi') - if 'title' in self._items: - self._items['title']('', 'Kodi') +# if 'state' in self._items: +# self._items['state']('Menu', 'Kodi') + for elem in self.registered_items['state']: + elem('Pause', caller='Kodi') +# if 'media' in self._items: +# self._items['media']('', 'Kodi') + for elem in self.registered_items['media']: + elem('', caller='Kodi') +# if 'title' in self._items: +# self._items['title']('', 'Kodi') + for elem in self.registered_items['title']: + elem('Pause', caller='Kodi') elif event['method'] == 'GUI.OnScreensaverActivated': - if 'state' in self._items: - self._items['state']('Screensaver', 'Kodi') +# if 'state' in self._items: +# self._items['state']('Screensaver', 'Kodi') + for elem in self.registered_items['state']: + elem('Screensaver', caller='Kodi') if event['method'] in ['Player.OnPlay']: # use a different thread for event handling - self._sh.trigger('kodi-event', self._parse_event, 'Kodi', value={'event': event}) + self.get_sh().trigger('kodi-event', self._parse_event, 'Kodi', value={'event': event}) elif event['method'] in ['Application.OnVolumeChanged']: - if 'mute' in self._items: - self._set_item('mute', event['params']['data']['muted']) - if 'volume' in self._items: - self._set_item('volume', event['params']['data']['volume']) - +# if 'mute' in self._items: +# self._set_item('mute', event['params']['data']['muted']) + for elem in self.registered_items['mute']: + elem(event['params']['data']['muted'], caller='Kodi') +# if 'volume' in self._items: +# self._set_item('volume', event['params']['data']['volume']) + for elem in self.registered_items['volume']: + elem(event['params']['data']['volume'], caller='Kodi') def _parse_event(self, event): if event['method'] == 'Player.OnPlay': - result = self._send('Player.GetActivePlayers')['result'] + result = self.send_kodi_rpc(method='Player.GetActivePlayers')['result'] if len(result) == 0: - logger.info("Kodi: no active player found.") + self.logger.info('Kodi: no active player found.') return playerid = result[0]['playerid'] typ = result[0]['type'] - self._items['state']('Playing', 'Kodi') +# self._items['state']('Playing', 'Kodi') + for elem in self.registered_items['state']: + elem('Playing', caller='Kodi') if typ == 'video': - result = self._send('Player.GetItem', {"properties": ["title"], "playerid": playerid}, "VideoGetItem")['result'] + result = self.send_kodi_rpc(method='Player.GetItem', + params=dict(properties=['title'], playerid=playerid), + message_id='VideoGetItem')['result'] title = result['item']['title'] + typ = result['item']['type'] if not title and 'label' in result['item']: title = result['item']['label'] - if 'media' in self._items: - typ = result['item']['type'] - self._items['media'](typ.capitalize(), 'Kodi') +# if 'media' in self._items: +# typ = result['item']['type'] +# self._items['media'](typ.capitalize(), 'Kodi') + for elem in self.registered_items['media']: + elem(typ.capitalize(), caller='Kodi') elif typ == 'audio': - if 'media' in self._items: - self._items['media'](typ.capitalize(), 'Kodi') - result = self._send('Player.GetItem', {"properties": ["title", "artist"], "playerid": playerid}, "AudioGetItem")['result'] +# if 'media' in self._items: +# self._items['media'](typ.capitalize(), 'Kodi') + for elem in self.registered_items['media']: + elem('Audio', caller='Kodi') + result = self.send_kodi_rpc(method='Player.GetItem', + params=dict(properties=['title', 'artist'], playerid=playerid), + message_id='AudioGetItem')['result'] if len(result['item']['artist']) == 0: artist = 'unknown' else: artist = result['item']['artist'][0] title = artist + ' - ' + result['item']['title'] elif typ == 'picture': - if 'media' in self._items: - self._items['media'](typ.capitalize(), 'Kodi') +# if 'media' in self._items: +# self._items['media'](typ.capitalize(), 'Kodi') + for elem in self.registered_items['media']: + elem('Picture', caller='Kodi') title = '' else: - logger.warning("Kodi: Unknown type: {0}".format(typ)) + self.logger.warning('Kodi: Unknown type: {0}'.format(typ)) return - if 'title' in self._items: - self._items['title'](title, 'Kodi') +# if 'title' in self._items: +# self._items['title'](title, 'Kodi') + for elem in self.registered_items['title']: + elem(title, caller='Kodi') diff --git a/kodi/plugin.yaml b/kodi/plugin.yaml index 5ae0b65eb..2f61b24df 100755 --- a/kodi/plugin.yaml +++ b/kodi/plugin.yaml @@ -12,14 +12,16 @@ plugin: # support: https://knx-user-forum.de/forum/supportforen/smarthome-py # Following entries are for Smart-Plugins: -# version: 1.3.3 # Plugin version -# sh_minversion: 1.3 # minimum shNG version to use this plugin + version: 1.3c.0 # Plugin version + sh_minversion: 1.3c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) -# multi_instance: False - classname: XBMC # class containing the plugin + multi_instance: True + classname: Kodi # class containing the plugin #parameters: # Definition of parameters to be configured in etc/plugin.yaml + host: str + port: int #item_attributes: # Definition of item attributes defined by this plugin From 0b0b2277d6908efe6975cec567f7d5a450644ad8 Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Tue, 7 Nov 2017 07:15:03 +0100 Subject: [PATCH 005/705] updated to SmartPlugin, needs testing --- kodi/__init__.py | 1 + kodi/plugin.yaml | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/kodi/__init__.py b/kodi/__init__.py index 4278972e2..1dd924fec 100755 --- a/kodi/__init__.py +++ b/kodi/__init__.py @@ -220,6 +220,7 @@ class Kodi(SmartPlugin, Client): ''' PLUGIN_VERSION='1.3c.0' + ALLOW_MULTIINSTANCE = True _listen_keys = ['volume', 'mute', 'title', 'media', 'state'] _send_keys = {'volume': dict(method='Application.SetVolume', params=dict(volume='ITEM_VALUE')), diff --git a/kodi/plugin.yaml b/kodi/plugin.yaml index 2f61b24df..d4b5cc3ce 100755 --- a/kodi/plugin.yaml +++ b/kodi/plugin.yaml @@ -20,8 +20,12 @@ plugin: #parameters: # Definition of parameters to be configured in etc/plugin.yaml - host: str - port: int + host: + type: ipv4 + + port: + type: int + default: 9090 #item_attributes: # Definition of item attributes defined by this plugin From 4eb479d7dde9fa9f746214972ec4136a4b3ed4e0 Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Tue, 7 Nov 2017 17:46:53 +0100 Subject: [PATCH 006/705] preliminary finish, already some testing done --- kodi/__init__.py | 366 ++++++++++------------------------------------- kodi/plugin.yaml | 2 +- 2 files changed, 80 insertions(+), 288 deletions(-) diff --git a/kodi/__init__.py b/kodi/__init__.py index 1dd924fec..f4c7d4ea7 100755 --- a/kodi/__init__.py +++ b/kodi/__init__.py @@ -21,190 +21,6 @@ # along with SmartHome.py. If not, see . ######################################################################### -# import logging -# import threading -# import json -# -# import lib.connection -# -# logger = logging.getLogger('') -# -# -# class Kodi(object): -# -# def __init__(self, smarthome, host, port='9090'): -# self._sh = smarthome -# self._boxes = [] -# -# def run(self): -# self.alive = True -# -# def stop(self): -# self.alive = False -# for box in self._boxes: -# box.handle_close() -# -# def notify_all(self, title, message, image=None): -# for box in self._boxes: -# box.notify(title, message, image) -# -# def parse_item(self, item): -# if 'kodi_host' in item.conf: -# self._boxes.append(kodi(self._sh, item)) -# -# -# class kodi(lib.connection.Client): -# -# _notification_time = 10000 -# _listen_keys = ['volume', 'mute', 'title', 'media', 'state'] -# _send_keys = {'volume': 'Application.SetVolume', 'mute': 'Application.SetMute', -# 'left': 'Input.Left', 'right': 'Input.Right', 'up': 'Input.Up', 'down': 'Input.Down', -# 'home': 'Input.Home', 'back': 'Input.Back', 'select': 'Input.Select'} -# -# def __init__(self, smarthome, item): -# if 'kodi_port' in item.conf: -# port = int(item.conf['kodi_port']) -# else: -# port = 9090 -# host = item.conf['kodi_host'] -# lib.connection.Client.__init__(self, host, port, monitor=True) -# self.terminator = 0 -# self.balance(b'{', b'}') -# self._sh = smarthome -# self.message_id = 1 -# self._rid = None -# self._cmd_lock = threading.Lock() -# self._reply_lock = threading.Condition() -# self._reply = None -# self._items = {'state': item} -# for child in self._sh.find_children(item, 'kodi_listen'): -# listen_to = child.conf['kodi_listen'] -# if listen_to in self._listen_keys: -# self._items[listen_to] = child -# for child in self._sh.find_children(item, 'kodi_send'): -# send_to = child.conf['kodi_send'] -# if send_to in self._send_keys: -# child.add_method_trigger(self._send_value) -# item.notify = self.notify -# -# def notify(self, title, message, image=None): -# if image is None: -# self._send('GUI.ShowNotification', {'title': title, 'message': message, 'displaytime': self._notification_time}) -# else: -# self._send('GUI.ShowNotification', {'title': title, 'message': message, 'image': image, 'displaytime': self._notification_time}) -# -# def _send_value(self, item, caller=None, source=None, dest=None): -# if caller != 'Kodi': -# if 'kodi_params' not in item.conf or item.conf['kodi_params'] == 'None': -# params = None -# else: -# params = item.conf['kodi_params'] -# self._send(self._send_keys[item.conf['kodi_send']], params, wait=False) -# -# def run(self): -# self.alive = True -# -# def _send(self, method, params=None, id=None, wait=True): -# self._cmd_lock.acquire() -# self._reply = None -# if id is None: -# self.message_id += 1 -# id = self.message_id -# if id > 100: -# self.message_id = 0 -# self._rid = id -# if params is not None: -# data = {"jsonrpc": "2.0", "id": id, "method": method, 'params': params} -# else: -# data = {"jsonrpc": "2.0", "id": id, "method": method} -# self._reply_lock.acquire() -# #logger.debug("Kodi sending: {0}".format(json.dumps(data, separators=(',', ':')))) -# self.send((json.dumps(data, separators=(',', ':')) + '\r\n').encode()) -# if wait: -# self._reply_lock.wait(2) -# self._reply_lock.release() -# reply = self._reply -# self._reply = None -# self._cmd_lock.release() -# return reply -# -# def _set_item(self, key, value): -# if key in self._items: -# self._items[key](value, 'Kodi') -# -# def found_balance(self, data): -# event = json.loads(data.decode()) -# #logger.debug("Kodi receiving: {0}".format(event)) -# if 'id' in event: -# if event['id'] == self._rid: -# self._rid = None -# self._reply = event -# self._reply_lock.acquire() -# self._reply_lock.notify() -# self._reply_lock.release() -# return -# if 'method' in event: -# if event['method'] == 'Player.OnPause': -# if 'state' in self._items: -# self._items['state']('Pause', 'Kodi') -# elif event['method'] == 'Player.OnStop': -# if 'state' in self._items: -# self._items['state']('Menu', 'Kodi') -# if 'media' in self._items: -# self._items['media']('', 'Kodi') -# if 'title' in self._items: -# self._items['title']('', 'Kodi') -# elif event['method'] == 'GUI.OnScreensaverActivated': -# if 'state' in self._items: -# self._items['state']('Screensaver', 'Kodi') -# if event['method'] in ['Player.OnPlay']: -# # use a different thread for event handling -# self._sh.trigger('kodi-event', self._parse_event, 'Kodi', value={'event': event}) -# elif event['method'] in ['Application.OnVolumeChanged']: -# if 'mute' in self._items: -# self._set_item('mute', event['params']['data']['muted']) -# if 'volume' in self._items: -# self._set_item('volume', event['params']['data']['volume']) -# -# -# def _parse_event(self, event): -# if event['method'] == 'Player.OnPlay': -# result = self._send('Player.GetActivePlayers')['result'] -# if len(result) == 0: -# logger.info("Kodi: no active player found.") -# return -# playerid = result[0]['playerid'] -# typ = result[0]['type'] -# self._items['state']('Playing', 'Kodi') -# if typ == 'video': -# result = self._send('Player.GetItem', {"properties": ["title"], "playerid": playerid}, "VideoGetItem")['result'] -# title = result['item']['title'] -# if not title and 'label' in result['item']: -# title = result['item']['label'] -# if 'media' in self._items: -# typ = result['item']['type'] -# self._items['media'](typ.capitalize(), 'Kodi') -# elif typ == 'audio': -# if 'media' in self._items: -# self._items['media'](typ.capitalize(), 'Kodi') -# result = self._send('Player.GetItem', {"properties": ["title", "artist"], "playerid": playerid}, "AudioGetItem")['result'] -# if len(result['item']['artist']) == 0: -# artist = 'unknown' -# else: -# artist = result['item']['artist'][0] -# title = artist + ' - ' + result['item']['title'] -# elif typ == 'picture': -# if 'media' in self._items: -# self._items['media'](typ.capitalize(), 'Kodi') -# title = '' -# else: -# logger.warning("Kodi: Unknown type: {0}".format(typ)) -# return -# if 'title' in self._items: -# self._items['title'](title, 'Kodi') - - - ### import logging import threading import json @@ -222,9 +38,10 @@ class Kodi(SmartPlugin, Client): PLUGIN_VERSION='1.3c.0' ALLOW_MULTIINSTANCE = True - _listen_keys = ['volume', 'mute', 'title', 'media', 'state'] - _send_keys = {'volume': dict(method='Application.SetVolume', params=dict(volume='ITEM_VALUE')), - 'mute ': dict(method='Application.SetMute', params = dict(mute='ITEM_VALUE')), + _get_items = ['volume', 'mute', 'title', 'media', 'state'] + + _set_items = {'volume': dict(method='Application.SetVolume', params=dict(volume='ITEM_VALUE')), + 'mute' : dict(method='Application.SetMute', params = dict(mute='ITEM_VALUE')), 'left' : dict(method='Input.Left', params=None), 'right' : dict(method='Input.Right', params=None), 'up' : dict(method='Input.Up', params=None), @@ -253,37 +70,18 @@ def __init__(self, sh, *args, **kwargs): # init logger self.logger = logging.getLogger(__name__) self.logger.info('Init Kodi Plugin') - - # setup everything for the connection later -# if 'kodi_port' in item.conf: -# port = int(item.conf['kodi_port']) -# else: -# port = 9090 -# host = item.conf['kodi_host'] Client.__init__(self, self.get_parameter_value('host'), self.get_parameter_value('port'), monitor=True) self.terminator = 0 self.balance(b'{', b'}') -# self._sh = smarthome self.message_id = 1 self.response_id = None self.cmd_lock = threading.Lock() self.reply_lock = threading.Condition() self.reply = None - self.registered_items = {key: [] for key in set(Kodi._send_keys.keys() + Kodi._listen_keys)} -# self._items = {'state': item} -# for child in self._sh.find_children(item, 'kodi_listen'): -# listen_to = child.conf['kodi_listen'] -# if listen_to in self._listen_keys: -# self._items[listen_to] = child -# for child in self._sh.find_children(item, 'kodi_send'): -# send_to = child.conf['kodi_send'] -# if send_to in self._send_keys: -# child.add_method_trigger(self._send_value) -# item.notify = self.notify - + self.registered_items = {key: [] for key in set(list(Kodi._set_items.keys()) + Kodi._get_items)} def run(self): ''' @@ -298,7 +96,22 @@ def stop(self): ''' self.logger.debug('Plugin \'{}\': stop method called'.format(self.get_shortname())) self.alive = False - + + def handle_connect(self): + ''' + This method is called on a succesful connect to Kodi + On a connect initialize all items with values extracted from Kodi + ''' + # get volume and mute state + result = self.send_kodi_rpc(method='Application.GetProperties', + params=dict(properties=['volume', 'muted']))['result'] + for elem in self.registered_items['mute']: + elem(result['muted'], caller='Kodi') + for elem in self.registered_items['volume']: + elem(result['volume'], caller='Kodi') + + # parse active player (if present) + self._get_player_info() def parse_item(self, item): ''' @@ -314,15 +127,15 @@ def parse_item(self, item): can be sent to the knx with a knx write function within the knx plugin. ''' if self.has_iattr(item.conf, 'kodi_item'): + kodi_item = self.get_iattr_value(item.conf, 'kodi_item') self.logger.debug('Plugin \'{}\': parse item: {}'.format(self.get_shortname(), item)) - if item.name in Kodi._send_keys: + if kodi_item in self.registered_items: + self.registered_items[kodi_item].append(item) + else: + self.logger.warning('I do not know the kodi_item \'%s\', skipping!', kodi_item) + if kodi_item in Kodi._set_items: return self.update_item - # todo - # if interesting item for sending values: - # return update_item - - def parse_logic(self, logic): ''' Default plugin parse_logic method @@ -345,10 +158,10 @@ def update_item(self, item, caller=None, source=None, dest=None): if caller != 'Kodi' and self.has_iattr(item.conf, 'kodi_item'): # update item was triggered from sometthing else then this plugin -> send to Kodi kodi_item = self.get_iattr_value(item.conf, 'kodi_item') - if kodi_item in Kodi._send_keys: + if kodi_item in Kodi._set_items: self.logger.debug('Plugin \'{}\': update_item ws called with item \'{}\' from caller \'{}\', source \'{}\' and dest \'{}\''.format(self.get_shortname(), item, caller, source, dest)) - method = self._send_keys[kodi_item]['method'] - params = self._send_keys[kodi_item]['params'] + method = self._set_items[kodi_item]['method'] + params = self._set_items[kodi_item]['params'] if params is not None: # copy so we don't interfer with the class variable params = params.copy() @@ -374,21 +187,13 @@ def notify(self, title, message, image=None, display_time=10000): params['image'] = image self.send_kodi_rpc(method='GUI.ShowNotification', params=params) -# def _send_value(self, item, caller=None, source=None, dest=None): -# if caller != 'Kodi': -# if 'kodi_params' not in item.conf or item.conf['kodi_params'] == 'None': -# params = None -# else: -# params = item.conf['kodi_params'] -# self.send_kodi_rpc(self._send_keys[item.conf['kodi_send']], params, wait=False) - def send_kodi_rpc(self, method, params=None, message_id=None, wait=True): self.cmd_lock.acquire() self.reply = None if message_id is None: self.message_id += 1 message_id = self.message_id - if id > 100: + if message_id > 99: self.message_id = 0 self.response_id = message_id if params is not None: @@ -406,10 +211,6 @@ def send_kodi_rpc(self, method, params=None, message_id=None, wait=True): self.cmd_lock.release() return reply -# def _set_item(self, key, value): -# if key in self._items: -# self._items[key](value, 'Kodi') - def found_balance(self, data): event = json.loads(data.decode()) self.logger.debug('Kodi receiving: {0}'.format(event)) @@ -425,86 +226,77 @@ def found_balance(self, data): if event['method'] == 'Player.OnPause': for elem in self.registered_items['state']: elem('Pause', caller='Kodi') -# if 'state' in self._items: -# self._items['state']('Pause', 'Kodi') elif event['method'] == 'Player.OnStop': -# if 'state' in self._items: -# self._items['state']('Menu', 'Kodi') for elem in self.registered_items['state']: - elem('Pause', caller='Kodi') -# if 'media' in self._items: -# self._items['media']('', 'Kodi') + elem('Stopped Player', caller='Kodi') for elem in self.registered_items['media']: elem('', caller='Kodi') -# if 'title' in self._items: -# self._items['title']('', 'Kodi') for elem in self.registered_items['title']: - elem('Pause', caller='Kodi') + elem('', caller='Kodi') elif event['method'] == 'GUI.OnScreensaverActivated': -# if 'state' in self._items: -# self._items['state']('Screensaver', 'Kodi') for elem in self.registered_items['state']: elem('Screensaver', caller='Kodi') if event['method'] in ['Player.OnPlay']: # use a different thread for event handling - self.get_sh().trigger('kodi-event', self._parse_event, 'Kodi', value={'event': event}) + self.get_sh().trigger('kodi-event', self._get_player_info, 'Kodi') elif event['method'] in ['Application.OnVolumeChanged']: -# if 'mute' in self._items: -# self._set_item('mute', event['params']['data']['muted']) for elem in self.registered_items['mute']: elem(event['params']['data']['muted'], caller='Kodi') -# if 'volume' in self._items: -# self._set_item('volume', event['params']['data']['volume']) for elem in self.registered_items['volume']: elem(event['params']['data']['volume'], caller='Kodi') - def _parse_event(self, event): - if event['method'] == 'Player.OnPlay': - result = self.send_kodi_rpc(method='Player.GetActivePlayers')['result'] - if len(result) == 0: - self.logger.info('Kodi: no active player found.') - return - playerid = result[0]['playerid'] - typ = result[0]['type'] -# self._items['state']('Playing', 'Kodi') + def _get_player_info(self): + result = self.send_kodi_rpc(method='Player.GetActivePlayers')['result'] + if len(result) == 0: + self.logger.info('Kodi: no active player found.') + for elem in self.registered_items['title']: + elem('', caller='Kodi') + for elem in self.registered_items['media']: + elem('', caller='Kodi') for elem in self.registered_items['state']: - elem('Playing', caller='Kodi') - if typ == 'video': - result = self.send_kodi_rpc(method='Player.GetItem', - params=dict(properties=['title'], playerid=playerid), - message_id='VideoGetItem')['result'] - title = result['item']['title'] - typ = result['item']['type'] - if not title and 'label' in result['item']: - title = result['item']['label'] + elem('No Active Player', caller='Kodi') + return + playerid = result[0]['playerid'] + typ = result[0]['type'] +# self._items['state']('Playing', 'Kodi') + for elem in self.registered_items['state']: + elem('Playing', caller='Kodi') + if typ == 'video': + result = self.send_kodi_rpc(method='Player.GetItem', + params=dict(properties=['title'], playerid=playerid), + message_id='VideoGetItem')['result'] + title = result['item']['title'] + typ = result['item']['type'] + if not title and 'label' in result['item']: + title = result['item']['label'] # if 'media' in self._items: # typ = result['item']['type'] # self._items['media'](typ.capitalize(), 'Kodi') - for elem in self.registered_items['media']: - elem(typ.capitalize(), caller='Kodi') - elif typ == 'audio': + for elem in self.registered_items['media']: + elem(typ.capitalize(), caller='Kodi') + elif typ == 'audio': # if 'media' in self._items: # self._items['media'](typ.capitalize(), 'Kodi') - for elem in self.registered_items['media']: - elem('Audio', caller='Kodi') - result = self.send_kodi_rpc(method='Player.GetItem', - params=dict(properties=['title', 'artist'], playerid=playerid), - message_id='AudioGetItem')['result'] - if len(result['item']['artist']) == 0: - artist = 'unknown' - else: - artist = result['item']['artist'][0] - title = artist + ' - ' + result['item']['title'] - elif typ == 'picture': + for elem in self.registered_items['media']: + elem('Audio', caller='Kodi') + result = self.send_kodi_rpc(method='Player.GetItem', + params=dict(properties=['title', 'artist'], playerid=playerid), + message_id='AudioGetItem')['result'] + if len(result['item']['artist']) == 0: + artist = 'unknown' + else: + artist = result['item']['artist'][0] + title = artist + ' - ' + result['item']['title'] + elif typ == 'picture': # if 'media' in self._items: # self._items['media'](typ.capitalize(), 'Kodi') - for elem in self.registered_items['media']: - elem('Picture', caller='Kodi') - title = '' - else: - self.logger.warning('Kodi: Unknown type: {0}'.format(typ)) - return + for elem in self.registered_items['media']: + elem('Picture', caller='Kodi') + title = '' + else: + self.logger.warning('Kodi: Unknown type: {0}'.format(typ)) + return # if 'title' in self._items: # self._items['title'](title, 'Kodi') - for elem in self.registered_items['title']: - elem(title, caller='Kodi') + for elem in self.registered_items['title']: + elem(title, caller='Kodi') diff --git a/kodi/plugin.yaml b/kodi/plugin.yaml index d4b5cc3ce..1fd2df9d1 100755 --- a/kodi/plugin.yaml +++ b/kodi/plugin.yaml @@ -18,7 +18,7 @@ plugin: multi_instance: True classname: Kodi # class containing the plugin -#parameters: +parameters: # Definition of parameters to be configured in etc/plugin.yaml host: type: ipv4 From cb93bd6eac7a01205f16cf23fdc6d28292ab8cb2 Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Tue, 7 Nov 2017 21:35:30 +0100 Subject: [PATCH 007/705] some documentation --- kodi/README.md | 100 +++++++++++++++++++++++++++++------------------ kodi/__init__.py | 70 +++++++++++++++------------------ 2 files changed, 94 insertions(+), 76 deletions(-) diff --git a/kodi/README.md b/kodi/README.md index b4f12d6c4..f1b82a62d 100644 --- a/kodi/README.md +++ b/kodi/README.md @@ -1,66 +1,96 @@ -# XBMC +# Kodi ## Requirements -You only need one or more XBMC (12 a.k.a. Frodo or above) with -System-Settings-Service "Allow programs on other systems to control XBMC" enabled. +You only need one or more Kodi (12 a.k.a. Frodo or above) with +System-Settings-Service "Allow programs on other systems to control Kodi" enabled. ## Configuration -### plugin.conf +### plugin.conf (deprecated) / plugin.yaml ``` -[xbmc] - class_name = XBMC - class_path = plugins.xbmc +# /etc/plugin.conf +[kodi] + class_name = Kodi + class_path = plugins.kodi + instance = living + host = xxx.xxx.xxx.xxx + port = 9090 ``` -### items.conf +```yaml +# /etc/plugin.yaml +kodi: + class_name: Kodi + class_path: plugins.kodi + instance: mediacenter + host: xxx.xxx.xxx.xxx + port: 9090 +``` + +#### host +This attribute is mandatory. You have to provide the IP address of the Kodi system. + +#### port +You could specify a port to connect to. By default port 9090 is used. + +### items.conf (deprecated) / items.yaml ``` +# /items/items.conf [living] - [[xbmc]] + [[kodi]] type = str - xbmc_host = xbmc.home - # xbmc_port = 9090 - xbmc_listen = state + kodi_item@mediacenter = state [[[title]]] type = str - xbmc_listen = title + kodi_item@mediacenter = title [[[media]]] type = str - xbmc_listen = media + kodi_item@mediacenter = media [[[volume]]] type = num - xbmc_listen = volume - xbmc_send = volume + kodi_item@mediacenter = volume [[[mute]]] type = bool - xbmc_listen = mute - xbmc_send = mute + kodi_item@mediacenter = mute ``` -#### xbmc_host -This attribute is mandatory. You have to provide the IP address or host name of the XBMC system. - -#### xbmc_port -You could specify a port to connect to. By default port 9090 is used. +```yaml +# /items/items.yaml +living: + kodi: + type: str + kodi_item@mediacenter: state + volume: + type: num + kodi_item@mediacenter: volume + mute: + type: bool + kodi_item@mediacenter: mute + title: + type: str + kodi_item@mediacenter: title + media: + type: str + kodi_item@mediacenter: media + favorites: + type: dict + kodi_item@mediacenter: favorites +``` -#### xbmc_listen -You could assign the following values to `xbmc_listen`: +#### kodi_item +You could assign the following values to `kodi_item`: * `volume` a numeric value (0 -100) * `mute` a bool flag * `title` a string with the name of the movie, song or picture * `media` a string with the current media type (Video, Audio, Picture) * `state` current state as string (Menu, Playing, Pause) + * `favorites` the favorites of your Kodi system (must be of type dict) -#### xbmc_send -The following `xbmc_send` attributes could be defined to send changes to the system: - - * `volume` a numeric value (0 -100) - * `mute` a bool flag - +The `volume` and `mute` items influence Kodi when their value changes. ### logic.conf @@ -68,12 +98,8 @@ Nothing so far ## Functions ========= -This plugin provides the function to send notification messages to xbmc. -``notify_all(title, message, picture)`` to send the notification to all xbmc systems and extends the item with the notify method. -The picture attribute is optional. +This plugin provides the function to send notification messages to Kodi. ```python -sh.xbmc.notify_all('Phone', 'Sister in law calling', 'http://smarthome.local/img/phone.png') -# or for a dedicated xbmc -sh.living.xbmc.notify('Door', 'Ding Dong') +sh.living.kodi.notify('Door', 'Ding Dong') ``` diff --git a/kodi/__init__.py b/kodi/__init__.py index f4c7d4ea7..9ec7bbf58 100755 --- a/kodi/__init__.py +++ b/kodi/__init__.py @@ -38,7 +38,7 @@ class Kodi(SmartPlugin, Client): PLUGIN_VERSION='1.3c.0' ALLOW_MULTIINSTANCE = True - _get_items = ['volume', 'mute', 'title', 'media', 'state'] + _get_items = ['volume', 'mute', 'title', 'media', 'state', 'favorites'] _set_items = {'volume': dict(method='Application.SetVolume', params=dict(volume='ITEM_VALUE')), 'mute' : dict(method='Application.SetMute', params = dict(mute='ITEM_VALUE')), @@ -52,20 +52,7 @@ class Kodi(SmartPlugin, Client): def __init__(self, sh, *args, **kwargs): ''' - Initalizes the plugin. The parameters describe for this method are pulled from the entry in plugin.conf. - - :param sh: **Deprecated**: The instance of the smarthome object. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! - :param *args: **Deprecated**: Old way of passing parameter values. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! - :param **kwargs:**Deprecated**: Old way of passing parameter values. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! - - If you need the sh object at all, use the method self.get_sh() to get it. There should be almost no need for - a reference to the sh object any more. - - The parameters *args and **kwargs are the old way of passing parameters. They are deprecated. They are implemented - to support oder plugins. Plugins for SmartHomeNG v1.4 and beyond should use the new way of getting parameter values: - use the SmartPlugin method `get_parameter_value(parameter_name)` instead. Anywhere within the Plugin you can get - the configured (and checked) value for a parameter by calling `self.get_parameter_value(parameter_name)`. It - returns the value in the datatype that is defined in the metadata. + Initalizes the plugin. ''' # init logger self.logger = logging.getLogger(__name__) @@ -109,22 +96,21 @@ def handle_connect(self): elem(result['muted'], caller='Kodi') for elem in self.registered_items['volume']: elem(result['volume'], caller='Kodi') - + # get the list of favorites + result = self.send_kodi_rpc(method='Favourites.GetFavourites', + params=dict(properties=['window', 'path', 'thumbnail', 'windowparameter']))['result'] + item_dict = {elem['title']: elem for elem in result['favourites']} + for elem in self.registered_items['favorites']: + elem(item_dict, caller='Kodi') # parse active player (if present) self._get_player_info() def parse_item(self, item): ''' - Default plugin parse_item method. Is called when the plugin is initialized. - The plugin can, corresponding to its attribute keywords, decide what to do with - the item in future, like adding it to an internal array for future reference + Method for parsing Kodi items. + If the item carries the kodi_item field, this item is registered to the plugin. :param item: The item to process. - :return: If the plugin needs to be informed of an items change you should return a call back function - like the function update_item down below. An example when this is needed is the knx plugin - where parse_item returns the update_item function when the attribute knx_send is found. - This means that when the items value is about to be updated, the call back function is called - with the item, caller, source and dest as arguments and in case of the knx plugin the value - can be sent to the knx with a knx write function within the knx plugin. + :return: The item update method to be triggered if the kodi_item is in the set item dict. ''' if self.has_iattr(item.conf, 'kodi_item'): kodi_item = self.get_iattr_value(item.conf, 'kodi_item') @@ -140,10 +126,7 @@ def parse_logic(self, logic): ''' Default plugin parse_logic method ''' - if 'xxx' in logic.conf: - # self.function(logic['name']) - pass - + pass def update_item(self, item, caller=None, source=None, dest=None): ''' @@ -188,6 +171,17 @@ def notify(self, title, message, image=None, display_time=10000): self.send_kodi_rpc(method='GUI.ShowNotification', params=params) def send_kodi_rpc(self, method, params=None, message_id=None, wait=True): + ''' + Send a JSON RPC to Kodi. + + The JSON string is extracted from the supplied method and the given parameters. + :param method: the Kodi method to be triggered + :param params: parameters dictionary + :param message_id: the message ID to be used. If none, use the internal counter + :param wait: whether to wait for the reply from Kodi or send off the RPC asynchronously + If wait is True, this method returns a dictionary parsed from the JSON + response from Kodi + ''' self.cmd_lock.acquire() self.reply = None if message_id is None: @@ -212,6 +206,10 @@ def send_kodi_rpc(self, method, params=None, message_id=None, wait=True): return reply def found_balance(self, data): + ''' + This method is called whenever data is received from the connection to + Kodi. + ''' event = json.loads(data.decode()) self.logger.debug('Kodi receiving: {0}'.format(event)) if 'id' in event: @@ -246,6 +244,10 @@ def found_balance(self, data): elem(event['params']['data']['volume'], caller='Kodi') def _get_player_info(self): + ''' + Extract information from Kodi reagrding the active player and save it + to the respective items + ''' result = self.send_kodi_rpc(method='Player.GetActivePlayers')['result'] if len(result) == 0: self.logger.info('Kodi: no active player found.') @@ -258,7 +260,6 @@ def _get_player_info(self): return playerid = result[0]['playerid'] typ = result[0]['type'] -# self._items['state']('Playing', 'Kodi') for elem in self.registered_items['state']: elem('Playing', caller='Kodi') if typ == 'video': @@ -269,14 +270,9 @@ def _get_player_info(self): typ = result['item']['type'] if not title and 'label' in result['item']: title = result['item']['label'] -# if 'media' in self._items: -# typ = result['item']['type'] -# self._items['media'](typ.capitalize(), 'Kodi') for elem in self.registered_items['media']: elem(typ.capitalize(), caller='Kodi') elif typ == 'audio': -# if 'media' in self._items: -# self._items['media'](typ.capitalize(), 'Kodi') for elem in self.registered_items['media']: elem('Audio', caller='Kodi') result = self.send_kodi_rpc(method='Player.GetItem', @@ -288,15 +284,11 @@ def _get_player_info(self): artist = result['item']['artist'][0] title = artist + ' - ' + result['item']['title'] elif typ == 'picture': -# if 'media' in self._items: -# self._items['media'](typ.capitalize(), 'Kodi') for elem in self.registered_items['media']: elem('Picture', caller='Kodi') title = '' else: self.logger.warning('Kodi: Unknown type: {0}'.format(typ)) return -# if 'title' in self._items: -# self._items['title'](title, 'Kodi') for elem in self.registered_items['title']: elem(title, caller='Kodi') From 2a35ee0337caf5eca63e1f5e791b0b04759cbdf7 Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Wed, 8 Nov 2017 14:20:50 +0100 Subject: [PATCH 008/705] fixed 'favourite bug' and added functionality for play,pause and stop. also some more docs --- kodi/README.md | 12 ++++++++- kodi/__init__.py | 63 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 58 insertions(+), 17 deletions(-) diff --git a/kodi/README.md b/kodi/README.md index f1b82a62d..679c64e3b 100644 --- a/kodi/README.md +++ b/kodi/README.md @@ -89,15 +89,25 @@ You could assign the following values to `kodi_item`: * `media` a string with the current media type (Video, Audio, Picture) * `state` current state as string (Menu, Playing, Pause) * `favorites` the favorites of your Kodi system (must be of type dict) + * `play_pause` request Kodi to pause or restart the current players (should be of type bool and `enforce_updates: true`) + * `stop` request Kodi to stop all players (should be of type bool and `enforce_updates: true`) + * `left` send a left request to Kodi, same as pressing the left arrow on the keyboard (should be of type bool and `enforce_updates: true`) + * `right` send a right request to Kodi, same as pressing the right arrow on the keyboard (should be of type bool and `enforce_updates: true`) + * `up` send an up request to Kodi, same as pressing the up arrow on the keyboard (should be of type bool and `enforce_updates: true`) + * `down` send a down request to Kodi, same as pressing the down arrow on the keyboard (should be of type bool and `enforce_updates: true`) + * `home` go to the home menu (should be of type bool and `enforce_updates: true`) + * `back` go to the previous menu (should be of type bool and `enforce_updates: true`) + * `select` select the currently highlightes item in Kodi (should be of type bool and `enforce_updates: true`) The `volume` and `mute` items influence Kodi when their value changes. +All items that are marked as "should be of type bool" are essentially commands which are usually send to Kodi over an attached keyboard. The keyboard behavior can be simulated through boolean items with `enforce_updates: true`. + ### logic.conf Nothing so far ## Functions -========= This plugin provides the function to send notification messages to Kodi. ```python diff --git a/kodi/__init__.py b/kodi/__init__.py index 9ec7bbf58..dcaa786fe 100755 --- a/kodi/__init__.py +++ b/kodi/__init__.py @@ -40,15 +40,17 @@ class Kodi(SmartPlugin, Client): _get_items = ['volume', 'mute', 'title', 'media', 'state', 'favorites'] - _set_items = {'volume': dict(method='Application.SetVolume', params=dict(volume='ITEM_VALUE')), - 'mute' : dict(method='Application.SetMute', params = dict(mute='ITEM_VALUE')), - 'left' : dict(method='Input.Left', params=None), - 'right' : dict(method='Input.Right', params=None), - 'up' : dict(method='Input.Up', params=None), - 'down' : dict(method='Input.Down', params=None), - 'home' : dict(method='Input.Home', params=None), - 'back' : dict(method='Input.Back', params=None), - 'select': dict(method='Input.Select', params=None)} + _set_items = {'volume' : dict(method='Application.SetVolume', params=dict(volume='ITEM_VALUE')), + 'mute' : dict(method='Application.SetMute', params = dict(mute='ITEM_VALUE')), + 'left' : dict(method='Input.Left', params=None), + 'right' : dict(method='Input.Right', params=None), + 'up' : dict(method='Input.Up', params=None), + 'down' : dict(method='Input.Down', params=None), + 'home' : dict(method='Input.Home', params=None), + 'back' : dict(method='Input.Back', params=None), + 'select' : dict(method='Input.Select', params=None), + 'play_pause': dict(method='Player.PlayPause', params=None), + 'stop' : dict(method='Player.Stop', params=None)} def __init__(self, sh, *args, **kwargs): ''' @@ -99,7 +101,9 @@ def handle_connect(self): # get the list of favorites result = self.send_kodi_rpc(method='Favourites.GetFavourites', params=dict(properties=['window', 'path', 'thumbnail', 'windowparameter']))['result'] - item_dict = {elem['title']: elem for elem in result['favourites']} + item_dict = dict() + if result['favourites'] is not None: + item_dict = {elem['title']: elem for elem in result['favourites']} for elem in self.registered_items['favorites']: elem(item_dict, caller='Kodi') # parse active player (if present) @@ -114,7 +118,10 @@ def parse_item(self, item): ''' if self.has_iattr(item.conf, 'kodi_item'): kodi_item = self.get_iattr_value(item.conf, 'kodi_item') - self.logger.debug('Plugin \'{}\': parse item: {}'.format(self.get_shortname(), item)) + self.logger.debug('Plugin \'%s\', instance \'%s\': registering item: %s', + self.get_shortname(), + self.get_instance_name(), + item) if kodi_item in self.registered_items: self.registered_items[kodi_item].append(item) else: @@ -139,9 +146,13 @@ def update_item(self, item, caller=None, source=None, dest=None): ''' if item(): if caller != 'Kodi' and self.has_iattr(item.conf, 'kodi_item'): - # update item was triggered from sometthing else then this plugin -> send to Kodi + # update item was triggered from something else then this plugin -> send to Kodi kodi_item = self.get_iattr_value(item.conf, 'kodi_item') - if kodi_item in Kodi._set_items: + # handle play/pause and stop separately as we need to find the active player + if kodi_item in ['play_pause', 'stop']: + self.get_sh().trigger('kodi-%s' % kodi_item, self._send_player_command, 'Kodi', value=dict(kodi_item=kodi_item)) + # all other Items can be handled through a standard interface + elif kodi_item in Kodi._set_items: self.logger.debug('Plugin \'{}\': update_item ws called with item \'{}\' from caller \'{}\', source \'{}\' and dest \'{}\''.format(self.get_shortname(), item, caller, source, dest)) method = self._set_items[kodi_item]['method'] params = self._set_items[kodi_item]['params'] @@ -152,7 +163,7 @@ def update_item(self, item, caller=None, source=None, dest=None): for key, value in params.items(): if value == 'ITEM_VALUE': params[key] = item() - self._send(method, params, wait=False) + self.send_kodi_rpc(method, params, wait=False) else: self.logger.info('kodi_item \'%s\' not in send_keys, skipping!', kodi_item) @@ -236,16 +247,36 @@ def found_balance(self, data): elem('Screensaver', caller='Kodi') if event['method'] in ['Player.OnPlay']: # use a different thread for event handling - self.get_sh().trigger('kodi-event', self._get_player_info, 'Kodi') + self.get_sh().trigger('kodi-player-start', self._get_player_info, 'Kodi') elif event['method'] in ['Application.OnVolumeChanged']: for elem in self.registered_items['mute']: elem(event['params']['data']['muted'], caller='Kodi') for elem in self.registered_items['volume']: elem(event['params']['data']['volume'], caller='Kodi') + + def _send_player_command(self, kodi_item): + ''' + This method should only be called from the update item method in + a new thread in order to handle Play/Pause and Stop commands to + the active Kodi players + ''' + # get the currently active players + result = self.send_kodi_rpc(method='Player.GetActivePlayers') + result = result['result'] + if len(result) == 0: + self.logger.warning('Kodi: no active player found, skipping request!') + else: + if len(result) > 1: + self.logger.info('Kodi: there is more than one active player. Sending request to each player!') + for player in result: + player_id = player['playerid'] + self.send_kodi_rpc(method=self._set_items[kodi_item]['method'], + params=dict(playerid=player_id), + wait=False) def _get_player_info(self): ''' - Extract information from Kodi reagrding the active player and save it + Extract information from Kodi regarding the active player and save it to the respective items ''' result = self.send_kodi_rpc(method='Player.GetActivePlayers')['result'] From 6520665ceaa8d0ce04c1ba51f02d6fc635123dbc Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Sun, 1 Oct 2017 09:04:44 +0200 Subject: [PATCH 009/705] initial commit --- xbmc/__init__.py | 202 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100755 xbmc/__init__.py diff --git a/xbmc/__init__.py b/xbmc/__init__.py new file mode 100755 index 000000000..b43ae8172 --- /dev/null +++ b/xbmc/__init__.py @@ -0,0 +1,202 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2013 Marcus Popp marcus@popp.mx +# Copyright 2017 Sebastian Sudholt sebastian.sudholt@tu-dortmund.de +######################################################################### +# This file is part of SmartHome.py. http://mknx.github.io/smarthome/ +# +# SmartHome.py is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# SmartHome.py is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with SmartHome.py. If not, see . +######################################################################### + +import logging +import threading +import json +import lib.connection + +logger = logging.getLogger('') + + +class Kodi(): + + def __init__(self, smarthome): + self._sh = smarthome + self._boxes = [] + + def run(self): + self.alive = True + + def stop(self): + self.alive = False + for box in self._boxes: + box.handle_close() + + def notify_all(self, title, message, image=None): + for box in self._boxes: + box.notify(title, message, image) + + def parse_item(self, item): + if 'kodi_host' in item.conf: + self._boxes.append(kodi(self._sh, item)) + + +class kodi(lib.connection.Client): + + _notification_time = 10000 + _listen_keys = ['volume', 'mute', 'title', 'media', 'state'] + _send_keys = {'volume': 'Application.SetVolume', 'mute': 'Application.SetMute', + 'left': 'Input.Left', 'right': 'Input.Right', 'up': 'Input.Up', 'down': 'Input.Down', + 'home': 'Input.Home', 'back': 'Input.Back', 'select': 'Input.Select'} + + def __init__(self, smarthome, item): + if 'kodi_port' in item.conf: + port = int(item.conf['kodi_port']) + else: + port = 9090 + host = item.conf['kodi_host'] + lib.connection.Client.__init__(self, host, port, monitor=True) + self.terminator = 0 + self.balance(b'{', b'}') + self._sh = smarthome + self._id = 1 + self._rid = None + self._cmd_lock = threading.Lock() + self._reply_lock = threading.Condition() + self._reply = None + self._items = {'state': item} + for child in self._sh.find_children(item, 'kodi_listen'): + listen_to = child.conf['kodi_listen'] + if listen_to in self._listen_keys: + self._items[listen_to] = child + for child in self._sh.find_children(item, 'kodi_send'): + send_to = child.conf['kodi_send'] + if send_to in self._send_keys: + child.add_method_trigger(self._send_value) + item.notify = self.notify + + def notify(self, title, message, image=None): + if image is None: + self._send('GUI.ShowNotification', {'title': title, 'message': message, 'displaytime': self._notification_time}) + else: + self._send('GUI.ShowNotification', {'title': title, 'message': message, 'image': image, 'displaytime': self._notification_time}) + + def _send_value(self, item, caller=None, source=None, dest=None): + if caller != 'Kodi': + if 'kodi_params' not in item.conf or item.conf['kodi_params'] == 'None': + params = None + else: + params = item.conf['kodi_params'] + self._send(self._send_keys[item.conf['kodi_send']], params, wait=False) + + def run(self): + self.alive = True + + def _send(self, method, params=None, id=None, wait=True): + self._cmd_lock.acquire() + self._reply = None + if id is None: + self._id += 1 + id = self._id + if id > 100: + self._id = 0 + self._rid = id + if params is not None: + data = {"jsonrpc": "2.0", "id": id, "method": method, 'params': params} + else: + data = {"jsonrpc": "2.0", "id": id, "method": method} + self._reply_lock.acquire() + #logger.debug("Kodi sending: {0}".format(json.dumps(data, separators=(',', ':')))) + self.send((json.dumps(data, separators=(',', ':')) + '\r\n').encode()) + if wait: + self._reply_lock.wait(2) + self._reply_lock.release() + reply = self._reply + self._reply = None + self._cmd_lock.release() + return reply + + def _set_item(self, key, value): + if key in self._items: + self._items[key](value, 'Kodi') + + def found_balance(self, data): + event = json.loads(data.decode()) + #logger.debug("Kodi receiving: {0}".format(event)) + if 'id' in event: + if event['id'] == self._rid: + self._rid = None + self._reply = event + self._reply_lock.acquire() + self._reply_lock.notify() + self._reply_lock.release() + return + if 'method' in event: + if event['method'] == 'Player.OnPause': + if 'state' in self._items: + self._items['state']('Pause', 'Kodi') + elif event['method'] == 'Player.OnStop': + if 'state' in self._items: + self._items['state']('Menu', 'Kodi') + if 'media' in self._items: + self._items['media']('', 'Kodi') + if 'title' in self._items: + self._items['title']('', 'Kodi') + elif event['method'] == 'GUI.OnScreensaverActivated': + if 'state' in self._items: + self._items['state']('Screensaver', 'Kodi') + if event['method'] in ['Player.OnPlay']: + # use a different thread for event handling + self._sh.trigger('kodi-event', self._parse_event, 'Kodi', value={'event': event}) + elif event['method'] in ['Application.OnVolumeChanged']: + if 'mute' in self._items: + self._set_item('mute', event['params']['data']['muted']) + if 'volume' in self._items: + self._set_item('volume', event['params']['data']['volume']) + + + def _parse_event(self, event): + if event['method'] == 'Player.OnPlay': + result = self._send('Player.GetActivePlayers')['result'] + if len(result) == 0: + logger.info("Kodi: no active player found.") + return + playerid = result[0]['playerid'] + typ = result[0]['type'] + self._items['state']('Playing', 'Kodi') + if typ == 'video': + result = self._send('Player.GetItem', {"properties": ["title"], "playerid": playerid}, "VideoGetItem")['result'] + title = result['item']['title'] + if not title and 'label' in result['item']: + title = result['item']['label'] + if 'media' in self._items: + typ = result['item']['type'] + self._items['media'](typ.capitalize(), 'Kodi') + elif typ == 'audio': + if 'media' in self._items: + self._items['media'](typ.capitalize(), 'Kodi') + result = self._send('Player.GetItem', {"properties": ["title", "artist"], "playerid": playerid}, "AudioGetItem")['result'] + if len(result['item']['artist']) == 0: + artist = 'unknown' + else: + artist = result['item']['artist'][0] + title = artist + ' - ' + result['item']['title'] + elif typ == 'picture': + if 'media' in self._items: + self._items['media'](typ.capitalize(), 'Kodi') + title = '' + else: + logger.warning("Kodi: Unknown type: {0}".format(typ)) + return + if 'title' in self._items: + self._items['title'](title, 'Kodi') From 72850b09d3df2072c8619c281e10e86abd7e0cd3 Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Sun, 5 Nov 2017 07:53:08 +0100 Subject: [PATCH 010/705] renamed folder to kodi --- kodi/README.md | 110 +++++-------- kodi/__init__.py | 413 +++++++++++++++++------------------------------ xbmc/__init__.py | 202 ----------------------- 3 files changed, 182 insertions(+), 543 deletions(-) delete mode 100755 xbmc/__init__.py diff --git a/kodi/README.md b/kodi/README.md index 679c64e3b..b4f12d6c4 100644 --- a/kodi/README.md +++ b/kodi/README.md @@ -1,106 +1,65 @@ -# Kodi +# XBMC ## Requirements -You only need one or more Kodi (12 a.k.a. Frodo or above) with -System-Settings-Service "Allow programs on other systems to control Kodi" enabled. +You only need one or more XBMC (12 a.k.a. Frodo or above) with +System-Settings-Service "Allow programs on other systems to control XBMC" enabled. ## Configuration -### plugin.conf (deprecated) / plugin.yaml +### plugin.conf ``` -# /etc/plugin.conf -[kodi] - class_name = Kodi - class_path = plugins.kodi - instance = living - host = xxx.xxx.xxx.xxx - port = 9090 +[xbmc] + class_name = XBMC + class_path = plugins.xbmc ``` -```yaml -# /etc/plugin.yaml -kodi: - class_name: Kodi - class_path: plugins.kodi - instance: mediacenter - host: xxx.xxx.xxx.xxx - port: 9090 -``` - -#### host -This attribute is mandatory. You have to provide the IP address of the Kodi system. - -#### port -You could specify a port to connect to. By default port 9090 is used. - -### items.conf (deprecated) / items.yaml +### items.conf ``` -# /items/items.conf [living] - [[kodi]] + [[xbmc]] type = str - kodi_item@mediacenter = state + xbmc_host = xbmc.home + # xbmc_port = 9090 + xbmc_listen = state [[[title]]] type = str - kodi_item@mediacenter = title + xbmc_listen = title [[[media]]] type = str - kodi_item@mediacenter = media + xbmc_listen = media [[[volume]]] type = num - kodi_item@mediacenter = volume + xbmc_listen = volume + xbmc_send = volume [[[mute]]] type = bool - kodi_item@mediacenter = mute + xbmc_listen = mute + xbmc_send = mute ``` -```yaml -# /items/items.yaml -living: - kodi: - type: str - kodi_item@mediacenter: state - volume: - type: num - kodi_item@mediacenter: volume - mute: - type: bool - kodi_item@mediacenter: mute - title: - type: str - kodi_item@mediacenter: title - media: - type: str - kodi_item@mediacenter: media - favorites: - type: dict - kodi_item@mediacenter: favorites -``` +#### xbmc_host +This attribute is mandatory. You have to provide the IP address or host name of the XBMC system. -#### kodi_item -You could assign the following values to `kodi_item`: +#### xbmc_port +You could specify a port to connect to. By default port 9090 is used. + +#### xbmc_listen +You could assign the following values to `xbmc_listen`: * `volume` a numeric value (0 -100) * `mute` a bool flag * `title` a string with the name of the movie, song or picture * `media` a string with the current media type (Video, Audio, Picture) * `state` current state as string (Menu, Playing, Pause) - * `favorites` the favorites of your Kodi system (must be of type dict) - * `play_pause` request Kodi to pause or restart the current players (should be of type bool and `enforce_updates: true`) - * `stop` request Kodi to stop all players (should be of type bool and `enforce_updates: true`) - * `left` send a left request to Kodi, same as pressing the left arrow on the keyboard (should be of type bool and `enforce_updates: true`) - * `right` send a right request to Kodi, same as pressing the right arrow on the keyboard (should be of type bool and `enforce_updates: true`) - * `up` send an up request to Kodi, same as pressing the up arrow on the keyboard (should be of type bool and `enforce_updates: true`) - * `down` send a down request to Kodi, same as pressing the down arrow on the keyboard (should be of type bool and `enforce_updates: true`) - * `home` go to the home menu (should be of type bool and `enforce_updates: true`) - * `back` go to the previous menu (should be of type bool and `enforce_updates: true`) - * `select` select the currently highlightes item in Kodi (should be of type bool and `enforce_updates: true`) -The `volume` and `mute` items influence Kodi when their value changes. -All items that are marked as "should be of type bool" are essentially commands which are usually send to Kodi over an attached keyboard. The keyboard behavior can be simulated through boolean items with `enforce_updates: true`. +#### xbmc_send +The following `xbmc_send` attributes could be defined to send changes to the system: + + * `volume` a numeric value (0 -100) + * `mute` a bool flag ### logic.conf @@ -108,8 +67,13 @@ All items that are marked as "should be of type bool" are essentially commands w Nothing so far ## Functions -This plugin provides the function to send notification messages to Kodi. +========= +This plugin provides the function to send notification messages to xbmc. +``notify_all(title, message, picture)`` to send the notification to all xbmc systems and extends the item with the notify method. +The picture attribute is optional. ```python -sh.living.kodi.notify('Door', 'Ding Dong') +sh.xbmc.notify_all('Phone', 'Sister in law calling', 'http://smarthome.local/img/phone.png') +# or for a dedicated xbmc +sh.living.xbmc.notify('Door', 'Ding Dong') ``` diff --git a/kodi/__init__.py b/kodi/__init__.py index dcaa786fe..b43ae8172 100755 --- a/kodi/__init__.py +++ b/kodi/__init__.py @@ -4,15 +4,14 @@ # Copyright 2013 Marcus Popp marcus@popp.mx # Copyright 2017 Sebastian Sudholt sebastian.sudholt@tu-dortmund.de ######################################################################### - -# This file is part of SmartHomeNG. +# This file is part of SmartHome.py. http://mknx.github.io/smarthome/ # -# SmartHomeNG is free software: you can redistribute it and/or modify +# SmartHome.py is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # -# SmartHomeNG is distributed in the hope that it will be useful, +# SmartHome.py is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. @@ -24,302 +23,180 @@ import logging import threading import json +import lib.connection -from lib.model.smartplugin import SmartPlugin -from lib.connection import Client +logger = logging.getLogger('') -class Kodi(SmartPlugin, Client): - ''' - Main class of the Plugin. Does all plugin specific stuff and provides - the update functions for the items - ''' - - PLUGIN_VERSION='1.3c.0' - ALLOW_MULTIINSTANCE = True +class Kodi(): - _get_items = ['volume', 'mute', 'title', 'media', 'state', 'favorites'] - - _set_items = {'volume' : dict(method='Application.SetVolume', params=dict(volume='ITEM_VALUE')), - 'mute' : dict(method='Application.SetMute', params = dict(mute='ITEM_VALUE')), - 'left' : dict(method='Input.Left', params=None), - 'right' : dict(method='Input.Right', params=None), - 'up' : dict(method='Input.Up', params=None), - 'down' : dict(method='Input.Down', params=None), - 'home' : dict(method='Input.Home', params=None), - 'back' : dict(method='Input.Back', params=None), - 'select' : dict(method='Input.Select', params=None), - 'play_pause': dict(method='Player.PlayPause', params=None), - 'stop' : dict(method='Player.Stop', params=None)} - - def __init__(self, sh, *args, **kwargs): - ''' - Initalizes the plugin. - ''' - # init logger - self.logger = logging.getLogger(__name__) - self.logger.info('Init Kodi Plugin') - Client.__init__(self, - self.get_parameter_value('host'), - self.get_parameter_value('port'), - monitor=True) - self.terminator = 0 - self.balance(b'{', b'}') - self.message_id = 1 - self.response_id = None - self.cmd_lock = threading.Lock() - self.reply_lock = threading.Condition() - self.reply = None - self.registered_items = {key: [] for key in set(list(Kodi._set_items.keys()) + Kodi._get_items)} + def __init__(self, smarthome): + self._sh = smarthome + self._boxes = [] def run(self): - ''' - Run method for the plugin - ''' - self.logger.debug('Plugin \'{}\': run method called'.format(self.get_shortname())) self.alive = True def stop(self): - ''' - Stop method for the plugin - ''' - self.logger.debug('Plugin \'{}\': stop method called'.format(self.get_shortname())) self.alive = False - - def handle_connect(self): - ''' - This method is called on a succesful connect to Kodi - On a connect initialize all items with values extracted from Kodi - ''' - # get volume and mute state - result = self.send_kodi_rpc(method='Application.GetProperties', - params=dict(properties=['volume', 'muted']))['result'] - for elem in self.registered_items['mute']: - elem(result['muted'], caller='Kodi') - for elem in self.registered_items['volume']: - elem(result['volume'], caller='Kodi') - # get the list of favorites - result = self.send_kodi_rpc(method='Favourites.GetFavourites', - params=dict(properties=['window', 'path', 'thumbnail', 'windowparameter']))['result'] - item_dict = dict() - if result['favourites'] is not None: - item_dict = {elem['title']: elem for elem in result['favourites']} - for elem in self.registered_items['favorites']: - elem(item_dict, caller='Kodi') - # parse active player (if present) - self._get_player_info() + for box in self._boxes: + box.handle_close() + + def notify_all(self, title, message, image=None): + for box in self._boxes: + box.notify(title, message, image) def parse_item(self, item): - ''' - Method for parsing Kodi items. - If the item carries the kodi_item field, this item is registered to the plugin. - :param item: The item to process. - :return: The item update method to be triggered if the kodi_item is in the set item dict. - ''' - if self.has_iattr(item.conf, 'kodi_item'): - kodi_item = self.get_iattr_value(item.conf, 'kodi_item') - self.logger.debug('Plugin \'%s\', instance \'%s\': registering item: %s', - self.get_shortname(), - self.get_instance_name(), - item) - if kodi_item in self.registered_items: - self.registered_items[kodi_item].append(item) - else: - self.logger.warning('I do not know the kodi_item \'%s\', skipping!', kodi_item) - if kodi_item in Kodi._set_items: - return self.update_item + if 'kodi_host' in item.conf: + self._boxes.append(kodi(self._sh, item)) - def parse_logic(self, logic): - ''' - Default plugin parse_logic method - ''' - pass - def update_item(self, item, caller=None, source=None, dest=None): - ''' - Callback method for sending values to Kodi when a registered item has changed +class kodi(lib.connection.Client): - :param item: item to be updated towards the plugin - :param caller: if given it represents the callers name - :param source: if given it represents the source - :param dest: if given it represents the dest - ''' - if item(): - if caller != 'Kodi' and self.has_iattr(item.conf, 'kodi_item'): - # update item was triggered from something else then this plugin -> send to Kodi - kodi_item = self.get_iattr_value(item.conf, 'kodi_item') - # handle play/pause and stop separately as we need to find the active player - if kodi_item in ['play_pause', 'stop']: - self.get_sh().trigger('kodi-%s' % kodi_item, self._send_player_command, 'Kodi', value=dict(kodi_item=kodi_item)) - # all other Items can be handled through a standard interface - elif kodi_item in Kodi._set_items: - self.logger.debug('Plugin \'{}\': update_item ws called with item \'{}\' from caller \'{}\', source \'{}\' and dest \'{}\''.format(self.get_shortname(), item, caller, source, dest)) - method = self._set_items[kodi_item]['method'] - params = self._set_items[kodi_item]['params'] - if params is not None: - # copy so we don't interfer with the class variable - params = params.copy() - # replace the wild card ITEM_VALUE with the item's value - for key, value in params.items(): - if value == 'ITEM_VALUE': - params[key] = item() - self.send_kodi_rpc(method, params, wait=False) - else: - self.logger.info('kodi_item \'%s\' not in send_keys, skipping!', kodi_item) - - def notify(self, title, message, image=None, display_time=10000): - ''' - Send a notification to Kodi to be displayed on the screen - - :param title: the title of the message - :param message: the message itself - :param image: an optional image to be displayed alongside the message - :param display_time: how long the message is displayed in milli seconds - ''' - params = dict(title=title, message=message,displaytime=display_time) - if image is not None: - params['image'] = image - self.send_kodi_rpc(method='GUI.ShowNotification', params=params) + _notification_time = 10000 + _listen_keys = ['volume', 'mute', 'title', 'media', 'state'] + _send_keys = {'volume': 'Application.SetVolume', 'mute': 'Application.SetMute', + 'left': 'Input.Left', 'right': 'Input.Right', 'up': 'Input.Up', 'down': 'Input.Down', + 'home': 'Input.Home', 'back': 'Input.Back', 'select': 'Input.Select'} + + def __init__(self, smarthome, item): + if 'kodi_port' in item.conf: + port = int(item.conf['kodi_port']) + else: + port = 9090 + host = item.conf['kodi_host'] + lib.connection.Client.__init__(self, host, port, monitor=True) + self.terminator = 0 + self.balance(b'{', b'}') + self._sh = smarthome + self._id = 1 + self._rid = None + self._cmd_lock = threading.Lock() + self._reply_lock = threading.Condition() + self._reply = None + self._items = {'state': item} + for child in self._sh.find_children(item, 'kodi_listen'): + listen_to = child.conf['kodi_listen'] + if listen_to in self._listen_keys: + self._items[listen_to] = child + for child in self._sh.find_children(item, 'kodi_send'): + send_to = child.conf['kodi_send'] + if send_to in self._send_keys: + child.add_method_trigger(self._send_value) + item.notify = self.notify + + def notify(self, title, message, image=None): + if image is None: + self._send('GUI.ShowNotification', {'title': title, 'message': message, 'displaytime': self._notification_time}) + else: + self._send('GUI.ShowNotification', {'title': title, 'message': message, 'image': image, 'displaytime': self._notification_time}) - def send_kodi_rpc(self, method, params=None, message_id=None, wait=True): - ''' - Send a JSON RPC to Kodi. - - The JSON string is extracted from the supplied method and the given parameters. - :param method: the Kodi method to be triggered - :param params: parameters dictionary - :param message_id: the message ID to be used. If none, use the internal counter - :param wait: whether to wait for the reply from Kodi or send off the RPC asynchronously - If wait is True, this method returns a dictionary parsed from the JSON - response from Kodi - ''' - self.cmd_lock.acquire() - self.reply = None - if message_id is None: - self.message_id += 1 - message_id = self.message_id - if message_id > 99: - self.message_id = 0 - self.response_id = message_id + def _send_value(self, item, caller=None, source=None, dest=None): + if caller != 'Kodi': + if 'kodi_params' not in item.conf or item.conf['kodi_params'] == 'None': + params = None + else: + params = item.conf['kodi_params'] + self._send(self._send_keys[item.conf['kodi_send']], params, wait=False) + + def run(self): + self.alive = True + + def _send(self, method, params=None, id=None, wait=True): + self._cmd_lock.acquire() + self._reply = None + if id is None: + self._id += 1 + id = self._id + if id > 100: + self._id = 0 + self._rid = id if params is not None: - data = {'jsonrpc': '2.0', 'id': message_id, 'method': method, 'params': params} + data = {"jsonrpc": "2.0", "id": id, "method": method, 'params': params} else: - data = {'jsonrpc': '2.0', 'id': message_id, 'method': method} - self.reply_lock.acquire() - self.logger.debug('Kodi sending: {0}'.format(json.dumps(data, separators=(',', ':')))) + data = {"jsonrpc": "2.0", "id": id, "method": method} + self._reply_lock.acquire() + #logger.debug("Kodi sending: {0}".format(json.dumps(data, separators=(',', ':')))) self.send((json.dumps(data, separators=(',', ':')) + '\r\n').encode()) if wait: - self.reply_lock.wait(2) - self.reply_lock.release() - reply = self.reply - self.reply = None - self.cmd_lock.release() + self._reply_lock.wait(2) + self._reply_lock.release() + reply = self._reply + self._reply = None + self._cmd_lock.release() return reply + def _set_item(self, key, value): + if key in self._items: + self._items[key](value, 'Kodi') + def found_balance(self, data): - ''' - This method is called whenever data is received from the connection to - Kodi. - ''' event = json.loads(data.decode()) - self.logger.debug('Kodi receiving: {0}'.format(event)) + #logger.debug("Kodi receiving: {0}".format(event)) if 'id' in event: - if event['id'] == self.response_id: - self.response_id = None - self.reply = event - self.reply_lock.acquire() - self.reply_lock.notify() - self.reply_lock.release() + if event['id'] == self._rid: + self._rid = None + self._reply = event + self._reply_lock.acquire() + self._reply_lock.notify() + self._reply_lock.release() return if 'method' in event: if event['method'] == 'Player.OnPause': - for elem in self.registered_items['state']: - elem('Pause', caller='Kodi') + if 'state' in self._items: + self._items['state']('Pause', 'Kodi') elif event['method'] == 'Player.OnStop': - for elem in self.registered_items['state']: - elem('Stopped Player', caller='Kodi') - for elem in self.registered_items['media']: - elem('', caller='Kodi') - for elem in self.registered_items['title']: - elem('', caller='Kodi') + if 'state' in self._items: + self._items['state']('Menu', 'Kodi') + if 'media' in self._items: + self._items['media']('', 'Kodi') + if 'title' in self._items: + self._items['title']('', 'Kodi') elif event['method'] == 'GUI.OnScreensaverActivated': - for elem in self.registered_items['state']: - elem('Screensaver', caller='Kodi') + if 'state' in self._items: + self._items['state']('Screensaver', 'Kodi') if event['method'] in ['Player.OnPlay']: # use a different thread for event handling - self.get_sh().trigger('kodi-player-start', self._get_player_info, 'Kodi') + self._sh.trigger('kodi-event', self._parse_event, 'Kodi', value={'event': event}) elif event['method'] in ['Application.OnVolumeChanged']: - for elem in self.registered_items['mute']: - elem(event['params']['data']['muted'], caller='Kodi') - for elem in self.registered_items['volume']: - elem(event['params']['data']['volume'], caller='Kodi') - - def _send_player_command(self, kodi_item): - ''' - This method should only be called from the update item method in - a new thread in order to handle Play/Pause and Stop commands to - the active Kodi players - ''' - # get the currently active players - result = self.send_kodi_rpc(method='Player.GetActivePlayers') - result = result['result'] - if len(result) == 0: - self.logger.warning('Kodi: no active player found, skipping request!') - else: - if len(result) > 1: - self.logger.info('Kodi: there is more than one active player. Sending request to each player!') - for player in result: - player_id = player['playerid'] - self.send_kodi_rpc(method=self._set_items[kodi_item]['method'], - params=dict(playerid=player_id), - wait=False) + if 'mute' in self._items: + self._set_item('mute', event['params']['data']['muted']) + if 'volume' in self._items: + self._set_item('volume', event['params']['data']['volume']) + - def _get_player_info(self): - ''' - Extract information from Kodi regarding the active player and save it - to the respective items - ''' - result = self.send_kodi_rpc(method='Player.GetActivePlayers')['result'] - if len(result) == 0: - self.logger.info('Kodi: no active player found.') - for elem in self.registered_items['title']: - elem('', caller='Kodi') - for elem in self.registered_items['media']: - elem('', caller='Kodi') - for elem in self.registered_items['state']: - elem('No Active Player', caller='Kodi') - return - playerid = result[0]['playerid'] - typ = result[0]['type'] - for elem in self.registered_items['state']: - elem('Playing', caller='Kodi') - if typ == 'video': - result = self.send_kodi_rpc(method='Player.GetItem', - params=dict(properties=['title'], playerid=playerid), - message_id='VideoGetItem')['result'] - title = result['item']['title'] - typ = result['item']['type'] - if not title and 'label' in result['item']: - title = result['item']['label'] - for elem in self.registered_items['media']: - elem(typ.capitalize(), caller='Kodi') - elif typ == 'audio': - for elem in self.registered_items['media']: - elem('Audio', caller='Kodi') - result = self.send_kodi_rpc(method='Player.GetItem', - params=dict(properties=['title', 'artist'], playerid=playerid), - message_id='AudioGetItem')['result'] - if len(result['item']['artist']) == 0: - artist = 'unknown' + def _parse_event(self, event): + if event['method'] == 'Player.OnPlay': + result = self._send('Player.GetActivePlayers')['result'] + if len(result) == 0: + logger.info("Kodi: no active player found.") + return + playerid = result[0]['playerid'] + typ = result[0]['type'] + self._items['state']('Playing', 'Kodi') + if typ == 'video': + result = self._send('Player.GetItem', {"properties": ["title"], "playerid": playerid}, "VideoGetItem")['result'] + title = result['item']['title'] + if not title and 'label' in result['item']: + title = result['item']['label'] + if 'media' in self._items: + typ = result['item']['type'] + self._items['media'](typ.capitalize(), 'Kodi') + elif typ == 'audio': + if 'media' in self._items: + self._items['media'](typ.capitalize(), 'Kodi') + result = self._send('Player.GetItem', {"properties": ["title", "artist"], "playerid": playerid}, "AudioGetItem")['result'] + if len(result['item']['artist']) == 0: + artist = 'unknown' + else: + artist = result['item']['artist'][0] + title = artist + ' - ' + result['item']['title'] + elif typ == 'picture': + if 'media' in self._items: + self._items['media'](typ.capitalize(), 'Kodi') + title = '' else: - artist = result['item']['artist'][0] - title = artist + ' - ' + result['item']['title'] - elif typ == 'picture': - for elem in self.registered_items['media']: - elem('Picture', caller='Kodi') - title = '' - else: - self.logger.warning('Kodi: Unknown type: {0}'.format(typ)) - return - for elem in self.registered_items['title']: - elem(title, caller='Kodi') + logger.warning("Kodi: Unknown type: {0}".format(typ)) + return + if 'title' in self._items: + self._items['title'](title, 'Kodi') diff --git a/xbmc/__init__.py b/xbmc/__init__.py deleted file mode 100755 index b43ae8172..000000000 --- a/xbmc/__init__.py +++ /dev/null @@ -1,202 +0,0 @@ -#!/usr/bin/env python3 -# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab -######################################################################### -# Copyright 2013 Marcus Popp marcus@popp.mx -# Copyright 2017 Sebastian Sudholt sebastian.sudholt@tu-dortmund.de -######################################################################### -# This file is part of SmartHome.py. http://mknx.github.io/smarthome/ -# -# SmartHome.py is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# SmartHome.py is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with SmartHome.py. If not, see . -######################################################################### - -import logging -import threading -import json -import lib.connection - -logger = logging.getLogger('') - - -class Kodi(): - - def __init__(self, smarthome): - self._sh = smarthome - self._boxes = [] - - def run(self): - self.alive = True - - def stop(self): - self.alive = False - for box in self._boxes: - box.handle_close() - - def notify_all(self, title, message, image=None): - for box in self._boxes: - box.notify(title, message, image) - - def parse_item(self, item): - if 'kodi_host' in item.conf: - self._boxes.append(kodi(self._sh, item)) - - -class kodi(lib.connection.Client): - - _notification_time = 10000 - _listen_keys = ['volume', 'mute', 'title', 'media', 'state'] - _send_keys = {'volume': 'Application.SetVolume', 'mute': 'Application.SetMute', - 'left': 'Input.Left', 'right': 'Input.Right', 'up': 'Input.Up', 'down': 'Input.Down', - 'home': 'Input.Home', 'back': 'Input.Back', 'select': 'Input.Select'} - - def __init__(self, smarthome, item): - if 'kodi_port' in item.conf: - port = int(item.conf['kodi_port']) - else: - port = 9090 - host = item.conf['kodi_host'] - lib.connection.Client.__init__(self, host, port, monitor=True) - self.terminator = 0 - self.balance(b'{', b'}') - self._sh = smarthome - self._id = 1 - self._rid = None - self._cmd_lock = threading.Lock() - self._reply_lock = threading.Condition() - self._reply = None - self._items = {'state': item} - for child in self._sh.find_children(item, 'kodi_listen'): - listen_to = child.conf['kodi_listen'] - if listen_to in self._listen_keys: - self._items[listen_to] = child - for child in self._sh.find_children(item, 'kodi_send'): - send_to = child.conf['kodi_send'] - if send_to in self._send_keys: - child.add_method_trigger(self._send_value) - item.notify = self.notify - - def notify(self, title, message, image=None): - if image is None: - self._send('GUI.ShowNotification', {'title': title, 'message': message, 'displaytime': self._notification_time}) - else: - self._send('GUI.ShowNotification', {'title': title, 'message': message, 'image': image, 'displaytime': self._notification_time}) - - def _send_value(self, item, caller=None, source=None, dest=None): - if caller != 'Kodi': - if 'kodi_params' not in item.conf or item.conf['kodi_params'] == 'None': - params = None - else: - params = item.conf['kodi_params'] - self._send(self._send_keys[item.conf['kodi_send']], params, wait=False) - - def run(self): - self.alive = True - - def _send(self, method, params=None, id=None, wait=True): - self._cmd_lock.acquire() - self._reply = None - if id is None: - self._id += 1 - id = self._id - if id > 100: - self._id = 0 - self._rid = id - if params is not None: - data = {"jsonrpc": "2.0", "id": id, "method": method, 'params': params} - else: - data = {"jsonrpc": "2.0", "id": id, "method": method} - self._reply_lock.acquire() - #logger.debug("Kodi sending: {0}".format(json.dumps(data, separators=(',', ':')))) - self.send((json.dumps(data, separators=(',', ':')) + '\r\n').encode()) - if wait: - self._reply_lock.wait(2) - self._reply_lock.release() - reply = self._reply - self._reply = None - self._cmd_lock.release() - return reply - - def _set_item(self, key, value): - if key in self._items: - self._items[key](value, 'Kodi') - - def found_balance(self, data): - event = json.loads(data.decode()) - #logger.debug("Kodi receiving: {0}".format(event)) - if 'id' in event: - if event['id'] == self._rid: - self._rid = None - self._reply = event - self._reply_lock.acquire() - self._reply_lock.notify() - self._reply_lock.release() - return - if 'method' in event: - if event['method'] == 'Player.OnPause': - if 'state' in self._items: - self._items['state']('Pause', 'Kodi') - elif event['method'] == 'Player.OnStop': - if 'state' in self._items: - self._items['state']('Menu', 'Kodi') - if 'media' in self._items: - self._items['media']('', 'Kodi') - if 'title' in self._items: - self._items['title']('', 'Kodi') - elif event['method'] == 'GUI.OnScreensaverActivated': - if 'state' in self._items: - self._items['state']('Screensaver', 'Kodi') - if event['method'] in ['Player.OnPlay']: - # use a different thread for event handling - self._sh.trigger('kodi-event', self._parse_event, 'Kodi', value={'event': event}) - elif event['method'] in ['Application.OnVolumeChanged']: - if 'mute' in self._items: - self._set_item('mute', event['params']['data']['muted']) - if 'volume' in self._items: - self._set_item('volume', event['params']['data']['volume']) - - - def _parse_event(self, event): - if event['method'] == 'Player.OnPlay': - result = self._send('Player.GetActivePlayers')['result'] - if len(result) == 0: - logger.info("Kodi: no active player found.") - return - playerid = result[0]['playerid'] - typ = result[0]['type'] - self._items['state']('Playing', 'Kodi') - if typ == 'video': - result = self._send('Player.GetItem', {"properties": ["title"], "playerid": playerid}, "VideoGetItem")['result'] - title = result['item']['title'] - if not title and 'label' in result['item']: - title = result['item']['label'] - if 'media' in self._items: - typ = result['item']['type'] - self._items['media'](typ.capitalize(), 'Kodi') - elif typ == 'audio': - if 'media' in self._items: - self._items['media'](typ.capitalize(), 'Kodi') - result = self._send('Player.GetItem', {"properties": ["title", "artist"], "playerid": playerid}, "AudioGetItem")['result'] - if len(result['item']['artist']) == 0: - artist = 'unknown' - else: - artist = result['item']['artist'][0] - title = artist + ' - ' + result['item']['title'] - elif typ == 'picture': - if 'media' in self._items: - self._items['media'](typ.capitalize(), 'Kodi') - title = '' - else: - logger.warning("Kodi: Unknown type: {0}".format(typ)) - return - if 'title' in self._items: - self._items['title'](title, 'Kodi') From fa07cb8f1987d88ed387f270e623bd91418cfe88 Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Sun, 5 Nov 2017 07:57:13 +0100 Subject: [PATCH 011/705] fixed license agreement --- kodi/__init__.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/kodi/__init__.py b/kodi/__init__.py index b43ae8172..655f3766a 100755 --- a/kodi/__init__.py +++ b/kodi/__init__.py @@ -4,20 +4,22 @@ # Copyright 2013 Marcus Popp marcus@popp.mx # Copyright 2017 Sebastian Sudholt sebastian.sudholt@tu-dortmund.de ######################################################################### -# This file is part of SmartHome.py. http://mknx.github.io/smarthome/ # -# SmartHome.py is free software: you can redistribute it and/or modify +# This file is part of SmartHomeNG. +# +# SmartHomeNG is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # -# SmartHome.py is distributed in the hope that it will be useful, +# SmartHomeNG is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with SmartHome.py. If not, see . +# along with SmartHomeNG. If not, see . +# ######################################################################### import logging From ed6e0c6e5280875176bd4edd4a1401339388c9b7 Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Sun, 5 Nov 2017 10:06:52 +0100 Subject: [PATCH 012/705] moved kodi to smartplugin (untested yet) --- kodi/__init__.py | 540 +++++++++++++++++++++++++++++++++++++---------- kodi/plugin.yaml | 10 +- 2 files changed, 426 insertions(+), 124 deletions(-) diff --git a/kodi/__init__.py b/kodi/__init__.py index 655f3766a..4bbaf7d10 100755 --- a/kodi/__init__.py +++ b/kodi/__init__.py @@ -22,183 +22,489 @@ # ######################################################################### +# import logging +# import threading +# import json +# +# import lib.connection +# +# logger = logging.getLogger('') +# +# +# class Kodi(object): +# +# def __init__(self, smarthome, host, port='9090'): +# self._sh = smarthome +# self._boxes = [] +# +# def run(self): +# self.alive = True +# +# def stop(self): +# self.alive = False +# for box in self._boxes: +# box.handle_close() +# +# def notify_all(self, title, message, image=None): +# for box in self._boxes: +# box.notify(title, message, image) +# +# def parse_item(self, item): +# if 'kodi_host' in item.conf: +# self._boxes.append(kodi(self._sh, item)) +# +# +# class kodi(lib.connection.Client): +# +# _notification_time = 10000 +# _listen_keys = ['volume', 'mute', 'title', 'media', 'state'] +# _send_keys = {'volume': 'Application.SetVolume', 'mute': 'Application.SetMute', +# 'left': 'Input.Left', 'right': 'Input.Right', 'up': 'Input.Up', 'down': 'Input.Down', +# 'home': 'Input.Home', 'back': 'Input.Back', 'select': 'Input.Select'} +# +# def __init__(self, smarthome, item): +# if 'kodi_port' in item.conf: +# port = int(item.conf['kodi_port']) +# else: +# port = 9090 +# host = item.conf['kodi_host'] +# lib.connection.Client.__init__(self, host, port, monitor=True) +# self.terminator = 0 +# self.balance(b'{', b'}') +# self._sh = smarthome +# self.message_id = 1 +# self._rid = None +# self._cmd_lock = threading.Lock() +# self._reply_lock = threading.Condition() +# self._reply = None +# self._items = {'state': item} +# for child in self._sh.find_children(item, 'kodi_listen'): +# listen_to = child.conf['kodi_listen'] +# if listen_to in self._listen_keys: +# self._items[listen_to] = child +# for child in self._sh.find_children(item, 'kodi_send'): +# send_to = child.conf['kodi_send'] +# if send_to in self._send_keys: +# child.add_method_trigger(self._send_value) +# item.notify = self.notify +# +# def notify(self, title, message, image=None): +# if image is None: +# self._send('GUI.ShowNotification', {'title': title, 'message': message, 'displaytime': self._notification_time}) +# else: +# self._send('GUI.ShowNotification', {'title': title, 'message': message, 'image': image, 'displaytime': self._notification_time}) +# +# def _send_value(self, item, caller=None, source=None, dest=None): +# if caller != 'Kodi': +# if 'kodi_params' not in item.conf or item.conf['kodi_params'] == 'None': +# params = None +# else: +# params = item.conf['kodi_params'] +# self._send(self._send_keys[item.conf['kodi_send']], params, wait=False) +# +# def run(self): +# self.alive = True +# +# def _send(self, method, params=None, id=None, wait=True): +# self._cmd_lock.acquire() +# self._reply = None +# if id is None: +# self.message_id += 1 +# id = self.message_id +# if id > 100: +# self.message_id = 0 +# self._rid = id +# if params is not None: +# data = {"jsonrpc": "2.0", "id": id, "method": method, 'params': params} +# else: +# data = {"jsonrpc": "2.0", "id": id, "method": method} +# self._reply_lock.acquire() +# #logger.debug("Kodi sending: {0}".format(json.dumps(data, separators=(',', ':')))) +# self.send((json.dumps(data, separators=(',', ':')) + '\r\n').encode()) +# if wait: +# self._reply_lock.wait(2) +# self._reply_lock.release() +# reply = self._reply +# self._reply = None +# self._cmd_lock.release() +# return reply +# +# def _set_item(self, key, value): +# if key in self._items: +# self._items[key](value, 'Kodi') +# +# def found_balance(self, data): +# event = json.loads(data.decode()) +# #logger.debug("Kodi receiving: {0}".format(event)) +# if 'id' in event: +# if event['id'] == self._rid: +# self._rid = None +# self._reply = event +# self._reply_lock.acquire() +# self._reply_lock.notify() +# self._reply_lock.release() +# return +# if 'method' in event: +# if event['method'] == 'Player.OnPause': +# if 'state' in self._items: +# self._items['state']('Pause', 'Kodi') +# elif event['method'] == 'Player.OnStop': +# if 'state' in self._items: +# self._items['state']('Menu', 'Kodi') +# if 'media' in self._items: +# self._items['media']('', 'Kodi') +# if 'title' in self._items: +# self._items['title']('', 'Kodi') +# elif event['method'] == 'GUI.OnScreensaverActivated': +# if 'state' in self._items: +# self._items['state']('Screensaver', 'Kodi') +# if event['method'] in ['Player.OnPlay']: +# # use a different thread for event handling +# self._sh.trigger('kodi-event', self._parse_event, 'Kodi', value={'event': event}) +# elif event['method'] in ['Application.OnVolumeChanged']: +# if 'mute' in self._items: +# self._set_item('mute', event['params']['data']['muted']) +# if 'volume' in self._items: +# self._set_item('volume', event['params']['data']['volume']) +# +# +# def _parse_event(self, event): +# if event['method'] == 'Player.OnPlay': +# result = self._send('Player.GetActivePlayers')['result'] +# if len(result) == 0: +# logger.info("Kodi: no active player found.") +# return +# playerid = result[0]['playerid'] +# typ = result[0]['type'] +# self._items['state']('Playing', 'Kodi') +# if typ == 'video': +# result = self._send('Player.GetItem', {"properties": ["title"], "playerid": playerid}, "VideoGetItem")['result'] +# title = result['item']['title'] +# if not title and 'label' in result['item']: +# title = result['item']['label'] +# if 'media' in self._items: +# typ = result['item']['type'] +# self._items['media'](typ.capitalize(), 'Kodi') +# elif typ == 'audio': +# if 'media' in self._items: +# self._items['media'](typ.capitalize(), 'Kodi') +# result = self._send('Player.GetItem', {"properties": ["title", "artist"], "playerid": playerid}, "AudioGetItem")['result'] +# if len(result['item']['artist']) == 0: +# artist = 'unknown' +# else: +# artist = result['item']['artist'][0] +# title = artist + ' - ' + result['item']['title'] +# elif typ == 'picture': +# if 'media' in self._items: +# self._items['media'](typ.capitalize(), 'Kodi') +# title = '' +# else: +# logger.warning("Kodi: Unknown type: {0}".format(typ)) +# return +# if 'title' in self._items: +# self._items['title'](title, 'Kodi') + + + ### import logging import threading import json -import lib.connection -logger = logging.getLogger('') +from lib.model.smartplugin import SmartPlugin +from lib.connection import Client -class Kodi(): +class Kodi(SmartPlugin, Client): + ''' + Main class of the Plugin. Does all plugin specific stuff and provides + the update functions for the items + ''' + + PLUGIN_VERSION='1.3c.0' + + _listen_keys = ['volume', 'mute', 'title', 'media', 'state'] + _send_keys = {'volume': dict(method='Application.SetVolume', params=dict(volume='ITEM_VALUE')), + 'mute ': dict(method='Application.SetMute', params = dict(mute='ITEM_VALUE')), + 'left' : dict(method='Input.Left', params=None), + 'right' : dict(method='Input.Right', params=None), + 'up' : dict(method='Input.Up', params=None), + 'down' : dict(method='Input.Down', params=None), + 'home' : dict(method='Input.Home', params=None), + 'back' : dict(method='Input.Back', params=None), + 'select': dict(method='Input.Select', params=None)} + + def __init__(self, sh, *args, **kwargs): + ''' + Initalizes the plugin. The parameters describe for this method are pulled from the entry in plugin.conf. + + :param sh: **Deprecated**: The instance of the smarthome object. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! + :param *args: **Deprecated**: Old way of passing parameter values. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! + :param **kwargs:**Deprecated**: Old way of passing parameter values. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! + + If you need the sh object at all, use the method self.get_sh() to get it. There should be almost no need for + a reference to the sh object any more. + + The parameters *args and **kwargs are the old way of passing parameters. They are deprecated. They are implemented + to support oder plugins. Plugins for SmartHomeNG v1.4 and beyond should use the new way of getting parameter values: + use the SmartPlugin method `get_parameter_value(parameter_name)` instead. Anywhere within the Plugin you can get + the configured (and checked) value for a parameter by calling `self.get_parameter_value(parameter_name)`. It + returns the value in the datatype that is defined in the metadata. + ''' + # init logger + self.logger = logging.getLogger(__name__) + self.logger.info('Init Kodi Plugin') + + # setup everything for the connection later +# if 'kodi_port' in item.conf: +# port = int(item.conf['kodi_port']) +# else: +# port = 9090 +# host = item.conf['kodi_host'] + Client.__init__(self, + self.get_parameter_value('host'), + self.get_parameter_value('port'), + monitor=True) + self.terminator = 0 + self.balance(b'{', b'}') +# self._sh = smarthome + self.message_id = 1 + self.response_id = None + self.cmd_lock = threading.Lock() + self.reply_lock = threading.Condition() + self.reply = None + self.registered_items = {key: [] for key in set(Kodi._send_keys.keys() + Kodi._listen_keys)} +# self._items = {'state': item} +# for child in self._sh.find_children(item, 'kodi_listen'): +# listen_to = child.conf['kodi_listen'] +# if listen_to in self._listen_keys: +# self._items[listen_to] = child +# for child in self._sh.find_children(item, 'kodi_send'): +# send_to = child.conf['kodi_send'] +# if send_to in self._send_keys: +# child.add_method_trigger(self._send_value) +# item.notify = self.notify - def __init__(self, smarthome): - self._sh = smarthome - self._boxes = [] def run(self): + ''' + Run method for the plugin + ''' + self.logger.debug('Plugin \'{}\': run method called'.format(self.get_shortname())) self.alive = True def stop(self): + ''' + Stop method for the plugin + ''' + self.logger.debug('Plugin \'{}\': stop method called'.format(self.get_shortname())) self.alive = False - for box in self._boxes: - box.handle_close() - def notify_all(self, title, message, image=None): - for box in self._boxes: - box.notify(title, message, image) def parse_item(self, item): - if 'kodi_host' in item.conf: - self._boxes.append(kodi(self._sh, item)) + ''' + Default plugin parse_item method. Is called when the plugin is initialized. + The plugin can, corresponding to its attribute keywords, decide what to do with + the item in future, like adding it to an internal array for future reference + :param item: The item to process. + :return: If the plugin needs to be informed of an items change you should return a call back function + like the function update_item down below. An example when this is needed is the knx plugin + where parse_item returns the update_item function when the attribute knx_send is found. + This means that when the items value is about to be updated, the call back function is called + with the item, caller, source and dest as arguments and in case of the knx plugin the value + can be sent to the knx with a knx write function within the knx plugin. + ''' + if self.has_iattr(item.conf, 'kodi_item'): + self.logger.debug('Plugin \'{}\': parse item: {}'.format(self.get_shortname(), item)) + if item.name in Kodi._send_keys: + return self.update_item + # todo + # if interesting item for sending values: + # return update_item -class kodi(lib.connection.Client): - _notification_time = 10000 - _listen_keys = ['volume', 'mute', 'title', 'media', 'state'] - _send_keys = {'volume': 'Application.SetVolume', 'mute': 'Application.SetMute', - 'left': 'Input.Left', 'right': 'Input.Right', 'up': 'Input.Up', 'down': 'Input.Down', - 'home': 'Input.Home', 'back': 'Input.Back', 'select': 'Input.Select'} + def parse_logic(self, logic): + ''' + Default plugin parse_logic method + ''' + if 'xxx' in logic.conf: + # self.function(logic['name']) + pass - def __init__(self, smarthome, item): - if 'kodi_port' in item.conf: - port = int(item.conf['kodi_port']) - else: - port = 9090 - host = item.conf['kodi_host'] - lib.connection.Client.__init__(self, host, port, monitor=True) - self.terminator = 0 - self.balance(b'{', b'}') - self._sh = smarthome - self._id = 1 - self._rid = None - self._cmd_lock = threading.Lock() - self._reply_lock = threading.Condition() - self._reply = None - self._items = {'state': item} - for child in self._sh.find_children(item, 'kodi_listen'): - listen_to = child.conf['kodi_listen'] - if listen_to in self._listen_keys: - self._items[listen_to] = child - for child in self._sh.find_children(item, 'kodi_send'): - send_to = child.conf['kodi_send'] - if send_to in self._send_keys: - child.add_method_trigger(self._send_value) - item.notify = self.notify - - def notify(self, title, message, image=None): - if image is None: - self._send('GUI.ShowNotification', {'title': title, 'message': message, 'displaytime': self._notification_time}) - else: - self._send('GUI.ShowNotification', {'title': title, 'message': message, 'image': image, 'displaytime': self._notification_time}) - def _send_value(self, item, caller=None, source=None, dest=None): - if caller != 'Kodi': - if 'kodi_params' not in item.conf or item.conf['kodi_params'] == 'None': - params = None - else: - params = item.conf['kodi_params'] - self._send(self._send_keys[item.conf['kodi_send']], params, wait=False) + def update_item(self, item, caller=None, source=None, dest=None): + ''' + Callback method for sending values to Kodi when a registered item has changed - def run(self): - self.alive = True + :param item: item to be updated towards the plugin + :param caller: if given it represents the callers name + :param source: if given it represents the source + :param dest: if given it represents the dest + ''' + if item(): + if caller != 'Kodi' and self.has_iattr(item.conf, 'kodi_item'): + # update item was triggered from sometthing else then this plugin -> send to Kodi + kodi_item = self.get_iattr_value(item.conf, 'kodi_item') + if kodi_item in Kodi._send_keys: + self.logger.debug('Plugin \'{}\': update_item ws called with item \'{}\' from caller \'{}\', source \'{}\' and dest \'{}\''.format(self.get_shortname(), item, caller, source, dest)) + method = self._send_keys[kodi_item]['method'] + params = self._send_keys[kodi_item]['params'] + if params is not None: + # copy so we don't interfer with the class variable + params = params.copy() + # replace the wild card ITEM_VALUE with the item's value + for key, value in params.items(): + if value == 'ITEM_VALUE': + params[key] = item() + self._send(method, params, wait=False) + else: + self.logger.info('kodi_item \'%s\' not in send_keys, skipping!', kodi_item) + + def notify(self, title, message, image=None, display_time=10000): + ''' + Send a notification to Kodi to be displayed on the screen + + :param title: the title of the message + :param message: the message itself + :param image: an optional image to be displayed alongside the message + :param display_time: how long the message is displayed in milli seconds + ''' + params = dict(title=title, message=message,displaytime=display_time) + if image is not None: + params['image'] = image + self.send_kodi_rpc(method='GUI.ShowNotification', params=params) + +# def _send_value(self, item, caller=None, source=None, dest=None): +# if caller != 'Kodi': +# if 'kodi_params' not in item.conf or item.conf['kodi_params'] == 'None': +# params = None +# else: +# params = item.conf['kodi_params'] +# self.send_kodi_rpc(self._send_keys[item.conf['kodi_send']], params, wait=False) - def _send(self, method, params=None, id=None, wait=True): - self._cmd_lock.acquire() - self._reply = None - if id is None: - self._id += 1 - id = self._id + def send_kodi_rpc(self, method, params=None, message_id=None, wait=True): + self.cmd_lock.acquire() + self.reply = None + if message_id is None: + self.message_id += 1 + message_id = self.message_id if id > 100: - self._id = 0 - self._rid = id + self.message_id = 0 + self.response_id = message_id if params is not None: - data = {"jsonrpc": "2.0", "id": id, "method": method, 'params': params} + data = {'jsonrpc': '2.0', 'id': message_id, 'method': method, 'params': params} else: - data = {"jsonrpc": "2.0", "id": id, "method": method} - self._reply_lock.acquire() - #logger.debug("Kodi sending: {0}".format(json.dumps(data, separators=(',', ':')))) + data = {'jsonrpc': '2.0', 'id': message_id, 'method': method} + self.reply_lock.acquire() + self.logger.debug('Kodi sending: {0}'.format(json.dumps(data, separators=(',', ':')))) self.send((json.dumps(data, separators=(',', ':')) + '\r\n').encode()) if wait: - self._reply_lock.wait(2) - self._reply_lock.release() - reply = self._reply - self._reply = None - self._cmd_lock.release() + self.reply_lock.wait(2) + self.reply_lock.release() + reply = self.reply + self.reply = None + self.cmd_lock.release() return reply - def _set_item(self, key, value): - if key in self._items: - self._items[key](value, 'Kodi') +# def _set_item(self, key, value): +# if key in self._items: +# self._items[key](value, 'Kodi') def found_balance(self, data): event = json.loads(data.decode()) - #logger.debug("Kodi receiving: {0}".format(event)) + self.logger.debug('Kodi receiving: {0}'.format(event)) if 'id' in event: - if event['id'] == self._rid: - self._rid = None - self._reply = event - self._reply_lock.acquire() - self._reply_lock.notify() - self._reply_lock.release() + if event['id'] == self.response_id: + self.response_id = None + self.reply = event + self.reply_lock.acquire() + self.reply_lock.notify() + self.reply_lock.release() return if 'method' in event: if event['method'] == 'Player.OnPause': - if 'state' in self._items: - self._items['state']('Pause', 'Kodi') + for elem in self.registered_items['state']: + elem('Pause', caller='Kodi') +# if 'state' in self._items: +# self._items['state']('Pause', 'Kodi') elif event['method'] == 'Player.OnStop': - if 'state' in self._items: - self._items['state']('Menu', 'Kodi') - if 'media' in self._items: - self._items['media']('', 'Kodi') - if 'title' in self._items: - self._items['title']('', 'Kodi') +# if 'state' in self._items: +# self._items['state']('Menu', 'Kodi') + for elem in self.registered_items['state']: + elem('Pause', caller='Kodi') +# if 'media' in self._items: +# self._items['media']('', 'Kodi') + for elem in self.registered_items['media']: + elem('', caller='Kodi') +# if 'title' in self._items: +# self._items['title']('', 'Kodi') + for elem in self.registered_items['title']: + elem('Pause', caller='Kodi') elif event['method'] == 'GUI.OnScreensaverActivated': - if 'state' in self._items: - self._items['state']('Screensaver', 'Kodi') +# if 'state' in self._items: +# self._items['state']('Screensaver', 'Kodi') + for elem in self.registered_items['state']: + elem('Screensaver', caller='Kodi') if event['method'] in ['Player.OnPlay']: # use a different thread for event handling - self._sh.trigger('kodi-event', self._parse_event, 'Kodi', value={'event': event}) + self.get_sh().trigger('kodi-event', self._parse_event, 'Kodi', value={'event': event}) elif event['method'] in ['Application.OnVolumeChanged']: - if 'mute' in self._items: - self._set_item('mute', event['params']['data']['muted']) - if 'volume' in self._items: - self._set_item('volume', event['params']['data']['volume']) - +# if 'mute' in self._items: +# self._set_item('mute', event['params']['data']['muted']) + for elem in self.registered_items['mute']: + elem(event['params']['data']['muted'], caller='Kodi') +# if 'volume' in self._items: +# self._set_item('volume', event['params']['data']['volume']) + for elem in self.registered_items['volume']: + elem(event['params']['data']['volume'], caller='Kodi') def _parse_event(self, event): if event['method'] == 'Player.OnPlay': - result = self._send('Player.GetActivePlayers')['result'] + result = self.send_kodi_rpc(method='Player.GetActivePlayers')['result'] if len(result) == 0: - logger.info("Kodi: no active player found.") + self.logger.info('Kodi: no active player found.') return playerid = result[0]['playerid'] typ = result[0]['type'] - self._items['state']('Playing', 'Kodi') +# self._items['state']('Playing', 'Kodi') + for elem in self.registered_items['state']: + elem('Playing', caller='Kodi') if typ == 'video': - result = self._send('Player.GetItem', {"properties": ["title"], "playerid": playerid}, "VideoGetItem")['result'] + result = self.send_kodi_rpc(method='Player.GetItem', + params=dict(properties=['title'], playerid=playerid), + message_id='VideoGetItem')['result'] title = result['item']['title'] + typ = result['item']['type'] if not title and 'label' in result['item']: title = result['item']['label'] - if 'media' in self._items: - typ = result['item']['type'] - self._items['media'](typ.capitalize(), 'Kodi') +# if 'media' in self._items: +# typ = result['item']['type'] +# self._items['media'](typ.capitalize(), 'Kodi') + for elem in self.registered_items['media']: + elem(typ.capitalize(), caller='Kodi') elif typ == 'audio': - if 'media' in self._items: - self._items['media'](typ.capitalize(), 'Kodi') - result = self._send('Player.GetItem', {"properties": ["title", "artist"], "playerid": playerid}, "AudioGetItem")['result'] +# if 'media' in self._items: +# self._items['media'](typ.capitalize(), 'Kodi') + for elem in self.registered_items['media']: + elem('Audio', caller='Kodi') + result = self.send_kodi_rpc(method='Player.GetItem', + params=dict(properties=['title', 'artist'], playerid=playerid), + message_id='AudioGetItem')['result'] if len(result['item']['artist']) == 0: artist = 'unknown' else: artist = result['item']['artist'][0] title = artist + ' - ' + result['item']['title'] elif typ == 'picture': - if 'media' in self._items: - self._items['media'](typ.capitalize(), 'Kodi') +# if 'media' in self._items: +# self._items['media'](typ.capitalize(), 'Kodi') + for elem in self.registered_items['media']: + elem('Picture', caller='Kodi') title = '' else: - logger.warning("Kodi: Unknown type: {0}".format(typ)) + self.logger.warning('Kodi: Unknown type: {0}'.format(typ)) return - if 'title' in self._items: - self._items['title'](title, 'Kodi') +# if 'title' in self._items: +# self._items['title'](title, 'Kodi') + for elem in self.registered_items['title']: + elem(title, caller='Kodi') diff --git a/kodi/plugin.yaml b/kodi/plugin.yaml index 1fd2df9d1..2f61b24df 100755 --- a/kodi/plugin.yaml +++ b/kodi/plugin.yaml @@ -18,14 +18,10 @@ plugin: multi_instance: True classname: Kodi # class containing the plugin -parameters: +#parameters: # Definition of parameters to be configured in etc/plugin.yaml - host: - type: ipv4 - - port: - type: int - default: 9090 + host: str + port: int #item_attributes: # Definition of item attributes defined by this plugin From d6541e52f6814deaf901ee41d5d58c5f51d42c18 Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Tue, 7 Nov 2017 07:15:03 +0100 Subject: [PATCH 013/705] updated to SmartPlugin, needs testing --- kodi/__init__.py | 1 + kodi/plugin.yaml | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/kodi/__init__.py b/kodi/__init__.py index 4bbaf7d10..6037cc98a 100755 --- a/kodi/__init__.py +++ b/kodi/__init__.py @@ -221,6 +221,7 @@ class Kodi(SmartPlugin, Client): ''' PLUGIN_VERSION='1.3c.0' + ALLOW_MULTIINSTANCE = True _listen_keys = ['volume', 'mute', 'title', 'media', 'state'] _send_keys = {'volume': dict(method='Application.SetVolume', params=dict(volume='ITEM_VALUE')), diff --git a/kodi/plugin.yaml b/kodi/plugin.yaml index 2f61b24df..d4b5cc3ce 100755 --- a/kodi/plugin.yaml +++ b/kodi/plugin.yaml @@ -20,8 +20,12 @@ plugin: #parameters: # Definition of parameters to be configured in etc/plugin.yaml - host: str - port: int + host: + type: ipv4 + + port: + type: int + default: 9090 #item_attributes: # Definition of item attributes defined by this plugin From 25b772c286c09ec3d325efec3d77276fec482d51 Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Tue, 7 Nov 2017 17:46:53 +0100 Subject: [PATCH 014/705] preliminary finish, already some testing done --- kodi/__init__.py | 366 ++++++++++------------------------------------- kodi/plugin.yaml | 2 +- 2 files changed, 80 insertions(+), 288 deletions(-) diff --git a/kodi/__init__.py b/kodi/__init__.py index 6037cc98a..aef4e330f 100755 --- a/kodi/__init__.py +++ b/kodi/__init__.py @@ -22,190 +22,6 @@ # ######################################################################### -# import logging -# import threading -# import json -# -# import lib.connection -# -# logger = logging.getLogger('') -# -# -# class Kodi(object): -# -# def __init__(self, smarthome, host, port='9090'): -# self._sh = smarthome -# self._boxes = [] -# -# def run(self): -# self.alive = True -# -# def stop(self): -# self.alive = False -# for box in self._boxes: -# box.handle_close() -# -# def notify_all(self, title, message, image=None): -# for box in self._boxes: -# box.notify(title, message, image) -# -# def parse_item(self, item): -# if 'kodi_host' in item.conf: -# self._boxes.append(kodi(self._sh, item)) -# -# -# class kodi(lib.connection.Client): -# -# _notification_time = 10000 -# _listen_keys = ['volume', 'mute', 'title', 'media', 'state'] -# _send_keys = {'volume': 'Application.SetVolume', 'mute': 'Application.SetMute', -# 'left': 'Input.Left', 'right': 'Input.Right', 'up': 'Input.Up', 'down': 'Input.Down', -# 'home': 'Input.Home', 'back': 'Input.Back', 'select': 'Input.Select'} -# -# def __init__(self, smarthome, item): -# if 'kodi_port' in item.conf: -# port = int(item.conf['kodi_port']) -# else: -# port = 9090 -# host = item.conf['kodi_host'] -# lib.connection.Client.__init__(self, host, port, monitor=True) -# self.terminator = 0 -# self.balance(b'{', b'}') -# self._sh = smarthome -# self.message_id = 1 -# self._rid = None -# self._cmd_lock = threading.Lock() -# self._reply_lock = threading.Condition() -# self._reply = None -# self._items = {'state': item} -# for child in self._sh.find_children(item, 'kodi_listen'): -# listen_to = child.conf['kodi_listen'] -# if listen_to in self._listen_keys: -# self._items[listen_to] = child -# for child in self._sh.find_children(item, 'kodi_send'): -# send_to = child.conf['kodi_send'] -# if send_to in self._send_keys: -# child.add_method_trigger(self._send_value) -# item.notify = self.notify -# -# def notify(self, title, message, image=None): -# if image is None: -# self._send('GUI.ShowNotification', {'title': title, 'message': message, 'displaytime': self._notification_time}) -# else: -# self._send('GUI.ShowNotification', {'title': title, 'message': message, 'image': image, 'displaytime': self._notification_time}) -# -# def _send_value(self, item, caller=None, source=None, dest=None): -# if caller != 'Kodi': -# if 'kodi_params' not in item.conf or item.conf['kodi_params'] == 'None': -# params = None -# else: -# params = item.conf['kodi_params'] -# self._send(self._send_keys[item.conf['kodi_send']], params, wait=False) -# -# def run(self): -# self.alive = True -# -# def _send(self, method, params=None, id=None, wait=True): -# self._cmd_lock.acquire() -# self._reply = None -# if id is None: -# self.message_id += 1 -# id = self.message_id -# if id > 100: -# self.message_id = 0 -# self._rid = id -# if params is not None: -# data = {"jsonrpc": "2.0", "id": id, "method": method, 'params': params} -# else: -# data = {"jsonrpc": "2.0", "id": id, "method": method} -# self._reply_lock.acquire() -# #logger.debug("Kodi sending: {0}".format(json.dumps(data, separators=(',', ':')))) -# self.send((json.dumps(data, separators=(',', ':')) + '\r\n').encode()) -# if wait: -# self._reply_lock.wait(2) -# self._reply_lock.release() -# reply = self._reply -# self._reply = None -# self._cmd_lock.release() -# return reply -# -# def _set_item(self, key, value): -# if key in self._items: -# self._items[key](value, 'Kodi') -# -# def found_balance(self, data): -# event = json.loads(data.decode()) -# #logger.debug("Kodi receiving: {0}".format(event)) -# if 'id' in event: -# if event['id'] == self._rid: -# self._rid = None -# self._reply = event -# self._reply_lock.acquire() -# self._reply_lock.notify() -# self._reply_lock.release() -# return -# if 'method' in event: -# if event['method'] == 'Player.OnPause': -# if 'state' in self._items: -# self._items['state']('Pause', 'Kodi') -# elif event['method'] == 'Player.OnStop': -# if 'state' in self._items: -# self._items['state']('Menu', 'Kodi') -# if 'media' in self._items: -# self._items['media']('', 'Kodi') -# if 'title' in self._items: -# self._items['title']('', 'Kodi') -# elif event['method'] == 'GUI.OnScreensaverActivated': -# if 'state' in self._items: -# self._items['state']('Screensaver', 'Kodi') -# if event['method'] in ['Player.OnPlay']: -# # use a different thread for event handling -# self._sh.trigger('kodi-event', self._parse_event, 'Kodi', value={'event': event}) -# elif event['method'] in ['Application.OnVolumeChanged']: -# if 'mute' in self._items: -# self._set_item('mute', event['params']['data']['muted']) -# if 'volume' in self._items: -# self._set_item('volume', event['params']['data']['volume']) -# -# -# def _parse_event(self, event): -# if event['method'] == 'Player.OnPlay': -# result = self._send('Player.GetActivePlayers')['result'] -# if len(result) == 0: -# logger.info("Kodi: no active player found.") -# return -# playerid = result[0]['playerid'] -# typ = result[0]['type'] -# self._items['state']('Playing', 'Kodi') -# if typ == 'video': -# result = self._send('Player.GetItem', {"properties": ["title"], "playerid": playerid}, "VideoGetItem")['result'] -# title = result['item']['title'] -# if not title and 'label' in result['item']: -# title = result['item']['label'] -# if 'media' in self._items: -# typ = result['item']['type'] -# self._items['media'](typ.capitalize(), 'Kodi') -# elif typ == 'audio': -# if 'media' in self._items: -# self._items['media'](typ.capitalize(), 'Kodi') -# result = self._send('Player.GetItem', {"properties": ["title", "artist"], "playerid": playerid}, "AudioGetItem")['result'] -# if len(result['item']['artist']) == 0: -# artist = 'unknown' -# else: -# artist = result['item']['artist'][0] -# title = artist + ' - ' + result['item']['title'] -# elif typ == 'picture': -# if 'media' in self._items: -# self._items['media'](typ.capitalize(), 'Kodi') -# title = '' -# else: -# logger.warning("Kodi: Unknown type: {0}".format(typ)) -# return -# if 'title' in self._items: -# self._items['title'](title, 'Kodi') - - - ### import logging import threading import json @@ -223,9 +39,10 @@ class Kodi(SmartPlugin, Client): PLUGIN_VERSION='1.3c.0' ALLOW_MULTIINSTANCE = True - _listen_keys = ['volume', 'mute', 'title', 'media', 'state'] - _send_keys = {'volume': dict(method='Application.SetVolume', params=dict(volume='ITEM_VALUE')), - 'mute ': dict(method='Application.SetMute', params = dict(mute='ITEM_VALUE')), + _get_items = ['volume', 'mute', 'title', 'media', 'state'] + + _set_items = {'volume': dict(method='Application.SetVolume', params=dict(volume='ITEM_VALUE')), + 'mute' : dict(method='Application.SetMute', params = dict(mute='ITEM_VALUE')), 'left' : dict(method='Input.Left', params=None), 'right' : dict(method='Input.Right', params=None), 'up' : dict(method='Input.Up', params=None), @@ -254,37 +71,18 @@ def __init__(self, sh, *args, **kwargs): # init logger self.logger = logging.getLogger(__name__) self.logger.info('Init Kodi Plugin') - - # setup everything for the connection later -# if 'kodi_port' in item.conf: -# port = int(item.conf['kodi_port']) -# else: -# port = 9090 -# host = item.conf['kodi_host'] Client.__init__(self, self.get_parameter_value('host'), self.get_parameter_value('port'), monitor=True) self.terminator = 0 self.balance(b'{', b'}') -# self._sh = smarthome self.message_id = 1 self.response_id = None self.cmd_lock = threading.Lock() self.reply_lock = threading.Condition() self.reply = None - self.registered_items = {key: [] for key in set(Kodi._send_keys.keys() + Kodi._listen_keys)} -# self._items = {'state': item} -# for child in self._sh.find_children(item, 'kodi_listen'): -# listen_to = child.conf['kodi_listen'] -# if listen_to in self._listen_keys: -# self._items[listen_to] = child -# for child in self._sh.find_children(item, 'kodi_send'): -# send_to = child.conf['kodi_send'] -# if send_to in self._send_keys: -# child.add_method_trigger(self._send_value) -# item.notify = self.notify - + self.registered_items = {key: [] for key in set(list(Kodi._set_items.keys()) + Kodi._get_items)} def run(self): ''' @@ -299,7 +97,22 @@ def stop(self): ''' self.logger.debug('Plugin \'{}\': stop method called'.format(self.get_shortname())) self.alive = False - + + def handle_connect(self): + ''' + This method is called on a succesful connect to Kodi + On a connect initialize all items with values extracted from Kodi + ''' + # get volume and mute state + result = self.send_kodi_rpc(method='Application.GetProperties', + params=dict(properties=['volume', 'muted']))['result'] + for elem in self.registered_items['mute']: + elem(result['muted'], caller='Kodi') + for elem in self.registered_items['volume']: + elem(result['volume'], caller='Kodi') + + # parse active player (if present) + self._get_player_info() def parse_item(self, item): ''' @@ -315,15 +128,15 @@ def parse_item(self, item): can be sent to the knx with a knx write function within the knx plugin. ''' if self.has_iattr(item.conf, 'kodi_item'): + kodi_item = self.get_iattr_value(item.conf, 'kodi_item') self.logger.debug('Plugin \'{}\': parse item: {}'.format(self.get_shortname(), item)) - if item.name in Kodi._send_keys: + if kodi_item in self.registered_items: + self.registered_items[kodi_item].append(item) + else: + self.logger.warning('I do not know the kodi_item \'%s\', skipping!', kodi_item) + if kodi_item in Kodi._set_items: return self.update_item - # todo - # if interesting item for sending values: - # return update_item - - def parse_logic(self, logic): ''' Default plugin parse_logic method @@ -346,10 +159,10 @@ def update_item(self, item, caller=None, source=None, dest=None): if caller != 'Kodi' and self.has_iattr(item.conf, 'kodi_item'): # update item was triggered from sometthing else then this plugin -> send to Kodi kodi_item = self.get_iattr_value(item.conf, 'kodi_item') - if kodi_item in Kodi._send_keys: + if kodi_item in Kodi._set_items: self.logger.debug('Plugin \'{}\': update_item ws called with item \'{}\' from caller \'{}\', source \'{}\' and dest \'{}\''.format(self.get_shortname(), item, caller, source, dest)) - method = self._send_keys[kodi_item]['method'] - params = self._send_keys[kodi_item]['params'] + method = self._set_items[kodi_item]['method'] + params = self._set_items[kodi_item]['params'] if params is not None: # copy so we don't interfer with the class variable params = params.copy() @@ -375,21 +188,13 @@ def notify(self, title, message, image=None, display_time=10000): params['image'] = image self.send_kodi_rpc(method='GUI.ShowNotification', params=params) -# def _send_value(self, item, caller=None, source=None, dest=None): -# if caller != 'Kodi': -# if 'kodi_params' not in item.conf or item.conf['kodi_params'] == 'None': -# params = None -# else: -# params = item.conf['kodi_params'] -# self.send_kodi_rpc(self._send_keys[item.conf['kodi_send']], params, wait=False) - def send_kodi_rpc(self, method, params=None, message_id=None, wait=True): self.cmd_lock.acquire() self.reply = None if message_id is None: self.message_id += 1 message_id = self.message_id - if id > 100: + if message_id > 99: self.message_id = 0 self.response_id = message_id if params is not None: @@ -407,10 +212,6 @@ def send_kodi_rpc(self, method, params=None, message_id=None, wait=True): self.cmd_lock.release() return reply -# def _set_item(self, key, value): -# if key in self._items: -# self._items[key](value, 'Kodi') - def found_balance(self, data): event = json.loads(data.decode()) self.logger.debug('Kodi receiving: {0}'.format(event)) @@ -426,86 +227,77 @@ def found_balance(self, data): if event['method'] == 'Player.OnPause': for elem in self.registered_items['state']: elem('Pause', caller='Kodi') -# if 'state' in self._items: -# self._items['state']('Pause', 'Kodi') elif event['method'] == 'Player.OnStop': -# if 'state' in self._items: -# self._items['state']('Menu', 'Kodi') for elem in self.registered_items['state']: - elem('Pause', caller='Kodi') -# if 'media' in self._items: -# self._items['media']('', 'Kodi') + elem('Stopped Player', caller='Kodi') for elem in self.registered_items['media']: elem('', caller='Kodi') -# if 'title' in self._items: -# self._items['title']('', 'Kodi') for elem in self.registered_items['title']: - elem('Pause', caller='Kodi') + elem('', caller='Kodi') elif event['method'] == 'GUI.OnScreensaverActivated': -# if 'state' in self._items: -# self._items['state']('Screensaver', 'Kodi') for elem in self.registered_items['state']: elem('Screensaver', caller='Kodi') if event['method'] in ['Player.OnPlay']: # use a different thread for event handling - self.get_sh().trigger('kodi-event', self._parse_event, 'Kodi', value={'event': event}) + self.get_sh().trigger('kodi-event', self._get_player_info, 'Kodi') elif event['method'] in ['Application.OnVolumeChanged']: -# if 'mute' in self._items: -# self._set_item('mute', event['params']['data']['muted']) for elem in self.registered_items['mute']: elem(event['params']['data']['muted'], caller='Kodi') -# if 'volume' in self._items: -# self._set_item('volume', event['params']['data']['volume']) for elem in self.registered_items['volume']: elem(event['params']['data']['volume'], caller='Kodi') - def _parse_event(self, event): - if event['method'] == 'Player.OnPlay': - result = self.send_kodi_rpc(method='Player.GetActivePlayers')['result'] - if len(result) == 0: - self.logger.info('Kodi: no active player found.') - return - playerid = result[0]['playerid'] - typ = result[0]['type'] -# self._items['state']('Playing', 'Kodi') + def _get_player_info(self): + result = self.send_kodi_rpc(method='Player.GetActivePlayers')['result'] + if len(result) == 0: + self.logger.info('Kodi: no active player found.') + for elem in self.registered_items['title']: + elem('', caller='Kodi') + for elem in self.registered_items['media']: + elem('', caller='Kodi') for elem in self.registered_items['state']: - elem('Playing', caller='Kodi') - if typ == 'video': - result = self.send_kodi_rpc(method='Player.GetItem', - params=dict(properties=['title'], playerid=playerid), - message_id='VideoGetItem')['result'] - title = result['item']['title'] - typ = result['item']['type'] - if not title and 'label' in result['item']: - title = result['item']['label'] + elem('No Active Player', caller='Kodi') + return + playerid = result[0]['playerid'] + typ = result[0]['type'] +# self._items['state']('Playing', 'Kodi') + for elem in self.registered_items['state']: + elem('Playing', caller='Kodi') + if typ == 'video': + result = self.send_kodi_rpc(method='Player.GetItem', + params=dict(properties=['title'], playerid=playerid), + message_id='VideoGetItem')['result'] + title = result['item']['title'] + typ = result['item']['type'] + if not title and 'label' in result['item']: + title = result['item']['label'] # if 'media' in self._items: # typ = result['item']['type'] # self._items['media'](typ.capitalize(), 'Kodi') - for elem in self.registered_items['media']: - elem(typ.capitalize(), caller='Kodi') - elif typ == 'audio': + for elem in self.registered_items['media']: + elem(typ.capitalize(), caller='Kodi') + elif typ == 'audio': # if 'media' in self._items: # self._items['media'](typ.capitalize(), 'Kodi') - for elem in self.registered_items['media']: - elem('Audio', caller='Kodi') - result = self.send_kodi_rpc(method='Player.GetItem', - params=dict(properties=['title', 'artist'], playerid=playerid), - message_id='AudioGetItem')['result'] - if len(result['item']['artist']) == 0: - artist = 'unknown' - else: - artist = result['item']['artist'][0] - title = artist + ' - ' + result['item']['title'] - elif typ == 'picture': + for elem in self.registered_items['media']: + elem('Audio', caller='Kodi') + result = self.send_kodi_rpc(method='Player.GetItem', + params=dict(properties=['title', 'artist'], playerid=playerid), + message_id='AudioGetItem')['result'] + if len(result['item']['artist']) == 0: + artist = 'unknown' + else: + artist = result['item']['artist'][0] + title = artist + ' - ' + result['item']['title'] + elif typ == 'picture': # if 'media' in self._items: # self._items['media'](typ.capitalize(), 'Kodi') - for elem in self.registered_items['media']: - elem('Picture', caller='Kodi') - title = '' - else: - self.logger.warning('Kodi: Unknown type: {0}'.format(typ)) - return + for elem in self.registered_items['media']: + elem('Picture', caller='Kodi') + title = '' + else: + self.logger.warning('Kodi: Unknown type: {0}'.format(typ)) + return # if 'title' in self._items: # self._items['title'](title, 'Kodi') - for elem in self.registered_items['title']: - elem(title, caller='Kodi') + for elem in self.registered_items['title']: + elem(title, caller='Kodi') diff --git a/kodi/plugin.yaml b/kodi/plugin.yaml index d4b5cc3ce..1fd2df9d1 100755 --- a/kodi/plugin.yaml +++ b/kodi/plugin.yaml @@ -18,7 +18,7 @@ plugin: multi_instance: True classname: Kodi # class containing the plugin -#parameters: +parameters: # Definition of parameters to be configured in etc/plugin.yaml host: type: ipv4 From 36f6828958d57bd2fdd37bd9050f42f6f66adc62 Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Tue, 7 Nov 2017 21:35:30 +0100 Subject: [PATCH 015/705] some documentation --- kodi/README.md | 100 +++++++++++++++++++++++++++++------------------ kodi/__init__.py | 70 +++++++++++++++------------------ 2 files changed, 94 insertions(+), 76 deletions(-) diff --git a/kodi/README.md b/kodi/README.md index b4f12d6c4..f1b82a62d 100644 --- a/kodi/README.md +++ b/kodi/README.md @@ -1,66 +1,96 @@ -# XBMC +# Kodi ## Requirements -You only need one or more XBMC (12 a.k.a. Frodo or above) with -System-Settings-Service "Allow programs on other systems to control XBMC" enabled. +You only need one or more Kodi (12 a.k.a. Frodo or above) with +System-Settings-Service "Allow programs on other systems to control Kodi" enabled. ## Configuration -### plugin.conf +### plugin.conf (deprecated) / plugin.yaml ``` -[xbmc] - class_name = XBMC - class_path = plugins.xbmc +# /etc/plugin.conf +[kodi] + class_name = Kodi + class_path = plugins.kodi + instance = living + host = xxx.xxx.xxx.xxx + port = 9090 ``` -### items.conf +```yaml +# /etc/plugin.yaml +kodi: + class_name: Kodi + class_path: plugins.kodi + instance: mediacenter + host: xxx.xxx.xxx.xxx + port: 9090 +``` + +#### host +This attribute is mandatory. You have to provide the IP address of the Kodi system. + +#### port +You could specify a port to connect to. By default port 9090 is used. + +### items.conf (deprecated) / items.yaml ``` +# /items/items.conf [living] - [[xbmc]] + [[kodi]] type = str - xbmc_host = xbmc.home - # xbmc_port = 9090 - xbmc_listen = state + kodi_item@mediacenter = state [[[title]]] type = str - xbmc_listen = title + kodi_item@mediacenter = title [[[media]]] type = str - xbmc_listen = media + kodi_item@mediacenter = media [[[volume]]] type = num - xbmc_listen = volume - xbmc_send = volume + kodi_item@mediacenter = volume [[[mute]]] type = bool - xbmc_listen = mute - xbmc_send = mute + kodi_item@mediacenter = mute ``` -#### xbmc_host -This attribute is mandatory. You have to provide the IP address or host name of the XBMC system. - -#### xbmc_port -You could specify a port to connect to. By default port 9090 is used. +```yaml +# /items/items.yaml +living: + kodi: + type: str + kodi_item@mediacenter: state + volume: + type: num + kodi_item@mediacenter: volume + mute: + type: bool + kodi_item@mediacenter: mute + title: + type: str + kodi_item@mediacenter: title + media: + type: str + kodi_item@mediacenter: media + favorites: + type: dict + kodi_item@mediacenter: favorites +``` -#### xbmc_listen -You could assign the following values to `xbmc_listen`: +#### kodi_item +You could assign the following values to `kodi_item`: * `volume` a numeric value (0 -100) * `mute` a bool flag * `title` a string with the name of the movie, song or picture * `media` a string with the current media type (Video, Audio, Picture) * `state` current state as string (Menu, Playing, Pause) + * `favorites` the favorites of your Kodi system (must be of type dict) -#### xbmc_send -The following `xbmc_send` attributes could be defined to send changes to the system: - - * `volume` a numeric value (0 -100) - * `mute` a bool flag - +The `volume` and `mute` items influence Kodi when their value changes. ### logic.conf @@ -68,12 +98,8 @@ Nothing so far ## Functions ========= -This plugin provides the function to send notification messages to xbmc. -``notify_all(title, message, picture)`` to send the notification to all xbmc systems and extends the item with the notify method. -The picture attribute is optional. +This plugin provides the function to send notification messages to Kodi. ```python -sh.xbmc.notify_all('Phone', 'Sister in law calling', 'http://smarthome.local/img/phone.png') -# or for a dedicated xbmc -sh.living.xbmc.notify('Door', 'Ding Dong') +sh.living.kodi.notify('Door', 'Ding Dong') ``` diff --git a/kodi/__init__.py b/kodi/__init__.py index aef4e330f..af34a8d6e 100755 --- a/kodi/__init__.py +++ b/kodi/__init__.py @@ -39,7 +39,7 @@ class Kodi(SmartPlugin, Client): PLUGIN_VERSION='1.3c.0' ALLOW_MULTIINSTANCE = True - _get_items = ['volume', 'mute', 'title', 'media', 'state'] + _get_items = ['volume', 'mute', 'title', 'media', 'state', 'favorites'] _set_items = {'volume': dict(method='Application.SetVolume', params=dict(volume='ITEM_VALUE')), 'mute' : dict(method='Application.SetMute', params = dict(mute='ITEM_VALUE')), @@ -53,20 +53,7 @@ class Kodi(SmartPlugin, Client): def __init__(self, sh, *args, **kwargs): ''' - Initalizes the plugin. The parameters describe for this method are pulled from the entry in plugin.conf. - - :param sh: **Deprecated**: The instance of the smarthome object. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! - :param *args: **Deprecated**: Old way of passing parameter values. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! - :param **kwargs:**Deprecated**: Old way of passing parameter values. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! - - If you need the sh object at all, use the method self.get_sh() to get it. There should be almost no need for - a reference to the sh object any more. - - The parameters *args and **kwargs are the old way of passing parameters. They are deprecated. They are implemented - to support oder plugins. Plugins for SmartHomeNG v1.4 and beyond should use the new way of getting parameter values: - use the SmartPlugin method `get_parameter_value(parameter_name)` instead. Anywhere within the Plugin you can get - the configured (and checked) value for a parameter by calling `self.get_parameter_value(parameter_name)`. It - returns the value in the datatype that is defined in the metadata. + Initalizes the plugin. ''' # init logger self.logger = logging.getLogger(__name__) @@ -110,22 +97,21 @@ def handle_connect(self): elem(result['muted'], caller='Kodi') for elem in self.registered_items['volume']: elem(result['volume'], caller='Kodi') - + # get the list of favorites + result = self.send_kodi_rpc(method='Favourites.GetFavourites', + params=dict(properties=['window', 'path', 'thumbnail', 'windowparameter']))['result'] + item_dict = {elem['title']: elem for elem in result['favourites']} + for elem in self.registered_items['favorites']: + elem(item_dict, caller='Kodi') # parse active player (if present) self._get_player_info() def parse_item(self, item): ''' - Default plugin parse_item method. Is called when the plugin is initialized. - The plugin can, corresponding to its attribute keywords, decide what to do with - the item in future, like adding it to an internal array for future reference + Method for parsing Kodi items. + If the item carries the kodi_item field, this item is registered to the plugin. :param item: The item to process. - :return: If the plugin needs to be informed of an items change you should return a call back function - like the function update_item down below. An example when this is needed is the knx plugin - where parse_item returns the update_item function when the attribute knx_send is found. - This means that when the items value is about to be updated, the call back function is called - with the item, caller, source and dest as arguments and in case of the knx plugin the value - can be sent to the knx with a knx write function within the knx plugin. + :return: The item update method to be triggered if the kodi_item is in the set item dict. ''' if self.has_iattr(item.conf, 'kodi_item'): kodi_item = self.get_iattr_value(item.conf, 'kodi_item') @@ -141,10 +127,7 @@ def parse_logic(self, logic): ''' Default plugin parse_logic method ''' - if 'xxx' in logic.conf: - # self.function(logic['name']) - pass - + pass def update_item(self, item, caller=None, source=None, dest=None): ''' @@ -189,6 +172,17 @@ def notify(self, title, message, image=None, display_time=10000): self.send_kodi_rpc(method='GUI.ShowNotification', params=params) def send_kodi_rpc(self, method, params=None, message_id=None, wait=True): + ''' + Send a JSON RPC to Kodi. + + The JSON string is extracted from the supplied method and the given parameters. + :param method: the Kodi method to be triggered + :param params: parameters dictionary + :param message_id: the message ID to be used. If none, use the internal counter + :param wait: whether to wait for the reply from Kodi or send off the RPC asynchronously + If wait is True, this method returns a dictionary parsed from the JSON + response from Kodi + ''' self.cmd_lock.acquire() self.reply = None if message_id is None: @@ -213,6 +207,10 @@ def send_kodi_rpc(self, method, params=None, message_id=None, wait=True): return reply def found_balance(self, data): + ''' + This method is called whenever data is received from the connection to + Kodi. + ''' event = json.loads(data.decode()) self.logger.debug('Kodi receiving: {0}'.format(event)) if 'id' in event: @@ -247,6 +245,10 @@ def found_balance(self, data): elem(event['params']['data']['volume'], caller='Kodi') def _get_player_info(self): + ''' + Extract information from Kodi reagrding the active player and save it + to the respective items + ''' result = self.send_kodi_rpc(method='Player.GetActivePlayers')['result'] if len(result) == 0: self.logger.info('Kodi: no active player found.') @@ -259,7 +261,6 @@ def _get_player_info(self): return playerid = result[0]['playerid'] typ = result[0]['type'] -# self._items['state']('Playing', 'Kodi') for elem in self.registered_items['state']: elem('Playing', caller='Kodi') if typ == 'video': @@ -270,14 +271,9 @@ def _get_player_info(self): typ = result['item']['type'] if not title and 'label' in result['item']: title = result['item']['label'] -# if 'media' in self._items: -# typ = result['item']['type'] -# self._items['media'](typ.capitalize(), 'Kodi') for elem in self.registered_items['media']: elem(typ.capitalize(), caller='Kodi') elif typ == 'audio': -# if 'media' in self._items: -# self._items['media'](typ.capitalize(), 'Kodi') for elem in self.registered_items['media']: elem('Audio', caller='Kodi') result = self.send_kodi_rpc(method='Player.GetItem', @@ -289,15 +285,11 @@ def _get_player_info(self): artist = result['item']['artist'][0] title = artist + ' - ' + result['item']['title'] elif typ == 'picture': -# if 'media' in self._items: -# self._items['media'](typ.capitalize(), 'Kodi') for elem in self.registered_items['media']: elem('Picture', caller='Kodi') title = '' else: self.logger.warning('Kodi: Unknown type: {0}'.format(typ)) return -# if 'title' in self._items: -# self._items['title'](title, 'Kodi') for elem in self.registered_items['title']: elem(title, caller='Kodi') From 1696aa55e3b1b6bc5121f6f5f7893251ed3482c2 Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Thu, 9 Nov 2017 08:29:40 +0100 Subject: [PATCH 016/705] added documentation regarding correct port and added a check to see if JSON API is available --- kodi/README.md | 2 +- kodi/__init__.py | 102 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 72 insertions(+), 32 deletions(-) diff --git a/kodi/README.md b/kodi/README.md index f1b82a62d..0acf6d7f8 100644 --- a/kodi/README.md +++ b/kodi/README.md @@ -33,7 +33,7 @@ kodi: This attribute is mandatory. You have to provide the IP address of the Kodi system. #### port -You could specify a port to connect to. By default port 9090 is used. +The port to connect to. This must be Kodi's TCP port not its HTTP port (see [Kodi JSON-RPC API(http://kodi.wiki/?title=JSON-RPC_API)]. Ddefault is 9090. ### items.conf (deprecated) / items.yaml diff --git a/kodi/__init__.py b/kodi/__init__.py index af34a8d6e..4ffc63e46 100755 --- a/kodi/__init__.py +++ b/kodi/__init__.py @@ -41,15 +41,17 @@ class Kodi(SmartPlugin, Client): _get_items = ['volume', 'mute', 'title', 'media', 'state', 'favorites'] - _set_items = {'volume': dict(method='Application.SetVolume', params=dict(volume='ITEM_VALUE')), - 'mute' : dict(method='Application.SetMute', params = dict(mute='ITEM_VALUE')), - 'left' : dict(method='Input.Left', params=None), - 'right' : dict(method='Input.Right', params=None), - 'up' : dict(method='Input.Up', params=None), - 'down' : dict(method='Input.Down', params=None), - 'home' : dict(method='Input.Home', params=None), - 'back' : dict(method='Input.Back', params=None), - 'select': dict(method='Input.Select', params=None)} + _set_items = {'volume' : dict(method='Application.SetVolume', params=dict(volume='ITEM_VALUE')), + 'mute' : dict(method='Application.SetMute', params = dict(mute='ITEM_VALUE')), + 'left' : dict(method='Input.Left', params=None), + 'right' : dict(method='Input.Right', params=None), + 'up' : dict(method='Input.Up', params=None), + 'down' : dict(method='Input.Down', params=None), + 'home' : dict(method='Input.Home', params=None), + 'back' : dict(method='Input.Back', params=None), + 'select' : dict(method='Input.Select', params=None), + 'play_pause': dict(method='Player.PlayPause', params=None), + 'stop' : dict(method='Player.Stop', params=None)} def __init__(self, sh, *args, **kwargs): ''' @@ -88,23 +90,34 @@ def stop(self): def handle_connect(self): ''' This method is called on a succesful connect to Kodi - On a connect initialize all items with values extracted from Kodi + On a connect first check if the JSON-RPC API is available. + If this is the case initialize all items with values extracted from Kodi ''' - # get volume and mute state - result = self.send_kodi_rpc(method='Application.GetProperties', - params=dict(properties=['volume', 'muted']))['result'] - for elem in self.registered_items['mute']: - elem(result['muted'], caller='Kodi') - for elem in self.registered_items['volume']: - elem(result['volume'], caller='Kodi') - # get the list of favorites - result = self.send_kodi_rpc(method='Favourites.GetFavourites', - params=dict(properties=['window', 'path', 'thumbnail', 'windowparameter']))['result'] - item_dict = {elem['title']: elem for elem in result['favourites']} - for elem in self.registered_items['favorites']: - elem(item_dict, caller='Kodi') - # parse active player (if present) - self._get_player_info() + # check if API is available + result = self.send_kodi_rpc(method='JSONRPC.Ping') + if result is None or result['result'] != 'pong': + self.logger.error('Kodi JSON-RPC API not available. Did you connect to the TCP port (default: 9090)?') + self.stop() + else: + # API available -> init items + # + # get volume and mute state + result = self.send_kodi_rpc(method='Application.GetProperties', + params=dict(properties=['volume', 'muted']))['result'] + for elem in self.registered_items['mute']: + elem(result['muted'], caller='Kodi') + for elem in self.registered_items['volume']: + elem(result['volume'], caller='Kodi') + # get the list of favorites + result = self.send_kodi_rpc(method='Favourites.GetFavourites', + params=dict(properties=['window', 'path', 'thumbnail', 'windowparameter']))['result'] + item_dict = dict() + if result['favourites'] is not None: + item_dict = {elem['title']: elem for elem in result['favourites']} + for elem in self.registered_items['favorites']: + elem(item_dict, caller='Kodi') + # parse active player (if present) + self._get_player_info() def parse_item(self, item): ''' @@ -115,7 +128,10 @@ def parse_item(self, item): ''' if self.has_iattr(item.conf, 'kodi_item'): kodi_item = self.get_iattr_value(item.conf, 'kodi_item') - self.logger.debug('Plugin \'{}\': parse item: {}'.format(self.get_shortname(), item)) + self.logger.debug('Plugin \'%s\', instance \'%s\': registering item: %s', + self.get_shortname(), + self.get_instance_name(), + item) if kodi_item in self.registered_items: self.registered_items[kodi_item].append(item) else: @@ -140,9 +156,13 @@ def update_item(self, item, caller=None, source=None, dest=None): ''' if item(): if caller != 'Kodi' and self.has_iattr(item.conf, 'kodi_item'): - # update item was triggered from sometthing else then this plugin -> send to Kodi + # update item was triggered from something else then this plugin -> send to Kodi kodi_item = self.get_iattr_value(item.conf, 'kodi_item') - if kodi_item in Kodi._set_items: + # handle play/pause and stop separately as we need to find the active player + if kodi_item in ['play_pause', 'stop']: + self.get_sh().trigger('kodi-%s' % kodi_item, self._send_player_command, 'Kodi', value=dict(kodi_item=kodi_item)) + # all other Items can be handled through a standard interface + elif kodi_item in Kodi._set_items: self.logger.debug('Plugin \'{}\': update_item ws called with item \'{}\' from caller \'{}\', source \'{}\' and dest \'{}\''.format(self.get_shortname(), item, caller, source, dest)) method = self._set_items[kodi_item]['method'] params = self._set_items[kodi_item]['params'] @@ -153,7 +173,7 @@ def update_item(self, item, caller=None, source=None, dest=None): for key, value in params.items(): if value == 'ITEM_VALUE': params[key] = item() - self._send(method, params, wait=False) + self.send_kodi_rpc(method, params, wait=False) else: self.logger.info('kodi_item \'%s\' not in send_keys, skipping!', kodi_item) @@ -237,16 +257,36 @@ def found_balance(self, data): elem('Screensaver', caller='Kodi') if event['method'] in ['Player.OnPlay']: # use a different thread for event handling - self.get_sh().trigger('kodi-event', self._get_player_info, 'Kodi') + self.get_sh().trigger('kodi-player-start', self._get_player_info, 'Kodi') elif event['method'] in ['Application.OnVolumeChanged']: for elem in self.registered_items['mute']: elem(event['params']['data']['muted'], caller='Kodi') for elem in self.registered_items['volume']: elem(event['params']['data']['volume'], caller='Kodi') + + def _send_player_command(self, kodi_item): + ''' + This method should only be called from the update item method in + a new thread in order to handle Play/Pause and Stop commands to + the active Kodi players + ''' + # get the currently active players + result = self.send_kodi_rpc(method='Player.GetActivePlayers') + result = result['result'] + if len(result) == 0: + self.logger.warning('Kodi: no active player found, skipping request!') + else: + if len(result) > 1: + self.logger.info('Kodi: there is more than one active player. Sending request to each player!') + for player in result: + player_id = player['playerid'] + self.send_kodi_rpc(method=self._set_items[kodi_item]['method'], + params=dict(playerid=player_id), + wait=False) def _get_player_info(self): ''' - Extract information from Kodi reagrding the active player and save it + Extract information from Kodi regarding the active player and save it to the respective items ''' result = self.send_kodi_rpc(method='Player.GetActivePlayers')['result'] From 52b255d74eb7f12a35ec3e69aa8c7e6e7cafa680 Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Thu, 9 Nov 2017 08:36:23 +0100 Subject: [PATCH 017/705] typo fix in docs + more docs on input commands --- kodi/README.md | 54 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/kodi/README.md b/kodi/README.md index 0acf6d7f8..a52483b91 100644 --- a/kodi/README.md +++ b/kodi/README.md @@ -14,7 +14,7 @@ System-Settings-Service "Allow programs on other systems to control Kodi" enable [kodi] class_name = Kodi class_path = plugins.kodi - instance = living + instance = mediacenter host = xxx.xxx.xxx.xxx port = 9090 ``` @@ -33,7 +33,7 @@ kodi: This attribute is mandatory. You have to provide the IP address of the Kodi system. #### port -The port to connect to. This must be Kodi's TCP port not its HTTP port (see [Kodi JSON-RPC API(http://kodi.wiki/?title=JSON-RPC_API)]. Ddefault is 9090. +The port to connect to. This must be Kodi's TCP port not its HTTP port (see [Kodi JSON-RPC API](http://kodi.wiki/?title=JSON-RPC_API)]. Default is 9090. ### items.conf (deprecated) / items.yaml @@ -55,6 +55,7 @@ The port to connect to. This must be Kodi's TCP port not its HTTP port (see [Kod [[[mute]]] type = bool kodi_item@mediacenter = mute +... ``` ```yaml @@ -78,6 +79,43 @@ living: favorites: type: dict kodi_item@mediacenter: favorites + # input commands + left: + type: bool + enforce_updates: true + kodi_item@mediacenter: left + right: + type: bool + enforce_updates: true + kodi_item@mediacenter: right + up: + type: bool + enforce_updates: true + kodi_item@mediacenter: up + down: + type: bool + enforce_updates: true + kodi_item@mediacenter: down + home: + type: bool + enforce_updates: true + kodi_item@mediacenter: home + back: + type: bool + enforce_updates: true + kodi_item@mediacenter: back + select: + type: bool + enforce_updates: true + kodi_item@mediacenter: select + play_pause: + type: bool + enforce_updates: true + kodi_item@mediacenter: play_pause + stop: + type: bool + enforce_updates: true + kodi_item@mediacenter: stop ``` #### kodi_item @@ -89,15 +127,25 @@ You could assign the following values to `kodi_item`: * `media` a string with the current media type (Video, Audio, Picture) * `state` current state as string (Menu, Playing, Pause) * `favorites` the favorites of your Kodi system (must be of type dict) + * `play_pause` request Kodi to pause or restart the current players (should be of type bool and `enforce_updates: true`) + * `stop` request Kodi to stop all players (should be of type bool and `enforce_updates: true`) + * `left` send a left request to Kodi, same as pressing the left arrow on the keyboard (should be of type bool and `enforce_updates: true`) + * `right` send a right request to Kodi, same as pressing the right arrow on the keyboard (should be of type bool and `enforce_updates: true`) + * `up` send an up request to Kodi, same as pressing the up arrow on the keyboard (should be of type bool and `enforce_updates: true`) + * `down` send a down request to Kodi, same as pressing the down arrow on the keyboard (should be of type bool and `enforce_updates: true`) + * `home` go to the home menu (should be of type bool and `enforce_updates: true`) + * `back` go to the previous menu (should be of type bool and `enforce_updates: true`) + * `select` select the currently highlightes item in Kodi (should be of type bool and `enforce_updates: true`) The `volume` and `mute` items influence Kodi when their value changes. +All items that are marked as "should be of type bool" are essentially input commands which are usually send to Kodi over an attached keyboard. The keyboard behavior can be simulated through boolean items with `enforce_updates: true`. + ### logic.conf Nothing so far ## Functions -========= This plugin provides the function to send notification messages to Kodi. ```python From 6f30f72d7d94926765650a178812b3d00f9d3b3f Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Thu, 9 Nov 2017 08:39:47 +0100 Subject: [PATCH 018/705] typo fix in doc --- kodi/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kodi/README.md b/kodi/README.md index a52483b91..6ca0e486b 100644 --- a/kodi/README.md +++ b/kodi/README.md @@ -33,7 +33,7 @@ kodi: This attribute is mandatory. You have to provide the IP address of the Kodi system. #### port -The port to connect to. This must be Kodi's TCP port not its HTTP port (see [Kodi JSON-RPC API](http://kodi.wiki/?title=JSON-RPC_API)]. Default is 9090. +The port to connect to. This must be Kodi's TCP port not its HTTP port (see [Kodi JSON-RPC API](http://kodi.wiki/?title=JSON-RPC_API)). Default is 9090. ### items.conf (deprecated) / items.yaml @@ -119,7 +119,7 @@ living: ``` #### kodi_item -You could assign the following values to `kodi_item`: +You can assign the following values to `kodi_item`: * `volume` a numeric value (0 -100) * `mute` a bool flag @@ -135,7 +135,7 @@ You could assign the following values to `kodi_item`: * `down` send a down request to Kodi, same as pressing the down arrow on the keyboard (should be of type bool and `enforce_updates: true`) * `home` go to the home menu (should be of type bool and `enforce_updates: true`) * `back` go to the previous menu (should be of type bool and `enforce_updates: true`) - * `select` select the currently highlightes item in Kodi (should be of type bool and `enforce_updates: true`) + * `select` select the currently highlighted item in Kodi (should be of type bool and `enforce_updates: true`) The `volume` and `mute` items influence Kodi when their value changes. All items that are marked as "should be of type bool" are essentially input commands which are usually send to Kodi over an attached keyboard. The keyboard behavior can be simulated through boolean items with `enforce_updates: true`. From 580769d03e5cb04af4b45804318e487022a0e919 Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Thu, 9 Nov 2017 16:03:25 +0100 Subject: [PATCH 019/705] using input item now instead of multiple bool items --- kodi/README.md | 108 +++++++++++++++++++++-------------------------- kodi/__init__.py | 88 ++++++++++++++++++++++++++------------ 2 files changed, 108 insertions(+), 88 deletions(-) diff --git a/kodi/README.md b/kodi/README.md index 6ca0e486b..6914b1a66 100644 --- a/kodi/README.md +++ b/kodi/README.md @@ -36,7 +36,7 @@ This attribute is mandatory. You have to provide the IP address of the Kodi syst The port to connect to. This must be Kodi's TCP port not its HTTP port (see [Kodi JSON-RPC API](http://kodi.wiki/?title=JSON-RPC_API)). Default is 9090. ### items.conf (deprecated) / items.yaml - +You can register an item to the plugin by adding a field named `kodi_item` augmented with the respective plugin instance you want to register the item to: ``` # /items/items.conf [living] @@ -62,8 +62,6 @@ The port to connect to. This must be Kodi's TCP port not its HTTP port (see [Kod # /items/items.yaml living: kodi: - type: str - kodi_item@mediacenter: state volume: type: num kodi_item@mediacenter: volume @@ -73,73 +71,63 @@ living: title: type: str kodi_item@mediacenter: title + state: + type: str + kodi_item@mediacenter: state media: type: str kodi_item@mediacenter: media favorites: type: dict kodi_item@mediacenter: favorites - # input commands - left: - type: bool - enforce_updates: true - kodi_item@mediacenter: left - right: - type: bool - enforce_updates: true - kodi_item@mediacenter: right - up: - type: bool - enforce_updates: true - kodi_item@mediacenter: up - down: - type: bool - enforce_updates: true - kodi_item@mediacenter: down - home: - type: bool - enforce_updates: true - kodi_item@mediacenter: home - back: - type: bool - enforce_updates: true - kodi_item@mediacenter: back - select: - type: bool - enforce_updates: true - kodi_item@mediacenter: select - play_pause: - type: bool - enforce_updates: true - kodi_item@mediacenter: play_pause - stop: - type: bool + input: + type: str enforce_updates: true - kodi_item@mediacenter: stop + kodi_item@mediacenter: input ``` #### kodi_item -You can assign the following values to `kodi_item`: - - * `volume` a numeric value (0 -100) - * `mute` a bool flag - * `title` a string with the name of the movie, song or picture - * `media` a string with the current media type (Video, Audio, Picture) - * `state` current state as string (Menu, Playing, Pause) - * `favorites` the favorites of your Kodi system (must be of type dict) - * `play_pause` request Kodi to pause or restart the current players (should be of type bool and `enforce_updates: true`) - * `stop` request Kodi to stop all players (should be of type bool and `enforce_updates: true`) - * `left` send a left request to Kodi, same as pressing the left arrow on the keyboard (should be of type bool and `enforce_updates: true`) - * `right` send a right request to Kodi, same as pressing the right arrow on the keyboard (should be of type bool and `enforce_updates: true`) - * `up` send an up request to Kodi, same as pressing the up arrow on the keyboard (should be of type bool and `enforce_updates: true`) - * `down` send a down request to Kodi, same as pressing the down arrow on the keyboard (should be of type bool and `enforce_updates: true`) - * `home` go to the home menu (should be of type bool and `enforce_updates: true`) - * `back` go to the previous menu (should be of type bool and `enforce_updates: true`) - * `select` select the currently highlighted item in Kodi (should be of type bool and `enforce_updates: true`) - -The `volume` and `mute` items influence Kodi when their value changes. -All items that are marked as "should be of type bool" are essentially input commands which are usually send to Kodi over an attached keyboard. The keyboard behavior can be simulated through boolean items with `enforce_updates: true`. - +If an item carries a `kodi_item` it should be of a specific type. Listed below are the types depending on the value that is assigned to `kodi_item`: + +##### volume +Item type `num`. Changing the item controls the volume of Kodi. The allowed range is 0 to 100. + +##### mute +Item type `bool`. Changing the item controls muting the Kodi player. + +##### title +Item type `str`. This item displays information about the currently playing element's title in Kodi. Changing its value has no effect as it is only set by the plugin and not read on updates. + +##### media +Item type `str`. This item displays information about the currently playing element's media type in Kodi. Changing its value has no effect as it is only set by the plugin and not read on updates. + +##### state +Item type `str`. This item displays information about the current state of Kodi (Playing, Stopped, Screensaver,...). Changing its value has no effect as it is only set by the plugin and not read on updates. + +##### favorites +Item type `dict`. The item stores information about favorites defined in Kodi in a dictionary. Changing its value has no effect as it is only set by the plugin and not read on updates. + +##### input +Item type `str`. This item gives complete control over sending inputs to Kodi and can be seen as simulating keyboard events and shotcuts. +If the item is set to an allowed Kodi input action, the respective action is send to Kodi. +The item should be set to enforce updates in order to allow for sending consecutive commands of the same action. +There is a huge amount of actions possible. Listed below are a number of oft-used input actions this item may be set to. For all allowed actions see the plugin's source code (most of them are pretty self-explanatory). + + * `play` start the current Kodi player + * `pause` pause the current Kodi player + * `playpause` toggle the current Kodi player (if paused play, if playing pause) + * `stop` stop the current Kodi player + * `osd` show the On Screen Display for the current Kodi player + * `left` highlight the element left of the current one (same as hitting the left arrow key on a keyboard) + * `right` highlight the element right of the current one (same as hitting the right arrow key on a keyboard) + * `up` highlight the element above the current one (same as hitting the up arrow key on a keyboard) + * `down` highlight the element above the current one (same as hitting the down arrow key on a keyboard) + * `select` select the currently highlighted element + * `contextmenu` show the context menu for the currently highlighted element + * `home` go to the home menu + * `back` go to the previous menu + * `volumeup` increase the volume + * `volumedown` decrease the volume ### logic.conf diff --git a/kodi/__init__.py b/kodi/__init__.py index 4ffc63e46..6402795d0 100755 --- a/kodi/__init__.py +++ b/kodi/__init__.py @@ -38,20 +38,50 @@ class Kodi(SmartPlugin, Client): PLUGIN_VERSION='1.3c.0' ALLOW_MULTIINSTANCE = True + + # list of all possible input actions for Kodi + _possible_input_actions = [ + 'left','right','up','down','pageup','pagedown','select','highlight', + 'parentdir','parentfolder','back','menu','previousmenu','info', + 'pause','stop','skipnext','skipprevious','fullscreen','aspectratio', + 'stepforward','stepback','bigstepforward','bigstepback', + 'chapterorbigstepforward','chapterorbigstepback','osd','showsubtitles', + 'nextsubtitle','cyclesubtitle','playerdebug','codecinfo','playerprocessinfo', + 'nextpicture','previouspicture','zoomout','zoomin','playlist','queue', + 'zoomnormal','zoomlevel1','zoomlevel2','zoomlevel3','zoomlevel4', + 'zoomlevel5','zoomlevel6','zoomlevel7','zoomlevel8','zoomlevel9', + 'nextcalibration','resetcalibration','analogmove','analogmovex', + 'analogmovey','rotate','rotateccw','close','subtitledelayminus', + 'subtitledelay','subtitledelayplus','audiodelayminus','audiodelay', + 'audiodelayplus','subtitleshiftup','subtitleshiftdown','subtitlealign', + 'audionextlanguage','verticalshiftup','verticalshiftdown','nextresolution', + 'audiotoggledigital','number0','number1','number2','number3','number4', + 'number5','number6','number7','number8','number9','smallstepback', + 'fastforward','rewind','play','playpause','switchplayer','delete','copy', + 'move','screenshot','rename','togglewatched','scanitem','reloadkeymaps', + 'volumeup','volumedown','mute','backspace','scrollup','scrolldown', + 'analogfastforward','analogrewind','moveitemup','moveitemdown','contextmenu', + 'shift','symbols','cursorleft','cursorright','showtime','analogseekforward', + 'analogseekback','showpreset','nextpreset','previouspreset','lockpreset','randompreset', + 'increasevisrating','decreasevisrating','showvideomenu','enter','increaserating', + 'decreaserating','setrating','togglefullscreen','nextscene','previousscene','nextletter', + 'prevletter','jumpsms2','jumpsms3','jumpsms4','jumpsms5','jumpsms6','jumpsms7','jumpsms8', + 'jumpsms9','filter','filterclear','filtersms2','filtersms3','filtersms4','filtersms5', + 'filtersms6','filtersms7','filtersms8','filtersms9','firstpage','lastpage','guiprofile', + 'red','green','yellow','blue','increasepar','decreasepar','volampup','volampdown', + 'volumeamplification','createbookmark','createepisodebookmark','settingsreset', + 'settingslevelchange','stereomode','nextstereomode','previousstereomode', + 'togglestereomode','stereomodetomono','channelup','channeldown','previouschannelgroup', + 'nextchannelgroup','playpvr','playpvrtv','playpvrradio','record','togglecommskip', + 'showtimerrule','leftclick','rightclick','middleclick','doubleclick','longclick', + 'wheelup','wheeldown','mousedrag','mousemove','tap','longpress','pangesture', + 'zoomgesture','rotategesture','swipeleft','swiperight','swipeup','swipedown','error','noop'] _get_items = ['volume', 'mute', 'title', 'media', 'state', 'favorites'] - _set_items = {'volume' : dict(method='Application.SetVolume', params=dict(volume='ITEM_VALUE')), - 'mute' : dict(method='Application.SetMute', params = dict(mute='ITEM_VALUE')), - 'left' : dict(method='Input.Left', params=None), - 'right' : dict(method='Input.Right', params=None), - 'up' : dict(method='Input.Up', params=None), - 'down' : dict(method='Input.Down', params=None), - 'home' : dict(method='Input.Home', params=None), - 'back' : dict(method='Input.Back', params=None), - 'select' : dict(method='Input.Select', params=None), - 'play_pause': dict(method='Player.PlayPause', params=None), - 'stop' : dict(method='Player.Stop', params=None)} + _set_items = {'volume': dict(method='Application.SetVolume', params=dict(volume='ITEM_VALUE')), + 'mute' : dict(method='Application.SetMute', params = dict(mute='ITEM_VALUE')), + 'input' : dict(method='Input.ExecuteAction', params=dict(action='ITEM_VALUE'))} def __init__(self, sh, *args, **kwargs): ''' @@ -154,26 +184,28 @@ def update_item(self, item, caller=None, source=None, dest=None): :param source: if given it represents the source :param dest: if given it represents the dest ''' - if item(): + item_value = item() + if item_value: if caller != 'Kodi' and self.has_iattr(item.conf, 'kodi_item'): # update item was triggered from something else then this plugin -> send to Kodi kodi_item = self.get_iattr_value(item.conf, 'kodi_item') - # handle play/pause and stop separately as we need to find the active player - if kodi_item in ['play_pause', 'stop']: - self.get_sh().trigger('kodi-%s' % kodi_item, self._send_player_command, 'Kodi', value=dict(kodi_item=kodi_item)) - # all other Items can be handled through a standard interface - elif kodi_item in Kodi._set_items: - self.logger.debug('Plugin \'{}\': update_item ws called with item \'{}\' from caller \'{}\', source \'{}\' and dest \'{}\''.format(self.get_shortname(), item, caller, source, dest)) - method = self._set_items[kodi_item]['method'] - params = self._set_items[kodi_item]['params'] - if params is not None: - # copy so we don't interfer with the class variable - params = params.copy() - # replace the wild card ITEM_VALUE with the item's value - for key, value in params.items(): - if value == 'ITEM_VALUE': - params[key] = item() - self.send_kodi_rpc(method, params, wait=False) + + if kodi_item in Kodi._set_items: + if kodi_item == 'input' and item() not in self._possible_input_actions: + self.logger.error('The action \'%s\' for the kodi_item \'input\' is not allowed, skipping!', item_value) + else: + self.logger.debug('Plugin \'%s\': update_item ws called with item \'%s\' from caller \'%s\', source \'%s\' and dest \'%s\'', + self.get_shortname(), item, caller, source, dest) + method = self._set_items[kodi_item]['method'] + params = self._set_items[kodi_item]['params'] + if params is not None: + # copy so we don't interfer with the class variable + params = params.copy() + # replace the wild card ITEM_VALUE with the item's value + for key, value in params.items(): + if value == 'ITEM_VALUE': + params[key] = item_value + self.send_kodi_rpc(method, params, wait=False) else: self.logger.info('kodi_item \'%s\' not in send_keys, skipping!', kodi_item) From ec66eedddbdbe862fd223e39d7d18f23dfe879d9 Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Thu, 9 Nov 2017 16:04:42 +0100 Subject: [PATCH 020/705] typo fix --- kodi/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kodi/README.md b/kodi/README.md index 6914b1a66..8d999e435 100644 --- a/kodi/README.md +++ b/kodi/README.md @@ -108,7 +108,7 @@ Item type `str`. This item displays information about the current state of Kodi Item type `dict`. The item stores information about favorites defined in Kodi in a dictionary. Changing its value has no effect as it is only set by the plugin and not read on updates. ##### input -Item type `str`. This item gives complete control over sending inputs to Kodi and can be seen as simulating keyboard events and shotcuts. +Item type `str`. This item gives complete control over sending inputs to Kodi and can be seen as simulating keyboard events and shortcuts. If the item is set to an allowed Kodi input action, the respective action is send to Kodi. The item should be set to enforce updates in order to allow for sending consecutive commands of the same action. There is a huge amount of actions possible. Listed below are a number of oft-used input actions this item may be set to. For all allowed actions see the plugin's source code (most of them are pretty self-explanatory). From b2a01c0c59cf8fabf53908252e7155bc73d5da71 Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Sun, 26 Nov 2017 08:09:51 +0100 Subject: [PATCH 021/705] added on/off item and switched to lib.network --- kodi/README.md | 6 ++ kodi/__init__.py | 193 +++++++++++++++++++++++++++++------------------ 2 files changed, 127 insertions(+), 72 deletions(-) diff --git a/kodi/README.md b/kodi/README.md index 8d999e435..631b552f2 100644 --- a/kodi/README.md +++ b/kodi/README.md @@ -84,11 +84,17 @@ living: type: str enforce_updates: true kodi_item@mediacenter: input + on_off: + type: bool + kodi_item@mediacenter: on_off ``` #### kodi_item If an item carries a `kodi_item` it should be of a specific type. Listed below are the types depending on the value that is assigned to `kodi_item`: +##### on_off +Item type `bool`. If the item is set to `False`, a shutdown request is send to Kodi. If the item is set to `True`, the plugin tries to establish a connection to Kodi (this does not include Wake on LAN or anything else). + ##### volume Item type `num`. Changing the item controls the volume of Kodi. The allowed range is 0 to 100. diff --git a/kodi/__init__.py b/kodi/__init__.py index 6402795d0..820ef9c8d 100755 --- a/kodi/__init__.py +++ b/kodi/__init__.py @@ -27,61 +27,63 @@ import json from lib.model.smartplugin import SmartPlugin -from lib.connection import Client +from lib.network import Tcp_client +import time -class Kodi(SmartPlugin, Client): +class Kodi(SmartPlugin): ''' Main class of the Plugin. Does all plugin specific stuff and provides the update functions for the items ''' - PLUGIN_VERSION='1.3c.0' + PLUGIN_VERSION = '1.3c.0' ALLOW_MULTIINSTANCE = True # list of all possible input actions for Kodi _possible_input_actions = [ - 'left','right','up','down','pageup','pagedown','select','highlight', - 'parentdir','parentfolder','back','menu','previousmenu','info', - 'pause','stop','skipnext','skipprevious','fullscreen','aspectratio', - 'stepforward','stepback','bigstepforward','bigstepback', - 'chapterorbigstepforward','chapterorbigstepback','osd','showsubtitles', - 'nextsubtitle','cyclesubtitle','playerdebug','codecinfo','playerprocessinfo', - 'nextpicture','previouspicture','zoomout','zoomin','playlist','queue', - 'zoomnormal','zoomlevel1','zoomlevel2','zoomlevel3','zoomlevel4', - 'zoomlevel5','zoomlevel6','zoomlevel7','zoomlevel8','zoomlevel9', - 'nextcalibration','resetcalibration','analogmove','analogmovex', - 'analogmovey','rotate','rotateccw','close','subtitledelayminus', - 'subtitledelay','subtitledelayplus','audiodelayminus','audiodelay', - 'audiodelayplus','subtitleshiftup','subtitleshiftdown','subtitlealign', - 'audionextlanguage','verticalshiftup','verticalshiftdown','nextresolution', - 'audiotoggledigital','number0','number1','number2','number3','number4', - 'number5','number6','number7','number8','number9','smallstepback', - 'fastforward','rewind','play','playpause','switchplayer','delete','copy', - 'move','screenshot','rename','togglewatched','scanitem','reloadkeymaps', - 'volumeup','volumedown','mute','backspace','scrollup','scrolldown', - 'analogfastforward','analogrewind','moveitemup','moveitemdown','contextmenu', - 'shift','symbols','cursorleft','cursorright','showtime','analogseekforward', - 'analogseekback','showpreset','nextpreset','previouspreset','lockpreset','randompreset', - 'increasevisrating','decreasevisrating','showvideomenu','enter','increaserating', - 'decreaserating','setrating','togglefullscreen','nextscene','previousscene','nextletter', - 'prevletter','jumpsms2','jumpsms3','jumpsms4','jumpsms5','jumpsms6','jumpsms7','jumpsms8', - 'jumpsms9','filter','filterclear','filtersms2','filtersms3','filtersms4','filtersms5', - 'filtersms6','filtersms7','filtersms8','filtersms9','firstpage','lastpage','guiprofile', - 'red','green','yellow','blue','increasepar','decreasepar','volampup','volampdown', - 'volumeamplification','createbookmark','createepisodebookmark','settingsreset', - 'settingslevelchange','stereomode','nextstereomode','previousstereomode', - 'togglestereomode','stereomodetomono','channelup','channeldown','previouschannelgroup', - 'nextchannelgroup','playpvr','playpvrtv','playpvrradio','record','togglecommskip', - 'showtimerrule','leftclick','rightclick','middleclick','doubleclick','longclick', - 'wheelup','wheeldown','mousedrag','mousemove','tap','longpress','pangesture', - 'zoomgesture','rotategesture','swipeleft','swiperight','swipeup','swipedown','error','noop'] + 'left', 'right', 'up', 'down', 'pageup', 'pagedown', 'select', 'highlight', + 'parentdir', 'parentfolder', 'back', 'menu', 'previousmenu', 'info', + 'pause', 'stop', 'skipnext', 'skipprevious', 'fullscreen', 'aspectratio', + 'stepforward', 'stepback', 'bigstepforward', 'bigstepback', + 'chapterorbigstepforward', 'chapterorbigstepback', 'osd', 'showsubtitles', + 'nextsubtitle', 'cyclesubtitle', 'playerdebug', 'codecinfo', 'playerprocessinfo', + 'nextpicture', 'previouspicture', 'zoomout', 'zoomin', 'playlist', 'queue', + 'zoomnormal', 'zoomlevel1', 'zoomlevel2', 'zoomlevel3', 'zoomlevel4', + 'zoomlevel5', 'zoomlevel6', 'zoomlevel7', 'zoomlevel8', 'zoomlevel9', + 'nextcalibration', 'resetcalibration', 'analogmove', 'analogmovex', + 'analogmovey', 'rotate', 'rotateccw', 'close', 'subtitledelayminus', + 'subtitledelay', 'subtitledelayplus', 'audiodelayminus', 'audiodelay', + 'audiodelayplus', 'subtitleshiftup', 'subtitleshiftdown', 'subtitlealign', + 'audionextlanguage', 'verticalshiftup', 'verticalshiftdown', 'nextresolution', + 'audiotoggledigital', 'number0', 'number1', 'number2', 'number3', 'number4', + 'number5', 'number6', 'number7', 'number8', 'number9', 'smallstepback', + 'fastforward', 'rewind', 'play', 'playpause', 'switchplayer', 'delete', 'copy', + 'move', 'screenshot', 'rename', 'togglewatched', 'scanitem', 'reloadkeymaps', + 'volumeup', 'volumedown', 'mute', 'backspace', 'scrollup', 'scrolldown', + 'analogfastforward', 'analogrewind', 'moveitemup', 'moveitemdown', 'contextmenu', + 'shift', 'symbols', 'cursorleft', 'cursorright', 'showtime', 'analogseekforward', + 'analogseekback', 'showpreset', 'nextpreset', 'previouspreset', 'lockpreset', 'randompreset', + 'increasevisrating', 'decreasevisrating', 'showvideomenu', 'enter', 'increaserating', + 'decreaserating', 'setrating', 'togglefullscreen', 'nextscene', 'previousscene', 'nextletter', + 'prevletter', 'jumpsms2', 'jumpsms3', 'jumpsms4', 'jumpsms5', 'jumpsms6', 'jumpsms7', 'jumpsms8', + 'jumpsms9', 'filter', 'filterclear', 'filtersms2', 'filtersms3', 'filtersms4', 'filtersms5', + 'filtersms6', 'filtersms7', 'filtersms8', 'filtersms9', 'firstpage', 'lastpage', 'guiprofile', + 'red', 'green', 'yellow', 'blue', 'increasepar', 'decreasepar', 'volampup', 'volampdown', + 'volumeamplification', 'createbookmark', 'createepisodebookmark', 'settingsreset', + 'settingslevelchange', 'stereomode', 'nextstereomode', 'previousstereomode', + 'togglestereomode', 'stereomodetomono', 'channelup', 'channeldown', 'previouschannelgroup', + 'nextchannelgroup', 'playpvr', 'playpvrtv', 'playpvrradio', 'record', 'togglecommskip', + 'showtimerrule', 'leftclick', 'rightclick', 'middleclick', 'doubleclick', 'longclick', + 'wheelup', 'wheeldown', 'mousedrag', 'mousemove', 'tap', 'longpress', 'pangesture', + 'zoomgesture', 'rotategesture', 'swipeleft', 'swiperight', 'swipeup', 'swipedown', 'error', 'noop'] _get_items = ['volume', 'mute', 'title', 'media', 'state', 'favorites'] _set_items = {'volume': dict(method='Application.SetVolume', params=dict(volume='ITEM_VALUE')), - 'mute' : dict(method='Application.SetMute', params = dict(mute='ITEM_VALUE')), - 'input' : dict(method='Input.ExecuteAction', params=dict(action='ITEM_VALUE'))} + 'mute' : dict(method='Application.SetMute', params=dict(mute='ITEM_VALUE')), + 'input' : dict(method='Input.ExecuteAction', params=dict(action='ITEM_VALUE')), + 'on_off': dict(method='System.Shutdown', params=None)} def __init__(self, sh, *args, **kwargs): ''' @@ -90,12 +92,18 @@ def __init__(self, sh, *args, **kwargs): # init logger self.logger = logging.getLogger(__name__) self.logger.info('Init Kodi Plugin') - Client.__init__(self, - self.get_parameter_value('host'), - self.get_parameter_value('port'), - monitor=True) - self.terminator = 0 - self.balance(b'{', b'}') + self.kodi_tcp_connection = Tcp_client(host=self.get_parameter_value('host'), + port=self.get_parameter_value('port'), + name='KodiTCPConnection', + autoreconnect=False, + connect_retries=5, + connect_cycle=5) + self.kodi_tcp_connection.set_callbacks(connected=None, + data_received=self.received_data, + disconnected=self.on_disconnect) + self.kodi_server_alive = False +# self.terminator = 0 +# self.balance(b'{', b'}') self.message_id = 1 self.response_id = None self.cmd_lock = threading.Lock() @@ -108,6 +116,7 @@ def run(self): Run method for the plugin ''' self.logger.debug('Plugin \'{}\': run method called'.format(self.get_shortname())) + self.connect_to_kodi() self.alive = True def stop(self): @@ -115,9 +124,11 @@ def stop(self): Stop method for the plugin ''' self.logger.debug('Plugin \'{}\': stop method called'.format(self.get_shortname())) + self.kodi_tcp_connection.close() + self.kodi_server_alive = False self.alive = False - def handle_connect(self): + def on_connect(self): ''' This method is called on a succesful connect to Kodi On a connect first check if the JSON-RPC API is available. @@ -148,6 +159,34 @@ def handle_connect(self): elem(item_dict, caller='Kodi') # parse active player (if present) self._get_player_info() + + def on_disconnect(self): + ''' function called when TCP connection to Kodi is disconnected ''' + self.logger.debug('Received disconnect from Kodi server') + self.kodi_server_alive = False + for elem in self.registered_items['on_off']: + elem(self.kodi_server_alive, caller='Kodi') + + def connect_to_kodi(self): + ''' + try to establish a new connection to Kodi + + While this method is called during the start-up phase of the plugin, + it can also be used to establish a connection to the Kodi server if the + plugin was initialized before the server went up. + ''' + self.kodi_tcp_connection.connect() + # we allow for 2 seconds to connect + time.sleep(2) + if not self.kodi_tcp_connection.connected(): + # no connection could be established, Kodi may be offline + self.logger.info('Could not establish a connection to Kodi Server') + self.kodi_server_alive = False + else: + self.kodi_server_alive = True + self.on_connect() + for elem in self.registered_items['on_off']: + elem(self.kodi_server_alive, caller='Kodi') def parse_item(self, item): ''' @@ -188,9 +227,15 @@ def update_item(self, item, caller=None, source=None, dest=None): if item_value: if caller != 'Kodi' and self.has_iattr(item.conf, 'kodi_item'): # update item was triggered from something else then this plugin -> send to Kodi - kodi_item = self.get_iattr_value(item.conf, 'kodi_item') + kodi_item = self.get_iattr_value(item.conf, 'kodi_item') - if kodi_item in Kodi._set_items: + if kodi_item == 'on_off' and item(): + # handle the on_off item as special case: + # if item is on, try to establish a connection to Kodi + self.connect_to_kodi() + # if item is off send shutdown command to Kodi. This is + # handled in the standard block below though + elif kodi_item in Kodi._set_items: if kodi_item == 'input' and item() not in self._possible_input_actions: self.logger.error('The action \'%s\' for the kodi_item \'input\' is not allowed, skipping!', item_value) else: @@ -218,7 +263,7 @@ def notify(self, title, message, image=None, display_time=10000): :param image: an optional image to be displayed alongside the message :param display_time: how long the message is displayed in milli seconds ''' - params = dict(title=title, message=message,displaytime=display_time) + params = dict(title=title, message=message, displaytime=display_time) if image is not None: params['image'] = image self.send_kodi_rpc(method='GUI.ShowNotification', params=params) @@ -235,35 +280,39 @@ def send_kodi_rpc(self, method, params=None, message_id=None, wait=True): If wait is True, this method returns a dictionary parsed from the JSON response from Kodi ''' - self.cmd_lock.acquire() - self.reply = None - if message_id is None: - self.message_id += 1 - message_id = self.message_id - if message_id > 99: - self.message_id = 0 - self.response_id = message_id - if params is not None: - data = {'jsonrpc': '2.0', 'id': message_id, 'method': method, 'params': params} + reply = None + if self.kodi_server_alive: + self.cmd_lock.acquire() + self.reply = None + if message_id is None: + self.message_id += 1 + message_id = self.message_id + if message_id > 99: + self.message_id = 0 + self.response_id = message_id + if params is not None: + data = {'jsonrpc': '2.0', 'id': message_id, 'method': method, 'params': params} + else: + data = {'jsonrpc': '2.0', 'id': message_id, 'method': method} + self.reply_lock.acquire() + self.logger.debug('Kodi sending: {0}'.format(json.dumps(data, separators=(',', ':')))) + self.kodi_tcp_connection.send((json.dumps(data, separators=(',', ':')) + '\r\n').encode()) + if wait: + self.reply_lock.wait(2) + self.reply_lock.release() + reply = self.reply + self.reply = None + self.cmd_lock.release() else: - data = {'jsonrpc': '2.0', 'id': message_id, 'method': method} - self.reply_lock.acquire() - self.logger.debug('Kodi sending: {0}'.format(json.dumps(data, separators=(',', ':')))) - self.send((json.dumps(data, separators=(',', ':')) + '\r\n').encode()) - if wait: - self.reply_lock.wait(2) - self.reply_lock.release() - reply = self.reply - self.reply = None - self.cmd_lock.release() + self.logger.debug('JSON-RPC command requested without an established connection to Kodi.') return reply - def found_balance(self, data): + def received_data(self, connection, data): ''' This method is called whenever data is received from the connection to Kodi. ''' - event = json.loads(data.decode()) + event = json.loads(data) self.logger.debug('Kodi receiving: {0}'.format(event)) if 'id' in event: if event['id'] == self.response_id: From 104e50bd593009befe7a7aceac37a355461ad69e Mon Sep 17 00:00:00 2001 From: Sebastian Sudholt Date: Sun, 3 Dec 2017 14:49:34 +0100 Subject: [PATCH 022/705] readded the old XBMC plugin --- xbmc/README.md | 79 +++++++++++++++++++ xbmc/__init__.py | 195 +++++++++++++++++++++++++++++++++++++++++++++++ xbmc/plugin.yaml | 26 +++++++ 3 files changed, 300 insertions(+) create mode 100644 xbmc/README.md create mode 100644 xbmc/__init__.py create mode 100644 xbmc/plugin.yaml diff --git a/xbmc/README.md b/xbmc/README.md new file mode 100644 index 000000000..b4f12d6c4 --- /dev/null +++ b/xbmc/README.md @@ -0,0 +1,79 @@ +# XBMC + +## Requirements + +You only need one or more XBMC (12 a.k.a. Frodo or above) with +System-Settings-Service "Allow programs on other systems to control XBMC" enabled. + +## Configuration + +### plugin.conf + +``` +[xbmc] + class_name = XBMC + class_path = plugins.xbmc +``` + +### items.conf + +``` +[living] + [[xbmc]] + type = str + xbmc_host = xbmc.home + # xbmc_port = 9090 + xbmc_listen = state + [[[title]]] + type = str + xbmc_listen = title + [[[media]]] + type = str + xbmc_listen = media + [[[volume]]] + type = num + xbmc_listen = volume + xbmc_send = volume + [[[mute]]] + type = bool + xbmc_listen = mute + xbmc_send = mute +``` + +#### xbmc_host +This attribute is mandatory. You have to provide the IP address or host name of the XBMC system. + +#### xbmc_port +You could specify a port to connect to. By default port 9090 is used. + +#### xbmc_listen +You could assign the following values to `xbmc_listen`: + + * `volume` a numeric value (0 -100) + * `mute` a bool flag + * `title` a string with the name of the movie, song or picture + * `media` a string with the current media type (Video, Audio, Picture) + * `state` current state as string (Menu, Playing, Pause) + +#### xbmc_send +The following `xbmc_send` attributes could be defined to send changes to the system: + + * `volume` a numeric value (0 -100) + * `mute` a bool flag + + +### logic.conf + +Nothing so far + +## Functions +========= +This plugin provides the function to send notification messages to xbmc. +``notify_all(title, message, picture)`` to send the notification to all xbmc systems and extends the item with the notify method. +The picture attribute is optional. + +```python +sh.xbmc.notify_all('Phone', 'Sister in law calling', 'http://smarthome.local/img/phone.png') +# or for a dedicated xbmc +sh.living.xbmc.notify('Door', 'Ding Dong') +``` diff --git a/xbmc/__init__.py b/xbmc/__init__.py new file mode 100644 index 000000000..43b25dcfd --- /dev/null +++ b/xbmc/__init__.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2013 Marcus Popp marcus@popp.mx +######################################################################### +# This file is part of SmartHomeNG. https://github.com/smarthomeNG// +# +# SmartHomeNG is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# SmartHomeNG is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with SmartHomeNG. If not, see . +######################################################################### + +import logging +import threading +import json +import lib.connection + +logger = logging.getLogger('') + + +class XBMC(): + + def __init__(self, smarthome): + self._sh = smarthome + self._boxes = [] + + def run(self): + self.alive = True + + def stop(self): + self.alive = False + for box in self._boxes: + box.handle_close() + + def notify_all(self, title, message, image=None): + for box in self._boxes: + box.notify(title, message, image) + + def parse_item(self, item): + if 'xbmc_host' in item.conf: + self._boxes.append(xbmc(self._sh, item)) + + +class xbmc(lib.connection.Client): + + _notification_time = 10000 + _listen_keys = ['volume', 'mute', 'title', 'media', 'state'] + _send_keys = {'volume': 'Application.SetVolume', 'mute': 'Application.SetMute', 'shutdown': 'System.Shutdown'} + + def __init__(self, smarthome, item): + if 'xbmc_port' in item.conf: + port = int(item.conf['xbmc_port']) + else: + port = 9090 + host = item.conf['xbmc_host'] + lib.connection.Client.__init__(self, host, port, monitor=True) + self.terminator = 0 + self.balance(b'{', b'}') + self._sh = smarthome + self._id = 1 + self._rid = None + self._cmd_lock = threading.Lock() + self._reply_lock = threading.Condition() + self._reply = None + self._items = {'state': item} + for child in self._sh.find_children(item, 'xbmc_listen'): + listen_to = child.conf['xbmc_listen'] + if listen_to in self._listen_keys: + self._items[listen_to] = child + for child in self._sh.find_children(item, 'xbmc_send'): + send_to = child.conf['xbmc_send'] + if send_to in self._send_keys: + child.add_method_trigger(self._send_value) + item.notify = self.notify + + def notify(self, title, message, image=None): + if image is None: + self._send('GUI.ShowNotification', {'title': title, 'message': message, 'displaytime': self._notification_time}) + else: + self._send('GUI.ShowNotification', {'title': title, 'message': message, 'image': image, 'displaytime': self._notification_time}) + + def _send_value(self, item, caller=None, source=None, dest=None): + if caller != 'XBMC': + self._send(self._send_keys[item.conf['xbmc_send']], {item.conf['xbmc_send']: item()}, wait=False) + + def run(self): + self.alive = True + + def _send(self, method, params=None, id=None, wait=True): + self._cmd_lock.acquire() + self._reply = None + if id is None: + self._id += 1 + id = self._id + if id > 100: + self._id = 0 + self._rid = id + + if method == 'System.Shutdown': + params = None + + if params is not None: + data = {"jsonrpc": "2.0", "id": id, "method": method, 'params': params} + else: + data = {"jsonrpc": "2.0", "id": id, "method": method} + self._reply_lock.acquire() + logger.debug("XBMC sending: {0}".format(json.dumps(data, separators=(',', ':')))) + self.send((json.dumps(data, separators=(',', ':')) + '\r\n').encode()) + if wait: + self._reply_lock.wait(2) + self._reply_lock.release() + reply = self._reply + self._reply = None + self._cmd_lock.release() + return reply + + def _set_item(self, key, value): + if key in self._items: + self._items[key](value, 'XBMC') + + def found_balance(self, data): + event = json.loads(data.decode()) + logger.debug("XBMC receiving: {0}".format(event)) + if 'id' in event: + if event['id'] == self._rid: + self._rid = None + self._reply = event + self._reply_lock.acquire() + self._reply_lock.notify() + self._reply_lock.release() + return + if 'method' in event: + if event['method'] == 'Player.OnPause': + if 'state' in self._items: + self._items['state']('Pause', 'XBMC') + elif event['method'] == 'Player.OnStop': + if 'state' in self._items: + self._items['state']('Menu', 'XBMC') + if 'media' in self._items: + self._items['media']('', 'XBMC') + if 'title' in self._items: + self._items['title']('', 'XBMC') + if event['method'] in ['Player.OnPlay']: + # use a different thread for event handling + self._sh.trigger('xbmc-event', self._parse_event, 'XBMC', value={'event': event}) + elif event['method'] in ['Application.OnVolumeChanged']: + if 'mute' in self._items: + self._set_item('mute', event['params']['data']['muted']) + if 'volume' in self._items: + self._set_item('volume', event['params']['data']['volume']) + + def _parse_event(self, event): + if event['method'] == 'Player.OnPlay': + result = self._send('Player.GetActivePlayers')['result'] + if len(result) == 0: + logger.info("XBMC: no active player found.") + return + playerid = result[0]['playerid'] + typ = result[0]['type'] + self._items['state']('Playing', 'XBMC') + if typ == 'video': + result = self._send('Player.GetItem', {"properties": ["title"], "playerid": playerid}, "VideoGetItem")['result'] + title = result['item']['title'] + if not title and 'label' in result['item']: + title = result['item']['label'] + if 'media' in self._items: + typ = result['item']['type'] + self._items['media'](typ.capitalize(), 'XBMC') + elif typ == 'audio': + if 'media' in self._items: + self._items['media'](typ.capitalize(), 'XBMC') + result = self._send('Player.GetItem', {"properties": ["title", "artist"], "playerid": playerid}, "AudioGetItem")['result'] + if len(result['item']['artist']) == 0: + artist = 'unknown' + else: + artist = result['item']['artist'][0] + title = artist + ' - ' + result['item']['title'] + elif typ == 'picture': + if 'media' in self._items: + self._items['media'](typ.capitalize(), 'XBMC') + title = '' + else: + logger.warning("XBMC: Unknown type: {0}".format(typ)) + return + if 'title' in self._items: + self._items['title'](title, 'XBMC') diff --git a/xbmc/plugin.yaml b/xbmc/plugin.yaml new file mode 100644 index 000000000..5ae0b65eb --- /dev/null +++ b/xbmc/plugin.yaml @@ -0,0 +1,26 @@ +# Metadata for the classic-plugin +plugin: + # Global plugin attributes + type: interface # plugin type (gateway, interface, protocol, system, web) + description: + de: 'Anbindung von XBMC v12 (Frodo) oder neuer' + en: '' + maintainer: ggf. cmalo (mknx) + tester: onkelandy + keywords: mediacenter +# documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page +# support: https://knx-user-forum.de/forum/supportforen/smarthome-py + +# Following entries are for Smart-Plugins: +# version: 1.3.3 # Plugin version +# sh_minversion: 1.3 # minimum shNG version to use this plugin +# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) +# multi_instance: False + classname: XBMC # class containing the plugin + +#parameters: + # Definition of parameters to be configured in etc/plugin.yaml + +#item_attributes: + # Definition of item attributes defined by this plugin + From 1cdf78b6634b76b3415c1a0a34fac44e0f04a020 Mon Sep 17 00:00:00 2001 From: Rudi Date: Thu, 8 Mar 2018 22:47:50 +0100 Subject: [PATCH 023/705] This plugin has been developed for the Raspberry Pi. It allows easy access to 1-Wire - sensors --- rpi1wire/README.md | 181 ++++++++++++++++++++++++++++++++++++ rpi1wire/__init__.py | 217 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 398 insertions(+) create mode 100644 rpi1wire/README.md create mode 100644 rpi1wire/__init__.py diff --git a/rpi1wire/README.md b/rpi1wire/README.md new file mode 100644 index 000000000..fa88af17c --- /dev/null +++ b/rpi1wire/README.md @@ -0,0 +1,181 @@ +# Raspberry Pi 1-Wire plugin + +# Requirements + +This plugin has been developed for the Raspberry Pi. It allows easy access to 1-Wire - sensors. +We tested the plugin with the Raspberry Pi B and the temperature sensor DS18B20. + +## Supported Hardware + +Tested width: +Raspberry Pi Model B +1-Wire - Sensor DS18B20 + +# Configuration + +## Raspberry Pi + + see also: http://www.kompf.de/weather/pionewiremini.html + +### /boot/config.txt +
+   # activating 1-wire without pullup (3-wire-Version)
+   dtoverlay=w1-gpio,gpiopin=4,pullup=off
+
+### /etc/modules + +
+   #(3-wire-Version)
+   w1-gpio pullup=0  
+   w1-therm
+
+ +# Smarthome + +## plugin.conf + +
+[rpi1wire]
+   class_name = Rpi1Wire
+   class_path = plugins.rpi1wire
+#   dirname = "/sys/bus/w1/devices"
+#   cycle = 120
+
+ +## plugin.yaml + +
+rpi1wire:
+   class_name: Rpi1Wire
+   class_path: plugins.rpi1wire
+#   dirname: "/sys/bus/w1/devices"
+#   cycle: 120
+
+ +dirname +
+   is the path where the Raspberry provides the values of the 1-wire - sensors
+   default "/sys/bus/w1/devices"
+
+cycle +
+   is the period in which the values are updated
+   default 120 seconds
+
+ + +## items +# .conf + +
+   [rpi1wire]
+       [[sensor_list]]
+           name = Sensor-List
+           type = str
+           visu_acl = ro
+       [[sensors]]
+          name = Sensors
+          type = num
+          visu_acl = ro
+
+ +# .yaml + +
+   rpi1wire:
+       sensor_list:
+           name: Sensor-List
+           type: str
+           visu_acl: ro
+       sensors:
+          name: Sensors
+          type: num
+          visu_acl: ro
+
+sh.rpi1wire.sensor_list() +
+   - contains a list of all found sensors
+
+sh.rpi1wire.sensors() +
+   - contains the number of sensors found
+
+### rpi1wire_name +
   
+   The name of the 1-wire - sensor
+    - rpi1wire_name or rpi1wire_id are possible
+
+### rpi1wire_id +
   
+   The id of the 1-wire - sensor
+    - rpi1wire_name or rpi1wire_id are possible
+
+### rpi1wire_update +
   
+   If you trigger this item, the sensors are re-searched without restart the server
+
+ +### Example + + +
+# items/my.conf
+
+[someroom]
+    [[mytemperature]]
+        name = my Name
+        type = num
+        visu_acl = ro
+        rpi1wire_name = rpi_temp1
+        sqlite = yes
+
+#or
+
+[someroom]
+    [[mytemperature]]
+        name = my Name
+        name = Wohnzimme Raumtemperatur
+        type = num
+        visu_acl = ro
+        rpi1wire_id = 28-0215018970ff
+        sqlite = yes
+
+[rpi1wire]
+    [[update]]
+        name = Update Sensor-List
+        type = bool
+        visu_acl = rw
+        rpi1wire_update = 1
+
+
+# or in YAML +
+# items/my.yaml
+
+someroom:
+     mytemperature:
+        name: my Name
+        type: num
+        visu_acl: ro
+        rpi1wire_name: rpi_temp1
+        sqlite: yes
+
+#or
+
+someroom:
+     mytemperature:
+        name: my Name
+        name: Wohnzimme Raumtemperatur
+        type: num
+        visu_acl: ro
+        rpi1wire_id: 28-0215018970ff
+        sqlite: yes
+
+rpi1wire:
+     update:
+        name: Update Sensor-List
+        type: bool
+        visu_acl: rw
+        rpi1wire_update: 1
+
+
diff --git a/rpi1wire/__init__.py b/rpi1wire/__init__.py new file mode 100644 index 000000000..cd0b70592 --- /dev/null +++ b/rpi1wire/__init__.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2015 R.Rauer software@rrauer.de +######################################################################### +# This file is part of SmartHome.py. http://mknx.github.io/smarthome/ +# +# SmartHome.py is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# SmartHome.py is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with SmartHome.py. If not, see . +######################################################################### + +import logging +import os + +class Rpi1Wire(): + def __init__(self, smarthome, dirname="/sys/bus/w1/devices",cycle = 120): + self.logger = logging.getLogger(__name__) + self.logger.info('Init rpi1wire') + self._sh = smarthome + self.dirname = dirname + self.cycle = cycle + self.sensors = {} + self._sensordaten = {} + self.values = {} + self.update = False + self.get_sensors() + self.anz_sensors = len(self.sensors) + self.logger.info("rpi1wire find {0} sensors".format(self.anz_sensors)) + self.logger.info(self.sensors) + self._sh.scheduler.add('rpi1wire', self.update_values, prio=3, cycle=self.cycle) + + + + def run(self): + self.alive = True + self.update_values() + self.update_basics() + + def update_basics(self): + anz = self._sh.return_item("rpi1wire.sensors") + ids = self._sh.return_item("rpi1wire.sensor_list") + if anz != None: + anz(int(self.anz_sensors),'rpi1wire') + self.logger.debug("rpi1wire-item sensors value = {0}".format(self.anz_sensors)) + if ids != None: + ids(str(self.sensors),'rpi1wire') + self.logger.debug("rpi1wire-item sensor_list value = {0}".format(self.sensors)) + + def stop(self): + self.alive = False + + def parse_item(self, item): + if 'rpi1wire_update' in item.conf: + ad=item.conf['rpi1wire_update'] + return self.update_item + if 'rpi1wire_id' not in item.conf: + if 'rpi1wire_name' not in item.conf: + return None + if 'rpi1wire_unit' not in item.conf: + self.logger.warning("rpi1wire_unit for {0} not defined".format(item.id())) + return None + not_found = False + if 'rpi1wire_id'in item.conf: + addr = item.conf['rpi1wire_id'] + try: + for sn, sid in self.sensors.items(): + if sid == item.conf['rpi1wire_id']: + name = sn + break + except: + self.logger.warning("Sensor {0} Hardware not found".format(item.conf['rpi1wire_id'])) + not_found = True + else: + if 'rpi1wire_name'in item.conf: + name = item.conf['rpi1wire_name'] + try: + addr = self.sensors[item.conf['rpi1wire_name']] + except: + self.logger.warning("Sensor {0} Hardware not found".format(item.conf['rpi1wire_name'])) + not_found = True + if not_found == False: + self._sensordaten[addr]['item'] = item + + def parse_logic(self, logic): + pass + + def update_item(self, item, caller=None, source=None, dest=None): + if self.update == True: + return None + if 'rpi1wire_update' in item.conf: + self.logger.info("rpi1wire_update wurde angefordert") + self.update_sensors() + return None + if caller != 'plugin': + self.logger.info("update item: {0}".format(item.id())) + + def update_values(self): + for sensor in self.sensors: + id = self.sensors[sensor] + value = self.getvalue(id) + #if value != 99999: + text = sensor +"=" + sensor[0] +": " + str(round(value/float(1000),1)) + " (" + str(value)+")" + self.logger.debug(text) + self.values[sensor] = round(value/float(1000),1) + try: + rpix = self._sensordaten[id] + temp = rpix['item'] + temp(round(value/float(1000),1), "rpi1wire") + self._sensordaten[id]['value'] = round(value/float(1000),1) + except: + self.logger.info("sensor {0} has no item".format(id)) + + def get_sensors(self): + objects = self.folder_objects(self.dirname) + i=1 + for sensor in objects: + if 'w1_bus' in sensor: + continue + typ = sensor.rsplit("-",1) + if typ[0] in ['10', '22', '28']: + value = self.getvalue(sensor) + if value == 99999: + self.logger.warning("rpi1wire {0} - has no value".format(sensor)) + else: + text = "rpi_temp"+str(i)+"=" + sensor +": " + str(round(value/float(1000),1)) + " (" + str(value)+")" + self.logger.info(text) + self.sensors["rpi_temp"+str(i)] = sensor + self.values["rpi_temp"+str(i)] = round(value/float(1000),1) + self._sensordaten[sensor]= {'name' : "rpi_temp"+str(i), 'value' : round(value/float(1000),1)} + i+=1 + + def folder_objects(self, dirname, otype="all"): + if (os.path.exists(dirname) == False or + os.path.isdir(dirname) == False or + os.access(dirname, os.R_OK) == False): + return False + else: + objects = os.listdir(dirname) + result = [] + for objectname in objects: + objectpath = dirname + "/" + objectname + if (otype == "all" or + (otype == "dir" and os.path.isdir(objectpath) == True) or + (otype == "file" and os.path.isfile(objectpath) == True) or + (otype == "link" and os.path.islink(objectpath) == True)): + result.append(objectname) + result.sort() + return result + + + def getvalue(self, id): + try: + mytemp = '' + filename = 'w1_slave' + f = open('/' + self.dirname + '/' + id + '/' + filename, 'r') + line = f.readline() # read 1st line + crc = line.rsplit(' ',1) + crc = crc[1].replace('\n', '') + if crc=='YES': + line = f.readline() # read 2nd line + mytemp = line.rsplit('t=',1) + else: + self.logger.warning("rpi1wire {0} - return no value".format(id)) + mytemp = '99999' + f.close() + return int(mytemp[1]) + except: + self.logger.warning("can not read sensor {}".format(id)) + return 99999 + + def update_sensors(self): + self.update = True + self.sensors = {} + self.anz_sensors = 0 + self.get_sensors() + self.anz_sensors = len(self.sensors) + self.search_item() + self.update_basics() + self.update_values() + upd = self._sh.return_item("rpi1wire.update") + if upd != None: + upd(False,'rpi1wire') + self.logger.info("rpi1wire-item update value done, {0} sensors found".format(self.anz_sensors)) + self.update = False + + def search_item(self): + items = self._sh.return_items() + for item in items: + if 'rpi1wire_id'in item.conf: + addr = item.conf['rpi1wire_id'] + try: + for sn, sid in self.sensors.items(): + if sid == item.conf['rpi1wire_id']: + name = sn + self._sensordaten[addr]['item'] = item + break + except: + self.logger.warning("Sensor {0} Hardware not found".format(item.conf['rpi1wire_id'])) + not_found = True + if 'rpi1wire_name'in item.conf: + name = item.conf['rpi1wire_name'] + try: + addr = self.sensors[item.conf['rpi1wire_name']] + self._sensordaten[addr]['item'] = item + except: + self.logger.warning("Sensor {0} Hardware not found".format(item.conf['rpi1wire_name'])) + self.logger.info("{0} rpi1wire-items registriert".format(len(self._sensordaten))) From 6da255972ba2bb9011aac400f595136c5e9288f7 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 15 Jul 2018 11:46:09 +0200 Subject: [PATCH 024/705] Xiaomi Plugin: renaming to "miflora" plugin --- {xiaomi => miflora}/README.md | 36 ++++++++++++++-------------- {xiaomi => miflora}/__init__.py | 2 +- {xiaomi => miflora}/plugin.yaml | 10 ++++---- {xiaomi => miflora}/requirements.txt | 0 4 files changed, 24 insertions(+), 24 deletions(-) rename {xiaomi => miflora}/README.md (55%) rename {xiaomi => miflora}/__init__.py (99%) rename {xiaomi => miflora}/plugin.yaml (87%) mode change 100755 => 100644 rename {xiaomi => miflora}/requirements.txt (100%) diff --git a/xiaomi/README.md b/miflora/README.md similarity index 55% rename from xiaomi/README.md rename to miflora/README.md index 6e8cbf123..9869007a0 100644 --- a/xiaomi/README.md +++ b/miflora/README.md @@ -1,6 +1,6 @@ -# Xiaomi +# Miflora -Version 0.3 +Version 0.4 ## Requirements This plugin requires lib miflora in version 0.4 or above. You can install this lib with: @@ -15,32 +15,32 @@ Forum thread to the plugin: https://knx-user-forum.de/forum/supportforen/smartho ## Supported Hardware -* Xiaomi Mi Plant Flowers Tester Light Monitor +* Xiaomi MiFlora Plant Flowers Tester Light Monitor ## Configuration ### plugin.yaml ```yaml -xiaomi: - class_name: Xiaomi - class_path: plugins.xiaomi +miflora: + class_name: Miflora + class_path: miflora bt_addr: C4:7C:7E:21:F3:2B cycle: 300 - instance: xiaomi + instance: miflora ``` #### Attributes - * `bt_addr`: The Bluetooth address of your xiaomi plant sensor. Find e.g. with hcitool lescan + * `bt_addr`: The Bluetooth address of your xiaomi miflora plant sensor. Find e.g. with hcitool lescan * `cycle`: Cycle interval for data retrieval * `instance`: Instance name in case multi-instance use is needed (one instance can handle one sensor) ### items.yaml -#### xiaomi_data_type +#### miflora_data_type -The xiaomi_data_type is needed to provide information to the plugin, which values shall be stored in the item. -Possible xiaomi_data_type's are temperature, light, moisture, conductivity, name, firmware and battery. +The miflora_data_type is needed to provide information to the plugin, which values shall be stored in the item. +Possible miflora_data_type's are temperature, light, moisture, conductivity, name, firmware and battery. #### Example @@ -51,29 +51,29 @@ plants: temperature: type: num - xiaomi_data_type@xiaomi: temperature + miflora_data_type@miflora: temperature light: type: num - xiaomi_data_type@xiaomi: light + miflora_data_type@miflora: light moisture: type: num - xiaomi_data_type@xiaomi: moisture + miflora_data_type@miflora: moisture conductivity: type: num - xiaomi_data_type@xiaomi: conductivity + miflora_data_type@miflora: conductivity name: type: str - xiaomi_data_type@xiaomi: name + miflora_data_type@miflora: name firmware: type: str - xiaomi_data_type@xiaomi: firmware + miflora_data_type@miflora: firmware battery: type: num - xiaomi_data_type@xiaomi: battery + miflora_data_type@miflora: battery ``` diff --git a/xiaomi/__init__.py b/miflora/__init__.py similarity index 99% rename from xiaomi/__init__.py rename to miflora/__init__.py index 5d5317512..a61ada22e 100644 --- a/xiaomi/__init__.py +++ b/miflora/__init__.py @@ -26,7 +26,7 @@ from btlewrap import available_backends, BluepyBackend, GatttoolBackend, PygattBackend from lib.model.smartplugin import SmartPlugin -class Xiaomi(SmartPlugin): +class Miflora(SmartPlugin): ALLOW_MULTIINSTANCE = True PLUGIN_VERSION = "1.3.0.3" diff --git a/xiaomi/plugin.yaml b/miflora/plugin.yaml old mode 100755 new mode 100644 similarity index 87% rename from xiaomi/plugin.yaml rename to miflora/plugin.yaml index ff75aa90b..409f6e7e9 --- a/xiaomi/plugin.yaml +++ b/miflora/plugin.yaml @@ -8,14 +8,14 @@ plugin: maintainer: psilo909 tester: Sandman60 # keywords: iot xyz - documentation: http://smarthomeng.de/user/plugins_doc/config/xiaomi.html # url of documentation (wiki) page - support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1027133-plugin-xiaomi-mi-plant-flowers-tester-light-monitor + documentation: http://smarthomeng.de/user/plugins_doc/config/miflora.html # url of documentation (wiki) page + support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1027133-plugin-miflora-mi-plant-flowers-tester-light-monitor - version: 1.3.0.3 # Plugin version + version: 1.3.0.4 # Plugin version sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance - classname: Xiaomi # class containing the plugin + classname: Miflora # class containing the plugin parameters: # Definition of parameters to be configured in etc/plugin.yaml @@ -37,7 +37,7 @@ parameters: item_attributes: # Definition of item attributes defined by this plugin - xiaomi_data_type: + miflora_data_type: type: str mandatory: True description: diff --git a/xiaomi/requirements.txt b/miflora/requirements.txt similarity index 100% rename from xiaomi/requirements.txt rename to miflora/requirements.txt From 7269c7e8fb280ca61c110de9bc05c90e5188ff14 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 15 Jul 2018 11:47:52 +0200 Subject: [PATCH 025/705] Miflora: forgot to increment version --- miflora/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miflora/__init__.py b/miflora/__init__.py index a61ada22e..31e7427f6 100644 --- a/miflora/__init__.py +++ b/miflora/__init__.py @@ -28,7 +28,7 @@ class Miflora(SmartPlugin): ALLOW_MULTIINSTANCE = True - PLUGIN_VERSION = "1.3.0.3" + PLUGIN_VERSION = "1.3.0.4" def __init__(self, smarthome, bt_addr, cycle=300): """ From 0f8928d70effd53da0ee7cd990f6a868bdd8f677 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sun, 15 Jul 2018 15:14:41 +0200 Subject: [PATCH 026/705] fixed problem with item initialization --- avdevice/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/avdevice/__init__.py b/avdevice/__init__.py index e41b13626..95519131b 100755 --- a/avdevice/__init__.py +++ b/avdevice/__init__.py @@ -1097,6 +1097,11 @@ def _checkdependency(self, dep_function, dep_type): "Checking Dependency {}: Adding query because it's init dependency is set to true.".format( self._name)) return False + elif func.lower() == 'init' and dep_type == 'statusupdate' and len(totest[zone][dep_function]) == 1: + self.logger.log(VERBOSE2, + "Checking Dependency {}: Adding query because updating status and no other dependencies set.".format( + self._name)) + return False elif dep_type == 'initupdate' and self._statusquery is False: self.logger.log(VERBOSE2, "Checking Dependency {}: Not adding query because no init dependency defined.".format( From 1d505ff293edaacee178d4f36842139c4aee3414 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 15 Jul 2018 16:22:20 +0200 Subject: [PATCH 027/705] changed _type to type() --- avm/webif/templates/index.html | 2 +- darksky/webif/templates/index.html | 2 +- simulation/webif/templates/index.html | 2 +- sma_em/webif/templates/index.html | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/avm/webif/templates/index.html b/avm/webif/templates/index.html index aadcc25d9..37abe313e 100644 --- a/avm/webif/templates/index.html +++ b/avm/webif/templates/index.html @@ -47,7 +47,7 @@ {% endif %} {{ item._path }} - {{ item._type }} + {{ item.type() }} {{ item.conf[instance_key] }} {{ item() }} {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} diff --git a/darksky/webif/templates/index.html b/darksky/webif/templates/index.html index e8d10502e..1b667a330 100644 --- a/darksky/webif/templates/index.html +++ b/darksky/webif/templates/index.html @@ -29,7 +29,7 @@
Darksky Plugin Items ({{ p.get_items()|length }})
{% for key, item in p.get_items().items() %} {{ item._path }} - {{ item._type }} + {{ item.type() }} {{ key }} {{ item() }} {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} diff --git a/simulation/webif/templates/index.html b/simulation/webif/templates/index.html index ee38d32b1..76198a423 100644 --- a/simulation/webif/templates/index.html +++ b/simulation/webif/templates/index.html @@ -68,7 +68,7 @@
{{ _('Simulation Plugin Items') }} ({{ p.get_items()|length }})
{% for item in p.get_items() %} {{ item._path }} - {{ item._type }} + {{ item.type() }} {{ item() }} {{ item.conf['sim'] }} {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} diff --git a/sma_em/webif/templates/index.html b/sma_em/webif/templates/index.html index c6019804e..ae1b89e7f 100644 --- a/sma_em/webif/templates/index.html +++ b/sma_em/webif/templates/index.html @@ -47,7 +47,7 @@
SMA EM Items ({{ p.get_items()|length }})
{% for key, item in p.get_items().items() %} {{ item._path }} - {{ item._type }} + {{ item.type() }} {{ key }} {{ item() }} {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} From 3c8fc05aa0df499da765356b494fb6d61fc200b1 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 15 Jul 2018 16:25:15 +0200 Subject: [PATCH 028/705] More calls to item attributes changed --- avm/webif/templates/index.html | 18 +++++++++--------- darksky/webif/templates/index.html | 2 +- simulation/webif/templates/index.html | 2 +- sma_em/webif/templates/index.html | 2 +- webservices/webif/templates/index.html | 8 ++++---- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/avm/webif/templates/index.html b/avm/webif/templates/index.html index 37abe313e..bbb83b270 100644 --- a/avm/webif/templates/index.html +++ b/avm/webif/templates/index.html @@ -46,7 +46,7 @@ {% set instance_key = "avm_data_type" %} {% endif %} - {{ item._path }} + {{ item.id() }} {{ item.type() }} {{ item.conf[instance_key] }} {{ item() }} @@ -80,8 +80,8 @@ {% set instance_key = "avm_data_type" %} {% endif %} - {{ item._path }} - {{ item._type }} + {{ item.id() }} + {{ item.type() }} {{ item.conf[instance_key] }} {{ item() }} {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} @@ -95,8 +95,8 @@ {% set instance_key = "avm_data_type" %} {% endif %} - {{ item._path }} - {{ item._type }} + {{ item.id() }} + {{ item.type() }} {{ item.conf[instance_key] }} {{ item() }} {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} @@ -110,8 +110,8 @@ {% set instance_key = "avm_data_type" %} {% endif %} - {{ item._path }} - {{ item._type }} + {{ item.id() }} + {{ item.type() }} {{ item.conf[instance_key] }} {{ item() }} {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} @@ -125,8 +125,8 @@ {% set instance_key = "avm_data_type" %} {% endif %} - {{ item._path }} - {{ item._type }} + {{ item.id() }} + {{ item.type() }} {{ item.conf[instance_key] }} {{ item() }} {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} diff --git a/darksky/webif/templates/index.html b/darksky/webif/templates/index.html index 1b667a330..e12934b3f 100644 --- a/darksky/webif/templates/index.html +++ b/darksky/webif/templates/index.html @@ -28,7 +28,7 @@
Darksky Plugin Items ({{ p.get_items()|length }})
{% for key, item in p.get_items().items() %} - {{ item._path }} + {{ item.id() }} {{ item.type() }} {{ key }} {{ item() }} diff --git a/simulation/webif/templates/index.html b/simulation/webif/templates/index.html index 76198a423..a0b9a7905 100644 --- a/simulation/webif/templates/index.html +++ b/simulation/webif/templates/index.html @@ -67,7 +67,7 @@
{{ _('Simulation Plugin Items') }} ({{ p.get_items()|length }})
{% for item in p.get_items() %} - {{ item._path }} + {{ item.id() }} {{ item.type() }} {{ item() }} {{ item.conf['sim'] }} diff --git a/sma_em/webif/templates/index.html b/sma_em/webif/templates/index.html index ae1b89e7f..20ed4e9da 100644 --- a/sma_em/webif/templates/index.html +++ b/sma_em/webif/templates/index.html @@ -46,7 +46,7 @@
SMA EM Items ({{ p.get_items()|length }})
{% for key, item in p.get_items().items() %} - {{ item._path }} + {{ item.id() }} {{ item.type() }} {{ key }} {{ item() }} diff --git a/webservices/webif/templates/index.html b/webservices/webif/templates/index.html index af6fe0fff..ec7ff881a 100755 --- a/webservices/webif/templates/index.html +++ b/webservices/webif/templates/index.html @@ -44,10 +44,10 @@ {% for item in value %} - {{item._path}} + {{item.id()}} - {{item._path}} + {{item.id()}} {{item.type()}} @@ -63,10 +63,10 @@ {% for item in item_data %} - {{item._path}} + {{item.id()}} - {{item._path}} + {{item.id()}} {{item.type()}} From ebb33d807b243478f294403c5f821af6b70ee160 Mon Sep 17 00:00:00 2001 From: msinn Date: Mon, 16 Jul 2018 00:15:23 +0200 Subject: [PATCH 029/705] backend: Optimized display of item details --- backend/webif/templates/items.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/webif/templates/items.html b/backend/webif/templates/items.html index bfd1b1580..4801b3f61 100755 --- a/backend/webif/templates/items.html +++ b/backend/webif/templates/items.html @@ -92,7 +92,7 @@ } temp = '
'; - temp = temp + ''; + temp = temp + ''; temp = temp + ''; temp = temp + ''; temp = temp + ''; From 9ba606a01c7868862cccd802f1f2a00b6ab29a5c Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 16 Jul 2018 09:48:08 +0200 Subject: [PATCH 030/705] OpenWeatherMap: first version of plugin, supporting weather and uvi data --- openweathermap/README.md | 151 ++++++++++ openweathermap/__init__.py | 274 ++++++++++++++++++ openweathermap/assets/webif1.jpg | Bin 0 -> 232368 bytes openweathermap/assets/webif2.jpg | Bin 0 -> 130994 bytes openweathermap/plugin.yaml | 71 +++++ openweathermap/user_doc.rst | 54 ++++ .../webif/static/img/plugin_logo.png | Bin 0 -> 76636 bytes openweathermap/webif/templates/index.html | 58 ++++ 8 files changed, 608 insertions(+) create mode 100644 openweathermap/README.md create mode 100644 openweathermap/__init__.py create mode 100644 openweathermap/assets/webif1.jpg create mode 100644 openweathermap/assets/webif2.jpg create mode 100644 openweathermap/plugin.yaml create mode 100644 openweathermap/user_doc.rst create mode 100644 openweathermap/webif/static/img/plugin_logo.png create mode 100644 openweathermap/webif/templates/index.html diff --git a/openweathermap/README.md b/openweathermap/README.md new file mode 100644 index 000000000..bb7359a60 --- /dev/null +++ b/openweathermap/README.md @@ -0,0 +1,151 @@ +# OpenWeatherMap + +#### Version 1.5.0.1 + +This plugins can be used retrieve weather information from OpenWeatherMap (https://openweathermap.org/). + +## Support +Support is provided trough the support thread within the smarthomeNG forum: [Smarthome.py](https://knx-user-forum.de/forum/supportforen/smarthome-py) + + +### Requirements + +An api key from OpenWeatherMap is needed. It can be obtained free of charge from ```https://openweathermap.org```. + +The api key which is available free of charge allows up to 60 calls a minute. Keep this in mind if you want to change the update frequency using the **`cycle`** parameter. + +## Configuration + +### plugin.yaml + +Use the plugin configuration to configure the openweathermap plugin. + +You can configure multiple instances of the openweathermap plugin to collect data for multiple locations. + +```yaml +# for etc/plugin.yaml configuration file: +weather_openweathermap: + class_name: OpenWeatherMap + class_path: plugins.openweathermap + key: xxxxyyyyxxxxyyyy + latitude: '48.04712' + longitude: '11.81421' + # language: de + # cycle: 600 + # instance: ... +``` + + +### Example: items.yaml +Example configuration of an item-tree for the openweathermap plugin in yaml-format: + +```yaml + + ...: + +owm: + + home: + + latitude: + type: num + owm_matchstring@home: coord/lat + + longitude: + type: num + owm_matchstring@home: coord/lon + + conditions: + type: list + owm_matchstring@home: weather + + temp: + type: num + owm_matchstring@home: main/temp + + pressure: + type: num + owm_matchstring@home: main/pressure + + grnd_level: + type: num + owm_matchstring@home: main/grnd_level + + sea_level: + type: num + owm_matchstring@home: main/sea_level + + humidity: + type: num + owm_matchstring@home: main/humidity + + temp_min: + type: num + owm_matchstring@home: main/temp_min + + temp_max: + type: num + owm_matchstring@home: main/temp_max + + wind: + + wind_speed: + type: num + owm_matchstring@home: wind/speed + + wind_deg: + type: num + owm_matchstring@home: wind/deg + + clouds: + type: num + owm_matchstring@home: clouds/all + + rain_3h: + type: num + owm_matchstring@home: rain/3h + + snow_3h: + type: num + owm_matchstring@home: snow/3h + + time: + type: num + owm_matchstring@home: dt + + sunrise_utc: + type: num + owm_matchstring@home: sys/sunrise + + sunset_utc: + type: num + owm_matchstring@home: sys/sunset + + country: + type: str + owm_matchstring@home: sys/country + + city_name: + type: str + owm_matchstring@home: name + + city_id: + type: num + owm_matchstring@home: id + + uvi: + type: num + owm_matchstring@home: uvi_value + + uvi_date: + type: num + owm_matchstring@home: uvi_date +``` + +### logic.yaml + +No logic configuration implemented. + +## Methods / Functions + +No methods or functions are implemented. diff --git a/openweathermap/__init__.py b/openweathermap/__init__.py new file mode 100644 index 000000000..7bd5a5df4 --- /dev/null +++ b/openweathermap/__init__.py @@ -0,0 +1,274 @@ +#!/usr/bin/env python3 +# +######################################################################### +# Copyright 2018 René Frieß rene.friess(a)gmail.com +# Version 1.5.0.1 +######################################################################### +# +# This file is part of SmartHomeNG. +# +# SmartHomeNG is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# SmartHomeNG is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with SmartHomeNG. If not, see . +# +######################################################################### + +import logging +import requests +import datetime +import json +from lib.module import Modules +from lib.model.smartplugin import * + + +class OpenWeatherMap(SmartPlugin): + PLUGIN_VERSION = "1.5.0.1" + + _base_url = 'https://api.openweathermap.org/%s' + + def __init__(self, sh, *args, **kwargs): + """ + Initializes the plugin + @param apikey: For accessing the free "Tankerkönig-Spritpreis-API" you need a personal + api key. For your own key register to https://creativecommons.tankerkoenig.de + """ + self.logger = logging.getLogger(__name__) + self._key = self.get_parameter_value('key') + if self.get_parameter_value('latitude') != '' and self.get_parameter_value('longitude') != '': + self._lat = self.get_parameter_value('latitude') + self._lon = self.get_parameter_value('longitude') + else: + self.logger.debug("__init__: latitude and longitude not provided, using shng system values instead.") + self._lat = self.get_sh()._lat + self._lon = self.get_sh()._lon + self._lang = self.get_parameter_value('lang') + self._units = self.get_parameter_value('units') + self._jsonData = {} + self._session = requests.Session() + self._cycle = int(self.get_parameter_value('cycle')) + self._items = {} + + if not self.init_webinterface(): + self._init_complete = False + + def run(self): + self.scheduler_add(__name__, self._update_loop, prio=5, cycle=self._cycle, offset=2) + self.alive = True + + def stop(self): + self.alive = False + + def _update_loop(self): + """ + Starts the update loop for all known items. + """ + self.logger.debug('Starting update loop for instance %s' % self.get_instance_name()) + if not self.alive: + return + + self._update() + + def _update(self): + """ + Updates information on diverse items + """ + weather = self.get_weather() + uv = self.get_uv() + + self._jsonData['weather'] = weather + self._jsonData['uvi'] = uv + for s, item in self._items.items(): + + if 'uvi' not in s: + wrk = weather + else: + wrk = uv + s = s.replace("uvi_", "") + sp = s.split('/') + if s == "flags/sources": + wrk = ', '.join(wrk['flags']['sources']) + else: + while True: + if (len(sp) == 0) or (wrk is None): + break + if type(wrk) is list: + if self.is_int(sp[0]): + if int(sp[0]) < len(wrk): + wrk = wrk[int(sp[0])] + else: + self.logger.error( + "_update: invalid owm_matchstring '{}'; integer too large in matchstring".format( + s)) + break + else: + self.logger.error( + "_update: invalid owm_matchstring '{}'; integer expected in matchstring".format( + s)) + break + else: + wrk = wrk.get(sp[0]) + if len(sp) == 1: + spl = s.split('/') + self.logger.debug( + "_update: owm_matchstring split len={}, content={} -> '{}'".format(str(len(spl)), + str(spl), + str(wrk))) + sp.pop(0) + + # if a value was found, store it to item + if wrk is not None: + item(wrk, 'DarkSky') + self.logger.debug('_update: Value "{0}" written to item'.format(wrk)) + + return + + def get_weather(self): + """ + Requests the weather information at openweathermap.com + """ + try: + response = self._session.get(self._build_url('weather')) + except Exception as e: + self.logger.error( + "get_weather: Exception when sending GET request for get_weather: %s" % str(e)) + return + json_obj = response.json() + return json_obj + + def get_uv(self): + """ + Requests the weather information at openweathermap.com + """ + try: + response = self._session.get(self._build_url('uv')) + except Exception as e: + self.logger.error( + "get_uv: Exception when sending GET request for get_uv: %s" % str(e)) + return + json_obj = response.json() + return json_obj + + def parse_item(self, item): + """ + Default plugin parse_item method. Is called when the plugin is initialized. Selects each item corresponding to + the owm_matchstring and adds it to an internal array + + :param item: The item to process. + """ + if self.get_iattr_value(item.conf, 'owm_matchstring'): + self._items[self.get_iattr_value(item.conf, 'owm_matchstring')] = item + + def get_items(self): + return self._items + + def get_json_data_weather(self): + return self._jsonData['weather'] + + def get_json_data_uvi(self): + return self._jsonData['uvi'] + + def _build_url(self, url_type='weather'): + """ + Builds a request url + @param url_type: url type (currently on 'forecast', as historic data are not supported. + @return: string of the url + """ + url = '' + if url_type == 'weather': + url = self._base_url % 'data/2.5/weather' + parameters = "?lat=%s&lon=%s&appid=%s&lang=%s&units=%s" % (self._lat, self._lon, self._key, self._lang, + self._units) + url = '%s%s' % (url, parameters) + elif url_type == 'uv': + url = self._base_url % 'data/2.5/uvi' + parameters = "?lat=%s&lon=%s&appid=%s&lang=%s&units=%s" % (self._lat, self._lon, self._key, self._lang, + self._units) + url = '%s%s' % (url, parameters) + else: + self.logger.error('_build_url: Wrong url type specified: %s' % url_type) + return url + + def init_webinterface(self): + """" + Initialize the web interface for this plugin + + This method is only needed if the plugin is implementing a web interface + """ + try: + self.mod_http = Modules.get_instance().get_module( + 'http') # try/except to handle running in a core version that does not support modules + except: + self.mod_http = None + if self.mod_http == None: + self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_shortname())) + return False + + # set application configuration for cherrypy + webif_dir = self.path_join(self.get_plugin_dir(), 'webif') + config = { + '/': { + 'tools.staticdir.root': webif_dir, + }, + '/static': { + 'tools.staticdir.on': True, + 'tools.staticdir.dir': 'static' + } + } + + # Register the web interface as a cherrypy app + self.mod_http.register_webif(WebInterface(webif_dir, self), + self.get_shortname(), + config, + self.get_classname(), self.get_instance_name(), + description='') + + return True + + +import cherrypy +from jinja2 import Environment, FileSystemLoader + + +class WebInterface(SmartPluginWebIf): + + def __init__(self, webif_dir, plugin): + """ + Initialization of instance of class WebInterface + + :param webif_dir: directory where the webinterface of the plugin resides + :param plugin: instance of the plugin + :type webif_dir: str + :type plugin: object + """ + self.logger = logging.getLogger(__name__) + self.webif_dir = webif_dir + self.plugin = plugin + self.tplenv = self.init_template_environment() + + @cherrypy.expose + def index(self, reload=None): + """ + Build index.html for cherrypy + + Render the template and return the html file to be delivered to the browser + + :return: contents of the template after beeing rendered + """ + from pprint import pformat + + tmpl = self.tplenv.get_template('index.html') + json_data_weather = pformat(self.plugin.get_json_data_weather()) + json_data_uvi = pformat(self.plugin.get_json_data_uvi()) + return tmpl.render(plugin_shortname=self.plugin.get_shortname(), plugin_version=self.plugin.get_version(), + plugin_info=self.plugin.get_info(), p=self.plugin, + json_data_uvi=json_data_uvi.replace('\n', '
').replace(' ', ' '), + json_data_weather=json_data_weather.replace('\n', '
').replace(' ', ' ')) diff --git a/openweathermap/assets/webif1.jpg b/openweathermap/assets/webif1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2034631b681c31a247d483a3304c0872a4f90707 GIT binary patch literal 232368 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

>Tk1E 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஬g8z83%oh9uxXqw2f3=<5YCtSUKHj=_8#_Spb(yeo_^P$zQ5N+(m=4gTI`bEiP@K}KS^k- zGJMCRHRot1aDg0Y>T&UAi~4)h>h{}k#6m&>)L=KKcipI3$LUt;Zw3+DbLpR5*oD>K zy?Aa^3|-e;115EL4@QCP+5Bn$;**WSH$&zVA5hk|k3Yc841CPyijD{S@R(=I3!w(i zimR4E5wz$S8H=hZL_CQy)(9gjKB+cSxClz>kNXfh2nue1LZ+ERf6O?SuIJ{t(oagz l%dERHy1fzvf(DOZaGMhvug|#;{*`~Y`` aufgerufen werden. + + +Beispiele +--------- + +Folgende Informationen können im Webinterface angezeigt werden: + +Oben rechts werden allgemeine Parameter zum Plugin angezeigt. + +Im ersten Tab werden die Items angezeigt, die das darksky Plugin nutzen: + +.. image:: assets/webif1.jpg + :class: screenshot + +Im zweiten Tab werden die darksky Rohdaten (JSON Format) angezeigt: + +.. image:: assets/webif2.jpg + :class: screenshot + + diff --git a/openweathermap/webif/static/img/plugin_logo.png b/openweathermap/webif/static/img/plugin_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..4d7ba48d35fb61c32afcaeda8b6b96bb0062f466 GIT binary patch literal 76636 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 SlFGyY0000 +

)L$*vV1hX4ayJXfK^sUPf^Rp}q zo=WJN`lIUO6|V?Bv)g^)LUKV*hI2UU^^4cDwxrAENRJ#XvPZPC(|UOUOg^xulJCX| zp8wrt;T@RsoYc>CbeO#wJxP_Ld?OHXIap9rew8oc9<%!A>Z_$X0O@5BI9}wG@+w(26@RHTK?}Ci1^G2=(#>z(=CbBlk23voS6}A1q zp0-w+h&Mjh7P9j8FNsDSH^Dl?efL*aQ+^5H|@Nr$Xl1>d$*voL0 zY>=?Xzdf{8-ln~&)8hv36ziJtMB*b4a6Uz+y{L+C*>ll#-)e0|4Sp-CAQTeU$<-5= z-4r|gnJZmsf|lP}_Je)g26MbN;6H|aGS<^x8pP3@Pfd1o0x7>9IOVK}_Zt=Q1lt0X z1Zb*tIl8jVQyOKJwq+18ouTSm?SN%j=X;W94{vUYk-uGy^Jwz(ji4LXtS=~sCV{xA@L<0Mr`ffY_XE|f ze0J?on}?=74v8pr2_Z*b_OwS9xK7nD^^2(EM12ms8Fhx-SUW&K&ZG3{jd%8EBDyYI zDEsB`fLZmVh=*8LLX5cKwt9B4^d5d0`qs(rkKYQlFUjXx^R@(Do7+fQRy=h zY4daEgjxgW3H~S4c>}0Ae`(Npv_?nP%6Hd9$F(VUB-t#UsTDN~YA=`fYQd-@D{jUF zfr%jS^!Y>Od#?tK@n)q8Zp+&bmai0-M7R$bNQDLI;_=;s0QPhaWp{UckLk;bce)P& zu-e-`9L-rRUX}A!4?c3g0iVFXkK*kizIx0#d7ZvJNOZ0gLQO51u@a4*T_X&v4|xUM zajDjda-#Wa!9FM#O~#ql9qiU=538n>lx3r&1h^VDY|I6D&4;CxVIqfO$P00`>>}&# zhN2$=#H7cj4Fs*fiD<;9Vd_rYpb^X669;-5uX@}@mU>UJe-`p|7V_LzDoi(_-P`@Y z5(!c#m{yBthN202t&9K_rYz4Sn1+My3*t0-XjjA~3Emt$BMrs+I4Fk(tKiGhbM8{C z*p5Zsau`u)Ee5z@`p1_hH5doJ-!^Tdj}ohX{TH25tx$d3)v*HdX;A-2+_8|7Y&gW> zXU}NDv-ZpIPmtizpu8l;l|H>=2Xh+D0Mx zy<2^zZ7f;$%KSz{0j(WtCvkzao?==^8V)~zO7!3mC~Xn=h?EQ{w1IYTyTZAT>d7Y@ zYvt-9H?jHO1@v2fPyBwtb_yB@f|PfXNk0m;xh@<@0C*=hc>%sAcZyi~B?vedu4I(R zw6K%9-?r=C`jGC@G!(8Ub}D2hU8`;BsU^G&gyzJFPxn-2Ek}k|)7yRAq?M0-!YU^T zh*u<*2O%Qf0I!l>`Pi>#An7R!)%1nDAPk?bfbfg76yJ^59;ACRN^ZwVIum5l3i2XGBe*sw?D}(?5 literal 0 HcmV?d00001 diff --git a/openweathermap/assets/webif2.jpg b/openweathermap/assets/webif2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ae83e62ceb111882f000366fe6a03439df3d116f GIT binary patch literal 130994 zcmeEu2Ut_vwr=bdu}~D0SSSiYl&Vs))h$IfvO(!Wwjwo#h;#_awt>`aKtNyvDj-4# zkrE;V5~V5ukq!wEiXbf{p(T*^mZ#iz@7d?v^4|B|_kH)BkO?1ID|5{;)|g|C@sEEl z$$(@OwD+p1g(+ym1`uci@B@;FL57!YuUx!gZF}LU*BwpYdmdg#gU@Q6IeIcEz{k() zsKr&YqgQ{vVs#J!-68#Zm)xOvm}Q3Gd30>?p{_ifpK?Ciy@2W)O_JMJ%|{UGV( z_7j)NKFHd3a+Gy$-+#Dcr=0x3LkcRYY9~*r>+0znoI8Kv@{d? zja>Txxi)UzylL~c?{aO}7y`6S`!;Vmc6RIji#FSC`5!p0{b0MyrKFc-A9kG3vE|6# zzTdf1PFZ(Mh5KE!KS}nV6YSytk!1fO*#DM`4%)qG190;;?E^tUqU*0>PlEoN+6J;W z!zQx$?1hFpRG%xumpDbfRoM31kgJ(Y0`Erm|htCx44eD&-9 z*mgO-*OJVL)b6s(Dw-fxC4?ANe3ZR`scd)j8V`94o%ZR3a&AdWK(bb**0)towv1m0 z*GQLuo@9+mKS(^1XSP7!HA?TK*YO`NkHR8i`HuvtG|ie3tv@Z`A!s| zhnIy{B%lwEp+Y+_rve3*fG%H)lYky=$MB2Ks|jDSjtN_=uLS(z7<9~&4;4pc%S%98 z_ewzA8~3f(F4HfsCFaCV{oxqq-;UzV*WAVE%IKvd#d z^O@C7J530F#n5~K;gvW`zcQ5k;i$(gF-`LhlfTs9?9o$2$~o4B*K#*>JH&Q3g%wwL zrk~EZ*%|Yt^Ja_iG;^B-^rici1T>^pPVWI zQLMBqv>ttn6PUKk*qDDg`6?Fl@3-HUbwQpF{T-e4sY(TJX7yV^0;8-O5>RM}1k^&Z zAJdChH!TT!adYgXp?Q#ut!LFy=YMDJ@3qOKag|8OG5nsT>(%ET()Cj*sb8H#;>D-< zHBCVYisoI2z-n~pFV*jm`he|IgGx?a^`APE?f79ahuQVJwCo2VgdeSzSjk|L1|%R) z-x^f&$Rab?4lH8VlkICCTw2K3$|f%b75%QV<9_+Xxz9!)%dY&u`#BGx-HaFY`6gxC zg~-+S43J+g-`MARSp#8Vlhx^*x^Nch8bNzpyma)BJ>`rK0y_q8&0LP6xx)L)QmW+gccxvz{$q>`Hrw ziObQc=3_?V+I_oZazbwdc9)bb~9HmMW5gY@-l&{dh6)?y;307w} zKU_B!VJ=GPJXu^N_o}(?q)~JFFM=*`Cf?!f7a5x?p#O0#DlHbo1=E{7v19GY+tkZ_ z{WaWc*6tgKX)qOsJ}8j@-Lu>v0ogbLF7>D0C9hvm+7t*kF(r>&>F@gam8o^DJljBg zfw*!$Fz>L=Gi+K*k>!Ebcm<8YKx%9!o&R>4e#aRag*u&}e5~}eN#~UM!dkvq)l&i* zET*;~_lCM(?>5qLAB&3%L(J1>3StKjxyR&tGc?{s4l{7&dS7QvwI8&opIyEG>`s`h zj6)veLFE)blv$mGvaP}}vNE#ZPGLE)bkc%|If4nVQNQs7^0Yqtd{25!Si9^r`ZzyG z!JDp+^W*p^xX;Kf4GoW2sDARx_c5`v8){=XEEKcsT$!3WP2kHqduuBmw+m2O6^{P z=RP+!|Bi1LAp+W`OS@h8$e=8CqSP zU9#_DX`a552sO@6N}FiIwk6~-6#eX-AKCNak$KKA3r*JJ^uDt#DpOg9MW^k6v$Erqo>Ysna$6DOzq;>Bu8TZC_`PdAjA5Rfda`vd?iRMPE|80uC}P zz%MSW;S%u2Y-J;-52)WS~AKWo3%+jw`AV> zir~H1$rWCMy72p=i%-{0(~5TRNTM-Q$H9Hvde==ixLl2C_E-db2U|-~U?Of^uy|1& zEw0gx$CD;KJs2c@8Zq1P(#`nKX9KWj-`lvwjA5hKJ=m*X1LhP=UzPc!>zMh=be|6H zGE>%=(x2|l2>!?j#%W-rbgcLhO25}ISL0k}Z3xkf8{G>m4ID_P}^2%g=b}AadgwU=zX4+uSm?l`5FDhtMRPw!o z-dOH)AtN*)5ar75(O!isIb*3+tTlH8p6n}RpnX%U`8Gwq`gAzPd!{cvyfCLKOR5NQ{%*4cKUV;G`d?Ps zu<;$)*xkN6XcyT@Hfa0kU2N9f5hp>RsCZhJx_8jG@Q(K84D_K!t`eDKABeqwnl=3a%W1P1m*wahy)g4c$#?0VhJ;CH}uVDW$U}JN*HVVSCYc~ zex21DFtIw>@J8s1c*CtIRGVSu;{9C2_SWn>LARfI_^1`>L1el6KIyPTGJJw@!B{1XfsqUcLsj9bB&dN#^PT7B;{ZOn|Qq>!&#g+B` zf>a2-&1}v&NbM{=l%|ot(pZ)*oMjAOV;nvyAX9wV4YVO2i*TLKjb_ZLNzC!)7%nI@ zub!e&RnsK_l^I?10y=!*xE);}A zu*EY!QU;=tuysq8Fm=;*;?x&`W#rQRwJmCA3q~^ zUA?YnlgQ&6IDqY7gBUgBQ+AS`e8LKToLO{PSqnLX6suQfBgd{$k3>Hr=&lgSJ-X(r z79RJRH7RTi*UqF*PlavCIva87N<^7JEoWAKT`j8Ceaw)(ZD6+MhJpOZmByt@ogeOz zT_z6ED(4>J3s&o#IC zyoDvDTWSqQc3tE1Ud`Ar$j)X3G{|R0Mn-Utyd33Z)&x7op`K(P9DvVPa(8W*($JcL z(g{CssSi=6Xk{NabaV{X=c zU}WQO)?3K!rvf6VMQ#lvmF}xp4gRn@R|y*3k0AIu-&}`fOJ~RuDgDTiQf5|AAVuB4 z?G)GGf$*^3>#8n4-9~b)qYK=Mh-QloUD?gB?QZbhTca(oLLXsRg(B zEn}22f3>Kfx~-w^+^q>4KTNiZOMyi;t>Q^&>pp7DidLY?AiD-Ne`lY}Yv~ZW{pVg`bEY+qgb>~{e|M7iBnK-(J=I)`u=!#8aU$mC*A2yack_7Y^-6y3z zwf$KGviRzI?UuoekjTl>mlUvX%$P`_-jdDQm1RF{+*atfTAb|&yYJJLzW7{xcVv4l zxqA}1toV^9djJHD*@%;YsfHpzJqwb=CNC@xDfC<=}oQLn2#<~>Qf=?3G!@K zFms{*08YsbSs5I0KH$D6S$azwLbx~C*=*`saXS$cgF9s8a!-7$A_`bH5_e@BLVLn8 ze9dc5jYFj^Plx}+rTMm3+c5m-bz`}khs}T#$JcjB^lFapAgClrhhJn1$_$H7zIyk0 z^uGzP`tJh9{(7BF4OBR6O)cDuu$qrqSM^;BX`oMbL`X|m4Kuo z3u~z^ezVKRxOomrr^TJaL853ePOy!Yu!>ZpEeh+X zA;1igW7aL*pmIJ__hP2qpnOGOoo+cP0YwGz0a)h}R|0y^z=+RZvpYjXpa0RO@M$5Z z`HJiH@t{)DOK0zN`l+mIl@;ciSh}4TDZ_~xS{{aJB-^DU+lgovm{ZPDuFD*cRB)1- zO0Kb+#m|LLK3p#aneL6v|Gzo8sh%LC+= zz3Z?@eRrH+<^|Uz4KBOj%n^aq`RV+sp5WmIL5EJ8Q!O<$E4XhB6URrh6xhwutOt=2 z(EjQJESrIr8aVrc^|HO^P&;YLa~QyOcC)#ga`}Z=@Uq~$yr(c@*_5N0FBA+%p9wg- zpL6zEW@SS8ds(s1!oo1pzcKkP`g0Muk=I!5j-onR`z~KYyyub*>2owqG+~yTnwpkI zo7lbTqq_?cf<&rj!GB>FGKqDqdNnKyIV(IVcxsB(TNC$Dp#>|rxQ+jaSop42yzG}Zw(VfCD)W-8ZHRGD>d}5O3f1=>i;+9 z>Y#rhQ`jl^RHfQCnLgw>%iK>T>Pa7T#dxlH!4mZts|idm#&Hr4jU?NgWc+1e(}+&HzGL?4DVX`)b zpJ~nZlYr)_WD=I^Rzp$a%8HBAY799- zuIq8&;SH`f_H^Ef2i=7vVvpu)GEopzd0)c{F{O*X4H(-3jO?10!Zm^Jrq86+s6OW~ z=uAD~qo2uw%RjY)(@B$w#yDaY-}jqPhxD)Y^;aXP{fqh8sJ{!NhT8yoh)Fp7Bl=*4 z60=#sBxO%Y=Cw!u-Zcr&R!jR8qJO7N>E0z{f~o3jm=HFK8UETj#znWFLfkH>QS_#G z(V=w)8B>u={vM_O^wc}|pCtXI-md9OrM(4k4vK)})w9t`1+6*=vQAXfw1-V@mC2&+3OH$+SN z1HJYZMpeU$Ej$X0FXaZ)ZX>)3#P8bko6l-4;3)OZv=oHiqa7 z`?H1qV~2L-t&PA&&?qKCVzmX>3-8j~Go4HpriR@T1Q#%$+&Mf^EoR2(S?>3K0ul)`(GxV#MCjbX5R$#&l_r<)JZatemsFkp@ zwZ!A3C~s!{;G^O&DZsOM>rz1=X`6J*nJ^&C>b^+Jv0C;;x{dpfvo6Pt{l*7WJqo3oB4n=({rm|*BQ02RZfuZv!kuyp5Q z^e|gO^Q_;7X7PBzhPRRF3l)BA@CW>`F$Pu%zOBjac<{6By=f{EkR3u1gCiwiq9+B+ zN!)}^_>H%{CdBKog*6E%Jz(%dtKBi0untA-D4XkdJKZC+tPZr*W$Eovw5@h+lYmy* zUDo@4907N$V6?@S?Vf%eL5AwzXYnPAb_SuftUg!Wlp3gcb@h%}br_-JY*^`uLs}k$ zl}^NZ4)I)bViFHiI%Sk;7M<@(9q^VHWzcgyZfWHVep$&%Fa~U=Yo_+23lOgtmC7S8 z+d0Z95l1mTx9|0yC#<9G4R0RqZ{p3ZWv!x*Tkk*cVy^6njtz1Jp@?2U@~p))OU=p8 zQP?{+a&vwRkA&co5~g};>21?!yGMcx%e*#uaFa}KgKPA|6&R~h-?>}^u5g3wNaCWX zr&D=@eizQSjbTD*YkXE`7<2G!-KC9+C@_f@XKBC zv2NQ5Jw@FK=N22+!Yo>Ewr#uWd=mfT-vd3}L!bF>Gkd3Ctq@I{T%?Y;G9$3$%+cE1 zrxYMz#2h2s5PE;WAG@CZ^4ZJwp2dz6;|2m4Z&ASr`;^MUFh9b3s2j{iHDD!}po0Pk zTZe}F%K`62lM@)?pSrMZd7GzHj|EQIRxVyLB7Nk?iTg#uDC}Q5TR9!E^X&Y|^%maG z5r64}`Mq1f7l7+Pa|464Zdh<`~>VMo|X0xO@$$oxbh-`U`e0^2cfr1ABHsX^-LPp6tu0c< z=H}FgD>6TC`2V3+Ih=+!0b#}uVUSHH+NX9~+)L(^Tsh|E=Yaq)Q*?{TaEsL4zMs01}$d_1|YPkK*B zc~F0d^JNe3l74LoC_>Z=WFmQG72S6OX&PbfNl3()ZJ;{aJ z4oW}p#foH^w^`cQAE>nZ?}jM{OY`?5^Tj}T84`8mD2 z=UX~4;GhSTOwH7z5uR2`{X~+#Qle$e z%i?3WvxUXtcJz*_iZ;0p_By+K^P<=omv=Uj- zR(!p5x~EWtE{uQsrRZQQaDz{Dnq9rHv%NFRCIZQSUb4$TbVf6_Q!SP^rsX{}3Qrvf zl6gkF{Rbk#VXp2s`JLfU^DL zG()zQHBm>GaUJf*n4D(_4XXvc3x;d5_VO$1*n<4m)yG^wI>F9K*jMkEQQ^#3;l;6Y zNR-FefRQFacjNL;rX_vyex_z^M_|70uUz&GqGg_Y;n20`p0TP)0rQmx9`}>UW#NghD3PK#iZTDu zYCQiUG!|v)Q|RP-b~eE2wDV0{Gx;=};wcT~cm@T-cKG62JSi{l`Qx4Z(kJ;dFhleg zXrFU?f$8{8|8so?O$}ee8PJF>E8$o8F%d5RFJj!E=qLA#sc3`yOp== zr#2is+?n*#?M^FY&ssU!D&Y&UBasemh&*w*&nu$2E@6fIQK_%3u9%ehb}gEFU^Dzgj_2yzu` zxUxS9b%@X9nvF-j9HX^cjuM0?Om_Dn&;yiXN*YA+;+Qw;W7hnf!bb+h4lwSZbAtEF zH(S2EN~^YhN-^#-k>_hTa_z}FE;AQyNcrDuHPFEX*5@Kxh+dBALn>>But24z|!H4^p&=bSJA48zxS(f z!Q)yP9BKms@B7=VyiJVUcDye6yjH272aNxQ-{BnmVfz0&=Ncied9$HD;Ju&1 z4J-?1N7K9xNI-Pv-OzVaA> zG=7%wm_nL$@8D58IQ^M`VeS_i`s)w79dU0+r-{p(7uvJnn2M@bKR=$Joh`aQA0$WO z42OCyHp#aRlP8BIAXG2TvV-Iuj+hp7wtTe&ST137)I|>VIc{rFXd4plr!<4v!sTSoj+6SoNfWtRWYv}mhErvqELC_0@Q19I#SNX&DL-Kj7WzZ8{|7# zyJM7(*70>fAMdAIpdem`E;BX0RXy41Y-w`H$%}Hc*bdkaq1$VS@Lp^k_;I&>5$#~}etu%1 zE$3SleK>FcrBguLoU6{z{2e2-3Zxw1WT!t0JXa~$F4z3om~ktC7Z#C`K>>=;J~+tx z`Sgu!+w>`f_$sDCG)u+72Zo8bm1XR6jnKrA^X^FX@hg~Bito}l&JjZVYsZy$w{kSj z*M1zNczn;zNA12?8qxFP-!SaZOL|^3^0jwMCu)G&X*o;Kd(?{`Jy!T+p=4zE?kxdT zYq}q(jKR{%D0@QFc<*!cAAKN^_TQXNpJfi>&yK8?L)tnQ#B&faP2B6!Lu?NAa2_SX z_73_`_n{8yt#r{Z!%-xI0~aKqBCLqOdsDt?ey93DPs`_h=7V<dEsytc;{YiX~gB2>HWjX8y#I+Ig*EwBX;|LGDxKk}d zzHP+1jgfx;JA}x6JwDRniMAF$WzOYabK{#K>yv#nf#hUNkmp0u_ zzUx1%O#pZVO~O-scT1?Fxf0L;N@u`fu!qvIstl*9wfmLHtc1ElwT){S1_AHEhmX;) zPy56d(yu|r-|4P)EGx;fHyvWu+S#vR+pnLjhGiAQ*&({|$;rvn{i7wQ+0}cfAF-=$e6Mkr zxj4)wxYB-025q~a(x4vvDeL$mDXh)vVm_vH9LVdi>Yn0wGGh3CGHgcGh zyukj+al$T6(Zi{#ymYvg*|6krNT7>4T@6(r!oUNeTbITPAF={vIO2pnU;on%{f4iX zrru>5x3x0f(JFN8hlUmrm(Z>buKIfXXbbYzSCW{GWm_DSI zI>TPljOciZmIrX8O&B=z5y@?D%Fh)kO-y=U&QW=V$2=(A&9&xZxz&`RUt~L3kM&8Q zFT6nFhag99aAsgT86y&qchfJB1+)uRr)_vDEXRv!Shc`#HG67uBs8MQM4j_3M$Z_^ zy3il(9HvXgn*1m*yqcwKX!o#c@@JD@!fmV;$<(=F%Vl-+iiKsJ1f(wk-S80J=U}30 zBRF}D7v$rEd~_jF!}YJ0Y%Ciq7iI6*OHEM$MG{8FYlio?GORjJBTj!ckgHndHpwKY zJ^vj0^2UN#>+F)f7q)iOOOzD{&yGS_ziug>4jHo_@3J_wiRIz3mYSMAWhWpKU(Zz0 z?XwZL;5!+E^v1UhJ0k}sY={nvO`c-8BiMHAV-sl(fUg2r6A(=#aSiQz%o3L2K$$6~LOgCC2_LeK;RG7o1sW}SdCd?9W^Z{$poUihLlYPsOpQhcCj)3sj4 zRhO9%S%z`FXn=Q>%F(0_6RK*h1jkWITx9$L$_~euzDDWSveaw*-1YRe=i!P=2TeP~ zovwr5^pu(9(0VvEYIS5|?gvi$7~CbTj#QSsFqU~Li>=*06&9Dvd-JfInhXo*XYYV( ztWlfL(XF}V@tK4MCOu_bzJXr}<6qX5<1pN)k6-pH+C6L@Lt!&Kk>iXL0LB3FP*osZlf zmJ?DX_^I13Db+43Fuwhxoml<#LT-c$7xU8C0RRv-Ek=y4=Bbi7%rVjfBbdMbBM#P) zi)hSzP1uEL>1}PxQ#F@bG(}I>;SRtGUr!xLyie?R`61?9;D%9&r;s|m( z9gYW(YxgyO38-Y3qDJH}Ku{T?HZ0;J&7|kEIj@*w1uYFtoQDRFRqMo^@NIR~o-WvQ zUfcs zcnUTqt}Hu~K!MD;*F0UT3WyKj;tG(&jjGY(mK^i!`MJ?Cg%us@iXNUkY0K* zqv@Yal zMXOQm#9v69_nG70ejYwfp!rOd+#PJtL4X?v1wC0;wKM?L%ZqLn$hYO!Qa6ngc7-N? zTg7tZ=a)FQXTU6dh3xlSy$aDZ0w4pV+EGUmswAK~*bAyG`iPV8C%(rxc)Qyc7leJi z%MXqIin1aG=DiCX1K{D90U#GmEAZe#$05y-y`gTf?KkA3abNh5dXr-{q8GZ>4`929%4$D4V zMO5fd#RL`#jQl@|*!r%-Ihc&J&`a$D_+tLt2?^-f&J`eqMJaGX9@csg_@pbHd2jny z#=*9=P9Df}3&XraRj(Zv5XEHdNIR^TqQDPv=9b2c&$UB4xNHR7R!=D zXtUIr5wsLI>ScNt#ov1OY;J`?OYRdlIZl5gbbn~pC9YA*fGgj<|6;1 zP|Nz@b%DNU56+(i^BF6)wkj! z;x^`P^nN%`f%&*r1zzA=p`k{9T;9gbi~Ndh^IS|9JztIWM-_z^E_Dl^qInHdi4xFH zT)C7|>o*q*ebYjgW|l;m3mPs@lJEsB>(#(ene#-T%q9VC79Zm83jij#9AG~Mnr?dLc&epZE7zY<1U%BGBDwfeHNnRwENN*_hQia{y)|y_}1P?F6VD@7R{OL0J$TwkovngnuapAgJ^?;PcL-&i+7_&m0>xAgJ^ zBzna#((E$#^&?*%J?(MFYTQZjN-vIkoFKSN5N_|+^q+{7Z?2m2FPQ5)3oI~Bh)9DZ zBg}j`F;Z%`@!`|wPno4EA)G7lCSeOf7Yt(Z;4aU*eaqXc0f#8Z1}Ng?dXW)qRPSfV z;QZI2%)WF9XhW?t-aibWEUX}msjL}zfDWOX=wWpPQ`^SCN!#`+*n2oPiH9mk38_IE z#t9KJiD55(*+TCSH&jGKJfD2xC2$a;bg4QPVhop#S^W%z%FsS4Zw;C>(RxHT0l4%F>0d+{K@o8spb;OEHV_OB(Bu2|U1c^Yuz)1y z3vNK;SH9+`Q|*S)r>BwTk+!p@b(A2Zur7?WaEqM-r&L_BG4|w(zipeFHrt~s-T?8h zH?O}Qsx$xA0-FB2AHAULChR>j_S-~AJxrR<5I_VnzMY?rmJ7^sClN_NJ=_VX{W2H2 zhG09UpBKDJ(QTHw{cc!e936)jnsT>2)clEs_f7+-16i*a`|}yKbtUK}6mj5Dlg7-w zBNnC?*`_|fR@#_{|GaTu$`6P86K8VeiE&Ii_9h>pf=`|fc2kIUPMmZ{R#vj0X{~K8 ze#6vx0L#J+1TTde>-baxKOk@4$*XQtEgK}Dod?EvqMdyhU>b05VCo<9BLOA| zF?R~!p4f#;$<7>Z$^Dy8k)Z+a-4rFSDy|qGzup<=ZbAb)2OHd#*k2!LP8vABH~r ze2S>c9mnqAZflSNk0Mz#I!@=g-Kg~04D&U{yA%MyoZUDZ-&cK2`y(cleeFoZ?rDqS4oJ5QLB zx>m9cMaNyg3|mkvJi$=Fdy3d;wcV=^Fw&vjV-iq;_*AIj`^?s1pY>;KBv<|h*U;tW zW&b0enah@#vstuZ0TFu_qs1Ht@+dRTw)Z*e{DgwgB|FZd^?2RsmQ~lQ8Zobe=m3Jz z+**z>Ho!R;`U}9qBa|M!xj~e)r%Yx`;h~kdJwwWSX9*qvAj2_>V8WhY{cTL(+3r5w)$EYNj=I&2y1{{bp|F2J~ttd zD%VhOm%Ass0CU@UB=Ys$7B6y0dIi7-qQ<0$2<#HZ!GnVLXw~Rue_vAGjebTP1d(H=Aupo581_hShkctj}x2=HE`p8F5o^g=MaR) zb7Z_nX!XHLcYs|5ERPhMXCEh1^X)x=qSg{72sa}=2&4=qa{Ne6#nn!fEdJ9tM2b<_ zj(B6d9FpTXb0~{fCM<-@!P2{`JGP)(pxebtbF0pMkH&oFiM#afJjw5a6aow>??F_x zss}RlIf^z?cVO&WL&qMJ8iz=V5^B6Q%lA%e8c{SK{z`WuLEGBe(6@cpYNVg7MK>~~ z0Jnspl}>b*92)Octrm}v zGN|Fn8s;?B$u$xLSeb1HgvUAGnvo2HiJa8&ccnxr1!F^VNa4jW&D!faE~R}bG!IV( zP~(B>vlm!A3`pFH*@>19eF~>2a1i)3f)Xk#LoIXkL+;vmg*iN;VlaVs!>(>YC;`csU?9hsXDe}(?5g;Q(^u|i zwSuL;MjEofbJS4S{e>a)oD{VomH^Z#A1G}AxOxvOJ9dUXYIy7GEcZOA#eH+RdAWE`l;(9me4cZt%ZHRK zc%5Q{{`yQWrhGUxEy&)(-tnu)5Ky-rVZbc=cK{g^^AUQ_3`qg=sPbH;x7JMy!_&!D zr`xE3pOoW2GdZfI)600}wWudR*njoE0_Fen+<&zNTVsmKKgknjm^DGxxd0vW>PtdA z)Dy;6X=z|4LMt$jQQ;#RT(>9VtlOV0`Ye6$BV9YveD*oHFWO(Co`lXpM{jIcZ@Gd- zV?OAijrsVFCdlL5{Xt>G?CWFgJuz|x_gF@+M$RiodDFldX{zxEv1U0!EbE*F1pNiF_1%a?^5n>{>{DE@^8P z*KEQd)@U1t`JtvT0gp03Dw9TzSJotIY&f0=)^wsQ>BdbGcv%6Fy~D27z{=zl8nXI^ zA6CN8yVkv6bU`<6@H8P%WO~Kt7DM5qGJ;y)%H&V{ysfs=ZI?hz+^Y{JVxxs-gz20k zJ-UbkmOYq?7v#Dm7gho(K>LY+YzJf(l(~^Nf2BwN>%SYd>%3dQ*#TnX{z6X21L5To z=MtpKQ#t;q2HGk1+8U9AnkpZHFD!}_E%z?%5TEI3^t9OmoxT+KlYxe)KvJG z7ogR*=7gSFxW=q&Is#b|Q#b;9F%`dOAXX;8&E}=JlPN9q4-ZU`ZfqA-=;!LcJghxK zI%_Gj@5!)^nKFD)*y<26B0kcaJJx~Ck>)TTp$?FiQJj-+G0MBuF35C1H6W3urLJ4zhpm;90(rWl}`<>Yd^x!e!{l%&D{ z@`u<2u24810bqD)4NI8Y{DC)wn|nfATul-5;9f6k?`marka=d%q}kEz4Kf+cr%F>tYqJ za3)-dTorZ{V#T8-876J@V(241DY4^ovR=}dyW=1sL#rB&f8-`_+eob;p4Mq%6)phhIUCC$!ad_cXJ81UbDgXX+&G=Vq z#y`-L2^?_gSj?wqC|jU}c@Vl>tiXi~w5)dWH8@$TKXO#D<5=(vJ-DL4@h6Dxq?2;B z{Zjrf6la_tqJ+rXmVi3&Qh0^aBmqSmSr)p?T~Jvsc6GXm9d0XbZ3q$Wa9AW9eY7ei z%0;|(a_3u*O@)5GVd2-7%cJS{y^xNPfNmjRZcoKM0OMmg?THQ@rdk-8=lD4xt6KPp zpa4y0t0(QOVzLc*@Q+3gT-&(`(mZh-t0c4%6$I@-S>N{{R`NXxI*ydwH!t6U{Y=7& z?p#45M%4ETyw5%}?+_?Ee7YtPpswMPba{t_LA|!{LpaxHWeNvi49u-(=!_ z=1s9em)4!Sx7~+aTB|aDTJTtVH(ZUY;WB?+mX1NoP&gei%UO}gOO(OYtX-*Xw)07M zT$vmddkN^*FWV-d@7cRUqgU1XD4WG!C`YTK8UC;lp+7+=s}bXhuy?A3r1N60Z)-YENN%#lXc3-lT!3E zwPzU6*vp<39LRfT38=vZ8NHtVq*B1#O3(NIkVli7KJLgk%K|r4;X?C9k3m!cYX}xyAgfwQjF>Z0eUQoGV4J?2QRYlq8eLf2Ev6PKMQ#0-( zUz^GcCQnMWUj253nDyC7Hq+e6={nou-GYEP1LfF2c83zi3!A`$$REhn3Xp`_%lR%& zH*eBvpyea&%DYbJGlAW|?L7DbH5&TX`n~lN%JD~TK$$&G5n(@^X08SCD@Dd@QG-(b zRFdq{1+?~XuQ-ZSs9K9y6IkM7jV_MSjyNc#j_g0QzqjK;ed-<@`m@X5)K$3EFu9cveQGdb#=nf~*Q`Zx797ZJJQ*7=TSU zuuhCwnW#mZ@?Qc8Hfj37w$}6m?UPl^g*9}L1SAq9Qf-Ac9P9UDZSE9y!WGtFZ!mJY z)9!$E-$CsmhI)l|aXAnneM1UnaAQz8lrq0Ta97;Jl-6TDh3#l*z=A@xklNF3%qzh> zhR4!Q4TOEt9q$QOa&Ykif~g0J^cTpZ4na3UJ##nlZ9{)jC?3>Y$S*O$5ZeWVcGMwH z0CXQtfDgU-J3irZ7x1uxNfYH62WMUbQ^qH4Ul@;<>Do@Lb+TigxYUYE8%4F$g_+H- z3G{t(HgE_JR$K$&@?xE?%ICj0u4KExrzV9Zux;MA!3}~ko~dkA|Ce)HAH_%9 zXc?}n0g_({=u9{ceAEZF6@8R%*^slV@2*fsR8+!;H`DvdRAWRhkuoHGhvb{ZmG^bR zBC1;P#0;Mx*hAPpfJw)WcQ9}RS9Iw`A{)c)>k53jefPC*Sq{eC9r-C4GCcehfuNB> zcvRpi;^s_0yvp0wA?CT?aKi}=$kF@wt0uGE>kQ#<*#(e@ zb*6A|Nu{rF9D7*YbKw+V$>69U6^`l~`KyRaisXX*RvU5Vol|=DDdB`RW>7|zh~C4u z;&?UX9PXoft*y8obTJ#V-p=%)^5tvi+?PoG) zAsG=Qbs0%t*@Y_tc;XD6-BiYi=_UagSJSNVBe3UX4zr}vERcX)Fi8{Civ9;g!o~*f zR%2hf`rf*2RQr~YFcz9SwijTld9s&eit z@F?}Jsl@ttFSV;QYP&Ue;?!G+uYBYu?bax;tVu#8w(o%iG*=)?6NL>q)K*gobHa`+ zU_)|1liLvvqzN3g%{uX$X|E=-R2L&h)4lCdjg;k?g_CQWbM!GQjNlq|QJ*tFj@rm) z+x0-b1PKoH+S4aKJY1*QSp+FMRhfx0R=r=tw5&7StjAy(m^eh_59WEXA=ELxln-BQ zn5&Ia;VX_qrBE)5dT}z*?@ji+>+wUWsbwpMb)Z_?1w;hxtA@400+8A`E%tY3Pq!Sk znX`O#X?6ezEuPo^9d!P0(fWV>|Hlf(|E*3o=gCz53+w(rCY`_f4@l|%JbrRx9k7AU zqbkjhyf5>GrPJV6!Jw>Q&6kW>RzL$e`cZPn`d8+<)Xf(=bKSGVm{KSk$ZPqTCM^a4 zwsjN3JPUySdVaB>qSf=%Z|f7{H7v06CT~6f)3MSbS^@*fjQ#ZgyYJeUUl^ioPEF;2emxiCV{)#y zdDe-;dEL<9azsktY?pR3WAK)fqK})2$M9$HW6H5^qkUs=xLh|xZ+KIqfkKb}O;-yk zV*MwTjs^Oam<$(M_1q+>jmlAP=WctSM&^E|;-S9^H%x5qzw>b1GIzh3IOW#y`lRwA z!D*^Dmgn7Ckk{ZR=F!eF)`1A=A!Lq=;p{1N zTfh5+d4*IL&RiddD#KZbX?E;gLXYlRi;}^CPx-U!uB8Qc))Uj;%%1u2H(&iZQb05A zgaw#(Tz@cGA3&ZpZl^Nq=LY@I%8_Z7Cy#RFQjvu-+*2Or&W2&P*LonW)k)|D_A@&w z{|7zumH)-wnFlqMuIt_&Y;6&70u&Usg1D6-%GfGHx5y;YC`y2YkXFVJLqvvv1k&9I zCD1@9KN*J!hY@_pMvE>h4o@>hvF4 zD_CW8)mq>8z3=-xzo+O6xSd&r{CaalM_Frw#enYPE)C&EoIh7vX4=eLV9LLA|HNFS z%J(n*%s8Q~y)%$3o}^YFEGV5a*D=t3-s1S10@`70Q=Z*KO*P?kXGaW{2opvD21#ZT zWIciI9$Uplux%2;7gBr=e6&6~YGkw+&=>$lW~VvcbdKEcR87T2&x8a_FfCq!Gc``l zGnbXUJ{IH8q7Qr&aRmO1FBvlteI$VibyF14}vF)2k#wwk|>p{5QQg($yE-;SLg&eJvw z&|kRILtH`mZ*iSlNIZr1ru=IntA;1$iE$=rlE5z415SeUZBl$&@Vb^#lb9yOd%kgb z-W_2^aJp^znzI!BSeJD&hlxXiCOJM?Wl@t;p3+X!Uc-wQc*@>U0Y|}aFYe26(&GP| z;n(TqWxmdFdWHq`<@e!TlbVd7oJo~E9}5p>eg7-BAkSaRPg(mmN@gix>|A#mSrYjVp%$leypClK`fjfw&bWKKp5#LCZE<=M z?RdIBLF&+c{*gleS7m(}(q$CfZ_3Cs%gBL7mn4AC>0X}}1`S#D$Rb5il=D$T0fqV~^X+Jp#f3YxfPjpK8Sm4boJdq^BzAbscV!E;sbK>GNo^`mKCrf& zoMRl4#Djh%3-vo7T2I&{h*A0NcQwa0vID%1H3#LH1##|fr09*xn8u>*syc?QeFEO~6_tGr_`Tp6=;ziWApukxiQ za#HiWCPJa6Y~D?E$}P=!7T>?&g-d`=cd^#1U`RmlYUxlc)iVscD6V~Ye6YH#u0>o^ zO!UV2`Ix`GWbuf13vGO9nRokcYY!t}8r7rm;PWuph3y-{feXw4XW*3gC?#R0j8yvICv{>88PKqf?f?K95))s4>1>^>9Iyt-qbh#-!VVv1M*LAUqI_pO33~Z zw6SXfH+~2}+MPN*{g*%cZ~vgy{y+5L{@?G_i*gTOB@cfEZP?fR^NHt`i;U0PiXPZ3 zwc#Y;xBuq)i@V7c^)kgDI0>dQpcWha+YfKH_na>5UD}YwE94e{MAiOpuD@6RYgG)0 zIV(_+iFtCE=D%HT)2NmIx@5DEh5KlBw_%pt+?428T6naE2EAV)?{JR)+dsPf zKRhw^&R(f)E(hz1{oVb;4c9R^vSRdt|GNASFh!guFphbq^u*l?&s&k~*aCVpMydaH z`Lofr8*6afK)d!jpDArN|F_F+O?KDc0ooLsy*M6#xDkB(cOSl-R(1W`Zz%cO4}X5$ zpEvX0o|``(l|SFRe_deyTvh&URsM6$1oomoH=sYa*Z+bq!haK*$$w2^OYXDnfNY<% z?HVBZ{&&Beod1_{-Ywu~wZ9umT!#E#xc~pRT!26S{2%2eoKm?Av3)ZX^Th{i9ce8A zaURz$yf@ZAG;1qPc#?wBRPzFXbmIH-jYHUVH6N!q)X3?q8HL8jYBS#6kC~*&Q~8cb zml_7An(1RD@cQqm(ENUZ)6=f~&k5McikVs+$vG(QK3tPT-LF^nY%*Bm_f*B=uXYxX zO-^z%)wtwrs($oceZzaR0NHu>1onHWZxtfXFNcT;+Z_hkDlKZbGT8i@pvT(?kVR5u zhEDoF*qqqF!S7gwui)b0<9(Io@=$SFZJ^Z%22%E9Z%dW>NVxvOv6E~)&!2+iA3gfO z8KW4zX&BF3ALA}fcpd~v;HIwfsm%?;exoxF+H?+*9`Q>zJjSICECuV1mT7(``~X91 zK4(y>epM_Y1{x+7qx`FQ@6NOUvWW|ciROt2Rd;#;!!JKhx)HZ_hRoX|9qv--ORVco z#@CQ8=nri738LHyR$ogEU%zV|S>L9cQT0-ZOz&Kxp-!#XA!aua(vKQ8Z7cBN2`AYP zQO8V)Hg4w&cyCuPq}R<2ryd6w#GuUK7nF7zCRc+pmVUPZOK4(1r~*)G+yOD^W$NXX zt3S6i!&nUt^o-lZH~ew`{O*k`*$}@WYuz7oG0j z(Z`FyGo4u`3h~5aZ9V{_cn=> zAc-2`3o32U(iJ11ZA;fAy{t~4)Rs6aIcxD+WId~(gh|b!wn7z(4Eq!E{Qb<}d&!C1 zl*+f=#}gIvIm_c)Pasd_ySDHEekqGLsz58gAo8`<=Hjfx!o-&6uzc=uh0S^PRBuq< zgBYPdSo=YZdaJdWB>mxsCK{z-IAGXU;xhT8%ek&qNyL-k228p94~R&#_py{HOpFInl_6TSYo*j2+D316w}$+WED8 zBKYL(G(~Kxe(ansK;qQF4uwnrLVT7pZlS4!v$@E6tuT!8r+a88vPKs*?hlhojVBQJ zt872w=Y^ge?>x_EBihc*EiT3%*rY{s{?w%qYKt&fEHm*5aUGiSU7Wk3emx%S+d_K>qOPYf+ob% zE_7PxzRVo6JyK*bnL%~8QGrM+I<m=Ae zzt6jyd@I@Rw!@0i%v=5v7Cy$CIk^>Q^C1TQAPz9tv^GyGQgJUPy@NNgp{(ee<#Xzo z^}Suk8+3_B>37ehEA>5PR{+m|KTC)f@DjtVw6Bcj&9A!;um07pqnfRTkEq&s%!jf# z$Rm&HAF}`!)VW6EjvUo~)?EIyu;U(0~Y(LKc&P?oc$8ld=v{(LC zUVl74JymW}B6VmRUu#}^5bkLDEQ=H60EL~t5bIJNkm*!o`O!#&3wEiij$yc?1{B!zal(<9aG2A?n6L9P z13ij6Fi5`?4$YT6sL2Tu`g}l)gZ#fh)_xUNQ3=qk*MGG% zteW5S7ZF0&h^j+Yu8VB{(H;b+#7kA=muBwi>yMiBdqh|U*w+;HdXYwTzMxI|$}Y_-4hj!+RQ|4~9m41(m6H=_>lIaS!z(hfPl7%0O#= zXFvc2k!}yqM_Jg42LS!5M6;Eh`=+M0T2I`;NQpKhb};46Gl?#;QV&40Nj)Z`w?Hh)f)W#=g?Lw^mvKobyb(MoFQr)fTohVf=P$sFJJ+1zz)u_^YiWpyDn{_;} zb=NeJ;M6V7UB4iDrRo#Y+qz)z{_X7FMIB-H)PFI{hh2Z)H#|3=!WU`@#;@w#KsQ_& zd(&BEjn1C|!+L4UGmSP!qHs`gdV&xFI~8IiV(4|fc*myC7X_s`7YxeVB8LE4XdeHe?>hFkA>pRQM#;NRDvz{OB`0cXEzdt8S;53APTjyG7kyxlGRQC^SHMl_C>1isK`;da6Xp#(k4;K($9EUyu#- z0#E&WjgAHMLh;;HY@nDto7mZcFe1j5J0I`*>Rph>xN=0Z%~_wx@A!dvRz()M8i1yb z>^+;pM1b~4BZpt%$IRJFqAJx)&a=q%A(HO%}wsxDg zT9h-O{Y&z*)}+%$!r@2ZQSmYjEARyxEyXEsP94?J-c#>HnT8s_uI4~(%&t?-n&GRL z2+KZD&Zj_nMOt{Y2Rs9$9gx^2bBLfPkA2?O=$zi{VJK@-Wq7Z4O&+SwjWdz{Xyxko z(pi?DY74GUacdwq3DeAp4x^2=}yjJq!?asf{i`~;Q zbRO#5!e4t0@l;$N5X;-91v$&h!^;@Co2~T7TY#T2>6q%uWNy0uBR4V?bh)QUiuo^{q@g^p1kAkC`ER4K)tw z1j=rltuqv>bhZK8aqpg-JQcS`s&9m^YAaq)C`){Zsx|fFgGi^TZ<%#R;|A9r zlq1bsCh9@GGBTAj16qeh#H`g;22+|D3Fw<8M=!UE1eZoY2}2HBMH=mk_0gymr)E3H zwOTHhCJlm~+zK}o*$NiW2Vifz)DuA@mhn1nAgt=0bM*eMtk!$)7kMN4uhI z1S-j91K%Jm_61S$){{+%w@|7j4Nc}?50@jon%>`J^#zrqENta0xeG zlEncf?~(dy%YPXLeIR4}Wt~?z1I7h?tfpM5Nl1WV^}E%B&3myLlAJP$5`PRhc2L$R z_;vK1h9CU;2JL+d9oGmJeZau+CXNfIc^jol!oU)nP8VG3ohaU`^EPV%Rg}=E5Yb@y z7>Ez`JelM84n2(C?Dnv>MJ=ymN1Mb0P7;SU0H5>?z^&OiyOvmOrk6ZFAgr@ni-|`2 z1vYY5^rJ(&XHf85z<>b8bpVoLiEhPxf!J!MXjkwW^{n*ynut~XK5dfkzruIVt+AZB z#4hQERr5?x8!zChfPmmvnXc9;X;T%blfe7>t(5c1=b+l!7zpiK`;N?7D>h{rO(%fY zzFMy8k{hlQCR~5;xghyXn%~JdB60WyxTjxC&hMKaEAJm~S67d8s%V=zuGq9gFy0Uk zgrIZOHcDX3#kI+O<1-@>E@6)5%Uk&uV`8+0-m61?P<^anl+sT! z2grH1p*>GXJ^$}RxPRt=@4w#PZOnX0nj*NoU=)S0A5j(%C*~evyAr&fUV<*6fJ`tT zNXm7{6sfH;2W}3*`+k#O0qH#cYyZ%Rw7+J@%~#d-5Fj`Hr|9oXx4}Q)7XXN0hnWDq z9T9gn=l5W-Ge$ML)yEdSR;iOv3f^7rnVqf2e&q$W`>DFBZRT)I)=?y$F}A9#->$wA ztQ6?aSF$=A!nx6y?R&Pb_GErbF2i%o49ul!$IJ-mvt2ev4I;F+1#c$ZHzGU3?8g_~ z?80J;xez-8W0-^1M~!*aG=Kj9%@XcnQWwSU69qkIm7Y3(t2T<=Y$ zyBRi9#*dY8mI>PY;E$#}^^cpArKU3Fi~0n7efrf$uU5KF&>!_4Asm-iSG(7dtA6I1 zrSJ!KBMSG`7Y;j7WCjOduF=P%A92d_>@)2*(j_J)9#%L>d}~geR>RnjB~~2;!jZAa zP_MalbqkB@m-^}rz=NH`jvl>_3kd7i@KBKv z=ndI7=8bVsr2LYVgAB=5wkTyki{1n!4SZ9o~jZ@>V0^aG%!p4|fH58GI z8|k6}+}lXPN8S;+y5MLq&t-TOF>MiMs)nhpfH_p~E;m^N*dcq$3blu4aQEy5sEl|e zesG)Mahm>P*N1W1xZQ814kcU*ZHkSN_35RbucH_+WwD|EeNPoJW8c)SH@Rifldug#=-YY zGi-5RJjB1wbR4sT^#LhG{^%!puycuMiG%7CLsznt8j%{ow&I8B#>KDYGs z9g}-$A&WvVj5i6VtCD6E^mt+#^^jRojWqB_i7{f~1t+%bcJ1*IU?v~cJ3VlCA{D3r z(nVYB_w=KJfkQ|Q00baEhKntBtqpq2W}#}{A{q>H7VbZ;Hi3|P&t%$w!azkU27?y8 zSED@Ii}n@?J{4+=tQILF^Xw7})>uEHF8t8=GIP>N6Gb}BiZO05@AhKAv)yqmb}dT_ zBe}O@R8JVH+WjMJ;-5eJ=a5Z~pgW3oc}o}gV=cvRE%)(Y9AUih2YOBh^lm9FdimWG zeOx`uTOEMn`AS^*3}R{bdu8V~NQU`-14v@A?{U`g2|L}C1GXmEsyZs5He+S8ncTI_ zzkb!Jrmc##lGHw8x4rVPHh3vfoq(hgR}-eIZ343v2RS4QXVW@r4&!n?33;*y$XJ5s z>$EDABp$DXwymj1em545(oQ_~X33`hBsFP~y0^Ops=nXhDU|gXOUuQQH=r1;Ptci? zh!bVZnjCooZ*#@^wix~kJ>tEK#qWj3n#3>1$c7+U$oTa)q+U*#B{Di@wsdTWr5pMZ ze#!%BilV@mjMyy|a&t-TgRCx%_DvUNl39N3!FN$9w&WI?mv6>TWU{LfznD9nvpk); zCSvz-upRCJo5z#Q74)Tz^s@9b^%9kb^swz?4{<=n0Tti3$hq4US~+jQ#%5fE7&ktE zPB`f>X0)SyVZ~|h--4$|+#Q`hdgAf>mg+B}PRY+(+Qe3{Fg2RJ2-6Lnx`M-Topn9K zAz3}%1{q!C!&LKWcXTZGSKO|zKFNbF_b>E{-@?Zyqxy@)ZSGVl@k4iT<@*?y%jg5| z>H)|pc5nl=2RJf&Y0OMTa%mMl3*PW}#jf76`8OXS0QC>+L9jzslRrU*qFT|54scTJ z^HX`OT8u$TmuQTKe#+#cMn8S*&>|Tcez2&VE&3L#|02pqMOFFY8%Q@!a6u+@^g|mT z*4^UB8C5nZGd1a#N61iC41~fMOe?BjJ88_V&&-{W-6LJ@pM=N34~DfVtoXkm zN168r=fEIR;GDX;Is{ccKGqu;qZ_=;sb<`2mu@^UALYh(3dzq%pnGahbJ|`!PyTaZ z`-j1j|Nj@ZBjhzIt_->Ucc(hy-<;}XJhSN6(kXvIda}X&B9Fn*))|mx?fB2zc9e=&qz(?_a!o-AhR>o!5Yi6~ zV4jm6w-0uiwUqcYV0+>`*<4i%i*=9i{c;Tnsw%2HiqyDtQrt1Xw%pCUo$A*NrpvGy zA?Vf9oLeLyPQV=9JnFNEt6dOj(=ml+(jr1|+zBxy>Aj1GLt?D+wGq>WUhZ|5yyfrw z$m!u3)kxFr`FFFqG?bR6bfnoHFW8BVFe}xlNvgr!%nf%&%qoVni_@YQtYF6NNnZzJ zQ3AFTmT5i%&ueP3{$~Dsc5Q2nmA(FZ)3(@{TJD?%eQf`U>2`x5n#K7`9;ZP@In(a`jb1gn?m1I;69e+>0>D`_-1W@J zEZ0qrVkgx!g86XM=Aq@$6KhF=aq-kEf|sYab971fT7I-&)5Ev{v+CFN_QM9rv|Nwi zp88l`UNw@ZO;_QgJUoU$WN11$sK0I=7cgv8bKRAz@wzrlH?+P@Q$J)y*B_qEKxb3L zaXMm^WO=B{1MK%$>rJznO2S8FwUp4%knyvex09urE+!5-wll`0qSLQ=v@{z5ia=L< zF~%zDQq>4up*xwTmdCBy4B=(Qhk#KNd{PI*qExa^F&8T2+Vj(|V6x6(EMhpl)8zdZ z6~V-FFVj}d4v{!iszF~H`svG!o93Ul^`cEe7HcOVV`6Grd1KL~H zU&ieYe17k)~t+A`8h2&f|Arp9RQ zae8teu?fE(cXK07c<&NBv5Ik)ROfQ2ySUrmU>K>5xb|T}zq9Vuhpm|jq7GU{m#VxDW9JT1xHK?+%=wY5cLRIaTcC|H&k_5bO zqyv`+MV7Wk_;T)?I@_gG+!a1J5xqzEVR`0vZ>w|Wnjm%?Ub#?x@&syplebz|@(w!i z39x>k<@%DGVgdJpXT#VK*Ybzrc{hZ|(yd21%de9&4KfHO#`;~lC~_{qNouNV6c_Da z7|t{I(>-ECu;}-dZaqMlcOrb(Td#)TH=MRmgMCiAMIopr&VjRMa9TY41p@AOw!=fL z?zl!Z|+(8o-C1FyBC zMf{t!)(G!f)0mkv?VM%DUT5tr#9DM|2E8)_6PKQ={ zsk`8U$}TB^-(SF2i*X5q7kMUi48out$lDFvt&+YB>;NgYd^ZYKS5L*OEU6n#%kcLt zT|mi1vkS$3w~6mZLT;np@xp$5`FhZ_)OT9>csI4i1Bp{r^52To>2Re z-*QC$y#D9ik1w7H(#X@=hp`@lqHm?nUCo6BN6d3H;E93E`jOuqGCD4J)z(A|?W z1EY`O;~6GWcn2mFvDTd3%Zp7C_Kcs8?Vw{Gr_#zPKw*2~fx>@-9{?}F(NBdlSI6bQ z`Yf%^DFREhp6to)#kF?4(R3Aeh?#oB?X^cBHyBr*HX@E8vZQg|U78lGwCo=5xFNX8 z?T|iopX26(WfPm>)O9uWvz~1jO=B`0?{X;doQWnX^{EM#h6#c7bHA!MJ5Ta>f-E{@ zYO_~n#ek+Um8Cbjp(!Ie$!NcDhdh1-klOf&S^!&k zzQ0z`)tn={G-9TdsyE;ybDl>WsZ%*`o)C9^uRq+#tgjGl&w;78)~0W&x3?Tr1)@XG$fd$Z<#>eL5&rymEb%Ul;ERjb@T`NO@C>Z+w7Pc9|1Ka*MXU zEKD6(I*gy0i?hUDX_6vJr1zX-(Ladak48NB^v(>uuWJSZ>H6TJe*sjaBA0L!4bm!9 z#p+hX=`O-G@2;O~L1s3)-ojxE%{C7U=PW<2!oC@OMrurDEZ7r)o@{H}`cn>}qDuE4 zDQW)v**{NVbxPUr*t0!KQyxiV72rTAsYxn>=CgpxtVU?~(`4n0^S|zrWIt*8tMlcR zQ?A=!KcJ|t!=x?yF%hg+mY8!W#|DpKtwTlQFLDGwhh4rbdFitTW7fXepaMhQ^xE*H zc!f4Y?9C32GPy?8D6iBj4u0e9pq$;&%(_j`aU5(gro2-#hxGz2ChA3W!lW*qe=Df# z3K#HUC~ZR;e&y`|pha;UUhs-V2uD#d!&zr00WCMiFWfh>t3M7(-6x%R{XneXhSK6P zmT9wM`ITV2P31sTAujdgkHc|8mUizsR{GALw>hT94Mu2l)*S$$fPw+arPQ(%t7sxM zS*|S6Z@-t2et$;tW3J#kqJ}z(yHe%uH_NuFT$9*oB{pjb9WU#LRy8f~i?92RHFHg0 zc0B~dUM(Cvj(l(X!5&LEzYo&&vr9|MOuTAY*CR`Zn7HN}>Pl2cN{|K^u`3ar6^=9R zTHe4Lu2@W>19eOfd~ZsB2xuA0uU>P?`%}R9pSeV?)IP`)QA-dCgMwOtcsyxQZgXP9 zN5`BQoYTLsPW!Emww|Iz2t1DNS)4G9rJQqg9Bl zV|VCWe8izN2;te3S)_YWDr8SFa8{2q8#E>0$n*Dd(lLR^Z&qEFyOmC-vX*Q691Okj z?|`VKrOwUH65sbSrn(oBLV4sjY$QBZ*e^IFFFDdF2wK1RZZ}bD2D}0&N16ar_K{|r zh2p`e{HehE^iwa)3Rb5V$It#w#e7?V@bKXICNMrw4bhrg1zxsi5Rs4cwfSaxR0+OS z>u5_ospxvn=E~K2#ZUuf=ypiNw;{xO!ptR#VXLBF zjj-1d0{s_c{TQM3+SswLc>&4X;^vjoR62RtJ$uT_8jQx@m5;_9k{gW5m8U@8l6yKr zk!4Ze1r1Gd_8wQa#)b@bR?NIh*ocES6YPaJnD#>PZ!M!+7$7nxtRkw%RTbB2QXPd{ z+{E8sJrqzV+5&Wt+nBUgz|0ylQC&^Lhm5h2VXcLyhb>Wjjxx@kCJV`W(MmOM*g$FL zYQ~PSd#am&j2Mq&Vw<+}756Q-hxu1|ZRLGhIN!pyZSf?91zVV0Vy>hhPSmJHayvqgEq|Y_tZ)7Lmb9-pa@MA5xTj$m#E!Qw0knjL9yT2nMPxol_75) zEi4GNdYk(r@K6yB7qQ%k%{HLBLR61=-U{ylyR)n~Zcw4zGAy@=5Co>Top0_A^tC+e zy(j}0tvJk@hBkz7+8miipSRK9g1eiY=g^nhw0F|4A)k|sgFGmJC`jp>aabDf>X;45XnS(kjwRhZ zFRxrYG6dGgc_N&kd9~=f4Mh+^Q)OwiZ&E_5g4Q?B49zxE@>FHJQ%*fLP0>y6t3L91 z8v%H-M1yPi)iw0S$3T`Lu9l4My;k(K^$8VKsZHA$yYpEH_8O+b`q})O=m1Y}K>8ha zRgpf*8?^r9^EOqCwWj39e8Ivg(WiVS1=1D~>Nm9WokxEnIN8pvcLkNp`fW50V$uST;Q0DmCf+R;<2k3Ew;C-8$yVm` zJ))iGIAb5jYx z+-(UL<&hS}{9U0hr5BzaaZQ>Q`(;UemcAbrn&k?on+g%Rek&(r2AQ2ND^uNZQLGi` zs)uRx zL5KpJyh$(dU4c~j*^`feb;9NJ+Cpn&oa$%|o#osP&N0N8=bA?1*M#~81XQT$EzNY= z`m;y?EO8;a_Ok0kh9-Jf`hMl>3SA~rwxj4nH%+J=B(un#7V>EQTa(-tMRUM z2sE`e$v0f?3I$q!cYsb*%^RmM#p*toCGZ{rCVUg~A`6R5IZyu8#M7!%x9&Wr+W`7^ z?N7w(P;mr4VHKLSRZ(jj6i{@fP%}n`GrE5AU3uP#G=7{r>WvAuBvM#TQ%3Wxi(WvZ z@|=&lLXxhHEsBWFum#LI_%W#`&X1fKkZ465zEv~0Tr)9VP+-wjsM{b#lzK;f|VWRj`O@<#PT)BrYeZqDz8oGZeg# ze-~2w(}-T7v!h?*uu(Co(0@1Uh=;32o9=#+>CXl@H%X(oYU#aEZl4G9hUN-0L{FiH@?*!BfPdLQ(l-nB< zJd=xcCOA^pG!S0DJq+V>B1Z*)6=)@QR6tWSQ#dIvWo}&G%oBF{)ER_jC*UmyWRc$; zl(%js|BIMr_kZSj=D*!{)%eJuBc{YS1?-30i}YiG<%XPK{Ql}V@1CJ(+PnPeR9|-# z2iLL!wn>aLlR9_gCB6M5C*l-DyhBh<5ddP_eD4IgrJKc4ZAj+^*UX1qB|6=kpSzJ!#muh$f=}wfXB<8 zYYr*969Tfex<7s|Vzi9$Og+aOf55(OLSBLq0g?bfZ!)rL_Svn+X~@2kt!G$e^Kye* zqaxi?mDcHo?e}2AkXQHWH*5m)rh1ldX7#bF>WxJ_O(Xa5$n*!+#!}bTypd*~GF;e^ zu^H2*!lULhNN2Syks+%ulw>}O)Q?*QsKMyw-tTXRt7{z`4xwK|2u`7#k!q1yoke)(~~2V1 zXHmmW*D4aA3cVC)k$s-km!j6L>$e!N{<5I;Go2R79VK2m0UH>c#?agr4(70y+N|G0 z-#(?HCVf8KnP=9Xr(1aZjTvb1ZA3oQ3-8((ka&tdpwkxsPVav^xWO}VSkJ=r@ODY5 zov0~o)hH84)08yA$4dUHSFsBs`a#dnq4tnzkMNblj;^zgMm!C{pvpIux~9 z|CKgKPK?!;L4b5YyWyF-Y^ohd)q9uopscclw(8$I}#hG1w{sb;&mmst+(r->&Yy_KT0YKqW=-7jZ?R+^`}l z%UxV?pAN%S06Py-gHqdUc+wfxL&H)EAWnz#dvC1ZMSo=Qf>+@?;I5TX$RFvAqaUM>z*T~s_!sw_hZ#S8`<(S2*bkrb5pJ;;ab)fU%)2|( ztUdptC|WllfL&EZpaoY|)r=mh0T7t~?Us?}|M~ytsW=0v+iVwn4_Ub9)%&zf5%0Ek zu<{2|GAH|l(m+mMF?1^@SO7t*0qV5&Le-57l&hN zQZL+^GO?V5bAjB2d^E}J>JApbl&nprWB3C{-bPjY&gLc3uTR0O1w%{T&CSCVb@l1J znHOR_<@uD{l2oW7x@HD(m?GM^_u#f1I<@8eD)L^%uP4M$;t(T=~b442%bN1S+U!1xQTH#cFzuXNSmrQIZTobK<5a9$J0qPqo6NTRT zq#kYL7Imd$<9(Kg>|!@9lDDdB0kpi9z(!PY2nNWdyiLaKkk)o+cs!`ho7ZnS(6Qo) zP~501MJrEJIX7ix&@hMH`6ZlnfTCIMYIVw9BcZg3SyS}kR16R3snybF$qOy6mximq zNqSy@NS!8=9>><96ayhcr+dw3WRs8(R8cfVxa4jbOPBfxz7anvv>^Ysp$^eSqno3k zOIWJP5kt;&Bpk2UsG%KtHdvZO=^EHHN|^#CX!@NPg{ru$Gj**SbxXV+U)n^@_|!P= z7v@;E0Z;_fr@6;p9hroS#zmw@1a#ZUcAo=ckB7eEfj0DhjS3| zV)Js_%3uG8t(@cD8~p7$gSzj7^>^a_vSK-8$oek`AN8V+0ksV46sxi)W0J{N&31X` zN@SNZI(wI!EtXUn{xY8VTg6_l`M9rP7g{~;1-FI1D7fCPu8$67D4+79ujr8Ac);D` z)4ME$bDbzHKi8U~X37v-*gxpD0DcMdI`-hTD}N5R{&~Z!e>5okDrKDRf#DlELq}Gh z@=0PazBHDBx{kC=IZjGF!!D(arn)nhh;Bg73BFTGfCIXG;pJ$frCZ1py~0kxr1C|x zU43g=P8wZzs;Y@ky%=Ebk~AF*6m2jfx^jHSaxq{?8tPUntS>qAUUz|@~ zhzvtCKu#S7XKFr}%5Y~UQ22nlZN>!q7s=N}4Yi3_%kXX-g@k+^ahOCvxm1@nE{inm z(=I&lgB#hqc|q@{axliJqlcs})+PLcu&aZXnl&F4$Du^ynM0PL0`SP}NL*Lw+Wn+H znLE4f@J2QiGZ`7+il4c*qM!qwn`os?pkx3-As5NG8ATD68sYIF zaigZ8q{xL8Ty=JK6gvL{s?q0sdWZHw?5Ugkr6$+joFqxKQe)OoZp*B)sGH1R5g)X! z40VxxughcdXEx$QB29-8tVd`C7A{^-lB*h#^~eIli~YRo>J$kZYWmn#(@Fq@N~mH& zwt9N{2y)A7lllXI9R;wgY_}BZwzLM&IU2NYk*xgd& zwawU#oIQ>!0rtFRM~^?8$i}t3%>?G^D3GuB4R?HXFpjG7Mcf<6j#SGX(Sj5L%(iVT z2V)GqjBk#Zh{+AnIy43{RyA>ysjr6;jA_xhdt{X^*X^(PEC(O@nBO32%Uqy|{Jc#V zqm*)(s1e|v(w`VK<~T^LT{;{&Wk?IASTa_CW=yR$(44$r^veq+<{oJd47?9feWGY> zl;-2@OkoRvG!(z(a$tQebX_v95z_L?8l_HpME=psQ%+*n2cKX8>z;$ktJF3}qEASv&k9t{Hu$H&D?e4sm=}p`#?bVIK;xaixTv&&$>8Gx1VDIUk3VWf~ zPys_U*eZo^PU1rkhP>t+(m!2a2fiBSl{eeIWdUq7c}tGtt2R5k(N&%hCk!Dfa{jQb zQ|SI`Twr6eImdhnc=5;>kwT+in(#i>)=M(*z)UlJcQ3FpFSVVW%k+Z6y3mHhTb1uh z>=6fi4Ny(cyK-JTnMM5-8&e~gQ!Hno~17HK5nkK^D$AsrNY#3WcNmn|rBh1Gk=09inNCmS_^bylk;|MgMP~F)WxZ&>6 zmv>?#H*V{09{N5AFVJppu>p&>MuFIEpO*t$<@IfAcb@lLa5DUG{bYXQ29&z9M~G`- z7jG55XN=z(v2>|wa19F~@KY}2pm;%volZKLvs*>y(Px=l&-p*x4A~9L)vb_w=GlTR z6Zj~(K(GHpcjd<+J7xJd=J4ZAI$o+6V<9>to8g8WuymSQ(g@z>4R6?UBD_hSlWudv&h|y93J0n9D=!C7o#5vu}Hp)CcJLoZ3OhM=%2Xj^rn3l;O>hx;siYkIndnChzYrSGt?n~! znuA=um?Q2wh^#l&bdM!G8OK6_o!$Z1>0j_0{&lA}{rjCBw=;_1L-}7j{mp;f=}-LK zPJj7){BRiaIep=>bozY@ki9W}n~W$MtR6hN)L#(((h*{-o_#P?>s|SZdhfC?S5H8o zhW(WQvFUW(ISB}c{xswN^O5oJ7AO+JkJB&&Qs zT&fwiR#}o-LWSpV`Bf9z04Fc%9B?{?*}OjhoLrwzYrze?9FKS! z0MbVf#_U^#b)Bp1ozS~#C+Xr>f&G-13MGekz4}ml;9m3uj{#1bGQz~x~s|!`fC)fLyQEUX- zoMX~)ui;2?Zt5Tkdwb zG{zL@*@hh%2;IMx2KCDJODO+i$*md9_LDKqetHYQJ#Wy)>0XE!LCNzUe5VLjdcEiG zd2hTiD<~}=nAQe89qN{KZs0LPzj>^#Th>PA!8t>Kl+L^ym%XlA?>|IT4XsMiPJ4BkFnUU#91^ zjMNCYJw5LoVK5K|RV$zDXof$CfB|y9CKKMr zaU~>9`^mxwAf2j;mK#YGeE@G@V&|862jtf!@f}mRz0$ipNA&I}bHvTY1_rs%xyAh% zpiN#r;iY<$(^LW*>~6|n%#V7jpoLEE;oOTyue(y|RFrt)QiDBj5_}j!`K|=@b-`#C z07vTlGa~#yM1)`a|NJ=-=!vb^upPCfS8euv-nQriU}b?ysI$OVQ1m}5q2T{r3FZBV zO6bbJuY_U)+b55{l%SJVUDR(-W#If5oNi>qj;Fmd4#$Q56U;L`v!byl`%aL)Js7xe0%&+6MDV@F2S#pkI=jbOnpNI->D#wZ0D3P_abza*N+bY$9P z1&g?{?A%-rDRTa+<)YTQa1~_)<4D%E*z=r4)(dVoE1~d1Mxp=KshAY|ZoZB=|r)UVrep@%OH5+(ZZ%7(! zkP|ii6+rlk;`Dro<+e3#HTphW=^S`1PIEBa(BVg=V4dU(;7n(m<7SV-sJD${N7*#w z$hWUczWYlo^3sQb@uDf*iV}QN2tiQXgay(At;wcL()KOlT+#%cKxYKRkp2^H0t zAtxQp*KE7|aFhwbAhf&bS{yn*_-(v{1PFUfzBg9q`<~_8sbSca6rOrolX!l!|3Xe7 zx28A5`Qg-tO%yFZQrJgxX9U2bxH(;AhkI|O-$zgWu}it;-;!dc(8^JmR*1`VP7@($ zS=oLaGHiLYy6dK;$GAE!C^hcQFw_w>wGs&D0xSiOyY*Y_$%E2}Dco059N)c5e%vh> z6L)09EO%9DXN0F;;ddep9H=)h0DdmN4^Ho;Npq2N6UoZjfls_ESnS%i0d;AU8FR09 z(0)KN&P@KK^fuf}^d3R1zFqSkWZIW$8izdnTIQRBD!ElEg1rq&Xv3X)1hDk^G8B-S7@=bGR5{%z+z z=lF5^LmMt%BVVgkD`L4F(nl`{%#^GdJ*m?0$UJIXiZSD$OV(%*6NIACVinu^a?emBb>aEMMmru$zA2 zT~z`kyD}CzVfu@mXDxSHBc{v_i>$Nk%<%|{L~MI`;BiQTYiW8AF#ZMg83_#Gt5t$V zAnz}2t4vSXIST}$?OSF*R?w$p^G_XgT1&{9(kMy2nq?#Qp?KC_k!MOb~II+fQ=gEvFb-deN>#6*3^BPKM;;n=}ss9 z(0IC$5NNL}e6RUDzclr-h-dNZ1;z#m#APfVs}ffY7Oabv_Y&BH>l{S}pxK@9_@%MX zjB|rJtYr+3c3tv|()w+|)qc*vGy70_kP(xzQ!S>p?~gMQBWghn>VY&RnJd_Ep1q#* zo|LiRAI7OqOg=oRPvfbsYfK;&s5lG|DM0zSh}oeqlcD0h{#NWW029|%+eP7_Sn0*s z92W$_dL;#`OJ-1&4!TM$fps5#5ta!A{_H~B5;{JsMW76Y{pt{Hz3kmjf~A}^ebz(@ zj25$S9;wQMG{2oF9VE9lpXc0f3K}Kkx6;EEboMug@~PB%u2c@&PM!buYDv&zY=@{%QiDHhW**j8cn!8SbDtP&+Z$7;t4} zn0I5yzewIgV-XeR)i%&#qpE$On+>C`f8L!WLPupDAr zFbEfR6AruM-V!v%E_>!($`)eIg2jeJvI!eZ;kA0nJ%pyImYHc9*yQD6Ro}4qhw%`4 z!=1#HwEWwnc2`*98^_{2`9xojmQ^aqn0nWF8sq&DFj#w8y4&4 z;D2j7^3UJ>L$*;De>|czkWQwgS*YA{8a7rAmxo&|`1-#UnXP3}{@&CS4VQhh6LBcg z`K8`@q8GP0AgBXdq{WVQV|x2~$J#Ki`c(`~Mton;hdB$3Oz6K4TiVQX1U(Nh2^1Rv<2Vk=t4SE%ua2w`RV~o0}=~|j*Xq%Rg zi0KyXKX#*wWe!tnQRySqV(XP>atxjsLZXc3lnt{+jt;t076>Lj3L=@3!{9-!=CO>z z5=1^4{NiRS?bV{a8$ru3S!UhYuM%tSo$1atsfE3ug{`KQ2e<}rz5MZpJ*(?O`!I%m znI4Cs5y2gfnl!y}0vG_$A?9_ivwlD9^}z>#>NvC2(?9#@FO~ySubvx8A*;@laqesWoj=}J~HAu50k2VJ@n`b!m z&x98Q6r5t&TKRhVe%IJ-?T|0Lh+;GG;sK|PKD00Bi(z5K*BL5twH^IOW3g}JP1B?C z?l$iO%w42I+}uJyrf6M|pwZW5<@u{MmKda*A43!jR(TxcPAm6k1`JDn8k}Pdz-vOY zNI;I)XtxCgygsYEsHB@N+Gt$$%AKJfu`t~y*XcS4p=?e)j#e?fnkVsV@w-4t7PUDV zr}8&bg+F}8S)KvBn)yeeZXG~tXZ{IM?>$3FUwK*S8bZG5R0=ul`wK(W!@*k|l=U*b zAcmcYUm%Ung}*FHO8T*OA2^eOc&tdAm^Ix$>&(NZsgpqThJ z@>prh)E%%}(M#tj+=Ad4c;BQPSkG+pu{<&Ou*D5*<;9!uS}fVnVpO{=G{7Nxnc=m4 zOrqC3%+}YmbAA_;a;>52VwHWVhPC3CJHy5XZ;JX2n^7M_FMoFLMVd^m(NiqeqqeU4 zx;)%=N|z>LOjIP*5F`}|vtr9nMeLnoVxqx9m&md4>YG25S3i^%`CWdCVzvf~0jTZA z!6tdhc!IrONBq6@A=kul#;Ij3-_vUJ0oX`D9thU7Q3o75bXp_HOXWR7&!RL{DtIE$ zoRUi3tgIWa6x!{6WjR|)0hJ}5C|yv4LQGm22aQ{(&J7K50ODs2?HS%M(f@>7Sdkt< zSPB3gwQ#Hbc4mFZ{p)Uv2h82RaR-eG{0vFJLmNz1ZMirA=1A#l2MYNuj+&VKxsToG zQ@bCz$GIdc%^{>#)q%bEsD#(@pJ}!TLZBan0_z+t@I8wSCa34wi>Uy$Qk}!CfZmX< z3fUDv>{ih?GWDdFOvs(8E1A`uuX)VfBW-Mi$rp{_%=h4Pzh^SjeSCaK0233DRjvRG zUB@l;i!t&j_Lo51Phrew+ z;Jm;ib{Gv%QH06H26JmgV~!mErD!NL^*IZvY}}c^c)pg|jovMr>hME6J4_fq+K2#T z)!QzXgspfX*@P&|Hlk<}%g8E8CtsyvVi`oNh~Mlr94sx|P{0Rh=T|Ikg2~B}rB%wF zVk4G6&!(F^pZM|PpIeZrOOLieeyD=407IxGf!uGw8W7jux13VQgw2_q9)uxBowSqD=+!Eq582(Ym|fR&n+3iM9*fh*jc9D z#5wQPKIk3$$lmrcnY>UUIQF4b)?+aiTBxL)(?jqTfa9^XdE8^?j0UFDLuZB)6HbBG zA zn{uR6>)aJ`OJ6MK55nG1nR?mE<3+&t@J;pDp#f3MXur-2{Ve)CcjTgS>3~<&`N|oX zaHLT*aOKO>pkuOG$M9RNsKe$7B~VoaL$4RA5!Z#vSwM()t<*)zaBXgT9)+uUY7F za{ys%{Ia)Z?cU=ouP79L@%xQo(U=KK;VHW~Zr}gd*gyk`4=Qk)!f%g-$>aUHcm(CkZG zFwNJIO!6lsh+H&?A1H;`vLPdjm;kSt1DR&z+tBKZ=w+d*H_8Hlta=y#28lA=IboXYU??vOo@j}O?M3XJ(Rl8ANh2l= zSy_G9dS?Zn$eAxEX6318m4*$MWaT?^)&O33$zpQn(X}duh_k-zkjQG?>lceZFAD>F zR<}Bf4h}D?oL-_P0R9|#;j-V)&9u(5m~wt~c)dQ1`hYY)UK79i2>`JX#kS{%O&_`? zAoj)9h}^&$Jf{S0Uc%1O$0T59m&ZJ2h2PEqj5me&nG3HTC8fHK0Dha|TecW52cGiG zn4a3I9oygK;vo&_2kc%>Nc9p(!kswi4)VXzx!$Csa)ZOzKz8^f5a?-s_-*a}FK*+| zQ{ubyw5!s+mA^A0p}O5Vyb!3P$q&N?_dyG#-0n$FZ~;PX3B2`CNzM&p&sJ~}ILA1l zW_F!D)lc7w){qyEo8;>}u6alvYGj7=0I>Ucn}boo@!xquq4a`>12w~!?`6ged!|1> zV@Qsas$OH;Sxb}JfyLfKKf>YbA0BQbp1Bcealp7cXV-C@RkE|TA8ZW?L(HGylxAh0 zcJ1^polIC(W}SVMdgC1ZtJrMtVY!PNr@SuFdgB5g9z=?>rgRA`oSOX2P1uGCTN1~^ z)$RQG|8J&${9EGnSN|Jd|Mo)EMcGQFbV1M&KgrHsZ9T$Tii|tjknCC$LQysNveMn0 z8?y!m3SgwIIm|b;djgqKCJjsz8opSDdWg@HRDKBKuma!lkdD~!H*2gje{Sh_%7hCF zY@rphvB%a=Y5RpL+I+Tc;YE+8#&m%MZx?|t-k718`bbruL~l5z;KcKf6xZs%;5^@_ zV}763)^j(%5ipA&g_V7ts7}jZCPi3c!U4+z?!Ur zn?)d$fB-+&T1oI4X_L$0)0Zb-n$ed5-;O>~`?#DxZn|qWKKVaT_ba9;PJD&*KT!9T z4Vt&bAXr~BwHoCwZA~kiwn-8&U;EAOFc{=G)fe0T1okz94`QePFBbOlS}FNdaJ@;w;Obtr*UyEB6dG zGSw9`3!~kH>TdVs_r0Q-g!0VI2*{qu#-h7_ZaI{IG-0oyLG8=nXWEAcmOok~%(h(U z6~^5m9li;%e$-=-gTNlcqP=pCr8j#)FB6)F(Tk^QtlNus-y5)Vk_s2ENSE2^p$@bpEKEbD_CzxKWNW zX^mKa+?5;qrbnYwbcKie)|03BA!PBe$bFdCKVhuPp1MHJo^x?%n#Nklvwi6K=lW}SB8(!-ys;*ukh=ZED zG|B|2C?9FPyT>1^+Q%BCJbw(-J^D4*l>(}Z^(5pSJ<@2K-x{*OlPKrsVK=A(#&Yw4 z)fgqIZgjd>3#C>KiO(QF@E%s!yA|*0N+!j7_gcA*!MQzt_X_#~imnEij(Sb5VfDcW zI9)(Av`A|A0N|N>WSDP=zS#fGaszghY|6EEo;h6EZ=*|5ghhA6Ad_=mHT z3x%kHOp|j~K!60QzH0((3=);?84e$sNhA#*B|{Op)Kr=bqhfH}mpG+*e=te+0? zbk&TC@HkQb)(gp8SdHIXh6j&9&(7GKWxXV}e(&7}XCcUbYmww)B4$`2){Q_EtR~P? zX-OTsg^7Mbd*w@^PKv`R*|p44K0Y>{bCt$oy^X0Nb4xRzAIID>&0_|2#m~-&0Wf&C zH&D!RD%Moy0O|hh(6obr0-$Us(cH(W0gmmY>@batlAxeyydZF#;h}f>vhlE+`I#D@ z(y+F9cl=2vxkjEVjI&dbE_Nt&pXxy#63m2a>R<}uXLqSIP18b z@HpqnO6&1ALnc8;r|;V}C0UuwWL{Akg%l0mCr@s_IXpp@R^!TYYYMeG%Q{;WXL}MK z_`0v)k3GH=QB_xb_Jv_wA!*1s=mem2KLOOd&&9S&z?V+3HB%lcJFwBwx^I}~6g5%1 zP5vG*=O$p_1Y{Ua#Bv~4B* z7&p2jwI&F6F~O0)hJ_D1nvOd^y(5Hyg${&?5j#!fxS-+7$*U=DbSiNJUTM}Ns#zgt zd*@jKExK!yMZKbm9$(F|Va{i&b|l_vLn`;MXx8H!U*Nh!p~URP8%6_HsvH;=jLEJy zbODT4w&o?TlB_E8{@jwd^v!RL%A)S3pWWE?4|g-DeC;lgvJbL4_+z$vSbf~1qeszU zt9OtvyU_3@LWIoy%iJztr3tjiZ(jXFCW!w8VEy}jz4+q}r!8JZiVHHy-%ATIJLklF zvPFxgIIG}?dpHsF_XT)nL_)q7B6l$^!7Hl4YPedwTWAsZ16`{9GN?N6%l9+C2Dlp} zy$);WHeU1gq_f>MEZmMJ@<`$wdHCJufE4YG8{Zz3x)4T(&{Gbas7~rQu)}n>abX7z z#=3|+lTAQ;L(m?PSR0yVX<8Jt1~d~k09)IkA%$sWY=-?6?}tpQ5MqlPPctpy#mTj^ zyZw4Jm?GDW z4LdmT!=%C(c=^EmwL(rsU4)9LC_j{7ZzwfYNRGc7D(5>`~4=8R-*#5aiFFEym#7@sO<2MTfhye^-EI zF6lY#zI!wGX1Q0y=b{FGdkH}TGUXm44$$%rC6S}+ce8acm zy;a;3#c6kjB@ZNb}b4mD4>SiG?FX7qpnX`eqg2TYdbaC05aoh;t&fz`hx0I>%=fvsIVL777+=@Mr$)y)w$(lG`afkB z|5XIz|Cp5G|51){Q^WVv*571fDgV;-Xz2o7Px{}xo>z@o^#Hm-;3+~M{$S@;H6z#^ zZ3sL=fnnP(49-U&##<=Ftd}9lM}|2)*-pVB>A-~d@MgY=oFHacgMQ> z;~m@P_j6-)KCufU%MVedN{VUpsb>S$Svpy<)I};3HR!U6v}SrLqNTu6RXo*U+tj!= z{}X|5nXij`)o2bohHUw|La*&n;!6)seL?c$nDgzW&^eYX1AA*E5_| zTwi>~vxl#Z5wx_U>0I}fS&WI*;!5p0y|C0heGxs6lz}!4Afqn7DK1Od6*aLH}6(phzVqLr&f&PvUVej57 z6n@iOm*M6{DD%mSE6)&)UG3If`(SA849*YFz>e!2RhSPe%!NB2&h|giNKxpibN4n{ z%)S6k*8uM|xLQqV`aKZD05sYwFtcK>kv8zxD=eUYffG9ujW;pAI*v?fSAgDIobRmm z9yZF0(2ozd8DhnH_++%rUu~k~mxc+OplQwvEAN6}gvE$8tVsAc^N&KeHXFoaI~M>E z8CgQ;J++H%C8f0++g(DnKtyw zpIbP~QKC)o__k)DyLpGh32b{7cjhqq^c$Id#V@rc$73+{F2^G3%^EI{4;n=X49z49 ztJY(|ABL*Y-=({Bwc30@oro)eY7~|imyUeF9#+4}r*zvDMbDlYO)T#7o zvU(cKE{|jWPGA91*m`<}*9_mTskqPp*gqY<3qzk|)65e;Z3JxVo!K!*++E;P*4*55 zc3bdG`dKR@(*)V#73`o!TXp5VAU(dEfj< zZplvt^bx+lN^V6OEm7w8mZEI<1g%vG!@;vEN5-5g1-|Zj?&liUV$SQQ4v?So{9@*F z$!8Q)tefdM)qJP> z=tG;oHzMRe+I?FYTRt_X{7&YOO?hqu$5xE;U2V@e4_5E%s=v%b4a4Z>uu(zu(Y)HW z{$wuuDW0ztGMbp#PKk=ev}Yexcfoyl$BGjqk|gOc-8B+vHq|7 zDl1R?O^$rK>KpR=*hAP#LZw3|$r0dKFPotl&1m1@Q@nqHz^tiq)<4b{Oq~41>n*9( zK%+Dpg2Xxok-d%J`qaFMC__I&RaYn^H@DqoQWB8a?98t5`-6Tof(YD2g)^nt`)n-u z!lTZiaCIOJHpk+D1>?-+G+pxUh09b5CjQMG>ESe#c~!eGA>f-?<2yp;t?M>+Ui%20 zon@>S>@W>i(1|Sc%E(bPC`Ur>9Vt2iAVoZ$fPm?bsma4_A4=K!113v&&2-PZI80rA z?+1n@)jCVh3?|UD;`jD4NpJYz!6n7x6(QhJ?OWcVw3Ay*#}gIn$uG-0%k-lHJFCL5 zd0tl1cf6Y+kHSD6Cu8OXumw&K{0_0ML}+@%!+5hRXZ&7@r|jEwb`ke6txDu4Dsgu!b z*hvxXt*dUa^IM$#+S^*|Y`!keUkg)@C z1e90xX!t;EJwVeG&nX9Nn4#7oDh`Rmjf4IBhvK&jscJadM5Rsxm*8hvcC51 zx%rc*sSwkJ4BXFwn?yfP9c()dh1boT_YsJ5{Nn=s&Pam6IMaeK&rziHY8c8>HkpxB z8jkag#Vhy2f+HM8DUYVbi7S^;A14+y?90%huqpxr#Y0cPzODQ6d!*~H?vWZ5otb;5 z(MI6C9+peo;=*qZ6xf?cL}O#Fb(7up9g!B_H^48FTyCX+lqYKK06h?(1m=!_t)B(a z-sE)aj39H|e#)DL!a?qUKSH?(J(GDB9l~_`%PGLxJimcopA&pZ5Pf?@?K5|(b5pgW zb-V29x??Jwb~>T-NuFr-#s|0_bx_d-7~vb5()EK8FAQN^fpq}EC-6Jj`|6_aA;*;6!)xu1!H0XB%I_#`Z&Pok$9pEnbwu9>B{OuIvBPLN+e78ot~so zi!=1N)|r}VU2r~j{x&^2>JTx;rsU&|S^uu230vbJFX{*VUsd-**m>mm^z5#WN$&+@ z(FS4BgwS4=Q;iPJ_Yc-4Z9cgyqbrun0{upyS5D`|>ZVv~f|NlF$ z#s2?zZQE3z*%^mUc^wc5ROdC-L8A;oDK@jbCZzsQFD z6LGMF=mQ`OG7~_aH|R0^de@bFEg3^FAp5Ko1;P6NF+P3gTJ==wcXOVL6|Yx?Q)r2pm84-1Kqu33;cmqUD3Z z5bdlmQI|Eaykjb*_ve=zS9*>OG^U;GtFK|F`^{U4i8&kg+|ijH3}NO(%?Z}l*ehKN zE~A`%AN%zmj3x$Wp%Lps;;e6Lt~$AF^rOFPlv+zi$Y~AMj9=VsOoM(z{pr8l^ufcz_}D!P`Z3ZD2&s4r4ENM#ijK>+VJ95-LvRGiv-Nwv z(YR?bqG8XaaJcckFhv*Qx9YUN#A}f;qw)lZ5b%$V?Uo8sDp+uZ(+O;fhHI^)7Iyd7 zz^=M#kZq8s|M#JuIg;0DqL2`NVEvEGtzTyY`y>u#@!+rkPzbps$8K%2$t~`PT`pAp z1F5rzc5ZL+LrQX%(Mn_uAId-rk$aoM+CF+rMf*A0wN^b6M-eO) zbj%AkIu=YU(+c>f8#lGpZHqL+*qfypI=M)*E|x3NXBFlN#&pM<-#(YnZT`vhfE#el zJEr58*rosgBg~J`7t?RB0wg9pA@??g1XO#;k+7Pg)GJ$jPyMes%>U0UqDn2kYL_Q< zAszl>0h0w3Fvb6k0w$tgcCsDRs>g0TM~uz6JrEHzG%wEg+tlWhfi1(4DFy<=497eP zJm8@ds|l8VZm^`xh-(_j*hS%2RjNB$7N&GmtkDy%FnRvX{cLK289zl zbcgghNd@=cbQ>aoAQuHfKX>99*6S$u$0iRHoIQ&?7Wm; zSYG&$-7qcQH67VUAUR{;cE)E^0E@w>Z^w!cjE-Ie@U&Jc zpX-8sIAS2K!DWNIDTITu^Io{vjq%VY(Ny}=+0Zhh6>k5EhWA#BD-Fi9;?^~91=VXq zkRXQ!3CZnR(C#tA;k(4MT<;m}-9t-`;+;DT)jHeT8_klMYK9TLIlh~KC|CTyJ#K+*K$4yR}l_dCOeIBrt@H9!V5p z%UFd9wjG#{21N;>1ZT%5$CuH`@wmN$=Q zZVj)zgZB^QX6u>8;5lc6;~wF^!W?mOoP) z7Eoqf2jsd17{3+78HRwz-Nu=YaJrNB=HGhz|PPEkt z{29U>AZsAH)uX9t!{%M}K#!q*L|qq8QxxLa&nO&bhB<23of`+Xwr8US>h8jTTmFOY zlezqI;O~(h5aivL-3{Fn!CL_ux+);yh$IH_653i14lT_;)!9dch`;ukVN)JjVZU}l zShVlK>u!n}!~!`!OYS3ObU0|!FJS#CD4poC8I>t#K`13>&M#=q4>)aao$RAx zCo7W|L`w3XTmE)xqjzpz09XgT-sTkFh}G@ThkAyZ-oMt z@HcWC=SLfcx4hx@(B4d~4#UVu$is3=+_r4br}w}uBxi7L=>}ne)cuz4ag*I@s<_oM zWKlklPp=Phb3K^>dHLrS=a7-JPjP1rj{1c+n6NzxL@yH<>kB7HWkG|D|5<>Lu=&?o zt}=Ook>O4^QwWUeNPsFld>nmBPVK^|27Bzg7&pE_R{;(VpAnO%#?KkA1L9cSsuBrp zvnXWR+6a9S&Lbn4%?T~rZw%MYTfSJCTR}iOeu31_jW-I++Q)2Kk#`bc7rf73) zURbLKL^LJd>Wb&j`C7NfEeX`s-P}~4yqf7%BR=*4BMXoHxg~MBd=D6*1TJ+6&ya2>Lnk zaY^m3#mjOGSlS&b?e3yW-_TS_XKP_Angy>%;Kp`LgBA_hA3J zYkcvlDgE!$2osa&7s5tqsxPlJ{#Ouk;~q!bE3X&O=!()rTs5Q?bCY*a;VK;l^5Y15 zVS%TX1Jt|huPH}z=>uY3%*fHY3=|1?+Ax3Ql`F-a>~4SeBNLXBSqje&jS2ng(DmAX zJ$_-KgIqP%M801{x&fcH6KRMN%&aJQP)wUZjb<)nY~JkZl8APCb4&T`n7KTCp!pP z=8jM=3n6)#!AaS|6Fw!2>f08-3)$#dghf(AugY99(FXeK5;XB}4-?ZFon9s8NQI|5_4M|v;rIzNcPh3mZa=c2RHsgfbq6=@19pO5E z9B37J^16L5+Rj`X{_I;JR(SdcFj7b<6Gs90ou1^R>iNl zcKdn^NBi|T2mC!E4HKtN;6M=lAb`IH&(%q%`D}mGcy9SzP__s~XeoPcWXEG93r_|0 z%gj-&e80(CfbME54N|T6QSSF@ma9;YS!c5P$Y&wrw8z=!N}tXB6-)2o`^~ETmb;l< zw2STZqoFc#CLtoiE?`_m{k>bIE=kH?Aa;?f&L8|9`lOqyyKsX>3f}A!Pysd&lZa4U zlDA`kaqSZTfyzz_{Z>jDKHkWdOzmNW9;@pe=xVyNF}1LYQ6C29qXEJ}T+%AybArmD zq%z~PkN+p-r~Y%v^!FvxF?xsNj*3j0icod0tGQoIWw7O|{{8K3ePtl0RZu%xZ4sz^ z+jO*MDSOka1+i!@K=Upax!ZQB%fj~yc~_gfgL286Bl&ubPh)BoOEBWHgAMDeTRPEy zDeIKfC_E z0+H~kCFH$r;n{Lp-sSv2QCJY}v|c3ToLVlaHeYoW{o8~^WO00@6`+W;Ro>Y|tJ_^v z?(f&~hJts}E>?S6KP3`O-6^c)DOS;#S-t=6h|#;wPkqz~ya(NjsEKggvc1=hVdG_{ z2D{(cdOdn5o3Qe7r7UyqOr7M}8f?+Er4@{oY|ikfogwzlaoripL#`7#hrV!^9KM%r zPeD98I)rbF;(3K{gnpg+Eqkhuf@tgCKi#@_(BUXA_C|FC zAn)1VUDYj=n~2%Gx!J@O`dQC=8!lWQ%mc=xc$B%(1#W?M6gOnh?-gkTZ0%MW(Jsl( z%#fM)DL=-Njf#T1MD?I7?1LIMe?dV7gg{GC$M&7N)l=F?Ugjy10AC51J#}u}@qoK9 zEIKYdpZJJ#qo{2RloRD|WIWmUf@`Ie-3y>?@&%nFO8BYr@BdwM_fP%dKkQy)=l$*P z^O%3!e4<19SY8M@;ASt>sYoy7asICAGzlSDVK}t`s3{z5IS-9BeOf;l|1LwM!tV{z z?tJ6>ODt&+u6|?^fDy%nTo&sF-~m68ChQ7Hz@}o}E~r=oRmIS$wE$j^{lM!H z^KY+5i#OZCazp&$91|Dn)?#W`TUVv*?oLFq4JQ-jRn-|D)L1uUcewHkhI?Qi$S^G> zB`kP*WI&Z5*MJCoM&0k0R_O%bvwTxojY1Db&mTqEuoP#j_|@@U^#i@|#!7;4D1zN9 za%Z#rFX1iFcmEi>w?`1?0IRVMQ`pKXo}o|pI}j^o9gdJc5Tae@Ozmve6FYF}m8l-a z*?z^1XS%KU^>Hx7!o26GU{+H@2Pt%vUxP#Bl`77&pyYWnjfRz z>1N?BD|)swbpbyTh6)hap&Hr^6FN_9)SH8(fIsrB!|8^WBysDRW?J1sO@zABBB5Z8 zqhi_iE{$Y~v-E@!7V6nG95ClDz$RX_0X`yk_aC?b@zPYimAU2qqO_i3d_Zi;hT*=SQNU)WOKliB-1;8>!R@n5y3Uf;m~w=k8oY zkvo2Y>}cqf3Nec<@siedf_Huy+XcHm+j@L>u7vF{0w;l#QE?Hg;VdJ;8IriJ+hEdj zqj~M2or^Se&j5PyktW4v7OOMTJ&rGz@uVJ$ojgTAX^7RHPyU)s6Q&^iy$Qao)C`E%3;DOYkgNxCd$hmJ-|^l6&9CqIFR8L$<@g zVdXw~Yx{NS>La*i%hw1MpRkKpS+y?{TF#2^dru)R#@AETw}z@^~E@o}8!432xL+L0@axoP)DRCb$f$C}RXYYsE&a;s@=H z3z??fMOt;7MmIWX`mk&#p~jAs*>_O@J@ZE46iNRIWm_vp{6WrB>eZ#W57$@{KuWg+ z2pf1TT5#Sgt_rt0Y@R1zhTG(d?er?cx%A{YQ_GekUo>a~+nRvqe{L~_zaGeqO|2E#21|IrOa#ZcaKTi6xP#}%6h09*_B)S%s2{4Dsu zk}=dx9u+Me6WUJEWZKoMR$-J5^rgBrBT~*~j!R#bkMH;`I6HW)0Olu8szzOs?Ja!e zWBQ0V>uxn8T8@5!vaI^JNjrb63^p8!6Y3bl53W8NP%c=md1hryW@PDbt?YD!#hNH* zslFF3u;lkJ96zrzp&abbhujiy11t$0B(eT}!jMraQ+qzY0MSRc9;67vRKo9Z_bOZ>Z`7HO0j4`bT2W)P~Ep~~MBip2&tLyp@l{Zx0z zO@MH%mX_c0e4W#gCvZpn;6qvNv<2rXDmhUsFb+lq3`8jQOTTv9>wW$hX~#M!<~VKZA6Zw(eml=Pa<^P3nj%f2f0vqGm<>&mR(V0KrSk%eF9AZ*?Q zt`SP(eRFlb8Az2cU05|YH`n9%{P>@X^qbee9{307P5-se{y*(!VVJ&`t&l;8AG}J& zsQSK5L~}@4Otl^^K7zBK&{rIX4o+bP16wthUO^0Pa3Zr?toPPox2zX}Yg|!&$9l*p zHd$9Oi<=Xhq6!CGjQfG~h@R$Gn?vbMYgr1qjbt0vyiR0uYYt#>7jlAyXGUhs&Y?Z-x0Iihe0d`nQr^-A(qezO~Cl2twmK0$5m1ONiX z@Wd51I#Z~+?+a_jT;3L-E4Wa{GBzn?e*!oB$Z@1^fEoII16@^b%p}T16jNcs^`~OM z$hE>r<5)sP*M^505d9gL{xT5E8xiop%(&31>BH&=`s%umre5-U9h8+5WzE!K1cao? zircs=l~H#fk(I`ypoM^LmG|j!aQOH$m42w`0zDj@j~R+9PQ=g}cg#C&qm_*Jck?y7 z1Gmy-cDR^^^7EmQCuqMiOTi8AK*-0a$6;#aAzTOV;d~zwndwUs>`zIz2&PJ}Vz^$Q zbz)0V38d1O8ERRIzK6!-?@{_^)wgvy0Y2&8-s&SaXYV4Sqduq-x28_ftc9C~o$S?x zX)g>kqiX?X^XbV5iu%MaB5l#s);s!`7tTc%+L0G{SWXr~J6SbA1F*|IZf{}5d4#?h zePrCn+THeYFOQ7b10`=(`H!ud=Ki_Gbny(A_g=smjW16bFLZ3r5|kGrR)Sk-c}mRK z*+qja^5xM#x0vKMZZrI4fY^UvI!EA`iuKTND$0U9h_-i7e;Pssnpf^{5JW%N$ulK< za~|;iDK$WUZaIcJ9{Ez9a~pe|HVCt`hpvck8sBoG)i;yL?bd}Waj$$d9CP2yR1=8L z6S)ZqFIy{0_jjtb#Rg5N{-OZa07Mz?GbYl)Jt}-v-P%eDZlfYyAr@KH$Q$FiPYQo8tCsK7{bXj*0ff>2CEONyS3IJnyW%bsY`RMl?cb%MLyyvygCAHLWF~eB< z$N0y__c`FhG=Pd-qoW$&4}2Hg?~`034RT{h#zvPXy;LY|iJUfzyhP z(qtj{@h{Oki*K^-#S-_CthL>9jCMNCmoF%qhD(0x?dv5h0*a-ds`rXgKhdmZIc=>* z^t|_ND+`9t$q64>8&@d})}Yzdav+!o+~^D-DKj4^W;Z9R9Mm^|w^N<)+tlSb55sHd zr0>k9$)@Fe7g+pDyDsmLSoS%6Pd>#mNOum#Sg_h+Z%7CU_th@MGlMKwieU+sfK(qs zOn3ouCO2{B`;;QmpI#h0Rcja_?XJbkYL%#6oiPBeWX0w zp6Aa+%ShY86m0{EY=1VQ9g#YALVH)eEHg8jzrPVbg=2HBe6Twgw=!Y^ib=ne0EcTJ z^3G{8GPHQkV&0AV-LqPf1Qp0S z)x+$v!CQUq2DHr>ZqWE=SA9bD*eh;t(2#DT###t#Q)9(ZFB)gCMkkbQ3WZ`w**h zm}ac{c&T>(#Y$2|*-VKN@DPsV<$yh6V0h;WD-Tu9`s zWDT17?$q#be9&0rg4L*MUwFrYW##9h?}g9M$M1eIu8`lAgL5E4uMFceV1ujv7QZ(3 zC>%|K(s`opE8ng(Un@Xh!ma+?a%S8j^V!$|_S7(I@K)CNfRbgYIbB_&+dzcI*)`|6 zB|p1Vlafs(!`AA^qH5KBsCbsb3~fhwY2O?zS4W5?Yc63<)kZ(XLmY2Md$W6xMX$5|4ebq1dZ7#1X4UR?jrjyg-l z$6_!3p^huUM@9+LL!C)Y*%EiFFk@4A>-+j^zmCSaA@tKWm;+rrY>=WP2nGRYhk|biIEJdUoKm~zQ4mdDG z8B4}eOArxpVhkY%8AD7WV*-Sv)B+R?6i|SW5>zH3gvgKtNJvUXB_J|J5|R)Q5Rj07 zkN_e6U(e}#x=;V_x!tRKt^27y_{HUNEdspn^XzBu-v$?(^&n8zUF&&~q&O3Gt0@EX z4UrgPpbf^@G*wMQ3`SqwznS3TINRNPL*z%^NVN(FEr zbB1k{mxj}QFUo!6&A@*3p!!!jb>>G^+JL(}Coc*ia3%k|aOtSlJ0PKu#)OSg^b|<- zxn9lLc!PT}UIU1F4tU@E!aSFg1BE3 zhd@sjw{&#z12@J==0^suKisY1aBT|zK>uqQJGF#cpVx2aQVpZq?4|eZah7e1_edgh z&diw!SJ6A%jLa+X+xq7JYDHPF_5~(6A24-mV0;m&&E5X*M`M^KP<_`9ME=+%v}$Jc?A7xj%70l`7{6uCZO)d zZRtnYL88WgNrqW+?wzY?XlN{mNd@Ia-|Fc0+;k(g2e|AXuj13VZXOYb13B!l25j#g zf6J!tnF8C3MVFIsix$5YpTG0ddaZNgH}6G}wNj3+ftKCL#0gPSLD{2X%MxDF;1&0q zAk8(44_U?}-P%uT94mf(5pnXSa!Bw>rz_d|i=pJL^!U<}uoVY`esZ+Hv_r%C5{+=< z&g9B_Kife;ZR~F_*=5|5``B zrJ#+la!e<9F^GQ%T;P5l1;Byk>QfmdKs{GTsgXOeOO%R#V&y-- zE&?Ke=DOo&6e(8}Q5EdF<%`srgXv(ev@TOlv+udIo(<8%KFM`6EF&L{r7nf0E5E7= z6K+-vjqk(Sk8A95Vo7(@-cuB}8SwJR7Kqq>BWoVgj>D4SX7yZ5+`dOtArFtn+XwD_!&bxg`4PPlKMbubv3cbm$r_;H2qIqsCveLr~^ z($&Q&T7g5#yHoE@UI4A}l^N#LdYM;-UE&x=aJI!7C~~zsF5h$2Z&U>C&Kqz+9j@)X z`TS+~n{m(VXpTCz2HR-7=QVD>x1zYy@hiI{V=wLWOv;L)(3`qhhpboTgK}lU#3!lM z3-yUl0E#m9QDrZqJJ=sr_0zXMgHHF?Vo!>j9bc?z6lRp3UU9SOi#@yfVQ&o@IV-Y` zFQRsbYIS80nGk>sA~cq1&{uL(#`V0e*2$6zpElKDl5G(?q8noNP7(rY(kJ9u&f5h- ztS#O6L9My*1pyP7_$>+eR*{}XT$b%-S)#Jly&=~jA;FDT{`bSEn zk|N= ztZ%gaFNN#C|9U?62cd&*R2(tyT?=h0_*IkQ*tniq=ZkpiR7NG-TDuNz9^P~$347W! zKMJ{))Fr?dch`Z9({_P!yZQlrRAhdfoVWueCRp*?xP^a7eOpFB!!>^Ae(ALOgisRp zraD$hHh#oTrOAdXy4KQH(9q#ryPd7#i@9tmrP?B6Tez=aCjc@iV@BD0)wU;RkcGO4rVb6~5c;;(?)6H`O-bw!1a9!}xFi9Zz z-n#;)OhCZ!+22P~aHGS6_{&E7ceQ_2aKVqVrfS-yXQ86AXX6gxbhyy~Y^(s_1FpEW z3p2*`zUg$gDXo9L>ba9o3|I0!*lAN0 zOn?&JuETmF+xkh(y@p=kN&x>f6wOa)96a|d@j>gMUq7i0*!SojufuB(uTvN7Zq#61 z#T*0e_i`K0r`eoPhZa$2W3KRAa7=J;mX(*2=hhcFx5q1Jf>$nw1KaR4%U*3(=c%jBnaXSBMBR%U~9ptUDX9aec;6YQenWOxmRY1)TJp(w;O&rCPKlHx;IH4g= zHoX}%BsS~7b=S;fw;r*5E@EbSO$y|sex2qWp^#;+SuHN`)R50c6k_7!%|Zd);FsjXqmLU{2K}u z9vA|rjP{tlTJNdkFuFrRQ1WK;0}qD$(yzU+1gVDu$MO5+;qhLr#Eh@t$AE_sNkN~F zjW8{RsUyO?`4$Wb7wI6)ck)8l6df5NT`f0_ki;U(w(>}jxILN9j)gM~$D-iXoIXOPaDQ})_ z%<6BFoSaxCpSI-hUa54HiS9F9OM6LS!UOCfV3gbg7QG_5j_(!s0Yxkm%>o_1cc;~G za0*8-eWn(<p`!jh({S{Cf#aH8TqQTJvcZb#$J@mDDi%hYL!`XW!Rp< z@&x#A#eM+86SO^i5mu11F>2O!aNVs1mUor!6ZdNJovOT2 zqDbGUe#+>x3$RRnH0i42Bo%@aX$DOmbc&qYlFNWQYu>M2lGwZc;RtLsP zxlS7}m6)`~Wf})!Z>=KsEm>O>h79qkG|97%8DEB5IUG`y+IUyR^18L3&-5=qMaHo> ze<33ej%8a$3Aan3_kr$Sr4b|V$3}K~Zwp+!aRp&&BA;23)T2(yU$TPmj68H+Bg zCD)#WlD}SH%W=LEEJ&8tQfM+nbRVEp_q@7Y{nzynVoW&w)*W+``fMjs#NN>&i^F-- z{&!&JWjfPHBObd-wKKjvVTDo_tBGp?>(JW)!sqEOe%hX_IBbB5r<3E^A?#uH02p zw^63rAHF5n*k+^k+_SUOGfP(4n3~!BAjv%B2|vQRd(X?XXyRQ{LDwHQ>7ANizZh$@ z^NOj~usxH!96bX>3SeZNVR4x^wsAbi^ZX?_bUBrAJ$aqU-6TdO7k)pWG+MVGfxwcE zNUKtLOx#Vx3RIEfcbbdtS%0O4gNWiAGw!SOhLxuP%ilhsYq_&=L1!EJ%TH<-Q{#rT zXHOdD?UWcXI2-TGfI|!m!iT#$^N!-drK@I#fy_L)XjPy4L^HP6tzwZdMu>fJw`sS zj(2X|D6sVOvFjDOE&>h1`0dJ5I!V|Aw_ea)YM8t%YiTDb}%5t78E7#fz}myH20UBJj@&}(EHdEH|2E5 zlTHW_++yHD!hk0yZJq(%%QD+|$^`7KTi@&drG_?0qWQY#$<%q>R-Fghdlqlfujq6}F16Au zfxw(;Pzd0}f^?0lGNg6wzDHUZY0+>tn}vU&_m>V0FHR+RGz0E@Siwb$LO^B9 zN)*%4PGwv+GH=6cCdz_eR^-WcUMm!rV?^hN$W)iV6b5WO%xr!a$?Mtn>*o6*5Y7P- za&g4F+8T6r$rI4DJ9@vJA&8}Ggu%tR6-S1a zJP=G=-DW~G8QnoCRhTYZPixOT;Rdty=bfSLfd()7>H?+1TNwutZ;VBWpVSyjwtpCG zr*7U7fe|OGM9(t0K*y& z#uIIgdLIaP4FGTk3t(mOQ_rbQV1HQ8tw|R@*WLp98XubOd4n`rpUQvarJEm)N+~pJ zmLZ=^97Pu2vFM{#Sn%=RpBL!7*hVCp$mth^kBmAk@OS#X=XlBYDHz-K`1zb+c0`3U zX#~@Oi4IAI(;7Vsdgm)Shi;0@$P6Ph5^|M@0*fgl(=AQCsZ5{&fcuBO{xHhY1W|3g z5CgFqUUV_R^?pg|?&>a%bXlYx#V62L@h^4*U$_V`FpTNgIJc=U?1Tw-Fq*hx>HN_2 z{TL0~54kHEHnS0Y>IXQ|haP7_)5a7|pn5w$c_rhzNzrZY_iRuAeI~O!Y(DhRcOx^| z{`S9Xz^7a+M4|T!exRc^-W7pf;=+mJ+*Bo6%prd%Z{dAXOUBp4Ji0L8mTZ6aYy%?~ zAivX=ikk^R&~ZK$FC@DfY!0Uhk1Hs+726x!8#M4{k$&jn2PI7f%A1;);(L2JYEoAn zw6KT!+LJBqw=Oslul~$2kZ5mmw|&G1BQ*sARZn0gd?>MJ_L$%ZvRCS>rzZQRRLtHT zHY_|UqyA1m8CH^ z-{ne1Au}?<0XeQhUyJSo%5GXfPL4j0d(gQ0b7j#^rUrSAz2nAUmGQ+D*RlD~3$U+i zC~FrNeJxJT2QsD>OMn56vlLqvhWl!mZ0UaYntS=z(CzQ#+D&)&U14#|eOq-X!c|sq z@F;^#_Jf)M?yq2#>%zy)(I41AQteR?UYlv+csEdX(f9W(*iN^VurA&uWYEJ?86V~l z^w;LVv+9>FERyFu-$z3!s$)_7f&?cedqbRVUBY*9*Fz(h15*)M!vVfj~MLyA8hHCBA zhc}fy67w^3z?kIzf#_Vi=ddWa`L>QBY#6pjZU)NbKV8}fH07!!68sf~r=8K5=<6`b znCLr9t9O6>6wPKKIfmMQDA|b@>~m-x!W3T20_?`!>qY2D@>aPD&>F|^7Yl)~W=-FF z)(Kfkx>7Tc@_ubPnQ1(XK*OtAD`8RL5v4uM-fbPHc1lDy!)34JzX2s!yh)UUC8qAQ z!cvUi35amg@{|STS+WUJr>s2Sa5JI#L1ExIi(g-1s%kAFlKInER)|PUzAMFFd*kpm zPw~}-da9^GSUEf4rmoT4+&nZ=upHpYU#F(K1bP4kMM~<7gURr+!8UK+s}cqDvg}9m zZ%gX?r>V*319_qo>p#^T+*Vm_9XeHNbdv#?Bk|k{UjQ7l9jJ_W;`j?r2eu|yxMycO zPTIH>uqnBsjN}cAlz5^}KJ1C0{VAm6nidg982F6vuqo5^J7 zyEv0?@ykZHME0G+Mdb=0rF~K}IsUp-+S{&wq7fi@Jne(F#+S~oq&Yj!!N4Tk&6;M4wz z!H@Ur!7z*Wl>9PRd~JQCi^K3z$zAzv;$)GeT0}&(s7z(J4B7V1mO}HqbL?!d0mH$Y zsA$(?WbIRb$+9fmveTzTpki71XywJ~Mp8J8Y#AT`@4yBmhWZlE5nH@yydW!It4CG6 zU%8reqci>E>MWVr$2N%_}4ES`VrIC_9&jtt3U$1(QKFVADgEBe%r zd|DCN{rsO2$N#iG$EZkl_%%J8=h8&Xk94p3K_ul7tqiNJ{`0fm3e3{Z=!&MU(x{L;t3FXrC6(RHMdN1=Ifx)x(wfS@p=% zNu2Nw2gGsuRX%LV=yG@ON!<=?hMyaTD4my zI`Pz9Nf{^86;EI~mV8DSZ@^_>eW=ktVcea7+wqzHWTCsh{%ZN9$qiPv>wpD=w4RAL zXj9c0z<=*TN!veEcBp=*j9C?V~pcC9vHw z8Avge1N$+GTf!jMy`udNU?*%(&yjp;>^y?;OhMC3 z8UI@WT1!3UJLOf!T~z!wsG|G@DXQ;)YQ;ph+1*Qe2-*vVOkK~hAJ*#lnpp$1 zJhuAHd;@Vx{oT1HH^6{1`By95iHti4rPh&D3H3$U`^&=WNA|Ca5thZiqZS;^JiDuv zueJ#1R5f1V&ryt}Yjq91XC9}D>op(fYsvPkRJK3sE#s8%H>%h4kR21Qxw=^Eg)V`! zZk*#m+>$QvSzfo%?7(kT+zbC^cyUGOs_x7x(7Sel@jQo|x8SxPy~C-$vs0K6xyTm! zz5WCJ*5a?+LLV$rT2?Afl5Kj_QISykvd`qd+(Yffy<5X{HVCv*3Q(U`@9WREHn`&#byVk9uy+RCdgYSrdIDZW*hDXA3RcCVk6Ysu1BRYqRR%OmNh3U~D7LLHF7n6hGS4rqfYT z?HpYCeh)mbV$^MSs!0gSD7hod%=&8m^XpBqhIM#VWz2=$gQ%n$e z7I%o2cd3z4_t5I)O;b~5qan~zh0fFC9G3{z*-Zl7z*d#{t>t73(iMLSSwwf%_W|fUx$!sZ*796FJ#Wu~>b_V0w4V{4El1 z81S3NBG8yi?_q@B@nz^&JQ&a0&;5R)SNGf)Wm9i;FZ^)p-EE#Lfs=97hM5QM?Ej>; z1$GGN<*kC+$&8tJGSU-_^5CuuVfcro9{r1-wCJBX7RR0znjcbx(B z^~e#Z`d|G2rv8%}E$A|*8Zkb#aCe_loA-o^JxdyKCT-LTZX%RZizAZ0 z5+9Zaf*+Xf)EpA-+vG+oIpPhL*CerBL0GZWI|M!>uG!p;oc-@1TIzF^R^v;wH z2DV0^R9;*VqpBGLWw4BC{dOkL6g?(NqbI&K&l%LzNuS_BtGdK8@1YzTZOU_$OrJz_ zbGAV>?GR$hc7>}8qn2xl&^i4~IOiLBH|F7oBdKfS3-dcDJRLYp15iQd)*H2m;Sx_M zV?oS(&babpywZ zUunTs$5SothOg~{_h7-7!R)$?ry*f@Oizl0ac3D_M%-^PtZK|4@hHJDKPBo(*LY*V^1ieul-Ho{u1*a z6mGZA3ir9cE8NrYe+b-^$JwcUXin&I7|2Mz%y58=i;L5D}^OQ+k+UAfHgHRv75@_D9D@YloH)cF#lfS48N z;U^4%)flPPO7LZmylA~Rie;d*<$gr%#vW%j4=^7_1Bj7g(fJSpGmU1YdjkOBjBjBD zui~K1OC|~Fo4(rZEC3uK1Y9Y#2QZ9fF6n1WJ;8eD%YBxj%?b*nwuvjTJi43!+UvIc z!JD2~?(qSi4XRHNfjH$s4-WA_h|Ccmn7T3J8DA^79l2SGuONf<8=-B6Dv{UorU6{{ z^LlNWBsgo{u&W-?5QmpYDDWSO_x|0TCS-Fdt3{{$FwPwasmM=podsAWS#X9o)|;No z9vL47Tvqctou?9u=eO2czkFU>e_vGxaBxxDO1(ilcNua@DCx58O=%ipqSq+I<4W$E z7l$i5CpV^+4rXn!#%qo^@+h$j!|5AgtXv=vRcx2Bf|aJ+XF5KfwPsn~{$6H3*>>yv zE1Pa#A#XQ5Ne)teTzm(#B<7DKc;O$1$5$6SR5q1mMaR&a!;Ja!Mvi=wA+MW2P-3mQ zyPKg4aFe1VoHkv{&Sn@6zg-gP0H}>2l_Az)2!X)%*t%qGNT!ywuoN>9Cu8zR6jmgt z*6p~gDDqWgCK|GV8lA!;(vCa}&8H(X)&*fTh37o7=e>6H#_i5JpM~`BbR$iYj)w3! z3-vkn$SV_2Z7ir-=_ie)Kjw%ZlC_0y=GO)Q5TUN~Gq-J=h{IJJ{RLy(94BNoPfpCc z<=Z-JcW?r4Fz0V5Gc9^5z-(2yYntANBPv8KbnDtUVeE9)YadT755fLOBa765mq2`6 zBHs{M9ThFzNW(*oaA#EPYf~G?IhUoTbrl%KIYmH(bneFi3)e=_$J0@Px^V8I1!DW# z`9lTvoXOf%z`V|!gj6wT8~c#`b|>pA4`!pfZ_^QuzJ*y2+y6b}eDTe{rOFJ$z6b+G zgQI```5%1-z_xDkd0W5ouebI0M;~wBiBH4rrOEvC4GO1J>Lb+-of>UCNdMbc5%sD` zl#XLveUXuA`>!VDh54wnX7qZ*dI+Iw( zG1r`=;P4cPY&#`bpR&SK=zm-Bn#GzvN(8Fe53Y_tM; zJKqAeRiqXNZJAcb-9&txL*u3@uYOp3NL~y+(xfER5wIaVcjsgJ5{%do+eGKC%I{De0b0kv15n zuRVwj$yM!sL-u|P;k8Fr)y@KO_5tJYE`VTW{z^52mV{3C#w$Ll`x zKh8Yy|Co6k|7qr7Z#F$7Lp`XX;x}U`?K9Dp&*xrN_TPJ1C;ryU`mYD6YZ{*~lp8mXK|tuW zA^Z!2QcTKtp3-<8+G?#jCJlc(?!%qDHteD8$uq`&7S(DRyo((O?`zCiE(ukn%dZl zKkj9v`z(G3KZ>qcfZzdZ1L*II)ik zJ_JPg8?}e6nu{ipIH00@vQvhw=MStcS!8hqD!^ucCps5jFKQ*6HZDzpHiS|4VmBN@ z`cc~UXOlJrq zP=*otM2Si(6YK@lce6Nv>4|jDMzYF|I{>J?3tj+#zO_k|V&^zv`zreVWVW{==P`69 z)7|E&!0Ax`IHVmNhi4|ATg^jr7zkL{`Z>+HXtv>5-Y2!;US$USjS8gjYJ>7xOq>#J zAjd`X=r?n*);fOA`AQMnC}uxm5=&U`MgRtu_H$3Lp@3O|B}AY=Uk0uqV(}E^mpO%n_;>M}@;XFY!*Tnd-}#J&)0_N~57P?<&a(0; zb}!pfhhfiXmUMXXLAIqT6dsfRY;)PcbqG=QHv+pMq^Obm*{ZvsbhD=Hxy=#4n(Mi-_J8OY>2dR0^-_s?s{>}~1 zT7Xz)et0p7y9T)4ver8mP-wu#KQiKv4UrZWja&AW51L*b^CM>qKBhvG9a6N??qy+5bJytUZE9764?AI2j*eGZ1K<{(CVa=_?reuBX_ zev0BhR93Rm5|$b_#>CM__63_h^uhF_sLt4A6Eh({h~ZL8)9}bGUN;jtOaE31NxU<08R9VWk)QA&X)&nTyN4Nx40aTkdH`~|l2L#BrRYFQSO1Z<9&%$0(?^QFEOTsU5EB?jB`Wv#t!8ceH%asvoO$jQ31OpXpJgS zgvTb@cmgPg?k3`E|JVr*w7ID%V`Tk>(C`h`z5}^$A)2Yy`A4UQQd5+A?90$);mM2NLOVKQb z>ds}&*jSZXwvY3P4NQ*iy&FurfZj_hI6rKAk8Y+~)D8yvl2&sY*n1RTL5D1Q(`9^^ z3XaKhUAOv;6&*Nlh7YZ`#mPDAy+G->C(~Iv?LDNtGInojF5P&AmPNk}bK~cf0H9@Dbf9F9hi@Gr@x>sjZ~bq2UGf z`bP$g$sYqFirrCmdA`q^Jl2iVCReYlI>x)3M;DoGh(H^aeb36Ds6U)w*(#RWKB;YI z8O%0uld+DWq*3n?0o2W^IBq2Yemzwi(OpSC^q_}OQ!Nl#%^VyXhIZgnxh%B-=1%FH zYQL1SGW8fy9fRN1IpxFapw$5k8s7J-`NbZ<;Z*4{sD!_vYHBGD$g1y`f;TAF2I~_T zuHM#_sNC~D*O5S9d*Dzd1m!=>JW@7up!LOCdFt77lfBzBqeA!pYL>)v=NTsX;N$|N zC^n-Ox(L{U&ZxtfUR4;Kmc)Z?LY?NJ>NBsKKKNejpXqNAnK5JM(2ewCR~YkqRiG94 zS1<58vDe57^R{d&Lg2W;jxb);+D}I=G_0HCK7BvSimZR2x==k{YdW(}=a>h!Ll?g5 ztP}tVC8>7zl+Lj=ceStZhAHU87_qHkZIR>%IRdr(0C4s#N3*|H z9wRBD+_)MW57xAaanJVE7isp!(lttbT-cikcn&x`ctJ5QTQcs-NIY?PcBzQOC4 z${#49#h9+SmO>+&OZ1AK5|=6%T}PwXJMH%VwEe^LyO&-iduD0W#u33i0MTKxkqG^T zbufF3FnkXYK$U4x?n{=}brXo0lik;Rv(`3+LipI1ElW!X5%3_VHL=xaY`AHvL*)cZ ziiQw#$==pA+ok6DAkt*ADW@#=lwl65_fTdPzTvi)oJf=t0ez=+GJBwRaX@w)$`z^3 zI_yz8%Rs4Y@hRx8_pt?#mD|`{*-XJXj=$A#?VSnuc@Mi+))zR7l@zJ+?dV&_?Ko2f z(SI1beXU+-!0N}s%l*QwJmW2{n!L`RtaPFI_ z;9ePn+Mwd2>X_kGZ@LHk%`bAS^J8o1T|M$gx#h~d$!D&gNwVhde|%EYv2(AU#eF+S zd7Zkp`GG0&!~DktSJ(iyQ_|1v0KBTR3?i!MxH3Q%81_c-(YZJy zWeL9JuT3y2as51x${q1sn%57_Q`O``ja~r-JHYeS+RIUFkit4x&$ZLP_D7@w)ozp6 z9oojSh4Y;t;d>{7Gttfm{rswc{ITglLZF!CN${kMC^XwqV;ocxU1ysVX4O=3$?mc# znfDsvVB6m4;jQeo?F~}jKAaIwn_AMH6hOR|`D+qa1)JhHcV?womeL*p16HdHi{(DN zSnW;BmJbr+vO6JcX0k9)L(q-Z5AWPQ>=WD8M_T|)HLFEO7^KZ=E0jVM%Ro_zH5jKP z!NrXd3;Tp?tW3KrdV+>}`g3MO!u{OyJooxI&Qy<1Wk*-fB>f?g$XPK^$E3R97TR{C zeUE^bL#c#%6>@=!NH;$?f#T4dFhG!c!{^C7aMK2BENo!YD*?XlpG>;{ali1i(j|(_ zqh&?Iy^(EsGUvqU%zI=U$_yC(r`Fj3bu9L0YhaQ!NRD3E?u;vlVUHxuzoRdyWEuGu zgeIry)#$2yDih2Ne*3SOcsNl3Dr;QdZ@mkKb`3n-F|eM)3{$=C$5t`4&+u~qzbQ5E z8SV}4>;47MUmJ&mJBl#FI)rW=#2}4_1wbkED8P^3r0hap=wbkU9B~yHdCMDN`p&_@ zVu)F9TR}2gqs9$-g?6WZcA`6wbre7?#Y%Wq_5IPRWu#Z3B6|Y*3qTb!B7CD#Eha{) zds9mKKlYf;s@{Rmzb2hX7oOTzEYLMNp$o*H=#dg?1=d?SNlA$&N9r=j;EO|h5{uv4 zBzBY=zuJ�lpe4W*a}2WJXGyeQX=`6VAUdPmx^8!mZ_( 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

{{ _('Attribut') }}{{ _('Wert') }}
{{ _('Attribut') }}{{ _('Wert') }}
{{ _('path', 'items') }}'+element.path+'
{{ _('name', 'items') }}'+element.name+'
{{ _('type', 'items') }}'+element.type+'
+ + + + + + + + + + + + {% for key, item in p.get_items().items() %} + + + + + + + + + {% endfor %} + +
PfadTypowm_matchstringWertLetztes UpdateLetzter Change
{{ item.id() }}{{ item.type() }}{{ key }}{{ item() }}{{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }}{{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }}
+
+ +{% endblock %} +{% block bodytab2 %} + +
+ ({{ json_data_weather }}) +
+ +{% endblock %} +{% block bodytab3 %} + +
+ ({{ json_data_uvi }}) +
+ +{% endblock %} From 94fddd5f29a627c6a88584eace0d4cf0ccd952bc Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 16 Jul 2018 12:29:17 +0200 Subject: [PATCH 031/705] OpenWeatherMap: added support thread link --- openweathermap/plugin.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openweathermap/plugin.yaml b/openweathermap/plugin.yaml index 1cd2bbdcc..1d1dc48f7 100644 --- a/openweathermap/plugin.yaml +++ b/openweathermap/plugin.yaml @@ -9,7 +9,7 @@ plugin: tester: # keywords: iot xyz documentation: '' - support: '' + support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/1246998-support-thread-zum-openweathermap-plugin' keywords: weather version: 1.5.0.1 # Plugin version sh_minversion: 1.4c # minimum shNG version to use this plugin From 5b611d517f62243757d578e1591d27ade6c2fb74 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 16 Jul 2018 16:36:22 +0200 Subject: [PATCH 032/705] OpenWeatherMap: added possibility to request urls for image overlays --- openweathermap/__init__.py | 60 +++++++++++++++++++---- openweathermap/webif/templates/index.html | 2 +- 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/openweathermap/__init__.py b/openweathermap/__init__.py index 7bd5a5df4..1d3e9ebcd 100644 --- a/openweathermap/__init__.py +++ b/openweathermap/__init__.py @@ -34,6 +34,7 @@ class OpenWeatherMap(SmartPlugin): PLUGIN_VERSION = "1.5.0.1" _base_url = 'https://api.openweathermap.org/%s' + _base_img_url = 'https://tile.openweathermap.org/map/%s/%s/%s/%s.png?appid=%s' def __init__(self, sh, *args, **kwargs): """ @@ -88,15 +89,17 @@ def _update(self): self._jsonData['uvi'] = uv for s, item in self._items.items(): - if 'uvi' not in s: - wrk = weather - else: - wrk = uv - s = s.replace("uvi_", "") - sp = s.split('/') - if s == "flags/sources": - wrk = ', '.join(wrk['flags']['sources']) + if s in ['clouds_new', 'precipitation_new', 'pressure_new', 'wind_new', 'temp_new']: + wrk = self.get_owm_layer(item) + self.logger.error(wrk) else: + if 'uvi' not in s: + wrk = weather + else: + wrk = uv + s = s.replace("uvi_", "") + sp = s.split('/') + while True: if (len(sp) == 0) or (wrk is None): break @@ -131,6 +134,12 @@ def _update(self): return + def get_owm_layer(self, item): + """ + Requests the layer information (image links) at openweathermap.com + """ + return self._build_url('owm_layer', item) + def get_weather(self): """ Requests the weather information at openweathermap.com @@ -146,7 +155,7 @@ def get_weather(self): def get_uv(self): """ - Requests the weather information at openweathermap.com + Requests the uv index information at openweathermap.com """ try: response = self._session.get(self._build_url('uv')) @@ -176,7 +185,7 @@ def get_json_data_weather(self): def get_json_data_uvi(self): return self._jsonData['uvi'] - def _build_url(self, url_type='weather'): + def _build_url(self, url_type='weather', item=None): """ Builds a request url @param url_type: url type (currently on 'forecast', as historic data are not supported. @@ -193,6 +202,37 @@ def _build_url(self, url_type='weather'): parameters = "?lat=%s&lon=%s&appid=%s&lang=%s&units=%s" % (self._lat, self._lon, self._key, self._lang, self._units) url = '%s%s' % (url, parameters) + elif url_type == 'owm_layer': + if self.has_iattr(item.conf, 'owm_matchstring'): + layer = self.get_iattr_value(item.conf, 'owm_matchstring') + elif 'owm_matchstring' in item.conf: + layer = item.conf['owm_matchstring'] + + if self.has_iattr(item.conf, 'x'): + x = self.get_iattr_value(item.conf, 'x') + elif 'x' in item.conf: + x = item.conf['x'] + else: + self.logger.warning("_build_url: x attribute not set for item, setting default 1") + x = 1 + + if self.has_iattr(item.conf, 'y'): + y = self.get_iattr_value(item.conf, 'y') + elif 'y' in item.conf: + y = item.conf['y'] + else: + self.logger.warning("_build_url: y attribute not set for item, setting default 1") + y = 1 + + if self.has_iattr(item.conf, 'z'): + z = self.get_iattr_value(item.conf, 'z') + elif 'z' in item.conf: + z = item.conf['z'] + else: + self.logger.warning("_build_url: z attribute not set for item, setting default 1") + z = 1 + + url = self._base_img_url % (layer, z, x, y, self._key) else: self.logger.error('_build_url: Wrong url type specified: %s' % url_type) return url diff --git a/openweathermap/webif/templates/index.html b/openweathermap/webif/templates/index.html index 3f667593b..ffb4b6aad 100644 --- a/openweathermap/webif/templates/index.html +++ b/openweathermap/webif/templates/index.html @@ -32,7 +32,7 @@
OpenWeatherMap Plugin Items ({{ p.get_items()|length }})
{{ item.id() }} {{ item.type() }} {{ key }} - {{ item() }} + {% if key in ['precipitation_new', 'clouds_new', 'pressure_new', 'wind_new', 'temp_new'] %}
{{ item() }}{% else %} {{ item() }} {% endif %} {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} {{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }} From 3509a6e891e0ea1f393a704dcb8ab894f3b6c92d Mon Sep 17 00:00:00 2001 From: psilo909 Date: Tue, 17 Jul 2018 06:11:22 +0200 Subject: [PATCH 033/705] Backend: removed disclosure template and put to core --- backend/__init__.py | 8 +- backend/plugin.yaml | 2 +- backend/webif/templates/disclosure.html | 210 ------------------------ 3 files changed, 6 insertions(+), 214 deletions(-) delete mode 100755 backend/webif/templates/disclosure.html diff --git a/backend/__init__.py b/backend/__init__.py index db8cbc032..d415157bd 100755 --- a/backend/__init__.py +++ b/backend/__init__.py @@ -49,7 +49,7 @@ class BackendServer(SmartPlugin): the update functions for the items """ - PLUGIN_VERSION='1.4.12' + PLUGIN_VERSION = '1.4.13' def __init__(self, sh, updates_allowed='True', developer_mode="no", pypi_timeout=5): @@ -209,8 +209,10 @@ def __init__(self, webif_dir, plugin): self.webif_dir = webif_dir self.plugin = plugin self.logger.info("{}: Running from '{}'".format(self.__class__.__name__, self.webif_dir)) - - self.tplenv = Environment(loader=FileSystemLoader(self.plugin.path_join( self.webif_dir, 'templates' ) )) + backendtemplates = self.plugin.path_join(self.webif_dir, 'templates') + globaltemplates = self.plugin.mod_http.gtemplates_dir + self.tplenv = Environment(loader=FileSystemLoader([backendtemplates, globaltemplates])) + from os.path import basename as get_basename self.tplenv.globals['get_basename'] = get_basename self.tplenv.globals['is_userlogic'] = Logics.is_userlogic diff --git a/backend/plugin.yaml b/backend/plugin.yaml index 51d4df95f..341635e23 100755 --- a/backend/plugin.yaml +++ b/backend/plugin.yaml @@ -51,7 +51,7 @@ plugin: # documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/959964-support-thread-für-das-backend-plugin - version: 1.4.12 # Plugin version + version: 1.4.13 # Plugin version sh_minversion: 1.4e # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance diff --git a/backend/webif/templates/disclosure.html b/backend/webif/templates/disclosure.html deleted file mode 100755 index e094efc13..000000000 --- a/backend/webif/templates/disclosure.html +++ /dev/null @@ -1,210 +0,0 @@ - -{% extends "base.html" %} -{% block navbar %} - {% with active_page="disclosure" %} - {% include "navbar.html" %} - {% endwith %} -{% endblock navbar %} - -{% block title %} -{{ _('Disclosure', 'menu') }} - SmartHomeNG -{% endblock title %} - -{% block content %} - -
-
-
-
{{ _('Verwendete Open Source Software Komponenten', 'disclosure') }}
- - - - - - - - - - - - - - - - - -
{{ _('Name', 'disclosure') }}{{ _('Lizenz', 'disclosure') }}{{ _('Link', 'disclosure') }}
Bootstrap v4.1.2MIT Licensehttp://getbootstrap.com/
Bootstrap Tree ViewApache License, Version 2.0https://github.com/jonmiles/bootstrap-treeview
Bootstrap Datepicker v1.8.0Apache License, Version 2.0https://github.com/uxsolutions/bootstrap-datepicker
CodeMirror 5.39.0MIT Licensehttps://codemirror.net/
jQuery 3.3.1MIT Licensehttps://jquery.org
Font Awesome 5.1.0 (Free)Font Awesome licensed under SIL OFL 1.1
Font Awesome CSS, LESS, and Sass files are licensed under the MIT License
Font Awesome icons (all icons packaged as .svg and .js files) are licensed under the CC BY 4.0 License
http://fontawesome.com
{{ _('Icons/Bilder', 'disclosure') }}{{ _('Alle Icons und Bilder kommen von', 'disclosure') }} https://openclipart.orghttps://openclipart.org
-
-
-
-
-
-
-
-
Bootstrap v4.1.2:
-

- MIT License
-
- Copyright (c) 2011-2016 Twitter, Inc.
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
-

-
-
-
-
-
-
Bootstrap Tree View:
-

- Copyright 2013 Jonathan Miles
-
- Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-

-
-
-
-
-
-
Bootstrap Datepicker:
-

Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) -

-
-
-
-
-
-
CodeMirror 5.39.0:
-

- Copyright (C) 2017 by Marijn Haverbeke and others
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
-

-
-
-
-
-
-
Font Awesome 5.1.0 (Free)
-

- Font Awesome Free is free, open source, and GPL friendly. You can use it for - commercial projects, open source projects, or really almost whatever you want. - Full Font Awesome Free license: https://fontawesome.com/license. -

- # Icons:
- CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/) - In the Font Awesome Free download, the CC BY 4.0 license applies to all icons - packaged as SVG and JS file types. -

- # Fonts:
- SIL OFL 1.1 License (https://scripts.sil.org/OFL) - In the Font Awesome Free download, the SIL OLF license applies to all icons - packaged as web and desktop font files. -

- # Code:
- MIT License (https://opensource.org/licenses/MIT) - In the Font Awesome Free download, the MIT license applies to all non-font and - non-icon files. -

- # Attribution
- Attribution is required by MIT, SIL OLF, and CC BY licenses. Downloaded Font - Awesome Free files already contain embedded comments with sufficient - attribution, so you shouldn't need to do anything additional when using these - files normally. -

- We've kept attribution comments terse, so we ask that you do not actively work - to remove them from files, especially code. They're a great way for folks to - learn about Font Awesome. -

- # Brand Icons
- All brand icons are trademarks of their respective owners. The use of these - trademarks does not indicate endorsement of the trademark holder by Font - Awesome, nor vice versa. **Please do not use brand logos for any purpose except - to represent the company, product, or service to which they refer.** -

-
-
-
-
-
-
JQuery 3.3.1:
-

- MIT License
-
- Copyright jQuery Foundation and other contributors, https://jquery.org/
-
- This software consists of voluntary contributions made by many
- individuals. For exact contribution history, see the revision history
- available at https://github.com/jquery/jquery
-
- The following license applies to all parts of this software except as
- documented below:
-
-
-
- Permission is hereby granted, free of charge, to any person obtaining
- a copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, sublicense, and/or sell copies of the Software, and to
- permit persons to whom the Software is furnished to do so, subject to
- the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-
-
- All files located in the node_modules and external directories are
- externally maintained libraries used by this software which have their
- own licenses; we recommend you read them, as their terms may differ from
- the terms above.

-

-
-
-
-
-{% endblock %} From 747158b77b72ef28845e9dedd5972b78698d2c54 Mon Sep 17 00:00:00 2001 From: aschwith Date: Tue, 17 Jul 2018 18:22:57 +0200 Subject: [PATCH 034/705] Enocean: added support for NodOne occupancy sensor --- enocean/README.md | 16 ++++++++++++++++ enocean/eep_parser.py | 19 ++++++++++++++++++- enocean/plugin.yaml | 16 ++++++++-------- 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/enocean/README.md b/enocean/README.md index e119ffc87..16c244a89 100644 --- a/enocean/README.md +++ b/enocean/README.md @@ -249,6 +249,21 @@ EnOcean_Item: movement: type: bool enocean_rx_key: MOV + + occupancy_sensor: + enocean_rx_id: 01234567 + enocean_rx_eep: A5_07_03 + lux: + type: num + enocean_rx_key: ILL + + movement: + type: bool + enocean_rx_key: PIR + + voltage: + type: bool + enocean_rx_key: SVC temperature_sensor: enocean_rx_id: 01234567 @@ -336,6 +351,7 @@ The following status EEPs are supported: * A5_02_20 High Precision Temperature Sensor (ranges -10*C to +41.2°C, 1/20°C resolution) * A5_02_30 High Precision Temperature Sensor (ranges -40*C to +62.3°C, 1/10°C resolution) * A5_04_02 Energy (optional), humidity and temperature sensor +* A5_07_03 Occupancy sensor, e.g. NodOn PIR-2-1-0x * A5_08_01 Brightness and movement sensor * A5_11_04 Dimmer status feedback * A5_12_01 Power Measurement, e.g. Eltako FSVA-230V diff --git a/enocean/eep_parser.py b/enocean/eep_parser.py index 525f7c2d8..9043da2a0 100644 --- a/enocean/eep_parser.py +++ b/enocean/eep_parser.py @@ -131,6 +131,24 @@ def _parse_eep_A5_06_01(self, payload, status): if (result['BRI'] > 0): self.logger.info('enocean: brightness: {0}'.format(result['BRI'])) return result + + def _parse_eep_A5_07_03(self, payload, status): + # Occupancy sensor with supply voltage monitor, NodOne + self.logger.debug("enocean: parsing A5_07_03: Occupancy sensor") + result = {} + is_data = ((payload[3] & 0x08) == 0x08) # learn or data telegeram: 1:data, 0:learn + if not is_data: + self.logger.info("enocean: occupancy sensor: Received learn telegram.") + return result + + if payload[0] > 250: + self.logger.error("enocean: occupancy sensor issued error code: {0}".format(payload[0])) + else: + result['SVC'] = (payload[0] / 255.0 * 5.0) # supply voltage in volts + result['ILL'] = (payload[1] << 2) + ((payload[2] & 0xC0) >> 6) # 10 bit illumination in lux + result['PIR'] = ((payload[3] & 0x80) == 0x80) # Movement flag, 1:motion detected + self.logger.debug("occupancy: PIR:{0} illumination: {1}lx, voltage: {2}V".format(result['PIR'],result['ILL'],result['SVC'])) + return result def _parse_eep_A5_08_01(self, payload, status): # Brightness and movement sensor, for example eltako FBH65TFB @@ -139,7 +157,6 @@ def _parse_eep_A5_08_01(self, payload, status): result['BRI'] = (payload[1] / 255.0 * 2048) # brightness in lux result['MOV'] = not ((payload[3] & 0x02) == 0x02) # movement #self.logger.debug("enocean: movement: {0}, brightness: {1}".format(result['MOV'],result['BRI'])) - #self.logger.debug("enocean: movement data byte0: {0}".format(payload[3])) return result def _parse_eep_A5_11_04(self, payload, status): diff --git a/enocean/plugin.yaml b/enocean/plugin.yaml index 3e30b7b28..681197036 100755 --- a/enocean/plugin.yaml +++ b/enocean/plugin.yaml @@ -6,7 +6,7 @@ plugin: # Alternative: description in multiple languages de: 'Anbindung von EnOcean' en: 'EnOcean Interface' - maintainer: Robert Budde / aschwith + maintainer: Robert Budde / A. Schwithal # Who tests this plugin? #tester: keywords: EnOcean, Eltako @@ -15,7 +15,7 @@ plugin: # url oof the support thread #support: https://... - version: 1.3.3 # Plugin version + version: 1.3.4 # Plugin version sh_minversion: 1.3 # minimum shNG version to use this plugin #sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance @@ -27,8 +27,8 @@ parameters: type: str default: /dev/ttyAMA0 description: - de: 'Name der Schnittstelle an der sich der EnOcean Adapter befindet' - en: 'name of the port where the EnOcean adapter is plugged' + de: 'Name der Schnittstelle, an der sich der EnOcean Adapter befindet' + en: 'name of the port where the EnOcean adapter is plugged in' mandatory: 'True' tx_id: @@ -54,7 +54,7 @@ item_attributes: default: F6_02_03 description: de: 'EEP Profile des Response Telegramms' - en: 'EEP Profile of the response meassage' + en: 'EEP Profile of the response message' mandatory: 'True' enocean_tx_eep: @@ -62,14 +62,14 @@ item_attributes: default: A5_38_08 description: de: 'EEP Profile des Sende Telegramms' - en: 'EEP Profile of the send meassage' + en: 'EEP Profile of the send message' mandatory: 'True' enocean_tx_id_offset: type: int default: 0 description: - de: 'Offset zur Base-ID auf welche der Aktor reagiert' + de: 'Offset zur Base-ID, auf welche der Aktor reagiert' en: 'offset to the Base-ID on which the actor responds to' mandatory: 'False' @@ -114,7 +114,7 @@ item_attributes: Max: 100 description: de: 'Referenzwert in % fuer Dimmwert beim Einschalten' - en: 'refeence dim value in % when switching on' + en: 'reference dim value in % when switching on' mandatory: 'False' color: From 190ee809575e581610d1d44370408b7db21ff400 Mon Sep 17 00:00:00 2001 From: msinn Date: Tue, 17 Jul 2018 21:01:04 +0200 Subject: [PATCH 035/705] backend: Optimized display of item details --- backend/__init__.py | 2 +- backend/locale/de.json | 2 +- backend/locale/en.json | 4 +- backend/locale/fr.json | 2 +- backend/locale/pl.json | 2 +- backend/webif/templates/disclosure.html | 210 ++++++++++++++++++++++++ 6 files changed, 216 insertions(+), 6 deletions(-) create mode 100644 backend/webif/templates/disclosure.html diff --git a/backend/__init__.py b/backend/__init__.py index d415157bd..f36f8d185 100755 --- a/backend/__init__.py +++ b/backend/__init__.py @@ -211,7 +211,7 @@ def __init__(self, webif_dir, plugin): self.logger.info("{}: Running from '{}'".format(self.__class__.__name__, self.webif_dir)) backendtemplates = self.plugin.path_join(self.webif_dir, 'templates') globaltemplates = self.plugin.mod_http.gtemplates_dir - self.tplenv = Environment(loader=FileSystemLoader([backendtemplates, globaltemplates])) + self.tplenv = Environment(loader=FileSystemLoader([globaltemplates, backendtemplates])) from os.path import basename as get_basename self.tplenv.globals['get_basename'] = get_basename diff --git a/backend/locale/de.json b/backend/locale/de.json index 3b535aaed..e43e82f38 100755 --- a/backend/locale/de.json +++ b/backend/locale/de.json @@ -234,7 +234,7 @@ "Lizenz": "Lizenz", "Link": "Link", "Name": "Name", - "disclosure_title": "Offenlegung von Open Source Software Komponenten des SmartHomeNG BackendServer Plugins", + "disclosure_title": "Offenlegung der genutzten Open Source Software Komponenten in SmartHomeNG", "Verwendete Open Source Software Komponenten": "Verwendete Open Source Software Komponenten", "Icons/Bilder": "Icons/Bilder", "Alle Icons und Bilder kommen von": "Alle Icons und Bilder kommen von " diff --git a/backend/locale/en.json b/backend/locale/en.json index 7f30fa58b..f6b0c775c 100755 --- a/backend/locale/en.json +++ b/backend/locale/en.json @@ -235,8 +235,8 @@ "Lizenz": "License", "Link": "Link", "Name": "Name", - "disclosure_title": "Disclosure of Open Source Software Components deployed in SmartHomeNG BackendServer Plugin", - "Verwendete Open Source Software Komponenten": "Open Source Software Components used for the Plugin", + "disclosure_title": "Disclosure of Open Source Software Components deployed in SmartHomeNG", + "Verwendete Open Source Software Komponenten": "Open Source Software Components used", "Icons/Bilder": "Icons/Images", "Alle Icons und Bilder kommen von": "All icons and images are taken from " }, diff --git a/backend/locale/fr.json b/backend/locale/fr.json index b1450024b..82dfd88a1 100755 --- a/backend/locale/fr.json +++ b/backend/locale/fr.json @@ -235,7 +235,7 @@ "Lizenz": "Licence", "Link": "Lien", "Name": "Nom", - "disclosure_title": "Déclaration des composantes Open Source utilisées dans le serveur Backend de SmartHomeNG", + "disclosure_title": "Déclaration des composantes Open Source utilisées dans SmartHomeNG", "Verwendete Open Source Software Komponenten": "Composantes Open Source utilisées", "Icons/Bilder": "Icônes/Images", "Alle Icons und Bilder kommen von": "Toutes les images et icônes parviennent de" diff --git a/backend/locale/pl.json b/backend/locale/pl.json index fad0de6ad..a29e6deed 100755 --- a/backend/locale/pl.json +++ b/backend/locale/pl.json @@ -233,7 +233,7 @@ "Lizenz": "Licencja", "Link": "Link", "Name": "Nazwa", - "disclosure_title": "Deklaracja oprogramowania Open Source wykorzystanego w SmartHomeNG przez plugin 'backend'", + "disclosure_title": "Deklaracja oprogramowania Open Source wykorzystanego w SmartHomeNG", "Verwendete Open Source Software Komponenten": "Wykaz użytego oprogramowania Open Source", "Icons/Bilder": "Ikony/Obrazy", "Alle Icons und Bilder kommen von": "Wszystkie ikony i obrazy pochodzą z" diff --git a/backend/webif/templates/disclosure.html b/backend/webif/templates/disclosure.html new file mode 100644 index 000000000..e094efc13 --- /dev/null +++ b/backend/webif/templates/disclosure.html @@ -0,0 +1,210 @@ + +{% extends "base.html" %} +{% block navbar %} + {% with active_page="disclosure" %} + {% include "navbar.html" %} + {% endwith %} +{% endblock navbar %} + +{% block title %} +{{ _('Disclosure', 'menu') }} - SmartHomeNG +{% endblock title %} + +{% block content %} + +
+
+
+
{{ _('Verwendete Open Source Software Komponenten', 'disclosure') }}
+ + + + + + + + + + + + + + + + + +
{{ _('Name', 'disclosure') }}{{ _('Lizenz', 'disclosure') }}{{ _('Link', 'disclosure') }}
Bootstrap v4.1.2MIT Licensehttp://getbootstrap.com/
Bootstrap Tree ViewApache License, Version 2.0https://github.com/jonmiles/bootstrap-treeview
Bootstrap Datepicker v1.8.0Apache License, Version 2.0https://github.com/uxsolutions/bootstrap-datepicker
CodeMirror 5.39.0MIT Licensehttps://codemirror.net/
jQuery 3.3.1MIT Licensehttps://jquery.org
Font Awesome 5.1.0 (Free)Font Awesome licensed under SIL OFL 1.1
Font Awesome CSS, LESS, and Sass files are licensed under the MIT License
Font Awesome icons (all icons packaged as .svg and .js files) are licensed under the CC BY 4.0 License
http://fontawesome.com
{{ _('Icons/Bilder', 'disclosure') }}{{ _('Alle Icons und Bilder kommen von', 'disclosure') }} https://openclipart.orghttps://openclipart.org
+
+
+
+
+
+
+
+
Bootstrap v4.1.2:
+

+ MIT License
+
+ Copyright (c) 2011-2016 Twitter, Inc.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+

+
+
+
+
+
+
Bootstrap Tree View:
+

+ Copyright 2013 Jonathan Miles
+
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
+

+
+
+
+
+
+
Bootstrap Datepicker:
+

Licensed under the Apache License v2.0 (http://www.apache.org/licenses/LICENSE-2.0) +

+
+
+
+
+
+
CodeMirror 5.39.0:
+

+ Copyright (C) 2017 by Marijn Haverbeke and others
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+

+
+
+
+
+
+
Font Awesome 5.1.0 (Free)
+

+ Font Awesome Free is free, open source, and GPL friendly. You can use it for + commercial projects, open source projects, or really almost whatever you want. + Full Font Awesome Free license: https://fontawesome.com/license. +

+ # Icons:
+ CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/) + In the Font Awesome Free download, the CC BY 4.0 license applies to all icons + packaged as SVG and JS file types. +

+ # Fonts:
+ SIL OFL 1.1 License (https://scripts.sil.org/OFL) + In the Font Awesome Free download, the SIL OLF license applies to all icons + packaged as web and desktop font files. +

+ # Code:
+ MIT License (https://opensource.org/licenses/MIT) + In the Font Awesome Free download, the MIT license applies to all non-font and + non-icon files. +

+ # Attribution
+ Attribution is required by MIT, SIL OLF, and CC BY licenses. Downloaded Font + Awesome Free files already contain embedded comments with sufficient + attribution, so you shouldn't need to do anything additional when using these + files normally. +

+ We've kept attribution comments terse, so we ask that you do not actively work + to remove them from files, especially code. They're a great way for folks to + learn about Font Awesome. +

+ # Brand Icons
+ All brand icons are trademarks of their respective owners. The use of these + trademarks does not indicate endorsement of the trademark holder by Font + Awesome, nor vice versa. **Please do not use brand logos for any purpose except + to represent the company, product, or service to which they refer.** +

+
+
+
+
+
+
JQuery 3.3.1:
+

+ MIT License
+
+ Copyright jQuery Foundation and other contributors, https://jquery.org/
+
+ This software consists of voluntary contributions made by many
+ individuals. For exact contribution history, see the revision history
+ available at https://github.com/jquery/jquery
+
+ The following license applies to all parts of this software except as
+ documented below:
+
+
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+
+ All files located in the node_modules and external directories are
+ externally maintained libraries used by this software which have their
+ own licenses; we recommend you read them, as their terms may differ from
+ the terms above.

+

+
+
+
+
+{% endblock %} From 17cb30327815dc8c99c3512a825acc69616ed04f Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 20 Jul 2018 07:32:10 +0200 Subject: [PATCH 036/705] OpenWeatherMap: removed error log --- openweathermap/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/openweathermap/__init__.py b/openweathermap/__init__.py index 1d3e9ebcd..b3510e186 100644 --- a/openweathermap/__init__.py +++ b/openweathermap/__init__.py @@ -91,7 +91,6 @@ def _update(self): if s in ['clouds_new', 'precipitation_new', 'pressure_new', 'wind_new', 'temp_new']: wrk = self.get_owm_layer(item) - self.logger.error(wrk) else: if 'uvi' not in s: wrk = weather From 33907b2c2f7a301f40b91eebd619791ef2a85694 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 20 Jul 2018 07:49:13 +0200 Subject: [PATCH 037/705] AVM: added curl to test AHA data to code comment --- avm/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/avm/__init__.py b/avm/__init__.py index 8db0577ff..055531f34 100644 --- a/avm/__init__.py +++ b/avm/__init__.py @@ -1446,6 +1446,8 @@ def _update_home_automation(self, item): Updates AVM home automation device related information Uses: http://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/x_homeauto.pdf + CURL for testing which data is coming back: + curl --anyauth -u user:'password' "https://192.168.178.1:49443/upnp/control/x_homeauto" -H "Content-Type: text/xml; charset="utf-8"" -H "SoapAction:urn:dslforum-org:service:X_AVM-DE_Homeauto:1#GetSpecificDeviceInfos" -d "xxxxx xxxxxxx" -s -k :param item: item to be updated (Supported item avm_data_types: aha_device) """ From 94151e8c9dbe434b576658ccf54037f8a89aa00a Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 20 Jul 2018 20:03:20 +0200 Subject: [PATCH 038/705] AVM: removed misleading info from README --- avm/README.md | 54 +++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/avm/README.md b/avm/README.md index 9d4b3db40..d92645fe2 100644 --- a/avm/README.md +++ b/avm/README.md @@ -417,19 +417,19 @@ avm: cache: 'yes' visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device ip: type: str avm_data_type@fritzbox_7490: device_ip visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device connection_type: type: str avm_data_type@fritzbox_7490: device_connection_type visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device hostname: type: str avm_data_type@fritzbox_7490: device_hostname @@ -442,19 +442,19 @@ avm: cache: 'yes' visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device ip: type: str avm_data_type: device_ip visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device connection_type: type: str avm_data_type: device_connection_type visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device hostname: type: str avm_data_type: device_hostname @@ -468,19 +468,19 @@ avm: type: bool visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device ip: type: str avm_data_type: device_ip visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device connection_type: type: str avm_data_type: device_connection_type visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device hostname: type: str avm_data_type: device_hostname @@ -492,19 +492,19 @@ avm: type: bool visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device ip: type: str avm_data_type: device_ip visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device connection_type: type: str avm_data_type: device_connection_type visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device hostname: type: str avm_data_type: device_hostname @@ -517,19 +517,19 @@ avm: cache: 'yes' visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device ip: type: str avm_data_type: device_ip visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device connection_type: type: str avm_data_type: device_connection_type visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device hostname: type: str avm_data_type: device_hostname @@ -541,19 +541,19 @@ avm: type: bool visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device ip: type: str avm_data_type: device_ip visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device connection_type: type: str avm_data_type: device_connection_type visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device hostname: type: str avm_data_type: device_hostname @@ -566,19 +566,19 @@ avm: cache: 'yes' visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device ip: type: str avm_data_type: device_ip visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device connection_type: type: str avm_data_type: device_connection_type visu_acl: ro - # these items need to be child items from network_device, an @... must not be set + # these items need to be child items from network_device hostname: type: str avm_data_type: device_hostname @@ -592,13 +592,13 @@ avm: ain: 14324 0432601 # has to be identical to id in fritzbox (also with spaces!) visu_acl: rw - # these items need to be child items from aha_device, an @... must not be set + # these items need to be child items from aha_device energy: avm_data_type: energy type: num visu_acl: ro - # these items need to be child items from aha_device, an @... must not be set + # these items need to be child items from aha_device power: avm_data_type: power type: num @@ -607,7 +607,7 @@ avm: visu_acl: ro eval: value / 100 - # these items need to be child items from aha_device, an @... must not be set + # these items need to be child items from aha_device temperature: avm_data_type: temperature type: num @@ -619,13 +619,13 @@ avm: ain: 03456 0221393 # has to be identical to id in fritzbox (also with spaces!) visu_acl: rw - # these items need to be child items from aha_device, an @... must not be set + # these items need to be child items from aha_device energy: avm_data_type: energy type: num visu_acl: ro - # these items need to be child items from aha_device, an @... must not be set + # these items need to be child items from aha_device power: avm_data_type: power type: num @@ -634,7 +634,7 @@ avm: visu_acl: ro eval: value / 100 - # these items need to be child items from aha_device, an @... must not be set + # these items need to be child items from aha_device temperature: avm_data_type: temperature type: num From 6d56fed1abd1140b4c29aadc63f671333e05b830 Mon Sep 17 00:00:00 2001 From: aschwith Date: Fri, 20 Jul 2018 21:21:42 +0200 Subject: [PATCH 039/705] added first draft version for enocean webinterface --- enocean/README.md | 8 +- enocean/__init__.py | 1547 +++++++++++---------- enocean/eep_parser.py | 2 +- enocean/locale.yaml | 26 + enocean/webif/static/img/plugin_logo.png | Bin 0 -> 19435 bytes enocean/webif/templates/base_enocean.html | 42 + enocean/webif/templates/index.html | 32 + 7 files changed, 928 insertions(+), 729 deletions(-) create mode 100644 enocean/locale.yaml create mode 100644 enocean/webif/static/img/plugin_logo.png create mode 100644 enocean/webif/templates/base_enocean.html create mode 100644 enocean/webif/templates/index.html diff --git a/enocean/README.md b/enocean/README.md index 16c244a89..481713647 100644 --- a/enocean/README.md +++ b/enocean/README.md @@ -9,7 +9,7 @@ This plugin is still under development. If you have special hardware not supported yet please feel free to improve and contribute! ## Version / Change History -Version: 1.6 +Version: 1.3.4 Change History: currently not maintained. @@ -249,15 +249,15 @@ EnOcean_Item: movement: type: bool enocean_rx_key: MOV - - occupancy_sensor: + + occupancy_sensor: enocean_rx_id: 01234567 enocean_rx_eep: A5_07_03 lux: type: num enocean_rx_key: ILL - movement: + movement: type: bool enocean_rx_key: PIR diff --git a/enocean/__init__.py b/enocean/__init__.py index e2aa1af02..751e95348 100644 --- a/enocean/__init__.py +++ b/enocean/__init__.py @@ -1,724 +1,823 @@ -#!/usr/bin/env python3 -# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab -######################################################################### -# Copyright 2013-2014 Robert Budde robert@ing-budde.de -# Copyright 2014 Alexander Schwithal aschwith -######################################################################### -# Enocean plugin for SmartHomeNG. https://github.com/smarthomeNG// -# -# This plugin is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This plugin is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this plugin. If not, see . -######################################################################### - -import serial -import os -import sys -import logging -import struct -import time -import threading -from . import eep_parser -from . import prepare_packet_data -from lib.model.smartplugin import SmartPlugin - -FCSTAB = [ - 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, - 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, - 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, - 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, - 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, - 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, - 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, - 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, - 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, - 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, - 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, - 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a, - 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, - 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, - 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, - 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, - 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, - 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, - 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, - 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, - 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, - 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, - 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, - 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, - 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, - 0x76, 0x71, 0x78, 0x7f, 0x6A, 0x6d, 0x64, 0x63, - 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, - 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, - 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, - 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8D, 0x84, 0x83, - 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, - 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3 - ] - -################################ -### --- Packet Sync Byte --- ### -################################ -PACKET_SYNC_BYTE = 0x55 # PACKET SYNC BYTE - - -############################ -### --- Packet Types --- ### -############################ - -PACKET_TYPE_RADIO = 0x01 # RADIO ERP1 -PACKET_TYPE_RESPONSE = 0x02 # RESPONSE -PACKET_TYPE_RADIO_SUB_TEL = 0x03 # RADIO_SUB_TEL -PACKET_TYPE_EVENT = 0x04 # EVENT -PACKET_TYPE_COMMON_COMMAND = 0x05 # COMMON COMMAND -PACKET_TYPE_SMART_ACK_COMMAND = 0x06 # SMART ACK COMMAND -PACKET_REMOTE_MAN_COMMAND = 0x07 # REMOTE MANAGEMENT COMMAND -PACKET_TYPE_RADIO_MESSAGE = 0x09 # RADIO MESSAGE -PACKET_TYPE_RADIO_ERP2 = 0x0A # RADIO ERP2 -PACKET_TYPE_RADIO_802_15_4 = 0x10 # RADIO_802_15_4 -PACKET_TYPE_COMMAND_2_4 = 0x11 # COMMAND_2_4 - - -############################################ -### --- List of Common Command Codes --- ### -############################################ - -CO_WR_SLEEP = 0x01 # Order to enter in energy saving mode -CO_WR_RESET = 0x02 # Order to reset the device -CO_RD_VERSION = 0x03 # Read the device (SW) version /(HW) version, chip ID etc. -CO_RD_SYS_LOG = 0x04 # Read system log from device databank -CO_WR_SYS_LOG = 0x05 # Reset System log from device databank -CO_WR_BIST = 0x06 # Perform built in self test -CO_WR_IDBASE = 0x07 # Write ID range base number -CO_RD_IDBASE = 0x08 # Read ID range base number -CO_WR_REPEATER = 0x09 # Write Repeater Level off,1,2 -CO_RD_REPEATER = 0x0A # Read Repeater Level off,1,2 -CO_WR_FILTER_ADD = 0x0B # Add filter to filter list -CO_WR_FILTER_DEL = 0x0C # Delete filter from filter list -CO_WR_FILTER_DEL_ALL = 0x0D # Delete all filter -CO_WR_FILTER_ENABLE = 0x0E # Enable/Disable supplied filters -CO_RD_FILTER = 0x0F # Read supplied filters -CO_WR_WAIT_MATURITY = 0x10 # Waiting till end of maturity time before received radio telegrams will transmitted -CO_WR_SUBTEL = 0x11 # Enable/Disable transmitting additional subtelegram info -CO_WR_MEM = 0x12 # Write x bytes of the Flash, XRAM, RAM0 … -CO_RD_MEM = 0x13 # Read x bytes of the Flash, XRAM, RAM0 …. -CO_RD_MEM_ADDRESS = 0x14 # Feedback about the used address and length of the configarea and the Smart Ack Table -CO_RD_SECURITY = 0x15 # Read own security information (level, key) -CO_WR_SECURITY = 0x16 # Write own security information (level, key) -CO_WR_LEARNMODE = 0x17 # Function: Enables or disables learn mode of Controller. -CO_RD_LEARNMODE = 0x18 # Function: Reads the learn-mode state of Controller. -CO_WR_SECUREDEVICE_ADD = 0x19 # Add a secure device -CO_WR_SECUREDEVICE_DEL = 0x1A # Delete a secure device -CO_RD_SECUREDEVICE_BY_INDEX = 0x1B # Read secure device by index -CO_WR_MODE = 0x1C # Sets the gateway transceiver mode -CO_RD_NUMSECUREDEVICES = 0x1D # Read number of taught in secure devices -CO_RD_SECUREDEVICE_BY_ID = 0x1E # Read secure device by ID -CO_WR_SECUREDEVICE_ADD_PSK = 0x1F # Add Pre-shared key for inbound secure device -CO_WR_SECUREDEVICE_SENDTEACHIN = 0x20 # Send secure Teach-In message -CO_WR_TEMPORARY_RLC_WINDOW = 0x21 # Set the temporary rolling-code window for every taught-in devic -CO_RD_SECUREDEVICE_PSK = 0x22 # Read PSK -CO_RD_DUTYCYCLE_LIMIT = 0x23 # Read parameters of actual duty cycle limit -CO_SET_BAUDRATE = 0x24 # Modifies the baud rate of the EnOcean device -CO_GET_FREQUENCY_INFO = 0x25 # Reads Frequency and protocol of the Device -CO_GET_STEPCODE = 0x27 # Reads Hardware Step code and Revision of the Device - - -################################### -### --- List of Event Codes --- ### -################################### - -SA_RECLAIM_NOT_SUCCESSFUL = 0x01 # Informs the backbone of a Smart Ack Client to not successful reclaim. -SA_CONFIRM_LEARN = 0x02 # Used for SMACK to confirm/discard learn in/out -SA_LEARN_ACK = 0x03 # Inform backbone about result of learn request -CO_READY = 0x04 # Inform backbone about the readiness for operation -CO_EVENT_SECUREDEVICES = 0x05 # Informs about a secure device -CO_DUTYCYCLE_LIMIT = 0x06 # Informs about duty cycle limit -CO_TRANSMIT_FAILED = 0x07 # Informs that the device was not able to send a telegram. - - -########################################### -### --- Smart Acknowledge Defines: --- ### -########################################### - -SA_WR_LEARNMODE = 0x01 # Set/Reset Smart Ack learn mode -SA_RD_LEARNMODE = 0x02 # Get Smart Ack learn mode state -SA_WR_LEARNCONFIRM = 0x03 # Used for Smart Ack to add or delete a mailbox of a client -SA_WR_CLIENTLEARNRQ = 0x04 # Send Smart Ack Learn request (Client) -SA_WR_RESET = 0x05 # Send reset command to a Smart Ack client -SA_RD_LEARNEDCLIENTS = 0x06 # Get Smart Ack learned sensors / mailboxes -SA_WR_RECLAIMS = 0x07 # Set number of reclaim attempts -SA_WR_POSTMASTER = 0x08 # Activate/Deactivate Post master functionality - -SENT_RADIO_PACKET = 0xFF -SENT_ENCAPSULATED_RADIO_PACKET = 0xA6 - -class EnOcean(SmartPlugin): - ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.3.3" - - - def __init__(self, smarthome, serialport, tx_id=''): - self._sh = smarthome - self.port = serialport - self.logger = logging.getLogger(__name__) - if (len(tx_id) < 8): - self.tx_id = 0 - self.logger.warning('enocean: No valid enocean stick ID configured. Transmitting is not supported') - else: - self.tx_id = int(tx_id, 16) - self.logger.info('enocean: Stick TX ID configured via plugin.conf to: {0}'.format(tx_id)) - self._tcm = serial.Serial(serialport, 57600, timeout=0.5) - self._cmd_lock = threading.Lock() - self._response_lock = threading.Condition() - self._rx_items = {} - self._block_ext_out_msg = False - # call init of eep_parser - self.eep_parser = eep_parser.EEP_Parser() - # call init of prepare_packet_data - self.prepare_packet_data = prepare_packet_data.Prepare_Packet_Data(self) - - def eval_telegram(self, sender_id, data, opt): - self.logger.debug("enocean: call function << eval_telegram >>") - for item in self._items: - # validate id for item id: - if item.conf['enocean_id'] == sender_id: - #print ("validated {0} for {1}".format(sender_id,item)) - #print ("try to get value for: {0} and {1}".format(item.conf['enocean_rorg'][0],item.conf['enocean_rorg'][1])) - rorg = item.conf['enocean_rorg'] - eval_value = item.conf['enocean_value'] - if rorg in RADIO_PAYLOAD_VALUE: # check if RORG exists - pl = eval(RADIO_PAYLOAD_VALUE[rorg]['payload_idx']) - #could be nicer - for entity in RADIO_PAYLOAD_VALUE: - if (rorg == entity) and (eval_value in RADIO_PAYLOAD_VALUE[rorg]['entities']): - value_dict = RADIO_PAYLOAD_VALUE[rorg]['entities'] - value = eval(RADIO_PAYLOAD_VALUE[rorg]['entities'][eval_value]) - self.logger.debug("Resulting value: {0} for {1}".format(value, item)) - if value: # not sure about this - item(value, 'EnOcean', 'RADIO') - - def _process_packet_type_event(self, data, optional): - self.logger.debug("enocean: call function << _process_packet_type_event >>") - event_code = data[0] - if(event_code == SA_RECLAIM_NOT_SUCCESSFUL): - self.logger.error("enocean: SA reclaim was not successful") - elif(event_code == SA_CONFIRM_LEARN): - self.logger.info("enocean: Requesting how to handle confirm/discard learn in/out") - elif(event_code == SA_LEARN_ACK): - self.logger.info("enocean: SA lern acknowledged") - elif(event_code == CO_READY): - self.logger.info("enocean: Controller is ready for operation") - elif(event_code == CO_TRANSMIT_FAILED): - self.logger.error("enocean: Telegram transmission failed") - elif(event_code == CO_DUTYCYCLE_LIMIT): - self.logger.warning("enocean: Duty cycle limit reached") - elif(event_code == CO_EVENT_SECUREDEVICES): - self.logger.info("enocean: secure device event packet received") - else: - self.logger.warning("enocean: unknown event packet received") - - def _rocker_sequence(self, item, sender_id, sequence): - self.logger.debug("enocean: call function << _rocker_sequence >>") - try: - for step in sequence: - event, relation, delay = step.split() - #self.logger.debug("waiting for {} {} {}".format(event, relation, delay)) - if item._enocean_rs_events[event.upper()].wait(float(delay)) != (relation.upper() == "WITHIN"): - self.logger.debug("NOT {} - aborting sequence!".format(step)) - return - else: - self.logger.debug("{}".format(step)) - item._enocean_rs_events[event.upper()].clear() - continue - value = True - if 'enocean_rocker_action' in item.conf: - if item.conf['enocean_rocker_action'].upper() == "UNSET": - value = False - elif item.conf['enocean_rocker_action'].upper() == "TOGGLE": - value = not item() - item(value, 'EnOcean', "{:08X}".format(sender_id)) - except Exception as e: - self.logger.error("enocean: error handling enocean_rocker_sequence \"{}\" - {}".format(sequence, e)) - - def _process_packet_type_radio(self, data, optional): - self.logger.debug("enocean: call function << _process_packet_type_radio >>") - #self.logger.warning("enocean: processing radio message with data = [{}] / optional = [{}]".format(', '.join(['0x%02x' % b for b in data]), ', '.join(['0x%02x' % b for b in optional]))) - - choice = data[0] - payload = data[1:-5] - sender_id = int.from_bytes(data[-5:-1], byteorder='big', signed=False) - status = data[-1] - repeater_cnt = status & 0x0F - self.logger.info("enocean: radio message: choice = {:02x} / payload = [{}] / sender_id = {:08X} / status = {} / repeat = {}".format(choice, ', '.join(['0x%02x' % b for b in payload]), sender_id, status, repeater_cnt)) - - if (len(optional) == 7): - subtelnum = optional[0] - dest_id = int.from_bytes(optional[1:5], byteorder='big', signed=False) - dBm = -optional[5] - SecurityLevel = optional[6] - self.logger.debug("enocean: radio message with additional info: subtelnum = {} / dest_id = {:08X} / signal = {}dBm / SecurityLevel = {}".format(subtelnum, dest_id, dBm, SecurityLevel)) - if (choice == 0xD4) and (self.UTE_listen == True): - self.logger.info("call send_UTE_response") - self._send_UTE_response(data, optional) - if sender_id in self._rx_items: - self.logger.debug("enocean: Sender ID found in item list") - # iterate over all eep known for this id and get list of associated items - for eep,items in self._rx_items[sender_id].items(): - # check if choice matches first byte in eep (this seems to be the only way to find right eep for this particular packet) - if eep.startswith("{:02X}".format(choice)): - # call parser for particular eep - returns dictionary with key-value pairs - results = self.eep_parser.Parse(eep, payload, status) - self.logger.debug("enocean: radio message results = {}".format(results)) - for item in items: - rx_key = item.conf['enocean_rx_key'].upper() - if rx_key in results: - if 'enocean_rocker_sequence' in item.conf: - try: - if hasattr(item, '_enocean_rs_thread') and item._enocean_rs_thread.isAlive(): - if results[rx_key]: - self.logger.debug("sending pressed event") - item._enocean_rs_events["PRESSED"].set() - else: - self.logger.debug("sending released event") - item._enocean_rs_events["RELEASED"].set() - elif results[rx_key]: - item._enocean_rs_events = {'PRESSED': threading.Event(), 'RELEASED': threading.Event()} - item._enocean_rs_thread = threading.Thread(target=self._rocker_sequence, name="enocean-rs", args=(item, sender_id, item.conf['enocean_rocker_sequence'].split(','), )) - #self.logger.info("starting enocean_rocker_sequence thread") - item._enocean_rs_thread.daemon = True - item._enocean_rs_thread.start() - except Exception as e: - self.logger.error("enocean: error handling enocean_rocker_sequence - {}".format(e)) - else: - item(results[rx_key], 'EnOcean', "{:08X}".format(sender_id)) - elif (sender_id <= self.tx_id + 127) and (sender_id >= self.tx_id): - self.logger.debug("enocean: Received repeated enocean stick message") - else: - self.logger.info("unknown ID = {:08X}".format(sender_id)) - - - def _process_packet_type_smart_ack_command(self, data, optional): - self.logger.debug("enocean: call function << _process_packet_type_smart_ack_command >>") - self.logger.warning("enocean: smart acknowledge command 0x06 received but not supported at the moment") - - - def _process_packet_type_response(self, data, optional): - self.logger.debug("enocean: call function << _process_packet_type_response >>") - RETURN_CODES = ['OK', 'ERROR', 'NOT SUPPORTED', 'WRONG PARAM', 'OPERATION DENIED'] - if (self._last_cmd_code == SENT_RADIO_PACKET) and (len(data) == 1): - self.logger.debug("enocean: sending command returned code = {}".format(RETURN_CODES[data[0]])) - elif (self._last_packet_type == PACKET_TYPE_COMMON_COMMAND) and (self._last_cmd_code == CO_WR_RESET) and (len(data) == 1): - self.logger.info("enocean: Reset returned code = {}".format(RETURN_CODES[data[0]])) - elif (self._last_packet_type == PACKET_TYPE_COMMON_COMMAND) and (self._last_cmd_code == CO_WR_LEARNMODE) and (len(data) == 1): - self.logger.info("enocean: Write LearnMode returned code = {}".format(RETURN_CODES[data[0]])) - elif (self._last_packet_type == PACKET_TYPE_COMMON_COMMAND) and (self._last_cmd_code == CO_RD_VERSION): - if (data[0] == 0) and (len(data) == 33): - self.logger.info("enocean: Chip ID = 0x{} / Chip Version = 0x{}".format(''.join(['%02x' % b for b in data[9:13]]), ''.join(['%02x' % b for b in data[13:17]]))) - self.logger.info("enocean: APP version = {} / API version = {} / App description = {}".format('.'.join(['%d' % b for b in data[1:5]]), '.'.join(['%d' % b for b in data[5:9]]), ''.join(['%c' % b for b in data[17:33]]))) - elif (data[0] == 0) and (len(data) == 0): - self.logger.error("enocean: Reading version: No answer") - else: - self.logger.error("enocean: Reading version returned code = {}".format(RETURN_CODES[data[0]])) - elif (self._last_packet_type == PACKET_TYPE_COMMON_COMMAND) and (self._last_cmd_code == CO_RD_IDBASE): - if (data[0] == 0) and (len(data) == 5): - self.logger.info("enocean: Base ID = 0x{}".format(''.join(['%02x' % b for b in data[1:5]]))) - if (self.tx_id == 0): - self.tx_id = int.from_bytes(data[1:5], byteorder='big', signed=False) - self.logger.info("enocean: Transmit ID set set automatically by reading chips BaseID") - if (len(optional) == 1): - self.logger.info("enocean: Remaining write cycles for Base ID = {}".format(optional[0])) - elif (data[0] == 0) and (len(data) == 0): - self.logger.error("enocean: Reading Base ID: No answer") - else: - self.logger.error("enocean: Reading Base ID returned code = {}".format(RETURN_CODES[data[0]])) - elif (self._last_packet_type == PACKET_TYPE_COMMON_COMMAND) and (self._last_cmd_code == CO_WR_BIST): - if (data[0] == 0) and (len(data) == 2): - if (data[1] == 0): - self.logger.info("enocean: built in self test result: All OK") - else: - self.logger.info("enocean: built in self test result: Problem, code = {}".format(data[1])) - elif (data[0] == 0) and (len(data) == 0): - self.logger.error("enocean: Doing built in self test: No answer") - else: - self.logger.error("enocean: Doing built in self test returned code = {}".format(RETURN_CODES[data[0]])) - elif (self._last_packet_type == PACKET_TYPE_COMMON_COMMAND) and (self._last_cmd_code == CO_RD_LEARNMODE): - if (data[0] == 0) and (len(data) == 2): - self.logger.info("enocean: Reading LearnMode = 0x{}".format(''.join(['%02x' % b for b in data[1]]))) - if (len(optional) == 1): - self.logger.info("enocean: learn channel = {}".format(optional[0])) - elif (data[0] == 0) and (len(data) == 0): - self.logger.error("enocean: Reading LearnMode: No answer") - elif (self._last_packet_type == PACKET_TYPE_COMMON_COMMAND) and (self._last_cmd_code == CO_RD_NUMSECUREDEVICES): - if (data[0] == 0) and (len(data) == 2): - self.logger.info("enocean: Number of taught in devices = 0x{}".format(''.join(['%02x' % b for b in data[1]]))) - elif (data[0] == 0) and (len(data) == 0): - self.logger.error("enocean: Reading NUMSECUREDEVICES: No answer") - elif (data[0] == 2) and (len(data) == 1): - self.logger.error("enocean: Reading NUMSECUREDEVICES: Command not supported") - else: - self.logger.error("enocean: Reading NUMSECUREDEVICES: Unknown error") - elif (self._last_packet_type == PACKET_TYPE_SMART_ACK_COMMAND) and (self._last_cmd_code == SA_WR_LEARNMODE): - self.logger.info("enocean: Setting SmartAck mode returned code = {}".format(RETURN_CODES[data[0]])) - elif (self._last_packet_type == PACKET_TYPE_SMART_ACK_COMMAND) and (self._last_cmd_code == SA_RD_LEARNEDCLIENTS): - if (data[0] == 0): - self.logger.info("enocean: Number of smart acknowledge mailboxes = {}".format( int((len(data)-1)/9) )) - else: - self.logger.error("enocean: Requesting SmartAck mailboxes returned code = {}".format(RETURN_CODES[data[0]])) - else: - self.logger.error("enocean: processing unexpected response with return code = {} / data = [{}] / optional = [{}]".format(RETURN_CODES[data[0]], ', '.join(['0x%02x' % b for b in data]), ', '.join(['0x%02x' % b for b in optional]))) - self._response_lock.acquire() - self._response_lock.notify() - self._response_lock.release() - - def _startup(self): - self.logger.debug("enocean: call function << _startup >>") - # request one time information - self.logger.info("enocean: resetting device") - self._send_common_command(CO_WR_RESET) - self.logger.info("enocean: requesting id-base") - self._send_common_command(CO_RD_IDBASE) - self.logger.info("enocean: requesting version information") - self._send_common_command(CO_RD_VERSION) - self.logger.debug("enocean: ending connect-thread") - - def run(self): - self.logger.debug("enocean: call function << run >>") - self.alive = True - self.UTE_listen = False - #self.learn_id = 0 - t = threading.Thread(target=self._startup, name="enocean-startup") - t.daemon = True - t.start() - msg = [] - while self.alive: - readin = self._tcm.read(1000) - if readin: - msg += readin - self.logger.debug("enocean: data received") - # check if header is complete (6bytes including sync) - # 0x55 (SYNC) + 4bytes (HEADER) + 1byte(HEADER-CRC) - while (len(msg) >= 6): - #check header for CRC - if (msg[0] == PACKET_SYNC_BYTE) and (self._calc_crc8(msg[1:5]) == msg[5]): - # header bytes: sync; length of data (2); optional length; packet type; crc - data_length = (msg[1] << 8) + msg[2] - opt_length = msg[3] - packet_type = msg[4] - msg_length = data_length + opt_length + 7 - self.logger.debug("enocean: received header with data_length = {} / opt_length = 0x{:02x} / type = {}".format(data_length, opt_length, packet_type)) - - # break if msg is not yet complete: - if (len(msg) < msg_length): - break - - # msg complete - if (self._calc_crc8(msg[6:msg_length - 1]) == msg[msg_length - 1]): - self.logger.debug("enocean: accepted package with type = 0x{:02x} / len = {} / data = [{}]!".format(packet_type, msg_length, ', '.join(['0x%02x' % b for b in msg]))) - data = msg[6:msg_length - (opt_length + 1)] - optional = msg[(6 + data_length):msg_length - 1] - if (packet_type == PACKET_TYPE_RADIO): - self._process_packet_type_radio(data, optional) - elif (packet_type == PACKET_TYPE_SMART_ACK_COMMAND): - self._process_packet_type_smart_ack_command(data, optional) - elif (packet_type == PACKET_TYPE_RESPONSE): - self._process_packet_type_response(data, optional) - elif (packet_type == PACKET_TYPE_EVENT): - self._process_packet_type_event(data, optional) - else: - self.logger.error("enocean: received packet with unknown type = 0x{:02x} - len = {} / data = [{}]".format(packet_type, msg_length, ', '.join(['0x%02x' % b for b in msg]))) - else: - self.logger.error("enocean: crc error - dumping packet with type = 0x{:02x} / len = {} / data = [{}]!".format(packet_type, msg_length, ', '.join(['0x%02x' % b for b in msg]))) - msg = msg[msg_length:] - else: - #self.logger.warning("enocean: consuming [0x{:02x}] from input buffer!".format(msg[0])) - msg.pop(0) - - def stop(self): - self.logger.debug("enocean: call function << stop >>") - self.alive = False - self.logger.info("enocean: Thread stopped") - - - def _send_UTE_response(self, data, optional): - self.logger.debug("enocean: call function << _send_UTE_response >>") - choice = data[0] - payload = data[1:-5] - #sender_id = int.from_bytes(data[-5:-1], byteorder='big', signed=False) - #status = data[-1] - #repeater_cnt = status & 0x0F - SubTel = 0x03 - db = 0xFF - Secu = 0x0 - - self._send_radio_packet(self.learn_id, choice, [0x91, payload[1], payload[2], payload[3], payload[4], payload[5], payload[6]],[SubTel, data[-5], data[-4], data[-3], data[-2], db, Secu] )#payload[0] = 0x91: EEP Teach-in response, Request accepted, teach-in successful, bidirectional - self.UTE_listen = False - self.logger.info("enocean: sending UTE response and end listening") - - def parse_item(self, item): - self.logger.debug("enocean: call function << parse_item >>") - if 'enocean_rx_key' in item.conf: - # look for info from the most specific info to the broadest (key->eep->id) - one id might use multiple eep might define multiple keys - eep_item = item - while (not 'enocean_rx_eep' in eep_item.conf): - eep_item = eep_item.return_parent() - if (eep_item is self._sh): - self.logger.error("enocean: could not find enocean_rx_eep for item {}".format(item)) - return None - id_item = eep_item - while (not 'enocean_rx_id' in id_item.conf): - id_item = id_item.return_parent() - if (id_item is self._sh): - self.logger.error("enocean: could not find enocean_rx_id for item {}".format(item)) - return None - - rx_key = item.conf['enocean_rx_key'].upper() - rx_eep = eep_item.conf['enocean_rx_eep'].upper() - rx_id = int(id_item.conf['enocean_rx_id'],16) - - # check if there is a function to parse payload - if not self.eep_parser.CanParse(rx_eep): - return None - - if (rx_key in ['A0', 'A1', 'B0', 'B1']): - self.logger.warning("enocean: key \"{}\" does not match EEP - \"0\" (Zero, number) should be \"O\" (letter) (same for \"1\" and \"I\") - will be accepted for now".format(rx_key)) - rx_key = rx_key.replace('0', 'O').replace("1", 'I') - - if (not rx_id in self._rx_items): - self._rx_items[rx_id] = {rx_eep: [item]} - elif (not rx_eep in self._rx_items[rx_id]): - self._rx_items[rx_id][rx_eep] = [item] - elif (not item in self._rx_items[rx_id][rx_eep]): - self._rx_items[rx_id][rx_eep].append(item) - - self.logger.info("enocean: item {} listens to id {:08X} with eep {} key {}".format(item, rx_id, rx_eep, rx_key)) - #self.logger.info("enocean: self._rx_items = {}".format(self._rx_items)) - return self.update_item - - def update_item(self, item, caller=None, source=None, dest=None): - self.logger.debug("enocean: call function << update_item >>") - if caller != 'EnOcean': - self.logger.debug('enocean: item << {} >> updated externally.'.format(item)) - if self._block_ext_out_msg: - self.logger.debug('enocean: sending manually blocked by user. Aborting') - return None - if 'enocean_tx_eep' in item.conf: - if isinstance(item.conf['enocean_tx_eep'], str): - tx_eep = item.conf['enocean_tx_eep'] - self.logger.debug('enocean: item << {} >> has tx_eep'.format(item)) - # check if Data can be Prepared - if not self.prepare_packet_data.CanDataPrepare(tx_eep): - self.logger.error('enocean-update_item: method missing for prepare telegram data for {}'.format(tx_eep)) - else: - # call method prepare_packet_data(item, tx_eep) - id_offset, rorg, payload, optional = self.prepare_packet_data.PrepareData(item, tx_eep) - self._send_radio_packet(id_offset, rorg, payload, optional) - else: - self.logger.error('enocean: tx_eep {} is not a string value'.format(tx_eep)) - else: - self.logger.debug('enocean: item << {} >>has no tx_eep value'.format(item)) - - def read_num_securedivices(self): - self.logger.debug("enocean: call function << read_num_securedivices >>") - self._send_common_command(CO_RD_NUMSECUREDEVICES) - self.logger.info("enocean: Read number of secured devices") - - - # Request all taught in smart acknowledge devices that have a mailbox - def get_smart_ack_devices(self): - self.logger.debug("enocean: call function << get_smart_ack_devices >>") - self._send_smart_ack_command(SA_RD_LEARNEDCLIENTS) - self.logger.info("enocean: Requesting all available smart acknowledge mailboxes") - - - def reset_stick(self): - self.logger.debug("enocean: call function << reset_stick >>") - self.logger.info("enocean: resetting device") - self._send_common_command(CO_WR_RESET) - - def block_external_out_messages(self, block=True): - self.logger.debug("enocean: call function << block_external_out_messages >>") - if block: - self.logger.info("enocean: Blocking of external out messages activated") - self._block_ext_out_msg = True - elif not block: - self.logger.info("enocean: Blocking of external out messages deactivated") - self._block_ext_out_msg = False - else: - self.logger.info("enocean: invalid argument. Must be True/False") - - def send_bit(self): - self.logger.debug("enocean: call function << send_bit >>") - self.logger.info("enocean: trigger Built-In Self Test telegram") - self._send_common_command(CO_WR_BIST) - - def version(self): - self.logger.debug("enocean: call function << version >>") - self.logger.info("enocean: request stick version") - self._send_common_command(CO_RD_VERSION) - - def _send_packet(self, packet_type, data=[], optional=[]): - self.logger.debug("enocean: call function << _send_packet >>") - length_optional = len(optional) - if length_optional > 255: - self.logger.error("enocean: optional too long ({} bytes, 255 allowed)".format(length_optional)) - return None - length_data = len(data) - if length_data > 65535: - self.logger.error("enocean: data too long ({} bytes, 65535 allowed)".format(length_data)) - return None - - packet = bytearray([PACKET_SYNC_BYTE]) - packet += length_data.to_bytes(2, byteorder='big') + bytes([length_optional, packet_type]) - packet += bytes([self._calc_crc8(packet[1:5])]) - packet += bytes(data + optional) - packet += bytes([self._calc_crc8(packet[6:])]) - self.logger.info("enocean: sending packet with len = {} / data = [{}]!".format(len(packet), ', '.join(['0x%02x' % b for b in packet]))) - self._tcm.write(packet) - - def _send_smart_ack_command(self, _code, data=[]): - self.logger.debug("enocean: call function << _send_smart_ack_command >>") - self._cmd_lock.acquire() - self._last_cmd_code = _code - self._last_packet_type = PACKET_TYPE_SMART_ACK_COMMAND - self._send_packet(PACKET_TYPE_SMART_ACK_COMMAND, [_code] + data) - self._response_lock.acquire() - # wait 5sec for response - self._response_lock.wait(5) - self._response_lock.release() - self._cmd_lock.release() - - def _send_common_command(self, _code, data=[], optional=[]): - self.logger.debug("enocean: call function << _send_common_command >>") - self._cmd_lock.acquire() - self._last_cmd_code = _code - self._last_packet_type = PACKET_TYPE_COMMON_COMMAND - self._send_packet(PACKET_TYPE_COMMON_COMMAND, [_code] + data, optional) - self._response_lock.acquire() - # wait 5sec for response - self._response_lock.wait(5) - self._response_lock.release() - self._cmd_lock.release() - - def _send_radio_packet(self, id_offset, _code, data=[], optional=[]): - self.logger.debug("enocean: call function << _send_radio_packet >>") - if (id_offset < 0) or (id_offset > 127): - self.logger.error("enocean: invalid base ID offset range. (Is {}, must be [0 127])".format(id_offset)) - return - self._cmd_lock.acquire() - self._last_cmd_code = SENT_RADIO_PACKET - self._send_packet(PACKET_TYPE_RADIO, [_code] + data + list((self.tx_id + id_offset).to_bytes(4, byteorder='big')) + [0x00], optional) - self._response_lock.acquire() - # wait 5sec for response - self._response_lock.wait(5) - self._response_lock.release() - self._cmd_lock.release() - - - - -#################################################### -### --- START - Definitions of Learn Methods --- ### -#################################################### - def send_learn_protocol(self, id_offset=0, device=10): - self.logger.debug("enocean: call function << send_learn_protocol >>") - # define RORG - rorg = 0xA5 - - # check offset range between 0 and 127 - if (id_offset < 0) or (id_offset > 127): - self.logger.error('enocean: ID offset with value = {} out of range (0-127). Aborting.'.format(id_offset)) - return None - # device range 10 - 19 --> Learn protocol for switch actuators - elif (device == 10): - # Prepare Data for Eltako switch FSR61, Eltako FSVA-230V - payload = [0xE0, 0x40, 0x0D, 0x80] - self.logger.info('enocean: sending learn telegram for switch command with [Device], [ID-Offset], [RORG], [payload] / [{}], [{:#04x}], [{:#04x}], [{}]'.format(device, id_offset, rorg, ', '.join('{:#04x}'.format(x) for x in payload))) - # device range 20 - 29 --> Learn protocol for dim actuators - elif (device == 20): - # Only for Eltako FSUD-230V - payload = [0x02, 0x00, 0x00, 0x00] - self.logger.info('enocean: sending learn telegram for dim command with [Device], [ID-Offset], [RORG], [payload] / [{}], [{:#04x}], [{:#04x}], [{}]'.format(device, id_offset, rorg, ', '.join('{:#04x}'.format(x) for x in payload))) - elif (device == 21): - # For Eltako FHK61SSR dim device (EEP A5-38-08) - payload = [0xE0, 0x40, 0x0D, 0x80] - self.logger.info('enocean: sending learn telegram for dim command with [Device], [ID-Offset], [RORG], [payload] / [{}], [{:#04x}], [{:#04x}], [{}]'.format(device, id_offset, rorg, ', '.join('{:#04x}'.format(x) for x in payload))) - elif (device == 22): - # For Eltako FRGBW71L RGB dim devices (EEP 07-3F-7F) - payload = [0xFF, 0xF8, 0x0D, 0x87] - self.logger.info('enocean: sending learn telegram for rgbw dim command with [Device], [ID-Offset], [RORG], [payload] / [{}], [{:#04x}], [{:#04x}], [{}]'.format(device, id_offset, rorg, ', '.join('{:#04x}'.format(x) for x in payload))) - # device range 30 - 39 --> Learn protocol for radiator valves - elif (device == 30): - # Radiator Valve - payload = [0x00, 0x00, 0x00, 0x00] - self.logger.info('enocean: sending learn telegram for radiator valve with [Device], [ID-Offset], [RORG], [payload] / [{}], [{:#04x}], [{:#04x}], [{}]'.format(device, id_offset, rorg, ', '.join('{:#04x}'.format(x) for x in payload))) - # device range 40 - 49 --> Learn protocol for other actuators - elif (device == 40): - # Eltako shutter actor FSB14, FSB61, FSB71 - payload = [0xFF, 0xF8, 0x0D, 0x80] - self.logger.info('enocean: sending learn telegram for actuator with [Device], [ID-Offset], [RORG], [payload] / [{}], [{:#04x}], [{:#04x}], [{}]'.format(device, id_offset, rorg, ', '.join('{:#04x}'.format(x) for x in payload))) - else: - self.logger.error('enocean: sending learn telegram with invalid device! Device {} actually not defined!'.format(device)) - return None - # Send radio package - self._send_radio_packet(id_offset, rorg, payload) - return None - - - def start_UTE_learnmode(self, id_offset=0): - self.logger.debug("enocean: call function << start_UTE_learnmode >>") - self.UTE_listen = True - self.learn_id = id_offset - self.logger.info("enocean: Listeining for UTE package ('D4')") - - - def enter_learn_mode(self, onoff=1): - self.logger.debug("enocean: call function << enter_learn_mode >>") - if (onoff == 1): - self._send_common_command(CO_WR_LEARNMODE, [0x01, 0x00, 0x00, 0x00, 0x00],[0xFF]) - self.logger.info("enocean: entering learning mode") - return None - else: - self._send_common_command(CO_WR_LEARNMODE, [0x00, 0x00, 0x00, 0x00, 0x00],[0xFF]) - self.logger.info("enocean: leaving learning mode") - return None - - - # This function enables/disables the controller's smart acknowledge mode - def set_smart_ack_learn_mode(self, onoff=1): - self.logger.debug("enocean: call function << set_smart_ack_learn_mode >>") - if (onoff == 1): - self._send_smart_ack_command(SA_WR_LEARNMODE, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00]) - self.logger.info("enocean: enabling smart acknowledge learning mode") - return None - else: - self._send_smart_ack_command(SA_WR_LEARNMODE, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) - self.logger.info("enocean: disabling smart acknowledge learning mode") - return None - -################################################## -### --- END - Definitions of Learn Methods --- ### -################################################## - - -################################# -### --- START - Calc CRC8 --- ### -################################# - def _calc_crc8(self, msg, crc=0): - self.logger.debug("enocean: call function << _calc_crc8 >>") - for i in msg: - crc = FCSTAB[crc ^ i] - return crc - -############################### -### --- END - Calc CRC8 --- ### -############################### +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2013-2014 Robert Budde robert@ing-budde.de +# Copyright 2014 Alexander Schwithal aschwith +######################################################################### +# Enocean plugin for SmartHomeNG. https://github.com/smarthomeNG// +# +# This plugin is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This plugin is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this plugin. If not, see . +######################################################################### + +import serial +import os +import sys +import logging +import struct +import time +import threading +from lib.item import Items #what for? +from . import eep_parser +from . import prepare_packet_data +from lib.model.smartplugin import * + +FCSTAB = [ + 0x00, 0x07, 0x0e, 0x09, 0x1c, 0x1b, 0x12, 0x15, + 0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d, + 0x70, 0x77, 0x7e, 0x79, 0x6c, 0x6b, 0x62, 0x65, + 0x48, 0x4f, 0x46, 0x41, 0x54, 0x53, 0x5a, 0x5d, + 0xe0, 0xe7, 0xee, 0xe9, 0xfc, 0xfb, 0xf2, 0xf5, + 0xd8, 0xdf, 0xd6, 0xd1, 0xc4, 0xc3, 0xca, 0xcd, + 0x90, 0x97, 0x9e, 0x99, 0x8c, 0x8b, 0x82, 0x85, + 0xa8, 0xaf, 0xa6, 0xa1, 0xb4, 0xb3, 0xba, 0xbd, + 0xc7, 0xc0, 0xc9, 0xce, 0xdb, 0xdc, 0xd5, 0xd2, + 0xff, 0xf8, 0xf1, 0xf6, 0xe3, 0xe4, 0xed, 0xea, + 0xb7, 0xb0, 0xb9, 0xbe, 0xab, 0xac, 0xa5, 0xa2, + 0x8f, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9d, 0x9a, + 0x27, 0x20, 0x29, 0x2e, 0x3b, 0x3c, 0x35, 0x32, + 0x1f, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0d, 0x0a, + 0x57, 0x50, 0x59, 0x5e, 0x4b, 0x4c, 0x45, 0x42, + 0x6f, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7d, 0x7a, + 0x89, 0x8e, 0x87, 0x80, 0x95, 0x92, 0x9b, 0x9c, + 0xb1, 0xb6, 0xbf, 0xb8, 0xad, 0xaa, 0xa3, 0xa4, + 0xf9, 0xfe, 0xf7, 0xf0, 0xe5, 0xe2, 0xeb, 0xec, + 0xc1, 0xc6, 0xcf, 0xc8, 0xdd, 0xda, 0xd3, 0xd4, + 0x69, 0x6e, 0x67, 0x60, 0x75, 0x72, 0x7b, 0x7c, + 0x51, 0x56, 0x5f, 0x58, 0x4d, 0x4a, 0x43, 0x44, + 0x19, 0x1e, 0x17, 0x10, 0x05, 0x02, 0x0b, 0x0c, + 0x21, 0x26, 0x2f, 0x28, 0x3d, 0x3a, 0x33, 0x34, + 0x4e, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5c, 0x5b, + 0x76, 0x71, 0x78, 0x7f, 0x6A, 0x6d, 0x64, 0x63, + 0x3e, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2c, 0x2b, + 0x06, 0x01, 0x08, 0x0f, 0x1a, 0x1d, 0x14, 0x13, + 0xae, 0xa9, 0xa0, 0xa7, 0xb2, 0xb5, 0xbc, 0xbb, + 0x96, 0x91, 0x98, 0x9f, 0x8a, 0x8D, 0x84, 0x83, + 0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, + 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3 + ] + +################################ +### --- Packet Sync Byte --- ### +################################ +PACKET_SYNC_BYTE = 0x55 # PACKET SYNC BYTE + + +############################ +### --- Packet Types --- ### +############################ + +PACKET_TYPE_RADIO = 0x01 # RADIO ERP1 +PACKET_TYPE_RESPONSE = 0x02 # RESPONSE +PACKET_TYPE_RADIO_SUB_TEL = 0x03 # RADIO_SUB_TEL +PACKET_TYPE_EVENT = 0x04 # EVENT +PACKET_TYPE_COMMON_COMMAND = 0x05 # COMMON COMMAND +PACKET_TYPE_SMART_ACK_COMMAND = 0x06 # SMART ACK COMMAND +PACKET_REMOTE_MAN_COMMAND = 0x07 # REMOTE MANAGEMENT COMMAND +PACKET_TYPE_RADIO_MESSAGE = 0x09 # RADIO MESSAGE +PACKET_TYPE_RADIO_ERP2 = 0x0A # RADIO ERP2 +PACKET_TYPE_RADIO_802_15_4 = 0x10 # RADIO_802_15_4 +PACKET_TYPE_COMMAND_2_4 = 0x11 # COMMAND_2_4 + + +############################################ +### --- List of Common Command Codes --- ### +############################################ + +CO_WR_SLEEP = 0x01 # Order to enter in energy saving mode +CO_WR_RESET = 0x02 # Order to reset the device +CO_RD_VERSION = 0x03 # Read the device (SW) version /(HW) version, chip ID etc. +CO_RD_SYS_LOG = 0x04 # Read system log from device databank +CO_WR_SYS_LOG = 0x05 # Reset System log from device databank +CO_WR_BIST = 0x06 # Perform built in self test +CO_WR_IDBASE = 0x07 # Write ID range base number +CO_RD_IDBASE = 0x08 # Read ID range base number +CO_WR_REPEATER = 0x09 # Write Repeater Level off,1,2 +CO_RD_REPEATER = 0x0A # Read Repeater Level off,1,2 +CO_WR_FILTER_ADD = 0x0B # Add filter to filter list +CO_WR_FILTER_DEL = 0x0C # Delete filter from filter list +CO_WR_FILTER_DEL_ALL = 0x0D # Delete all filter +CO_WR_FILTER_ENABLE = 0x0E # Enable/Disable supplied filters +CO_RD_FILTER = 0x0F # Read supplied filters +CO_WR_WAIT_MATURITY = 0x10 # Waiting till end of maturity time before received radio telegrams will transmitted +CO_WR_SUBTEL = 0x11 # Enable/Disable transmitting additional subtelegram info +CO_WR_MEM = 0x12 # Write x bytes of the Flash, XRAM, RAM0 … +CO_RD_MEM = 0x13 # Read x bytes of the Flash, XRAM, RAM0 …. +CO_RD_MEM_ADDRESS = 0x14 # Feedback about the used address and length of the configarea and the Smart Ack Table +CO_RD_SECURITY = 0x15 # Read own security information (level, key) +CO_WR_SECURITY = 0x16 # Write own security information (level, key) +CO_WR_LEARNMODE = 0x17 # Function: Enables or disables learn mode of Controller. +CO_RD_LEARNMODE = 0x18 # Function: Reads the learn-mode state of Controller. +CO_WR_SECUREDEVICE_ADD = 0x19 # Add a secure device +CO_WR_SECUREDEVICE_DEL = 0x1A # Delete a secure device +CO_RD_SECUREDEVICE_BY_INDEX = 0x1B # Read secure device by index +CO_WR_MODE = 0x1C # Sets the gateway transceiver mode +CO_RD_NUMSECUREDEVICES = 0x1D # Read number of taught in secure devices +CO_RD_SECUREDEVICE_BY_ID = 0x1E # Read secure device by ID +CO_WR_SECUREDEVICE_ADD_PSK = 0x1F # Add Pre-shared key for inbound secure device +CO_WR_SECUREDEVICE_SENDTEACHIN = 0x20 # Send secure Teach-In message +CO_WR_TEMPORARY_RLC_WINDOW = 0x21 # Set the temporary rolling-code window for every taught-in devic +CO_RD_SECUREDEVICE_PSK = 0x22 # Read PSK +CO_RD_DUTYCYCLE_LIMIT = 0x23 # Read parameters of actual duty cycle limit +CO_SET_BAUDRATE = 0x24 # Modifies the baud rate of the EnOcean device +CO_GET_FREQUENCY_INFO = 0x25 # Reads Frequency and protocol of the Device +CO_GET_STEPCODE = 0x27 # Reads Hardware Step code and Revision of the Device + + +################################### +### --- List of Event Codes --- ### +################################### + +SA_RECLAIM_NOT_SUCCESSFUL = 0x01 # Informs the backbone of a Smart Ack Client to not successful reclaim. +SA_CONFIRM_LEARN = 0x02 # Used for SMACK to confirm/discard learn in/out +SA_LEARN_ACK = 0x03 # Inform backbone about result of learn request +CO_READY = 0x04 # Inform backbone about the readiness for operation +CO_EVENT_SECUREDEVICES = 0x05 # Informs about a secure device +CO_DUTYCYCLE_LIMIT = 0x06 # Informs about duty cycle limit +CO_TRANSMIT_FAILED = 0x07 # Informs that the device was not able to send a telegram. + + +########################################### +### --- Smart Acknowledge Defines: --- ### +########################################### + +SA_WR_LEARNMODE = 0x01 # Set/Reset Smart Ack learn mode +SA_RD_LEARNMODE = 0x02 # Get Smart Ack learn mode state +SA_WR_LEARNCONFIRM = 0x03 # Used for Smart Ack to add or delete a mailbox of a client +SA_WR_CLIENTLEARNRQ = 0x04 # Send Smart Ack Learn request (Client) +SA_WR_RESET = 0x05 # Send reset command to a Smart Ack client +SA_RD_LEARNEDCLIENTS = 0x06 # Get Smart Ack learned sensors / mailboxes +SA_WR_RECLAIMS = 0x07 # Set number of reclaim attempts +SA_WR_POSTMASTER = 0x08 # Activate/Deactivate Post master functionality + +SENT_RADIO_PACKET = 0xFF +SENT_ENCAPSULATED_RADIO_PACKET = 0xA6 + +class EnOcean(SmartPlugin): + ALLOW_MULTIINSTANCE = False + PLUGIN_VERSION = "1.3.4" + + + def __init__(self, smarthome, serialport, tx_id=''): + self._sh = smarthome + self.port = serialport + self.logger = logging.getLogger(__name__) + if (len(tx_id) < 8): + self.tx_id = 0 + self.logger.warning('enocean: No valid enocean stick ID configured. Transmitting is not supported') + else: + self.tx_id = int(tx_id, 16) + self.logger.info('enocean: Stick TX ID configured via plugin.conf to: {0}'.format(tx_id)) + self._tcm = serial.Serial(serialport, 57600, timeout=0.5) + self._cmd_lock = threading.Lock() + self._response_lock = threading.Condition() + self._rx_items = {} + self.UTE_listen = False + self._block_ext_out_msg = False + # call init of eep_parser + self.eep_parser = eep_parser.EEP_Parser() + # call init of prepare_packet_data + self.prepare_packet_data = prepare_packet_data.Prepare_Packet_Data(self) + + if not self.init_webinterface(): + self._init_complete = False + + def eval_telegram(self, sender_id, data, opt): + self.logger.debug("enocean: call function << eval_telegram >>") + for item in self._items: + # validate id for item id: + if item.conf['enocean_id'] == sender_id: + #print ("validated {0} for {1}".format(sender_id,item)) + #print ("try to get value for: {0} and {1}".format(item.conf['enocean_rorg'][0],item.conf['enocean_rorg'][1])) + rorg = item.conf['enocean_rorg'] + eval_value = item.conf['enocean_value'] + if rorg in RADIO_PAYLOAD_VALUE: # check if RORG exists + pl = eval(RADIO_PAYLOAD_VALUE[rorg]['payload_idx']) + #could be nicer + for entity in RADIO_PAYLOAD_VALUE: + if (rorg == entity) and (eval_value in RADIO_PAYLOAD_VALUE[rorg]['entities']): + value_dict = RADIO_PAYLOAD_VALUE[rorg]['entities'] + value = eval(RADIO_PAYLOAD_VALUE[rorg]['entities'][eval_value]) + self.logger.debug("Resulting value: {0} for {1}".format(value, item)) + if value: # not sure about this + item(value, 'EnOcean', 'RADIO') + + def _process_packet_type_event(self, data, optional): + self.logger.debug("enocean: call function << _process_packet_type_event >>") + event_code = data[0] + if(event_code == SA_RECLAIM_NOT_SUCCESSFUL): + self.logger.error("enocean: SA reclaim was not successful") + elif(event_code == SA_CONFIRM_LEARN): + self.logger.info("enocean: Requesting how to handle confirm/discard learn in/out") + elif(event_code == SA_LEARN_ACK): + self.logger.info("enocean: SA lern acknowledged") + elif(event_code == CO_READY): + self.logger.info("enocean: Controller is ready for operation") + elif(event_code == CO_TRANSMIT_FAILED): + self.logger.error("enocean: Telegram transmission failed") + elif(event_code == CO_DUTYCYCLE_LIMIT): + self.logger.warning("enocean: Duty cycle limit reached") + elif(event_code == CO_EVENT_SECUREDEVICES): + self.logger.info("enocean: secure device event packet received") + else: + self.logger.warning("enocean: unknown event packet received") + + def _rocker_sequence(self, item, sender_id, sequence): + self.logger.debug("enocean: call function << _rocker_sequence >>") + try: + for step in sequence: + event, relation, delay = step.split() + #self.logger.debug("waiting for {} {} {}".format(event, relation, delay)) + if item._enocean_rs_events[event.upper()].wait(float(delay)) != (relation.upper() == "WITHIN"): + self.logger.debug("NOT {} - aborting sequence!".format(step)) + return + else: + self.logger.debug("{}".format(step)) + item._enocean_rs_events[event.upper()].clear() + continue + value = True + if 'enocean_rocker_action' in item.conf: + if item.conf['enocean_rocker_action'].upper() == "UNSET": + value = False + elif item.conf['enocean_rocker_action'].upper() == "TOGGLE": + value = not item() + item(value, 'EnOcean', "{:08X}".format(sender_id)) + except Exception as e: + self.logger.error("enocean: error handling enocean_rocker_sequence \"{}\" - {}".format(sequence, e)) + + def _process_packet_type_radio(self, data, optional): + self.logger.debug("enocean: call function << _process_packet_type_radio >>") + #self.logger.warning("enocean: processing radio message with data = [{}] / optional = [{}]".format(', '.join(['0x%02x' % b for b in data]), ', '.join(['0x%02x' % b for b in optional]))) + + choice = data[0] + payload = data[1:-5] + sender_id = int.from_bytes(data[-5:-1], byteorder='big', signed=False) + status = data[-1] + repeater_cnt = status & 0x0F + self.logger.info("enocean: radio message: choice = {:02x} / payload = [{}] / sender_id = {:08X} / status = {} / repeat = {}".format(choice, ', '.join(['0x%02x' % b for b in payload]), sender_id, status, repeater_cnt)) + + if (len(optional) == 7): + subtelnum = optional[0] + dest_id = int.from_bytes(optional[1:5], byteorder='big', signed=False) + dBm = -optional[5] + SecurityLevel = optional[6] + self.logger.debug("enocean: radio message with additional info: subtelnum = {} / dest_id = {:08X} / signal = {}dBm / SecurityLevel = {}".format(subtelnum, dest_id, dBm, SecurityLevel)) + if (choice == 0xD4) and (self.UTE_listen == True): + self.logger.info("call send_UTE_response") + self._send_UTE_response(data, optional) + if sender_id in self._rx_items: + self.logger.debug("enocean: Sender ID found in item list") + # iterate over all eep known for this id and get list of associated items + for eep,items in self._rx_items[sender_id].items(): + # check if choice matches first byte in eep (this seems to be the only way to find right eep for this particular packet) + if eep.startswith("{:02X}".format(choice)): + # call parser for particular eep - returns dictionary with key-value pairs + results = self.eep_parser.Parse(eep, payload, status) + self.logger.debug("enocean: radio message results = {}".format(results)) + for item in items: + rx_key = item.conf['enocean_rx_key'].upper() + if rx_key in results: + if 'enocean_rocker_sequence' in item.conf: + try: + if hasattr(item, '_enocean_rs_thread') and item._enocean_rs_thread.isAlive(): + if results[rx_key]: + self.logger.debug("sending pressed event") + item._enocean_rs_events["PRESSED"].set() + else: + self.logger.debug("sending released event") + item._enocean_rs_events["RELEASED"].set() + elif results[rx_key]: + item._enocean_rs_events = {'PRESSED': threading.Event(), 'RELEASED': threading.Event()} + item._enocean_rs_thread = threading.Thread(target=self._rocker_sequence, name="enocean-rs", args=(item, sender_id, item.conf['enocean_rocker_sequence'].split(','), )) + #self.logger.info("starting enocean_rocker_sequence thread") + item._enocean_rs_thread.daemon = True + item._enocean_rs_thread.start() + except Exception as e: + self.logger.error("enocean: error handling enocean_rocker_sequence - {}".format(e)) + else: + item(results[rx_key], 'EnOcean', "{:08X}".format(sender_id)) + elif (sender_id <= self.tx_id + 127) and (sender_id >= self.tx_id): + self.logger.debug("enocean: Received repeated enocean stick message") + else: + self.logger.info("unknown ID = {:08X}".format(sender_id)) + + + def _process_packet_type_smart_ack_command(self, data, optional): + self.logger.debug("enocean: call function << _process_packet_type_smart_ack_command >>") + self.logger.warning("enocean: smart acknowledge command 0x06 received but not supported at the moment") + + + def _process_packet_type_response(self, data, optional): + self.logger.debug("enocean: call function << _process_packet_type_response >>") + RETURN_CODES = ['OK', 'ERROR', 'NOT SUPPORTED', 'WRONG PARAM', 'OPERATION DENIED'] + if (self._last_cmd_code == SENT_RADIO_PACKET) and (len(data) == 1): + self.logger.debug("enocean: sending command returned code = {}".format(RETURN_CODES[data[0]])) + elif (self._last_packet_type == PACKET_TYPE_COMMON_COMMAND) and (self._last_cmd_code == CO_WR_RESET) and (len(data) == 1): + self.logger.info("enocean: Reset returned code = {}".format(RETURN_CODES[data[0]])) + elif (self._last_packet_type == PACKET_TYPE_COMMON_COMMAND) and (self._last_cmd_code == CO_WR_LEARNMODE) and (len(data) == 1): + self.logger.info("enocean: Write LearnMode returned code = {}".format(RETURN_CODES[data[0]])) + elif (self._last_packet_type == PACKET_TYPE_COMMON_COMMAND) and (self._last_cmd_code == CO_RD_VERSION): + if (data[0] == 0) and (len(data) == 33): + self.logger.info("enocean: Chip ID = 0x{} / Chip Version = 0x{}".format(''.join(['%02x' % b for b in data[9:13]]), ''.join(['%02x' % b for b in data[13:17]]))) + self.logger.info("enocean: APP version = {} / API version = {} / App description = {}".format('.'.join(['%d' % b for b in data[1:5]]), '.'.join(['%d' % b for b in data[5:9]]), ''.join(['%c' % b for b in data[17:33]]))) + elif (data[0] == 0) and (len(data) == 0): + self.logger.error("enocean: Reading version: No answer") + else: + self.logger.error("enocean: Reading version returned code = {}".format(RETURN_CODES[data[0]])) + elif (self._last_packet_type == PACKET_TYPE_COMMON_COMMAND) and (self._last_cmd_code == CO_RD_IDBASE): + if (data[0] == 0) and (len(data) == 5): + self.logger.info("enocean: Base ID = 0x{}".format(''.join(['%02x' % b for b in data[1:5]]))) + if (self.tx_id == 0): + self.tx_id = int.from_bytes(data[1:5], byteorder='big', signed=False) + self.logger.info("enocean: Transmit ID set set automatically by reading chips BaseID") + if (len(optional) == 1): + self.logger.info("enocean: Remaining write cycles for Base ID = {}".format(optional[0])) + elif (data[0] == 0) and (len(data) == 0): + self.logger.error("enocean: Reading Base ID: No answer") + else: + self.logger.error("enocean: Reading Base ID returned code = {}".format(RETURN_CODES[data[0]])) + elif (self._last_packet_type == PACKET_TYPE_COMMON_COMMAND) and (self._last_cmd_code == CO_WR_BIST): + if (data[0] == 0) and (len(data) == 2): + if (data[1] == 0): + self.logger.info("enocean: built in self test result: All OK") + else: + self.logger.info("enocean: built in self test result: Problem, code = {}".format(data[1])) + elif (data[0] == 0) and (len(data) == 0): + self.logger.error("enocean: Doing built in self test: No answer") + else: + self.logger.error("enocean: Doing built in self test returned code = {}".format(RETURN_CODES[data[0]])) + elif (self._last_packet_type == PACKET_TYPE_COMMON_COMMAND) and (self._last_cmd_code == CO_RD_LEARNMODE): + if (data[0] == 0) and (len(data) == 2): + self.logger.info("enocean: Reading LearnMode = 0x{}".format(''.join(['%02x' % b for b in data[1]]))) + if (len(optional) == 1): + self.logger.info("enocean: learn channel = {}".format(optional[0])) + elif (data[0] == 0) and (len(data) == 0): + self.logger.error("enocean: Reading LearnMode: No answer") + elif (self._last_packet_type == PACKET_TYPE_COMMON_COMMAND) and (self._last_cmd_code == CO_RD_NUMSECUREDEVICES): + if (data[0] == 0) and (len(data) == 2): + self.logger.info("enocean: Number of taught in devices = 0x{}".format(''.join(['%02x' % b for b in data[1]]))) + elif (data[0] == 0) and (len(data) == 0): + self.logger.error("enocean: Reading NUMSECUREDEVICES: No answer") + elif (data[0] == 2) and (len(data) == 1): + self.logger.error("enocean: Reading NUMSECUREDEVICES: Command not supported") + else: + self.logger.error("enocean: Reading NUMSECUREDEVICES: Unknown error") + elif (self._last_packet_type == PACKET_TYPE_SMART_ACK_COMMAND) and (self._last_cmd_code == SA_WR_LEARNMODE): + self.logger.info("enocean: Setting SmartAck mode returned code = {}".format(RETURN_CODES[data[0]])) + elif (self._last_packet_type == PACKET_TYPE_SMART_ACK_COMMAND) and (self._last_cmd_code == SA_RD_LEARNEDCLIENTS): + if (data[0] == 0): + self.logger.info("enocean: Number of smart acknowledge mailboxes = {}".format( int((len(data)-1)/9) )) + else: + self.logger.error("enocean: Requesting SmartAck mailboxes returned code = {}".format(RETURN_CODES[data[0]])) + else: + self.logger.error("enocean: processing unexpected response with return code = {} / data = [{}] / optional = [{}]".format(RETURN_CODES[data[0]], ', '.join(['0x%02x' % b for b in data]), ', '.join(['0x%02x' % b for b in optional]))) + self._response_lock.acquire() + self._response_lock.notify() + self._response_lock.release() + + def _startup(self): + self.logger.debug("enocean: call function << _startup >>") + # request one time information + self.logger.info("enocean: resetting device") + self._send_common_command(CO_WR_RESET) + self.logger.info("enocean: requesting id-base") + self._send_common_command(CO_RD_IDBASE) + self.logger.info("enocean: requesting version information") + self._send_common_command(CO_RD_VERSION) + self.logger.debug("enocean: ending connect-thread") + + def run(self): + self.logger.debug("enocean: call function << run >>") + self.alive = True + self.UTE_listen = False + #self.learn_id = 0 + t = threading.Thread(target=self._startup, name="enocean-startup") + t.daemon = True + t.start() + msg = [] + while self.alive: + readin = self._tcm.read(1000) + if readin: + msg += readin + self.logger.debug("enocean: data received") + # check if header is complete (6bytes including sync) + # 0x55 (SYNC) + 4bytes (HEADER) + 1byte(HEADER-CRC) + while (len(msg) >= 6): + #check header for CRC + if (msg[0] == PACKET_SYNC_BYTE) and (self._calc_crc8(msg[1:5]) == msg[5]): + # header bytes: sync; length of data (2); optional length; packet type; crc + data_length = (msg[1] << 8) + msg[2] + opt_length = msg[3] + packet_type = msg[4] + msg_length = data_length + opt_length + 7 + self.logger.debug("enocean: received header with data_length = {} / opt_length = 0x{:02x} / type = {}".format(data_length, opt_length, packet_type)) + + # break if msg is not yet complete: + if (len(msg) < msg_length): + break + + # msg complete + if (self._calc_crc8(msg[6:msg_length - 1]) == msg[msg_length - 1]): + self.logger.debug("enocean: accepted package with type = 0x{:02x} / len = {} / data = [{}]!".format(packet_type, msg_length, ', '.join(['0x%02x' % b for b in msg]))) + data = msg[6:msg_length - (opt_length + 1)] + optional = msg[(6 + data_length):msg_length - 1] + if (packet_type == PACKET_TYPE_RADIO): + self._process_packet_type_radio(data, optional) + elif (packet_type == PACKET_TYPE_SMART_ACK_COMMAND): + self._process_packet_type_smart_ack_command(data, optional) + elif (packet_type == PACKET_TYPE_RESPONSE): + self._process_packet_type_response(data, optional) + elif (packet_type == PACKET_TYPE_EVENT): + self._process_packet_type_event(data, optional) + else: + self.logger.error("enocean: received packet with unknown type = 0x{:02x} - len = {} / data = [{}]".format(packet_type, msg_length, ', '.join(['0x%02x' % b for b in msg]))) + else: + self.logger.error("enocean: crc error - dumping packet with type = 0x{:02x} / len = {} / data = [{}]!".format(packet_type, msg_length, ', '.join(['0x%02x' % b for b in msg]))) + msg = msg[msg_length:] + else: + #self.logger.warning("enocean: consuming [0x{:02x}] from input buffer!".format(msg[0])) + msg.pop(0) + + def stop(self): + self.logger.debug("enocean: call function << stop >>") + self.alive = False + self.logger.info("enocean: Thread stopped") + + + def _send_UTE_response(self, data, optional): + self.logger.debug("enocean: call function << _send_UTE_response >>") + choice = data[0] + payload = data[1:-5] + #sender_id = int.from_bytes(data[-5:-1], byteorder='big', signed=False) + #status = data[-1] + #repeater_cnt = status & 0x0F + SubTel = 0x03 + db = 0xFF + Secu = 0x0 + + self._send_radio_packet(self.learn_id, choice, [0x91, payload[1], payload[2], payload[3], payload[4], payload[5], payload[6]],[SubTel, data[-5], data[-4], data[-3], data[-2], db, Secu] )#payload[0] = 0x91: EEP Teach-in response, Request accepted, teach-in successful, bidirectional + self.UTE_listen = False + self.logger.info("enocean: sending UTE response and end listening") + + def parse_item(self, item): + self.logger.debug("enocean: call function << parse_item >>") + if 'enocean_rx_key' in item.conf: + # look for info from the most specific info to the broadest (key->eep->id) - one id might use multiple eep might define multiple keys + eep_item = item + while (not 'enocean_rx_eep' in eep_item.conf): + eep_item = eep_item.return_parent() + if (eep_item is self._sh): + self.logger.error("enocean: could not find enocean_rx_eep for item {}".format(item)) + return None + id_item = eep_item + while (not 'enocean_rx_id' in id_item.conf): + id_item = id_item.return_parent() + if (id_item is self._sh): + self.logger.error("enocean: could not find enocean_rx_id for item {}".format(item)) + return None + + rx_key = item.conf['enocean_rx_key'].upper() + rx_eep = eep_item.conf['enocean_rx_eep'].upper() + rx_id = int(id_item.conf['enocean_rx_id'],16) + + # check if there is a function to parse payload + if not self.eep_parser.CanParse(rx_eep): + return None + + if (rx_key in ['A0', 'A1', 'B0', 'B1']): + self.logger.warning("enocean: key \"{}\" does not match EEP - \"0\" (Zero, number) should be \"O\" (letter) (same for \"1\" and \"I\") - will be accepted for now".format(rx_key)) + rx_key = rx_key.replace('0', 'O').replace("1", 'I') + + if (not rx_id in self._rx_items): + self._rx_items[rx_id] = {rx_eep: [item]} + elif (not rx_eep in self._rx_items[rx_id]): + self._rx_items[rx_id][rx_eep] = [item] + elif (not item in self._rx_items[rx_id][rx_eep]): + self._rx_items[rx_id][rx_eep].append(item) + + self.logger.info("enocean: item {} listens to id {:08X} with eep {} key {}".format(item, rx_id, rx_eep, rx_key)) + #self.logger.info("enocean: self._rx_items = {}".format(self._rx_items)) + return self.update_item + + def update_item(self, item, caller=None, source=None, dest=None): + self.logger.debug("enocean: call function << update_item >>") + if caller != 'EnOcean': + self.logger.debug('enocean: item << {} >> updated externally.'.format(item)) + if self._block_ext_out_msg: + self.logger.debug('enocean: sending manually blocked by user. Aborting') + return None + if 'enocean_tx_eep' in item.conf: + if isinstance(item.conf['enocean_tx_eep'], str): + tx_eep = item.conf['enocean_tx_eep'] + self.logger.debug('enocean: item << {} >> has tx_eep'.format(item)) + # check if Data can be Prepared + if not self.prepare_packet_data.CanDataPrepare(tx_eep): + self.logger.error('enocean-update_item: method missing for prepare telegram data for {}'.format(tx_eep)) + else: + # call method prepare_packet_data(item, tx_eep) + id_offset, rorg, payload, optional = self.prepare_packet_data.PrepareData(item, tx_eep) + self._send_radio_packet(id_offset, rorg, payload, optional) + else: + self.logger.error('enocean: tx_eep {} is not a string value'.format(tx_eep)) + else: + self.logger.debug('enocean: item << {} >>has no tx_eep value'.format(item)) + + def read_num_securedivices(self): + self.logger.debug("enocean: call function << read_num_securedivices >>") + self._send_common_command(CO_RD_NUMSECUREDEVICES) + self.logger.info("enocean: Read number of secured devices") + + + # Request all taught in smart acknowledge devices that have a mailbox + def get_smart_ack_devices(self): + self.logger.debug("enocean: call function << get_smart_ack_devices >>") + self._send_smart_ack_command(SA_RD_LEARNEDCLIENTS) + self.logger.info("enocean: Requesting all available smart acknowledge mailboxes") + + + def reset_stick(self): + self.logger.debug("enocean: call function << reset_stick >>") + self.logger.info("enocean: resetting device") + self._send_common_command(CO_WR_RESET) + + def block_external_out_messages(self, block=True): + self.logger.debug("enocean: call function << block_external_out_messages >>") + if block: + self.logger.info("enocean: Blocking of external out messages activated") + self._block_ext_out_msg = True + elif not block: + self.logger.info("enocean: Blocking of external out messages deactivated") + self._block_ext_out_msg = False + else: + self.logger.info("enocean: invalid argument. Must be True/False") + + def toggle_block_external_out_messages(self): + self.logger.debug("enocean: call function << toggle block_external_out_messages >>") + if self._block_ext_out_msg == False: + self.logger.info("enocean: Blocking of external out messages activated") + self._block_ext_out_msg = True + else: + self.logger.info("enocean: Blocking of external out messages deactivated") + self._block_ext_out_msg = False + + def send_bit(self): + self.logger.debug("enocean: call function << send_bit >>") + self.logger.info("enocean: trigger Built-In Self Test telegram") + self._send_common_command(CO_WR_BIST) + + def version(self): + self.logger.debug("enocean: call function << version >>") + self.logger.info("enocean: request stick version") + self._send_common_command(CO_RD_VERSION) + + def _send_packet(self, packet_type, data=[], optional=[]): + self.logger.debug("enocean: call function << _send_packet >>") + length_optional = len(optional) + if length_optional > 255: + self.logger.error("enocean: optional too long ({} bytes, 255 allowed)".format(length_optional)) + return None + length_data = len(data) + if length_data > 65535: + self.logger.error("enocean: data too long ({} bytes, 65535 allowed)".format(length_data)) + return None + + packet = bytearray([PACKET_SYNC_BYTE]) + packet += length_data.to_bytes(2, byteorder='big') + bytes([length_optional, packet_type]) + packet += bytes([self._calc_crc8(packet[1:5])]) + packet += bytes(data + optional) + packet += bytes([self._calc_crc8(packet[6:])]) + self.logger.info("enocean: sending packet with len = {} / data = [{}]!".format(len(packet), ', '.join(['0x%02x' % b for b in packet]))) + self._tcm.write(packet) + + def _send_smart_ack_command(self, _code, data=[]): + self.logger.debug("enocean: call function << _send_smart_ack_command >>") + self._cmd_lock.acquire() + self._last_cmd_code = _code + self._last_packet_type = PACKET_TYPE_SMART_ACK_COMMAND + self._send_packet(PACKET_TYPE_SMART_ACK_COMMAND, [_code] + data) + self._response_lock.acquire() + # wait 5sec for response + self._response_lock.wait(5) + self._response_lock.release() + self._cmd_lock.release() + + def _send_common_command(self, _code, data=[], optional=[]): + self.logger.debug("enocean: call function << _send_common_command >>") + self._cmd_lock.acquire() + self._last_cmd_code = _code + self._last_packet_type = PACKET_TYPE_COMMON_COMMAND + self._send_packet(PACKET_TYPE_COMMON_COMMAND, [_code] + data, optional) + self._response_lock.acquire() + # wait 5sec for response + self._response_lock.wait(5) + self._response_lock.release() + self._cmd_lock.release() + + def _send_radio_packet(self, id_offset, _code, data=[], optional=[]): + self.logger.debug("enocean: call function << _send_radio_packet >>") + if (id_offset < 0) or (id_offset > 127): + self.logger.error("enocean: invalid base ID offset range. (Is {}, must be [0 127])".format(id_offset)) + return + self._cmd_lock.acquire() + self._last_cmd_code = SENT_RADIO_PACKET + self._send_packet(PACKET_TYPE_RADIO, [_code] + data + list((self.tx_id + id_offset).to_bytes(4, byteorder='big')) + [0x00], optional) + self._response_lock.acquire() + # wait 5sec for response + self._response_lock.wait(5) + self._response_lock.release() + self._cmd_lock.release() + + + + +#################################################### +### --- START - Definitions of Learn Methods --- ### +#################################################### + def send_learn_protocol(self, id_offset=0, device=10): + self.logger.debug("enocean: call function << send_learn_protocol >>") + # define RORG + rorg = 0xA5 + + # check offset range between 0 and 127 + if (id_offset < 0) or (id_offset > 127): + self.logger.error('enocean: ID offset with value = {} out of range (0-127). Aborting.'.format(id_offset)) + return None + # device range 10 - 19 --> Learn protocol for switch actuators + elif (device == 10): + # Prepare Data for Eltako switch FSR61, Eltako FSVA-230V + payload = [0xE0, 0x40, 0x0D, 0x80] + self.logger.info('enocean: sending learn telegram for switch command with [Device], [ID-Offset], [RORG], [payload] / [{}], [{:#04x}], [{:#04x}], [{}]'.format(device, id_offset, rorg, ', '.join('{:#04x}'.format(x) for x in payload))) + # device range 20 - 29 --> Learn protocol for dim actuators + elif (device == 20): + # Only for Eltako FSUD-230V + payload = [0x02, 0x00, 0x00, 0x00] + self.logger.info('enocean: sending learn telegram for dim command with [Device], [ID-Offset], [RORG], [payload] / [{}], [{:#04x}], [{:#04x}], [{}]'.format(device, id_offset, rorg, ', '.join('{:#04x}'.format(x) for x in payload))) + elif (device == 21): + # For Eltako FHK61SSR dim device (EEP A5-38-08) + payload = [0xE0, 0x40, 0x0D, 0x80] + self.logger.info('enocean: sending learn telegram for dim command with [Device], [ID-Offset], [RORG], [payload] / [{}], [{:#04x}], [{:#04x}], [{}]'.format(device, id_offset, rorg, ', '.join('{:#04x}'.format(x) for x in payload))) + elif (device == 22): + # For Eltako FRGBW71L RGB dim devices (EEP 07-3F-7F) + payload = [0xFF, 0xF8, 0x0D, 0x87] + self.logger.info('enocean: sending learn telegram for rgbw dim command with [Device], [ID-Offset], [RORG], [payload] / [{}], [{:#04x}], [{:#04x}], [{}]'.format(device, id_offset, rorg, ', '.join('{:#04x}'.format(x) for x in payload))) + # device range 30 - 39 --> Learn protocol for radiator valves + elif (device == 30): + # Radiator Valve + payload = [0x00, 0x00, 0x00, 0x00] + self.logger.info('enocean: sending learn telegram for radiator valve with [Device], [ID-Offset], [RORG], [payload] / [{}], [{:#04x}], [{:#04x}], [{}]'.format(device, id_offset, rorg, ', '.join('{:#04x}'.format(x) for x in payload))) + # device range 40 - 49 --> Learn protocol for other actuators + elif (device == 40): + # Eltako shutter actor FSB14, FSB61, FSB71 + payload = [0xFF, 0xF8, 0x0D, 0x80] + self.logger.info('enocean: sending learn telegram for actuator with [Device], [ID-Offset], [RORG], [payload] / [{}], [{:#04x}], [{:#04x}], [{}]'.format(device, id_offset, rorg, ', '.join('{:#04x}'.format(x) for x in payload))) + else: + self.logger.error('enocean: sending learn telegram with invalid device! Device {} actually not defined!'.format(device)) + return None + # Send radio package + self._send_radio_packet(id_offset, rorg, payload) + return None + + + def start_UTE_learnmode(self, id_offset=0): + self.logger.debug("enocean: call function << start_UTE_learnmode >>") + self.UTE_listen = True + self.learn_id = id_offset + self.logger.info("enocean: Listeining for UTE package ('D4')") + + + def enter_learn_mode(self, onoff=1): + self.logger.debug("enocean: call function << enter_learn_mode >>") + if (onoff == 1): + self._send_common_command(CO_WR_LEARNMODE, [0x01, 0x00, 0x00, 0x00, 0x00],[0xFF]) + self.logger.info("enocean: entering learning mode") + return None + else: + self._send_common_command(CO_WR_LEARNMODE, [0x00, 0x00, 0x00, 0x00, 0x00],[0xFF]) + self.logger.info("enocean: leaving learning mode") + return None + + + # This function enables/disables the controller's smart acknowledge mode + def set_smart_ack_learn_mode(self, onoff=1): + self.logger.debug("enocean: call function << set_smart_ack_learn_mode >>") + if (onoff == 1): + self._send_smart_ack_command(SA_WR_LEARNMODE, [0x01, 0x00, 0x00, 0x00, 0x00, 0x00]) + self.logger.info("enocean: enabling smart acknowledge learning mode") + return None + else: + self._send_smart_ack_command(SA_WR_LEARNMODE, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) + self.logger.info("enocean: disabling smart acknowledge learning mode") + return None + +################################################## +### --- END - Definitions of Learn Methods --- ### +################################################## + + +################################# +### --- START - Calc CRC8 --- ### +################################# + def _calc_crc8(self, msg, crc=0): + self.logger.debug("enocean: call function << _calc_crc8 >>") + for i in msg: + crc = FCSTAB[crc ^ i] + return crc + +############################### +### --- END - Calc CRC8 --- ### +############################### + + def init_webinterface(self): + """" + Initialize the web interface for this plugin + + This method is only needed if the plugin is implementing a web interface + """ + try: + self.mod_http = Modules.get_instance().get_module( + 'http') # try/except to handle running in a core version that does not support modules + except: + self.mod_http = None + if self.mod_http == None: + self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_shortname())) + return False + + # set application configuration for cherrypy + webif_dir = self.path_join(self.get_plugin_dir(), 'webif') + config = { + '/': { + 'tools.staticdir.root': webif_dir, + }, + '/static': { + 'tools.staticdir.on': True, + 'tools.staticdir.dir': 'static' + } + } + + # Register the web interface as a cherrypy app + self.mod_http.register_webif(WebInterface(webif_dir, self), + self.get_shortname(), + config, + self.get_classname(), self.get_instance_name(), + description='') + + return True + +# ------------------------------------------ +# Webinterface of the plugin +# ------------------------------------------ + +import cherrypy +import csv +from jinja2 import Environment, FileSystemLoader + + +class WebInterface(SmartPluginWebIf): + + def __init__(self, webif_dir, plugin): + """ + Initialization of instance of class WebInterface + + :param webif_dir: directory where the webinterface of the plugin resides + :param plugin: instance of the plugin + :type webif_dir: str + :type plugin: object + """ + self.logger = logging.getLogger(__name__) + self.webif_dir = webif_dir + self.plugin = plugin + self.items = Items.get_instance() + + self.tplenv = self.init_template_environment() + + + @cherrypy.expose + def index(self, reload=None, action=None, item_id=None, item_path=None, day=None, month=None, year=None, + time_orig=None, changed_orig=None): + """ + Build index.html for cherrypy + + Render the template and return the html file to be delivered to the browser + + :return: contents of the template after beeing rendered + """ + if action is not None: + if action == "toggle_tx_blocking": + self.plugin.toggle_block_external_out_messages() + + tmpl = self.tplenv.get_template('index.html') + return tmpl.render(p=self.plugin, + items=sorted(self.items.return_items(), key=lambda k: str.lower(k['_path']), reverse=False), + tabcount=1, action=action, item_id=item_id) + + diff --git a/enocean/eep_parser.py b/enocean/eep_parser.py index 9043da2a0..26bd0e4cc 100644 --- a/enocean/eep_parser.py +++ b/enocean/eep_parser.py @@ -131,7 +131,7 @@ def _parse_eep_A5_06_01(self, payload, status): if (result['BRI'] > 0): self.logger.info('enocean: brightness: {0}'.format(result['BRI'])) return result - + def _parse_eep_A5_07_03(self, payload, status): # Occupancy sensor with supply voltage monitor, NodOne self.logger.debug("enocean: parsing A5_07_03: Occupancy sensor") diff --git a/enocean/locale.yaml b/enocean/locale.yaml new file mode 100644 index 000000000..80d8410b5 --- /dev/null +++ b/enocean/locale.yaml @@ -0,0 +1,26 @@ +plugin_translations: + # Translations for the plugin specially for the web interface + 'Aktionen': {'de': 'Aktionen', 'en': 'Actions'} + 'Blockiert': {'de': 'Blockiert', 'en': 'Blocked'} + 'Ja': {'de': 'Ja', 'en': 'Yes'} + 'Nein': {'de': 'Nein', 'en': 'No'} + 'Ein': {'de': 'Ein', en: 'On'} + 'Zeit': {'de': 'Zeit', en: 'Time'} + 'Item ID': {'de': 'Item ID', en: 'Item ID'} + 'Dauer': {'de': 'Dauer', en: 'Duration'} + 'Übersicht': {'de': 'Übersicht', en: 'Overview'} + 'Senden': + de: 'Senden' + en: 'Sending' + 'Die folgenden Items sind dieser Instanz des Enocean Plugins zugewiesen': + de: 'Die folgenden Items sind dieser Instanz des Enocean Plugins zugewiesen' + en: 'The following items are assigned to this instance of the enocean plugin' + 'UTE Listen': + de: 'UTE Listen' + en: 'UTE Listen' + 'Senden An/Aus': + de: 'Senden An/Aus' + en: 'Tx On/Off' + 'Wollen Sie das Senden wirklich umschalten?': + de: 'Wollen Sie das Senden wirklich umschalten?' + en: 'Do you really want to change the sending state?' \ No newline at end of file diff --git a/enocean/webif/static/img/plugin_logo.png b/enocean/webif/static/img/plugin_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1530243770188ed99feebcb2cde6ea771923df88 GIT binary patch literal 19435 zcma%BV|OJ?w>+_JPHfw@ZQHh!i8(PQHYetZZQHi(+~@rV_d|ED)!%xrTDx{tb(E5V zBmyihEC2vNkd_it`R@$+--3qxZyyjao&W%38>GdA)x6d(yP&f5)!R9`*B#0xGX>6) zx66r(S)WCmilcWvIjv%k+a60uqQ$Wy1TKc*O+E5bO<%2%h{Be{*K6XU(O2T5$bdV zVe+4I0^c;%u^ks56h(EetRP}WNumnPh7*m=A9e~c#HNH#G=pY7$W9j!r4AERjzbc; zPoFoyk-;EGS5i_zW{3jQVj>0Gr>)={!U4k;;dkwq@h{&n3dFym1?V+fVPimdAXuo) zk{l9%qF-lFxuK|IrQG0F>f1y{$huOoGi*Z=0kA`z03j%RO4u?h_N4JE*5I3vXu+JQ zGtdHYw>%SQ#AS3UGLkwKksSub(%4WPGCUx?1r_n?%7*;LOCM=C+gN~%dMh%FO;Z)j zP?}H?*fW-pK;%hDbUzcTARRTp_lFzCsvOyu__r5>A#-8ig~Aw5a@_ z=kuy?4nH@!pL1r?@FoAp+fZG7#&Xh2a*{Tg^YU^zd>M5*37WjtyqkM5(7YShbFYwg zFArrrcq*c_w{rKB^-@X0_00~yrw)Pyh8tMV7G+VmS6{@u%!S2WRxQMN)I8dO-r7j~ z`@O2_iRWzZNPpmJ{SDr66h0l)s>vWpf?WgVgFdmpd1c-DrXy zk3kO#lV1LiLNCd7i}Q~*4`_^zH+o&9cpUayYt0S|)A394MiAy_gqiT2rz%14%{O&N zy;>8!7p$b`=L@1x#ho1jT{IGG@c;PF>QZ!7E&YWh+uRpi|6Y6D53OJdEM{$V640j) z;Wbj>>W601VUZ!FD!aLyt;$o%#4>&P_d@f-0v50kN)R7V$j7C#-CY-7k)5Tdk)32% ztfpWU#DO5Nm2B7dh;pjnxihP)YdwS7up-k$E$!+H2n!#)pv02-$2bD!H1bpaL z`?r>#<|k$xI-mAVIHv-|P}ZU(F2RX-Z|k)?8Pi#sq&DRSal)MFGI02{NFT8QS{_%H0c=BIHEp3tR&-W>%1aRfN2^g^IashcT8=3g%DC@mPjF4i7mAwO&`-Wg?l) zAVP7=;$ln77o(s6hF>BIvRa^n;W|j=?4kmmBYB_%a;z5+#PA4UGQFpAN`(^uB6JcJ zh}YzV2WY;;O6;wdShV=-z-!5Ovv{sfuMeKcMt!Yd{OeVzNx z^lG|}$ryX>w)06WUovPPaDc^@D_08t0S!&ZJo;~~OxVv{VN;FZ%qj)k=eIjb`1k&| z^0hIn76!lD3eA6pL2^6Mj}X#z*~b(KT7?3vfFKE`FBKIjw&dRnuD6yT=+FnVtD(Jv zxjR=jP`Qe`OR(RH{c?k|_|jfdojJj)QSPYgP!^!2R-i#Lpxn|-qIqcHdK_n?0%(fA zOGo*ezh7Df>z~7c%GT?%mG*Vn1c+rhhzPL#a3ttN>`$>LKH2Vk#efV%-IHi=6;_LU*-G?<`pcTI6_c&Ej2Hd`Rv$w$>R z;K&E7X`y$tKJa+>EC4w}KKv}+zI*3sXDNZmie!oG%H2_0zn;n!97(^Em?B&O@Adbz zvb4>QeIy5~3H$XBjSI6B_ew4EDA@ z`lSC!LF}=CZ6)GtpB#+%pVv7CqBt^p(tTV9b}heu#=Q1wfD)bl@#y$BO8#lXB&;ld z1JbdZ4`w8xeR(J4-li;;BvLLDw~J7Bj-> zw(#!_IeGkuTs6_RcDe@h3QW>G>@UVPIJUZZ>>!T%OxC-l`M(s5*h=4oAO=i2=q2~y zMi5^hwl*}0cd3MmEAfIh<3|Iy0v`7VwgJ9hXtsf^$hnO;GL7Og+t=-6C*16bmmox3 z<$w&3bx*Gb^iL)Z>ghS7;YDT&8_KxMw`OC6vVh0FRKcIA#tTPpK#-NFN(;$rPRN8E zIo*SwpC!=F%H37^@?4REC#&j{K+lPWa7c>h>s8TG!Olq!Le@H&) zbs=t^j{9VOj6lG8d2OKiReZ!R{W`y6#y+(vu5^kLE8xv+^@*D2@7-B@ZVWxcNK?;95EocDk5%oVprySc6B|CSgZsqtqunfRF*J%3jKD z97l)8G!7X^tdQ!3=!ix&9HQ9GCQspz?w13NLz1D$4<=eGdyfoY9|MV#u5BSkdz7Z! z9PjmFl05(Xlh?lElrWu(NpXlEfNnjA}nC{pnGCoGy_C`tULND?BDHAQgqnSfx ztNRcrI2vKUF^fGFI>w=OQ;i&eQjDM87|_)|9uoPnd#;48e#wLKr;muJ`HI}k+D{&L zE!(b|*JHIe3oV{t?!q);i2@4YXwkL0TvX|yWq@k=O@wN~6eL%Q3_tC^Dg)>+xzsY5 z9HwgwTYWx686B;>&okrXXR0A=wS?S+$vv#WC+A48fThULNL27LTiu!ohUTSoR!tA6 zx6G4sJkKz3Dq=A-bt?A#Rpn zKz7f8k{fSaB#698%w?%Wn?9$f?{En}cbsED*xUHmFy^&3rFV` zu(FYEAa?hbSk!4z`$&dJivx%zhbT{+i)0>A%@xRC&8xe#X+Q z-nd)MO8b1*Y-z3arq|q@gXq_6*;ifX#|&Zvf7&n*%6-I}@1lu#sgZ`qWogCiz}IsY{{g(`^$arRQNrc9dsaA&$}Y0%<2oBvKm#Dlm>Zw>_dSzx zyGQ53(=%1jdp74npEK~?^^}F&KeP&bP2J#?c!*?Px}{iqex2h#Mr3;oKR`7%o(6#$ z4ez6jPX>jo~bR`nQYGP|wj{p#7LQM%P2vuYHhh|I9qazm#1Q-$HP zfQi`Rkyt_1(8VXfPE)~M6*O5J>Qhy%@N(h#xjU2NYu3{!2$G&p+>+MW`LsQq;$goQQn-USu{xb{&6aY)caGJ5@f!iwXE~Hzql`(9C!sNs zk{}t?NB~)mUPdWz#_tfT@h{Ixjee8e@C>mi0Cbxy>U`8I6(R-Kn@M~R1guv*22%8~ zB!dRiZ!88Qya89wZXjx)$LTsT&N9z;0qw_9M$%(L0vwTTRA=sUEvWR$i9X~Vjf10=g{$0uin!IcCsFlGz)8BO&a1hB!^DpEiT=-nq=e-vKoUWy-k`_vMXK% zQrsa|>3Kj-`8Cst#WCIUFvi}~gSOKRmew$&EL@f>g+ZFR!aDLR8>AQvGN|f?a7Yaw zm^DOQL5(!%;0<) z`VRQxWDQgCaB8G_>|hu1c&^KH3qMnyG&FfWN8!48-cO|;g>9?By&iim4Z8*az<7=d zR{&-VlUkt;)!H@DNNQBR#3hq*#RXRTHFet%G*7n-%NkAlBOhWmm(cHsn+IhMC5PCn zcX?oZ9=FFWd08IQ;R6=t!Su8E%+&i*cxlPRoj<+Rm`0sS!~r+AqL#9z8tX_clSc^6 zChUy(e?=!pc&-#atE{TR=Gfm)4iLDBFY94-b-jq0*>m%Nw$N#RZixRSwxA%$Rk9ld zFnZrNUUbGs!ElL+{3EkC{$8xP^<${eeqAPO@U{>)VbFC|E7hG7smQ8Qya1D2fUdIs zu08z;&UlWPV4D^CQ`P@rySHMaK=9QJmw@LsMtR@ z?{gVOVWp)Ba9aZASG9kvPc|9!IKC`{JXqD6GFCvF|Rvfn8z)OhM-rKnvBl>)g9TE`+2jguE-n2Gj|c1N$Wf++R6=+;u;q zF+BNMk4D1UY=KOWgn2E>=@t`2R8+Dj3;8hcp#=w(L=1mqw2YhJDss3ymU|8+MnlXO z0t=(Iso||nVCK#$<+z?6PY~N^S8o7R=7MOq{b9vT`km`+@D5zxZ3_wS)0_c6x8^^s z*zR_cSy$jA{nsTAp%<^`Ft(5C=6xe2(?B+gia%#IUe_IJ4aU81BmRN71BN#`98Z)r z`WGt$8qIrE>)4bzV)dYkZw1hqDLji*#EyjuYysZKNX_#4KIh$T6L6)Uf%w1<-yJ|W z1hVU-@i?i-2?^2(p4G++k}}kXl6npy+i7;a>kpcQ>UQ@d(6ynR;4eD4e6B^!FtK)m zCCMpzm@POoB$(``F<)LJMoq|1`OB7EEn~LNSK!vmCsM%sd3;%VNT?F5RLqDf_pOFs zK2+Q@EufUaj_&EX&+$X8G1j6ZUZrd$UEsMaPoU#mbES6e{T5AXDkr-UbLBvrbPE|> z8y1@l3`rdvGB$az&gRxxf4$1_6aL&xv!DV4=XpS+-aq1ss=tUJsYVvdni;wi`x|cE zIN^FPOq2)@f6*X4>jbkmMRt#x151%?tu zp7$V3g+tMhZSfh^%eh!p>61Nn?tRZ+f&Z+C^yjMKg7E#46Zzpvu90HEO>(}5p^)A< zVugSS`BL*gH_EG=KL6h`jkt+A7>GL3QlN5P`S^A}RUOpzoBm!*phQZps%fFSTQ*ZM< zoSr6c+8WTo`6rf(m+85Cj?Y#~O8P0?D~Zj^pY4$Vk#Y<}MP7l*FiIGW@sHU;fd-St z`UXU)zNOKBqSpU2qb%fw zU=zm_1Ipg}DlKyT>i3#cWqtXmjU zQsu@E{>|YkZTA_O(Ocj#n&u^Cjnup$EW2(HG;ah@>n;KHm4$8sLx{_Hbd;MTZxX`S zL7$J|V+;-~9FO0d$yU0qY*uqv3vvr1?4}lP%W09YCAeNP^!ijRwW2TT;d_hYUjIWd zD=7b(``oLDi9XBUxIw70;+#Q8W;R)gK>D;)0rGnf_W1MKG2H;=e3OH0Mq%SD1yvn_ zD+H_*;u#NMmxGbSO`J+?=8aI^y%%cy<04E`Ui+~TBiJ2}+o+1We95vr7WOOnJym_A zrATt3lfXt6kKzwP<=*1Jzcw?auRF@$3bo^s1RJsD@hV%K+B;QLFtoN{VUQNP<{tk@~W74i6S&>fSzFJYJ-D= z-X9~FHi-B>e2%VKGz};1Ao`FU!&tn7Bic;Z(A{D!_o~5DIpd`lKus0M1X3Z}mbp!( z+qiP$_g)`i_&p>)cuSx*L2-S{Fj7I~{prv;5SQjqEgzPT`!8rYa6i&9fLeET?QwBk za65dy4(xIk6`8SW&jwMgr#Aqs_i<>TJ%zX_VcJRbg3Hra|NBlizIh;5|C?51rCHP? z@CHDu-|6oe1rHCS&haAiU^-L1c6ZyLzHt*+sC3!j`oW{*!c!pKal5Yz=_qijl6c#tChnTuc!&*a>+RKTqdG|1P;}?*o6uv|KTld$S)-~1c@62 zv#6Ph&bf59ZJv_V%irE+q!JtS#rFFKGb@nv{FZ_F?<2>u`&-={BOBv zRxuet1(C9nGo57tNGUzG96#k)3L1~GB!>|FRDP)@=_~tyZ=T2g>i}h7d;i7K%hEDs zo_5P!n(wlm?;$zW1?ayfD_j2hm+!gzK_?p-G_cSmNG{1=@#NUsA1MPP90qR3yXR;L zSMaSp9xt*hpB_^!P6#79@u|-^Eo~$5la^2VvB7b6|qzR5nud@#< z0>Kb1K7KR)d_uO#or26y#{D&qM_c@fzXIoI`wO_vX$2K3C-XJSh79ntxxcOH{1>`MUY#cXrYW z${;`K@nHkmhjJKpF`_!7_0N+M1g(GY&1_JdUA?rMWUEXNb+61S;>T**-do(N5e%}C z|7r!3WR-WqV%fk(n9naT3tQiE1L=zCp&P6FC+2t>;ll0%B!@uH4EDd=!nr3s_ys;_ z%o8F1-?Lb5m~=!E4XuR$&;CT-4bAmxz2DcTFZMb1IxscbOyMu|+K&x&3CD_G? zODMoJ_QMt}&%;KmVEg;~21-s2WaW-0KKN|&D5L&s>=0=t*jG*r&@P`Pf0SqD36Fx1 z|3WaF)9;Ut249D4yuMHP zd5Z}2dX-&Jrt}n&=IlH0Y!fcDO6~DSvcp^9X#k^7ZF$zD_<-+xEb953YYqe+!ctx3 z+}_C>owpPl{+1i7;3l7iFX;ZepA&Z6i{=m}+#+Rq&d7D`yMwRhIUfZ*ouKLHYXxJ~ zwI~aHw>lI>X8Hku&y8L_bH`nXFr9|^vOQ{2G)Ed@&Q9JcipJxQ8E>iUmd<$nIwmU>QoqFs>6r=Fh zQC`~_7N@{_vt#o~i$k3b0JD87jC3`1t}azia=a|WeAnn)FW2sMvtnhc<2iW756EU6 zI%gs2qrX`&R~_}?nHc>ankpWkoS_7GO-ezVG}EOY37pQ24L`>9WlO&SIIHkoTc9AT zVYn!3#@l20fiq9pRC$Wn5lciyPrq=Uju^2C!W64J_ZV*ndE1%kvq)u)E}Z*Htfut% zaMcJ%fNHqf$}yk@f#;{R4BVx6Au*0V`?jk8Sw1>(*$zXpx_u)00%hX%sP+1IgB~a| znXk_iU2^nO$Ie>TU(m4r#wVD#rou{b7M0iP+%ALviFcRnMm$I0+aAX9_FT>@VO`28 zDjSA8f6=C6!m|;%#{x|WRZT(GVjkQ1Ltg3R6QSYT#txVguXVL;6jYqn9Vd+&KjB8h_3O*dclEd%ptvyoG)ZxH{W145^XQ*Dt2uzRog{YDw+ zb11veUv3M`q5V&wKSztH6N_0)4fxtUvmSHPFi?=iR0V~G8+QqMj1ShcTGIP?3}3qQ z5_+RbZxvEI9*KE$Owytrr&3sI&308?P$%paxk#a0tZIs>F%{XZxJ}K5t19qaWK`Aa zwAmd$Hg6F6h@mKTc&zI&rb?1WS}JH6Q|v75Y|l?W4C(E@DU{@VoVK4C^*KK&x^TlSHxiX9B zr3rz`&)5LDZnTs#ec~u-8j31xh0p4u+V|y!i|@ygw9Bg7?`rL0X{d>hp(^0Tt2$hS zi$oz&Q&(8_B2opf_2p@|rJT;|<>N1F`Kb6XsVX3V_ zQwx9FA=?)QuadJUbDhK-!ryfV7|>R0JEHI|X&l{`Bsg^%_VPAP2X~@^AB-`%f4@lM z#P)TX-uOl_q&22_Ee8T znsVlBWxjP5!-XgcX3;Q(LN$|%IXvgKhHKj`E^n1JNc8mw;L1|#DoU#;*aHUTOW4_O z@%!!IECslk27&!`Gx}VGGn4|}0|SPy3_=U=c&n2Y)-RiCebEg#AJ$*FXK)egC1v1z z0r~Kcu;d&W&3S@PFFS@^PmV8w&Cf{7IQi%q8tH1s&4{MDMfN5^IAVRHp%;lX8#{sx zGb6)KmALH3d#OF22u+q~d&TT$YDXYhZQxmNalJ_g{Zu8XEsbSzQ&@^03n@GNkL}!4 z;#0HKHFXKv=4Na!mtUYv*YW|a(C~qlB+IlN?vk&(LXEA;-jY z@FTV@^Wd0GAqlOEtV0lsudeMpv^GMF3a|0xBJH*Jb(SGo&EF_x`joflQmxMK)Gv>? z8w`M+S2yKD`APONd^sL#VYkg;)Wq_ZUvfbugtMdUtNU_~N0A>ul>WseGvd!db8wym z*GC)o&s#d>&jBvgk3~>EhT2M)MIDwl;hrwnJOk2!Yl3>A@_7Qj)AVcNm%v+vF5%C+ z9C){O5J>25PDojQ6=IMgL(afH%4|si6uUNY9{?b7CI0K}ZBkwL`sV`f?{x=WO`B?1 z2Y*gAtpcxWJ6)@MQBKq;s<07^Jo~xyRhi=F&DcY_!iRLhYBSgs7>M>RsZaN;cV>!$9>Ri#XWyM*M!m~K*UP`v_g2dCIr->Bj)da- z(82q2{^6S!fiwpHc*nICdmmNXiITu>({G^}cWHTd3(?y5bv(R}mmK#Y&F=fOIG!m6 zK52ar;=jA=I-(k!9W#^)xJx&&tPZ~Kyqb8tmw3E220W>>=p95JhV(f=B|U5kv~^>3 zv9k`-2m?Q1N#l>`X5C)~h_!QaB&UFp<{Z;4#6sm$sgFft9N*f*Juu3E6cmcw4W=K* z6yXD^RcjFbrLT8U#2{)oT!_zj!$@uNhQi}ll=J`(*M|orM|*GYE*I+UwbFGq4OB*G7+-{$D zf}Wo#!RP-Y4IE+k#R274ecEZ9W(RpOzu0^rz-eU_ z-d2zv5OCJ<^MgrZ&3mpDGl8mIvF|ip{Is=I0v5KcEW};AsI!>McOPTuA8Y6eHo zn~x9=H(ipG}Q_nko7_PweYz^gQ3P5NkIcXnIQL485g)Fwlwi6Z#_eVeoOV zSLB!Ol@C8K_}DGo1WaYvamX}78OVc_R89Wzd}^)I=)3=m{-}z8QhMK3@UtT>yRzl= zTe%~Zt6|HMy`}gW9RQD-SRzisA{LePpEzliCDguq*oY;zrvkBOfN5ZcDbV3`^Grnq zHHwBQ;y!OL=RU}&NZ;zRo0e~RiRWn;s;`9t94q)VKli9uk{NI?JsNXD`+&t=K#R=pFE#o*DV0H(T#Gr zLq2s1fLBbHZ$2a z1)0}Y%}&3m*P;}AlGCNEn7Om_+yq163N!X8!xePy8lU5OM<7eFGkohaWM!-Jx)uU| z;GN9Ti3pJJx7LCnZLrwN-U7$rK&d2bR;D|DVaoARrKr%w;PgYS~>37#wKZ5_Jk;iVoN5tTFC5ckS zq_TuBVDuRU)9SLDr0LKhjW!4B<_3$oirRt)c;%#|po5TAszF(N7}j^~)1Q$8;wa>+ zpPB&EPm^ab{}y<2=u-CTdG-B?B#UxuhUgnKt?f42YtZJz!)bM4654&Hk>l;MBS4}C zP|V!GQM`oC+zV?`(crjNGID)q#R$&?)&pj&elOvr%|vfw00BbExq9i` z(nIVlI-2@kp9u_|S7SHZljU|t(L!V^AOLxDz~)lka8g?~uk^562?St#vdq!f=YC3O zq{dpYMRgl!WEeQLru!^w*y{@r>QNDjq6TM{0dO|GUphZbXZDz_i+}-yUYpRU@3SyT zfCe)T0Q5$fGaj4)v8DErY3`3{%ToFV&M;h>b^Yr@6Ya*q`p%t3s(ZJA@=kYi`i^=VJ4-k>#oeKcwp}&a`_uv7N6P=Mo30-5XA|?Uq8s~#8xW3wR|MR@G|C;s-DMPWZtK~Q^9=iU#Z?eM?FRt$y@)m=D z33(d2dT8fg`E>PN+}R$z7L{c;dcAdu%Vi*vZ#|p!g8=BjQVa#XzX8{Ez3Oa^AB$K1 z-Y1SWzSmJ#HB~KZIF0dGhvlKCS#`(x004OqN`!A+i8Sv+yXMpAHdtl6z*(lIV@Hll zHqw+?b5xP`mcSMZ;H4Zbf}~Get%7_?4x9C;8kqOj6YG0ZL4Gsy_8fL$+RMPhkWmKG z84VFTXqDQb;a*izG1u$nVPz9$Zf*F*=ZhFB=&3!Qyr*0Y;#~cRx`?6YbdJ5J>$ml? zFc;zY7+zbD_m=;P>d64)`cl^wZ2quXJf6?pAo+zuM*`dyNX=pa+l(rvq$@DOp@vGN zrrGn70wcTkcDsxKv4&W~;rk*c{!>A! z^!F&s9;q7~I6oHomvvER{+=k!91s@d6EB60X_;b{=`6~~?LXG>7b^|3o27xa?g4bT zrwI=rqq1@*7D8q3SUu+F_L@H9Yj)J!Dx}%`q36L;*05@7x0?b1)}A!%8Jesi)8A;| zcKx47^y9RwR<+fk0U?V%;I}6zg2zEGO_a`L{w?rzcT~Im9op5XiMI@LdLmbRps!!# zVYT#9ar;I|Z}^iAB~{In zao{d2)nmW{@G`#G;Q;vT0td%TN>ysN=sEtmUox^>T16lk|zkWr>~PH z_z#6_F&hCGm?DA?8vXewL?23@=7fjBOYesx4I;} z*4w)OOoftXTlXkR|A02y%Jn&y2}2RXJZ}ZU6kt=G^gV~iDZDQ!+7Ql zb{NLBPj6OTMKud&{lc`!B$c+a!+uQSIs=hrlP(n=r>hibSu1EN#+5Y(&g>j^W61(m zIr6LxyxMC{sZemh@-&KaQk2Q-_5wda#u3*Bk2_yPi93+&X?ojkj-BsJWK#@fP%@o8 z#e1m$d&U9~nd||KE-;YFnPBYY_HVx};eDMCwrI;Ov<+Xq&$;e$(KxTv7)?lkD%$f_ z2F%qj6$2d23>!Lh9&WujZm_>?gOD>CV~G38C6Ixm_A*0ktZgrC5)qWY-8X*ejK!WA zfpTasSb2CxaUTNeQih;Ci;ZCv+`3a|8Wq(70j6# z7>2JkvD^7*FjlOO!@w1z^NL$0$&?FaP`Pdwa9F;XGidj8{P?Sv9ENLDP4sAVe2O>C zjy3zxTNopCh7@3wr(ORGq*uIL9|Jm%CJB4iRuu`HgLOH+> z#rRK$YjPXvlzF6>XkUdA9{4y)xw8F=%1LJ{k|T;kB}FJ}OE9s+T<5l9Xn@JLXOkDk zcB;zD(_C|OlucHOEvxg0kBdumoz=+MQ(^oJ1rYjaNyv?04$EcjCR)7Fchz#SeTc4p zmJ?q8cA~@)K|WvGB26NfrOce22VXRm7I!}%G)^b{UR=jBWTL|1DP0r$6B6LvWnW5< zAN`roMa5#RB>5isZAtJwf9$JaT?v#b28O7KOPfyStg2FkY5|<`&{S@lQ7W{?qmv~A z&qgUV4L(9t6w)A+(=AzssHW4yJ+FK(7b%rf9GHoW5R!1!UJ^lcbu~F88){-uvzD^Z zp-JyL`Ki7thXyiLbetH7iQ*jb_twLN@-s?KvP`fO|FGBqCE0~;!-u_V0d>v46sh`f zG4p(k#rzp!nI=iu(okHjl&J|}8OSnhU$}KABG+%6rY{X7s5R9}KGYH_^>-d$DU{Tg z8UOG}lNIVeb@HVnUsBDcL2yoaXY)8O9!Uzc>~~<{6Z7DtYEQEaF-=!`C;N=1)Tszz zAsnmODypQig_b2;3w~#ua54rcD!P=HtLu(GGgfEE6TR0U~ z`0E3=Vj>{&+h@fdp7Y(5iu7+Yhl(S?-7ZxSa`iEnuR+UT?iI8C*b?G-&3pUS_xeKg zqHnyRp+pKEVF&9`^dHHo4rG!fg(VFah<2_zNU~Zcph$1n%Nb+4C#F1eR94~Ztj*uq zed-&Of6 zSMO5C7`cNpu+0aP&}=C&HxX_xudTmt+KNS2JF5{kGq1DvvbM8%Zl8FVH;>i@4bnwT zLJ>8Ec1+t!o>UwX8*~8SQ-qnyo02rOl;V?x7Ic1NDBIxIT(X3QL?qI&RFEnL-h{09 zLhir;0(^e7?IiagDE#P)L07QPW;2}k(^`ll5BSh?XH30(*k7ujfISQE-g;QHtQRj3 zP_``ofFGFNFVLVdIH=WJILV4xMw#3Yep$q70@bdHuP_3N6mC==ZZ_daqwat4SMrH^ z+(Un$vNuXrn=C!=8g(0ltxu>^|7!_#!=;>hmnmT_iII^hZhjXOa`3;6umW6D4nqDk z%Ag)oQ*x?7-669c$@Z}QKm)$pZX?tvTjns|NH*5$qhrv~oXzmZO|lv4FGR~p66@h| zA={2RqkMBtLL`PWJYs{5*m#uJ*W*)K=-^Wey?0b0iiYq8vvUkAVf(={$toz5z-SWe zR%bgqF+5mL;8Kq^B`cKgvSDrUjf)iIxiy#X#;E`em0o`8fhII_vZjYMvr1 zP>js?n2{q2CDtHzKC@$8V90r(XyJlrm>2Cf=pKO}y#um0<`w6E&W-TwSth*GwI>ct zRGd&hqUZ6NBjvxgvv1iOzfS6GJ-AA295$=ho)5V;yTtz1wyh6pNX?)hLq zVmKrF?myl)+;e4!Zbio62wRgSh*0OoJGK}u%B&`&07icx0gr;vfKs%LH4AS>MhSU7 zi`3_9;e5J95Em}+J!|vvzPv|?IqRWc=iNo9B})?ifFV|oU=>--ER41wdk9-SR_o;T zB6{p~&|l}^UiL}Uz@H%fsd01+bL|=Nu|E!MzWv{gfgczEk1@Alz&jufr$e#rW9!iTdWRzEJZC&xX$`?$NP`~ zkHlXZ>n~MST&pQjVnXT}lsw@gm$(J~?63fA6A+>uazH4AP;iY|E&8?TWa6v=49Nq; zK=JILWl3*QF6pZyeo~H$W)TGCi5M^u6bjmRq<)|PvzdcJY>h?&{5cF80&q!{pFl1LlI6mT#?sYKq_QeuYe2<-Sni zpzUl3NI}5^j)H>T`3|_W4`hi^LHnl}rtG;SITkuOl$FK#vRWl^>L!YJVftx2OwhCz zeb=RUSuvw$#n|8odLa(6w05)Q-=}ugeqpnk6Q#UBh~7!5aQe2vsF7AYLJEP+zUqS* zjrl8x)06zUB)jr~*jjwb_yXOyE$ytv4(Ul4!&bcx6-oui)#{))Y7^_nQ4UQJVYR~K zX#%J?*%^kdyKWY;?Vr)`g71dm3eLJbkKIB_ z4ximX0HE?;e!z+|nelt_cs|lvhj=$Fq?g$kSYd+%GNV2bfdz*4LW|K#dzSY}SIZ21 zQ=_;2Gu*#W^jukz109Iaz@XtJW-=M7m`eQ5M#Gu!>zuLB*eJMd_+9GDLdi`BW9YbK z&q%uAVzVfatgpPU|8T#BHF!w_9OTMfrpXWSsZ?WjA7uBdhVzADeuc!$Ff;*)M;x6JLt#^? zAb(zD1+Gtsfr@BB{AqDY6Ut&E{tgPkjPQ*)$wdSJ5qVo*0*l<iX0`QpF<)pnGbwa@sq+k>BX_L@nv(cv22 z?Nm6g&olCBO@I1Kw!Lc4&-f&N))ImS&ld&M=Hk@ffp<6@^O~*g%C!Nop?Bn0r z$oJtFomC0)pQulGym6#1;Nq{5U1fO>C^DSu zOhC~{#DAZH(}ihw=TjqV2uVClwQZ`?RJbAhwb%Emz(c$(9sMPd@u2~7nLB?y9Qmir z;4^jCZLm`?bh}2Y_k>}cs7+-*j^)??vnH)TfIsE5WKSg;47gB(QH8Y#TnXWW%;ZzI z2A)Fvr+~VV)Mw1H)#Kl8#^-zys+!F5?G~`HIIzE(YXHWQ_KvG~j85nJV3)88a(i(C zLY9<&y~JD@n+EYrtjtHtjx9`eiS01toaN@?#h6hsHO#A^}D z{O7o>y45z8+88QzkDNV!$R1u{FF>CbI0$wdIWVuF1y3t05(PsA;e<5ueVZGK;{ypF zaNX49ZbbyNZ#7|9ogN5-vEYRaaunR%>w&=vS74&xveM|wY5T{# zkDe%%4&|{p96+J-TWfvAi66N${PZTr*QoI)2qYgo z1UN3WQYR7GPWTU1nQYUlbT8HPDhs;1S72bj)0-sXN}aW(;Oh4peI9yr6ljdnMh|qB z`8rb<93Ts7a+0uTtlPb38mi9T?fiuG@X(c(4se;N1ROyYBXpHf_+=TDg`{L_^HSDm zJ6G6g=sNxPglfIO98>upXp^{@euiNLi@hej+WfTTtnz5;5_idEVBigo84@itJ+zk@ zK0=HsJ~R+I9p4Hf3jM#Crk)0_zx@LsY#qD#??}^Nb|nom>zR6Lh`d(V3S7sF6fntr zARsc${bIsmI=(XH3(`AZGBX=32l1cf$pr#9%>^*kQGv6MGsLc{vjKUcWx7INr}P?; z(nBs8^?whfqDhyV@P4%RDv@1@v6y1j$27@arB;B^eIfD&WjkeVpQ$0KiB^IK=PaC*bTCE}}ux zE1`~|rYr!^fdoKCO>e~$&Y{=}9$Cx0Ht4VUfDX`Jagq}Kla3tD^^8dhG@y1(rBlN2 zo$YLKyX3a}o&g2uoG+_p`G#{Zk|HMk%7QXq;ELv|kGLbI;kg zBe8b};XT}Tbh!zX!`OlFk5RygB>`nZ5<~UHywp(y-S7|YbJSx2PzqkDqsNpcRe5%1 zOiTo!*49%y!lHB>OYTADAp@vwgtOne5w2R$Z+Gx_Ju4If?o%@Rj7?-u1^@ueKL~)m z8GxL8K}9L}-Cw-BdwBMwx9%k@t)gmoCWV+)A!MTC2&f0n>}vJU$JDX&+3avvS@a#q z4xhI=4%+VFb{wCU?41#IGKX90^;C8ifYDi3+ZE7a?nvlo+dTT6{O|OeOCr-o!p4Pc zTo;lXuG+B+0AxP_pripBkMhVDCif~SJW9*KpLOxupP%g|v`&V>%0lXhI8JevitPTS zNOeek9Vt7hgp~{0o8}c9tmB{opwuX(+pCe{wx^I&PVj$SV2s(09_B$Ob}EvCjdDvq z-^`n|`;8E zokvLQrro6hAcaa0a9UbG-X$V#HO1IbcIJPn%hxXL&6t^Y)<3o&!hsqK*!!5WxSyRZ z007v|Ny=nom@g!}Pcj2 zFwY`~00&@9I7U*?y8&Q#b+tSE%s%toHQIp&z>L3^mVvQbPqN(rNR&35V^O528xs9dk0zVztwTb0APtR z4G{J-0QT&EC_VOI0K5G-u`~X4sm#;z9K!PUBvAT)w~#%kM~?x3Jti;cL+R@~JJW6; zlpK|X28UwU2LSeL*f%xuegXj9>*u`zVE3rEUvIk4V)wb(y{WI6^!H6(ITS~a0>G|g z%A)?S_x5$q_9b?9br}F;uM+SE7O*z(*(HzfZt(X4fYoc(&^`JA_Rjv&&j0`^1Av&_ zf$u)^d1v)3y5HB)BLT4Mn6a?&^+vaa0Ve99TiY!FcK!R_CBW?253nBwgLd@;yrJuP zk7qOEo<>4c_c?SA5?np8=ZL&_I(jq!_HmwjQ}LS`8UQf+xg+SUO2WQM&-*6udpGR+ z<#;E7W)4tK;6A~&$ML=k{NK}{J^k3{xgUhFfL+J?Ht6rzi2qE-!RiWrzaIbe7yBUq z-v0Qfzt|4}@b-W$L6fhO;rFT}kW z!_S1)jk{GfR-uX+3xeZEeOO`eAYHfC>~@hVRYN^#~V^WY=o-2kAywfJ|QmFWaPp5+c- z<_NZoP`b?X*xJJm8~whrhdmYmk3aGB=v2!8cca;-jUm;gN%!4NyXVjEbS${{fp-Of zT=vaN@zXt8YS&N|-Ssnh{dfGY1Lt+SALyTt8gbO}L*0gd&(UK6@Y0GGwgtY^Yj?x% zb+(jt54xFhCtd0OoY$vq@9w+1@2}61IA0*u)fHqwV?Q#me?Q^|J}FuN%$iM_0D!Sa z9zl*j_88KqcLV9wH}mF3F|@mzpYHDdF?)3cn>~KU(KTf7sER|~hJVk|V*zmUt@pRp zRaaD2Wl|*Yy?^*jUs~}h2@BcMZefi8Ky7s;$>npzE-?J-8~#Xgg*+KOd|2txt5-cC zTKwZDZHN9DA+9ILkimm`Y}@X6^w^X9<4yOp$vCc*aa5WVknmlSP9;cHRV7KMQ^fNe zA{wuV*ofhzp`o5Q%zN9< zvjhB591|%e9uZMm5xb<9Wh8q(uHzENb;#gB9|GV#9eV;m*#^fmekU#(HwXffNcbd~ z2uL!OBq=-s{O)^R>F*8#A%rNcCb?nLRuUEq08bKSptAHFBX}`BYw_P6AYl}e0e$+A z%1i}m>+B$FU)cn36ie^5LAAkFva~WyX{K#ID)2e!RI2-t#J@YGz<&sU{cwEi z+gFRjjykrTXq|jJ03`5i1D{AFx_`GnDz4DCP^bp6}OHR#hSv36@Ex8GfcUHMO*%S3Sk=Zwr7u z1HLx^Hg4Hc0>C|gd+<#FNC9B3UDU;HS0T7@h0w0!*t>hOoUx{giga_YhK8Me`}c3| zRbSs0BoeQ{X8vLH=uzRJZp(K%dL#h;=U2Dzipq*(LHQ#<{nav-2^oi8R17^Xs0SsU zBt#}4$$dk0!f2CFS_TM6z&Q^PB-iy^E_nCy{&v+e`=FGSmM((Av$M6sIMxt&8j4;u zwX~?^FT9{%T)9dC01ARq2fiPIWs1pUqEL}e=QEj#d}U>2zPhriSX)z*Z>X=!Rc10# zCX+7W3nP?(JW48SWknx|K3bFQ(VT>A$Iv$WWQZalRI9J3S27-+++~A9)3v# ziT~H$wd6Dm15w*)633sWrFZESfOD~6#S%`y1(1-C+DZrz*FY4pX$fhe&@>-=7`N&M z2??nSh}tJjY$eNiei=J@lR%0v5Il0E2(TXTur^?R!)L~Ir81V<^@t>J)-CJoxdyL* zcPa}HPeXgz>qGzc&Ssx;OgbiBVbZlMwbBJ9zt9rrvBFUmZ6$Ld<3+5a47Z^fZYy(C zfzqI+pu$w$ZnqZS1pX}nzT@oleA#6LfZ^))TzC~95B?%dgU&uH~;5AK2I-QcY*^FRCPjEGZOYpiV uJUKq9#mfFIYEOV2Hp7kpTaFz8wj5vKma`RWz3<)t0000 + + +{%- endblock scripts %} + +{%- block styles %} +{{ super() }} + +{%- endblock styles %} + +{% block headtable %} + + + + + + + + + + + + + + + + + + + + +
{{ _('ChipBaseID') }}{{ p.tx_id }}
{{ _('Senden') }}{% if p._block_ext_out_msg %}{{ _('Blockiert') }}{% else %}{{ _('Ein') }}{% endif %}
{{ _('UTE Listen') }}{% if p.UTE_listen %}{{ _('Aktiv') }}{% else %}{{ _('Aus') }}{% endif %}
+{% endblock headtable %} + +{% block buttons %} + + +{% endblock buttons %} \ No newline at end of file diff --git a/enocean/webif/templates/index.html b/enocean/webif/templates/index.html new file mode 100644 index 000000000..bec237ff4 --- /dev/null +++ b/enocean/webif/templates/index.html @@ -0,0 +1,32 @@ +{% extends "base_enocean.html" %} + +{% block bodytab1 %} + + +
+ {{ _('Die folgenden Items sind dieser Instanz des Enocean Plugins zugewiesen') }}: +
+ + + + + + + + {% for item in items %} + {% if p.has_iattr(item.conf, 'enocean_rx_id') %} + + + + + {% endif %} + {% endfor %} +
{{ _('Item') }}{{ _('RxEEP') }}
{{ item._path }}{{ item.conf['enocean_rx_eep']}}
+{% endblock bodytab1 %} From 1dde1e943a714ab65ac04957fce23053ff0aaacf Mon Sep 17 00:00:00 2001 From: aschwith Date: Sat, 21 Jul 2018 22:02:38 +0200 Subject: [PATCH 040/705] enocean webif: added teach-in function --- enocean/__init__.py | 11 ++++-- enocean/locale.yaml | 16 ++++++-- enocean/webif/templates/base_enocean.html | 1 + enocean/webif/templates/index.html | 48 +++++++++++++++++++++++ 4 files changed, 70 insertions(+), 6 deletions(-) diff --git a/enocean/__init__.py b/enocean/__init__.py index 751e95348..666c03f62 100644 --- a/enocean/__init__.py +++ b/enocean/__init__.py @@ -802,7 +802,7 @@ def __init__(self, webif_dir, plugin): @cherrypy.expose - def index(self, reload=None, action=None, item_id=None, item_path=None, day=None, month=None, year=None, + def index(self, reload=None, action=None, item_id=None, item_path=None, device_id=None, device_offset=None, time_orig=None, changed_orig=None): """ Build index.html for cherrypy @@ -814,10 +814,15 @@ def index(self, reload=None, action=None, item_id=None, item_path=None, day=None if action is not None: if action == "toggle_tx_blocking": self.plugin.toggle_block_external_out_messages() - + elif action == "send_learn" and device_id is not None and device_offset is not None: + self.logger.warning("Learn telegram triggered via webinterface (ID:{0} Offset:{1})".format(device_id,device_offset)) + self.plugin.send_learn_protocol(int(device_offset), int(device_id)) + else: + self.logger.error("Unknown comman received via webinterface") + tmpl = self.tplenv.get_template('index.html') return tmpl.render(p=self.plugin, items=sorted(self.items.return_items(), key=lambda k: str.lower(k['_path']), reverse=False), - tabcount=1, action=action, item_id=item_id) + tabcount=1, item_id=item_id) diff --git a/enocean/locale.yaml b/enocean/locale.yaml index 80d8410b5..1bb51847c 100644 --- a/enocean/locale.yaml +++ b/enocean/locale.yaml @@ -1,13 +1,13 @@ plugin_translations: # Translations for the plugin specially for the web interface 'Aktionen': {'de': 'Aktionen', 'en': 'Actions'} - 'Blockiert': {'de': 'Blockiert', 'en': 'Blocked'} + 'Blockiert': {'de': 'Blockiert', 'en': 'Blocked', 'fr': 'Blocke'} 'Ja': {'de': 'Ja', 'en': 'Yes'} 'Nein': {'de': 'Nein', 'en': 'No'} 'Ein': {'de': 'Ein', en: 'On'} 'Zeit': {'de': 'Zeit', en: 'Time'} 'Item ID': {'de': 'Item ID', en: 'Item ID'} - 'Dauer': {'de': 'Dauer', en: 'Duration'} + 'Gerätetyp': {'de': 'Gerätetyp', en: 'Device Type'} 'Übersicht': {'de': 'Übersicht', en: 'Overview'} 'Senden': de: 'Senden' @@ -23,4 +23,14 @@ plugin_translations: en: 'Tx On/Off' 'Wollen Sie das Senden wirklich umschalten?': de: 'Wollen Sie das Senden wirklich umschalten?' - en: 'Do you really want to change the sending state?' \ No newline at end of file + en: 'Do you really want to change the sending state?' + fr: 'Changer le stade de l'emitteur?' + + 'Neu hinzufügen': + de: 'Neu hinzufügen' + en: 'Add devie' + fr: 'Ajouter' + 'Enocean Geräte anlernen': + de: 'Enocean Geräte anlernen' + en: 'Teach-in new Enocean devices + fr: 'Ajouter nouveux acteur' \ No newline at end of file diff --git a/enocean/webif/templates/base_enocean.html b/enocean/webif/templates/base_enocean.html index 15dbd1f79..ed027ed10 100644 --- a/enocean/webif/templates/base_enocean.html +++ b/enocean/webif/templates/base_enocean.html @@ -39,4 +39,5 @@ {% block buttons %} + {% endblock buttons %} \ No newline at end of file diff --git a/enocean/webif/templates/index.html b/enocean/webif/templates/index.html index bec237ff4..c3aceaf7b 100644 --- a/enocean/webif/templates/index.html +++ b/enocean/webif/templates/index.html @@ -1,6 +1,20 @@ {% extends "base_enocean.html" %} + +{% set tabcount = 2 %} + + + + +{% set start_tab = 2 %} + +{% set tab1title = " " ~ _('Übersicht') ~ " " %} {% block bodytab1 %} +
@@ -30,3 +56,25 @@ {% endfor %} {% endblock bodytab1 %} + +{% set tab2title = " " ~ _('Neu hinzufügen') ~ " " %} + +{% block bodytab2 %} + +
+ {{ _('Enocean Geräte anlernen') }}: +
+
{{ _('Gerätetyp') }}:
+ + + {{ _('Offset') }} + + +{% endblock bodytab2 %} + From 70b1cb28e02652e45ab0a9e570f1d3c307a503c6 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 22 Jul 2018 16:17:02 +0200 Subject: [PATCH 041/705] Backend: added () to autocomplete of item paths --- backend/webif/static/js/logics_view_functions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/webif/static/js/logics_view_functions.js b/backend/webif/static/js/logics_view_functions.js index 2cf5472b4..ec2bbb394 100755 --- a/backend/webif/static/js/logics_view_functions.js +++ b/backend/webif/static/js/logics_view_functions.js @@ -16,7 +16,7 @@ var dict = []; function getItemDictionary() { $.getJSON('items.json?mode=list', function(result) { for (i = 0; i < result.length; i++) { - dict.push("sh."+result[i]); + dict.push("sh."+result[i]+"()"); } }); } From c216e3aa65448a979dd659dc011179506c4c4def Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 22 Jul 2018 16:28:27 +0200 Subject: [PATCH 042/705] Backend: added method to return plugin names from config as json structure (needed for support of pluginnames in autocompletion --- backend/BackendPlugins.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/backend/BackendPlugins.py b/backend/BackendPlugins.py index a1c196642..10ce3fea4 100755 --- a/backend/BackendPlugins.py +++ b/backend/BackendPlugins.py @@ -118,4 +118,16 @@ def plugins_html(self, configname=None, shortname=None, instancename=None, enabl return self.render_template('plugins.html', plugins=plugins_sorted, lang=get_translation_lang(), mod_http=self._bs.mod_http) + @cherrypy.expose + def plugins_json(self): + """ + returns a list of plugin names (from config) as json structure + """ + plugin_list = [] + for x in self.plugins.return_plugins(): + if isinstance(x, SmartPlugin): + plugin_list.append(x.get_configname()) + else: + plugin_list.append(x._configname) + return json.dumps(plugin_list) From bf9cbbf4df7b7bb26b79ce63871066d1334465e2 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 22 Jul 2018 16:30:41 +0200 Subject: [PATCH 043/705] Backend: added pluginnames from config to autocomplete dictionary --- backend/webif/static/js/logics_view_functions.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/backend/webif/static/js/logics_view_functions.js b/backend/webif/static/js/logics_view_functions.js index ec2bbb394..11030abf8 100755 --- a/backend/webif/static/js/logics_view_functions.js +++ b/backend/webif/static/js/logics_view_functions.js @@ -20,7 +20,15 @@ function getItemDictionary() { } }); } +function getPluginDictionary() { + $.getJSON('plugins.json', function(result) { + for (i = 0; i < result.length; i++) { + dict.push("sh."+result[i]); + } + }); +} getItemDictionary(); +getPluginDictionary(); CodeMirror.registerHelper('hint', 'itemsHint', function(editor) { var cur = editor.getCursor(), From 2546e0e90416bee65b8059af0638ac72e1b13ab4 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 22 Jul 2018 18:43:55 +0200 Subject: [PATCH 044/705] Backend: filtered unncessary plugin methods for autocomplete --- backend/BackendPlugins.py | 56 ++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/backend/BackendPlugins.py b/backend/BackendPlugins.py index 10ce3fea4..ffa64a97f 100755 --- a/backend/BackendPlugins.py +++ b/backend/BackendPlugins.py @@ -27,21 +27,20 @@ import lib.config from lib.plugin import Plugins from lib.model.smartplugin import SmartPlugin +import inspect from .utils import * -#import lib.item_conversion -class BackendPlugins: +# import lib.item_conversion +class BackendPlugins: plugins = None def __init__(self): self.plugins = Plugins.get_instance() self.logger.info("BackendPlugins __init__ self.plugins = {}".format(str(self.plugins))) - - # ----------------------------------------------------------------------------------- # PLUGINS @@ -57,12 +56,16 @@ def plugins_html(self, configname=None, shortname=None, instancename=None, enabl myplg = self.plugins.return_plugin(configname) myplg2 = self.plugins.get_pluginthread(configname) myplg.run() - self.logger.warning("disable: configname = {}, myplg = {}, myplg.alive = {}, myplg2 = {}".format(configname, myplg, myplg.alive, myplg2)) + self.logger.warning( + "disable: configname = {}, myplg = {}, myplg.alive = {}, myplg2 = {}".format(configname, myplg, + myplg.alive, myplg2)) elif disable is not None: myplg = self.plugins.return_plugin(configname) myplg2 = self.plugins.get_pluginthread(configname) myplg.stop() - self.logger.warning("disable: configname = {}, myplg = {}, myplg.alive = {}, myplg2 = {}".format(configname, myplg, myplg.alive, myplg2)) + self.logger.warning( + "disable: configname = {}, myplg = {}, myplg.alive = {}, myplg2 = {}".format(configname, myplg, + myplg.alive, myplg2)) elif unload is not None: result = self.plugins.unload_plugin(configname) @@ -102,7 +105,7 @@ def plugins_html(self, configname=None, shortname=None, instancename=None, enabl plugin['classpath'] = x._classpath plugin['classname'] = x._classname plugin['stopped'] = False - + try: plugin['stopped'] = not x.alive plugin['stoppable'] = True @@ -111,23 +114,52 @@ def plugins_html(self, configname=None, shortname=None, instancename=None, enabl plugin['stoppable'] = False if plugin['shortname'] == 'backend': plugin['stoppable'] = False - - + plugin_list.append(plugin) plugins_sorted = sorted(plugin_list, key=lambda k: k['classpath']) - return self.render_template('plugins.html', plugins=plugins_sorted, lang=get_translation_lang(), mod_http=self._bs.mod_http) + return self.render_template('plugins.html', plugins=plugins_sorted, lang=get_translation_lang(), + mod_http=self._bs.mod_http) @cherrypy.expose def plugins_json(self): """ returns a list of plugin names (from config) as json structure """ + not_allowed_functions = ['__init__', 'parse_item', 'parse_logic', 'update_item', 'init_webinterface', + 'init_webinterfaces'] plugin_list = [] for x in self.plugins.return_plugins(): if isinstance(x, SmartPlugin): - plugin_list.append(x.get_configname()) + plugin_config_name = x.get_configname() else: - plugin_list.append(x._configname) + plugin_config_name = x._configname + + plugin_list.append(plugin_config_name) + + for func_name in inspect.getmembers(x, predicate=inspect.ismethod): + if self.get_class_that_defined_method(func_name[1]) is not None: + class_name = self.get_class_that_defined_method(func_name[1]).__name__ + if 'SmartPlugin' not in class_name and func_name[0] not in not_allowed_functions and not func_name[ + 0].startswith('_'): + plugin_list.append(plugin_config_name + "." + func_name[0]) return json.dumps(plugin_list) + + def get_class_that_defined_method(self, meth): + if inspect.ismethod(meth): + for cls in inspect.getmro(meth.__self__.__class__): + if cls.__dict__.get(meth.__name__) is meth: + return cls + meth = meth.__func__ # fallback to __qualname__ parsing + if inspect.isfunction(meth): + + # Check to make sure the method has a "qualname" + if not getattr(meth, '__qualname__', None): + return None + + cls = getattr(inspect.getmodule(meth), + meth.__qualname__.split('.', 1)[0].rsplit('.', 1)[0]) + if isinstance(cls, type): + return cls + return None # not required since None would have been implicitly returned anyway From 9d2c19d98f9bef5ac9e726a4cce198cffc416767 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 22 Jul 2018 18:47:08 +0200 Subject: [PATCH 045/705] Backend: removed pluginname without methods from autocomplete list --- backend/BackendPlugins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/BackendPlugins.py b/backend/BackendPlugins.py index ffa64a97f..b643c992d 100755 --- a/backend/BackendPlugins.py +++ b/backend/BackendPlugins.py @@ -135,7 +135,7 @@ def plugins_json(self): else: plugin_config_name = x._configname - plugin_list.append(plugin_config_name) + #plugin_list.append(plugin_config_name) for func_name in inspect.getmembers(x, predicate=inspect.ismethod): if self.get_class_that_defined_method(func_name[1]) is not None: From d604590840ef314ef096f1a7e2ba4aa1f361e2ba Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 22 Jul 2018 19:13:51 +0200 Subject: [PATCH 046/705] Backend: changed hint name --- backend/webif/static/js/logics_view_functions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/webif/static/js/logics_view_functions.js b/backend/webif/static/js/logics_view_functions.js index 11030abf8..d18e4bd0f 100755 --- a/backend/webif/static/js/logics_view_functions.js +++ b/backend/webif/static/js/logics_view_functions.js @@ -30,7 +30,7 @@ function getPluginDictionary() { getItemDictionary(); getPluginDictionary(); -CodeMirror.registerHelper('hint', 'itemsHint', function(editor) { +CodeMirror.registerHelper('hint', 'autocompleteHint', function(editor) { var cur = editor.getCursor(), curLine = editor.getLine(cur.line); var start = cur.ch, @@ -56,7 +56,7 @@ CodeMirror.registerHelper('hint', 'itemsHint', function(editor) { }); CodeMirror.commands.autocomplete_item = function(cm) { - CodeMirror.showHint(cm, CodeMirror.hint.itemsHint); + CodeMirror.showHint(cm, CodeMirror.hint.autocompleteHint); }; function switchRulers() { From 660512f84bd99f9b7cc0079587a0a4c9844ec85f Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 22 Jul 2018 21:00:47 +0200 Subject: [PATCH 047/705] Backend: - added displayed information of autocomplete string is item or plugin - added custom sort function --- .../webif/static/js/logics_view_functions.js | 25 +++++++++++++------ backend/webif/templates/logics_view.html | 2 +- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/backend/webif/static/js/logics_view_functions.js b/backend/webif/static/js/logics_view_functions.js index d18e4bd0f..22b0ba1fb 100755 --- a/backend/webif/static/js/logics_view_functions.js +++ b/backend/webif/static/js/logics_view_functions.js @@ -16,14 +16,14 @@ var dict = []; function getItemDictionary() { $.getJSON('items.json?mode=list', function(result) { for (i = 0; i < result.length; i++) { - dict.push("sh."+result[i]+"()"); + dict.push({ text: "sh."+result[i]+"()", displayText: "sh."+result[i]+"() | Item" }); } }); } function getPluginDictionary() { $.getJSON('plugins.json', function(result) { for (i = 0; i < result.length; i++) { - dict.push("sh."+result[i]); + dict.push({ text: "sh."+result[i], displayText: "sh."+result[i]+" | Plugin"}); } }); } @@ -45,17 +45,26 @@ CodeMirror.registerHelper('hint', 'autocompleteHint', function(editor) { } var regex = new RegExp('^' + curWord, 'i'); if (curWord.length >= 3) { - return { - list: (!curWord ? [] : dict.filter(function(item) { - return item.match(regex); - })).sort(), + var oCompletions = { + list: (!curWord ? [] : dict.filter(function (item) { + return item['text'].match(regex); + })).sort(function(a, b){ + var nameA=a.text.toLowerCase(), nameB=b.text.toLowerCase() + if (nameA < nameB) //sort string ascending + return -1 + if (nameA > nameB) + return 1 + return 0 //default return value (no sorting) + }), from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end) - } + }; + + return oCompletions; } }); -CodeMirror.commands.autocomplete_item = function(cm) { +CodeMirror.commands.autocomplete_shng = function(cm) { CodeMirror.showHint(cm, CodeMirror.hint.autocompleteHint); }; diff --git a/backend/webif/templates/logics_view.html b/backend/webif/templates/logics_view.html index c05622ac1..5f12332f9 100755 --- a/backend/webif/templates/logics_view.html +++ b/backend/webif/templates/logics_view.html @@ -205,7 +205,7 @@ event.keyCode != 39 && event.keyCode != 40 && event.keyCode != 46)) { - CodeMirror.commands.autocomplete_item(cm, null, {completeSingle: false}); + CodeMirror.commands.autocomplete_shng(cm, null, {completeSingle: false}); }; }); var answer = false; From 902d1ca9498aed1e4d6491cc240f41a485750949 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 22 Jul 2018 21:09:14 +0200 Subject: [PATCH 048/705] Backend: added () to plugin method autocomplete --- backend/webif/static/js/logics_view_functions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/webif/static/js/logics_view_functions.js b/backend/webif/static/js/logics_view_functions.js index 22b0ba1fb..3e9acddd5 100755 --- a/backend/webif/static/js/logics_view_functions.js +++ b/backend/webif/static/js/logics_view_functions.js @@ -23,7 +23,7 @@ function getItemDictionary() { function getPluginDictionary() { $.getJSON('plugins.json', function(result) { for (i = 0; i < result.length; i++) { - dict.push({ text: "sh."+result[i], displayText: "sh."+result[i]+" | Plugin"}); + dict.push({ text: "sh."+result[i]+"()", displayText: "sh."+result[i]+"() | Plugin"}); } }); } From 2b726bcd8732b678d47ce7ce0ff465c0c99de6c5 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 23 Jul 2018 16:07:39 +0200 Subject: [PATCH 049/705] Backend: corrected button class for log view --- backend/webif/templates/log_view.html | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/backend/webif/templates/log_view.html b/backend/webif/templates/log_view.html index 7ab489d62..c8b1e555d 100755 --- a/backend/webif/templates/log_view.html +++ b/backend/webif/templates/log_view.html @@ -9,6 +9,8 @@ {{ _('Logging', 'menu') }} - SmartHomeNG {% endblock title %} + + {% block content %} - +   - - + +

@@ -41,22 +43,22 @@

SmarthomeNG {{ _('Logfile') }}: {{ logfile }}

- + - + ({{ current_page }} / {{ pages }}) - + - + - +
From 31e309ddb5c6c66d183c2d62261579007b8ab8fe Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 23 Jul 2018 16:41:18 +0200 Subject: [PATCH 050/705] Backend: added autocomplete for watch items --- .../webif/static/js/logics_view_functions.js | 44 ++++++++++++++++++- backend/webif/templates/logics_view.html | 34 ++++++++++++-- 2 files changed, 73 insertions(+), 5 deletions(-) diff --git a/backend/webif/static/js/logics_view_functions.js b/backend/webif/static/js/logics_view_functions.js index 3e9acddd5..9dba55f2b 100755 --- a/backend/webif/static/js/logics_view_functions.js +++ b/backend/webif/static/js/logics_view_functions.js @@ -13,10 +13,12 @@ window.addEventListener("resize", function(){resizeCodeMirror(logicsCodeMirror, resizeCodeMirror(logicsCodeMirror, 15); var dict = []; +var watch_items_dict = []; function getItemDictionary() { $.getJSON('items.json?mode=list', function(result) { for (i = 0; i < result.length; i++) { dict.push({ text: "sh."+result[i]+"()", displayText: "sh."+result[i]+"() | Item" }); + watch_items_dict.push({ text: result[i], displayText: result[i] }); } }); } @@ -29,6 +31,7 @@ function getPluginDictionary() { } getItemDictionary(); getPluginDictionary(); +console.log(watch_items_dict); CodeMirror.registerHelper('hint', 'autocompleteHint', function(editor) { var cur = editor.getCursor(), @@ -44,9 +47,44 @@ CodeMirror.registerHelper('hint', 'autocompleteHint', function(editor) { curWord = curWord.trim(); } var regex = new RegExp('^' + curWord, 'i'); + if (curWord.length >= 3) { var oCompletions = { - list: (!curWord ? [] : dict.filter(function (item) { + list: (!curWord ? [] : watch_items_dict.filter(function (item) { + return item['text'].match(regex); + })).sort(function(a, b){ + var nameA=a.text.toLowerCase(), nameB=b.text.toLowerCase() + if (nameA < nameB) //sort string ascending + return -1 + if (nameA > nameB) + return 1 + return 0 //default return value (no sorting) + }), + from: CodeMirror.Pos(cur.line, start), + to: CodeMirror.Pos(cur.line, end) + }; + + return oCompletions; + } +}); + +CodeMirror.registerHelper('hint', 'autocompleteWatchItemsHint', function(editor) { + var cur = editor.getCursor(), + curLine = editor.getLine(cur.line); + var start = cur.ch, + end = start; + + var charexp = /[\w\.$]+/; + while (end < curLine.length && charexp.test(curLine.charAt(end))) ++end; + while (start && charexp.test(curLine.charAt(start - 1))) --start; + var curWord = start != end && curLine.slice(start, end); + if (curWord.length > 1) { + curWord = curWord.trim(); + } + var regex = new RegExp('^' + curWord, 'i'); + if (curWord.length >= 3) { + var oCompletions = { + list: (!curWord ? [] : watch_items_dict.filter(function (item) { return item['text'].match(regex); })).sort(function(a, b){ var nameA=a.text.toLowerCase(), nameB=b.text.toLowerCase() @@ -68,6 +106,10 @@ CodeMirror.commands.autocomplete_shng = function(cm) { CodeMirror.showHint(cm, CodeMirror.hint.autocompleteHint); }; +CodeMirror.commands.autocomplete_shng_watch_items = function(cm) { + CodeMirror.showHint(cm, CodeMirror.hint.autocompleteWatchItemsHint); +}; + function switchRulers() { if (logicsCodeMirror.getOption('rulers').length == 0) { diff --git a/backend/webif/templates/logics_view.html b/backend/webif/templates/logics_view.html index 5f12332f9..bba355913 100755 --- a/backend/webif/templates/logics_view.html +++ b/backend/webif/templates/logics_view.html @@ -101,20 +101,20 @@ {{ _('Watch_Item(s)') }} - + {{ 'visu_acl' }} - + -
+
{% if logic_lines %} {% if updates %}{% endif %} @@ -125,7 +125,11 @@ rulers.push({color: '#eee', column: i * 4, lineStyle: "dashed"}); } -var logicsCodeMirror = CodeMirror.fromTextArea(document.getElementById("logics_code"), { +var watchitemsCodeMirror = CodeMirror.fromTextArea($("#watch")[0], { + {% if not yaml_updates or not updates %}readOnly: true,{% endif %} +}); + +var logicsCodeMirror = CodeMirror.fromTextArea($("#logics_code")[0], { lineNumbers: true, extraKeys: { @@ -208,6 +212,28 @@ CodeMirror.commands.autocomplete_shng(cm, null, {completeSingle: false}); }; }); +watchitemsCodeMirror.on("keyup", function (cm, event) { + if (checkChangedContent()) { + markChangedContent(); + } else { + markIdenticalContent(); + } + + if (!cm.state.completionActive && /*Enables keyboard navigation in autocomplete list*/ + (event.keyCode != 8 && + event.keyCode != 9 && + event.keyCode != 13 && + event.keyCode != 27 && + event.keyCode != 37 && + event.keyCode != 38 && + event.keyCode != 39 && + event.keyCode != 40 && + event.keyCode != 46)) { + CodeMirror.commands.autocomplete_shng_watch_items(cm, null, {completeSingle: false}); + }; +}); + + var answer = false; var unloadCheck = true; $('a').click(function(e) { From ad3311c20e3810ba9370cf31e9b218bb406a8ea7 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 23 Jul 2018 16:57:21 +0200 Subject: [PATCH 051/705] Backend: registration of hint helper put to function --- .../webif/static/js/logics_view_functions.js | 105 +++++++----------- 1 file changed, 38 insertions(+), 67 deletions(-) diff --git a/backend/webif/static/js/logics_view_functions.js b/backend/webif/static/js/logics_view_functions.js index 9dba55f2b..58e0663be 100755 --- a/backend/webif/static/js/logics_view_functions.js +++ b/backend/webif/static/js/logics_view_functions.js @@ -31,76 +31,47 @@ function getPluginDictionary() { } getItemDictionary(); getPluginDictionary(); -console.log(watch_items_dict); -CodeMirror.registerHelper('hint', 'autocompleteHint', function(editor) { - var cur = editor.getCursor(), - curLine = editor.getLine(cur.line); - var start = cur.ch, - end = start; - - var charexp = /[\w\.$]+/; - while (end < curLine.length && charexp.test(curLine.charAt(end))) ++end; - while (start && charexp.test(curLine.charAt(start - 1))) --start; - var curWord = start != end && curLine.slice(start, end); - if (curWord.length > 1) { - curWord = curWord.trim(); - } - var regex = new RegExp('^' + curWord, 'i'); - - if (curWord.length >= 3) { - var oCompletions = { - list: (!curWord ? [] : watch_items_dict.filter(function (item) { - return item['text'].match(regex); - })).sort(function(a, b){ - var nameA=a.text.toLowerCase(), nameB=b.text.toLowerCase() - if (nameA < nameB) //sort string ascending - return -1 - if (nameA > nameB) - return 1 - return 0 //default return value (no sorting) - }), - from: CodeMirror.Pos(cur.line, start), - to: CodeMirror.Pos(cur.line, end) - }; - - return oCompletions; - } -}); - -CodeMirror.registerHelper('hint', 'autocompleteWatchItemsHint', function(editor) { - var cur = editor.getCursor(), - curLine = editor.getLine(cur.line); - var start = cur.ch, - end = start; +function registerAutocompleteHelper(name, curDict) { + CodeMirror.registerHelper('hint', name, function(editor) { + var cur = editor.getCursor(), + curLine = editor.getLine(cur.line); + var start = cur.ch, + end = start; + + var charexp = /[\w\.$]+/; + while (end < curLine.length && charexp.test(curLine.charAt(end))) ++end; + while (start && charexp.test(curLine.charAt(start - 1))) --start; + var curWord = start != end && curLine.slice(start, end); + if (curWord.length > 1) { + curWord = curWord.trim(); + } + var regex = new RegExp('^' + curWord, 'i'); + + if (curWord.length >= 3) { + var oCompletions = { + list: (!curWord ? [] : curDict.filter(function (item) { + return item['text'].match(regex); + })).sort(function(a, b){ + var nameA=a.text.toLowerCase(), nameB=b.text.toLowerCase() + if (nameA < nameB) //sort string ascending + return -1 + if (nameA > nameB) + return 1 + return 0 //default return value (no sorting) + }), + from: CodeMirror.Pos(cur.line, start), + to: CodeMirror.Pos(cur.line, end) + }; + + return oCompletions; + } + }); +} - var charexp = /[\w\.$]+/; - while (end < curLine.length && charexp.test(curLine.charAt(end))) ++end; - while (start && charexp.test(curLine.charAt(start - 1))) --start; - var curWord = start != end && curLine.slice(start, end); - if (curWord.length > 1) { - curWord = curWord.trim(); - } - var regex = new RegExp('^' + curWord, 'i'); - if (curWord.length >= 3) { - var oCompletions = { - list: (!curWord ? [] : watch_items_dict.filter(function (item) { - return item['text'].match(regex); - })).sort(function(a, b){ - var nameA=a.text.toLowerCase(), nameB=b.text.toLowerCase() - if (nameA < nameB) //sort string ascending - return -1 - if (nameA > nameB) - return 1 - return 0 //default return value (no sorting) - }), - from: CodeMirror.Pos(cur.line, start), - to: CodeMirror.Pos(cur.line, end) - }; +registerAutocompleteHelper('autocompleteHint', dict); +registerAutocompleteHelper('autocompleteWatchItemsHint', watch_items_dict); - return oCompletions; - } -}); CodeMirror.commands.autocomplete_shng = function(cm) { CodeMirror.showHint(cm, CodeMirror.hint.autocompleteHint); From 12540688b4217e0b41a429259f786117337f8e56 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 23 Jul 2018 17:00:01 +0200 Subject: [PATCH 052/705] Backend: watch items codemirror preventing new lines --- backend/webif/templates/logics_view.html | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/backend/webif/templates/logics_view.html b/backend/webif/templates/logics_view.html index bba355913..bb1c1e11b 100755 --- a/backend/webif/templates/logics_view.html +++ b/backend/webif/templates/logics_view.html @@ -129,6 +129,25 @@ {% if not yaml_updates or not updates %}readOnly: true,{% endif %} }); +watchitemsCodeMirror.on("beforeChange", function(cm, changeObj) { + var typedNewLine = changeObj.origin == '+input' && typeof changeObj.text == "object" && changeObj.text.join("") == ""; + if (typedNewLine) { + return changeObj.cancel(); + } + + var pastedNewLine = changeObj.origin == 'paste' && typeof changeObj.text == "object" && changeObj.text.length > 1; + if (pastedNewLine) { + var newText = changeObj.text.join(" "); + + // trim + //newText = $.trim(newText); + + return changeObj.update(null, null, [newText]); + } + + return null; +}); + var logicsCodeMirror = CodeMirror.fromTextArea($("#logics_code")[0], { lineNumbers: true, From 1496f276f30b1407dc81a116c983dbec1c667e05 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 23 Jul 2018 17:01:07 +0200 Subject: [PATCH 053/705] Backend: comments removed --- backend/webif/templates/logics_view.html | 4 ---- 1 file changed, 4 deletions(-) diff --git a/backend/webif/templates/logics_view.html b/backend/webif/templates/logics_view.html index bb1c1e11b..a46997db5 100755 --- a/backend/webif/templates/logics_view.html +++ b/backend/webif/templates/logics_view.html @@ -138,10 +138,6 @@ var pastedNewLine = changeObj.origin == 'paste' && typeof changeObj.text == "object" && changeObj.text.length > 1; if (pastedNewLine) { var newText = changeObj.text.join(" "); - - // trim - //newText = $.trim(newText); - return changeObj.update(null, null, [newText]); } From 243e122e1279fcbc8a1cb52dc2e13adb56cb68c4 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 23 Jul 2018 17:05:47 +0200 Subject: [PATCH 054/705] Backend: added possibility to add watch items with "sh." prefix (will be cutted off when the item is inserted) --- backend/webif/static/js/logics_view_functions.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/webif/static/js/logics_view_functions.js b/backend/webif/static/js/logics_view_functions.js index 58e0663be..92d1a5610 100755 --- a/backend/webif/static/js/logics_view_functions.js +++ b/backend/webif/static/js/logics_view_functions.js @@ -19,6 +19,7 @@ function getItemDictionary() { for (i = 0; i < result.length; i++) { dict.push({ text: "sh."+result[i]+"()", displayText: "sh."+result[i]+"() | Item" }); watch_items_dict.push({ text: result[i], displayText: result[i] }); + watch_items_dict.push({ text: result[i], displayText: "sh."+result[i] }); } }); } @@ -51,7 +52,7 @@ function registerAutocompleteHelper(name, curDict) { if (curWord.length >= 3) { var oCompletions = { list: (!curWord ? [] : curDict.filter(function (item) { - return item['text'].match(regex); + return item['displayText'].match(regex); })).sort(function(a, b){ var nameA=a.text.toLowerCase(), nameB=b.text.toLowerCase() if (nameA < nameB) //sort string ascending From fcc2d516064f5a0ebeac2f9f3cf6deae8cf182b7 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 23 Jul 2018 18:15:59 +0200 Subject: [PATCH 055/705] Backend: added standard parameters to plugin autocomplete --- backend/BackendPlugins.py | 2 +- backend/webif/static/js/logics_view_functions.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/BackendPlugins.py b/backend/BackendPlugins.py index b643c992d..b63a5c45d 100755 --- a/backend/BackendPlugins.py +++ b/backend/BackendPlugins.py @@ -142,7 +142,7 @@ def plugins_json(self): class_name = self.get_class_that_defined_method(func_name[1]).__name__ if 'SmartPlugin' not in class_name and func_name[0] not in not_allowed_functions and not func_name[ 0].startswith('_'): - plugin_list.append(plugin_config_name + "." + func_name[0]) + plugin_list.append(plugin_config_name + "." + func_name[0]+str(inspect.signature(func_name[1]))) return json.dumps(plugin_list) diff --git a/backend/webif/static/js/logics_view_functions.js b/backend/webif/static/js/logics_view_functions.js index 92d1a5610..3627efbb6 100755 --- a/backend/webif/static/js/logics_view_functions.js +++ b/backend/webif/static/js/logics_view_functions.js @@ -26,7 +26,7 @@ function getItemDictionary() { function getPluginDictionary() { $.getJSON('plugins.json', function(result) { for (i = 0; i < result.length; i++) { - dict.push({ text: "sh."+result[i]+"()", displayText: "sh."+result[i]+"() | Plugin"}); + dict.push({ text: "sh."+result[i], displayText: "sh."+result[i]+" | Plugin"}); } }); } From 430b88ab23246fc63bb33bd236874b1eb98959fb Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 23 Jul 2018 18:42:26 +0200 Subject: [PATCH 056/705] Backend: grey color for readonly codemirror --- backend/webif/templates/logics_view.html | 94 ++++++++++++++---------- 1 file changed, 55 insertions(+), 39 deletions(-) diff --git a/backend/webif/templates/logics_view.html b/backend/webif/templates/logics_view.html index a46997db5..ef158cab8 100755 --- a/backend/webif/templates/logics_view.html +++ b/backend/webif/templates/logics_view.html @@ -101,7 +101,11 @@ {{ _('Watch_Item(s)') }} + {% if yaml_updates and updates %} + {% else %} + + {% endif %} @@ -119,12 +123,22 @@ {% if updates %}{% endif %} {% else %}{{ _('no data available') }}{% endif %} + {% if not yaml_updates or not updates %} + + {% endif %} - - - - - - - - - - - - - - - - - - - - - - - - - - - - {%- endblock scripts %} - {%- endblock head %} - - - - {% block body -%} -
- {% block navbar %} - {%- endblock navbar %} -
- -
- {% block content -%} - {%- endblock content %} - - {%- endblock body %} -
- -{%- endblock html %} - -{% endblock doc -%} From ce28831a98e9543e053cee42948f49276e8649e3 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Tue, 24 Jul 2018 13:27:29 +0200 Subject: [PATCH 060/705] Database: added info about number of data sets per day --- database/locale.yaml | 1 + database/webif/templates/item_details.html | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/database/locale.yaml b/database/locale.yaml index 5c423980d..ae22b9c5d 100644 --- a/database/locale.yaml +++ b/database/locale.yaml @@ -11,6 +11,7 @@ plugin_translations: 'Geändert': {'de': 'Geändert', en: 'Changed'} 'Übersicht': {'de': 'Übersicht', en: 'Overview'} 'am': {'de': 'am', en: 'on the'} + 'Datensätze': {'de': 'Datensätze', 'en': 'Data Sets'] 'Item-ID in der Datenbank': de: 'Item-ID in der Datenbank' en: 'Item ID within the database' diff --git a/database/webif/templates/item_details.html b/database/webif/templates/item_details.html index 7d223cdf7..451cdef8f 100644 --- a/database/webif/templates/item_details.html +++ b/database/webif/templates/item_details.html @@ -33,7 +33,7 @@
{% endif %}
- {{ _('Die folgenden Einträge entstammen der log Tabelle mit historischen Daten für das Item') }} {{ item_path }} {{ _('am') }} {% if day and month and year %}{% if language == 'en' %}{{ month }}/{{ day }}/{{ year }}{% else %}{{ day }}.{{ month }}.{{ year }}{% endif %}{% else %}{% if language == 'en' %}{{ now.strftime('%-m/%-d/%Y') }}{% else %}{{ now.strftime('%-d.%-m.%Y') }}{% endif %}{% endif %} {{_('(Datenbank-ID') }}: {{ item_id }}): + {{ _('Die folgenden Einträge entstammen der log Tabelle mit historischen Daten für das Item') }} {{ item_path }} {{ _('am') }} {% if day and month and year %}{% if language == 'en' %}{{ month }}/{{ day }}/{{ year }}{% else %}{{ day }}.{{ month }}.{{ year }}{% endif %}{% else %}{% if language == 'en' %}{{ now.strftime('%-m/%-d/%Y') }}{% else %}{{ now.strftime('%-d.%-m.%Y') }}{% endif %}{% endif %} {{_('(Datenbank-ID') }}: {{ item_id }}, {{ log_array | length }} {{_('Datensätze')}}):
From af7aeac9b6268997f20604f983bed94a43e6180f Mon Sep 17 00:00:00 2001 From: psilo909 Date: Tue, 24 Jul 2018 18:00:15 +0200 Subject: [PATCH 061/705] Database: fix for locale --- database/locale.yaml | 76 ++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/database/locale.yaml b/database/locale.yaml index ae22b9c5d..6720d50a2 100644 --- a/database/locale.yaml +++ b/database/locale.yaml @@ -4,56 +4,56 @@ plugin_translations: 'Verbunden': {'de': 'Verbunden', 'en': 'Connected'} 'Ja': {'de': 'Ja', 'en': 'Yes'} 'Nein': {'de': 'Nein', 'en': 'No'} - 'Datenbank-Dump': {'de': 'Datenbank-Dump', en: 'Database Dump'} - 'Zeit': {'de': 'Zeit', en: 'Time'} - 'Item ID': {'de': 'Item ID', en: 'Item ID'} - 'Dauer': {'de': 'Dauer', en: 'Duration'} - 'Geändert': {'de': 'Geändert', en: 'Changed'} - 'Übersicht': {'de': 'Übersicht', en: 'Overview'} - 'am': {'de': 'am', en: 'on the'} - 'Datensätze': {'de': 'Datensätze', 'en': 'Data Sets'] + 'Datenbank-Dump': {'de': 'Datenbank-Dump', 'en': 'Database Dump'} + 'Zeit': {'de': 'Zeit', 'en': 'Time'} + 'Item ID': {'de': 'Item ID', 'en': 'Item ID'} + 'Dauer': {'de': 'Dauer', 'en': 'Duration'} + 'Geändert': {'de': 'Geändert', 'en': 'Changed'} + 'Übersicht': {'de': 'Übersicht', 'en': 'Overview'} + 'am': {'de': 'am', 'en': 'on the'} + 'Datensätze': {'de': 'Datensätze', 'en': 'Data Sets'} 'Item-ID in der Datenbank': - de: 'Item-ID in der Datenbank' - en: 'Item ID within the database' + 'de': 'Item-ID in der Datenbank' + 'en': 'Item ID within the database' 'Die folgenden Items sind dieser Instanz des Database Plugins zugewiesen': - de: 'Die folgenden Items sind dieser Instanz des Database Plugins zugewiesen' - en: 'The following items are assigned to this instance of the database plugin' + 'de': 'Die folgenden Items sind dieser Instanz des Database Plugins zugewiesen' + 'en': 'The following items are assigned to this instance of the database plugin' 'Löschauftrag für die Einträge von Item ID': - de: 'Löschauftrag für die Einträge von Item ID' - en: 'Deletion of data for the entries of item ID' + 'de': 'Löschauftrag für die Einträge von Item ID' + 'en': 'Deletion of data for the entries of item ID' 'in der Tabelle "log" wurde erfolgreich initiiert!': - de: 'in der Tabelle "log" wurde erfolgreich initiiert!' - en: 'in table "log" successfully initiated.' + 'de': 'in der Tabelle "log" wurde erfolgreich initiiert!' + 'en': 'in table "log" successfully initiated.' 'Löschauftrag in der Tabelle "log" wurde erfolgreich initiiert!': - de: 'Löschauftrag in der Tabelle "log" wurde erfolgreich initiiert!' - en: 'Deletion of data set successfully initiated!' + 'de': 'Löschauftrag in der Tabelle "log" wurde erfolgreich initiiert!' + 'en': 'Deletion of data set successfully initiated!' 'Das Löschen kann noch kurze Zeit dauern, da die Ausführung des Delete Queries erst nach Abschluß der bestehenden Transaktionen erfolgen kann.': - de: 'Das Löschen kann noch kurze Zeit dauern, da die Ausführung des Delete Queries erst nach Abschluß der bestehenden Transaktionen erfolgen kann.' - en: 'The deletion could take a short time, as the DELETE query will be processed after the end of already existing database transactions.' + 'de': 'Das Löschen kann noch kurze Zeit dauern, da die Ausführung des Delete Queries erst nach Abschluß der bestehenden Transaktionen erfolgen kann.' + 'en': 'The deletion could take a short time, as the DELETE query will be processed after the end of already existing database transactions.' 'Die folgenden Einträge entstammen der log Tabelle mit historischen Daten für das Item {{ item_path }} (Datenbank-ID: {{ item_id }})': - de: 'Die folgenden Einträge entstammen der log Tabelle mit historischen Daten für das Item' - en: 'The following entries are derived from the log table with historical data for item )' + 'de': 'Die folgenden Einträge entstammen der log Tabelle mit historischen Daten für das Item' + 'en': 'The following entries are derived from the log table with historical data for item )' 'Datenbank-ID': - de: 'Datenbank-ID' - en: 'Database ID' + 'de': 'Datenbank-ID' + 'en': 'Database ID' 'Wollen Sie die historischen Daten (Tabelle log) dieses Items wirklich löschen?': - de: 'Wollen Sie die historischen Daten (Tabelle log) dieses Items wirklich löschen?' - en: 'Do you really want to delete the historical data (table log) of this item?' + 'de': 'Wollen Sie die historischen Daten (Tabelle log) dieses Items wirklich löschen?' + 'en': 'Do you really want to delete the historical data (table log) of this item?' 'Wollen Sie den Datensatz (Tabelle log) dieses Items wirklich löschen?': - de: 'Wollen Sie den Datensatz (Tabelle log) dieses Items wirklich löschen?' - en: 'Do you really want to delete the historic dataset (table log) of this item?' + 'de': 'Wollen Sie den Datensatz (Tabelle log) dieses Items wirklich löschen?' + 'en': 'Do you really want to delete the historic dataset (table log) of this item?' 'CSV Export der Werte': - de: 'CSV Export der Werte' - en: 'CSV Export of Values' + 'de': 'CSV Export der Werte' + 'en': 'CSV Export of Values' 'Historische Daten': - de: 'Historische Daten' - en: 'Historical Data' + 'de': 'Historische Daten' + 'en': 'Historical Data' 'Wertehistorie löschen': - de: 'Wertehistorie löschen' - en: 'Delete Historical Data' + 'de': 'Wertehistorie löschen' + 'en': 'Delete Historical Data' 'Wert löschen': - de: 'Wert löschen' - en: 'Delete Value' + 'de': 'Wert löschen' + 'en': 'Delete Value' 'Zeige Einträge vom': - de: 'Zeige Einträge vom' - en: 'Show entries from' \ No newline at end of file + 'de': 'Zeige Einträge vom' + 'en': 'Show entries from' \ No newline at end of file From 71a26df53f7d26eedf0a5bc016acc6b7e2632b55 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Tue, 24 Jul 2018 18:02:14 +0200 Subject: [PATCH 062/705] Database: fix for translation --- database/webif/templates/item_details.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/webif/templates/item_details.html b/database/webif/templates/item_details.html index 451cdef8f..34b75e23e 100644 --- a/database/webif/templates/item_details.html +++ b/database/webif/templates/item_details.html @@ -33,7 +33,7 @@
{% endif %}
- {{ _('Die folgenden Einträge entstammen der log Tabelle mit historischen Daten für das Item') }} {{ item_path }} {{ _('am') }} {% if day and month and year %}{% if language == 'en' %}{{ month }}/{{ day }}/{{ year }}{% else %}{{ day }}.{{ month }}.{{ year }}{% endif %}{% else %}{% if language == 'en' %}{{ now.strftime('%-m/%-d/%Y') }}{% else %}{{ now.strftime('%-d.%-m.%Y') }}{% endif %}{% endif %} {{_('(Datenbank-ID') }}: {{ item_id }}, {{ log_array | length }} {{_('Datensätze')}}): + {{ _('Die folgenden Einträge entstammen der log Tabelle mit historischen Daten für das Item') }} {{ item_path }} {{ _('am') }} {% if day and month and year %}{% if language == 'en' %}{{ month }}/{{ day }}/{{ year }}{% else %}{{ day }}.{{ month }}.{{ year }}{% endif %}{% else %}{% if language == 'en' %}{{ now.strftime('%-m/%-d/%Y') }}{% else %}{{ now.strftime('%-d.%-m.%Y') }}{% endif %}{% endif %} ({{_('Datenbank-ID') }}: {{ item_id }}, {{ log_array | length }} {{_('Datensätze')}}):
From 5fc17bebc2a9cf463bcb7861f6097259636c2e64 Mon Sep 17 00:00:00 2001 From: aschwith Date: Tue, 24 Jul 2018 19:22:32 +0200 Subject: [PATCH 063/705] Enocean: minor improvements for webif --- enocean/__init__.py | 8 +++++++- enocean/locale.yaml | 4 ++-- enocean/webif/templates/base_enocean.html | 2 +- enocean/webif/templates/index.html | 6 +++++- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/enocean/__init__.py b/enocean/__init__.py index 666c03f62..495638718 100644 --- a/enocean/__init__.py +++ b/enocean/__init__.py @@ -183,6 +183,7 @@ def __init__(self, smarthome, serialport, tx_id=''): self._response_lock = threading.Condition() self._rx_items = {} self.UTE_listen = False + self.unknown_sender_id = 'None' self._block_ext_out_msg = False # call init of eep_parser self.eep_parser = eep_parser.EEP_Parser() @@ -309,6 +310,7 @@ def _process_packet_type_radio(self, data, optional): elif (sender_id <= self.tx_id + 127) and (sender_id >= self.tx_id): self.logger.debug("enocean: Received repeated enocean stick message") else: + self.unknown_sender_id = "{:08X}".format(sender_id) self.logger.info("unknown ID = {:08X}".format(sender_id)) @@ -453,7 +455,11 @@ def stop(self): self.alive = False self.logger.info("enocean: Thread stopped") - + def get_tx_id_as_hex(self): + hexstring = "{:08X}".format(self.tx_id) + return hexstring + + def _send_UTE_response(self, data, optional): self.logger.debug("enocean: call function << _send_UTE_response >>") choice = data[0] diff --git a/enocean/locale.yaml b/enocean/locale.yaml index 1bb51847c..85f64e8da 100644 --- a/enocean/locale.yaml +++ b/enocean/locale.yaml @@ -24,7 +24,7 @@ plugin_translations: 'Wollen Sie das Senden wirklich umschalten?': de: 'Wollen Sie das Senden wirklich umschalten?' en: 'Do you really want to change the sending state?' - fr: 'Changer le stade de l'emitteur?' + fr: 'Changer le stade de lemitteur?' 'Neu hinzufügen': de: 'Neu hinzufügen' @@ -32,5 +32,5 @@ plugin_translations: fr: 'Ajouter' 'Enocean Geräte anlernen': de: 'Enocean Geräte anlernen' - en: 'Teach-in new Enocean devices + en: 'Teach-in new Enocean devices' fr: 'Ajouter nouveux acteur' \ No newline at end of file diff --git a/enocean/webif/templates/base_enocean.html b/enocean/webif/templates/base_enocean.html index ed027ed10..7f8fd825c 100644 --- a/enocean/webif/templates/base_enocean.html +++ b/enocean/webif/templates/base_enocean.html @@ -17,7 +17,7 @@ {{ _('ChipBaseID') }} - {{ p.tx_id }} + {{ p.get_tx_id_as_hex() }} diff --git a/enocean/webif/templates/index.html b/enocean/webif/templates/index.html index c3aceaf7b..c0f07e138 100644 --- a/enocean/webif/templates/index.html +++ b/enocean/webif/templates/index.html @@ -61,6 +61,11 @@ {% block bodytab2 %} +
+ {{ _('Unbekannte Sensor ID') }}: + {{ p.unknown_sender_id }} +
+
{{ _('Enocean Geräte anlernen') }}:
@@ -75,6 +80,5 @@ {{ _('Offset') }} - {% endblock bodytab2 %} From dc594cb0fcd6633a78c5392bb5f0ed01d4752e5e Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 25 Jul 2018 15:47:41 +0200 Subject: [PATCH 064/705] Webservices: added optional parameter to overwrite item settings val or full to items and itemsets --- webservices/__init__.py | 112 +++++++++++++------------ webservices/locale.yaml | 8 +- webservices/webif/templates/index.html | 7 +- 3 files changed, 70 insertions(+), 57 deletions(-) diff --git a/webservices/__init__.py b/webservices/__init__.py index f97cbb68b..6dd8c6c82 100644 --- a/webservices/__init__.py +++ b/webservices/__init__.py @@ -26,6 +26,7 @@ import json import html import os +import cherrypy from lib.model.smartplugin import * @@ -44,6 +45,9 @@ def __init__(self, smarthome, mode="all"): if not self.init_webinterfaces(): self._init_complete = False + def get_mode(self): + return self._mode + def init_webinterfaces(self): try: self.mod_http = Modules.get_instance().get_module( @@ -109,12 +113,6 @@ def stop(self): # Webinterface of the plugin # ------------------------------------------ -import cherrypy - - -# from jinja2 import Environment, FileSystemLoader - - class WebInterface(SmartPluginWebIf): def __init__(self, webif_dir, plugin): @@ -145,9 +143,9 @@ def index(self, reload=None): item_sets = {} items_sorted = sorted(self.plugin._sh.return_items(), key=lambda k: str.lower(k['_path']), reverse=False) for item in items_sorted: - if self.plugin._mode == 'all' or self.plugin.has_iattr(item.conf, 'webservices_set'): + if self.plugin.get_mode() == 'all' or self.plugin.has_iattr(item.conf, 'webservices_set'): if item.type() in ['str', 'bool', 'num'] or ( - item.type() in ['foo'] and item._path in self.plugin.ALLOWED_FOO_PATHS): + item.type() in ['foo'] and item.path() in self.plugin.ALLOWED_FOO_PATHS): items_filtered.append(item) if self.plugin.has_iattr(item.conf, 'webservices_set'): if isinstance(self.plugin.get_iattr_value(item.conf, 'webservices_set'), list): @@ -194,9 +192,9 @@ def check_set(self, set_id, item_sets): def assemble_item_data(self, item, webservices_data='full'): if item is not None: if item.type() in ['str', 'bool', 'num'] or ( - item.type() in ['foo'] and item._path in self.plugin.ALLOWED_FOO_PATHS): + item.type() in ['foo'] and item.path() in self.plugin.ALLOWED_FOO_PATHS): value = item._value - if item.type() in ['foo'] and item._path in self.plugin.ALLOWED_FOO_PATHS: + if item.type() in ['foo'] and item.path() in self.plugin.ALLOWED_FOO_PATHS: if isinstance(value, datetime.datetime): value = str(value) if webservices_data == 'full': @@ -208,7 +206,7 @@ def assemble_item_data(self, item, webservices_data='full'): cycle = '' crontab = '' for entry in self.plugin._sh.scheduler._scheduler: - if entry == item._path: + if entry == item.path(): if self.plugin._sh.scheduler._scheduler[entry]['cycle']: cycle = self.plugin._sh.scheduler._scheduler[entry]['cycle'] if self.plugin._sh.scheduler._scheduler[entry]['cron']: @@ -235,7 +233,7 @@ def assemble_item_data(self, item, webservices_data='full'): trig = trig[1:len(trig) - 27] triggers.append(format(trig.replace("<", ""))) - data_dict = {'path': item._path, + data_dict = {'path': item.path(), 'name': item._name, 'type': item.type(), 'value': value, @@ -260,7 +258,7 @@ def assemble_item_data(self, item, webservices_data='full'): } return data_dict elif webservices_data == 'val': - return {'path': item._path, 'value': value} + return {'path': item.path(), 'value': value} else: return None @@ -269,7 +267,7 @@ class SimpleWebServiceInterface(WebServiceInterface): @cherrypy.expose @cherrypy.tools.json_in() @cherrypy.tools.json_out() - def itemset(self, set_id=None): + def itemset(self, set_id=None, mode=None): """ REST function for items """ @@ -285,7 +283,8 @@ def itemset(self, set_id=None): for item in items_sorted: if self.plugin.has_iattr(item.conf, 'webservices_set'): if self.check_set(set_id, self.plugin.get_iattr_value(item.conf, 'webservices_set')): - if self.plugin.get_iattr_value(item.conf, 'webservices_data') == 'val': + if (mode is None and self.plugin.get_iattr_value(item.conf, + 'webservices_data') == 'val') or mode == 'val': item_data = self.assemble_item_data(item, 'val') if item_data is not None: items[item_data['path']] = item_data['value'] @@ -294,15 +293,15 @@ def itemset(self, set_id=None): if item_data is not None: item_data['url'] = "http://%s:%s/ws/items/%s" % ( self.plugin.mod_http.get_local_ip_address(), - self.plugin.mod_http.get_local_port(), item._path) - items[item._path] = item_data + self.plugin.mod_http.get_local_port(), item.path()) + items[item.path()] = item_data return items else: return {"Error": "No set-ID for item set is given."} @cherrypy.expose @cherrypy.tools.json_out() - def items(self, item_path=None, value=None): + def items(self, item_path=None, value=None, mode=None): """ Simpole WS functions for item """ @@ -316,16 +315,17 @@ def items(self, item_path=None, value=None): reverse=False) items = {} for item in items_sorted: - if self.plugin._mode == 'all' or self.plugin.has_iattr(item.conf, 'webservices_set'): - mode = "full" - if self.plugin.get_iattr_value(item.conf, 'webservices_data') == 'val': - mode = "val" - item_data = self.assemble_item_data(item, mode) + if self.plugin.get_mode() == 'all' or self.plugin.has_iattr(item.conf, 'webservices_set'): + final_mode = "full" + if (mode is None and self.plugin.get_iattr_value(item.conf, + 'webservices_data') == 'val') or mode == 'val': + final_mode = "val" + item_data = self.assemble_item_data(item, final_mode) if item_data is not None: - if mode != "val": + if final_mode != "val": item_data['url'] = "http://%s:%s/ws/items/%s" % ( self.plugin.mod_http.get_local_ip_address(), - self.plugin.mod_http.get_local_servicesport(), item._path) + self.plugin.mod_http.get_local_servicesport(), item.path()) items[item_data['path']] = item_data return items else: @@ -333,22 +333,24 @@ def items(self, item_path=None, value=None): if item is None: return {"Error": "No item with item path %s found." % item_path} - if self.plugin._mode == 'all' or self.plugin.has_iattr(item.conf, 'webservices_set'): + if self.plugin.get_mode() == 'all' or self.plugin.has_iattr(item.conf, 'webservices_set'): if item.type() in ['str', 'bool', 'num'] or ( - item.type() in ['foo'] and item._path in self.plugin.ALLOWED_FOO_PATHS): + item.type() in ['foo'] and item.path() in self.plugin.ALLOWED_FOO_PATHS): if value is not None and item.type() in ['str', 'bool', 'num']: item(value) return {"Success": "Item with item path %s set to %s." % (item_path, value)} else: - mode = "full" - if self.plugin.get_iattr_value(item.conf, 'webservices_data') == 'val': - mode = "val" - item_data = self.assemble_item_data(item, mode) + final_mode = "full" + if (mode is None and self.plugin.get_iattr_value(item.conf, + 'webservices_data') == 'val') or mode == 'val': + final_mode = "val" + item_data = self.assemble_item_data(item, final_mode) if item_data is not None: return item_data else: - return {"Error": "Item with path %s is type %s, only str, num, bool and foo item types (of special system items) are supported." % - (item_path, item.type())} + return { + "Error": "Item with path %s is type %s, only str, num, bool and foo item types (of special system items) are supported." % + (item_path, item.type())} else: return {"Error": "Item with path %s not allowed for access via Webservice plugin." % item_path} @@ -358,7 +360,7 @@ class RESTWebServicesInterface(WebServiceInterface): @cherrypy.expose @cherrypy.tools.json_in() @cherrypy.tools.json_out() - def itemset(self, set_id=None): + def itemset(self, set_id=None, mode=None): """ REST function for items """ @@ -374,7 +376,8 @@ def itemset(self, set_id=None): for item in items_sorted: if self.plugin.has_iattr(item.conf, 'webservices_set'): if self.check_set(set_id, self.plugin.get_iattr_value(item.conf, 'webservices_set')): - if self.plugin.get_iattr_value(item.conf, 'webservices_data') == 'val': + if (mode is None and self.plugin.get_iattr_value(item.conf, + 'webservices_data') == 'val') or mode == 'val': item_data = self.assemble_item_data(item, 'val') if item_data is not None: items[item_data['path']] = item_data['value'] @@ -383,7 +386,7 @@ def itemset(self, set_id=None): if item_data is not None: item_data['url'] = "http://%s:%s/rest/items/%s" % ( self.plugin.mod_http.get_local_ip_address(), - self.plugin.mod_http.get_local_port(), item._path) + self.plugin.mod_http.get_local_port(), item.path()) items[item_data['path']] = item_data return items else: @@ -392,7 +395,7 @@ def itemset(self, set_id=None): @cherrypy.expose @cherrypy.tools.json_in() @cherrypy.tools.json_out() - def items(self, item_path=None): + def items(self, item_path=None, mode=None): """ REST function for items """ @@ -406,16 +409,17 @@ def items(self, item_path=None): reverse=False) items = {} for item in items_sorted: - if self.plugin._mode == 'all' or self.plugin.has_iattr(item.conf, 'webservices_set'): - mode = "full" - if self.plugin.get_iattr_value(item.conf, 'webservices_data') == 'val': - mode = "val" - item_data = self.assemble_item_data(item, mode) + if self.plugin.get_mode() == 'all' or self.plugin.has_iattr(item.conf, 'webservices_set'): + final_mode = "full" + if (mode is None and self.plugin.get_iattr_value(item.conf, + 'webservices_data') == 'val') or mode == 'val': + final_mode = "val" + item_data = self.assemble_item_data(item, final_mode) if item_data is not None: - if mode != 'val': + if final_mode != 'val': item_data['url'] = "http://%s:%s/rest/items/%s" % ( self.plugin.mod_http.get_local_ip_address(), - self.plugin.mod_http.get_local_port(), item._path) + self.plugin.mod_http.get_local_port(), item.path()) items[item_data['path']] = item_data return items else: @@ -424,7 +428,7 @@ def items(self, item_path=None): if item is None: return {"Error": "No item with item path %s found." % item_path} - if self.plugin._mode == 'all' or self.plugin.has_iattr(item.conf, 'webservices_set'): + if self.plugin.get_mode() == 'all' or self.plugin.has_iattr(item.conf, 'webservices_set'): if cherrypy.request.method == 'PUT' or cherrypy.request.method == 'POST': data = cherrypy.request.json self.logger.debug(data) @@ -464,20 +468,22 @@ def items(self, item_path=None): item.type())} elif cherrypy.request.method == 'GET': - mode = "full" - if self.plugin.get_iattr_value(item.conf, 'webservices_data') == 'val': - mode = "val" - item_data = self.assemble_item_data(item, mode) + final_mode = "full" + if (mode is None and self.plugin.get_iattr_value(item.conf, + 'webservices_data') == 'val') or mode == 'val': + final_mode = "val" + item_data = self.assemble_item_data(item, final_mode) if item_data is not None: - if mode != 'val': + if final_mode != 'val': item_data['url'] = "http://%s:%s/rest/items/%s" % ( self.plugin.mod_http.get_local_ip_address(), self.plugin.mod_http.get_local_servicesport(), - item._path) + item.path()) return item_data else: - return {"Error": "Item with path %s is type %s, only str, num, bool and foo item types (of special system items) are supported." % - (item_path, item.type())} + return { + "Error": "Item with path %s is type %s, only str, num, bool and foo item types (of special system items) are supported." % + (item_path, item.type())} else: return {"Error": "Item with path %s not allowed for access via Webservice plugin." % item_path} diff --git a/webservices/locale.yaml b/webservices/locale.yaml index e2f7ffbc8..c78b587d0 100755 --- a/webservices/locale.yaml +++ b/webservices/locale.yaml @@ -7,6 +7,8 @@ plugin_translations: # Alternative format for translations of longer texts: 'Die folgenden Items und Sets können über die REST und die Simple WebService API gelesen und (bei str, num und bool Items) verändert werden': - de: '=' - en: 'The following items and sets can be read through the REST and the Simple WebService API. Values of str, num, and bool items can also be changed.' - + 'de': '=' + 'en': 'The following items and sets can be read through the REST and the Simple WebService API. Values of str, num, and bool items can also be changed.' + 'Tipp: Durch Anhängen des Parameters "?mode=val|full" kann erzwungen werden, dass das Item / Itemset mit vollen oder einfachen Daten zurückgeliefert wird. Ansonsten greift die Konfiguration im Item via webservices_data.': + 'de': '=' + 'en': 'Hint: By adding the parameter "?mode=val|full" to the URL, it can be enforced that the Item / Itemset is returned with full / simple data. Otherwise the configuration within the item (webservices_data) applies.' diff --git a/webservices/webif/templates/index.html b/webservices/webif/templates/index.html index ec7ff881a..d97a23af5 100755 --- a/webservices/webif/templates/index.html +++ b/webservices/webif/templates/index.html @@ -21,7 +21,12 @@ {% block bodytab1 %}
- {{ _('Die folgenden Items und Sets können über die REST und die Simple WebService API gelesen und (bei str, num und bool Items) verändert werden') }}: +

+ {{ _('Tipp: Durch Anhängen des Parameters "?mode=val|full" kann erzwungen werden, dass das Item / Itemset mit vollen oder einfachen Daten zurückgeliefert wird. Ansonsten greift die Konfiguration im Item via webservices_data.')}} +

+

+ {{ _('Die folgenden Items und Sets können über die REST und die Simple WebService API gelesen und (bei str, num und bool Items) verändert werden') }}: +

From 809f1d832176a75ac6d516cbbd900e3563e078dd Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 25 Jul 2018 15:49:28 +0200 Subject: [PATCH 065/705] Webservices: increased version --- webservices/README.md | 2 +- webservices/__init__.py | 2 +- webservices/plugin.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/webservices/README.md b/webservices/README.md index dc7621ded..08ef1598b 100644 --- a/webservices/README.md +++ b/webservices/README.md @@ -11,7 +11,7 @@ Support-Thread für das Plugin: https://knx-user-forum.de/forum/supportforen/sma ## Requirements This plugin requires CherryPy to be installed via pip. -It requires SmartHomeNG 1.4 or higher! +It requires SmartHomeNG 1.5 or higher! ## Configuration diff --git a/webservices/__init__.py b/webservices/__init__.py index 6dd8c6c82..18d2a516c 100644 --- a/webservices/__init__.py +++ b/webservices/__init__.py @@ -34,7 +34,7 @@ class WebServices(SmartPlugin): - PLUGIN_VERSION = '1.5.0.3' + PLUGIN_VERSION = '1.5.0.4' ALLOWED_FOO_PATHS = ['env.location.moonrise', 'env.location.moonset', 'env.location.sunrise', 'env.location.sunset'] def __init__(self, smarthome, mode="all"): diff --git a/webservices/plugin.yaml b/webservices/plugin.yaml index 82c028f0f..fd9119fe9 100755 --- a/webservices/plugin.yaml +++ b/webservices/plugin.yaml @@ -11,8 +11,8 @@ plugin: documentation: https://www.smarthomeng.de/?category_name=plugins&s=webservices support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1163886-support-thread-f%C3%BCr-das-webservices-plugin - version: 1.5.0.3 # Plugin version - sh_minversion: 1.4c # minimum shNG version to use this plugin + version: 1.5.0.5 # Plugin version + sh_minversion: 1.5 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance classname: WebServices # class containing the plugin From 169c9542c22598c21e0eb67b5a09b79b6339f98c Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 25 Jul 2018 15:53:24 +0200 Subject: [PATCH 066/705] Webservices: access to smarthome via get method --- webservices/__init__.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/webservices/__init__.py b/webservices/__init__.py index 18d2a516c..08d5b48eb 100644 --- a/webservices/__init__.py +++ b/webservices/__init__.py @@ -141,7 +141,7 @@ def index(self, reload=None): """ items_filtered = [] item_sets = {} - items_sorted = sorted(self.plugin._sh.return_items(), key=lambda k: str.lower(k['_path']), reverse=False) + items_sorted = sorted(self.plugin.get_sh().return_items(), key=lambda k: str.lower(k['_path']), reverse=False) for item in items_sorted: if self.plugin.get_mode() == 'all' or self.plugin.has_iattr(item.conf, 'webservices_set'): if item.type() in ['str', 'bool', 'num'] or ( @@ -205,12 +205,12 @@ def assemble_item_data(self, item, webservices_data='full'): cycle = '' crontab = '' - for entry in self.plugin._sh.scheduler._scheduler: + for entry in self.plugin.get_sh().scheduler._scheduler: if entry == item.path(): - if self.plugin._sh.scheduler._scheduler[entry]['cycle']: - cycle = self.plugin._sh.scheduler._scheduler[entry]['cycle'] - if self.plugin._sh.scheduler._scheduler[entry]['cron']: - crontab = str(self.plugin._sh.scheduler._scheduler[entry]['cron']) + if self.plugin.get_sh().scheduler._scheduler[entry]['cycle']: + cycle = self.plugin.get_sh().scheduler._scheduler[entry]['cycle'] + if self.plugin.get_sh().scheduler._scheduler[entry]['cron']: + crontab = str(self.plugin.get_sh().scheduler._scheduler[entry]['cron']) break changed_by = item.changed_by() @@ -277,7 +277,7 @@ def itemset(self, set_id=None, mode=None): return {"Error": "%s requests not allowed for this URL" % cherrypy.request.method} elif cherrypy.request.method == 'GET': - items_sorted = sorted(self.plugin._sh.return_items(), key=lambda k: str.lower(k['_path']), + items_sorted = sorted(self.plugin.get_sh().return_items(), key=lambda k: str.lower(k['_path']), reverse=False) items = {} for item in items_sorted: From 7cfe7c9f7edbb40b638463791757bb133a1d5db7 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 25 Jul 2018 18:39:03 +0200 Subject: [PATCH 067/705] Webservices: version fixed --- webservices/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webservices/__init__.py b/webservices/__init__.py index 08d5b48eb..ab425852f 100644 --- a/webservices/__init__.py +++ b/webservices/__init__.py @@ -34,7 +34,7 @@ class WebServices(SmartPlugin): - PLUGIN_VERSION = '1.5.0.4' + PLUGIN_VERSION = '1.5.0.5' ALLOWED_FOO_PATHS = ['env.location.moonrise', 'env.location.moonset', 'env.location.sunrise', 'env.location.sunset'] def __init__(self, smarthome, mode="all"): From d844237ab3b9fb55cc158d4a24a806cca6e87b2e Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 25 Jul 2018 20:55:26 +0200 Subject: [PATCH 068/705] item.path() -> item._path --- webservices/__init__.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/webservices/__init__.py b/webservices/__init__.py index ab425852f..9afef9b94 100644 --- a/webservices/__init__.py +++ b/webservices/__init__.py @@ -145,7 +145,7 @@ def index(self, reload=None): for item in items_sorted: if self.plugin.get_mode() == 'all' or self.plugin.has_iattr(item.conf, 'webservices_set'): if item.type() in ['str', 'bool', 'num'] or ( - item.type() in ['foo'] and item.path() in self.plugin.ALLOWED_FOO_PATHS): + item.type() in ['foo'] and item._path in self.plugin.ALLOWED_FOO_PATHS): items_filtered.append(item) if self.plugin.has_iattr(item.conf, 'webservices_set'): if isinstance(self.plugin.get_iattr_value(item.conf, 'webservices_set'), list): @@ -192,9 +192,9 @@ def check_set(self, set_id, item_sets): def assemble_item_data(self, item, webservices_data='full'): if item is not None: if item.type() in ['str', 'bool', 'num'] or ( - item.type() in ['foo'] and item.path() in self.plugin.ALLOWED_FOO_PATHS): + item.type() in ['foo'] and item._path in self.plugin.ALLOWED_FOO_PATHS): value = item._value - if item.type() in ['foo'] and item.path() in self.plugin.ALLOWED_FOO_PATHS: + if item.type() in ['foo'] and item._path in self.plugin.ALLOWED_FOO_PATHS: if isinstance(value, datetime.datetime): value = str(value) if webservices_data == 'full': @@ -206,7 +206,7 @@ def assemble_item_data(self, item, webservices_data='full'): cycle = '' crontab = '' for entry in self.plugin.get_sh().scheduler._scheduler: - if entry == item.path(): + if entry == item._path: if self.plugin.get_sh().scheduler._scheduler[entry]['cycle']: cycle = self.plugin.get_sh().scheduler._scheduler[entry]['cycle'] if self.plugin.get_sh().scheduler._scheduler[entry]['cron']: @@ -233,7 +233,7 @@ def assemble_item_data(self, item, webservices_data='full'): trig = trig[1:len(trig) - 27] triggers.append(format(trig.replace("<", ""))) - data_dict = {'path': item.path(), + data_dict = {'path': item._path, 'name': item._name, 'type': item.type(), 'value': value, @@ -258,7 +258,7 @@ def assemble_item_data(self, item, webservices_data='full'): } return data_dict elif webservices_data == 'val': - return {'path': item.path(), 'value': value} + return {'path': item._path, 'value': value} else: return None @@ -293,8 +293,8 @@ def itemset(self, set_id=None, mode=None): if item_data is not None: item_data['url'] = "http://%s:%s/ws/items/%s" % ( self.plugin.mod_http.get_local_ip_address(), - self.plugin.mod_http.get_local_port(), item.path()) - items[item.path()] = item_data + self.plugin.mod_http.get_local_port(), item._path) + items[item._path] = item_data return items else: return {"Error": "No set-ID for item set is given."} @@ -325,7 +325,7 @@ def items(self, item_path=None, value=None, mode=None): if final_mode != "val": item_data['url'] = "http://%s:%s/ws/items/%s" % ( self.plugin.mod_http.get_local_ip_address(), - self.plugin.mod_http.get_local_servicesport(), item.path()) + self.plugin.mod_http.get_local_servicesport(), item._path) items[item_data['path']] = item_data return items else: @@ -335,7 +335,7 @@ def items(self, item_path=None, value=None, mode=None): if self.plugin.get_mode() == 'all' or self.plugin.has_iattr(item.conf, 'webservices_set'): if item.type() in ['str', 'bool', 'num'] or ( - item.type() in ['foo'] and item.path() in self.plugin.ALLOWED_FOO_PATHS): + item.type() in ['foo'] and item._path in self.plugin.ALLOWED_FOO_PATHS): if value is not None and item.type() in ['str', 'bool', 'num']: item(value) return {"Success": "Item with item path %s set to %s." % (item_path, value)} @@ -386,7 +386,7 @@ def itemset(self, set_id=None, mode=None): if item_data is not None: item_data['url'] = "http://%s:%s/rest/items/%s" % ( self.plugin.mod_http.get_local_ip_address(), - self.plugin.mod_http.get_local_port(), item.path()) + self.plugin.mod_http.get_local_port(), item._path) items[item_data['path']] = item_data return items else: @@ -419,7 +419,7 @@ def items(self, item_path=None, mode=None): if final_mode != 'val': item_data['url'] = "http://%s:%s/rest/items/%s" % ( self.plugin.mod_http.get_local_ip_address(), - self.plugin.mod_http.get_local_port(), item.path()) + self.plugin.mod_http.get_local_port(), item._path) items[item_data['path']] = item_data return items else: @@ -478,7 +478,7 @@ def items(self, item_path=None, mode=None): item_data['url'] = "http://%s:%s/rest/items/%s" % ( self.plugin.mod_http.get_local_ip_address(), self.plugin.mod_http.get_local_servicesport(), - item.path()) + item._path) return item_data else: return { From 3d6b9376c37d6608ac6ed27af677cc782e5ad3ea Mon Sep 17 00:00:00 2001 From: aschwith Date: Thu, 26 Jul 2018 21:40:50 +0200 Subject: [PATCH 069/705] Enocean: further work on webif, local.yaml; Url fix for eta_pu plugin --- enocean/locale.yaml | 60 +++++++++++++++------- enocean/prepare_packet_data.py | 2 +- enocean/webif/templates/base_enocean.html | 1 - enocean/webif/templates/index.html | 61 +++++++++++++++-------- eta_pu/README.md | 2 +- 5 files changed, 84 insertions(+), 42 deletions(-) diff --git a/enocean/locale.yaml b/enocean/locale.yaml index 85f64e8da..d938f4166 100644 --- a/enocean/locale.yaml +++ b/enocean/locale.yaml @@ -1,36 +1,58 @@ plugin_translations: # Translations for the plugin specially for the web interface - 'Aktionen': {'de': 'Aktionen', 'en': 'Actions'} - 'Blockiert': {'de': 'Blockiert', 'en': 'Blocked', 'fr': 'Blocke'} - 'Ja': {'de': 'Ja', 'en': 'Yes'} - 'Nein': {'de': 'Nein', 'en': 'No'} - 'Ein': {'de': 'Ein', en: 'On'} - 'Zeit': {'de': 'Zeit', en: 'Time'} - 'Item ID': {'de': 'Item ID', en: 'Item ID'} - 'Gerätetyp': {'de': 'Gerätetyp', en: 'Device Type'} - 'Übersicht': {'de': 'Übersicht', en: 'Overview'} + 'Item': {'de': 'Item', 'en': 'Item', 'fr': 'Objet'} + 'Blockiert': {'de': 'Blockiert', 'en': 'Blocked', 'fr': 'Blocké'} + 'Ja': {'de': 'Ja', 'en': 'Yes', 'fr': 'Oui'} + 'Nein': {'de': 'Nein', 'en': 'No', 'fr': 'Non'} 'Senden': de: 'Senden' en: 'Sending' - 'Die folgenden Items sind dieser Instanz des Enocean Plugins zugewiesen': - de: 'Die folgenden Items sind dieser Instanz des Enocean Plugins zugewiesen' - en: 'The following items are assigned to this instance of the enocean plugin' + fr: 'Emettre' 'UTE Listen': de: 'UTE Listen' en: 'UTE Listen' + fr: 'UTE Listen' + 'Aktiv': {'de': 'Aktiv', 'en': 'Active', 'fr': Active} + 'Aus': {'de': 'Aus', 'en': 'Off', 'fr': 'éteint'} + 'Ein': {'de': 'Ein', en: 'On', 'fr': 'Active'} 'Senden An/Aus': de: 'Senden An/Aus' en: 'Tx On/Off' + fr: 'Tx On/Off' 'Wollen Sie das Senden wirklich umschalten?': de: 'Wollen Sie das Senden wirklich umschalten?' en: 'Do you really want to change the sending state?' - fr: 'Changer le stade de lemitteur?' - - 'Neu hinzufügen': - de: 'Neu hinzufügen' + fr: "Changer le stade de l'emitteur?" + 'Ãœbersicht': {'de': 'Ãœbersicht', 'en': 'Overview', 'fr': "vue d'ensemble"} + 'Wollen Sie ein Lerntelegramm schicken?': + de: 'Wollen Sie ein Lerntelegramm schicken?' + en: 'Do you really want to send a lern telegram?' + fr: "Volez-vous emettre un message à programmer?" + 'Wollen Sie den UTE Modus umschalten?': + de: 'Wollen Sie den UTE Modus umschalten?' + en: 'Do you really want to toggle the UTE mode?' + fr: "Confirmez de changer le mode UTE" + 'Neu hinzufügen': + de: 'Gerät hinzufügen' en: 'Add devie' fr: 'Ajouter' - 'Enocean Geräte anlernen': - de: 'Enocean Geräte anlernen' + 'Unbekannte Sensor ID': + de: 'Unbekannte Sensor ID' + en: 'Unknown Sensor ID' + fr: 'Capteur ID inconnu' + 'Enocean Geräte anlernen': + de: 'Enocean Geräte anlernen' en: 'Teach-in new Enocean devices' - fr: 'Ajouter nouveux acteur' \ No newline at end of file + fr: 'Ajouter nouveau acteur' + 'Gerätetyp': {'de': 'Gerätetyp', 'en': 'Device Type', 'fr': 'Type'} + 'ID Offset': {'de': 'ID Offset', 'en': 'ID Offset'} + 'Anlernen': {'de': 'Anlernen', 'en': 'Teach-in', 'fr': 'Programmer'} + 'UTE An/Aus': {'de': 'UTE An/Aus', 'en': 'UTE On/Off', 'fr': 'UTE On/Off'} + 'Die folgenden Items sind dieser Instanz des Enocean Plugins zugewiesen': + de: 'Die folgenden Items sind dieser Instanz des Enocean Plugins zugewiesen' + en: 'The following items are assigned to this instance of the Enocean plugin' + fr: "Les object suivants sont liés à cette instance de l'extension Enocean" + + + + diff --git a/enocean/prepare_packet_data.py b/enocean/prepare_packet_data.py index 816ad4d83..15111b644 100644 --- a/enocean/prepare_packet_data.py +++ b/enocean/prepare_packet_data.py @@ -62,7 +62,7 @@ def PrepareData(self, item, tx_eep): id_offset = 0 # start prepare data rorg, payload, optional = getattr(self, '_prepare_data_for_tx_eep_' + tx_eep)(item, tx_eep) - self.logger.info('enocean-PrepareData: {} returns [{:#04x}], [{}], [{}]'.format(tx_eep, rorg, ', '.join('{:#04x}'.format(x) for x in payload), ', '.join('{:#04x}'.format(x) for x in optional))) + #self.logger.info('enocean-PrepareData: {} returns [{:#04x}], [{}], [{}]'.format(tx_eep, rorg, ', '.join('{:#04x}'.format(x) for x in payload), ', '.join('{:#04x}'.format(x) for x in optional))) return id_offset, rorg, payload, optional diff --git a/enocean/webif/templates/base_enocean.html b/enocean/webif/templates/base_enocean.html index 7f8fd825c..5ffdd01f1 100644 --- a/enocean/webif/templates/base_enocean.html +++ b/enocean/webif/templates/base_enocean.html @@ -39,5 +39,4 @@ {% block buttons %} - {% endblock buttons %} \ No newline at end of file diff --git a/enocean/webif/templates/index.html b/enocean/webif/templates/index.html index c0f07e138..8d4334ede 100644 --- a/enocean/webif/templates/index.html +++ b/enocean/webif/templates/index.html @@ -23,7 +23,7 @@ return false; } - function prepareCommand() { + function prepareLearnCommand() { if (confirm('{{ _('Wollen Sie ein Lerntelegramm schicken?') }}')) { offsetvalue = $('#input-offset'); device_id_type = $('#enocean_device'); @@ -31,9 +31,17 @@ window.location.href='?action=send_learn&device_offset=' + offsetvalue .val() + '&device_id=' + device_id_type.val(); } return false; + } - + function prepareUTECommand() { + if (confirm('{{ _('Wollen Sie den UTE Modus umschalten?') }}')) { + offsetvalue = $('#input-offset'); + + window.location.href='?action=toggle_UTE&device_offset=' + offsetvalue .val(); + } + return false; } +
@@ -60,25 +68,38 @@ {% set tab2title = " " ~ _('Neu hinzufügen') ~ " " %} {% block bodytab2 %} - -
- {{ _('Unbekannte Sensor ID') }}: -
- - -
- {{ _('Enocean Geräte anlernen') }}: -
-
{{ _('Gerätetyp') }}:
+
+
+ {{ _('Unbekannte Sensor ID') }}: +
+ +
+
+
+ {{ _('Enocean Geräte anlernen') }}: +
+ {{ _('Gerätetyp') }}: +
+
- - {{ _('Offset') }} - +
- - - + {% if item.type() == 'num' %}{% endif %} + {% if item.type() == 'bool' %}{% endif %} + {% if item.type() == 'str' %}{% endif %} @@ -59,9 +59,9 @@ - - - + {% if item.type() == 'num' %}{% endif %} + {% if item.type() == 'bool' %}{% endif %} + {% if item.type() == 'str' %}{% endif %} {% endfor %} @@ -71,9 +71,9 @@ - - - + {{ item.type() == 'num'}} + {{ item.type() == 'bool'}} + {{ item.type() == 'str'}} {% endif %} From d344cfdcbacb3dc6a9819fe97ec0161c9c479285 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 27 Jul 2018 13:11:00 +0200 Subject: [PATCH 071/705] Tankerkoenig: added check for key in json response --- tankerkoenig/__init__.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tankerkoenig/__init__.py b/tankerkoenig/__init__.py index 306bd1ce5..0494f9b2b 100755 --- a/tankerkoenig/__init__.py +++ b/tankerkoenig/__init__.py @@ -130,18 +130,22 @@ def get_petrol_station_prices(self, ids): return json_obj = response.json() keys = ['e5', 'e10', 'diesel', 'status'] + for id in ids: - if id in json_obj['prices']: - result_station = dict() - result_station['id'] = id - for key in keys: - if key in json_obj['prices'][id]: - result_station[key] = json_obj['prices'][id][key] - else: - result_station[key] = "" - result_station_prices.append(result_station) + if 'prices' in json_obj: + if id in json_obj['prices']: + result_station = dict() + result_station['id'] = id + for key in keys: + if key in json_obj['prices'][id]: + result_station[key] = json_obj['prices'][id][key] + else: + result_station[key] = "" + result_station_prices.append(result_station) + else: + self.logger.error("No result for station with id %s. Check manually!" % id) else: - self.logger.error("No result for station with id %s. Check manually!" % id) + self.logger.error("'prices' key missing in json response! Check manually!" % id) return result_station_prices def _build_url(self, suffix): From 98f27fa0899c95821f69d24ecb7d30f5a060601f Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 27 Jul 2018 13:11:24 +0200 Subject: [PATCH 072/705] Backend: added missing translations --- backend/locale/de.json | 2 ++ backend/locale/en.json | 2 ++ backend/locale/fr.json | 2 ++ backend/locale/pl.json | 2 ++ 4 files changed, 8 insertions(+) diff --git a/backend/locale/de.json b/backend/locale/de.json index e43e82f38..caf4d7bca 100755 --- a/backend/locale/de.json +++ b/backend/locale/de.json @@ -206,6 +206,8 @@ "Entwicklungs-Daten": "Entwicklungs-Daten", "Plugin spezifische Parameter": "Plugin spezifische Parameter", "Plugin spezifische Item Attribute": "Plugin spezifische Item Attribute", + "Pakete für den Bau der Dokumentation": "Pakete für den Bau der Dokumentation", + "Pakete für die Testsuite": "Pakete für die Testsuite", "_items": { "path": "Pfad", diff --git a/backend/locale/en.json b/backend/locale/en.json index f6b0c775c..02025b037 100755 --- a/backend/locale/en.json +++ b/backend/locale/en.json @@ -206,6 +206,8 @@ "Entwicklungs-Daten": "Development Data", "Plugin spezifische Parameter": "Plugin specific parameters", "Plugin spezifische Item Attribute": "Plugin specific item attributes", + "Pakete für den Bau der Dokumentation": "Packages for Building the Documentation", + "Pakete für die Testsuite": "Packages for the Test Suite", "_items": { "path": "Pfad", diff --git a/backend/locale/fr.json b/backend/locale/fr.json index 82dfd88a1..ba881a4a3 100755 --- a/backend/locale/fr.json +++ b/backend/locale/fr.json @@ -111,6 +111,8 @@ "Ergebnis: Aufbereitetes .YAML Format": "Résultat: Format .YAML édité", "Ergebnis: Aufbereitet als Python Source Code": "Résultat: Edité en format code source Python", "Python Code Ausgabe": "Sortie code Python", + "Pakete für den Bau der Dokumentation": "Packages for Building the Documentation", + "Pakete für die Testsuite": "Packages for the Test Suite", "Nr.": "N°", "Type": "Type", diff --git a/backend/locale/pl.json b/backend/locale/pl.json index a29e6deed..d069230e9 100755 --- a/backend/locale/pl.json +++ b/backend/locale/pl.json @@ -108,6 +108,8 @@ "Ergebnis: Aufbereitetes .YAML Format": "", "Ergebnis: Aufbereitet als Python Source Code": "", "Python Code Ausgabe": "", + "Pakete für den Bau der Dokumentation": "Packages for Building the Documentation", + "Pakete für die Testsuite": "Packages for the Test Suite", "Nr.": "Nr", "Type": "Typ", From 6ce8acc9fd1bda5f6312d8de042c7d6c8ab00c46 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 27 Jul 2018 13:12:40 +0200 Subject: [PATCH 073/705] Database: added translations --- database/locale.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/database/locale.yaml b/database/locale.yaml index 6720d50a2..2315627ab 100644 --- a/database/locale.yaml +++ b/database/locale.yaml @@ -12,6 +12,9 @@ plugin_translations: 'Übersicht': {'de': 'Übersicht', 'en': 'Overview'} 'am': {'de': 'am', 'en': 'on the'} 'Datensätze': {'de': 'Datensätze', 'en': 'Data Sets'} + 'Aktueller Wert': {'de': '=', 'en': 'Recent Value'} + 'Typ': {'de': '=', 'en': 'Type'} + 'Tabelle': {'de': '=', 'en': 'Table'} 'Item-ID in der Datenbank': 'de': 'Item-ID in der Datenbank' 'en': 'Item ID within the database' From ad2d6682cb21dd98bb0843ebfe4ca6abb2aa6424 Mon Sep 17 00:00:00 2001 From: msinn Date: Fri, 27 Jul 2018 16:26:41 +0200 Subject: [PATCH 074/705] backend: Added json url for systeminfo (experimental for Angular) --- backend/BackendSysteminfo.py | 73 ++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/backend/BackendSysteminfo.py b/backend/BackendSysteminfo.py index 9a8ce237c..66b5abf15 100755 --- a/backend/BackendSysteminfo.py +++ b/backend/BackendSysteminfo.py @@ -109,6 +109,79 @@ def system_html(self): ip=ip, ipv6=ipv6) + @cherrypy.expose + def system_json(self): + """ + Return System inforation as json ( + for Angular tests only) + + :return: + """ +# now = datetime.datetime.now().strftime('%d.%m.%Y %H:%M') + now = self.plugin.shtime.now().strftime('%d.%m.%Y %H:%M') + system = platform.system() + vers = platform.version() + # node = platform.node() + node = socket.getfqdn() + arch = platform.machine() + user = pwd.getpwuid(os.geteuid()).pw_name # os.getlogin() + + ip = Utils.get_local_ipv4_address() + ipv6 = Utils.get_local_ipv6_address() + + space = os.statvfs(self._sh_dir) + freespace = space.f_frsize * space.f_bavail / 1024 / 1024 + + # return host uptime + uptime = time.mktime(datetime.datetime.now().timetuple()) - psutil.boot_time() + days = uptime // (24 * 3600) + uptime = uptime % (24 * 3600) + hours = uptime // 3600 + uptime %= 3600 + minutes = uptime // 60 + uptime %= 60 + seconds = uptime + uptime = self.age_to_string(days, hours, minutes, seconds) + + # return SmarthomeNG runtime + rt = str(self._sh.runtime()) + daytest = rt.split(' ') + if len(daytest) == 3: + days = int(daytest[0]) + hours, minutes, seconds = [float(val) for val in str(daytest[2]).split(':')] + else: + days = 0 + hours, minutes, seconds = [float(val) for val in str(daytest[0]).split(':')] + sh_uptime = self.age_to_string(days, hours, minutes, seconds) + + pyversion = "{0}.{1}.{2} {3}".format(sys.version_info[0], sys.version_info[1], sys.version_info[2], + sys.version_info[3]) + + #python_packages = self.getpackages() + #req_dict = self.get_requirements_info() + + response = {} + response['now'] = now + response['system'] = system + response['sh_vers'] = shngversion.get_shng_version() + response['sh_desc'] = shngversion.get_shng_description() + response['plg_vers'] = shngversion.get_plugins_version() + response['plg_desc'] = shngversion.get_plugins_description() + response['sh_dir'] = self._sh_dir + response['vers'] = vers + response['node'] = node + response['arch'] = arch + response['user'] = user + response['freespace'] = freespace + response['uptime'] = uptime + response['sh_uptime'] = sh_uptime + response['pyversion'] = pyversion + response['ip'] = ip + response['ipv6'] = ipv6 + + return json.dumps(response) + + # def get_process_info(self, command): # """ # returns output from executing a given command via the shell. From 317d45d59f49a199bdcbf88e0abd27ba61777c56 Mon Sep 17 00:00:00 2001 From: msinn Date: Fri, 27 Jul 2018 16:28:16 +0200 Subject: [PATCH 075/705] wunderground: Added item-struct wug_weather (experimental) --- wunderground/plugin.yaml | 58 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/wunderground/plugin.yaml b/wunderground/plugin.yaml index 77c09502f..3d22d93a9 100644 --- a/wunderground/plugin.yaml +++ b/wunderground/plugin.yaml @@ -99,3 +99,61 @@ item_attributes: description: de: 'Veraltet. Bitte stattdessen wug_matchstring verwenden.' en: 'Deprecated. Use wug_matchstring instead.' + +structs: + wug_wetter: + ort: + type: str + wug_matchstring: current_observation/display_location/city + log_change: q21-items + + ort_wetterstation: + type: str + wug_matchstring: current_observation/observation_location/city + log_change: q21-items + value: unbekannt + + lokale_zeit: + type: str + wug_matchstring: current_observation/local_time_rfc822 + log_change: q21-items + + beobachtungszeitpunkt: + type: str + wug_matchstring: current_observation/observation_time_rfc822 + log_change: q21-items + + beobachtungszeitpunkt_datetime: + type: num + wug_matchstring: current_observation/observation_epoch + log_change: q21-items + + wetter: + type: str + wug_matchstring: current_observation/weather + log_change: q21-items + + icon: + type: str + wug_matchstring: current_observation/icon + log_change: q21-items + + temperatur: + type: num + value: -9999 + wug_matchstring: current_observation/temp_c + log_change: q21-items + + temperatur_gefuehlt: + type: num + value: -9999 + wug_matchstring: current_observation/feelslike_c + log_change: q21-items + + rel_luftfeuchtigkeit: + type: num + value: -9999 + wug_matchstring: current_observation/relative_humidity + wug_datatype: percent + log_change: q21-items + From 660b79cffa1dff697d8a68ecfd519ccb66415a33 Mon Sep 17 00:00:00 2001 From: aschwith Date: Fri, 27 Jul 2018 17:40:54 +0200 Subject: [PATCH 076/705] Enocean: Webif - added feedback on successful teach-in --- enocean/__init__.py | 34 +++++++++---- enocean/locale.yaml | 8 +++ enocean/webif/templates/index.html | 80 ++++++++++++++++++++---------- 3 files changed, 88 insertions(+), 34 deletions(-) diff --git a/enocean/__init__.py b/enocean/__init__.py index 495638718..5d07e016d 100644 --- a/enocean/__init__.py +++ b/enocean/__init__.py @@ -520,7 +520,7 @@ def update_item(self, item, caller=None, source=None, dest=None): if caller != 'EnOcean': self.logger.debug('enocean: item << {} >> updated externally.'.format(item)) if self._block_ext_out_msg: - self.logger.debug('enocean: sending manually blocked by user. Aborting') + self.logger.warning('enocean: sending manually blocked by user. Aborting') return None if 'enocean_tx_eep' in item.conf: if isinstance(item.conf['enocean_tx_eep'], str): @@ -575,7 +575,16 @@ def toggle_block_external_out_messages(self): else: self.logger.info("enocean: Blocking of external out messages deactivated") self._block_ext_out_msg = False - + + def toggle_UTE_mode(self,id_offset=0): + self.logger.debug("enocean: toggle UTE mode") + if self.UTE_listen == True: + self.logger.info("enocean: UTE mode deactivated") + self.UTE_listen = False + elif (id_offset is not None) and not (id_offset == 0): + self.start_UTE_learnmode(id_offset) + self.logger.info("enocean: UTE mode activated for ID offset") + def send_bit(self): self.logger.debug("enocean: call function << send_bit >>") self.logger.info("enocean: trigger Built-In Self Test telegram") @@ -657,7 +666,7 @@ def send_learn_protocol(self, id_offset=0, device=10): # check offset range between 0 and 127 if (id_offset < 0) or (id_offset > 127): self.logger.error('enocean: ID offset with value = {} out of range (0-127). Aborting.'.format(id_offset)) - return None + return False # device range 10 - 19 --> Learn protocol for switch actuators elif (device == 10): # Prepare Data for Eltako switch FSR61, Eltako FSVA-230V @@ -688,17 +697,17 @@ def send_learn_protocol(self, id_offset=0, device=10): self.logger.info('enocean: sending learn telegram for actuator with [Device], [ID-Offset], [RORG], [payload] / [{}], [{:#04x}], [{:#04x}], [{}]'.format(device, id_offset, rorg, ', '.join('{:#04x}'.format(x) for x in payload))) else: self.logger.error('enocean: sending learn telegram with invalid device! Device {} actually not defined!'.format(device)) - return None + return False # Send radio package self._send_radio_packet(id_offset, rorg, payload) - return None + return True def start_UTE_learnmode(self, id_offset=0): self.logger.debug("enocean: call function << start_UTE_learnmode >>") self.UTE_listen = True self.learn_id = id_offset - self.logger.info("enocean: Listeining for UTE package ('D4')") + self.logger.info("enocean: Listening for UTE package ('D4')") def enter_learn_mode(self, onoff=1): @@ -817,18 +826,25 @@ def index(self, reload=None, action=None, item_id=None, item_path=None, device_i :return: contents of the template after beeing rendered """ + learn_triggered = False + if action is not None: if action == "toggle_tx_blocking": self.plugin.toggle_block_external_out_messages() - elif action == "send_learn" and device_id is not None and device_offset is not None: + elif action == "toggle_UTE": + self.plugin.toggle_UTE_mode(device_offset) + self.logger.warning("UTE mode triggered via webinterface (Offset:{0})".format(device_offset)) + elif action == "send_learn" and (device_id is not None) and not (device_id=="") and (device_offset is not None) and not(device_offset==""): self.logger.warning("Learn telegram triggered via webinterface (ID:{0} Offset:{1})".format(device_id,device_offset)) - self.plugin.send_learn_protocol(int(device_offset), int(device_id)) + ret = self.plugin.send_learn_protocol(int(device_offset), int(device_id)) + if ret == True: + learn_triggered = True else: self.logger.error("Unknown comman received via webinterface") tmpl = self.tplenv.get_template('index.html') return tmpl.render(p=self.plugin, items=sorted(self.items.return_items(), key=lambda k: str.lower(k['_path']), reverse=False), - tabcount=1, item_id=item_id) + tabcount=1, item_id=item_id, learn_triggered=learn_triggered, action='') diff --git a/enocean/locale.yaml b/enocean/locale.yaml index d938f4166..44b207d67 100644 --- a/enocean/locale.yaml +++ b/enocean/locale.yaml @@ -8,6 +8,14 @@ plugin_translations: de: 'Senden' en: 'Sending' fr: 'Emettre' + 'Lerntelegramm erfolgreich gesendet.': + de: 'Lerntelegramm erfolgreich gesendet.' + en: 'Teach-in telegram sent successfully.' + fr: 'Message envoyé avec succes.' + 'Lerntelegramm': + de: 'Lerntelegramm' + en: 'Teach-in telegram' + fr: 'Message à programmer' 'UTE Listen': de: 'UTE Listen' en: 'UTE Listen' diff --git a/enocean/webif/templates/index.html b/enocean/webif/templates/index.html index 8d4334ede..039cf6981 100644 --- a/enocean/webif/templates/index.html +++ b/enocean/webif/templates/index.html @@ -66,39 +66,69 @@ {% endblock bodytab1 %} {% set tab2title = " " ~ _('Neu hinzufügen') ~ " " %} - {% block bodytab2 %} + +{% if learn_triggered %} + +{% endif %} + +
-
+
{{ _('Unbekannte Sensor ID') }}:
-
+
-
- {{ _('Enocean Geräte anlernen') }}: +
+
+ {{ _('Enocean Geräte anlernen') }}: +
+
+
+
+ {{ _('Gerätetyp') }}: +
+ +
+ +
- {{ _('Gerätetyp') }}: -
-
- +
{% endif %} + + + +
{{ p.unknown_sender_id }}{{ p.unknown_sender_id }} +
+
+ {{ _('ID Offset') }}: + + + + {% endblock bodytab2 %} diff --git a/eta_pu/README.md b/eta_pu/README.md index d62f6b607..ad1ce2095 100644 --- a/eta_pu/README.md +++ b/eta_pu/README.md @@ -4,7 +4,7 @@ ## Supported Hardware -* ETA Pellet Unit PU (http://www.eta.at) with remote access enabled (there are 3 modes available: none, readonly, read/write) +* ETA Pellet Unit PU (http://www.eta.co.at) with remote access enabled (there are 3 modes available: none, readonly, read/write) ## Configuration From e7df52d197a33f011552e11319de7e8728a1e9da Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 27 Jul 2018 13:00:26 +0200 Subject: [PATCH 070/705] Database: some more information in detail view (current value) and a filter for the item type... added information about database: init to README --- database/README.md | 5 +++-- database/__init__.py | 7 +++++-- database/webif/templates/item_details.html | 22 +++++++++++----------- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/database/README.md b/database/README.md index c159141d2..bfc7d2b75 100644 --- a/database/README.md +++ b/database/README.md @@ -83,13 +83,14 @@ The plugin supports the types `str`, `num` and `bool` which can be logged into the database. #### database -This attribute enables the database logging when set (just use value `yes`). +This attribute enables the database logging when set (just use value `yes`). If value `init` is used, an item will +be initalized from the database after SmartHomeNG is restarted. ```yaml some: item: type: num - database: 'yes' + database: 'yes' # or 'init' # database_acl: rw ``` diff --git a/database/__init__.py b/database/__init__.py index 121caf829..65bb2934a 100644 --- a/database/__init__.py +++ b/database/__init__.py @@ -196,7 +196,7 @@ def cleanup(self): def id(self, item, create=True, cur=None): id = self.readItem(str(item.id()), cur=cur) - if id == None and create == True: + if id is None and create == True: id = [self.insertItem(item.id(), cur)] return None if id == None else int(id[COL_ITEM_ID]) @@ -582,6 +582,7 @@ def _execute(self, query, params, cur=None): self._query(self._db.execute, query, params, cur) def _query(self, func, query, params, cur=None): + self.logger.debug(query) if not self._initialize(): return None if cur is None: @@ -720,6 +721,7 @@ def index(self, reload=None, action=None, item_id=None, item_path=None, day=None :return: contents of the template after beeing rendered """ + item = self.plugin.get_sh().return_item(item_path) delete_triggered = False if action is not None: if action == "delete_log" and item_id is not None: @@ -739,6 +741,7 @@ def index(self, reload=None, action=None, item_id=None, item_path=None, day=None "%m/%d/%Y").timetuple())*1000 time_end = time_start + 24 * 60 * 60 * 1000 tmpl = self.tplenv.get_template('item_details.html') + rows = self.plugin.readLogs(item_id, time_start=time_start, time_end=time_end) log_array = [] for row in rows: @@ -755,7 +758,7 @@ def index(self, reload=None, action=None, item_id=None, item_path=None, day=None reversed_arr = log_array[::-1] return tmpl.render(p=self.plugin, items=sorted(self.items.return_items(), key=lambda k: str.lower(k['_path']), - reverse=False), + reverse=False), item = item, tabcount=1, action=action, item_id=item_id, item_path=item_path, language=self.plugin._sh.get_defaultlanguage(), now=self.plugin.shtime.now(), log_array=reversed_arr, day=day, month=month, year=year, diff --git a/database/webif/templates/item_details.html b/database/webif/templates/item_details.html index 34b75e23e..aedadd379 100644 --- a/database/webif/templates/item_details.html +++ b/database/webif/templates/item_details.html @@ -33,8 +33,8 @@ {% endif %}
- {{ _('Die folgenden Einträge entstammen der log Tabelle mit historischen Daten für das Item') }} {{ item_path }} {{ _('am') }} {% if day and month and year %}{% if language == 'en' %}{{ month }}/{{ day }}/{{ year }}{% else %}{{ day }}.{{ month }}.{{ year }}{% endif %}{% else %}{% if language == 'en' %}{{ now.strftime('%-m/%-d/%Y') }}{% else %}{{ now.strftime('%-d.%-m.%Y') }}{% endif %}{% endif %} ({{_('Datenbank-ID') }}: {{ item_id }}, {{ log_array | length }} {{_('Datensätze')}}): -
+ {{ _('Die folgenden Einträge entstammen der log Tabelle mit historischen Daten für das Item') }} {{ item_path }} {{ _('am') }} {% if day and month and year %}{% if language == 'en' %}{{ month }}/{{ day }}/{{ year }}{% else %}{{ day }}.{{ month }}.{{ year }}{% endif %}{% else %}{% if language == 'en' %}{{ now.strftime('%-m/%-d/%Y') }}{% else %}{{ now.strftime('%-d.%-m.%Y') }}{% endif %}{% endif %} +
({{_('Datenbank-ID') }}: {{ item_id }}, {{ _('Typ') }}: {{ item.type() }}, {{ log_array | length }} {{_('Datensätze')}}, {{_('Aktueller Wert')}}: {{ item() }} )
@@ -46,9 +46,9 @@
{{ _('Zeit') }} {{ _('Dauer') }} {{ _('Geändert') }}VAL_NUMVAL_BOOLVAL_STRVAL_NUMVAL_BOOLVAL_STR{{ _('Aktionen') }}
{{ dataset[0].strftime('%d.%m.%Y %H:%M:%S') }} {{ dataset[2] }} {{ dataset[6].strftime('%d.%m.%Y %H:%M:%S') }} {{ dataset[4] }}{{ dataset[5] }}{{ dataset[3] }}{{ dataset[4] }}{{ dataset[5] }}{{ dataset[3] }}
- - ------- -
{{ p.unknown_sender_id }} -
-
- {{ _('ID Offset') }}: - - +
+ {{ _('ID Offset') }}: +
+
+ +
+ +
+
+ +
+
+ +
+
{% endblock bodytab2 %} From dd6f505cbe39df2a666328a4e979e93dd539b219 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 28 Jul 2018 00:12:21 +0200 Subject: [PATCH 077/705] fixed ugly bug that deleted wrong commands from queue --- avdevice/__init__.py | 89 ++++++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 45 deletions(-) diff --git a/avdevice/__init__.py b/avdevice/__init__.py index 95519131b..c68c99c5a 100755 --- a/avdevice/__init__.py +++ b/avdevice/__init__.py @@ -1097,11 +1097,6 @@ def _checkdependency(self, dep_function, dep_type): "Checking Dependency {}: Adding query because it's init dependency is set to true.".format( self._name)) return False - elif func.lower() == 'init' and dep_type == 'statusupdate' and len(totest[zone][dep_function]) == 1: - self.logger.log(VERBOSE2, - "Checking Dependency {}: Adding query because updating status and no other dependencies set.".format( - self._name)) - return False elif dep_type == 'initupdate' and self._statusquery is False: self.logger.log(VERBOSE2, "Checking Dependency {}: Not adding query because no init dependency defined.".format( @@ -1560,8 +1555,8 @@ def _foundappend(_foundexpected, _data): try: if _del_data.startswith(tuple(found)): self.logger.log(VERBOSE1, - "Parsing Input {}: Expected response edited {}. Data starts with one of the entries." - " Resetting resend counter".format(self._name, found)) + "Parsing Input {}: Expected response edited {}. Data {} starts with one of the entries." + " Resetting resend counter".format(self._name, found, _del_data)) _entry, _value, _del_valuetype = self._write_itemsdict(_del_data, found) self._sendingcommand = 'done' self._resend_counter = 0 @@ -1571,44 +1566,48 @@ def _foundappend(_foundexpected, _data): self.logger.log(VERBOSE1, "Parsing Input {}: No response expected. Resend Counter reset.".format( self._name)) - - # only add send command to list again if response doesn't fit to corresponding command - expectedindices = _duplicateindex(_del_expectedresponse, expected) - self.logger.log(VERBOSE2, "Parsing Input {}: expectedindices {}.".format( - self._name, expectedindices)) - for expectedindex in expectedindices: - self.logger.log(VERBOSE2, - "Parsing Input {}: expected {}, deletecommands {}.".format( - self._name, self._send_commands[expectedindex], - del_commands)) - if self._send_commands[expectedindex] not in del_commands: - parse_expectedtype = \ - self._send_commands[expectedindex].split(';')[0].split('|')[0].split(',') \ - if self._send_commands[expectedindex].split(',', 2)[2].find('|') >= 0 \ - else self._send_commands[expectedindex].split(';')[0].split(',') - try: - int(parse_expectedtype[-1]) - length = len(parse_expectedtype) - 1 - except Exception: - length = len(parse_expectedtype) - try: - parse_expectedtype[3:length] = [','.join(parse_expectedtype[3:length])] - testvalue = parse_expectedtype[3] - except Exception: - testvalue = '' - if not _del_valuetype == testvalue or not found or _del_data == 'ERROR': - self.logger.log(VERBOSE2, - "Parsing Input {}: Test Value {} of {} is not same as Valuetype:" - "{} or nothing found {}. Keeping in Sendcommands.".format( - self._name, testvalue, self._send_commands[expectedindex], - _del_valuetype, found)) - elif not _del_data == 'ERROR': - del_commands.append(self._send_commands[expectedindex]) - self.logger.log(VERBOSE1, - "Parsing Input {}: Test Value {} of {} is same as Valuetype: {}. Removing from Sendcommands.".format( - self._name, testvalue, - self._send_commands[expectedindex], - _del_valuetype)) + if _del_data.startswith(tuple(found)): + # only add send command to list again if response doesn't fit to corresponding command + expectedindices = _duplicateindex(_del_expectedresponse, expected) + self.logger.log(VERBOSE2, "Parsing Input {}: expectedindices {}.".format( + self._name, expectedindices)) + for expectedindex in expectedindices: + self.logger.log(VERBOSE2, + "Parsing Input {}: expected {}, deletecommands {}.".format( + self._name, self._send_commands[expectedindex], + del_commands)) + if self._send_commands[expectedindex] not in del_commands: + parse_expectedtype = \ + self._send_commands[expectedindex].split(';')[0].split('|')[0].split(',') \ + if self._send_commands[expectedindex].split(',', 2)[2].find('|') >= 0 \ + else self._send_commands[expectedindex].split(';')[0].split(',') + try: + int(parse_expectedtype[-1]) + length = len(parse_expectedtype) - 1 + except Exception: + length = len(parse_expectedtype) + try: + parse_expectedtype[3:length] = [','.join(parse_expectedtype[3:length])] + testvalue = parse_expectedtype[3] + except Exception: + testvalue = '' + if not _del_valuetype == testvalue or not found or _del_data == 'ERROR': + self.logger.log(VERBOSE2, + "Parsing Input {}: Test Value {} of {} is not same as Valuetype:" + "{} or nothing found {}. Keeping in Sendcommands.".format( + self._name, testvalue, self._send_commands[expectedindex], + _del_valuetype, found)) + elif not _del_data == 'ERROR': + del_commands.append(self._send_commands[expectedindex]) + self.logger.log(VERBOSE1, + "Parsing Input {}: Test Value {} of {} is same as Valuetype: {}. Removing from Sendcommands.".format( + self._name, testvalue, + self._send_commands[expectedindex], + _del_valuetype)) + else: + self.logger.log(VERBOSE1, + "Parsing Input {}: Expected response edited {}. Data {} is different, not deleting" + " the command from sendcommands.".format(self._name, found, _del_data)) except Exception as _err: self.logger.log(VERBOSE1, "Parsing Input {}: Deleting commands problem: {}".format(self._name, _err)) From 64e4003fe7485748cfc7a8530c6f6f4606520d25 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Tue, 31 Jul 2018 06:15:00 +0200 Subject: [PATCH 078/705] Darksky: added check for key --- darksky/__init__.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/darksky/__init__.py b/darksky/__init__.py index 87dfe96c0..28633c157 100644 --- a/darksky/__init__.py +++ b/darksky/__init__.py @@ -95,16 +95,17 @@ def _update(self): wrk = wrk['alerts'] else: alerts_string = '' - for alert in wrk['alerts']: - start_time = datetime.datetime.fromtimestamp( - int(alert['time']) - ).strftime('%d.%m.%Y %H:%M') - expire_time = datetime.datetime.fromtimestamp( - int(alert['expires']) - ).strftime('%d.%m.%Y %H:%M') - alerts_string_wrk = "

"+alert['title']+" ("+start_time+" - "+expire_time+")

" - alerts_string_wrk = alerts_string_wrk + ""+alert['description']+"

" - alerts_string = alerts_string + alerts_string_wrk + if 'alerts' in wrk: + for alert in wrk['alerts']: + start_time = datetime.datetime.fromtimestamp( + int(alert['time']) + ).strftime('%d.%m.%Y %H:%M') + expire_time = datetime.datetime.fromtimestamp( + int(alert['expires']) + ).strftime('%d.%m.%Y %H:%M') + alerts_string_wrk = "

"+alert['title']+" ("+start_time+" - "+expire_time+")

" + alerts_string_wrk = alerts_string_wrk + ""+alert['description']+"

" + alerts_string = alerts_string + alerts_string_wrk wrk = alerts_string else: wrk = [] From 5c50475fc36807c9cb094eea34835168109a4569 Mon Sep 17 00:00:00 2001 From: aschwith Date: Wed, 1 Aug 2018 10:06:43 +0200 Subject: [PATCH 079/705] Update README.md fixed docu for child items that got corrupted during last merge --- avm/README.md | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/avm/README.md b/avm/README.md index d92645fe2..0b0756147 100644 --- a/avm/README.md +++ b/avm/README.md @@ -445,19 +445,19 @@ avm: # these items need to be child items from network_device ip: type: str - avm_data_type: device_ip + avm_data_type@fritzbox_7490: device_ip visu_acl: ro # these items need to be child items from network_device connection_type: type: str - avm_data_type: device_connection_type + avm_data_type@fritzbox_7490: device_connection_type visu_acl: ro # these items need to be child items from network_device hostname: type: str - avm_data_type: device_hostname + avm_data_type@fritzbox_7490: device_hostname visu_acl: ro fritzbox_7490: @@ -471,19 +471,19 @@ avm: # these items need to be child items from network_device ip: type: str - avm_data_type: device_ip + avm_data_type@fritzbox_7490: device_ip visu_acl: ro # these items need to be child items from network_device connection_type: type: str - avm_data_type: device_connection_type + avm_data_type@fritzbox_7490: device_connection_type visu_acl: ro # these items need to be child items from network_device hostname: type: str - avm_data_type: device_hostname + avm_data_type@fritzbox_7490: device_hostname visu_acl: ro hauptrechner: @@ -495,19 +495,19 @@ avm: # these items need to be child items from network_device ip: type: str - avm_data_type: device_ip + avm_data_type@fritzbox_7490: device_ip visu_acl: ro # these items need to be child items from network_device connection_type: type: str - avm_data_type: device_connection_type + avm_data_type@fritzbox_7490: device_connection_type visu_acl: ro # these items need to be child items from network_device hostname: type: str - avm_data_type: device_hostname + avm_data_type@fritzbox_7490: device_hostname visu_acl: ro GalaxyS5: @@ -520,19 +520,19 @@ avm: # these items need to be child items from network_device ip: type: str - avm_data_type: device_ip + avm_data_type@fritzbox_7490: device_ip visu_acl: ro # these items need to be child items from network_device connection_type: type: str - avm_data_type: device_connection_type + avm_data_type@fritzbox_7490: device_connection_type visu_acl: ro # these items need to be child items from network_device hostname: type: str - avm_data_type: device_hostname + avm_data_type@fritzbox_7490: device_hostname visu_acl: ro GalaxyTabS2: @@ -544,19 +544,19 @@ avm: # these items need to be child items from network_device ip: type: str - avm_data_type: device_ip + avm_data_type@fritzbox_7490: device_ip visu_acl: ro # these items need to be child items from network_device connection_type: type: str - avm_data_type: device_connection_type + avm_data_type@fritzbox_7490: device_connection_type visu_acl: ro # these items need to be child items from network_device hostname: type: str - avm_data_type: device_hostname + avm_data_type@fritzbox_7490: device_hostname visu_acl: ro iPhone: @@ -569,19 +569,19 @@ avm: # these items need to be child items from network_device ip: type: str - avm_data_type: device_ip + avm_data_type@fritzbox_7490: device_ip visu_acl: ro # these items need to be child items from network_device connection_type: type: str - avm_data_type: device_connection_type + avm_data_type@fritzbox_7490: device_connection_type visu_acl: ro # these items need to be child items from network_device hostname: type: str - avm_data_type: device_hostname + avm_data_type@fritzbox_7490: device_hostname visu_acl: ro dect: @@ -594,13 +594,13 @@ avm: # these items need to be child items from aha_device energy: - avm_data_type: energy + avm_data_type@fritzbox_7490: energy type: num visu_acl: ro # these items need to be child items from aha_device power: - avm_data_type: power + avm_data_type@fritzbox_7490: power type: num sqlite: 'yes' enforce_updates: 'true' @@ -609,7 +609,7 @@ avm: # these items need to be child items from aha_device temperature: - avm_data_type: temperature + avm_data_type@fritzbox_7490: temperature type: num visu_acl: ro @@ -621,13 +621,13 @@ avm: # these items need to be child items from aha_device energy: - avm_data_type: energy + avm_data_type@fritzbox_7490: energy type: num visu_acl: ro # these items need to be child items from aha_device power: - avm_data_type: power + avm_data_type@fritzbox_7490: power type: num sqlite: 'yes' enforce_updates: 'true' @@ -636,7 +636,7 @@ avm: # these items need to be child items from aha_device temperature: - avm_data_type: temperature + avm_data_type@fritzbox_7490: temperature type: num visu_acl: ro ``` From 3169bbd6c0b2dd42e04b70901ac355e93d8a2b86 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 1 Aug 2018 11:54:55 +0200 Subject: [PATCH 080/705] Simulation: added support link --- simulation/plugin.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simulation/plugin.yaml b/simulation/plugin.yaml index f4d12d638..ce559b78b 100755 --- a/simulation/plugin.yaml +++ b/simulation/plugin.yaml @@ -9,7 +9,7 @@ plugin: tester: psilo909, Sandman60, cmalo # keywords: iot xyz # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page - + support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/1121182-simulation-plugin' version: 1.5.0.6 # Plugin version sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) From 446a6ac698c1bac75c7a23c593d674b2c65df839 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Thu, 2 Aug 2018 01:39:53 +0200 Subject: [PATCH 081/705] optimized querycommand creation and re-ordering commands in queue --- avdevice/AVDeviceInit.py | 32 ++++++++++++++++++++------------ avdevice/__init__.py | 14 +++++++++++--- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/avdevice/AVDeviceInit.py b/avdevice/AVDeviceInit.py index 5d31a4b0a..a7b92f0ec 100755 --- a/avdevice/AVDeviceInit.py +++ b/avdevice/AVDeviceInit.py @@ -93,10 +93,15 @@ def update_dependencies(self, dependencies): for resp in responselist: resp_split = re.sub('[*]', '', resp.split(',')[0]) cond1 = resp_split in responses + cond2_1 = set(resp.split(',')[1:-1]) + cond2_2 = set(already.split('|')[0].split(',')[3:-1]) + cond2 = cond2_1 == cond2_2 self.logger.log(VERBOSE2, "Updating Dependencies {}: Querycommand {} for zone {}" - " already in list. Testing -{}- against the responses {}.".format( - self._name, querycommand, zone, resp_split, responses)) - if resp not in alreadylist and cond1: + " already in list. Testing -{}- against the responses {}." + " Testing type {} against {}".format( + self._name, querycommand, zone, resp_split, + responses, cond2_1, cond2_2)) + if resp not in alreadylist and cond1 and cond2: newquery = already + '|' + resp dependencies['Slave_query'][dependzone][newquery] = \ dependencies['Slave_query'][dependzone].get(already) @@ -107,13 +112,13 @@ def update_dependencies(self, dependencies): self._name, resp, alreadylist)) if commandlist not in alreadydone: alreadydone.append(commandlist) - elif cond1: + elif cond1 and cond2: if commandlist not in alreadydone: alreadydone.append(commandlist) self.logger.log(VERBOSE2, "Updating Dependencies {}: Skipping {}.".format( self._name, commandlist)) except Exception as err: - pass + self.logger.error(err) if commandlist in alreadydone: self.logger.log(VERBOSE2, "Updating Dependencies {}: Commandlist {} is alreadydone: {}, skipping.".format( self._name, commandlist, alreadydone)) @@ -369,15 +374,18 @@ def create_querycommands(self): if already.split(',')[0] == querycommand: alreadylist = ','.join(already.split(',')[2:]).split('|') responses = [re.sub('[*]', '', x.split(',')[0]) for x in alreadylist] - - for resp in responselist: resp_split = re.sub('[*]', '', resp.split(',')[0]) cond1 = resp_split in responses - self.logger.log(VERBOSE2, "Initializing {}: Querycommand {} for zone {} already in list. " - "Testing -{}- against the responses {}.".format( - self._name, querycommand, zone, resp_split, responses)) - if resp not in alreadylist and cond1: + cond2_1 = set(resp.split(',')[1:-1]) + cond2_2 = set(already.split('|')[0].split(',')[3:-1]) + cond2 = cond2_1 == cond2_2 + self.logger.log(VERBOSE2, "Updating Dependencies {}: Querycommand {} for zone {}" + " already in list. Testing -{}- against the responses {}." + " Testing type {} against {}".format( + self._name, querycommand, zone, resp_split, + responses, cond2_1, cond2_2)) + if resp not in alreadylist and cond1 and cond2: self.logger.log(VERBOSE2, "Initializing {}: Adding {} to {}.".format( self._name, resp, alreadylist)) self._query_commands[x] = already + '|' + resp @@ -385,7 +393,7 @@ def create_querycommands(self): self._query_zonecommands['zone{}'.format(zone)][idx] = already + '|' + resp if commandlist not in alreadydone: alreadydone.append(commandlist) - elif cond1: + elif cond1 and cond2: if commandlist not in alreadydone: alreadydone.append(commandlist) self.logger.log(VERBOSE2, "Initializing {}: Skipping {}.".format( diff --git a/avdevice/__init__.py b/avdevice/__init__.py index c68c99c5a..719a0b8d1 100755 --- a/avdevice/__init__.py +++ b/avdevice/__init__.py @@ -1925,16 +1925,24 @@ def _duplicateindex(seq, seqitem): reorderlist = [] index = 0 for command in self._send_commands: - command = command.split(';')[0] - if command in self._query_commands: + command_split = command.split(';')[0] + try: + commanditem = command.split(';')[1] + except Exception: + commanditem = None + if command_split in self._query_commands: reorderlist.append(command) - elif command in self._power_commands: + elif command_split in self._power_commands: + if commanditem: + command = '{};{}'.format(command_split, item) self.logger.log(VERBOSE1, "Parsing Input {}: Ordering power command {} to first position.".format( self._name, command)) reorderlist.insert(0, command) index += 1 else: + if commanditem: + command = '{};{}'.format(command, item) reorderlist.insert(index, command) self.logger.log(VERBOSE1, "Parsing Input {}: Adding command {} to position {}.".format( From 21f2e74e0f106a4a2531f2020986eb0bcc3c2fc8 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Thu, 2 Aug 2018 01:42:38 +0200 Subject: [PATCH 082/705] optimized querycommand creation and re-ordering commands in queue --- avdevice/AVDeviceInit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avdevice/AVDeviceInit.py b/avdevice/AVDeviceInit.py index a7b92f0ec..ba581d068 100755 --- a/avdevice/AVDeviceInit.py +++ b/avdevice/AVDeviceInit.py @@ -118,7 +118,7 @@ def update_dependencies(self, dependencies): self.logger.log(VERBOSE2, "Updating Dependencies {}: Skipping {}.".format( self._name, commandlist)) except Exception as err: - self.logger.error(err) + pass if commandlist in alreadydone: self.logger.log(VERBOSE2, "Updating Dependencies {}: Commandlist {} is alreadydone: {}, skipping.".format( self._name, commandlist, alreadydone)) From 12f9227837ea1cff003aa153ab302bf990a3769f Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Thu, 2 Aug 2018 08:34:49 +0200 Subject: [PATCH 083/705] optimized querycommand creation and re-ordering commands in queue --- avdevice/__init__.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/avdevice/__init__.py b/avdevice/__init__.py index 719a0b8d1..1f71cf3fc 100755 --- a/avdevice/__init__.py +++ b/avdevice/__init__.py @@ -1930,19 +1930,20 @@ def _duplicateindex(seq, seqitem): commanditem = command.split(';')[1] except Exception: commanditem = None + if commanditem: + command = '{};{}'.format(command_split, commanditem) + self.logger.log(VERBOSE1, + "Parsing Input {}: Adding command commandsplit {}, commanditem {}. Command: {}".format( + self._name, command_split, commanditem, command)) if command_split in self._query_commands: reorderlist.append(command) elif command_split in self._power_commands: - if commanditem: - command = '{};{}'.format(command_split, item) self.logger.log(VERBOSE1, - "Parsing Input {}: Ordering power command {} to first position.".format( + "Parsing Input {}: Adding command and ordering power command {} to first position.".format( self._name, command)) reorderlist.insert(0, command) index += 1 else: - if commanditem: - command = '{};{}'.format(command, item) reorderlist.insert(index, command) self.logger.log(VERBOSE1, "Parsing Input {}: Adding command {} to position {}.".format( From 243fb87adf3738b19bb04e9cbc7e40fb8245f419 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 2 Aug 2018 17:07:34 +0200 Subject: [PATCH 084/705] AVM: added curl to readme --- avm/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/avm/__init__.py b/avm/__init__.py index 055531f34..b800bf0bc 100644 --- a/avm/__init__.py +++ b/avm/__init__.py @@ -1513,6 +1513,8 @@ def _update_fritz_device_info(self, item): Updates FritzDevice specific information Uses: http://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/deviceinfoSCPD.pdf + CURL for testing: + curl --anyauth -u user:'password' 'https://192.168.178.1:49443/upnp/control/deviceinfo' -H 'Content-Type: text/xml; charset="utf-8"' -H 'SoapAction: urn:dslforum-org:service:DeviceInfo:1#GetInfo' -d ' ' -s -k :param item: Item to be updated (Supported item avm_data_types: uptime, software_version, hardware_version,serial_number, description) """ From b63fe9975428b57721f3e6fe35077bab10571079 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Mon, 6 Aug 2018 18:20:46 +0200 Subject: [PATCH 085/705] Fixed problem when caller contains a space or special characters --- influxdata/__init__.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/influxdata/__init__.py b/influxdata/__init__.py index 1d5beec84..8be45ef31 100644 --- a/influxdata/__init__.py +++ b/influxdata/__init__.py @@ -21,6 +21,7 @@ import logging import socket +import re from lib.model.smartplugin import SmartPlugin @@ -37,6 +38,11 @@ def __init__(self, smarthome, influx_host='localhost', influx_port=8089, influx_ self.influx_keyword = influx_keyword self._items = [] + def cleanstring(self, s): + s = re.sub(r"[^\w\s]", '', s) + s = re.sub(r"\s+", '-', s) + return s + def run(self): self.alive = True @@ -66,7 +72,7 @@ def parse_item(self, item): return self.update_item def update_item(self, item, caller=None, source=None, dest=None): - message = "{},caller={},source={},dest={} value={}".format(item.id(), caller, source, dest, float(item())) + message = "{},caller={},source={},dest={} value={}".format(item.id(), self.cleanstring(caller), source, dest, float(item())) self.udp(message) return None From d841c2d83f84d5ca4c1945e01d826246bbb78ba5 Mon Sep 17 00:00:00 2001 From: aschwith Date: Wed, 8 Aug 2018 20:32:06 +0200 Subject: [PATCH 086/705] Sonos: made audio snippet duration offset configurable --- sonos/README.md | 2 ++ sonos/__init__.py | 7 ++++--- sonos/plugin.yaml | 9 ++++++++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/sonos/README.md b/sonos/README.md index 7ea887e75..f653cb6da 100644 --- a/sonos/README.md +++ b/sonos/README.md @@ -80,6 +80,7 @@ Sonos: # ip address here. # webservice_port: 23500 # optional, default: 23500 # discover_cycle: 120 # optional, default: 120 (in seconds) + # snippet_duration_offset: 0.4 # optional, default: 0.0 (in seconds) # speaker_ips: # optional. You can set static IP addresses for your Sonos speaker. This # - 192.168.1.10 # will disable auto-discovery. This is useful if you're using a # - 192.168.1.77 # containerized environment with restricted network access. @@ -778,6 +779,7 @@ option for the Sonos plugin in your ```plugin.yaml```. In addition to that, you ```local_webservice_path``` option. If you want to separate your audio snippets from the automatic generated TTS audio files, you have to set the ```local_webservice_path_snippet``` option. A very simple Webservice will be started to serve Sonos requests. +In order to adapt the automatically calculated duration of audio snippets to different hardware, a fixed duration offset (in seconds) can be configured via the snippet_duration_offset option. ### Configure Speaker IPs manually diff --git a/sonos/__init__.py b/sonos/__init__.py index ee6a4b2c9..22e7e7ea8 100755 --- a/sonos/__init__.py +++ b/sonos/__init__.py @@ -2155,7 +2155,7 @@ def _play_snippet(self, file_path: str, webservice_url: str, volume: int = -1, f volumes[member] = sonos_speaker[member].volume tag = TinyTag.get(file_path) - duration = int(round(tag.duration)) + 0.4 + duration = int(round(tag.duration)) + self.__snippet_duration_offset self._logger.debug("Sonos: TTS track duration: {duration}s".format(duration=duration)) file_name = quote(os.path.split(file_path)[1]) snippet_url = "{url}/{file}".format(url=webservice_url, file=file_name) @@ -2284,10 +2284,10 @@ def load_sonos_playlist(self, name: str, start: bool = False, clear_queue: bool class Sonos(SmartPlugin): ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.4.6" + PLUGIN_VERSION = "1.4.7" def __init__(self, sh, tts=False, local_webservice_path=None, local_webservice_path_snippet=None, - discover_cycle="120", webservice_ip=None, webservice_port=23500, speaker_ips=None, **kwargs): + discover_cycle="120", webservice_ip=None, webservice_port=23500, speaker_ips=None, snippet_duration_offset=0.0, **kwargs): super().__init__(**kwargs) self._sh = sh self._logger = logging.getLogger('sonos') # get a unique logger for the plugin and provide it internally @@ -2296,6 +2296,7 @@ def __init__(self, sh, tts=False, local_webservice_path=None, local_webservice_p self._sonos_dpt3_time = 1 # default value for dpt3 volume time (time period per step in seconds) self._tts = self.to_bool(tts, default=False) self._local_webservice_path = local_webservice_path + self._snippet_duration_offset = float(snippet_duration_offset) # see documentation: if no exclusive snippet path is set, we use the global one if local_webservice_path_snippet is None: diff --git a/sonos/plugin.yaml b/sonos/plugin.yaml index 0120eae3b..2c2d5e090 100755 --- a/sonos/plugin.yaml +++ b/sonos/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: https://github.com/smarthomeNG/plugins/tree/master/sonos # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/25151-sonos-anbindung - version: 1.4.6 # Plugin version + version: 1.4.7 # Plugin version sh_minversion: 1.3 # minimum shNG version to use this plugin multi_instance: False # plugin supports multi instance classname: Sonos # class containing the plugin @@ -61,6 +61,13 @@ parameters: de: "Zeitintervall, in dem (erneut) nach (neuen) Lautsprechern im Netzwerk gesucht wird." en: "Time interval in which (again) searches are made for (new) speakers in the network." + snippet_duration_offset: + type: num + default: 0.0 + description: + de: "(optional) Verlängert die Dauer von Snippet Audio Dateien um einen festen Offset in Sekunden." + en: "(optional) Extend snippet duration by a fixed offset specified in seconds" + item_attributes: # Definition of item attributes defined by this plugin From e202847f1d37084f9e58bbb4cd6ba7fe648a428c Mon Sep 17 00:00:00 2001 From: msinn Date: Sun, 12 Aug 2018 11:53:06 +0200 Subject: [PATCH 087/705] Sample Plugins: Added example code to handle errors while importing packages --- backend/BackendItems.py | 3 +-- homematic/__init__.py | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/backend/BackendItems.py b/backend/BackendItems.py index 8e902b3fc..3097c59a1 100755 --- a/backend/BackendItems.py +++ b/backend/BackendItems.py @@ -50,8 +50,7 @@ def __init__(self): self.items = Items.get_instance() self.logger.info("BackendItems __init__ {}".format(self.items)) - # ----------------------------------------------------------------------------------- - + # ----------------------------------------------------------------------------------- # ITEMS # ----------------------------------------------------------------------------------- diff --git a/homematic/__init__.py b/homematic/__init__.py index 876d896ca..29f58f5f9 100755 --- a/homematic/__init__.py +++ b/homematic/__init__.py @@ -25,7 +25,14 @@ import logging -from pyhomematic import HMConnection + +try: + from pyhomematic import HMConnection + REQUIRED_PACKAGE_IMPORTED = True + +except: + REQUIRED_PACKAGE_IMPORTED = False + from lib.module import Modules from lib.model.smartplugin import * @@ -64,9 +71,15 @@ def __init__(self, sh, *args, **kwargs): """ self.logger = logging.getLogger(__name__) + # Exit if the required package(s) could not be imported + if not REQUIRED_PACKAGE_IMPORTED: + self.logger.error("{}: Unable to import Python package 'pyhomematic'".format(self.get_fullname())) + self._init_complete = False + return + # get the parameters for the plugin (as defined in metadata plugin.yaml): # self.param1 = self.get_parameter_value('param1') - + # Initialization code goes here self.username = self.get_parameter_value('username') self.password = self.get_parameter_value('password') From fc7dd5706e6db05713933d17716f954b07bee58f Mon Sep 17 00:00:00 2001 From: msinn Date: Sun, 12 Aug 2018 11:56:28 +0200 Subject: [PATCH 088/705] homematic: Added error handling to import pyhomematic --- homematic/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/homematic/__init__.py b/homematic/__init__.py index 29f58f5f9..c71837d9b 100755 --- a/homematic/__init__.py +++ b/homematic/__init__.py @@ -29,7 +29,6 @@ try: from pyhomematic import HMConnection REQUIRED_PACKAGE_IMPORTED = True - except: REQUIRED_PACKAGE_IMPORTED = False From 416cbf72830454dcbf4a6b8aa1eef63821b136a1 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 13 Aug 2018 06:55:29 +0200 Subject: [PATCH 089/705] Simulation: corrected info in README --- simulation/plugin.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/simulation/plugin.yaml b/simulation/plugin.yaml index ce559b78b..e32ef412a 100755 --- a/simulation/plugin.yaml +++ b/simulation/plugin.yaml @@ -5,11 +5,11 @@ plugin: description: # Alternative: description in multiple languages de: 'Aufnahme und Abspielen von Aktionsreihenfolgen.' en: 'Recording And Replay of Actions on Items.' - maintainer: ggf. cmalo (?) + maintainer: MichaelBu (?) tester: psilo909, Sandman60, cmalo # keywords: iot xyz -# documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page - support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/1121182-simulation-plugin' + documentation: https://www.smarthomeng.de/developer/plugins/simulation/README.html # url of documentation (wiki) page + support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/841097-anwesenheitssimulation-0-1' version: 1.5.0.6 # Plugin version sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) From 6fe8ac843f6aec3993a5d816c44ff46d2326681d Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 13 Aug 2018 06:55:50 +0200 Subject: [PATCH 090/705] AVM: Added error handling for requests package --- avm/__init__.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/avm/__init__.py b/avm/__init__.py index b800bf0bc..233045a5c 100644 --- a/avm/__init__.py +++ b/avm/__init__.py @@ -27,9 +27,14 @@ import time import threading from xml.dom import minidom -import requests -from requests.packages import urllib3 -from requests.auth import HTTPDigestAuth +try: + import requests + from requests.packages import urllib3 + from requests.auth import HTTPDigestAuth + REQUIRED_PACKAGE_IMPORTED = True +except: + REQUIRED_PACKAGE_IMPORTED = False + from lib.model.smartplugin import * from lib.module import Modules @@ -515,6 +520,12 @@ def __init__(self, sh, *args, **kwargs): Initalizes the plugin. The parameters describe for this method are pulled from the entry in plugin.conf. """ self.logger = logging.getLogger(__name__) + + if not REQUIRED_PACKAGE_IMPORTED: + self.logger.error("{}: Unable to import Python package 'requests'".format(self.get_fullname())) + self._init_complete = False + return + self.logger.info('Init AVM Plugin') self._session = requests.Session() From b1ca231caefd4e26cfc23bb19059eb60dcdaaf80 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 13 Aug 2018 07:01:59 +0200 Subject: [PATCH 091/705] Nokia: added error handling for nokia package --- nokia_health/__init__.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/nokia_health/__init__.py b/nokia_health/__init__.py index bc5320cfc..f3aa11795 100644 --- a/nokia_health/__init__.py +++ b/nokia_health/__init__.py @@ -22,9 +22,12 @@ # ######################################################################### -import requests from lib.model.smartplugin import * -from nokia import NokiaAuth, NokiaApi, NokiaCredentials +try: + from nokia import NokiaAuth, NokiaApi, NokiaCredentials + REQUIRED_PACKAGE_IMPORTED = True +except: + REQUIRED_PACKAGE_IMPORTED = False class NokiaHealth(SmartPlugin): @@ -37,6 +40,11 @@ class NokiaHealth(SmartPlugin): def __init__(self, smarthome, consumer_key, consumer_secret, access_token, access_token_secret, user_id, cycle=300): self.logger = logging.getLogger(__name__) + if not REQUIRED_PACKAGE_IMPORTED: + self.logger.error("{}: Unable to import Python package 'nokia'".format(self.get_fullname())) + self._init_complete = False + return + self._sh = smarthome self._consumer_key = consumer_key self._consumer_secret = consumer_secret From 77a9db67cf4d8f22c2963975c798099ddc8d9784 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 13 Aug 2018 07:03:03 +0200 Subject: [PATCH 092/705] Enigma2: added error handling for package requests --- enigma2/__init__.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/enigma2/__init__.py b/enigma2/__init__.py index b4e17d0ed..82a2d5bb4 100644 --- a/enigma2/__init__.py +++ b/enigma2/__init__.py @@ -25,9 +25,14 @@ import logging import time from xml.dom import minidom -import requests -from requests.packages import urllib3 -from requests.auth import HTTPBasicAuth +try: + import requests + from requests.packages import urllib3 + from requests.auth import HTTPBasicAuth + REQUIRED_PACKAGE_IMPORTED = True +except: + REQUIRED_PACKAGE_IMPORTED = False + from lib.model.smartplugin import SmartPlugin @@ -161,6 +166,11 @@ def __init__(self, smarthome, username='', password='', host='dreambox', port='8 self.logger = logging.getLogger(__name__) # self.logger.info('Init Enigma2 Plugin with device_id %s' % ) + if not REQUIRED_PACKAGE_IMPORTED: + self.logger.error("{}: Unable to import Python package 'requests'".format(self.get_fullname())) + self._init_complete = False + return + self._session = requests.Session() self._timeout = 10 self._verify = self.to_bool(verify) From 26cbbdafaa727997b9e7e393bf1088293946f57c Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 13 Aug 2018 07:04:52 +0200 Subject: [PATCH 093/705] ODLInfo: added error handling for package requests --- odlinfo/__init__.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/odlinfo/__init__.py b/odlinfo/__init__.py index 3afd7fe4b..e42b2cff8 100644 --- a/odlinfo/__init__.py +++ b/odlinfo/__init__.py @@ -34,9 +34,14 @@ ######################################################################### import logging -import requests from lib.model.smartplugin import SmartPlugin -from requests.auth import HTTPBasicAuth +try: + import requests + from requests.auth import HTTPBasicAuth + REQUIRED_PACKAGE_IMPORTED = True +except: + REQUIRED_PACKAGE_IMPORTED = False + class ODLInfo(SmartPlugin): PLUGIN_VERSION = "1.4.1" @@ -49,6 +54,10 @@ def __init__(self, sh, *args, **kwargs): @param password: For accessing the ODLINFO API you need a personal password """ self.logger = logging.getLogger(__name__) + if not REQUIRED_PACKAGE_IMPORTED: + self.logger.error("{}: Unable to import Python package 'requests'".format(self.get_fullname())) + self._init_complete = False + return self._user = self.get_parameter_value('user') self._password = self.get_parameter_value('password') self._keys = ['ort', 'kenn', 'plz', 'status', 'kid', 'hoehe', 'lon', 'lat', 'mw'] From 297dead0a93a86b2c8ae6511a045251bf63b479c Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 13 Aug 2018 07:09:20 +0200 Subject: [PATCH 094/705] Slight adaptions to README's and Versions --- avm/README.md | 5 ++--- avm/__init__.py | 2 +- avm/plugin.yaml | 2 +- enigma2/__init__.py | 2 +- enigma2/plugin.yaml | 2 +- nokia_health/__init__.py | 2 +- nokia_health/plugin.yaml | 2 +- odlinfo/__init__.py | 2 +- odlinfo/plugin.yaml | 2 +- 9 files changed, 10 insertions(+), 11 deletions(-) diff --git a/avm/README.md b/avm/README.md index 0b0756147..b5f4525ca 100644 --- a/avm/README.md +++ b/avm/README.md @@ -14,9 +14,8 @@ It is completely based on the TR-064 interface from AVM (http://avm.de/service/s Forum thread to the plugin: https://knx-user-forum.de/forum/supportforen/smarthome-py/934835-avm-plugin -Version 1.1.2 tested with a FRITZ!Box 7490 (FRITZ!OS 06.51), a FRITZ! WLAN Repeater 1750E (FRITZ!OS 06.32) and a -WLAN Repeater 300E (FRITZ!OS 06.30). It was also tested with a FRITZ!Box 7390 with FW 84.06.36 and a Fritz!Box 7390 -with v6.30 und v6.51. +Version 1.5.5 tested with a FRITZ!Box 7590 (FRITZ!OS 7), FRITZ!Box 7490 (FRITZ!OS 06.93), and a FRITZ! WLAN Repeater +1750E (FRITZ!OS 06.93). Lower firmwares and other models may work as well! The avm_data_types listed in the example items under "devices" only work correctly with firmware <= v6.30, if the FRITZ!Box does not handle more than 16 devices in parallel (under "Heimnetz/Netzwerk"). Otherwise some of the devices diff --git a/avm/__init__.py b/avm/__init__.py index 233045a5c..ce4a961fc 100644 --- a/avm/__init__.py +++ b/avm/__init__.py @@ -482,7 +482,7 @@ class AVM(SmartPlugin): Main class of the Plugin. Does all plugin specific stuff and provides the update functions for the different TR-064 services on the FritzDevice """ - PLUGIN_VERSION = "1.5.4" + PLUGIN_VERSION = "1.5.5" _header = {'SOAPACTION': '', 'CONTENT-TYPE': 'text/xml; charset="utf-8"'} _envelope = """ diff --git a/avm/plugin.yaml b/avm/plugin.yaml index 2ea0a3ae9..6bac0951a 100755 --- a/avm/plugin.yaml +++ b/avm/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: http://smarthomeng.de/user/plugins_doc/config/avm.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/934835-avm-plugin - version: 1.5.4 # Plugin version + version: 1.5.5 # Plugin version sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance diff --git a/enigma2/__init__.py b/enigma2/__init__.py index 82a2d5bb4..dc93e9f06 100644 --- a/enigma2/__init__.py +++ b/enigma2/__init__.py @@ -129,7 +129,7 @@ class Enigma2(SmartPlugin): Main class of the Plugin. Does all plugin specific stuff and provides the update functions for the Enigma2Device """ ALLOW_MULTIINSTANCE = True - PLUGIN_VERSION = "1.4.11" + PLUGIN_VERSION = "1.4.12" _url_suffix_map = dict([('about', '/web/about'), ('deviceinfo', '/web/deviceinfo'), diff --git a/enigma2/plugin.yaml b/enigma2/plugin.yaml index 78d67297d..24d14e465 100755 --- a/enigma2/plugin.yaml +++ b/enigma2/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: http://smarthomeng.de/user/plugins_doc/config/enigma2.html # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/943871-enigma2-plugin - version: 1.4.11 # Plugin version + version: 1.4.12 # Plugin version sh_minversion: 1.3c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance diff --git a/nokia_health/__init__.py b/nokia_health/__init__.py index f3aa11795..43d327ed8 100644 --- a/nokia_health/__init__.py +++ b/nokia_health/__init__.py @@ -32,7 +32,7 @@ class NokiaHealth(SmartPlugin): ALLOW_MULTIINSTANCE = True - PLUGIN_VERSION = "1.5.2" + PLUGIN_VERSION = "1.5.3" BASE_URL = "https://api.health.nokia.com/" ALLOWED_MEASURE_TYPES = [1, 4, 5, 6, 8, 11] diff --git a/nokia_health/plugin.yaml b/nokia_health/plugin.yaml index f04458fac..7cd4ddfa0 100644 --- a/nokia_health/plugin.yaml +++ b/nokia_health/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: 'http://smarthomeng.de/user/plugins_doc/config/nokia_health.html' support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/1141179-nokia-health-plugin' - version: 1.5.2 # Plugin version + version: 1.5.3 # Plugin version sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance diff --git a/odlinfo/__init__.py b/odlinfo/__init__.py index e42b2cff8..fa9a8fe20 100644 --- a/odlinfo/__init__.py +++ b/odlinfo/__init__.py @@ -44,7 +44,7 @@ class ODLInfo(SmartPlugin): - PLUGIN_VERSION = "1.4.1" + PLUGIN_VERSION = "1.4.2" _base_url = 'https://odlinfo.bfs.de/daten/json/stamm.json' def __init__(self, sh, *args, **kwargs): diff --git a/odlinfo/plugin.yaml b/odlinfo/plugin.yaml index 3be7a2f28..68b893b88 100755 --- a/odlinfo/plugin.yaml +++ b/odlinfo/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: http://smarthomeng.de/user/plugins_doc/config/odlinfo.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/986480-odlinfo-plugin-für-strahlungsdaten - version: 1.4.1 # Plugin version + version: 1.4.2 # Plugin version sh_minversion: 1.4 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance From 7adce0ed93baa6600010894710b660e343d23c72 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 13 Aug 2018 07:20:01 +0200 Subject: [PATCH 095/705] Tankerkoenig: check for requests package, modifications to version and README --- tankerkoenig/README.md | 4 +++- tankerkoenig/__init__.py | 15 +++++++++++++-- tankerkoenig/plugin.yaml | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/tankerkoenig/README.md b/tankerkoenig/README.md index 834258316..64ec13276 100644 --- a/tankerkoenig/README.md +++ b/tankerkoenig/README.md @@ -1,6 +1,8 @@ # TankerKoenig -Version 0.1 +## Description + +This plugin provides petrol station prices by the API of TankerKönig. Take care not to request the interface too often or for too many petrol stations. Please follow instructions given on https://creativecommons.tankerkoenig.de/#techInfo. ## Requirements diff --git a/tankerkoenig/__init__.py b/tankerkoenig/__init__.py index 0494f9b2b..1bc0378cb 100755 --- a/tankerkoenig/__init__.py +++ b/tankerkoenig/__init__.py @@ -23,13 +23,18 @@ ######################################################################### import logging -import requests +try: + import requests + REQUIRED_PACKAGE_IMPORTED = True +except: + REQUIRED_PACKAGE_IMPORTED = False + import json from lib.model.smartplugin import SmartPlugin class TankerKoenig(SmartPlugin): - PLUGIN_VERSION = "1.4.1" + PLUGIN_VERSION = "1.4.2" _base_url = 'https://creativecommons.tankerkoenig.de/json/' _detail_url_suffix = 'detail.php' _prices_url_suffix = 'prices.php' @@ -42,6 +47,12 @@ def __init__(self, sh, *args, **kwargs): api key. For your own key register to https://creativecommons.tankerkoenig.de """ self.logger = logging.getLogger(__name__) + + if not REQUIRED_PACKAGE_IMPORTED: + self.logger.error("{}: Unable to import Python package 'requests'".format(self.get_fullname())) + self._init_complete = False + return + self._apikey = self.get_parameter_value('apikey') self._session = requests.Session() diff --git a/tankerkoenig/plugin.yaml b/tankerkoenig/plugin.yaml index d156abfe2..068bf71f8 100755 --- a/tankerkoenig/plugin.yaml +++ b/tankerkoenig/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: http://smarthomeng.de/user/plugins_doc/config/tankerkoenig.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/938924-benzinpreis-plugin keywords: petrol station, fuel prices, petrol prices - version: 1.4.1 # Plugin version + version: 1.4.2 # Plugin version sh_minversion: 1.4 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance From bd80e4c39d2b19dce47ebde1c4d1d7f693618090 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 13 Aug 2018 07:23:58 +0200 Subject: [PATCH 096/705] Miflora: added check for miflora package --- miflora/README.md | 3 ++- miflora/__init__.py | 17 +++++++++++++---- miflora/plugin.yaml | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/miflora/README.md b/miflora/README.md index 9869007a0..04e0dd3f0 100644 --- a/miflora/README.md +++ b/miflora/README.md @@ -1,6 +1,7 @@ # Miflora -Version 0.4 +## Description +Read data from Xiaomi MiFlora plant sensors via Bluetooth LE. ## Requirements This plugin requires lib miflora in version 0.4 or above. You can install this lib with: diff --git a/miflora/__init__.py b/miflora/__init__.py index 31e7427f6..584d04034 100644 --- a/miflora/__init__.py +++ b/miflora/__init__.py @@ -21,14 +21,19 @@ ######################################################################### import logging -from miflora.miflora_poller import MiFloraPoller, \ - MI_CONDUCTIVITY, MI_MOISTURE, MI_LIGHT, MI_TEMPERATURE, MI_BATTERY +try: + from miflora.miflora_poller import MiFloraPoller, \ + MI_CONDUCTIVITY, MI_MOISTURE, MI_LIGHT, MI_TEMPERATURE, MI_BATTERY + REQUIRED_PACKAGE_IMPORTED = True +except: + REQUIRED_PACKAGE_IMPORTED = False + from btlewrap import available_backends, BluepyBackend, GatttoolBackend, PygattBackend from lib.model.smartplugin import SmartPlugin class Miflora(SmartPlugin): ALLOW_MULTIINSTANCE = True - PLUGIN_VERSION = "1.3.0.4" + PLUGIN_VERSION = "1.3.0.5" def __init__(self, smarthome, bt_addr, cycle=300): """ @@ -39,7 +44,11 @@ def __init__(self, smarthome, bt_addr, cycle=300): :param cycle: Cycle interval in seconds """ self._sh = smarthome - self.logger = logging.getLogger(__name__) # get a unique logger for the plugin and provide it internally + self.logger = logging.getLogger(__name__) + if not REQUIRED_PACKAGE_IMPORTED: + self.logger.error("{}: Unable to import Python package 'pyhomematic'".format(self.get_fullname())) + self._init_complete = False + return self._bt_addr = bt_addr self._cycle = int(cycle) self._items = [] diff --git a/miflora/plugin.yaml b/miflora/plugin.yaml index 409f6e7e9..74fa5f1b8 100644 --- a/miflora/plugin.yaml +++ b/miflora/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: http://smarthomeng.de/user/plugins_doc/config/miflora.html # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1027133-plugin-miflora-mi-plant-flowers-tester-light-monitor - version: 1.3.0.4 # Plugin version + version: 1.3.0.5 # Plugin version sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance From e48c65b53bfa52bfe849dbc5cb6cf8eaa9e94320 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 13 Aug 2018 07:26:44 +0200 Subject: [PATCH 097/705] miflora: changed error message --- miflora/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miflora/__init__.py b/miflora/__init__.py index 584d04034..463e3cfdb 100644 --- a/miflora/__init__.py +++ b/miflora/__init__.py @@ -46,7 +46,7 @@ def __init__(self, smarthome, bt_addr, cycle=300): self._sh = smarthome self.logger = logging.getLogger(__name__) if not REQUIRED_PACKAGE_IMPORTED: - self.logger.error("{}: Unable to import Python package 'pyhomematic'".format(self.get_fullname())) + self.logger.error("{}: Unable to import Python package 'miflora'".format(self.get_fullname())) self._init_complete = False return self._bt_addr = bt_addr From bc94545073617792e4dfb95e8a7aa18b36d4ccc4 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 13 Aug 2018 07:26:59 +0200 Subject: [PATCH 098/705] MVGLive: added check for MVGLive package --- mvg_live/README.md | 4 +++- mvg_live/__init__.py | 17 +++++++++++++---- mvg_live/plugin.yaml | 2 +- 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/mvg_live/README.md b/mvg_live/README.md index 1b070777f..1a9f80aad 100644 --- a/mvg_live/README.md +++ b/mvg_live/README.md @@ -1,6 +1,8 @@ # MVG Live -Version 0.1 +## Description + +Retrieval of departure times of stations within the Münchner Verkehrsbetriebe (MVG) ## Requirements This plugin requires lib PyMVGLive. You can install this lib with: diff --git a/mvg_live/__init__.py b/mvg_live/__init__.py index ee459eb73..26a896170 100644 --- a/mvg_live/__init__.py +++ b/mvg_live/__init__.py @@ -2,7 +2,7 @@ # ######################################################################### # Copyright 2017 René Frieß rene.friess(a)gmail.com -# Version 1.3.0.1 +# Version 1.3.0.2 ######################################################################### # # This file is part of SmartHomeNG. @@ -23,19 +23,28 @@ ######################################################################### import logging -import MVGLive - +try: + import MVGLive + REQUIRED_PACKAGE_IMPORTED = True +except: + REQUIRED_PACKAGE_IMPORTED = False from lib.model.smartplugin import SmartPlugin + class MVG_Live(SmartPlugin): ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.3.0.1" + PLUGIN_VERSION = "1.3.0.2" def __init__(self, smarthome): """ Initializes the plugin """ self.logger = logging.getLogger(__name__) + if not REQUIRED_PACKAGE_IMPORTED: + self.logger.error("{}: Unable to import Python package 'MVGLive'".format(self.get_fullname())) + self._init_complete = False + return + self._sh = smarthome self._mvg_live = MVGLive.MVGLive() diff --git a/mvg_live/plugin.yaml b/mvg_live/plugin.yaml index 2439f3e71..ab7382893 100755 --- a/mvg_live/plugin.yaml +++ b/mvg_live/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: http://smarthomeng.de/user/plugins_doc/config/mvg_live.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1108867-neues-plugin-mvg_live - version: 1.3.0.1 # Plugin version + version: 1.3.0.2 # Plugin version sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance From de3def61cf44a4089d0f213dd3b9b66fb81bdb01 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 13 Aug 2018 07:30:23 +0200 Subject: [PATCH 099/705] Darksky, OpenWeatherMap: added check for requests package --- darksky/README.md | 2 +- darksky/__init__.py | 16 +++++++++++----- darksky/plugin.yaml | 2 +- openweathermap/README.md | 2 +- openweathermap/__init__.py | 14 +++++++++++--- openweathermap/plugin.yaml | 2 +- 6 files changed, 26 insertions(+), 12 deletions(-) diff --git a/darksky/README.md b/darksky/README.md index 7081790eb..581804ff6 100644 --- a/darksky/README.md +++ b/darksky/README.md @@ -1,6 +1,6 @@ # darksky.net / forecast.io -#### Version 1.5.0.1 +#### Version 1.5.0.2 This plugins can be used retrieve weather information from darksky.net / forecast.io. diff --git a/darksky/__init__.py b/darksky/__init__.py index 28633c157..db2cafe1f 100644 --- a/darksky/__init__.py +++ b/darksky/__init__.py @@ -2,7 +2,7 @@ # ######################################################################### # Copyright 2018 René Frieß rene.friess(a)gmail.com -# Version 1.5.0.1 +# Version 1.5.0.2 ######################################################################### # # This file is part of SmartHomeNG. @@ -23,7 +23,11 @@ ######################################################################### import logging -import requests +try: + import requests + REQUIRED_PACKAGE_IMPORTED = True +except: + REQUIRED_PACKAGE_IMPORTED = False import datetime import json from lib.module import Modules @@ -31,9 +35,7 @@ class DarkSky(SmartPlugin): - - PLUGIN_VERSION = "1.5.0.1" - + PLUGIN_VERSION = "1.5.0.2" _base_forecast_url = 'https://api.darksky.net/forecast/%s/%s,%s' def __init__(self, sh, *args, **kwargs): @@ -43,6 +45,10 @@ def __init__(self, sh, *args, **kwargs): api key. For your own key register to https://creativecommons.tankerkoenig.de """ self.logger = logging.getLogger(__name__) + if not REQUIRED_PACKAGE_IMPORTED: + self.logger.error("{}: Unable to import Python package 'requests'".format(self.get_fullname())) + self._init_complete = False + return self._key = self.get_parameter_value('key') if self.get_parameter_value('latitude') != '' and self.get_parameter_value('longitude') != '': self._lat = self.get_parameter_value('latitude') diff --git a/darksky/plugin.yaml b/darksky/plugin.yaml index 4190e4626..0f16e3e5d 100644 --- a/darksky/plugin.yaml +++ b/darksky/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: '' support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/1244744-neues-plugin-wetterdaten-via-darksky-net-forecast-io' keywords: weather - version: 1.5.0.1 # Plugin version + version: 1.5.0.2 # Plugin version sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance diff --git a/openweathermap/README.md b/openweathermap/README.md index bb7359a60..8793113b0 100644 --- a/openweathermap/README.md +++ b/openweathermap/README.md @@ -1,6 +1,6 @@ # OpenWeatherMap -#### Version 1.5.0.1 +#### Version 1.5.0.2 This plugins can be used retrieve weather information from OpenWeatherMap (https://openweathermap.org/). diff --git a/openweathermap/__init__.py b/openweathermap/__init__.py index b3510e186..688079f66 100644 --- a/openweathermap/__init__.py +++ b/openweathermap/__init__.py @@ -2,7 +2,7 @@ # ######################################################################### # Copyright 2018 René Frieß rene.friess(a)gmail.com -# Version 1.5.0.1 +# Version 1.5.0.2 ######################################################################### # # This file is part of SmartHomeNG. @@ -23,7 +23,11 @@ ######################################################################### import logging -import requests +try: + import requests + REQUIRED_PACKAGE_IMPORTED = True +except: + REQUIRED_PACKAGE_IMPORTED = False import datetime import json from lib.module import Modules @@ -31,7 +35,7 @@ class OpenWeatherMap(SmartPlugin): - PLUGIN_VERSION = "1.5.0.1" + PLUGIN_VERSION = "1.5.0.2" _base_url = 'https://api.openweathermap.org/%s' _base_img_url = 'https://tile.openweathermap.org/map/%s/%s/%s/%s.png?appid=%s' @@ -43,6 +47,10 @@ def __init__(self, sh, *args, **kwargs): api key. For your own key register to https://creativecommons.tankerkoenig.de """ self.logger = logging.getLogger(__name__) + if not REQUIRED_PACKAGE_IMPORTED: + self.logger.error("{}: Unable to import Python package 'requests'".format(self.get_fullname())) + self._init_complete = False + return self._key = self.get_parameter_value('key') if self.get_parameter_value('latitude') != '' and self.get_parameter_value('longitude') != '': self._lat = self.get_parameter_value('latitude') diff --git a/openweathermap/plugin.yaml b/openweathermap/plugin.yaml index 1d1dc48f7..6acd8cbbd 100644 --- a/openweathermap/plugin.yaml +++ b/openweathermap/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: '' support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/1246998-support-thread-zum-openweathermap-plugin' keywords: weather - version: 1.5.0.1 # Plugin version + version: 1.5.0.2 # Plugin version sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance From d35b23e357069cc4e92ecef25f7e565f442fc48d Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 13 Aug 2018 07:32:51 +0200 Subject: [PATCH 100/705] Traffic: added check for requests package --- traffic/README.md | 2 +- traffic/__init__.py | 17 +++++++++++++---- traffic/plugin.yaml | 2 +- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/traffic/README.md b/traffic/README.md index 80f31a173..99817d3d5 100644 --- a/traffic/README.md +++ b/traffic/README.md @@ -1,6 +1,6 @@ # Traffic -Version 0.1 +## Description This plugin provides functionality to query the Google Directions API for traffic / direction info. All mappings to items need to be done via your own logic. diff --git a/traffic/__init__.py b/traffic/__init__.py index 15261febb..2e305c595 100644 --- a/traffic/__init__.py +++ b/traffic/__init__.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 # ######################################################################### -# Copyright 2017 René Frieß rene.friess(a)gmail.com -# Version 1.3.0.1 +# Copyright 2017-2018 René Frieß rene.friess(a)gmail.com +# Version 1.3.0.2 ######################################################################### # # This file is part of SmartHomeNG. @@ -23,12 +23,17 @@ ######################################################################### import logging -import requests +try: + import requests + REQUIRED_PACKAGE_IMPORTED = True +except: + REQUIRED_PACKAGE_IMPORTED = False + from lib.model.smartplugin import SmartPlugin class Traffic(SmartPlugin): ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.3.0.1" + PLUGIN_VERSION = "1.3.0.2" _base_url = 'https://maps.googleapis.com/maps/api/directions/json' def __init__(self, smarthome, apikey, language='de'): @@ -39,6 +44,10 @@ def __init__(self, smarthome, apikey, language='de'): @param language: two char language code. default: de """ self.logger = logging.getLogger(__name__) + if not REQUIRED_PACKAGE_IMPORTED: + self.logger.error("{}: Unable to import Python package 'requests'".format(self.get_fullname())) + self._init_complete = False + return self._sh = smarthome self._apikey = apikey self._language = language diff --git a/traffic/plugin.yaml b/traffic/plugin.yaml index 5672e4b96..6d6dfebfe 100755 --- a/traffic/plugin.yaml +++ b/traffic/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: http://smarthomeng.de/user/plugins_doc/config/traffic.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1048446-traffic-plugin-support-thread - version: 1.3.0.1 # Plugin version + version: 1.3.0.2 # Plugin version sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance From d44de8c90838925001d25b481c60b57f8c0b9df9 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 13 Aug 2018 07:36:54 +0200 Subject: [PATCH 101/705] Join: added check for requests package --- join/README.md | 2 +- join/__init__.py | 12 ++++++++++-- join/plugin.yaml | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/join/README.md b/join/README.md index a2b2c9a7e..1c36114b2 100644 --- a/join/README.md +++ b/join/README.md @@ -1,6 +1,6 @@ # Join -Version 1.0 +Version 1.4.1.1 This plugin allows to send command to your mobile phone via the Join API: https://joaoapps.com/join/api/ diff --git a/join/__init__.py b/join/__init__.py index 390dcaad6..bfe5c473b 100644 --- a/join/__init__.py +++ b/join/__init__.py @@ -22,7 +22,11 @@ ######################################################################### import logging -import requests +try: + import requests + REQUIRED_PACKAGE_IMPORTED = True +except: + REQUIRED_PACKAGE_IMPORTED = False from lib.model.smartplugin import SmartPlugin @@ -30,12 +34,16 @@ class Join(SmartPlugin): URL_PREFIX = 'https://joinjoaomgcd.appspot.com/_ah/api/' SEND_URL = URL_PREFIX+'messaging/v1/sendPush?apikey=' LIST_URL = URL_PREFIX+'registration/v1/listDevices?apikey=' - PLUGIN_VERSION = "1.4.1.0" + PLUGIN_VERSION = "1.4.1.1" ALLOW_MULTIINSTANCE = False def __init__(self, smarthome, api_key=None, device_id=None): logging.getLogger("requests").setLevel(logging.WARNING) self.logger = logging.getLogger(__name__) + if not REQUIRED_PACKAGE_IMPORTED: + self.logger.error("{}: Unable to import Python package 'requests'".format(self.get_fullname())) + self._init_complete = False + return self._api_key = api_key self._device_id = device_id self._sh = smarthome diff --git a/join/plugin.yaml b/join/plugin.yaml index f6952c667..5ca66c529 100755 --- a/join/plugin.yaml +++ b/join/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: http://smarthomeng.de/user/plugins_doc/config/join.html # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1113523-neues-plugin-join-tts-sms-phonecall-notification-uvm - version: 1.4.1.0 # Plugin version + version: 1.4.1.1 # Plugin version sh_minversion: 1.3a # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance From 5d879cc96a7a58361ba65e0c3fb253bf5141e95a Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 13 Aug 2018 07:42:45 +0200 Subject: [PATCH 102/705] Nuki: added english text --- nuki/plugin.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nuki/plugin.yaml b/nuki/plugin.yaml index fe4c8810d..39d88d4f5 100755 --- a/nuki/plugin.yaml +++ b/nuki/plugin.yaml @@ -4,7 +4,7 @@ plugin: type: interface # plugin type (gateway, interface, protocol, system, web) description: de: 'Unterstützung für ein Nuki Smart-Lock' - en: '' + en: 'Support for smart locks by Nuki' maintainer: fuppy, pfischi # tester: # Who tests this plugin? # keywords: iot xyz From cafa6303ca4e38bfbbd5929ebb7e5dd2038df2c8 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 13 Aug 2018 09:15:25 +0200 Subject: [PATCH 103/705] Revert import check feature as solved centrally. --- avm/README.md | 5 +++-- avm/__init__.py | 19 ++++--------------- avm/plugin.yaml | 2 +- darksky/README.md | 2 +- darksky/__init__.py | 16 +++++----------- darksky/plugin.yaml | 2 +- enigma2/__init__.py | 18 ++++-------------- enigma2/plugin.yaml | 2 +- join/README.md | 2 +- join/__init__.py | 12 ++---------- join/plugin.yaml | 2 +- miflora/README.md | 3 +-- miflora/__init__.py | 17 ++++------------- miflora/plugin.yaml | 2 +- mvg_live/README.md | 4 +--- mvg_live/__init__.py | 17 ++++------------- mvg_live/plugin.yaml | 2 +- nokia_health/__init__.py | 14 +++----------- nokia_health/plugin.yaml | 2 +- nuki/plugin.yaml | 2 +- odlinfo/__init__.py | 15 +++------------ odlinfo/plugin.yaml | 2 +- openweathermap/README.md | 2 +- openweathermap/__init__.py | 14 +++----------- openweathermap/plugin.yaml | 2 +- tankerkoenig/README.md | 4 +--- tankerkoenig/__init__.py | 15 ++------------- tankerkoenig/plugin.yaml | 2 +- traffic/README.md | 2 +- traffic/__init__.py | 17 ++++------------- traffic/plugin.yaml | 2 +- 31 files changed, 60 insertions(+), 162 deletions(-) diff --git a/avm/README.md b/avm/README.md index b5f4525ca..0b0756147 100644 --- a/avm/README.md +++ b/avm/README.md @@ -14,8 +14,9 @@ It is completely based on the TR-064 interface from AVM (http://avm.de/service/s Forum thread to the plugin: https://knx-user-forum.de/forum/supportforen/smarthome-py/934835-avm-plugin -Version 1.5.5 tested with a FRITZ!Box 7590 (FRITZ!OS 7), FRITZ!Box 7490 (FRITZ!OS 06.93), and a FRITZ! WLAN Repeater -1750E (FRITZ!OS 06.93). Lower firmwares and other models may work as well! +Version 1.1.2 tested with a FRITZ!Box 7490 (FRITZ!OS 06.51), a FRITZ! WLAN Repeater 1750E (FRITZ!OS 06.32) and a +WLAN Repeater 300E (FRITZ!OS 06.30). It was also tested with a FRITZ!Box 7390 with FW 84.06.36 and a Fritz!Box 7390 +with v6.30 und v6.51. The avm_data_types listed in the example items under "devices" only work correctly with firmware <= v6.30, if the FRITZ!Box does not handle more than 16 devices in parallel (under "Heimnetz/Netzwerk"). Otherwise some of the devices diff --git a/avm/__init__.py b/avm/__init__.py index ce4a961fc..b800bf0bc 100644 --- a/avm/__init__.py +++ b/avm/__init__.py @@ -27,14 +27,9 @@ import time import threading from xml.dom import minidom -try: - import requests - from requests.packages import urllib3 - from requests.auth import HTTPDigestAuth - REQUIRED_PACKAGE_IMPORTED = True -except: - REQUIRED_PACKAGE_IMPORTED = False - +import requests +from requests.packages import urllib3 +from requests.auth import HTTPDigestAuth from lib.model.smartplugin import * from lib.module import Modules @@ -482,7 +477,7 @@ class AVM(SmartPlugin): Main class of the Plugin. Does all plugin specific stuff and provides the update functions for the different TR-064 services on the FritzDevice """ - PLUGIN_VERSION = "1.5.5" + PLUGIN_VERSION = "1.5.4" _header = {'SOAPACTION': '', 'CONTENT-TYPE': 'text/xml; charset="utf-8"'} _envelope = """ @@ -520,12 +515,6 @@ def __init__(self, sh, *args, **kwargs): Initalizes the plugin. The parameters describe for this method are pulled from the entry in plugin.conf. """ self.logger = logging.getLogger(__name__) - - if not REQUIRED_PACKAGE_IMPORTED: - self.logger.error("{}: Unable to import Python package 'requests'".format(self.get_fullname())) - self._init_complete = False - return - self.logger.info('Init AVM Plugin') self._session = requests.Session() diff --git a/avm/plugin.yaml b/avm/plugin.yaml index 6bac0951a..2ea0a3ae9 100755 --- a/avm/plugin.yaml +++ b/avm/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: http://smarthomeng.de/user/plugins_doc/config/avm.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/934835-avm-plugin - version: 1.5.5 # Plugin version + version: 1.5.4 # Plugin version sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance diff --git a/darksky/README.md b/darksky/README.md index 581804ff6..7081790eb 100644 --- a/darksky/README.md +++ b/darksky/README.md @@ -1,6 +1,6 @@ # darksky.net / forecast.io -#### Version 1.5.0.2 +#### Version 1.5.0.1 This plugins can be used retrieve weather information from darksky.net / forecast.io. diff --git a/darksky/__init__.py b/darksky/__init__.py index db2cafe1f..28633c157 100644 --- a/darksky/__init__.py +++ b/darksky/__init__.py @@ -2,7 +2,7 @@ # ######################################################################### # Copyright 2018 René Frieß rene.friess(a)gmail.com -# Version 1.5.0.2 +# Version 1.5.0.1 ######################################################################### # # This file is part of SmartHomeNG. @@ -23,11 +23,7 @@ ######################################################################### import logging -try: - import requests - REQUIRED_PACKAGE_IMPORTED = True -except: - REQUIRED_PACKAGE_IMPORTED = False +import requests import datetime import json from lib.module import Modules @@ -35,7 +31,9 @@ class DarkSky(SmartPlugin): - PLUGIN_VERSION = "1.5.0.2" + + PLUGIN_VERSION = "1.5.0.1" + _base_forecast_url = 'https://api.darksky.net/forecast/%s/%s,%s' def __init__(self, sh, *args, **kwargs): @@ -45,10 +43,6 @@ def __init__(self, sh, *args, **kwargs): api key. For your own key register to https://creativecommons.tankerkoenig.de """ self.logger = logging.getLogger(__name__) - if not REQUIRED_PACKAGE_IMPORTED: - self.logger.error("{}: Unable to import Python package 'requests'".format(self.get_fullname())) - self._init_complete = False - return self._key = self.get_parameter_value('key') if self.get_parameter_value('latitude') != '' and self.get_parameter_value('longitude') != '': self._lat = self.get_parameter_value('latitude') diff --git a/darksky/plugin.yaml b/darksky/plugin.yaml index 0f16e3e5d..4190e4626 100644 --- a/darksky/plugin.yaml +++ b/darksky/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: '' support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/1244744-neues-plugin-wetterdaten-via-darksky-net-forecast-io' keywords: weather - version: 1.5.0.2 # Plugin version + version: 1.5.0.1 # Plugin version sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance diff --git a/enigma2/__init__.py b/enigma2/__init__.py index dc93e9f06..b4e17d0ed 100644 --- a/enigma2/__init__.py +++ b/enigma2/__init__.py @@ -25,14 +25,9 @@ import logging import time from xml.dom import minidom -try: - import requests - from requests.packages import urllib3 - from requests.auth import HTTPBasicAuth - REQUIRED_PACKAGE_IMPORTED = True -except: - REQUIRED_PACKAGE_IMPORTED = False - +import requests +from requests.packages import urllib3 +from requests.auth import HTTPBasicAuth from lib.model.smartplugin import SmartPlugin @@ -129,7 +124,7 @@ class Enigma2(SmartPlugin): Main class of the Plugin. Does all plugin specific stuff and provides the update functions for the Enigma2Device """ ALLOW_MULTIINSTANCE = True - PLUGIN_VERSION = "1.4.12" + PLUGIN_VERSION = "1.4.11" _url_suffix_map = dict([('about', '/web/about'), ('deviceinfo', '/web/deviceinfo'), @@ -166,11 +161,6 @@ def __init__(self, smarthome, username='', password='', host='dreambox', port='8 self.logger = logging.getLogger(__name__) # self.logger.info('Init Enigma2 Plugin with device_id %s' % ) - if not REQUIRED_PACKAGE_IMPORTED: - self.logger.error("{}: Unable to import Python package 'requests'".format(self.get_fullname())) - self._init_complete = False - return - self._session = requests.Session() self._timeout = 10 self._verify = self.to_bool(verify) diff --git a/enigma2/plugin.yaml b/enigma2/plugin.yaml index 24d14e465..78d67297d 100755 --- a/enigma2/plugin.yaml +++ b/enigma2/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: http://smarthomeng.de/user/plugins_doc/config/enigma2.html # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/943871-enigma2-plugin - version: 1.4.12 # Plugin version + version: 1.4.11 # Plugin version sh_minversion: 1.3c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance diff --git a/join/README.md b/join/README.md index 1c36114b2..a2b2c9a7e 100644 --- a/join/README.md +++ b/join/README.md @@ -1,6 +1,6 @@ # Join -Version 1.4.1.1 +Version 1.0 This plugin allows to send command to your mobile phone via the Join API: https://joaoapps.com/join/api/ diff --git a/join/__init__.py b/join/__init__.py index bfe5c473b..390dcaad6 100644 --- a/join/__init__.py +++ b/join/__init__.py @@ -22,11 +22,7 @@ ######################################################################### import logging -try: - import requests - REQUIRED_PACKAGE_IMPORTED = True -except: - REQUIRED_PACKAGE_IMPORTED = False +import requests from lib.model.smartplugin import SmartPlugin @@ -34,16 +30,12 @@ class Join(SmartPlugin): URL_PREFIX = 'https://joinjoaomgcd.appspot.com/_ah/api/' SEND_URL = URL_PREFIX+'messaging/v1/sendPush?apikey=' LIST_URL = URL_PREFIX+'registration/v1/listDevices?apikey=' - PLUGIN_VERSION = "1.4.1.1" + PLUGIN_VERSION = "1.4.1.0" ALLOW_MULTIINSTANCE = False def __init__(self, smarthome, api_key=None, device_id=None): logging.getLogger("requests").setLevel(logging.WARNING) self.logger = logging.getLogger(__name__) - if not REQUIRED_PACKAGE_IMPORTED: - self.logger.error("{}: Unable to import Python package 'requests'".format(self.get_fullname())) - self._init_complete = False - return self._api_key = api_key self._device_id = device_id self._sh = smarthome diff --git a/join/plugin.yaml b/join/plugin.yaml index 5ca66c529..f6952c667 100755 --- a/join/plugin.yaml +++ b/join/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: http://smarthomeng.de/user/plugins_doc/config/join.html # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1113523-neues-plugin-join-tts-sms-phonecall-notification-uvm - version: 1.4.1.1 # Plugin version + version: 1.4.1.0 # Plugin version sh_minversion: 1.3a # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance diff --git a/miflora/README.md b/miflora/README.md index 04e0dd3f0..9869007a0 100644 --- a/miflora/README.md +++ b/miflora/README.md @@ -1,7 +1,6 @@ # Miflora -## Description -Read data from Xiaomi MiFlora plant sensors via Bluetooth LE. +Version 0.4 ## Requirements This plugin requires lib miflora in version 0.4 or above. You can install this lib with: diff --git a/miflora/__init__.py b/miflora/__init__.py index 463e3cfdb..31e7427f6 100644 --- a/miflora/__init__.py +++ b/miflora/__init__.py @@ -21,19 +21,14 @@ ######################################################################### import logging -try: - from miflora.miflora_poller import MiFloraPoller, \ - MI_CONDUCTIVITY, MI_MOISTURE, MI_LIGHT, MI_TEMPERATURE, MI_BATTERY - REQUIRED_PACKAGE_IMPORTED = True -except: - REQUIRED_PACKAGE_IMPORTED = False - +from miflora.miflora_poller import MiFloraPoller, \ + MI_CONDUCTIVITY, MI_MOISTURE, MI_LIGHT, MI_TEMPERATURE, MI_BATTERY from btlewrap import available_backends, BluepyBackend, GatttoolBackend, PygattBackend from lib.model.smartplugin import SmartPlugin class Miflora(SmartPlugin): ALLOW_MULTIINSTANCE = True - PLUGIN_VERSION = "1.3.0.5" + PLUGIN_VERSION = "1.3.0.4" def __init__(self, smarthome, bt_addr, cycle=300): """ @@ -44,11 +39,7 @@ def __init__(self, smarthome, bt_addr, cycle=300): :param cycle: Cycle interval in seconds """ self._sh = smarthome - self.logger = logging.getLogger(__name__) - if not REQUIRED_PACKAGE_IMPORTED: - self.logger.error("{}: Unable to import Python package 'miflora'".format(self.get_fullname())) - self._init_complete = False - return + self.logger = logging.getLogger(__name__) # get a unique logger for the plugin and provide it internally self._bt_addr = bt_addr self._cycle = int(cycle) self._items = [] diff --git a/miflora/plugin.yaml b/miflora/plugin.yaml index 74fa5f1b8..409f6e7e9 100644 --- a/miflora/plugin.yaml +++ b/miflora/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: http://smarthomeng.de/user/plugins_doc/config/miflora.html # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1027133-plugin-miflora-mi-plant-flowers-tester-light-monitor - version: 1.3.0.5 # Plugin version + version: 1.3.0.4 # Plugin version sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance diff --git a/mvg_live/README.md b/mvg_live/README.md index 1a9f80aad..1b070777f 100644 --- a/mvg_live/README.md +++ b/mvg_live/README.md @@ -1,8 +1,6 @@ # MVG Live -## Description - -Retrieval of departure times of stations within the Münchner Verkehrsbetriebe (MVG) +Version 0.1 ## Requirements This plugin requires lib PyMVGLive. You can install this lib with: diff --git a/mvg_live/__init__.py b/mvg_live/__init__.py index 26a896170..ee459eb73 100644 --- a/mvg_live/__init__.py +++ b/mvg_live/__init__.py @@ -2,7 +2,7 @@ # ######################################################################### # Copyright 2017 René Frieß rene.friess(a)gmail.com -# Version 1.3.0.2 +# Version 1.3.0.1 ######################################################################### # # This file is part of SmartHomeNG. @@ -23,28 +23,19 @@ ######################################################################### import logging -try: - import MVGLive - REQUIRED_PACKAGE_IMPORTED = True -except: - REQUIRED_PACKAGE_IMPORTED = False -from lib.model.smartplugin import SmartPlugin +import MVGLive +from lib.model.smartplugin import SmartPlugin class MVG_Live(SmartPlugin): ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.3.0.2" + PLUGIN_VERSION = "1.3.0.1" def __init__(self, smarthome): """ Initializes the plugin """ self.logger = logging.getLogger(__name__) - if not REQUIRED_PACKAGE_IMPORTED: - self.logger.error("{}: Unable to import Python package 'MVGLive'".format(self.get_fullname())) - self._init_complete = False - return - self._sh = smarthome self._mvg_live = MVGLive.MVGLive() diff --git a/mvg_live/plugin.yaml b/mvg_live/plugin.yaml index ab7382893..2439f3e71 100755 --- a/mvg_live/plugin.yaml +++ b/mvg_live/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: http://smarthomeng.de/user/plugins_doc/config/mvg_live.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1108867-neues-plugin-mvg_live - version: 1.3.0.2 # Plugin version + version: 1.3.0.1 # Plugin version sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance diff --git a/nokia_health/__init__.py b/nokia_health/__init__.py index 43d327ed8..bc5320cfc 100644 --- a/nokia_health/__init__.py +++ b/nokia_health/__init__.py @@ -22,17 +22,14 @@ # ######################################################################### +import requests from lib.model.smartplugin import * -try: - from nokia import NokiaAuth, NokiaApi, NokiaCredentials - REQUIRED_PACKAGE_IMPORTED = True -except: - REQUIRED_PACKAGE_IMPORTED = False +from nokia import NokiaAuth, NokiaApi, NokiaCredentials class NokiaHealth(SmartPlugin): ALLOW_MULTIINSTANCE = True - PLUGIN_VERSION = "1.5.3" + PLUGIN_VERSION = "1.5.2" BASE_URL = "https://api.health.nokia.com/" ALLOWED_MEASURE_TYPES = [1, 4, 5, 6, 8, 11] @@ -40,11 +37,6 @@ class NokiaHealth(SmartPlugin): def __init__(self, smarthome, consumer_key, consumer_secret, access_token, access_token_secret, user_id, cycle=300): self.logger = logging.getLogger(__name__) - if not REQUIRED_PACKAGE_IMPORTED: - self.logger.error("{}: Unable to import Python package 'nokia'".format(self.get_fullname())) - self._init_complete = False - return - self._sh = smarthome self._consumer_key = consumer_key self._consumer_secret = consumer_secret diff --git a/nokia_health/plugin.yaml b/nokia_health/plugin.yaml index 7cd4ddfa0..f04458fac 100644 --- a/nokia_health/plugin.yaml +++ b/nokia_health/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: 'http://smarthomeng.de/user/plugins_doc/config/nokia_health.html' support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/1141179-nokia-health-plugin' - version: 1.5.3 # Plugin version + version: 1.5.2 # Plugin version sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance diff --git a/nuki/plugin.yaml b/nuki/plugin.yaml index 39d88d4f5..fe4c8810d 100755 --- a/nuki/plugin.yaml +++ b/nuki/plugin.yaml @@ -4,7 +4,7 @@ plugin: type: interface # plugin type (gateway, interface, protocol, system, web) description: de: 'Unterstützung für ein Nuki Smart-Lock' - en: 'Support for smart locks by Nuki' + en: '' maintainer: fuppy, pfischi # tester: # Who tests this plugin? # keywords: iot xyz diff --git a/odlinfo/__init__.py b/odlinfo/__init__.py index fa9a8fe20..3afd7fe4b 100644 --- a/odlinfo/__init__.py +++ b/odlinfo/__init__.py @@ -34,17 +34,12 @@ ######################################################################### import logging +import requests from lib.model.smartplugin import SmartPlugin -try: - import requests - from requests.auth import HTTPBasicAuth - REQUIRED_PACKAGE_IMPORTED = True -except: - REQUIRED_PACKAGE_IMPORTED = False - +from requests.auth import HTTPBasicAuth class ODLInfo(SmartPlugin): - PLUGIN_VERSION = "1.4.2" + PLUGIN_VERSION = "1.4.1" _base_url = 'https://odlinfo.bfs.de/daten/json/stamm.json' def __init__(self, sh, *args, **kwargs): @@ -54,10 +49,6 @@ def __init__(self, sh, *args, **kwargs): @param password: For accessing the ODLINFO API you need a personal password """ self.logger = logging.getLogger(__name__) - if not REQUIRED_PACKAGE_IMPORTED: - self.logger.error("{}: Unable to import Python package 'requests'".format(self.get_fullname())) - self._init_complete = False - return self._user = self.get_parameter_value('user') self._password = self.get_parameter_value('password') self._keys = ['ort', 'kenn', 'plz', 'status', 'kid', 'hoehe', 'lon', 'lat', 'mw'] diff --git a/odlinfo/plugin.yaml b/odlinfo/plugin.yaml index 68b893b88..3be7a2f28 100755 --- a/odlinfo/plugin.yaml +++ b/odlinfo/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: http://smarthomeng.de/user/plugins_doc/config/odlinfo.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/986480-odlinfo-plugin-für-strahlungsdaten - version: 1.4.2 # Plugin version + version: 1.4.1 # Plugin version sh_minversion: 1.4 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance diff --git a/openweathermap/README.md b/openweathermap/README.md index 8793113b0..bb7359a60 100644 --- a/openweathermap/README.md +++ b/openweathermap/README.md @@ -1,6 +1,6 @@ # OpenWeatherMap -#### Version 1.5.0.2 +#### Version 1.5.0.1 This plugins can be used retrieve weather information from OpenWeatherMap (https://openweathermap.org/). diff --git a/openweathermap/__init__.py b/openweathermap/__init__.py index 688079f66..b3510e186 100644 --- a/openweathermap/__init__.py +++ b/openweathermap/__init__.py @@ -2,7 +2,7 @@ # ######################################################################### # Copyright 2018 René Frieß rene.friess(a)gmail.com -# Version 1.5.0.2 +# Version 1.5.0.1 ######################################################################### # # This file is part of SmartHomeNG. @@ -23,11 +23,7 @@ ######################################################################### import logging -try: - import requests - REQUIRED_PACKAGE_IMPORTED = True -except: - REQUIRED_PACKAGE_IMPORTED = False +import requests import datetime import json from lib.module import Modules @@ -35,7 +31,7 @@ class OpenWeatherMap(SmartPlugin): - PLUGIN_VERSION = "1.5.0.2" + PLUGIN_VERSION = "1.5.0.1" _base_url = 'https://api.openweathermap.org/%s' _base_img_url = 'https://tile.openweathermap.org/map/%s/%s/%s/%s.png?appid=%s' @@ -47,10 +43,6 @@ def __init__(self, sh, *args, **kwargs): api key. For your own key register to https://creativecommons.tankerkoenig.de """ self.logger = logging.getLogger(__name__) - if not REQUIRED_PACKAGE_IMPORTED: - self.logger.error("{}: Unable to import Python package 'requests'".format(self.get_fullname())) - self._init_complete = False - return self._key = self.get_parameter_value('key') if self.get_parameter_value('latitude') != '' and self.get_parameter_value('longitude') != '': self._lat = self.get_parameter_value('latitude') diff --git a/openweathermap/plugin.yaml b/openweathermap/plugin.yaml index 6acd8cbbd..1d1dc48f7 100644 --- a/openweathermap/plugin.yaml +++ b/openweathermap/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: '' support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/1246998-support-thread-zum-openweathermap-plugin' keywords: weather - version: 1.5.0.2 # Plugin version + version: 1.5.0.1 # Plugin version sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance diff --git a/tankerkoenig/README.md b/tankerkoenig/README.md index 64ec13276..834258316 100644 --- a/tankerkoenig/README.md +++ b/tankerkoenig/README.md @@ -1,8 +1,6 @@ # TankerKoenig -## Description - -This plugin provides petrol station prices by the API of TankerKönig. Take care not to request the interface too often or for too many petrol stations. Please follow instructions given on https://creativecommons.tankerkoenig.de/#techInfo. +Version 0.1 ## Requirements diff --git a/tankerkoenig/__init__.py b/tankerkoenig/__init__.py index 1bc0378cb..0494f9b2b 100755 --- a/tankerkoenig/__init__.py +++ b/tankerkoenig/__init__.py @@ -23,18 +23,13 @@ ######################################################################### import logging -try: - import requests - REQUIRED_PACKAGE_IMPORTED = True -except: - REQUIRED_PACKAGE_IMPORTED = False - +import requests import json from lib.model.smartplugin import SmartPlugin class TankerKoenig(SmartPlugin): - PLUGIN_VERSION = "1.4.2" + PLUGIN_VERSION = "1.4.1" _base_url = 'https://creativecommons.tankerkoenig.de/json/' _detail_url_suffix = 'detail.php' _prices_url_suffix = 'prices.php' @@ -47,12 +42,6 @@ def __init__(self, sh, *args, **kwargs): api key. For your own key register to https://creativecommons.tankerkoenig.de """ self.logger = logging.getLogger(__name__) - - if not REQUIRED_PACKAGE_IMPORTED: - self.logger.error("{}: Unable to import Python package 'requests'".format(self.get_fullname())) - self._init_complete = False - return - self._apikey = self.get_parameter_value('apikey') self._session = requests.Session() diff --git a/tankerkoenig/plugin.yaml b/tankerkoenig/plugin.yaml index 068bf71f8..d156abfe2 100755 --- a/tankerkoenig/plugin.yaml +++ b/tankerkoenig/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: http://smarthomeng.de/user/plugins_doc/config/tankerkoenig.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/938924-benzinpreis-plugin keywords: petrol station, fuel prices, petrol prices - version: 1.4.2 # Plugin version + version: 1.4.1 # Plugin version sh_minversion: 1.4 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance diff --git a/traffic/README.md b/traffic/README.md index 99817d3d5..80f31a173 100644 --- a/traffic/README.md +++ b/traffic/README.md @@ -1,6 +1,6 @@ # Traffic -## Description +Version 0.1 This plugin provides functionality to query the Google Directions API for traffic / direction info. All mappings to items need to be done via your own logic. diff --git a/traffic/__init__.py b/traffic/__init__.py index 2e305c595..15261febb 100644 --- a/traffic/__init__.py +++ b/traffic/__init__.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 # ######################################################################### -# Copyright 2017-2018 René Frieß rene.friess(a)gmail.com -# Version 1.3.0.2 +# Copyright 2017 René Frieß rene.friess(a)gmail.com +# Version 1.3.0.1 ######################################################################### # # This file is part of SmartHomeNG. @@ -23,17 +23,12 @@ ######################################################################### import logging -try: - import requests - REQUIRED_PACKAGE_IMPORTED = True -except: - REQUIRED_PACKAGE_IMPORTED = False - +import requests from lib.model.smartplugin import SmartPlugin class Traffic(SmartPlugin): ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.3.0.2" + PLUGIN_VERSION = "1.3.0.1" _base_url = 'https://maps.googleapis.com/maps/api/directions/json' def __init__(self, smarthome, apikey, language='de'): @@ -44,10 +39,6 @@ def __init__(self, smarthome, apikey, language='de'): @param language: two char language code. default: de """ self.logger = logging.getLogger(__name__) - if not REQUIRED_PACKAGE_IMPORTED: - self.logger.error("{}: Unable to import Python package 'requests'".format(self.get_fullname())) - self._init_complete = False - return self._sh = smarthome self._apikey = apikey self._language = language diff --git a/traffic/plugin.yaml b/traffic/plugin.yaml index 6d6dfebfe..5672e4b96 100755 --- a/traffic/plugin.yaml +++ b/traffic/plugin.yaml @@ -11,7 +11,7 @@ plugin: documentation: http://smarthomeng.de/user/plugins_doc/config/traffic.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1048446-traffic-plugin-support-thread - version: 1.3.0.2 # Plugin version + version: 1.3.0.1 # Plugin version sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance From e6f8a5e1361ed8f8d647edefc0ad8182f23ef834 Mon Sep 17 00:00:00 2001 From: aschwith Date: Tue, 14 Aug 2018 21:30:07 +0200 Subject: [PATCH 104/705] Sonos: fix for duration offset --- sonos/__init__.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/sonos/__init__.py b/sonos/__init__.py index 22e7e7ea8..5742651f7 100755 --- a/sonos/__init__.py +++ b/sonos/__init__.py @@ -2141,11 +2141,11 @@ def sonos_playlists(self) -> None: for item in self.sonos_playlists_items: item(p_l, 'Sonos') - def _play_snippet(self, file_path: str, webservice_url: str, volume: int = -1, fade_in=False) -> None: + def _play_snippet(self, file_path: str, webservice_url: str, volume: int = -1, duration_offset: float = 0, fade_in=False) -> None: if not self._check_property(): return if not self.is_coordinator: - sonos_speaker[self.coordinator]._play_snippet(file_path, webservice_url, volume, fade_in) + sonos_speaker[self.coordinator]._play_snippet(file_path, webservice_url, volume, duration_offset, fade_in) else: with self._snippet_queue_lock: snap = None @@ -2155,7 +2155,8 @@ def _play_snippet(self, file_path: str, webservice_url: str, volume: int = -1, f volumes[member] = sonos_speaker[member].volume tag = TinyTag.get(file_path) - duration = int(round(tag.duration)) + self.__snippet_duration_offset + duration = round(tag.duration) + duration_offset + self._logger.debug("Sonos: TTS track duration offset is: {offset}s".format(offset=duration_offset)) self._logger.debug("Sonos: TTS track duration: {duration}s".format(duration=duration)) file_name = quote(os.path.split(file_path)[1]) snippet_url = "{url}/{file}".format(url=webservice_url, file=file_name) @@ -2195,12 +2196,12 @@ def _play_snippet(self, file_path: str, webservice_url: str, volume: int = -1, f else: sonos_speaker[member].set_volume(volumes[member], group_command=False) - def play_snippet(self, audio_file, local_webservice_path_snippet: str, webservice_url: str, volume: int = -1, + def play_snippet(self, audio_file, local_webservice_path_snippet: str, webservice_url: str, volume: int = -1, duration_offset: float = 0, fade_in=False) -> None: if not self._check_property(): return if not self.is_coordinator: - sonos_speaker[self.coordinator].play_snippet(audio_file, local_webservice_path_snippet, webservice_url, volume, + sonos_speaker[self.coordinator].play_snippet(audio_file, local_webservice_path_snippet, webservice_url, volume, duration_offset, fade_in) else: if "tinytag" not in sys.modules: @@ -2212,15 +2213,15 @@ def play_snippet(self, audio_file, local_webservice_path_snippet: str, webservic if not os.path.exists(file_path): self._logger.error("Sonos: Snippet file '{file_path}' does not exists.".format(file_path=file_path)) return - self._play_snippet(file_path, webservice_url, volume, fade_in) + self._play_snippet(file_path, webservice_url, volume, duration_offset, fade_in) - def play_tts(self, tts: str, tts_language: str, local_webservice_path: str, webservice_url: str, volume: int = -1, + def play_tts(self, tts: str, tts_language: str, local_webservice_path: str, webservice_url: str, volume: int = -1, duration_offset: float = 0, fade_in=False) -> None: if not self._check_property(): return if not self.is_coordinator: sonos_speaker[self.coordinator].play_tts(tts, tts_language, local_webservice_path, webservice_url, - volume, fade_in) + volume, duration_offset, fade_in) else: if "tinytag" not in sys.modules: self._logger.error("Sonos: TinyTag module not installed. Please install the module with 'sudo pip3 " @@ -2239,7 +2240,7 @@ def play_tts(self, tts: str, tts_language: str, local_webservice_path: str, webs else: self._logger.debug("Sonos: File {file} already exists. No TTS request necessary.".format( file=file_path)) - self._play_snippet(file_path, webservice_url, volume, fade_in) + self._play_snippet(file_path, webservice_url, volume, duration_offset, fade_in) def load_sonos_playlist(self, name: str, start: bool = False, clear_queue: bool = False, track: int = 0) -> None: """ @@ -2627,13 +2628,13 @@ def update_item(self, item: Item, caller: object = str, source: object = str, de volume = self._resolve_child_command_int(item, 'tts_volume', -1) fade_in = self._resolve_child_command_bool(item, 'tts_fade_in') sonos_speaker[uid].play_tts(item(), language, self._local_webservice_path, self._webservice_url, - volume, fade_in) + volume, self._snippet_duration_offset, fade_in) if command == 'play_snippet': if item() == "": return volume = self._resolve_child_command_int(item, 'snippet_volume', -1) fade_in = self._resolve_child_command_bool(item, 'snippet_fade_in') - sonos_speaker[uid].play_snippet(item(), self._local_webservice_path_snippet, self._webservice_url, volume, + sonos_speaker[uid].play_snippet(item(), self._local_webservice_path_snippet, self._webservice_url, volume, self._snippet_duration_offset, fade_in) def _resolve_child_command_str(self, item: Item, child_command, default_value="") -> str: From 92d3d56baa969e095dd76b504dac9f2ccc6f3e92 Mon Sep 17 00:00:00 2001 From: Foxi352 Date: Wed, 15 Aug 2018 10:32:28 +0200 Subject: [PATCH 105/705] Backend: Added missing french translations --- backend/locale/fr.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/backend/locale/fr.json b/backend/locale/fr.json index ba881a4a3..a12d63264 100755 --- a/backend/locale/fr.json +++ b/backend/locale/fr.json @@ -111,18 +111,18 @@ "Ergebnis: Aufbereitetes .YAML Format": "Résultat: Format .YAML édité", "Ergebnis: Aufbereitet als Python Source Code": "Résultat: Edité en format code source Python", "Python Code Ausgabe": "Sortie code Python", - "Pakete für den Bau der Dokumentation": "Packages for Building the Documentation", - "Pakete für die Testsuite": "Packages for the Test Suite", + "Pakete für den Bau der Dokumentation": "Paquets pour le génération de la documentation:", + "Pakete für die Testsuite": "Paquets pour la suite de tests", "Nr.": "N°", "Type": "Type", - "Configname": "", + "Configname": "Nom configuré", "Plugin": "Extension", "Classname": "Nom de la classe", "Instanz": "Instance", "Version": "Version", "Mehrere Instanzen möglich": "Supporte plusieurs instances", - "Web Interface": "", + "Web Interface": "Interface web", "ja": "oui", "Ja": "Oui", "nein": "non", @@ -184,7 +184,7 @@ "Systemeigenschaften": "Propriétés du système", "Sie verlieren ggf. Ihre letzten, nicht gespeicherten Eingaben!": "Si vous ne sauvegardez pas vous perdez toutes modifications!", "Wollen Sie die Logik" : "Voulez-vous vraiment supprimer cette logique", - "Wollen Sie die selektierten Dateien wirklich löschen?" : "", + "Wollen Sie die selektierten Dateien wirklich löschen?" : "Voulez-vous vraiment supprimer tous les fichiers choisis ?", "wirklich löschen?" : "?", "Neue Logik erstellen": "Créer nouvelle logique", "Angaben für die Erzeugung einer neuen Python Logik": "Donées de la nouvelle logique", @@ -206,9 +206,9 @@ "Version nicht zulässig!": "Version non autorisée", "Schlüsselwörter": "Mots-clés", - "Entwicklungs-Daten": "", - "Plugin spezifische Parameter": "", - "Plugin spezifische Item Attribute": "", + "Entwicklungs-Daten": "Données de développement", + "Plugin spezifische Parameter": "Paramètres spécifiques à l'extension", + "Plugin spezifische Item Attribute": "Attributs d'objets spécifiques à l'extension", "_items": { "path": "Chemin", @@ -273,14 +273,14 @@ "Speichern_und_Neu_Laden" : "Sauvegarder et recharger", "Speichern_Neu_Laden_und_Triggern": "Sauvegarder, recharger et déclencher", "Löschen" : "Supprimer", - "Alle ausgewählten löschen" : "", + "Alle ausgewählten löschen" : "Supprimer tous les éléments choisis", "Konvertieren": "Convertir", "Neue Blockly Logik": "Nouvelle logique 'Blockly'", "Neue Python Logik": "Nouvelle logique 'Python'", "Erstellen": "Créer", "Entladen": "Décharger", - "Starten": "", - "Stoppen": "", + "Starten": "Démarrer", + "Stoppen": "Arrêter", "Nach unten scrollen": "Défiler vers le bas" }, From e32069fbe458ee1cdf22dba015ba7e8b93949419 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 16 Aug 2018 07:57:24 +0200 Subject: [PATCH 106/705] Simulation: - new parameter handling - fixed if statement for empty callers list (all callers are accepted) --- simulation/__init__.py | 14 ++++++++------ simulation/plugin.yaml | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/simulation/__init__.py b/simulation/__init__.py index 940306901..06339580e 100644 --- a/simulation/__init__.py +++ b/simulation/__init__.py @@ -47,18 +47,20 @@ class Simulation(SmartPlugin): ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.5.0.6" + PLUGIN_VERSION = "1.5.0.7" - def __init__(self, smarthome, data_file, callers=None): + def __init__(self, sh, *args, **kwargs): self.logger = logging.getLogger(__name__) self.logger.info('Init Simulation release 1.5.0.6') - self._sh = smarthome self.shtime = Shtime.get_instance() - self._datafile = data_file + self._datafile = self.get_parameter_value('data_file') self.lastday = '' self.items = Items.get_instance() self.scheduler = Scheduler.get_instance() - self._callers = callers + if len(self.get_parameter_value('callers')) == 0: + self._callers = None + else: + self._callers = self.get_parameter_value('callers') self._items = [] self.scheduler_add('midnight', self._midnight, cron='0 0 * *', prio=3) @@ -107,7 +109,7 @@ def parse_logic(self, logic): # Callback. Writes the event to the file def update_item(self, item, caller=None, source=None, dest=None): - if (item.conf['sim'] == 'track') and (self.state() == 2) and (self._callers and caller in self._callers): + if (item.conf['sim'] == 'track') and (self.state() == 2) and (self._callers is None or caller in self._callers): now = self.shtime.now() day = now.day self.file.write(now.strftime('%a;%H:%M:%S')) diff --git a/simulation/plugin.yaml b/simulation/plugin.yaml index e32ef412a..4934b889b 100755 --- a/simulation/plugin.yaml +++ b/simulation/plugin.yaml @@ -10,7 +10,7 @@ plugin: # keywords: iot xyz documentation: https://www.smarthomeng.de/developer/plugins/simulation/README.html # url of documentation (wiki) page support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/841097-anwesenheitssimulation-0-1' - version: 1.5.0.6 # Plugin version + version: 1.5.0.7 # Plugin version sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance @@ -25,7 +25,7 @@ parameters: de: 'Voller Pfad zum Datenfile (Textdatei).' en: 'Full path to data file (text file).' callers: - type: str + type: list(str) mandatory: False description: de: '(optional) Liste von Event-Sourcen, um Events aufzuzeichnen. Wenn ein Item geändert wird, werden nur From ba66aa71b5119c1e7dbb24681318fd4f536e72f5 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 16 Aug 2018 07:58:18 +0200 Subject: [PATCH 107/705] Simulation added version information --- simulation/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/simulation/__init__.py b/simulation/__init__.py index 06339580e..18dc34e75 100644 --- a/simulation/__init__.py +++ b/simulation/__init__.py @@ -33,6 +33,7 @@ # corrected serious bug in compare entry with NextDay # 0.5 Added feature to select which caller is written to the simulation file # 0.6 Added WebGUI and Clear Data File function +# 0.7 Implemented new way of parameter handling (taken from plugin.yaml). Fixed IF statement for empty caller list # ########################################################################## From 50e7ca81ddff85d1cc81dddfd45d9422c5f27a03 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 16 Aug 2018 09:56:05 +0200 Subject: [PATCH 108/705] Simulation: added more info to webif --- simulation/locale.yaml | 6 ++++++ simulation/webif/templates/index.html | 27 +++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/simulation/locale.yaml b/simulation/locale.yaml index e8d8d3eaf..9114eb9d9 100644 --- a/simulation/locale.yaml +++ b/simulation/locale.yaml @@ -6,6 +6,12 @@ plugin_translations: en: 'Simulation Plugin Items' 'startrecord Scheduler': {'de': 'startrecord Scheduler', 'en': 'startrecord Scheduler'} 'simulate Scheduler': {'de': 'simulate Scheduler', 'en': 'simulate Scheduler'} + 'State': {'de': 'Status', 'en': 'Stop'} + 'Stop': {'de': 'Stop', 'en': 'Stop'} + 'Standby': {'de': 'Standby', 'en': 'Standby'} + 'Record': {'de': 'Record', 'en': 'Record'} + 'Play': {'de': 'Play', 'en': 'Play'} + 'Days': {'de': 'Tage', 'en': 'Days'} 'Last Day': de: 'Letzter Tag' en: 'Last Day' diff --git a/simulation/webif/templates/index.html b/simulation/webif/templates/index.html index a0b9a7905..a3fb2087b 100644 --- a/simulation/webif/templates/index.html +++ b/simulation/webif/templates/index.html @@ -25,6 +25,17 @@
{{ simulate.strftime('%d.%m.%Y %H:%M:%S') }}
{{ _('State') }}{% for item in p.get_items() %} + {% if item.conf['sim'] == 'state' %} + {% if item() == 0 %}{{ _('Stop') }}{% endif %} + {% if item() == 1 %}{{ _('Standby') }}{% endif %} + {% if item() == 2 %}{{ _('Record') }}{% endif %} + {% if item() == 4 %}{{ _('Play') }}{% endif %} + {% endif %} + {% endfor %}
{% endblock headtable %} @@ -67,9 +78,21 @@
{{ _('Simulation Plugin Items') }} ({{ p.get_items()|length }})
{% for item in p.get_items() %} - {{ item.id() }} + + {% if item.conf['sim'] in ['state','tank','message','control'] %}{% endif %} + {{ item.id() }} + {% if item.conf['sim'] in ['state','tank','message','control'] %}{% endif %} + {{ item.type() }} - {{ item() }} + {{ item() }} + {% if item.conf['sim'] == 'state' %} + {% if item() == 0 %}({{ _('Stop') }}){% endif %} + {% if item() == 1 %}({{ _('Standby') }}){% endif %} + {% if item() == 2 %}({{ _('Record') }}){% endif %} + {% if item() == 4 %}({{ _('Play') }}){% endif %} + {% elif item.conf['sim'] == 'tank' %} + ({{ _('Days') }}) + {% endif %} {{ item.conf['sim'] }} {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} {{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }} From a82ea0210e9c261a36cfadf3bd78fc288b94fc69 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 16 Aug 2018 09:59:28 +0200 Subject: [PATCH 109/705] Simulation: layout correction --- simulation/webif/templates/index.html | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/simulation/webif/templates/index.html b/simulation/webif/templates/index.html index a3fb2087b..dbfbdbd55 100644 --- a/simulation/webif/templates/index.html +++ b/simulation/webif/templates/index.html @@ -9,32 +9,33 @@ {{ _('Datendatei') }}:
{{p._datafile}} + {{ _('State') }} + {% for item in p.get_items() %} + {% if item.conf['sim'] == 'state' %} + {% if item() == 0 %}{{ _('Stop') }}{% endif %} + {% if item() == 1 %}{{ _('Standby') }}{% endif %} + {% if item() == 2 %}{{ _('Record') }}{% endif %} + {% if item() == 4 %}{{ _('Play') }}{% endif %} + {% endif %} + {% endfor %} {{ _('Last Day') }} - {% if p.lastday == '' %}-{% else %}{{ p.lastday }}{% endif %} + {% if p.lastday == '' %}-{% else %}{{ p.lastday }}{% endif %} {% if startRecord %} {{ _('startrecord Scheduler') }} - {{ startRecord.strftime('%d.%m.%Y %H:%M:%S') }} + {{ startRecord.strftime('%d.%m.%Y %H:%M:%S') }} {% elif simulate %} {{ _('simulate Scheduler') }} - {{ simulate.strftime('%d.%m.%Y %H:%M:%S') }} + {{ simulate.strftime('%d.%m.%Y %H:%M:%S') }} {% endif %} - {{ _('State') }} - {% for item in p.get_items() %} - {% if item.conf['sim'] == 'state' %} - {% if item() == 0 %}{{ _('Stop') }}{% endif %} - {% if item() == 1 %}{{ _('Standby') }}{% endif %} - {% if item() == 2 %}{{ _('Record') }}{% endif %} - {% if item() == 4 %}{{ _('Play') }}{% endif %} - {% endif %} - {% endfor %} + From 905fc3e83c33c8d893c8242fe67470fa784b97ce Mon Sep 17 00:00:00 2001 From: aschwith Date: Thu, 16 Aug 2018 20:40:12 +0200 Subject: [PATCH 110/705] Enocean: reworked the Readme, added webinterface to documentation --- enocean/README.md | 98 +++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/enocean/README.md b/enocean/README.md index 481713647..d716f9602 100644 --- a/enocean/README.md +++ b/enocean/README.md @@ -1,19 +1,17 @@ # EnOcean ## Description -This plugin allows you to interact with EnOcean devices via SmarthomeNG and SmartVisu. - -This plugin is still under development. +This plugin adds EnOcean support to SmarthomeNG. ## Support -If you have special hardware not supported yet please feel free to improve and contribute! +If you have special hardware not supported yet, please feel free to improve and contribute! ## Version / Change History Version: 1.3.4 Change History: currently not maintained. -## Requirements +## Hardware Requirements For use of this plugin you need an EnOcean radio transceiver module like: - Fam4Pi - USB 300 @@ -30,26 +28,34 @@ Add the following lines to your `plugin.yaml`: ##### serialport -You have to specify the `serialport` to your port name of your EnOcean-adpater. -Creating **udev-rules** for the EnOcean-adapter is recommend, when using different uart devices. +You have to specify the `serialport` to your port name of your EnOcean adapter. +UNder Linux, the creation of a specific **udev-rules** for the EnOcean adapter is recommended, when using different Uart devices. ##### tx_id -The specification of the EnOcean `tx_id` is optional **but** mandatory for sending control commands from the enocean-adapter to an EnOcean device. -It is defined as a 8-digit hex value. +The specification of the EnOcean `tx_id` is optional **but** mandatory for sending control commands from smarthomeNG to EnOcean devices. +It is defined as a 8-digit hexadecimal value. -When controlling multiple devices, it is recommended to use the EnOcean-adapter's Base-ID (not Unique-ID or Chip-ID) as transmitting ID. +When controlling multiple devices, it is recommended to use the EnOcean adapter's Base-ID (not Unique-ID or Chip-ID) as transmitting ID. For further information regarding the difference between Base-ID and Chip-ID, see [Knowledge Base](https://www.enocean.com/en/knowledge-base-doku/enoceansystemspecification%3Aissue%3Awhat_is_a_base_id/) With the specification of the Base-ID, 128 different transmit ID's are available, ranging between Base-ID and Base-ID + 127. -##### How-To Get the ID of an EnOcean device +##### How-To Get the Base-ID of the EnOcean adapter +There are two different ways of reading the EnOcean adapter's Base ID: +a) Via the Enocean Plugin Webinterface +b) Via the logfiles created by the Enocean plugin. + +For a) +1. Open the plugin's webinterface under: http://localip:8383/enocean/ +2. Read the ChipBaseID, which is displayed on the upper right side. +3. Insert the Base-ID in the plugin.yaml file. -1. reboot the pi or restart the smarthome (`sudo reboot` or `sudo systemctl restart smarthome`) -2. wait some time for comming up of the service -3. have a look into the log file an look for `enocean: Base ID = 0xYYYYZZZZ` -4. now you have the right Base-ID and you can place it into the plugin.yaml file. -5. alternating you will also find the EnOcean-adapter's Unique-ID / Chip-ID in the log-file. +For b) +1. Reboot the pi or restart the SmarthomeNG (`sudo reboot` or `sudo systemctl restart smarthome`) +2. Wait until all plugins came up +3. Open the logfile (Enocean or general smarthomeNG logfile) and search for `enocean: Base ID = 0xYYYYZZZZ` +4. Insert the Base-ID in the plugin.yaml file. #### Example plugin.yaml ```yaml @@ -63,14 +69,17 @@ enocean: ### Items #### enocean_rx_id, enocean_rx_eep and enocean_tx_id_offset -An EnOcean item must specify at minimum an `enocean_rx_id` (EnOcean Identification Number (hex code)) and an `enocean_rx_eep` (EnOcean Equipment Profile). -Send items additionally hold an `enocean_tx_id_offset`. +An EnOcean item (sensor or actor) must specify at minimum an `enocean_rx_id` (EnOcean Identification Number (hex code)) and an `enocean_rx_eep` (EnOcean Equipment Profile). +Transmitting items additionally need an `enocean_tx_id_offset`. + +#### enocean_rx_eep +The EEP [EnOcean Equippment Profile] defines the message type that is broadcast by the Enocean device. EEPs are standardized by Enocean. More information can be found under http://www.enocean-alliance.org/eep/ #### enocean_rx_key -The status of an EnOcean device can be read by using the shortcut names of the Button which should be defined under `enocean_rx_key`. -Therefore see [EnOcean Equippment Profile](http://www.enocean-alliance.org/eep/) +Generally, EnOcean devices broadcast more than just one information. These can be linked to different smarthomeNG items via so called shortcut key names (enocean_rx_key). See the list below for different examples of key names. -The following example explaines the button shortcut and its meaning for a rocker/switch with two rocker (EEP-Profile: F6_02_01 or F6_02_02). + +The following example outlines the available button shortcuts and their meaning for a rocker/switch with two rocker (EEP-Profile: F6_02_01 or F6_02_02). ``` AI = left rocker down @@ -79,7 +88,7 @@ BI = right rocker down B0 = right rocker up ``` -The following example explaines the button shortcut and its meaning for a rocker/switch with two rocker and 6 available combinations (EEP F6_02_03). +The following example outlines the button shortcuts and its meaning for a rocker/switch with two rocker and 6 available combinations (EEP F6_02_03). ``` AI = left rocker down @@ -98,7 +107,7 @@ STATUS = handle_status ### items.yaml #### Attributes -For attributes have a look to the examples. +For attributes have a look at the examples. #### Example item.yaml ``` @@ -362,7 +371,7 @@ The following status EEPs are supported: * F6_02_03 2-Button-Rocker, Status feedback from manual buttons on different actors, e.g. Eltako FT55, FSUD-230, FSVA-230V, FSB61NP-230V or Gira switches. * F6_10_00 Mechanical Handle (value: 0(closed), 1(open), 2(tilted) ``` -A complete list of available EEPs is documented at [EnOcean Alliance](http://www.enocean-alliance.org/eep/) +A complete list of available EEPs is accessible at [EnOcean Alliance](http://www.enocean-alliance.org/eep/) ### Send commands: Tx EEPs @@ -375,34 +384,30 @@ A complete list of available EEPs is documented at [EnOcean Alliance](http://www * D2_01_07 Simple electronic switch ``` -The optional ref_level parameter defines default dim value when dimmer is switched on via on command. +The optional ref_level parameter defines default dim value when dimmer is switched on via the regular "on"" command. ## Functions ### Learning Mode -Devices that shall receive commands from the smarthome plugin, i.e. the encoean gateway must be subscribed first. -Generally follow the teach in procedure as described by enocean: -1. set the EnOcean device/actor into learn mode -2. send the learn telegram -3. exit the learn mode of the actor - -Usually, the EnOcean device, e.g. enocean actor, is set to teach in mode. -See the manual of the respective device for further information. -Once being in teach in mode, trigger a learn-in command from smarthomeNG. +Devices that shall receive commands from the SmarthomeNG plugin must be subscribed (tought-in) first. +Generally follow the teach-in procedure as described by EnOcean: +1. Set the EnOcean device/actor into learn mode. See the manual of the respective EnOcean device for detailed information on how to enter learn mode. +2. While being in learn mode, trigger the learn telegram from SmarthomeNG (via webinterface or via interactive SmarthomeNG console) +3. Exit the learn mode of the actor -In order to send a special learning message, start smarthome with the interactive console: +The SmarthomeNG interactive console can be reached via: ```bash cd /usr/local/smarthome/bin sudo systemctl stop smarthome sudo ./smarthome.py -i ``` - -Then use one of the following learn-in commands, depending on your EnOcean device: - +The learn message is issued by the following command: ```python sh.enocean.send_learn_protocol(id_offset, device) ``` +Then teach-in commands vary for different EnOcean sensor/actors. The following classes are currently supported: + With device are different actuators defined: - 10: Eltako Switch FSR61, Eltako FSVA-230V @@ -422,17 +427,12 @@ Where `id_offset`, range (0-127), specifies the sending ID-offset with respect t Later, the ID-offset is specified in the for every outgoing send command, see the examples above. Use different ID-offsets for different groups of actors. -After complete the teach-in procedure, leave the interactive console by `STRG+C` and add the applied id_offset to the respective enocean send item (enocean_tx_id_offset = ID_Offset). - +After complete the teach-in procedure, leave the interactive console by `STRG+C` and add the applied id_offset to the respective EnOcean send item (enocean_tx_id_offset = ID_Offset). ### UTE teach-in -UTE does mean "Universal Uni- and Bidirectional Teach in". -When activated on EnOcean device the device will send a `D4` teach in request. An automatic answer within 500 ms is expected. -To do so enable the UTE learnmode prior to the activation on the device: Start smarthome with the interactive console - see above. - -`sh.enocean.start_UTE_learnmode(ID_Offset)` - -The device will be teached in and the learn mode will be ended automatically - -That's it! +UTE stands for "Universal Uni- and Bidirectional Teach in". +When being activated on an EnOcean device the device will send a `D4` teach-in request. SmarthomeNG will answer within 500 ms with a telegram to complete the teach-in process. +To do so enable the UTE learn mode prior to the activation on the device. Again, enabling the UTE mode can be achieved via +a) The plugin webinterface +b) SmarthomeNG's interactive console - see above - and the following command `sh.enocean.start_UTE_learnmode(ID_Offset)` From 0c1e73eed31bb357f0b855ac159c0f64f6f01dbc Mon Sep 17 00:00:00 2001 From: aschwith Date: Thu, 16 Aug 2018 20:42:14 +0200 Subject: [PATCH 111/705] Sonos: added check for external python packages (thx to Msinn) --- sonos/__init__.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/sonos/__init__.py b/sonos/__init__.py index 5742651f7..4d5477501 100755 --- a/sonos/__init__.py +++ b/sonos/__init__.py @@ -35,10 +35,16 @@ from queue import Empty import sys from urllib.parse import unquote -import requests -import xmltodict -from requests.utils import quote -from tinytag import TinyTag + +try: + import requests + import xmltodict + from requests.utils import quote + from tinytag import TinyTag + REQUIRED_PACKAGE_IMPORTED = True +except: + REQUIRED_PACKAGE_IMPORTED = False + from plugins.sonos.soco.exceptions import SoCoUPnPException from plugins.sonos.soco.music_services import MusicService from lib.item import Item @@ -2299,6 +2305,11 @@ def __init__(self, sh, tts=False, local_webservice_path=None, local_webservice_p self._local_webservice_path = local_webservice_path self._snippet_duration_offset = float(snippet_duration_offset) + # Exit if the required package(s) could not be imported + if not REQUIRED_PACKAGE_IMPORTED: + self._logger.error("{}: Unable to import required external python packages. Please install.".format(self.get_fullname())) + return + # see documentation: if no exclusive snippet path is set, we use the global one if local_webservice_path_snippet is None: self._local_webservice_path_snippet = self._local_webservice_path From 7b22a78a4369b5530c52e9a35ce3a800306c7112 Mon Sep 17 00:00:00 2001 From: Foxi352 Date: Mon, 20 Aug 2018 10:03:12 +0200 Subject: [PATCH 112/705] French translation: Moved 'Logfile speichern' into correct section --- backend/locale/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/locale/fr.json b/backend/locale/fr.json index a12d63264..e65c5560b 100755 --- a/backend/locale/fr.json +++ b/backend/locale/fr.json @@ -88,7 +88,6 @@ "Dienst für die KNX Unterstützung": "Service pour le support du KNX", "Nicht aktiv": "Inactif", "Sprache des Backends": "Langue du backend", - "Logfile speichern": "Sauvegarder fichier journal", "Logfile ansehen": "Afficher journal", "Logger ansehen": "Afficher journalisateurs", "Datenbank-Dump": "Dump de la base de données", @@ -269,6 +268,7 @@ "Änderungen verwerfen" : "Annuler modifications", "Blöcke speichern" : "Enregistrer les blocs", "Beenden" : "Terminer", + "Logfile speichern": "Sauvegarder fichier journal", "Speichern" : "Sauvegarder", "Speichern_und_Neu_Laden" : "Sauvegarder et recharger", "Speichern_Neu_Laden_und_Triggern": "Sauvegarder, recharger et déclencher", From 9dec67bc528c3260fffeab40aaa1be3732c1dc69 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Tue, 21 Aug 2018 14:44:23 +0200 Subject: [PATCH 113/705] DarkSky: fix for parsing warnings --- darksky/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/darksky/__init__.py b/darksky/__init__.py index 28633c157..7adee84e9 100644 --- a/darksky/__init__.py +++ b/darksky/__init__.py @@ -108,7 +108,10 @@ def _update(self): alerts_string = alerts_string + alerts_string_wrk wrk = alerts_string else: - wrk = [] + if s == "alerts_string": + wrk = '' + else: + wrk = [] else: while True: if (len(sp) == 0) or (wrk is None): From 8e8af444f939c12f6d19620e9de48c262afd7541 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 22 Aug 2018 08:16:41 +0200 Subject: [PATCH 114/705] AVDevice: upgraded to Items API to remove deprecated warnings --- avdevice/__init__.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/avdevice/__init__.py b/avdevice/__init__.py index 1f71cf3fc..57cad023d 100755 --- a/avdevice/__init__.py +++ b/avdevice/__init__.py @@ -25,6 +25,7 @@ import logging from lib.model.smartplugin import SmartPlugin +from lib.item import Items import io import time import re @@ -73,6 +74,7 @@ def __init__(self, smarthome, autoreconnect=False, update_exclude='', statusquery=True): + self.itemsApi = Items.get_instance() self.logger = logging.getLogger(__name__) self._sh = smarthome self.alive = False @@ -191,7 +193,7 @@ def _resetitem(self, founditem): "Resetting {}: Resetting nothing because command is query command only.".format(self._name)) return None try: - founditem = self._sh.return_item(founditem) + founditem = self.itemsApi.return_item(founditem) except Exception as err: self.logger.debug("Resetting {}: {} is no valid item. Message: {}.".format(self._name, founditem, err)) return None @@ -876,7 +878,7 @@ def run(self): self.logger.log(VERBOSE1, "Initializing {}: Speaker Items: {}".format(self._name, self._items_speakers)) try: try: - self._dependson = self._sh.return_item(self._dependson) + self._dependson = self.itemsApi.return_item(self._dependson) self.logger.debug("Initializing {}: Dependson Item: {}.".format(self._name, self._dependson)) except Exception: self._dependson = None @@ -1300,7 +1302,7 @@ def _checkdependency(self, dep_function, dep_type): else: depending = True try: - item = self._sh.return_item(dep_function).id() + item = self.itemsApi.return_item(dep_function).id() except Exception: item = dep_function.id() if not item == self._dependson.id(): From 2c42913c7f877cf1077638565390f420bda358bb Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 22 Aug 2018 08:21:33 +0200 Subject: [PATCH 115/705] NUKI: using scheduler_add of smartplugin now --- nuki/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/nuki/__init__.py b/nuki/__init__.py index a52a57b33..02fc0b16d 100644 --- a/nuki/__init__.py +++ b/nuki/__init__.py @@ -110,8 +110,9 @@ def __init__(self, sh, bridge_ip, bridge_port, bridge_api_token, bridge_callback def run(self): self._clear_callbacks() - self._sh.scheduler.add("nuki_scheduler", self._scheduler_job, prio=3, cron=None, cycle=300, value=None, + self.scheduler_add(__name__, self._scheduler_job, prio=3, cron=None, cycle=300, value=None, offset=None, next=None) + self.alive = True def _scheduler_job(self): From 425b52239fcc7ccee32718be946ef8c52c3c5d6f Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 22 Aug 2018 10:33:11 +0200 Subject: [PATCH 116/705] NUKI: upgraded version --- nuki/__init__.py | 2 +- nuki/plugin.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nuki/__init__.py b/nuki/__init__.py index 02fc0b16d..913e6f50c 100644 --- a/nuki/__init__.py +++ b/nuki/__init__.py @@ -67,7 +67,7 @@ def handle_connection(self): class Nuki(SmartPlugin): - PLUGIN_VERSION = "1.3.0.1" + PLUGIN_VERSION = "1.4.0.2" ALLOW_MULTIINSTANCE = False def __init__(self, sh, bridge_ip, bridge_port, bridge_api_token, bridge_callback_ip=None, diff --git a/nuki/plugin.yaml b/nuki/plugin.yaml index fe4c8810d..842e7ab3c 100755 --- a/nuki/plugin.yaml +++ b/nuki/plugin.yaml @@ -11,7 +11,7 @@ plugin: # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1052437-nuki-smartlock-plugin-support-thread - version: 1.3.0.1 # Plugin version + version: 1.4.0.2 # Plugin version sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance From 235d101d8effaf84fe6b5b572e6b7149eec905d0 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 22 Aug 2018 13:16:55 +0200 Subject: [PATCH 117/705] NUKI: added info to plugin.yaml, upgraded version, added "get_parameter", removed self.sh --- nuki/__init__.py | 35 ++++++++++++----------- nuki/plugin.yaml | 73 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 88 insertions(+), 20 deletions(-) diff --git a/nuki/__init__.py b/nuki/__init__.py index 913e6f50c..711706641 100644 --- a/nuki/__init__.py +++ b/nuki/__init__.py @@ -32,6 +32,7 @@ nuki_battery_items = {} paired_nukis = [] + class NukiTCPDispatcher(lib.connection.Server): def __init__(self, ip, port): self._logger = logging.getLogger(__name__) @@ -66,27 +67,25 @@ def handle_connection(self): class Nuki(SmartPlugin): - - PLUGIN_VERSION = "1.4.0.2" + PLUGIN_VERSION = "1.5.0.3" ALLOW_MULTIINSTANCE = False - def __init__(self, sh, bridge_ip, bridge_port, bridge_api_token, bridge_callback_ip=None, - bridge_callback_port=8090, protocol='http'): + def __init__(self, sh, *args, **kwargs): global paired_nukis global nuki_event_items global nuki_action_items global nuki_battery_items self._logger = logging.getLogger(__name__) - self._sh = sh - self._base_url = protocol + '://' + bridge_ip + ":" + bridge_port + '/' - self._token = bridge_api_token - self._callback_ip = bridge_callback_ip - self._callback_port = bridge_callback_port + self._base_url = self.get_parameter_value('protocol') + '://' + self.get_parameter_value( + 'bridge_ip') + ":" + self.get_parameter_value('bridge_port') + '/' + self._token = self.get_parameter_value('bridge_api_token') + self._callback_ip = self.get_parameter_value('bridge_callback_ip') + self._callback_port = self.get_parameter_value('bridge_callback_port') self._action = '' self._noWait = '' - if self._callback_ip is None: + if self._callback_ip is None or self._callback_ip in ['0.0.0.0', '']: self._callback_ip = get_lan_ip() if not self._callback_ip: @@ -101,17 +100,17 @@ def __init__(self, sh, bridge_ip, bridge_port, bridge_api_token, bridge_callback NukiTCPDispatcher(self._callback_ip, self._callback_port) - self._lockActions = [1, # unlock - 2, # lock - 3, # unlatch - 4, # lockAndGo - 5, # lockAndGoWithUnlatch + self._lockActions = [1, # unlock + 2, # lock + 3, # unlatch + 4, # lockAndGo + 5, # lockAndGoWithUnlatch ] def run(self): self._clear_callbacks() self.scheduler_add(__name__, self._scheduler_job, prio=3, cron=None, cycle=300, value=None, - offset=None, next=None) + offset=None, next=None) self.alive = True @@ -190,7 +189,8 @@ def _get_paired_nukis(self): return for nuki in response: paired_nukis.append(nuki['nukiId']) - self._logger.info('Nuki: Paired Nuki Lock found: {name} - {id}'.format(name=nuki['name'], id=nuki['nukiId'])) + self._logger.info( + 'Nuki: Paired Nuki Lock found: {name} - {id}'.format(name=nuki['name'], id=nuki['nukiId'])) self._logger.debug(paired_nukis) def _clear_callbacks(self): @@ -255,6 +255,7 @@ def _api_call(self, base_url, endpoint=None, nuki_id=None, token=None, action=No except Exception as ex: self._logger.error(ex) + ####################################################################### # UTIL FUNCTION ####################################################################### diff --git a/nuki/plugin.yaml b/nuki/plugin.yaml index 842e7ab3c..d6e20ff9e 100755 --- a/nuki/plugin.yaml +++ b/nuki/plugin.yaml @@ -11,15 +11,82 @@ plugin: # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1052437-nuki-smartlock-plugin-support-thread - version: 1.4.0.2 # Plugin version - sh_minversion: 1.3 # minimum shNG version to use this plugin + version: 1.5.0.3 # Plugin version + sh_minversion: 1.5 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance classname: Nuki # class containing the plugin parameters: # Definition of parameters to be configured in etc/plugin.yaml - + bridge_ip: + type: ip + mandatory: True + description: + de: 'IP-Adresse der NUKI Bridge.' + en: 'IP address of the NUKI Bridge.' + + bridge_port: + type: str + mandatory: True + description: + de: 'Portnummer der NUKI Bridge.' + en: 'Port number of the NUKI Bridge.' + + bridge_api_token: + type: str + mandatory: True + description: + de: 'Token für die Authentifizierung mit der API der NUKI Bridge.' + en: 'Token for authentication with the API of the NUKI Bridge.' + + bridge_callback_ip: + type: ip + mandatory: False + description: + de: '(optional) IP Adresse, die die Callbacks der NUKI Bridge verarbeitet. Default: Lokale IP Adresse.' + en: '(optional) IP address of the TCP dispatcher which is handling the Bridge callback requests. By default, the local IP address is used.' + + bridge_callback_port: + type: int + mandatory: False + default: 8090 + description: + de: 'Port, über den die Callbacks der NUKI Bridge verarbeitet werden sollen. Default: 8090.' + en: 'Port for the callbacks from NUK Bridge. Default: 8090.' + + protocol: + type: str + mandatory: False + default: 'http' + description: + de: '(optional) Zu verwendendes Protokoll für die Kommunikaton mit der NUKI Bridge. Default: http.' + en: '(optional) Protocol for communication with NUKE bridge. Default http.' + + item_attributes: # Definition of item attributes defined by this plugin + nuki_id: + type: str + mandatory: True + description: + de: 'Dieses Attribut weist das Item dem jeweiligen NUKI Smart Lock zu. Die `nuki_id` kann entweder über die + REST API der NUKI Bridget (siehe Dokumentation)herausgefunden werden, oder durch Neustart von SmartHomeNG mit + dem konfigurierten NUKI Plugin. Der `name` und die `nuki_id` werden in das jeweilige Logfile geschrieben.' + en: 'This attribute connects the related item with the corresponding Nuki Smart Lock. + The `nuki_id` can be figured out via the REST API of the Nuki Bridge (see API documentation) or by just (re)starting + SmarthomeNG with the configured Nuki plugin. The `name` and the `nuki_id` of all paired Nuki Locks will be written to + the log file of SmarthomeNG.' + + nuki_trigger: + type: str + mandatory: True + description: + de: 'Es gibt drei Typen von NUKI Triggern, `action`, `state` und `battery`. Ein Item kann nur einen Trigger gleichzeitig haben..' + en: 'There are three types of nuki triggers, `action`, `state` and `battery`. An item can only have one trigger + attribute at once.' + valid_list: + - 'state' + - 'battery' + - 'action' \ No newline at end of file From d0e927fe63961aac687190f25c07cdf3723930f9 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 22 Aug 2018 13:22:41 +0200 Subject: [PATCH 118/705] Darksky: added docu link --- darksky/plugin.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/darksky/plugin.yaml b/darksky/plugin.yaml index 4190e4626..c0f865ed1 100644 --- a/darksky/plugin.yaml +++ b/darksky/plugin.yaml @@ -8,7 +8,7 @@ plugin: maintainer: psilo909 tester: # keywords: iot xyz - documentation: '' + documentation: 'https://www.smarthomeng.de/user/plugins/darksky/user_doc.html' support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/1244744-neues-plugin-wetterdaten-via-darksky-net-forecast-io' keywords: weather version: 1.5.0.1 # Plugin version From 7dc25e94259836be9e885335dac25b574c92838c Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 22 Aug 2018 13:23:43 +0200 Subject: [PATCH 119/705] NUKI: added tester --- nuki/plugin.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nuki/plugin.yaml b/nuki/plugin.yaml index d6e20ff9e..9e982bba9 100755 --- a/nuki/plugin.yaml +++ b/nuki/plugin.yaml @@ -6,7 +6,7 @@ plugin: de: 'Unterstützung für ein Nuki Smart-Lock' en: '' maintainer: fuppy, pfischi -# tester: # Who tests this plugin? + tester: psilo909 # keywords: iot xyz # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1052437-nuki-smartlock-plugin-support-thread From a4e195d1d8c440ea4608ff8ecbafd391f8561ba9 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 22 Aug 2018 13:24:20 +0200 Subject: [PATCH 120/705] NUKI: added (optional) --- nuki/plugin.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nuki/plugin.yaml b/nuki/plugin.yaml index 9e982bba9..43bda0e54 100755 --- a/nuki/plugin.yaml +++ b/nuki/plugin.yaml @@ -52,8 +52,8 @@ parameters: mandatory: False default: 8090 description: - de: 'Port, über den die Callbacks der NUKI Bridge verarbeitet werden sollen. Default: 8090.' - en: 'Port for the callbacks from NUK Bridge. Default: 8090.' + de: '(optional) Port, über den die Callbacks der NUKI Bridge verarbeitet werden sollen. Default: 8090.' + en: '(optional) Port for the callbacks from NUK Bridge. Default: 8090.' protocol: type: str From 9e5159a2269d51ec89f3b0b3e7e035e362195d25 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 22 Aug 2018 13:27:35 +0200 Subject: [PATCH 121/705] NUKI: added more meta information --- nuki/plugin.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nuki/plugin.yaml b/nuki/plugin.yaml index 43bda0e54..273ce5718 100755 --- a/nuki/plugin.yaml +++ b/nuki/plugin.yaml @@ -3,11 +3,11 @@ plugin: # Global plugin attributes type: interface # plugin type (gateway, interface, protocol, system, web) description: - de: 'Unterstützung für ein Nuki Smart-Lock' - en: '' + de: 'Unterstützung für ein NUKI Smart-Lock' + en: 'Support for the NUKI Smart Lock' maintainer: fuppy, pfischi tester: psilo909 -# keywords: iot xyz + keywords: 'Smart Lock', 'NUKI' # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1052437-nuki-smartlock-plugin-support-thread From ba6dca0df90700bf57292ad0565d40186d9d0692 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 22 Aug 2018 13:29:02 +0200 Subject: [PATCH 122/705] NUKI: switched bridge port to type int --- nuki/plugin.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nuki/plugin.yaml b/nuki/plugin.yaml index 273ce5718..f10e66181 100755 --- a/nuki/plugin.yaml +++ b/nuki/plugin.yaml @@ -27,7 +27,7 @@ parameters: en: 'IP address of the NUKI Bridge.' bridge_port: - type: str + type: int mandatory: True description: de: 'Portnummer der NUKI Bridge.' From a825d60d15086a802144b55b386bfe21cae4f0b7 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 22 Aug 2018 13:39:01 +0200 Subject: [PATCH 123/705] NUKI: cast of port from int to str --- nuki/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nuki/__init__.py b/nuki/__init__.py index 711706641..cd1d905ac 100644 --- a/nuki/__init__.py +++ b/nuki/__init__.py @@ -78,7 +78,7 @@ def __init__(self, sh, *args, **kwargs): global nuki_battery_items self._logger = logging.getLogger(__name__) self._base_url = self.get_parameter_value('protocol') + '://' + self.get_parameter_value( - 'bridge_ip') + ":" + self.get_parameter_value('bridge_port') + '/' + 'bridge_ip') + ":" + str(self.get_parameter_value('bridge_port')) + '/' self._token = self.get_parameter_value('bridge_api_token') self._callback_ip = self.get_parameter_value('bridge_callback_ip') self._callback_port = self.get_parameter_value('bridge_callback_port') From b28fda8d7d095d9118c4c969236552c8a622e6ab Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 22 Aug 2018 13:45:31 +0200 Subject: [PATCH 124/705] NUKI: Fixed keywords --- nuki/plugin.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nuki/plugin.yaml b/nuki/plugin.yaml index f10e66181..a1e7368aa 100755 --- a/nuki/plugin.yaml +++ b/nuki/plugin.yaml @@ -7,7 +7,7 @@ plugin: en: 'Support for the NUKI Smart Lock' maintainer: fuppy, pfischi tester: psilo909 - keywords: 'Smart Lock', 'NUKI' + keywords: Smart Lock, Nuki # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1052437-nuki-smartlock-plugin-support-thread From fe11a360a9ef26edd58d3bdd9361603ad17b8ca3 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 22 Aug 2018 13:50:33 +0200 Subject: [PATCH 125/705] MVG Live: removed unneccessary stuff, migrated to newest way of implementation --- mvg_live/__init__.py | 5 ++--- mvg_live/plugin.yaml | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/mvg_live/__init__.py b/mvg_live/__init__.py index ee459eb73..167fe5578 100644 --- a/mvg_live/__init__.py +++ b/mvg_live/__init__.py @@ -29,14 +29,13 @@ class MVG_Live(SmartPlugin): ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.3.0.1" + PLUGIN_VERSION = "1.5.0.2" - def __init__(self, smarthome): + def __init__(self, sh, *args, **kwargs): """ Initializes the plugin """ self.logger = logging.getLogger(__name__) - self._sh = smarthome self._mvg_live = MVGLive.MVGLive() def run(self): diff --git a/mvg_live/plugin.yaml b/mvg_live/plugin.yaml index 2439f3e71..4a3884bc5 100755 --- a/mvg_live/plugin.yaml +++ b/mvg_live/plugin.yaml @@ -11,8 +11,8 @@ plugin: documentation: http://smarthomeng.de/user/plugins_doc/config/mvg_live.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1108867-neues-plugin-mvg_live - version: 1.3.0.1 # Plugin version - sh_minversion: 1.3 # minimum shNG version to use this plugin + version: 1.5.0.2 # Plugin version + sh_minversion: 1.5 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance classname: MVG_Live # class containing the plugin From f2072bb3070d7a35baa3af52411930a7a457b288 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 22 Aug 2018 13:51:16 +0200 Subject: [PATCH 126/705] MVG Live: removed version from readme --- mvg_live/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/mvg_live/README.md b/mvg_live/README.md index 1b070777f..1bda22c8c 100644 --- a/mvg_live/README.md +++ b/mvg_live/README.md @@ -1,7 +1,5 @@ # MVG Live -Version 0.1 - ## Requirements This plugin requires lib PyMVGLive. You can install this lib with: From ef0dd76d3ca5005c0e90cdfdc5b4a74516876597 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 22 Aug 2018 14:01:23 +0200 Subject: [PATCH 127/705] Backend, system: fix for deprecated message shtime runtime --- backend/BackendSysteminfo.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/BackendSysteminfo.py b/backend/BackendSysteminfo.py index 66b5abf15..91af2479a 100755 --- a/backend/BackendSysteminfo.py +++ b/backend/BackendSysteminfo.py @@ -38,6 +38,7 @@ import bin.shngversion as shngversion import lib.config +from lib.shtime import Shtime #from lib.logic import Logics #from lib.model.smartplugin import SmartPlugin from lib.utils import Utils @@ -86,7 +87,7 @@ def system_html(self): uptime = self.age_to_string(days, hours, minutes, seconds) # return SmarthomeNG runtime - rt = str(self._sh.runtime()) + rt = str(Shtime.get_instance().runtime()) daytest = rt.split(' ') if len(daytest) == 3: days = int(daytest[0]) @@ -144,7 +145,7 @@ def system_json(self): uptime = self.age_to_string(days, hours, minutes, seconds) # return SmarthomeNG runtime - rt = str(self._sh.runtime()) + rt = str(Shtime.get_instance().runtime()) daytest = rt.split(' ') if len(daytest) == 3: days = int(daytest[0]) From 26228053b176c5527b94be7aaa16fd8ad6258b79 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 22 Aug 2018 19:57:02 +0200 Subject: [PATCH 128/705] Nokia: started rewoking plugin for nokia 1.0.0 package with oauth2, as oauth1 will expire end of november --- nokia_health/README.md | 27 ++++++++++------ nokia_health/__init__.py | 29 ++++++++---------- nokia_health/plugin.yaml | 58 ++++++++++++++++++++++------------- nokia_health/requirements.txt | 2 +- 4 files changed, 68 insertions(+), 48 deletions(-) diff --git a/nokia_health/README.md b/nokia_health/README.md index 6cbc24d42..078d89f78 100644 --- a/nokia_health/README.md +++ b/nokia_health/README.md @@ -15,21 +15,30 @@ This plugin requires lib nokia. You can install this lib with: sudo pip3 install nokia --upgrade ``` -You have to go through the registration and oauth process on https://developer.health.nokia.com/api. -In the end, after step 4, you see the access token and the access token secret in the input fields and the user id in the data right to it. +You have to register at https://account.health.nokia.com/partner/dashboard_oauth2. +The callback URL does not need to be reachable from the internet. You will have to start a small webserver for the oauth2 +process. The script can be found at https://github.com/orcasgit/python-nokia and is installed with the pypi package. +``` +nokia saveconfig --consumer-key [consumerkey] --consumer-secret [consumersecret] --callback-url [callbackurl] --config nokia.cfg +``` +The script for me only worked, when running it on the machine where i used the browser for accessing the callback url. +Once the script finishs, the required data for the plugin will be written to the config file and can be used for the plugin. + +In future i will provide the oauth2 process in the web interface of the plugin! ## Configuration ### plugin.yaml ```yaml nokia_health: - class_name: NokiaHealth - class_path: plugins.nokia_health - consumer_key: - consumer_secret: - access_token: - access_token_secret: - user_id: + access_token: + token_expiry: + token_type: + refresh_token: + user_id: + client_id: + consumer_secret: + cycle: 300 instance: nokia_health ``` diff --git a/nokia_health/__init__.py b/nokia_health/__init__.py index bc5320cfc..84faf1eab 100644 --- a/nokia_health/__init__.py +++ b/nokia_health/__init__.py @@ -29,26 +29,23 @@ class NokiaHealth(SmartPlugin): ALLOW_MULTIINSTANCE = True - PLUGIN_VERSION = "1.5.2" - BASE_URL = "https://api.health.nokia.com/" + PLUGIN_VERSION = "1.5.3" ALLOWED_MEASURE_TYPES = [1, 4, 5, 6, 8, 11] - # see https://developer.health.nokia.com/api/doc - - def __init__(self, smarthome, consumer_key, consumer_secret, access_token, access_token_secret, user_id, cycle=300): + def __init__(self, sh, *args, **kwargs): self.logger = logging.getLogger(__name__) - self._sh = smarthome - self._consumer_key = consumer_key - self._consumer_secret = consumer_secret - self._access_token = access_token - self._access_token_secret = access_token_secret - self._auth = NokiaAuth(self._consumer_key, self._consumer_secret) - self._user_id = user_id - self._creds = NokiaCredentials(self._access_token, self._access_token_secret, self._consumer_key, - self._consumer_secret, self._user_id) + self._access_token = self.get_parameter_value('access_token') + self._token_expiry = self.get_parameter_value('token_expiry') + self._token_type = self.get_parameter_value('token_type') + self._refresh_token = self.get_parameter_value('refresh_token') + self._user_id = self.get_parameter_value('user_id') + self._client_id = self.get_parameter_value('client_id') + self._consumer_secret = self.get_parameter_value('consumer_secret') + self._cycle = self.get_parameter_value('cycle') + + self._creds = NokiaCredentials(self._access_token, self._token_expiry, self._token_type, self._refresh_token, self._user_id, self._client_id, + self._consumer_secret) self._client = NokiaApi(self._creds) - - self._cycle = cycle self._items = {} if not self.init_webinterface(): diff --git a/nokia_health/plugin.yaml b/nokia_health/plugin.yaml index f04458fac..89242bc77 100644 --- a/nokia_health/plugin.yaml +++ b/nokia_health/plugin.yaml @@ -3,15 +3,15 @@ plugin: # Global plugin attributes type: web # plugin type (gateway, interface, protocol, system, web) description: - de: 'Anbindung der Nokia Health API' - en: '' + de: 'Anbindung der Nokia Health API mit Oauth2' + en: 'Usage of the nokia health api with oauth2' maintainer: 'psilo909' tester: 'psilo909' keywords: health documentation: 'http://smarthomeng.de/user/plugins_doc/config/nokia_health.html' support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/1141179-nokia-health-plugin' - version: 1.5.2 # Plugin version + version: 1.5.3 # Plugin version sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance @@ -20,42 +20,55 @@ plugin: parameters: # Definition of parameters to be configured in etc/plugin.yaml - consumer_key: + access_token: type: str - default: 300 mandatory: True description: - de: 'Nokia Health API Key' - en: 'Nokia Health API Key' + de: 'Access-Token, via nokia Script von https://github.com/orcasgit/python-nokia' + en: 'Access token, retrieved via script from https://github.com/orcasgit/python-nokia' - consumer_secret: + token_expiry: type: str - default: 300 mandatory: True description: - de: 'Nokia Health API Secret' - en: 'Nokia Health API Secret' + de: 'Token expiry, via nokia Script von https://github.com/orcasgit/python-nokia' + en: 'Token expiry, retrieved via script from https://github.com/orcasgit/python-nokia' - access_token: + token_type: type: str - mandatory: False + mandatory: True description: - de: 'Access Token (über https://developer.health.nokia.com/api bestimmt)' - en: 'access token (can be found via https://developer.health.nokia.com/api)' + de: 'Token-Type, via nokia Script von https://github.com/orcasgit/python-nokia' + en: 'Token type, retrieved via script from https://github.com/orcasgit/python-nokia' - access_token_secret: + refresh_token: type: str - mandatory: False + mandatory: True description: - de: 'Access Token Secret (über https://developer.health.nokia.com/api bestimmt)' - en: 'access token secret (can be found via https://developer.health.nokia.com/api)' + de: 'Refresh-Token, via nokia Script von https://github.com/orcasgit/python-nokia' + en: 'Refresh token, retrieved via script from https://github.com/orcasgit/python-nokia' user_id: type: str - mandatory: False + mandatory: True description: - de: 'User ID' - en: 'user id' + de: 'Nokia Health User ID (steht in der URL, wenn man als nomraler User einloggt)' + en: 'Nokia Health User ID (can be found in the URL when you log in)' + + client_id: + type: str + mandatory: True + description: + de: 'Client ID von https://account.health.nokia.com/partner/dashboard_oauth2' + en: 'Client ID from https://account.health.nokia.com/partner/dashboard_oauth2' + + consumer_secret: + type: str + default: 300 + mandatory: True + description: + de: 'Consumer-Geheimnis von https://account.health.nokia.com/partner/dashboard_oauth2' + en: 'Consumer secret from https://account.health.nokia.com/partner/dashboard_oauth2' cycle: type: int @@ -64,6 +77,7 @@ parameters: de: 'Dieser Parameter muss normalerweise nicht angegeben werden. Er erlaubt es die Update-Frquenz anzupassen (Standard: alle 600 Sekunden). Mit dem Standardwert werden die Daten von Nokia Health alle 5 Minuten aktualisiert.' en: "This parameter usually doesn't have to be specified. It allows to change the update frequency (cycle every 300 seconds). As a standard, the plugin updates the Nokia Health data every 5 minutes." + item_attributes: # Definition of item attributes defined by this plugin diff --git a/nokia_health/requirements.txt b/nokia_health/requirements.txt index 01960d405..353d50fe6 100644 --- a/nokia_health/requirements.txt +++ b/nokia_health/requirements.txt @@ -1 +1 @@ -nokia==0.4.0 +nokia==1.0.0 From 31d6684690cc84ef27bcf666f4222dac793ecd84 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Wed, 22 Aug 2018 20:43:32 +0200 Subject: [PATCH 129/705] fixed Denon item example and added denon avr1100 command file --- avdevice/Denon_Items.yaml | 18 +++++----- avdevice/models/denon-avr1100.txt | 60 +++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 9 deletions(-) create mode 100755 avdevice/models/denon-avr1100.txt diff --git a/avdevice/Denon_Items.yaml b/avdevice/Denon_Items.yaml index 127a3d154..07eeb165f 100755 --- a/avdevice/Denon_Items.yaml +++ b/avdevice/Denon_Items.yaml @@ -231,10 +231,10 @@ Denon: Musik: type: bool visu_acl: ro - eval: 1 if ((sh.Musik.OG.Denon.Source() == 'DVD' or sh.Musik.OG.Denon.Source() == 'CD' or sh.Musik.OG.Denon.Source() == 'NET') and sh.Musik.OG.Denon.Power()) else 0 + eval: 1 if ((sh.Denon.Source() == 'DVD' or sh.Denon.Source() == 'CD' or sh.Denon.Source() == 'NET') and sh.Denon.Power()) else 0 eval_trigger: - - Musik.OG.Denon.Source - - Musik.OG.Denon.Power + - Denon.Source + - Denon.Power enforce_updates: 'yes' Mode: @@ -437,10 +437,10 @@ Denon: Musik: type: bool visu_acl: ro - eval: 1 if ((sh.Musik.OG.Denon.Source2() == 'DVD' or sh.Musik.OG.Denon.Source2() == 'CD' or sh.Musik.OG.Denon.Source2() == 'NET') and sh.Musik.OG.Denon.Power2()) else 0 + eval: 1 if ((sh.Denon.Source2() == 'DVD' or sh.Denon.Source2() == 'CD' or sh.Denon.Source2() == 'NET') and sh.Denon.Power2()) else 0 eval_trigger: - - Musik.OG.Denon.Source2 - - Musik.OG.Denon.Power2 + - Denon.Source2 + - Denon.Power2 Mute2: type: bool @@ -522,10 +522,10 @@ Denon: Musik: type: bool visu_acl: ro - eval: 1 if ((sh.Musik.OG.Denon.Source3() == 'DVD' or sh.Musik.OG.Denon.Source3() == 'CD' or sh.Musik.OG.Denon.Source3() == 'NET') and sh.Musik.OG.Denon.Power3()) else 0 + eval: 1 if ((sh.Denon.Source3() == 'DVD' or sh.Denon.Source3() == 'CD' or sh.Denon.Source3() == 'NET') and sh.Denon.Power3()) else 0 eval_trigger: - - Musik.OG.Denon.Source3 - - Musik.OG.Denon.Power3 + - Denon.Source3 + - Denon.Power3 Mute3: type: bool diff --git a/avdevice/models/denon-avr1100.txt b/avdevice/models/denon-avr1100.txt new file mode 100755 index 000000000..ef2c90fc0 --- /dev/null +++ b/avdevice/models/denon-avr1100.txt @@ -0,0 +1,60 @@ +ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MINVALUE; MAXVALUE; RESPONSETYPE +0; power; on; PWON|PWON; PW?; PW**; RW +0; power; off; PWSTANDBY; PW?; PW*******; RW +0; eco; set; ECO*; ECO?; ECO*; RW; ; ; ; str|bool +1; power; on; ZMON; ZM?; ZM**; RW +1; power; off; ZMOFF; ZM?; ZM***; RW +1; mute; on; MUON; MU?; MU**; RW +1; mute; off; MUOFF; MU?; MU***; RW +1; sleep; set; SLP***; SLP?; SLP***; RW; ; 0; 120; num|bool +1; standby; set; STBY*; STBY?; STBY*; RW; ; ; ; str|bool +1; volume; set; MV**; MV?; MV**; RW; ; 30; 90 +1; volume+; increase; MVUP; ; MV; W +1; volume-; decrease; MVDOWN; ; MV; W +1; volumelow; ; MV50; MV?; MV50; W; ; ; ; num +1; volumehigh; ; MV75; MV?; MV75; W; ; ; ; num +1; volumemax; set; MVMAX **; MV?; MVMAX **|MVMAX ***; RW +1; input; set; SI*; SI?; SI*; RW; ; ; ; str +1; mode; set; MS*; MS?; MS*; RW; ; ; ; str +1; audioinput; set; SD*; SD?; SD*; RW; ; ; ; str +1; videoinput; set; SV*; SV?; SV*; RW; ; ; ; str|bool +1; tone; on; PSTONE CTRL ON; PSTONE CTRL ?; PSTONE CTRL **; RW +1; tone; off; PSTONE CTRL OFF; PSTONE CTRL ?; PSTONE CTRL ***; RW +1; bass; set; PSBAS **; PSBAS ?; PSBAS **; RW; ; 40; 60 +1; trebble; set; PSTRE **; PSTRE ?; PSTRE **; RW; ; 40; 60 +1; bass+; increase; PSBAS UP; ; PSBAS; W +1; bass-; decrease; PSBAS DOWN; ; PSBAS; W +1; trebble+; increase; PSTRE UP; ; PSTRE; W +1; trebble-; decrease; PSTRE DOWN; ; PSTRE; W +1; dialogtoggle; on; PSDIL ON; PSDIL ?; PSDIL **; RW +1; dialogtoggle; off; PSDIL OFF; PSDIL ?; PSDIL ***; RW +1; dialog; set; PSDIL **; PSDIL ?; PSDIL **; RW; ; 0; 62 +1; subwoofertoggle; on; PSSWL ON; PSSWL ?; PSSWL **; RW +1; subwoofertoggle; off; PSSWL OFF; PSSWL ?; PSSWL ***; RW +1; subwoofer; set; PSSWL **; PSSWL ?; PSSWL **; RW; ; 0; 62 +1; cinemaeq; on; PSCINEMA EQ.ON; PSCINEMA EQ. ?; PSCINEMA EQ.**; RW +1; cinemaeq; off; PSCINEMA EQ.OFF; PSCINEMA EQ. ?; PSCINEMA EQ.***; RW +2; power; on; Z2ON; Z2?; Z2**; RW +2; power; off; Z2OFF; Z2?; Z2***; RW +2; input; set; Z2*; Z2?; Z2*; RW; ; ; ; str +2; mute; on; Z2MUON; Z2MU?; Z2MU**; RW +2; mute; off; Z2MUOFF; Z2MU?; Z2MU***; RW +2; volume+; increase; Z2UP; ; Z2; W +2; volume-; decrease; Z2DOWN; ; Z2; W +2; volumelow; ; Z250; MV?; Z250; W; ; ; ; num +2; volumehigh; ; Z275; MV?; Z275; W; ; ; ; num +2; volume; set; Z2**; Z2?; Z2**; RW; ; 0; 90 +2; standby; set; Z2STBY*; Z2STBY?; Z2STBY*; RW; ; ; ; str|bool +2; sleep; set; Z2SLP***; Z2SLP?; Z2SLP***; RW; ; 0; 120; num|bool +3; power; on; Z3ON; Z3?; Z3**; RW +3; power; off; Z3OFF; Z3?; Z3***; RW +3; input; set; Z3*; Z3?; Z3*; RW; ; ; ; str +3; mute; on; Z3MUON; Z3MU?; Z3MU**; RW +3; mute; off; Z3MUOFF; Z3MU?; Z3MU***; RW +3; volume+; increase; Z3UP; ; Z3; W +3; volume-; decrease; Z3DOWN; ; Z3; W +3; volumelow; ; Z350; MV?; Z350; W; ; ; ; num +3; volumehigh; ; Z375; MV?; Z375; W; ; ; ; num +3; volume; set; Z3**; Z3?; Z3**; RW; ; 0; 90 +3; standby; set; Z3STBY*; Z3STBY?; Z3STBY*; RW; ; ; ; str|bool +3; sleep; set; Z3SLP***; Z3SLP?; Z3SLP***; RW; ; 0; 120; num|bool From 89c7a9fc09329e2ac2f2a6c678155077182694c9 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 23 Aug 2018 16:04:18 +0200 Subject: [PATCH 130/705] NUKI: kicked get_lan_ip, switched to function by utils class (smartplugin) --- nuki/__init__.py | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/nuki/__init__.py b/nuki/__init__.py index cd1d905ac..9e68d973c 100644 --- a/nuki/__init__.py +++ b/nuki/__init__.py @@ -86,7 +86,7 @@ def __init__(self, sh, *args, **kwargs): self._noWait = '' if self._callback_ip is None or self._callback_ip in ['0.0.0.0', '']: - self._callback_ip = get_lan_ip() + self._callback_ip = self.get_local_ipv4_address() if not self._callback_ip: self._logger.critical("Nuki: Could not fetch internal ip address. Set it manually!") @@ -253,21 +253,4 @@ def _api_call(self, base_url, endpoint=None, nuki_id=None, token=None, action=No response.raise_for_status() return json.loads(response.text) except Exception as ex: - self._logger.error(ex) - - -####################################################################### -# UTIL FUNCTION -####################################################################### - -def get_lan_ip(): - try: - import socket - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.settimeout(5) - s.connect(("google.com", 80)) - ip = s.getsockname()[0] - s.close() - return ip - except: - return None + self._logger.error(ex) \ No newline at end of file From 6e25972deeb2ad499ac9c60af4da25685fdccd98 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 23 Aug 2018 21:07:48 +0200 Subject: [PATCH 131/705] Nokia Health: first raw prototype with OAuth2 process via Web Interface and storage of value in new items! --- nokia_health/README.md | 46 ++++--- nokia_health/__init__.py | 154 +++++++++++++++++++----- nokia_health/plugin.yaml | 55 ++++----- nokia_health/webif/templates/index.html | 59 +++++---- 4 files changed, 214 insertions(+), 100 deletions(-) diff --git a/nokia_health/README.md b/nokia_health/README.md index 078d89f78..c7c8fac8d 100644 --- a/nokia_health/README.md +++ b/nokia_health/README.md @@ -15,26 +15,18 @@ This plugin requires lib nokia. You can install this lib with: sudo pip3 install nokia --upgrade ``` -You have to register at https://account.health.nokia.com/partner/dashboard_oauth2. -The callback URL does not need to be reachable from the internet. You will have to start a small webserver for the oauth2 -process. The script can be found at https://github.com/orcasgit/python-nokia and is installed with the pypi package. -``` -nokia saveconfig --consumer-key [consumerkey] --consumer-secret [consumersecret] --callback-url [callbackurl] --config nokia.cfg -``` -The script for me only worked, when running it on the machine where i used the browser for accessing the callback url. -Once the script finishs, the required data for the plugin will be written to the config file and can be used for the plugin. +You have to register at https://account.health.nokia.com/partner/add_oauth2. +The callback URL to enter when registering is shown via the plugin's web interface and can be added as soon as client_id and consumer_secret have been set in etc/plugin.yaml -In future i will provide the oauth2 process in the web interface of the plugin! +The OAuth2 process can then be triggered via the Web Interface of the plugin. Therefore at least the first four items of the example below need to exist (access_token, token_expiry, token_type, refresh_token). + +In case your SmartHomeNG instance is offline for too long, the tokens expire. You then have to start the OAuth2 process via the Web Interface again. Errors will be logged in this case! ## Configuration ### plugin.yaml ```yaml -nokia_health: - access_token: - token_expiry: - token_type: - refresh_token: +nokia_health: user_id: client_id: consumer_secret: @@ -48,9 +40,35 @@ Please be aware that there are dependencies for the values. E.g. the body measur height exists. From what i saw so far is, that the height is transmitted only one time, the first time the scale communicates with the Nokia servers. In case you miss it, set the item value manually! +The first four items are mandatory, as they are needed for OAuth2 data! + ```yaml body: + access_token: + type: str + visu_acl: ro + cache: yes + nh_type@nokia_health: access_token + + token_expiry: + type: num + visu_acl: ro + cache: yes + nh_type@nokia_health: token_expiry + + token_type: + type: str + visu_acl: ro + cache: yes + nh_type@nokia_health: token_type + + refresh_token: + type: str + visu_acl: ro + cache: yes + nh_type@nokia_health: refresh_token + weight: type: num visu_acl: ro diff --git a/nokia_health/__init__.py b/nokia_health/__init__.py index 84faf1eab..bae77f805 100644 --- a/nokia_health/__init__.py +++ b/nokia_health/__init__.py @@ -23,6 +23,7 @@ ######################################################################### import requests +import ruamel.yaml from lib.model.smartplugin import * from nokia import NokiaAuth, NokiaApi, NokiaCredentials @@ -34,18 +35,12 @@ class NokiaHealth(SmartPlugin): def __init__(self, sh, *args, **kwargs): self.logger = logging.getLogger(__name__) - self._access_token = self.get_parameter_value('access_token') - self._token_expiry = self.get_parameter_value('token_expiry') - self._token_type = self.get_parameter_value('token_type') - self._refresh_token = self.get_parameter_value('refresh_token') self._user_id = self.get_parameter_value('user_id') self._client_id = self.get_parameter_value('client_id') self._consumer_secret = self.get_parameter_value('consumer_secret') self._cycle = self.get_parameter_value('cycle') - - self._creds = NokiaCredentials(self._access_token, self._token_expiry, self._token_type, self._refresh_token, self._user_id, self._client_id, - self._consumer_secret) - self._client = NokiaApi(self._creds) + self._creds = None + self._client = None self._items = {} if not self.init_webinterface(): @@ -53,16 +48,27 @@ def __init__(self, sh, *args, **kwargs): def run(self): self.alive = True - self.scheduler_add(__name__, self._update_loop, cycle=self._cycle) + self.scheduler_add('poll_data', self._update_loop, cycle=self._cycle) def stop(self): self.alive = False + def _store_tokens(self, token): + self.logger.debug( + "Plugin '{}': Updating tokens to items: access_token - {} token_expiry - {} token_type - {} refresh_token - {}". + format(self.get_fullname(), token['access_token'], token['expires_in'], token['token_type'], + token['refresh_token'])) + self.plugin.get_item('access_token')(token['access_token']) + self.plugin.get_item('token_expiry')(token['expires_in']) + self.plugin.get_item('token_type')(token['token_type']) + self.plugin.get_item('refresh_token')(token['refresh_token']) + def _update_loop(self): """ Starts the update loop for all known items. """ - self.logger.debug('Starting update loop for instance %s' % self.get_instance_name()) + self.logger.debug( + "Plugin '{}': Starting update loop".format(self.get_fullname())) if not self.alive: return @@ -89,12 +95,36 @@ def _update(self): ('bone_mass', 88), ('pulse_wave_velocity', 91) """ + if self._client is None: + if self.get_item('access_token')() and self.get_item( + 'token_expiry')() > 0 and self.get_item( + 'token_type')() and self.get_item('refresh_token')(): + self.logger.debug( + "Plugin '{}': Initializing NokiaCredentials: access_token - {} token_expiry - {} token_type - {} refresh_token - {} user_id - {} client_id - {} consumer_secret - {}". + format(self.get_fullname(), self.get_item('access_token')(), + self.get_item('token_expiry')(), + self.get_item('token_type')(), + self.get_item('refresh_token')(), + self._user_id, + self._client_id, + self._consumer_secret)) + self._creds = NokiaCredentials(self.get_item('access_token')(), + self.get_item('token_expiry')(), + self.get_item('token_type')(), + self.get_item('refresh_token')(), + self._user_id, self._client_id, + self._consumer_secret) + self._client = NokiaApi(self._creds, refresh_cb=self._store_tokens) + else: + self.logger.error( + "Plugin '{}': Items for OAuth2 Data not set. Please run process via WebGUI of the plugin.".format(self.get_fullname())) + return measures = self._client.get_measures() last_measure = measures[0] if last_measure.get_measure(11) is not None and 'heart_pulse' in self._items: self._items['heart_pulse'](last_measure.get_measure(11)) - self.logger.debug(last_measure.get_measure(11)) + self.logger.debug("Plugin '{}': heart_pulse - {}".format(self.get_fullname(), last_measure.get_measure(11))) # Bugfix for strange behavior of returning heart_pulse as seperate dataset.. if last_measure.get_measure(1) is None: @@ -102,67 +132,74 @@ def _update(self): if last_measure.get_measure(1) is not None and 'weight' in self._items: self._items['weight'](last_measure.get_measure(1)) - self.logger.debug(last_measure.get_measure(1)) + self.logger.debug("Plugin '{}': weight - {}".format(self.get_fullname(), last_measure.get_measure(1))) if last_measure.get_measure(4) is not None and 'height' in self._items: self._items['height'](last_measure.get_measure(4)) - self.logger.debug(last_measure.get_measure(4)) + self.logger.debug("Plugin '{}': height - {}".format(self.get_fullname(), last_measure.get_measure(4))) if last_measure.get_measure(5) is not None and 'fat_free_mass' in self._items: self._items['fat_free_mass'](last_measure.get_measure(5)) - self.logger.debug(last_measure.get_measure(5)) + self.logger.debug( + "Plugin '{}': fat_free_mass - {}".format(self.get_fullname(), last_measure.get_measure(5))) if last_measure.get_measure(6) is not None and 'fat_ratio' in self._items: self._items['fat_ratio'](last_measure.get_measure(6)) - self.logger.debug(last_measure.get_measure(6)) + self.logger.debug("Plugin '{}': fat_ratio - {}".format(self.get_fullname(), last_measure.get_measure(6))) if last_measure.get_measure(8) is not None and 'fat_mass_weight' in self._items: self._items['fat_mass_weight'](last_measure.get_measure(8)) - self.logger.debug(last_measure.get_measure(8)) + self.logger.debug( + "Plugin '{}': fat_mass_weight - {}".format(self.get_fullname(), last_measure.get_measure(8))) if last_measure.get_measure(9) is not None and 'diastolic_blood_pressure' in self._items: self._items['diastolic_blood_pressure'](last_measure.get_measure(9)) - self.logger.debug(last_measure.get_measure(9)) + self.logger.debug( + "Plugin '{}': diastolic_blood_pressure - {}".format(self.get_fullname(), last_measure.get_measure(9))) if last_measure.get_measure(10) is not None and 'systolic_blood_pressure' in self._items: self._items['systolic_blood_pressure'](last_measure.get_measure(10)) - self.logger.debug(last_measure.get_measure(10)) + self.logger.debug( + "Plugin '{}': systolic_blood_pressure - {}".format(self.get_fullname(), last_measure.get_measure(10))) if last_measure.get_measure(11) is not None and 'heart_pulse' in self._items: self._items['heart_pulse'](last_measure.get_measure(11)) - self.logger.debug(last_measure.get_measure(11)) + self.logger.debug("Plugin '{}': heart_pulse - {}".format(self.get_fullname(), last_measure.get_measure(11))) if last_measure.get_measure(12) is not None and 'temperature' in self._items: self._items['temperature'](last_measure.get_measure(12)) - self.logger.debug(last_measure.get_measure(12)) + self.logger.debug("Plugin '{}': temperature - {}".format(self.get_fullname(), last_measure.get_measure(12))) if last_measure.get_measure(54) is not None and 'spo2' in self._items: self._items['spo2'](last_measure.get_measure(54)) - self.logger.debug(last_measure.get_measure(54)) + self.logger.debug("Plugin '{}': spo2 - {}".format(self.get_fullname(), last_measure.get_measure(54))) if last_measure.get_measure(71) is not None and 'body_temperature' in self._items: self._items['body_temperature'](last_measure.get_measure(71)) - self.logger.debug(last_measure.get_measure(71)) + self.logger.debug( + "Plugin '{}': body_temperature - {}".format(self.get_fullname(), last_measure.get_measure(71))) if last_measure.get_measure(72) is not None and 'skin_temperature' in self._items: self._items['skin_temperature'](last_measure.get_measure(72)) - self.logger.debug(last_measure.get_measure(72)) + self.logger.debug( + "Plugin '{}': skin_temperature - {}".format(self.get_fullname(), last_measure.get_measure(72))) if last_measure.get_measure(76) is not None and 'muscle_mass' in self._items: self._items['muscle_mass'](last_measure.get_measure(76)) - self.logger.debug(last_measure.get_measure(76)) + self.logger.debug("Plugin '{}': muscle_mass - {}".format(self.get_fullname(), last_measure.get_measure(76))) if last_measure.get_measure(77) is not None and 'hydration' in self._items: self._items['hydration'](last_measure.get_measure(77)) - self.logger.debug(last_measure.get_measure(77)) + self.logger.debug("Plugin '{}': hydration - {}".format(self.get_fullname(), last_measure.get_measure(77))) if last_measure.get_measure(88) is not None and 'bone_mass' in self._items: self._items['bone_mass'](last_measure.get_measure(88)) - self.logger.debug(last_measure.get_measure(88)) + self.logger.debug("Plugin '{}': bone_mass - {}".format(self.get_fullname(), last_measure.get_measure(88))) if last_measure.get_measure(91) is not None and 'pulse_wave_velocity' in self._items: self._items['pulse_wave_velocity'](last_measure.get_measure(91)) - self.logger.debug(last_measure.get_measure(91)) + self.logger.debug( + "Plugin '{}': pulse_wave_velocity - {}".format(self.get_fullname(), last_measure.get_measure(91))) if 'height' in self._items and ('bmi' in self._items or 'bmi_text' in self._items) and last_measure.get_measure( 1) is not None: @@ -190,9 +227,11 @@ def _update(self): self._items['bmi_text']('Adipositas Grad III') else: self.logger.error( - "Cannot calculate BMI: height is 0, please set height (in m) for height item manually.") + "Plugin '{}': Cannot calculate BMI: height is 0, please set height (in m) for height item manually.".format( + self.get_fullname())) else: - self.logger.error("Cannot calculate BMI: height and / or bmi item missing.") + self.logger.error( + "Plugin '{}': Cannot calculate BMI: height and / or bmi item missing.".format(self.get_fullname())) def parse_item(self, item): """ @@ -207,12 +246,16 @@ def parse_item(self, item): 'systolic_blood_pressure', 'heart_pulse', 'temperature', 'spo2', 'body_temperature', 'skin_temperature', 'muscle_mass', 'hydration', 'bone_mass', 'pulse_wave_velocity', 'bmi', - 'bmi_text']: + 'bmi_text', 'access_token', 'token_expiry', 'token_type', + 'refresh_token']: self._items[self.get_iattr_value(item.conf, 'nh_type')] = item def get_items(self): return self._items + def get_item(self, key): + return self._items[key] + def init_webinterface(self): """" Initialize the web interface for this plugin @@ -225,7 +268,7 @@ def init_webinterface(self): except: self.mod_http = None if self.mod_http == None: - self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_shortname())) + self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_fullname())) return False # set application configuration for cherrypy @@ -272,11 +315,25 @@ def __init__(self, webif_dir, plugin): self.logger = logging.getLogger(__name__) self.webif_dir = webif_dir self.plugin = plugin + self._creds = None + self._auth = None self.tplenv = self.init_template_environment() + def _get_callback_url(self): + ip = self.plugin.mod_http.get_local_ip_address() + port = self.plugin.mod_http.get_local_port() + web_ifs = self.plugin.mod_http.get_webifs_for_plugin(self.plugin.get_shortname()) + for web_if in web_ifs: + if web_if['Instance'] == self.plugin.get_instance_name(): + callback_url = "http://{}:{}{}".format(ip, port, web_if['Mount']) + self.logger.debug("Plugin '{}': WebIf found, callback is {}".format(self.plugin.get_fullname(), + callback_url)) + return callback_url + self.logger.error("Plugin '{}': Callback URL cannot be established.".format(self.plugin.get_fullname())) + @cherrypy.expose - def index(self, reload=None): + def index(self, reload=None, state=None, code=None, error=None): """ Build index.html for cherrypy @@ -284,9 +341,40 @@ def index(self, reload=None): :return: contents of the template after beeing rendered """ + if self._auth is None: + self._auth = NokiaAuth( + self.plugin._client_id, + self.plugin._consumer_secret, + callback_uri=self._get_callback_url(), + scope='user.info,user.metrics,user.activity' + ) + + if code: + self.logger.debug("Plugin '{}': Got code as callback: {}".format(self.plugin.get_fullname(), code)) + credentials = None + try: + credentials = self._auth.get_credentials(code) + except: + self.logger.error( + "Plugin '{}': An error occurred, perhaps code parameter is invalid or too old?".format( + self.plugin.get_fullname())) + if credentials is not None: + self._creds = credentials + self.logger.debug( + "Plugin '{}': New credentials are: access_token {}, token_expiry {}, token_type {}, refresh_token {}". + format(self.plugin.get_fullname(), self._creds.access_token, self._creds.token_expiry, + self._creds.token_type, self._creds.refresh_token)) + self.plugin.get_item('access_token')(self._creds.access_token) + self.plugin.get_item('token_expiry')(self._creds.token_expiry) + self.plugin.get_item('token_type')(self._creds.token_type) + self.plugin.get_item('refresh_token')(self._creds.refresh_token) + + self.plugin._client = None + tmpl = self.tplenv.get_template('index.html') return tmpl.render(plugin_shortname=self.plugin.get_shortname(), plugin_version=self.plugin.get_version(), interface=None, item_count=len(self.plugin.get_items()), - plugin_info=self.plugin.get_info(), tabcount=1, + plugin_info=self.plugin.get_info(), tabcount=2, callback_url=self._get_callback_url(), tab1title="Nokia Health Items (%s)" % len(self.plugin.get_items()), + tab2title="OAuth2 Data", authorize_url=self._auth.get_authorize_url(), p=self.plugin) diff --git a/nokia_health/plugin.yaml b/nokia_health/plugin.yaml index 89242bc77..e80ce239b 100644 --- a/nokia_health/plugin.yaml +++ b/nokia_health/plugin.yaml @@ -20,34 +20,6 @@ plugin: parameters: # Definition of parameters to be configured in etc/plugin.yaml - access_token: - type: str - mandatory: True - description: - de: 'Access-Token, via nokia Script von https://github.com/orcasgit/python-nokia' - en: 'Access token, retrieved via script from https://github.com/orcasgit/python-nokia' - - token_expiry: - type: str - mandatory: True - description: - de: 'Token expiry, via nokia Script von https://github.com/orcasgit/python-nokia' - en: 'Token expiry, retrieved via script from https://github.com/orcasgit/python-nokia' - - token_type: - type: str - mandatory: True - description: - de: 'Token-Type, via nokia Script von https://github.com/orcasgit/python-nokia' - en: 'Token type, retrieved via script from https://github.com/orcasgit/python-nokia' - - refresh_token: - type: str - mandatory: True - description: - de: 'Refresh-Token, via nokia Script von https://github.com/orcasgit/python-nokia' - en: 'Refresh token, retrieved via script from https://github.com/orcasgit/python-nokia' - user_id: type: str mandatory: True @@ -84,5 +56,28 @@ item_attributes: nh_type: type: str description: - de: 'nh_type kann folgende Werte annehmen: weight, height (wird von Nokia Health nur beim allerersten Messwert geliefert), bmi, bmi_text, fat_ratio, fat_free_mass, fat_mass_weight, heart_pulse, last_update.' - en: 'nh_type can be out of the following values: weight, height (wird von Nokia Health nur beim allerersten Messwert geliefert), bmi, bmi_text, fat_ratio, fat_free_mass, fat_mass_weight, heart_pulse, last_update.' \ No newline at end of file + de: 'nh_type kann folgende Werte annehmen: Zwingend für OAuth2: access_token, token_expiry, token_type, refresh_token | Optional: weight, height (wird von Nokia Health nur beim allerersten Messwert geliefert), bmi, bmi_text, fat_ratio, fat_free_mass, fat_mass_weight, diastolic_blood_pressure, systolic_blood_pressure, temperature, body_temperature, skin_temperature, spo2, heart_pulse, hydration, bone_mass, pulse_wave_velocity.' + en: 'nh_type can be out of the following values: Mandatory for OAuth2: access_token, token_expiry, token_type, refresh_token | Optional: weight, height (only supplied on the very first measurement value, set manually if you dont get it), bmi, bmi_text, fat_ratio, fat_free_mass, fat_mass_weight, diastolic_blood_pressure, systolic_blood_pressure, temperature, body_temperature, skin_temperature, spo2, heart_pulse, hydration, bone_mass, pulse_wave_velocity.' + valid_list: + - 'weight' + - 'height' + - 'bmi' + - 'bmi_text' + - 'fat_ratio' + - 'fat_free_mass' + - 'fat_mass_weight' + - 'diastolic_blood_pressure' + - 'systolic_blood_pressure' + - 'temperature' + - 'body_temperature' + - 'skin_temperature' + - 'spo2' + - 'heart_pulse' + - 'hydration' + - 'bone_mass' + - 'pulse_wave_velocity' + - 'access_token' + - 'token_expiry' + - 'token_type' + - 'refresh_token' + diff --git a/nokia_health/webif/templates/index.html b/nokia_health/webif/templates/index.html index baf6770b5..b1a865dae 100644 --- a/nokia_health/webif/templates/index.html +++ b/nokia_health/webif/templates/index.html @@ -7,32 +7,13 @@ - - + + - + - {% if not p._access_token and not p._access_token_secret %} - - - - - {% else %} - - - - - - - - - {% endif %} @@ -74,5 +55,37 @@
Nokia Health Items ({{ p.get_items()|length }})
Consumer Key{{ p._consumer_key }}Client ID{{ p._client_id }}
Consumer Secret{{ p._consumer_secret }}{{ p._consumer_secret }}
- OAuth API - - https://developer.health.nokia.com/api -
Access Token{{ p._access_token }}
Access Token Secret{{ p._access_token_secret }}
User ID {{ p._user_id}}
- {% endblock %} + +{% block bodytab2 %} + + + + + + + + + + + + + + + + + + + + + +
+ OAuth2 Authorization URL + + Click Here! +
+ Callback URL + + {{ callback_url }} +
Access Token{{ p.get_item('access_token')() }}Token Expiry{{ p.get_item('token_expiry')() }}
Token Type{{ p.get_item('token_type')() }}Refresh Token{{ p.get_item('refresh_token')() }}
+{% endblock %} \ No newline at end of file From 302794771953e93f94ed38540742728591f04c3e Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 23 Aug 2018 21:56:59 +0200 Subject: [PATCH 132/705] Nokia Health: added check for expired token, readable info in web if --- nokia_health/__init__.py | 50 ++++++++++++++++--------- nokia_health/webif/templates/index.html | 4 +- 2 files changed, 35 insertions(+), 19 deletions(-) diff --git a/nokia_health/__init__.py b/nokia_health/__init__.py index bae77f805..56b362901 100644 --- a/nokia_health/__init__.py +++ b/nokia_health/__init__.py @@ -24,7 +24,9 @@ import requests import ruamel.yaml +import datetime from lib.model.smartplugin import * +from lib.shtime import Shtime from nokia import NokiaAuth, NokiaApi, NokiaCredentials @@ -35,6 +37,7 @@ class NokiaHealth(SmartPlugin): def __init__(self, sh, *args, **kwargs): self.logger = logging.getLogger(__name__) + self.shtime = Shtime.get_instance() self._user_id = self.get_parameter_value('user_id') self._client_id = self.get_parameter_value('client_id') self._consumer_secret = self.get_parameter_value('consumer_secret') @@ -99,22 +102,34 @@ def _update(self): if self.get_item('access_token')() and self.get_item( 'token_expiry')() > 0 and self.get_item( 'token_type')() and self.get_item('refresh_token')(): - self.logger.debug( - "Plugin '{}': Initializing NokiaCredentials: access_token - {} token_expiry - {} token_type - {} refresh_token - {} user_id - {} client_id - {} consumer_secret - {}". - format(self.get_fullname(), self.get_item('access_token')(), - self.get_item('token_expiry')(), - self.get_item('token_type')(), - self.get_item('refresh_token')(), - self._user_id, - self._client_id, - self._consumer_secret)) - self._creds = NokiaCredentials(self.get_item('access_token')(), - self.get_item('token_expiry')(), - self.get_item('token_type')(), - self.get_item('refresh_token')(), - self._user_id, self._client_id, - self._consumer_secret) - self._client = NokiaApi(self._creds, refresh_cb=self._store_tokens) + + if (self.shtime.now() < datetime.datetime.fromtimestamp(self.get_item( + 'token_expiry')(), tz=self.shtime.tzinfo())): + self.logger.error( + "Plugin '{}': Token is valid, will expire on {}.".format( + self.get_fullname(), datetime.datetime.fromtimestamp(self.get_item( + 'token_expiry')(), tz=self.shtime.tzinfo()).strftime('%d.%m.%Y %H:%M:%S'))) + self.logger.debug( + "Plugin '{}': Initializing NokiaCredentials: access_token - {} token_expiry - {} token_type - {} refresh_token - {} user_id - {} client_id - {} consumer_secret - {}". + format(self.get_fullname(), self.get_item('access_token')(), + self.get_item('token_expiry')(), + self.get_item('token_type')(), + self.get_item('refresh_token')(), + self._user_id, + self._client_id, + self._consumer_secret)) + self._creds = NokiaCredentials(self.get_item('access_token')(), + self.get_item('token_expiry')(), + self.get_item('token_type')(), + self.get_item('refresh_token')(), + self._user_id, self._client_id, + self._consumer_secret) + self._client = NokiaApi(self._creds, refresh_cb=self._store_tokens) + else: + self.logger.error( + "Plugin '{}': Token is expired, run OAuth2 again from Web Interface (Expiry Date: {}).".format( + self.get_fullname(), datetime.datetime.fromtimestamp(self.get_item( + 'token_expiry')(), tz=self.shtime.tzinfo()).strftime('%d.%m.%Y %H:%M:%S'))) else: self.logger.error( "Plugin '{}': Items for OAuth2 Data not set. Please run process via WebGUI of the plugin.".format(self.get_fullname())) @@ -377,4 +392,5 @@ def index(self, reload=None, state=None, code=None, error=None): plugin_info=self.plugin.get_info(), tabcount=2, callback_url=self._get_callback_url(), tab1title="Nokia Health Items (%s)" % len(self.plugin.get_items()), tab2title="OAuth2 Data", authorize_url=self._auth.get_authorize_url(), - p=self.plugin) + p=self.plugin, token_expiry=datetime.datetime.fromtimestamp(self.plugin.get_item( + 'token_expiry')(), tz=self.plugin.shtime.tzinfo())) diff --git a/nokia_health/webif/templates/index.html b/nokia_health/webif/templates/index.html index b1a865dae..a2074ebaf 100644 --- a/nokia_health/webif/templates/index.html +++ b/nokia_health/webif/templates/index.html @@ -46,7 +46,7 @@
Nokia Health Items ({{ p.get_items()|length }})
{{ item._path }} {{ item._type }} {{ key }} - {{ item() }} + {{ item() }} {% if key == 'token_expiry' %}({{ token_expiry.strftime('%d.%m.%Y %H:%M:%S') }}){% endif %} {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} {{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }} @@ -79,7 +79,7 @@
Nokia Health Items ({{ p.get_items()|length }})
Access Token {{ p.get_item('access_token')() }} Token Expiry - {{ p.get_item('token_expiry')() }} + {{ p.get_item('token_expiry')() }} ({{ token_expiry.strftime('%d.%m.%Y %H:%M:%S') }}) Token Type From 777741bb7086e5ba746dff9333479cdfccc7a100 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 06:12:04 +0200 Subject: [PATCH 133/705] Nokia Health: fix for token renewal --- nokia_health/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nokia_health/__init__.py b/nokia_health/__init__.py index 56b362901..b3f21d460 100644 --- a/nokia_health/__init__.py +++ b/nokia_health/__init__.py @@ -61,10 +61,10 @@ def _store_tokens(self, token): "Plugin '{}': Updating tokens to items: access_token - {} token_expiry - {} token_type - {} refresh_token - {}". format(self.get_fullname(), token['access_token'], token['expires_in'], token['token_type'], token['refresh_token'])) - self.plugin.get_item('access_token')(token['access_token']) - self.plugin.get_item('token_expiry')(token['expires_in']) - self.plugin.get_item('token_type')(token['token_type']) - self.plugin.get_item('refresh_token')(token['refresh_token']) + self.get_item('access_token')(token['access_token']) + self.get_item('token_expiry')(token['expires_in']) + self.get_item('token_type')(token['token_type']) + self.get_item('refresh_token')(token['refresh_token']) def _update_loop(self): """ From ced5d81f573071099cd91fb10d5412aff5cea317 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 06:50:28 +0200 Subject: [PATCH 134/705] Nokia Health: translations, bugfixes, messages --- nokia_health/__init__.py | 5 ++-- nokia_health/locale.yaml | 17 ++++++++++++++ nokia_health/webif/templates/index.html | 31 ++++++++++++++++--------- 3 files changed, 40 insertions(+), 13 deletions(-) create mode 100644 nokia_health/locale.yaml diff --git a/nokia_health/__init__.py b/nokia_health/__init__.py index b3f21d460..a03726601 100644 --- a/nokia_health/__init__.py +++ b/nokia_health/__init__.py @@ -370,7 +370,7 @@ def index(self, reload=None, state=None, code=None, error=None): try: credentials = self._auth.get_credentials(code) except: - self.logger.error( + self.logger.warning( "Plugin '{}': An error occurred, perhaps code parameter is invalid or too old?".format( self.plugin.get_fullname())) if credentials is not None: @@ -386,6 +386,7 @@ def index(self, reload=None, state=None, code=None, error=None): self.plugin._client = None + tmpl = self.tplenv.get_template('index.html') return tmpl.render(plugin_shortname=self.plugin.get_shortname(), plugin_version=self.plugin.get_version(), interface=None, item_count=len(self.plugin.get_items()), @@ -393,4 +394,4 @@ def index(self, reload=None, state=None, code=None, error=None): tab1title="Nokia Health Items (%s)" % len(self.plugin.get_items()), tab2title="OAuth2 Data", authorize_url=self._auth.get_authorize_url(), p=self.plugin, token_expiry=datetime.datetime.fromtimestamp(self.plugin.get_item( - 'token_expiry')(), tz=self.plugin.shtime.tzinfo())) + 'token_expiry')(), tz=self.plugin.shtime.tzinfo()), now = self.plugin.shtime.now(), code=code) diff --git a/nokia_health/locale.yaml b/nokia_health/locale.yaml new file mode 100644 index 000000000..7ed129ccb --- /dev/null +++ b/nokia_health/locale.yaml @@ -0,0 +1,17 @@ +plugin_translations: + 'Warnung': {'de': 'Warnung', 'en': 'Warning'} + 'Das Token ist abgelaufen und wurde nicht verlängert. Bitte den OAuth2 Prozess neu starten.': + 'de': 'Das Token ist abgelaufen und wurde nicht verlängert. Bitte den OAuth2 Prozess neu starten.' + 'en': 'The token has expired and was not renewed. Please start OAuth2 process again.' + 'Nokia Health Items': + 'de': 'Nokia Health Items' + 'en': 'Nokia Health Items' + 'Hier klicken, um OAuth2 Prozess zu starten!': + 'de': 'Hier klicken, um OAuth2 Prozess zu starten!' + 'en': 'Click here, to start OAuth2 process!' + 'OAuth2 Authorization URL': + 'de': 'OAuth2 Authorization URL' + 'en': 'OAuth2 Authorization URL' + 'Callback URL': + 'de': 'Callback URL' + 'en': 'Callback URL' \ No newline at end of file diff --git a/nokia_health/webif/templates/index.html b/nokia_health/webif/templates/index.html index a2074ebaf..b89ab0549 100644 --- a/nokia_health/webif/templates/index.html +++ b/nokia_health/webif/templates/index.html @@ -23,21 +23,30 @@ {% endblock %} {% block bodytab1 %} +{% if p.get_item('token_expiry')() > 0 and token_expiry < now %} + +{% endif %}
-
Nokia Health Items ({{ p.get_items()|length }})
+
{{ _('Nokia Health Items') }} ({{ p.get_items()|length }})
- - + + - - - + + + @@ -46,7 +55,7 @@
Nokia Health Items ({{ p.get_items()|length }})
- + @@ -61,15 +70,15 @@
Nokia Health Items ({{ p.get_items()|length }})
PfadTyp{{ _('Pfad') }}{{ _('Typ') }} Nokia Health Data TypeWertLetztes UpdateLetzter Change{{ _('Wert') }}{{ _('Letztes Update') }}{{ _('Letzter Change') }}
{{ item._path }} {{ item._type }} {{ key }}{{ item() }} {% if key == 'token_expiry' %}({{ token_expiry.strftime('%d.%m.%Y %H:%M:%S') }}){% endif %} 0 and token_expiry < now %}style="color: red; font-weight: bold;"{% endif %}>{{ item() }} {% if key == 'token_expiry' %}({{ token_expiry.strftime('%d.%m.%Y %H:%M:%S') }}){% endif %} {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} {{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }}
- + From 6b60df4b0b998fc68723db222575ea1c5bdf532f Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 08:11:39 +0200 Subject: [PATCH 135/705] Nokia Health: small changes to message handling after oauth2 --- nokia_health/__init__.py | 29 +++++++++++++------------ nokia_health/locale.yaml | 8 ++++++- nokia_health/webif/templates/index.html | 10 +++++++++ 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/nokia_health/__init__.py b/nokia_health/__init__.py index a03726601..c97cece75 100644 --- a/nokia_health/__init__.py +++ b/nokia_health/__init__.py @@ -104,20 +104,20 @@ def _update(self): 'token_type')() and self.get_item('refresh_token')(): if (self.shtime.now() < datetime.datetime.fromtimestamp(self.get_item( - 'token_expiry')(), tz=self.shtime.tzinfo())): + 'token_expiry')(), tz=self.shtime.tzinfo())): self.logger.error( "Plugin '{}': Token is valid, will expire on {}.".format( self.get_fullname(), datetime.datetime.fromtimestamp(self.get_item( 'token_expiry')(), tz=self.shtime.tzinfo()).strftime('%d.%m.%Y %H:%M:%S'))) self.logger.debug( "Plugin '{}': Initializing NokiaCredentials: access_token - {} token_expiry - {} token_type - {} refresh_token - {} user_id - {} client_id - {} consumer_secret - {}". - format(self.get_fullname(), self.get_item('access_token')(), - self.get_item('token_expiry')(), - self.get_item('token_type')(), - self.get_item('refresh_token')(), - self._user_id, - self._client_id, - self._consumer_secret)) + format(self.get_fullname(), self.get_item('access_token')(), + self.get_item('token_expiry')(), + self.get_item('token_type')(), + self.get_item('refresh_token')(), + self._user_id, + self._client_id, + self._consumer_secret)) self._creds = NokiaCredentials(self.get_item('access_token')(), self.get_item('token_expiry')(), self.get_item('token_type')(), @@ -129,10 +129,11 @@ def _update(self): self.logger.error( "Plugin '{}': Token is expired, run OAuth2 again from Web Interface (Expiry Date: {}).".format( self.get_fullname(), datetime.datetime.fromtimestamp(self.get_item( - 'token_expiry')(), tz=self.shtime.tzinfo()).strftime('%d.%m.%Y %H:%M:%S'))) + 'token_expiry')(), tz=self.shtime.tzinfo()).strftime('%d.%m.%Y %H:%M:%S'))) else: self.logger.error( - "Plugin '{}': Items for OAuth2 Data not set. Please run process via WebGUI of the plugin.".format(self.get_fullname())) + "Plugin '{}': Items for OAuth2 Data not set. Please run process via WebGUI of the plugin.".format( + self.get_fullname())) return measures = self._client.get_measures() last_measure = measures[0] @@ -364,13 +365,13 @@ def index(self, reload=None, state=None, code=None, error=None): scope='user.info,user.metrics,user.activity' ) - if code: + if not reload and code: self.logger.debug("Plugin '{}': Got code as callback: {}".format(self.plugin.get_fullname(), code)) credentials = None try: credentials = self._auth.get_credentials(code) except: - self.logger.warning( + self.logger.error( "Plugin '{}': An error occurred, perhaps code parameter is invalid or too old?".format( self.plugin.get_fullname())) if credentials is not None: @@ -386,7 +387,6 @@ def index(self, reload=None, state=None, code=None, error=None): self.plugin._client = None - tmpl = self.tplenv.get_template('index.html') return tmpl.render(plugin_shortname=self.plugin.get_shortname(), plugin_version=self.plugin.get_version(), interface=None, item_count=len(self.plugin.get_items()), @@ -394,4 +394,5 @@ def index(self, reload=None, state=None, code=None, error=None): tab1title="Nokia Health Items (%s)" % len(self.plugin.get_items()), tab2title="OAuth2 Data", authorize_url=self._auth.get_authorize_url(), p=self.plugin, token_expiry=datetime.datetime.fromtimestamp(self.plugin.get_item( - 'token_expiry')(), tz=self.plugin.shtime.tzinfo()), now = self.plugin.shtime.now(), code=code) + 'token_expiry')(), tz=self.plugin.shtime.tzinfo()), now=self.plugin.shtime.now(), code=code, + state=state, reload=reload) diff --git a/nokia_health/locale.yaml b/nokia_health/locale.yaml index 7ed129ccb..6d729e90c 100644 --- a/nokia_health/locale.yaml +++ b/nokia_health/locale.yaml @@ -14,4 +14,10 @@ plugin_translations: 'en': 'OAuth2 Authorization URL' 'Callback URL': 'de': 'Callback URL' - 'en': 'Callback URL' \ No newline at end of file + 'en': 'Callback URL' + 'Code Parameter für OAuth2 an Callback gesendet. Bitte Prüfen, ob die Werte, insbesondere Token Expiry aktualisiert wurden. Der Code ist nur einmal gültig, daher ist bspw. beim Reload der Seite mit gestztem "code" Parameter keine Änderung an Token Expiry mehr zu sehen!': + 'de': 'Code Parameter für OAuth2 an Callback Funktion gesendet. Bitte Prüfen, ob die Werte, insbesondere Token Expiry aktualisiert wurden. Der Code ist nur einmal gültig, daher ist bspw. beim Reload der Seite mit gestztem "code" Parameter keine Änderung an Token Expiry mehr zu sehen!' + 'en': 'Code parameter sent to callback function for OAuth2. Please verify, if the values, especially Token Expiry have updated. The code is valid only for one time. So when e.g. reloading the page with set "code" parameter, no change will happend anymore.' + 'Code': + 'de': 'Code' + 'en': 'Code' \ No newline at end of file diff --git a/nokia_health/webif/templates/index.html b/nokia_health/webif/templates/index.html index b89ab0549..038329c07 100644 --- a/nokia_health/webif/templates/index.html +++ b/nokia_health/webif/templates/index.html @@ -32,6 +32,16 @@ {% endif %} +{% if code and not reload %} + +{% endif %}
From 382f6355ae0e0ca80d69d6572cec686389d7a530 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 08:13:33 +0200 Subject: [PATCH 136/705] Nokia Health: small updates --- nokia_health/locale.yaml | 5 ++++- nokia_health/webif/templates/index.html | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/nokia_health/locale.yaml b/nokia_health/locale.yaml index 6d729e90c..1b19878e4 100644 --- a/nokia_health/locale.yaml +++ b/nokia_health/locale.yaml @@ -20,4 +20,7 @@ plugin_translations: 'en': 'Code parameter sent to callback function for OAuth2. Please verify, if the values, especially Token Expiry have updated. The code is valid only for one time. So when e.g. reloading the page with set "code" parameter, no change will happend anymore.' 'Code': 'de': 'Code' - 'en': 'Code' \ No newline at end of file + 'en': 'Code' + 'State': + 'de': 'State' + 'en': 'State' \ No newline at end of file diff --git a/nokia_health/webif/templates/index.html b/nokia_health/webif/templates/index.html index 038329c07..115a71443 100644 --- a/nokia_health/webif/templates/index.html +++ b/nokia_health/webif/templates/index.html @@ -35,8 +35,9 @@ {% if code and not reload %} {% endif %} +{% if p.get_item('token_expiry')() == 0 %} + +{% endif %} {% if code and not reload %}
From 273dc1e2256f603b7fc9e912c386a9b7bb3d6333 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 09:36:04 +0200 Subject: [PATCH 138/705] Nokia Health: added info translation --- nokia_health/locale.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/nokia_health/locale.yaml b/nokia_health/locale.yaml index 9642b4c69..c0a467d88 100644 --- a/nokia_health/locale.yaml +++ b/nokia_health/locale.yaml @@ -1,5 +1,6 @@ plugin_translations: 'Warnung': {'de': 'Warnung', 'en': 'Warning'} + 'Info': {'de': 'Info', 'en': 'Info'} 'Das Token ist abgelaufen und wurde nicht verlängert. Bitte den OAuth2 Prozess neu starten.': 'de': 'Das Token ist abgelaufen und wurde nicht verlängert. Bitte den OAuth2 Prozess neu starten.' 'en': 'The token has expired and was not renewed. Please start OAuth2 process again.' From 67cef50dcd230b8d94b82ff718a327a788d77840 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 09:46:57 +0200 Subject: [PATCH 139/705] Nokia Health: fix for english dates --- nokia_health/__init__.py | 2 +- nokia_health/webif/templates/index.html | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/nokia_health/__init__.py b/nokia_health/__init__.py index c97cece75..f4a1f6ef0 100644 --- a/nokia_health/__init__.py +++ b/nokia_health/__init__.py @@ -395,4 +395,4 @@ def index(self, reload=None, state=None, code=None, error=None): tab2title="OAuth2 Data", authorize_url=self._auth.get_authorize_url(), p=self.plugin, token_expiry=datetime.datetime.fromtimestamp(self.plugin.get_item( 'token_expiry')(), tz=self.plugin.shtime.tzinfo()), now=self.plugin.shtime.now(), code=code, - state=state, reload=reload) + state=state, reload=reload, language=self.plugin.get_sh().get_defaultlanguage()) diff --git a/nokia_health/webif/templates/index.html b/nokia_health/webif/templates/index.html index 49bcd02c5..00cac9e7a 100644 --- a/nokia_health/webif/templates/index.html +++ b/nokia_health/webif/templates/index.html @@ -75,9 +75,9 @@
{{ _('Nokia Health Items') }} ({{ p.get_items()|length }})
- - - + + + {% endfor %} @@ -109,7 +109,7 @@
{{ _('Nokia Health Items') }} ({{ p.get_items()|length }})
- + From 340cfd30839d342d5fbdde0ced15d7fe0a48df28 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 09:47:15 +0200 Subject: [PATCH 140/705] Database: adjusted referencing sh from plugin --- database/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/database/__init__.py b/database/__init__.py index 65bb2934a..8732583c0 100644 --- a/database/__init__.py +++ b/database/__init__.py @@ -811,8 +811,8 @@ def db_dump(self): returns the smarthomeNG sqlite database as download """ - self.plugin.dump('%s/var/db/smarthomedb_%s.dump' % (self.plugin._sh.base_dir, self.plugin.get_instance_name())) + self.plugin.dump('%s/var/db/smarthomedb_%s.dump' % (self.plugin.get_sh().base_dir, self.plugin.get_instance_name())) mime = 'application/octet-stream' return cherrypy.lib.static.serve_file( - "%s/var/db/smarthomedb_%s.dump" % (self.plugin._sh.base_dir, self.plugin.get_instance_name()), - mime, "%s/var/db/" % self.plugin._sh.base_dir) + "%s/var/db/smarthomedb_%s.dump" % (self.plugin.get_sh().base_dir, self.plugin.get_instance_name()), + mime, "%s/var/db/" % self.plugin.get_sh().base_dir) From 6aac6a83cdcd878064e1d83e15eb5f618f1c22a3 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 11:01:12 +0200 Subject: [PATCH 141/705] Nokia Health: added font-weight: bold for mandatory items --- nokia_health/webif/templates/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nokia_health/webif/templates/index.html b/nokia_health/webif/templates/index.html index 00cac9e7a..09c80805f 100644 --- a/nokia_health/webif/templates/index.html +++ b/nokia_health/webif/templates/index.html @@ -72,10 +72,10 @@
{{ _('Nokia Health Items') }} ({{ p.get_items()|length }})
{% for key, item in p.get_items().items() %} - + - + From 449e7a34b3d7e3eeb43db7dccfcf45c85d5bd96b Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 12:03:56 +0200 Subject: [PATCH 142/705] Nokia Health: update to callback function and gui after token renewal --- nokia_health/__init__.py | 11 +++++++++-- nokia_health/webif/templates/index.html | 4 ++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/nokia_health/__init__.py b/nokia_health/__init__.py index f4a1f6ef0..0d00a62ec 100644 --- a/nokia_health/__init__.py +++ b/nokia_health/__init__.py @@ -62,7 +62,7 @@ def _store_tokens(self, token): format(self.get_fullname(), token['access_token'], token['expires_in'], token['token_type'], token['refresh_token'])) self.get_item('access_token')(token['access_token']) - self.get_item('token_expiry')(token['expires_in']) + self.get_item('token_expiry')(int((self.shtime.utcnow() - datetime.datetime(1970, 1, 1)).total_seconds())+int(token['expires_in'])) self.get_item('token_type')(token['token_type']) self.get_item('refresh_token')(token['refresh_token']) @@ -98,6 +98,13 @@ def _update(self): ('bone_mass', 88), ('pulse_wave_velocity', 91) """ + + if 'access_token' not in self.get_items() or 'token_expiry' not in self.get_items() or 'token_type' not in self.get_items() or 'refresh_token' not in self.get_items(): + self.logger.error( + "Plugin '{}': Mandatory Items for OAuth2 Data do not exist. Verify that you have items with nh_type: token_expiry, token_type, refresh_token and access_token in your item tree.".format( + self.get_fullname())) + return + if self._client is None: if self.get_item('access_token')() and self.get_item( 'token_expiry')() > 0 and self.get_item( @@ -132,7 +139,7 @@ def _update(self): 'token_expiry')(), tz=self.shtime.tzinfo()).strftime('%d.%m.%Y %H:%M:%S'))) else: self.logger.error( - "Plugin '{}': Items for OAuth2 Data not set. Please run process via WebGUI of the plugin.".format( + "Plugin '{}': Items for OAuth2 Data are not set with required values. Please run process via WebGUI of the plugin.".format( self.get_fullname())) return measures = self._client.get_measures() diff --git a/nokia_health/webif/templates/index.html b/nokia_health/webif/templates/index.html index 09c80805f..36b7b31a8 100644 --- a/nokia_health/webif/templates/index.html +++ b/nokia_health/webif/templates/index.html @@ -75,7 +75,7 @@
{{ _('Nokia Health Items') }} ({{ p.get_items()|length }})
- + @@ -109,7 +109,7 @@
{{ _('Nokia Health Items') }} ({{ p.get_items()|length }})
- + From 1c0d2939191fd7d4ed6e08a39730daaeb0781a1a Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 12:08:13 +0200 Subject: [PATCH 143/705] Database: changes rolled back as travis failed --- database/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/database/__init__.py b/database/__init__.py index 8732583c0..65bb2934a 100644 --- a/database/__init__.py +++ b/database/__init__.py @@ -811,8 +811,8 @@ def db_dump(self): returns the smarthomeNG sqlite database as download """ - self.plugin.dump('%s/var/db/smarthomedb_%s.dump' % (self.plugin.get_sh().base_dir, self.plugin.get_instance_name())) + self.plugin.dump('%s/var/db/smarthomedb_%s.dump' % (self.plugin._sh.base_dir, self.plugin.get_instance_name())) mime = 'application/octet-stream' return cherrypy.lib.static.serve_file( - "%s/var/db/smarthomedb_%s.dump" % (self.plugin.get_sh().base_dir, self.plugin.get_instance_name()), - mime, "%s/var/db/" % self.plugin.get_sh().base_dir) + "%s/var/db/smarthomedb_%s.dump" % (self.plugin._sh.base_dir, self.plugin.get_instance_name()), + mime, "%s/var/db/" % self.plugin._sh.base_dir) From aa7c9eb35ed9010f401c548c516038d29e401677 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 13:21:37 +0200 Subject: [PATCH 144/705] Nokia Health: fixed logging level --- nokia_health/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nokia_health/__init__.py b/nokia_health/__init__.py index 0d00a62ec..8e7189e43 100644 --- a/nokia_health/__init__.py +++ b/nokia_health/__init__.py @@ -112,7 +112,7 @@ def _update(self): if (self.shtime.now() < datetime.datetime.fromtimestamp(self.get_item( 'token_expiry')(), tz=self.shtime.tzinfo())): - self.logger.error( + self.logger.debug( "Plugin '{}': Token is valid, will expire on {}.".format( self.get_fullname(), datetime.datetime.fromtimestamp(self.get_item( 'token_expiry')(), tz=self.shtime.tzinfo()).strftime('%d.%m.%Y %H:%M:%S'))) From 5352975cc17bdee1c127a74965a41c4e40854f00 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 13:22:23 +0200 Subject: [PATCH 145/705] NUKI: made noWait Flag configurable to resolve 503 issues with requests --- nuki/__init__.py | 5 +++-- nuki/plugin.yaml | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/nuki/__init__.py b/nuki/__init__.py index 9e68d973c..c653bec5f 100644 --- a/nuki/__init__.py +++ b/nuki/__init__.py @@ -83,7 +83,7 @@ def __init__(self, sh, *args, **kwargs): self._callback_ip = self.get_parameter_value('bridge_callback_ip') self._callback_port = self.get_parameter_value('bridge_callback_port') self._action = '' - self._noWait = '' + self._noWait = self.get_parameter_value('no_wait') if self._callback_ip is None or self._callback_ip in ['0.0.0.0', '']: self._callback_ip = self.get_local_ipv4_address() @@ -243,7 +243,8 @@ def _api_call(self, base_url, endpoint=None, nuki_id=None, token=None, action=No if action is not None: payload['action'] = action if no_wait is not None: - payload['noWait'] = no_wait + payload['noWait'] = int(no_wait) + self._logger.debug("Nuki: noWait is {}".format(int(no_wait))) if callback_url is not None: payload['url'] = callback_url if id is not None: diff --git a/nuki/plugin.yaml b/nuki/plugin.yaml index a1e7368aa..2725bba5e 100755 --- a/nuki/plugin.yaml +++ b/nuki/plugin.yaml @@ -63,6 +63,13 @@ parameters: de: '(optional) Zu verwendendes Protokoll für die Kommunikaton mit der NUKI Bridge. Default: http.' en: '(optional) Protocol for communication with NUKE bridge. Default http.' + no_wait: + type: bool + mandatory: False + default: True + description: + de: '(optional) Flag, ob gewartet werden soll, bis die Aktion des Schlosses beendet ist. False kann zu Fehler bei Requests an die NUKI Bridge führen. Default: True' + en: '(optional) Flag indicating whether or not to wait for the lock action to complete and return its result. 0 may lead to errors in requests to NUKI Bridge. Default: True' item_attributes: # Definition of item attributes defined by this plugin From c163d2a2c51cb644b74db6b7f9ad0766d28419d6 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 13:45:06 +0200 Subject: [PATCH 146/705] Database: once more migration to self.getSh() --- database/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/database/__init__.py b/database/__init__.py index 65bb2934a..8732583c0 100644 --- a/database/__init__.py +++ b/database/__init__.py @@ -811,8 +811,8 @@ def db_dump(self): returns the smarthomeNG sqlite database as download """ - self.plugin.dump('%s/var/db/smarthomedb_%s.dump' % (self.plugin._sh.base_dir, self.plugin.get_instance_name())) + self.plugin.dump('%s/var/db/smarthomedb_%s.dump' % (self.plugin.get_sh().base_dir, self.plugin.get_instance_name())) mime = 'application/octet-stream' return cherrypy.lib.static.serve_file( - "%s/var/db/smarthomedb_%s.dump" % (self.plugin._sh.base_dir, self.plugin.get_instance_name()), - mime, "%s/var/db/" % self.plugin._sh.base_dir) + "%s/var/db/smarthomedb_%s.dump" % (self.plugin.get_sh().base_dir, self.plugin.get_instance_name()), + mime, "%s/var/db/" % self.plugin.get_sh().base_dir) From 6714f09862e8dbda17fa6562bac6bc07f92aa8d0 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 15:06:51 +0200 Subject: [PATCH 147/705] Nokia Health: changed to standard datetime for expiry calculation --- nokia_health/__init__.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/nokia_health/__init__.py b/nokia_health/__init__.py index 8e7189e43..966aa07e0 100644 --- a/nokia_health/__init__.py +++ b/nokia_health/__init__.py @@ -62,7 +62,8 @@ def _store_tokens(self, token): format(self.get_fullname(), token['access_token'], token['expires_in'], token['token_type'], token['refresh_token'])) self.get_item('access_token')(token['access_token']) - self.get_item('token_expiry')(int((self.shtime.utcnow() - datetime.datetime(1970, 1, 1)).total_seconds())+int(token['expires_in'])) + self.get_item('token_expiry')( + int((self.shtime.utcnow() - datetime.datetime(1970, 1, 1)).total_seconds()) + int(token['expires_in'])) self.get_item('token_type')(token['token_type']) self.get_item('refresh_token')(token['refresh_token']) @@ -101,8 +102,8 @@ def _update(self): if 'access_token' not in self.get_items() or 'token_expiry' not in self.get_items() or 'token_type' not in self.get_items() or 'refresh_token' not in self.get_items(): self.logger.error( - "Plugin '{}': Mandatory Items for OAuth2 Data do not exist. Verify that you have items with nh_type: token_expiry, token_type, refresh_token and access_token in your item tree.".format( - self.get_fullname())) + "Plugin '{}': Mandatory Items for OAuth2 Data do not exist. Verify that you have items with nh_type: token_expiry, token_type, refresh_token and access_token in your item tree.".format( + self.get_fullname())) return if self._client is None: @@ -110,7 +111,7 @@ def _update(self): 'token_expiry')() > 0 and self.get_item( 'token_type')() and self.get_item('refresh_token')(): - if (self.shtime.now() < datetime.datetime.fromtimestamp(self.get_item( + if (datetime.datetime.utcnow() < datetime.datetime.fromtimestamp(self.get_item( 'token_expiry')(), tz=self.shtime.tzinfo())): self.logger.debug( "Plugin '{}': Token is valid, will expire on {}.".format( From 59836a38152405158a19d40869e149ce4235fbda Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 15:09:27 +0200 Subject: [PATCH 148/705] Nokia Health: updated wrong line --- nokia_health/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nokia_health/__init__.py b/nokia_health/__init__.py index 966aa07e0..f5d5aa669 100644 --- a/nokia_health/__init__.py +++ b/nokia_health/__init__.py @@ -63,7 +63,7 @@ def _store_tokens(self, token): token['refresh_token'])) self.get_item('access_token')(token['access_token']) self.get_item('token_expiry')( - int((self.shtime.utcnow() - datetime.datetime(1970, 1, 1)).total_seconds()) + int(token['expires_in'])) + int((datetime.datetime.utcnow() - datetime.datetime(1970, 1, 1)).total_seconds()) + int(token['expires_in'])) self.get_item('token_type')(token['token_type']) self.get_item('refresh_token')(token['refresh_token']) @@ -111,7 +111,7 @@ def _update(self): 'token_expiry')() > 0 and self.get_item( 'token_type')() and self.get_item('refresh_token')(): - if (datetime.datetime.utcnow() < datetime.datetime.fromtimestamp(self.get_item( + if (self.shtime.now() < datetime.datetime.fromtimestamp(self.get_item( 'token_expiry')(), tz=self.shtime.tzinfo())): self.logger.debug( "Plugin '{}': Token is valid, will expire on {}.".format( From 7dc4ef337966ecd913e14ef916739e078e893bb4 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 15:16:28 +0200 Subject: [PATCH 149/705] NUKI: get empty responses due to 503 error --- nuki/__init__.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/nuki/__init__.py b/nuki/__init__.py index c653bec5f..f54dd692b 100644 --- a/nuki/__init__.py +++ b/nuki/__init__.py @@ -159,9 +159,12 @@ def update_item(self, item, caller=None, source=None, dest=None): response = self._api_call(self._base_url, nuki_id=nuki_action_items[item], endpoint='lockAction', action=action, token=self._token, no_wait=self._noWait) - if response['success']: - # self._get_nuki_status() - self._logger.info("Nuki: update item: {0}".format(item.id())) + if response is not None: + if response['success']: + # self._get_nuki_status() + self._logger.info("Nuki: update item: {0}".format(item.id())) + else: + self._logger.error("Nuki: no response.") @staticmethod def update_lock_state(nuki_id, lock_state): From f4f6e1968b178b8a0d9dc1131d05a905ee659a78 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 18:45:27 +0200 Subject: [PATCH 150/705] Traffic: upgraded to new init method style and logging format --- traffic/README.md | 2 -- traffic/__init__.py | 11 +++++------ traffic/plugin.yaml | 4 ++-- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/traffic/README.md b/traffic/README.md index 80f31a173..2e58204b5 100644 --- a/traffic/README.md +++ b/traffic/README.md @@ -1,7 +1,5 @@ # Traffic -Version 0.1 - This plugin provides functionality to query the Google Directions API for traffic / direction info. All mappings to items need to be done via your own logic. diff --git a/traffic/__init__.py b/traffic/__init__.py index 15261febb..bf3955ccc 100644 --- a/traffic/__init__.py +++ b/traffic/__init__.py @@ -28,10 +28,10 @@ class Traffic(SmartPlugin): ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.3.0.1" + PLUGIN_VERSION = "1.5.0.2" _base_url = 'https://maps.googleapis.com/maps/api/directions/json' - def __init__(self, smarthome, apikey, language='de'): + def __init__(self, sh, *args, **kwargs): """ Initializes the plugin @param apikey: For accessing the free "Google Directions API" you need a personal @@ -39,9 +39,8 @@ def __init__(self, smarthome, apikey, language='de'): @param language: two char language code. default: de """ self.logger = logging.getLogger(__name__) - self._sh = smarthome - self._apikey = apikey - self._language = language + self._apikey = self.get_parameter_value('apikey') + self._language = self.get_parameter_value('language') self._session = requests.Session() def run(self): @@ -68,7 +67,7 @@ def get_route_info(self, origin, destination, alternatives=False, departure_time self._language, alternatives, origin, destination, mode, departure_time, self._apikey)) except Exception as e: self.logger.error( - "Exception when sending GET request for get_route_info: %s" % str(e)) + "Plugin '{}': Exception when sending GET request for get_route_info: {}".format(self.get_fullname(), str(e))) return json_obj = response.json() route_information = {} diff --git a/traffic/plugin.yaml b/traffic/plugin.yaml index 5672e4b96..483ac9fbc 100755 --- a/traffic/plugin.yaml +++ b/traffic/plugin.yaml @@ -11,8 +11,8 @@ plugin: documentation: http://smarthomeng.de/user/plugins_doc/config/traffic.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1048446-traffic-plugin-support-thread - version: 1.3.0.1 # Plugin version - sh_minversion: 1.3 # minimum shNG version to use this plugin + version: 1.5.0.2 # Plugin version + sh_minversion: 1.5 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance classname: Traffic # class containing the plugin From 8ec85a606db9e5dcb8c85cee9f629031f8e12ef4 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 18:52:00 +0200 Subject: [PATCH 151/705] =?UTF-8?q?Tankerk=C3=B6nig:=20updated=20logging?= =?UTF-8?q?=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tankerkoenig/__init__.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/tankerkoenig/__init__.py b/tankerkoenig/__init__.py index 0494f9b2b..d267c6fbc 100755 --- a/tankerkoenig/__init__.py +++ b/tankerkoenig/__init__.py @@ -65,18 +65,19 @@ def get_petrol_stations(self, lat, lon, type='diesel', sort='price', rad='4'): result_stations = [] try: response = self._session.get(self._build_url("%s?lat=%s&lng=%s&rad=%s&sort=%s&type=%s&apikey=%s" % ( - self._list_url_suffix, lat, lon, rad, sort, type, self._apikey))) + self._list_url_suffix, lat, lon, rad, sort, type, self._apikey))) except Exception as e: self.logger.error( "Exception when sending GET request for get_petrol_stations: %s" % str(e)) return - self.logger.debug(self._build_url("%s?lat=%s&lng=%s&rad=%s&sort=%s&type=%s&apikey=%s" % ( - self._list_url_suffix, lat, lon, rad, sort, type, self._apikey))) + self.logger.debug("Plugin '{}': {}".format(self.get_fullname(), self._build_url( + "%s?lat=%s&lng=%s&rad=%s&sort=%s&type=%s&apikey=%s" % ( + self._list_url_suffix, lat, lon, rad, sort, type, self._apikey)))) json_obj = response.json() keys = ['place', 'brand', 'houseNumber', 'street', 'id', 'lng', 'name', 'lat', 'price', 'dist', 'isOpen', 'postCode'] if json_obj.get('stations', None) is None: - self.logger.warning("Tankerkönig didn't return any station") + self.logger.warning("Plugin '{}': Tankerkönig didn't return any station".format(self.get_fullname())) else: for i in json_obj['stations']: result_station = {} @@ -97,7 +98,8 @@ def get_petrol_station_detail(self, id): self._build_url("%s?id=%s&apikey=%s" % (self._detail_url_suffix, id, self._apikey))) except Exception as e: self.logger.error( - "Exception when sending GET request for get_petrol_station_detail: %s" % str(e)) + "Plugin '{}': Exception when sending GET request for get_petrol_station_detail: {}".format( + self.get_fullname(), str(e))) return json_obj = response.json() keys = ['e5', 'e10', 'diesel', 'street', 'houseNumber', 'postCode', 'place', 'brand', 'id', 'lng', 'name', @@ -126,7 +128,8 @@ def get_petrol_station_prices(self, ids): self._build_url("%s?ids=%s&apikey=%s" % (self._prices_url_suffix, station_ids_string, self._apikey))) except Exception as e: self.logger.error( - "Exception when sending GET request for get_petrol_station_detail: %s" % str(e)) + "Plugin '{}': Exception when sending GET request for get_petrol_station_detail: {}".format( + self.get_fullname(), str(e))) return json_obj = response.json() keys = ['e5', 'e10', 'diesel', 'status'] @@ -143,9 +146,13 @@ def get_petrol_station_prices(self, ids): result_station[key] = "" result_station_prices.append(result_station) else: - self.logger.error("No result for station with id %s. Check manually!" % id) + self.logger.error( + "Plugin '{}': No result for station with id {}. Check manually!".format( + self.get_fullname(), id)) else: - self.logger.error("'prices' key missing in json response! Check manually!" % id) + self.logger.error( + "Plugin '{}': 'prices' key missing in json response for station with id {}. Check manually!".format( + self.get_fullname(), id)) return result_station_prices def _build_url(self, suffix): From 5a3eed6926556b525e9bee8e6292418b06f073c1 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 18:59:11 +0200 Subject: [PATCH 152/705] Webservices: upgraded to items api --- webservices/__init__.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/webservices/__init__.py b/webservices/__init__.py index 9afef9b94..37142f825 100644 --- a/webservices/__init__.py +++ b/webservices/__init__.py @@ -29,7 +29,7 @@ import cherrypy from lib.model.smartplugin import * - +from lib.item import Items from lib.module import Modules @@ -41,6 +41,7 @@ def __init__(self, smarthome, mode="all"): self.logger = logging.getLogger(__name__) self.logger.debug('Backend.__init__') self._mode = mode + self.items = Items.get_instance() if not self.init_webinterfaces(): self._init_complete = False @@ -141,7 +142,7 @@ def index(self, reload=None): """ items_filtered = [] item_sets = {} - items_sorted = sorted(self.plugin.get_sh().return_items(), key=lambda k: str.lower(k['_path']), reverse=False) + items_sorted = sorted(self.plugin.items.return_items(), key=lambda k: str.lower(k['_path']), reverse=False) for item in items_sorted: if self.plugin.get_mode() == 'all' or self.plugin.has_iattr(item.conf, 'webservices_set'): if item.type() in ['str', 'bool', 'num'] or ( @@ -277,7 +278,7 @@ def itemset(self, set_id=None, mode=None): return {"Error": "%s requests not allowed for this URL" % cherrypy.request.method} elif cherrypy.request.method == 'GET': - items_sorted = sorted(self.plugin.get_sh().return_items(), key=lambda k: str.lower(k['_path']), + items_sorted = sorted(self.plugin.items.return_items(), key=lambda k: str.lower(k['_path']), reverse=False) items = {} for item in items_sorted: @@ -311,7 +312,7 @@ def items(self, item_path=None, value=None, mode=None): return {"Error": "%s requests not allowed for this URL" % cherrypy.request.method} elif cherrypy.request.method == 'GET': - items_sorted = sorted(self.plugin.return_items(), key=lambda k: str.lower(k['_path']), + items_sorted = sorted(self.plugin.items.return_items(), key=lambda k: str.lower(k['_path']), reverse=False) items = {} for item in items_sorted: @@ -370,7 +371,7 @@ def itemset(self, set_id=None, mode=None): return {"Error": "%s requests not allowed for this URL" % cherrypy.request.method} elif cherrypy.request.method == 'GET': - items_sorted = sorted(self.plugin.get_sh().return_items(), key=lambda k: str.lower(k['_path']), + items_sorted = sorted(self.plugin.items.return_items(), key=lambda k: str.lower(k['_path']), reverse=False) items = {} for item in items_sorted: @@ -405,7 +406,7 @@ def items(self, item_path=None, mode=None): return {"Error": "%s requests not allowed for this URL" % cherrypy.request.method} elif cherrypy.request.method == 'GET': - items_sorted = sorted(self.plugin.get_sh().return_items(), key=lambda k: str.lower(k['_path']), + items_sorted = sorted(self.plugin.items.return_items(), key=lambda k: str.lower(k['_path']), reverse=False) items = {} for item in items_sorted: From bde9692a820ede31f974e0e6e4275490a9d37dce Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 19:02:55 +0200 Subject: [PATCH 153/705] Webservices: slight changes to logging --- webservices/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/webservices/__init__.py b/webservices/__init__.py index 37142f825..e4bfd34f1 100644 --- a/webservices/__init__.py +++ b/webservices/__init__.py @@ -39,7 +39,7 @@ class WebServices(SmartPlugin): def __init__(self, smarthome, mode="all"): self.logger = logging.getLogger(__name__) - self.logger.debug('Backend.__init__') + self.logger.debug("Plugin '{}': '__init__'".format(self.get_fullname())) self._mode = mode self.items = Items.get_instance() @@ -56,7 +56,7 @@ def init_webinterfaces(self): except: self.mod_http = None if self.mod_http == None: - self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_shortname())) + self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_fullname())) return False webif_dir = self.path_join(self.get_plugin_dir(), 'webif') @@ -99,14 +99,14 @@ def run(self): """ Run method for the plugin """ - self.logger.debug("Plugin '{}': run method called".format(self.get_shortname())) + self.logger.debug("Plugin '{}': run method called".format(self.get_fullname())) self.alive = True def stop(self): """ Stop method for the plugin """ - self.logger.debug("Plugin '{}': stop method called".format(self.get_shortname())) + self.logger.debug("Plugin '{}': stop method called".format(self.get_fullname())) self.alive = False From 76f509dda0abc504d096ff6ece8610b7110e027d Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 19:04:22 +0200 Subject: [PATCH 154/705] =?UTF-8?q?OpenWeatherMap:=20removed=20code=20comm?= =?UTF-8?q?ent=20from=20Tankerk=C3=B6nig=20Plugin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- openweathermap/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/openweathermap/__init__.py b/openweathermap/__init__.py index b3510e186..0a9011625 100644 --- a/openweathermap/__init__.py +++ b/openweathermap/__init__.py @@ -39,8 +39,6 @@ class OpenWeatherMap(SmartPlugin): def __init__(self, sh, *args, **kwargs): """ Initializes the plugin - @param apikey: For accessing the free "Tankerkönig-Spritpreis-API" you need a personal - api key. For your own key register to https://creativecommons.tankerkoenig.de """ self.logger = logging.getLogger(__name__) self._key = self.get_parameter_value('key') From 9e49705668a7b9633913e81f89839001a07a3600 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 19:05:18 +0200 Subject: [PATCH 155/705] =?UTF-8?q?Darksky:=20removed=20code=20comment=20f?= =?UTF-8?q?rom=20tankerk=C3=B6nig=20plugin?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- darksky/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/darksky/__init__.py b/darksky/__init__.py index 7adee84e9..7d0d646f8 100644 --- a/darksky/__init__.py +++ b/darksky/__init__.py @@ -39,8 +39,6 @@ class DarkSky(SmartPlugin): def __init__(self, sh, *args, **kwargs): """ Initializes the plugin - @param apikey: For accessing the free "Tankerkönig-Spritpreis-API" you need a personal - api key. For your own key register to https://creativecommons.tankerkoenig.de """ self.logger = logging.getLogger(__name__) self._key = self.get_parameter_value('key') From 7c9f814f3a40bcf34e61b0793d7f004de543f96a Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 24 Aug 2018 19:11:07 +0200 Subject: [PATCH 156/705] Miflora: adjusted logging --- miflora/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/miflora/__init__.py b/miflora/__init__.py index 31e7427f6..209408868 100644 --- a/miflora/__init__.py +++ b/miflora/__init__.py @@ -49,7 +49,7 @@ def run(self): """ Run method for the plugin """ - self.logger.debug("run method called") + self.logger.debug("Plugin '{}': 'run' method called.".format(self.get_fullname())) self._sh.scheduler.add(__name__, self._update_loop, prio=7, cycle=self._cycle) self.alive = True @@ -57,11 +57,11 @@ def stop(self): """ Stop method for the plugin """ - self.logger.debug("stop method called") + self.logger.debug("Plugin '{}': 'stop' method called.".format(self.get_fullname())) try: self._sh.scheduler.remove(__name__) except: - self.logger.error("removing of scheduler failed: {}".format(sys.exc_info())) + self.logger.error("Plugin '{}': Removing of scheduler failed: {}.".format(self.get_fullname(), sys.exc_info())) self.alive = False @@ -73,7 +73,7 @@ def parse_item(self, item): :param item: The item to process. """ if self.has_iattr(item.conf, 'xiaomi_data_type'): - self.logger.debug("parse item: {0}".format(item)) + self.logger.debug("Plugin '{}': Parse item: {}.".format(self.get_fullname(), item)) self._items.append(item) def _update_loop(self): From 0a8fe8655d890495dcf8d30df8af726194250136 Mon Sep 17 00:00:00 2001 From: msinn Date: Sat, 25 Aug 2018 00:55:23 +0200 Subject: [PATCH 157/705] Retired old plugin versions of homematic and mqtt --- homematic1/README.md | 44 ------------ homematic1/__init__.py | 148 ----------------------------------------- homematic1/plugin.yaml | 26 -------- mqtt_1_0/README.md | 70 ------------------- mqtt_1_0/__init__.py | 141 --------------------------------------- mqtt_1_0/plugin.yaml | 25 ------- 6 files changed, 454 deletions(-) delete mode 100644 homematic1/README.md delete mode 100644 homematic1/__init__.py delete mode 100755 homematic1/plugin.yaml delete mode 100644 mqtt_1_0/README.md delete mode 100755 mqtt_1_0/__init__.py delete mode 100755 mqtt_1_0/plugin.yaml diff --git a/homematic1/README.md b/homematic1/README.md deleted file mode 100644 index 6f1155475..000000000 --- a/homematic1/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# homematic - -## Requirements - -Homematic Hardware Gateway - -## Configuration - -### plugin.yaml - -``` -homematic: - class_name: Homematic - class_path: plugins.homematic - host: 192.168.50.250 - # port: 2001 - # cycle: 60 -``` - -## items.yaml - -```yaml - deckenlicht_sofa: - name: Deckenlicht Sofa - visu: yes - type: bool - hm_address: JEQ0017982 - hm_type: switch -``` - -### hm_type - -Possible values - -- for switches: - - - switch - - 2ch_switch - -- for raffstores: - - - pos - - stop - - move diff --git a/homematic1/__init__.py b/homematic1/__init__.py deleted file mode 100644 index 96c561918..000000000 --- a/homematic1/__init__.py +++ /dev/null @@ -1,148 +0,0 @@ -#!/usr/bin/env python -# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab -######################################################################### -# Copyright 2013 KNX-User-Forum e.V. https://knx-user-forum.de/ -######################################################################### -# This file is part of SmartHomeNG -# https://github.com/smarthomeNG/smarthome -# http://knx-user-forum.de/ - -# SmartHomeNG is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# SmartHomeNG is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with SmartHomeNG. If not, see . -######################################################################### - -import logging -import sys -import xmlrpc -import xmlrpc.server -import xmlrpc.client - - -class Homematic(): - - def __init__(self, smarthome, host='0.0.0.0', port='2001', cycle='60'): - self.logger = logging.getLogger(__name__) - self.sh = smarthome - self.host = host - self.port = port - self._cycle = int(cycle) - self.korrektur = 0 - - - def run(self): - """ - Run method for the plugin - """ - self.sh.scheduler.add(__name__, self._update_loop, cycle=self._cycle) -# self.scheduler_add('update', self._update_loop, cycle=self._cycle) - self.alive = True - - - def _update_loop(self): - """ - Starts the update loop for all known items. - """ - server_url = 'http://' + self.host + ':' + self.port + '/' - self.server = xmlrpc.client.ServerProxy(server_url) - self.load_status() - - - def load_status(self): - for hm_devices in self.sh.find_items('hm_type'): - if hm_devices.conf['hm_type'] == 'pos': - try: - result = self.server.getValue(hm_devices.conf['hm_address'] + ':1', 'LEVEL') - value = 1 - float(result) - hm_devices(int(255 * float(value))) - except Exception as e: - self.logger.error("Could not connect to Homematic Device: " + hm_devices.conf['hm_address']) - elif hm_devices.conf['hm_type'] == 'switch': - try: - result = self.server.getValue(hm_devices.conf['hm_address'] + ':1', 'STATE') - hm_devices(bool(result)) - except Exception as e: - self.logger.error("Could not connect to Homematic Device: " + hm_devices.conf['hm_address']) - elif hm_devices.conf['hm_type'] == '2ch_switch': - try: - result = self.server.getValue(hm_devices.conf['hm_address'] + ':' + hm_devices.conf['hm_channel'], 'STATE') - hm_devices(bool(result)) - except Exception as e: - self.logger.error("Could not connect to Homematic Device: " + hm_devices.conf['hm_address']) - - def stop(self): - self.alive = False - - def parse_item(self, item): - if 'hm_address' in item.conf: - self.logger.debug("parse item: {0}".format(item)) - return self.update_item - else: - return None - - def update_item(self, item, caller=None, source=None, dest=None): - if caller != 'Homematic': - if item.conf['hm_type'] == 'pos': - new_value = float(item()) / 255 - conv_value = 1 - float(new_value) - try: - result = self.server.setValue(item.conf['hm_address'] + ':1', 'LEVEL', str(conv_value)) - self.logger.debug('Homematic: Rollo auf ' + str(conv_value)) - except Exception as e: - self.logger.error("Could not connect to Homematic Device: ".format(e)) - elif item.conf['hm_type'] == 'stop': - item(0) - try: - result = self.server.setValue(item.conf['hm_address'] + ':1', 'STOP', bool('true')) - result2 = self.server.getValue(item.conf['hm_address'] + ':1', 'LEVEL') - for shutter_items in self.sh.find_items('hm_type'): - if shutter_items.conf['hm_type'] == 'pos': - if shutter_items.conf['hm_address'] == item.conf['hm_address']: - akt_value = 1 - float(result2) - shutter_items(int(255 * float(akt_value))) - self.logger.debug('Homematic: Rollo stop...') - except Exception as e: - self.logger.error("Could not connect to Homematic Device: ".format(e)) - elif item.conf['hm_type'] == 'move': - direction = item() - item(2) - if direction == 0: - try: - result = self.server.setValue(item.conf['hm_address'] + ':1', 'LEVEL', '1') - except Exception as e: - self.logger.error("Could not connect to Homematic Device: ".format(e)) - elif direction == 1: - try: - result = self.server.setValue(item.conf['hm_address'] + ':1', 'LEVEL', '0') - result2 = self.server.getValue(item.conf['hm_address'] + ':1', 'LEVEL') - except Exception as e: - self.logger.error("Could not connect to Homematic Device: ".format(e)) - for shutter_items in self.sh.find_items('hm_type'): - if shutter_items.conf['hm_type'] == 'pos': - if shutter_items.conf['hm_address'] == item.conf['hm_address']: - akt_value = 1 - float(result2) - shutter_items(int(255 * float(akt_value))) - elif item.conf['hm_type'] == 'switch': - try: - result = self.server.setValue(item.conf['hm_address'] + ':1', 'STATE', item()) - except Exception as e: - self.logger.error("Could not connect to Homematic Device: ".format(e)) - elif item.conf['hm_type'] == '2ch_switch': - try: - result = self.server.setValue(item.conf['hm_address'] + ':' + item.conf['hm_channel'], 'STATE', item()) - except Exception as e: - self.logger.error("Could not connect to Homematic Device: ".format(e)) - -if __name__ == '__main__': - logging.basicConfig(level=logging.DEBUG) - myplugin = Homematic('homematic') - myplugin.run() diff --git a/homematic1/plugin.yaml b/homematic1/plugin.yaml deleted file mode 100755 index 4e9db5dd8..000000000 --- a/homematic1/plugin.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# Metadata for the classic-plugin -plugin: - # Global plugin attributes - type: interface # plugin type (gateway, interface, protocol, system, web) - description: - de: 'Steuerung von Buderus Heizkesseln über ein Logamatic web KM200 Modul (noch in der Entwicklung)' - en: '' - maintainer: rthill # Who maintains this plugin? -# tester: efgh # Who tests this plugin? -# keywords: kwd1 kwd2 # keywords, where applicable -# documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page -# support: https://knx-user-forum.de/forum/supportforen/smarthome-py - -# Following entries are for Smart-Plugins: -# version: 1.3.3 # Plugin version -# sh_minversion: 1.3 # minimum shNG version to use this plugin -# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) -# multi_instance: False - classname: Homematic # class containing the plugin - -#parameters: - # Definition of parameters to be configured in etc/plugin.yaml - -#item_attributes: - # Definition of item attributes defined by this plugin - diff --git a/mqtt_1_0/README.md b/mqtt_1_0/README.md deleted file mode 100644 index 839d33393..000000000 --- a/mqtt_1_0/README.md +++ /dev/null @@ -1,70 +0,0 @@ -# MQTT 1.0 - -This plugin implements a MQTT client. - -The MQTT protocol was initially developed by IBM. Since protocol version v3.1.1 it has become an official OASIS standard. - -## Requirements - -This plugin needs the following MQTT python modules: - - * [paho-mqtt](https://pypi.python.org/pypi/paho-mqtt) - -In Linux systems can use: - -``` -pip3 install paho-mqtt -``` - -Besides the Python module you need a MQTT broker to communicate to other MQTT clients. The open souce broker [Mosquitto](https://mosquitto.org) is a good choice. - - -## Configuration - -### plugin.yaml - -``` -mqtt: - class_name: Mqtt - class_path: plugins.mqtt - host: '192.168.0.55' - port: 1883 - -``` - - -### items.yaml - -With this attribute you could specify channels to send and receive info. - -#### Example - -```yaml -alarm_in: - # messages coming from the alarm panel - name: alarm_test_mqtt_in - type: foo - mqtt_topic_in: "alarm/out" - -alarm_out: - # messages to send to the alarm panel - name: alarm_test_mqtt_out - type: foo - mqtt_topic_out: "alarm/in" -``` - -Datatype foo delivers the raw data from the mqtt message to the item (as an array of bytes). - -**NEW:** You can use any of the other datatypes. If you use any of those datatypes, the data from the mqtt message will be casted to the desired format. - -Now you could simply use: - -```sh.alarm_out(arm)``` to send a mqtt message via the topic 'alarm/out'. -```sh.alarm_in()``` to see messages coming from mqtt bus via topic 'alarm/in' - -### logic.yaml - -``` -Alarm: - watch_item: alarm_in # monitor for changes -``` diff --git a/mqtt_1_0/__init__.py b/mqtt_1_0/__init__.py deleted file mode 100755 index f10b7bb5c..000000000 --- a/mqtt_1_0/__init__.py +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env python - -# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab -######################################################################### -# Copyright 2017 Martin Sinn m.sinn@gmx.de -# Copyright 2012 KNX-User-Forum e.V. http://knx-user-forum.de/ -######################################################################### -# This file is part of SmartHomeNG. https://github.com/smarthomeNG/ -# -# SmartHomeNG is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# SmartHomeNG is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with SmartHomeNG. If not, see . -# Skender Haxhimolla -######################################################################### - -import logging -import paho.mqtt.client as paho -import paho.mqtt.publish as pahopub -import os -from lib.utils import Utils -import json - -logger = logging.getLogger() - - -class Mqtt(): - - def __init__(self, smarthome, host='127.0.0.1', port='1883'): - self._sh = smarthome - self.clients = [] - self.items = {} - self.logics = {} - if Utils.is_ip(host): - self.broker_ip = host - else: - self.broker_ip = '' - logger.error('MQTT: Invalid ip address for broker specified, plugin not starting') - return - if Utils.is_int(port): - self.broker_port = int(port) - else: - self.broker_port = 1883 - logger.error('MQTT: Invalid port number for broker specified, plugin trying standard port 1883') - self.publisher = self.create_client('main') - - def run(self): - self.alive = True - - def stop(self): - self.alive = False - for client in self.clients: - logger.debug('Stopping mqtt client {0}'.format(client._client_id)) - client.loop_stop() - - def parse_item(self, item): - if 'mqtt_topic' in item.conf: - item.conf['mqtt_topic_in'] = item.conf['mqtt_topic'] - item.conf['mqtt_topic_out'] = item.conf['mqtt_topic'] - logger.debug("parse item: {0}".format(item)) - - if 'mqtt_topic_in' in item.conf: - if self.broker_ip != '': - client = self.create_client(item.id()) -# client.on_message = lambda client, obj, msg: self.items[msg.topic](msg.payload, 'MQTT') - client.on_message = lambda client, obj, msg: self.items[msg.topic](self.cast_mqtt(self.items[msg.topic], msg.payload), 'MQTT') - client.on_connect = lambda client, obj, rc: client.subscribe(item.conf['mqtt_topic_in'], 2) - client.loop_start() - self.items[item.conf['mqtt_topic_in']] = item - logger.debug('Item [{0}] is listening for messages on topic [{1}]'.format(item, item.conf['mqtt_topic_in'])) - - if 'mqtt_topic_out' in item.conf: - return self.update_item - - def parse_logic(self, logic): - if 'mqtt_topic' in logic.conf: - if self.broker_ip != '': - client = self.create_client(logic.name) - client.on_message = lambda client, obj, msg: self.logics[msg.topic].trigger('MQTT', msg.topic, msg.payload) - client.subscribe(logic.conf['mqtt_topic'], 2) - client.loop_start() - self.logics[logic.conf['mqtt_topic']] = logic - logger.debug('Logic [{0}] is listening for messages on topic [{1}]'.format(logic.name, logic.conf['mqtt_topic'])) - - - def update_item(self, item, caller=None, source=None, dest=None): - if self.broker_ip != '': - pahopub.single(topic=item.conf['mqtt_topic_out'], payload=str(item()), qos=2, hostname=self.broker_ip) - logger.info("update item: {0}".format(item.id())) - logger.debug("Mqtt caller item: {0} \t Source: {1} \t Destination:{2}".format(caller, source, dest)) - logger.info("update topic: {0}\t{1}".format(item.conf['mqtt_topic_out'], str(item()))) - - - def cast_mqtt(self, item, raw_data): - """ - Cast input data to SmartHomeNG datatypes - - :param item: item to whichs type the data should be casted - :param raw_data: data as received from the mqtt broker - :return: data casted to the datatype of the item it should be written to - """ - str_data = raw_data.decode('utf-8') - if item.type() == 'str': - data = str_data - elif item.type() == 'num': - data = str_data - elif item.type() == 'bool': - data = Utils.to_bool(str_data, default=False) - elif item.type() == 'list': - if (len(str_data) > 0) and (str_data[0] == '['): - data = json.loads(str_data) - else: - data = json.loads('['+str_data+']') - elif item.type() == 'dict': - data = json.loads(str_data) - elif item.type() == 'scene': - data = '0' - if Utils.is_int(str_data): - if (int(str_data) >= 0) and (int(str_data) < 0): - data = str_data - elif item.type() == 'foo': - data = raw_data - else: - logger.warning("mqtt: item '{}' - Casting to '{}' is not implemented".format(str(item._path), str(item.type()))) - data = raw_data - return data - - - def create_client(self, name): - client = paho.Client('{0}.{1}'.format(os.uname()[1], name)) - client.connect(self.broker_ip, self.broker_port, 60) - self.clients.append(client) - return client diff --git a/mqtt_1_0/plugin.yaml b/mqtt_1_0/plugin.yaml deleted file mode 100755 index b67ccb642..000000000 --- a/mqtt_1_0/plugin.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Metadata for the classic-plugin -plugin: - # Global plugin attributes - type: protocol # plugin type (gateway, interface, protocol, system, web) - description: # Alternative: description in multiple languages - de: 'Implementierung eines MQTT Clients. - veraltet' - en: 'Implementation of a MQTT client. - To be retired' - maintainer: cmalo # Who maintains this plugin? -# tester: efgh # Who tests this plugin? - keywords: iot -# documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page - -# Following entries are for Smart-Plugins: -# version: 1.3.3 # Plugin version -# sh_minversion: 1.3 # minimum shNG version to use this plugin -# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) -# multi_instance: False - classname: Mqtt # class containing the plugin - -#parameters: - # Definition of parameters to be configured in etc/plugin.yaml - -#item_attributes: - # Definition of item attributes defined by this plugin - From 086f6a50df20698240b138b1396e9cb7e05d190d Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sat, 25 Aug 2018 13:28:03 +0200 Subject: [PATCH 158/705] AVM: added valid list for avm_data_type --- avm/plugin.yaml | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/avm/plugin.yaml b/avm/plugin.yaml index 2ea0a3ae9..3c9dedc2f 100755 --- a/avm/plugin.yaml +++ b/avm/plugin.yaml @@ -89,6 +89,62 @@ item_attributes: description: de: 'AVM Datentyp des jeweiligen Items.' en: 'AVM Data Type of the respective item.' + valid_list: + - 'uptime' + - 'serial_number' + - 'software_version' + - 'hardware_version' + - 'myfritz_status' + - 'monitor_trigger' + - 'is_call_incoming' + - 'call_duration_incoming' + - 'last_caller_incoming' + - 'last_number_incoming' + - 'last_called_number_incoming' + - 'last_call_date_incoming' + - 'call_event_incoming' + - 'is_call_outgoing' + - 'call_duration_outgoing' + - 'last_caller_outgoing' + - 'last_number_outgoing' + - 'last_called_number_outgoing' + - 'last_call_date_outgoing' + - 'call_event_outgoing' + - 'call_direction' + - 'call_event' + - 'tam' + - 'tam_name' + - 'tam_old_message_number' + - 'tam_new_message_number' + - 'tam_total_message_number' + - 'wan_connection_status' + - 'wan_connection_error' + - 'wan_is_connected' + - 'wan_uptime' + - 'wan_ip' + - 'wan_upstream' + - 'wan_downstream' + - 'wan_total_packets_sent' + - 'wan_total_packets_received' + - 'wan_current_packets_sent' + - 'wan_current_packets_received' + - 'wan_total_bytes_sent' + - 'wan_total_bytes_received' + - 'wan_current_bytes_sent' + - 'wan_current_bytes_received' + - 'wan_link' + - 'wlanconfig' + - 'wlanconfig_ssid' + - 'wlan_guest_time_remaining' + - 'network_device' + - 'device_ip' + - 'device_connection_type' + - 'device_hostname' + - 'aha_device' + - 'energy' + - 'power' + - 'temperature' + avm_incoming_allowed: type: str description: From 4f1fd2f11e4f4ba47d5a82833f88a7f80ee37c83 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sat, 25 Aug 2018 14:07:01 +0200 Subject: [PATCH 159/705] AVM: corrected mandatory information --- avm/plugin.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/avm/plugin.yaml b/avm/plugin.yaml index 3c9dedc2f..8735d32ed 100755 --- a/avm/plugin.yaml +++ b/avm/plugin.yaml @@ -147,23 +147,25 @@ item_attributes: avm_incoming_allowed: type: str + mandatory: False description: de: '(optional) Definition der erlaubten eingehenden Rufnummer in Items vom avm_data_type `monitor_trigger`.' en: '(optional) Definition of the allowed incoming number. Only in items of avm_data_type `monitor_trigger`.' avm_target_number: type: str + mandatory: False description: de: '(optional) Definition der erlaubten angerufenen Rufnummer in Items vom avm_data_type `monitor_trigger`.' en: '(optional) Definition of the allowed called number. Only in items of avm_data_type `monitor_trigger`.' mac: type: str - mandatory: True + mandatory: False description: de: 'Definition der MAC Adresse für Items vom avm_data_type `network_device`. Nur für diese Items mandatory!' en: 'Definition of the MAC address for items of avm_data_type `network_device`. Only mandatory for these items!' ain: type: str - mandatory: True + mandatory: False description: de: 'Definition der Aktor Identifikationsnummer (AIN)Items vom avm_data_type `aha_device`. Nur für diese Items mandatory!' en: 'Definition of the actor identification number (AIN) for items of avm_data_type `aha_device`. Only mandatory for these items!' From 4347d6e305b58f907f51cbefa45384cf5db4a005 Mon Sep 17 00:00:00 2001 From: msinn Date: Sat, 25 Aug 2018 17:07:38 +0200 Subject: [PATCH 160/705] Added 'state' (develop, ready, qa-passed) to the metadata of some plugins --- homematic/__init__.py | 2 +- homematic/plugin.yaml | 24 ++++++++++++++++++++++++ kodi/plugin.yaml | 1 + visu_smartvisu/plugin.yaml | 1 + visu_websocket/plugin.yaml | 1 + wol/plugin.yaml | 11 ++++++++--- zwave/plugin.yaml | 1 + 7 files changed, 37 insertions(+), 4 deletions(-) diff --git a/homematic/__init__.py b/homematic/__init__.py index c71837d9b..1c0f200e7 100755 --- a/homematic/__init__.py +++ b/homematic/__init__.py @@ -68,7 +68,7 @@ def __init__(self, sh, *args, **kwargs): the configured (and checked) value for a parameter by calling self.get_parameter_value(parameter_name). It returns the value in the datatype that is defined in the metadata. """ - self.logger = logging.getLogger(__name__) +# self.logger = logging.getLogger(__name__) # Exit if the required package(s) could not be imported if not REQUIRED_PACKAGE_IMPORTED: diff --git a/homematic/plugin.yaml b/homematic/plugin.yaml index 14c7cc63f..73d067970 100755 --- a/homematic/plugin.yaml +++ b/homematic/plugin.yaml @@ -6,6 +6,7 @@ plugin: de: 'Ansteuerung von HomeMatic Komponenten über eine HomeMatic CCU2 Zentrale. Es werden HomeMatic und HomeMaticIP Geräte unterstützt.' en: 'Control HomeMatic devices through a HomeMatic CCU2 (used as gateway). HomeMatic and HomeMaticIP devices are supported.' maintainer: msinn # Who maintains this plugin? + state: qa-passed # tester: efgh # Who tests this plugin? # keywords: kwd1 kwd2 # keywords, where applicable # documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page @@ -88,3 +89,26 @@ item_attributes: en: 'Optional: Channel of the devicemon which the function shall be used. Has only to be specified, if the requested function is implemented more than once on the device.' +plugin_functions: + # Definition of function interface of the plugin + + : + type: str + description: + de: '' + en: '' + + parameters: + : + type: int + valid_min: 0 + description: + de: '' + en: '' + + : + type: str + valid_list: ['yes','no','dont know'] + description: + de: '' + en: '' diff --git a/kodi/plugin.yaml b/kodi/plugin.yaml index 1fd2df9d1..00c8f8634 100755 --- a/kodi/plugin.yaml +++ b/kodi/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: '' maintainer: ggf. cmalo (mknx) tester: onkelandy + state: develop keywords: mediacenter # documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page # support: https://knx-user-forum.de/forum/supportforen/smarthome-py diff --git a/visu_smartvisu/plugin.yaml b/visu_smartvisu/plugin.yaml index 3a0703eb1..740a8cb27 100755 --- a/visu_smartvisu/plugin.yaml +++ b/visu_smartvisu/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Support for smartVISU: Automatic generation of pages; widget handling' maintainer: msinn tester: psilo909 + state: qa-passed # keywords: iot xyz # documentation: https://github.com/smarthomeNG/smarthome/wiki/Visu_Unterstuetzung # url of documentation (wiki) page diff --git a/visu_websocket/plugin.yaml b/visu_websocket/plugin.yaml index d341c0c99..73f2a284e 100755 --- a/visu_websocket/plugin.yaml +++ b/visu_websocket/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Support for a websocket protocol (for smartVISU, etc.)' maintainer: msinn tester: psilo909 + state: qa-passed # keywords: iot xyz documentation: https://github.com/smarthomeNG/smarthome/wiki/Visu_Unterstuetzung # url of documentation (wiki) page diff --git a/wol/plugin.yaml b/wol/plugin.yaml index 2e48c9c56..37e8ca9cb 100755 --- a/wol/plugin.yaml +++ b/wol/plugin.yaml @@ -6,6 +6,7 @@ plugin: de: 'Wake on LAN' en: 'Wake on LAN' maintainer: cmalo + state: qa-passed # tester: # Who tests this plugin? # keywords: iot xyz # documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page @@ -16,9 +17,10 @@ plugin: multi_instance: True # plugin supports multi instance classname: WakeOnLan # class containing the plugin -parameters: +parameters: NONE # Definition of parameters to be configured in etc/plugin.yaml - + + item_attributes: # Definition of item attributes defined by this plugin wol_mac: @@ -33,4 +35,7 @@ item_attributes: mandatory: False description: de: '(optional) IP Adresse des per WOL aufzuweckenden Geräts.' - en: '(optional) IP address of device that shall be started by WOL.' \ No newline at end of file + en: '(optional) IP address of device that shall be started by WOL.' + +plugin_functions: NONE + # Definition of function interface of the plugin diff --git a/zwave/plugin.yaml b/zwave/plugin.yaml index 4400eb557..254d65026 100755 --- a/zwave/plugin.yaml +++ b/zwave/plugin.yaml @@ -6,6 +6,7 @@ plugin: de: 'Z-Wave Unterstützung' en: 'Z-Wave Support' maintainer: 'Thomas Creutz' + state: develop # tester: # Who tests this plugin? keywords: z-wave, zwave # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page From 9cb7106d3bcc49ae36eb23fdcb93fad63199ca5d Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sat, 25 Aug 2018 19:03:25 +0200 Subject: [PATCH 161/705] Nokia Health:set valid_list to correct indent --- nokia_health/plugin.yaml | 44 ++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/nokia_health/plugin.yaml b/nokia_health/plugin.yaml index e80ce239b..67428ab75 100644 --- a/nokia_health/plugin.yaml +++ b/nokia_health/plugin.yaml @@ -58,26 +58,26 @@ item_attributes: description: de: 'nh_type kann folgende Werte annehmen: Zwingend für OAuth2: access_token, token_expiry, token_type, refresh_token | Optional: weight, height (wird von Nokia Health nur beim allerersten Messwert geliefert), bmi, bmi_text, fat_ratio, fat_free_mass, fat_mass_weight, diastolic_blood_pressure, systolic_blood_pressure, temperature, body_temperature, skin_temperature, spo2, heart_pulse, hydration, bone_mass, pulse_wave_velocity.' en: 'nh_type can be out of the following values: Mandatory for OAuth2: access_token, token_expiry, token_type, refresh_token | Optional: weight, height (only supplied on the very first measurement value, set manually if you dont get it), bmi, bmi_text, fat_ratio, fat_free_mass, fat_mass_weight, diastolic_blood_pressure, systolic_blood_pressure, temperature, body_temperature, skin_temperature, spo2, heart_pulse, hydration, bone_mass, pulse_wave_velocity.' - valid_list: - - 'weight' - - 'height' - - 'bmi' - - 'bmi_text' - - 'fat_ratio' - - 'fat_free_mass' - - 'fat_mass_weight' - - 'diastolic_blood_pressure' - - 'systolic_blood_pressure' - - 'temperature' - - 'body_temperature' - - 'skin_temperature' - - 'spo2' - - 'heart_pulse' - - 'hydration' - - 'bone_mass' - - 'pulse_wave_velocity' - - 'access_token' - - 'token_expiry' - - 'token_type' - - 'refresh_token' + valid_list: + - 'weight' + - 'height' + - 'bmi' + - 'bmi_text' + - 'fat_ratio' + - 'fat_free_mass' + - 'fat_mass_weight' + - 'diastolic_blood_pressure' + - 'systolic_blood_pressure' + - 'temperature' + - 'body_temperature' + - 'skin_temperature' + - 'spo2' + - 'heart_pulse' + - 'hydration' + - 'bone_mass' + - 'pulse_wave_velocity' + - 'access_token' + - 'token_expiry' + - 'token_type' + - 'refresh_token' From 1f67599cdaa9260b0bef95e75bd070c95606672c Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sat, 25 Aug 2018 19:03:38 +0200 Subject: [PATCH 162/705] Miflora: added valid_list --- miflora/plugin.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/miflora/plugin.yaml b/miflora/plugin.yaml index 409f6e7e9..ade149122 100644 --- a/miflora/plugin.yaml +++ b/miflora/plugin.yaml @@ -43,3 +43,11 @@ item_attributes: description: de: 'Auszulesender Wert. Mögliche Werte: temperature, light, moisture, conductivity, name, firmware, firmware' en: 'Value to read. Possible: values temperature, light, moisture, conductivity, name, firmware, firmware.' + valid_list: + - 'temperature' + - 'light' + - 'moisture' + - 'conductivity' + - 'name' + - 'firmware' + - 'battery' \ No newline at end of file From 1593196f0f2ab144804c97f5c87e24a931545faa Mon Sep 17 00:00:00 2001 From: msinn Date: Sun, 26 Aug 2018 12:59:25 +0200 Subject: [PATCH 163/705] wunderground: Added item-struct wug_weather (experimental) --- avm/plugin.yaml | 1 + darksky/plugin.yaml | 7 +- enigma2/plugin.yaml | 68 ++++++++++++++++++- {telegram_1 => telegram/_pv_1_1_3}/README.md | 0 .../_pv_1_1_3}/__init__.py | 0 .../_pv_1_1_3}/logging.yaml.telegram | 0 .../_pv_1_1_3}/plugin.yaml | 0 .../_pv_1_1_3}/requirements.txt | 0 wunderground/plugin.yaml | 4 ++ 9 files changed, 77 insertions(+), 3 deletions(-) rename {telegram_1 => telegram/_pv_1_1_3}/README.md (100%) rename {telegram_1 => telegram/_pv_1_1_3}/__init__.py (100%) mode change 100755 => 100644 rename {telegram_1 => telegram/_pv_1_1_3}/logging.yaml.telegram (100%) rename {telegram_1 => telegram/_pv_1_1_3}/plugin.yaml (100%) mode change 100755 => 100644 rename {telegram_1 => telegram/_pv_1_1_3}/requirements.txt (100%) diff --git a/avm/plugin.yaml b/avm/plugin.yaml index 8735d32ed..022610a18 100755 --- a/avm/plugin.yaml +++ b/avm/plugin.yaml @@ -8,6 +8,7 @@ plugin: maintainer: psilo909 tester: Sandman60, cmalo # keywords: iot xyz + state: 'qa-passed' documentation: http://smarthomeng.de/user/plugins_doc/config/avm.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/934835-avm-plugin diff --git a/darksky/plugin.yaml b/darksky/plugin.yaml index c0f865ed1..9cfafebb0 100644 --- a/darksky/plugin.yaml +++ b/darksky/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Weather data via darksky.net.' maintainer: psilo909 tester: + state: 'qa-passed' # keywords: iot xyz documentation: 'https://www.smarthomeng.de/user/plugins/darksky/user_doc.html' support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/1244744-neues-plugin-wetterdaten-via-darksky-net-forecast-io' @@ -68,4 +69,8 @@ item_attributes: mandatory: True description: de: 'Matchstring basierend auf der Response des "Forecast Request" aus https://darksky.net/dev/docs (Example Request), bspw. "currently/temperature". Ausnahmen: Im Fall von "alerts" wird ein Item vom Typ "list" benötigt, der Wert "alerts_string" schreibt die Alerts-Liste in einen HTML String. Das Array in "flags/sources" wird in ein "str" Item gemerged.' - en: 'Matchstring according to the response of the "forecast request" described in https://darksky.net/dev/docs (Example Request), e.g. "currently/temperature". Exceptions: In case of "alerts" an item of type "list" will be filled with raw data, the value "alerts_string" creates a html string with alerts data. The array "flags/sources" will be merged to a string.' \ No newline at end of file + en: 'Matchstring according to the response of the "forecast request" described in https://darksky.net/dev/docs (Example Request), e.g. "currently/temperature". Exceptions: In case of "alerts" an item of type "list" will be filled with raw data, the value "alerts_string" creates a html string with alerts data. The array "flags/sources" will be merged to a string.' + +plugin_functions: NONE + # Definition of function interface of the plugin + diff --git a/enigma2/plugin.yaml b/enigma2/plugin.yaml index 78d67297d..ad2f6e6ee 100755 --- a/enigma2/plugin.yaml +++ b/enigma2/plugin.yaml @@ -6,7 +6,8 @@ plugin: de: 'Plugin zur Einbindung von Enigma2 kompatiblen Sat-Receivern mit openwebif' en: 'Plugin to include Enigma2 sat receivers compatible to openwebif' maintainer: psilo909 - tester: Sandman60, cmalo + tester: Sandman60, msinn + state: 'qa-passed' # keywords: iot xyz documentation: http://smarthomeng.de/user/plugins_doc/config/enigma2.html # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/943871-enigma2-plugin @@ -93,4 +94,67 @@ item_attributes: type: str description: de: 'Referenz auf Services (bspw. Sender), siehe README.' - en: 'Service reference, see README.' \ No newline at end of file + en: 'Service reference, see README.' + +plugin_functions: + # Definition of function interface of the plugin + + get_audio_tracks: + type: list + description: + de: "Diese Funktion liefert eine Liste von dicts mit den folgenden Keys: 'e2audiotrackdescription' (str), 'e2audiotrackid' (int), 'e2audiotrackpid' (int), 'e2audiotrackactive' (bool) - Beispiel: sh.vusolo2.get_audio_tracks()" + en: "This function returns a list of dicts with the following keys: 'e2audiotrackdescription' (str), 'e2audiotrackid' (int), 'e2audiotrackpid' (int), 'e2audiotrackactive' (bool) - Example: sh.vusolo2.get_audio_tracks()" + + parameters: + # This function has no parameters + + send_message: + type: foo + description: + de: "Sendet eine Message an das Enigma2 Device - Beispiel: sh.vusolo2.send_message('Testnachricht', 1, 10)" + en: "Sends a message to the device - Example: sh.vusolo2.send_message('Testmessage', 1, 10)" + + parameters: + messagetext: + type: str + description: + de: "Anzuzeignder Text" + en: "Text to be displayed" + messagetype: + type: int + default: 1 + valid_min: 0 + valid_max: 3 + description: + de: "0=Ja/Nein, 1=Info, 2=Mitteilung, 3=Achtung" + en: "0=Yes/No, 1=Info, 2=Message, 3=Attention" + timeout: + type: int + default: 10 + description: + de: "Anzeigedauer der Message in Sekunden" + en: "Number of seconds the message should stay on the device" + + set_power_state: + type: foo + description: + de: "Setzt den Power-Status auf einen bestimmten Wert - Beispiel (toggle standby): sh.vusolo2.set_power_state(0)" + en: "Sets the power state to a specific value - Example (toggle standby): sh.vusolo2.set_power_state(0)" + + parameters: + value: + type: int + valid_min: 0 + valid_max: 5 + description: + de: "0 = Toggle Standby 1 = Deepstandby 2 = Reboot 3 = Restart Enigma2 4 = Wakeup from Standby 5 = Standby" + en: "0 = Toggle Standby 1 = Deepstandby 2 = Reboot 3 = Restart Enigma2 4 = Wakeup from Standby 5 = Standby" + + get_answer: + type: foo + description: + de: "Diese Funktion prüft, ob eine Antwort zu einer gesendeten Message eingegangen ist. Dabei ist ddas timeout zu beachten, bis eine Message beantwortet wird. - Beispiel: sh.vusolo2.get_answer()" + en: "This function checks for an answer to a sent message. If you call this method, take into account the timeout until the message can be answered and e.g. set a 'while (count < 0)' - Example: sh.vusolo2.get_answer()" + + parameters: + # This function has no parameters diff --git a/telegram_1/README.md b/telegram/_pv_1_1_3/README.md similarity index 100% rename from telegram_1/README.md rename to telegram/_pv_1_1_3/README.md diff --git a/telegram_1/__init__.py b/telegram/_pv_1_1_3/__init__.py old mode 100755 new mode 100644 similarity index 100% rename from telegram_1/__init__.py rename to telegram/_pv_1_1_3/__init__.py diff --git a/telegram_1/logging.yaml.telegram b/telegram/_pv_1_1_3/logging.yaml.telegram similarity index 100% rename from telegram_1/logging.yaml.telegram rename to telegram/_pv_1_1_3/logging.yaml.telegram diff --git a/telegram_1/plugin.yaml b/telegram/_pv_1_1_3/plugin.yaml old mode 100755 new mode 100644 similarity index 100% rename from telegram_1/plugin.yaml rename to telegram/_pv_1_1_3/plugin.yaml diff --git a/telegram_1/requirements.txt b/telegram/_pv_1_1_3/requirements.txt similarity index 100% rename from telegram_1/requirements.txt rename to telegram/_pv_1_1_3/requirements.txt diff --git a/wunderground/plugin.yaml b/wunderground/plugin.yaml index 3d22d93a9..28321a5b4 100644 --- a/wunderground/plugin.yaml +++ b/wunderground/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Get weather data from wunderground.com' maintainer: msinn # tester: # Who tests this plugin? + state: 'qa-passed' keywords: weather # documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/959964-support-thread-für-das-backend-plugin @@ -157,3 +158,6 @@ structs: wug_datatype: percent log_change: q21-items +plugin_functions: NONE + # Definition of function interface of the plugin + From 81f041d7e1401dbd55eb697f0d9073e69b4f9b19 Mon Sep 17 00:00:00 2001 From: msinn Date: Sun, 26 Aug 2018 21:35:37 +0200 Subject: [PATCH 164/705] Updates to metadata of various plugins --- apcups/plugin.yaml | 6 ++++ cli/plugin.yaml | 49 +++++++++++++++++++++++++++++++-- darksky/plugin.yaml | 3 +- enigma2/plugin.yaml | 8 +++--- homematic/plugin.yaml | 24 ++-------------- kodi/plugin.yaml | 56 ++++++++++++++++++++++++++++++++++---- openweathermap/plugin.yaml | 10 +++++-- simulation/plugin.yaml | 8 +++++- sma/plugin.yaml | 6 ++++ sma_em/plugin.yaml | 8 +++++- smarttv/plugin.yaml | 6 ++++ telegram/plugin.yaml | 7 +++++ visu_smartvisu/plugin.yaml | 32 ++++++++++++---------- webservices/plugin.yaml | 8 +++++- wol/plugin.yaml | 4 ++- wunderground/plugin.yaml | 3 +- 16 files changed, 184 insertions(+), 54 deletions(-) diff --git a/apcups/plugin.yaml b/apcups/plugin.yaml index 72c32d3b7..ee5a2d21e 100755 --- a/apcups/plugin.yaml +++ b/apcups/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: '' maintainer: cmalo tester: Sandman60 + state: ready # keywords: iot xyz # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page # support: https://knx-user-forum.de/forum/supportforen/smarthome-py @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance + restartable: unknown classname: APCUPS # class containing the plugin parameters: @@ -48,3 +50,7 @@ item_attributes: description: de: 'Für eine Liste gültiger Werte, "apcaccess" auf der Kommandozeile aufrufen. Dieser Befehl gibt einen Textblock zurück, der eine Liste von ``statusname : value`` Einträgen enthält' en: 'For a list of values for this attribute call "apcaccess" on the command line. This command will give back a text block containing a list of ``statusname : value`` entries' + +plugin_functions: NONE + # Definition of function interface of the plugin + diff --git a/cli/plugin.yaml b/cli/plugin.yaml index 43d7bbc69..5495119a0 100755 --- a/cli/plugin.yaml +++ b/cli/plugin.yaml @@ -8,6 +8,7 @@ plugin: en: 'Commandline interface for SmartHomeNG - Works with SmartHomeNG v1.4 and up' maintainer: msinn tester: onkelandy, Sandman60, ohinckel + state: qa-passed # keywords: iot xyz # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.4 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance + restartable: unknown classname: CLI # class containing the plugin parameters: @@ -38,6 +40,7 @@ parameters: default: 2323 description: de: 'Netzwerk Port der für die Verbindung genutzt wird' + en: 'used network port' hashed_password: @@ -47,6 +50,48 @@ parameters: en: "password that needs to be entered on login. SHA-512 hashed. Hashes can be created via the backend plugin. If you don't use a password, a warning will be logged. If you don't want that log entry, this parameter must be set to 'none'." -item_attributes: +item_attributes: NONE # Definition of item attributes defined by this plugin - + +plugin_functions: + # Definition of function interface of the plugin + + add_command: + type: void + description: + de: "sh.cli.commands.add_command(command, function, group, usage)" + en: "sh.cli.commands.add_command(command, function, group, usage)" + parameters: + command: + type: str + description: + de: "Name des Kommandos" + en: "Name of the command" + function: + type: function + description: + de: "Funktion die aufgerufen werden soll, wenn das Kommando eingegeben wird" + en: "function to be called when the command is entered" + group: + type: str + valid_list: ['item', 'log', 'logic', 'scheduler'] + description: + de: "Kommando Gruppe (item, log, logic, scheduler)" + en: "Command group (item, log, logic, scheduler)" + usage: + type: str + description: + de: "Beschreibung der Kommando-Nutzung" + en: "description how to use that command" + + remove_command: + type: bool + description: + de: "sh.cli.commands.remove_command(command)" + en: "sh.cli.commands.remove_command(command)" + parameters: + command: + type: str + description: + de: "Name des Kommandos" + en: "Name of the command" diff --git a/darksky/plugin.yaml b/darksky/plugin.yaml index 9cfafebb0..dcdba2d2a 100644 --- a/darksky/plugin.yaml +++ b/darksky/plugin.yaml @@ -6,7 +6,7 @@ plugin: de: 'Wetterdaten über darksky.net.' en: 'Weather data via darksky.net.' maintainer: psilo909 - tester: + tester: psilo909 state: 'qa-passed' # keywords: iot xyz documentation: 'https://www.smarthomeng.de/user/plugins/darksky/user_doc.html' @@ -16,6 +16,7 @@ plugin: sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance + restartable: unknown classname: DarkSky # class containing the plugin parameters: diff --git a/enigma2/plugin.yaml b/enigma2/plugin.yaml index ad2f6e6ee..0a8ae6a4e 100755 --- a/enigma2/plugin.yaml +++ b/enigma2/plugin.yaml @@ -16,6 +16,7 @@ plugin: sh_minversion: 1.3c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance + restartable: unknown classname: Enigma2 # class containing the plugin parameters: @@ -109,7 +110,7 @@ plugin_functions: # This function has no parameters send_message: - type: foo + type: void description: de: "Sendet eine Message an das Enigma2 Device - Beispiel: sh.vusolo2.send_message('Testnachricht', 1, 10)" en: "Sends a message to the device - Example: sh.vusolo2.send_message('Testmessage', 1, 10)" @@ -123,8 +124,7 @@ plugin_functions: messagetype: type: int default: 1 - valid_min: 0 - valid_max: 3 + valid_list: [0, 1, 2, 3] description: de: "0=Ja/Nein, 1=Info, 2=Mitteilung, 3=Achtung" en: "0=Yes/No, 1=Info, 2=Message, 3=Attention" @@ -136,7 +136,7 @@ plugin_functions: en: "Number of seconds the message should stay on the device" set_power_state: - type: foo + type: void description: de: "Setzt den Power-Status auf einen bestimmten Wert - Beispiel (toggle standby): sh.vusolo2.set_power_state(0)" en: "Sets the power state to a specific value - Example (toggle standby): sh.vusolo2.set_power_state(0)" diff --git a/homematic/plugin.yaml b/homematic/plugin.yaml index 73d067970..9be0b1402 100755 --- a/homematic/plugin.yaml +++ b/homematic/plugin.yaml @@ -6,6 +6,7 @@ plugin: de: 'Ansteuerung von HomeMatic Komponenten über eine HomeMatic CCU2 Zentrale. Es werden HomeMatic und HomeMaticIP Geräte unterstützt.' en: 'Control HomeMatic devices through a HomeMatic CCU2 (used as gateway). HomeMatic and HomeMaticIP devices are supported.' maintainer: msinn # Who maintains this plugin? + tester: msinn state: qa-passed # tester: efgh # Who tests this plugin? # keywords: kwd1 kwd2 # keywords, where applicable @@ -17,6 +18,7 @@ plugin: sh_minversion: 1.4d # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True + restartable: unknown classname: Homematic # class containing the plugin parameters: @@ -89,26 +91,6 @@ item_attributes: en: 'Optional: Channel of the devicemon which the function shall be used. Has only to be specified, if the requested function is implemented more than once on the device.' -plugin_functions: +plugin_functions: NONE # Definition of function interface of the plugin - : - type: str - description: - de: '' - en: '' - - parameters: - : - type: int - valid_min: 0 - description: - de: '' - en: '' - - : - type: str - valid_list: ['yes','no','dont know'] - description: - de: '' - en: '' diff --git a/kodi/plugin.yaml b/kodi/plugin.yaml index 00c8f8634..5e5411b35 100755 --- a/kodi/plugin.yaml +++ b/kodi/plugin.yaml @@ -3,9 +3,9 @@ plugin: # Global plugin attributes type: interface # plugin type (gateway, interface, protocol, system, web) description: - de: 'Anbindung von XBMC v12 (Frodo) oder neuer' - en: '' - maintainer: ggf. cmalo (mknx) + de: 'Anbindung von Kodi (ehemals XBMC) v12 (Frodo) oder neuer' + en: 'Connecting Kodi (formerly XBMC) v12 (Frode) or newer' + maintainer: ggf. msinn tester: onkelandy state: develop keywords: mediacenter @@ -23,11 +23,57 @@ parameters: # Definition of parameters to be configured in etc/plugin.yaml host: type: ipv4 + mandatory: True port: type: int + valid_min: 0 default: 9090 -#item_attributes: + +item_attributes: # Definition of item attributes defined by this plugin - + + kody_item: + type: str + valid_list: ['on_off', 'volume', 'mute', 'title', 'media', 'state', 'favorites', 'input'] + description: + de: '' + en: '' + +plugin_functions: + # Definition of function interface of the plugin + + notify: + type: str + description: + de: "Diese Funktion ermöglicht es, Mitteilungen an Kodi zu schicken. Beispiel: sh.living.kodi.notify('Door', 'Ding Dong')" + en: "This function provies the functionallity to send notification messages to Kodi. Example: sh.living.kodi.notify('Door', 'Ding Dong')" + + parameters: + title: + type: str + description: + de: 'Überschrift der Mitteilung' + en: '' + + message: + type: str + description: + de: 'Text der Mitteilung' + en: '' + + image: + type: str + default: None* + description: + de: "Url des anzuzeigenden Bildes (z.B.: 'http://smarthome.local/img/phone.png')" + en: '' + + display_time: + type: int + default: 10000 + description: + de: 'Dauer der Anzeige in msec' + en: '' + diff --git a/openweathermap/plugin.yaml b/openweathermap/plugin.yaml index 1d1dc48f7..fc4471757 100644 --- a/openweathermap/plugin.yaml +++ b/openweathermap/plugin.yaml @@ -6,7 +6,8 @@ plugin: de: 'Wetterdaten über darksky.net.' en: 'Weather data via darksky.net.' maintainer: psilo909 - tester: + tester: psilo909 + state: qa-passed # keywords: iot xyz documentation: '' support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/1246998-support-thread-zum-openweathermap-plugin' @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance + restartable: unknown classname: OpenWeatherMap # class containing the plugin parameters: @@ -68,4 +70,8 @@ item_attributes: mandatory: True description: de: 'Matchstring für die OpenWeatherMap Daten, siehe Beispiele in der README.' - en: 'Matchstring for the OpenWeatherMap data, see examples in README.' \ No newline at end of file + en: 'Matchstring for the OpenWeatherMap data, see examples in README.' + +plugin_functions: NONE + # Definition of function interface of the plugin + diff --git a/simulation/plugin.yaml b/simulation/plugin.yaml index 4934b889b..147787cd4 100755 --- a/simulation/plugin.yaml +++ b/simulation/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Recording And Replay of Actions on Items.' maintainer: MichaelBu (?) tester: psilo909, Sandman60, cmalo + state: ready # keywords: iot xyz documentation: https://www.smarthomeng.de/developer/plugins/simulation/README.html # url of documentation (wiki) page support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/841097-anwesenheitssimulation-0-1' @@ -14,6 +15,7 @@ plugin: sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance + restartable: unknown classname: Simulation # class containing the plugin parameters: @@ -45,4 +47,8 @@ item_attributes: werden.' en: 'May be either the value "track", "state", "control", "message" or "tank". Besides "track" the values may only be assigned one time over all items. They are used for plugin internal information storage. - "track" may be assigned to multiple items and is used to record the value changes of that item.' \ No newline at end of file + "track" may be assigned to multiple items and is used to record the value changes of that item.' + +plugin_functions: NONE + # Definition of function interface of the plugin + diff --git a/sma/plugin.yaml b/sma/plugin.yaml index 50493eda5..c059a3929 100755 --- a/sma/plugin.yaml +++ b/sma/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Support for the SMA Inverter SunnyBoy 5000TL-21, Sunny Tripower 8000TL-10, Sunny Tripower 12000TL-10' maintainer: '? (Robert Budde)' tester: psilo909 + state: ready # keywords: iot xyz documentation: https://smarthomeng.de/user/plugins_doc/config/sma.html # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/27997-beitrag-plugin-zum-lesen-von-sma-wechselrichtern-sunnyboy-5000tl-21-getestet @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance + restartable: unknown classname: SMA # class containing the plugin parameters: @@ -57,3 +59,7 @@ item_attributes: description: de: 'Auszulesender Wert, möglich sind: PLUGIN_ACTIVE, AC_P_TOTAL, E_DAY, E_TOTAL, INV_SERIAL, INV_ADDRESS, LAST_UPDATE, DC_STRING1_P, DC_STRING2_P, DC_STRING1_U, DC_STRING2_U, DC_STRING1_I, DC_STRING2_I, OPERATING_TIME, FEEDING_TIME, GRID_FREQUENCY, STATUS, GRID_RELAY, SW_VERSION.' en: 'Value to read. Possible: PLUGIN_ACTIVE, AC_P_TOTAL, E_DAY, E_TOTAL, INV_SERIAL, INV_ADDRESS, LAST_UPDATE, DC_STRING1_P, DC_STRING2_P, DC_STRING1_U, DC_STRING2_U, DC_STRING1_I, DC_STRING2_I, OPERATING_TIME, FEEDING_TIME, GRID_FREQUENCY, STATUS, GRID_RELAY, SW_VERSION.' + +plugin_functions: NONE + # Definition of function interface of the plugin + diff --git a/sma_em/plugin.yaml b/sma_em/plugin.yaml index c7a4f5402..a472deb8e 100755 --- a/sma_em/plugin.yaml +++ b/sma_em/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Access to data from SMA Energy Meter network multicast' maintainer: psilo909 tester: psilo909 + state: qa-passed keywords: smart meter, power consumption documentation: http://smarthomeng.de/user/plugins_doc/config/sma_em.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1030610-sma_em-plugin @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance + restartable: unknown classname: SMA_EM # class containing the plugin parameters: @@ -39,4 +41,8 @@ item_attributes: mandatory: True description: de: 'Datentyp. Folgende Werte sind möglich: pregard, pregardcounter, psurplus, psurpluscounter, sregard, sregardcounter, ssurplus, ssurpluscounter, qregard, qregardcounter, qsurplus, qsurpluscounter, cosphi, p1regard, p1regardcounter, p1surplus, p1surpluscounter, s1regard, s1regardcounter, s1surplus, s1surpluscounter, q1regard, q1regardcounter, q1surplus, q1surpluscounter, v1, thd1, cosphi1, p2regard, p2regardcounter, p2surplus, p2surpluscounter, s2regard, s2regardcounter, s2surplus, s2surpluscounter, q2regard, q2regardcounter, q2surplus, q2surpluscounter, v2, thd2, cosphi2, p3regard, p3regardcounter, p3surplus, p3surpluscounter, s3regard, s3regardcounter, s3surplus, s3surpluscounter, q3regard, q3regardcounter, q3surplus, q3surpluscounter, v3, thd3, cosphi3.' - en: 'Datentyp. The following values are possible: pregard, pregardcounter, psurplus, psurpluscounter, sregard, sregardcounter, ssurplus, ssurpluscounter, qregard, qregardcounter, qsurplus, qsurpluscounter, cosphi, p1regard, p1regardcounter, p1surplus, p1surpluscounter, s1regard, s1regardcounter, s1surplus, s1surpluscounter, q1regard, q1regardcounter, q1surplus, q1surpluscounter, v1, thd1, cosphi1, p2regard, p2regardcounter, p2surplus, p2surpluscounter, s2regard, s2regardcounter, s2surplus, s2surpluscounter, q2regard, q2regardcounter, q2surplus, q2surpluscounter, v2, thd2, cosphi2, p3regard, p3regardcounter, p3surplus, p3surpluscounter, s3regard, s3regardcounter, s3surplus, s3surpluscounter, q3regard, q3regardcounter, q3surplus, q3surpluscounter, v3, thd3, cosphi3.' \ No newline at end of file + en: 'Datentyp. The following values are possible: pregard, pregardcounter, psurplus, psurpluscounter, sregard, sregardcounter, ssurplus, ssurpluscounter, qregard, qregardcounter, qsurplus, qsurpluscounter, cosphi, p1regard, p1regardcounter, p1surplus, p1surpluscounter, s1regard, s1regardcounter, s1surplus, s1surpluscounter, q1regard, q1regardcounter, q1surplus, q1surpluscounter, v1, thd1, cosphi1, p2regard, p2regardcounter, p2surplus, p2surpluscounter, s2regard, s2regardcounter, s2surplus, s2surpluscounter, q2regard, q2regardcounter, q2surplus, q2surpluscounter, v2, thd2, cosphi2, p3regard, p3regardcounter, p3surplus, p3surpluscounter, s3regard, s3regardcounter, s3surplus, s3surpluscounter, q3regard, q3regardcounter, q3surplus, q3surpluscounter, v3, thd3, cosphi3.' + +plugin_functions: NONE +# Definition of function interface of the plugin + diff --git a/smarttv/plugin.yaml b/smarttv/plugin.yaml index 7778d7d09..4272aabdd 100755 --- a/smarttv/plugin.yaml +++ b/smarttv/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: '' maintainer: '? (2ndsky)' tester: psilo909 + state: ready # keywords: iot xyz # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page # support: https://knx-user-forum.de/forum/supportforen/smarthome-py @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance + restartable: unknown classname: SmartTV # class containing the plugin parameters: @@ -62,3 +64,7 @@ item_attributes: en: 'There are two possibilities to use this attribute. * Define it on a string item and set it to `true`: With this configuration, every string you set to this item will be send to the SmartTV device. * Define it on a boolean item and set it to a key value: With this configuration, the specified key value is sent whenever you set the item to `true` (if the item is only for sending a specific command to the tv then you should consider using the `enforce_updates` attribute, too). It is even possible to define several keys separeted with a comma.' + +plugin_functions: NONE + # Definition of function interface of the plugin + diff --git a/telegram/plugin.yaml b/telegram/plugin.yaml index 73b88e961..df0f36f36 100644 --- a/telegram/plugin.yaml +++ b/telegram/plugin.yaml @@ -6,6 +6,8 @@ plugin: de: 'Anbindung des Telegram Service (verwendet python-telegram-bot Package statt telepot Package)' en: '' maintainer: gamade, ivan73, bmxp +# tester: + state: ready # tester: # Who tests this plugin? # keywords: iot xyz # documentation: https://github.com/smarthomeNG/smarthome/wiki/... # url of documentation (wiki) page @@ -15,6 +17,7 @@ plugin: sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance + restartable: unknown classname: Telegram # class containing the plugin parameters: @@ -57,3 +60,7 @@ item_attributes: description: de: 'Itemwert gegen einen regulän Ausdruck prüfen vor versenden einer Mitteilung' en: 'check a value against a condition before sending a message' + +plugin_functions: NONE + # Definition of function interface of the plugin + diff --git a/visu_smartvisu/plugin.yaml b/visu_smartvisu/plugin.yaml index 740a8cb27..192cd8e7e 100755 --- a/visu_smartvisu/plugin.yaml +++ b/visu_smartvisu/plugin.yaml @@ -15,6 +15,7 @@ plugin: sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance + restartable: True classname: SmartVisu # class containing the plugin parameters: @@ -63,7 +64,7 @@ item_attributes: # type: bool # description: # de: '' -# en: '' +# en: 'Simply set the visu_acl attribute to something to allow read/write access to the item' sv_page: type: str @@ -76,7 +77,7 @@ item_attributes: - room_lite description: de: '' - en: '' + en: 'Set sv_page to to one of the following values generate a page for this item. Every widget beneath this item will be included in the page' sv_overview: type: str @@ -87,54 +88,57 @@ item_attributes: sv_item_type: type: str description: - de: '' + de: 'sv_item_type erlaubt es, items auf anderen Seiten als der Raum-Seite anzuzeigen' en: 'sv_item_type allows items to be displayed on an overview page.' sv_img: type: str description: - de: '' - en: '' + de: 'Bild, das in der Navigation der smartVISU angezeigt wird' + en: 'By setting sv_img you could assign an icon or picture for a page or widget' sv_widget: type: str description: - de: '' - en: '' + de: 'Definition des Widgets, welches für das Item verwendet wird' + en: 'allows the specification of a widget. You could define multiple widgets. The widget(s) is/are shown by being encapsulated in a block of type 2 (Collapsable Block) - Relative item references are supported' sv_widget2: type: str description: - de: '' - en: '' + de: 'Definition des zweiten Widgets, welches für das Item verwendet wird' + en: 'Definition of the secondary widget which is used for the item' sv_nav_aside: type: str description: de: '' - en: '' + en: 'allows the specification of a widget, that is being displayed at the right side of the navigation bar for a room. (upper line) - Relative item references are supported' sv_nav_aside2: type: str description: de: '' - en: '' + en: 'allows the specification of a widget, that is being displayed at the right side of the navigation bar for a room. (lower line) - Relative item references are supported.' sv_heading_left: type: str description: de: '' - en: '' + en: 'allows the specification of a widget, hat is being displayed at the top of a room-page. This widget is shown without being encapsulated in a block. The widget is aligned to to the left' sv_heading_center: type: str description: de: '' - en: '' + en: 'allows the specification of a widget, hat is being displayed at the top of a room-page. This widget is shown without being encapsulated in a block. The widget is aligned to to the center' sv_heading_right: type: str description: de: '' - en: '' + en: 'allows the specification of a widget, hat is being displayed at the top of a room-page. This widget is shown without being encapsulated in a block. The widget is aligned to to the right' +plugin_functions: NONE + # Definition of function interface of the plugin + diff --git a/webservices/plugin.yaml b/webservices/plugin.yaml index fd9119fe9..8dc22ae27 100755 --- a/webservices/plugin.yaml +++ b/webservices/plugin.yaml @@ -6,7 +6,8 @@ plugin: de: 'Implementierung eines Webservice interfaces' en: 'Implementation of a webservice interface' maintainer: psilo909 -# tester: # Who tests this plugin? + tester: psilo909 # Who tests this plugin? + state: qa-passed keywords: REST, API, Webservice documentation: https://www.smarthomeng.de/?category_name=plugins&s=webservices support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1163886-support-thread-f%C3%BCr-das-webservices-plugin @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.5 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance + restartable: unknown classname: WebServices # class containing the plugin parameters: @@ -39,3 +41,7 @@ item_attributes: description: de: '(optional) webservices_data dient dazu, die Rückgabedaten von Items zu limitieren. Wird als Wert "val" eingegeben, so wird nur der Pfadname und der Wert zurückgegeben, sonst zusätzlich alle Metainformationen.' en: '(optional) webservices_data is used, to limit the returned values for an item. If the attribute value "val" is set, only the path name and the item value is returned. Otherwise, also all meta information is returned.' + +plugin_functions: NONE + # Definition of function interface of the plugin + diff --git a/wol/plugin.yaml b/wol/plugin.yaml index 37e8ca9cb..bb2c6b2b8 100755 --- a/wol/plugin.yaml +++ b/wol/plugin.yaml @@ -6,6 +6,7 @@ plugin: de: 'Wake on LAN' en: 'Wake on LAN' maintainer: cmalo + tester: ohinckel state: qa-passed # tester: # Who tests this plugin? # keywords: iot xyz @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.1 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance + restartable: unknown classname: WakeOnLan # class containing the plugin parameters: NONE @@ -24,7 +26,7 @@ parameters: NONE item_attributes: # Definition of item attributes defined by this plugin wol_mac: - type: str + type: mac mandatory: True description: de: 'MAC Adresse des per WOL aufzuweckenden Geräts.' diff --git a/wunderground/plugin.yaml b/wunderground/plugin.yaml index 28321a5b4..49fb71c58 100644 --- a/wunderground/plugin.yaml +++ b/wunderground/plugin.yaml @@ -6,7 +6,7 @@ plugin: de: 'Abfrage der Daten des Wetterdienstes Wunderground.com' en: 'Get weather data from wunderground.com' maintainer: msinn -# tester: # Who tests this plugin? + tester: msinn # Who tests this plugin? state: 'qa-passed' keywords: weather # documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page @@ -16,6 +16,7 @@ plugin: sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance + restartable: unknown classname: Wunderground # class containing the plugin From ab7a494ecbdd100a34faf83b99a4dbea78026ab9 Mon Sep 17 00:00:00 2001 From: msinn Date: Sun, 26 Aug 2018 21:59:45 +0200 Subject: [PATCH 165/705] Metadata update --- enigma2/plugin.yaml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/enigma2/plugin.yaml b/enigma2/plugin.yaml index 0a8ae6a4e..ef3556d34 100755 --- a/enigma2/plugin.yaml +++ b/enigma2/plugin.yaml @@ -125,6 +125,9 @@ plugin_functions: type: int default: 1 valid_list: [0, 1, 2, 3] + valid_list_description: + de: ['Ja/Nein', 'Info', 'Mitteilung', 'Achtung'] + en: ['Yes/No', 'Info', 'Message', 'Attention'] description: de: "0=Ja/Nein, 1=Info, 2=Mitteilung, 3=Achtung" en: "0=Yes/No, 1=Info, 2=Message, 3=Attention" @@ -144,8 +147,10 @@ plugin_functions: parameters: value: type: int - valid_min: 0 - valid_max: 5 + valid_list: [0, 1, 2, 3, 4, 5] + valid_list_description: + de: ['Toggle Standby', 'Deepstandby', 'Reboot', 'Restart Enigma2', 'Wakeup from Standby', 'Standby'] + en: ['Toggle Standby', 'Deepstandby', 'Reboot', 'Restart Enigma2', 'Wakeup from Standby', 'Standby'] description: de: "0 = Toggle Standby 1 = Deepstandby 2 = Reboot 3 = Restart Enigma2 4 = Wakeup from Standby 5 = Standby" en: "0 = Toggle Standby 1 = Deepstandby 2 = Reboot 3 = Restart Enigma2 4 = Wakeup from Standby 5 = Standby" From cb177a735636109429aab816c381501b26c286ca Mon Sep 17 00:00:00 2001 From: msinn Date: Sun, 26 Aug 2018 22:54:24 +0200 Subject: [PATCH 166/705] Metadata updates --- visu_websocket/plugin.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/visu_websocket/plugin.yaml b/visu_websocket/plugin.yaml index 73f2a284e..83a1922d4 100755 --- a/visu_websocket/plugin.yaml +++ b/visu_websocket/plugin.yaml @@ -51,6 +51,9 @@ parameters: - true - yes - no + valid_list_description: + de: ['Lesen/Schreiben', 'Nur Lesen', 'Kein Zugriff', 'Lesen/Schreiben', 'Lesen/Schreiben', 'Kein Zugriff'] + en: ['Read/Write', 'Read Only', 'Deny access', 'Read/Write', 'Read/Write', 'Deny access'] description: de: 'Erlaube den Zugriff über Websocket Protokoll (rw=Lesen/Schreiben, ro=Nur Lesen, deny=Kein Zugriff) - Voreinstellung für alle Items' en: 'Allow access through wbsocket protocol (rw=Read/Write, ro=Read Only, deny=Deny access) - Default for all items' From 0df0df8d0849304177223eae66a4ffe3c073fafc Mon Sep 17 00:00:00 2001 From: msinn Date: Sun, 26 Aug 2018 23:51:33 +0200 Subject: [PATCH 167/705] Metadata update --- visu_websocket/plugin.yaml | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/visu_websocket/plugin.yaml b/visu_websocket/plugin.yaml index 83a1922d4..aa20a1677 100755 --- a/visu_websocket/plugin.yaml +++ b/visu_websocket/plugin.yaml @@ -55,15 +55,16 @@ parameters: de: ['Lesen/Schreiben', 'Nur Lesen', 'Kein Zugriff', 'Lesen/Schreiben', 'Lesen/Schreiben', 'Kein Zugriff'] en: ['Read/Write', 'Read Only', 'Deny access', 'Read/Write', 'Read/Write', 'Deny access'] description: - de: 'Erlaube den Zugriff über Websocket Protokoll (rw=Lesen/Schreiben, ro=Nur Lesen, deny=Kein Zugriff) - Voreinstellung für alle Items' - en: 'Allow access through wbsocket protocol (rw=Read/Write, ro=Read Only, deny=Deny access) - Default for all items' + de: 'Steuert den Zugriff über Websocket Protokoll - Voreinstellung für alle Items' + en: 'Control access through wbsocket protocol - Default for all items' wsproto: type: int default: 4 - valid_list: - - 3 - - 4 + valid_list: [3, 4] + valid_list_description: + de: ['Version 3', 'Version 4'] + en: ['version 3', 'version 4'] description: de: 'Verwendete Version des Websocket Protokolls' en: 'Used version of the websocket protocol' @@ -87,7 +88,11 @@ item_attributes: - true - yes - no + valid_list_description: + de: ['Lesen/Schreiben', 'Nur Lesen', 'Kein Zugriff', 'Lesen/Schreiben', 'Lesen/Schreiben', 'Kein Zugriff'] + en: ['Read/Write', 'Read Only', 'Deny access', 'Read/Write', 'Read/Write', 'Deny access'] description: - de: 'Erlaube den Zugriff auf das Item über Websocket Protokoll (rw=Lesen/Schreiben, ro=Nur Lesen, deny=Kein Zugriff)' - en: 'Allow access to the item through websocket protocol (rw=Read/Write, ro=Read Only, deny=Deny access)' + de: 'Steuert den Zugriff auf das Item über Websocket Protokoll' + en: 'Control access to this item through wbsocket protocol' + From 9869a7533a1ab08880ce7b7b8a7e0aa5b4e1f672 Mon Sep 17 00:00:00 2001 From: msinn Date: Mon, 27 Aug 2018 00:50:08 +0200 Subject: [PATCH 168/705] Metadata Updates --- enigma2/plugin.yaml | 8 ++++---- visu_websocket/plugin.yaml | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/enigma2/plugin.yaml b/enigma2/plugin.yaml index ef3556d34..52eb8bdd2 100755 --- a/enigma2/plugin.yaml +++ b/enigma2/plugin.yaml @@ -129,8 +129,8 @@ plugin_functions: de: ['Ja/Nein', 'Info', 'Mitteilung', 'Achtung'] en: ['Yes/No', 'Info', 'Message', 'Attention'] description: - de: "0=Ja/Nein, 1=Info, 2=Mitteilung, 3=Achtung" - en: "0=Yes/No, 1=Info, 2=Message, 3=Attention" + de: "messagetype bestimmt die Art wie die Mitteilung angezeigt werden soll" + en: "messagetype determines the way the message shall be shown" timeout: type: int default: 10 @@ -152,8 +152,8 @@ plugin_functions: de: ['Toggle Standby', 'Deepstandby', 'Reboot', 'Restart Enigma2', 'Wakeup from Standby', 'Standby'] en: ['Toggle Standby', 'Deepstandby', 'Reboot', 'Restart Enigma2', 'Wakeup from Standby', 'Standby'] description: - de: "0 = Toggle Standby 1 = Deepstandby 2 = Reboot 3 = Restart Enigma2 4 = Wakeup from Standby 5 = Standby" - en: "0 = Toggle Standby 1 = Deepstandby 2 = Reboot 3 = Restart Enigma2 4 = Wakeup from Standby 5 = Standby" + de: "Status in den die Enigma2 Box versetzt werden soll" + en: "State into which the Enigma2 box should be changed" get_answer: type: foo diff --git a/visu_websocket/plugin.yaml b/visu_websocket/plugin.yaml index aa20a1677..a4511e552 100755 --- a/visu_websocket/plugin.yaml +++ b/visu_websocket/plugin.yaml @@ -95,4 +95,39 @@ item_attributes: de: 'Steuert den Zugriff auf das Item über Websocket Protokoll' en: 'Control access to this item through wbsocket protocol' +logic_parameter: + # Definition of item attributes defined by this plugin + visu_acl: + type: bool + default: False + valid_list: + - True + - False + valid_list_description: + de: ['Logik kann durch smartVISU getriggert werden', 'Logik kann durch smartVISU getriggert werden'] + en: ['Logic can be triggered by smartVISU', 'Logic cannot be triggered by smartVISU'] + description: + de: 'Dieses Attribut kann für jede Logik in ../etc/logic.yaml angegeben werden.' + en: 'This attribute can be added to every logic in ../etc/logic.yaml.' + +plugin_functions: + # Definition of function interface of the plugin + + url: + type: void + description: + de: "Diese Funktion weist smartVISU Clients an, auf die angegebene Url (Visu Seite) zu wechseln. Die Funktion funktioniert mit smartVISU v2.9 und später. Für smartVISU v2.8 muss ein modifiziertes Treiber io_smarthome.js verwendet werden - Beispiel: sh.visu.url('index.php?page=apartement.living', '10.0.0.23')" + en: "This function instructs the smartVISU clients to change to the specified url (visu page). This function works with smartVISU v2.9 and up, for smartVISU v2.8 a modified driver io_smarthome.js is needed - Example: sh.visu.url('index.php?page=apartement.living', '10.0.0.23')" + parameters: + url: + type: str + description: + de: "Die URL zu der smartVISU wechseln soll" + en: "url to which smartVISU should change" + clientip: + type: str + default: '' + description: + de: "Falls angegeben, werden nur Clients (Browser) die auf dem Host mit der angegebenen IP Adresse laufen angewiesen die Seite zu wechseln. " + en: "If specified, only clients (browsers) running on the host with the specified ip address are instructed to change the page." From ba12f8cc6e620fe0beab1693350768b3487a28a3 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sun, 26 Aug 2018 19:54:11 +0200 Subject: [PATCH 169/705] Database: remove debug logging from _expression() method --- database/__init__.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/database/__init__.py b/database/__init__.py index 8732583c0..1126197a3 100644 --- a/database/__init__.py +++ b/database/__init__.py @@ -410,10 +410,6 @@ def _expression(self, func): if func is 'count' or func.startswith('count'): parts = re.match('(count)((<>|!=|<|=|>)(\d+))?', func) func = 'count' - self.logger.debug(parts) - self.logger.debug(parts.groups()) - self.logger.debug(parts.group(3)) - self.logger.debug(parts.group(4)) if parts and parts.group(3) is not None: expression['params']['op'] = parts.group(3) if parts and parts.group(4) is not None: From 3a4d0c7a8c59c0dc6c5161cc98a5023238f0c883 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Mon, 27 Aug 2018 19:39:59 +0200 Subject: [PATCH 170/705] Database: complete description for prefix parameter (de) --- database/plugin.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/plugin.yaml b/database/plugin.yaml index eecb529a1..a40672b58 100755 --- a/database/plugin.yaml +++ b/database/plugin.yaml @@ -32,7 +32,7 @@ parameters: prefix: type: str description: - de: '' + de: 'Enthält ein Prefix welches vor die Datenbanktabellen des Plugins geschrieben wird' en: "if you want to log into an existing database with other tables you can specify a prefix for the plugins' tables" cycle: type: int From 7e58e0cff98f4da455db39b50b0dff659238d30c Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Mon, 27 Aug 2018 20:15:12 +0200 Subject: [PATCH 171/705] Database: Add new `precision` parameter This can be used to define the amount of digits after comma will be returned for data selected from database. The default is 2. Settings this to 0 will return values without digits, settings this to -1 will return the float value directly Details see https://github.com/smarthomeNG/smarthome/issues/261 --- database/__init__.py | 17 ++++++++++++----- database/plugin.yaml | 6 ++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/database/__init__.py b/database/__init__.py index 1126197a3..03b61823b 100644 --- a/database/__init__.py +++ b/database/__init__.py @@ -74,13 +74,14 @@ class Database(SmartPlugin): '6' : ["CREATE INDEX {item}_name ON {item} (name);", "DROP INDEX {item}_name;"] } - def __init__(self, smarthome, driver, connect, prefix="", cycle=60): + def __init__(self, smarthome, driver, connect, prefix="", cycle=60, precision=2): self._sh = smarthome self.shtime = Shtime.get_instance() self.items = Items.get_instance() self.logger = logging.getLogger(__name__) self._dump_cycle = int(cycle) + self._precision = int(precision) self._name = self.get_instance_name() self._replace = {table: table if prefix == "" else prefix + "_" + table for table in ["log", "item"]} self._replace['item_columns'] = ", ".join(COL_ITEM) @@ -99,6 +100,7 @@ def __init__(self, smarthome, driver, connect, prefix="", cycle=60): self._init_complete = False def parse_item(self, item): + self.logger.debug(item.conf) if self.has_iattr(item.conf, 'database'): self._buffer_insert(item, []) item.series = functools.partial(self._series, item=item.id()) @@ -431,12 +433,12 @@ def _series(self, func, start, end='now', count=100, ratio=1, update=False, step sid = item + '|' + func + '|' + str(start) + '|' + str(end) + '|' + str(count) func, expression = self._expression(func) queries = { - 'avg' : 'MIN(time), ROUND(AVG(val_num * duration) / AVG(duration), 2)', + 'avg' : 'MIN(time), ' + self._precision_query('AVG(val_num * duration) / AVG(duration)'), 'avg.order' : 'ORDER BY time ASC', 'count' : 'MIN(time), SUM(CASE WHEN val_num{op}{value} THEN 1 ELSE 0 END)'.format(**expression['params']), 'min' : 'MIN(time), MIN(val_num)', 'max' : 'MIN(time), MAX(val_num)', - 'on' : 'MIN(time), ROUND(SUM(val_bool * duration) / SUM(duration), 2)', + 'on' : 'MIN(time), ' + self._precision_query('SUM(val_bool * duration) / SUM(duration)'), 'on.order' : 'ORDER BY time ASC', 'sum' : 'MIN(time), SUM(val_num)', 'raw' : 'time, val_num', @@ -479,11 +481,11 @@ def _series(self, func, start, end='now', count=100, ratio=1, update=False, step def _single(self, func, start, end='now', item=None): func, expression = self._expression(func) queries = { - 'avg' : 'ROUND(AVG(val_num * duration) / AVG(duration), 2)', + 'avg' : self._precision_query('AVG(val_num * duration) / AVG(duration)'), 'count' : 'SUM(CASE WHEN val_num{op}{value} THEN 1 ELSE 0 END)'.format(**expression['params']), 'min' : 'MIN(val_num)', 'max' : 'MAX(val_num)', - 'on' : 'ROUND(SUM(val_bool * duration) / SUM(duration), 2)', + 'on' : self._precision_query('SUM(val_bool * duration) / SUM(duration)'), 'sum' : 'SUM(val_num)', 'raw' : 'val_num', 'raw.order' : 'ORDER BY time DESC', @@ -498,6 +500,11 @@ def _single(self, func, start, end='now', item=None): return return logs['tuples'][0][0] + def _precision_query(self, query): + if self._precision >= 0: + return 'ROUND({}, {})'.format(query, self._precision) + return query + def _fetch_log(self, item, columns, start, end, step=None, count=100, group='', order=''): _item = self.items.return_item(item) diff --git a/database/plugin.yaml b/database/plugin.yaml index a40672b58..1fbae6a83 100755 --- a/database/plugin.yaml +++ b/database/plugin.yaml @@ -40,6 +40,12 @@ parameters: description: de: 'Dump Cycle bestimmt wie oft die Daten auf Platte geschrieben werden (in Sekunden).' en: 'Dump cycle defined how often the database is dumped to disc (in seconds).' + precision: + type: int + default: 2 + description: + de: 'Genauigkeit der aus der Datenbank ausgelesenen Werte (Nachkommastellen).' + en: 'Precision of values read from database (digits after comma).' item_attributes: # Definition of item attributes defined by this plugin From 0ef5db4469c1199bdf1082b08866d53d08aea0bf Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Mon, 27 Aug 2018 20:22:11 +0200 Subject: [PATCH 172/705] Database: add precision parameter to README.md --- database/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/database/README.md b/database/README.md index bfc7d2b75..ab74425df 100644 --- a/database/README.md +++ b/database/README.md @@ -62,6 +62,7 @@ database: - database:/path/to/log.db - check_same_thread:0 # prefix: log + # precision: 2 ``` The following attributes can be used in the plugin configuration: @@ -76,6 +77,10 @@ The following attributes can be used in the plugin configuration: `connect = host:127.0.0.1 | user:db_user | passwd:db_password | db:smarthome` * `prefix` - if you want to log into an existing database with other tables you can specify a prefix for the plugins' tables + * `precision` - specifies the amount of digits after comma for values + queried from the database (defaults to 2, other values are -1 to return + raw float values, 0 to return integer numbers, >0 for the given amount + of digits after comma) ### items.yaml From 4ed4ef9e50ded3f98cc969eba6154bee2a423e97 Mon Sep 17 00:00:00 2001 From: msinn Date: Mon, 27 Aug 2018 21:42:34 +0200 Subject: [PATCH 173/705] Metadata Updates --- database/plugin.yaml | 5 +++++ jvcproj/plugin.yaml | 6 ++++++ miflora/plugin.yaml | 9 ++++++++- mlgw/plugin.yaml | 6 ++++++ nuki/plugin.yaml | 7 ++++++- visu_smartvisu/plugin.yaml | 16 ++++++++-------- visu_websocket/plugin.yaml | 1 + 7 files changed, 40 insertions(+), 10 deletions(-) diff --git a/database/plugin.yaml b/database/plugin.yaml index 1fbae6a83..20fba6c6c 100755 --- a/database/plugin.yaml +++ b/database/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Database plugin, **since SmartHomeNG v1.3**' maintainer: ohinckel tester: psilo909, onkelandy, brandst + state: ready keywords: database # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page @@ -50,3 +51,7 @@ parameters: item_attributes: # Definition of item attributes defined by this plugin + +plugin_functions: + # Definition of function interface of the plugin + diff --git a/jvcproj/plugin.yaml b/jvcproj/plugin.yaml index 231e47d72..7ac44e68d 100644 --- a/jvcproj/plugin.yaml +++ b/jvcproj/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'plugin to control JVC D-ILA projectors and transfer gammatables generated with jvcprojectortools' maintainer: NPortz # tester: NPortz + state: ready # keywords: iot xyz # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1188479-plugin-steuerung-von-jvc-d-ila-projektoren @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance + restartable: unknown classname: JVC_DILA_Control # class containing the plugin parameters: @@ -46,3 +48,7 @@ item_attributes: description: de: 'Bei Aenderung des Items auf WAHR werden die Gammadaten aus der aufgefuehrten Datei in den angegebenen Custom Gammaspeicher (1-3) geladen. Die beiden Attribute muessen durch | getrennt werden.' en: 'Changing this item to true results in sending the gamma table from the declared file to the declared custom gamma table (1-3). The two attributes need to be seperated with a | .' + +plugin_functions: NONE + # Definition of function interface of the plugin + diff --git a/miflora/plugin.yaml b/miflora/plugin.yaml index ade149122..981da8077 100644 --- a/miflora/plugin.yaml +++ b/miflora/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Read from Xiaomi MiFlora plant sensors.' maintainer: psilo909 tester: Sandman60 + state: qa-passed # keywords: iot xyz documentation: http://smarthomeng.de/user/plugins_doc/config/miflora.html # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1027133-plugin-miflora-mi-plant-flowers-tester-light-monitor @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance + restartable: unknown classname: Miflora # class containing the plugin parameters: @@ -50,4 +52,9 @@ item_attributes: - 'conductivity' - 'name' - 'firmware' - - 'battery' \ No newline at end of file + - 'battery' + + +plugin_functions: NONE + # Definition of function interface of the plugin + diff --git a/mlgw/plugin.yaml b/mlgw/plugin.yaml index 75c28d113..d418802e0 100755 --- a/mlgw/plugin.yaml +++ b/mlgw/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Bang & Olufsen Masterlink Gateway' maintainer: msinn # tester: # Who tests this plugin? + state: ready # keywords: iot xyz # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page @@ -14,6 +15,7 @@ plugin: sh_minversion: 1.1 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance + restartable: False classname: Mlgw # class containing the plugin parameters: @@ -107,3 +109,7 @@ item_attributes: de: 'Befehl auf den reagiert werden soll' en: 'Command to listen for' + +plugin_functions: NONE + # Definition of function interface of the plugin + diff --git a/nuki/plugin.yaml b/nuki/plugin.yaml index 2725bba5e..028127cc3 100755 --- a/nuki/plugin.yaml +++ b/nuki/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Support for the NUKI Smart Lock' maintainer: fuppy, pfischi tester: psilo909 + state: ready keywords: Smart Lock, Nuki # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1052437-nuki-smartlock-plugin-support-thread @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.5 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance + restartable: unknown classname: Nuki # class containing the plugin parameters: @@ -96,4 +98,7 @@ item_attributes: valid_list: - 'state' - 'battery' - - 'action' \ No newline at end of file + - 'action' + +plugin_functions: NONE + # Definition of item attributes defined by this plugin diff --git a/visu_smartvisu/plugin.yaml b/visu_smartvisu/plugin.yaml index 192cd8e7e..348763916 100755 --- a/visu_smartvisu/plugin.yaml +++ b/visu_smartvisu/plugin.yaml @@ -76,13 +76,13 @@ item_attributes: - cat_seperator - room_lite description: - de: '' - en: 'Set sv_page to to one of the following values generate a page for this item. Every widget beneath this item will be included in the page' + de: "Setzen Sie 'sv_page' auf einen der angegebenen Werte, um eine Seite für dieses Item zu generieren. Jedes Widget unterhalb dieses Elements wird auf der Seite angezeigt" + en: 'Set sv_page to to one of the listed values generate a page for this item. Every widget beneath this item will be included in the page' sv_overview: type: str description: - de: '' + de: "Wenn eine Seite sv_page als 'overview' definiert hat, werden Items eines bestimmten Typs angezeigt. Der Name/Bezeichner des Typs wird definiert, indem 'sv_overview' auf einen eindeutigen Namen gesetzt wird. Damit Elemente auf dieser Seite angezeigt werden, müssen die Items 'sv_item_type' definieren und auf den Wert von 'sv_overview' setzen." en: 'If a page has defined sv_page as overview, it shows items of a specific type. The name/identifier of the type is defined by setting sv_overview to an unique name. For items to be displayed on this page, the items have to define sv_item_type and set it to the value of sv_overview.' sv_item_type: @@ -112,31 +112,31 @@ item_attributes: sv_nav_aside: type: str description: - de: '' + de: 'Ermöglicht die Angabe eines Widgets, das auf der rechten Seite der Navigationsleiste für einen Raum angezeigt wird. (obere Zeile) - Relative Item-Referenzen werden unterstützt' en: 'allows the specification of a widget, that is being displayed at the right side of the navigation bar for a room. (upper line) - Relative item references are supported' sv_nav_aside2: type: str description: - de: '' + de: 'Ermöglicht die Angabe eines Widgets, das auf der rechten Seite der Navigationsleiste für einen Raum angezeigt wird. (untere Zeile) - Relative Item-Referenzen werden unterstützt.' en: 'allows the specification of a widget, that is being displayed at the right side of the navigation bar for a room. (lower line) - Relative item references are supported.' sv_heading_left: type: str description: - de: '' + de: 'erlaubt die Angabe eines Widgets, das oben auf einer Raumseite angezeigt wird. Dieses Widget wird angezeigt, ohne in einem Block gekapselt zu sein. Das Widget ist nach links ausgerichtet' en: 'allows the specification of a widget, hat is being displayed at the top of a room-page. This widget is shown without being encapsulated in a block. The widget is aligned to to the left' sv_heading_center: type: str description: - de: '' + de: 'erlaubt die Angabe eines Widgets, das oben auf einer Raumseite angezeigt wird. Dieses Widget wird angezeigt, ohne in einem Block gekapselt zu sein. Das Widget wird zentriert' en: 'allows the specification of a widget, hat is being displayed at the top of a room-page. This widget is shown without being encapsulated in a block. The widget is aligned to to the center' sv_heading_right: type: str description: - de: '' + de: 'erlaubt die Angabe eines Widgets, das oben auf einer Raumseite angezeigt wird. Dieses Widget wird angezeigt, ohne in einem Block gekapselt zu sein. Das Widget ist nach rechts ausgerichtet' en: 'allows the specification of a widget, hat is being displayed at the top of a room-page. This widget is shown without being encapsulated in a block. The widget is aligned to to the right' plugin_functions: NONE diff --git a/visu_websocket/plugin.yaml b/visu_websocket/plugin.yaml index a4511e552..d52bbcda6 100755 --- a/visu_websocket/plugin.yaml +++ b/visu_websocket/plugin.yaml @@ -15,6 +15,7 @@ plugin: sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance + restartable: unknown classname: WebSocket # class containing the plugin parameters: From f29788caf32c5927c2f2b532000b6655995a8e96 Mon Sep 17 00:00:00 2001 From: msinn Date: Mon, 27 Aug 2018 23:29:03 +0200 Subject: [PATCH 174/705] Update to metadata --- knx/plugin.yaml | 153 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) diff --git a/knx/plugin.yaml b/knx/plugin.yaml index d9de5ca63..4e4bcb7ca 100755 --- a/knx/plugin.yaml +++ b/knx/plugin.yaml @@ -8,6 +8,7 @@ plugin: fr: 'Connexion de systèmes KNX via EIBD/KNXD' maintainer: msinn, (cmalo) tester: psilo909, onkelandy, Sandman60, brandst + state: qa-passed # keywords: iot xyz # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.4 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance + restartable: unknown classname: KNX # class containing the plugin attribute_prefix: knx # prefix of the item-attributes, so attributes have to start with 'knx_' @@ -189,6 +191,59 @@ logic_trigger_attributes: - '20' - '24' - '232' + valid_list_description: + de: + - 'Schalten (1 Bit) -> bool' + - 'Zwangssteuerung (2 Bit) -> list' + - 'Dimmen (4 Bit) -> list' + - 'Zeichen [8859_1] (8 Bit) -> str' + - 'Zeichen [8859_1] (8 Bit) -> str' + - 'Relativwert, 0 … 255 (8 Bit) -> num' + - 'Relativwert, 0 … 100 % (8 Bit) -> num' + - 'Relativwert, 0 … 100 % (8 Bit) -> num' + - 'Ganzzahl -128 - 127 (8 Bit) -> num' + - 'Ganzzahl 0 - 65535 (16 Bit) -> num' + - 'Ganzzahl -32768 - 32767 (16 Bit) -> num' + - 'Gleitkomma -671088,64 - 670760,96 (16 Bit) -> num' + - 'Uhrzeit [datetime.time] (24 Bit) -> foo' + - 'Datum [datetime.date] (24 Bit) -> foo' + - 'Ganzzahl 0 - 4294967295 (32 Bit) -> num' + - 'Ganzzahl -2147483648 - 2147483647(32 Bit) -> num' + - 'Gleitkommazahl (32 Bit) -> num' + - 'Zeichenkette [ASCII] (14 Byte) -> str' + - 'Zeichenkette [ASCII] (14 Byte) -> str' + - 'Zeichenkette [8859_1] (14 Byte) -> str' + - 'Zeichenkette [8859_1] (14 Byte) -> str' + - 'Szenennummer: 0 - 63 (8 Bit) -> num' + - 'HVAC: 0 - 255 (8 Bit) -> num' + - 'Unlimitierte Zeichenkette [8859_1] (var) -> str' + - 'RGB: [0, 0, 0] - [255, 255, 255] (3 Byte) -> list' + en: + - 'Switch (1 Bit) -> bool' + - 'forced control (2 Bit) -> list' + - 'Dim (4 Bit) -> list' + - 'Char [8859_1] (8 Bit) -> str' + - 'Char [8859_1] (8 Bit) -> str' + - 'Relative value, 0 … 255 (8 Bit) -> num' + - 'Relative value, 0 … 100 % (8 Bit) -> num' + - 'Relative value, 0 … 100 % (8 Bit) -> num' + - 'Integer -128 - 127 (8 Bit) -> num' + - 'Integer 0 - 65535 (16 Bit) -> num' + - 'Integer -32768 - 32767 (16 Bit) -> num' + - 'Float -671088,64 - 670760,96 (16 Bit) -> num' + - 'Time [datetime.time] (24 Bit) -> foo' + - 'Date [datetime.date] (24 Bit) -> foo' + - 'Integer 0 - 4294967295 (32 Bit) -> num' + - 'Integer -2147483648 - 2147483647(32 Bit) -> num' + - 'Float (32 Bit) -> num' + - 'String [ASCII] (14 Byte) -> str' + - 'String [ASCII] (14 Byte) -> str' + - 'String [8859_1] (14 Byte) -> str' + - 'String [8859_1] (14 Byte) -> str' + - 'Scene number: 0 - 63 (8 Bit) -> num' + - 'HVAC: 0 - 255 (8 Bit) -> num' + - 'unlimited string [8859_1] (var) -> str' + - 'RGB: [0, 0, 0] - [255, 255, 255] (3 Byte) -> list' description: de: 'Dieses Attribut setzt den Typ des KNX-Datenpunktes, der für die Konvertierung der KNX-Nachrichten in das interne SmartHomeNG-Format verwendet wird. Die Angabe ist zwingend erforderlich ist. Wenn Sie keinen Wert angeben, wird das Element vom Plugin ignoriert. Der DPT muss dem Typ des Artikels entsprechen!' en: "This attribute set the KNX datapoint type used for conversion of the KNX messages to internal SmartHomeNG format. It is mandatory. If you don't provide one the item will be ignored by the plugin. The DPT has to match the type of the item!" @@ -205,3 +260,101 @@ logic_trigger_attributes: de: 'Eine oder mehrere Gruppenadressen angeben, um den Objektwert vom KNX-Bus aus lesen zu können.' en: 'Specify one or more group addresses to allow reading the item value from the KNX bus.' + +logic_parameter: + # Definition of logic parameters defined by this plugin + knx_listen: + type: list(knx_ga) + description: + de: 'Gruppenadresse (oder Liste von Gruppenadressen), auf die gehört werden soll. KNX-Nachrichten an diese Gruppenadresse(n) werden an die Logik weitergegeben' + en: "Group address (or list of group addresses) to listen for. KNX messages to this group address(es) will be directed to th logic" + + knx_reply: + type: list(knx_ga) + description: + de: 'Eine oder mehrere Gruppenadressen angeben, um den Objektwert vom KNX-Bus aus lesen zu können.' + en: 'Specify one or more group addresses to allow reading the item value from the KNX bus.' + + +plugin_functions: + # Definition of function interface of the plugin + + encode: + type: foo + description: + de: "Diese Funktion codiert Ihre Daten entsprechend dem angegebenen Datenpunkt - Beispiel: data = sh.knx.encode(data, 9)" + en: "This function encodes your data according to the specified datapoint - Example: data = sh.knx.encode(data, 9)" + parameters: + data: + type: foo + description: + de: "Zu codierende Daten" + en: "Data to encode" + dpt: + type: foo + description: + de: "KNX Datenpunkttyp" + en: "KNX datapoint type" + + groupwrite: + type: foo + description: + de: "Mit dieser Funktion könnten Sie die Daten an die angegebene Gruppenadresse senden - Beispiel: sh.knx.groupwrite('1/1/10', 10.3, '9')" + en: "With this function you could send the data to the specified group address - Example: sh.knx.groupwrite('1/1/10', 10.3, '9')" + parameters: + ga: + type: knx_ga + description: + de: "Gruppenadresse an die der Wert gesendet werden soll" + en: "Group adress to write to" + data: + type: foo + description: + de: "Zu sendende Daten. Der Datentyp wird durch den Parameter 'dpt' bestimmt." + en: "Data to be sent. The data type is determined by the parameter 'dpt'" + dpt: + type: foo + description: + de: "KNX Datenpunkttyp" + en: "KNX datapoint type" + + groupread: + type: foo + description: + de: "Diese Funktion löst eine Leseanforderung für die angegebene Gruppenadresse aus. Da KNX ereignisgesteuert ist **wird der empfangene Wert nicht zurückgegeben**!" + en: "This function triggers a read request on the specified group address. Since KNX is event driven **it will not return the received value**!" + parameters: + ga: + type: knx_ga + description: + de: "Gruppenadresse von der gelesen werden soll" + en: "Group address from which to read" + cache: + type: bool + default: False + description: + de: "Versuchen den Wert aus dem Cache von KNXD zu lesen?" + en: "Try to read the value from the cache of KNXD?" + + send_time: + type: foo + description: + de: "Diese Funktion sendet die aktuelle Uhrzeit und/oder das aktuelle Datum an die angegebene Gruppenadresse. Hinweis: Anstelle dieser Funktion können Sie das Plugin-Attribut 'send_time' wie oben beschrieben verwenden - Beispiele: sh.knx.send_time('1/1/1', '1/1/2') # sendet die Zeit zu 1/1/1 und das Datum zu 1/1/2; sh.knx.send_time('1/1/1') # sendet nur die Zeit zu 1/1/1; sh.knx.send_time(data_ga='1/1/2') # Sendet nur das Datum zu 1/1/2" + en: "This function sends the current time and/or date to the specified group address. Hint: instead of this function you could use the plugin attribute 'send_time' as described above - Examples: sh.knx.send_time('1/1/1', '1/1/2') # send the time to 1/1/1 and the date to 1/1/2; sh.knx.send_time('1/1/1') # only send the time to 1/1/1; sh.knx.send_time(data_ga='1/1/2') # only send the date to 1/1/2" + parameters: + time_ga: + type: knx_ga + description: + de: "Gruppenadresse an die die Uhrzeit gesendet wird" + en: "Group address to send the time to" + date_ga: + type: knx_ga + description: + de: "Gruppenadresse an die das Datum gesendet wird" + en: "Group address to send the date to" + + + + + + From 9e4bb78d768ce8caefb597f6d79b6b2f55534b7f Mon Sep 17 00:00:00 2001 From: msinn Date: Mon, 27 Aug 2018 23:40:05 +0200 Subject: [PATCH 175/705] Metadata updates --- knx/plugin.yaml | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/knx/plugin.yaml b/knx/plugin.yaml index 4e4bcb7ca..8529be0e6 100755 --- a/knx/plugin.yaml +++ b/knx/plugin.yaml @@ -50,6 +50,9 @@ parameters: - 'true' - 'false' - 'logger' + valid_list_description: + de: ['Ein', 'Aus', 'Ein', 'Aus', 'in eigenen Logger'] + en: ['On', 'Off', 'On', 'Off', 'to own logger'] description: de: "Wenn auf 'on'/'true' gesetzt, wird jedes KNX-Paket im Standard-Logger protokolliert. Wenn 'logger' eingestellt ist, werden alle KNX-Meldungen in einem separaten Logger 'knx_busmonitor' protokolliert." en: "If set to 'on'/'true' every KNX packet will be logged to the default plugin logger. If set to 'logger', all knx messages will be logged to a separate logger 'knx_busmonitor'" @@ -114,6 +117,59 @@ item_attributes: - '20' - '24' - '232' + valid_list_description: + de: + - 'Schalten (1 Bit) -> bool' + - 'Zwangssteuerung (2 Bit) -> list' + - 'Dimmen (4 Bit) -> list' + - 'Zeichen [8859_1] (8 Bit) -> str' + - 'Zeichen [8859_1] (8 Bit) -> str' + - 'Relativwert, 0 … 255 (8 Bit) -> num' + - 'Relativwert, 0 … 100 % (8 Bit) -> num' + - 'Relativwert, 0 … 100 % (8 Bit) -> num' + - 'Ganzzahl -128 - 127 (8 Bit) -> num' + - 'Ganzzahl 0 - 65535 (16 Bit) -> num' + - 'Ganzzahl -32768 - 32767 (16 Bit) -> num' + - 'Gleitkomma -671088,64 - 670760,96 (16 Bit) -> num' + - 'Uhrzeit [datetime.time] (24 Bit) -> foo' + - 'Datum [datetime.date] (24 Bit) -> foo' + - 'Ganzzahl 0 - 4294967295 (32 Bit) -> num' + - 'Ganzzahl -2147483648 - 2147483647(32 Bit) -> num' + - 'Gleitkommazahl (32 Bit) -> num' + - 'Zeichenkette [ASCII] (14 Byte) -> str' + - 'Zeichenkette [ASCII] (14 Byte) -> str' + - 'Zeichenkette [8859_1] (14 Byte) -> str' + - 'Zeichenkette [8859_1] (14 Byte) -> str' + - 'Szenennummer: 0 - 63 (8 Bit) -> num' + - 'HVAC: 0 - 255 (8 Bit) -> num' + - 'Unlimitierte Zeichenkette [8859_1] (var) -> str' + - 'RGB: [0, 0, 0] - [255, 255, 255] (3 Byte) -> list' + en: + - 'Switch (1 Bit) -> bool' + - 'forced control (2 Bit) -> list' + - 'Dim (4 Bit) -> list' + - 'Char [8859_1] (8 Bit) -> str' + - 'Char [8859_1] (8 Bit) -> str' + - 'Relative value, 0 … 255 (8 Bit) -> num' + - 'Relative value, 0 … 100 % (8 Bit) -> num' + - 'Relative value, 0 … 100 % (8 Bit) -> num' + - 'Integer -128 - 127 (8 Bit) -> num' + - 'Integer 0 - 65535 (16 Bit) -> num' + - 'Integer -32768 - 32767 (16 Bit) -> num' + - 'Float -671088,64 - 670760,96 (16 Bit) -> num' + - 'Time [datetime.time] (24 Bit) -> foo' + - 'Date [datetime.date] (24 Bit) -> foo' + - 'Integer 0 - 4294967295 (32 Bit) -> num' + - 'Integer -2147483648 - 2147483647(32 Bit) -> num' + - 'Float (32 Bit) -> num' + - 'String [ASCII] (14 Byte) -> str' + - 'String [ASCII] (14 Byte) -> str' + - 'String [8859_1] (14 Byte) -> str' + - 'String [8859_1] (14 Byte) -> str' + - 'Scene number: 0 - 63 (8 Bit) -> num' + - 'HVAC: 0 - 255 (8 Bit) -> num' + - 'unlimited string [8859_1] (var) -> str' + - 'RGB: [0, 0, 0] - [255, 255, 255] (3 Byte) -> list' description: de: 'Dieses Attribut setzt den Typ des KNX-Datenpunktes, der für die Konvertierung der KNX-Nachrichten in das interne SmartHomeNG-Format verwendet wird. Die Angabe ist zwingend erforderlich ist. Wenn Sie keinen Wert angeben, wird das Element vom Plugin ignoriert. Der DPT muss dem Typ des Artikels entsprechen!' en: "This attribute set the KNX datapoint type used for conversion of the KNX messages to internal SmartHomeNG format. It is mandatory. If you don't provide one the item will be ignored by the plugin. The DPT has to match the type of the item! BE CAREFUL to put the value in quotes to ensure they are interpreted as strings and not as numbers!" From 4de9266cc93750fbe1a17c7178eaf88b3b1d1d69 Mon Sep 17 00:00:00 2001 From: msinn Date: Mon, 27 Aug 2018 23:43:36 +0200 Subject: [PATCH 176/705] Metadata update --- knx/plugin.yaml | 166 +++++++++++++++++++++++------------------------- 1 file changed, 80 insertions(+), 86 deletions(-) diff --git a/knx/plugin.yaml b/knx/plugin.yaml index 8529be0e6..54f3de72e 100755 --- a/knx/plugin.yaml +++ b/knx/plugin.yaml @@ -219,91 +219,6 @@ item_attributes: logic_trigger_attributes: # Definition of logic trigger attributes defined by this plugin - knx_dpt: - type: str - valid_list: - - '1' - - '2' - - '3' - - '4002' - - '4.002' - - '5' - - '5001' - - '5.001' - - '6' - - '7' - - '8' - - '9' - - '10' - - '11' - - '12' - - '13' - - '14' - - '16000' - - '16' - - '16001' - - '16.001' - - '17' - - '20' - - '24' - - '232' - valid_list_description: - de: - - 'Schalten (1 Bit) -> bool' - - 'Zwangssteuerung (2 Bit) -> list' - - 'Dimmen (4 Bit) -> list' - - 'Zeichen [8859_1] (8 Bit) -> str' - - 'Zeichen [8859_1] (8 Bit) -> str' - - 'Relativwert, 0 … 255 (8 Bit) -> num' - - 'Relativwert, 0 … 100 % (8 Bit) -> num' - - 'Relativwert, 0 … 100 % (8 Bit) -> num' - - 'Ganzzahl -128 - 127 (8 Bit) -> num' - - 'Ganzzahl 0 - 65535 (16 Bit) -> num' - - 'Ganzzahl -32768 - 32767 (16 Bit) -> num' - - 'Gleitkomma -671088,64 - 670760,96 (16 Bit) -> num' - - 'Uhrzeit [datetime.time] (24 Bit) -> foo' - - 'Datum [datetime.date] (24 Bit) -> foo' - - 'Ganzzahl 0 - 4294967295 (32 Bit) -> num' - - 'Ganzzahl -2147483648 - 2147483647(32 Bit) -> num' - - 'Gleitkommazahl (32 Bit) -> num' - - 'Zeichenkette [ASCII] (14 Byte) -> str' - - 'Zeichenkette [ASCII] (14 Byte) -> str' - - 'Zeichenkette [8859_1] (14 Byte) -> str' - - 'Zeichenkette [8859_1] (14 Byte) -> str' - - 'Szenennummer: 0 - 63 (8 Bit) -> num' - - 'HVAC: 0 - 255 (8 Bit) -> num' - - 'Unlimitierte Zeichenkette [8859_1] (var) -> str' - - 'RGB: [0, 0, 0] - [255, 255, 255] (3 Byte) -> list' - en: - - 'Switch (1 Bit) -> bool' - - 'forced control (2 Bit) -> list' - - 'Dim (4 Bit) -> list' - - 'Char [8859_1] (8 Bit) -> str' - - 'Char [8859_1] (8 Bit) -> str' - - 'Relative value, 0 … 255 (8 Bit) -> num' - - 'Relative value, 0 … 100 % (8 Bit) -> num' - - 'Relative value, 0 … 100 % (8 Bit) -> num' - - 'Integer -128 - 127 (8 Bit) -> num' - - 'Integer 0 - 65535 (16 Bit) -> num' - - 'Integer -32768 - 32767 (16 Bit) -> num' - - 'Float -671088,64 - 670760,96 (16 Bit) -> num' - - 'Time [datetime.time] (24 Bit) -> foo' - - 'Date [datetime.date] (24 Bit) -> foo' - - 'Integer 0 - 4294967295 (32 Bit) -> num' - - 'Integer -2147483648 - 2147483647(32 Bit) -> num' - - 'Float (32 Bit) -> num' - - 'String [ASCII] (14 Byte) -> str' - - 'String [ASCII] (14 Byte) -> str' - - 'String [8859_1] (14 Byte) -> str' - - 'String [8859_1] (14 Byte) -> str' - - 'Scene number: 0 - 63 (8 Bit) -> num' - - 'HVAC: 0 - 255 (8 Bit) -> num' - - 'unlimited string [8859_1] (var) -> str' - - 'RGB: [0, 0, 0] - [255, 255, 255] (3 Byte) -> list' - description: - de: 'Dieses Attribut setzt den Typ des KNX-Datenpunktes, der für die Konvertierung der KNX-Nachrichten in das interne SmartHomeNG-Format verwendet wird. Die Angabe ist zwingend erforderlich ist. Wenn Sie keinen Wert angeben, wird das Element vom Plugin ignoriert. Der DPT muss dem Typ des Artikels entsprechen!' - en: "This attribute set the KNX datapoint type used for conversion of the KNX messages to internal SmartHomeNG format. It is mandatory. If you don't provide one the item will be ignored by the plugin. The DPT has to match the type of the item!" - knx_listen: type: list(knx_ga) description: @@ -369,7 +284,86 @@ plugin_functions: de: "Zu sendende Daten. Der Datentyp wird durch den Parameter 'dpt' bestimmt." en: "Data to be sent. The data type is determined by the parameter 'dpt'" dpt: - type: foo + type: str + valid_list: + - '1' + - '2' + - '3' + - '4002' + - '4.002' + - '5' + - '5001' + - '5.001' + - '6' + - '7' + - '8' + - '9' + - '10' + - '11' + - '12' + - '13' + - '14' + - '16000' + - '16' + - '16001' + - '16.001' + - '17' + - '20' + - '24' + - '232' + valid_list_description: + de: + - 'Schalten (1 Bit) -> bool' + - 'Zwangssteuerung (2 Bit) -> list' + - 'Dimmen (4 Bit) -> list' + - 'Zeichen [8859_1] (8 Bit) -> str' + - 'Zeichen [8859_1] (8 Bit) -> str' + - 'Relativwert, 0 … 255 (8 Bit) -> num' + - 'Relativwert, 0 … 100 % (8 Bit) -> num' + - 'Relativwert, 0 … 100 % (8 Bit) -> num' + - 'Ganzzahl -128 - 127 (8 Bit) -> num' + - 'Ganzzahl 0 - 65535 (16 Bit) -> num' + - 'Ganzzahl -32768 - 32767 (16 Bit) -> num' + - 'Gleitkomma -671088,64 - 670760,96 (16 Bit) -> num' + - 'Uhrzeit [datetime.time] (24 Bit) -> foo' + - 'Datum [datetime.date] (24 Bit) -> foo' + - 'Ganzzahl 0 - 4294967295 (32 Bit) -> num' + - 'Ganzzahl -2147483648 - 2147483647(32 Bit) -> num' + - 'Gleitkommazahl (32 Bit) -> num' + - 'Zeichenkette [ASCII] (14 Byte) -> str' + - 'Zeichenkette [ASCII] (14 Byte) -> str' + - 'Zeichenkette [8859_1] (14 Byte) -> str' + - 'Zeichenkette [8859_1] (14 Byte) -> str' + - 'Szenennummer: 0 - 63 (8 Bit) -> num' + - 'HVAC: 0 - 255 (8 Bit) -> num' + - 'Unlimitierte Zeichenkette [8859_1] (var) -> str' + - 'RGB: [0, 0, 0] - [255, 255, 255] (3 Byte) -> list' + en: + - 'Switch (1 Bit) -> bool' + - 'forced control (2 Bit) -> list' + - 'Dim (4 Bit) -> list' + - 'Char [8859_1] (8 Bit) -> str' + - 'Char [8859_1] (8 Bit) -> str' + - 'Relative value, 0 … 255 (8 Bit) -> num' + - 'Relative value, 0 … 100 % (8 Bit) -> num' + - 'Relative value, 0 … 100 % (8 Bit) -> num' + - 'Integer -128 - 127 (8 Bit) -> num' + - 'Integer 0 - 65535 (16 Bit) -> num' + - 'Integer -32768 - 32767 (16 Bit) -> num' + - 'Float -671088,64 - 670760,96 (16 Bit) -> num' + - 'Time [datetime.time] (24 Bit) -> foo' + - 'Date [datetime.date] (24 Bit) -> foo' + - 'Integer 0 - 4294967295 (32 Bit) -> num' + - 'Integer -2147483648 - 2147483647(32 Bit) -> num' + - 'Float (32 Bit) -> num' + - 'String [ASCII] (14 Byte) -> str' + - 'String [ASCII] (14 Byte) -> str' + - 'String [8859_1] (14 Byte) -> str' + - 'String [8859_1] (14 Byte) -> str' + - 'Scene number: 0 - 63 (8 Bit) -> num' + - 'HVAC: 0 - 255 (8 Bit) -> num' + - 'unlimited string [8859_1] (var) -> str' + - 'RGB: [0, 0, 0] - [255, 255, 255] (3 Byte) -> list' description: de: "KNX Datenpunkttyp" en: "KNX datapoint type" From 72cecc058aee2c84bade40a6acde61eba0a838c9 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Tue, 28 Aug 2018 00:06:10 +0200 Subject: [PATCH 177/705] Implemented webinterface, updated methods and logging --- avdevice/AVDeviceInit.py | 19 +- avdevice/Denon_Items.yaml | 18 +- avdevice/__init__.py | 356 +- avdevice/_pv_1_3_6/AVDeviceFunctions.py | 606 ++++ avdevice/_pv_1_3_6/AVDeviceInit.py | 868 +++++ avdevice/_pv_1_3_6/Denon_Items.yaml | 640 ++++ avdevice/_pv_1_3_6/Pioneer_Items.yaml | 305 ++ avdevice/_pv_1_3_6/README.md | 476 +++ avdevice/_pv_1_3_6/__init__.py | 2968 +++++++++++++++++ .../models/denon-avr6300.txt} | 67 +- avdevice/_pv_1_3_6/models/epson-tw5000.txt | 3 + avdevice/_pv_1_3_6/models/oppo-udp203.txt | 47 + .../_pv_1_3_6/models/oppo-udp203_real.txt | 68 + avdevice/_pv_1_3_6/models/sc-lx86.txt | 65 + avdevice/_pv_1_3_6/models/vsx-923.txt | 47 + avdevice/_pv_1_3_6/plugin.yaml | 334 ++ .../_pv_1_3_6/translations/denon_standby.txt | 19 + .../_pv_1_3_6/translations/denon_volume.txt | 2 + .../_pv_1_3_6/translations/pioneer_LM.txt | 143 + .../_pv_1_3_6/translations/pioneer_SR.txt | 103 + .../_pv_1_3_6/translations/pioneer_input.txt | 21 + avdevice/plugin.yaml | 4 +- avdevice/webif/static/img/avdevice.tif | Bin 0 -> 87356 bytes avdevice/webif/static/img/plugin_logo.png | Bin 0 -> 8980 bytes avdevice/webif/static/img/readme.txt | 6 + avdevice/webif/templates/index.html | 378 +++ 26 files changed, 7424 insertions(+), 139 deletions(-) create mode 100755 avdevice/_pv_1_3_6/AVDeviceFunctions.py create mode 100755 avdevice/_pv_1_3_6/AVDeviceInit.py create mode 100755 avdevice/_pv_1_3_6/Denon_Items.yaml create mode 100755 avdevice/_pv_1_3_6/Pioneer_Items.yaml create mode 100755 avdevice/_pv_1_3_6/README.md create mode 100755 avdevice/_pv_1_3_6/__init__.py rename avdevice/{models/denon-avr1100.txt => _pv_1_3_6/models/denon-avr6300.txt} (51%) create mode 100755 avdevice/_pv_1_3_6/models/epson-tw5000.txt create mode 100755 avdevice/_pv_1_3_6/models/oppo-udp203.txt create mode 100755 avdevice/_pv_1_3_6/models/oppo-udp203_real.txt create mode 100755 avdevice/_pv_1_3_6/models/sc-lx86.txt create mode 100755 avdevice/_pv_1_3_6/models/vsx-923.txt create mode 100755 avdevice/_pv_1_3_6/plugin.yaml create mode 100755 avdevice/_pv_1_3_6/translations/denon_standby.txt create mode 100755 avdevice/_pv_1_3_6/translations/denon_volume.txt create mode 100755 avdevice/_pv_1_3_6/translations/pioneer_LM.txt create mode 100755 avdevice/_pv_1_3_6/translations/pioneer_SR.txt create mode 100755 avdevice/_pv_1_3_6/translations/pioneer_input.txt create mode 100644 avdevice/webif/static/img/avdevice.tif create mode 100644 avdevice/webif/static/img/plugin_logo.png create mode 100755 avdevice/webif/static/img/readme.txt create mode 100755 avdevice/webif/templates/index.html diff --git a/avdevice/AVDeviceInit.py b/avdevice/AVDeviceInit.py index ba581d068..22411d8b5 100755 --- a/avdevice/AVDeviceInit.py +++ b/avdevice/AVDeviceInit.py @@ -28,6 +28,8 @@ import re import os +from lib.item import Items + VERBOSE1 = logging.DEBUG - 1 VERBOSE2 = logging.DEBUG - 2 logging.addLevelName(logging.DEBUG - 1, 'VERBOSE1') @@ -36,12 +38,12 @@ class Init(object): - def __init__(self, smarthome, name, model, items): + def __init__(self, name, model, items): self._items = items self._name = name self._model = model - self._sh = smarthome self._ignoreresponse = [] + self.itemsApi = Items.get_instance() self.logger = logging.getLogger(__name__) self.logger.log(VERBOSE1, "Initializing {}: Started".format(self._name)) @@ -55,6 +57,19 @@ def __init__(self, smarthome, name, model, items): self._number_of_zones = 0 self._special_commands = {} + def get_items(self, zone): + itemlist = [] + sortedlist = [] + finallist = [] + for item in self._items[zone]: + _result = self._items[zone][item].get('Item') + itemlist.append(_result) + sortedlist.append(_result.id()) + sortedlist.sort() + for i in sortedlist: + finallist.append(self.itemsApi.return_item(i)) + return finallist + def update_dependencies(self, dependencies): done = False for zone in dependencies['Master_function']: diff --git a/avdevice/Denon_Items.yaml b/avdevice/Denon_Items.yaml index 07eeb165f..127a3d154 100755 --- a/avdevice/Denon_Items.yaml +++ b/avdevice/Denon_Items.yaml @@ -231,10 +231,10 @@ Denon: Musik: type: bool visu_acl: ro - eval: 1 if ((sh.Denon.Source() == 'DVD' or sh.Denon.Source() == 'CD' or sh.Denon.Source() == 'NET') and sh.Denon.Power()) else 0 + eval: 1 if ((sh.Musik.OG.Denon.Source() == 'DVD' or sh.Musik.OG.Denon.Source() == 'CD' or sh.Musik.OG.Denon.Source() == 'NET') and sh.Musik.OG.Denon.Power()) else 0 eval_trigger: - - Denon.Source - - Denon.Power + - Musik.OG.Denon.Source + - Musik.OG.Denon.Power enforce_updates: 'yes' Mode: @@ -437,10 +437,10 @@ Denon: Musik: type: bool visu_acl: ro - eval: 1 if ((sh.Denon.Source2() == 'DVD' or sh.Denon.Source2() == 'CD' or sh.Denon.Source2() == 'NET') and sh.Denon.Power2()) else 0 + eval: 1 if ((sh.Musik.OG.Denon.Source2() == 'DVD' or sh.Musik.OG.Denon.Source2() == 'CD' or sh.Musik.OG.Denon.Source2() == 'NET') and sh.Musik.OG.Denon.Power2()) else 0 eval_trigger: - - Denon.Source2 - - Denon.Power2 + - Musik.OG.Denon.Source2 + - Musik.OG.Denon.Power2 Mute2: type: bool @@ -522,10 +522,10 @@ Denon: Musik: type: bool visu_acl: ro - eval: 1 if ((sh.Denon.Source3() == 'DVD' or sh.Denon.Source3() == 'CD' or sh.Denon.Source3() == 'NET') and sh.Denon.Power3()) else 0 + eval: 1 if ((sh.Musik.OG.Denon.Source3() == 'DVD' or sh.Musik.OG.Denon.Source3() == 'CD' or sh.Musik.OG.Denon.Source3() == 'NET') and sh.Musik.OG.Denon.Power3()) else 0 eval_trigger: - - Denon.Source3 - - Denon.Power3 + - Musik.OG.Denon.Source3 + - Musik.OG.Denon.Power3 Mute3: type: bool diff --git a/avdevice/__init__.py b/avdevice/__init__.py index 1f71cf3fc..82512a238 100755 --- a/avdevice/__init__.py +++ b/avdevice/__init__.py @@ -24,13 +24,16 @@ ######################################################################### import logging -from lib.model.smartplugin import SmartPlugin +from lib.model.smartplugin import * +from lib.item import Items + import io import time +import datetime import re import errno -import sys import itertools + from .AVDeviceInit import Init from .AVDeviceInit import ProcessVariables from .AVDeviceFunctions import CreateResponse @@ -38,6 +41,11 @@ from .AVDeviceFunctions import ConvertValue from .AVDeviceFunctions import CreateExpectedResponse +# Used to get errorline, for debugging only +# sys.exc_info()[-1].tb_lineno +#try: +# import sys + VERBOSE1 = logging.DEBUG - 1 VERBOSE2 = logging.DEBUG - 2 logging.addLevelName(logging.DEBUG - 1, 'VERBOSE1') @@ -46,69 +54,46 @@ class AVDevice(SmartPlugin): ALLOW_MULTIINSTANCE = True - PLUGIN_VERSION = "1.3.6" - - def __init__(self, smarthome, - model='', - ignoreresponse='RGB,RGC,RGD,GBH,GHH,VTA,AUA,AUB', - errorresponse='E02,E04,E06', - forcebuffer='GEH01020, GEH04022, GEH05024', - inputignoredisplay='', - dependson_item='', - dependson_value=True, - rs232_port='', - rs232_baudrate=9600, - rs232_timeout=0.1, - tcp_ip='', - tcp_port=23, - tcp_timeout=1, - resetonerror=False, - depend0_power0=False, - depend0_volume0=False, - sendretries=10, - resendwait=1.0, - reconnectretries=13, - secondstokeep=50, - responsebuffer='5', - autoreconnect=False, - update_exclude='', - statusquery=True): - self.logger = logging.getLogger(__name__) - self._sh = smarthome - self.alive = False - self._name = self.get_instance_name() - self._serialwrapper = None - self._serial = None - self._tcpsocket = None - self._functions = {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}} - self._items = {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}} - self._query_zonecommands = {'zone0': [], 'zone1': [], 'zone2': [], 'zone3': [], 'zone4': []} - self._items_speakers = {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}} - self._send_commands = [] - self._init_commands = {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}} - self._keep_commands = {} - self._specialparse = {} - self._query_commands = [] - self._power_commands = [] - self._expected_response = [] - self._response_commands = {} - self._response_wildcards = {'wildcard': {}, 'original': {}} - self._number_of_zones = 0 - self._trigger_reconnect = True - self._reconnect_counter = 0 - self._resend_counter = 0 - self._resend_on_empty_counter = 0 - self._clearbuffer = False - self._sendingcommand = 'done' - self._special_commands = {} - self._is_connected = [] - self._parsinginput = [] - self._dependencies = {'Slave_function': {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}}, - 'Slave_item': {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}}, - 'Master_function': {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}}, - 'Master_item': {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}}} + PLUGIN_VERSION = "1.5.0" + def __init__(self, smarthome): + self.itemsApi = Items.get_instance() + self.logger = logging.getLogger(__name__) + self.init_webinterface() try: + self.alive = False + self._name = self.get_fullname() + self._serialwrapper = None + self._serial = None + self._tcpsocket = None + self._functions = {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}} + self._items = {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}} + self._query_zonecommands = {'zone0': [], 'zone1': [], 'zone2': [], 'zone3': [], 'zone4': []} + self._items_speakers = {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}} + self._send_commands = [] + self._init_commands = {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}} + self._keep_commands = {} + self._specialparse = {} + self._query_commands = [] + self._power_commands = [] + self._expected_response = [] + self._response_commands = {} + self._response_wildcards = {'wildcard': {}, 'original': {}} + self._number_of_zones = 0 + self._trigger_reconnect = True + self._reconnect_counter = 0 + self._resend_counter = 0 + self._resend_on_empty_counter = 0 + self._clearbuffer = False + self._sendingcommand = 'done' + self._special_commands = {} + self._is_connected = [] + self._parsinginput = [] + self._send_history = {'query': {}, 'command': {}} + self._dependencies = {'Slave_function': {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}}, + 'Slave_item': {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}}, + 'Master_function': {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}}, + 'Master_item': {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}}} self._model = self.get_parameter_value('model') self._resend_wait = float(self.get_parameter_value('resendwait')) self._secondstokeep = int(self.get_parameter_value('secondstokeep')) @@ -133,39 +118,37 @@ def __init__(self, smarthome, rs232_timeout = self.get_parameter_value('rs232_timeout') update_exclude = self.get_parameter_value('update_exclude') statusquery = self.get_parameter_value('statusquery') + + # Initializing all variables + self.logger.debug("Initializing {}: Resendwait: {}. Seconds to keep: {}.".format(self._name, self._resend_wait, + self._secondstokeep)) + self.init = Init(self._name, self._model, self._items) + self._rs232, self._baud, self._timeout = ProcessVariables([rs232_port, rs232_baudrate, rs232_timeout], + self._name).process_rs232() + self._tcp, self._port, self._tcp_timeout = ProcessVariables([tcp_ip, tcp_port, tcp_timeout], + self._name).process_tcp() + self._dependson, self._dependson_value, self._depend0_power0, self._depend0_volume0 = ProcessVariables( + [dependson_item, dependson_value, depend0_power0, depend0_volume0], self._name).process_dependson() + + self._response_buffer = ProcessVariables(responsebuffer, self._name).process_responsebuffer() + self._reset_onerror = ProcessVariables(resetonerror, self._name).process_resetonerror() + self._statusquery = ProcessVariables(statusquery, self._name).process_statusquery() + self._ignore_response, self._error_response, self._force_buffer, self._ignoredisplay = ProcessVariables( + [ignoreresponse, errorresponse, forcebuffer, inputignoredisplay], self._name).process_responses() + self.logger.debug( + "Initializing {}: Special Settings: Ignoring responses {}.".format(self._name, self._ignore_response)) + self.logger.debug( + "Initializing {}: Special Settings: Error responses {}.".format(self._name, self._error_response)) + self.logger.debug("Initializing {}: Special Settings: Force buffer {}.".format(self._name, self._force_buffer)) + self.logger.debug( + "Initializing {}: Special Settings: Ignore Display {}".format(self._name, self._ignoredisplay)) + self.logger.debug( + "Initializing {}: Querying at plugin init is set to {}".format(self._name, self._statusquery)) + self._update_exclude = ProcessVariables(update_exclude, self._name).process_update_exclude() + except Exception: - self._model = model - self._resend_wait = float(resendwait) - self._secondstokeep = int(secondstokeep) - self._auto_reconnect = autoreconnect - self._resend_retries = int(sendretries) - self._reconnect_retries = int(reconnectretries) - # Initializing all variables - self.logger.debug("Initializing {}: Resendwait: {}. Seconds to keep: {}.".format(self._name, self._resend_wait, - self._secondstokeep)) - self.init = Init(self._sh, self._name, self._model, self._items) - self._rs232, self._baud, self._timeout = ProcessVariables([rs232_port, rs232_baudrate, rs232_timeout], - self._name).process_rs232() - self._tcp, self._port, self._tcp_timeout = ProcessVariables([tcp_ip, tcp_port, tcp_timeout], - self._name).process_tcp() - self._dependson, self._dependson_value, self._depend0_power0, self._depend0_volume0 = ProcessVariables( - [dependson_item, dependson_value, depend0_power0, depend0_volume0], self._name).process_dependson() - - self._response_buffer = ProcessVariables(responsebuffer, self._name).process_responsebuffer() - self._reset_onerror = ProcessVariables(resetonerror, self._name).process_resetonerror() - self._statusquery = ProcessVariables(statusquery, self._name).process_statusquery() - self._ignore_response, self._error_response, self._force_buffer, self._ignoredisplay = ProcessVariables( - [ignoreresponse, errorresponse, forcebuffer, inputignoredisplay], self._name).process_responses() - self.logger.debug( - "Initializing {}: Special Settings: Ignoring responses {}.".format(self._name, self._ignore_response)) - self.logger.debug( - "Initializing {}: Special Settings: Error responses {}.".format(self._name, self._error_response)) - self.logger.debug("Initializing {}: Special Settings: Force buffer {}.".format(self._name, self._force_buffer)) - self.logger.debug( - "Initializing {}: Special Settings: Ignore Display {}".format(self._name, self._ignoredisplay)) - self.logger.debug( - "Initializing {}: Querying at plugin init is set to {}".format(self._name, self._statusquery)) - self._update_exclude = ProcessVariables(update_exclude, self._name).process_update_exclude() + self._init_complete = False + return # Non-blocking wait function @staticmethod @@ -191,7 +174,7 @@ def _resetitem(self, founditem): "Resetting {}: Resetting nothing because command is query command only.".format(self._name)) return None try: - founditem = self._sh.return_item(founditem) + founditem = self.itemsApi.return_item(founditem) except Exception as err: self.logger.debug("Resetting {}: {} is no valid item. Message: {}.".format(self._name, founditem, err)) return None @@ -822,6 +805,12 @@ def _processing_response(self, socket): self.logger.error("Processing Response {}: Problems: {} in line {}.".format( self._name, err, sys.exc_info()[-1].tb_lineno)) + def _clear_history(self, part): + if part == 'keep': + self._keep_commands.clear() + else: + self._send_history[part].clear() + # init function def _initialize(self): self._send_commands[:] = [] @@ -862,6 +851,7 @@ def _initialize(self): # Run function def run(self): + self.logger.debug("Plugin '{}': run method called".format(self.get_fullname())) if self._tcp is None and self._rs232 is None: self.logger.error( "Initializing {}: Neither IP address nor RS232 port given. Not running.".format(self._name)) @@ -876,7 +866,7 @@ def run(self): self.logger.log(VERBOSE1, "Initializing {}: Speaker Items: {}".format(self._name, self._items_speakers)) try: try: - self._dependson = self._sh.return_item(self._dependson) + self._dependson = self.itemsApi.return_item(self._dependson) self.logger.debug("Initializing {}: Dependson Item: {}.".format(self._name, self._dependson)) except Exception: self._dependson = None @@ -903,15 +893,18 @@ def connect(self, trigger): if depending is False: if self._tcp is not None and 'TCP' not in self._is_connected: self.logger.log(VERBOSE1, "Connecting {}: Starting TCP scheduler".format(self._name)) - self._sh.scheduler.add('avdevice-tcp-reconnect', self.connect_tcp, cycle=7) - self._sh.scheduler.change('avdevice-tcp-reconnect', active=True) - self._sh.scheduler.trigger('avdevice-tcp-reconnect') + try: + self.scheduler_add('avdevice-tcp-reconnect', self.connect_tcp, cycle=7) + except Exception as err: + self.logger.error(err) + self.scheduler_change('avdevice-tcp-reconnect', active=True) + self.scheduler_trigger('avdevice-tcp-reconnect') self._trigger_reconnect = False if self._rs232 is not None and 'Serial' not in self._is_connected: self.logger.log(VERBOSE1, "Connecting {}: Starting RS232 scheduler".format(self._name)) - self._sh.scheduler.add('avdevice-serial-reconnect', self.connect_serial, cycle=7) - self._sh.scheduler.change('avdevice-serial-reconnect', active=True) - self._sh.scheduler.trigger('avdevice-serial-reconnect') + self.scheduler_add('avdevice-serial-reconnect', self.connect_serial, cycle=7) + self.scheduler_change('avdevice-serial-reconnect', active=True) + self.scheduler_trigger('avdevice-serial-reconnect') self._trigger_reconnect = False elif depending is True and trigger == 'parse_dataerror': self._resetondisconnect('connect') @@ -920,7 +913,15 @@ def connect(self, trigger): def connect_tcp(self): try: if self._tcp is not None and 'TCP' not in self._is_connected: - socket = __import__('socket') + try: + socket = __import__('socket') + REQUIRED_PACKAGE_IMPORTED = True + except: + REQUIRED_PACKAGE_IMPORTED = False + if not REQUIRED_PACKAGE_IMPORTED: + self.logger.error("{}: Unable to import Python package 'socket'".format(self.get_fullname())) + self._init_complete = False + return self.logger.log(VERBOSE1, "Connecting TCP {}: Starting to connect to {}.".format(self._name, self._tcp)) self._tcpsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._tcpsocket.setblocking(0) @@ -951,7 +952,7 @@ def connect_tcp(self): self.logger.warning("Connecting TCP {}: Reconnecting. Command list while connecting: {}.".format( self._name, self._send_commands)) elif cond3 or cond4: - self._sh.scheduler.change('avdevice-tcp-reconnect', active=False) + self.scheduler_change('avdevice-tcp-reconnect', active=False) self._reconnect_counter = 0 if cond4: self._addorremove_keepcommands('disconnect', 'all') @@ -959,7 +960,7 @@ def connect_tcp(self): self._addorremove_keepcommands('connected', 'all') self._trigger_reconnect = True self.logger.debug( - "Connecting TCP {}: Deactivating reconnect scheduler. Command list while connecting: {}. " + "Connecting TCP {}: Deactivating reconnect schedulerApi. Command list while connecting: {}. " "Keep Commands: {}. Reconnecttrigger: {}".format( self._name, self._send_commands, self._keep_commands, self._trigger_reconnect)) self._reconnect_counter += 1 @@ -973,7 +974,15 @@ def connect_tcp(self): def connect_serial(self): try: if self._rs232 is not None and 'Serial' not in self._is_connected: - serial = __import__('serial') + try: + serial = __import__('serial') + REQUIRED_PACKAGE_IMPORTED = True + except: + REQUIRED_PACKAGE_IMPORTED = False + if not REQUIRED_PACKAGE_IMPORTED: + self.logger.error("{}: Unable to import Python package 'serial'".format(self.get_fullname())) + self._init_complete = False + return ser = serial.serial_for_url('{}'.format(self._rs232), baudrate=int(self._baud), timeout=float(self._timeout), write_timeout=float(self._timeout)) i = 0 @@ -1033,10 +1042,10 @@ def connect_serial(self): if cond1 and cond2: self._trigger_reconnect = False self.logger.log(VERBOSE1, - "Connecting Serial {}: Activating reconnect scheduler. Command list while connecting: {}.".format( + "Connecting Serial {}: Activating reconnect schedulerApi. Command list while connecting: {}.".format( self._name, self._send_commands)) elif cond3 or cond4: - self._sh.scheduler.change('avdevice-serial-reconnect', active=False) + self.scheduler_change('avdevice-serial-reconnect', active=False) self._reconnect_counter = 0 if cond4: self._addorremove_keepcommands('disconnect', 'all') @@ -1044,7 +1053,7 @@ def connect_serial(self): self._addorremove_keepcommands('connected', 'all') self._trigger_reconnect = True self.logger.debug( - "Connecting Serial {}: Deactivating reconnect scheduler. Command list while connecting: {}. " + "Connecting Serial {}: Deactivating reconnect schedulerApi. Command list while connecting: {}. " "Keep commands: {}. Reconnecttrigger: {}".format( self._name, self._send_commands, self._keep_commands, self._trigger_reconnect)) self._reconnect_counter += 1 @@ -1221,6 +1230,7 @@ def _checkdependency(self, dep_function, dep_type): if primarycount > 0 and queryentry is not None: if queryentry not in self._send_commands: self._send_commands.append(queryentry) + self._send_history['query'][datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")] = queryentry self.logger.debug( "Checking Dependency {}: Dependent Query command {} added to Send Commands. Dependencies: {}".format( self._name, queryentry, dependitems)) @@ -1300,7 +1310,7 @@ def _checkdependency(self, dep_function, dep_type): else: depending = True try: - item = self._sh.return_item(dep_function).id() + item = self.itemsApi.return_item(dep_function).id() except Exception: item = dep_function.id() if not item == self._dependson.id(): @@ -2149,6 +2159,7 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl depending = self._checkdependency(query, 'statusupdate') if query not in self._send_commands and depending is False: self._send_commands.append(query) + self._send_history['query'][datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")] = query self._reconnect_counter = 0 self._trigger_reconnect = True @@ -2195,6 +2206,7 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl "Updating Item {}: Readonly. Updating Zone {} Commands {} for {}".format( self._name, zone, self._send_commands, item)) self._send_commands.append(appendcommand) + self._send_history['command'][datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")] = appendcommand except Exception as err: self.logger.log(VERBOSE2, @@ -2228,6 +2240,7 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl "Updating Item {}: Updating Zone {} Commands {} for {}".format( self._name, zone, self._send_commands, item)) self._send_commands.append(appendcommand) + self._send_history['command'][datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")] = appendcommand checkquery = True elif command_increase in self._functions['zone{}'.format(zone)]: commandinfo = self._functions['zone{}'.format(zone)][command_increase] @@ -2281,6 +2294,7 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl "Updating Item {}: Updating Zone {} Command Increase {} for {}".format( self._name, zone, self._send_commands, item)) self._send_commands.append(appendcommand) + self._send_history['command'][datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")] = appendcommand elif command_decrease in self._functions['zone{}'.format(zone)]: commandinfo = self._functions['zone{}'.format(zone)][command_decrease] try: @@ -2333,6 +2347,7 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl "Updating Item {}: Updating Zone {} Command Decrease {} for {}".format( self._name, zone, self._send_commands, item)) self._send_commands.append(appendcommand) + self._send_history['command'][datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")] = appendcommand elif command_on in self._functions['zone{}'.format(zone)] and \ isinstance(value, bool) and value == 1: @@ -2383,6 +2398,7 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl self._name, appendcommand, self._keep_commands)) else: self._send_commands.append(appendcommand) + self._send_history['command'][datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")] = appendcommand self._sendingcommand = appendcommand checkquery = True self.logger.log(VERBOSE1, @@ -2398,6 +2414,7 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl depending = self._checkdependency(query, 'statusupdate') if query not in self._send_commands and depending is False: self._send_commands.append(query) + self._send_history['query'][datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")] = query elif command_off in self._functions['zone{}'.format(zone)] and \ isinstance(value, bool) and value == 0: @@ -2448,6 +2465,7 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl self._name, appendcommand, self._keep_commands)) else: self._send_commands.append(appendcommand) + self._send_history['command'][datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")] = appendcommand self._sendingcommand = appendcommand checkquery = True self.logger.log(VERBOSE1, @@ -2584,6 +2602,7 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl self._name, appendcommand, self._keep_commands)) else: self._send_commands.append(appendcommand) + self._send_history['command'][datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")] = appendcommand self._sendingcommand = appendcommand self._resend_counter = 0 checkquery = True @@ -2611,6 +2630,7 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl self._name, appendcommand, self._keep_commands)) else: self._send_commands.append(appendcommand) + self._send_history['command'][datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")] = appendcommand self._resend_counter = 0 checkquery = True self.logger.log(VERBOSE1, @@ -2938,13 +2958,13 @@ def _send(self, command, caller): def stop(self): self.alive = False try: - self._sh.scheduler.change('avdevice-tcp-reconnect', active=False) - self._sh.scheduler.remove('avdevice-tcp-reconnect') + self.scheduler_change('avdevice-tcp-reconnect', active=False) + self.scheduler_remove('avdevice-tcp-reconnect') except Exception: pass try: - self._sh.scheduler.change('avdevice-serial-reconnect', active=False) - self._sh.scheduler.remove('avdevice-serial-reconnect') + self.scheduler_change('avdevice-serial-reconnect', active=False) + self.scheduler_remove('avdevice-serial-reconnect') except Exception: pass try: @@ -2958,9 +2978,105 @@ def stop(self): except Exception: self.logger.log(VERBOSE1, "Stopping {}: No Serial socket to close.".format(self._name)) + def init_webinterface(self): + """" + Initialize the web interface for this plugin + + This method is only needed if the plugin is implementing a web interface + """ + try: + self.mod_http = Modules.get_instance().get_module('http') # try/except to handle running in a core version that does not support modules + except: + self.mod_http = None + if self.mod_http == None: + self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_shortname())) + return False + + import sys + if not "SmartPluginWebIf" in list(sys.modules['lib.model.smartplugin'].__dict__): + self.logger.warning("Plugin '{}': Web interface needs SmartHomeNG v1.5 and up. Not initializing the web interface".format(self.get_shortname())) + return False -if __name__ == '__main__': - logging.basicConfig( - level=logging.DEBUG, format='%(relativeCreated)6d %(threadName)s %(message)s') - # noinspection PyUnresolvedReferences - PluginClassName(AVDevice).run() + # set application configuration for cherrypy + webif_dir = self.path_join(self.get_plugin_dir(), 'webif') + config = { + '/': { + 'tools.staticdir.root': webif_dir, + }, + '/static': { + 'tools.staticdir.on': True, + 'tools.staticdir.dir': 'static' + } + } + + # Register the web interface as a cherrypy app + self.mod_http.register_webif(WebInterface(webif_dir, self), + self.get_shortname(), + config, + self.get_classname(), self.get_instance_name(), + description='') + + return True + + +# ------------------------------------------ +# Webinterface of the plugin +# ------------------------------------------ + +import cherrypy +from jinja2 import Environment, FileSystemLoader + +class WebInterface(SmartPluginWebIf): + + + def __init__(self, webif_dir, plugin): + """ + Initialization of instance of class WebInterface + + :param webif_dir: directory where the webinterface of the plugin resides + :param plugin: instance of the plugin + :type webif_dir: str + :type plugin: object + """ + self.logger = logging.getLogger(__name__) + self.webif_dir = webif_dir + self.plugin = plugin + self.tplenv = self.init_template_environment() + + + @cherrypy.expose + def index(self, action=None, item_id=None, item_path=None, reload=None): + """ + Build index.html for cherrypy + + Render the template and return the html file to be delivered to the browser + + :return: contents of the template after beeing rendered + """ + item = self.plugin.get_sh().return_item(item_path) + config_reloaded = False + keep_cleared = False + command_cleared = False + query_cleared = False + if action is not None: + if action == "reload": + self.plugin._initialize() + config_reloaded = True + if action == "connect": + self.plugin.connect('webif') + if action == "clear_query_history": + self.plugin._clear_history('query') + query_cleared = True + if action == "clear_command_history": + self.plugin._clear_history('command') + command_cleared = True + if action == "clear_keep_commands": + self.plugin._clear_history('keep') + keep_cleared = True + + tmpl = self.tplenv.get_template('index.html') + # add values to be passed to the Jinja2 template eg: tmpl.render(p=self.plugin, interface=interface, ...) + return tmpl.render(p=self.plugin, + config_reloaded=config_reloaded, query_cleared=query_cleared, + command_cleared=command_cleared, keep_cleared=keep_cleared, + language=self.plugin._sh.get_defaultlanguage(), now=self.plugin.shtime.now()) diff --git a/avdevice/_pv_1_3_6/AVDeviceFunctions.py b/avdevice/_pv_1_3_6/AVDeviceFunctions.py new file mode 100755 index 000000000..3817aa4b6 --- /dev/null +++ b/avdevice/_pv_1_3_6/AVDeviceFunctions.py @@ -0,0 +1,606 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2016 +######################################################################### +# This file is part of SmartHomeNG. +# +# Plugin to control AV Devices via TCP and/or RS232 +# Tested with Pioneer AV Receivers. +# +# SmartHomeNG is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# SmartHomeNG is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with SmartHomeNG. If not, see . +# +######################################################################### + +import logging +import re + +VERBOSE1 = logging.DEBUG - 1 +VERBOSE2 = logging.DEBUG - 2 +logging.addLevelName(logging.DEBUG - 1, 'VERBOSE1') +logging.addLevelName(logging.DEBUG - 2, 'VERBOSE2') + + +class CreateExpectedResponse(object): + def __init__(self, buffer, name, sendcommands): + self._buffer = buffer + self._name = name + self._send_commands = sendcommands + + self.logger = logging.getLogger(__name__) + self.logger.debug( + "Processing Response {}: Creating expected response. Buffer: {}. Name: {}. Sendcommands: {}".format( + self._name, re.sub('[\r\n]', ' --- ', self._buffer), self._name, self._send_commands)) + + def create_expected(self): + expectedresponse = [] + try: + for resp in self._send_commands: + if resp.split(',', 2)[2].find('|') >= 0: + splitresponse = resp.split(';')[0].split('|') + else: + splitresponse = [resp] + splitresponse[0] = splitresponse[0].split(',', 2)[2] + for i in range(0, len(splitresponse)): + splitresponse[i] = splitresponse[i].split(',')[0] + if not self._buffer == '': + splitresponse[i] = Translate(self._buffer.split("\r\n")[0], splitresponse[i], self._name, '', '').wildcard() + self.logger.log(VERBOSE2, "Processing Response {}: Splitresponse after wildcard {}: {}.".format( + self._name, i, splitresponse[i])) + wildcardresponse = [] + for wild in splitresponse: + if '?' not in wild: + wildcardresponse.append(wild) + splitresponse = '|'.join(wildcardresponse) + if not splitresponse == '': + expectedresponse.append(splitresponse) + except Exception as err: + self.logger.error( + "Processing Response {}: Problems creating expected response list. Error: {}".format(self._name, err)) + return expectedresponse + + +class Translate(object): + def __init__(self, code, dictentry, name, caller, specialparse): + self._code = code + self._dictentry = dictentry + self._caller = caller + self._name = name + self._specialparse = specialparse + self._data = code + self._command = dictentry + + self.logger = logging.getLogger(__name__) + + def wildcard(self): + if self._command.find('?') >= 1: + wildcard_replace = [] + wildcard = [] + command = self._command.split('*')[0] + unprocessed = command + command = command.replace('*{str}', '*') + command = realcommand = command.replace('?{str}', '?') + for i in range(9, 0, -1): + command = command.replace('?' * i, '?') + splitcommand = command.split('?') + splitreal = unprocessed.split('*')[0].split('?')[1:] + splitcommand = splitcommand[:-1] if splitcommand[len(splitcommand) - 1] == '' else splitcommand + splitreal = splitreal[:-1] if splitcommand[len(splitcommand) - 1] == '' else splitreal + self.logger.log(VERBOSE2, + "Processing Wildcard {}: Command: {} (original: {}), Splitcommand: {}. Splitreal: {}. Data: {}".format( + self._name, command, unprocessed, splitcommand, splitreal, self._data)) + for i in range(0, len(splitcommand)): + try: + data = self._data.split(splitcommand[i], 1)[1] + except Exception: + break + try: + toreplace = data[0:data.find(splitcommand[i + 1])] if data.find(splitcommand[i + 1]) >= 0 else data + wildcard_replace.append(toreplace) + except Exception: + wildcard_replace.append(data) + try: + start = realcommand.find(splitcommand[i]) + len(splitcommand[i]) \ + if i == 0 and not splitcommand[i] == '' else 0 + try: + end = start + realcommand[start:].find(splitcommand[i + 1]) + newstart = end + len(splitcommand[i + 1]) + except Exception: + end = None + newstart = 0 + wildcard.append(realcommand[start:end]) + realcommand = realcommand[newstart:] + except Exception: + pass + if wildcard_replace: + self.logger.log(VERBOSE2, + "Processing Wildcard {}: Wildcard replace: {}, Wildcard: {}.".format( + self._name, wildcard_replace, wildcard)) + newstring = '' + for i in range(0, len(splitcommand)): + try: + self.logger.log(VERBOSE2, + "Processing Wildcard {}: replace {}, wildcard {}, splitreal {}".format( + self._name, wildcard_replace[i], wildcard[i], splitreal[i])) + cond1 = len(wildcard_replace[i]) == len(wildcard[i]) + cond2 = '{str}' in splitreal[i] + replace = True if ((cond1 or cond2) and not wildcard[i] == '') else False + except Exception: + replace = False + try: + if replace is True: + newstring += splitcommand[i] + wildcard_replace[i] + self.logger.log(VERBOSE2, + "Processing Wildcard {}: Replace {} by {}.".format(self._name, wildcard[i], + wildcard_replace[i])) + else: + try: + newstring += splitcommand[i] + wildcard[i] + except Exception: + newstring += splitcommand[i] + wildcard_replace[i] + except Exception as err: + newstring = unprocessed + self.logger.log(VERBOSE2, "Processing Wildcard {}: Problem {}.".format(self._name, err)) + break + else: + newstring = unprocessed.split('*')[0] + self.logger.log(VERBOSE2, "Processing Wildcard {}: Command to compare: {}.".format(self._name, newstring)) + else: + newstring = self._command.split('*')[0] + + return newstring + + def translate(self): + origcaller = self._caller + caller = 'parse' if self._caller == 'writedict' else self._caller + str_code = '' + result = '' + try: + self._code = eval(self._code) + except Exception: + pass + try: + code = self._code.lower() + except Exception: + try: + str_code = str(self._code) + if str_code in self._specialparse[self._dictentry][caller].keys(): + code = str_code + else: + code = '' + for i in range(0, len(str_code)): + code += str_code[i].replace(str_code[i], '*') if \ + str_code[i].isdigit() else str_code[i] + except Exception: + code = self._code + try: + if '*' in code and caller == 'parse': + result_temp = self._specialparse[self._dictentry][caller].get(code) + z = 0 + for i in range(0, len(result_temp)): + if result_temp[i] == '*': + result += result_temp[i].replace('*', str_code[z]) + z += 1 + else: + result += result_temp[i] + self._specialparse[self._dictentry][caller].update({self._code: result}) + elif '*' in code: + result_temp = self._specialparse[self._dictentry][caller].get(code) + z = 0 + for i in range(0, len(str_code)): + if str_code[i].isdigit() and result_temp[z] == '*': + result += result_temp[z].replace('*', str_code[i]) + z += 1 + self._specialparse[self._dictentry]['parse'].update({result: self._code}) + self._specialparse[self._dictentry]['update'].update({self._code: result}) + else: + result = self._specialparse[self._dictentry][caller].get(code) + except Exception: + result = None + self.logger.log(VERBOSE2, "Translating {}: Called by: {}. Dictentry: {}," + " Code: {}, Result: {}.".format( + self._name, origcaller, self._dictentry, code, result)) + return result + + +class ConvertValue(object): + def __init__(self, receivedvalue, expectedtype, invert, valuelength, command, name, specialcommands): + self._receivedvalue = receivedvalue + self._expectedtype = expectedtype + self._invert = invert + self._valuelength = valuelength + self._command = command[0] if isinstance(command, list) else command + self._special_commands = specialcommands + self._name = name + self.logger = logging.getLogger(__name__) + self.logger.debug( + "Converting Values {}: Received Value is: {} with expected type {}. Invert: {}. Length: {}. Command: {}".format( + self._name, receivedvalue, expectedtype, invert, valuelength, command)) + + def _convertbool(self): + try: + if self._invert is True: + self._receivedvalue = False if int(self._receivedvalue) == 1 and \ + len(str(self._receivedvalue)) <= 1 and self._valuelength == 1 \ + else True if int(self._receivedvalue) == 0 and \ + len(str(self._receivedvalue)) <= 1 and self._valuelength == 1 \ + else self._receivedvalue + else: + self._receivedvalue = True if int(self._receivedvalue) == 1 and \ + len(str(self._receivedvalue)) <= 1 and self._valuelength == 1 \ + else False if int(self._receivedvalue) == 0 and \ + len(str(self._receivedvalue)) <= 1 and self._valuelength == 1 \ + else self._receivedvalue + except Exception: + pass + return self._receivedvalue + + def _convertdisplay(self): + returnvalue = ['display', ''] + try: + content = self._receivedvalue[2:][:28] + tempvalue = "".join(list(map(lambda i: chr(int(content[2 * i:][:2], 0x10)), range(14)))).strip() + self._receivedvalue = re.sub(r'^[^A-Z0-9]*', '', tempvalue) + self.logger.debug("Converting Values {}: Display Output Pioneer {}".format(self._name, self._receivedvalue)) + returnvalue = ['display', self._receivedvalue] + except Exception as err: + self.logger.log(VERBOSE1, "Converting Values {}: No display info for Pioneer found. Message: {}".format( + self._name, err)) + try: + infotype = self._receivedvalue[3:4] + if infotype.isdigit(): + infotype = int(infotype) + self._receivedvalue = self._receivedvalue[4:] if infotype == 0 else \ + self._receivedvalue[5:] if infotype == 1 else self._receivedvalue[6:] + returnvalue = ['nowplaying', self._receivedvalue] if infotype == 1 and self._receivedvalue \ + else ['station', self._receivedvalue] if infotype == 2 and self._receivedvalue \ + else ['display', self._receivedvalue] + self.logger.log(VERBOSE1, "Converting Values {}: Displayinfo: {}".format(self._name, returnvalue)) + except Exception as err: + self.logger.debug( + "Converting Values {}: Unknown display info for Denon received. Message: {}".format( + self._name, err)) + return returnvalue + + # Converting received values to bool, string or int to compare the responses with the expected response + def convert_value(self): + self._receivedvalue = self._convertdisplay() \ + if self._command in self._special_commands['Display']['Command'] \ + else self._convertbool() if 'bool' in self._expectedtype \ + else self._receivedvalue + cond1 = 'bool' in self._expectedtype and 'int' in self._expectedtype + cond2 = 'str' in self._expectedtype and 'bool' in self._expectedtype + if 'int' in self._expectedtype: + try: + cond1 = str(self._receivedvalue).lower() == 'on' and \ + ('bool' in self._expectedtype or self._valuelength == 1) + cond2 = ('bool' in self._expectedtype or self._valuelength == 1) \ + and (str(self._receivedvalue).lower() == 'off' or str(self._receivedvalue).lower() == 'standby') + self._receivedvalue = 1 if cond1 else 0 if cond2 else self._receivedvalue + except Exception: + pass + try: + self._receivedvalue = int(self._receivedvalue) + except Exception: + pass + elif not (cond1 or cond2): + try: + cond1 = str(self._receivedvalue).lower() == 'on' and (self._valuelength == 100 or self._valuelength == 2) + cond2 = str(self._receivedvalue).lower() == 'open' and (self._valuelength == 100 or self._valuelength == 4) + cond3 = str(self._receivedvalue).lower() == 'off' and (self._valuelength == 100 or self._valuelength == 3) + cond4 = str(self._receivedvalue).lower() == 'standby' and (self._valuelength == 100 or self._valuelength == 7) + cond5 = str(self._receivedvalue).lower() == 'close' and (self._valuelength == 100 or self._valuelength == 5) + cond6 = str(self._receivedvalue).lower() == 'clos' and (self._valuelength == 100 or self._valuelength == 4) + self._receivedvalue = True if cond1 or cond2 \ + else False if cond3 or cond4 or cond5 or cond6 \ + else self._receivedvalue + except Exception: + pass + try: + self._receivedvalue = eval(self._receivedvalue.lstrip('0')) + except Exception: + try: + self._receivedvalue = eval(self._receivedvalue) + except Exception: + pass + if not self._expectedtype == 'str': + try: + self._receivedvalue = float(self._receivedvalue) if '.' in self._receivedvalue \ + else int(self._receivedvalue) + except Exception: + pass + self.logger.debug("Converting Values {}: Received Value is now: {} with type {}.".format( + self._name, self._receivedvalue, type(self._receivedvalue))) + return self._receivedvalue + + +class CreateResponse(object): + def __init__(self, commandinfo, reverseinfo, value, name, specialparse): + self._commandinfo = commandinfo + self._reverseinfo = reverseinfo + self._value = value + self._name = name + self._specialparse = specialparse + + try: + self._splitresponse = self._commandinfo[4].split('|') + except Exception: + self._splitresponse = self._commandinfo.split('|') + try: + self._splitreverse = self._reverseinfo[4].split('|') + except Exception: + self._splitreverse = self._reverseinfo.split('|') + + self.logger = logging.getLogger(__name__) + self.logger.log(VERBOSE1, + "Creating Response {}: Create response command {}, reverse {}, value {}".format( + self._name, commandinfo, reverseinfo, value)) + + def _finalize(self, responselist, reverselist, func_type): + replacedresponse = "|".join(responselist) + replacedreverse = "|".join(reverselist) + self.logger.log(VERBOSE2, + "Updating Item {}: Replaced response: {}, replaced reverse: {}. Type: {}".format( + self._name, replacedresponse, replacedreverse, func_type)) + return replacedresponse, replacedreverse + + def replace_string(self, command, value, dictentry=None): + value = value.upper() + try: + value = self._specialparse[dictentry]['update'].get(value) or value + except Exception: + pass + try: + replaced = command.replace('*', '{}'.format(value), 1) + replaced = replaced.replace('*', '') + except Exception: + replaced = command + self.logger.log(VERBOSE2, + "Updating Item {}: Replaced string for command {} with dictentry {}: original value: {}. replaced value: {}".format( + self._name, command, dictentry, value, replaced)) + return replaced + + def replace_number(self, command, value, dictentry=None): + try: + value = self._specialparse[dictentry]['parse'].get(str(value)) or value + except Exception: + pass + try: + value = max(min(value, int(self._commandinfo[8])), int(self._commandinfo[7])) + except Exception: + try: + value = min(value, int(self._commandinfo[8])) + except Exception: + pass + value = max(min(value, int(re.sub('[^0-9]', '', re.sub('\*', '9', self._commandinfo[2])))), 0) \ + if self._commandinfo[2].count('*') > 1 else \ + max(min(value, 9), 0) if command.count('*') == 1 \ + else value + try: + value = str(self._specialparse[dictentry]['update'].get(value) or value)[:command.count('*')] + except Exception: + pass + replaced = re.sub(r'(\*)\1+', '{0:0{1}d}'.format(int(value), command.count('*')), command) \ + if command.count('*') > 1 \ + else command.replace('*', '{0:01d}'.format(int(value))) \ + if command.count('*') == 1 \ + else command + self.logger.log(VERBOSE2, + "Updating Item {}: 2: Replaced number for command {} with dictentry {}: original value: {}. replaced value: {}".format( + self._name, command, dictentry, value, replaced)) + return replaced + + def response_power(self): + responselist = [] + for splitre in self._splitresponse: + valuelength = splitre.count('*') + if valuelength > 0 or 'R' in self._commandinfo[5]: + responselist = [] + if self._commandinfo[6].lower() in ['1', 'true', 'yes', 'on']: + replacedvalue = '0' + else: + replacedvalue = '1' + replacedresponse = splitre.replace('*', replacedvalue) + else: + replacedresponse = splitre + + responselist.append('{},{},{}'.format(replacedresponse, self._commandinfo[9], valuelength)) + + return self._finalize(responselist, [], 'power') + + def response_standard(self): + responselist = [] + for splitre in self._splitresponse: + valuelength = splitre.count('*') + if valuelength > 0 or 'R' in self._commandinfo[5]: + responselist = [] + replacedresponse = splitre.split('*')[0].strip() + if splitre.count('?') == 1: + replacedresponse = re.sub('[?]', '', replacedresponse) + else: + replacedresponse = splitre + + responselist.append('{},{},{}'.format(replacedresponse, self._commandinfo[9], valuelength)) + + return self._finalize(responselist, [], 'standard') + + def response_in_decrease(self): + responselist = [] + reverselist = [] + for counting, splitre in enumerate(self._splitresponse): + valuelength = reverselength = splitre.count('*') + if valuelength > 0 or 'R' in self._commandinfo[5]: + responselist = [] + reverselist = [] + replacedresponse = re.sub('[*]', '', splitre.strip()) + if splitre.count('?') == 1: + replacedresponse = re.sub('[?]', '', replacedresponse) + try: + reverselength = self._splitreverse[counting].count('*') + replacedreverse = re.sub('[*]', '', self._splitreverse[counting].strip()) + if self._splitreverse[counting].count('?') == 1: + replacedreverse = re.sub('[?]', '', replacedreverse) + except Exception: + replacedreverse = '' + else: + replacedresponse = splitre + try: + replacedreverse = self._splitreverse[counting] + reverselength = self._splitreverse[counting].count('*') + except Exception: + replacedreverse = '' + + if not replacedresponse == '': + responselist.append('{},{},{}'.format(replacedresponse, self._commandinfo[9], valuelength)) + if not replacedreverse == '': + reverselist.append('{},{},{}'.format(replacedreverse, self._commandinfo[9], reverselength)) + return self._finalize(responselist, reverselist, 'in_decrease') + + def response_off(self): + responselist = [] + reverselist = [] + for counting, splitre in enumerate(self._splitresponse): + valuelength = reverselength = splitre.count('*') + if valuelength > 0 or 'R' in self._commandinfo[5]: + responselist = [] + reverselist = [] + replacedreverse = '' + replacedresponse = splitre.replace('*******', 'STANDBY') + replacedresponse = replacedresponse.replace('*****', 'CLOSE') + replacedresponse = replacedresponse.replace('****', 'CLOS') + replacedresponse = replacedresponse.replace('***', 'OFF') + if self._commandinfo[6].lower() in ['1', 'true', 'yes', 'on']: + replacedvalue = '1' + reversevalue = '0' + else: + replacedvalue = '0' + reversevalue = '1' + try: + reverselength = self._splitreverse[counting].count('*') + replacedreverse = self._splitreverse[counting].replace('****', 'OPEN') + replacedreverse = replacedreverse.replace('**', 'ON') + except Exception as err: + self.logger.log(VERBOSE2, + "Updating Item {}: Problems replacing * for off reverse command: {}".format( + self._name, err)) + + replacedresponse = replacedresponse.replace('*', replacedvalue) + replacedreverse = replacedreverse.replace('*', reversevalue) + else: + replacedresponse = splitre + try: + replacedreverse = self._splitreverse[counting] + reverselength = self._splitreverse[counting].count('*') + except Exception: + replacedreverse = '' + + if not replacedresponse == '': + responselist.append('{},{},{}'.format(replacedresponse, self._commandinfo[9], valuelength)) + if not replacedreverse == '': + reverselist.append('{},{},{}'.format(replacedreverse, self._commandinfo[9], reverselength)) + + return self._finalize(responselist, reverselist, 'off') + + def response_set(self): + responselist = [] + for splitre in self._splitresponse: + valuelength = splitre.count('*') + if valuelength > 0 or 'R' in self._commandinfo[5]: + replacedresponse = '' + try: + value = Translate(self._value, self._commandinfo[10], self._name, + 'update', self._specialparse).translate() or self._value + except Exception: + value = self._value + try: + value = eval(value.lstrip('0')) + except Exception: + pass + self.logger.log(VERBOSE2, "Setting Response {}: Final value: {}".format(self._name, value)) + try: + translatecode = self._commandinfo[10] + except Exception: + translatecode = None + cond2 = isinstance(value, int) and 'int' in self._commandinfo[9] + cond3 = isinstance(value, float) and 'float' in self._commandinfo[9] + if value == 0 and 'bool' in self._commandinfo[9]: + value = 'OFF' + try: + replacedresponse = re.sub('\*+', '{}'.format(value), splitre) + except Exception: + replacedresponse = splitre + elif cond2 or cond3: + replacedresponse = self.replace_number(splitre, value, translatecode) + elif isinstance(value, str) and 'str' in self._commandinfo[9]: + replacedresponse = self.replace_string(splitre, value, translatecode) + else: + self.logger.log(VERBOSE2, + "Setting Response {}: There might be something wrong with replacing the response.".format( + self._name)) + else: + replacedresponse = splitre + + if not replacedresponse == '': + responselist.append('{},{},{}'.format(replacedresponse, self._commandinfo[9], valuelength)) + self.logger.log(VERBOSE2, "Setting Response {}: Responselist: {}".format(self._name, responselist)) + return self._finalize(responselist, [], 'set') + + def response_on(self): + responselist = [] + reverselist = [] + for counting, splitre in enumerate(self._splitresponse): + valuelength = reverselength = splitre.count('*') + if valuelength > 0 or 'R' in self._commandinfo[5]: + replacedresponse = replacedreverse = replacedvalue = reversevalue = '' + try: + replacedresponse = splitre.replace('****', 'OPEN') + replacedresponse = replacedresponse.replace('**', 'ON') + if self._commandinfo[6].lower() in ['1', 'true', 'yes', 'on']: + replacedvalue = '0' + reversevalue = '1' + else: + replacedvalue = '1' + reversevalue = '0' + except Exception as err: + self.logger.debug( + "Updating Item {}: Problems replacing * for on command: {}".format(self._name, err)) + try: + reverselength = self._splitreverse[counting].count('*') + replacedreverse = self._splitreverse[counting].replace('*****', 'CLOSE') + replacedreverse = replacedreverse.replace('****', 'CLOS') + replacedreverse = replacedreverse.replace('***', 'OFF') + except Exception as err: + self.logger.log(VERBOSE2, + "Updating Item {}: Problems replacing * for on reverse command: {}".format( + self._name, err)) + replacedresponse = replacedresponse.replace('*', replacedvalue) + replacedreverse = replacedreverse.replace('*', reversevalue) + self.logger.log(VERBOSE2, + "Updating Item {}: Replaced on response: {} Replaced on reverse: {}".format( + self._name, replacedresponse, replacedreverse)) + else: + replacedresponse = splitre + try: + replacedreverse = self._splitreverse[counting] + reverselength = self._splitreverse[counting].count('*') + except Exception: + replacedreverse = '' + + if not replacedresponse == '': + responselist.append('{},{},{}'.format(replacedresponse, self._commandinfo[9], valuelength)) + if not replacedreverse == '': + reverselist.append('{},{},{}'.format(replacedreverse, self._commandinfo[9], reverselength)) + self.logger.log(VERBOSE2, "Updating Item {}: Replaced on responselist: {} Replaced on reverselist: {}".format( + self._name, responselist, reverselist)) + return self._finalize(responselist, reverselist, 'on') diff --git a/avdevice/_pv_1_3_6/AVDeviceInit.py b/avdevice/_pv_1_3_6/AVDeviceInit.py new file mode 100755 index 000000000..ba581d068 --- /dev/null +++ b/avdevice/_pv_1_3_6/AVDeviceInit.py @@ -0,0 +1,868 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2016 +######################################################################### +# This file is part of SmartHomeNG. +# +# Plugin to control AV Devices via TCP and/or RS232 +# Tested with Pioneer AV Receivers. +# +# SmartHomeNG is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# SmartHomeNG is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with SmartHomeNG. If not, see . +# +######################################################################### + +import logging + +import re +import os + +VERBOSE1 = logging.DEBUG - 1 +VERBOSE2 = logging.DEBUG - 2 +logging.addLevelName(logging.DEBUG - 1, 'VERBOSE1') +logging.addLevelName(logging.DEBUG - 2, 'VERBOSE2') + + +class Init(object): + + def __init__(self, smarthome, name, model, items): + self._items = items + self._name = name + self._model = model + self._sh = smarthome + self._ignoreresponse = [] + + self.logger = logging.getLogger(__name__) + self.logger.log(VERBOSE1, "Initializing {}: Started".format(self._name)) + + self._functions = {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}} + self._query_zonecommands = {'zone0': [], 'zone1': [], 'zone2': [], 'zone3': [], 'zone4': []} + self._query_commands = [] + self._power_commands = [] + self._response_commands = {} + self._specialparse = {} + self._number_of_zones = 0 + self._special_commands = {} + + def update_dependencies(self, dependencies): + done = False + for zone in dependencies['Master_function']: + self.logger.log(VERBOSE2, "Updating Dependencies {}: Starting for {}. ".format(self._name, zone)) + for entry in dependencies['Master_function'][zone]: + for device_function in self._functions[zone]: + alreadydone = [] + if self._functions[zone][device_function][1] == entry: + for instance in dependencies['Master_function'][zone][entry]: + dependingfunction = instance.get('Function') + dependzone = instance.get('Zone') + # self.logger.log(VERBOSE2, "Updating Dependencies {}: Testing depending {}.".format(self._name, dependzone)) + for command in self._functions[dependzone]: + # self.logger.log(VERBOSE2, "Updating Dependencies {}: Command {}.".format(self._name, command)) + if self._functions[dependzone][command][1] == dependingfunction: + for entrylist in self._items[dependzone][dependingfunction]['Master']: + querycommand = self._functions[dependzone][command][3] + valuetype = self._functions[dependzone][command][9] + splitresponse = self._functions[dependzone][command][4].split('|') + responselist = [] + for splitted in splitresponse: + valuelength = splitted.count('*') + if valuelength > 0 or 'R' in self._functions[dependzone][command][5]: + response_toadd = splitted.strip() + cond1 = splitted.count('?') == 1 and splitted.count('*') == 0 + response_toadd = re.sub('[?]', '*', response_toadd) if cond1 else response_toadd + responselist.append('{},{},{}'.format(response_toadd, valuetype, valuelength)) + responsecommand = "|".join(responselist) + commandlist = '{},{},{}'.format(querycommand, querycommand, responsecommand) + try: + if command.split(' ')[1] in ['on', 'off', 'increase', 'decrease']: + for already in dependencies['Slave_query'][dependzone]: + if already.split(',')[0] == querycommand: + alreadylist = ','.join(already.split(',')[2:]).split('|') + responses = [re.sub('[*]', '', x.split(',')[0]) for x in alreadylist] + for resp in responselist: + resp_split = re.sub('[*]', '', resp.split(',')[0]) + cond1 = resp_split in responses + cond2_1 = set(resp.split(',')[1:-1]) + cond2_2 = set(already.split('|')[0].split(',')[3:-1]) + cond2 = cond2_1 == cond2_2 + self.logger.log(VERBOSE2, "Updating Dependencies {}: Querycommand {} for zone {}" + " already in list. Testing -{}- against the responses {}." + " Testing type {} against {}".format( + self._name, querycommand, zone, resp_split, + responses, cond2_1, cond2_2)) + if resp not in alreadylist and cond1 and cond2: + newquery = already + '|' + resp + dependencies['Slave_query'][dependzone][newquery] = \ + dependencies['Slave_query'][dependzone].get(already) + dependencies['Slave_query'][dependzone].pop(already) + instance['Query'] = newquery + self.logger.log(VERBOSE2, + "Updating Dependencies {}: Adding {} to {}.".format( + self._name, resp, alreadylist)) + if commandlist not in alreadydone: + alreadydone.append(commandlist) + elif cond1 and cond2: + if commandlist not in alreadydone: + alreadydone.append(commandlist) + self.logger.log(VERBOSE2, "Updating Dependencies {}: Skipping {}.".format( + self._name, commandlist)) + except Exception as err: + pass + if commandlist in alreadydone: + self.logger.log(VERBOSE2, "Updating Dependencies {}: Commandlist {} is alreadydone: {}, skipping.".format( + self._name, commandlist, alreadydone)) + else: + toadd = {'Item': entrylist['Item'], 'Dependvalue': entrylist['Dependvalue'], + 'Compare': entrylist['Compare'], 'Zone': entrylist['Zone'], + 'Function': entrylist['Function'], 'Group': entrylist['Group']} + if not querycommand == '' and self._functions[dependzone][command][4].find('*') >= 0: + instance['Query'] = commandlist + try: + if toadd not in dependencies['Slave_query'][dependzone][commandlist]: + dependencies['Slave_query'][dependzone][commandlist].append(toadd) + self.logger.log(VERBOSE2, + "Updating Dependencies {}: Adding {} to {} in {}".format( + self._name, commandlist, dependingfunction, + dependzone)) + except Exception: + dependencies['Slave_query'][dependzone].update({commandlist: [toadd]}) + self.logger.log(VERBOSE2, + "Updating Dependencies {}: Creating {} for {} in {}".format( + self._name, commandlist, dependingfunction, + dependzone)) + done = True + # break + if done is True: + break + pass + return dependencies + + def _dependstage1(self, dependson_list, problems): + for zone in self._items.keys(): + for entry in self._items[zone]: + try: + depend = self._items[zone][entry]['Master'] + if depend is not None: + dependson_list[zone].update({entry: depend}) + except Exception: + pass + for zone in dependson_list: + for entry in dependson_list[zone]: + for count, entrylist in enumerate(dependson_list[zone][entry]): + sub = dependson_list[zone][entry][count].get('Item') + # self.logger.log(VERBOSE2, "Initializing {}: List {}, Entry {}, {}.".format(self._name, entrylist, entry, sub)) + try: + itemzone = dependson_list[zone][entry][count].get('Zone') + dependson_list[zone][entry][count].update({'Item': self._items[itemzone][sub].get('Item')}) + dependson_list[zone][entry][count].update({'Function': sub}) + self.logger.log(VERBOSE2, + "Initializing {}: Updated Dependon entry for {} with entry {}.".format( + self._name, sub, entrylist)) + except Exception as err: + if sub == 'init': + problems[zone].append("{}=init".format(entry)) + dependson_list[zone][entry][count].update({'Item': None}) + dependson_list[zone][entry][count].update({'Function': sub}) + self.logger.log(VERBOSE2, + "Initializing {}: Item with function {} is set to init. Problems: {}".format( + self._name, sub, problems)) + else: + problems[zone].append(sub) + self.logger.error( + "Initializing {}: Item with function {} for dependency does not exist. Entry: {}, Error: {}".format( + self._name, sub, entry, err)) + self._items[zone][entry]['Master'] = dependson_list[zone][entry] + return dependson_list, problems + + def _dependstage2(self, dependson_list, problems): + for zone in dependson_list: + for entry in dependson_list[zone]: + for count, _ in enumerate(dependson_list[zone][entry]): + if entry not in problems[zone] and '{}=init'.format(entry) not in problems[zone]: + item = self._items[zone][entry]['Item'] + try: + self._items[dependson_list[zone][entry][count]['Zone']][ + dependson_list[zone][entry][count]['Function']]['Slave'].append( + {'Function': entry, 'Item': item, + 'Compare': dependson_list[zone][entry][count]['Compare'], + 'Zone': zone, + 'Group': dependson_list[zone][entry][count]['Group'], + 'Dependvalue': dependson_list[zone][entry][count]['Dependvalue']}) + except Exception: + self._items[dependson_list[zone][entry][count]['Zone']][ + dependson_list[zone][entry][count]['Function']].update( + {'Slave': + [{'Function': entry, + 'Item': item, + 'Compare': dependson_list[zone][entry][count]['Compare'], + 'Zone': zone, + 'Dependvalue': dependson_list[zone][entry][count]['Dependvalue'], + 'Group': dependson_list[zone][entry][count]['Group']}]}) + + def _dependstage3(self, dependson_list, problems, finaldepend): + for zone in dependson_list: + for entry in dependson_list[zone]: + for count, _ in enumerate(dependson_list[zone][entry]): + if entry not in problems[zone] and '{}=init'.format(entry) not in problems[zone]: + dependzone = dependson_list[zone][entry][count].get('Zone') + item = dependson_list[zone][entry][count].get('Item') + try: + finaldepend['Slave_function'][zone][entry].append( + {'Item': item, + 'Dependvalue': dependson_list[zone][entry][count].get('Dependvalue'), + 'Compare': dependson_list[zone][entry][count].get('Compare'), + 'Zone': dependson_list[zone][entry][count].get('Zone'), + 'Group': dependson_list[zone][entry][count].get('Group'), + 'Function': dependson_list[zone][entry][count].get('Function')}) + except Exception: + finaldepend['Slave_function'][zone].update( + {entry: + [{'Item': item, + 'Dependvalue': dependson_list[zone][entry][count].get('Dependvalue'), + 'Compare': dependson_list[zone][entry][count].get('Compare'), + 'Zone': dependson_list[zone][entry][count].get('Zone'), + 'Group': dependson_list[zone][entry][count].get('Group'), + 'Function': dependson_list[zone][entry][count].get('Function')}]}) + + try: + finaldepend['Slave_item'][zone][self._items[zone][entry].get('Item').id()].append( + {'Item': item, + 'Dependvalue': dependson_list[zone][entry][count].get('Dependvalue'), + 'Compare': dependson_list[zone][entry][count].get('Compare'), + 'Zone': dependson_list[zone][entry][count].get('Zone'), + 'Group': dependson_list[zone][entry][count].get('Group'), + 'Function': dependson_list[zone][entry][count].get('Function')}) + except Exception: + finaldepend['Slave_item'][zone].update( + {self._items[zone][entry].get('Item').id(): + [{'Item': item, + 'Dependvalue': dependson_list[zone][entry][count].get('Dependvalue'), + 'Compare': dependson_list[zone][entry][count].get('Compare'), + 'Zone': dependson_list[zone][entry][count].get('Zone'), + 'Group': dependson_list[zone][entry][count].get('Group'), + 'Function': dependson_list[zone][entry][count].get('Function')}]}) + + try: + finaldepend['Master_item'][dependzone][ + self._items[dependzone][dependson_list[zone][entry][count]['Function']].get( + 'Item').id()].append( + {'Item': self._items[zone][entry].get('Item'), + 'Function': entry, + 'Compare': dependson_list[zone][entry][count].get('Compare'), + 'Zone': zone, + 'Group': dependson_list[zone][entry][count].get('Group'), + 'Dependvalue': dependson_list[zone][entry][count].get('Dependvalue')}) + except Exception: + finaldepend['Master_item'][dependzone].update( + {self._items[dependzone][dependson_list[zone][entry][count]['Function']].get( + 'Item').id(): + [{'Item': self._items[zone][entry].get('Item'), + 'Function': entry, + 'Compare': dependson_list[zone][entry][count].get('Compare'), + 'Zone': zone, + 'Group': dependson_list[zone][entry][count].get('Group'), + 'Dependvalue': dependson_list[zone][entry][count].get('Dependvalue')}]}) + try: + finaldepend['Master_function'][dependzone][ + dependson_list[zone][entry][count]['Function']].append( + {'Item': self._items[zone][entry].get('Item'), + 'Function': entry, + 'Compare': dependson_list[zone][entry][count].get('Compare'), + 'Zone': zone, + 'Group': dependson_list[zone][entry][count].get('Group'), + 'Dependvalue': dependson_list[zone][entry][count].get('Dependvalue')}) + except Exception: + finaldepend['Master_function'][dependzone].update( + {dependson_list[zone][entry][count]['Function']: + [{'Item': self._items[zone][entry].get('Item'), + 'Function': entry, + 'Compare': dependson_list[zone][entry][count].get('Compare'), + 'Zone': zone, + 'Group': dependson_list[zone][entry][count].get('Group'), + 'Dependvalue': dependson_list[zone][entry][count].get('Dependvalue')}]}) + return finaldepend + + def _dependstage4(self, dependson_list, problems, finaldepend): + for zone in dependson_list: + for entry in dependson_list[zone]: + for count, _ in enumerate(dependson_list[zone][entry]): + if '{}=init'.format(entry) in problems[zone]: + dependzone = dependson_list[zone][entry][count].get('Zone') + try: + finaldepend['Master_function'][dependzone][ + dependson_list[zone][entry][count]['Function']].append( + {'Item': self._items[zone][entry].get('Item'), + 'Function': entry, + 'Compare': dependson_list[zone][entry][count].get('Compare'), + 'Zone': zone, + 'Group': dependson_list[zone][entry][count].get('Group'), + 'Dependvalue': dependson_list[zone][entry][count].get('Dependvalue')}) + except Exception: + finaldepend['Master_function'][dependzone].update( + {dependson_list[zone][entry][count]['Function']: + [{'Item': self._items[zone][entry].get('Item'), + 'Function': entry, + 'Compare': dependson_list[zone][entry][count].get('Compare'), + 'Zone': zone, + 'Group': dependson_list[zone][entry][count].get('Group'), + 'Dependvalue': dependson_list[zone][entry][count].get('Dependvalue')}]}) + return finaldepend + + def process_items(self): + if 'statusupdate' not in self._items['zone0'].keys(): + self._items['zone0']['statusupdate'] = {'Item': ['self._statusupdate'], 'Value': False} + self.logger.debug("Initializing {}: No statusupdate Item set, creating dummy item.".format(self._name)) + dependson_list = {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}} + finaldepend = {'Slave_function': {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}}, + 'Slave_item': {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}}, + 'Slave_query': {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}}, + 'Master_function': {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}}, + 'Master_item': {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}}} + problems = {'zone0': [], 'zone1': [], 'zone2': [], 'zone3': [], 'zone4': []} + + dependson_list, problems = self._dependstage1(dependson_list, problems) + self._dependstage2(dependson_list, problems) + finaldepend = self._dependstage3(dependson_list, problems, finaldepend) + finaldepend = self._dependstage4(dependson_list, problems, finaldepend) + + return self._items, finaldepend + + def create_querycommands(self): + length = 0 + try: + self._query_zonecommands['zone0'].clear() + self._query_zonecommands['zone1'].clear() + self._query_zonecommands['zone2'].clear() + self._query_zonecommands['zone3'].clear() + self._query_zonecommands['zone4'].clear() + self._query_zonecommands = {'zone0': [], 'zone1': [], 'zone2': [], 'zone3': [], 'zone4': []} + self._query_commands.clear() + self.logger.debug( + "Initializing {}: Starting to create query commands. Query Commands: {}, Query Zone: {}".format( + self._name, self._query_commands, self._query_zonecommands)) + displaycommand = '' + for zone in range(0, self._number_of_zones + 1): + alreadydone = [] + for command in self._functions['zone{}'.format(zone)]: + try: + querycommand = self._functions['zone{}'.format(zone)][command][3] + valuetype = self._functions['zone{}'.format(zone)][command][9] + responselist = [] + splitresponse = self._functions['zone{}'.format(zone)][command][4].split("|") + for splitted in splitresponse: + valuelength = splitted.count('*') + if valuelength > 0 or 'R' in self._functions['zone{}'.format(zone)][command][5]: + toadd = splitted.strip() + toadd = re.sub('[?]', '*', toadd) if splitted.count('?') == 1 and splitted.count('*') == 0 else toadd + responselist.append('{},{},{}'.format(toadd, valuetype, valuelength)) + responsecommand = "|".join(responselist) + commandlist = '{},{},{}'.format(querycommand, querycommand, responsecommand) + try: + if command.split(' ')[1] in ['on', 'off', 'increase', 'decrease']: + for x, already in enumerate(self._query_commands): + if already.split(',')[0] == querycommand: + alreadylist = ','.join(already.split(',')[2:]).split('|') + responses = [re.sub('[*]', '', x.split(',')[0]) for x in alreadylist] + for resp in responselist: + resp_split = re.sub('[*]', '', resp.split(',')[0]) + cond1 = resp_split in responses + cond2_1 = set(resp.split(',')[1:-1]) + cond2_2 = set(already.split('|')[0].split(',')[3:-1]) + cond2 = cond2_1 == cond2_2 + self.logger.log(VERBOSE2, "Updating Dependencies {}: Querycommand {} for zone {}" + " already in list. Testing -{}- against the responses {}." + " Testing type {} against {}".format( + self._name, querycommand, zone, resp_split, + responses, cond2_1, cond2_2)) + if resp not in alreadylist and cond1 and cond2: + self.logger.log(VERBOSE2, "Initializing {}: Adding {} to {}.".format( + self._name, resp, alreadylist)) + self._query_commands[x] = already + '|' + resp + idx = self._query_zonecommands['zone{}'.format(zone)].index(already) + self._query_zonecommands['zone{}'.format(zone)][idx] = already + '|' + resp + if commandlist not in alreadydone: + alreadydone.append(commandlist) + elif cond1 and cond2: + if commandlist not in alreadydone: + alreadydone.append(commandlist) + self.logger.log(VERBOSE2, "Initializing {}: Skipping {}.".format( + self._name, commandlist)) + except Exception: + pass + if commandlist in alreadydone: + self.logger.log(VERBOSE2, "Initializing {}: Commandlist {} is alreadydone: {}, skipping.".format( + self._name, commandlist, alreadydone)) + else: + cond1 = commandlist not in self._query_zonecommands['zone{}'.format(zone)] + cond2 = not responsecommand == '' and not responsecommand == ' ' and not responsecommand == 'none' + cond3 = not querycommand == '' + cond4 = not self._functions['zone{}'.format(zone)][command][4] in self._ignoreresponse + cond5 = not self._functions['zone{}'.format(zone)][command][4] in self._special_commands['Display']['Command'] + if cond1 and cond2 and cond3 and cond4: + if cond5: + self._query_zonecommands['zone{}'.format(zone)].append(commandlist) + self.logger.log(VERBOSE1, "Initializing {}: Added Query Command for zone {}: {}".format( + self._name, zone, commandlist)) + else: + displaycommand = commandlist + self.logger.debug( + "Initializing {}: Displaycommand: {}".format(self._name, displaycommand)) + cond1 = commandlist not in self._query_commands + if cond1 and cond2 and cond3 and cond4: + if cond5: + self._query_commands.append(commandlist) + self.logger.log(VERBOSE1, + "Initializing {}: Added general Query Command: {}.".format(self._name, + commandlist)) + else: + displaycommand = '{},{},{}'.format(querycommand, querycommand, responsecommand) + self.logger.log(VERBOSE1, "Initializing {}: Displaycommand: {}".format(self._name, + displaycommand)) + except Exception as err: + self.logger.error( + "Initializing {}: Problems adding query commands for command {}. Error: {}".format( + self._name, command, err)) + length += len(self._query_zonecommands['zone{}'.format(zone)]) + if not displaycommand == '': + self._query_commands.append(displaycommand) + length += 1 + except Exception as err: + self.logger.error( + "Initializing {}: Problems searching for query commands. Error: {}".format(self._name, err)) + finally: + self.logger.info( + "Initializing {}: Created query commands, including {} entries.".format(self._name, length)) + return self._query_commands, self._query_zonecommands + + def create_powercommands(self): + try: + self._power_commands.clear() + self.logger.debug( + "Initializing {}: Starting to create Powercommands: {}".format( + self._name, self._power_commands)) + for zone in range(0, self._number_of_zones + 1): + for command in self._functions['zone{}'.format(zone)]: + try: + if command.startswith('power on'): + valuetype = self._functions['zone{}'.format(zone)][command][9] + responselist = [] + splitresponse = self._functions['zone{}'.format(zone)][command][4].split("|") + for response in splitresponse: + valuelength = response.count('*') + if valuelength > 0 or 'R' in self._functions['zone{}'.format(zone)][command][5]: + value = response.strip() + value = re.sub('[?]', '*', value) if response.count('?') == 1 and response.count('*') == 0 else value + if '**' in response: + value = re.sub('\*\*', 'ON', response) + else: + if self._functions['zone{}'.format(zone)][command][6] == 'yes': + value = re.sub('[*]', '0', response) + else: + value = re.sub('[*]', '1', response) + responselist.append('{},{},{}'.format(value, valuetype, valuelength)) + responsecommand = "|".join(responselist) + combined = '{},{},{}'.format(self._functions['zone{}'.format(zone)][command][2], + self._functions['zone{}'.format(zone)][command][3], responsecommand) + self._power_commands.append(combined) + except Exception as err: + self.logger.warning( + "Initializing {}: Problems searching Powercommands for {} in zone {}. Error: {}".format( + self._name, command, zone, err)) + except Exception as err: + self.logger.warning("Initializing {}: Problems creating Powercommands. Error: {}".format(self._name, err)) + finally: + self.logger.info("Initializing {}: Created Powercommands, including {} entries.".format(self._name, len( + self._power_commands))) + + return self._power_commands + + def create_responsecommands(self): + try: + self._response_commands.clear() + self._special_commands.clear() + self.logger.debug( + "Initializing {}: Starting to create response commands. Response Commands: {}".format( + self._name, self._response_commands)) + for zone in range(0, self._number_of_zones + 1): + for command in self._functions['zone{}'.format(zone)]: + if not command == 'init' and not command == 'statusupdate': + try: + response_to_split = self._functions['zone{}'.format(zone)][command][4].split("|") + for response in response_to_split: + if not response: + self.logger.log(VERBOSE2, "Initializing {}: No response set for {}".format( + self._name, command)) + break + origresponse = response + try: + specialparse = self._functions['zone{}'.format(zone)][command][10] + except Exception: + specialparse = '' + valuelength = response.count('*') + commandlength = 100 if response.find('?{str}') >= 0 else len(response) + response = re.sub('\?\{str\}', '?', response) if response.find('?{str}') >= 0 else response + cond1 = response.count('?') == 1 and response.count('*') == 0 + cond2 = response.count('*') == 1 + cond3 = 'str' in self._functions['zone{}'.format(zone)][command][9].split(',') + if (cond1 or cond2) and cond3: + valuelength = 100 + response = re.sub('\*\{str\}', '*', response) + cond1 = response.count('?') == 1 and response.count('*') == 0 + response = re.sub('[?]', '*', response) if cond1 else response + position = response.index('*') if response.find('*') >= 0 else 0 + response = re.sub('[*]', '', response.split('*')[0]) + inverse = self._functions['zone{}'.format(zone)][command][6] + expectedtype = self._functions['zone{}'.format(zone)][command][9] + device_function = command.split(" ")[0] + try: + functiontype = command.split(" ")[1] + except Exception: + functiontype = '' + item = self._items['zone{}'.format(zone)][device_function]['Item'] + self.logger.log(VERBOSE2, + "Initializing {}: Response: {}, Original {}; Function: {}, Item: {}," + " Type: {}, Valuelength: {}, Commandlength: {}".format( + self._name, response, origresponse, device_function, item, + expectedtype, valuelength, commandlength)) + if self._functions['zone{}'.format(zone)][command][5].lower() in ['r', 'rw']: + if device_function == 'display': + self._special_commands['Display'] = {'Command': response, 'Ignore': 1, 'Item': item} \ + if response in self._ignoreresponse and '' not in self._ignoreresponse \ + else {'Command': response, 'Ignore': 0, 'Item': item} + elif device_function == 'input': + if 'Input' not in self._special_commands: + self._special_commands['Input'] = {'Command': [response], 'Ignore': [0], + 'Item': [item]} + else: + self._special_commands['Input']['Command'].append(response) + self._special_commands['Input']['Item'].append(item) + self._special_commands['Input']['Ignore'].append(0) + self.logger.log(VERBOSE2, "Initializing {}: Found Input Command and added it" + " to display commands.".format(self._name)) + elif device_function == 'title' or device_function == 'station' or device_function == 'genre': + if 'Nowplaying' not in self._special_commands: + self._special_commands['Nowplaying'] = {'Command': [response], 'Item': item} + else: + self._special_commands['Nowplaying']['Command'].append(response) + elif device_function == 'speakers': + if 'Speakers' not in self._special_commands: + self._special_commands['Speakers'] = {'Command': [response], 'Item': item} + else: + self._special_commands['Speakers']['Command'].append(response) + + try: + toadd = len(self._response_commands[response]) + for entry in self._response_commands[response]: + cond1 = item not in entry and expectedtype in entry + cond2 = valuelength == entry[0] and device_function == entry[4] + cond3 = expectedtype not in entry + cond4 = not valuelength == entry[0] + cond5 = not device_function == entry[4] + if cond1 and cond2: + self.logger.log(VERBOSE1, "Initializing {}: Appending Item to response" + " {} for function {} with response {}.".format( + self._name, response, device_function, entry)) + entry[3] = [entry[3]] + entry[3].append(item[0]) + elif cond3 or cond4 or cond5: + toadd -= 1 + else: + self.logger.log(VERBOSE1, "Initializing {}: Ignoring response {} for function {}" + " because it is already in list.".format( + self._name, response, device_function, entry)) + if toadd < len(self._response_commands[response]): + self.logger.log(VERBOSE1, "Initializing {}: Adding additional list to function {}" + " for response {} with value {}.".format( + self._name, device_function, response, self._response_commands[response])) + self._response_commands[response].append([ + valuelength, commandlength, position, item, device_function, + 'zone{}'.format(zone), inverse, expectedtype, functiontype, + specialparse]) + + except Exception as err: + self.logger.log(VERBOSE2, + "Initializing {}: Creating response command for: {}. Message: {}".format( + self._name, response, err)) + self._response_commands[response] = [[ + valuelength, commandlength, position, item, device_function, + 'zone{}'.format(zone), + inverse, expectedtype, functiontype, specialparse]] + self._response_commands[response] = sorted(self._response_commands[response], + key=lambda x: x[0], reverse=True) + except Exception as err: + self.logger.warning( + "Initializing {}: Problems searching functions for {} in zone {}. Either it is not in" + " the textfile or wrong instance name defined. Error: {}".format( + self._name, command, zone, err)) + except Exception as err: + self.logger.error("Initializing {}: Problems creating response commands. Error: {}".format(self._name, err)) + finally: + self._special_commands['Display'] = {'Command': '', 'Ignore': 1, 'Item': ''} \ + if 'Display' not in self._special_commands else self._special_commands['Display'] + self._special_commands['Input'] = {'Command': '', 'Ignore': [1], 'Item': ''} \ + if 'Input' not in self._special_commands else self._special_commands['Input'] + self._special_commands['Nowplaying'] = {'Command': '', 'Item': ''} \ + if 'Nowplaying' not in self._special_commands else self._special_commands['Nowplaying'] + self._special_commands['Speakers'] = {'Command': '', 'Item': ''} \ + if 'Speakers' not in self._special_commands else self._special_commands['Speakers'] + self.logger.debug("Initializing {}: Special commands for solving Display issues: {}".format( + self._name, self._special_commands)) + self.logger.info("Initializing {}: Created response commands, including {} entries.".format( + self._name, len(self._response_commands))) + return self._response_commands, self._special_commands + + def _read_parsefile(self, device_function): + resulting = {'update': {}, 'parse': {}} + try: + self.logger.debug( + "Initializing {}: Starting to read translation file {}. ".format(self._name, device_function)) + filename = '{}/translations/{}.txt'.format(os.path.abspath(os.path.dirname(__file__)), device_function) + with open(filename, encoding='utf-8') as parsing: + comment = 0 + for line in parsing: + line = re.sub('[\\n\\r]', '', line) + line = re.sub('; ', ';', line) + line = re.sub(' ;', ';', line) + cond1 = line == "'''" and comment == 0 + cond2 = line == "'''" and comment == 1 + cond3 = (line == "'''" or line == '' or line.startswith('#') or line.startswith('CODE;')) + comment += 1 if cond1 else -1 if cond2 else 0 + code = '' + if comment == 0 and not cond1 and not cond2 and not cond3: + code = line.split(";")[0] + if not code == '': + translation = line.split(";")[1] + try: + code = code.lower() + except Exception: + pass + try: + origtranslation = translation + translation = translation.lower() + except Exception: + origtranslation = translation + resulting['update'].update({translation: code}) + resulting['parse'].update({code: origtranslation}) + except Exception as err: + self.logger.error("Initializing {}: Problems reading Special Parse file: {}".format(self._name, err)) + finally: + return resulting + + def read_commandfile(self): + try: + self._functions.clear() + self._functions = {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}} + self._specialparse.clear() + self._specialparse = {} + self.logger.debug("Initializing {}: Starting to read file {}. Functions: {}".format( + self._name, self._model, self._functions)) + filename = '{}/{}.txt'.format(os.path.abspath(os.path.dirname(__file__)), self._model) + + with open(filename, encoding='utf-8') as commands: + zones = [0] + comment = 0 + for line in commands: + line = re.sub('[\\n\\r]', '', line) + line = re.sub('; ', ';', line) + line = re.sub(' ;', ';', line) + cond1 = line == "'''" and comment == 0 + cond2 = line == "'''" and comment == 1 + cond3 = (line == "'''" or line == '' or line.startswith('#') or line.startswith('ZONE;')) + comment += 1 if cond1 else -1 if cond2 else 0 + device_function = '' + itemkeys = [] + itemtest = '' + row = [None, None] + origfunction = None + if comment == 0 and not cond3: + row = line.split(";") + row[0] = '0' if row[0] == '' else row[0] + origfunction = row[1] + row[1:3] = [''.join(row[1:3])] if row[2] == '' else [' '.join(row[1:3])] + device_function = row[1] + itemtest = re.sub(' set| on| off| increase| decrease| open| close| query', '', device_function) + for i in range(0, 10): + try: + row[i] + except IndexError: + cond1 = (i == 9 and ("set" in device_function or + "increase" in device_function or + "decrease" in device_function)) + cond2 = (i == 9 and ("open" in device_function or + "close" in device_function or + "on" in device_function or + "off" in device_function)) + row.append('RW' if i == 5 + else 'no' if i == 6 + else 'int,float' if cond1 + else 'str' if (i == 9 and "display" in device_function) + else 'bool' if cond2 + else '') + cond1 = ("increase" in device_function or "decrease" in device_function) + if i == 9 and cond1: + row[5] = row[5].replace('*', '') + row[9] = row[9].replace('string', 'str') + row[9] = row[9].replace('num', 'int,float') + row[9] = row[9].replace('|', ',') + row[9] = 'empty' if (row[4].count('*') == 0 and row[4].count('?') == 0 and row[9] == '') \ + else 'bool,int,str' if row[9] == '' else row[9] + row[2] = row[3] if not row[2] else row[2] + try: + itemkeys = self._items['zone{}'.format(row[0])].keys() + except Exception: + itemkeys = [] + if device_function == "FUNCTION" or device_function == '' or device_function == "FUNCTION FUNCTIONTYPE": + pass + elif itemtest in itemkeys: + device_function = device_function.replace('open', 'on') + device_function = device_function.replace('close', 'off') + row[1] = origfunction + rowzone = '0' if row[0] == '' else row[0] + self._functions['zone{}'.format(rowzone)][device_function] = row + zones.append(int(row[0]) if not int(row[0]) in zones else 0) + try: + self._specialparse[row[10]] = self._read_parsefile(row[10]) + except Exception: + pass + else: + self.logger.warning( + "Initializing {}: Function {} for zone {} not used by any item. Re-visit items and config file!".format( + self._name, device_function, row[0])) + self._number_of_zones = max(zones) + self.logger.debug("Initializing {}: Number of zones: {}".format(self._name, self._number_of_zones)) + except Exception as err: + self.logger.error("Initializing {}: Problems loading command file. Error: {}".format(self._name, err)) + finally: + self._functions['zone0']['statusupdate'] = ['0', 'statusupdate', '', '', '', 'W', '', '', '', 'bool'] + self._functions['zone0']['init'] = ['0', 'init', '', '', '', 'W', '', '', '', 'bool'] + self._functions['zone1']['init'] = ['0', 'init', '', '', '', 'W', '', '', '', 'bool'] + self._functions['zone2']['init'] = ['0', 'init', '', '', '', 'W', '', '', '', 'bool'] + self._functions['zone3']['init'] = ['0', 'init', '', '', '', 'W', '', '', '', 'bool'] + self._functions['zone4']['init'] = ['0', 'init', '', '', '', 'W', '', '', '', 'bool'] + self.logger.info( + "Initializing {}: Created functions list, including entries for {} zones.".format(self._name, + self._number_of_zones)) + self.logger.log(VERBOSE1, "Initializing {}: Finishing reading file. ".format(self._name)) + return self._functions, self._number_of_zones, self._specialparse + + +class ProcessVariables(Init): + def __init__(self, value, name): + self._value = value + self._name = name + self.logger = logging.getLogger(__name__) + + def process_rs232(self): + baud = serial_timeout = None + try: + rs232 = re.sub('[ ]', '', self._value[0]) + rs232 = None if rs232 == 'None' or rs232 == '' else rs232 + self.logger.debug("Initializing Serial {}: Serial port is {}.".format(self._name, rs232)) + except Exception as err: + rs232 = None + self.logger.warning( + "Initializing Serial {}: Serial Port is {}. Error: {}.".format(self._name, baud, err)) + if rs232 is not None: + try: + baud = int(self._value[1]) + self.logger.debug("Initializing Serial {}: Baud rate is {}.".format(self._name, baud)) + except Exception as err: + baud = 9600 + self.logger.debug( + "Initializing Serial {}: Using standard baud rate {} because: {}.".format(self._name, baud, err)) + try: + serial_timeout = float(self._value[2]) + self.logger.debug("Initializing Serial {}: Timeout is {}.".format(self._name, serial_timeout)) + except Exception as err: + serial_timeout = 0.1 + self.logger.debug( + "Initializing Serial {}: Using standard timeout {}. Because: {}.".format(self._name, + serial_timeout, err)) + return rs232, baud, serial_timeout + + def process_tcp(self): + port = tcp_timeout = None + try: + tcp = re.sub('[ ]', '', self._value[0]) + tcp = None if tcp == 'None' or tcp == '' or tcp == '0.0.0.0' else tcp + self.logger.debug("Initializing TCP {}: IP is {}.".format(self._name, tcp)) + except Exception as err: + tcp = None + self.logger.warning("Initializing TCP {}: Problem setting IP: {}.".format(self._name, err)) + if tcp is not None: + try: + port = int(self._value[1]) + self.logger.debug("Initializing TCP {}: Port is {}.".format(self._name, port)) + except Exception as err: + port = None + self.logger.warning("Initializing TCP {}: Port is {} because: {}.".format(self._name, port, err)) + try: + tcp_timeout = int(self._value[2]) + self.logger.debug("Initializing TCP {}: Timeoout is {}.".format(self._name, tcp_timeout)) + except Exception as err: + tcp_timeout = 1 + self.logger.warning( + "Initializing TCP {}: Timeout is set to standard (1) because: {}.".format(self._name, err)) + return tcp, port, tcp_timeout + + def process_dependson(self): + depend = None + try: + depend = re.sub('[ ]', '', self._value[0]) + depend = None if depend == 'None' or depend == '' else depend + dependson_value = True if re.sub('[ ]', '', str(self._value[1])).lower() in ['1', 'yes', 'true', 'on'] \ + else False if re.sub('[ ]', '', str(self._value[1])).lower() in ['0', 'no', 'false', 'off'] \ + else None + self.logger.debug( + "Initializing {}: Dependson Item: {}. Value: {}".format(self._name, depend, dependson_value)) + except Exception: + dependson_value = True if depend is not None else None + depend0_power0 = True if re.sub('[ ]', '', str(self._value[2])).lower() in ['1', 'yes', 'true', 'on'] and depend else False + depend0_volume0 = True if re.sub('[ ]', '', str(self._value[3])).lower() in ['1', 'yes', 'true', 'on'] and depend else False + self.logger.debug( + "Initializing {}: Resetting volume after dependson is off: {}. Resetting power: {}.".format( + self._name, depend0_volume0, depend0_power0)) + return depend, dependson_value, depend0_power0, depend0_volume0 + + def process_responsebuffer(self): + buffer = True if str(self._value).lower() in ['1', 'yes', 'true', 'on'] \ + else False if str(self._value).lower() in ['0', 'no', 'false', 'off'] \ + else abs(int(self._value)) * -1 + return buffer + + def process_resetonerror(self): + reset = True if str(self._value).lower() in ['1', 'yes', 'true', 'on'] else False + return reset + + def process_statusquery(self): + statusquery = True if str(self._value).lower() in ['1', 'yes', 'true', 'on'] else False + return statusquery + + def process_responses(self): + ignoreresponse = self._ignoreresponse = re.sub(', ', ',', self._value[0]).split(",") + errorresponse = re.sub(', ', ',', self._value[1]).split(",") + force_buffer = re.sub(', ', ',', self._value[2]).split(",") + ignoredisplay = re.sub(', ', ',', self._value[3]).split(",") + newignore = [] + for ignore in ignoredisplay: + newignore.append(re.sub('^0', '', ignore)) + ignoredisplay = newignore + self.logger.debug("Initializing {}: Ignore Display: {}".format(self._name, ignoredisplay)) + return ignoreresponse, errorresponse, force_buffer, ignoredisplay + + def process_update_exclude(self): + exclude = re.sub(', ', ',', self._value).split(",") + self.logger.debug( + "Initializing {}: Special Settings: Exclude updates by {}".format(self._name, exclude)) + return exclude diff --git a/avdevice/_pv_1_3_6/Denon_Items.yaml b/avdevice/_pv_1_3_6/Denon_Items.yaml new file mode 100755 index 000000000..127a3d154 --- /dev/null +++ b/avdevice/_pv_1_3_6/Denon_Items.yaml @@ -0,0 +1,640 @@ +%YAML 1.1 +--- +Denon: + type: foo + + Reload: + visu_acl: rw + type: bool + cache: 'false' + enforce_updates: 'yes' + avdevice@denon: reload + + Powerall: + type: bool + visu_acl: rw + avdevice_zone0@denon: power + avdevice_zone1_depend@denon: init + + Update: + type: bool + visu_acl: rw + avdevice_zone0@denon: statusupdate + enforce_updates: 'yes' + + Running: + type: bool + visu_acl: ro + enforce_updates: 'yes' + value: 0 + + Power: + type: bool + visu_acl: rw + avdevice_zone1@denon: power + avdevice_zone1_depend@denon: init + influxdb: 'yes' + database@nas: 'yes' + + Mute: + type: bool + visu_acl: rw + avdevice_zone1@denon: mute + avdevice_zone1_depend@denon: power + + VolumeFL: + type: num + visu_acl: rw + avdevice_zone1@denon: volumefl + avdevice_zone1_depend@denon: power + cache: 'True' + + VolumeFLUp: + type: bool + visu_acl: rw + avdevice_zone1@denon: volumefl+ + avdevice_zone1_depend@denon: power + enforce_updates: 'yes' + + VolumeFLDown: + type: bool + visu_acl: rw + avdevice_zone1@denon: volumefl- + avdevice_zone1_depend@denon: power + enforce_updates: 'yes' + + VolumeFR: + type: num + visu_acl: rw + avdevice_zone1@denon: volumefr + avdevice_zone1_depend@denon: power + cache: 'True' + + VolumeFRUp: + type: bool + visu_acl: rw + avdevice_zone1@denon: volumefr+ + avdevice_zone1_depend@denon: power + enforce_updates: 'yes' + + VolumeFRDown: + type: bool + visu_acl: rw + avdevice_zone1@denon: volumefr- + avdevice_zone1_depend@denon: power + enforce_updates: 'yes' + + VolumeSR: + type: num + visu_acl: rw + avdevice_zone1@denon: volumesr + avdevice_zone1_depend@denon: power + cache: 'True' + + VolumeSRUp: + type: bool + visu_acl: rw + avdevice_zone1@denon: volumesr+ + avdevice_zone1_depend@denon: power + enforce_updates: 'yes' + + VolumeSRDown: + type: bool + visu_acl: rw + avdevice_zone1@denon: volumesr- + avdevice_zone1_depend@denon: power + enforce_updates: 'yes' + + VolumeSL: + type: num + visu_acl: rw + avdevice_zone1@denon: volumesl + avdevice_zone1_depend@denon: power + cache: 'True' + + VolumeSLUp: + type: bool + visu_acl: rw + avdevice_zone1@denon: volumesl+ + avdevice_zone1_depend@denon: power + enforce_updates: 'yes' + + VolumeSLDown: + type: bool + visu_acl: rw + avdevice_zone1@denon: volumesl- + avdevice_zone1_depend@denon: power + enforce_updates: 'yes' + + VolumeC: + type: num + visu_acl: rw + avdevice_zone1@denon: volumec + avdevice_zone1_depend@denon: power + cache: 'True' + + VolumeCUp: + type: bool + visu_acl: rw + avdevice_zone1@denon: volumec+ + avdevice_zone1_depend@denon: power + enforce_updates: 'yes' + + VolumeCDown: + type: bool + visu_acl: rw + avdevice_zone1@denon: volumec- + avdevice_zone1_depend@denon: power + enforce_updates: 'yes' + + Dynamicrange: + type: num + visu_acl: rw + avdevice_zone1@denon: dynamicrange + avdevice_zone1_depend@denon: power + + DynamicrangeUp: + type: num + visu_acl: rw + avdevice_zone1@denon: dynamicrange+ + avdevice_zone1_depend@denon: power + + DynamicrangeDown: + type: num + visu_acl: rw + avdevice_zone1@denon: dynamicrange- + avdevice_zone1_depend@denon: power + + Volume: + type: num + visu_acl: rw + avdevice_zone1@denon: volume + avdevice_zone1_depend@denon: power + cache: 'True' + + Fading: + type: num + + VolumeMax: + type: num + visu_acl: ro + avdevice_zone1@denon: volumemax + avdevice_zone1_depend@denon: power + + VolumeUp: + type: bool + visu_acl: rw + avdevice_zone1@denon: volume+ + avdevice_zone1_depend@denon: power + enforce_updates: 'yes' + knx_listen: 3/4/8 + knx_dpt: 1 + + VolumeDown: + type: bool + visu_acl: rw + avdevice_zone1@denon: volume- + avdevice_zone1_depend@denon: power + enforce_updates: 'yes' + knx_listen: 3/4/7 + knx_dpt: 1 + + VolumeLow: + type: bool + enforce_updates: 'yes' + visu_acl: rw + knx_listen: 3/4/9 + knx_dpt: 1 + avdevice_zone1@denon: volumelow + avdevice_zone1_depend@denon: power + + VolumeHigh: + type: bool + enforce_updates: 'yes' + visu_acl: rw + knx_listen: 3/4/10 + knx_dpt: 1 + avdevice_zone1@denon: volumehigh + avdevice_zone1_depend@denon: power + + Eco: + type: str + visu_acl: rw + avdevice_zone0@denon: eco + + Source: + type: str + visu_acl: rw + avdevice_zone1@denon: input + avdevice_zone1_depend@denon: power + + Musik: + type: bool + visu_acl: ro + eval: 1 if ((sh.Musik.OG.Denon.Source() == 'DVD' or sh.Musik.OG.Denon.Source() == 'CD' or sh.Musik.OG.Denon.Source() == 'NET') and sh.Musik.OG.Denon.Power()) else 0 + eval_trigger: + - Musik.OG.Denon.Source + - Musik.OG.Denon.Power + enforce_updates: 'yes' + + Mode: + type: str + visu_acl: rw + avdevice_zone1@denon: mode + avdevice_zone1_depend@denon: power + + Dialog: + type: num + visu_acl: rw + avdevice_zone1@denon: dialog + avdevice_zone1_depend@denon: power + enforce_updates: 'no' + + Dialogtoggle: + type: bool + visu_acl: rw + avdevice_zone1@denon: dialogtoggle + avdevice_zone1_depend@denon: power + + Subwoofer: + type: num + visu_acl: rw + avdevice_zone1@denon: subwoofer + avdevice_zone1_depend@denon: power + enforce_updates: 'no' + + Subwoofertoggle: + type: bool + visu_acl: rw + avdevice_zone1@denon: subwoofertoggle + avdevice_zone1_depend@denon: power + + CinemaEQ: + type: bool + visu_acl: rw + avdevice_zone1@denon: cinemaeq + avdevice_zone1_depend@denon: power + + Mainspeakers: + type: str + visu_acl: rw + avdevice_zone1@denon: mainspeakers + avdevice_zone1_depend@denon: power + + Sleep: + type: num + visu_acl: rw + avdevice_zone1@denon: sleep + avdevice_zone1_depend@denon: power + + Standby: + type: foo + visu_acl: rw + avdevice_zone1@denon: standby + avdevice_zone1_depend@denon: power + + Bass: + type: num + visu_acl: rw + avdevice_zone1@denon: bass + avdevice_zone1_depend@denon: tone + + BassUp: + type: num + visu_acl: rw + avdevice_zone1@denon: bass+ + enforce_updates: 'yes' + avdevice_zone1_depend@denon: tone + + BassDown: + type: num + visu_acl: rw + avdevice_zone1@denon: bass- + enforce_updates: 'yes' + avdevice_zone1_depend@denon: tone + + Tone: + type: bool + visu_acl: rw + avdevice_zone1@denon: tone + avdevice_zone1_depend@denon: power + + Trebble: + type: num + visu_acl: rw + avdevice_zone1@denon: trebble + avdevice_zone1_depend@denon: tone + + TrebbleUp: + type: num + visu_acl: rw + avdevice_zone1@denon: trebble+ + enforce_updates: 'yes' + avdevice_zone1_depend@denon: tone + + TrebbleDown: + type: num + visu_acl: rw + avdevice_zone1@denon: trebble- + enforce_updates: 'yes' + avdevice_zone1_depend@denon: tone + + Videoinput: + type: str + visu_acl: rw + avdevice_zone1@denon: videoinput + avdevice_zone1_depend@denon: power + + Audioinput: + type: str + visu_acl: rw + avdevice_zone1@denon: audioinput + avdevice_zone1_depend@denon: power + + Videoparams: + type: foo + + Aspectratio: + type: str + visu_acl: rw + avdevice_zone1@denon: aspectratio + avdevice_zone1_depend@denon: power + + Monitorout: + type: foo + visu_acl: rw + avdevice_zone1@denon: monitorout + avdevice_zone1_depend@denon: power + + Resolution: + type: str + visu_acl: rw + avdevice_zone1@denon: resolution + avdevice_zone1_depend@denon: power + + Audioout: + type: str + visu_acl: rw + avdevice_zone1@denon: audioout + avdevice_zone1_depend@denon: power + + Videoprocessing: + type: str + visu_acl: rw + avdevice_zone1@denon: videoprocessing + avdevice_zone1_depend@denon: power + + Stretch: + type: str + visu_acl: rw + avdevice_zone1@denon: stretch + avdevice_zone1_depend@denon: + - power, a + - aspectratio = NRM, b + + Display: + type: str + visu_acl: ro + avdevice_zone0@denon: display + avdevice_zone1_depend@denon: input = NET + avdevice_zone2_depend@denon: input = NET + + Title: + type: str + visu_acl: ro + avdevice_zone0@denon: title + avdevice_zone1_depend@denon: input = NET + avdevice_zone2_depend@denon: input = NET + + Station: + type: str + visu_acl: ro + avdevice_zone0@denon: station + avdevice_zone1_depend@denon: input = NET + avdevice_zone2_depend@denon: input = NET + + Genre: + type: str + visu_acl: ro + avdevice_zone0@denon: genre + avdevice_zone1_depend@denon: input = NET + avdevice_zone2_depend@denon: input = NET + + Power2: + type: bool + visu_acl: rw + avdevice_zone2@denon: power + avdevice_zone2_depend@denon: init + influxdb: 'yes' + database@nas: 'yes' + + Source2: + type: str + visu_acl: rw + avdevice_zone2@denon: input + avdevice_zone2_depend@denon: power + + Musik: + type: bool + visu_acl: ro + eval: 1 if ((sh.Musik.OG.Denon.Source2() == 'DVD' or sh.Musik.OG.Denon.Source2() == 'CD' or sh.Musik.OG.Denon.Source2() == 'NET') and sh.Musik.OG.Denon.Power2()) else 0 + eval_trigger: + - Musik.OG.Denon.Source2 + - Musik.OG.Denon.Power2 + + Mute2: + type: bool + visu_acl: rw + avdevice_zone2@denon: mute + avdevice_zone2_depend@denon: power + + Volume2: + type: num + visu_acl: rw + avdevice_zone2@denon: volume + avdevice_zone2_depend@denon: power + + Fading: + type: num + + VolumeUp2: + type: bool + visu_acl: rw + avdevice_zone2@denon: volume+ + avdevice_zone2_depend@denon: power + enforce_updates: 'yes' + knx_listen: 3/4/15 + knx_dpt: 1 + + VolumeDown2: + type: bool + visu_acl: rw + avdevice_zone2@denon: volume- + avdevice_zone2_depend@denon: power + enforce_updates: 'yes' + knx_listen: 3/4/14 + knx_dpt: 1 + + VolumeHigh2: + type: bool + visu_acl: rw + avdevice_zone2@denon: volumehigh + avdevice_zone2_depend@denon: power + enforce_updates: 'yes' + knx_listen: 3/4/17 + knx_dpt: 1 + + VolumeLow2: + type: bool + visu_acl: rw + avdevice_zone2@denon: volumelow + avdevice_zone2_depend@denon: power + enforce_updates: 'yes' + knx_listen: 3/4/16 + knx_dpt: 1 + + Sleep2: + type: num + visu_acl: rw + avdevice_zone2@denon: sleep + avdevice_zone2_depend@denon: power + + Standby2: + type: foo + visu_acl: rw + avdevice_zone2@denon: standby + avdevice_zone2_depend@denon: power + + Power3: + type: bool + visu_acl: rw + avdevice_zone3@denon: power + avdevice_zone3_depend@denon: init + influxdb: 'yes' + database@nas: 'yes' + + Source3: + type: str + visu_acl: rw + avdevice_zone3@denon: input + avdevice_zone3_depend@denon: power + + Musik: + type: bool + visu_acl: ro + eval: 1 if ((sh.Musik.OG.Denon.Source3() == 'DVD' or sh.Musik.OG.Denon.Source3() == 'CD' or sh.Musik.OG.Denon.Source3() == 'NET') and sh.Musik.OG.Denon.Power3()) else 0 + eval_trigger: + - Musik.OG.Denon.Source3 + - Musik.OG.Denon.Power3 + + Mute3: + type: bool + visu_acl: rw + avdevice_zone3@denon: mute + avdevice_zone3_depend@denon: power + enforce_updates: yes + + Volume3: + type: num + visu_acl: rw + avdevice_zone3@denon: volume + avdevice_zone3_depend@denon: power + + Fading: + type: num + + VolumeUp3: + type: bool + visu_acl: rw + avdevice_zone3@denon: volume+ + avdevice_zone3_depend@denon: power + enforce_updates: 'yes' + knx_listen: 3/4/19 + knx_dpt: 1 + + VolumeDown3: + type: bool + visu_acl: rw + avdevice_zone3@denon: volume- + avdevice_zone3_depend@denon: power + enforce_updates: 'yes' + knx_listen: 3/4/18 + knx_dpt: 1 + + VolumeHigh3: + type: bool + visu_acl: rw + avdevice_zone3@denon: volumehigh + avdevice_zone3_depend@denon: power + enforce_updates: 'yes' + knx_listen: 3/4/21 + knx_dpt: 1 + + VolumeLow3: + type: bool + visu_acl: rw + avdevice_zone3@denon: volumelow + avdevice_zone3_depend@denon: power + enforce_updates: 'yes' + knx_listen: 3/4/20 + knx_dpt: 1 + + Sleep3: + type: num + visu_acl: rw + avdevice_zone3@denon: sleep + avdevice_zone3_depend@denon: power + + Standby3: + type: foo + visu_acl: rw + avdevice_zone3@denon: standby + avdevice_zone3_depend@denon: power + + CursorUp: + type: bool + visu_acl: rw + avdevice@denon: up + enforce_updates: 'yes' + + CursorDown: + type: bool + visu_acl: rw + avdevice@denon: down + enforce_updates: 'yes' + + CursorLeft: + type: bool + visu_acl: rw + avdevice@denon: left + enforce_updates: 'yes' + + CursorRight: + type: bool + visu_acl: rw + avdevice@denon: right + enforce_updates: 'yes' + + CursorEnter: + type: bool + visu_acl: rw + avdevice@denon: enter + enforce_updates: 'yes' + + Firmware: + type: foo + visu_acl: rw + avdevice@denon: firmware + avdevice_zone1_depend@denon: power + + Info: + type: bool + visu_acl: rw + avdevice@denon: info + avdevice_zone1_depend@denon: power + + Menu: + type: bool + visu_acl: rw + avdevice@denon: menu + avdevice_zone1_depend@denon: power diff --git a/avdevice/_pv_1_3_6/Pioneer_Items.yaml b/avdevice/_pv_1_3_6/Pioneer_Items.yaml new file mode 100755 index 000000000..c65a6d15c --- /dev/null +++ b/avdevice/_pv_1_3_6/Pioneer_Items.yaml @@ -0,0 +1,305 @@ +%YAML 1.1 +--- +Pioneer: + type: foo + + Reload: + visu_acl: rw + type: bool + cache: 'false' + enforce_updates: 'yes' + avdevice@pioneer: reload + + Update: + type: bool + visu_acl: rw + avdevice_zone0@pioneer: statusupdate + enforce_updates: 'yes' + + Running: + type: bool + visu_acl: ro + enforce_updates: 'yes' + value: 0 + + Speakers: + type: num + visu_acl: rw + avdevice_zone1@pioneer: speakers + avdevice_zone1_depend@pioneer: power + + SpeakerA: + knx_init: 1/4/2 + knx_dpt: 1 + type: bool + visu_acl: rw + avdevice_zone1_speakers@pioneer: 1 + avdevice_zone1_depend@pioneer: power + name: Musik Bad + influxdb: 'yes' + database@nas: 'yes' + + SpeakerB: + knx_init: 1/4/1 + knx_dpt: 1 + type: bool + visu_acl: rw + avdevice_zone1_speakers@pioneer: 2 + avdevice_zone1_depend@pioneer: power + name: Musik Sauna + influxdb: 'yes' + database@nas: 'yes' + + Power: + type: bool + visu_acl: rw + avdevice_zone1@pioneer: power + avdevice_zone1_depend@pioneer: init + influxdb: 'yes' + database@nas: 'yes' + + Mute: + type: bool + visu_acl: rw + avdevice_zone1@pioneer: mute + avdevice_zone1_depend@pioneer: power + + Volume: + type: num + visu_acl: rw + avdevice_zone1@pioneer: volume + avdevice_zone1_depend@pioneer: power + cache: 'True' + + Fading: + type: num + + VolumeUp: + type: bool + visu_acl: rw + avdevice_zone1@pioneer: volume+ + enforce_updates: 'yes' + knx_listen: 3/4/8 + knx_dpt: 1 + avdevice_zone1_depend@pioneer: + - power, a + - volume < 160, b + + VolumeDown: + type: bool + visu_acl: rw + avdevice_zone1@pioneer: volume- + enforce_updates: 'yes' + knx_listen: 3/4/7 + knx_dpt: 1 + avdevice_zone1_depend@pioneer: + - volume > 10, b + - power, a + + VolumeLow: + type: bool + enforce_updates: 'yes' + visu: rw + knx_listen: 3/4/9 + knx_dpt: 1 + avdevice_zone1@pioneer: volumelow + avdevice_zone1_depend@pioneer: power + + VolumeHigh: + type: bool + enforce_updates: 'yes' + visu: rw + knx_listen: 3/4/10 + knx_dpt: 1 + avdevice_zone1@pioneer: volumehigh + avdevice_zone1_depend@pioneer: power + + Source: + type: foo + visu_acl: rw + avdevice_zone1@pioneer: input + avdevice_zone1_depend@pioneer: power + + Musik: + type: bool + visu_acl: ro + eval: 1 if (sh.Musik.KG.Pioneer.Source() == 13 and sh.Musik.KG.Pioneer.Power()) else 0 + eval_trigger: + - Musik.KG.Pioneer.Source + - Musik.KG.Pioneer.Power + enforce_updates: 'yes' + + Mode: + type: foo + visu_acl: rw + avdevice_zone1@pioneer: mode + avdevice_zone1_depend@pioneer: power = True + + Playingmode: + type: foo + visu_acl: ro + avdevice_zone1@pioneer: playingmode + avdevice_zone1_depend@pioneer: power + + Bass: + type: num + visu_acl: rw + avdevice_zone1@pioneer: bass + avdevice_zone1_depend@pioneer: tone + + BassUp: + type: bool + visu_acl: rw + avdevice_zone1@pioneer: bass+ + enforce_updates: 'yes' + avdevice_zone1_depend@pioneer: tone + + BassDown: + type: bool + visu_acl: rw + avdevice_zone1@pioneer: bass- + enforce_updates: 'yes' + avdevice_zone1_depend@pioneer: tone + + Dialog: + type: num + visu_acl: rw + avdevice_zone1@pioneer: dialog + avdevice_zone1_depend@pioneer: power + + Trebble: + type: num + visu_acl: rw + avdevice_zone1@pioneer: trebble + avdevice_zone1_depend@pioneer: tone + + TrebbleUp: + type: bool + visu_acl: rw + avdevice_zone1@pioneer: trebble+ + enforce_updates: 'yes' + avdevice_zone1_depend@pioneer: tone + + TrebbleDown: + type: bool + visu_acl: rw + avdevice_zone1@pioneer: trebble- + enforce_updates: 'yes' + avdevice_zone1_depend@pioneer: tone + + Tone: + type: bool + visu_acl: rw + avdevice_zone1@pioneer: tone + avdevice_zone1_depend@pioneer: power + + Display: + type: str + visu_acl: ro + avdevice_zone0@pioneer: display + avdevice_zone1_depend@pioneer: power + avdevice_zone2_depend@pioneer: power + + HDMI: + type: num + visu_acl: ro + avdevice_zone1@pioneer: HDMI + avdevice_zone1_depend@pioneer: power + avdevice_zone1_depend@pioneer: power + + Title: + type: str + visu_acl: ro + avdevice_zone0@pioneer: title + avdevice_zone1_depend@pioneer: + - power, a + - input = 26, b + + Station: + type: str + visu_acl: ro + avdevice_zone0@pioneer: station + avdevice_zone1_depend@pioneer: + - power, a + - input = 26, b + + Genre: + type: str + visu_acl: ro + avdevice_zone0@pioneer: genre + avdevice_zone1_depend@pioneer: + - power, a + - input = 26, b + + Power2: + type: bool + visu_acl: rw + avdevice_zone2@pioneer: power + avdevice_zone2_depend@pioneer: init + + Source2: + type: foo + visu_acl: rw + avdevice_zone2@pioneer: input + avdevice_zone2_depend@pioneer: power + + Musik: + type: bool + visu_acl: ro + eval: 1 if (sh.Musik.KG.Pioneer.Source2() == 13 and sh.Musik.KG.Pioneer.Power2()) else 0 + eval_trigger: + - Musik.KG.Pioneer.Source2 + - Musik.KG.Pioneer.Power2 + enforce_updates: 'no' + + Mute2: + type: bool + visu_acl: rw + avdevice_zone2@pioneer: mute + avdevice_zone2_depend@pioneer: power + + Volume2: + type: num + visu_acl: rw + avdevice_zone2@pioneer: volume + cache: 'True' + avdevice_zone2_depend@pioneer: power + + Fading: + type: num + + VolumeUp2: + type: bool + visu_acl: rw + avdevice_zone2@pioneer: volume+ + enforce_updates: 'yes' + knx_listen: 3/4/15 + knx_dpt: 1 + avdevice_zone2_depend@pioneer: power + + VolumeDown2: + type: bool + visu_acl: rw + avdevice_zone2@pioneer: volume- + enforce_updates: 'yes' + knx_listen: 3/4/14 + knx_dpt: 1 + avdevice_zone2_depend@pioneer: power + + VolumeHigh2: + type: num + visu_acl: rw + avdevice_zone2@pioneer: volumehigh + enforce_updates: 'yes' + knx_listen: 3/4/17 + knx_dpt: 1 + avdevice_zone2_depend@pioneer: power + + VolumeLow2: + type: num + visu_acl: rw + avdevice_zone2@pioneer: volumelow + enforce_updates: 'yes' + knx_listen: 3/4/16 + knx_dpt: 1 + avdevice_zone2_depend@pioneer: power diff --git a/avdevice/_pv_1_3_6/README.md b/avdevice/_pv_1_3_6/README.md new file mode 100755 index 000000000..f03e13888 --- /dev/null +++ b/avdevice/_pv_1_3_6/README.md @@ -0,0 +1,476 @@ +# AV Device + +## Requirements +If you want to connect to your device via RS232 (recommended) you need to install: +Serial Python module + +Install it with: +sudo pip3 install serial --upgrade + +## Supported Hardware + +Hopefully several different AV devices based on TCP or Serial RS232 connections +Tested with Pioneer (< 2016 models) and Denon AV receivers, Epson projector Oppo Bluray player + +## Changelog + +### v1.3.6 +Major code re-write using multiple modules and classes, minimizing complexity +Extended "translate" functionality with wildcards +Implemented optional waiting time between multiple commands +Improved Keep Command handling +Several bug fixes and tests + +### v1.3.5 +Implemented possibility to "translate" values +Improved Wildcard handling +Improved code +Added Oppo support +Improved response and queue handling + +### v1.3.4 +Tested full Denon support +Implemented Dependencies +Implemented rudimentary Wildcard handling +Implemented Initialization commands +Improved Queue handling and CPU usage +Bug fixes + +### v1.3.3 +Added Denon support +Added option to provide min-value in config file +Improved response handling +Implemented possibility to reload config files +Improved verbose logging +Bug fixes + +### v1.3.2 +Added and tested full Denon support + + +## Configuration + +### plugin.yaml + +``` +# etc/plugin.yaml +avdevice: + class_name: AVDevice + class_path: plugins.avdevice + model: sc-lx86 + #instance: pioneer_one + tcp_ip: 10.0.0.130 + #tcp_port: 23 + #tcp_timeout: 1 + rs232_port: /dev/ttyUSB1 + #rs232_baudrate: 9600 + #rs232_timeout: 0.1 + #ignoreresponse: 'RGB,RGC,RGD,GBH,GHH,VTA,AUA,AUB' + #forcebuffer: 'GEH01020, GEH04022, GEH05024' + #inputignoredisplay: '' + #dependson_item: '' + #dependson_value: True + #errorresponse: E02, E04, E06 + #resetonerror: False + #depend0_power0: False + #depend0_volume0: False + #sendretries: 10 + #resendwait: 1.0 + #reconnectretries: 13 + #reconnectcycle: 10 + #secondstokeep: 50 + #responsebuffer: 5 + #autoreconnect: false + #update_exclude: '' +``` + + +#### Attributes: + +* `model`: string. name of AV device. Has to correspond to a text file with the same name in the folder plugins/avdevice. +* `instance`: string. define instance name, each device needs an individual instance name! +* `tcp_ip`: IP address +* `tcp_port`: TCP/IP port +* `tcp_timeout`: TCP/IP timeout +* `rs232_port`: If you use a RS232 cable to communicate with your device (highly recommended!) define the interface port +* `rs232_baudrate`: baudrate for RS232 +* `rs232_timeout`: timeout for RS232 +* `ignoreresponse`: list of values. the plugin doesn't care about responses from the device starting with the given values. List responses for menu navigation, etc. For Pioneer receivers the following list is recommended: RGB, RGC, RGD, GBH, GHH, VTA, AUA, AUB +* `forcedbuffer`: list of strings. If for whatever reason you don't want to buffer the response from your device you can still define specific responses that should get buffered. This is important for responses that change very quickly. Artist, title, radio station, etc. are examples that should be put here. Furthermore the response buffer from the device usually gets cleaned of duplicate values. If you need to keep specific answers in the buffer even as duplicates, define them here, too. This could be relevant for multiple "cursor up" or "cursor down" commands. For Pioneer receivers the following list is recommended: GEH01020, GEH04022, GEH05024, R. +* `inputignoredisplay`: list of int. The value of the LCD display on your receiver might get updated very often, e.g. when it shows song titles as a scrolling text. To avoid constant display updates and therefore possible confusion with relevant answers of your device listing source inputs like internet radio, LAN streaming, etc. here is highly recommended. For Pioneer receivers the following list is recommended: 26,38,40,41,44,17,02,48,0 +* `dependson_item`: item. If given item has given value the commands are sent to the device, otherwise they are not. Relevant if you have your device connected to a power socket that can be turned off. +* `dependson_value`: boolean. If given item has given value the commands are sent to the device, otherwise they are not. Relevant if you have your device connected to a power socket that can be turned off. +* `errorresponse`: list of strings. The standard error responses from your device. For Pioneer receivers they are "E" followed by a number. If no values are provided error answers from your device might get recognized much slower but actually should still get recognized. +* `resetonerror`: boolean. Reset the value of the item that could not be updated. E.g. you set the volume of zone 2 to "100". If either the dependson item is off or the device sends an error response or after several connection and send retries the expected response is not received, the volume item gets set to value it had before you sent the command. That way you avoid having a wrong value displayed in your Visu. +* `depend0_power0`: boolean. If the dependson item is off the power off all zones are set to off. This is especially relevant for a correct representation in your Visu when you have a powered on device but turn off the power socket. +* `depend0_volume0`: boolean. Same as above but in this case the volume is set to 0 for all zones. This is for Visu purposes only. +* `sendretries`: integer. This value defines how often a command should be sent when receiving a wrong answer from the device. +* `resendwait`: float. Seconds the plugin should wait between each resend retry. +* `reconnectretries`: integer. If the plugin can not connect to the device it retries this often. This is especially useful for TCP connections on devices that are plugged into a switchable socket as most receivers need about 40-50 seconds to boot their network device. +* `secondstokeep`: integer. Seconds the plugin should temporarily save a command to retry later on after establishing a connection. This is especially useful for TCP connections on devices that are plugged into a switchable socket as most receivers need about 40-50 seconds to boot their network device. +* `responsebuffer`: integer or boolean. Set this to a number to collect quickly received responses in a buffer and evaluate them collectively. The standard value should be fine and prevent responses getting lost. Some receivers might first respond to a command with an update of the display and then with the actual value. The buffer ensures the correct evaluation of the response. +* `autoreconnect`: boolean. Automatically tries to reconnect if no response is received or connection is lost. This should not be necessary as the plugin always tries to reconnect before sending a command. +* `update_exclude`: string. Define smarthomeNG callers that should be ignored if they change an item. An example would be on_update or on_change. If you use i.e. on_update on an item using avdevice you might get stuck in an endless loop. Use this attribute to avoid this. +* `statusquery`: bool. If set to true (default) value will get queried after connection or manual statusupdate. If set to false only those items with depend=init will get updated. + +### items.yaml + +#### avdevice_zone[0-4]@[instance]: [command] + +Specifiy the zone number and instance. If you don't use zones you can either use "avdevice" or "avdevice_zone0" as attributes. + +The command has to correspond to a "base" command in the relevant text configuration file in the avdevice plugin folder named the same as the "model" configured in plugin.yaml. +It is important to set the correct type for each item. The Pioneer RS232 codeset expects bool and int types only. +For example to set the listening mode to "pure direct", the item has to be int and you set it to the value "8". If you want to use the "translation-feature" you should set the item to "foo". This feature is explained later. + +Full item examples are included as separate yaml files for Pioneer and Denon devices. In general the items are setup the same, independent of the AV device model. The examples include the tested items/commands and allow easy copy/paste. + +You can use two special avdevice attribute values if you want: +* `avdevice: statusupdate`: Use this item to trigger a full statusupdate. All query commands regarding the currently powered on zones are sent. This is especially useful if you have a power socket you can switch on or off and want to update all items on connection. +* `avdevice: reload`: Use this item to reload your text configurations. This re-reads the config as well as translation files and recreates all functions and commands. This is useful if you find an error in your configuration file or if you want to add new commands while smarthomeNG is running. You don't need to restart the plugin to reload the config! + +#### Example + +``` +# items/my.yaml +Pioneer: + type: foo + + Update: + type: bool + visu_acl: rw + avdevice: statusupdate + enforce_updates: 'yes' + + Reload: + type: bool + visu_acl: rw + avdevice: reload + enforce_updates: 'yes' + + Power: + type: bool + visu_acl: rw + avdevice_zone1: power + +``` +#### avdevice_zone[0-4]_speakers@[instance]: [command] + +Specifiy the zone number and instance. +Speakers Items are special and should be set up the way mentioned in the following example. 1 and 2 correspond to the value the speaker command expects (for example for Pioneer receivers < 2016). + +#### Example + +``` +# items/my.yaml +Pioneer: + type: foo + + Speakers: + type: num + visu_acl: rw + avdevice_zone1: speakers + + SpeakerA: + type: bool + visu_acl: rw + avdevice_zone1_speakers: 1 + + SpeakerB: + type: bool + visu_acl: rw + avdevice_zone1_speakers: 2 + +``` + +#### avdevice_zone[0-4]_depend@[instance]: [command] + +Specifiy the zone number and instance. +The depend attribute lets you specifiy for each item if it depends on another item/function. If you define such a dependency several things will happen: +- The item only gets updated/changed if the dependency is fullfilled +- Query command of the item will get removed from the queue if the dependency is not fullfilled +- Query command of the item will (only) get added if one of the "master" items gets changed and the dependency is fullfilled. +- After connecting to the device the query command of an item only gets added if you add "init" to the dependency configuration. + +You can use multiple depend items and attributes even for different zones. You can even define "and/or" for the dependencies by adding up to four different groups (a, b, c, d) after the value seperated by a comma ",". + +You can not only define a "master" item but also a "master value" and several standard python comparison operators. + +If you don't set an operator and value, "==" and "True" is assumed. If you don't set a group, group "a" is assumed. This means, if you add several dependent function without a group, the functions will get evaluated as "or" and dependency is fullfilled as soon as one of the functions/items corresponds to the given value. + +The example below shows the following dependencies: +- The disctype will always be queried after connecting to the device (as long as you have specified a query command in the command-file) +- Audio language and encoding will be queried after connecting to the device or as soon as the item with the "play" function (Oppo.Play) is True +- The track will get updated/queried if these dependencies are fullfilled: (play is True or status is play) AND verbose is set to 2 AND audiotype is either PCM or PCM 44.1/16 +- The trackname will get updated/queried if these dependencies are fullfilled: (play is True or status is play) AND verbose is set to 2 AND audiotype is either PCM or PCM 44.1/16 AND disctpye is one of these three values: DVD-AUDIO, CDDA, DATA-DISC + +#### Example + +``` +# items/my.yaml +Oppo: + type: foo + + Power: + visu_acl: rw + type: bool + avdevice@oppo: power + + Verbose: + visu_acl: rw + type: num + cache: 'false' + enforce_updates: 'yes' + avdevice@oppo: verbose + + Status: + visu_acl: rw + type: str + cache: 'False' + enforce_updates: 'yes' + avdevice@oppo: status + on_change: + - ..Pause = True if value == 'PAUSE' else False + - ..Stop = True if not (value == 'PLAY' or value == 'PAUSE' or value == 'INVALID') else False + - ..Play = True if value == 'PLAY' else False + + Play: + visu_acl: rw + type: bool + enforce_updates: 'yes' + avdevice@oppo: play + + Disctype: + visu_acl: rw + type: str + cache: 'False' + enforce_updates: 'yes' + avdevice@oppo: disctype + avdevice_depend@oppo: init + + Audio: + type: foo + + Language: + visu_acl: rw + type: str + cache: 'False' + enforce_updates: 'yes' + avdevice@oppo: audiolanguage + avdevice_depend@oppo: + - play + - init + + Encoding: + visu_acl: rw + type: str + cache: 'False' + enforce_updates: 'yes' + avdevice@oppo: audiotype + avdevice_depend@oppo: + - play + - init + + Track: + visu_acl: rw + type: num + cache: 'False' + enforce_updates: 'yes' + avdevice@oppo: audiotrack + avdevice_depend@oppo: + - play = True, a + - status = PLAY, a + - verbose = 2, b + - audiotype = PCM, c + - audiotype = PCM 44.1/16, c + + Trackname: + visu_acl: rw + type: str + avdevice@oppo: trackname + avdevice_depend@oppo: + - disctype = DVD-AUDIO, a + - disctype = CDDA, a + - disctype = DATA-DISC, a + - play = True, b + - status = PLAY, b + - audiotype = PCM, c + - audiotype = PCM 44.1/16, c + - verbose = 2, d +``` + +#### avdevice_zone[0-4]_init@[instance]: [command] + +Specifiy the zone number and instance. +The init attribute lets you set a specific command to a specific value as soon as the device is connected. For example if you want to always unmute your device as soon as the plugin connects to it (at startup and after turning on the power socket or reconnecting the cable) you can define an additional item with the attribute "avdevice_init". The value of that item (Oppo.Verbose.Init) gets written to the linked item (Oppo.Verbose). + +You can use multiple init items and attributes even for different zones. + +#### Example + +``` +# items/my.yaml +Oppo: + type: foo + Verbose: + type: bool + visu_acl: rw + avdevice_zone1: verbose + + Init: + visu_acl: rw + type: bool + cache: 'true' + value: 2 + avdevice_zone1_init: verbose + +Pioneer: + type: foo + + Zone1: + type: foo + + Mute: + type: bool + visu_acl: rw + avdevice_zone1: mute + + Init: + visu_acl: rw + type: bool + cache: 'true' + value: True + avdevice_zone1_init: mute + + Zone2: + type: foo + + Mute: + type: bool + visu_acl: rw + avdevice_zone2: mute + + Init: + visu_acl: rw + type: bool + cache: 'true' + value: True + avdevice_zone2_init: mute + +``` + +### model.txt + +#### ZONE;FUNCTION;FUNCTIONTYPE;SEND;QUERY;RESPONSE;READWRITE;INVERTRESPONSE;MINVALUE;MAXVALUE;RESPONSETYPE;TRANSLATIONFILE + +Configure your commands depending on your model and manufacturer. You have to name the file the same as configured in the plugin.yaml as "model". E.g. if you've configured "model: vsx-923" you name the file "vsx-923.txt" + +Each line holds one specific command that should be sent to the device. You also specify the zone, the query command, response command, etc. You can comment out lines by placing a # in front of the line. You can also comment a whole block by using ''' at the beginning and end of a block. + +* `zone`: Number of zone. Has to correspond to the attribute in item.yaml. E.g. for zone 1 use "avdevice_zone1: command". Zone 0 holds special commands like navigating in the menu, display reponse, information about currently playing songs, etc. + +* `function`: name of the function. You can name it whatever you like. You reference this value in the item using avdevice_zoneX: function. + +* `functiontype`: for boolean functions use "on" or "off". For commands setting a specific value like source, input mode, volume, etc. use "set". To increase or decrease a value use the corresponding "increase" or "decrease". For everything else leave empty! + +* `send`: the command to be sent, e.g. power off is "PF" for Pioneer receivers. You can use a pipe "|" if more than one command should be sent. Add an integer or float to specify a pause in seconds between the commands, like "PO|2|PO". That might be necessary for power on commands via RS232, e.g. for Pioneer receivers to power on "PO|PO" forces the plugin to send the "PO" command twice. Use stars "\*" to specify the format of the value to be sent. Let's say your device expects the value for volume as 3 digits, a "\*\*\*VL" ensures that even setting the volume to "5" sends the command as "005VL" + +* `query`: Query command. This is usually useful after setting up the connection or turning on the power. This command gets also used if the plugin doesn't receive the correct answer after sending a command. It is recommended to leave this value empty for all functions except on, off and set. + +* `response`: The expected response after sending a command. Use "none" if you don't want to wait for the correct response. You can use stars "\*" again to ensure that the exact correct value is set. Example: You set the volume to 100. If you want to ensure that the device responds with any value for volume just use "VOL" here (or whatever response your device sends). If you want to ensure that the device is set to a volume of 100, use stars as placeholders, e.g. "VOL\*\*\*" for 3 digits. You can even specify multiple response possibilities separated by "|". + +* `readwrite`: R for read only, W for write only, RW for Read and Write. E.g. display values are read only whereas turning the volume up might be a write operation only. Setting this correctly ensures a fast and reliable plugin operation + +* `invertresponse`: some devices are stupid enough to reply with a "0" for "on" and "1" for "off". E.g. a Pioneer receiver responds with "PWR0" if the device is turned on. Configure with "yes" if your device is quite stupid, too. + +* `minvalue`: You can define the minimum value for setting a specific function. This might be most relevant for setting the volume or bass/trebble values. If you configure this with "-3" and set the bass to "-5" (via Visu or CLI) the value will get clamped by the plugin and set to "-3". + +* `maxvalue`: You can define the maximum value for setting a specific function. This might be most relevant for setting the volume. If you configure this with "100" and set the volume to "240" (via Visu or CLI) the value will get clamped by the plugin and set to "100". + +* `responsetype`: Defines the type of the response value and can be set to "bool", "num" or "str" or a mixture of them (separated by a pipe "|" or comma ","). Most response types are set automatically on startup but you can force a specific type using this value. It is recommended to use the values suggested in the txt files that come with the plugin. + +* `translationfile`: If you want to translate a specific value/code to something else, define a txt file here that holds the information on how to translate which value + +#### Example + +``` +# plugins/avdevice/pioneer.txt +ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MINVALUE; MAXVALUE; RESPONSETYPE; TRANSLATIONFILE +1; power; on; PO|PO; ?P; PWR*; RW; yes +1; power; off; PF; ?P; PWR*; RW; yes +1; volume+; increase; VU; ; VOL; W +1; volume-; decrease; VD; ; VOL; W +1; volume; set; ***VL; ?V; VOL***; RW; ; 80; 185 +1; input; set; **FN; ?F; FN**; RW +1; speakers; set; *SPK; ?SPK; SPK*; RW +''' +#commented out from here +2; power; on; APO|APO; ?AP; APR*; RW; yes +2; power; off; APF; ?AP; APR*; RW; yes +0; title; ; ; ; GEH01020; R +0; station; ; ; ; GEH04022; R +0; genre; ; ; ; GEH05024; R +#commented out until here +''' +0; display; ; ?FL; ?FL; FL******************************; R +1; input; set; **FN; ?F; FN**; RW; ; ; ; ; pioneer_input +1; mode; set; ****SR; ?S; SR****; RW; ; ; ; num; pioneer_SR +1; playingmode; ; ?L; ?L; LM****; R; ; ; ; str,int; pioneer_LM +#0; test; ; ; ; noidea; R (commented out) +``` + +### Translation + +Define a filename that contains translations in your main model.txt as seen above. +You could create a file called denon_volume.txt and link it in your model.txt file to convert 3 digit volume to a float. Denon receivers handle e.g. 50.5 as 505. If you want to use value limits or visualize the volume correctly in your VISU you should use the following translation file: + +``` +# plugins/avdevice/denon_volume.txt +CODE; TRANSLATION +***; **.* +``` + +Pioneer receivers use numbers to define input source or listening mode what is very cryptic and not very user friendly. Therefore you should use the relevant files in the plugins folder like pioneer_input. That file looks something like this: + +``` +# plugins/avdevice/pioneer_input.txt +CODE; TRANSLATION +00; PHONO +01; CD +02; TUNER +``` + +Now, when the plugin receives FN01 as a response, the response gets converted to "CD". Vice versa you can even update your item to "CD" and the plugin will send "01FN" as a command. It is advised to define the according item as type=foo so you can either use a number or string, just the way you like. + +### Wildcards + +For the model.txt file you can use question marks as a wild card if the response of the device includes information for several different items. This is the case with a lot of responses from Oppo bluray players. + +Use a "?" for "any single character", use "??" for "two characters of any value" and so on. If the length of the wildcard can differ, use a "?{str}" meaning that the plugin expects a string of any given length. + +The definition for audiotype in the example means that the expected response consists of: +"@QAT OK " in the beginning followed by a single character followed by a "/" and another single character again. After that is the relevant part of the response, the value of the item, defined by exactly three digits/characters. Behind that is a blank and any value consisting of five characters or digits. + +The example definition for audiotrack means that the response can be: "@UAT " followed by any word/number without a specific length, followed by a blank and the real value consisting of two characters. The response could also start with "@QTK OK " followed by the relevant value consisting of exactly one digit/character. After that there will be a "/" and any character/digit. It is important to add the "/?" in the end because the plugin also compares the length of the response with the expected length (calculated from the response in the command-file). It is not relevant, if you use a {str} in your response because then the length can not be determined. + +This feature is still under development. Feel free to experiment with it and post your experience in the knx-forum. + +#### Example + +``` +# plugins/avdevice/oppo-udp203.txt +ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MINVALUE; MAXVALUE; RESPONSETYPE; TRANSLATIONFILE +0; audiotype; ; ; #QAT; @QAT OK ?/? *** ?????; R; ; ; ; str +0; audiotrack; ; #AUD; #QTK; @UAT ?{str} **|@QTK OK */?; RW; ; ; ; num +``` + +## Troubleshooting +1.) Have a look at the smarthome logfile. If you can't figure out the reason for your problem, change the verbose level in logging.yaml. +You can use level 10 (=DEBUG), 9 (VERBOSE1) and 8 (VERBOSE2) as debugging levels. + +2.) Concerning send and response entries in the textfile, make sure the number of stars correspond to the way your device wants to receive the command or sends the response. +Example 1: Your Pioneer receiver expects the value for the volume as three digits. So the command needs three stars. If you now set the item to a value with only two digits, like 90, the plugin converts the command automatically to have a leading 0. +Example 2: Your Denon receiver responds with values like ON, OFF or STANDBY to power commands. Replace every character with a star! ON = 2 stars, OFF = 3 stars, etc. +Example 3: Sending or receiving strings of different length like "CD", "GAME", etc. should be set up with one star only. Alternatively you can use "*{str}". Set the responsetype accordingly! + +3.) Set the response type in the textfile to the correct value. The plugin tries to anticipate the correct value but that doesn't always work. The sleep timer of Denon devices is a wonderfully sick example: You can set values between 1 and 120 to set the timer in minutes. If you want to turn it off, the receiver expects the value "OFF" instead of a zero. The plugin fixes that problem if you set the responsetype to bool|num. As soon as you set the item to 0, it magically converts that value to "OFF" and the other way around when receiving "OFF". diff --git a/avdevice/_pv_1_3_6/__init__.py b/avdevice/_pv_1_3_6/__init__.py new file mode 100755 index 000000000..57cad023d --- /dev/null +++ b/avdevice/_pv_1_3_6/__init__.py @@ -0,0 +1,2968 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2016 +######################################################################### +# This file is part of SmartHomeNG. +# +# Plugin to control AV Devices via TCP and/or RS232 +# Tested with Pioneer AV Receivers. +# +# SmartHomeNG is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# SmartHomeNG is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with SmartHomeNG. If not, see . +# +######################################################################### + +import logging +from lib.model.smartplugin import SmartPlugin +from lib.item import Items +import io +import time +import re +import errno +import sys +import itertools +from .AVDeviceInit import Init +from .AVDeviceInit import ProcessVariables +from .AVDeviceFunctions import CreateResponse +from .AVDeviceFunctions import Translate +from .AVDeviceFunctions import ConvertValue +from .AVDeviceFunctions import CreateExpectedResponse + +VERBOSE1 = logging.DEBUG - 1 +VERBOSE2 = logging.DEBUG - 2 +logging.addLevelName(logging.DEBUG - 1, 'VERBOSE1') +logging.addLevelName(logging.DEBUG - 2, 'VERBOSE2') + + +class AVDevice(SmartPlugin): + ALLOW_MULTIINSTANCE = True + PLUGIN_VERSION = "1.3.6" + + def __init__(self, smarthome, + model='', + ignoreresponse='RGB,RGC,RGD,GBH,GHH,VTA,AUA,AUB', + errorresponse='E02,E04,E06', + forcebuffer='GEH01020, GEH04022, GEH05024', + inputignoredisplay='', + dependson_item='', + dependson_value=True, + rs232_port='', + rs232_baudrate=9600, + rs232_timeout=0.1, + tcp_ip='', + tcp_port=23, + tcp_timeout=1, + resetonerror=False, + depend0_power0=False, + depend0_volume0=False, + sendretries=10, + resendwait=1.0, + reconnectretries=13, + secondstokeep=50, + responsebuffer='5', + autoreconnect=False, + update_exclude='', + statusquery=True): + self.itemsApi = Items.get_instance() + self.logger = logging.getLogger(__name__) + self._sh = smarthome + self.alive = False + self._name = self.get_instance_name() + self._serialwrapper = None + self._serial = None + self._tcpsocket = None + self._functions = {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}} + self._items = {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}} + self._query_zonecommands = {'zone0': [], 'zone1': [], 'zone2': [], 'zone3': [], 'zone4': []} + self._items_speakers = {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}} + self._send_commands = [] + self._init_commands = {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}} + self._keep_commands = {} + self._specialparse = {} + self._query_commands = [] + self._power_commands = [] + self._expected_response = [] + self._response_commands = {} + self._response_wildcards = {'wildcard': {}, 'original': {}} + self._number_of_zones = 0 + self._trigger_reconnect = True + self._reconnect_counter = 0 + self._resend_counter = 0 + self._resend_on_empty_counter = 0 + self._clearbuffer = False + self._sendingcommand = 'done' + self._special_commands = {} + self._is_connected = [] + self._parsinginput = [] + self._dependencies = {'Slave_function': {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}}, + 'Slave_item': {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}}, + 'Master_function': {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}}, + 'Master_item': {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}}} + + try: + self._model = self.get_parameter_value('model') + self._resend_wait = float(self.get_parameter_value('resendwait')) + self._secondstokeep = int(self.get_parameter_value('secondstokeep')) + self._auto_reconnect = self.get_parameter_value('autoreconnect') + self._resend_retries = int(self.get_parameter_value('sendretries')) + self._reconnect_retries = int(self.get_parameter_value('reconnectretries')) + ignoreresponse = self.get_parameter_value('ignoreresponse') + errorresponse = self.get_parameter_value('errorresponse') + forcebuffer = self.get_parameter_value('forcebuffer') + inputignoredisplay = self.get_parameter_value('inputignoredisplay') + resetonerror = self.get_parameter_value('resetonerror') + responsebuffer = self.get_parameter_value('responsebuffer') + depend0_power0 = self.get_parameter_value('depend0_power0') + depend0_volume0 = self.get_parameter_value('depend0_volume0') + dependson_item = self.get_parameter_value('dependson_item') + dependson_value = self.get_parameter_value('dependson_value') + tcp_ip = self.get_parameter_value('tcp_ip') + tcp_port = self.get_parameter_value('tcp_port') + tcp_timeout = self.get_parameter_value('tcp_timeout') + rs232_port = self.get_parameter_value('rs232_port') + rs232_baudrate = self.get_parameter_value('rs232_baudrate') + rs232_timeout = self.get_parameter_value('rs232_timeout') + update_exclude = self.get_parameter_value('update_exclude') + statusquery = self.get_parameter_value('statusquery') + except Exception: + self._model = model + self._resend_wait = float(resendwait) + self._secondstokeep = int(secondstokeep) + self._auto_reconnect = autoreconnect + self._resend_retries = int(sendretries) + self._reconnect_retries = int(reconnectretries) + # Initializing all variables + self.logger.debug("Initializing {}: Resendwait: {}. Seconds to keep: {}.".format(self._name, self._resend_wait, + self._secondstokeep)) + self.init = Init(self._sh, self._name, self._model, self._items) + self._rs232, self._baud, self._timeout = ProcessVariables([rs232_port, rs232_baudrate, rs232_timeout], + self._name).process_rs232() + self._tcp, self._port, self._tcp_timeout = ProcessVariables([tcp_ip, tcp_port, tcp_timeout], + self._name).process_tcp() + self._dependson, self._dependson_value, self._depend0_power0, self._depend0_volume0 = ProcessVariables( + [dependson_item, dependson_value, depend0_power0, depend0_volume0], self._name).process_dependson() + + self._response_buffer = ProcessVariables(responsebuffer, self._name).process_responsebuffer() + self._reset_onerror = ProcessVariables(resetonerror, self._name).process_resetonerror() + self._statusquery = ProcessVariables(statusquery, self._name).process_statusquery() + self._ignore_response, self._error_response, self._force_buffer, self._ignoredisplay = ProcessVariables( + [ignoreresponse, errorresponse, forcebuffer, inputignoredisplay], self._name).process_responses() + self.logger.debug( + "Initializing {}: Special Settings: Ignoring responses {}.".format(self._name, self._ignore_response)) + self.logger.debug( + "Initializing {}: Special Settings: Error responses {}.".format(self._name, self._error_response)) + self.logger.debug("Initializing {}: Special Settings: Force buffer {}.".format(self._name, self._force_buffer)) + self.logger.debug( + "Initializing {}: Special Settings: Ignore Display {}".format(self._name, self._ignoredisplay)) + self.logger.debug( + "Initializing {}: Querying at plugin init is set to {}".format(self._name, self._statusquery)) + self._update_exclude = ProcessVariables(update_exclude, self._name).process_update_exclude() + + # Non-blocking wait function + @staticmethod + def _wait(time_lapse): + time_start = time.time() + time_end = (time_start + time_lapse) + + while time_end > time.time(): + time.sleep(0.001) + + # Resetting items when send command failed + def _resetitem(self, founditem): + try: + resetting = None + if founditem == '': + try: + founditem = self._sendingcommand.split(';')[1] + except Exception: + try: + founditem = self._send_commands[0].split(';')[1] + except Exception: + self.logger.log(VERBOSE2, + "Resetting {}: Resetting nothing because command is query command only.".format(self._name)) + return None + try: + founditem = self.itemsApi.return_item(founditem) + except Exception as err: + self.logger.debug("Resetting {}: {} is no valid item. Message: {}.".format(self._name, founditem, err)) + return None + self.logger.log(VERBOSE2, "Resetting {}: Item: {}.".format(self._name, founditem)) + speakerfound = True if founditem == self._special_commands['Speakers']['Item'] else False + + for zone in self._items.keys(): + for itemlist in self._items[zone].keys(): + previousvalue = self._items[zone][itemlist]['Value'] + if isinstance(self._items[zone][itemlist]['Item'], list): + for search in self._items[zone][itemlist]['Item']: + self.logger.log(VERBOSE2, "Resetting {}: Search {} in {} with {}.".format( + self._name, founditem, self._items[zone][itemlist]['Item'], search)) + if founditem == search: + founditem(previousvalue, 'AVDevice', self._tcp) + self.logger.info("Resetting {}: Item {} to {}".format( + self._name, founditem, previousvalue)) + resetting = founditem + break + else: + compare = self._items[zone][itemlist].get('Item') + self.logger.log(VERBOSE2, + "Resetting {}: Search {} in {}.".format(self._name, founditem, compare)) + if founditem == compare: + founditem(previousvalue, 'AVDevice', self._tcp) + self.logger.info("Resetting {}: Item {} to {}".format( + self._name, founditem, previousvalue)) + resetting = founditem + break + for speakerlist in self._items_speakers[zone].keys(): + search = self._items_speakers[zone][speakerlist]['Item'] + self.logger.log(VERBOSE2, "Resetting {}: Search {} in speakers {}.".format( + self._name, founditem, search)) + speakerfound = True if founditem == search else False + if speakerfound is True: + for itemlist in self._items_speakers[zone].keys(): + search = self._items_speakers[zone][itemlist]['Item'] + previousvalue = self._items_speakers[zone][itemlist]['Value'] + self.logger.info("Resetting {}: Resetting additional speaker item {} to value {}".format( + self._name, search, previousvalue)) + search(previousvalue, 'AVDevice', self._tcp) + resetting = founditem + if resetting is not None: + break + + self._trigger_reconnect = False + self.logger.log(VERBOSE2, "Resetting {}: Finished. Returning value: {}.".format(self._name, resetting)) + return resetting + except Exception as err: + self.logger.error("Resetting {}: Problem resetting Item. Error: {}".format(self._name, err)) + return 'ERROR' + + # Resetting items if no connection available + def _resetondisconnect(self, caller): + if self._depend0_volume0 is True or self._depend0_power0 is True: + self.logger.debug('Resetting {}: Starting to reset on disconnect. Called by {}'.format(self._name, caller)) + try: + for zone in self._items: + if 'power' in self._items[zone].keys() and self._depend0_power0 is True: + self._items[zone]['power']['Value'] = 0 + self._items[zone]['power']['Item'](0, 'AVDevice', self._tcp) + self.logger.log(VERBOSE1, 'Resetting {}: Power to 0 for item {}'.format( + self._name, self._items[zone]['power']['Item'])) + if 'speakers' in self._items[zone].keys() and self._depend0_power0 is True: + self._items[zone]['speakers']['Value'] = 0 + for itemlist in self._items_speakers[zone].keys(): + self._items_speakers[zone][itemlist]['Value'] = 0 + speakeritem = self._items_speakers[zone][itemlist]['Item'] + speakeritem(0, 'AVDevice', self._tcp) + self.logger.log(VERBOSE1, + 'Resetting {}: Speakers to 0 for item {}'.format(self._name, + speakeritem)) + speakeritem = self._items[zone]['speakers']['Item'] + speakeritem(0, 'AVDevice', self._tcp) + self.logger.log(VERBOSE1, + 'Resetting {}: Speakers to 0 for item {}'.format(self._name, speakeritem)) + if 'volume' in self._items[zone].keys() and self._depend0_volume0 is True: + self._items[zone]['volume']['Value'] = 0 + self._items[zone]['volume']['Item'](0, 'AVDevice', self._tcp) + self.logger.log(VERBOSE1, 'Resetting {}: Volume to 0 for item {}'.format( + self._name, self._items[zone]['volume']['Item'])) + self.logger.debug('Resetting {}: Done.'.format(self._name)) + except Exception as err: + self.logger.warning('Resetting {}: Problem resetting Item on disconnect. Error: {}'.format(self._name, err)) + else: + self.logger.log(VERBOSE1, + 'Resetting {}: Not resetting on disconnect because this feature is disabled in the plugin config.'.format( + self._name)) + + # Store actual value to a temporary dict for resetting purposes + def _write_itemsdict(self, data, found): + zone = updated = 0 + receivedvalue = expectedtype = av_function = 'empty' + try: + self.logger.debug( + "Storing Values {}: Starting to store value for data {} in dictionary. Found expected responses: {}.".format( + self._name, data, found)) + sorted_response_commands = sorted(self._response_commands, key=len, reverse=True) + for i, respo in enumerate(sorted_response_commands): + try: + sorted_response_commands[i] = self._response_wildcards['original'][respo] + except Exception as err: + sorted_response_commands[i] = None + self.logger.log(VERBOSE2, + "Storing Values {}: Can not find wildcard equivalent for: {}".format(self._name, + err)) + for entry in found: + if entry in sorted_response_commands: + sorted_response_commands.insert(0, entry) + sorted_response_commands = [value for value in sorted_response_commands if value is not None] + self.logger.log(VERBOSE2, "Storing Values {}: Sorted wildcarded response commands {}.".format(self._name, + sorted_response_commands)) + for command in sorted_response_commands: + self.logger.log(VERBOSE2, "Storing Values {}: Comparing command {}.".format(self._name, command)) + if data == command: + self.logger.debug( + "Storing Values {}: Response is identical to expected response. Skipping Storing: {}".format( + self._name, data)) + break + for entry in self._response_commands[self._response_wildcards['wildcard'][command]]: + self.logger.log(VERBOSE2, "Storing Values {}: Comparing entry {}.".format(self._name, entry)) + commandstart = entry[0] if entry[2] == 0 else 0 + commandend = entry[1] if entry[2] == 0 else entry[2] + valuestart = entry[2] + valueend = entry[2] + entry[0] + av_function = entry[4] + expectedtype = entry[7] + + if data[commandstart:commandend] == command: + zone = entry[5] + value = data[valuestart:valueend] + invert = True if entry[6].lower() in ['1', 'true', 'yes', 'on'] else False + received = ConvertValue(value, expectedtype, invert, entry[0], command, + self._name, self._special_commands).convert_value() \ + if not value == '' else data[valuestart:valueend] + receivedvalue = received[1] if isinstance(received, list) else received + try: + sametype = True if isinstance(receivedvalue, eval(expectedtype)) else False + except Exception as err: + self.logger.log(VERBOSE2, + "Storing Values {}: Cannot compare {} with {}. Message: {}".format( + self._name, receivedvalue, expectedtype, err)) + sametype = True if receivedvalue == '' and expectedtype == 'empty' else False + if sametype is True: + self._items[zone][av_function]['Value'] = Translate( + value, entry[9], self._name, 'writedict', self._specialparse).translate() + self.logger.debug( + "Storing Values {}: Found writeable dict key: {}. Zone: {}. " + "Value {} with type {}. Function: {}.".format( + self._name, command, zone, receivedvalue, expectedtype, av_function)) + updated = 1 + break + else: + self.logger.debug( + "Storing Values {}: Found writeable dict key: {} with type {}, " + "but received value {} is type {}. Not writing value!".format( + self._name, command, expectedtype, receivedvalue, type(receivedvalue))) + + if updated == 1: + self.logger.log(VERBOSE1, + "Storing Values {}: Stored all relevant items from function {}. step 1".format( + self._name, av_function)) + break + if updated == 1: + self.logger.log(VERBOSE1, + "Storing Values {}: Stored all relevant items from function {}. step 2".format( + self._name, av_function)) + break + if updated == 1: + self.logger.log(VERBOSE1, + "Storing Values {}: Stored all relevant items from function {}. step 3".format( + self._name, av_function)) + break + except Exception as err: + self.logger.error( + "Storing Values {}: Problems creating items dictionary. Error: {}".format(self._name, err)) + finally: + self.logger.log(VERBOSE1, + "Storing Values {}: Finished. Send Commands: {}. Returning: {}, {}".format( + self._name, self._send_commands, receivedvalue, expectedtype)) + if updated == 1: + return self._items[zone][av_function], receivedvalue, expectedtype + else: + return 'empty', 'empty', 'empty' + + def _parse_depend_item(self, item, info, zone): + for dependzone in range(0, 5): + dependzone = 'zone{}'.format(dependzone) + cond1 = self.has_iattr(item.conf, 'avdevice_{}_depend'.format(dependzone)) + cond2 = (self.has_iattr(item.conf, 'avdevice_depend') and dependzone == 'zone0') + if cond1 or cond2: + liste = self.get_iattr_value(item.conf, 'avdevice_{}_depend'.format(dependzone)) \ + if cond1 else self.get_iattr_value(item.conf, 'avdevice_depend') + liste = [liste] if not isinstance(liste, list) else liste + for entry in liste: + splitting = entry.split('>=') if entry.find('>=') >= 0 \ + else entry.split('<=') if entry.find('<=') >= 0 \ + else entry.split('==') if entry.find('==') >= 0 \ + else entry.split('=') if entry.find('=') >= 0 \ + else entry.split('>') if entry.find('>') >= 0 \ + else entry.split('<') if entry.find('<') >= 0 \ + else entry.split('!=') if entry.find('!=') >= 0 or entry.find('<>') >= 0 \ + else [entry.split(',')[0], '{}, {}'.format(True, entry.split(',')[1])] if entry.find(',') >= 0 \ + else [entry, True] + comparing = '>=' if entry.find('>=') >= 0 \ + else '<=' if entry.find('<=') >= 0 \ + else '>' if entry.find('>') >= 0 \ + else '<' if entry.find('<') >= 0 \ + else '!=' if entry.find('!=') >= 0 or entry.find('<>') >= 0 \ + else '==' + try: + depend = splitting[0].strip().lower() + except Exception: + depend = None + try: + dependvalue = splitting[1].split(',')[0].strip() + dependvalue = True if re.sub('[ ]', '', str(dependvalue)).lower() in ['yes', 'true', 'on'] \ + else False if re.sub('[ ]', '', str(dependvalue)).lower() in ['no', 'false', 'off'] \ + else dependvalue + except Exception: + dependvalue = None if depend is None else True + try: + dependgroup = splitting[1].split(',')[1].strip().lower() + except Exception: + dependgroup = 'a' + try: + dependvalue = eval(dependvalue) + except Exception: + pass + if splitting is None: + return None + else: + try: + self._items[zone][info]['Master'].append( + {'Zone': dependzone, 'Item': depend, 'Dependvalue': dependvalue, 'Compare': comparing, + 'Group': dependgroup}) + self.logger.log(VERBOSE1, + "Initializing {}: Adding dependency for {}.".format(self._name, info)) + except Exception: + self._items[zone][info].update({'Master': [ + {'Zone': dependzone, 'Item': depend, 'Dependvalue': dependvalue, 'Compare': comparing, + 'Group': dependgroup}]}) + self.logger.log(VERBOSE1, + "Initializing {}: Creating dependency for {}.".format(self._name, info)) + + # Finding relevant items for the plugin based on the avdevice keyword + def parse_item(self, item): + if self._tcp is not None or self._rs232 is not None: + keywords = ['avdevice', 'avdevice_zone0', 'avdevice_init', 'avdevice_speakers', 'avdevice_zone1', + 'avdevice_zone1_init', 'avdevice_zone1_speakers', 'avdevice_zone2', 'avdevice_zone2_init', + 'avdevice_zone2_speakers', 'avdevice_zone3', 'avdevice_zone3_init', 'avdevice_zone3_speakers', + 'avdevice_zone4', 'avdevice_zone4_init', 'avdevice_zone4_speakers'] + for keyword in keywords: + try: + zone = keyword.split("_")[1] + except Exception: + zone = 'zone0' + if zone == 'init' or zone == 'speakers' or zone == 'depend': + zone = 'zone0' + if str(item) == self._dependson: + self._items[zone]['dependson'] = {'Item': self._dependson, 'Value': self._dependson_value} + self._dependencies['General'] = {'Item': self._dependson, 'Value': self._dependson_value} + self.logger.debug( + "Initializing {}: Dependson Item found: {}".format(self._name, item, self._dependson)) + return self.update_item + elif self.has_iattr(item.conf, keyword): + info = self.get_iattr_value(item.conf, keyword) + if info is not None: + if '_init' in keyword: + self._init_commands[zone][info] = {'Inititem': item, 'Item': item, 'Value': item()} + return self.update_item + elif '_speakers' in keyword: + self._items_speakers[zone][info] = {'Item': item, 'Value': item()} + return self.update_item + else: + self._items[zone][info] = {'Item': item, 'Value': item()} + self._parse_depend_item(item, info, zone) + return self.update_item + return None + + # Processing the response from the AV device, dealing with buffers, etc. + def _processing_response(self, socket): + try: + buffer = '' + tidy = lambda c: re.sub( + r'(^\s*[\r\n]+|^\s*\Z)|(\s*\Z|\s*[\r\n]+)', + lambda m: '\r\n' if m.lastindex == 2 else '', + c) + try: + if self._rs232 and (socket == self._serialwrapper or socket == self._serial): + buffer = socket.readline().decode('utf-8') if socket == self._serial else socket.read() + if self._tcp and socket == self._tcpsocket: + buffer = socket.recv(4096).decode('utf-8') + buffer = tidy(buffer) + buffering = False + cond1 = self._response_buffer is not False or self._response_buffer is not 0 + if not buffer == '' and cond1: + buffering = True + elif buffer == '' and not self._sendingcommand == 'done' and not self._sendingcommand == 'gaveup': + self._resend_on_empty_counter += 1 + self._wait(0.1) + sending = self._send(self._sendingcommand, 'responseprocess') + self.logger.log(VERBOSE1, + "Processing Response {}: Received empty response while sending command: {}." + " Return from send is {}. Retry: {}".format( + self._name, self._sendingcommand, sending, self._resend_counter)) + if self._resend_on_empty_counter >= 2: + self.logger.debug( + "Processing Response {}: Stop resending command {} and sending back error.".format( + self._name, self._sendingcommand)) + self._resend_on_empty_counter = 0 + yield 'ERROR' + + except Exception as err: + buffering = False + try: + cond1 = not self._sendingcommand == 'done' and not self._sendingcommand == 'gaveup' + try: + cond2 = (self._sendingcommand.split(',')[2] == '' or self._sendingcommand.split(',')[2] == ' ' or + self._sendingcommand.split(',')[2] == 'none') + except Exception: + cond2 = self._sendingcommand == '' + if cond1 and not cond2: + buffering = True + self._expected_response = CreateExpectedResponse(buffer, self._name, + self._send_commands).create_expected() + self.logger.log(VERBOSE1, + "Processing Response {}: Error reading.. Error: {}. Sending Command: {}.".format( + self._name, err, self._sendingcommand)) + self.logger.log(VERBOSE2, + "Processing Response {}: Expected response: {}.".format( + self._name, self._expected_response)) + if self._rs232 and (socket == self._serialwrapper or socket == self._serial): + self.logger.log(VERBOSE1, + "Processing Response {}: Problems buffering RS232 response. Error: {}." + " Increasing timeout temporarily.".format(self._name, err)) + self._wait(1) + socket.timeout = 2 + sending = self._send(self._sendingcommand, 'getresponse') + buffer = socket.readline().decode('utf-8') if socket == self._serial else socket.read() + socket.timeout = 0.3 + self.logger.log(VERBOSE1, + "Processing Response {}: Error reading.. Return from send is {}. Error: {}".format( + self._name, sending, err)) + if not buffer: + yield 'ERROR' + if self._tcp and socket == self._tcpsocket: + self.logger.log(VERBOSE1, + "Processing Response {}: Problems buffering TCP response. Error: {}." + " Increasing timeout temporarily.".format(self._name, err)) + self._wait(1) + socket.settimeout(self._tcp_timeout * 3) + sending = self._send(self._sendingcommand, 'getresponse') + self.logger.debug( + "Processing Response {}: Error reading.. Return from send is {}. Error: {}".format( + self._name, sending, err)) + buffer = socket.recv(4096).decode('utf-8') + socket.settimeout(self._tcp_timeout) + if not buffer: + yield 'ERROR' + elif cond2: + # self._sendingcommand = 'done' + yield 'none' + except Exception as err: + buffering = False + self.logger.error( + "Processing Response {}: Connection error. Error: {} Resend Counter: {}. Resend Max: {}".format( + self._name, err, self._resend_counter, self._resend_retries)) + yield 'ERROR' + + while buffering: + if '\r\n' in buffer: + self.logger.log(VERBOSE2, + "Processing Response {}: Buffer before removing duplicates: {}".format( + self._name, re.sub('[\r\n]', ' --- ', buffer))) + if self._clearbuffer is True: + buffer = '\r\n' + self.logger.log(VERBOSE1, + "Processing Response {}: Clearing buffer because clearbuffer set to true. It is now: {}".format( + self._name, re.sub('[\r\n]', ' --- ', buffer))) + self._clearbuffer = False + bufferlist = buffer.split("\r\n") + bufferlist = bufferlist[:-1] if len(bufferlist) > 1 else bufferlist + # Removing duplicates + buffer_cleaned = [] + for buff in bufferlist: + if buff not in buffer_cleaned or buff in self._force_buffer: + buffer_cleaned.append(buff) + bufferlist = buffer_cleaned + buffer = "\r\n".join(bufferlist) + "\r\n" + expectedsplit = [] + + if self._send_commands: + self._expected_response = CreateExpectedResponse(buffer, self._name, + self._send_commands).create_expected() + expectedsplit = list(itertools.chain(*[x.split('|') for x in self._expected_response])) + sortedbuffer = [] + for e in expectedsplit: + for entry in bufferlist: + if entry == e and entry not in self._ignore_response: + sortedbuffer.append(entry) + self.logger.log(VERBOSE2, + "Processing Response {}: Response is same as expected. adding: {}.".format( + self._name, entry)) + break + elif entry.startswith(e): + try: + realresponse = self._response_wildcards['original'][e] + except Exception: + realresponse = e + try: + for resp in self._response_commands[realresponse]: + self.logger.log(VERBOSE2, + "Processing Response {}: realresponse: {}. Length: {}, expected length: {}.".format( + self._name, realresponse, len(entry), resp[1])) + cond1 = len(entry) == resp[1] or resp[1] == 100 or resp[0] == 100 + cond2 = entry not in sortedbuffer and entry not in self._ignore_response + if cond1 and cond2: + self.logger.log(VERBOSE2, + "Processing Response {}: length is same. adding: {}.".format( + self._name, entry)) + sortedbuffer.append(entry) + break + except Exception: + pass + + self.logger.log(VERBOSE2, + "Processing Response {}: expected response: {}, bufferlist {}. Sortedbuffer: {}".format( + self._name, expectedsplit, bufferlist, sortedbuffer)) + bufferlist = [x for x in bufferlist if x not in sortedbuffer] + buffer = "\r\n".join(sortedbuffer + bufferlist) + buffer = "{}\r\n".format(buffer) + self.logger.log(VERBOSE2, "Processing Response {}: Buffer after sorting: {}.".format( + self._name, re.sub('[\r\n]', ' --- ', buffer))) + + (line, buffer) = buffer.split("\r\n", 1) + self.logger.log(VERBOSE2, + "Processing Response {}: Buffer: {} Line: {}. Response buffer: {}, force buffer: {}.".format( + self._name, re.sub('\r\n', ' --- ', buffer), re.sub('\r\n', '. ', line), + self._response_buffer, self._force_buffer)) + cond1 = ('' in self._force_buffer and len(self._force_buffer) == 1) + cond2 = (self._response_buffer is False or self._response_buffer == 0) + cond3 = (not re.sub('[ ]', '', buffer) == '' and not re.sub('[ ]', '', line) == '') + if not cond1 and cond2 and cond3: + bufferlist = [] + for buf in self._force_buffer: + try: + if buf in buffer and not buf.startswith( + tuple(self._ignore_response)) and '' not in self._ignore_response: + start = buffer.index(buf) + self.logger.log(VERBOSE2, + "Processing Response {}: Testing forcebuffer {}. Bufferlist: {}. Start: {}".format( + self._name, buf, bufferlist, start)) + if not buffer.find('\r\n', start) == -1: + end = buffer.index('\r\n', start) + if not buffer[start:end] in bufferlist and not buffer[start:end] in line: + bufferlist.append(buffer[start:end]) + else: + if not buffer[start:] in bufferlist and not buffer[start:] in line: + bufferlist.append(buffer[start:]) + self.logger.debug( + "Processing Response {}: Forcebuffer {} FOUND in buffer. Bufferlist: {}. Buffer: {}".format( + self._name, buf, bufferlist, re.sub('[\r\n]', ' --- ', buffer))) + except Exception as err: + self.logger.warning( + "Processing Response {}: Problems while buffering. Error: {}".format(self._name, + err)) + buffer = tidy('\r\n'.join(bufferlist)) if bufferlist else tidy(buffer) + self.logger.log(VERBOSE2, "Processing Response {}: Tidied entry without buffer: {}".format( + self._name, buffer)) + + if '{}\r\n'.format(line) == buffer: + buffer = '' + self.logger.log(VERBOSE1, + "Processing Response {}: Clearing buffer because it's the same as Line: {}".format( + self._name, line)) + + line = re.sub('[\\n\\r]', '', line).strip() + responseforsending = False + for entry in self._response_commands: + newentry = Translate(line, entry, self._name, '', '').wildcard() + self._response_wildcards['wildcard'].update({newentry: entry}) + self._response_wildcards['original'].update({entry: newentry}) + responsecommands = list(self._response_wildcards['wildcard'].keys()) + responsecommands = [value for value in responsecommands if '?' not in value] + self.logger.log(VERBOSE1, + "Processing Response {}: New Response Command list after processing wildcard: {}".format( + self._name, responsecommands)) + try: + for resp in ','.join(self._sendingcommand.split(';')[0].split(',')[2:]).split('|'): + resp = resp.split(',')[0] + resp = Translate(line, resp, self._name, '', '').wildcard() if len(line) == len( + resp) else resp + self.logger.log(VERBOSE2, + "Processing Response {}: Testing sendingcommand {}. Line: {}, expected response: {}".format( + self._name, self._sendingcommand, line, resp)) + responseforsending = True if line == resp else False + except Exception as err: + self.logger.log(VERBOSE2, + "Processing Response {}: Problem comparing line {}. Message {}".format( + self._name, line, err)) + try: + displaycheck = expectedsplit[0] if buffer == '' else 'nodisplaycommandexpectedsofar' + except Exception: + displaycheck = 'nodisplaycommandexpectedsofar' + cond1 = not line.startswith(tuple(responsecommands)) + cond2 = line not in self._error_response and responseforsending is False + cond3 = line.startswith(self._special_commands['Display']['Command']) + cond4 = self._response_buffer is not False and not line.startswith(displaycheck) + cond5 = not self._special_commands['Display']['Command'] == '' + if cond1 and cond2: + self.logger.log(VERBOSE1, + "Processing Response {}: Response {} is not in possible responses for items. Sending Command: {}".format( + self._name, line, self._sendingcommand)) + elif line in self._error_response and '' not in self._error_response: + self.logger.debug( + "Processing Response {}: Response {} is in Error responses.".format(self._name, line)) + yield "{}".format(line) + elif cond3 and cond4 and cond5: + buffering = False + buffer = tidy(buffer + '\r\n{}\r\n'.format(line)) + self.logger.log(VERBOSE1, "Processing Response {}: Append Display info {} to buffer: {}".format( + self._name, line, re.sub('[\r\n]', ' --- ', buffer))) + elif line.startswith(tuple(self._ignore_response)) and '' not in self._ignore_response: + try: + keyfound = False + compare = ','.join(self._send_commands[0].split(';')[0].split(',')[2:]).split('|') + for comp in compare: + comp = Translate(line, comp.split(',')[0], self._name, '', '').wildcard() + keyfound = True if line.startswith(comp) else False + if keyfound is True: + self.logger.log(VERBOSE1, + "Processing Response {}: Sendcommands: {} Keep command {}".format( + self._name, self._send_commands, self._keep_commands)) + for entry in self._keep_commands: + if self._send_commands[0] in self._keep_commands.get(entry): + self._keep_commands.pop(entry) + self.logger.log(VERBOSE1, + "Processing Response {}: Removed Keep command {} from {}" + " because command sent successfully".format( + self._name, entry, self._keep_commands)) + break + self._send_commands.pop(0) + self._sendingcommand = 'done' + sending = self._send('command', 'commandremoval') + self.logger.debug( + "Processing Response {}: Response {} is same as expected {} and defined as response" + " to be ignored. Removing command from send list. It is now: {}. Ignore responses are: {}." + " Sending return: {}".format( + self._name, line, compare, self._send_commands, self._ignore_response, sending)) + + except Exception as err: + self.logger.log(VERBOSE2, + "Processing Response {}: Response {} is ignored because ignore responses is {}." + " Command list is now: {}. Message: {}".format( + self._name, line, self._ignore_response, self._send_commands, err)) + else: + if self._response_buffer is False and not buffer.startswith( + tuple(self._force_buffer)) and '' not in self._force_buffer: + buffering = False + self.logger.log(VERBOSE1, "Processing Response {}: Clearing buffer: {}".format( + self._name, re.sub('[\r\n]', ' --- ', buffer))) + buffer = '\r\n' + self.logger.log(VERBOSE1, + "Processing Response {}: Sending back line: {}.".format(self._name, line)) + yield "{}".format(line) + else: + try: + more = '\r\n' + if self._rs232 and (socket == self._serialwrapper or socket == self._serial): + more = socket.readline().decode('utf-8') if socket == self._serial else socket.read() + if self._tcp and socket == self._tcp: + more = socket.recv(4096).decode('utf-8') + morelist = more.split("\r\n") + buffer += '\r\n' if buffer.find('\r\n') == -1 and len(buffer) > 0 else '' + buffer += '\r\n'.join([x[0] for x in itertools.groupby(morelist)]) + except Exception: + pass + finally: + buffering = False + self.logger.log(VERBOSE1, "Processing Response {}: Buffering false. Buffer: {}".format( + self._name, re.sub('[\r\n]', ' --- ', buffer))) + + if not buffer == '\r\n' and (self._response_buffer is True or type(self._response_buffer) is int): + buffer = tidy(buffer) + bufferlist = buffer.split('\r\n') + # Removing everything except last x lines + maximum = abs(self._response_buffer) if type(self._response_buffer) is int else 11 + # Removing empty entries + bufferlist = list(filter(lambda a: a != '', bufferlist)) + newbuffer = [buf for buf in bufferlist if not buf.startswith(tuple(self._ignore_response)) and + '' not in self._ignore_response and + buf.startswith(tuple(self._response_commands))] + bufferlist = newbuffer[-1 * max(min(len(newbuffer), maximum), 0):] + buffering = False + if bufferlist: + self._expected_response = CreateExpectedResponse('\r\n'.join(bufferlist), self._name, + self._send_commands).create_expected() + for buf in bufferlist: + cond1 = not re.sub('[ ]', '', buf) == '' + cond2 = not buf.startswith(tuple(self._ignore_response)) + cond3 = '' not in self._ignore_response + if cond1 and cond2 and cond3: + self.logger.log(VERBOSE1, + "Processing Response {}: Sending back {} from buffer because " + "Responsebuffer is activated. Expected response updated {}.".format( + self._name, buf, self._expected_response)) + self._wait(0.2) + yield buf + + elif not buffer == '\r\n': + buffer = tidy(buffer) + bufferlist = buffer.split('\r\n') + # Removing everything except last x lines + maximum = abs(self._response_buffer) if type(self._response_buffer) is int else 11 + multiplier = 1 if self._response_buffer >= 0 else -1 + bufferlist = bufferlist[multiplier * max(min(len(bufferlist), maximum), 0):] + buffering = False + for buf in bufferlist: + if not re.sub('[ ]', '', buf) == '' and not buf.startswith( + tuple(self._ignore_response)) and '' not in self._ignore_response: + self.logger.debug( + "Processing Response {}: Sending back {} from filtered buffer: {}.".format( + self._name, buf, re.sub('[\r\n]', ' --- ', buffer))) + self._wait(0.2) + yield buf + except Exception as err: + self.logger.error("Processing Response {}: Problems: {} in line {}.".format( + self._name, err, sys.exc_info()[-1].tb_lineno)) + + # init function + def _initialize(self): + self._send_commands[:] = [] + self._sendingcommand = 'done' + self._functions, self._number_of_zones, self._specialparse = self.init.read_commandfile() + self._response_commands, self._special_commands = self.init.create_responsecommands() + self._power_commands = self.init.create_powercommands() + self._query_commands, self._query_zonecommands = self.init.create_querycommands() + self.logger.log(VERBOSE1, + "Initializing {}: Functions: {}, Number of Zones: {}".format(self._name, self._functions, + self._number_of_zones)) + self.logger.log(VERBOSE1, "Initializing {}: Responsecommands: {}.".format(self._name, self._response_commands)) + self.logger.log(VERBOSE1, "Initializing {}: Special Commands: {}".format(self._name, self._special_commands)) + self.logger.log(VERBOSE1, "Initializing {}: Special Parsing: {}".format(self._name, self._specialparse)) + self.logger.log(VERBOSE1, "Initializing {}: Powercommands: {}".format(self._name, self._power_commands)) + self.logger.log(VERBOSE1, + "Initializing {}: Querycommands: {}, Query Zone: {}".format(self._name, self._query_commands, + self._query_zonecommands)) + problems = {'zone3': {}, 'zone1': {}, 'zone2': {}, 'zone0': {}} + new = {'zone3': {}, 'zone1': {}, 'zone2': {}, 'zone0': {}} + for zone in self._init_commands: + try: + for command in self._init_commands[zone]: + try: + self._init_commands[zone][command]['Item'] = self._items[zone][command]['Item'] + except Exception as err: + problems[zone] = command + self.logger.error( + "Initializing {}: Problems occured with init command {} for {}.".format(self._name, err, + zone)) + except Exception as err: + self.logger.debug("Initializing {}: No init commands set. Message: {}".format(self._name, err)) + for zone in self._init_commands: + new[zone] = {k: v for k, v in self._init_commands[zone].items() if k not in problems[zone]} + self._init_commands = new + self.logger.log(VERBOSE1, "Initializing {}: Initcommands: {}".format(self._name, self._init_commands)) + return True + + # Run function + def run(self): + if self._tcp is None and self._rs232 is None: + self.logger.error( + "Initializing {}: Neither IP address nor RS232 port given. Not running.".format(self._name)) + else: + self._items, self._dependencies = self.init.process_items() + initdone = self._initialize() + self.logger.log(VERBOSE1, "Initializing {}: Init done: {}".format(self._name, initdone)) + self.logger.log(VERBOSE1, "Initializing {}: Items: {}".format(self._name, self._items)) + self._dependencies = self.init.update_dependencies(self._dependencies) + self.logger.log(VERBOSE1, + "Initializing {}: Updated Dependencies: {}".format(self._name, self._dependencies)) + self.logger.log(VERBOSE1, "Initializing {}: Speaker Items: {}".format(self._name, self._items_speakers)) + try: + try: + self._dependson = self.itemsApi.return_item(self._dependson) + self.logger.debug("Initializing {}: Dependson Item: {}.".format(self._name, self._dependson)) + except Exception: + self._dependson = None + self.logger.warning( + "Initializing {}: Dependson Item {} is no valid item.".format(self._name, self._dependson)) + self.logger.debug("Initializing {}: Running".format(self._name)) + self.alive = True + except Exception as err: + self.logger.error( + "Initializing {}: Problem running and creating items. Error: {}".format(self._name, err)) + finally: + if self._tcp is not None or self._rs232 is not None: + self.connect('run') + + # Triggering TCP or RS232 connection schedulers + def connect(self, trigger): + self._trigger_reconnect = True + if not self._is_connected: + self._parsinginput = [] + self._is_connected.append('Connecting') + self.logger.log(VERBOSE1, "Connecting {}: Starting to connect. Triggered by {}. Current Connections: {}".format( + self._name, trigger, self._is_connected)) + depending = self._checkdependency(self._dependson, 'connect') + if depending is False: + if self._tcp is not None and 'TCP' not in self._is_connected: + self.logger.log(VERBOSE1, "Connecting {}: Starting TCP scheduler".format(self._name)) + self._sh.scheduler.add('avdevice-tcp-reconnect', self.connect_tcp, cycle=7) + self._sh.scheduler.change('avdevice-tcp-reconnect', active=True) + self._sh.scheduler.trigger('avdevice-tcp-reconnect') + self._trigger_reconnect = False + if self._rs232 is not None and 'Serial' not in self._is_connected: + self.logger.log(VERBOSE1, "Connecting {}: Starting RS232 scheduler".format(self._name)) + self._sh.scheduler.add('avdevice-serial-reconnect', self.connect_serial, cycle=7) + self._sh.scheduler.change('avdevice-serial-reconnect', active=True) + self._sh.scheduler.trigger('avdevice-serial-reconnect') + self._trigger_reconnect = False + elif depending is True and trigger == 'parse_dataerror': + self._resetondisconnect('connect') + + # Connect to TCP IP + def connect_tcp(self): + try: + if self._tcp is not None and 'TCP' not in self._is_connected: + socket = __import__('socket') + self.logger.log(VERBOSE1, "Connecting TCP {}: Starting to connect to {}.".format(self._name, self._tcp)) + self._tcpsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self._tcpsocket.setblocking(0) + self._tcpsocket.settimeout(6) + self._tcpsocket.connect(('{}'.format(self._tcp), int(self._port))) + self._tcpsocket.settimeout(self._tcp_timeout) + self._is_connected.append('TCP') + try: + self._is_connected.remove('Connecting') + except Exception: + pass + self.logger.info("Connecting TCP {}: Connected to {}:{}".format( + self._name, self._tcp, self._port)) + + except Exception as err: + if 'TCP' in self._is_connected: + self._is_connected.remove('TCP') + self.logger.warning("Connecting TCP {}: Could not connect to {}:{}. Error:{}. Counter: {}/{}".format( + self._name, self._tcp, self._port, err, self._reconnect_counter, self._reconnect_retries)) + + finally: + cond1 = 'TCP' not in self._is_connected and self._tcp is not None + cond2 = str(self._auto_reconnect).lower() in ['1', 'yes', 'true', 'on'] + cond3 = 'TCP' in self._is_connected and self._tcp is not None + cond4 = self._reconnect_counter >= self._reconnect_retries + if cond1 and cond2: + self._trigger_reconnect = False + self.logger.warning("Connecting TCP {}: Reconnecting. Command list while connecting: {}.".format( + self._name, self._send_commands)) + elif cond3 or cond4: + self._sh.scheduler.change('avdevice-tcp-reconnect', active=False) + self._reconnect_counter = 0 + if cond4: + self._addorremove_keepcommands('disconnect', 'all') + else: + self._addorremove_keepcommands('connected', 'all') + self._trigger_reconnect = True + self.logger.debug( + "Connecting TCP {}: Deactivating reconnect scheduler. Command list while connecting: {}. " + "Keep Commands: {}. Reconnecttrigger: {}".format( + self._name, self._send_commands, self._keep_commands, self._trigger_reconnect)) + self._reconnect_counter += 1 + if 'TCP' in self._is_connected: + self.logger.debug("Connecting TCP {}: TCP is connected.".format(self._name)) + if not self._parsinginput: + self.logger.debug("Connecting TCP {}: Starting Parse Input.".format(self._name)) + self._parse_input_init('tcpconnect') + + # Connect to RS232 + def connect_serial(self): + try: + if self._rs232 is not None and 'Serial' not in self._is_connected: + serial = __import__('serial') + ser = serial.serial_for_url('{}'.format(self._rs232), baudrate=int(self._baud), + timeout=float(self._timeout), write_timeout=float(self._timeout)) + i = 0 + try: + command = self._power_commands[0].split(',')[1] + self.logger.debug("Connecting Serial {}: Starting to connect to {} with init command {}.".format( + self._name, self._rs232, command)) + except Exception: + self.logger.warning( + "Connecting Serial {}: No Powercommands found. Please check your config files!".format( + self._name)) + command = '?P' + while ser.in_waiting == 0: + i += 1 + self._wait(0.5) + ser.write(bytes('{}\r'.format(command), 'utf-8')) + # buffer = bytes() + buffer = ser.read().decode('utf-8') + self.logger.log(VERBOSE1, + "Connecting Serial {}: Buffer: {}. Reconnecting Retry: {}.".format( + self._name, re.sub('[\r\n]', ' --- ', buffer), i)) + if i >= 4: + ser.close() + self.logger.log(VERBOSE1, + "Connecting Serial {}: Ran through several retries.".format(self._name)) + break + if ser.isOpen(): + self._serialwrapper = io.TextIOWrapper(io.BufferedRWPair(ser, ser), newline='\r\n', + encoding='utf-8', line_buffering=True) + self._serialwrapper.timeout = 0.1 + self._serial = ser + self._trigger_reconnect = False + if 'Serial' not in self._is_connected: + self._is_connected.append('Serial') + try: + self._is_connected.remove('Connecting') + except Exception: + pass + self.logger.info("Connecting Serial {}: Connected to {} with baudrate {}.".format( + self._name, ser, self._baud)) + else: + self.logger.warning( + "Connecting Serial {}: Serial port is not open. Connection status: {}. Reconnect Counter: {}".format( + self._name, self._is_connected, self._reconnect_counter)) + except Exception as err: + if 'Serial' in self._is_connected: + self._is_connected.remove('Serial') + self.logger.warning( + "Connecting Serial {}: Could not connect to {}, baudrate {}. Error:{}, Counter: {}/{}".format( + self._name, self._rs232, self._baud, err, self._reconnect_counter, self._reconnect_retries)) + + finally: + cond1 = 'Serial' not in self._is_connected and self._rs232 is not None + cond2 = str(self._auto_reconnect).lower() in ['1', 'yes', 'true', 'on'] + cond3 = 'Serial' in self._is_connected and self._rs232 is not None + cond4 = self._reconnect_counter >= self._reconnect_retries + if cond1 and cond2: + self._trigger_reconnect = False + self.logger.log(VERBOSE1, + "Connecting Serial {}: Activating reconnect scheduler. Command list while connecting: {}.".format( + self._name, self._send_commands)) + elif cond3 or cond4: + self._sh.scheduler.change('avdevice-serial-reconnect', active=False) + self._reconnect_counter = 0 + if cond4: + self._addorremove_keepcommands('disconnect', 'all') + else: + self._addorremove_keepcommands('connected', 'all') + self._trigger_reconnect = True + self.logger.debug( + "Connecting Serial {}: Deactivating reconnect scheduler. Command list while connecting: {}. " + "Keep commands: {}. Reconnecttrigger: {}".format( + self._name, self._send_commands, self._keep_commands, self._trigger_reconnect)) + self._reconnect_counter += 1 + if 'Serial' in self._is_connected: + self.logger.debug("Connecting Serial {}: Serial is connected.".format(self._name)) + if not self._parsinginput: + self.logger.debug("Connecting Serial {}: Starting Parse Input.".format(self._name)) + self._parse_input_init('serialconnect') + + def _checkdependency(self, dep_function, dep_type): + depending = False + self.logger.log(VERBOSE2, + "Checking Dependency {}: dep_function: {}, dep_type: {}.".format(self._name, dep_function, + dep_type)) + cond1 = dep_type == 'statusupdate' or dep_type == 'initupdate' or dep_type == 'checkquery' or dep_type == 'keepcommand' + cond2 = dep_type == 'update' and not dep_function == '' + if cond1 or cond2: + totest = queryzone = orig_function = dependitem = stopdepend = None + if dep_type == 'statusupdate' or dep_type == 'initupdate': + totest = self._dependencies['Slave_query'] + elif dep_type == 'update': + totest = self._dependencies['Slave_item'] + dep_function = dep_function.id() + elif dep_type == 'keepcommand': + totest = self._dependencies['Slave_item'] + try: + dep_function = dep_function.split(';')[1] + except Exception: + return False + elif dep_type == 'checkquery': + orig_function = dep_function + totest = self._dependencies['Master_function'] + queryzone = orig_function.split(', ')[0] + dep_function = orig_function.split(', ')[1] + + for zone in totest: + cond1 = dep_function in totest[zone] and not dep_type == 'checkquery' + cond2 = dep_type == 'checkquery' and zone == queryzone and dep_function in totest[zone] + if cond1 or cond2: + donedependitems = [] + dependtotal = comparetotal = 0 + groupcount = {'a': 0, 'b': 0, 'c': 0, 'd': 0} + grouptotal = {'a': 0, 'b': 0, 'c': 0, 'd': 0} + dependitems = {'a': {}, 'b': {}, 'c': {}, 'd': {}} + for entry in totest[zone][dep_function]: + try: + func = entry['Function'] + if func.lower() == 'init' and dep_type == 'initupdate': + self.logger.log(VERBOSE2, + "Checking Dependency {}: Adding query because it's init dependency is set to true.".format( + self._name)) + return False + elif dep_type == 'initupdate' and self._statusquery is False: + self.logger.log(VERBOSE2, + "Checking Dependency {}: Not adding query because no init dependency defined.".format( + self._name)) + return True + except Exception: + pass + try: + dependitem = entry['Item'] + stopdepend = entry['Item'] + if not dep_type == 'checkquery': + try: + dependvalue = dependitem() + except Exception: + dependvalue = None + else: + dependvalue = orig_function.split(', ')[2] + try: + dependvalue = eval(dependvalue.lstrip('0')) + except Exception: + pass + expectedvalue = entry['Dependvalue'] + compare = entry['Compare'] + group = entry['Group'] + grouptotal[group] += 1 if dependitem not in donedependitems else 0 + self.logger.log(VERBOSE2, + "Checking Dependency {}: first: dependitem: {} expvalue: {}, dependvalue: {}, compare {}.".format( + self._name, dependitem, expectedvalue, dependvalue, compare)) + try: + expectedvalue = eval(expectedvalue.lstrip('0')) + except Exception: + pass + if type(dependvalue) == type(expectedvalue): + groupcount[group] += 1 if (dependvalue == expectedvalue and compare == '==') or \ + (dependvalue >= expectedvalue and compare == '>=') or \ + (dependvalue <= expectedvalue and compare == '<=') or \ + (dependvalue < expectedvalue and compare == '<') or \ + (dependvalue > expectedvalue and compare == '>') or \ + (not dependvalue == expectedvalue and compare == '!=') \ + else 0 + if not dep_type == 'checkquery': + try: + dependitems[group][dependitem].append([dependvalue, compare, expectedvalue]) + except Exception: + dependitems[group].update({dependitem: [[dependvalue, compare, expectedvalue]]}) + except Exception as err: + depending = False + self.logger.warning( + "Checking Dependency {}: Adding primary {} (depending on {}) in {} caused problem: {}.".format( + self._name, entry['Function'], dep_function, zone, err)) + + if dep_type == 'checkquery' and dependitem not in donedependitems: + primarycount = sum(groupcount.values()) + groupcount = {'a': 0, 'b': 0, 'c': 0, 'd': 0} + grouptotal = {'a': 0, 'b': 0, 'c': 0, 'd': 0} + additional_zone = entry['Zone'] + try: + for additional in self._dependencies['Slave_item'][additional_zone][dependitem.id()]: + dependitem = additional['Item'] + dependvalue = dependitem() + expectedvalue = additional['Dependvalue'] + compare = additional['Compare'] + group = additional['Group'] + grouptotal[group] += 1 + self.logger.log(VERBOSE2, + "Checking Dependency {}: zone: {}, additional: dependitem: {} expvalue: {}, dependvalue: {}, compare {}.".format( + self._name, additional_zone, dependitem, expectedvalue, + dependvalue, compare)) + try: + expectedvalue = eval(expectedvalue.lstrip('0')) + except Exception: + pass + for x in self._functions[zone]: + if self._functions[zone][x][1] == additional['Function']: + try: + dict_entry = self._functions[zone][x][10] + break + except Exception: + dict_entry = None + else: + dict_entry = None + expectedvalue = Translate(expectedvalue, dict_entry, self._name, 'parse', + self._specialparse).translate() or expectedvalue + self.logger.log(VERBOSE2, + "Checking Dependency {}: Expectedvalue after Translation {}. Dependitem: {}, expected {}".format( + self._name, expectedvalue, dependitem, expectedvalue)) + if type(dependvalue) == type(expectedvalue): + groupcount[group] += 1 if (dependvalue == expectedvalue and compare == '==') or \ + (dependvalue >= expectedvalue and compare == '>=') or \ + (dependvalue <= expectedvalue and compare == '<=') or \ + (dependvalue < expectedvalue and compare == '<') or \ + (dependvalue > expectedvalue and compare == '>') or \ + (not dependvalue == expectedvalue and compare == '!=') \ + else 0 + try: + dependitems[group][dependitem].append([dependvalue, compare, expectedvalue]) + except Exception: + dependitems[group].update({dependitem: [[dependvalue, compare, expectedvalue]]}) + except Exception as err: + depending = False + self.logger.warning( + "Checking Dependency {}: Adding {} (depending on {}) in {} caused problem: {}.".format( + self._name, entry['Function'], dep_function, zone, err)) + self.logger.log(VERBOSE2, + "Checking Dependency {}: Zone: {}, Groupcount: {}, Grouptotal: {}. Primarycount: {}".format( + self._name, additional_zone, groupcount, grouptotal, primarycount)) + comparetotal = 0 + dependtotal = 0 + for group in grouptotal: + if grouptotal[group] > 0: + comparetotal += 1 + dependtotal += 1 if groupcount.get(group) > 0 else 0 + try: + queryentry = entry['Query'] + except Exception as err: + self.logger.log(VERBOSE2, + "Checking Dependency {}: Dependent functions found for {}. " + "But no Query command for {}. Message: {}".format( + self._name, dep_function, entry['Function'], err)) + queryentry = None + if dependtotal == comparetotal: + if primarycount > 0 and queryentry is not None: + if queryentry not in self._send_commands: + self._send_commands.append(queryentry) + self.logger.debug( + "Checking Dependency {}: Dependent Query command {} added to Send Commands. Dependencies: {}".format( + self._name, queryentry, dependitems)) + else: + self.logger.log(VERBOSE2, + "Checking Dependency {}: Dependent Query command {} already in send commands: {}.".format( + self._name, queryentry, self._send_commands)) + else: + self.logger.log(VERBOSE2, + "Checking Dependency {}: Primary dependency not fullfilled," + " not adding or removing query {}".format(self._name, queryentry)) + elif primarycount == 0 and queryentry is not None: + try: + self._send_commands.remove(queryentry) + self._clearbuffer = True + self.logger.debug( + "Checking Dependency {}: Dependent Query command {} removed from Send Commands. Dependencies: {}".format( + self._name, queryentry, self._send_commands, dependitems)) + except Exception: + self.logger.log(VERBOSE2, + "Checking Dependency {}: Dependent Query command {} not in Send Commands, not removing it." + " Dependencies: {}".format(self._name, queryentry, dependitems)) + else: + self.logger.log(VERBOSE2, + "Checking Dependency {}: Primary dependency not fullfilled. Doing nothing.".format( + self._name)) + donedependitems.append(stopdepend) + groupcount = {'a': 0, 'b': 0, 'c': 0, 'd': 0} + grouptotal = {'a': 0, 'b': 0, 'c': 0, 'd': 0} + dependitems = {'a': {}, 'b': {}, 'c': {}, 'd': {}} + if not dep_type == 'checkquery': + self.logger.log(VERBOSE2, + "Checking Dependency {}: Groupcount: {}, Grouptotal: {}.".format( + self._name, groupcount, grouptotal)) + comparetotal = 0 + dependtotal = 0 + for group in grouptotal: + if grouptotal[group] > 0: + comparetotal += 1 + dependtotal += 1 if groupcount.get(group) > 0 else 0 + if dependtotal == comparetotal and not dep_type == 'checkquery': + depending = False + self.logger.log(VERBOSE1, + "Checking Dependency {}: Adding function {} because dependency fullfilled: {}.".format( + self._name, dep_function, dependitems)) + elif not dep_type == 'checkquery': + depending = True + self.logger.debug( + "Checking Dependency {}: Not adding function {} because dependency not fullfilled: {}".format( + self._name, dep_function, dependitems)) + if depending is True and dep_type == 'update': + self.logger.log(VERBOSE2, + "Checking Dependency {}: Starting to reset item: {}.".format(self._name, + dep_function)) + self._resetitem(dep_function) + elif dep_type == 'initupdate' and self._statusquery is False: + depending = True + + elif dep_type == 'globaldepend' or dep_type == 'parseinput' or dep_type == 'connect' or dep_type == 'dependitem': + try: + dependsvalue = self._dependson() + self.logger.debug( + "Checking Dependency {}: Connection depends on {}. It's value is {}, has to be {}. Connections are {}".format( + self._name, self._dependson, dependsvalue, self._dependson_value, self._is_connected)) + if dependsvalue == self._dependson_value: + depending = False + if dep_type == 'dependitem': + try: + eval(self._items['zone0']['statusupdate']['Item'])(1, 'Depending', + self._rs232 or self._tcp) + except Exception: + try: + self._items['zone0']['statusupdate']['Item'](1, 'Depending', + self._rs232 or self._tcp) + except Exception: + pass + else: + depending = True + try: + item = self.itemsApi.return_item(dep_function).id() + except Exception: + item = dep_function.id() + if not item == self._dependson.id(): + self.logger.log(VERBOSE2, + "Checking Dependency {}: Starting to reset item: {}.".format(self._name, item)) + self._resetitem(item) + if dep_type == 'connect': + self._is_connected = [] + self._parsinginput = [] + if dep_type == 'parseinput' or dep_type == 'dependitem': + self._resetondisconnect('parseinput') + except Exception as e: + depending = False + self.logger.log(VERBOSE1, + "Checking Dependency {}: Globally assigned Dependency is false. Message: {}".format( + self._name, e)) + self.logger.log(VERBOSE2, "Checking Dependency {}: Returning {}".format(self._name, depending)) + return depending + + # Updating Status even if no statusupdate is defined in device text file + def _statusupdate(self, value, trigger, caller): + self.logger.debug( + "Statusupdate {}: Value: {}. Trigger from {}. Caller: {}".format(self._name, value, trigger, caller)) + self.update_item('statusupdate', 'Init') + + # Adding Keep Commands to Send Commands + def _addorremove_keepcommands(self, trigger, zone): + self.logger.log(VERBOSE1, + "Keep Commands {}: Trigger from {} for zone {}. Send Commands: {}".format( + self._name, trigger, zone, self._send_commands)) + if trigger == 'removefromkeep': + deletekeep = [] + data = zone + for zeit in self._keep_commands: + self.logger.log(VERBOSE1, + "Parsing Input {}: Testing Keep Command {} with age of {}s".format( + self._name, zeit, int(time.time() - zeit))) + if data in self._keep_commands.get(zeit).split(',')[2].split('|'): + self.logger.debug( + "Parsing Input {}: Removing {} from Keep Commands {} because corresponding value received.".format( + self._name, zeit, self._keep_commands)) + deletekeep.append(zeit) + elif time.time() - zeit >= self._secondstokeep: + self.logger.debug( + "Parsing Input {}: Removing {} from Keep Commands {} because age is {}s.".format( + self._name, zeit, self._keep_commands, int(time.time() - zeit))) + deletekeep.append(zeit) + for todelete in deletekeep: + self._keep_commands.pop(todelete) + elif trigger == 'addtokeep' or trigger == 'disconnect': + for command in self._send_commands: + self.logger.log(VERBOSE1, + "Parsing Input {}: Going to reset in the end because connection is lost: {}.".format( + self._name, command)) + cond1 = command not in self._query_commands + cond2 = command not in self._special_commands['Display']['Command'] + cond3 = self._sendingcommand == 'gaveup' + if cond1 and cond2 and not cond3: + self._keep_commands[time.time()] = self._sendingcommand = command + self.logger.debug( + "Parsing Input {}: Removing item {} from send command because not connected, storing in keep commands: {}.".format( + self._name, command, self._keep_commands)) + if not self._send_commands[0].split(',')[0] == self._send_commands[0].split(',')[1]: + self._resetitem('') + self._send_commands.pop(0) + self.logger.debug( + 'Parsing Input {}: First entry from send_commands removed. Send commands are now: {}'.format( + self._name, self._send_commands)) + else: + keeptemp = [] + for zeit in self._keep_commands: + keeping = False + if time.time() - zeit <= self._secondstokeep and not self._keep_commands[zeit] in keeptemp: + try: + for itemlist in self._query_zonecommands['{}'.format(zone)]: + keeping = True if itemlist.split(',')[1] == self._keep_commands[zeit].split(',')[1] else False + except Exception: + self.logger.log(VERBOSE2, "Keep Commands {}: Zone is set to all.".format(self._name)) + try: + keeping = not self._checkdependency(self._keep_commands[zeit], 'keepcommand') + except Exception as err: + self.logger.log(VERBOSE2, "Keep Commands {}: Problem checking dependency: {}.".format(self._name, err)) + if zone == 'all' or keeping is True or trigger == 'powercommand': + keeping = True + keeptemp.append(self._keep_commands[zeit]) + self.logger.debug("Keep Commands {}: Age {}s of command {}. Secondstokeep: {}. Keeping command: {}".format( + self._name, int(time.time() - zeit), self._keep_commands[zeit], self._secondstokeep, keeping)) + self._send_commands = self._send_commands + list(set(keeptemp)) + seen = set() + self._send_commands = [x for x in self._send_commands if x not in seen and not seen.add(x)] + self._keep_commands = {} + + # Parsing the response and comparing it with expected response + def _parse_input_init(self, trigger): + if not self._is_connected == [] and not self._is_connected == ['Connecting']: + self._parsinginput.append(trigger) + else: + self._parsinginput = [] + self.logger.log(VERBOSE1, "Parsing Input {}: Init Triggerd by these functions so far: {}".format( + self._name, self._parsinginput)) + if trigger == 'tcpconnect' or trigger == 'serialconnect': + for zone in self._init_commands: + if len(self._init_commands[zone].keys()) > 0: + for init in self._init_commands[zone]: + try: + initvalue = self._init_commands[zone][init]['Inititem']() + self.logger.log(VERBOSE1, + "Parsing Input {}: Starting eval init: {} for {} with value {}".format( + self._name, init, zone, initvalue)) + eval(self._init_commands[zone][init]['Item'])(initvalue, 'Init', self._tcp) + self.logger.debug( + "Parsing Input {}: Updated Item after connection: {} with value {}. Commandlist: {}".format( + self._name, self._init_commands[zone][init]['Item'], initvalue, + self._send_commands)) + except Exception as err: + try: + initvalue = self._init_commands[zone][init]['Inititem']() + self.logger.log(VERBOSE1, + "Parsing Input {}: Starting exception init: {} for {}. Message: {}".format( + self._name, init, zone, err)) + self._init_commands[zone][init]['Item'](initvalue, 'Init', self._tcp) + self.logger.debug( + "Parsing Input {}: Updated Item after connection: {} with value {}. Commandlist: {}".format( + self._name, self._init_commands[zone][init]['Item'], initvalue, + self._send_commands)) + except Exception as err: + self.logger.log(VERBOSE1, + "Parsing Input {}: No init defined, not executing command after {}. Message: {}".format( + self._name, trigger, err)) + try: + self.logger.log(VERBOSE1, "Parsing Input {}: Starting eval statusupdate.".format(self._name)) + eval(self._items['zone0']['statusupdate']['Item'])(1, 'Init', self._tcp) + self.logger.debug( + "Parsing Input {}: Updated Item after connection: {} with value 1. Commandlist: {}".format( + self._name, self._items['zone0']['statusupdate']['Item'], self._send_commands)) + except Exception: + try: + self.logger.log(VERBOSE1, "Parsing Input {}: Starting exception statusupdate.".format(self._name)) + self._items['zone0']['statusupdate']['Item'](1, 'Init', self._tcp) + self.logger.debug( + "Parsing Input {}: Updated Item after connection: {} with value 1. Commandlist: {}".format( + self._name, self._items['zone0']['statusupdate']['Item'], self._send_commands)) + except Exception as err: + self.logger.log(VERBOSE1, + "Parsing Input {}: No statusupdate defined, not querying status after {}. Message: {}".format( + self._name, trigger, err)) + if len(self._parsinginput) == 1: + self._parse_input(trigger) + + def _checkforerror(self, _data, depending=False): + if self._resend_counter >= self._resend_retries or depending is True: + self.logger.warning( + "Parsing Input {}: Giving up Sending {} and removing from list. Original Commandlist: {}".format( + self._name, self._sendingcommand, self._send_commands)) + self._resend_counter = 0 + self.logger.log(VERBOSE1, + "Parsing Input {}: Resetting Resend Counter because maximum retries exceeded.".format(self._name)) + try: + cond1 = self._send_commands[0] not in self._query_commands + cond2 = self._send_commands[0] not in self._special_commands['Display']['Command'] + if cond1 and cond2: + self._sendingcommand = self._send_commands[0] + if self._reset_onerror is True: + self._resetitem('') + self._keep_commands[time.time()] = self._send_commands[0] + self.logger.debug( + "Parsing Input {}: Giving up and removing item from send command, storing in keep commands: {}.".format( + self._name, self._keep_commands)) + self._send_commands.pop(0) + try: + self._expected_response.pop(0) + except Exception: + pass + if not self._send_commands == []: + sending = self._send('command', 'parseinput') + self.logger.log(VERBOSE1, + "Parsing Input {}: Command List is now: {}. Sending return is {}.".format( + self._name, self._send_commands, sending)) + except Exception as err: + self.logger.debug( + "Parsing Input {}: Nothing to remove from Send Command List. Error: {}".format(self._name, err)) + if self._reset_onerror is True: + self._resetitem('') + self._sendingcommand = 'gaveup' + if _data == 'ERROR': + connectionproblem = True + if self._trigger_reconnect is True: + self.logger.log(VERBOSE1, + "Parsing Input {}: Trying to connect while parsing item".format(self._name)) + self.connect('parse_input') + else: + connectionproblem = False + return connectionproblem + else: + return False + + # Parsing the response and comparing it with expected response + def _parse_input(self, trigger): + self.logger.log(VERBOSE1, "Parsing Input {}: Triggerd by {}".format(self._name, trigger)) + + def _deletecommands(_del_expectedresponse, _del_data, _del_valuetype): + self.logger.log(VERBOSE2, "Parsing Input {}: del_expectedresponse: {}, del_data: {}, del_valuetype: {}".format( + self._name, _del_expectedresponse, _del_data, _del_valuetype)) + + def _foundappend(_foundexpected, _data): + parse_expectedlist = _foundexpected.split('|') + _found = [] + try: + for expectedpart in parse_expectedlist: + try: + datalength = self._response_commands[expectedpart][0][1] + expectedlength = [] + stringvalue = [] + + for vals in self._response_commands[expectedpart]: + stringvalue.append(True if int(vals[0]) == 100 or int( + vals[1]) == 100 else False) + expectedlength.append(int(vals[1])) + datalength = int(vals[2]) if datalength > int( + vals[2]) > 0 else datalength + self.logger.log(VERBOSE2, + "Parsing Input {}: Comparing Data {} (cut: {}) to: {}," + " expectedlength: {}, datalength: {}, string: {}.".format( + self._name, _data, _data[:datalength], + expectedpart, expectedlength, len(_data), + stringvalue)) + if _data[:datalength].startswith(expectedpart) and ( + len(_data) in expectedlength or True in stringvalue): + _found.append(expectedpart) + self.logger.log(VERBOSE1, + "Parsing Input {}: Expected response edited: {}.".format( + self._name, _found)) + except Exception: + _found.append(expectedpart) + self.logger.log(VERBOSE1, + "Parsing Input {}: Expected response edited 2nd try: {}.".format( + self._name, _found)) + except Exception as depend_err: + _found.append(_foundexpected) + self.logger.debug( + "Parsing Input {}: Expected response after exception: {}. Problem: {}".format( + self._name, _found, depend_err)) + self.logger.log(VERBOSE1, "Parsing Input {}: Found: {}.".format(self._name, _found)) + return _found, parse_expectedlist + + runthrough = [] + del_commands = [] + for expected in _del_expectedresponse: + if expected not in runthrough and not _del_data == 'ERROR': + runthrough.append(expected) + found, expectedlist = _foundappend(expected, _del_data) + try: + if _del_data.startswith(tuple(found)): + self.logger.log(VERBOSE1, + "Parsing Input {}: Expected response edited {}. Data {} starts with one of the entries." + " Resetting resend counter".format(self._name, found, _del_data)) + _entry, _value, _del_valuetype = self._write_itemsdict(_del_data, found) + self._sendingcommand = 'done' + self._resend_counter = 0 + elif expectedlist[0] in ['', ' ', 'none']: + self._sendingcommand = 'done' + self._resend_counter = 0 + self.logger.log(VERBOSE1, + "Parsing Input {}: No response expected. Resend Counter reset.".format( + self._name)) + if _del_data.startswith(tuple(found)): + # only add send command to list again if response doesn't fit to corresponding command + expectedindices = _duplicateindex(_del_expectedresponse, expected) + self.logger.log(VERBOSE2, "Parsing Input {}: expectedindices {}.".format( + self._name, expectedindices)) + for expectedindex in expectedindices: + self.logger.log(VERBOSE2, + "Parsing Input {}: expected {}, deletecommands {}.".format( + self._name, self._send_commands[expectedindex], + del_commands)) + if self._send_commands[expectedindex] not in del_commands: + parse_expectedtype = \ + self._send_commands[expectedindex].split(';')[0].split('|')[0].split(',') \ + if self._send_commands[expectedindex].split(',', 2)[2].find('|') >= 0 \ + else self._send_commands[expectedindex].split(';')[0].split(',') + try: + int(parse_expectedtype[-1]) + length = len(parse_expectedtype) - 1 + except Exception: + length = len(parse_expectedtype) + try: + parse_expectedtype[3:length] = [','.join(parse_expectedtype[3:length])] + testvalue = parse_expectedtype[3] + except Exception: + testvalue = '' + if not _del_valuetype == testvalue or not found or _del_data == 'ERROR': + self.logger.log(VERBOSE2, + "Parsing Input {}: Test Value {} of {} is not same as Valuetype:" + "{} or nothing found {}. Keeping in Sendcommands.".format( + self._name, testvalue, self._send_commands[expectedindex], + _del_valuetype, found)) + elif not _del_data == 'ERROR': + del_commands.append(self._send_commands[expectedindex]) + self.logger.log(VERBOSE1, + "Parsing Input {}: Test Value {} of {} is same as Valuetype: {}. Removing from Sendcommands.".format( + self._name, testvalue, + self._send_commands[expectedindex], + _del_valuetype)) + else: + self.logger.log(VERBOSE1, + "Parsing Input {}: Expected response edited {}. Data {} is different, not deleting" + " the command from sendcommands.".format(self._name, found, _del_data)) + except Exception as _err: + self.logger.log(VERBOSE1, + "Parsing Input {}: Deleting commands problem: {}".format(self._name, _err)) + return del_commands + + def _duplicateindex(seq, seqitem): + start_at = -1 + locs = [] + while True: + try: + loc = seq.index(seqitem, start_at + 1) + except ValueError: + break + else: + locs.append(loc) + start_at = loc + return locs + + while self.alive and not self._parsinginput == [] and not self._is_connected == [] and not self._is_connected == ['Connecting']: + connectionproblem = False + if self._sendingcommand not in ['', 'done', 'gaveup']: + self.logger.log(VERBOSE1, + "Parsing Input {}: Starting to parse input. Alive: {}. Connected: {}. Parsinginput: {}. Sendcommand: {}".format( + self._name, self.alive, self._is_connected, self._parsinginput, self._sendingcommand)) + to_send = 'command' + data = 'waiting' + item = None + try: + databuffer = [] + if 'Serial' in self._is_connected: + try: + databuffer = self._processing_response(self._serialwrapper) + except Exception as err: + self.logger.error("Parsing Input {}: Problem receiving Serial data {}.".format(self._name, err)) + elif 'TCP' in self._is_connected: + try: + databuffer = self._processing_response(self._tcpsocket) + except Exception as err: + self.logger.error("Parsing Input {}: Problem receiving TCP data {}.".format(self._name, err)) + else: + self._sendingcommand = 'gaveup' + break + for data_part in databuffer: + data = data_part.strip() + if data == 'ERROR' and self._sendingcommand not in ['gaveup', 'done']: + self._checkforerror(data) + + sorted_response_commands = sorted(self._response_commands, key=len, reverse=True) + for i in range(0, len(sorted_response_commands)): + try: + sorted_response_commands[i] = self._response_wildcards['original'][sorted_response_commands[i]] + except Exception as err: + sorted_response_commands[i] = None + self.logger.log(VERBOSE2, + "Parsing Input {}: Can not find wildcard equivalent for: {}".format( + self._name, err)) + sorted_response_commands = [value for value in sorted_response_commands if + (value is not None and '?' not in value)] + self.logger.log(VERBOSE2, + "Parsing Input {}: New Response Command list after sorting: {}".format( + self._name, sorted_response_commands)) + + self.logger.debug("Parsing Input {}: Response: {}. Send Commands: {}".format( + self._name, data, self._send_commands)) + updated = 0 + if (data == 'ERROR' and self._send_commands == []) or data in self._error_response: + self._resend_counter += 1 + updated = 1 + self.logger.debug( + "Parsing Input {}: Response {} is in error responses. Resend counter: {}".format( + self._name, data, self._resend_counter)) + self._checkforerror(data) + if not self._sendingcommand == 'gaveup' and not self._send_commands == []: + to_send = 'query' if (self._resend_counter % 2 == 1 and not + self._send_commands[0].split(',')[1] == '') else 'command' + self.logger.debug( + "Parsing Input {}: Requesting {} from {} because response was {}. Resend Counter: {}".format( + self._name, to_send, self._send_commands[0], data, self._resend_counter)) + self._wait(self._resend_wait) + elif data == 'none' and not self._send_commands: + self._sendingcommand = 'done' + break + elif self._send_commands: + self.logger.debug("Parsing Input {}: Expected response while parsing: {}.".format( + self._name, self._expected_response)) + + try: + to_send = 'command' + valuetype = 'empty' + deletecommands = [] + deleteexpected = [] + if not self._expected_response == []: + deletecommands = _deletecommands(self._expected_response, data, valuetype) + deleteexpected = [x.split(',')[2].split('*')[0] for x in deletecommands] + self.logger.log(VERBOSE2, + "Parsing Input {}: Deleting {} from sendcommands and {} " + "from expected response.".format(self._name, deletecommands, deleteexpected)) + self._send_commands = [x for x in self._send_commands if x not in set(deletecommands)] + self._expected_response = [x for x in self._expected_response if x not in set(deleteexpected)] + self.logger.log(VERBOSE1, + "Parsing Input {}: Sendcommands: {}. Sendingcommand: {}. Expected Response: {}.".format( + self._name, self._send_commands, self._sendingcommand, self._expected_response)) + if self._send_commands and not self._sendingcommand == 'done': + self._resend_counter += 1 + depending = self._checkdependency('', 'parseinput') + connectionproblem = self._checkforerror(data, depending) + + if not self._sendingcommand == 'gaveup': + to_send = 'query' if (self._resend_counter % 2 == 1 and not + self._send_commands[0].split(',')[1] == '') else 'command' + self.logger.debug( + "Parsing Input {}: Requesting {} from {} because response was {}. Resend Counter: {}".format( + self._name, to_send, self._send_commands[0], data, self._resend_counter)) + self._wait(self._resend_wait) + except Exception as err: + self.logger.warning( + "Parsing Input {}: Problems with checking for expected response. Error: {}".format(self._name, err)) + + if not data == 'ERROR' and data not in self._error_response and not data == 'none': + self.logger.log(VERBOSE1, + "Parsing Input {}: Starting to compare values for data {} with {}.".format( + self._name, data, sorted_response_commands)) + + for dictkey in sorted_response_commands: + comparekey = self._response_wildcards['wildcard'][dictkey] + self.logger.log(VERBOSE2, + "Parsing Input {}: Starting to compare values for data {} with key: {} (before wildcard processing: {}).".format( + self._name, data, dictkey, comparekey)) + if data == comparekey and not self._send_commands == []: + self._send_commands = [x for x in self._send_commands if comparekey not in x] + self._sendingcommand = self._send_commands[0] if self._sendingcommand not in self._send_commands and \ + self._send_commands else self._sendingcommand + self.logger.debug( + "Parsing Input {}: Response is identical to expected response. Cleaned Send Commands: {}".format( + self._name, self._send_commands)) + for entry in self._response_commands[comparekey]: + valuelength = entry[0] + responseposition = entry[2] + item = entry[3] + expectedtype = entry[7] + index = data.find(dictkey) + if index == 0: + av_function = entry[4] + zone = entry[5] + receivedvalue = origvalue = '' + cond1 = data.startswith(self._special_commands['Display']['Command']) + cond2 = not self._special_commands['Display']['Command'] == '' + cond3 = data.startswith(tuple(self._special_commands['Nowplaying']['Command'])) + cond4 = not self._special_commands['Nowplaying']['Command'] == '' + cond5 = data.startswith(tuple(self._special_commands['Speakers']['Command'])) + cond6 = not self._special_commands['Speakers']['Command'] == '' + if cond1 and cond2: + received = ConvertValue( + data[responseposition:responseposition + valuelength], expectedtype, False, + valuelength, self._special_commands['Display']['Command'], + self._name, self._special_commands).convert_value() + self.logger.debug( + "Parsing Input {}: Displaycommand found in response {}. Converted to {}.".format( + self._name, data, receivedvalue)) + try: + receivedtype, receivedvalue = received[0], received[1] + if receivedtype == 'nowplaying': + self.logger.info("Parsing Input {}: Now playing {}".format( + self._name, receivedvalue)) + self._special_commands['Nowplaying']['Item']( + receivedvalue, 'AVDevice', self._tcp) + elif receivedtype == 'station': + for singleitem in self._special_commands['Input']['Item']: + if singleitem() == 'IRADIO': + self.logger.info( + "Parsing Input {}: Internet radio station {}".format( + self._name, receivedvalue)) + self._items['zone0']['station']( + receivedvalue, 'AVDevice', self._tcp) + else: + self.logger.info( + "Parsing Input {}: Found Display information {}".format( + self._name, receivedvalue)) + except Exception: + receivedvalue = received + + elif cond3 and cond4: + self.logger.debug( + "Parsing Input {}: Now playing info found in response {}.".format( + self._name, data)) + try: + m = re.search('"(.+?)"', data) + receivedvalue = m.group(1) if m else '' + except Exception as err: + self.logger.debug( + "Parsing Input {}: Problems reading Now Playing info. Error:{}".format( + self._name, err)) + elif cond5 and cond6: + self.logger.debug( + "Parsing Input {}: Speakers info found in response {}. Command: {}".format( + self._name, data, self._special_commands['Speakers']['Command'])) + receivedvalue = ConvertValue( + data[responseposition:responseposition + valuelength], expectedtype, False, + valuelength, self._special_commands['Speakers']['Command'], self._name, + self._special_commands).convert_value() + try: + for _ in self._special_commands['Speakers']['Command']: + for zone in self._items_speakers: + for speakerlist in self._items_speakers[zone]: + speaker_ab = sum(map(int, self._items_speakers[zone].keys())) + self.logger.debug( + "Parsing Input {}: Received value: {}. Speaker {}. speaker_ab: {}".format( + self._name, receivedvalue, speakerlist, speaker_ab)) + speaker = self._items_speakers[zone][speakerlist]['Item'] + if receivedvalue == int(speakerlist) or receivedvalue == speaker_ab: + self.logger.info( + "Parsing Input {}: Speaker {} is on.".format( + self._name, speaker)) + speaker(1, 'AVDevice', self._tcp) + else: + self.logger.info( + "Parsing Input {}: Speaker {} is off.".format( + self._name, speaker)) + speaker(0, 'AVDevice', self._tcp) + + except Exception as err: + self.logger.warning( + "Parsing Input {}: Problems reading Speakers info. Error:{}".format( + self._name, err)) + else: + origvalue = value = receivedvalue = data[responseposition:responseposition + valuelength] + self.logger.log(VERBOSE1, + "Parsing Input {}: Neither Display nor Now Playing in response. receivedvalue: {}.".format( + self._name, receivedvalue)) + + invert = True if entry[6].lower() in ['1', 'true', 'yes', 'on'] else False + if not receivedvalue == '': + receivedvalue = ConvertValue(value, expectedtype, invert, valuelength, + data, self._name, + self._special_commands).convert_value() + try: + sametype = True if isinstance(receivedvalue, eval(expectedtype)) else False + except Exception: + sametype = True if receivedvalue == '' and expectedtype == 'empty' else False + receivedvalue = True if receivedvalue == '' and expectedtype == 'empty' else receivedvalue + if sametype is False: + self.logger.log(VERBOSE1, + "Parsing Input {}: Receivedvalue {} does not match type {} - ignoring it.".format( + self._name, receivedvalue, expectedtype)) + else: + self.logger.log(VERBOSE1, + "Parsing Input {}: Receivedvalue {} does match type {} - going on.".format( + self._name, receivedvalue, expectedtype)) + self._displayignore(data, receivedvalue, 'parsing') + value = receivedvalue + self.logger.debug( + "Parsing Input {}: Found key {} in response at position {} with value {}.".format( + self._name, dictkey, responseposition, value)) + self._addorremove_keepcommands('removefromkeep', data) + value = Translate(origvalue, entry[9], self._name, 'parse', + self._specialparse).translate() or value + if av_function in self._items[zone].keys(): + self._items[zone][av_function]['Value'] = value + self.logger.log(VERBOSE1, + "Parsing Input {}: Updated Item dict {} with value {}.".format( + self._name, av_function, value)) + + item(value, 'AVDevice', self._tcp) + self.logger.debug("Parsing Input {}: Updated Item {} with {} Value: {}.".format( + self._name, item, expectedtype, value)) + if av_function in self._items[zone].keys(): + self._checkdependency('{}, {}, {}'.format(zone, av_function, value), + 'checkquery') + + # TOTEST + try: + testcommand = data.split('?')[0] + commandstarts = [x.split('?')[0] for x in self._response_commands if x.split('?')[0] in testcommand and x.split('?')[0]] + self.logger.log(VERBOSE1, + "Parsing Input {}: Commandstarts {}. testcommand {}".format( + self._name, commandstarts, testcommand)) + updated = 1 if len(commandstarts) >= 1 or testcommand == 'none' else 0 + except Exception as err: + self.logger.error( + "Parsing Input {}: Problem with new tests {}".format(self._name, err)) + self._wait(0.15) + + if updated == 1: + self.logger.log(VERBOSE1, + "Parsing Input {}: Updated all relevant items from item {}. step 1".format( + self._name, item)) + break + if updated == 1: + self.logger.log(VERBOSE1, + "Parsing Input {}: Updated all relevant items from {}. step 2".format( + self._name, item)) + break + + if updated == 1: + self.logger.log(VERBOSE1, + "Parsing Input {}: Updated all relevant items from {}. step 3".format( + self._name, item)) + break + if updated == 1: + self.logger.log(VERBOSE1, + "Parsing Input {}: Updated all relevant items from {}. step 4".format( + self._name, item)) + break + self.logger.log(VERBOSE2, "Parsing Input {}: Finished comparing values.".format(self._name)) + if not self._send_commands: + self._sendingcommand = 'done' + except Exception as err: + self.logger.error("Parsing Input {}: Problems parsing input. Error: {}".format(self._name, err)) + finally: + if not self._send_commands: + self._displayignore('', None, 'parsing_final') + elif not self._send_commands == [] and data == 'waiting': + self.logger.log(VERBOSE2, "Parsing Input {}: Waiting for response..".format(self._name)) + elif not self._send_commands == [] and not data == 'waiting': + reorderlist = [] + index = 0 + for command in self._send_commands: + command_split = command.split(';')[0] + try: + commanditem = command.split(';')[1] + except Exception: + commanditem = None + if commanditem: + command = '{};{}'.format(command_split, commanditem) + self.logger.log(VERBOSE1, + "Parsing Input {}: Adding command commandsplit {}, commanditem {}. Command: {}".format( + self._name, command_split, commanditem, command)) + if command_split in self._query_commands: + reorderlist.append(command) + elif command_split in self._power_commands: + self.logger.log(VERBOSE1, + "Parsing Input {}: Adding command and ordering power command {} to first position.".format( + self._name, command)) + reorderlist.insert(0, command) + index += 1 + else: + reorderlist.insert(index, command) + self.logger.log(VERBOSE1, + "Parsing Input {}: Adding command {} to position {}.".format( + self._name, command, index)) + index += 1 + self._send_commands = reorderlist + self.logger.debug( + 'Parsing Input {}: Newly sorted send commands at end of parsing: {}'.format(self._name, + self._send_commands)) + if not self._is_connected: + self.logger.log(VERBOSE2, + "Parsing Input {}: Not connected.".format(self._name)) + self._addorremove_keepcommands('addtokeep', '') + else: + sending = self._send('{}'.format(to_send), 'parseinput_final') + self.logger.log(VERBOSE1, + "Parsing Input {}: Sending again because list is not empty yet. Sending return is {}.".format( + self._name, sending)) + if 'Serial' in self._is_connected and connectionproblem is True: + self._is_connected.remove('Serial') + try: + self._is_connected.remove('Connecting') + except Exception: + pass + self._trigger_reconnect = True + if 'TCP' in self._is_connected and connectionproblem is True: + self._is_connected.remove('TCP') + try: + self._is_connected.remove('Connecting') + except Exception: + pass + self._trigger_reconnect = True + if self._trigger_reconnect is True and self._is_connected == []: + self.logger.log(VERBOSE1, + "Parsing Input {}: Trying to connect while parsing item".format(self._name)) + self.connect('parse_dataerror') + + # Updating items based on value changes via Visu, CLI, etc. + def update_item(self, item, caller=None, source=None, dest=None): + + def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, replace_value, replace_type): + set_appending = True + set_removefromkeeping = [] + for sendcommand in replace_dict: + keepdict = sendcommand + sendcommand = replace_dict.get(sendcommand) if replace_type == 'keep' else sendcommand + commandlist = self._keep_commands if replace_type == 'keep' else self._send_commands + self.logger.log(VERBOSE1, "Updating Item {}: Testing {} command: {}".format(self._name, replace_type, sendcommand)) + if replace_commandinfo[3] in sendcommand: + splitfind = sendcommand.split(',', 2)[2] + before = sendcommand.split(',', 2)[0:2] + testvalues = [] + for after in splitfind.split('|'): + after = [after] + sendcommand_temp = ','.join(before + after) + valuetype = sendcommand_temp.split(';')[0].split(',') + if valuetype[len(valuetype) - 1].isdigit(): + valuetype.pop(len(valuetype) - 1) + try: + valuetype[3:] = [','.join(valuetype[3:])] + testvalues.append(valuetype[3]) + except Exception: + pass + self.logger.log(VERBOSE2, + "Updating Item {}: Is expected type {} in testvalues {}?".format( + self._name, testvalues, replace_commandinfo[9])) + if replace_commandinfo[9] in testvalues: + self.logger.log(VERBOSE1, + "Updating Item {}: Command Set {} ({}) already in Commandlist {}." + " Value type: {}, expected type: {}. Replaced. Sendingcommand: {}".format( + self._name, command, replace_commandinfo[3], + commandlist, type(replace_value), replace_commandinfo[9], + self._sendingcommand)) + if replace_type == 'keep': + set_removefromkeeping.append(keepdict) + else: + commandlist[commandlist.index(sendcommand)] = replace_command + self._sendingcommand = replace_command + self._resend_counter = 0 + set_appending = False + self.logger.log(VERBOSE1, + "Updating Item {}: Resetting Resend Counter due to replaced command.".format( + self._name)) + break + else: + self.logger.log(VERBOSE2, + "Updating Item {}: Command Set {} ({}) already in Commandlist {}" + " but value {} is not same type as {}. Continue...".format( + self._name, command, replace_commandinfo[3], type(replace_value), + replace_commandinfo[9], commandlist)) + self.logger.log(VERBOSE1, + "Updating Item {}: Return from replace_setcommand: appending = {}, remove = {}.".format( + self._name, set_appending, set_removefromkeeping)) + return set_appending if replace_type == 'append' else set_removefromkeeping + + if self.alive: + if caller in self._update_exclude: + self.logger.debug( + "Updating Item {}: Not updating {} because caller {} is excluded.".format(self._name, item, caller)) + if not caller == 'AVDevice' and caller not in self._update_exclude: + emptycommand = False + commandinfo = command_re = response = '' + value = item() + try: + self.logger.debug("Updating Item {}: {} trying to update {}. Reconnecttrigger: {}".format( + self._name, caller, item, self._trigger_reconnect)) + self.logger.log(VERBOSE1, "Updating Item {}: Starting to update item {}. " + "Caller: {}, Source: {}. Destination: {}. Value: {}. Reconnecttrigger is {}".format( + self._name, item, caller, source, dest, value, self._trigger_reconnect)) + try: + depending = self._checkdependency(item, 'update') + except Exception: + depending = False + self.logger.log(VERBOSE1, "Updating Item {}: Depending is {}.".format(self._name, depending)) + condition1 = (self.has_iattr(item.conf, 'avdevice') and + self.get_iattr_value(item.conf, 'avdevice') == 'reload') + condition2 = (self.has_iattr(item.conf, 'avdevice_zone0') and + self.get_iattr_value(item.conf, 'avdevice_zone0') == 'reload') + if condition1 or condition2: + self._initialize() + self.logger.info("Initializing {}: Reloaded Text file and functions".format(self._name)) + depending = False + + # connect if necessary + if self._trigger_reconnect is True: + self.logger.log(VERBOSE1, + "Updating Item {}: Trying to connect while updating item".format(self._name)) + self.connect('update_item') + depending = self._checkdependency(self._dependson, 'dependitem') if item == self._dependson else depending + + for zone in range(0, self._number_of_zones + 1): + command = '' + letsgo = False + try: + if self.has_iattr(item.conf, 'avdevice'): + command = self.get_iattr_value(item.conf, 'avdevice') + zone_x = True if command in self._items['zone{}'.format(zone)].keys() else False + elif self.has_iattr(item.conf, 'avdevice_zone{}_speakers'.format(zone)): + command = 'speakers' + zone_x = True + else: + zone_x = False + except Exception: + zone_x = False + try: + if self.has_iattr(item.conf, 'avdevice_zone{}'.format(zone)) or zone_x is True: + letsgo = True + except Exception: + letsgo = True if item == 'statusupdate' and zone == 0 else False + + if letsgo is True: + if zone_x is False: + try: + command = self.get_iattr_value(item.conf, 'avdevice_zone{}'.format(zone)) + except Exception: + command = 'statusupdate' + value = True + command_on = '{} on'.format(command) + command_off = '{} off'.format(command) + command_set = '{} set'.format(command) + command_increase = '{} increase'.format(command) + command_decrease = '{} decrease'.format(command) + updating = True + + try: + if command is None: + command = '{} on'.format(command) + if command is None or command == 'None on': + command = '{} off'.format(command) + if command is None or command == 'None off': + command = '{} set'.format(command) + if command is None or command == 'None set': + command = '{} increase'.format(command) + if command is None or command == 'None increase': + command = '{} decrease'.format(command) + cond1 = self._functions['zone{}'.format(zone)][command][5].lower() == 'w' + cond2 = value in [False, '0', 0, 'False'] + if cond1 and cond2: + self.logger.debug( + "Updating Item {}: Skipping command {} with WRITE flag because it's set to False".format( + self._name, command)) + break + if self._functions['zone{}'.format(zone)][command][2] == '': + emptycommand = True + if command == 'statusupdate': + try: + checkvalue = item() + except Exception: + checkvalue = True + self.logger.log(VERBOSE1, + "Updating Item {}: Statusupdate. Checkvalue: {}. Display Ignore: {}. Caller: {}".format( + self._name, checkvalue, + self._special_commands['Display']['Ignore'], caller)) + cond1 = checkvalue is True or caller == 'Init' + cond2 = not self._special_commands['Display']['Ignore'] >= 5 + if cond1 and cond2: + if not self._is_connected == []: + self._addorremove_keepcommands('statusupdate', 'all') + for query in self._query_commands: + if caller == 'Init': + depending = self._checkdependency(query, 'initupdate') + else: + depending = self._checkdependency(query, 'statusupdate') + if query not in self._send_commands and depending is False: + self._send_commands.append(query) + self._reconnect_counter = 0 + self._trigger_reconnect = True + + if not self._is_connected == []: + self.logger.log(VERBOSE1, + "Updating Item {}: Updating status. Sendcommands: {}. " + "Reconnecttrigger: {}. Display Ignore: {}".format( + self._name, self._send_commands, self._trigger_reconnect, + self._special_commands['Display']['Ignore'])) + elif checkvalue is False and not self._special_commands['Display']['Ignore'] >= 5: + depending = self._checkdependency(item, 'globaldepend') + if depending is True or self._is_connected == [] or self._is_connected == ['Connecting']: + self._resetondisconnect('statusupdate') + updating = False + if self._functions['zone{}'.format(zone)][command][5].lower() == 'r': + updating = False + commandinfo = self._functions['zone{}'.format(zone)][command] + if commandinfo[2] == '' and commandinfo[3] == '': + self.logger.warning( + "Updating Item {}: Function is read only and empty. Doing nothing. Command: {}".format( + self._name, command)) + else: + self.logger.info( + "Updating Item {}: Function is read only. Sending query. Command: {}".format( + self._name, command)) + + responsecommand, _ = CreateResponse(commandinfo, '', '', self._name, + self._specialparse).response_standard() + appendcommand = '{},{},{};{}'.format(commandinfo[2], commandinfo[3], + responsecommand, item.id()) + cond1 = appendcommand not in self._query_commands + cond2 = appendcommand not in self._special_commands['Display']['Command'] + if appendcommand in self._send_commands: + self.logger.debug( + "Updating Item {}: Readonly Command {} already in Commandlist. Ignoring.".format( + self._name, appendcommand)) + elif cond1 and cond2 and depending is True: + self._keep_commands[time.time()] = appendcommand + self.logger.debug( + "Updating Item {}: Not adding readonly command {} because dependency is not fullfilled, storing in keep commands: {}.".format( + self._name, appendcommand, self._keep_commands)) + else: + self.logger.debug( + "Updating Item {}: Readonly. Updating Zone {} Commands {} for {}".format( + self._name, zone, self._send_commands, item)) + self._send_commands.append(appendcommand) + + except Exception as err: + self.logger.log(VERBOSE2, + "Updating Item {}: Command {} is a standard command. Updating: {}. Message: {}".format( + self._name, command, updating, err)) + + if updating is True: + self.logger.debug("Updating Item {}: {} set {} to {} for {} in zone {}".format( + self._name, caller, command, value, item, zone)) + self._trigger_reconnect = True + setting = False + checkquery = False + if command in self._functions['zone{}'.format(zone)]: + commandinfo = self._functions['zone{}'.format(zone)][command] + replacedresponse, _ = CreateResponse(commandinfo, '', '', self._name, + self._specialparse).response_standard() + appendcommand = '{},{},{};{}'.format(commandinfo[2], commandinfo[3], replacedresponse, item.id()) + cond1 = appendcommand not in self._query_commands + cond2 = appendcommand not in self._special_commands['Display']['Command'] + if appendcommand in self._send_commands: + self.logger.debug( + "Updating Item {}: Command {} already in Commandlist. Ignoring.".format( + self._name, appendcommand)) + elif cond1 and cond2 and depending is True: + self._keep_commands[time.time()] = appendcommand + self.logger.debug( + "Updating Item {}: Not adding command {} because dependency is not fullfilled, storing in keep commands: {}.".format( + self._name, appendcommand, self._keep_commands)) + else: + self.logger.debug( + "Updating Item {}: Updating Zone {} Commands {} for {}".format( + self._name, zone, self._send_commands, item)) + self._send_commands.append(appendcommand) + checkquery = True + elif command_increase in self._functions['zone{}'.format(zone)]: + commandinfo = self._functions['zone{}'.format(zone)][command_increase] + try: + reverseinfo = self._functions['zone{}'.format(zone)][command_decrease] + except Exception: + try: + reverseinfo = self._functions['zone{}'.format(zone)][ + '{} decrease'.format(command.replace('+', '-', 1))] + except Exception: + reverseinfo = '' + replacedresponse, replacedreverse = CreateResponse( + commandinfo, reverseinfo, '', self._name, + self._specialparse).response_in_decrease() + try: + reverseitem = self._items['zone{}'.format(zone)][command.replace('+', '-', 1)].get('Item') + except Exception: + reverseitem = item.id() + + appendcommand = '{},{},{};{}'.format(commandinfo[2], commandinfo[3], replacedresponse, item.id()) + reversecommand = '{},{},{};{}'.format(reverseinfo[2], reverseinfo[3], replacedreverse, reverseitem) + + self.logger.log(VERBOSE2, + "Updating Item {}: Appendcommand increase: {}, Reversecommand: {}, Send Commands: {}".format( + self._name, appendcommand, reversecommand, self._send_commands)) + cond1 = appendcommand not in self._query_commands + cond2 = appendcommand not in self._special_commands['Display']['Command'] + if appendcommand in self._send_commands: + self.logger.debug( + "Updating Item {}: Increase Command {} already in Commandlist. Ignoring.".format( + self._name, appendcommand)) + elif reversecommand in self._send_commands: + self.logger.debug( + "Updating Item {}: Command Decrease {} already in Commandlist {}. Replacing with Command Increase {}.".format( + self._name, reversecommand, self._send_commands, appendcommand)) + self._send_commands[self._send_commands.index(reversecommand)] = self._sendingcommand = appendcommand + self.logger.log(VERBOSE1, "Updating Item {}: New Commandlist {}.".format( + self._name, self._send_commands)) + self._resend_counter = 0 + checkquery = True + self.logger.log(VERBOSE1, + "Updating Item {}: Resetting Resend Counter due to updated command.".format( + self._name)) + elif cond1 and cond2 and depending is True: + self._keep_commands[time.time()] = appendcommand + self.logger.debug( + "Updating Item {}: Not adding increase command {} because dependency is not fullfilled, storing in keep commands: {}.".format( + self._name, appendcommand, self._keep_commands)) + else: + self.logger.debug( + "Updating Item {}: Updating Zone {} Command Increase {} for {}".format( + self._name, zone, self._send_commands, item)) + self._send_commands.append(appendcommand) + elif command_decrease in self._functions['zone{}'.format(zone)]: + commandinfo = self._functions['zone{}'.format(zone)][command_decrease] + try: + reverseinfo = self._functions['zone{}'.format(zone)][command_increase] + except Exception: + try: + reverseinfo = self._functions['zone{}'.format(zone)][ + '{} increase'.format(command.replace('-', '+', 1))] + except Exception: + reverseinfo = '' + replacedresponse, replacedreverse = CreateResponse( + commandinfo, reverseinfo, '', self._name, + self._specialparse).response_in_decrease() + try: + reverseitem = self._items['zone{}'.format(zone)][command.replace('-', '+', 1)].get('Item') + except Exception: + reverseitem = item.id() + + appendcommand = '{},{},{};{}'.format(commandinfo[2], commandinfo[3], replacedresponse, item.id()) + reversecommand = '{},{},{};{}'.format(reverseinfo[2], reverseinfo[3], replacedreverse, reverseitem) + + self.logger.log(VERBOSE2, + "Updating Item {}: Appendcommand decrease: {}, Reversecommand: {}, Send Commands: {}".format( + self._name, appendcommand, reversecommand, self._send_commands)) + cond1 = appendcommand not in self._query_commands + cond2 = appendcommand not in self._special_commands['Display']['Command'] + if appendcommand in self._send_commands: + self.logger.debug( + "Updating Item {}: Decrease Command {} already in Commandlist. Ignoring.".format( + self._name, appendcommand)) + elif reversecommand in self._send_commands: + self.logger.debug( + "Updating Item {}: Command Increase {} already in Commandlist {}. Replacing with Command Decrease {}.".format( + self._name, reversecommand, self._send_commands, appendcommand)) + self._send_commands[self._send_commands.index(reversecommand)] = self._sendingcommand = appendcommand + self.logger.log(VERBOSE1, "Updating Item {}: New Commandlist {}.".format( + self._name, self._send_commands)) + self._resend_counter = 0 + checkquery = True + self.logger.log(VERBOSE1, + "Updating Item {}: Resetting Resend Counter due to updated command.".format( + self._name)) + elif cond1 and cond2 and depending is True: + self._keep_commands[time.time()] = appendcommand + self.logger.debug( + "Updating Item {}: Not adding decrease command {} because dependency is not fullfilled, storing in keep commands: {}.".format( + self._name, appendcommand, self._keep_commands)) + else: + self.logger.debug( + "Updating Item {}: Updating Zone {} Command Decrease {} for {}".format( + self._name, zone, self._send_commands, item)) + self._send_commands.append(appendcommand) + + elif command_on in self._functions['zone{}'.format(zone)] and \ + isinstance(value, bool) and value == 1: + commandinfo = self._functions['zone{}'.format(zone)][command_on] + reverseinfo = self._functions['zone{}'.format(zone)][command_off] + replacedresponse, replacedreverse = CreateResponse( + commandinfo, reverseinfo, '', self._name, self._specialparse).response_on() + + appendcommand = '{},{},{};{}'.format(commandinfo[2], commandinfo[3], replacedresponse, item.id()) + reversecommand = '{},{},{};{}'.format(reverseinfo[2], reverseinfo[3], replacedreverse, item.id()) + + self.logger.log(VERBOSE2, + "Updating Item {}: Appendcommand on: {}, Reversecommand: {}, Send Commands: {}".format( + self._name, appendcommand, reversecommand, self._send_commands)) + removefromkeeping = [] + for x in self._keep_commands: + cond1 = appendcommand == self._keep_commands.get(x) + cond2 = reversecommand == self._keep_commands.get(x) + if cond1 or cond2: + removefromkeeping.append(x) + cond1 = appendcommand not in self._query_commands + cond2 = appendcommand not in self._special_commands['Display']['Command'] + if appendcommand in self._send_commands: + self.logger.debug( + "Updating Item {}: Command On {} already in Commandlist {}. Ignoring.".format( + self._name, appendcommand, self._send_commands)) + elif reversecommand in self._send_commands: + self.logger.debug( + "Updating Item {}: Command Off {} already in Commandlist {}. Replacing with Command On {}.".format( + self._name, reversecommand, self._send_commands, appendcommand)) + self._send_commands[self._send_commands.index(reversecommand)] = self._sendingcommand = appendcommand + self.logger.log(VERBOSE1, "Updating Item {}: New Commandlist {}.".format( + self._name, self._send_commands)) + self._resend_counter = 0 + checkquery = True + self.logger.log(VERBOSE1, + "Updating Item {}: Resetting Resend Counter due to new command.".format(self._name)) + elif cond1 and cond2 and depending is True: + for i in removefromkeeping: + self.logger.log(VERBOSE1, + "Updating Item {}: Removing {} from keepcommands " + "before storing equivalent command.".format(self._name, self._keep_commands.get(i))) + self._keep_commands.pop(i, None) + self._keep_commands[time.time()] = appendcommand + self.logger.debug( + "Updating Item {}: Not adding on command {} because dependency is not fullfilled," + " storing in keep commands: {}.".format( + self._name, appendcommand, self._keep_commands)) + else: + self._send_commands.append(appendcommand) + self._sendingcommand = appendcommand + checkquery = True + self.logger.log(VERBOSE1, + "Updating Item {}: Update Zone {} Command On {} for {}".format( + self._name, zone, commandinfo[2], item)) + if command_on == 'power on' and checkquery is True: + self._addorremove_keepcommands('powercommand', 'zone{}'.format(zone)) + self.logger.debug( + "Updating Item {}: Command Power On for zone: {}. Appending relevant query commands.".format( + self._name, zone)) + checkquery = False + for query in self._query_zonecommands['zone{}'.format(zone)]: + depending = self._checkdependency(query, 'statusupdate') + if query not in self._send_commands and depending is False: + self._send_commands.append(query) + + elif command_off in self._functions['zone{}'.format(zone)] and \ + isinstance(value, bool) and value == 0: + commandinfo = self._functions['zone{}'.format(zone)][command_off] + reverseinfo = self._functions['zone{}'.format(zone)][command_on] + replacedresponse, replacedreverse = CreateResponse( + commandinfo, reverseinfo, '', self._name, self._specialparse).response_off() + + appendcommand = '{},{},{};{}'.format(commandinfo[2], commandinfo[3], replacedresponse, item.id()) + reversecommand = '{},{},{};{}'.format(reverseinfo[2], reverseinfo[3], replacedreverse, item.id()) + + self.logger.log(VERBOSE1, + "Updating Item {}: Appendcommand off: {}. Reversecommand: {} Send Commands: {}".format( + self._name, appendcommand, reversecommand, self._send_commands)) + removefromkeeping = [] + for x in self._keep_commands: + cond1 = appendcommand == self._keep_commands.get(x) + cond2 = reversecommand == self._keep_commands.get(x) + if cond1 or cond2: + removefromkeeping.append(x) + cond1 = appendcommand not in self._query_commands + cond2 = appendcommand not in self._special_commands['Display']['Command'] + if appendcommand in self._send_commands: + self.logger.debug( + "Updating Item {}: Command Off {} already in Commandlist {}. Ignoring.".format( + self._name, appendcommand, self._send_commands)) + elif reversecommand in self._send_commands: + self.logger.debug( + "Updating Item {}: Command On {} already in Commandlist {}. Replacing with Command Off {}.".format( + self._name, reversecommand, self._send_commands, appendcommand)) + self._send_commands[self._send_commands.index(reversecommand)] = self._sendingcommand = appendcommand + self.logger.log(VERBOSE1, "Updating Item {}: New Commandlist {}.".format( + self._name, self._send_commands)) + self._resend_counter = 0 + checkquery = True + self.logger.log(VERBOSE1, + "Updating Item {}: Resetting Resend Counter due to new command.".format( + self._name)) + elif cond1 and cond2 and depending is True: + for i in removefromkeeping: + self.logger.log(VERBOSE1, + "Updating Item {}: Removing {} from keepcommands " + "before storing equivalent command.".format(self._name, self._keep_commands.get(i))) + self._keep_commands.pop(i, None) + self._keep_commands[time.time()] = appendcommand + self.logger.debug( + "Updating Item {}: Not adding off command {} because dependency is not fullfilled, storing in keep commands: {}.".format( + self._name, appendcommand, self._keep_commands)) + else: + self._send_commands.append(appendcommand) + self._sendingcommand = appendcommand + checkquery = True + self.logger.log(VERBOSE1, + "Updating Item {}: Update Zone {} Command Off {} for {}".format( + self._name, zone, commandinfo[2], item)) + + elif command_set in self._functions['zone{}'.format(zone)]: + commandinfo = self._functions['zone{}'.format(zone)][command_set] + newvalue = None + if not command.lower().startswith('speakers'): + response, _ = CreateResponse(commandinfo, '', value, self._name, + self._specialparse).response_set() + try: + newvalue = value.lower() if isinstance(value, str) else value + newvalue = Translate(newvalue, commandinfo[10], self._name, 'update', + self._specialparse).translate() + self.logger.log(VERBOSE2, + "Updating Item {}: Translated value: {}".format(self._name, + newvalue)) + except Exception: + pass + value = newvalue or value + try: + value = eval(value.lstrip('0')) + except Exception: + pass + self.logger.log(VERBOSE2, + "Updating Item {}: Final value: {}".format(self._name, + value)) + try: + translatecode = commandinfo[10] + except Exception: + translatecode = None + cond1 = isinstance(value, int) and 'int' in commandinfo[9] + cond2 = isinstance(value, float) and 'float' in commandinfo[9] + if value == 0 and 'bool' in commandinfo[9]: + setting = True + value = 'OFF' + try: + command_re = re.sub('\*+', '{}'.format(value), commandinfo[2]) + except Exception: + command_re = commandinfo[2] + self.logger.debug( + "Updating Item {}: Value 0 is converted to OFF. command_re: {}, response: {}".format( + self._name, command_re, response)) + elif cond1 or cond2: + setting = True + if commandinfo[2].count('*') == 1 and command.lower().startswith('speakers'): + currentvalue = int( + self._items['zone{}'.format(zone)]['speakers']['Item']()) + multiply = -1 if item() == 0 else 1 + multiply = 0 if (currentvalue == 0 and item() == 0) else multiply + try: + value = abs(int(self.get_iattr_value(item.conf, + 'avdevice_zone{}_speakers'.format( + zone)))) + except Exception: + self.logger.warning( + "Updating Item {}: This speaker item is not supposed to be manipulated directly.".format( + self._name)) + break + + powerinfo = self._functions['zone{}'.format(zone)]['power on'] + if not currentvalue == value or multiply == -1: + maxvalue = sum(map(int, self._items_speakers['zone{}'.format(zone)].keys())) + value = min(currentvalue + (value * multiply), maxvalue) + self.logger.log(VERBOSE1, + "Updating Item {}: Speaker {} current value is {}. Item: {} with value {}." + " Multiply: {}. Value: {}".format( + self._name, self._items['zone{}'.format(zone)]['speakers']['Item'], + currentvalue, item, item(), multiply, value)) + response, _ = CreateResponse(commandinfo, '', value, self._name, + self._specialparse).response_set() + command_re = CreateResponse(commandinfo, '', value, self._name, + self._specialparse).replace_number( + commandinfo[2], value, translatecode) + self.logger.log(VERBOSE2, + "Updating Item {}: Speakers commandinfo 2: {}, value: {}. command_re: {}".format( + self._name, commandinfo[2], value, command_re)) + if value > 0: + replacedresponse, _ = CreateResponse(powerinfo, '', True, self._name, + self._specialparse).response_power() + try: + poweritem = self._items['zone{}'.format(zone)][powerinfo[1]].get('Item') + except Exception: + poweritem = self._items['zone0'][powerinfo[1]].get('Item') + appendcommand = '{},{},{};{}'.format(powerinfo[2], powerinfo[3], + replacedresponse, + poweritem.id()) + self._send_commands.insert(0, appendcommand) + self._sendingcommand = appendcommand + self.logger.debug( + "Updating Item {}: Turning power on. powercommands is: {}".format( + self._name, powerinfo)) + else: + command_re = CreateResponse(commandinfo, '', value, self._name, + self._specialparse).replace_number( + commandinfo[2], value, translatecode) + self.logger.log(VERBOSE2, + "Updating Item {}: commandinfo 2: {}, value: {}. command_re: {}".format( + self._name, commandinfo[2], value, command_re)) + + elif isinstance(value, str) and 'str' in commandinfo[9]: + setting = True + command_re = CreateResponse(commandinfo, '', value, self._name, + self._specialparse).replace_string( + commandinfo[2], value, translatecode) + + else: + setting = False + else: + self.logger.error("Updating Item {}: Command {} not in text file or wrong Item type! Valuetype is {}".format( + self._name, command, type(value))) + updating = False + + if not self._send_commands == [] and setting is True: + appendcommand = '{},{},{};{}'.format(command_re, commandinfo[3], response, + item.id()) + setting = False + appending = _replace_setcommand(commandinfo, self._send_commands, appendcommand, value, 'append') + removefromkeeping = _replace_setcommand(commandinfo, self._keep_commands, appendcommand, value, 'keep') + for i in removefromkeeping: + self.logger.log(VERBOSE1, + "Updating Item {}: Removing {} from keepcommands " + "before storing equivalent command.".format(self._name, self._keep_commands.get(i))) + self._keep_commands.pop(i, None) + if appending is True: + cond1 = appendcommand not in self._query_commands + cond2 = appendcommand not in self._special_commands['Display']['Command'] + if cond1 and cond2 and depending is True: + self._keep_commands[time.time()] = appendcommand + self.logger.debug( + "Updating Item {}: Not adding set command {} because dependency is not fullfilled, storing in keep commands: {}.".format( + self._name, appendcommand, self._keep_commands)) + else: + self._send_commands.append(appendcommand) + self._sendingcommand = appendcommand + self._resend_counter = 0 + checkquery = True + self.logger.log(VERBOSE1, + "Updating Item {}: Resetting Resend Counter because appending new set command.".format( + self._name)) + self.logger.log(VERBOSE1, + "Updating Item {}: Update Zone {} Command Set {} for {}. Command: {}".format( + self._name, zone, commandinfo[2], item, command_re)) + elif setting is True: + appendcommand = '{},{},{};{}'.format(command_re, commandinfo[3], response, + item.id()) + removefromkeeping = _replace_setcommand(commandinfo, self._keep_commands, appendcommand, value, 'keep') + for i in removefromkeeping: + self.logger.log(VERBOSE1, + "Updating Item {}: Removing {} from keepcommands " + "before storing equivalent command.".format(self._name, self._keep_commands.get(i))) + self._keep_commands.pop(i, None) + cond1 = appendcommand not in self._query_commands + cond2 = appendcommand not in self._special_commands['Display']['Command'] + if cond1 and cond2 and depending is True: + self._keep_commands[time.time()] = appendcommand + self.logger.debug( + "Updating Item {}: Not adding set command {} because dependency is not fullfilled, storing in keep commands: {}.".format( + self._name, appendcommand, self._keep_commands)) + else: + self._send_commands.append(appendcommand) + self._resend_counter = 0 + checkquery = True + self.logger.log(VERBOSE1, + "Updating Item {}: Resetting Resend Counter because adding new set command.".format( + self._name)) + self.logger.debug( + "Updating Item {}: Update Zone {} Command Set, adding to empty Commandlist {} for {}. Command: {}".format( + self._name, zone, self._send_commands, item, command_re)) + + if checkquery is True: + self.logger.debug( + "Updating Item {}: Command {} for zone: {}. Removing relevant query commands.".format( + self._name, command, zone)) + self._checkdependency('zone{}, {}, {}'.format(zone, command, value), 'checkquery') + else: + command = self.get_iattr_value(item.conf, 'avdevice_zone{}'.format(zone)) + self.logger.log(VERBOSE2, + "Updating Item {}: Did not update item {} with command {} for zone {}".format( + self._name, item, command, zone)) + except Exception as err: + self.logger.error("Updating Item {}: Problem updating item. Error: {}. Does the item exist?".format( + self._name, err)) + finally: + if not self._send_commands == []: + reorderlist = [] + index = 0 + for command in self._send_commands: + if command in self._query_commands: + reorderlist.append(command) + else: + reorderlist.insert(index, command) + index += 1 + self._send_commands = reorderlist + self._sendingcommand = self._send_commands[0] + + try: + if self._is_connected and self._send_commands and not self._is_connected == ['Connecting']: + self.logger.log(VERBOSE1, + "Updating Item {}: Updating item {}. Command list is {}. Sendingcommand: {}. ".format( + self._name, item, self._send_commands, self._sendingcommand)) + sending = self._send('command', 'updateitem') + self.logger.log(VERBOSE1, + "Updating Item {}: Updating item {}. Command list is {}. Return from send is {}".format( + self._name, item, self._send_commands, sending)) + cond1 = self._reset_onerror is True and emptycommand is False + cond2 = self._send_commands and not self._sendingcommand == 'done' and not self._is_connected + if cond1 and cond2: + if not self._send_commands[0].split(',')[0] == self._send_commands[0].split(',')[1]: + self.logger.log(VERBOSE1, + "Updating Item {}: Sending command {}. Starting to reset".format( + self._name, self._sendingcommand)) + resetting = self._resetitem('') + else: + resetting = '' + befehle = [x.split(',')[0] for x in self._send_commands] + try: + index = self._send_commands.index(self._sendingcommand) + self.logger.log(VERBOSE2, "Updating Item {}: Sending command {} " + "index is {}".format(self._name, self._sendingcommand, index)) + except Exception: + index = befehle.index(self._sendingcommand) + self.logger.log(VERBOSE1, "Updating Item {}: Sending command {} " + "not in Sendcommands {} list, but found in {}".format( + self._name, self._sendingcommand, self._send_commands, befehle)) + cond1 = self._send_commands[index] not in self._query_commands + cond2 = self._send_commands[index] not in self._special_commands['Display']['Command'] + if cond1 and cond2: + self._keep_commands[time.time()] = self._send_commands[index] + self._send_commands.pop(index) + if self._depend0_volume0 is True or self._depend0_power0 is True: + self._resetondisconnect('update_end') + try: + self._sendingcommand = self._send_commands[0] + except Exception: + self._sendingcommand = 'gaveup' + if resetting == '': + self.logger.debug( + "Updating Item {}: Connection error. Nothing reset.".format(self._name)) + else: + self.logger.info( + "Updating Item {}: Connection error. Resetting Item {}. " + "Keepcommands: {}. Sendcommands: {} Sendingcommand: {}".format( + self._name, resetting, self._keep_commands, + self._send_commands, self._sendingcommand)) + self._trigger_reconnect = True + + except Exception as err: + if self._is_connected: + self.logger.warning( + "Updating Item {}: Problem sending command. It is most likely not in the text file! Error: {}".format( + self._name, err)) + else: + self.logger.warning( + "Updating Item {}: Problem sending command - not connected! Error: {}".format( + self._name, err)) + self._trigger_reconnect = True + + def _displayignore(self, response, receivedvalue, caller): + if not caller == 'parsing_final': + self.logger.log(VERBOSE1, + "Display Ignore {}: Function called by: {}. Response: {}. Received Value: {}".format( + self._name, caller, response, receivedvalue)) + try: + displaycommand = self._special_commands['Display']['Command'] + displayignore = self._special_commands['Display']['Ignore'] + inputignore = self._special_commands['Input']['Ignore'] + inputcommands = self._special_commands['Input']['Command'] + responseignore = self._ignore_response + except Exception: + displaycommand = inputcommands = responseignore = '' + displayignore = inputignore = 1 + try: + sending = self._send_commands[0] + except Exception: + sending = '' + if receivedvalue is None: + try: + keyfound = False + for resp in response: + keyfound = True if resp in displaycommand and not displaycommand == '' else False + cond1 = sending in self._query_commands and len(self._send_commands) > 1 + cond2 = keyfound is not True and displayignore < 5 + if cond1 and cond2: + self._special_commands['Display']['Ignore'] = displayignore + 5 + if displaycommand not in self._ignore_response and '' not in self._ignore_response and not displaycommand == '': + self._ignore_response.append(displaycommand) + self.logger.log(VERBOSE2, + "Display Ignore {}: Command: {}. Display Ignore: {}, Input Ignore: {}".format( + self._name, sending, self._special_commands['Display']['Ignore'], inputignore)) + + elif sending not in self._query_commands or len(self._send_commands) <= 1 or keyfound is True: + if displayignore >= 5: + self._special_commands['Display']['Ignore'] = displayignore - 5 + self.logger.log(VERBOSE2, + "Display Ignore {}: Init Phase finished, Display Ignore: {}, Input Ignore: {}".format( + self._name, self._special_commands['Display']['Ignore'], inputignore)) + cond1 = self._special_commands['Display']['Ignore'] == 0 + cond2 = 1 not in inputignore and not displaycommand == '' + if cond1 and cond2: + if displaycommand in self._ignore_response: + try: + self._ignore_response.remove(displaycommand) + self.logger.log(VERBOSE2, "Display Ignore {}: Removing {} from ignore.".format( + self._name, displaycommand)) + except Exception as err: + self.logger.log(VERBOSE2, + "Display Ignore {}: Cannot remove {} from ignore. Message: {}".format( + self._name, displaycommand, err)) + cond1 = self._ignore_response == responseignore + cond2 = self._special_commands['Display']['Ignore'] == displayignore + cond3 = self._special_commands['Input']['Ignore'] == inputignore + if not (cond1 and cond2 and cond3): + self.logger.debug( + "Display Ignore {}: Ignored responses are now: {}. Display Ignore: {}, Input Ignore: {}".format( + self._name, self._ignore_response, self._special_commands['Display']['Ignore'], + self._special_commands['Input']['Ignore'])) + except Exception as err: + self.logger.debug( + "Display Ignore {}: Problems: {} in line {}.".format(self._name, err, sys.exc_info()[-1].tb_lineno)) + else: + try: + cond1 = response.startswith(tuple(inputcommands)) + cond2 = str(receivedvalue) in self._ignoredisplay + cond3 = '' not in self._ignoredisplay + cond4 = str(receivedvalue) not in self._ignoredisplay + if cond1 and cond2 and cond3: + for i in range(0, len(inputcommands)): + if response.startswith(inputcommands[i]): + self._special_commands['Input']['Ignore'][i] = 1 + if displaycommand not in self._ignore_response and not displaycommand == '' and '' not in self._ignore_response: + self._ignore_response.append(displaycommand) + self.logger.debug( + "Display Ignore {}: Data {} has value in ignoredisplay {}. Ignorecommands are now: {}." + " Display Ignore is {}. Input Ignore is {}".format(self._name, response, + self._ignoredisplay, self._ignore_response, + displayignore, inputignore)) + elif cond1 and cond4 and cond3: + for i in range(0, len(inputcommands)): + if response.startswith(inputcommands[i]): + self._special_commands['Input']['Ignore'][i] = 0 + self.logger.log(VERBOSE2, + "Display Ignore {}: Data {} with received value {} has NO value in ignoredisplay {}." + " Ignored responses are now: {}. Display Ignore is {}. Input Ignore is {}".format( + self._name, response, receivedvalue, self._ignoredisplay, self._ignore_response, + displayignore, inputignore)) + cond1 = displayignore == 0 and 1 not in inputignore + cond2 = not displaycommand == '' and displaycommand in self._ignore_response + if cond1 and cond2: + try: + self._ignore_response.remove(displaycommand) + self.logger.log(VERBOSE2, "Display Ignore {}: Removing {} from ignore.".format( + self._name, displaycommand)) + except Exception as err: + self.logger.log(VERBOSE2, + "Display Ignore {}: Cannot remove {} from ignore. Message: {}".format( + self._name, displaycommand, err)) + cond1 = self._ignore_response == responseignore + cond2 = self._special_commands['Display']['Ignore'] == displayignore + cond3 = self._special_commands['Input']['Ignore'] == inputignore + if not (cond1 and cond2 and cond3): + self.logger.debug( + "Display Ignore {}: Ignored responses are now: {}. Display Ignore: {}, Input Ignore: {}".format( + self._name, self._ignore_response, self._special_commands['Display']['Ignore'], + self._special_commands['Input']['Ignore'])) + except Exception as err: + self.logger.debug("Display Ignore {}: Problems: {}.".format(self._name, err)) + + # Sending commands to the device + def _send(self, command, caller): + self.logger.log(VERBOSE1, + "Sending {}: Sending function called by: {}. Command: {}.".format(self._name, caller, command)) + try: + if not self._send_commands == []: + if command == 'command': + to_send = self._send_commands[0].split(',')[0] + expected_resp = self._send_commands[0].split(',')[2] + elif command == 'query': + to_send = self._send_commands[0].split(',')[1] + expected_resp = self._send_commands[0].split(',')[2] + else: + try: + to_send = command.split(',')[0] + expected_resp = command.split(',')[2] + except Exception: + to_send = command + expected_resp = 'empty' + command = 'Resendcommand' + commandlist = to_send.split('|') + self.logger.log(VERBOSE1, "Sending {}: Starting to send {} {}. Caller: {}.".format( + self._name, command, to_send, caller)) + try: + self._sendingcommand = self._send_commands[0] + except Exception: + self._sendingcommand = to_send + response = self._send_commands[0].split(',')[2].split('|') + if not self._parsinginput: + self.logger.log(VERBOSE1, "Sending {}: Starting Parse Input. Expected response: {}".format( + self._name, response)) + self._parse_input_init('sending') + self._displayignore(response, None, 'sending') + + if self._trigger_reconnect is True: + self.logger.log(VERBOSE1, "Sending {}: Trying to connect while sending command".format(self._name)) + self.connect('send') + for cmd, multicommand in enumerate(commandlist): + result = None + try: + multicommand = eval(multicommand) + except Exception: + pass + if isinstance(multicommand, float) or isinstance(multicommand, int): + waitingtime = float(multicommand) + self.logger.log(VERBOSE1, "Sending {}: Waitingtime between commands: {}".format(self._name, waitingtime)) + self._wait(waitingtime) + else: + if self._rs232 is not None: + result = self._serialwrapper.write(u'{}\r'.format(multicommand)) + self._serialwrapper.flush() + self.logger.debug( + "Sending Serial {}: {} was sent {} from Multicommand-List {}. Returns {}. Sending command: {}".format( + self._name, command, multicommand, commandlist, result, self._sendingcommand)) + self._wait(0.2) + + elif self._tcp is not None: + result = self._tcpsocket.send(bytes('{}\r'.format(multicommand), 'utf-8')) + self.logger.debug( + "Sending TCP {}: {} was sent {} from Multicommand-List {}. Returns {}".format( + self._name, command, multicommand, commandlist, result)) + self._wait(0.2) + else: + self.logger.error( + "Sending {}: Neither IP address nor Serial device definition found".format(self._name)) + if cmd >= len(commandlist) - 1: + if not expected_resp and self._send_commands: + self.logger.log(VERBOSE1, "Sending {}: Removing first send command {}" + " because no response is expected".format(self._name, self._send_commands[0])) + self._send_commands.pop(0) + return result + except IOError as err: + if err.errno == 32: + self.logger.warning( + "Sending {}: Problem sending multicommand {}, not connected. Message: {}".format( + self._name, self._send_commands[0], err)) + if self._tcp is not None: + try: + self._tcpsocket.shutdown(2) + self._tcpsocket.close() + self.logger.debug("Sending {}: TCP socket closed".format(self._name)) + except Exception: + self.logger.log(VERBOSE1, "Sending {}: No TCP socket to close.".format(self._name)) + try: + if 'TCP' in self._is_connected: + self._is_connected.remove('TCP') + if 'Connecting' in self._is_connected: + self._is_connected.remove('Connecting') + self.logger.log(VERBOSE1, "Sending {}: reconnect TCP started.".format(self._name)) + self.connect('send_IOError_TCP') + except Exception as err: + self.logger.debug("Sending {}: Cannot reconnect TCP. Error: {}".format(self._name, err)) + elif self._rs232 is not None: + try: + self._serialwrapper.close() + self.logger.debug("Sending {}: Serial socket closed".format(self._name)) + except Exception: + self.logger.log(VERBOSE1, "Sending {}: No Serial socket to close.".format(self._name)) + try: + if 'Serial' in self._is_connected: + self._is_connected.remove('Serial') + if 'Connecting' in self._is_connected: + self._is_connected.remove('Connecting') + self.logger.log(VERBOSE1, "Sending {}: reconnect Serial started.".format(self._name)) + self.connect('send_IOError_RS232') + except Exception as err: + self.logger.debug("Sending {}: Cannot reconnect Serial. Error: {}".format(self._name, err)) + except Exception as err: + try: + self.logger.warning("Sending {}: Problem sending multicommand {}. Message: {}".format( + self._name, self._send_commands[0], err)) + except Exception: + self.logger.warning( + "Sending {}: Problem sending multicommand {}. Message: {}".format( + self._name, self._send_commands, err)) + + # Stopping function when SmarthomeNG is stopped + def stop(self): + self.alive = False + try: + self._sh.scheduler.change('avdevice-tcp-reconnect', active=False) + self._sh.scheduler.remove('avdevice-tcp-reconnect') + except Exception: + pass + try: + self._sh.scheduler.change('avdevice-serial-reconnect', active=False) + self._sh.scheduler.remove('avdevice-serial-reconnect') + except Exception: + pass + try: + self._tcpsocket.shutdown(2) + self._tcpsocket.close() + self.logger.debug("Stopping {}: closed".format(self._name)) + except Exception: + self.logger.log(VERBOSE1, "Stopping {}: No TCP socket to close.".format(self._name)) + try: + self._serialwrapper.close() + except Exception: + self.logger.log(VERBOSE1, "Stopping {}: No Serial socket to close.".format(self._name)) + + +if __name__ == '__main__': + logging.basicConfig( + level=logging.DEBUG, format='%(relativeCreated)6d %(threadName)s %(message)s') + # noinspection PyUnresolvedReferences + PluginClassName(AVDevice).run() diff --git a/avdevice/models/denon-avr1100.txt b/avdevice/_pv_1_3_6/models/denon-avr6300.txt similarity index 51% rename from avdevice/models/denon-avr1100.txt rename to avdevice/_pv_1_3_6/models/denon-avr6300.txt index ef2c90fc0..2e4816958 100755 --- a/avdevice/models/denon-avr1100.txt +++ b/avdevice/_pv_1_3_6/models/denon-avr6300.txt @@ -1,23 +1,42 @@ ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MINVALUE; MAXVALUE; RESPONSETYPE + +# General Commands 0; power; on; PWON|PWON; PW?; PW**; RW 0; power; off; PWSTANDBY; PW?; PW*******; RW 0; eco; set; ECO*; ECO?; ECO*; RW; ; ; ; str|bool +0; up; ; MNCUP; ; ; W +0; down; ; MNCDN; ; ; W +0; left; ; MNCLT; ; ; W +0; right; ; MNCRT; ; ; W +0; enter; ; MNENT; ; ; W +0; info; ; MNINF; ; ; W +0; menu; on; MNMEN ON; MNMEN?; MNMEN **; RW +0; menu; off; MNMEN OFF; MNMEN?; MNMEN ***; RW +# Firmware response often hast problems. Not recommended to implement this command. +#0; firmware; ; ; UGIDN; UGIDN ************|UGIDN **; R +# The display command is only working with receivers without HEOS +#0; display; ; NSE; NSE; NSA*|NSE*; RW; ; ; ; str + + +# Zone 1 1; power; on; ZMON; ZM?; ZM**; RW -1; power; off; ZMOFF; ZM?; ZM***; RW +1; power; off; ZMOFF; ZM?; ZM***; RW 1; mute; on; MUON; MU?; MU**; RW 1; mute; off; MUOFF; MU?; MU***; RW 1; sleep; set; SLP***; SLP?; SLP***; RW; ; 0; 120; num|bool -1; standby; set; STBY*; STBY?; STBY*; RW; ; ; ; str|bool -1; volume; set; MV**; MV?; MV**; RW; ; 30; 90 +1; standby; set; STBY***; STBY?; STBY***; RW; ; ; ; ; denon_standby +1; volume; set; MV**; MV?; MV**|MV***; RW; ; 30; 90; num; denon_volume 1; volume+; increase; MVUP; ; MV; W 1; volume-; decrease; MVDOWN; ; MV; W 1; volumelow; ; MV50; MV?; MV50; W; ; ; ; num 1; volumehigh; ; MV75; MV?; MV75; W; ; ; ; num -1; volumemax; set; MVMAX **; MV?; MVMAX **|MVMAX ***; RW +1; volumemax; set; MVMAX **; MV?; MVMAX **|MVMAX ***; RW; ; ; ; ; denon_volume 1; input; set; SI*; SI?; SI*; RW; ; ; ; str 1; mode; set; MS*; MS?; MS*; RW; ; ; ; str 1; audioinput; set; SD*; SD?; SD*; RW; ; ; ; str 1; videoinput; set; SV*; SV?; SV*; RW; ; ; ; str|bool + +# Finetuning 1; tone; on; PSTONE CTRL ON; PSTONE CTRL ?; PSTONE CTRL **; RW 1; tone; off; PSTONE CTRL OFF; PSTONE CTRL ?; PSTONE CTRL ***; RW 1; bass; set; PSBAS **; PSBAS ?; PSBAS **; RW; ; 40; 60 @@ -34,6 +53,40 @@ ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; 1; subwoofer; set; PSSWL **; PSSWL ?; PSSWL **; RW; ; 0; 62 1; cinemaeq; on; PSCINEMA EQ.ON; PSCINEMA EQ. ?; PSCINEMA EQ.**; RW 1; cinemaeq; off; PSCINEMA EQ.OFF; PSCINEMA EQ. ?; PSCINEMA EQ.***; RW +1; mainspeakers; set; PSSP:*; PSSP: ?; PSSP:*; RW; ; ; ; str +1; dynamicrange+; increase; PVENH UP; PVENH ?; PVENH; W +1; dynamicrange-; decrease; PVENH DOWN; PVENH ?; PVENH; W +1; dynamicrange; set; PVENH **; PVENH ?; PVENH **; RW; ; 0; 12 + +# Seperate Volume Control +1; volumefl; set; CVFL **; CV?; CVFL **|CVFL ***; RW; ; 0; 62; num; denon_volume +1; volumefl+; increase; CVFL UP; CV?; CVFL; W +1; volumefl-; decrease; CVFL DOWN; CV?; CVFL; W +1; volumefr; set; CVFR **; CV?; CVFR **|CVFR ***; RW; ; 0; 62; num; denon_volume +1; volumefr+; increase; CVFL UP; CV?; CVFR; W +1; volumefr-; decrease; CVFR DOWN; CV?; CVFR; W +1; volumec; set; CVC **; CV?; CVC **|CVC ***; RW; ; 0; 62; num; denon_volume +1; volumec+; increase; CVC UP; CV?; CVC; W +1; volumec-; decrease; CVC DOWN; CV?; CVC; W +1; volumec; set; CVC **; CV?; CVC **|CVC ***; RW; ; 0; 62; num; denon_volume +1; volumec+; increase; CVC UP; CV?; CVC; W +1; volumec-; decrease; CVC DOWN; CV?; CVC; W +1; volumesl; set; CVSL **; CV?; CVSL **|CVSL ***; RW; ; 0; 62; num; denon_volume +1; volumesl+; increase; CVSL UP; CV?; CVSL; W +1; volumesl-; decrease; CVSL DOWN; CV?; CVSL; W +1; volumesr; set; CVSR **; CV?; CVSR **|CVSR ***; RW; ; 0; 62; num; denon_volume +1; volumesr+; increase; CVSR UP; CV?; CVSR; W +1; volumesr-; decrease; CVSR DOWN; CV?; CVSR; W + +# Videoparams +1; aspectratio; set; VSASP*; VSASP ?; VSASP*; RW; ; ; ; str +1; monitorout; set; VSMONI*; VSMONI ?; VSMONI*; RW; ; ; ; int|str +1; resolution; set; VSSC*; VSSC ?; VSSC*; RW; ; ; ; str +1; audioout; set; VSAUDIO *; VSAUDIO ?; VSAUDIO *; RW; ; ; ; str +1; videoprocessing; set; VSVPM*; VSVPM ?; VSVPM*; RW; ; ; ; str +1; stretch; set; VSVST*; VSVST ?; VSVST*; RW; ; ; ; bool + +# Zone 2 2; power; on; Z2ON; Z2?; Z2**; RW 2; power; off; Z2OFF; Z2?; Z2***; RW 2; input; set; Z2*; Z2?; Z2*; RW; ; ; ; str @@ -43,9 +96,11 @@ ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; 2; volume-; decrease; Z2DOWN; ; Z2; W 2; volumelow; ; Z250; MV?; Z250; W; ; ; ; num 2; volumehigh; ; Z275; MV?; Z275; W; ; ; ; num -2; volume; set; Z2**; Z2?; Z2**; RW; ; 0; 90 +2; volume; set; Z2**; Z2?; Z2**; RW; num; 0; 90 2; standby; set; Z2STBY*; Z2STBY?; Z2STBY*; RW; ; ; ; str|bool 2; sleep; set; Z2SLP***; Z2SLP?; Z2SLP***; RW; ; 0; 120; num|bool + +# Zone 3 3; power; on; Z3ON; Z3?; Z3**; RW 3; power; off; Z3OFF; Z3?; Z3***; RW 3; input; set; Z3*; Z3?; Z3*; RW; ; ; ; str @@ -55,6 +110,6 @@ ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; 3; volume-; decrease; Z3DOWN; ; Z3; W 3; volumelow; ; Z350; MV?; Z350; W; ; ; ; num 3; volumehigh; ; Z375; MV?; Z375; W; ; ; ; num -3; volume; set; Z3**; Z3?; Z3**; RW; ; 0; 90 +3; volume; set; Z3**; Z3?; Z3**; RW; num; 0; 90 3; standby; set; Z3STBY*; Z3STBY?; Z3STBY*; RW; ; ; ; str|bool 3; sleep; set; Z3SLP***; Z3SLP?; Z3SLP***; RW; ; 0; 120; num|bool diff --git a/avdevice/_pv_1_3_6/models/epson-tw5000.txt b/avdevice/_pv_1_3_6/models/epson-tw5000.txt new file mode 100755 index 000000000..fde5f1ea4 --- /dev/null +++ b/avdevice/_pv_1_3_6/models/epson-tw5000.txt @@ -0,0 +1,3 @@ +ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MINVALUE; MAXVALUE; TYPE +0; power; on; PWR ON; PWR?; :PWR=0*|:WR=0*|PWR=0*; RW; no; 0; 1; bool +0; power; off; PWR OFF; PWR?; :PWR=0*|:WR=0*|PWR=0*; RW; no; 0; 1; bool diff --git a/avdevice/_pv_1_3_6/models/oppo-udp203.txt b/avdevice/_pv_1_3_6/models/oppo-udp203.txt new file mode 100755 index 000000000..0f394340a --- /dev/null +++ b/avdevice/_pv_1_3_6/models/oppo-udp203.txt @@ -0,0 +1,47 @@ +ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MINVALUE; MAXVALUE; RESPONSETYPE +0; power; on; #PON; #QPW; @PON OK **|@QPW OK **|@UPW *; RW +0; power; off; #POF; #QPW; @POF OK ***|@QPW OK ***|@UPW *; RW +0; verbose; set; #SVM *; #QVM; @SVM OK *|@QVM OK *; RW +0; eject; open; #EJT; ; @EJT OK ****|@UPL ****; RW +0; eject; close; #EJT; ; @EJT OK *****|@UPL ****; RW +0; status; ; #QPL; #QPL; @UPL *{str}|@QPL OK *{str}|@QPL ER *{str}; R; ; ; ; str +0; pure; on; #PUR; ; @PUR OK **; RW; ; ; ; bool +0; pure; off; #PUR; ; @PUR OK ***; RW; ; ; ; bool +''' +0; num1; ; #NU1; ; @OK|@NU1 OK; W +0; num2; ; #NU2; ; @OK|@NU2 OK; W +0; num3; ; #NU3; ; @OK|@NU3 OK; W +0; num4; ; #NU4; ; @OK|@NU4 OK; W +0; num5; ; #NU5; ; @OK|@NU5 OK; W +0; num6; ; #NU6; ; @OK|@NU6 OK; W +0; num7; ; #NU7; ; @OK|@NU7 OK; W +0; num8; ; #NU8; ; @OK|@NU8 OK; W +0; num9; ; #NU9; ; @OK|@NU9 OK; W +0; num0; ; #NU0; ; @OK|@NU0 OK; W +''' +0; stop; ; #STP; ; @OK STOP|@STP OK STOP|@STP OK FULL STOP; RW +0; play; ; #PLA; ; @OK PLAY|@PLA OK PLAY; RW +0; pause; ; #PAU; ; @OK PAUSE|@PAU OK PAUSE; RW +0; disctype; ; #QDT; #QDT; @UDT *|@QDT OK *; R; ; ; ; str +''' +0; track; set; #SRH T*; #QTK; @QTK OK **/??|@UTC ??? ***; RW +0; chapter; set; #SRH C*; #QCH; @QCH OK **|UTC ***; RW +0; hdr; set; #SHR *; #QHR; @QHR OK *; RW; ; ; ; str +0; subtitleshift; set; #SSH *; #QSH; @QSH OK *; W; ; ; ; num +0; timedisplay; set; #STC; ; @STC OK *; RW; ; ; ; str +0; trackelapsed; ; #QTE; #QTE; @QTE OK ********|@UTC ??? ??? T ********; R; ; ; ; str +0; trackremain; ; #QTR; #QTR; @QTR OK ********|@UTC ??? ??? X ********; R; ; ; ; str +0; chapterelapsed; ; #QCE; #QCE; @QCE OK ********|@UTC ??? ??? C ********; R; ; ; ; str +0; chapterremain; ; #QCR; #QCR; @QCR OK ********|@UTC ??? ??? K ********; R; ; ; ; str +0; totalelapsed; ; #QEL; #QEL; @QEL OK ********|@UTC ??? ??? E ********; R; ; ; ; str +0; totalremain; ; #QRE; #QRE; @QRE OK ********|@UTC ??? ??? R ********; R; ; ; ; str +''' +0; trackname; ; ; #QTN; @QTN OK *|@QTN ER INVALID; R; ; ; ; str +0; albumname; ; ; #QTA; @QTA OK *|@QTA ER INVALID; R; ; ; ; str +0; artistname; ; ; #QTP; @QTP OK *|@QTP ER INVALID; R; ; ; ; str +0; audiotrack; ; #AUD; #QTK; @QTK OK **/??|@UAT ?{str} **/?? ??? ???|@QTK OK */?|@UAT ?{str} */? ??? ???; RW; ; ; ; num +0; audiotype; ; ; #QAT; @UAT *{str} ??/?? ??? ???|@QAT OK *{str} ?/? ?{str}; R; ; ; ; str +#0; audiochannels; ; ; ; @UAT ?? ??/?? ??? ***; R; ; ; ; str +0; audiolanguage; ; #AUD; ; @QAT OK ?{str} ?/? *{str}|@QAT OK ?{str} ??/?? *{str}|@UAT ?{str} ??/?? *** ???; RW; ; ; ; str +#0; subtitletrack; ; #SUB; #QST; @QST OK **|@UST **; RW +#0; subtitlelanguage; ; #SUB; #QST; @QST OK ??/?? ***|@UST ??/?? ***; RW diff --git a/avdevice/_pv_1_3_6/models/oppo-udp203_real.txt b/avdevice/_pv_1_3_6/models/oppo-udp203_real.txt new file mode 100755 index 000000000..967da2c27 --- /dev/null +++ b/avdevice/_pv_1_3_6/models/oppo-udp203_real.txt @@ -0,0 +1,68 @@ +ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MAXVALUE; RESPONSETYPE +0; power; on; #PON; #QPW; @PON OK **|@UPW *|OK **; RW +0; power; off; #POFF; #QPW; @POF OK ***|@UPW *|OK ***; RW +0; eject; open; #EJT; ; @EJT OK ****|@OK ****|@UPL ****; RW +0; eject; close; #EJT; ; @EJT OK *****|@OK *****|@UPL ****; RW +0; track; set; #SRH T*; #QTK; @UTC ??? ***; RW +0; chapter; set; #SRH C*; #QCH; @UTC ***; RW +0; hdr; set; #SHR *; #QHR; @OK *; RW; ; ; str +0; subtitleshift; set; #SSH *; #QSH; @OK *; W; ; ; num +0; timedisplay; set; #STC; ; @OK *; RW; ; ; str +0; trackelapsed; query; #QTE; #QTE; @OK ********|@UTC ??? ??? T ********; RW +0; trackremain; query; #QTR; #QTR; @OK ********|@UTC ??? ??? X ********; RW +0; chapterelapsed; query; #QCE; #QCE; @OK ********|@UTC ??? ??? C ********; RW +0; chapterremain; query; #QCR; #QCR; @OK ********|@UTC ??? ??? K ********; RW +0; totalelapsed; query; #QEL; #QEL; @OK ********|@UTC ??? ??? E ********; RW +0; totalremain; query; #QRE; #QRE; @OK ********|@UTC ??? ??? R ********; RW +0; disctype; ; #QDT; #QDT; OK BD-MV|OK DVD-VIDEO|OK DVD-AUDIO|OK SACD|OK CDDA|OK DATA-DISC|UDT BD-MV|UDT DVD-VIDEO|UDT DVD-AUDIO|UDT SACD|UDT CDDA|UDT DATA-DISC; R +0; status; ; #QPL; #QPL; @OK NO DISC|@OK LOADING|@OK OPEN|@OK CLOSE|@UPL DISC|@UPL LOAD|@UPL OPEN|@UPL CLOS|@OK SCREEN SAVER|@QPL OK NO DISC|@QPL OK LOADING|@QPL OK OPEN|@QPL OK CLOSE|@QPL UPL DISC|@QPL UPL LOAD|@QPL UPL OPEN|@QPL UPL CLOS|@QPL OK SCREEN SAVER; RW +0; dimmer; ; #DIM; ; @OK ON|@OK DIM|@OK OFF; W +0; pure; set; #PUR; ; @PUR OK **|@PUR OK ***; W; ; ; bool +0; num0; ; #NU1; ; @OK|@NU1 OK; W +0; num2; ; #NU2; ; @OK|@NU2 OK; W +0; num3; ; #NU3; ; @OK|@NU3 OK; W +0; num4; ; #NU4; ; @OK|@NU4 OK; W +0; num5; ; #NU5; ; @OK|@NU5 OK; W +0; num6; ; #NU6; ; @OK|@NU6 OK; W +0; num7; ; #NU7; ; @OK|@NU7 OK; W +0; num8; ; #NU8; ; @OK|@NU8 OK; W +0; num9; ; #NU9; ; @OK|@NU9 OK; W +0; num0; ; #NU0; ; @OK|@NU0 OK; W +0; clear; ; #CLR; ; @OK; W +0; goto; ; #GOT; ; @OK; W +0; home; ; #HOM; #QPL; @OK HOME MENU|@UPL HOME; RW +0; pageup; ; #PUD; ; @OK; W +0; pagedown; ; #PDN; ; @OK; W +0; osd; ; #OSD; ; @OK; W +0; topmenu; ; #TTL; ; @OK; W +0; popupmenu; ; #MNU; ; @OK; W +0; up; ; #NUP; ; @OK; W +0; left; ; #NLT; ; @OK; W +0; right; ; #NRT; ; @OK; W +0; down; ; #NDN; ; @OK; W +0; enter; ; #SEL; ; @OK; W +0; setup; ; #SET; #QPL; @OK SETUP; W +0; return; ; #RET; ; @OK; W +0; red; ; #RED; ; @OK; W +0; green; ; #GRN; ; @OK; W +0; blue; ; #BLU; ; @OK; W +0; yellow; ; #YLW; ; @OK; W +0; stop; ; #STP; #QPL; @OK STOP|@UPL STOP; RW +0; play; ; #PLA; #QPL; @OK PLAY|@UPL PLAY; RW +0; pause; ; #PAU; #QPL; @OK PAUSE|@UPL PAUSE; RW +0; previous; ; #PRE; ; @OK; W +0; next; ; #NXT; ; @OK; W +0; rewind; ; #REV; #QPL; @OK FREV|@UPL FRV?; RW +0; fastforward; ; #FWD; #QPL; @OK FFWD|@UPL FFW?; RW +0; audiotrack; ; #AUD; #QAT; @UAT ?? **/??; RW +0; audiotype; ; ; ; @UAT ** ??/?? ??? ***; R +0; audiolanguage; ; #AUD; #QAT; @UAT ?? ??/?? ***; RW +0; subtitletrack; ; #SUB; #QST; @UST **/??; RW +0; subtitlelanguage; ; #SUB; #QST; @UST ??/?? ***; RW +0; option; ; #OPT; ; @OK; W +0; m3d; ; #M3D; ; @OK; W +0; pictureadjustment; ; #SEH; ; @OK; W +0; info; ; #INH; ; @OK; W +0; avsync; ; #AVS; ; @OK; W +0; gapless; ; #GPA; ; @OK; W +0; verbose; set; #SVM *; #QVM; @OK *|@SVM OK *|@QVM OK *; RW diff --git a/avdevice/_pv_1_3_6/models/sc-lx86.txt b/avdevice/_pv_1_3_6/models/sc-lx86.txt new file mode 100755 index 000000000..beba7af2c --- /dev/null +++ b/avdevice/_pv_1_3_6/models/sc-lx86.txt @@ -0,0 +1,65 @@ +ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MINVALUE; MAXVALUE; RESPONSETYPE + +# General Commands +0; title; ; ; ; GEH01020?; R; ; ; ; str +0; station; ; ; ; GEH04022?; R; ; ; ; str +0; genre; ; ; ; GEH05024?; R; ; ; ; str +0; display; ; ?FL; ?FL; FL*; R; ; ; ; str + +# Zone 1 +1; power; on; PO|PO; ?P; PWR*; RW; yes +1; power; off; PF; ?P; PWR*; RW; yes +1; volume+; increase; VU; ; VOL; W +1; volume-; decrease; VD; ; VOL; W +1; volumehigh; ; 150VL; ?V; VOL150; W +1; volumelow; ; 110VL; ?V; VOL110; W +1; volume; set; ***VL; ?V; VOL***; RW; ; 0; 161 +1; mute; on; MO; ?M; MUT*; RW; yes +1; mute; off; MF; ?M; MUT*; RW; yes +1; mode; set; ****SR; ?S; SR****; RW +1; playingmode; ; ?L; ?L; LM****; R; ; ; ; str +1; speakers; set; *SPK; ?SPK; SPK*; RW +1; input; set; **FN; ?F; FN**; RW +1; tone; on; 1TO; ?TO; TO*; RW +1; tone; off; 0TO; ?TO; TO*; RW +1; bass; set; **BA; ?BA; BA**; RW; ; 0; 12 +1; trebble; set; **TR; ?TR; TR**; RW; ; 0; 12 +1; bass+; increase; BI; ; BA; W +1; bass-; decrease; BD; ; BA; W +1; trebble+; increase; TI; ; TR; W +1; trebble-; decrease; TD; ; TR; W +1; dialog; set; *ATH; ?ATH; ATH*; RW +1; HDMI; set; *HO; ?HO; HO*; RW +1; input+; increase; FU; ?F; FN; W +1; input-; decrease; FD; ?F; FN; W +1; radiof+; ; TPI; ; PR; W; ; ; ; str +1; radiof-; ; TPD; ; PR; W; ; ; ; str + +# Zone 2 +2; power; on; APO|APO; ?AP; APR*; RW; yes +2; power; off; APF; ?AP; APR*; RW; yes +2; volume+; increase; ZU; ; ZV; W +2; volume-; decrease; ZD; ; ZV; W +2; volumehigh; ; 70ZV; ?ZV; ZV70; W +2; volumelow; ; 45ZV; ?ZV; ZV45; W +2; volume; set; **ZV; ?ZV; ZV**; RW; ; 0; 81 +2; mute; on; Z2MO; ?Z2M; Z2MUT*; RW; yes +2; mute; off; Z2MF; ?Z2M; Z2MUT*; RW; yes +2; input; set; **ZS; ?ZS; Z2F**; RW + +# Zone 3 +3; power; on; BPO|BPO; ?BP; BPR*; RW; yes +3; power; off; BPF; ?BP; BPR*; RW; yes +3; volume+; increase; YU; ; YV; W +3; volume-; decrease; YD; ; YV; W +3; volumehigh; ; 75YV; ?YV; YV75; W +3; volumelow; ; 45YV; ?YV; YV45; W +3; volume; set; **YV; ?YV; YV**; RW; ; 0; 81 +3; mute; on; Z3MO; ?Z3M; Z3MUT*; RW; yes +3; mute; off; Z3MF; ?Z3M; Z3MUT*; RW; yes +3; input; set; **ZT; ?ZT; Z3F**; RW + +# Zone 4 +4; power; on; ZEO; ?ZEP; ZEP*; RW; yes +4; power; off; ZEF; ?ZEP; ZEP*; RW; yes +4; input; set; **ZEA; ?ZEA; ZEA**; RW diff --git a/avdevice/_pv_1_3_6/models/vsx-923.txt b/avdevice/_pv_1_3_6/models/vsx-923.txt new file mode 100755 index 000000000..08177a792 --- /dev/null +++ b/avdevice/_pv_1_3_6/models/vsx-923.txt @@ -0,0 +1,47 @@ +ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MINVALUE; MAXVALUE; RESPONSETYPE; TRANSLATIONFILE +# General Commands +0; title; ; ; ; GEH01020; R; ; ; ; str +0; station; ; ; ; GEH04022; R; ; ; ; str +0; genre; ; ; ; GEH05024; R; ; ; ; str +0; display; ; ?FL; ?FL; FL*; R + +# Zone 1 +1; power; on; PO|PO; ?P; PWR*; RW; yes +1; power; off; PF; ?P; PWR*; RW; yes +1; volume+; increase; VU; ; VOL; W +1; volume-; decrease; VD; ; VOL; W +1; volumehigh; ; 150VL; ?V; VOL150; W +1; volumelow; ; 110VL; ?V; VOL110; W +1; volume; set; ***VL; ?V; VOL***; RW; no; 10; 160 +1; mute; on; MO; ?M; MUT*; RW; yes +1; mute; off; MF; ?M; MUT*; RW; yes +1; input; set; **FN; ?F; FN**; RW; ; ; ; ; pioneer_input +1; mode; set; ****SR; ?S; SR****; RW; ; ; ; num; pioneer_SR +1; playingmode; ; ?L; ?L; LM****; R; ; ; ; str,int; pioneer_LM +1; speakers; set; *SPK; ?SPK; SPK*; RW +1; tone; on; 1TO; ?TO; TO*; RW +1; tone; off; 0TO; ?TO; TO*; RW +1; bass; set; **BA; ?BA; BA**; RW; no; 0; 12 +1; trebble; set; **TR; ?TR; TR**; RW; no; 0; 12 +1; bass+; increase; BI; ; BA; W +1; bass-; decrease; BD; ; BA; W +1; trebble+; increase; TI; ; TR; W +1; trebble-; decrease; TD; ; TR; W +1; dialog; set; *ATH; ?ATH; ATH*; RW +1; HDMI; set; *HO; ?HO; HO*; RW +1; input+; increase; FU; ?F; FN; W +1; input-; decrease; FD; ?F; FN; W +1; radiof+; ; TPI; ; PR; W; ; ; ; str +1; radiof-; ; TPD; ; PR; W; ; ; ; str + +# Zone 2 +2; power; on; APO|APO; ?AP; APR*; RW; yes +2; power; off; APF; ?AP; APR*; RW; yes +2; volume+; increase; ZU; ; ZV; W +2; volume-; decrease; ZD; ; ZV; W +2; volumehigh; ; 75ZV; ?ZV; ZV75; W +2; volumelow; ; 45ZV; ?ZV; ZV45; W +2; volume; set; **ZV; ?ZV; ZV**; RW; no; 0; 81 +2; mute; on; Z2MO; ?Z2M; Z2MUT*; RW; yes +2; mute; off; Z2MF; ?Z2M; Z2MUT*; RW; yes +2; input; set; **ZS; ?ZS; Z2F**; RW; ; ; ; ; pioneer_input diff --git a/avdevice/_pv_1_3_6/plugin.yaml b/avdevice/_pv_1_3_6/plugin.yaml new file mode 100755 index 000000000..218ae60b9 --- /dev/null +++ b/avdevice/_pv_1_3_6/plugin.yaml @@ -0,0 +1,334 @@ +# Metadata for the Smart-Plugin +plugin: + # Global plugin attributes + type: interface # plugin type (gateway, interface, protocol, system, web) + description: + de: 'Steuerung von diversen AV Geräten über TCP/IP und RS232 Schnittstelle, **seit SmartHomeNG v1.3**' + en: 'Controlling AV devices via TCP/IP and RS232' + maintainer: onkelandy + tester: Foxi352 # Who tests this plugin? + keywords: av denon pioneer epson oppo player amp receiver projector rs232 telnet tcpip +# documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page + support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1097870-neues-plugin-av-device-f%C3%BCr-yamaha-pioneer-denon-etc + + version: 1.3.6 # Plugin version + sh_minversion: 1.3 # minimum shNG version to use this plugin +# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) + multi_instance: True # plugin supports multi instance + classname: AVDevice # class containing the plugin + +parameters: + # Definition of parameters to be configured in etc/plugin.yaml + model: + type: str + default: '' + mandatory: True + description: + de: 'Name des Geräts. Muss mit dem Namen der Textdatei unter plugins/avdevice korrelieren, die sämtliche Befehle beinhaltet.' + en: 'Name of AV device. Has to correspond to a text file with the same name in the folder plugins/avdevice including all commands.' + + update_exclude: + type: str + default: '' + description: + de: "Caller, bei denen kein Itemupdate vollzogen werden soll. Dies ist hilfreich, um beispielsweise mittels on_change Items abhängig von einem anderen Item zu aktualisieren, ohne dass die Updatefunktion des Plugins getriggert wird (z.B. für play/stop/pause). Es können mehrere durch Komma getrennte Einträge definiert werden." + en: "Define calles that shouldn't trigger an item update. This is helpful if you want to change values of items based on other items by using on_change or on_update functions. In that case the plugin wouldn't update the dependent item additionally (e.g. play/pause/stop). You can define a list of callers delimited by ," + + tcp_ip: + type: ip + default: 0.0.0.0 + description: + de: 'Beim Nutzen der TCP Verbindungen ist die IP Adresse des Endgeräts anzugeben.' + en: 'If you use TCP connection define IP address of your device.' + + tcp_port: + type: int + default: 23 + description: + de: 'Beim Nutzen der TCP Verbindungen ist der Port anzugeben, auf dem das Gerät Verbindungen zulässt. Für Denon: 23, für Pioneer: 8002.' + en: 'If you use TCP connection define the port where your device accepts TCPIP connections. For Denon use 23, for Pioneer 8002.' + + tcp_timeout: + type: int + default: 1 + description: + de: 'Beim Nutzen der TCP Verbindungen kann ein Timeout angegeben werden.' + en: 'If you use TCP connection you can define a connection timeout.' + + rs232_port: + type: str + default: '' + description: + de: "Beim Nutzen einer RS232 Schnittstelle (empfohlen!) ist die serielle Schnittstelle anzugeben." + en: "If you use a RS232 cable to communicate with your device (highly recommended!) define the serial port." + + rs232_baudrate: + type: int + default: 9600 + description: + de: "Beim Nutzen einer RS232 Schnittstelle ist die benötigte Baudrate anzugeben." + en: "If you use a RS232 interface define the baudrate." + + rs232_timeout: + type: float + default: 0.1 + description: + de: "Beim Nutzen einer RS232 Schnittstelle kann ein Timeout zum Lesen und Schreiben definiert werden." + en: "If you use a RS232 interface you can define read and write timeout." + + ignoreresponse: + type: str + default: 'RGB,RGC,RGD,GBH,GHH,VTA,AUA,AUB' + description: + de: "Das Plugin ignoriert Antworten die mit den hier angegebenen Werten starten, beispielsweise Rückmeldungen für die Menünavigation, etc. Der Defaultwert ist für Pioneer Receiver empfohlen." + en: "The plugin doesn't care about responses from the device starting with the given values. List responses for menu navigation, etc. The default value is recommended for Pioneer receivers." + + forcebuffer: + type: str + default: 'GEH01020,GEH04022,GEH05024,R' + description: + de: "Wenn aus irgendeinem Grund die Antworten nicht gepuffert werden sollen, können hier dennoch Antworten definiert werden, die sehr wohl gepuffert werden. Dies ist besonders wichtig bei Informationen, die schnell hintereinander gesendet werden bzw. wechseln wie Künstler, Musiktitel, Radiostation, etc. Der Defaultwert ist für Pioneer Receiver empfohlen." + en: "If for whatever reason you don't want to buffer the response from your device you can still define specific responses that should get buffered. This is important for responses that change or get sent very quickly. Artist, title, radio station, etc. are examples that should be put here. The default value is recommended for Pioneer receivers." + + inputignoredisplay: + type: str + default: '' + description: + de: "Die LCD Anzeige auf dem Gerät wird mitunter sehr häufig aktualisiert, zB bei einem scrollenden Text bei Songtiteln. Um ein ständiges Update und dadurch Konflikte mit tatsächlich relevanten Rückmeldungen zu vermeiden, können hier Source Typen hinterlegt werden. Internet Radio, LAN Streaming, etc. werden empfohlen. Für Pioneer-Receiver werden empfohlen: 26,38,40,41,44,17,02,48,0" + en: "The value of the LCD display on your receiver might get updated very often, e.g. when it shows song titles as a scrolling text. To avoid constant display updates and therefore possible confusion with relevant answers of your device listing source inputs like internet radio, LAN streaming, etc. here is highly recommended. For Pioneer receivers use: 26,38,40,41,44,17,02,48,0" + + dependson_item: + type: str + default: '' + description: + de: "Wenn das angegebene Item den angegebenen Wert erhält, werden die Befehle gesendet, ansonsten nicht. Das ist insbesondere dann sinnvoll, wenn das Gerät an einer schaltbaren Steckdose hängt." + en: " If given item has given value the commands are sent to the device, otherwise they are not. Relevant if you have your device connected to a power socket that can be turned off." + + dependson_value: + type: bool + default: True + description: + de: "Wenn das angegebene Item den angegebenen Wert erhält, werden die Befehle gesendet, ansonsten nicht. Das ist insbesondere dann sinnvoll, wenn das Gerät an einer schaltbaren Steckdose hängt." + en: " If given item has given value the commands are sent to the device, otherwise they are not. Relevant if you have your device connected to a power socket that can be turned off." + + errorresponse: + type: str + default: 'E02,E04,E06' + description: + de: "Standard Fehlermeldungen des Geräts, bei Pioneer beispielsweise ein 'E' gefolgt von einer Nummer. Werden diese Antworten hier nicht angegeben, werden Rückmeldungen unter Umständen deutlich langsamer verarbeitet, aber voraussichtlich trotzdem erkannt." + en: "The standard error responses from your device. For Pioneer receivers they are 'E' followed by a number. If no values are provided error answers from your device might get recognized much slower but actually should still get recognized." + + resetonerror: + type: bool + default: False + description: + de: "Zurücksetzen des Items auf den vorigen Wert, wenn kein Update durchgeführt werden konnte, zB das Setzen der Lautstärke in einer abgeschalteten Zone. Sobald das dependson Item ausgeschaltet wird oder mehrere Verbindungs- und Sendeversuche fehlgeschlagen sind, wird das Item zurückgesetzt, damit keine falschen Werte in der Visu angezeigt werden." + en: "Reset the value of the item that could not be updated. E.g. you set the volume of zone 2 when it is not powered on. If either the dependson item is off or the device sends an error response or after several connection and send retries the expected response is not received, the item gets set to the value it had before you sent the command. That way you avoid having a wrong value displayed in your Visu." + + depend0_power0: + type: bool + default: False + description: + de: "Wenn das dependson Item abgeschaltet ist, werden alle Poweritems ebenfalls auf 0 gesetzt. Das ist dann relevant, wenn beispielsweise das Gerät eingeschaltet ist, die Steckdose aber ausgeschaltet wird. Durch Aktivieren dieser Funktion werden automatisch die Poweritems auf 0 gesetzt." + en: "If the dependson item is off the power off all zones are set to off. This is especially relevant for a correct representation in your Visu when you have a powered on device but turn off the power socket." + + depend0_volume0: + type: bool + default: False + description: + de: "Wie beim obigen Attribut dient auch diese Funktion zum korrekten Update der Visu auf den Lautstärkewert 0, sobald das dependson Item deaktiviert wird (zB Ausschalten der Steckdose)." + en: "Same as above but in this case the volume is set to 0 for all zones. This is for Visu purposes only." + + sendretries: + type: int + default: 10 + description: + de: "Dieser Wert definiert, wie oft bei einer falschen Antwort versucht werden soll, den Befehl nochmals zu senden." + en: "This value defines how often a command should be sent when receiving a wrong answer from the device." + + resendwait: + type: float + default: 1.0 + description: + de: "Angabe der Pause zwischen Resend Versuchen in Sekunden" + en: "Seconds the plugin should wait between each resend retry." + + reconnectretries: + type: int + default: 13 + description: + de: "Anzahl der Verbindungsversuche bei Verbindungsproblemen. Das ist insbesondere bei TCP Verbindungen von Geräten relevant, die an schaltbaren Steckdosen hängen, da diese oftmals 30-40 Sekunden zum Hochfahren benötigen." + en: "If the plugin can not connect to the device it retries this often. This is especially useful for TCP connections on devices that are plugged into a switchable socket as most receivers need about 40-50 seconds to boot their network device." + + secondstokeep: + type: int + default: 50 + description: + de: "Dauer in Sekunden, wie lange ein Kommando, das nicht erfolgreich war in einem Zwischenspeicher aufbewahrt werden soll. Dies ist besonders bei TCP Verbindungen mit Geräten an schaltbaren Steckdosen relevant, da diese ofmals 30-40 Sekunden zum Hochfahren benötigen." + en: "Seconds the plugin should temporarily save a command to retry later on after establishing a connection. This is especially useful for TCP connections on devices that are plugged into a switchable socket as most receivers need about 40-50 seconds to boot their network device." + + responsebuffer: + type: int + default: 5 + description: + de: "Schnell hintereinander empfangene Werte werden bei einer negativen Attributangabe im Puffer gespeichert und gemeinsam verarbeitet. Der Standardwert sollte dafür sorgen, dass keine Antworten verloren gehen. Einige Receiver antworten unter Umständen immer zuerst mit der Angabe zum auf dem Display gezeigten Wert. Der Puffer sorgt dafür, dass auch eine nachfolgende Rückmeldung evaluiert wird." + en: "Set this to a number to collect quickly received responses in a buffer and evaluate them collectively. The standard value should be fine and prevent responses getting lost. Some receivers might first respond to a command with an update of the display and then with the actual value. The buffer ensures the correct evaluation of the response." + + autoreconnect: + type: bool + default: False + description: + de: "Automatischer Versuch, sich mit dem Gerät zu verbinden, wenn keine Rückmeldung kommt oder die Verbindung verloren wurde. Dies sollte nicht notwendig sein, da das Plugin ohnehin bei jedem neuen Senden eines Befehls einen Verbindungsaufbauversuch startet." + en: "Automatically tries to reconnect if no response is received or connection is lost. This should not be necessary as the plugin always tries to reconnect before sending a command." + + statusquery: + type: bool + default: True + description: + de: "Verbindet sich das Plugin, werden die Werte automatisch abgefragt, auch wenn kein Depend=Init im Item angegeben ist. Sollen nur Items abgefragt werden, bei denen das depend-Attribut auf init gesetzt ist, sollte dieser Wert auf False gestellt werden." + en: "As soon as the plugin connects to the device the values get queried automatically even if the Depend=Init is not set in the items. If you want to query only those items that are set explicitly change this value to False." + +item_attributes: + avdevice_zone0_depend: + type: list(str) + description: + de: 'Hier wird der Funktionsname eingefügt, von dem ein Item abhängig sein soll. Der Bass des Verstärkers lässt sich beispielsweise nur ändern, wenn Tone aktiviert ist. "tone = True" führt dazu, dass das Item nur geändert wird, wenn die Bedingung erfüllt ist. Mehrere Bedingungen werden als "oder" interpretiert.' + en: 'Insert a function name your item should be depending on. For exmaple changing the Bass value of your amp is only useful/possible, if tone is activated. "tone = True" makes sure, that the item only gets updated if the dependency is fullfilled. Multiple entries are interepreted as "or".' + + avdevice_zone1_depend: + type: list(str) + description: + de: 'Hier wird der Funktionsname eingefügt, von dem ein Item abhängig sein soll. Der Bass des Verstärkers lässt sich beispielsweise nur ändern, wenn Tone aktiviert ist. "tone = True" führt dazu, dass das Item nur geändert wird, wenn die Bedingung erfüllt ist. Mehrere Bedingungen werden als "oder" interpretiert.' + en: 'Insert a function name your item should be depending on. For exmaple changing the Bass value of your amp is only useful/possible, if tone is activated. "tone = True" makes sure, that the item only gets updated if the dependency is fullfilled. Multiple entries are interepreted as "or".' + + avdevice_zone2_depend: + type: list(str) + description: + de: 'Hier wird der Funktionsname eingefügt, von dem ein Item abhängig sein soll. Der Bass des Verstärkers lässt sich beispielsweise nur ändern, wenn Tone aktiviert ist. "tone = True" führt dazu, dass das Item nur geändert wird, wenn die Bedingung erfüllt ist. Mehrere Bedingungen werden als "oder" interpretiert.' + en: 'Insert a function name your item should be depending on. For exmaple changing the Bass value of your amp is only useful/possible, if tone is activated. "tone = True" makes sure, that the item only gets updated if the dependency is fullfilled. Multiple entries are interepreted as "or".' + + avdevice_zone3_depend: + type: list(str) + description: + de: 'Hier wird der Funktionsname eingefügt, von dem ein Item abhängig sein soll. Der Bass des Verstärkers lässt sich beispielsweise nur ändern, wenn Tone aktiviert ist. "tone = True" führt dazu, dass das Item nur geändert wird, wenn die Bedingung erfüllt ist. Mehrere Bedingungen werden als "oder" interpretiert.' + en: 'Insert a function name your item should be depending on. For exmaple changing the Bass value of your amp is only useful/possible, if tone is activated. "tone = True" makes sure, that the item only gets updated if the dependency is fullfilled. Multiple entries are interepreted as "or".' + + avdevice_zone4_depend: + type: list(str) + description: + de: 'Hier wird der Funktionsname eingefügt, von dem ein Item abhängig sein soll. Der Bass des Verstärkers lässt sich beispielsweise nur ändern, wenn Tone aktiviert ist. "tone = True" führt dazu, dass das Item nur geändert wird, wenn die Bedingung erfüllt ist. Mehrere Bedingungen werden als "oder" interpretiert.' + en: 'Insert a function name your item should be depending on. For exmaple changing the Bass value of your amp is only useful/possible, if tone is activated. "tone = True" makes sure, that the item only gets updated if the dependency is fullfilled. Multiple entries are interepreted as "or".' + + avdevice_depend: + type: list(str) + description: + de: 'Hier wird der Funktionsname eingefügt, von dem ein Item abhängig sein soll. Der Bass des Verstärkers lässt sich beispielsweise nur ändern, wenn Tone aktiviert ist. "tone = True" führt dazu, dass das Item nur geändert wird, wenn die Bedingung erfüllt ist. Mehrere Bedingungen werden als "oder" interpretiert.' + en: 'Insert a function name your item should be depending on. For exmaple changing the Bass value of your amp is only useful/possible, if tone is activated. "tone = True" makes sure, that the item only gets updated if the dependency is fullfilled. Multiple entries are interepreted as "or".' + + avdevice_zone0: + type: str + description: + de: 'Obiges Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei hinterlegt ist, zB power oder volume' + en: 'This attribute has to be followed by one of the commands declared in the device text file like power or volume' + + avdevice_zone1: + type: str + description: + de: 'Obiges Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei hinterlegt ist, zB power oder volume' + en: 'This attribute has to be followed by one of the commands declared in the device text file like power or volume' + + avdevice_zone2: + type: str + description: + de: 'Obiges Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei hinterlegt ist, zB power oder volume' + en: 'This attribute has to be followed by one of the commands declared in the device text file like power or volume' + + avdevice_zone3: + type: str + description: + de: 'Obiges Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei hinterlegt ist, zB power oder volume' + en: 'This attribute has to be followed by one of the commands declared in the device text file like power or volume' + + avdevice_zone4: + type: str + description: + de: 'Obiges Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei hinterlegt ist, zB power oder volume' + en: 'This attribute has to be followed by one of the commands declared in the device text file like power or volume' + + avdevice: + type: str + description: + de: 'Obiges Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei hinterlegt ist, zB power oder volume' + en: 'This attribute has to be followed by one of the commands declared in the device text file like power or volume' + + avdevice_zone0_speakers: + type: str + description: + de: 'Soll zwischen Lautsprecher A, B und AB umgeschaltet werden, bietet es sich an, dies über dieses Attribut zu definieren. Als Wert muss hier der zu sendende Wert angegeben werden.' + en: 'If you want to switch between A, B or AB speaker setups you can use this attribue. The value has to be identical to the value the device expects.' + + avdevice_zone1_speakers: + type: str + description: + de: 'Soll zwischen Lautsprecher A, B und AB umgeschaltet werden, bietet es sich an, dies über dieses Attribut zu definieren. Als Wert muss hier der zu sendende Wert angegeben werden.' + en: 'If you want to switch between A, B or AB speaker setups you can use this attribue. The value has to be identical to the value the device expects.' + + avdevice_zone2_speakers: + type: str + description: + de: 'Soll zwischen Lautsprecher A, B und AB umgeschaltet werden, bietet es sich an, dies über dieses Attribut zu definieren. Als Wert muss hier der zu sendende Wert angegeben werden.' + en: 'If you want to switch between A, B or AB speaker setups you can use this attribue. The value has to be identical to the value the device expects.' + + avdevice_zone3_speakers: + type: str + description: + de: 'Soll zwischen Lautsprecher A, B und AB umgeschaltet werden, bietet es sich an, dies über dieses Attribut zu definieren. Als Wert muss hier der zu sendende Wert angegeben werden.' + en: 'If you want to switch between A, B or AB speaker setups you can use this attribue. The value has to be identical to the value the device expects.' + + avdevice_zone4_speakers: + type: str + description: + de: 'Soll zwischen Lautsprecher A, B und AB umgeschaltet werden, bietet es sich an, dies über dieses Attribut zu definieren. Als Wert muss hier der zu sendende Wert angegeben werden.' + en: 'If you want to switch between A, B or AB speaker setups you can use this attribue. The value has to be identical to the value the device expects.' + + avdevice_speakers: + type: str + description: + de: 'Soll zwischen Lautsprecher A, B und AB umgeschaltet werden, bietet es sich an, dies über dieses Attribut zu definieren. Als Wert muss hier der zu sendende Wert angegeben werden.' + en: 'If you want to switch between A, B or AB speaker setups you can use this attribue. The value has to be identical to the value the device expects.' + + avdevice_zone0_init: + type: str + description: + de: 'Über dieses Attribut lässt sich ein anderes Item auf einen bestimmten Wert setzen, sobald das Plugin sich mit dem Gerät verbindet. Der Wert muss bereits als avdevice-Attribut bei einem anderen Item hinterlegt sein.' + en: 'This attribute changes the value of another item to a specific value as soon as the plugin connects to the device. The value has to exist as an avdevice-attribute on another item.' + + avdevice_zone1_init: + type: str + description: + de: 'Über dieses Attribut lässt sich ein anderes Item auf einen bestimmten Wert setzen, sobald das Plugin sich mit dem Gerät verbindet. Der Wert muss bereits als avdevice-Attribut bei einem anderen Item hinterlegt sein.' + en: 'This attribute changes the value of another item to a specific value as soon as the plugin connects to the device. The value has to exist as an avdevice-attribute on another item.' + + avdevice_zone2_init: + type: str + description: + de: 'Über dieses Attribut lässt sich ein anderes Item auf einen bestimmten Wert setzen, sobald das Plugin sich mit dem Gerät verbindet. Der Wert muss bereits als avdevice-Attribut bei einem anderen Item hinterlegt sein.' + en: 'This attribute changes the value of another item to a specific value as soon as the plugin connects to the device. The value has to exist as an avdevice-attribute on another item.' + + avdevice_zone3_init: + type: str + description: + de: 'Über dieses Attribut lässt sich ein anderes Item auf einen bestimmten Wert setzen, sobald das Plugin sich mit dem Gerät verbindet. Der Wert muss bereits als avdevice-Attribut bei einem anderen Item hinterlegt sein.' + en: 'This attribute changes the value of another item to a specific value as soon as the plugin connects to the device. The value has to exist as an avdevice-attribute on another item.' + + avdevice_zone4_init: + type: str + description: + de: 'Über dieses Attribut lässt sich ein anderes Item auf einen bestimmten Wert setzen, sobald das Plugin sich mit dem Gerät verbindet. Der Wert muss bereits als avdevice-Attribut bei einem anderen Item hinterlegt sein.' + en: 'This attribute changes the value of another item to a specific value as soon as the plugin connects to the device. The value has to exist as an avdevice-attribute on another item.' + + avdevice_init: + type: str + description: + de: 'Über dieses Attribut lässt sich ein anderes Item auf einen bestimmten Wert setzen, sobald das Plugin sich mit dem Gerät verbindet. Der Wert muss bereits als avdevice-Attribut bei einem anderen Item hinterlegt sein.' + en: 'This attribute changes the value of another item to a specific value as soon as the plugin connects to the device. The value has to exist as an avdevice-attribute on another item.' diff --git a/avdevice/_pv_1_3_6/translations/denon_standby.txt b/avdevice/_pv_1_3_6/translations/denon_standby.txt new file mode 100755 index 000000000..8457800cc --- /dev/null +++ b/avdevice/_pv_1_3_6/translations/denon_standby.txt @@ -0,0 +1,19 @@ +CODE; TRANSLATION +OFF; 0 +15M; 1 +15M; 2 +15M; 3 +15M; 4 +15M; 5 +15M; 6 +15M; 7 +15M; 8 +15M; 9 +15M; 10 +15M; 11 +15M; 12 +15M; 13 +15M; 14 +15M; 15 +30M; 30 +60M; 60 diff --git a/avdevice/_pv_1_3_6/translations/denon_volume.txt b/avdevice/_pv_1_3_6/translations/denon_volume.txt new file mode 100755 index 000000000..fa3f2e61c --- /dev/null +++ b/avdevice/_pv_1_3_6/translations/denon_volume.txt @@ -0,0 +1,2 @@ +CODE; TRANSLATION +***; **.* diff --git a/avdevice/_pv_1_3_6/translations/pioneer_LM.txt b/avdevice/_pv_1_3_6/translations/pioneer_LM.txt new file mode 100755 index 000000000..b37deee1e --- /dev/null +++ b/avdevice/_pv_1_3_6/translations/pioneer_LM.txt @@ -0,0 +1,143 @@ +CODE; TRANSLATION +0001; STEREO +0002; F.S.SURR FOCUS +0003; F.S.SURR WIDE +0004; RETRIEVER AIR +0101; PLIIx MOVIE +0102; PLII MOVIE +0103; PLIIx MUSIC +0104; PLII MUSIC +0105; PLIIx GAME +0106; PLII GAME +0107; PROLOGIC +0108; Neo:6 CINEMA +0109; Neo:6 MUSIC +010a; XM HD Surround +010b; NEURAL SURR +010c; 2ch Straight Decode +010d; PLIIz HEIGHT +010e; WIDE SURR MOVIE +010f; WIDE SURR MUSIC +1101; PLIIx MOVIE +1102; PLIIx MUSIC +1103; DIGITAL EX +1104; DTS +Neo:6 +1105; ES MATRIX +1106; ES DISCRETE +1107; DTS-ES 7.1 +1108; multi ch Straight Decode +1109; PLIIz HEIGHT +110a; WIDE SURR MOVIE +110b; WIDE SURR MUSIC +0201; ACTION +0202; DRAMA +0203; SCI-FI +0204; MONOFILM +0205; ENT.SHOW +0206; EXPANDED +0207; TV SURROUND +0208; ADVANCEDGAME +0209; SPORTS +020a; CLASSICAL +020b; ROCK/POP +020c; UNPLUGGED +020d; EXT.STEREO +020e; PHONES SURR. +0301; PLIIx MOVIE + THX +0302; PLII MOVIE + THX +0303; PL + THX CINEMA +0304; Neo:6 CINEMA + THX +0305; THX CINEMA +0306; PLIIx MUSIC + THX +0307; PLII MUSIC + THX +0308; PL + THX MUSIC +0309; Neo:6 MUSIC + THX +030a; THX MUSIC +030b; PLIIx GAME + THX +030c; PLII GAME + THX +030d; PL + THX GAMES +030e; THX ULTRA2 GAMES +030f; THX SELECT2 GAMES +0310; THX GAMES +0311; PLIIz + THX CINEMA +0312; PLIIz + THX MUSIC +0313; PLIIz + THX GAMES +1301; THX Surr EX +1302; Neo:6 + THX CINEMA +1303; ES MTRX + THX CINEMA +1304; ES DISC + THX CINEMA +1305; ES7.1 + THX CINEMA +1306; PLIIx MOVIE + THX +1307; THX ULTRA2 CINEMA +1308; THX SELECT2 CINEMA +1309; THX CINEMA +130a; Neo:6 + THX MUSIC +130b; ES MTRX + THX MUSIC +130c; ES DISC + THX MUSIC +130d; ES7.1 + THX MUSIC +130e; PLIIx MUSIC + THX +130f; THX ULTRA2 MUSIC +1310; THX SELECT2 MUSIC +1311; THX MUSIC +1312; Neo:6 + THX GAMES +1313; ES MTRX + THX GAMES +1314; ES DISC + THX GAMES +1315; ES7.1 + THX GAMES +1316; EX + THX GAMES +1317; THX ULTRA2 GAMES +1318; THX SELECT2 GAMES +1319; THX GAMES +131a; PLIIz + THX CINEMA +131b; PLIIz + THX MUSIC +131c; PLIIz + THX GAMES +0401; STEREO +0402; PLII MOVIE +0403; PLIIx MOVIE +0404; Neo:6 CINEMA +0405; AUTO SURROUND Straight Decode +0406; DIGITAL EX +0407; PLIIx MOVIE +0408; DTS +Neo:6 +0409; ES MATRIX +040a; ES DISCRETE +040b; DTS-ES 7.1 +040c; XM HD Surround +040d; NEURALSURR +040e; RETRIEVER AIR +0501; STEREO +0502; PLII MOVIE +0503; PLIIx MOVIE +0504; Neo:6 CINEMA +0505; ALC Straight Decode +0506; DIGITAL EX +0507; PLIIx MOVIE +0508; DTS +Neo:6 +0509; ES MATRIX +050a; ES DISCRETE +050b; DTS-ES 7.1 +050c; XM HD Surround +050d; NEURAL SURR +050e; RETRIEVER AIR +0601; STEREO +0602; PLII MOVIE +0603; PLIIx MOVIE +0604; Neo:6 CINEMA +0605; STREAM DIRECT NORMAL Straight Decode +0606; DIGITAL EX +0607; PLIIx MOVIE +0609; ES MATRIX +060a; ES DISCRETE +060b; DTS-ES 7.1 +0701; STREAM DIRECT PURE 2ch +0702; PLII MOVIE +0703; PLIIx MOVIE +0704; Neo:6 CINEMA +0705; STREAM DIRECT PURE Straight Decode +0706; DIGITAL EX +0707; PLIIx MOVIE +0709; ES MATRIX +070a; ES DISCRETE +070b; DTS-ES 7.1 +0881; OPTIMUM +0e01; HDMI THROUGH +0f01; MULTI CH IN diff --git a/avdevice/_pv_1_3_6/translations/pioneer_SR.txt b/avdevice/_pv_1_3_6/translations/pioneer_SR.txt new file mode 100755 index 000000000..371852120 --- /dev/null +++ b/avdevice/_pv_1_3_6/translations/pioneer_SR.txt @@ -0,0 +1,103 @@ +CODE; TRANSLATION +0001; STEREO (cyclic) +0009; STEREO (direct set) +0151; Auto Level Control (A.L.C.) +0003; Front Stage Surround Advance Focus +0004; Front Stage Surround Advance Wide +0153; RETRIEVER AIR +0010; STANDARD +0011; (2ch source) +0013; PRO LOGIC2 MOVIE +0018; PRO LOGIC2x MOVIE +0014; PRO LOGIC2 MUSIC +0019; PRO LOGIC2x MUSIC +0015; PRO LOGIC2 GAME +0020; PRO LOGIC2x GAME +0031; PRO LOGIC2z Height +0032; WIDE SURROUND MOVIE +0033; WIDE SURROUND MUSIC +0012; PRO LOGIC +0016; Neo:6 CINEMA +0017; Neo:6 MUSIC +0028; XM HD SURROUND +0029; NEURAL SURROUND +0021; (Multi ch source) +0022; (Multi ch source)+DOLBY EX +0023; (Multi ch source)+PRO LOGIC2x MOVIE +0024; (Multi ch source)+PRO LOGIC2x MUSIC +0034; (Multi-ch Source)+PRO LOGIC2z HEIGHT +0035; (Multi-ch Source)+WIDE SURROUND MOVIE +0036; (Multi-ch Source)+WIDE SURROUND MUSIC +0025; DTS-ES Neo:6 +0026; DTS-ES matrix +0027; DTS-ES discrete +0030; DTS-ES 8ch discrete +0100; ADVANCED SURROUND (cyclic) +0101; ACTION +0103; DRAMA +0102; SCI-FI +0105; MONO FILM +0104; ENTERTAINMENT SHOW +0106; EXPANDED THEATER +0116; TV SURROUND +0118; ADVANCED GAME +0117; SPORTS +0107; CLASSICAL +0110; ROCK/POP +0109; UNPLUGGED +0112; EXTENDED STEREO +0113; PHONES SURROUND +0050; THX (cyclic) +0051; PROLOGIC + THX CINEMA +0052; PL2 MOVIE + THX CINEMA +0053; Neo:6 CINEMA + THX CINEMA +0054; PL2x MOVIE + THX CINEMA +0092; PL2z HEIGHT + THX CINEMA +0055; THX SELECT2 GAMES +0068; THX CINEMA (for 2ch) +0069; THX MUSIC (for 2ch) +0070; THX GAMES (for 2ch) +0071; PL2 MUSIC + THX MUSIC +0072; PL2x MUSIC + THX MUSIC +0093; PL2z HEIGHT + THX MUSIC +0073; Neo:6 MUSIC + THX MUSIC +0074; PL2 GAME + THX GAMES +0075; PL2x GAME + THX GAMES +0094; PL2z HEIGHT + THX GAMES +0076; THX ULTRA2 GAMES +0077; PROLOGIC + THX MUSIC +0078; PROLOGIC + THX GAMES +0056; THX CINEMA (for multi ch) +0057; THX SURROUND EX (for multi ch) +0058; PL2x MOVIE + THX CINEMA (for multi ch) +0095; PL2z HEIGHT + THX CINEMA (for multi ch) +0059; ES Neo:6 + THX CINEMA (for multi ch) +0060; ES MATRIX + THX CINEMA (for multi ch) +0061; ES DISCRETE + THX CINEMA (for multi ch) +0067; ES 8ch DISCRETE + THX CINEMA (for multi ch) +0062; THX SELECT2 CINEMA (for multi ch) +0063; THX SELECT2 MUSIC (for multi ch) +0064; THX SELECT2 GAMES (for multi ch) +0065; THX ULTRA2 CINEMA (for multi ch) +0066; THX ULTRA2 MUSIC (for multi ch) +0079; THX ULTRA2 GAMES (for multi ch) +0080; THX MUSIC (for multi ch) +0081; THX GAMES (for multi ch) +0082; PL2x MUSIC + THX MUSIC (for multi ch) +0096; PL2z HEIGHT + THX MUSIC (for multi ch) +0083; EX + THX GAMES (for multi ch) +0097; PL2z HEIGHT + THX GAMES (for multi ch) +0084; Neo:6 + THX MUSIC (for multi ch) +0085; Neo:6 + THX GAMES (for multi ch) +0086; ES MATRIX + THX MUSIC (for multi ch) +0087; ES MATRIX + THX GAMES (for multi ch) +0088; ES DISCRETE + THX MUSIC (for multi ch) +0089; ES DISCRETE + THX GAMES (for multi ch) +0090; ES 8CH DISCRETE + THX MUSIC (for multi ch) +0091; ES 8CH DISCRETE + THX GAMES (for multi ch) +0005; AUTO SURR/STREAM DIRECT (cyclic) +0006; AUTO SURROUND +0152; OPTIMUM SURROUND +0151; Auto Level Control (A.L.C.) +0007; DIRECT +0008; PURE DIRECT diff --git a/avdevice/_pv_1_3_6/translations/pioneer_input.txt b/avdevice/_pv_1_3_6/translations/pioneer_input.txt new file mode 100755 index 000000000..f831edb28 --- /dev/null +++ b/avdevice/_pv_1_3_6/translations/pioneer_input.txt @@ -0,0 +1,21 @@ +CODE; TRANSLATION +00; PHONO +01; CD +02; TUNER +03; TAPE +04; DVD +05; TV +10; VIDEO 1 +12; MULTI CHANNEL +14; VIDEO 2 +15; DVR +17; USB +18; XM Radio +19; HDMI 1 +20; HDMI 2 +21; HDMI 3 +22; HDMI 4 +23; HDMI 5 +25; BD +26; iRadio +27; SIRIUS diff --git a/avdevice/plugin.yaml b/avdevice/plugin.yaml index 218ae60b9..5a2e046a2 100755 --- a/avdevice/plugin.yaml +++ b/avdevice/plugin.yaml @@ -11,8 +11,8 @@ plugin: # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1097870-neues-plugin-av-device-f%C3%BCr-yamaha-pioneer-denon-etc - version: 1.3.6 # Plugin version - sh_minversion: 1.3 # minimum shNG version to use this plugin + version: 1.5.0 # Plugin version + sh_minversion: 1.5 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance classname: AVDevice # class containing the plugin diff --git a/avdevice/webif/static/img/avdevice.tif b/avdevice/webif/static/img/avdevice.tif new file mode 100644 index 0000000000000000000000000000000000000000..78e087908674ea93908ea2ecd35defb5deb3270f GIT binary patch literal 87356 zcmeFacUV)~w=TTsz4xAk-kbE^L8N!2g(M)-Lnta86jZuM5fy1-Ljma^T@VGO2#88Y z5Ty5>8&KKq{oChU&;9QA*LCq^Wy~?&Ip&z}EGtiDh8h?E0ssII0`$NkfQyl^Ft4K< z&e0q8(GBYt8T(kq*s$oaaK7sSJWL7yhm5I!MRn{4;|q%wi~5Hi;}DDPhkRW7hx`bm zXE?zNVKE%;3z~6jC2M|;#j7|$R1cqe_^oej{M1Z zV)Wrx^p0ef4*(#$7~}S{zX{tn>;M7)Xv5S^3wG zRQ=a@Jw5-mrXNZx07JnKO8>Q{pZNtJgs3UP&)XjfLudtHBKeC~3~h>-*5x&j2q?-M zY3}Xqq5R)ZM@7+p;{T%mFINanC<>u`G;xK+WQ8SU%zsW?K`{w=F|l8qd`JGnhXH0P z!l5YW?|Ate_Md*d;chM$e#^^W$X|S%47t2HA_#Q`dI5p-JD%4k)9rYIt3zG?u05jl zXoh;Y9ZysrDAEscGz?0RpW|>cvrjx7)%mNvp^_5EGtt1{*XsY_TGJcmf3$!xuD@@VaBmpK z{a?c&EiD0ck&+P?mXs5h5Qalfxd_X_Pr-y`WMEKd7(&cNN(}b1pC=#LOikTt*+r9I< z%fHw8r|pe$J_X4CZ$SzdS9E$Md@u^DM@E3=lo}9Pl4QeKHXLH-&$8@&Bgp z6JLKCIiccrggvvc>!Th1?go@u0{?PS1ES+Hf&~-w^ z?+AbB`W==|Fn{Peq2hOhKXm;LODC8=be&M~JHj8jeut$K%pbZ=sQ4Y>4_&{*(h24d zT_;rhj_`-B-(l$l^M|ezDt<@!L)Y)Hbb|Rq*9jHBBmAN3cUU^X{GscFir*3b(Dgek zonZdZbwb7O2!H7M9hOcof9N`);&+5Ubo~xXCzwBUolx;R!XLVRhouwDAG%Jc_#NR7 zUBAQ93FZ%7Csh27@ZZu!{8wfj!V8m57l_H517y|p3~;$IxqARWd3^unc5IVBR($zk z$K(oPE)pLkCWX()ALZkZ!W54Z6aiyDl$kRo$?6!P=Y>Kby!qzl5@RPiMr#<@=znKJ z;m8HHFy?l|$oC+qf9bK&ah{$Z#>Rko0UACiub-X3bkZ4lQZRM(GdL+|AiXsHDtMv( zDx7il@H?>>x}pM33R<2XnkNMekAJyVhq=4{AmV#~fT@nU1|}LzDk%V%!a*Rox4*Nh z_t;VK_|ido{fAE7<3DlgNVvI$7fPGc)Z=JuPcC&2IOyN>rhXo%W4&>ZhpOoboHzgh z!=&M064Wrcj6Y_Dv8%D)&slLKAAvFNM_~hJ5H8={{G(ZOOxEbXHERa*_^vlb!c=XJ zJRDz?Fr>GS6(;+|_-KZ@dAa_ikNn7Biit_x8-?=r^zim_{ZWPVr{ySwU-V=@^`>sF z=YBPi{4`)`9CzrKDRMt;Amx`|MkN8dSw1r6Z-#)?U;)r*O&J+&A4$i#(BEq_ z9~E(q*!j-OQSmsn`g=f_!jDCGZ1{QmMR$Zd!Tz-WYo#9n9bvruJ&tz9qk8z5d|)rQ z-#=D73?+`S9ZekIXqlYMMNIi0a~V)Sne*SnFg=;l$7Os!4>uUX&(h<}(W1oqTRV8i zHjJ7Y^CCDd=xP4a7J)0$+u!GJDtzzbbibebt(Mu5_wTuT7$0O%f0VZl!V7^s%A3O| zfTIM`A7J9|;3LhEMbFa}gn9e_yZ<R;fNKh=MSlQ_E`=b!#UF4cGc>N+O|OclV;+v|vHB9yle=8^7)_;s%%_P}h4|Dh#y zKHfzCLr;Pk_H+M)AFnpPqlPfgY|M04Sw5D(uPmx#8SDF=hKu>v1~Avrgr+#Ib%Y0~ z-(zk^Yw6zi7uFbnC4>>Fs{lp-3;hAT0FWLhb~|bq0NCh7fc&@wz{4>hEc7QJ8XzSk zBqSmvB_blFA|WQBqN5-srJ!S^p`oLpVWc8GzJ9!YFZ}b4MMgqGMovaaPEJWnPEJmH zbR(zzUWMv+9H1KkDnd*L?%`lT0BkBO94ajIFs7r#=vFKhOq6)v_bW`mM;8v}pP9hL z!zUmlA|}E5rxEj9!TD*V1h8p}~`gNTxlCpvkmnS(3|n92uFSVMYh@JGH`%e-r=#k5qFnCWt%+ zxR!-93NdjK!hanB?_VLHKLVsU$8AypD!_($iXJyVSBl#w-|nuO$= z6Ud`H_oMxy9~vkt?AuMy8rD%L{BlM5vnxTbHQ}&+Ye~Cb_LA$i){QXp_1zIs(>)$T zZcCZ@YQtAg#0#EEYD8744BKZL9g;cBjg4=3kUtt`oC!%3tSs%@Wl-3m8_Bt1*0RQQ z$@F3NXuC?9;}{zFEL|9>2=^h}+ukmTI5bjL$zly_Xh8!BlO8S`q*wgyMDAQ;wD<9^ z775}-2ptSRb*&jZj8Cu-U#l;k{*=CHR8sN8jXX{vxOIUeg6(QJAYDx;-jSct!RMp|;se zMj|G1(E&p{8!o*dqCCzltYf7{`?KmdY#|u&<@rV9)Cps4Rp{4jR}neR>&J>-Vu;JhCfm*8ft2T!WT- z3UK2d>&?r9*7FI4J)aEP@?cMgLVR=&7z3ugKfm)cTWxK|Z8PP{AlrM(sjW!Egv8>5 z0Xkeyv||cszp#TjvSMQP7CNCDi3_BAXNwaQvyII^X-trMj4WguxC!k$WMyeN+OYvn-Tiu^1dn8iRJdApXV?YImZD8yNG@CcGA&Hb{c1?U;fuu2 zUmSVw!KPf!W=J5WuPkDI_SJP)POWo;mZ;(^g(QWCNV?5CAHrQ^w0)!Oasr|$;_IXCW+@I@3 zm2vzzvICPP_=Mzyq9)^w1GCxtl_rga55|XLF8H0VkfCP`EN|{2B0uOCs#CQ490)^L z3K#5`?F8apx;2Hm5$EiYL_s;OEPiNeD{+P}0wSw-+kGAG{$8c^dR*v}-sy|dt}a9I zP3`_8&7Yua-9DvE@n_jw1brfCL+*@Zp7SBwHMZY*tjG1vm5r)d>L4!W zR;R9_YoGri!+ovJ!W`+W$5pN_4ShZV?ISbdJv$YWYq!dJ_2k9kLQV8}Q~W@k!3upjC8d^hl*r5z1aV34o43VG20t8z9P@D<&gLj%1J!zN?;(7+-$ z8VGURwQvu8H#@pT!EyNU8K#-^`NKPCz-I*wEIdL3t3>=AXrP^<5c3GoKiq9tf8@A5 zzK#a=u7-_T9p1DZ{aZ`izXov{8Me}bS;||~XrTVtfk67NJ+-X-M>BtmA?0@V|2tj% z+o%>L#B4-S6iJM#B|dshxFJ|f6l2(4-s$&Yx)#>!YB*ca$og|WR4=Vuz)Tk7!vd8J z8zO%6z*m(vjW26$b#f-b zbixpf*Fog>>))SN7ne}UC9Q9llq|CQmYvvV+bp2q`MOjer$H{YI83f`tKVg2qvq}S z4GT1|9AM5&u{rl~iq%rO?tI1w4%SX`b^D5@EsS0^fr>DBMB|$2?qTA#2v>DnpQ0;Q zu3?>6ax~|G1LOYacrBa4L#ynw2UoJ@6ub&PrrlV#8w?HcI{4!2SH<_+#fW$(Ir%MHM@(5k!J6swzK0z*Tlv4f%>AT z_od>GOWhHPq%7_|Ig7Bfix1xh_L!rAnRc6lrRIhM$iom<&dm{{eMI)o>dTv8r`wrA zyED}Xa%f;wNvu5N23TK)yKuXDCVVx+ya&_2x!WS?IImJx7k+c{K3uX2Bx7eBS10(hK$H_Un%;(tDpAg^LDjV{Q@jO*It2DYbAhR}7R6EOY)o#ng z_j%E9?O|WvSwVJ|_6J*Gy&o&9gEhG39EEhK*wBD>!;E6P%q{B@9FALXb>6Ko{prxzD%hbi#Ip46eWuwD0nbGm+%*!(UO{(R8hQmDF^E@~ zA-r})+_G!btP+GwS$U{%>U2o+4jB&CGFf--1zpk8-Mk$)E=tbPg9fnXmbxmv%!xB9=$p{Og}T+SG@4ts-_}_rsLE6@IldIf_;ZDmG>$SjSei;J5$df__BL= zR3>VTGj4N=mxZTqze5lHZQ|$d4!J(Gh_rF?V^_2tFMpGc1{lNMVYaL}do*B?P?M#c zRnO0Noz}skE6gaUxlvd~7U1AhIj{EKBmUqg64IeKR7Jt=v)6tIU|-R>7BwPzkSjTt%2 z6JT_kJA2oJWxt$b^GevaN0XaN3NWwR0*7rhhlU&zS`~74orsxAi4W`0z|!r}ora!< zMVUh)*TYo(L+^F(y?8VbX@hzC&|w}HZWrI}sSGJGZC<>4|7*nh=B3aSVTa0G<(}D# zpW=2EDi-!fXOv!rj8g182)jxb@+|`mC}9{T%|2Mu_?t7#rk{1dayS__mKHXv<;S^@ zowvt3G(qw3+fwF2WuH;v=DXgIXY(sKed{uvhXG3_qP62_K#F1o^6Z5l$4n_27{7s; z>26_NhnV<$8`CnvZIdk-W7FBDT_lFncRUWhgd7$YxaQ67b}Ok^2Aug; z>soE~Z1dTJQL}l6yWU?N9^uo~LcyU_g9UKj`V4jM>L-Lu{!`{@> zb|VEEWD!r+S08)#ejuN=YdZ`q-1&y+scNSwY~qH|Ya}>pI7El8+h#7eOG{$AKY^=g zYdEiNOu;@3_kV1sh$WaFyLW^K^{lUnOnCfn+C(#k4t%G^G4&uFJ}GeqT{@i}vOZu)qgd{Z~` z8ie#6qX*{aO_+uai>#hlx?9wI33%aHZ0%vGz@3(9@!ZzavKCP>>|JH&Wu;Isuz*`; zzhqVWW%D4c(aFbJk%wOLLW{Gnb)Ab0TjDD?(%MejNI1RI#m}a0I#4P5^~}1h5>L88 z;rsLcro-gV?4Nz`2so>Bf8a~eC$GS>FQ&Ib8pfbw!R)*Y@$FN{3)aK!qIceXMP0O4 z&fm-GpAWcXUq2K0aBwLo*g=Iiy(?q+!hu7BYvu6Lvx}h|Dusg!Tl;#4j@dI?`{+iB zs4bu|Nr()miJX)Gw<*bkji8ydjDfH@>4`8&3yB>sX-m?)5=AR9tqf&rvXBAIOTza$ zv@erA>={~C?4V3-$xl2E+f3^G+1iu8RkF7Cl3oVCivJt|>7YJyllwVRF_ZT-bzFXZ zNAK+-!8g>e8wB2%&c6`tBxbD^>%1Y81+aQ|(R_CL=XQDbZ>5B$3f*_tM65ZJMm#5!UY`FA_Y{m%5-hW`;V@GI<|w zuVLCxXJEcA>u+ywH9&UR$a>&rkw?{l{|kTn!NmBp4j<^rqH6}F+2UbCL@%$yhtfQ6 zA6RXM6u5o7hL?W+6Ma`%lh-n=)#dRNL%J&yjB$Z66V^|K=_fMkrQ+M96XX)7 zsNYH^O=Sv^B~J|*n(rf+9PHD3Gd7`_)5+3jZ_O~hDa@L&Sqz?>$vnKA^J*yVYThix z)2RH}Tkd)VvmX-*EO~F;EqYvQd!?l4TO4`$(|H!Mt9c%0MY?P}vXuMFXZH+;Di@jW zPgXC+y=|yjV(ENY>3w!_zt(FHjn`D3HAB?0LPCMlx^mmYqQ&=fBG>a()@Z;Pcew#z5cY|fn=>0}kw$;EUi=*R*%`67jk6X;6-k-N_r3a2|GaH4C zZQo*unb=`^mpHYP8IwM}%Vd=ObvKisaBh#W;o1CNMoi`6KBG#*@_zbO`|1Hh!@Ko^ z^uWQ*Lk7{&?ZdRKnO!vfv!#7>THq$y3A;UP86R7SkO0d`y)t~62Vano0mmuwVZ^dF zu>c=0o>OyXv ze#X=6BC_5T&e*0gEBFwusu(I~b71J@uKBu%Ky)h^ zVAyQeSFT8a&$Tnb)G6Xt?n{GW2U%c|3D;KIJPR!;J6}*tN7{~ z`~+aQrgYLOkG97B$DHuU3-PPkr`h;0rK5m*g3RH1pYbA(?D7?AaX3Na)DvW40NJdUOfIGZJU9ghU*YKSgt7F7n)S@%icw88E(j{FY zE@rN2pJ$LOlyYhEy0zxwMW0zIIPt8-&=^y_#i$zuXBAs?OJRE zoIk?rY)1h+=x$zjRA8>u7&|^SKC&+OW~<4%9SvVWpZ})^{_V&i{+Azs$ncE?H@tL2 zDci{F5eh#c*$i6QR9&snpb`H&-yB96dTT=+Kj7o}+h<61#6cK`w5~p^u-SG=8>;pQ zV{>Ij!~zi+sn{{iZ2~tZwof<3!;&^yScY6nhjaO0-#Msf?f zKG+1gX0C!`u{4I9V`pXLGXp#>;zvL5lI<$b1YexCcs8%V{^t1tU&2tO7gK0z%(P8z zydQ@wzEh4vqgayU+(&u6y4g!3S>&@TCCjE1u0zr0ko01D4Tk+*MA>{ZHh;-H?yV9( zr?2;m)#pANQdJ8KIuWy9SM0i&w|4C?Ga<+R%DbVj_RqZGTYTApBf0FS+1fsxCQDC6 zp7$1fv)UrBvmjXSaL2NX;lfv0eBEwxe)3TP--kq-k-RAzufw!w?G-q&7K;Yz0!t_E zVx0~4g61~#B6o===fKa#52$!|u&!N4qu$<&l`pixiM68yd;756n67zEyhamH9DZFL zQjVK6nWIg4Cp5X>Lt{rPOW2gjPJ@+*IpglCL$umsg;IW!YZIGTSSWQ_$R%pxRxz;8 zY_CT9*Mn=pYH-fh*jCHuRAXvX(b4^7i4mt*K#!TMRJjw>o4IL;>r723N+fF;h;`VW z81nd@2PbWje|jBkP60QmxK0mdWZUuZ@D)3mGfki5>l2m3Y>&1TfxAFy%6Qg2Pw8zt#Id3w$E z#cjAWOs$z)!dmD}=5u9z><;l$Q~Kht1lhFLa{Ao5pDckQ;!tY5QT&hd!;q&v#mN_5 z1H7_AcRSoZwBKeO({X4<-W zYVX6%Eqy%p^U;P$4X3r=*HW^PxA|;EuHI>$f(Vu>ByHCXT&)XmEsytViM&CEYeE}2w;QZX&2oD9k`jmd)ETu> zg)@bpzq-*e*S?SJu+1`|xbp2mffeyo{rOICakNAowZ+Jxpx{HRXK6w-x6;jAPg%uG zA&a^#aIAWS7VJqL-D~QO1-L?5_tW9 z#5iV_yXO3YOFtFiC0D)P=OIh2R|k++4fDB&I2pKd?V3f!iRf{KysNjR&OWpyrUxK_ z6`FPmB~~IPoUT?L*N1n{8ISB9Jfdk$8hi9YjJgfKxXQWs^4tdkcVFrHd}Rt%+pk8S z)*MPKD%x!I2h@FXRG+V73u?@C>iLSp+u#b!pOKCUzMcIX8{?wYrd!U@ z&q5cl@DryXtyCaQL5{J%ZofV5N9~s5QbGQeWx;vY}OO7&>o)GnAHL=co^(zX_m+n0Y zdfU=iF{h3eRfW$=Y9mJFrkyV4hFUsk>zq3rsqzL6tY&t;@VWB*i3Qu*7505hG`T9Nnj zU7KaLqL&t%$!f0?kU;FD0v(^QcybQ1O$0eQe;Oz}!}E+q{L+E^GA(DoOkUiL%yXB0 z6zqY``v*LV6N{5|&_unvx2zbKos>hB_+%d%%xbE?T<=xsA|cSEAJWOE5xK7+|IF~q zMFp$mPA)C?Y{}Uvnj|06x|9o4N-dY-I)KF35nZ zr*W1YD2v@ExWPU<0!s&@jhl)Q?*rcekMi}SH=hX??YF&MnB_#d)m)(`yuS-Nh|bz} z1{-OVh%RzzT)1G*@@0?Tay?(C5uw8HRp00-_^@TjoFH35dSGns5dC>?Nm;$>YWz2% zcUhpgqOux%X~^Bqm;-9p#aHJy;rR{yl%5MkpD;?$n9v%(oHG=<8_@KzjEg*>IXoa3Y!TDLnBEVk;+v@tT?6bCO|k zjbg#c@O8D9B2TTnvCMNmpR**-_4Mr?MH@F|Fh5x?#D@f!4?ctto^Qm3<|cTY&%;^v z04Jq!CEeQR(M40{0F*wEXCEP=u@aQ2=ZY(Ex@*oE*QZYe=^4ipxaB5cD-o*GkvcnK zz z2oig6sUG607czVIvlA)NUhQLn$kC`%F8cN^2@QDq@FcGUahgmWnnW@8%=4S%s)<*q zh_8cIa5OQKP?o;`ILQT`7U>fB44Q| zH-wDWl#Z7q>B~3dq-h#w%B{AfxA5K^kh7!!viJ?ske~X2YA>^L$rp}DGfHe4wnz(h zV-rxaJz2X*zPi1D5Q(S|uh0YqIjDr(XO75tk!y7Uk}JnLVP>b>v>| z+!MCslKgtu+YDKn1N&*-zA+_Wc7b)a0FRFbf90Ymig*-74tY-vHfKU7g8vjYk-Rfhv^hd+Ar)O@pl)_aE_X%; zn@l5@L-)PETB?eAt|(I^n_`*1UIB#)tY1l;LO0S(Hj+eS0>*AM0!D>EXrA(*f_T@9 zLGNMG%gtX>RYg%vy4aj&{L0TfZ#tcF>aN#yUDU|v`!h!CPZU!%g-<1M-}nq#^8lOo zu2RtG-B^)rj_0FrV|pK*Z2=PTCkORYgQXZ`&6iBp%fO|c;*&IIrrsEHw(~SsibR^J z(n96b$xPL0^xtmTQDs`G9jcxXL#P|IRBOF=i0pz<0}*}zi2 zM-3QG6I9-`pbOlFyS0DEJ^+p4GN`~?73n5;q>_atfz;*=kCh151b4S+1%p#* zXDp(xdsVxqQFr#n>ker0Y^-w&Ja8iLDM zz89K(?6>kl1J|*>$pxf83%vQ#n?X+t*C6cFbIr&+UW+2uSj^85)XvD_gwF2TfHz$k z1~~aWFFd_W6@)ALf$-q{6kni-AxRrzn-Stx?=Dlu_4Re!qSJf4vR3b#GTROYl~r<^ zUZ8Yae(N-VKANl7GLbrtFXKFTP?_mxVasltzMKJ&3^~yda$gfpxk?~>@99aXHX4< zPi~GM?*q`7Kt`=_Po7rbA|o%e2IsW|d6~-er7L zDD3?5by1YMV>*N-w?-=?_nPy0{BxcPR5jWHw&!_1MuTr%joWpVkvq>d19Gg2nA;v=4_OhD#3qIn&&~hUgj}} z<({XuR+O$rH!s-oepJZY)gWbhCHQeyt)^3^`cgvk3!aaZTz+hbch3B`Ho17{p%1O0 z_rZ_0i-aLLB@>>{LGMJf@DfQmquYFMVtHpx=sGi8Ei)A{H4=n zsLtjS`Jl8Zb zYCA!D?R9(oFD@0nP#Ai#H)efyxL#qlzCf@3(n5p6y6LBthD!$xU&tEjuo{C27d{9# z)=@Pnd~39$YpP?_uVZT3=Wd2)H!Jct?~Caw3b!cAwdA|D1S_>FYHHT0wFVosu3l=~ zH+dOsy>4gmvJToNn_R<+Xsh#Vu5)YK_iqoD!hC>g-;Ze74|%0{^;MnTtKj$!#hWh` z(>v;JYbok?>=(R-IlfkW_`*wfhopath#hrHtfHiA!w-Qlz9^1QNvK}Q`J2rxz5VoF) zr5-kLZwMdfFn8|@@jeKD?}1d`3q`QKT;G9K-+{*a5Q9E8{r3kJJqKp}A@<$FXZsH@ zzaNARgm}Ikb{{zK?|R`k7!uMsd};9D@|zb?A41|^-?{$b;AY2*8$%&?UcJZ~Iw)wr zllL*CsO`n$j|b&1?>zq$@}kv!gyTgkb4bVMoTks?lfz1_94{J%>+petF|30roI79f zUM!4^5sX6odvXOo=O9MMhsKnK$AY!7?~)SLQ{s)#a(^-87-6Na2QiFrkKN^O16`gN zOP>VcOYHq) z7={wf0jfj=Fqv>n7vvBZL_E5(!xg(7g+x1 zsZN*c&F;)Ht(VNn0tIH^(vO!<_XO5Cc>nEGr|5je+2r*M)<;=JS6})JDc-mGf~Z3^WCVQr#ge4m7k4HSq^j8oB6ieeMz@Vn>jw!v8#8Lx$~~9dmY&& zB9Y!ycz#aNAtvy}=<@NYPFi5?OaG_#ciEqJEo}#fIv$pd`14#>IrxaOB(l<%`0KpiO_cQB_q*OkBp)B;9?Z7Zkz zXip!X>d=t3W}m*Q_~eE@wWd#MyBX`S%v+kcFLL+#1PmnepPx41dV{o^Rq3WB!&7VV zE7e!zy3wnzY>@JWNC$JO!>w11lF-xSLYeAmbJKY88@;C^(=sVWmFk?~GVj$f9)vd7B?~ygp-2bpl5y`(Gv6y;|r_wAZ5>3K~scI0&n= zx}|V2FTF+~IA3N2>+*Pp7wZQn-D$%3u~*ZSNl+vH=3s#5>Q{id@By~>-7%t9!QlkH zn*e*^SL{n1jaXBmm^>ju085qL2P=ClgBZYZk_D)+c(*O_vd4oM0h}>SPrmTUZts}6 z>np1oOcIAO36neIIw?~-hE{1`b`o4~P4B!7ygRc?9+UfZ*D(G5>{2Kse&XDKK>Wnl zLy2j2*ROy*+dZP7z;JDd z*{&eTZf3~4qg992S}0=UvKiYB6-}H9SGH}M0oY>-<}S9QOHS7qOtBuk`c%Xq)mP@{ z6Y>z@_8y3iodh_2Q_`1pdo+UBIL6PAP>c}+#@{|(N;*^WVoDkf;2efi5@V}jA7Hib z6Giw)6Wn(7(zfql41^;_k_SUw*$E#6O^EpdRBi2~Rcvle-4qnd#Ty(Ki6f0oA#`7b zBB61TSBgg{n5{-U&Qj0?9#7wQ@TcuEV`VGECMxH5tbM zbq_xPya(zK!*^BHCg^Cy?Fz@_d8*$Y=dR5g)3d^jxYg;%O~=d*Vy%2R%49BEt>lNyPC7KKq%b=y zGQ!5wyo?;KpkUl^kOVeBNgbVEev@M5tun##IQu#x!_d^2lr#Je9_Kd2smWO}-JmyY zoUeQnrA;IrM$qHjJB1TvEP`|YhP84kF3>GcqSm2Al!KCv>0##4=PP2!JLTcigZbb% z3!wAOQ*MB_CN7#VeUl*C?j#8$X3_4(VHfI7iFgDe0nTCLstRGfM~2|zuL(0pb%v3j z7t>R{Btz|#5gMI-D%eepyuiFP-He4)H%o??|yQ}bpu_lVS1e$t3Izktl@Jdd7yiIlWevs$QvWh-<^4WWM z-ohJ=LY3qbpD*1&=`M6u530VljpR5V>;DA2SrvB{yBnfIhiPU8p4 z7vwQ%V(sS+ng$!=n#R^dHDcMCW7KDpvK~Xd-hyibM3&6*UWSWNPBcaP;f=-7?viZM zG&Ab0QOyfq5$m~J-zvXP`FLI9**HVP%M>6SOvDwt&rRT@i;dmLrbsG2$Q<=5G|ps1 zh1(58k+O+9{yZ~ASDT||`%24%LXFnq&f8bj9CXQXH*ZJ;7>iZw3m`m7(qrq-atxuG zV5M}4x`rxX8{F$~iALUbS#0u^gwK@s1hB#hb+H?132pMk6gkGK*fi$-6N{MD#+I+f z=R}jvL?vbrDm!9GuL#W;1*9yH;NxRl}d@NT;_dtC4NpxpLq{e3G>5HY2>in>CN+{b%S z=ZmZ|-3mVUx68N!Y&m6RI|LtV9X%GFJ5~l9j(>)8A{RsY>Q5iGf>{`&<|C;}V?#Ry zX_rB9%lJdD#!g`aq^uG2UcPP0R!mV%O;pvYq7ktNUNNEpl=j25vk6756{n_r4TakX zN0}#Y2TdWVc3$o9Gf(Xo-b_!RRojN*kGBf%3k z$GyGkA)YG8AHfbxSx}*gBaA}ojM#z{;Ls>Za;3v*! zUXY>ukK0S&so2p}AoOhFoh1ns#Zfg*vp5zd9abW)LN^Dt7|*Df(0s9&p!YIBv5pQ0(9M`E zCnRl7H=sJk;^P9EZO0R%RK6xa2Y$_QT9FeAgqyQZ;{H{-_*8LRJI;gH{Ydux7BzzI z2tsv9!eR!($r&QCbfR2QqUAhd=O+AOFWsrl*@BBJkrlV^c`$|JUyYO?XygIH9Xh@) zzm5oJd%6oDyvw9|j-!|bhbNy?w1tGAnnazABub9Fdxb(>oFeIf5|@zK7mqShl5&NH z%IDmp$#o@-;>XVOLVR%GbQ7U7=|GYh9&Ac}+?us%v)NhV8FW8pNn4WgF-|gQ-$%J~ z$#M|~N>}2*DUQJMJ*O=0$v}nTq`JWHmWH-{h7MPsPNPcDHIl%1ndJd7C-4YImADB` z-wd^4z?O){x=tnTBq<)*N_8bNnG0;fCrQ=7D&7WJdBZyIq$b|a7AelwGbY&mS#9bW zIl-d77W3oCDu$R?67ZvM&O*5ONTPcp2dxtH&|VH`W3{>%?U*IUz1U$RJ*r%Bs+GC( zC5vG3Rf$zDK!P9A4CVyzI89|WsFk>=H6g2dT)oDErqrP+^yBzDJH<_M@u3Y0$0 zr7q2*t`y7_7F=x+a<1kpDbp9PQg1FsjTtimgm;?RACyjMr7S*F7fQ`3CcxVEi?SE$ z?T$pg2d#b(>mw5DqXhTS3G^`u-e85$fF;cM1SR$#i<>H#SPH7yu{mLrj+gK>vws2z z@%&7+)E@bOgV~aa!Q&EmSi8ikg8VoH5`7|<{3Jkq(qhkH(thVTC4FVgJTz`xyDqzC!Gfy+*6aaamf_c`=8p^~7mKD%3Waoxk%lV*vvXQ{mNXHq9HO_tZ|-t5 zaS-FE$(f}Ki(eaoDJg~HDfK{=C1;fL&6L;HRGjHlo}(EiyrtmhADh{;?YrOhMxItfgGr`>Kl1yF%qA)`KbW5B1PKn zG)}OLY4`|lw*U^w^`f-x@Yn{iRaXk zV!7#cvu=C8_q-9LDQfJjzD}w4-r`J0>w+a%!E2HW_${jI>19pa>Z05?A&&jLrnv`} zPI#8(Ual5?R`3X`^3X9436B04^=4NK_?qHND+^5OBP4*d?>yZa9MULK1w6sgf#`xQ zu))1mkwV0h2{dL`tqawxmu1**-Y_*Mo`xydH4@lUW!pR9*q4v!(oJw!Ojpv)b8M{W z;rJ_Rx+>mmuy{ykr%huQi6RoyXIgj!IK^QfaOE zK-*a2;BqR!G5;HPg(g;-9=tUZA#KT?W(%rt;MjznoA5jPlEw}%5Ozfz){Mk2Q)Z;7*n8?nK~TVW>0E$dT3x zX`A&JXjk79(oGY0+dP$>mhV0AfEUnZ93y<mKEaU_%l3W(^hT2< z+|LijZ%RMlnDz-*L)`BM^2b54SOWkYl3uhu|X{qVjPvH5F~S@r!xKmgPm4o`i08- z^ILfr0|8-Jp&~NgB6ZcMY*QdyfH7bZy!7z^p0S6ue~2x?=5#5zh3I1C6Z^qp$@Ixk zXSUFyqR@qxVd~;x>H9ntcLJ@5%PTKl9t`Da)MRWVL~UIUn(MhVWfLrO=hR@%Mav$? zq@r+cbT~{VN>;{ut2SyXGuo;>x{94A17aZ)aMoJjdWHzkJv$~4A?t=Nguw<0&kSIY zycpZ%nS!k85>*d1!sFFMr^ZeN37KOzuYj>;AG zN}Jb9Tl01Xdsn1Tsj< zD7rp7 z%Xi{m-YsX3`zIZ8L8CxkNGu4U{J+RtWWcI2qGNMXK%G?pUB z&zH*IHHGY26_hQcw=QKcF=d>I$aCMz%Y_**mLbgtA8|<Zt0_Hx(6>Q9x{tRG$42wcllwn3qDG@FjAfuKCJi90?fLK|0zQkc95#{9;FjgC2lrRRXNG9c^i7w>o63w5hE;@;kQH&GP@cvEkdLVBc5mtb?0 z5JZg0pHoZ0&)M!B<{zAb_76h~hg}W+S9@Oq7)6o&-3eF1nE(nX>M$UJATzm%93~+r zw**85R)(aLj0}@FGa-N+QBlK+u83Cz1+QJj6Lnn{TxAiwh$R?y7rEb}OFq>QQ;ujQP9v{O#%KuY9!njgPi$ z@38y&z60YWY5k1P?IRy_T@qy6KH$do-Ohi1MN#sI*E)9GlR4vEsd(eaMIY=5zb@`y zpPgEid~@B{ng5!Yx4Ne4{LX9I-F-Bs?O#?r`L*=&jIWZ158Qs~{Z#9&$zR$S>Wo<)JQqUtRg}>2%A<*AMqy z(&|*&s#C9T?rX0<{z3P_tG0hz|G4{KHSW6l0d3z67@xgtOF-#u{-v)coY)e2*goa8 z+j>>>n}2r6=)ND^cp}YSx+A~un(2q1J9%c&xifD%&z#CTYh2f(UHgt**OdNbD4BWR z?!gBlcKBs&>MsTE>)!RFzz*XoZrhOLeptHUv4eL5dP1?Ykxi|M+^Tzob-ZkBj zKkMm=d)E{gPR$!MZf56CKI(fS>+5j?aL0Ure_)$?V)q9?yyFz8dut_@Y}NaBi5vJ zE6WM~VT1ppZDKZejk&pf&|MRb230*e>AIc|ru@9Vx>KU#^EZYJ?&ezbP?r1cah)Rz z|7rX_>>pFF`Ltcn!1nu|PdW1Q+J}Q~?d-R?tlQB|;||oN4J-M}KfAB3Ff8faYQuY- zCk%XSyL_hC>YdrqPk)hlw(F|LzCJPFy}c*@QP=T5%hEf3>U{t9>ibSCu6Q@pxnWVQ ztINDQuUs?rjUP@_-dTUuRgW)Ox&6>*HN_*}NGff2YS`=N-+k=8>_I!~pMCH{*WTb` z*X}6XFy8R+KicM8A31jQ+MwEOX+qriV8584+XJNhH#=`0k#uAElETcps(-NFQ!m-Je&O;+Hu+htgZ*Y+_RRL@X8OIi zV9iI*9$LKm7Bozo*i zzd2ABGja0O9Sd&kKBZUEq)FTJuKUN!D;K{rcHpZY2Y%D`hvU-n#0{-&Q$H;Txa*$N z(#Y2NF?$aDEoE8ZzGbW58Mx)nH6M4Jx%kE-ITPDlb>Q%%C9QYXg*c~ICVZ1SBX8D{ zKkcgMbbr>>kDL9{rJJS{W=^)g_`;GOAK&(dZOzUf5}C=+U~cy`h*O9 z^TjXxg2t?m?l>jo=8n(%54beO&u_Cq^3RXyJX{)RXdk)+M%8`EGfDfTy!E%df7?S> z58Ciar!^m*>0Li#WB&)9&#FmW>6}%yBXae@TclPi(hDPRd`vE!J5$QI<*##A8y9?? zjRn!bx@W(xnv*$X=UX*t%cc(fYk~YsOhB1EKe6!0{BQiSdM;Vfr&sM|cYS}~V;|_6za^>WvxDZTRpKU(Ox@$mJn z@>@BLLq7U^YOmdM>ppfC=UJzwe3N^{)LX91Exup=ao*&Q!=G|KQfYqd#E}i!QNu2`C%;{JZkPiqG+x$WuFZ_X`RlDT{9g7-go`^5S6U;O)Ys}HXE z{A||VNtuTtKVCihnY+Rkj9<3x$@L3|wHpeVk8e_cS?!lMe{_sPC66USHbk^7H?timZ+S(I$ z#Sc$ec1Pqj+j{=>hM!(}@4obpE?XI3f3o-a99Kws&c^j?hi{g?yK-&o?2YR`8yO=V zUe>B;v2^LiS=%>F_FEgY=^VH=dt|_Wm&xb$y$d?r>;>X-OAnWW) z&rJI0!7J6XH@w@ub&JTZiYf|iyZKL{xfAw6d^_3A>>6I^@yS8BR zXPK!lkDK_?W0O~W^V}^H0%wez6(K!2Y4mG1$FxbD@pt308yBpMKRV-*XTKZ$_;;hX zO-~+o^VPXok4@P!EqPsC-0PF~z7=G-cV=SUJtJf8`>@rqpu}S#Bi=Z0>E`8w+D09} z?*8@t;dRf;I#;n_SKO2t%f`*S z`mw`L?Cdb(wpZ?G-+k`c%xPy1bbLK%#)il5d-v91bK~Y5e*PanU%zk9um|MVf}`Gf zV#uLAr{p{QPkgj0s^8KXv-20)FZp3(jML`%&%Gd&fB=-r_~wq zoc@s?UHVF|KiN7I%Sy-* zXTc*GaT5xcWn_JkdQJ4pw(_yA>mU27-zy0(kGuS_x8I-mUd^S;Gq%k*i#{6yBO>1{fT5{vd z*Nq;NTeIT(eyc1mcY5IEzb^{;Ze!($ul_D4O`CC5e)Kh6G8PuT{oLM<$L_u+>Gt>b zzwNqd-;Pxe47866{^z^jKDTpe_O#$mIVlle4cxWrjXSd!oqj)W=ND1ocO3lc@c!g$ zk2~+bao3_#i-Wh!o7&;QRk8OE-!**cl#-4=t)BY89gEE`Ckr9VRN4?SO z!0IPfIu=h%ulk|O&o2!7%Zm5oQmU^Scxd&mRnEmZqpEM|eDH;+CsuTxmGaLu(TAVz z@w{tsj~$<6kLa_y_WrY7$9!3nlzQ~(sju8N^3hS(TRI%sI_#yc<6r#le2=u_Pd}cW z`$&(SpG=+6=U)p~R9yM_o;#m#mi^^#?*zU6ZQPxfjwiNeZ^*mNZ{NZm_skfvXKCdl z!FxZsZIST`_m+9?J_i=As5`Z_@7ACt-Q(V~bUD3u!WZ-1v4_Wg@R*@~`aSa>>2~Oo zoI&UEm+V?#vK(LZ#M^`Jxqo-3+wS;qU%TLnXDUnXbmwmz5z^*d>%QMDylO@H;;Gxi zZs>UT!bx3D*JplHvu5hC#4DVvtz5i_gHcPK* z+j~G z*rq1TpSvyn=7iO^CcGS$@aVLJq8SO_S0!xyQ$p>`#DE;(NBl&+bZmXHMer?8Ni0CmzU2>g`A@l9L9zlE#it8lIbE z%ZqP4H)-Mgq}2mIUcMmdy@j#e?@TIMoOE3Jc+ZmLj(6SAF+aKYJ;}okBoAJiJpH~A zOYcp#6(m3K@h1zHCBOQ>u;qVFe(%BL-7kMq^iXo`!_lw)C8gsdDT5v;KtlE(eV(%? z?S|NDt)JA29v*eOvDunG+lLL0rTSynGVL?U@nSoy875|ByRw~G*m^KNJ1uvPYmbtw{=))5~9i9Q>tkY#&Q|wqp*S!pB!XGyc#E zJIE2mFTXnvH$klIFtB|I`3|?XT)P!K40v~zhD#=CtYneq<1t$YV3}+mS=u{xBt4aD zvpZ2|skIF|;j!=Yt+YuY?Mm00eRrnO#;Ek2?IdY)=42?}S(|NXHlinuvKP@fv*r+w zWW4?8ds?njY_1v(n6~L-z#Q3SNrw^%6YoG9HD$7Oj!gTx#_rsA^372_KVxz-<~it* zV4}V7tBINpSgWvUvZlLDqFpKFbOY_HYO!b9WJ3tGZmu(pHdl3}W{=9oRcoEt(vn(6 z`vDs~Hk$Okh3%ZIo^b}kmn3xyTOCZ@!WOVuz~S=eU>i$6w1e5R$F7~kNB2^DNe2@j zaU%ok1Myv4{iJ8{F)+ zJPC#Tr9&YLn`BA1T0JbLje|fyCQ02f#$7jAY`OA{xt4Tnis=MLMIaem0QR?JTluQH z75C#}@V6bxXvkJ^U5r`cxNz_T^=5`DMYGv?8E zyxI5J_Sxh|)bGE$$L-Zg@hdKjkygV|7j1lWaJn4Xv*lFRe4DHkbk%`8?T`$=6E97$ zTV~nhbg@HhhYYLD<^}7n<1^N3m#13OU0G_cU0X!2&%v>m7hb%@nKdCJ1M!O^+eNGa zu5^hGd7RZHV;Ik|y4c9mw$Z*+heVP`S#osS$Tm_6=K7Y$<+@y;1GI-1x6#>FyN+FB z#h}z{fK`@A0q^O>k?o3035c?baHHj*)z_ZUrP!U;bm}|3wA3_A0bg}I*?zghz)+%hq>zG4hL9fUOIhHi5 zYd-HwkKNAoSfjG3^)3(h(glvyn$9-+WhoID(->=N=$&@9;7~r{>q4&%riNY(rZ+C% zZk@)r(;hkzJZU_$Y^bqJhWm=SEE@yv-FSPxnwZ(NyICP?a%K~lV6$0soXBUC=y)+R znrSzkUTEMoQZpLs(Jj3cn5tI$)||olLOx|Q(q_CVL;tlIO>1;NGXTaz`{O6Qn=eUM z9SmgGYhxsK4S%W<*zW^60;rz?O4n}yrK_K`2Y(5Nu0%su;^D_|dgOB&x)Kk%>M{+# z$@ofj(LAY08wlFWOoL3xXQn|xRhLFImTCNF#YLz!Hllz>QVldPEAIGY%e+Y*mIengJ?14iUt8SDkcw?yQY zh%8_Hh)hFYywuPkzw_zf7!FlK$DGp3@@F#GZ;QyA6Y36qwKE`N^E7$e$TL|dE?PuR z=M`?os*W0w4Qbgq^Oezm5!V_1s8M;l5|wwx@Tj~`jmk%$LyF3DrKn6-9+e4)qA}6X zm3Z)|{9!()p({mYy0%1RkElG4rY!u`q^P{eAkdo-l?k`AkEm?G+&LRjdOjOr$_k{9 z`EsZKj_5q2B|7USxZYDkWi|~{&`;o6=F9)(^JU=%==!@v=NQN4QCA}_Um!Yvi@My1 zu+RbTHzYP+?mnF=*#0G&ec>;bq}snkUWNbW5`eOP34IDL&z*lu-#F zB3_f{r)Eh~Uz|@PPWwTD$4kIta=LA%f|#6TygU>a-JEdpys8WWgf(aU?1C10uO{mYz{5vf0w)RH9(5Tlp!x|XWXfxw6D3+Gw7W## zp)8P{b>+2I+&;mc$yUHz7FRm`lx2u)-+uV;_JJm)z?$Z2A4mW|(yjO@0iW2{KojvZ z45)WE=-*BQfi!X?(M+^BESU~VPS&JcyG9w$56S|JeuM;EVX4DU&5~tE)`|j63Kd(v zWyJ`vOg9L#)GLnQxdz1PVv3*%zf5fu_+|y|iXn(=7DUiy@TPEzp!`bvRwL zf=NFC;3r+wQ52=REDl#gaDqL(AutuImU5h&k?oK@SP(ci1MALuXe>^IOP-&Da~p9a zoWbSDm4!$Znm#q#k)CQ@Aj6ob2gwc`GB4IDKQY_s@`hm^=9JU$1Jhgu-DwyqSlo)U z&kSLaS`(QRT5z>zqK}3QW&IX1BrHsHUZ82L>_YXaeH=-2q}G|JTapdU(Qv5u#apq0 zKohlktc;(qAS+~u+5rlP5(r_8fu>~qzDjr*7W^(PY9E*DusAK57KhanKE`TyX3x%@ z;7BJm3+x1(A2*+^=4a2z$#$Yh$Bf&bVt}X`Tid>sIUlEclNczlMKkggF%aJubrN1%KtL*L>3rgoX;EG*Pfm zv1eohz+2BD&IxwSxJ{{9*?EMh1JPI36(K`;S1>v;7(C3(Ph7yAzNIdk(?~kfs2!~sX2)@OQut8B3BRc7%Px1PBx}YQ=D?5!;(h+-eO}O ziv6VM6ozM-gkPm(hn%jdQ~CXp(ZeR_S8NvNMBS%4taQw7yw!nUu_=yldo_*9vf9!e zvYm%85yKP?de=sA7DtcLkM&}tn5b!9Q8&=kh$L95CQFzxS3DJEXV11O{!*zjpz4iF z$^cPIeAJK7;h0=;7W^FK9knS6QGvooZ6?8)uJkP>;ADrz?nF$S!+4r?`GFW94Uj?< zsj5}+A??X2)K}Gn7KED}U3OcXW3)pLbv8zTAD4+s|BU zxWv%QaD_Y2e2II6dxkmC+`-(*+{GMht~1x0pEf^ZZexx$k1{8ilgugRH1j>?d(HQo zA2L5{e%}0|`ETZz%^#Y7HXk&Xn#;`R%oXNU=G8b8vX3-1=8oph<{)YM0BM?Zr~9D0we-B(ApOnU z)!m9yj*;aYMtF(gY7P-mT4^5y4yFR8$bxiIYtCxY$vF{GJnF|<7q%;m~ydCB;28J>RSAL9ph_}vu1Fz7F$Sdq3@(NdZ zF(ppUlE=dbuu6V78;?#ye9|^rU&rjUXufa zheoCbCeMk1>6fMjO_&t?@|3{mgaDk`3_%x3d`t#RKBodE9}@x71*QRNFbHHuso7$) zO-mycNw+W~mJ;*14oi=D7A6v6Q=%nzUR<_Km#ZO*1}w#8!6D*mdV`MF&z{u8S!he0 zT$*s0wsip#ZwxKErH5u=Wc-09WHv5Le!annt7)?-8CTGJ=I18Q?40EQHY6>nS=J0~ z#?0D>#a^f2MQx{aflvi(3T0djpv}f8_qNWKU0FC;Ju^$+=&{yJi!0Y5t0@}|V-2Wd zA>?S8nWFT`PTZ=k>4)_cEjZ9Q$PoPXV=bSo- z<;t4$yO}SjnADk3-_Sv)inmUgjv%qJeNklSuMDe7B&dK#Fg$f z{@8r6k+dsTnu{Ac?1-5TX*@p7!>yOsA)eCBm{y9W+{LG|dv&?3F>}-=FQ(M_c2|}R z`K;Jyj-s7Ml>%9F!PzM#BAnPoUgDcS(?e7EkHby)4sf-g))Vn58*QK)Ni)#`8zqhx zYDJ?`xbw=z>K(sTnYoxD5ktc$T}jp8&^y$Rc?Xtvl(JbqDHLc!d<1M81~?ZGr6kef zVF-~-V?XOD3($n19zydgMsDMMZZrNb5Wcd*qdF>JOyP zZ0@Sur=bB*8bGDWjUKFk{QyP}IiXOzx)9PtOcHYFr;EAl30qNyYj>~W379N7yjZj+ zoJrZZ&p~~Vhi)q&F5*@a9Y=m|jPev+cN7G8-{qjc`wu^!q_gkZ({i2Z`yc+^d|N!b z2dJ^9dOQ?DUz++9kGNl^$#*4n_)k8UoOZshTxp7Wv)9Db*kJ|^RBy!|_)ND5fT-u@ zI{%|j@%Xc+cE;!P`-JsZUh)>I@h(dBSAU6~O(BT)m6s3~D$!qgTiEl$ztdAZTjw7d~S>=Xu|!%y@A`|S3X-C@ZaGr?or0ZAL-fJmM3}m z1I=Tx?5Qpcw>(=r>-IE^NAgCJ^c$b8wGaRE<&2N+Ug29tf7f<12dd#Crg-C24*G3R z^28u&>R&vwxCqbI{+6g5%A?}Ne2S-ek1YQ#QF#yao}AC0#L-{<*|Rw_P)Zp3tG{$W zfp}ke32~tk{q=t|D&GlJC@<}{Yed;u1_Abbwsv8@3isFpBQr+8e^XQrRdW2spWq4n z?}*C(Y>CRWPN>AZmM3`rH+HSeDoy!t(W0_VVTh>z%R8nK zPLMWN4&_hSiaG25Ky=Q4wkQVcuRJ<0$mb>cE04hhp%|>c@)F`gCHiYiboPkORwz$- zdCZv`i_Z470=)^*xgT(Ye9oCeasOM>p0jQL-w~xtTB3AIl-Bki`ybhtN{ha~Pn3=s zmoMB8yI!;?EuQFXa+L1s9i>i#W}x+PM#MC$)^q|Oi?h+i*O zr1oE}@NM#(x_ztzn|NCs>DcU<)k51pw>|F9bKt?MS$HssJ;jds2s`0I%t!Ey>nvV# z^^6eZOc1uEKY3-g!!_-#MfGC1zxR0|bCQ`{sw=8Pb2?Tps*e;vP-;9r(`}U<#dlh0 z@YqYdbDGWKbSB!eE#km}*2IAJk@C7JQlil04WqC`u$X+J;xGCE)(h4#GZ%ZY({4i8 z6GAy$f{?q4dSTBWr|hC0mw*(o2QpI6N0hN6OgK$vrAZ zBeddu+St90URJ%9xBCKr{jfV^cj-3i7U@>@j~?Z-;c>e;*h|4GW#Pd%dS~Ld1^Snc zvJAlKdnT|l*rRh9u-Dt9nRwqOO$QE9&c?cT8m>1>qp@GwX#5)oIi2s4?vj4SZrio- zQt&7Ee3x`sY895ZuBgi0s;Dr-__=gUk~W=pOU9FuUvL>dlmWe<27p==l)2j$Z(5f( zC0II$Z$G)EP4&LeKo(yQPX1v9#i!i>y!hMR1EZ@^FTQ4 zmWurfrj#nI>wKVa&NyBre$z3xe_3AeSsmlT8n<6r@JUHBLc%)KFdo+o;#`VtxBZLr zf{$vf8{lx(Xm%LT{mSyr3C<^=uPV2chbk9=VelbIDm+h;IOjT6544Nv16pc`#95z` zq`aTqew%_Tb)56Sxfq-?z&Wo}QDz}dgFz)o$P`Eyj2q%`#^sWqv1q^BuPC@m$GN!D zElm-WmB0|75uOi-^=eMb>&Rym9D-MGS81zWI6b9}2qJZI?C8?Eezry%) zl7Dbs8C0}R@H-Ok7bZd2rgO|jnK2b$BV6jv3nX zTaSZwAP&{rWIPT1=fQ|JvGx&FsRS*>;}aPv87*ClArEMhibW0cCkG<1lDO$|HjyA|?&CB^jB0fh~!d0;??ou#kF}(8{ofqj3`{H291r&L=8~ zgYrlb$E4Q5MeeeA02E>94G8itBy*PXAT1cu3gG}~gvM*q>QN8$!6uzBpP2O$8Zw0m zJA$#l$w)(pDqJd&?L$;N*CiPXYavEW0T7CX0?MR1(n&R{Lj#*=_cexFFICZSp)nu! zgI-WsE$k0e{wO@ADfi^pMnl!!$^}+DM5ldU?G9k$s4bp%$`a%dB`AMVUR&OCR3&nUI;yg z;aVo#OBuNl7>?44!lQYTQIX#Om&u_v7btRo?Qdjp zh@onNAb^Ji`apF+d#D{nr~$Qe6ZFr#CDWaU9Mr%kW+P(Q=tu3vsH9LpE``2lTu_Qn zOkYxP$P80b7{rhvkU>*?qu~*ZD;ahpjX?!`V)_=thDVWNnq<;!m_iC&X_)$uf)ZwM zpz?|BDT!l~!GS9o8mWlXZ$!YO7)jktHCEFQ) z6ov*dWCvu|tjFLjna5KSEQB3YNE<`(2#`MUm=GF2o8ubm{i=IbysY`;D5E`a&7jfMv z)CBfEQ5kzOp8^l|d08;gH-LW; zW?d8sXttxUr-)BMlH8o&&z!3_sv7Y#b}E>q6b3T(a9uO!k35E&5v*q~L8CA;!5+ju zQ5k!d6L_#M+6{J4K1{P!0Urj1G--kqo_%E?IbgFnf`HT)B1`e8k$F%aBP~UO$R?2F z4w!LJ2SWxz9@$2`CW8+6zzmI=L-tC(q>y57o+bw!M9IDy zAt9zAnwses1s`G4iXzpvnIPr@A&6{^ESDuPLPi z3>qq`hpzH4S{3!7O%!G~VMt zDJIg;$tEKPwITxgAe+m82)dG241O5UKm-|c5hm}&v|0hU#~gYcl`?24S)d+I%$%#RAW?wq(?2+)7z!?gdr%16+@cF0 zhk6;3*rioli;k(GADs6pi3Z zJzfmH!6-FyzNFAF8ZC^mTEH1AYZvGwhTz8-tixoT7?O>m^QCo|aHE2C=%WnM`#v|! zNG;%uXzpHs#EQ*J_PPC7#ytg$D7tL|BO0O^oRJ$fVjmeJwSY6il1Y3KR)C7a&haX- zWThCBL+TtdG1ghIZd$O~+M1F+E zBVSi5%tJ~^>uQXbTE=-{F)hBZ>=de%K~}cUt*qU}=WRkKD{FVk>YkCW?%}z$_V_nM z{TC{QN|Ef}^~#lhyYOG4(*9kqejbedRR^$t{iXgSiA%337wd|r%4s#Ry8NV6RsJ*H zwNfe4mV?s1a(F@oQjO2Yq@(5KfYK4hRppq)lpg@qdFfEOySxa zpH(T&Fd0XHQw^$esjmE7`DuLm2@nA#PjeQ~3Wh`LN#&4Jt(LZH@pJ4p24U6kR_l*RZ)ISsx7ZzRHyJ)!kha07~Y%`SSqD} zQuwGqo$Ap(k|!vs?~emQwVQcw8Z6URJAB4uHICY<=-C!8dMeU$E#9ON zdN-sJP@<|T-wE7O*cDL`1yNSBdV#w_zgGvPe6CWVqTZ=tWmT{xK~)7RYT;g71(c|& z%D)4&6n>pkQSDCyN}8i}1Wr|~gX*cyqMUe8?MO4!OWsr*N>tV5-{M^gd*;?eZKgJI zDykj5i*-<%E>w9?aamMbdeiKNsP;1+0xGEXm%A|vcps50k|U_dDv3&iHl!j=Y2_sA z!c-L~r?==UYMVwylBqTX)ypDVpqdE_@TTI{;!Q<$q1uxy(gA5-lSSA9s+UDDD*H85 zTpKi&^|GqVe?%<=RLG)UCfg}jYDj*HtWNY-H5<7C>PbbI+(t#YW>GZW1yoN(V}hut zU1VommatwL?*gi~!)j?Sqd1RpqSWLNg@Eeqy++!@fex zQ}7<$rGt7>>}K`XD1>+Mq|p4tdFe-1fA|in5#EA={D^?+Jz7%gO5qC`ExvSd5#E51Kbn^rId< ztx$>B@tpz@aif;$UZbEW$K_y6j#>J*3Pi-H8fL3RQO)B0Da2Nun}~S$tpXtmiiMTT zc1k7k`jjCE3N7wx6clq$A?}d15k)mJ7@{}_P4L)W0*>^J`bCTDCD1u#I~p#<5k2l1 zWDIp^eHEbIxYUPw+;Z4;B_I;`QBH6QZ8!q?=h4y<=!d?M{L{!ZDtzG8p zDi%v=Y#jzS%E?NY?kH2Ce5@4S)f4M5>Uz)v>zH&5{-dOvXRVYOYT4rdQJyNRd8*9v zR2iOFMxH7oPnB7oDx>ceNHsnqPnD6Uq6~Se46h+0PnD5*%5E8Xsto&8AcT!PRYso5 zuqzpFWTgzdRz{x6usMXVp=ovJstS4k7-q zXVm?yN^yqCKt>8kH8fTypOX$SU%g9qzC>xt- zVGUYe4V@!TWwJ1?(86kPK%Oci;)1FQTINvZ17zf>GGZ>MV997%HKRmEs!#$;r4&%+ zZy>!M?bB0I-^1UqS}@;+p01XWajH=Ap%pUX7L!*4Epd4o74lTZ)tjnPMic@SX^f~y zE67t7S@7443VEsuB@bUIBTA@LRjh49NiAk^fqg=r%J>mfPepo06k}903K~)gC{b0( zJAupcRAy<2bD*qd^@2==eyHgW}2)R1h0_>F@pcE)8< z4M+<#-UU=|hsaYI1u{~0)#MO`fa>iXc`B2`$1=5tJOh_OagFowrl49OFCuJ4!FzO< z4(dsVps`I>;z^;og6v$JV-Fj09|4I=Rc`B06oYM8CEJe9?JWSxLgzlnH=tdl`REUaXYdy$XBQx=b#B5+e@Ht`bPbt#q|>CoN^ltm*R*X7kMgd=rn5I5SRK; zkBdANdMSZ^t5{BeJQXqakbEBPDuFiW8_7qW3cG5ESBG*v9?zXh1`+WjR?1 z(-dVYEKh}Z^~5@ib|FvIVIfb2|0t1_JQbOtlBXhD{6ET5jcT6C?#`^neG^qiMH%u`-2PLAb@^%|@>HW6OV#^~$Ws*vVIxn)-4z_WlJQ1X z%CKv(e$TNvgs`D&{IWpU$UGTuWTgzd20!iWL!GLO975R074f@}9vdDMzpWfHRvVG0 zGHebZY~-o93xi{yV>J=jR4;FA z8FfFaQk-Ejkdd--j2GiM+yPi^M4oCCP?o0xTETEwo(ehDYB|QG@hr4mZA6}`LfP0v z3v1B&YUmt!DwBnAg%(zW1M*bd8$wi7&@zV-RfQ3GD(<%+Dp)dF#`_x?sX_@Xl~O>N zzk&36v`P=N?L=*xQX^f~y zE67t7S@7443VEsuB@bU|M3hjes+d-Yl3L92RQ3sZD&t2`Jr(I0QH)X1C}>C}phQ(= z+zDKkr!q@JoC9Sws~2P{^m}zsigT3;74;6HGLuC;L7HU|n6(gjDlCjcS#&faVnCLl zqBbE<^`b(?sY3Ns$nzkJv_a+7td}%doQgwi{uC@vPz=Tpbe==Q(8I80xw8~92K&74N2?N zHjRoT3#eWe*#gx}Sb#Sbw-$oxsgS3#+LPvKtdjOMS%fX1o>aV6zlMrygZfP`tJ;V> zmGvecPvp721rBAL)Q?;ng^DDDx*L~%C4Fmq7YEMy(3R$a`;%L_K;`bGAOQbKHd~mD`cI7%_w+} z?$SX$DR#5^YZNrL$x1vaG(UknmDL}S z{2uaDFAC(T%x=9Ygny-oiaeFo3>hi&+?p>ZuOpx=Pld&}+4x{tC!!zq=xK#Y#17=C z3?kx2Ez`Y5fjm{AK%UCRAM#X%g2$*DW~(euW$_+)Dk2y4n}~aj6gW zxX4qXmlEi=isb~zQxRhi8PB6#CC~QJu7UC2{)Sjbc1KT3>Bo{G#+$y1RnHupu(ER7xKoDI6peD^rUAv7Ns zDw}9=xd=j^C(m<*O45Mt22=Dq-li3hu7&(%z^esezO;fG}i;gzXsk}CNh>D#B zsNkB}X|lh3teL?SY6u}2{681k6vpXzh;No8OASvlBbMgov;5`5%YG%}$#_s}4r=O@ z=w!D%X%cEq$9LMLiBhUGPMSQ>O9?ZW&O?1@n`w2R(zY4YBcd-@gE?VXV}y{G1=%jV zo$ON%ZWQr-W@|X=6ru1j8%$w_P+tn=o!oS;VcuNBF9z38Z?0h%gKLO4SD#kOHE;`h zlMY9o1I^m;rbCkLfG}t?_$1-{JZ>8<^iZzUEWQ_L^)KnXM77GpM`6v zat%|i;lABTW7hBcz-(7*j|X z`%50k6ao(T8_E7gDKtYB?jg}aUZ`396rz4os}-u&D>Pg!jZi;Ds-L3NPeavDs*EsH z6-`w6hpGI-RQ_Qq|F8(852i3woLU|h#lEqYhoR|k8)}WiL#QmAH9cJ9F+-TEH-(3@ zGR7-B5{aoP97@1n#wk47a2-=@gjswDq0$JoW)YkpC9J8|IXO0YqQ#2ik=1;abdGeY z!MVmtGGU6~0p-`zbL-OR<7_w*N_G%`Q$(b&5>@XJqH7~mwMVLoie!z8WQvLm5<`%tx2Ls_eah8n`C9z(;Ft6HC-Yy=GD!%mYoD%XkaC=z9M zlr~f6Pz*0KYs^rkmVA1lrVO4VTOOs36(H4+ z;Xlv=)cNosyuNTD0>l~u_W@RL9bgUD!I{E$&{x$Xss7^vK|2mtHQ{WP2$jaxQ~^h2g;g9V;WERr7 zxP3-qxKc=At>RKHQ!9p6sl7{?6>DJANhoh45}$2}R;668lLF0iDNR>0lCH+3`0f|X zjG9Y=q^H?6Lx5;LjWB@bn3=GEX4n};{^n{LnRfGOgb_5SZok3`km2*X`7}1)W`NAA z*)*6TC^~5RIKX_O`828>G((PR2O7;UxhPC&8q`gr(OiMvtziOm0loPi*q9|La+*G} zX^Pcc8>KlIr}3qOMtrWY1GDO<&7f9YA0}~}r@5nWmu3Vyt^9)h>)ZA)3v71VC|Y^9 zjkI|ow~g5)r)kExz+ANXbyNFS)B7*hP4sVb>gJ<=e^HL;Ute;h;UW-8BXxa>rMhP8 z8jE_3>$)*HsvR_4Z&)yFcK={evGKYYe2>}iX4wJFh{O^D1^r~?vUbcfXwHG0mg$xj zb;T+It#I(nOk`L*&m!7b=_V;&O2FR~X%w!MRtnyp*eZ<<11gQ?D>lSmnsg-sU<6{>i`hdITl&Vt87sHVnK%!L4v#j6Ai<1|G)EhTgdowRbt%+^YS@eg*CC-1 zW`q;Zi(tgr5l4@PB6Z=df_a9jdf{liK&X^;2rYvtNiVHDP8>z5XNurx1Wbeowy??; zscB|RjHqN1Y0Tqm1C+5K#-uqiWJvhXC>FOP3}INQiw@-uj<3{d!A@!Y{4L9_v&ZWXW}9C(O&S*wZIuWMBt)kG<)oiNFSy zKi*QZV}ad!_xYO~t~4)L+iZt5(`x_Ce1f%_CD<*qY;yW6+}%iZ?m{KwWv9yv-i_cB zvz=C#HQVl0*29_Qu-a$mIV?F7?5UQyvaXyO*DpOgEnd#B0<-AyB^L}k>`cc`o uY=>u?CMCs<0%a>ApOkJ8TE!+^5<5Oo(K7o^``_!n_x%NFo*UtV-~R(2w$u;+ literal 0 HcmV?d00001 diff --git a/avdevice/webif/static/img/plugin_logo.png b/avdevice/webif/static/img/plugin_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..cc3b2aa5e30cdc4bddd0b2e1f90cacf33b0f1eb5 GIT binary patch literal 8980 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. + +Extension can be png, svg or jpg + diff --git a/avdevice/webif/templates/index.html b/avdevice/webif/templates/index.html new file mode 100755 index 000000000..fdf475204 --- /dev/null +++ b/avdevice/webif/templates/index.html @@ -0,0 +1,378 @@ +{% extends "base_plugin.html" %} +{% block scripts %} +{{ super() }} + +{% endblock scripts %} +{% set logo_frame = false %} + + +{% set item_count_zone0 = p.init.get_items('zone0')|length %} +{% set item_count_zone1 = p.init.get_items('zone1')|length %} +{% set item_count_zone2 = p.init.get_items('zone2')|length %} +{% set item_count_zone3 = p.init.get_items('zone3')|length %} +{% set tab1title = "Zone 0 Items (" ~ item_count_zone0 ~ ")" %} +{% set tab2title = "Zone 1 Items (" ~ item_count_zone1 ~ ")" %} +{% set tab3title = "Zone 2 Items (" ~ item_count_zone2 ~ ")" %} +{% set tab4title = "Zone 3 Items (" ~ item_count_zone3 ~ ")" %} + +{% set tabcount = 1 %} +{% if item_count_zone1>0 %} + {% set tabcount = 2 %} +{% endif %} +{% if item_count_zone2>0 %} + {% set tabcount = 3 %} +{% endif %} +{% if item_count_zone3>0 %} + {% set tabcount = 4 %} +{% endif %} + +{% if item_count_zone0==0 %} + {% set start_tab = 2 %} +{% endif %} + +{% block headtable %} + +{% if (p._tcp and 'TCP' not in p._is_connected) or (p._rs232 and 'Serial' not in p._is_connected) %} + {% set conn_color = 'red' %} +{% else %} + {% set conn_color = 'green' %} +{% endif %} + +
- OAuth2 Authorization URL + {{ _('OAuth2 Authorization URL') }} - Click Here! + {{ _('Hier klicken, um OAuth2 Prozess zu starten!') }}
- Callback URL + {{ _('Callback URL') }} {{ callback_url }} @@ -79,7 +88,7 @@
Nokia Health Items ({{ p.get_items()|length }})
Access Token {{ p.get_item('access_token')() }} Token Expiry{{ p.get_item('token_expiry')() }} ({{ token_expiry.strftime('%d.%m.%Y %H:%M:%S') }}) 0 and token_expiry < now %}style="color: red; font-weight: bold;"{% endif %}>{{ p.get_item('token_expiry')() }} ({{ token_expiry.strftime('%d.%m.%Y %H:%M:%S') }})
Token Type - {{ _('Hier klicken, um OAuth2 Prozess zu starten!') }} + {{ _('Hier zuerst registrieren:') }} https://account.health.nokia.com/partner/add_oauth2
+ {{ _('Hier klicken, um OAuth2 Prozess zu starten!') }}
{{ item._path }} {{ item._type }} {{ key }} 0 and token_expiry < now %}style="color: red; font-weight: bold;"{% endif %}>{{ item() }} {% if key == 'token_expiry' %}({{ token_expiry.strftime('%d.%m.%Y %H:%M:%S') }}){% endif %}{{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }}{{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }} 0 and token_expiry < now %}style="color: red; font-weight: bold;"{% endif %}>{{ item() }} {% if key == 'token_expiry' %}({% if language == 'en' %}{{ token_expiry.strftime('%m/%d/%Y %H:%M:%S') }}{% else %}{{ token_expiry.strftime('%d.%m.%Y %H:%M:%S') }}{% endif %}){% endif %}{% if language == 'en' %}{{ item.last_update().strftime('%m/%d/%Y %H:%M:%S') }}{% else %}{{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }}{% endif %}{% if language == 'en' %}{{ item.last_change().strftime('%m/%d/%Y %H:%M:%S') }}{% else %}{{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }}{% endif %}
Access Token {{ p.get_item('access_token')() }} Token Expiry 0 and token_expiry < now %}style="color: red; font-weight: bold;"{% endif %}>{{ p.get_item('token_expiry')() }} ({{ token_expiry.strftime('%d.%m.%Y %H:%M:%S') }}) 0 and token_expiry < now %}style="color: red; font-weight: bold;"{% endif %}>{{ p.get_item('token_expiry')() }} ({% if language == 'en' %}{{ token_expiry.strftime('%m/%d/%Y %H:%M:%S') }}{% else %}{{ token_expiry.strftime('%d.%m.%Y %H:%M:%S') }}{% endif %})
Token Type
{{ item._path }}{{ item._path }} {{ item._type }} {{ key }} 0 and token_expiry < now %}style="color: red; font-weight: bold;"{% endif %}>{{ item() }} {% if key == 'token_expiry' %}({% if language == 'en' %}{{ token_expiry.strftime('%m/%d/%Y %H:%M:%S') }}{% else %}{{ token_expiry.strftime('%d.%m.%Y %H:%M:%S') }}{% endif %}){% endif %} 0 and token_expiry < now %}color: red; font-weight: bold;"{% endif %}>{{ item() }} {% if key == 'token_expiry' %}({% if language == 'en' %}{{ token_expiry.strftime('%m/%d/%Y %H:%M:%S') }}{% else %}{{ token_expiry.strftime('%d.%m.%Y %H:%M:%S') }}{% endif %}){% endif %} {% if language == 'en' %}{{ item.last_update().strftime('%m/%d/%Y %H:%M:%S') }}{% else %}{{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }}{% endif %} {% if language == 'en' %}{{ item.last_change().strftime('%m/%d/%Y %H:%M:%S') }}{% else %}{{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }}{% endif %}
{{ item._path }} {{ item._type }} {{ key }} 0 and token_expiry < now %}color: red; font-weight: bold;"{% endif %}>{{ item() }} {% if key == 'token_expiry' %}({% if language == 'en' %}{{ token_expiry.strftime('%m/%d/%Y %H:%M:%S') }}{% else %}{{ token_expiry.strftime('%d.%m.%Y %H:%M:%S') }}{% endif %}){% endif %} 0 and token_expiry < now %}color: red; font-weight: bold;"{% endif %}>{{ item() }} {% if key == 'token_expiry' %}{% if p.get_item('token_expiry')() > 0 %}({% if language == 'en' %}{{ token_expiry.strftime('%m/%d/%Y %H:%M:%S') }}{% else %}{{ token_expiry.strftime('%d.%m.%Y %H:%M:%S') }}{% endif %}){% endif %}{% endif %} {% if language == 'en' %}{{ item.last_update().strftime('%m/%d/%Y %H:%M:%S') }}{% else %}{{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }}{% endif %} {% if language == 'en' %}{{ item.last_change().strftime('%m/%d/%Y %H:%M:%S') }}{% else %}{{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }}{% endif %}
Access Token {{ p.get_item('access_token')() }} Token Expiry 0 and token_expiry < now %}style="color: red; font-weight: bold;"{% endif %}>{{ p.get_item('token_expiry')() }} ({% if language == 'en' %}{{ token_expiry.strftime('%m/%d/%Y %H:%M:%S') }}{% else %}{{ token_expiry.strftime('%d.%m.%Y %H:%M:%S') }}{% endif %}) 0 and token_expiry < now %}style="color: red; font-weight: bold;"{% endif %}>{{ p.get_item('token_expiry')() }} {% if p.get_item('token_expiry')() > 0 %}({% if language == 'en'%}{{ token_expiry.strftime('%m/%d/%Y %H:%M:%S') }}{% else %}{{ token_expiry.strftime('%d.%m.%Y %H:%M:%S') }}{% endif %}){% endif %}
Token Type
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Model{{ p.get_parameter_value_for_display('model').replace('models/', '').upper() }}Connection{% if p._rs232 %}{{ p._rs232 }}:{{ p._baud }}, {{ p._timeout }} + {% else %}{{ p._tcp }}:{{ p._port }}, {{ p._tcp_timeout }}{% endif %} + {{ p._is_connected }} + {% if p._tcp and 'TCP' not in p._is_connected %} + + {% elif p._rs232 and 'Serial' not in p._is_connected %} + + {% endif %} +
Depends On{% if p._dependson %}{{ p._dependson }} = {{ p._dependsonvalue }} + {% else %}No global dependency{% endif %}Depend to 0{% if p._depend0_power0 %}Power, {% endif %} + {% if p._depend0_volume0 %}Volume{% endif %} + {% if not p._depend0_volume0 and not p._depend0_power0 %}None{% endif %}
Ignore Response{% if p._ignore_response %}{{ p._ignore_response }} + {% else %}None{% endif %}
Error Response{% if p._error_response %}{{ p._error_response }} + {% else %}None{% endif %}
+{% endblock headtable %} + + + +{% block buttons %} +{% if 1==1 %} + + +{% if config_reloaded %} + +{% endif %} + +{% endif %} +{% endblock %} + +{% block bodytab1 %} +
+{% if item_count_zone0>0 %} +
+ {{ _('Die folgenden Items sind dieser Instanz des Database Plugins zugewiesen') }}: +
+ + + + + + + + {% for item in p.init.get_items('zone0') %} + + {% if p.has_iattr(item.conf, 'avdevice_zone0') %} + + + + + {% endif %} + {% endfor %} +
{{ _('Item') }}{{ _('Wert') }}
{{ item._path }}{{ item() }}
+{% else %} +
+ Es sind keine Item in dieser Zone definiert. +
+{% endif %} + +
+ {{ _('DEBUGGING') }}: +
+ + + + + + + + + + {% if p._send_history['query'].items() %} + {% for key, value in p._send_history['query'].items() %} + + + + + {% endfor %} + {% else %} + + + + + {% endif %} + +
+ {{ _('Abfrageprotokoll') }}  + + + {% if query_cleared %} + + {% else %} + {{ _('Zeit') }} + {% endif %} + {{ _('Abfrage') }}
+ + {{key}}{{value}}
+ + -{{ _('noch keine Abfrage gesendet') }}
+ + + + + + + + + + {% if p._send_history['command'].items() %} + {% for key, value in p._send_history['command'].items() %} + + + + + {% endfor %} + {% else %} + + + + + {% endif %} + + +
+ {{ _('Kommandoprotokoll') }}  + + + {% if command_cleared %} + + {% else %} + {{ _('Zeit') }} + {% endif %} + {{ _('Kommando') }}
+ {{ key }}{{ value }}
+ -{{ _('noch kein Kommando gesendet') }}
+ + + + + + + + + + {% if p._keep_commands.items() %} + {% for key, value in p._keep_commands.items() %} + + + + + {% endfor %} + {% else %} + + + + + {% endif %} + + +
+ {{ _('Zwischenspeicher') }}  + + + + {% if keep_cleared %} + + {% else %} + {{ _('Zeit') }} + {% endif %} + {{ _('Kommando') }}
+ {{ key }}{{ value }}
+ + -{{ _('noch kein Kommando gespeichert') }}
+ + + + + + + +
Sending Command{{ p._sendingcommand }}
+
+{% endblock bodytab1 %} + + + +{% block bodytab2 %} +
+{% if item_count_zone1>0 %} +
+ {{ _('Die folgenden Items sind dieser Instanz des Database Plugins zugewiesen') }}: +
+ + + + + + + + {% for item in p.init.get_items('zone1') %} + + {% if p.has_iattr(item.conf, 'avdevice_zone1') %} + + + + + {% endif %} + {% endfor %} +
{{ _('Item') }}{{ _('Wert') }}
{{ item._path }}{{ item() }}
+{% else %} +
+ Es sind keine Item in dieser Zone definiert. +
+{% endif %} +
+{% endblock bodytab2 %} + +{% block bodytab3 %} +
+{% if item_count_zone2>0 %} +
+ {{ _('Die folgenden Items sind dieser Instanz des Database Plugins zugewiesen') }}: +
+ + + + + + + + {% for item in p.init.get_items('zone2') %} + + {% if p.has_iattr(item.conf, 'avdevice_zone2') %} + + + + + {% endif %} + {% endfor %} +
{{ _('Item') }}{{ _('Wert') }}
{{ item._path }}{{ item() }}
+{% else %} +
+ Es sind keine Item in dieser Zone definiert. +
+{% endif %} +
+{% endblock bodytab3 %} + + +{% block bodytab4 %} +
+{% if item_count_zone3>0 %} +
+ {{ _('Die folgenden Items sind dieser Instanz des Database Plugins zugewiesen') }}: +
+ + + + + + + + {% for item in p.init.get_items('zone3') %} + + {% if p.has_iattr(item.conf, 'avdevice_zone3') %} + + + + + {% endif %} + {% endfor %} +
{{ _('Item') }}{{ _('Wert') }}
{{ item._path }}{{ item() }}
+{% else %} +
+ Es sind keine Item in dieser Zone definiert. +
+{% endif %} +
+{% endblock bodytab4 %} From 0fc2f35640187f95382a306efee65f31876f03a6 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Tue, 28 Aug 2018 00:12:28 +0200 Subject: [PATCH 178/705] re-up correct items example --- avdevice/Denon_Items.yaml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/avdevice/Denon_Items.yaml b/avdevice/Denon_Items.yaml index 127a3d154..07eeb165f 100755 --- a/avdevice/Denon_Items.yaml +++ b/avdevice/Denon_Items.yaml @@ -231,10 +231,10 @@ Denon: Musik: type: bool visu_acl: ro - eval: 1 if ((sh.Musik.OG.Denon.Source() == 'DVD' or sh.Musik.OG.Denon.Source() == 'CD' or sh.Musik.OG.Denon.Source() == 'NET') and sh.Musik.OG.Denon.Power()) else 0 + eval: 1 if ((sh.Denon.Source() == 'DVD' or sh.Denon.Source() == 'CD' or sh.Denon.Source() == 'NET') and sh.Denon.Power()) else 0 eval_trigger: - - Musik.OG.Denon.Source - - Musik.OG.Denon.Power + - Denon.Source + - Denon.Power enforce_updates: 'yes' Mode: @@ -437,10 +437,10 @@ Denon: Musik: type: bool visu_acl: ro - eval: 1 if ((sh.Musik.OG.Denon.Source2() == 'DVD' or sh.Musik.OG.Denon.Source2() == 'CD' or sh.Musik.OG.Denon.Source2() == 'NET') and sh.Musik.OG.Denon.Power2()) else 0 + eval: 1 if ((sh.Denon.Source2() == 'DVD' or sh.Denon.Source2() == 'CD' or sh.Denon.Source2() == 'NET') and sh.Denon.Power2()) else 0 eval_trigger: - - Musik.OG.Denon.Source2 - - Musik.OG.Denon.Power2 + - Denon.Source2 + - Denon.Power2 Mute2: type: bool @@ -522,10 +522,10 @@ Denon: Musik: type: bool visu_acl: ro - eval: 1 if ((sh.Musik.OG.Denon.Source3() == 'DVD' or sh.Musik.OG.Denon.Source3() == 'CD' or sh.Musik.OG.Denon.Source3() == 'NET') and sh.Musik.OG.Denon.Power3()) else 0 + eval: 1 if ((sh.Denon.Source3() == 'DVD' or sh.Denon.Source3() == 'CD' or sh.Denon.Source3() == 'NET') and sh.Denon.Power3()) else 0 eval_trigger: - - Musik.OG.Denon.Source3 - - Musik.OG.Denon.Power3 + - Denon.Source3 + - Denon.Power3 Mute3: type: bool From c71a1fee913f6996bed75722d7c65e7fbc4458cb Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Tue, 28 Aug 2018 00:16:05 +0200 Subject: [PATCH 179/705] re-up denon avr1100 config --- avdevice/models/denon-avr1100.txt | 60 +++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100755 avdevice/models/denon-avr1100.txt diff --git a/avdevice/models/denon-avr1100.txt b/avdevice/models/denon-avr1100.txt new file mode 100755 index 000000000..ef2c90fc0 --- /dev/null +++ b/avdevice/models/denon-avr1100.txt @@ -0,0 +1,60 @@ +ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MINVALUE; MAXVALUE; RESPONSETYPE +0; power; on; PWON|PWON; PW?; PW**; RW +0; power; off; PWSTANDBY; PW?; PW*******; RW +0; eco; set; ECO*; ECO?; ECO*; RW; ; ; ; str|bool +1; power; on; ZMON; ZM?; ZM**; RW +1; power; off; ZMOFF; ZM?; ZM***; RW +1; mute; on; MUON; MU?; MU**; RW +1; mute; off; MUOFF; MU?; MU***; RW +1; sleep; set; SLP***; SLP?; SLP***; RW; ; 0; 120; num|bool +1; standby; set; STBY*; STBY?; STBY*; RW; ; ; ; str|bool +1; volume; set; MV**; MV?; MV**; RW; ; 30; 90 +1; volume+; increase; MVUP; ; MV; W +1; volume-; decrease; MVDOWN; ; MV; W +1; volumelow; ; MV50; MV?; MV50; W; ; ; ; num +1; volumehigh; ; MV75; MV?; MV75; W; ; ; ; num +1; volumemax; set; MVMAX **; MV?; MVMAX **|MVMAX ***; RW +1; input; set; SI*; SI?; SI*; RW; ; ; ; str +1; mode; set; MS*; MS?; MS*; RW; ; ; ; str +1; audioinput; set; SD*; SD?; SD*; RW; ; ; ; str +1; videoinput; set; SV*; SV?; SV*; RW; ; ; ; str|bool +1; tone; on; PSTONE CTRL ON; PSTONE CTRL ?; PSTONE CTRL **; RW +1; tone; off; PSTONE CTRL OFF; PSTONE CTRL ?; PSTONE CTRL ***; RW +1; bass; set; PSBAS **; PSBAS ?; PSBAS **; RW; ; 40; 60 +1; trebble; set; PSTRE **; PSTRE ?; PSTRE **; RW; ; 40; 60 +1; bass+; increase; PSBAS UP; ; PSBAS; W +1; bass-; decrease; PSBAS DOWN; ; PSBAS; W +1; trebble+; increase; PSTRE UP; ; PSTRE; W +1; trebble-; decrease; PSTRE DOWN; ; PSTRE; W +1; dialogtoggle; on; PSDIL ON; PSDIL ?; PSDIL **; RW +1; dialogtoggle; off; PSDIL OFF; PSDIL ?; PSDIL ***; RW +1; dialog; set; PSDIL **; PSDIL ?; PSDIL **; RW; ; 0; 62 +1; subwoofertoggle; on; PSSWL ON; PSSWL ?; PSSWL **; RW +1; subwoofertoggle; off; PSSWL OFF; PSSWL ?; PSSWL ***; RW +1; subwoofer; set; PSSWL **; PSSWL ?; PSSWL **; RW; ; 0; 62 +1; cinemaeq; on; PSCINEMA EQ.ON; PSCINEMA EQ. ?; PSCINEMA EQ.**; RW +1; cinemaeq; off; PSCINEMA EQ.OFF; PSCINEMA EQ. ?; PSCINEMA EQ.***; RW +2; power; on; Z2ON; Z2?; Z2**; RW +2; power; off; Z2OFF; Z2?; Z2***; RW +2; input; set; Z2*; Z2?; Z2*; RW; ; ; ; str +2; mute; on; Z2MUON; Z2MU?; Z2MU**; RW +2; mute; off; Z2MUOFF; Z2MU?; Z2MU***; RW +2; volume+; increase; Z2UP; ; Z2; W +2; volume-; decrease; Z2DOWN; ; Z2; W +2; volumelow; ; Z250; MV?; Z250; W; ; ; ; num +2; volumehigh; ; Z275; MV?; Z275; W; ; ; ; num +2; volume; set; Z2**; Z2?; Z2**; RW; ; 0; 90 +2; standby; set; Z2STBY*; Z2STBY?; Z2STBY*; RW; ; ; ; str|bool +2; sleep; set; Z2SLP***; Z2SLP?; Z2SLP***; RW; ; 0; 120; num|bool +3; power; on; Z3ON; Z3?; Z3**; RW +3; power; off; Z3OFF; Z3?; Z3***; RW +3; input; set; Z3*; Z3?; Z3*; RW; ; ; ; str +3; mute; on; Z3MUON; Z3MU?; Z3MU**; RW +3; mute; off; Z3MUOFF; Z3MU?; Z3MU***; RW +3; volume+; increase; Z3UP; ; Z3; W +3; volume-; decrease; Z3DOWN; ; Z3; W +3; volumelow; ; Z350; MV?; Z350; W; ; ; ; num +3; volumehigh; ; Z375; MV?; Z375; W; ; ; ; num +3; volume; set; Z3**; Z3?; Z3**; RW; ; 0; 90 +3; standby; set; Z3STBY*; Z3STBY?; Z3STBY*; RW; ; ; ; str|bool +3; sleep; set; Z3SLP***; Z3SLP?; Z3SLP***; RW; ; 0; 120; num|bool From edb5301467195f332aa94b8f7a2e32c22de2bd9b Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Tue, 28 Aug 2018 00:20:22 +0200 Subject: [PATCH 180/705] updated readme --- avdevice/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/avdevice/README.md b/avdevice/README.md index f03e13888..f6cfa1768 100755 --- a/avdevice/README.md +++ b/avdevice/README.md @@ -14,6 +14,12 @@ Tested with Pioneer (< 2016 models) and Denon AV receivers, Epson projector Oppo ## Changelog +### v1.5.0 +Minor code re-write using smartplugin methods and logging +added config file for Denon AVR1100 +fixed Denon example +added Web Interface + ### v1.3.6 Major code re-write using multiple modules and classes, minimizing complexity Extended "translate" functionality with wildcards From 040405d85f5cdf6633736cf431d47a1379349239 Mon Sep 17 00:00:00 2001 From: msinn Date: Tue, 28 Aug 2018 22:50:09 +0200 Subject: [PATCH 181/705] Metadata updates --- knx/plugin.yaml | 17 +---------------- visu_websocket/plugin.yaml | 2 +- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/knx/plugin.yaml b/knx/plugin.yaml index 54f3de72e..910755d55 100755 --- a/knx/plugin.yaml +++ b/knx/plugin.yaml @@ -217,22 +217,7 @@ item_attributes: en: 'Specify a group address to poll and the time interval in seconds for an automated query of KNX in form of a list. First entry is the group address, second entry is the poll interval in seconds. This may be used for actors or sensors that do no support a regular sending of values themselves.' -logic_trigger_attributes: - # Definition of logic trigger attributes defined by this plugin - knx_listen: - type: list(knx_ga) - description: - de: 'Gruppenadresse (oder Liste von Gruppenadressen), auf die gehört werden soll. KNX-Nachrichten an diese Gruppenadresse(n) ändern den Wert des Items' - en: "Group address (or list of goup addresses) to listen for. KNX messages to this group address will change the item's value" - - knx_reply: - type: list(knx_ga) - description: - de: 'Eine oder mehrere Gruppenadressen angeben, um den Objektwert vom KNX-Bus aus lesen zu können.' - en: 'Specify one or more group addresses to allow reading the item value from the KNX bus.' - - -logic_parameter: +logic_parameters: # Definition of logic parameters defined by this plugin knx_listen: type: list(knx_ga) diff --git a/visu_websocket/plugin.yaml b/visu_websocket/plugin.yaml index d52bbcda6..09b0c5307 100755 --- a/visu_websocket/plugin.yaml +++ b/visu_websocket/plugin.yaml @@ -96,7 +96,7 @@ item_attributes: de: 'Steuert den Zugriff auf das Item über Websocket Protokoll' en: 'Control access to this item through wbsocket protocol' -logic_parameter: +logic_parameters: # Definition of item attributes defined by this plugin visu_acl: type: bool From 259eba9501d0ae7567bd5dc642f449910538b8ce Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 29 Aug 2018 11:34:57 +0200 Subject: [PATCH 182/705] Backend: modified determination of plugin API for autocomplete --- backend/BackendPlugins.py | 38 +++++++------------------------------- 1 file changed, 7 insertions(+), 31 deletions(-) diff --git a/backend/BackendPlugins.py b/backend/BackendPlugins.py index b63a5c45d..309e6e6a0 100755 --- a/backend/BackendPlugins.py +++ b/backend/BackendPlugins.py @@ -132,34 +132,10 @@ def plugins_json(self): for x in self.plugins.return_plugins(): if isinstance(x, SmartPlugin): plugin_config_name = x.get_configname() - else: - plugin_config_name = x._configname - - #plugin_list.append(plugin_config_name) - - for func_name in inspect.getmembers(x, predicate=inspect.ismethod): - if self.get_class_that_defined_method(func_name[1]) is not None: - class_name = self.get_class_that_defined_method(func_name[1]).__name__ - if 'SmartPlugin' not in class_name and func_name[0] not in not_allowed_functions and not func_name[ - 0].startswith('_'): - plugin_list.append(plugin_config_name + "." + func_name[0]+str(inspect.signature(func_name[1]))) - - return json.dumps(plugin_list) - - def get_class_that_defined_method(self, meth): - if inspect.ismethod(meth): - for cls in inspect.getmro(meth.__self__.__class__): - if cls.__dict__.get(meth.__name__) is meth: - return cls - meth = meth.__func__ # fallback to __qualname__ parsing - if inspect.isfunction(meth): - - # Check to make sure the method has a "qualname" - if not getattr(meth, '__qualname__', None): - return None - - cls = getattr(inspect.getmodule(meth), - meth.__qualname__.split('.', 1)[0].rsplit('.', 1)[0]) - if isinstance(cls, type): - return cls - return None # not required since None would have been implicitly returned anyway + if x.metadata is not None: + api = x.metadata.get_plugin_function_defstrings(with_type=True, with_default=True) + if api is not None: + for function in api: + plugin_list.append(plugin_config_name + "." +function) + + return json.dumps(plugin_list) \ No newline at end of file From be0a264cd3074f3c01948e9a24b1b9fa08c98e0f Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 29 Aug 2018 12:19:05 +0200 Subject: [PATCH 183/705] Tankerkoenig: added API spec --- tankerkoenig/__init__.py | 2 +- tankerkoenig/plugin.yaml | 67 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/tankerkoenig/__init__.py b/tankerkoenig/__init__.py index d267c6fbc..82f9f093b 100755 --- a/tankerkoenig/__init__.py +++ b/tankerkoenig/__init__.py @@ -51,7 +51,7 @@ def run(self): def stop(self): self.alive = False - def get_petrol_stations(self, lat, lon, type='diesel', sort='price', rad='4'): + def get_petrol_stations(self, lat, lon, type='diesel', sort='price', rad=4): """ Returns a list of information for petrol stations around a specific location and radius Should not be used extensively, due to performance issues on tankerkoenig side. diff --git a/tankerkoenig/plugin.yaml b/tankerkoenig/plugin.yaml index d156abfe2..8d78b3887 100755 --- a/tankerkoenig/plugin.yaml +++ b/tankerkoenig/plugin.yaml @@ -28,4 +28,69 @@ parameters: item_attributes: # Definition of item attributes defined by this plugin - + +plugin_functions: + # Definition of function interface of the plugin + get_petrol_stations: + type: dict + description: + de: "Diese Funktion liefert ein DICT mit den Tankstellen im Umkreis." + en: "This function returns a DICT with petrol stations around a coordinate." + + parameters: + lat: + type: float + description: + de: "Breitengrad des Mittelpunkts der Anfrage." + en: "Latitude of center." + lon: + type: float + description: + de: "Längengrad des Mittelpunkts der Anfrage." + en: "Longitude of center." + + + type: + type: str + description: + de: "Typ des Benzins: 'e5', 'e10', 'diesel' oder 'all'." + en: "Type of fuel: 'e5', 'e10', 'diesel' or 'all'." + + sort: + type: str + description: + de: "Sortierreihenfolge der Ergebnisse, 'price' oder 'dist'." + en: "Sort order of results, 'price', or 'dist'." + + rad: + type: float + description: + de: "Suchradius in km, Max: 25" + en: "Search radius in km, max: 25" + + + get_petrol_station_detail: + type: dict + description: + de: "Diese Funktion gibt Details über eine Tankstelle als DICT mit folgenden Keys zurück: 'e5', 'e10', 'diesel', 'street', 'houseNumber', 'postCode', 'place', 'brand', 'id', 'lng', 'name', 'lat', 'isOpen'" + en: "This function returns details about a petrol station as DICT with keys: 'e5', 'e10', 'diesel', 'street', 'houseNumber', 'postCode', 'place', 'brand', 'id', 'lng', 'name', 'lat', 'isOpen'" + + parameters: + id: + type: str + description: + de: "UUID für die anzufragende Tankstelle." + en: "UUID for requested petrol station." + + get_petrol_station_prices: + type: dict + description: + de: "Gibt ein DICT mit Preisen für ein Array an Tankstellen-IDs zurück. Benutzung wird vom Tankerkoenig Team aus Performanzgründen empfeohlen!!!" + en: "Returns a list of prices for an array of petrol station ids. Recommended to be used by tankerkoenig team due to performance issues!!!" + + parameters: + ids: + type: list(str) + description: + de: "Array der Tankstellen IDs, für die Preise angefragt werden sollen." + en: "Array of petrol station IDs, for which prices shall be queried." \ No newline at end of file From dc1aa6005f9578d5dcf9e3aa79a5f807870e4964 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 29 Aug 2018 15:36:05 +0200 Subject: [PATCH 184/705] OLDInfo: added plugin functions --- odlinfo/plugin.yaml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/odlinfo/plugin.yaml b/odlinfo/plugin.yaml index 3be7a2f28..d0ca76dde 100755 --- a/odlinfo/plugin.yaml +++ b/odlinfo/plugin.yaml @@ -36,3 +36,30 @@ parameters: item_attributes: # Definition of item attributes defined by this plugin +plugin_functions: + + get_radiation_data_for_id: + type: dict + description: + de: "Gibt ein DICT mit Infos zur einer Messstation zurück. Keys: 'plz', 'kid', 'lon', 'lat', 'ort', 'hoehe', 'mw', 'status'." + en: "Returns a DICT with Infos of a measuring station. Keys: 'plz', 'kid', 'lon', 'lat', 'ort', 'hoehe', 'mw', 'status'." + + parameters: + odlinfo_id: + type: str + description: + de: "ID der Messstation. Siehe https://odlinfo.bfs.de." + en: "ID of measuring station. See https://odlinfo.bfs.de." + + get_radiation_data_for_ids: + type: list(dict) + description: + de: "Gibt ein Array von DICTs mit Infos zu Messstationen zurück. Keys: 'plz', 'kid', 'lon', 'lat', 'ort', 'hoehe', 'mw', 'status'." + en: "Returns an array of DICTs with Infos of measuring stations. Keys: 'plz', 'kid', 'lon', 'lat', 'ort', 'hoehe', 'mw', 'status'." + + parameters: + odlinfo_ids: + type: list(str) + description: + de: "Array der IDs der Messstationen. Siehe https://odlinfo.bfs.de." + en: "Array of IDs of measuring stations. See https://odlinfo.bfs.de." \ No newline at end of file From b0ce58a763d2559d681b1b121c5df52e79424c59 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 29 Aug 2018 16:04:57 +0200 Subject: [PATCH 185/705] Traffic Plugin: added api description --- traffic/plugin.yaml | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/traffic/plugin.yaml b/traffic/plugin.yaml index 483ac9fbc..d70c90f56 100755 --- a/traffic/plugin.yaml +++ b/traffic/plugin.yaml @@ -35,4 +35,43 @@ parameters: item_attributes: # Definition of item attributes defined by this plugin - + +plugin_functions: + + get_route_info: + type: dict + description: + de: 'Ermittelt Infos zu einer Fahrtroute via Google Directions.' + en: 'Returns information on a route via Google Directions.' + + parameters: + + origin: + type: str + description: + de: "Startpunkt der Route, kann eine Adresse, Geokoordinaten, etc. sein." + en: "Origin of your route, can be an address, geocoordinates, etc." + + destination: + type: str + description: + de: "Ziel der Route, kann eine Adresse, Geokoordinaten, etc. sein." + en: "Destination of your route, can be an address, geocoordinates, etc." + + alternatives: + type: bool + description: + de: "Rückgabe alternativer Routen. Default: False" + en: "Return alternative routes. Default: False." + + departure_time: + type: str + description: + de: "Spezifiziert die gewünschte Abfahrtszeit als Timestamp (Sekunden seit 1.1.1970 UTC). Alternativ kann 'now' für den aktuellen Zeitpunkt gesetzt werden. Default: 'now'." + en: "Specifies the desired time of departure. You can specify the time as an integer in seconds since midnight, January 1, 1970 UTC. Alternatively, you can specify a value of now, which sets the departure time to the current time (correct to the nearest second). Default: 'now'." + + mode: + type: str + description: + de: "Travel Mode, mögliche Werte 'driving', 'walking', 'bicycling', 'transit'. Default: 'driving'." + en: "Travel Mode, possible values 'driving', 'walking', 'bicycling', 'transit'. Default: 'driving'." \ No newline at end of file From f6149f07a0b13b1eefe4bc99ad023ef64b44783e Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 29 Aug 2018 16:32:20 +0200 Subject: [PATCH 186/705] MVG Live: added API spec --- mvg_live/plugin.yaml | 52 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/mvg_live/plugin.yaml b/mvg_live/plugin.yaml index 4a3884bc5..53e0a7446 100755 --- a/mvg_live/plugin.yaml +++ b/mvg_live/plugin.yaml @@ -22,4 +22,54 @@ parameters: item_attributes: # Definition of item attributes defined by this plugin - + +plugin_functions: + + get_station_departures: + type: list(dict) + description: + de: "Gibt ein Array von DICTs mit Infos Verkehrverbindungen der Münchner Verkehrsbetriebe (MVG) zurück. Keys: 'productsymbol', 'product', 'linesymbol', 'time', 'direction', 'linename', 'productsymbolurl', 'linesymbolurl', 'destination'." + en: "Returns an Array of DICTs with information on lines of the Münchner Verkehrsbetriebe (MVG). Keys: 'productsymbol', 'product', 'linesymbol', 'time', 'direction', 'linename', 'productsymbolurl', 'linesymbolurl', 'destination'." + + parameters: + station: + type: str + description: + de: "Name der Haltestelle. Schauen Sie auf der MVG live Webseite nach gültigen Namen." + en: "Name of the stop or station. Visit the MVG live web site to find valid names." + + timeoffset: + type: int + description: + de: "Keine Verbindungen in weniger als dieser Zeitdauer anzeigen. Sinnvoll, wenn man einige Minuten von der Haltstelle entfernt ist. Default: 0" + en: "Do not display connections departing sooner than this number of minutes. Useful if you are a couple of minutes away from the stop. Default: 0" + + entries: + type: int + description: + de: "Anzahl der Einträge, die geholt werden sollen. Default: 10" + en: "Number of entries to retrieve. Default: 10." + + ubahn: + type: bool + description: + de: "Falls 'False', keine U-Bahn Abfahrtzeiten anzeigen. Default: True." + en: "If 'False', do not display U-Bahn (subway) departures. Default: True." + + tram: + type: bool + description: + de: "Falls 'False', keine Tram Abfahrtzeiten anzeigen. Default: True." + en: "If 'False', do not display tram departures. Default: True." + + bus: + type: bool + description: + de: "Falls 'False', keine Bus Abfahrtzeiten anzeigen. Default: True." + en: "If 'False', do not display bus departures. Default: True." + + sbahn: + type: bool + description: + de: "Falls 'False', keine S-Bahn Abfahrtzeiten anzeigen. Default: True." + en: "If 'False', do not display S-Bahn (suburban train) departures. Default: True." From 844434bc05e762fab39c9f112aa52559e5c2ac49 Mon Sep 17 00:00:00 2001 From: pfischi Date: Wed, 29 Aug 2018 23:24:25 +0200 Subject: [PATCH 187/705] bugfix: coordinator is now set up correctly SoCo framework update v0.16 simplified streamtype detection updated version strings --- sonos/__init__.py | 34 +++++++++--------- sonos/plugin.yaml | 4 +-- sonos/soco/__init__.py | 2 +- sonos/soco/alarms.py | 10 ++++-- sonos/soco/cache.py | 4 ++- sonos/soco/config.py | 9 +++++ sonos/soco/core.py | 37 ++++++------------- sonos/soco/data_structures.py | 38 +++++++++++++++----- sonos/soco/data_structures_entry.py | 2 +- sonos/soco/events.py | 8 +++++ sonos/soco/exceptions.py | 3 ++ sonos/soco/groups.py | 3 ++ sonos/soco/ms_data_structures.py | 3 ++ sonos/soco/music_library.py | 19 ++++++++-- sonos/soco/music_services/accounts.py | 3 ++ sonos/soco/music_services/data_structures.py | 4 +++ sonos/soco/music_services/music_service.py | 3 ++ sonos/soco/plugins/__init__.py | 9 +++-- sonos/soco/services.py | 3 ++ sonos/soco/snapshot.py | 3 ++ sonos/soco/soap.py | 3 ++ sonos/soco/utils.py | 3 ++ 22 files changed, 142 insertions(+), 65 deletions(-) diff --git a/sonos/__init__.py b/sonos/__init__.py index 4d5477501..022271eb1 100755 --- a/sonos/__init__.py +++ b/sonos/__init__.py @@ -350,6 +350,7 @@ def soco(self, value): self.device_subscription ] self._is_coordinator = self._soco.is_coordinator + self.coordinator = self.soco.group.coordinator.uid.lower() self.uid = self.soco.uid.lower() self.household_id = self.soco.household_id @@ -562,6 +563,16 @@ def _av_transport_event(self, sub_handler: SubscriptionHandler) -> None: try: event = sub_handler.event.events.get(timeout=0.5) + # set streaming type + if self.soco.is_playing_line_in: + self.streamtype = "line_in" + elif self.soco.is_playing_tv: + self.streamtype = "tv" + elif self.soco.is_playing_radio: + self.streamtype = "radio" + else: + self.streamtype = "music" + if 'transport_state' in event.variables: transport_state = event.variables['transport_state'] if transport_state: @@ -1221,8 +1232,10 @@ def streamtype(self, streamtype: str) -> None: return self._streamtype = streamtype - for item in self.streamtype_items: - item(streamtype, 'Sonos') + if self.is_coordinator: + for member in self.zone_group_members: + for item in sonos_speaker[member].streamtype_items: + item(self.streamtype, 'Sonos') @property def track_uri(self) -> str: @@ -1250,27 +1263,13 @@ def track_uri(self, track_uri: str) -> None: return self._track_uri = track_uri - if re.match(r"^x-sonos-htastream:", self.track_uri) is not None: - streamtype = 'tv' - elif re.match(r"^x-rincon-stream:", self.track_uri) is not None: - streamtype = 'line-in' - elif re.match(r"^x-rincon-mp3radio:", self.track_uri) is not None: - streamtype = 'radio' - else: - # aac, wma etc possible for audio; everything except x- should be radio - if re.match(r'^x-', self.track_uri) is not None: - streamtype = 'music' - else: - streamtype = 'radio' # coordinator call / update all items if self.is_coordinator: for member in self.zone_group_members: - sonos_speaker[member].streamtype = streamtype for item in sonos_speaker[member].track_uri_items: item(self.track_uri, 'Sonos') # slave call, update just the slave else: - self.streamtype = streamtype for item in self.track_uri_items: item(self.track_uri, 'Sonos') @@ -2291,7 +2290,7 @@ def load_sonos_playlist(self, name: str, start: bool = False, clear_queue: bool class Sonos(SmartPlugin): ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.4.7" + PLUGIN_VERSION = "1.4.8" def __init__(self, sh, tts=False, local_webservice_path=None, local_webservice_path_snippet=None, discover_cycle="120", webservice_ip=None, webservice_port=23500, speaker_ips=None, snippet_duration_offset=0.0, **kwargs): @@ -2811,6 +2810,7 @@ def _discover(self) -> None: else: _initialize_speaker(uid, self._logger) + sonos_speaker[uid].soco = zone sonos_speaker[uid].is_initialized = True sonos_speaker[uid].refresh_static_properties() diff --git a/sonos/plugin.yaml b/sonos/plugin.yaml index 2c2d5e090..b1d1f4d11 100755 --- a/sonos/plugin.yaml +++ b/sonos/plugin.yaml @@ -11,8 +11,8 @@ plugin: documentation: https://github.com/smarthomeNG/plugins/tree/master/sonos # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/25151-sonos-anbindung - version: 1.4.7 # Plugin version - sh_minversion: 1.3 # minimum shNG version to use this plugin + version: 1.4.8 # Plugin version + sh_minversion: 1.5.1 # minimum shNG version to use this plugin multi_instance: False # plugin supports multi instance classname: Sonos # class containing the plugin diff --git a/sonos/soco/__init__.py b/sonos/soco/__init__.py index eceaf82af..1302d211c 100644 --- a/sonos/soco/__init__.py +++ b/sonos/soco/__init__.py @@ -19,7 +19,7 @@ __author__ = 'The SoCo-Team ' # Please add the suffix "+" to the version after release, to make it # possible infer whether in development code from the version string -__version__ = '0.14+' +__version__ = '0.16' __website__ = 'https://github.com/SoCo/SoCo' __license__ = 'MIT License' diff --git a/sonos/soco/alarms.py b/sonos/soco/alarms.py index 1e655307d..3350f8d9f 100644 --- a/sonos/soco/alarms.py +++ b/sonos/soco/alarms.py @@ -1,5 +1,8 @@ # -*- coding: utf-8 -*- +# Disable while we have Python 2.x compatability +# pylint: disable=useless-object-inheritance + """This module contains classes relating to Sonos Alarms.""" from __future__ import unicode_literals @@ -306,8 +309,11 @@ def get_alarms(zone=None): datetime.strptime(values['Duration'], "%H:%M:%S").time() instance.recurrence = values['Recurrence'] instance.enabled = values['Enabled'] == '1' - instance.zone = [z for z in zone.all_zones - if z.uid == values['RoomUUID']][0] + instance.zone = next((z for z in zone.all_zones + if z.uid == values['RoomUUID']), None) + # some alarms are not associated to zones -> filter these out + if instance.zone is None: + continue instance.program_uri = None if values['ProgramURI'] ==\ "x-rincon-buzzer:0" else values['ProgramURI'] instance.program_metadata = values['ProgramMetaData'] diff --git a/sonos/soco/cache.py b/sonos/soco/cache.py index 5ea9fd417..115c6d9f8 100644 --- a/sonos/soco/cache.py +++ b/sonos/soco/cache.py @@ -1,9 +1,11 @@ # -*- coding: utf-8 -*- -# pylint: disable=not-context-manager +# pylint: disable=not-context-manager,useless-object-inheritance # NOTE: The pylint not-content-manager warning is disabled pending the fix of # a bug in pylint: https://github.com/PyCQA/pylint/issues/782 +# NOTE: useless-object-inheritance needed for Python 2.x compatability + """This module contains the classes underlying SoCo's caching system.""" from __future__ import unicode_literals diff --git a/sonos/soco/config.py b/sonos/soco/config.py index 64ffc279e..d2b49be30 100644 --- a/sonos/soco/config.py +++ b/sonos/soco/config.py @@ -30,6 +30,15 @@ The :mod:`soco.cache` module. """ +EVENT_ADVERTISE_IP = None +"""The IP on which to advertise to Sonos. + +The default of None means that the relevant IP address will be detected +automatically. + +See also: + The :mod:`soco.events` module. +""" EVENT_LISTENER_IP = None """The IP on which the event listener listens. diff --git a/sonos/soco/core.py b/sonos/soco/core.py index d66cbcfb5..8d7cd5376 100755 --- a/sonos/soco/core.py +++ b/sonos/soco/core.py @@ -4,13 +4,14 @@ the main entry to the SoCo functionality """ -from __future__ import unicode_literals +from __future__ import absolute_import, unicode_literals import datetime import logging import re import socket from functools import wraps +from xml.sax.saxutils import escape import warnings import requests @@ -574,7 +575,9 @@ def play_uri(self, uri='', meta='', title='', start=True, 'metadata-1-0/">{service}' tunein_service = 'SA_RINCON65031_' # Radio stations need to have at least a title to play - meta = meta_template.format(title=title, service=tunein_service) + meta = meta_template.format( + title=escape(title), + service=tunein_service) # change uri prefix to force radio style display and commands if force_radio: @@ -1185,8 +1188,6 @@ def get_current_track_info(self): track['title'] = metadata.findtext('.//{http://purl.org/dc/' 'elements/1.1/}title') if not track['title']: - _LOG.warning('Could not handle track info: "%s"', - trackinfo) track['title'] = trackinfo # If the speaker is playing from the line-in source, querying for track @@ -1214,8 +1215,8 @@ def get_current_track_info(self): album_art_url = metadata.findtext( './/{urn:schemas-upnp-org:metadata-1-0/upnp/}albumArtURI') if album_art_url is not None: - track['album_art'] = self._build_album_art_full_uri( - album_art_url) + track['album_art'] = \ + self.music_library.build_album_art_full_uri(album_art_url) return track @@ -1344,7 +1345,7 @@ def get_queue(self, start=0, max_items=100, full_album_art_uri=False): for item in items: # Check if the album art URI should be fully qualified if full_album_art_uri: - self._update_album_art_to_full_uri(item) + self.music_library._update_album_art_to_full_uri(item) queue.append(item) # pylint: disable=star-args @@ -1532,7 +1533,7 @@ def __get_favorites(self, favorite_type, start=0, max_items=100): max_items (int): The total number of results to return. """ - if favorite_type != RADIO_SHOWS and favorite_type != RADIO_STATIONS: + if favorite_type not in (RADIO_SHOWS, RADIO_STATIONS): favorite_type = SONOS_FAVORITES response = self.contentDirectory.Browse([ @@ -1573,16 +1574,6 @@ def __get_favorites(self, favorite_type, start=0, max_items=100): return result - def _update_album_art_to_full_uri(self, item): - """Update an item's Album Art URI to be an absolute URI. - - Args: - item: The item to update the URI for - """ - if getattr(item, 'album_art_uri', False): - item.album_art_uri = self._build_album_art_full_uri( - item.album_art_uri) - def create_sonos_playlist(self, title): """Create a new empty Sonos playlist. @@ -1680,14 +1671,6 @@ def add_item_to_sonos_playlist(self, queueable_item, sonos_playlist): ('AddAtIndex', 4294967295) ]) - def get_item_album_art_uri(self, item): - """Get an item's Album Art absolute URI.""" - - if getattr(item, 'album_art_uri', False): - return self._build_album_art_full_uri(item.album_art_uri) - else: - return None - @only_on_master def set_sleep_timer(self, sleep_time_seconds): """Sets the sleep timer. @@ -1842,7 +1825,7 @@ def reorder_sonos_playlist(self, sonos_playlist, tracks, new_pos, # track_list = ','.join(track_list) # position_list = ','.join(position_list) if update_id == 0: # retrieve the update id for the object - response, _ = self._music_lib_search(object_id, 0, 1) + response, _ = self.music_library._music_lib_search(object_id, 0, 1) update_id = response['UpdateID'] change = 0 diff --git a/sonos/soco/data_structures.py b/sonos/soco/data_structures.py index e66376bc0..1abc8ba74 100755 --- a/sonos/soco/data_structures.py +++ b/sonos/soco/data_structures.py @@ -1,6 +1,9 @@ # -*- coding: utf-8 -*- # pylint: disable=star-args, too-many-arguments, fixme +# Disable while we have Python 2.x compatability +# pylint: disable=useless-object-inheritance,bad-mcs-classmethod-argument + """ This module contains classes for handling DIDL-Lite metadata. @@ -160,7 +163,7 @@ def _int_helper(name): try: return int(result) except ValueError: - raise ValueError( + raise DIDLMetadataError( 'Could not convert {0} to an integer'.format(name)) else: return None @@ -169,8 +172,8 @@ def _int_helper(name): # required content['protocol_info'] = element.get('protocolInfo') if content['protocol_info'] is None: - raise Exception('Could not create Resource from Element: ' - 'protocolInfo not found (required).') + raise DIDLMetadataError('Could not create Resource from Element: ' + 'protocolInfo not found (required).') # Optional content['import_uri'] = element.get('importUri') content['size'] = _int_helper('size') @@ -200,8 +203,9 @@ def to_element(self): ~xml.etree.ElementTree.Element: an Element. """ if not self.protocol_info: - raise Exception('Could not create Element for this resource: ' - 'protocolInfo not set (required).') + raise DIDLMetadataError('Could not create Element for this' + 'resource:' + 'protocolInfo not set (required).') root = XML.Element('res') # Required @@ -300,7 +304,7 @@ class DidlMetaClass(type): """Meta class for all Didl objects.""" - def __new__(mcs, name, bases, attrs): + def __new__(cls, name, bases, attrs): """Create a new instance. Args: @@ -308,7 +312,7 @@ def __new__(mcs, name, bases, attrs): bases (tuple): Base classes. attrs (dict): attributes defined for the class. """ - new_cls = super(DidlMetaClass, mcs).__new__(mcs, name, bases, attrs) + new_cls = super(DidlMetaClass, cls).__new__(cls, name, bases, attrs) # Register all subclasses with the global _DIDL_CLASS_TO_CLASS mapping item_class = attrs.get('item_class', None) if item_class is not None: @@ -764,6 +768,24 @@ class DidlMusicTrack(DidlAudioItem): ) +class DidlAudioBook(DidlAudioItem): + + """Class that represents an audio book.""" + + # the DIDL Lite class for this object. + item_class = 'object.item.audioItem.audioBook' + # name: (ns, tag) + _translation = DidlAudioItem._translation.copy() + _translation.update( + { + 'storageMedium': ('upnp', 'storageMedium'), + 'producer': ('upnp', 'producer'), + 'contributor': ('dc', 'contributor'), + 'date': ('dc', 'date'), + } + ) + + class DidlAudioBroadcast(DidlAudioItem): """Class that represents an audio broadcast.""" @@ -889,7 +911,7 @@ class DidlMusicAlbum(DidlAlbum): # name: (ns, tag) # pylint: disable=protected-access #: - _translation = DidlAudioItem._translation.copy() + _translation = DidlAlbum._translation.copy() _translation.update( { 'artist': ('upnp', 'artist'), diff --git a/sonos/soco/data_structures_entry.py b/sonos/soco/data_structures_entry.py index 70bf1b3aa..d20ec79af 100644 --- a/sonos/soco/data_structures_entry.py +++ b/sonos/soco/data_structures_entry.py @@ -50,7 +50,7 @@ def from_didl_string(string): except KeyError: raise DIDLMetadataError("Unknown UPnP class: %s" % item_class) item = cls.from_element(elt) - #item = attempt_datastructure_upgrade(item) + item = attempt_datastructure_upgrade(item) items.append(item) else: # elements are allowed as an immediate child of diff --git a/sonos/soco/events.py b/sonos/soco/events.py index 63e438a02..7692830e5 100755 --- a/sonos/soco/events.py +++ b/sonos/soco/events.py @@ -4,6 +4,10 @@ # NOTE: The pylint not-content-manager warning is disabled pending the fix of # a bug in pylint: https://github.com/PyCQA/pylint/issues/782 +# Disable while we have Python 2.x compatability +# pylint: disable=useless-object-inheritance + + """Classes to handle Sonos UPnP Events and Subscriptions.""" from __future__ import unicode_literals @@ -472,6 +476,10 @@ def run(self): # pylint: disable=unbalanced-tuple-unpacking ip_address, port = event_listener.address + + if config.EVENT_ADVERTISE_IP: + ip_address = config.EVENT_ADVERTISE_IP + headers = { 'Callback': ''.format(ip_address, port), 'NT': 'upnp:event' diff --git a/sonos/soco/exceptions.py b/sonos/soco/exceptions.py index bd67ca61f..385c09e5d 100755 --- a/sonos/soco/exceptions.py +++ b/sonos/soco/exceptions.py @@ -1,5 +1,8 @@ # -*- coding: utf-8 -*- +# Disable while we have Python 2.x compatability +# pylint: disable=useless-object-inheritance + """Exceptions that are used by SoCo.""" from __future__ import unicode_literals diff --git a/sonos/soco/groups.py b/sonos/soco/groups.py index 64b9342b8..05fca633e 100644 --- a/sonos/soco/groups.py +++ b/sonos/soco/groups.py @@ -1,5 +1,8 @@ # -*- coding: utf-8 -*- +# Disable while we have Python 2.x compatability +# pylint: disable=useless-object-inheritance + """This module contains classes and functionality relating to Sonos Groups.""" from __future__ import unicode_literals diff --git a/sonos/soco/ms_data_structures.py b/sonos/soco/ms_data_structures.py index 786a43bc9..a4d53e2c1 100644 --- a/sonos/soco/ms_data_structures.py +++ b/sonos/soco/ms_data_structures.py @@ -2,6 +2,9 @@ # pylint: disable = star-args, too-many-arguments, unsupported-membership-test # pylint: disable = not-an-iterable +# Disable while we have Python 2.x compatability +# pylint: disable=useless-object-inheritance + """This module contains all the data structures for music service plugins.""" # This needs to be integrated with Music Library data structures diff --git a/sonos/soco/music_library.py b/sonos/soco/music_library.py index 98679669d..e505521ff 100644 --- a/sonos/soco/music_library.py +++ b/sonos/soco/music_library.py @@ -1,5 +1,8 @@ # -*- coding: utf-8 -*- +# Disable while we have Python 2.x compatability +# pylint: disable=useless-object-inheritance + """Access to the Music Library. The Music Library is the collection of music stored on your local network. @@ -53,7 +56,7 @@ def __init__(self, soco=None): self.soco = soco if soco is not None else discovery.any_soco() self.contentDirectory = self.soco.contentDirectory - def _build_album_art_full_uri(self, url): + def build_album_art_full_uri(self, url): """Ensure an Album Art URI is an absolute URI. Args: @@ -68,6 +71,16 @@ def _build_album_art_full_uri(self, url): url = 'http://' + self.soco.ip_address + ':1400' + url return url + def _update_album_art_to_full_uri(self, item): + """Update an item's Album Art URI to be an absolute URI. + + Args: + item: The item to update the URI for + """ + if getattr(item, 'album_art_uri', False): + item.album_art_uri = self.build_album_art_full_uri( + item.album_art_uri) + def get_artists(self, *args, **kwargs): """Convenience method for `get_music_library_information` with ``search_type='artists'``. For details of other arguments, @@ -304,7 +317,7 @@ def get_music_library_information(self, search_type, start=0, for item in items: # Check if the album art URI should be fully qualified if full_album_art_uri: - self.soco._update_album_art_to_full_uri(item) + self._update_album_art_to_full_uri(item) # Append the item to the list item_list.append(item) @@ -378,7 +391,7 @@ def browse(self, ml_item=None, start=0, max_items=100, for container in containers: # Check if the album art URI should be fully qualified if full_album_art_uri: - self.soco._update_album_art_to_full_uri(container) + self._update_album_art_to_full_uri(container) item_list.append(container) # pylint: disable=star-args diff --git a/sonos/soco/music_services/accounts.py b/sonos/soco/music_services/accounts.py index c5150dd7b..be6072ea3 100644 --- a/sonos/soco/music_services/accounts.py +++ b/sonos/soco/music_services/accounts.py @@ -1,5 +1,8 @@ # -*- coding: utf-8 -*- +# Disable while we have Python 2.x compatability +# pylint: disable=useless-object-inheritance + """This module contains classes relating to Third Party music services.""" from __future__ import ( diff --git a/sonos/soco/music_services/data_structures.py b/sonos/soco/music_services/data_structures.py index c3c65a580..122859abc 100644 --- a/sonos/soco/music_services/data_structures.py +++ b/sonos/soco/music_services/data_structures.py @@ -1,4 +1,8 @@ # -*- coding: utf-8 -*- + +# Disable while we have Python 2.x compatability +# pylint: disable=useless-object-inheritance + """Data structures for music service items The basis for this implementation is this page in the Sonos API diff --git a/sonos/soco/music_services/music_service.py b/sonos/soco/music_services/music_service.py index 2654f0f89..bd7c0b186 100644 --- a/sonos/soco/music_services/music_service.py +++ b/sonos/soco/music_services/music_service.py @@ -1,6 +1,9 @@ # -*- coding: utf-8 -*- # pylint: disable=fixme +# Disable while we have Python 2.x compatability +# pylint: disable=useless-object-inheritance + """Sonos Music Services interface. This module provides the MusicService class and related functionality. diff --git a/sonos/soco/plugins/__init__.py b/sonos/soco/plugins/__init__.py index 1d43a79fa..84cfc9e50 100644 --- a/sonos/soco/plugins/__init__.py +++ b/sonos/soco/plugins/__init__.py @@ -1,6 +1,9 @@ # -*- coding: utf-8 -*- # pylint: disable=R0201,E0711 +# Disable while we have Python 2.x compatability +# pylint: disable=useless-object-inheritance + """This is the __init__ module for the plugins. It contains the base class for all plugins @@ -38,8 +41,8 @@ def from_name(cls, fullname, soco, *args, **kwargs): clsname = parts[-1] mod = importlib.import_module(modname) - cls = getattr(mod, clsname) + class_ = getattr(mod, clsname) - _LOG.info('Loaded class %s', cls) + _LOG.info('Loaded class %s', class_) - return cls(soco, *args, **kwargs) + return class_(soco, *args, **kwargs) diff --git a/sonos/soco/services.py b/sonos/soco/services.py index c056de28d..dec543091 100644 --- a/sonos/soco/services.py +++ b/sonos/soco/services.py @@ -1,6 +1,9 @@ # -*- coding: utf-8 -*- # pylint: disable=fixme, invalid-name +# Disable while we have Python 2.x compatability +# pylint: disable=useless-object-inheritance + """Classes representing Sonos UPnP services. >>> import soco diff --git a/sonos/soco/snapshot.py b/sonos/soco/snapshot.py index 2ac724b47..a4a35d2bd 100644 --- a/sonos/soco/snapshot.py +++ b/sonos/soco/snapshot.py @@ -1,6 +1,9 @@ # -*- coding: utf-8 -*- # pylint: disable=too-many-instance-attributes +# Disable while we have Python 2.x compatability +# pylint: disable=useless-object-inheritance + """Functionality to support saving and restoring the current Sonos state. This is useful for scenarios such as when you want to switch to radio diff --git a/sonos/soco/soap.py b/sonos/soco/soap.py index 21c5beec0..6c43f76fd 100644 --- a/sonos/soco/soap.py +++ b/sonos/soco/soap.py @@ -1,6 +1,9 @@ # -*- coding: utf-8 -*- # pylint: disable=fixme +# Disable while we have Python 2.x compatability +# pylint: disable=useless-object-inheritance + """Classes for handling SoCo's basic SOAP requirements. This module does not handle anything like the full `SOAP Specification diff --git a/sonos/soco/utils.py b/sonos/soco/utils.py index 9dd6534c3..af36226a4 100644 --- a/sonos/soco/utils.py +++ b/sonos/soco/utils.py @@ -1,5 +1,8 @@ # -*- coding: utf-8 -*- +# Disable while we have Python 2.x compatability +# pylint: disable=useless-object-inheritance + """This class contains utility functions used internally by SoCo.""" from __future__ import ( From 28d41f0fb1fd3e101a9839735a4997652f8fb9b3 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Thu, 30 Aug 2018 20:39:36 +0200 Subject: [PATCH 188/705] SML: debug log amount of bytes read from device --- sml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sml/__init__.py b/sml/__init__.py index de9c8047c..0c6014e41 100755 --- a/sml/__init__.py +++ b/sml/__init__.py @@ -208,7 +208,7 @@ def _parse(self, data): # Details see http://wiki.volkszaehler.org/software/sml values = {} packetsize = 7 - self.logger.debug('Data:{}'.format(''.join(' {:02x}'.format(x) for x in data))) + self.logger.debug('Data ({} bytes):{}'.format(len(data), ''.join(' {:02x}'.format(x) for x in data))) self._dataoffset = 0 while self._dataoffset < len(data)-packetsize: From 6b641e33fd3d3e18d103c128ac927f132d0be1a4 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Thu, 30 Aug 2018 20:41:48 +0200 Subject: [PATCH 189/705] SML: do verify packets read from device by checking CRC16 checksum See https://github.com/smarthomeNG/smarthome/issues/201 --- sml/__init__.py | 60 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/sml/__init__.py b/sml/__init__.py index 0c6014e41..5bceb1317 100755 --- a/sml/__init__.py +++ b/sml/__init__.py @@ -36,6 +36,8 @@ class Sml(SmartPlugin): ALLOW_MULTIINSTANCE = True PLUGIN_VERSION = '1.0.0' + _v1_start = b'\x1b\x1b\x1b\x1b\x01\x01\x01\x01' + _v1_end = b'\x1b\x1b\x1b\x1b\x1a' _units = { # Blue book @ http://www.dlms.com/documentation/overviewexcerptsofthedlmsuacolouredbooks/index.html 1 : 'a', 2 : 'mo', 3 : 'wk', 4 : 'd', 5 : 'h', 6 : 'min.', 7 : 's', 8 : '°', 9 : '°C', 10 : 'currency', 11 : 'm', 12 : 'm/s', 13 : 'm³', 14 : 'm³', 15 : 'm³/h', 16 : 'm³/h', 17 : 'm³/d', 18 : 'm³/d', 19 : 'l', 20 : 'kg', @@ -168,22 +170,32 @@ def _refresh(self): if self.connected: start = time.time() retry = 5 + data = None while retry > 0: try: data = self._read(512) if len(data) == 0: self.logger.error('Reading data from device returned 0 bytes!') + else: + end_pos = len(data) + while end_pos > 0: + end_pos = data.rfind(self._v1_end) + start_pos = data.rfind(self._v1_start, 0, end_pos) + if start_pos != -1 and end_pos == -1: + data = data[:start_pos] + elif start_pos != -1 and end_pos != -1: + chunk = data[start_pos:end_pos+len(self._v1_end)+3] + self.logger.debug('Found chunk at {} - {} ({} bytes):{}'.format(start_pos, end_pos, end_pos-start_pos, ''.join(' {:02x}'.format(x) for x in chunk))) + chunk_crc_str = '{:02X}{:02X}'.format(chunk[-2], chunk[-1]) + chunk_crc_calc = self._crc16(chunk[:-2]) + chunk_crc_calc_str = '{:02X}{:02X}'.format((chunk_crc >> 8) & 0xff, chunk_crc & 0xff) + if chunk_crc_str != chunk_crc_calc_str: + self.logger.warn('CRC checksum mismatch: Expected {}, but was {}'.format(chunk_crc_str, chunk_crc_calc_str)) + data = data[:start_pos] + else: + end_pos = 0 retry = 0 - values = self._parse(self._prepare(data)) - - for obis in values: - self.logger.debug('Entry {}'.format(values[obis])) - - if obis in self._items: - for prop in self._items[obis]: - for item in self._items[obis][prop]: - item(values[obis][prop], 'Sml') except Exception as e: self.logger.error('Reading data from {0} failed: {1} - reconnecting!'.format(self._target, e)) @@ -196,6 +208,17 @@ def _refresh(self): if retry == 0: self.logger.warn('Trying to read data in next cycle due to connection errors!') + if data is not None: + retry = 0 + values = self._parse(self._prepare(data)) + + for obis in values: + self.logger.debug('Entry {}'.format(values[obis])) + + if obis in self._items: + for prop in self._items[obis]: + for item in self._items[obis][prop]: + item(values[obis][prop], 'Sml') cycletime = time.time() - start self.logger.debug("cycle takes {0} seconds".format(cycletime)) @@ -308,3 +331,22 @@ def _prepareHex(self, data): data = data.encode() return bytes(''.join(chr(int(data[i:i+2], 16)) for i in range(0, len(data), 2)), "iso8859-1") + def _crc16(self, data): + crc = 0xffff + + p = 0; + while p < len(data): + c = 0xff & data[p] + p = p + 1 + + for i in range(0, 8): + if ((crc & 0x0001) ^ (c & 0x0001)): + crc = (crc >> 1) ^ 0x8408 + else: + crc = crc >> 1 + c = c >> 1 + + crc = ~crc & 0xffff + + return ((crc << 8) | ((crc >> 8) & 0xff)) & 0xffff + From ff0d0958e1f651100ea664276e0aad76cb6fb89a Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Thu, 30 Aug 2018 21:01:20 +0200 Subject: [PATCH 190/705] SML: Complete plugin metadata --- sml/plugin.yaml | 54 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/sml/plugin.yaml b/sml/plugin.yaml index ccc2c8d0a..80d6c73e4 100755 --- a/sml/plugin.yaml +++ b/sml/plugin.yaml @@ -4,11 +4,11 @@ plugin: type: interface # plugin type (gateway, interface, protocol, system, web) description: de: 'Auslesen von Stromzählern via SML-Protokoll' - en: '' + en: 'Read data from powermeter device using SML protocol' maintainer: ohinckel # tester: # Who tests this plugin? # keywords: iot xyz -# documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page + documentation: http://smarthomeng.de/user/plugins_doc/config/sml.html # support: https://knx-user-forum.de/forum/supportforen/smarthome-py version: 1.0.0 # Plugin version @@ -19,7 +19,53 @@ plugin: parameters: # Definition of parameters to be configured in etc/plugin.yaml - + serialport: + type: str + description: + de: 'Gibt die serielle Schnittstelle an von der die Daten gelesen werden (z.B. /dev/ttyUSB0)' + en: 'Specifies the serial device to read data from (e.g. /dev/ttyUSB0)' + host: + type: str + description: + de: '(optional) Alternativ zu "serialport" kann hier ein Netzwerk-Host hinterlegt werden' + en: '(optional) Alternatively you can specify a host instead of a serial device' + port: + type: int + description: + de: '(optional) Wenn ein "host" angegeben wurde kann hier der Port festgelegt werden' + en: '(optional) In case a "host" was specify this can be use to specify the port' + device: + type: str + default: 'raw' + valid_list: + - raw + - hex + - smart-meter-gateway-com-1 + description: + de: '(optional) Legt ein Gerät fest von dem die Daten ausgelesen werden' + en: '(optional) Specifies a device from which the data is read' + item_attributes: # Definition of item attributes defined by this plugin - + sml_obis: + type: str + description: + de: 'Gibt den OBIS-Code des Wertes an, das in das Item geschrieben werden soll' + en: 'Defines the OBIS code of the value to store in the item' + sml_prop: + type: str + default: valueReal + valid_list: + - objName + - status + - valTime + - unit + - scalar + - value + - signature + - obis + - valueReal + - unitName + description: + de: 'Gibt den Eigenschaftstyp an, der in das Item geschrieben werden soll' + en: 'Defines the property type to put into the item' From fb8921db3c342ef72ea30fd7083805b24b883304 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Thu, 29 Jun 2017 21:40:43 +0200 Subject: [PATCH 191/705] - fix some parsing problems in SML plugin: . do not break when trying to read entity from end of stream . unify error logging including data dump . always use builtin.len() instead of len() for binary-safty . make _refresh() return the values read from data stream - add tests for SML plugin --- sml/__init__.py | 39 ++++++++--- sml/tests/base.py | 81 +++++++++++++++++++++++ sml/tests/test_basic.py | 115 +++++++++++++++++++++++++++++++++ sml/tests/test_special_case.py | 31 +++++++++ 4 files changed, 257 insertions(+), 9 deletions(-) create mode 100644 sml/tests/base.py create mode 100644 sml/tests/test_basic.py create mode 100644 sml/tests/test_special_case.py diff --git a/sml/__init__.py b/sml/__init__.py index 5bceb1317..9a76143ce 100755 --- a/sml/__init__.py +++ b/sml/__init__.py @@ -28,6 +28,7 @@ import struct import socket import errno +import builtins from lib.model.smartplugin import SmartPlugin @@ -174,7 +175,7 @@ def _refresh(self): while retry > 0: try: data = self._read(512) - if len(data) == 0: + if builtins.len(data) == 0: self.logger.error('Reading data from device returned 0 bytes!') else: end_pos = len(data) @@ -219,10 +220,14 @@ def _refresh(self): for prop in self._items[obis]: for item in self._items[obis][prop]: item(values[obis][prop], 'Sml') + else: + values = {} cycletime = time.time() - start self.logger.debug("cycle takes {0} seconds".format(cycletime)) + return values + def _parse(self, data): # Search SML List Entry sequences like: # "77 07 81 81 c7 82 03 ff 01 01 01 01 04 xx xx xx xx" - manufactor @@ -233,7 +238,7 @@ def _parse(self, data): packetsize = 7 self.logger.debug('Data ({} bytes):{}'.format(len(data), ''.join(' {:02x}'.format(x) for x in data))) self._dataoffset = 0 - while self._dataoffset < len(data)-packetsize: + while self._dataoffset < builtins.len(data)-packetsize: # Find SML_ListEntry starting with 0x77 0x07 and OBIS code end with 0xFF if data[self._dataoffset] == 0x77 and data[self._dataoffset+1] == 0x07 and data[self._dataoffset+packetsize] == 0xff: @@ -257,22 +262,21 @@ def _parse(self, data): values[entry['obis']] = entry except Exception as e: - if self._dataoffset < len(data) - 1: - self.logger.warning('Can not parse entity at position {}, byte {}: {}:{}...'.format(self._dataoffset, self._dataoffset - packetstart, e, ''.join(' {:02x}'.format(x) for x in data[packetstart:packetstart+64]))) - self._dataoffset = packetstart + packetsize - 1 + self._parse_error('Can not parse entity: {}', [e], data, self._dataoffset, packetstart) + self._dataoffset = packetstart + packetsize - 1 else: self._dataoffset += 1 return values def _read_entity(self, data): - import builtins upack = { 5 : { 1 : '>b', 2 : '>h', 4 : '>i', 8 : '>q' }, # int 6 : { 1 : '>B', 2 : '>H', 4 : '>I', 8 : '>Q' } # uint } result = None + packetstart = self._dataoffset tlf = data[self._dataoffset] type = (tlf & 112) >> 4 @@ -291,9 +295,9 @@ def _read_entity(self, data): return result if self._dataoffset + len >= builtins.len(data): - raise Exception("Try to read {} bytes, but only have {}".format(len, builtins.len(data) - self._dataoffset)) + self._parse_error('Tried to read {} bytes, but only have {}', [len, builtins.len(data) - self._dataoffset], data, self._dataoffset, packetstart) - if type == 0: # octet string + elif type == 0: # octet string result = data[self._dataoffset:self._dataoffset+len] elif type == 5 or type == 6: # int or uint @@ -315,12 +319,29 @@ def _read_entity(self, data): return result else: - self.logger.warning('Skipping unkown field {}'.format(hex(tlf))) + self._parse_error('Skipping unkown field {}', [hex(tlf)], data, self._dataoffset, packetstart) self._dataoffset += len return result + def _parse_error(self, msg, msgargs, data, dataoffset, packetstart): + position = dataoffset - packetstart + databytes = '' + for i, b in enumerate(data[packetstart:packetstart+64]): + databytes = databytes + ' {}{:02x}{}'.format( + '' if i != position - 1 else '<', + b, + '' if i != position - 1 else '>' + ) + params = [] + params.extend(msgargs) + params.append(packetstart) + params.append(position) + params.append(databytes) + log = msg + " at position {}, byte {}:{}" + self.logger.warning(log.format(*params)) + def _prepareRaw(self, data): return data diff --git a/sml/tests/base.py b/sml/tests/base.py new file mode 100644 index 000000000..a4e1fa6a9 --- /dev/null +++ b/sml/tests/base.py @@ -0,0 +1,81 @@ +import re +import common +import unittest + +from plugins.sml import Sml +from tests.mock.core import MockSmartHome + +class SmlPacket: + + def __init__(self, data, type='string'): + self.data = bytearray() + self.add(data, type) + + def add(self, data, type='string'): + if type == 'string': + self.data.extend(map(ord, data)) + elif type == 'hex': + self.data = bytearray.fromhex(re.sub('[^0-9a-f]', '', data)) + elif type == 'byte': + self.data = data + else: + raise Exception("Type {} not supported by SmlPacket".format(type)) + + def get_data(self, start=None, length=None): + if start is None: + start = 0 + if length is None: + length = len(self.data) - start + return self.data[start:start+length] + + +class SmlPacketReader: + + def __init__(self): + self.packets = [] + self.packet = -1 + self.pos = 0 + self.buf = bytearray() + + def add(self, packet): + self.packets.append(packet) + + def read(self, length): + if length > len(self.buf): + self.buf = self.buf[self.pos:] + if self.packet < len(self.packets): + self.buf.extend(self.packets[self.packet].get_data()) + self.packet = self.packet + 1 + + if length > len(self.buf): + length = len(self.buf) + + data = self.buf[0:length] + self.buf = self.buf[length:] + + return data + + +class TestSmlBase(unittest.TestCase): + + def plugin(self): + self.sh = MockSmartHome() + plugin = Sml(self.sh) + plugin.connect() + plugin.data = SmlPacketReader() + plugin._serial = plugin.data + return plugin + + def assertEntry(self, values, obis, value, unit=None, unitname=None, status=None, scaler=None): + self.assertTrue(obis in values) + self.assertEqual( value, values[obis]['value']); + if unit is not None: + self.assertEqual( unit, values[obis]['unit']); + if unitname is not None: + self.assertEqual(unitname, values[obis]['unitName']); + if status is not None: + self.assertEqual( status, values[obis]['status']); + if scaler is not None: + self.assertEqual( scaler, values[obis]['scaler']); + + diff --git a/sml/tests/test_basic.py b/sml/tests/test_basic.py new file mode 100644 index 000000000..25a83169d --- /dev/null +++ b/sml/tests/test_basic.py @@ -0,0 +1,115 @@ +import common +import unittest + +from plugins.sml import Sml +from plugins.sml.tests.base import TestSmlBase, SmlPacket + +class TestSmlBasic(TestSmlBase): + + DEFAULT_PACKET1 = SmlPacket( + # Data from: EHZ363Z5 / EHZ363W5 + # Entry {'signature': None, 'unit': 30, 'status': None, 'obis': '1-0:2.8.1*255', 'valTime': None, 'objName': b'\x01\x00\x02\x08\x01\xff', 'unitName': 'Wh', 'scaler': -1, 'valueReal': 27445183.5, 'value': 274451835} + # Entry {'signature': None, 'unit': 30, 'status': 130, 'obis': '1-0:1.8.0*255', 'valTime': None, 'objName': b'\x01\x00\x01\x08\x00\xff', 'unitName': 'Wh', 'scaler': -1, 'valueReal': 7071245.300000001, 'value': 70712453} + # Entry {'signature': None, 'unit': 30, 'status': None, 'obis': '1-0:1.8.2*255', 'valTime': None, 'objName': b'\x01\x00\x01\x08\x02\xff', 'unitName': 'Wh', 'scaler': -1, 'valueReal': 1000.0, 'value': 10000} + # Entry {'signature': None, 'unit': None, 'status': None, 'obis': '129-129:199.130.5*255', 'valTime': None, 'objName': b'\x81\x81\xc7\x82\x05\xff', 'unitName': None, 'scaler': None, 'valueReal': b'\x00..\x00', 'value': b'\x00..\x00'} + # Entry {'signature': None, 'unit': 30, 'status': None, 'obis': '1-0:1.8.1*255', 'valTime': None, 'objName': b'\x01\x00\x01\x08\x01\xff', 'unitName': 'Wh', 'scaler': -1, 'valueReal': 7070245.300000001, 'value': 70702453} + # Entry {'signature': None, 'unit': None, 'status': None, 'obis': '129-129:199.130.3*255', 'valTime': None, 'objName': b'\x81\x81\xc7\x82\x03\xff', 'unitName': None, 'scaler': None, 'valueReal': b'HAG', 'value': b'HAG'} + # Entry {'signature': None, 'unit': 30, 'status': 130, 'obis': '1-0:2.8.0*255', 'valTime': None, 'objName': b'\x01\x00\x02\x08\x00\xff', 'unitName': 'Wh', 'scaler': -1, 'valueReal': 27446183.5, 'value': 274461835} + # Entry {'signature': None, 'unit': None, 'status': None, 'obis': '1-0:0.0.9*255', 'valTime': None, 'objName': b'\x01\x00\x00\x00\t\xff', 'unitName': None, 'scaler': None, 'valueReal': b'\x06HAG\x00..\x00', 'value': b'\x06HAG\x00..\x00'} + # Entry {'signature': None, 'unit': 27, 'status': None, 'obis': '1-0:16.7.0*255', 'valTime': None, 'objName': b'\x01\x00\x10\x07\x00\xff', 'unitName': 'W', 'scaler': 0, 'valueReal': 391, 'value': 391} + # Entry {'signature': None, 'unit': 30, 'status': None, 'obis': '1-0:2.8.2*255', 'valTime': None, 'objName': b'\x01\x00\x02\x08\x02\xff', 'unitName': 'Wh', 'scaler': -1, 'valueReal': 1000.0, 'value': 10000} + '1b 1b 1b 1b 01 01 01 01 76 09 00 00 00 00 0f 40 0f a9 62 01 62 00 72 63 01 01 ' + '76 01 01 09 00 00 00 00 05 15 5a 90 0b 00 48 41 47 00 00 00 00 00 00>01 01 63 ' + '23 14 00 76 09 00 00 00 00 0f 40 0f aa 62 01 62 00 72 63 07 01 77 01 0b 06 48 ' + '41 47 01 07 19 43 8c d4 07 01 00 62 0a ff ff 72 62 01 65 07 80 49 b9 7a 77 07 ' + '81 81 c7 82 03 ff 01 01 01 01 04 48 41 47 01 77 07 01 00 00 00 09 ff 01 01 01 ' + '01 0b 06 48 41 47 01 07 19 43 8c d4 01 77 07 01 00 01 08 00 ff 62 82 01 62 1e ' + '52 ff 55 04 36 fc 85 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 ff 55 04 36 d5 ' + '75 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 ff 53 27 10 01 77 07 01 00 02 08 ' + '00 ff 62 82 01 62 1e 52 ff 55 10 5b f4 8b 01 77 07 01 00 02 08 01 ff 01 01 62 ' + '1e 52 ff 55 10 5b cd 7b 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 ff 53 27 10 ' + '01 77 07 01 00 10 07 00 ff 01 01 62 1b 52 00 53 01 87 01 77 07 81 81 c7 82 05 ' + 'ff 01 01 01 01 83 02<00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ' + '00 00 00 00>01 01 63 4e ab 00 76 09 00 00 00 00 0f 40 0f ab 62 01 62 00 72 63 ' + '02 01 71 01 63 4e 4c 00 1b 1b 1b 1b 1a 00 18 6e', + 'hex' + ) + DEFAULT_PACKET2 = SmlPacket( + # Data from: EHZ363Z5 / EHZ363W5 + # Entry {'signature': None, 'unit': 30, 'status': 128, 'obis': '1-0:1.8.0*255', 'valTime': None, 'objName': b'\x01\x00\x01\x08\x00\xff', 'unitName': 'Wh', 'scaler': -1, 'valueReal': 18121741.400000002, 'value': 181217414} + # Entry {'signature': None, 'unit': 30, 'status': None, 'obis': '1-0:1.8.2*255', 'valTime': None, 'objName': b'\x01\x00\x01\x08\x02\xff', 'unitName': 'Wh', 'scaler': -1, 'valueReal': 1000.0, 'value': 10000} + # Entry {'signature': None, 'unit': None, 'status': None, 'obis': '129-129:199.130.5*255', 'valTime': None, 'objName': b'\x81\x81\xc7\x82\x05\xff', 'unitName': None, 'scaler': None, 'valueReal': b"\x00..\x00", 'value': b"\x00..\x00"} + # Entry {'signature': None, 'unit': 30, 'status': None, 'obis': '1-0:1.8.1*255', 'valTime': None, 'objName': b'\x01\x00\x01\x08\x01\xff', 'unitName': 'Wh', 'scaler': -1, 'valueReal': 18120741.400000002, 'value': 181207414} + # Entry {'signature': None, 'unit': None, 'status': None, 'obis': '129-129:199.130.3*255', 'valTime': None, 'objName': b'\x81\x81\xc7\x82\x03\xff', 'unitName': None, 'scaler': None, 'valueReal': b'HAG', 'value': b'HAG'} + # Entry {'signature': None, 'unit': None, 'status': None, 'obis': '1-0:0.0.9*255', 'valTime': None, 'objName': b'\x01\x00\x00\x00\t\xff', 'unitName': None, 'scaler': None, 'valueReal': b'\x06HAG\x00..\x00', 'value': b'\x06HAG\x00..\x00'} + # Entry {'signature': None, 'unit': 27, 'status': None, 'obis': '1-0:16.7.0*255', 'valTime': None, 'objName': b'\x01\x00\x10\x07\x00\xff', 'unitName': 'W', 'scaler': 0, 'valueReal': 8, 'value': 8} + '1b 1b 1b 1b 01 01 01 01 76 09 00 00 00 00 0d f2 9d b2 62 01 62 00 72 63 01 01 ' + '76 01 01 09 00 00 00 00 04 a6 34 92 0b 06 48 41 47<01 00 00 00 00>32 01 01 63 ' + 'f6 3c 00 76 09 00 00 00 00 0d f2 9d b3 62 01 62 00 72 63 07 01 77 01 0b 06 48 ' + '41 47 01 04 c5 37 5a 32 07 01 00 62 0a ff ff 72 62 01 65 08 f4 54 a4 77 77 07 ' + '81 81 c7 82 03 ff 01 01 01 01 04 48 41 47 01 77 07 01 00 00 00 09 ff 01 01 01 ' + '01 0b 06 48 41 47 01 04 c5 37 5a 32 01 77 07 01 00 01 08 00 ff 62 80 01 62 1e ' + '52 ff 55 0a cd 28 86 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 ff 55 0a cd 01 ' + '76 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 ff 53 27 10 01 77 07 01 00 10 07 ' + '00 ff 01 01 62 1b 52 00 53 00 08 01 77 07 81 81 c7 82 05 ff 01 01 01 01 83 02 ' + '<00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ' + '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00>01 01 63 ' + 'a1 b8 00 76 09 00 00 00 00 0d f2 9d b4 62 01 62 00 72 63 02 01 71 01 63 b8 47 ' + '00 00 00 00 1b 1b 1b 1b 1a 03 74 cd', + 'hex' + ) + DEFAULT_PACKET_MISSING_END = SmlPacket( + # Entity {'scaler': -4, 'unitName': 'Wh', 'objName': b'\x01\x00\x02\x08\x00\xff', 'status': None, 'obis': '1-0:2.8.0*255', 'value': 29803232821505, 'valTime': None, 'unit': 30, 'signature': None, 'valueReal': 2980323282.1505003} + # Entity {'scaler': -4, 'unitName': 'Wh', 'objName': b'\x01\x00\x01\x08\x00\xff', 'status': None, 'obis': '1-0:1.8.0*255', 'value': 64963419, 'valTime': None, 'unit': 30, 'signature': None, 'valueReal': 6496.3419} + # Entity {'scaler': None, 'unitName': None, 'objName': b'\x81\x81\xc7\x82\x03\xff', 'status': None, 'obis': '129-129:199.130.3*255', 'value': b'ESY', 'valTime': None, 'unit': None, 'signature': None, 'valueReal': b'ESY'}} + '1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 f7 62 00 62 00 72 65 00 00 01 01 76 01 ' + '01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 bf 6e 00 76 ' + '05 08 ca 78 f8 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 ' + 'f6 db 01 72 62 01 65 06 5a fc 21 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 ' + '53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b ' + '01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00', + 'hex' + ) + + def test_read_packet(self): + """ Test reading one complete package without data before or after. + """ + plugin = self.plugin() + plugin.data.add(TestSmlBasic.DEFAULT_PACKET1) + values = plugin._refresh() + self.assertEqual(10, len(values)) + self.assertEntry(values, '1-0:2.8.1*255', unit=30, unitname='Wh', value=274451835) + self.assertEntry(values, '1-0:1.8.0*255', unit=30, unitname='Wh', value=70712453) + self.assertEntry(values, '1-0:1.8.1*255', unit=30, unitname='Wh', value=70702453) + self.assertEntry(values, '1-0:1.8.2*255', unit=30, unitname='Wh', value=10000) + self.assertEntry(values, '129-129:199.130.3*255', value=b'HAG') + self.assertEntry(values, '1-0:16.7.0*255', unit=27, unitname='W', value=391) + self.assertEntry(values, '1-0:2.8.2*255', unit=30, unitname='Wh', value=10000) + + def test_read_packet_within_returns_last_values(self): + """ Test reading package including data before and after (both only a part + of a packet). In this case everything is tried to parse and in case a OBIS + value occurs multiple times in the stream, only the last one will be returned + """ + plugin = self.plugin() + plugin.data.add(SmlPacket(TestSmlBasic.DEFAULT_PACKET1.get_data(start=200), 'byte')) + plugin.data.add(TestSmlBasic.DEFAULT_PACKET1) + plugin.data.add(SmlPacket(TestSmlBasic.DEFAULT_PACKET2.get_data(length=200), 'byte')) + values = plugin._refresh() + self.assertEqual(10, len(values)) + self.assertEntry(values, '1-0:1.8.0*255', unit=30, unitname='Wh', value=181217414) + self.assertEntry(values, '1-0:1.8.1*255', unit=30, unitname='Wh', value=181207414) + self.assertEntry(values, '1-0:1.8.2*255', unit=30, unitname='Wh', value=10000) + self.assertEntry(values, '129-129:199.130.3*255', value=b'HAG') + self.assertEntry(values, '1-0:16.7.0*255', unit=27, unitname='W', value=391) + + def test_read_packet_missing_end(self): + plugin = self.plugin() + plugin.data.add(TestSmlBasic.DEFAULT_PACKET_MISSING_END) + values = plugin._refresh() + self.assertEqual(3, len(values)) + self.assertEntry(values, '1-0:2.8.0*255', unit=30, unitname='Wh', value=29803232821505, scaler=-4) + self.assertEntry(values, '1-0:1.8.0*255', unit=30, unitname='Wh', value=64963419, scaler=-4) + self.assertEntry(values, '129-129:199.130.3*255', value=b'ESY') + diff --git a/sml/tests/test_special_case.py b/sml/tests/test_special_case.py new file mode 100644 index 000000000..da9f456d2 --- /dev/null +++ b/sml/tests/test_special_case.py @@ -0,0 +1,31 @@ +import common +import unittest + +from plugins.sml import Sml +from plugins.sml.tests.base import TestSmlBase, SmlPacket + +class TestSmlEasymeter(TestSmlBase): + + def test_read_packet_knxuf_39119_629002(self): + """ Parse error reported by user: + https://knx-user-forum.de/forum/supportforen/smarthome-py/39119-sml-plugin-datenblock-gr%C3%B6%C3%9Fenfehler?p=629002#post629002 + """ + plugin = self.plugin() + plugin.data.add(SmlPacket( + '00 04 48 41 47 01 77 07 01 00 00 00 09 ff 01 01 01 01 0b 06 48 41 47 01 07 54 de c2 97 01 77 07 01 00 01 08 00 ff 62 82 01 62 1e 52 ff 55 00 f0 f2 07 01 77 07 01 00 01 08 01 ff 01 01 62 1e 00 52 ff 55 00 f0 ca f7 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 ff 53 27 10 01 77 07 01 00 10 07 00 ff 01 01 62 1b 52 00 53 00 ed 01 77 07 81 81 c7 82 05 ff 01 01 01 01 83 02 54 50 35 87 00 05 39 e5 1c d0 15 93 f7 c4 0d 5b b9 84 47 e1 9d 8d 1d 02 27 87 19 b9 19 dc f6 e3 c9 3e 6f 62 95 54 ca 19 2d 61 12 41 79 32 60 f0 b9 01 01 01 63 2b d4 00 76 09 00 00 00 00 02 2f a4 f1 62 00 01 62 00 72 63 02 01 71 01 63 1e 6e 00 00 00 00 1b 1b 1b 1b 1a 03 52 2b 1b 1b 1b 1b 01 01 01 01 76 09 00 00 00 00 02 2f a4 f3 62 01 62 00 72 63 01 01 76 01 01 09 00 00 00 00 00 ba 8c 51 00 0b 06 48 41 47 01 07 54 c2 97 01 77 07 01 00 01 08 00 ff 62 82 01 62 1e 52 ff 55 00 f0 f2 5d 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 ff 55 00 f0 cb 4d 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 ff 53 27 10 01 77 07 01 00 10 07 00 ff 01 01 62 1b 52 00 53 00 e8 01 77 07 81 81 c7 82 05 ff 01 01 01 01 83 02 54 50 35 87 05 39 e5 1c d0 15 93 f7 c4 0d 5b b9 84 47 e1 9d 8d 1d 02 27 87 19 b9 19 dc f6 e3 c9 3e 6f 62 95 54 ca 19 2d 61 12 41 79 32 60 f0 b9 01 01 01 63 2d 81 00 76 09 00 00 00 00 02 2f a5 f3 62 01 62 00 72 63 02 01 71 01 63 69 40 00 00 00 00 1b 1b 1b 1b 1a 03 b8 6d 1b 1b 1b 1b 01 01 01 01 76 09 00 00 00 00 02 2f a5 f5 62 01 62 00 72 63 01 01 76 01 01 09 00 00 00 00 00 ba 8c a7 0b 06 48 41 47 01 07 54 de c2 97 01 01 63 c9 dd 00 76 09 00 00 00 00 02 2f a5 f6 62 01 62 00 72 63 07 01 77 01 0b 06 48 41 47 01 07 54 de c2 97 07 01 00 62 0a ff ff 72 62 01 65 01 51 b4 7b 77 77 07 81 81 c7 82 03 ff 01 01 01 01 04 48 41 47 01 77 07 01 00 00 00 09 ff 01 01 01 01 0b 06 48 41 47 01 07 54 de c2 97 01 77 07 01 00 01 08 00 ff 62 82 01 62 1e 52 ff 55 00 f0 f2 5f 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 ff 55 00 f0 cb 4f 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 ff 53 27 10 01 77 07 01 00 10 07 00 ff 01 01 62 1b 52 00 53 00 e9 01 77 07 81 81 c7 82 05 ff 01 01 01 01 83 02 54 50 35 87 05 39 e5 1c d0 15 93 f7 c4 0d 5b b9 84 47 e1 9d 8d 1d 02 27 87 19 b9 19 dc f6 e3 c9 3e 6f 62 95 54 ca 19 2d 61 12 41 79 32 60 f0 b9 01 01 01 63 7c b6 00 76 09 00 00 00 00 02 2f a5 f9 62 01 62 00 72 63 02 01 71 01 63 e1 57 00 00 00 00 1b 1b 1b 1b 1a 03 d6 05 1b 1b 1b 1b 01 01 01 01 76 09 00 00 00 00 02 2f a5 fb 62 01 62 00 72 63 01 01 76 01 01 09 00 00 00 00 00 ba 8c a9 0b 06 48 41 47 01 07 54 de c2 97 01 01 63 d2 4e 00 76 09 00 00 00 00 02 2f a5 fc 62 01 62 00 72 63 07 01 77 01 0b 06 48 41 47 01 07 54 de c2 97 07 01 00 62 0a ff ff 72 62 01 65 01 51 b4 7e 77 77 07 81 81 c7 82 03 ff 01 01 01 01 04 48 41 47 01 77 07 01 00 00 00 09 ff 01 01 01 01 0b 06 48 41 47 01 07 54 de c2 97 01 77 07 01 00 01 08 00 ff 62 82 01 62 1e 52 ff 55 00 f0 f2 61 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 ff 55 00 f0 cb 51 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 ff 53 27 10 01 77 07 01 00 10 07 00 ff 01 01 62 1b 52 00 53 00 e8 01 77 07 81 81 c7 82 05 ff 01 01 01 01 83 02 54 50 35 87 05 39 e5 1c d0 15 93 f7 c4 0d 5b b9 84 47 e1 9d 8d 1d 02 27 87 19 b9 19 dc f6 e3 c9 3e 6f 62 95 54 ca 19 2d 61 12 41 79 32 60 f0 b9 01 01 01 63 03 c6 00 76 09 00 00 00 00 02 2f a5 ff 62 01 62 00 72 63 02 01 71 01 63 96 a2 00 00 00 00 1b 1b 1b 1b 1a 03 f5 29 1b 1b 1b 1b 01 01 01 01 76 09 00 00 00 00 02 2f a6 01 62 01 62 00 72 63 01 01 76 01 01 09 00 00 00 00 00 ba 8c ab 0b 06 48 41 47 01 07 54 de c2 97 01 01 63 9f b5 00 76 09 00 00 00 00 02 2f a6 02 62 01 62 00 72 63 07 01 77 01 0b 06 48 41 47 01 07 54 de c2 97 07 01 00 62 0a ff ff 72 62 01 65 01 51 b4 81 77 77 07 81 81 c7 82 03 ff 01 01 01 01 04 48 41 47 01 77 07 01 00 00 00 09 ff 01 01 01 01 0b 06 48 41 47 01 07 54 de c2 97 01 77 07 01 00 01 08 00 ff 62 82 01 62 1e 52 ff 55 00 f0 f2 63 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 ff 55 00 f0 cb 53 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 ff 53 27 10 01 77 07 01 00 10 07 00 ff 01 01 62 1b 52 00 53 00 e8 01 77 07 81 81 c7 82 05 ff 01 01 01 01 83 02 54 50 35 87 05 39 e5 1c d0 15 93 f7 c4 0d 5b b9 84 47 e1 9d 8d 1d 02 27 87 19 b9 19 dc f6 e3 c9 3e 6f 62 95 54 ca 19 2d 61 12 41 79 32 60 f0 b9 01 01 01 63 6c 5e 00 76 09 00 00 00 00 02 2f a6 05 62 01 62 00 72 63 02 01 71 01 63 21 fe 00 00 00 00 1b 1b 1b 1b 1a 03 f9 1f 1b 1b 1b 1b 01 01 01 01 76 09 00 00 00 00 02 2f a6 07 62 01 62 00 72 63 01 01 76 01 01 09 00 00 00 00 00 ba 8c ae 0b 06 48 41 47 01 07 54 de c2 97 01 01 63 13 d4 00 76 09 00 00 00 00 02 2f a6 0a 62 01 62 00 72 63 07 01 77 01 0b 06 48 41 47 01 07 54 de c2 97 07 01 00 62 0a ff ff 72 62 01 65 01 51 b4 84 77 77 07 81 81 c7 82 03 ff 01 01 01 01 04 48 41 47 01 77 07 01 00 00 00 09 ff 01 01 01 01 0b 06 48 41 47 01 07 54 de c2 97 01 77 07 01 00 01 08 00 ff 62 82 01 62 1e 52 ff 55 00 f0 f2 65 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 ff 55 00 f0 cb 55 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 ff 53 27 10 01 77 07 01 00 10 07 00 ff 01 01 62 1b 52 00 53 00 e7 01 77 07 81 81 c7 82 05 ff 01 01 01 01 83 02 54 50 35 87 05 39 e5 1c d0 15 93 f7 c4 0d 5b b9 84 47 e1 9d 8d 1d 02 27 87 19 b9 19 dc f6 e3 c9 3e 6f 62 95 54 ca 19 2d 61 12 41 79 32 60 f0 b9 01 01 01 63 e0 9d 00 76 09 00 00 00 00 02 2f a6 0b 62 01 62 00 72 63 02 01 71 01 63 fc b7 00 00 00 00 1b 1b 1b 1b 1a 03 4f 6a 1b 1b 1b 1b 01 01 01 01 76 09 00 00 00 00 02 2f a6 0d 62 01 62 00 72 63 01 01 76 01 01 09 00 00 00 00 00 ba 8c af 0b 06 48 41 47 01 07 54 de c2 97 01 01 63 89 97 00 76 09 00 00 00 00 02 2f a6 0e 62 01 62 00 72 63 07 01 77 01 0b 06 48 41 47 01 07 54 de c2 97 07 01 00 62 0a ff ff 72 62 01 65 01 51 b4 87 77 77 07 81 81 c7 82 03 ff 01 01 01 01 04 48 41 47 01 77 07 01 00 00 00 09 ff 01 01 01 01 0b 06 48 41 47 01 07 54 de c2 97 01 77 07 01 00 01 08 00 ff 62 82 01 62 1e 52 ff 55 00 f0 f2 67 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 ff 55 00 f0 cb 57 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 ff 53 27 10 01 77 07 01 00 10 07 00 ff 01 01 62 1b 52 00 53 00 e7 01 77 07 81 81 c7 82 05 ff 01 01 01 01 83 02 54 50 35 87 05 39 e5 1c d0 15 93 f7 c4 0d 5b b9 84 47 e1 9d 8d 1d 02 27 87 19 b9 19 dc f6 e3 c9 3e 6f 62 95 54 ca 19 2d 61 12 41 79 32 60 f0 b9 01 01 01 63 18 7c 00 76 09 00 00 00 00 02 2f a6 11 62 01 62 00 72 63 02 01 71 01 63 31 d1 00 00 00 00 1b 1b 1b 1b 1a 03 28 f4 1b 1b 1b 1b 01 01 01 01 76 09 00 00 00 00 02 2f a6 13 62 01 62 00 72 63 01 01 76 01 01 09 00 00 00 00 00 ba 8c b1 0b 06 48 41 47 01 07 54 de c2 97 01 01 63 c0 e7 00 76 09 00 00 00 00 02 2f a6 14 62 01 62 00 72 63 07 01 77 01 0b 06 48 41 47 01 07 54 de c2 97 07 01 00 62 0a ff ff 72 62 01 65 01 51 b4 8b 77 77 07 81 81 c7 82 03 ff 01 01 01 01 04 48 41 47 01 77 07 01 00 00 00 09 ff 01 01 01 01 0b 06 48 41 47 01 07 54 de c2 97 01 77 07 01 00 01 08 00 ff 62 82 01 62 1e 52 ff 55 00 f0 f2 69 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 ff 55 00 f0 cb 59 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 ff 53 27 10 01 77 07 01 00 10 07 00 ff 01 01 62 1b 52 00 53 00 e7 01 77 07 81 81 c7 82 05 ff 01 01 01 01 83 02 54 50 35 87 05 39 e5 1c d0 15 93 f7 c4 0d 5b b9 84 47 e1 9d 8d 1d 02 27 87 19 b9 19 dc f6 e3 c9 3e 6f 62 95 54 ca 19 2d 61 12 41 79 32 60 f0 b9 01 01 01 63 09 81 00 76 09 00 00 00 00 02 2f a6 17 62 01 62 00 72 63 02 01 71 01 63 46 24 00 00 00 00 1b 1b 1b 1b 1a 03 d0 fa 1b 1b 1b 1b 01 01 01 01 76 09 00 00 00 00 02 2f a6 19 62 01 62 00 72 63 01 01 76 01 01 09 00 00 00 00 00 ba 8c b3 0b 06 48 41 47 01 07 54 de c2 97 01 01 63 64 27 00 76 09 00 00 00 00 02 2f a6 1a 62 01 62 00 72 63 07 01 77 01 0b 06 48 41 47 01 07 54 de c2 97 07 01 00 62 0a ff ff 72 62 01 65 01 51 b4 8e 77 77 07 81 81 c7 82 03 ff 01 01 01 01 04 48 41 47 01 77 07 01 00 00 00 09 ff 01 01 01 01 0b 06 48 41 47 01 07 54 de c2 97 01 77 07 01 00 01 08 00 ff 62 82 01 62 1e 52 ff 55 00 f0 f2 6b 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 ff 55 00 f0 cb 5b 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 ff 53 27 10 01 77 07 01 00 10 07 00 ff 01 01 62 1b 52 00 53 00 e7 01 77 07 81 81 c7 82 05 ff 01 01 01 01 83 02 54 50 35 87 05 39 e5 1c d0 15 93 f7 c4 0d 5b b9 84 47 e1 9d 8d 1d 02 27 87 19 b9 19 dc f6 e3 c9 3e 6f 62 95 54 ca 19 2d 61 12 41 79 32 60 f0 b9 01 01 01 63 c5 20 00 76 09 00 00 00 00 02 2f a6 1d 62 01 62 00 72 63 02 01 71 01 63 ce 33 00 00 00 00 1b 1b 1b 1b 1a 03 82 89 1b 1b 1b 1b 01 01 01 01 76 09 00 00 00 00 02 2f a6 1f 62 01 62 00 72 63 01 01 76 01 01 09 00 00 00 00 00 ba 8c b5 0b 06 48 41 47 01 07 54 de c2 97 01 01 63 d6 c5 00 76 09 00 00 00 00 02 2f a6 20 62 01 62 00 72 63 07 01 77 01 0b 06 48 41 47 01 07 54 de c2 97 07 01 00 62 0a ff ff 72 62 01 65 01 51 b4 91 77 77 07 81 81 c7 82 03 ff 01 01 01 01 04 48 41 47 01 77 07 01 00 00 00 09 ff 01 01 01 01 0b 06 48 41 47 01 07 54 de c2 97 01 77 07 01 00 01 08 00 ff 62 82 01 62 1e 52 ff 55 00 f0 f2 6d 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 ff 55 00 f0 cb 5d 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 ff 53 27 10 01 77 07 01 00 10 07 00 ff 01 01 62 1b 52 00 53 00 e6 01 77 07 81 81 c7 82 05 ff 01 01 01 01 83 02 54 50 35 87 05 39 e5 1c d0 15 93 f7 c4 0d 5b b9 84 47 e1 9d 8d 1d 02 27 87 19 b9 19 dc f6 e3 c9 3e 6f 62 95 54 ca 19 2d 61 12 41 79 32 60 f0 b9 01 01 01 63 dd 2f 00 76 09 00 00 00 00 02 2f a6 23 62 01 62 00 72 63 02 01 71 01 63 dc e9 00 00 00 00 1b 1b 1b 1b 1a 03 ef 8b 1b 1b 1b 1b 01 01 01 01 76 09 00 00 00 00 02 2f a6 25 62 01 62 00 72 63 01 01 76 01 01 09 00 00 00 00 00 ba 8c b7 0b 06 48 41 47 01 07 54 de c2 97 01 01 63 fd 5b 00 76 09 00 00 00 00 02 2f a6 26 62 01 62 00 72 63 07 01 77 01 0b 06 48 41 47 01 07 54 de c2 97 07 01 00 62 0a ff ff 72 62 01 65 01 51 b4 94 77 77 07 81 81 c7 82 03 ff 01 01 01 01 04 48 41 47 01 77 07 01 00 00 00 09 ff 01 01 01 01 0b 06 48 41 47 01 07 54 de c2 97 01 77 07 01 00 01 08 00 ff 62 82 01 62 1e 52 ff 55 00 f0 f2 6f 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 ff 55 00 f0 cb 5f 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 ff 53 27 10 01 77 07 01 00 10 07 00 ff 01 01 62 1b 52 00 53 00 e7 01 77 07 81 81 c7 82 05 ff 01 01 01 01 83 02 54 50 35 87 05 39 e5 1c d0 15 93 f7 c4 0d 5b b9 84 47 e1 9d 8d 1d 02 27 87 19 b9 19 dc f6 e3 c9 3e 6f 62 95 54 ca 19 2d 61 12 41 79 32 60 f0 b9 01 01 01 63 34 e3 00 76 09 00 00 00 00 02 2f a6 29 62 01 62 00 72 63 02 01 71 01 63 54 fe 00 00 00 00 1b 1b 1b 1b 1a 03 96 bf 1b 1b 1b 1b 01 01 01 01 76 09 00 00 00 00 02 2f a6 2b 62 01 62 00 72 63 01 01 76 01 01 09 00 00 00 00 00 ba 8c b9 0b 06 48 41 47 01 07 54 de c2 97 01 01 63 e6 c8 00 76 09 00 00 00 00 02 2f a6 2c 62 01 62 00 72 63 07 01 77 01 0b 06 48 41 47 01 07 54 de c2 97 07 01 00 62 0a ff ff 72 62 01 65 01 51 b4 97 77 77 07 81 81 c7 82 03 ff 01 01 01 01 04 48 41 47 01 77 07 01 00 00 00 09 ff 01 01 01 01 0b 06 48 41 47 01 07 54 de c2 97 01 77 07 01 00 01 08 00 ff 62 82 01 62 1e 52 ff 55 00 f0 f2 71 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 ff 55 00 f0 cb 61 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 ff 53 27 10 01 77 07 01 00 10 07 00 ff 01 01 62 1b 52 00 53 00 e6 01 77 07 81 81 c7 82 05 ff 01 01 01 01 83 02 54 50 35 87 05 39 e5 1c d0 15 93 f7 c4 0d 5b b9 84 47 e1 9d 8d 1d 02 27 87 19 b9 19 dc f6 e3 c9 3e 6f 62 95 54 ca 19 2d 61 12 41 79 32 60 f0 b9 01 01 01 63 f5 47 00 76 09 00 00 00 00 02 2f a6 2f 62 01 62 00 72 63 02 01 71 01 63 23 0b 00 00 00 00 1b 1b 1b 1b 1a 03 a6 57 1b 1b 1b 1b 01 01 01 01 76 09 00 00 00 00 02 2f a6 31 62 01 62 00 72 63 01 01 76 01 01 09 00 00 00 00 00 ba 8c bb 0b 06 48 41 47 01 07 54 de c2 97 01 01 63 c7 3d 00 76 09 00 00 00 00 02 2f a6 34 62 01 62 00 72 63 07 01 77 01 0b 06 48 41 47 01 07 54 de c2 97 07 01 00 62 0a ff ff 72 62 01 65 01 51 b4 9a 77 77 07 81 81 c7 82 03 ff 01 01 01 01 04 48 41 47 01 77 07 01 00 00 00 09 ff 01 01 01 01 0b 06 48 41 47 01 07 54 de c2 97 01 77 07 01 00 01 08 00 ff 62 82 01 62 1e 52 ff 55 00 f0 f2 73 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 ff 55 00 f0 cb 63 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 ff 53 27 10 01 77 07 01 00 10 07 00 ff 01 01 62 1b 52 00 53 00 e7 01 77 07 81 81 c7 82 05 ff 01 01 01 01 83 02 54 50 35 87 05 39 e5 1c d0 15 93 f7 c4 0d 5b b9 84 47 e1 9d 8d 1d 02 27 87 19 b9 19 dc f6 e3 c9 3e 6f 62 95 54 ca 19 2d 61 12 41 79 32 60 f0 b9 01 01', + 'hex' + )) + values = plugin._refresh() + + def test_read_packet_github_201_283661510(self): + """ + Parse error reported by user: + https://github.com/smarthomeNG/smarthome/issues/201#issuecomment-283661510 + """ + plugin = self.plugin() + plugin.data.add(SmlPacket( + '1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 79 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 86 e8 00 76 05 08 ca 75 7a 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fa f7 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a3 27 e3 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe a1 13 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 8d 6b 00 76 05 08 ca 75 7b 62 00 62 00 72 65 00 00 02 01 71 01 63 ba 19 00 00 1b 1b 1b 1b 1a 01 0a 09 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 7f 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 59 04 00 76 05 08 ca 75 80 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fa f9 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a3 3b 7e 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 9e 7d 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 73 84 00 76 05 08 ca 75 81 62 00 62 00 72 65 00 00 02 01 71 01 63 0b 75 00 00 1b 1b 1b 1b 1a 01 3e b5 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 85 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 8b 15 00 76 05 08 ca 75 86 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fa fb 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a3 4f 39 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 9c 62 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 56 48 00 76 05 08 ca 75 87 62 00 62 00 72 65 00 00 02 01 71 01 63 e5 68 00 00 1b 1b 1b 1b 1a 01 4d a5 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 8b 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 9e 67 00 76 05 08 ca 75 8c 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fa fd 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a3 63 10 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 9a 43 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 cb c4 00 76 05 08 ca 75 8d 62 00 62 00 72 65 00 00 02 01 71 01 63 d7 4e 00 00 1b 1b 1b 1b 1a 01 ca 5f 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 91 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 6b 6f 00 76 05 08 ca 75 92 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fa ff 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a3 77 03 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 98 8f 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 98 05 00 76 05 08 ca 75 93 62 00 62 00 72 65 00 00 02 01 71 01 63 81 24 00 00 1b 1b 1b 1b 1a 01 ad 16 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 97 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 b4 83 00 76 05 08 ca 75 98 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 01 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a3 8b 0a 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 97 3c 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 6d 79 00 76 05 08 ca 75 99 62 00 62 00 72 65 00 00 02 01 71 01 63 b3 02 00 00 1b 1b 1b 1b 1a 01 20 ce 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 9d 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 c4 be 00 76 05 08 ca 75 9e 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 03 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a3 9f 20 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 96 03 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 a5 f1 00 76 05 08 ca 75 9f 62 00 62 00 72 65 00 00 02 01 71 01 63 5d 1f 00 00 1b 1b 1b 1b 1a 01 fe 86 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 a3 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 5e 92 00 76 05 08 ca 75 a4 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 05 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a3 b3 4f 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 94 34 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 35 7b 00 76 05 08 ca 75 a5 62 00 62 00 72 65 00 00 02 01 71 01 63 1f d6 00 00 1b 1b 1b 1b 1a 01 0e 04 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 a9 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 2e af 00 76 05 08 ca 75 aa 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 07 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a3 c7 97 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 92 a4 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 23 13 00 76 05 08 ca 75 ab 62 00 62 00 72 65 00 00 02 01 71 01 63 99 e6 00 00 1b 1b 1b 1b 1a 01 74 81 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 af 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 f1 43 00 76 05 08 ca 75 b0 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 09 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a3 db f0 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 91 67 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 1d 53 00 76 05 08 ca 75 b1 62 00 62 00 72 65 00 00 02 01 71 01 63 7b 9a 00 00 1b 1b 1b 1b 1a 01 aa e4 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 b5 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 04 4b 00 76 05 08 ca 75 b6 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 0b 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a3 f0 5c 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 90 05 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 2d a8 00 76 05 08 ca 75 b7 62 00 62 00 72 65 00 00 02 01 71 01 63 95 87 00 00 1b 1b 1b 1b 1a 01 23 38 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 bb 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 11 39 00 76 05 08 ca 75 bc 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 0d 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a4 04 e0 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 8e 6d 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 af 37 00 76 05 08 ca 75 bd 62 00 62 00 72 65 00 00 02 01 71 01 63 a7 a1 00 00 1b 1b 1b 1b 1a 01 a9 3c 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 c1 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 fa 8c 00 76 05 08 ca 75 c2 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 0f 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a4 19 75 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 8d 26 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 0b 0e 00 76 05 08 ca 75 c3 62 00 62 00 72 65 00 00 02 01 71 01 63 00 1d 00 00 1b 1b 1b 1b 1a 01 4d a9 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 c7 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 25 60 00 76 05 08 ca 75 c8 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 11 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a4 2e 21 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 8b 7a 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 8a 3e 00 76 05 08 ca 75 c9 62 00 62 00 72 65 00 00 02 01 71 01 63 32 3b 00 00 1b 1b 1b 1b 1a 01 de 21 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 cd 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 55 5d 00 76 05 08 ca 75 ce 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 13 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a4 42 e3 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 8a 19 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 ce ff 00 76 05 08 ca 75 cf 62 00 62 00 72 65 00 00 02 01 71 01 63 dc 26 00 00 1b 1b 1b 1b 1a 01 f8 ab 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 d3 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 c5 1a 00 76 05 08 ca 75 d4 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 15 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a4 57 b2 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 89 3a 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 93 01 00 76 05 08 ca 75 d5 62 00 62 00 72 65 00 00 02 01 71 01 63 3e 5a 00 00 1b 1b 1b 1b 1a 01 0f 3f 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 d9 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 b5 27 00 76 05 08 ca 75 da 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 17 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a4 6c 93 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 87 bb 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 98 d4 00 76 05 08 ca 75 db 62 00 62 00 72 65 00 00 02 01 71 01 63 b8 6a 00 00 1b 1b 1b 1b 1a 01 05 28 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 df 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 6a cb 00 76 05 08 ca 75 e0 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 19 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a4 81 8d 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 85 d8 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 ae 9f 00 76 05 08 ca 75 e1 62 00 62 00 72 65 00 00 02 01 71 01 63 fa a3 00 00 1b 1b 1b 1b 1a 01 d6 19 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 e5 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 95 a8 00 76 05 08 ca 75 e6 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 1b 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a4 96 a8 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 83 93 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 a1 96 00 76 05 08 ca 75 e7 62 00 62 00 72 65 00 00 02 01 71 01 63 14 be 00 00 1b 1b 1b 1b 1a 01 bf 37 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 eb 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 80 da 00 76 05 08 ca 75 ec 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 1d 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a4 ab e1 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5c 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 81 75 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 a1 4b 00 76 05 08 ca 75 ed 62 00 62 00 72 65 00 00 02 01 71 01 63 26 98 00 00 1b 1b 1b 1b 1a 01 dc 97 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 f1 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 75 d2 00 76 05 08 ca 75 f2 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 1f 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a4 c1 3d 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5d 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 7e fc 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 b7 cd 00 76 05 08 ca 75 f3 62 00 62 00 72 65 00 00 02 01 71 01 63 70 f2 00 00 1b 1b 1b 1b 1a 01 cf 65 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 f7 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 aa 3e 00 76 05 08 ca 75 f8 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 21 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a4 d6 b6 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5d 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 7d 0e 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 fc 04 00 76 05 08 ca 75 f9 62 00 62 00 72 65 00 00 02 01 71 01 63 42 d4 00 00 1b 1b 1b 1b 1a 01 b9 45 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 75 fd 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 da 03 00 76 05 08 ca 75 fe 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 23 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a4 ec 42 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5d 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 7b dd 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 d3 76 00 76 05 08 ca 75 ff 62 00 62 00 72 65 00 00 02 01 71 01 63 ac c9 00 00 1b 1b 1b 1b 1a 01 33 f0 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 03 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 26 4a 00 76 05 08 ca 76 04 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 25 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a5 01 e7 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5d 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 79 d9 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 bc 7b 00 76 05 08 ca 76 05 62 00 62 00 72 65 00 00 02 01 71 01 63 23 26 00 00 1b 1b 1b 1b 1a 01 19 b3 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 09 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 56 77 00 76 05 08 ca 76 0a 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 27 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a5 17 b1 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5d 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 77 17 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 fb 15 00 76 05 08 ca 76 0b 62 00 62 00 72 65 00 00 02 01 71 01 63 a5 16 00 00 1b 1b 1b 1b 1a 01 1b 74 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 0f 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 89 9b 00 76 05 08 ca 76 10 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 29 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a5 2d a2 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5d 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 74 66 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 0a 38 00 76 05 08 ca 76 11 62 00 62 00 72 65 00 00 02 01 71 01 63 47 6a 00 00 1b 1b 1b 1b 1a 01 6f 00 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 15 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 7c 93 00 76 05 08 ca 76 16 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 2b 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a5 43 b4 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5d 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 72 3d 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 c4 b4 00 76 05 08 ca 76 17 62 00 62 00 72 65 00 00 02 01 71 01 63 a9 77 00 00 1b 1b 1b 1b 1a 01 ab e9 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 1b 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 69 e1 00 76 05 08 ca 76 1c 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 2d 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a5 59 e4 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5d 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 70 42 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 c6 d1 00 76 05 08 ca 76 1d 62 00 62 00 72 65 00 00 02 01 71 01 63 9b 51 00 00 1b 1b 1b 1b 1a 01 a9 ed 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 21 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 96 82 00 76 05 08 ca 76 22 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 2f 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a5 70 2f 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5d 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 6e 05 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 55 bb 00 76 05 08 ca 76 23 62 00 62 00 72 65 00 00 02 01 71 01 63 6d 8e 00 00 1b 1b 1b 1b 1a 01 ec 20 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 27 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 49 6e 00 76 05 08 ca 76 28 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 31 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a5 86 a1 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5d 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 6b 5e 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 11 df 00 76 05 08 ca 76 29 62 00 62 00 72 65 00 00 02 01 71 01 63 5f a8 00 00 1b 1b 1b 1b 1a 01 10 e9 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 2d 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 39 53 00 76 05 08 ca 76 2e 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 33 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a5 9d 32 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5d 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 69 67 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 61 b7 00 76 05 08 ca 76 2f 62 00 62 00 72 65 00 00 02 01 71 01 63 b1 b5 00 00 1b 1b 1b 1b 1a 01 b9 02 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 33 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 a9 14 00 76 05 08 ca 76 34 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 35 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a5 b3 e0 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5d 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 67 2b 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 45 c7 00 76 05 08 ca 76 35 62 00 62 00 72 65 00 00 02 01 71 01 63 53 c9 00 00 1b 1b 1b 1b 1a 01 67 f8 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 39 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 d9 29 00 76 05 08 ca 76 3a 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 37 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a5 ca b0 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5d 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 64 b0 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 46 98 00 76 05 08 ca 76 3b 62 00 62 00 72 65 00 00 02 01 71 01 63 d5 f9 00 00 1b 1b 1b 1b 1a 01 c7 7f 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 3f 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 06 c5 00 76 05 08 ca 76 40 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 39 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a5 e1 a0 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5d 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 62 c4 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 89 d8 00 76 05 08 ca 76 41 62 00 62 00 72 65 00 00 02 01 71 01 63 c6 53 00 00 1b 1b 1b 1b 1a 01 f4 ec 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 45 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 ed 70 00 76 05 08 ca 76 46 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 3b 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a5 f8 a9 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5d 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 60 de 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 35 9b 00 76 05 08 ca 76 47 62 00 62 00 72 65 00 00 02 01 71 01 63 28 4e 00 00 1b 1b 1b 1b 1a 01 5e 62 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 4b 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 f8 02 00 76 05 08 ca 76 4c 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 3d 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a6 0f d4 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5d 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 5e 2f 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 98 01 00 76 05 08 ca 76 4d 62 00 62 00 72 65 00 00 02 01 71 01 63 1a 68 00 00 1b 1b 1b 1b 1a 01 a0 e8 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 51 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 0d 0a 00 76 05 08 ca 76 52 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 3f 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a6 27 28 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5d 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 5b 73 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 ba b8 00 76 05 08 ca 76 53 62 00 62 00 72 65 00 00 02 01 71 01 63 4c 02 00 00 1b 1b 1b 1b 1a 01 cb 45 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 57 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 d2 e6 00 76 05 08 ca 76 58 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 41 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a6 3e 9e 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5e 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 59 27 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 6e f6 00 76 05 08 ca 76 59 62 00 62 00 72 65 00 00 02 01 71 01 63 7e 24 00 00 1b 1b 1b 1b 1a 01 d1 90 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 5d 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 a2 db 00 76 05 08 ca 76 5e 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 43 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a6 56 2d 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5e 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 57 93 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 23 11 00 76 05 08 ca 76 5f 62 00 62 00 72 65 00 00 02 01 71 01 63 90 39 00 00 1b 1b 1b 1b 1a 01 9e d3 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 63 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 38 f7 00 76 05 08 ca 76 64 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 45 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a6 6d d2 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5e 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 55 fa 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 54 56 00 76 05 08 ca 76 65 62 00 62 00 72 65 00 00 02 01 71 01 63 d2 f0 00 00 1b 1b 1b 1b 1a 01 c6 2d 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 69 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 48 ca 00 76 05 08 ca 76 6a 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 47 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a6 85 8f 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5e 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 54 46 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 e2 db 00 76 05 08 ca 76 6b 62 00 62 00 72 65 00 00 02 01 71 01 63 54 c0 00 00 1b 1b 1b 1b 1a 01 dd b8 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 6f 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 97 26 00 76 05 08 ca 76 70 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 49 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a6 9d 64 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5e 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 52 b7 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 2d 1c 00 76 05 08 ca 76 71 62 00 62 00 72 65 00 00 02 01 71 01 63 b6 bc 00 00 1b 1b 1b 1b 1a 01 ab 52 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 75 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 62 2e 00 76 05 08 ca 76 76 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 4b 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a6 b5 46 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5e 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 51 e4 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 a7 c4 00 76 05 08 ca 76 77 62 00 62 00 72 65 00 00 02 01 71 01 63 58 a1 00 00 1b 1b 1b 1b 1a 01 2a 94 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 7b 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 77 5c 00 76 05 08 ca 76 7c 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 4d 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a6 cd 36 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5e 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 50 bb 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 51 3b 00 76 05 08 ca 76 7d 62 00 62 00 72 65 00 00 02 01 71 01 63 6a 87 00 00 1b 1b 1b 1b 1a 01 97 58 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 81 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 a5 4d 00 76 05 08 ca 76 82 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 4f 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a6 e5 3e 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5e 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 4f 1d 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 6e 92 00 76 05 08 ca 76 83 62 00 62 00 72 65 00 00 02 01 71 01 63 6f fd 00 00 1b 1b 1b 1b 1a 01 4d ed 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 87 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 7a a1 00 76 05 08 ca 76 88 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 51 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a6 fd 57 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5e 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 4d f4 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 91 70 00 76 05 08 ca 76 89 62 00 62 00 72 65 00 00 02 01 71 01 63 5d db 00 00 1b 1b 1b 1b 1a 01 c9 6f 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 8d 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 0a 9c 00 76 05 08 ca 76 8e 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 53 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a7 15 87 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5e 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 4c 1c 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 ef b9 00 76 05 08 ca 76 8f 62 00 62 00 72 65 00 00 02 01 71 01 63 b3 c6 00 00 1b 1b 1b 1b 1a 01 74 39 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 93 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 9a db 00 76 05 08 ca 76 94 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 55 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a7 2d d7 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5e 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 49 c6 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 18 b9 00 76 05 08 ca 76 95 62 00 62 00 72 65 00 00 02 01 71 01 63 51 ba 00 00 1b 1b 1b 1b 1a 01 2c 7a 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 99 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 ea e6 00 76 05 08 ca 76 9a 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 57 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a7 46 47 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5e 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 47 9b 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 aa 8b 00 76 05 08 ca 76 9b 62 00 62 00 72 65 00 00 02 01 71 01 63 d7 8a 00 00 1b 1b 1b 1b 1a 01 c1 fe 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 9f 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 35 0a 00 76 05 08 ca 76 a0 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 59 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a7 5e d0 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5e 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 45 fb 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 c0 34 00 76 05 08 ca 76 a1 62 00 62 00 72 65 00 00 02 01 71 01 63 95 43 00 00 1b 1b 1b 1b 1a 01 30 35 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 a5 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 ca 69 00 76 05 08 ca 76 a6 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 5b 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a7 77 7a 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5e 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 43 29 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 57 e8 00 76 05 08 ca 76 a7 62 00 62 00 72 65 00 00 02 01 71 01 63 7b 5e 00 00 1b 1b 1b 1b 1a 01 29 85 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 ab 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 df 1b 00 76 05 08 ca 76 ac 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 5d 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a7 90 62 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5e 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 3e b1 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 74 21 00 76 05 08 ca 76 ad 62 00 62 00 72 65 00 00 02 01 71 01 63 49 78 00 00 1b 1b 1b 1b 1a 01 ae 08 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 b1 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 2a 13 00 76 05 08 ca 76 b2 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 5f 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a7 a9 7c 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5e 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 3b 5b 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 96 2e 00 76 05 08 ca 76 b3 62 00 62 00 72 65 00 00 02 01 71 01 63 1f 12 00 00 1b 1b 1b 1b 1a 01 32 91 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 b7 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 f5 ff 00 76 05 08 ca 76 b8 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 61 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a7 c2 c6 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5f 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 37 db 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 d3 5f 00 76 05 08 ca 76 b9 62 00 62 00 72 65 00 00 02 01 71 01 63 2d 34 00 00 1b 1b 1b 1b 1a 01 38 79 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 bd 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 85 c2 00 76 05 08 ca 76 be 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 63 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a7 dc 47 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5f 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 33 f8 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 05 2d 00 76 05 08 ca 76 bf 62 00 62 00 72 65 00 00 02 01 71 01 63 c3 29 00 00 1b 1b 1b 1b 1a 01 79 02 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 c3 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 0b 38 00 76 05 08 ca 76 c4 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 65 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a7 f6 06 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5f 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 2f 62 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 62 11 00 76 05 08 ca 76 c5 62 00 62 00 72 65 00 00 02 01 71 01 63 d0 83 00 00 1b 1b 1b 1b 1a 01 92 b0 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 c9 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 7b 05 00 76 05 08 ca 76 ca 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 67 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a8 10 08 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5f 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 2a bb 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 ff 1d 00 76 05 08 ca 76 cb 62 00 62 00 72 65 00 00 02 01 71 01 63 56 b3 00 00 1b 1b 1b 1b 1a 01 68 58 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 cf 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 a4 e9 00 76 05 08 ca 76 d0 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 69 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a8 2a 4c 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5f 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 25 de 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 a9 f5 00 76 05 08 ca 76 d1 62 00 62 00 72 65 00 00 02 01 71 01 63 b4 cf 00 00 1b 1b 1b 1b 1a 01 cc 42 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 d5 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 51 e1 00 76 05 08 ca 76 d6 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 6b 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a8 44 d3 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5f 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 21 62 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 2f 4a 00 76 05 08 ca 76 d7 62 00 62 00 72 65 00 00 02 01 71 01 63 5a d2 00 00 1b 1b 1b 1b 1a 01 0a eb 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 db 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 44 93 00 76 05 08 ca 76 dc 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 6d 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a8 5f a3 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5f 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 1b dd 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 9b a4 00 76 05 08 ca 76 dd 62 00 62 00 72 65 00 00 02 01 71 01 63 68 f4 00 00 1b 1b 1b 1b 1a 01 a5 2e 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 e1 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 bb f0 00 76 05 08 ca 76 e2 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 6f 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a8 7a bd 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5f 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 16 cc 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 36 2d 00 76 05 08 ca 76 e3 62 00 62 00 72 65 00 00 02 01 71 01 63 9e 2b 00 00 1b 1b 1b 1b 1a 01 51 75 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 e7 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 64 1c 00 76 05 08 ca 76 e8 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 71 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a8 96 21 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5f 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 11 99 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 c7 e3 00 76 05 08 ca 76 e9 62 00 62 00 72 65 00 00 02 01 71 01 63 ac 0d 00 00 1b 1b 1b 1b 1a 01 e3 6d 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 ed 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 14 21 00 76 05 08 ca 76 ee 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 73 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a8 b1 d7 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5f 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 0b 68 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 0d eb 00 76 05 08 ca 76 ef 62 00 62 00 72 65 00 00 02 01 71 01 63 42 10 00 00 1b 1b 1b 1b 1a 01 d4 bd 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 f3 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 84 66 00 76 05 08 ca 76 f4 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 75 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a8 cd f0 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5f 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fe 04 a1 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 ea 4e 00 76 05 08 ca 76 f5 62 00 62 00 72 65 00 00 02 01 71 01 63 a0 6c 00 00 1b 1b 1b 1b 1a 01 de f0 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 f9 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 f4 5b 00 76 05 08 ca 76 fa 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 77 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a8 ea 64 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5f 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd fe 3c 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 42 62 00 76 05 08 ca 76 fb 62 00 62 00 72 65 00 00 02 01 71 01 63 26 5c 00 00 1b 1b 1b 1b 1a 01 f2 b0 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 76 ff 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 2b b7 00 76 05 08 ca 77 00 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 79 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a9 07 2c 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5f 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd f8 75 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 b1 cd 00 76 05 08 ca 77 01 62 00 62 00 72 65 00 00 02 01 71 01 63 7d 4e 00 00 1b 1b 1b 1b 1a 01 98 f7 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 05 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 c0 ab 00 76 05 08 ca 77 06 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 7b 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a9 24 48 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 5f 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd f2 79 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 a7 37 00 76 05 08 ca 77 07 62 00 62 00 72 65 00 00 02 01 71 01 63 93 53 00 00 1b 1b 1b 1b 1a 01 42 90 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 0b 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 d5 d9 00 76 05 08 ca 77 0c 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 7d 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a9 41 be 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 60 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd ec 29 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 06 a3 00 76 05 08 ca 77 0d 62 00 62 00 72 65 00 00 02 01 71 01 63 a1 75 00 00 1b 1b 1b 1b 1a 01 83 79 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 11 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 20 d1 00 76 05 08 ca 77 12 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 7f 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a9 5f 8e 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 60 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd e5 fc 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 c1 83 00 76 05 08 ca 77 13 62 00 62 00 72 65 00 00 02 01 71 01 63 f7 1f 00 00 1b 1b 1b 1b 1a 01 9e 9d 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 17 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 ff 3d 00 76 05 08 ca 77 18 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 81 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a9 7d a7 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 60 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd e1 0d 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 f7 b5 00 76 05 08 ca 77 19 62 00 62 00 72 65 00 00 02 01 71 01 63 c5 39 00 00 1b 1b 1b 1b 1a 01 83 c4 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 1d 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 8f 00 00 76 05 08 ca 77 1e 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 83 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a9 9c 02 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 60 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd dc 9f 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 83 88 00 76 05 08 ca 77 1f 62 00 62 00 72 65 00 00 02 01 71 01 63 2b 24 00 00 1b 1b 1b 1b 1a 01 a4 1a 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 23 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 15 2c 00 76 05 08 ca 77 24 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 85 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a9 ba 9f 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 60 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd d7 a4 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 79 7e 00 76 05 08 ca 77 25 62 00 62 00 72 65 00 00 02 01 71 01 63 69 ed 00 00 1b 1b 1b 1b 1a 01 1b 24 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 29 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 65 11 00 76 05 08 ca 77 2a 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 87 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a9 d9 86 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 60 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd d2 63 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 ff bf 00 76 05 08 ca 77 2b 62 00 62 00 72 65 00 00 02 01 71 01 63 ef dd 00 00 1b 1b 1b 1b 1a 01 87 95 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 2f 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 ba fd 00 76 05 08 ca 77 30 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 89 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 a9 f8 b0 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 60 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd ce 16 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 ec fa 00 76 05 08 ca 77 31 62 00 62 00 72 65 00 00 02 01 71 01 63 0d a1 00 00 1b 1b 1b 1b 1a 01 2f 10 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 35 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 4f f5 00 76 05 08 ca 77 36 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 8b 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 aa 18 0b 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 60 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd ca b9 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 8c a2 00 76 05 08 ca 77 37 62 00 62 00 72 65 00 00 02 01 71 01 63 e3 bc 00 00 1b 1b 1b 1b 1a 01 ae df 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 3b 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 5a 87 00 76 05 08 ca 77 3c 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 8d 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 aa 37 9a 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 60 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd c6 ec 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 69 de 00 76 05 08 ca 77 3d 62 00 62 00 72 65 00 00 02 01 71 01 63 d1 9a 00 00 1b 1b 1b 1b 1a 01 33 0a 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 41 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 b1 32 00 76 05 08 ca 77 42 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 8f 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 aa 57 5e 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 60 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd c3 66 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 a9 10 00 76 05 08 ca 77 43 62 00 62 00 72 65 00 00 02 01 71 01 63 76 26 00 00 1b 1b 1b 1b 1a 01 62 b3 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 47 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 6e de 00 76 05 08 ca 77 48 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 91 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 aa 77 4e 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 60 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd c0 3c 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 0a 20 00 76 05 08 ca 77 49 62 00 62 00 72 65 00 00 02 01 71 01 63 44 00 00 00 1b 1b 1b 1b 1a 01 b5 85 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 4d 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 1e e3 00 76 05 08 ca 77 4e 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 93 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 aa 97 6d 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 60 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bd 02 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 5a 25 00 76 05 08 ca 77 4f 62 00 62 00 72 65 00 00 02 01 71 01 63 aa 1d 00 00 1b 1b 1b 1b 1a 01 58 6b 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 53 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 8e a4 00 76 05 08 ca 77 54 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 95 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 aa b7 ab 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 60 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bb 3a 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 ba 62 00 76 05 08 ca 77 55 62 00 62 00 72 65 00 00 02 01 71 01 63 48 61 00 00 1b 1b 1b 1b 1a 01 c8 3d 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 59 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 fe 99 00 76 05 08 ca 77 5a 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 97 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 aa d8 09 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 61 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd b8 ab 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 e6 7e 00 76 05 08 ca 77 5b 62 00 62 00 72 65 00 00 02 01 71 01 63 ce 51 00 00 1b 1b 1b 1b 1a 01 5e 6e 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 5f 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 21 75 00 76 05 08 ca 77 60 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 99 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 aa f8 94 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 61 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd b5 81 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 c5 87 00 76 05 08 ca 77 61 62 00 62 00 72 65 00 00 02 01 71 01 63 8c 98 00 00 1b 1b 1b 1b 1a 01 90 c0 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 65 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 de 16 00 76 05 08 ca 77 66 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 9b 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ab 19 48 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 61 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd b2 a6 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 06 c6 00 76 05 08 ca 77 67 62 00 62 00 72 65 00 00 02 01 71 01 63 62 85 00 00 1b 1b 1b 1b 1a 01 ca 36 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 6b 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 cb 64 00 76 05 08 ca 77 6c 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 9d 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ab 3a 24 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 61 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd af c2 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 4e 4e 00 76 05 08 ca 77 6d 62 00 62 00 72 65 00 00 02 01 71 01 63 50 a3 00 00 1b 1b 1b 1b 1a 01 a7 67 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 71 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 3e 6c 00 76 05 08 ca 77 72 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb 9f 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ab 5b 25 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 61 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd ad 72 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 81 67 00 76 05 08 ca 77 73 62 00 62 00 72 65 00 00 02 01 71 01 63 06 c9 00 00 1b 1b 1b 1b 1a 01 10 3b 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 77 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 e1 80 00 76 05 08 ca 77 78 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb a1 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ab 7c 3c 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 61 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd ac 12 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 8d aa 00 76 05 08 ca 77 79 62 00 62 00 72 65 00 00 02 01 71 01 63 34 ef 00 00 1b 1b 1b 1b 1a 01 86 ef 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 7d 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 91 bd 00 76 05 08 ca 77 7e 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb a3 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ab 9d 67 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 61 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd aa 99 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 98 a1 00 76 05 08 ca 77 7f 62 00 62 00 72 65 00 00 02 01 71 01 63 da f2 00 00 1b 1b 1b 1b 1a 01 d1 4d 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 83 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 26 e3 00 76 05 08 ca 77 84 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb a5 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ab be ac 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 61 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd a8 7b 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 8b b9 00 76 05 08 ca 77 85 62 00 62 00 72 65 00 00 02 01 71 01 63 6b 9e 00 00 1b 1b 1b 1b 1a 01 16 62 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 89 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 56 de 00 76 05 08 ca 77 8a 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb a7 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ab e0 13 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 61 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd a6 37 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 36 c2 00 76 05 08 ca 77 8b 62 00 62 00 72 65 00 00 02 01 71 01 63 ed ae 00 00 1b 1b 1b 1b 1a 01 2b 24 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 8f 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 89 32 00 76 05 08 ca 77 90 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb a9 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ac 01 96 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 61 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd a4 61 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 c5 05 00 76 05 08 ca 77 91 62 00 62 00 72 65 00 00 02 01 71 01 63 0f d2 00 00 1b 1b 1b 1b 1a 01 25 1a 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 95 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 7c 3a 00 76 05 08 ca 77 96 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb ab 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ac 23 2d 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 61 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd a3 27 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 48 13 00 76 05 08 ca 77 97 62 00 62 00 72 65 00 00 02 01 71 01 63 e1 cf 00 00 1b 1b 1b 1b 1a 01 17 5f 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 9b 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 69 48 00 76 05 08 ca 77 9c 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb ad 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ac 44 ce 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 61 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd a2 93 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 65 bd 00 76 05 08 ca 77 9d 62 00 62 00 72 65 00 00 02 01 71 01 63 d3 e9 00 00 1b 1b 1b 1b 1a 01 d5 d3 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 a1 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 96 2b 00 76 05 08 ca 77 a2 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb af 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ac 66 71 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 62 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd a2 7c 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 18 2d 00 76 05 08 ca 77 a3 62 00 62 00 72 65 00 00 02 01 71 01 63 25 36 00 00 1b 1b 1b 1b 1a 01 dc 64 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 a7 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 49 c7 00 76 05 08 ca 77 a8 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb b1 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ac 88 15 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 62 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd a2 9a 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 29 4a 00 76 05 08 ca 77 a9 62 00 62 00 72 65 00 00 02 01 71 01 63 17 10 00 00 1b 1b 1b 1b 1a 01 36 88 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 ad 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 39 fa 00 76 05 08 ca 77 ae 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb b3 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ac a9 ac 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 62 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd a3 a5 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 ad 05 00 76 05 08 ca 77 af 62 00 62 00 72 65 00 00 02 01 71 01 63 f9 0d 00 00 1b 1b 1b 1b 1a 01 6f 0a 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 b3 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 a9 bd 00 76 05 08 ca 77 b4 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb b5 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ac cb 33 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 62 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd a4 d9 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 99 64 00 76 05 08 ca 77 b5 62 00 62 00 72 65 00 00 02 01 71 01 63 1b 71 00 00 1b 1b 1b 1b 1a 01 1f 57 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 b9 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 d9 80 00 76 05 08 ca 77 ba 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb b7 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ac ec a0 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 62 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd a6 c9 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 ce c9 00 76 05 08 ca 77 bb 62 00 62 00 72 65 00 00 02 01 71 01 63 9d 41 00 00 1b 1b 1b 1b 1a 01 43 2f 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 bf 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 06 6c 00 76 05 08 ca 77 c0 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb b9 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ad 0d e9 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 62 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd a9 bc 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 e3 4f 00 76 05 08 ca 77 c1 62 00 62 00 72 65 00 00 02 01 71 01 63 8e eb 00 00 1b 1b 1b 1b 1a 01 d3 4f 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 c5 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 ed d9 00 76 05 08 ca 77 c6 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb bb 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ad 2f 03 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 62 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd ac f3 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 75 0a 00 76 05 08 ca 77 c7 62 00 62 00 72 65 00 00 02 01 71 01 63 60 f6 00 00 1b 1b 1b 1b 1a 01 e3 7a 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 cb 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 f8 ab 00 76 05 08 ca 77 cc 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb bd 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ad 4f fc 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 62 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd ae b3 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 a1 48 00 76 05 08 ca 77 cd 62 00 62 00 72 65 00 00 02 01 71 01 63 52 d0 00 00 1b 1b 1b 1b 1a 01 55 a9 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 d1 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 0d a3 00 76 05 08 ca 77 d2 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb bf 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ad 70 e7 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 62 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd af d7 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 32 49 00 76 05 08 ca 77 d3 62 00 62 00 72 65 00 00 02 01 71 01 63 04 ba 00 00 1b 1b 1b 1b 1a 01 12 18 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 d7 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 d2 4f 00 76 05 08 ca 77 d8 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb c1 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ad 91 bb 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 62 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd b1 91 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 d3 7d 00 76 05 08 ca 77 d9 62 00 62 00 72 65 00 00 02 01 71 01 63 36 9c 00 00 1b 1b 1b 1b 1a 01 20 31 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 dd 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 a2 72 00 76 05 08 ca 77 de 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb c3 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ad b2 70 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 62 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd b3 e6 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 46 90 00 76 05 08 ca 77 df 62 00 62 00 72 65 00 00 02 01 71 01 63 d8 81 00 00 1b 1b 1b 1b 1a 01 bb 8d 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 e3 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 38 5e 00 76 05 08 ca 77 e4 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb c5 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ad d3 02 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 62 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd b6 75 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 dc 23 00 76 05 08 ca 77 e5 62 00 62 00 72 65 00 00 02 01 71 01 63 9a 48 00 00 1b 1b 1b 1b 1a 01 8e 5f 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 e9 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 48 63 00 76 05 08 ca 77 ea 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb c7 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ad f3 70 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 63 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd b8 ca 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 18 48 00 76 05 08 ca 77 eb 62 00 62 00 72 65 00 00 02 01 71 01 63 1c 78 00 00 1b 1b 1b 1b 1a 01 88 f3 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 ef 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 97 8f 00 76 05 08 ca 77 f0 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb c9 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ae 13 c1 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 63 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd ba b9 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 f9 23 00 76 05 08 ca 77 f1 62 00 62 00 72 65 00 00 02 01 71 01 63 fe 04 00 00 1b 1b 1b 1b 1a 01 65 a5 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 f5 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 62 87 00 76 05 08 ca 77 f6 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb cb 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ae 33 fb 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 63 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bc 5f 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 bf d3 00 76 05 08 ca 77 f7 62 00 62 00 72 65 00 00 02 01 71 01 63 10 19 00 00 1b 1b 1b 1b 1a 01 1c bf 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 77 fb 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 77 f5 00 76 05 08 ca 77 fc 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb cd 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ae 54 20 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 63 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bd a7 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 19 2e 00 76 05 08 ca 77 fd 62 00 62 00 72 65 00 00 02 01 71 01 63 22 3f 00 00 1b 1b 1b 1b 1a 01 a2 df 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 01 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 c2 ae 00 76 05 08 ca 78 02 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb cf 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ae 74 38 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 63 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd be 95 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 43 33 00 76 05 08 ca 78 03 62 00 62 00 72 65 00 00 02 01 71 01 63 c3 da 00 00 1b 1b 1b 1b 1a 01 59 4d 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 07 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 1d 42 00 76 05 08 ca 78 08 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb d1 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ae 94 42 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 63 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bf 99 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 af 22 00 76 05 08 ca 78 09 62 00 62 00 72 65 00 00 02 01 71 01 63 f1 fc 00 00 1b 1b 1b 1b 1a 01 ed af 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 0d 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 6d 7f 00 76 05 08 ca 78 0e 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb d3 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ae b4 3c 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 63 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd c0 89 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 91 d0 00 76 05 08 ca 78 0f 62 00 62 00 72 65 00 00 02 01 71 01 63 1f e1 00 00 1b 1b 1b 1b 1a 01 ae b3 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 13 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 fd 38 00 76 05 08 ca 78 14 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb d5 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ae d4 33 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 63 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd c0 ac 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 13 26 00 76 05 08 ca 78 15 62 00 62 00 72 65 00 00 02 01 71 01 63 fd 9d 00 00 1b 1b 1b 1b 1a 01 37 31 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 19 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 8d 05 00 76 05 08 ca 78 1a 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb d7 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 ae f4 30 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 63 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd c0 06 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 04 24 00 76 05 08 ca 78 1b 62 00 62 00 72 65 00 00 02 01 71 01 63 7b ad 00 00 1b 1b 1b 1b 1a 01 df 51 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 1f 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 52 e9 00 76 05 08 ca 78 20 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb d9 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 af 14 3c 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 63 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd be d3 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 7c c6 00 76 05 08 ca 78 21 62 00 62 00 72 65 00 00 02 01 71 01 63 39 64 00 00 1b 1b 1b 1b 1a 01 60 cf 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 25 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 ad 8a 00 76 05 08 ca 78 26 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb db 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 af 34 55 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 63 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd be 1f 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 4f 33 00 76 05 08 ca 78 27 62 00 62 00 72 65 00 00 02 01 71 01 63 d7 79 00 00 1b 1b 1b 1b 1a 01 15 d9 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 2b 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 b8 f8 00 76 05 08 ca 78 2c 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb dd 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 af 54 75 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 63 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bd ab 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 2e d4 00 76 05 08 ca 78 2d 62 00 62 00 72 65 00 00 02 01 71 01 63 e5 5f 00 00 1b 1b 1b 1b 1a 01 99 66 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 31 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 4d f0 00 76 05 08 ca 78 32 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb df 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 af 74 92 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 64 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd be 19 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 5f bc 00 76 05 08 ca 78 33 62 00 62 00 72 65 00 00 02 01 71 01 63 b3 35 00 00 1b 1b 1b 1b 1a 01 54 94 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 37 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 92 1c 00 76 05 08 ca 78 38 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb e1 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 af 94 b0 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 64 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bd a9 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 df fe 00 76 05 08 ca 78 39 62 00 62 00 72 65 00 00 02 01 71 01 63 81 13 00 00 1b 1b 1b 1b 1a 01 6b 3e 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 3d 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 e2 21 00 76 05 08 ca 78 3e 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb e3 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 af b4 e3 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 64 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bc 0b 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 83 3b 00 76 05 08 ca 78 3f 62 00 62 00 72 65 00 00 02 01 71 01 63 6f 0e 00 00 1b 1b 1b 1b 1a 01 0d b5 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 43 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 6c db 00 76 05 08 ca 78 44 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb e5 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 af d5 20 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 64 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bb d2 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 46 67 00 76 05 08 ca 78 45 62 00 62 00 72 65 00 00 02 01 71 01 63 7c a4 00 00 1b 1b 1b 1b 1a 01 42 e4 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 49 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 1c e6 00 76 05 08 ca 78 4a 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb e7 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 af f5 54 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 64 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bc 5a 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 0e 4a 00 76 05 08 ca 78 4b 62 00 62 00 72 65 00 00 02 01 71 01 63 fa 94 00 00 1b 1b 1b 1b 1a 01 c8 37 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 4f 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 c3 0a 00 76 05 08 ca 78 50 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb e9 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b0 15 87 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 64 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bc 75 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 dd 24 00 76 05 08 ca 78 51 62 00 62 00 72 65 00 00 02 01 71 01 63 18 e8 00 00 1b 1b 1b 1b 1a 01 6e dc 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 55 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 36 02 00 76 05 08 ca 78 56 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb eb 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b0 35 b7 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 64 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bc bb 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 5b 12 00 76 05 08 ca 78 57 62 00 62 00 72 65 00 00 02 01 71 01 63 f6 f5 00 00 1b 1b 1b 1b 1a 01 f0 8b 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 5b 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 23 70 00 76 05 08 ca 78 5c 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb ed 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b0 55 e7 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 64 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bc 88 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 73 50 00 76 05 08 ca 78 5d 62 00 62 00 72 65 00 00 02 01 71 01 63 c4 d3 00 00 1b 1b 1b 1b 1a 01 88 7d 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 61 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 dc 13 00 76 05 08 ca 78 62 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb ef 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b0 76 1c 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 64 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bc 2a 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 2d f6 00 76 05 08 ca 78 63 62 00 62 00 72 65 00 00 02 01 71 01 63 32 0c 00 00 1b 1b 1b 1b 1a 01 6e 70 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 67 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 03 ff 00 76 05 08 ca 78 68 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb f1 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b0 96 55 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 64 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bb ef 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 09 94 00 76 05 08 ca 78 69 62 00 62 00 72 65 00 00 02 01 71 01 63 00 2a 00 00 1b 1b 1b 1b 1a 01 8e 74 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 6d 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 73 c2 00 76 05 08 ca 78 6e 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb f3 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b0 b6 8f 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 64 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bc 0d 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 ea 4d 00 76 05 08 ca 78 6f 62 00 62 00 72 65 00 00 02 01 71 01 63 ee 37 00 00 1b 1b 1b 1b 1a 01 fc 35 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 73 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 e3 85 00 76 05 08 ca 78 74 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb f5 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b0 d6 bd 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 64 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bc e4 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 4d e7 00 76 05 08 ca 78 75 62 00 62 00 72 65 00 00 02 01 71 01 63 0c 4b 00 00 1b 1b 1b 1b 1a 01 1f 6d 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 79 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 93 b8 00 76 05 08 ca 78 7a 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb f7 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b0 f6 e8 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 65 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bd 0f 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 9d 4b 00 76 05 08 ca 78 7b 62 00 62 00 72 65 00 00 02 01 71 01 63 8a 7b 00 00 1b 1b 1b 1b 1a 01 39 7b 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 7f 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 4c 54 00 76 05 08 ca 78 80 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb f9 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b1 17 0e 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 65 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bd 76 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 10 03 00 76 05 08 ca 78 81 62 00 62 00 72 65 00 00 02 01 71 01 63 3b 17 00 00 1b 1b 1b 1b 1a 01 3a 84 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 85 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 9e 45 00 76 05 08 ca 78 86 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb fb 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b1 37 2a 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 65 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd be 44 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 08 d6 00 76 05 08 ca 78 87 62 00 62 00 72 65 00 00 02 01 71 01 63 d5 0a 00 00 1b 1b 1b 1b 1a 01 58 02 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 8b 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 8b 37 00 76 05 08 ca 78 8c 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb fd 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b1 57 39 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 65 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd bf 23 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 c7 7e 00 76 05 08 ca 78 8d 62 00 62 00 72 65 00 00 02 01 71 01 63 e7 2c 00 00 1b 1b 1b 1b 1a 01 af 74 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 91 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 7e 3f 00 76 05 08 ca 78 92 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fb ff 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b1 77 33 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 65 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd c0 dc 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 e5 cb 00 76 05 08 ca 78 93 62 00 62 00 72 65 00 00 02 01 71 01 63 b1 46 00 00 1b 1b 1b 1b 1a 01 5b ba 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 97 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 a1 d3 00 76 05 08 ca 78 98 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fc 01 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b1 97 17 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 65 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd c2 52 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 bd 4d 00 76 05 08 ca 78 99 62 00 62 00 72 65 00 00 02 01 71 01 63 83 60 00 00 1b 1b 1b 1b 1a 01 04 e9 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 9d 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 d1 ee 00 76 05 08 ca 78 9e 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fc 03 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b1 b6 e0 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 65 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd c4 7e 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 a9 ae 00 76 05 08 ca 78 9f 62 00 62 00 72 65 00 00 02 01 71 01 63 6d 7d 00 00 1b 1b 1b 1b 1a 01 97 34 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 a3 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 4b c2 00 76 05 08 ca 78 a4 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fc 05 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b1 d6 8b 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 65 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd c6 68 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 41 3c 00 76 05 08 ca 78 a5 62 00 62 00 72 65 00 00 02 01 71 01 63 2f b4 00 00 1b 1b 1b 1b 1a 01 b8 d1 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 a9 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 3b ff 00 76 05 08 ca 78 aa 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fc 07 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b1 f6 27 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 65 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd c7 32 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 59 c3 00 76 05 08 ca 78 ab 62 00 62 00 72 65 00 00 02 01 71 01 63 a9 84 00 00 1b 1b 1b 1b 1a 01 7c da 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 af 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 e4 13 00 76 05 08 ca 78 b0 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fc 09 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b2 15 b1 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 65 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd c8 b7 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 b1 af 00 76 05 08 ca 78 b1 62 00 62 00 72 65 00 00 02 01 71 01 63 4b f8 00 00 1b 1b 1b 1b 1a 01 18 0c 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 b5 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 11 1b 00 76 05 08 ca 78 b6 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fc 0b 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b2 35 1e 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 65 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd ca eb 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 27 19 00 76 05 08 ca 78 b7 62 00 62 00 72 65 00 00 02 01 71 01 63 a5 e5 00 00 1b 1b 1b 1b 1a 01 4e c5 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 bb 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 04 69 00 76 05 08 ca 78 bc 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fc 0d 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b2 54 66 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 65 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd cd 9d 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 03 7e 00 76 05 08 ca 78 bd 62 00 62 00 72 65 00 00 02 01 71 01 63 97 c3 00 00 1b 1b 1b 1b 1a 01 b1 cf 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 c1 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 ef dc 00 76 05 08 ca 78 c2 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fc 0f 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b2 73 86 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 66 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd d0 70 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 6d 8a 00 76 05 08 ca 78 c3 62 00 62 00 72 65 00 00 02 01 71 01 63 30 7f 00 00 1b 1b 1b 1b 1a 01 a7 ad 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 c7 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 30 30 00 76 05 08 ca 78 c8 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fc 11 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b2 92 7e 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 66 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd d3 42 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 a1 32 00 76 05 08 ca 78 c9 62 00 62 00 72 65 00 00 02 01 71 01 63 02 59 00 00 1b 1b 1b 1b 1a 01 bb 9a 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 cd 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 40 0d 00 76 05 08 ca 78 ce 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fc 13 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b2 b1 56 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 66 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd d5 31 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 bc a5 00 76 05 08 ca 78 cf 62 00 62 00 72 65 00 00 02 01 71 01 63 ec 44 00 00 1b 1b 1b 1b 1a 01 5a 60 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 d3 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 d0 4a 00 76 05 08 ca 78 d4 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fc 15 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b2 d0 1c 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 66 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd d6 6b 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 31 61 00 76 05 08 ca 78 d5 62 00 62 00 72 65 00 00 02 01 71 01 63 0e 38 00 00 1b 1b 1b 1b 1a 01 0d 3d 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 d9 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 a0 77 00 76 05 08 ca 78 da 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fc 17 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b2 ee cd 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 66 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd d8 1b 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 24 8c 00 76 05 08 ca 78 db 62 00 62 00 72 65 00 00 02 01 71 01 63 88 08 00 00 1b 1b 1b 1b 1a 01 b3 7c 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 df 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 7f 9b 00 76 05 08 ca 78 e0 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fc 19 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b3 0d 68 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 66 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd d9 4e 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 ce c6 00 76 05 08 ca 78 e1 62 00 62 00 72 65 00 00 02 01 71 01 63 ca c1 00 00 1b 1b 1b 1b 1a 01 be 0a 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 e5 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 80 f8 00 76 05 08 ca 78 e6 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fc 1b 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b3 2b f6 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 66 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd da 3c 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 34 07 00 76 05 08 ca 78 e7 62 00 62 00 72 65 00 00 02 01 71 01 63 24 dc 00 00 1b 1b 1b 1b 1a 01 72 35 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 eb 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 95 8a 00 76 05 08 ca 78 ec 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fc 1d 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b3 4a 78 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 66 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd db 25 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 54 fa 00 76 05 08 ca 78 ed 62 00 62 00 72 65 00 00 02 01 71 01 63 16 fa 00 00 1b 1b 1b 1b 1a 01 7c 16 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 f1 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 60 82 00 76 05 08 ca 78 f2 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fc 1f 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 57 b6 b3 68 f8 01 77 07 01 00 01 08 01 ff 01 01 62 1e 52 01 65 00 00 02 04 01 77 07 01 00 01 08 02 ff 01 01 62 1e 52 01 65 00 00 00 85 01 77 07 01 00 02 08 01 ff 01 01 62 1e 52 01 65 00 39 7b 66 01 77 07 01 00 02 08 02 ff 01 01 62 1e 52 01 65 00 00 00 83 01 77 07 01 00 01 07 00 ff 01 01 62 1b 52 fe 55 ff fd da d5 01 77 07 01 00 60 05 05 ff 01 01 01 01 63 01 a0 01 01 01 63 2b 42 00 76 05 08 ca 78 f3 62 00 62 00 72 65 00 00 02 01 71 01 63 40 90 00 00 1b 1b 1b 1b 1a 01 e3 92 1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 f7 62 00 62 00 72 65 00 00 01 01 76 01 01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 bf 6e 00 76 05 08 ca 78 f8 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 f6 db 01 72 62 01 65 06 5a fc 21 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b 01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00', + 'hex' + )) + values = plugin._refresh() + From 27e37b33ed78a4b7a3ce880f343ebc36134150f3 Mon Sep 17 00:00:00 2001 From: msinn Date: Thu, 30 Aug 2018 21:42:21 +0200 Subject: [PATCH 192/705] Metadata update --- mvg_live/plugin.yaml | 6 ++++-- odlinfo/plugin.yaml | 4 +++- tankerkoenig/plugin.yaml | 4 +++- traffic/plugin.yaml | 10 +++++++--- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/mvg_live/plugin.yaml b/mvg_live/plugin.yaml index 53e0a7446..ade4fe9f2 100755 --- a/mvg_live/plugin.yaml +++ b/mvg_live/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Retrieval of departure times of stations within the Münchner Verkehrsbetriebe (MVG)' maintainer: psilo909 # tester: # Who tests this plugin? + state: ready keywords: public transport, departure times, Munich, München documentation: http://smarthomeng.de/user/plugins_doc/config/mvg_live.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1108867-neues-plugin-mvg_live @@ -15,12 +16,13 @@ plugin: sh_minversion: 1.5 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance + restartable: unknown classname: MVG_Live # class containing the plugin -parameters: +parameters: NONE # Definition of parameters to be configured in etc/plugin.yaml -item_attributes: +item_attributes: NONE # Definition of item attributes defined by this plugin plugin_functions: diff --git a/odlinfo/plugin.yaml b/odlinfo/plugin.yaml index d0ca76dde..1ca981f96 100755 --- a/odlinfo/plugin.yaml +++ b/odlinfo/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'This plugin retrieves the Gamma-Ortsdosisleistung (ODL) in from several measuring stations (by "Bundesamt für Strahlenschutz") in Germany. For more information see https://odlinfo.bfs.de.' maintainer: psilo909 tester: Sandman60 + state: ready keywords: radioactivity documentation: http://smarthomeng.de/user/plugins_doc/config/odlinfo.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/986480-odlinfo-plugin-für-strahlungsdaten @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.4 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance + restartable: unknown classname: ODLInfo # class containing the plugin parameters: @@ -33,7 +35,7 @@ parameters: de: 'Persönliches Passwort für odlinfo.bfs.de. Anleitung unter https://odlinfo.bfs.de/DE/service/datenschnittstelle.html.' en: 'Your own personal password for odlinfo.bfs.de. Instructions see https://odlinfo.bfs.de/DE/service/datenschnittstelle.html.' -item_attributes: +item_attributes: NONE # Definition of item attributes defined by this plugin plugin_functions: diff --git a/tankerkoenig/plugin.yaml b/tankerkoenig/plugin.yaml index 8d78b3887..1044d2422 100755 --- a/tankerkoenig/plugin.yaml +++ b/tankerkoenig/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Petrol station prices by the API of TankerKönig. Take care not to request the interface too often or for too many petrol stations. Please follow instructions given on https://creativecommons.tankerkoenig.de/#techInfo.' maintainer: psilo909 tester: Sandman60 + state: ready # keywords: iot xyz documentation: http://smarthomeng.de/user/plugins_doc/config/tankerkoenig.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/938924-benzinpreis-plugin @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.4 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance + restartable: unknown classname: TankerKoenig # class containing the plugin parameters: @@ -26,7 +28,7 @@ parameters: de: 'Persönlicher API Key für TankerKoenig. Registrierung unter https://creativecommons.tankerkoenig.de.' en: 'Your own personal API key for TankerKoenig. For your own key register to https://creativecommons.tankerkoenig.de.' -item_attributes: +item_attributes: NONE # Definition of item attributes defined by this plugin plugin_functions: diff --git a/traffic/plugin.yaml b/traffic/plugin.yaml index d70c90f56..e9a831527 100755 --- a/traffic/plugin.yaml +++ b/traffic/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Get travel times and directions via the (free) Google Directions API. For your own key see https://developers.google.com/maps/documentation/directions/intro?hl=de#traffic-model' maintainer: psilo909 # tester: # Who tests this plugin? + state: ready keywords: google directions, travel times, routing information documentation: http://smarthomeng.de/user/plugins_doc/config/traffic.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1048446-traffic-plugin-support-thread @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.5 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance + restartable: unknown classname: Traffic # class containing the plugin parameters: @@ -32,10 +34,12 @@ parameters: description: de: '(optional) Sprache, in der bspw. Routinganweisungen bezogen werden sollen. Default: deutsch.' en: '(optional) Language to retrieve routing information. Default: German (de)' - -item_attributes: + + +item_attributes: NONE # Definition of item attributes defined by this plugin + plugin_functions: get_route_info: @@ -74,4 +78,4 @@ plugin_functions: type: str description: de: "Travel Mode, mögliche Werte 'driving', 'walking', 'bicycling', 'transit'. Default: 'driving'." - en: "Travel Mode, possible values 'driving', 'walking', 'bicycling', 'transit'. Default: 'driving'." \ No newline at end of file + en: "Travel Mode, possible values 'driving', 'walking', 'bicycling', 'transit'. Default: 'driving'." From c3b5e0d8afddbd3718c2fcac9e1108c649710056 Mon Sep 17 00:00:00 2001 From: Civer666 <35876720+Civer666@users.noreply.github.com> Date: Fri, 31 Aug 2018 06:52:17 +0200 Subject: [PATCH 193/705] Fixed parenthesis error --- jvcproj/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jvcproj/__init__.py b/jvcproj/__init__.py index 20465929f..c3f42fa0b 100644 --- a/jvcproj/__init__.py +++ b/jvcproj/__init__.py @@ -109,7 +109,7 @@ def __init__(self, smarthome, host='0.0.0.0', gammaconf_dir='/usr/local/smarthom """ self.logger = logging.getLogger(__name__) self._sh=smarthome - self.host_port = (host, 20554)) + self.host_port = (host, 20554) self.gammaconf_dir = gammaconf_dir self.logger.debug("Plugin '{}': configured for host: '{}'".format(self.get_fullname(), self.host_port)) From e031d53ceb85ca90c5eca08b2b17f253f31254fd Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Fri, 31 Aug 2018 12:36:52 +0200 Subject: [PATCH 194/705] UZSU: interpolation, problem handling, logging --- uzsu/README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 uzsu/README.md diff --git a/uzsu/README.md b/uzsu/README.md old mode 100644 new mode 100755 From dababe00507ae55b88264d9d71f93bb75a38dd33 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Fri, 31 Aug 2018 12:56:09 +0200 Subject: [PATCH 195/705] UZSU: interpolation, problem handling, logging --- uzsu/README.md | 29 ++++- uzsu/__init__.py | 330 +++++++++++++++++++++++++++++++++++------------ uzsu/plugin.yaml | 14 +- 3 files changed, 278 insertions(+), 95 deletions(-) mode change 100644 => 100755 uzsu/__init__.py diff --git a/uzsu/README.md b/uzsu/README.md index 981c84297..1b1ac7667 100755 --- a/uzsu/README.md +++ b/uzsu/README.md @@ -6,6 +6,12 @@ Provides universal time switches for items (German: *U*niverselle *Z*eit*s*chalt Calculating of sunset/sunrise in triggers, requires installation of ephem (which should already be part of core) +Calculating interpolation requires installation of scipy. Install with: +pip3 install scipy + +On Raspberry debian stretch you also have to run: +apt-get install libatlas-base-dev + ## Configuration ### plugin.yaml @@ -19,7 +25,10 @@ uzsu: ### items.yaml #### uzsu -You have to specify a item with `type = dict` and with the `uzsu_item` attribute set to the path of the item which will be set by this item. The dict has to have two keys. `active` which says if the whole list of entries should be active or not and `list` which contains a list of all entries (see the Item Data Format section for more details). +You have to specify an item with `type = dict` and with the `uzsu_item` attribute set to the path of the item which will be set by this item. The dict has to have two keys. `active` which says if the whole list of entries should be active or not and `list` which contains a list of all entries (see the Item Data Format section for more details). + +From version 1.4.1 on you can also specify an `interpolation` dictionary. + ```yaml # items/my.yaml @@ -50,6 +59,17 @@ Each UZSU item is of type list. Each list entry has to be a dict with specific k * __rrule__: You can use the recurrence rules documented in the [iCalendar RFC](http://www.ietf.org/rfc/rfc2445.txt) for recurrence use of a switching entry. +## Interpolation +* __type__: string, sets the mathematical function to interpolate between values. Can be cubic, linear or none. If set to cubic or linear the value calculated for the current time will be set on startup and change. + +* __interval__: integer, sets the time span in seconds between the automatic triggers based on the interpolation calculation + +* __initage__: integer, sets the amount of seconds the plugin should go back in time at startup to find the last UZSU item and triggers that right on startup of the plugin. This is useless if interpolation is active as the interpolated time will get set an init anyhow. + +* __itemtype__: the type of the item that should be changed by the UZSU. This is set automatically on init and should not be touched. + +* __initizialized__: bool, gets set automatically at startup as soon as a valid UZSU entry was found in the specified initage and the item was indeed initialized with that value. + ## Example Activates the light every other day at 16:30 and deactivates it at 17:30 for five times: @@ -57,10 +77,11 @@ Activates the light every other day at 16:30 and deactivates it at 17:30 for fiv ```python sh.eg.wohnen.kugellampe.uzsu({'active':True, 'list':[ {'value':1, 'active':True, 'rrule':'FREQ=DAILY;INTERVAL=2;COUNT=5', 'time': '16:30'}, -{'value':0, 'active':True, 'rrule':'FREQ=DAILY;INTERVAL=2;COUNT=5', 'time': '17:30'} -]}) +{'value':0, 'active':True, 'rrule':'FREQ=DAILY;INTERVAL=2;COUNT=5', 'time': '17:30'}], +{'interval': 5, 'type': 'cubic', 'initialized': False, 'itemtype': 'num', 'initage': 0} +}) ``` ## SmartVISU -There is a widget available which gives an interface to the UZSU. The structure has changed from SmartVISU 2.8 to 2.9 slightly, please consult the corresponding forum. +There is a widget available which gives an interface to the UZSU. The structure has changed from SmartVISU 2.8 to 2.9 slightly. Interpolation feature is supported in 2.9 only. Please consult the corresponding forum. diff --git a/uzsu/__init__.py b/uzsu/__init__.py old mode 100644 new mode 100755 index 9d3a97318..cd74049e7 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -22,31 +22,31 @@ # Item Data Format -# -# Each UZSU item is of type list. Each list entry has to be a dict with specific key and value pairs. +# +# Each UZSU item is of type list. Each list entry has to be a dict with specific key and value pairs. # Here are the possible keys and their purpose: -# +# # dtstart: a datetime object. Exact datetime as start value for the rrule algorithm. Important e.g. for FREQ=MINUTELY rrules (optional). -# +# # value: the value which will be set to the item. -# -# active: True if the entry is activated, False if not. +# +# active: True if the entry is activated, False if not. # A deactivated entry is stored to the database but doesn't trigger the setting of the value. # It can be enabled later with the update method. -# -# time: time as string to use sunrise/sunset arithmetics like in the crontab -# examples: +# +# time: time as string to use sunrise/sunset arithmetics like in the crontab +# examples: # 17:008:00 -# 17:00= 0 + cond2 = _interpolation.lower() in ['cubic', 'linear'] + cond3 = _initialized is False + cond4 = _initage > 0 + cond5 = isinstance(_value, float) + if not cond2 and cond3 and cond4: + self.logger.info("{}: Looking if there was a value set after {} for item {}".format( + self._name, _timediff, item)) + self._items[item]['interpolation']['initialized'] = True + item(self._items[item]) + if cond1 and not cond2 and cond3: + self._set(item=item, value=_initvalue, caller='scheduler') + self.logger.info("{}: Updated item {} on startup with value {} from time {}".format( + self._name, item, _initvalue, datetime.fromtimestamp(_inittime/1000.0))) + self._itpl = OrderedDict(itpl_list) + _itemtype = self._items[item]['interpolation'].get('itemtype') + if cond2 and not REQUIRED_PACKAGE_IMPORTED: + self.logger.warning("{}: Interpolation is set to {} but scipy not installed. Ignoring interpolation".format( + self._name, _interpolation)) + elif cond2 and _interval < 1: + self.logger.warning("{}: Interpolation is set to {} but interval is {}. Ignoring interpolation".format( + self._name, _interpolation, _interval)) + elif cond2 and _itemtype not in ['num']: + self.logger.warning("{}: Interpolation is set to {} but type of item is {}." + " Ignoring interpolation and setting USZU interpolation to none.".format( + self._name, _interpolation, _itemtype)) + _reset_interpolation = True + elif _interpolation.lower() == 'cubic' and _interval > 0: + try: + tck = interpolate.PchipInterpolator(list(self._itpl.keys()), list(self._itpl.values())) + _nextinterpolation = datetime.now(self._timezone) + timedelta(minutes=_interval) + _next = _nextinterpolation if _next > _nextinterpolation else _next + _value = round(float(tck(_next.timestamp() * 1000.0)), 2) + _value_now = round(float(tck(entry_now)), 2) + self._set(item=item, value=_value_now, caller='scheduler') + self.logger.info("{}: Updated: {}, cubic interpolation value: {}, based on dict: {}." + " Next: {}, value: {}".format(self._name, item, _value_now, self._itpl, _next, _value)) + except Exception as e: + self.logger.error("{}: Error cubic interpolation: {}".format(self._name, e)) + elif _interpolation.lower() == 'linear' and _interval > 0: + try: + tck = interpolate.interp1d(list(self._itpl.keys()), list(self._itpl.values())) + _nextinterpolation = datetime.now(self._timezone) + timedelta(minutes=_interval) + _next = _nextinterpolation if _next > _nextinterpolation else _next + _value = round(float(tck(_next.timestamp() * 1000.0)), 2) + _value_now = round(float(tck(entry_now)), 2) + self._set(item=item, value=_value_now, caller='scheduler') + self.logger.info("{}: Updated: {}, linear interpolation value: {}, based on dict: {}." + " Next: {}, value: {}".format(self._name, item, _value_now, self._itpl, _next, _value)) + except Exception as e: + self.logger.error("{}: Error linear interpolation: {}".format(self._name, e)) + if cond5 and _value < 0: + self.logger.warning("{}: value {} for item {} is negative. This might be due" + " to not enough values set in the UZSU.".format(self._name, _value, item)) + if _reset_interpolation == True: + self._items[item]['interpolation']['type'] = 'none' + item(self._items[item]) + else: + self.logger.debug("{}: will add scheduler named uzsu_{} with datetime {} and tzinfo {}" + " and value {}".format(self._name, item, _next, _next.tzinfo, _value)) + self.scheduler_add('uzsu_{}'.format(item), self._set, value={'item': item, 'value': _value}, next=_next) def _set(self, **kwargs): item = kwargs['item'] value = kwargs['value'] - self._sh.return_item(item.conf['uzsu_item'])(value, caller='UZSU') - self._schedule(item) + try: + caller = kwargs['caller'] + except Exception: + caller = None + _uzsuitem = self.itemsApi.return_item(self.get_iattr_value(item.conf, ITEM_TAG[0])) + _uzsuitem(value, caller='UZSU') + if not caller: + self._schedule(item, caller='set') - def _next_time(self, entry): + def _get_time(self, entry, timescan): """ Returns the next execution time and value :param entry: a dictionary that may contain the following keys: @@ -189,17 +322,18 @@ def _next_time(self, entry): try: if not isinstance(entry, dict): return None, None - if not 'value' in entry: + if 'value' not in entry: return None, None - if not 'active' in entry: + if 'active' not in entry: return None, None - if not 'time' in entry: + if 'time' not in entry: return None, None now = datetime.now() value = entry['value'] active = entry['active'] today = datetime.today() yesterday = today - timedelta(days=1) + weekbefore = today - timedelta(days=6) time = entry['time'] if not active: return None, None @@ -210,50 +344,68 @@ def _next_time(self, entry): rrule = rrulestr(entry['rrule'], dtstart=entry['dtstart']) else: try: - rrule = rrulestr(entry['rrule'], dtstart=datetime.combine(yesterday, parser.parse(time.strip()).time())) + rrule = rrulestr(entry['rrule'], dtstart=datetime.combine(weekbefore, parser.parse(time.strip()).time())) except ValueError: - self.logger.debug("Could not create a rrule from rrule:'{}'and time:'{}'".format(entry['rrule'],time)) + self.logger.debug("{}: Could not create a rrule from rrule:'{}' and time:'{}'".format( + self._name, entry['rrule'], time)) if 'sun' in time: - self.logger.debug("Looking for next sun-related time with rrulestr()") - rrule = rrulestr(entry['rrule'], dtstart=datetime.combine(yesterday, self._sun(datetime.combine(yesterday.date(), datetime.min.time()).replace(tzinfo=self._sh.tzinfo()), time).time())) + self.logger.debug("{}: Looking for {} sun-related time with rrulestr()".format( + self._name, timescan)) + rrule = rrulestr(entry['rrule'], dtstart=datetime.combine(weekbefore, self._sun(datetime.combine(yesterday.date(), datetime.min.time()).replace(tzinfo=self._timezone), time).time())) else: - self.logger.debug("Looking for next time with rrulestr()") - rrule = rrulestr(entry['rrule'], dtstart=datetime.combine(yesterday, datetime.min.time())) + self.logger.debug("{}: Looking for {} time with rrulestr()".format( + self._name, timescan)) + rrule = rrulestr(entry['rrule'], dtstart=datetime.combine(weekbefore, datetime.min.time())) dt = now while self.alive: - dt = rrule.after(dt) + dt = rrule.before(dt) if timescan == 'previous' else rrule.after(dt) if dt is None: return None, None if 'sun' in time: - next = self._sun(datetime.combine(dt.date(), datetime.min.time()).replace(tzinfo=self._sh.tzinfo()), time) - self.logger.debug("Result parsing time (rrule){}: {}".format(time, next)) + next = self._sun(datetime.combine(dt.date(), datetime.min.time()).replace(tzinfo=self._timezone), time) + self.logger.debug("{}: Result parsing time (rrule){}: {}".format(self._name, time, next)) else: - next = datetime.combine(dt.date(), parser.parse(time.strip()).time()).replace(tzinfo=self._sh.tzinfo()) - if next and next.date() == dt.date() and next > datetime.now(self._sh.tzinfo()): + next = datetime.combine(dt.date(), parser.parse(time.strip()).time()).replace(tzinfo=self._timezone) + cond_next = next > datetime.now(self._timezone) and timescan == 'next' + cond_previous = next < datetime.now(self._timezone) and timescan == 'previous' + if next and next.date() == dt.date() and cond_next: + self._itpl[next.timestamp() * 1000.0] = value + self.logger.debug("{}: Return from rrule next: {}, value {}.".format(self._name, next, value)) + return next, value + if next and next.date() == dt.date() and cond_previous: + self._itpl[next.timestamp() * 1000.0] = value + self.logger.debug("{}: Return from rrule previous: {}, value {}.".format(self._name, next, value)) return next, value if 'sun' in time: - next = self._sun(datetime.combine(today, datetime.min.time()).replace(tzinfo=self._sh.tzinfo()), time) - self.logger.debug("Result parsing time (sun) {}: {}".format(time, next)) + next = self._sun(datetime.combine(today, datetime.min.time()).replace(tzinfo=self._timezone), time) + self.logger.debug("{}: Result parsing time (sun) {}: {}".format(self._name, time, next)) else: - next = datetime.combine(today, parser.parse(time.strip()).time()).replace(tzinfo=self._sh.tzinfo()) - if next and next.date() == today and next > datetime.now(self._sh.tzinfo()): + next = datetime.combine(today, parser.parse(time.strip()).time()).replace(tzinfo=self._timezone) + if next and next.date() == today and cond_next: + self._itpl[next.timestamp() * 1000.0] = value + self.logger.debug("{}: Return next: {}, value {}".format(self._name, next, value)) + return next, value + if next and next.date() == today and cond_previous: + self._itpl[next.timestamp() * 1000.0] = value + self.logger.debug("{}: Return previous: {}, value {}".format(self._name, next, value)) return next, value except Exception as e: - self.logger.error("Error '{}' parsing time: {}".format(time, e)) + self.logger.error("{}: Error '{}' parsing time: {}".format(self._name, time, e)) return None, None def _sun(self, dt, tstr): """ - parses a given string with a time range to determine it's timely boundaries and - returns a time - - :param: dt contains a datetime object, + parses a given string with a time range to determine it's timely boundaries and + returns a time + + :param: dt contains a datetime object, :param: tstr contains a string with '[H:M<](sunrise|sunset)[+|-][offset][ next_time: next_time = dmin if smax is not None: h, sep, m = smax.partition(':') try: - dmax = next_time.replace(hour=int(h), minute=int(m), second=0, tzinfo=self._sh.tzinfo()) + dmax = next_time.replace(hour=int(h), minute=int(m), second=0, tzinfo=self._timezone) except Exception: - self.logger.error('Wrong syntax: {0}. Should be [H:M<](sunrise|sunset)[+|-][offset][ dmax: - self.logger.error('Wrong times: the earliest time should be smaller than the latest time in {}'.format(tstr)) + self.logger.error("{}: Wrong times: the earliest time should be smaller than the " + "latest time in {}".format(self._name, tstr)) return - + return next_time diff --git a/uzsu/plugin.yaml b/uzsu/plugin.yaml index 00a946cfd..2c1c9ecb2 100755 --- a/uzsu/plugin.yaml +++ b/uzsu/plugin.yaml @@ -6,19 +6,23 @@ plugin: de: 'Universelle Zeitschaltuhr' en: 'Universal time switch' maintainer: cmalo (Niko Will) - tester: Sandman60, cmalo + tester: Sandman60, cmalo, onkelandy # keywords: iot xyz documentation: https://github.com/smarthomeNG/smarthome/wiki/UZSU-%28Universelle-Zeitschaltuhr%29 # url of documentation (wiki) page - version: 1.3.0 # Plugin version - sh_minversion: 1.3 # minimum shNG version to use this plugin + version: 1.5.1 # Plugin version + sh_minversion: 1.5 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance classname: UZSU # class containing the plugin parameters: # Definition of parameters to be configured in etc/plugin.yaml - + item_attributes: # Definition of item attributes defined by this plugin - + uzsu_item: + type: str + description: + de: 'Das Item, das durch die UZSU geschaltet werden soll' + en: 'The item that gets changed by the UZSU' From 9e423ec939adf61d22fd68a4949c9a19713ef3b6 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Fri, 31 Aug 2018 16:31:19 +0200 Subject: [PATCH 196/705] SML: fix variable name for CRC16 checksum --- sml/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sml/__init__.py b/sml/__init__.py index 9a76143ce..21ea382c8 100755 --- a/sml/__init__.py +++ b/sml/__init__.py @@ -189,7 +189,7 @@ def _refresh(self): self.logger.debug('Found chunk at {} - {} ({} bytes):{}'.format(start_pos, end_pos, end_pos-start_pos, ''.join(' {:02x}'.format(x) for x in chunk))) chunk_crc_str = '{:02X}{:02X}'.format(chunk[-2], chunk[-1]) chunk_crc_calc = self._crc16(chunk[:-2]) - chunk_crc_calc_str = '{:02X}{:02X}'.format((chunk_crc >> 8) & 0xff, chunk_crc & 0xff) + chunk_crc_calc_str = '{:02X}{:02X}'.format((chunk_crc_calc >> 8) & 0xff, chunk_crc_calc & 0xff) if chunk_crc_str != chunk_crc_calc_str: self.logger.warn('CRC checksum mismatch: Expected {}, but was {}'.format(chunk_crc_str, chunk_crc_calc_str)) data = data[:start_pos] From 97e5245099cabd2f1945b12ae88bc1f6e6b657b8 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Fri, 31 Aug 2018 17:32:49 +0200 Subject: [PATCH 197/705] SML: remove unused import for common module --- sml/tests/base.py | 1 - sml/tests/test_basic.py | 1 - sml/tests/test_special_case.py | 1 - 3 files changed, 3 deletions(-) diff --git a/sml/tests/base.py b/sml/tests/base.py index a4e1fa6a9..536bb1b03 100644 --- a/sml/tests/base.py +++ b/sml/tests/base.py @@ -1,5 +1,4 @@ import re -import common import unittest from plugins.sml import Sml diff --git a/sml/tests/test_basic.py b/sml/tests/test_basic.py index 25a83169d..749c32823 100644 --- a/sml/tests/test_basic.py +++ b/sml/tests/test_basic.py @@ -1,4 +1,3 @@ -import common import unittest from plugins.sml import Sml diff --git a/sml/tests/test_special_case.py b/sml/tests/test_special_case.py index da9f456d2..92c1b2362 100644 --- a/sml/tests/test_special_case.py +++ b/sml/tests/test_special_case.py @@ -1,4 +1,3 @@ -import common import unittest from plugins.sml import Sml From da023d6b148bcfdb26add5f9207933bb0a0df1ac Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Fri, 31 Aug 2018 17:34:17 +0200 Subject: [PATCH 198/705] SML: adjust tests (fix dummy data CRC16, add marker in hex data, fix expected result) --- sml/tests/test_basic.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/sml/tests/test_basic.py b/sml/tests/test_basic.py index 749c32823..563da58a3 100644 --- a/sml/tests/test_basic.py +++ b/sml/tests/test_basic.py @@ -31,7 +31,7 @@ class TestSmlBasic(TestSmlBase): 'ff 01 01 01 01 83 02<00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ' '00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ' '00 00 00 00>01 01 63 4e ab 00 76 09 00 00 00 00 0f 40 0f ab 62 01 62 00 72 63 ' - '02 01 71 01 63 4e 4c 00 1b 1b 1b 1b 1a 00 18 6e', + '02 01 71 01 63 4e 4c 00 1b 1b 1b 1b 1a 00 33 f7', 'hex' ) DEFAULT_PACKET2 = SmlPacket( @@ -59,15 +59,15 @@ class TestSmlBasic(TestSmlBase): 'hex' ) DEFAULT_PACKET_MISSING_END = SmlPacket( - # Entity {'scaler': -4, 'unitName': 'Wh', 'objName': b'\x01\x00\x02\x08\x00\xff', 'status': None, 'obis': '1-0:2.8.0*255', 'value': 29803232821505, 'valTime': None, 'unit': 30, 'signature': None, 'valueReal': 2980323282.1505003} - # Entity {'scaler': -4, 'unitName': 'Wh', 'objName': b'\x01\x00\x01\x08\x00\xff', 'status': None, 'obis': '1-0:1.8.0*255', 'value': 64963419, 'valTime': None, 'unit': 30, 'signature': None, 'valueReal': 6496.3419} # Entity {'scaler': None, 'unitName': None, 'objName': b'\x81\x81\xc7\x82\x03\xff', 'status': None, 'obis': '129-129:199.130.3*255', 'value': b'ESY', 'valTime': None, 'unit': None, 'signature': None, 'valueReal': b'ESY'}} + # Entity {'scaler': -4, 'unitName': 'Wh', 'objName': b'\x01\x00\x01\x08\x00\xff', 'status': None, 'obis': '1-0:1.8.0*255', 'value': 64963419, 'valTime': None, 'unit': 30, 'signature': None, 'valueReal': 6496.3419} + # Entity {'scaler': -4, 'unitName': 'Wh', 'objName': b'\x01\x00\x02\x08\x00\xff', 'status': None, 'obis': '1-0:2.8.0*255', 'value': 29803232821505, 'valTime': None, 'unit': 30, 'signature': None, 'valueReal': 2980323282.1505003} '1b 1b 1b 1b 01 01 01 01 76 05 08 ca 78 f7 62 00 62 00 72 65 00 00 01 01 76 01 ' '01 07 45 53 59 51 33 42 0b 06 45 53 59 01 04 c6 a1 f6 db 01 01 63 bf 6e 00 76 ' '05 08 ca 78 f8 62 00 62 00 72 65 00 00 07 01 77 01 0b 06 45 53 59 01 04 c6 a1 ' - 'f6 db 01 72 62 01 65 06 5a fc 21 79 77 07 81 81 c7 82 03 ff 01 01 01 01 04 45 ' - '53 59 01 77 07 01 00 01 08 00 ff 01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b ' - '01 77 07 01 00 02 08 00 ff 01 01 62 1e 52 fc 69 00 00', + 'f6 db 01 72 62 01 65 06 5a fc 21 79 77 07[81 81:c7 82 03*ff]01 01 01 01 04 45 ' + '53 59 01 77 07[01 00:01 08 00*ff]01 01 62 1e 52 fc 69 00 00 00 00 03 df 43 5b ' + '01 77 07[01 00:02 08 00*ff]01 01 62 1e 52 fc 69 00 00', 'hex' ) @@ -107,8 +107,7 @@ def test_read_packet_missing_end(self): plugin = self.plugin() plugin.data.add(TestSmlBasic.DEFAULT_PACKET_MISSING_END) values = plugin._refresh() - self.assertEqual(3, len(values)) - self.assertEntry(values, '1-0:2.8.0*255', unit=30, unitname='Wh', value=29803232821505, scaler=-4) + self.assertEqual(2, len(values)) self.assertEntry(values, '1-0:1.8.0*255', unit=30, unitname='Wh', value=64963419, scaler=-4) self.assertEntry(values, '129-129:199.130.3*255', value=b'ESY') From b2f0e9ce98b1a1efa551e7796bd14741b894558d Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Fri, 31 Aug 2018 17:53:54 +0200 Subject: [PATCH 199/705] Added Webinterface, fixed some problems --- avdevice/AVDeviceInit.py | 6 +++- avdevice/webif/static/img/avdevice.tif | Bin avdevice/webif/static/img/plugin_logo.png | Bin avdevice/webif/templates/index.html | 33 +++++++++++----------- 4 files changed, 22 insertions(+), 17 deletions(-) mode change 100644 => 100755 avdevice/webif/static/img/avdevice.tif mode change 100644 => 100755 avdevice/webif/static/img/plugin_logo.png diff --git a/avdevice/AVDeviceInit.py b/avdevice/AVDeviceInit.py index 22411d8b5..4da922018 100755 --- a/avdevice/AVDeviceInit.py +++ b/avdevice/AVDeviceInit.py @@ -64,7 +64,11 @@ def get_items(self, zone): for item in self._items[zone]: _result = self._items[zone][item].get('Item') itemlist.append(_result) - sortedlist.append(_result.id()) + if not item == 'dependson': + try: + sortedlist.append(_result.id()) + except Exception: + sortedlist.append(_result) sortedlist.sort() for i in sortedlist: finallist.append(self.itemsApi.return_item(i)) diff --git a/avdevice/webif/static/img/avdevice.tif b/avdevice/webif/static/img/avdevice.tif old mode 100644 new mode 100755 diff --git a/avdevice/webif/static/img/plugin_logo.png b/avdevice/webif/static/img/plugin_logo.png old mode 100644 new mode 100755 diff --git a/avdevice/webif/templates/index.html b/avdevice/webif/templates/index.html index fdf475204..04299835e 100755 --- a/avdevice/webif/templates/index.html +++ b/avdevice/webif/templates/index.html @@ -50,10 +50,10 @@ - + - + - - + + - - + - + - + @@ -100,7 +101,7 @@ {% if config_reloaded %}
Model{{ _('Modell') }} {{ p.get_parameter_value_for_display('model').replace('models/', '').upper() }} Connection{{ _('Verbindung') }} {% if p._rs232 %}{{ p._rs232 }}:{{ p._baud }}, {{ p._timeout }} {% else %}{{ p._tcp }}:{{ p._port }}, {{ p._tcp_timeout }}{% endif %} {{ p._is_connected }} @@ -66,23 +66,24 @@
Depends On{% if p._dependson %}{{ p._dependson }} = {{ p._dependsonvalue }} - {% else %}No global dependency{% endif %}{{ _('Abhängig von') }}{{ p._dependson|default('nichts') }} + {% if p._dependson_value %} = {{ p._dependson_value }}{% endif %} Depend to 0{% if p._depend0_power0 %}Power, {% endif %} + {{ _('0 wenn') }} + {% if p._depend0_power0 %}Power{% endif %}{% if p._depend0_power0 and p._depend0_volume0%}, {% endif %} {% if p._depend0_volume0 %}Volume{% endif %} {% if not p._depend0_volume0 and not p._depend0_power0 %}None{% endif %}
Ignore Response{{ _('Ignorieren') }} {% if p._ignore_response %}{{ p._ignore_response }} {% else %}None{% endif %}
Error Response{{ _('Fehlermeldung') }} {% if p._error_response %}{{ p._error_response }} {% else %}None{% endif %}
@@ -135,7 +136,7 @@
{% else %}
- Es sind keine Item in dieser Zone definiert. + {{ _('Es sind keine Item in dieser Zone definiert.') }}
{% endif %} @@ -308,7 +309,7 @@ {% else %}
- Es sind keine Item in dieser Zone definiert. + {{ _('Es sind keine Item in dieser Zone definiert.') }}
{% endif %}
@@ -318,7 +319,7 @@
{% if item_count_zone2>0 %}
- {{ _('Die folgenden Items sind dieser Instanz des Database Plugins zugewiesen') }}: + {{ _('Die folgenden Items sind dieser Instanz des AVDevice Plugins zugewiesen') }}:
@@ -339,7 +340,7 @@
{% else %}
- Es sind keine Item in dieser Zone definiert. + {{ _('Es sind keine Item in dieser Zone definiert.') }}
{% endif %}
@@ -371,7 +372,7 @@ {% else %}
- Es sind keine Item in dieser Zone definiert. + {{ _('Es sind keine Item in dieser Zone definiert.') }}
{% endif %}
From 7eca14b504bd1fade94732fbe2b48c74851ce320 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Fri, 31 Aug 2018 18:16:13 +0200 Subject: [PATCH 200/705] Added webinterface and optimized code and logging --- gpio/README.md | 0 gpio/__init__.py | 185 ++++++++++++++++++++------ gpio/plugin.yaml | 14 +- gpio/webif/static/img/plugin_logo.png | Bin 0 -> 41049 bytes gpio/webif/static/img/readme.txt | 6 + gpio/webif/templates/index.html | 100 ++++++++++++++ 6 files changed, 259 insertions(+), 46 deletions(-) mode change 100644 => 100755 gpio/README.md create mode 100644 gpio/webif/static/img/plugin_logo.png create mode 100755 gpio/webif/static/img/readme.txt create mode 100755 gpio/webif/templates/index.html diff --git a/gpio/README.md b/gpio/README.md old mode 100644 new mode 100755 diff --git a/gpio/__init__.py b/gpio/__init__.py index 68a3b525f..cba826b05 100755 --- a/gpio/__init__.py +++ b/gpio/__init__.py @@ -3,7 +3,7 @@ ######################################################################### # Copyright 2016 ######################################################################### -# This file is part of SmartHomeNG. +# This file is part of SmartHomeNG. # # SmartHomeNG is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -20,62 +20,84 @@ ######################################################################### import logging -from lib.model.smartplugin import SmartPlugin -import RPi.GPIO as GPIO +from lib.model.smartplugin import * import threading +import datetime + +try: + import RPi.GPIO as GPIO + REQUIRED_PACKAGE_IMPORTED = True +except: + REQUIRED_PACKAGE_IMPORTED = False class Raspi_GPIO(SmartPlugin): - PLUGIN_VERSION = "1.0.1" + PLUGIN_VERSION = "1.4.1" ALLOW_MULTIINSTANCE = False - def __init__(self, sh, mode="board"): + def __init__(self, sh): self.logger = logging.getLogger(__name__) - self._sh = sh - self._items = [] - self._itemsdict = {} - self._mode = mode.upper() - GPIO.setwarnings(False) - if self._mode == "BCM": - GPIO.setmode(GPIO.BCM) - else: - GPIO.setmode(GPIO.BOARD) - self.logger.debug("GPIO: Mode set to {0}".format(self._mode)) - self.alive = False - self._lock = threading.Lock() - + self.init_webinterface() + self._name = self.get_fullname() + if not REQUIRED_PACKAGE_IMPORTED: + self.logger.error("{}: Unable to import Python package 'GPIO'".format(self._name)) + self._init_complete = False + return + try: + self._items = [] + self._itemsdict = {} + self._initdict = {} + self._mode = self.get_parameter_value('mode').upper() + GPIO.setwarnings(False) + if self._mode == "BCM": + GPIO.setmode(GPIO.BCM) + else: + GPIO.setmode(GPIO.BOARD) + self.logger.debug("{}: Mode set to {}".format(self._name, self._mode)) + self.alive = False + self._lock = threading.Lock() + except Exception: + self._init_complete = False + return + + def get_sensors(self, sensor): try: value = GPIO.input(sensor) self._itemsdict[sensor](value, 'GPIO', 'get_sensors') - self.logger.info("GPIO: SENSOR READ: {0} VALUE: {1}".format(sensor,value)) + self.logger.info("{}: SENSOR READ: {} VALUE: {}".format(self._name, sensor, value)) except Exception as e: - self.logger.warning("GPIO: Problem reading sensor: {0}".format(e)) + self.logger.warning("{}: Problem reading sensor: {}".format(self._name, e)) def run(self): - self.logger.debug("GPIO: run method called") - self.alive = True + self.logger.debug("{}: run method called") + self.alive = True for item in self._items: if self.has_iattr(item.conf, 'gpio_in'): - sensor = int(self.get_iattr_value(item.conf, 'gpio_in')) - value = GPIO.input(sensor) + sensor = int(self.get_iattr_value(item.conf, 'gpio_in')) + try: + value = GPIO.input(sensor) + self._initdict[sensor] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f") + except Exception: + self._initdict[sensor] = False item(value, 'GPIO', 'gpio_init') GPIO.add_event_detect(sensor, GPIO.BOTH, callback=self.get_sensors) - self.logger.info("GPIO: Adding Event Detection for Pin {}. Initial value is {}".format(sensor, value)) + self.logger.info("{}: Adding Event Detection for Pin {}. Initial value is {}".format( + self._name, sensor, value)) def stop(self): self.alive = False GPIO.cleanup() - self.logger.debug("GPIO: cleaned up") - + self.logger.debug("{}: cleaned up".format(self._name)) + def parse_item(self, item): if self.has_iattr(item.conf, 'gpio_in'): in_pin = int(item.conf['gpio_in']) GPIO.setup(in_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) - self.logger.debug("GPIO: INPUT {0} assigned to pin \'{1}\'".format(item, in_pin)) + self.logger.debug("{}: INPUT {} assigned to pin \'{}\'".format(self._name, item, in_pin)) self._items.append(item) self._itemsdict[in_pin] = item - return self.update_item + return self.update_item if self.has_iattr(item.conf, 'gpio_out'): out_pin = int(self.get_iattr_value(item.conf, 'gpio_out')) GPIO.setup(out_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) @@ -83,12 +105,13 @@ def parse_item(self, item): value = GPIO.input(out_pin) item(value, 'GPIO', 'gpio_init') GPIO.add_event_detect(out_pin, GPIO.BOTH, callback=self.get_sensors) - self.logger.info("GPIO: Adding Event Detection for Output Pin {}. Initial value is {}".format(out_pin, value)) + self.logger.info("{}: Adding Event Detection for Output Pin {}. Initial value is {}".format( + self._name, out_pin, value)) GPIO.setup(out_pin, GPIO.OUT) - self.logger.debug("GPIO: OUTPUT {0} assigned to \'{1}\'".format(item, out_pin)) + self.logger.debug("{}: OUTPUT {} assigned to \'{}\'".format(self._name, item, out_pin)) if (out_pin is None): return None - self.logger.debug("GPIO: No out_pin set for item {}".format(item)) + self.logger.debug("{}: No out_pin set for item {}".format(self._name, item)) else: self._items.append(item) return self.update_item @@ -97,25 +120,103 @@ def parse_logic(self, logic): pass def update_item(self, item, caller=None, source=None, dest=None): - self.logger.debug("GPIO: Trying to update {}.".format(item)) + self.logger.debug("{}: Trying to update {}.".format(self._name, item)) if self.has_iattr(item.conf, 'gpio_out'): out_pin = int(self.get_iattr_value(item.conf, 'gpio_out')) - value = item() - self.logger.debug("GPIO: OUTPUT Setting pin {0} ({2}) to {1}.".format(out_pin, value, item.id())) + value = item() + self.logger.debug("{}: OUTPUT Setting pin {} ({}) to {}.".format(self._name, out_pin, value, item.id())) self.send(out_pin, value) else: - self.logger.debug("GPIO: No gpio_out") + self.logger.debug("{}: No gpio_out".format(self._name)) def send(self, pin, value): self._lock.acquire() try: GPIO.output(pin, value) - self.logger.info("GPIO: Pin {0} successfully set to {1}".format(pin, value)) + self.logger.info("{}: Pin {} successfully set to {}".format(self._name, pin, value)) except: - self.logger.error("GPIO: Send {0} failed for {1}!".format(value, pin)) + self.logger.error("{}: Send {} failed for {}!".format(self._name, value, pin)) finally: - self._lock.release() + self._lock.release() + + def init_webinterface(self): + """" + Initialize the web interface for this plugin + + This method is only needed if the plugin is implementing a web interface + """ + try: + self.mod_http = Modules.get_instance().get_module('http') # try/except to handle running in a core version that does not support modules + except: + self.mod_http = None + if self.mod_http == None: + self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_shortname())) + return False + + import sys + if not "SmartPluginWebIf" in list(sys.modules['lib.model.smartplugin'].__dict__): + self.logger.warning("Plugin '{}': Web interface needs SmartHomeNG v1.5 and up. Not initializing the web interface".format(self.get_shortname())) + return False + + # set application configuration for cherrypy + webif_dir = self.path_join(self.get_plugin_dir(), 'webif') + config = { + '/': { + 'tools.staticdir.root': webif_dir, + }, + '/static': { + 'tools.staticdir.on': True, + 'tools.staticdir.dir': 'static' + } + } + + # Register the web interface as a cherrypy app + self.mod_http.register_webif(WebInterface(webif_dir, self), + self.get_shortname(), + config, + self.get_classname(), self.get_instance_name(), + description='') + + return True + + +# ------------------------------------------ +# Webinterface of the plugin +# ------------------------------------------ + +import cherrypy +from jinja2 import Environment, FileSystemLoader + +class WebInterface(SmartPluginWebIf): + + + def __init__(self, webif_dir, plugin): + """ + Initialization of instance of class WebInterface + + :param webif_dir: directory where the webinterface of the plugin resides + :param plugin: instance of the plugin + :type webif_dir: str + :type plugin: object + """ + self.logger = logging.getLogger(__name__) + self.webif_dir = webif_dir + self.plugin = plugin + self.tplenv = self.init_template_environment() + + + @cherrypy.expose + def index(self, action=None, item_id=None, item_path=None, reload=None): + """ + Build index.html for cherrypy + + Render the template and return the html file to be delivered to the browser + + :return: contents of the template after beeing rendered + """ + item = self.plugin.get_sh().return_item(item_path) -if __name__ == '__main__': - logging.basicConfig(level=logging.DEBUG, format='%(relativeCreated)6d %(threadName)s %(message)s') - FooClass(None).run() + tmpl = self.tplenv.get_template('index.html') + # add values to be passed to the Jinja2 template eg: tmpl.render(p=self.plugin, interface=interface, ...) + return tmpl.render(p=self.plugin, + language=self.plugin._sh.get_defaultlanguage(), now=self.plugin.shtime.now()) diff --git a/gpio/plugin.yaml b/gpio/plugin.yaml index 9c6f42548..7832f82a9 100755 --- a/gpio/plugin.yaml +++ b/gpio/plugin.yaml @@ -11,15 +11,21 @@ plugin: # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page # support: https://knx-user-forum.de/forum/supportforen/smarthome-py - version: 1.0.1 # Plugin version - sh_minversion: 1.1 # minimum shNG version to use this plugin + version: 1.4.1 # Plugin version + sh_minversion: 1.4 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance classname: Raspi_GPIO # class containing the plugin parameters: # Definition of parameters to be configured in etc/plugin.yaml - + mode: + type: str + default: 'BOARD' + mandatory: True + description: + de: 'BOARD oder BCM, abhängig davon, nach welcher Methode die Pins zugewiesen werden sollen.' + en: 'BOARD or BCM, depending on how to assign the pins.' + item_attributes: # Definition of item attributes defined by this plugin - diff --git a/gpio/webif/static/img/plugin_logo.png b/gpio/webif/static/img/plugin_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..03ff039040ad0521daa15cb7b695bca6a4c23ea6 GIT binary patch literal 41049 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 QTj0;B. + +Extension can be png, svg or jpg + diff --git a/gpio/webif/templates/index.html b/gpio/webif/templates/index.html new file mode 100755 index 000000000..3b60f58ff --- /dev/null +++ b/gpio/webif/templates/index.html @@ -0,0 +1,100 @@ +{% extends "base_plugin.html" %} +{% block scripts %} +{{ super() }} + +{% endblock scripts %} +{% set logo_frame = false %} + + +{% set item_count = p._items|length %} +{% set tab1title = "IN Items" %} +{% set tab2title = "OUT Items" %} +{% set tabcount = 2 %} + +{% block headtable %} + + + + + + + + + + + +
Mode{{ p.get_parameter_value_for_display('mode') }}Items{{ item_count }}
+{% endblock headtable %} + + +{% block bodytab1 %} + +
+
+ {{ _('Die folgenden Items sind dem GPIO Plugin als IN Pin zugewiesen') }}: +
+ + + + + + + + + + {% for item in p._items %} + + {% if p.has_iattr(item.conf, 'gpio_in') %} + {% if p._initdict[p.get_iattr_value(item.conf, 'gpio_in') | int] %} + {% set color = 'green' %} + {% else %} + {% set color = 'red' %} + {% endif %} + + + + + + + {% endif %} + {% endfor %} +
{{ _('Item') }}{{ _('Pin IN') }}{{ _('Wert') }}{{ _('Init') }}
{{ item._path }}{{ p.get_iattr_value(item.conf, 'gpio_in') }}{{ item() }} + {{ p._initdict[p.get_iattr_value(item.conf, 'gpio_in') | int] }}
+
+{% endblock bodytab1 %} + +{% block bodytab2 %} +
+
+ {{ _('Die folgenden Items sind dem GPIO Plugin als OUT Pin zugewiesen') }}: +
+ + + + + + + + + {% for item in p._items %} + + {% if p.has_iattr(item.conf, 'gpio_out') %} + + + + + + {% endif %} + {% endfor %} +
{{ _('Item') }}{{ _('Pin OUT') }}{{ _('Wert') }}
{{ item._path }}{{ p.get_iattr_value(item.conf, 'gpio_out') }}{{ item() }}
+
+{% endblock bodytab2 %} From ff7207aeef2762a698f52b04f819978304032592 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Fri, 31 Aug 2018 18:47:35 +0200 Subject: [PATCH 201/705] valid_list for plugin.yaml --- gpio/plugin.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gpio/plugin.yaml b/gpio/plugin.yaml index 7832f82a9..1faff7784 100755 --- a/gpio/plugin.yaml +++ b/gpio/plugin.yaml @@ -23,6 +23,11 @@ parameters: type: str default: 'BOARD' mandatory: True + valid_list: + - 'board' + - 'bcm' + - 'BOARD' + - 'BCM' description: de: 'BOARD oder BCM, abhängig davon, nach welcher Methode die Pins zugewiesen werden sollen.' en: 'BOARD or BCM, depending on how to assign the pins.' From 46f6397a45c4e39dabdc61f8355d68d4d6c780eb Mon Sep 17 00:00:00 2001 From: msinn Date: Fri, 31 Aug 2018 23:00:45 +0200 Subject: [PATCH 202/705] ebus: Plugin converted to SmartPlugin --- ebus/{README.md => README_old.md} | 0 ebus/__init__.py | 138 ++++++++++++++++++++++------ ebus/_pv_1_0_1/README.md | 67 ++++++++++++++ ebus/_pv_1_0_1/__init__.py | 147 ++++++++++++++++++++++++++++++ ebus/_pv_1_0_1/plugin.yaml | 26 ++++++ ebus/plugin.yaml | 72 ++++++++++++--- 6 files changed, 409 insertions(+), 41 deletions(-) rename ebus/{README.md => README_old.md} (100%) create mode 100644 ebus/_pv_1_0_1/README.md create mode 100644 ebus/_pv_1_0_1/__init__.py create mode 100644 ebus/_pv_1_0_1/plugin.yaml diff --git a/ebus/README.md b/ebus/README_old.md similarity index 100% rename from ebus/README.md rename to ebus/README_old.md diff --git a/ebus/__init__.py b/ebus/__init__.py index 53ea1f306..df19e3cce 100755 --- a/ebus/__init__.py +++ b/ebus/__init__.py @@ -1,59 +1,109 @@ #!/usr/bin/env python3 # vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2018- Martin Sinn m.sinn@gmx.de +# Copyright 2012-2013 KNX-User-Forum e.V. http://knx-user-forum.de/ +######################################################################### +# This file is part of SmartHomeNG.py. +# Visit: https://github.com/smarthomeNG/ +# https://knx-user-forum.de/forum/supportforen/smarthome-py # -# Copyright 2012-2013 KNX-User-Forum e.V. http://knx-user-forum.de/ -# -# This file is part of SmartHomeNG. https://github.com/smarthomeNG// -# -# SmartHomeNG is free software: you can redistribute it and/or modify +# SmartHomeNG.py is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # -# SmartHomeNG is distributed in the hope that it will be useful, +# SmartHomeNG.py is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with SmartHomeNG. If not, see . -# +# along with SmartHomeNG.py. If not, see . +######################################################################### import logging import socket import threading import time -logger = logging.getLogger('eBus') +from lib.model.smartplugin import * + + +class eBus(SmartPlugin): + """ + Main class of the Plugin. Does all plugin specific stuff and provides + the update functions for the items + """ + PLUGIN_VERSION = '1.5.0' -class eBus(): _items = [] - def __init__(self, smarthome, host, port, cycle=240): - self._sh = smarthome - self._cycle = int(cycle) + def __init__(self, sh, *args, **kwargs): + """ + Initalizes the plugin. The parameters descriptions for this method are pulled from the entry in plugin.yaml. + + :param sh: **Deprecated**: The instance of the smarthome object. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! + :param *args: **Deprecated**: Old way of passing parameter values. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! + :param **kwargs:**Deprecated**: Old way of passing parameter values. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! + + If you need the sh object at all, use the method self.get_sh() to get it. There should be almost no need for + a reference to the sh object any more. + + The parameters *args and **kwargs are the old way of passing parameters. They are deprecated. They are imlemented + to support older plugins. Plugins for SmartHomeNG v1.4 and beyond should use the new way of getting parameter values: + use the SmartPlugin method get_parameter_value(parameter_name) instead. Anywhere within the Plugin you can get + the configured (and checked) value for a parameter by calling self.get_parameter_value(parameter_name). It + returns the value in the datatype that is defined in the metadata. + """ + + logger = logging.getLogger(__name__) # remove for shNG v1.6 + self.host = self.get_parameter_value('host') + self.port = self.get_parameter_value('port') + self._cycle = self.get_parameter_value('cycle') + self._sock = False self.connected = False - self.host = host - self.port = int(port) self._connection_attempts = 0 self._connection_errorlog = 60 - smarthome.connections.monitor(self) + # smarthome.connections.monitor(self) + self.get_sh().connections.monitor(self) self._lock = threading.Lock() - self.refresh_cycle = self._cycle + # self.refresh_cycle = self._cycle # not used + def parse_item(self, item): - # Attribute und Parameter werden regelmäßig ausgelesen + """ + Default plugin parse_item method. Is called when the plugin is initialized. + The plugin can, corresponding to its attribute keywords, decide what to do with + the item in future, like adding it to an internal array for future reference + :param item: The item to process. + :return: If the plugin needs to be informed of an items change you should return a call back function + like the function update_item down below. An example when this is needed is the knx plugin + where parse_item returns the update_item function when the attribute knx_send is found. + This means that when the items value is about to be updated, the call back function is called + with the item, caller, source and dest as arguments and in case of the knx plugin the value + can be sent to the knx with a knx write function within the knx plugin. + """ if 'ebus_type' in item.conf and 'ebus_cmd' in item.conf: self._items.append(item) return self.update_item + def run(self): + """ + Run method for the plugin + """ + self.logger.debug("Run method called".format(self.get_fullname())) self.alive = True - self._sh.scheduler.add('eBusd', self.refresh, prio=5, cycle=self._cycle, offset=2) + self.scheduler_add('eBusd', self.refresh, prio=5, cycle=self._cycle, offset=2) + def refresh(self): + """ + Refresh items with data from ebusd + """ for item in self._items: time.sleep(1) ebus_type = item.conf['ebus_type'] @@ -69,35 +119,46 @@ def refresh(self): if not self.alive: break + def request(self, request): + """ + send request to ebusd deamon + + :param request: Command to send to ebusd + :type request: str + """ if not self.connected: - logger.info("eBusd not connected") + self.logger.info("eBusd not connected") return self._lock.acquire() try: self._sock.send(request.encode()) - logger.debug("REQUEST: {0}".format(request)) + self.logger.debug("REQUEST: {0}".format(request)) except Exception as e: self._lock.release() self.close() - logger.warning("error sending request: {0} => {1}".format(request, e)) + self.logger.warning("error sending request: {0} => {1}".format(request, e)) return try: answer = self._sock.recv(256).decode()[:-2] - logger.debug("ANSWER: {0}".format(answer)) + self.logger.debug("ANSWER: {0}".format(answer)) except socket.timeout: self._lock.release() - logger.warning("error receiving answer: timeout") + self.logger.warning("error receiving answer: timeout") return except Exception as e: self._lock.release() self.close() - logger.warning("error receiving answer: {0}".format(e)) + self.logger.warning("error receiving answer: {0}".format(e)) return self._lock.release() return answer + def connect(self): + """ + Open socket connection to ebusd deamon + """ self._lock.acquire() try: self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -106,16 +167,20 @@ def connect(self): except Exception as e: self._connection_attempts -= 1 if self._connection_attempts <= 0: - logger.error('eBus: could not connect to {0}:{1}: {2}'.format(self.host, self.port, e)) + self.logger.error('eBus: could not connect to ebusd at {0}:{1}: {2}'.format(self.host, self.port, e)) self._connection_attempts = self._connection_errorlog self._lock.release() return - logger.info('Connected to {0}:{1}'.format(self.host, self.port)) + self.logger.info('Connected to {0}:{1}'.format(self.host, self.port)) self.connected = True self._connection_attempts = 0 self._lock.release() + def close(self): + """ + Close socket connection + """ self.connected = False try: self._sock.shutdown(socket.SHUT_RDWR) @@ -124,15 +189,28 @@ def close(self): try: self._sock.close() self._sock = False - logger.info('Connection closed to {0}:{1}'.format(self.host, self.port)) + self.logger.info('Connection closed to {0}:{1}'.format(self.host, self.port)) except: pass + def stop(self): + """ + Stop method for the plugin + """ + self.logger.debug("Stop method called".format(self.get_fullname())) self.close() self.alive = False + def update_item(self, item, caller=None, source=None, dest=None): + """ + Write items values + :param item: item to be updated towards the plugin + :param caller: if given it represents the callers name + :param source: if given it represents the source + :param dest: if given it represents the dest + """ if caller != 'eBus': value = str(int(item())) cmd = item.conf['ebus_cmd'] @@ -144,4 +222,4 @@ def update_item(self, item, caller=None, source=None, dest=None): answer = self.request(request) #transfer value and answer to float for better comparsion if float(answer) != float(value) or answer is None: - logger.warning("Failed to set parameter: value: {0} cmd: {1} answer {2}".format(value, request, answer)) + self.logger.warning("Failed to set parameter: value: {0} cmd: {1} answer {2}".format(value, request, answer)) diff --git a/ebus/_pv_1_0_1/README.md b/ebus/_pv_1_0_1/README.md new file mode 100644 index 000000000..aaf192c09 --- /dev/null +++ b/ebus/_pv_1_0_1/README.md @@ -0,0 +1,67 @@ +# eBus + +## Requirements/Description +Description: +Connects to ebusd http://cometvisu.de/wiki/index.php?title=Ebusd wich is communicating with eBus heatings. +Requirements: +running ebusd in network (note: ebusd also requires an ebus-interface) + +## Supported Hardware +I.e. Vaillant, Wolf, Kromschroeder or other eBus-heatings + +## Configuration + +### plugin.yaml + +```yaml +ebus: + class_name: eBus + class_path: plugins.ebus + host: localhost # ip of ebusd + port: 8888 # port of ebusd + cycle: 240 # cycle of each item +``` + +### items.yaml + +Items need parameter "ebus_cmd" and "ebus_type". +ebus_cmd is the command you use for telnet-connection to ebusd. +ebus_type can be "get" or "set". + +#### ebus_set + +Items are read/write. All "set"-items will be read cyclic too! + +#### ebus_get + +Items will only be readable, i.e. sensors. + +```yaml +ebus: + + hk_pumpe_perc: + type: num + knx_dpt: 5 + knx_send: 8/6/110 + knx_reply: 8/6/110 + ebus_cmd: cir2 heat_pump_curr + ebus_type: get + # akt. PWM-Wert Heizkreizpumpe + + ernergie_summe: + type: num + knx_dpt: 12 + knx_send: 8/6/22 + knx_reply: 8/6/22 + ebus_cmd: mv yield_sum + ebus_type: get + # Energieertrag + + speicherladung: + type: bool + knx_dpt: 1 + knx_listen: 8/7/1 + ebus_cmd: short hw_load + ebus_type: set + # Quick - WW Speicherladung +``` diff --git a/ebus/_pv_1_0_1/__init__.py b/ebus/_pv_1_0_1/__init__.py new file mode 100644 index 000000000..df1a6d2f6 --- /dev/null +++ b/ebus/_pv_1_0_1/__init__.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +# +# Copyright 2012-2013 KNX-User-Forum e.V. http://knx-user-forum.de/ +# +# This file is part of SmartHomeNG. https://github.com/smarthomeNG// +# +# SmartHomeNG is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# SmartHomeNG is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with SmartHomeNG. If not, see . +# + +import logging +import socket +import threading +import time + +logger = logging.getLogger('eBus') + + +class eBus(): + _items = [] + + def __init__(self, smarthome, host='127.0.0.1', port='8888', cycle=240): + self._sh = smarthome + self._cycle = int(cycle) + self._sock = False + self.connected = False + self.host = host + self.port = int(port) + self._connection_attempts = 0 + self._connection_errorlog = 60 + smarthome.connections.monitor(self) + self._lock = threading.Lock() + self.refresh_cycle = self._cycle + + def parse_item(self, item): + # Attribute und Parameter werden regelmäßig ausgelesen + if 'ebus_type' in item.conf and 'ebus_cmd' in item.conf: + self._items.append(item) + return self.update_item + + def run(self): + self.alive = True + self._sh.scheduler.add('eBusd', self.refresh, prio=5, cycle=self._cycle, offset=2) + + def refresh(self): + for item in self._items: + time.sleep(1) + ebus_type = item.conf['ebus_type'] + ebus_cmd = item.conf['ebus_cmd'] + if ebus_cmd == "cycle": + request = ebus_type + " " + ebus_cmd # build command + else: + request = "get" + " " + ebus_cmd # build command + value = self.request(request) + #if reading fails (i.e. at broadcast-commands) the value will not be updated + if 'command not found' not in str(value) and value is not None: + item(value, 'eBus', 'refresh') + if not self.alive: + break + + def request(self, request): + if not self.connected: + logger.info("eBusd not connected") + return + self._lock.acquire() + try: + self._sock.send(request.encode()) + logger.debug("REQUEST: {0}".format(request)) + except Exception as e: + self._lock.release() + self.close() + logger.warning("error sending request: {0} => {1}".format(request, e)) + return + try: + answer = self._sock.recv(256).decode()[:-2] + logger.debug("ANSWER: {0}".format(answer)) + except socket.timeout: + self._lock.release() + logger.warning("error receiving answer: timeout") + return + except Exception as e: + self._lock.release() + self.close() + logger.warning("error receiving answer: {0}".format(e)) + return + self._lock.release() + return answer + + def connect(self): + self._lock.acquire() + try: + self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self._sock.settimeout(2) + self._sock.connect((self.host, self.port)) + except Exception as e: + self._connection_attempts -= 1 + if self._connection_attempts <= 0: + logger.error('eBus: could not connect to {0}:{1}: {2}'.format(self.host, self.port, e)) + self._connection_attempts = self._connection_errorlog + self._lock.release() + return + logger.info('Connected to {0}:{1}'.format(self.host, self.port)) + self.connected = True + self._connection_attempts = 0 + self._lock.release() + + def close(self): + self.connected = False + try: + self._sock.shutdown(socket.SHUT_RDWR) + except: + pass + try: + self._sock.close() + self._sock = False + logger.info('Connection closed to {0}:{1}'.format(self.host, self.port)) + except: + pass + + def stop(self): + self.close() + self.alive = False + + def update_item(self, item, caller=None, source=None, dest=None): + if caller != 'eBus': + value = str(int(item())) + cmd = item.conf['ebus_cmd'] + request = "set " + cmd + " " + value + set_answer = self.request(request) + #just check if set was no broadcast-message + if 'broadcast done' not in set_answer: + request = "get " + cmd + answer = self.request(request) + #transfer value and answer to float for better comparsion + if float(answer) != float(value) or answer is None: + logger.warning("Failed to set parameter: value: {0} cmd: {1} answer {2}".format(value, request, answer)) diff --git a/ebus/_pv_1_0_1/plugin.yaml b/ebus/_pv_1_0_1/plugin.yaml new file mode 100644 index 000000000..ce847fba2 --- /dev/null +++ b/ebus/_pv_1_0_1/plugin.yaml @@ -0,0 +1,26 @@ +# Metadata for the classic-plugin +plugin: + # Global plugin attributes + type: interface # plugin type (gateway, interface, protocol, system, web) + description: + de: 'Unterstützt eBus Heizungen (Vailant, Wolf, Kromschroeder)' + en: '' + maintainer: '?' + tester: Sandman60 +# keywords: kwd1 kwd2 # keywords, where applicable +# documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page +# support: https://knx-user-forum.de/forum/supportforen/smarthome-py + +# Following entries are for Smart-Plugins: +# version: 1.3.3 # Plugin version +# sh_minversion: 1.3 # minimum shNG version to use this plugin +# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) +# multi_instance: False + classname: eBus # class containing the plugin + +#parameters: + # Definition of parameters to be configured in etc/plugin.yaml + +#item_attributes: + # Definition of item attributes defined by this plugin + diff --git a/ebus/plugin.yaml b/ebus/plugin.yaml index ce847fba2..4973746d2 100755 --- a/ebus/plugin.yaml +++ b/ebus/plugin.yaml @@ -3,24 +3,74 @@ plugin: # Global plugin attributes type: interface # plugin type (gateway, interface, protocol, system, web) description: - de: 'Unterstützt eBus Heizungen (Vailant, Wolf, Kromschroeder)' - en: '' - maintainer: '?' + de: 'Unterstützt eBus Heizungen (z.B. Vailant, Wolf, Kromschroeder) - Dieses Plugin verbindet sich zu einem ebusd Deamon (http://www.cometvisu.de/wiki/Ebusd), welcher mit einer eBus Heizung kommuniziert. Voraussetzungen: Ein ebusd Deamon läuft auf dem Netzwerk. (Anmerkung: Der ebusd benötigt ein ebus-Interface um mit ihm zu kommunizieren.' + en: 'Supports eBus heating systems (e.g. Vailant, Wolf, Kromschroeder) - The plugin connects to a ebusd damon (http://www.cometvisu.de/wiki/Ebusd) which is communicating with eBus heatings. Requirements: running ebusd deamon on the network (note: ebusd also requires an ebus-interface)' + maintainer: '? (msinn)' tester: Sandman60 + state: develop # keywords: kwd1 kwd2 # keywords, where applicable # documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page # support: https://knx-user-forum.de/forum/supportforen/smarthome-py # Following entries are for Smart-Plugins: -# version: 1.3.3 # Plugin version -# sh_minversion: 1.3 # minimum shNG version to use this plugin -# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) -# multi_instance: False + version: 1.5.0 # Plugin version + sh_minversion: 1.5 # minimum shNG version to use this plugin + sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) + multi_instance: False + restartable: unknown classname: eBus # class containing the plugin -#parameters: + +parameters: # Definition of parameters to be configured in etc/plugin.yaml - -#item_attributes: + + host: + type: ip + default: 127.0.0.1 + description: + de: 'IP Adresse des ebusd Deamons' + en: 'ip address of ebusd deamon' + + port: + type: int + valid_min: 0 + default: 8888 + description: + de: 'Port auf dem der ebusd Deamon lauscht' + en: 'port of ebusd deamon' + + cycle: + type: int + valid_min: 0 + default: 240 + description: + de: 'Cycle Zeit zur Abfrage jedes Items' + en: 'cycle of each item' + +item_attributes: # Definition of item attributes defined by this plugin - + + ebus_cmd: + type: str + description: + de: "ebus_cmd ist das Kommando, welches durch die Telnet Verbindung zum ebusd übertragen wird - z.B. 'cir2 heat_pump_curr', 'mv yield_sum' or 'short hw_load'" + en: "ebus_cmd is the command you use though the telnet-connection to ebusd - e.g. 'cir2 heat_pump_curr', 'mv yield_sum' or 'short hw_load'" + + ebus_type: + type: str + default: 'get' + valid_list: ['get', 'set'] + valid_list_description: + de: ['get', 'set'] + en: ['Items will only be readable, i.e. sensors', 'Items are read/write. All "set"-items will be read cyclic too!'] + description: + de: 'ebus_type legt fest, ob vom ebusd Deamon nur gelesen werden soll oder ob auch Daten an ebusd übertragen werden sollen.' + en: 'ebus_type determins, if data should only be read from the ebusd deamon or if data should be written to ebusd too.' + + +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + +plugin_functions: NONE + # Definition of function interface of the plugin + From 0e0b040c5ff9ab4000e1c2dbbdaeb5e213e4bcd2 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 1 Sep 2018 02:26:55 +0200 Subject: [PATCH 203/705] UZSU now also works without rrule, small improvement --- uzsu/__init__.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index cd74049e7..0ac182611 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -81,7 +81,7 @@ class UZSU(SmartPlugin): ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.5.1" + PLUGIN_VERSION = "1.4.1" _items = {} # item buffer for all uzsu enabled items @@ -240,6 +240,7 @@ def _schedule(self, item, caller=None): cond3 = _initialized is False cond4 = _initage > 0 cond5 = isinstance(_value, float) + self._itpl = OrderedDict(itpl_list) if not cond2 and cond3 and cond4: self.logger.info("{}: Looking if there was a value set after {} for item {}".format( self._name, _timediff, item)) @@ -249,7 +250,6 @@ def _schedule(self, item, caller=None): self._set(item=item, value=_initvalue, caller='scheduler') self.logger.info("{}: Updated item {} on startup with value {} from time {}".format( self._name, item, _initvalue, datetime.fromtimestamp(_inittime/1000.0))) - self._itpl = OrderedDict(itpl_list) _itemtype = self._items[item]['interpolation'].get('itemtype') if cond2 and not REQUIRED_PACKAGE_IMPORTED: self.logger.warning("{}: Interpolation is set to {} but scipy not installed. Ignoring interpolation".format( @@ -333,13 +333,13 @@ def _get_time(self, entry, timescan): active = entry['active'] today = datetime.today() yesterday = today - timedelta(days=1) - weekbefore = today - timedelta(days=6) + weekbefore = today - timedelta(days=7) time = entry['time'] if not active: return None, None if 'date' in entry: date = entry['date'] - if 'rrule' in entry: + if 'rrule' in entry and entry['rrule']: if 'dtstart' in entry: rrule = rrulestr(entry['rrule'], dtstart=entry['dtstart']) else: @@ -381,14 +381,25 @@ def _get_time(self, entry, timescan): self.logger.debug("{}: Result parsing time (sun) {}: {}".format(self._name, time, next)) else: next = datetime.combine(today, parser.parse(time.strip()).time()).replace(tzinfo=self._timezone) - if next and next.date() == today and cond_next: + + cond1 = next.date() == today.date() + cond2 = next.date() - timedelta(days=1) == yesterday.date() + cond_next = next > datetime.now(self._timezone) and timescan == 'next' + cond_previous_today = next < datetime.now(self._timezone) and timescan == 'previous' + cond_previous_yesterday = next - timedelta(days=1) < datetime.now(self._timezone) and timescan == 'previous' + self.logger.error('next: {}, today: {}, yesterday: {}.'.format(next, today, yesterday)) + if next and cond1 and cond_next: self._itpl[next.timestamp() * 1000.0] = value self.logger.debug("{}: Return next: {}, value {}".format(self._name, next, value)) return next, value - if next and next.date() == today and cond_previous: + if next and cond1 and cond_previous_today: self._itpl[next.timestamp() * 1000.0] = value self.logger.debug("{}: Return previous: {}, value {}".format(self._name, next, value)) return next, value + if next and cond2 and cond_previous_yesterday: + self._itpl[(next - timedelta(days=1)).timestamp() * 1000.0] = value + self.logger.debug("{}: Return previous: {}, value {}".format(self._name, next - timedelta(days=1), value)) + return next - timedelta(days=1), value except Exception as e: self.logger.error("{}: Error '{}' parsing time: {}".format(self._name, time, e)) return None, None From 2b3849263724ea51a8ff2b098a826eeeacc39f44 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 1 Sep 2018 02:40:00 +0200 Subject: [PATCH 204/705] UZSU: fixed version number --- uzsu/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 0ac182611..3802b5c1c 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -81,7 +81,7 @@ class UZSU(SmartPlugin): ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.4.1" + PLUGIN_VERSION = "1.5.1" _items = {} # item buffer for all uzsu enabled items From 1725212c5661e15b8ce2131a314ee4d8e172fbb0 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 1 Sep 2018 02:44:59 +0200 Subject: [PATCH 205/705] UZSU: cleaned log msg --- uzsu/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 3802b5c1c..4e474de2f 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -387,7 +387,6 @@ def _get_time(self, entry, timescan): cond_next = next > datetime.now(self._timezone) and timescan == 'next' cond_previous_today = next < datetime.now(self._timezone) and timescan == 'previous' cond_previous_yesterday = next - timedelta(days=1) < datetime.now(self._timezone) and timescan == 'previous' - self.logger.error('next: {}, today: {}, yesterday: {}.'.format(next, today, yesterday)) if next and cond1 and cond_next: self._itpl[next.timestamp() * 1000.0] = value self.logger.debug("{}: Return next: {}, value {}".format(self._name, next, value)) From 79a88240d8e3bdc2bbbdf9d806718f73d1b15c49 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sat, 1 Sep 2018 10:58:02 +0200 Subject: [PATCH 206/705] Art-Net: Complete plugin meta data (common, parameters, items) --- artnet/plugin.yaml | 52 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/artnet/plugin.yaml b/artnet/plugin.yaml index a3d06f74c..d548d0ecb 100755 --- a/artnet/plugin.yaml +++ b/artnet/plugin.yaml @@ -3,23 +3,57 @@ plugin: # Global plugin attributes type: gateway # plugin type (gateway, interface, protocol, system, web) description: - de: 'Ansteuerung der meisten USB DMX Adapter' - en: '' + de: 'Ansteuerung der meisten USB/Netwerk DMX Adapter' + en: 'Can control most of USB/network DMX adapters' maintainer: mode2k tester: ohinckel keywords: dmx # documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page -# Following entries are for Smart-Plugins: -# version: 1.3.3 # Plugin version -# sh_minversion: 1.3 # minimum shNG version to use this plugin + version: 1.3.0 # Plugin version + sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) -# multi_instance: False + multi_instance: False classname: ArtNet # class containing the plugin -#parameters: +parameters: # Definition of parameters to be configured in etc/plugin.yaml + artnet_net: + type: int + default: 0 + description: + de: 'Gibt das ArtNet Net an' + en: 'Specifies the ArtNet Net to use' + valid_min: 0 + valid_max: 127 + artnet_subnet: + type: int + default: 0 + description: + de: 'Gibt das Art-Net Sub-Net an' + en: 'Specifies the Art-Net Sub-Net to use' + valid_min: 0 + valid_max: 15 + artnet_universe: + type: int + default: 0 + description: + de: 'Gibt das Art-Net Universe an' + en: 'Specifies the Art-Net Universe to use' + valid_min: 0 + valid_max: 15 + ip: + type: ip + default: '' + description: + de: 'Gibt die Adresse einer Art-Net Node an' + en: 'Specifies the address of a Art-Net node' + port: + type: int + default: '' + description: + de: 'Gibt den Port einer Art-Net Node an' + en: 'Specifies the port of a Art-Net node' -#item_attributes: +item_attributes: # Definition of item attributes defined by this plugin - From 56023d00fb27319bf82b0580c5317b8bbefa3ac3 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sat, 1 Sep 2018 10:58:49 +0200 Subject: [PATCH 207/705] Luxtronic2: Complete plugin meta data (common, parameters, items) --- luxtronic2/plugin.yaml | 54 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/luxtronic2/plugin.yaml b/luxtronic2/plugin.yaml index 050078cdf..23700afb4 100755 --- a/luxtronic2/plugin.yaml +++ b/luxtronic2/plugin.yaml @@ -11,16 +11,56 @@ plugin: # documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page # support: https://knx-user-forum.de/forum/supportforen/smarthome-py -# Following entries are for Smart-Plugins: -# version: 1.3.3 # Plugin version -# sh_minversion: 1.3 # minimum shNG version to use this plugin + version: 1.3.0 # Plugin version + sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) -# multi_instance: False + multi_instance: False classname: LuxBase # class containing the plugin -#parameters: +parameters: # Definition of parameters to be configured in etc/plugin.yaml + host: + type: str + description: + de: 'Gibt den Host des Gerätes an' + en: 'Specifies the host of the device' + port: + type: int + default: 8888 + description: + de: 'Gibt den Port des Gerätes an' + en: 'Specifies the port of the devices' -#item_attributes: +item_attributes: # Definition of item attributes defined by this plugin - + lux2: + type: int + description: + de: 'Gibt einen Parameterwert an, der automatisch dekodiert werden (z.B. Umwandlung Betriebsart zu einem Text)' + en: 'Specifies a parameter value which will automatically be decoded (e.g. operation mode to text)' + valid_list: + - 10 + - 11 + - 12 + - 15 + - 19 + - 20 + - 119 # Operation mode + - 151 + - 152 + lux2_a: + type: int + description: + de: 'Gibt einen Attributwert an, der ausgelesen werden soll (Zugriff ist nur lesend)' + en: 'Specifies the attribute value which should be read (only read-only access)' + lux2_c: + type: int + description: + de: 'Gibt einen berechneten Attributwert an (Zugriff ist nur lesend)' + en: 'Specifies the attribute value which should be calculated (only read-only access)' + lux2_p: + type: int + description: + de: 'Gibt einen Attributwert für einen Parameter an (Zugriff lesend und schreibend)' + en: 'Specifies the attribute value for parameter (read and write access)' + From 6e37d09ea1ed7090ebe10cc4a27a575c85c7ed83 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sat, 1 Sep 2018 11:06:14 +0200 Subject: [PATCH 208/705] Tests: Exit with error code in case tox fail --- .travis.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.sh b/.travis.sh index 567d0d9cf..c17922bd8 100755 --- a/.travis.sh +++ b/.travis.sh @@ -91,7 +91,7 @@ echo "travis_fold:end:Links" echo -e "travis_fold:start:Suite\nRunning suite" cd smarthome -tox +tox || exit 1 cd .. echo "travis_fold:end:Suite" From 7342c2db3004ae73011cb26f3dd1f1d6f291af8a Mon Sep 17 00:00:00 2001 From: msinn Date: Sat, 1 Sep 2018 11:06:22 +0200 Subject: [PATCH 209/705] Re-Added (empty) REQUIRES list to setup.py --- backend/BackendItems.py | 5 ++++- cli/plugin.yaml | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/backend/BackendItems.py b/backend/BackendItems.py index 3097c59a1..d9f931df3 100755 --- a/backend/BackendItems.py +++ b/backend/BackendItems.py @@ -143,7 +143,10 @@ def item_change_value_html(self, item_path, value): value = float(value) else: value = int(value) - item(value, caller='Backend') + if 'dict' in item.type(): + if type(value) is str: + self.logger.warning('Item type is dict, value type is str') + item(value, caller='Backend', source='item_change_value_html()') return diff --git a/cli/plugin.yaml b/cli/plugin.yaml index 5495119a0..b8a499d1a 100755 --- a/cli/plugin.yaml +++ b/cli/plugin.yaml @@ -53,6 +53,9 @@ parameters: item_attributes: NONE # Definition of item attributes defined by this plugin +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + plugin_functions: # Definition of function interface of the plugin From 87b1246ec58bcb1865249edff8a3904ca6803d4e Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sat, 1 Sep 2018 11:39:28 +0200 Subject: [PATCH 210/705] Tests: Remove deprecated Python version 3.3 from Travis configuration --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7b3895780..2b2438cbc 100755 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ sudo: false language: python python: - - "3.3" - "3.4" - "3.5" - "3.6" From 7329d8304a8241a974721572a539c12d2b018891 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sat, 1 Sep 2018 11:45:09 +0200 Subject: [PATCH 211/705] Tests: Upgrade setuptools to a recent version --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 2b2438cbc..f3fdf9a18 100755 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ env: install: - pip install tox-travis "virtualenv<14.0.0" + - pip install --upgrade setuptools script: - sh .travis.sh From bac1713e5a9883f3422383fca221e5d7043d9f9d Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sat, 1 Sep 2018 11:51:59 +0200 Subject: [PATCH 212/705] Tests: Remove setup upgrade again --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f3fdf9a18..2b2438cbc 100755 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,6 @@ env: install: - pip install tox-travis "virtualenv<14.0.0" - - pip install --upgrade setuptools script: - sh .travis.sh From 2bd9f03ef4a55cb93d183771df6c763ef657bac0 Mon Sep 17 00:00:00 2001 From: msinn Date: Sat, 1 Sep 2018 18:04:37 +0200 Subject: [PATCH 213/705] artnet: Completed metadata (declaring empty sections are indeed empty and not missing) --- artnet/plugin.yaml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/artnet/plugin.yaml b/artnet/plugin.yaml index d548d0ecb..8c66e757a 100755 --- a/artnet/plugin.yaml +++ b/artnet/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Can control most of USB/network DMX adapters' maintainer: mode2k tester: ohinckel + state: qa-passed keywords: dmx # documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page @@ -14,6 +15,7 @@ plugin: sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False + restartable: unknown classname: ArtNet # class containing the plugin parameters: @@ -44,16 +46,22 @@ parameters: valid_max: 15 ip: type: ip - default: '' description: de: 'Gibt die Adresse einer Art-Net Node an' en: 'Specifies the address of a Art-Net node' port: type: int - default: '' + valid_min: 0 description: de: 'Gibt den Port einer Art-Net Node an' en: 'Specifies the port of a Art-Net node' -item_attributes: +item_attributes: NONE # Definition of item attributes defined by this plugin + +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + +plugin_functions: NONE + # Definition of function interface of the plugin + From c6c2953e45576baea154bc9a2eba263fe67af155 Mon Sep 17 00:00:00 2001 From: msinn Date: Sat, 1 Sep 2018 18:09:10 +0200 Subject: [PATCH 214/705] luxtronic2: Completed metadata (declaring empty sections are indeed empty and not missing) --- luxtronic2/plugin.yaml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/luxtronic2/plugin.yaml b/luxtronic2/plugin.yaml index 23700afb4..47a16fc65 100755 --- a/luxtronic2/plugin.yaml +++ b/luxtronic2/plugin.yaml @@ -4,9 +4,10 @@ plugin: type: interface # plugin type (gateway, interface, protocol, system, web) description: de: 'Integration von Systemen die eine Luxtronic-Steuerung haben (z.B Heizungen)' - en: '' + en: 'Integration of systems that have a Luxtronic interface (e.g. heating systems)' maintainer: '? (2ndsky)' tester: ohinckel + state: qa-passed # keywords: kwd1 kwd2 # keywords, where applicable # documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page # support: https://knx-user-forum.de/forum/supportforen/smarthome-py @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False + restartable: unknown classname: LuxBase # class containing the plugin parameters: @@ -64,3 +66,9 @@ item_attributes: de: 'Gibt einen Attributwert für einen Parameter an (Zugriff lesend und schreibend)' en: 'Specifies the attribute value for parameter (read and write access)' +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + +plugin_functions: NONE + # Definition of function interface of the plugin + From a8d138421e8a9bc802b1ff87422008ba889bdf25 Mon Sep 17 00:00:00 2001 From: msinn Date: Sat, 1 Sep 2018 18:10:01 +0200 Subject: [PATCH 215/705] backend: Cleanup after searching for an error in dict handling --- backend/BackendItems.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/backend/BackendItems.py b/backend/BackendItems.py index d9f931df3..3eee30637 100755 --- a/backend/BackendItems.py +++ b/backend/BackendItems.py @@ -143,9 +143,6 @@ def item_change_value_html(self, item_path, value): value = float(value) else: value = int(value) - if 'dict' in item.type(): - if type(value) is str: - self.logger.warning('Item type is dict, value type is str') item(value, caller='Backend', source='item_change_value_html()') return From b50cdd6d799c35b80e0a828fa6be95d9dc5f397c Mon Sep 17 00:00:00 2001 From: msinn Date: Sat, 1 Sep 2018 18:22:16 +0200 Subject: [PATCH 216/705] apcups, smarttv, telegram: Completed metadata --- apcups/plugin.yaml | 5 ++++- smarttv/plugin.yaml | 7 +++++-- telegram/plugin.yaml | 5 ++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/apcups/plugin.yaml b/apcups/plugin.yaml index ee5a2d21e..d045fe410 100755 --- a/apcups/plugin.yaml +++ b/apcups/plugin.yaml @@ -4,7 +4,7 @@ plugin: type: interface # plugin type (gateway, interface, protocol, system, web) description: de: 'Unterstützung für smartUPS Geräte der Firma APC' - en: '' + en: 'Support for smartUPS devices sold by APC' maintainer: cmalo tester: Sandman60 state: ready @@ -51,6 +51,9 @@ item_attributes: de: 'Für eine Liste gültiger Werte, "apcaccess" auf der Kommandozeile aufrufen. Dieser Befehl gibt einen Textblock zurück, der eine Liste von ``statusname : value`` Einträgen enthält' en: 'For a list of values for this attribute call "apcaccess" on the command line. This command will give back a text block containing a list of ``statusname : value`` entries' +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + plugin_functions: NONE # Definition of function interface of the plugin diff --git a/smarttv/plugin.yaml b/smarttv/plugin.yaml index 4272aabdd..7a7df7ca8 100755 --- a/smarttv/plugin.yaml +++ b/smarttv/plugin.yaml @@ -3,8 +3,8 @@ plugin: # Global plugin attributes type: interface # plugin type (gateway, interface, protocol, system, web) description: - de: 'Anbdindung (Remote Control) von SmartTV Geräten' - en: '' + de: 'Dieses Plugin erlaubt es SmartTV Geräte wie z.B. Samsung zu steuern. Es hat zwei Implementierungen (für das alte und das neue API der TVs). Für das neue API muss auf dem TV der Zugriff akzeptiert werden, indem ein Button auf dem TV gedrückt wird, wenn der erste Request eingeht.' + en: 'The plugin allows to control SmartTVs such as Samsung. It has two implementations for old and new versions of the API on the TV. For the new version you will have to accept the access to your TV by pressing a button on your TV on the first request that comes in.' maintainer: '? (2ndsky)' tester: psilo909 state: ready @@ -65,6 +65,9 @@ item_attributes: * Define it on a string item and set it to `true`: With this configuration, every string you set to this item will be send to the SmartTV device. * Define it on a boolean item and set it to a key value: With this configuration, the specified key value is sent whenever you set the item to `true` (if the item is only for sending a specific command to the tv then you should consider using the `enforce_updates` attribute, too). It is even possible to define several keys separeted with a comma.' +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + plugin_functions: NONE # Definition of function interface of the plugin diff --git a/telegram/plugin.yaml b/telegram/plugin.yaml index df0f36f36..81cf53a46 100644 --- a/telegram/plugin.yaml +++ b/telegram/plugin.yaml @@ -4,7 +4,7 @@ plugin: type: web # plugin type (gateway, interface, protocol, system, web) description: de: 'Anbindung des Telegram Service (verwendet python-telegram-bot Package statt telepot Package)' - en: '' + en: 'Connects to the telegram service (uses python-telegram-bot package instead of telebot package)' maintainer: gamade, ivan73, bmxp # tester: state: ready @@ -61,6 +61,9 @@ item_attributes: de: 'Itemwert gegen einen regulän Ausdruck prüfen vor versenden einer Mitteilung' en: 'check a value against a condition before sending a message' +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + plugin_functions: NONE # Definition of function interface of the plugin From b842f6022b48d333a2455d38632d6d66eb22600d Mon Sep 17 00:00:00 2001 From: msinn Date: Sat, 1 Sep 2018 21:03:02 +0200 Subject: [PATCH 217/705] backend: Added display of plugin-methods to plugin page --- backend/locale/de.json | 1 + backend/locale/en.json | 1 + backend/locale/fr.json | 1 + backend/locale/pl.json | 1 + backend/webif/templates/plugins.html | 16 ++++++++++++++++ homematic/webif/templates/index.html | 2 +- kodi/__init__.py | 8 +++++--- 7 files changed, 26 insertions(+), 4 deletions(-) diff --git a/backend/locale/de.json b/backend/locale/de.json index caf4d7bca..448825500 100755 --- a/backend/locale/de.json +++ b/backend/locale/de.json @@ -52,6 +52,7 @@ "Plugin Metadaten": "Plugin Metadaten", "Verbundene Logiken": "Verbundene Logiken", "Verbundene Trigger": "Verbundene Trigger", + "vom Plugin definierte Methoden": "vom Plugin definierte Methoden", "Willkommen im Backend von": "Willkommen im Backend von", "Eigenschaft": "Eigenschaft", "IP": "IP Adresse", diff --git a/backend/locale/en.json b/backend/locale/en.json index 02025b037..1d154e471 100755 --- a/backend/locale/en.json +++ b/backend/locale/en.json @@ -52,6 +52,7 @@ "Plugin Metadaten": "Plugin Metadata", "Verbundene Logiken": "Bound Logics", "Verbundene Trigger": "Bound Triggers", + "vom Plugin definierte Methoden": "Methods defined by the plugin", "Willkommen im Backend von": "Welcome to the backend of", "Eigenschaft": "Property", "IP": "IP Address", diff --git a/backend/locale/fr.json b/backend/locale/fr.json index e65c5560b..21c359286 100755 --- a/backend/locale/fr.json +++ b/backend/locale/fr.json @@ -54,6 +54,7 @@ "Plugin Metadaten": "Métadonnées de l'extension", "Verbundene Logiken": "Logiques connexes", "Verbundene Trigger": "Déclencheurs connexes", + "vom Plugin definierte Methoden": "", "Willkommen im Backend von": "Bienvenue au Backend de", "Eigenschaft": "Propriété", "IP": "Adresse IP", diff --git a/backend/locale/pl.json b/backend/locale/pl.json index d069230e9..a004e83aa 100755 --- a/backend/locale/pl.json +++ b/backend/locale/pl.json @@ -51,6 +51,7 @@ "Plugin Metadaten": "Metadane pluginu", "Verbundene Logiken": "Powiązana Logika", "Verbundene Trigger": "Powiązane wyzwalacze", + "vom Plugin definierte Methoden": "", "Willkommen im Backend von": "Witaj w backendzie", "Eigenschaft": "Atrybut", "IP": "Adres IP", diff --git a/backend/webif/templates/plugins.html b/backend/webif/templates/plugins.html index c2c92d224..6be23934c 100755 --- a/backend/webif/templates/plugins.html +++ b/backend/webif/templates/plugins.html @@ -139,6 +139,7 @@ {% endfor %}
+ {% if p.metadata.get_itemdefinitionlist()|length > 0 %}
{{ _('Plugin spezifische Item Attribute') }}:
@@ -165,6 +166,21 @@
{% endif %} + {% if p.metadata.get_plugin_function_defstrings()|length > 0 %} +
{{ _('vom Plugin definierte Methoden') }}:
+
+ + {% set first = True %} + {% for func in p.metadata.get_plugin_function_defstrings() %} + + + + {% endfor %} +
{{ func }} +
+
+ {% endif %} +
{{ _('Plugin Metadaten') }}:
{% if p.metadata.get_mlstring('description') %} diff --git a/homematic/webif/templates/index.html b/homematic/webif/templates/index.html index 5ee6199a2..55e845a5c 100755 --- a/homematic/webif/templates/index.html +++ b/homematic/webif/templates/index.html @@ -61,7 +61,7 @@ -{% set tab1title = "" ~ p.get_shortname() ~ " Items (" ~ item_count ~ ")" %} +{% set tab1title = "" ~ p.get_shortname() ~ " Items (" ~ item_count ~ ")" ~ %} {% block bodytab1 %}
diff --git a/kodi/__init__.py b/kodi/__init__.py index 820ef9c8d..b464341e5 100755 --- a/kodi/__init__.py +++ b/kodi/__init__.py @@ -92,8 +92,10 @@ def __init__(self, sh, *args, **kwargs): # init logger self.logger = logging.getLogger(__name__) self.logger.info('Init Kodi Plugin') - self.kodi_tcp_connection = Tcp_client(host=self.get_parameter_value('host'), - port=self.get_parameter_value('port'), + self.host = self.get_parameter_value('host') + self.port = self.get_parameter_value('port') + self.kodi_tcp_connection = Tcp_client(host=self.host, + port=self.port, name='KodiTCPConnection', autoreconnect=False, connect_retries=5, @@ -137,7 +139,7 @@ def on_connect(self): # check if API is available result = self.send_kodi_rpc(method='JSONRPC.Ping') if result is None or result['result'] != 'pong': - self.logger.error('Kodi JSON-RPC API not available. Did you connect to the TCP port (default: 9090)?') + self.logger.error('Kodi JSON-RPC API not available on {}:{}'.format(self.host, self.port)) self.stop() else: # API available -> init items From 45661f2a199321df8b6c10bc36c14fdbf8453335 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sat, 1 Sep 2018 21:32:43 +0200 Subject: [PATCH 218/705] Tests: Install libudev-dev for python-openzwave --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 2b2438cbc..ff5b82cee 100755 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,8 @@ python: env: - REPOSITORY_ORIGIN=plugins +before_install: + - sudo apt-get install libudev-dev install: - pip install tox-travis "virtualenv<14.0.0" From bb05a26686712e8f934db7644cc626d219858765 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sat, 1 Sep 2018 21:53:42 +0200 Subject: [PATCH 219/705] Database: Fix path to items configuration Was renamed in 3ccfa414c3c2092b53d705d0cddd2ae02db5f18f --- database/tests/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/tests/base.py b/database/tests/base.py index 4641d7b40..9dd832103 100644 --- a/database/tests/base.py +++ b/database/tests/base.py @@ -13,7 +13,7 @@ class TestDatabaseBase(unittest.TestCase): def plugin(self): self.sh = MockSmartHome() - self.sh.with_items_from(common.BASE + '/plugins/database/tests/test_items.conf') + self.sh.with_items_from(common.BASE + '/plugins/database/tests/test_items.yaml') plugin = Database(self.sh, 'sqlite3', {'database' : ':memory:'}) for item in self.sh.return_items(): plugin.parse_item(item) From fdbc72cdec60352d9864aa1179a75fd295453f0c Mon Sep 17 00:00:00 2001 From: msinn Date: Sat, 1 Sep 2018 22:45:00 +0200 Subject: [PATCH 220/705] lib.metadata: Bugfix --- database/locale.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/database/locale.yaml b/database/locale.yaml index 2315627ab..e4eb6b683 100644 --- a/database/locale.yaml +++ b/database/locale.yaml @@ -36,6 +36,9 @@ plugin_translations: 'Die folgenden Einträge entstammen der log Tabelle mit historischen Daten für das Item {{ item_path }} (Datenbank-ID: {{ item_id }})': 'de': 'Die folgenden Einträge entstammen der log Tabelle mit historischen Daten für das Item' 'en': 'The following entries are derived from the log table with historical data for item )' + 'Die folgenden Einträge entstammen der log Tabelle mit historischen Daten für das Item': + 'de': 'Die folgenden Einträge entstammen der log Tabelle mit historischen Daten für das Item' + 'en': 'The following entries are derived from the log table with historical data for item )' 'Datenbank-ID': 'de': 'Datenbank-ID' 'en': 'Database ID' From 64f1b6b46180326e857877b00416748ee846534f Mon Sep 17 00:00:00 2001 From: msinn Date: Sun, 2 Sep 2018 10:10:48 +0200 Subject: [PATCH 221/705] dlms: Metadata changes & moved old version to standard _pv (previous version) folder --- {dlms_1 => dlms/_pv_1_2_5}/README.md | 0 {dlms_1 => dlms/_pv_1_2_5}/__init__.py | 0 {dlms_1 => dlms/_pv_1_2_5}/plugin.yaml | 7 +++++++ {dlms_1 => dlms/_pv_1_2_5}/requirements.txt | 0 dlms/plugin.yaml | 9 +++++++++ 5 files changed, 16 insertions(+) rename {dlms_1 => dlms/_pv_1_2_5}/README.md (100%) rename {dlms_1 => dlms/_pv_1_2_5}/__init__.py (100%) rename {dlms_1 => dlms/_pv_1_2_5}/plugin.yaml (95%) rename {dlms_1 => dlms/_pv_1_2_5}/requirements.txt (100%) diff --git a/dlms_1/README.md b/dlms/_pv_1_2_5/README.md similarity index 100% rename from dlms_1/README.md rename to dlms/_pv_1_2_5/README.md diff --git a/dlms_1/__init__.py b/dlms/_pv_1_2_5/__init__.py similarity index 100% rename from dlms_1/__init__.py rename to dlms/_pv_1_2_5/__init__.py diff --git a/dlms_1/plugin.yaml b/dlms/_pv_1_2_5/plugin.yaml similarity index 95% rename from dlms_1/plugin.yaml rename to dlms/_pv_1_2_5/plugin.yaml index cc6445b21..e571bcc03 100644 --- a/dlms_1/plugin.yaml +++ b/dlms/_pv_1_2_5/plugin.yaml @@ -85,3 +85,10 @@ item_attributes: description: de: 'In Items mit diesem Attribut wird der komplette Auslesepuffer abgelegt für eigene Untersuchungen' en: 'in items with this attribut the complete readout will be set for examination with own logics' + +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + +plugin_functions: NONE + # Definition of function interface of the plugin + diff --git a/dlms_1/requirements.txt b/dlms/_pv_1_2_5/requirements.txt similarity index 100% rename from dlms_1/requirements.txt rename to dlms/_pv_1_2_5/requirements.txt diff --git a/dlms/plugin.yaml b/dlms/plugin.yaml index d889f8e4f..8e09ac4b0 100644 --- a/dlms/plugin.yaml +++ b/dlms/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Support for smartmeter using DLMS (Device Language Message Specification, IEC 62056-21) and delivering OBIS codes' maintainer: bmxp (JuMi2006) # tester: # Who tests this plugin? + state: ready keywords: dlms obis smartmeter # documentation: https://github.com/smarthomeNG/smarthome/wiki/DLMS-Plugin # url of documentation (wiki) page # support: https://knx-user-forum.de/forum/supportforen/smarthome-py @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.4 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance + restartable: unknown classname: DLMS # class containing the plugin parameters: @@ -97,3 +99,10 @@ item_attributes: description: de: 'In Items mit diesem Attribut wird der komplette Auslesepuffer abgelegt für eigene Untersuchungen' en: 'in items with this attribut the complete readout will be set for examination with own logics' + +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + +plugin_functions: NONE + # Definition of function interface of the plugin + From 5496bb283528d293d032c80d5042215a2200d527 Mon Sep 17 00:00:00 2001 From: msinn Date: Sun, 2 Sep 2018 11:22:58 +0200 Subject: [PATCH 222/705] onewire, nokia_health: Update metadata --- nokia_health/plugin.yaml | 8 ++++++++ onewire/plugin.yaml | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/nokia_health/plugin.yaml b/nokia_health/plugin.yaml index 67428ab75..d7534a8fa 100644 --- a/nokia_health/plugin.yaml +++ b/nokia_health/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Usage of the nokia health api with oauth2' maintainer: 'psilo909' tester: 'psilo909' + state: ready keywords: health documentation: 'http://smarthomeng.de/user/plugins_doc/config/nokia_health.html' support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/1141179-nokia-health-plugin' @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance + restartable: unknown classname: NokiaHealth # class containing the plugin parameters: @@ -81,3 +83,9 @@ item_attributes: - 'token_type' - 'refresh_token' +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + +plugin_functions: NONE + # Definition of function interface of the plugin + diff --git a/onewire/plugin.yaml b/onewire/plugin.yaml index 7f7c37251..898c95432 100755 --- a/onewire/plugin.yaml +++ b/onewire/plugin.yaml @@ -6,10 +6,13 @@ plugin: en: '1-Wire support via owserver' fr: 'Support de 1-Wire à travers owserver' maintainer: cmalo (mknx) + # tester: + state: ready keywords: 1wire onewire version: 1.3.2 # Plugin version sh_minversion: 1.3 # minimum shNG version to use this plugin multi_instance: False + restartable: unknown classname: OneWire # class containing the plugin parameters: @@ -82,3 +85,25 @@ item_attributes: en: 'Sensor type. See plugin readme for supported types' fr: 'Type du capteur. Voir dans readme du plugin pour formats supportés' +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + +plugin_functions: + # Definition of function interface of the plugin + + ibutton_hook: + type: void + description: + de: 'Dieses ist eine spezielle Funktion, die aufgerufen wird, wenn ein unbekannter iButton an den Bus gehängt wird. Falls der unbekannte iButton bereits erkannt wurde, wird die Id gecached und die Funktion nicht erneut aufgerufen. Der Cache wird alle 10 Minuten geleert. Die Funktion muss zwei Argumente akzeptieren. - Um die Funktionalität zu nutzen, muss eine (sinnvolle) Funktion zugewiesen werden. (z.B.: sh.ow.ibutton_hook = intruder_alert)' + en: 'This is a special function which is called if an unknown ibutton is attached to the bus. If the unknown ibutton is already seen, the id will be cached and the function is not called again. The cache will be reset every ten minutes. The function must take two arguments. The first will be the id of the ibutton and the second is the item of the ibutton busmaster (e.g. sh.home.key_hanger). - To use it you have to assign a (useful) function. (e.g.: sh.ow.ibutton_hook = intruder_alert)' + parameter: + ibutton: + type: str + description: + de: 'Id des iButten der benutzt wurde' + en: 'Id of the iButton that was used' + item: + type: str + description: + de: 'Item des Busmasters an dem der iButton genutzt wurde' + en: 'item of the busmaster at which the ibutton was used' From 0f576ed3003e3399775c28018c38c77806baa3e4 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sun, 2 Sep 2018 11:23:36 +0200 Subject: [PATCH 223/705] Tests: Configure Python 3.7 --- .travis.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index ff5b82cee..bf9e439b4 100755 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,13 @@ sudo: false language: python -python: - - "3.4" - - "3.5" - - "3.6" + +matrix: + include: + - python: 3.4 + - python: 3.5 + - python: 3.6 + - python: 3.7 + dist: xenial env: - REPOSITORY_ORIGIN=plugins From a9da498ce31c4ea3a579c3099965385de026f8a7 Mon Sep 17 00:00:00 2001 From: msinn Date: Sun, 2 Sep 2018 13:10:41 +0200 Subject: [PATCH 224/705] avdevice: Additions to metadata --- avdevice/plugin.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/avdevice/plugin.yaml b/avdevice/plugin.yaml index 218ae60b9..0f00bf6f1 100755 --- a/avdevice/plugin.yaml +++ b/avdevice/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Controlling AV devices via TCP/IP and RS232' maintainer: onkelandy tester: Foxi352 # Who tests this plugin? + state: ready keywords: av denon pioneer epson oppo player amp receiver projector rs232 telnet tcpip # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1097870-neues-plugin-av-device-f%C3%BCr-yamaha-pioneer-denon-etc @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance + restartable: unknown classname: AVDevice # class containing the plugin parameters: @@ -332,3 +334,10 @@ item_attributes: description: de: 'Über dieses Attribut lässt sich ein anderes Item auf einen bestimmten Wert setzen, sobald das Plugin sich mit dem Gerät verbindet. Der Wert muss bereits als avdevice-Attribut bei einem anderen Item hinterlegt sein.' en: 'This attribute changes the value of another item to a specific value as soon as the plugin connects to the device. The value has to exist as an avdevice-attribute on another item.' + +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + +plugin_functions: NONE + # Definition of function interface of the plugin + From dcab0fbbcb0d163ba8cffce2d4577bd979937590 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sun, 2 Sep 2018 21:00:43 +0200 Subject: [PATCH 225/705] XMPP: Convert plugin to SmartPlugin and extend plugin metadata --- xmpp/__init__.py | 17 +++++++++-------- xmpp/plugin.yaml | 27 ++++++++++++++++++++------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/xmpp/__init__.py b/xmpp/__init__.py index f102e9f58..91e72060b 100755 --- a/xmpp/__init__.py +++ b/xmpp/__init__.py @@ -24,16 +24,17 @@ ######################################################################### import logging - -logger = logging.getLogger() - import sleekxmpp -logging.basicConfig(level=logging.DEBUG) +from lib.model.smartplugin import * + +class XMPP(SmartPlugin): + PLUGIN_VERSION = "1.4.0" + ALLOW_MULTIINSTANCE = False -class XMPP: def __init__(self, smarthome, jid, password, logic='XMPP'): + self.logger = logging.getLogger(__name__) self.xmpp = sleekxmpp.ClientXMPP(jid, password) self.xmpp.add_event_handler("session_start", self.handleXMPPConnected) self.xmpp.add_event_handler("message", self.handleIncomingMessage) @@ -48,7 +49,7 @@ def run(self): def stop(self): self._run = False self.alive = False - logger.info("Shutting Down XMPP Client") + self.logger.info("Shutting Down XMPP Client") self.xmpp.disconnect(wait=False) def parse_item(self, item): @@ -61,7 +62,7 @@ def __call__(self, to, msgsend): try: self.send(to, msgsend, mt='chat') except Exception as e: - logger.error("XMPP: Could not send message {} to {}: {}".format(msgsend, to, e)) + self.logger.error("XMPP: Could not send message {} to {}: {}".format(msgsend, to, e)) finally: try: pass @@ -99,7 +100,7 @@ def send(self, to, msgsend, mt='chat'): msgsend->mbody = body of the message eg 'Hello world' mt->mtype = message type, could be 'chat' or 'groupchat' """ - logger.info("Sending message via XMPP. To: {0}\t Message: {1}".format(to, msgsend)) + self.logger.info("Sending message via XMPP. To: {0}\t Message: {1}".format(to, msgsend)) self.xmpp.send_message(mto=to, mbody=str(msgsend), mtype=mt) diff --git a/xmpp/plugin.yaml b/xmpp/plugin.yaml index 65ca76e83..e03b58615 100755 --- a/xmpp/plugin.yaml +++ b/xmpp/plugin.yaml @@ -4,22 +4,35 @@ plugin: type: protocol # plugin type (gateway, interface, protocol, system, web) description: de: 'Unterstützung des Extensible Messaging and Presence Protocol (XMPP). Unterstützt z.Zt. nur das Senden von Nachrichten' - en: '' + en: 'Support for the Extensible Messaging and Presence Protocol (XMPP). Currently only message sending supported' maintainer: '? (Skender Haxhimolla)' -# tester: efgh # Who tests this plugin? + tester: ohinckel # Who tests this plugin? # keywords: kwd1 kwd2 # keywords, where applicable # documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page # Following entries are for Smart-Plugins: -# version: 1.3.3 # Plugin version -# sh_minversion: 1.3 # minimum shNG version to use this plugin + version: 1.3.3 # Plugin version + sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) -# multi_instance: False + multi_instance: False classname: XMPP # class containing the plugin -#parameters: +parameters: # Definition of parameters to be configured in etc/plugin.yaml + jid: + type: str + mandatory: True + description: + de: 'Gibt den Benutzernamen / JID des zu nutzenden Accounts an' + en: 'Specifies the username / JID of the account to use' + password: + type: str + mandatory: True + hide: True + description: + de: 'Gibt das Passwort für den zu nutzenden Account an' + en: 'Specifies the password of the account to use' -#item_attributes: +item_attributes: NONE # Definition of item attributes defined by this plugin From e6f21516a75f20bab728bafbaafd22dea51acd61 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sun, 2 Sep 2018 21:23:54 +0200 Subject: [PATCH 226/705] Database: Add simple script to convert settings from SQLite to database --- database/tools/sqlite2db_config.py | 58 ++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 database/tools/sqlite2db_config.py diff --git a/database/tools/sqlite2db_config.py b/database/tools/sqlite2db_config.py new file mode 100644 index 000000000..168b52985 --- /dev/null +++ b/database/tools/sqlite2db_config.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2018- Oliver Hinckel github@ollisnet.de +######################################################################### +# This file is part of SmartHomeNG +# https://github.com/smarthomeNG/smarthome +# http://knx-user-forum.de/ +# +# SmartHomeNG is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# SmartHomeNG is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with SmartHomeNG. If not, see . +######################################################################### + + +""" +This will migrate the configuration file using sqlite settings to +settings for the database plugin (e.g sqlite=yes to database=yes) + +The result is printed to stdout +""" + +import os +import re +import argparse + + +def convert_config(filename): + with open(filename, 'r') as f: + data = f.read() + data = re.sub(r'sqlite([\w\s@]*)(=|:)(\s*)(\w+)', r'database\1\2\3\4', data) + print(data) + +if __name__ == '__main__': + + parser = argparse.ArgumentParser(add_help=False) + group = parser.add_mutually_exclusive_group() + group.add_argument('-c', '--config', dest='config', help='the configuration file to convert') + args = parser.parse_args() + + if args.config: + convert_config(args.config) + else: + print('') + print(os.path.basename(__file__) + ' - Converts the configuration file for database plugin') + print('') + parser.print_help() + print() + From 9d947548a5aabfa449d5ea12f955d6b7a8cfc4e6 Mon Sep 17 00:00:00 2001 From: msinn Date: Sun, 2 Sep 2018 22:39:21 +0200 Subject: [PATCH 227/705] xmpp: Added plugin-function description to metadata --- xmpp/plugin.yaml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/xmpp/plugin.yaml b/xmpp/plugin.yaml index e03b58615..b35298658 100755 --- a/xmpp/plugin.yaml +++ b/xmpp/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Support for the Extensible Messaging and Presence Protocol (XMPP). Currently only message sending supported' maintainer: '? (Skender Haxhimolla)' tester: ohinckel # Who tests this plugin? + state: ready # keywords: kwd1 kwd2 # keywords, where applicable # documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False + restartable: unknown classname: XMPP # class containing the plugin parameters: @@ -36,3 +38,31 @@ parameters: item_attributes: NONE # Definition of item attributes defined by this plugin +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + +plugin_functions: + # Definition of function interface of the plugin + send: + description: + de: 'Eine Messgae via xmpp senden' + en: 'Send a message via xmpp' + parameter: + to: + type: str + description: + de: "An wen, z.B. 'skender@haxhimolla.im'" + en: "To whom e.g. 'skender@haxhimolla.im'" + msgsend: + type: str + description: + de: "Text der Message, z.B. 'Hello world'" + en: "body of the message e.g. 'Hello world'" + mt: + type: str + default: 'chat' + valid_list: ['chat', 'groupchat'] + description: + de: "Message Typ, kann 'chat' oder 'groupchat' sein" + en: "message type, could be 'chat' or 'groupchat'" + From 202e641c40502c256281c40c11bd128660c59226 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Mon, 3 Sep 2018 16:03:25 +0200 Subject: [PATCH 228/705] supports relative item configuration --- uzsu/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 4e474de2f..52580e380 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -156,12 +156,15 @@ def parse_item(self, item): can be sent to the knx with a knx write function within the knx plugin. """ if self.has_iattr(item.conf, ITEM_TAG[0]): + item.expand_relativepathes(ITEM_TAG[0], '', '') self._items[item] = item() try: self._items[item]['interpolation']['initialized'] = False + item(self._items[item]) except Exception: self._items[item]['interpolation'] = {} self._items[item]['interpolation']['initialized'] = False + item(self._items[item]) return self.update_item def update_item(self, item, caller=None, source=None, dest=None): From f832560ae5cd31ebe52b43f30e95ec5f10c61ae4 Mon Sep 17 00:00:00 2001 From: msinn Date: Tue, 4 Sep 2018 21:14:16 +0200 Subject: [PATCH 229/705] lib.item: Changed the way to reference an attibute's value from an attribute of a child item --- homematic/__init__.py | 1 + homematic/webif/templates/index.html | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/homematic/__init__.py b/homematic/__init__.py index 1c0f200e7..f3e8d4928 100755 --- a/homematic/__init__.py +++ b/homematic/__init__.py @@ -197,6 +197,7 @@ def parse_item(self, item): with the item, caller, source and dest as arguments and in case of the knx plugin the value can be sent to the knx with a knx write function within the knx plugin. """ + item.expand_relativepathes('test_attr', "", "") if self.has_iattr(item.conf, 'hm_address'): init_error = False # self.logger.debug("parse_item{}: {}".format(self.log_instance_str, item)) diff --git a/homematic/webif/templates/index.html b/homematic/webif/templates/index.html index 55e845a5c..5ee6199a2 100755 --- a/homematic/webif/templates/index.html +++ b/homematic/webif/templates/index.html @@ -61,7 +61,7 @@ -{% set tab1title = "" ~ p.get_shortname() ~ " Items (" ~ item_count ~ ")" ~ %} +{% set tab1title = "" ~ p.get_shortname() ~ " Items (" ~ item_count ~ ")" %} {% block bodytab1 %}
From 157f0c54ad61066f13915945a8f6511369d59384 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Wed, 5 Sep 2018 20:06:30 +0200 Subject: [PATCH 230/705] Database: Use current timestamp for new item entry As discussed in https://github.com/smarthomeNG/smarthome/issues/262#issuecomment-418766452 --- database/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/database/__init__.py b/database/__init__.py index 03b61823b..a4d70b474 100644 --- a/database/__init__.py +++ b/database/__init__.py @@ -117,11 +117,10 @@ def parse_item(self, item): if cache is not None: value = self._item_value_tuple_rev(item.type(), cache[COL_ITEM_VAL_STR:COL_ITEM_VAL_BOOL+1]) last_change = self._datetime(cache[COL_ITEM_TIME]) - last_change_ts = self._timestamp(last_change) prev_change = self._fetchone('SELECT MAX(time) from {log} WHERE item_id = :id', {'id':cache[COL_ITEM_ID]}, cur=cur) if value is not None and prev_change is not None: item.set(value, 'Database', prev_change=self._datetime(prev_change[0]), last_change=last_change) - self._buffer_insert(item, [(last_change_ts, None, value)]) + self._buffer_insert(item, [(self._timestamp(self.shtime.now()), None, value)]) except Exception as e: self.logger.error("Reading cache value from database for {} failed: {}".format(item.id(), e)) cur.close() From 59e4b5728d2117b83cf13899abfc06ee81883e6f Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Wed, 5 Sep 2018 21:31:51 +0200 Subject: [PATCH 231/705] Database: Add plugin methods to plugin meta data --- database/plugin.yaml | 350 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 350 insertions(+) diff --git a/database/plugin.yaml b/database/plugin.yaml index 20fba6c6c..c7c1402e3 100755 --- a/database/plugin.yaml +++ b/database/plugin.yaml @@ -54,4 +54,354 @@ item_attributes: plugin_functions: # Definition of function interface of the plugin + id: + description: + de: 'Liefert für das angegebene Item die Datenbank-ID zurück' + en: 'Return the database ID for the given item' + parameter: + item: + type: foo + description: + de: "Das Item-Objekt" + en: "An item object" + + db: + description: + de: 'Liefert das Lowlevel Datenbank-Objekt zurück' + en: 'Returns the low-level database object' + dump: + description: + de: 'Erzeugt einen Datenbank-Dump für angegebene Kriterien' + en: 'Creates a database dump for given criterias' + parameter: + dumpfile: + type: str + description: + de: "Dateiname in die der Dump geschrieben werden soll" + en: "Filename to write dump to" + id: + type: int + description: + de: "Dump auf angegebene Item-ID eingeschränken (optional)" + en: "Restrict dump to given item ID (optional)" + time: + type: int + description: + de: "Dump auf die angegebene Zeit eingeschränken (optional)" + en: "Restrict dump to given time (optional)" + time_start: + type: int + description: + de: "Dump auf die Startzeit eingeschränken (optional)" + en: "Restrict dump to given start time (optional)" + time_end: + type: int + description: + de: "Dump auf die Endzeit eingeschränken (optional)" + en: "Restrict dump to given end time (optional)" + changed: + type: int + description: + de: "Dump auf die angegebene Zeit einer Änderung eingeschränken (optional)" + en: "Restrict dump to given time of change (optional)" + changed_start: + type: int + description: + de: "Dump auf die angegebene Startzeit von Änderungen eingeschränken (optional)" + en: "Restrict dump to given start time of changes (optional)" + changed_end: + type: int + description: + de: "Dump auf die angegebene Endzeit von Änderungen eingeschränken (optional)" + en: "Restrict dump to given end time of changes (optional)" + cur: + type: foo + description: + de: "Ein Datenbankcursor Objekt, falls vorhanden (optional)" + en: "A database cursor object if available (optional)" + insertLog: + description: + de: 'Log-Datenbankeintrag für angegebene Datenbank-ID anlegen' + en: 'Create database log record for given database ID' + parameter: + id: + type: int + description: + de: "Datenbank-ID des Items für das ein Eintrag angelegt werden soll" + en: "Database ID of item to create a record for" + time: + type: int + description: + de: "Zeitpunkt an dem der Wert aktiv war" + en: "Time for the given value" + duration: + type: int + description: + de: "Zeitintervall für den der Wert aktiv war" + en: "Time duration for the given value" + val: + type: str + description: + de: "Der Wert der in die Datenbank geschrieben werden soll" + en: "The value to write to the database" + it: + type: str + description: + de: "Der Item-Typ des Wertes ('str', 'num', 'bool')" + en: "The item type of the value ('str', 'num', 'bool')" + changed: + type: int + description: + de: "Zeitstempel der Änderung" + cur: + type: foo + description: + de: "Ein Datenbankcursor Objekt, falls vorhanden (optional)" + en: "A database cursor object if available (optional)" + en: "Timestamp of change" + updateLog: + description: + de: 'Log-Datenbankeintrag für angegebene Datenbank-ID aktualisieren' + en: 'Update database log record for given database ID' + parameter: + id: + type: int + description: + de: "Datenbank-ID des Items für das der Eintrag aktualisiert werden soll" + en: "Database ID of item to update the record for" + time: + type: int + description: + de: "Zeitpunkt an dem der Wert aktiv war" + en: "Time for the given value" + duration: + type: int + description: + de: "Zeitintervall für den der Wert aktiv war" + en: "Time duration for the given value" + val: + type: str + description: + de: "Der Wert der in die Datenbank geschrieben werden soll" + en: "The value to write to the database" + it: + type: str + description: + de: "Der Item-Typ des Wertes ('str', 'num', 'bool')" + en: "The item type of the value ('str', 'num', 'bool')" + changed: + type: int + description: + de: "Zeitstempel der Änderung" + cur: + type: foo + description: + de: "Ein Datenbankcursor Objekt, falls vorhanden (optional)" + en: "A database cursor object if available (optional)" + en: "Timestamp of change" deleteLog: + readLog: + description: + de: 'Log-Datenbankeintrag für angegebene Datenbank-ID auslesen' + en: 'Read database log record for given database ID' + parameter: + id: + type: int + description: + de: "Datenbank-ID des Items für das der Eintrag aktualisiert werden soll" + en: "Database ID of item to update the record for" + time: + type: int + description: + de: "Zeitpunkt an dem der Wert aktiv war" + en: "Time for the given value" + deleteLog: + description: + de: 'Log-Datenbankeinträge für angegebene Datenbank-ID löschen' + en: 'Delete database log records for given database ID' + parameter: + id: + type: int + description: + de: "Datenbank-ID für die Einträge gelöscht werden sollen" + en: "Database ID of item to delete the records for" + time: + type: int + description: + de: "Löschen auf angegebene Zeit eingeschränken (optional)" + en: "Restrict deletion of records to given time (optional)" + time_start: + type: int + description: + de: "Löschen auf angegebene Startzeit eingeschränken eingeschränken (optional)" + en: "Restrict deletion of records to given start time (optional)" + time_end: + type: int + description: + de: "Löschen auf angegebene Endzeit eingeschränken eingeschränken (optional)" + en: "Restrict deletion of records to given end time (optional)" + changed: + type: int + description: + de: "Löschen auf angegebene Änderungszeit eingeschränken (optional)" + en: "Restrict deletion of records to given change time (optional)" + changed_start: + type: int + description: + de: "Löschen auf angegebene Start der Änderungszeit eingeschränken eingeschränken (optional)" + en: "Restrict deletion of records to given start time of changes (optional)" + changed_end: + type: int + description: + de: "Löschen auf angegebene Ende der Änderungszeit eingeschränken eingeschränken (optional)" + en: "Restrict deletion of records to given end time of changes (optional)" + cur: + type: foo + description: + de: "Ein Datenbankcursor Objekt, falls vorhanden (optional)" + en: "A database cursor object if available (optional)" + en: "Timestamp of change" deleteLog: + readLogs: + description: + de: 'Log-Datenbankeinträge für angegebene Datenbank-ID auslesen' + en: 'Read database log records for given database ID' + parameter: + id: + type: int + description: + de: "Datenbank-ID des Items für das der Eintrag aktualisiert werden soll" + en: "Database ID of item to update the record for" + time: + type: int + description: + de: "Auslesen auf angegebene Zeit eingeschränken (optional)" + en: "Restrict reading of records to given time (optional)" + time_start: + type: int + description: + de: "Auslesen auf angegebene Startzeit eingeschränken eingeschränken (optional)" + en: "Restrict reading of records to given start time (optional)" + time_end: + type: int + description: + de: "Auslesen auf angegebene Endzeit eingeschränken eingeschränken (optional)" + en: "Restrict reading of records to given end time (optional)" + changed: + type: int + description: + de: "Auslesen auf angegebene Änderungszeit eingeschränken (optional)" + en: "Restrict reading of records to given change time (optional)" + changed_start: + type: int + description: + de: "Auslesen auf angegebene Start der Änderungszeit eingeschränken eingeschränken (optional)" + en: "Restrict reading of records to given start time of changes (optional)" + changed_end: + type: int + description: + de: "Auslesen auf angegebene Ende der Änderungszeit eingeschränken eingeschränken (optional)" + en: "Restrict reading of records to given end time of changes (optional)" + cur: + type: foo + description: + de: "Ein Datenbankcursor Objekt, falls vorhanden (optional)" + en: "A database cursor object if available (optional)" + insertItem: + description: + de: 'Item-Datenbankeintrag für angegebene Datenbank-ID anlegen' + en: 'Create database item record for given database ID' + parameter: + name: + type: str + description: + de: "Name des Items für das ein Eintrag angelegt werden soll" + en: "name of item to create a record for" + cur: + type: foo + description: + de: "Ein Datenbankcursor Objekt, falls vorhanden (optional)" + en: "A database cursor object if available (optional)" + updateItem: + description: + de: 'Item-Datenbankeintrag für angegebene Datenbank-ID aktualisieren' + en: 'Update database item record for given database ID' + parameter: + id: + type: int + description: + de: "Datenbank-ID des Items für das der Eintrag aktualisiert werden soll" + en: "Database ID of item to update the record for" + time: + type: int + description: + de: "Zeitpunkt an dem der Wert aktiv war" + en: "Time for the given value" + duration: + type: int + description: + de: "Zeitintervall für den der Wert aktiv war" + en: "Time duration for the given value" + val: + type: str + description: + de: "Der Wert der in die Datenbank geschrieben werden soll" + en: "The value to write to the database" + it: + type: str + description: + de: "Der Item-Typ des Wertes ('str', 'num', 'bool')" + en: "The item type of the value ('str', 'num', 'bool')" + changed: + type: int + description: + de: "Zeitstempel der Änderung" + cur: + type: foo + description: + de: "Ein Datenbankcursor Objekt, falls vorhanden (optional)" + en: "A database cursor object if available (optional)" + + readItem: + description: + de: 'Item-Datenbankeintrag für angegebene Datenbank-ID auslesen' + en: 'Read database item record for given database ID' + parameter: + id: + type: int + description: + de: "Datenbank-ID des Items für das der Eintrag ausgelesen werden soll" + en: "Database ID of item to read the record for" + cur: + type: foo + description: + de: "Ein Datenbankcursor Objekt, falls vorhanden (optional)" + en: "A database cursor object if available (optional)" + readItems: + description: + de: 'Item-Datenbankeinträge auslesen' + en: 'Read database item records' + parameter: + id: + type: int + description: + de: "Datenbank-ID des Items für das der Eintrag ausgelesen werden soll" + en: "Database ID of item to read the record for" + cur: + type: foo + description: + de: "Ein Datenbankcursor Objekt, falls vorhanden (optional)" + en: "A database cursor object if available (optional)" + deleteItem: + description: + de: 'Item-Datenbankeintrag für angegebene Datenbank-ID löschen' + en: 'Delete database item record for given database ID' + parameter: + id: + type: int + description: + de: "Datenbank-ID des Items für das der Eintrag gelöscht werden soll" + en: "Database ID of item to delete the record for" + cleanup: + description: + de: 'Datenbank aufräumen (löscht ungenutzte Item/Log Einträge aus der Datenbank)' + en: 'Cleanup database (deletes unused item/log records in the database)' From 3e395d74c6ce69417501348b52dc6a95477441ec Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Thu, 6 Sep 2018 17:18:25 +0200 Subject: [PATCH 232/705] small fixes --- gpio/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gpio/__init__.py b/gpio/__init__.py index cba826b05..4026f343b 100755 --- a/gpio/__init__.py +++ b/gpio/__init__.py @@ -69,7 +69,7 @@ def get_sensors(self, sensor): self.logger.warning("{}: Problem reading sensor: {}".format(self._name, e)) def run(self): - self.logger.debug("{}: run method called") + self.logger.debug("{}: run method called".format(self._name)) self.alive = True for item in self._items: if self.has_iattr(item.conf, 'gpio_in'): @@ -79,7 +79,7 @@ def run(self): self._initdict[sensor] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f") except Exception: self._initdict[sensor] = False - item(value, 'GPIO', 'gpio_init') + item(value) GPIO.add_event_detect(sensor, GPIO.BOTH, callback=self.get_sensors) self.logger.info("{}: Adding Event Detection for Pin {}. Initial value is {}".format( self._name, sensor, value)) @@ -103,7 +103,7 @@ def parse_item(self, item): GPIO.setup(out_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) self._itemsdict[out_pin] = item value = GPIO.input(out_pin) - item(value, 'GPIO', 'gpio_init') + item(value) GPIO.add_event_detect(out_pin, GPIO.BOTH, callback=self.get_sensors) self.logger.info("{}: Adding Event Detection for Output Pin {}. Initial value is {}".format( self._name, out_pin, value)) From 96be53ab0f73b61eebd078a66f09e5cadc2d8cb6 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Thu, 6 Sep 2018 18:31:45 +0200 Subject: [PATCH 233/705] Database: Fix text snippets in plugin metadata Thanks to @onkelandy --- database/plugin.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/database/plugin.yaml b/database/plugin.yaml index c7c1402e3..d82d80a6d 100755 --- a/database/plugin.yaml +++ b/database/plugin.yaml @@ -153,6 +153,7 @@ plugin_functions: type: int description: de: "Zeitstempel der Änderung" + en: "Time of change" cur: type: foo description: @@ -193,12 +194,12 @@ plugin_functions: type: int description: de: "Zeitstempel der Änderung" + en: "Time of change" cur: type: foo description: de: "Ein Datenbankcursor Objekt, falls vorhanden (optional)" en: "A database cursor object if available (optional)" - en: "Timestamp of change" deleteLog: readLog: description: de: 'Log-Datenbankeintrag für angegebene Datenbank-ID auslesen' @@ -354,6 +355,7 @@ plugin_functions: type: int description: de: "Zeitstempel der Änderung" + en: "Time of change" cur: type: foo description: From 35bb34b61a3e1c08d8c8440290b13360ca5b86a6 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Thu, 6 Sep 2018 18:39:57 +0200 Subject: [PATCH 234/705] Database: Fix more errors in plugin meta data --- database/plugin.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/database/plugin.yaml b/database/plugin.yaml index d82d80a6d..8d8f6cdc8 100755 --- a/database/plugin.yaml +++ b/database/plugin.yaml @@ -159,7 +159,6 @@ plugin_functions: description: de: "Ein Datenbankcursor Objekt, falls vorhanden (optional)" en: "A database cursor object if available (optional)" - en: "Timestamp of change" updateLog: description: de: 'Log-Datenbankeintrag für angegebene Datenbank-ID aktualisieren' @@ -260,7 +259,6 @@ plugin_functions: description: de: "Ein Datenbankcursor Objekt, falls vorhanden (optional)" en: "A database cursor object if available (optional)" - en: "Timestamp of change" deleteLog: readLogs: description: de: 'Log-Datenbankeinträge für angegebene Datenbank-ID auslesen' From 4cd80f16df33961451b7282f23213381621809ab Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Thu, 6 Sep 2018 20:53:59 +0200 Subject: [PATCH 235/705] added sunrise and sunset values for uzsugraph --- uzsu/__init__.py | 69 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 17 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 52580e380..8997a1c9c 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -96,6 +96,7 @@ def __init__(self, smarthome): self._name = self.get_fullname() self._timezone = Shtime.get_instance().tzinfo() self._sh = smarthome + self._uzsu_sun = None self.logger.info('{}: Init with timezone {}'.format(self._name, self._timezone)) if not REQUIRED_PACKAGE_IMPORTED: self.logger.error("{}: Unable to import Python package 'scipy'" @@ -109,6 +110,9 @@ def run(self): """ self.logger.debug('{}: run method called'.format(self._name)) self.alive = True + self.scheduler_add('uzsu_sunupdate', self._update_all_suns, value={'caller': 'scheduler'}, cron='0 0 * *') + self.scheduler_trigger('uzsu_sunupdate') + self.logger.info('{}: Triggering sun update and scheduling for midnight'.format(self._name)) # if you want to create child threads, do not make them daemon = True! # They will not shutdown properly. (It's a python bug) @@ -127,6 +131,24 @@ def stop(self): self.logger.debug('{}: stop method called'.format(self._name)) self.alive = False + def _update_all_suns(self, caller=None): + for item in self._items: + self._update_sun(item) + + def _update_sun(self, item, caller=None): + self._uzsu_sun = self._create_sun() + self._items[item] = item() + _sunrise = self._uzsu_sun.rise() + _sunset = self._uzsu_sun.set() + if _sunrise.tzinfo == tzutc(): + _sunrise = _sunrise.astimezone(self._timezone) + if _sunset.tzinfo == tzutc(): + _sunset = _sunset.astimezone(self._timezone) + self._items[item]['sunrise'] = '{:02}:{:02}'.format(_sunrise.hour, _sunrise.minute) + self._items[item]['sunset'] = '{:02}:{:02}'.format(_sunset.hour, _sunset.minute) + self.logger.debug('{}: Updating sun entries for item {}, called by {}. sunrise: {}, sunset: {}'.format( + self._name, item, caller, self._items[item]['sunrise'], self._items[item]['sunset'])) + def _add_type(self, item): try: _uzsuitem = self.itemsApi.return_item(self.get_iattr_value(item.conf, ITEM_TAG[0])) @@ -165,6 +187,7 @@ def parse_item(self, item): self._items[item]['interpolation'] = {} self._items[item]['interpolation']['initialized'] = False item(self._items[item]) + self.logger.debug('{}: Dict for item {} is: {}'.format(self._name, item, self._items[item])) return self.update_item def update_item(self, item, caller=None, source=None, dest=None): @@ -188,11 +211,15 @@ def _schedule(self, item, caller=None): self.logger.debug('{}: called by {}, changed by: {}'.format(self._name, caller, item.changed_by())) _next = None _value = None + self._update_sun(item, caller='schedule') + + item(self._items[item]) if not self._items[item]['interpolation'].get('itemtype'): self.logger.error("{}: item '{}' to be set by uzsu does not exist.".format( self._name, self.get_iattr_value(item.conf, ITEM_TAG[0]))) elif 'active' in self._items[item]: if self._items[item]['active']: + self._itpl.clear() for entry in self._items[item]['list']: next, value = self._get_time(entry, 'next') @@ -406,6 +433,29 @@ def _get_time(self, entry, timescan): self.logger.error("{}: Error '{}' parsing time: {}".format(self._name, time, e)) return None, None + def _create_sun(self): + # checking preconditions from configuration: + uzsu_sun = None + if not self._sh.sun: # no sun object created + self.logger.error("{}: No latitude/longitude specified. " + "Not possible to create sun object.".format(self._name)) + + # create an own sun object: + if not self._uzsu_sun: + try: + longitude = self._sh.sun._obs.long + latitude = self._sh.sun._obs.lat + elevation = self._sh.sun._obs.elev + uzsu_sun = lib.orb.Orb('sun', longitude, latitude, elevation) + self.logger.debug("{}: Created a new sun object with latitude={}, longitude={}, elevation={}".format( + self._name, latitude, longitude, elevation)) + except Exception as e: + self.logger.error("{}: Error '{}' creating a new sun object. You could not " + "use sunrise/sunset as UZSU entry.".format(self._name, e)) + else: + uzsu_sun = self._uzsu_sun + return uzsu_sun + def _sun(self, dt, tstr): """ parses a given string with a time range to determine it's timely boundaries and @@ -415,23 +465,8 @@ def _sun(self, dt, tstr): :param: tstr contains a string with '[H:M<](sunrise|sunset)[+|-][offset][ Date: Thu, 6 Sep 2018 21:24:22 +0200 Subject: [PATCH 236/705] small fixes, added bouncetime option --- gpio/__init__.py | 7 ++++--- gpio/plugin.yaml | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/gpio/__init__.py b/gpio/__init__.py index 4026f343b..c8171a5da 100755 --- a/gpio/__init__.py +++ b/gpio/__init__.py @@ -47,12 +47,13 @@ def __init__(self, sh): self._itemsdict = {} self._initdict = {} self._mode = self.get_parameter_value('mode').upper() + self._bouncetime = self.get_parameter_value('bouncetime') GPIO.setwarnings(False) if self._mode == "BCM": GPIO.setmode(GPIO.BCM) else: GPIO.setmode(GPIO.BOARD) - self.logger.debug("{}: Mode set to {}".format(self._name, self._mode)) + self.logger.debug("{}: Mode set to {}. Bouncetime: {}".format(self._name, self._mode, self._bouncetime)) self.alive = False self._lock = threading.Lock() except Exception: @@ -80,7 +81,7 @@ def run(self): except Exception: self._initdict[sensor] = False item(value) - GPIO.add_event_detect(sensor, GPIO.BOTH, callback=self.get_sensors) + GPIO.add_event_detect(sensor, GPIO.BOTH, callback=self.get_sensors, bouncetime=self._bouncetime) self.logger.info("{}: Adding Event Detection for Pin {}. Initial value is {}".format( self._name, sensor, value)) @@ -104,7 +105,7 @@ def parse_item(self, item): self._itemsdict[out_pin] = item value = GPIO.input(out_pin) item(value) - GPIO.add_event_detect(out_pin, GPIO.BOTH, callback=self.get_sensors) + GPIO.add_event_detect(out_pin, GPIO.BOTH, callback=self.get_sensors, bouncetime=self._bouncetime) self.logger.info("{}: Adding Event Detection for Output Pin {}. Initial value is {}".format( self._name, out_pin, value)) GPIO.setup(out_pin, GPIO.OUT) diff --git a/gpio/plugin.yaml b/gpio/plugin.yaml index 1faff7784..5a3dfb85c 100755 --- a/gpio/plugin.yaml +++ b/gpio/plugin.yaml @@ -32,5 +32,22 @@ parameters: de: 'BOARD oder BCM, abhängig davon, nach welcher Methode die Pins zugewiesen werden sollen.' en: 'BOARD or BCM, depending on how to assign the pins.' + bouncetime: + type: int + default: 300 + mandatory: False + description: + de: 'Prellzeit in ms, um Änderungen innerhalb kurzer Zeit zu verhindern.' + en: 'bouncetime in ms to avoid multiple events in a short time period.' item_attributes: # Definition of item attributes defined by this plugin + gpio_in: + type: int + description: + de: 'Pin Nummer für den GPIO Eingang. Die Nummer hängt vom Modus in den Plugin-Paramtern ab!' + en: 'Pin number of the GPIO input. Depends on the mode you have set in the plugin parameters!' + gpio_out: + type: int + description: + de: 'Pin Nummer für den GPIO Ausgang. Die Nummer hängt vom Modus in den Plugin-Paramtern ab! Der Ausgang wird zum Pluginstart automatisch aktualisiert, sollte also nicht im Item als gpio_in und gpio_out definiert werden.' + en: 'Pin number of the GPIO output. Depends on the mode you have set in the plugin parameters! Do not set gpio_in and gpio_out for the same item as the output item will get initialized at plugin start automatically.' From c43991dda4db611b62e854a984a79af531752d1c Mon Sep 17 00:00:00 2001 From: msinn Date: Fri, 7 Sep 2018 03:09:49 +0200 Subject: [PATCH 237/705] sqlite & sqlite_visu2_8: Added metadata --- sqlite/plugin.yaml | 32 +++++++++++++++++++++++++++++-- sqlite_visu2_8/__init__.py | 4 ++-- sqlite_visu2_8/plugin.yaml | 39 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 69 insertions(+), 6 deletions(-) diff --git a/sqlite/plugin.yaml b/sqlite/plugin.yaml index 1a42b6909..a094756df 100755 --- a/sqlite/plugin.yaml +++ b/sqlite/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Integration of a SQLite database - use this version of the plugin for smartVISU v2.7' maintainer: '?' # tester: # Who tests this plugin? + state: ready keywords: database # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page @@ -14,11 +15,38 @@ plugin: sh_minversion: 1.3c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance + restartable: unknown classname: SQL # class containing the plugin parameters: # Definition of parameters to be configured in etc/plugin.yaml - + cycle: + type: int + valid_min: 0 + default: 300 + description: + de: 'Zyklus-Zeit in dem die Datanbank Daten auf den Datenträger geschrieben werden' + en: 'cycle time for data beeing written to disc' + + path: + type: str + description: + de: "Pfad zur Datenbank Datei (Pfad ohne Dateiname)" + en: "Path to the database file (path without filename)" + default: None* + item_attributes: # Definition of item attributes defined by this plugin - + sqlite: + type: str + description: + de: "Falls auf 'yes' gesetzt, wird der Wert des Items in die sqlite Datenbank geschrieben." + en: "If set to 'yes', the value of the item will be written to the sqlite database" + valid_list: ['', 'yes', 'True', 'no', 'False'] + +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + +plugin_functions: + # Definition of function interface of the plugin + diff --git a/sqlite_visu2_8/__init__.py b/sqlite_visu2_8/__init__.py index ec838245b..d2265e506 100755 --- a/sqlite_visu2_8/__init__.py +++ b/sqlite_visu2_8/__init__.py @@ -54,7 +54,7 @@ class SQL(SmartPlugin): GROUP by CAST((_start / {}) AS INTEGER), _item ORDER BY _start DESC;""" - def __init__(self, smarthome, cycle=300, path=None, dumpfile=False): + def __init__(self, smarthome, cycle=300, path=None, dumpfile=''): self.logger = logging.getLogger(__name__) # sqlite3.register_adapter(datetime.datetime, self._timestamp) self._sh = smarthome @@ -299,7 +299,7 @@ def _maintain(self): if self._buffer[item] != []: self._insert(item) self._pack() - if self._dumpfile: + if self._dumpfile and (self._dumpfile != ''): self.dump(self._dumpfile) def _pack(self): diff --git a/sqlite_visu2_8/plugin.yaml b/sqlite_visu2_8/plugin.yaml index fade5d564..fe9e56128 100755 --- a/sqlite_visu2_8/plugin.yaml +++ b/sqlite_visu2_8/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Integration of a SQLite database - use this version of the plugin for smartVISU v2.8 and above' maintainer: '?' # tester: # Who tests this plugin? + state: ready keywords: database # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page @@ -14,11 +15,45 @@ plugin: sh_minversion: 1.3c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance + restartable: unknown classname: SQL # class containing the plugin parameters: # Definition of parameters to be configured in etc/plugin.yaml - +# cycle: +# type: int +# valid_min: 0 +# default: 300 +# description: +# de: 'Zyklus-Zeit in dem die Datanbank Daten auf den Datenträger geschrieben werden' +# en: 'cycle time for data beeing written to disc' + + path: + type: str + description: + de: "Pfad zur Datenbank Datei (Pfad ohne Dateiname)" + en: "Path to the database file (path without filename)" + default: None* + + dumpfile: + type: str + description: + de: "Falls dumpfile angegeben ist, erzeugt SmartHomeNG jede Nacht einen Datenbank Dump in diese Datei. (kompletter Pfad und Dateiname)" + en: "If dumpfile is specified, SmartHomeNG dumps the database every night into this file. (Complete path and filename)" + default: '' + item_attributes: # Definition of item attributes defined by this plugin - + sqlite: + type: str + description: + de: "Falls auf 'yes' gesetzt, wird der Wert des Items in die sqlite Datenbank geschrieben." + en: "If set to 'yes', the value of the item will be written to the sqlite database" + valid_list: ['', 'yes', 'True', 'no', 'False'] + +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + +plugin_functions: + # Definition of function interface of the plugin + From 8c34182668a506c75e366e52fc180773384a7243 Mon Sep 17 00:00:00 2001 From: msinn Date: Fri, 7 Sep 2018 03:13:43 +0200 Subject: [PATCH 238/705] database: Fix to enable plugin start without http/web interface --- database/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/database/__init__.py b/database/__init__.py index a4d70b474..8e92b8d04 100644 --- a/database/__init__.py +++ b/database/__init__.py @@ -96,8 +96,9 @@ def __init__(self, smarthome, driver, connect, prefix="", cycle=60, precision=2) smarthome.scheduler.add('Database dump ' + self._name + ("" if prefix == "" else " [" + prefix + "]"), self._dump, cycle=self._dump_cycle, prio=5) - if not self.init_webinterface(): - self._init_complete = False + self.init_webinterface() + return + def parse_item(self, item): self.logger.debug(item.conf) From ee4d34e73c7bf9264e1e0bcb3f00112db0854155 Mon Sep 17 00:00:00 2001 From: msinn Date: Fri, 7 Sep 2018 04:35:11 +0200 Subject: [PATCH 239/705] Metadata Updates --- database/plugin.yaml | 13 +++++++- eta_pu/plugin.yaml | 62 +++++++++++++++++++++++++++++++++++--- kodi/plugin.yaml | 4 +-- sqlite/plugin.yaml | 26 ++++++++++++++-- sqlite_visu2_8/plugin.yaml | 58 ++++++++++++++++++++++++++++++++++- 5 files changed, 153 insertions(+), 10 deletions(-) diff --git a/database/plugin.yaml b/database/plugin.yaml index 8d8f6cdc8..1e773630d 100755 --- a/database/plugin.yaml +++ b/database/plugin.yaml @@ -15,6 +15,7 @@ plugin: sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance + restartable: unknown classname: Database # class containing the plugin parameters: @@ -48,9 +49,19 @@ parameters: de: 'Genauigkeit der aus der Datenbank ausgelesenen Werte (Nachkommastellen).' en: 'Precision of values read from database (digits after comma).' + item_attributes: # Definition of item attributes defined by this plugin - + database: + type: str + valid_list: ['', 'yes', 'init'] + description: + de: "Wenn auf 'yes' gesetzt, werden die Werte des Items in die Datenbank geschrieben. Wenn auf 'init' gesetzt, wird zusätzlich beim Start von SmartHomeNG der Wert in die Datenbank geschrieben." + en: "This attribute enables the database logging when set (just use value 'yes'). If value 'init' is used, an item will be initalized from the database after SmartHomeNG is restarted." + + +logic_parameters: NONE + # Definition of logic parameters defined by this plugin plugin_functions: # Definition of function interface of the plugin diff --git a/eta_pu/plugin.yaml b/eta_pu/plugin.yaml index 98cdad3be..b95b30170 100755 --- a/eta_pu/plugin.yaml +++ b/eta_pu/plugin.yaml @@ -3,10 +3,11 @@ plugin: # Global plugin attributes type: interface # plugin type (gateway, interface, protocol, system, web) description: - de: 'Anbindung der REST-Schnittstelle von ETA Heizungen' - en: '' + de: 'Anbindung der REST-Schnittstelle von ETA Heizungen (http://www.eta.co.at)' + en: 'ETA Pellet Unit PU (http://www.eta.co.at) with remote access enabled (there are 3 modes available: none, readonly, read/write)' maintainer: '? (Brootux)' tester: 'psilo909, ?' + state: ready # keywords: iot xyz # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page # support: https://knx-user-forum.de/forum/supportforen/smarthome-py @@ -15,11 +16,64 @@ plugin: sh_minversion: 1.1 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance + restartable: unknkown classname: ETA_PU # class containing the plugin parameters: # Definition of parameters to be configured in etc/plugin.yaml - + address: + type: ip + mandatory: True + description: + de: 'IP Adresse der ETA Pellet Einheit' + en: 'ip address of the ETA pellet unit' + + port: + type: int + valid_min: 0 + default: 8080 + description: + de: 'Port der ETA Webservers' + en: 'port of the ETA webserver' + + setpath: + type: str + description: + de: 'Pfad zu den vorab gesicherten Sets von CAN-Bus-uri' + en: 'path to the presaved sets of CAN-bus-uri' + + setname: + type: str + description: + de: 'Name des Sets, welches durch dieses Plugin genutzt wird' + en: 'the name of the set, used by this plugin' + + item_attributes: # Definition of item attributes defined by this plugin - + eta_pu_uri: + type: str + description: + de: "Enthält die CAN-Bus-Id. Die Pellet Einheit zeigt alle Ids mit Beschreibung unter der Url http:///user/menu" + en: "Contains the CAN-bus-id. The pellet unit shows all ids with description by requesting http:///user/menu" + + eta_pu_type: + type: str + description: + de: "" + en: "Represents the field of the data line. Must be one of: strValue, unit, decPlaces, scaleFactor, advTextOffset or calc" + + eta_pu_error: + type: str + valid_list: ['', 'yes', 'no'] + description: + de: "Wenn auf 'yes' gesetzt, werden Fehlermeldung der ETA Pellet Einheit in dieses Item eingelesen." + en: "The error message from the ETA pellet unit will be read." + + +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + +plugin_functions: NONE + # Definition of function interface of the plugin + diff --git a/kodi/plugin.yaml b/kodi/plugin.yaml index 5e5411b35..76ba318e4 100755 --- a/kodi/plugin.yaml +++ b/kodi/plugin.yaml @@ -21,10 +21,10 @@ plugin: parameters: # Definition of parameters to be configured in etc/plugin.yaml - host: + host: type: ipv4 mandatory: True - + port: type: int valid_min: 0 diff --git a/sqlite/plugin.yaml b/sqlite/plugin.yaml index a094756df..7bc076fbc 100755 --- a/sqlite/plugin.yaml +++ b/sqlite/plugin.yaml @@ -42,11 +42,33 @@ item_attributes: description: de: "Falls auf 'yes' gesetzt, wird der Wert des Items in die sqlite Datenbank geschrieben." en: "If set to 'yes', the value of the item will be written to the sqlite database" - valid_list: ['', 'yes', 'True', 'no', 'False'] + valid_list: ['', 'yes', 'init', 'True', 'no', 'False'] logic_parameters: NONE # Definition of logic parameters defined by this plugin plugin_functions: # Definition of function interface of the plugin - + db: + type: num + description: + de: "Diese Methode liefert einen Wert, für die gewählte Zeitspanne. Die Funktion legt fest, wie der Wert berechnet wird." + en: "This method returns an value for the specified function and timeframe." + parameters: + function: + type: str + valid_list: ['avg', 'max', 'min', 'avg', 'sum'] + description: + de: "Funktion die genutzt wird um den Rückgabewert zu berechnen" + en: "function used to calculate the return value" + start: + type: str + description: + de: "Beginn der Zeitspanne" + en: "start of timeframe" + end: + type: str + default: now + description: + de: "Ende der Zeitspanne" + en: "end of timeframe" diff --git a/sqlite_visu2_8/plugin.yaml b/sqlite_visu2_8/plugin.yaml index fe9e56128..297b4ba42 100755 --- a/sqlite_visu2_8/plugin.yaml +++ b/sqlite_visu2_8/plugin.yaml @@ -49,11 +49,67 @@ item_attributes: description: de: "Falls auf 'yes' gesetzt, wird der Wert des Items in die sqlite Datenbank geschrieben." en: "If set to 'yes', the value of the item will be written to the sqlite database" - valid_list: ['', 'yes', 'True', 'no', 'False'] + valid_list: ['', 'yes', 'init', 'True', 'no', 'False'] logic_parameters: NONE # Definition of logic parameters defined by this plugin plugin_functions: # Definition of function interface of the plugin + db: + type: num + description: + de: "Diese Methode liefert einen Wert, für die gewählte Zeitspanne. Die Funktion legt fest, wie der Wert berechnet wird." + en: "This method returns an value for the specified function and timeframe." + parameters: + function: + type: str + valid_list: ['avg', 'max', 'min', 'avg', 'sum'] + description: + de: "Funktion die genutzt wird um den Rückgabewert zu berechnen" + en: "function used to calculate the return value" + start: + type: str + description: + de: "Beginn der Zeitspanne" + en: "start of timeframe" + end: + type: str + default: now + description: + de: "Ende der Zeitspanne" + en: "end of timeframe" + + cleanup: + description: + de: "Diese Funktion entfernt verwaiste Items, welche nicht mehr in der Item Konfiguration referenziert werden." + en: "This function removes orphaned item entries which are no longer referenced in the item configuration." + + dump: + description: + de: "Erzeugt einen Dump der Datenbank in die angegebene Datei" + en: "Dumps the database into the specified file. 'sh.sql.dump('/tmp/smarthomedb.dump')' writes the database content into /tmp/smarthomedb.dump" + parameters: + filename: + type: str + description: + de: "Dateiname für den Datenbank Dump" + en: "filename for the datbase dump" + + move: + description: + de: "Diese Funktion benennt Item Einträge um. sh.sql.move('my.old.item', 'my.new.item')" + en: "This function renames item entries. sh.sql.move('my.old.item', 'my.new.item')" + parameters: + old: + type: str + description: + de: "Alter Item Name" + en: "old item name" + new: + type: str + description: + de: "Neuer Item Name" + en: "new item name" + From 4ce0251ca650ab707d9495b2a5450c9837db3731 Mon Sep 17 00:00:00 2001 From: msinn Date: Fri, 7 Sep 2018 10:07:37 +0200 Subject: [PATCH 240/705] Metadata Updates --- asterisk/plugin.yaml | 6 ++++++ buderus/plugin.yaml | 6 ++++++ dashbutton/plugin.yaml | 8 +++++++- database/plugin.yaml | 24 ++++++++++++------------ datalog/plugin.yaml | 12 +++++++++--- drexelundweiss/plugin.yaml | 6 ++++++ gpio/plugin.yaml | 6 ++++++ homematic/__init__.py | 1 - kostal/plugin.yaml | 6 ++++++ 9 files changed, 58 insertions(+), 17 deletions(-) diff --git a/asterisk/plugin.yaml b/asterisk/plugin.yaml index e861aaeb0..10d38b973 100755 --- a/asterisk/plugin.yaml +++ b/asterisk/plugin.yaml @@ -23,3 +23,9 @@ parameters: item_attributes: # Definition of item attributes defined by this plugin +logic_parameters: + # Definition of logic parameters defined by this plugin + +plugin_functions: + # Definition of function interface of the plugin + diff --git a/buderus/plugin.yaml b/buderus/plugin.yaml index e4c91d9a3..b164b26e1 100755 --- a/buderus/plugin.yaml +++ b/buderus/plugin.yaml @@ -23,3 +23,9 @@ parameters: item_attributes: # Definition of item attributes defined by this plugin +logic_parameters: + # Definition of logic parameters defined by this plugin + +plugin_functions: + # Definition of function interface of the plugin + diff --git a/dashbutton/plugin.yaml b/dashbutton/plugin.yaml index d1225dfbd..5dba1deee 100755 --- a/dashbutton/plugin.yaml +++ b/dashbutton/plugin.yaml @@ -17,9 +17,15 @@ plugin: multi_instance: False # plugin supports multi instance classname: Dashbutton # class containing the plugin -parameters: +parameters: NONE # Definition of parameters to be configured in etc/plugin.yaml item_attributes: # Definition of item attributes defined by this plugin +logic_parameters: + # Definition of logic parameters defined by this plugin + +plugin_functions: + # Definition of function interface of the plugin + diff --git a/database/plugin.yaml b/database/plugin.yaml index 1e773630d..f6cb6623d 100755 --- a/database/plugin.yaml +++ b/database/plugin.yaml @@ -69,7 +69,7 @@ plugin_functions: description: de: 'Liefert für das angegebene Item die Datenbank-ID zurück' en: 'Return the database ID for the given item' - parameter: + parameters: item: type: foo description: @@ -84,7 +84,7 @@ plugin_functions: description: de: 'Erzeugt einen Datenbank-Dump für angegebene Kriterien' en: 'Creates a database dump for given criterias' - parameter: + parameters: dumpfile: type: str description: @@ -134,7 +134,7 @@ plugin_functions: description: de: 'Log-Datenbankeintrag für angegebene Datenbank-ID anlegen' en: 'Create database log record for given database ID' - parameter: + parameters: id: type: int description: @@ -174,7 +174,7 @@ plugin_functions: description: de: 'Log-Datenbankeintrag für angegebene Datenbank-ID aktualisieren' en: 'Update database log record for given database ID' - parameter: + parameters: id: type: int description: @@ -214,7 +214,7 @@ plugin_functions: description: de: 'Log-Datenbankeintrag für angegebene Datenbank-ID auslesen' en: 'Read database log record for given database ID' - parameter: + parameters: id: type: int description: @@ -229,7 +229,7 @@ plugin_functions: description: de: 'Log-Datenbankeinträge für angegebene Datenbank-ID löschen' en: 'Delete database log records for given database ID' - parameter: + parameters: id: type: int description: @@ -274,7 +274,7 @@ plugin_functions: description: de: 'Log-Datenbankeinträge für angegebene Datenbank-ID auslesen' en: 'Read database log records for given database ID' - parameter: + parameters: id: type: int description: @@ -319,7 +319,7 @@ plugin_functions: description: de: 'Item-Datenbankeintrag für angegebene Datenbank-ID anlegen' en: 'Create database item record for given database ID' - parameter: + parameters: name: type: str description: @@ -334,7 +334,7 @@ plugin_functions: description: de: 'Item-Datenbankeintrag für angegebene Datenbank-ID aktualisieren' en: 'Update database item record for given database ID' - parameter: + parameters: id: type: int description: @@ -375,7 +375,7 @@ plugin_functions: description: de: 'Item-Datenbankeintrag für angegebene Datenbank-ID auslesen' en: 'Read database item record for given database ID' - parameter: + parameters: id: type: int description: @@ -390,7 +390,7 @@ plugin_functions: description: de: 'Item-Datenbankeinträge auslesen' en: 'Read database item records' - parameter: + parameters: id: type: int description: @@ -405,7 +405,7 @@ plugin_functions: description: de: 'Item-Datenbankeintrag für angegebene Datenbank-ID löschen' en: 'Delete database item record for given database ID' - parameter: + parameters: id: type: int description: diff --git a/datalog/plugin.yaml b/datalog/plugin.yaml index f778d7e2c..fdb932044 100755 --- a/datalog/plugin.yaml +++ b/datalog/plugin.yaml @@ -17,9 +17,15 @@ plugin: multi_instance: True classname: DataLog # class containing the plugin -#parameters: +parameters: # Definition of parameters to be configured in etc/plugin.yaml -#item_attributes: +item_attributes: # Definition of item attributes defined by this plugin - + +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + +plugin_functions: NONE + # Definition of function interface of the plugin + diff --git a/drexelundweiss/plugin.yaml b/drexelundweiss/plugin.yaml index f43960bd0..4cdd184b3 100755 --- a/drexelundweiss/plugin.yaml +++ b/drexelundweiss/plugin.yaml @@ -23,3 +23,9 @@ parameters: item_attributes: # Definition of item attributes defined by this plugin +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + +plugin_functions: NONE + # Definition of function interface of the plugin + diff --git a/gpio/plugin.yaml b/gpio/plugin.yaml index 9c6f42548..3f6a538c0 100755 --- a/gpio/plugin.yaml +++ b/gpio/plugin.yaml @@ -23,3 +23,9 @@ parameters: item_attributes: # Definition of item attributes defined by this plugin +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + +plugin_functions: NONE + # Definition of function interface of the plugin + diff --git a/homematic/__init__.py b/homematic/__init__.py index f3e8d4928..1c0f200e7 100755 --- a/homematic/__init__.py +++ b/homematic/__init__.py @@ -197,7 +197,6 @@ def parse_item(self, item): with the item, caller, source and dest as arguments and in case of the knx plugin the value can be sent to the knx with a knx write function within the knx plugin. """ - item.expand_relativepathes('test_attr', "", "") if self.has_iattr(item.conf, 'hm_address'): init_error = False # self.logger.debug("parse_item{}: {}".format(self.log_instance_str, item)) diff --git a/kostal/plugin.yaml b/kostal/plugin.yaml index f89771cfb..3764e3d4d 100755 --- a/kostal/plugin.yaml +++ b/kostal/plugin.yaml @@ -23,3 +23,9 @@ parameters: item_attributes: # Definition of item attributes defined by this plugin +logic_parameters: NONE + # Definition of logic parameters defined by this plugin + +plugin_functions: NONE + # Definition of function interface of the plugin + From 267c0ffc9de5faae3ec29d769c8c3b2401f8c408 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Fri, 7 Sep 2018 14:39:58 +0200 Subject: [PATCH 241/705] SML: Add `__init__.py` to test folder to fix tests discovery See also https://github.com/pytest-dev/pytest/issues/529 --- sml/tests/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 sml/tests/__init__.py diff --git a/sml/tests/__init__.py b/sml/tests/__init__.py new file mode 100644 index 000000000..e69de29bb From 74ad5661c9b88771822dfe55b878c4676244278d Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 7 Sep 2018 14:48:05 +0200 Subject: [PATCH 242/705] Pushbullet: added parameters --- pushbullet/plugin.yaml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/pushbullet/plugin.yaml b/pushbullet/plugin.yaml index 106254dc7..b98aa7b84 100755 --- a/pushbullet/plugin.yaml +++ b/pushbullet/plugin.yaml @@ -19,7 +19,19 @@ plugin: parameters: # Definition of parameters to be configured in etc/plugin.yaml - + apikey: + type: str + mandatory: False + description: + de: '(optional) Persönlicher API Key für Pushbullet. Registrierung siehe https://docs.pushbullet.com/. Wenn der Key nicht gesetzt ist, muss er expizit in Funktionsaufrufen gesetzt werden.' + en: '(optional) Your own personal API key for Pushbullet. For your own key refer to https://docs.pushbullet.com/. If key is not set, you have to use it in function calls.' + + deviceid: + type: str + mandatory: False + description: + de: '(optional) Id des anzusprechenden Geräts, wo eine Pushbullet App läuft. Auf http://www.pushbullet.com einloggen, Gerät auswählen und den Teil der URL kopieren, der hinter "device_iden=" kommt. Falls nicht gesetzt, muss der Wert explizit in Funktionsaufrufen als Parameter angegeben werden.' + en: '(optional) Id of referenced device, where Pushbullet app is running. Log in into http://www.pushbullet.com, select target device, copy the part of the browser URL behind "device_iden=" If not set, you have to use it in function calls.' + item_attributes: # Definition of item attributes defined by this plugin - From 9a4907b0f600986210247c9d5b3f5242f30f1ca3 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Fri, 7 Sep 2018 15:15:56 +0200 Subject: [PATCH 243/705] Database: Add `__init__.py` to test folder to fix tests discovery See also https://github.com/pytest-dev/pytest/issues/529 --- database/tests/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 database/tests/__init__.py diff --git a/database/tests/__init__.py b/database/tests/__init__.py new file mode 100644 index 000000000..e69de29bb From c49114abf7b053e5b5a5bb691ca9f159ffb6d714 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 7 Sep 2018 15:23:25 +0200 Subject: [PATCH 244/705] Pushbullet: reworked acc. to logging convention and get_parameter_value --- pushbullet/__init__.py | 76 +++++++++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/pushbullet/__init__.py b/pushbullet/__init__.py index d13727f0c..53b5cece8 100755 --- a/pushbullet/__init__.py +++ b/pushbullet/__init__.py @@ -35,12 +35,10 @@ class Pushbullet(SmartPlugin): ALLOW_MULTIINSTANCE = False PLUGIN_VERSION = "1.3.1" - def __init__(self, smarthome, apikey=None, deviceid=None, debug=False): + def __init__(self, sh, *args, **kwargs): logging.getLogger("requests").setLevel(logging.WARNING) - self._apikey = apikey - self._deviceid = deviceid - self._sh = smarthome - self._debug = debug + self._apikey = self.get_parameter_value('apikey') + self._deviceid = self.get_parameter_value('deviceid') self.logger = logging.getLogger(__name__) def run(self): @@ -60,9 +58,13 @@ def delete(self, pushid, apikey=None): if self._is_response_ok(response): return response.json() - self.logger.error("Could not delete Pushbullet notification. Error: {0}".format(response.text)) + self.logger.error( + "Plugin '{}': Could not delete Pushbullet notification. Error: {}".format(self.get_fullname(), + response.text)) except Exception as exception: - self.logger.error("Could not delete Pushbullet notification. Error: {0}".format(exception)) + self.logger.error( + "Plugin '{}': Could not delete Pushbullet notification. Error: {}".format(self.get_fullname(), + exception)) return False @@ -81,7 +83,9 @@ def list(self, title, items, deviceid=None, apikey=None): def file(self, filepath, deviceid=None, apikey=None, body=None): if os.path.exists(filepath) == False: - self.logger.error("Trying to push non existing file: {0}".format(filepath)) + self.logger.error( + "Plugin '{}': Trying to push non existing file: {}".format(self.get_fullname(), + filepath)) return False return self._upload_and_push_file(filepath, body, deviceid, apikey) @@ -117,11 +121,17 @@ def _upload_and_push_file(self, filepath, body=None, deviceid=None, apikey=None) data={"type": "file", "file_name": data["file_name"], "file_type": data["file_type"], "file_url": data["file_url"], "body": body}, deviceid=deviceid, apikey=apikey) else: - self.logger.error("Error while uploading file: {0}".format(upload_response.text)) + self.logger.error( + "Plugin '{}': Error while uploading file: {}".format(self.get_fullname(), + upload_response.text)) else: - self.logger.error("Error while requesting upload: {0}".format(upload_request_response.text)) + self.logger.error( + "Plugin '{}': Error while requesting upload: {}".format(self.get_fullname(), + upload_request_response.text)) except Exception as exception: - self.logger.error("Could not send file to Pushbullet notification. Error: {0}".format(exception)) + self.logger.error( + "Plugin '{}': Could not send file to Pushbullet notification. Error: {}".format(self.get_fullname(), + exception)) return False @@ -144,33 +154,51 @@ def _push(self, data, deviceid=None, apikey=None): if self._is_response_ok(response): return response.json() - self.logger.error("Could not send Pushbullet notification. Error: {0}".format(response.text)) + self.logger.error( + "Plugin '{}': Could not send Pushbullet notification. Error: {}".format(self.get_fullname(), + response.text)) except Exception as exception: - self.logger.error("Could not send Pushbullet notification. Error: {0}".format(exception)) - + self.logger.error( + "Plugin '{}': Could not send Pushbullet notification. Error: {}.".format( + self.get_fullname(), exception)) return False def _is_response_ok(self, response): if response.status_code == 200 or response.status_code == 204: - self.logger.debug("Pushbullet returns: Notification submitted.") + self.logger.debug("Plugin '{}': Pushbullet returns: Notification submitted.".format(self.get_fullname())) return True elif response.status_code == 400: - self.logger.warning("Pushbullet returns: Bad Request - Often missing a required parameter.") + self.logger.warning( + "Plugin '{}': Pushbullet returns: Bad Request - Often missing a required parameter.".format( + self.get_fullname())) elif response.status_code == 401: - self.logger.warning("Pushbullet returns: Unauthorized - No valid API key provided.") + self.logger.warning( + "Plugin '{}': Pushbullet returns: Unauthorized - No valid API key provided.".format( + self.get_fullname())) elif response.status_code == 402: - self.logger.warning("Pushbullet returns: Request Failed - Parameters were valid but the request failed.") + self.logger.warning( + "Plugin '{}': Pushbullet returns: Request Failed - Parameters were valid but the request failed.".format( + self.get_fullname())) elif response.status_code == 403: - self.logger.warning("Pushbullet returns: Forbidden - The API key is not valid for that request.") + self.logger.warning( + "Plugin '{}': Pushbullet returns: Forbidden - The API key is not valid for that request.".format( + self.get_fullname())) elif response.status_code == 404: - self.logger.warning("Pushbullet returns: Not Found - The requested item doesn't exist.") + self.logger.warning( + "Plugin '{}': Pushbullet returns: Not Found - The requested item doesn't exist.".format( + self.get_fullname())) elif response.status_code >= 500: - self.logger.warning("Pushbullet returns: Server errors - something went wrong on PushBullet's side.") + self.logger.warning( + "Plugin '{}': Server errors - something went wrong on PushBullet's side.".format( + self.get_fullname())) else: - self.logger.error("Pushbullet returns unknown HTTP status code = {0}".format(response.status_code)) + self.logger.error( + "Plugin '{}': Pushbullet returns unknown HTTP status code = {}.".format( + self.get_fullname(), response.status_code)) - if self._debug: - self.logger.warning("Response was: {}".format(response.text)) + self.logger.debug( + "Plugin '{}': Response was: {}".format( + self.get_fullname(), response.text)) return False From e04e905e79f997621a5af208671fd648ed18a79c Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 7 Sep 2018 15:27:29 +0200 Subject: [PATCH 245/705] Pushbullet: upgraded version --- pushbullet/README.md | 3 +++ pushbullet/__init__.py | 2 +- pushbullet/plugin.yaml | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pushbullet/README.md b/pushbullet/README.md index c455592ec..8a0364b94 100644 --- a/pushbullet/README.md +++ b/pushbullet/README.md @@ -12,6 +12,9 @@ --- ## Changelog +__2018-09-07__: +* migrated to new parameter handling and logging convention + __2015-11-17__: * Added "delete" function diff --git a/pushbullet/__init__.py b/pushbullet/__init__.py index 53b5cece8..8e54cc885 100755 --- a/pushbullet/__init__.py +++ b/pushbullet/__init__.py @@ -33,7 +33,7 @@ class Pushbullet(SmartPlugin): _apiurl = "https://api.pushbullet.com/v2/pushes" _upload_apiurl = "https://api.pushbullet.com/v2/upload-request" ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.3.1" + PLUGIN_VERSION = "1.5.2" def __init__(self, sh, *args, **kwargs): logging.getLogger("requests").setLevel(logging.WARNING) diff --git a/pushbullet/plugin.yaml b/pushbullet/plugin.yaml index b98aa7b84..cc2bf050c 100755 --- a/pushbullet/plugin.yaml +++ b/pushbullet/plugin.yaml @@ -11,8 +11,8 @@ plugin: # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page # support: https://knx-user-forum.de/forum/supportforen/smarthome-py - version: 1.3.1 # Plugin version - sh_minversion: 1.3 # minimum shNG version to use this plugin + version: 1.5.2 # Plugin version + sh_minversion: 1.5 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance classname: Pushbullet # class containing the plugin From 2faed4b16f4239990a03dded3b89cc17e7a319bf Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Fri, 7 Sep 2018 18:18:17 +0200 Subject: [PATCH 246/705] XMPP: Add IPv6 support flag to disable IPv6 (only use IPv4) --- xmpp/README.md | 2 ++ xmpp/__init__.py | 1 + xmpp/plugin.yaml | 6 ++++++ 3 files changed, 9 insertions(+) diff --git a/xmpp/README.md b/xmpp/README.md index 2d0afa80c..824fa61b7 100644 --- a/xmpp/README.md +++ b/xmpp/README.md @@ -17,12 +17,14 @@ xmpp: class_path: plugins.xmpp jid: 'user account eg skender@somexmppserver.com' password: your xmpp server password + #use_ipv6: 1 ``` Description of the attributes: * jid: jabber/xmpp user account * password: jabber/xmpp user password +* use_ipv6: enable IPv6 support, which is the default ### logic.yaml At this stage there are no specific logic files. But in order to use this module you can create a logic file for another attribute and execute diff --git a/xmpp/__init__.py b/xmpp/__init__.py index 91e72060b..8c2bc2aff 100755 --- a/xmpp/__init__.py +++ b/xmpp/__init__.py @@ -36,6 +36,7 @@ class XMPP(SmartPlugin): def __init__(self, smarthome, jid, password, logic='XMPP'): self.logger = logging.getLogger(__name__) self.xmpp = sleekxmpp.ClientXMPP(jid, password) + self.xmpp.use_ipv6 = self.get_parameter_value('use_ipv6') self.xmpp.add_event_handler("session_start", self.handleXMPPConnected) self.xmpp.add_event_handler("message", self.handleIncomingMessage) self._logic = logic diff --git a/xmpp/plugin.yaml b/xmpp/plugin.yaml index b35298658..cd4a75ea9 100755 --- a/xmpp/plugin.yaml +++ b/xmpp/plugin.yaml @@ -34,6 +34,12 @@ parameters: description: de: 'Gibt das Passwort für den zu nutzenden Account an' en: 'Specifies the password of the account to use' + use_ipv6: + type: bool + default: True + description: + de: 'Aktiviert die Nutzung von IPv6 zusätzlich zu IPv4 (optional)' + en: 'Activates IPv6 support beside of IPv4 (optional)' item_attributes: NONE # Definition of item attributes defined by this plugin From f284fb91b7663fd776a5f7bc28b68be9c68cb76c Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Fri, 7 Sep 2018 18:23:01 +0200 Subject: [PATCH 247/705] XMPP: Add support to load additional modules --- xmpp/README.md | 4 ++++ xmpp/__init__.py | 2 ++ xmpp/plugin.yaml | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/xmpp/README.md b/xmpp/README.md index 824fa61b7..f16e98802 100644 --- a/xmpp/README.md +++ b/xmpp/README.md @@ -18,6 +18,9 @@ xmpp: jid: 'user account eg skender@somexmppserver.com' password: your xmpp server password #use_ipv6: 1 + #plugins: + # - xep_0199 # MUC + # - xep_0045 # PING ``` Description of the attributes: @@ -25,6 +28,7 @@ Description of the attributes: * jid: jabber/xmpp user account * password: jabber/xmpp user password * use_ipv6: enable IPv6 support, which is the default +* plugins: list of plugins (XEP to support) ### logic.yaml At this stage there are no specific logic files. But in order to use this module you can create a logic file for another attribute and execute diff --git a/xmpp/__init__.py b/xmpp/__init__.py index 8c2bc2aff..adc554cd7 100755 --- a/xmpp/__init__.py +++ b/xmpp/__init__.py @@ -36,6 +36,8 @@ class XMPP(SmartPlugin): def __init__(self, smarthome, jid, password, logic='XMPP'): self.logger = logging.getLogger(__name__) self.xmpp = sleekxmpp.ClientXMPP(jid, password) + for plugin in self.get_parameter_value('plugins'): + self.xmpp.register_plugin(plugin) self.xmpp.use_ipv6 = self.get_parameter_value('use_ipv6') self.xmpp.add_event_handler("session_start", self.handleXMPPConnected) self.xmpp.add_event_handler("message", self.handleIncomingMessage) diff --git a/xmpp/plugin.yaml b/xmpp/plugin.yaml index cd4a75ea9..8bc673cb3 100755 --- a/xmpp/plugin.yaml +++ b/xmpp/plugin.yaml @@ -34,6 +34,11 @@ parameters: description: de: 'Gibt das Passwort für den zu nutzenden Account an' en: 'Specifies the password of the account to use' + plugins: + type: list(str) + description: + de: 'Aktiviert weitere Plugins (XEP)' + en: 'Activates additional plugins (XEP)' use_ipv6: type: bool default: True From c11098709f8d9a4d4612018dfcfde2b1e6929086 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Fri, 7 Sep 2018 18:39:14 +0200 Subject: [PATCH 248/705] XMPP: Add new `join` option to specify group chats to join automatically Specifying group chats in the `join` setting will force to load the MUC (multi user chat) plugin automatically. The plugin will join the rooms when connected to server and will leave the rooms when connection is shut down. --- xmpp/__init__.py | 14 +++++++++++++- xmpp/plugin.yaml | 15 ++++++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/xmpp/__init__.py b/xmpp/__init__.py index adc554cd7..8e44b39b0 100755 --- a/xmpp/__init__.py +++ b/xmpp/__init__.py @@ -35,14 +35,22 @@ class XMPP(SmartPlugin): def __init__(self, smarthome, jid, password, logic='XMPP'): self.logger = logging.getLogger(__name__) + plugins = self.get_parameter_value('plugins') + joins = self.get_parameter_value('join') + + # Enable MUC in case account should join channels + if len(joins) and 'xep_0045' not in plugins: + plugins.append('xep_0045') + self.xmpp = sleekxmpp.ClientXMPP(jid, password) - for plugin in self.get_parameter_value('plugins'): + for plugin in plugins: self.xmpp.register_plugin(plugin) self.xmpp.use_ipv6 = self.get_parameter_value('use_ipv6') self.xmpp.add_event_handler("session_start", self.handleXMPPConnected) self.xmpp.add_event_handler("message", self.handleIncomingMessage) self._logic = logic self._sh = smarthome + self._join = joins def run(self): self.alive = True @@ -52,6 +60,8 @@ def run(self): def stop(self): self._run = False self.alive = False + for chat in self._join: + self.xmpp.plugin['xep_0045'].leaveMUC(chat, self.xmpp.jid) self.logger.info("Shutting Down XMPP Client") self.xmpp.disconnect(wait=False) @@ -75,6 +85,8 @@ def __call__(self, to, msgsend): def handleXMPPConnected(self, event): self.xmpp.sendPresence(pstatus="Send me a message") self.xmpp.get_roster() + for chat in self._join: + self.xmpp.plugin['xep_0045'].joinMUC(chat, self.xmpp.jid, wait=True) def handleIncomingMessage(self, msg): """ diff --git a/xmpp/plugin.yaml b/xmpp/plugin.yaml index 8bc673cb3..b22561e49 100755 --- a/xmpp/plugin.yaml +++ b/xmpp/plugin.yaml @@ -34,17 +34,22 @@ parameters: description: de: 'Gibt das Passwort für den zu nutzenden Account an' en: 'Specifies the password of the account to use' - plugins: - type: list(str) - description: - de: 'Aktiviert weitere Plugins (XEP)' - en: 'Activates additional plugins (XEP)' use_ipv6: type: bool default: True description: de: 'Aktiviert die Nutzung von IPv6 zusätzlich zu IPv4 (optional)' en: 'Activates IPv6 support beside of IPv4 (optional)' + plugins: + type: list(str) + description: + de: 'Aktiviert weitere Plugins (XEP) (optional)' + en: 'Activates additional plugins (XEP) (optional)' + join: + type: list(str) + description: + de: 'Gibt die Liste der Gruppenchats an die automatisch betreten werden sollen (optional)' + en: 'Specifies the list of group chats to join automatically (optional)' item_attributes: NONE # Definition of item attributes defined by this plugin From 8b8ce9c9dd7d42956d39add2780f611f39d1fd39 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 8 Sep 2018 01:46:38 +0200 Subject: [PATCH 249/705] UZSU: Added calculated sunrise/set times to item dict, additional tweaks --- uzsu/__init__.py | 84 +++++++++++++++++++++++++----------------------- uzsu/plugin.yaml | 2 +- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 8997a1c9c..8be5f2ac6 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -65,7 +65,7 @@ from collections import OrderedDict try: - from scipy import interpolate + from scipy import interpolate, optimize REQUIRED_PACKAGE_IMPORTED = True except: REQUIRED_PACKAGE_IMPORTED = False @@ -81,7 +81,7 @@ class UZSU(SmartPlugin): ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.5.1" + PLUGIN_VERSION = "1.5.2" _items = {} # item buffer for all uzsu enabled items @@ -213,36 +213,31 @@ def _schedule(self, item, caller=None): _value = None self._update_sun(item, caller='schedule') - item(self._items[item]) if not self._items[item]['interpolation'].get('itemtype'): self.logger.error("{}: item '{}' to be set by uzsu does not exist.".format( self._name, self.get_iattr_value(item.conf, ITEM_TAG[0]))) - elif 'active' in self._items[item]: - if self._items[item]['active']: - - self._itpl.clear() - for entry in self._items[item]['list']: - next, value = self._get_time(entry, 'next') - self._get_time(entry, 'previous') - if next is not None: - self.logger.debug("{}: uzsu active entry for item {} with datetime {}, value {}" - " and tzinfo {}".format(self._name, item, next, value, next.tzinfo)) - if _next is None: - _next = next - _value = value - elif next and next < _next: - self.logger.debug("{}: uzsu active entry for item {} using now {}, value {}" - " and tzinfo {}".format(self._name, item, next, value, next.tzinfo)) - _next = next - _value = value - else: - self.logger.debug("{}: uzsu active entry for item {} keep {}, value {} and tzinfo {}".format( - self._name, item, _next, _value, _next.tzinfo)) - else: - self.logger.debug("{}: uzsu item '{}' is not active".format(self._name, item)) else: - self.logger.debug("{}: uzsu item '{}' does not have an 'active' attribute".format(self._name, item)) - if _next and _value is not None: + self._itpl.clear() + for entry in self._items[item]['list']: + next, value = self._get_time(entry, 'next', item) + self._get_time(entry, 'previous', item) + item(self._items[item]) + if next is not None: + self.logger.debug("{}: uzsu active entry for item {} with datetime {}, value {}" + " and tzinfo {}".format(self._name, item, next, value, next.tzinfo)) + if _next is None: + _next = next + _value = value + elif next and next < _next: + self.logger.debug("{}: uzsu active entry for item {} using now {}, value {}" + " and tzinfo {}".format(self._name, item, next, value, next.tzinfo)) + _next = next + _value = value + else: + self.logger.debug("{}: uzsu active entry for item {} keep {}, value {} and tzinfo {}".format( + self._name, item, _next, _value, _next.tzinfo)) + + if _next and _value is not None and 'active' in self._items[item] and self._items[item]['active']: _reset_interpolation = False _interval = self._items[item]['interpolation'].get('interval') _interval = 5 if not _interval else int(_interval) @@ -339,7 +334,7 @@ def _set(self, **kwargs): if not caller: self._schedule(item, caller='set') - def _get_time(self, entry, timescan): + def _get_time(self, entry, timescan, item=None): """ Returns the next execution time and value :param entry: a dictionary that may contain the following keys: @@ -374,25 +369,30 @@ def _get_time(self, entry, timescan): rrule = rrulestr(entry['rrule'], dtstart=entry['dtstart']) else: try: - rrule = rrulestr(entry['rrule'], dtstart=datetime.combine(weekbefore, parser.parse(time.strip()).time())) + rrule = rrulestr(entry['rrule'], dtstart=datetime.combine( + weekbefore, parser.parse(time.strip()).time())) + self.logger.debug("{}: Created rrule:'{}' for time:'{}'".format( + self._name, str(rrule).replace('\n', ';'), time)) except ValueError: self.logger.debug("{}: Could not create a rrule from rrule:'{}' and time:'{}'".format( self._name, entry['rrule'], time)) if 'sun' in time: - self.logger.debug("{}: Looking for {} sun-related time with rrulestr()".format( - self._name, timescan)) - rrule = rrulestr(entry['rrule'], dtstart=datetime.combine(weekbefore, self._sun(datetime.combine(yesterday.date(), datetime.min.time()).replace(tzinfo=self._timezone), time).time())) + rrule = rrulestr(entry['rrule'], dtstart=datetime.combine( + weekbefore, self._sun(datetime.combine(weekbefore.date(), + datetime.min.time()).replace(tzinfo=self._timezone), time, timescan).time())) + self.logger.debug("{}: Looking for {} sun-related time. Found rrule: {}".format( + self._name, timescan, str(rrule).replace('\n', ';'))) else: - self.logger.debug("{}: Looking for {} time with rrulestr()".format( - self._name, timescan)) rrule = rrulestr(entry['rrule'], dtstart=datetime.combine(weekbefore, datetime.min.time())) + self.logger.debug("{}: Looking for {} time. Found rrule: {}".format( + self._name, timescan, str(rrule).replace('\n', ';'))) dt = now while self.alive: dt = rrule.before(dt) if timescan == 'previous' else rrule.after(dt) if dt is None: return None, None if 'sun' in time: - next = self._sun(datetime.combine(dt.date(), datetime.min.time()).replace(tzinfo=self._timezone), time) + next = self._sun(datetime.combine(dt.date(), datetime.min.time()).replace(tzinfo=self._timezone), time, timescan) self.logger.debug("{}: Result parsing time (rrule){}: {}".format(self._name, time, next)) else: next = datetime.combine(dt.date(), parser.parse(time.strip()).time()).replace(tzinfo=self._timezone) @@ -407,8 +407,12 @@ def _get_time(self, entry, timescan): self.logger.debug("{}: Return from rrule previous: {}, value {}.".format(self._name, next, value)) return next, value if 'sun' in time: - next = self._sun(datetime.combine(today, datetime.min.time()).replace(tzinfo=self._timezone), time) + next = self._sun(datetime.combine(today, datetime.min.time()).replace(tzinfo=self._timezone), time, timescan) self.logger.debug("{}: Result parsing time (sun) {}: {}".format(self._name, time, next)) + entry_calculated = self._items[item].get('list').index(entry) + self._items[item].get('list')[entry_calculated]['calculated'] = next.strftime("%H:%M") + self.logger.debug("{}: Updated calculated time for item {}.".format( + self._name, item)) else: next = datetime.combine(today, parser.parse(time.strip()).time()).replace(tzinfo=self._timezone) @@ -456,7 +460,7 @@ def _create_sun(self): uzsu_sun = self._uzsu_sun return uzsu_sun - def _sun(self, dt, tstr): + def _sun(self, dt, tstr, timescan): """ parses a given string with a time range to determine it's timely boundaries and returns a time @@ -497,7 +501,6 @@ def _sun(self, dt, tstr): self.logger.error('{}: Wrong syntax: {}. Should be [H:M<](sunrise|sunset)[+|-][offset][ Date: Sat, 8 Sep 2018 01:50:49 +0200 Subject: [PATCH 250/705] UZSU: removed unneccessary import --- uzsu/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 8be5f2ac6..9c48b77b8 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -65,9 +65,9 @@ from collections import OrderedDict try: - from scipy import interpolate, optimize + from scipy import interpolate REQUIRED_PACKAGE_IMPORTED = True -except: +except Exception: REQUIRED_PACKAGE_IMPORTED = False ITEM_TAG = ['uzsu_item'] From a387859d7687a4bf693b9c2b9c3e30d186a37fe0 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 8 Sep 2018 10:16:40 +0200 Subject: [PATCH 251/705] implemented web interface --- uzsu/__init__.py | 196 ++++++++++++++++++++++---- uzsu/locale.yaml | 11 ++ uzsu/webif/static/img/plugin_logo.svg | 11 ++ uzsu/webif/static/img/readme.txt | 6 + uzsu/webif/templates/index.html | 88 ++++++++++++ 5 files changed, 284 insertions(+), 28 deletions(-) create mode 100755 uzsu/locale.yaml create mode 100644 uzsu/webif/static/img/plugin_logo.svg create mode 100755 uzsu/webif/static/img/readme.txt create mode 100755 uzsu/webif/templates/index.html diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 9c48b77b8..46bf12bd0 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -53,7 +53,7 @@ # ]}) import logging -from lib.model.smartplugin import SmartPlugin +from lib.model.smartplugin import * from lib.item import Items from lib.shtime import Shtime @@ -97,11 +97,14 @@ def __init__(self, smarthome): self._timezone = Shtime.get_instance().tzinfo() self._sh = smarthome self._uzsu_sun = None + self._items = {} + self._itpl = OrderedDict() + self.init_webinterface() self.logger.info('{}: Init with timezone {}'.format(self._name, self._timezone)) if not REQUIRED_PACKAGE_IMPORTED: self.logger.error("{}: Unable to import Python package 'scipy'" " which is necessary for interpolation.".format(self._name)) - self._itpl = OrderedDict() + self._init_complete = False def run(self): """ @@ -120,9 +123,8 @@ def run(self): for item in self._items: self._items[item]['interpolation']['itemtype'] = self._add_type(item) item(self._items[item]) - if 'active' in self._items[item]: - if self._items[item]['active']: - self._schedule(item, caller='run') + if 'active' in self._items[item] and self._items[item]['active']: + self._schedule(item, caller='run') def stop(self): """ @@ -132,10 +134,24 @@ def stop(self): self.alive = False def _update_all_suns(self, caller=None): + """ + Update sun information for all uzsu items + + :param caller: if given it represents the callers name + :type caller: str + """ for item in self._items: self._update_sun(item) def _update_sun(self, item, caller=None): + """ + Update general sunrise and sunset information for visu + + :param caller: if given it represents the callers name + :param item: uzsu item + :type caller: str + :type item: item + """ self._uzsu_sun = self._create_sun() self._items[item] = item() _sunrise = self._uzsu_sun.rise() @@ -150,6 +166,13 @@ def _update_sun(self, item, caller=None): self._name, item, caller, self._items[item]['sunrise'], self._items[item]['sunset'])) def _add_type(self, item): + """ + Adding the type of the item that is changed by the uzsu to the item dict + + :param item: uzsu item + :type item: item + :return: The item type of the item that is changed + """ try: _uzsuitem = self.itemsApi.return_item(self.get_iattr_value(item.conf, ITEM_TAG[0])) except Exception as err: @@ -170,6 +193,7 @@ def parse_item(self, item): the item in future, like adding it to an internal array for future reference :param item: The item to process. + :type item: item :return: If the plugin needs to be informed of an items change you should return a call back function like the function update_item down below. An example when this is needed is the knx plugin where parse_item returns the update_item function when the attribute knx_send is found. @@ -194,10 +218,11 @@ def update_item(self, item, caller=None, source=None, dest=None): """ This is called by smarthome engine when the item changes, e.g. by Visu or by the command line interface The relevant item is put into the internal item list and registered to the scheduler - :param item: item to be updated towards the plugin - :param caller: if given it represents the callers name - :param source: if given it represents the source - :param dest: if given it represents the dest + + :param item: item to be updated towards the plugin + :param caller: if given it represents the callers name + :param source: if given it represents the source + :param dest: if given it represents the dest """ self._items[item] = item() self._schedule(item, caller='update') @@ -205,7 +230,11 @@ def update_item(self, item, caller=None, source=None, dest=None): def _schedule(self, item, caller=None): """ This function schedules an item: First the item is removed from the scheduler. - If the item is active then the list is searched for the nearest next execution time + If the item is active then the list is searched for the nearest next execution time. + No matter it active or not the calculation for the execution time is triggered. + + :param item: item to be updated towards the plugin + :param caller: if given it represents the callers name """ self.scheduler_remove('uzsu_{}'.format(item)) self.logger.debug('{}: called by {}, changed by: {}'.format(self._name, caller, item.changed_by())) @@ -314,7 +343,7 @@ def _schedule(self, item, caller=None): if cond5 and _value < 0: self.logger.warning("{}: value {} for item {} is negative. This might be due" " to not enough values set in the UZSU.".format(self._name, _value, item)) - if _reset_interpolation == True: + if _reset_interpolation is True: self._items[item]['interpolation']['type'] = 'none' item(self._items[item]) else: @@ -323,6 +352,13 @@ def _schedule(self, item, caller=None): self.scheduler_add('uzsu_{}'.format(item), self._set, value={'item': item, 'value': _value}, next=_next) def _set(self, **kwargs): + """ + This function sets the specific item + + :param item: item to be updated towards the plugin + :param value: value the item should be set to + :param caller: if given it represents the callers name + """ item = kwargs['item'] value = kwargs['value'] try: @@ -336,13 +372,15 @@ def _set(self, **kwargs): def _get_time(self, entry, timescan, item=None): """ - Returns the next execution time and value - :param entry: a dictionary that may contain the following keys: - value - active - date - rrule - dtstart + Returns the next and previous execution time and value + :param entry: a dictionary that may contain the following keys: + value + active + date + rrule + dtstart + :param item: item to be updated towards the plugin + :param timescan: defines whether to find values in the future or past """ try: if not isinstance(entry, dict): @@ -362,8 +400,6 @@ def _get_time(self, entry, timescan, item=None): time = entry['time'] if not active: return None, None - if 'date' in entry: - date = entry['date'] if 'rrule' in entry and entry['rrule']: if 'dtstart' in entry: rrule = rrulestr(entry['rrule'], dtstart=entry['dtstart']) @@ -438,6 +474,9 @@ def _get_time(self, entry, timescan, item=None): return None, None def _create_sun(self): + """ + Creates a sun object for sun calculations + """ # checking preconditions from configuration: uzsu_sun = None if not self._sh.sun: # no sun object created @@ -465,9 +504,10 @@ def _sun(self, dt, tstr, timescan): parses a given string with a time range to determine it's timely boundaries and returns a time - :param: dt contains a datetime object, - :param: tstr contains a string with '[H:M<](sunrise|sunset)[+|-][offset][ dmax: - self.logger.error("{}: Wrong times: the earliest time should be smaller than the " - "latest time in {}".format(self._name, tstr)) - return + if dmin is not None and dmax is not None and dmin > dmax: + self.logger.error("{}: Wrong times: the earliest time should be smaller than the " + "latest time in {}".format(self._name, tstr)) + return return next_time + + def _get_dependant(self, item): + """ + Getting the value of the dependent item for the webif + + :param item: uzsu item + :type item: item + :return: The item value of the item that is changed + """ + try: + _uzsuitem = self.itemsApi.return_item(self.get_iattr_value(item.conf, ITEM_TAG[0])) + except Exception as err: + _uzsuitem = None + self.logger.warning("{}: Item to be queried does not exist. Error: {}".format(self._name, err)) + try: + _itemvalue = _uzsuitem() + except Exception as err: + _itemvalue = None + self.logger.warning("{}: Item to be queried does not have a type attribute. Error: {}".format( + self._name, err)) + return _itemvalue + + def init_webinterface(self): + """" + Initialize the web interface for this plugin + + This method is only needed if the plugin is implementing a web interface + """ + try: + self.mod_http = Modules.get_instance().get_module('http') + except Exception: + self.mod_http = None + if self.mod_http is None: + self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_shortname())) + return False + + import sys + if "SmartPluginWebIf" not in list(sys.modules['lib.model.smartplugin'].__dict__): + self.logger.warning("Plugin '{}': Web interface needs SmartHomeNG v1.5 and up. Not initializing the web interface".format(self.get_shortname())) + return False + + # set application configuration for cherrypy + webif_dir = self.path_join(self.get_plugin_dir(), 'webif') + config = { + '/': { + 'tools.staticdir.root': webif_dir, + }, + '/static': { + 'tools.staticdir.on': True, + 'tools.staticdir.dir': 'static' + } + } + + # Register the web interface as a cherrypy app + self.mod_http.register_webif(WebInterface(webif_dir, self), + self.get_shortname(), + config, + self.get_classname(), self.get_instance_name(), + description='') + + return True + + +# ------------------------------------------ +# Webinterface of the plugin +# ------------------------------------------ + +import cherrypy +from jinja2 import Environment, FileSystemLoader + + +class WebInterface(SmartPluginWebIf): + + def __init__(self, webif_dir, plugin): + """ + Initialization of instance of class WebInterface + + :param webif_dir: directory where the webinterface of the plugin resides + :param plugin: instance of the plugin + :type webif_dir: str + :type plugin: object + """ + self.logger = logging.getLogger(__name__) + self.webif_dir = webif_dir + self.plugin = plugin + self.tplenv = self.init_template_environment() + + @cherrypy.expose + def index(self, action=None, item_id=None, item_path=None, reload=None): + """ + Build index.html for cherrypy + + Render the template and return the html file to be delivered to the browser + + :return: contents of the template after beeing rendered + """ + #item = self.plugin.get_sh().return_item(item_path) + tmpl = self.tplenv.get_template('index.html') + # add values to be passed to the Jinja2 template eg: tmpl.render(p=self.plugin, interface=interface, ...) + return tmpl.render(p=self.plugin, + language=self.plugin._sh.get_defaultlanguage(), now=self.plugin.shtime.now()) diff --git a/uzsu/locale.yaml b/uzsu/locale.yaml new file mode 100755 index 000000000..7d227e3d2 --- /dev/null +++ b/uzsu/locale.yaml @@ -0,0 +1,11 @@ +plugin_translations: + # Translations for the plugin specially for the web interface + 'Die folgenden Items sind dem UZSU Plugin zugewiesen': {'de': '=', 'en': 'The following items are assigned to the UZSU plugin'} + 'UZSU Item': {'de': '=', 'en': '='} + 'Abhängige Items (mit Typ)': {'de': '=', 'en': 'Dependant Item (with type)'} + 'Wert des abhängigen Items': {'de': '=', 'en': 'Value of dependant Item'} + 'Interpolation': {'de': '=', 'en': '='} + 'Back in Time': {'de': '=', 'en': '='} + 'Sonnenaufgang': {'de': '=', 'en': 'sun rise'} + 'Sonnenuntergang': {'de': '=', 'en': 'sun set'} + 'Uhr': {'de': '=', 'en': "o'clock"} diff --git a/uzsu/webif/static/img/plugin_logo.svg b/uzsu/webif/static/img/plugin_logo.svg new file mode 100644 index 000000000..2f7fbfe91 --- /dev/null +++ b/uzsu/webif/static/img/plugin_logo.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/uzsu/webif/static/img/readme.txt b/uzsu/webif/static/img/readme.txt new file mode 100755 index 000000000..1a7c55eef --- /dev/null +++ b/uzsu/webif/static/img/readme.txt @@ -0,0 +1,6 @@ +This directory is for storing images that are used by the web interface. + +If you want to have your own logo on the top of the web interface, store it here and name it plugin_logo.. + +Extension can be png, svg or jpg + diff --git a/uzsu/webif/templates/index.html b/uzsu/webif/templates/index.html new file mode 100755 index 000000000..d52887d5e --- /dev/null +++ b/uzsu/webif/templates/index.html @@ -0,0 +1,88 @@ +{% extends "base_plugin.html" %} +{% block scripts %} +{{ super() }} + +{% endblock scripts %} +{% set logo_frame = false %} + + +{% set item_count = p._items|length %} +{% set tab1title = "" ~ p.get_shortname() ~ " Items (" ~ item_count ~ ")" %} +{% set tabcount = 1 %} + +{% block headtable %} + {% set sun = {'sunrise': '-', 'sunset': '-'} %} + {% for item in p._items %} + {% if p._items[item]['sunrise'] and sun.sunrise == '-' %} + {% if sun.update({'sunrise': p._items[item]['sunrise']|string}) %} {% endif %} + {% if sun.update({'sunset': p._items[item]['sunset']|string}) %} {% endif %} + {% endif %} + {% endfor %} + + + + + + + + + + + + + + + + + +
{{ _('Sonnenaufgang') }}{{ sun.sunrise }}{{ _('Sonnenuntergang') }}{{ sun.sunset }}
Items{{ item_count }}
+{% endblock headtable %} + + +{% block bodytab1 %} + +
+
+ {{ _('Die folgenden Items sind dem UZSU Plugin zugewiesen') }}: +
+ + + + + + + + + + + {% for item in p._items %} + {% if p.has_iattr(item.conf, 'uzsu_item') %} + {% if p._items[item]['active'] == True %} + {% set color = 'green' %} + {% else %} + {% set color = 'gray' %} + {% endif %} + + + + + + + + {% endif %} + {% endfor %} +
{{ _('UZSU Item') }}{{ _('Abhängige Items (mit Typ)') }}{{ _('Wert des abhängigen Items') }}{{ _('Interpolation') }}{{ _('Back in Time') }}
{{ item._path }}{{ p.get_iattr_value(item.conf, 'uzsu_item') }} + ({{ p._items[item]['interpolation']['itemtype'] }}){{ p._get_dependant(item) }}{% if p._items[item]['interpolation']['type'] %} + {{ p._items[item]['interpolation']['type'] }}{% else %}-{% endif %}{% if p._items[item]['interpolation']['initage'] %} + {{ p._items[item]['interpolation']['initage'] }}{% else %}-{% endif %}
+
+{% endblock bodytab1 %} From e0288ca6e4627a294a0618c5b04ed3593ea817ad Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 8 Sep 2018 14:27:24 +0200 Subject: [PATCH 252/705] Added config attribute to delete existing entries when everything is the same on an update except the value --- uzsu/__init__.py | 23 +++++++++++++++++++++++ uzsu/plugin.yaml | 6 ++++++ 2 files changed, 29 insertions(+) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 46bf12bd0..9a289a704 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -62,6 +62,7 @@ from dateutil import parser from dateutil.tz import tzutc import lib.orb +from unittest import mock from collections import OrderedDict try: @@ -95,6 +96,7 @@ def __init__(self, smarthome): self.itemsApi = Items.get_instance() self._name = self.get_fullname() self._timezone = Shtime.get_instance().tzinfo() + self._remove_duplicates = self.get_parameter_value('remove_duplicates') self._sh = smarthome self._uzsu_sun = None self._items = {} @@ -225,6 +227,27 @@ def update_item(self, item, caller=None, source=None, dest=None): :param dest: if given it represents the dest """ self._items[item] = item() + if self._remove_duplicates is True: + compare_entries = item.prev_value() + newentries = [] + [newentries.append(i) for i in self._items[item]['list'] if i not in compare_entries['list']] + self.logger.debug('{}: Got update for item {}: {}'.format(self._name, item, newentries)) + todel = [] + for entry in self._items[item]['list']: + for new in newentries: + found = False + if not entry.get('value') == new.get('value'): + with mock.patch.dict(entry, value=new.get('value')): + found = True if entry == new else False + if found is True: + todel.append(entry) + finallist = [n for n in self._items[item]['list'] if n not in todel] + self._items[item]['list'] = finallist + item(self._items[item]) + if todel: + self.logger.warning('Deleted the following entries from the actual dict' + ' because the entry got updated: {}'.format(todel)) + self._schedule(item, caller='update') def _schedule(self, item, caller=None): diff --git a/uzsu/plugin.yaml b/uzsu/plugin.yaml index 965955aa1..f5883097f 100755 --- a/uzsu/plugin.yaml +++ b/uzsu/plugin.yaml @@ -18,6 +18,12 @@ plugin: parameters: # Definition of parameters to be configured in etc/plugin.yaml + remove_duplicates: + type: bool + default: False + description: + de: 'Falls True, werden Einträge mit exakt den selben Einstellungen, aber unterschiedlichem Wert durch einen neu geätigten Eintrag ersetzt' + en: 'If True, existing entries with exactly the same settings except the value get replaced by the new entry' item_attributes: # Definition of item attributes defined by this plugin From b8bb6b7fb1a18efe239bb9f949ba5cc05cf23f90 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sun, 9 Sep 2018 13:05:12 +0200 Subject: [PATCH 253/705] OperationLog: Add plugin parameters to meta data --- operationlog/plugin.yaml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/operationlog/plugin.yaml b/operationlog/plugin.yaml index 1c1cb7c53..031e75108 100755 --- a/operationlog/plugin.yaml +++ b/operationlog/plugin.yaml @@ -18,6 +18,35 @@ plugin: parameters: # Definition of parameters to be configured in etc/plugin.yaml + name: + type: str + description: + de: 'Definiert den Namen des Logs' + en: 'Defines the name of the log' + maxlen: + type: int + default: 50 + description: + de: 'Gibt an, wieviele Einträge im Speicher vorgehalten werden' + en: 'Specifies how many log entries will be kept in memory' + cache: + type: bool + default: True + description: + de: 'Aktiviert die Caching-Funktion für das Log (Log bleibt bei Neustart erhalten)' + en: 'Activates the caching for the log (log will be restored on restarts)' + logtofile: + type: bool + default: True + description: + de: 'Aktiviert das Schreiben des Logs in eine Datei' + en: 'Activates logging to file' + filepattern: + type: str + default: '{year:04}-{month:02}-{day:02}-{name}.log' + description: + de: 'Definiert das Namensformat für die Logdateien' + en: 'Defines the name patter for the log files' item_attributes: # Definition of item attributes defined by this plugin From 75de32e05f60eefe799550486dc82c927dcf6080 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sun, 9 Sep 2018 13:12:28 +0200 Subject: [PATCH 254/705] OperationLog: Add item attributes and logic parameters to meta data --- operationlog/plugin.yaml | 55 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/operationlog/plugin.yaml b/operationlog/plugin.yaml index 031e75108..1d2e70843 100755 --- a/operationlog/plugin.yaml +++ b/operationlog/plugin.yaml @@ -4,7 +4,7 @@ plugin: type: system # plugin type (gateway, interface, protocol, system, web) description: # Alternative: description in multiple languages de: 'Implementierung seperater Logs' - en: '' + en: 'Implementation for additional logs' maintainer: '? (JanT112)' tester: Sandman60, onkelandy # keywords: iot xyz @@ -50,4 +50,55 @@ parameters: item_attributes: # Definition of item attributes defined by this plugin - + olog: + type: str + description: + de: 'Wenn gesetzt, werden Item-Änderungen in das angegebene Log geloggt' + en: 'When set, item changes will be logged to the given log' + olog_txt: + type: str + description: + de: 'Gibt den Text an, der bei Änderungen geloggt werden soll' + en: 'Specifies the text to log on changes' + olog_level: + type: str + valid_list: + - DEBUG + - INFO + - WARNING + - ERROR + description: + de: 'Gibt den Log-Level an (DEBUG, INFO, WARNING, ERROR)' + en: 'Specifies the log level (DEBUG, INFO, WARNING, ERROR)' + olog_rules: + type: str + description: + de: 'Definiert bestimmte Regel/Mappings für das Logging' + en: 'Declares specific rules/mappings for the logging' + +logic_parameters: + # Definition of logic parameters defined by this plugin + olog: + type: str + description: + de: 'Wenn gesetzt, werden Item-Änderungen in das angegebene Log geloggt' + en: 'When set, item changes will be logged to the given log' + olog_txt: + type: str + description: + de: 'Gibt den Text an, der bei Änderungen geloggt werden soll' + en: 'Specifies the text to log on changes' + olog_level: + type: str + valid_list: + - DEBUG + - INFO + - WARNING + - ERROR + description: + de: 'Gibt den Log-Level an (DEBUG, INFO, WARNING, ERROR)' + en: 'Specifies the log level (DEBUG, INFO, WARNING, ERROR)' + +plugin_functions: NONE + # Definition of function interface of the plugin + From 348a7c0ec00972ec44140c1148f1fcc17a91f875 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sun, 9 Sep 2018 14:20:51 +0200 Subject: [PATCH 255/705] OperationLog: Introduce new parameter `logger` for standard logging This can be used to log the messages to the standard logger implementation of Python. It references the logger to use to log to. --- operationlog/__init__.py | 11 +++++++++-- operationlog/plugin.yaml | 6 ++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/operationlog/__init__.py b/operationlog/__init__.py index ef373c5f9..69e282c2e 100755 --- a/operationlog/__init__.py +++ b/operationlog/__init__.py @@ -40,7 +40,7 @@ class OperationLog(AbLogger, SmartPlugin): ALLOW_MULTIINSTANCE = False def __init__(self, smarthome, name, cache=True, logtofile=True, filepattern="{year:04}-{month:02}-{day:02}-{name}.log", - mapping=['time', 'thread', 'level', 'message'], items=[], maxlen=50): + mapping=['time', 'thread', 'level', 'message'], items=[], maxlen=50, logger=None): log_directory = "var/log/operationlog/" self._sh = smarthome self.shtime = Shtime.get_instance() @@ -61,6 +61,7 @@ def __init__(self, smarthome, name, cache=True, logtofile=True, filepattern="{ye AbLogger.__init__(self, name) self._filepattern = filepattern self._log = lib.log.Log(smarthome, name, mapping, int(maxlen)) + self._logger = None if logger else logging.getLogger(logger) self._path = name self._cachefile = None self._cache = True @@ -76,12 +77,15 @@ def __init__(self, smarthome, name, cache=True, logtofile=True, filepattern="{ye if isinstance(cache, str) and cache in ['False', 'false', 'No', 'no']: self._cache = False info_txt_cache = "" + info_logger_log = ", logging to {}".format(logger) + if not logger: + info_logger_log = "" self._logtofile = True info_txt_log = "OperationLog {}: logging to file {}{}, keeping {} entries in memory".format(self.name, self.log_directory, self._filepattern, int(self._maxlen)) if isinstance(logtofile, str) and logtofile in ['False', 'false', 'No', 'no']: self._logtofile = False - self.logger.info(info_txt_log + info_txt_cache) + self.logger.info(info_txt_log + info_txt_cache + info_logger_log) ############################################################# # Cache @@ -316,6 +320,9 @@ def log(self, logvalues, level='INFO'): except Exception as e: self.logger.warning("OperationLog {}: could not update cache {}".format(self._path, e)) + if self._logger: + self._logger.log(logging.getLevelName(level), ' '.join(map(str, logvalues))) + ##################################################################### # Cache Methods diff --git a/operationlog/plugin.yaml b/operationlog/plugin.yaml index 1d2e70843..36bfec7f8 100755 --- a/operationlog/plugin.yaml +++ b/operationlog/plugin.yaml @@ -47,6 +47,12 @@ parameters: description: de: 'Definiert das Namensformat für die Logdateien' en: 'Defines the name patter for the log files' + logger: + type: str + default: '' + description: + de: 'Logt zusätzlich in den angegebenen Logger (z.B. "plugins.operationlog.logger")' + en: 'Additionally log to the given logger (e.g. "plugins.operationlog.logger")' item_attributes: # Definition of item attributes defined by this plugin From 6cae8afc59c34ce69536a4d81f3bd360753d7870 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sun, 9 Sep 2018 20:45:29 +0200 Subject: [PATCH 256/705] deactivating duplicate entries on creation, some minor fixes, sun calculation entries update, fixed interpolation for non rrule entries --- uzsu/__init__.py | 155 ++++++++++++++++++++++++++++++++--------------- uzsu/plugin.yaml | 2 +- 2 files changed, 107 insertions(+), 50 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 9a289a704..e796e9d13 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -124,7 +124,7 @@ def run(self): for item in self._items: self._items[item]['interpolation']['itemtype'] = self._add_type(item) - item(self._items[item]) + item(self._items[item], 'USZU Plugin', 'itemtype') if 'active' in self._items[item] and self._items[item]['active']: self._schedule(item, caller='run') @@ -133,6 +133,12 @@ def stop(self): Stop method for the plugin """ self.logger.debug('{}: stop method called'.format(self._name)) + for item in self._items: + try: + self.scheduler_remove('uzsu_{}'.format(item)) + self.logger.debug('{}: Removing scheduler for item {}'.format(self._name, item)) + except Exception as err: + self.logger.debug('{}: Scheduler for item {} not removed. Problem: {}'.format(self._name, item, err)) self.alive = False def _update_all_suns(self, caller=None): @@ -164,9 +170,26 @@ def _update_sun(self, item, caller=None): _sunset = _sunset.astimezone(self._timezone) self._items[item]['sunrise'] = '{:02}:{:02}'.format(_sunrise.hour, _sunrise.minute) self._items[item]['sunset'] = '{:02}:{:02}'.format(_sunset.hour, _sunset.minute) - self.logger.debug('{}: Updating sun entries for item {}, called by {}. sunrise: {}, sunset: {}'.format( + self.logger.debug('{}: Updating sun entries for item {}, triggered by {}. sunrise: {}, sunset: {}'.format( self._name, item, caller, self._items[item]['sunrise'], self._items[item]['sunset'])) + def _update_suncalc(self, item, entry, entryindex, entryvalue): + update = False + if entry.get('calculated'): + update = True if entry == self._items[item]['list'][entryindex] else update + with mock.patch.dict(entry, calculated=entryvalue): + update = True if entry == self._items[item]['list'][entryindex] else update + else: + update = True + if update is True and not entry.get('calculated') == entryvalue: + self.logger.debug("{}: Updated calculated time for item {} entry {} with {}.".format( + self._name, item, self._items[item]['list'][entryindex], entryvalue)) + self._items[item]['list'][entryindex]['calculated'] = entryvalue + item(self._items[item], 'USZU Plugin', 'update_sun') + else: + self.logger.debug("{}: Sun calculation {} entry not updated for item {} with value {}".format( + self._name, entryvalue, item, entry.get('calculated'))) + def _add_type(self, item): """ Adding the type of the item that is changed by the uzsu to the item dict @@ -208,14 +231,42 @@ def parse_item(self, item): self._items[item] = item() try: self._items[item]['interpolation']['initialized'] = False - item(self._items[item]) + item(self._items[item], 'USZU Plugin', 'init') except Exception: self._items[item]['interpolation'] = {} self._items[item]['interpolation']['initialized'] = False - item(self._items[item]) + item(self._items[item], 'USZU Plugin', 'init') self.logger.debug('{}: Dict for item {} is: {}'.format(self._name, item, self._items[item])) return self.update_item + def _remove_dupes(self, item): + self._items[item]['list'] = [i for n, i in enumerate(self._items[item]['list']) + if i not in self._items[item]['list'][:n]] + self.logger.debug('{}: Removed duplicate entries for item {}.'.format(self._name, item)) + compare_entries = item.prev_value() + if compare_entries.get('list'): + newentries = [] + [newentries.append(i) for i in self._items[item]['list'] if i not in compare_entries['list']] + self.logger.debug('{}: Got update for item {}: {}'.format(self._name, item, newentries)) + for entry in self._items[item]['list']: + for new in newentries: + found = False + if not entry.get('value') == new.get('value') and new.get('active') is True: + try: + with mock.patch.dict(entry, value=new.get('value'), calculated=new['calculated']): + found = True if entry == new else found + except Exception: + with mock.patch.dict(entry, value=new.get('value')): + found = True if entry == new else found + if found is True: + self._items[item]['list'][self._items[item]['list'].index(entry)].update({'active': False}) + time = entry['time'] + oldvalue, newvalue = entry['value'], new['value'] + self.logger.warning('{}: Set old entry for item {} at {} with value {} to inactive' + ' because newer active entry with value {} found.'.format( + self._name, item, time, oldvalue, newvalue)) + item(self._items[item], 'USZU Plugin', 'update') + def update_item(self, item, caller=None, source=None, dest=None): """ This is called by smarthome engine when the item changes, e.g. by Visu or by the command line interface @@ -227,28 +278,13 @@ def update_item(self, item, caller=None, source=None, dest=None): :param dest: if given it represents the dest """ self._items[item] = item() - if self._remove_duplicates is True: - compare_entries = item.prev_value() - newentries = [] - [newentries.append(i) for i in self._items[item]['list'] if i not in compare_entries['list']] - self.logger.debug('{}: Got update for item {}: {}'.format(self._name, item, newentries)) - todel = [] - for entry in self._items[item]['list']: - for new in newentries: - found = False - if not entry.get('value') == new.get('value'): - with mock.patch.dict(entry, value=new.get('value')): - found = True if entry == new else False - if found is True: - todel.append(entry) - finallist = [n for n in self._items[item]['list'] if n not in todel] - self._items[item]['list'] = finallist - item(self._items[item]) - if todel: - self.logger.warning('Deleted the following entries from the actual dict' - ' because the entry got updated: {}'.format(todel)) - - self._schedule(item, caller='update') + self.logger.debug('{}: Update Item {}, Caller {}, Source {}, Dest {}.'.format( + self._name, item, caller, source, dest)) + # Removing Duplicates + if self._remove_duplicates is True and self._items[item].get('list') and not caller == 'USZU Plugin': + self._remove_dupes(item) + if not caller == 'USZU Plugin': + self._schedule(item, caller='update') def _schedule(self, item, caller=None): """ @@ -260,7 +296,8 @@ def _schedule(self, item, caller=None): :param caller: if given it represents the callers name """ self.scheduler_remove('uzsu_{}'.format(item)) - self.logger.debug('{}: called by {}, changed by: {}'.format(self._name, caller, item.changed_by())) + self.logger.debug('{}: Schedule Item {}, Trigger: {}, Changed by: {}'.format( + self._name, item, caller, item.changed_by())) _next = None _value = None self._update_sun(item, caller='schedule') @@ -270,10 +307,10 @@ def _schedule(self, item, caller=None): self._name, self.get_iattr_value(item.conf, ITEM_TAG[0]))) else: self._itpl.clear() - for entry in self._items[item]['list']: - next, value = self._get_time(entry, 'next', item) + for i, entry in enumerate(self._items[item]['list']): + next, value = self._get_time(entry, 'next', item, i) self._get_time(entry, 'previous', item) - item(self._items[item]) + item(self._items[item], 'USZU Plugin', 'schedule') if next is not None: self.logger.debug("{}: uzsu active entry for item {} with datetime {}, value {}" " and tzinfo {}".format(self._name, item, next, value, next.tzinfo)) @@ -288,8 +325,7 @@ def _schedule(self, item, caller=None): else: self.logger.debug("{}: uzsu active entry for item {} keep {}, value {} and tzinfo {}".format( self._name, item, _next, _value, _next.tzinfo)) - - if _next and _value is not None and 'active' in self._items[item] and self._items[item]['active']: + if _next and _value is not None and 'active' in self._items[item] and self._items[item]['active'] is True: _reset_interpolation = False _interval = self._items[item]['interpolation'].get('interval') _interval = 5 if not _interval else int(_interval) @@ -322,7 +358,7 @@ def _schedule(self, item, caller=None): self.logger.info("{}: Looking if there was a value set after {} for item {}".format( self._name, _timediff, item)) self._items[item]['interpolation']['initialized'] = True - item(self._items[item]) + item(self._items[item], 'USZU Plugin', 'init') if cond1 and not cond2 and cond3: self._set(item=item, value=_initvalue, caller='scheduler') self.logger.info("{}: Updated item {} on startup with value {} from time {}".format( @@ -368,7 +404,7 @@ def _schedule(self, item, caller=None): " to not enough values set in the UZSU.".format(self._name, _value, item)) if _reset_interpolation is True: self._items[item]['interpolation']['type'] = 'none' - item(self._items[item]) + item(self._items[item], 'USZU Plugin', 'reset_interpolation') else: self.logger.debug("{}: will add scheduler named uzsu_{} with datetime {} and tzinfo {}" " and value {}".format(self._name, item, _next, _next.tzinfo, _value)) @@ -393,7 +429,7 @@ def _set(self, **kwargs): if not caller: self._schedule(item, caller='set') - def _get_time(self, entry, timescan, item=None): + def _get_time(self, entry, timescan, item=None, entryindex=None): """ Returns the next and previous execution time and value :param entry: a dictionary that may contain the following keys: @@ -418,6 +454,7 @@ def _get_time(self, entry, timescan, item=None): value = entry['value'] active = entry['active'] today = datetime.today() + tomorrow = today + timedelta(days=1) yesterday = today - timedelta(days=1) weekbefore = today - timedelta(days=7) time = entry['time'] @@ -430,10 +467,10 @@ def _get_time(self, entry, timescan, item=None): try: rrule = rrulestr(entry['rrule'], dtstart=datetime.combine( weekbefore, parser.parse(time.strip()).time())) - self.logger.debug("{}: Created rrule:'{}' for time:'{}'".format( + self.logger.debug("{}: Created rrule: '{}' for time:'{}'".format( self._name, str(rrule).replace('\n', ';'), time)) except ValueError: - self.logger.debug("{}: Could not create a rrule from rrule:'{}' and time:'{}'".format( + self.logger.debug("{}: Could not create a rrule from rrule: '{}' and time:'{}'".format( self._name, entry['rrule'], time)) if 'sun' in time: rrule = rrulestr(entry['rrule'], dtstart=datetime.combine( @@ -452,7 +489,9 @@ def _get_time(self, entry, timescan, item=None): return None, None if 'sun' in time: next = self._sun(datetime.combine(dt.date(), datetime.min.time()).replace(tzinfo=self._timezone), time, timescan) - self.logger.debug("{}: Result parsing time (rrule){}: {}".format(self._name, time, next)) + self.logger.debug("{}: Result parsing time (rrule) {}: {}".format(self._name, time, next)) + if entryindex: + self._update_suncalc(item, entry, entryindex, next.strftime("%H:%M")) else: next = datetime.combine(dt.date(), parser.parse(time.strip()).time()).replace(tzinfo=self._timezone) cond_next = next > datetime.now(self._timezone) and timescan == 'next' @@ -466,31 +505,49 @@ def _get_time(self, entry, timescan, item=None): self.logger.debug("{}: Return from rrule previous: {}, value {}.".format(self._name, next, value)) return next, value if 'sun' in time: - next = self._sun(datetime.combine(today, datetime.min.time()).replace(tzinfo=self._timezone), time, timescan) - self.logger.debug("{}: Result parsing time (sun) {}: {}".format(self._name, time, next)) - entry_calculated = self._items[item].get('list').index(entry) - self._items[item].get('list')[entry_calculated]['calculated'] = next.strftime("%H:%M") - self.logger.debug("{}: Updated calculated time for item {}.".format( - self._name, item)) + next = self._sun(datetime.combine(today, datetime.min.time()).replace( + tzinfo=self._timezone), time, timescan) + cond_today = next > datetime.now(self._timezone) and timescan == 'next' + if cond_today: + self.logger.debug("{}: Result parsing time today (sun) {}: {}".format(self._name, time, next)) + if entryindex: + self._update_suncalc(item, entry, entryindex, next.strftime("%H:%M")) + else: + self._itpl[next.timestamp() * 1000.0] = value + self.logger.debug("{}: Include previous today: {}, value {} for interpolation.".format(self._name, next, value)) + if entryindex: + self._update_suncalc(item, entry, entryindex, next.strftime("%H:%M")) + next = self._sun(datetime.combine(tomorrow, datetime.min.time()).replace( + tzinfo=self._timezone), time, timescan) + self.logger.debug("{}: Result parsing time tomorrow (sun) {}: {}".format(self._name, time, next)) else: next = datetime.combine(today, parser.parse(time.strip()).time()).replace(tzinfo=self._timezone) - + cond_today = next > datetime.now(self._timezone) and timescan == 'next' + if not cond_today: + self._itpl[next.timestamp() * 1000.0] = value + self.logger.debug("{}: Include next today: {}, value {} for interpolation.".format(self._name, next, value)) + next = datetime.combine(tomorrow, parser.parse(time.strip()).time()).replace(tzinfo=self._timezone) cond1 = next.date() == today.date() cond2 = next.date() - timedelta(days=1) == yesterday.date() + cond3 = next.date() == tomorrow.date() cond_next = next > datetime.now(self._timezone) and timescan == 'next' cond_previous_today = next < datetime.now(self._timezone) and timescan == 'previous' cond_previous_yesterday = next - timedelta(days=1) < datetime.now(self._timezone) and timescan == 'previous' if next and cond1 and cond_next: self._itpl[next.timestamp() * 1000.0] = value - self.logger.debug("{}: Return next: {}, value {}".format(self._name, next, value)) + self.logger.debug("{}: Return next today: {}, value {}".format(self._name, next, value)) + return next, value + if next and cond3 and cond_next: + self._itpl[next.timestamp() * 1000.0] = value + self.logger.debug("{}: Return next tomorrow: {}, value {}".format(self._name, next, value)) return next, value if next and cond1 and cond_previous_today: self._itpl[next.timestamp() * 1000.0] = value - self.logger.debug("{}: Return previous: {}, value {}".format(self._name, next, value)) + self.logger.debug("{}: Return previous today: {}, value {}".format(self._name, next, value)) return next, value if next and cond2 and cond_previous_yesterday: self._itpl[(next - timedelta(days=1)).timestamp() * 1000.0] = value - self.logger.debug("{}: Return previous: {}, value {}".format(self._name, next - timedelta(days=1), value)) + self.logger.debug("{}: Return previous yesterday: {}, value {}".format(self._name, next - timedelta(days=1), value)) return next - timedelta(days=1), value except Exception as e: self.logger.error("{}: Error '{}' parsing time: {}".format(self._name, time, e)) @@ -730,7 +787,7 @@ def index(self, action=None, item_id=None, item_path=None, reload=None): :return: contents of the template after beeing rendered """ - #item = self.plugin.get_sh().return_item(item_path) + # item = self.plugin.get_sh().return_item(item_path) tmpl = self.tplenv.get_template('index.html') # add values to be passed to the Jinja2 template eg: tmpl.render(p=self.plugin, interface=interface, ...) return tmpl.render(p=self.plugin, diff --git a/uzsu/plugin.yaml b/uzsu/plugin.yaml index f5883097f..99ac5ce93 100755 --- a/uzsu/plugin.yaml +++ b/uzsu/plugin.yaml @@ -20,7 +20,7 @@ parameters: # Definition of parameters to be configured in etc/plugin.yaml remove_duplicates: type: bool - default: False + default: True description: de: 'Falls True, werden Einträge mit exakt den selben Einstellungen, aber unterschiedlichem Wert durch einen neu geätigten Eintrag ersetzt' en: 'If True, existing entries with exactly the same settings except the value get replaced by the new entry' From 2155a93bbb997bffd9d2bf3fe8fc21b08589cde3 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sun, 9 Sep 2018 20:55:25 +0200 Subject: [PATCH 257/705] Resurrected additional info on item update --- gpio/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gpio/__init__.py b/gpio/__init__.py index c8171a5da..80560da02 100755 --- a/gpio/__init__.py +++ b/gpio/__init__.py @@ -80,7 +80,7 @@ def run(self): self._initdict[sensor] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f") except Exception: self._initdict[sensor] = False - item(value) + item(value, 'GPIO Plugin', 'run') GPIO.add_event_detect(sensor, GPIO.BOTH, callback=self.get_sensors, bouncetime=self._bouncetime) self.logger.info("{}: Adding Event Detection for Pin {}. Initial value is {}".format( self._name, sensor, value)) @@ -104,7 +104,7 @@ def parse_item(self, item): GPIO.setup(out_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) self._itemsdict[out_pin] = item value = GPIO.input(out_pin) - item(value) + item(value, 'GPIO Plugin', 'parse') GPIO.add_event_detect(out_pin, GPIO.BOTH, callback=self.get_sensors, bouncetime=self._bouncetime) self.logger.info("{}: Adding Event Detection for Output Pin {}. Initial value is {}".format( self._name, out_pin, value)) From 46f3694e74b2024233dc755596a0cb8c264ea8d0 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Mon, 10 Sep 2018 13:55:30 +0200 Subject: [PATCH 258/705] make all entries rrule entries, so interpolation works in all cases --- uzsu/__init__.py | 28 ++++++++++++++++++++------- uzsu/locale.yaml | 2 +- uzsu/webif/static/img/plugin_logo.svg | 0 uzsu/webif/templates/index.html | 7 ++++--- 4 files changed, 26 insertions(+), 11 deletions(-) mode change 100644 => 100755 uzsu/webif/static/img/plugin_logo.svg diff --git a/uzsu/__init__.py b/uzsu/__init__.py index e796e9d13..22721e6c5 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -460,7 +460,9 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): time = entry['time'] if not active: return None, None - if 'rrule' in entry and entry['rrule']: + if 'rrule' in entry: + if entry['rrule'] == '': + entry['rrule'] = 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU' if 'dtstart' in entry: rrule = rrulestr(entry['rrule'], dtstart=entry['dtstart']) else: @@ -507,8 +509,8 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): if 'sun' in time: next = self._sun(datetime.combine(today, datetime.min.time()).replace( tzinfo=self._timezone), time, timescan) - cond_today = next > datetime.now(self._timezone) and timescan == 'next' - if cond_today: + cond_future = next > datetime.now(self._timezone) and timescan == 'next' + if cond_future: self.logger.debug("{}: Result parsing time today (sun) {}: {}".format(self._name, time, next)) if entryindex: self._update_suncalc(item, entry, entryindex, next.strftime("%H:%M")) @@ -522,8 +524,8 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): self.logger.debug("{}: Result parsing time tomorrow (sun) {}: {}".format(self._name, time, next)) else: next = datetime.combine(today, parser.parse(time.strip()).time()).replace(tzinfo=self._timezone) - cond_today = next > datetime.now(self._timezone) and timescan == 'next' - if not cond_today: + cond_future = next > datetime.now(self._timezone) and timescan == 'next' + if not cond_future: self._itpl[next.timestamp() * 1000.0] = value self.logger.debug("{}: Include next today: {}, value {} for interpolation.".format(self._name, next, value)) next = datetime.combine(tomorrow, parser.parse(time.strip()).time()).replace(tzinfo=self._timezone) @@ -593,7 +595,7 @@ def _sun(self, dt, tstr, timescan): if not uzsu_sun: return - self.logger.debug("{}: Given param dt={}, tz={}".format(self._name, dt, dt.tzinfo)) + self.logger.debug("{}: Given param dt={}, tz={} for {}".format(self._name, dt, dt.tzinfo, timescan)) # now start into parsing details self.logger.debug('{}: Examine param time string: {}'.format(self._name, tstr)) @@ -713,6 +715,18 @@ def _get_dependant(self, item): self._name, err)) return _itemvalue + def get_items(self): + """ + Getting a sorted item list with uzsu config + + :return: sorted itemlist + """ + sortedlist = sorted([k.id() for k in self._items.keys()]) + finallist = [] + for i in sortedlist: + finallist.append(self.itemsApi.return_item(i)) + return finallist + def init_webinterface(self): """" Initialize the web interface for this plugin @@ -787,7 +801,7 @@ def index(self, action=None, item_id=None, item_path=None, reload=None): :return: contents of the template after beeing rendered """ - # item = self.plugin.get_sh().return_item(item_path) + item = self.plugin.get_sh().return_item(item_path) tmpl = self.tplenv.get_template('index.html') # add values to be passed to the Jinja2 template eg: tmpl.render(p=self.plugin, interface=interface, ...) return tmpl.render(p=self.plugin, diff --git a/uzsu/locale.yaml b/uzsu/locale.yaml index 7d227e3d2..33a03f176 100755 --- a/uzsu/locale.yaml +++ b/uzsu/locale.yaml @@ -4,7 +4,7 @@ plugin_translations: 'UZSU Item': {'de': '=', 'en': '='} 'Abhängige Items (mit Typ)': {'de': '=', 'en': 'Dependant Item (with type)'} 'Wert des abhängigen Items': {'de': '=', 'en': 'Value of dependant Item'} - 'Interpolation': {'de': '=', 'en': '='} + 'Interpolation (Intervall)': {'de': '=', 'en': 'Interpolation (interval)'} 'Back in Time': {'de': '=', 'en': '='} 'Sonnenaufgang': {'de': '=', 'en': 'sun rise'} 'Sonnenuntergang': {'de': '=', 'en': 'sun set'} diff --git a/uzsu/webif/static/img/plugin_logo.svg b/uzsu/webif/static/img/plugin_logo.svg old mode 100644 new mode 100755 diff --git a/uzsu/webif/templates/index.html b/uzsu/webif/templates/index.html index d52887d5e..79db83755 100755 --- a/uzsu/webif/templates/index.html +++ b/uzsu/webif/templates/index.html @@ -60,11 +60,11 @@ {{ _('UZSU Item') }} {{ _('Abhängige Items (mit Typ)') }} {{ _('Wert des abhängigen Items') }} - {{ _('Interpolation') }} + {{ _('Interpolation (Intervall)') }} {{ _('Back in Time') }} - {% for item in p._items %} + {% for item in p.get_items() %} {% if p.has_iattr(item.conf, 'uzsu_item') %} {% if p._items[item]['active'] == True %} {% set color = 'green' %} @@ -77,7 +77,8 @@ ({{ p._items[item]['interpolation']['itemtype'] }}) {{ p._get_dependant(item) }} {% if p._items[item]['interpolation']['type'] %} - {{ p._items[item]['interpolation']['type'] }}{% else %}-{% endif %} + {{ p._items[item]['interpolation']['type'] }} ({% if p._items[item]['interpolation']['interval'] %}{{ p._items[item]['interpolation']['interval'] }}{% else %}5{% endif %}) + {% else %}-{% endif %} {% if p._items[item]['interpolation']['initage'] %} {{ p._items[item]['interpolation']['initage'] }}{% else %}-{% endif %} From ac2fb36f4c490cb029cd3c7d75e1468a579503af Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Mon, 10 Sep 2018 21:43:57 +0200 Subject: [PATCH 259/705] improved error handling and web interface, added functions to use in logics --- uzsu/README.md | 31 ++++++++- uzsu/__init__.py | 117 ++++++++++++++++++++++++++------ uzsu/locale.yaml | 1 + uzsu/webif/templates/index.html | 31 +++++++-- 4 files changed, 153 insertions(+), 27 deletions(-) diff --git a/uzsu/README.md b/uzsu/README.md index 1b1ac7667..7399b9390 100755 --- a/uzsu/README.md +++ b/uzsu/README.md @@ -39,11 +39,11 @@ someroom: anotheritem: type: dict - uzsu_item: someroom.someitem + uzsu_item: someroom.someitem #using smarthomeNG 1.5.1 develop you can use '..' to define a relative item cache: 'True' ``` -If you specify the ``cache: True`` as well, then you're switching entries will be there even if you restart smarthome.py. +If you specify the ``cache: True`` as well, then your switching entries will be there even if you restart smarthome.py. ## Item Data Format @@ -70,6 +70,33 @@ Each UZSU item is of type list. Each list entry has to be a dict with specific k * __initizialized__: bool, gets set automatically at startup as soon as a valid UZSU entry was found in the specified initage and the item was indeed initialized with that value. +## Additional item functions + +You can use these function in logics to query or set yout uzsu item: + +``` +# query the next scheduled value and time +sh.eg.wohnen.kugellampe.uzsu.planned() + +# query the interpolation settings +sh.eg.wohnen.kugellampe.uzsu.interpolation() + +# query whether the uzsu is set active or not +sh.eg.wohnen.kugellampe.uzsu.activate() + +# set the uzsu active or inactive +sh.eg.wohnen.kugellampe.uzsu.activate(True/False) + +# set interpolation options +sh.eg.wohnen.kugellampe.uzsu.activate(type='linear/none/cubic', interval=5, backintime=0) + +# clear your settings of the uzsu item. BE CAREFUL! +sh.eg.wohnen.kugellampe.uzsu.clear(True) + + +``` + + ## Example Activates the light every other day at 16:30 and deactivates it at 17:30 for five times: diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 22721e6c5..540b8ffe5 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -53,6 +53,7 @@ # ]}) import logging +import functools from lib.model.smartplugin import * from lib.item import Items from lib.shtime import Shtime @@ -100,6 +101,8 @@ def __init__(self, smarthome): self._sh = smarthome self._uzsu_sun = None self._items = {} + self._planned = {} + self._update_count = {'todo': 0, 'done': 0} self._itpl = OrderedDict() self.init_webinterface() self.logger.info('{}: Init with timezone {}'.format(self._name, self._timezone)) @@ -116,16 +119,20 @@ def run(self): self.logger.debug('{}: run method called'.format(self._name)) self.alive = True self.scheduler_add('uzsu_sunupdate', self._update_all_suns, value={'caller': 'scheduler'}, cron='0 0 * *') - self.scheduler_trigger('uzsu_sunupdate') - self.logger.info('{}: Triggering sun update and scheduling for midnight'.format(self._name)) - - # if you want to create child threads, do not make them daemon = True! - # They will not shutdown properly. (It's a python bug) + self.logger.info('{}: Adding sun update schedule for midnight'.format(self._name)) for item in self._items: self._items[item]['interpolation']['itemtype'] = self._add_type(item) item(self._items[item], 'USZU Plugin', 'itemtype') - if 'active' in self._items[item] and self._items[item]['active']: + cond1 = self._items[item].get('active') and self._items[item]['active'] is True + cond2 = self._items[item].get('list') + if cond1 and cond2: + self._update_count['todo'] = self._update_count.get('todo') + 1 + + for item in self._items: + cond1 = self._items[item].get('active') and self._items[item]['active'] is True + cond2 = self._items[item].get('list') + if cond1 and cond2: self._schedule(item, caller='run') def stop(self): @@ -149,7 +156,10 @@ def _update_all_suns(self, caller=None): :type caller: str """ for item in self._items: - self._update_sun(item) + success = self._update_sun(item) + if success: + self.logger.debug('{}: Updating item {}'.format(self._name, item)) + item(self._items[item]) def _update_sun(self, item, caller=None): """ @@ -160,18 +170,23 @@ def _update_sun(self, item, caller=None): :type caller: str :type item: item """ - self._uzsu_sun = self._create_sun() - self._items[item] = item() - _sunrise = self._uzsu_sun.rise() - _sunset = self._uzsu_sun.set() - if _sunrise.tzinfo == tzutc(): - _sunrise = _sunrise.astimezone(self._timezone) - if _sunset.tzinfo == tzutc(): - _sunset = _sunset.astimezone(self._timezone) - self._items[item]['sunrise'] = '{:02}:{:02}'.format(_sunrise.hour, _sunrise.minute) - self._items[item]['sunset'] = '{:02}:{:02}'.format(_sunset.hour, _sunset.minute) - self.logger.debug('{}: Updating sun entries for item {}, triggered by {}. sunrise: {}, sunset: {}'.format( - self._name, item, caller, self._items[item]['sunrise'], self._items[item]['sunset'])) + try: + self._uzsu_sun = self._create_sun() + self._items[item] = item() + _sunrise = self._uzsu_sun.rise() + _sunset = self._uzsu_sun.set() + if _sunrise.tzinfo == tzutc(): + _sunrise = _sunrise.astimezone(self._timezone) + if _sunset.tzinfo == tzutc(): + _sunset = _sunset.astimezone(self._timezone) + self._items[item]['sunrise'] = '{:02}:{:02}'.format(_sunrise.hour, _sunrise.minute) + self._items[item]['sunset'] = '{:02}:{:02}'.format(_sunset.hour, _sunset.minute) + self.logger.debug('{}: Updated sun entries for item {}, triggered by {}. sunrise: {}, sunset: {}'.format( + self._name, item, caller, self._items[item]['sunrise'], self._items[item]['sunset'])) + success = True + except Exception: + success = False + return success def _update_suncalc(self, item, entry, entryindex, entryvalue): update = False @@ -211,6 +226,55 @@ def _add_type(self, item): self._name, err)) return _itemtype + def _logics_activate(self, activevalue=None, item=None): + if isinstance(activevalue, str): + if activevalue.lower() in ['1', 'yes', 'true', 'on']: + activevalue = True + elif activevalue.lower() in ['0', 'no', 'false', 'off']: + activevalue = False + else: + self.logger.warning("{}: Value to activate item {} has to be True or False".format(self._name, item)) + if isinstance(activevalue, bool): + self._items[item] = item() + self._items[item]['active'] = activevalue + self.logger.info("{}: Item {} is set via logic to: {}".format(self._name, item, activevalue)) + item(self._items[item], 'UZSU Plugin', 'logic') + if activevalue is None: + return self._items[item].get('active') + + def _logics_interpolation(self, type=None, interval=5, backintime=0, item=None): + if type is None: + return self._items[item].get('interpolation') + else: + self._items[item] = item() + self._items[item]['interpolation']['type'] = str(type).lower() + self._items[item]['interpolation']['interval'] = int(interval) + self._items[item]['interpolation']['initage'] = int(backintime) + self.logger.info("{}: Item {} interpolation is set via logic to: type={}, interval={}, backintime={}".format( + self._name, item, type, interval, backintime)) + item(self._items[item], 'UZSU Plugin', 'logic') + + def _logics_clear(self, clear=False, item=None): + if isinstance(clear, str): + if clear.lower() in ['1', 'yes', 'true', 'on']: + clear = True + else: + self.logger.warning("{}: Value to clear uzsu item {} has to be True".format(self._name, item)) + if isinstance(clear, bool) and clear is True: + self._items[item].clear() + self._items[item] = {'interpolation': {}, 'active': False} + self.logger.info("{}: UZSU settings for item {} are cleared".format(self._name, item)) + item(self._items[item], 'UZSU Plugin', 'clear') + + def _logics_planned(self, item=None): + try: + self.logger.info("{}: Item {} is going to be set to {} at {}".format( + self._name, item, self._planned[item]['value'], self._planned[item]['next'])) + return self._planned[item] + except Exception: + self.logger.info("{}: Nothing planned for item {}. {}".format(self._name, item, self._planned)) + return None + def parse_item(self, item): """ Default plugin parse_item method. Is called when the plugin is initialized. @@ -228,6 +292,13 @@ def parse_item(self, item): """ if self.has_iattr(item.conf, ITEM_TAG[0]): item.expand_relativepathes(ITEM_TAG[0], '', '') + + # add functions for use in logics and webif + item.activate = functools.partial(self._logics_activate, item=item) + item.interpolation = functools.partial(self._logics_interpolation, item=item) + item.clear = functools.partial(self._logics_clear, item=item) + item.planned = functools.partial(self._logics_planned, item=item) + self._items[item] = item() try: self._items[item]['interpolation']['initialized'] = False @@ -305,6 +376,9 @@ def _schedule(self, item, caller=None): if not self._items[item]['interpolation'].get('itemtype'): self.logger.error("{}: item '{}' to be set by uzsu does not exist.".format( self._name, self.get_iattr_value(item.conf, ITEM_TAG[0]))) + elif not self._items[item].get('list'): + self.logger.warning("{}: uzsu item '{}' is active but has no entries.".format( + self._name, item)) else: self._itpl.clear() for i, entry in enumerate(self._items[item]['list']): @@ -408,7 +482,12 @@ def _schedule(self, item, caller=None): else: self.logger.debug("{}: will add scheduler named uzsu_{} with datetime {} and tzinfo {}" " and value {}".format(self._name, item, _next, _next.tzinfo, _value)) + self._planned[item] = {'value': _value, 'next': _next.strftime('%Y-%m-%d %H:%M')} + self._update_count['done'] = self._update_count.get('done') + 1 self.scheduler_add('uzsu_{}'.format(item), self._set, value={'item': item, 'value': _value}, next=_next) + if self._update_count.get('done') == self._update_count.get('todo'): + self.scheduler_trigger('uzsu_sunupdate', by='UZSU Plugin') + self._update_count = {'done': 0, 'todo': 0} def _set(self, **kwargs): """ diff --git a/uzsu/locale.yaml b/uzsu/locale.yaml index 33a03f176..bd3d4c22e 100755 --- a/uzsu/locale.yaml +++ b/uzsu/locale.yaml @@ -1,6 +1,7 @@ plugin_translations: # Translations for the plugin specially for the web interface 'Die folgenden Items sind dem UZSU Plugin zugewiesen': {'de': '=', 'en': 'The following items are assigned to the UZSU plugin'} + 'Klick auf ein Item um dessen Konfiguration anzuzeigen': {'de': '=', 'en': 'Click on an item to show its configuration'} 'UZSU Item': {'de': '=', 'en': '='} 'Abhängige Items (mit Typ)': {'de': '=', 'en': 'Dependant Item (with type)'} 'Wert des abhängigen Items': {'de': '=', 'en': 'Value of dependant Item'} diff --git a/uzsu/webif/templates/index.html b/uzsu/webif/templates/index.html index 79db83755..e293d95c2 100755 --- a/uzsu/webif/templates/index.html +++ b/uzsu/webif/templates/index.html @@ -10,6 +10,14 @@ window.location.href = final; }; } + function togglevis(id) { + var div = document.getElementById(id); + div.style.display = div.style.display == "none" ? "block" : "none"; + } + function hide(id) { + document.getElementById(id).style.display = "none"; + } + {% endblock scripts %} {% set logo_frame = false %} @@ -52,7 +60,8 @@
- {{ _('Die folgenden Items sind dem UZSU Plugin zugewiesen') }}: + {{ _('Die folgenden Items sind dem UZSU Plugin zugewiesen') }}. + {{ _('Klick auf ein Item um dessen Konfiguration anzuzeigen') }}
@@ -66,16 +75,26 @@ {% for item in p.get_items() %} {% if p.has_iattr(item.conf, 'uzsu_item') %} - {% if p._items[item]['active'] == True %} - {% set color = 'green' %} + + {% if p._logics_planned(item) == none and p._items[item]['active'] == True %} + {% set color = 'red' %} + {% elif p._items[item]['active'] == True %} + {% set color = 'green' %} {% else %} {% set color = 'gray' %} {% endif %} - + + - + ({{ p._items[item]['interpolation']['itemtype'] }}) + + + From 64e4750a61bf8e6dbe75a8fe76a8060d2f48059f Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Tue, 11 Sep 2018 09:24:04 +0200 Subject: [PATCH 260/705] tweaked CSS for webif --- avdevice/webif/static/avdevice.css | 34 ++++++++++++++++++++++++++ avdevice/webif/templates/index.html | 38 +++++++++++++++-------------- 2 files changed, 54 insertions(+), 18 deletions(-) create mode 100755 avdevice/webif/static/avdevice.css diff --git a/avdevice/webif/static/avdevice.css b/avdevice/webif/static/avdevice.css new file mode 100755 index 000000000..0944e9e42 --- /dev/null +++ b/avdevice/webif/static/avdevice.css @@ -0,0 +1,34 @@ +div.container-fluid { + margin-top:250px; +} + +div.container-fluid.m-3 .col-sm-7 .table { + table-layout:fixed; +} + +div.container-fluid.m-3 .col-sm-7 { + min-width:390px; +} + +div.container-fluid.m-3 .col-sm-7 .table td.py-1 { + min-width:160px; + overflow: hidden; + text-overflow: ellipsis; + word-wrap:break-word; +} + +div.container-fluid.m-3 .col-sm-7 .table td.header { + max-width:180px; + min-width: 150px; + width:150px; +} + +div.container-fluid.m-3 .col-sm-7 .table td.content div { + max-height: 45px; + display: block; +} + +div.container-fluid.m-3 .col-sm-7 .table .py-1 div.oneliner { + max-height: 25px; + display: block; +} diff --git a/avdevice/webif/templates/index.html b/avdevice/webif/templates/index.html index 04299835e..d5235f21f 100755 --- a/avdevice/webif/templates/index.html +++ b/avdevice/webif/templates/index.html @@ -12,6 +12,12 @@ } {% endblock scripts %} + +{%- block styles %} +{{ super() }} + +{%- endblock styles %} + {% set logo_frame = false %} @@ -50,9 +56,8 @@
{{ item._path }} {{ p.get_iattr_value(item.conf, 'uzsu_item') }} - ({{ p._items[item]['interpolation']['itemtype'] }}){{ p._get_dependant(item) }}{{ p._get_dependant(item) }}
+ {% if p._logics_planned(item) != none %}{{ p._logics_planned(item) }}{% endif %} + {% if p._logics_planned(item) == none and p._items[item]['active'] == True %} + ACTIVE, BUT NO ENTRIES!{% endif %} +
{% if p._items[item]['interpolation']['type'] %} {{ p._items[item]['interpolation']['type'] }} ({% if p._items[item]['interpolation']['interval'] %}{{ p._items[item]['interpolation']['interval'] }}{% else %}5{% endif %}) {% else %}-{% endif %}
- + - - - - - - - + + + - + {% if not p._depend0_volume0 and not p._depend0_power0 %}None{% endif %} - - + + - - + +
{{ _('Modell') }}{{ _('Modell') }} {{ p.get_parameter_value_for_display('model').replace('models/', '').upper() }} {{ _('Verbindung') }} {% if p._rs232 %}{{ p._rs232 }}:{{ p._baud }}, {{ p._timeout }} {% else %}{{ p._tcp }}:{{ p._port }}, {{ p._tcp_timeout }}{% endif %} @@ -63,29 +68,26 @@ {% endif %}
{{ _('Abhängig von') }}{{ p._dependson|default('nichts') }} - {% if p._dependson_value %} = {{ p._dependson_value }}{% endif %}{{ _('0 wenn') }} +
{{ _('Abhängig von') }}
{{ p._dependson|default('nichts') }} + {% if p._dependson_value %} = {{ p._dependson_value }}{% endif %}
{{ _('0 wenn') }}
{% if p._depend0_power0 %}Power{% endif %}{% if p._depend0_power0 and p._depend0_volume0%}, {% endif %} {% if p._depend0_volume0 %}Volume{% endif %} - {% if not p._depend0_volume0 and not p._depend0_power0 %}None{% endif %}
{{ _('Ignorieren') }}{% if p._ignore_response %}{{ p._ignore_response }} - {% else %}None{% endif %}
{{ _('Ignorieren') }}
{% if p._ignore_response %}{{ p._ignore_response }} + {% else %}None{% endif %}
{{ _('Fehlermeldung') }}{% if p._error_response %}{{ p._error_response }} - {% else %}None{% endif %}
{{ _('Fehlermeldung') }}
{% if p._error_response %}{{ p._error_response }} + {% else %}None{% endif %}
@@ -112,7 +114,7 @@ {% endblock %} {% block bodytab1 %} -
+
{% if item_count_zone0>0 %}
{{ _('Die folgenden Items sind dieser Instanz des AVDevice Plugins zugewiesen') }}: From b02b29415fce428d10afef9eb5e2aa105f410a50 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Tue, 11 Sep 2018 10:43:51 +0200 Subject: [PATCH 261/705] minor webif improvements --- uzsu/locale.yaml | 2 ++ uzsu/webif/templates/index.html | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/uzsu/locale.yaml b/uzsu/locale.yaml index bd3d4c22e..adb3d3602 100755 --- a/uzsu/locale.yaml +++ b/uzsu/locale.yaml @@ -2,6 +2,8 @@ plugin_translations: # Translations for the plugin specially for the web interface 'Die folgenden Items sind dem UZSU Plugin zugewiesen': {'de': '=', 'en': 'The following items are assigned to the UZSU plugin'} 'Klick auf ein Item um dessen Konfiguration anzuzeigen': {'de': '=', 'en': 'Click on an item to show its configuration'} + 'Aktives Item, keine (aktiven) Einträge!': {'de': '=', 'en': 'Active item, no (active) entries!'} + 'Item existiert nicht!': {'de': '=', 'en': 'Item does not exist!'} 'UZSU Item': {'de': '=', 'en': '='} 'Abhängige Items (mit Typ)': {'de': '=', 'en': 'Dependant Item (with type)'} 'Wert des abhängigen Items': {'de': '=', 'en': 'Value of dependant Item'} diff --git a/uzsu/webif/templates/index.html b/uzsu/webif/templates/index.html index e293d95c2..e45f954f3 100755 --- a/uzsu/webif/templates/index.html +++ b/uzsu/webif/templates/index.html @@ -76,7 +76,7 @@ {% for item in p.get_items() %} {% if p.has_iattr(item.conf, 'uzsu_item') %} - {% if p._logics_planned(item) == none and p._items[item]['active'] == True %} + {% if (p._logics_planned(item) == none and p._items[item]['active'] == True) or p._items[item]['interpolation']['itemtype'] == none %} {% set color = 'red' %} {% elif p._items[item]['active'] == True %} {% set color = 'green' %} @@ -87,13 +87,16 @@ {{ item._path }} {{ p.get_iattr_value(item.conf, 'uzsu_item') }} + {% if p._items[item]['interpolation']['itemtype'] == none %} - + {{ _('Item existiert nicht!') }}{% else %} ({{ p._items[item]['interpolation']['itemtype'] }}) - + {% endif %} {{ p._get_dependant(item) }}
{% if p._logics_planned(item) != none %}{{ p._logics_planned(item) }}{% endif %} {% if p._logics_planned(item) == none and p._items[item]['active'] == True %} - ACTIVE, BUT NO ENTRIES!{% endif %} + {{ _('Aktives Item, keine (aktiven) Einträge!') }} + {% endif %} {% if p._items[item]['interpolation']['type'] %} {{ p._items[item]['interpolation']['type'] }} ({% if p._items[item]['interpolation']['interval'] %}{{ p._items[item]['interpolation']['interval'] }}{% else %}5{% endif %}) From 305550319678bdc9e2fe10c568866cfbbe33f52f Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Tue, 11 Sep 2018 17:17:03 +0200 Subject: [PATCH 262/705] OperationLog: Fix logger parameter initialization --- operationlog/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operationlog/__init__.py b/operationlog/__init__.py index 69e282c2e..b06607637 100755 --- a/operationlog/__init__.py +++ b/operationlog/__init__.py @@ -61,7 +61,7 @@ def __init__(self, smarthome, name, cache=True, logtofile=True, filepattern="{ye AbLogger.__init__(self, name) self._filepattern = filepattern self._log = lib.log.Log(smarthome, name, mapping, int(maxlen)) - self._logger = None if logger else logging.getLogger(logger) + self._logger = None if not logger else logging.getLogger(logger) self._path = name self._cachefile = None self._cache = True From 0c956e230d696848f91083bc0525ba90ee3bf4ba Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Tue, 11 Sep 2018 17:20:07 +0200 Subject: [PATCH 263/705] OperationLog: Add `logger` parameter to documentation --- operationlog/README.md | 4 ++++ 1 file changed, 4 insertions(+) mode change 100644 => 100755 operationlog/README.md diff --git a/operationlog/README.md b/operationlog/README.md old mode 100644 new mode 100755 index bfef4bc34..afb976dde --- a/operationlog/README.md +++ b/operationlog/README.md @@ -22,6 +22,7 @@ mylogname1: # cache = yes # logtofile = yes # filepattern = {year:04}-{month:02}-{day:02}-{name}.log + # logger = mylogname2: class_name: OperationLog @@ -43,6 +44,9 @@ The entries of the second log will not be kept in memory, only logged to a yearl The logging file can be named as desired. The keys `{name}`, `{year}`, `{month}` and `{day}` are replaced by the log name and current time respectively. Every time a log entry is written, the file name is checked and a new file is created upon change. +If you also want to log to a configured logger of the environment +you can specify the logger name in the `logger` setting. + ### items.yaml From 199f8816491e3aa6070b016a6276a62bdfaa1bfa Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Tue, 11 Sep 2018 17:30:46 +0200 Subject: [PATCH 264/705] XMPP: Implement a standard XMPP log handler to send logs via XMPP --- xmpp/README.md | 24 ++++++++++++++++++++++++ xmpp/__init__.py | 23 +++++++++++++++++++++++ 2 files changed, 47 insertions(+) mode change 100644 => 100755 xmpp/README.md diff --git a/xmpp/README.md b/xmpp/README.md old mode 100644 new mode 100755 index f16e98802..9dc2c2ef0 --- a/xmpp/README.md +++ b/xmpp/README.md @@ -7,6 +7,30 @@ This Plugin uses sleekxmpp as basis to connect to XMPP etc services: https://pyp At this stage the XMPP plugin module only supports in sending messages. Recevied messages are ignored. OTR not supported as the sleekxmpp libraries do not support this as yet. +This Plugin can also be used to setup a standard logger category which +can be used to log messages using XMPP to some chat or groupchat contact. +The logging configuration looks like this: + +```yaml +handlers: + xmpp: + class: plugins.xmpp.XMPPLogHandler + formatter: shng_simple + xmpp_plugin: xmpp + xmpp_receiver: room@conference.example.com + xmpp_receiver_type: groupchat +loggers: + xmpp: + handlers: [xmpp] + level: WARN +``` + +This requires a XMPP plugin configured in a section named `xmpp` +which is used in the `xmpp_plugin` setting. The receiver and type needs +to be specified to configure the target receiving the log +messages. + + ## Configuration ### plugin.yaml diff --git a/xmpp/__init__.py b/xmpp/__init__.py index 8e44b39b0..0cd8084bb 100755 --- a/xmpp/__init__.py +++ b/xmpp/__init__.py @@ -26,6 +26,7 @@ import logging import sleekxmpp +from lib.plugin import Plugins from lib.model.smartplugin import * class XMPP(SmartPlugin): @@ -119,6 +120,28 @@ def send(self, to, msgsend, mt='chat'): self.xmpp.send_message(mto=to, mbody=str(msgsend), mtype=mt) +class XMPPLogHandler(logging.Handler): + + def __init__(self, xmpp_plugin, xmpp_receiver, xmpp_receiver_type='chat'): + logging.Handler.__init__(self) + self._plugin = None + self._xmpp_plugin = xmpp_plugin + self._xmpp_receiver = xmpp_receiver + self._xmpp_receiver_type = xmpp_receiver_type + + def emit(self, record): + if self._plugin is None: + self._plugin = Plugins.get_instance().return_plugin(self._xmpp_plugin) + if self._plugin is None: + logging.getLogger(__name__).error('Can not get XMPP plugin for {} - disabling XMPP logging!'.format(self._xmpp_plugin)) + self._plugin = False + else: + logging.getLogger(__name__).info('Configured XMPP logging using pluing {}'.format(self._xmpp_plugin)) + + if self._plugin is not False: + self._plugin.send(self._xmpp_receiver, self.format(record), self._xmpp_receiver_type) + + def main(): bot = XMPP("skender@haxhimolla.im", "mypassword") bot.run() From e2fc21f336a0046e76fcb1163e93093fb7862de4 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Wed, 12 Sep 2018 16:08:50 +0200 Subject: [PATCH 265/705] fixed sun calculation entry for all items --- uzsu/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 540b8ffe5..9112f8336 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -571,7 +571,7 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): if 'sun' in time: next = self._sun(datetime.combine(dt.date(), datetime.min.time()).replace(tzinfo=self._timezone), time, timescan) self.logger.debug("{}: Result parsing time (rrule) {}: {}".format(self._name, time, next)) - if entryindex: + if entryindex is not None: self._update_suncalc(item, entry, entryindex, next.strftime("%H:%M")) else: next = datetime.combine(dt.date(), parser.parse(time.strip()).time()).replace(tzinfo=self._timezone) @@ -591,7 +591,7 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): cond_future = next > datetime.now(self._timezone) and timescan == 'next' if cond_future: self.logger.debug("{}: Result parsing time today (sun) {}: {}".format(self._name, time, next)) - if entryindex: + if entryindex is not None: self._update_suncalc(item, entry, entryindex, next.strftime("%H:%M")) else: self._itpl[next.timestamp() * 1000.0] = value From 5b4cfc5eaa71c10e2575cdb4fa06b3405d7b9244 Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Wed, 12 Sep 2018 22:28:34 +0200 Subject: [PATCH 266/705] whitespace cleanup --- zwave/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zwave/__init__.py b/zwave/__init__.py index dd369eb99..99210c881 100755 --- a/zwave/__init__.py +++ b/zwave/__init__.py @@ -3,7 +3,7 @@ ######################################################################### # Copyright 2017 Thomas Creutz ######################################################################### -# This file is part of SmartHomeNG. +# This file is part of SmartHomeNG. # # Sample plugin for new plugins to run with SmartHomeNG version 1.4 and # upwards. @@ -50,14 +50,14 @@ class ZWave(SmartPlugin): def __init__(self, sh, device='/dev/ttyUSB0', sec_strategy='SUPPORTED', config_path='/etc/openzwave/', zlogging='false', logfile='OZW.log', loglevel='Info'): """ Initalizes the plugin. The parameters describe for this method are pulled from the entry in plugin.conf. - - :param sh: **Deprecated**: The instance of the smarthome object. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! + + :param sh: **Deprecated**: The instance of the smarthome object. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! :param *args: **Deprecated**: Old way of passing parameter values. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! :param **kwargs:**Deprecated**: Old way of passing parameter values. For SmartHomeNG versions **beyond** 1.3: **Don't use it**! - + If you need the sh object at all, use the method self.get_sh() to get it. There should be almost no need for a reference to the sh object any more. - + The parameters *args and **kwargs are the old way of passing parameters. They are deprecated. They are implemented to support older plugins. Plugins for SmartHomeNG v1.4 and beyond should use the new way of getting parameter values: use the SmartPlugin method `get_parameter_value(parameter_name)` instead. Anywhere within the Plugin you can get From 1eeb98adf73d0bfb7ebd2fb25968163794cfb223 Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Wed, 12 Sep 2018 22:42:37 +0200 Subject: [PATCH 267/705] fix endless loop in ZWave->run() --- zwave/__init__.py | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/zwave/__init__.py b/zwave/__init__.py index 99210c881..e498542be 100755 --- a/zwave/__init__.py +++ b/zwave/__init__.py @@ -83,6 +83,7 @@ def __init__(self, sh, device='/dev/ttyUSB0', sec_strategy='SUPPORTED', config_p self.logger.debug('zwave: logath={0}', self._logfile) self._loglevel = loglevel self._sec_strategy = sec_strategy + self._ready = False def run(self): """ @@ -92,7 +93,7 @@ def run(self): self.alive = True try: - options = ZWaveOption(self._device, config_path=self._config_path, user_path='.', cmd_line='') + options = ZWaveOption(self._device, config_path=self._config_path, user_path='./var/ozw', cmd_line='') except Exception as e: self.logger.error('zwave: error on create ZWaveOption - {}'.format(e)) self.alive = False @@ -125,24 +126,40 @@ def run(self): try: self._network.start() except Exception as e: + self.alive = False self.logger.error('zwave: error on start network - {}'.format(e)) self.logger.info('zwave: use openzwave library: {}'.format(self._network.controller.ozw_library_version)) self.logger.info('zwave: use python library: {}'.format(self._network.controller.python_library_version)) self.logger.info('zwave: use ZWave library: {}'.format(self._network.controller.library_description)) - while 1: - if self.alive and self._network.state < self._network.STATE_READY: + + while self.alive: + + if self._network.state != self._network.STATE_READY: + self.logger.debug('zwave: wait until network is ready... current state is: {}'.format(self._network.state_str)) - time.sleep(3.0) if self._network.state == self._network.STATE_FAILED: - self.alive = false + self.alive = False return - self.logger.info('zwave: controller ready : {} nodes were found.'.format(self._network.nodes_count)) - self.logger.info('zwave: controller node id : {}'.format(self._network.controller.node.node_id)) - self.logger.info('zwave: controller node version : {}'.format(self._network.controller.node.version)) - self.logger.info('zwave: Network home id : {}'.format(self._network.home_id_str)) - self.logger.info('zwave: Nodes in network : {}'.format(self._network.nodes_count)) + # Dump network information on STATE_READY + if self._network.state == self._network.STATE_READY and self._ready == False: + self.logger.info('zwave: controller ready : {} nodes were found.'.format(self._network.nodes_count)) + self.logger.info('zwave: controller node id : {}'.format(self._network.controller.node.node_id)) + self.logger.info('zwave: controller node version : {}'.format(self._network.controller.node.version)) + self.logger.info('zwave: Network home id : {}'.format(self._network.home_id_str)) + self.logger.info('zwave: Nodes in network : {}'.format(self._network.nodes_count)) + + self.logger.info("zwave: Start refresh values") + for __id in self.listenOn: + __val = self._network.get_value(__id) + self.logger.info("zwave: id : '{}', val: '{}'".format(__id,__val)) + for __item in self.listenOn[__id][ITEMS]: + __item(__val.data, 'ZWave') + + self._ready = True + + time.sleep(3.0) def stop(self): """ From 9f51e6325c0141dd7d56f62c32de49d99d966450 Mon Sep 17 00:00:00 2001 From: msinn Date: Thu, 13 Sep 2018 09:03:46 +0200 Subject: [PATCH 268/705] operationlog: Addition to metadata --- operationlog/plugin.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operationlog/plugin.yaml b/operationlog/plugin.yaml index 1c1cb7c53..820c6d807 100755 --- a/operationlog/plugin.yaml +++ b/operationlog/plugin.yaml @@ -4,7 +4,7 @@ plugin: type: system # plugin type (gateway, interface, protocol, system, web) description: # Alternative: description in multiple languages de: 'Implementierung seperater Logs' - en: '' + en: 'Implementation of seperate logs' maintainer: '? (JanT112)' tester: Sandman60, onkelandy # keywords: iot xyz From 92ac751ab31636ce9aa498d69bef62b5988acb4c Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 15 Sep 2018 16:56:33 +0200 Subject: [PATCH 269/705] changed logger init, added short sleep after sun evaluation --- uzsu/__init__.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 9112f8336..e6b40921c 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -59,12 +59,14 @@ from lib.shtime import Shtime from datetime import datetime, timedelta +from time import sleep from dateutil.rrule import rrulestr from dateutil import parser from dateutil.tz import tzutc import lib.orb from unittest import mock from collections import OrderedDict +from bin.smarthome import VERSION try: from scipy import interpolate @@ -93,7 +95,9 @@ def __init__(self, smarthome): :param sh: The instance of the smarthome object, save it for later references """ - self.logger = logging.getLogger(__name__) + + if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': + self.logger = logging.getLogger(__name__) self.itemsApi = Items.get_instance() self._name = self.get_fullname() self._timezone = Shtime.get_instance().tzinfo() @@ -569,6 +573,7 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): if dt is None: return None, None if 'sun' in time: + sleep(0.01) next = self._sun(datetime.combine(dt.date(), datetime.min.time()).replace(tzinfo=self._timezone), time, timescan) self.logger.debug("{}: Result parsing time (rrule) {}: {}".format(self._name, time, next)) if entryindex is not None: From c0d408e319368dbeb942fdfc35f71128c38d48bf Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 15 Sep 2018 16:57:52 +0200 Subject: [PATCH 270/705] updated logger init --- gpio/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gpio/__init__.py b/gpio/__init__.py index 80560da02..28bda7b66 100755 --- a/gpio/__init__.py +++ b/gpio/__init__.py @@ -23,6 +23,7 @@ from lib.model.smartplugin import * import threading import datetime +from bin.smarthome import VERSION try: import RPi.GPIO as GPIO @@ -35,7 +36,8 @@ class Raspi_GPIO(SmartPlugin): ALLOW_MULTIINSTANCE = False def __init__(self, sh): - self.logger = logging.getLogger(__name__) + if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': + self.logger = logging.getLogger(__name__) self.init_webinterface() self._name = self.get_fullname() if not REQUIRED_PACKAGE_IMPORTED: From 5d43318e7000473c3b59011c9c8ca5782aab700c Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 15 Sep 2018 17:00:12 +0200 Subject: [PATCH 271/705] updated logger init --- avdevice/AVDeviceFunctions.py | 4 +- avdevice/AVDeviceInit.py | 4 +- avdevice/__init__.py | 116 +++++++++++++++++----------------- 3 files changed, 64 insertions(+), 60 deletions(-) diff --git a/avdevice/AVDeviceFunctions.py b/avdevice/AVDeviceFunctions.py index 3817aa4b6..6ddc9ac2c 100755 --- a/avdevice/AVDeviceFunctions.py +++ b/avdevice/AVDeviceFunctions.py @@ -25,6 +25,7 @@ import logging import re +from bin.smarthome import VERSION VERBOSE1 = logging.DEBUG - 1 VERBOSE2 = logging.DEBUG - 2 @@ -38,7 +39,8 @@ def __init__(self, buffer, name, sendcommands): self._name = name self._send_commands = sendcommands - self.logger = logging.getLogger(__name__) + if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': + self.logger = logging.getLogger(__name__) self.logger.debug( "Processing Response {}: Creating expected response. Buffer: {}. Name: {}. Sendcommands: {}".format( self._name, re.sub('[\r\n]', ' --- ', self._buffer), self._name, self._send_commands)) diff --git a/avdevice/AVDeviceInit.py b/avdevice/AVDeviceInit.py index 4da922018..dab2fe903 100755 --- a/avdevice/AVDeviceInit.py +++ b/avdevice/AVDeviceInit.py @@ -29,6 +29,7 @@ import os from lib.item import Items +from bin.smarthome import VERSION VERBOSE1 = logging.DEBUG - 1 VERBOSE2 = logging.DEBUG - 2 @@ -45,7 +46,8 @@ def __init__(self, name, model, items): self._ignoreresponse = [] self.itemsApi = Items.get_instance() - self.logger = logging.getLogger(__name__) + if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': + self.logger = logging.getLogger(__name__) self.logger.log(VERBOSE1, "Initializing {}: Started".format(self._name)) self._functions = {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}} diff --git a/avdevice/__init__.py b/avdevice/__init__.py index 82512a238..589619188 100755 --- a/avdevice/__init__.py +++ b/avdevice/__init__.py @@ -33,6 +33,7 @@ import re import errno import itertools +from bin.smarthome import VERSION from .AVDeviceInit import Init from .AVDeviceInit import ProcessVariables @@ -41,11 +42,6 @@ from .AVDeviceFunctions import ConvertValue from .AVDeviceFunctions import CreateExpectedResponse -# Used to get errorline, for debugging only -# sys.exc_info()[-1].tb_lineno -#try: -# import sys - VERBOSE1 = logging.DEBUG - 1 VERBOSE2 = logging.DEBUG - 2 logging.addLevelName(logging.DEBUG - 1, 'VERBOSE1') @@ -58,7 +54,8 @@ class AVDevice(SmartPlugin): def __init__(self, smarthome): self.itemsApi = Items.get_instance() - self.logger = logging.getLogger(__name__) + if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': + self.logger = logging.getLogger(__name__) self.init_webinterface() try: self.alive = False @@ -457,6 +454,50 @@ def parse_item(self, item): # Processing the response from the AV device, dealing with buffers, etc. def _processing_response(self, socket): + + def _sortbuffer(buffer, bufferlist): + expectedsplit = [] + self._expected_response = CreateExpectedResponse(buffer, self._name, + self._send_commands).create_expected() + expectedsplit = list(itertools.chain(*[x.split('|') for x in self._expected_response])) + sortedbuffer = [] + for e in expectedsplit: + for entry in bufferlist: + if entry == e and entry not in self._ignore_response: + sortedbuffer.append(entry) + self.logger.log(VERBOSE2, + "Processing Response {}: Response is same as expected. adding: {}.".format( + self._name, entry)) + break + elif entry.startswith(e): + try: + realresponse = self._response_wildcards['original'][e] + except Exception: + realresponse = e + try: + for resp in self._response_commands[realresponse]: + self.logger.log(VERBOSE2, + "Processing Response {}: realresponse: {}. Length: {}, expected length: {}.".format( + self._name, realresponse, len(entry), resp[1])) + cond1 = len(entry) == resp[1] or resp[1] == 100 or resp[0] == 100 + cond2 = entry not in sortedbuffer and entry not in self._ignore_response + if cond1 and cond2: + self.logger.log(VERBOSE2, + "Processing Response {}: length is same. adding: {}.".format( + self._name, entry)) + sortedbuffer.append(entry) + break + except Exception: + pass + + self.logger.log(VERBOSE2, + "Processing Response {}: expected response: {}, bufferlist {}. Sortedbuffer: {}".format( + self._name, expectedsplit, bufferlist, sortedbuffer)) + bufferlist = [x for x in bufferlist if x not in sortedbuffer] + buffer = "\r\n".join(sortedbuffer + bufferlist) + buffer = "{}\r\n".format(buffer) + return buffer, expectedsplit + try: buffer = '' tidy = lambda c: re.sub( @@ -565,48 +606,10 @@ def _processing_response(self, socket): buffer_cleaned.append(buff) bufferlist = buffer_cleaned buffer = "\r\n".join(bufferlist) + "\r\n" - expectedsplit = [] if self._send_commands: - self._expected_response = CreateExpectedResponse(buffer, self._name, - self._send_commands).create_expected() - expectedsplit = list(itertools.chain(*[x.split('|') for x in self._expected_response])) - sortedbuffer = [] - for e in expectedsplit: - for entry in bufferlist: - if entry == e and entry not in self._ignore_response: - sortedbuffer.append(entry) - self.logger.log(VERBOSE2, - "Processing Response {}: Response is same as expected. adding: {}.".format( - self._name, entry)) - break - elif entry.startswith(e): - try: - realresponse = self._response_wildcards['original'][e] - except Exception: - realresponse = e - try: - for resp in self._response_commands[realresponse]: - self.logger.log(VERBOSE2, - "Processing Response {}: realresponse: {}. Length: {}, expected length: {}.".format( - self._name, realresponse, len(entry), resp[1])) - cond1 = len(entry) == resp[1] or resp[1] == 100 or resp[0] == 100 - cond2 = entry not in sortedbuffer and entry not in self._ignore_response - if cond1 and cond2: - self.logger.log(VERBOSE2, - "Processing Response {}: length is same. adding: {}.".format( - self._name, entry)) - sortedbuffer.append(entry) - break - except Exception: - pass - - self.logger.log(VERBOSE2, - "Processing Response {}: expected response: {}, bufferlist {}. Sortedbuffer: {}".format( - self._name, expectedsplit, bufferlist, sortedbuffer)) - bufferlist = [x for x in bufferlist if x not in sortedbuffer] - buffer = "\r\n".join(sortedbuffer + bufferlist) - buffer = "{}\r\n".format(buffer) + _, expectedsplit = _sortbuffer(buffer, bufferlist) + # first entry should be buffer as soon as resorting works perfectly smooth. Problem now: On very short interval settings the sorting results in wrong reponses. self.logger.log(VERBOSE2, "Processing Response {}: Buffer after sorting: {}.".format( self._name, re.sub('[\r\n]', ' --- ', buffer))) @@ -802,8 +805,7 @@ def _processing_response(self, socket): self._wait(0.2) yield buf except Exception as err: - self.logger.error("Processing Response {}: Problems: {} in line {}.".format( - self._name, err, sys.exc_info()[-1].tb_lineno)) + self.logger.error("Processing Response {}: Problems: {}".format(self._name, err)) def _clear_history(self, part): if part == 'keep': @@ -1188,7 +1190,7 @@ def _checkdependency(self, dep_function, dep_type): else: dict_entry = None expectedvalue = Translate(expectedvalue, dict_entry, self._name, 'parse', - self._specialparse).translate() or expectedvalue + self._specialparse).translate() or expectedvalue self.logger.log(VERBOSE2, "Checking Dependency {}: Expectedvalue after Translation {}. Dependitem: {}, expected {}".format( self._name, expectedvalue, dependitem, expectedvalue)) @@ -1943,7 +1945,7 @@ def _duplicateindex(seq, seqitem): if commanditem: command = '{};{}'.format(command_split, commanditem) self.logger.log(VERBOSE1, - "Parsing Input {}: Adding command commandsplit {}, commanditem {}. Command: {}".format( + "Parsing Input {}: Adding command commandsplit {}, commanditem {}. Command: {}".format( self._name, command_split, commanditem, command)) if command_split in self._query_commands: reorderlist.append(command) @@ -2789,7 +2791,7 @@ def _displayignore(self, response, receivedvalue, caller): self._special_commands['Input']['Ignore'])) except Exception as err: self.logger.debug( - "Display Ignore {}: Problems: {} in line {}.".format(self._name, err, sys.exc_info()[-1].tb_lineno)) + "Display Ignore {}: Problems: {}".format(self._name, err)) else: try: cond1 = response.startswith(tuple(inputcommands)) @@ -2985,15 +2987,15 @@ def init_webinterface(self): This method is only needed if the plugin is implementing a web interface """ try: - self.mod_http = Modules.get_instance().get_module('http') # try/except to handle running in a core version that does not support modules + self.mod_http = Modules.get_instance().get_module('http') except: - self.mod_http = None - if self.mod_http == None: + self.mod_http = None + if self.mod_http is None: self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_shortname())) return False import sys - if not "SmartPluginWebIf" in list(sys.modules['lib.model.smartplugin'].__dict__): + if "SmartPluginWebIf" not in list(sys.modules['lib.model.smartplugin'].__dict__): self.logger.warning("Plugin '{}': Web interface needs SmartHomeNG v1.5 and up. Not initializing the web interface".format(self.get_shortname())) return False @@ -3026,8 +3028,8 @@ def init_webinterface(self): import cherrypy from jinja2 import Environment, FileSystemLoader -class WebInterface(SmartPluginWebIf): +class WebInterface(SmartPluginWebIf): def __init__(self, webif_dir, plugin): """ @@ -3043,7 +3045,6 @@ def __init__(self, webif_dir, plugin): self.plugin = plugin self.tplenv = self.init_template_environment() - @cherrypy.expose def index(self, action=None, item_id=None, item_path=None, reload=None): """ @@ -3053,7 +3054,6 @@ def index(self, action=None, item_id=None, item_path=None, reload=None): :return: contents of the template after beeing rendered """ - item = self.plugin.get_sh().return_item(item_path) config_reloaded = False keep_cleared = False command_cleared = False From 0aac487f9422aeb95d391d1dfe421a9734cb7012 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 15 Sep 2018 18:14:14 +0200 Subject: [PATCH 272/705] fixed logger init --- avdevice/AVDeviceFunctions.py | 22 +++++----- avdevice/AVDeviceInit.py | 10 ++--- avdevice/__init__.py | 76 ++++++++++++++++++----------------- avdevice/plugin.yaml | 2 + 4 files changed, 56 insertions(+), 54 deletions(-) diff --git a/avdevice/AVDeviceFunctions.py b/avdevice/AVDeviceFunctions.py index 6ddc9ac2c..17168c9e9 100755 --- a/avdevice/AVDeviceFunctions.py +++ b/avdevice/AVDeviceFunctions.py @@ -25,7 +25,6 @@ import logging import re -from bin.smarthome import VERSION VERBOSE1 = logging.DEBUG - 1 VERBOSE2 = logging.DEBUG - 2 @@ -34,13 +33,12 @@ class CreateExpectedResponse(object): - def __init__(self, buffer, name, sendcommands): + def __init__(self, buffer, name, sendcommands, logger): self._buffer = buffer self._name = name self._send_commands = sendcommands - if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': - self.logger = logging.getLogger(__name__) + self.logger = logger self.logger.debug( "Processing Response {}: Creating expected response. Buffer: {}. Name: {}. Sendcommands: {}".format( self._name, re.sub('[\r\n]', ' --- ', self._buffer), self._name, self._send_commands)) @@ -57,7 +55,7 @@ def create_expected(self): for i in range(0, len(splitresponse)): splitresponse[i] = splitresponse[i].split(',')[0] if not self._buffer == '': - splitresponse[i] = Translate(self._buffer.split("\r\n")[0], splitresponse[i], self._name, '', '').wildcard() + splitresponse[i] = Translate(self._buffer.split("\r\n")[0], splitresponse[i], self._name, '', '', self.logger).wildcard() self.logger.log(VERBOSE2, "Processing Response {}: Splitresponse after wildcard {}: {}.".format( self._name, i, splitresponse[i])) wildcardresponse = [] @@ -74,7 +72,7 @@ def create_expected(self): class Translate(object): - def __init__(self, code, dictentry, name, caller, specialparse): + def __init__(self, code, dictentry, name, caller, specialparse, logger): self._code = code self._dictentry = dictentry self._caller = caller @@ -83,7 +81,7 @@ def __init__(self, code, dictentry, name, caller, specialparse): self._data = code self._command = dictentry - self.logger = logging.getLogger(__name__) + self.logger = logger def wildcard(self): if self._command.find('?') >= 1: @@ -217,7 +215,7 @@ def translate(self): class ConvertValue(object): - def __init__(self, receivedvalue, expectedtype, invert, valuelength, command, name, specialcommands): + def __init__(self, receivedvalue, expectedtype, invert, valuelength, command, name, specialcommands, logger): self._receivedvalue = receivedvalue self._expectedtype = expectedtype self._invert = invert @@ -225,7 +223,7 @@ def __init__(self, receivedvalue, expectedtype, invert, valuelength, command, na self._command = command[0] if isinstance(command, list) else command self._special_commands = specialcommands self._name = name - self.logger = logging.getLogger(__name__) + self.logger = logger self.logger.debug( "Converting Values {}: Received Value is: {} with expected type {}. Invert: {}. Length: {}. Command: {}".format( self._name, receivedvalue, expectedtype, invert, valuelength, command)) @@ -328,7 +326,7 @@ def convert_value(self): class CreateResponse(object): - def __init__(self, commandinfo, reverseinfo, value, name, specialparse): + def __init__(self, commandinfo, reverseinfo, value, name, specialparse, logger): self._commandinfo = commandinfo self._reverseinfo = reverseinfo self._value = value @@ -344,7 +342,7 @@ def __init__(self, commandinfo, reverseinfo, value, name, specialparse): except Exception: self._splitreverse = self._reverseinfo.split('|') - self.logger = logging.getLogger(__name__) + self.logger = logger self.logger.log(VERBOSE1, "Creating Response {}: Create response command {}, reverse {}, value {}".format( self._name, commandinfo, reverseinfo, value)) @@ -522,7 +520,7 @@ def response_set(self): replacedresponse = '' try: value = Translate(self._value, self._commandinfo[10], self._name, - 'update', self._specialparse).translate() or self._value + 'update', self._specialparse, self.logger).translate() or self._value except Exception: value = self._value try: diff --git a/avdevice/AVDeviceInit.py b/avdevice/AVDeviceInit.py index dab2fe903..968069028 100755 --- a/avdevice/AVDeviceInit.py +++ b/avdevice/AVDeviceInit.py @@ -39,15 +39,13 @@ class Init(object): - def __init__(self, name, model, items): + def __init__(self, name, model, items, logger): self._items = items self._name = name self._model = model self._ignoreresponse = [] self.itemsApi = Items.get_instance() - - if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': - self.logger = logging.getLogger(__name__) + self.logger = logger self.logger.log(VERBOSE1, "Initializing {}: Started".format(self._name)) self._functions = {'zone0': {}, 'zone1': {}, 'zone2': {}, 'zone3': {}, 'zone4': {}} @@ -779,10 +777,10 @@ def read_commandfile(self): class ProcessVariables(Init): - def __init__(self, value, name): + def __init__(self, value, name, logger): self._value = value self._name = name - self.logger = logging.getLogger(__name__) + self.logger = logger def process_rs232(self): baud = serial_timeout = None diff --git a/avdevice/__init__.py b/avdevice/__init__.py index 589619188..27ef86549 100755 --- a/avdevice/__init__.py +++ b/avdevice/__init__.py @@ -56,6 +56,7 @@ def __init__(self, smarthome): self.itemsApi = Items.get_instance() if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': self.logger = logging.getLogger(__name__) + self.logger.error(self.logger) self.init_webinterface() try: self.alive = False @@ -119,19 +120,21 @@ def __init__(self, smarthome): # Initializing all variables self.logger.debug("Initializing {}: Resendwait: {}. Seconds to keep: {}.".format(self._name, self._resend_wait, self._secondstokeep)) - self.init = Init(self._name, self._model, self._items) + self.init = Init(self._name, self._model, self._items, self.logger) self._rs232, self._baud, self._timeout = ProcessVariables([rs232_port, rs232_baudrate, rs232_timeout], - self._name).process_rs232() + self._name, self.logger).process_rs232() self._tcp, self._port, self._tcp_timeout = ProcessVariables([tcp_ip, tcp_port, tcp_timeout], - self._name).process_tcp() + self._name, self.logger).process_tcp() self._dependson, self._dependson_value, self._depend0_power0, self._depend0_volume0 = ProcessVariables( - [dependson_item, dependson_value, depend0_power0, depend0_volume0], self._name).process_dependson() + [dependson_item, dependson_value, depend0_power0, depend0_volume0], + self._name, self.logger).process_dependson() - self._response_buffer = ProcessVariables(responsebuffer, self._name).process_responsebuffer() - self._reset_onerror = ProcessVariables(resetonerror, self._name).process_resetonerror() - self._statusquery = ProcessVariables(statusquery, self._name).process_statusquery() + self._response_buffer = ProcessVariables(responsebuffer, self._name, self.logger).process_responsebuffer() + self._reset_onerror = ProcessVariables(resetonerror, self._name, self.logger).process_resetonerror() + self._statusquery = ProcessVariables(statusquery, self._name, self.logger).process_statusquery() self._ignore_response, self._error_response, self._force_buffer, self._ignoredisplay = ProcessVariables( - [ignoreresponse, errorresponse, forcebuffer, inputignoredisplay], self._name).process_responses() + [ignoreresponse, errorresponse, forcebuffer, inputignoredisplay], + self._name, self.logger).process_responses() self.logger.debug( "Initializing {}: Special Settings: Ignoring responses {}.".format(self._name, self._ignore_response)) self.logger.debug( @@ -141,9 +144,10 @@ def __init__(self, smarthome): "Initializing {}: Special Settings: Ignore Display {}".format(self._name, self._ignoredisplay)) self.logger.debug( "Initializing {}: Querying at plugin init is set to {}".format(self._name, self._statusquery)) - self._update_exclude = ProcessVariables(update_exclude, self._name).process_update_exclude() + self._update_exclude = ProcessVariables(update_exclude, self._name, self.logger).process_update_exclude() - except Exception: + except Exception as err: + self.logger.error(err) self._init_complete = False return @@ -305,7 +309,7 @@ def _write_itemsdict(self, data, found): value = data[valuestart:valueend] invert = True if entry[6].lower() in ['1', 'true', 'yes', 'on'] else False received = ConvertValue(value, expectedtype, invert, entry[0], command, - self._name, self._special_commands).convert_value() \ + self._name, self._special_commands, self.logger).convert_value() \ if not value == '' else data[valuestart:valueend] receivedvalue = received[1] if isinstance(received, list) else received try: @@ -317,7 +321,7 @@ def _write_itemsdict(self, data, found): sametype = True if receivedvalue == '' and expectedtype == 'empty' else False if sametype is True: self._items[zone][av_function]['Value'] = Translate( - value, entry[9], self._name, 'writedict', self._specialparse).translate() + value, entry[9], self._name, 'writedict', self._specialparse, self.logger).translate() self.logger.debug( "Storing Values {}: Found writeable dict key: {}. Zone: {}. " "Value {} with type {}. Function: {}.".format( @@ -458,7 +462,7 @@ def _processing_response(self, socket): def _sortbuffer(buffer, bufferlist): expectedsplit = [] self._expected_response = CreateExpectedResponse(buffer, self._name, - self._send_commands).create_expected() + self._send_commands, self.logger).create_expected() expectedsplit = list(itertools.chain(*[x.split('|') for x in self._expected_response])) sortedbuffer = [] for e in expectedsplit: @@ -541,7 +545,7 @@ def _sortbuffer(buffer, bufferlist): if cond1 and not cond2: buffering = True self._expected_response = CreateExpectedResponse(buffer, self._name, - self._send_commands).create_expected() + self._send_commands, self.logger).create_expected() self.logger.log(VERBOSE1, "Processing Response {}: Error reading.. Error: {}. Sending Command: {}.".format( self._name, err, self._sendingcommand)) @@ -658,7 +662,7 @@ def _sortbuffer(buffer, bufferlist): line = re.sub('[\\n\\r]', '', line).strip() responseforsending = False for entry in self._response_commands: - newentry = Translate(line, entry, self._name, '', '').wildcard() + newentry = Translate(line, entry, self._name, '', '', self.logger).wildcard() self._response_wildcards['wildcard'].update({newentry: entry}) self._response_wildcards['original'].update({entry: newentry}) responsecommands = list(self._response_wildcards['wildcard'].keys()) @@ -669,7 +673,7 @@ def _sortbuffer(buffer, bufferlist): try: for resp in ','.join(self._sendingcommand.split(';')[0].split(',')[2:]).split('|'): resp = resp.split(',')[0] - resp = Translate(line, resp, self._name, '', '').wildcard() if len(line) == len( + resp = Translate(line, resp, self._name, '', '', self.logger).wildcard() if len(line) == len( resp) else resp self.logger.log(VERBOSE2, "Processing Response {}: Testing sendingcommand {}. Line: {}, expected response: {}".format( @@ -706,7 +710,7 @@ def _sortbuffer(buffer, bufferlist): keyfound = False compare = ','.join(self._send_commands[0].split(';')[0].split(',')[2:]).split('|') for comp in compare: - comp = Translate(line, comp.split(',')[0], self._name, '', '').wildcard() + comp = Translate(line, comp.split(',')[0], self._name, '', '', self.logger).wildcard() keyfound = True if line.startswith(comp) else False if keyfound is True: self.logger.log(VERBOSE1, @@ -775,7 +779,7 @@ def _sortbuffer(buffer, bufferlist): buffering = False if bufferlist: self._expected_response = CreateExpectedResponse('\r\n'.join(bufferlist), self._name, - self._send_commands).create_expected() + self._send_commands, self.logger).create_expected() for buf in bufferlist: cond1 = not re.sub('[ ]', '', buf) == '' cond2 = not buf.startswith(tuple(self._ignore_response)) @@ -1190,7 +1194,7 @@ def _checkdependency(self, dep_function, dep_type): else: dict_entry = None expectedvalue = Translate(expectedvalue, dict_entry, self._name, 'parse', - self._specialparse).translate() or expectedvalue + self._specialparse, self.logger).translate() or expectedvalue self.logger.log(VERBOSE2, "Checking Dependency {}: Expectedvalue after Translation {}. Dependitem: {}, expected {}".format( self._name, expectedvalue, dependitem, expectedvalue)) @@ -1775,7 +1779,7 @@ def _duplicateindex(seq, seqitem): received = ConvertValue( data[responseposition:responseposition + valuelength], expectedtype, False, valuelength, self._special_commands['Display']['Command'], - self._name, self._special_commands).convert_value() + self._name, self._special_commands, self.logger).convert_value() self.logger.debug( "Parsing Input {}: Displaycommand found in response {}. Converted to {}.".format( self._name, data, receivedvalue)) @@ -1819,7 +1823,7 @@ def _duplicateindex(seq, seqitem): receivedvalue = ConvertValue( data[responseposition:responseposition + valuelength], expectedtype, False, valuelength, self._special_commands['Speakers']['Command'], self._name, - self._special_commands).convert_value() + self._special_commands, self.logger).convert_value() try: for _ in self._special_commands['Speakers']['Command']: for zone in self._items_speakers: @@ -1854,7 +1858,7 @@ def _duplicateindex(seq, seqitem): if not receivedvalue == '': receivedvalue = ConvertValue(value, expectedtype, invert, valuelength, data, self._name, - self._special_commands).convert_value() + self._special_commands, self.logger).convert_value() try: sametype = True if isinstance(receivedvalue, eval(expectedtype)) else False except Exception: @@ -1875,7 +1879,7 @@ def _duplicateindex(seq, seqitem): self._name, dictkey, responseposition, value)) self._addorremove_keepcommands('removefromkeep', data) value = Translate(origvalue, entry[9], self._name, 'parse', - self._specialparse).translate() or value + self._specialparse, self.logger).translate() or value if av_function in self._items[zone].keys(): self._items[zone][av_function]['Value'] = value self.logger.log(VERBOSE1, @@ -2189,7 +2193,7 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl self._name, command)) responsecommand, _ = CreateResponse(commandinfo, '', '', self._name, - self._specialparse).response_standard() + self._specialparse, self.logger).response_standard() appendcommand = '{},{},{};{}'.format(commandinfo[2], commandinfo[3], responsecommand, item.id()) cond1 = appendcommand not in self._query_commands @@ -2224,7 +2228,7 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl if command in self._functions['zone{}'.format(zone)]: commandinfo = self._functions['zone{}'.format(zone)][command] replacedresponse, _ = CreateResponse(commandinfo, '', '', self._name, - self._specialparse).response_standard() + self._specialparse, self.logger).response_standard() appendcommand = '{},{},{};{}'.format(commandinfo[2], commandinfo[3], replacedresponse, item.id()) cond1 = appendcommand not in self._query_commands cond2 = appendcommand not in self._special_commands['Display']['Command'] @@ -2256,7 +2260,7 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl reverseinfo = '' replacedresponse, replacedreverse = CreateResponse( commandinfo, reverseinfo, '', self._name, - self._specialparse).response_in_decrease() + self._specialparse, self.logger).response_in_decrease() try: reverseitem = self._items['zone{}'.format(zone)][command.replace('+', '-', 1)].get('Item') except Exception: @@ -2309,7 +2313,7 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl reverseinfo = '' replacedresponse, replacedreverse = CreateResponse( commandinfo, reverseinfo, '', self._name, - self._specialparse).response_in_decrease() + self._specialparse, self.logger).response_in_decrease() try: reverseitem = self._items['zone{}'.format(zone)][command.replace('-', '+', 1)].get('Item') except Exception: @@ -2356,7 +2360,7 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl commandinfo = self._functions['zone{}'.format(zone)][command_on] reverseinfo = self._functions['zone{}'.format(zone)][command_off] replacedresponse, replacedreverse = CreateResponse( - commandinfo, reverseinfo, '', self._name, self._specialparse).response_on() + commandinfo, reverseinfo, '', self._name, self._specialparse, self.logger).response_on() appendcommand = '{},{},{};{}'.format(commandinfo[2], commandinfo[3], replacedresponse, item.id()) reversecommand = '{},{},{};{}'.format(reverseinfo[2], reverseinfo[3], replacedreverse, item.id()) @@ -2423,7 +2427,7 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl commandinfo = self._functions['zone{}'.format(zone)][command_off] reverseinfo = self._functions['zone{}'.format(zone)][command_on] replacedresponse, replacedreverse = CreateResponse( - commandinfo, reverseinfo, '', self._name, self._specialparse).response_off() + commandinfo, reverseinfo, '', self._name, self._specialparse, self.logger).response_off() appendcommand = '{},{},{};{}'.format(commandinfo[2], commandinfo[3], replacedresponse, item.id()) reversecommand = '{},{},{};{}'.format(reverseinfo[2], reverseinfo[3], replacedreverse, item.id()) @@ -2479,11 +2483,11 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl newvalue = None if not command.lower().startswith('speakers'): response, _ = CreateResponse(commandinfo, '', value, self._name, - self._specialparse).response_set() + self._specialparse, self.logger).response_set() try: newvalue = value.lower() if isinstance(value, str) else value newvalue = Translate(newvalue, commandinfo[10], self._name, 'update', - self._specialparse).translate() + self._specialparse, self.logger).translate() self.logger.log(VERBOSE2, "Updating Item {}: Translated value: {}".format(self._name, newvalue)) @@ -2540,16 +2544,16 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl self._name, self._items['zone{}'.format(zone)]['speakers']['Item'], currentvalue, item, item(), multiply, value)) response, _ = CreateResponse(commandinfo, '', value, self._name, - self._specialparse).response_set() + self._specialparse, self.logger).response_set() command_re = CreateResponse(commandinfo, '', value, self._name, - self._specialparse).replace_number( + self._specialparse, self.logger).replace_number( commandinfo[2], value, translatecode) self.logger.log(VERBOSE2, "Updating Item {}: Speakers commandinfo 2: {}, value: {}. command_re: {}".format( self._name, commandinfo[2], value, command_re)) if value > 0: replacedresponse, _ = CreateResponse(powerinfo, '', True, self._name, - self._specialparse).response_power() + self._specialparse, self.logger).response_power() try: poweritem = self._items['zone{}'.format(zone)][powerinfo[1]].get('Item') except Exception: @@ -2564,7 +2568,7 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl self._name, powerinfo)) else: command_re = CreateResponse(commandinfo, '', value, self._name, - self._specialparse).replace_number( + self._specialparse, self.logger).replace_number( commandinfo[2], value, translatecode) self.logger.log(VERBOSE2, "Updating Item {}: commandinfo 2: {}, value: {}. command_re: {}".format( @@ -2573,7 +2577,7 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl elif isinstance(value, str) and 'str' in commandinfo[9]: setting = True command_re = CreateResponse(commandinfo, '', value, self._name, - self._specialparse).replace_string( + self._specialparse, self.logger).replace_string( commandinfo[2], value, translatecode) else: diff --git a/avdevice/plugin.yaml b/avdevice/plugin.yaml index 5a2e046a2..be0399b6f 100755 --- a/avdevice/plugin.yaml +++ b/avdevice/plugin.yaml @@ -7,6 +7,7 @@ plugin: en: 'Controlling AV devices via TCP/IP and RS232' maintainer: onkelandy tester: Foxi352 # Who tests this plugin? + state: develop keywords: av denon pioneer epson oppo player amp receiver projector rs232 telnet tcpip # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1097870-neues-plugin-av-device-f%C3%BCr-yamaha-pioneer-denon-etc @@ -15,6 +16,7 @@ plugin: sh_minversion: 1.5 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance + restartable: unknown classname: AVDevice # class containing the plugin parameters: From 13cdf16a0b15af4e9d8fdab642db05e460853669 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sun, 16 Sep 2018 07:39:46 +0200 Subject: [PATCH 273/705] fix a weird reaction on weird sun offset settings --- uzsu/__init__.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index e6b40921c..b96706dd8 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -749,33 +749,35 @@ def _sun(self, dt, tstr, timescan): self.logger.error('{}: Wrong syntax: {}. Should be [H:M<](sunrise|sunset)[+|-][offset][ next_time: - next_time = dmin + else: + dmin = next_time if smax is not None: h, sep, m = smax.partition(':') try: - dmax = next_time.replace(hour=int(h), minute=int(m), second=0, tzinfo=self._timezone) + dmax = next_time.replace(day=dt.day, hour=int(h), minute=int(m), second=0, tzinfo=self._timezone) except Exception: self.logger.error('{}: Wrong syntax: {}. Should be [H:M<](sunrise|sunset)[+|-][offset][ dmax: self.logger.error("{}: Wrong times: the earliest time should be smaller than the " "latest time in {}".format(self._name, tstr)) return - + if dmin > next_time: + next_time = dmin + if dmax < next_time: + next_time = dmax return next_time def _get_dependant(self, item): From 0100338b97554c13958a7ca0b858b646c901c671 Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Mon, 17 Sep 2018 22:44:49 +0200 Subject: [PATCH 274/705] - fix typo in class contructor for logging - add parmas and item into plugin.yaml --- zwave/__init__.py | 2 +- zwave/plugin.yaml | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/zwave/__init__.py b/zwave/__init__.py index e498542be..6dadc8b3d 100755 --- a/zwave/__init__.py +++ b/zwave/__init__.py @@ -76,7 +76,7 @@ def __init__(self, sh, device='/dev/ttyUSB0', sec_strategy='SUPPORTED', config_p self.listenOn = {} self._device = device self._config_path = config_path - self._logging = logging + self._logging = zlogging self._logfile = os.path.join(sh._base_dir, 'var') self._logfile = os.path.join(self._logfile, 'log') self._logfile = os.path.join(self._logfile, logfile) diff --git a/zwave/plugin.yaml b/zwave/plugin.yaml index 254d65026..f2fca7ee1 100755 --- a/zwave/plugin.yaml +++ b/zwave/plugin.yaml @@ -19,13 +19,56 @@ plugin: parameters: # Definition of parameters to be configured in etc/plugin.yaml + device: type: str - default: '' + default: '/dev/ttyUSB0' description: de: 'Gerätedatei des Z-Wave Garätes' en: 'Devicefile of the Z-Wave Device' + sec_strategy: + type: str + default: 'SUPPORTED' + description: + de: 'Definiert die Sicherheitsstrategie : SUPPORTED|ESSENTIAL|CUSTOM' + en: 'The security strategy : SUPPORTED|ESSENTIAL|CUSTOM' + + config_path: + type: str + default: '/etc/openzwave/' + description: + de: 'Der Ordner in dem die Konfiuration liegt' + en: 'The folder with the configuration' + + zlogging: + type: bool + default: False + description: + en: 'True to activate logs, False to disable' + + logfile: + type: str + default: 'OZW.log' + description: + en: 'set the name of the logfile' + + loglevel: + type: str + default: 'Info' + description: + en: 'set the loglevel' + item_attributes: # Definition of item attributes defined by this plugin - + + zwave_node: + type: str + description: + en: 'connects the item to the defined node' + + zwave_valu: + type: str + description: + en: 'connects the item to the defined value' + From 82d691ab75caa914a316e0f2f18c17ee3196d3da Mon Sep 17 00:00:00 2001 From: msinn Date: Wed, 19 Sep 2018 04:54:43 +0200 Subject: [PATCH 275/705] hue: Fix an error that led to an ever increasing number of used threads --- hue/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hue/__init__.py b/hue/__init__.py index 1b6bf7145..4f448a5c8 100755 --- a/hue/__init__.py +++ b/hue/__init__.py @@ -560,7 +560,10 @@ def _get_web_content(self, hueBridgeId='0', path='', method='GET', body=None): errorItem = None self.logger.info('_get_web_content '+hueBridgeId) # dann der aufruf kompatibel, aber inhaltlich nicht identisch fetch_url aus lib.tools, daher erst eimal das fehlerobjekt nicht mehr da - response = client.fetch_url(url, None, None, 2, 0, method, body, errorItem) + try: + response = client.fetch_url(url, None, None, 2, 0, method, body, errorItem) + except: + response = False if response: # und jetzt der anteil der decodierung, der nicht in der fetch_url drin ist # lesen, decodieren nach utf-8 (ist pflicht nach der api definition philips) und in ein python objekt umwandeln From baa642ab66c1dfbdf66d360daa8d0800179dae10 Mon Sep 17 00:00:00 2001 From: msinn Date: Wed, 19 Sep 2018 04:55:31 +0200 Subject: [PATCH 276/705] Changes to Metadata --- cli/plugin.yaml | 4 +++- homematic/plugin.yaml | 2 ++ knx/plugin.yaml | 7 +++++-- mqtt/plugin.yaml | 1 + 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/cli/plugin.yaml b/cli/plugin.yaml index b8a499d1a..7661b8d06 100755 --- a/cli/plugin.yaml +++ b/cli/plugin.yaml @@ -32,11 +32,13 @@ parameters: type: ip default: 127.0.0.1 description: - de: 'Legt festm auf welchen Netzwerk Interfaces CLI nach Verbindungen lauscht (127.0.0.1 für localhost, 0.0.0.0 für alle Netzwerk Interfaces)' + de: 'Legt fest auf welchen Netzwerk Interfaces CLI nach Verbindungen lauscht (127.0.0.1 für localhost, 0.0.0.0 für alle Netzwerk Interfaces)' en: 'used network interface, e.g. 127.0.0.1 (localhost) or listen on all network interfaces: 0.0.0.0' port: type: int + valid_min: 0 + valid_max: 65535 default: 2323 description: de: 'Netzwerk Port der für die Verbindung genutzt wird' diff --git a/homematic/plugin.yaml b/homematic/plugin.yaml index 9be0b1402..70bbd10ca 100755 --- a/homematic/plugin.yaml +++ b/homematic/plugin.yaml @@ -64,6 +64,8 @@ parameters: learnmode_length: type: int default: 60 + valid_min: 0 + valid_max: 300 description: de: 'Dauer des Anlernmodus der HomeMatic CCU2 Zentrale nach Aktivierung durch das Web Interface' en: 'Duration of learnmode of the HomeMatic CCU2 gateway after activation through the web interface' diff --git a/knx/plugin.yaml b/knx/plugin.yaml index 910755d55..9522e1efd 100755 --- a/knx/plugin.yaml +++ b/knx/plugin.yaml @@ -37,9 +37,10 @@ parameters: send_time: type: int default: 0 + valid_min: 0 description: - de: 'Zeitintervall zum Senden von Uhrzeit und Datum an den KNX-Bus' - en: 'time interval to send time and date to the knx bus' + de: 'Zeitintervall (in Sekunden) zum Senden von Uhrzeit und Datum an den KNX-Bus' + en: 'time interval (in seconds) to send time and date to the knx bus' busmonitor: type: str @@ -66,6 +67,8 @@ parameters: port: type: int + valid_min: 0 + valid_max: 65535 default: 6720 description: de: 'Port, der bei der Kommunikation mit dem Eibd- oder Knxd-Daemon verwendet wird' diff --git a/mqtt/plugin.yaml b/mqtt/plugin.yaml index f6259cf0e..8ea935e0e 100755 --- a/mqtt/plugin.yaml +++ b/mqtt/plugin.yaml @@ -83,6 +83,7 @@ parameters: type: int default: 1883 valid_min: 0 + valid_max: 65535 description: de: 'Vom Broker benutzter Port' en: 'Port used by broker' From 0ed2f8e303808af7574242060cfe8b1070534922 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Thu, 20 Sep 2018 19:25:04 +0200 Subject: [PATCH 277/705] Fixed interpolation that didn't work in very rare cases --- uzsu/__init__.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index b96706dd8..2757556bc 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -387,7 +387,15 @@ def _schedule(self, item, caller=None): self._itpl.clear() for i, entry in enumerate(self._items[item]['list']): next, value = self._get_time(entry, 'next', item, i) - self._get_time(entry, 'previous', item) + prev, prev_value = self._get_time(entry, 'previous', item) + try: + cond1 = prev > datetime.now(self._timezone) + cond2 = prev < next + except Exception as err: + cond1 = cond2 = False + if cond1 and cond2: + next = prev + value = prev_value item(self._items[item], 'USZU Plugin', 'schedule') if next is not None: self.logger.debug("{}: uzsu active entry for item {} with datetime {}, value {}" @@ -533,7 +541,6 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): return None, None if 'time' not in entry: return None, None - now = datetime.now() value = entry['value'] active = entry['active'] today = datetime.today() @@ -567,7 +574,7 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): rrule = rrulestr(entry['rrule'], dtstart=datetime.combine(weekbefore, datetime.min.time())) self.logger.debug("{}: Looking for {} time. Found rrule: {}".format( self._name, timescan, str(rrule).replace('\n', ';'))) - dt = now + dt = datetime.now() while self.alive: dt = rrule.before(dt) if timescan == 'previous' else rrule.after(dt) if dt is None: @@ -580,15 +587,9 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): self._update_suncalc(item, entry, entryindex, next.strftime("%H:%M")) else: next = datetime.combine(dt.date(), parser.parse(time.strip()).time()).replace(tzinfo=self._timezone) - cond_next = next > datetime.now(self._timezone) and timescan == 'next' - cond_previous = next < datetime.now(self._timezone) and timescan == 'previous' - if next and next.date() == dt.date() and cond_next: - self._itpl[next.timestamp() * 1000.0] = value - self.logger.debug("{}: Return from rrule next: {}, value {}.".format(self._name, next, value)) - return next, value - if next and next.date() == dt.date() and cond_previous: + if next and next.date() == dt.date(): self._itpl[next.timestamp() * 1000.0] = value - self.logger.debug("{}: Return from rrule previous: {}, value {}.".format(self._name, next, value)) + self.logger.debug("{}: Return from rrule {}: {}, value {}.".format(self._name, timescan, next, value)) return next, value if 'sun' in time: next = self._sun(datetime.combine(today, datetime.min.time()).replace( @@ -617,7 +618,7 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): cond2 = next.date() - timedelta(days=1) == yesterday.date() cond3 = next.date() == tomorrow.date() cond_next = next > datetime.now(self._timezone) and timescan == 'next' - cond_previous_today = next < datetime.now(self._timezone) and timescan == 'previous' + cond_previous_today = next - timedelta(seconds=1) < datetime.now(self._timezone) and timescan == 'previous' cond_previous_yesterday = next - timedelta(days=1) < datetime.now(self._timezone) and timescan == 'previous' if next and cond1 and cond_next: self._itpl[next.timestamp() * 1000.0] = value @@ -628,7 +629,7 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): self.logger.debug("{}: Return next tomorrow: {}, value {}".format(self._name, next, value)) return next, value if next and cond1 and cond_previous_today: - self._itpl[next.timestamp() * 1000.0] = value + self._itpl[(next - timedelta(seconds=1)).timestamp() * 1000.0] = value self.logger.debug("{}: Return previous today: {}, value {}".format(self._name, next, value)) return next, value if next and cond2 and cond_previous_yesterday: From c87442deb770019a639519f0340431590bd7f521 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Fri, 21 Sep 2018 07:50:16 +0200 Subject: [PATCH 278/705] removed useless log entry --- avdevice/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/avdevice/__init__.py b/avdevice/__init__.py index 27ef86549..69008fe97 100755 --- a/avdevice/__init__.py +++ b/avdevice/__init__.py @@ -56,7 +56,6 @@ def __init__(self, smarthome): self.itemsApi = Items.get_instance() if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': self.logger = logging.getLogger(__name__) - self.logger.error(self.logger) self.init_webinterface() try: self.alive = False From 1a9fc54bd4efe0a8b6c50b5fd942192a9eff79dc Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 22 Sep 2018 23:15:43 +0200 Subject: [PATCH 279/705] drexelundweiss: Updated logging and other stuff based on sample plugin, readonly items are now queried after update --- drexelundweiss/__init__.py | 242 ++++++++++++++++++++----------------- drexelundweiss/plugin.yaml | 65 ++++++++-- 2 files changed, 188 insertions(+), 119 deletions(-) mode change 100644 => 100755 drexelundweiss/__init__.py diff --git a/drexelundweiss/__init__.py b/drexelundweiss/__init__.py old mode 100644 new mode 100755 index bcd413dd1..965ff332b --- a/drexelundweiss/__init__.py +++ b/drexelundweiss/__init__.py @@ -18,74 +18,90 @@ # You should have received a copy of the GNU General Public License # along with SmartHomeNG. If not, see . # -# encoding=utf8 +# encoding=utf8 import logging import threading -import serial import os.path import time import string import re from lib.model.smartplugin import SmartPlugin +from bin.smarthome import VERSION + +try: + import serial + REQUIRED_PACKAGE_IMPORTED = True +except Exception: + REQUIRED_PACKAGE_IMPORTED = False class DuW(SmartPlugin): ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.3.0" - - def __init__(self, smarthome, tty, LU_ID=130, WP_ID=140, Busmonitor=0, device=0, retrylimit=100): - self._sh = smarthome - self._LU_ID = LU_ID - self._WP_ID = WP_ID - self._cmd = False - self.LUregl = {} - self.WPregl = {} - self.LUcmdl = {} - self.WPcmdl = {} - self.devl = {} - self._is_connected = False - self._device = int(device) - self._retrylimit = int(retrylimit) - self._lock = threading.Lock() - self.busmonitor = Busmonitor - self._pollservice = False - self.logger = logging.getLogger(__name__) - - self.devl[1] = {'device': 'aerosilent primus', 'cmdpath': - smarthome.base_dir + '/plugins/drexelundweiss/aerosilent_primus.txt'} - self.devl[2] = {'device': 'aerosilent topo', 'cmdpath': - smarthome.base_dir + '/plugins/drexelundweiss/aerosilent_topo.txt'} - self.devl[3] = {'device': 'aerosilent micro', 'cmdpath': - smarthome.base_dir + '/plugins/drexelundweiss/aerosilent_micro.txt'} - self.devl[4] = {'device': 'aerosmart s', 'cmdpath': - smarthome.base_dir + '/plugins/drexelundweiss/aerosmart_s.txt'} - self.devl[5] = {'device': 'aerosmart m', 'cmdpath': - smarthome.base_dir + '/plugins/drexelundweiss/aerosmart_m.txt'} - self.devl[6] = {'device': 'aerosmart l', 'cmdpath': - smarthome.base_dir + '/plugins/drexelundweiss/aerosmart_l.txt'} - self.devl[7] = {'device': 'aerosmart xls', 'cmdpath': - smarthome.base_dir + '/plugins/drexelundweiss/aerosmart_xls.txt'} - self.devl[8] = {'device': 'aerosilent centro', 'cmdpath': - smarthome.base_dir + '/plugins/drexelundweiss/aerosilent_centro.txt'} - self.devl[9] = {'device': 'termosmart sc', 'cmdpath': - smarthome.base_dir + '/plugins/drexelundweiss/termosmart_sc.txt'} - self.devl[10] = {'device': 'x2', 'cmdpath': - smarthome.base_dir + '/plugins/drexelundweiss/x2.txt'} - self.devl[11] = {'device': 'aerosmart mono', 'cmdpath': - smarthome.base_dir + '/plugins/drexelundweiss/aerosmart_mono.txt'} - self.devl[13] = {'device': 'aerosilent bianco', 'cmdpath': - smarthome.base_dir + '/plugins/drexelundweiss/aerosilent_bianco.txt'} - self.devl[14] = {'device': 'x2 plus', 'cmdpath': - smarthome.base_dir + '/plugins/drexelundweiss/x2_plus.txt'} - self.devl[15] = {'device': 'aerosilent business', 'cmdpath': - smarthome.base_dir + '/plugins/drexelundweiss/aerosilent_business.txt'} - self.devl[17] = {'device': 'aerosilent stratos', 'cmdpath': - smarthome.base_dir + '/plugins/drexelundweiss/aerosilent_stratos.txt'} + PLUGIN_VERSION = "1.5.1" + + def __init__(self, smarthome): + self._name = self.get_fullname() + if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': + self.logger = logging.getLogger(__name__) + if not REQUIRED_PACKAGE_IMPORTED: + self.logger.error("{}: Unable to import Python package 'serial'".format(self._name)) + self._init_complete = False + return + try: + self._LU_ID = self.get_parameter_value('LU_ID') + self._WP_ID = self.get_parameter_value('WP_ID') + self._tty = self.get_parameter_value('tty') + self._cmd = False + self.LUregl = {} + self.WPregl = {} + self.LUcmdl = {} + self.WPcmdl = {} + self.devl = {} + self._is_connected = False + self._device = self.get_parameter_value('device') + self._retrylimit = self.get_parameter_value('retrylimit') + self._lock = threading.Lock() + self.busmonitor = self.get_parameter_value('busmonitor') + self._pollservice = False + self.devl[1] = {'device': 'aerosilent primus', 'cmdpath': + smarthome.base_dir + '/plugins/drexelundweiss/aerosilent_primus.txt'} + self.devl[2] = {'device': 'aerosilent topo', 'cmdpath': + smarthome.base_dir + '/plugins/drexelundweiss/aerosilent_topo.txt'} + self.devl[3] = {'device': 'aerosilent micro', 'cmdpath': + smarthome.base_dir + '/plugins/drexelundweiss/aerosilent_micro.txt'} + self.devl[4] = {'device': 'aerosmart s', 'cmdpath': + smarthome.base_dir + '/plugins/drexelundweiss/aerosmart_s.txt'} + self.devl[5] = {'device': 'aerosmart m', 'cmdpath': + smarthome.base_dir + '/plugins/drexelundweiss/aerosmart_m.txt'} + self.devl[6] = {'device': 'aerosmart l', 'cmdpath': + smarthome.base_dir + '/plugins/drexelundweiss/aerosmart_l.txt'} + self.devl[7] = {'device': 'aerosmart xls', 'cmdpath': + smarthome.base_dir + '/plugins/drexelundweiss/aerosmart_xls.txt'} + self.devl[8] = {'device': 'aerosilent centro', 'cmdpath': + smarthome.base_dir + '/plugins/drexelundweiss/aerosilent_centro.txt'} + self.devl[9] = {'device': 'termosmart sc', 'cmdpath': + smarthome.base_dir + '/plugins/drexelundweiss/termosmart_sc.txt'} + self.devl[10] = {'device': 'x2', 'cmdpath': + smarthome.base_dir + '/plugins/drexelundweiss/x2.txt'} + self.devl[11] = {'device': 'aerosmart mono', 'cmdpath': + smarthome.base_dir + '/plugins/drexelundweiss/aerosmart_mono.txt'} + self.devl[13] = {'device': 'aerosilent bianco', 'cmdpath': + smarthome.base_dir + '/plugins/drexelundweiss/aerosilent_bianco.txt'} + self.devl[14] = {'device': 'x2 plus', 'cmdpath': + smarthome.base_dir + '/plugins/drexelundweiss/x2_plus.txt'} + self.devl[15] = {'device': 'aerosilent business', 'cmdpath': + smarthome.base_dir + '/plugins/drexelundweiss/aerosilent_business.txt'} + self.devl[17] = {'device': 'aerosilent stratos', 'cmdpath': + smarthome.base_dir + '/plugins/drexelundweiss/aerosilent_stratos.txt'} + except Exception as err: + self.logger.error("{}: Error on init {}.".format(self._name, err)) + self._init_complete = False + return try: - self._port = serial.Serial(tty, 115200, timeout=5) + self._port = serial.Serial(self._tty, 115200, timeout=5) except: - self.logger.error("DuW: could not open {}.".format(tty)) + self.logger.error("{}: could not open {}.".format(self._name, self._tty)) return else: self._is_connected = True @@ -96,7 +112,7 @@ def __init__(self, smarthome, tty, LU_ID=130, WP_ID=140, Busmonitor=0, device=0, def _convertresponse(self,antwort,teil): antwort = antwort.decode() - #self.logger.debug("DuW: Antwort: {}".format(antwort)) + #self.logger.debug("{}: Antwort: {}".format(antwort)) allow = string.digits + ' ' antwort = re.sub('[^%s]' % allow, '', antwort) liste = antwort.splitlines() @@ -121,7 +137,6 @@ def _convertresponse(self,antwort,teil): antwort = str(antwort) allow = string.digits antwort = re.sub('[^%s]' % allow, '', antwort) - #self.logger.debug("DuW: Response: {1} = {0}".format(antwort, teil)) return int(antwort) def _get_device_type(self): @@ -130,27 +145,27 @@ def _get_device_type(self): (data, done) = self._read_register('LU\n', 5000, 1, 0) if done: if data in self.devl: - self.logger.info("DuW: device: {}".format(self.devl[data]['device'])) + self.logger.info("{}: device: {}".format(self._name, self.devl[data]['device'])) if os.path.isfile(self.devl[data]['cmdpath']): self._cmd = self.devl[data]['cmdpath'] - self.logger.debug("DuW: Command File:{}".format(self._cmd)) + self.logger.debug("{}: Command File:{}".format(self._name, self._cmd)) else: self.logger.error( - "DuW: no command file found at {}".format(self.devl[data]['cmdpath'])) + "{}: no command file found at {}".format(self._name, self.devl[data]['cmdpath'])) self._cmd = False else: - self.logger.error("DuW: device not supported: {}".format(data)) + self.logger.error("{}: device not supported: {}".format(self._name, data)) self._cmd = False else: - self.logger.error("DuW: Error reading device type! Trying to activate configured device") + self.logger.error("{}: Error reading device type! Trying to activate configured device".format(self._name)) if os.path.isfile(self.devl[self._device]['cmdpath']): self._cmd = self.devl[self._device]['cmdpath'] - self.logger.info("DuW: device: {0}".format(self.devl[self._device]['device'])) + self.logger.info("{}: device: {}".format(self._name, self.devl[self._device]['device'])) #self._cmd = False else: self._cmd = False - self.logger.error("DuW: no connection") + self.logger.error("{}: no connection".format(self._name)) self.alive = False def _send_DW(self, data, pcb): @@ -162,7 +177,7 @@ def _send_DW(self, data, pcb): elif(pcb == 'WP\n'): device_ID = self._WP_ID else: - self.logger.error("DuW: wrong pcb description") + self.logger.error("{}: wrong pcb description".format(self._name)) return if not self._lock.acquire(timeout=2): @@ -170,7 +185,7 @@ def _send_DW(self, data, pcb): try: self._port.write("{0} {1}\r\n".format(device_ID,data).encode()) except Exception as e: - self.logger.exception("DuW: Problem sending {0}".format(e)) + self.logger.error("{}: Problem sending {}".format(self._name, e)) finally: self._lock.release() @@ -187,13 +202,13 @@ def _get_register_info(self, register, pcb): else: return False else: - self.logger.error("DuW: wrong pcb description") + self.logger.error("{}: wrong pcb description".format(self._name)) return def _load_cmd(self): - self.logger.debug("DuW: Opening command file") + self.logger.debug("{}: Opening command file".format(self._name)) f = open(self._cmd, "r") - self.logger.debug("DuW: Opened command file") + self.logger.debug("{}: Opened command file".format(self._name)) try: for line in f: if not self._lock.acquire(timeout=2): @@ -209,23 +224,23 @@ def _load_cmd(self): elif row[7] == 'WP\n': self.WPcmdl[int(row[0])] = {'reginfo': row} else: - self.logger.debug("DuW: Error in Commandfile: " + line) + self.logger.debug("{}: Error in Commandfile: {}".format(self._name, line)) except Exception as e: - self.logger.exception("DuW: problems loading commands: {0}".format(e)) + self.logger.error("{}: problems loading commands: {}".format(self._name, e)) finally: self._lock.release() finally: f.close() def run(self): - self.logger.debug("run method called") + self.logger.debug("{}: run method called".format(self._name)) if not self._cmd: self.alive = False try: if self._is_connected: self._port.close() except Exception as e: - self.logger.exception(e) + self.logger.error("{}: Error {}".format(self._name, e)) return self.alive = True @@ -241,7 +256,7 @@ def run(self): if done: item(data, 'DuW', 'init process') else: - self.logger.debug("DuW: Init LU register failed: {}".format(register)) + self.logger.debug("{}: Init LU register failed: {}".format(self._name, register)) # WP register init for register in self.WPregl: @@ -254,7 +269,7 @@ def run(self): if done: item(data, 'DuW', 'init process') else: - self.logger.debug("DuW: Init WP register failed: {0}".format(register)) + self.logger.debug("{}: Init WP register failed: {}".format(self._name, register)) # poll DuW interface dw_id = 0 @@ -281,7 +296,7 @@ def run(self): elif (response[-1] == 0x0a): dw_data = self._convertresponse(response,'data') - + if (self.busmonitor): if dw_id == self._LU_ID: if dw_register in self.LUcmdl: @@ -289,21 +304,25 @@ def run(self): dw_register]['reginfo'] divisor = int(reginfo[4]) komma = int(reginfo[5]) - self.logger.debug("DuW Busmonitor LU register: {0} {1}: {2}".format(dw_register,reginfo[1],((dw_data / divisor) / (10 ** komma)))) + self.logger.debug("DuW Busmonitor LU register: {} {}: {}".format( + self._name, dw_register,reginfo[1],((dw_data / divisor) / (10 ** komma)))) else: - self.logger.debug("DuW Busmonitor: unknown LU register: {0} {1}".format(dw_register,dw_data)) + self.logger.debug("{} Busmonitor: unknown LU register: {} {}".format( + self._name, dw_register,dw_data)) elif dw_id == self._WP_ID: if dw_register in self.WPcmdl: reginfo = self.WPcmdl[dw_register][ 'reginfo'] divisor = int(reginfo[4]) komma = int(reginfo[5]) - self.logger.debug("DuW Busmonitor WP register: {0} {1}: {2}".format(dw_register,reginfo[1],((dw_data / divisor) / (10 ** komma)))) + self.logger.debug("DuW Busmonitor WP register: {} {}: {}".format( + self._name, dw_register,reginfo[1],((dw_data / divisor) / (10 ** komma)))) else: - self.logger.debug("DuW Busmonitor: unknown WP register: {0} {1}".format(dw_register,dw_data)) + self.logger.debug("{} Busmonitor: unknown WP register: {} {}".format( + self._name, dw_register,dw_data)) else: self.logger.debug( - "DuW Busmonitor: unknown device ID: {}".format(dw_id)) + "{} Busmonitor: unknown device ID: {}".format(self._name, dw_id)) if dw_id == self._LU_ID: if dw_register in self.LUregl: @@ -317,7 +336,7 @@ def run(self): / (10 ** komma)), 'DuW', 'Poll') else: - self.logger.debug("DuW: Ignore LU register {}".format(dw_register)) + self.logger.debug("{}: Ignore LU register {}".format(self._name, dw_register)) elif dw_id == self._WP_ID: if dw_register in self.WPregl: reginfo = self.WPregl[ @@ -330,9 +349,9 @@ def run(self): / (10 ** komma)), 'DuW', 'Poll') else: - self.logger.debug("DuW: Ignore WP register {}" .format(dw_register)) + self.logger.debug("{}: Ignore WP register {}" .format(self._name, dw_register)) else: - self.logger.debug("DuW: unknown device ID: {}".format(dw_id)) + self.logger.debug("{}: unknown device ID: {}".format(self._name, dw_id)) dw_id = 0 dw_register = 0 @@ -343,20 +362,20 @@ def run(self): dw_id = 0 dw_register = 0 dw_data = 0 - self.logger.debug("DuW: Read timeout") + self.logger.debug("{}: Read timeout".format(self._name)) except Exception as e: - self.logger.exception("DuW: Polling error {0}".format(e)) + self.logger.error("{}: Polling error {}".format(self._name, e)) finally: self._lock.release() time.sleep(0.1) # exit poll service self._pollservice = False except Exception as e: - self.logger.exception("DuW: not alive error, {0}".format(e)) + self.logger.error("{}: not alive error, {}".format(self._name, e)) def stop(self): self.alive = False - self.logger.debug("stop method called") + self.logger.debug("{}: stop method called".format(self._name)) while self._pollservice == True: pass @@ -364,7 +383,7 @@ def stop(self): if self._is_connected: self._port.close() except Exception as e: - self.logger.exception("DuW: Stop Exception, {}".format(e)) + self.logger.error("{}: Stop Exception, {}".format(self._name, e)) def write_DW(self, pcb, register, value): self._send_DW("{0:d} {1:d}".format(int(register), int(value)), pcb) @@ -378,7 +397,7 @@ def _read_register(self, pcb, register, divisor, komma): elif(pcb == 'WP\n'): device_ID = self._WP_ID else: - self.logger.error("DuW: wrong pcb description") + self.logger.error("{}: wrong pcb description".format(self._name)) self._port.flushInput() self.req_DW(pcb, str(register + 1)) @@ -394,7 +413,6 @@ def _read_register(self, pcb, register, divisor, komma): response += self._port.read() allow = string.digits test = re.sub('[^%s]' % allow, '', str(response.decode())) - #self.logger.debug("DuW: Response: {0}".format(test)) if len(test) != 0: if (response[-1] == 0x20 and dw_id == 0): dw_id = self._convertresponse(response,'id') @@ -410,24 +428,24 @@ def _read_register(self, pcb, register, divisor, komma): response = bytes() else: retries += 1 - self.logger.info("DuW: read timeout: {0}. Retries: {1}".format(response, retries)) + self.logger.info("{}: read timeout: {}. Retries: {}".format(self._name, response, retries)) if retries >= self._retrylimit: break time.sleep(0.1) except Exception as e: - self.logger.warning("DuW: Read error: {0}".format(e)) + self.logger.warning("{}: Read error: {}".format(self._name, e)) finally: self._lock.release() if(dw_id == device_ID and (dw_register - 1) == register): - self.logger.debug("DuW: Read {1} on Register: {0}".format(register,dw_data)) + self.logger.debug("{}: Read {} on Register: {}".format(self._name, dw_data, register)) try: return (((dw_data / divisor) / (10 ** komma)), 1) except: self.logger.debug("Division durch Null Problem") return (((dw_data / 1) / (10 ** 1)), 1) else: - self.logger.error("DuW: read errror Device ID: {0}, register {1}".format(dw_id,dw_register - 1)) + self.logger.error("{}: read errror Device ID: {}, register {}".format(self._name, dw_id, dw_register - 1)) return (0, 0) def parse_item(self, item): @@ -446,7 +464,7 @@ def parse_item(self, item): return self.update_item else: - self.logger.warning("DuW: LU register: {} not supported by configured device!".format(register)) + self.logger.warning("{}: LU register: {} not supported by configured device!".format(self._name, register)) return None if self.has_iattr(item.conf, 'DuW_WP_register'): register = int(self.get_iattr_value(item.conf, 'DuW_WP_register')) @@ -461,7 +479,7 @@ def parse_item(self, item): return self.update_item else: - self.logger.warning("DuW: WP register: {} not supported by configured device!".format(register)) + self.logger.warning("{}: WP register: {} not supported by configured device!".format(self._name, register)) return None def update_item(self, item, caller=None, source=None, dest=None): @@ -472,32 +490,38 @@ def update_item(self, item, caller=None, source=None, dest=None): reginfo = self.LUregl[register]['reginfo'] data = item() * int(reginfo[4]) * (10 ** int(reginfo[5])) if (data < int(reginfo[2]) or data > int(reginfo[3])): - self.logger.error("DuW: value of LU register: {} out of range, changes ignored!".format(register)) + self.logger.error("{}: value of LU register: {} out of range, changes ignored!".format( + self._name, register)) pass else: if reginfo[6] == 'R/W': - self.logger.debug("DuW: update LU register: {0} {1} with {2}".format(register,reginfo[1],data)) + self.logger.debug("{}: update LU register: {} {} with {}".format( + self._name, register,reginfo[1],data)) self.write_DW(reginfo[7], register, data) else: - self.logger.warning("DuW: tried to update read only LU register: {}".format(register)) + (data, done) = self._read_register(reginfo[7], register, int(reginfo[4]), int(reginfo[5])) + if done: + item(data, 'DuW', 'query') + self.logger.info("{}: Queried read only LU register: {}".format(self._name, register)) + else: + self.logger.debug("{}: Query LU register failed: {}".format(self._name, register)) if self.has_iattr(item.conf, 'DuW_WP_register'): register = int(self.get_iattr_value(item.conf, 'DuW_WP_register')) if register in self.WPregl: reginfo = self.WPregl[register]['reginfo'] data = item() * int(reginfo[4]) * (10 ** int(reginfo[5])) if (data < int(reginfo[2]) or data > int(reginfo[3])): - self.logger.error("DuW: value of WP register {} out of range, changes ignored!".format(register)) + self.logger.error("{}: value of WP register {} out of range, changes ignored!".format(register)) pass else: if reginfo[6] == 'R/W': - self.logger.debug("DuW: update WP register: {0} {1} with {2}".format(register,reginfo[1],data)) + self.logger.debug("{}: update WP register: {} {} with {}".format( + self._name, register,reginfo[1],data)) self.write_DW(reginfo[7], register, data) else: - self.logger.warning( - "DuW: tried to update read only WP register: {}".format(register)) - -if __name__ == '__main__': - logging.basicConfig(level=logging.DEBUG, format='%(relativeCreated)6d %(threadName)s %(message)s') - # todo - # change PluginClassName appropriately - PluginClassName(DuW).run() \ No newline at end of file + (data, done) = self._read_register(reginfo[7], register, int(reginfo[4]), int(reginfo[5])) + if done: + item(data, 'DuW', 'query') + self.logger.info("{}: Queried read only WP register: {}".format(self._name, register)) + else: + self.logger.debug("{}: Query WP register failed: {}".format(self._name, register)) diff --git a/drexelundweiss/plugin.yaml b/drexelundweiss/plugin.yaml index 4cdd184b3..e092a086c 100755 --- a/drexelundweiss/plugin.yaml +++ b/drexelundweiss/plugin.yaml @@ -5,27 +5,72 @@ plugin: description: de: 'Unterstützt Drexel & Weiss USB Devices' en: '' - maintainer: '?' + maintainer: 'onkelandy' tester: onkelandy, brandst # keywords: iot xyz # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/34582-drexel-weiss-plugin - version: 1.3.0 # Plugin version - sh_minversion: 1.3 # minimum shNG version to use this plugin + version: 1.5.1 # Plugin version + sh_minversion: 1.5 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance classname: DuW # class containing the plugin parameters: # Definition of parameters to be configured in etc/plugin.yaml - + tty: + type: str + default: '' + description: + de: "Beim Nutzen einer RS232/USB Schnittstelle ist die serielle Schnittstelle anzugeben." + en: "If you use a RS232/USB cable to communicate with your device define the serial port." + + LU_ID: + type: int + default: 130 + description: + de: "ID für Lüftung." + en: "ID for ventilation." + + WP_ID: + type: int + default: 140 + description: + de: "ID für Heizung." + en: "ID for heating." + + device: + type: int + default: 0 + description: + de: "ID des Geräts, falls die Info nicht automatisch ausgelesen werden kann." + en: "ID of the device if it is not possible to read it automatically." + + retrylimit: + type: int + default: 100 + description: + de: "Maximale Versuche, einen Wert einzulesen." + en: "Maximum retries to read a value." + + busmonitor: + type: bool + default: False + description: + de: "Busmonitor." + en: "Busmonitor." + item_attributes: # Definition of item attributes defined by this plugin - -logic_parameters: NONE - # Definition of logic parameters defined by this plugin - -plugin_functions: NONE - # Definition of function interface of the plugin + DuW_WP_register: + type: int + description: + de: 'Register für Wärmepumpe entsprechend Textdatei' + en: 'Register for heating based on text file' + DuW_LU_register: + type: int + description: + de: 'Register für Lüftung entsprechend Textdatei' + en: 'Register for ventilation based on text file' From 06764eb707eeb18b92a9dab4a6cfbb97d1322ddb Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sun, 23 Sep 2018 20:03:57 +0200 Subject: [PATCH 280/705] drexelundweiss: Updated logging to newest sampleplugin, minor tweaks --- drexelundweiss/__init__.py | 142 ++++++++++++++++++------------------- 1 file changed, 68 insertions(+), 74 deletions(-) diff --git a/drexelundweiss/__init__.py b/drexelundweiss/__init__.py index 965ff332b..dd8cf2d10 100755 --- a/drexelundweiss/__init__.py +++ b/drexelundweiss/__init__.py @@ -26,6 +26,7 @@ import time import string import re +import codecs from lib.model.smartplugin import SmartPlugin from bin.smarthome import VERSION @@ -44,7 +45,7 @@ def __init__(self, smarthome): if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': self.logger = logging.getLogger(__name__) if not REQUIRED_PACKAGE_IMPORTED: - self.logger.error("{}: Unable to import Python package 'serial'".format(self._name)) + self.logger.error("Unable to import Python package 'serial'") self._init_complete = False return try: @@ -95,13 +96,13 @@ def __init__(self, smarthome): self.devl[17] = {'device': 'aerosilent stratos', 'cmdpath': smarthome.base_dir + '/plugins/drexelundweiss/aerosilent_stratos.txt'} except Exception as err: - self.logger.error("{}: Error on init {}.".format(self._name, err)) + self.logger.error("Error on init {}.".format(err)) self._init_complete = False return try: self._port = serial.Serial(self._tty, 115200, timeout=5) except: - self.logger.error("{}: could not open {}.".format(self._name, self._tty)) + self.logger.error("Could not open {}.".format(self._tty)) return else: self._is_connected = True @@ -112,7 +113,6 @@ def __init__(self, smarthome): def _convertresponse(self,antwort,teil): antwort = antwort.decode() - #self.logger.debug("{}: Antwort: {}".format(antwort)) allow = string.digits + ' ' antwort = re.sub('[^%s]' % allow, '', antwort) liste = antwort.splitlines() @@ -142,42 +142,41 @@ def _convertresponse(self,antwort,teil): def _get_device_type(self): self.alive = True if self._is_connected: - (data, done) = self._read_register('LU\n', 5000, 1, 0) + (data, done) = self._read_register('LU', 5000, 1, 0) if done: if data in self.devl: - self.logger.info("{}: device: {}".format(self._name, self.devl[data]['device'])) + self.logger.info("device: {}".format(self.devl[data]['device'])) if os.path.isfile(self.devl[data]['cmdpath']): self._cmd = self.devl[data]['cmdpath'] - self.logger.debug("{}: Command File:{}".format(self._name, self._cmd)) + self.logger.debug("Command File: {}".format(self._cmd)) else: - self.logger.error( - "{}: no command file found at {}".format(self._name, self.devl[data]['cmdpath'])) + self.logger.error("No command file found at {}".format(self.devl[data]['cmdpath'])) self._cmd = False else: - self.logger.error("{}: device not supported: {}".format(self._name, data)) + self.logger.error("Device not supported: {}".format(data)) self._cmd = False else: - self.logger.error("{}: Error reading device type! Trying to activate configured device".format(self._name)) + self.logger.error("Error reading device type! Trying to activate configured device") if os.path.isfile(self.devl[self._device]['cmdpath']): self._cmd = self.devl[self._device]['cmdpath'] - self.logger.info("{}: device: {}".format(self._name, self.devl[self._device]['device'])) + self.logger.info("device: {}".format(self.devl[self._device]['device'])) #self._cmd = False else: self._cmd = False - self.logger.error("{}: no connection".format(self._name)) + self.logger.error("no connection") self.alive = False def _send_DW(self, data, pcb): if not self._is_connected: return False - if (pcb == 'LU\n'): + if (pcb == 'LU'): device_ID = self._LU_ID - elif(pcb == 'WP\n'): + elif(pcb == 'WP'): device_ID = self._WP_ID else: - self.logger.error("{}: wrong pcb description".format(self._name)) + self.logger.error("wrong pcb description {}".format(pcb)) return if not self._lock.acquire(timeout=2): @@ -185,62 +184,58 @@ def _send_DW(self, data, pcb): try: self._port.write("{0} {1}\r\n".format(device_ID,data).encode()) except Exception as e: - self.logger.error("{}: Problem sending {}".format(self._name, e)) + self.logger.error("Problem sending {}".format(e)) finally: self._lock.release() def _get_register_info(self, register, pcb): - if (pcb == 'LU\n'): + if (pcb == 'LU'): if register in self.LUcmdl: return self.LUcmdl[register]['reginfo'] else: return False - elif(pcb == 'WP\n'): + elif(pcb == 'WP'): if register in self.WPcmdl: return self.WPcmdl[register]['reginfo'] else: return False else: - self.logger.error("{}: wrong pcb description".format(self._name)) + self.logger.error("wrong pcb description {}".format(pcb)) return def _load_cmd(self): - self.logger.debug("{}: Opening command file".format(self._name)) - f = open(self._cmd, "r") - self.logger.debug("{}: Opened command file".format(self._name)) - try: + with codecs.open(self._cmd, 'r', 'utf-8') as f: + self.logger.debug("Opened command file {}".format(f)) for line in f: if not self._lock.acquire(timeout=2): return try: - row = line.split(";") + row = line.replace('\r\n', '').split(";") # skip first row if (row[1] == ""): pass else: - if row[7] == 'LU\n': + if row[7] == 'LU': self.LUcmdl[int(row[0])] = {'reginfo': row} - elif row[7] == 'WP\n': + elif row[7] == 'WP': self.WPcmdl[int(row[0])] = {'reginfo': row} else: - self.logger.debug("{}: Error in Commandfile: {}".format(self._name, line)) + self.logger.debug("Error in Commandfile: {}, end of row: {}.".format(line, row[7])) except Exception as e: - self.logger.error("{}: problems loading commands: {}".format(self._name, e)) + self.logger.error("problems loading commands: {}".format(e)) finally: self._lock.release() - finally: - f.close() def run(self): - self.logger.debug("{}: run method called".format(self._name)) + self.logger.debug("run method called") if not self._cmd: self.alive = False try: if self._is_connected: self._port.close() except Exception as e: - self.logger.error("{}: Error {}".format(self._name, e)) + self.logger.error("Error {}".format(e)) return self.alive = True @@ -256,7 +251,7 @@ def run(self): if done: item(data, 'DuW', 'init process') else: - self.logger.debug("{}: Init LU register failed: {}".format(self._name, register)) + self.logger.debug("Init LU register failed: {}".format(register)) # WP register init for register in self.WPregl: @@ -269,7 +264,7 @@ def run(self): if done: item(data, 'DuW', 'init process') else: - self.logger.debug("{}: Init WP register failed: {}".format(self._name, register)) + self.logger.debug("Init WP register failed: {}".format(register)) # poll DuW interface dw_id = 0 @@ -305,10 +300,10 @@ def run(self): divisor = int(reginfo[4]) komma = int(reginfo[5]) self.logger.debug("DuW Busmonitor LU register: {} {}: {}".format( - self._name, dw_register,reginfo[1],((dw_data / divisor) / (10 ** komma)))) + dw_register, reginfo[1], ((dw_data / divisor) / (10 ** komma)))) else: - self.logger.debug("{} Busmonitor: unknown LU register: {} {}".format( - self._name, dw_register,dw_data)) + self.logger.debug("DuW Busmonitor: unknown LU register: {} {}".format( + dw_register, dw_data)) elif dw_id == self._WP_ID: if dw_register in self.WPcmdl: reginfo = self.WPcmdl[dw_register][ @@ -316,13 +311,12 @@ def run(self): divisor = int(reginfo[4]) komma = int(reginfo[5]) self.logger.debug("DuW Busmonitor WP register: {} {}: {}".format( - self._name, dw_register,reginfo[1],((dw_data / divisor) / (10 ** komma)))) + dw_register, reginfo[1], ((dw_data / divisor) / (10 ** komma)))) else: - self.logger.debug("{} Busmonitor: unknown WP register: {} {}".format( - self._name, dw_register,dw_data)) + self.logger.debug("DuW Busmonitor: unknown WP register: {} {}".format( + dw_register, dw_data)) else: - self.logger.debug( - "{} Busmonitor: unknown device ID: {}".format(self._name, dw_id)) + self.logger.debug("DuW Busmonitor: unknown device ID: {}".format(dw_id)) if dw_id == self._LU_ID: if dw_register in self.LUregl: @@ -336,7 +330,7 @@ def run(self): / (10 ** komma)), 'DuW', 'Poll') else: - self.logger.debug("{}: Ignore LU register {}".format(self._name, dw_register)) + self.logger.debug("Ignore LU register {}".format(dw_register)) elif dw_id == self._WP_ID: if dw_register in self.WPregl: reginfo = self.WPregl[ @@ -349,9 +343,9 @@ def run(self): / (10 ** komma)), 'DuW', 'Poll') else: - self.logger.debug("{}: Ignore WP register {}" .format(self._name, dw_register)) + self.logger.debug("Ignore WP register {}" .format(dw_register)) else: - self.logger.debug("{}: unknown device ID: {}".format(self._name, dw_id)) + self.logger.debug("unknown device ID: {}".format(dw_id)) dw_id = 0 dw_register = 0 @@ -362,20 +356,20 @@ def run(self): dw_id = 0 dw_register = 0 dw_data = 0 - self.logger.debug("{}: Read timeout".format(self._name)) + self.logger.debug("Read timeout") except Exception as e: - self.logger.error("{}: Polling error {}".format(self._name, e)) + self.logger.error("Polling error {}".format(e)) finally: self._lock.release() time.sleep(0.1) # exit poll service self._pollservice = False except Exception as e: - self.logger.error("{}: not alive error, {}".format(self._name, e)) + self.logger.error("not alive error, {}".format(e)) def stop(self): self.alive = False - self.logger.debug("{}: stop method called".format(self._name)) + self.logger.debug("stop method called") while self._pollservice == True: pass @@ -383,7 +377,7 @@ def stop(self): if self._is_connected: self._port.close() except Exception as e: - self.logger.error("{}: Stop Exception, {}".format(self._name, e)) + self.logger.error("Stop Exception, {}".format(e)) def write_DW(self, pcb, register, value): self._send_DW("{0:d} {1:d}".format(int(register), int(value)), pcb) @@ -392,12 +386,12 @@ def req_DW(self, pcb, register): self._send_DW("{0:d}".format(int(register)), pcb) def _read_register(self, pcb, register, divisor, komma): - if (pcb == 'LU\n'): + if (pcb == 'LU'): device_ID = self._LU_ID - elif(pcb == 'WP\n'): + elif(pcb == 'WP'): device_ID = self._WP_ID else: - self.logger.error("{}: wrong pcb description".format(self._name)) + self.logger.error("wrong pcb description {}".format(pcb)) self._port.flushInput() self.req_DW(pcb, str(register + 1)) @@ -428,24 +422,24 @@ def _read_register(self, pcb, register, divisor, komma): response = bytes() else: retries += 1 - self.logger.info("{}: read timeout: {}. Retries: {}".format(self._name, response, retries)) + self.logger.info("read timeout: {}. Retries: {}".format(response, retries)) if retries >= self._retrylimit: break time.sleep(0.1) except Exception as e: - self.logger.warning("{}: Read error: {}".format(self._name, e)) + self.logger.warning("Read error: {}".format(e)) finally: self._lock.release() if(dw_id == device_ID and (dw_register - 1) == register): - self.logger.debug("{}: Read {} on Register: {}".format(self._name, dw_data, register)) + self.logger.debug(" Read {} on Register: {}".format(dw_data, register)) try: return (((dw_data / divisor) / (10 ** komma)), 1) except: - self.logger.debug("Division durch Null Problem") + self.logger.debug("Division with zero problem") return (((dw_data / 1) / (10 ** 1)), 1) else: - self.logger.error("{}: read errror Device ID: {}, register {}".format(self._name, dw_id, dw_register - 1)) + self.logger.error("read errror Device ID: {}, register {}".format(dw_id, dw_register - 1)) return (0, 0) def parse_item(self, item): @@ -453,7 +447,7 @@ def parse_item(self, item): return None if self.has_iattr(item.conf, 'DuW_LU_register'): register = int(self.get_iattr_value(item.conf, 'DuW_LU_register')) - reginfo = self._get_register_info(register, 'LU\n') + reginfo = self._get_register_info(register, 'LU') if reginfo: if not register in self.LUregl: self.LUregl[register] = {'reginfo': @@ -464,11 +458,11 @@ def parse_item(self, item): return self.update_item else: - self.logger.warning("{}: LU register: {} not supported by configured device!".format(self._name, register)) + self.logger.warning("LU register: {} not supported by configured device!".format(register)) return None if self.has_iattr(item.conf, 'DuW_WP_register'): register = int(self.get_iattr_value(item.conf, 'DuW_WP_register')) - reginfo = self._get_register_info(register, 'WP\n') + reginfo = self._get_register_info(register, 'WP') if reginfo: if not register in self.WPregl: self.WPregl[register] = {'reginfo': @@ -479,7 +473,7 @@ def parse_item(self, item): return self.update_item else: - self.logger.warning("{}: WP register: {} not supported by configured device!".format(self._name, register)) + self.logger.warning("WP register: {} not supported by configured device!".format(register)) return None def update_item(self, item, caller=None, source=None, dest=None): @@ -490,38 +484,38 @@ def update_item(self, item, caller=None, source=None, dest=None): reginfo = self.LUregl[register]['reginfo'] data = item() * int(reginfo[4]) * (10 ** int(reginfo[5])) if (data < int(reginfo[2]) or data > int(reginfo[3])): - self.logger.error("{}: value of LU register: {} out of range, changes ignored!".format( - self._name, register)) + self.logger.error("value of LU register: {} out of range, changes ignored!".format( + register)) pass else: if reginfo[6] == 'R/W': - self.logger.debug("{}: update LU register: {} {} with {}".format( - self._name, register,reginfo[1],data)) + self.logger.debug("update LU register: {} {} with {}".format( + register,reginfo[1],data)) self.write_DW(reginfo[7], register, data) else: (data, done) = self._read_register(reginfo[7], register, int(reginfo[4]), int(reginfo[5])) if done: item(data, 'DuW', 'query') - self.logger.info("{}: Queried read only LU register: {}".format(self._name, register)) + self.logger.info("Queried read only LU register: {}".format(register)) else: - self.logger.debug("{}: Query LU register failed: {}".format(self._name, register)) + self.logger.debug("Query LU register failed: {}".format(register)) if self.has_iattr(item.conf, 'DuW_WP_register'): register = int(self.get_iattr_value(item.conf, 'DuW_WP_register')) if register in self.WPregl: reginfo = self.WPregl[register]['reginfo'] data = item() * int(reginfo[4]) * (10 ** int(reginfo[5])) if (data < int(reginfo[2]) or data > int(reginfo[3])): - self.logger.error("{}: value of WP register {} out of range, changes ignored!".format(register)) + self.logger.error("value of WP register {} out of range, changes ignored!".format(register)) pass else: if reginfo[6] == 'R/W': - self.logger.debug("{}: update WP register: {} {} with {}".format( - self._name, register,reginfo[1],data)) + self.logger.debug("update WP register: {} {} with {}".format( + register,reginfo[1],data)) self.write_DW(reginfo[7], register, data) else: (data, done) = self._read_register(reginfo[7], register, int(reginfo[4]), int(reginfo[5])) if done: item(data, 'DuW', 'query') - self.logger.info("{}: Queried read only WP register: {}".format(self._name, register)) + self.logger.info("Queried read only WP register: {}".format(register)) else: - self.logger.debug("{}: Query WP register failed: {}".format(self._name, register)) + self.logger.debug("Query WP register failed: {}".format(register)) From 3b5aef7f6b63a3c39e09f56a4140ac76f08235e6 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 24 Sep 2018 18:12:11 +0200 Subject: [PATCH 281/705] Nokia Health: fixed header --- nokia_health/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/nokia_health/__init__.py b/nokia_health/__init__.py index f5d5aa669..640f90dfc 100644 --- a/nokia_health/__init__.py +++ b/nokia_health/__init__.py @@ -1,8 +1,7 @@ #!/usr/bin/env python3 # ######################################################################### -# Copyright 2017 Marc René Frieß rene.friess(a)gmail.com -# Version 1.3.1 +# Copyright 2017-2018 Marc René Frieß rene.friess(a)gmail.com ######################################################################### # # This file is part of SmartHomeNG. From 1e54f062d5849a52efe270a6761c58a53f0ab2c7 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Thu, 27 Sep 2018 14:02:47 +0200 Subject: [PATCH 282/705] Updated logger implementation and info --- uzsu/__init__.py | 229 +++++++++++++++++++++++------------------------ 1 file changed, 114 insertions(+), 115 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 2757556bc..bc7e31774 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -99,7 +99,6 @@ def __init__(self, smarthome): if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': self.logger = logging.getLogger(__name__) self.itemsApi = Items.get_instance() - self._name = self.get_fullname() self._timezone = Shtime.get_instance().tzinfo() self._remove_duplicates = self.get_parameter_value('remove_duplicates') self._sh = smarthome @@ -109,10 +108,9 @@ def __init__(self, smarthome): self._update_count = {'todo': 0, 'done': 0} self._itpl = OrderedDict() self.init_webinterface() - self.logger.info('{}: Init with timezone {}'.format(self._name, self._timezone)) + self.logger.info("Init with timezone {}".format(self._timezone)) if not REQUIRED_PACKAGE_IMPORTED: - self.logger.error("{}: Unable to import Python package 'scipy'" - " which is necessary for interpolation.".format(self._name)) + self.logger.warning("Unable to import Python package 'scipy' which is necessary for interpolation.") self._init_complete = False def run(self): @@ -120,10 +118,10 @@ def run(self): This is called once at the beginning after all items are already parsed from smarthome.py All active uzsu items are registered to the scheduler """ - self.logger.debug('{}: run method called'.format(self._name)) + self.logger.debug("run method called") self.alive = True self.scheduler_add('uzsu_sunupdate', self._update_all_suns, value={'caller': 'scheduler'}, cron='0 0 * *') - self.logger.info('{}: Adding sun update schedule for midnight'.format(self._name)) + self.logger.info("Adding sun update schedule for midnight") for item in self._items: self._items[item]['interpolation']['itemtype'] = self._add_type(item) @@ -143,13 +141,13 @@ def stop(self): """ Stop method for the plugin """ - self.logger.debug('{}: stop method called'.format(self._name)) + self.logger.debug("stop method called") for item in self._items: try: self.scheduler_remove('uzsu_{}'.format(item)) - self.logger.debug('{}: Removing scheduler for item {}'.format(self._name, item)) + self.logger.debug('Removing scheduler for item {}'.format(item)) except Exception as err: - self.logger.debug('{}: Scheduler for item {} not removed. Problem: {}'.format(self._name, item, err)) + self.logger.debug('Scheduler for item {} not removed. Problem: {}'.format(item, err)) self.alive = False def _update_all_suns(self, caller=None): @@ -162,7 +160,7 @@ def _update_all_suns(self, caller=None): for item in self._items: success = self._update_sun(item) if success: - self.logger.debug('{}: Updating item {}'.format(self._name, item)) + self.logger.debug('Updating item {}'.format(item)) item(self._items[item]) def _update_sun(self, item, caller=None): @@ -185,8 +183,8 @@ def _update_sun(self, item, caller=None): _sunset = _sunset.astimezone(self._timezone) self._items[item]['sunrise'] = '{:02}:{:02}'.format(_sunrise.hour, _sunrise.minute) self._items[item]['sunset'] = '{:02}:{:02}'.format(_sunset.hour, _sunset.minute) - self.logger.debug('{}: Updated sun entries for item {}, triggered by {}. sunrise: {}, sunset: {}'.format( - self._name, item, caller, self._items[item]['sunrise'], self._items[item]['sunset'])) + self.logger.debug('Updated sun entries for item {}, triggered by {}. sunrise: {}, sunset: {}'.format( + item, caller, self._items[item]['sunrise'], self._items[item]['sunset'])) success = True except Exception: success = False @@ -201,13 +199,13 @@ def _update_suncalc(self, item, entry, entryindex, entryvalue): else: update = True if update is True and not entry.get('calculated') == entryvalue: - self.logger.debug("{}: Updated calculated time for item {} entry {} with {}.".format( - self._name, item, self._items[item]['list'][entryindex], entryvalue)) + self.logger.debug("Updated calculated time for item {} entry {} with value {}.".format( + item, self._items[item]['list'][entryindex], entryvalue)) self._items[item]['list'][entryindex]['calculated'] = entryvalue item(self._items[item], 'USZU Plugin', 'update_sun') else: - self.logger.debug("{}: Sun calculation {} entry not updated for item {} with value {}".format( - self._name, entryvalue, item, entry.get('calculated'))) + self.logger.debug("Sun calculation {} entry not updated for item {} with value {}".format( + entryvalue, item, entry.get('calculated'))) def _add_type(self, item): """ @@ -221,13 +219,14 @@ def _add_type(self, item): _uzsuitem = self.itemsApi.return_item(self.get_iattr_value(item.conf, ITEM_TAG[0])) except Exception as err: _uzsuitem = None - self.logger.warning("{}: Item to be set by uzsu does not exist. Error: {}".format(self._name, err)) + self.logger.warning("Item to be set by uzsu '{}' does not exist. Error: {}".format( + self.get_iattr_value(item.conf, ITEM_TAG[0]), err)) try: _itemtype = _uzsuitem.type() except Exception as err: _itemtype = 'foo' if _uzsuitem else None - self.logger.warning("{}: Item to be set by uzsu does not have a type attribute. Error: {}".format( - self._name, err)) + self.logger.warning("Item to be set by uzsu '{}' does not have a type attribute. Error: {}".format( + self.get_iattr_value(item.conf, ITEM_TAG[0]), err)) return _itemtype def _logics_activate(self, activevalue=None, item=None): @@ -237,11 +236,11 @@ def _logics_activate(self, activevalue=None, item=None): elif activevalue.lower() in ['0', 'no', 'false', 'off']: activevalue = False else: - self.logger.warning("{}: Value to activate item {} has to be True or False".format(self._name, item)) + self.logger.warning("Value to activate item '{}' has to be True or False".format(item)) if isinstance(activevalue, bool): self._items[item] = item() self._items[item]['active'] = activevalue - self.logger.info("{}: Item {} is set via logic to: {}".format(self._name, item, activevalue)) + self.logger.info("Item {} is set via logic to: {}".format(item, activevalue)) item(self._items[item], 'UZSU Plugin', 'logic') if activevalue is None: return self._items[item].get('active') @@ -254,8 +253,8 @@ def _logics_interpolation(self, type=None, interval=5, backintime=0, item=None): self._items[item]['interpolation']['type'] = str(type).lower() self._items[item]['interpolation']['interval'] = int(interval) self._items[item]['interpolation']['initage'] = int(backintime) - self.logger.info("{}: Item {} interpolation is set via logic to: type={}, interval={}, backintime={}".format( - self._name, item, type, interval, backintime)) + self.logger.info("Item {} interpolation is set via logic to: type={}, interval={}, backintime={}".format( + item, type, interval, backintime)) item(self._items[item], 'UZSU Plugin', 'logic') def _logics_clear(self, clear=False, item=None): @@ -263,20 +262,20 @@ def _logics_clear(self, clear=False, item=None): if clear.lower() in ['1', 'yes', 'true', 'on']: clear = True else: - self.logger.warning("{}: Value to clear uzsu item {} has to be True".format(self._name, item)) + self.logger.warning("Value to clear uzsu item '{}' has to be True".format(item)) if isinstance(clear, bool) and clear is True: self._items[item].clear() self._items[item] = {'interpolation': {}, 'active': False} - self.logger.info("{}: UZSU settings for item {} are cleared".format(self._name, item)) + self.logger.info("UZSU settings for item '{}' are cleared".format(item)) item(self._items[item], 'UZSU Plugin', 'clear') def _logics_planned(self, item=None): try: - self.logger.info("{}: Item {} is going to be set to {} at {}".format( - self._name, item, self._planned[item]['value'], self._planned[item]['next'])) + self.logger.info("Item {} is going to be set to {} at {}".format( + item, self._planned[item]['value'], self._planned[item]['next'])) return self._planned[item] except Exception: - self.logger.info("{}: Nothing planned for item {}. {}".format(self._name, item, self._planned)) + self.logger.info("Nothing planned for item {}. {}".format(item, self._planned)) return None def parse_item(self, item): @@ -311,18 +310,18 @@ def parse_item(self, item): self._items[item]['interpolation'] = {} self._items[item]['interpolation']['initialized'] = False item(self._items[item], 'USZU Plugin', 'init') - self.logger.debug('{}: Dict for item {} is: {}'.format(self._name, item, self._items[item])) + self.logger.debug('Dict for item {} is: {}'.format(item, self._items[item])) return self.update_item def _remove_dupes(self, item): self._items[item]['list'] = [i for n, i in enumerate(self._items[item]['list']) if i not in self._items[item]['list'][:n]] - self.logger.debug('{}: Removed duplicate entries for item {}.'.format(self._name, item)) + self.logger.debug('Removed duplicate entries for item {}.'.format(item)) compare_entries = item.prev_value() if compare_entries.get('list'): newentries = [] [newentries.append(i) for i in self._items[item]['list'] if i not in compare_entries['list']] - self.logger.debug('{}: Got update for item {}: {}'.format(self._name, item, newentries)) + self.logger.debug('Got update for item {}: {}'.format(item, newentries)) for entry in self._items[item]['list']: for new in newentries: found = False @@ -337,9 +336,9 @@ def _remove_dupes(self, item): self._items[item]['list'][self._items[item]['list'].index(entry)].update({'active': False}) time = entry['time'] oldvalue, newvalue = entry['value'], new['value'] - self.logger.warning('{}: Set old entry for item {} at {} with value {} to inactive' - ' because newer active entry with value {} found.'.format( - self._name, item, time, oldvalue, newvalue)) + self.logger.warning("Set old entry for item '{}' at {} with value {} to inactive" + " because newer active entry with value {} found.".format( + item, time, oldvalue, newvalue)) item(self._items[item], 'USZU Plugin', 'update') def update_item(self, item, caller=None, source=None, dest=None): @@ -353,8 +352,8 @@ def update_item(self, item, caller=None, source=None, dest=None): :param dest: if given it represents the dest """ self._items[item] = item() - self.logger.debug('{}: Update Item {}, Caller {}, Source {}, Dest {}.'.format( - self._name, item, caller, source, dest)) + self.logger.debug('Update Item {}, Caller {}, Source {}, Dest {}.'.format( + item, caller, source, dest)) # Removing Duplicates if self._remove_duplicates is True and self._items[item].get('list') and not caller == 'USZU Plugin': self._remove_dupes(item) @@ -371,18 +370,18 @@ def _schedule(self, item, caller=None): :param caller: if given it represents the callers name """ self.scheduler_remove('uzsu_{}'.format(item)) - self.logger.debug('{}: Schedule Item {}, Trigger: {}, Changed by: {}'.format( - self._name, item, caller, item.changed_by())) + self.logger.debug('Schedule Item {}, Trigger: {}, Changed by: {}'.format( + item, caller, item.changed_by())) _next = None _value = None self._update_sun(item, caller='schedule') if not self._items[item]['interpolation'].get('itemtype'): - self.logger.error("{}: item '{}' to be set by uzsu does not exist.".format( - self._name, self.get_iattr_value(item.conf, ITEM_TAG[0]))) + self.logger.error("item '{}' to be set by uzsu does not exist.".format( + self.get_iattr_value(item.conf, ITEM_TAG[0]))) elif not self._items[item].get('list'): - self.logger.warning("{}: uzsu item '{}' is active but has no entries.".format( - self._name, item)) + self.logger.warning("uzsu item '{}' is active but has no entries.".format( + item)) else: self._itpl.clear() for i, entry in enumerate(self._items[item]['list']): @@ -398,19 +397,19 @@ def _schedule(self, item, caller=None): value = prev_value item(self._items[item], 'USZU Plugin', 'schedule') if next is not None: - self.logger.debug("{}: uzsu active entry for item {} with datetime {}, value {}" - " and tzinfo {}".format(self._name, item, next, value, next.tzinfo)) + self.logger.debug("uzsu active entry for item {} with datetime {}, value {}" + " and tzinfo {}".format(item, next, value, next.tzinfo)) if _next is None: _next = next _value = value elif next and next < _next: - self.logger.debug("{}: uzsu active entry for item {} using now {}, value {}" - " and tzinfo {}".format(self._name, item, next, value, next.tzinfo)) + self.logger.debug("uzsu active entry for item {} using now {}, value {}" + " and tzinfo {}".format(item, next, value, next.tzinfo)) _next = next _value = value else: - self.logger.debug("{}: uzsu active entry for item {} keep {}, value {} and tzinfo {}".format( - self._name, item, _next, _value, _next.tzinfo)) + self.logger.debug("uzsu active entry for item {} keep {}, value {} and tzinfo {}".format( + item, _next, _value, _next.tzinfo)) if _next and _value is not None and 'active' in self._items[item] and self._items[item]['active'] is True: _reset_interpolation = False _interval = self._items[item]['interpolation'].get('interval') @@ -441,25 +440,25 @@ def _schedule(self, item, caller=None): cond5 = isinstance(_value, float) self._itpl = OrderedDict(itpl_list) if not cond2 and cond3 and cond4: - self.logger.info("{}: Looking if there was a value set after {} for item {}".format( - self._name, _timediff, item)) + self.logger.info("Looking if there was a value set after {} for item {}".format( + _timediff, item)) self._items[item]['interpolation']['initialized'] = True item(self._items[item], 'USZU Plugin', 'init') if cond1 and not cond2 and cond3: self._set(item=item, value=_initvalue, caller='scheduler') - self.logger.info("{}: Updated item {} on startup with value {} from time {}".format( - self._name, item, _initvalue, datetime.fromtimestamp(_inittime/1000.0))) + self.logger.info("Updated item {} on startup with value {} from time {}".format( + item, _initvalue, datetime.fromtimestamp(_inittime/1000.0))) _itemtype = self._items[item]['interpolation'].get('itemtype') if cond2 and not REQUIRED_PACKAGE_IMPORTED: - self.logger.warning("{}: Interpolation is set to {} but scipy not installed. Ignoring interpolation".format( - self._name, _interpolation)) + self.logger.warning("Interpolation is set to {} but scipy not installed. Ignoring interpolation".format( + _interpolation)) elif cond2 and _interval < 1: - self.logger.warning("{}: Interpolation is set to {} but interval is {}. Ignoring interpolation".format( - self._name, _interpolation, _interval)) + self.logger.warning("Interpolation is set to {} but interval is {}. Ignoring interpolation".format( + _interpolation, _interval)) elif cond2 and _itemtype not in ['num']: - self.logger.warning("{}: Interpolation is set to {} but type of item is {}." + self.logger.warning("Interpolation is set to {} but type of item is {}." " Ignoring interpolation and setting USZU interpolation to none.".format( - self._name, _interpolation, _itemtype)) + _interpolation, _itemtype)) _reset_interpolation = True elif _interpolation.lower() == 'cubic' and _interval > 0: try: @@ -469,10 +468,10 @@ def _schedule(self, item, caller=None): _value = round(float(tck(_next.timestamp() * 1000.0)), 2) _value_now = round(float(tck(entry_now)), 2) self._set(item=item, value=_value_now, caller='scheduler') - self.logger.info("{}: Updated: {}, cubic interpolation value: {}, based on dict: {}." - " Next: {}, value: {}".format(self._name, item, _value_now, self._itpl, _next, _value)) + self.logger.info("Updated: {}, cubic interpolation value: {}, based on dict: {}." + " Next: {}, value: {}".format(item, _value_now, self._itpl, _next, _value)) except Exception as e: - self.logger.error("{}: Error cubic interpolation: {}".format(self._name, e)) + self.logger.error("Error cubic interpolation: {}".format(e)) elif _interpolation.lower() == 'linear' and _interval > 0: try: tck = interpolate.interp1d(list(self._itpl.keys()), list(self._itpl.values())) @@ -481,19 +480,19 @@ def _schedule(self, item, caller=None): _value = round(float(tck(_next.timestamp() * 1000.0)), 2) _value_now = round(float(tck(entry_now)), 2) self._set(item=item, value=_value_now, caller='scheduler') - self.logger.info("{}: Updated: {}, linear interpolation value: {}, based on dict: {}." - " Next: {}, value: {}".format(self._name, item, _value_now, self._itpl, _next, _value)) + self.logger.info("Updated: {}, linear interpolation value: {}, based on dict: {}." + " Next: {}, value: {}".format(item, _value_now, self._itpl, _next, _value)) except Exception as e: - self.logger.error("{}: Error linear interpolation: {}".format(self._name, e)) + self.logger.error("Error linear interpolation: {}".format(e)) if cond5 and _value < 0: - self.logger.warning("{}: value {} for item {} is negative. This might be due" - " to not enough values set in the UZSU.".format(self._name, _value, item)) + self.logger.warning("value {} for item '{}' is negative. This might be due" + " to not enough values set in the UZSU.".format(_value, item)) if _reset_interpolation is True: self._items[item]['interpolation']['type'] = 'none' item(self._items[item], 'USZU Plugin', 'reset_interpolation') else: - self.logger.debug("{}: will add scheduler named uzsu_{} with datetime {} and tzinfo {}" - " and value {}".format(self._name, item, _next, _next.tzinfo, _value)) + self.logger.debug("will add scheduler named uzsu_{} with datetime {} and tzinfo {}" + " and value {}".format(item, _next, _next.tzinfo, _value)) self._planned[item] = {'value': _value, 'next': _next.strftime('%Y-%m-%d %H:%M')} self._update_count['done'] = self._update_count.get('done') + 1 self.scheduler_add('uzsu_{}'.format(item), self._set, value={'item': item, 'value': _value}, next=_next) @@ -559,21 +558,21 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): try: rrule = rrulestr(entry['rrule'], dtstart=datetime.combine( weekbefore, parser.parse(time.strip()).time())) - self.logger.debug("{}: Created rrule: '{}' for time:'{}'".format( - self._name, str(rrule).replace('\n', ';'), time)) + self.logger.debug("Created rrule: '{}' for time:'{}'".format( + str(rrule).replace('\n', ';'), time)) except ValueError: - self.logger.debug("{}: Could not create a rrule from rrule: '{}' and time:'{}'".format( - self._name, entry['rrule'], time)) + self.logger.debug("Could not create a rrule from rrule: '{}' and time:'{}'".format( + entry['rrule'], time)) if 'sun' in time: rrule = rrulestr(entry['rrule'], dtstart=datetime.combine( weekbefore, self._sun(datetime.combine(weekbefore.date(), datetime.min.time()).replace(tzinfo=self._timezone), time, timescan).time())) - self.logger.debug("{}: Looking for {} sun-related time. Found rrule: {}".format( - self._name, timescan, str(rrule).replace('\n', ';'))) + self.logger.debug("Looking for {} sun-related time. Found rrule: {}".format( + timescan, str(rrule).replace('\n', ';'))) else: rrule = rrulestr(entry['rrule'], dtstart=datetime.combine(weekbefore, datetime.min.time())) - self.logger.debug("{}: Looking for {} time. Found rrule: {}".format( - self._name, timescan, str(rrule).replace('\n', ';'))) + self.logger.debug("Looking for {} time. Found rrule: {}".format( + timescan, str(rrule).replace('\n', ';'))) dt = datetime.now() while self.alive: dt = rrule.before(dt) if timescan == 'previous' else rrule.after(dt) @@ -582,37 +581,37 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): if 'sun' in time: sleep(0.01) next = self._sun(datetime.combine(dt.date(), datetime.min.time()).replace(tzinfo=self._timezone), time, timescan) - self.logger.debug("{}: Result parsing time (rrule) {}: {}".format(self._name, time, next)) + self.logger.debug("Result parsing time (rrule) {}: {}".format(time, next)) if entryindex is not None: self._update_suncalc(item, entry, entryindex, next.strftime("%H:%M")) else: next = datetime.combine(dt.date(), parser.parse(time.strip()).time()).replace(tzinfo=self._timezone) if next and next.date() == dt.date(): self._itpl[next.timestamp() * 1000.0] = value - self.logger.debug("{}: Return from rrule {}: {}, value {}.".format(self._name, timescan, next, value)) + self.logger.debug("Return from rrule {}: {}, value {}.".format(timescan, next, value)) return next, value if 'sun' in time: next = self._sun(datetime.combine(today, datetime.min.time()).replace( tzinfo=self._timezone), time, timescan) cond_future = next > datetime.now(self._timezone) and timescan == 'next' if cond_future: - self.logger.debug("{}: Result parsing time today (sun) {}: {}".format(self._name, time, next)) + self.logger.debug("Result parsing time today (sun) {}: {}".format(time, next)) if entryindex is not None: self._update_suncalc(item, entry, entryindex, next.strftime("%H:%M")) else: self._itpl[next.timestamp() * 1000.0] = value - self.logger.debug("{}: Include previous today: {}, value {} for interpolation.".format(self._name, next, value)) + self.logger.debug("Include previous today: {}, value {} for interpolation.".format(next, value)) if entryindex: self._update_suncalc(item, entry, entryindex, next.strftime("%H:%M")) next = self._sun(datetime.combine(tomorrow, datetime.min.time()).replace( tzinfo=self._timezone), time, timescan) - self.logger.debug("{}: Result parsing time tomorrow (sun) {}: {}".format(self._name, time, next)) + self.logger.debug("Result parsing time tomorrow (sun) {}: {}".format(time, next)) else: next = datetime.combine(today, parser.parse(time.strip()).time()).replace(tzinfo=self._timezone) cond_future = next > datetime.now(self._timezone) and timescan == 'next' if not cond_future: self._itpl[next.timestamp() * 1000.0] = value - self.logger.debug("{}: Include next today: {}, value {} for interpolation.".format(self._name, next, value)) + self.logger.debug("Include next today: {}, value {} for interpolation.".format(next, value)) next = datetime.combine(tomorrow, parser.parse(time.strip()).time()).replace(tzinfo=self._timezone) cond1 = next.date() == today.date() cond2 = next.date() - timedelta(days=1) == yesterday.date() @@ -622,22 +621,22 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): cond_previous_yesterday = next - timedelta(days=1) < datetime.now(self._timezone) and timescan == 'previous' if next and cond1 and cond_next: self._itpl[next.timestamp() * 1000.0] = value - self.logger.debug("{}: Return next today: {}, value {}".format(self._name, next, value)) + self.logger.debug("Return next today: {}, value {}".format(next, value)) return next, value if next and cond3 and cond_next: self._itpl[next.timestamp() * 1000.0] = value - self.logger.debug("{}: Return next tomorrow: {}, value {}".format(self._name, next, value)) + self.logger.debug("Return next tomorrow: {}, value {}".format(next, value)) return next, value if next and cond1 and cond_previous_today: self._itpl[(next - timedelta(seconds=1)).timestamp() * 1000.0] = value - self.logger.debug("{}: Return previous today: {}, value {}".format(self._name, next, value)) + self.logger.debug("Return previous today: {}, value {}".format(next, value)) return next, value if next and cond2 and cond_previous_yesterday: self._itpl[(next - timedelta(days=1)).timestamp() * 1000.0] = value - self.logger.debug("{}: Return previous yesterday: {}, value {}".format(self._name, next - timedelta(days=1), value)) + self.logger.debug("Return previous yesterday: {}, value {}".format(next - timedelta(days=1), value)) return next - timedelta(days=1), value except Exception as e: - self.logger.error("{}: Error '{}' parsing time: {}".format(self._name, time, e)) + self.logger.error("Error '{}' parsing time: {}".format(time, e)) return None, None def _create_sun(self): @@ -647,8 +646,7 @@ def _create_sun(self): # checking preconditions from configuration: uzsu_sun = None if not self._sh.sun: # no sun object created - self.logger.error("{}: No latitude/longitude specified. " - "Not possible to create sun object.".format(self._name)) + self.logger.error("No latitude/longitude specified. Not possible to create sun object.") # create an own sun object: if not self._uzsu_sun: @@ -657,11 +655,11 @@ def _create_sun(self): latitude = self._sh.sun._obs.lat elevation = self._sh.sun._obs.elev uzsu_sun = lib.orb.Orb('sun', longitude, latitude, elevation) - self.logger.debug("{}: Created a new sun object with latitude={}, longitude={}, elevation={}".format( - self._name, latitude, longitude, elevation)) + self.logger.debug("Created a new sun object with latitude={}, longitude={}, elevation={}".format( + latitude, longitude, elevation)) except Exception as e: - self.logger.error("{}: Error '{}' creating a new sun object. You could not " - "use sunrise/sunset as UZSU entry.".format(self._name, e)) + self.logger.error("Error '{}' creating a new sun object. You could not " + "use sunrise/sunset as UZSU entry.".format(e)) else: uzsu_sun = self._uzsu_sun return uzsu_sun @@ -680,10 +678,10 @@ def _sun(self, dt, tstr, timescan): if not uzsu_sun: return - self.logger.debug("{}: Given param dt={}, tz={} for {}".format(self._name, dt, dt.tzinfo, timescan)) + self.logger.debug("Given param dt={}, tz={} for {}".format(dt, dt.tzinfo, timescan)) # now start into parsing details - self.logger.debug('{}: Examine param time string: {}'.format(self._name, tstr)) + self.logger.debug('Examine param time string: {}'.format(tstr)) # find min/max times tabs = tstr.split('<') @@ -705,8 +703,8 @@ def _sun(self, dt, tstr, timescan): cron = tabs[1].strip() smax = tabs[2].strip() else: - self.logger.error('{}: Wrong syntax: {}. Should be [H:M<](sunrise|sunset)[+|-][offset][ dmax: - self.logger.error("{}: Wrong times: the earliest time should be smaller than the " - "latest time in {}".format(self._name, tstr)) + self.logger.error("Wrong times: the earliest time should be smaller than the " + "latest time in {}".format(tstr)) return if dmin > next_time: next_time = dmin @@ -793,13 +791,14 @@ def _get_dependant(self, item): _uzsuitem = self.itemsApi.return_item(self.get_iattr_value(item.conf, ITEM_TAG[0])) except Exception as err: _uzsuitem = None - self.logger.warning("{}: Item to be queried does not exist. Error: {}".format(self._name, err)) + self.logger.warning("Item to be queried '{}' does not exist. Error: {}".format( + self.get_iattr_value(item.conf, ITEM_TAG[0]), err)) try: _itemvalue = _uzsuitem() except Exception as err: _itemvalue = None - self.logger.warning("{}: Item to be queried does not have a type attribute. Error: {}".format( - self._name, err)) + self.logger.warning("Item to be queried '{}' does not have a type attribute. Error: {}".format( + self.get_iattr_value(item.conf, ITEM_TAG[0]), err)) return _itemvalue def get_items(self): From 4cc7614001434ea860921359d672ef098552bfb2 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 29 Sep 2018 15:36:06 +0200 Subject: [PATCH 283/705] Plugin wetter.com: improved README and provided necessary files in separate folder. Updated code to use plugin.yaml and tools library --- wettercom/README.md | 120 +++++-- wettercom/__init__.py | 73 ++-- wettercom/additional_files/wettercom.py | 43 +++ wettercom/additional_files/wettercom.yaml | 412 ++++++++++++++++++++++ wettercom/plugin.yaml | 26 +- 5 files changed, 602 insertions(+), 72 deletions(-) mode change 100644 => 100755 wettercom/README.md create mode 100755 wettercom/additional_files/wettercom.py create mode 100755 wettercom/additional_files/wettercom.yaml diff --git a/wettercom/README.md b/wettercom/README.md old mode 100644 new mode 100755 index 1b8e55d97..c84ebdb08 --- a/wettercom/README.md +++ b/wettercom/README.md @@ -4,9 +4,6 @@ wetter.com account with project, recommended: 3 days, all data transmitted -### Supported Hardware - -none ## Configuration @@ -25,20 +22,27 @@ in plugin.yaml ### items.yaml -none +Create a yaml file in the items folder with the following content or copy the file from additional_files #### Example ```yaml +%yaml 1.1 +--- wetter: + type: foo vorhersage: + type: foo heute: + type: foo frueh: + type: foo temperatur: + type: foo max: type: num @@ -53,6 +57,7 @@ wetter: type: num wind: + type: foo geschwindigkeit: type: num @@ -67,8 +72,10 @@ wetter: type: num mittag: + type: foo temperatur: + type: foo max: type: num @@ -83,6 +90,7 @@ wetter: type: num wind: + type: foo geschwindigkeit: type: num @@ -97,8 +105,10 @@ wetter: type: num spaet: + type: foo temperatur: + type: foo max: type: num @@ -113,6 +123,7 @@ wetter: type: num wind: + type: foo geschwindigkeit: type: num @@ -127,8 +138,10 @@ wetter: type: num nacht: + type: foo temperatur: + type: foo max: type: num @@ -143,6 +156,7 @@ wetter: type: num wind: + type: foo geschwindigkeit: type: num @@ -157,10 +171,13 @@ wetter: type: num morgen: + type: foo frueh: + type: foo temperatur: + type: foo max: type: num @@ -175,6 +192,7 @@ wetter: type: num wind: + type: foo geschwindigkeit: type: num @@ -189,8 +207,10 @@ wetter: type: num mittag: + type: foo temperatur: + type: foo max: type: num @@ -205,6 +225,7 @@ wetter: type: num wind: + type: foo geschwindigkeit: type: num @@ -219,8 +240,10 @@ wetter: type: num spaet: + type: foo temperatur: + type: foo max: type: num @@ -235,6 +258,7 @@ wetter: type: num wind: + type: foo geschwindigkeit: type: num @@ -249,8 +273,10 @@ wetter: type: num nacht: + type: foo temperatur: + type: foo max: type: num @@ -265,6 +291,7 @@ wetter: type: num wind: + type: foo geschwindigkeit: type: num @@ -279,10 +306,13 @@ wetter: type: num uebermorgen: + type: foo frueh: + type: foo temperatur: + type: foo max: type: num @@ -297,6 +327,7 @@ wetter: type: num wind: + type: foo geschwindigkeit: type: num @@ -311,8 +342,10 @@ wetter: type: num mittag: + type: foo temperatur: + type: foo max: type: num @@ -327,6 +360,7 @@ wetter: type: num wind: + type: foo geschwindigkeit: type: num @@ -341,8 +375,10 @@ wetter: type: num spaet: + type: foo temperatur: + type: foo max: type: num @@ -357,6 +393,7 @@ wetter: type: num wind: + type: foo geschwindigkeit: type: num @@ -371,8 +408,10 @@ wetter: type: num nacht: + type: foo temperatur: + type: foo max: type: num @@ -387,6 +426,7 @@ wetter: type: num wind: + type: foo geschwindigkeit: type: num @@ -404,48 +444,68 @@ wetter: This structure will be filled by the example logic file (see below) ### logic.yaml +Use etc/logic.yaml for cyclic call (900s or so, requests are limited +at 10000 / month) + +```yaml +wettercom: + filename: wettercom.py + visu_acl: rw + crontab: init + cycle: 900 +``` -none +#### Example wettercom.py -#### Example +Create a wettercom.py File in the logics folder or copy the file from additional_files. +Change the city code appropriately! ```python #!/usr/bin/env python # parse weather data -forecast = sh.wettercom.forecast('DE0003318') +forecast = sh.wettercom.forecast('CITYCODE') d0 = sh.now().date() d1 = (sh.now() + dateutil.relativedelta.relativedelta(days=1)).date() d2 = (sh.now() + dateutil.relativedelta.relativedelta(days=2)).date() items = { d0: sh.wetter.vorhersage.heute, d1: sh.wetter.vorhersage.morgen, d2: sh.wetter.vorhersage.uebermorgen} -for date in forecast: - if date.date() in items: - base = items[date.date()] - if date.hour == 6: - frame = base.frueh - elif date.hour == 11: - frame = base.mittag - elif date.hour == 23: - frame = base.nacht - else: # hour == 18 - frame = base.spaet - frame.temperatur.min(forecast[date][0]) - frame.temperatur.max(forecast[date][1]) - frame.text(forecast[date][2]) - frame.niederschlag(forecast[date][3]) - frame.wind.geschwindigkeit(forecast[date][4]) - frame.wind.richtung(forecast[date][5]) - frame.wind.richtung.text(forecast[date][6]) - frame.code(forecast[date][7]) - -logger.info(forecast) +try: + for date in forecast: + if date.date() in items: + base = items[date.date()] + if date.hour == 6: + frame = base.frueh + elif date.hour == 11: + frame = base.mittag + elif date.hour == 23: + frame = base.nacht + else: # hour == 18 + frame = base.spaet + frame.temperatur.min(forecast[date][0]) + frame.temperatur.max(forecast[date][1]) + frame.text(forecast[date][2]) + frame.niederschlag(forecast[date][3]) + frame.wind.geschwindigkeit(forecast[date][4]) + frame.wind.richtung(forecast[date][5]) + frame.wind.richtung.text(forecast[date][6]) + frame.code(forecast[date][7]) +except TypeError as e: + logger.debug("Problems fetching wetter.com forecast. TypeError: {}".format(e)) + +except AttributeError as e: + logger.debug("Problems fetching wetter.com forecast. AttributeError: {}".format(e)) + +except: + e = sys.exc_info()[0] + logger.debug("Problems fetching wetter.com forecast: {}".format(e)) + +logger.debug(forecast) ``` This logic will parse the weather data and put it in the example items.yaml -above. Use etc/logic.yaml for cyclic call (900s or so, requests are limited -at 10000 / month) +above. ## Methods diff --git a/wettercom/__init__.py b/wettercom/__init__.py index f2572ae40..47b5cd5a8 100755 --- a/wettercom/__init__.py +++ b/wettercom/__init__.py @@ -23,28 +23,36 @@ import threading import xml.etree.cElementTree from lib.model.smartplugin import SmartPlugin +from bin.smarthome import VERSION +from lib.tools import Tools class wettercom(SmartPlugin): ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.3.1" + PLUGIN_VERSION = "1.4.0" _server = 'api.wetter.com' - """get city code - - returns one or more city code(s) for use in forecast function - - """ + def __init__(self, smarthome): + if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': + self.logger = logging.getLogger(__name__) + self._project = self.get_parameter_value('project') + self._apikey = self.get_parameter_value('apikey') + self._tools = Tools() + self.lock = threading.Lock() def search(self, location): - + """ + get city code + returns one or more city code(s) for use in forecast function + """ retval = {} + searchURL = 'http://{}/location/index/search/{}/project/{}/cs/{}'.format( + self._server, location, self._project, hashlib.md5(('{}{}{}'.format( + self._project, self._apikey, location)).encode('UTF-8')).hexdigest()) + self.logger.debug('Search URL: {}'.format(searchURL)) - searchURL = 'http://' + self._server + '/location/index/search/' \ - + location + '/project/' + self._project + '/cs/' \ - + hashlib.md5((self._project + self._apikey + location).encode('UTF-8')).hexdigest() + content = self._tools.fetch_url(searchURL) - content = self._sh.tools.fetch_url(searchURL) if content: searchXML = xml.etree.cElementTree.fromstring(content) @@ -53,30 +61,28 @@ def search(self, location): break if numhits > 0: - retval = [ - ccodes.text for ccodes in searchXML.iter('city_code')] + retval = [ccodes.text for ccodes in searchXML.iter('city_code')] return retval - """get forecast data - - returns forecast data for the location city_code (use search to get it) - - forecast data is returned as dictionary for each date/time values are - - max. temperature, weather condition text, wind speed, - condensation probability, min. temperatur, wind direction in degree, - wind direction text, weather condition code - - """ - def forecast(self, city_code): + """ + get forecast data + returns forecast data for the location city_code (use search to get it) + forecast data is returned as dictionary for each date/time values are + + max. temperature, weather condition text, wind speed, + condensation probability, min. temperatur, wind direction in degree, + wind direction text, weather condition code + """ retval = {} - forecastURL = 'http://' + self._server + '/forecast/weather/city/' \ - + city_code + '/project/' + self._project + '/cs/' \ - + hashlib.md5((self._project + self._apikey + city_code).encode('UTF-8')).hexdigest() + forecastURL = 'http://{}/forecast/weather/city/{}/project/{}/cs/{}'.format( + self._server, city_code, self._project, hashlib.md5(('{}{}{}'.format( + self._project, self._apikey, city_code)).encode('UTF-8')).hexdigest()) + self.logger.debug('Forecast URL: {}'.format(forecastURL)) + + content = self._tools.fetch_url(forecastURL) - content = self._sh.tools.fetch_url(forecastURL) if content: forecastXML = xml.etree.cElementTree.fromstring(content) @@ -101,18 +107,13 @@ def forecast(self, city_code): return retval - def __init__(self, smarthome, project, apikey): - self.logger = logging.getLogger(__name__) - self._sh = smarthome - self._project = project - self._apikey = apikey - self.lock = threading.Lock() - def run(self): self.alive = True + self.logger.debug('run method called') def stop(self): self.alive = False + self.logger.debug('stop method called') def parse_item(self, item): return None diff --git a/wettercom/additional_files/wettercom.py b/wettercom/additional_files/wettercom.py new file mode 100755 index 000000000..7a50feeea --- /dev/null +++ b/wettercom/additional_files/wettercom.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# parse weather data +# -*- coding: iso-8859-15 -*- + +forecast = sh.wetter_com.forecast('CITYCODE') + +d0 = sh.now().date() +d1 = (sh.now() + dateutil.relativedelta.relativedelta(days=1)).date() +d2 = (sh.now() + dateutil.relativedelta.relativedelta(days=2)).date() + +items = { d0: sh.wetter.vorhersage.heute, d1: sh.wetter.vorhersage.morgen, d2: sh.wetter.vorhersage.uebermorgen} +try: + for date in forecast: + if date.date() in items: + base = items[date.date()] + if date.hour == 5 or date.hour == 6: + frame = base.frueh + elif date.hour == 11: + frame = base.mittag + elif date.hour == 23: + frame = base.nacht + else: # hour == 18 + frame = base.spaet + frame.temperatur.min(forecast[date][0]) + frame.temperatur.max(forecast[date][1]) + frame.text(forecast[date][2]) + frame.niederschlag(forecast[date][3]) + frame.wind.geschwindigkeit(forecast[date][4]) + frame.wind.richtung(forecast[date][5]) + frame.wind.richtung.text(forecast[date][6]) + frame.code(forecast[date][7]) + +except TypeError as e: + logger.debug("Problems fetching wetter.com forecast. TypeError: {}".format(e)) + +except AttributeError as e: + logger.debug("Problems fetching wetter.com forecast. AttributeError: {}".format(e)) + +except: + e = sys.exc_info()[0] + logger.debug("Problems fetching wetter.com forecast: {}".format(e)) + +logger.debug(forecast) diff --git a/wettercom/additional_files/wettercom.yaml b/wettercom/additional_files/wettercom.yaml new file mode 100755 index 000000000..c486e7e11 --- /dev/null +++ b/wettercom/additional_files/wettercom.yaml @@ -0,0 +1,412 @@ +%yaml 1.1 +--- +wetter: + type: foo + + vorhersage: + type: foo + + heute: + type: foo + + frueh: + type: foo + + temperatur: + type: foo + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + type: foo + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + mittag: + type: foo + + temperatur: + type: foo + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + type: foo + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + spaet: + type: foo + + temperatur: + type: foo + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + type: foo + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + nacht: + type: foo + + temperatur: + type: foo + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + type: foo + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + morgen: + type: foo + + frueh: + type: foo + + temperatur: + type: foo + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + type: foo + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + mittag: + type: foo + + temperatur: + type: foo + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + type: foo + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + spaet: + type: foo + + temperatur: + type: foo + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + type: foo + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + nacht: + type: foo + + temperatur: + type: foo + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + type: foo + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + uebermorgen: + type: foo + + frueh: + type: foo + + temperatur: + type: foo + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + type: foo + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + mittag: + type: foo + + temperatur: + type: foo + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + type: foo + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + spaet: + type: foo + + temperatur: + type: foo + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + type: foo + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + nacht: + type: foo + + temperatur: + type: foo + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + type: foo + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num diff --git a/wettercom/plugin.yaml b/wettercom/plugin.yaml index e6dfe9489..8e288a618 100755 --- a/wettercom/plugin.yaml +++ b/wettercom/plugin.yaml @@ -4,22 +4,36 @@ plugin: type: web # plugin type (gateway, interface, protocol, system, web) description: de: 'Integration von Wetter.COM' - en: '' + en: 'Integrating Wetter.COM' maintainer: '? (Jan N. Klug)' - tester: psilo909 + tester: psilo909, onkelandy keywords: weather # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page # support: https://knx-user-forum.de/forum/supportforen/smarthome-py - version: 1.3.1 # Plugin version - sh_minversion: 1.3 # minimum shNG version to use this plugin + version: 1.4.0 # Plugin version + sh_minversion: 1.4 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance classname: wettercom # class containing the plugin parameters: # Definition of parameters to be configured in etc/plugin.yaml - + project: + type: str + default: '' + mandatory: True + description: + de: 'Projektname für die wetter.com API' + en: 'Project name for the wetter.com API' + + apikey: + type: str + default: '' + mandatory: True + description: + de: 'Key für die wetter.com API' + en: 'key for the wetter.com API' + item_attributes: # Definition of item attributes defined by this plugin - From 8e533968072cc54aa9dddfe08592da502935b304 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 29 Sep 2018 15:40:26 +0200 Subject: [PATCH 284/705] Added version 1.3.1 for compatibility with older sh versions --- wettercom/_pv_1_3_1/README.md | 463 ++++++++++++++++++++++++++++++++ wettercom/_pv_1_3_1/__init__.py | 121 +++++++++ wettercom/_pv_1_3_1/plugin.yaml | 25 ++ 3 files changed, 609 insertions(+) create mode 100755 wettercom/_pv_1_3_1/README.md create mode 100755 wettercom/_pv_1_3_1/__init__.py create mode 100755 wettercom/_pv_1_3_1/plugin.yaml diff --git a/wettercom/_pv_1_3_1/README.md b/wettercom/_pv_1_3_1/README.md new file mode 100755 index 000000000..1b8e55d97 --- /dev/null +++ b/wettercom/_pv_1_3_1/README.md @@ -0,0 +1,463 @@ +# wetter.com + +## Requirements + +wetter.com account with project, recommended: 3 days, all data transmitted + +### Supported Hardware + +none + +## Configuration + +### plugin.yaml + +```yaml +wettercom: + class_name: wettercom + class_path: plugins.wettercom + apikey: + project: +``` + +add your project on wetter.com and paste API-key and project name +in plugin.yaml + +### items.yaml + +none + +#### Example + +```yaml +wetter: + + vorhersage: + + heute: + + frueh: + + temperatur: + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + mittag: + + temperatur: + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + spaet: + + temperatur: + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + nacht: + + temperatur: + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + morgen: + + frueh: + + temperatur: + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + mittag: + + temperatur: + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + spaet: + + temperatur: + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + nacht: + + temperatur: + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + uebermorgen: + + frueh: + + temperatur: + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + mittag: + + temperatur: + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + spaet: + + temperatur: + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num + + nacht: + + temperatur: + + max: + type: num + + min: + type: num + + text: + type: str + + code: + type: num + + wind: + + geschwindigkeit: + type: num + + richtung: + type: num + + text: + type: str + + niederschlag: + type: num +``` + +This structure will be filled by the example logic file (see below) + +### logic.yaml + +none + +#### Example + +```python +#!/usr/bin/env python +# parse weather data + +forecast = sh.wettercom.forecast('DE0003318') + +d0 = sh.now().date() +d1 = (sh.now() + dateutil.relativedelta.relativedelta(days=1)).date() +d2 = (sh.now() + dateutil.relativedelta.relativedelta(days=2)).date() + +items = { d0: sh.wetter.vorhersage.heute, d1: sh.wetter.vorhersage.morgen, d2: sh.wetter.vorhersage.uebermorgen} +for date in forecast: + if date.date() in items: + base = items[date.date()] + if date.hour == 6: + frame = base.frueh + elif date.hour == 11: + frame = base.mittag + elif date.hour == 23: + frame = base.nacht + else: # hour == 18 + frame = base.spaet + frame.temperatur.min(forecast[date][0]) + frame.temperatur.max(forecast[date][1]) + frame.text(forecast[date][2]) + frame.niederschlag(forecast[date][3]) + frame.wind.geschwindigkeit(forecast[date][4]) + frame.wind.richtung(forecast[date][5]) + frame.wind.richtung.text(forecast[date][6]) + frame.code(forecast[date][7]) + +logger.info(forecast) +``` + +This logic will parse the weather data and put it in the example items.yaml +above. Use etc/logic.yaml for cyclic call (900s or so, requests are limited +at 10000 / month) + +## Methods + +### search(location) +Uses wetter.com to search for your city_code. method will return an +empty dictionary if no match is found. If more than one match is found, +the dictionary will contain at most 20 matches, best match first + +### forecast(city_code) +Returns forecast data for your city_code (use search or wetter.com +website to find it). Forecast data is returned as dictionary for each +date/time (usually three days at four times). Values are min. temperature, +max. temperature, weather condition text, condensation probability, +wind speed, wind direction in degree, wind direction text, +weather condition code (can be used to select appropriate icon) diff --git a/wettercom/_pv_1_3_1/__init__.py b/wettercom/_pv_1_3_1/__init__.py new file mode 100755 index 000000000..f2572ae40 --- /dev/null +++ b/wettercom/_pv_1_3_1/__init__.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +# +# Copyright 2013 Jan N. Klug +# +# +# This SmartHomeNG plugin is free software: you can redistribute it and/or +# modify it under the terms of the GNU General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This software is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with it. If not, see . +# + +import hashlib +import logging +import datetime +import threading +import xml.etree.cElementTree +from lib.model.smartplugin import SmartPlugin + + +class wettercom(SmartPlugin): + ALLOW_MULTIINSTANCE = False + PLUGIN_VERSION = "1.3.1" + _server = 'api.wetter.com' + + """get city code + + returns one or more city code(s) for use in forecast function + + """ + + def search(self, location): + + retval = {} + + searchURL = 'http://' + self._server + '/location/index/search/' \ + + location + '/project/' + self._project + '/cs/' \ + + hashlib.md5((self._project + self._apikey + location).encode('UTF-8')).hexdigest() + + content = self._sh.tools.fetch_url(searchURL) + if content: + searchXML = xml.etree.cElementTree.fromstring(content) + + for hits in searchXML.iter('hits'): + numhits = int(hits.text) + break + + if numhits > 0: + retval = [ + ccodes.text for ccodes in searchXML.iter('city_code')] + + return retval + + """get forecast data + + returns forecast data for the location city_code (use search to get it) + + forecast data is returned as dictionary for each date/time values are + + max. temperature, weather condition text, wind speed, + condensation probability, min. temperatur, wind direction in degree, + wind direction text, weather condition code + + """ + + def forecast(self, city_code): + retval = {} + forecastURL = 'http://' + self._server + '/forecast/weather/city/' \ + + city_code + '/project/' + self._project + '/cs/' \ + + hashlib.md5((self._project + self._apikey + city_code).encode('UTF-8')).hexdigest() + + content = self._sh.tools.fetch_url(forecastURL) + if content: + forecastXML = xml.etree.cElementTree.fromstring(content) + + for days in forecastXML.findall('./forecast/date'): + year, month, day = days.attrib['value'].split('-') + for time in days.iter('time'): + hour, minute = time.attrib['value'].split(':') + d = datetime.datetime(int(year), int(month), int(day), + int(hour)) + items = [time.find('tn'), + time.find('tx'), + time.find('w_txt'), + time.find('pc'), + time.find('ws'), + time.find('wd'), + time.find('wd_txt'), + time.find('w')] + + retval[d] = [] + for item in items: + retval[d].append(None if item is None else item.text) + + return retval + + def __init__(self, smarthome, project, apikey): + self.logger = logging.getLogger(__name__) + self._sh = smarthome + self._project = project + self._apikey = apikey + self.lock = threading.Lock() + + def run(self): + self.alive = True + + def stop(self): + self.alive = False + + def parse_item(self, item): + return None + + def parse_logic(self, logic): + return None diff --git a/wettercom/_pv_1_3_1/plugin.yaml b/wettercom/_pv_1_3_1/plugin.yaml new file mode 100755 index 000000000..e6dfe9489 --- /dev/null +++ b/wettercom/_pv_1_3_1/plugin.yaml @@ -0,0 +1,25 @@ +# Metadata for the Smart-Plugin +plugin: + # Global plugin attributes + type: web # plugin type (gateway, interface, protocol, system, web) + description: + de: 'Integration von Wetter.COM' + en: '' + maintainer: '? (Jan N. Klug)' + tester: psilo909 + keywords: weather +# documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page +# support: https://knx-user-forum.de/forum/supportforen/smarthome-py + + version: 1.3.1 # Plugin version + sh_minversion: 1.3 # minimum shNG version to use this plugin +# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) + multi_instance: False # plugin supports multi instance + classname: wettercom # class containing the plugin + +parameters: + # Definition of parameters to be configured in etc/plugin.yaml + +item_attributes: + # Definition of item attributes defined by this plugin + From 6e3c6a662a410ba0ef1e2d938dbb3eb868ebb3d9 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 29 Sep 2018 22:20:00 +0200 Subject: [PATCH 285/705] Fixed issue when only min value for sun event was given --- uzsu/__init__.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index bc7e31774..d7613d784 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -756,7 +756,7 @@ def _sun(self, dt, tstr, timescan): self.logger.error('Wrong syntax: {}. Should be [H:M<](sunrise|sunset)[+|-][offset][ dmax: self.logger.error("Wrong times: the earliest time should be smaller than the " "latest time in {}".format(tstr)) return - if dmin > next_time: - next_time = dmin - if dmax < next_time: - next_time = dmax + try: + next_time = dmin if dmin > next_time else next_time + except Exception: + pass + try: + next_time = dmax if dmax < next_time else next_time + except Exception: + pass return next_time def _get_dependant(self, item): From 896452c1249e7f504df4a40223884e8f6c79c4c1 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 29 Sep 2018 23:36:11 +0200 Subject: [PATCH 286/705] improved rrule handling if rrule empty --- uzsu/__init__.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index d7613d784..853b54b21 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -352,6 +352,16 @@ def update_item(self, item, caller=None, source=None, dest=None): :param dest: if given it represents the dest """ self._items[item] = item() + for entry in self._items[item]['list']: + if entry['rrule'] == '': + try: + _index = self._items[item]['list'].index(entry) + self._items[item]['list'][_index]['rrule'] = 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU' + self.logger.debug("Updated rrule for item: {}".format(item)) + item(self._items[item], 'USZU Plugin', 'create_rrule') + except Exception as err: + self.logger.warning("Error creating rrule: {}".format(err)) + self.logger.debug('Update Item {}, Caller {}, Source {}, Dest {}.'.format( item, caller, source, dest)) # Removing Duplicates From 8fc17626fb2656cc64df04b7d4ade80ac6d3151e Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sun, 30 Sep 2018 01:23:35 +0200 Subject: [PATCH 287/705] fixed rrule update on empty uzsu item --- uzsu/__init__.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 853b54b21..b82a3b7e9 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -352,15 +352,16 @@ def update_item(self, item, caller=None, source=None, dest=None): :param dest: if given it represents the dest """ self._items[item] = item() - for entry in self._items[item]['list']: - if entry['rrule'] == '': - try: - _index = self._items[item]['list'].index(entry) - self._items[item]['list'][_index]['rrule'] = 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU' - self.logger.debug("Updated rrule for item: {}".format(item)) - item(self._items[item], 'USZU Plugin', 'create_rrule') - except Exception as err: - self.logger.warning("Error creating rrule: {}".format(err)) + if self._items[item].get('list'): + for entry in self._items[item]['list']: + if entry['rrule'] == '': + try: + _index = self._items[item]['list'].index(entry) + self._items[item]['list'][_index]['rrule'] = 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU' + self.logger.debug("Updated rrule for item: {}".format(item)) + item(self._items[item], 'USZU Plugin', 'create_rrule') + except Exception as err: + self.logger.warning("Error creating rrule: {}".format(err)) self.logger.debug('Update Item {}, Caller {}, Source {}, Dest {}.'.format( item, caller, source, dest)) From 37346b813b1ae18dd04bbb9941f963377ad489a6 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sun, 30 Sep 2018 01:52:02 +0200 Subject: [PATCH 288/705] error handling if no values received --- wettercom/__init__.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/wettercom/__init__.py b/wettercom/__init__.py index 47b5cd5a8..db5bc1f66 100755 --- a/wettercom/__init__.py +++ b/wettercom/__init__.py @@ -51,7 +51,10 @@ def search(self, location): self._project, self._apikey, location)).encode('UTF-8')).hexdigest()) self.logger.debug('Search URL: {}'.format(searchURL)) - content = self._tools.fetch_url(searchURL) + try: + content = self._tools.fetch_url(searchURL) + except Exception: + content = None if content: searchXML = xml.etree.cElementTree.fromstring(content) @@ -81,7 +84,10 @@ def forecast(self, city_code): self._project, self._apikey, city_code)).encode('UTF-8')).hexdigest()) self.logger.debug('Forecast URL: {}'.format(forecastURL)) - content = self._tools.fetch_url(forecastURL) + try: + content = self._tools.fetch_url(forecastURL) + except Exception: + content = None if content: forecastXML = xml.etree.cElementTree.fromstring(content) From fb959cbefd4ca72862906a3552808e37a50eeb96 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sun, 30 Sep 2018 08:29:17 +0200 Subject: [PATCH 289/705] StateEngine Plugin, aka AutoBlind v1.4.1 --- stateengine/.gitignore | 3 + stateengine/README.md | 36 ++ stateengine/StateEngineAction.py | 524 ++++++++++++++++++++++++ stateengine/StateEngineActions.py | 250 +++++++++++ stateengine/StateEngineCliCommands.py | 77 ++++ stateengine/StateEngineCondition.py | 357 ++++++++++++++++ stateengine/StateEngineConditionSet.py | 118 ++++++ stateengine/StateEngineConditionSets.py | 71 ++++ stateengine/StateEngineCurrent.py | 88 ++++ stateengine/StateEngineDefaults.py | 34 ++ stateengine/StateEngineEval.py | 126 ++++++ stateengine/StateEngineFunctions.py | 187 +++++++++ stateengine/StateEngineItem.py | 485 ++++++++++++++++++++++ stateengine/StateEngineLogger.py | 245 +++++++++++ stateengine/StateEngineState.py | 192 +++++++++ stateengine/StateEngineTools.py | 234 +++++++++++ stateengine/StateEngineValue.py | 219 ++++++++++ stateengine/__init__.py | 136 ++++++ stateengine/autblind_update.sh | 72 ++++ stateengine/plugin.yaml | 62 +++ 20 files changed, 3516 insertions(+) create mode 100755 stateengine/.gitignore create mode 100755 stateengine/README.md create mode 100755 stateengine/StateEngineAction.py create mode 100755 stateengine/StateEngineActions.py create mode 100755 stateengine/StateEngineCliCommands.py create mode 100755 stateengine/StateEngineCondition.py create mode 100755 stateengine/StateEngineConditionSet.py create mode 100755 stateengine/StateEngineConditionSets.py create mode 100755 stateengine/StateEngineCurrent.py create mode 100755 stateengine/StateEngineDefaults.py create mode 100755 stateengine/StateEngineEval.py create mode 100755 stateengine/StateEngineFunctions.py create mode 100755 stateengine/StateEngineItem.py create mode 100755 stateengine/StateEngineLogger.py create mode 100755 stateengine/StateEngineState.py create mode 100755 stateengine/StateEngineTools.py create mode 100755 stateengine/StateEngineValue.py create mode 100755 stateengine/__init__.py create mode 100755 stateengine/autblind_update.sh create mode 100755 stateengine/plugin.yaml diff --git a/stateengine/.gitignore b/stateengine/.gitignore new file mode 100755 index 000000000..36333719f --- /dev/null +++ b/stateengine/.gitignore @@ -0,0 +1,3 @@ +/__pycache__ +.idea/ +*~ \ No newline at end of file diff --git a/stateengine/README.md b/stateengine/README.md new file mode 100755 index 000000000..e78d08fd0 --- /dev/null +++ b/stateengine/README.md @@ -0,0 +1,36 @@ +#StateEngine +Created by i-am-offline + +##Description +Finite state machine plugin for smarthomeNG, previously known as AutoBlind + +## Support +If you require support, please raise an issue at GitHub: + +## Documentation +The manual can be found in the Wiki at GitHub: . + +## Configuration + +To update from autoblind to stateengine use the script "autoblind_update.sh" in the plugin folder! + +### plugin.yaml +See the [manual at GitHub](https://github.com/i-am-offline/smarthome.plugin.autoblind/wiki) + +### items.yaml +See the [manual at GitHub](https://github.com/i-am-offline/smarthome.plugin.autoblind/wiki) + +##Changelog +### v1.4.1 +Added to official develop repository +Renamed to StateEngine +Added script to change autoblind entries to stateengine entries in items, logics and cache +Fix compatibility of logic trigger for SmarthomeNG 1.4+ +Changed state condition evaluation to OrderedDict to keep original order +Added additional option for manual item called "manual_on" to figure out if item WAS trigger by specific KNX GA + +### v1.4.0 +Make compatible with SmarthomeNG 1.4+ (i-am-offline) + +### before v1.4.0 +Constant improvements to infinite state machine (complete plugin development by i-am-offline) diff --git a/stateengine/StateEngineAction.py b/stateengine/StateEngineAction.py new file mode 100755 index 000000000..1057f3a21 --- /dev/null +++ b/stateengine/StateEngineAction.py @@ -0,0 +1,524 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2014- Thomas Ernst offline@gmx.net +######################################################################### +# Finite state machine plugin for SmartHomeNG +# +# This plugin is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This plugin is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this plugin. If not, see . +######################################################################### +from . import StateEngineTools +from . import StateEngineEval +from . import StateEngineValue +from . import StateEngineDefaults +import datetime + + +# Base class from which all action classes are derived +class SeActionBase(StateEngineTools.SeItemChild): + # Cast function for delay + # value: value to cast + @staticmethod + def __cast_delay(value): + if isinstance(value, str): + delay = value.strip() + if delay.endswith('m'): + return int(delay.strip('m')) * 60 + else: + return int(delay) + elif isinstance(value, int): + return value + elif isinstance(value, float): + return int(value) + else: + raise ValueError("Can not cast delay value {0} to int!".format(value)) + + # Initialize the action + # abitem: parent SeItem instance + # name: Name of action + def __init__(self, abitem, name: str): + super().__init__(abitem) + self._name = name + self.__delay = StateEngineValue.SeValue(self._abitem, "delay") + self.__repeat = None + self.__order = StateEngineValue.SeValue(self._abitem, "order", False, "num") + self._scheduler_name = None + + def update_delay(self, value): + self.__delay.set(value) + self.__delay.set_cast(SeActionBase.__cast_delay) + + def update_repeat(self, value): + if self.__repeat is None: + self.__repeat = StateEngineValue.SeValue(self._abitem, "repeat", False, "bool") + self.__repeat.set(value) + + def update_order(self, value): + self.__order.set(value) + + def get_order(self): + return self.__order.get(1) + + # Write action to logger + def write_to_logger(self): + self.__delay.write_to_logger() + if self.__repeat is not None: + self.__repeat.write_to_logger() + self.__order.write_to_logger() + + # Execute action (considering delay, etc) + # is_repeat: Inidicate if this is a repeated action without changing the state + # item_allow_repeat: Is repeating actions generally allowed for the item? + def execute(self, is_repeat: bool, allow_item_repeat: bool): + if not self._can_execute(): + return + + if is_repeat: + if self.__repeat is None: + if allow_item_repeat: + repeat_text = " Repeat allowed by item configuration." + else: + self._log_info("Action '{0}': Repeat denied by item configuration.", self._name) + return + elif self.__repeat.get(): + repeat_text = " Repeat allowed by action configuration." + else: + self._log_info("Action '{0}': Repeat denied by action configuration.", self._name) + return + else: + repeat_text = "" + + plan_next = self._sh.scheduler.return_next(self._scheduler_name) + if plan_next is not None and plan_next > self._sh.now(): + self._log_info("Action '{0}: Removing previous delay timer '{1}'.", self._name, self._scheduler_name) + self._sh.scheduler.remove(self._scheduler_name) + + delay = 0 if self.__delay.is_empty() else self.__delay.get() + actionname = "Action '{0}'".format(self._name) if delay == 0 else "Delay Timer '{0}'".format( + self._scheduler_name) + if delay == 0: + self._execute(actionname, repeat_text) + elif delay is None: + self._log_warning("Action'{0}: Ignored because of errors while determining the delay!", self._name) + elif delay < 0: + self._log_warning("Action'{0}: Ignored because of delay is negative!", self._name) + else: + self._log_info("Action '{0}: Add {1} second timer '{2}' for delayed execution. {3}", self._name, delay, + self._scheduler_name, repeat_text) + next_run = self._sh.now() + datetime.timedelta(seconds=delay) + self._sh.scheduler.add(self._scheduler_name, self._execute, value={'actionname': actionname}, next=next_run) + + # set the action based on a set_(action_name) attribute + # value: Value of the set_(action_name) attribute + def update(self, value): + raise NotImplementedError("Class %s doesn't implement update()" % self.__class__.__name__) + + # Complete action + # item_state: state item to read from + def complete(self, item_state): + raise NotImplementedError("Class %s doesn't implement complete()" % self.__class__.__name__) + + # Check if execution is possible + def _can_execute(self): + return True + + # Really execute the action (needs to be implemented in derived classes) + def _execute(self, actionname: str, repeat_text: str = ""): + raise NotImplementedError("Class %s doesn't implement _execute()" % self.__class__.__name__) + + +# Class representing a single "se_set" action +class SeActionSetItem(SeActionBase): + # Initialize the action + # abitem: parent SeItem instance + # name: Name of action + def __init__(self, abitem, name: str): + super().__init__(abitem, name) + self.__item = None + self.__value = StateEngineValue.SeValue(self._abitem, "value") + self.__mindelta = StateEngineValue.SeValue(self._abitem, "mindelta") + self.__caller = StateEngineDefaults.plugin_identification + + # set the action based on a set_(action_name) attribute + # value: Value of the set_(action_name) attribute + def update(self, value): + self.__value.set(value) + + # Complete action + # item_state: state item to read from + def complete(self, item_state): + # missing item in action: Try to find it. + if self.__item is None: + item = StateEngineTools.find_attribute(self._sh, item_state, "se_item_" + self._name) + if item is not None: + self.__item = self._abitem.return_item(item) + + if self.__mindelta.is_empty(): + mindelta = StateEngineTools.find_attribute(self._sh, item_state, "se_mindelta_" + self._name) + if mindelta is not None: + self.__mindelta.set(mindelta) + + if self.__item is not None: + self.__value.set_cast(self.__item.cast) + self.__mindelta.set_cast(self.__item.cast) + self._scheduler_name = self.__item.id() + "-SeItemDelayTimer" + if self._abitem.id == self.__item.id(): + self.__caller += '_self' + + # Write action to logger + def write_to_logger(self): + SeActionBase.write_to_logger(self) + if self.__item is not None: + self._log_debug("item: {0}", self.__item.id()) + self.__mindelta.write_to_logger() + self.__value.write_to_logger() + + # Check if execution is possible + def _can_execute(self): + if self.__item is None: + self._log_info("Action '{0}': No item defined. Ignoring.", self._name) + return False + + if self.__value.is_empty(): + self._log_info("Action '{0}': No value defined. Ignoring.", self._name) + return False + + return True + + # Really execute the action (needs to be implemented in derived classes) + def _execute(self, actionname: str, repeat_text: str = ""): + value = self.__value.get() + if value is None: + return + + if not self.__mindelta.is_empty(): + mindelta = self.__mindelta.get() + # noinspection PyCallingNonCallable + delta = float(abs(self.__item() - value)) + if delta < mindelta: + text = "{0}: Not setting '{1}' to '{2}' because delta '{3:.2}' is lower than mindelta '{4}'" + self._log_debug(text, actionname, self.__item.id(), value, delta, mindelta) + return + + self._log_debug("{0}: Set '{1}' to '{2}'.{3}", actionname, self.__item.id(), value, repeat_text) + # noinspection PyCallingNonCallable + self.__item(value, caller=self.__caller) + + +# Class representing a single "se_setbyattr" action +class SeActionSetByattr(SeActionBase): + # Initialize the action + # abitem: parent SeItem instance + # name: Name of action + def __init__(self, abitem, name: str): + super().__init__(abitem, name) + self.__byattr = None + + # set the action based on a set_(action_name) attribute + # value: Value of the set_(action_name) attribute + def update(self, value): + self.__byattr = value + + # Complete action + # item_state: state item to read from + def complete(self, item_state): + self._scheduler_name = self.__byattr + "-SeByAttrDelayTimer" + + # Write action to logger + def write_to_logger(self): + SeActionBase.write_to_logger(self) + if self.__byattr is not None: + self._log_debug("set by attriute: {0}", self.__byattr) + + # Really execute the action + def _execute(self, actionname: str, repeat_text: str = ""): + self._log_info("{0}: Setting values by attribute '{1}'.{2}", actionname, self.__byattr, repeat_text) + for item in self._sh.find_items(self.__byattr): + self._log_info("\t{0} = {1}", item.id(), item.conf[self.__byattr]) + item(item.conf[self.__byattr], caller=StateEngineDefaults.plugin_identification) + + +# Class representing a single "se_trigger" action +class SeActionTrigger(SeActionBase): + # Initialize the action + # abitem: parent SeItem instance + # name: Name of action + def __init__(self, abitem, name: str): + super().__init__(abitem, name) + self.__logic = None + self.__value = None + + # set the action based on a set_(action_name) attribute + # value: Value of the set_(action_name) attribute + def update(self, value): + logic, value = StateEngineTools.partition_strip(value, ":") + self.__logic = logic + self.__value = None if value == "" else value + + # Complete action + # item_state: state item to read from + def complete(self, item_state): + self._scheduler_name = self.__logic + "-SeLogicDelayTimer" + + # Write action to logger + def write_to_logger(self): + SeActionBase.write_to_logger(self) + if self.__logic is not None: + self._log_debug("trigger logic: {0}", self.__logic) + if self.__value is not None: + self._log_debug("value: {0}", self.__value) + + # Really execute the action + def _execute(self, actionname: str, repeat_text: str = ""): + # Trigger logic + self._log_info("{0}: Triggering logic '{1}' using value '{2}'.{3}", actionname, self.__logic, self.__value, repeat_text) + by = StateEngineDefaults.plugin_identification + add_logics = 'logics.{}'.format(self.__logic) if not self.__logic.startswith('logics.') else self.__logic + self._sh.trigger(add_logics, by=by, source=self._name, value=self.__value) + + +# Class representing a single "se_run" action +class SeActionRun(SeActionBase): + # Initialize the action + # abitem: parent SeItem instance + # name: Name of action + def __init__(self, abitem, name: str): + super().__init__(abitem, name) + self.__eval = None + + # set the action based on a set_(action_name) attribute + # value: Value of the set_(action_name) attribute + def update(self, value): + func, value = StateEngineTools.partition_strip(value, ":") + if value == "": + value = func + func = "eval" + + if func == "eval": + self.__eval = value + + # Complete action + # item_state: state item to read from + def complete(self, item_state): + self._scheduler_name = StateEngineTools.get_eval_name(self.__eval) + "-SeRunDelayTimer" + + # Write action to logger + def write_to_logger(self): + SeActionBase.write_to_logger(self) + if self.__eval is not None: + self._log_debug("eval: {0}", StateEngineTools.get_eval_name(self.__eval)) + + # Really execute the action + def _execute(self, actionname: str, repeat_text: str = ""): + if isinstance(self.__eval, str): + # noinspection PyUnusedLocal + sh = self._sh + if "stateengine_eval" in self.__eval: + # noinspection PyUnusedLocal + stateengine_eval = StateEngineEval.SeEval(self._abitem) + try: + eval(self.__eval) + except Exception as ex: + text = "{0}: Problem evaluating '{1}': {2}." + self._log_error(text.format(actionname, StateEngineTools.get_eval_name(self.__eval), str(ex))) + else: + try: + # noinspection PyCallingNonCallable + self.__eval() + except Exception as ex: + text = "{0}: Problem calling '{0}': {1}." + self._log_error(text.format(actionname, StateEngineTools.get_eval_name(self.__eval), str(ex))) + + +# Class representing a single "se_force" action +class SeActionForceItem(SeActionBase): + # Initialize the action + # abitem: parent SeItem instance + # name: Name of action + def __init__(self, abitem, name: str): + super().__init__(abitem, name) + self.__item = None + self.__value = StateEngineValue.SeValue(self._abitem, "value") + self.__mindelta = StateEngineValue.SeValue(self._abitem, "mindelta") + + # set the action based on a set_(action_name) attribute + # value: Value of the set_(action_name) attribute + def update(self, value): + self.__value.set(value) + + # Complete action + # item_state: state item to read from + def complete(self, item_state): + # missing item in action: Try to find it. + if self.__item is None: + item = StateEngineTools.find_attribute(self._sh, item_state, "se_item_" + self._name) + if item is not None: + self.__item = self._abitem.return_item(item) + + if self.__mindelta.is_empty(): + mindelta = StateEngineTools.find_attribute(self._sh, item_state, "se_mindelta_" + self._name) + if mindelta is not None: + self.__mindelta.set(mindelta) + + if self.__item is not None: + self.__value.set_cast(self.__item.cast) + self.__mindelta.set_cast(self.__item.cast) + self._scheduler_name = self.__item.id() + "-SeItemDelayTimer" + + # Write action to logger + def write_to_logger(self): + SeActionBase.write_to_logger(self) + if self.__item is not None: + self._log_debug("item: {0}", self.__item.id()) + self.__mindelta.write_to_logger() + self.__value.write_to_logger() + self._log_debug("force update: yes") + + # Check if execution is possible + def _can_execute(self): + if self.__item is None: + self._log_info("Action '{0}': No item defined. Ignoring.", self._name) + return False + + if self.__value.is_empty(): + self._log_info("Action '{0}': No value defined. Ignoring.", self._name) + return False + + return True + + # Really execute the action (needs to be implemented in derived classes) + # noinspection PyProtectedMember + def _execute(self, actionname: str, repeat_text: str = ""): + value = self.__value.get() + if value is None: + return + + if not self.__mindelta.is_empty(): + mindelta = self.__mindelta.get() + # noinspection PyCallingNonCallable + delta = float(abs(self.__item() - value)) + if delta < mindelta: + text = "{0}: Not setting '{1}' to '{2}' because delta '{3:.2}' is lower than mindelta '{4}'" + self._log_debug(text, actionname, self.__item.id(), value, delta, mindelta) + return + + # Set to different value first ("force") + if self.__item() == value: + if self.__item._type == 'bool': + self._log_debug("{0}: Set '{1}' to '{2}' (Force)", actionname, self.__item.id(), not value) + self.__item(not value, caller=StateEngineDefaults.plugin_identification) + elif self.__item._type == 'str': + if value != '': + self._log_debug("{0}: Set '{1}' to '{2}' (Force)", actionname, self.__item.id(), '') + self.__item('', caller=StateEngineDefaults.plugin_identification) + else: + self._log_debug("{0}: Set '{1}' to '{2}' (Force)", actionname, self.__item.id(), '-') + self.__item('-', caller=StateEngineDefaults.plugin_identification) + elif self.__item._type == 'num': + if value != 0: + self._log_debug("{0}: Set '{1}' to '{2}' (Force)", actionname, self.__item.id(), 0) + self.__item(0, caller=StateEngineDefaults.plugin_identification) + else: + self._log_debug("{0}: Set '{1}' to '{2}' (Force)", actionname, self.__item.id(), 1) + self.__item(1, caller=StateEngineDefaults.plugin_identification) + else: + self._log_warning("{0}: Force not implemented for item type '{1}'", actionname, self.__item._type) + else: + self._log_debug("{0}: New value differs from old value, no force required.", actionname) + + self._log_debug("{0}: Set '{1}' to '{2}'.{3}", actionname, self.__item.id(), value, repeat_text) + # noinspection PyCallingNonCallable + self.__item(value, caller=StateEngineDefaults.plugin_identification) + + +# Class representing a single "se_special" action +class SeActionSpecial(SeActionBase): + # Initialize the action + # abitem: parent SeItem instance + # name: Name of action + def __init__(self, abitem, name: str): + super().__init__(abitem, name) + self.__special = None + self.__value = None + + # set the action based on a set_(action_name) attribute + # value: Value of the set_(action_name) attribute + def update(self, value): + special, value = StateEngineTools.partition_strip(value, ":") + if special == "suspend": + self.__value = self.suspend_get_value(value) + else: + raise ValueError("Action {0}: Unknown special value '{1}'!".format(self._name, special)) + self.__special = special + + # Complete action + # item_state: state item to read from + def complete(self, item_state): + self._scheduler_name = self.__special + "-SeSpecialDelayTimer" + + # Write action to logger + def write_to_logger(self): + SeActionBase.write_to_logger(self) + self._log_debug("Special Action: {0}", self.__special) + if self.__value is not None: + self._log_debug("value: {0}", self.__value) + + # Really execute the action + def _execute(self, actionname: str, repeat_text: str = ""): + # Trigger logic + self._log_info("{0}: Executing special action '{1}' using value '{2}'.{3}", actionname, self.__special, self.__value, repeat_text) + self._log_increase_indent() + if self.__special == "suspend": + self.suspend_execute() + else: + self._log_decrease_indent() + raise ValueError("{0}: Unknown special value '{1}'!".format(actionname, self.__special)) + self._log_decrease_indent() + + def suspend_get_value(self, value): + if value is None: + raise ValueError("Action {0}: Secial action 'suspend' requires arguments!") + + suspend, manual = StateEngineTools.partition_strip(value, ",") + if suspend is None or manual is None: + raise ValueError("Action {0}: Secial action 'suspend' requires two arguments (separated by a comma)!") + + suspend_item = self._abitem.return_item(suspend) + if suspend_item is None: + raise ValueError("Action {0}: Suspend item '{1}' not found!", self._name, suspend) + + manual_item = self._abitem.return_item(manual) + if manual_item is None: + raise ValueError("Action {0}: Manual item '{1}' not found!", self._name, manual) + + return [suspend_item, manual_item.id()] + + def suspend_execute(self): + suspend_item = self.__value[0] + if self._abitem.get_update_trigger_source() == self.__value[1]: + # triggered by manual-item: Update suspend item + if suspend_item(): + self._log_debug("Set '{0}' to '{1}' (Force)", suspend_item.id(), False) + suspend_item(False) + self._log_debug("Set '{0}' to '{1}'.", suspend_item.id(), True) + suspend_item(True) + else: + self._log_debug("Leaving '{0}' untouched.", suspend_item.id()) + + # determine remaining suspend time and write to variable item.suspend_remaining + suspend_time = self._abitem.get_variable("item.suspend_time") + suspend_over = suspend_item.age() + suspend_remaining = int(suspend_time - suspend_over + 0.5) # adding 0.5 causes round up ... + self._abitem.set_variable("item.suspend_remaining", suspend_remaining) + self._log_debug("Updated variable 'item.suspend_remaining' to {0}".format(suspend_remaining)) diff --git a/stateengine/StateEngineActions.py b/stateengine/StateEngineActions.py new file mode 100755 index 000000000..fd9679d72 --- /dev/null +++ b/stateengine/StateEngineActions.py @@ -0,0 +1,250 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2014- Thomas Ernst offline@gmx.net +######################################################################### +# Finite state machine plugin for SmartHomeNG +# +# This plugin is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This plugin is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this plugin. If not, see . +######################################################################### +from . import StateEngineAction +from . import StateEngineTools + + +# Class representing a list of actions +class SeActions(StateEngineTools.SeItemChild): + # Initialize the set of actions + # abitem: parent SeItem instance + def __init__(self, abitem): + super().__init__(abitem) + self.__actions = {} + self.__unassigned_delays = {} + self.__unassigned_repeats = {} + self.__unassigned_orders = {} + + # Return number of actions in list + def count(self): + return len(self.__actions) + + # update action + # attribute: name of attribute that defines action + # value: value of the attribute + def update(self, attribute, value): + # Split attribute in function and action name + func, name = StateEngineTools.partition_strip(attribute, "_") + try: + if func == "se_delay": + # set delay + if name not in self.__actions: + # If we do not have the action yet (delay-attribute before action-attribute), ... + self.__unassigned_delays[name] = value + else: + self.__actions[name].update_delay(value) + return + elif func == "se_repeat": + # set repeat + if name not in self.__actions: + # If we do not have the action yet (repeat-attribute before action-attribute), ... + self.__unassigned_repeats[name] = value + else: + self.__actions[name].update_repeat(value) + return + elif func == "se_order": + # set order + if name not in self.__actions: + # If we do not have the action yet (order-attribute before action-attribute), ... + self.__unassigned_orders[name] = value + else: + self.__actions[name].update_order(value) + return + elif func == "se_action": # and name not in self.__actions: + self.__handle_combined_action_attribute(name, value) + elif self.__ensure_action_exists(func, name): + # update action + self.__actions[name].update(value) + except ValueError as ex: + if name in self.__actions: + del self.__actions[name] + self._log_warning("Ignoring action {0} because: {1} (2)".format(attribute, str(ex))) + #raise ValueError("Action {0}: {1}".format(attribute, str(ex))) + + # ensure that action exists and create if missing + # func: action function + # name: action name + def __ensure_action_exists(self, func, name): + # Check if action exists + if name in self.__actions: + return True + + # Create action depending on function + if func == "se_set": + action = StateEngineAction.SeActionSetItem(self._abitem, name) + elif func == "se_force": + action = StateEngineAction.SeActionForceItem(self._abitem, name) + elif func == "se_byattr": + action = StateEngineAction.SeActionSetByattr(self._abitem, name) + elif func == "se_trigger": + action = StateEngineAction.SeActionTrigger(self._abitem, name) + elif func == "se_run": + action = StateEngineAction.SeActionRun(self._abitem, name) + elif func == "se_special": + action = StateEngineAction.SeActionSpecial(self._abitem, name) + else: + return False + + if name in self.__unassigned_delays: + action.update_delay(self.__unassigned_delays[name]) + del self.__unassigned_delays[name] + + if name in self.__unassigned_repeats: + action.update_repeat(self.__unassigned_repeats[name]) + del self.__unassigned_repeats[name] + + if name in self.__unassigned_orders: + action.update_order(self.__unassigned_orders[name]) + del self.__unassigned_orders[name] + + self.__actions[name] = action + return True + + def __handle_combined_action_attribute(self, name, value_list): + # value_list needs to be string or list + if isinstance(value_list, str): + value_list = [value_list, ] + elif not isinstance(value_list, list): + raise ValueError("Attribute 'se_action_{0}': Value must be a string or a list!".format(name)) + + # parse parameters + parameter = {'function': None, 'force': None, 'repeat': None, 'delay': 0, 'order': None} + for entry in value_list: + key, val = StateEngineTools.partition_strip(entry, ":") + if key == "function": + parameter[key] = StateEngineTools.cast_str(val) + elif key == "force": + parameter[key] = StateEngineTools.cast_bool(val) + else: + parameter[key] = val + parameter['action'] = name + + # function given and valid? + if parameter['function'] is None: + raise ValueError("Attribute 'se_action_{0}: Parameter 'function' must be set!".format(name)) + if parameter['function'] not in ('set', 'force', 'run', 'byattr', 'trigger', 'special'): + raise ValueError("Attribute 'se_action_{0}: Invalid value '{1}' for parameter 'function'!".format(name, parameter['function'])) + + # handle force + if parameter['force'] is not None: + # Parameter force is supported only for type "set" and type "force" + if parameter['function'] != "set" and parameter['function'] != "force": + self._log_warning("Attribute 'se_action_{0}': Parameter 'force' not supported for function '{1}'".format(name, parameter['function'])) + elif parameter['force'] and parameter['function'] == "set": + # Convert type "set" with force=True to type "force" + self._log_info("Attribute 'se_action_{0}': Parameter 'function' changed from 'set' to 'force', because parameter 'force' is 'True'!".format(name)) + parameter['function'] = "force" + elif not parameter['force'] and parameter['function'] == "force": + # Convert type "force" with force=False to type "set" + self._log_info("Attribute 'se_action_{0}': Parameter 'function' changed from 'force' to 'set', because parameter 'force' is 'False'!".format(name)) + parameter['function'] = "set" + + # create action based on function + exists = False + try: + if parameter['function'] == "set": + if self.__ensure_action_exists("se_set", name): + self.__raise_missing_parameter_error(parameter, 'to') + self.__actions[name].update(parameter['to']) + exists = True + elif parameter['function'] == "force": + if self.__ensure_action_exists("se_force", name): + self.__raise_missing_parameter_error(parameter, 'to') + self.__actions[name].update(parameter['to']) + exists = True + elif parameter['function'] == "run": + if self.__ensure_action_exists("se_run", name): + self.__raise_missing_parameter_error(parameter, 'eval') + self.__actions[name].update(parameter['eval']) + exists = True + elif parameter['function'] == "byattr": + if self.__ensure_action_exists("se_byattr", name): + self.__raise_missing_parameter_error(parameter, 'attribute') + self.__actions[name].update(parameter['attribute']) + exists = True + elif parameter['function'] == "trigger": + if self.__ensure_action_exists("se_trigger", name): + self.__raise_missing_parameter_error(parameter, 'logic') + if 'value' in parameter and parameter['value'] is not None: + self.__actions[name].update(parameter['logic'] + ':' + parameter['value']) + else: + self.__actions[name].update(parameter['logic']) + exists = True + elif parameter['function'] == "special": + if self.__ensure_action_exists("se_special", name): + self.__raise_missing_parameter_error(parameter, 'value') + self.__actions[name].update(parameter['value']) + exists = True + except ValueError as ex: + exists = False + if name in self.__actions: + del self.__actions[name] + self._log_warning("Ignoring action {0} because: {1}".format(name, str(ex))) + + + # add additional parameters + if exists: + if parameter['repeat'] is not None: + self.__actions[name].update_repeat(parameter['repeat']) + if parameter['delay'] != 0: + self.__actions[name].update_delay(parameter['delay']) + if parameter['order'] is not None: + self.__actions[name].update_order(parameter['order']) + + # noinspection PyMethodMayBeStatic + def __raise_missing_parameter_error(self, parameter, param_name): + if param_name not in parameter or parameter[param_name] is None: + raise ValueError("Attribute 'se_action_{0}: Parameter '{1}' must be set for function '{2}'!".format(parameter['action'], param_name, parameter['function'])) + + # Check the actions optimize and complete them + # item_state: item to read from + def complete(self, item_state): + for name in self.__actions: + try: + self.__actions[name].complete(item_state) + except ValueError as ex: + raise ValueError("State '{0}', Action '{1}': {2}".format(item_state.id(), name, str(ex))) + + # Execute all actions + # is_repeat: Inidicate if this is a repeated action without changing the state + # item_allow_repeat: Is repeating actions generally allowed for the item? + # additional_actions: SeActions-Instance containing actions which should be executed, too + def execute(self, is_repeat: bool, allow_item_repeat: bool, additional_actions=None): + actions = [] + for name in self.__actions: + actions.append((self.__actions[name].get_order(), self.__actions[name])) + if additional_actions is not None: + for name in additional_actions.__actions: + actions.append((additional_actions.__actions[name].get_order(), additional_actions.__actions[name])) + for order, action in sorted(actions, key=lambda x: x[0]): + action.execute(is_repeat, allow_item_repeat) + + # log all actions + def write_to_logger(self): + actions = [] + for name in self.__actions: + actions.append((self.__actions[name].get_order(), self.__actions[name])) + for order, action in sorted(actions, key=lambda x: x[0]): + # noinspection PyProtectedMember + self._log_info("Action '{0}':", action._name) + self._log_increase_indent() + action.write_to_logger() + self._log_decrease_indent() diff --git a/stateengine/StateEngineCliCommands.py b/stateengine/StateEngineCliCommands.py new file mode 100755 index 000000000..0ad4327d4 --- /dev/null +++ b/stateengine/StateEngineCliCommands.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2014- Thomas Ernst offline@gmx.net +######################################################################### +# Finite state machine plugin for SmartHomeNG +# +# This plugin is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This plugin is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this plugin. If not, see . +######################################################################### +import logging +# noinspection PyUnresolvedReferences +from lib.model.smartplugin import SmartPlugin +from lib.plugin import Plugins + +class SeCliCommands: + def __init__(self, smarthome, items): + self.__items = items + self._sh = smarthome + self.logger = logging.getLogger(__name__) + + # Add additional cli commands if cli is active (and functionality to add own cli commands is available) + try: + cli = self._get_cli_plugin() + if cli is None: + self.logger.info("StateEngine: Additional CLI commands not registered because CLI plugin is not active") + elif not isinstance(cli, SmartPlugin): + self.logger.info("StateEngine: Additional CLI commands not registered because CLI plugin is to old") + else: + cli.commands.add_command("se_list", self.cli_list, "StateEngine", "se_list: list AutoState items") + cli.commands.add_command("se_detail", self.cli_detail, "StateEngine", "se_detail [asItem]: show details on AutoState item [asItem]") + self.logger.info("StateEngine: Two additional CLI commands registered") + except AttributeError as err: + self.logger.error("StateEngine: Additional CLI commands not registered because error occured.") + self.logger.exception(err) + + # CLI command se_list + # noinspection PyUnusedLocal + def cli_list(self, handler, parameter, source): + handler.push("Items for AutoState Plugin\n") + handler.push("==========================\n") + for name in sorted(self.__items): + self.__items[name].cli_list(handler) + + # CLI command se_detail + # noinspection PyUnusedLocal + def cli_detail(self, handler, parameter, source): + item = self.__cli_getitem(handler, parameter) + if item is not None: + item.cli_detail(handler) + + # get item from parameter + def __cli_getitem(self, handler, parameter): + if parameter not in self.__items: + handler.push("no AutoState item \"{0}\" found.\n".format(parameter)) + return None + return self.__items[parameter] + + def _get_cli_plugin(self): + # noinspection PyBroadException + try: + for plugin in self._sh.return_plugins(): + if plugin.__module__ == 'plugins.cli': + return plugin + return None + except Exception: + return None diff --git a/stateengine/StateEngineCondition.py b/stateengine/StateEngineCondition.py new file mode 100755 index 000000000..c8acf5d2c --- /dev/null +++ b/stateengine/StateEngineCondition.py @@ -0,0 +1,357 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2014- Thomas Ernst offline@gmx.net +######################################################################### +# Finite state machine plugin for SmartHomeNG +# +# This plugin is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This plugin is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this plugin. If not, see . +######################################################################### +from . import StateEngineTools +from . import StateEngineCurrent +from . import StateEngineValue +from . import StateEngineEval + + +# Class representing a single condition +class SeCondition(StateEngineTools.SeItemChild): + # Name of condition + @property + def name(self): + return self.__name + + # Initialize the condition + # abitem: parent SeItem instance + # name: Name of condition + def __init__(self, abitem, name: str): + super().__init__(abitem) + self.__name = name + self.__item = None + self.__eval = None + self.__value = StateEngineValue.SeValue(self._abitem, "value", True) + self.__min = StateEngineValue.SeValue(self._abitem, "min") + self.__max = StateEngineValue.SeValue(self._abitem, "max") + self.__negate = False + self.__agemin = StateEngineValue.SeValue(self._abitem, "agemin") + self.__agemax = StateEngineValue.SeValue(self._abitem, "agemax") + self.__agenegate = None + self.__error = None + + # set a certain function to a given value + # func: Function to set ('item', 'eval', 'value', 'min', 'max', 'negate', 'agemin', 'agemax' or 'agenegate' + # value: Value for function + def set(self, func, value): + if func == "se_item": + self.__item = self._abitem.return_item(value) + elif func == "se_eval": + self.__eval = value + if func == "se_value": + self.__value.set(value, self.__name) + elif func == "se_min": + self.__min.set(value, self.__name) + elif func == "se_max": + self.__max.set(value, self.__name) + elif func == "se_agemin": + self.__agemin.set(value, self.__name) + elif func == "se_agemax": + self.__agemax.set(value, self.__name) + elif func == "se_negate": + self.__negate = value + elif func == "se_agenegate": + self.__agenegate = value + + # Complete condition (do some checks, cast value, min and max based on item or eval data types) + # item_state: item to read from + # abitem_object: Related SeItem instance for later determination of current age and current delay + def complete(self, item_state): + # check if it is possible to complete this condition + if self.__min.is_empty() and self.__max.is_empty() and self.__value.is_empty() \ + and self.__agemin.is_empty() and self.__agemax.is_empty(): + return False + + # set 'eval' for some known conditions if item and eval are not set, yet + if self.__item is None and self.__eval is None: + if self.__name == "weekday": + self.__eval = StateEngineCurrent.values.get_weekday + elif self.__name == "sun_azimut": + self.__eval = StateEngineCurrent.values.get_sun_azimut + elif self.__name == "sun_altitude": + self.__eval = StateEngineCurrent.values.get_sun_altitude + elif self.__name == "age": + self.__eval = self._abitem.get_age + elif self.__name == "time": + self.__eval = StateEngineCurrent.values.get_time + elif self.__name == "random": + self.__eval = StateEngineCurrent.values.get_random + elif self.__name == "month": + self.__eval = StateEngineCurrent.values.get_month + elif self.__name == "laststate": + self.__eval = self._abitem.get_laststate_id + elif self.__name == "trigger_item": + self.__eval = self._abitem.get_update_trigger_item + elif self.__name == "trigger_caller": + self.__eval = self._abitem.get_update_trigger_caller + elif self.__name == "trigger_source": + self.__eval = self._abitem.get_update_trigger_source + elif self.__name == "trigger_dest": + self.__eval = self._abitem.get_update_trigger_dest + elif self.__name == "original_item": + self.__eval = self._abitem.get_update_original_item + elif self.__name == "original_caller": + self.__eval = self._abitem.get_update_original_caller + elif self.__name == "original_source": + self.__eval = self._abitem.get_update_original_source + + # missing item in condition: Try to find it + if self.__item is None: + result = StateEngineTools.find_attribute(self._sh, item_state, "se_item_" + self.__name) + if result is not None: + self.__item = self._abitem.return_item(result) + + # missing eval in condition: Try to find it + if self.__eval is None: + result = StateEngineTools.find_attribute(self._sh, item_state, "se_eval_" + self.__name) + if result is not None: + self.__eval = result + + # no we should have either 'item' or 'eval' set. If not, raise ValueError + if self.__item is None and self.__eval is None: + raise ValueError("Condition {}: Neither 'item' nor 'eval' given!".format(self.__name)) + + # cast stuff + try: + if self.__item is not None: + self.__cast_all(self.__item.cast) + elif self.__name in ("weekday", "sun_azimut", "sun_altitude", "age", "delay", "random", "month"): + self.__cast_all(StateEngineTools.cast_num) + elif self.__name in ( + "laststate", "trigger_item", "trigger_caller", "trigger_source", "trigger_dest", "original_item", + "original_caller", "original_source"): + self.__cast_all(StateEngineTools.cast_str) + elif self.__name == "time": + self.__cast_all(StateEngineTools.cast_time) + except Exception as ex: + raise ValueError("Condition {0}: Error when casting: {1}".format(self.__name, str(ex))) + + # 'min' must not be greater than 'max' + if self.__min.get_type() == "value" and self.__max.get_type() == "value": + if self.__min.get() > self.__max.get(): + raise ValueError("Condition {}: 'min' must not be greater than 'max'!".format(self.__name)) + + # 'agemin' and 'agemax' can only be used for items, not for eval + if self.__item is None and not (self.__agemin.is_empty() and self.__agemax.is_empty()): + raise ValueError("Condition {}: 'agemin'/'agemax' can not be used for eval!".format(self.__name)) + + return True + + # Check if condition is matching + def check(self): + # Ignore if no current value can be determined (should not happen as we check this earlier, but to be sure ...) + if self.__item is None and self.__eval is None: + self._log_info("condition '{0}': No item or eval found! Considering condition as matching!", self.__name) + return True + + if not self.__check_value(): + return False + if not self.__check_age(): + return False + return True + + # Write condition to logger + def write_to_logger(self): + if self.__error is not None: + self._log_debug("error: {0}", self.__error) + if self.__item is not None: + self._log_debug("item: {0}", self.__item.id()) + if self.__eval is not None: + self._log_debug("eval: {0}", StateEngineTools.get_eval_name(self.__eval)) + self.__value.write_to_logger() + self.__min.write_to_logger() + self.__max.write_to_logger() + if self.__negate is not None: + self._log_debug("negate: {0}", self.__negate) + self.__agemin.write_to_logger() + self.__agemax.write_to_logger() + if self.__agenegate is not None: + self._log_debug("age negate: {0}", self.__agenegate) + + # Cast 'value', 'min' and 'max' using given cast function + # cast_func: cast function to use + def __cast_all(self, cast_func): + self.__value.set_cast(cast_func) + self.__min.set_cast(cast_func) + self.__max.set_cast(cast_func) + if self.__negate is not None: + self.__negate = StateEngineTools.cast_bool(self.__negate) + self.__agemin.set_cast(StateEngineTools.cast_num) + self.__agemax.set_cast(StateEngineTools.cast_num) + if self.__agenegate is not None: + self.__agenegate = StateEngineTools.cast_bool(self.__agenegate) + + # Check if value conditions match + def __check_value(self): + current = self.__get_current() + try: + if not self.__value.is_empty(): + # 'value' is given. We ignore 'min' and 'max' and check only for the given value + value = self.__value.get() + + if type(value) == list: + text = "Condition '{0}': value={1} negate={2} current={3}" + self._log_debug(text, self.__name, value, self.__negate, current) + self._log_increase_indent() + + for element in value: + if type(element) != type(current): + element = str(element) + current = str(current) + if self.__negate: + if current == element: + self._log_debug("{0} found but negated -> not matching", element) + return False + else: + if current == element: + self._log_debug("{0} found -> matching", element) + return True + + if self.__negate: + self._log_debug("{0} not in list -> matching", current) + return True + else: + self._log_debug("{0} not in list -> not matching", current) + return False + + else: + # If current and value have different types, convert both to string + if type(value) != type(current): + value = str(value) + current = str(current) + text = "Condition '{0}': value={1} negate={2} current={3}" + self._log_debug(text, self.__name, value, self.__negate, current) + self._log_increase_indent() + + if self.__negate: + if current != value: + self._log_debug("not OK but negated -> matching") + return True + else: + if current == value: + self._log_debug("OK -> matching") + return True + + self._log_debug("not OK -> not matching") + return False + + else: + + min_value = self.__min.get() + max_value = self.__max.get() + + # 'value' is not given. We check 'min' and 'max' (if given) + text = "Condition '{0}': min={1} max={2} negate={3} current={4}" + self._log_debug(text, self.__name, min_value, max_value, self.__negate, current) + self._log_increase_indent() + + if min_value is None and max_value is None: + self._log_debug("no limit given -> matching") + return True + + if not self.__negate: + if min_value is not None and current < min_value: + self._log_debug("to low -> not matching") + return False + + if max_value is not None and current > max_value: + self._log_debug("to high -> not matching") + return False + else: + if min_value is not None and current > min_value and (max_value is None or current < max_value): + self._log_debug("not lower than min -> not matching") + return False + + if max_value is not None and current < max_value and (min_value is None or current > min_value): + self._log_debug("not higher than max -> not matching") + return False + + self._log_debug("given limits ok -> matching") + return True + finally: + self._log_decrease_indent() + + # Check if age conditions match + def __check_age(self): + # No limits given -> OK + if self.__agemin.is_empty() and self.__agemax.is_empty(): + self._log_info("Age of '{0}': No limits given", self.__name) + return True + + # Ignore if no current value can be determined (should not happen as we check this earlier, but to be sure ...) + if self.__item is None: + self._log_info("Age of '{0}': No item found! Considering condition as matching!", self.__name) + return True + + current = self.__item.age() + agemin = None if self.__agemin.is_empty() else self.__agemin.get() + agemax = None if self.__agemax.is_empty() else self.__agemax.get() + try: + # We check 'min' and 'max' (if given) + text = "Age of '{0}': min={1} max={2} negate={3} current={4}" + self._log_debug(text, self.__name, agemin, agemax, self.__agenegate, current) + self._log_increase_indent() + + if not self.__agenegate: + if agemin is not None and current < agemin: + self._log_debug("to young -> not matching") + return False + + if agemax is not None and current > agemax: + self._log_debug("to old -> not matching") + return False + else: + if agemin is not None and current > agemin and (agemax is None or current < agemax): + self._log_debug("not younger than min -> not matching") + return False + + if agemax is not None and current < agemax and (agemin is None or current > agemin): + self._log_debug("not older than max -> not matching") + return False + + self._log_debug("given age limits ok -> matching") + return True + finally: + self._log_decrease_indent() + + # Current value of condition (based on item or eval) + def __get_current(self): + if self.__item is not None: + # noinspection PyCallingNonCallable + return self.__item() + if self.__eval is not None: + if isinstance(self.__eval, str): + # noinspection PyUnusedLocal + sh = self._sh + if "stateengine_eval" in self.__eval: + # noinspection PyUnusedLocal + stateengine_eval = StateEngineEval.SeEval(self._abitem) + try: + value = eval(self.__eval) + except Exception as ex: + text = "Condition {}: problem evaluating {}: {}" + raise ValueError(text.format(self.__name, str(self.__eval), str(ex))) + else: + return value + else: + # noinspection PyCallingNonCallable + return self.__eval() + raise ValueError("Condition {}: Neither 'item' nor eval given!".format(self.__name)) diff --git a/stateengine/StateEngineConditionSet.py b/stateengine/StateEngineConditionSet.py new file mode 100755 index 000000000..4e1a970a0 --- /dev/null +++ b/stateengine/StateEngineConditionSet.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2014- Thomas Ernst offline@gmx.net +######################################################################### +# Finite state machine plugin for SmartHomeNG +# +# This plugin is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This plugin is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this plugin. If not, see . +######################################################################### +from . import StateEngineCondition +from . import StateEngineTools + + +# Class representing a set of conditions +class SeConditionSet(StateEngineTools.SeItemChild): + # Name of condition set + @property + def name(self): + return self.__name + + # List of conditions that are part of this condition set + @property + def conditions(self): + return self.__conditions + + # Initialize the condition set + # abitem: parent SeItem instance + # name: Name of condition set + def __init__(self, abitem, name): + super().__init__(abitem) + self.__name = name + self.__conditions = {} + + # Update condition set + # item: item containing settings for condition set + # grandparent_item: grandparent item of item (containing the definition if items and evals) + def update(self, item, grandparent_item): + # Update conditions in condition set + if item is not None: + for attribute in item.conf: + func, name = StateEngineTools.partition_strip(attribute, "_") + if name == "": + continue + + try: + # update this condition + if name not in self.__conditions: + self.__conditions[name] = StateEngineCondition.SeCondition(self._abitem, name) + self.__conditions[name].set(func, item.conf[attribute]) + + except ValueError as ex: + raise ValueError("Condition {0}: {1}".format(name, str(ex))) + + # Update item from grandparent_item + for attribute in grandparent_item.conf: + func, name = StateEngineTools.partition_strip(attribute, "_") + if name == "": + continue + + # update item/eval in this condition + if func == "se_item" or func == "se_eval": + if name not in self.__conditions: + self.__conditions[name] = StateEngineCondition.SeCondition(self._abitem, name) + try: + self.__conditions[name].set(func, grandparent_item.conf[attribute]) + except ValueError as ex: + text = "Item '{0}', Attribute '{1}': {2}" + raise ValueError(text.format(grandparent_item.id(), attribute, str(ex))) + + # Check the condition set, optimize and complete it + # item_state: item to read from + def complete(self, item_state): + conditions_to_remove = [] + # try to complete conditions + for name in self.conditions: + try: + if not self.__conditions[name].complete(item_state): + conditions_to_remove.append(name) + continue + except ValueError as ex: + text = "State '{0}', Condition Set '{1}', Condition '{2}': {3}" + raise ValueError(text.format(item_state.id(), self.name, name, str(ex))) + + # Remove incomplete conditions + for name in conditions_to_remove: + del self.conditions[name] + + # Write the whole condition set to the logger + def write_to_logger(self): + for name in self.__conditions: + self._log_info("Condition '{0}':", name) + self._log_increase_indent() + self.__conditions[name].write_to_logger() + self._log_decrease_indent() + + # Check all conditions in the condition set. Return + # returns: True = all conditions in set are matching, False = at least one condition is not matching + def all_conditions_matching(self): + try: + self._log_info("Check condition set '{0}':", self.__name) + self._log_increase_indent() + for name in self.__conditions: + if not self.__conditions[name].check(): + return False + return True + finally: + self._log_decrease_indent() diff --git a/stateengine/StateEngineConditionSets.py b/stateengine/StateEngineConditionSets.py new file mode 100755 index 000000000..0d05dd089 --- /dev/null +++ b/stateengine/StateEngineConditionSets.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2014- Thomas Ernst offline@gmx.net +######################################################################### +# Finite state machine plugin for SmartHomeNG +# +# This plugin is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This plugin is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this plugin. If not, see . +######################################################################### +from . import StateEngineConditionSet +from . import StateEngineTools +from collections import OrderedDict + +# Class representing a list of condition sets +class SeConditionSets(StateEngineTools.SeItemChild): + # Initialize the list of condition sets + # abitem: parent SeItem instance + def __init__(self, abitem): + super().__init__(abitem) + self.__condition_sets = OrderedDict() + + # Return number of condition sets in list + def count(self): + return len(self.__condition_sets) + + # Add/update a condition set + # name: Name of condition set + # item: item containing settings for condition set + # grandparent_item: grandparent item of item (containing the definition if items and evals) + def update(self, name, item, grandparent_item): + # Add condition set if not yet existing + if name not in self.__condition_sets: + self.__condition_sets[name] = StateEngineConditionSet.SeConditionSet(self._abitem, name) + # Update this condition set + self.__condition_sets[name].update(item, grandparent_item) + + # Check the condition sets, optimize and complete them + # item_state: item to read from + def complete(self, item_state): + for name in self.__condition_sets: + self.__condition_sets[name].complete(item_state) + + # Write all condition sets to logger + def write_to_logger(self): + for name in self.__condition_sets: + self._log_info("Condition Set '{0}':", name) + self._log_increase_indent() + self.__condition_sets[name].write_to_logger() + self._log_decrease_indent() + + # check if one of the conditions sets in the list is matching. + # returns: True = one condition set is matching or no condition sets are defined, False: no condition set matching + def one_conditionset_matching(self): + if self.count() == 0: + self._log_debug("No condition sets defined -> matching") + return True + for name in self.__condition_sets: + if self.__condition_sets[name].all_conditions_matching(): + return True + return False diff --git a/stateengine/StateEngineCurrent.py b/stateengine/StateEngineCurrent.py new file mode 100755 index 000000000..a797e2f15 --- /dev/null +++ b/stateengine/StateEngineCurrent.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2014- Thomas Ernst offline@gmx.net +######################################################################### +# Finite state machine plugin for SmartHomeNG +# +# This plugin is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This plugin is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this plugin. If not, see . +######################################################################### +import time +import math +import datetime +from random import randint + +# Static current conditions object +values = None +""":type : SeCurrent""" + + +# Init current conditions +def init(smarthome): + global values + values = SeCurrent(smarthome) + + +# Update current conditions +def update(): + values.update() + + +# Class representing the current conditions to check against +class SeCurrent: + # Initialize + # smarthome: Instance of smarthome.py-class + def __init__(self, smarthome): + self.__sh = smarthome + self.__weekday = None + self.__time = None + self.__sun_azimut = None + self.__sun_altitude = None + self.__month = None + self.update() + + # Return current weekday + def get_weekday(self): + return self.__weekday + + # Return current time + def get_time(self): + return self.__time + + # Return current sun_azimut + def get_sun_azimut(self): + return self.__sun_azimut + + # Return current sun_altitude + def get_sun_altitude(self): + return self.__sun_altitude + + # Return current month + def get_month(self): + return self.__month + + # Return random number between 0 and 100 + # noinspection PyMethodMayBeStatic + def get_random(self): + return randint(0, 100) + + # Update current values + def update(self): + now = time.localtime() + self.__weekday = now.tm_wday + self.__time = datetime.datetime.time(datetime.datetime.now()) + self.__month = now.tm_mon + azimut, altitude = self.__sh.sun.pos() + self.__sun_azimut = math.degrees(float(azimut)) + self.__sun_altitude = math.degrees(float(altitude)) diff --git a/stateengine/StateEngineDefaults.py b/stateengine/StateEngineDefaults.py new file mode 100755 index 000000000..f118ecfe1 --- /dev/null +++ b/stateengine/StateEngineDefaults.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2014- Thomas Ernst offline@gmx.net +######################################################################### +# Finite state machine plugin for SmartHomeNG +# +# This plugin is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This plugin is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this plugin. If not, see . +######################################################################### +import logging + + +startup_delay = 10 + +suspend_time = 3600 + +plugin_identification = "StateEngine Plugin" + + +def write_to_log(): + logger = logging.getLogger(__name__) + logger.info("StateEngine default startup delay = {0}".format(startup_delay)) + logger.info("StateEngine default suspension time = {0}".format(suspend_time)) diff --git a/stateengine/StateEngineEval.py b/stateengine/StateEngineEval.py new file mode 100755 index 000000000..72ae7f45d --- /dev/null +++ b/stateengine/StateEngineEval.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2014- Thomas Ernst offline@gmx.net +######################################################################### +# Finite state machine plugin for SmartHomeNG +# +# This plugin is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This plugin is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this plugin. If not, see . +######################################################################### +from . import StateEngineTools +from . import StateEngineCurrent +from random import randint +import subprocess +import datetime + + +class SeEval(StateEngineTools.SeItemChild): + # Initialize + # abitem: parent SeItem instance + def __init__(self, abitem): + super().__init__(abitem) + + # Get lamella angle based on sun_altitute for sun tracking + def sun_tracking(self): + self._log_debug("Executing method 'SunTracking()'") + self._log_increase_indent() + + altitude = StateEngineCurrent.values.get_sun_altitude() + self._log_debug("Current sun altitude is {0}°", altitude) + + value = 90 - altitude + self._log_debug("Blinds at right angle to the sun at {0}°", value) + + self._log_decrease_indent() + return value + + # Return random integer + # min_value: minimum value for random integer (default 0) + # max_value: maximum value for random integer (default 255) + def get_random_int(self, min_value=0, max_value=255): + self._log_debug("Executing method 'GetRandomInt({0},{1})'", min_value, max_value) + return randint(min_value, max_value) + + # Execute a command + # command: command to execute + def execute(self, command): + self._log_debug("Executing method 'execute({0})'", command) + try: + return subprocess.call(command, shell=True) + except Exception as ex: + self._log_exception(ex) + + # Return a variable + # varname: name of variable to return + def get_variable(self, varname): + self._log_debug("Executing method 'get_variable({0})'", varname) + try: + return self._abitem.get_variable(varname) + except Exception as ex: + self._log_exception(ex) + + # Return the absolute id of an item related to the StateEngine Object Item + # item_id: Relative id of item whose absolute id should be returned + # + # See describtion if StateEngineItem.SeItem.return_item for details + def get_relative_itemid(self, subitem_id): + self._log_debug("Executing method 'get_relative_itemid({0})'", subitem_id) + try: + item = self._abitem.return_item(subitem_id) + return item.id() + except Exception as ex: + self._log_exception(ex) + + # Return the value of an item related to the StateEngine Object Item + # item_id: Relative id of item whose value should be returned + # + # See describtion if StateEngineItem.SeItem.return_item for details + def get_relative_itemvalue(self, subitem_id): + self._log_debug("Executing method 'get_relative_itemvalue({0})'", subitem_id) + try: + item = self._abitem.return_item(subitem_id) + return item() + except Exception as ex: + self._log_exception(ex) + + # Insert end time of suspension into text + # suspend_item_id: Item whose age is used to determine how much of the suspend time is already over + # suspend_text: Text to insert end time of suspension into. Use strftime/strptime format codes for the end time + # (see https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior) + def insert_suspend_time(self, suspend_item_id, suspend_text="Ausgesetzt bis %X"): + self._log_debug("Executing method 'insert_suspend_time({0}, {1})'", suspend_item_id, suspend_text) + self._log_increase_indent() + try: + suspend_time = self._abitem.get_variable("item.suspend_time") + self._log_debug("Suspend time is {0}", suspend_time) + suspend_item = self._abitem.return_item(suspend_item_id) + if suspend_item is None: + text = "Eval-Method 'insert_suspend_time': Suspend Item {0} not found!" + raise ValueError(text.format(suspend_item_id)) + self._log_debug("Suspend item is {0}", suspend_item.id()) + suspend_over = suspend_item.age() + self._log_debug("Current suspend age: {0}", suspend_over) + suspend_remaining = suspend_time - suspend_over + self._log_debug("Remaining suspend time: {0}", suspend_remaining) + if suspend_remaining < 0: + self._log_debug("Eval-Method 'insert_suspend_time': Suspend should alredy be finished!") + return "Suspend already over." + suspend_until = self._abitem.sh.now() + datetime.timedelta(seconds=suspend_remaining) + self._log_debug("Suspend finished at {0}", suspend_until) + return suspend_until.strftime(suspend_text) + except Exception as ex: + self._log_exception(ex) + return "(Error while determining text. Check log)" + finally: + self._log_decrease_indent() diff --git a/stateengine/StateEngineFunctions.py b/stateengine/StateEngineFunctions.py new file mode 100755 index 000000000..9a760d97f --- /dev/null +++ b/stateengine/StateEngineFunctions.py @@ -0,0 +1,187 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2014- Thomas Ernst offline@gmx.net +######################################################################### +# Finite state machine plugin for SmartHomeNG +# +# This plugin is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This plugin is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this plugin. If not, see . +######################################################################### +import logging +import threading +from . import StateEngineLogger + + +class SeFunctions: + # return instance of smarthome.py class + @property + def ab_alive(self): + return self.__ab_alive + + @ab_alive.setter + def ab_alive(self, value): + self.__ab_alive = value + + def __init__(self, smarthome): + self.logger = logging.getLogger(__name__) + self.__sh = smarthome + self.__locks = {} + self.__ab_alive = False + + # get a lock object + # lock_id: Id of the lock object to return + def __get_lock(self, lock_id): + if lock_id not in self.__locks: + self.__locks[lock_id] = threading.Lock() + return self.__locks[lock_id] + + # return new item value for "manual" item + # item_id: Id of "manual" item + # caller: Caller that triggered the update + # source: Source that triggered the update + # The Method will determine the original caller/source and then check if this original caller/source is not + # contained in se_manual_exclude list (if given) and is contained in se_manual_include list (if given). + # If the original caller/source should be consiedered, the method returns the inverted value of the item. + # Otherwise, the method returns the current value of the item, so that no change will be made + def manual_item_update_eval(self, item_id, caller=None, source=None): + item = self.__sh.return_item(item_id) + if item is None: + self.logger.error("manual_item_update_eval: item {0} not found!".format(item_id)) + + # Leave immediately in case StateEngine Plugin is not yet fully running + if not self.__ab_alive: + return item() + + lock = self.__get_lock(item_id) + try: + lock.acquire() + + if "se_manual_logitem" in item.conf: + elog_item_id = item.conf["se_manual_logitem"] + elog_item = self.__sh.return_item(elog_item_id) + if elog_item is None: + self.logger.error("manual_item_update_item: se_manual_logitem {0} not found!".format(elog_item_id)) + elog = StateEngineLogger.SeLoggerDummy() + else: + elog = StateEngineLogger.SeLogger.create(elog_item) + else: + elog = StateEngineLogger.SeLoggerDummy() + elog.header("manual_item_update_eval") + elog.debug("running for item '{0}' source '{1}' caller '{2}'", item_id, caller, source) + + retval_no_trigger = item() + retval_trigger = not item() + elog.debug("Current value of item {0} is {1}", item_id, retval_no_trigger) + + original_caller, original_source = self.get_original_caller(elog, caller, source) + elog.debug("original trigger by caller '{0}' source '{1}'", original_caller, original_source) + + if "se_manual_on" in item.conf: + # get list of include entries + include = item.conf["se_manual_on"] + if isinstance(include, str): + include = [include, ] + elif not isinstance(include, list): + elog.error("Item '{0}', Attribute 'se_manual_on': Value must be a string or a list!", item_id) + return retval_no_trigger + elog.debug("checking include values: {0}", include) + elog.increase_indent() + + # If current value is in list -> Return "Trigger" + for entry in include: + entry_caller, __, entry_source = entry.partition(":") + if (entry_caller == original_caller or entry_caller == "*") and ( + entry_source == original_source or entry_source == "*"): + elog.debug("{0}: matching. Writing value {1}", entry, retval_no_trigger) + return retval_no_trigger + elog.debug("{0}: not matching", entry) + elog.decrease_indent() + + if "se_manual_exclude" in item.conf: + # get list of exclude entries + exclude = item.conf["se_manual_exclude"] + + if isinstance(exclude, str): + exclude = [exclude, ] + elif not isinstance(exclude, list): + elog.error("Item '{0}', Attribute 'se_manual_exclude': Value must be a string or a list!", item_id) + return retval_no_trigger + elog.debug("checking exclude values: {0}", exclude) + elog.increase_indent() + + # If current value is in list -> Return "NoTrigger" + for entry in exclude: + entry_caller, __, entry_source = entry.partition(":") + if (entry_caller == original_caller or entry_caller == "*") and ( + entry_source == original_source or entry_source == "*"): + elog.debug("{0}: matching. Writing value {1}", entry, retval_no_trigger) + return retval_no_trigger + elog.debug("{0}: not matching", entry) + elog.decrease_indent() + + if "se_manual_include" in item.conf: + # get list of include entries + include = item.conf["se_manual_include"] + if isinstance(include, str): + include = [include, ] + elif not isinstance(include, list): + elog.error("Item '{0}', Attribute 'se_manual_include': Value must be a string or a list!", item_id) + return retval_no_trigger + elog.debug("checking include values: {0}", include) + elog.increase_indent() + + # If current value is in list -> Return "Trigger" + for entry in include: + entry_caller, __, entry_source = entry.partition(":") + if (entry_caller == original_caller or entry_caller == "*") and ( + entry_source == original_source or entry_source == "*"): + elog.debug("{0}: matching. Writing value {1}", entry, retval_trigger) + return retval_trigger + elog.debug("{0}: not matching", entry) + elog.decrease_indent() + + # Current value not in list -> Return "No Trigger + elog.debug("No include values matching. Writing value {0}", retval_no_trigger) + return retval_no_trigger + else: + # No include-entries -> return "Trigger" + elog.debug("No include limitation. Writing value {0}", retval_trigger) + return retval_trigger + finally: + lock.release() + + # determine original caller/source + # elog: instance of logging class + # caller: caller + # source: source + def get_original_caller(self, elog, caller, source): + original_caller = caller + original_source = source + while original_caller == "Eval": + original_item = self.__sh.return_item(original_source) + if original_item is None: + elog.debug("get_original_caller({0}, {1}): original item not found", original_caller, original_source) + break + original_changed_by = original_item.changed_by() + if ":" not in original_changed_by: + text = "get_original_caller({0}, {1}): changed by {2} -> separator missing" + elog.debug(text, original_caller, original_source, original_changed_by) + break + oc = original_caller + os = original_source + original_caller, __, original_source = original_changed_by.partition(":") + elog.debug("get_original_caller({0}, {1}): changed by {2}, {3} at {4}", oc, os, original_caller, original_source, original_item.last_change()) + + elog.debug("get_original_caller: returning {0}, {1}", original_caller, original_source) + return original_caller, original_source diff --git a/stateengine/StateEngineItem.py b/stateengine/StateEngineItem.py new file mode 100755 index 000000000..6225c898e --- /dev/null +++ b/stateengine/StateEngineItem.py @@ -0,0 +1,485 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2014- Thomas Ernst offline@gmx.net +######################################################################### +# Finite state machine plugin for SmartHomeNG +# +# This plugin is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This plugin is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this plugin. If not, see . +######################################################################### +import datetime +from . import StateEngineTools +from .StateEngineLogger import SeLogger +from . import StateEngineState +from . import StateEngineDefaults +from . import StateEngineCurrent +from . import StateEngineValue + + +# Class representing a blind item +# noinspection PyCallingNonCallable +class SeItem: + # return item id + @property + def id(self): + return self.__id + + # return instance of smarthome.py class + @property + def sh(self): + return self.__sh + + # return instance of logger class + @property + def logger(self): + return self.__logger + + # Constructor + # smarthome: instance of smarthome.py + # item: item to use + def __init__(self, smarthome, item): + self.__sh = smarthome + self.__item = item + self.__id = self.__item.id() + self.__name = str(self.__item) + # initialize logging + self.__logger = SeLogger.create(self.__item) + self.__logger.header("Initialize Item {0}".format(self.id)) + + # get startup delay + self.__startup_delay = StateEngineValue.SeValue(self, "Startup Delay", False, "num") + self.__startup_delay.set_from_attr(self.__item, "se_startup_delay", StateEngineDefaults.startup_delay) + self.__startup_delay_over = False + + # Init suspend settings + self.__suspend_time = StateEngineValue.SeValue(self, "Suspension time on manual changes", False, "num") + self.__suspend_time.set_from_attr(self.__item, "se_suspend_time", StateEngineDefaults.suspend_time) + + # Init laststate items/values + self.__laststate_item_id = self.return_item_by_attribute("se_laststate_item_id") + self.__laststate_internal_id = "" if self.__laststate_item_id is None else self.__laststate_item_id() + self.__laststate_item_name = self.return_item_by_attribute("se_laststate_item_name") + self.__laststate_internal_name = "" if self.__laststate_item_name is None else self.__laststate_item_name() + + self.__states = [] + self.__repeat_actions = StateEngineValue.SeValue(self, "Repeat actions if state is not changed", False, "bool") + self.__repeat_actions.set_from_attr(self.__item, "se_repeat_actions", True) + + self.__update_trigger_item = None + self.__update_trigger_caller = None + self.__update_trigger_source = None + self.__update_trigger_dest = None + self.__update_in_progress = False + self.__update_original_item = None + self.__update_original_caller = None + self.__update_original_source = None + + # Check item configuration + self.__check_item_config() + + # Init variables + self.__variables = { + "item.suspend_time": self.__suspend_time.get(), + "item.suspend_remaining": 0, + "current.state_id": "", + "current.state_name": "" + } + + # initialize states + for item_state in self.__item.return_children(): + try: + self.__states.append(StateEngineState.SeState(self, item_state)) + except ValueError as ex: + self.__logger.error("Ignoring state {0} because: {1}".format(item_state.id(), str(ex))) + + if len(self.__states) == 0: + raise ValueError("{0}: No states defined!".format(self.id)) + + # Write settings to log + self.__write_to_log() + + # start timer with startup-delay + startup_delay = 0 if self.__startup_delay.is_empty() else self.__startup_delay.get() + if startup_delay > 0: + first_run = self.__sh.now() + datetime.timedelta(seconds=startup_delay) + scheduler_name = self.__id + "-Startup Delay" + value = {"item": self.__item, "caller": "Init"} + self.__sh.scheduler.add(scheduler_name, self.__startup_delay_callback, value=value, next=first_run) + elif startup_delay == -1: + self.__startup_delay_over = True + self.__add_triggers() + else: + self.__startup_delay_callback(self.__item, "Init", None, None) + + # Find the state, matching the current conditions and perform the actions of this state + # caller: Caller that triggered the update + # noinspection PyCallingNonCallable,PyUnusedLocal + def update_state(self, item, caller=None, source=None, dest=None): + if self.__update_in_progress or not self.__startup_delay_over: + return + + self.__update_in_progress = True + + self.__logger.update_logfile() + self.__logger.header("Update state of item {0}".format(self.__name)) + if caller: + item_id = item.id() if item is not None else "(no item)" + self.__logger.debug("Update triggered by {0} (item={1} source={2} dest={3})", caller, item_id, source, dest) + + # Find out what initially caused the update to trigger if the caller is "Eval" + orig_caller, orig_source, orig_item = StateEngineTools.get_original_caller(self.sh, caller, source, item) + if orig_caller != caller: + text = "Eval initially triggered by {0} (item={1} source={2})" + self.__logger.debug(text, orig_caller, orig_item.id(), orig_source) + + if orig_caller == StateEngineDefaults.plugin_identification or caller == StateEngineDefaults.plugin_identification: + self.__logger.debug("Ignoring changes from {0}", StateEngineDefaults.plugin_identification) + self.__update_in_progress = False + return + + self.__update_trigger_item = item.id() + self.__update_trigger_caller = caller + self.__update_trigger_source = source + self.__update_trigger_dest = dest + self.__update_original_item = orig_item.id() + self.__update_original_caller = orig_caller + self.__update_original_source = orig_source + + # Update current values + StateEngineCurrent.update() + self.__variables["item.suspend_time"] = self.__suspend_time.get() + self.__variables["item.suspend_remaining"] = -1 + + # get last state + last_state = self.__laststate_get() + if last_state is not None: + self.__logger.info("Last state: {0} ('{1}')", last_state.id, last_state.name) + + # find new state + new_state = None + for state in self.__states: + if self.__update_check_can_enter(state): + new_state = state + break + + # no new state -> stay + if new_state is None: + if last_state is None: + self.__logger.info("No matching state found, no previous state available. Doing nothing.") + else: + text = "No matching state found, staying at {0} ('{1}')" + self.__logger.info(text, last_state.id, last_state.name) + last_state.run_stay(self.__repeat_actions.get()) + self.__update_in_progress = False + return + + # get data for new state + if last_state is not None and new_state.id == last_state.id: + self.__logger.info("Staying at {0} ('{1}')", new_state.id, new_state.name) + new_state.run_stay(self.__repeat_actions.get()) + + # New state is last state + if self.__laststate_internal_name != new_state.name: + self.__laststate_set(new_state) + + else: + # New state is different from last state + if last_state is not None: + self.__logger.info("Leaving {0} ('{1}')", last_state.id, last_state.name) + last_state.run_leave(self.__repeat_actions.get()) + + self.__logger.info("Entering {0} ('{1}')", new_state.id, new_state.name) + new_state.run_enter(self.__repeat_actions.get()) + + self.__laststate_set(new_state) + + self.__update_in_progress = False + + # check if state can be entered after setting state-specific variables + # state: state to check + def __update_check_can_enter(self, state): + try: + self.__variables["current.state_id"] = state.id + self.__variables["current.state_name"] = state.name + return state.can_enter() + finally: + self.__variables["current.state_id"] = "" + self.__variables["current.state_name"] = "" + + # region Laststate ************************************************************************************************* + # Set laststate + # new_state: new state to be used as laststate + def __laststate_set(self, new_state): + self.__laststate_internal_id = new_state.id + if self.__laststate_item_id is not None: + # noinspection PyCallingNonCallable + self.__laststate_item_id(self.__laststate_internal_id) + + self.__laststate_internal_name = new_state.text + if self.__laststate_item_name is not None: + # noinspection PyCallingNonCallable + self.__laststate_item_name(self.__laststate_internal_name) + + # get last state object based on laststate_id + # returns: SeState instance of last state or "None" if no last state could be found + def __laststate_get(self): + for state in self.__states: + if state.id == self.__laststate_internal_id: + return state + return None + + # endregion + + # region Helper methods ******************************************************************************************** + # add all required triggers + def __add_triggers(self): + # add item trigger + self.__item.add_method_trigger(self.update_state) + + # Check item settings and update if required + # noinspection PyProtectedMember + def __check_item_config(self): + # set "enforce updates" for item + self.__item._enforce_updates = True + + # set "eval" for item if initial + if self.__item._eval_trigger and self.__item._eval is None: + self.__item._eval = "1" + + # Check scheduler settings and update if requred + job = self.__sh.scheduler._scheduler.get(self.id) + if job is None: + # We do not have an scheduler job so there is nothing to check and update + return + + changed = False + + # inject value into cycle if required + if "cycle" in job and job["cycle"] is not None: + cycle = list(job["cycle"].keys())[0] + value = job["cycle"][cycle] + if value is None: + value = "1" + changed = True + new_cycle = {cycle: value} + else: + new_cycle = None + + # inject value into cron if required + if "cron" in job and job["cron"] is not None: + new_cron = {} + for entry, value in job['cron'].items(): + if value is None: + value = 1 + changed = True + new_cron[entry] = value + else: + new_cron = None + + # change scheduler settings if cycle or cron have been changed + if changed: + self.__sh.scheduler.change(self.id, cycle=new_cycle, cron=new_cron) + + # get triggers in readable format + def __verbose_eval_triggers(self): + # noinspection PyProtectedMember + if not self.__item._eval_trigger: + return "Inactive" + + triggers = "" + # noinspection PyProtectedMember + for trigger in self.__item._eval_trigger: + if triggers != "": + triggers += ", " + triggers += trigger + return triggers + + # get crons and cycles in readable format + def __verbose_crons_and_cycles(self): + # get crons and cycles + cycles = "" + crons = "" + + # noinspection PyProtectedMember + job = self.__sh.scheduler._scheduler.get(self.__item.id) + if job is not None: + if "cycle" in job and job["cycle"] is not None: + cycle = list(job["cycle"].keys())[0] + cycles = "every {0} seconds".format(cycle) + + # inject value into cron if required + if "cron" in job and job["cron"] is not None: + for entry in job['cron']: + if crons != "": + crons += ", " + crons += entry + + if cycles == "": + cycles = "Inactive" + if crons == "": + crons = "Inactive" + return crons, cycles + + # log item data + def __write_to_log(self): + # get crons and cycles + crons, cycles = self.__verbose_crons_and_cycles() + triggers = self.__verbose_eval_triggers() + + # log general config + self.__logger.header("Configuration of item {0}".format(self.__name)) + self.__startup_delay.write_to_logger() + self.__logger.info("Cycle: {0}", cycles) + self.__logger.info("Cron: {0}", crons) + self.__logger.info("Trigger: {0}".format(triggers)) + self.__repeat_actions.write_to_logger() + + # log laststate settings + if self.__laststate_item_id is not None: + self.__logger.info("Item 'Laststate Id': {0}", self.__laststate_item_id.id()) + if self.__laststate_item_name is not None: + self.__logger.info("Item 'Laststate Name': {0}", self.__laststate_item_name.id()) + + # log states + for state in self.__states: + state.write_to_log() + + # endregion + + # region Methods for CLI commands ********************************************************************************** + def cli_list(self, handler): + handler.push("{0}: {1}\n".format(self.id, self.__laststate_internal_name)) + + def cli_detail(self, handler): + # get data + crons, cycles = self.__verbose_crons_and_cycles() + triggers = self.__verbose_eval_triggers() + handler.push("AutoState Item {0}:\n".format(self.id)) + handler.push("\tCurrent state: {0}\n".format(self.__laststate_internal_name)) + handler.push(self.__startup_delay.get_text("\t", "\n")) + handler.push("\tCycle: {0}\n".format(cycles)) + handler.push("\tCron: {0}\n".format(crons)) + handler.push("\tTrigger: {0}\n".format(triggers)) + handler.push(self.__repeat_actions.get_text("\t", "\n")) + + # endregion + + # region Getter methods for "special" conditions ******************************************************************* + # return age of item + def get_age(self): + if self.__laststate_item_id is not None: + return self.__laststate_item_id.age() + else: + self.__logger.warning('No item for last state id given. Can not determine age!') + return 0 + + # return id of last state + def get_laststate_id(self): + return self.__laststate_internal_id + + # return update trigger item + def get_update_trigger_item(self): + return self.__update_trigger_item + + # return update trigger caller + def get_update_trigger_caller(self): + return self.__update_trigger_caller + + # return update trigger source + def get_update_trigger_source(self): + return self.__update_trigger_source + + # return update trigger dest + def get_update_trigger_dest(self): + return self.__update_trigger_dest + + # return update original item + def get_update_original_item(self): + return self.__update_original_item + + # return update original caller + def get_update_original_caller(self): + return self.__update_original_caller + + # return update original source + def get_update_original_source(self): + return self.__update_original_source + + # return value of variable + def get_variable(self, varname): + return self.__variables[varname] if varname in self.__variables else "(Unknown variable '{0}'!)".format(varname) + + # set value of variable + def set_variable(self, varname, value): + if varname not in self.__variables: + raise ValueError("Unknown variable '{0}!".format(varname)) + self.__variables[varname] = value + + # endregion + + # callback function that is called after the startup delay + # noinspection PyUnusedLocal + def __startup_delay_callback(self, item, caller=None, source=None, dest=None): + self.__startup_delay_over = True + self.update_state(item, "Startup Delay", source, dest) + self.__add_triggers() + + # Return an item related to the StateEngine Object Item + # item_id: Id of item to return + # + # With this function it is possible to provide items relative to the current StateEngine object item. + # If an item_id starts with one or more ".", the item is relative to the StateEngine object item. One "." means + # that the given item Id is relative to the current level of the StateEngine object item. Every additional "." + # removes one level of the StateEngine object item before adding the item_id. + # Examples (based on StateEngine object item "my.stateengine.objectitem": + # - item_id = "not.prefixed.with.dots" will return item "not.prefixed.with.dots" + # - item_id = ".onedot" will return item "my.stateengine.objectitem.onedot" + # - item_id = "..twodots" will return item "my.stateengine.twodots" + # - item_id = "..threedots" will return item "my.threedots" + # - item_id = "..threedots.further.down" will return item "my.threedots.further.down" + def return_item(self, item_id: str): + if not item_id.startswith("."): + item = self.__sh.return_item(item_id) + if item is None: + raise ValueError("Item '{0}' not found!".format(item_id)) + return item + + parent_level = 0 + for c in item_id: + if c != '.': + break + parent_level += 1 + + levels = self.id.split(".") + use_num_levels = len(levels) - parent_level + 1 + if use_num_levels < 0: + text = "Item '{0}' can not be determined. Parent item '{1}' has only {2} levels!" + raise ValueError(text.format(item_id, self.id, len(levels))) + result = "" + for level in levels[0:use_num_levels]: + result += level if result == "" else "." + level + rel_item_id = item_id[parent_level:] + if rel_item_id != "": + result += "." + rel_item_id + item = self.__sh.return_item(result) + if item is None: + raise ValueError("Determined item '{0}' does not exist.".format(result)) + return item + + # Return an item related to the StateEngine object item + # attribute: Name of the attribute of the StateEngine object item, which contains the item_id to read + def return_item_by_attribute(self, attribute): + if attribute not in self.__item.conf: + return None + return self.return_item(self.__item.conf[attribute]) diff --git a/stateengine/StateEngineLogger.py b/stateengine/StateEngineLogger.py new file mode 100755 index 000000000..132167646 --- /dev/null +++ b/stateengine/StateEngineLogger.py @@ -0,0 +1,245 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2014- Thomas Ernst offline@gmx.net +######################################################################### +# Finite state machine plugin for SmartHomeNG +# +# This plugin is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This plugin is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this plugin. If not, see . +######################################################################### +import logging +import datetime +import os + + +class SeLogger: + # Log-Level: (0=off 1=Info, 2=Debug) + __loglevel = 2 + + # Target directory for log files + __logdirectory = "/usr/local/smarthome/var/log/StateEngine/" + + # Max age for log files (days) + __logmaxage = 0 + + # Set log level + # loglevel: current loglevel + @staticmethod + def set_loglevel(loglevel): + try: + SeLogger.__loglevel = int(loglevel) + except ValueError: + SeLogger.__loglevel = 2 + logger = logging.getLogger('plugins.stateengine.StateEngineLogger') + logger.error("Das Log-Level muss numerisch angegeben werden.") + + # Set log directory + # logdirectory: Target directory for StateEngine log files + @staticmethod + def set_logdirectory(logdirectory): + SeLogger.__logdirectory = logdirectory + + # Set max age for log files + # logmaxage: Maximum age for log files (days) + @staticmethod + def set_logmaxage(logmaxage): + try: + SeLogger.__logmaxage = int(logmaxage) + except ValueError: + SeLogger.__logmaxage = 0 + logger = logging.getLogger('plugins.stateengine.StateEngineLogger') + logger.error("Das maximale Alter der Logdateien muss numerisch angegeben werden.") + + @staticmethod + def remove_old_logfiles(): + if SeLogger.__logmaxage == 0: + return + logger = logging.getLogger('plugins.stateengine.StateEngineLogger') + logger.info("Removing logfiles older than {0} days".format(SeLogger.__logmaxage)) + count_success = 0 + count_error = 0 + now = datetime.datetime.now() + for file in os.listdir(SeLogger.__logdirectory): + if file.endswith(".log"): + try: + abs_file = os.path.join(SeLogger.__logdirectory, file) + stat = os.stat(abs_file) + mtime = datetime.datetime.fromtimestamp(stat.st_mtime) + age_in_days = (now - mtime).total_seconds() / 86400.0 + if age_in_days > SeLogger.__logmaxage: + os.unlink(abs_file) + count_success += 1 + except Exception as ex: + logger.error(str(ex)) + count_error += 1 + logger.info("{0} files removed, {1} errors occured".format(count_success, count_error)) + + # Return SeLogger instance for given item + # item: item for which the detailed log is + @staticmethod + def create(item): + return SeLogger(item) + + # Constructor + # item: item for which the detailed log is (used as part of file name) + def __init__(self, item): + self.logger = logging.getLogger(__name__) + self.__section = item.id().replace(".", "_").replace("/", "") + self.__indentlevel = 0 + self.__date = None + self.__filename = "" + self.update_logfile() + + # Update name logfile if required + def update_logfile(self): + if self.__date == datetime.datetime.today() and self.__filename is not None: + return + self.__date = str(datetime.date.today()) + self.__filename = str(SeLogger.__logdirectory + self.__date + '-' + self.__section + ".log") + + # Increase indentation level + # by: number of levels to increase + def increase_indent(self, by=1): + self.__indentlevel += by + + # Decrease indentation level + # by: number of levels to decrease + def decrease_indent(self, by=1): + if self.__indentlevel > by: + self.__indentlevel -= by + else: + self.__indentlevel = 0 + + # log text something + # level: required loglevel + # text: text to log + def log(self, level, text, *args): + # Section givn: Check level + if level <= SeLogger.__loglevel: + indent = "\t" * self.__indentlevel + text = text.format(*args) + logtext = "{0}{1} {2}\r\n".format(datetime.datetime.now(), indent, text) + with open(self.__filename, mode="a", encoding="utf-8") as f: + f.write(logtext) + + # log header line (as info) + # text: header text + def header(self, text): + self.__indentlevel = 0 + text += " " + self.log(1, text.ljust(80, "=")) + + # log with level=info + # @param text text to log + # @param *args parameters for text + def info(self, text, *args): + self.log(1, text, *args) + + # log with lebel=debug + # text: text to log + # *args: parameters for text + def debug(self, text, *args): + self.log(2, text, *args) + + # log warning (always to main smarthome.py log) + # text: text to log + # *args: parameters for text + # noinspection PyMethodMayBeStatic + def warning(self, text, *args): + self.log(1, "WARNING: " + text, *args) + self.logger.warning(text.format(*args)) + + # log error (always to main smarthome.py log) + # text: text to log + # *args: parameters for text + # noinspection PyMethodMayBeStatic + def error(self, text, *args): + self.log(1, "ERROR: " + text, *args) + self.logger.error(text.format(*args)) + + # log exception (always to main smarthome.py log' + # msg: message to log + # *args: arguments for message + # **kwargs: known arguments for message + # noinspection PyMethodMayBeStatic + def exception(self, msg, *args, **kwargs): + self.log(1, "EXCEPTION: " + str(msg), *args) + self.logger.exception(msg, *args, **kwargs) + + +class SeLoggerDummy: + # Constructor + # item: item for which the detailed log is (used as part of file name) + # noinspection PyUnusedLocal + def __init__(self, item=None): + self.logger = logging.getLogger(__name__) + + # Update name logfile if required + def update_logfile(self): + pass + + # Increase indentation level + # by: number of levels to increase + def increase_indent(self, by=1): + pass + + # Decrease indentation level + # by: number of levels to decrease + def decrease_indent(self, by=1): + pass + + # log text something + # level: required loglevel + # text: text to log + def log(self, level, text, *args): + pass + + # log header line (as info) + # text: header text + def header(self, text): + pass + + # log with level=info + # @param text text to log + # @param *args parameters for text + def info(self, text, *args): + pass + + # log with lebel=debug + # text: text to log + # *args: parameters for text + def debug(self, text, *args): + pass + + # log warning (always to main smarthome.py log) + # text: text to log + # *args: parameters for text + # noinspection PyMethodMayBeStatic + def warning(self, text, *args): + self.logger.warning(text.format(*args)) + + # log error (always to main smarthome.py log) + # text: text to log + # *args: parameters for text + # noinspection PyMethodMayBeStatic + def error(self, text, *args): + self.logger.error(text.format(*args)) + + # log exception (always to main smarthome.py log' + # msg: message to log + # *args: arguments for message + # **kwargs: known arguments for message + # noinspection PyMethodMayBeStatic + def exception(self, msg, *args, **kwargs): + self.logger.exception(msg, *args, **kwargs) diff --git a/stateengine/StateEngineState.py b/stateengine/StateEngineState.py new file mode 100755 index 000000000..9cd8ed74b --- /dev/null +++ b/stateengine/StateEngineState.py @@ -0,0 +1,192 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2014- Thomas Ernst offline@gmx.net +######################################################################### +# Finite state machine plugin for SmartHomeNG +# +# This plugin is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This plugin is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this plugin. If not, see . +######################################################################### +from . import StateEngineTools +from . import StateEngineConditionSets +from . import StateEngineActions +from . import StateEngineValue + + +# Class representing an object state, consisting of name, conditions to be met and configured actions for state +class SeState(StateEngineTools.SeItemChild): + # Return id of state (= id of defining item) + @property + def id(self): + return self.__id + + # Return name of state + @property + def name(self): + return self.__name + + # Return text of state + @property + def text(self): + return self.__text.get(self.__name) + + # Constructor + # abitem: parent SeItem instance + # item_state: item containing configuration of state + def __init__(self, abitem, item_state): + super().__init__(abitem) + self.__item = item_state + self.__id = self.__item.id() + self.__name = "" + self.__text = StateEngineValue.SeValue(self._abitem, "State Name", False, "str") + self.__conditions = StateEngineConditionSets.SeConditionSets(self._abitem) + self.__actions_enter_or_stay = StateEngineActions.SeActions(self._abitem) + self.__actions_enter = StateEngineActions.SeActions(self._abitem) + self.__actions_stay = StateEngineActions.SeActions(self._abitem) + self.__actions_leave = StateEngineActions.SeActions(self._abitem) + self._log_info("Init state {}", item_state.id()) + self._log_increase_indent() + try: + self.__fill(self.__item, 0) + finally: + self._log_decrease_indent() + + # Check conditions if state can be entered + # returns: True = At least one enter condition set is fulfulled, False = No enter condition set is fulfilled + def can_enter(self): + self._log_info("Check if state '{0}' ('{1}') can be entered:", self.id, self.name) + self._log_increase_indent() + result = self.__conditions.one_conditionset_matching() + self._log_decrease_indent() + if result: + self._log_info("State can be entered") + else: + self._log_info("State can not be entered") + return result + + # log state data + def write_to_log(self): + self._log_info("State {0}:", self.id) + self._log_increase_indent() + self._log_info("Name: {0}", self.name) + self.__text.write_to_logger() + if self.__conditions.count() > 0: + self._log_info("Condition sets to enter state:") + self._log_increase_indent() + self.__conditions.write_to_logger() + self._log_decrease_indent() + if self.__actions_enter.count() > 0: + self._log_info("Actions to perform on enter:") + self._log_increase_indent() + self.__actions_enter.write_to_logger() + self._log_decrease_indent() + if self.__actions_stay.count() > 0: + self._log_info("Actions to perform on stay:") + self._log_increase_indent() + self.__actions_stay.write_to_logger() + self._log_decrease_indent() + if self.__actions_enter_or_stay.count() > 0: + self._log_info("Actions to perform on enter or stay:") + self._log_increase_indent() + self.__actions_enter_or_stay.write_to_logger() + self._log_decrease_indent() + if self.__actions_leave.count() > 0: + self._log_info("Actions to perform on leave:") + self._log_increase_indent() + self.__actions_leave.write_to_logger() + self._log_decrease_indent() + self._log_decrease_indent() + + # run actions when entering the state + # item_allow_repeat: Is repeating actions generally allowed for the item? + def run_enter(self, allow_item_repeat: bool): + self._log_increase_indent() + self.__actions_enter.execute(False, allow_item_repeat, self.__actions_enter_or_stay) + self._log_decrease_indent() + + # run actions when staying at the state + # item_allow_repeat: Is repeating actions generally allowed for the item? + def run_stay(self, allow_item_repeat: bool): + self._log_increase_indent() + self.__actions_stay.execute(True, allow_item_repeat, self.__actions_enter_or_stay) + self._log_decrease_indent() + + # run actions when leaving the state + # item_allow_repeat: Is repeating actions generally allowed for the item? + def run_leave(self, allow_item_repeat: bool): + self._log_increase_indent() + self.__actions_leave.execute(False, allow_item_repeat) + self._log_decrease_indent() + + # Read configuration from item and populate data in class + # item_state: item to read from + # recursion_depth: current recursion_depth (recursion is canceled after five levels) + # item_stateengine: StateEngine-Item defining items for conditions + # abitem_object: Related SeItem instance for later determination of current age and current delay + def __fill(self, item_state, recursion_depth): + if recursion_depth > 5: + self._log_error("{0}/{1}: to many levels of 'use'", self.id, item_state.id()) + return + + # Import data from other item if attribute "use" is found + if "se_use" in item_state.conf: + use_item = self._abitem.return_item(item_state.conf["se_use"]) + if use_item is not None: + self.__fill(use_item, recursion_depth + 1) + else: + self._log_error("{0}: Referenced item '{1}' not found!", item_state.id(), item_state.conf["se_use"]) + + # Get action sets and condition sets + parent_item = item_state.return_parent() + child_items = item_state.return_children() + for child_item in child_items: + child_name = StateEngineTools.get_last_part_of_item_id(child_item) + try: + if child_name == "on_enter": + for attribute in child_item.conf: + self.__actions_enter.update(attribute, child_item.conf[attribute]) + elif child_name == "on_stay": + for attribute in child_item.conf: + self.__actions_stay.update(attribute, child_item.conf[attribute]) + elif child_name == "on_enter_or_stay": + for attribute in child_item.conf: + self.__actions_enter_or_stay.update(attribute, child_item.conf[attribute]) + elif child_name == "on_leave": + for attribute in child_item.conf: + self.__actions_leave.update(attribute, child_item.conf[attribute]) + elif child_name == "enter" or child_name.startswith("enter_"): + self.__conditions.update(child_name, child_item, parent_item) + except ValueError as ex: + raise ValueError("Condition {0}: {1}".format(child_name, str(ex))) + + # Actions defined directly in the item go to "enter_or_stay" + for attribute in item_state.conf: + self.__actions_enter_or_stay.update(attribute, item_state.conf[attribute]) + + # if an item name is given, or if we do not have a name after returning from all recursions, + # use item name as state name + if str(item_state) != item_state.id() or (self.__name == "" and recursion_depth == 0): + self.__name = str(item_state) + if "se_name" in item_state.conf: + self.__text.set_from_attr(item_state, "se_name", self.__text.get(None)) + elif self.__text.is_empty() and recursion_depth == 0: + self.__text.set("value:" + self.__name) + + # Complete condition sets and actions at the end + if recursion_depth == 0: + self.__conditions.complete(item_state) + self.__actions_enter.complete(item_state) + self.__actions_stay.complete(item_state) + self.__actions_enter_or_stay.complete(item_state) + self.__actions_leave.complete(item_state) diff --git a/stateengine/StateEngineTools.py b/stateengine/StateEngineTools.py new file mode 100755 index 000000000..1b0bfeec3 --- /dev/null +++ b/stateengine/StateEngineTools.py @@ -0,0 +1,234 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2014- Thomas Ernst offline@gmx.net +######################################################################### +# Finite state machine plugin for SmartHomeNG +# +# This plugin is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This plugin is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this plugin. If not, see . +######################################################################### +import datetime + +# +# Some general tool functions +# + + +# Find a certain item below a given item. +# item: Item to search below +# child_id: Id of child item to search (without prefixed id of "item") +# returns: child item if found, otherwise None +def get_child_item(item, child_id): + search_id = item.id() + "." + child_id + for child in item.return_children(): + if child.id() == search_id: + return child + return None + + +# Returns the last part of the id of an item (everythig behind last .) +# item: Item for which the last part of the id should be returned +# returns: last part of item id +def get_last_part_of_item_id(item): + return item.id().rsplit(".", 1)[1] + + +# cast a value as numeric. Throws ValueError if cast not possible +# Taken from smarthome.py/lib/item.py +# value: value to cast +# returns: value as num or float +# noinspection PyBroadException +def cast_num(value): + if isinstance(value, float): + return value + try: + return int(value) + except: + pass + try: + return float(value) + except: + pass + raise ValueError("Can't cast {0} to int!".format(str(value))) + + +# cast a value as boolean. Throws ValueError or TypeError if cast is not possible +# Taken from smarthome.py/lib/item.py +# value: value to cast +# returs: value as boolean +def cast_bool(value): + if type(value) in [bool, int, float]: + if value in [False, 0]: + return False + elif value in [True, 1]: + return True + else: + raise ValueError("Can't cast {0} to bool!".format(str(value))) + elif type(value) in [str, str]: + if value.lower() in ['0', 'false', 'no', 'off']: + return False + elif value.lower() in ['1', 'true', 'yes', 'on']: + return True + else: + raise ValueError("Can't cast {0} to bool!".format(str(value))) + else: + raise ValueError("Can't cast {0} to bool!".format(str(value))) + + +# cast a value as string. Throws ValueError if cast is not possible +# Taken from smarthome.py/lib/item.py +# value: value to cast +# returns: value as string +def cast_str(value): + if isinstance(value, str): + return value + else: + raise ValueError("Can't cast {0} to str!".format(str(value))) + + +# cast value as datetime.time. Throws ValueError if cast is not possible +# value: value to cast +# returns: value as datetime.time +def cast_time(value): + if isinstance(value, datetime.time): + return value + + orig_value = value + value = value.replace(",", ":") + value_parts = value.split(":") + if len(value_parts) != 2: + raise ValueError("Can not cast '{0}' to data type 'time' due to incorrect format!".format(orig_value)) + else: + try: + hour = int(value_parts[0]) + minute = int(value_parts[1]) + except ValueError: + raise ValueError("Can not cast '{0}' to data type 'time' due to non-numeric parts!".format(orig_value)) + if hour == 24 and minute == 0: + return datetime.time(23, 59, 59) + else: + return datetime.time(hour, minute) + + +# find a certain attribute for a generic condition. If an "use"-attribute is found, the "use"-item is searched +# recursively +# smarthome: instance of smarthome.py base class +# base_item: base item to search in +# attribute: name of attribute to find +def find_attribute(smarthome, base_item, attribute, recursion_depth=0): + # 1: parent of given item could have attribute + parent_item = base_item.return_parent() + if parent_item is not None and attribute in parent_item.conf: + return parent_item.conf[attribute] + + # 2: if item has attribute "se_use", get the item to use and search this item for required attribute + if "se_use" in base_item.conf: + if recursion_depth > 5: + return None + use_item = smarthome.return_item(base_item.conf["se_use"]) + if use_item is not None: + result = find_attribute(smarthome, use_item, attribute, recursion_depth + 1) + if result is not None: + return result + + # 3: nothing found + return None + + +# partition value at splitchar and strip resulting parts +# value: what to split +# splitchar: where to split +# returns: Parts before and after split, whitespaces stripped +def partition_strip(value, splitchar): + if value.startswith("se_") and splitchar == "_": + part1, __, part2 = value[3:].partition(splitchar) + return "se_" + part1.strip(), part2.strip() + else: + part1, __, part2 = value.partition(splitchar) + return part1.strip(), part2.strip() + + +# return string representation of eval function +# eval_func: eval function +# returns: string representation +def get_eval_name(eval_func): + if eval_func is None: + return None + if eval_func is not None: + if isinstance(eval_func, str): + return eval_func + else: + return eval_func.__module__ + "." + eval_func.__name__ + + +# determine original caller/source +# smarthome: instance of smarthome.py +# caller: caller +# source: source +def get_original_caller(smarthome, caller, source, item=None): + original_caller = caller + original_source = source + original_item = item + while original_caller == "Eval": + original_item = smarthome.return_item(original_source) + if original_item is None: + break + original_changed_by = original_item.changed_by() + if ":" not in original_changed_by: + break + original_caller, __, original_source = original_changed_by.partition(":") + if item is None: + return original_caller, original_source + else: + return original_caller, original_source, original_item + + +# General class for everything that is below the SeItem Class +# This class provides some general stuff: +# - Protected wrapper-methods for logging +# - abitem and smarthome Instances +class SeItemChild: + # Constructor + # abitem: parent SeItem instance + def __init__(self, abitem): + self._abitem = abitem + self._sh = abitem.sh + + # wrapper method for logger.info + def _log_info(self, text, *args): + self._abitem.logger.info(text, *args) + + # wrapper method for logger.debug + def _log_debug(self, text, *args): + self._abitem.logger.debug(text, *args) + + # wrapper method for logger.warning + def _log_warning(self, text, *args): + self._abitem.logger.warning(text, *args) + + # wrapper method for logger.error + def _log_error(self, text, *args): + self._abitem.logger.error(text, *args) + + # wrapper method for logger.exception + def _log_exception(self, msg, *args, **kwargs): + self._abitem.logger.exception(msg, *args, **kwargs) + + # wrapper method for logger.increase_indent + def _log_increase_indent(self, by=1): + self._abitem.logger.increase_indent(by) + + # wrapper method for logger.decrease_indent + def _log_decrease_indent(self, by=1): + self._abitem.logger.decrease_indent(by) diff --git a/stateengine/StateEngineValue.py b/stateengine/StateEngineValue.py new file mode 100755 index 000000000..a380182d3 --- /dev/null +++ b/stateengine/StateEngineValue.py @@ -0,0 +1,219 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2014- Thomas Ernst offline@gmx.net +######################################################################### +# Finite state machine plugin for SmartHomeNG +# +# This plugin is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This plugin is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this plugin. If not, see . +######################################################################### +from . import StateEngineTools +from . import StateEngineEval + + +# Class representing a value for a condition (either value or via item/eval) +class SeValue(StateEngineTools.SeItemChild): + # Constructor + # abitem: parent SeItem instance + # name: Name of value + # allow_value_list: Flag: list of values allowed + # value_type: Type of value to preset the cast function (allowed: str, num, bool, time) + def __init__(self, abitem, name, allow_value_list=False, value_type=None): + super().__init__(abitem) + self.__name = name + self.__allow_value_list = allow_value_list + self.__value = None + self.__item = None + self.__eval = None + self.__varname = None + + if value_type == "str": + self.__cast_func = StateEngineTools.cast_str + elif value_type == "num": + self.__cast_func = StateEngineTools.cast_num + elif value_type == "bool": + self.__cast_func = StateEngineTools.cast_bool + elif value_type == "time": + self.__cast_func = StateEngineTools.cast_time + else: + self.__cast_func = None + + # Indicate of object is empty (neither value nor item nor eval set) + def is_empty(self): + return self.__value is None and self.__item is None and self.__eval is None and self.__varname is None + + # Set value directly from attribute + # item: item containing the attribute + # attribute_name: name of attribute to use + # value_type: type of value for casting (allowed: str, num ,bool, time) + # default_value: default value to be used if item contains no such attribute + def set_from_attr(self, item, attribute_name, default_value=None): + value = item.conf[attribute_name] if attribute_name in item.conf else default_value + self.set(value) + + # Set value + # value: string indicating value or source of value + # name: name of object ("time" is being handeled different) + def set(self, value, name=""): + if isinstance(value, list): + source, field_value = StateEngineTools.partition_strip(value[0], ":") + if field_value == "": + source = "value" + field_value = value + else: + value[0] = field_value + field_value = value + elif isinstance(value, str): + source, field_value = StateEngineTools.partition_strip(value, ":") + if name == "time" and source.isdigit() and field_value.isdigit(): + field_value = value + source = "value" + elif field_value == "": + field_value = source + source = "value" + else: + source = "value" + field_value = value + + if source == "value": + if isinstance(field_value, list) and not self.__allow_value_list: + raise ValueError("{0}: value_in is not allowed".format(self.__name)) + self.__value = self.__do_cast(field_value) + else: + self.__value = None + self.__item = None if source != "item" else self._abitem.return_item(field_value) + self.__eval = None if source != "eval" else field_value + self.__varname = None if source != "var" else field_value + + # Set cast function + # cast_func: cast function + def set_cast(self, cast_func): + self.__cast_func = cast_func + self.__value = self.__do_cast(self.__value) + + # determine and return value + def get(self, default=None): + if self.__value is not None: + return self.__value + elif self.__eval is not None: + return self.__get_eval() + elif self.__item is not None: + return self.__get_from_item() + elif self.__varname is not None: + return self.__get_from_variable() + else: + return default + + def get_type(self): + if self.__value is not None: + return "value" + elif self.__item is not None: + return "item" + elif self.__eval is not None: + return "eval" + elif self.__varname is not None: + return "var" + else: + return None + + # Write condition to logger + def write_to_logger(self): + if self.__value is not None: + self._log_debug("{0}: {1}", self.__name, self.__value) + elif self.__item is not None: + self._log_debug("{0} from item: {1}", self.__name, self.__item.id()) + elif self.__eval is not None: + self._log_debug("{0} from eval: {1}", self.__name, self.__eval) + elif self.__varname is not None: + self._log_debug("{0} from variable: {1}", self.__name, self.__varname) + + # Get Text (similar to logger text) + # prefix: Prefix for text + # suffix: Suffix for text + def get_text(self, prefix=None, suffix=None): + if self.__value is not None: + value = "{0}: {1}".format(self.__name, self.__value, prefix, suffix) + elif self.__item is not None: + value = "{0} from item: {1}".format(self.__name, self.__item.id()) + elif self.__eval is not None: + value = "{0} from eval: {1}".format(self.__name, self.__eval) + elif self.__varname is not None: + value = "{0} from variable: {1}".format(self.__name, self.__varname) + else: + value = "{0}: (undefined)".format(self.__name) + + value = value if prefix is None else prefix + value + value = value if suffix is None else value + suffix + return value + + # Cast given value, if cast-function is set + # value: value to cast + def __do_cast(self, value): + if value is not None and self.__cast_func is not None: + try: + if type(value) == list: + # noinspection PyCallingNonCallable + value = [self.__cast_func(element) for element in value] + else: + # noinspection PyCallingNonCallable + value = self.__cast_func(value) + except Exception as ex: + self._log_info("Problem casting value '{0}': {1}.", value, str(ex)) + return None + + return value + + # Determine value by executing eval-function + def __get_eval(self): + if isinstance(self.__eval, str): + # noinspection PyUnusedLocal + sh = self._sh + if "stateengine_eval" in self.__eval: + # noinspection PyUnusedLocal + stateengine_eval = StateEngineEval.SeEval(self._abitem) + try: + value = eval(self.__eval) + except Exception as ex: + self._log_info("Problem evaluating '{0}': {1}.", StateEngineTools.get_eval_name(self.__eval), str(ex)) + return None + else: + try: + # noinspection PyCallingNonCallable + value = self.__eval() + except Exception as ex: + self._log_info("Problem calling '{0}': {1}.", StateEngineTools.get_eval_name(self.__eval), str(ex)) + return None + + return self.__do_cast(value) + + # Determine value from item + def __get_from_item(self): + try: + # noinspection PyCallingNonCallable + value = self.__item() + except Exception as ex: + self._log_info("Problem while reading item '{0}': {1}.", self.__item.id(), str(ex)) + return None + + return self.__do_cast(value) + + # Fetermine value from variable + def __get_from_variable(self): + try: + value = self._abitem.get_variable(self.__varname) + except Exception as ex: + self._log_info("Problem while reading variable '{0}': {1}.", self.__varname, str(ex)) + return None + + return self.__do_cast(value) diff --git a/stateengine/__init__.py b/stateengine/__init__.py new file mode 100755 index 000000000..6d1a7184d --- /dev/null +++ b/stateengine/__init__.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2014- Thomas Ernst offline@gmx.net +######################################################################### +# Finite state machine plugin for SmartHomeNG +# +# This plugin is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This plugin is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this plugin. If not, see . +######################################################################### +from .StateEngineLogger import SeLogger +from . import StateEngineItem +from . import StateEngineCurrent +from . import StateEngineDefaults +from . import StateEngineTools +from . import StateEngineCliCommands +from . import StateEngineFunctions +import logging +import os +from lib.model.smartplugin import SmartPlugin + + +class StateEngine(SmartPlugin): + PLUGIN_VERSION = '1.4.1' + + # Constructor + # noinspection PyUnusedLocal,PyMissingConstructor + def __init__(self, sh, *args, **kwargs): + + self.logger = logging.getLogger(__name__) + self.__items = {} + self.alive = False + self.__cli = None + + log_level = self.get_parameter_value("log_level") + log_directory = self.get_parameter_value("log_directory") + self.logger.info("Init StateEngine (log_level={0}, log_directory={1})".format(log_level, log_directory)) + + StateEngineDefaults.startup_delay = self.get_parameter_value("startup_delay_default") + StateEngineDefaults.suspend_time = self.get_parameter_value("suspend_time_default") + StateEngineDefaults.write_to_log() + + StateEngineCurrent.init(self.get_sh()) + + if log_level > 0: + if log_directory[0] != "/": + base = self.get_sh().get_basedir() + if base[-1] != "/": + base += "/" + log_directory = base + log_directory + if not os.path.exists(log_directory): + os.makedirs(log_directory) + SeLogger.set_loglevel(log_level) + SeLogger.set_logdirectory(log_directory) + text = "StateEngine extended logging is active. Logging to '{0}' with loglevel {1}." + self.logger.info(text.format(log_directory, log_level)) + log_maxage = self.get_parameter_value("log_maxage") + if log_level > 0 and log_maxage > 0: + self.logger.info("StateEngine extended log files will be deleted after {0} days.".format(log_maxage)) + SeLogger.set_logmaxage(log_maxage) + cron = ['init', '30 0 * *'] + self.scheduler_add('StateEngine: Remove old logfiles', SeLogger.remove_old_logfiles, cron=cron, offset=0) + + self.get_sh().stateengine_plugin_functions = StateEngineFunctions.SeFunctions(self.get_sh()) + + # Parse an item + # noinspection PyMethodMayBeStatic + def parse_item(self, item): + if "se_manual_include" in item.conf or "se_manual_exclude" in item.conf: + item._eval = "sh.stateengine_plugin_functions.manual_item_update_eval('" + item.id() + "', caller, source)" + elif "se_manual_invert" in item.conf: + item._eval = "not sh." + item.id() + "()" + + return None + + # Initialization of plugin + def run(self): + # Initialize + self.logger.info("Init StateEngine items") + for item in self.get_sh().find_items("se_plugin"): + if item.conf["se_plugin"] == "active": + try: + ab_item = StateEngineItem.SeItem(self.get_sh(), item) + self.__items[ab_item.id] = ab_item + except ValueError as ex: + self.logger.error("Item: {0}: {1}".format(item.id(), str(ex))) + + if len(self.__items) > 0: + self.logger.info("Using StateEngine for {} items".format(len(self.__items))) + else: + self.logger.info("StateEngine deactivated because no items have been found.") + + self.__cli = StateEngineCliCommands.SeCliCommands(self.get_sh(), self.__items) + + self.alive = True + self.get_sh().stateengine_plugin_functions.ab_alive = True + + # Stopping of plugin + def stop(self): + self.alive = False + + # Determine if caller/source are contained in changed_by list + # caller: Caller to check + # source: Source to check + # changed_by: List of callers/source (element format :) to check against + def is_changed_by(self, caller, source, changed_by): + original_caller, original_source = StateEngineTools.get_original_caller(self.get_sh(), caller, source) + for entry in changed_by: + entry_caller, __, entry_source = entry.partition(":") + if (entry_caller == original_caller or entry_caller == "*") and ( + entry_source == original_source or entry_source == "*"): + return True + return False + + # Determine if caller/source are not contained in changed_by list + # caller: Caller to check + # source: Source to check + # changed_by: List of callers/source (element format :) to check against + def not_changed_by(self, caller, source, changed_by): + original_caller, original_source = StateEngineTools.get_original_caller(self.get_sh(), caller, source) + for entry in changed_by: + entry_caller, __, entry_source = entry.partition(":") + if (entry_caller == original_caller or entry_caller == "*") and ( + entry_source == original_source or entry_source == "*"): + return False + return True diff --git a/stateengine/autblind_update.sh b/stateengine/autblind_update.sh new file mode 100755 index 000000000..8a8d70248 --- /dev/null +++ b/stateengine/autblind_update.sh @@ -0,0 +1,72 @@ +#!/bin/bash +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" +SCRIPTSYSTEM=$(uname -a) +stringContain() { [ -z "${2##*$1*}" ] && { [ -z "$1" ] || [ -n "$2" ] ;} ; } +items_mac () { +echo "Updating item yaml on Mac OS X" +sudo sed -i {} 's/as_/se_/g' ../../items/*.yaml 2>&1 +sudo sed -i {} 's/autostate_/stateengine_/g' ../../items/*.yaml 2>&1 +sudo sed -i {} 's/autoblind/stateengine/g' ../../items/*.yaml 2>&1 +} + +items_linux () { +echo "Updating item yaml on Linux" +sudo sed -i 's/as_/se_/g' ../../items/*.yaml 2>&1 +sudo sed -i 's/autostate_/stateengine_/g' ../../items/*.yaml 2>&1 +sudo sed -i 's/autoblind/stateengine/g' ../../items/*.yaml 2>&1 +} + +update_items () { + if stringContain 'Darwin' $SCRIPTSYSTEM; then items_mac; else items_linux; fi +} + +logics_mac () { +echo "Updating logics on Mac OS X" +sudo sed -i {} 's/autostate_/stateengine_/g' ../../logics/*.py 2>&1 +sudo sed -i {} 's/autoblind/stateengine/g' ../../logics/*.py 2>&1 +} + +logics_linux () { +echo "Updating logics on Linux" +sudo sed -i 's/autostate_/stateengine_/g' ../../logics/*.py 2>&1 +sudo sed -i 's/autoblind/stateengine/g' ../../logics/*.py 2>&1 +} + +update_logics () { + if stringContain 'Darwin' $SCRIPTSYSTEM; then logics_mac; else logics_linux; fi +} + +rename_files () { +find ../../var/cache/ -type f -name '*autoblind*' -exec bash -c 'mv "$0" "${0/\autoblind/stateengine}"' {} \; +find ../../var/cache/ -type f -name '*autostate*' -exec bash -c 'mv "$0" "${0/\autostate/stateengine}"' {} \; +} + +cd $DIR +echo "Changed to directory: $DIR. Running on $SCRIPTSYSTEM" +echo "This script replaces as_* entries by se_* entries, autostate and autoblind entries by stateengine." + echo "Do you want to update all item yaml files?" + select rerun in "Update" "Skip"; do + case $rerun in + "Update" ) update_items;break;; + "Skip" ) echo "Skipping"; break;; + *) echo "Skipping"; break;; + esac + done + echo "Do you want to update your logics files and replace autostate/autoblind entries by stateengine?" + select rerun in "Update" "Skip"; do + case $rerun in + "Update" ) update_logics;break;; + "Skip" ) echo "Skipping"; break;; + *) echo "Skipping"; break;; + esac + done +echo "" +echo "This script renames all cache files including autoblind or autostate to stateengine" + echo "Do you want to rename cache files?" + select rerun in "Rename" "Skip"; do + case $rerun in + "Rename" ) rename_files;break;; + "Skip" ) echo "Skipping"; break;; + *) echo "Skipping"; break;; + esac + done diff --git a/stateengine/plugin.yaml b/stateengine/plugin.yaml new file mode 100755 index 000000000..01b008bcd --- /dev/null +++ b/stateengine/plugin.yaml @@ -0,0 +1,62 @@ +# Metadata for the StateEngine plugin +plugin: + # Global plugin attributes + type: system # plugin type (gateway, interface, protocol, system, web) + description: + de: 'Zustandsautomat für SmarthomeNG, ehemals AutoBlind' + en: 'Finite state machine for SmarthomeNG, previously known as AutoBlind' + mainainer: i-am-offline + documentation: https://github.com/i-am-offline/smarthome.plugin.autoblind/wiki + + version: 1.4.1 + sh_minversion: 1.4.1 + multi_instance: False + classname: StateEngine + +parameters: + # Definition of parameters to be configured in etc/plugin.yaml + startup_delay_default: + type: int + default: 10 + description: + de: 'Vorgabe für Verzögerung der ersten Zustandsermittlung beim Start' + en: 'Default delay for first state determination at startup' + valid_min: -1 + valid_max: 600 + + suspend_time_default: + type: int + default: 3600 + description: + de: 'Vorgabezeit zur Unterbrechung der automatischen Steuerung nach manuellen Aktionen' + en: 'Default suspend duration after manual actions' + valid_min: 1 + valid_max: 86400 + + log_level: + type: int + default: 0 + description: + de: 'Erweiterte Protokollierung: Loglevel (0: aus, 1: Info, 2: Debug)' + en: 'Extended Logging: Loglevel (0: off, 1: Info, 2: Debug)' + valid_list: + - 0 + - 1 + - 2 + + log_directory: + type: str + default: 'var/log/StateEngine/' + description: + de: 'Erweiterte Protokollierung: Verzeichnis für die Protokolldateien' + en: 'Extended Logging: Directory for log files' + + log_maxage: + type: int + default: 0 + description: + de: 'Erweiterte Protokollierung: Anzahl der Tage, nach der die Dateien im Verzeichnis für die Protokolldateien wieder gelöscht werden sollen' + en: 'Extended Logging: Number of days after which the files in the directory for log files should be deleted' + +item_attributes: + # Definition of item attributes defined by this plugin From 88da655fc286cdebe61a2b9ef5320794fb6e7b76 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sun, 30 Sep 2018 09:01:24 +0200 Subject: [PATCH 290/705] updated logger behaviour --- stateengine/README.md | 13 +++++-------- stateengine/StateEngineCliCommands.py | 17 ++++++++++------- stateengine/StateEngineDefaults.py | 3 +-- stateengine/StateEngineFunctions.py | 4 ++-- stateengine/__init__.py | 12 +++++++----- 5 files changed, 25 insertions(+), 24 deletions(-) diff --git a/stateengine/README.md b/stateengine/README.md index e78d08fd0..29e013975 100755 --- a/stateengine/README.md +++ b/stateengine/README.md @@ -12,8 +12,6 @@ The manual can be found in the Wiki at GitHub: Date: Sun, 30 Sep 2018 21:22:57 +0200 Subject: [PATCH 291/705] Fixed bug with infinite loop, changed logging entries --- uzsu/__init__.py | 17 +++++++---------- uzsu/webif/templates/index.html | 8 ++++---- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index b82a3b7e9..819679666 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -130,12 +130,15 @@ def run(self): cond2 = self._items[item].get('list') if cond1 and cond2: self._update_count['todo'] = self._update_count.get('todo') + 1 + self.logger.debug("Going to update {} items".format(self._update_count['todo'])) for item in self._items: cond1 = self._items[item].get('active') and self._items[item]['active'] is True cond2 = self._items[item].get('list') if cond1 and cond2: self._schedule(item, caller='run') + else: + self.logger.debug("Not scheduling item {}, cond1 {}, cond2 {}".format(item, cond1, cond2)) def stop(self): """ @@ -160,7 +163,7 @@ def _update_all_suns(self, caller=None): for item in self._items: success = self._update_sun(item) if success: - self.logger.debug('Updating item {}'.format(item)) + self.logger.debug('Updating sun info for item {}'.format(item)) item(self._items[item]) def _update_sun(self, item, caller=None): @@ -275,7 +278,7 @@ def _logics_planned(self, item=None): item, self._planned[item]['value'], self._planned[item]['next'])) return self._planned[item] except Exception: - self.logger.info("Nothing planned for item {}. {}".format(item, self._planned)) + self.logger.info("Nothing planned for item {}.".format(item)) return None def parse_item(self, item): @@ -511,7 +514,7 @@ def _schedule(self, item, caller=None): self.scheduler_trigger('uzsu_sunupdate', by='UZSU Plugin') self._update_count = {'done': 0, 'todo': 0} - def _set(self, **kwargs): + def _set(self, item=None, value=None, caller=None): """ This function sets the specific item @@ -519,14 +522,8 @@ def _set(self, **kwargs): :param value: value the item should be set to :param caller: if given it represents the callers name """ - item = kwargs['item'] - value = kwargs['value'] - try: - caller = kwargs['caller'] - except Exception: - caller = None _uzsuitem = self.itemsApi.return_item(self.get_iattr_value(item.conf, ITEM_TAG[0])) - _uzsuitem(value, caller='UZSU') + _uzsuitem(value, caller='UZSU Plugin') if not caller: self._schedule(item, caller='set') diff --git a/uzsu/webif/templates/index.html b/uzsu/webif/templates/index.html index e45f954f3..17070b5c8 100755 --- a/uzsu/webif/templates/index.html +++ b/uzsu/webif/templates/index.html @@ -75,8 +75,8 @@ {% for item in p.get_items() %} {% if p.has_iattr(item.conf, 'uzsu_item') %} - - {% if (p._logics_planned(item) == none and p._items[item]['active'] == True) or p._items[item]['interpolation']['itemtype'] == none %} + {% set planned = p._logics_planned(item) %} + {% if (p._items[item]['active'] == True and planned == none) or p._items[item]['interpolation']['itemtype'] == none %} {% set color = 'red' %} {% elif p._items[item]['active'] == True %} {% set color = 'green' %} @@ -93,8 +93,8 @@ {% endif %} {{ p._get_dependant(item) }}
- {% if p._logics_planned(item) != none %}{{ p._logics_planned(item) }}{% endif %} - {% if p._logics_planned(item) == none and p._items[item]['active'] == True %} + {% if planned != none %}{{ planned }}{% endif %} + {% if planned == none and p._items[item]['active'] == True %} {{ _('Aktives Item, keine (aktiven) Einträge!') }} {% endif %} From 87a38ed1b7e2d7df3b379bfa24a50d8e9149cb77 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Mon, 1 Oct 2018 19:59:32 +0200 Subject: [PATCH 292/705] fixed eternal loop --- uzsu/__init__.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 819679666..77299ecf7 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -596,8 +596,12 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): next = datetime.combine(dt.date(), parser.parse(time.strip()).time()).replace(tzinfo=self._timezone) if next and next.date() == dt.date(): self._itpl[next.timestamp() * 1000.0] = value - self.logger.debug("Return from rrule {}: {}, value {}.".format(timescan, next, value)) - return next, value + if next - timedelta(seconds=1) > datetime.now().replace(tzinfo=self._timezone): + self.logger.debug("Return from rrule {}: {}, value {}.".format(timescan, next, value)) + return next, value + else: + self.logger.debug("Not returning {} rrule {} because it's in the past.".format(timescan, next)) + return None, None if 'sun' in time: next = self._sun(datetime.combine(today, datetime.min.time()).replace( tzinfo=self._timezone), time, timescan) From f64cea86ddd15ef33cc4750a6e1651b39e90ef97 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Tue, 2 Oct 2018 21:59:17 +0200 Subject: [PATCH 293/705] added dict deepcopy for shng lower than 1.5a - Important fix --- uzsu/__init__.py | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 77299ecf7..5c29a936a 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -67,6 +67,7 @@ from unittest import mock from collections import OrderedDict from bin.smarthome import VERSION +import copy try: from scipy import interpolate @@ -177,7 +178,10 @@ def _update_sun(self, item, caller=None): """ try: self._uzsu_sun = self._create_sun() - self._items[item] = item() + if VERSION > '1.5.1': + self._items[item] = item() + else: + self._items[item] = copy.deepcopy(item()) _sunrise = self._uzsu_sun.rise() _sunset = self._uzsu_sun.set() if _sunrise.tzinfo == tzutc(): @@ -241,7 +245,10 @@ def _logics_activate(self, activevalue=None, item=None): else: self.logger.warning("Value to activate item '{}' has to be True or False".format(item)) if isinstance(activevalue, bool): - self._items[item] = item() + if VERSION > '1.5.1': + self._items[item] = item() + else: + self._items[item] = copy.deepcopy(item()) self._items[item]['active'] = activevalue self.logger.info("Item {} is set via logic to: {}".format(item, activevalue)) item(self._items[item], 'UZSU Plugin', 'logic') @@ -252,7 +259,10 @@ def _logics_interpolation(self, type=None, interval=5, backintime=0, item=None): if type is None: return self._items[item].get('interpolation') else: - self._items[item] = item() + if VERSION > '1.5.1': + self._items[item] = item() + else: + self._items[item] = copy.deepcopy(item()) self._items[item]['interpolation']['type'] = str(type).lower() self._items[item]['interpolation']['interval'] = int(interval) self._items[item]['interpolation']['initage'] = int(backintime) @@ -305,7 +315,10 @@ def parse_item(self, item): item.clear = functools.partial(self._logics_clear, item=item) item.planned = functools.partial(self._logics_planned, item=item) - self._items[item] = item() + if VERSION > '1.5.1': + self._items[item] = item() + else: + self._items[item] = copy.deepcopy(item()) try: self._items[item]['interpolation']['initialized'] = False item(self._items[item], 'USZU Plugin', 'init') @@ -354,7 +367,10 @@ def update_item(self, item, caller=None, source=None, dest=None): :param source: if given it represents the source :param dest: if given it represents the dest """ - self._items[item] = item() + if VERSION > '1.5.1': + self._items[item] = item() + else: + self._items[item] = copy.deepcopy(item()) if self._items[item].get('list'): for entry in self._items[item]['list']: if entry['rrule'] == '': From 5ac3ded9bfa946dab83b6e2a9d66a67c1375355a Mon Sep 17 00:00:00 2001 From: pfischi Date: Wed, 3 Oct 2018 13:26:33 +0200 Subject: [PATCH 294/705] tts token generator updated --- sonos/tts.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/sonos/tts.py b/sonos/tts.py index b5c1afc16..7328d6f3d 100644 --- a/sonos/tts.py +++ b/sonos/tts.py @@ -51,22 +51,26 @@ def _get_token_key(self): if self.token_key is not None: return self.token_key - timestamp = calendar.timegm(time.gmtime()) - hours = int(math.floor(timestamp / 3600)) - response = requests.get("https://translate.google.com/") line = response.text.split('\n')[-1] - tkk_expr = re.search(".*?(TKK=.*?;)W.*?", line).group(1) - a = re.search("a\\\\x3d(-?\d+);", tkk_expr).group(1) - b = re.search("b\\\\x3d(-?\d+);", tkk_expr).group(1) - result = str(hours) + "." + str(int(a) + int(b)) + try: + # Grab the token directly if already generated by function call + result = re.search("\d{6}\.[0-9]+", tkk_expr).group(0) + except AttributeError: + # Generate the token using algorithm + timestamp = calendar.timegm(time.gmtime()) + hours = int(math.floor(timestamp / 3600)) + a = re.search("a\\\\x3d(-?\d+);", tkk_expr).group(1) + b = re.search("b\\\\x3d(-?\d+);", tkk_expr).group(1) + + result = str(hours) + "." + str(int(a) + int(b)) + self.token_key = result return result """ Functions used by the token calculation algorithm """ - def _rshift(self, val, n): return val >> n if val >= 0 else (val + 0x100000000) >> n From 27927ed1acebd5e0445504ddb7bb8cac193d2cd9 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Wed, 3 Oct 2018 14:44:32 +0200 Subject: [PATCH 295/705] added debug entry, fixed typos --- uzsu/__init__.py | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 5c29a936a..cb076aaed 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -126,12 +126,12 @@ def run(self): for item in self._items: self._items[item]['interpolation']['itemtype'] = self._add_type(item) - item(self._items[item], 'USZU Plugin', 'itemtype') + item(self._items[item], 'UZSU Plugin', 'itemtype') cond1 = self._items[item].get('active') and self._items[item]['active'] is True cond2 = self._items[item].get('list') if cond1 and cond2: self._update_count['todo'] = self._update_count.get('todo') + 1 - self.logger.debug("Going to update {} items".format(self._update_count['todo'])) + self.logger.debug("Going to update {} items: {}".format(self._update_count['todo'], list(self._items.keys()))) for item in self._items: cond1 = self._items[item].get('active') and self._items[item]['active'] is True @@ -209,7 +209,7 @@ def _update_suncalc(self, item, entry, entryindex, entryvalue): self.logger.debug("Updated calculated time for item {} entry {} with value {}.".format( item, self._items[item]['list'][entryindex], entryvalue)) self._items[item]['list'][entryindex]['calculated'] = entryvalue - item(self._items[item], 'USZU Plugin', 'update_sun') + item(self._items[item], 'UZSU Plugin', 'update_sun') else: self.logger.debug("Sun calculation {} entry not updated for item {} with value {}".format( entryvalue, item, entry.get('calculated'))) @@ -321,11 +321,11 @@ def parse_item(self, item): self._items[item] = copy.deepcopy(item()) try: self._items[item]['interpolation']['initialized'] = False - item(self._items[item], 'USZU Plugin', 'init') + item(self._items[item], 'UZSU Plugin', 'init') except Exception: self._items[item]['interpolation'] = {} self._items[item]['interpolation']['initialized'] = False - item(self._items[item], 'USZU Plugin', 'init') + item(self._items[item], 'UZSU Plugin', 'init') self.logger.debug('Dict for item {} is: {}'.format(item, self._items[item])) return self.update_item @@ -355,7 +355,7 @@ def _remove_dupes(self, item): self.logger.warning("Set old entry for item '{}' at {} with value {} to inactive" " because newer active entry with value {} found.".format( item, time, oldvalue, newvalue)) - item(self._items[item], 'USZU Plugin', 'update') + item(self._items[item], 'UZSU Plugin', 'update') def update_item(self, item, caller=None, source=None, dest=None): """ @@ -371,6 +371,8 @@ def update_item(self, item, caller=None, source=None, dest=None): self._items[item] = item() else: self._items[item] = copy.deepcopy(item()) + self.logger.debug('Update Item {}, Caller {}, Source {}, Dest {}.'.format( + item, caller, source, dest)) if self._items[item].get('list'): for entry in self._items[item]['list']: if entry['rrule'] == '': @@ -378,16 +380,13 @@ def update_item(self, item, caller=None, source=None, dest=None): _index = self._items[item]['list'].index(entry) self._items[item]['list'][_index]['rrule'] = 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU' self.logger.debug("Updated rrule for item: {}".format(item)) - item(self._items[item], 'USZU Plugin', 'create_rrule') + item(self._items[item], 'UZSU Plugin', 'create_rrule') except Exception as err: self.logger.warning("Error creating rrule: {}".format(err)) - - self.logger.debug('Update Item {}, Caller {}, Source {}, Dest {}.'.format( - item, caller, source, dest)) # Removing Duplicates - if self._remove_duplicates is True and self._items[item].get('list') and not caller == 'USZU Plugin': + if self._remove_duplicates is True and self._items[item].get('list') and not caller == 'UZSU Plugin': self._remove_dupes(item) - if not caller == 'USZU Plugin': + if not caller == 'UZSU Plugin': self._schedule(item, caller='update') def _schedule(self, item, caller=None): @@ -425,7 +424,7 @@ def _schedule(self, item, caller=None): if cond1 and cond2: next = prev value = prev_value - item(self._items[item], 'USZU Plugin', 'schedule') + item(self._items[item], 'UZSU Plugin', 'schedule') if next is not None: self.logger.debug("uzsu active entry for item {} with datetime {}, value {}" " and tzinfo {}".format(item, next, value, next.tzinfo)) @@ -473,7 +472,7 @@ def _schedule(self, item, caller=None): self.logger.info("Looking if there was a value set after {} for item {}".format( _timediff, item)) self._items[item]['interpolation']['initialized'] = True - item(self._items[item], 'USZU Plugin', 'init') + item(self._items[item], 'UZSU Plugin', 'init') if cond1 and not cond2 and cond3: self._set(item=item, value=_initvalue, caller='scheduler') self.logger.info("Updated item {} on startup with value {} from time {}".format( @@ -487,7 +486,7 @@ def _schedule(self, item, caller=None): _interpolation, _interval)) elif cond2 and _itemtype not in ['num']: self.logger.warning("Interpolation is set to {} but type of item is {}." - " Ignoring interpolation and setting USZU interpolation to none.".format( + " Ignoring interpolation and setting UZSU interpolation to none.".format( _interpolation, _itemtype)) _reset_interpolation = True elif _interpolation.lower() == 'cubic' and _interval > 0: @@ -519,7 +518,7 @@ def _schedule(self, item, caller=None): " to not enough values set in the UZSU.".format(_value, item)) if _reset_interpolation is True: self._items[item]['interpolation']['type'] = 'none' - item(self._items[item], 'USZU Plugin', 'reset_interpolation') + item(self._items[item], 'UZSU Plugin', 'reset_interpolation') else: self.logger.debug("will add scheduler named uzsu_{} with datetime {} and tzinfo {}" " and value {}".format(item, _next, _next.tzinfo, _value)) From 62b82a4a404fae036f08f8d48e4032d95d1227a3 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Fri, 5 Oct 2018 15:29:12 +0200 Subject: [PATCH 296/705] remove scheduler on logics deactivation --- uzsu/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index cb076aaed..9606ddbd2 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -254,6 +254,8 @@ def _logics_activate(self, activevalue=None, item=None): item(self._items[item], 'UZSU Plugin', 'logic') if activevalue is None: return self._items[item].get('active') + elif activevalue is True: + self.scheduler_remove('uzsu_{}'.format(item)) def _logics_interpolation(self, type=None, interval=5, backintime=0, item=None): if type is None: From cecba5cb5d160724efba96fee07bd416fef17251 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Fri, 5 Oct 2018 18:03:18 +0200 Subject: [PATCH 297/705] fixed activation-logic, interpolation-reset and hopefully wrong info in webif for deactivated items --- uzsu/__init__.py | 42 ++++++++++++++++++--------------- uzsu/webif/templates/index.html | 2 +- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 9606ddbd2..5d01cbd50 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -254,8 +254,6 @@ def _logics_activate(self, activevalue=None, item=None): item(self._items[item], 'UZSU Plugin', 'logic') if activevalue is None: return self._items[item].get('active') - elif activevalue is True: - self.scheduler_remove('uzsu_{}'.format(item)) def _logics_interpolation(self, type=None, interval=5, backintime=0, item=None): if type is None: @@ -285,11 +283,14 @@ def _logics_clear(self, clear=False, item=None): item(self._items[item], 'UZSU Plugin', 'clear') def _logics_planned(self, item=None): - try: + if self._planned.get(item) not in [None, {}, 'deactivated']: self.logger.info("Item {} is going to be set to {} at {}".format( item, self._planned[item]['value'], self._planned[item]['next'])) return self._planned[item] - except Exception: + elif self._planned.get(item) == 'deactivated': + self.logger.info("Nothing planned for item {} because UZSU is not active.".format(item)) + return 'deactivated' + else: self.logger.info("Nothing planned for item {}.".format(item)) return None @@ -373,8 +374,9 @@ def update_item(self, item, caller=None, source=None, dest=None): self._items[item] = item() else: self._items[item] = copy.deepcopy(item()) - self.logger.debug('Update Item {}, Caller {}, Source {}, Dest {}.'.format( - item, caller, source, dest)) + cond = (not caller == 'UZSU Plugin') or source == 'logic' + self.logger.debug('Update Item {}, Caller {}, Source {}, Dest {}. Will update: {}'.format( + item, caller, source, dest, cond)) if self._items[item].get('list'): for entry in self._items[item]['list']: if entry['rrule'] == '': @@ -386,9 +388,9 @@ def update_item(self, item, caller=None, source=None, dest=None): except Exception as err: self.logger.warning("Error creating rrule: {}".format(err)) # Removing Duplicates - if self._remove_duplicates is True and self._items[item].get('list') and not caller == 'UZSU Plugin': + if self._remove_duplicates is True and self._items[item].get('list') and cond: self._remove_dupes(item) - if not caller == 'UZSU Plugin': + if cond: self._schedule(item, caller='update') def _schedule(self, item, caller=None): @@ -410,10 +412,12 @@ def _schedule(self, item, caller=None): if not self._items[item]['interpolation'].get('itemtype'): self.logger.error("item '{}' to be set by uzsu does not exist.".format( self.get_iattr_value(item.conf, ITEM_TAG[0]))) - elif not self._items[item].get('list'): - self.logger.warning("uzsu item '{}' is active but has no entries.".format( - item)) - else: + elif self._items[item].get('list') is None: + self.logger.warning("uzsu item '{}' is active but has no entries.".format(item)) + self._planned.update({item: None}) + elif self._items[item].get('active') is False: + self._planned.update({item: 'deactivated'}) + elif self._items[item].get('active') is True: self._itpl.clear() for i, entry in enumerate(self._items[item]['list']): next, value = self._get_time(entry, 'next', item, i) @@ -441,7 +445,7 @@ def _schedule(self, item, caller=None): else: self.logger.debug("uzsu active entry for item {} keep {}, value {} and tzinfo {}".format( item, _next, _value, _next.tzinfo)) - if _next and _value is not None and 'active' in self._items[item] and self._items[item]['active'] is True: + if _next and _value is not None and self._items[item].get('active') is True: _reset_interpolation = False _interval = self._items[item]['interpolation'].get('interval') _interval = 5 if not _interval else int(_interval) @@ -521,12 +525,12 @@ def _schedule(self, item, caller=None): if _reset_interpolation is True: self._items[item]['interpolation']['type'] = 'none' item(self._items[item], 'UZSU Plugin', 'reset_interpolation') - else: - self.logger.debug("will add scheduler named uzsu_{} with datetime {} and tzinfo {}" - " and value {}".format(item, _next, _next.tzinfo, _value)) - self._planned[item] = {'value': _value, 'next': _next.strftime('%Y-%m-%d %H:%M')} - self._update_count['done'] = self._update_count.get('done') + 1 - self.scheduler_add('uzsu_{}'.format(item), self._set, value={'item': item, 'value': _value}, next=_next) + + self.logger.debug("will add scheduler named uzsu_{} with datetime {} and tzinfo {}" + " and value {}".format(item, _next, _next.tzinfo, _value)) + self._planned.update({item: {'value': _value, 'next': _next.strftime('%Y-%m-%d %H:%M')}}) + self._update_count['done'] = self._update_count.get('done') + 1 + self.scheduler_add('uzsu_{}'.format(item), self._set, value={'item': item, 'value': _value}, next=_next) if self._update_count.get('done') == self._update_count.get('todo'): self.scheduler_trigger('uzsu_sunupdate', by='UZSU Plugin') self._update_count = {'done': 0, 'todo': 0} diff --git a/uzsu/webif/templates/index.html b/uzsu/webif/templates/index.html index 17070b5c8..7310e90e4 100755 --- a/uzsu/webif/templates/index.html +++ b/uzsu/webif/templates/index.html @@ -93,7 +93,7 @@ {% endif %} {{ p._get_dependant(item) }}
- {% if planned != none %}{{ planned }}{% endif %} + {% if planned != none and planned != 'deactivated' %}{{ planned }}{% endif %} {% if planned == none and p._items[item]['active'] == True %} {{ _('Aktives Item, keine (aktiven) Einträge!') }} {% endif %} From 40213fb4a0f997202bd0dc35d7adb04cd3963609 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Fri, 5 Oct 2018 23:12:39 +0200 Subject: [PATCH 298/705] (re)fixed full value evaluation for all items --- uzsu/__init__.py | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 5d01cbd50..9bf743e25 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -421,15 +421,7 @@ def _schedule(self, item, caller=None): self._itpl.clear() for i, entry in enumerate(self._items[item]['list']): next, value = self._get_time(entry, 'next', item, i) - prev, prev_value = self._get_time(entry, 'previous', item) - try: - cond1 = prev > datetime.now(self._timezone) - cond2 = prev < next - except Exception as err: - cond1 = cond2 = False - if cond1 and cond2: - next = prev - value = prev_value + self._get_time(entry, 'previous', item) item(self._items[item], 'UZSU Plugin', 'schedule') if next is not None: self.logger.debug("uzsu active entry for item {} with datetime {}, value {}" @@ -531,7 +523,7 @@ def _schedule(self, item, caller=None): self._planned.update({item: {'value': _value, 'next': _next.strftime('%Y-%m-%d %H:%M')}}) self._update_count['done'] = self._update_count.get('done') + 1 self.scheduler_add('uzsu_{}'.format(item), self._set, value={'item': item, 'value': _value}, next=_next) - if self._update_count.get('done') == self._update_count.get('todo'): + if self._update_count.get('done') == self._update_count.get('todo'): self.scheduler_trigger('uzsu_sunupdate', by='UZSU Plugin') self._update_count = {'done': 0, 'todo': 0} @@ -622,7 +614,6 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): return next, value else: self.logger.debug("Not returning {} rrule {} because it's in the past.".format(timescan, next)) - return None, None if 'sun' in time: next = self._sun(datetime.combine(today, datetime.min.time()).replace( tzinfo=self._timezone), time, timescan) From 876a5e2afdb83480b79232b534bc8101f3003264 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Fri, 5 Oct 2018 23:29:45 +0200 Subject: [PATCH 299/705] fixed deepcopy for 1.5.1master --- uzsu/__init__.py | 10 +++++----- uzsu/plugin.yaml | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 9bf743e25..e1d246bb7 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -178,7 +178,7 @@ def _update_sun(self, item, caller=None): """ try: self._uzsu_sun = self._create_sun() - if VERSION > '1.5.1': + if '.'.join(VERSION.split('.', 3)[:3]) > '1.5.1': self._items[item] = item() else: self._items[item] = copy.deepcopy(item()) @@ -245,7 +245,7 @@ def _logics_activate(self, activevalue=None, item=None): else: self.logger.warning("Value to activate item '{}' has to be True or False".format(item)) if isinstance(activevalue, bool): - if VERSION > '1.5.1': + if '.'.join(VERSION.split('.', 3)[:3]) > '1.5.1': self._items[item] = item() else: self._items[item] = copy.deepcopy(item()) @@ -259,7 +259,7 @@ def _logics_interpolation(self, type=None, interval=5, backintime=0, item=None): if type is None: return self._items[item].get('interpolation') else: - if VERSION > '1.5.1': + if '.'.join(VERSION.split('.', 3)[:3]) > '1.5.1': self._items[item] = item() else: self._items[item] = copy.deepcopy(item()) @@ -318,7 +318,7 @@ def parse_item(self, item): item.clear = functools.partial(self._logics_clear, item=item) item.planned = functools.partial(self._logics_planned, item=item) - if VERSION > '1.5.1': + if '.'.join(VERSION.split('.', 3)[:3]) > '1.5.1': self._items[item] = item() else: self._items[item] = copy.deepcopy(item()) @@ -370,7 +370,7 @@ def update_item(self, item, caller=None, source=None, dest=None): :param source: if given it represents the source :param dest: if given it represents the dest """ - if VERSION > '1.5.1': + if '.'.join(VERSION.split('.', 3)[:3]) > '1.5.1': self._items[item] = item() else: self._items[item] = copy.deepcopy(item()) diff --git a/uzsu/plugin.yaml b/uzsu/plugin.yaml index 99ac5ce93..ae7971e10 100755 --- a/uzsu/plugin.yaml +++ b/uzsu/plugin.yaml @@ -5,8 +5,8 @@ plugin: description: # Alternative: description in multiple languages de: 'Universelle Zeitschaltuhr' en: 'Universal time switch' - maintainer: cmalo (Niko Will) - tester: Sandman60, cmalo, onkelandy + maintainer: onkelandy + tester: Sandman60, cmalo, schuma # keywords: iot xyz documentation: https://github.com/smarthomeNG/smarthome/wiki/UZSU-%28Universelle-Zeitschaltuhr%29 # url of documentation (wiki) page From af7524eb2710d7f10fa3dcbef950af69258e7022 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 6 Oct 2018 00:34:29 +0200 Subject: [PATCH 300/705] improved webif status info --- uzsu/__init__.py | 15 ++++++++------- uzsu/webif/templates/index.html | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index e1d246bb7..1311f0ac7 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -283,13 +283,10 @@ def _logics_clear(self, clear=False, item=None): item(self._items[item], 'UZSU Plugin', 'clear') def _logics_planned(self, item=None): - if self._planned.get(item) not in [None, {}, 'deactivated']: + if self._planned.get(item) not in [None, {}] and self._items[item].get('active') is True: self.logger.info("Item {} is going to be set to {} at {}".format( item, self._planned[item]['value'], self._planned[item]['next'])) return self._planned[item] - elif self._planned.get(item) == 'deactivated': - self.logger.info("Nothing planned for item {} because UZSU is not active.".format(item)) - return 'deactivated' else: self.logger.info("Nothing planned for item {}.".format(item)) return None @@ -378,8 +375,11 @@ def update_item(self, item, caller=None, source=None, dest=None): self.logger.debug('Update Item {}, Caller {}, Source {}, Dest {}. Will update: {}'.format( item, caller, source, dest, cond)) if self._items[item].get('list'): + _inactive = 0 for entry in self._items[item]['list']: - if entry['rrule'] == '': + if entry.get('active') == False: + _inactive += 1 + if entry.get('rrule') == '': try: _index = self._items[item]['list'].index(entry) self._items[item]['list'][_index]['rrule'] = 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU' @@ -387,6 +387,9 @@ def update_item(self, item, caller=None, source=None, dest=None): item(self._items[item], 'UZSU Plugin', 'create_rrule') except Exception as err: self.logger.warning("Error creating rrule: {}".format(err)) + self.logger.error("inactive: {}, length: {}".format(_inactive, len(self._items[item]['list']))) + if _inactive >= len(self._items[item]['list']): + self._planned.update({item: None}) # Removing Duplicates if self._remove_duplicates is True and self._items[item].get('list') and cond: self._remove_dupes(item) @@ -415,8 +418,6 @@ def _schedule(self, item, caller=None): elif self._items[item].get('list') is None: self.logger.warning("uzsu item '{}' is active but has no entries.".format(item)) self._planned.update({item: None}) - elif self._items[item].get('active') is False: - self._planned.update({item: 'deactivated'}) elif self._items[item].get('active') is True: self._itpl.clear() for i, entry in enumerate(self._items[item]['list']): diff --git a/uzsu/webif/templates/index.html b/uzsu/webif/templates/index.html index 7310e90e4..17070b5c8 100755 --- a/uzsu/webif/templates/index.html +++ b/uzsu/webif/templates/index.html @@ -93,7 +93,7 @@ {% endif %} {{ p._get_dependant(item) }}
- {% if planned != none and planned != 'deactivated' %}{{ planned }}{% endif %} + {% if planned != none %}{{ planned }}{% endif %} {% if planned == none and p._items[item]['active'] == True %} {{ _('Aktives Item, keine (aktiven) Einträge!') }} {% endif %} From 6ceaf674eb47d22944eeea73c7e48512ff0b1116 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 6 Oct 2018 12:39:53 +0200 Subject: [PATCH 301/705] fixed newly introduced error concerning inactive items in the webif, updated README --- uzsu/README.md | 21 +++++++++++++++++---- uzsu/__init__.py | 5 ++--- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/uzsu/README.md b/uzsu/README.md index 7399b9390..c24768d03 100755 --- a/uzsu/README.md +++ b/uzsu/README.md @@ -12,6 +12,19 @@ pip3 install scipy On Raspberry debian stretch you also have to run: apt-get install libatlas-base-dev +##Changelog +### v1.5.2 +Make the plugin compatible with the master 1.5.1 version +Correctly write cache file when changing the uzsu item +Automatically activate all days of the week if no day is set via Visu +Variety of bug fixes and optimizations + +### v1.4.1 - 1.5.1 +Added "back in time" feature to re-trigger missed uzsu evaluations on smarthomeng startup +Added interpolation feature: the UZSU can now be used for smooth transitions of values (e.g. for light dimming, etc.) +Added item functions to (de)activate, change interpolation and query some settings from the uzsu item via logic +Fixed uzsu evaluation for entries without an rrule setting (day of week) + ## Configuration ### plugin.yaml @@ -43,7 +56,7 @@ someroom: cache: 'True' ``` -If you specify the ``cache: True`` as well, then your switching entries will be there even if you restart smarthome.py. +If you specify the ``cache: True`` as well, then your switching entries will be there even if you restart smarthome.py (sometimes didn't work correctly with plugin version < 1.5.2). ## Item Data Format @@ -72,7 +85,7 @@ Each UZSU item is of type list. Each list entry has to be a dict with specific k ## Additional item functions -You can use these function in logics to query or set yout uzsu item: +You can use these function in logics to query or set your uzsu item: ``` # query the next scheduled value and time @@ -99,7 +112,7 @@ sh.eg.wohnen.kugellampe.uzsu.clear(True) ## Example -Activates the light every other day at 16:30 and deactivates it at 17:30 for five times: +Activates the light every other day at 16:30 and deactivates it at 17:30 for five times. Between the UZSU entries the values are interpolated every 5 minutes. ```python sh.eg.wohnen.kugellampe.uzsu({'active':True, 'list':[ @@ -111,4 +124,4 @@ sh.eg.wohnen.kugellampe.uzsu({'active':True, 'list':[ ## SmartVISU -There is a widget available which gives an interface to the UZSU. The structure has changed from SmartVISU 2.8 to 2.9 slightly. Interpolation feature is supported in 2.9 only. Please consult the corresponding forum. +There is a widget available which gives an interface to the UZSU. The structure has changed from SmartVISU 2.8 to 2.9 slightly. Interpolation feature is supported in 2.9 only as a popup and graph. Please consult the corresponding forum. diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 1311f0ac7..414b89c38 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -387,9 +387,8 @@ def update_item(self, item, caller=None, source=None, dest=None): item(self._items[item], 'UZSU Plugin', 'create_rrule') except Exception as err: self.logger.warning("Error creating rrule: {}".format(err)) - self.logger.error("inactive: {}, length: {}".format(_inactive, len(self._items[item]['list']))) - if _inactive >= len(self._items[item]['list']): - self._planned.update({item: None}) + if _inactive >= len(self._items[item]['list']): + self._planned.update({item: None}) # Removing Duplicates if self._remove_duplicates is True and self._items[item].get('list') and cond: self._remove_dupes(item) From 22cd73e510c4d3ee4e0b666873cccb59fc309284 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 6 Oct 2018 12:41:44 +0200 Subject: [PATCH 302/705] fix readme header --- uzsu/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/uzsu/README.md b/uzsu/README.md index c24768d03..339745ed4 100755 --- a/uzsu/README.md +++ b/uzsu/README.md @@ -13,6 +13,7 @@ On Raspberry debian stretch you also have to run: apt-get install libatlas-base-dev ##Changelog + ### v1.5.2 Make the plugin compatible with the master 1.5.1 version Correctly write cache file when changing the uzsu item From 7442bc2f08a71003ba57ae9f0b7d89182c556ac1 Mon Sep 17 00:00:00 2001 From: onkelandy Date: Sat, 6 Oct 2018 12:42:19 +0200 Subject: [PATCH 303/705] Update README.md --- uzsu/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uzsu/README.md b/uzsu/README.md index 339745ed4..11681aca3 100755 --- a/uzsu/README.md +++ b/uzsu/README.md @@ -12,7 +12,7 @@ pip3 install scipy On Raspberry debian stretch you also have to run: apt-get install libatlas-base-dev -##Changelog +## Changelog ### v1.5.2 Make the plugin compatible with the master 1.5.1 version From 52b7551a56cc6d9f531864c1ef570513f4307e06 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 6 Oct 2018 12:43:06 +0200 Subject: [PATCH 304/705] fix readme header --- uzsu/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uzsu/README.md b/uzsu/README.md index 339745ed4..11681aca3 100755 --- a/uzsu/README.md +++ b/uzsu/README.md @@ -12,7 +12,7 @@ pip3 install scipy On Raspberry debian stretch you also have to run: apt-get install libatlas-base-dev -##Changelog +## Changelog ### v1.5.2 Make the plugin compatible with the master 1.5.1 version From 6c9ea51667b958409479f6faca271ea9628ad36b Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 6 Oct 2018 12:51:36 +0200 Subject: [PATCH 305/705] updated README --- uzsu/README.md | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/uzsu/README.md b/uzsu/README.md index 11681aca3..11ba08015 100755 --- a/uzsu/README.md +++ b/uzsu/README.md @@ -15,16 +15,19 @@ apt-get install libatlas-base-dev ## Changelog ### v1.5.2 -Make the plugin compatible with the master 1.5.1 version -Correctly write cache file when changing the uzsu item -Automatically activate all days of the week if no day is set via Visu -Variety of bug fixes and optimizations +* Make the plugin compatible with the master 1.5.1 version +* Correctly write cache file when changing the uzsu item +* Automatically activate all days of the week if no day is set via Visu +* Variety of bug fixes and optimizations +* Corrected information on web interface concerning (in)active entries ### v1.4.1 - 1.5.1 -Added "back in time" feature to re-trigger missed uzsu evaluations on smarthomeng startup -Added interpolation feature: the UZSU can now be used for smooth transitions of values (e.g. for light dimming, etc.) -Added item functions to (de)activate, change interpolation and query some settings from the uzsu item via logic -Fixed uzsu evaluation for entries without an rrule setting (day of week) +* Added a web interface for easier debugging +* Added "back in time" feature to re-trigger missed uzsu evaluations on smarthomeng startup +* Added interpolation feature: the UZSU can now be used for smooth transitions of values (e.g. for light dimming, etc.) +* Added item functions to (de)activate, change interpolation and query some settings from the uzsu item via logic +* Fixed uzsu evaluation for entries without an rrule setting (day of week) +* Improved error handling (detecting wrong items to be set by UZSU, empty entries, etc.) ## Configuration @@ -106,10 +109,17 @@ sh.eg.wohnen.kugellampe.uzsu.activate(type='linear/none/cubic', interval=5, back # clear your settings of the uzsu item. BE CAREFUL! sh.eg.wohnen.kugellampe.uzsu.clear(True) - - ``` +## Web Interface +The web interface gives you the following information: +* list of all UZSU items +* items to be set as well as their item type (bool, string, num, etc.) +* current value of the item to be set as well as the planned next value + timestamp of that scheduling +* interpolation type and interval +* back in time value +* show the complete dictionary entry of an UZSU entry as a popup by clicking on it +* color coded info: gray = inacitve, green = active, red = problem ## Example From 1052d3b4aa272017682d630aa7e40ff243bca6f8 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 6 Oct 2018 12:58:47 +0200 Subject: [PATCH 306/705] Mini-Update --- uzsu/README.md | 1 + uzsu/__init__.py | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/uzsu/README.md b/uzsu/README.md index 11ba08015..03d00d350 100755 --- a/uzsu/README.md +++ b/uzsu/README.md @@ -27,6 +27,7 @@ apt-get install libatlas-base-dev * Added interpolation feature: the UZSU can now be used for smooth transitions of values (e.g. for light dimming, etc.) * Added item functions to (de)activate, change interpolation and query some settings from the uzsu item via logic * Fixed uzsu evaluation for entries without an rrule setting (day of week) +* Automatic deactivating older entries when new entry for exactly the same time (and day) is created (only works with specific VISU widgets) * Improved error handling (detecting wrong items to be set by UZSU, empty entries, etc.) ## Configuration diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 414b89c38..15b546fa8 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -377,7 +377,7 @@ def update_item(self, item, caller=None, source=None, dest=None): if self._items[item].get('list'): _inactive = 0 for entry in self._items[item]['list']: - if entry.get('active') == False: + if entry.get('active') is False: _inactive += 1 if entry.get('rrule') == '': try: @@ -792,7 +792,6 @@ def _sun(self, dt, tstr, timescan): return elif smin is None: dmax = next_time - min = max = 0 if dmin is not None and dmax is not None and dmin > dmax: self.logger.error("Wrong times: the earliest time should be smaller than the " "latest time in {}".format(tstr)) From b65f01a4fd2e4179c748c6a84105d7c57627e64a Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 6 Oct 2018 14:21:15 +0200 Subject: [PATCH 307/705] Added documentation via web interface from i-am-offlines Wiki --- stateengine/README.md | 21 +- stateengine/__init__.py | 150 +++- stateengine/webif/static/img/plugin_logo.png | Bin 0 -> 21516 bytes stateengine/webif/static/img/plugin_logo.tif | Bin 0 -> 143044 bytes stateengine/webif/static/img/readme.txt | 6 + stateengine/webif/templates/doku1.html | 123 ++++ stateengine/webif/templates/doku10.html | 128 ++++ stateengine/webif/templates/doku11.html | 88 +++ stateengine/webif/templates/doku12.html | 121 ++++ stateengine/webif/templates/doku13.html | 304 ++++++++ stateengine/webif/templates/doku14.html | 85 +++ stateengine/webif/templates/doku15.html | 687 +++++++++++++++++++ stateengine/webif/templates/doku2.html | 132 ++++ stateengine/webif/templates/doku3.html | 203 ++++++ stateengine/webif/templates/doku4.html | 185 +++++ stateengine/webif/templates/doku5.html | 266 +++++++ stateengine/webif/templates/doku6.html | 157 +++++ stateengine/webif/templates/doku7.html | 260 +++++++ stateengine/webif/templates/doku8.html | 234 +++++++ stateengine/webif/templates/doku9.html | 146 ++++ stateengine/webif/templates/index.html | 123 ++++ 21 files changed, 3377 insertions(+), 42 deletions(-) create mode 100755 stateengine/webif/static/img/plugin_logo.png create mode 100644 stateengine/webif/static/img/plugin_logo.tif create mode 100755 stateengine/webif/static/img/readme.txt create mode 100755 stateengine/webif/templates/doku1.html create mode 100755 stateengine/webif/templates/doku10.html create mode 100755 stateengine/webif/templates/doku11.html create mode 100755 stateengine/webif/templates/doku12.html create mode 100755 stateengine/webif/templates/doku13.html create mode 100755 stateengine/webif/templates/doku14.html create mode 100755 stateengine/webif/templates/doku15.html create mode 100755 stateengine/webif/templates/doku2.html create mode 100755 stateengine/webif/templates/doku3.html create mode 100755 stateengine/webif/templates/doku4.html create mode 100755 stateengine/webif/templates/doku5.html create mode 100755 stateengine/webif/templates/doku6.html create mode 100755 stateengine/webif/templates/doku7.html create mode 100755 stateengine/webif/templates/doku8.html create mode 100755 stateengine/webif/templates/doku9.html create mode 100755 stateengine/webif/templates/index.html diff --git a/stateengine/README.md b/stateengine/README.md index 29e013975..f0ccd0d0d 100755 --- a/stateengine/README.md +++ b/stateengine/README.md @@ -1,7 +1,7 @@ -#StateEngine +# StateEngine Created by i-am-offline -##Description +## Description Finite state machine plugin for smarthomeNG, previously known as AutoBlind ## Support @@ -18,16 +18,17 @@ See the [manual at GitHub](https://github.com/i-am-offline/smarthome.plugin.auto ### items.yaml See the [manual at GitHub](https://github.com/i-am-offline/smarthome.plugin.autoblind/wiki) -##Changelog +## Changelog ### v1.4.1 -Added to official develop repository (onkelandy) -Renamed to StateEngine (onkelandy) -Fix compatibility of logic trigger for SmarthomeNG 1.4+ (onkelandy) -Changed state condition evaluation to OrderedDict to keep original order (onkelandy) -Added additional option for manual item called "manual_on" to figure out if item WAS trigger by specific KNX GA (onkelandy) +* Added to official develop repository (onkelandy) +* Renamed to StateEngine (onkelandy) +* Fixed compatibility of logic trigger for SmarthomeNG 1.4+ (onkelandy) +* Changed state condition evaluation to OrderedDict to keep original order (onkelandy) +* Added additional option for manual item called "manual_on" to figure out if item WAS trigger by specific KNX GA (onkelandy) +* Added Webinterface with documentation (german) ### v1.4.0 -Make compatible with SmarthomeNG 1.4+ (i-am-offline) +* Make compatible with SmarthomeNG 1.4+ (i-am-offline) ### before v1.4.0 -Constant improvements to infinite state machine (complete plugin development by i-am-offline) +* Constant improvements to infinite state machine (complete plugin development by i-am-offline) diff --git a/stateengine/__init__.py b/stateengine/__init__.py index da728781f..e654b0cb6 100755 --- a/stateengine/__init__.py +++ b/stateengine/__init__.py @@ -27,7 +27,7 @@ from . import StateEngineFunctions import logging import os -from lib.model.smartplugin import SmartPlugin +from lib.model.smartplugin import * from bin.smarthome import VERSION @@ -43,37 +43,41 @@ def __init__(self, sh): self.__items = {} self.alive = False self.__cli = None - - log_level = self.get_parameter_value("log_level") - log_directory = self.get_parameter_value("log_directory") - self.logger.info("Init StateEngine (log_level={0}, log_directory={1})".format(log_level, log_directory)) - - StateEngineDefaults.startup_delay = self.get_parameter_value("startup_delay_default") - StateEngineDefaults.suspend_time = self.get_parameter_value("suspend_time_default") - StateEngineDefaults.write_to_log(self.logger) - - StateEngineCurrent.init(self.get_sh()) - - if log_level > 0: - if log_directory[0] != "/": - base = self.get_sh().get_basedir() - if base[-1] != "/": - base += "/" - log_directory = base + log_directory - if not os.path.exists(log_directory): - os.makedirs(log_directory) - SeLogger.set_loglevel(log_level) - SeLogger.set_logdirectory(log_directory) - text = "StateEngine extended logging is active. Logging to '{0}' with loglevel {1}." - self.logger.info(text.format(log_directory, log_level)) - log_maxage = self.get_parameter_value("log_maxage") - if log_level > 0 and log_maxage > 0: - self.logger.info("StateEngine extended log files will be deleted after {0} days.".format(log_maxage)) - SeLogger.set_logmaxage(log_maxage) - cron = ['init', '30 0 * *'] - self.scheduler_add('StateEngine: Remove old logfiles', SeLogger.remove_old_logfiles, cron=cron, offset=0) - - self.get_sh().stateengine_plugin_functions = StateEngineFunctions.SeFunctions(self.get_sh(), self.logger) + self.init_webinterface() + try: + log_level = self.get_parameter_value("log_level") + log_directory = self.get_parameter_value("log_directory") + self.logger.info("Init StateEngine (log_level={0}, log_directory={1})".format(log_level, log_directory)) + + StateEngineDefaults.startup_delay = self.get_parameter_value("startup_delay_default") + StateEngineDefaults.suspend_time = self.get_parameter_value("suspend_time_default") + StateEngineDefaults.write_to_log(self.logger) + + StateEngineCurrent.init(self.get_sh()) + + if log_level > 0: + if log_directory[0] != "/": + base = self.get_sh().get_basedir() + if base[-1] != "/": + base += "/" + log_directory = base + log_directory + if not os.path.exists(log_directory): + os.makedirs(log_directory) + SeLogger.set_loglevel(log_level) + SeLogger.set_logdirectory(log_directory) + text = "StateEngine extended logging is active. Logging to '{0}' with loglevel {1}." + self.logger.info(text.format(log_directory, log_level)) + log_maxage = self.get_parameter_value("log_maxage") + if log_level > 0 and log_maxage > 0: + self.logger.info("StateEngine extended log files will be deleted after {0} days.".format(log_maxage)) + SeLogger.set_logmaxage(log_maxage) + cron = ['init', '30 0 * *'] + self.scheduler_add('StateEngine: Remove old logfiles', SeLogger.remove_old_logfiles, cron=cron, offset=0) + + self.get_sh().stateengine_plugin_functions = StateEngineFunctions.SeFunctions(self.get_sh(), self.logger) + except Exception: + self._init_complete = False + return # Parse an item # noinspection PyMethodMayBeStatic @@ -136,3 +140,85 @@ def not_changed_by(self, caller, source, changed_by): entry_source == original_source or entry_source == "*"): return False return True + + def init_webinterface(self): + """" + Initialize the web interface for this plugin + + This method is only needed if the plugin is implementing a web interface + """ + try: + self.mod_http = Modules.get_instance().get_module('http') # try/except to handle running in a core version that does not support modules + except: + self.mod_http = None + if self.mod_http == None: + self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_shortname())) + return False + + import sys + if not "SmartPluginWebIf" in list(sys.modules['lib.model.smartplugin'].__dict__): + self.logger.warning("Plugin '{}': Web interface needs SmartHomeNG v1.5 and up. Not initializing the web interface".format(self.get_shortname())) + return False + + # set application configuration for cherrypy + webif_dir = self.path_join(self.get_plugin_dir(), 'webif') + config = { + '/': { + 'tools.staticdir.root': webif_dir, + }, + '/static': { + 'tools.staticdir.on': True, + 'tools.staticdir.dir': 'static' + } + } + + # Register the web interface as a cherrypy app + self.mod_http.register_webif(WebInterface(webif_dir, self), + self.get_shortname(), + config, + self.get_classname(), self.get_instance_name(), + description='') + + return True + + +# ------------------------------------------ +# Webinterface of the plugin +# ------------------------------------------ + +import cherrypy +from jinja2 import Environment, FileSystemLoader + +class WebInterface(SmartPluginWebIf): + + + def __init__(self, webif_dir, plugin): + """ + Initialization of instance of class WebInterface + + :param webif_dir: directory where the webinterface of the plugin resides + :param plugin: instance of the plugin + :type webif_dir: str + :type plugin: object + """ + self.logger = logging.getLogger(__name__) + self.webif_dir = webif_dir + self.plugin = plugin + self.tplenv = self.init_template_environment() + + + @cherrypy.expose + def index(self, action=None, item_id=None, item_path=None, reload=None, page='index'): + """ + Build index.html for cherrypy + + Render the template and return the html file to be delivered to the browser + + :return: contents of the template after beeing rendered + """ + item = self.plugin.get_sh().return_item(item_path) + + tmpl = self.tplenv.get_template('{}.html'.format(page)) + # add values to be passed to the Jinja2 template eg: tmpl.render(p=self.plugin, interface=interface, ...) + return tmpl.render(p=self.plugin, + language=self.plugin._sh.get_defaultlanguage(), now=self.plugin.shtime.now()) diff --git a/stateengine/webif/static/img/plugin_logo.png b/stateengine/webif/static/img/plugin_logo.png new file mode 100755 index 0000000000000000000000000000000000000000..c5d78af6be2d00947930df0735fcd0aed6f211fe GIT binary patch literal 21516 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 z zMqJG0&T(uYczgL?O7M4r0NL!iGrM)(Ge9D6*6*m^mG_BaISU;;+e@q3AU16@Xc9SK zP&faOu&TY_QnG;vVx_kMO8k`nxwoJao7IV;My!^3J=BD7r#9CzC>L74Qnr4uUX8gGl#n=INBD1=3RblK<949+ zv^#S}(!09KO=rN>vJ&g}h_A% zLhL0vr)b5fTeKs;VMGX`Y~|ZsnvfUD{KkHuhK)zD0{T}eE7BsJqE$LO z^E6ZsTtrg=?Jc`?F(W%V8%`5jJ}?ao=G$As#%HZy)}_FotaOmP6xcKqIsBmOwpiwt zw=yDdixFJ^zOl}iIj(6bgzTZ~*s|)y+&jZxcmlR22q1cjz+}vU*`K(NK=oUN_fV-V z37$*SgD3e%4OL>x3e0^FB&eHn>E_i-e#=0d9EBQI58*`Lb{PD^RzH(^hLA^JZJ#HO zK&>hVc|9esu0HA*SnpO<0&)+k8PgV zcaMPO;7F1?yiRh1MNt5N#JL41rrb?M=rKWOt4Ka=lmpL>fy(_*2Ba(ttwrALS<(4) zt$*${nEten*k(!Mw+He2LVi8F7HVinEbCDIujBqf!7Zc?7p06^~69n$B-%C~H# zK+b}XHEgO@hI%>hv8Az^NxUDu-3Q-yH_7RrADO2XhJ$;fLdbaXlvOUK;>KXj4>85H zlDAP*cm#I}FTR9>RqH{Iw}F&9qhX<1^EEf>j(kL|E*tcaa63BE!eFo){)flntwK5X zr;>Y$(_rRAG9MrO4HN}tv}+{~T*#KV?>jM)7omAM`zKlQT%QA_I;yJCZs9rRXzFS( zw&&S%|7c7VI(3)^-Dnr^F-$lAV`g8iNiBuGaJB`{xFBX*UZxe$=3MoP67VR#gjL|s z70BI6R*kh^wV^t0g^a6~&QtE#Njf)zJSc3ZO-4r)py_%y~(h`KX9+z=0 zEiT{)?}YcSp=PhW)2GC`i<7mk5c8JhKpmi(omx1~`FOK(Cb-?vc6UtRO*?Bop!r=e z1DTbUJeSuS-8a}B_bIVj!?SWcmEL)a7v!j=Ol{?96 z4^)z%(#)3SUm9K!sCP9S5MOiZxaqN+ JpMU-Re*rokYViO7 literal 0 HcmV?d00001 diff --git a/stateengine/webif/static/img/plugin_logo.tif b/stateengine/webif/static/img/plugin_logo.tif new file mode 100644 index 0000000000000000000000000000000000000000..b0ec6f0f4b36a7070ad1f722450ed9c32f478b7d GIT binary patch literal 143044 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 RLd_Ltrp6f0Owl>1{|{z^Qb_;+ literal 0 HcmV?d00001 diff --git a/stateengine/webif/static/img/readme.txt b/stateengine/webif/static/img/readme.txt new file mode 100755 index 000000000..1a7c55eef --- /dev/null +++ b/stateengine/webif/static/img/readme.txt @@ -0,0 +1,6 @@ +This directory is for storing images that are used by the web interface. + +If you want to have your own logo on the top of the web interface, store it here and name it plugin_logo.. + +Extension can be png, svg or jpg + diff --git a/stateengine/webif/templates/doku1.html b/stateengine/webif/templates/doku1.html new file mode 100755 index 000000000..903423d8e --- /dev/null +++ b/stateengine/webif/templates/doku1.html @@ -0,0 +1,123 @@ +{% extends "base_plugin.html" %} +{% block scripts %} +{{ super() }} + +{% endblock scripts %} +{% set logo_frame = false %} + + +{% set item_count = p.__items|length %} +{% set tab1title = "_('Dokumentation')" %} +{% set tab2title = "Items" %} +{% set tabcount = 1 %} + +{% block headtable %} + + + + + + + + + + + + + + + + + + + + + + + + + +
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
+{% endblock headtable %} + + +{% block bodytab1 %} + +
+ +
+

stateengine Plugin für smarthomeNG - Deutsche Dokumentation

+ +

Warnung

+ +

Wichtig: + Es ist nicht empfehlenswert das stateengine Plugin für sicherheitsrelevante Zustände, wie zum Beispiel das Hochfahren von Jalousien bei zu viel Wind, zu verwenden. Sicherheitsrelevante Funktionen müssen so einfach wie möglich aufgebaut sein. Es wird daher dringend dazu geraten, solche Funktionen unabhängig von smarthomeNG und dem stateengine Plugin zu realisieren. Für das Hochfahren von Jalousien bei Windalarm beispielsweise sollte die Sperrfunktionalität verwendet werden, über die alle aktuellen Jalousieaktoren verfügen!

+ +

Funktionalität

+ +

Über zusätzliche Items in den items/*.conf-Dateien können Objekte definiert werden, die eine beliebige Anzahl benutzerdefinierter Zustand haben. Jeder Zustand kann Sets von Einstiegs- und Ausstiegsbedingungen haben, sowie diverse Aktionen auslösen, wenn der Zustand aktiv wird. In regelmäßigen Intervallen werden die Zustände für jedes Objekt geprüft.

+ +
    +
  • Wenn die Ausstiegsbedingungen des aktuellen Zustands nicht erfüllt sind bleibt das Objekt im aktuellen Zustand.
  • + +
  • Wenn der aktuelle Zustand verlassen werden kann werden alle Zustände in der Reihenfolge, in der sie in der Konfigurationsdatei definiert sind, abgeprüft.
  • + +
  • Der erste Zustand bei dem eine Gruppe Einstiegsbedingungen vollständig erfüllt ist, wird zum aktuellen Zustand. Die Aktionen, die für diesen Zustand definiert sind, werden ausgeführt.
  • + +
  • Wenn kein passender Zustand gefunden wird passiert nichts. Das Objekt verbleibt im vorherigen Zustand.
  • +
+ +

Die folgenden Bedingungen können Teil der Bedingungsgruppen sein:

+ +
    +
  • Tageszeit (Minimum, Maximum, Wert)
  • + +
  • Wochentag (Minimum, Maximum, Wert)
  • + +
  • Azimut der Sonne (Minimum, Maximum, Wert)
  • + +
  • Altitude der Sonne (Minimum, Maximum, Wert)
  • + +
  • Alter des aktuellen Zustands (Minimum, Maximum, Wert)
  • + +
  • Zufallszahl (Minimum, Maximum, Wert)
  • + +
  • Vorheriger Zustand (Wert)
  • + +
  • Trigger-Objekt, dass die Zustandsermittlung ausgelöst hat
  • +
+ +

Zusätzlich können beliebige Items als Bedingungen geprüft werden (Minimum, Maximum oder Wert)

+ +

Der ursprüngliche Zweck dieses Plugins war es, Jalousien zu steuern. Mit den steigenden Anforderungen hat es sich jedoch zu einem flexiblen Zustandsautomaten entwickelt, mit dem nahezu alles gesteuert werden kann. Im Prinzip ist es ein endlicher Automat.

+
+ + +
+{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku10.html b/stateengine/webif/templates/doku10.html new file mode 100755 index 000000000..72e6fe6b2 --- /dev/null +++ b/stateengine/webif/templates/doku10.html @@ -0,0 +1,128 @@ +{% extends "base_plugin.html" %} +{% block scripts %} +{{ super() }} + +{% endblock scripts %} +{% set logo_frame = false %} + + +{% set item_count = p.__items|length %} +{% set tab1title = "StateEngine" %} +{% set tabcount = 1 %} + +{% block headtable %} + + + + + + + + + + + + + + + + + + + + + + + + + +
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
+{% endblock headtable %} + + +{% block bodytab1 %} + +
+ +
+

Vordefinierte Funktionen

+ +

Das stateengine Plugin stellt verschiedene vordefinierte Funktionen zur Verfügung die einfach für "se_set_<Aktionsname>" und "se_run_<Aktionsname>" Aktionen verwendet werden können. Diese Funktionen sind in einer Klasse enthalten, die bei Bedarf für das Ausführen der Aktion instanziiert wird. Die folgenden Funktionen können verwendet werden:

+ +

Winkel zum Nachführen der Jalousielamellen auf Basis des Sonnenstands berechnen

+ +
stateengine_eval.sun_tracking()
+    
+ +

Zufallszahl

+ +
stateengine_eval.get_random_int(min,max)
+    
+ +

Über "min" und "max" kann die kleinste/größte Nummer, die zurückgegeben werden soll, festgelegt werden. "min" und "max" können weggelassen werden, in diesem Fall sind die Vorgabewerte 0 für min und 255 für max.

+ +

Shell-Kommando ausführen

+ +
stateengine_eval.execute(command)
+    
+ +

Führt das Shell-Kommando "command" aus

+ +

Wert einer Variable ermitteln

+ +
stateengine_eval.get_variable(varname)
+    
+ +

Liefert den Wert der [[Variablen|Doku-De-Variablen]] "varname"

+ +

Item-Id relativ zum Objekt-Item ermitteln

+ +
stateengine_eval.get_relative_itemid(subitem_id)
+    
+ +

Eine Item-Id relativ zur Item-Id des Objekt-Items wird ermittelt. Die Ermittlung erfolgt dabei mit der gleichen Rotine, die zur [[relativen Ermittlung von Items|Doku-De-Grundsaetzliches-Relative-Itemangaben]] verwendet wird.

+ +

Item-Wert relativ zum Objekt-Item ermitteln

+ +
stateengine_eval.get_relative_itemvalue(subitem_id)
+    
+ +

Der Wert eines Items relativ zur Item-Id des Objekt-Items wird ermittelt. Die Ermittlung erfolgt dabei mit der gleichen Rotine, die zur [[relativen Ermittlung von Items|Doku-De-Grundsaetzliches-Relative-Itemangaben]] verwendet wird.

+ +

Suspend-Ende in einen Text einsetzen

+ +
stateengine_eval.insert_suspend_time(suspend_item_id, suspend_text="Ausgesetzt bis %X")
+    
+ +

Das Ende der Suspend-Zeit wird in den Text "suspend_text" eingesetzt. Im Text sind daher entsprechende Platzhalter vorzusehen (Siehe strftime() and strptime() Behavior). Wird kein "suspend_text" angegeben, so wird als Vorgabewert "Ausgesetzt bis %X" verwendet.

+ +

Zur Ermittlung des Endes der Suspend-Zeit muss über "suspend_item_id" ein Item angegeben werden, dessen Wert bei Eintritt in den Suspend-Status geändert wird. Über das Alter des Werts in diesem Item wird die bereits abgelaufene Suspend-Zeit bestimmt.

+
+
+{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku11.html b/stateengine/webif/templates/doku11.html new file mode 100755 index 000000000..5d97895b2 --- /dev/null +++ b/stateengine/webif/templates/doku11.html @@ -0,0 +1,88 @@ +{% extends "base_plugin.html" %} +{% block scripts %} +{{ super() }} + +{% endblock scripts %} +{% set logo_frame = false %} + + +{% set item_count = p.__items|length %} +{% set tab1title = "StateEngine" %} +{% set tabcount = 1 %} + +{% block headtable %} + + + + + + + + + + + + + + + + + + + + + + + + + +
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
+{% endblock headtable %} + + +{% block bodytab1 %} + +
+ +
+

Variablen

+ +

Mit dem [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] kann auf Variablen des Plugins zugegriffen werden. Derzeit stehen folgende Variablen zur Verfügung:

+ +

item.suspendtime:
+ _Die Suspend-Time des Items

+ +

current.stateid: + _Die Id des Status, der gerade geprüft wird

+ +

current.statename: + _Der Name des Status, der gerade geprüft wird

+
+
+{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku12.html b/stateengine/webif/templates/doku12.html new file mode 100755 index 000000000..2092bae59 --- /dev/null +++ b/stateengine/webif/templates/doku12.html @@ -0,0 +1,121 @@ +{% extends "base_plugin.html" %} +{% block scripts %} +{{ super() }} + +{% endblock scripts %} +{% set logo_frame = false %} + + +{% set item_count = p.__items|length %} +{% set tab1title = "StateEngine" %} +{% set tabcount = 1 %} + +{% block headtable %} + + + + + + + + + + + + + + + + + + + + + + + + + +
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
+{% endblock headtable %} + + +{% block bodytab1 %} + +
+ +
+

Lock - Sperren der automatischen Zustandsermittlung

+ +

Für das Sperren der automatischen Zustandsermittlung führt man ein Sperr-Item ein, dass beispielsweise über einen Taster änderbar ist.

+ +

Die Sperre soll aktiv sein, wenn das Sperr-Item den Wert True hat.

+ +

Das Sperr-Item

+ +

Das Sperritem definiert man wie folgt:

+ +
beispiel:
+        lock:
+            item:
+                type: bool
+                name: Sperr-Item
+                visu_acl: rw
+                cache: on
+    
+ +

Der Sperrzustand

+ +

Der Sperrzustand geht allen anderen Zuständen vor und wird deshalb als erster Zustand definiert.

+ +

Zudem muss eine Änderung des Sperr-Items direkt eine Zustandsermittlung auslösen, das Sperr-Item wird daher in die Liste der eval_trigger aufgenommen.

+ +

Einstiegsbedingung für den Sperrzustand ist nun einfach, dass das Sperr-Item den Wert True hat. Für das Sperr-Item werden in diesem Beispiel keinerlei Aktionen definiert. Solange also das Sperr-Item aktiv ist, passiert: nichts.

+ +
beispiel:
+        lock:
+            rules:
+                # Sperr-Item zu eval_trigger:
+                eval_trigger: <andere Einträge> | beispiel.lock.item
+
+                # Items für Bedingungen und Aktionen
+                se_item_lock: beispiel.lock.item
+
+                lock:
+                    type: foo
+                    name: Manuell gesperrt
+
+                    enter:
+                        se_value_lock: true
+    
+ +

Bei der Zustandsermittlung die Reihenfolge der Definition der Zustände relevant. Da der Sperrzustand allen anderen Zuständen vorgeht ist er üblicherweise der erste Zustand in der Definition.

+
+
+{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku13.html b/stateengine/webif/templates/doku13.html new file mode 100755 index 000000000..82d2047e0 --- /dev/null +++ b/stateengine/webif/templates/doku13.html @@ -0,0 +1,304 @@ +{% extends "base_plugin.html" %} +{% block scripts %} +{{ super() }} + +{% endblock scripts %} +{% set logo_frame = false %} + + +{% set item_count = p.__items|length %} +{% set tab1title = "StateEngine" %} +{% set tabcount = 1 %} + +{% block headtable %} + + + + + + + + + + + + + + + + + + + + + + + + + +
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
+{% endblock headtable %} + + +{% block bodytab1 %} + +
+ +
+

Suspend - Zeitweises Deaktivieren der automatischen Zustandsermittlung nach manuellen Aktionen

+ +

Eine besondere Anforderung: Nach bestimmten manuellen Aktionen (z. B. über einen Taster, die Visu, o. ä.) soll die automatische Zustandsermittlung für eine gewisse Zeit ausgesetzt werden. Nach Ablauf dieser Zeit soll die Automatik wieder aktiv werden.

+ +

Für dieses Verhalten sind zunächst einige weitere Steueritems erforderlich, dann kann das Verhalten in einem Zustand abgebildet werden.

+ +

Das "Suspend"-Item

+ +

Zunächst wird ein "Suspend"-Item benötigt. Dieses Item zeigt zum einen die zeitweise Deaktivierung an, außerdem kann die Deaktivierung über dieses Item vorzeitig beendet werden:

+ +
beispiel:
+        suspend:
+            suspend:
+                type: bool
+                name: Suspend-Item
+                visu_acl: rw
+    
+ +

Das "Manuell"-Item

+ +

Ein weiteres Item wird benötigt, um alle Aktionen, die den Suspend-Zustand auslösen sollen, zu kapseln. Dieses Item ist das "Manuell"-Item. + Es wird so angelegt, dass der Wert dieses Items bei jeder manuellen Betätigung invertiert wird:

+ +
beispiel:
+        suspend:
+            manuell:
+                type: bool
+                name: Manuelle Bedienung
+                eval_trigger: beispiel.item1 | beispiel.item2 | ...
+                se_manual_invert = true
+    
+ +

In das Attribut eval_trigger werden alle Items eingetragen, deren Änderung als manuelle Betätigung gewertet werden soll. Änderungen an diesen Items, die vom stateengine-Plugin selbst vorgenommen wurden, werden dabei automatisch ausgefiltert um Endlosschleifen zu verhindern.

+ +

Das Attribut se_manual_invert: true veranlasst das stateengine-Plugin dabei, den Wert des Items bei Änderungen zu invertieren, wie es für das Auslösen des Suspend-Zustands erforderlich ist.

+ +

Das Manuell-Item kann noch wesentlich komplexer ausgestaltet werden. Beispielsweise können Änderungen durch bestimmte Ereignisse ausgeschlossen werden. Details hierzu finden sich auf der Seite [[Erweiterte Funktionen des "Manuell"-Items für den Suspend-Zustand|Doku-De-BesondereZustaende-Suspend-Manuell]].

+ +

Der Suspend-Zustand

+ +

Mit diesen beiden Items kann nun ein einfacher Suspend-Zustand definiert werden. Als Aktion im Suspend-Zustand wird dabei die Sonderaktion "suspend" verwendet. Diese hat zwei Parameter:

+ +
se_special_suspend: suspend:<Suspend-Item>,<Manuell-Item>
+    
+ +

Der Suspend-Zustand sieht damit wie folgt aus:

+ +
suspend:
+        type: foo
+        name: Ausgesetzt
+
+        on_enter_or_stay:
+            type: foo
+            name: Ausführen immer wenn ein Zustand aktiv ist
+
+            # Suspend-Item setzen
+            se_special_suspend: suspend:test.suspend.suspend,test.suspend.manuell
+
+        on_leave:
+            type: foo
+            name: Ausführen beim Verlassen des Zustands
+
+            # Suspend-Item zurücksetzen
+            se_set_suspend: False
+
+       enter_manuell:
+            type: foo
+            name: Bedingung: Suspend beginnen
+
+            #Bedingung: Manuelle Aktion wurde durchgeführt
+            se_value_trigger_source: test.suspend.manuell
+
+        enter_stay:
+            type: foo
+            name: Bedingung: Im Suspend verbleiben
+
+            #Bedingung: Suspend ist aktiv
+            se_value_laststate: var:current.state_id
+
+            #Bedingung: Suspendzeit ist noch nicht abgelaufen
+            se_agemax_manuell: var:item.suspend_time
+
+            #Bedingung: Suspend-Item wurde nicht extern geändert
+            se_value_suspend: True
+    
+ +

Bei der Zustandsermittlung die Reihenfolge der Definition der Zustände relevant. Da der Suspend-Zustand anderen Zuständen vorgehen sollte steht er üblicherweise sehr weit vorrne in der Reihenfolge. In der Regel wird der Suspend-Zustand in der Definition der zweite Zustand, nach dem [[Lock-Zustand|Doku-De-BesondereZustaende-Lock]] sein.

+ +

Komplettes Beispiel

+ +

Baut man die einzelnen Teile zusammen erhält man die folgende Konfiguration.

+ +

test: + type: foo

+ +
    suspend:
+            type: foo
+            name: stateengine Suspend Beispiel
+
+            suspend:
+                type: bool
+                name: Suspend-Item
+                visu_acl: rw
+
+            manuell:
+                type: bool
+                name: Manuelle Bedienung
+                eval_trigger: beispiel.item1 | beispiel.item2 | ...
+                se_manual_invert: true
+
+            rules:
+                type: bool
+                name: Automatik Test Suspend
+                se_plugin: active
+
+                # Sowohl das Manuell- als auch das Suspend-Item müssen eine Zustandsermittlung auslösen
+                eval_trigger: test.suspend.manuell | test.suspend.suspend
+
+                #Items für Bedingungen und Aktionen zuweisen
+                se_item_suspend: test.suspend.suspend
+                se_item_manuell: test.suspend.manuell
+
+                suspend:
+                    type: foo
+                    name: Ausgesetzt
+
+                    on_enter_or_stay:
+                        type: foo
+                        name :Ausführen immer wenn ein Zustand aktiv ist
+
+                        # Suspend-Item setzen
+                        se_special_suspend: suspend:test.suspend.suspend,test.suspend.manuell
+
+                    on_leave:
+                        type: foo
+                        name: Ausführen beim Verlassen des Zustands
+
+                        # Suspend-Item zurücksetzen
+                        se_set_suspend: False
+
+                    enter_manuell:
+                        type: foo
+                        name: Bedingung: Suspend beginnen
+
+                        #Bedingung: Manuelle Aktion wurde durchgeführt
+                        se_value_trigger_source_ test.suspend.manuell
+
+                    enter_stay:
+                        type: foo
+
+                        name: Bedingung: Im Suspend verbleiben
+
+                        #Bedingung: Suspend ist aktiv
+                        se_value_laststate: var:current.state_id
+
+                        #Bedingung: Suspendzeit ist noch nicht abgelaufen
+                        se_agemax_manuell: var:item.suspend_time
+
+                        #Bedingung: Suspend-Item wurde nicht extern geändert
+                        se_value_suspend: True
+    
+ +

Dauer der zeitweisen Deaktivierung

+ +

Die Dauer der zeitweisen Deaktivierung wird in der Plugin-Konfiguration über die Einstellung suspend_time_default angegeben. Vorgabewert sind 3600 Sekunden (1 Stunde). + Wenn die Dauer der zeitweisen Deaktivierung für ein einzelnes Objekt-Item abweichend sein soll, kann dort das Attribut

+ +
    se_suspend_time: <Sekunden>
+    
+ +

angegeben werden.
+ Der Parameter verwendet den [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]]

+ +

Erweiterte Funktionen des "Manuell"-Items für den Suspend-Zustand

+ +

Bestimmte Item-Änderungen nicht als "manuelle Bedienung" auswerte

+ +

In bestimmten Fällen ist es erforderlich, das Item-Änderungen, die durch bestimmte Aufrufe ausgelöst werden, nicht als manuelle Betätigung gewertet werden. Hierzu zählt zum Beispiel die Rückmeldung der Raffstore-Position nach dem Verfahren durch den Jalousieaktor. + Hierfür stehen zwei für das Manuell-Item weitere Attribute bereit:

+ +

asmanualinclude
+ Liste der Aufrufe, die als "manuelle Betätigung" gewertet werden sollen

+ +

asmanualexclude
+ Liste der Aufrufe, die nicht als "manuelle Betätigung" gewertet werden sollen

+ +

Bei beiden Attributen wird eine Liste von Elementen angegeben. Die einzelnen Elemente bestehen dabei aus dem Aufrufenden ("Caller") einem Doppelpunkt und der Quelle ("Source"). Mehrere Elemente werden durch "|" getrennt. Für "Caller" und "Source" kann dabei jeweils auch "*" angegeben werden, dies bedeutet, dass der jeweilige Teil nicht berücksichtigt werd.

+ +

Wenn bei der Prüfung festgestellt wird, dass ein Wert über eine Eval-Funktionalität geändert wurde, so wird die Änderung zurückverfolgt bis zur ursprünglichen Änderung, die die Eval-Kette ausgelöst hat. Diese ursprüngliche Änderung wird dann geprüft.

+ +

Der Wert von "Caller" zeigt an, welche Funktionalität das Item geändert hat. Der Wert von "Source" ist Abhängig vom Caller. Häufig verwendete "Caller" sind:

+ +
    +
  • "Init": Initialisierung von smarthomeNG. "Source" ist in der Regel leer
  • + +
  • "Visu": Änderung über die Visualisierung (Visu-Plugin). "Source" beinhaltet die IP und den Port der Gegenstelle
  • + +
  • "KNX": Änderung über das KNX-Plugin. "Source" ist die physische Adresse des sendenden Geräts
  • +
+ +

Wenn se_manual_include oder se_manual_exclude angegeben sind, muss se_manual_invert nicht angegeben werden.

+ +
beispiel:
+        suspend:
+            manuell:
+                type: bool
+                name: Manuelle Bedienung
+                eval_trigger: beispiel.item1 | beispiel.item2 | ...
+                se_manual_exclude: KNX:1.1.42 | Init:*
+    
+ +

Hier werden alle Änderungen der Items beispiel.item1 und beispiel.item2 als manuelle Betätigung gewertet, sofern Sie nicht durch das KNX-Gerät mit der physischen Adresse 1.1.42 oder durch die Initialisierung von smarthomeNG erfolgt sind.

+ +

Erweitertes Logging für das Manuell-Item:

+ +

Sofern im Manuell-Item die Attribute se_manual_include bzw. se_manual_exclude verwendet werden, ist auch hier eine Protokollierung mittels des erweiterten Loggings möglich. Dazu muss das Item, unter dem das Log geführt wird über das zusätzliche Attribut se_manual_logitem angegeben werden. Hier wird man als Item in der Regel das Manuell-Item angeben:

+ +
beispiel:
+        suspend:
+            manuell:
+                type: bool
+                name: Manuelle Bedienung
+                eval_trigger: beispiel.item1 | beispiel.item2 | ...
+                se_manual_exclude: KNX:1.1.42 | Init:*
+                se_manual_logitem: beispiel.suspend.manuell
+    
+ +

Wird statt se_manual_include oder se_manual_exclude nur se_manual_invert verwendet, ist kein erweitertes Logging möglich.

+
+
+{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku14.html b/stateengine/webif/templates/doku14.html new file mode 100755 index 000000000..acf7d2a52 --- /dev/null +++ b/stateengine/webif/templates/doku14.html @@ -0,0 +1,85 @@ +{% extends "base_plugin.html" %} +{% block scripts %} +{{ super() }} + +{% endblock scripts %} +{% set logo_frame = false %} + + +{% set item_count = p.__items|length %} +{% set tab1title = "StateEngine" %} +{% set tabcount = 1 %} + +{% block headtable %} + + + + + + + + + + + + + + + + + + + + + + + + + +
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
+{% endblock headtable %} + + +{% block bodytab1 %} + +
+ +
+

Zusätzliche Kommandos für das CLI Plugin

+ +

Sofern die eingesetzte smarthomeNG-Version dies unterstützt, registriert das stateengine-Plugin zwei eigene Kommandos beim CLI-Plugin.

+ +

se_list
+ Zeigt eine Liste der Objekt-Items, für die das stateengine-Plugin aktiv ist

+ +

se_detail <Id eines Objekt-Items>
+ Zeigt Details zum Objekt Item

+
+
+{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku15.html b/stateengine/webif/templates/doku15.html new file mode 100755 index 000000000..04a1a9015 --- /dev/null +++ b/stateengine/webif/templates/doku15.html @@ -0,0 +1,687 @@ +{% extends "base_plugin.html" %} +{% block scripts %} +{{ super() }} + +{% endblock scripts %} +{% set logo_frame = false %} + + +{% set item_count = p.__items|length %} +{% set tab1title = "StateEngine" %} +{% set tabcount = 1 %} + +{% block headtable %} + + + + + + + + + + + + + + + + + + + + + + + + + +
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
+{% endblock headtable %} + + +{% block bodytab1 %} + +
+ +
+

Vollständiges Beispiel

+ +

In diesem Beispiel soll die Automatisierung eines Raffstores gezeigt werden. Folgende Zustände sollen abgedeckt werden:

+ +
    +
  • Sperre über Sperr-Item
  • + +
  • Zeitweises Deaktivieren ("Suspend") bei manuellen Aktionen
  • + +
  • Nachführen der Lamellen zum Sonnenstand bei großer Helligkeit
  • + +
  • Nacht
  • + +
  • Morgens
  • + +
  • Abends
  • + +
  • Tag
  • +
+ +

Dabei sollen möglichst viele Features des stateengine Plugins verwendet werden

+ +

Items zum Prüfen

+ +

Zuerst benötigen wir ein paar Items, die nachher als Bedingungen abgeprüft werden sollen:

+ +
beispiel:
+        steckdosen:
+            type: bool
+
+        licht:
+            type: bool
+
+        wetterstation:
+            helligkeit:
+                name: Helligkeit
+                type: num
+
+                gt43k:
+                    type: bool
+                    name: Flag: Helligkeit größer als 43 kLux
+                    eval: sh.beispiel.wetterstation.helligkeit() > 43000
+                    eval_trigger beispiel.wetterstation.helligkeit
+
+                gt35k:
+                    type: bool
+                    name: Flag: Helligkeit größer als 35 kLux
+                    eval: sh.beispiel.wetterstation.helligkeit() > 35000
+                    eval_trigger beispiel.wetterstation.helligkeit
+
+                gt25k:
+                    type: bool
+                    name: Flag: Helligkeit größer als 25 kLux
+                    eval: sh.beispiel.wetterstation.helligkeit() > 25000
+                    eval_trigger beispiel.wetterstation.helligkeit
+
+                gt20k:
+                    type: bool
+                    name: Flag: Helligkeit größer als 20 kLux
+                    eval: sh.beispiel.wetterstation.helligkeit() > 20000
+                    eval_trigger beispiel.wetterstation.helligkeit
+
+            temperatur:
+        name: Temperatur
+        type: num
+    
+ +

Trigger

+ +

Da wir mehrere Raffstores automatisieren wollen und alle Raffstores gleichzeitig fahren sollen, brauchen wir einen externen Trigger, auf den dann alle Automatiken hören:

+ +
beispiel:
+        trigger:
+            raffstore:
+                type: bool
+                name: Gemeinsamer Trigger für alle Raffstores
+                enforce_updates: yes
+                cycle: 300 = 1
+    
+ +

In diesem Fall wird die Zustandsermittlung alle 300 Sekunden (5 Minuten) ausgelöst.

+ +

Default-Konfiguration

+ +

Nun kommt die Default-Konfiguration. Sie ist unabhängig von konkreten zu automatisierenden Objekten. Sie beinhaltet jedoch umfangreiche Einstellungen, so dass die zu automatisierenden Objekte, die die Einstellungen aus der Default-Konfiguration verwenden, oft sehr simpel aufgebaut werden können.

+ +
beispiel:
+        default:
+            raffstore:
+                # Item für Helligkeit außen
+                se_item_brightness: beispiel.wetterstation.helligkeit
+                # Item für Temperatur außen
+                se_item_temperature: beispiel.wetterstation.temperatur
+                # Item das anzeigt, ob die Helligkeit außen mehr als 25kLux beträgt
+                se_item_brightnessGt25k: beispiel.wetterstation.helligkeit.gt25k
+                # Item das anzeigt, ob die Helligkeit außen mehr als 43kLux beträgt
+                se_item_brightnessGt43k: beispiel.wetterstation.helligkeit.gt43k
+                # Item für Behanghöhe
+                se_item_hoehe: ...hoehe
+                # Keine Änderung der Behanghöhe wenn Abweichung kleiner 10
+                se_mindelta_hoehe: 10
+                # Item für Lamellenwinkel
+                se_item_lamelle: ...lamelle
+                # Keine Änderung des Lamellenwinkels wenn Abweichung kleiner 5
+                se_mindelta_lamelle: 5
+                # "Manuell" Item
+                se_item_manuell: ..manuell
+                # "Lock" Item
+                se_item_lock: ..lock
+                # "Suspend" Item
+                se_item_suspend: ..suspend
+
+                # Zustand "Sperre über Sperr-Item"
+                Lock:
+                    type: foo
+                    name: Automatik manuell gesperrt
+                    # Aktionen:
+                    # - "Suspend"-Item ggf. zurücksetzen
+                    se_set_suspend: False
+                    # sonst nichts tun
+                    enter
+                        # Einstieg in "Lock": Wenn
+                        # - das "Lock"-Item gesetzt ist
+                        se_value_lock: True
+
+                # Zustand "Zeitweises Deaktivieren bei manuellen Aktionen"
+                Suspend:
+                    type: foo
+                    name: Ausgesetzt
+                    # Namensermittlung über eval-Funktion
+                    se_name: eval:stateengine_eval.insert_suspend_time("..suspend", "Automatik ausgesetzt bis %X")
+                    # Aktionen:
+                    # - "Suspend"-Item setzen
+                    se_set_suspend: True
+                    # sonst nichts tun
+
+                    # Einstieg in "Suspend": Wenn
+                    enter_manuell:
+                        # - die Zustandsermittlung über das "Manuell"-Item ausgelöst wurde
+                        se_value_trigger_source: eval:    stateengine_eval.get_relative_itemid("..manuell")
+
+                    # Verbleib in "Suspend": Wenn
+                    enter_stay:
+                        # - wir bereits in "Suspend" sind
+                        se_value_laststate: var:current.state_id
+                        # - wir weniger 3600 Sekunden im Suspend-Zustand sind
+                        se_agemax_suspend: 3600
+                        # - das "Suspend"-Item nicht von irgendwo anders auf "False" gesetzt wurde
+                        se_value_suspend: True
+
+                # Zustand "Nachführen der Lamellen zum Sonnenstand bei großer Helligkeit", Gebäudeseite 1
+                Nachfuehren_Seite_Eins:
+                    type: foo
+                    name: Tag (nachführen)
+                    # Aktionen:
+                    # - Behang ganz herunterfahren
+                    se_set_hoehe: value:100
+                    # - Lamellen zur Sonne ausrichten
+                    se_set_lamelle: eval:stateengine_eval.sun_tracking()
+                    # - "Suspend"-Item ggf. zurücksetzen
+                    se_set_suspend: False
+
+                    # Einstieg in "Nachführen": Wenn
+                    enter:
+                        # - das Flag "Helligkeit > 43kLux" seit mindestens 60 Sekunden gesetzt ist
+                        se_value_brightnessGt43k: true
+                        se_agemin_brightnessGt43k: 60
+                        # - die Sonnenhöhe mindestens 18° ist
+                        se_min_sun_altitude: 18
+                        # - die Sonne aus Richtung 130° bis 270° kommt
+                        se_min_sun_azimut: 130
+                        se_max_sun_azimut: 270
+                        # - es draußen mindestens 22° hat
+                        se_min_temperature: 22
+
+                    # Hysterese für Helligkeit: Wenn
+                    enter_hysterese:
+                        # ... wir bereits in "Nachführen" sind
+                        se_value_laststate: var:current.state_id
+                        # .... das Flag "Helligkeit > 25kLux" gesetzt ist
+                        se_value_brightnessGt25k: true
+                        # ... die Sonnenhöhe mindestens 18° ist
+                        se_min_sun_altitude: 18
+                        # ... die Sonne aus Richtung 130° bis 270° kommt
+                        se_min_sun_azimut: 130
+                        se_max_sun_azimut: 270
+                        # Anmerkung: Hier keine erneute Prüfung der Temperatur, damit Temperaturschwankungen nicht
+                        # zum Auf-/Abfahren der Raffstores führen
+
+                    # Verzögerter Ausstieg nach Unterschreitung der Mindesthelligkeit: Wenn
+                    enter_delay:
+                        # ... wir bereits in "Nachführen" sind
+                        se_value_laststate: var:current.state_id
+                        # .... das Flag "Helligkeit > 25kLux" nicht (!) gesetzt ist, aber diese Änderung nicht mehr als 20 Minuten her ist
+                        se_value_brightnessGt25k: false
+                        se_agemax_brightnessGt25k: 1200
+                        # ... die Sonnenhöhe mindestens 18° ist
+                        se_min_sun_altitude: 18
+                        # ... die Sonne aus Richtung 130° bis 270° kommt
+                        se_min_sun_azimut: 130
+                        se_max_sun_azimut: 270
+                        # Anmerkung: Auch hier keine erneute Prüfung der Temperatur, damit Temperaturschwankungen nicht
+                        # zum Auf-/Abfahren der Raffstores führen
+
+                # Zustand "Nachführen der Lamellen zum Sonnenstand bei großer Helligkeit", Gebäudeseite 2
+                Nachfuehren_Seite_Zwei:
+                    type: foo
+                    # Einstellungen des Vorgabezustands "Nachfuehren_Seite_Eins" übernehmen
+                    se_use: beispiel.default.raffstore.Nachfuehren_Seite_Eins
+
+                    # Sonnenwinkel in den Bedingungsgruppen anpassen
+                    enter:
+                        # ... die Sonne aus Richtung 220° bis 340° kommt
+                        se_min_sun_azimut: 220
+                        se_max_sun_azimut: 340
+
+                    enter_hysterese:
+                        # ... die Sonne aus Richtung 220° bis 340° kommt
+                        se_min_sun_azimut: 220
+                        se_max_sun_azimut: 340
+
+                    :enter_delay:
+                        # ... die Sonne aus Richtung 220° bis 340° kommt
+                        se_min_sun_azimut: 220
+                        se_max_sun_azimut: 340
+
+                # Zustand "Nacht"
+                Nacht:
+                    type: foo
+                    name: Nacht
+                    # Aktionen:
+                    # - Behang ganz herunterfahren
+                    se_set_hoehe: value:100
+                    # - Lamellen ganz schließen
+                    se_set_lamelle: value:0
+                    # - "Suspend"-Item ggf. zurücksetzen
+                    se_set_suspend: False
+
+                    # Einstieg in "Nacht": Wenn
+                    enter:
+                        # - es zwischen 16:00 und 08:00 Uhr ist
+                        se_min_time: 08:00
+                        se_max_time: 16:00
+                        se_negate_time: True
+                        # - die Helligkeit höchstens 90 Lux beträgt
+                        se_max_brightness: 90
+
+                # Zustand "Morgens"
+                Morgens:
+                    type: foo
+                    name: Dämmerung Morgens
+                    # Aktionen:
+                    # - Behang ganz herunterfahren
+                    se_set_hoehe: value:100
+                    # - Lamellen ca 45° nach unten
+                    se_set_lamelle: value:25
+                    # - "Suspend"-Item ggf. zurücksetzen
+                    se_set_suspend: False
+
+                    # Einstieg in "Morgens": Wenn
+                    enter:
+                        # - die Helligkeit zwischen 90 und 250 Lux beträgt
+                        se_min_brightness: 90
+                        se_max_brightness: 250
+                        # - es zwischen 00:00 und 12:00 Uhr ist
+                        se_min_time: 00:00
+                        se_max_time: 12:00
+
+                # Zustand "Abends"
+                Abends:
+                    type: foo
+                    name: Dämmerung Abends
+                    # Aktionen:
+                    # - Behang ganz herunterfahren
+                    se_set_hoehe: value:100
+                    # - Lamellen ca 45° nach oben
+                    se_set_lamelle: value:75
+                    # - "Suspend"-Item ggf. zurücksetzen
+                    se_set_suspend: False
+
+                    # Einstieg in "Abends": Wenn
+                    enter:
+                        # - die Helligkeit zwischen 90 und 250 Lux beträgt
+                        se_min_brightness: 90
+                        se_max_brightness: 250
+                        # - es zwischen 12:00 und 24:00 Uhr ist
+                        se_min_time: 12:00
+                        se_max_time: 24:00
+                        # Anmerkung: "24:00" ist eigentlich eine ungültige Zeit. Sie wird aber automatisch zu 23:59:59 umgewandelt
+
+                # Zustand "Tag"
+                Tag:
+                    type: foo
+                    name: Tag (statisch)
+                    # Aktionen:
+                    # - Behang ganz hochfahren
+                    se_set_hoehe: value:0
+                    # - Lamellen auf den Standardwert bei ganz hochgefahrenem Behang
+                    se_set_lamelle: value:100
+                    # - "Suspend"-Item ggf. zurücksetzen
+                    se_set_suspend: False
+
+                    # Einstieg in "Tag": Wenn
+                    enter:
+                        # - es zwischen 06:30 und 21:30 Uhr ist
+                        se_min_time: 06:30
+                        se_max_time: 21:30
+    
+ +

Automatisierung Raffstore 1

+ +

Jetzt wollen wir den ersten Raffstore automatisieren. Einige Items dazu haben wir sowieso schon, da der Raffstore über diese Items gesteuert wird.

+ +
beispiel:
+        raffstore1:
+            name: Raffstore Beispiel 1
+
+            aufab:
+                type: bool
+                name: Raffstore auf/ab fahren
+                enforce_updates: on
+
+            step:
+                type: bool
+                name: Raffstore Schritt fahren/stoppen
+                enforce_updates: on
+
+            hoehe:
+                type: num
+                name: Behanghöhe des Raffstores
+
+            lamelle:
+                type: num
+                name: Lamellenwinkel des Raffstores
+    
+ +

Jetzt kommen noch die Items zur Automatisierung und schließlich das stateengine Objekt-Item hinzu:

+ +
beispiel:
+        raffstore1:
+            automatik:
+                lock:
+                    type: bool
+                    name: Sperr-Item
+                    visu_acl: rw
+                    cache: on
+
+                suspend:
+                    type: bool
+                    name: Suspend-Item
+                    visu_acl: rw
+                    # Achtung: Beim "Suspend"-Item niemals "enforce_updates = yes" setzen! Das führt dazu dass das Setzen des
+                    # Suspend-Items bei der Initialisierung zu einem endlosen sofortigen Wiederaufruf der Statusermittlung führt!
+
+                state_id:
+                    type: str
+                    name: Id des aktuellen Zustands
+                    visu_acl: r
+                    cache: on
+
+                state_name:
+                    type: str
+                    name: Name des aktuellen Zustands
+                    visu_acl: r
+                    cache: on
+
+                manuell:
+                    type: bool
+                    name: Manuelle Bedienung
+                    # Änderungen dieser Items sollen als manuelle Bedienung gewertet werden
+                    eval_trigger: beispiel.raffstore1.aufab | beispiel.raffstore1.step | beispiel.raffstore1.hoehe | beispiel.raffstore1.lamelle
+                    # Änderungen, die ursprünglich von diesen Triggern (<caller>:<source>) ausgelöst wurden, sollen nicht als manuelle Bedienung gewertet werden
+                    se_manual_exclude: KNX:y.y.y | Init:*
+
+                rules:
+                    type: bool
+                    name: Automatik Raffstore 1
+                    se_plugin: active
+                    # Erste Zustandsermittlung nach 30 Sekunden
+                    se_startup_delay: 30
+                    # Über diese Items soll die Statusermittlung ausgelöst werden
+                    eval_trigger: beispiel.trigger.raffstore | beispiel.raffstore1.automatik.anwesenheit | beispiel.raffstore1.automatik.manuell | beispiel.raffstore1.automatik.lock | beispiel.raffstore1.automatik.suspend
+                    # In dieses Item soll die Id des aktuellen Zustands geschrieben werden
+                    se_laststate_item_id: ..state_id
+                    # In dieses Item soll der Name des aktuellen Zustands geschrieben werden
+                    se_laststate_item_name: ..state_name
+
+                    Lock:
+                        # Zustand "Lock": Nur die Vorgabeeinstellungen übernehmen
+                        se_use: beispiel.default.raffstore.Lock
+
+                    Suspend:
+                        # Zustand "Suspend": Nur die Vorgabeeinstellungen übernehmen
+                        se_use: beispiel.default.raffstore.Suspend
+
+                    Nachfuehren:
+                        # Zustand "Nachfuehren": Nur die Vorgabeeinstellungen übernehmen (Gebäudeseite 2)
+                        se_use: beispiel.default.raffstore.Nachfuehren_Seite_Zwei
+
+                    Nacht:
+                        # Zustand "Nacht": Nur die Vorgabeeinstellungen übernehmen
+                        se_use: beispiel.default.raffstore.Nacht
+
+                    Morgens:
+                        # Zustand "Morgens": Nur die Vorgabeeinstellungen übernehmen
+                        se_use: beispiel.default.raffstore.Morgens
+
+                    Abends:
+                        # Zustand "Abends": Nur die Vorgabeeinstellungen übernehmen
+                        se_use: beispiel.default.raffstore.Abends
+
+                    Tag:
+                        # Zustand "Tag": Vorgabeeinstellungen übernehmen
+                        se_use: beispiel.default.raffstore.Tag
+    
+ +

Automatisierung Raffstore 2

+ +

Der zweite Raffstore ist ein komplexeres Beispiel. Hier werden nicht nur die Vorgabewerte übernommen, hier werden komplett neue Bedingungsgruppen definiert, sowie vorhandene Bedingungsgruppen abgeändert.

+ +
beispiel:
+        raffstore2:
+            name: Raffstore Beispiel 2
+
+            aufab:
+                type: bool
+                name: Raffstore auf/ab fahren
+                enforce_updates: on
+
+            step:
+                type: bool
+                name: Raffstore Schritt fahren/stoppen
+                enforce_updates: on
+
+            hoehe:
+                type: num
+                name: Behanghöhe des Raffstores
+
+            lamelle:
+                type: num
+                name: Lamellenwinkel des Raffstores
+
+            automatik:
+                lock:
+                    type: bool
+                    name: Sperr-Item
+                    visu_acl: rw
+                    cache: on
+
+                suspend:
+                    type: bool
+                    name: Suspend-Item
+                    visu_acl: rw
+                    # Achtung: Beim "Suspend"-Item niemals "enforce_updates = yes" setzen! Das führt dazu dass das Setzen des
+                    # Suspend-Items bei der Initialisierung zu einem endlosen sofortigen Wiederaufruf der Statusermittlung führt!
+
+                state_id:
+                    type: str
+                    name: Id des aktuellen Zustands
+                    visu_acl: r
+                    cache: on
+
+                state_name:
+                    type: str
+                    name: Name des aktuellen Zustands
+                    visu_acl: r
+                    cache: on
+
+                manuell:
+                    type: bool
+                    name: Manuelle Bedienung
+                    # Änderungen dieser Items sollen als manuelle Bedienung gewertet werden
+                    eval_trigger: beispiel.raffstore2.aufab | beispiel.raffstore2.step | beispiel.raffstore2.hoehe | beispiel.raffstore2.lamelle
+                    # Änderungen, die ursprünglich von diesen Triggern (<caller>:<source>) ausgelöst wurden, sollen nicht als manuelle Bedienung gewertet werden
+                    se_manual_exclude: KNX:y.y.y | Init:*
+
+                anwesenheit:
+                    type: bool
+                    name: Anwesenheit im Raum
+                    eval: or
+                    eval_trigger: beispiel.steckdosen | beispiel.licht
+
+                rules:
+                    type: bool
+                    name: Automatik Raffstore 2
+                    se_plugin: active
+                    # Erste Zustandsermittlung nach 30 Sekunden
+                    se_startup_delay: 30
+                    # Über diese Items soll die Statusermittlung ausgelöst werden
+                    eval_trigger: beispiel.trigger.raffstore | beispiel.raffstore2.automatik.anwesenheit | beispiel.raffstore2.automatik.manuell | beispiel.raffstore2.automatik.lock | beispiel.raffstore2.automatik.suspend
+                    # In dieses Item soll die Id des aktuellen Zustands geschrieben werden
+                    se_laststate_item_id: ..state_id
+                    # In dieses Item soll der Name des aktuellen Zustands geschrieben werden
+                    se_laststate_item_name: ..state_name
+                    # Dieses Item zeigt die Anwesenheit im Raum
+                    se_item_anwesend: ..anwesenheit
+                    # Item das anzeigt, ob die Helligkeit außen mehr als 35kLux beträgt
+                    se_item_brightnessGt35k: beispiel.wetterstation.helligkeit.gt35k
+                    # Item das anzeigt, ob die Helligkeit außen mehr als 20Lux beträgt
+                    se_item_brightnessGt20k: beispiel.wetterstation.helligkeit.gt20k
+
+                    Lock:
+                        # Zustand "Lock": Nur die Vorgabeeinstellungen übernehmen
+                        se_use: beispiel.default.raffstore.Lock
+
+                    Suspend:
+                        # Zustand "Suspend": Nur die Vorgabeeinstellungen übernehmen
+                        se_use: beispiel.default.raffstore.Suspend
+
+                    Nachfuehren:
+                        # Zustand "Nachführen": Vorgabeeinstellungen übernehmen
+                        se_use: beispiel.default.raffstore.Nachfuehren_Seite_Eins
+
+                        # ..und jetzt verändern wir das ganze, in dem wir abhängig vom "Anwesend"-Flag andere
+                        # Grenzwerte für die Helligkeit setzen.
+
+                        # Erst definieren wir mal zusätzliche Einstiegsbedingungen, die die neuen Grenzwerte beinhalten:
+                        :enter_anwesend:
+                            # Einstieg in "Nachführen" bei Anwesenheit: Wenn
+                            # - das Flag "Anwesenheit" gesetzt ist
+                            se_value_anwesend: true
+                            # - das Flag "Helligkeit > 35kLux" seit mindestens 60 Sekunden gesetzt ist (also 8k Lux früher als in "enter")
+                            se_value_brightnessGt35k: true
+                            se_agemin_brightnessGt35k: 60
+                            # - die Sonnenhöhe mindestens 15° ist (also 3° früher als in "enter")
+                            se_min_sun_altitude: 15
+                            # - die Sonne aus Richtung 110° bis 270° kommt (also 20° früher als in "enter"
+                            se_min_sun_azimut: 110
+                            se_max_sun_azimut: 270
+
+                        enter_anwesend_hysterese:
+                            # Hysterese für Helligkeit bei Anwesenheit: Wenn
+                            # - das Flag "Anwesenheit" gesetzt ist
+                            se_value_anwesend: true
+                            # ... wir bereits in "Nachführen" sind
+                            se_value_laststate: var:current.state_id
+                            # .... das Flag "Helligkeit > 20kLux" gesetzt ist (also 5 kLux früher als in "enter_hysterese")
+                            se_value_brightnessGt20k: true
+                            # ... die Sonnenhöhe mindestens 15° ist (Übernahme aus "enter_anwesend")
+                            se_min_sun_altitude: 15
+                            # ... die Sonne aus Richtung 110° bis 270° kommt (Übernahme aus "enter_anwesend")
+                            se_min_sun_azimut: 110
+                            se_max_sun_azimut: 270
+
+                        enter_anwesend_delay:
+                            # Verzögerter Ausstieg nach Unterschreitung der Mindesthelligkeit bei Anwesenheit: Wenn
+                            # - das Flag "Anwesenheit" gesetzt ist
+                            se_value_anwesend: true
+                            # ... wir bereits in "Nachführen" sind
+                            se_value_laststate: var:current.state_id
+                            # .... das Flag "Helligkeit > 20kLux" nicht (!) gesetzt ist, aber diese Änderung nicht mehr als 20 Minuten her ist
+                            se_value_brightnessGt20k: false
+                            se_agemax_brightnessGt20k: 1200
+                            # ... die Sonnenhöhe mindestens 15° ist (Übernahme aus "enter_anwesend")
+                            se_min_sun_altitude: 15
+                            # ... die Sonne aus Richtung 110° bis 270° kommt (Übernahme aus "enter_anwesend")
+                            se_min_sun_azimut: 110
+                            se_max_sun_azimut: 270
+
+                        # Jetzt müssen wir die vorhandenen Bedingungen noch erweitern (sie gelten ja nur noch, wenn "Anwesenheit" nicht gesetzt ist)
+                        enter:
+                            # Einstieg in "Nachführen": Wenn zusätzlich
+                            # - das Flag "Anwesenheit" nicht gesetzt ist
+                            se_value_anwesend: false
+
+                        enter_hysterese:
+                            # Hysterese für Helligkeit: Wenn zusätzlich
+                            # - das Flag "Anwesenheit" nicht gesetzt ist
+                            se_value_anwesend: false
+
+                        enter_delay:
+                            # Verzögerter Ausstieg nach Unterschreitung der Mindesthelligkeit:  Wenn zusätzlich
+                            # - das Flag "Anwesenheit" nicht gesetzt ist
+                            se_value_anwesend: false
+
+                    Nacht:
+                        # Zustand "Nacht": Vorgabeeinstellungen übernehmen
+                        se_use: beispiel.default.raffstore.Nacht
+                        # .. und zwei weitere Einstiegsbedingungen definieren
+
+                        enter_schlafenszeit_woche:
+                            # Einstieg in "Nacht": Wenn
+                            # - es zwischen 21:00 und 07:00 Uhr ist
+                            se_min_time: 07:00
+                            se_max_time: 21:00
+                            se_negate_time: True
+                            # - der Wochentag zwischen Montag und Freitag liegt
+                            se_min_weekday: 0
+                            se_max_weekday: 4
+
+                        enter_schlafenszeit_wochenende:
+                            # Einstieg in "Nacht": Wenn
+                            # - es zwischen 21:00 und 08:30 Uhr ist
+                            se_min_time: 08:30
+                            se_max_time: 21:00
+                            se_negate_time: True
+                            # - der Wochentag Samstag oder Sonntag ist
+                            se_value_weekday: 5 | 6
+
+                    Morgens:
+                        # Zustand "Morgens": Nur die Vorgabeeinstellungen übernehmen
+                        se_use: beispiel.default.raffstore.Morgens
+
+                    Abends:
+                        # Zustand "Abends": Nur die Vorgabeeinstellungen übernehmen
+                        se_use: beispiel.default.raffstore.Abends
+
+                    Tag:
+                        # Zustand "Tag": Vorgabeeinstellungen übernehmen
+                        se_use: beispiel.default.raffstore.Tag
+    
+
+
+{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku2.html b/stateengine/webif/templates/doku2.html new file mode 100755 index 000000000..6d70cc4df --- /dev/null +++ b/stateengine/webif/templates/doku2.html @@ -0,0 +1,132 @@ +{% extends "base_plugin.html" %} +{% block scripts %} +{{ super() }} + +{% endblock scripts %} +{% set logo_frame = false %} + + +{% set item_count = p.__items|length %} +{% set tab1title = "StateEngine" %} +{% set tabcount = 1 %} + +{% block headtable %} + + + + + + + + + + + + + + + + + + + + + + + + + +
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
+{% endblock headtable %} + + +{% block bodytab1 %} + +
+ +
+

Konfiguration des Plugins

+ +

Um das StateEngine Plugin zu verwenden müssen die folgenden Zeilen in die plugin.yaml Datei der smarthomeNG Installation eingetragen werden.

+ +
stateengine:
+        class_name: StateEngine
+        class_path: plugins.stateengine
+        #startup_delay_default: 10
+        #suspend_time_default: 3600
+        #log_level: 0
+        #log_directory: var/log/StateEngine/
+        #log_maxage: 0
+    
+ +

Auskommentierte Attribute sind Vorgabewerte, die nach den eigenen Bedürfnissen angepasst werden können.

+ +

startup_delay_default (optional):
+ Vorgabewert für die Startverzögerung der ersten Zustandsermittlung beim Start von smarthomeNG

+ +

Beim Starten von smarthomeNG dauert es üblicherweise einige Sekunden, bis alle Items initialisiert sind. Um zu verhindern, dass die erste Zustandsermittlung stattfindet, bevor alle Items ihren Initialwert haben, wird die erste Zustandsermittlung verzögert. Die Dauer der Verzögerung kann bei den Objekt-Items angegeben werden. Wenn bei einem Objekt-Item kein Wert angegeben ist, wird der hier angegebene Standardwert verwendet. Wenn kein abweichender Standardwert in der Plugin-Konfiguration angegeben ist, ist der Vorgabewert 10 Sekunden.

+ +

Folgende Werte sind möglich:

+ +

Zahl größer 0:
+ Angabe der Startverzögerung in Sekunden. Während der Startverzögerung sind die Auslöser der Zustandsermittlung inaktiv. Sie werden erst nach Ablauf der Startverzögerung und der ersten Zustandsermittlung aktiviert.

+ +

0:
+ Keine Startverzögerung. Die erste Zustandsermittlung wird direkt nach der Initialisierung des Objekt-Items durchgeführt. Anschließend werden die Auslöser für die Zustandsermittung aktiviert.

+ +

-1:
+ Es wird keine erste Zustandsermittlung durchgeführt. Nach der Initialisierung des Objekt-Items sind alle Auslöser für die Zustandsermittlung aktiv.

+ +

suspend_time_default (optional):
+ Vorgabezeit zur Unterbrechung der automatischen Steuerung nach manuellen Aktionen

+ +

Nach manuellen Aktionen kann die Automatik für eine bestimmte Zeit Unterbrochen werden. Die Dauer dieser Unterbrechungen kann bei den Objekt-Items angegeben werden. Die Einheit für den Wert sind Sekunden. Wenn bei einem Objekt-Item kein Wert angegeben ist, wird der hier angegebene Standardwert verwendet. Wenn kein abweichender Standardwert in der Plugin-Konfiguration angegeben ist, ist der Vorgabewert 3600 Sekunden (1 Stunde)

+ +

log_level(optional):
+ _Erweiterte Protokollierung: Loglevel (0: aus, 1: Info, 2: Debug

+ +

Die erweiterte Protokollierung wird über das Setzen des Loglevels auf 1 (Info) oder 2 (Debug) aktiviert. Wenn der Parameter nicht angegeben ist, ist die erweiterte Protokollierung deaktiviert.

+ +

log_directory (optional):
+ _Erweiterte Protokollierung: Verzeichnis für die Protokolldateien

+ +

Die Logdateien der erweiterten Protokollierung werden in das hier angegebene Verzeichnis geschrieben.
+ Wenn der angegebene Verzeichnisname mit "/" beginnt wird er als absoluter Verzeichnisname behandelt. Alle anderen Verzeichnisnamen werden als Unterverzeichnisse des smarthomeNG Basisverzeichnisses behandelt. + Das angegebene Verzeichnis wird angelegt, wenn es nicht existiert.
+ Wenn hier kein abweichendes Verzeichnis angegeben ist, wird das Verzeichnis <smarthome_base_directory>/var/log/AutoState/ verwendet.

+ +

log_maxage (optional):
+ _Erweiterte Protokollierung: Anzahl der Tage, nach der die Dateien im Verzeichnis "log_directory" wieder gelöscht werden sollen

+ +

Alte Protokolldateien können nach einer bestimmten Zeit automatisch gelöscht werden. Diesen Parameter wird die Anzahl der Tage festgelegt, nachdem die Dateien gelöscht werden sollen. Das Löschen ist ausgesetzt solange der Parameter den Wert 0 hat. Wenn der Parameter auf einen anderen Wert gesetzt wird, wird das Alter der Dateien im Protokollverzeichnis "log_directory" täglich geprüft und überalterte Dateien werden gelöscht.
+ Wichtig: Die Löschfunktionalität prüft und löscht alle Dateien im Protokollverzeichnis, ob sie Protokolldateien sind oder nicht. Daher sollten keine anderen Dateien in diesem Verzeichnis abgelegt werden!

+ +
+
+{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku3.html b/stateengine/webif/templates/doku3.html new file mode 100755 index 000000000..d8a34ddc5 --- /dev/null +++ b/stateengine/webif/templates/doku3.html @@ -0,0 +1,203 @@ +{% extends "base_plugin.html" %} +{% block scripts %} +{{ super() }} + +{% endblock scripts %} +{% set logo_frame = false %} + + +{% set item_count = p.__items|length %} +{% set tab1title = "StateEngine" %} +{% set tabcount = 1 %} + +{% block headtable %} + + + + + + + + + + + + + + + + + + + + + + + + + +
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
+{% endblock headtable %} + + +{% block bodytab1 %} + +
+ +
+

Die Grundkonfiguration für eine Automatik: Das Objekt-Item

+ +

Für jedes Objekt, dass mit dem StateEngine Plugin gesteuert werden soll, ist ein Item erforderlich, dass alle Konfigurationsdaten für dieses Objekt enthält. Dieses Item wird aus "Objekt-Item" bezeichnet. + Es können beliebig viele Objekt-Items und damit beliebig viele Automatiken angelegt werden.

+ +

Grundlegende Einstellungen

+ +

Über die folgenden Attribute werden die grundlegenden Einstellungen für eine Automatik festgelegt

+ +
beispiel:
+        raffstore1:
+            automatik:
+                rules:
+                    type: bool
+                    name: Automatik Raffstore 1
+                    se_plugin: active
+                    se_startup_delay: 30
+                    se_laststate_item_id: beispiel.raffstore1.automatik.state_id
+                    se_laststate_item_name: beispiel.raffstore1.automatik.state_name
+                    se_repeat_actions: true
+                    se_suspend_time: 7200
+    
+ +

type (obligatorisch):
+ Datentp des Items

+ +

Für das Objekt-Item muss immer der Datentyp "bool" verwendet werden

+ +

name (optional):
+ Name des Items

+ +

Wenn das Attribut nicht angegeben ist, wird die Id des Items als Name verwendet.

+ +

se_plugin (obligatorisch):
+ _Kennzeichnet das Item als Objekt-Item des StateEngine-Plugins

+ +

Der Wert dieses Attributs muss zwingend "active" sein, damit das Plugin das Item berücksichtigt. Zu Debuggingzwecken kann der Wert dieses Attributs auf einen anderen Wert geändert werden, dadurch wird das Plugin das Objekt ignorieren.

+ +

se_startupdelay (optional):
+ Startverzögerung der ersten Zustandsermittlung beim Start von smarthomeNG

+ +

Beim Starten von smarthomeNG dauert es üblicherweise einige Sekunden, bis alle Items initialisiert sind. Um zu verhindern, dass die erste Zustandsermittlung stattfindet, bevor alle Items ihren Initialwert haben, wird die erste Zustandsermittlung verzögert. Erst nach der ersten Zustandsermittlung werden alle Auslöser und Funktionen vollständig aktiviert. Zustandsermittlungen, die durch Items oder Timer vor Ablauf der Startverzögerung ausgelöst werden, werden nicht durchgeführt. + Die zulässigen Werte für "se_startup_delay" sind identisch mit den zulässigen Werten für den Plugin-Parameter "startup_delay_default".
+ Der Parameter verwendet den [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]]

+ +

se_laststateitemid (optional):
+ _Id des Items, in dem die Id des aktuellen Zustands abgelegt wird

+ +

In das hier angegebene Item wird die Id des aktuellen Zustands abgelegt. Das Item kann mit dem Attribut "cache = yes" versehen werden, dann bleibt der vorherige Zustand bei einem Neustart von smarthomeNG erhalten. Wenn das Item "se_laststate_item_id" nicht angegeben ist, wird der aktuelle Zustand nur im Plugin gespeichert und geht mit einem Neustart von smarthomeNG verloren.

+ +

Sofern verwendet, sollte das Item für "se_laststate_item_id" wie folgt definiert werden

+ +
beispiel:
+        raffstore1:
+            automatik:
+                state_id:
+                    type: str
+                    name: Id des aktuellen Zustands
+                    visu_acl: r
+                    cache: yes
+    
+ +

se_laststateitemname (optional):
+ _Id des Items, in dem der Name des aktuellen Zustands abgelegt wird

+ +

In das hier angegebene Item wird der Name des aktuellen Zustands abgelegt. Das Item kann für Displayzwecke verwendet werden. Wenn das Item "se_laststate_item_name" nicht angegeben ist, steht der Name des aktuellen Zustands nicht zur Verfügung

+ +

Sofern verwendet, sollte das Item für "se_laststate_item_name" wie folgt definiert werden

+ +
beispiel:
+        raffstore1:
+            automatik:
+                state_name:
+                    type: str
+                    name: Name des aktuellen Zustands
+                    visu_acl: r
+                    cache: yes
+    
+ +

se_repeatactions (optional):
+ Wiederholen der Aktionen bei unverändertem Zustand

+ +

Im Normalfall werden Aktionen jedesmal ausgeführt wenn der aktuelle Zustand neu ermittelt wurde. Dies ist unabhängig davon, ob sich der Zustand bei der Neuermittlung geändert hat oder nicht. + Dieses Verhalten kann über die Angabe von "se_repeat_actions = false" umgestellt werden. Wenn das Attribut auf "false" gesetzt ist, werden Aktionen nur ausgeführt, wenn sich der Zustand tatsächlich geändert hat. + Der Parameter verwendet den [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]]

+ +

se_suspendtime (optional):
+ Zeit zur Unterbrechung der automatischen Steuerung nach manuellen Aktionen

+ +

Nach manuellen Aktionen kann die Automatik für eine bestimmte Zeit Unterbrochen werden. Die Dauer dieser Unterbrechungen wird hier angegeben. Die Einheit für den Wert sind Sekunden. Wenn bei einem Objekt-Item kein Wert angegeben ist, wird der in der Pluginkonfiguration angegebene Standardwert (suspendtimedefault) verwendet. + Der Parameter verwendet den [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]]

+ +

Einstellungen zum Auslösen der Zustandsermittlung

+ +

Eine Neuermittlung des aktuellen Zustands wird jedesmal durchgeführt, wenn ein Wert für das Objekt-Item geschrieben wird. Somit können die Standardmöglichkeiten von smarthomeNG wie "cycle", "crontab" und "eval_trigger" verwendet werden, um die Neuermittlung des aktuellen Zustands auszulösen.

+ +
beispiel:
+        rafffstore2:
+            automatik:
+                rules:
+                    <...>
+                    cycle: 300
+                    crontab: 0 5 * * | 0 6 * *
+                    eval_trigger: beispiel.trigger.raffstore | beispiel.raffstore2.automatik.anwesenheit
+    
+ +

Details zu diesen Attributen können der smarthomeNG Dokumentation entnommen werden.

+ +

Um die Konfiguration einfach zu halten, verändert das Plugin einige Einstellungen des Objekt-Items. + Folgende Erleichterungen werden dabei vorgenommen:

+ +
    +
  • Es ist nicht erforderlich mit "cycle" bzw. "crontab" Werte anzugeben. Das StateEngine Plugin ergänzt diese automatisch, sofern erforderlich. Statt "cycle = 300=1" ist es ausreichend, wenn man "cycle = 300" angibt.

  • + +
  • Es ist nicht erforderlich das Attribut "eval = (irgendwas)" anzugeben, wenn "eval_trigger" verwendet wird. Das StateEngine plugin ergänzt dies automatisch, sofern erforderlich.

  • + +
  • "crontab = init" funktioniert nicht für das StateEngine Plugin. Die Neuberechnung des ersten Zustands nach dem Start von smarthomeNG wird über das Attribut "se_startup_delay" gesteuert.

  • +
+ +

Es ist auch möglich andere Wege zu verwenden, um den Wert des Objekt-Items zu setzen:

+ +
    +
  • Zuweisung einer hörenden KNX Gruppenadresse zum Objekt-Item und Senden eines Wertes auf diese Gruppenadresse.

  • + +
  • Setzen des Werts des Objekt-Items aus einer Logik, einer anderen Automatik oder sogar aus der selben Automatik (ggf. mit Verzögerung).

  • +
+ +
+
+{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku4.html b/stateengine/webif/templates/doku4.html new file mode 100755 index 000000000..b6a371bac --- /dev/null +++ b/stateengine/webif/templates/doku4.html @@ -0,0 +1,185 @@ +{% extends "base_plugin.html" %} +{% block scripts %} +{{ super() }} + +{% endblock scripts %} +{% set logo_frame = false %} + + +{% set item_count = p.__items|length %} +{% set tab1title = "StateEngine" %} +{% set tabcount = 1 %} + +{% block headtable %} + + + + + + + + + + + + + + + + + + + + + + + + + +
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
+{% endblock headtable %} + + +{% block bodytab1 %} + +
+ +
+

Zustände: Das Zustands-Item

+ +

Alle Items unterhalb des Objekt-Items beschreiben Zustände des Objekts ("Zustands-Item"). Die Ids der Zustands-Items sind beliebig. Sie werden als Werte für das über "se_laststate_item_id" angegebene Item verwendet um den aktuellen Zustand abzulegen.

+ +
beispiel:
+        raffstore1:
+            automatik:
+                rules:
+                    Tag:
+                        type: foo
+                        name: Tag
+                        se_name: eval: sh.eine_funktion()
+    
+ +

type (obligatorisch):
+ Datentp des Items

+ +

Für das Zustands-Item muss immer der Datentyp "foo" verwendet werden

+ +

name (optional):
+ Name des Zustands

+ +

Der Name des Zustands wird im Protokoll sowie als Wert für das über "se_laststate_item_name" angegebene Item verwendet. Wenn kein Name angegeben ist, wird hier ebenfalls die Id des Zustands-Items verwendet.

+ +

se_name (optional):
+ _Ermittlung des Namens des Zustands

+ +

Über das Attribut "se_name" kann der im Attribut "name" überschrieben werden. Dies wirkt sich jedoch nur auf den Wert aus, der in das über "se_laststate_item_name" angegebene Item geschrieben wird. Im Protokoll wird immer der über das Attribut "name" angegebene Wert verwendet.
+ Der Parameter verwendet den [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]]

+ +

Bedingungsgruppen

+ +

Jeder Zustand kann eine beliebige Anzahl von Bedingungsgruppen haben. Jede Bedingungsgruppe definiert ein Set an Bedingungen das überprüft wird, wenn der aktuelle Status neu ermittelt wird. Sobald die Bedingungen einer Bedingungsgruppe vollständig erfüllt sind, kann der Status aktiv werden.

+ +

Jede Bedingungsgruppe wird durch ein Item ("Bedingungsgruppen-Item") unterhalb des Zustands-Items abgebildet. Eine Bedingungsgruppe kann beliebig viele Bedingungen umfassen. Bedingungen werden als Attribute im Bedingungsgruppen-Item definiert. Details zu den Bedingungen werden im Abschnitt [[Bedingungen|Doku-De-Bedingungen]] erläutert.

+ +

Die folgenden Regeln kommen zur Anwendung:

+ +
    +
  • Zustände und Bedingungsgruppen werden in der Reihenfolge geprüft, in der sie in der Konfigurationsdatei definiert sind.

  • + +
  • Eine einzelne Bedingungsgruppe ist erfüllt, wenn alle Bedingungen, die in der Bedingungsgruppe definiert sind, erfüllt sind (UND-Verknüpfung). Einschränkungen, die in der Bedingungsgruppe nicht definiert sind, werden nicht geprüft.

  • + +
  • Ein Zustand kann aktueller Zustand werden, wenn eine beliebige der definierten Bedingungsgruppen des Zustands erfüllt ist. Die Prüfung ist mit der ersten erfüllten Bedingungsgruppe beendet (ODER-Verknüpfung).

  • + +
  • Ein Zustand der keine Bedingungsgruppen hat kann immer aktueller Zustand werden. Solch ein Zustand kann als Default-Zustand am Ende der Zustände definiert werden.

  • +
+ +

Aktionen

+ +

Jeder Zustand kann eine beliebige Anzahl an Aktionen definieren. Sobald ein Zustand aktueller Zustand wird werden die Aktionen des Zustands ausgeführt. + Für die Aktionen gibt es vier Ereignisse, die festlegen, wann eine Aktion ausgeführt wird:

+ +
    +
  • on_enter: Aktionen, die beim erstmaligen Aktivieren des Zustands ausgeführt werden

  • + +
  • on_stay: Aktionen, die ausgeführt werden, wenn der Zustand zuvor bereits aktiv war und weiterhin aktiv bleibt.

  • + +
  • on_enteror_stay: Aktionen, die ausgeführt werden, wenn der Zustand aktiv ist, unabhängig davon, ob er bereits zuvor aktiv war oder nicht.

  • + +
  • on_leave: Aktionen, die ausgeführt werden, direkt bevor ein anderer Zustand aktiv wird.

    + +

    Details zu den Aktionen werden im Abschnitt [[Aktionen|Doku-De-Aktionen]] erläutert.

  • +
+ +

Items

+ +

Bedingungen und Aktionen beziehen sich überlicherweise auf Items. Diese Items müssen auf Ebene des Objekt-Items über das Attribut "se_item_<Bedingungsname/Aktionsname>" bekannt gemacht werden.

+ +

Beispiel

+ +
beispiel:
+        raffstore1:
+            automatik:
+                rules:
+                    <Allgemeine Objektkonfiguration>
+
+                    Tag:
+                        type: foo
+                        name: Tag
+                        <Aktionen bei Zustand "Tag">
+                        enter:
+                            <Bedingungen>
+                    Nacht:
+                        type: foo
+                        name: Nacht
+                        <Aktionen bei Zustand "Nacht">
+                        enter_todark:
+                            <Bedingungen um den Zustand anzusteuern, wenn es zu dunkel ist>
+                        enter_tolate:
+                            <Bedingungen um den Zustand anzusteuern, wenn es zu spät ist>
+    
+ +

Attribute "se_item_height" und "se_item_lamella":
+ Definition der Items, die durch die Aktionen "se_set_height" und "se_set_lamella" verändert werden

+ +

Die Items werden durch ihre Item-Id angegeben

+ +

Attribut "name":
+ Name des Zustands

+ +

Der Name wird in das über "se_laststate_item_name" definierte Item geschrieben, wenn der Zustand aktueller Zustand wird. Dieser Wert kann z. B. in einer Visualisierung dargestellt werden.

+ +

Attribute "se_set_height" und "se_set_leave":
+ Neue statische Werte für die Items die über "se_item_height" und "se_item_leave" festgelegt wurden

+ +

Untergeordnete Items "enter", "enter_todark" und "enter_tolate":
+ Bedingungsgruppen die erfüllt sein müssen, damit ein Zustand aktueller Zustand werden kann

+ +
+
+{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku5.html b/stateengine/webif/templates/doku5.html new file mode 100755 index 000000000..531bf3686 --- /dev/null +++ b/stateengine/webif/templates/doku5.html @@ -0,0 +1,266 @@ +{% extends "base_plugin.html" %} +{% block scripts %} +{{ super() }} + +{% endblock scripts %} +{% set logo_frame = false %} + + +{% set item_count = p.__items|length %} +{% set tab1title = "StateEngine" %} +{% set tabcount = 1 %} + +{% block headtable %} + + + + + + + + + + + + + + + + + + + + + + + + + +
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
+{% endblock headtable %} + + +{% block bodytab1 %} + +
+ +
+

Bedingungen

+ +

Jede Bedingung erfordert drei Dinge:

+ +
    +
  • Einen Namen der die Bedingung und die zugehörigen Elemente identifiziert
  • + +
  • Grenzwerte um zu prüfen, ob die Bedingung erfüllt ist
  • + +
  • Eine Möglichkeit den aktuellen Wert zu ermitteln, gegen den die Grenzwerte geprüft werden
  • +
+ +

Name der Bedingung

+ +

Der Name der Bedingung ist beliebig und wird lediglich zur Benennung der Attribute verwendet. Die Namen aller Attribute, die zu einer Bedingung gehören, folgen dem Muster "se_<Funktion>_<Bedingungsname>". Es gibt verschiedene "besondere" Bedingungsnamen, die später erläutert werden.

+ +

Grenzwerte

+ +

Die Grenzwerte einer Bedingung werden in den Bedingungsgruppen definiert. Die folgenden Grenzwerte sind möglich:

+ +

Minimum

+ +
    se_min_<Bedingungsname>: [Wert]
+    
+ +

Die Bedingung ist erfüllt, wenn der aktuelle Wert großer als das angegebene Minimum ist. + Fur das Attribut wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet.

+ +

Maximum

+ +
    se_max_<Bedingungsname>: [Wert]
+    
+ +

Die Bedingung ist erfüllt, wenn der aktuelle Wert kleiner als das angegebene Maximum ist. + Fur das Attribut wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet.

+ +

Bestimmter Wert

+ +
    se_value_<Bedingungsname>: [Wert]
+    
+ +

Die Bedingung ist erfüllt, wenn der aktuelle Wert gleich dem angegebenen Wert ist. + Fur das Attribut wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet.

+ +

Für den Fall, dass der Wert aus Festwerten stammt ("[Wert]" ist "value: [Festwert]") kann auch eine Wertliste angegeben werden:

+ +
    se_value_<Bedingungsname>: value:[Wert1]|[Wert2]|(...)[WertN]
+    
+ +

In diesem Fall ist die Bedingung erfüllt, wenn der aktuelle Wert in der Wertliste enthalten ist.

+ +

Negieren

+ +
    se_negate_<Bedingungsname>: True|False
+    
+ +

Die gesamte Bedingung (Minimum, Maximum und Wert) wird negiert (umgekehrt). + Für das Attribut wird der Datentyp Boolean verwendet, zulässige Werte sind "true", "1", "yes", "on" bzw. "false", "0", "no", "off"

+ +

Mindestalter

+ +
    se_agemin_<Bedingungsname>: [Wert]
+    
+ +

Die Bedingung ist erfüllt, wenn das Alter des Items, dass zur Ermittlung des Werts angegeben ist, größer als das angegebene Mindestalter ist. + Fur das Attribut wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet.

+ +

Höchstalter

+ +
    se_agemax_<Bedingungsname>: [Wert]
+    
+ +

Die Bedingung ist erfüllt, wenn das Alter des Items, dass zur Ermittlung des Werts angegeben ist, kleiner als das angegebene Höchstalter ist. + Fur das Attribut wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet.

+ +

Altersbedingung negieren

+ +
    se_agenegate_<Bedingungsname>: True|False
+    
+ +

Die Altersbedingung (Mindestalter, Höchstalter) wird negiert (umgekehrt). + Fur das Attribut wird der Datentyp Boolean verwendet, zulässige Werte sind "true", "1", "yes", "on" bzw. "false", "0", "no", "off"

+ +

Bereitstellung des aktuellen Werts

+ +

Der aktuelle Wert kann entweder über ein Item oder über eine Eval-Funktion bereitgestellt werden. Wenn beides angegeben ist wird das Item verwendet und die Eval-Funktion ignoriert.

+ +

Der Name des Items, über das der aktuelle Wert abgerufen werden soll, wird auf Ebene des Objekt-Items über das Attribut "se_item_<Bedingungsname>" angegeben. + Die Eval-Funktion, über die der aktuelle Wert abgerufen werden soll, wird auf Ebene des Objekt-Items über das Attribut "se_eval_<Bedingungsname>'" angegeben. Der Bedingungsname in "se_item" bzw. "se_eval'" muss mit den Bedingungsnamen in den Bedingungen korrespondieren.

+ +

Das sich Altersbedingungen auf das Alter der hinterlegten Items beziehen können "se_agemin_<Bedingungsname>", "se_agemax_<Bedingungsname>" und "se_agenegate_<Bedingungsname>" nur verwendet werden, wenn der aktuelle Wert über ein Item bereitgestellt wird.

+ +

Beispiel

+ +
beispiel:
+        raffstore1:
+            automatik:
+                rules:
+                    <...>
+                    se_item_height: beispiel.raffstore1.hoehe
+                    se_item_lamella: beispiel.raffstore1.lamelle
+                    se_item_brightness: beispiel.wetterstation.helligkeit
+                    Daemmerung:
+                        type: foo
+                        name: Dämmerung
+                        <Aktionen>
+                        enter:
+                            se_min_brightness: 500
+                            se_max_brightness: value:1000
+
+                    Nacht:
+                        type: foo
+                        name: Nacht
+                        <Aktionen>
+                        enter_todark:
+                            se_max_brightness: 500
+
+                    Sonder:
+                        type: foo
+                        name: Ein spezielles Bedingungsset
+                        <Aktionen>
+                        enter:
+                            se_min_brightness: item:test.wert
+                            se_max_brightness: eval:sh.test.wert() + 500
+    
+ +

"Besondere" Bedingungen

+ +

Das Plugin stellt die Werte für einige "besondere" Bedingungen automatisch bereit. Für diese Bedingungen muss daher kein Item und keine Eval-Funktion zur Ermittlung des aktuellen Werts angegeben werden. + Die "besonderen" Bedingungen werden über reservierte Bedingungsnamen gekennzeichnet. Diese Bedingungsnamen dürfen daher nicht für andere Bedingungen verwendet werden.

+ +

Die folgenden "besonderen" Bedingungsnamen können verwendet werden

+ +

time

+ +

Aktuelle Uhreit

+ +

Die Werte für "se_value_time", "se_min_time" und "se_max_time" müssen im Format "hh:mm" (":") angegeben werden. Es wird ein 24 Stunden-Zeitformat verwendet. Beispiele: "08:00" oder "13:37". Um das Ende des Tages anzugeben kann der Wert "24:00" verwendet werden, der für die Prüfungen automatisch zu "23:59:59" konvertiert wird.

+ +

weekday

+ +

Wochentag

+ +

0 = Montag, 1 = Dienstag, 2 = Mittwoch, 3 = Donnerstag, 4 = Freitag, 5 = Samstag, 6 = Sonntag

+ +

month

+ +

_Monat | 1 = Januar, ..., 12 = Dezember

+ +

sun_azimut

+ +

Sonnenstand (Horizontalwinkel)

+ +

Der Azimut (Horizontalwinkel) ist die Kompasrichtung in der die Sonne steht. Der Azimut wird von smarthomeNg auf Basis der aktuellen Zeit sowie der konfigurierten geographischen Position berechnet. Siehe auch SmarthomeNg Dokumentation für Voraussetzungen zur Berechnung der Sonnenposition. Beispielwerte: 0 → Sonne exakt im Norden, 90 → Sonne exakt im Osten, 180 → Sonne exakt im Süden, 270 → Sonne exakt im Westen

+ +

sun_altitude

+ +

Sonnenstand (Vertikalwinkel)

+ +

Die Altitude (Vertikalwikel) ist der Winkel, in dem die Sonne über dem Horizont steht. Die Altitude wird von smarthomeNg auf Basis der aktuellen Zeit sowie der konfigurierten geographischen Position berechnet. Siehe auch SmarthomeNG Dokumentation für Voraussetzungen zur Berechnung der Sonnenposition. Werte: negativ → Sonne unterhalb des Horizonts, 0 → Sonnenaufgang/Sonnenuntergang, 90 → Sonne exakt im Zenith (passiert nur in äquatorialen Bereichen)

+ +

age

+ +

Zeit seit der letzten Änderung des Zustands (Sekunden)

+ +

Das Alter wird über die letzte Änderung des Items, dass als se_laststate_item_id angegeben ist, ermittelt.

+ +

random

+ +

Zufallszahl zwischen 0 und 100

+ +

Wenn etwas zufällig mit einer Wahrscheinlichkeit von 60% passieren soll, kan beispielsweise die Bedingung max_random = 60 verwendet werden.

+ +

laststate

+ +

Id des Zustandsitems des aktuellen Status

+ +

Wichtig: Hier muss die vollständige Item-Id angegeben werden

+ +

trigger_item, trigger_caller, trigger_source, trigger_dest

+ +

item, caller, source und dest-Werte durch die die Zustandsermittlung direkt ausgelöst wurde

+ +

Über diese vier Bedingungen kann der direkte Auslöser der Zustandsermittlung abgeprüft werden, also die Änderung, die smarthomeNG veranlasst, die Zustandsermittlung des stateengine-Plugins aufzurufen.

+ +

original_item, original_caller, original_source

+ +

item, caller, source und dest-Werte durch die die Zustandsermittlung ursprünglich ausgelöst wurde

+ +

Über diese vier Bedingungen kann der ursprüngliche Auslöser der Zustandsermittlung abgeprüft werden. Beim Aufruf der Zustandsermittung über einen "eval_trigger" Eintrag wird über "trigger_caller" beispielsweise nur "Eval" weitergegeben. In den drei "original_*" Bedingungen wird in diesem Fall der Auslöser der Änderung zurückverfolgt und der Einstieg in die "Eval"-Kette ermittelt.

+
+
+{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku6.html b/stateengine/webif/templates/doku6.html new file mode 100755 index 000000000..b0bbb501f --- /dev/null +++ b/stateengine/webif/templates/doku6.html @@ -0,0 +1,157 @@ +{% extends "base_plugin.html" %} +{% block scripts %} +{{ super() }} + +{% endblock scripts %} +{% set logo_frame = false %} + + +{% set item_count = p.__items|length %} +{% set tab1title = "StateEngine" %} +{% set tabcount = 1 %} + +{% block headtable %} + + + + + + + + + + + + + + + + + + + + + + + + + +
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
+{% endblock headtable %} + + +{% block bodytab1 %} + +
+ +
+

Aktionen - Ausführungszeitpunkt

+ +

Um festzulegen, wann die Aktionen eines Zustands ausgeführt werden, gibt es vier Ereignisse, denen die Aktionen zugeordnet werden können: + Für jedes dieser Ereignisse wird ein Item unterhalb des Zustands-Items angelegt, unterhalb dem die jeweiligen Aktionen als Attribute definiert werden.

+ +
    +
  • on_enter: Aktionen, die beim erstmaligen Aktivieren des Zustands ausgeführt werden
  • + +
  • on_stay: Aktionen, die ausgeführt werden, wenn der Zustand zuvor bereits aktiv war und weiterhin aktiv bleibt.
  • + +
  • on_enter_or_stay: Aktionen, die ausgeführt werden, wenn der Zustand aktiv ist, unabhängig davon, ob er bereits zuvor aktiv war oder nicht.
  • + +
  • on_leave: Aktionen, die ausgeführt werden, direkt bevor ein anderer Zustand aktiv wird.
  • +
+ +

Aktionen können auch ohne diese Ereigniss-Items direkt im Zustands-Item definiert werden. Solche Aktionen werden analog zum Ereignis on_enter_or_stay behandelt.

+ +

Beispiel

+ +
test:
+        type: foo
+
+        events:
+            name: stateengine Event Beispiel
+            type: foo
+
+            item:
+                name: Dummy Item
+                type: bool
+                value: False
+
+            rules:
+                type: bool
+                name: Automatik Test Event
+                # Dies ist ein Objekt-Item für das stateengine-Plugin:
+                se_plugin: active
+
+                state1:
+                    type: foo
+                    name: Status 1
+
+                    on_enter:
+                    type: foo
+                    name: Ausführen immer wenn ein Zustand gerade aktiv geworden ist
+                    <... Aktionen ...>
+
+                    on_stay:
+                    type: foo
+                    name: Ausführen immer wenn ein Zustand aktiv geworden ist und bereits vorher aktiv war
+                    <... Aktionen ...>
+
+                    on_enter_or_stay:
+                    type: foo
+                    name: Ausführen immer wenn ein Zustand aktiv ist
+                    <... Aktionen ...>
+
+                    on_leave:
+                    type: foo
+                    name: Ausführen beim Verlassen des Zustands
+                    <... Aktionen ...>
+
+                    enter_1:
+                    type: foo
+                    name: Bedingung 1
+                    <...Einstiegs-Bedingungsset 1...>
+
+                    enter_2:
+                    type: foo
+                    name: Bedingung 2
+                    <...Einstiegs-Bedingungsset 2...>
+
+                state2:
+                    type: foo
+                    name: Status 2
+                    <... Weitere Bedingungssets und Aktionsgruppen ...>
+
+                state3:
+                    type: foo
+                    name: Status 3
+                    <... Weitere Bedingungssets und Aktionsgruppen ...>
+    
+
+
+{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku7.html b/stateengine/webif/templates/doku7.html new file mode 100755 index 000000000..aa24c261b --- /dev/null +++ b/stateengine/webif/templates/doku7.html @@ -0,0 +1,260 @@ +{% extends "base_plugin.html" %} +{% block scripts %} +{{ super() }} + +{% endblock scripts %} +{% set logo_frame = false %} + + +{% set item_count = p.__items|length %} +{% set tab1title = "StateEngine" %} +{% set tabcount = 1 %} + +{% block headtable %} + + + + + + + + + + + + + + + + + + + + + + + + + +
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
+{% endblock headtable %} + + +{% block bodytab1 %} + +
+ +
+

Aktionen - Einzelvariante

+ +

Bei der Einzelvariante zur Definition von Aktionen werden alle Parameter einer Aktion in separaten Attributen definiert. Über den gemeinsamen Aktionsnamen gehören die Attribute einer Aktion zusammen.

+ +

Ähnlich wie Bedingungen benötigen auch Aktionen einen Namen. Der Name ist auch hier beliebig und wird lediglich in der Benennung der Attribute verwendet. Die Namen aller Attribute, die zu einer Bedingung gehören, folgen dem Muster "se_<Funktion>_<Aktionsname>".

+ +

Aktion: Item auf einen Wert setzen

+ +
    se_set_<Aktionsname>
+    
+ +

Das Item, dass verändert werden soll, muss auf Ebene des Objekt-Items über das Attribut "se_item_<Aktionsname>" angegeben werden.

+ +

Das Attribut "se_set_<Aktionsname>" nutzt den [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]]. Der Wert, auf den das Item gesezt wird kann dadurch als statischer Wert, als Wert eines Items oder als Ergebnis der Ausführung einer Funktion festgelegt werden.

+ +

Minimumabweichung: + Es ist möglich eine Minimumabweichung für Änderungen zu definieren. Wenn die Differenz zwischen dem aktuellen Wert des Items und dem ermittelten neuen Wert kleiner ist als die festgelegte Minimumabweichung wird keine Änderung vorgenommen. Die Minimumabweichung wird über das Attribut "se_mindelta_<Aktionsname>" auf der Ebene des Objekt-Items festgelegt. Auch hier wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet.

+ +

Aktion: Item zwangsweise auf einen Wert setzen

+ +
    se_force_<Aktionsname>
+    
+ +

Diese Aktion funktioniert analog zu se_set_<Aktionsname>. Einziger Unterschied ist, dass die Wertänderung erzwungen wird: Wenn das Item bereits den zu setzenden Wert hat, dann ändert smarthomeNG das Item nicht. Selbst wenn beim Item das Attribut enforce_updates = yes gesetzt ist, wird zwar der Wert neu gesetzt, der von smarthomeNG Änderungszeit nicht neu gesetzt. Mit dem Attribut se_force_<Aktionsname> wird das Plugin den Wert des Items bei Bedarf zuerst auf einen anderen Wert ändern und dann auf dem Zielwert setzen. Damit erfolgt auf jeden Fall eine Wertänderung (ggf. sogar zwei) mit allen damit in Zusammenhang stehenden Änderungen (eval's, Aktualisierung der Änderungszeiten, etc).

+ +

Aktion: Ausführen einer Funktion

+ +
    se_run_<Aktionsname>: eval:(Funktion)
+    
+ +

Die Angabe ist vergleichbar mit dem Ausführen einer Funktion zur Ermittlung des Werts für ein Item, hier wird jedoch kein Item benötigt. Außerdem wird der Rückgabewert der Funktion ignoriert.

+ +

Aktion: Auslösen einer Logikausführung

+ +
    se_trigger_<Aktionsname>
+    
+ +

Um beim Auslösen einen Wert an die Logik zu übergeben, kann dieser Wert im Attribut über die Angabe von :<Wert> hinter dem Logiknamen angegeben werden.

+ +

Beispiel:

+ +
    se_trigger_<Aktionsname>: meineLogik:Zu übergebender Wert
+    
+ +

Aktion: Alle Items, die ein bestimmtes Attribut haben, auf den Wert dieses Attributs setzen

+ +
    se_byattr_<Aktionsname>
+    
+ +

Mit diesem Attribut wird der Name eines anderen (beliebigen) Attributs angegeben. Beim Ausführen werden alle Items herausgesucht, die das angegebene Attribut enthalten. Diese Items werden auf den Wert gesetzt, der dem genannten Attribut in den Items jeweils zugewiesen ist.

+ +

Beispiel:

+ +
    se_byattr_<Aktionsname>: mein_eigenes_Attribut
+    
+ +

sucht alle Items heraus, bei denen das Attribut "mein_eigenes_Attribut" angegeben ist. + Ein Item

+ +
    dummy:
+            type: num
+            mein_eigenes_Attribut: 42
+    
+ +

wird dann auf "42" gesetzt.
+ Ein anderes Item

+ +
    dummy2:
+            type: str
+            mein_eigenes_Attribut: Rums
+    
+ +

wird gleichzeitig auf "Rums" gesetzt.

+ +

Aktion: Sondervorgänge

+ +
    se_special_<Aktionsname>: (Sondervorgang)
+    
+ +

Für bestimmte Sondervorgänge sind besondere Aktionen im Plugin definiert (z. B. für das Suspend). Diese werden jedoch nicht hier erläutert, sondern an den Stellen, andenen Sie verwendet werden.

+ +

Verzögertes Ausführen einer Aktion

+ +
    se_delay_<Aktionsname>
+    
+ +

Über das Attribut wird die Verzögerung angegeben, nach der die Aktion ausgeführt werden soll. Die Angabe erfolgt in Sekunden oder mit dem Suffix "m" in Minuten.

+ +
    se_delay_<Aktionsname>: 30         --> 30 Sekunden
+        se_delay_<Aktionsname>: 30m        --> 30 Minuten
+    
+ +

Der Timer zur Ausführung der Aktion nach der angegebenen Verzögerung wird entfernt, wenn eine gleichartike Aktion ausgeführt werden soll (egal ob verzögert oder nicht). Wenn also die Verzögerung größer als der "cycle" ist, wird die Aktion nie durchgeführt werden, es sei denn die Aktion soll nur einmalig ausgeführt werden.
+ Das Attribut "se_delay_<Aktionsname>" verwendet den [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]]

+ +

Wiederholen einer Aktion

+ +
    se_repeat_<Aktionsname>
+    
+ +

Über das Attribut wird unabhängig vom globalen Setting für das stateengine Item festgelegt, ob eine Aktion auch beim erneuten Eintritt in den Status ausgeführt wird oder nicht.

+ +
    se_delay_<Aktionsname>: True    # Aktion wird bei jedem Mal aufs neue ausgeführt
+        se_delay_<Aktionsname>: False   # Aktion wird nur beim ersten Eintritt in den Status ausgeführt
+    
+ +

Festlegen der Ausführungsreihenfolge von Aktionen

+ +
    se_order_<Aktionsname>
+    
+ +

Die Reihenfolge, in der die Aktionen ausgeführt werden, ist nicht zwingend die Reihenfolge in der die Attribute definiert sind. In den meisten Fällen ist dies kein Problem da die Aktionen voneinander unabhängig sind und daher in beliebiger Reihenfolge ausgeführt werden können. In Einzelfällen kann es jedoch erforderlich sein, mehrere Aktionen in einer bestimmten Reihenfolge auszuführen. Dies kann über das Attribut se_order_<Aktionsname> erfolgen. Mit diesem Attribut wird der Aktion eine Zahl zugewiesen. Aktionen werden in aufsteigender Reihenfolge der zugewiesenen Zahlen ausgeführt.

+ +

Es ist möglich zwei Aktionen die gleiche Zahl zuzuweisen, die Reihenfolge der beiden Aktionen untereinander ist dann wieder undefiniert. Innerhalb der gesamten Aktionen werden die beiden Aktionen jedoch an der angegebenen Position ausgeführt.

+ +

Wird für eine Aktion kein Reihenfolgenwert angegeben, wird implizit der Wert 1 verwendet.

+ +

Das Attribut "se_order_<Aktionsname>" verwendet den [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]]

+ +

Beispiel zur Ausführungsreihenfolge:

+ +
beispiel:
+        automatik:
+            rules:
+                <...>
+                Zustand1:
+                    se_order_aktion1: 3
+                    se_order_aktion2: 2
+                    se_order_aktion3: 1
+                    se_order_aktion4: 2
+    
+ +

Die Reihenfolge der Aktionen hier wird wie folgt sein:

+ +
    +
  1. aktion3
  2. + +
  3. aktion2, aktion4 ODER aktion4, aktion2
  4. + +
  5. aktion 1
  6. +
+ +

Ist zusätzlich eine aktion5 definiert, die keine Reihenfolge festgelegt hat, wird die Reihenfolge der Aktionen wie folgt sein:

+ +
    +
  1. aktion3, aktion5 ODER aktion5, aktion3
  2. + +
  3. aktion2, aktion4 ODER aktion4, aktion2
  4. + +
  5. aktion 1
  6. +
+ +

Beispiel zu Aktionen

+ +
beispiel:
+        raffstore:
+            automatik:
+                rules:
+                    <...>
+                    se_item_height: beispiel.raffstore1.hoehe
+                    se_mindelta_height: 10
+                    se_item_lamella: beispiel.raffstore1.lamelle
+                    se_mindelta_lamella: 5
+                    Daemmerung:
+                        <...>
+                        se_set_height: value:100
+                        se_set_lamella: value:25
+                        <...>
+                    Nacht:
+                        <...>
+                        se_set_height: value:100
+                        se_set_lamella: value:0
+                        <...>
+                    Nachfuehren:
+                        <...>
+                        se_set_height: value:100
+                        se_set_lamella: eval:stateengine_eval.sun_tracking()
+                        <...>
+                    Sonder:
+                        <...>
+                        se_trigger_logic1: myLogic:42
+                        se_delay_logic1: 10
+                        <...>
+    
+
+
+{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku8.html b/stateengine/webif/templates/doku8.html new file mode 100755 index 000000000..070198cbf --- /dev/null +++ b/stateengine/webif/templates/doku8.html @@ -0,0 +1,234 @@ +{% extends "base_plugin.html" %} +{% block scripts %} +{{ super() }} + +{% endblock scripts %} +{% set logo_frame = false %} + + +{% set item_count = p.__items|length %} +{% set tab1title = "StateEngine" %} +{% set tabcount = 1 %} + +{% block headtable %} + + + + + + + + + + + + + + + + + + + + + + + + + +
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
+{% endblock headtable %} + + +{% block bodytab1 %} + +
+ +
+

Aktionen - Kombinierte Variante

+ +

Bei der kombinierten Variante zur Definition von Aktionen werden alle Parameter einer Aktion in einem Attribut definiert. Über den Aktionsnamen werden lediglich eventuelle Items zugeordnet. + Die einzelnen Parameter werden bei conf-Files in der Listenschreibweise mit dem Zeichen | getrennt aufgelistet:

+ +
 se_action_<Aktionsname>: function: <func> | (evtl. Detailparameter zur Funktion) | delay: <delay> | order: <order> | repeat: <repeat>
+    
+ +

Bei yaml Files werden die Parameter mittels Aufzählungszeichen "-" untereinander definiert:

+ +
 se_action_<Aktionsname>:
+        - function: <func>
+        - Detailparameter der Funktion, z.B. "to: .."
+        - delay: <delay>
+        - order: <order>
+        - repeat: <repeat>
+    
+ +

Die Parameter haben dabei folgende Bedeutung:

+ +

delay: <delay>

+ +

Über <delay> wird die Verzögerung angegeben, nach der die Aktion ausgeführt werden soll.

+ +

Der Parameter ist optional und kann auch weggelassen werden. In diesem Fall wird die Aktion sofort ausgeführt.

+ +

Die Angabe erfolgt in Sekunden oder mit dem Suffix "m" in Minuten.

+ +
    delay: 30         --> 30 Sekunden
+        delay: 30m        --> 30 Minuten
+    
+ +

Der Timer zur Ausführung der Aktion nach der angegebenen Verzögerung wird entfernt, wenn eine gleichartike Aktion ausgeführt werden soll (egal ob verzögert oder nicht). Wenn also die Verzögerung größer als der "cycle" ist, wird die Aktion nie durchgeführt werden, es sei denn die Aktion soll nur einmalig ausgeführt werden.
+ Für den Wert von <delay> wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet.

+ +

repeat: <repeat>

+ +
    se_repeat_<Aktionsname>
+    
+ +

Über das Attribut wird unabhängig vom globalen Setting für das stateengine Item festgelegt, ob eine Aktion auch beim erneuten Eintritt in den Status ausgeführt wird oder nicht.

+ +
    se_delay_<Aktionsname>: True    # Aktion wird bei jedem Mal aufs neue ausgeführt
+        se_delay_<Aktionsname>: False   # Aktion wird nur beim ersten Eintritt in den Status ausgeführt
+    
+ +

order: <order>

+ +

Die Reihenfolge, in der die Aktionen ausgeführt werden, ist nicht zwingend die Reihenfolge in der die Attribute definiert sind. In den meisten Fällen ist dies kein Problem da die Aktionen voneinander unabhängig sind und daher in beliebiger Reihenfolge ausgeführt werden können. In Einzelfällen kann es jedoch erforderlich sein, mehrere Aktionen in einer bestimmten Reihenfolge auszuführen. Dies kann über den Parameter order: <order> erfolgen. Mit diesem Attribut wird der Aktion eine Zahl zugewiesen. Aktionen werden in aufsteigender Reihenfolge der zugewiesenen Zahlen ausgeführt.

+ +

Der Parameter ist optional und kann auch weggelassen werden. Für Aktionen, denen keine Reihenfolge explizit zugewiesen wurde, wird der Reihenfolgenwert 1 verwendet.

+ +

Es ist möglich zwei Aktionen die gleiche Zahl zuzuweisen, die Reihenfolge der beiden Aktionen untereinander ist dann wieder undefiniert. Innerhalb der gesamten Aktionen werden die beiden Aktionen jedoch an der angegebenen Position ausgeführt.

+ +

Für den Wert von <order> wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet.

+ +

function: <func>

+ +

Mit dem Parameter <func> wird die auszuführende Funktion festgelegt. In Abhängigkeit zur gewählten Funktion werden zusätzliche Detailparameter erforderlich.
+ Folgende Werte sind möglich:

+ +

Funktion set: Item auf einen Wert setzen

+ +
se_action_<Aktionsname>: function: set | to: <val> | force: [True/False]
+    
+ +

Das Item, dass verändert werden soll, muss auf Ebene des Objekt-Items über das Attribut "se_item_<Aktionsname>" angegeben werden.

+ +

Der Parameter to: <val> legt fest, auf welchen Wert das Item gesetzt werden soll. Für <val> wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet. Der Wert, auf den das Item gesezt wird kann dadurch als statischer Wert, als Wert eines Items oder als Ergebnis der Ausführung einer Funktion festgelegt werden.

+ +

Erzwingen der Wertänderung: + Über den optionalen Parameter force: [True/False] kann eine Wertänderung erzwungen werden: Wenn das Item bereits den zu setzenden Wert hat, dann ändert smarthomeNG das Item nicht. Selbst wenn beim Item das Attribut enforce_updates = yes gesetzt ist, wird zwar der Wert neu gesetzt, der von smarthomeNG Änderungszeit nicht neu gesetzt. Wird der Parameter force: True gesetzt, so wird das Plugin den Wert des Items bei Bedarf zuerst auf einen anderen Wert ändern und dann auf dem Zielwert setzen. Damit erfolgt auf jeden Fall eine Wertänderung (ggf. sogar zwei) mit allen damit in Zusammenhang stehenden Änderungen (eval's, Aktualisierung der Änderungszeiten, etc).

+ +

Minimumabweichung: + Es ist möglich eine Minimumabweichung für Änderungen zu definieren. Wenn die Differenz zwischen dem aktuellen Wert des Items und dem ermittelten neuen Wert kleiner ist als die festgelegte Minimumabweichung wird keine Änderung vorgenommen. Die Minimumabweichung wird über das Attribut "se_mindelta_<Aktionsname>" auf der Ebene des Objekt-Items festgelegt. Auch hier wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet.

+ +

Funktion run: Ausführen einer Funktion

+ +
se_action_<Aktionsname>: function: run | eval:(Funktion)
+    
+ +

Die Angabe ist vergleichbar mit dem Ausführen einer Funktion zur Ermittlung des Werts für ein Item, hier wird jedoch kein Item benötigt. Außerdem wird der Rückgabewert der Funktion ignoriert.

+ +

Funktion trigger: Auslösen einer Logikausführung

+ +
se_action_<Aktionsname>: function: trigger | logic: <Logikname> | value: <Wert>
+    
+ +

Löst die Ausführung der Logik <Logikname>aus. Um beim Auslösen einen Wert an die Logik zu übergeben, kann dieser Wert über die Angabe von value: <Wert> hinter dem Logiknamen angegeben werden. Wenn kein Wert übergeben werden soll lässt man den Teil weg.

+ +

Funktion byattr: Alle Items, die ein bestimmtes Attribut haben, auf den Wert dieses Attributs setzen

+ +
se_action_<Aktionsname>: function: byattr | attribute: <Attributname>
+    
+ +

Mit dieser Funktion wird der Name eines anderen (beliebigen) Attributs angegeben. Beim Ausführen werden alle Items herausgesucht, die das angegebene Attribut enthalten. Diese Items werden auf den Wert gesetzt, der dem genannten Attribut in den Items jeweils zugewiesen ist.

+ +

Beispiel:

+ +
    se_action_<Aktionsname>: function: byattr | attribute: mein_eigenes_Attribut
+    
+ +

sucht alle Items heraus, bei denen das Attribut "mein_eigenes_Attribut" angegeben ist. + Ein Item

+ +
    dummy1:
+            type: num
+            mein_eigenes_Attribut: 42
+    
+ +

wird dann auf "42" gesetzt.
+ Ein anderes Item

+ +
    dummy2:
+            type: str
+            mein_eigenes_Attribut: Rums
+    
+ +

wird gleichzeitig auf "Rums" gesetzt.

+ +

Funktion special: Sondervorgänge

+ +
se_action_<Aktionsname>: function: special | value: <Sondervorgang>
+    
+ +

Für bestimmte Sondervorgänge sind besondere Aktionen im Plugin definiert (z. B. für das Suspend). Diese werden jedoch nicht hier erläutert, sondern an den Stellen, andenen Sie verwendet werden.

+ +

Beispiel zu Aktionen

+ +
beispiel:
+        raffstore:
+            automatik:
+                rules:
+                    <...>
+                    se_item_height: beispiel.raffstore1.hoehe
+                    se_mindelta_height: 10
+                    se_item_lamella: beispiel.raffstore1.lamelle
+                    se_mindelta_lamella: 5
+                    Daemmerung:
+                        <...>
+                        se_action_height: function: set | to: value:100
+                        se_action_lamella: function: set | to: value:25
+                        <...>
+                    Nacht:
+                        <...>
+                        se_action_height: function: set | to: value:100
+                        se_action_lamella: function: set | to: value:0
+                        <...>
+                    Nachfuehren:
+                        <...>
+                        se_action_height: function: set | to: value:100
+                        se_action_lamella: function: set | to: eval:stateengine_eval.sun_tracking()
+                        <...>
+                    Sonder:
+                        <...>
+                        se_action_logic1: function: trigger | logic: myLogic | value:42 | delay: 10
+                        <...>
+    
+
+
+{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku9.html b/stateengine/webif/templates/doku9.html new file mode 100755 index 000000000..74787fc68 --- /dev/null +++ b/stateengine/webif/templates/doku9.html @@ -0,0 +1,146 @@ +{% extends "base_plugin.html" %} +{% block scripts %} +{{ super() }} + +{% endblock scripts %} +{% set logo_frame = false %} + + +{% set item_count = p.__items|length %} +{% set tab1title = "StateEngine" %} +{% set tabcount = 1 %} + +{% block headtable %} + + + + + + + + + + + + + + + + + + + + + + + + + +
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
+{% endblock headtable %} + + +{% block bodytab1 %} + +
+ +
+

Vorgabezustände verwenden

+ +

Es ist möglich Vorgabezustände in der Konfiguration zu definieren und diese später für konkrete Objekte anzuwenden. Dabei können im konkreten Zustand auch Einstellungen des Vorgabezustands überschrieben werden.

+ +

Vorgabezustände werden als Item an beliebiger Stelle innerhalb der Item-Struktur definiert. Es ist sinnvoll, die Vorgabezustände unter eingem gemeinsamen Item zusammenzufassen. Innerhalb der Vorgabezustand-Items stehen die gleichen Möglichkeiten wie in normalen Zustands-Items zur Verfügung. Das dem Vorgabezustands-Item übergeordnete Item darf nicht das Attribut "se_plugin: active" haben. Im Item über dem Vorgabezustands-Item können jedoch Items über "se_item_<Bedingungsname|Aktionsname>" angegeben werden. Diese stehen in den Vorgabezuständen und in den von den Vorgabezuständen abgeleiteten Zuständen zur Verfügung und müssen so nicht jedes mal neu definiert werden.

+ +

Im konkreten Zustands-Item kann das Vorgabezustand-Item über das Attribut

+ +
se_use: <Id des Vorgabezustand-Item>
+    
+ +

eingebunden werden. Die Vorgabezustand-Items können geschachtelt werden, dass heißt ein Vorgabezustand kann also selbst wiederum über se_use von einem weiteren Vorgabezustand abgeleitet werden. Um unnötige Komplexität und Zirkelbezüge zu vermeiden ist die maximale Tiefe jedoch auf 5 Ebenen begrenzt.

+ +

Beispiel

+ +
beispiel:
+        default:
+            <...>
+            se_item_height: ...hoehe
+            Nacht:
+                <...>
+                enter:
+                    (...)
+                se_set_height: value:100
+                se_set_lamella: 0
+            Morgens:
+                <...>
+                enter:
+                    <...>
+                se_set_height: value:100
+                se_set_lamella: 25
+
+            Abends:
+                <...>
+                enter:
+                    <...>
+                se_set_height: value:100
+                se_set_lamella: 75
+
+            Tag:
+                <...>
+                enter:
+                    <...>
+                se_set_height: value:0
+                se_set_lamella: 100
+
+    beispiel
+        raffstore1:
+            automatik:
+                rules:
+                    <...>
+                    se_item_lamella: beispiel.raffstore1.lamelle
+                    Nacht:
+                        se_use: beispiel.default.Nacht
+                        enter_additional:
+                            <... zusätzliche Einstiegsbedingung ...>
+                    Morgens:
+                        se_use: beispiel.default.Morgens
+                    Abends:
+                        se_use: beispiel.default.Abends
+                        enter:
+                            <... Änderungen an der Einstiegsbedingung des Vorgabezustands ...>
+                    Nachfuehren:
+                        <...>
+                        name: Zusätzlicher Zustand, der nicht aus den Vorgabezuständen kommt
+                        se_set_height: value:100
+                        se_set_lamella: eval:stateengine_eval.sun_tracking()
+                    Tag:
+                        se_use: stateengine.default.day
+    
+
+
+{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/index.html b/stateengine/webif/templates/index.html new file mode 100755 index 000000000..903423d8e --- /dev/null +++ b/stateengine/webif/templates/index.html @@ -0,0 +1,123 @@ +{% extends "base_plugin.html" %} +{% block scripts %} +{{ super() }} + +{% endblock scripts %} +{% set logo_frame = false %} + + +{% set item_count = p.__items|length %} +{% set tab1title = "_('Dokumentation')" %} +{% set tab2title = "Items" %} +{% set tabcount = 1 %} + +{% block headtable %} + + + + + + + + + + + + + + + + + + + + + + + + + +
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
+{% endblock headtable %} + + +{% block bodytab1 %} + +
+ +
+

stateengine Plugin für smarthomeNG - Deutsche Dokumentation

+ +

Warnung

+ +

Wichtig: + Es ist nicht empfehlenswert das stateengine Plugin für sicherheitsrelevante Zustände, wie zum Beispiel das Hochfahren von Jalousien bei zu viel Wind, zu verwenden. Sicherheitsrelevante Funktionen müssen so einfach wie möglich aufgebaut sein. Es wird daher dringend dazu geraten, solche Funktionen unabhängig von smarthomeNG und dem stateengine Plugin zu realisieren. Für das Hochfahren von Jalousien bei Windalarm beispielsweise sollte die Sperrfunktionalität verwendet werden, über die alle aktuellen Jalousieaktoren verfügen!

+ +

Funktionalität

+ +

Über zusätzliche Items in den items/*.conf-Dateien können Objekte definiert werden, die eine beliebige Anzahl benutzerdefinierter Zustand haben. Jeder Zustand kann Sets von Einstiegs- und Ausstiegsbedingungen haben, sowie diverse Aktionen auslösen, wenn der Zustand aktiv wird. In regelmäßigen Intervallen werden die Zustände für jedes Objekt geprüft.

+ +
    +
  • Wenn die Ausstiegsbedingungen des aktuellen Zustands nicht erfüllt sind bleibt das Objekt im aktuellen Zustand.
  • + +
  • Wenn der aktuelle Zustand verlassen werden kann werden alle Zustände in der Reihenfolge, in der sie in der Konfigurationsdatei definiert sind, abgeprüft.
  • + +
  • Der erste Zustand bei dem eine Gruppe Einstiegsbedingungen vollständig erfüllt ist, wird zum aktuellen Zustand. Die Aktionen, die für diesen Zustand definiert sind, werden ausgeführt.
  • + +
  • Wenn kein passender Zustand gefunden wird passiert nichts. Das Objekt verbleibt im vorherigen Zustand.
  • +
+ +

Die folgenden Bedingungen können Teil der Bedingungsgruppen sein:

+ +
    +
  • Tageszeit (Minimum, Maximum, Wert)
  • + +
  • Wochentag (Minimum, Maximum, Wert)
  • + +
  • Azimut der Sonne (Minimum, Maximum, Wert)
  • + +
  • Altitude der Sonne (Minimum, Maximum, Wert)
  • + +
  • Alter des aktuellen Zustands (Minimum, Maximum, Wert)
  • + +
  • Zufallszahl (Minimum, Maximum, Wert)
  • + +
  • Vorheriger Zustand (Wert)
  • + +
  • Trigger-Objekt, dass die Zustandsermittlung ausgelöst hat
  • +
+ +

Zusätzlich können beliebige Items als Bedingungen geprüft werden (Minimum, Maximum oder Wert)

+ +

Der ursprüngliche Zweck dieses Plugins war es, Jalousien zu steuern. Mit den steigenden Anforderungen hat es sich jedoch zu einem flexiblen Zustandsautomaten entwickelt, mit dem nahezu alles gesteuert werden kann. Im Prinzip ist es ein endlicher Automat.

+
+ + +
+{% endblock bodytab1 %} From 92eae94f7b122da31181fbf60c71c4d66ad9bf66 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sun, 7 Oct 2018 20:58:06 +0200 Subject: [PATCH 308/705] small update for webif status --- uzsu/README.md | 4 ++-- uzsu/__init__.py | 2 +- uzsu/plugin.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/uzsu/README.md b/uzsu/README.md index 03d00d350..2d122f967 100755 --- a/uzsu/README.md +++ b/uzsu/README.md @@ -23,7 +23,7 @@ apt-get install libatlas-base-dev ### v1.4.1 - 1.5.1 * Added a web interface for easier debugging -* Added "back in time" feature to re-trigger missed uzsu evaluations on smarthomeng startup +* Added "back in time"/initage feature to re-trigger missed uzsu evaluations on smarthomeng startup * Added interpolation feature: the UZSU can now be used for smooth transitions of values (e.g. for light dimming, etc.) * Added item functions to (de)activate, change interpolation and query some settings from the uzsu item via logic * Fixed uzsu evaluation for entries without an rrule setting (day of week) @@ -82,7 +82,7 @@ Each UZSU item is of type list. Each list entry has to be a dict with specific k * __interval__: integer, sets the time span in seconds between the automatic triggers based on the interpolation calculation -* __initage__: integer, sets the amount of seconds the plugin should go back in time at startup to find the last UZSU item and triggers that right on startup of the plugin. This is useless if interpolation is active as the interpolated time will get set an init anyhow. +* __initage__: integer, sets the amount of seconds the plugin should go back in time at startup to find the last UZSU item and triggers that right on startup of the plugin. This is useless if interpolation is active as the interpolated time will get set on init anyhow. * __itemtype__: the type of the item that should be changed by the UZSU. This is set automatically on init and should not be touched. diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 15b546fa8..6a81e0612 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -414,7 +414,7 @@ def _schedule(self, item, caller=None): if not self._items[item]['interpolation'].get('itemtype'): self.logger.error("item '{}' to be set by uzsu does not exist.".format( self.get_iattr_value(item.conf, ITEM_TAG[0]))) - elif self._items[item].get('list') is None: + elif not self._items[item].get('list'): self.logger.warning("uzsu item '{}' is active but has no entries.".format(item)) self._planned.update({item: None}) elif self._items[item].get('active') is True: diff --git a/uzsu/plugin.yaml b/uzsu/plugin.yaml index ae7971e10..f9cc24a82 100755 --- a/uzsu/plugin.yaml +++ b/uzsu/plugin.yaml @@ -5,7 +5,7 @@ plugin: description: # Alternative: description in multiple languages de: 'Universelle Zeitschaltuhr' en: 'Universal time switch' - maintainer: onkelandy + maintainer: cmalo, bmxp, onkelandy tester: Sandman60, cmalo, schuma # keywords: iot xyz documentation: https://github.com/smarthomeNG/smarthome/wiki/UZSU-%28Universelle-Zeitschaltuhr%29 # url of documentation (wiki) page From 9a5f57d6322c7be9f45ac7516a92282e50f16cc8 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Mon, 8 Oct 2018 08:04:18 +0200 Subject: [PATCH 309/705] corrected log entry at startup --- uzsu/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 6a81e0612..cdc8bbc6a 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -414,7 +414,7 @@ def _schedule(self, item, caller=None): if not self._items[item]['interpolation'].get('itemtype'): self.logger.error("item '{}' to be set by uzsu does not exist.".format( self.get_iattr_value(item.conf, ITEM_TAG[0]))) - elif not self._items[item].get('list'): + elif not self._items[item].get('list') and self._items[item].get('active') is True: self.logger.warning("uzsu item '{}' is active but has no entries.".format(item)) self._planned.update({item: None}) elif self._items[item].get('active') is True: From e0c413ed4029214d7048ea6b95e3535bd1b3efbb Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Mon, 8 Oct 2018 10:16:42 +0200 Subject: [PATCH 310/705] OperationLog: Include complete log redirection to XMPP The operation log can be used to configure a log. When logging to a given log it is possible to configure a logger which is additionally used when the log gets messages. You can log the messages to a file or other handler. This example describes logging the messages additionally though XMPP to a XMPP contact --- xmpp/README.md | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/xmpp/README.md b/xmpp/README.md index 9dc2c2ef0..3ef6270d8 100755 --- a/xmpp/README.md +++ b/xmpp/README.md @@ -25,10 +25,22 @@ loggers: level: WARN ``` -This requires a XMPP plugin configured in a section named `xmpp` -which is used in the `xmpp_plugin` setting. The receiver and type needs -to be specified to configure the target receiving the log -messages. +This requires a XMPP plugin configured in a section named `xmpp` (e.g. +see below for example) which is referenced in the `xmpp_plugin` setting. +The receiver and chat type needs to be specified to configure the target +contact receiving the messages. + +It is also possible to log all messages to a given operation log instance +via XMPP. E.g. when having multiple operation logs configured, one for events +one for alarms, the alarms operation log can be send via XMPP when it +receives log messages: + +```yaml +loggers: + plugins.operationlog.alarms: + handlers: [xmpp] + level: INFO +``` ## Configuration From beae438ceda1b3f8d19b85122fc054e852aa5258 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Mon, 8 Oct 2018 11:09:22 +0200 Subject: [PATCH 311/705] improved log info for inactive uzsu entries --- uzsu/__init__.py | 51 ++++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index cdc8bbc6a..208b16f61 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -134,10 +134,14 @@ def run(self): self.logger.debug("Going to update {} items: {}".format(self._update_count['todo'], list(self._items.keys()))) for item in self._items: - cond1 = self._items[item].get('active') and self._items[item]['active'] is True + cond1 = self._items[item].get('active') is True cond2 = self._items[item].get('list') + self._check_rruleandplanned(item) if cond1 and cond2: self._schedule(item, caller='run') + elif cond1 and not cond2: + self.logger.warning("Item '{}' is active but has no entries.".format(item)) + self._planned.update({item: None}) else: self.logger.debug("Not scheduling item {}, cond1 {}, cond2 {}".format(item, cond1, cond2)) @@ -284,11 +288,14 @@ def _logics_clear(self, clear=False, item=None): def _logics_planned(self, item=None): if self._planned.get(item) not in [None, {}] and self._items[item].get('active') is True: - self.logger.info("Item {} is going to be set to {} at {}".format( + self.logger.info("Item '{}' is going to be set to {} at {}".format( item, self._planned[item]['value'], self._planned[item]['next'])) return self._planned[item] + elif not self._planned.get(item) and self._items[item].get('active') is True: + self.logger.warning("Item '{}' is active but has no (active) entries.".format(item)) + self._planned.update({item: None}) else: - self.logger.info("Nothing planned for item {}.".format(item)) + self.logger.info("Nothing planned for item '{}'.".format(item)) return None def parse_item(self, item): @@ -357,6 +364,23 @@ def _remove_dupes(self, item): item, time, oldvalue, newvalue)) item(self._items[item], 'UZSU Plugin', 'update') + def _check_rruleandplanned(self, item): + if self._items[item].get('list'): + _inactive = 0 + for entry in self._items[item]['list']: + if entry.get('active') is False: + _inactive += 1 + if entry.get('rrule') == '': + try: + _index = self._items[item]['list'].index(entry) + self._items[item]['list'][_index]['rrule'] = 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU' + self.logger.debug("Updated rrule for item: {}".format(item)) + item(self._items[item], 'UZSU Plugin', 'create_rrule') + except Exception as err: + self.logger.warning("Error creating rrule: {}".format(err)) + if _inactive >= len(self._items[item]['list']): + self._planned.update({item: None}) + def update_item(self, item, caller=None, source=None, dest=None): """ This is called by smarthome engine when the item changes, e.g. by Visu or by the command line interface @@ -374,21 +398,7 @@ def update_item(self, item, caller=None, source=None, dest=None): cond = (not caller == 'UZSU Plugin') or source == 'logic' self.logger.debug('Update Item {}, Caller {}, Source {}, Dest {}. Will update: {}'.format( item, caller, source, dest, cond)) - if self._items[item].get('list'): - _inactive = 0 - for entry in self._items[item]['list']: - if entry.get('active') is False: - _inactive += 1 - if entry.get('rrule') == '': - try: - _index = self._items[item]['list'].index(entry) - self._items[item]['list'][_index]['rrule'] = 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR,SA,SU' - self.logger.debug("Updated rrule for item: {}".format(item)) - item(self._items[item], 'UZSU Plugin', 'create_rrule') - except Exception as err: - self.logger.warning("Error creating rrule: {}".format(err)) - if _inactive >= len(self._items[item]['list']): - self._planned.update({item: None}) + self._check_rruleandplanned(item) # Removing Duplicates if self._remove_duplicates is True and self._items[item].get('list') and cond: self._remove_dupes(item) @@ -415,7 +425,7 @@ def _schedule(self, item, caller=None): self.logger.error("item '{}' to be set by uzsu does not exist.".format( self.get_iattr_value(item.conf, ITEM_TAG[0]))) elif not self._items[item].get('list') and self._items[item].get('active') is True: - self.logger.warning("uzsu item '{}' is active but has no entries.".format(item)) + self.logger.warning("item '{}' is active but has no entries.".format(item)) self._planned.update({item: None}) elif self._items[item].get('active') is True: self._itpl.clear() @@ -526,6 +536,9 @@ def _schedule(self, item, caller=None): if self._update_count.get('done') == self._update_count.get('todo'): self.scheduler_trigger('uzsu_sunupdate', by='UZSU Plugin') self._update_count = {'done': 0, 'todo': 0} + elif self._items[item].get('active') is True: + self.logger.warning("item '{}' is active but has no active entries.".format(item)) + self._planned.update({item: None}) def _set(self, item=None, value=None, caller=None): """ From 9257c488b9466d953854c993eccd25fbf6a55fd7 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Mon, 8 Oct 2018 20:33:16 +0200 Subject: [PATCH 312/705] convert negative interval to positive --- uzsu/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 208b16f61..3caa39467 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -268,10 +268,10 @@ def _logics_interpolation(self, type=None, interval=5, backintime=0, item=None): else: self._items[item] = copy.deepcopy(item()) self._items[item]['interpolation']['type'] = str(type).lower() - self._items[item]['interpolation']['interval'] = int(interval) + self._items[item]['interpolation']['interval'] = abs(int(interval)) self._items[item]['interpolation']['initage'] = int(backintime) self.logger.info("Item {} interpolation is set via logic to: type={}, interval={}, backintime={}".format( - item, type, interval, backintime)) + item, type, abs(interval), backintime)) item(self._items[item], 'UZSU Plugin', 'logic') def _logics_clear(self, clear=False, item=None): @@ -450,7 +450,7 @@ def _schedule(self, item, caller=None): if _next and _value is not None and self._items[item].get('active') is True: _reset_interpolation = False _interval = self._items[item]['interpolation'].get('interval') - _interval = 5 if not _interval else int(_interval) + _interval = 5 if not _interval else abs(int(_interval)) _interpolation = self._items[item]['interpolation'].get('type') _interpolation = 'none' if not _interpolation else _interpolation _initage = self._items[item]['interpolation'].get('initage') From 418035f76380634047ee38f6c7833f9af8fbc1bc Mon Sep 17 00:00:00 2001 From: msinn Date: Mon, 8 Oct 2018 22:27:01 +0200 Subject: [PATCH 313/705] hue: Adjusted version number after bugfix (a situation that started growing number of threads) --- hue/__init__.py | 2 +- hue/plugin.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hue/__init__.py b/hue/__init__.py index 4f448a5c8..15375b33c 100755 --- a/hue/__init__.py +++ b/hue/__init__.py @@ -56,7 +56,7 @@ class HUE(SmartPlugin): - PLUGIN_VERSION = "1.4.2" + PLUGIN_VERSION = "1.4.3" def __init__(self, smarthome, hue_ip = '', hue_user = '', hue_port = '80', cycle_lamps = '10', cycle_bridges = '60', default_transitionTime = '0.4'): diff --git a/hue/plugin.yaml b/hue/plugin.yaml index 987d2626e..1123cffaa 100755 --- a/hue/plugin.yaml +++ b/hue/plugin.yaml @@ -11,7 +11,7 @@ plugin: # documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/41379-philips-hue-plugin-neu-v1-0-released - version: 1.4.2 # Plugin version + version: 1.4.3 # Plugin version sh_minversion: 1.3c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False From 1da9cc02182a2f6f17ed49698d6ef08cf36d7f77 Mon Sep 17 00:00:00 2001 From: msinn Date: Mon, 8 Oct 2018 22:30:40 +0200 Subject: [PATCH 314/705] mqtt: Abort plugin initialization if no connection to broker could established --- mqtt/__init__.py | 11 ++++++++--- mqtt/plugin.yaml | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/mqtt/__init__.py b/mqtt/__init__.py index 322441605..bb60ad9b8 100644 --- a/mqtt/__init__.py +++ b/mqtt/__init__.py @@ -58,7 +58,7 @@ class Mqtt(SmartPlugin): ALLOW_MULTIINSTANCE = True - PLUGIN_VERSION = "1.4.6" + PLUGIN_VERSION = "1.4.7" __plugif_CallbackTopics = {} # for plugin interface __plugif_Sub = None @@ -165,7 +165,10 @@ def __init__(self, sh, *args, **kwargs): # tls ... # ca_certs ... - self.ConnectToBroker() + if not self.ConnectToBroker(): + self._init_complete = False + return + self.init_webinterface() @@ -417,8 +420,10 @@ def ConnectToBroker(self): self._client.on_message = self.on_mqtt_message try: self._client.connect(self.broker_ip, self.broker_port, 60) - except Exception as e: + except ERROR as e: self.logger.error(self.get_loginstance()+'Connection error:', e) + return False + return True diff --git a/mqtt/plugin.yaml b/mqtt/plugin.yaml index 8ea935e0e..8395971ef 100755 --- a/mqtt/plugin.yaml +++ b/mqtt/plugin.yaml @@ -53,7 +53,7 @@ plugin: # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1089334-neues-mqtt-plugin - version: 1.4.6 # Plugin version + version: 1.4.7 # Plugin version sh_minversion: 1.4 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance From 87f8e8bc0c181a6ea8503d782d89f188f6be2dc2 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Tue, 9 Oct 2018 20:25:24 +0200 Subject: [PATCH 315/705] mini-update for readme and item init --- uzsu/README.md | 2 ++ uzsu/__init__.py | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/uzsu/README.md b/uzsu/README.md index 2d122f967..672adf8d8 100755 --- a/uzsu/README.md +++ b/uzsu/README.md @@ -78,6 +78,8 @@ Each UZSU item is of type list. Each list entry has to be a dict with specific k * __rrule__: You can use the recurrence rules documented in the [iCalendar RFC](http://www.ietf.org/rfc/rfc2445.txt) for recurrence use of a switching entry. ## Interpolation +Note: If Interpolation is activated the value will always be set in the given interval even if the next event is not on the same day. + * __type__: string, sets the mathematical function to interpolate between values. Can be cubic, linear or none. If set to cubic or linear the value calculated for the current time will be set on startup and change. * __interval__: integer, sets the time span in seconds between the automatic triggers based on the interpolation calculation diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 3caa39467..4f8bd9d1a 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -268,10 +268,10 @@ def _logics_interpolation(self, type=None, interval=5, backintime=0, item=None): else: self._items[item] = copy.deepcopy(item()) self._items[item]['interpolation']['type'] = str(type).lower() - self._items[item]['interpolation']['interval'] = abs(int(interval)) + self._items[item]['interpolation']['interval'] = int(interval) self._items[item]['interpolation']['initage'] = int(backintime) self.logger.info("Item {} interpolation is set via logic to: type={}, interval={}, backintime={}".format( - item, type, abs(interval), backintime)) + item, type, interval, backintime)) item(self._items[item], 'UZSU Plugin', 'logic') def _logics_clear(self, clear=False, item=None): @@ -331,6 +331,7 @@ def parse_item(self, item): item(self._items[item], 'UZSU Plugin', 'init') except Exception: self._items[item]['interpolation'] = {} + self._items[item]['interpolation']['type'] = 'none' self._items[item]['interpolation']['initialized'] = False item(self._items[item], 'UZSU Plugin', 'init') self.logger.debug('Dict for item {} is: {}'.format(item, self._items[item])) @@ -450,7 +451,7 @@ def _schedule(self, item, caller=None): if _next and _value is not None and self._items[item].get('active') is True: _reset_interpolation = False _interval = self._items[item]['interpolation'].get('interval') - _interval = 5 if not _interval else abs(int(_interval)) + _interval = 5 if not _interval else int(_interval) _interpolation = self._items[item]['interpolation'].get('type') _interpolation = 'none' if not _interpolation else _interpolation _initage = self._items[item]['interpolation'].get('initage') From df988fbc56761bac58be7974aca4b9162420a33a Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Tue, 9 Oct 2018 21:08:36 +0200 Subject: [PATCH 316/705] change negative interval to positive --- uzsu/__init__.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 4f8bd9d1a..8b5ea197d 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -268,10 +268,10 @@ def _logics_interpolation(self, type=None, interval=5, backintime=0, item=None): else: self._items[item] = copy.deepcopy(item()) self._items[item]['interpolation']['type'] = str(type).lower() - self._items[item]['interpolation']['interval'] = int(interval) + self._items[item]['interpolation']['interval'] = abs(int(interval)) self._items[item]['interpolation']['initage'] = int(backintime) self.logger.info("Item {} interpolation is set via logic to: type={}, interval={}, backintime={}".format( - item, type, interval, backintime)) + item, type, abs(interval), backintime)) item(self._items[item], 'UZSU Plugin', 'logic') def _logics_clear(self, clear=False, item=None): @@ -452,6 +452,10 @@ def _schedule(self, item, caller=None): _reset_interpolation = False _interval = self._items[item]['interpolation'].get('interval') _interval = 5 if not _interval else int(_interval) + if _interval < 0: + _interval = abs(int(_interval)) + self._items[item]['interpolation']['interval'] = _interval + item(self._items[item], 'UZSU Plugin', 'intervalchange') _interpolation = self._items[item]['interpolation'].get('type') _interpolation = 'none' if not _interpolation else _interpolation _initage = self._items[item]['interpolation'].get('initage') From c7cf95d236eee72e5c13e66e1985dc23e5062adc Mon Sep 17 00:00:00 2001 From: henfri Date: Wed, 10 Oct 2018 21:28:40 +0200 Subject: [PATCH 317/705] Improved robustness to instable Busses Previously, the Plugin disconnected from OWServer when a problem occured. Now it tries to complete the sensor-cycle. --- onewire/__init__.py | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/onewire/__init__.py b/onewire/__init__.py index 2940a43d4..8b27aa88c 100755 --- a/onewire/__init__.py +++ b/onewire/__init__.py @@ -326,6 +326,7 @@ def _io_cycle(self): value = self._flip[self.read('/uncached' + path).decode()] except Exception: self.logger.warning("1-Wire: problem reading {0}".format(addr)) + #pydevd.settrace("192.168.177.20") continue item(value, '1-Wire', path) @@ -377,6 +378,7 @@ def _sensor_cycle(self): start = time.time() for addr in self._sensors: if not self.alive: + self.logger.info("1-Wire: Self not alive".format(addr)) break for key in self._sensors[addr]: item = self._sensors[addr][key]['item'] @@ -388,23 +390,28 @@ def _sensor_cycle(self): value = self.read('/uncached' + path).decode() if key.startswith('T') and value == '85.0000': self.logger.info("1-Wire: problem reading {0}. Wiring problem?".format(addr)) + temperror=True continue + else: + temperror=False value = float(value) except Exception as e: - self.logger.warning("1-Wire: problem reading {} {}: {}".format(addr, path, e)) - if not self.connected: - return - else: - self.close() - break - if key == 'L': # light lux conversion - if value > 0: - value = round(10 ** ((float(value) / 47) * 1000)) - else: - value = 0 - elif key == 'VOC': - value = value * 310 + 450 - item(value, '1-Wire', path) + self.logger.warning("1-Wire: problem reading {} {}: {}. Trying to continue with next sensor".format(addr, path, e)) + #if not self.connected: + # return + #else: + # self.close() + # break + else: #only if no exception + if key == 'L': # light lux conversion + if value > 0: + value = round(10 ** ((float(value) / 47) * 1000)) + else: + value = 0 + elif key == 'VOC': + value = value * 310 + 450 + if not temperror: item(value, '1-Wire', path) + cycletime = time.time() - start self.logger.debug("1-Wire: sensor cycle takes {0} seconds".format(cycletime)) From 8eec7bda6473431ea1cb9803a2588f069f89ed76 Mon Sep 17 00:00:00 2001 From: henfri Date: Wed, 10 Oct 2018 22:14:54 +0200 Subject: [PATCH 318/705] Create requirements.txt --- iaqstick/requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 iaqstick/requirements.txt diff --git a/iaqstick/requirements.txt b/iaqstick/requirements.txt new file mode 100644 index 000000000..6513d5e38 --- /dev/null +++ b/iaqstick/requirements.txt @@ -0,0 +1 @@ +pyusb From 19feab84f55bb9feb0efb227fe292fb71ee2ef24 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Wed, 10 Oct 2018 22:24:49 +0200 Subject: [PATCH 319/705] fixed problem with interpolation when evaluating multiple items at the exact same time --- uzsu/__init__.py | 49 ++++++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 8b5ea197d..81150e07f 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -107,7 +107,7 @@ def __init__(self, smarthome): self._items = {} self._planned = {} self._update_count = {'todo': 0, 'done': 0} - self._itpl = OrderedDict() + self._itpl = {} self.init_webinterface() self.logger.info("Init with timezone {}".format(self._timezone)) if not REQUIRED_PACKAGE_IMPORTED: @@ -286,6 +286,17 @@ def _logics_clear(self, clear=False, item=None): self.logger.info("UZSU settings for item '{}' are cleared".format(item)) item(self._items[item], 'UZSU Plugin', 'clear') + def _logics_itpl(self, clear=False, item=None): + if isinstance(clear, str): + if clear.lower() in ['1', 'yes', 'true', 'on']: + clear = True + if isinstance(clear, bool) and clear is True: + self._itpl[item].clear() + self.logger.info("UZSU interpolation dict for item '{}' is cleared".format(item)) + else: + self.logger.info("UZSU interpolation dict for item '{}' is: {}".format(item, self._itpl[item])) + return self._itpl[item] + def _logics_planned(self, item=None): if self._planned.get(item) not in [None, {}] and self._items[item].get('active') is True: self.logger.info("Item '{}' is going to be set to {} at {}".format( @@ -321,6 +332,7 @@ def parse_item(self, item): item.interpolation = functools.partial(self._logics_interpolation, item=item) item.clear = functools.partial(self._logics_clear, item=item) item.planned = functools.partial(self._logics_planned, item=item) + item.itpl = functools.partial(self._logics_itpl, item=item) if '.'.join(VERSION.split('.', 3)[:3]) > '1.5.1': self._items[item] = item() @@ -429,7 +441,7 @@ def _schedule(self, item, caller=None): self.logger.warning("item '{}' is active but has no entries.".format(item)) self._planned.update({item: None}) elif self._items[item].get('active') is True: - self._itpl.clear() + self._itpl[item] = OrderedDict() for i, entry in enumerate(self._items[item]['list']): next, value = self._get_time(entry, 'next', item, i) self._get_time(entry, 'previous', item) @@ -463,8 +475,8 @@ def _schedule(self, item, caller=None): _initialized = self._items[item]['interpolation'].get('initialized') _initialized = False if not _initialized else _initialized entry_now = datetime.now(self._timezone).timestamp() * 1000.0 - self._itpl[entry_now] = 'NOW' - itpl_list = sorted(list(self._itpl.items())) + self._itpl[item][entry_now] = 'NOW' + itpl_list = sorted(list(self._itpl[item].items())) entry_index = itpl_list.index((entry_now, 'NOW')) _inittime = itpl_list[entry_index - min(1, entry_index)][0] _initvalue = itpl_list[entry_index - min(1, entry_index)][1] @@ -480,7 +492,7 @@ def _schedule(self, item, caller=None): cond3 = _initialized is False cond4 = _initage > 0 cond5 = isinstance(_value, float) - self._itpl = OrderedDict(itpl_list) + self._itpl[item] = OrderedDict(itpl_list) if not cond2 and cond3 and cond4: self.logger.info("Looking if there was a value set after {} for item {}".format( _timediff, item)) @@ -504,26 +516,27 @@ def _schedule(self, item, caller=None): _reset_interpolation = True elif _interpolation.lower() == 'cubic' and _interval > 0: try: - tck = interpolate.PchipInterpolator(list(self._itpl.keys()), list(self._itpl.values())) + tck = interpolate.PchipInterpolator(list(self._itpl[item].keys()), list(self._itpl[item].values())) _nextinterpolation = datetime.now(self._timezone) + timedelta(minutes=_interval) _next = _nextinterpolation if _next > _nextinterpolation else _next _value = round(float(tck(_next.timestamp() * 1000.0)), 2) _value_now = round(float(tck(entry_now)), 2) self._set(item=item, value=_value_now, caller='scheduler') self.logger.info("Updated: {}, cubic interpolation value: {}, based on dict: {}." - " Next: {}, value: {}".format(item, _value_now, self._itpl, _next, _value)) + " Next: {}, value: {}".format(item, _value_now, self._itpl[item], _next, _value)) except Exception as e: - self.logger.error("Error cubic interpolation: {}".format(e)) + self.logger.error("Error cubic interpolation for item {} " + "with interpolation list {}: {}".format(item, self._itpl[item], e)) elif _interpolation.lower() == 'linear' and _interval > 0: try: - tck = interpolate.interp1d(list(self._itpl.keys()), list(self._itpl.values())) + tck = interpolate.interp1d(list(self._itpl[item].keys()), list(self._itpl[item].values())) _nextinterpolation = datetime.now(self._timezone) + timedelta(minutes=_interval) _next = _nextinterpolation if _next > _nextinterpolation else _next _value = round(float(tck(_next.timestamp() * 1000.0)), 2) _value_now = round(float(tck(entry_now)), 2) self._set(item=item, value=_value_now, caller='scheduler') self.logger.info("Updated: {}, linear interpolation value: {}, based on dict: {}." - " Next: {}, value: {}".format(item, _value_now, self._itpl, _next, _value)) + " Next: {}, value: {}".format(item, _value_now, self._itpl[item], _next, _value)) except Exception as e: self.logger.error("Error linear interpolation: {}".format(e)) if cond5 and _value < 0: @@ -541,7 +554,7 @@ def _schedule(self, item, caller=None): if self._update_count.get('done') == self._update_count.get('todo'): self.scheduler_trigger('uzsu_sunupdate', by='UZSU Plugin') self._update_count = {'done': 0, 'todo': 0} - elif self._items[item].get('active') is True: + elif self._items[item].get('active') is True and self._items[item].get('list'): self.logger.warning("item '{}' is active but has no active entries.".format(item)) self._planned.update({item: None}) @@ -626,7 +639,7 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): else: next = datetime.combine(dt.date(), parser.parse(time.strip()).time()).replace(tzinfo=self._timezone) if next and next.date() == dt.date(): - self._itpl[next.timestamp() * 1000.0] = value + self._itpl[item][next.timestamp() * 1000.0] = value if next - timedelta(seconds=1) > datetime.now().replace(tzinfo=self._timezone): self.logger.debug("Return from rrule {}: {}, value {}.".format(timescan, next, value)) return next, value @@ -641,7 +654,7 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): if entryindex is not None: self._update_suncalc(item, entry, entryindex, next.strftime("%H:%M")) else: - self._itpl[next.timestamp() * 1000.0] = value + self._itpl[item][next.timestamp() * 1000.0] = value self.logger.debug("Include previous today: {}, value {} for interpolation.".format(next, value)) if entryindex: self._update_suncalc(item, entry, entryindex, next.strftime("%H:%M")) @@ -652,7 +665,7 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): next = datetime.combine(today, parser.parse(time.strip()).time()).replace(tzinfo=self._timezone) cond_future = next > datetime.now(self._timezone) and timescan == 'next' if not cond_future: - self._itpl[next.timestamp() * 1000.0] = value + self._itpl[item][next.timestamp() * 1000.0] = value self.logger.debug("Include next today: {}, value {} for interpolation.".format(next, value)) next = datetime.combine(tomorrow, parser.parse(time.strip()).time()).replace(tzinfo=self._timezone) cond1 = next.date() == today.date() @@ -662,19 +675,19 @@ def _get_time(self, entry, timescan, item=None, entryindex=None): cond_previous_today = next - timedelta(seconds=1) < datetime.now(self._timezone) and timescan == 'previous' cond_previous_yesterday = next - timedelta(days=1) < datetime.now(self._timezone) and timescan == 'previous' if next and cond1 and cond_next: - self._itpl[next.timestamp() * 1000.0] = value + self._itpl[item][next.timestamp() * 1000.0] = value self.logger.debug("Return next today: {}, value {}".format(next, value)) return next, value if next and cond3 and cond_next: - self._itpl[next.timestamp() * 1000.0] = value + self._itpl[item][next.timestamp() * 1000.0] = value self.logger.debug("Return next tomorrow: {}, value {}".format(next, value)) return next, value if next and cond1 and cond_previous_today: - self._itpl[(next - timedelta(seconds=1)).timestamp() * 1000.0] = value + self._itpl[item][(next - timedelta(seconds=1)).timestamp() * 1000.0] = value self.logger.debug("Return previous today: {}, value {}".format(next, value)) return next, value if next and cond2 and cond_previous_yesterday: - self._itpl[(next - timedelta(days=1)).timestamp() * 1000.0] = value + self._itpl[item][(next - timedelta(days=1)).timestamp() * 1000.0] = value self.logger.debug("Return previous yesterday: {}, value {}".format(next - timedelta(days=1), value)) return next - timedelta(days=1), value except Exception as e: From 271b7c96136ce5ae0522490df4743381f3ed32aa Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Thu, 11 Oct 2018 11:27:01 +0200 Subject: [PATCH 320/705] XMPP: Replace `jid` with `boundjid.bare` This avoids warnings about using deprecated stuff: jid property deprecated. Use boundjid.bare --- xmpp/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmpp/__init__.py b/xmpp/__init__.py index 0cd8084bb..d8e86706b 100755 --- a/xmpp/__init__.py +++ b/xmpp/__init__.py @@ -62,7 +62,7 @@ def stop(self): self._run = False self.alive = False for chat in self._join: - self.xmpp.plugin['xep_0045'].leaveMUC(chat, self.xmpp.jid) + self.xmpp.plugin['xep_0045'].leaveMUC(chat, self.xmpp.boundjid.bare) self.logger.info("Shutting Down XMPP Client") self.xmpp.disconnect(wait=False) @@ -87,7 +87,7 @@ def handleXMPPConnected(self, event): self.xmpp.sendPresence(pstatus="Send me a message") self.xmpp.get_roster() for chat in self._join: - self.xmpp.plugin['xep_0045'].joinMUC(chat, self.xmpp.jid, wait=True) + self.xmpp.plugin['xep_0045'].joinMUC(chat, self.xmpp.boundjid.bare, wait=True) def handleIncomingMessage(self, msg): """ From 79b2e50e03e9180906fc3cbced9e482d01c3abb4 Mon Sep 17 00:00:00 2001 From: onkelandy Date: Thu, 11 Oct 2018 18:13:11 +0200 Subject: [PATCH 321/705] Update avdevice/__init__.py fix problem with bufferclear --- avdevice/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avdevice/__init__.py b/avdevice/__init__.py index f179f69d4..a65018be0 100755 --- a/avdevice/__init__.py +++ b/avdevice/__init__.py @@ -1252,7 +1252,7 @@ def _checkdependency(self, dep_function, dep_type): elif primarycount == 0 and queryentry is not None: try: self._send_commands.remove(queryentry) - self._clearbuffer = True + self._clearbuffer = True if not self._send_commands else False self.logger.debug( "Checking Dependency {}: Dependent Query command {} removed from Send Commands. Dependencies: {}".format( self._name, queryentry, self._send_commands, dependitems)) From ebc37a70049915e1420af96d6631303c60648337 Mon Sep 17 00:00:00 2001 From: maddinador <43716888+maddinador@users.noreply.github.com> Date: Thu, 11 Oct 2018 20:36:18 +0200 Subject: [PATCH 322/705] Re-Add slack plugin Made a mistake when switching rthill's fork from upstream:master to upstream:develop --- slack/README.md | 63 +++++++++++++++++++++++++++++++++++ slack/__init__.py | 85 +++++++++++++++++++++++++++++++++++++++++++++++ slack/plugin.yaml | 66 ++++++++++++++++++++++++++++++++++++ 3 files changed, 214 insertions(+) create mode 100644 slack/README.md create mode 100644 slack/__init__.py create mode 100644 slack/plugin.yaml diff --git a/slack/README.md b/slack/README.md new file mode 100644 index 000000000..a90a7ff2e --- /dev/null +++ b/slack/README.md @@ -0,0 +1,63 @@ +# smarthome-slack +Plugin to send push notifications to Slack + +## Installation +
+cd smarthome.py directory
+cd plugins
+git clone https://github.com/rthill/slack.git
+
+ +## Configuration +### etc/plugin.yaml single instance example +
+SlackInstance:
+    plugin_name: slack
+    token: abc/def/ghi # Token for posting to workspace ''
+
+ +### etc/plugin.yaml multi instance example +If you want to post to more than one Slack workspaces or if you want to use more than one incoming webhook / authentication token, configure this plugin with multiple instances. +
+SlackInstance_1:
+    plugin_name: slack
+    instance: WorkspaceYourTeam
+    token: abc/def/ghi # Token for posting to workspace ''
+	
+SlackInstance_2:
+    plugin_name: slack
+    instance: WorkspaceAnotherTeam
+    token: jkl/mno/pqr # Token for posting to another workspace ''
+
+ +## Usage +To enable posting to Slack you need to create an "incoming webhook" there, which gives you an authorization token. +Open the following URL for your team workspace. +https://.slack.com/apps/new/A0F7XDUAZ-incoming-webhooks +Create a new webhook at which you need to select one channel of your workspace. +The created URL contains an API token which authorizes posting to every channel in this workspace. +Afterwards you need to setup your etc/plugin.yaml as described above and insert the webhook token. + +To send a notification use the following syntax in your logics with the first parameter being the desired channel: +
+# Default informational notification to channel #general
+sh.SlackInstance.notify('#general', 'Ding Dong: Front door')
+# Or use the following to set the default notification type to normal
+sh.SlackInstance.notify('#otherChannel', 'Ding Dong: Front door', 'normal')
+# Other notification types use warning, danger or good.
+sh.SlackInstance.notify('#differentChannel', 'Alarm: Garage door open', 'danger')
+
+ +To learn more on message formatting (e.g. bold, underline, URLs, Emojis, multiline) visit the following link: +https://api.slack.com/docs/message-formatting + + +For most users a single instance would be sufficient. +If you want to send notifications to more than one Slack workspace or if you want to use more than one incoming webhook / authentication token, you need to generate a webhook / token in every Slack workspace. +For each of them you'll need to configure a instace of this plugn in etc/plugin.yaml with different instance names as shown in multi instance example configuration above. +Sending notifications in multi instance example: +
+# Sending a notification to two workspaces
+sh.SlackInstance_1.notify('#general', 'Hello first workspace!')
+sh.SlackInstance_2.notify('#general', 'Hello second workspace!')
+
diff --git a/slack/__init__.py b/slack/__init__.py new file mode 100644 index 000000000..fd2ee67ed --- /dev/null +++ b/slack/__init__.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2016-2018 Raoul Thill raoul.thill@gmail.com +######################################################################### +# This file is part of SmartHomeNG. +# +# SmartHomeNG is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# SmartHomeNG is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with SmartHomeNG. If not, see . +######################################################################### + +import logging +import json +import requests +import html +from lib.model.smartplugin import SmartPlugin + + +class Slack(SmartPlugin): + PLUGIN_VERSION = "1.0.0" + ALLOW_MULTIINSTANCE = True + SLACK_INCOMING_WEBHOOK = 'https://hooks.slack.com/services/%s' + + def __init__(self, sh): + self.logger = logging.getLogger(__name__) + self.logger.info("Init Slack notifications") + self._sh = sh + self.token = self.get_parameter_value('token') + + def run(self): + pass + + def stop(self): + pass + + def _push(self, payload): + webhook = self.SLACK_INCOMING_WEBHOOK % self.token + try: + res = requests.post(webhook, + headers={ + "User-Agent": "sh.py", + "Content-Type": "application/json", + "Accept": "application/json"}, + timeout=4, + data=payload, + ) + self.logger.debug(res) + response = res.text + del res + self.logger.debug(response) + except BaseException as e: + self.logger.exception(e) + + def notify(self, channel, text, color='normal'): + color_choices = ['normal', 'good', 'warning', 'danger'] + if color not in color_choices: + self.logger.error("Please choose a valid color from {}".format(','.join(color_choices))) + color = "normal" + payload = {} + if color == "normal" and text is not None: + payload = dict(text=html.escape(text, quote=False)) + elif text is not None: + payload = dict(attachments=[dict(text=html.escape(text, quote=False), color=color, mrkdwn_in=["text"])]) + if channel is not None: + if (channel[0] == '#') or (channel[0] == '@'): + payload['channel'] = channel + else: + payload['channel'] = '#' + channel + + payload = json.dumps(payload) + self.logger.debug("Slack sending notification {}".format(payload)) + self._push(payload) + + def parse_item(self, item): + pass diff --git a/slack/plugin.yaml b/slack/plugin.yaml new file mode 100644 index 000000000..45742aef4 --- /dev/null +++ b/slack/plugin.yaml @@ -0,0 +1,66 @@ +# Metadata for the Smart-Plugin +plugin: + # Global plugin attributes + type: web # plugin type (gateway, interface, protocol, system, web) + description: + de: 'Slack messaging Dienst' + en: 'Slack messaging service' + maintainer: rthill + tester: maddinador + state: develop + keywords: messaging +# documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page +# support: https://knx-user-forum.de/forum/supportforen/smarthome-py + + version: 1.0.0 # Plugin version + sh_minversion: 1.4 # minimum shNG version to use this plugin +# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) + multi_instance: True # plugin supports multi instance + restartable: True # restartable: yes + classname: Slack # class containing the plugin + +parameters: + # Definition of parameters to be configured in etc/plugin.yaml + token: + type: str + description: + de: 'Slack-Token für den API-Zugriff auf einen oder mehrere Kanäle in einem Slack-Workspace' + en: 'Slack token for API access to one or more channels in a single Slack workspace' + mandatory: True + +item_attributes: NONE + # Definition of item attributes defined by this plugin + +plugin_functions: + # Definition of public functions defined by this plugin + notify: + type: foo + description: + de: 'Absetzen einer Messaging-Nachricht an den Slack Workspace' + en: 'send a messaging text to Slack workspace' + parameters: + channel: + type: str + description: + de: 'Slack-Kanal, in den gepostet wird' + en: 'Slack channel to be posted to' + mandatory: True + text: + type: str + description: + de: 'Text der Nachricht' + en: 'text of your message' + mandatory: True + color: + type: str + description: + de: 'Typ der Nachricht (=Farbe)' + en: 'type of message (=color)' + mandatory: False + default: 'normal' + valid_list: + - 'normal' + - 'good' + - 'warning' + - 'danger' + From f065052a056c0457a1aa906f8b792fa914df1dc4 Mon Sep 17 00:00:00 2001 From: onkelandy Date: Thu, 11 Oct 2018 22:08:07 +0200 Subject: [PATCH 323/705] Update avdevice/README.md fixed list in readme --- avdevice/README.md | 55 +++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/avdevice/README.md b/avdevice/README.md index f6cfa1768..c1be2b1a6 100755 --- a/avdevice/README.md +++ b/avdevice/README.md @@ -15,43 +15,44 @@ Tested with Pioneer (< 2016 models) and Denon AV receivers, Epson projector Oppo ## Changelog ### v1.5.0 -Minor code re-write using smartplugin methods and logging -added config file for Denon AVR1100 -fixed Denon example -added Web Interface +* Minor code re-write using smartplugin methods and logging +* added config file for Denon AVR1100 +* fixed Denon example +* added Web Interface +* some bug fixes ### v1.3.6 -Major code re-write using multiple modules and classes, minimizing complexity -Extended "translate" functionality with wildcards -Implemented optional waiting time between multiple commands -Improved Keep Command handling -Several bug fixes and tests +* Major code re-write using multiple modules and classes, minimizing complexity +* Extended "translate" functionality with wildcards +* Implemented optional waiting time between multiple commands +* Improved Keep Command handling +* Several bug fixes and tests ### v1.3.5 -Implemented possibility to "translate" values -Improved Wildcard handling -Improved code -Added Oppo support -Improved response and queue handling +* Implemented possibility to "translate" values +* Improved Wildcard handling +* Improved code +* Added Oppo support +* Improved response and queue handling ### v1.3.4 -Tested full Denon support -Implemented Dependencies -Implemented rudimentary Wildcard handling -Implemented Initialization commands -Improved Queue handling and CPU usage -Bug fixes +* Tested full Denon support +* Implemented Dependencies +* Implemented rudimentary Wildcard handling +* Implemented Initialization commands +* Improved Queue handling and CPU usage +* Bug fixes ### v1.3.3 -Added Denon support -Added option to provide min-value in config file -Improved response handling -Implemented possibility to reload config files -Improved verbose logging -Bug fixes +* Added Denon support +* Added option to provide min-value in config file +* Improved response handling +* Implemented possibility to reload config files +* Improved verbose logging +* Bug fixes ### v1.3.2 -Added and tested full Denon support +* Added and tested full Denon support ## Configuration From 09acc536cd603d984e6029b8bd608f91a01477c0 Mon Sep 17 00:00:00 2001 From: maddinador <43716888+maddinador@users.noreply.github.com> Date: Fri, 12 Oct 2018 23:09:09 +0200 Subject: [PATCH 324/705] Update slack/README.md changed
 Tags to Markdown ```
removed installation instructions because they are not neccessary.
---
 slack/README.md | 23 ++++++++---------------
 1 file changed, 8 insertions(+), 15 deletions(-)

diff --git a/slack/README.md b/slack/README.md
index a90a7ff2e..e989567f6 100644
--- a/slack/README.md
+++ b/slack/README.md
@@ -1,24 +1,17 @@
 # smarthome-slack
 Plugin to send push notifications to Slack 
 
-## Installation
-
-cd smarthome.py directory
-cd plugins
-git clone https://github.com/rthill/slack.git
-
- ## Configuration ### etc/plugin.yaml single instance example -
+```yaml
 SlackInstance:
     plugin_name: slack
     token: abc/def/ghi # Token for posting to workspace ''
-
+``` ### etc/plugin.yaml multi instance example If you want to post to more than one Slack workspaces or if you want to use more than one incoming webhook / authentication token, configure this plugin with multiple instances. -
+```yaml
 SlackInstance_1:
     plugin_name: slack
     instance: WorkspaceYourTeam
@@ -28,7 +21,7 @@ SlackInstance_2:
     plugin_name: slack
     instance: WorkspaceAnotherTeam
     token: jkl/mno/pqr # Token for posting to another workspace ''
-
+``` ## Usage To enable posting to Slack you need to create an "incoming webhook" there, which gives you an authorization token. @@ -39,14 +32,14 @@ The created URL contains an API token which authorizes posting to every channel Afterwards you need to setup your etc/plugin.yaml as described above and insert the webhook token. To send a notification use the following syntax in your logics with the first parameter being the desired channel: -
+```python
 # Default informational notification to channel #general
 sh.SlackInstance.notify('#general', 'Ding Dong: Front door')
 # Or use the following to set the default notification type to normal
 sh.SlackInstance.notify('#otherChannel', 'Ding Dong: Front door', 'normal')
 # Other notification types use warning, danger or good.
 sh.SlackInstance.notify('#differentChannel', 'Alarm: Garage door open', 'danger')
-
+``` To learn more on message formatting (e.g. bold, underline, URLs, Emojis, multiline) visit the following link: https://api.slack.com/docs/message-formatting @@ -56,8 +49,8 @@ For most users a single instance would be sufficient. If you want to send notifications to more than one Slack workspace or if you want to use more than one incoming webhook / authentication token, you need to generate a webhook / token in every Slack workspace. For each of them you'll need to configure a instace of this plugn in etc/plugin.yaml with different instance names as shown in multi instance example configuration above. Sending notifications in multi instance example: -
+```python
 # Sending a notification to two workspaces
 sh.SlackInstance_1.notify('#general', 'Hello first workspace!')
 sh.SlackInstance_2.notify('#general', 'Hello second workspace!')
-
+``` From 2b48d51a78daa170015f1103280a605094d36e56 Mon Sep 17 00:00:00 2001 From: maddinador <43716888+maddinador@users.noreply.github.com> Date: Fri, 12 Oct 2018 23:12:38 +0200 Subject: [PATCH 325/705] Update slack/README.md spell and grammar update --- slack/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/slack/README.md b/slack/README.md index e989567f6..f427625ec 100644 --- a/slack/README.md +++ b/slack/README.md @@ -10,13 +10,13 @@ SlackInstance: ``` ### etc/plugin.yaml multi instance example -If you want to post to more than one Slack workspaces or if you want to use more than one incoming webhook / authentication token, configure this plugin with multiple instances. +If you want to post to more than one Slack workspace or if you want to use more than one incoming webhook / authentication token, configure this plugin with multiple instances. ```yaml SlackInstance_1: plugin_name: slack instance: WorkspaceYourTeam token: abc/def/ghi # Token for posting to workspace '' - + SlackInstance_2: plugin_name: slack instance: WorkspaceAnotherTeam @@ -46,7 +46,7 @@ https://api.slack.com/docs/message-formatting For most users a single instance would be sufficient. -If you want to send notifications to more than one Slack workspace or if you want to use more than one incoming webhook / authentication token, you need to generate a webhook / token in every Slack workspace. +If you want to go beyond that and want to send notifications to more than one Slack workspace or if you want to use more than one incoming webhook / authentication token, you need to generate a webhook / token in every Slack workspace. For each of them you'll need to configure a instace of this plugn in etc/plugin.yaml with different instance names as shown in multi instance example configuration above. Sending notifications in multi instance example: ```python From fb723f07ada6ec796dd11dbb0d079cd371c7a179 Mon Sep 17 00:00:00 2001 From: 2pi Date: Sat, 13 Oct 2018 23:18:22 +0200 Subject: [PATCH 326/705] changes due to latest pyusb updates - usb.core.find: returns list/no-list - usb.util.get_string: number of kwarg - dev.read: number of kwarg - dev.write: number of kwarg --- iaqstick/__init__.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/iaqstick/__init__.py b/iaqstick/__init__.py index 752ff515f..e3447ff86 100644 --- a/iaqstick/__init__.py +++ b/iaqstick/__init__.py @@ -41,7 +41,7 @@ def read(self, dev): in_data = bytes() try: while True: - ret = bytes(dev.read(0x81, 0x10, self._intf, 1000)) + ret = bytes(dev.read(0x81, 0x10, 1000)) if len(ret) == 0: break in_data += ret @@ -53,13 +53,13 @@ def read(self, dev): def xfer_type1(self, dev, msg): out_data = bytes('@{:04X}{}\n@@@@@@@@@@'.format(self._devs[dev]['type1_seq'], msg), 'utf-8') self._devs[dev]['type1_seq'] = (self._devs[dev]['type1_seq'] + 1) & 0xFFFF - ret = dev.write(0x02, out_data[:16], self._intf, 1000) + ret = dev.write(0x02, out_data[:16], 1000) return self.read(dev).decode('iso-8859-1') def xfer_type2(self, dev, msg): out_data = bytes('@', 'utf-8') + self._devs[dev]['type2_seq'].to_bytes(1, byteorder='big') + bytes('{}\n@@@@@@@@@@@@@'.format(msg), 'utf-8') self._devs[dev]['type2_seq'] = (self._devs[dev]['type2_seq'] + 1) if (self._devs[dev]['type2_seq'] < 0xFF) else 0x67 - ret = dev.write(0x02, out_data[:16], self._intf, 1000) + ret = dev.write(0x02, out_data[:16], 1000) in_data = bytes() return self.read(dev) @@ -70,8 +70,8 @@ def _init_dev(self, dev): dev.set_configuration(0x01) usb.util.claim_interface(dev, self._intf) dev.set_interface_altsetting(self._intf, 0x00) - vendor = usb.util.get_string(dev, 0x101, 0x01, 0x409) - product = usb.util.get_string(dev, 0x101, 0x02, 0x409) + vendor = usb.util.get_string(dev, dev.iManufacturer) + product = usb.util.get_string(dev,dev.iProduct ) self._devs[dev] = {'type1_seq':0x0001, 'type2_seq':0x67} ret = self.xfer_type1(dev, '*IDN?') pos1 = ret.find('S/N:') + 4 @@ -88,7 +88,7 @@ def _init_dev(self, dev): return None def run(self): - devs = usb.core.find(idVendor=0x03eb, idProduct=0x2013, find_all=True) + devs = list(usb.core.find(idVendor=0x03eb, idProduct=0x2013, find_all=True)) if devs is None: logger.error('iaqstick: iAQ Stick not found') return @@ -145,7 +145,7 @@ def _update_values(self): logger.error("iaqstick: Trying to recover ...") broken_id = self._devs[dev]['id'] del self._devs[dev] - __devs = usb.core.find(idVendor=0x03eb, idProduct=0x2013, find_all=True) + __devs = list(usb.core.find(idVendor=0x03eb, idProduct=0x2013, find_all=True)) for __dev in __devs: if (__dev not in self._devs): id = self._init_dev(__dev) @@ -218,4 +218,4 @@ def parse_item(self, item): #Records=&h0000; #nValues (last)=&h0000; #uint16_t g_u16_loop_cnt_100ms=&h08D4; -#;\x0A \ No newline at end of file +#;\x0A From b8e7cdc0002559225e32abf0eb88be8ed219a075 Mon Sep 17 00:00:00 2001 From: henfri Date: Sun, 14 Oct 2018 11:06:10 +0200 Subject: [PATCH 327/705] Update __init__.py removed temperror --- onewire/__init__.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/onewire/__init__.py b/onewire/__init__.py index 8b27aa88c..4d3e8666a 100755 --- a/onewire/__init__.py +++ b/onewire/__init__.py @@ -390,18 +390,10 @@ def _sensor_cycle(self): value = self.read('/uncached' + path).decode() if key.startswith('T') and value == '85.0000': self.logger.info("1-Wire: problem reading {0}. Wiring problem?".format(addr)) - temperror=True continue - else: - temperror=False value = float(value) except Exception as e: self.logger.warning("1-Wire: problem reading {} {}: {}. Trying to continue with next sensor".format(addr, path, e)) - #if not self.connected: - # return - #else: - # self.close() - # break else: #only if no exception if key == 'L': # light lux conversion if value > 0: @@ -410,7 +402,7 @@ def _sensor_cycle(self): value = 0 elif key == 'VOC': value = value * 310 + 450 - if not temperror: item(value, '1-Wire', path) + item(value, '1-Wire', path) cycletime = time.time() - start self.logger.debug("1-Wire: sensor cycle takes {0} seconds".format(cycletime)) From a26bffa6e2c7579721c7f590445761164ebc8535 Mon Sep 17 00:00:00 2001 From: henfri Date: Sun, 14 Oct 2018 11:13:37 +0200 Subject: [PATCH 328/705] Update README.md updated requirement for Version of pyusb --- iaqstick/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iaqstick/README.md b/iaqstick/README.md index 8abe6c25a..c684b184b 100644 --- a/iaqstick/README.md +++ b/iaqstick/README.md @@ -8,7 +8,7 @@ install by ```bash apt-get install python3-setuptools -easy_install3 pyusb +pip3 install "pyusb>=1.0.2" ``` ``` From 56640764347e25b9b029c5d798d09936ceb4556a Mon Sep 17 00:00:00 2001 From: henfri Date: Sun, 14 Oct 2018 11:14:16 +0200 Subject: [PATCH 329/705] Update requirements.txt --- iaqstick/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iaqstick/requirements.txt b/iaqstick/requirements.txt index 6513d5e38..62b1668a7 100644 --- a/iaqstick/requirements.txt +++ b/iaqstick/requirements.txt @@ -1 +1 @@ -pyusb +pyusb>=1.0.2 From 0f4a1b4e9a34ddb1a62eddfa3ba4810dbfc7b36d Mon Sep 17 00:00:00 2001 From: aschwith Date: Tue, 16 Oct 2018 10:16:05 +0200 Subject: [PATCH 330/705] AVM plugin: fix during exception Fixed error: "local variable 'response' referenced before assignment" --- avm/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/avm/__init__.py b/avm/__init__.py index b800bf0bc..481a9efaf 100644 --- a/avm/__init__.py +++ b/avm/__init__.py @@ -1954,6 +1954,7 @@ def _update_wan_ip_connection(self, item): verify=self._verify) except Exception as e: self.logger.error("Exception when sending POST request: %s" % str(e)) + return self._response_cache["wan_ip_connection_" + action] = response.content else: self.logger.debug("Accessing TAM reponse cache for action %s!" % action) From 8cdcf9f5015f7d26bfce1f6722aa9426e374c38a Mon Sep 17 00:00:00 2001 From: Gerd Hildebrand Date: Sun, 21 Oct 2018 17:58:47 +0200 Subject: [PATCH 331/705] Support D2_01_12 --- enocean/README.md | 13 +++++++++ enocean/eep_parser.py | 21 +++++++++++++++ enocean/prepare_packet_data.py | 49 ++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) diff --git a/enocean/README.md b/enocean/README.md index d716f9602..24b401bbd 100644 --- a/enocean/README.md +++ b/enocean/README.md @@ -202,6 +202,17 @@ EnOcean_Item: enocean_tx_id_offset: 1 # pulsewith-attribute removed use autotimer functionality instead autotimer: 1 = 0 + + actorD2_01_12: + enocean_rx_id: 050A2FF4 + enocean_rx_eep: D2_01_12 + switch: + cache: 'on' + type: bool + enocean_rx_key: STAT_A + enocean_channel: A + enocean_tx_eep: D2_01_12 + enocean_tx_id_offset: 2 awning: remark: Eltako FSB14, FSB61, FSB71 - actor for Shutter @@ -365,6 +376,7 @@ The following status EEPs are supported: * A5_11_04 Dimmer status feedback * A5_12_01 Power Measurement, e.g. Eltako FSVA-230V * D2_01_07 Simple electronic switch +* D2_01_12 Simple electronic switch with 2 channels, like NodOn In-Wall module * D5_00_01 Door/Window Contact, e.g. Eltako FTK, FTKB * F6_02_01 2-Button-Rocker * F6_02_02 2-Button-Rocker @@ -382,6 +394,7 @@ A complete list of available EEPs is accessible at [EnOcean Alliance](http://www * A5_38_08_03 Dimmer command with specified dim level (0-100) * A5_3F_7F Universal actuator command, e.g. blind control * D2_01_07 Simple electronic switch +* D2_01_12 Simple electronic switch with 2 channels ``` The optional ref_level parameter defines default dim value when dimmer is switched on via the regular "on"" command. diff --git a/enocean/eep_parser.py b/enocean/eep_parser.py index 26bd0e4cc..bda364d1f 100644 --- a/enocean/eep_parser.py +++ b/enocean/eep_parser.py @@ -279,6 +279,27 @@ def _parse_eep_D2_01_07(self, payload, status): self.logger.debug('enocean: D2 Switch on') return results + def _parse_eep_D2_01_12(self, payload, status): + # self.logger.debug("enocean: processing D2_01_12: VLD Switch") + results = {} + # self.logger.info('enocean: D2 Switch Feedback 0:{} 1:{} 2:{}').format(payload[0],payload[1],payload[2]) + if (payload[1] == 0x60) and (payload[2] == 0x80): + # Switch is off + results['STAT_A'] = 0 + self.logger.debug('enocean: D2 Switch Channel A: off') + elif (payload[1] == 0x60) and (payload[2] == 0xe4): + # Switch is on + results['STAT_A'] = 1 + self.logger.debug('enocean: D2 Channel A: Switch on') + elif (payload[1] == 0x61) and (payload[2] == 0x80): + # Switch is off + results['STAT_B'] = 0 + self.logger.debug('enocean: D2 SwitchChannel A: off') + elif (payload[1] == 0x61) and (payload[2] == 0xe4): + # Switch is on + results['STAT_B'] = 1 + self.logger.debug('enocean: D2 Switch Channel B: on') + return results #################################################### ### --- Definitions for RORG = D5 / ORG = 06 --- ### diff --git a/enocean/prepare_packet_data.py b/enocean/prepare_packet_data.py index 15111b644..12e2e9006 100644 --- a/enocean/prepare_packet_data.py +++ b/enocean/prepare_packet_data.py @@ -386,3 +386,52 @@ def _prepare_data_for_tx_eep_D2_01_07(self, item, tx_eep): self.logger.info('enocean-PrepareData: {} Packet Data Prepared for {} (VLD)'.format(tx_eep, tx_eep)) optional = [SubTel, rx_id, db, Secu] return rorg, payload, optional + + def _prepare_data_for_tx_eep_D2_01_12(self, item, tx_eep): + """ + ### --- Data for D2_01_12 (VLD) --- ### + Prepare data for Devices with Varable Length Telegram. + There is currently no device information available. + Optional 'pulsewidth' - Attribute was removed, it can be realized with the smarthomeNG + build in function autotimer! + """ + self.logger.debug('enocean-PrepareData: prepare data for tx_eep {}'.format(tx_eep)) + rorg = 0xD2 + SubTel = 0x03 + db = 0xFF + Secu = 0x0 + if self._plugin_instance.has_iattr(item.conf, 'enocean_rx_id'): + rx_id = int(self._plugin_instance.get_iattr_value(item.conf, 'enocean_rx_id'), 16) + if (rx_id < 0) or (rx_id > 0xFFFFFFFF): + self.logger.error('enocean-PrepareData: {} rx-ID-Offset out of range (0-127). Aborting.'.format(tx_eep)) + return None + self.logger.debug('enocean-PrepareData: {} enocean_rx_id found.'.format(tx_eep)) + else: + rx_id = 0 + self.logger.debug('enocean-PrepareData: {} no enocean_rx_id found!'.format(tx_eep)) + if self._plugin_instance.has_iattr(item.conf, 'enocean_channel'): + schannel = self._plugin_instance.get_iattr_value(item.conf, 'enocean_channel') + if (schannel == "A"): + channel = 0x00 + elif (schannel == "B"): + channel = 0x01 + else: + channel = 0x1E + self.logger.debug('enocean-PrepareData: {} enocean_channel found: %s '.format(tx_eep), schannel) + else: + channel = 0x1E + self.logger.debug('enocean-PrepareData: {} no enocean_channel found!'.format(tx_eep)) + # Prepare Data Packet + if (item() == 0): + payload = [0x01, channel, 0x00] + optional = [SubTel, rx_id, db, Secu] + elif (item() == 1): + payload = [0x01, channel, 0x01] + optional = [SubTel, rx_id, db, Secu] + else: + self.logger.error('enocean-PrepareData: {} undefined Value. Error!'.format(tx_eep)) + return None + # packet_data_prepared = (id_offset, 0xD2, payload, [0x03, 0xFF, 0xBA, 0xD0, 0x00, 0xFF, 0x0]) + self.logger.info('enocean-PrepareData: {} Packet Data Prepared for {} (VLD)'.format(tx_eep, tx_eep)) + optional = [SubTel, rx_id, db, Secu] + return rorg, payload, optional From d60476959e748aad15b2e261cafc24949d6ab5fa Mon Sep 17 00:00:00 2001 From: henfri Date: Sun, 21 Oct 2018 21:59:06 +0200 Subject: [PATCH 332/705] Update __init__.py Debugging entry removed and logging to i_button_cycle added --- onewire/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onewire/__init__.py b/onewire/__init__.py index 4d3e8666a..5f7a3bf3b 100755 --- a/onewire/__init__.py +++ b/onewire/__init__.py @@ -326,7 +326,6 @@ def _io_cycle(self): value = self._flip[self.read('/uncached' + path).decode()] except Exception: self.logger.warning("1-Wire: problem reading {0}".format(addr)) - #pydevd.settrace("192.168.177.20") continue item(value, '1-Wire', path) @@ -344,6 +343,7 @@ def _ibutton_cycle(self): return for bus in self._ibutton_buses: if not self.alive: + self.logger.info("1-Wire: Self not alive".format(bus)) break path = '/uncached/' + bus + '/' name = self._ibutton_buses[bus] From d82fb665ed5d12e83d77cdd0ea414e5889a10283 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 24 Oct 2018 07:22:22 +0200 Subject: [PATCH 333/705] Renamed Plugin NokiaHealth to WithingsHealth --- nokia_health/requirements.txt | 1 - {nokia_health => withings_health}/README.md | 37 ++++++++++-------- {nokia_health => withings_health}/__init__.py | 8 ++-- {nokia_health => withings_health}/locale.yaml | 9 +++-- {nokia_health => withings_health}/plugin.yaml | 2 +- withings_health/requirements.txt | 1 + .../webif/static/img/plugin_logo.png | Bin .../webif/templates/index.html | 6 +-- 8 files changed, 35 insertions(+), 29 deletions(-) delete mode 100644 nokia_health/requirements.txt rename {nokia_health => withings_health}/README.md (67%) rename {nokia_health => withings_health}/__init__.py (98%) rename {nokia_health => withings_health}/locale.yaml (91%) rename {nokia_health => withings_health}/plugin.yaml (99%) create mode 100644 withings_health/requirements.txt rename {nokia_health => withings_health}/webif/static/img/plugin_logo.png (100%) rename {nokia_health => withings_health}/webif/templates/index.html (95%) diff --git a/nokia_health/requirements.txt b/nokia_health/requirements.txt deleted file mode 100644 index 353d50fe6..000000000 --- a/nokia_health/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -nokia==1.0.0 diff --git a/nokia_health/README.md b/withings_health/README.md similarity index 67% rename from nokia_health/README.md rename to withings_health/README.md index c7c8fac8d..f13addf8a 100644 --- a/nokia_health/README.md +++ b/withings_health/README.md @@ -2,7 +2,7 @@ ## Description -This plugin allows to retrieve data from the Nokia Health API (https://developer.health.nokia.com/api). Currently it +This plugin allows to retrieve data from the Withings (former Nokia) Health API (https://developer.withings.com/api). Currently it only has support for "Withings WS-50 Smart Body Analyzer", a wifi capabale scale. Support Thread: https://knx-user-forum.de/forum/supportforen/smarthome-py/1141179-nokia-health-plugin @@ -15,7 +15,7 @@ This plugin requires lib nokia. You can install this lib with: sudo pip3 install nokia --upgrade ``` -You have to register at https://account.health.nokia.com/partner/add_oauth2. +You have to register at https://account.withings.com/partner/add_oauth2. The callback URL to enter when registering is shown via the plugin's web interface and can be added as soon as client_id and consumer_secret have been set in etc/plugin.yaml The OAuth2 process can then be triggered via the Web Interface of the plugin. Therefore at least the first four items of the example below need to exist (access_token, token_expiry, token_type, refresh_token). @@ -26,19 +26,22 @@ In case your SmartHomeNG instance is offline for too long, the tokens expire. Yo ### plugin.yaml ```yaml -nokia_health: +withings_health: + class_name: WithingsHealth + class_path: plugins.withings_health user_id: client_id: consumer_secret: cycle: 300 - instance: nokia_health + instance: withings_health + ``` ### items.yaml Please be aware that there are dependencies for the values. E.g. the body measurement index will only be calculated if a height exists. From what i saw so far is, that the height is transmitted only one time, the first time the scale -communicates with the Nokia servers. In case you miss it, set the item value manually! +communicates with the Withings (former Nokia) servers. In case you miss it, set the item value manually! The first four items are mandatory, as they are needed for OAuth2 data! @@ -49,64 +52,64 @@ body: type: str visu_acl: ro cache: yes - nh_type@nokia_health: access_token + withings_type@withings_health: access_token token_expiry: type: num visu_acl: ro cache: yes - nh_type@nokia_health: token_expiry + withings_type@withings_health: token_expiry token_type: type: str visu_acl: ro cache: yes - nh_type@nokia_health: token_type + withings_type@withings_health: token_type refresh_token: type: str visu_acl: ro cache: yes - nh_type@nokia_health: refresh_token + withings_type@withings_health: refresh_token weight: type: num visu_acl: ro - nh_type@nokia_health: weight + withings_type@withings_health: weight height: type: num visu_acl: ro - nh_type@nokia_health: height + withings_type@withings_health: height bmi: type: num visu_acl: ro - nh_type@nokia_health: bmi + withings_type@withings_health: bmi bmi_text: type: str visu_acl: ro - nh_type@nokia_health: bmi_text + withings_type@withings_health: bmi_text fat_ratio: type: num visu_acl: ro - nh_type@nokia_health: fat_ratio + withings_type@withings_health: fat_ratio fat_free_mass: type: num visu_acl: ro - nh_type@nokia_health: fat_free_mass + withings_type@withings_health: fat_free_mass fat_mass_weight: type: num visu_acl: ro - nh_type@nokia_health: fat_mass_weight + withings_type@withings_health: fat_mass_weight heart_pulse: type: num visu_acl: ro - nh_type@nokia_health: heart_pulse + withings_type@withings_health: heart_pulse ``` diff --git a/nokia_health/__init__.py b/withings_health/__init__.py similarity index 98% rename from nokia_health/__init__.py rename to withings_health/__init__.py index 640f90dfc..9a05797b1 100644 --- a/nokia_health/__init__.py +++ b/withings_health/__init__.py @@ -29,7 +29,7 @@ from nokia import NokiaAuth, NokiaApi, NokiaCredentials -class NokiaHealth(SmartPlugin): +class WithingsHealth(SmartPlugin): ALLOW_MULTIINSTANCE = True PLUGIN_VERSION = "1.5.3" ALLOWED_MEASURE_TYPES = [1, 4, 5, 6, 8, 11] @@ -101,7 +101,7 @@ def _update(self): if 'access_token' not in self.get_items() or 'token_expiry' not in self.get_items() or 'token_type' not in self.get_items() or 'refresh_token' not in self.get_items(): self.logger.error( - "Plugin '{}': Mandatory Items for OAuth2 Data do not exist. Verify that you have items with nh_type: token_expiry, token_type, refresh_token and access_token in your item tree.".format( + "Plugin '{}': Mandatory Items for OAuth2 Data do not exist. Verify that you have items with withings_type: token_expiry, token_type, refresh_token and access_token in your item tree.".format( self.get_fullname())) return @@ -264,14 +264,14 @@ def parse_item(self, item): :param item: The item to process. """ # items specific to call monitor - if self.get_iattr_value(item.conf, 'nh_type') in ['weight', 'height', 'fat_free_mass', 'fat_mass_weight', + if self.get_iattr_value(item.conf, 'withings_type') in ['weight', 'height', 'fat_free_mass', 'fat_mass_weight', 'fat_ratio', 'fat_mass_weight', 'diastolic_blood_pressure', 'systolic_blood_pressure', 'heart_pulse', 'temperature', 'spo2', 'body_temperature', 'skin_temperature', 'muscle_mass', 'hydration', 'bone_mass', 'pulse_wave_velocity', 'bmi', 'bmi_text', 'access_token', 'token_expiry', 'token_type', 'refresh_token']: - self._items[self.get_iattr_value(item.conf, 'nh_type')] = item + self._items[self.get_iattr_value(item.conf, 'withings_type')] = item def get_items(self): return self._items diff --git a/nokia_health/locale.yaml b/withings_health/locale.yaml similarity index 91% rename from nokia_health/locale.yaml rename to withings_health/locale.yaml index c0a467d88..516526203 100644 --- a/nokia_health/locale.yaml +++ b/withings_health/locale.yaml @@ -4,9 +4,12 @@ plugin_translations: 'Das Token ist abgelaufen und wurde nicht verlängert. Bitte den OAuth2 Prozess neu starten.': 'de': 'Das Token ist abgelaufen und wurde nicht verlängert. Bitte den OAuth2 Prozess neu starten.' 'en': 'The token has expired and was not renewed. Please start OAuth2 process again.' - 'Nokia Health Items': - 'de': 'Nokia Health Items' - 'en': 'Nokia Health Items' + 'Withings Health Items': + 'de': 'Withings Health Items' + 'en': 'Withings Health Items' + 'Withings Health Data Type': + 'de': 'Withings Health Datentyp' + 'en': 'Withings Health Data Type' 'Hier klicken, um OAuth2 Prozess zu starten!': 'de': 'Hier klicken, um OAuth2 Prozess zu starten!' 'en': 'Click here, to start OAuth2 process!' diff --git a/nokia_health/plugin.yaml b/withings_health/plugin.yaml similarity index 99% rename from nokia_health/plugin.yaml rename to withings_health/plugin.yaml index d7534a8fa..f9e1a4e4f 100644 --- a/nokia_health/plugin.yaml +++ b/withings_health/plugin.yaml @@ -9,7 +9,7 @@ plugin: tester: 'psilo909' state: ready keywords: health - documentation: 'http://smarthomeng.de/user/plugins_doc/config/nokia_health.html' + documentation: 'http://smarthomeng.de/user/plugins_doc/config/withings_health.html' support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/1141179-nokia-health-plugin' version: 1.5.3 # Plugin version diff --git a/withings_health/requirements.txt b/withings_health/requirements.txt new file mode 100644 index 000000000..cd7f22535 --- /dev/null +++ b/withings_health/requirements.txt @@ -0,0 +1 @@ +nokia>=1.0.0,<=1.1.0 diff --git a/nokia_health/webif/static/img/plugin_logo.png b/withings_health/webif/static/img/plugin_logo.png similarity index 100% rename from nokia_health/webif/static/img/plugin_logo.png rename to withings_health/webif/static/img/plugin_logo.png diff --git a/nokia_health/webif/templates/index.html b/withings_health/webif/templates/index.html similarity index 95% rename from nokia_health/webif/templates/index.html rename to withings_health/webif/templates/index.html index 36b7b31a8..947e06e36 100644 --- a/nokia_health/webif/templates/index.html +++ b/withings_health/webif/templates/index.html @@ -56,14 +56,14 @@
-
{{ _('Nokia Health Items') }} ({{ p.get_items()|length }})
+
{{ _('Withings Health Items') }} ({{ p.get_items()|length }})
- + @@ -93,7 +93,7 @@
{{ _('Nokia Health Items') }} ({{ p.get_items()|length }})
{{ _('OAuth2 Authorization URL') }} From ea2d8eb39ffbea3c38601ce7bb3c0949072791e5 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 24 Oct 2018 07:23:36 +0200 Subject: [PATCH 334/705] WithingsHealth: updated readme --- withings_health/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/withings_health/README.md b/withings_health/README.md index f13addf8a..23ef4012f 100644 --- a/withings_health/README.md +++ b/withings_health/README.md @@ -1,4 +1,4 @@ -# Nokia Health +# Withings Health ## Description From 326748c7686209f4406d5b83633a76379f00c2cb Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 24 Oct 2018 07:30:42 +0200 Subject: [PATCH 335/705] WithingsHealth: small correction --- withings_health/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/withings_health/__init__.py b/withings_health/__init__.py index 9a05797b1..34b0849b0 100644 --- a/withings_health/__init__.py +++ b/withings_health/__init__.py @@ -398,7 +398,7 @@ def index(self, reload=None, state=None, code=None, error=None): return tmpl.render(plugin_shortname=self.plugin.get_shortname(), plugin_version=self.plugin.get_version(), interface=None, item_count=len(self.plugin.get_items()), plugin_info=self.plugin.get_info(), tabcount=2, callback_url=self._get_callback_url(), - tab1title="Nokia Health Items (%s)" % len(self.plugin.get_items()), + tab1title="Withings Health Items (%s)" % len(self.plugin.get_items()), tab2title="OAuth2 Data", authorize_url=self._auth.get_authorize_url(), p=self.plugin, token_expiry=datetime.datetime.fromtimestamp(self.plugin.get_item( 'token_expiry')(), tz=self.plugin.shtime.tzinfo()), now=self.plugin.shtime.now(), code=code, From cdc40048b4a1fbcf4c3887f705230ea8098c0e27 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 24 Oct 2018 07:36:05 +0200 Subject: [PATCH 336/705] Dashbutton: change to "kamene" pypi package, successor of scapy-python3, to get rid of warming at startup --- dashbutton/__init__.py | 2 +- dashbutton/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dashbutton/__init__.py b/dashbutton/__init__.py index 18131285a..d9059ce30 100644 --- a/dashbutton/__init__.py +++ b/dashbutton/__init__.py @@ -1,7 +1,7 @@ __author__ = 'pfischi' import threading -from scapy.all import * +from kamene.all import * import logging from lib.model.smartplugin import SmartPlugin import time diff --git a/dashbutton/requirements.txt b/dashbutton/requirements.txt index 679d7ac67..d40efffde 100644 --- a/dashbutton/requirements.txt +++ b/dashbutton/requirements.txt @@ -1 +1 @@ -scapy-python3 >= 0.18 \ No newline at end of file +kamene >= 0.32 \ No newline at end of file From b3efda1b8a7d2a326f36f0b217c96e7b7f63dd56 Mon Sep 17 00:00:00 2001 From: onkelandy Date: Wed, 24 Oct 2018 20:35:43 +0200 Subject: [PATCH 337/705] got rid of type:foo entries --- wettercom/README.md | 177 --------------------- wettercom/additional_files/wettercom.yaml | 179 +--------------------- 2 files changed, 1 insertion(+), 355 deletions(-) diff --git a/wettercom/README.md b/wettercom/README.md index c84ebdb08..7aeb24672 100755 --- a/wettercom/README.md +++ b/wettercom/README.md @@ -30,413 +30,236 @@ Create a yaml file in the items folder with the following content or copy the fi %yaml 1.1 --- wetter: - type: foo - vorhersage: - type: foo - heute: - type: foo - frueh: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - mittag: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - spaet: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - nacht: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - morgen: - type: foo - frueh: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - mittag: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - spaet: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - nacht: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - uebermorgen: - type: foo - frueh: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - mittag: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - spaet: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - nacht: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num ``` diff --git a/wettercom/additional_files/wettercom.yaml b/wettercom/additional_files/wettercom.yaml index c486e7e11..a73cfa198 100755 --- a/wettercom/additional_files/wettercom.yaml +++ b/wettercom/additional_files/wettercom.yaml @@ -1,412 +1,235 @@ %yaml 1.1 --- wetter: - type: foo - vorhersage: - type: foo - heute: - type: foo - frueh: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - mittag: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - spaet: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - nacht: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - morgen: - type: foo - frueh: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - mittag: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - spaet: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - nacht: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - uebermorgen: - type: foo - frueh: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - mittag: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - spaet: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: type: num - nacht: - type: foo - temperatur: - type: foo - max: type: num - min: type: num - text: type: str - code: type: num - wind: - type: foo - geschwindigkeit: type: num - richtung: type: num - text: type: str - niederschlag: - type: num + type: num \ No newline at end of file From 7bd10ef96dde90976ce0f98e2ecadc98016dc37b Mon Sep 17 00:00:00 2001 From: Zapfen83 Date: Thu, 25 Oct 2018 11:13:26 +0200 Subject: [PATCH 338/705] neue Datei: roomba_980/README.md neue Datei: roomba_980/__init__.py neue Datei: roomba_980/plugin.yaml --- roomba_980/README.md | 98 ++ roomba_980/__init__.py | 100 ++ roomba_980/examples/complicated.py | 95 ++ roomba_980/examples/example_start_roomba | 8 + roomba_980/examples/simple.py | 25 + roomba_980/plugin.yaml | 52 + roomba_980/roomba/__init__.py | 3 + roomba_980/roomba/__main__.py | 590 ++++++++ roomba_980/roomba/config.ini | 24 + roomba_980/roomba/getpassword.py | 39 + roomba_980/roomba/password.py | 186 +++ roomba_980/roomba/res/binfull.png | Bin 0 -> 4806 bytes roomba_980/roomba/res/home.png | Bin 0 -> 1378 bytes roomba_980/roomba/res/map.png | Bin 0 -> 32050 bytes roomba_980/roomba/res/roomba-base.png | Bin 0 -> 1510 bytes roomba_980/roomba/res/roomba-charge.png | Bin 0 -> 1500 bytes roomba_980/roomba/res/roomba.png | Bin 0 -> 3668 bytes roomba_980/roomba/res/roombacancelled.png | Bin 0 -> 5149 bytes roomba_980/roomba/res/roombaerror.png | Bin 0 -> 1523 bytes roomba_980/roomba/roomba.py | 1641 +++++++++++++++++++++ roomba_980/roomba/roomba_direct.py | 599 ++++++++ 21 files changed, 3460 insertions(+) create mode 100644 roomba_980/README.md create mode 100755 roomba_980/__init__.py create mode 100644 roomba_980/examples/complicated.py create mode 100644 roomba_980/examples/example_start_roomba create mode 100644 roomba_980/examples/simple.py create mode 100644 roomba_980/plugin.yaml create mode 100755 roomba_980/roomba/__init__.py create mode 100755 roomba_980/roomba/__main__.py create mode 100644 roomba_980/roomba/config.ini create mode 100755 roomba_980/roomba/getpassword.py create mode 100755 roomba_980/roomba/password.py create mode 100644 roomba_980/roomba/res/binfull.png create mode 100644 roomba_980/roomba/res/home.png create mode 100644 roomba_980/roomba/res/map.png create mode 100644 roomba_980/roomba/res/roomba-base.png create mode 100644 roomba_980/roomba/res/roomba-charge.png create mode 100644 roomba_980/roomba/res/roomba.png create mode 100644 roomba_980/roomba/res/roombacancelled.png create mode 100644 roomba_980/roomba/res/roombaerror.png create mode 100755 roomba_980/roomba/roomba.py create mode 100755 roomba_980/roomba/roomba_direct.py diff --git a/roomba_980/README.md b/roomba_980/README.md new file mode 100644 index 000000000..47f43bada --- /dev/null +++ b/roomba_980/README.md @@ -0,0 +1,98 @@ +# roomba_980 + +Dies ist ein Plugin für das SmarthomeNG Projekt um den iRobot Roomba 980 zu nutzen + +zusätzlich muss das Projekt https://github.com/NickWaterton/Roomba980-Python in das verzeichniss hinterlegt werden + + +## Wie bekomme ich meine blid und mein Passwort + +zu erst müsst ihr das Projekt Roomba980-Python herrunterladen und das roomba Verzeichnis ins rooomba_980 Plugin Verzeichnis kopieren + +in dem Verzeichnis befindet ein getpassword.py, das ihr ausführen müsst, danach bekommt ihr folgende meldung: + +``` +found 1 Roomba(s) +Make sure your robot (Robii) at IP 192.168.0.100 is on the Home Base and powered on (green lights on). Then press and hold the HOME button on your robot until it plays a series of tones (about 2 seconds). Release the button and your robot will flash WIFI light. +Press Enter to continue... +Received: { + "robotname": "Robii", + "sku": "R980040", + "nc": 0, + "ver": "3", + "proto": "mqtt", + "ip": "192.168.5.147", + "hostname": "Roomba-6977C20412227550", + "sw": "v2.4.6-3", + "mac": "F0:03:8C:B5:78:36", + "cap": { + "carpetBoost": 1, + "pp": 1, + "langOta": 1, + "binFullDetect": 1, + "ota": 2, + "maps": 1, + "pose": 1, + "eco": 1, + "multiPass": 2, + "edge": 1, + "svcConf": 1 + } +} +Roomba (Robii) IP address is: 192.168.5.147 +blid is: 123456789013456 +Password=> ABCD EFGGDBAN <= Yes, all this string. +Use these credentials in roomba.py +``` + + + + +## Um das Plugin zu aktivieren müsst ihr Folgendes in eure plugin.ymal aufnehmen: + +``` +roomba_980: + class_name: ROOMBA_980 + class_path: plugins.roomba_980 + adress: '192.168.0.100' # IP Adresse des Roomba + blid: '123456789013456' # die blid des roomba Staubsaugers -> kann mit der getpassword.py ausgelesen werden" + roombaPassword: 'ABCD EFGGDBAN' # das Passwort des roomba Staubsaugers -> kann mit der getpassword.py ausgelesen werden" + # cycle: 600 # Optional, nach wie vielen Sekunden die nächste Statusabfrage durchgeführt wird +``` + + +## Hier meine item.yaml: +``` +roomba: + + status_batterie: + type: num + roomba_980: status_batterie + + status_bin_full: + type: bool + roomba_980: status_bin_full + + status_cleanMissionStatus_phase: + type: str + roomba_980: status_cleanMissionStatus_phase + + status_cleanMissionStatus_error: + type: num + roomba_980: status_cleanMissionStatus_error + + start: + type: bool + roomba_980: start + visu_acl: rw + + stop: + type: bool + roomba_980: stop + visu_acl: rw + + dock: + type: bool + roomba_980: dock + visu_acl: rw +``` diff --git a/roomba_980/__init__.py b/roomba_980/__init__.py new file mode 100755 index 000000000..71eb875e2 --- /dev/null +++ b/roomba_980/__init__.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2011 KNX-User-Forum e.V. http://knx-user-forum.de/ +######################################################################### +# This file is part of SmartHome.py. http://mknx.github.io/smarthome/ +# +# SmartHome.py is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# SmartHome.py is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with SmartHome.py. If not, see . +######################################################################### + +import logging +from plugins.roomba_980.roomba import Roomba +from lib.model.smartplugin import SmartPlugin + +class ROOMBA_980(SmartPlugin): + + ALLOW_MULTIINSTANCE = False + PLUGIN_VERSION = "1.0.0" + + logger = logging.getLogger(__name__) + + def __init__(self, sh, adress=None, blid=None, roombaPassword=None, cycle=900): + self._sh = sh + self._address = adress + self._blid = blid + self._roombaPassword = roombaPassword + self._cycle = cycle + + self.myroomba = None + + self._status_batterie = None + self._status_items = {} + + def parse_logic(self, logic): + pass + + def parse_item(self, item): + if self.has_iattr(item.conf, 'roomba_980'): + item_type = self.get_iattr_value(item.conf, 'roomba_980') + if item_type == "start" or item_type == "stop" or item_type == "dock": + return self.update_item + + self._status_items[item_type] = item + + self.logger.debug('Roomba_980: item gefunden {}'.format(item)) + + def run(self): + self.myroomba = Roomba(self._address, self._blid, self._roombaPassword) + self.myroomba.connect() + self.scheduler_add(__name__, self.get_status, prio=5, cycle=self._cycle, offset=2) + self.alive = True + + def stop(self): + self.scheduler.remove(__name__) + self.myroomba.disconnect() + self.alive = False + + def __call__(self): + pass + + def update_item(self, item, caller=None, source=None, dest=None): + if caller != __name__ and self.has_iattr(item.conf, 'roomba_980'): + if self.get_iattr_value(item.conf, 'roomba_980') == "start": + if item() == True: + self.logger.debug('Roomba_980: Start') + if self.get_iattr_value(item.conf, 'roomba_980') == "stop": + if item() == True: + self.logger.debug('Roomba_980: Stop') + if self.get_iattr_value(item.conf, 'roomba_980') == "dock": + if item() == True: + self.logger.debug('Roomba_980: Dock') + + def get_status(self): + + status = self.myroomba.master_state + + for status_item in self._status_items: + if status_item == "status_batterie": + self._status_items[status_item](status['state']['reported']['batPct'],__name__) + if status_item == "status_bin_full": + self._status_items[status_item](status['state']['reported']['bin']['full'],__name__) + if status_item == "status_cleanMissionStatus_phase": + self._status_items[status_item](status['state']['reported']['cleanMissionStatus']['phase'],__name__) + if status_item == "status_cleanMissionStatus_error": + self._status_items[status_item](status['state']['reported']['cleanMissionStatus']['error'],__name__) + + self.logger.debug('Roomba_980: Status update') + + diff --git a/roomba_980/examples/complicated.py b/roomba_980/examples/complicated.py new file mode 100644 index 000000000..90a50393b --- /dev/null +++ b/roomba_980/examples/complicated.py @@ -0,0 +1,95 @@ +from __future__ import print_function +from roomba import Roomba +import paho.mqtt.client as mqtt +import time +import json + +#put your own values here +broker = 'localhost' #ip of mqtt broker +user = 'user' #mqtt username +password = 'password' #mqtt password +#broker = None if not using local mqtt broker +address = '192.168.100.181' +blid = '3117850851637850' +roombaPassword = ':1:1493919143:gOiaWpQ4LbSoD1xJ' + +def broker_on_connect(client, userdata, flags, rc): + print("Broker Connected with result code "+str(rc)) + #subscribe to roomba feedback + if rc == 0: + mqttc.subscribe(brokerCommand) + mqttc.subscribe(brokerSetting) + +def broker_on_message(mosq, obj, msg): + #publish to roomba + if "command" in msg.topic: + print("Received COMMAND: %s" % str(msg.payload)) + myroomba.send_command(str(msg.payload)) + elif "setting" in msg.topic: + print("Received SETTING: %s" % str(msg.payload)) + cmd = str(msg.payload).split() + myroomba.set_preference(cmd[0], cmd[1]) + +def broker_on_publish(mosq, obj, mid): + pass + +def broker_on_subscribe(mosq, obj, mid, granted_qos): + print("Broker Subscribed: %s %s" % (str(mid), str(granted_qos))) + +def broker_on_disconnect(mosq, obj, rc): + print("Broker disconnected") + +def broker_on_log(mosq, obj, level, string): + print(string) + + +mqttc = None +if broker is not None: + brokerCommand = "/roomba/command" + brokerSetting = "/roomba/setting" + brokerFeedback = "/roomba/feedback" + + #connect to broker + mqttc = mqtt.Client() + #Assign event callbacks + mqttc.on_message = broker_on_message + mqttc.on_connect = broker_on_connect + mqttc.on_disconnect = broker_on_disconnect + mqttc.on_publish = broker_on_publish + mqttc.on_subscribe = broker_on_subscribe + + try: + mqttc.username_pw_set(user, password) #put your own mqtt user and password here if you are using them, otherwise comment out + mqttc.connect(broker, 1883, 60) #Ping MQTT broker every 60 seconds if no data is published from this script. + + except Exception as e: + print("Unable to connect to MQTT Broker: %s" % e) + mqttc = None + +myroomba = Roomba() #minnimum required to connect on Linux Debian system, will read connection from config file +#myroomba = Roomba(address, blid, roombaPassword, topic="#", continuous=True, clean=False, cert_name = "./ca-certificates.crt") #setting things manually + +#all these are optional, if you don't include them, the defaults will work just fine +#if you are using maps +myroomba.enable_map(enable=True, mapSize="(800,1650,-300,-50,2,0)", mapPath="./", iconPath="./") #enable live maps, class default is no maps +if broker is not None: + myroomba.set_mqtt_client(mqttc, brokerFeedback) #if you want to publish Roomba data to your own mqtt broker (default is not to) if you have more than one roomba, and assign a roombaName, it is addded to this topic (ie brokerFeedback/roombaName) +#finally connect to Roomba - (required!) +myroomba.connect() + +print(" to exit") +print("Subscribe to /roomba/feedback/# to see published data") + +try: + if mqttc is not None: + mqttc.loop_forever() + else: + while True: + print("Roomba Data: %s" % json.dumps(myroomba.master_state, indent=2)) + time.sleep(5) + +except (KeyboardInterrupt, SystemExit): + print("System exit Received - Exiting program") + myroomba.disconnect() + if mqttc is not None: + mqttc.disconnect() diff --git a/roomba_980/examples/example_start_roomba b/roomba_980/examples/example_start_roomba new file mode 100644 index 000000000..e27a6dc93 --- /dev/null +++ b/roomba_980/examples/example_start_roomba @@ -0,0 +1,8 @@ +#! /bin/bash +# example start line - insert your own values + +# looks like 3012830851937810 +# looks like :1:1493919143:gOiaYpQ4LbfoD1yJ +# -b is the ip of the mqtt broker to publish to, leave it out if you are not forwarding roomba data +# -s is the size and shape of the map (if you are drawing maps) x,y, dock location x,y, map rotation, roomba rotation +./roomba.py -R -u -w -b localhost -s '(800,1650,-300,-50,2,0)' diff --git a/roomba_980/examples/simple.py b/roomba_980/examples/simple.py new file mode 100644 index 000000000..798f601e6 --- /dev/null +++ b/roomba_980/examples/simple.py @@ -0,0 +1,25 @@ +from __future__ import print_function +from roomba import Roomba + +#uncomment the option you want to run, and replace address, blid and roombaPassword with your own values + +address = "192.168.100.181" +blid = "3115850251687850" +roombaPassword = ":1:1493319243:gOiaXpQ4lbSoD1xJ" + +myroomba = Roomba(address, blid, roombaPassword) +#or myroomba = Roomba() #if you have a config file - will attempt discovery if you don't +myroomba.connect() + +myroomba.set_preference("carpetBoost", "true") +#myroomba.set_preference("twoPass", "false") + +#myroomba.send_command("start") +#myroomba.send_command("stop") +#myroomba.send_command("dock") + +import json, time +for i in range(5): + print(json.dumps(myroomba.master_state, indent=2)) + time.sleep(1) +myroomba.disconnect() diff --git a/roomba_980/plugin.yaml b/roomba_980/plugin.yaml new file mode 100644 index 000000000..99d7fef6c --- /dev/null +++ b/roomba_980/plugin.yaml @@ -0,0 +1,52 @@ +# Metadata for the classic-plugin +plugin: + # Global plugin attributes + type: interface # plugin type (gateway, interface, protocol, system, web) + description: + de: 'Anbindung von iRobot Roomba Staubsaugern der Serie 900' + en: '' + maintainer: 'Zapfen' + tester: + keywords: irobot roomba # keywords, where applicable +# documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page +# support: https://knx-user-forum.de/forum/supportforen/smarthome-py + +# Following entries are for Smart-Plugins: + version: 1.0.0 # Plugin version + sh_minversion: 1.5 # minimum shNG version to use this plugin +# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) + multi_instance: False + classname: ROOMBA_980 # class containing the plugin + +parameters: + # Definition of parameters to be configured in etc/plugin.yaml + + adress: + type: str + default: True + description: + de: "IP Adresse des roomba Staubsaugers" + en: "" + + blid: + type: str + default: True + description: + de: "Die blid des roomba Staubsaugers -> kann mit der getpassword.py ausgelesen werden" + en: "" + + roombaPassword: + type: str + default: True + description: + de: "Das Passwort des roomba Staubsaugers -> kann mit der getpassword.py ausgelesen werden" + en: "" + + cycle: + type: num + default: False + description: + de: "update des items alle x Sekunden" + en: "" +#item_attributes: + # Definition of item attributes defined by this plugin diff --git a/roomba_980/roomba/__init__.py b/roomba_980/roomba/__init__.py new file mode 100755 index 000000000..f73355eda --- /dev/null +++ b/roomba_980/roomba/__init__.py @@ -0,0 +1,3 @@ +from __future__ import absolute_import +from .roomba import Roomba +from .password import Password diff --git a/roomba_980/roomba/__main__.py b/roomba_980/roomba/__main__.py new file mode 100755 index 000000000..2c2ee66b8 --- /dev/null +++ b/roomba_980/roomba/__main__.py @@ -0,0 +1,590 @@ +from __future__ import print_function +from ast import literal_eval +from logging.handlers import RotatingFileHandler +import sys +if sys.version_info[0] < 3: #added for python 2.7 fix NW 15/9/2017 + import roomba + from roomba import Password +else: + from roomba import roomba + from roomba.password import Password +import argparse +import json +import logging +import os +import six +import socket +import time +# Import trickery +global HAVE_CV2 +global HAVE_MQTT +global HAVE_PIL +HAVE_CV2 = HAVE_MQTT = HAVE_PIL = False #fix for if neither PIL or OPENCV is installed (RPI versions) NW 3/2/2018 +try: + import configparser +except: + from six.moves import configparser +try: + import paho.mqtt.client as mqtt + HAVE_MQTT = True +except ImportError: + print("paho mqtt client not found") +try: + import cv2 + HAVE_CV2 = True +except ImportError: + print("CV or numpy module not found, falling back to PIL") + +# NOTE: MUST use Pillow Pillow 4.1.1 to avoid some horrible memory leaks in the +# text handling! +try: + from PIL import Image + HAVE_PIL = True +except ImportError: + print("PIL module not found, maps are disabled") + +def parse_args(): + default_icon_path = os.path.join(os.path.dirname(__file__), 'res') + #-------- Command Line ----------------- + parser = argparse.ArgumentParser( + description='Forward MQTT data from Roomba 980 to local MQTT broker') + parser.add_argument( + '-f', '--configfile', + action='store', + type=str, + default="./config.ini", + help='config file name (default: ./config.ini)') + parser.add_argument( + '-n', '--roombaName', + action='store', + type=str, + default="", help='optional Roomba name (default: "")') + parser.add_argument( + '-t', '--topic', + action='store', + type=str, + default="#", + help='Roomba MQTT Topic to subscribe to (can use wildcards # and ' + '+ default: #)') + parser.add_argument( + '-T', '--brokerFeedback', + action='store', + type=str, + default="/roomba/feedback", + help='Topic on broker to publish feedback to (default: ' + '/roomba/feedback)') + parser.add_argument( + '-C', '--brokerCommand', + action='store', + type=str, + default="/roomba/command", + help='Topic on broker to publish commands to (default: ' + '/roomba/command)') + parser.add_argument( + '-S', '--brokerSetting', + action='store', + type=str, + default="/roomba/setting", + help='Topic on broker to publish settings to (default: ' + '/roomba/setting)') + parser.add_argument( + '-b', '--broker', + action='store', + type=str, + default=None, + help='ipaddress of MQTT broker (default: None)') + parser.add_argument( + '-p', '--port', + action='store', + type=int, + default=1883, + help='MQTT broker port number (default: 1883)') + parser.add_argument( + '-U', '--user', + action='store', + type=str, + default=None, + help='MQTT broker user name (default: None)') + parser.add_argument( + '-P', '--password', + action='store', + type=str, + default=None, + help='MQTT broker password (default: None)') + parser.add_argument( + '-R', '--roombaIP', + action='store', + type=str, + default=None, + help='ipaddress of Roomba 980 (default: None)') + parser.add_argument( + '-u', '--blid', + action='store', + type=str, + default=None, + help='Roomba 980 blid (default: None)') + parser.add_argument( + '-w', '--roombaPassword', + action='store', + type=str, + default=None, + help='Roomba 980 password (default: None)') + parser.add_argument( + '-i', '--indent', + action='store', + type=int, + default=0, + help='Default indentation=auto') + parser.add_argument( + '-l', '--log', + action='store', + type=str, + default="./Roomba.log", + help='path/name of log file (default: ./Roomba.log)') + parser.add_argument( + '-e', '--echo', + action='store_false', + default = True, + help='Echo to Console (default: True)') + parser.add_argument( + '-D', '--debug', + action='store_true', + default = False, + help='debug mode') + parser.add_argument( + '-r', '--raw', + action='store_true', + default = False, + help='Output raw data to mqtt, no decoding of json data') + parser.add_argument( + '-j', '--pretty_print', + action='store_true', + default = False, + help='pretty print json in logs') + parser.add_argument( + '-c','--continuous', + action='store_false', + default = True, + help='Continuous connection to Roomba (default: True)') + parser.add_argument( + '-d', '--delay', + action='store', + type=int, + default=1000, + help='Disconnect period for non-continuous connection (default: ' + '1000ms)') + parser.add_argument( + '-m', '--drawmap', + action='store_false', + default = True, + help='Draw Roomba cleaning map (default: True)') + parser.add_argument( + '-M', '--mapPath', + action='store', + type=str, + default=".", + help='Location to store maps to (default: .)') + parser.add_argument( + '-s', '--mapSize', + action='store', + type=str, + default="(800,1500,0,0,0,0)", + help='Map Size, Dock offset and skew for the map. (800,1500) is the ' + 'size, (0,0) is the dock location, in the center of the map, 0 ' + 'is the rotation of the map, 0 is the rotation of the roomba. ' + 'Use single quotes around the string. (default: ' + '"(800,1500,0,0,0,0)")') + parser.add_argument( + '-I', '--iconPath', + action='store', + type=str, + default=default_icon_path, + help='location of icons. (default: "./")') + parser.add_argument( + '-o', '--roomOutline', + action='store_false', + default = True, + help='Draw room outline (default: True)') + parser.add_argument( + '-x', '--exclude', + action='store',type=str, default="", help='Exclude topics that have this in them (default: "")') + parser.add_argument( + '--cert', + action='store', + type=str, + default='/etc/ssl/certs/ca-certificates.crt', + help='Set the certificate to use for MQTT communication with the Roomba') + parser.add_argument( + '--version', + action='version', + version="%(prog)s ({})".format(roomba.__version__), + help='Display version of this program') + return parser.parse_args() + +def main(): + arg = parse_args() + + #----------- Local Routines ------------ + + def broker_on_connect(client, userdata, flags, rc): + log.debug("Broker Connected with result code " + str(rc)) + #subscribe to roomba feedback, if there is more than one roomba, the + # roombaName is added to the topic to subscribe to + if rc == 0: + if brokerCommand != "": + if len(roombas) == 1: + mqttc.subscribe(brokerCommand) + else: + for myroomba in roomba_list: + mqttc.subscribe( + brokerCommand + "/" + myroomba.roombaName) + if brokerSetting != "": + if len(roombas) == 1: + mqttc.subscribe(brokerSetting) + else: + for myroomba in roomba_list: + mqttc.subscribe( + brokerSetting + "/" + myroomba.roombaName) + + def broker_on_message(mosq, obj, msg): + # publish to roomba, if there is more than one roomba, the roombaName + # is added to the topic to publish to + msg.payload = msg.payload.decode("utf-8") + if "command" in msg.topic: + log.info("Received COMMAND: %s" % str(msg.payload)) + if len(roombas) == 1: + roomba_list[0].send_command(str(msg.payload)) + else: + for myroomba in roomba_list: + if myroomba.roombaName in msg.topic: + myroomba.send_command(str(msg.payload)) + elif "setting" in msg.topic: + log.info("Received SETTING: %s" % str(msg.payload)) + cmd = str(msg.payload).split() + if len(roombas) == 1: + roomba_list[0].set_preference(cmd[0], cmd[1]) + else: + for myroomba in roomba_list: + if myroomba.roombaName in msg.topic: + myroomba.set_preference(cmd[0], cmd[1]) + else: + log.warn("Unknown topic: %s" % str(msg.topic)) + + def broker_on_publish(mosq, obj, mid): + pass + + def broker_on_subscribe(mosq, obj, mid, granted_qos): + log.debug("Broker Subscribed: %s %s" % (str(mid), str(granted_qos))) + + def broker_on_disconnect(mosq, obj, rc): + log.debug("Broker disconnected") + if rc == 0: + sys.exit(0) + + def broker_on_log(mosq, obj, level, string): + log.info(string) + + def read_config_file(file="./config.ini"): + #read config file + Config = configparser.ConfigParser() + try: + Config.read(file) + log.info("reading info from config file %s" % file) + roombas = {} + for address in Config.sections(): + roomba_data = literal_eval(Config.get(address, "data")) + roombas[address] = { + "blid": Config.get(address, "blid"), + "password": Config.get(address, "password"), + "roombaName": roomba_data.get("robotname", None)} + except Exception as e: + log.warn("Error reading config file %s" %e) + return roombas + + def create_html(myroomba,mapPath="."): + ''' + Create html files for live display of roomba maps - but only if they + don't already exist + ''' + #default css and html + css='''body { + background-color: white; + color: white; + margin: 0; + padding: 0; + } +img,video { + width: auto; + max-height:100%; + } +''' + html=''' + + + + + + + +''' + html +='Roomba Map Live' % myroomba.roombaName + html +=''' + + +''' + #python 3 workaround + try: + FileNotFoundError + except NameError: + #py2 + FileNotFoundError = PermissionError = IOError + + #check is style.css exists, if not create it + css_path = mapPath+"/style.css" + try: + fn = open(css_path , "r") #check if file exists (or is readable) + fn.close() + except (IOError,FileNotFoundError): + log.warn("CSS file not found, creating %s" % css_path) + try: + with open(css_path , "w") as fn: + fn.write(css) + except (IOError, PermissionError) as e: + log.error("unable to create file %s, error: %s" % css_path, e) + #check is html exists, if not create it + html_path = mapPath+"/"+ myroomba.roombaName + "roomba_map.html" + try: + fn = open(html_path, "r") #check if file exists (or is readable) + fn.close() + except (IOError,FileNotFoundError): + log.warn("html file not found, creating %s" % html_path) + try: + with open(html_path, "w") as fn: + fn.write(html) + make_executable(html_path) + except (IOError, PermissionError) as e: + log.error("unable to create file %s, error: %s" % html_path, e) + + def make_executable(path): + mode = os.stat(path).st_mode + mode |= (mode & 0o444) >> 2 # copy R bits to X + os.chmod(path, mode) + + def setup_logger(logger_name, log_file, level=logging.DEBUG, console=False): + try: + l = logging.getLogger(logger_name) + if logger_name ==__name__: + formatter = logging.Formatter( + '[%(levelname)1.1s %(asctime)s] %(message)s') + else: + formatter = logging.Formatter('%(message)s') + fileHandler = RotatingFileHandler( + log_file, mode='a', maxBytes=2000000, backupCount=5) + fileHandler.setFormatter(formatter) + if console == True: + streamHandler = logging.StreamHandler() + + l.setLevel(level) + l.addHandler(fileHandler) + if console == True: + streamHandler.setFormatter(formatter) + l.addHandler(streamHandler) + except IOError as e: + if e[0] == 13: #errno Permission denied + print("Error: %s: You probably don't have permission to " + "write to the log file/directory - try sudo" % e) + else: + print("Log Error: %s" % e) + sys.exit(1) + + args = parse_args() + + if arg.debug: + log_level = logging.DEBUG + else: + log_level = logging.INFO + + #setup logging + setup_logger(__name__, arg.log,level=log_level,console=arg.echo) + + log = logging.getLogger(__name__) + + log.info("*******************") + log.info("* Program Started *") + log.info("*******************") + + log.info("Roomba.py Version: %s" % roomba.__version__) + + log.info("Python Version: %s" % sys.version.replace('\n','')) + + if HAVE_MQTT: + import paho.mqtt # bit of a kludge, just to get the version number + log.info("Paho MQTT Version: %s" % paho.mqtt.__version__) + if (sys.version_info.major == 2 and sys.version_info.minor == 7 and + sys.version_info.micro < 9 and + int(paho.mqtt.__version__.split(".")[0]) >= 1 and + int(paho.mqtt.__version__.split(".")[1]) > 2): + log.error("NOTE: if your python version is less than 2.7.9, " + "and Paho MQTT verion is not 1.2.3 or lower, this " + "program will NOT WORK") + log.error("Please use pip install paho-mqtt==1.2.3 to " + "downgrade paho-mqtt, or use a later version of python") + sys.exit(1) + + if HAVE_CV2: + log.info("CV Version: %s" % cv2.__version__) + + if HAVE_PIL: + import PIL #bit of a kludge, just to get the version number + log.info("PIL Version: %s" % PIL.__version__) + if int(PIL.__version__.split(".")[0]) < 4: + log.warn("WARNING: PIL version is %s, this is not the latest! " + "You can get bad memory leaks with old versions of PIL" + % Image.PILLOW_VERSION) + log.warn("run: 'pip install --upgrade pillow' to fix this") + + log.debug("-- DEBUG Mode ON -") + log.info(" to Exit") + log.info("Roomba 980 MQTT data Interface") + + roombas = {} + + if arg.blid is None or arg.roombaPassword is None: + roombas = read_config_file(arg.configfile) + if len(roombas) == 0: + log.warn("No roomba or config file defined, I will attempt to " + "discover Roombas, please put the Roomba on the dock " + "and follow the instructions:") + if arg.roombaIP is None: + Password(file=arg.configfile) + else: + Password(arg.roombaIP,file=arg.configfile) + roombas = read_config_file(arg.configfile) + if len(roombas) == 0: + log.error("No Roombas found! You must specify RoombaIP, blid " + "and roombaPassword to run this program, or have " + "a config file, use -h to show options.") + sys.exit(0) + else: + log.info("Success! %d Roombas Found!" % len(roombas)) + else: + roombas[arg.roombaIP] = { + "blid": arg.blid, + "password": arg.roombaPassword, + "roombaName": arg.roombaName} + + # set broker = "127.0.0.1" # mosquitto broker is running on localhost + mqttc = None + if arg.broker is not None: + brokerCommand = arg.brokerCommand + brokerSetting = arg.brokerSetting + + # connect to broker + mqttc = mqtt.Client() + # Assign event callbacks + mqttc.on_message = broker_on_message + mqttc.on_connect = broker_on_connect + mqttc.on_disconnect = broker_on_disconnect + mqttc.on_publish = broker_on_publish + mqttc.on_subscribe = broker_on_subscribe + # uncomment to enable logging + # mqttc.on_log = broker_on_log + + try: + if arg.user != None: + mqttc.username_pw_set(arg.user, arg.password) + log.info("connecting to broker") + # Ping MQTT broker every 60 seconds if no data is published + # from this script. + mqttc.connect(arg.broker, arg.port, 60) + + except socket.error: + log.error("Unable to connect to MQTT Broker") + mqttc = None + + roomba_list = [] + for addr, info in six.iteritems(roombas): + log.info("Creating Roomba object %s" % addr) + #NOTE: cert_name is a default certificate. change this if your + # certificates are in a different place. any valid certificate will + # do, it's not used but needs to be there to enable mqtt TLS encryption + # instansiate Roomba object + # minnimum required to connect on Linux Debian system + # myroomba = Roomba(address, blid, roombaPassword) + roomba_list.append( + roomba.Roomba(addr, blid=info["blid"], + password=info["password"], + topic=arg.topic, continuous=arg.continuous, + clean=False, + cert_name=args.cert, + roombaName=info["roombaName"])) + + for myroomba in roomba_list: + log.info("connecting Roomba %s" % myroomba.address) + # auto create html files (if they don't exist) + create_html(myroomba,arg.mapPath) + # all these are optional, if you don't include them, the defaults + # will work just fine + if arg.exclude != "": + myroomba.exclude = arg.exclude + myroomba.set_options( + raw=arg.raw, indent=arg.indent, pretty_print=arg.pretty_print) + if not arg.continuous: + myroomba.delay = arg.delay//1000 + if arg.mapSize != "" and arg.mapPath != "": + # enable live maps, class default is no maps + myroomba.enable_map(enable=True, mapSize=arg.mapSize, + mapPath=arg.mapPath, iconPath=arg.iconPath, + roomOutline=arg.roomOutline) + if arg.broker is not None: + # if you want to publish Roomba data to your own mqtt broker + # (default is not to) if you have more than one roomba, and + # assign a roombaName, it is addded to this topic + # (ie brokerFeedback/roombaName) + myroomba.set_mqtt_client(mqttc, arg.brokerFeedback) + # finally connect to Roomba - (required!) + myroomba.connect() + + try: + if mqttc is not None: + mqttc.loop_forever() + else: + while True: + log.info("Roomba Data: %s" % + json.dumps(myroomba.master_state, indent=2)) + time.sleep(5) + + except (KeyboardInterrupt, SystemExit): + log.info("System exit Received - Exiting program") + mqttc.disconnect() + sys.exit(0) + + +if __name__ == '__main__': + main() diff --git a/roomba_980/roomba/config.ini b/roomba_980/roomba/config.ini new file mode 100644 index 000000000..c7797d4df --- /dev/null +++ b/roomba_980/roomba/config.ini @@ -0,0 +1,24 @@ +[192.168.5.147] +blid = 6977C20412227550 +password = U1OuP439NAlFAahW +data = {u'cap': {u'binFullDetect': 1, + u'carpetBoost': 1, + u'eco': 1, + u'edge': 1, + u'langOta': 1, + u'maps': 1, + u'multiPass': 2, + u'ota': 2, + u'pose': 1, + u'pp': 1, + u'svcConf': 1}, + u'hostname': u'Roomba-6977C20412227550', + u'ip': u'192.168.5.147', + u'mac': u'F0:03:8C:B5:78:36', + u'nc': 0, + u'proto': u'mqtt', + u'robotname': u'Robii', + u'sku': u'R980040', + u'sw': u'v2.4.6-3', + u'ver': u'3'} + diff --git a/roomba_980/roomba/getpassword.py b/roomba_980/roomba/getpassword.py new file mode 100755 index 000000000..dd39db604 --- /dev/null +++ b/roomba_980/roomba/getpassword.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +__version__ = "1.0" +''' +Python 2.7+ +Quick Program to get blid and password from roomba + +Nick Waterton 5th May 2017: V 1.0: Initial Release +''' + +from roomba import Password + +def main(): + import argparse + #-------- Command Line ----------------- + parser = argparse.ArgumentParser( + description='Forward MQTT data from Roomba 980 to local MQTT broker') + parser.add_argument( + '-f', '--configfile', + action='store', + type=str, + default="./config.ini", + help='config file name, default: ./config.ini)') + parser.add_argument( + '-R','--roombaIP', + action='store', + type=str, + default=None, + help='ipaddress of Roomba 980 (default: None)') + arg = parser.parse_args() + + if arg.roombaIP is None: + Password(file=arg.configfile) + else: + Password(arg.roombaIP,file=arg.configfile) + +if __name__ == '__main__': + main() diff --git a/roomba_980/roomba/password.py b/roomba_980/roomba/password.py new file mode 100755 index 000000000..4e6e4995f --- /dev/null +++ b/roomba_980/roomba/password.py @@ -0,0 +1,186 @@ +from __future__ import print_function +from pprint import pformat +import json +import logging +import socket +import six +import ssl +import sys +try: + import configparser +except: + from six.moves import configparser + +if sys.version_info[0] < 3: #fix more python 3 incompatibilities + input = raw_input + +log = logging.getLogger(__name__) + +class Password(object): + ''' + Get Roomba blid and password - only V2 firmware supported + if IP is not supplied, class will attempt to discover the Roomba IP first. + Results are written to a config file, default ".\config.ini" + V 1.2.3 NW 9/10/2018 added support for Roomba i7 + ''' + + VERSION = __version__ = "1.2.4" + + def __init__(self, address='255.255.255.255', file=".\config.ini"): + self.address = address + self.file = file + #self.log = logging.getLogger(__name__+'.Roomba_getpassword') + if __name__ == "password": + self.log = logging.getLogger("__main__") #another logging fix NW 3/2/2018 + else: + self.log = logging.getLogger("roomba.__main__") + #self.log.info("__name__ is %s" % __name__) + self.log.info("Using Password version %s" % self.VERSION) + self.get_password() + + def receive_udp(self): + #set up UDP socket to receive data from robot + port = 5678 + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + s.settimeout(10) + if self.address == '255.255.255.255': + s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) + s.bind(("", port)) #bind all intefaces to port + print("waiting on port: %d for data" % port) + message = 'irobotmcs' + s.sendto(message.encode(), (self.address, port)) + roomba_dict = {} + while True: + try: + udp_data, addr = s.recvfrom(1024) #wait for udp data + #print('Received: Robot addr: %s Data: %s ' % (addr, udp_data)) + if len(udp_data) > 0: + if udp_data != message: + try: + if self.address != addr[0]: + self.log.warn( + "supplied address %s does not match " + "discovered address %s, using discovered " + "address..." % (self.address, addr[0])) + if udp_data.decode() != message: + parsedMsg = json.loads(udp_data.decode()) #1.2.3 added .decode() to avoid python 3 bytes error + roomba_dict[addr]=parsedMsg + except Exception as e: + print("json decode error: %s" % e) + print('RECEIVED: %s', pformat(udp_data)) + # print('Robot Data: %s ' + # % json.dumps(parsedMsg, indent=2)) + else: + break + except socket.timeout: + break + s.close() + return roomba_dict + + def get_password(self): + import struct + #get roomba info + blid=None + roombas = self.receive_udp() + + if len(roombas) == 0: + print("No Roombas found, try again...") + return False + else: + print("found %d Roomba(s)" % len(roombas)) + + for address,parsedMsg in six.iteritems(roombas): + addr = address[0] + if int(parsedMsg["ver"]) < 2: + print("Roombas at address: %s does not have the correct " + "firmware version. Your version info is: %s" + % (addr,json.dumps(parsedMsg, indent=2))) + continue + + print("Make sure your robot (%s) at IP %s is on the Home Base and " + "powered on (green lights on). Then press and hold the HOME " + "button on your robot until it plays a series of tones " + "(about 2 seconds). Release the button and your robot will " + "flash WIFI light." + % (parsedMsg["robotname"],addr)) + input("Press Enter to continue...") + + print("Received: %s" % json.dumps(parsedMsg, indent=2)) + print("\r\rRoomba (%s) IP address is: %s" + % (parsedMsg["robotname"],addr)) + hostname = parsedMsg["hostname"].split('-') + if hostname[0] == 'Roomba' or hostname[0] == 'iRobot': #for i7 robot name is now iRobot + blid = hostname[1] + + if hasattr(str, 'decode'): + # this is 0xf0 (mqtt reserved) 0x05(data length) + # 0xefcc3b2900 (data) + packet = 'f005efcc3b2900'.decode("hex") + else: + #this is 0xf0 (mqtt reserved) 0x05(data length) + # 0xefcc3b2900 (data) + packet = bytes.fromhex('f005efcc3b2900') + #send socket + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.settimeout(10) + + #ssl wrap + wrappedSocket = ssl.wrap_socket( + sock, ssl_version=ssl.PROTOCOL_TLSv1) + #connect and send packet + try: + wrappedSocket.connect((addr, 8883)) + except Exception as e: + print("Connection Error %s" % e) + + wrappedSocket.send(packet) + data = b'' + data_len = 35 + while True: + try: + # NOTE data is 0xf0 (mqtt RESERVED) length (0x23 = 35), + # 0xefcc3b2900 (magic packet), 0xXXXX... (30 bytes of + # password). so 7 bytes, followed by 30 bytes of password + # (total of 37) + if len(data) >= data_len+2: + break + data_received = wrappedSocket.recv(1024) + except socket.error as e: + print("Socket Error: %s" % e) + break + + if len(data_received) == 0: + print("socket closed") + break + else: + data += data_received + if len(data) >= 2: + data_len = struct.unpack("B", data[1:2])[0] + + #close socket + wrappedSocket.close() + # if len(data) > 0: + # import binascii + # print("received data: hex: %s, length: %d" + # % (binascii.hexlify(data), len(data))) + if len(data) <= 7: + print('Error getting password, receive %d bytes. Follow the ' + 'instructions and try again.' % len(data)) + return False + else: + # Convert password to str + #password = str(data[7:].decode()) #old version + password = str(data[7:].decode().rstrip()) #for i7 - has null termination + print("blid is: %s" % blid) + print('Password=> %s <= Yes, all this string.' % password) + print('Use these credentials in roomba.py') + + Config = configparser.ConfigParser() + Config.add_section(addr) + Config.set(addr,'blid', blid) + Config.set(addr,'password', password) + Config.set(addr,'data', pformat(parsedMsg)) + # write config file + with open(self.file, 'w') as cfgfile: + Config.write(cfgfile) + return True diff --git a/roomba_980/roomba/res/binfull.png b/roomba_980/roomba/res/binfull.png new file mode 100644 index 0000000000000000000000000000000000000000..15c2db65c68bd270066a55741bf941b0e8f562ae GIT binary patch literal 4806 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 literal 0 HcmV?d00001 diff --git a/roomba_980/roomba/res/home.png b/roomba_980/roomba/res/home.png new file mode 100644 index 0000000000000000000000000000000000000000..7496991078f279dc4906e278c7af3d49c1179ce9 GIT binary patch literal 1378 zcmV-o1)chdP)ijMHK#K?%hYL-9CgO zp(*J@UO{MBD7M{gw|lz?5(!2K1O%f&C1QN=k0@yi_#hFLNccev34(yp5D5Ix?)J9V zwiZe>5QPAt+jd*ZGo^)=w(Pxg{2^%DeX!da^-Jc*J#)|bzH?^I%mDu}*k~O+E?1Gk z`6@<4Oo#(MO*=W7I8wY0<>lpElB7+7Xg_BxAB^P-;MJV0ES@=ea(!D{n}{b~ToouO zDM^tfX&-n>gnd2vH}Q&8w@bs@mOd_j(4b2LJ+sobwlbK3`yDOgUC^ zMNysx(GdW-06GjImetnQo_a8MLb@gwuEYAbcR{&DM`B4xR#1cDd1(q*gZtl8ya|ejt0ssO&F$`mK zb$z|AD9RJJ2T=hIBr$!n*X!*D@S371K4BPpIOj8B5fE_?xZUnaB*b@|^8z8n9me^~ zs;V9Z0Efd-);%s~r+@Lb832%d{DX5TUCkTn>+3ZD@OV5~!Y~d2m`_B+7-Iw!tEyTz zk|%5zD2n1DA$*+kX$1VvIWJRHwE+O~3mxU{c`H7={QO7RL8}cxs|`11Elo%NUC&gh z*LtNRQ0MpiyVKIr_E{|!Gh@v0AZ%t%PR=pE-#-|w0?h4pZzLhMbIv6K4oZ^ry4UON zTj+3%zizf2@IO~k+><%a8cujhb3=db4_j)|ELc-jRn-LmrKP0{NQnKCB&7?Y7RK00 zRaKip1QZq)CM8%bd%@T;06K^^R@c<*0zgGYMV_8zHM$@!g0N`@D<}=0)aU!#$q$HC8V2aDNn>fE^7)GV0X}aSX$HMOP zr#`!|Wao6;#71)ZFL-!c=y+0D-^PEevdze4W!yeOyaI?;JU2FdFO`KYMZW zqA&ACFW})%5h{>%W>0%lz4}rliS`2MNw+TL-A$VkK0uhbq3;0^dB`l7P+ndh@doAK zCPoxFMoblW#2$DgqWOohhkuZawGHF&{~uN$T7XzG8?%719z@anV{XH-?15ak0T1JdQc7X(R kGFd*ZX__7_iGLk`05fMcj2k-sKmY&$07*qoM6N<$f)8D4hX4Qo literal 0 HcmV?d00001 diff --git a/roomba_980/roomba/res/map.png b/roomba_980/roomba/res/map.png new file mode 100644 index 0000000000000000000000000000000000000000..e6bebdfe58f0df29c8e103723ee1672b0b1c676e GIT binary patch literal 32050 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 literal 0 HcmV?d00001 diff --git a/roomba_980/roomba/res/roomba-base.png b/roomba_980/roomba/res/roomba-base.png new file mode 100644 index 0000000000000000000000000000000000000000..4af2f6df3de91752584e5918b3bea7c54bf47235 GIT binary patch literal 1510 zcmbtU`#;kQ0R0x4w+UmZ8IwmgT%n0#n&h=y+&qiPR!JUfJ&@jSu+ar~+NQXKWbtE38H4-LQj_)mOtdg9~s^Ef$L()KlK?Zm}bK;5>KZ{{iqOwiXKj zl95hWjMwe)+(!!3e6)N@_k4?GV}HKeetBpXF{#2xFrpTYSo%$^&T)G;KGixUKwP^Z zSjh`>>fQX6GS|K-x7`Vp^Jc$?_wW^0qui($MOcf=uYf?ol9B(4W|_#E^Miq7BAniVH#h_@#0px=-UW5pS4TM z#8L~QV(A8c3DYfGa>v|FwgR`!LL&r@G>CUf#qt(YO02iqt+S%l$aorm<;|K*bkb1z-t$^6CpOjN*~jT}MXF%k z89~WQ`o(gHSWilcw@>^gQXBSXWPmEX=#0PEa?yipNzb}=n~1DVq1D#!^^$;=jCH0i ziIDrIGeRMns5T_OX)LF!MRhtT;X z_(gl^UTHkn^)fPH6lg%-tXyB-sl3IO3L8aM6st+nQVvcWO1@V>RL&X{${BfIcjc5>=W5b|{4te6of4js z7Q|u^k!#?Ih`~-KvE+dtZzfvk^An9Nkt|}~2^&B5)IBw$dWW|h8;ftotvv!ypEg&BB|4Wz-o>H7E&Rr%#uy<# zx`m%fd#Ri$E7xTCHt&*idDEA>`P0rB%g^Rrrfjc954^u=)=6*0&@0cyM8-Y!8_*kU zHd()A4Hd&J@`H5tgC?T9t^SpL0>dKU=SWv%3|A5QHT4q(-(@h^CdL$UsHxpv&8nro zWq8PMBQ>6SQAI;dy7~H9YPwb5=-%Q`N%Icj#+AmHDk-v%f@l?; zRa9tTQex`;G<9wvk+mq2i?X!#`Jy)aCAny0eRBq0D8FH?%;ww(A1Kxf7IJ02N;5_h zpXk3@J&RJNH}~yn-RMMfN$3wlm_gsJNl#)N{0YYbX}4AHN$!(Gwk4ku256WfK?S!X zH&ktH8J}#xtXNj-E6u6I0900=vuG}-OJW){0Z6U?nj^NYvbZOM_@X=|{j0aQQm~_? ypXCxV)j89)J6$r5t=(Z`#YNP$c0uyCQ5TRE5xw#oS}NTAF~G?Ihkb4zl<*(5KK0Z9 literal 0 HcmV?d00001 diff --git a/roomba_980/roomba/res/roomba-charge.png b/roomba_980/roomba/res/roomba-charge.png new file mode 100644 index 0000000000000000000000000000000000000000..491b26cb32a3e0c8579fa9fdad1882535566dc0d GIT binary patch literal 1500 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 LTx_dh0SW&B4g&=X literal 0 HcmV?d00001 diff --git a/roomba_980/roomba/roomba.py b/roomba_980/roomba/roomba.py new file mode 100755 index 000000000..8923f8ab3 --- /dev/null +++ b/roomba_980/roomba/roomba.py @@ -0,0 +1,1641 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +''' +Python 2.7/Python 3.5/3.6 (thanks to pschmitt for adding Python 3 compatibility) +Program to connect to Roomba 980 vacuum cleaner, dcode json, and forward to mqtt +server + +Nick Waterton 24th April 2017: V 1.0: Initial Release +Nick Waterton 4th July 2017 V 1.1.1: Fixed MQTT protocol version, and map +paths, fixed paho-mqtt tls changes +Nick Waterton 5th July 2017 V 1.1.2: Minor fixes, CV version 3 .2 support +Nick Waterton 7th July 2017 V1.2.0: Added -o option "roomOutline" allows +enabling/disabling of room outline drawing, added auto creation of css/html files +Nick Waterton 11th July 2017 V1.2.1: Quick (untested) fix for room outlines +if you don't have OpenCV +Nick Waterton 3rd Feb 2018 V1.2.2: Quick (untested) fix for running directly (ie not installed) +Nick Waterton 12th April 2018 V1.2.3: Fixed image rotation bug causing distorted maps if map rotation was not 0. +''' + +from __future__ import print_function +from __future__ import absolute_import +__version__ = "1.2.3" + +from ast import literal_eval +from collections import OrderedDict, Mapping +try: + from roomba.password import Password +except ImportError: + from .password import Password +import datetime +import json +import math +import logging +import os +import six +import socket +import ssl +import sys +import threading +import time +import traceback +try: + import configparser +except: + from six.moves import configparser + +# Import trickery +global HAVE_CV2 +global HAVE_MQTT +global HAVE_PIL +HAVE_CV2 = False +HAVE_MQTT = False +HAVE_PIL = False +try: + import paho.mqtt.client as mqtt + HAVE_MQTT = True +except ImportError: + print("paho mqtt client not found") +try: + import cv2 + import numpy as np + HAVE_CV2 = True +except ImportError: + print("CV or numpy module not found, falling back to PIL") + +# NOTE: MUST use Pillow Pillow 4.1.1 to avoid some horrible memory leaks in the +# text handling! +try: + from PIL import Image, ImageDraw, ImageFont, ImageFilter, ImageOps + HAVE_PIL = True +except ImportError: + print("PIL module not found, maps are disabled") + +# On Python 3 raw_input was renamed to input +try: + input = raw_input +except NameError: + pass + + +class Roomba(object): + ''' + This is a Class for Roomba 900 series WiFi connected Vacuum cleaners + Requires firmware version 2.0 and above (not V1.0). Tested with Roomba 980 + username (blid) and password are required, and can be found using the + password() class above (or can be auto discovered) + Most of the underlying info was obtained from here: + https://github.com/koalazak/dorita980 many thanks! + The values received from the Roomba as stored in a dictionay called + master_state, and can be accessed at any time, the contents are live, and + will build with time after connection. + This is not needed if the forward to mqtt option is used, as the events will + be decoded and published on the designated mqtt client topic. + ''' + + VERSION = "1.0" + + states = {"charge": "Charging", + "new": "New Mission", + "run": "Running", + "resume": "Running", + "hmMidMsn": "Recharging", + "recharge": "Recharging", + "stuck": "Stuck", + "hmUsrDock": "User Docking", + "dock": "Docking", + "dockend": "Docking - End Mission", + "cancelled": "Cancelled", + "stop": "Stopped", + "pause": "Paused", + "hmPostMsn": "End Mission", + "": None} + + # From http://homesupport.irobot.com/app/answers/detail/a_id/9024/~/roomba-900-error-messages + _ErrorMessages = { + 0: "None", + 1: "Roomba is stuck with its left or right wheel hanging down.", + 2: "The debris extractors can't turn.", + 5: "The left or right wheel is stuck.", + 6: "The cliff sensors are dirty, it is hanging over a drop, "\ + "or it is stuck on a dark surface.", + 8: "The fan is stuck or its filter is clogged.", + 9: "The bumper is stuck, or the bumper sensor is dirty.", + 10: "The left or right wheel is not moving.", + 11: "Roomba has an internal error.", + 14: "The bin has a bad connection to the robot.", + 15: "Roomba has an internal error.", + 16: "Roomba has started while moving or at an angle, or was bumped "\ + "while running.", + 17: "The cleaning job is incomplete.", + 18: "Roomba cannot return to the Home Base or starting position." + } + + def __init__(self, address=None, blid=None, password=None, topic="#", + continuous=True, clean=False, cert_name="", roombaName="", + file="./config.ini"): + ''' + address is the IP address of the Roomba, the continuous flag enables a + continuous mqtt connection, if this is set to False, the client connects + and disconnects every 'delay' seconds (1 by default, but can be + changed). This is to allow other programs access, as there can only be + one Roomba connection at a time. + As cloud connections are unaffected, I reccomend leaving this as True. + leave topic as is, unless debugging (# = all messages). + if a python standard logging object exists, it will be used for logging. + ''' + + self.debug = False + self.log = logging.getLogger("roomba.__main__") #modified to work with new scheme NW 15/9/2017 + #self.log = logging.getLogger(__name__+'.Roomba') + if self.log.getEffectiveLevel() == logging.DEBUG: + self.debug = True + self.address = address + if not cert_name: + self.cert_name = "/etc/ssl/certs/ca-certificates.crt" + else: + self.cert_name = cert_name + self.continuous = continuous + if self.continuous: + self.log.info("CONTINUOUS connection") + else: + self.log.info("PERIODIC connection") + # set the following to True to enable pretty printing of json data + self.pretty_print = False + self.stop_connection = False + self.periodic_connection_running = False + self.clean = clean + self.roomba_port = 8883 + self.blid = blid + self.password = password + self.roombaName = roombaName + self.topic = topic + self.mqttc = None + self.exclude = "" + self.delay = 1 + self.roomba_connected = False + self.indent = 0 + self.master_indent = 0 + self.raw = False + self.drawmap = False + self.previous_co_ords = self.co_ords = self.zero_coords() + self.fnt = None + self.home_pos = None + self.angle = 0 + self.cleanMissionStatus_phase = "" + self.previous_cleanMissionStatus_phase = "" + self.current_state = None + self.last_completed_time = None + self.bin_full = False + self.base = None #base map + self.dock_icon = None #dock icon + self.roomba_icon = None #roomba icon + self.roomba_cancelled_icon = None #roomba cancelled icon + self.roomba_battery_icon = None #roomba battery low icon + self.roomba_error_icon = None #roomba error icon + self.bin_full_icon = None #bin full icon + self.room_outline_contour = None + self.room_outline = None + self.transparent = (0, 0, 0, 0) #transparent + self.previous_display_text = self.display_text = None + self.master_state = {} + self.time = time.time() + self.update_seconds = 300 #update with all values every 5 minutes + self.show_final_map = True + self.client = None + + if self.address is None or blid is None or password is None: + self.read_config_file(file) + + def read_config_file(self, file="./config.ini"): + #read config file + Config = configparser.ConfigParser() + try: + Config.read(file) + except Exception as e: + self.log.warn("Error reading config file %s" %e) + self.log.info("No Roomba specified, and no config file found - " + "attempting discovery") + if Password(self.address, file): + return self.read_config_file(file) + else: + return False + self.log.info("reading info from config file %s" % file) + addresses = Config.sections() + if self.address is None: + if len(addresses) > 1: + self.log.warn("config file has entries for %d Roombas, " + "only configuring the first!") + self.address = addresses[0] + self.blid = Config.get(self.address, "blid"), + self.password = Config.get(self.address, "password") + # self.roombaName = literal_eval( + # Config.get(self.address, "data"))["robotname"] + return True + + def setup_client(self): + if self.client is None: + if not HAVE_MQTT: + print("Please install paho-mqtt 'pip install paho-mqtt' " + "to use this library") + return False + self.client = mqtt.Client( + client_id=self.blid, clean_session=self.clean, + protocol=mqtt.MQTTv311) + # Assign event callbacks + self.client.on_message = self.on_message + self.client.on_connect = self.on_connect + self.client.on_publish = self.on_publish + self.client.on_subscribe = self.on_subscribe + self.client.on_disconnect = self.on_disconnect + + # Uncomment to enable debug messages + # client.on_log = self.on_log + + # set TLS, self.cert_name is required by paho-mqtt, even if the + # certificate is not used... + # but v1.3 changes all this, so have to do the following: + + self.log.info("Setting TLS") + try: + self.client.tls_set( + self.cert_name, cert_reqs=ssl.CERT_NONE, + tls_version=ssl.PROTOCOL_TLSv1) + except (ValueError, FileNotFoundError): # try V1.3 version + self.log.warn("TLS Setting failed - trying 1.3 version") + self.client._ssl_context = None + context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + context.verify_mode = ssl.CERT_NONE + context.load_default_certs() + self.client.tls_set_context(context) + except: + self.log.error("Error setting TLS: %s" % traceback.format_exc()) + + # disables peer verification + self.client.tls_insecure_set(True) + self.client.username_pw_set(self.blid, self.password) + self.log.info("Setting TLS - OK") + return True + return False + + def connect(self): + if self.address is None or self.blid is None or self.password is None: + self.log.critical("Invalid address, blid, or password! All these " + "must be specified!") + sys.exit(1) + if self.roomba_connected or self.periodic_connection_running: return + + if self.continuous: + if not self._connect(): + if self.mqttc is not None: + self.mqttc.disconnect() + sys.exit(1) + else: + self._thread = threading.Thread(target=self.periodic_connection) + self._thread.daemon = True + self._thread.start() + + self.time = time.time() #save connect time + + def _connect(self, count=0, new_connection=False): + max_retries = 3 + try: + if self.client is None or new_connection: + self.log.info("Connecting %s" % self.roombaName) + self.setup_client() + self.client.connect(self.address, self.roomba_port, 60) + else: + self.log.info("Attempting to Reconnect %s" % self.roombaName) + self.client.loop_stop() + self.client.reconnect() + self.client.loop_start() + return True + except Exception as e: + self.log.error("Error: %s " % e) + exc_type, exc_obj, exc_tb = sys.exc_info() + # self.log.error("Exception: %s" % exc_type) + # if e[0] == 111: #errno.ECONNREFUSED - does not work with + # python 3.0 so... + if exc_type == socket.error or exc_type == ConnectionRefusedError: + count += 1 + if count <= max_retries: + self.log.error("Attempting new Connection# %d" % count) + time.sleep(1) + self._connect(count, True) + if count == max_retries: + self.log.error("Unable to connect %s" % self.roombaName) + return False + + def disconnect(self): + if self.continuous: + self.client.disconnect() + else: + self.stop_connection = True + + def periodic_connection(self): + # only one connection thread at a time! + if self.periodic_connection_running: return + self.periodic_connection_running = True + while not self.stop_connection: + if self._connect(): + time.sleep(self.delay) + self.client.disconnect() + time.sleep(self.delay) + + self.client.disconnect() + self.periodic_connection_running = False + + def on_connect(self, client, userdata, flags, rc): + self.log.info("Roomba Connected %s" % self.roombaName) + if rc == 0: + self.roomba_connected = True + self.client.subscribe(self.topic) + else: + self.log.error("Roomba Connected with result code " + str(rc)) + self.log.error("Please make sure your blid and password are " + "correct %s" % self.roombaName) + if self.mqttc is not None: + self.mqttc.disconnect() + sys.exit(1) + + def on_message(self, mosq, obj, msg): + # print(msg.topic + " " + str(msg.qos) + " " + str(msg.payload)) + if self.exclude != "": + if self.exclude in msg.topic: + return + + if self.indent == 0: + self.master_indent = max(self.master_indent, len(msg.topic)) + + log_string, json_data = self.decode_payload(msg.topic,msg.payload) + self.dict_merge(self.master_state, json_data) + + if self.pretty_print: + self.log.info("%-{:d}s : %s".format(self.master_indent) + % (msg.topic,log_string)) + else: + self.log.info("Received Roomba Data %s: %s, %s" + % (self.roombaName, str(msg.topic), str(msg.payload))) + + if self.raw: + self.publish(msg.topic, msg.payload) + else: + self.decode_topics(json_data) + + # default every 5 minutes + if time.time() - self.time > self.update_seconds: + self.log.info("Publishing master_state %s" % self.roombaName) + self.decode_topics(self.master_state) # publish all values + self.time = time.time() + + def on_publish(self, mosq, obj, mid): + pass + + def on_subscribe(self, mosq, obj, mid, granted_qos): + self.log.debug("Subscribed: %s %s" % (str(mid), str(granted_qos))) + + def on_disconnect(self, mosq, obj, rc): + self.roomba_connected = False + if rc != 0: + self.log.warn("Unexpected Disconnect From Roomba %s! - reconnecting" + % self.roombaName) + else: + self.log.info("Disconnected From Roomba %s" % self.roombaName) + + def on_log(self, mosq, obj, level, string): + self.log.info(string) + + def set_mqtt_client(self, mqttc=None, brokerFeedback=""): + self.mqttc = mqttc + if self.mqttc is not None: + if self.roombaName != "": + self.brokerFeedback = brokerFeedback + "/" + self.roombaName + else: + self.brokerFeedback = brokerFeedback + + def send_command(self, command): + self.log.info("Received COMMAND: %s" % command) + Command = OrderedDict() + Command["command"] = command + Command["time"] = self.totimestamp(datetime.datetime.now()) + Command["initiator"] = "localApp" + myCommand = json.dumps(Command) + self.log.info("Publishing Roomba Command : %s" % myCommand) + self.client.publish("cmd", myCommand) + + def set_preference(self, preference, setting): + self.log.info("Received SETTING: %s, %s" % (preference, setting)) + val = False + if setting.lower() == "true": + val = True + tmp = {preference: val} + Command = {"state": tmp} + myCommand = json.dumps(Command) + self.log.info("Publishing Roomba Setting : %s" % myCommand) + self.client.publish("delta", myCommand) + + def publish(self, topic, message): + if self.mqttc is not None and message is not None: + self.log.debug("Publishing item: %s: %s" + % (self.brokerFeedback + "/" + topic, message)) + self.mqttc.publish(self.brokerFeedback + "/" + topic, message) + + def set_options(self, raw=False, indent=0, pretty_print=False): + self.raw = raw + self.indent = indent + self.pretty_print = pretty_print + if self.raw: + self.log.info("Posting RAW data") + else: + self.log.info("Posting DECODED data") + + def enable_map(self, enable=False, mapSize="(800,1500,0,0,0,0)", + mapPath=".", iconPath = "./", roomOutline=True, + home_icon_file="home.png", + roomba_icon_file="roomba.png", + roomba_error_file="roombaerror.png", + roomba_cancelled_file="roombacancelled.png", + roomba_battery_file="roomba-charge.png", + bin_full_file="binfull.png", + roomba_size=(50,50), draw_edges = 30, auto_rotate=True): + ''' + Enable live map drawing. mapSize is x,y size, x,y offset of docking + station ((0,0) is the center of the image) final value is map rotation + (in case map is not straight up/down). These values depend on the + size/shape of the area Roomba covers. Offset depends on where you place + the docking station. This will need some experimentation to get right. + You can supply 32x32 icons for dock and roomba etc. If the files don't + exist, crude representations are made. If you specify home_icon_file as + None, then no dock is drawn. Draw edges attempts to draw straight lines + around the final (not live) map, and Auto_rotate (on/off) attempts to + line the map up vertically. These only work if you have openCV + installed. otherwise a PIL version is used, which is not as good (but + less CPU intensive). roomOutline enables the previous largest saved + outline to be overlayed on the map (so you can see where cleaning was + missed). This is on by default, but the alignment doesn't work so well, + so you can turn it off. + Returns map enabled True/False + ''' + + if not HAVE_PIL: #can't draw a map without PIL! + return False + + if Image.PILLOW_VERSION < "4.1.1": + print("WARNING: PIL version is %s, this is not the latest! you " + "can get bad memory leaks with old versions of PIL" + % Image.PILLOW_VERSION) + print("run: 'pip install --upgrade pillow' to fix this") + + self.drawmap = enable + if self.drawmap: + self.log.info("MAP: Maps Enabled") + self.mapSize = literal_eval(mapSize) + if len(mapSize) < 6: + self.log.error("mapSize is required, and is of the form " + "(800,1500,0,0,0,0) - (x,y size, x,y dock loc," + "theta1, theta2), map,roomba roatation") + self.drawmap = False + return False + self.angle = self.mapSize[4] + self.roomba_angle = self.mapSize[5] + self.mapPath = mapPath + if home_icon_file is None: + self.home_icon_file = None + else: + self.home_icon_file = os.path.join(iconPath, home_icon_file) + self.roomba_icon_file = os.path.join(iconPath, roomba_icon_file) + self.roomba_error_file = os.path.join(iconPath, roomba_error_file) + self.roomba_cancelled_file = os.path.join(iconPath, roomba_cancelled_file) + self.roomba_battery_file = os.path.join(iconPath, roomba_battery_file) + self.bin_full_file = os.path.join(iconPath, bin_full_file) + self.draw_edges = draw_edges // 10000 + self.auto_rotate = auto_rotate + if not roomOutline: + self.log.info("MAP: Not drawing Room Outline") + self.roomOutline = roomOutline + + self.initialise_map(roomba_size) + return True + return False + + def totimestamp(self, dt): + td = dt - datetime.datetime(1970, 1, 1) + return int(td.total_seconds()) + + def dict_merge(self, dct, merge_dct): + """ Recursive dict merge. Inspired by :meth:``dict.update()``, instead + of updating only top-level keys, dict_merge recurses down into dicts + nested to an arbitrary depth, updating keys. The ``merge_dct`` is + merged into ``dct``. + :param dct: dict onto which the merge is executed + :param merge_dct: dct merged into dct + :return: None + """ + for k, v in six.iteritems(merge_dct): + if (k in dct and isinstance(dct[k], dict) + and isinstance(merge_dct[k], Mapping)): + self.dict_merge(dct[k], merge_dct[k]) + else: + dct[k] = merge_dct[k] + + def decode_payload(self, topic, payload): + ''' + Format json for pretty printing, return string sutiable for logging, + and a dict of the json data + ''' + indent = self.master_indent + 31 #number of spaces to indent json data + + try: + # if it's json data, decode it (use OrderedDict to preserve keys + # order), else return as is... + json_data = json.loads( + payload.decode("utf-8").replace(":nan", ":NaN").\ + replace(":inf", ":Infinity").replace(":-inf", ":-Infinity"), + object_pairs_hook=OrderedDict) + # if it's not a dictionary, probably just a number + if not isinstance(json_data, dict): + return json_data, dict(json_data) + json_data_string = "\n".join((indent * " ") + i for i in \ + (json.dumps(json_data, indent = 2)).splitlines()) + + formatted_data = "Decoded JSON: \n%s" % (json_data_string) + + except ValueError: + formatted_data = payload + + if self.raw: + formatted_data = payload + + return formatted_data, dict(json_data) + + def decode_topics(self, state, prefix=None): + ''' + decode json data dict, and publish as individual topics to + brokerFeedback/topic the keys are concatinated with _ to make one unique + topic name strings are expressely converted to strings to avoid unicode + representations + ''' + for k, v in six.iteritems(state): + if isinstance(v, dict): + if prefix is None: + self.decode_topics(v, k) + else: + self.decode_topics(v, prefix+"_"+k) + else: + if isinstance(v, list): + newlist = [] + for i in v: + if isinstance(i, dict): + for ki, vi in six.iteritems(i): + newlist.append((str(ki), vi)) + else: + if isinstance(i, six.string_types): + i = str(i) + newlist.append(i) + v = newlist + if prefix is not None: + k = prefix+"_"+k + # all data starts with this, so it's redundant + k = k.replace("state_reported_","") + # save variables for drawing map + if k == "pose_theta": + self.co_ords["theta"] = v + if k == "pose_point_x": #x and y are reversed... + self.co_ords["y"] = v + if k == "pose_point_y": + self.co_ords["x"] = v + if k == "bin_full": + self.bin_full = v + if k == "cleanMissionStatus_error": + try: + self.error_message = self._ErrorMessages[v] + except KeyError as e: + self.log.warn( + "Error looking up Roomba error message %s" % e) + self.error_message = "Unknown Error number: %d" % v + self.publish("error_message", self.error_message) + if k == "cleanMissionStatus_phase": + self.previous_cleanMissionStatus_phase = \ + self.cleanMissionStatus_phase + self.cleanMissionStatus_phase = v + + self.publish(k, str(v)) + + if prefix is None: + self.update_state_machine() + + def update_state_machine(self, new_state = None): + ''' + Roomba progresses through states (phases), current identified states + are: + "" : program started up, no state yet + "run" : running on a Cleaning Mission + "hmUsrDock" : returning to Dock + "hmMidMsn" : need to recharge + "hmPostMsn" : mission completed + "charge" : chargeing + "stuck" : Roomba is stuck + "stop" : Stopped + "pause" : paused + + available states: + states = { "charge":"Charging", + "new":"New Mission", + "run":"Running", + "resume":"Running", + "hmMidMsn":"Recharging", + "recharge":"Recharging", + "stuck":"Stuck", + "hmUsrDock":"User Docking", + "dock":"Docking", + "dockend":"Docking - End Mission", + "cancelled":"Cancelled", + "stop":"Stopped", + "pause":"Paused", + "hmPostMsn":"End Mission", + "":None} + + Normal Sequence is "" -> charge -> run -> hmPostMsn -> charge + Mid mission recharge is "" -> charge -> run -> hmMidMsn -> charge + -> run -> hmPostMsn -> charge + Stuck is "" -> charge -> run -> hmPostMsn -> stuck + -> run/charge/stop/hmUsrDock -> charge + Start program during run is "" -> run -> hmPostMsn -> charge + + Need to identify a new mission to initialize map, and end of mission to + finalise map. + Assume charge -> run = start of mission (init map) + stuck - > charge = init map + Assume hmPostMsn -> charge = end of mission (finalize map) + Anything else = continue with existing map + ''' + + current_mission = self.current_state + + #if self.current_state == None: #set initial state here for debugging + # self.current_state = self.states["recharge"] + # self.show_final_map = False + + # deal with "bin full" timeout on mission + try: + if (self.master_state["state"]["reported"]["cleanMissionStatus"]["mssnM"] == "none" and + self.cleanMissionStatus_phase == "charge" and + (self.current_state == self.states["pause"] or + self.current_state == self.states["recharge"])): + self.current_state = self.states["cancelled"] + except KeyError: + pass + + if (self.current_state == self.states["charge"] and + self.cleanMissionStatus_phase == "run"): + self.current_state = self.states["new"] + elif (self.current_state == self.states["run"] and + self.cleanMissionStatus_phase == "hmMidMsn"): + self.current_state = self.states["dock"] + elif (self.current_state == self.states["dock"] and + self.cleanMissionStatus_phase == "charge"): + self.current_state = self.states["recharge"] + elif (self.current_state == self.states["recharge"] and + self.cleanMissionStatus_phase == "charge" and self.bin_full): + self.current_state = self.states["pause"] + elif (self.current_state == self.states["run"] and + self.cleanMissionStatus_phase == "charge"): + self.current_state = self.states["recharge"] + elif (self.current_state == self.states["recharge"] + and self.cleanMissionStatus_phase == "run"): + self.current_state = self.states["pause"] + elif (self.current_state == self.states["pause"] + and self.cleanMissionStatus_phase == "charge"): + self.current_state = self.states["pause"] + # so that we will draw map and can update recharge time + current_mission = None + elif (self.current_state == self.states["charge"] and + self.cleanMissionStatus_phase == "charge"): + # so that we will draw map and can update charge status + current_mission = None + elif ((self.current_state == self.states["stop"] or + self.current_state == self.states["pause"]) and + self.cleanMissionStatus_phase == "hmUsrDock"): + self.current_state = self.states["cancelled"] + elif ((self.current_state == self.states["hmUsrDock"] or + self.current_state == self.states["cancelled"]) and + self.cleanMissionStatus_phase == "charge"): + self.current_state = self.states["dockend"] + elif (self.current_state == self.states["hmPostMsn"] and + self.cleanMissionStatus_phase == "charge"): + self.current_state = self.states["dockend"] + elif (self.current_state == self.states["dockend"] and + self.cleanMissionStatus_phase == "charge"): + self.current_state = self.states["charge"] + + else: + self.current_state = self.states[self.cleanMissionStatus_phase] + + if new_state is not None: + self.current_state = self.states[new_state] + self.log.info("set current state to: %s" % (self.current_state)) + + if self.current_state != current_mission: + self.log.info("updated state to: %s" % (self.current_state)) + + self.publish("state", self.current_state) + self.draw_map(current_mission != self.current_state) + + def make_transparent(self, image, colour=None): + ''' + take image and make white areas transparent + return transparent image + ''' + image = image.convert("RGBA") + datas = image.getdata() + newData = [] + for item in datas: + # white (ish) + if item[0] >= 254 and item[1] >= 254 and item[2] >= 254: + newData.append(self.transparent) + else: + if colour: + newData.append(colour) + else: + newData.append(item) + + image.putdata(newData) + return image + + def make_icon(self, input="./roomba.png", output="./roomba_mod.png"): + #utility function to make roomba icon from generic roomba icon + if not HAVE_PIL: #drawing library loaded? + self.log.error("PIL module not loaded") + return None + try: + roomba = Image.open(input).convert('RGBA') + roomba = roomba.rotate(90, expand=False) + roomba = self.make_transparent(roomba) + draw_wedge = ImageDraw.Draw(roomba) + draw_wedge.pieslice( + [(5,0),(roomba.size[0]-5,roomba.size[1])], + 175, 185, fill="red", outline="red") + roomba.save(output, "PNG") + return roomba + except Exception as e: + self.log.error("ERROR: %s" % e) + return None + + def load_icon(self, filename="", icon_name=None, fnt=None, size=(32,32), + base_icon=None): + ''' + Load icon from file, or draw icon if file not found. + returns icon object + ''' + if icon_name is None: + return None + + try: + icon = Image.open(filename).convert('RGBA').resize( + size,Image.ANTIALIAS) + icon = self.make_transparent(icon) + except IOError as e: + self.log.warn("error loading %s: %s, using default icon instead" + % (icon_name,e)) + if base_icon is None: + icon = Image.new('RGBA', size, self.transparent) + else: + icon = base_icon + + draw_icon = ImageDraw.Draw(icon) + + if icon_name == "roomba": + if base_icon is None: + draw_icon.ellipse([(5,5),(icon.size[0]-5,icon.size[1]-5)], + fill="green", outline="black") + draw_icon.pieslice([(5,5),(icon.size[0]-5,icon.size[1]-5)], + 355, 5, fill="red", outline="red") + elif icon_name == "stuck": + if base_icon is None: + draw_icon.ellipse([(5,5),(icon.size[0]-5,icon.size[1]-5)], + fill="green", outline="black") + draw_icon.pieslice([(5,5),(icon.size[0]-5,icon.size[1]-5)], + 175, 185, fill="red", outline="red") + draw_icon.polygon([( + icon.size[0]//2,icon.size[1]), (0, 0), (0,icon.size[1])], + fill = 'red') + if fnt is not None: + draw_icon.text((4,-4), "!", font=fnt, + fill=(255,255,255,255)) + elif icon_name == "cancelled": + if base_icon is None: + draw_icon.ellipse([(5,5),(icon.size[0]-5,icon.size[1]-5)], + fill="green", outline="black") + draw_icon.pieslice([(5,5),(icon.size[0]-5,icon.size[1]-5)], + 175, 185, fill="red", outline="red") + if fnt is not None: + draw_icon.text((4,-4), "X", font=fnt, fill=(255,0,0,255)) + elif icon_name == "bin full": + draw_icon.rectangle([ + icon.size[0]-10, icon.size[1]-10, + icon.size[0]+10, icon.size[1]+10], + fill = "grey") + if fnt is not None: + draw_icon.text((4,-4), "F", font=fnt, + fill=(255,255,255,255)) + elif icon_name == "battery": + draw_icon.rectangle([icon.size[0]-10, icon.size[1]-10, + icon.size[0]+10,icon.size[1]+10], fill = "orange") + if fnt is not None: + draw_icon.text((4,-4), "B", font=fnt, + fill=(255,255,255,255)) + elif icon_name == "home": + draw_icon.rectangle([0,0,32,32], fill="red", outline="black") + if fnt is not None: + draw_icon.text((4,-4), "D", font=fnt, + fill=(255,255,255,255)) + else: + icon = None + #rotate icon 180 degrees + icon = icon.rotate(180-self.angle, expand=False) + return icon + + def initialise_map(self, roomba_size): + ''' + Initialize all map items (base maps, overlay, icons fonts etc) + ''' + # get base image of Roomba path + if self.base is None: + try: + self.log.info("MAP: openening existing line image") + self.base = Image.open( + self.mapPath + '/' + self.roombaName + 'lines.png')\ + .convert('RGBA') + if self.base.size != (self.mapSize[0], self.mapSize[1]): + raise IOError("Image is wrong size") + except IOError as e: + self.base = Image.new( + 'RGBA', + (self.mapSize[0], self.mapSize[1]), self.transparent) + self.log.warn("MAP: line image problem: %s: created new image" + % e) + + try: + self.log.info("MAP: openening existing problems image") + self.roomba_problem = Image.open( + self.mapPath + '/'+self.roombaName + 'problems.png')\ + .convert('RGBA') + if self.roomba_problem.size != self.base.size: + raise IOError("Image is wrong size") + except IOError as e: + self.roomba_problem = Image.new( + 'RGBA', self.base.size, self.transparent) + self.log.warn("MAP: problems image problem: %s: created new " + "image" % e) + + try: + self.log.info("MAP: openening existing map no text image") + self.previous_map_no_text = None + self.map_no_text = Image.open( + self.mapPath + '/' + self.roombaName + 'map_notext.png')\ + .convert('RGBA') + if self.map_no_text.size != self.base.size: + raise IOError("Image is wrong size") + except IOError as e: + self.map_no_text = None + self.log.warn("MAP: map no text image problem: %s: set to None" + % e) + # save x and y center of image, for centering of final map image + self.cx = self.base.size[0] + self.cy = self.base.size[1] + + # get a font + if self.fnt is None: + try: + self.fnt = ImageFont.truetype('FreeMono.ttf', 40) + except IOError as e: + self.log.warn("error loading font: %s, loading default font" + % e) + self.fnt = ImageFont.load_default() + + #set dock home position + if self.home_pos is None: + self.home_pos = ( + self.mapSize[0] // 2 + self.mapSize[2], + self.mapSize[1] // 2 + self.mapSize[3]) + self.log.info("MAP: home_pos: (%d,%d)" + % (self.home_pos[0], self.home_pos[1])) + + #get icons + if self.roomba_icon is None: + self.roomba_icon = self.load_icon( + filename=self.roomba_icon_file, icon_name="roomba", + fnt=self.fnt, size=roomba_size, base_icon=None) + + if self.roomba_error_icon is None: + self.roomba_error_icon = self.load_icon( + filename=self.roomba_error_file, icon_name="stuck", + fnt=self.fnt, size=roomba_size, base_icon=self.roomba_icon) + + if self.roomba_cancelled_icon is None: + self.roomba_cancelled_icon = self.load_icon( + filename=self.roomba_cancelled_file, icon_name="cancelled", + fnt=self.fnt, size=roomba_size, base_icon=self.roomba_icon) + + if self.roomba_battery_icon is None: + self.roomba_battery_icon = self.load_icon( + filename=self.roomba_battery_file, icon_name="battery", + fnt=self.fnt, size=roomba_size, base_icon=self.roomba_icon) + + if self.dock_icon is None and self.home_icon_file is not None: + self.dock_icon = self.load_icon( + filename=self.home_icon_file, icon_name="home", fnt=self.fnt) + self.dock_position = ( + self.home_pos[0] - self.dock_icon.size[0] // 2, + self.home_pos[1] - self.dock_icon.size[1] // 2) + + if self.bin_full_icon is None: + self.bin_full_icon = self.load_icon( + filename=self.bin_full_file, icon_name="bin full", + fnt=self.fnt, size=roomba_size, base_icon=self.roomba_icon) + + self.log.info("MAP: Initialisation complete") + + def transparent_paste(self, base_image, icon, position): + ''' + needed because PIL pasting of transparent imges gives weird results + ''' + image = Image.new('RGBA', self.base.size, self.transparent) + image.paste(icon,position) + base_image = Image.alpha_composite(base_image, image) + return base_image + + def zero_coords(self): + ''' + returns dictionary with default zero coords + ''' + return {"x": 0, "y": 0, "theta": 180} + + def offset_coordinates(self, old_co_ords, new_co_ords): + ''' + offset coordinates according to mapSize settings, with 0,0 as center + ''' + x_y = (new_co_ords["x"] + self.mapSize[0] // 2 + self.mapSize[2], + new_co_ords["y"] + self.mapSize[1] // 2 + self.mapSize[3]) + old_x_y = (old_co_ords["x"]+self.mapSize[0] // 2 + self.mapSize[2], + old_co_ords["y"]+self.mapSize[1]//2+self.mapSize[3]) + + theta = int(new_co_ords["theta"] - 90 + self.roomba_angle) + while theta > 359: theta = 360 - theta + while theta < 0: theta = 360 + theta + + return old_x_y, x_y, theta + + def get_roomba_pos(self, x_y): + ''' + calculate roomba position as list + ''' + return [x_y[0] - self.roomba_icon.size[0] // 2, + x_y[1] - self.roomba_icon.size[1] // 2, + x_y[0] + self.roomba_icon.size[0] // 2, + x_y[1] + self.roomba_icon.size[1] // 2] + + def draw_vacuum_lines(self, image, old_x_y, x_y, theta, colour="lawngreen"): + ''' + draw lines on image from old_x_y to x_y reepresenting vacuum coverage, + taking into account angle theta (roomba angle). + ''' + lines = ImageDraw.Draw(image) + if x_y != old_x_y: + self.log.info("MAP: drawing line: %s, %s" % (old_x_y, x_y)) + lines.line([old_x_y, x_y], fill=colour, + width=self.roomba_icon.size[0] // 2) + #draw circle over roomba vacuum area to give smooth edges. + arcbox = [x_y[0]-self.roomba_icon.size[0] // 4, + x_y[1]-self.roomba_icon.size[0] // 4, + x_y[0]+self.roomba_icon.size[0] // 4, + x_y[1]+self.roomba_icon.size[0] // 4] + lines.ellipse(arcbox, fill=colour) + + def draw_text(self, image, display_text, fnt, pos=(0,0), + colour=(0,0,255,255), rotate=False): + #draw text - (WARNING old versions of PIL have huge memory leak here!) + if display_text is None: return + self.log.info("MAP: writing text: pos: %s, text: %s" + % (pos, display_text)) + if rotate: + txt = Image.new('RGBA', (fnt.getsize(display_text)), + self.transparent) + text = ImageDraw.Draw(txt) + # draw text rotated 180 degrees... + text.text((0,0), display_text, font=fnt, fill=colour) + image.paste(txt.rotate(180-self.angle, expand=True), pos) + else: + text = ImageDraw.Draw(image) + text.text(pos, display_text, font=fnt, fill=colour) + + def draw_map(self, force_redraw=False): + ''' + Draw map of Roomba cleaning progress + ''' + if ((self.co_ords != self.previous_co_ords or + self.cleanMissionStatus_phase != + self.previous_cleanMissionStatus_phase) + or force_redraw) and self.drawmap: + self.render_map(self.co_ords, self.previous_co_ords) + self.previous_co_ords = self.co_ords.copy() + self.previous_cleanMissionStatus_phase = \ + self.cleanMissionStatus_phase + + def render_map(self, new_co_ords, old_co_ords): + ''' + draw map + ''' + draw_final = False + stuck = False + cancelled = False + bin_full = False + battery_low = False + + # program just started, and we don't have phase yet. + if self.current_state is None: + return + + if self.show_final_map == False: + self.log.info("MAP: received: new_co_ords: %s old_co_ords: %s " + "phase: %s, state: %s" % ( + new_co_ords, old_co_ords, + self.cleanMissionStatus_phase, self.current_state)) + + if self.current_state == self.states["charge"]: + self.log.info("MAP: ignoring new co-ords in charge phase") + new_co_ords = old_co_ords = self.zero_coords() + self.display_text = "Charging: Battery: " + \ + str(self.master_state["state"]["reported"]["batPct"]) + "%" + if self.bin_full: + self.display_text = "Bin Full," + \ + self.display_text.replace("Charging", "Not Ready") + if (self.last_completed_time is None or time.time() - + self.last_completed_time > 3600): + self.save_text_and_map_on_whitebg(self.map_no_text) + draw_final = True + + elif self.current_state == self.states["recharge"]: + self.log.info("MAP: ignoring new co-ords in recharge phase") + new_co_ords = old_co_ords = self.zero_coords() + self.display_text = "Recharging:" + " Time: " + \ + str(self.master_state["state"]["reported"]["cleanMissionStatus"]["rechrgM"]) + "m" + if self.bin_full: + self.display_text = "Bin Full," + self.display_text + self.save_text_and_map_on_whitebg(self.map_no_text) + + elif self.current_state == self.states["pause"]: + self.log.info("MAP: ignoring new co-ords in pause phase") + new_co_ords = old_co_ords + self.display_text = "Paused: " + \ + str(self.master_state["state"]["reported"]["cleanMissionStatus"]["mssnM"]) + \ + "m, Bat: "+ str(self.master_state["state"]["reported"]["batPct"]) + \ + "%" + if self.bin_full: + self.display_text = "Bin Full," + self.display_text + # assume roomba is docked... + new_co_ords = old_co_ords = self.zero_coords() + self.save_text_and_map_on_whitebg(self.map_no_text) + + elif self.current_state == self.states["hmPostMsn"]: + self.display_text = "Completed: " + \ + time.strftime("%a %b %d %H:%M:%S") + self.log.info("MAP: end of mission") + + elif self.current_state == self.states["dockend"]: + self.log.info("MAP: mission completed: ignoring new co-ords in " + "docking phase") + new_co_ords = old_co_ords = self.zero_coords() + self.draw_final_map(True) + draw_final = True + + elif (self.current_state == self.states["run"] or + self.current_state == self.states["stop"] or + self.current_state == self.states["pause"]): + if self.current_state == self.states["run"]: + self.display_text = self.states["run"] + " Time: " + \ + str(self.master_state["state"]["reported"]["cleanMissionStatus"]["mssnM"]) + \ + "m, Bat: "+ str(self.master_state["state"]["reported"]["batPct"]) + \ + "%" + else: + self.display_text = None + self.show_final_map = False + + elif self.current_state == self.states["new"]: + self.angle = self.mapSize[4] #reset angle + self.base = Image.new('RGBA', self.base.size, self.transparent) + # overlay for roomba problem position + self.roomba_problem = Image.new('RGBA', self.base.size, + self.transparent) + self.show_final_map = False + self.display_text = None + self.log.info("MAP: created new image at start of new run") + + elif self.current_state == self.states["stuck"]: + self.display_text = "STUCK!: " + time.strftime("%a %b %d %H:%M:%S") + self.draw_final_map(True) + draw_final = True + stuck = True + + elif self.current_state == self.states["cancelled"]: + self.display_text = "Cancelled: " + \ + time.strftime("%a %b %d %H:%M:%S") + cancelled = True + + elif self.current_state == self.states["dock"]: + self.display_text = "Docking" + if self.bin_full: + self.display_text = "Bin Full," + self.display_text + bin_full = True + else: + self.display_text = "Battery low: " + \ + str(self.master_state["state"]["reported"]["batPct"]) + \ + "%, " + self.display_text + battery_low = True + + else: + self.log.warn("MAP: no special handling for state: %s" + % self.current_state) + + if self.base is None: + self.log.warn("MAP: no image, exiting...") + return + + if self.display_text is None: + self.display_text = self.current_state + + if self.show_final_map: #just display final map - not live + self.log.debug("MAP: not updating map - Roomba not running") + return + + if self.debug: + # debug final map (careful, uses a lot of CPU power!) + self.draw_final_map() + + #calculate co-ordinates, with 0,0 as center + old_x_y, x_y, theta = self.offset_coordinates(old_co_ords, new_co_ords) + roomba_pos = self.get_roomba_pos(x_y) + + self.log.info("MAP: old x,y: %s new x,y: %s theta: %s roomba pos: %s" % + (old_x_y, x_y, theta, roomba_pos)) + + #draw lines + self.draw_vacuum_lines(self.base, old_x_y, x_y, theta) + + # make a blank image for the text and Roomba overlay, initialized to + # transparent text color + roomba_sprite = Image.new('RGBA', self.base.size, self.transparent) + + #draw roomba + self.log.info("MAP: drawing roomba: pos: %s, theta: %s" + % (roomba_pos, theta)) + if stuck: + self.log.info("MAP: Drawing stuck Roomba") + self.roomba_problem.paste(self.roomba_error_icon,roomba_pos) + if cancelled: + self.log.info("MAP: Drawing cancelled Roomba") + self.roomba_problem.paste(self.roomba_cancelled_icon,roomba_pos) + if bin_full: + self.log.info("MAP: Drawing full bin") + self.roomba_problem.paste(self.bin_full_icon,roomba_pos) + if battery_low: + self.log.info("MAP: Drawing low battery Roomba") + self.roomba_problem.paste(self.roomba_battery_icon,roomba_pos) + + roomba_sprite = self.transparent_paste( + roomba_sprite, + self.roomba_icon.rotate(theta, expand=False), roomba_pos) + + # paste dock over roomba_sprite + if self.dock_icon is not None: + roomba_sprite = self.transparent_paste( + roomba_sprite, self.dock_icon, self.dock_position) + + # save base lines + self.base.save(self.mapPath + '/' + self.roombaName + 'lines.png', + "PNG") + # save problem overlay + self.roomba_problem.save(self.mapPath + '/' + self.roombaName + \ + 'problems.png', "PNG") + if self.roomOutline or self.auto_rotate: + # draw room outline (saving results if this is a final map) update + # x,y and angle if auto_rotate + self.draw_room_outline(draw_final) + # merge room outline into base + if self.roomOutline: + #if we want to draw the room outline + out = Image.alpha_composite(self.base, self.room_outline) + else: + out = self.base + #merge roomba lines (trail) with base + out = Image.alpha_composite(out, roomba_sprite) + #merge problem location for roomba into out + out = Image.alpha_composite(out, self.roomba_problem) + if draw_final and self.auto_rotate: + #translate image to center it if auto_rotate is on + self.log.info("MAP: calculation of center: (%d,%d), " + "translating final map to center it, x:%d, y:%d " + "deg: %.2f" % ( + self.cx, self.cy, self.cx - out.size[0] // 2, + self.cy - out.size[1] // 2, + self.angle)) + out = out.transform( + out.size, Image.AFFINE, + (1, 0, self.cx-out.size[0] // 2, + 0, 1, self.cy-out.size[1] // 2)) + # map is upside down, so rotate 180 degrees, and size to fit (NW 12/4/2018 fixed bug causing distorted maps when rotation is not 0) + #out_rotated = out.rotate(180 + self.angle, expand=True).resize(self.base.size) #old version + out_rotated = out.rotate(180, expand=False) + # save composite image + self.save_text_and_map_on_whitebg(out_rotated) + if draw_final: + self.show_final_map = True # prevent re-drawing of map until reset + + def save_text_and_map_on_whitebg(self, map): + # if no map or nothing changed + if map is None or (map == self.previous_map_no_text and + self.previous_display_text == self.display_text): + return + self.map_no_text = map + self.previous_map_no_text = self.map_no_text + self.previous_display_text = self.display_text + self.map_no_text.save(self.mapPath + '/' + self.roombaName + + 'map_notext.png', "PNG") + final = Image.new('RGBA', self.base.size, (255,255,255,255)) # white + # paste onto a white background, so it's easy to see + final = Image.alpha_composite(final, map) + final = final.rotate(self.angle, expand=True) #(NW 12/4/2018 fixed bug causing distorted maps when rotation is not 0 - moved rotate to here) + # draw text + self.draw_text(final, self.display_text, self.fnt) + final.save(self.mapPath + '/'+self.roombaName + '_map.png', "PNG") + # try to avoid other programs reading file while writing it, + # rename should be atomic. + os.rename(self.mapPath + '/' + self.roombaName + '_map.png', + self.mapPath + '/' + self.roombaName + 'map.png') + + def ScaleRotateTranslate(self, image, angle, center=None, new_center=None, + scale=None, expand=False): + ''' + experimental - not used yet + ''' + if center is None: + return image.rotate(angle, expand) + angle = -angle / 180.0 * math.pi + nx, ny = x, y = center + if new_center != center: + (nx, ny) = new_center + sx = sy = 1.0 + if scale: + (sx, sy) = scale + cosine = math.cos(angle) + sine = math.sin(angle) + a = cosine / sx + b = sine / sx + c = x - nx * a - ny * b + d = -sine / sy + e = cosine / sy + f = y - nx * d - ny * e + return image.transform(image.size, Image.AFFINE, + (a,b,c,d,e,f), resample=Image.BICUBIC) + + def match_outlines(self, orig_image, skewed_image): + orig_image = np.array(orig_image) + skewed_image = np.array(skewed_image) + try: + surf = cv2.xfeatures2d.SURF_create(400) + except Exception: + surf = cv2.SIFT(400) + kp1, des1 = surf.detectAndCompute(orig_image, None) + kp2, des2 = surf.detectAndCompute(skewed_image, None) + + FLANN_INDEX_KDTREE = 0 + index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5) + search_params = dict(checks=50) + flann = cv2.FlannBasedMatcher(index_params, search_params) + matches = flann.knnMatch(des1, des2, k=2) + + # store all the good matches as per Lowe's ratio test. + good = [] + for m, n in matches: + if m.distance < 0.7 * n.distance: + good.append(m) + + MIN_MATCH_COUNT = 10 + if len(good) > MIN_MATCH_COUNT: + src_pts = np.float32([kp1[m.queryIdx].pt for m in good + ]).reshape(-1, 1, 2) + dst_pts = np.float32([kp2[m.trainIdx].pt for m in good + ]).reshape(-1, 1, 2) + + M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) + + # see https://ch.mathworks.com/help/images/examples/find-image-rotation-and-scale-using-automated-feature-matching.html for details + ss = M[0, 1] + sc = M[0, 0] + scaleRecovered = math.sqrt(ss * ss + sc * sc) + thetaRecovered = math.atan2(ss, sc) * 180 / math.pi + self.log.info("MAP: Calculated scale difference: %.2f, " + "Calculated rotation difference: %.2f" % + (scaleRecovered, thetaRecovered)) + + #deskew image + im_out = cv2.warpPerspective(skewed_image, np.linalg.inv(M), + (orig_image.shape[1], orig_image.shape[0])) + return im_out + + else: + self.log.warn("MAP: Not enough matches are found - %d/%d" + % (len(good), MIN_MATCH_COUNT)) + return skewed_image + + def draw_room_outline(self, overwrite=False, colour=(64,64,64,255), + width=1): + ''' + draw room outline + ''' + self.log.info("MAP: checking room outline") + if HAVE_CV2: + if self.room_outline_contour is None or overwrite: + try: + self.room_outline_contour = np.load( + self.mapPath + '/' + self.roombaName + 'room.npy') + except IOError as e: + self.log.warn("Unable to load room outline: %s, setting " + "to 0" % e) + self.room_outline_contour = np.array( + [(0,0),(0,0),(0,0),(0,0)], dtype=np.int) + + try: + self.log.info("MAP: openening existing room outline image") + self.room_outline = Image.open( + self.mapPath + '/' + self.roombaName + 'room.png').\ + convert('RGBA') + if self.room_outline.size != self.base.size: + raise IOError("Image is wrong size") + except IOError as e: + self.room_outline = Image.new( + 'RGBA', self.base.size, self.transparent) + self.log.warn("MAP: room outline image problem: %s: " + "set to New" % e) + + room_outline_area = cv2.contourArea(self.room_outline_contour) + # edgedata = cv2.add( + # np.array(self.base.convert('L'), dtype=np.uint8), + # np.array(self.room_outline.convert('L'), dtype=np.uint8)) + edgedata = np.array(self.base.convert('L')) + # find external contour + _, contours, _ = self.findContours( + edgedata,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) + if contours[0] is None: return + if len(contours[0]) < 5: return + max_area = cv2.contourArea(contours[0]) + # experimental shape matching + # note cv2.cv.CV_CONTOURS_MATCH_I1 does not exist in CV 3.0, + # so just use 1 + match = cv2.matchShapes( + self.room_outline_contour,contours[0],1,0.0) + self.log.info("MAP: perimeter/outline match is: %.4f" % match) + # if match is less than 0.35 - shapes are similar (but if it's 0 - + # then they are the same shape..) try auto rotating map to fit. + if match < 0.35 and match > 0: + #self.match_outlines(self.room_outline, self.base) + pass + if max_area > room_outline_area: + self.log.info("MAP: found new outline perimiter") + self.room_outline_contour = contours[0] + perimeter = cv2.arcLength(self.room_outline_contour,True) + outline = Image.new('RGBA',self.base.size,self.transparent) + edgeimage = np.array(outline) # make blank RGBA image array + # self.draw_edges is the max deviation from a line (set to 0.3%) + # you can fiddle with this + approx = cv2.approxPolyDP( + self.room_outline_contour, + self.draw_edges * perimeter, + True) + # outline with grey, width 1 + cv2.drawContours(edgeimage,[approx] , -1, colour, width) + self.room_outline = Image.fromarray(edgeimage) + + else: + if self.room_outline is None or overwrite: + try: + self.log.info("MAP: openening existing room outline image") + self.room_outline = Image.open( + self.mapPath + '/' + self.roombaName + 'room.png').\ + convert('RGBA') + if self.room_outline.size != self.base.size: + raise IOError("Image is wrong size") + except IOError as e: + self.room_outline = Image.new( + 'RGBA', self.base.size, self.transparent) + self.log.warn("MAP: room outline image problem: %s: " + "set to New" % e) + edges = ImageOps.invert(self.room_outline.convert('L')) + edges.paste(self.base) + edges = edges.convert('L').filter(ImageFilter.SMOOTH_MORE) + edges = ImageOps.invert(edges.filter(ImageFilter.FIND_EDGES)) + self.room_outline = self.make_transparent(edges, (0, 0, 0, 255)) + + if overwrite or self.debug: + # save room outline + self.room_outline.save( + self.mapPath+'/'+self.roombaName+'room.png', "PNG") + if HAVE_CV2: + # save room outline contour as numpy array + np.save(self.mapPath + '/' + self.roombaName + 'room.npy', + self.room_outline_contour) + if self.auto_rotate: + # update outline centre + self.get_image_parameters( + image=self.room_outline, contour=self.room_outline_contour, + final=overwrite) + self.log.info("MAP: calculation of center: (%d,%d), " + "translating room outline to center it, " + "x:%d, y:%d deg: %.2f" % ( + self.cx, self.cy, + self.cx - self.base.size[0] // 2, + self.cy - self.base.size[1] // 2, + self.angle)) + # center room outline, same as map. + self.room_outline = self.room_outline.transform( + self.base.size, Image.AFFINE, + (1, 0, self.cx - self.base.size[0] // 2, + 0, 1, self.cy-self.base.size[1]//2)) + self.log.info("MAP: Wrote new room outline files") + + def PIL_get_image_parameters(self, image=None, start=90, end = 0, step=-1, + recursion=0): + ''' + updates angle of image, and centre using PIL. + NOTE: this assumes the floorplan is rectangular! if you live in a + lighthouse, the angle will not be valid! + input is PIL image + ''' + if image is not None and HAVE_PIL: + imbw = image.convert('L') + max_area = self.base.size[0] * self.base.size[1] + x_y = (self.base.size[0] // 2, self.base.size[1] // 2) + angle = self.angle + div_by_10 = False + if step >=10 or step <=-10: + step /= 10 + div_by_10 = True + for try_angle in range(start, end, step): + if div_by_10: + try_angle /= 10.0 + #rotate image and resize to fit + im = imbw.rotate(try_angle, expand=True) + box = im.getbbox() + if box is not None: + area = (box[2]-box[0]) * (box[3]-box[1]) + if area < max_area: + angle = try_angle + x_y = ((box[2] - box[0]) // 2 + box[0], + (box[3] - box[1]) // 2 + box[1]) + max_area = area + + if recursion >= 1: + return x_y, angle + + x_y, angle = self.PIL_get_image_parameters( + image, + (angle + 1) * 10, + (angle - 1) * 10, -10, + recursion + 1) + + # self.log.info("MAP: PIL: image center: " + # "x:%d, y:%d, angle %.2f" % (x_y[0], x_y[1], angle)) + return x_y, angle + + def get_image_parameters(self, image=None, contour=None, final=False): + ''' + updates angle of image, and centre using cv2 or PIL. + NOTE: this assumes the floorplan is rectangular! if you live in a + lighthouse, the angle will not be valid! + input is cv2 contour or PIL image + routines find the minnimum area rectangle that fits the image outline + ''' + if contour is not None and HAVE_CV2: + # find minnimum area rectangle that fits + # returns (x,y), (width, height), theta - where (x,y) is the center + x_y,l_w,angle = cv2.minAreaRect(contour) + + elif image is not None and HAVE_PIL: + x_y, angle = self.PIL_get_image_parameters(image) + + else: + return + + if angle < self.angle - 45: + angle += 90 + if angle > 45-self.angle: + angle -= 90 + + if final: + self.cx = x_y[0] + self.cy = x_y[1] + self.angle = angle + self.log.info("MAP: image center: x:%d, y:%d, angle %.2f" % + (x_y[0], x_y[1], angle)) + + def angle_between(self, p1, p2): + ''' + clockwise angle between two points in degrees + ''' + if HAVE_CV2: + ang1 = np.arctan2(*p1[::-1]) + ang2 = np.arctan2(*p2[::-1]) + return np.rad2deg((ang1 - ang2) % (2 * np.pi)) + else: + side1=math.sqrt(((p1[0] - p2[0]) ** 2)) + side2=math.sqrt(((p1[1] - p2[1]) ** 2)) + return math.degrees(math.atan(side2/side1)) + + def findContours(self,image,mode,method): + ''' + Version independent find contours routine. Works with OpenCV 2 or 3. + Returns modified image (with contours applied), contours list, hierarchy + ''' + ver = int(cv2.__version__.split(".")[0]) + im = image.copy() + if ver == 2: + contours, hierarchy = cv2.findContours(im,mode,method) + return im, contours, hierarchy + else: + im_cont, contours, hierarchy = cv2.findContours(im,mode,method) + return im_cont, contours, hierarchy + + def draw_final_map(self, overwrite=False): + ''' + draw map with outlines at end of mission. Called when mission has + finished and Roomba has docked + ''' + merge = Image.new('RGBA',self.base.size,self.transparent) + if HAVE_CV2: + # NOTE: this is CPU intensive! + edgedata = np.array(self.base.convert('L'), dtype=np.uint8) + # find all contours + _, contours, _ = self.findContours( + edgedata,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) + # zero edge data for later use + edgedata.fill(0) + max_perimeter = 0 + max_contour = None + for cnt in contours: + perimeter = cv2.arcLength(cnt,True) + if perimeter >= max_perimeter: + max_contour = cnt # get the contour with maximum length + max_perimeter = perimeter + if max_contour is None: return + if len(max_contour) < 5: return + try: + contours.remove(max_contour) # remove max contour from list + except ValueError: + self.log.warn("MAP: unable to remove contour") + pass + + mask = np.full(edgedata.shape, 255, dtype=np.uint8) # white + # create mask (of other contours) in black + cv2.drawContours(mask,contours, -1, 0, -1) + + # self.draw_edges is the max deviation from a line + # you can fiddle with this in enable_map + approx = cv2.approxPolyDP(max_contour, + self.draw_edges * max_perimeter,True) + + bgimage = np.array(merge) # make blank RGBA image array + # draw contour and fill with "lawngreen" + cv2.drawContours(bgimage,[approx] , -1, (124, 252, 0, 255), -1) + # mask image with internal contours + bgimage = cv2.bitwise_and(bgimage,bgimage,mask = mask) + # not dure if you really need this - uncomment if you want the + # area outlined. + # draw longest contour aproximated to lines (in black), width 1 + cv2.drawContours(edgedata,[approx] , -1, (255), 1) + + outline = Image.fromarray(edgedata) # outline + base = Image.fromarray(bgimage) # filled background image + else: + base = self.base.filter(ImageFilter.SMOOTH_MORE) + # draw edges at end of mission + outline = base.convert('L').filter(ImageFilter.FIND_EDGES) + # outline = ImageChops.subtract( + # base.convert('L').filter(ImageFilter.EDGE_ENHANCE), + # base.convert('L')) + + edges = ImageOps.invert(outline) + edges = self.make_transparent(edges, (0, 0, 0, 255)) + if self.debug: + edges.save(self.mapPath+'/'+self.roombaName+'edges.png', "PNG") + merge = Image.alpha_composite(merge,base) + merge = Image.alpha_composite(merge,edges) + if overwrite: + self.log.info("MAP: Drawing final map") + self.last_completed_time = time.time() + self.base=merge + + if self.debug: + merge_rotated = merge.rotate(180+self.angle, expand=True) + merge_rotated.save( + self.mapPath+'/'+self.roombaName+'final_map.png', "PNG") diff --git a/roomba_980/roomba/roomba_direct.py b/roomba_980/roomba/roomba_direct.py new file mode 100755 index 000000000..8e6aef6ab --- /dev/null +++ b/roomba_980/roomba/roomba_direct.py @@ -0,0 +1,599 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from __future__ import print_function +from ast import literal_eval +from logging.handlers import RotatingFileHandler +import sys +if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] < 5): #added for python 2.7 and < 3.4 fix NW 15/9/2017 + import roomba + try: + from roomba import Password + except ImportError: + from password import Password +else: + from roomba import roomba + try: + from roomba.password import Password + except ImportError: + from password import Password +import argparse +import json +import logging +import os +import six +import socket +import time +# Import trickery +global HAVE_CV2 +global HAVE_MQTT +global HAVE_PIL +HAVE_CV2 = HAVE_MQTT = HAVE_PIL = False #fix for if neither PIL or OPENCV is installed (RPI versions) NW 3/2/2018 +try: + import configparser +except: + from six.moves import configparser +try: + import paho.mqtt.client as mqtt + HAVE_MQTT = True +except ImportError: + print("paho mqtt client not found") +try: + import cv2 + HAVE_CV2 = True +except ImportError: + print("CV or numpy module not found, falling back to PIL") + +# NOTE: MUST use Pillow Pillow 4.1.1 to avoid some horrible memory leaks in the +# text handling! +try: + from PIL import Image + HAVE_PIL = True +except ImportError: + print("PIL module not found, maps are disabled") + +def parse_args(): + default_icon_path = os.path.join(os.path.dirname(__file__), 'res') + #-------- Command Line ----------------- + parser = argparse.ArgumentParser( + description='Forward MQTT data from Roomba 980 to local MQTT broker') + parser.add_argument( + '-f', '--configfile', + action='store', + type=str, + default="./config.ini", + help='config file name (default: ./config.ini)') + parser.add_argument( + '-n', '--roombaName', + action='store', + type=str, + default="", help='optional Roomba name (default: "")') + parser.add_argument( + '-t', '--topic', + action='store', + type=str, + default="#", + help='Roomba MQTT Topic to subscribe to (can use wildcards # and ' + '+ default: #)') + parser.add_argument( + '-T', '--brokerFeedback', + action='store', + type=str, + default="/roomba/feedback", + help='Topic on broker to publish feedback to (default: ' + '/roomba/feedback)') + parser.add_argument( + '-C', '--brokerCommand', + action='store', + type=str, + default="/roomba/command", + help='Topic on broker to publish commands to (default: ' + '/roomba/command)') + parser.add_argument( + '-S', '--brokerSetting', + action='store', + type=str, + default="/roomba/setting", + help='Topic on broker to publish settings to (default: ' + '/roomba/setting)') + parser.add_argument( + '-b', '--broker', + action='store', + type=str, + default=None, + help='ipaddress of MQTT broker (default: None)') + parser.add_argument( + '-p', '--port', + action='store', + type=int, + default=1883, + help='MQTT broker port number (default: 1883)') + parser.add_argument( + '-U', '--user', + action='store', + type=str, + default=None, + help='MQTT broker user name (default: None)') + parser.add_argument( + '-P', '--password', + action='store', + type=str, + default=None, + help='MQTT broker password (default: None)') + parser.add_argument( + '-R', '--roombaIP', + action='store', + type=str, + default=None, + help='ipaddress of Roomba 980 (default: None)') + parser.add_argument( + '-u', '--blid', + action='store', + type=str, + default=None, + help='Roomba 980 blid (default: None)') + parser.add_argument( + '-w', '--roombaPassword', + action='store', + type=str, + default=None, + help='Roomba 980 password (default: None)') + parser.add_argument( + '-i', '--indent', + action='store', + type=int, + default=0, + help='Default indentation=auto') + parser.add_argument( + '-l', '--log', + action='store', + type=str, + default="./Roomba.log", + help='path/name of log file (default: ./Roomba.log)') + parser.add_argument( + '-e', '--echo', + action='store_false', + default = True, + help='Echo to Console (default: True)') + parser.add_argument( + '-D', '--debug', + action='store_true', + default = False, + help='debug mode') + parser.add_argument( + '-r', '--raw', + action='store_true', + default = False, + help='Output raw data to mqtt, no decoding of json data') + parser.add_argument( + '-j', '--pretty_print', + action='store_true', + default = False, + help='pretty print json in logs') + parser.add_argument( + '-c','--continuous', + action='store_false', + default = True, + help='Continuous connection to Roomba (default: True)') + parser.add_argument( + '-d', '--delay', + action='store', + type=int, + default=1000, + help='Disconnect period for non-continuous connection (default: ' + '1000ms)') + parser.add_argument( + '-m', '--drawmap', + action='store_false', + default = True, + help='Draw Roomba cleaning map (default: True)') + parser.add_argument( + '-M', '--mapPath', + action='store', + type=str, + default=".", + help='Location to store maps to (default: .)') + parser.add_argument( + '-s', '--mapSize', + action='store', + type=str, + default="(800,1500,0,0,0,0)", + help='Map Size, Dock offset and skew for the map. (800,1500) is the ' + 'size, (0,0) is the dock location, in the center of the map, 0 ' + 'is the rotation of the map, 0 is the rotation of the roomba. ' + 'Use single quotes around the string. (default: ' + '"(800,1500,0,0,0,0)")') + parser.add_argument( + '-I', '--iconPath', + action='store', + type=str, + default=default_icon_path, + help='location of icons. (default: "./")') + parser.add_argument( + '-o', '--roomOutline', + action='store_false', + default = True, + help='Draw room outline (default: True)') + parser.add_argument( + '-x', '--exclude', + action='store',type=str, default="", help='Exclude topics that have this in them (default: "")') + parser.add_argument( + '--cert', + action='store', + type=str, + default='/etc/ssl/certs/ca-certificates.crt', + help='Set the certificate to use for MQTT communication with the Roomba') + parser.add_argument( + '--version', + action='version', + version="%(prog)s ({})".format(roomba.__version__), + help='Display version of this program') + return parser.parse_args() + +def main(): + + #----------- Local Routines ------------ + + def broker_on_connect(client, userdata, flags, rc): + log.debug("Broker Connected with result code " + str(rc)) + #subscribe to roomba feedback, if there is more than one roomba, the + # roombaName is added to the topic to subscribe to + if rc == 0: + if brokerCommand != "": + if len(roombas) == 1: + mqttc.subscribe(brokerCommand) + else: + for myroomba in roomba_list: + mqttc.subscribe( + brokerCommand + "/" + myroomba.roombaName) + if brokerSetting != "": + if len(roombas) == 1: + mqttc.subscribe(brokerSetting) + else: + for myroomba in roomba_list: + mqttc.subscribe( + brokerSetting + "/" + myroomba.roombaName) + + def broker_on_message(mosq, obj, msg): + # publish to roomba, if there is more than one roomba, the roombaName + # is added to the topic to publish to + msg.payload = msg.payload.decode("utf-8") + if "command" in msg.topic: + log.info("Received COMMAND: %s" % str(msg.payload)) + if len(roombas) == 1: + roomba_list[0].send_command(str(msg.payload)) + else: + for myroomba in roomba_list: + if myroomba.roombaName in msg.topic: + myroomba.send_command(str(msg.payload)) + elif "setting" in msg.topic: + log.info("Received SETTING: %s" % str(msg.payload)) + cmd = str(msg.payload).split() + if len(roombas) == 1: + roomba_list[0].set_preference(cmd[0], cmd[1]) + else: + for myroomba in roomba_list: + if myroomba.roombaName in msg.topic: + myroomba.set_preference(cmd[0], cmd[1]) + else: + log.warn("Unknown topic: %s" % str(msg.topic)) + + def broker_on_publish(mosq, obj, mid): + pass + + def broker_on_subscribe(mosq, obj, mid, granted_qos): + log.debug("Broker Subscribed: %s %s" % (str(mid), str(granted_qos))) + + def broker_on_disconnect(mosq, obj, rc): + log.debug("Broker disconnected") + if rc == 0: + sys.exit(0) + + def broker_on_log(mosq, obj, level, string): + log.info(string) + + def read_config_file(file="./config.ini"): + #read config file + Config = configparser.ConfigParser() + try: + Config.read(file) + log.info("reading info from config file %s" % file) + roombas = {} + for address in Config.sections(): + roomba_data = literal_eval(Config.get(address, "data")) + roombas[address] = { + "blid": Config.get(address, "blid"), + "password": Config.get(address, "password"), + "roombaName": roomba_data.get("robotname", None)} + except Exception as e: + log.warn("Error reading config file %s" %e) + return roombas + + def create_html(myroomba,mapPath="."): + ''' + Create html files for live display of roomba maps - but only if they + don't already exist + ''' + #default css and html + css='''body { + background-color: white; + color: white; + margin: 0; + padding: 0; + } +img,video { + width: auto; + max-height:100%; + } +''' + html=''' + + + + + + + +''' + html +='Roomba Map Live' % myroomba.roombaName + html +=''' + + +''' + #python 3 workaround + try: + FileNotFoundError + except NameError: + #py2 + FileNotFoundError = PermissionError = IOError + + #check is style.css exists, if not create it + css_path = mapPath+"/style.css" + try: + fn = open(css_path , "r") #check if file exists (or is readable) + fn.close() + except (IOError,FileNotFoundError): + log.warn("CSS file not found, creating %s" % css_path) + try: + with open(css_path , "w") as fn: + fn.write(css) + except (IOError, PermissionError) as e: + log.error("unable to create file %s, error: %s" % css_path, e) + #check is html exists, if not create it + html_path = mapPath+"/"+ myroomba.roombaName + "roomba_map.html" + try: + fn = open(html_path, "r") #check if file exists (or is readable) + fn.close() + except (IOError,FileNotFoundError): + log.warn("html file not found, creating %s" % html_path) + try: + with open(html_path, "w") as fn: + fn.write(html) + make_executable(html_path) + except (IOError, PermissionError) as e: + log.error("unable to create file %s, error: %s" % html_path, e) + + def make_executable(path): + mode = os.stat(path).st_mode + mode |= (mode & 0o444) >> 2 # copy R bits to X + os.chmod(path, mode) + + def setup_logger(logger_name, log_file, level=logging.DEBUG, console=False): + try: + l = logging.getLogger(logger_name) + if logger_name ==__name__: + formatter = logging.Formatter( + '[%(levelname)1.1s %(asctime)s] %(message)s') + else: + formatter = logging.Formatter('%(message)s') + fileHandler = RotatingFileHandler( + log_file, mode='a', maxBytes=2000000, backupCount=5) + fileHandler.setFormatter(formatter) + if console == True: + streamHandler = logging.StreamHandler() + + l.setLevel(level) + l.addHandler(fileHandler) + if console == True: + streamHandler.setFormatter(formatter) + l.addHandler(streamHandler) + except IOError as e: + if e[0] == 13: #errno Permission denied + print("Error: %s: You probably don't have permission to " + "write to the log file/directory - try sudo" % e) + else: + print("Log Error: %s" % e) + sys.exit(1) + + #args = parse_args() #don't know what this is for - removed NW 3/2/2018 + arg = parse_args() + + if arg.debug: + log_level = logging.DEBUG + else: + log_level = logging.INFO + + #setup logging + setup_logger(__name__, arg.log,level=log_level,console=arg.echo) + + log = logging.getLogger(__name__) + + log.info("*******************") + log.info("* Program Started *") + log.info("*******************") + + log.info("Roomba.py Version: %s" % roomba.__version__) + + log.info("Python Version: %s" % sys.version.replace('\n','')) + + if HAVE_MQTT: + import paho.mqtt # bit of a kludge, just to get the version number + log.info("Paho MQTT Version: %s" % paho.mqtt.__version__) + if (sys.version_info.major == 2 and sys.version_info.minor == 7 and + sys.version_info.micro < 9 and + int(paho.mqtt.__version__.split(".")[0]) >= 1 and + int(paho.mqtt.__version__.split(".")[1]) > 2): + log.error("NOTE: if your python version is less than 2.7.9, " + "and Paho MQTT verion is not 1.2.3 or lower, this " + "program will NOT WORK") + log.error("Please use pip install paho-mqtt==1.2.3 to " + "downgrade paho-mqtt, or use a later version of python") + sys.exit(1) + + if HAVE_CV2: + log.info("CV Version: %s" % cv2.__version__) + + if HAVE_PIL: + import PIL #bit of a kludge, just to get the version number + log.info("PIL Version: %s" % PIL.__version__) + if int(PIL.__version__.split(".")[0]) < 4: + log.warn("WARNING: PIL version is %s, this is not the latest! " + "You can get bad memory leaks with old versions of PIL" + % Image.PILLOW_VERSION) + log.warn("run: 'pip install --upgrade pillow' to fix this") + + log.debug("-- DEBUG Mode ON -") + log.info(" to Exit") + log.info("Roomba 980 MQTT data Interface") + + roombas = {} + + if arg.blid is None or arg.roombaPassword is None: + roombas = read_config_file(arg.configfile) + if len(roombas) == 0: + log.warn("No roomba or config file defined, I will attempt to " + "discover Roombas, please put the Roomba on the dock " + "and follow the instructions:") + if arg.roombaIP is None: + Password(file=arg.configfile) + else: + Password(arg.roombaIP,file=arg.configfile) + roombas = read_config_file(arg.configfile) + if len(roombas) == 0: + log.error("No Roombas found! You must specify RoombaIP, blid " + "and roombaPassword to run this program, or have " + "a config file, use -h to show options.") + sys.exit(0) + else: + log.info("Success! %d Roombas Found!" % len(roombas)) + else: + roombas[arg.roombaIP] = { + "blid": arg.blid, + "password": arg.roombaPassword, + "roombaName": arg.roombaName} + + # set broker = "127.0.0.1" # mosquitto broker is running on localhost + mqttc = None + if arg.broker is not None: + brokerCommand = arg.brokerCommand + brokerSetting = arg.brokerSetting + + # connect to broker + mqttc = mqtt.Client() + # Assign event callbacks + mqttc.on_message = broker_on_message + mqttc.on_connect = broker_on_connect + mqttc.on_disconnect = broker_on_disconnect + mqttc.on_publish = broker_on_publish + mqttc.on_subscribe = broker_on_subscribe + # uncomment to enable logging + # mqttc.on_log = broker_on_log + + try: + if arg.user != None: + mqttc.username_pw_set(arg.user, arg.password) + log.info("connecting to broker") + # Ping MQTT broker every 60 seconds if no data is published + # from this script. + mqttc.connect(arg.broker, arg.port, 60) + + except socket.error: + log.error("Unable to connect to MQTT Broker") + mqttc = None + + roomba_list = [] + for addr, info in six.iteritems(roombas): + log.info("Creating Roomba object %s" % addr) + #NOTE: cert_name is a default certificate. change this if your + # certificates are in a different place. any valid certificate will + # do, it's not used but needs to be there to enable mqtt TLS encryption + # instansiate Roomba object + # minnimum required to connect on Linux Debian system + # myroomba = Roomba(address, blid, roombaPassword) + roomba_list.append( + roomba.Roomba(addr, blid=info["blid"], + password=info["password"], + topic=arg.topic, continuous=arg.continuous, + clean=False, + cert_name=arg.cert, + roombaName=info["roombaName"])) + + for myroomba in roomba_list: + log.info("connecting Roomba %s" % myroomba.address) + # auto create html files (if they don't exist) + create_html(myroomba,arg.mapPath) + # all these are optional, if you don't include them, the defaults + # will work just fine + if arg.exclude != "": + myroomba.exclude = arg.exclude + myroomba.set_options( + raw=arg.raw, indent=arg.indent, pretty_print=arg.pretty_print) + if not arg.continuous: + myroomba.delay = arg.delay//1000 + if arg.mapSize != "" and arg.mapPath != "": + # enable live maps, class default is no maps + myroomba.enable_map(enable=True, mapSize=arg.mapSize, + mapPath=arg.mapPath, iconPath=arg.iconPath, + roomOutline=arg.roomOutline) + if arg.broker is not None: + # if you want to publish Roomba data to your own mqtt broker + # (default is not to) if you have more than one roomba, and + # assign a roombaName, it is addded to this topic + # (ie brokerFeedback/roombaName) + myroomba.set_mqtt_client(mqttc, arg.brokerFeedback) + # finally connect to Roomba - (required!) + myroomba.connect() + + try: + if mqttc is not None: + mqttc.loop_forever() + else: + while True: + log.info("Roomba Data: %s" % + json.dumps(myroomba.master_state, indent=2)) + time.sleep(5) + + except (KeyboardInterrupt, SystemExit): + log.info("System exit Received - Exiting program") + mqttc.disconnect() + sys.exit(0) + + +if __name__ == '__main__': + main() From 25e6dcab532473d81d8581faa7f5096f2def0f20 Mon Sep 17 00:00:00 2001 From: Zapfen83 Date: Thu, 25 Oct 2018 11:18:59 +0200 Subject: [PATCH 339/705] =?UTF-8?q?=09gel=C3=B6scht:=20=20=20=20=20=20=20r?= =?UTF-8?q?oomba=5F980/examples/complicated.py=20=09gel=C3=B6scht:=20=20?= =?UTF-8?q?=20=20=20=20=20roomba=5F980/examples/example=5Fstart=5Froomba?= =?UTF-8?q?=20=09gel=C3=B6scht:=20=20=20=20=20=20=20roomba=5F980/examples/?= =?UTF-8?q?simple.py=20=09gel=C3=B6scht:=20=20=20=20=20=20=20roomba=5F980/?= =?UTF-8?q?roomba/=5F=5Finit=5F=5F.py=20=09gel=C3=B6scht:=20=20=20=20=20?= =?UTF-8?q?=20=20roomba=5F980/roomba/=5F=5Fmain=5F=5F.py=20=09gel=C3=B6sch?= =?UTF-8?q?t:=20=20=20=20=20=20=20roomba=5F980/roomba/config.ini=20=09gel?= =?UTF-8?q?=C3=B6scht:=20=20=20=20=20=20=20roomba=5F980/roomba/getpassword?= =?UTF-8?q?.py=20=09gel=C3=B6scht:=20=20=20=20=20=20=20roomba=5F980/roomba?= =?UTF-8?q?/password.py=20=09gel=C3=B6scht:=20=20=20=20=20=20=20roomba=5F9?= =?UTF-8?q?80/roomba/res/binfull.png=20=09gel=C3=B6scht:=20=20=20=20=20=20?= =?UTF-8?q?=20roomba=5F980/roomba/res/home.png=20=09gel=C3=B6scht:=20=20?= =?UTF-8?q?=20=20=20=20=20roomba=5F980/roomba/res/map.png=20=09gel=C3=B6sc?= =?UTF-8?q?ht:=20=20=20=20=20=20=20roomba=5F980/roomba/res/roomba-base.png?= =?UTF-8?q?=20=09gel=C3=B6scht:=20=20=20=20=20=20=20roomba=5F980/roomba/re?= =?UTF-8?q?s/roomba-charge.png=20=09gel=C3=B6scht:=20=20=20=20=20=20=20roo?= =?UTF-8?q?mba=5F980/roomba/res/roomba.png=20=09gel=C3=B6scht:=20=20=20=20?= =?UTF-8?q?=20=20=20roomba=5F980/roomba/res/roombacancelled.png=20=09gel?= =?UTF-8?q?=C3=B6scht:=20=20=20=20=20=20=20roomba=5F980/roomba/res/roombae?= =?UTF-8?q?rror.png=20=09gel=C3=B6scht:=20=20=20=20=20=20=20roomba=5F980/r?= =?UTF-8?q?oomba/roomba.py=20=09gel=C3=B6scht:=20=20=20=20=20=20=20roomba?= =?UTF-8?q?=5F980/roomba/roomba=5Fdirect.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- roomba_980/examples/complicated.py | 95 -- roomba_980/examples/example_start_roomba | 8 - roomba_980/examples/simple.py | 25 - roomba_980/roomba/__init__.py | 3 - roomba_980/roomba/__main__.py | 590 -------- roomba_980/roomba/config.ini | 24 - roomba_980/roomba/getpassword.py | 39 - roomba_980/roomba/password.py | 186 --- roomba_980/roomba/res/binfull.png | Bin 4806 -> 0 bytes roomba_980/roomba/res/home.png | Bin 1378 -> 0 bytes roomba_980/roomba/res/map.png | Bin 32050 -> 0 bytes roomba_980/roomba/res/roomba-base.png | Bin 1510 -> 0 bytes roomba_980/roomba/res/roomba-charge.png | Bin 1500 -> 0 bytes roomba_980/roomba/res/roomba.png | Bin 3668 -> 0 bytes roomba_980/roomba/res/roombacancelled.png | Bin 5149 -> 0 bytes roomba_980/roomba/res/roombaerror.png | Bin 1523 -> 0 bytes roomba_980/roomba/roomba.py | 1641 --------------------- roomba_980/roomba/roomba_direct.py | 599 -------- 18 files changed, 3210 deletions(-) delete mode 100644 roomba_980/examples/complicated.py delete mode 100644 roomba_980/examples/example_start_roomba delete mode 100644 roomba_980/examples/simple.py delete mode 100755 roomba_980/roomba/__init__.py delete mode 100755 roomba_980/roomba/__main__.py delete mode 100644 roomba_980/roomba/config.ini delete mode 100755 roomba_980/roomba/getpassword.py delete mode 100755 roomba_980/roomba/password.py delete mode 100644 roomba_980/roomba/res/binfull.png delete mode 100644 roomba_980/roomba/res/home.png delete mode 100644 roomba_980/roomba/res/map.png delete mode 100644 roomba_980/roomba/res/roomba-base.png delete mode 100644 roomba_980/roomba/res/roomba-charge.png delete mode 100644 roomba_980/roomba/res/roomba.png delete mode 100644 roomba_980/roomba/res/roombacancelled.png delete mode 100644 roomba_980/roomba/res/roombaerror.png delete mode 100755 roomba_980/roomba/roomba.py delete mode 100755 roomba_980/roomba/roomba_direct.py diff --git a/roomba_980/examples/complicated.py b/roomba_980/examples/complicated.py deleted file mode 100644 index 90a50393b..000000000 --- a/roomba_980/examples/complicated.py +++ /dev/null @@ -1,95 +0,0 @@ -from __future__ import print_function -from roomba import Roomba -import paho.mqtt.client as mqtt -import time -import json - -#put your own values here -broker = 'localhost' #ip of mqtt broker -user = 'user' #mqtt username -password = 'password' #mqtt password -#broker = None if not using local mqtt broker -address = '192.168.100.181' -blid = '3117850851637850' -roombaPassword = ':1:1493919143:gOiaWpQ4LbSoD1xJ' - -def broker_on_connect(client, userdata, flags, rc): - print("Broker Connected with result code "+str(rc)) - #subscribe to roomba feedback - if rc == 0: - mqttc.subscribe(brokerCommand) - mqttc.subscribe(brokerSetting) - -def broker_on_message(mosq, obj, msg): - #publish to roomba - if "command" in msg.topic: - print("Received COMMAND: %s" % str(msg.payload)) - myroomba.send_command(str(msg.payload)) - elif "setting" in msg.topic: - print("Received SETTING: %s" % str(msg.payload)) - cmd = str(msg.payload).split() - myroomba.set_preference(cmd[0], cmd[1]) - -def broker_on_publish(mosq, obj, mid): - pass - -def broker_on_subscribe(mosq, obj, mid, granted_qos): - print("Broker Subscribed: %s %s" % (str(mid), str(granted_qos))) - -def broker_on_disconnect(mosq, obj, rc): - print("Broker disconnected") - -def broker_on_log(mosq, obj, level, string): - print(string) - - -mqttc = None -if broker is not None: - brokerCommand = "/roomba/command" - brokerSetting = "/roomba/setting" - brokerFeedback = "/roomba/feedback" - - #connect to broker - mqttc = mqtt.Client() - #Assign event callbacks - mqttc.on_message = broker_on_message - mqttc.on_connect = broker_on_connect - mqttc.on_disconnect = broker_on_disconnect - mqttc.on_publish = broker_on_publish - mqttc.on_subscribe = broker_on_subscribe - - try: - mqttc.username_pw_set(user, password) #put your own mqtt user and password here if you are using them, otherwise comment out - mqttc.connect(broker, 1883, 60) #Ping MQTT broker every 60 seconds if no data is published from this script. - - except Exception as e: - print("Unable to connect to MQTT Broker: %s" % e) - mqttc = None - -myroomba = Roomba() #minnimum required to connect on Linux Debian system, will read connection from config file -#myroomba = Roomba(address, blid, roombaPassword, topic="#", continuous=True, clean=False, cert_name = "./ca-certificates.crt") #setting things manually - -#all these are optional, if you don't include them, the defaults will work just fine -#if you are using maps -myroomba.enable_map(enable=True, mapSize="(800,1650,-300,-50,2,0)", mapPath="./", iconPath="./") #enable live maps, class default is no maps -if broker is not None: - myroomba.set_mqtt_client(mqttc, brokerFeedback) #if you want to publish Roomba data to your own mqtt broker (default is not to) if you have more than one roomba, and assign a roombaName, it is addded to this topic (ie brokerFeedback/roombaName) -#finally connect to Roomba - (required!) -myroomba.connect() - -print(" to exit") -print("Subscribe to /roomba/feedback/# to see published data") - -try: - if mqttc is not None: - mqttc.loop_forever() - else: - while True: - print("Roomba Data: %s" % json.dumps(myroomba.master_state, indent=2)) - time.sleep(5) - -except (KeyboardInterrupt, SystemExit): - print("System exit Received - Exiting program") - myroomba.disconnect() - if mqttc is not None: - mqttc.disconnect() diff --git a/roomba_980/examples/example_start_roomba b/roomba_980/examples/example_start_roomba deleted file mode 100644 index e27a6dc93..000000000 --- a/roomba_980/examples/example_start_roomba +++ /dev/null @@ -1,8 +0,0 @@ -#! /bin/bash -# example start line - insert your own values - -# looks like 3012830851937810 -# looks like :1:1493919143:gOiaYpQ4LbfoD1yJ -# -b is the ip of the mqtt broker to publish to, leave it out if you are not forwarding roomba data -# -s is the size and shape of the map (if you are drawing maps) x,y, dock location x,y, map rotation, roomba rotation -./roomba.py -R -u -w -b localhost -s '(800,1650,-300,-50,2,0)' diff --git a/roomba_980/examples/simple.py b/roomba_980/examples/simple.py deleted file mode 100644 index 798f601e6..000000000 --- a/roomba_980/examples/simple.py +++ /dev/null @@ -1,25 +0,0 @@ -from __future__ import print_function -from roomba import Roomba - -#uncomment the option you want to run, and replace address, blid and roombaPassword with your own values - -address = "192.168.100.181" -blid = "3115850251687850" -roombaPassword = ":1:1493319243:gOiaXpQ4lbSoD1xJ" - -myroomba = Roomba(address, blid, roombaPassword) -#or myroomba = Roomba() #if you have a config file - will attempt discovery if you don't -myroomba.connect() - -myroomba.set_preference("carpetBoost", "true") -#myroomba.set_preference("twoPass", "false") - -#myroomba.send_command("start") -#myroomba.send_command("stop") -#myroomba.send_command("dock") - -import json, time -for i in range(5): - print(json.dumps(myroomba.master_state, indent=2)) - time.sleep(1) -myroomba.disconnect() diff --git a/roomba_980/roomba/__init__.py b/roomba_980/roomba/__init__.py deleted file mode 100755 index f73355eda..000000000 --- a/roomba_980/roomba/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from __future__ import absolute_import -from .roomba import Roomba -from .password import Password diff --git a/roomba_980/roomba/__main__.py b/roomba_980/roomba/__main__.py deleted file mode 100755 index 2c2ee66b8..000000000 --- a/roomba_980/roomba/__main__.py +++ /dev/null @@ -1,590 +0,0 @@ -from __future__ import print_function -from ast import literal_eval -from logging.handlers import RotatingFileHandler -import sys -if sys.version_info[0] < 3: #added for python 2.7 fix NW 15/9/2017 - import roomba - from roomba import Password -else: - from roomba import roomba - from roomba.password import Password -import argparse -import json -import logging -import os -import six -import socket -import time -# Import trickery -global HAVE_CV2 -global HAVE_MQTT -global HAVE_PIL -HAVE_CV2 = HAVE_MQTT = HAVE_PIL = False #fix for if neither PIL or OPENCV is installed (RPI versions) NW 3/2/2018 -try: - import configparser -except: - from six.moves import configparser -try: - import paho.mqtt.client as mqtt - HAVE_MQTT = True -except ImportError: - print("paho mqtt client not found") -try: - import cv2 - HAVE_CV2 = True -except ImportError: - print("CV or numpy module not found, falling back to PIL") - -# NOTE: MUST use Pillow Pillow 4.1.1 to avoid some horrible memory leaks in the -# text handling! -try: - from PIL import Image - HAVE_PIL = True -except ImportError: - print("PIL module not found, maps are disabled") - -def parse_args(): - default_icon_path = os.path.join(os.path.dirname(__file__), 'res') - #-------- Command Line ----------------- - parser = argparse.ArgumentParser( - description='Forward MQTT data from Roomba 980 to local MQTT broker') - parser.add_argument( - '-f', '--configfile', - action='store', - type=str, - default="./config.ini", - help='config file name (default: ./config.ini)') - parser.add_argument( - '-n', '--roombaName', - action='store', - type=str, - default="", help='optional Roomba name (default: "")') - parser.add_argument( - '-t', '--topic', - action='store', - type=str, - default="#", - help='Roomba MQTT Topic to subscribe to (can use wildcards # and ' - '+ default: #)') - parser.add_argument( - '-T', '--brokerFeedback', - action='store', - type=str, - default="/roomba/feedback", - help='Topic on broker to publish feedback to (default: ' - '/roomba/feedback)') - parser.add_argument( - '-C', '--brokerCommand', - action='store', - type=str, - default="/roomba/command", - help='Topic on broker to publish commands to (default: ' - '/roomba/command)') - parser.add_argument( - '-S', '--brokerSetting', - action='store', - type=str, - default="/roomba/setting", - help='Topic on broker to publish settings to (default: ' - '/roomba/setting)') - parser.add_argument( - '-b', '--broker', - action='store', - type=str, - default=None, - help='ipaddress of MQTT broker (default: None)') - parser.add_argument( - '-p', '--port', - action='store', - type=int, - default=1883, - help='MQTT broker port number (default: 1883)') - parser.add_argument( - '-U', '--user', - action='store', - type=str, - default=None, - help='MQTT broker user name (default: None)') - parser.add_argument( - '-P', '--password', - action='store', - type=str, - default=None, - help='MQTT broker password (default: None)') - parser.add_argument( - '-R', '--roombaIP', - action='store', - type=str, - default=None, - help='ipaddress of Roomba 980 (default: None)') - parser.add_argument( - '-u', '--blid', - action='store', - type=str, - default=None, - help='Roomba 980 blid (default: None)') - parser.add_argument( - '-w', '--roombaPassword', - action='store', - type=str, - default=None, - help='Roomba 980 password (default: None)') - parser.add_argument( - '-i', '--indent', - action='store', - type=int, - default=0, - help='Default indentation=auto') - parser.add_argument( - '-l', '--log', - action='store', - type=str, - default="./Roomba.log", - help='path/name of log file (default: ./Roomba.log)') - parser.add_argument( - '-e', '--echo', - action='store_false', - default = True, - help='Echo to Console (default: True)') - parser.add_argument( - '-D', '--debug', - action='store_true', - default = False, - help='debug mode') - parser.add_argument( - '-r', '--raw', - action='store_true', - default = False, - help='Output raw data to mqtt, no decoding of json data') - parser.add_argument( - '-j', '--pretty_print', - action='store_true', - default = False, - help='pretty print json in logs') - parser.add_argument( - '-c','--continuous', - action='store_false', - default = True, - help='Continuous connection to Roomba (default: True)') - parser.add_argument( - '-d', '--delay', - action='store', - type=int, - default=1000, - help='Disconnect period for non-continuous connection (default: ' - '1000ms)') - parser.add_argument( - '-m', '--drawmap', - action='store_false', - default = True, - help='Draw Roomba cleaning map (default: True)') - parser.add_argument( - '-M', '--mapPath', - action='store', - type=str, - default=".", - help='Location to store maps to (default: .)') - parser.add_argument( - '-s', '--mapSize', - action='store', - type=str, - default="(800,1500,0,0,0,0)", - help='Map Size, Dock offset and skew for the map. (800,1500) is the ' - 'size, (0,0) is the dock location, in the center of the map, 0 ' - 'is the rotation of the map, 0 is the rotation of the roomba. ' - 'Use single quotes around the string. (default: ' - '"(800,1500,0,0,0,0)")') - parser.add_argument( - '-I', '--iconPath', - action='store', - type=str, - default=default_icon_path, - help='location of icons. (default: "./")') - parser.add_argument( - '-o', '--roomOutline', - action='store_false', - default = True, - help='Draw room outline (default: True)') - parser.add_argument( - '-x', '--exclude', - action='store',type=str, default="", help='Exclude topics that have this in them (default: "")') - parser.add_argument( - '--cert', - action='store', - type=str, - default='/etc/ssl/certs/ca-certificates.crt', - help='Set the certificate to use for MQTT communication with the Roomba') - parser.add_argument( - '--version', - action='version', - version="%(prog)s ({})".format(roomba.__version__), - help='Display version of this program') - return parser.parse_args() - -def main(): - arg = parse_args() - - #----------- Local Routines ------------ - - def broker_on_connect(client, userdata, flags, rc): - log.debug("Broker Connected with result code " + str(rc)) - #subscribe to roomba feedback, if there is more than one roomba, the - # roombaName is added to the topic to subscribe to - if rc == 0: - if brokerCommand != "": - if len(roombas) == 1: - mqttc.subscribe(brokerCommand) - else: - for myroomba in roomba_list: - mqttc.subscribe( - brokerCommand + "/" + myroomba.roombaName) - if brokerSetting != "": - if len(roombas) == 1: - mqttc.subscribe(brokerSetting) - else: - for myroomba in roomba_list: - mqttc.subscribe( - brokerSetting + "/" + myroomba.roombaName) - - def broker_on_message(mosq, obj, msg): - # publish to roomba, if there is more than one roomba, the roombaName - # is added to the topic to publish to - msg.payload = msg.payload.decode("utf-8") - if "command" in msg.topic: - log.info("Received COMMAND: %s" % str(msg.payload)) - if len(roombas) == 1: - roomba_list[0].send_command(str(msg.payload)) - else: - for myroomba in roomba_list: - if myroomba.roombaName in msg.topic: - myroomba.send_command(str(msg.payload)) - elif "setting" in msg.topic: - log.info("Received SETTING: %s" % str(msg.payload)) - cmd = str(msg.payload).split() - if len(roombas) == 1: - roomba_list[0].set_preference(cmd[0], cmd[1]) - else: - for myroomba in roomba_list: - if myroomba.roombaName in msg.topic: - myroomba.set_preference(cmd[0], cmd[1]) - else: - log.warn("Unknown topic: %s" % str(msg.topic)) - - def broker_on_publish(mosq, obj, mid): - pass - - def broker_on_subscribe(mosq, obj, mid, granted_qos): - log.debug("Broker Subscribed: %s %s" % (str(mid), str(granted_qos))) - - def broker_on_disconnect(mosq, obj, rc): - log.debug("Broker disconnected") - if rc == 0: - sys.exit(0) - - def broker_on_log(mosq, obj, level, string): - log.info(string) - - def read_config_file(file="./config.ini"): - #read config file - Config = configparser.ConfigParser() - try: - Config.read(file) - log.info("reading info from config file %s" % file) - roombas = {} - for address in Config.sections(): - roomba_data = literal_eval(Config.get(address, "data")) - roombas[address] = { - "blid": Config.get(address, "blid"), - "password": Config.get(address, "password"), - "roombaName": roomba_data.get("robotname", None)} - except Exception as e: - log.warn("Error reading config file %s" %e) - return roombas - - def create_html(myroomba,mapPath="."): - ''' - Create html files for live display of roomba maps - but only if they - don't already exist - ''' - #default css and html - css='''body { - background-color: white; - color: white; - margin: 0; - padding: 0; - } -img,video { - width: auto; - max-height:100%; - } -''' - html=''' - - - - - - - -''' - html +='Roomba Map Live' % myroomba.roombaName - html +=''' - - -''' - #python 3 workaround - try: - FileNotFoundError - except NameError: - #py2 - FileNotFoundError = PermissionError = IOError - - #check is style.css exists, if not create it - css_path = mapPath+"/style.css" - try: - fn = open(css_path , "r") #check if file exists (or is readable) - fn.close() - except (IOError,FileNotFoundError): - log.warn("CSS file not found, creating %s" % css_path) - try: - with open(css_path , "w") as fn: - fn.write(css) - except (IOError, PermissionError) as e: - log.error("unable to create file %s, error: %s" % css_path, e) - #check is html exists, if not create it - html_path = mapPath+"/"+ myroomba.roombaName + "roomba_map.html" - try: - fn = open(html_path, "r") #check if file exists (or is readable) - fn.close() - except (IOError,FileNotFoundError): - log.warn("html file not found, creating %s" % html_path) - try: - with open(html_path, "w") as fn: - fn.write(html) - make_executable(html_path) - except (IOError, PermissionError) as e: - log.error("unable to create file %s, error: %s" % html_path, e) - - def make_executable(path): - mode = os.stat(path).st_mode - mode |= (mode & 0o444) >> 2 # copy R bits to X - os.chmod(path, mode) - - def setup_logger(logger_name, log_file, level=logging.DEBUG, console=False): - try: - l = logging.getLogger(logger_name) - if logger_name ==__name__: - formatter = logging.Formatter( - '[%(levelname)1.1s %(asctime)s] %(message)s') - else: - formatter = logging.Formatter('%(message)s') - fileHandler = RotatingFileHandler( - log_file, mode='a', maxBytes=2000000, backupCount=5) - fileHandler.setFormatter(formatter) - if console == True: - streamHandler = logging.StreamHandler() - - l.setLevel(level) - l.addHandler(fileHandler) - if console == True: - streamHandler.setFormatter(formatter) - l.addHandler(streamHandler) - except IOError as e: - if e[0] == 13: #errno Permission denied - print("Error: %s: You probably don't have permission to " - "write to the log file/directory - try sudo" % e) - else: - print("Log Error: %s" % e) - sys.exit(1) - - args = parse_args() - - if arg.debug: - log_level = logging.DEBUG - else: - log_level = logging.INFO - - #setup logging - setup_logger(__name__, arg.log,level=log_level,console=arg.echo) - - log = logging.getLogger(__name__) - - log.info("*******************") - log.info("* Program Started *") - log.info("*******************") - - log.info("Roomba.py Version: %s" % roomba.__version__) - - log.info("Python Version: %s" % sys.version.replace('\n','')) - - if HAVE_MQTT: - import paho.mqtt # bit of a kludge, just to get the version number - log.info("Paho MQTT Version: %s" % paho.mqtt.__version__) - if (sys.version_info.major == 2 and sys.version_info.minor == 7 and - sys.version_info.micro < 9 and - int(paho.mqtt.__version__.split(".")[0]) >= 1 and - int(paho.mqtt.__version__.split(".")[1]) > 2): - log.error("NOTE: if your python version is less than 2.7.9, " - "and Paho MQTT verion is not 1.2.3 or lower, this " - "program will NOT WORK") - log.error("Please use pip install paho-mqtt==1.2.3 to " - "downgrade paho-mqtt, or use a later version of python") - sys.exit(1) - - if HAVE_CV2: - log.info("CV Version: %s" % cv2.__version__) - - if HAVE_PIL: - import PIL #bit of a kludge, just to get the version number - log.info("PIL Version: %s" % PIL.__version__) - if int(PIL.__version__.split(".")[0]) < 4: - log.warn("WARNING: PIL version is %s, this is not the latest! " - "You can get bad memory leaks with old versions of PIL" - % Image.PILLOW_VERSION) - log.warn("run: 'pip install --upgrade pillow' to fix this") - - log.debug("-- DEBUG Mode ON -") - log.info(" to Exit") - log.info("Roomba 980 MQTT data Interface") - - roombas = {} - - if arg.blid is None or arg.roombaPassword is None: - roombas = read_config_file(arg.configfile) - if len(roombas) == 0: - log.warn("No roomba or config file defined, I will attempt to " - "discover Roombas, please put the Roomba on the dock " - "and follow the instructions:") - if arg.roombaIP is None: - Password(file=arg.configfile) - else: - Password(arg.roombaIP,file=arg.configfile) - roombas = read_config_file(arg.configfile) - if len(roombas) == 0: - log.error("No Roombas found! You must specify RoombaIP, blid " - "and roombaPassword to run this program, or have " - "a config file, use -h to show options.") - sys.exit(0) - else: - log.info("Success! %d Roombas Found!" % len(roombas)) - else: - roombas[arg.roombaIP] = { - "blid": arg.blid, - "password": arg.roombaPassword, - "roombaName": arg.roombaName} - - # set broker = "127.0.0.1" # mosquitto broker is running on localhost - mqttc = None - if arg.broker is not None: - brokerCommand = arg.brokerCommand - brokerSetting = arg.brokerSetting - - # connect to broker - mqttc = mqtt.Client() - # Assign event callbacks - mqttc.on_message = broker_on_message - mqttc.on_connect = broker_on_connect - mqttc.on_disconnect = broker_on_disconnect - mqttc.on_publish = broker_on_publish - mqttc.on_subscribe = broker_on_subscribe - # uncomment to enable logging - # mqttc.on_log = broker_on_log - - try: - if arg.user != None: - mqttc.username_pw_set(arg.user, arg.password) - log.info("connecting to broker") - # Ping MQTT broker every 60 seconds if no data is published - # from this script. - mqttc.connect(arg.broker, arg.port, 60) - - except socket.error: - log.error("Unable to connect to MQTT Broker") - mqttc = None - - roomba_list = [] - for addr, info in six.iteritems(roombas): - log.info("Creating Roomba object %s" % addr) - #NOTE: cert_name is a default certificate. change this if your - # certificates are in a different place. any valid certificate will - # do, it's not used but needs to be there to enable mqtt TLS encryption - # instansiate Roomba object - # minnimum required to connect on Linux Debian system - # myroomba = Roomba(address, blid, roombaPassword) - roomba_list.append( - roomba.Roomba(addr, blid=info["blid"], - password=info["password"], - topic=arg.topic, continuous=arg.continuous, - clean=False, - cert_name=args.cert, - roombaName=info["roombaName"])) - - for myroomba in roomba_list: - log.info("connecting Roomba %s" % myroomba.address) - # auto create html files (if they don't exist) - create_html(myroomba,arg.mapPath) - # all these are optional, if you don't include them, the defaults - # will work just fine - if arg.exclude != "": - myroomba.exclude = arg.exclude - myroomba.set_options( - raw=arg.raw, indent=arg.indent, pretty_print=arg.pretty_print) - if not arg.continuous: - myroomba.delay = arg.delay//1000 - if arg.mapSize != "" and arg.mapPath != "": - # enable live maps, class default is no maps - myroomba.enable_map(enable=True, mapSize=arg.mapSize, - mapPath=arg.mapPath, iconPath=arg.iconPath, - roomOutline=arg.roomOutline) - if arg.broker is not None: - # if you want to publish Roomba data to your own mqtt broker - # (default is not to) if you have more than one roomba, and - # assign a roombaName, it is addded to this topic - # (ie brokerFeedback/roombaName) - myroomba.set_mqtt_client(mqttc, arg.brokerFeedback) - # finally connect to Roomba - (required!) - myroomba.connect() - - try: - if mqttc is not None: - mqttc.loop_forever() - else: - while True: - log.info("Roomba Data: %s" % - json.dumps(myroomba.master_state, indent=2)) - time.sleep(5) - - except (KeyboardInterrupt, SystemExit): - log.info("System exit Received - Exiting program") - mqttc.disconnect() - sys.exit(0) - - -if __name__ == '__main__': - main() diff --git a/roomba_980/roomba/config.ini b/roomba_980/roomba/config.ini deleted file mode 100644 index c7797d4df..000000000 --- a/roomba_980/roomba/config.ini +++ /dev/null @@ -1,24 +0,0 @@ -[192.168.5.147] -blid = 6977C20412227550 -password = U1OuP439NAlFAahW -data = {u'cap': {u'binFullDetect': 1, - u'carpetBoost': 1, - u'eco': 1, - u'edge': 1, - u'langOta': 1, - u'maps': 1, - u'multiPass': 2, - u'ota': 2, - u'pose': 1, - u'pp': 1, - u'svcConf': 1}, - u'hostname': u'Roomba-6977C20412227550', - u'ip': u'192.168.5.147', - u'mac': u'F0:03:8C:B5:78:36', - u'nc': 0, - u'proto': u'mqtt', - u'robotname': u'Robii', - u'sku': u'R980040', - u'sw': u'v2.4.6-3', - u'ver': u'3'} - diff --git a/roomba_980/roomba/getpassword.py b/roomba_980/roomba/getpassword.py deleted file mode 100755 index dd39db604..000000000 --- a/roomba_980/roomba/getpassword.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -__version__ = "1.0" -''' -Python 2.7+ -Quick Program to get blid and password from roomba - -Nick Waterton 5th May 2017: V 1.0: Initial Release -''' - -from roomba import Password - -def main(): - import argparse - #-------- Command Line ----------------- - parser = argparse.ArgumentParser( - description='Forward MQTT data from Roomba 980 to local MQTT broker') - parser.add_argument( - '-f', '--configfile', - action='store', - type=str, - default="./config.ini", - help='config file name, default: ./config.ini)') - parser.add_argument( - '-R','--roombaIP', - action='store', - type=str, - default=None, - help='ipaddress of Roomba 980 (default: None)') - arg = parser.parse_args() - - if arg.roombaIP is None: - Password(file=arg.configfile) - else: - Password(arg.roombaIP,file=arg.configfile) - -if __name__ == '__main__': - main() diff --git a/roomba_980/roomba/password.py b/roomba_980/roomba/password.py deleted file mode 100755 index 4e6e4995f..000000000 --- a/roomba_980/roomba/password.py +++ /dev/null @@ -1,186 +0,0 @@ -from __future__ import print_function -from pprint import pformat -import json -import logging -import socket -import six -import ssl -import sys -try: - import configparser -except: - from six.moves import configparser - -if sys.version_info[0] < 3: #fix more python 3 incompatibilities - input = raw_input - -log = logging.getLogger(__name__) - -class Password(object): - ''' - Get Roomba blid and password - only V2 firmware supported - if IP is not supplied, class will attempt to discover the Roomba IP first. - Results are written to a config file, default ".\config.ini" - V 1.2.3 NW 9/10/2018 added support for Roomba i7 - ''' - - VERSION = __version__ = "1.2.4" - - def __init__(self, address='255.255.255.255', file=".\config.ini"): - self.address = address - self.file = file - #self.log = logging.getLogger(__name__+'.Roomba_getpassword') - if __name__ == "password": - self.log = logging.getLogger("__main__") #another logging fix NW 3/2/2018 - else: - self.log = logging.getLogger("roomba.__main__") - #self.log.info("__name__ is %s" % __name__) - self.log.info("Using Password version %s" % self.VERSION) - self.get_password() - - def receive_udp(self): - #set up UDP socket to receive data from robot - port = 5678 - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.settimeout(10) - if self.address == '255.255.255.255': - s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) - s.bind(("", port)) #bind all intefaces to port - print("waiting on port: %d for data" % port) - message = 'irobotmcs' - s.sendto(message.encode(), (self.address, port)) - roomba_dict = {} - while True: - try: - udp_data, addr = s.recvfrom(1024) #wait for udp data - #print('Received: Robot addr: %s Data: %s ' % (addr, udp_data)) - if len(udp_data) > 0: - if udp_data != message: - try: - if self.address != addr[0]: - self.log.warn( - "supplied address %s does not match " - "discovered address %s, using discovered " - "address..." % (self.address, addr[0])) - if udp_data.decode() != message: - parsedMsg = json.loads(udp_data.decode()) #1.2.3 added .decode() to avoid python 3 bytes error - roomba_dict[addr]=parsedMsg - except Exception as e: - print("json decode error: %s" % e) - print('RECEIVED: %s', pformat(udp_data)) - # print('Robot Data: %s ' - # % json.dumps(parsedMsg, indent=2)) - else: - break - except socket.timeout: - break - s.close() - return roomba_dict - - def get_password(self): - import struct - #get roomba info - blid=None - roombas = self.receive_udp() - - if len(roombas) == 0: - print("No Roombas found, try again...") - return False - else: - print("found %d Roomba(s)" % len(roombas)) - - for address,parsedMsg in six.iteritems(roombas): - addr = address[0] - if int(parsedMsg["ver"]) < 2: - print("Roombas at address: %s does not have the correct " - "firmware version. Your version info is: %s" - % (addr,json.dumps(parsedMsg, indent=2))) - continue - - print("Make sure your robot (%s) at IP %s is on the Home Base and " - "powered on (green lights on). Then press and hold the HOME " - "button on your robot until it plays a series of tones " - "(about 2 seconds). Release the button and your robot will " - "flash WIFI light." - % (parsedMsg["robotname"],addr)) - input("Press Enter to continue...") - - print("Received: %s" % json.dumps(parsedMsg, indent=2)) - print("\r\rRoomba (%s) IP address is: %s" - % (parsedMsg["robotname"],addr)) - hostname = parsedMsg["hostname"].split('-') - if hostname[0] == 'Roomba' or hostname[0] == 'iRobot': #for i7 robot name is now iRobot - blid = hostname[1] - - if hasattr(str, 'decode'): - # this is 0xf0 (mqtt reserved) 0x05(data length) - # 0xefcc3b2900 (data) - packet = 'f005efcc3b2900'.decode("hex") - else: - #this is 0xf0 (mqtt reserved) 0x05(data length) - # 0xefcc3b2900 (data) - packet = bytes.fromhex('f005efcc3b2900') - #send socket - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.settimeout(10) - - #ssl wrap - wrappedSocket = ssl.wrap_socket( - sock, ssl_version=ssl.PROTOCOL_TLSv1) - #connect and send packet - try: - wrappedSocket.connect((addr, 8883)) - except Exception as e: - print("Connection Error %s" % e) - - wrappedSocket.send(packet) - data = b'' - data_len = 35 - while True: - try: - # NOTE data is 0xf0 (mqtt RESERVED) length (0x23 = 35), - # 0xefcc3b2900 (magic packet), 0xXXXX... (30 bytes of - # password). so 7 bytes, followed by 30 bytes of password - # (total of 37) - if len(data) >= data_len+2: - break - data_received = wrappedSocket.recv(1024) - except socket.error as e: - print("Socket Error: %s" % e) - break - - if len(data_received) == 0: - print("socket closed") - break - else: - data += data_received - if len(data) >= 2: - data_len = struct.unpack("B", data[1:2])[0] - - #close socket - wrappedSocket.close() - # if len(data) > 0: - # import binascii - # print("received data: hex: %s, length: %d" - # % (binascii.hexlify(data), len(data))) - if len(data) <= 7: - print('Error getting password, receive %d bytes. Follow the ' - 'instructions and try again.' % len(data)) - return False - else: - # Convert password to str - #password = str(data[7:].decode()) #old version - password = str(data[7:].decode().rstrip()) #for i7 - has null termination - print("blid is: %s" % blid) - print('Password=> %s <= Yes, all this string.' % password) - print('Use these credentials in roomba.py') - - Config = configparser.ConfigParser() - Config.add_section(addr) - Config.set(addr,'blid', blid) - Config.set(addr,'password', password) - Config.set(addr,'data', pformat(parsedMsg)) - # write config file - with open(self.file, 'w') as cfgfile: - Config.write(cfgfile) - return True diff --git a/roomba_980/roomba/res/binfull.png b/roomba_980/roomba/res/binfull.png deleted file mode 100644 index 15c2db65c68bd270066a55741bf941b0e8f562ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4806 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 diff --git a/roomba_980/roomba/res/home.png b/roomba_980/roomba/res/home.png deleted file mode 100644 index 7496991078f279dc4906e278c7af3d49c1179ce9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1378 zcmV-o1)chdP)ijMHK#K?%hYL-9CgO zp(*J@UO{MBD7M{gw|lz?5(!2K1O%f&C1QN=k0@yi_#hFLNccev34(yp5D5Ix?)J9V zwiZe>5QPAt+jd*ZGo^)=w(Pxg{2^%DeX!da^-Jc*J#)|bzH?^I%mDu}*k~O+E?1Gk z`6@<4Oo#(MO*=W7I8wY0<>lpElB7+7Xg_BxAB^P-;MJV0ES@=ea(!D{n}{b~ToouO zDM^tfX&-n>gnd2vH}Q&8w@bs@mOd_j(4b2LJ+sobwlbK3`yDOgUC^ zMNysx(GdW-06GjImetnQo_a8MLb@gwuEYAbcR{&DM`B4xR#1cDd1(q*gZtl8ya|ejt0ssO&F$`mK zb$z|AD9RJJ2T=hIBr$!n*X!*D@S371K4BPpIOj8B5fE_?xZUnaB*b@|^8z8n9me^~ zs;V9Z0Efd-);%s~r+@Lb832%d{DX5TUCkTn>+3ZD@OV5~!Y~d2m`_B+7-Iw!tEyTz zk|%5zD2n1DA$*+kX$1VvIWJRHwE+O~3mxU{c`H7={QO7RL8}cxs|`11Elo%NUC&gh z*LtNRQ0MpiyVKIr_E{|!Gh@v0AZ%t%PR=pE-#-|w0?h4pZzLhMbIv6K4oZ^ry4UON zTj+3%zizf2@IO~k+><%a8cujhb3=db4_j)|ELc-jRn-LmrKP0{NQnKCB&7?Y7RK00 zRaKip1QZq)CM8%bd%@T;06K^^R@c<*0zgGYMV_8zHM$@!g0N`@D<}=0)aU!#$q$HC8V2aDNn>fE^7)GV0X}aSX$HMOP zr#`!|Wao6;#71)ZFL-!c=y+0D-^PEevdze4W!yeOyaI?;JU2FdFO`KYMZW zqA&ACFW})%5h{>%W>0%lz4}rliS`2MNw+TL-A$VkK0uhbq3;0^dB`l7P+ndh@doAK zCPoxFMoblW#2$DgqWOohhkuZawGHF&{~uN$T7XzG8?%719z@anV{XH-?15ak0T1JdQc7X(R kGFd*ZX__7_iGLk`05fMcj2k-sKmY&$07*qoM6N<$f)8D4hX4Qo diff --git a/roomba_980/roomba/res/map.png b/roomba_980/roomba/res/map.png deleted file mode 100644 index e6bebdfe58f0df29c8e103723ee1672b0b1c676e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32050 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 diff --git a/roomba_980/roomba/res/roomba-base.png b/roomba_980/roomba/res/roomba-base.png deleted file mode 100644 index 4af2f6df3de91752584e5918b3bea7c54bf47235..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1510 zcmbtU`#;kQ0R0x4w+UmZ8IwmgT%n0#n&h=y+&qiPR!JUfJ&@jSu+ar~+NQXKWbtE38H4-LQj_)mOtdg9~s^Ef$L()KlK?Zm}bK;5>KZ{{iqOwiXKj zl95hWjMwe)+(!!3e6)N@_k4?GV}HKeetBpXF{#2xFrpTYSo%$^&T)G;KGixUKwP^Z zSjh`>>fQX6GS|K-x7`Vp^Jc$?_wW^0qui($MOcf=uYf?ol9B(4W|_#E^Miq7BAniVH#h_@#0px=-UW5pS4TM z#8L~QV(A8c3DYfGa>v|FwgR`!LL&r@G>CUf#qt(YO02iqt+S%l$aorm<;|K*bkb1z-t$^6CpOjN*~jT}MXF%k z89~WQ`o(gHSWilcw@>^gQXBSXWPmEX=#0PEa?yipNzb}=n~1DVq1D#!^^$;=jCH0i ziIDrIGeRMns5T_OX)LF!MRhtT;X z_(gl^UTHkn^)fPH6lg%-tXyB-sl3IO3L8aM6st+nQVvcWO1@V>RL&X{${BfIcjc5>=W5b|{4te6of4js z7Q|u^k!#?Ih`~-KvE+dtZzfvk^An9Nkt|}~2^&B5)IBw$dWW|h8;ftotvv!ypEg&BB|4Wz-o>H7E&Rr%#uy<# zx`m%fd#Ri$E7xTCHt&*idDEA>`P0rB%g^Rrrfjc954^u=)=6*0&@0cyM8-Y!8_*kU zHd()A4Hd&J@`H5tgC?T9t^SpL0>dKU=SWv%3|A5QHT4q(-(@h^CdL$UsHxpv&8nro zWq8PMBQ>6SQAI;dy7~H9YPwb5=-%Q`N%Icj#+AmHDk-v%f@l?; zRa9tTQex`;G<9wvk+mq2i?X!#`Jy)aCAny0eRBq0D8FH?%;ww(A1Kxf7IJ02N;5_h zpXk3@J&RJNH}~yn-RMMfN$3wlm_gsJNl#)N{0YYbX}4AHN$!(Gwk4ku256WfK?S!X zH&ktH8J}#xtXNj-E6u6I0900=vuG}-OJW){0Z6U?nj^NYvbZOM_@X=|{j0aQQm~_? ypXCxV)j89)J6$r5t=(Z`#YNP$c0uyCQ5TRE5xw#oS}NTAF~G?Ihkb4zl<*(5KK0Z9 diff --git a/roomba_980/roomba/res/roomba-charge.png b/roomba_980/roomba/res/roomba-charge.png deleted file mode 100644 index 491b26cb32a3e0c8579fa9fdad1882535566dc0d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1500 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 LTx_dh0SW&B4g&=X diff --git a/roomba_980/roomba/roomba.py b/roomba_980/roomba/roomba.py deleted file mode 100755 index 8923f8ab3..000000000 --- a/roomba_980/roomba/roomba.py +++ /dev/null @@ -1,1641 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -''' -Python 2.7/Python 3.5/3.6 (thanks to pschmitt for adding Python 3 compatibility) -Program to connect to Roomba 980 vacuum cleaner, dcode json, and forward to mqtt -server - -Nick Waterton 24th April 2017: V 1.0: Initial Release -Nick Waterton 4th July 2017 V 1.1.1: Fixed MQTT protocol version, and map -paths, fixed paho-mqtt tls changes -Nick Waterton 5th July 2017 V 1.1.2: Minor fixes, CV version 3 .2 support -Nick Waterton 7th July 2017 V1.2.0: Added -o option "roomOutline" allows -enabling/disabling of room outline drawing, added auto creation of css/html files -Nick Waterton 11th July 2017 V1.2.1: Quick (untested) fix for room outlines -if you don't have OpenCV -Nick Waterton 3rd Feb 2018 V1.2.2: Quick (untested) fix for running directly (ie not installed) -Nick Waterton 12th April 2018 V1.2.3: Fixed image rotation bug causing distorted maps if map rotation was not 0. -''' - -from __future__ import print_function -from __future__ import absolute_import -__version__ = "1.2.3" - -from ast import literal_eval -from collections import OrderedDict, Mapping -try: - from roomba.password import Password -except ImportError: - from .password import Password -import datetime -import json -import math -import logging -import os -import six -import socket -import ssl -import sys -import threading -import time -import traceback -try: - import configparser -except: - from six.moves import configparser - -# Import trickery -global HAVE_CV2 -global HAVE_MQTT -global HAVE_PIL -HAVE_CV2 = False -HAVE_MQTT = False -HAVE_PIL = False -try: - import paho.mqtt.client as mqtt - HAVE_MQTT = True -except ImportError: - print("paho mqtt client not found") -try: - import cv2 - import numpy as np - HAVE_CV2 = True -except ImportError: - print("CV or numpy module not found, falling back to PIL") - -# NOTE: MUST use Pillow Pillow 4.1.1 to avoid some horrible memory leaks in the -# text handling! -try: - from PIL import Image, ImageDraw, ImageFont, ImageFilter, ImageOps - HAVE_PIL = True -except ImportError: - print("PIL module not found, maps are disabled") - -# On Python 3 raw_input was renamed to input -try: - input = raw_input -except NameError: - pass - - -class Roomba(object): - ''' - This is a Class for Roomba 900 series WiFi connected Vacuum cleaners - Requires firmware version 2.0 and above (not V1.0). Tested with Roomba 980 - username (blid) and password are required, and can be found using the - password() class above (or can be auto discovered) - Most of the underlying info was obtained from here: - https://github.com/koalazak/dorita980 many thanks! - The values received from the Roomba as stored in a dictionay called - master_state, and can be accessed at any time, the contents are live, and - will build with time after connection. - This is not needed if the forward to mqtt option is used, as the events will - be decoded and published on the designated mqtt client topic. - ''' - - VERSION = "1.0" - - states = {"charge": "Charging", - "new": "New Mission", - "run": "Running", - "resume": "Running", - "hmMidMsn": "Recharging", - "recharge": "Recharging", - "stuck": "Stuck", - "hmUsrDock": "User Docking", - "dock": "Docking", - "dockend": "Docking - End Mission", - "cancelled": "Cancelled", - "stop": "Stopped", - "pause": "Paused", - "hmPostMsn": "End Mission", - "": None} - - # From http://homesupport.irobot.com/app/answers/detail/a_id/9024/~/roomba-900-error-messages - _ErrorMessages = { - 0: "None", - 1: "Roomba is stuck with its left or right wheel hanging down.", - 2: "The debris extractors can't turn.", - 5: "The left or right wheel is stuck.", - 6: "The cliff sensors are dirty, it is hanging over a drop, "\ - "or it is stuck on a dark surface.", - 8: "The fan is stuck or its filter is clogged.", - 9: "The bumper is stuck, or the bumper sensor is dirty.", - 10: "The left or right wheel is not moving.", - 11: "Roomba has an internal error.", - 14: "The bin has a bad connection to the robot.", - 15: "Roomba has an internal error.", - 16: "Roomba has started while moving or at an angle, or was bumped "\ - "while running.", - 17: "The cleaning job is incomplete.", - 18: "Roomba cannot return to the Home Base or starting position." - } - - def __init__(self, address=None, blid=None, password=None, topic="#", - continuous=True, clean=False, cert_name="", roombaName="", - file="./config.ini"): - ''' - address is the IP address of the Roomba, the continuous flag enables a - continuous mqtt connection, if this is set to False, the client connects - and disconnects every 'delay' seconds (1 by default, but can be - changed). This is to allow other programs access, as there can only be - one Roomba connection at a time. - As cloud connections are unaffected, I reccomend leaving this as True. - leave topic as is, unless debugging (# = all messages). - if a python standard logging object exists, it will be used for logging. - ''' - - self.debug = False - self.log = logging.getLogger("roomba.__main__") #modified to work with new scheme NW 15/9/2017 - #self.log = logging.getLogger(__name__+'.Roomba') - if self.log.getEffectiveLevel() == logging.DEBUG: - self.debug = True - self.address = address - if not cert_name: - self.cert_name = "/etc/ssl/certs/ca-certificates.crt" - else: - self.cert_name = cert_name - self.continuous = continuous - if self.continuous: - self.log.info("CONTINUOUS connection") - else: - self.log.info("PERIODIC connection") - # set the following to True to enable pretty printing of json data - self.pretty_print = False - self.stop_connection = False - self.periodic_connection_running = False - self.clean = clean - self.roomba_port = 8883 - self.blid = blid - self.password = password - self.roombaName = roombaName - self.topic = topic - self.mqttc = None - self.exclude = "" - self.delay = 1 - self.roomba_connected = False - self.indent = 0 - self.master_indent = 0 - self.raw = False - self.drawmap = False - self.previous_co_ords = self.co_ords = self.zero_coords() - self.fnt = None - self.home_pos = None - self.angle = 0 - self.cleanMissionStatus_phase = "" - self.previous_cleanMissionStatus_phase = "" - self.current_state = None - self.last_completed_time = None - self.bin_full = False - self.base = None #base map - self.dock_icon = None #dock icon - self.roomba_icon = None #roomba icon - self.roomba_cancelled_icon = None #roomba cancelled icon - self.roomba_battery_icon = None #roomba battery low icon - self.roomba_error_icon = None #roomba error icon - self.bin_full_icon = None #bin full icon - self.room_outline_contour = None - self.room_outline = None - self.transparent = (0, 0, 0, 0) #transparent - self.previous_display_text = self.display_text = None - self.master_state = {} - self.time = time.time() - self.update_seconds = 300 #update with all values every 5 minutes - self.show_final_map = True - self.client = None - - if self.address is None or blid is None or password is None: - self.read_config_file(file) - - def read_config_file(self, file="./config.ini"): - #read config file - Config = configparser.ConfigParser() - try: - Config.read(file) - except Exception as e: - self.log.warn("Error reading config file %s" %e) - self.log.info("No Roomba specified, and no config file found - " - "attempting discovery") - if Password(self.address, file): - return self.read_config_file(file) - else: - return False - self.log.info("reading info from config file %s" % file) - addresses = Config.sections() - if self.address is None: - if len(addresses) > 1: - self.log.warn("config file has entries for %d Roombas, " - "only configuring the first!") - self.address = addresses[0] - self.blid = Config.get(self.address, "blid"), - self.password = Config.get(self.address, "password") - # self.roombaName = literal_eval( - # Config.get(self.address, "data"))["robotname"] - return True - - def setup_client(self): - if self.client is None: - if not HAVE_MQTT: - print("Please install paho-mqtt 'pip install paho-mqtt' " - "to use this library") - return False - self.client = mqtt.Client( - client_id=self.blid, clean_session=self.clean, - protocol=mqtt.MQTTv311) - # Assign event callbacks - self.client.on_message = self.on_message - self.client.on_connect = self.on_connect - self.client.on_publish = self.on_publish - self.client.on_subscribe = self.on_subscribe - self.client.on_disconnect = self.on_disconnect - - # Uncomment to enable debug messages - # client.on_log = self.on_log - - # set TLS, self.cert_name is required by paho-mqtt, even if the - # certificate is not used... - # but v1.3 changes all this, so have to do the following: - - self.log.info("Setting TLS") - try: - self.client.tls_set( - self.cert_name, cert_reqs=ssl.CERT_NONE, - tls_version=ssl.PROTOCOL_TLSv1) - except (ValueError, FileNotFoundError): # try V1.3 version - self.log.warn("TLS Setting failed - trying 1.3 version") - self.client._ssl_context = None - context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) - context.verify_mode = ssl.CERT_NONE - context.load_default_certs() - self.client.tls_set_context(context) - except: - self.log.error("Error setting TLS: %s" % traceback.format_exc()) - - # disables peer verification - self.client.tls_insecure_set(True) - self.client.username_pw_set(self.blid, self.password) - self.log.info("Setting TLS - OK") - return True - return False - - def connect(self): - if self.address is None or self.blid is None or self.password is None: - self.log.critical("Invalid address, blid, or password! All these " - "must be specified!") - sys.exit(1) - if self.roomba_connected or self.periodic_connection_running: return - - if self.continuous: - if not self._connect(): - if self.mqttc is not None: - self.mqttc.disconnect() - sys.exit(1) - else: - self._thread = threading.Thread(target=self.periodic_connection) - self._thread.daemon = True - self._thread.start() - - self.time = time.time() #save connect time - - def _connect(self, count=0, new_connection=False): - max_retries = 3 - try: - if self.client is None or new_connection: - self.log.info("Connecting %s" % self.roombaName) - self.setup_client() - self.client.connect(self.address, self.roomba_port, 60) - else: - self.log.info("Attempting to Reconnect %s" % self.roombaName) - self.client.loop_stop() - self.client.reconnect() - self.client.loop_start() - return True - except Exception as e: - self.log.error("Error: %s " % e) - exc_type, exc_obj, exc_tb = sys.exc_info() - # self.log.error("Exception: %s" % exc_type) - # if e[0] == 111: #errno.ECONNREFUSED - does not work with - # python 3.0 so... - if exc_type == socket.error or exc_type == ConnectionRefusedError: - count += 1 - if count <= max_retries: - self.log.error("Attempting new Connection# %d" % count) - time.sleep(1) - self._connect(count, True) - if count == max_retries: - self.log.error("Unable to connect %s" % self.roombaName) - return False - - def disconnect(self): - if self.continuous: - self.client.disconnect() - else: - self.stop_connection = True - - def periodic_connection(self): - # only one connection thread at a time! - if self.periodic_connection_running: return - self.periodic_connection_running = True - while not self.stop_connection: - if self._connect(): - time.sleep(self.delay) - self.client.disconnect() - time.sleep(self.delay) - - self.client.disconnect() - self.periodic_connection_running = False - - def on_connect(self, client, userdata, flags, rc): - self.log.info("Roomba Connected %s" % self.roombaName) - if rc == 0: - self.roomba_connected = True - self.client.subscribe(self.topic) - else: - self.log.error("Roomba Connected with result code " + str(rc)) - self.log.error("Please make sure your blid and password are " - "correct %s" % self.roombaName) - if self.mqttc is not None: - self.mqttc.disconnect() - sys.exit(1) - - def on_message(self, mosq, obj, msg): - # print(msg.topic + " " + str(msg.qos) + " " + str(msg.payload)) - if self.exclude != "": - if self.exclude in msg.topic: - return - - if self.indent == 0: - self.master_indent = max(self.master_indent, len(msg.topic)) - - log_string, json_data = self.decode_payload(msg.topic,msg.payload) - self.dict_merge(self.master_state, json_data) - - if self.pretty_print: - self.log.info("%-{:d}s : %s".format(self.master_indent) - % (msg.topic,log_string)) - else: - self.log.info("Received Roomba Data %s: %s, %s" - % (self.roombaName, str(msg.topic), str(msg.payload))) - - if self.raw: - self.publish(msg.topic, msg.payload) - else: - self.decode_topics(json_data) - - # default every 5 minutes - if time.time() - self.time > self.update_seconds: - self.log.info("Publishing master_state %s" % self.roombaName) - self.decode_topics(self.master_state) # publish all values - self.time = time.time() - - def on_publish(self, mosq, obj, mid): - pass - - def on_subscribe(self, mosq, obj, mid, granted_qos): - self.log.debug("Subscribed: %s %s" % (str(mid), str(granted_qos))) - - def on_disconnect(self, mosq, obj, rc): - self.roomba_connected = False - if rc != 0: - self.log.warn("Unexpected Disconnect From Roomba %s! - reconnecting" - % self.roombaName) - else: - self.log.info("Disconnected From Roomba %s" % self.roombaName) - - def on_log(self, mosq, obj, level, string): - self.log.info(string) - - def set_mqtt_client(self, mqttc=None, brokerFeedback=""): - self.mqttc = mqttc - if self.mqttc is not None: - if self.roombaName != "": - self.brokerFeedback = brokerFeedback + "/" + self.roombaName - else: - self.brokerFeedback = brokerFeedback - - def send_command(self, command): - self.log.info("Received COMMAND: %s" % command) - Command = OrderedDict() - Command["command"] = command - Command["time"] = self.totimestamp(datetime.datetime.now()) - Command["initiator"] = "localApp" - myCommand = json.dumps(Command) - self.log.info("Publishing Roomba Command : %s" % myCommand) - self.client.publish("cmd", myCommand) - - def set_preference(self, preference, setting): - self.log.info("Received SETTING: %s, %s" % (preference, setting)) - val = False - if setting.lower() == "true": - val = True - tmp = {preference: val} - Command = {"state": tmp} - myCommand = json.dumps(Command) - self.log.info("Publishing Roomba Setting : %s" % myCommand) - self.client.publish("delta", myCommand) - - def publish(self, topic, message): - if self.mqttc is not None and message is not None: - self.log.debug("Publishing item: %s: %s" - % (self.brokerFeedback + "/" + topic, message)) - self.mqttc.publish(self.brokerFeedback + "/" + topic, message) - - def set_options(self, raw=False, indent=0, pretty_print=False): - self.raw = raw - self.indent = indent - self.pretty_print = pretty_print - if self.raw: - self.log.info("Posting RAW data") - else: - self.log.info("Posting DECODED data") - - def enable_map(self, enable=False, mapSize="(800,1500,0,0,0,0)", - mapPath=".", iconPath = "./", roomOutline=True, - home_icon_file="home.png", - roomba_icon_file="roomba.png", - roomba_error_file="roombaerror.png", - roomba_cancelled_file="roombacancelled.png", - roomba_battery_file="roomba-charge.png", - bin_full_file="binfull.png", - roomba_size=(50,50), draw_edges = 30, auto_rotate=True): - ''' - Enable live map drawing. mapSize is x,y size, x,y offset of docking - station ((0,0) is the center of the image) final value is map rotation - (in case map is not straight up/down). These values depend on the - size/shape of the area Roomba covers. Offset depends on where you place - the docking station. This will need some experimentation to get right. - You can supply 32x32 icons for dock and roomba etc. If the files don't - exist, crude representations are made. If you specify home_icon_file as - None, then no dock is drawn. Draw edges attempts to draw straight lines - around the final (not live) map, and Auto_rotate (on/off) attempts to - line the map up vertically. These only work if you have openCV - installed. otherwise a PIL version is used, which is not as good (but - less CPU intensive). roomOutline enables the previous largest saved - outline to be overlayed on the map (so you can see where cleaning was - missed). This is on by default, but the alignment doesn't work so well, - so you can turn it off. - Returns map enabled True/False - ''' - - if not HAVE_PIL: #can't draw a map without PIL! - return False - - if Image.PILLOW_VERSION < "4.1.1": - print("WARNING: PIL version is %s, this is not the latest! you " - "can get bad memory leaks with old versions of PIL" - % Image.PILLOW_VERSION) - print("run: 'pip install --upgrade pillow' to fix this") - - self.drawmap = enable - if self.drawmap: - self.log.info("MAP: Maps Enabled") - self.mapSize = literal_eval(mapSize) - if len(mapSize) < 6: - self.log.error("mapSize is required, and is of the form " - "(800,1500,0,0,0,0) - (x,y size, x,y dock loc," - "theta1, theta2), map,roomba roatation") - self.drawmap = False - return False - self.angle = self.mapSize[4] - self.roomba_angle = self.mapSize[5] - self.mapPath = mapPath - if home_icon_file is None: - self.home_icon_file = None - else: - self.home_icon_file = os.path.join(iconPath, home_icon_file) - self.roomba_icon_file = os.path.join(iconPath, roomba_icon_file) - self.roomba_error_file = os.path.join(iconPath, roomba_error_file) - self.roomba_cancelled_file = os.path.join(iconPath, roomba_cancelled_file) - self.roomba_battery_file = os.path.join(iconPath, roomba_battery_file) - self.bin_full_file = os.path.join(iconPath, bin_full_file) - self.draw_edges = draw_edges // 10000 - self.auto_rotate = auto_rotate - if not roomOutline: - self.log.info("MAP: Not drawing Room Outline") - self.roomOutline = roomOutline - - self.initialise_map(roomba_size) - return True - return False - - def totimestamp(self, dt): - td = dt - datetime.datetime(1970, 1, 1) - return int(td.total_seconds()) - - def dict_merge(self, dct, merge_dct): - """ Recursive dict merge. Inspired by :meth:``dict.update()``, instead - of updating only top-level keys, dict_merge recurses down into dicts - nested to an arbitrary depth, updating keys. The ``merge_dct`` is - merged into ``dct``. - :param dct: dict onto which the merge is executed - :param merge_dct: dct merged into dct - :return: None - """ - for k, v in six.iteritems(merge_dct): - if (k in dct and isinstance(dct[k], dict) - and isinstance(merge_dct[k], Mapping)): - self.dict_merge(dct[k], merge_dct[k]) - else: - dct[k] = merge_dct[k] - - def decode_payload(self, topic, payload): - ''' - Format json for pretty printing, return string sutiable for logging, - and a dict of the json data - ''' - indent = self.master_indent + 31 #number of spaces to indent json data - - try: - # if it's json data, decode it (use OrderedDict to preserve keys - # order), else return as is... - json_data = json.loads( - payload.decode("utf-8").replace(":nan", ":NaN").\ - replace(":inf", ":Infinity").replace(":-inf", ":-Infinity"), - object_pairs_hook=OrderedDict) - # if it's not a dictionary, probably just a number - if not isinstance(json_data, dict): - return json_data, dict(json_data) - json_data_string = "\n".join((indent * " ") + i for i in \ - (json.dumps(json_data, indent = 2)).splitlines()) - - formatted_data = "Decoded JSON: \n%s" % (json_data_string) - - except ValueError: - formatted_data = payload - - if self.raw: - formatted_data = payload - - return formatted_data, dict(json_data) - - def decode_topics(self, state, prefix=None): - ''' - decode json data dict, and publish as individual topics to - brokerFeedback/topic the keys are concatinated with _ to make one unique - topic name strings are expressely converted to strings to avoid unicode - representations - ''' - for k, v in six.iteritems(state): - if isinstance(v, dict): - if prefix is None: - self.decode_topics(v, k) - else: - self.decode_topics(v, prefix+"_"+k) - else: - if isinstance(v, list): - newlist = [] - for i in v: - if isinstance(i, dict): - for ki, vi in six.iteritems(i): - newlist.append((str(ki), vi)) - else: - if isinstance(i, six.string_types): - i = str(i) - newlist.append(i) - v = newlist - if prefix is not None: - k = prefix+"_"+k - # all data starts with this, so it's redundant - k = k.replace("state_reported_","") - # save variables for drawing map - if k == "pose_theta": - self.co_ords["theta"] = v - if k == "pose_point_x": #x and y are reversed... - self.co_ords["y"] = v - if k == "pose_point_y": - self.co_ords["x"] = v - if k == "bin_full": - self.bin_full = v - if k == "cleanMissionStatus_error": - try: - self.error_message = self._ErrorMessages[v] - except KeyError as e: - self.log.warn( - "Error looking up Roomba error message %s" % e) - self.error_message = "Unknown Error number: %d" % v - self.publish("error_message", self.error_message) - if k == "cleanMissionStatus_phase": - self.previous_cleanMissionStatus_phase = \ - self.cleanMissionStatus_phase - self.cleanMissionStatus_phase = v - - self.publish(k, str(v)) - - if prefix is None: - self.update_state_machine() - - def update_state_machine(self, new_state = None): - ''' - Roomba progresses through states (phases), current identified states - are: - "" : program started up, no state yet - "run" : running on a Cleaning Mission - "hmUsrDock" : returning to Dock - "hmMidMsn" : need to recharge - "hmPostMsn" : mission completed - "charge" : chargeing - "stuck" : Roomba is stuck - "stop" : Stopped - "pause" : paused - - available states: - states = { "charge":"Charging", - "new":"New Mission", - "run":"Running", - "resume":"Running", - "hmMidMsn":"Recharging", - "recharge":"Recharging", - "stuck":"Stuck", - "hmUsrDock":"User Docking", - "dock":"Docking", - "dockend":"Docking - End Mission", - "cancelled":"Cancelled", - "stop":"Stopped", - "pause":"Paused", - "hmPostMsn":"End Mission", - "":None} - - Normal Sequence is "" -> charge -> run -> hmPostMsn -> charge - Mid mission recharge is "" -> charge -> run -> hmMidMsn -> charge - -> run -> hmPostMsn -> charge - Stuck is "" -> charge -> run -> hmPostMsn -> stuck - -> run/charge/stop/hmUsrDock -> charge - Start program during run is "" -> run -> hmPostMsn -> charge - - Need to identify a new mission to initialize map, and end of mission to - finalise map. - Assume charge -> run = start of mission (init map) - stuck - > charge = init map - Assume hmPostMsn -> charge = end of mission (finalize map) - Anything else = continue with existing map - ''' - - current_mission = self.current_state - - #if self.current_state == None: #set initial state here for debugging - # self.current_state = self.states["recharge"] - # self.show_final_map = False - - # deal with "bin full" timeout on mission - try: - if (self.master_state["state"]["reported"]["cleanMissionStatus"]["mssnM"] == "none" and - self.cleanMissionStatus_phase == "charge" and - (self.current_state == self.states["pause"] or - self.current_state == self.states["recharge"])): - self.current_state = self.states["cancelled"] - except KeyError: - pass - - if (self.current_state == self.states["charge"] and - self.cleanMissionStatus_phase == "run"): - self.current_state = self.states["new"] - elif (self.current_state == self.states["run"] and - self.cleanMissionStatus_phase == "hmMidMsn"): - self.current_state = self.states["dock"] - elif (self.current_state == self.states["dock"] and - self.cleanMissionStatus_phase == "charge"): - self.current_state = self.states["recharge"] - elif (self.current_state == self.states["recharge"] and - self.cleanMissionStatus_phase == "charge" and self.bin_full): - self.current_state = self.states["pause"] - elif (self.current_state == self.states["run"] and - self.cleanMissionStatus_phase == "charge"): - self.current_state = self.states["recharge"] - elif (self.current_state == self.states["recharge"] - and self.cleanMissionStatus_phase == "run"): - self.current_state = self.states["pause"] - elif (self.current_state == self.states["pause"] - and self.cleanMissionStatus_phase == "charge"): - self.current_state = self.states["pause"] - # so that we will draw map and can update recharge time - current_mission = None - elif (self.current_state == self.states["charge"] and - self.cleanMissionStatus_phase == "charge"): - # so that we will draw map and can update charge status - current_mission = None - elif ((self.current_state == self.states["stop"] or - self.current_state == self.states["pause"]) and - self.cleanMissionStatus_phase == "hmUsrDock"): - self.current_state = self.states["cancelled"] - elif ((self.current_state == self.states["hmUsrDock"] or - self.current_state == self.states["cancelled"]) and - self.cleanMissionStatus_phase == "charge"): - self.current_state = self.states["dockend"] - elif (self.current_state == self.states["hmPostMsn"] and - self.cleanMissionStatus_phase == "charge"): - self.current_state = self.states["dockend"] - elif (self.current_state == self.states["dockend"] and - self.cleanMissionStatus_phase == "charge"): - self.current_state = self.states["charge"] - - else: - self.current_state = self.states[self.cleanMissionStatus_phase] - - if new_state is not None: - self.current_state = self.states[new_state] - self.log.info("set current state to: %s" % (self.current_state)) - - if self.current_state != current_mission: - self.log.info("updated state to: %s" % (self.current_state)) - - self.publish("state", self.current_state) - self.draw_map(current_mission != self.current_state) - - def make_transparent(self, image, colour=None): - ''' - take image and make white areas transparent - return transparent image - ''' - image = image.convert("RGBA") - datas = image.getdata() - newData = [] - for item in datas: - # white (ish) - if item[0] >= 254 and item[1] >= 254 and item[2] >= 254: - newData.append(self.transparent) - else: - if colour: - newData.append(colour) - else: - newData.append(item) - - image.putdata(newData) - return image - - def make_icon(self, input="./roomba.png", output="./roomba_mod.png"): - #utility function to make roomba icon from generic roomba icon - if not HAVE_PIL: #drawing library loaded? - self.log.error("PIL module not loaded") - return None - try: - roomba = Image.open(input).convert('RGBA') - roomba = roomba.rotate(90, expand=False) - roomba = self.make_transparent(roomba) - draw_wedge = ImageDraw.Draw(roomba) - draw_wedge.pieslice( - [(5,0),(roomba.size[0]-5,roomba.size[1])], - 175, 185, fill="red", outline="red") - roomba.save(output, "PNG") - return roomba - except Exception as e: - self.log.error("ERROR: %s" % e) - return None - - def load_icon(self, filename="", icon_name=None, fnt=None, size=(32,32), - base_icon=None): - ''' - Load icon from file, or draw icon if file not found. - returns icon object - ''' - if icon_name is None: - return None - - try: - icon = Image.open(filename).convert('RGBA').resize( - size,Image.ANTIALIAS) - icon = self.make_transparent(icon) - except IOError as e: - self.log.warn("error loading %s: %s, using default icon instead" - % (icon_name,e)) - if base_icon is None: - icon = Image.new('RGBA', size, self.transparent) - else: - icon = base_icon - - draw_icon = ImageDraw.Draw(icon) - - if icon_name == "roomba": - if base_icon is None: - draw_icon.ellipse([(5,5),(icon.size[0]-5,icon.size[1]-5)], - fill="green", outline="black") - draw_icon.pieslice([(5,5),(icon.size[0]-5,icon.size[1]-5)], - 355, 5, fill="red", outline="red") - elif icon_name == "stuck": - if base_icon is None: - draw_icon.ellipse([(5,5),(icon.size[0]-5,icon.size[1]-5)], - fill="green", outline="black") - draw_icon.pieslice([(5,5),(icon.size[0]-5,icon.size[1]-5)], - 175, 185, fill="red", outline="red") - draw_icon.polygon([( - icon.size[0]//2,icon.size[1]), (0, 0), (0,icon.size[1])], - fill = 'red') - if fnt is not None: - draw_icon.text((4,-4), "!", font=fnt, - fill=(255,255,255,255)) - elif icon_name == "cancelled": - if base_icon is None: - draw_icon.ellipse([(5,5),(icon.size[0]-5,icon.size[1]-5)], - fill="green", outline="black") - draw_icon.pieslice([(5,5),(icon.size[0]-5,icon.size[1]-5)], - 175, 185, fill="red", outline="red") - if fnt is not None: - draw_icon.text((4,-4), "X", font=fnt, fill=(255,0,0,255)) - elif icon_name == "bin full": - draw_icon.rectangle([ - icon.size[0]-10, icon.size[1]-10, - icon.size[0]+10, icon.size[1]+10], - fill = "grey") - if fnt is not None: - draw_icon.text((4,-4), "F", font=fnt, - fill=(255,255,255,255)) - elif icon_name == "battery": - draw_icon.rectangle([icon.size[0]-10, icon.size[1]-10, - icon.size[0]+10,icon.size[1]+10], fill = "orange") - if fnt is not None: - draw_icon.text((4,-4), "B", font=fnt, - fill=(255,255,255,255)) - elif icon_name == "home": - draw_icon.rectangle([0,0,32,32], fill="red", outline="black") - if fnt is not None: - draw_icon.text((4,-4), "D", font=fnt, - fill=(255,255,255,255)) - else: - icon = None - #rotate icon 180 degrees - icon = icon.rotate(180-self.angle, expand=False) - return icon - - def initialise_map(self, roomba_size): - ''' - Initialize all map items (base maps, overlay, icons fonts etc) - ''' - # get base image of Roomba path - if self.base is None: - try: - self.log.info("MAP: openening existing line image") - self.base = Image.open( - self.mapPath + '/' + self.roombaName + 'lines.png')\ - .convert('RGBA') - if self.base.size != (self.mapSize[0], self.mapSize[1]): - raise IOError("Image is wrong size") - except IOError as e: - self.base = Image.new( - 'RGBA', - (self.mapSize[0], self.mapSize[1]), self.transparent) - self.log.warn("MAP: line image problem: %s: created new image" - % e) - - try: - self.log.info("MAP: openening existing problems image") - self.roomba_problem = Image.open( - self.mapPath + '/'+self.roombaName + 'problems.png')\ - .convert('RGBA') - if self.roomba_problem.size != self.base.size: - raise IOError("Image is wrong size") - except IOError as e: - self.roomba_problem = Image.new( - 'RGBA', self.base.size, self.transparent) - self.log.warn("MAP: problems image problem: %s: created new " - "image" % e) - - try: - self.log.info("MAP: openening existing map no text image") - self.previous_map_no_text = None - self.map_no_text = Image.open( - self.mapPath + '/' + self.roombaName + 'map_notext.png')\ - .convert('RGBA') - if self.map_no_text.size != self.base.size: - raise IOError("Image is wrong size") - except IOError as e: - self.map_no_text = None - self.log.warn("MAP: map no text image problem: %s: set to None" - % e) - # save x and y center of image, for centering of final map image - self.cx = self.base.size[0] - self.cy = self.base.size[1] - - # get a font - if self.fnt is None: - try: - self.fnt = ImageFont.truetype('FreeMono.ttf', 40) - except IOError as e: - self.log.warn("error loading font: %s, loading default font" - % e) - self.fnt = ImageFont.load_default() - - #set dock home position - if self.home_pos is None: - self.home_pos = ( - self.mapSize[0] // 2 + self.mapSize[2], - self.mapSize[1] // 2 + self.mapSize[3]) - self.log.info("MAP: home_pos: (%d,%d)" - % (self.home_pos[0], self.home_pos[1])) - - #get icons - if self.roomba_icon is None: - self.roomba_icon = self.load_icon( - filename=self.roomba_icon_file, icon_name="roomba", - fnt=self.fnt, size=roomba_size, base_icon=None) - - if self.roomba_error_icon is None: - self.roomba_error_icon = self.load_icon( - filename=self.roomba_error_file, icon_name="stuck", - fnt=self.fnt, size=roomba_size, base_icon=self.roomba_icon) - - if self.roomba_cancelled_icon is None: - self.roomba_cancelled_icon = self.load_icon( - filename=self.roomba_cancelled_file, icon_name="cancelled", - fnt=self.fnt, size=roomba_size, base_icon=self.roomba_icon) - - if self.roomba_battery_icon is None: - self.roomba_battery_icon = self.load_icon( - filename=self.roomba_battery_file, icon_name="battery", - fnt=self.fnt, size=roomba_size, base_icon=self.roomba_icon) - - if self.dock_icon is None and self.home_icon_file is not None: - self.dock_icon = self.load_icon( - filename=self.home_icon_file, icon_name="home", fnt=self.fnt) - self.dock_position = ( - self.home_pos[0] - self.dock_icon.size[0] // 2, - self.home_pos[1] - self.dock_icon.size[1] // 2) - - if self.bin_full_icon is None: - self.bin_full_icon = self.load_icon( - filename=self.bin_full_file, icon_name="bin full", - fnt=self.fnt, size=roomba_size, base_icon=self.roomba_icon) - - self.log.info("MAP: Initialisation complete") - - def transparent_paste(self, base_image, icon, position): - ''' - needed because PIL pasting of transparent imges gives weird results - ''' - image = Image.new('RGBA', self.base.size, self.transparent) - image.paste(icon,position) - base_image = Image.alpha_composite(base_image, image) - return base_image - - def zero_coords(self): - ''' - returns dictionary with default zero coords - ''' - return {"x": 0, "y": 0, "theta": 180} - - def offset_coordinates(self, old_co_ords, new_co_ords): - ''' - offset coordinates according to mapSize settings, with 0,0 as center - ''' - x_y = (new_co_ords["x"] + self.mapSize[0] // 2 + self.mapSize[2], - new_co_ords["y"] + self.mapSize[1] // 2 + self.mapSize[3]) - old_x_y = (old_co_ords["x"]+self.mapSize[0] // 2 + self.mapSize[2], - old_co_ords["y"]+self.mapSize[1]//2+self.mapSize[3]) - - theta = int(new_co_ords["theta"] - 90 + self.roomba_angle) - while theta > 359: theta = 360 - theta - while theta < 0: theta = 360 + theta - - return old_x_y, x_y, theta - - def get_roomba_pos(self, x_y): - ''' - calculate roomba position as list - ''' - return [x_y[0] - self.roomba_icon.size[0] // 2, - x_y[1] - self.roomba_icon.size[1] // 2, - x_y[0] + self.roomba_icon.size[0] // 2, - x_y[1] + self.roomba_icon.size[1] // 2] - - def draw_vacuum_lines(self, image, old_x_y, x_y, theta, colour="lawngreen"): - ''' - draw lines on image from old_x_y to x_y reepresenting vacuum coverage, - taking into account angle theta (roomba angle). - ''' - lines = ImageDraw.Draw(image) - if x_y != old_x_y: - self.log.info("MAP: drawing line: %s, %s" % (old_x_y, x_y)) - lines.line([old_x_y, x_y], fill=colour, - width=self.roomba_icon.size[0] // 2) - #draw circle over roomba vacuum area to give smooth edges. - arcbox = [x_y[0]-self.roomba_icon.size[0] // 4, - x_y[1]-self.roomba_icon.size[0] // 4, - x_y[0]+self.roomba_icon.size[0] // 4, - x_y[1]+self.roomba_icon.size[0] // 4] - lines.ellipse(arcbox, fill=colour) - - def draw_text(self, image, display_text, fnt, pos=(0,0), - colour=(0,0,255,255), rotate=False): - #draw text - (WARNING old versions of PIL have huge memory leak here!) - if display_text is None: return - self.log.info("MAP: writing text: pos: %s, text: %s" - % (pos, display_text)) - if rotate: - txt = Image.new('RGBA', (fnt.getsize(display_text)), - self.transparent) - text = ImageDraw.Draw(txt) - # draw text rotated 180 degrees... - text.text((0,0), display_text, font=fnt, fill=colour) - image.paste(txt.rotate(180-self.angle, expand=True), pos) - else: - text = ImageDraw.Draw(image) - text.text(pos, display_text, font=fnt, fill=colour) - - def draw_map(self, force_redraw=False): - ''' - Draw map of Roomba cleaning progress - ''' - if ((self.co_ords != self.previous_co_ords or - self.cleanMissionStatus_phase != - self.previous_cleanMissionStatus_phase) - or force_redraw) and self.drawmap: - self.render_map(self.co_ords, self.previous_co_ords) - self.previous_co_ords = self.co_ords.copy() - self.previous_cleanMissionStatus_phase = \ - self.cleanMissionStatus_phase - - def render_map(self, new_co_ords, old_co_ords): - ''' - draw map - ''' - draw_final = False - stuck = False - cancelled = False - bin_full = False - battery_low = False - - # program just started, and we don't have phase yet. - if self.current_state is None: - return - - if self.show_final_map == False: - self.log.info("MAP: received: new_co_ords: %s old_co_ords: %s " - "phase: %s, state: %s" % ( - new_co_ords, old_co_ords, - self.cleanMissionStatus_phase, self.current_state)) - - if self.current_state == self.states["charge"]: - self.log.info("MAP: ignoring new co-ords in charge phase") - new_co_ords = old_co_ords = self.zero_coords() - self.display_text = "Charging: Battery: " + \ - str(self.master_state["state"]["reported"]["batPct"]) + "%" - if self.bin_full: - self.display_text = "Bin Full," + \ - self.display_text.replace("Charging", "Not Ready") - if (self.last_completed_time is None or time.time() - - self.last_completed_time > 3600): - self.save_text_and_map_on_whitebg(self.map_no_text) - draw_final = True - - elif self.current_state == self.states["recharge"]: - self.log.info("MAP: ignoring new co-ords in recharge phase") - new_co_ords = old_co_ords = self.zero_coords() - self.display_text = "Recharging:" + " Time: " + \ - str(self.master_state["state"]["reported"]["cleanMissionStatus"]["rechrgM"]) + "m" - if self.bin_full: - self.display_text = "Bin Full," + self.display_text - self.save_text_and_map_on_whitebg(self.map_no_text) - - elif self.current_state == self.states["pause"]: - self.log.info("MAP: ignoring new co-ords in pause phase") - new_co_ords = old_co_ords - self.display_text = "Paused: " + \ - str(self.master_state["state"]["reported"]["cleanMissionStatus"]["mssnM"]) + \ - "m, Bat: "+ str(self.master_state["state"]["reported"]["batPct"]) + \ - "%" - if self.bin_full: - self.display_text = "Bin Full," + self.display_text - # assume roomba is docked... - new_co_ords = old_co_ords = self.zero_coords() - self.save_text_and_map_on_whitebg(self.map_no_text) - - elif self.current_state == self.states["hmPostMsn"]: - self.display_text = "Completed: " + \ - time.strftime("%a %b %d %H:%M:%S") - self.log.info("MAP: end of mission") - - elif self.current_state == self.states["dockend"]: - self.log.info("MAP: mission completed: ignoring new co-ords in " - "docking phase") - new_co_ords = old_co_ords = self.zero_coords() - self.draw_final_map(True) - draw_final = True - - elif (self.current_state == self.states["run"] or - self.current_state == self.states["stop"] or - self.current_state == self.states["pause"]): - if self.current_state == self.states["run"]: - self.display_text = self.states["run"] + " Time: " + \ - str(self.master_state["state"]["reported"]["cleanMissionStatus"]["mssnM"]) + \ - "m, Bat: "+ str(self.master_state["state"]["reported"]["batPct"]) + \ - "%" - else: - self.display_text = None - self.show_final_map = False - - elif self.current_state == self.states["new"]: - self.angle = self.mapSize[4] #reset angle - self.base = Image.new('RGBA', self.base.size, self.transparent) - # overlay for roomba problem position - self.roomba_problem = Image.new('RGBA', self.base.size, - self.transparent) - self.show_final_map = False - self.display_text = None - self.log.info("MAP: created new image at start of new run") - - elif self.current_state == self.states["stuck"]: - self.display_text = "STUCK!: " + time.strftime("%a %b %d %H:%M:%S") - self.draw_final_map(True) - draw_final = True - stuck = True - - elif self.current_state == self.states["cancelled"]: - self.display_text = "Cancelled: " + \ - time.strftime("%a %b %d %H:%M:%S") - cancelled = True - - elif self.current_state == self.states["dock"]: - self.display_text = "Docking" - if self.bin_full: - self.display_text = "Bin Full," + self.display_text - bin_full = True - else: - self.display_text = "Battery low: " + \ - str(self.master_state["state"]["reported"]["batPct"]) + \ - "%, " + self.display_text - battery_low = True - - else: - self.log.warn("MAP: no special handling for state: %s" - % self.current_state) - - if self.base is None: - self.log.warn("MAP: no image, exiting...") - return - - if self.display_text is None: - self.display_text = self.current_state - - if self.show_final_map: #just display final map - not live - self.log.debug("MAP: not updating map - Roomba not running") - return - - if self.debug: - # debug final map (careful, uses a lot of CPU power!) - self.draw_final_map() - - #calculate co-ordinates, with 0,0 as center - old_x_y, x_y, theta = self.offset_coordinates(old_co_ords, new_co_ords) - roomba_pos = self.get_roomba_pos(x_y) - - self.log.info("MAP: old x,y: %s new x,y: %s theta: %s roomba pos: %s" % - (old_x_y, x_y, theta, roomba_pos)) - - #draw lines - self.draw_vacuum_lines(self.base, old_x_y, x_y, theta) - - # make a blank image for the text and Roomba overlay, initialized to - # transparent text color - roomba_sprite = Image.new('RGBA', self.base.size, self.transparent) - - #draw roomba - self.log.info("MAP: drawing roomba: pos: %s, theta: %s" - % (roomba_pos, theta)) - if stuck: - self.log.info("MAP: Drawing stuck Roomba") - self.roomba_problem.paste(self.roomba_error_icon,roomba_pos) - if cancelled: - self.log.info("MAP: Drawing cancelled Roomba") - self.roomba_problem.paste(self.roomba_cancelled_icon,roomba_pos) - if bin_full: - self.log.info("MAP: Drawing full bin") - self.roomba_problem.paste(self.bin_full_icon,roomba_pos) - if battery_low: - self.log.info("MAP: Drawing low battery Roomba") - self.roomba_problem.paste(self.roomba_battery_icon,roomba_pos) - - roomba_sprite = self.transparent_paste( - roomba_sprite, - self.roomba_icon.rotate(theta, expand=False), roomba_pos) - - # paste dock over roomba_sprite - if self.dock_icon is not None: - roomba_sprite = self.transparent_paste( - roomba_sprite, self.dock_icon, self.dock_position) - - # save base lines - self.base.save(self.mapPath + '/' + self.roombaName + 'lines.png', - "PNG") - # save problem overlay - self.roomba_problem.save(self.mapPath + '/' + self.roombaName + \ - 'problems.png', "PNG") - if self.roomOutline or self.auto_rotate: - # draw room outline (saving results if this is a final map) update - # x,y and angle if auto_rotate - self.draw_room_outline(draw_final) - # merge room outline into base - if self.roomOutline: - #if we want to draw the room outline - out = Image.alpha_composite(self.base, self.room_outline) - else: - out = self.base - #merge roomba lines (trail) with base - out = Image.alpha_composite(out, roomba_sprite) - #merge problem location for roomba into out - out = Image.alpha_composite(out, self.roomba_problem) - if draw_final and self.auto_rotate: - #translate image to center it if auto_rotate is on - self.log.info("MAP: calculation of center: (%d,%d), " - "translating final map to center it, x:%d, y:%d " - "deg: %.2f" % ( - self.cx, self.cy, self.cx - out.size[0] // 2, - self.cy - out.size[1] // 2, - self.angle)) - out = out.transform( - out.size, Image.AFFINE, - (1, 0, self.cx-out.size[0] // 2, - 0, 1, self.cy-out.size[1] // 2)) - # map is upside down, so rotate 180 degrees, and size to fit (NW 12/4/2018 fixed bug causing distorted maps when rotation is not 0) - #out_rotated = out.rotate(180 + self.angle, expand=True).resize(self.base.size) #old version - out_rotated = out.rotate(180, expand=False) - # save composite image - self.save_text_and_map_on_whitebg(out_rotated) - if draw_final: - self.show_final_map = True # prevent re-drawing of map until reset - - def save_text_and_map_on_whitebg(self, map): - # if no map or nothing changed - if map is None or (map == self.previous_map_no_text and - self.previous_display_text == self.display_text): - return - self.map_no_text = map - self.previous_map_no_text = self.map_no_text - self.previous_display_text = self.display_text - self.map_no_text.save(self.mapPath + '/' + self.roombaName + - 'map_notext.png', "PNG") - final = Image.new('RGBA', self.base.size, (255,255,255,255)) # white - # paste onto a white background, so it's easy to see - final = Image.alpha_composite(final, map) - final = final.rotate(self.angle, expand=True) #(NW 12/4/2018 fixed bug causing distorted maps when rotation is not 0 - moved rotate to here) - # draw text - self.draw_text(final, self.display_text, self.fnt) - final.save(self.mapPath + '/'+self.roombaName + '_map.png', "PNG") - # try to avoid other programs reading file while writing it, - # rename should be atomic. - os.rename(self.mapPath + '/' + self.roombaName + '_map.png', - self.mapPath + '/' + self.roombaName + 'map.png') - - def ScaleRotateTranslate(self, image, angle, center=None, new_center=None, - scale=None, expand=False): - ''' - experimental - not used yet - ''' - if center is None: - return image.rotate(angle, expand) - angle = -angle / 180.0 * math.pi - nx, ny = x, y = center - if new_center != center: - (nx, ny) = new_center - sx = sy = 1.0 - if scale: - (sx, sy) = scale - cosine = math.cos(angle) - sine = math.sin(angle) - a = cosine / sx - b = sine / sx - c = x - nx * a - ny * b - d = -sine / sy - e = cosine / sy - f = y - nx * d - ny * e - return image.transform(image.size, Image.AFFINE, - (a,b,c,d,e,f), resample=Image.BICUBIC) - - def match_outlines(self, orig_image, skewed_image): - orig_image = np.array(orig_image) - skewed_image = np.array(skewed_image) - try: - surf = cv2.xfeatures2d.SURF_create(400) - except Exception: - surf = cv2.SIFT(400) - kp1, des1 = surf.detectAndCompute(orig_image, None) - kp2, des2 = surf.detectAndCompute(skewed_image, None) - - FLANN_INDEX_KDTREE = 0 - index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5) - search_params = dict(checks=50) - flann = cv2.FlannBasedMatcher(index_params, search_params) - matches = flann.knnMatch(des1, des2, k=2) - - # store all the good matches as per Lowe's ratio test. - good = [] - for m, n in matches: - if m.distance < 0.7 * n.distance: - good.append(m) - - MIN_MATCH_COUNT = 10 - if len(good) > MIN_MATCH_COUNT: - src_pts = np.float32([kp1[m.queryIdx].pt for m in good - ]).reshape(-1, 1, 2) - dst_pts = np.float32([kp2[m.trainIdx].pt for m in good - ]).reshape(-1, 1, 2) - - M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) - - # see https://ch.mathworks.com/help/images/examples/find-image-rotation-and-scale-using-automated-feature-matching.html for details - ss = M[0, 1] - sc = M[0, 0] - scaleRecovered = math.sqrt(ss * ss + sc * sc) - thetaRecovered = math.atan2(ss, sc) * 180 / math.pi - self.log.info("MAP: Calculated scale difference: %.2f, " - "Calculated rotation difference: %.2f" % - (scaleRecovered, thetaRecovered)) - - #deskew image - im_out = cv2.warpPerspective(skewed_image, np.linalg.inv(M), - (orig_image.shape[1], orig_image.shape[0])) - return im_out - - else: - self.log.warn("MAP: Not enough matches are found - %d/%d" - % (len(good), MIN_MATCH_COUNT)) - return skewed_image - - def draw_room_outline(self, overwrite=False, colour=(64,64,64,255), - width=1): - ''' - draw room outline - ''' - self.log.info("MAP: checking room outline") - if HAVE_CV2: - if self.room_outline_contour is None or overwrite: - try: - self.room_outline_contour = np.load( - self.mapPath + '/' + self.roombaName + 'room.npy') - except IOError as e: - self.log.warn("Unable to load room outline: %s, setting " - "to 0" % e) - self.room_outline_contour = np.array( - [(0,0),(0,0),(0,0),(0,0)], dtype=np.int) - - try: - self.log.info("MAP: openening existing room outline image") - self.room_outline = Image.open( - self.mapPath + '/' + self.roombaName + 'room.png').\ - convert('RGBA') - if self.room_outline.size != self.base.size: - raise IOError("Image is wrong size") - except IOError as e: - self.room_outline = Image.new( - 'RGBA', self.base.size, self.transparent) - self.log.warn("MAP: room outline image problem: %s: " - "set to New" % e) - - room_outline_area = cv2.contourArea(self.room_outline_contour) - # edgedata = cv2.add( - # np.array(self.base.convert('L'), dtype=np.uint8), - # np.array(self.room_outline.convert('L'), dtype=np.uint8)) - edgedata = np.array(self.base.convert('L')) - # find external contour - _, contours, _ = self.findContours( - edgedata,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE) - if contours[0] is None: return - if len(contours[0]) < 5: return - max_area = cv2.contourArea(contours[0]) - # experimental shape matching - # note cv2.cv.CV_CONTOURS_MATCH_I1 does not exist in CV 3.0, - # so just use 1 - match = cv2.matchShapes( - self.room_outline_contour,contours[0],1,0.0) - self.log.info("MAP: perimeter/outline match is: %.4f" % match) - # if match is less than 0.35 - shapes are similar (but if it's 0 - - # then they are the same shape..) try auto rotating map to fit. - if match < 0.35 and match > 0: - #self.match_outlines(self.room_outline, self.base) - pass - if max_area > room_outline_area: - self.log.info("MAP: found new outline perimiter") - self.room_outline_contour = contours[0] - perimeter = cv2.arcLength(self.room_outline_contour,True) - outline = Image.new('RGBA',self.base.size,self.transparent) - edgeimage = np.array(outline) # make blank RGBA image array - # self.draw_edges is the max deviation from a line (set to 0.3%) - # you can fiddle with this - approx = cv2.approxPolyDP( - self.room_outline_contour, - self.draw_edges * perimeter, - True) - # outline with grey, width 1 - cv2.drawContours(edgeimage,[approx] , -1, colour, width) - self.room_outline = Image.fromarray(edgeimage) - - else: - if self.room_outline is None or overwrite: - try: - self.log.info("MAP: openening existing room outline image") - self.room_outline = Image.open( - self.mapPath + '/' + self.roombaName + 'room.png').\ - convert('RGBA') - if self.room_outline.size != self.base.size: - raise IOError("Image is wrong size") - except IOError as e: - self.room_outline = Image.new( - 'RGBA', self.base.size, self.transparent) - self.log.warn("MAP: room outline image problem: %s: " - "set to New" % e) - edges = ImageOps.invert(self.room_outline.convert('L')) - edges.paste(self.base) - edges = edges.convert('L').filter(ImageFilter.SMOOTH_MORE) - edges = ImageOps.invert(edges.filter(ImageFilter.FIND_EDGES)) - self.room_outline = self.make_transparent(edges, (0, 0, 0, 255)) - - if overwrite or self.debug: - # save room outline - self.room_outline.save( - self.mapPath+'/'+self.roombaName+'room.png', "PNG") - if HAVE_CV2: - # save room outline contour as numpy array - np.save(self.mapPath + '/' + self.roombaName + 'room.npy', - self.room_outline_contour) - if self.auto_rotate: - # update outline centre - self.get_image_parameters( - image=self.room_outline, contour=self.room_outline_contour, - final=overwrite) - self.log.info("MAP: calculation of center: (%d,%d), " - "translating room outline to center it, " - "x:%d, y:%d deg: %.2f" % ( - self.cx, self.cy, - self.cx - self.base.size[0] // 2, - self.cy - self.base.size[1] // 2, - self.angle)) - # center room outline, same as map. - self.room_outline = self.room_outline.transform( - self.base.size, Image.AFFINE, - (1, 0, self.cx - self.base.size[0] // 2, - 0, 1, self.cy-self.base.size[1]//2)) - self.log.info("MAP: Wrote new room outline files") - - def PIL_get_image_parameters(self, image=None, start=90, end = 0, step=-1, - recursion=0): - ''' - updates angle of image, and centre using PIL. - NOTE: this assumes the floorplan is rectangular! if you live in a - lighthouse, the angle will not be valid! - input is PIL image - ''' - if image is not None and HAVE_PIL: - imbw = image.convert('L') - max_area = self.base.size[0] * self.base.size[1] - x_y = (self.base.size[0] // 2, self.base.size[1] // 2) - angle = self.angle - div_by_10 = False - if step >=10 or step <=-10: - step /= 10 - div_by_10 = True - for try_angle in range(start, end, step): - if div_by_10: - try_angle /= 10.0 - #rotate image and resize to fit - im = imbw.rotate(try_angle, expand=True) - box = im.getbbox() - if box is not None: - area = (box[2]-box[0]) * (box[3]-box[1]) - if area < max_area: - angle = try_angle - x_y = ((box[2] - box[0]) // 2 + box[0], - (box[3] - box[1]) // 2 + box[1]) - max_area = area - - if recursion >= 1: - return x_y, angle - - x_y, angle = self.PIL_get_image_parameters( - image, - (angle + 1) * 10, - (angle - 1) * 10, -10, - recursion + 1) - - # self.log.info("MAP: PIL: image center: " - # "x:%d, y:%d, angle %.2f" % (x_y[0], x_y[1], angle)) - return x_y, angle - - def get_image_parameters(self, image=None, contour=None, final=False): - ''' - updates angle of image, and centre using cv2 or PIL. - NOTE: this assumes the floorplan is rectangular! if you live in a - lighthouse, the angle will not be valid! - input is cv2 contour or PIL image - routines find the minnimum area rectangle that fits the image outline - ''' - if contour is not None and HAVE_CV2: - # find minnimum area rectangle that fits - # returns (x,y), (width, height), theta - where (x,y) is the center - x_y,l_w,angle = cv2.minAreaRect(contour) - - elif image is not None and HAVE_PIL: - x_y, angle = self.PIL_get_image_parameters(image) - - else: - return - - if angle < self.angle - 45: - angle += 90 - if angle > 45-self.angle: - angle -= 90 - - if final: - self.cx = x_y[0] - self.cy = x_y[1] - self.angle = angle - self.log.info("MAP: image center: x:%d, y:%d, angle %.2f" % - (x_y[0], x_y[1], angle)) - - def angle_between(self, p1, p2): - ''' - clockwise angle between two points in degrees - ''' - if HAVE_CV2: - ang1 = np.arctan2(*p1[::-1]) - ang2 = np.arctan2(*p2[::-1]) - return np.rad2deg((ang1 - ang2) % (2 * np.pi)) - else: - side1=math.sqrt(((p1[0] - p2[0]) ** 2)) - side2=math.sqrt(((p1[1] - p2[1]) ** 2)) - return math.degrees(math.atan(side2/side1)) - - def findContours(self,image,mode,method): - ''' - Version independent find contours routine. Works with OpenCV 2 or 3. - Returns modified image (with contours applied), contours list, hierarchy - ''' - ver = int(cv2.__version__.split(".")[0]) - im = image.copy() - if ver == 2: - contours, hierarchy = cv2.findContours(im,mode,method) - return im, contours, hierarchy - else: - im_cont, contours, hierarchy = cv2.findContours(im,mode,method) - return im_cont, contours, hierarchy - - def draw_final_map(self, overwrite=False): - ''' - draw map with outlines at end of mission. Called when mission has - finished and Roomba has docked - ''' - merge = Image.new('RGBA',self.base.size,self.transparent) - if HAVE_CV2: - # NOTE: this is CPU intensive! - edgedata = np.array(self.base.convert('L'), dtype=np.uint8) - # find all contours - _, contours, _ = self.findContours( - edgedata,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) - # zero edge data for later use - edgedata.fill(0) - max_perimeter = 0 - max_contour = None - for cnt in contours: - perimeter = cv2.arcLength(cnt,True) - if perimeter >= max_perimeter: - max_contour = cnt # get the contour with maximum length - max_perimeter = perimeter - if max_contour is None: return - if len(max_contour) < 5: return - try: - contours.remove(max_contour) # remove max contour from list - except ValueError: - self.log.warn("MAP: unable to remove contour") - pass - - mask = np.full(edgedata.shape, 255, dtype=np.uint8) # white - # create mask (of other contours) in black - cv2.drawContours(mask,contours, -1, 0, -1) - - # self.draw_edges is the max deviation from a line - # you can fiddle with this in enable_map - approx = cv2.approxPolyDP(max_contour, - self.draw_edges * max_perimeter,True) - - bgimage = np.array(merge) # make blank RGBA image array - # draw contour and fill with "lawngreen" - cv2.drawContours(bgimage,[approx] , -1, (124, 252, 0, 255), -1) - # mask image with internal contours - bgimage = cv2.bitwise_and(bgimage,bgimage,mask = mask) - # not dure if you really need this - uncomment if you want the - # area outlined. - # draw longest contour aproximated to lines (in black), width 1 - cv2.drawContours(edgedata,[approx] , -1, (255), 1) - - outline = Image.fromarray(edgedata) # outline - base = Image.fromarray(bgimage) # filled background image - else: - base = self.base.filter(ImageFilter.SMOOTH_MORE) - # draw edges at end of mission - outline = base.convert('L').filter(ImageFilter.FIND_EDGES) - # outline = ImageChops.subtract( - # base.convert('L').filter(ImageFilter.EDGE_ENHANCE), - # base.convert('L')) - - edges = ImageOps.invert(outline) - edges = self.make_transparent(edges, (0, 0, 0, 255)) - if self.debug: - edges.save(self.mapPath+'/'+self.roombaName+'edges.png', "PNG") - merge = Image.alpha_composite(merge,base) - merge = Image.alpha_composite(merge,edges) - if overwrite: - self.log.info("MAP: Drawing final map") - self.last_completed_time = time.time() - self.base=merge - - if self.debug: - merge_rotated = merge.rotate(180+self.angle, expand=True) - merge_rotated.save( - self.mapPath+'/'+self.roombaName+'final_map.png', "PNG") diff --git a/roomba_980/roomba/roomba_direct.py b/roomba_980/roomba/roomba_direct.py deleted file mode 100755 index 8e6aef6ab..000000000 --- a/roomba_980/roomba/roomba_direct.py +++ /dev/null @@ -1,599 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from __future__ import print_function -from ast import literal_eval -from logging.handlers import RotatingFileHandler -import sys -if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] < 5): #added for python 2.7 and < 3.4 fix NW 15/9/2017 - import roomba - try: - from roomba import Password - except ImportError: - from password import Password -else: - from roomba import roomba - try: - from roomba.password import Password - except ImportError: - from password import Password -import argparse -import json -import logging -import os -import six -import socket -import time -# Import trickery -global HAVE_CV2 -global HAVE_MQTT -global HAVE_PIL -HAVE_CV2 = HAVE_MQTT = HAVE_PIL = False #fix for if neither PIL or OPENCV is installed (RPI versions) NW 3/2/2018 -try: - import configparser -except: - from six.moves import configparser -try: - import paho.mqtt.client as mqtt - HAVE_MQTT = True -except ImportError: - print("paho mqtt client not found") -try: - import cv2 - HAVE_CV2 = True -except ImportError: - print("CV or numpy module not found, falling back to PIL") - -# NOTE: MUST use Pillow Pillow 4.1.1 to avoid some horrible memory leaks in the -# text handling! -try: - from PIL import Image - HAVE_PIL = True -except ImportError: - print("PIL module not found, maps are disabled") - -def parse_args(): - default_icon_path = os.path.join(os.path.dirname(__file__), 'res') - #-------- Command Line ----------------- - parser = argparse.ArgumentParser( - description='Forward MQTT data from Roomba 980 to local MQTT broker') - parser.add_argument( - '-f', '--configfile', - action='store', - type=str, - default="./config.ini", - help='config file name (default: ./config.ini)') - parser.add_argument( - '-n', '--roombaName', - action='store', - type=str, - default="", help='optional Roomba name (default: "")') - parser.add_argument( - '-t', '--topic', - action='store', - type=str, - default="#", - help='Roomba MQTT Topic to subscribe to (can use wildcards # and ' - '+ default: #)') - parser.add_argument( - '-T', '--brokerFeedback', - action='store', - type=str, - default="/roomba/feedback", - help='Topic on broker to publish feedback to (default: ' - '/roomba/feedback)') - parser.add_argument( - '-C', '--brokerCommand', - action='store', - type=str, - default="/roomba/command", - help='Topic on broker to publish commands to (default: ' - '/roomba/command)') - parser.add_argument( - '-S', '--brokerSetting', - action='store', - type=str, - default="/roomba/setting", - help='Topic on broker to publish settings to (default: ' - '/roomba/setting)') - parser.add_argument( - '-b', '--broker', - action='store', - type=str, - default=None, - help='ipaddress of MQTT broker (default: None)') - parser.add_argument( - '-p', '--port', - action='store', - type=int, - default=1883, - help='MQTT broker port number (default: 1883)') - parser.add_argument( - '-U', '--user', - action='store', - type=str, - default=None, - help='MQTT broker user name (default: None)') - parser.add_argument( - '-P', '--password', - action='store', - type=str, - default=None, - help='MQTT broker password (default: None)') - parser.add_argument( - '-R', '--roombaIP', - action='store', - type=str, - default=None, - help='ipaddress of Roomba 980 (default: None)') - parser.add_argument( - '-u', '--blid', - action='store', - type=str, - default=None, - help='Roomba 980 blid (default: None)') - parser.add_argument( - '-w', '--roombaPassword', - action='store', - type=str, - default=None, - help='Roomba 980 password (default: None)') - parser.add_argument( - '-i', '--indent', - action='store', - type=int, - default=0, - help='Default indentation=auto') - parser.add_argument( - '-l', '--log', - action='store', - type=str, - default="./Roomba.log", - help='path/name of log file (default: ./Roomba.log)') - parser.add_argument( - '-e', '--echo', - action='store_false', - default = True, - help='Echo to Console (default: True)') - parser.add_argument( - '-D', '--debug', - action='store_true', - default = False, - help='debug mode') - parser.add_argument( - '-r', '--raw', - action='store_true', - default = False, - help='Output raw data to mqtt, no decoding of json data') - parser.add_argument( - '-j', '--pretty_print', - action='store_true', - default = False, - help='pretty print json in logs') - parser.add_argument( - '-c','--continuous', - action='store_false', - default = True, - help='Continuous connection to Roomba (default: True)') - parser.add_argument( - '-d', '--delay', - action='store', - type=int, - default=1000, - help='Disconnect period for non-continuous connection (default: ' - '1000ms)') - parser.add_argument( - '-m', '--drawmap', - action='store_false', - default = True, - help='Draw Roomba cleaning map (default: True)') - parser.add_argument( - '-M', '--mapPath', - action='store', - type=str, - default=".", - help='Location to store maps to (default: .)') - parser.add_argument( - '-s', '--mapSize', - action='store', - type=str, - default="(800,1500,0,0,0,0)", - help='Map Size, Dock offset and skew for the map. (800,1500) is the ' - 'size, (0,0) is the dock location, in the center of the map, 0 ' - 'is the rotation of the map, 0 is the rotation of the roomba. ' - 'Use single quotes around the string. (default: ' - '"(800,1500,0,0,0,0)")') - parser.add_argument( - '-I', '--iconPath', - action='store', - type=str, - default=default_icon_path, - help='location of icons. (default: "./")') - parser.add_argument( - '-o', '--roomOutline', - action='store_false', - default = True, - help='Draw room outline (default: True)') - parser.add_argument( - '-x', '--exclude', - action='store',type=str, default="", help='Exclude topics that have this in them (default: "")') - parser.add_argument( - '--cert', - action='store', - type=str, - default='/etc/ssl/certs/ca-certificates.crt', - help='Set the certificate to use for MQTT communication with the Roomba') - parser.add_argument( - '--version', - action='version', - version="%(prog)s ({})".format(roomba.__version__), - help='Display version of this program') - return parser.parse_args() - -def main(): - - #----------- Local Routines ------------ - - def broker_on_connect(client, userdata, flags, rc): - log.debug("Broker Connected with result code " + str(rc)) - #subscribe to roomba feedback, if there is more than one roomba, the - # roombaName is added to the topic to subscribe to - if rc == 0: - if brokerCommand != "": - if len(roombas) == 1: - mqttc.subscribe(brokerCommand) - else: - for myroomba in roomba_list: - mqttc.subscribe( - brokerCommand + "/" + myroomba.roombaName) - if brokerSetting != "": - if len(roombas) == 1: - mqttc.subscribe(brokerSetting) - else: - for myroomba in roomba_list: - mqttc.subscribe( - brokerSetting + "/" + myroomba.roombaName) - - def broker_on_message(mosq, obj, msg): - # publish to roomba, if there is more than one roomba, the roombaName - # is added to the topic to publish to - msg.payload = msg.payload.decode("utf-8") - if "command" in msg.topic: - log.info("Received COMMAND: %s" % str(msg.payload)) - if len(roombas) == 1: - roomba_list[0].send_command(str(msg.payload)) - else: - for myroomba in roomba_list: - if myroomba.roombaName in msg.topic: - myroomba.send_command(str(msg.payload)) - elif "setting" in msg.topic: - log.info("Received SETTING: %s" % str(msg.payload)) - cmd = str(msg.payload).split() - if len(roombas) == 1: - roomba_list[0].set_preference(cmd[0], cmd[1]) - else: - for myroomba in roomba_list: - if myroomba.roombaName in msg.topic: - myroomba.set_preference(cmd[0], cmd[1]) - else: - log.warn("Unknown topic: %s" % str(msg.topic)) - - def broker_on_publish(mosq, obj, mid): - pass - - def broker_on_subscribe(mosq, obj, mid, granted_qos): - log.debug("Broker Subscribed: %s %s" % (str(mid), str(granted_qos))) - - def broker_on_disconnect(mosq, obj, rc): - log.debug("Broker disconnected") - if rc == 0: - sys.exit(0) - - def broker_on_log(mosq, obj, level, string): - log.info(string) - - def read_config_file(file="./config.ini"): - #read config file - Config = configparser.ConfigParser() - try: - Config.read(file) - log.info("reading info from config file %s" % file) - roombas = {} - for address in Config.sections(): - roomba_data = literal_eval(Config.get(address, "data")) - roombas[address] = { - "blid": Config.get(address, "blid"), - "password": Config.get(address, "password"), - "roombaName": roomba_data.get("robotname", None)} - except Exception as e: - log.warn("Error reading config file %s" %e) - return roombas - - def create_html(myroomba,mapPath="."): - ''' - Create html files for live display of roomba maps - but only if they - don't already exist - ''' - #default css and html - css='''body { - background-color: white; - color: white; - margin: 0; - padding: 0; - } -img,video { - width: auto; - max-height:100%; - } -''' - html=''' - - - - - - - -''' - html +='Roomba Map Live' % myroomba.roombaName - html +=''' - - -''' - #python 3 workaround - try: - FileNotFoundError - except NameError: - #py2 - FileNotFoundError = PermissionError = IOError - - #check is style.css exists, if not create it - css_path = mapPath+"/style.css" - try: - fn = open(css_path , "r") #check if file exists (or is readable) - fn.close() - except (IOError,FileNotFoundError): - log.warn("CSS file not found, creating %s" % css_path) - try: - with open(css_path , "w") as fn: - fn.write(css) - except (IOError, PermissionError) as e: - log.error("unable to create file %s, error: %s" % css_path, e) - #check is html exists, if not create it - html_path = mapPath+"/"+ myroomba.roombaName + "roomba_map.html" - try: - fn = open(html_path, "r") #check if file exists (or is readable) - fn.close() - except (IOError,FileNotFoundError): - log.warn("html file not found, creating %s" % html_path) - try: - with open(html_path, "w") as fn: - fn.write(html) - make_executable(html_path) - except (IOError, PermissionError) as e: - log.error("unable to create file %s, error: %s" % html_path, e) - - def make_executable(path): - mode = os.stat(path).st_mode - mode |= (mode & 0o444) >> 2 # copy R bits to X - os.chmod(path, mode) - - def setup_logger(logger_name, log_file, level=logging.DEBUG, console=False): - try: - l = logging.getLogger(logger_name) - if logger_name ==__name__: - formatter = logging.Formatter( - '[%(levelname)1.1s %(asctime)s] %(message)s') - else: - formatter = logging.Formatter('%(message)s') - fileHandler = RotatingFileHandler( - log_file, mode='a', maxBytes=2000000, backupCount=5) - fileHandler.setFormatter(formatter) - if console == True: - streamHandler = logging.StreamHandler() - - l.setLevel(level) - l.addHandler(fileHandler) - if console == True: - streamHandler.setFormatter(formatter) - l.addHandler(streamHandler) - except IOError as e: - if e[0] == 13: #errno Permission denied - print("Error: %s: You probably don't have permission to " - "write to the log file/directory - try sudo" % e) - else: - print("Log Error: %s" % e) - sys.exit(1) - - #args = parse_args() #don't know what this is for - removed NW 3/2/2018 - arg = parse_args() - - if arg.debug: - log_level = logging.DEBUG - else: - log_level = logging.INFO - - #setup logging - setup_logger(__name__, arg.log,level=log_level,console=arg.echo) - - log = logging.getLogger(__name__) - - log.info("*******************") - log.info("* Program Started *") - log.info("*******************") - - log.info("Roomba.py Version: %s" % roomba.__version__) - - log.info("Python Version: %s" % sys.version.replace('\n','')) - - if HAVE_MQTT: - import paho.mqtt # bit of a kludge, just to get the version number - log.info("Paho MQTT Version: %s" % paho.mqtt.__version__) - if (sys.version_info.major == 2 and sys.version_info.minor == 7 and - sys.version_info.micro < 9 and - int(paho.mqtt.__version__.split(".")[0]) >= 1 and - int(paho.mqtt.__version__.split(".")[1]) > 2): - log.error("NOTE: if your python version is less than 2.7.9, " - "and Paho MQTT verion is not 1.2.3 or lower, this " - "program will NOT WORK") - log.error("Please use pip install paho-mqtt==1.2.3 to " - "downgrade paho-mqtt, or use a later version of python") - sys.exit(1) - - if HAVE_CV2: - log.info("CV Version: %s" % cv2.__version__) - - if HAVE_PIL: - import PIL #bit of a kludge, just to get the version number - log.info("PIL Version: %s" % PIL.__version__) - if int(PIL.__version__.split(".")[0]) < 4: - log.warn("WARNING: PIL version is %s, this is not the latest! " - "You can get bad memory leaks with old versions of PIL" - % Image.PILLOW_VERSION) - log.warn("run: 'pip install --upgrade pillow' to fix this") - - log.debug("-- DEBUG Mode ON -") - log.info(" to Exit") - log.info("Roomba 980 MQTT data Interface") - - roombas = {} - - if arg.blid is None or arg.roombaPassword is None: - roombas = read_config_file(arg.configfile) - if len(roombas) == 0: - log.warn("No roomba or config file defined, I will attempt to " - "discover Roombas, please put the Roomba on the dock " - "and follow the instructions:") - if arg.roombaIP is None: - Password(file=arg.configfile) - else: - Password(arg.roombaIP,file=arg.configfile) - roombas = read_config_file(arg.configfile) - if len(roombas) == 0: - log.error("No Roombas found! You must specify RoombaIP, blid " - "and roombaPassword to run this program, or have " - "a config file, use -h to show options.") - sys.exit(0) - else: - log.info("Success! %d Roombas Found!" % len(roombas)) - else: - roombas[arg.roombaIP] = { - "blid": arg.blid, - "password": arg.roombaPassword, - "roombaName": arg.roombaName} - - # set broker = "127.0.0.1" # mosquitto broker is running on localhost - mqttc = None - if arg.broker is not None: - brokerCommand = arg.brokerCommand - brokerSetting = arg.brokerSetting - - # connect to broker - mqttc = mqtt.Client() - # Assign event callbacks - mqttc.on_message = broker_on_message - mqttc.on_connect = broker_on_connect - mqttc.on_disconnect = broker_on_disconnect - mqttc.on_publish = broker_on_publish - mqttc.on_subscribe = broker_on_subscribe - # uncomment to enable logging - # mqttc.on_log = broker_on_log - - try: - if arg.user != None: - mqttc.username_pw_set(arg.user, arg.password) - log.info("connecting to broker") - # Ping MQTT broker every 60 seconds if no data is published - # from this script. - mqttc.connect(arg.broker, arg.port, 60) - - except socket.error: - log.error("Unable to connect to MQTT Broker") - mqttc = None - - roomba_list = [] - for addr, info in six.iteritems(roombas): - log.info("Creating Roomba object %s" % addr) - #NOTE: cert_name is a default certificate. change this if your - # certificates are in a different place. any valid certificate will - # do, it's not used but needs to be there to enable mqtt TLS encryption - # instansiate Roomba object - # minnimum required to connect on Linux Debian system - # myroomba = Roomba(address, blid, roombaPassword) - roomba_list.append( - roomba.Roomba(addr, blid=info["blid"], - password=info["password"], - topic=arg.topic, continuous=arg.continuous, - clean=False, - cert_name=arg.cert, - roombaName=info["roombaName"])) - - for myroomba in roomba_list: - log.info("connecting Roomba %s" % myroomba.address) - # auto create html files (if they don't exist) - create_html(myroomba,arg.mapPath) - # all these are optional, if you don't include them, the defaults - # will work just fine - if arg.exclude != "": - myroomba.exclude = arg.exclude - myroomba.set_options( - raw=arg.raw, indent=arg.indent, pretty_print=arg.pretty_print) - if not arg.continuous: - myroomba.delay = arg.delay//1000 - if arg.mapSize != "" and arg.mapPath != "": - # enable live maps, class default is no maps - myroomba.enable_map(enable=True, mapSize=arg.mapSize, - mapPath=arg.mapPath, iconPath=arg.iconPath, - roomOutline=arg.roomOutline) - if arg.broker is not None: - # if you want to publish Roomba data to your own mqtt broker - # (default is not to) if you have more than one roomba, and - # assign a roombaName, it is addded to this topic - # (ie brokerFeedback/roombaName) - myroomba.set_mqtt_client(mqttc, arg.brokerFeedback) - # finally connect to Roomba - (required!) - myroomba.connect() - - try: - if mqttc is not None: - mqttc.loop_forever() - else: - while True: - log.info("Roomba Data: %s" % - json.dumps(myroomba.master_state, indent=2)) - time.sleep(5) - - except (KeyboardInterrupt, SystemExit): - log.info("System exit Received - Exiting program") - mqttc.disconnect() - sys.exit(0) - - -if __name__ == '__main__': - main() From 1070d7a388219ff8d48f2ba4689da02ca4708319 Mon Sep 17 00:00:00 2001 From: Zapfen83 Date: Thu, 25 Oct 2018 11:24:48 +0200 Subject: [PATCH 340/705] =?UTF-8?q?=09ge=C3=A4ndert:=20=20=20=20=20=20=20r?= =?UTF-8?q?oomba=5F980/README.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- roomba_980/README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/roomba_980/README.md b/roomba_980/README.md index 47f43bada..cee8670d4 100644 --- a/roomba_980/README.md +++ b/roomba_980/README.md @@ -45,12 +45,12 @@ Password=> ABCD EFGGDBAN <= Yes, all this string. Use these credentials in roomba.py ``` - +Ganz am ende stehen die IP, blid und das Passwort welches ihr für die plugin.ymal braucht ## Um das Plugin zu aktivieren müsst ihr Folgendes in eure plugin.ymal aufnehmen: -``` + roomba_980: class_name: ROOMBA_980 class_path: plugins.roomba_980 @@ -58,11 +58,11 @@ roomba_980: blid: '123456789013456' # die blid des roomba Staubsaugers -> kann mit der getpassword.py ausgelesen werden" roombaPassword: 'ABCD EFGGDBAN' # das Passwort des roomba Staubsaugers -> kann mit der getpassword.py ausgelesen werden" # cycle: 600 # Optional, nach wie vielen Sekunden die nächste Statusabfrage durchgeführt wird -``` + ## Hier meine item.yaml: -``` + roomba: status_batterie: @@ -94,5 +94,4 @@ roomba: dock: type: bool roomba_980: dock - visu_acl: rw -``` + visu_acl: rw \ No newline at end of file From d062a4991f7a64498c6a4e1af5ac4be35d8300a8 Mon Sep 17 00:00:00 2001 From: Zapfen83 Date: Thu, 25 Oct 2018 12:26:35 +0200 Subject: [PATCH 341/705] =?UTF-8?q?=09ge=C3=A4ndert:=20=20=20=20=20=20=20r?= =?UTF-8?q?oomba=5F980/=5F=5Finit=5F=5F.py=20Kleine=20=C3=84nderungen=20be?= =?UTF-8?q?im=20start/stop/dock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- roomba_980/__init__.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/roomba_980/__init__.py b/roomba_980/__init__.py index 71eb875e2..d1e25cb0e 100755 --- a/roomba_980/__init__.py +++ b/roomba_980/__init__.py @@ -73,12 +73,18 @@ def update_item(self, item, caller=None, source=None, dest=None): if caller != __name__ and self.has_iattr(item.conf, 'roomba_980'): if self.get_iattr_value(item.conf, 'roomba_980') == "start": if item() == True: + self.myroomba.send_command("start") + item(False, __name__) self.logger.debug('Roomba_980: Start') if self.get_iattr_value(item.conf, 'roomba_980') == "stop": if item() == True: + self.myroomba.send_command("stop") + item(False, __name__) self.logger.debug('Roomba_980: Stop') if self.get_iattr_value(item.conf, 'roomba_980') == "dock": if item() == True: + self.myroomba.send_command("dock") + item(False, __name__) self.logger.debug('Roomba_980: Dock') def get_status(self): From b752dec9cad2a3700ac2c8e6d518edf3283fe0aa Mon Sep 17 00:00:00 2001 From: Zapfen83 Date: Fri, 26 Oct 2018 11:18:11 +0200 Subject: [PATCH 342/705] =?UTF-8?q?=09ge=C3=A4ndert:=20=20=20=20=20=20=20r?= =?UTF-8?q?oomba=5F980/README.md=20=09ge=C3=A4ndert:=20=20=20=20=20=20=20r?= =?UTF-8?q?oomba=5F980/=5F=5Finit=5F=5F.py=20=09ge=C3=A4ndert:=20=20=20=20?= =?UTF-8?q?=20=20=20roomba=5F980/plugin.yaml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- roomba_980/README.md | 56 ++++++++++++++++++++++++++++++++++++------ roomba_980/__init__.py | 31 ++++++++++++----------- roomba_980/plugin.yaml | 50 ++++++++++++++++++++++++++++++++++--- 3 files changed, 111 insertions(+), 26 deletions(-) diff --git a/roomba_980/README.md b/roomba_980/README.md index cee8670d4..e771f564d 100644 --- a/roomba_980/README.md +++ b/roomba_980/README.md @@ -22,9 +22,9 @@ Received: { "ver": "3", "proto": "mqtt", "ip": "192.168.5.147", - "hostname": "Roomba-6977C20412227550", + "hostname": "Roomba-123456789013456", "sw": "v2.4.6-3", - "mac": "F0:03:8C:B5:78:36", + "mac": "F0:03:8C:B5:68:63", "cap": { "carpetBoost": 1, "pp": 1, @@ -39,7 +39,7 @@ Received: { "svcConf": 1 } } -Roomba (Robii) IP address is: 192.168.5.147 +Roomba (Robii) IP address is: 192.168.0.100 blid is: 123456789013456 Password=> ABCD EFGGDBAN <= Yes, all this string. Use these credentials in roomba.py @@ -50,19 +50,19 @@ Ganz am ende stehen die IP, blid und das Passwort welches ihr für die plugin.ym ## Um das Plugin zu aktivieren müsst ihr Folgendes in eure plugin.ymal aufnehmen: - +``` roomba_980: class_name: ROOMBA_980 class_path: plugins.roomba_980 adress: '192.168.0.100' # IP Adresse des Roomba blid: '123456789013456' # die blid des roomba Staubsaugers -> kann mit der getpassword.py ausgelesen werden" roombaPassword: 'ABCD EFGGDBAN' # das Passwort des roomba Staubsaugers -> kann mit der getpassword.py ausgelesen werden" - # cycle: 600 # Optional, nach wie vielen Sekunden die nächste Statusabfrage durchgeführt wird - + # cycle: 900 # Optional, nach wie vielen Sekunden die nächste Statusabfrage durchgeführt wird +``` ## Hier meine item.yaml: - +``` roomba: status_batterie: @@ -85,13 +85,53 @@ roomba: type: bool roomba_980: start visu_acl: rw + autotimer: 2 = False stop: type: bool roomba_980: stop visu_acl: rw + autotimer: 2 = False dock: type: bool roomba_980: dock - visu_acl: rw \ No newline at end of file + visu_acl: rw + autotimer: 2 = False + + uszu: + name: roomba_uzsu + type: dict + uzsu_item: roomba.uzsu.text + cache: 'True' + visu_acl: rw + enforce_updates: 'True' + + text: + name: robii Text + type: str + enforce_updates: 'True' + autotimer: 2 = "" + + + # Integration der Zeitschaltuhr mit der Abfrage vom Feiertag und Urlaubs Item + uzsu_start: + type: bool + roomba_980: start + eval: True if ( sh.roomba.uzsu.text() == "start" and sh.calendar.urlaub() == False and sh.calendar.feiertag() == False ) else False + eval_trigger: roomba.uzsu.text + + uzsu_stop: + type: bool + roomba_980: stop + eval: True if ( sh.roomba.uzsu.text() == "stop" and sh.calendar.urlaub() == False and sh.calendar.feiertag() == False ) else False + eval_trigger: roomba.uzsu.text + + uzsu_dock: + type: bool + roomba_980: dock + eval: True if ( sh.roomba.uzsu.text() == "dock" and sh.calendar.urlaub() == False and sh.calendar.feiertag() == False ) else False + eval_trigger: roomba.uzsu.text + +``` + diff --git a/roomba_980/__init__.py b/roomba_980/__init__.py index d1e25cb0e..8d20bee4c 100755 --- a/roomba_980/__init__.py +++ b/roomba_980/__init__.py @@ -22,6 +22,7 @@ import logging from plugins.roomba_980.roomba import Roomba from lib.model.smartplugin import SmartPlugin +from lib.item import Items class ROOMBA_980(SmartPlugin): @@ -30,6 +31,8 @@ class ROOMBA_980(SmartPlugin): logger = logging.getLogger(__name__) + myroomba = None + def __init__(self, sh, adress=None, blid=None, roombaPassword=None, cycle=900): self._sh = sh self._address = adress @@ -37,11 +40,12 @@ def __init__(self, sh, adress=None, blid=None, roombaPassword=None, cycle=900): self._roombaPassword = roombaPassword self._cycle = cycle - self.myroomba = None - self._status_batterie = None self._status_items = {} + self.myroomba = Roomba(self._address, self._blid, self._roombaPassword) + self.myroomba.connect() + def parse_logic(self, logic): pass @@ -53,11 +57,9 @@ def parse_item(self, item): self._status_items[item_type] = item - self.logger.debug('Roomba_980: item gefunden {}'.format(item)) + self.logger.debug('{} item gefunden {}'.format(item_type, item)) def run(self): - self.myroomba = Roomba(self._address, self._blid, self._roombaPassword) - self.myroomba.connect() self.scheduler_add(__name__, self.get_status, prio=5, cycle=self._cycle, offset=2) self.alive = True @@ -71,24 +73,18 @@ def __call__(self): def update_item(self, item, caller=None, source=None, dest=None): if caller != __name__ and self.has_iattr(item.conf, 'roomba_980'): + self.logger.debug('item_update {} '.format(item)) if self.get_iattr_value(item.conf, 'roomba_980') == "start": if item() == True: - self.myroomba.send_command("start") - item(False, __name__) - self.logger.debug('Roomba_980: Start') + self.send_command("start") if self.get_iattr_value(item.conf, 'roomba_980') == "stop": if item() == True: - self.myroomba.send_command("stop") - item(False, __name__) - self.logger.debug('Roomba_980: Stop') + self.send_command("stop") if self.get_iattr_value(item.conf, 'roomba_980') == "dock": if item() == True: - self.myroomba.send_command("dock") - item(False, __name__) - self.logger.debug('Roomba_980: Dock') + self.send_command("dock") def get_status(self): - status = self.myroomba.master_state for status_item in self._status_items: @@ -103,4 +99,9 @@ def get_status(self): self.logger.debug('Roomba_980: Status update') + def send_command(self, command): + if self.myroomba != None: + self.myroomba.send_command(command) + self.logger.debug('send command: {} to Roomba'.format(command)) + diff --git a/roomba_980/plugin.yaml b/roomba_980/plugin.yaml index 99d7fef6c..65c7f9ede 100644 --- a/roomba_980/plugin.yaml +++ b/roomba_980/plugin.yaml @@ -5,7 +5,7 @@ plugin: description: de: 'Anbindung von iRobot Roomba Staubsaugern der Serie 900' en: '' - maintainer: 'Zapfen' + maintainer: 'Zapfen83' tester: keywords: irobot roomba # keywords, where applicable # documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page @@ -46,7 +46,51 @@ parameters: type: num default: False description: - de: "update des items alle x Sekunden" + de: "update des items alle x Sekunden, default wert 900" en: "" -#item_attributes: + +item_attributes: # Definition of item attributes defined by this plugin + + status_batterie: + type: num + description: + de: "Batterie ladewert in Prozent" + en: "" + + status_bin_full: + type: bool + description: + de: "Auffangbehälter voll" + en: "" + + status_cleanMissionStatus_phase: + type: str + description: + de: "Status was der Roomba gerade macht -> run / charge / ..." + en: "" + + status_cleanMissionStatus_error: + type: num + description: + de: "Fehlernummer" + en: "" + + start: + type: bool + description: + de: "Startet die Reinigung" + en: "" + + stop: + type: bool + description: + de: "Stoppt die Reinigung" + en: "" + + dock: + type: bool + description: + de: "Roomba fährt zur Homebase" + en: "" + From 6d4618fc133cf3ba0ea4dc1973aa6e9aa38030ef Mon Sep 17 00:00:00 2001 From: Bernd Meiners Date: Fri, 26 Oct 2018 18:04:10 +0200 Subject: [PATCH 343/705] updated Readme to show dlms_obis_code key usage --- dlms/README.md | 109 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 90 insertions(+), 19 deletions(-) diff --git a/dlms/README.md b/dlms/README.md index 8952ded6e..4aaf3e0a4 100644 --- a/dlms/README.md +++ b/dlms/README.md @@ -116,6 +116,7 @@ Some first lines of a sample OBIS Code readout for a **Landis & Gyr ZMD 310** Sm ``` ### OBIS code example B + Sample OBIS Code readout from a relative simple **Pafal 12EC3g** smartmeter ``` 0.0.0(72044837)(72044837) @@ -128,6 +129,8 @@ C.2.1(000000000000)( )(0000000000 0.2.2(:::::G11)!(:::::G11)(!) ``` +### Getting Values from Codelines + Comparing the above examples it is obvious that the basically same OBIS Code has different appearances. | Example A | Example B | @@ -136,64 +139,132 @@ Comparing the above examples it is obvious that the basically same OBIS Code has | 1-1:1.8.0(00051206*kWh) | 1.8.0*00(000783.16)(000783.16) | To get the value from ``1-1:1.8.0(00051206*kWh)`` into the item we write in the items config file -``dlms_obis_code: 1-1:1.8.0|0|Value|num``. This will get the first value in parentheses and cast it into a numeric value. +``` +dlms_obis_code: + - '1-1:1.8.0' + - 0 + - 'Value' + - 'num' +``` +This will get the first value in parentheses and cast it into a numeric value. To get the value from ``1.8.0*00(000783.16)(000783.16)`` into the item we write in the items config file -``dlms_obis_code: 1.8.0*00|0|Value|num``. This will too get the first value in parentheses and cast it into a numeric value. +``` +dlms_obis_code: + - '1.8.0*00' + - 0 + - 'Value' + - 'num' +``` +This will too get the first value in parentheses and cast it into a numeric value. -To get the unit from ``1-1:1.8.0(00051206*kWh)`` into another item we write ``dlms_obis_code: 1-1:1.8.0|0|Unit|str`` into the item.yaml. +To get the unit from ``1-1:1.8.0(00051206*kWh)`` into another item we write +```yaml +dlms_obis_code: + - '1-1:1.8.0' + - 0 + - 'Unit' + - 'str' +``` + +into the item.yaml. A sample item.yaml for example **A** might look like following: -``` +```yaml Stromzaehler: Auslesung: type: str dlms_obis_readout: yes Seriennummer: type: str - dlms_obis_code: 1-1:0.0.0|0|Value|str + dlms_obis_code: + - '1-1:0.0.0 + - 0 + - 'Value' + - 'str' Ablesung: # Datum und Uhrzeit der letzten Ablesung Uhrzeit: type: foo - dlms_obis_code: 1-1:0.9.1|0|Value|Z6 + dlms_obis_code: + - '1-1:0.9.1' + - 0 + - 'Value' + - 'Z6' Datum: type: foo - dlms_obis_code: 1-1:0.9.2|0|Value|D6 + dlms_obis_code: + - '1-1:0.9.2' + - 0 + - 'Value' + - 'D6' Datum_Aktueller_Abrechnungsmonat: type: foo - dlms_obis_code: 1-1:0.1.3|0|Value|D6 + dlms_obis_code: + - '1-1:0.1.3' + - 0 + - 'Value' + - 'D6' Monatszaehler: # Billing period counter type: num - dlms_obis_code: 1-1:0.1.0|0|Value|num + dlms_obis_code: + - '1-1:0.1.0' + - 0 + - 'Value' + - 'num' Bezug: Energie: type: num sqlite: yes - dlms_obis_code: 1-1:1.8.1|0|Value|num + dlms_obis_code: + - '1-1:1.8.1' + - 0 + - 'Value' + - 'num' + Energie_Einheit: type: str sqlite: yes - dlms_obis_code: 1-1:1.8.1|0|Unit|str + dlms_obis_code: + - '1-1:1.8.1' + - 0 + - 'Unit' + - 'str' Lieferung: Energie: type: num sqlite: yes - dlms_obis_code: 1-1:2.8.1|0|Value|num + dlms_obis_code: + - '1-1:2.8.1' + - 0 + - 'Value' + - 'num' + Energie_Einheit: type: str sqlite: yes - dlms_obis_code: 1-1:2.8.1|0|Unit|str + dlms_obis_code: + - '1-1:2.8.1' + - 0 + - 'Unit' + - 'str' ``` The basic syntax of the **dlms_obis_code** attributes value is -``dlms_obis_code: 1-1:1.6.2*01|Index|Value/Unit|Value Type`` +``` +dlms_obis_code: + - 1-1:1.6.2*01 + - Index + - 'Value' or 'Unit' + - Value Type +``` where + * __Index__ is the number of the value group you want to read * __Value__ or __Unit__ whether you are interested in the value (mostly) or the unit like **kWh** * __Value Type__ can be one of @@ -202,12 +273,12 @@ where * __D6__ (date coded with YYMMDD), * __ZST10__ (date and time coded with YYMMDDhhmm), * __ZST12__ (date and time coded with YYMMDDhhmmss), - * __str__, - * __float__, - * __int__ or - * __num__ + * __str__, a string + * __float__, a floating point number + * __int__ an integer + * __num__ a number either float or int -For any Value Type with time or date the python datetime will be used. +For any Value Type with ``time`` or ``date`` the python datetime will be used. That implies that you use ``type: foo`` for the items attribute in the respective item.yaml | OBIS A | meaning | From 22c3ebe3321af28776eff9e5ac56552cc19f18ff Mon Sep 17 00:00:00 2001 From: ohinckel Date: Fri, 26 Oct 2018 21:18:27 +0200 Subject: [PATCH 344/705] ComfoAir: Fix typo in type of `comfoair_trigger` --- comfoair/plugin.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/comfoair/plugin.yaml b/comfoair/plugin.yaml index be25e808e..1c235ed6d 100755 --- a/comfoair/plugin.yaml +++ b/comfoair/plugin.yaml @@ -72,7 +72,7 @@ item_attributes: de: 'Konfiguriert ob der Wert aus dem KWL System initialisiert werden soll.' en: 'Configures to initialize the item value with the value from the KWL system.' comfoair_trigger: - type: list(string) + type: list(str) description: de: 'Konfiguriert Lesekommandos die nach einem Schreibvorgang auf das Item aufgerufen werden.' en: 'Configures read commands after an update to the item.' From aab9518f77b0a6237ba296ff98beab2e1df727b8 Mon Sep 17 00:00:00 2001 From: msinn Date: Sat, 27 Oct 2018 17:10:19 +0200 Subject: [PATCH 345/705] wunderground: support for logging advances of SmartPlugin --- wunderground/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/wunderground/__init__.py b/wunderground/__init__.py index 0e0f96c4b..72ce52080 100644 --- a/wunderground/__init__.py +++ b/wunderground/__init__.py @@ -62,7 +62,10 @@ def __init__(self, sh, apikey='', language='de', location='', cycle='600', item_ :param item_subtree: subtree of items in which the plugin looks for items to update :param log_start: x """ - self.logger = logging.getLogger(__name__) + from bin.smarthome import VERSION + if '.'.join(VERSION.split('.',2)[:2]) <= '1.5': + self.logger = logging.getLogger(__name__) + self.__sh = sh self.items = Items.get_instance() From 171562102ad7d107b525112be7c16a9987a0f2b8 Mon Sep 17 00:00:00 2001 From: Thomas Ernst Date: Sun, 28 Oct 2018 09:55:20 +0100 Subject: [PATCH 346/705] [Bug] Fix "Rules not evaluating with new SmarthomeNG 1.5 master" https://github.com/i-am-offline/smarthome.plugin.autoblind/issues/24 --- stateengine/StateEngineItem.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stateengine/StateEngineItem.py b/stateengine/StateEngineItem.py index 6225c898e..2c942a128 100755 --- a/stateengine/StateEngineItem.py +++ b/stateengine/StateEngineItem.py @@ -254,7 +254,7 @@ def __check_item_config(self): self.__item._enforce_updates = True # set "eval" for item if initial - if self.__item._eval_trigger and self.__item._eval is None: + if self.__item._trigger and self.__item._eval is None: self.__item._eval = "1" # Check scheduler settings and update if requred @@ -292,14 +292,14 @@ def __check_item_config(self): self.__sh.scheduler.change(self.id, cycle=new_cycle, cron=new_cron) # get triggers in readable format - def __verbose_eval_triggers(self): + def __verbose_triggers(self): # noinspection PyProtectedMember - if not self.__item._eval_trigger: + if not self.__item._trigger: return "Inactive" triggers = "" # noinspection PyProtectedMember - for trigger in self.__item._eval_trigger: + for trigger in self.__item._trigger: if triggers != "": triggers += ", " triggers += trigger @@ -335,7 +335,7 @@ def __verbose_crons_and_cycles(self): def __write_to_log(self): # get crons and cycles crons, cycles = self.__verbose_crons_and_cycles() - triggers = self.__verbose_eval_triggers() + triggers = self.__verbose_triggers() # log general config self.__logger.header("Configuration of item {0}".format(self.__name)) @@ -364,7 +364,7 @@ def cli_list(self, handler): def cli_detail(self, handler): # get data crons, cycles = self.__verbose_crons_and_cycles() - triggers = self.__verbose_eval_triggers() + triggers = self.__verbose_triggers() handler.push("AutoState Item {0}:\n".format(self.id)) handler.push("\tCurrent state: {0}\n".format(self.__laststate_internal_name)) handler.push(self.__startup_delay.get_text("\t", "\n")) From 447abac5672e24a0004b8222fd33374f3ae5b18c Mon Sep 17 00:00:00 2001 From: Zapfen83 Date: Mon, 29 Oct 2018 07:36:10 +0100 Subject: [PATCH 347/705] =?UTF-8?q?=09ge=C3=A4ndert:=20=20=20=20=20=20room?= =?UTF-8?q?ba=5F980/README.md=20Typo=20=09ge=C3=A4ndert:=20=20=20=20=20=20?= =?UTF-8?q?=20roomba=5F980/=5F=5Finit=5F=5F.py=20Code=20Optimierungen=20?= =?UTF-8?q?=09ge=C3=A4ndert:=20=20=20=20=20=20=20roomba=5F980/plugin.yaml?= =?UTF-8?q?=20Englische=20beschreibung=20hinzugef=EF=BF=BDgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- roomba_980/README.md | 10 +++++----- roomba_980/__init__.py | 16 +++++++--------- roomba_980/plugin.yaml | 30 +++++++++++++++--------------- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/roomba_980/README.md b/roomba_980/README.md index e771f564d..6b9bd38d9 100644 --- a/roomba_980/README.md +++ b/roomba_980/README.md @@ -1,15 +1,15 @@ # roomba_980 -Dies ist ein Plugin für das SmarthomeNG Projekt um den iRobot Roomba 980 zu nutzen +Dies ist ein Plugin für das SmarthomeNG Projekt um den iRobot Roomba 980 zu steuern. -zusätzlich muss das Projekt https://github.com/NickWaterton/Roomba980-Python in das verzeichniss hinterlegt werden +zusätzlich muss das Projekt https://github.com/NickWaterton/Roomba980-Python in das Plugin Verzeichniss hinterlegt werden ## Wie bekomme ich meine blid und mein Passwort -zu erst müsst ihr das Projekt Roomba980-Python herrunterladen und das roomba Verzeichnis ins rooomba_980 Plugin Verzeichnis kopieren +zu erst müsst ihr das Projekt Roomba980-Python herrunterladen und das roomba Verzeichnis in das rooomba_980 Plugin Verzeichnis kopieren -in dem Verzeichnis befindet ein getpassword.py, das ihr ausführen müsst, danach bekommt ihr folgende meldung: +in dem Verzeichnis befindet sich ein getpassword.py, das ihr ausführen müsst, danach bekommt ihr folgende meldung: ``` found 1 Roomba(s) @@ -108,7 +108,7 @@ roomba: enforce_updates: 'True' text: - name: robii Text + name: roomba Text type: str enforce_updates: 'True' autotimer: 2 = "" diff --git a/roomba_980/__init__.py b/roomba_980/__init__.py index 8d20bee4c..7980a3699 100755 --- a/roomba_980/__init__.py +++ b/roomba_980/__init__.py @@ -27,9 +27,7 @@ class ROOMBA_980(SmartPlugin): ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.0.0" - - logger = logging.getLogger(__name__) + PLUGIN_VERSION = "1.0.1" myroomba = None @@ -57,10 +55,10 @@ def parse_item(self, item): self._status_items[item_type] = item - self.logger.debug('{} item gefunden {}'.format(item_type, item)) + self.logger.debug('found item {} with function {}'.format(item, item_type)) def run(self): - self.scheduler_add(__name__, self.get_status, prio=5, cycle=self._cycle, offset=2) + self.scheduler_add('get_status', self.get_status, prio=5, cycle=self._cycle, offset=2) self.alive = True def stop(self): @@ -72,15 +70,15 @@ def __call__(self): pass def update_item(self, item, caller=None, source=None, dest=None): - if caller != __name__ and self.has_iattr(item.conf, 'roomba_980'): + if caller != __name__: self.logger.debug('item_update {} '.format(item)) if self.get_iattr_value(item.conf, 'roomba_980') == "start": if item() == True: self.send_command("start") - if self.get_iattr_value(item.conf, 'roomba_980') == "stop": + elif self.get_iattr_value(item.conf, 'roomba_980') == "stop": if item() == True: self.send_command("stop") - if self.get_iattr_value(item.conf, 'roomba_980') == "dock": + elif self.get_iattr_value(item.conf, 'roomba_980') == "dock": if item() == True: self.send_command("dock") @@ -97,7 +95,7 @@ def get_status(self): if status_item == "status_cleanMissionStatus_error": self._status_items[status_item](status['state']['reported']['cleanMissionStatus']['error'],__name__) - self.logger.debug('Roomba_980: Status update') + self.logger.debug('Status update') def send_command(self, command): if self.myroomba != None: diff --git a/roomba_980/plugin.yaml b/roomba_980/plugin.yaml index 65c7f9ede..53cbae371 100644 --- a/roomba_980/plugin.yaml +++ b/roomba_980/plugin.yaml @@ -25,29 +25,29 @@ parameters: type: str default: True description: - de: "IP Adresse des roomba Staubsaugers" - en: "" + de: "Die IP Adresse des roomba Staubsaugers" + en: "The IP address of the roomba vacuum cleaner" blid: type: str default: True description: de: "Die blid des roomba Staubsaugers -> kann mit der getpassword.py ausgelesen werden" - en: "" + en: "The blid of the roomba vacuum cleaner -> use getpassword.py to get it" roombaPassword: type: str default: True description: de: "Das Passwort des roomba Staubsaugers -> kann mit der getpassword.py ausgelesen werden" - en: "" + en: "The password of the roomba vacuum cleaner -> use getpassword.py to get it" cycle: type: num default: False description: de: "update des items alle x Sekunden, default wert 900" - en: "" + en: "update the state item every x secounds, default is 900" item_attributes: # Definition of item attributes defined by this plugin @@ -56,41 +56,41 @@ item_attributes: type: num description: de: "Batterie ladewert in Prozent" - en: "" + en: "Battery charge in percent" status_bin_full: type: bool description: - de: "Auffangbehälter voll" - en: "" + de: "Wahr wenn der Auffangbehälter voll ist" + en: "True if bin is full" status_cleanMissionStatus_phase: type: str description: - de: "Status was der Roomba gerade macht -> run / charge / ..." - en: "" + de: "Status was der Roomba gerade macht -> run / charge / stock / ..." + en: "State of the roomba -> run / charge / stock / ..." status_cleanMissionStatus_error: type: num description: - de: "Fehlernummer" - en: "" + de: "Fehlernummer, 0 ist OK" + en: "Error Number, 0 is ok" start: type: bool description: de: "Startet die Reinigung" - en: "" + en: "Start cleaning misson" stop: type: bool description: de: "Stoppt die Reinigung" - en: "" + en: "Stop cleaning mission" dock: type: bool description: de: "Roomba fährt zur Homebase" - en: "" + en: "Roomba goes back to the homebase" From 870d81b1591d61511ab0df6dad477a6743070c8b Mon Sep 17 00:00:00 2001 From: Zapfen83 Date: Mon, 29 Oct 2018 09:57:45 +0100 Subject: [PATCH 348/705] =?UTF-8?q?=09ge=C3=A4ndert:=20=20=20=20=20=20=20r?= =?UTF-8?q?oomba=5F980/plugin.yaml=20Version=20auf=201.0.1=20ge=C3=A4ndert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- roomba_980/plugin.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roomba_980/plugin.yaml b/roomba_980/plugin.yaml index 53cbae371..7b79b0223 100644 --- a/roomba_980/plugin.yaml +++ b/roomba_980/plugin.yaml @@ -12,7 +12,7 @@ plugin: # support: https://knx-user-forum.de/forum/supportforen/smarthome-py # Following entries are for Smart-Plugins: - version: 1.0.0 # Plugin version + version: 1.0.1 # Plugin version sh_minversion: 1.5 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False From 511423ee4b057395f73d3f4dd84930ad0eead83e Mon Sep 17 00:00:00 2001 From: msinn Date: Wed, 31 Oct 2018 11:50:40 +0100 Subject: [PATCH 349/705] div. plugins: moved requirement for requests package to core (cor requirement updated due to CVE-2018-18074) --- avm/requirements.txt | 3 +-- enigma2/requirements.txt | 3 +-- intercom_2n/requirements.txt | 3 +-- nuki/requirements.txt | 3 +-- odlinfo/requirements.txt | 3 +-- pushbullet/requirements.txt | 3 +-- pushover/requirements.txt | 3 +-- sonos/requirements.txt | 3 +-- tankerkoenig/requirements.txt | 3 +-- traffic/requirements.txt | 3 +-- 10 files changed, 10 insertions(+), 20 deletions(-) diff --git a/avm/requirements.txt b/avm/requirements.txt index 648060e1e..7491ce9ce 100644 --- a/avm/requirements.txt +++ b/avm/requirements.txt @@ -1,2 +1 @@ -requests>=2.9.1;python_version>'3.2' -requests==2.5.1;python_version=='3.2' +#requests requirement moved to core diff --git a/enigma2/requirements.txt b/enigma2/requirements.txt index 648060e1e..7491ce9ce 100644 --- a/enigma2/requirements.txt +++ b/enigma2/requirements.txt @@ -1,2 +1 @@ -requests>=2.9.1;python_version>'3.2' -requests==2.5.1;python_version=='3.2' +#requests requirement moved to core diff --git a/intercom_2n/requirements.txt b/intercom_2n/requirements.txt index 648060e1e..7491ce9ce 100644 --- a/intercom_2n/requirements.txt +++ b/intercom_2n/requirements.txt @@ -1,2 +1 @@ -requests>=2.9.1;python_version>'3.2' -requests==2.5.1;python_version=='3.2' +#requests requirement moved to core diff --git a/nuki/requirements.txt b/nuki/requirements.txt index 886985cfc..7491ce9ce 100644 --- a/nuki/requirements.txt +++ b/nuki/requirements.txt @@ -1,2 +1 @@ -requests>=2.9.1;python_version>'3.2' -requests==2.5.1;python_version=='3.2' \ No newline at end of file +#requests requirement moved to core diff --git a/odlinfo/requirements.txt b/odlinfo/requirements.txt index 648060e1e..7491ce9ce 100644 --- a/odlinfo/requirements.txt +++ b/odlinfo/requirements.txt @@ -1,2 +1 @@ -requests>=2.9.1;python_version>'3.2' -requests==2.5.1;python_version=='3.2' +#requests requirement moved to core diff --git a/pushbullet/requirements.txt b/pushbullet/requirements.txt index 11f14cde7..096c9e7c3 100644 --- a/pushbullet/requirements.txt +++ b/pushbullet/requirements.txt @@ -1,3 +1,2 @@ -requests>=2.9.1;python_version>'3.2' -requests==2.5.1;python_version=='3.2' +#requests requirement moved to core python-magic>=0.4.12 diff --git a/pushover/requirements.txt b/pushover/requirements.txt index 648060e1e..7491ce9ce 100644 --- a/pushover/requirements.txt +++ b/pushover/requirements.txt @@ -1,2 +1 @@ -requests>=2.9.1;python_version>'3.2' -requests==2.5.1;python_version=='3.2' +#requests requirement moved to core diff --git a/sonos/requirements.txt b/sonos/requirements.txt index f7357a07e..ff2420586 100644 --- a/sonos/requirements.txt +++ b/sonos/requirements.txt @@ -1,4 +1,3 @@ -requests>=2.9.1;python_version>'3.2' -requests==2.5.1;python_version=='3.2' +#requests requirement moved to core xmltodict>=0.11.0 tinytag>=0.18.0 diff --git a/tankerkoenig/requirements.txt b/tankerkoenig/requirements.txt index 648060e1e..7491ce9ce 100644 --- a/tankerkoenig/requirements.txt +++ b/tankerkoenig/requirements.txt @@ -1,2 +1 @@ -requests>=2.9.1;python_version>'3.2' -requests==2.5.1;python_version=='3.2' +#requests requirement moved to core diff --git a/traffic/requirements.txt b/traffic/requirements.txt index 648060e1e..7491ce9ce 100644 --- a/traffic/requirements.txt +++ b/traffic/requirements.txt @@ -1,2 +1 @@ -requests>=2.9.1;python_version>'3.2' -requests==2.5.1;python_version=='3.2' +#requests requirement moved to core From 8bcc1296dc312cd80f402cfa31f9ba236d162a4c Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 31 Oct 2018 14:01:25 +0100 Subject: [PATCH 350/705] AVM: started API definition in plugin.yaml --- avm/__init__.py | 4 +-- avm/plugin.yaml | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/avm/__init__.py b/avm/__init__.py index 481a9efaf..55688dfe0 100644 --- a/avm/__init__.py +++ b/avm/__init__.py @@ -1088,7 +1088,7 @@ def wol(self, mac_address): def get_hosts(self, only_active): """ - Gets the name of all hosts as an array + Gets the information (host details) of all hosts as an array of dicts Uses: http://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/hostsSCPD.pdf @@ -1121,7 +1121,7 @@ def get_hosts(self, only_active): def get_host_details(self, index): """ - Gets the name of a hosts at a specific index + Gets the information of a hosts at a specific index Uses: http://avm.de/fileadmin/user_upload/Global/Service/Schnittstellen/hostsSCPD.pdf diff --git a/avm/plugin.yaml b/avm/plugin.yaml index 022610a18..61ba8fe72 100755 --- a/avm/plugin.yaml +++ b/avm/plugin.yaml @@ -171,3 +171,69 @@ item_attributes: de: 'Definition der Aktor Identifikationsnummer (AIN)Items vom avm_data_type `aha_device`. Nur für diese Items mandatory!' en: 'Definition of the actor identification number (AIN) for items of avm_data_type `aha_device`. Only mandatory for these items!' +plugin_functions: + # Definition of function interface of the plugin + + reboot: + type: void + description: + de: "Startet das Gerät neu." + en: "Reboots the device." + parameters: + # This function has no parameters + + reconnect: + type: void + description: + de: "Verbindet das Gerät neu mit dem WAN (Wide Area Network)." + en: "Reconnects the device to the WAN (Wide Area Network)." + parameters: + # This function has no parameters + + wol: + type: void + description: + de: "Sendet einen WOL (WakeOnLAN) Befehl an eine MAC Adresse." + en: "Sends a WOL (WakeOnLAN) command to a MAC address." + parameters: + mac_address: + type: mac + description: + de: "MAC Adresse" + en: "MAC address" + + get_hosts: + type: list(dict(str)) + description: + de: "Ermittelt ein Array mit den Namen aller verbundener Hosts." + en: "Gets the name of all connected hosts as an array." + parameters: + only_active: + type: bool + description: + de: "True, wenn nur aktuell aktive Hosts zurückgegeben werden sollen." + en: "True, if only active hosts shall be returned." + + get_host_details: + type: dict(str) + description: + de: "Ermittelt die Informationen zu einem Host an einem angegebenen Index." + en: "Gets the information of a hosts at a specific index." + parameters: + index: + type: int + description: + de: "Index." + en: "Index." + + is_host_active: + type: bool + description: + de: "Prüft, ob eine MAC Adresse auf dem Gerät aktiv ist. Das kann bspw. für die Umsetzung einer Präsenzerkennung genutzt werden." + en: "Checks if a MAC address is active on the FritzDevice, e.g. the status can be used for simple presence detection." + parameters: + mac_address: + type: mac + description: + de: "MAC Adresse" + en: "MAC address" From eef95d3e530e43d99f4c0493bb514bd97f22463a Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 31 Oct 2018 14:23:08 +0100 Subject: [PATCH 351/705] AVM: added api functions --- avm/plugin.yaml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/avm/plugin.yaml b/avm/plugin.yaml index 61ba8fe72..bf4db48d7 100755 --- a/avm/plugin.yaml +++ b/avm/plugin.yaml @@ -237,3 +237,27 @@ plugin_functions: description: de: "MAC Adresse" en: "MAC address" + + get_contact_name_by_phone_number: + type: str + description: + de: "Durchsucht das Telefonbuch mit einer (vollständigen) Telefonnummer nach Kontakten. Falls kein Name gefunden wird, wird die Telefonnummer zurückgeliefert." + en: "Searches the phonebook for a contact by a given (complete) phone number. In case no name is found, the phone number is returned." + parameters: + phone_number: + type: str + description: + de: "Vollständige Telefonnummer" + en: "Complete phone number" + + get_phone_numbers_by_name: + type: str + description: + de: "Durchsucht das Telefonbuch mit einem Namen nach nach Kontakten." + en: "Searches the phonebook for a contact by a given name." + parameters: + name: + type: str + description: + de: "Anteiliger oder vollständiger Name des Kontakts." + en: "Partial or full name of the contact." From 81a64a7fd98d440217eeeff853e7d5ae3323fad8 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 31 Oct 2018 14:26:33 +0100 Subject: [PATCH 352/705] AVM: changes to api description --- avm/plugin.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/avm/plugin.yaml b/avm/plugin.yaml index bf4db48d7..87a6726ed 100755 --- a/avm/plugin.yaml +++ b/avm/plugin.yaml @@ -251,10 +251,10 @@ plugin_functions: en: "Complete phone number" get_phone_numbers_by_name: - type: str + type: dict(dict(str)) description: - de: "Durchsucht das Telefonbuch mit einem Namen nach nach Kontakten." - en: "Searches the phonebook for a contact by a given name." + de: "Durchsucht das Telefonbuch mit einem Namen nach nach Kontakten und liefert die zugehörigen Telefonnummern." + en: "Searches the phonebook for a contact by a given name and returns the corresponding phone numbers." parameters: name: type: str From 6cf5b15240f208d8e222b6e74b22f08b7a3821a9 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 31 Oct 2018 14:39:03 +0100 Subject: [PATCH 353/705] AVM added get_calllist to api --- avm/plugin.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/avm/plugin.yaml b/avm/plugin.yaml index 87a6726ed..17708c048 100755 --- a/avm/plugin.yaml +++ b/avm/plugin.yaml @@ -261,3 +261,15 @@ plugin_functions: description: de: "Anteiliger oder vollständiger Name des Kontakts." en: "Partial or full name of the contact." + + get_calllist: + type: list(dict(str)) + description: + de: "Ermittelt ein Array mit dicts aller Einträge der Anrufliste (Attribute 'Id','Type','Caller','Called','CalledNumber','Name','Numbertype','Device','Port','Date','Duration' (some optional))." + en: "Returns an array of dicts with all calllist entries (attributes 'Id','Type','Caller','Called','CalledNumber','Name','Numbertype','Device','Port','Date','Duration' (some optional))." + parameters: + filter_incoming: + type: str + description: + de: "Filter, um nur die Anrufe zu erhalten, die zu einer bestimmten angerufenen Nummer gehören." + en: "Filter to filter calls to a specific destination phone number." \ No newline at end of file From 59841dca0eccbfcfd2839458740311842797aa19 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 31 Oct 2018 16:06:53 +0100 Subject: [PATCH 354/705] AVM: added api methods --- avm/plugin.yaml | 56 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/avm/plugin.yaml b/avm/plugin.yaml index 17708c048..5b1ee4039 100755 --- a/avm/plugin.yaml +++ b/avm/plugin.yaml @@ -182,6 +182,58 @@ plugin_functions: parameters: # This function has no parameters + cancel_call: + type: void + description: + de: "Beendet einen aktiven Anruf." + en: "Cancels an active call." + parameters: + # This function has no parameters + + start_call: + type: void + description: + de: "Startet einen anruf an eine übergebene Telefonnummer (intern oder extern)." + en: "Starts a call for a given phone number (internal or external)." + parameters: + phone_number: + type: str + description: + de: "Vollständige Telefonnummer, die angerufen werden soll." + en: "Full phone number to call" + + get_call_origin: + type: str + description: + de: "Gib den Namen des Telefons zurück, das aktuell als 'call origin' gesetzt ist." + en: "Gets the phone name, currently set as 'call origin'." + parameters: + # This function has no parameters + + set_call_origin: + type: void + description: + de: "Setzt den 'call origin', bspw. vor dem Aufruf von 'start_call'" + en: "Sets the 'call origin', e.g. before running 'start_call'" + parameters: + phone_name: + type: mac + description: + de: "Identifikator des Telefons, dass als 'call origin' gesetzt werden soll. Bspw. '**610' für ein internes Gerät." + en: "Full phone identifier, could be e.g. '**610' for an internal device." + + get_phone_name: + type: str + description: + de: "Gibt den Namen eines Telefons an einem Index zurück. Der zurückgegebene Wert kann in 'set_call_origin' verwendet werden." + en: "Get the phone name at a specific index. The returend value can be used as phone_name for set_call_origin." + parameters: + index: + type: int + description: + de: "Index" + en: "Index" + reconnect: type: void description: @@ -223,8 +275,8 @@ plugin_functions: index: type: int description: - de: "Index." - en: "Index." + de: "Index" + en: "Index" is_host_active: type: bool From a73d993fed3553bee6d0539620624c53d388da63 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 31 Oct 2018 16:09:30 +0100 Subject: [PATCH 355/705] Backend: two column layout for plugin api functions --- backend/webif/templates/plugins.html | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/backend/webif/templates/plugins.html b/backend/webif/templates/plugins.html index 6be23934c..dd105be4c 100755 --- a/backend/webif/templates/plugins.html +++ b/backend/webif/templates/plugins.html @@ -172,10 +172,17 @@
{{ _('Pfad') }} {{ _('Typ') }}Nokia Health Data Type{{ _('Withings Health Data Type') }} {{ _('Wert') }} {{ _('Letztes Update') }} {{ _('Letzter Change') }} - {{ _('Hier zuerst registrieren:') }} https://account.health.nokia.com/partner/add_oauth2
+ {{ _('Hier zuerst registrieren:') }} https://account.withings.com/partner/add_oauth2
{{ _('Hier klicken, um OAuth2 Prozess zu starten!') }}
{% set first = True %} {% for func in p.metadata.get_plugin_function_defstrings() %} + {% if loop.index % 2 > 0 %} + {% endif %} + {% if loop.index %2 > 0 and loop.last %} + + {% endif %} + {% if loop.index % 2 > 0 and not first %} + {% endif %} {% endfor %}
{{ func }}
From 029b9368689865cbce63ec6db84fc6c00dee3085 Mon Sep 17 00:00:00 2001 From: msinn Date: Wed, 31 Oct 2018 23:11:42 +0100 Subject: [PATCH 356/705] Adjusted requirements --- join/requirements.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/join/requirements.txt b/join/requirements.txt index 648060e1e..7491ce9ce 100644 --- a/join/requirements.txt +++ b/join/requirements.txt @@ -1,2 +1 @@ -requests>=2.9.1;python_version>'3.2' -requests==2.5.1;python_version=='3.2' +#requests requirement moved to core From 5e2b0c34cff76f9fabcf4358a8a75edc3fb43aa2 Mon Sep 17 00:00:00 2001 From: msinn Date: Wed, 31 Oct 2018 23:44:50 +0100 Subject: [PATCH 357/705] Changes to tox.ini --- backend/BackendSysteminfo.py | 54 ++++++++++++++++++++++++++-- backend/__init__.py | 2 +- backend/plugin.yaml | 4 +-- homematic/__init__.py | 69 +++++++++++++++--------------------- homematic/user_doc.rst | 17 +++++++-- kodi/plugin.yaml | 4 ++- 6 files changed, 102 insertions(+), 48 deletions(-) diff --git a/backend/BackendSysteminfo.py b/backend/BackendSysteminfo.py index 91af2479a..2296a170f 100755 --- a/backend/BackendSysteminfo.py +++ b/backend/BackendSysteminfo.py @@ -39,6 +39,7 @@ import bin.shngversion as shngversion import lib.config from lib.shtime import Shtime +from lib.shpypi import Shpypi #from lib.logic import Logics #from lib.model.smartplugin import SmartPlugin from lib.utils import Utils @@ -53,6 +54,8 @@ def __init__(self): self.logger.info("BackendSysteminfo __init__ {}".format('')) + self.shpypi = Shpypi.get_instance() + # ----------------------------------------------------------------------------------- # SYSTEMINFO @@ -380,7 +383,46 @@ def pypi_json(self): package_list.append(package) - + # self.logger.warning('installed_packages: {}'.format(installed_packages)) + self.logger.warning('req_dict: {}'.format(req_dict)) + inst_pkgname_list = [] + for pkg in package_list: + inst_pkgname_list.append(pkg['name']) + self.logger.warning('pkgname_list: {}'.format(inst_pkgname_list)) + for req in req_dict: + if not (req in inst_pkgname_list): + pkg = {} + pkg['name'] = req + pkg['vers_installed'] = '-' + pkg['is_required'] = True + pkg['is_required_for_testsuite'] = True + pkg['is_required_for_docbuild'] = True + # tests for min, max versions + rmin, rmax, rtxt = self.check_requirement(pkg['name'], req_dict.get(pkg['name'], '')) + pkg['vers_req_min'] = rmin + pkg['vers_req_max'] = rmax + pkg['vers_req_msg'] = rtxt + pkg['sort'] = '1' + pkg['name'] + package_list.append(pkg) +### + if pypi_available: + try: + available = pypi.package_releases(pkg['name']) #(dist.project_name) + self.logger.debug("pypi_json: pypi package: project_name {}, availabe = {}".format(pkg['name'], available)) + try: + pkg['pypi_version'] = available[0] + except: + pkg['pypi_version_not_available_msg'] = '?' + except: + pkg['pypi_version'] = '--' + pkg['pypi_version_not_available_msg'] = [translate('Keine Antwort von PyPI')] + else: + pkg['pypi_version_not_available_msg'] = pypi_unavailable_message +### + + self.logger.warning('package_list: {}'.format(package_list)) + + # sorted_package_list = sorted([(i['name'], i['version_installed'], i['version_available']) for i in package_list]) sorted_package_list = sorted(package_list, key=lambda k: k['sort'], reverse=False) self.logger.info("pypi_json: sorted_package_list = {}".format(sorted_package_list)) @@ -394,8 +436,15 @@ def get_requirements_info(self, req_group='base'): """ req_dict = {} if req_group == 'base': -# req_dict_base = parse_requirements("%s/requirements/base.txt" % self._sh_dir) req_dict_base = parse_requirements(os.path.join(self._sh_dir, 'requirements', 'base.txt')) +# req_dict_base = self.shpypi.parse_requirementsfile(os.path.join(self._sh_dir, 'requirements', 'base.txt')) + dummy = self.shpypi.parse_requirementsfile(os.path.join(self._sh_dir, 'requirements', 'all.txt')) + dummy = self.shpypi.test_base_requirements() + dummy = self.shpypi.test_requirements(os.path.join(self._sh_dir, 'requirements', 'all.txt')) + dummy = self.shpypi.get_packagelist() + self.logger.warning("get_requirements_info: get_packagelist = {}".format(dummy)) + + elif req_group == 'test': req_dict_base = parse_requirements(os.path.join(self._sh_dir, 'tests', 'requirements.txt')) self.logger.info("get_requirements_info: filepath = {}".format(os.path.join(self._sh_dir, 'tests', 'requirements.txt'))) @@ -734,6 +783,7 @@ def getpackages(self): package['version_available'] = pypi_unavailable_message packages.append(package) + sorted_packages = sorted([(i['key'], i['version_installed'], i['version_available']) for i in packages]) return sorted_packages diff --git a/backend/__init__.py b/backend/__init__.py index f36f8d185..9fd070d04 100755 --- a/backend/__init__.py +++ b/backend/__init__.py @@ -49,7 +49,7 @@ class BackendServer(SmartPlugin): the update functions for the items """ - PLUGIN_VERSION = '1.4.13' + PLUGIN_VERSION = '1.4.14' def __init__(self, sh, updates_allowed='True', developer_mode="no", pypi_timeout=5): diff --git a/backend/plugin.yaml b/backend/plugin.yaml index 341635e23..56bbb0d34 100755 --- a/backend/plugin.yaml +++ b/backend/plugin.yaml @@ -51,8 +51,8 @@ plugin: # documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/959964-support-thread-für-das-backend-plugin - version: 1.4.13 # Plugin version - sh_minversion: 1.4e # minimum shNG version to use this plugin + version: 1.4.14 # Plugin version + sh_minversion: 1.5b # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance classname: BackendServer # class containing the plugin diff --git a/homematic/__init__.py b/homematic/__init__.py index 1c0f200e7..8c681c6d7 100755 --- a/homematic/__init__.py +++ b/homematic/__init__.py @@ -26,11 +26,7 @@ import logging -try: - from pyhomematic import HMConnection - REQUIRED_PACKAGE_IMPORTED = True -except: - REQUIRED_PACKAGE_IMPORTED = False +from pyhomematic import HMConnection from lib.module import Modules @@ -68,13 +64,9 @@ def __init__(self, sh, *args, **kwargs): the configured (and checked) value for a parameter by calling self.get_parameter_value(parameter_name). It returns the value in the datatype that is defined in the metadata. """ -# self.logger = logging.getLogger(__name__) - - # Exit if the required package(s) could not be imported - if not REQUIRED_PACKAGE_IMPORTED: - self.logger.error("{}: Unable to import Python package 'pyhomematic'".format(self.get_fullname())) - self._init_complete = False - return + from bin.smarthome import VERSION + if '.'.join(VERSION.split('.',2)[:2]) <= '1.5': + self.logger = logging.getLogger(__name__) # get the parameters for the plugin (as defined in metadata plugin.yaml): # self.param1 = self.get_parameter_value('param1') @@ -92,9 +84,6 @@ def __init__(self, sh, *args, **kwargs): self.hm_id = 'rf' if self.get_instance_name() != '': self.hm_id += '_' + self.get_instance_name() - self.log_instance_str = ' ('+self.get_instance_name()+')' - else: - self.log_instance_str = '' # create HomeMatic object try: self.hm = HMConnection(interface_id="myserver", autostart=False, @@ -102,7 +91,7 @@ def __init__(self, sh, *args, **kwargs): remotes={self.hm_id:{"ip": self.host, "port": self.port}}) # remotes={self.hm_id:{"ip": self.host, "port": self.port}, self.hmip_id:{"ip": self.host, "port": self.port_hmip}}) except: - self.logger.error("{}: Unable to create HomeMatic object".format(self.get_fullname())) + self.logger.error("Unable to create HomeMatic object") self._init_complete = False return @@ -118,7 +107,7 @@ def __init__(self, sh, *args, **kwargs): eventcallback=self.eventcallback, systemcallback=self.systemcallback, remotes={self.hmip_id:{"ip": self.host, "port": self.port_hmip}}) except: - self.logger.error("{}: Unable to create HomeMaticIP object".format(self.get_fullname())) + self.logger.error("Unable to create HomeMaticIP object") # self._init_complete = False # return @@ -131,7 +120,7 @@ def __init__(self, sh, *args, **kwargs): self.hm.start() self.connected = True except: - self.logger.error("{}: Unable to start HomeMatic object - SmartHomeNG will be unable to terminate the thread vor this plugin (instance)".format(self.get_fullname())) + self.logger.error("Unable to start HomeMatic object - SmartHomeNG will be unable to terminate the thread vor this plugin (instance)") self.connected = False # self._init_complete = False # stop the thread that got created by initializing pyhomematic @@ -149,7 +138,7 @@ def __init__(self, sh, *args, **kwargs): sleep(20) # self.logger.warning("Plugin '{}': self.hm.devices".format(self.hm.devices)) if self.hm.devices.get(self.hm_id,{}) == {}: - self.logger.error("{}: Connection to ccu failed".format(self.get_fullname())) + self.logger.error("Connection to ccu failed") # self._init_complete = False # stop the thread that got created by initializing pyhomematic # self.hm.stop() @@ -168,7 +157,7 @@ def run(self): """ Run method for the plugin """ - self.logger.debug("Plugin '{}': run method called".format(self.get_fullname())) + self.logger.debug("Run method called") self.alive = True # if you want to create child threads, do not make them daemon = True! # They will not shutdown properly. (It's a python bug) @@ -178,7 +167,7 @@ def stop(self): """ Stop method for the plugin """ - self.logger.debug("Plugin '{}': stop method called".format(self.get_fullname())) + self.logger.debug("Stop method called") self.alive = False self.hm.stop() self.hmip.stop() @@ -199,7 +188,7 @@ def parse_item(self, item): """ if self.has_iattr(item.conf, 'hm_address'): init_error = False -# self.logger.debug("parse_item{}: {}".format(self.log_instance_str, item)) +# self.logger.debug("parse_item: {}".format(item)) dev_id = self.get_iattr_value(item.conf, 'hm_address') @@ -219,13 +208,13 @@ def parse_item(self, item): hm_function = self.get_iattr_value(item.conf, 'hm_function') hm_node = '' if dev is None: - self.logger.error("parse_item{}: No HomeMatic device found with address '{}' for {}".format(self.log_instance_str, dev_id, item)) + self.logger.error("No HomeMatic device found with address '{}' channel {} for {}".format(hm_address, hm_channel, hm_function)) # return else: hm_devicetype = self.get_hmdevicetype( dev_id ) -# self.logger.warning("{}, parse_item {}: type='{}', hm_address='{}', hm_channel='{}', hm_function='{}', hm_devicetype='{}'".format(self.get_fullname(), item, item.type(), hm_address, hm_channel, hm_function, hm_devicetype)) +# self.logger.warning("parse_item {}: type='{}', hm_address='{}', hm_channel='{}', hm_function='{}', hm_devicetype='{}'".format(item, item.type(), hm_address, hm_channel, hm_function, hm_devicetype)) # Lookup hm_node and hm_channel for the configured hm_function if hm_function is None: @@ -242,9 +231,9 @@ def parse_item(self, item): if hm_node == '': hm_channel, hm_node = self.get_hmchannelforfunction(hm_function, hm_channel, dev.WRITENODE, 'WR', item) -# self.logger.warning("{}, parse_item {}: dev.ELEMENT='{}'".format(self.get_fullname(), item, dev.ELEMENT)) +# self.logger.warning("parse_item {}: dev.ELEMENT='{}'".format(item, dev.ELEMENT)) - self.logger.debug("parse_item{}: {}, type='{}', address={}:{}, function='{}', devicetype='{}'".format(self.log_instance_str, item, item.type(), hm_address, hm_channel, hm_function, hm_devicetype)) + self.logger.debug("{}, type='{}', address={}:{}, function='{}', devicetype='{}'".format(item, item.type(), hm_address, hm_channel, hm_function, hm_devicetype)) if hm_node == '': hm_node = None @@ -270,14 +259,14 @@ def parse_item(self, item): value = dev.getWriteData(hm_function) else: init_error = True - self.logger.error("parse_item{}: Not initializing {}: Unknown hm_node='{}' for address={}:{}, function={}".format(self.log_instance_str, item, hm_node, hm_address, hm_channel, hm_function)) + self.logger.error("Not initializing {}: Unknown hm_node='{}' for address={}:{}, function={}".format(item, hm_node, hm_address, hm_channel, hm_function)) if value is not None: - self.logger.info("parse_item{}: Initializing {} with '{}' from address={}:{}, function={}".format(self.log_instance_str, item, value, hm_address, hm_channel, hm_function)) + self.logger.info("Initializing {} with '{}' from address={}:{}, function={}".format(item, value, hm_address, hm_channel, hm_function)) item(value, 'HomeMatic', 'Init') else: if not init_error: - self.logger.error("parse_item{}: Not initializing {} from address={}:{}, function='{}'".format(self.log_instance_str, item, hm_node, hm_address, hm_channel, hm_function)) + self.logger.error("Not initializing {} from address={}:{}, function='{}'".format(item, hm_node, hm_address, hm_channel, hm_function)) return self.update_item @@ -306,9 +295,9 @@ def update_item(self, item, caller=None, source=None, dest=None): for i in self.hm_items: if item == i[1]: myitem = i - self.logger.warning("update_item{}: Test: item='{}', caller='{}', hm_function={}, itemvalue='{}'".format(self.log_instance_str, item, caller, i[4], item())) + self.logger.warning("update_item: Test: item='{}', caller='{}', hm_function={}, itemvalue='{}'".format(item, caller, i[4], item())) - self.logger.warning("update_item{}: Todo: Called with value '{}' for item '{}' from caller '{}', source '{}' and dest '{}'".format(self.log_instance_str, item(), item, caller, source, dest)) + self.logger.warning("update_item: Todo: Called with value '{}' for item '{}' from caller '{}', source '{}' and dest '{}'".format(item(), item, caller, source, dest)) dev_id = self.get_iattr_value(item.conf, 'hm_address') dev = self.hm.devices[self.hm_id].get(dev_id) @@ -319,7 +308,7 @@ def update_item(self, item, caller=None, source=None, dest=None): hm_channel = myitem[3] hm_function = myitem[4] dev.CHANNELS[int(hm_channel)].setValue(hm_function, item()) - self.logger.warning("{}, update_item (hm): Called with value '{}' for item '{}' from caller '{}', source '{}' and dest '{}'".format(self.get_fullname(), item(), item, caller, source, dest)) + self.logger.warning("update_item (hm): Called with value '{}' for item '{}' from caller '{}', source '{}' and dest '{}'".format(item(), item, caller, source, dest)) else: dev = self.hmip.devices[self.hmip_id].get(dev_id) # Write item value to HomeMaticIP device @@ -328,7 +317,7 @@ def update_item(self, item, caller=None, source=None, dest=None): hm_channel = myitem[3] hm_function = myitem[4] dev.CHANNELS[int(hm_channel)].setValue(hm_function, item()) - self.logger.warning("{}, update_item (hmIP): Called with value '{}' for item '{}' from caller '{}', source '{}' and dest '{}'".format(self.get_fullname(), item(), item, caller, source, dest)) + self.logger.warning("update_item (hmIP): Called with value '{}' for item '{}' from caller '{}', source '{}' and dest '{}'".format(item(), item, caller, source, dest)) # ACTIONNODE: PRESS_LONG (action), PRESS_SHORT (action), [LEVEL (float 0.0-1.0)] # LEVEL (float: 0.0-1.0), STOP (action), INHIBIT (bool), INSTALL_TEST (action), @@ -373,12 +362,12 @@ def init_webinterface(self): except: self.mod_http = None if self.mod_http == None: - self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_shortname())) + self.logger.error("Not initializing the web interface") return False import sys if not "SmartPluginWebIf" in list(sys.modules['lib.model.smartplugin'].__dict__): - self.logger.warning("Plugin '{}': Web interface needs SmartHomeNG v1.5 and up. Not initializing the web interface".format(self.get_shortname())) + self.logger.warning("Web interface needs SmartHomeNG v1.5 and up. Not initializing the web interface") return False # set application configuration for cherrypy @@ -446,14 +435,14 @@ def get_hmchannelforfunction(self, hm_function, hm_channel, node, hm_node, item) if not int(hm_channel) in node[hm_function]: hm_node = '' - self.logger.error("get_hmchannelforfunction{}: Invalid channel '{}' specified for {}".format(self.log_instance_str, hm_channel, item)) + self.logger.error("get_hmchannelforfunction: Invalid channel '{}' specified for {}".format(hm_channel, item)) else: hm_node = '' return hm_channel, hm_node def systemcallback(self, src, *args): - self.logger.info("systemcallback{}: src = '{}', args = '{}'".format(self.log_instance_str, src, args)) + self.logger.info("systemcallback: src = '{}', args = '{}'".format(src, args)) def eventcallback(self, interface_id, address, value_key, value): @@ -466,13 +455,13 @@ def eventcallback(self, interface_id, address, value_key, value): for i in self.hm_items: if address == i[2]+':'+str(i[3]): if value_key == i[4]: - self.logger.info("eventcallback{}: address={}, {}='{}' -> {}".format(self.log_instance_str, address, value_key, value, i[0])) + self.logger.info("eventcallback: address={}, {}='{}' -> {}".format(address, value_key, value, i[0])) # i[1](value, 'HomeMatic', address) i[1](value, 'HomeMatic') defined = True if not defined: - self.logger.debug("eventcallback{}: Ohne item Zuordnung: interface_id = '{}', address = '{}', {} = '{}'".format(self.log_instance_str, interface_id, address, value_key, value)) + self.logger.debug("eventcallback: Ohne item Zuordnung: interface_id = '{}', address = '{}', {} = '{}'".format(interface_id, address, value_key, value)) # ------------------------------------------ @@ -585,7 +574,7 @@ def index(self, learn=None, reload=None): d['dev'] = dev ipdevice_count = len(ipdevices) - self.logger.warning("ipdevice_count = {}, ipdevices = {}".format(ipdevice_count, ipdevices)) + # self.logger.warning("ipdevice_count = {}, ipdevices = {}".format(ipdevice_count, ipdevices)) tmpl = self.tplenv.get_template('index.html') # The first paramter for the render method has to be specified. the base template diff --git a/homematic/user_doc.rst b/homematic/user_doc.rst index f9856eb67..0596fa1a1 100755 --- a/homematic/user_doc.rst +++ b/homematic/user_doc.rst @@ -6,12 +6,25 @@ homematic Das Plugin unterstützt HomeMatic und HomeMatic IP Geräte, die an einer HomeMatic CCU2 angelernt sind. Es wird eine große Zahl von HomeMatic Geräten unterstützt. Wenn ein Gerät nicht unterstützt wird, -hilft evtl. ein einfaches Update des Python Modules **pyhomematic** mit dem folgenden Kommando: +hilft evtl. ein einfaches Update des Python Packages **pyhomematic** mit dem folgenden Kommando: sudo pip3 install -U pyhomematic -Die Unterstützung der einzelnen HomeMatic und HomeMatic IP Geräte ist in dem Python Modul implementiert. +Die Unterstützung der einzelnen HomeMatic und HomeMatic IP Geräte ist in dem Python Package implementiert. + +.. important:: + + Für HomeMatic IP Devices ist eine Besonderheit zu beachten: Wenn die CCU2 neu gestartet wurde, stehen für HomeMatic IP + Devices nicht alle Attribute zur Verfügung. Hierin unterscheiden sich HomeMatic IP Devices von HomeMatic Devices. + Wenn diese Attribute durch SmartHomeNG abgefragt werden bevor sie in der CCU2 initialisier wurden, loggt das Python + Package **pyhomematic** einen Fehler in das Log von SmartHomeNG. Diese Fehlemedungen sehen etwa so aus: + + 2018-10-20 19:18:12 ERROR pyhomematic.devicetypes.generic HMGeneric.getValue: DUTY_CYCLE on 0007D7099D0552:0 Exception: + + Diese Fehler verschwinden nach einer gewissen Laufzeit der CCU2, wenn nach und nach entsprechende Messages von den + Devices bei der CCU2 eingehen. Die Dauer ist dabei z.B. abhängig von den in den HomeMatic IP eingestellten Sende-Zyklen. + Eventuell senden die Devices auch erst nach einem Statuswechsel eine Message an die CCU2. Konfiguration diff --git a/kodi/plugin.yaml b/kodi/plugin.yaml index 76ba318e4..385385f74 100755 --- a/kodi/plugin.yaml +++ b/kodi/plugin.yaml @@ -29,7 +29,9 @@ parameters: type: int valid_min: 0 default: 9090 - + description: + en: 'English description' + item_attributes: # Definition of item attributes defined by this plugin From 3e8f450d78056547fc346a8339d3935dcec6633a Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 1 Nov 2018 09:21:13 +0100 Subject: [PATCH 358/705] AVM: changed type to mac (from str) --- avm/plugin.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/plugin.yaml b/avm/plugin.yaml index 5b1ee4039..e132c0400 100755 --- a/avm/plugin.yaml +++ b/avm/plugin.yaml @@ -159,7 +159,7 @@ item_attributes: de: '(optional) Definition der erlaubten angerufenen Rufnummer in Items vom avm_data_type `monitor_trigger`.' en: '(optional) Definition of the allowed called number. Only in items of avm_data_type `monitor_trigger`.' mac: - type: str + type: mac mandatory: False description: de: 'Definition der MAC Adresse für Items vom avm_data_type `network_device`. Nur für diese Items mandatory!' From 7849371035b70170d55b7aca1b07832a5a1064d2 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 1 Nov 2018 11:31:12 +0100 Subject: [PATCH 359/705] Nuki: - started rework on plugin to find out about problems with 2 nukis.. - logging adapted - added WebIF --- nuki/__init__.py | 138 +++++++++++++++++++++----- nuki/locale.yaml | 14 +++ nuki/webif/static/img/plugin_logo.png | Bin 0 -> 34199 bytes nuki/webif/templates/index.html | 113 +++++++++++++++++++++ 4 files changed, 241 insertions(+), 24 deletions(-) create mode 100644 nuki/locale.yaml create mode 100644 nuki/webif/static/img/plugin_logo.png create mode 100644 nuki/webif/templates/index.html diff --git a/nuki/__init__.py b/nuki/__init__.py index f54dd692b..03e014940 100644 --- a/nuki/__init__.py +++ b/nuki/__init__.py @@ -25,7 +25,7 @@ import requests import lib.connection import re -from lib.model.smartplugin import SmartPlugin +from lib.model.smartplugin import * nuki_action_items = {} nuki_event_items = {} @@ -89,12 +89,12 @@ def __init__(self, sh, *args, **kwargs): self._callback_ip = self.get_local_ipv4_address() if not self._callback_ip: - self._logger.critical("Nuki: Could not fetch internal ip address. Set it manually!") + self._logger.critical("Plugin '{}': Could not fetch internal ip address. Set it manually!".format(self.get_shortname())) self.alive = False return - self._logger.info("Nuki: using local ip address {ip}".format(ip=self._callback_ip)) + self._logger.info("Plugin '{pluginname}': using local ip address {ip}".format(pluginname=self.get_shortname(), ip=self._callback_ip)) else: - self._logger.info("Nuki: using given ip address {ip}".format(ip=self._callback_ip)) + self._logger.info("Plugin '{pluginname}': using given ip address {ip}".format(pluginname=self.get_shortname(), ip=self._callback_ip)) self._callback_url = "http://{ip}:{port}/".format(ip=self._callback_ip, port=self._callback_port) @@ -107,6 +107,8 @@ def __init__(self, sh, *args, **kwargs): 5, # lockAndGoWithUnlatch ] + self.init_webinterface() + def run(self): self._clear_callbacks() self.scheduler_add(__name__, self._scheduler_job, prio=3, cron=None, cycle=300, value=None, @@ -125,14 +127,14 @@ def stop(self): def parse_item(self, item): if self.has_iattr(item.conf, 'nuki_id'): - self._logger.debug("parse item: {0}".format(item)) + self._logger.debug("Plugin '{0}': parse item: {1}".format(self.get_shortname(), item)) nuki_id = self.get_iattr_value(item.conf, 'nuki_id') if self.has_iattr(item.conf, 'nuki_trigger'): nuki_trigger = self.get_iattr_value(item.conf, "nuki_trigger") if nuki_trigger.lower() not in ['state', 'action', 'battery']: - self._logger.warning("Nuki: Item {item} defines an invalid Nuki trigger {trigger}! " - "It has to be 'state' or 'action'.".format(item=item, trigger=nuki_trigger)) + self._logger.warning("Plugin '{pluginname}': Item {item} defines an invalid Nuki trigger {trigger}! " + "It has to be 'state' or 'action'.".format(pluginname=self.get_shortname(), item=item, trigger=nuki_trigger)) return if nuki_trigger.lower() == 'state': nuki_event_items[item] = int(nuki_id) @@ -141,8 +143,8 @@ def parse_item(self, item): else: nuki_battery_items[item] = int(nuki_id) else: - self._logger.warning("Nuki: Item {item} defines a Nuki ID but no nuki trigger! " - "This item has no effect.".format(item=item)) + self._logger.warning("Plugin '{pluginname}': Item {item} defines a Nuki ID but no nuki trigger! " + "This item has no effect.".format(pluginname=self.get_shortname(), item=item)) return return self.update_item @@ -154,7 +156,7 @@ def update_item(self, item, caller=None, source=None, dest=None): if item in nuki_action_items: action = item() if action not in self._lockActions: - self._logger.warning("Nuki: action {action} not in list of possible actions.".format(action=action)) + self._logger.warning("Plugin '{pluginname}': action {action} not in list of possible actions.".format(pluginname=self.get_shortname(), action=action)) return response = self._api_call(self._base_url, nuki_id=nuki_action_items[item], endpoint='lockAction', @@ -162,9 +164,9 @@ def update_item(self, item, caller=None, source=None, dest=None): if response is not None: if response['success']: # self._get_nuki_status() - self._logger.info("Nuki: update item: {0}".format(item.id())) + self._logger.info("Plugin '{0}': update item: {1}".format(self.get_shortname(), item.id())) else: - self._logger.error("Nuki: no response.") + self._logger.error("Plugin '{}': no response.".format(self.get_shortname())) @staticmethod def update_lock_state(nuki_id, lock_state): @@ -193,7 +195,7 @@ def _get_paired_nukis(self): for nuki in response: paired_nukis.append(nuki['nukiId']) self._logger.info( - 'Nuki: Paired Nuki Lock found: {name} - {id}'.format(name=nuki['name'], id=nuki['nukiId'])) + "Plugin '{pluginname}': Paired Nuki Lock found: {name} - {id}".format(pluginname=self.get_shortname(), name=nuki['name'], id=nuki['nukiId'])) self._logger.debug(paired_nukis) def _clear_callbacks(self): @@ -202,10 +204,10 @@ def _clear_callbacks(self): for c in callbacks['callbacks']: response = self._api_call(self._base_url, endpoint='callback/remove', token=self._token, id=c['id']) if response['success']: - self._logger.debug("Nuki: Callback with id {id} removed.".format(id=c['id'])) + self._logger.debug("Plugin '{pluginname}': Callback with id {id} removed.".format(pluginname=self.get_shortname(), id=c['id'])) return - self._logger.debug("Nuki: Could not remove callback with id {id}: {message}". - format(id=c['id'], message=c['message'])) + self._logger.debug("Plugin '{pluginname}': Could not remove callback with id {id}: {message}". + format(pluginname=self.get_shortname(), id=c['id'], message=c['message'])) def _register_callback(self): found = False @@ -219,17 +221,21 @@ def _register_callback(self): response = self._api_call(self._base_url, endpoint='callback/add', token=self._token, callback_url=self._callback_url) if not response['success']: - self._logger.warning('Nuki: Error establishing the callback url: {message}'.format - (message=response['message'])) + self._logger.warning("Plugin '{pluginname}': Error establishing the callback url: {message}".format + (pluginname=self.get_shortname(), message=response['message'])) else: - self._logger.info('Nuki: Callback URL registered.') + self._logger.info("Plugin '{}': Callback URL registered.".format + (self.get_shortname())) else: - self._logger.info('Nuki: Callback URL already registered') + self._logger.info("Plugin '{}': Callback URL already registered".format + (self.get_shortname())) else: - self._logger.warning('Nuki: No callback ip set. Automatic Nuki lock status updates not available.') + self._logger.warning("Plugin '{}': No callback ip set. Automatic Nuki lock status updates not available.".format + (self.get_shortname())) def _get_nuki_status(self): - self._logger.info("Nuki: Getting Nuki status ...") + self._logger.info("Plugin '{}': Getting Nuki status ...".format + (self.get_shortname())) for nuki_id in paired_nukis: response = self._api_call(self._base_url, endpoint='lockState', nuki_id=nuki_id, token=self._token, no_wait=self._noWait) @@ -247,7 +253,7 @@ def _api_call(self, base_url, endpoint=None, nuki_id=None, token=None, action=No payload['action'] = action if no_wait is not None: payload['noWait'] = int(no_wait) - self._logger.debug("Nuki: noWait is {}".format(int(no_wait))) + self._logger.debug("Plugin '{}': noWait is {}".format(self.get_shortname(), int(no_wait))) if callback_url is not None: payload['url'] = callback_url if id is not None: @@ -257,4 +263,88 @@ def _api_call(self, base_url, endpoint=None, nuki_id=None, token=None, action=No response.raise_for_status() return json.loads(response.text) except Exception as ex: - self._logger.error(ex) \ No newline at end of file + self._logger.error(ex) + + def get_event_items(self): + return nuki_event_items + + def get_battery_items(self): + return nuki_battery_items + + def get_action_items(self): + return nuki_action_items + + def init_webinterface(self): + """" + Initialize the web interface for this plugin + + This method is only needed if the plugin is implementing a web interface + """ + try: + self.mod_http = Modules.get_instance().get_module( + 'http') # try/except to handle running in a core version that does not support modules + except: + self.mod_http = None + if self.mod_http is None: + self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_shortname())) + return False + + # set application configuration for cherrypy + webif_dir = self.path_join(self.get_plugin_dir(), 'webif') + config = { + '/': { + 'tools.staticdir.root': webif_dir, + }, + '/static': { + 'tools.staticdir.on': True, + 'tools.staticdir.dir': 'static' + } + } + + # Register the web interface as a cherrypy app + self.mod_http.register_webif(WebInterface(webif_dir, self), + self.get_shortname(), + config, + self.get_classname(), self.get_instance_name(), + description='') + + return True + +# ------------------------------------------ +# Webinterface of the plugin +# ------------------------------------------ + +import cherrypy +from jinja2 import Environment, FileSystemLoader + +class WebInterface(SmartPluginWebIf): + + def __init__(self, webif_dir, plugin): + """ + Initialization of instance of class WebInterface + + :param webif_dir: directory where the webinterface of the plugin resides + :param plugin: instance of the plugin + :type webif_dir: str + :type plugin: object + """ + self.logger = logging.getLogger(__name__) + self.webif_dir = webif_dir + self.plugin = plugin + + self.tplenv = self.init_template_environment() + + @cherrypy.expose + def index(self, reload=None): + """ + Build index.html for cherrypy + + Render the template and return the html file to be delivered to the browser + + :return: contents of the template after beeing rendered + """ + tmpl = self.tplenv.get_template('index.html') + return tmpl.render(plugin_shortname=self.plugin.get_shortname(), plugin_version=self.plugin.get_version(), + interface=None, item_count=len(self.plugin.get_event_items())+len(self.plugin.get_action_items())+len(self.plugin.get_battery_items()), + plugin_info=self.plugin.get_info(), tabcount=1, + p=self.plugin) diff --git a/nuki/locale.yaml b/nuki/locale.yaml new file mode 100644 index 000000000..f9bf8c8ce --- /dev/null +++ b/nuki/locale.yaml @@ -0,0 +1,14 @@ +plugin_translations: + 'Token': {'de': '=', 'en': '='} + 'Callback URL (SHNG)': {'de': '=', 'en': '='} + 'NoWait': {'de': '=', 'en': '='} + 'Base URL (Nuki Bridge)': {'de': '=', 'en': '='} + 'Pfad': {'de': '=', 'en': 'Path'} + 'Typ': {'de': '=', 'en': 'Type'} + 'Nuki ID': {'de': '=', 'en': '='} + 'Wert': {'de': '=', 'en': 'Value'} + 'Letztes Update': {'de': '=', 'en': 'Last Update'} + 'Letzter Change': {'de': '=', 'en': 'Last Change'} + 'Nuki Action Items': {'de': '=', 'en': '='} + 'Nuki Battery Items': {'de': '=', 'en': '='} + 'Nuki Event Items': {'de': '=', 'en': '='} diff --git a/nuki/webif/static/img/plugin_logo.png b/nuki/webif/static/img/plugin_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..4f6d8f5a1104b91c738f0a48dcc3f526e146872f GIT binary patch literal 34199 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�gMuXL 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 literal 0 HcmV?d00001 diff --git a/nuki/webif/templates/index.html b/nuki/webif/templates/index.html new file mode 100644 index 000000000..c23428801 --- /dev/null +++ b/nuki/webif/templates/index.html @@ -0,0 +1,113 @@ +{% extends "base_plugin.html" %} + +{% set logo_frame = false %} +{% set use_bodytabs = true %} + +{% set tab1title = "GFGFDG" %} + +{% block headtable %} + + + + + + + + + + + + + + + + +
{{ _('Token') }}{{ p._token }}{{ _('Callback URL (SHNG)') }}{{ p._callback_ip }}:{{ p._callback_port }}
{{ _('NoWait') }}{{ p._noWait }}{{ _('Base URL (Nuki Bridge)') }}{{ p._base_url }}
+{% endblock %} + +{% block bodytab1 %} + +
+
+
{{ _('Nuki Event Items') }} ({{ p.get_event_items()|length }})
+ + + + + + + + + + + + + + {% for item, value in p.get_event_items().items() %} + + + + + + + + + {% endfor %} + +
{{ _('Pfad') }}{{ _('Typ') }}{{ _('Nuki ID') }}{{ _('Wert') }}{{ _('Letztes Update') }}{{ _('Letzter Change') }}
{{ item.id() }}{{ item.type() }}{{ value }}{{ item() }}{{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }}{{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }}
+
{{ _('Nuki Action Items') }} ({{ p.get_action_items()|length }})
+ + + + + + + + + + + + + + {% for item, value in p.get_action_items().items() %} + + + + + + + + + {% endfor %} + +
{{ _('Pfad') }}{{ _('Typ') }}{{ _('Nuki ID') }}{{ _('Wert') }}{{ _('Letztes Update') }}{{ _('Letzter Change') }}
{{ item.id() }}{{ item.type() }}{{ value }}{{ item() }}{{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }}{{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }}
+
{{ _('Nuki Battery Items') }} ({{ p.get_battery_items()|length }})
+ + + + + + + + + + + + + + {% for item, value in p.get_battery_items().items() %} + + + + + + + + + {% endfor %} + +
{{ _('Pfad') }}{{ _('Typ') }}{{ _('Nuki ID') }}{{ _('Wert') }}{{ _('Letztes Update') }}{{ _('Letzter Change') }}
{{ item.id() }}{{ item.type() }}{{ value }}{{ item() }}{{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }}{{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }}
+
+
+ +{% endblock %} From 05a98a4107605e04b2e7ace3c7d4089da5a9c9f8 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 1 Nov 2018 11:37:54 +0100 Subject: [PATCH 360/705] Nuki:added logo for webif --- nuki/webif/static/img/plugin_logo.png | Bin 34199 -> 29021 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/nuki/webif/static/img/plugin_logo.png b/nuki/webif/static/img/plugin_logo.png index 4f6d8f5a1104b91c738f0a48dcc3f526e146872f..103de9b7f348aad1dfd77b74557bacf77bbeb286 100644 GIT binary patch delta 26486 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�gMuXL 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 From 471cc05814b959ebdcc7508b4f1af6cee9956523 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 1 Nov 2018 11:39:11 +0100 Subject: [PATCH 361/705] Nuki: increased version --- nuki/__init__.py | 2 +- nuki/plugin.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nuki/__init__.py b/nuki/__init__.py index 03e014940..d31554640 100644 --- a/nuki/__init__.py +++ b/nuki/__init__.py @@ -67,7 +67,7 @@ def handle_connection(self): class Nuki(SmartPlugin): - PLUGIN_VERSION = "1.5.0.3" + PLUGIN_VERSION = "1.5.0.4" ALLOW_MULTIINSTANCE = False def __init__(self, sh, *args, **kwargs): diff --git a/nuki/plugin.yaml b/nuki/plugin.yaml index 028127cc3..b2c517c19 100755 --- a/nuki/plugin.yaml +++ b/nuki/plugin.yaml @@ -12,7 +12,7 @@ plugin: # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1052437-nuki-smartlock-plugin-support-thread - version: 1.5.0.3 # Plugin version + version: 1.5.0.4 # Plugin version sh_minversion: 1.5 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance From be38af24051aec12310f2049a6e5eec461c72552 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 1 Nov 2018 11:56:09 +0100 Subject: [PATCH 362/705] Nuki: added textual information about lock state --- nuki/locale.yaml | 5 +++++ nuki/webif/templates/index.html | 9 ++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/nuki/locale.yaml b/nuki/locale.yaml index f9bf8c8ce..8aa8def82 100644 --- a/nuki/locale.yaml +++ b/nuki/locale.yaml @@ -12,3 +12,8 @@ plugin_translations: 'Nuki Action Items': {'de': '=', 'en': '='} 'Nuki Battery Items': {'de': '=', 'en': '='} 'Nuki Event Items': {'de': '=', 'en': '='} + 'unlock': {'de': 'aufgesperrt', 'en': '='} + 'lock': {'de': 'abgeschlossen', 'en': '='} + 'unlatch': {'de': 'entriegelt', 'en': '='} + 'lockAndGo': {'de': 'Lock And Go', 'en': 'Lock And Go'} + 'lockAndGoWithUnlatch': {'de': 'Lock And Go mit Entriegeln', 'en': 'Lock And Go with unlatch'} \ No newline at end of file diff --git a/nuki/webif/templates/index.html b/nuki/webif/templates/index.html index c23428801..cfd2f150d 100644 --- a/nuki/webif/templates/index.html +++ b/nuki/webif/templates/index.html @@ -48,7 +48,14 @@
{{ _('Nuki Event Items') }} ({{ p.get_event_items()|length }})
{{ item.id() }} {{ item.type() }} {{ value }} - {{ item() }} + + {{ item() }} + {% if item() == 1 %}({{ _('unlock') }}){% endif %} + {% if item() == 2 %}({{ _('lock') }}){% endif %} + {% if item() == 3 %}({{ _('unlatch') }}){% endif %} + {% if item() == 4 %}({{ _('lockAndGo') }}){% endif %} + {% if item() == 5 %}({{ _('lockAndGoWithUnlatch') }}){% endif %} + {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} {{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }} From a28a60e8abfdd215524360fa38f3705c93f3a857 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 1 Nov 2018 12:03:05 +0100 Subject: [PATCH 363/705] Nuki: Webif Translation and Layout fixes --- nuki/locale.yaml | 3 ++- nuki/webif/templates/index.html | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/nuki/locale.yaml b/nuki/locale.yaml index 8aa8def82..c98d41576 100644 --- a/nuki/locale.yaml +++ b/nuki/locale.yaml @@ -16,4 +16,5 @@ plugin_translations: 'lock': {'de': 'abgeschlossen', 'en': '='} 'unlatch': {'de': 'entriegelt', 'en': '='} 'lockAndGo': {'de': 'Lock And Go', 'en': 'Lock And Go'} - 'lockAndGoWithUnlatch': {'de': 'Lock And Go mit Entriegeln', 'en': 'Lock And Go with unlatch'} \ No newline at end of file + 'lockAndGoWithUnlatch': {'de': 'Lock And Go mit Entriegeln', 'en': 'Lock And Go with unlatch'} + 'Possible Lock States': {'de': 'Mögliche Zustände des Schlosses', 'en': '='} \ No newline at end of file diff --git a/nuki/webif/templates/index.html b/nuki/webif/templates/index.html index cfd2f150d..e15252951 100644 --- a/nuki/webif/templates/index.html +++ b/nuki/webif/templates/index.html @@ -62,6 +62,18 @@
{{ _('Nuki Event Items') }} ({{ p.get_event_items()|length }})
{% endfor %} +
+
+
{{ _('Possible Lock States') }}:
+

+ 1: {{ _('unlock') }}  -   + 2: {{ _('lock') }}  -   + 3: {{ _('unlatch') }}  -   + 4: {{ _('lockAndGo') }}  -   + 5: {{ _('lockAndGoWithUnlatch') }} +

+
+

{{ _('Nuki Action Items') }} ({{ p.get_action_items()|length }})
From 8db1564d0c921a1a9c713da9e54ef79c112be9bc Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 1 Nov 2018 12:04:42 +0100 Subject: [PATCH 364/705] SMA EM: allow to start plugin without webif --- sma_em/__init__.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sma_em/__init__.py b/sma_em/__init__.py index 41004c9df..b37e68e32 100644 --- a/sma_em/__init__.py +++ b/sma_em/__init__.py @@ -60,8 +60,7 @@ def __init__(self, smarthome, serial, time_sleep=5): mreq = struct.pack("4sl", socket.inet_aton(self.MCAST_GRP), socket.INADDR_ANY) self.sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) - if not self.init_webinterface(): - self._init_complete = False + self.init_webinterface() def get_serial(self): return self._serial From e8a2cb4efcc6d4716076cb4c37c01a38d5a530b0 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 1 Nov 2018 12:42:35 +0100 Subject: [PATCH 365/705] Nuki: corrected state and action translations --- nuki/README.md | 2 +- nuki/locale.yaml | 19 +++++++++--- nuki/webif/templates/index.html | 51 ++++++++++++++++++++++++++------- 3 files changed, 56 insertions(+), 16 deletions(-) diff --git a/nuki/README.md b/nuki/README.md index 7c6d710bf..cbf1fbf3b 100644 --- a/nuki/README.md +++ b/nuki/README.md @@ -76,7 +76,7 @@ whenever these lock state was changed. Find the list with the possible values be * 4 (locking) * 5 (unlatched) * 6 (unlatched (lock 'n' go)) -* 7 (unlachting) +* 7 (unlatching) * 254 (motor blocked) * 255 (undefined) diff --git a/nuki/locale.yaml b/nuki/locale.yaml index c98d41576..e8aef785b 100644 --- a/nuki/locale.yaml +++ b/nuki/locale.yaml @@ -12,9 +12,20 @@ plugin_translations: 'Nuki Action Items': {'de': '=', 'en': '='} 'Nuki Battery Items': {'de': '=', 'en': '='} 'Nuki Event Items': {'de': '=', 'en': '='} - 'unlock': {'de': 'aufgesperrt', 'en': '='} - 'lock': {'de': 'abgeschlossen', 'en': '='} - 'unlatch': {'de': 'entriegelt', 'en': '='} + 'Possible Lock Actions': {'de': 'Mögliche Aktionen des Schlosses', 'en': '='} + 'unlock': {'de': 'Aufsperren', 'en': '='} + 'lock': {'de': 'Abschließen', 'en': '='} + 'unlatch': {'de': 'Entriegeln', 'en': '='} 'lockAndGo': {'de': 'Lock And Go', 'en': 'Lock And Go'} 'lockAndGoWithUnlatch': {'de': 'Lock And Go mit Entriegeln', 'en': 'Lock And Go with unlatch'} - 'Possible Lock States': {'de': 'Mögliche Zustände des Schlosses', 'en': '='} \ No newline at end of file + 'Possible Lock States': {'de': 'Mögliche Zustände des Schlosses', 'en': '='} + 'uncalibrated': {'de': 'unkalibriert', 'en': '='} + 'locked': {'de': 'verschlossen', 'en': '='} + 'unlocking': {'de': 'aufschließend', 'en': '='} + 'unlocked': {'de': 'unverschlossen', 'en': '='} + 'locking': {'de': 'schließend', 'en': '='} + 'unlatched': {'de': 'aufgeklinkt', 'en': '='} + 'unlatched (lock and go)': {'de': 'aufgeklinkt (Lock And Go)', 'en': 'unlatched (Lock And Go)'} + 'unlatching': {'de': 'aufklinkend', 'en': '='} + 'motor blocked': {'de': 'Motor blockiert', 'en': '='} + 'undefined': {'de': 'undefiniert', 'en': '='} \ No newline at end of file diff --git a/nuki/webif/templates/index.html b/nuki/webif/templates/index.html index e15252951..ff4a0cf69 100644 --- a/nuki/webif/templates/index.html +++ b/nuki/webif/templates/index.html @@ -50,11 +50,16 @@
{{ _('Nuki Event Items') }} ({{ p.get_event_items()|length }})
@@ -66,11 +71,16 @@
{{ _('Nuki Event Items') }} ({{ p.get_event_items()|length }})
{{ _('Possible Lock States') }}:

- 1: {{ _('unlock') }}  -   - 2: {{ _('lock') }}  -   - 3: {{ _('unlatch') }}  -   - 4: {{ _('lockAndGo') }}  -   - 5: {{ _('lockAndGoWithUnlatch') }} + 0: {{ _('uncalibrated') }}  -   + 1: {{ _('locked') }}  -   + 2: {{ _('unlocking') }}  -   + 3: {{ _('unlocked') }}  -   + 4: {{ _('locking') }}  -   + 5: {{ _('unlatched') }}  -   + 6: {{ _('unlatched (lock and go)') }}  -   + 7: {{ _('unlatching') }}  -   + 254: {{ _('motor blocked') }}  -   + 255: {{ _('undefined') }}


@@ -93,13 +103,32 @@
{{ _('Nuki Action Items') }} ({{ p.get_action_items()|length }})
- + {% endfor %}
{{ value }} {{ item() }} - {% if item() == 1 %}({{ _('unlock') }}){% endif %} - {% if item() == 2 %}({{ _('lock') }}){% endif %} - {% if item() == 3 %}({{ _('unlatch') }}){% endif %} - {% if item() == 4 %}({{ _('lockAndGo') }}){% endif %} - {% if item() == 5 %}({{ _('lockAndGoWithUnlatch') }}){% endif %} + {% if item() == 0 %}({{ _('uncalibrated') }}){% endif %} + {% if item() == 1 %}({{ _('locked') }}){% endif %} + {% if item() == 2 %}({{ _('unlocking') }}){% endif %} + {% if item() == 3 %}({{ _('unlocked') }}){% endif %} + {% if item() == 4 %}({{ _('locking') }}){% endif %} + {% if item() == 5 %}({{ _('unlatched') }}){% endif %} + {% if item() == 6 %}({{ _('unlatched (lock and go)') }}){% endif %} + {% if item() == 7 %}({{ _('unlatching') }}){% endif %} + {% if item() == 254 %}({{ _('motor blocked') }}){% endif %} + {% if item() == 255 %}({{ _('undefined') }}){% endif %} {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} {{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }} {{ item.id() }} {{ item.type() }} {{ value }}{{ item() }} + {{ item() }} + {% if item() == 1 %}({{ _('unlock') }}){% endif %} + {% if item() == 2 %}({{ _('lock') }}){% endif %} + {% if item() == 3 %}({{ _('unlatch') }}){% endif %} + {% if item() == 4 %}({{ _('lockAndGo') }}){% endif %} + {% if item() == 5 %}({{ _('lockAndGoWithUnlatch') }}){% endif %} + {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} {{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }}
+
+
+
{{ _('Possible Lock Actions') }}:
+

+ 1: {{ _('unlock') }}  -   + 2: {{ _('lock') }}  -   + 3: {{ _('unlatch') }}  -   + 4: {{ _('lockAndGo') }}  -   + 5: {{ _('lockAndGoWithUnlatch') }} +

+
+

{{ _('Nuki Battery Items') }} ({{ p.get_battery_items()|length }})
From 49b6e4ee5c99494cd08e0b3c590e03008834ce27 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 1 Nov 2018 13:53:39 +0100 Subject: [PATCH 366/705] Nuki: changes to logger, added get methods --- nuki/__init__.py | 79 +++++++++++++++++++-------------- nuki/locale.yaml | 6 ++- nuki/webif/templates/index.html | 25 ++++++++--- 3 files changed, 71 insertions(+), 39 deletions(-) diff --git a/nuki/__init__.py b/nuki/__init__.py index d31554640..ec03c1fc5 100644 --- a/nuki/__init__.py +++ b/nuki/__init__.py @@ -26,6 +26,7 @@ import lib.connection import re from lib.model.smartplugin import * +from bin.smarthome import VERSION nuki_action_items = {} nuki_event_items = {} @@ -34,11 +35,11 @@ class NukiTCPDispatcher(lib.connection.Server): - def __init__(self, ip, port): - self._logger = logging.getLogger(__name__) - lib.connection.Server.__init__(self, ip, port, proto='TCP') - self.dest = 'tcp:' + ip + ':{port}'.format(port=port) - self._logger.debug('Nuki: starting tcp listener with {url}'.format(url=self.dest)) + def __init__(self, plugin): + self.plugin = plugin + lib.connection.Server.__init__(self, self.plugin.get_callback_ip(), self.plugin.get_callback_port(), proto='TCP') + self.dest = 'tcp:' + self.plugin.get_callback_ip() + ':{port}'.format(port=self.plugin.get_callback_port()) + self.plugin.logger.debug("Plugin '{pluginname}' - NukiTCPDispatcher: starting tcp listener with {url}".format(pluginname=self.plugin.get_shortname(), url=self.dest)) self.connect() def handle_connection(self): @@ -46,24 +47,24 @@ def handle_connection(self): conn, address = self.socket.accept() data = conn.recv(1024) address = "{}:{}".format(address[0], address[1]) - self._logger.info("Nuki: {}: incoming connection from {}".format('test', address)) + self.plugin.logger.info("Plugin '{}' - NukiTCPDispatcher: {}: incoming connection from {}".format(self.plugin.get_shortname(), 'test', address)) except Exception as err: - self._logger.error("Nuki:: {}: {}".format(self._name, err)) + self.logger.error("Plugin '{pluginname}':: {}: {}".format(self.plugin.get_shortname(), self._name, err)) return try: result = re.search('\{.*\}', data.decode('utf-8')) - self._logger.debug('Nuki: Getting JSON String') + self.plugin.logger.debug("Plugin '{}' - NukiTCPDispatcher: Getting JSON String".format(self.plugin.get_shortname())) nuki_bridge_response = json.loads(result.group(0)) nuki_id = nuki_bridge_response['nukiId'] state_name = nuki_bridge_response['stateName'] - self._logger.debug("Nuki: Status Smartlock: ID: {nuki_id} Status: {state_name}". - format(nuki_id=nuki_id, state_name=state_name)) + self.plugin.logger.debug("Plugin '{pluginname}' - NukiTCPDispatcher: Status Smartlock: ID: {nuki_id} Status: {state_name}". + format(pluginname=self.plugin.get_shortname(), nuki_id=nuki_id, state_name=state_name)) conn.send(b"HTTP/1.1 200 OK\nContent-Type: text/html\n\n") Nuki.update_lock_state(nuki_id, nuki_bridge_response) except Exception as err: - self._logger.error("Nuki: Error parsing nuki response!\nError: {}".format(err)) + self.plugin.logger.error("Plugin '{}' - NukiTCPDispatcher: Error parsing nuki response!\nError: {}".format(self.plugin.get_shortname(), err)) class Nuki(SmartPlugin): @@ -76,7 +77,10 @@ def __init__(self, sh, *args, **kwargs): global nuki_event_items global nuki_action_items global nuki_battery_items - self._logger = logging.getLogger(__name__) + + if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': + self.logger = logging.getLogger(__name__) + self._base_url = self.get_parameter_value('protocol') + '://' + self.get_parameter_value( 'bridge_ip') + ":" + str(self.get_parameter_value('bridge_port')) + '/' self._token = self.get_parameter_value('bridge_api_token') @@ -89,16 +93,16 @@ def __init__(self, sh, *args, **kwargs): self._callback_ip = self.get_local_ipv4_address() if not self._callback_ip: - self._logger.critical("Plugin '{}': Could not fetch internal ip address. Set it manually!".format(self.get_shortname())) + self.logger.critical("Plugin '{}': Could not fetch internal ip address. Set it manually!".format(self.get_shortname())) self.alive = False return - self._logger.info("Plugin '{pluginname}': using local ip address {ip}".format(pluginname=self.get_shortname(), ip=self._callback_ip)) + self.logger.info("Plugin '{pluginname}': using local ip address {ip}".format(pluginname=self.get_shortname(), ip=self._callback_ip)) else: - self._logger.info("Plugin '{pluginname}': using given ip address {ip}".format(pluginname=self.get_shortname(), ip=self._callback_ip)) + self.logger.info("Plugin '{pluginname}': using given ip address {ip}".format(pluginname=self.get_shortname(), ip=self._callback_ip)) self._callback_url = "http://{ip}:{port}/".format(ip=self._callback_ip, port=self._callback_port) - NukiTCPDispatcher(self._callback_ip, self._callback_port) + NukiTCPDispatcher(self) self._lockActions = [1, # unlock 2, # lock @@ -127,13 +131,13 @@ def stop(self): def parse_item(self, item): if self.has_iattr(item.conf, 'nuki_id'): - self._logger.debug("Plugin '{0}': parse item: {1}".format(self.get_shortname(), item)) + self.logger.debug("Plugin '{0}': parse item: {1}".format(self.get_shortname(), item)) nuki_id = self.get_iattr_value(item.conf, 'nuki_id') if self.has_iattr(item.conf, 'nuki_trigger'): nuki_trigger = self.get_iattr_value(item.conf, "nuki_trigger") if nuki_trigger.lower() not in ['state', 'action', 'battery']: - self._logger.warning("Plugin '{pluginname}': Item {item} defines an invalid Nuki trigger {trigger}! " + self.logger.warning("Plugin '{pluginname}': Item {item} defines an invalid Nuki trigger {trigger}! " "It has to be 'state' or 'action'.".format(pluginname=self.get_shortname(), item=item, trigger=nuki_trigger)) return if nuki_trigger.lower() == 'state': @@ -143,7 +147,7 @@ def parse_item(self, item): else: nuki_battery_items[item] = int(nuki_id) else: - self._logger.warning("Plugin '{pluginname}': Item {item} defines a Nuki ID but no nuki trigger! " + self.logger.warning("Plugin '{pluginname}': Item {item} defines a Nuki ID but no nuki trigger! " "This item has no effect.".format(pluginname=self.get_shortname(), item=item)) return return self.update_item @@ -156,7 +160,7 @@ def update_item(self, item, caller=None, source=None, dest=None): if item in nuki_action_items: action = item() if action not in self._lockActions: - self._logger.warning("Plugin '{pluginname}': action {action} not in list of possible actions.".format(pluginname=self.get_shortname(), action=action)) + self.logger.warning("Plugin '{pluginname}': action {action} not in list of possible actions.".format(pluginname=self.get_shortname(), action=action)) return response = self._api_call(self._base_url, nuki_id=nuki_action_items[item], endpoint='lockAction', @@ -164,9 +168,9 @@ def update_item(self, item, caller=None, source=None, dest=None): if response is not None: if response['success']: # self._get_nuki_status() - self._logger.info("Plugin '{0}': update item: {1}".format(self.get_shortname(), item.id())) + self.logger.info("Plugin '{0}': update item: {1}".format(self.get_shortname(), item.id())) else: - self._logger.error("Plugin '{}': no response.".format(self.get_shortname())) + self.logger.error("Plugin '{}': no response.".format(self.get_shortname())) @staticmethod def update_lock_state(nuki_id, lock_state): @@ -194,9 +198,9 @@ def _get_paired_nukis(self): return for nuki in response: paired_nukis.append(nuki['nukiId']) - self._logger.info( + self.logger.info( "Plugin '{pluginname}': Paired Nuki Lock found: {name} - {id}".format(pluginname=self.get_shortname(), name=nuki['name'], id=nuki['nukiId'])) - self._logger.debug(paired_nukis) + self.logger.debug(paired_nukis) def _clear_callbacks(self): callbacks = self._api_call(self._base_url, endpoint='callback/list', token=self._token) @@ -204,9 +208,9 @@ def _clear_callbacks(self): for c in callbacks['callbacks']: response = self._api_call(self._base_url, endpoint='callback/remove', token=self._token, id=c['id']) if response['success']: - self._logger.debug("Plugin '{pluginname}': Callback with id {id} removed.".format(pluginname=self.get_shortname(), id=c['id'])) + self.logger.debug("Plugin '{pluginname}': Callback with id {id} removed.".format(pluginname=self.get_shortname(), id=c['id'])) return - self._logger.debug("Plugin '{pluginname}': Could not remove callback with id {id}: {message}". + self.logger.debug("Plugin '{pluginname}': Could not remove callback with id {id}: {message}". format(pluginname=self.get_shortname(), id=c['id'], message=c['message'])) def _register_callback(self): @@ -221,20 +225,20 @@ def _register_callback(self): response = self._api_call(self._base_url, endpoint='callback/add', token=self._token, callback_url=self._callback_url) if not response['success']: - self._logger.warning("Plugin '{pluginname}': Error establishing the callback url: {message}".format + self.logger.warning("Plugin '{pluginname}': Error establishing the callback url: {message}".format (pluginname=self.get_shortname(), message=response['message'])) else: - self._logger.info("Plugin '{}': Callback URL registered.".format + self.logger.info("Plugin '{}': Callback URL registered.".format (self.get_shortname())) else: - self._logger.info("Plugin '{}': Callback URL already registered".format + self.logger.info("Plugin '{}': Callback URL already registered".format (self.get_shortname())) else: - self._logger.warning("Plugin '{}': No callback ip set. Automatic Nuki lock status updates not available.".format + self.logger.warning("Plugin '{}': No callback ip set. Automatic Nuki lock status updates not available.".format (self.get_shortname())) def _get_nuki_status(self): - self._logger.info("Plugin '{}': Getting Nuki status ...".format + self.logger.info("Plugin '{}': Getting Nuki status ...".format (self.get_shortname())) for nuki_id in paired_nukis: response = self._api_call(self._base_url, endpoint='lockState', nuki_id=nuki_id, token=self._token, @@ -253,7 +257,7 @@ def _api_call(self, base_url, endpoint=None, nuki_id=None, token=None, action=No payload['action'] = action if no_wait is not None: payload['noWait'] = int(no_wait) - self._logger.debug("Plugin '{}': noWait is {}".format(self.get_shortname(), int(no_wait))) + self.logger.debug("Plugin '{}': noWait is {}".format(self.get_shortname(), int(no_wait))) if callback_url is not None: payload['url'] = callback_url if id is not None: @@ -263,7 +267,7 @@ def _api_call(self, base_url, endpoint=None, nuki_id=None, token=None, action=No response.raise_for_status() return json.loads(response.text) except Exception as ex: - self._logger.error(ex) + self.logger.error(ex) def get_event_items(self): return nuki_event_items @@ -274,6 +278,15 @@ def get_battery_items(self): def get_action_items(self): return nuki_action_items + def get_callback_ip(self): + return self._callback_ip + + def get_callback_port(self): + return self._callback_port + + def get_callback_url(self): + return self._callback_url + def init_webinterface(self): """" Initialize the web interface for this plugin diff --git a/nuki/locale.yaml b/nuki/locale.yaml index e8aef785b..9301370cc 100644 --- a/nuki/locale.yaml +++ b/nuki/locale.yaml @@ -28,4 +28,8 @@ plugin_translations: 'unlatched (lock and go)': {'de': 'aufgeklinkt (Lock And Go)', 'en': 'unlatched (Lock And Go)'} 'unlatching': {'de': 'aufklinkend', 'en': '='} 'motor blocked': {'de': 'Motor blockiert', 'en': '='} - 'undefined': {'de': 'undefiniert', 'en': '='} \ No newline at end of file + 'undefined': {'de': 'undefiniert', 'en': '='} + 'Enforce Updates': {'de': '=', 'en': '='} + 'Possible Battery Values': {'de': 'Mögliche Werte für die Batterie', 'en': '='} + 'Batteries are good. No need to replace it.': {'de': 'Die Batterien sind gut, sie müssen nicht getauscht werden.', 'en': '='} + 'Batteries are low. Please replace as soon as possible!': {'de': 'Die Batterieladung ist niedrig. Bitte so bald als möglich austauschen!', 'en': '='} diff --git a/nuki/webif/templates/index.html b/nuki/webif/templates/index.html index ff4a0cf69..a5b7409f7 100644 --- a/nuki/webif/templates/index.html +++ b/nuki/webif/templates/index.html @@ -13,7 +13,7 @@ - + @@ -34,7 +34,7 @@
{{ _('Nuki Event Items') }} ({{ p.get_event_items()|length }})
{{ _('Token') }} {{ p._token }} {{ _('Callback URL (SHNG)') }}{{ p._callback_ip }}:{{ p._callback_port }}{{ p.get_callback_url() }}
{{ _('NoWait') }}
- + @@ -89,8 +89,9 @@
{{ _('Nuki Action Items') }} ({{ p.get_action_items()|length }})
{{ _('Pfad') }}{{ _('Pfad') }} {{ _('Typ') }} {{ _('Nuki ID') }} {{ _('Wert') }}
- + + @@ -102,6 +103,7 @@
{{ _('Nuki Action Items') }} ({{ p.get_action_items()|length }})
+ - From 5d4182da25926ea187f76093ded0cf61b57858c4 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 1 Nov 2018 17:44:11 +0100 Subject: [PATCH 369/705] Nuki: button for sending action value --- nuki/locale.yaml | 2 ++ nuki/webif/templates/index.html | 34 +++++++++++++++++---------------- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/nuki/locale.yaml b/nuki/locale.yaml index 9301370cc..44185ea0b 100644 --- a/nuki/locale.yaml +++ b/nuki/locale.yaml @@ -33,3 +33,5 @@ plugin_translations: 'Possible Battery Values': {'de': 'Mögliche Werte für die Batterie', 'en': '='} 'Batteries are good. No need to replace it.': {'de': 'Die Batterien sind gut, sie müssen nicht getauscht werden.', 'en': '='} 'Batteries are low. Please replace as soon as possible!': {'de': 'Die Batterieladung ist niedrig. Bitte so bald als möglich austauschen!', 'en': '='} + 'Send': {'de': 'Abschicken', 'en': '='} + 'none': {'de': 'keine Aktion', 'en': 'no action'} \ No newline at end of file diff --git a/nuki/webif/templates/index.html b/nuki/webif/templates/index.html index 13c8deac8..13d148abb 100644 --- a/nuki/webif/templates/index.html +++ b/nuki/webif/templates/index.html @@ -26,7 +26,6 @@ {% endblock %} {% block bodytab1 %} -
{{ _('Nuki Event Items') }} ({{ p.get_event_items()|length }})
@@ -96,6 +95,7 @@
{{ _('Nuki Action Items') }} ({{ p.get_action_items()|length }})
+ @@ -105,23 +105,25 @@
{{ _('Nuki Action Items') }} ({{ p.get_action_items()|length }})
- + + {% endfor %} From 29e9178dd0a44411d66b94834fb690a7e387a2bc Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 1 Nov 2018 17:46:51 +0100 Subject: [PATCH 370/705] Nuki: more info in webif --- nuki/webif/templates/index.html | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/nuki/webif/templates/index.html b/nuki/webif/templates/index.html index 13d148abb..158b654b5 100644 --- a/nuki/webif/templates/index.html +++ b/nuki/webif/templates/index.html @@ -105,7 +105,15 @@
{{ _('Nuki Action Items') }} ({{ p.get_action_items()|length }})
- + - + From ad658188482b7e398cb38f3501a88b8ced6438ac Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sat, 3 Nov 2018 13:33:25 +0100 Subject: [PATCH 402/705] Withing Health: change to imports and code formatting --- withings_health/__init__.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/withings_health/__init__.py b/withings_health/__init__.py index 8e8bc75f2..a8705d0a0 100644 --- a/withings_health/__init__.py +++ b/withings_health/__init__.py @@ -21,8 +21,7 @@ # ######################################################################### -import requests -import ruamel.yaml +import cherrypy import datetime from lib.model.smartplugin import * from lib.shtime import Shtime @@ -62,7 +61,8 @@ def _store_tokens(self, token): token['refresh_token'])) self.get_item('access_token')(token['access_token']) self.get_item('token_expiry')( - int((datetime.datetime.utcnow() - datetime.datetime(1970, 1, 1)).total_seconds()) + int(token['expires_in'])) + int((datetime.datetime.utcnow() - datetime.datetime(1970, 1, 1)).total_seconds()) + int( + token['expires_in'])) self.get_item('token_type')(token['token_type']) self.get_item('refresh_token')(token['refresh_token']) @@ -266,12 +266,15 @@ def parse_item(self, item): """ # items specific to call monitor if self.get_iattr_value(item.conf, 'withings_type') in ['weight', 'height', 'fat_free_mass', 'fat_mass_weight', - 'fat_ratio', 'fat_mass_weight', 'diastolic_blood_pressure', - 'systolic_blood_pressure', 'heart_pulse', 'temperature', - 'spo2', 'body_temperature', 'skin_temperature', 'muscle_mass', - 'hydration', 'bone_mass', 'pulse_wave_velocity', 'bmi', - 'bmi_text', 'access_token', 'token_expiry', 'token_type', - 'refresh_token']: + 'fat_ratio', 'fat_mass_weight', + 'diastolic_blood_pressure', + 'systolic_blood_pressure', 'heart_pulse', 'temperature', + 'spo2', 'body_temperature', 'skin_temperature', + 'muscle_mass', + 'hydration', 'bone_mass', 'pulse_wave_velocity', 'bmi', + 'bmi_text', 'access_token', 'token_expiry', + 'token_type', + 'refresh_token']: self._items[self.get_iattr_value(item.conf, 'withings_type')] = item def get_items(self): @@ -321,10 +324,6 @@ def init_webinterface(self): # Webinterface of the plugin # ------------------------------------------ -import cherrypy -from jinja2 import Environment, FileSystemLoader - - class WebInterface(SmartPluginWebIf): def __init__(self, webif_dir, plugin): From 053e523fcbc72cb7c30d3d6f4cac8cbc1a3b94e1 Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Sun, 4 Nov 2018 00:16:57 +0100 Subject: [PATCH 403/705] allow to use boost(), drop() and default() with the controller number only --- rtr/__init__.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/rtr/__init__.py b/rtr/__init__.py index 6e3c00219..c4bf90513 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab ######################################################################### -# Copyright 2017 Thomas Creutz thomas.creutz@gmx.de +# Copyright 2018 Thomas Creutz thomas.creutz@gmx.de # Copyright 2016 Bernd Meiners Bernd.Meiners@mail.de ######################################################################### # This file is part of SmartHomeNG @@ -465,6 +465,9 @@ def default(self, c, caller=None, source=None, dest=None): this function changes setpoint of the given controller to defined default temperature :param c: controller to be used """ + if re.match(r"[0-9]+$", str(c)): + c = 'c' + c + self.logger.debug("default(): called for controller: '{}'".format(c)) if c in self._controller: @@ -484,6 +487,9 @@ def boost(self, c, timer=True, edt=None): :param timer: if not True, no timer will be created :param edt: end datetime to override the default """ + if re.match(r"[0-9]+$", str(c)): + c = 'c' + c + self.logger.debug("boost(): called for controller: '{}'".format(c)) if c in self._controller: @@ -509,6 +515,9 @@ def drop(self, c, edt=None): :param c: controller to be used :param edt: end date time, if given a timer with the end date time get created """ + if re.match(r"[0-9]+$", str(c)): + c = 'c' + c + self.logger.debug("drop(): called for controller: '{}'".format(c)) if c in self._controller: From 4ea94429be350ce9cb29e580fdf5e166b257c634 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sun, 4 Nov 2018 17:36:04 +0100 Subject: [PATCH 404/705] Update uzsu/__init__.py added caller for update_sun --- uzsu/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 81150e07f..41c771776 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -169,7 +169,7 @@ def _update_all_suns(self, caller=None): success = self._update_sun(item) if success: self.logger.debug('Updating sun info for item {}'.format(item)) - item(self._items[item]) + item(self._items[item], 'UZSU Plugin', 'update_all_suns')) def _update_sun(self, item, caller=None): """ @@ -567,7 +567,7 @@ def _set(self, item=None, value=None, caller=None): :param caller: if given it represents the callers name """ _uzsuitem = self.itemsApi.return_item(self.get_iattr_value(item.conf, ITEM_TAG[0])) - _uzsuitem(value, caller='UZSU Plugin') + _uzsuitem(value, 'UZSU Plugin', 'set') if not caller: self._schedule(item, caller='set') From 257c813cb8deb26ec05e2624a4e1c433b20fe2eb Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Mon, 5 Nov 2018 01:00:57 +0100 Subject: [PATCH 405/705] HVACMode, Widget and small changes --- rtr/__init__.py | 104 +++++++++++++++++++++++++++++++-- rtr/plugin.yaml | 4 ++ rtr/sv_widgets/widget_rtr.html | 26 +++++++++ rtr/sv_widgets/widget_rtr.js | 9 +++ 4 files changed, 137 insertions(+), 6 deletions(-) create mode 100644 rtr/sv_widgets/widget_rtr.html create mode 100644 rtr/sv_widgets/widget_rtr.js diff --git a/rtr/__init__.py b/rtr/__init__.py index c4bf90513..f3d1ee2d5 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab ######################################################################### -# Copyright 2018 Thomas Creutz thomas.creutz@gmx.de +# Copyright 2013 Thomas Creutz thomas.creutz@gmx.de # Copyright 2016 Bernd Meiners Bernd.Meiners@mail.de ######################################################################### # This file is part of SmartHomeNG @@ -45,11 +45,20 @@ class RTR(SmartPlugin): ALLOW_MULTIINSTANCE = False PLUGIN_VERSION = "1.2.3" + HVACMode_Auto = 0 + HVACMode_Comfort = 1 + HVACMode_Standby = 2 + HVACMode_Economy = 3 + HVACMode_Bldg_Prot = 4 + _controller = {} _defaults = {'currentItem' : None, 'setpointItem' : None, 'actuatorItem' : None, 'stopItems' : None, + 'timerendItem' : None, + 'HVACModeItem' : None, + 'HVACMode': 0, 'eSum' : 0, 'Kp' : 0, 'Ki' : 0, @@ -140,7 +149,6 @@ def parse_item(self, item): else: self._controller[c]['Ki'] = float(item.conf['rtr_Ki']) - if not self._controller[c]['validated']: self.validate_controller(c) @@ -177,7 +185,7 @@ def parse_item(self, item): if not self._controller[c]['validated']: self.validate_controller(c) - return self.update_item + return self.update_setpoint if self.has_iattr(item.conf, 'rtr_actuator'): if not item.conf['rtr_actuator'].isdigit(): @@ -200,6 +208,28 @@ def parse_item(self, item): return + if self.has_iattr(item.conf, 'rtr_timer_end_text'): + if not item.conf['rtr_timer_end_text'].isdigit(): + self.logger.error("rtr: error in item {0}, rtr_timer_end_text need to be the controller number".format(item.id())) + return + + c = 'c' + item.conf['rtr_timer_end_text'] + + self._controller[c]['timerendItem'] = item.id() + + return + + if self.has_iattr(item.conf, 'rtr_hvac_mode'): + if not item.conf['rtr_hvac_mode'].isdigit(): + self.logger.error("rtr: error in item {0}, rtr_hvac_mode need to be the controller number".format(item.id())) + return + + c = 'c' + item.conf['rtr_hvac_mode'] + + self._controller[c]['HVACModeItem'] = item.id() + + return self.update_HVACMode + if self.has_iattr(item.conf, 'rtr_stop'): self.logger.error("rtr: parse item {0}, found rtr_stop which is not supported anymore - use rtr_stops instead") return @@ -243,6 +273,14 @@ def parse_item(self, item): return def stop_Controller(self, item, caller=None, source=None, dest=None): + """ + this is the callback function for the stopItems + + :param item: item to be updated towards the plugin + :param caller: if given it represents the callers name + :param source: if given it represents the source + :param dest: if given it represents the dest + """ for c in self._controller.keys(): if self._controller[c]['stopItems'] is not None and len(self._controller[c]['stopItems']) > 0: for item in self._controller[c]['stopItems']: @@ -251,19 +289,48 @@ def stop_Controller(self, item, caller=None, source=None, dest=None): logger.info("rtr: controller {0} stopped, because of item {1}".format(c, item.id())) self._controller[c]['actuatorItem'](0) - def update_item(self, item, caller=None, source=None, dest=None): + + def update_HVACMode(self, item, caller=None, source=None, dest=None): """ - write item's values + this is the callback function for the HVACModeItem :param item: item to be updated towards the plugin :param caller: if given it represents the callers name :param source: if given it represents the source :param dest: if given it represents the dest """ + if item() and caller != 'plugin': + if 'rtr_hvac_mode' in item.conf: + c = 'c' + item.conf['rtr_hvac_mode'] + if self._controller[c]['validated']: + if item() == self.HVACMode_Auto: + self.default(c) + elif item() == self.HVACMode_Comfort: + self.boost(c) + elif item() == self.HVACMode_Standby: + self.default(c) + elif item() == self.HVACMode_Economy: + self.drop(c) + elif item() == self.HVACMode_Bldg_Prot: + self.logger.warning("rtr: HVAC Mode '{}' from Item {} currently not implemented".format(c, item.id())) + self.default(c) + else: + self.logger.error("rtr: HVAC Mode '{}' from Item {} unknown".format(c, item.id())) + self.default(c) + + + def update_setpoint(self, item, caller=None, source=None, dest=None): + """ + this is the callback function for the setpointItems + :param item: item to be updated towards the plugin + :param caller: if given it represents the callers name + :param source: if given it represents the source + :param dest: if given it represents the dest + """ self.logger.debug("rtr: update item {}, from caller = {}, with source={} and dest={}".format(item.id(), caller, source, dest)) if item() and caller != 'plugin': - if 'rtr_setpoint' in item.conf or 'rtr_current' in item.conf: + if 'rtr_setpoint' in item.conf: c = 'c' + item.conf['rtr_setpoint'] if self._controller[c]['validated']: self.pi_controller(c) @@ -272,6 +339,7 @@ def update_items(self): """ this is the callback function for the scheduler """ for c in self._controller.keys(): if self._controller[c]['validated']: + self.pi_controller(c) def validate_controller(self, c): @@ -288,6 +356,10 @@ def validate_controller(self, c): if self._controller[c]['actuatorItem'] is None: return + self._controller[c]['HVACMode'] = self.HVACMode_Standby + if self._controller[c]['HVACModeItem'] is not None: + self._items.return_item(self._controller[c]['HVACModeItem'])(self._controller[c]['HVACMode']) + self.logger.info("rtr: all needed params are set, controller {0} validated".format(c)) self._controller[c]['validated'] = True @@ -423,6 +495,10 @@ def _createTimer(self, name, c, edt): self.scheduler_remove(name) # create scheduler self.scheduler_add(name, self.default, value={'c': c}, next=edt) + + if self._controller[c]['timerendItem'] is not None: + self._items.return_item(self._controller[c]['timerendItem'])(edt.strftime("%s")) + except Exception as e: self.logger.error("_createTimer(): ': {}".format(e)) @@ -474,9 +550,16 @@ def default(self, c, caller=None, source=None, dest=None): if self._controller[c]['tempDefault'] > 0: self._items.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempDefault']) + self._controller[c]['HVACMode'] = self.HVACMode_Standby + if self._controller[c]['HVACModeItem'] is not None: + self._items.return_item(self._controller[c]['HVACModeItem'])(self._controller[c]['HVACMode']) + self._deleteTimer('boost_' + c) self._deleteTimer('drop_' + c) + if self._controller[c]['timerendItem'] is not None: + self._items.return_item(self._controller[c]['timerendItem'])("") + else: self.logger.error("default(): unknown controller '{}' - we only have '{}'".format(c, self._controller.keys())) @@ -496,6 +579,10 @@ def boost(self, c, timer=True, edt=None): if self._controller[c]['tempBoost'] > 0: self._items.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempBoost']) + self._controller[c]['HVACMode'] = self.HVACMode_Comfort + if self._controller[c]['HVACModeItem'] is not None: + self._items.return_item(self._controller[c]['HVACModeItem'])(self._controller[c]['HVACMode']) + if self._controller[c]['tempBoostTime'] == 0 and edt is None: timer = False @@ -523,6 +610,11 @@ def drop(self, c, edt=None): if c in self._controller: if self._controller[c]['tempDrop'] > 0: self._items.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempDrop']) + + self._controller[c]['HVACMode'] = self.HVACMode_Economy + if self._controller[c]['HVACModeItem'] is not None: + self._items.return_item(self._controller[c]['HVACModeItem'])(self._controller[c]['HVACMode']) + if isinstance(edt, datetime.datetime): self._deleteTimer('boost_' + c) self._createTimer('drop_' + c, c, edt) diff --git a/rtr/plugin.yaml b/rtr/plugin.yaml index bda488198..52516c16a 100755 --- a/rtr/plugin.yaml +++ b/rtr/plugin.yaml @@ -5,6 +5,7 @@ plugin: de: 'Raum Temperatur Regler' en: 'Room Temperatur controller' maintainer: Thomas Creutz / bmxp + support: https://knx-user-forum.de/forum/supportforen/smarthome-py/31450-rtr-heizungs-plugin version: 1.2.3 # Plugin version sh_minversion: 1.2 # minimum shNG version to use this plugin @@ -105,6 +106,9 @@ item_attributes: de: 'Ordnet das Item dem Controller mit gegebener ID als Stellgröße zu' en: 'Defines the Item as actuator value for the given controller ID' + rtr_hvac_mode: + type: int + rtr_stops: type: list(int) description: diff --git a/rtr/sv_widgets/widget_rtr.html b/rtr/sv_widgets/widget_rtr.html new file mode 100644 index 000000000..6d9592ff4 --- /dev/null +++ b/rtr/sv_widgets/widget_rtr.html @@ -0,0 +1,26 @@ +/** +* Extended RTR (Room Temperatur Regulator) +* +* @param {id=} unique id for this widget (optional) +* @param {text=} name of the rtr +* @param {item} an item for the actual temperature +* @param {item} an item for the set temperature +* @param {item=} an item for comfort / standby (3x bit or 1x byte, optional) +* @param {item=} an item for night (3x bit or 1x byte, optional) +* @param {item=} an item for frost (3x bit or 1x byte, optional) +* @param {item=} an item for the current state of the actor (optional) +* @param {item=} an item for a text (some rtr have a text-display), (optional) +* @param {value=0.5} step for plus/minus buttons (optional, default: 0.5) +* @param {item=} an item for the offset temperature (optional, if provided set temperature changes will be written to this item instead of 'item_set') +* @param {text[]=} list of additional widgets / content to display +*/ +{% macro rtr(id, txt, item_actual, item_set, item_comfort, item_night, item_frost, item_state, item_txt, step, item_offset, supplements, item_actuator, item_endtime) %} + + {% import "device.html" as device %} + {% import "basic.html" as basic %} + + {{ device.rtr(id, txt, item_actual, item_set, item_comfort, item_night, item_frost, item_state, item_txt, step, item_offset, supplements) }} + {% if item_actuator %}{{ basic.print(id~"print_actuator", item_actuator, 'Heizt mit %d %')}}{% endif %} + {% if item_endtime %}
{{ basic.print(id~"print_endtime", item_endtime, 'text', 'VAR1=rtr_timer(VAR1 )')}}{% endif %} + +{% endmacro %} diff --git a/rtr/sv_widgets/widget_rtr.js b/rtr/sv_widgets/widget_rtr.js new file mode 100644 index 000000000..d980d8ce2 --- /dev/null +++ b/rtr/sv_widgets/widget_rtr.js @@ -0,0 +1,9 @@ +function rtr_timer(ts) { + + if (ts === "") { + return ""; + } else { + d = new Date(ts*1000);; + return "Timer endet " + d.transUnit("H:i, d.m."); + } +} From 264b12c8e549bad617dbb8001e547f2e3021e4dd Mon Sep 17 00:00:00 2001 From: msinn Date: Mon, 5 Nov 2018 01:51:14 +0100 Subject: [PATCH 406/705] knx: Expanded source information (for backend and logics) and adopted logging extenstion of new SmartPlugin --- knx/__init__.py | 116 ++++++++++++++++++++++++++---------------------- knx/plugin.yaml | 2 +- 2 files changed, 64 insertions(+), 54 deletions(-) diff --git a/knx/__init__.py b/knx/__init__.py index d01e7cd64..451afaeb8 100755 --- a/knx/__init__.py +++ b/knx/__init__.py @@ -73,7 +73,7 @@ class KNX(lib.connection.Client,SmartPlugin): ALLOW_MULTIINSTANCE = True - PLUGIN_VERSION = "1.4.5" + PLUGIN_VERSION = "1.4.6" # tags actually used by the plugin are shown here @@ -84,9 +84,13 @@ class KNX(lib.connection.Client,SmartPlugin): def __init__(self, smarthome): self.host = self.get_parameter_value('host') self.port = self.get_parameter_value('port') + + from bin.smarthome import VERSION + if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': + self.logger = logging.getLogger(__name__) + lib.connection.Client.__init__(self, self.host, self.port, monitor=True) - self.logger = logging.getLogger(__name__) - self.logger.debug("init knx") + self.logger.debug("init knx") self.shtime = Shtime.get_instance() busmonitor = self.get_parameter_value('busmonitor') @@ -100,7 +104,7 @@ def __init__(self, smarthome): self.date_ga = self.get_parameter_value('date_ga') send_time = self.get_parameter_value('send_time') self._bm_separatefile = False - self._bm_format= "KNX[{0}]:'BM': {1} set {2} to {3}" + self._bm_format= "BM': {1} set {2} to {3}" # following needed for statistics self.enable_stats = self.get_parameter_value('enable_stats') @@ -136,7 +140,7 @@ def __init__(self, smarthome): def _send(self, data): if len(data) < 2 or len(data) > 0xffff: - self.logger.debug('KNX[{0}]: Illegal data size: {1}'.format(self.get_instance_name(), repr(data))) + self.logger.debug('Illegal data size: {}'.format(repr(data))) return False # prepend data length send = bytearray(len(data).to_bytes(2, byteorder='big')) @@ -148,7 +152,7 @@ def groupwrite(self, ga, payload, dpt, flag='write'): try: pkt.extend(self.encode(ga, 'ga')) except: - self.logger.warning('KNX[{0}]: problem encoding ga: {1}'.format(self.get_instance_name(), ga)) + self.logger.warning('problem encoding ga: {}'.format(ga)) return pkt.extend([0]) pkt.extend(self.encode(payload, dpt)) @@ -158,12 +162,12 @@ def groupwrite(self, ga, payload, dpt, flag='write'): flag = KNXRESP else: self.logger.warning( - "KNX[{0}]: groupwrite telegram for {1} with unknown flag: {2}. Please choose beetween write and response.".format( - self.get_instance_name(), ga, flag)) + "groupwrite telegram for {} with unknown flag: {}. Please choose beetween write and response.".format( + ga, flag)) return pkt[5] = flag | pkt[5] if self.readonly: - self.logger.info("KNX[{2}]: groupwrite telegram for: {0} - Value: {1} not send. Plugin in READONLY mode. ".format(ga,payload,self.get_instance_name())) + self.logger.info("groupwrite telegram for: {} - Value: {} not send. Plugin in READONLY mode. ".format(ga,payload)) else: self._send(pkt) @@ -172,10 +176,10 @@ def _cacheread(self, ga): try: pkt.extend(self.encode(ga, 'ga')) except: - self.logger.warning('KNX[{0}]: problem encoding ga: {1}'.format(self.get_instance_name(), ga)) + self.logger.warning('problem encoding ga: {}'.format(ga)) return pkt.extend([0, 0]) - self.logger.debug('KNX[{0}]: reading knxd cache for ga: {1}'.format(self.get_instance_name(), ga)) + self.logger.debug('reading knxd cache for ga: {}'.format(ga)) self._send(pkt) def groupread(self, ga): @@ -183,7 +187,7 @@ def groupread(self, ga): try: pkt.extend(self.encode(ga, 'ga')) except: - self.logger.warning('KNX[{0}]: problem encoding ga: {1}'.format(self.get_instance_name(), ga)) + self.logger.warning('problem encoding ga: {}'.format(ga)) return pkt.extend([0, KNXREAD]) self._send(pkt) @@ -197,7 +201,7 @@ def _poll(self, **kwargs): if 'ga' in kwargs: self.groupread(kwargs['ga']) else: - self.logger.warning('KNX[{0}]: problem polling {1}, no known ga'.format(self.get_instance_name(), item)) + self.logger.warning('problem polling {}, no known ga'.format(item)) if 'interval' in kwargs and 'ga' in kwargs: ga = kwargs['ga'] @@ -219,14 +223,14 @@ def send_time(self, time_ga=None, date_ga=None): def handle_connect(self): if not self.connected: - self.logger.error('KNX[{0}]: connection was unexpectedly lost'.format(self.get_instance_name())) + self.logger.error('connection was unexpectedly lost') return self.discard_buffers() enable_cache = bytearray([0, KNXD_CACHE_ENABLE]) self._send(enable_cache) self.found_terminator = self.parse_length if self._cache_ga != []: - self.logger.debug('KNX[{0}]: reading knxd cache'.format(self.get_instance_name())) + self.logger.debug('reading knxd cache') for ga in self._cache_ga: self._cache_ga_response_pending.append(ga) for ga in self._cache_ga: @@ -234,18 +238,18 @@ def handle_connect(self): # wait a little to not overdrive the knxd unless there is a fix time.sleep(KNXD_CACHEREAD_DELAY) self._cache_ga = [] - self.logger.debug('KNX[{0}]: finished reading knxd cache'.format(self.get_instance_name())) + self.logger.debug('finished reading knxd cache') - self.logger.debug('KNX[{0}]: enable group monitor'.format(self.get_instance_name())) + self.logger.debug('enable group monitor') init = bytearray([0, KNXD_OPEN_GROUPCON, 0, 0, 0]) self._send(init) self.terminator = 2 if self._init_ga != []: - self.logger.debug('KNX[{0}]: knxd init read for {1} ga'.format(self.get_instance_name(),len(self._init_ga))) + self.logger.debug('knxd init read for {} ga'.format(len(self._init_ga))) for ga in self._init_ga: self.groupread(ga) self._init_ga = [] - self.logger.debug('KNX[{0}]: finished knxd init read'.format(self.get_instance_name())) + self.logger.debug('finished knxd init read') # def collect_incoming_data(self, data): # print('# bin h d') @@ -259,7 +263,7 @@ def parse_length(self, length): try: self.terminator = struct.unpack(">H", length)[0] except: - self.logger.error("KNX[{0}]: problem unpacking length: {1}".format(self.get_instance_name(), length)) + self.logger.error("problem unpacking length: {}".format(length)) self.close() def encode(self, data, dpt): @@ -288,7 +292,7 @@ def parse_telegram(self, data): # self.logger.debug("Ignore telegram.") return if (data[6] & 0x03 or (data[7] & 0xC0) == 0xC0): - self.logger.debug("KNX[{0}]: Unknown APDU".format(self.get_instance_name())) + self.logger.debug("Unknown APDU") return src = self.decode(data[2:4], 'pa') dst = self.decode(data[4:6], 'ga') @@ -300,7 +304,7 @@ def parse_telegram(self, data): elif flg == KNXRESP: flg = 'response' else: - self.logger.warning("KNX[{0}]: Unknown flag: {1:02x} src: {2} dest: {3}".format(self.get_instance_name(), flg, src, dst)) + self.logger.warning("Unknown flag: {:02x} src: {} dest: {}".format(flg, src, dst)) return if len(data) == 8: payload = bytearray([data[7] & 0x3f]) @@ -337,7 +341,7 @@ def parse_telegram(self, data): try: val = self.decode(payload, dpt) except Exception as e: - self.logger.exception("KNX[{0}]: Problem decoding frame from {1} to {2} with '{3}' and DPT {4}. Exception: {5}".format(self.get_instance_name(), src, dst, binascii.hexlify(payload).decode(), dpt, e)) + self.logger.exception("Problem decoding frame from {} to {} with '{}' and DPT {}. Exception: {}".format(src, dst, binascii.hexlify(payload).decode(), dpt, e)) return if val is not None: self._busmonitor(self._bm_format.format(self.get_instance_name(), src, dst, val)) @@ -352,20 +356,24 @@ def parse_telegram(self, data): if dst in self._cache_ga_response_pending: self._cache_ga_response_pending.remove(dst) way = "" if typ != KNXD_CACHE_READ else " (from knxd Cache)" - self.logger.debug("KNX[{0}]: {5} request from {1} to {2} with '{3}' and DPT {4}{6}".format(self.get_instance_name(), src, dst, binascii.hexlify(payload).decode(), dpt, flg, way)) + self.logger.debug("{} request from {} to {} with '{}' and DPT {}{}".format(flg, src, dst, binascii.hexlify(payload).decode(), dpt, way)) + src_wrk = self.get_instance_name() + if src_wrk != '': + src_wrk += ':' + src_wrk += src + ':ga=' + dst for item in self.gal[dst][ITEMS]: - item(val, 'KNX', src, dst) + item(val, self.get_shortname(), src_wrk, dst) for logic in self.gal[dst][LOGICS]: - logic.trigger('KNX', src, val, dst) + logic.trigger(self.get_shortname(), src_wrk, val, dst) else: - self.logger.warning("KNX[{0}]: Wrong payload '{3}' for ga '{2}' with dpt '{1}'.".format(self.get_instance_name(), dpt, dst, binascii.hexlify(payload).decode())) + self.logger.warning("Wrong payload '{2}' for ga '{1}' with dpt '{0}'.".format(dpt, dst, binascii.hexlify(payload).decode())) if self.enable_stats: if flg == 'write': self.stats_last_write = self.shtime.now() else: self.stats_last_response = self.shtime.now() elif flg == 'read': - self.logger.debug("KNX[{0}]: {1} read {2}".format(self.get_instance_name(), src, dst)) + self.logger.debug("{} read {}".format(src, dst)) if self.enable_stats: self.stats_last_read = self.shtime.now() if dst in self.gar: # read item @@ -373,14 +381,18 @@ def parse_telegram(self, data): item = self.gar[dst][ITEM] self.groupwrite(dst, item(), self.get_iattr_value(item.conf,KNX_DPT), 'response') if self.gar[dst][LOGIC] is not None: - self.gar[dst][LOGIC].trigger('KNX', src, None, dst) + src_wrk = self.get_instance_name() + if src_wrk != '': + src_wrk += ':' + src_wrk += src + ':ga=' + dst + self.gar[dst][LOGIC].trigger(self.get_shortname(), src_wrk, None, dst) def run(self): """ Run method for the plugin """ - self.logger.debug("Plugin '{}': run method called".format(self.get_fullname())) + self.logger.debug("run method called") self.alive = True @@ -388,7 +400,7 @@ def stop(self): """ Stop method for the plugin """ - self.logger.debug("Plugin '{}': stop method called".format(self.get_fullname())) + self.logger.debug("stop method called") self.alive = False self.close() @@ -407,27 +419,27 @@ def parse_item(self, item): can be sent to the knx with a knx write function within the knx plugin. """ if self.has_iattr(item.conf, KNX_DTP): - self.logger.error("KNX[{0}]: Ignoring {1}: please change knx_dtp to knx_dpt.".format(self.get_instance_name(), item)) + self.logger.error("Ignoring {}: please change knx_dtp to knx_dpt.".format(item)) return None if self.has_iattr(item.conf, KNX_DPT): dpt = self.get_iattr_value( item.conf, KNX_DPT) if dpt not in dpts.decode: - self.logger.warning("KNX[{0}]: Ignoring {1} unknown dpt: {2}".format(self.get_instance_name(), item, dpt)) + self.logger.warning("Ignoring {} unknown dpt: {}".format(item, dpt)) return None elif self.has_iattr(item.conf, KNX_STATUS) or self.has_iattr(item.conf, KNX_SEND) or self.has_iattr(item.conf, KNX_REPLY) or self.has_iattr(item.conf, KNX_LISTEN) or self.has_iattr(item.conf, KNX_INIT) or self.has_iattr( item.conf, KNX_CACHE): self.logger.warning( - "KNX[{0}]: Ignoring {1}: please add knx_dpt.".format(self.get_instance_name(), item)) + "Ignoring {}: please add knx_dpt.".format(item)) return None else: return None - self.logger.debug("KNX[{1}]: Item {0} is mapped to KNX Instance {1}".format(item, self.get_instance_name())) + self.logger.debug("Item {} is mapped to KNX Instance {}".format(item, self.get_instance_name())) if self.has_iattr(item.conf, KNX_LISTEN): knx_listen = self.get_iattr_value(item.conf, KNX_LISTEN) if isinstance(knx_listen, str): knx_listen = [knx_listen, ] for ga in knx_listen: - self.logger.debug("KNX[{0}]: {1} listen on {2}".format(self.get_instance_name(), item, ga)) + self.logger.debug("{} listen on {}".format(item, ga)) if not ga in self.gal: self.gal[ga] = {DPT: dpt, ITEMS: [item], LOGICS: []} else: @@ -436,7 +448,7 @@ def parse_item(self, item): if self.has_iattr(item.conf, KNX_INIT): ga = self.get_iattr_value(item.conf, KNX_INIT) - self.logger.debug("KNX[{0}]: {1} listen on and init with {2}".format(self.get_instance_name(), item, ga)) + self.logger.debug("{} listen on and init with {}".format(item, ga)) if not ga in self.gal: self.gal[ga] = {DPT: dpt, ITEMS: [item], LOGICS: []} else: @@ -446,7 +458,7 @@ def parse_item(self, item): if self.has_iattr(item.conf, KNX_CACHE): ga = self.get_iattr_value(item.conf, KNX_CACHE) - self.logger.debug("KNX[{0}]: {1} listen on and init with cache {2}".format(self.get_instance_name(), item, ga)) + self.logger.debug("{} listen on and init with cache {}".format(item, ga)) if not ga in self.gal: self.gal[ga] = {DPT: dpt, ITEMS: [item], LOGICS: []} else: @@ -459,13 +471,12 @@ def parse_item(self, item): if isinstance(knx_reply, str): knx_reply = [knx_reply, ] for ga in knx_reply: - self.logger.debug("KNX[{0}]: {1} reply to {2}".format(self.get_instance_name(), item, ga)) + self.logger.debug("{} reply to {}".format(item, ga)) if ga not in self.gar: self.gar[ga] = {DPT: dpt, ITEM: item, LOGIC: None} else: self.logger.warning( - "KNX[{0}]: {1} knx_reply ({2}) already defined for {3}".format(self.get_instance_name(), item.id(), ga, - self.gar[ga][ITEM])) + "{} knx_reply ({}) already defined for {}".format( item.id(), ga, self.gar[ga][ITEM])) if self.has_iattr(item.conf, KNX_SEND): if isinstance(self.get_iattr_value(item.conf, KNX_SEND), str): @@ -484,16 +495,15 @@ def parse_item(self, item): poll_interval = knx_poll[1] self.logger.info( - "KNX[{0}]: Item {1} is polled on GA {2} every {3} seconds".format(self.get_instance_name(), item, poll_ga, - poll_interval)) + "Item {} is polled on GA {} every {} seconds".format(item, poll_ga, poll_interval)) randomwait = random.randrange(15) next = self.shtime.now() + timedelta(seconds=poll_interval + randomwait) self._sh.scheduler.add('KNX poll {}'.format(item), self._poll, value={ITEM: item, 'ga': poll_ga, 'interval': poll_interval}, next=next) else: self.logger.warning( - "KNX[{0}]: Ignoring knx_poll for item {1}: We need two parameters, one for the GA and one for the polling interval.".format( - self.get_instance_name(), item)) + "Ignoring knx_poll for item {}: We need two parameters, one for the GA and one for the polling interval.".format( + item)) pass if self.has_iattr(item.conf, KNX_STATUS) or self.has_iattr(item.conf, KNX_SEND): @@ -509,19 +519,19 @@ def parse_logic(self, logic): if KNX_DPT in logic.conf: dpt = logic.conf[KNX_DPT] if dpt not in dpts.decode: - self.logger.warning("KNX[{0}]: Ignoring {1} unknown dpt: {2}".format(self.get_instance_name(), logic, dpt)) + self.logger.warning("Ignoring {} unknown dpt: {}".format(logic, dpt)) return None else: return None - self.logger.debug("KNX[{1}]: Logic {0} is mapped to KNX Instance {1}".format(logic, self.get_instance_name())) + self.logger.debug("Logic {} is mapped to KNX Instance {}".format(logic, self.get_instance_name())) if KNX_LISTEN in logic.conf: knx_listen = logic.conf[KNX_LISTEN] if isinstance(knx_listen, str): knx_listen = [knx_listen, ] for ga in knx_listen: - self.logger.debug("KNX[{0}]: {1} listen on {2}".format(self.get_instance_name(), logic, ga)) + self.logger.debug("{} listen on {}".format(logic, ga)) if not ga in self.gal: self.gal[ga] = {DPT: dpt, ITEMS: [], LOGICS: [logic]} else: @@ -532,13 +542,13 @@ def parse_logic(self, logic): if isinstance(knx_reply, str): knx_reply = [knx_reply, ] for ga in knx_reply: - self.logger.debug("KNX[{0}]: {1} reply to {2}".format(self.get_instance_name(), logic, ga)) + self.logger.debug("{} reply to {}".format(logic, ga)) if ga in self.gar: if self.gar[ga][LOGIC] is False: obj = self.gar[ga][ITEM] else: obj = self.gar[ga][LOGIC] - self.logger.warning("KNX[{0}]: {1} knx_reply ({2}) already defined for {3}".format(self.get_instance_name(), logic, ga, obj)) + self.logger.warning("{} knx_reply ({}) already defined for {}".format(logic, ga, obj)) else: self.gar[ga] = {DPT: dpt, ITEM: None, LOGIC: logic} @@ -557,7 +567,7 @@ def update_item(self, item, caller=None, source=None, dest=None): :param dest: if given it represents the dest """ if self.has_iattr(item.conf, KNX_SEND): - if caller != 'KNX': + if caller != 'knx': for ga in self.get_iattr_value(item.conf, KNX_SEND): self.groupwrite(ga, item(), self.get_iattr_value(item.conf, KNX_DPT)) if self.has_iattr(item.conf, KNX_STATUS): @@ -577,12 +587,12 @@ def init_webinterface(self): except: self.mod_http = None if self.mod_http == None: - self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_shortname())) + self.logger.error("Not initializing the web interface") return False import sys if not "SmartPluginWebIf" in list(sys.modules['lib.model.smartplugin'].__dict__): - self.logger.warning("Plugin '{}': Web interface needs SmartHomeNG v1.5 and up. Not initializing the web interface".format(self.get_shortname())) + self.logger.warning("Web interface needs SmartHomeNG v1.5 and up. Not initializing the web interface") return False # set application configuration for cherrypy diff --git a/knx/plugin.yaml b/knx/plugin.yaml index 9522e1efd..6ea324c51 100755 --- a/knx/plugin.yaml +++ b/knx/plugin.yaml @@ -12,7 +12,7 @@ plugin: # keywords: iot xyz # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page - version: 1.4.5 # Plugin version + version: 1.4.6 # Plugin version sh_minversion: 1.4 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance From 8ae05e3f3c1846b076ee29e9830cfed418f83c88 Mon Sep 17 00:00:00 2001 From: msinn Date: Mon, 5 Nov 2018 01:52:17 +0100 Subject: [PATCH 407/705] homematic: Extended source information (for backend and logics) --- backend/BackendSysteminfo.py | 23 ++++++++++++++--------- homematic/__init__.py | 10 +++++++--- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/backend/BackendSysteminfo.py b/backend/BackendSysteminfo.py index 2296a170f..d851bb319 100755 --- a/backend/BackendSysteminfo.py +++ b/backend/BackendSysteminfo.py @@ -89,16 +89,21 @@ def system_html(self): seconds = uptime uptime = self.age_to_string(days, hours, minutes, seconds) + # # return SmarthomeNG runtime + # rt = str(Shtime.get_instance().runtime()) + # daytest = rt.split(' ') + # if len(daytest) == 3: + # days = int(daytest[0]) + # hours, minutes, seconds = [float(val) for val in str(daytest[2]).split(':')] + # else: + # days = 0 + # hours, minutes, seconds = [float(val) for val in str(daytest[0]).split(':')] + # sh_uptime = self.age_to_string(days, hours, minutes, seconds) + # return SmarthomeNG runtime - rt = str(Shtime.get_instance().runtime()) - daytest = rt.split(' ') - if len(daytest) == 3: - days = int(daytest[0]) - hours, minutes, seconds = [float(val) for val in str(daytest[2]).split(':')] - else: - days = 0 - hours, minutes, seconds = [float(val) for val in str(daytest[0]).split(':')] - sh_uptime = self.age_to_string(days, hours, minutes, seconds) + rt = Shtime.get_instance().runtime_as_dict() + sh_uptime = self.age_to_string(rt['days'], rt['hours'], rt['minutes'], rt['seconds']) + pyversion = "{0}.{1}.{2} {3}".format(sys.version_info[0], sys.version_info[1], sys.version_info[2], sys.version_info[3]) diff --git a/homematic/__init__.py b/homematic/__init__.py index 8c681c6d7..c712be395 100755 --- a/homematic/__init__.py +++ b/homematic/__init__.py @@ -288,7 +288,7 @@ def update_item(self, item, caller=None, source=None, dest=None): :param source: if given it represents the source :param dest: if given it represents the dest """ - if caller != 'HomeMatic': + if caller != 'homematic': if self.has_iattr(item.conf, 'hm_address'): # self.hm_items[] = [str(item), item, hm_address, hm_channel, hm_function, hm_node] myitem = None @@ -456,8 +456,12 @@ def eventcallback(self, interface_id, address, value_key, value): if address == i[2]+':'+str(i[3]): if value_key == i[4]: self.logger.info("eventcallback: address={}, {}='{}' -> {}".format(address, value_key, value, i[0])) -# i[1](value, 'HomeMatic', address) - i[1](value, 'HomeMatic') + src = self.get_instance_name() + if src != '': + src += ':' + src += address + i[1](value, self.get_shortname(), src) +# i[1](value, 'HomeMatic') defined = True if not defined: From f6bc956885b3dd5269b7aad8228b0f1b6b616040 Mon Sep 17 00:00:00 2001 From: Zapfen83 Date: Mon, 5 Nov 2018 09:59:05 +0100 Subject: [PATCH 408/705] =?UTF-8?q?=09anpassung:=20=20=20=20=20=20=20roomb?= =?UTF-8?q?a=5F980/=5F=5Finit=5F=5F.py=20->lkleine=20=C3=A4nderungen=20=09?= =?UTF-8?q?Anpassung:=20=20=20=20=20=20=20roomba=5F980/plugin.yaml=20->=20?= =?UTF-8?q?Englische=20Plugin=20Beschreibung=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- roomba_980/__init__.py | 9 ++++----- roomba_980/plugin.yaml | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/roomba_980/__init__.py b/roomba_980/__init__.py index 7980a3699..ac2ab99e3 100755 --- a/roomba_980/__init__.py +++ b/roomba_980/__init__.py @@ -32,7 +32,6 @@ class ROOMBA_980(SmartPlugin): myroomba = None def __init__(self, sh, adress=None, blid=None, roombaPassword=None, cycle=900): - self._sh = sh self._address = adress self._blid = blid self._roombaPassword = roombaPassword @@ -62,7 +61,7 @@ def run(self): self.alive = True def stop(self): - self.scheduler.remove(__name__) + self.scheduler.remove('get_status') self.myroomba.disconnect() self.alive = False @@ -88,11 +87,11 @@ def get_status(self): for status_item in self._status_items: if status_item == "status_batterie": self._status_items[status_item](status['state']['reported']['batPct'],__name__) - if status_item == "status_bin_full": + elif status_item == "status_bin_full": self._status_items[status_item](status['state']['reported']['bin']['full'],__name__) - if status_item == "status_cleanMissionStatus_phase": + elif status_item == "status_cleanMissionStatus_phase": self._status_items[status_item](status['state']['reported']['cleanMissionStatus']['phase'],__name__) - if status_item == "status_cleanMissionStatus_error": + elif status_item == "status_cleanMissionStatus_error": self._status_items[status_item](status['state']['reported']['cleanMissionStatus']['error'],__name__) self.logger.debug('Status update') diff --git a/roomba_980/plugin.yaml b/roomba_980/plugin.yaml index 7b79b0223..968ca2b93 100644 --- a/roomba_980/plugin.yaml +++ b/roomba_980/plugin.yaml @@ -4,7 +4,7 @@ plugin: type: interface # plugin type (gateway, interface, protocol, system, web) description: de: 'Anbindung von iRobot Roomba Staubsaugern der Serie 900' - en: '' + en: 'integration of the iRobot Roomba vacuum cleaner series 900' maintainer: 'Zapfen83' tester: keywords: irobot roomba # keywords, where applicable From 9b855e47f1e1171d969dcd27621a4314a6d232f8 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Mon, 5 Nov 2018 20:29:54 +0100 Subject: [PATCH 409/705] Update uzsu/__init__.py fix )) --- uzsu/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uzsu/__init__.py b/uzsu/__init__.py index 41c771776..18cb06f31 100755 --- a/uzsu/__init__.py +++ b/uzsu/__init__.py @@ -169,7 +169,7 @@ def _update_all_suns(self, caller=None): success = self._update_sun(item) if success: self.logger.debug('Updating sun info for item {}'.format(item)) - item(self._items[item], 'UZSU Plugin', 'update_all_suns')) + item(self._items[item], 'UZSU Plugin', 'update_all_suns') def _update_sun(self, item, caller=None): """ From 254990966e46e81b345ea7b20bcb29463dee5b2e Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Thu, 8 Nov 2018 00:55:15 +0100 Subject: [PATCH 410/705] Updated README and updated plugin to use self.has_iattr() --- rtr/README.md | 111 ++++++++++++++++++++++++++++++++++++++++++++++++ rtr/__init__.py | 4 +- 2 files changed, 113 insertions(+), 2 deletions(-) diff --git a/rtr/README.md b/rtr/README.md index 941e8d6e2..67bdbf246 100644 --- a/rtr/README.md +++ b/rtr/README.md @@ -84,6 +84,16 @@ To achieve this, the plugins stores the unix timestamp of the timers end in a fi For more info about the functions contine reading. +#### rtr_hvac_mode + +The ``rtr_hvac_mode`` can be connected to a item, to trigger/read the 3 new modes (default/boost/drop) and get the currently mode set. It implements the KNX DPT 20.102. + +Set the item value to +- 1 to trigger the boost function of the controller +- 2 to trigger the default function of the controller +- 3 to trigger the drop function of the controller +- 4 is currently not implemented and sets the controller back to default + ### Example The following shows an simple example for a working. @@ -161,3 +171,104 @@ gf: rtr_stops: - '2' ``` + +## logic + +To define items which trigger the default(), boost() or drop() function, you can use the item attribute rtr_hvac_mode or you can start to use a logic and bind the watch item(s) to that logic. + +For that I made the following logic, which you can take as an example: + +``` +src = trigger['source'] +logger.info("triggerd by {}".format(src)) +src_item = sh.return_item(src) + +if src_item is not None and src_item(): + parent_item = src_item.return_parent() + src_item_name = src_item.id().replace("{}.".format(parent_item.id()), "") + logger.debug("extracted item name {}".format(src_item_name)) + + src_item_parts = src_item_name.split('_') + if len(src_item_parts) == 3: + m = 0 + st = src_item_parts[2] + if st.find("h") > 0: + num = st.replace("h", "") + if num.isnumeric(): + m = int(num) * 60 + elif st.find("m") > 0: + num = st.replace("m", "") + if num.isnumeric(): + m = int(num) + else: + logger.error("time is invalid for this logic!") + + if m > 0 or src_item_parts[0] == "default": + + items = [] + if src_item_parts[1] == "all": + for item in sh.find_items('rtr_current'): + items.append(item) + else: + for item in sh.match_items('*.'+src_item_parts[1]+'.*:rtr_current'): + items.append(item) + + edt = sh.now() + datetime.timedelta(minutes=m) + if src_item_parts[0] == "default": + for item in items: + sh.rtr.default(item.conf["rtr_current"]) + elif src_item_parts[0] == "boost": + for item in items: + sh.rtr.boost(item.conf["rtr_current"], edt) + elif src_item_parts[0] == "drop": + for item in items: + sh.rtr.drop(item.conf["rtr_current"], edt) + else: + logger.error("time of 0 is invalid for this logic!") + else: + logger.error("item name is invalid for this logic!") +``` + +Than I created the follow items: + +``` +central: + + heater: + sv_page: overview + sv_img: sani_heating.svg + sv_overview: heater + + sv_heading_left: "Boost for {{ basic.stateswitch('bz1', '.boost_all_3h', '', 1, 'sani_heating_temp', '3h', '', 'icon1') }}{{ basic.stateswitch('bz2', '.boost_all_5h', '', 1, 'sani_heating_temp', '5h', '', 'icon1') }}" + sv_heading_center: "{{ basic.stateswitch('nz1', '.default_all_0h', '', 1, 'sani_heating_temp', 'Normal', '', 'icon1') }}" + sv_heading_right: "Drop for {{ basic.stateswitch('dz1', '.drop_all_3h', '', 1, 'sani_heating_temp', '3h', '', 'icon1') }}{{ basic.stateswitch('dz2', '.drop_all_5h', '', 1, 'sani_heating_temp', '5h', '', 'icon1') }}" + + default_all_0h: + type: bool + visu_acl: rw + enforce_updates: 'yes' + + boost_all_3h: + type: bool + visu_acl: rw + enforce_updates: 'yes' + + boost_all_5h: + type: bool + visu_acl: rw + enforce_updates: 'yes' + + drop_all_3h: + type: bool + visu_acl: rw + enforce_updates: 'yes' + + drop_all_5h: + type: bool + visu_acl: rw + enforce_updates: 'yes' +``` + +The logic extract the function name (default/boost/drop), destination items and runtime from the triggering item name. +Because rtr->default() can't have a datetime set, you must define 0d/0m in the name. +Everything elso should be self explained and can/should be modified to your needs. diff --git a/rtr/__init__.py b/rtr/__init__.py index f3d1ee2d5..4604a2daf 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -300,7 +300,7 @@ def update_HVACMode(self, item, caller=None, source=None, dest=None): :param dest: if given it represents the dest """ if item() and caller != 'plugin': - if 'rtr_hvac_mode' in item.conf: + if self.has_iattr(item.conf, 'rtr_hvac_mode'): c = 'c' + item.conf['rtr_hvac_mode'] if self._controller[c]['validated']: if item() == self.HVACMode_Auto: @@ -330,7 +330,7 @@ def update_setpoint(self, item, caller=None, source=None, dest=None): """ self.logger.debug("rtr: update item {}, from caller = {}, with source={} and dest={}".format(item.id(), caller, source, dest)) if item() and caller != 'plugin': - if 'rtr_setpoint' in item.conf: + if self.has_iattr(item.conf, 'rtr_setpoint'): c = 'c' + item.conf['rtr_setpoint'] if self._controller[c]['validated']: self.pi_controller(c) From 3782cc6b49325d568c1e6093017a56f032160622 Mon Sep 17 00:00:00 2001 From: Stefan Date: Fri, 9 Nov 2018 11:39:54 +0100 Subject: [PATCH 411/705] Fix typos in enforce_updates --- intercom_2n/README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/intercom_2n/README.md b/intercom_2n/README.md index d3f160c3f..6316c65b6 100644 --- a/intercom_2n/README.md +++ b/intercom_2n/README.md @@ -1,3 +1,4 @@ + # 2N-Intercom Plugin ## Requirements @@ -257,7 +258,7 @@ Intercom_2n: # – button with a # or key symbol type: str event_data_2n: key - enforce_udpates: 'True' + enforce_updates: 'True' KeyReleased: # Signals releasing (KeyReleased) of speed dial or numeric keypad buttons. @@ -271,7 +272,7 @@ Intercom_2n: # – button with a # or key symbol type: str event_data_2n: key - enforce_udpates: 'True' + enforce_updates: 'True' CodeEntered: # Signals entering of a user code via the numeric keypad. The event is generated in numeric keypad equipped @@ -282,7 +283,7 @@ Intercom_2n: # User code, 1234, e.g.. The code includes 2 digits at least and 00 cannot be used. type: str event_data_2n: code - enforce_udpates: 'True' + enforce_updates: 'True' valid: # Code validity (i.e. if the code is defined as a valid user code or universal switch code in the intercom @@ -291,7 +292,7 @@ Intercom_2n: # true – valid code type: bool event_data_2n: valid - enforce_udpates: 'True' + enforce_updates: 'True' CardEntered: # Signals tapping an RFID card on the card reader. The event is generated in RFID card reader equipped devices From 36e87f03f54f0222b94fd3ab747a539ceeefb328 Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Sun, 11 Nov 2018 14:11:17 +0100 Subject: [PATCH 412/705] added plugin params into README.md --- rtr/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rtr/README.md b/rtr/README.md index 67bdbf246..df6f5ff1e 100644 --- a/rtr/README.md +++ b/rtr/README.md @@ -17,6 +17,9 @@ Description of the attributes: * __default_Kp__: change default value for Kp (optional, default: 10) * __default_Ki__: change default value for Ki (optional, default: 15) +* __cycle_time__: (optional, default: 60) +* __defaultBoostTime__: (optional, default: 240) +* __defaultOnExpiredTimer__: (optional, default: True) ## items.yaml From 07a025cdd734dd675b202cab21502512470e79ba Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Mon, 12 Nov 2018 22:33:38 +0100 Subject: [PATCH 413/705] added valve protection modified attribute value validation in parse_item() --- rtr/__init__.py | 100 ++++++++++++++++++++++++++++++++++++++++-------- rtr/plugin.yaml | 7 ++++ 2 files changed, 92 insertions(+), 15 deletions(-) diff --git a/rtr/__init__.py b/rtr/__init__.py index 4604a2daf..7a70a8195 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -67,6 +67,8 @@ class RTR(SmartPlugin): 'tempDrop' : 0, 'tempBoost' : 0, 'tempBoostTime' : 0, + 'valveProtect' : False, + 'valveProtectActive' : False, 'validated' : False} def __init__(self, sh, *args, **kwargs): @@ -92,6 +94,7 @@ def __init__(self, sh, *args, **kwargs): self._defaults['Kp'] = self.get_parameter_value('default_Kp') self._defaults['Ki'] = self.get_parameter_value('default_Ki') self._defaults['tempBoostTime'] = self.get_parameter_value('defaultBoostTime') + self._defaults['valveProtect'] = self.get_parameter_value('defaultValveProtect') self._cycle_time = self.get_parameter_value('cycle_time') self._defaultOnExpiredTimer = self.get_parameter_value('defaultOnExpiredTimer') @@ -104,6 +107,7 @@ def run(self): self.logger.debug("run method called") self.alive = True self.scheduler_add('cycle', self.update_items, prio=5, cycle=int(self._cycle_time)) + self.scheduler_add('protect', self.valve_protect, prio=5, cron='0 2 * 0') try: self._restoreTimer() @@ -139,15 +143,19 @@ def parse_item(self, item): self._controller[c]['currentItem'] = item.id() self.logger.info("rtr: bound item '{1}' to currentItem for controller '{0}'".format(c, item.id())) - if not self.has_iattr(item.conf, 'rtr_Kp'): - self.logger.info("rtr: missing rtr_Kp in item {0}, setting to default: {1}".format(item.id(), self._controller[c]['Kp'])) - else: - self._controller[c]['Kp'] = float(item.conf['rtr_Kp']) + # check for optional item attribute rtr_Kp (float) + if self.has_iattr(item.conf, 'rtr_Kp'): + if item.conf['rtr_Kp'].replace(".", "", 1).isdigit(): + self._controller[c]['Kp'] = float(item.conf['rtr_Kp']) + else: + self.logger.error("rtr: item {0}, rtr_Kp need to be a number".format(item.id())) - if not self.has_iattr(item.conf, 'rtr_Ki'): - self.logger.info("rtr: missing rtr_Ki in item {0}, setting to default: {1}".format(item.id(), self._controller[c]['Ki'])) - else: - self._controller[c]['Ki'] = float(item.conf['rtr_Ki']) + # check for optional item attribute rtr_Ki (float) + if self.has_iattr(item.conf, 'rtr_Ki'): + if item.conf['rtr_Ki'].replace(".", "", 1).isdigit(): + self._controller[c]['Ki'] = float(item.conf['rtr_Ki']) + else: + self.logger.error("rtr: item {0}, rtr_Ki need to be a number".format(item.id())) if not self._controller[c]['validated']: self.validate_controller(c) @@ -170,17 +178,33 @@ def parse_item(self, item): self._controller[c]['setpointItem'] = item.id() self.logger.info("rtr: bound item '{1}' to setpointItem for controller '{0}'".format(c, item.id())) + # check for optional item attribute rtr_temp_default (float) if self.has_iattr(item.conf, 'rtr_temp_default'): - self._controller[c]['tempDefault'] = float(item.conf['rtr_temp_default']) + if item.conf['rtr_temp_default'].replace(".", "", 1).isdigit(): + self._controller[c]['tempDefault'] = float(item.conf['rtr_temp_default']) + else: + self.logger.error("rtr: item {0}, rtr_temp_default need to be a number".format(item.id())) + # check for optional item attribute rtr_temp_drop (float) if self.has_iattr(item.conf, 'rtr_temp_drop'): - self._controller[c]['tempDrop'] = float(item.conf['rtr_temp_drop']) + if item.conf['rtr_temp_drop'].replace(".", "", 1).isdigit(): + self._controller[c]['tempDrop'] = float(item.conf['rtr_temp_drop']) + else: + self.logger.error("rtr: item {0}, rtr_temp_drop need to be a number".format(item.id())) + # check for optional item attribute rtr_temp_boost (float) if self.has_iattr(item.conf, 'rtr_temp_boost'): - self._controller[c]['tempBoost'] = float(item.conf['rtr_temp_boost']) + if item.conf['rtr_temp_boost'].replace(".", "", 1).isdigit(): + self._controller[c]['tempBoost'] = float(item.conf['rtr_temp_boost']) + else: + self.logger.error("rtr: item {0}, rtr_temp_boost need to be a number".format(item.id())) + # check for optional item attribute rtr_temp_boost_time (float) if self.has_iattr(item.conf, 'rtr_temp_boost_time'): - self._controller[c]['tempBoostTime'] = int(item.conf['rtr_temp_boost_time']) + if item.conf['rtr_temp_boost_time'].isdigit(): + self._controller[c]['tempBoostTime'] = int(item.conf['rtr_temp_boost_time']) + else: + self.logger.error("rtr: item {0}, rtr_temp_boost_time need to be a number".format(item.id())) if not self._controller[c]['validated']: self.validate_controller(c) @@ -203,6 +227,15 @@ def parse_item(self, item): self._controller[c]['actuatorItem'] = item.id() self.logger.info("rtr: bound item '{1}' to actuatorItem for controller '{0}'".format(c, item.id())) + # check for optional item attribute rtr_valve_protect (bool) + if self.has_iattr(item.conf, 'rtr_valve_protect'): + if item.conf['rtr_valve_protect'].lower() in ['yes', 'true', 'on', '1']: + self._controller[c]['valveProtect'] = True + elif item.conf['rtr_valve_protect'].lower() in ['no', 'false', 'off', '0']: + self._controller[c]['valveProtect'] = False + else: + self.logger.error("rtr: item {0}, rtr_valve_protect need to be boolean".format(item.id())) + if not self._controller[c]['validated']: self.validate_controller(c) @@ -215,6 +248,11 @@ def parse_item(self, item): c = 'c' + item.conf['rtr_timer_end_text'] + # init controller with defaults when it not exist + if c not in self._controller: + self.logger.debug("rtr: controller '{0}' does not exist yet. Init with default values".format(c)) + self._controller[c] = self._defaults.copy() + self._controller[c]['timerendItem'] = item.id() return @@ -226,6 +264,11 @@ def parse_item(self, item): c = 'c' + item.conf['rtr_hvac_mode'] + # init controller with defaults when it not exist + if c not in self._controller: + self.logger.debug("rtr: controller '{0}' does not exist yet. Init with default values".format(c)) + self._controller[c] = self._defaults.copy() + self._controller[c]['HVACModeItem'] = item.id() return self.update_HVACMode @@ -236,7 +279,7 @@ def parse_item(self, item): if self.has_iattr(item.conf, 'rtr_stops'): # validate this optional Item - if item._type != 'bool': + if item.type() != 'bool': self.logger.error("rtr: error in item {0}, rtr_stops Item need to be bool (current {1})".format(item.id(), item._type)) return @@ -338,8 +381,7 @@ def update_setpoint(self, item, caller=None, source=None, dest=None): def update_items(self): """ this is the callback function for the scheduler """ for c in self._controller.keys(): - if self._controller[c]['validated']: - + if self._controller[c]['validated'] and not self._controller[c]['valveProtectActive']: self.pi_controller(c) def validate_controller(self, c): @@ -620,3 +662,31 @@ def drop(self, c, edt=None): self._createTimer('drop_' + c, c, edt) else: self.logger.error("drop() unknown controller '{}' - we only have '{}'".format(c, self._controller.keys())) + + def valve_protect(self, y=100): + """ + Initalizes valve protecion + 1. call = open valve (y=100) -> timer +5min + 2. call = close valve (y=0) -> timer +5min + 3. call = active = false + """ + self.logger.info("run valve protecion") + + shtime = Shtime.get_instance() + edt = shtime.now() + datetime.timedelta(minutes=5) + + if y == 100: + self.scheduler_add('protectClose', self.valve_protect, value={'y': 0}, next=edt) + elif y == 0: + self.scheduler_add('protectOff', self.valve_protect, value={'y': -1}, next=edt) + + for c in self._controller.keys(): + if self._controller[c]['validated'] and self._controller[c]['valveProtect']: + + if y >= 0: + yItem = self._items.return_item(self._controller[c]['actuatorItem']) + self.logger.debug("set item '{}' to '{}'".format(yItem.id(), y)) + self._controller[c]['valveProtectActive'] = True + yItem(y) + else: + self._controller[c]['valveProtectActive'] = False diff --git a/rtr/plugin.yaml b/rtr/plugin.yaml index 52516c16a..85281f860 100755 --- a/rtr/plugin.yaml +++ b/rtr/plugin.yaml @@ -48,6 +48,10 @@ parameters: de: "Wenn nicht aktiviert, werden beim wiederherstellen von abgelaufenen Timern die Temperaturen nicht zurück auf Default gesetzt" en: "when not True, a expired timer will not set back to Default-Temperature on a timer restore (when SH will be restarted)" + defaultValveProtect: + type: bool + default: true + item_attributes: rtr_current: type: int @@ -106,6 +110,9 @@ item_attributes: de: 'Ordnet das Item dem Controller mit gegebener ID als Stellgröße zu' en: 'Defines the Item as actuator value for the given controller ID' + rtr_valve_protect: + type: bool + rtr_hvac_mode: type: int From 0db7d48c6c69cd30c8420d9f08d8397fdceb4d9c Mon Sep 17 00:00:00 2001 From: msinn Date: Wed, 14 Nov 2018 08:28:20 +0100 Subject: [PATCH 414/705] bin.smarthome: Removed superfluous print statement --- backend/BackendSysteminfo.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/backend/BackendSysteminfo.py b/backend/BackendSysteminfo.py index d851bb319..22edfa9c7 100755 --- a/backend/BackendSysteminfo.py +++ b/backend/BackendSysteminfo.py @@ -453,9 +453,11 @@ def get_requirements_info(self, req_group='base'): elif req_group == 'test': req_dict_base = parse_requirements(os.path.join(self._sh_dir, 'tests', 'requirements.txt')) self.logger.info("get_requirements_info: filepath = {}".format(os.path.join(self._sh_dir, 'tests', 'requirements.txt'))) + pass elif req_group == 'doc': req_dict_base = parse_requirements(os.path.join(self._sh_dir, 'doc', 'requirements.txt')) self.logger.info("get_requirements_info: filepath = {}".format(os.path.join(self._sh_dir, 'doc', 'requirements.txt'))) + pass else: self.logger.error("get_requirements_info: Unknown requirements group '{}' requested".format(req_group)) @@ -484,7 +486,10 @@ def get_requirements_info(self, req_group='base'): 'plugins.', '') + ')' if req_group in ['doc','test']: - req_dict = req_dict_base.copy() + try: + req_dict = req_dict_base.copy() + except: + pass self.logger.info("get_requirements_info: req_dict for group {} = {}".format(req_group, req_dict)) return req_dict From 36b9bd084c009c241b0a00529ca96d76b6e8305e Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 15 Nov 2018 17:53:17 +0100 Subject: [PATCH 415/705] Darksky: corrected parameter name in README --- darksky/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/darksky/README.md b/darksky/README.md index 7081790eb..205384039 100644 --- a/darksky/README.md +++ b/darksky/README.md @@ -30,7 +30,7 @@ weather_darksky: key: xxxxyyyyxxxxyyyy latitude: '48.04712' longitude: '11.81421' - # language: de + # lang: de # cycle: 600 # instance: ... ``` From 3e9247eb22d91c154ea0f48040cfe0324fedc251 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 16 Nov 2018 17:19:49 +0100 Subject: [PATCH 416/705] AVM: added tab for plugin api locale.yaml now working --- avm/__init__.py | 12 ++++++------ avm/locale.yaml | 17 +++++++++-------- avm/webif/templates/index.html | 12 ++++++++++-- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/avm/__init__.py b/avm/__init__.py index 55688dfe0..9968cddeb 100644 --- a/avm/__init__.py +++ b/avm/__init__.py @@ -2078,15 +2078,15 @@ def index(self, reload=None): :return: contents of the template after beeing rendered """ - tabcount = 1 - tab2title = "" + tabcount = 2 + call_monitor_items = 0 if self.plugin._call_monitor: - tab2title = "Call Monitor Items (%s)" % self.plugin._monitoring_service.get_item_count_total() - tabcount = 2 + call_monitor_items = self.plugin._monitoring_service.get_item_count_total() + tabcount = 3 tmpl = self.tplenv.get_template('index.html') return tmpl.render(plugin_shortname=self.plugin.get_shortname(), plugin_version=self.plugin.get_version(), plugin_info=self.plugin.get_info(), tabcount=tabcount, - tab1title="AVM Items (%s)" % self.plugin._fritz_device.get_item_count(), - tab2title=tab2title, + avm_items=self.plugin._fritz_device.get_item_count(), + call_monitor_items=call_monitor_items, p=self.plugin) diff --git a/avm/locale.yaml b/avm/locale.yaml index 987461463..2f0670309 100755 --- a/avm/locale.yaml +++ b/avm/locale.yaml @@ -1,10 +1,11 @@ plugin_translations: # Translations for the plugin specially for the web interface - 'AVM Datentyp': {'de': '=', 'en': 'AVM Data Type', 'fr': ''} - - # Alternative format for translations of longer texts: -# 'Hier kommt der Inhalt des Webinterfaces hin.': -# de: '=' -# en: 'Here goes the content of the web interface.' -# fr: 'Le contenu de l'interface web vient ici.' - + 'AVM Datentyp': {'de': '=', 'en': 'AVM Data Type', 'fr': ''} + 'AVM Items': {'de': '=', 'en': '=', 'fr': ''} + 'Pfad': {'de': '=', 'en': 'Path', 'fr': ''} + 'Typ': {'de': '=', 'en': 'Type', 'fr': ''} + 'Wert': {'de': '=', 'en': 'Value', 'fr': ''} + 'Letztes Update': {'de': '=', 'en': 'Last Update', 'fr': ''} + 'Letzter Change': {'de': '=', 'en': 'Last Change', 'fr': ''} + 'Plugin-API': {'de': '=', 'en': 'Plugin API', 'fr': ''} + 'Call Monitor Items': {'de': '=', 'en': '=', 'fr': ''} \ No newline at end of file diff --git a/avm/webif/templates/index.html b/avm/webif/templates/index.html index bbb83b270..e2d3291d2 100644 --- a/avm/webif/templates/index.html +++ b/avm/webif/templates/index.html @@ -1,5 +1,7 @@ {% extends "base_plugin.html" %} - +{% set tab1title = _('AVM Items') %} +{% set tab2title = _('Plugin-API') %} +{% set tab3title = _('Call Monitor Items') %} {% block headtable %}
{{ _('Pfad') }}{{ _('Pfad') }} {{ _('Typ') }}{{ _('Enforce Updates') }} {{ _('Nuki ID') }} {{ _('Wert') }} {{ _('Letztes Update') }}
{{ item.id() }} {{ item.type() }}{{ item._enforce_updates }} {{ value }} {{ item() }} @@ -134,7 +136,7 @@
{{ _('Nuki Battery Items') }} ({{ p.get_battery_items()|length }})
- + @@ -148,13 +150,26 @@
{{ _('Nuki Battery Items') }} ({{ p.get_battery_items()|length }})
- + {% endfor %}
{{ _('Pfad') }}{{ _('Pfad') }} {{ _('Typ') }} {{ _('Nuki ID') }} {{ _('Wert') }} {{ item.id() }} {{ item.type() }} {{ value }}{{ item() }} + {{ item() }} + {% if item() == 0 %}({{ _('Batteries are good. No need to replace it.') }}){% endif %} + {% if item() == 1 %}({{ _('Batteries are low. Please replace as soon as possible!') }}){% endif %} + {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} {{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }}
+
+
+
{{ _('Possible Battery Values') }}:
+

+ 0: {{ _('Batteries are good. No need to replace it.') }}  -   + 1: {{ _('Batteries are low. Please replace as soon as possible!') }} +

+
+

From aa3b95e663a1391b7d14a3b262cf7e08e5523bb8 Mon Sep 17 00:00:00 2001 From: msinn Date: Thu, 1 Nov 2018 15:54:32 +0100 Subject: [PATCH 367/705] Bugfix in lib.shpypi and modification to requirements --- backend/requirements.txt | 3 +-- blockly/requirements.txt | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/backend/requirements.txt b/backend/requirements.txt index 4f174159c..372a9b84d 100755 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -1,2 +1 @@ -jinja2>=2.9 -python-dateutil>=2.5.3 \ No newline at end of file +python-dateutil>=2.5.3 diff --git a/blockly/requirements.txt b/blockly/requirements.txt index e25e2a2ef..372a9b84d 100644 --- a/blockly/requirements.txt +++ b/blockly/requirements.txt @@ -1,3 +1 @@ -cherrypy>=8.1.2 -jinja2>=2.9 python-dateutil>=2.5.3 From 81798420bf041e743be7b60d2330d4b24dba8160 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 1 Nov 2018 17:19:25 +0100 Subject: [PATCH 368/705] Nuki: possibility to set nuki actions via webif now! --- nuki/__init__.py | 88 +++++++++++++++++++++++---------- nuki/webif/templates/index.html | 21 +++++--- 2 files changed, 76 insertions(+), 33 deletions(-) diff --git a/nuki/__init__.py b/nuki/__init__.py index ec03c1fc5..04baf665d 100644 --- a/nuki/__init__.py +++ b/nuki/__init__.py @@ -25,7 +25,10 @@ import requests import lib.connection import re +import cherrypy +from jinja2 import Environment, FileSystemLoader from lib.model.smartplugin import * +from lib.item import Items from bin.smarthome import VERSION nuki_action_items = {} @@ -37,9 +40,11 @@ class NukiTCPDispatcher(lib.connection.Server): def __init__(self, plugin): self.plugin = plugin - lib.connection.Server.__init__(self, self.plugin.get_callback_ip(), self.plugin.get_callback_port(), proto='TCP') + lib.connection.Server.__init__(self, self.plugin.get_callback_ip(), self.plugin.get_callback_port(), + proto='TCP') self.dest = 'tcp:' + self.plugin.get_callback_ip() + ':{port}'.format(port=self.plugin.get_callback_port()) - self.plugin.logger.debug("Plugin '{pluginname}' - NukiTCPDispatcher: starting tcp listener with {url}".format(pluginname=self.plugin.get_shortname(), url=self.dest)) + self.plugin.logger.debug("Plugin '{pluginname}' - NukiTCPDispatcher: starting tcp listener with {url}".format( + pluginname=self.plugin.get_shortname(), url=self.dest)) self.connect() def handle_connection(self): @@ -47,24 +52,29 @@ def handle_connection(self): conn, address = self.socket.accept() data = conn.recv(1024) address = "{}:{}".format(address[0], address[1]) - self.plugin.logger.info("Plugin '{}' - NukiTCPDispatcher: {}: incoming connection from {}".format(self.plugin.get_shortname(), 'test', address)) + self.plugin.logger.info( + "Plugin '{}' - NukiTCPDispatcher: {}: incoming connection from {}".format(self.plugin.get_shortname(), + 'test', address)) except Exception as err: self.logger.error("Plugin '{pluginname}':: {}: {}".format(self.plugin.get_shortname(), self._name, err)) return try: result = re.search('\{.*\}', data.decode('utf-8')) - self.plugin.logger.debug("Plugin '{}' - NukiTCPDispatcher: Getting JSON String".format(self.plugin.get_shortname())) + self.plugin.logger.debug( + "Plugin '{}' - NukiTCPDispatcher: Getting JSON String".format(self.plugin.get_shortname())) nuki_bridge_response = json.loads(result.group(0)) nuki_id = nuki_bridge_response['nukiId'] state_name = nuki_bridge_response['stateName'] - self.plugin.logger.debug("Plugin '{pluginname}' - NukiTCPDispatcher: Status Smartlock: ID: {nuki_id} Status: {state_name}". - format(pluginname=self.plugin.get_shortname(), nuki_id=nuki_id, state_name=state_name)) + self.plugin.logger.debug( + "Plugin '{pluginname}' - NukiTCPDispatcher: Status Smartlock: ID: {nuki_id} Status: {state_name}". + format(pluginname=self.plugin.get_shortname(), nuki_id=nuki_id, state_name=state_name)) conn.send(b"HTTP/1.1 200 OK\nContent-Type: text/html\n\n") Nuki.update_lock_state(nuki_id, nuki_bridge_response) except Exception as err: - self.plugin.logger.error("Plugin '{}' - NukiTCPDispatcher: Error parsing nuki response!\nError: {}".format(self.plugin.get_shortname(), err)) + self.plugin.logger.error("Plugin '{}' - NukiTCPDispatcher: Error parsing nuki response!\nError: {}".format( + self.plugin.get_shortname(), err)) class Nuki(SmartPlugin): @@ -88,17 +98,23 @@ def __init__(self, sh, *args, **kwargs): self._callback_port = self.get_parameter_value('bridge_callback_port') self._action = '' self._noWait = self.get_parameter_value('no_wait') + self.items = Items.get_instance() if self._callback_ip is None or self._callback_ip in ['0.0.0.0', '']: self._callback_ip = self.get_local_ipv4_address() if not self._callback_ip: - self.logger.critical("Plugin '{}': Could not fetch internal ip address. Set it manually!".format(self.get_shortname())) + self.logger.critical( + "Plugin '{}': Could not fetch internal ip address. Set it manually!".format(self.get_shortname())) self.alive = False return - self.logger.info("Plugin '{pluginname}': using local ip address {ip}".format(pluginname=self.get_shortname(), ip=self._callback_ip)) + self.logger.info( + "Plugin '{pluginname}': using local ip address {ip}".format(pluginname=self.get_shortname(), + ip=self._callback_ip)) else: - self.logger.info("Plugin '{pluginname}': using given ip address {ip}".format(pluginname=self.get_shortname(), ip=self._callback_ip)) + self.logger.info( + "Plugin '{pluginname}': using given ip address {ip}".format(pluginname=self.get_shortname(), + ip=self._callback_ip)) self._callback_url = "http://{ip}:{port}/".format(ip=self._callback_ip, port=self._callback_port) @@ -138,7 +154,8 @@ def parse_item(self, item): nuki_trigger = self.get_iattr_value(item.conf, "nuki_trigger") if nuki_trigger.lower() not in ['state', 'action', 'battery']: self.logger.warning("Plugin '{pluginname}': Item {item} defines an invalid Nuki trigger {trigger}! " - "It has to be 'state' or 'action'.".format(pluginname=self.get_shortname(), item=item, trigger=nuki_trigger)) + "It has to be 'state' or 'action'.".format(pluginname=self.get_shortname(), + item=item, trigger=nuki_trigger)) return if nuki_trigger.lower() == 'state': nuki_event_items[item] = int(nuki_id) @@ -148,7 +165,7 @@ def parse_item(self, item): nuki_battery_items[item] = int(nuki_id) else: self.logger.warning("Plugin '{pluginname}': Item {item} defines a Nuki ID but no nuki trigger! " - "This item has no effect.".format(pluginname=self.get_shortname(), item=item)) + "This item has no effect.".format(pluginname=self.get_shortname(), item=item)) return return self.update_item @@ -160,7 +177,9 @@ def update_item(self, item, caller=None, source=None, dest=None): if item in nuki_action_items: action = item() if action not in self._lockActions: - self.logger.warning("Plugin '{pluginname}': action {action} not in list of possible actions.".format(pluginname=self.get_shortname(), action=action)) + self.logger.warning( + "Plugin '{pluginname}': action {action} not in list of possible actions.".format( + pluginname=self.get_shortname(), action=action)) return response = self._api_call(self._base_url, nuki_id=nuki_action_items[item], endpoint='lockAction', @@ -199,7 +218,9 @@ def _get_paired_nukis(self): for nuki in response: paired_nukis.append(nuki['nukiId']) self.logger.info( - "Plugin '{pluginname}': Paired Nuki Lock found: {name} - {id}".format(pluginname=self.get_shortname(), name=nuki['name'], id=nuki['nukiId'])) + "Plugin '{pluginname}': Paired Nuki Lock found: {name} - {id}".format(pluginname=self.get_shortname(), + name=nuki['name'], + id=nuki['nukiId'])) self.logger.debug(paired_nukis) def _clear_callbacks(self): @@ -208,10 +229,12 @@ def _clear_callbacks(self): for c in callbacks['callbacks']: response = self._api_call(self._base_url, endpoint='callback/remove', token=self._token, id=c['id']) if response['success']: - self.logger.debug("Plugin '{pluginname}': Callback with id {id} removed.".format(pluginname=self.get_shortname(), id=c['id'])) + self.logger.debug( + "Plugin '{pluginname}': Callback with id {id} removed.".format(pluginname=self.get_shortname(), + id=c['id'])) return self.logger.debug("Plugin '{pluginname}': Could not remove callback with id {id}: {message}". - format(pluginname=self.get_shortname(), id=c['id'], message=c['message'])) + format(pluginname=self.get_shortname(), id=c['id'], message=c['message'])) def _register_callback(self): found = False @@ -226,20 +249,21 @@ def _register_callback(self): callback_url=self._callback_url) if not response['success']: self.logger.warning("Plugin '{pluginname}': Error establishing the callback url: {message}".format - (pluginname=self.get_shortname(), message=response['message'])) + (pluginname=self.get_shortname(), message=response['message'])) else: self.logger.info("Plugin '{}': Callback URL registered.".format - (self.get_shortname())) + (self.get_shortname())) else: self.logger.info("Plugin '{}': Callback URL already registered".format - (self.get_shortname())) + (self.get_shortname())) else: - self.logger.warning("Plugin '{}': No callback ip set. Automatic Nuki lock status updates not available.".format - (self.get_shortname())) + self.logger.warning( + "Plugin '{}': No callback ip set. Automatic Nuki lock status updates not available.".format + (self.get_shortname())) def _get_nuki_status(self): self.logger.info("Plugin '{}': Getting Nuki status ...".format - (self.get_shortname())) + (self.get_shortname())) for nuki_id in paired_nukis: response = self._api_call(self._base_url, endpoint='lockState', nuki_id=nuki_id, token=self._token, no_wait=self._noWait) @@ -323,13 +347,11 @@ def init_webinterface(self): return True + # ------------------------------------------ # Webinterface of the plugin # ------------------------------------------ -import cherrypy -from jinja2 import Environment, FileSystemLoader - class WebInterface(SmartPluginWebIf): def __init__(self, webif_dir, plugin): @@ -358,6 +380,20 @@ def index(self, reload=None): """ tmpl = self.tplenv.get_template('index.html') return tmpl.render(plugin_shortname=self.plugin.get_shortname(), plugin_version=self.plugin.get_version(), - interface=None, item_count=len(self.plugin.get_event_items())+len(self.plugin.get_action_items())+len(self.plugin.get_battery_items()), + interface=None, + item_count=len(self.plugin.get_event_items()) + len(self.plugin.get_action_items()) + len( + self.plugin.get_battery_items()), plugin_info=self.plugin.get_info(), tabcount=1, p=self.plugin) + + @cherrypy.expose + def triggerAction(self, path, value): + if path is None: + self.plugin.logger.error("Plugin '{}': Path parameter is missing when setting action item value!".format(self.get_shortname())) + return + if value is None: + self.plugin.logger.error("Plugin '{}': Value parameter is missing when setting action item value!".format(self.get_shortname())) + return + item = self.plugin.items.return_item(path) + item(int(value), caller=self.plugin.get_shortname(), source='triggerAction()') + return \ No newline at end of file diff --git a/nuki/webif/templates/index.html b/nuki/webif/templates/index.html index a5b7409f7..13c8deac8 100644 --- a/nuki/webif/templates/index.html +++ b/nuki/webif/templates/index.html @@ -105,13 +105,20 @@
{{ _('Nuki Action Items') }} ({{ p.get_action_items()|length }})
{{ item.type() }} {{ item._enforce_updates }} {{ value }} - {{ item() }} - {% if item() == 1 %}({{ _('unlock') }}){% endif %} - {% if item() == 2 %}({{ _('lock') }}){% endif %} - {% if item() == 3 %}({{ _('unlatch') }}){% endif %} - {% if item() == 4 %}({{ _('lockAndGo') }}){% endif %} - {% if item() == 5 %}({{ _('lockAndGoWithUnlatch') }}){% endif %} + +
+
+ + +
+
{{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} {{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }}{{ _('Wert') }} {{ _('Letztes Update') }} {{ _('Letzter Change') }}
{{ item.type() }} {{ item._enforce_updates }} {{ value }} -
-
- - -
-
-
{{ item() }}   {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} {{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }} +
+
+ +
+ +
+
+
+
{{ item.type() }} {{ item._enforce_updates }} {{ value }}{{ item() }}   + {{ item() }} + {% if item() == 0 %}({{ _('none') }}){% endif %} + {% if item() == 1 %}({{ _('unlock') }}){% endif %} + {% if item() == 2 %}({{ _('lock') }}){% endif %} + {% if item() == 3 %}({{ _('unlatch') }}){% endif %} + {% if item() == 4 %}({{ _('lockAndGo') }}){% endif %} + {% if item() == 5 %}({{ _('lockAndGoWithUnlatch') }}){% endif %} + {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} {{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }} From 81609698b7764fa4fd07d812c468ac1118063ef0 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 1 Nov 2018 19:34:37 +0100 Subject: [PATCH 371/705] Nuki: fix for exceptions when 503 is received as lock is currently switching to new state --- nuki/__init__.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/nuki/__init__.py b/nuki/__init__.py index 04baf665d..a8d762f37 100644 --- a/nuki/__init__.py +++ b/nuki/__init__.py @@ -241,21 +241,22 @@ def _register_callback(self): # Setting up the callback URL if self._callback_ip != "": callbacks = self._api_call(self._base_url, endpoint='callback/list', token=self._token) - for c in callbacks['callbacks']: - if c['url'] == self._callback_url: - found = True - if not found: - response = self._api_call(self._base_url, endpoint='callback/add', token=self._token, - callback_url=self._callback_url) - if not response['success']: - self.logger.warning("Plugin '{pluginname}': Error establishing the callback url: {message}".format - (pluginname=self.get_shortname(), message=response['message'])) + if callbacks is not None: + for c in callbacks['callbacks']: + if c['url'] == self._callback_url: + found = True + if not found: + response = self._api_call(self._base_url, endpoint='callback/add', token=self._token, + callback_url=self._callback_url) + if not response['success']: + self.logger.warning("Plugin '{pluginname}': Error establishing the callback url: {message}".format + (pluginname=self.get_shortname(), message=response['message'])) + else: + self.logger.info("Plugin '{}': Callback URL registered.".format + (self.get_shortname())) else: - self.logger.info("Plugin '{}': Callback URL registered.".format + self.logger.info("Plugin '{}': Callback URL already registered".format (self.get_shortname())) - else: - self.logger.info("Plugin '{}': Callback URL already registered".format - (self.get_shortname())) else: self.logger.warning( "Plugin '{}': No callback ip set. Automatic Nuki lock status updates not available.".format From 1744e849a7ab7f84906e89d23be5d84e12996a0a Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Thu, 1 Nov 2018 19:40:25 +0100 Subject: [PATCH 372/705] - updated logging object initialization - dropped reference to sh and include reference to plugins API - optmizied logging output --- rtr/__init__.py | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/rtr/__init__.py b/rtr/__init__.py index bf7ef6907..43b9a180b 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -27,10 +27,11 @@ # http://de.wikipedia.org/wiki/Regler#PI-Regler # http://www.honeywell.de/fp/regler/Reglerparametrierung.pdf -import logging -from lib.model.smartplugin import SmartPlugin import time +from lib.module import Modules +from lib.item import Items +from lib.model.smartplugin import * class RTR(SmartPlugin): """ @@ -58,11 +59,12 @@ def __init__(self, sh, default_Kp = 10, default_Ki = 15): :param sh: The instance of the smarthome object, save it for later references """ - self._sh = sh - # get a unique logger for the plugin and provide it internally - self.logger = logging.getLogger(__name__) - self.logger.debug("init method called") + from bin.smarthome import VERSION + if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': + self.logger = logging.getLogger(__name__) + + self.logger.debug("rtr: init method called") # preset the controller defaults self._default_Kp = default_Kp @@ -73,7 +75,9 @@ def __init__(self, sh, default_Kp = 10, default_Ki = 15): self._defaults['Kp'] = default_Kp self._defaults['Ki'] = default_Ki - self._sh.scheduler.add('rtr.scheduler', self.update_items, prio=5, cycle=int(self._cycle_time)) + self._items = Items.get_instance() + + return def run(self): """ @@ -81,6 +85,7 @@ def run(self): """ self.logger.debug("run method called") self.alive = True + self.scheduler_add('cycle', self.update_items, prio=5, cycle=int(self._cycle_time)) # if you want to create child threads, do not make them daemon = True! # They will not shutdown properly. (It's a python bug) @@ -271,21 +276,21 @@ def pi_controller(self, c): # calculate scanning time Ta = int(time.time()) - self._controller[c]['Tlast'] - self.logger.debug("rtr: {0} | Ta = Time() - Tlast | {1} = {2} - {3}" . format(c, Ta, (Ta + self._controller[c]['Tlast']), self._controller[c]['Tlast'])) + self.logger.debug("{0} | Ta = Time() - Tlast | {1} = {2} - {3}" . format(c, Ta, (Ta + self._controller[c]['Tlast']), self._controller[c]['Tlast'])) self._controller[c]['Tlast'] = int(time.time()) # get current and set point temp - w = self._sh.return_item(self._controller[c]['setpointItem'])() - x = self._sh.return_item(self._controller[c]['currentItem'])() + w = self._items.return_item(self._controller[c]['setpointItem'])() + x = self._items.return_item(self._controller[c]['currentItem'])() # skip execution if x is 0 if x == 0.00: - self.logger.debug("rtr: {0} | skip uninitiated x value (currently zero)" . format(c)) + self.logger.debug("{0} | skip uninitiated x value (currently zero)" . format(c)) return # calculate control error e = w - x - self.logger.debug("rtr: {0} | e = w - x | {1} = {2} - {3}" . format(c, e, w, x)) + self.logger.debug("{0} | e = w - x | {1} = {2} - {3}" . format(c, e, w, x)) Kp = 1.0 / self._controller[c]['Kp'] self._controller[c]['eSum'] = self._controller[c]['eSum'] + e * Ta @@ -302,7 +307,7 @@ def pi_controller(self, c): y = 0 self._controller[c]['eSum'] = 0 - self.logger.debug("rtr: {0} | eSum = {1}" . format(c, self._controller[c]['eSum'])) - self.logger.debug("rtr: {0} | y = {1}" . format(c, y)) + self.logger.debug("{0} | eSum = {1}" . format(c, self._controller[c]['eSum'])) + self.logger.debug("{0} | y = {1}" . format(c, y)) - self._sh.return_item(self._controller[c]['actuatorItem'])(y) + self._items.return_item(self._controller[c]['actuatorItem'])(y) From 88294e3da7c1a025e86801a6be46c7d8f833b93b Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Thu, 1 Nov 2018 21:46:01 +0100 Subject: [PATCH 373/705] added item attributes rtr_temp_default, rtr_temp_drop and rtr_temp_boost. with them it will be possible to set a boost temperature for special events or to set drop temperature for night or when nobody is at home --- rtr/__init__.py | 113 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 1 deletion(-) diff --git a/rtr/__init__.py b/rtr/__init__.py index 43b9a180b..d2519b4d7 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -28,9 +28,11 @@ # http://www.honeywell.de/fp/regler/Reglerparametrierung.pdf import time +import datetime from lib.module import Modules from lib.item import Items +from lib.shtime import Shtime from lib.model.smartplugin import * class RTR(SmartPlugin): @@ -51,6 +53,9 @@ class RTR(SmartPlugin): 'Kp' : 0, 'Ki' : 0, 'Tlast' : 0, + 'tempDefault' : 0, + 'tempDrop' : 0, + 'tempBoost' : 0, 'validated' : False} def __init__(self, sh, default_Kp = 10, default_Ki = 15): @@ -75,6 +80,8 @@ def __init__(self, sh, default_Kp = 10, default_Ki = 15): self._defaults['Kp'] = default_Kp self._defaults['Ki'] = default_Ki + self.path = sh.base_dir + '/var/rtr/' + self._items = Items.get_instance() return @@ -88,6 +95,7 @@ def run(self): self.scheduler_add('cycle', self.update_items, prio=5, cycle=int(self._cycle_time)) # if you want to create child threads, do not make them daemon = True! # They will not shutdown properly. (It's a python bug) + self._restoreTrigger() def stop(self): """ @@ -151,6 +159,15 @@ def parse_item(self, item): self._controller[c]['setpointItem'] = item.id() self.logger.info("rtr: bound item '{1}' to setpointItem for controller '{0}'". format(c, item.id())) + if self.has_iattr(item.conf, 'rtr_temp_default'): + self._controller[c]['tempDefault'] = int(item.conf['rtr_temp_default']) + + if self.has_iattr(item.conf, 'rtr_temp_drop'): + self._controller[c]['tempDrop'] = int(item.conf['rtr_temp_drop']) + + if self.has_iattr(item.conf, 'rtr_temp_boost'): + self._controller[c]['tempBoost'] = int(item.conf['rtr_temp_boost']) + if not self._controller[c]['validated']: self.validate_controller(c) @@ -235,7 +252,8 @@ def update_items(self): self.pi_controller(c) def validate_controller(self, c): - """ this function checks wether the needed parameters are set for a given controller + """ + this function checks wether the needed parameters are set for a given controller :param c: controller to be checked """ if self._controller[c]['setpointItem'] is None: @@ -311,3 +329,96 @@ def pi_controller(self, c): self.logger.debug("{0} | y = {1}" . format(c, y)) self._items.return_item(self._controller[c]['actuatorItem'])(y) + + def _restoreTrigger(self): + + self.logger.info("check if we need to restore triggers") + + if os.path.isdir(self.path): + for filename in os.listdir(self.path): + self.logger.info("need to restore '{}'" . format(filename)) + + try: + self.logger.debug("read file {}".format(filename)) + f = open(self.path + filename, "r") + ts = f.read() + f.close() + + except OSError as e: + self.logger.error("_restoreTrigger: cannot read '{}', error: {}" . format(self.path + filename, e.args)) + continue + + try: + ts = int(ts) + self.logger.debug("file content is {}" . format(ts)) + except ValueError: + self.logger.error("_restoreTrigger: file content '{}' is no timestamp" . format(ts)) + + name, c = filename.split('_') + self.logger.debug("controller is {}" . format(c)) + + self._createTrigger(filename, c, datetime.datetime.fromtimestamp(ts)) + + def _createTrigger(self, name, c, timer): + + self.logger.debug("_createTrigger called for name: '{}', controller: '{}', on '{}'" . format(name, c, timer)) + + self.scheduler_trigger(name, self.default, by='rtr', value={'c': c}, dt=timer) + + try: + if not os.path.isdir(self.path): + os.makedirs(self.path) + except OSError as e: + self.logger.error("_createTrigger: cannot create '{}', error: {}" . format(self.path, e.args)) + return + + try: + f = open(self.path + name, "w") + f.write(timer.strftime("%s")) + f.close() + except IOError as e: + self.logger.error("_createTrigger: I/O error({0}): {1}" . format(e.errno, e.strerror)) + + def default(self, c): + """ + this function changes setpoint to defined default temperature + :param c: controller to be used + """ + if c in self._controller: + if self._controller[c]['tempDefault'] > 0: + self._sh.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempDefault']) + + try: + if os.path.isfile(self.path + 'boost_' + c): + os.remove(self.path + 'boost_' + c) + except IOError as e: + self.logger.error("default: I/O error({0}): {1}" . format(e.errno, e.strerror)) + + if self.scheduler_get('boost_' + c) is not None: + self.scheduler_remove('boost_' + c) + + else: + self.logger.error("boost unknown controller '{}'" . format(self._controller.keys())) + + def boost(self, c): + """ + this function changes setpoint to defined boost temperature + :param c: controller to be used + """ + if c in self._controller: + if self._controller[c]['tempBoost'] > 0: + self._sh.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempBoost']) + shtime = Shtime.get_instance() + self._createTrigger('boost_' + c, c, shtime.now() + datetime.timedelta(minutes=5)) + else: + self.logger.error("boost unknown controller '{}'" . format(self._controller.keys())) + + def drop(self, c): + """ this function changes setpoint to defined drop temperature + :param c: controller to be used + """ + if c in self._controller: + if self._controller[c]['tempDrop'] > 0: + self._sh.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempDrop']) + else: + self.logger.error("drop unknown controller '{}'" . format(self._controller.keys())) From 5e71041bdbfb15e4684b6069bbfd7aa327b6210e Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Thu, 1 Nov 2018 22:22:50 +0100 Subject: [PATCH 374/705] changed self._sh.return_item to self._items.return_item --- rtr/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rtr/__init__.py b/rtr/__init__.py index d2519b4d7..89bd9befd 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -386,7 +386,7 @@ def default(self, c): """ if c in self._controller: if self._controller[c]['tempDefault'] > 0: - self._sh.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempDefault']) + self._items.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempDefault']) try: if os.path.isfile(self.path + 'boost_' + c): @@ -407,7 +407,7 @@ def boost(self, c): """ if c in self._controller: if self._controller[c]['tempBoost'] > 0: - self._sh.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempBoost']) + self._items.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempBoost']) shtime = Shtime.get_instance() self._createTrigger('boost_' + c, c, shtime.now() + datetime.timedelta(minutes=5)) else: @@ -419,6 +419,6 @@ def drop(self, c): """ if c in self._controller: if self._controller[c]['tempDrop'] > 0: - self._sh.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempDrop']) + self._items.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempDrop']) else: self.logger.error("drop unknown controller '{}'" . format(self._controller.keys())) From f9844be2a71694336a6cd5cb28e8b7e562d350fa Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Fri, 2 Nov 2018 00:03:42 +0100 Subject: [PATCH 375/705] Some improvements - updated plugin.yaml and changed the way to pass vars to the contructor - updated some function descriptions - included suggested change to call code from run() https://github.com/smarthomeNG/smarthome/issues/224#issuecomment-435196341 --- rtr/__init__.py | 44 ++++++++++++++++++++------------- rtr/plugin.yaml | 66 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 87 insertions(+), 23 deletions(-) diff --git a/rtr/__init__.py b/rtr/__init__.py index 89bd9befd..7de3b3a1c 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -58,11 +58,9 @@ class RTR(SmartPlugin): 'tempBoost' : 0, 'validated' : False} - def __init__(self, sh, default_Kp = 10, default_Ki = 15): + def __init__(self, sh, *args, **kwargs): """ Initalizes the plugin. The parameters describe for this method are pulled from the entry in plugin.conf. - - :param sh: The instance of the smarthome object, save it for later references """ from bin.smarthome import VERSION @@ -72,14 +70,15 @@ def __init__(self, sh, default_Kp = 10, default_Ki = 15): self.logger.debug("rtr: init method called") # preset the controller defaults - self._default_Kp = default_Kp - self._default_Ki = default_Ki + self._default_Kp = self.get_parameter_value('default_Kp') + self._default_Ki = self.get_parameter_value('default_Ki') self._cycle_time = 1*60 self._defaults['Tlast'] = time.time() - self._defaults['Kp'] = default_Kp - self._defaults['Ki'] = default_Ki + self._defaults['Kp'] = self.get_parameter_value('default_Kp') + self._defaults['Ki'] = self.get_parameter_value('default_Ki') + sh = self.get_sh() self.path = sh.base_dir + '/var/rtr/' self._items = Items.get_instance() @@ -93,9 +92,13 @@ def run(self): self.logger.debug("run method called") self.alive = True self.scheduler_add('cycle', self.update_items, prio=5, cycle=int(self._cycle_time)) - # if you want to create child threads, do not make them daemon = True! - # They will not shutdown properly. (It's a python bug) - self._restoreTrigger() + + try: + self._restoreTrigger() + except Exception as e: + self.logger.error("Error in 'self._restoreTrigger()': {}".format(e)) + + return def stop(self): """ @@ -107,7 +110,6 @@ def stop(self): def parse_item(self, item): """ Default plugin parse_item method. Is called when the plugin is initialized. - :param item: The item to process. """ if self.has_iattr(item.conf, 'rtr_current'): @@ -331,7 +333,9 @@ def pi_controller(self, c): self._items.return_item(self._controller[c]['actuatorItem'])(y) def _restoreTrigger(self): - + """ + scans folder for saved triggers to restore them at startup + """ self.logger.info("check if we need to restore triggers") if os.path.isdir(self.path): @@ -360,7 +364,12 @@ def _restoreTrigger(self): self._createTrigger(filename, c, datetime.datetime.fromtimestamp(ts)) def _createTrigger(self, name, c, timer): - + """ + this function changes setpoint to defined default temperature + :param name: name of the trigger + :param c: controller to be used + :param timer: datetime value for the trigger + """ self.logger.debug("_createTrigger called for name: '{}', controller: '{}', on '{}'" . format(name, c, timer)) self.scheduler_trigger(name, self.default, by='rtr', value={'c': c}, dt=timer) @@ -381,7 +390,7 @@ def _createTrigger(self, name, c, timer): def default(self, c): """ - this function changes setpoint to defined default temperature + this function changes setpoint of the given controller to defined default temperature :param c: controller to be used """ if c in self._controller: @@ -402,19 +411,20 @@ def default(self, c): def boost(self, c): """ - this function changes setpoint to defined boost temperature + this function changes setpoint of the given controller to defined boost temperature :param c: controller to be used """ if c in self._controller: if self._controller[c]['tempBoost'] > 0: self._items.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempBoost']) shtime = Shtime.get_instance() - self._createTrigger('boost_' + c, c, shtime.now() + datetime.timedelta(minutes=5)) + self._createTrigger('boost_' + c, c, shtime.now() + datetime.timedelta(minutes=1)) else: self.logger.error("boost unknown controller '{}'" . format(self._controller.keys())) def drop(self, c): - """ this function changes setpoint to defined drop temperature + """ + this function changes setpoint of the given controller to defined drop temperature :param c: controller to be used """ if c in self._controller: diff --git a/rtr/plugin.yaml b/rtr/plugin.yaml index 125b56f8c..800896540 100755 --- a/rtr/plugin.yaml +++ b/rtr/plugin.yaml @@ -1,10 +1,9 @@ # Metadata for the Smart-Plugin plugin: - # Global plugin attributes type: system # plugin type (gateway, interface, protocol, system, web) description: # Alternative: description in multiple languages de: 'Raum Temperatur Regler' - en: '' + en: 'Room Temperatur controller' maintainer: Thomas Creutz / bmxp version: 1.2.3 # Plugin version @@ -13,8 +12,63 @@ plugin: classname: RTR # class containing the plugin parameters: - # Definition of parameters to be configured in etc/plugin.yaml - + default_Kp: + type: int + default: 10 + description: + de: 'Standard Verstärkungsfaktor für erstellte Items' + en: 'default proportional gain for created items' + + default_Ki: + type: int + default: 15 + description: + de: 'Standard Integralfaktor für erstellte Items' + en: 'default integral gain for created items' + item_attributes: - # Definition of item attributes defined by this plugin - + rtr_current: + type: int + description: + de: 'Ordnet das Item dem Controller mit gegebener ID als Ist-Wert zu' + en: 'Defines the Item as current value for the given controller ID' + rtr_Kp: + type: int + description: + de: 'Ordnet dem Item einen vom Standard abweichenden Verstärkungsfaktor zu. Muss auf dem selben Item wie rtr_current gesetzt werden' + en: 'Defines a different proportional gain for the controller. Only valid in the same Item where rtr_current is defined' + rtr_Ki: + type: int + description: + de: 'Ordnet dem Item einen vom Standard abweichenden Integralfaktor zu. Muss auf dem selben Item wie rtr_current gesetzt werden' + en: 'Defines a different integral gain for the controller. Only valid in the same Item where rtr_current is defined' + rtr_setpoint: + type: int + description: + de: 'Ordnet das Item dem Controller mit gegebener ID als Soll-Wert zu' + en: 'Defines the Item as setpoint value for the given controller ID' + rtr_temp_default: + type: int + description: + de: 'Ordnet dem Item eine Standard Temperatur zu, auf die rtr_setpoint zurück gesetzt wird. Muss auf dem selben Item wie rtr_setpoint gesetzt werden' + en: 'Defines a default temperature for rtr_setpoint. Only valid in the same Item where rtr_setpoint is defined' + rtr_temp_drop: + type: int + description: + de: 'Ordnet dem Item eine Absenk-Temperatur zu, auf die rtr_setpoint beim aufruf der Funktion drop gesetzt wird. Muss auf dem selben Item wie rtr_setpoint gesetzt werden' + en: 'Defines a drop temperature for rtr_setpoint, which is set by calling the drop function. Only valid in the same Item where rtr_setpoint is defined' + rtr_temp_boost: + type: int + description: + de: 'Ordnet dem Item eine Boost-Temperatur zu, auf die rtr_setpoint beim aufruf der Funktion boost gesetzt wird. Muss auf dem selben Item wie rtr_setpoint gesetzt werden' + en: 'Defines a boost temperature for rtr_setpoint, which is set by calling the boost function. Only valid in the same Item where rtr_setpoint is defined' + rtr_actuator: + type: int + description: + de: 'Ordnet das Item dem Controller mit gegebener ID als Stellgröße zu' + en: 'Defines the Item as actuator value for the given controller ID' + rtr_stop: + type: int + description: + de: 'Ordnet das Item dem Controller mit gegebener ID als Stop-Objekt zu. Kann nur auf einem Item vom Typ Bool gesetzt werden. Ist der Item Wert True, Pausiert die Regelung.' + en: 'Defines the Item as stop item for the given controller ID. Only valid on Item-Type Bool. If Item is True, the controller gets paused' From ee3c8bdedf7de89e80330bc4f265bb7190dd138e Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Fri, 2 Nov 2018 00:18:22 +0100 Subject: [PATCH 376/705] removed duplicate default values --- rtr/__init__.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/rtr/__init__.py b/rtr/__init__.py index 7de3b3a1c..527b7f608 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -70,8 +70,6 @@ def __init__(self, sh, *args, **kwargs): self.logger.debug("rtr: init method called") # preset the controller defaults - self._default_Kp = self.get_parameter_value('default_Kp') - self._default_Ki = self.get_parameter_value('default_Ki') self._cycle_time = 1*60 self._defaults['Tlast'] = time.time() @@ -128,14 +126,12 @@ def parse_item(self, item): self.logger.info("rtr: bound item '{1}' to currentItem for controller '{0}'". format(c, item.id())) if not self.has_iattr(item.conf, 'rtr_Kp'): - self.logger.info("rtr: missing rtr_Kp in item {0}, setting to default: {1}" . format(item.id(), self._default_Kp)) - self._controller[c]['Kp'] = self._default_Kp + self.logger.info("rtr: missing rtr_Kp in item {0}, setting to default: {1}" . format(item.id(), self._controller[c]['Kp'])) else: self._controller[c]['Kp'] = float(item.conf['rtr_Kp']) if not self.has_iattr(item.conf, 'rtr_Ki'): - self.logger.info("rtr: missing rtr_Ki in item {0}, setting to default: {1}" . format(item.id(), self._default_Ki)) - self._controller[c]['Ki'] = self._default_Ki + self.logger.info("rtr: missing rtr_Ki in item {0}, setting to default: {1}" . format(item.id(), self._controller[c]['Ki'])) else: self._controller[c]['Ki'] = float(item.conf['rtr_Ki']) From 826dcf2376dd008a9856952edd2926de4ebda08f Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Fri, 2 Nov 2018 00:48:54 +0100 Subject: [PATCH 377/705] replaced rtr_stop with rtr_stops now it is possible to have not only one controller bound to a stop item so that as example one open window can also stop more than only one heater --- rtr/__init__.py | 89 +++++++++++++++++++++++++++++++------------------ rtr/plugin.yaml | 8 ++--- 2 files changed, 60 insertions(+), 37 deletions(-) diff --git a/rtr/__init__.py b/rtr/__init__.py index 527b7f608..24690c59d 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -61,26 +61,27 @@ class RTR(SmartPlugin): def __init__(self, sh, *args, **kwargs): """ Initalizes the plugin. The parameters describe for this method are pulled from the entry in plugin.conf. - """ + :param sh: **Deprecated**: The instance of the smarthome object. For SmartHomeNG versions 1.4 and up: **Don't use it**! + :param *args: **Deprecated**: Old way of passing parameter values. For SmartHomeNG versions 1.4 and up: **Don't use it**! + :param **kwargs:**Deprecated**: Old way of passing parameter values. For SmartHomeNG versions 1.4 and up: **Don't use it**! + """ from bin.smarthome import VERSION if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': self.logger = logging.getLogger(__name__) self.logger.debug("rtr: init method called") + sh = self.get_sh() + self.path = sh.base_dir + '/var/rtr/' + self._items = Items.get_instance() + # preset the controller defaults self._cycle_time = 1*60 - self._defaults['Tlast'] = time.time() self._defaults['Kp'] = self.get_parameter_value('default_Kp') self._defaults['Ki'] = self.get_parameter_value('default_Ki') - sh = self.get_sh() - self.path = sh.base_dir + '/var/rtr/' - - self._items = Items.get_instance() - return def run(self): @@ -193,29 +194,52 @@ def parse_item(self, item): return if self.has_iattr(item.conf, 'rtr_stop'): - if not item.conf['rtr_stop'].isdigit(): - self.logger.error("rtr: error in item {0}, rtr_stop need to be the controller number" . format(item.id())) - return - # validate this optional Item - if item._type is not 'bool': - self.logger.error("rtr: error in item {0}, rtr_stop Item need to be bool" . format(item.id())) + if item._type != 'bool': + logger.error("rtr: error in {0}, rtr_stops Item need to be bool (current {1})" . format(item.id(), item._type)) return - c = 'c' + item.conf['rtr_stop'] + logger.debug("rtr: parse item {0}, found rtr_stops={1}" . format(item.id(), item.conf['rtr_stops'])) - # init controller with defaults when it not exist - if c not in self._controller: - self.logger.debug("rtr: controller '{0}' does not exist yet. Init with default values" . format(c)) - self._controller[c] = self._defaults.copy() + cList = item.conf['rtr_stops'] + if isinstance(cList, str): + cList = [cList, ] + + for cNum in cList: + + # validate controller number + if not cNum.isdigit(): + logger.error("rtr: error in {0}, rtr_stops need to be the controller number(s) - skip {1}" . format(item.id(), cNum)) + continue + + c = 'c' + cNum + + # init controller with defaults when it not exist + if c not in self._controller: + self._controller[c] = self._defaults.copy() + logger.debug("rtr: create controller {0} for {1}" . format(c, item.id())) + + # store stopItems into controller + if self._controller[c]['stopItems'] is None: + self._controller[c]['stopItems'] = [] + self._controller[c]['stopItems'].append(item) + + # listen to item events + item.add_method_trigger(self.stop_Controller) + + logger.debug("rtr: parse item {0}, controller {1} stop items: {2} " . format(item.id(), c, self._controller[c]['stopItems'])) - # store stopItems into controller - if self._controller[c]['stopItems'] is None: - self._controller[c]['stopItems'] = [] - self._controller[c]['stopItems'].append(item) - self.logger.info("rtr: add item '{1}' to stopItems for controller '{0}'". format(c, item.id())) return + def stop_Controller(self, item, caller=None, source=None, dest=None): + for c in self._controller.keys(): + if self._controller[c]['stopItems'] is not None and len(self._controller[c]['stopItems']) > 0: + for item in self._controller[c]['stopItems']: + if item(): + if self._controller[c]['actuatorItem']() > 0: + logger.info("rtr: controller {0} stopped, because of item {1}" . format(c, item.id())) + self._controller[c]['actuatorItem'](0) + def update_item(self, item, caller=None, source=None, dest=None): """ write item's values @@ -231,22 +255,12 @@ def update_item(self, item, caller=None, source=None, dest=None): if 'rtr_setpoint' in item.conf or 'rtr_current' in item.conf: c = 'c' + item.conf['rtr_setpoint'] if self._controller[c]['validated']: - if self._controller[c]['stopItems'] is not None and len(self._controller[c]['stopItems']) > 0: - for item in self._controller[c]['stopItems']: - if item(): - return - self.pi_controller(c) def update_items(self): """ this is the callback function for the scheduler """ for c in self._controller.keys(): if self._controller[c]['validated']: - if self._controller[c]['stopItems'] is not None and len(self._controller[c]['stopItems']) > 0: - for item in self._controller[c]['stopItems']: - if item(): - return - self.pi_controller(c) def validate_controller(self, c): @@ -290,6 +304,15 @@ def pi_controller(self, c): :param c: controller for the calculation """ + # check if controller is currently deactivated + if self._controller[c]['stopItems'] is not None and len(self._controller[c]['stopItems']) > 0: + for item in self._controller[c]['stopItems']: + if item(): + if self._controller[c]['actuatorItem']() > 0: + logger.info("rtr: controller {0} currently deactivated, because of item {1}" . format(c, item.id())) + self._controller[c]['actuatorItem'](0) + return + # calculate scanning time Ta = int(time.time()) - self._controller[c]['Tlast'] self.logger.debug("{0} | Ta = Time() - Tlast | {1} = {2} - {3}" . format(c, Ta, (Ta + self._controller[c]['Tlast']), self._controller[c]['Tlast'])) diff --git a/rtr/plugin.yaml b/rtr/plugin.yaml index 800896540..206eeecf7 100755 --- a/rtr/plugin.yaml +++ b/rtr/plugin.yaml @@ -67,8 +67,8 @@ item_attributes: description: de: 'Ordnet das Item dem Controller mit gegebener ID als Stellgröße zu' en: 'Defines the Item as actuator value for the given controller ID' - rtr_stop: - type: int + rtr_stops: + type: list(int) description: - de: 'Ordnet das Item dem Controller mit gegebener ID als Stop-Objekt zu. Kann nur auf einem Item vom Typ Bool gesetzt werden. Ist der Item Wert True, Pausiert die Regelung.' - en: 'Defines the Item as stop item for the given controller ID. Only valid on Item-Type Bool. If Item is True, the controller gets paused' + de: 'Ordnet das Item dem einen oder mehreren Controllern per ID als Stop-Objekt zu. Kann nur auf einem Item vom Typ Bool gesetzt werden. Ist der Item Wert True, Pausiert die Regelung.' + en: 'Defines the Item as stop item for the given controller IDs. Only valid on Item-Type Bool. If Item is True, the controller gets paused' From c293a8a066acbd17d5e9dd201a8e5fe98638ec63 Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Fri, 2 Nov 2018 00:59:37 +0100 Subject: [PATCH 378/705] some fixes to rtr_stops --- rtr/__init__.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/rtr/__init__.py b/rtr/__init__.py index 24690c59d..a32850a44 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -194,12 +194,16 @@ def parse_item(self, item): return if self.has_iattr(item.conf, 'rtr_stop'): + self.logger.error("rtr: parse item {0}, found rtr_stop which is not supported anymore - use rtr_stops instead" . format(item.id(), item.conf['rtr_stops'])) + return + + if self.has_iattr(item.conf, 'rtr_stops'): # validate this optional Item - if item._type != 'bool': - logger.error("rtr: error in {0}, rtr_stops Item need to be bool (current {1})" . format(item.id(), item._type)) + if item._type is not 'bool': + self.logger.error("rtr: error in item {0}, rtr_stops Item need to be bool (current {1})" . format(item.id(), item._type)) return - logger.debug("rtr: parse item {0}, found rtr_stops={1}" . format(item.id(), item.conf['rtr_stops'])) + self.logger.debug("rtr: parse item {0}, found rtr_stops={1}" . format(item.id(), item.conf['rtr_stops'])) cList = item.conf['rtr_stops'] if isinstance(cList, str): @@ -227,7 +231,7 @@ def parse_item(self, item): # listen to item events item.add_method_trigger(self.stop_Controller) - logger.debug("rtr: parse item {0}, controller {1} stop items: {2} " . format(item.id(), c, self._controller[c]['stopItems'])) + self.logger.debug("rtr: parse item {0}, controller {1} stop items: {2} " . format(item.id(), c, self._controller[c]['stopItems'])) return From 3d54106cb8ced8fda1f9a8e7735805448cb08ef8 Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Fri, 2 Nov 2018 01:01:52 +0100 Subject: [PATCH 379/705] again code cleanup for rtr_stop --- rtr/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtr/__init__.py b/rtr/__init__.py index a32850a44..01becfe8c 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -194,7 +194,7 @@ def parse_item(self, item): return if self.has_iattr(item.conf, 'rtr_stop'): - self.logger.error("rtr: parse item {0}, found rtr_stop which is not supported anymore - use rtr_stops instead" . format(item.id(), item.conf['rtr_stops'])) + self.logger.error("rtr: parse item {0}, found rtr_stop which is not supported anymore - use rtr_stops instead") return if self.has_iattr(item.conf, 'rtr_stops'): From e221e66635d44780fdc1630d76ceeec81f991c27 Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Fri, 2 Nov 2018 01:09:44 +0100 Subject: [PATCH 380/705] with item._type != 'bool' it works better :) --- rtr/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rtr/__init__.py b/rtr/__init__.py index 01becfe8c..5a6740bbb 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -199,7 +199,7 @@ def parse_item(self, item): if self.has_iattr(item.conf, 'rtr_stops'): # validate this optional Item - if item._type is not 'bool': + if item._type != 'bool': self.logger.error("rtr: error in item {0}, rtr_stops Item need to be bool (current {1})" . format(item.id(), item._type)) return From 5c0c90a8f7ed1059a74ce8cd021ee69eb1202ffe Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Fri, 2 Nov 2018 01:42:59 +0100 Subject: [PATCH 381/705] found again a two bugs --- rtr/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rtr/__init__.py b/rtr/__init__.py index 5a6740bbb..983d8d5f3 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -213,7 +213,7 @@ def parse_item(self, item): # validate controller number if not cNum.isdigit(): - logger.error("rtr: error in {0}, rtr_stops need to be the controller number(s) - skip {1}" . format(item.id(), cNum)) + self.logger.error("rtr: error in {0}, rtr_stops need to be the controller number(s) - skip {1}" . format(item.id(), cNum)) continue c = 'c' + cNum @@ -221,7 +221,7 @@ def parse_item(self, item): # init controller with defaults when it not exist if c not in self._controller: self._controller[c] = self._defaults.copy() - logger.debug("rtr: create controller {0} for {1}" . format(c, item.id())) + self.logger.debug("rtr: create controller {0} for {1}" . format(c, item.id())) # store stopItems into controller if self._controller[c]['stopItems'] is None: From bcef871daa3a4d858d54b78f9dafe55c683a2b58 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 2 Nov 2018 07:23:25 +0100 Subject: [PATCH 382/705] OpenWeatherMap: small bugfixes --- openweathermap/README.md | 2 -- openweathermap/__init__.py | 18 ++++++++++++------ openweathermap/plugin.yaml | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/openweathermap/README.md b/openweathermap/README.md index bb7359a60..8fd32fae8 100644 --- a/openweathermap/README.md +++ b/openweathermap/README.md @@ -1,7 +1,5 @@ # OpenWeatherMap -#### Version 1.5.0.1 - This plugins can be used retrieve weather information from OpenWeatherMap (https://openweathermap.org/). ## Support diff --git a/openweathermap/__init__.py b/openweathermap/__init__.py index 0a9011625..a5cae79f9 100644 --- a/openweathermap/__init__.py +++ b/openweathermap/__init__.py @@ -28,10 +28,11 @@ import json from lib.module import Modules from lib.model.smartplugin import * +from bin.smarthome import VERSION class OpenWeatherMap(SmartPlugin): - PLUGIN_VERSION = "1.5.0.1" + PLUGIN_VERSION = "1.5.0.2" _base_url = 'https://api.openweathermap.org/%s' _base_img_url = 'https://tile.openweathermap.org/map/%s/%s/%s/%s.png?appid=%s' @@ -40,7 +41,8 @@ def __init__(self, sh, *args, **kwargs): """ Initializes the plugin """ - self.logger = logging.getLogger(__name__) + if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': + self.logger = logging.getLogger(__name__) self._key = self.get_parameter_value('key') if self.get_parameter_value('latitude') != '' and self.get_parameter_value('longitude') != '': self._lat = self.get_parameter_value('latitude') @@ -56,8 +58,7 @@ def __init__(self, sh, *args, **kwargs): self._cycle = int(self.get_parameter_value('cycle')) self._items = {} - if not self.init_webinterface(): - self._init_complete = False + self.init_webinterface() def run(self): self.scheduler_add(__name__, self._update_loop, prio=5, cycle=self._cycle, offset=2) @@ -160,7 +161,12 @@ def get_uv(self): self.logger.error( "get_uv: Exception when sending GET request for get_uv: %s" % str(e)) return - json_obj = response.json() + try: + json_obj = response.json() + except Exception as e: + self.logger.error( + "get_uv: Exception when decoding json data: %s" % str(e)) + return return json_obj def parse_item(self, item): @@ -286,7 +292,7 @@ def __init__(self, webif_dir, plugin): :type webif_dir: str :type plugin: object """ - self.logger = logging.getLogger(__name__) + self.logger = self.plugin.logger self.webif_dir = webif_dir self.plugin = plugin self.tplenv = self.init_template_environment() diff --git a/openweathermap/plugin.yaml b/openweathermap/plugin.yaml index fc4471757..a4f543b44 100644 --- a/openweathermap/plugin.yaml +++ b/openweathermap/plugin.yaml @@ -12,7 +12,7 @@ plugin: documentation: '' support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/1246998-support-thread-zum-openweathermap-plugin' keywords: weather - version: 1.5.0.1 # Plugin version + version: 1.5.0.2 # Plugin version sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance From 7b52a1e1f460cea0ab135f3e962f1706e5a6b4bf Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 2 Nov 2018 07:27:16 +0100 Subject: [PATCH 383/705] OpenWeatherMap: logger init after plugin is set --- openweathermap/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openweathermap/__init__.py b/openweathermap/__init__.py index a5cae79f9..b0e97780a 100644 --- a/openweathermap/__init__.py +++ b/openweathermap/__init__.py @@ -292,9 +292,9 @@ def __init__(self, webif_dir, plugin): :type webif_dir: str :type plugin: object """ - self.logger = self.plugin.logger self.webif_dir = webif_dir self.plugin = plugin + self.logger = self.plugin.logger self.tplenv = self.init_template_environment() @cherrypy.expose From cf4df823a6ca555b4e3abb7df494bc4ee2a8d3c5 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 2 Nov 2018 07:55:07 +0100 Subject: [PATCH 384/705] AVM: changed item name from trigger to trigger1, as trigger causes problems with DEV core! --- avm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/README.md b/avm/README.md index 0b0756147..cdd9e3180 100644 --- a/avm/README.md +++ b/avm/README.md @@ -132,7 +132,7 @@ avm: monitor: - trigger: + trigger1: type: bool avm_data_type@fritzbox_7490: monitor_trigger avm_incoming_allowed: xxxxxxxx From 182857ac3451cb62babe684a6e7917f1efc3159e Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 2 Nov 2018 08:18:07 +0100 Subject: [PATCH 385/705] Traffic: corrected logics example --- traffic/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/traffic/README.md b/traffic/README.md index 2e58204b5..b5d092861 100644 --- a/traffic/README.md +++ b/traffic/README.md @@ -95,7 +95,7 @@ route = sh.traffic.get_route_info(sh._lat+','+sh._lon, 'Berlin', False, 'now', ' if route['summary'] is not '': route['summary'] += ": " -summary = route['summary']+"%.1f km in %.0f min" % (round(route['duration_in_traffic']/60,2), round(route['distance']/1000,2)) +summary = route['summary'] + ": %.1f km in %.0f min" % (round(route['distance'] / 1000, 2), round(route['duration_in_traffic'] / 60, 2)) sh.travel_info.travel_time(route['duration']) sh.travel_info.travel_time.in_traffic(route['duration_in_traffic']) sh.travel_info.travel_distance(route['distance']) From 0abbd7416996351362565c70a523a8759e230e20 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 2 Nov 2018 08:20:09 +0100 Subject: [PATCH 386/705] Traffic: added blog links to readme --- traffic/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/traffic/README.md b/traffic/README.md index b5d092861..c8aa99d42 100644 --- a/traffic/README.md +++ b/traffic/README.md @@ -8,6 +8,10 @@ Forum thread to the plugin: https://knx-user-forum.de/forum/supportforen/smartho Take care not to request the interface too often as there currently is only a limit of 2500 free requests / day. More information and API key see: https://developers.google.com/maps/documentation/directions/intro?hl=de#traffic-model +Blog article to the plugin: +https://www.smarthomeng.de/das-traffic-plugin-am-beispiel-eines-staualarms +https://www.smarthomeng.de/geozonen-basierte-services-mit-der-egigeozone-app-und-dem-network-plugin +https://www.smarthomeng.de/google-maps-widget-fuer-smartvisu-2-9 ## Requirements From 5a606f173f3262b81797e2c642b1cfa935940c39 Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Fri, 2 Nov 2018 09:28:40 +0100 Subject: [PATCH 387/705] Some fixed bugs and improvements - changed trigger to scheduler - fixed some other bugs in stop_items handling - added default caller, source, dest params for the scheduler - added some TODO remerks --- rtr/__init__.py | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/rtr/__init__.py b/rtr/__init__.py index 983d8d5f3..5231d9b5a 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -312,9 +312,9 @@ def pi_controller(self, c): if self._controller[c]['stopItems'] is not None and len(self._controller[c]['stopItems']) > 0: for item in self._controller[c]['stopItems']: if item(): - if self._controller[c]['actuatorItem']() > 0: - logger.info("rtr: controller {0} currently deactivated, because of item {1}" . format(c, item.id())) - self._controller[c]['actuatorItem'](0) + if self._items.return_item(self._controller[c]['actuatorItem'])() > 0: + self.logger.info("rtr: controller {0} currently deactivated, because of item {1}" . format(c, item.id())) + self._items.return_item(self._controller[c]['actuatorItem'])(0) return # calculate scanning time @@ -384,8 +384,10 @@ def _restoreTrigger(self): name, c = filename.split('_') self.logger.debug("controller is {}" . format(c)) + # TODO: if trigger ts <= time(), run it and not recreate?! self._createTrigger(filename, c, datetime.datetime.fromtimestamp(ts)) + # TODO: rename Trigger -> Timer?! def _createTrigger(self, name, c, timer): """ this function changes setpoint to defined default temperature @@ -395,7 +397,16 @@ def _createTrigger(self, name, c, timer): """ self.logger.debug("_createTrigger called for name: '{}', controller: '{}', on '{}'" . format(name, c, timer)) - self.scheduler_trigger(name, self.default, by='rtr', value={'c': c}, dt=timer) + #self.scheduler_trigger(name, self.default, by='rtr', value={'c': c}, dt=timer) + + #next = shtime.now() + datetime.timedelta(seconds=time) + try: + if self.scheduler_get(name) is not None: + self.scheduler_remove(name) + + self.scheduler_add(name, self.default, value={'c': c}, next=timer) + except Exception as e: + self.logger.error("Error in '_createTrigger()': {}".format(e)) try: if not os.path.isdir(self.path): @@ -411,7 +422,7 @@ def _createTrigger(self, name, c, timer): except IOError as e: self.logger.error("_createTrigger: I/O error({0}): {1}" . format(e.errno, e.strerror)) - def default(self, c): + def default(self, c, caller=None, source=None, dest=None): """ this function changes setpoint of the given controller to defined default temperature :param c: controller to be used @@ -426,8 +437,11 @@ def default(self, c): except IOError as e: self.logger.error("default: I/O error({0}): {1}" . format(e.errno, e.strerror)) - if self.scheduler_get('boost_' + c) is not None: - self.scheduler_remove('boost_' + c) + try: + if self.scheduler_get('boost_' + c) is not None: + self.scheduler_remove('boost_' + c) + except Exception as e: + self.logger.error("Error in '_createTrigger()': {}".format(e)) else: self.logger.error("boost unknown controller '{}'" . format(self._controller.keys())) @@ -442,6 +456,7 @@ def boost(self, c): self._items.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempBoost']) shtime = Shtime.get_instance() self._createTrigger('boost_' + c, c, shtime.now() + datetime.timedelta(minutes=1)) + else: self.logger.error("boost unknown controller '{}'" . format(self._controller.keys())) From e30bd23775a15886a85f1cb5e503663833f090b5 Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Fri, 2 Nov 2018 17:21:13 +0100 Subject: [PATCH 388/705] change datatype from init to float for temperatures --- rtr/__init__.py | 6 +++--- rtr/plugin.yaml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/rtr/__init__.py b/rtr/__init__.py index 5231d9b5a..78ad32f06 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -159,13 +159,13 @@ def parse_item(self, item): self.logger.info("rtr: bound item '{1}' to setpointItem for controller '{0}'". format(c, item.id())) if self.has_iattr(item.conf, 'rtr_temp_default'): - self._controller[c]['tempDefault'] = int(item.conf['rtr_temp_default']) + self._controller[c]['tempDefault'] = float(item.conf['rtr_temp_default']) if self.has_iattr(item.conf, 'rtr_temp_drop'): - self._controller[c]['tempDrop'] = int(item.conf['rtr_temp_drop']) + self._controller[c]['tempDrop'] = float(item.conf['rtr_temp_drop']) if self.has_iattr(item.conf, 'rtr_temp_boost'): - self._controller[c]['tempBoost'] = int(item.conf['rtr_temp_boost']) + self._controller[c]['tempBoost'] = float(item.conf['rtr_temp_boost']) if not self._controller[c]['validated']: self.validate_controller(c) diff --git a/rtr/plugin.yaml b/rtr/plugin.yaml index 206eeecf7..94aaa0027 100755 --- a/rtr/plugin.yaml +++ b/rtr/plugin.yaml @@ -48,17 +48,17 @@ item_attributes: de: 'Ordnet das Item dem Controller mit gegebener ID als Soll-Wert zu' en: 'Defines the Item as setpoint value for the given controller ID' rtr_temp_default: - type: int + type: float description: de: 'Ordnet dem Item eine Standard Temperatur zu, auf die rtr_setpoint zurück gesetzt wird. Muss auf dem selben Item wie rtr_setpoint gesetzt werden' en: 'Defines a default temperature for rtr_setpoint. Only valid in the same Item where rtr_setpoint is defined' rtr_temp_drop: - type: int + type: float description: de: 'Ordnet dem Item eine Absenk-Temperatur zu, auf die rtr_setpoint beim aufruf der Funktion drop gesetzt wird. Muss auf dem selben Item wie rtr_setpoint gesetzt werden' en: 'Defines a drop temperature for rtr_setpoint, which is set by calling the drop function. Only valid in the same Item where rtr_setpoint is defined' rtr_temp_boost: - type: int + type: float description: de: 'Ordnet dem Item eine Boost-Temperatur zu, auf die rtr_setpoint beim aufruf der Funktion boost gesetzt wird. Muss auf dem selben Item wie rtr_setpoint gesetzt werden' en: 'Defines a boost temperature for rtr_setpoint, which is set by calling the boost function. Only valid in the same Item where rtr_setpoint is defined' From 71d628cd2c30f9f6ac97fd570cd374504e977b03 Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Fri, 2 Nov 2018 17:41:24 +0100 Subject: [PATCH 389/705] Allow to configure cycle time with plugin.yaml --- rtr/__init__.py | 2 +- rtr/plugin.yaml | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/rtr/__init__.py b/rtr/__init__.py index 78ad32f06..105d53c57 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -77,10 +77,10 @@ def __init__(self, sh, *args, **kwargs): self._items = Items.get_instance() # preset the controller defaults - self._cycle_time = 1*60 self._defaults['Tlast'] = time.time() self._defaults['Kp'] = self.get_parameter_value('default_Kp') self._defaults['Ki'] = self.get_parameter_value('default_Ki') + self._cycle_time = self.get_parameter_value('cycle_time') return diff --git a/rtr/plugin.yaml b/rtr/plugin.yaml index 94aaa0027..8c0439294 100755 --- a/rtr/plugin.yaml +++ b/rtr/plugin.yaml @@ -26,6 +26,13 @@ parameters: de: 'Standard Integralfaktor für erstellte Items' en: 'default integral gain for created items' + cycle_time: + type: int + default: 60 + description: + de: "Abständen in Sekunden, in denen die Regelung arbeitet. Dieser Wert sollte nur geändert werden, wenn man weiss was man tut!" + en: "Cycle timer in secounds. Don't change when you don't know what you do!" + item_attributes: rtr_current: type: int From 9b5dfa7b6e98f91508e809049f3f5457796abd8e Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Fri, 2 Nov 2018 18:05:09 +0100 Subject: [PATCH 390/705] Changed Function Name from Trigger to Timer Updated Logger Output --- rtr/__init__.py | 106 ++++++++++++++++++++++++------------------------ 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/rtr/__init__.py b/rtr/__init__.py index 105d53c57..42da9d49c 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -93,9 +93,9 @@ def run(self): self.scheduler_add('cycle', self.update_items, prio=5, cycle=int(self._cycle_time)) try: - self._restoreTrigger() + self._restoreTimer() except Exception as e: - self.logger.error("Error in 'self._restoreTrigger()': {}".format(e)) + self.logger.error("Error in 'self._restoreTimer()': {}".format(e)) return @@ -113,26 +113,26 @@ def parse_item(self, item): """ if self.has_iattr(item.conf, 'rtr_current'): if not item.conf['rtr_current'].isdigit(): - self.logger.error("rtr: error in item {0}, rtr_current need to be the controller number" . format(item.id())) + self.logger.error("rtr: error in item {0}, rtr_current need to be the controller number".format(item.id())) return c = 'c' + item.conf['rtr_current'] # init controller with defaults when it not exist if c not in self._controller: - self.logger.debug("rtr: controller '{0}' does not exist yet. Init with default values" . format(c)) + self.logger.debug("rtr: controller '{0}' does not exist yet. Init with default values".format(c)) self._controller[c] = self._defaults.copy() # store currentItem into controller self._controller[c]['currentItem'] = item.id() - self.logger.info("rtr: bound item '{1}' to currentItem for controller '{0}'". format(c, item.id())) + self.logger.info("rtr: bound item '{1}' to currentItem for controller '{0}'".format(c, item.id())) if not self.has_iattr(item.conf, 'rtr_Kp'): - self.logger.info("rtr: missing rtr_Kp in item {0}, setting to default: {1}" . format(item.id(), self._controller[c]['Kp'])) + self.logger.info("rtr: missing rtr_Kp in item {0}, setting to default: {1}".format(item.id(), self._controller[c]['Kp'])) else: self._controller[c]['Kp'] = float(item.conf['rtr_Kp']) if not self.has_iattr(item.conf, 'rtr_Ki'): - self.logger.info("rtr: missing rtr_Ki in item {0}, setting to default: {1}" . format(item.id(), self._controller[c]['Ki'])) + self.logger.info("rtr: missing rtr_Ki in item {0}, setting to default: {1}".format(item.id(), self._controller[c]['Ki'])) else: self._controller[c]['Ki'] = float(item.conf['rtr_Ki']) @@ -144,19 +144,19 @@ def parse_item(self, item): if self.has_iattr(item.conf, 'rtr_setpoint'): if not item.conf['rtr_setpoint'].isdigit(): - self.logger.error("rtr: error in item {0}, rtr_setpoint need to be the controller number" . format(item.id())) + self.logger.error("rtr: error in item {0}, rtr_setpoint need to be the controller number".format(item.id())) return c = 'c' + item.conf['rtr_setpoint'] # init controller with defaults when it not exist if c not in self._controller: - self.logger.debug("rtr: controller '{0}' does not exist yet. Init with default values" . format(c)) + self.logger.debug("rtr: controller '{0}' does not exist yet. Init with default values".format(c)) self._controller[c] = self._defaults.copy() # store setpointItem into controller self._controller[c]['setpointItem'] = item.id() - self.logger.info("rtr: bound item '{1}' to setpointItem for controller '{0}'". format(c, item.id())) + self.logger.info("rtr: bound item '{1}' to setpointItem for controller '{0}'".format(c, item.id())) if self.has_iattr(item.conf, 'rtr_temp_default'): self._controller[c]['tempDefault'] = float(item.conf['rtr_temp_default']) @@ -174,19 +174,19 @@ def parse_item(self, item): if self.has_iattr(item.conf, 'rtr_actuator'): if not item.conf['rtr_actuator'].isdigit(): - self.logger.error("rtr: error in item {0}, rtr_actuator need to be the controller number" . format(item.id())) + self.logger.error("rtr: error in item {0}, rtr_actuator need to be the controller number".format(item.id())) return c = 'c' + item.conf['rtr_actuator'] # init controller with defaults when it not exist if c not in self._controller: - self.logger.debug("rtr: controller '{0}' does not exist yet. Init with default values" . format(c)) + self.logger.debug("rtr: controller '{0}' does not exist yet. Init with default values".format(c)) self._controller[c] = self._defaults.copy() # store actuatorItem into controller self._controller[c]['actuatorItem'] = item.id() - self.logger.info("rtr: bound item '{1}' to actuatorItem for controller '{0}'". format(c, item.id())) + self.logger.info("rtr: bound item '{1}' to actuatorItem for controller '{0}'".format(c, item.id())) if not self._controller[c]['validated']: self.validate_controller(c) @@ -200,10 +200,10 @@ def parse_item(self, item): if self.has_iattr(item.conf, 'rtr_stops'): # validate this optional Item if item._type != 'bool': - self.logger.error("rtr: error in item {0}, rtr_stops Item need to be bool (current {1})" . format(item.id(), item._type)) + self.logger.error("rtr: error in item {0}, rtr_stops Item need to be bool (current {1})".format(item.id(), item._type)) return - self.logger.debug("rtr: parse item {0}, found rtr_stops={1}" . format(item.id(), item.conf['rtr_stops'])) + self.logger.debug("rtr: parse item {0}, found rtr_stops={1}".format(item.id(), item.conf['rtr_stops'])) cList = item.conf['rtr_stops'] if isinstance(cList, str): @@ -213,7 +213,7 @@ def parse_item(self, item): # validate controller number if not cNum.isdigit(): - self.logger.error("rtr: error in {0}, rtr_stops need to be the controller number(s) - skip {1}" . format(item.id(), cNum)) + self.logger.error("rtr: error in {0}, rtr_stops need to be the controller number(s) - skip {1}".format(item.id(), cNum)) continue c = 'c' + cNum @@ -221,7 +221,7 @@ def parse_item(self, item): # init controller with defaults when it not exist if c not in self._controller: self._controller[c] = self._defaults.copy() - self.logger.debug("rtr: create controller {0} for {1}" . format(c, item.id())) + self.logger.debug("rtr: create controller {0} for {1}".format(c, item.id())) # store stopItems into controller if self._controller[c]['stopItems'] is None: @@ -231,7 +231,7 @@ def parse_item(self, item): # listen to item events item.add_method_trigger(self.stop_Controller) - self.logger.debug("rtr: parse item {0}, controller {1} stop items: {2} " . format(item.id(), c, self._controller[c]['stopItems'])) + self.logger.debug("rtr: parse item {0}, controller {1} stop items: {2} ".format(item.id(), c, self._controller[c]['stopItems'])) return @@ -241,7 +241,7 @@ def stop_Controller(self, item, caller=None, source=None, dest=None): for item in self._controller[c]['stopItems']: if item(): if self._controller[c]['actuatorItem']() > 0: - logger.info("rtr: controller {0} stopped, because of item {1}" . format(c, item.id())) + logger.info("rtr: controller {0} stopped, because of item {1}".format(c, item.id())) self._controller[c]['actuatorItem'](0) def update_item(self, item, caller=None, source=None, dest=None): @@ -254,7 +254,7 @@ def update_item(self, item, caller=None, source=None, dest=None): :param dest: if given it represents the dest """ - self.logger.debug("rtr: update item {}, from caller = {}, with source={} and dest={}" . format(item.id(), caller, source, dest)) + self.logger.debug("rtr: update item {}, from caller = {}, with source={} and dest={}".format(item.id(), caller, source, dest)) if item() and caller != 'plugin': if 'rtr_setpoint' in item.conf or 'rtr_current' in item.conf: c = 'c' + item.conf['rtr_setpoint'] @@ -281,7 +281,7 @@ def validate_controller(self, c): if self._controller[c]['actuatorItem'] is None: return - self.logger.info("rtr: all needed params are set, controller {0} validated" . format(c)) + self.logger.info("rtr: all needed params are set, controller {0} validated".format(c)) self._controller[c]['validated'] = True def pi_controller(self, c): @@ -313,13 +313,13 @@ def pi_controller(self, c): for item in self._controller[c]['stopItems']: if item(): if self._items.return_item(self._controller[c]['actuatorItem'])() > 0: - self.logger.info("rtr: controller {0} currently deactivated, because of item {1}" . format(c, item.id())) + self.logger.info("rtr: controller {0} currently deactivated, because of item {1}".format(c, item.id())) self._items.return_item(self._controller[c]['actuatorItem'])(0) return # calculate scanning time Ta = int(time.time()) - self._controller[c]['Tlast'] - self.logger.debug("{0} | Ta = Time() - Tlast | {1} = {2} - {3}" . format(c, Ta, (Ta + self._controller[c]['Tlast']), self._controller[c]['Tlast'])) + self.logger.debug("{0} | Ta = Time() - Tlast | {1} = {2} - {3}".format(c, Ta, (Ta + self._controller[c]['Tlast']), self._controller[c]['Tlast'])) self._controller[c]['Tlast'] = int(time.time()) # get current and set point temp @@ -328,12 +328,12 @@ def pi_controller(self, c): # skip execution if x is 0 if x == 0.00: - self.logger.debug("{0} | skip uninitiated x value (currently zero)" . format(c)) + self.logger.debug("{0} | skip uninitiated x value (currently zero)".format(c)) return # calculate control error e = w - x - self.logger.debug("{0} | e = w - x | {1} = {2} - {3}" . format(c, e, w, x)) + self.logger.debug("{0} | e = w - x | {1} = {2} - {3}".format(c, e, w, x)) Kp = 1.0 / self._controller[c]['Kp'] self._controller[c]['eSum'] = self._controller[c]['eSum'] + e * Ta @@ -350,12 +350,12 @@ def pi_controller(self, c): y = 0 self._controller[c]['eSum'] = 0 - self.logger.debug("{0} | eSum = {1}" . format(c, self._controller[c]['eSum'])) - self.logger.debug("{0} | y = {1}" . format(c, y)) + self.logger.debug("{0} | eSum = {1}".format(c, self._controller[c]['eSum'])) + self.logger.debug("{0} | y = {1}".format(c, y)) self._items.return_item(self._controller[c]['actuatorItem'])(y) - def _restoreTrigger(self): + def _restoreTimer(self): """ scans folder for saved triggers to restore them at startup """ @@ -363,56 +363,50 @@ def _restoreTrigger(self): if os.path.isdir(self.path): for filename in os.listdir(self.path): - self.logger.info("need to restore '{}'" . format(filename)) + self.logger.info("need to restore '{}'".format(filename)) try: - self.logger.debug("read file {}".format(filename)) f = open(self.path + filename, "r") ts = f.read() f.close() except OSError as e: - self.logger.error("_restoreTrigger: cannot read '{}', error: {}" . format(self.path + filename, e.args)) + self.logger.error("_restoreTimer(): cannot read '{}', error: {}".format(self.path + filename, e.args)) continue try: ts = int(ts) - self.logger.debug("file content is {}" . format(ts)) except ValueError: - self.logger.error("_restoreTrigger: file content '{}' is no timestamp" . format(ts)) + self.logger.error("_restoreTimer(): file content '{}' is no timestamp".format(ts)) name, c = filename.split('_') - self.logger.debug("controller is {}" . format(c)) # TODO: if trigger ts <= time(), run it and not recreate?! - self._createTrigger(filename, c, datetime.datetime.fromtimestamp(ts)) + self._createTimer(filename, c, datetime.datetime.fromtimestamp(ts)) - # TODO: rename Trigger -> Timer?! - def _createTrigger(self, name, c, timer): + def _createTimer(self, name, c, timer): """ this function changes setpoint to defined default temperature - :param name: name of the trigger + :param name: name of the timer :param c: controller to be used - :param timer: datetime value for the trigger + :param timer: datetime value for the timer """ - self.logger.debug("_createTrigger called for name: '{}', controller: '{}', on '{}'" . format(name, c, timer)) + self.logger.debug("_createTimer(): called for name: '{}', controller: '{}', on '{}'".format(name, c, timer)) - #self.scheduler_trigger(name, self.default, by='rtr', value={'c': c}, dt=timer) - - #next = shtime.now() + datetime.timedelta(seconds=time) try: + # check if this scheduler already exist and delete it before create a new one if self.scheduler_get(name) is not None: self.scheduler_remove(name) - + # create scheduler self.scheduler_add(name, self.default, value={'c': c}, next=timer) except Exception as e: - self.logger.error("Error in '_createTrigger()': {}".format(e)) + self.logger.error("_createTimer(): ': {}".format(e)) try: if not os.path.isdir(self.path): os.makedirs(self.path) except OSError as e: - self.logger.error("_createTrigger: cannot create '{}', error: {}" . format(self.path, e.args)) + self.logger.error("_createTimer(): cannot create '{}', error: {}".format(self.path, e.args)) return try: @@ -420,13 +414,15 @@ def _createTrigger(self, name, c, timer): f.write(timer.strftime("%s")) f.close() except IOError as e: - self.logger.error("_createTrigger: I/O error({0}): {1}" . format(e.errno, e.strerror)) + self.logger.error("_createTimer(): I/O error({}): {}".format(e.errno, e.strerror)) def default(self, c, caller=None, source=None, dest=None): """ this function changes setpoint of the given controller to defined default temperature :param c: controller to be used """ + self.logger.debug("default(): called for controller: '{}'".format(c)) + if c in self._controller: if self._controller[c]['tempDefault'] > 0: self._items.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempDefault']) @@ -435,38 +431,42 @@ def default(self, c, caller=None, source=None, dest=None): if os.path.isfile(self.path + 'boost_' + c): os.remove(self.path + 'boost_' + c) except IOError as e: - self.logger.error("default: I/O error({0}): {1}" . format(e.errno, e.strerror)) + self.logger.error("default(): I/O error({0}): {1}".format(e.errno, e.strerror)) try: if self.scheduler_get('boost_' + c) is not None: self.scheduler_remove('boost_' + c) except Exception as e: - self.logger.error("Error in '_createTrigger()': {}".format(e)) + self.logger.error("default(): {}".format(e)) else: - self.logger.error("boost unknown controller '{}'" . format(self._controller.keys())) + self.logger.error("default(): unknown controller '{}' - we only have '{}'".format(c, self._controller.keys())) def boost(self, c): """ this function changes setpoint of the given controller to defined boost temperature :param c: controller to be used """ + self.logger.debug("boost(): called for controller: '{}'".format(c)) + if c in self._controller: if self._controller[c]['tempBoost'] > 0: self._items.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempBoost']) shtime = Shtime.get_instance() - self._createTrigger('boost_' + c, c, shtime.now() + datetime.timedelta(minutes=1)) + self._createTimer('boost_' + c, c, shtime.now() + datetime.timedelta(minutes=1)) else: - self.logger.error("boost unknown controller '{}'" . format(self._controller.keys())) + self.logger.error("boost() unknown controller '{}' - we only have '{}'".format(c, self._controller.keys())) def drop(self, c): """ this function changes setpoint of the given controller to defined drop temperature :param c: controller to be used """ + self.logger.debug("drop(): called for controller: '{}'".format(c)) + if c in self._controller: if self._controller[c]['tempDrop'] > 0: self._items.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempDrop']) else: - self.logger.error("drop unknown controller '{}'" . format(self._controller.keys())) + self.logger.error("drop() unknown controller '{}' - we only have '{}'".format(c, self._controller.keys())) From d638c1c7ac6314039e46ff9133dea6a5d6a56891 Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Fri, 2 Nov 2018 18:59:06 +0100 Subject: [PATCH 391/705] Add new Plugin Param, to choose if value should get restored on expired timers --- rtr/__init__.py | 25 ++++++++++++++++++------- rtr/plugin.yaml | 6 ++++++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/rtr/__init__.py b/rtr/__init__.py index 42da9d49c..f3f041653 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -73,7 +73,7 @@ def __init__(self, sh, *args, **kwargs): self.logger.debug("rtr: init method called") sh = self.get_sh() - self.path = sh.base_dir + '/var/rtr/' + self.path = sh.base_dir + '/var/rtr/timer/' self._items = Items.get_instance() # preset the controller defaults @@ -81,6 +81,7 @@ def __init__(self, sh, *args, **kwargs): self._defaults['Kp'] = self.get_parameter_value('default_Kp') self._defaults['Ki'] = self.get_parameter_value('default_Ki') self._cycle_time = self.get_parameter_value('cycle_time') + self._resetValOnExpiredTimer = self.get_parameter_value('resetValOnExpiredTimer') return @@ -357,32 +358,42 @@ def pi_controller(self, c): def _restoreTimer(self): """ - scans folder for saved triggers to restore them at startup + scans folder for saved timer to restore them at startup """ - self.logger.info("check if we need to restore triggers") + self.logger.info("check if we need to restore timer") if os.path.isdir(self.path): for filename in os.listdir(self.path): self.logger.info("need to restore '{}'".format(filename)) + if "boost_c" not in filename: + self.logger.error("file looks invalid! Skip it..") + return + try: f = open(self.path + filename, "r") ts = f.read() f.close() except OSError as e: - self.logger.error("_restoreTimer(): cannot read '{}', error: {}".format(self.path + filename, e.args)) + self.logger.error("cannot read '{}', error: {}".format(self.path + filename, e.args)) continue try: ts = int(ts) except ValueError: - self.logger.error("_restoreTimer(): file content '{}' is no timestamp".format(ts)) + self.logger.error("file content '{}' is no timestamp".format(ts)) name, c = filename.split('_') - # TODO: if trigger ts <= time(), run it and not recreate?! - self._createTimer(filename, c, datetime.datetime.fromtimestamp(ts)) + dt = datetime.datetime.fromtimestamp(ts) + shtime = Shtime.get_instance() + if dt < shtime.now(): + self.logger.info("timer '{}' is already expired - restore = {}".format(filename, self._resetValOnExpiredTimer)) + if self._resetValOnExpiredTimer: + self.default(c) + else: + self._createTimer(filename, c, dt) def _createTimer(self, name, c, timer): """ diff --git a/rtr/plugin.yaml b/rtr/plugin.yaml index 8c0439294..ff27b24a0 100755 --- a/rtr/plugin.yaml +++ b/rtr/plugin.yaml @@ -33,6 +33,12 @@ parameters: de: "Abständen in Sekunden, in denen die Regelung arbeitet. Dieser Wert sollte nur geändert werden, wenn man weiss was man tut!" en: "Cycle timer in secounds. Don't change when you don't know what you do!" + resetValOnExpiredTimer: + type: bool + default: true + description: + de: "Wenn nicht aktiviert, werden beim wiederherstellen von Timern (Restart von SH) die Werte von abgelaufenen Timern nicht zurück gesetzt" + item_attributes: rtr_current: type: int From 602408d73ff94ee20f3436478e946aca6d57e07d Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Fri, 2 Nov 2018 19:16:26 +0100 Subject: [PATCH 392/705] renamed resetValOnExpiredTimer to defaultOnExpiredTimer --- rtr/__init__.py | 6 +++--- rtr/plugin.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/rtr/__init__.py b/rtr/__init__.py index f3f041653..956adc375 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -81,7 +81,7 @@ def __init__(self, sh, *args, **kwargs): self._defaults['Kp'] = self.get_parameter_value('default_Kp') self._defaults['Ki'] = self.get_parameter_value('default_Ki') self._cycle_time = self.get_parameter_value('cycle_time') - self._resetValOnExpiredTimer = self.get_parameter_value('resetValOnExpiredTimer') + self._defaultOnExpiredTimer = self.get_parameter_value('defaultOnExpiredTimer') return @@ -389,8 +389,8 @@ def _restoreTimer(self): dt = datetime.datetime.fromtimestamp(ts) shtime = Shtime.get_instance() if dt < shtime.now(): - self.logger.info("timer '{}' is already expired - restore = {}".format(filename, self._resetValOnExpiredTimer)) - if self._resetValOnExpiredTimer: + self.logger.info("timer '{}' is already expired - restore default = {}".format(filename, self._defaultOnExpiredTimer)) + if self._defaultOnExpiredTimer: self.default(c) else: self._createTimer(filename, c, dt) diff --git a/rtr/plugin.yaml b/rtr/plugin.yaml index ff27b24a0..76b400711 100755 --- a/rtr/plugin.yaml +++ b/rtr/plugin.yaml @@ -33,7 +33,7 @@ parameters: de: "Abständen in Sekunden, in denen die Regelung arbeitet. Dieser Wert sollte nur geändert werden, wenn man weiss was man tut!" en: "Cycle timer in secounds. Don't change when you don't know what you do!" - resetValOnExpiredTimer: + defaultOnExpiredTimer: type: bool default: true description: From 9d0905107cb5472861c6076359aa4463c4e90ad7 Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Fri, 2 Nov 2018 22:57:06 +0100 Subject: [PATCH 393/705] added plugin param tempBoostTime and item param rtr_temp_boost_time: also added more robust error handling and _deleteTimer for better cleanup --- rtr/__init__.py | 86 +++++++++++++++++++++++++++++++++++-------------- rtr/plugin.yaml | 39 ++++++++++++++++++---- 2 files changed, 94 insertions(+), 31 deletions(-) diff --git a/rtr/__init__.py b/rtr/__init__.py index 956adc375..6e3c00219 100644 --- a/rtr/__init__.py +++ b/rtr/__init__.py @@ -27,6 +27,7 @@ # http://de.wikipedia.org/wiki/Regler#PI-Regler # http://www.honeywell.de/fp/regler/Reglerparametrierung.pdf +import re import time import datetime @@ -56,6 +57,7 @@ class RTR(SmartPlugin): 'tempDefault' : 0, 'tempDrop' : 0, 'tempBoost' : 0, + 'tempBoostTime' : 0, 'validated' : False} def __init__(self, sh, *args, **kwargs): @@ -80,6 +82,7 @@ def __init__(self, sh, *args, **kwargs): self._defaults['Tlast'] = time.time() self._defaults['Kp'] = self.get_parameter_value('default_Kp') self._defaults['Ki'] = self.get_parameter_value('default_Ki') + self._defaults['tempBoostTime'] = self.get_parameter_value('defaultBoostTime') self._cycle_time = self.get_parameter_value('cycle_time') self._defaultOnExpiredTimer = self.get_parameter_value('defaultOnExpiredTimer') @@ -104,7 +107,7 @@ def stop(self): """ Stop method for the plugin """ - self.logger.debug("stop method called") + self.logger.debug("rtr: stop method called") self.alive = False def parse_item(self, item): @@ -168,6 +171,9 @@ def parse_item(self, item): if self.has_iattr(item.conf, 'rtr_temp_boost'): self._controller[c]['tempBoost'] = float(item.conf['rtr_temp_boost']) + if self.has_iattr(item.conf, 'rtr_temp_boost_time'): + self._controller[c]['tempBoostTime'] = int(item.conf['rtr_temp_boost_time']) + if not self._controller[c]['validated']: self.validate_controller(c) @@ -366,7 +372,7 @@ def _restoreTimer(self): for filename in os.listdir(self.path): self.logger.info("need to restore '{}'".format(filename)) - if "boost_c" not in filename: + if not re.match(r"boost_c[0-9]+", filename) and not re.match(r"drop_c[0-9]+", filename): self.logger.error("file looks invalid! Skip it..") return @@ -386,8 +392,10 @@ def _restoreTimer(self): name, c = filename.split('_') - dt = datetime.datetime.fromtimestamp(ts) shtime = Shtime.get_instance() + dt = datetime.datetime.fromtimestamp(ts) + dt = dt.replace(tzinfo=shtime.tzinfo()) + if dt < shtime.now(): self.logger.info("timer '{}' is already expired - restore default = {}".format(filename, self._defaultOnExpiredTimer)) if self._defaultOnExpiredTimer: @@ -395,21 +403,26 @@ def _restoreTimer(self): else: self._createTimer(filename, c, dt) - def _createTimer(self, name, c, timer): + def _createTimer(self, name, c, edt): """ - this function changes setpoint to defined default temperature + this function create a scheduler and a recovery text file to restore + the scheduler on a restart from smarthome with _restoreTimer() :param name: name of the timer :param c: controller to be used - :param timer: datetime value for the timer + :param edt: end datetime value for the timer """ - self.logger.debug("_createTimer(): called for name: '{}', controller: '{}', on '{}'".format(name, c, timer)) + self.logger.debug("_createTimer(): called for name: '{}', controller: '{}', on '{}'".format(name, c, edt)) + + if not isinstance(edt, datetime.datetime): + self.logger.error("_createTimer(): edt is no datetime!") + return try: # check if this scheduler already exist and delete it before create a new one if self.scheduler_get(name) is not None: self.scheduler_remove(name) # create scheduler - self.scheduler_add(name, self.default, value={'c': c}, next=timer) + self.scheduler_add(name, self.default, value={'c': c}, next=edt) except Exception as e: self.logger.error("_createTimer(): ': {}".format(e)) @@ -422,11 +435,31 @@ def _createTimer(self, name, c, timer): try: f = open(self.path + name, "w") - f.write(timer.strftime("%s")) + f.write(edt.strftime("%s")) f.close() except IOError as e: self.logger.error("_createTimer(): I/O error({}): {}".format(e.errno, e.strerror)) + def _deleteTimer(self, name): + """ + this function delete a scheduler and its recovery text file + :param name: name of the timer + """ + self.logger.debug("_deleteTimer(): called for name: '{}'".format(name)) + + try: + if self.scheduler_get(name) is not None: + self.scheduler_remove(name) + except Exception as e: + self.logger.error("default(): {}".format(e)) + + try: + if os.path.isfile(self.path + name): + os.remove(self.path + name) + except IOError as e: + self.logger.error("default(): I/O error({0}): {1}".format(e.errno, e.strerror)) + + def default(self, c, caller=None, source=None, dest=None): """ this function changes setpoint of the given controller to defined default temperature @@ -438,46 +471,51 @@ def default(self, c, caller=None, source=None, dest=None): if self._controller[c]['tempDefault'] > 0: self._items.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempDefault']) - try: - if os.path.isfile(self.path + 'boost_' + c): - os.remove(self.path + 'boost_' + c) - except IOError as e: - self.logger.error("default(): I/O error({0}): {1}".format(e.errno, e.strerror)) - - try: - if self.scheduler_get('boost_' + c) is not None: - self.scheduler_remove('boost_' + c) - except Exception as e: - self.logger.error("default(): {}".format(e)) + self._deleteTimer('boost_' + c) + self._deleteTimer('drop_' + c) else: self.logger.error("default(): unknown controller '{}' - we only have '{}'".format(c, self._controller.keys())) - def boost(self, c): + def boost(self, c, timer=True, edt=None): """ this function changes setpoint of the given controller to defined boost temperature :param c: controller to be used + :param timer: if not True, no timer will be created + :param edt: end datetime to override the default """ self.logger.debug("boost(): called for controller: '{}'".format(c)) if c in self._controller: if self._controller[c]['tempBoost'] > 0: self._items.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempBoost']) - shtime = Shtime.get_instance() - self._createTimer('boost_' + c, c, shtime.now() + datetime.timedelta(minutes=1)) + if self._controller[c]['tempBoostTime'] == 0 and edt is None: + timer = False + + if timer == True: + if edt is None: + shtime = Shtime.get_instance() + edt = shtime.now() + datetime.timedelta(minutes=self._controller[c]['tempBoostTime']) + + self._deleteTimer('drop_' + c) + self._createTimer('boost_' + c, c, edt) else: self.logger.error("boost() unknown controller '{}' - we only have '{}'".format(c, self._controller.keys())) - def drop(self, c): + def drop(self, c, edt=None): """ this function changes setpoint of the given controller to defined drop temperature :param c: controller to be used + :param edt: end date time, if given a timer with the end date time get created """ self.logger.debug("drop(): called for controller: '{}'".format(c)) if c in self._controller: if self._controller[c]['tempDrop'] > 0: self._items.return_item(self._controller[c]['setpointItem'])(self._controller[c]['tempDrop']) + if isinstance(edt, datetime.datetime): + self._deleteTimer('boost_' + c) + self._createTimer('drop_' + c, c, edt) else: self.logger.error("drop() unknown controller '{}' - we only have '{}'".format(c, self._controller.keys())) diff --git a/rtr/plugin.yaml b/rtr/plugin.yaml index 76b400711..bda488198 100755 --- a/rtr/plugin.yaml +++ b/rtr/plugin.yaml @@ -33,55 +33,80 @@ parameters: de: "Abständen in Sekunden, in denen die Regelung arbeitet. Dieser Wert sollte nur geändert werden, wenn man weiss was man tut!" en: "Cycle timer in secounds. Don't change when you don't know what you do!" + defaultBoostTime: + type: int + default: 240 + description: + de: "Legt die Standard Zeit in Minuten fest, nachdem die Boost-Temperatur automatisch zurück auf Standard gesetzt wird" + en: "Defines the default time in minutes, when the boost-temperature gets autmatically set back to Default" + defaultOnExpiredTimer: type: bool default: true description: - de: "Wenn nicht aktiviert, werden beim wiederherstellen von Timern (Restart von SH) die Werte von abgelaufenen Timern nicht zurück gesetzt" + de: "Wenn nicht aktiviert, werden beim wiederherstellen von abgelaufenen Timern die Temperaturen nicht zurück auf Default gesetzt" + en: "when not True, a expired timer will not set back to Default-Temperature on a timer restore (when SH will be restarted)" item_attributes: rtr_current: type: int + mandatory: True description: - de: 'Ordnet das Item dem Controller mit gegebener ID als Ist-Wert zu' + de: 'Ordnet das Item dem Regler/Controller mit gegebener ID als Ist-Wert zu' en: 'Defines the Item as current value for the given controller ID' + rtr_Kp: type: int description: de: 'Ordnet dem Item einen vom Standard abweichenden Verstärkungsfaktor zu. Muss auf dem selben Item wie rtr_current gesetzt werden' en: 'Defines a different proportional gain for the controller. Only valid in the same Item where rtr_current is defined' + rtr_Ki: type: int description: de: 'Ordnet dem Item einen vom Standard abweichenden Integralfaktor zu. Muss auf dem selben Item wie rtr_current gesetzt werden' en: 'Defines a different integral gain for the controller. Only valid in the same Item where rtr_current is defined' + rtr_setpoint: type: int + mandatory: True description: - de: 'Ordnet das Item dem Controller mit gegebener ID als Soll-Wert zu' + de: 'Ordnet das Item dem Regler/Controller mit gegebener ID als Soll-Wert zu' en: 'Defines the Item as setpoint value for the given controller ID' + rtr_temp_default: type: float description: - de: 'Ordnet dem Item eine Standard Temperatur zu, auf die rtr_setpoint zurück gesetzt wird. Muss auf dem selben Item wie rtr_setpoint gesetzt werden' + de: 'Ordnet dem Regler/Controller eine Standard Temperatur zu, auf die rtr_setpoint zurück gesetzt wird. Muss auf dem selben Item wie rtr_setpoint gesetzt werden' en: 'Defines a default temperature for rtr_setpoint. Only valid in the same Item where rtr_setpoint is defined' + rtr_temp_drop: type: float description: - de: 'Ordnet dem Item eine Absenk-Temperatur zu, auf die rtr_setpoint beim aufruf der Funktion drop gesetzt wird. Muss auf dem selben Item wie rtr_setpoint gesetzt werden' + de: 'Ordnet dem Regler/Controller eine Absenk-Temperatur zu, auf die rtr_setpoint beim aufruf der Funktion drop gesetzt wird. Muss auf dem selben Item wie rtr_setpoint gesetzt werden' en: 'Defines a drop temperature for rtr_setpoint, which is set by calling the drop function. Only valid in the same Item where rtr_setpoint is defined' + rtr_temp_boost: type: float description: - de: 'Ordnet dem Item eine Boost-Temperatur zu, auf die rtr_setpoint beim aufruf der Funktion boost gesetzt wird. Muss auf dem selben Item wie rtr_setpoint gesetzt werden' + de: 'Ordnet dem Regler eine Boost-Temperatur zu, auf die rtr_setpoint beim aufruf der Funktion boost gesetzt wird. Muss auf dem selben Item wie rtr_setpoint gesetzt werden' en: 'Defines a boost temperature for rtr_setpoint, which is set by calling the boost function. Only valid in the same Item where rtr_setpoint is defined' + + rtr_temp_boost_time: + type: int + description: + de: "Ordnet dem Regler eine Standard Zeit für den Boost in Minten zu und überschreibt somit den globalen Standard defaultBoostTime. Muss auf dem selben Item wie rtr_setpoint gesetzt werden" + en: "Defines a default boost time in minutes for this controller and so overrides the global defaultBoostTime. Only valid in the same Item where rtr_setpoint is defined" + rtr_actuator: type: int + mandatory: True description: de: 'Ordnet das Item dem Controller mit gegebener ID als Stellgröße zu' en: 'Defines the Item as actuator value for the given controller ID' + rtr_stops: type: list(int) description: - de: 'Ordnet das Item dem einen oder mehreren Controllern per ID als Stop-Objekt zu. Kann nur auf einem Item vom Typ Bool gesetzt werden. Ist der Item Wert True, Pausiert die Regelung.' + de: 'Ordnet das Item dem einen oder mehreren Controllern per ID als Stop-Objekt zu. Kann nur auf einem Item vom Typ Bool gesetzt werden. Ist der Item Wert True, Pausiert die Regelung' en: 'Defines the Item as stop item for the given controller IDs. Only valid on Item-Type Bool. If Item is True, the controller gets paused' From 9c8a2238574d7f70b60f13807d5537d7d0000975 Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Sat, 3 Nov 2018 00:22:31 +0100 Subject: [PATCH 394/705] Update Readme --- rtr/README.md | 110 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 98 insertions(+), 12 deletions(-) diff --git a/rtr/README.md b/rtr/README.md index fe3d7592a..f2258dd2d 100644 --- a/rtr/README.md +++ b/rtr/README.md @@ -2,29 +2,30 @@ Providing a room temperature regulator -## Configuration -### plugin.yaml +## plugin.yaml ``` rtr: class_name: RTR class_path: plugins.rtr - # default_Kp: 5 # Proportional gain - # default_Ki: 240 # Integral gain + # default_Kp: 10 # Proportional gain + # default_Ki: 15 # Integral gain ``` Description of the attributes: -* __default_Kp__: change default value for Kp (optional, default: 5) -* __default_Ki__: change default value for Ki (optional, default: 240) +* __default_Kp__: change default value for Kp (optional, default: 10) +* __default_Ki__: change default value for Ki (optional, default: 15) -### items.yaml +## items.yaml Three items need to be assigned ``rtr_current``, ``rtr_setpoint`` and ``rtr_actuator``. The attributes each are assigned an integer index. -The same index shows that the items belong to the same rtr. +The same index shows that the items belong to the same controller. -The value of the items must be a numeric one. +But we have now a lot of optional attributes to custumize our controller from global defaults, read below. + +### Required attributes: #### rtr_current @@ -39,9 +40,53 @@ This attribute marks the item as a provider for the *setpoint value* (e.g. the w This attribute marks the item as a receiving one for the value to be sent to the actuator. In the example below it is the item ``gf.floor.temp.state`` -#### Example +### Optional attributes + +#### rtr_Kp, rtr_Ki + +With those you can define different Kp and/or Ki values to your controller, which override the global default from default_Kp/default_Ki. + +***The attributes are only valid on the same item, where ``rtr_current`` is defined and belongs to that controller.*** + +#### rtr_stops + +This attribute can be used to define a item as a stop/pause trigger of the given contoller(s). When the value of the Item changes to on/true the controller(s) stops execution and set rtr_actuator to 0, till the value changes back to off/false. + +***The attributes can only be set on a Item of type Bool. You can add muliple Items to one controller and also one Item to multiple controllers*** + +#### rtr_temp_default, rtr_temp_boost, rtr_temp_boost_time, rtr_temp_drop + +They are for a new way, to handle 3 different temperature modes: + +First we have a ``default`` room temperature, lets say 21 °C + +This is set with ``rtr_temp_default = 21`` + +Now when we want to ``boost`` the temperature for a special event or what ever you can imagine, you can set the temperature manually to a higher value and hope you dont forget to set it back. + +Or u use the boost function of this plugin, to set the temperature to your predefinied value of 23 °C. The Boost function will also handle for you a timer, when the temperature will be set back (lets say in 3 hours) to the predefinied default temperature. + +For this set ``rtr_temp_boost = 23``. The end time, where the value will be set back to Default is defined in minutes. We can use the global attribute defaultBoostTime or you set a individual time. + +For those finding this is not flexible enough: The function boost() can also be called with a individual end time. So you can create multiple logics with individual times and bind them to extra items. + +Now at least we have third temperature mode ``drop``. With it you can build as example a away mode or night reduction where you want want to set temperature to maybe 19 °C. + +So u set ``rtr_temp_drop = 19`` + +The drop-function has not per default a timer, like the boost function. But you can also pass a datetime value to the drop()-function, to set the time, when the temperature should be set back to default. + +The importent thing is, that a created scheduler will survice a restart of smarthome, that the temperature will also be set back to default, when your computer reboots. + +To achieve this, the plugins stores the unix timestamp of the timers end in a file under base_dir + '/var/rtr/timer/', to restore it at startup. -The following shows an example for a working +***The attributes are only valid on the same item, where ``rtr_setpoint`` is defined and belongs to that controller.*** + +For more info about the functions contine reading. + +### Example + +The following shows an simple example for a working. ```yaml gf: @@ -61,7 +106,7 @@ gf: set: type: num visu: 'yes' - cache: 'On' + cache: 'On' # this can be importent, or your defined setpoint get lost after restarts knx_dpt: 9 knx_send: 4/3/120 knx_listen: 4/3/120 @@ -74,4 +119,45 @@ gf: knx_send: 4/1/120 knx_listen: 4/1/120 rtr_actuator: 1 + + door: + name: Frontdoor + open: + rtr_stops: + - '1' + - '2' + + room1: + temp: + name: Temp + type: num + knx_dpt: 9 + knx_send: 4/2/130 + knx_reply: 4/2/130 + ow_addr: 28.52432A030000 + ow_sensor: T + rtr_current: 2 + + set: + type: num + visu: 'yes' + cache: 'On' # this can be importent, or your defined setpoint get lost after restarts + knx_dpt: 9 + knx_send: 4/3/130 + knx_listen: 4/3/130 + rtr_setpoint: 2 + + state: + type: num + visu: 'yes' + knx_dpt: 9 + knx_send: 4/1/130 + knx_listen: 4/1/130 + rtr_actuator: 2 + + window: + name: Window + open: + rtr_stops: + - '2' ``` From 2e20d9c274350bc103d2ace374062ce46da052a5 Mon Sep 17 00:00:00 2001 From: Thomas Creutz Date: Sat, 3 Nov 2018 00:35:22 +0100 Subject: [PATCH 395/705] fixed some typos and updated formatting --- rtr/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/rtr/README.md b/rtr/README.md index f2258dd2d..941e8d6e2 100644 --- a/rtr/README.md +++ b/rtr/README.md @@ -44,13 +44,13 @@ This attribute marks the item as a receiving one for the value to be sent to the #### rtr_Kp, rtr_Ki -With those you can define different Kp and/or Ki values to your controller, which override the global default from default_Kp/default_Ki. +With those you can define different Kp and/or Ki values to your controller, which override the global default from ``default_Kp``/``default_Ki``. ***The attributes are only valid on the same item, where ``rtr_current`` is defined and belongs to that controller.*** #### rtr_stops -This attribute can be used to define a item as a stop/pause trigger of the given contoller(s). When the value of the Item changes to on/true the controller(s) stops execution and set rtr_actuator to 0, till the value changes back to off/false. +This attribute can be used to define a item as a stop/pause trigger of the given controller(s). When the value of the Item changes to on/true the controller(s) stops execution and set the item of rtr_actuator to 0, till the value changes back to off/false. ***The attributes can only be set on a Item of type Bool. You can add muliple Items to one controller and also one Item to multiple controllers*** @@ -64,17 +64,17 @@ This is set with ``rtr_temp_default = 21`` Now when we want to ``boost`` the temperature for a special event or what ever you can imagine, you can set the temperature manually to a higher value and hope you dont forget to set it back. -Or u use the boost function of this plugin, to set the temperature to your predefinied value of 23 °C. The Boost function will also handle for you a timer, when the temperature will be set back (lets say in 3 hours) to the predefinied default temperature. +Or u use the ``boost`` function of this plugin, to set the temperature to your predefinied value of 23 °C. The Boost function will also handle for you a timer, when the temperature will be set back (lets say in 3 hours) to the predefinied default temperature. -For this set ``rtr_temp_boost = 23``. The end time, where the value will be set back to Default is defined in minutes. We can use the global attribute defaultBoostTime or you set a individual time. +For this set ``rtr_temp_boost = 23``. The end time, where the value will be set back to Default is defined in minutes. We can use the global attribute ``defaultBoostTime`` or you set a individual time with ``rtr_temp_boost_time``. -For those finding this is not flexible enough: The function boost() can also be called with a individual end time. So you can create multiple logics with individual times and bind them to extra items. +For those finding this is not flexible enough: The function ``boost()`` can also be called with a individual end time. So you can as an example create multiple logics with individual times and bind them to extra items to trigger them. -Now at least we have third temperature mode ``drop``. With it you can build as example a away mode or night reduction where you want want to set temperature to maybe 19 °C. +Now at least we have the third temperature mode ``drop``. With it you can build as example a away mode or night reduction where you want to set the reduced temperature to maybe 19 °C. So u set ``rtr_temp_drop = 19`` -The drop-function has not per default a timer, like the boost function. But you can also pass a datetime value to the drop()-function, to set the time, when the temperature should be set back to default. +The ``drop()`` function has not per default a timer, like the ``boost()`` function. But you can also pass a datetime value to the drop()-function, to set the time, when the temperature should be set back to default. The importent thing is, that a created scheduler will survice a restart of smarthome, that the temperature will also be set back to default, when your computer reboots. From 1048f2caf7b9b4992fdd933def2389652b668b11 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sat, 3 Nov 2018 10:49:26 +0100 Subject: [PATCH 396/705] Nuki: added logging information about api requests, added lock variable for testing if 503 errors vanish! --- holidays/plugin.yaml | 0 influxdb_new/plugin.yaml | 0 nuki/__init__.py | 16 +++++++++++++++- uwz_warnings/plugin.yaml | 0 4 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 holidays/plugin.yaml create mode 100644 influxdb_new/plugin.yaml create mode 100644 uwz_warnings/plugin.yaml diff --git a/holidays/plugin.yaml b/holidays/plugin.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/influxdb_new/plugin.yaml b/influxdb_new/plugin.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/nuki/__init__.py b/nuki/__init__.py index a8d762f37..195a84981 100644 --- a/nuki/__init__.py +++ b/nuki/__init__.py @@ -26,6 +26,7 @@ import lib.connection import re import cherrypy +import time from jinja2 import Environment, FileSystemLoader from lib.model.smartplugin import * from lib.item import Items @@ -35,6 +36,7 @@ nuki_event_items = {} nuki_battery_items = {} paired_nukis = [] +lock = False class NukiTCPDispatcher(lib.connection.Server): @@ -87,6 +89,8 @@ def __init__(self, sh, *args, **kwargs): global nuki_event_items global nuki_action_items global nuki_battery_items + global lock + global request_queue if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': self.logger = logging.getLogger(__name__) @@ -272,7 +276,12 @@ def _get_nuki_status(self): def _api_call(self, base_url, endpoint=None, nuki_id=None, token=None, action=None, no_wait=None, callback_url=None, id=None): + global lock + while lock: + time.sleep(0.1) try: + lock = True + self.logger.debug("Plugin '{}': Lock set.".format(self.get_shortname())) payload = {} if nuki_id is not None: payload['nukiID'] = nuki_id @@ -287,11 +296,16 @@ def _api_call(self, base_url, endpoint=None, nuki_id=None, token=None, action=No payload['url'] = callback_url if id is not None: payload['id'] = id - + url = urllib.parse.urljoin(base_url, endpoint) + self.logger.debug("Plugin '{}': starting API Call to Nuki Bridge at {} with payload {}.".format(self.get_shortname(), url, payload)) response = requests.get(url=urllib.parse.urljoin(base_url, endpoint), params=payload) + self.logger.debug("Plugin '{}': finishing API Call to Nuki Bridge at {}.".format(self.get_shortname(), url)) response.raise_for_status() + lock = False + self.logger.debug("Plugin '{}': Lock removed.".format(self.get_shortname())) return json.loads(response.text) except Exception as ex: + lock = False self.logger.error(ex) def get_event_items(self): diff --git a/uwz_warnings/plugin.yaml b/uwz_warnings/plugin.yaml new file mode 100644 index 000000000..e69de29bb From 55400c83ba8cd05190c1b881882171a6b9fc4d75 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sat, 3 Nov 2018 11:24:47 +0100 Subject: [PATCH 397/705] Removed wrongly committed local folders --- holidays/plugin.yaml | 0 influxdb_new/plugin.yaml | 0 uwz_warnings/plugin.yaml | 0 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 holidays/plugin.yaml delete mode 100644 influxdb_new/plugin.yaml delete mode 100644 uwz_warnings/plugin.yaml diff --git a/holidays/plugin.yaml b/holidays/plugin.yaml deleted file mode 100644 index e69de29bb..000000000 diff --git a/influxdb_new/plugin.yaml b/influxdb_new/plugin.yaml deleted file mode 100644 index e69de29bb..000000000 diff --git a/uwz_warnings/plugin.yaml b/uwz_warnings/plugin.yaml deleted file mode 100644 index e69de29bb..000000000 From 33cb8ddfc7633f504efffa55d8750b5d0387f7b5 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sat, 3 Nov 2018 13:10:44 +0100 Subject: [PATCH 398/705] Pushbullet: simplified bool comparison, added api to plugin.yaml --- pushbullet/__init__.py | 2 +- pushbullet/plugin.yaml | 159 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+), 1 deletion(-) diff --git a/pushbullet/__init__.py b/pushbullet/__init__.py index 8e54cc885..ab0d3aae7 100755 --- a/pushbullet/__init__.py +++ b/pushbullet/__init__.py @@ -82,7 +82,7 @@ def list(self, title, items, deviceid=None, apikey=None): return self._push(data={"type": "list", "title": title, "items": items}, deviceid=deviceid, apikey=apikey) def file(self, filepath, deviceid=None, apikey=None, body=None): - if os.path.exists(filepath) == False: + if os.path.exists(filepath): self.logger.error( "Plugin '{}': Trying to push non existing file: {}".format(self.get_fullname(), filepath)) diff --git a/pushbullet/plugin.yaml b/pushbullet/plugin.yaml index cc2bf050c..cf1dbb49d 100755 --- a/pushbullet/plugin.yaml +++ b/pushbullet/plugin.yaml @@ -35,3 +35,162 @@ parameters: item_attributes: # Definition of item attributes defined by this plugin + +plugin_functions: + # Definition of item attributes defined by this plugin + note: + type: str | bool + description: + de: "Sendet eine Nachricht an Pushbullet." + en: "Sends a note to pushbullet." + parameters: + title: + type: str + mandatory: True + description: + de: "Titel der Nachricht." + en: "Title of the note." + body: + type: str + mandatory: True + description: + de: "Inhalt der Nachricht." + en: "Body of the note." + deviceid: + type: str + mandatory: False + description: + de: '(optional) Id des anzusprechenden Geräts, wo eine Pushbullet App läuft. Auf http://www.pushbullet.com einloggen, Gerät auswählen und den Teil der URL kopieren, der hinter "device_iden=" kommt. Falls nicht gesetzt, muss der Wert explizit in Funktionsaufrufen als Parameter angegeben werden.' + en: '(optional) Id of referenced device, where Pushbullet app is running. Log in into http://www.pushbullet.com, select target device, copy the part of the browser URL behind "device_iden=" If not set, you have to use it in function calls.' + apikey: + type: str + mandatory: False + description: + de: '(optional) Persönlicher API Key für Pushbullet. Registrierung siehe https://docs.pushbullet.com/. Wenn der Key nicht gesetzt ist, muss er expizit in Funktionsaufrufen gesetzt werden.' + en: '(optional) Your own personal API key for Pushbullet. For your own key refer to https://docs.pushbullet.com/. If key is not set, you have to use it in function calls.' + link: + type: 'str | bool' + description: + de: "Sendet einen Link an Pushbullet." + en: "Sends a link to pushbullet." + parameters: + title: + type: str + mandatory: True + description: + de: "Titel des Links." + en: "Title of the link." + url: + type: str + mandatory: True + description: + de: "URL des Links." + en: "URL of the link." + deviceid: + type: str + mandatory: False + description: + de: '(optional) Id des anzusprechenden Geräts, wo eine Pushbullet App läuft. Auf http://www.pushbullet.com einloggen, Gerät auswählen und den Teil der URL kopieren, der hinter "device_iden=" kommt. Falls nicht gesetzt, muss der Wert explizit in Funktionsaufrufen als Parameter angegeben werden.' + en: '(optional) Id of referenced device, where Pushbullet app is running. Log in into http://www.pushbullet.com, select target device, copy the part of the browser URL behind "device_iden=" If not set, you have to use it in function calls.' + apikey: + type: str + mandatory: False + description: + de: '(optional) Persönlicher API Key für Pushbullet. Registrierung siehe https://docs.pushbullet.com/. Wenn der Key nicht gesetzt ist, muss er expizit in Funktionsaufrufen gesetzt werden.' + en: '(optional) Your own personal API key for Pushbullet. For your own key refer to https://docs.pushbullet.com/. If key is not set, you have to use it in function calls.' + body: + type: str + mandatory: False + description: + de: "Inhalt der Nachricht." + en: "Body of the note." + address: + type: 'str | bool' + description: + de: "Sendet eine Adresse an Pushbullet." + en: "Sends an address to pushbullet." + parameters: + name: + type: str + mandatory: True + description: + de: "Name der Adresse / des Kontakts." + en: "Name of the address / of the contact." + address: + type: str + mandatory: True + description: + de: "Adresse." + en: "Address." + deviceid: + type: str + mandatory: False + description: + de: '(optional) Id des anzusprechenden Geräts, wo eine Pushbullet App läuft. Auf http://www.pushbullet.com einloggen, Gerät auswählen und den Teil der URL kopieren, der hinter "device_iden=" kommt. Falls nicht gesetzt, muss der Wert explizit in Funktionsaufrufen als Parameter angegeben werden.' + en: '(optional) Id of referenced device, where Pushbullet app is running. Log in into http://www.pushbullet.com, select target device, copy the part of the browser URL behind "device_iden=" If not set, you have to use it in function calls.' + apikey: + type: str + mandatory: False + description: + de: '(optional) Persönlicher API Key für Pushbullet. Registrierung siehe https://docs.pushbullet.com/. Wenn der Key nicht gesetzt ist, muss er expizit in Funktionsaufrufen gesetzt werden.' + en: '(optional) Your own personal API key for Pushbullet. For your own key refer to https://docs.pushbullet.com/. If key is not set, you have to use it in function calls.' + list: + type: 'str | bool' + description: + de: "Sendet eine Liste an Pushbullet." + en: "Sends a list to pushbullet." + parameters: + title: + type: str + mandatory: True + description: + de: "Titel der Liste." + en: "Title of the list." + items: + type: str + mandatory: True + description: + de: "Items der Liste (als JSON Array)." + en: "Items of the list (as JSON array)." + deviceid: + type: str + mandatory: False + description: + de: '(optional) Id des anzusprechenden Geräts, wo eine Pushbullet App läuft. Auf http://www.pushbullet.com einloggen, Gerät auswählen und den Teil der URL kopieren, der hinter "device_iden=" kommt. Falls nicht gesetzt, muss der Wert explizit in Funktionsaufrufen als Parameter angegeben werden.' + en: '(optional) Id of referenced device, where Pushbullet app is running. Log in into http://www.pushbullet.com, select target device, copy the part of the browser URL behind "device_iden=" If not set, you have to use it in function calls.' + apikey: + type: str + mandatory: False + description: + de: '(optional) Persönlicher API Key für Pushbullet. Registrierung siehe https://docs.pushbullet.com/. Wenn der Key nicht gesetzt ist, muss er expizit in Funktionsaufrufen gesetzt werden.' + en: '(optional) Your own personal API key for Pushbullet. For your own key refer to https://docs.pushbullet.com/. If key is not set, you have to use it in function calls.' + file: + type: 'str | bool' + description: + de: "Sendet eine Datei an Pushbullet." + en: "Sends a file to pushbullet." + parameters: + filepath: + type: str + mandatory: True + description: + de: "Pfad der Datei." + en: "Path of the file." + deviceid: + type: str + mandatory: False + description: + de: '(optional) Id des anzusprechenden Geräts, wo eine Pushbullet App läuft. Auf http://www.pushbullet.com einloggen, Gerät auswählen und den Teil der URL kopieren, der hinter "device_iden=" kommt. Falls nicht gesetzt, muss der Wert explizit in Funktionsaufrufen als Parameter angegeben werden.' + en: '(optional) Id of referenced device, where Pushbullet app is running. Log in into http://www.pushbullet.com, select target device, copy the part of the browser URL behind "device_iden=" If not set, you have to use it in function calls.' + apikey: + type: str + mandatory: False + description: + de: '(optional) Persönlicher API Key für Pushbullet. Registrierung siehe https://docs.pushbullet.com/. Wenn der Key nicht gesetzt ist, muss er expizit in Funktionsaufrufen gesetzt werden.' + en: '(optional) Your own personal API key for Pushbullet. For your own key refer to https://docs.pushbullet.com/. If key is not set, you have to use it in function calls.' + body: + type: str + mandatory: False + description: + de: "Inhalt der Nachricht." + en: "Body of the note." \ No newline at end of file From 82f6b75b8fe74112036bac63cb55555210386aac Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sat, 3 Nov 2018 13:15:21 +0100 Subject: [PATCH 399/705] Pushbullet: added meta information --- pushbullet/plugin.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pushbullet/plugin.yaml b/pushbullet/plugin.yaml index cf1dbb49d..5063b199f 100755 --- a/pushbullet/plugin.yaml +++ b/pushbullet/plugin.yaml @@ -7,9 +7,9 @@ plugin: en: '' maintainer: '? (lbernau)' tester: onkelandy, psilo909, Sandman60 -# keywords: iot xyz -# documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page -# support: https://knx-user-forum.de/forum/supportforen/smarthome-py + keywords: messaging + documentation: https://www.smarthomeng.de/developer/plugins/pushbullet/README.html + support: https://knx-user-forum.de/forum/supportforen/smarthome-py/36001-neues-plugin-pushbullet/page8 version: 1.5.2 # Plugin version sh_minversion: 1.5 # minimum shNG version to use this plugin From 35b719656d0dc02ab7d70bba254485603e2b8706 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sat, 3 Nov 2018 13:16:49 +0100 Subject: [PATCH 400/705] Pushbullet: removed page8 --- pushbullet/plugin.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pushbullet/plugin.yaml b/pushbullet/plugin.yaml index 5063b199f..60aa892b9 100755 --- a/pushbullet/plugin.yaml +++ b/pushbullet/plugin.yaml @@ -9,7 +9,7 @@ plugin: tester: onkelandy, psilo909, Sandman60 keywords: messaging documentation: https://www.smarthomeng.de/developer/plugins/pushbullet/README.html - support: https://knx-user-forum.de/forum/supportforen/smarthome-py/36001-neues-plugin-pushbullet/page8 + support: https://knx-user-forum.de/forum/supportforen/smarthome-py/36001-neues-plugin-pushbullet version: 1.5.2 # Plugin version sh_minversion: 1.5 # minimum shNG version to use this plugin From 95be1cd4ec49a3e0d1a9e95e7e7c2df5968cd4a4 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sat, 3 Nov 2018 13:25:29 +0100 Subject: [PATCH 401/705] Withings Health: added missing return and style (in web if) --- withings_health/__init__.py | 1 + withings_health/webif/templates/index.html | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/withings_health/__init__.py b/withings_health/__init__.py index 34b0849b0..8e8bc75f2 100644 --- a/withings_health/__init__.py +++ b/withings_health/__init__.py @@ -137,6 +137,7 @@ def _update(self): "Plugin '{}': Token is expired, run OAuth2 again from Web Interface (Expiry Date: {}).".format( self.get_fullname(), datetime.datetime.fromtimestamp(self.get_item( 'token_expiry')(), tz=self.shtime.tzinfo()).strftime('%d.%m.%Y %H:%M:%S'))) + return else: self.logger.error( "Plugin '{}': Items for OAuth2 Data are not set with required values. Please run process via WebGUI of the plugin.".format( diff --git a/withings_health/webif/templates/index.html b/withings_health/webif/templates/index.html index 947e06e36..9c04c73e3 100644 --- a/withings_health/webif/templates/index.html +++ b/withings_health/webif/templates/index.html @@ -75,7 +75,7 @@
{{ _('Withings Health Items') }} ({{ p.get_items()|length }})
{{ item._path }} {{ item._type }} {{ key }} 0 and token_expiry < now %}color: red; font-weight: bold;"{% endif %}>{{ item() }} {% if key == 'token_expiry' %}{% if p.get_item('token_expiry')() > 0 %}({% if language == 'en' %}{{ token_expiry.strftime('%m/%d/%Y %H:%M:%S') }}{% else %}{{ token_expiry.strftime('%d.%m.%Y %H:%M:%S') }}{% endif %}){% endif %}{% endif %} 0 and token_expiry < now %}style="color: red; font-weight: bold;"{% endif %}>{{ item() }} {% if key == 'token_expiry' %}{% if p.get_item('token_expiry')() > 0 %}({% if language == 'en' %}{{ token_expiry.strftime('%m/%d/%Y %H:%M:%S') }}{% else %}{{ token_expiry.strftime('%d.%m.%Y %H:%M:%S') }}{% endif %}){% endif %}{% endif %} {% if language == 'en' %}{{ item.last_update().strftime('%m/%d/%Y %H:%M:%S') }}{% else %}{{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }}{% endif %} {% if language == 'en' %}{{ item.last_change().strftime('%m/%d/%Y %H:%M:%S') }}{% else %}{{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }}{% endif %}
@@ -60,6 +62,13 @@ {% endblock %} {% block bodytab2 %} +
    + {% for function in p.metadata.get_plugin_function_defstrings(with_type=True, with_default=True) %} +
  • {{ function }}
  • + {% endfor %} +
+{% endblock %} +{% block bodytab3 %} {% if p._call_monitor %}
@@ -138,5 +147,4 @@ {% endif %} - {% endblock %} From 07e694670f9ad7cf04ef1c9c74bcd06c92f17938 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 16 Nov 2018 17:25:03 +0100 Subject: [PATCH 417/705] Nuki: added check for empty responses --- nuki/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nuki/__init__.py b/nuki/__init__.py index 195a84981..53e368efe 100644 --- a/nuki/__init__.py +++ b/nuki/__init__.py @@ -272,6 +272,9 @@ def _get_nuki_status(self): for nuki_id in paired_nukis: response = self._api_call(self._base_url, endpoint='lockState', nuki_id=nuki_id, token=self._token, no_wait=self._noWait) + if response is None: + self.logger.info("Plugin '{}': Getting Nuki status ... Response is None.".format(self.get_shortname())) + return Nuki.update_lock_state(nuki_id, response) def _api_call(self, base_url, endpoint=None, nuki_id=None, token=None, action=None, no_wait=None, callback_url=None, From fabba93e87150460e72b121ec162a98574d52c37 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 16 Nov 2018 17:29:27 +0100 Subject: [PATCH 418/705] AVM: some more styling --- avm/webif/templates/index.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/avm/webif/templates/index.html b/avm/webif/templates/index.html index e2d3291d2..17a12bfdb 100644 --- a/avm/webif/templates/index.html +++ b/avm/webif/templates/index.html @@ -62,11 +62,13 @@ {% endblock %} {% block bodytab2 %} +
    {% for function in p.metadata.get_plugin_function_defstrings(with_type=True, with_default=True) %}
  • {{ function }}
  • {% endfor %}
+
{% endblock %} {% block bodytab3 %} {% if p._call_monitor %} From 2cbd22280756edada7f6c594e691e03cf0a955e3 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sat, 17 Nov 2018 10:55:23 +0100 Subject: [PATCH 419/705] AVM: adjusted padding and margin in web api --- avm/webif/templates/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/avm/webif/templates/index.html b/avm/webif/templates/index.html index 17a12bfdb..b023c20e8 100644 --- a/avm/webif/templates/index.html +++ b/avm/webif/templates/index.html @@ -65,7 +65,7 @@
    {% for function in p.metadata.get_plugin_function_defstrings(with_type=True, with_default=True) %} -
  • {{ function }}
  • +
  • {{ function }}
  • {% endfor %}
From 9f0fae518847ab2ac8170a3901bff707a5fed27e Mon Sep 17 00:00:00 2001 From: msinn Date: Sat, 17 Nov 2018 13:07:36 +0100 Subject: [PATCH 420/705] hue: Fixed function authorize (adopted revised hue API) --- hue/__init__.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hue/__init__.py b/hue/__init__.py index 15375b33c..ffd4a1a02 100755 --- a/hue/__init__.py +++ b/hue/__init__.py @@ -771,6 +771,7 @@ def _update_bridges(self): self._hueLock.release() numberBridgeId = numberBridgeId + 1 + def get_config(self, hueBridgeId='0'): # hier eine interaktive routing für di ecli, um den user herauszubekommen, # mit dem die szenen gesetzt worden sind, um ihn dann als user für das plugin einzusetzen @@ -781,9 +782,10 @@ def get_config(self, hueBridgeId='0'): self.logger.warning('get_config: Groups {0}'.format(returnValues)) return returnValues + def authorizeuser(self, hueBridgeId='0'): data = json.dumps( - {"devicetype": "smarthome", "username": self._hue_user[int(hueBridgeId)]}) + {"devicetype": "smarthome#" + self._hue_user[int(hueBridgeId)]}) con = http.client.HTTPConnection(self._hue_ip[int(hueBridgeId)]) con.request("POST", "/api", data) resp = con.getresponse() @@ -791,7 +793,7 @@ def authorizeuser(self, hueBridgeId='0'): if resp.status != 200: self.logger.error('authorize: Authenticate request failed') return "Authenticate request failed" - resp = resp.read() + resp = resp.read().decode('utf-8') self.logger.debug(resp) resp = json.loads(resp) self.logger.debug(resp) From 87ba3c113cfe8762b1ba9f16e3bea61b2b1e15a5 Mon Sep 17 00:00:00 2001 From: msinn Date: Sat, 17 Nov 2018 13:09:37 +0100 Subject: [PATCH 421/705] hue: Adjusted plugin version --- hue/__init__.py | 2 +- hue/plugin.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hue/__init__.py b/hue/__init__.py index ffd4a1a02..f3a397d3d 100755 --- a/hue/__init__.py +++ b/hue/__init__.py @@ -56,7 +56,7 @@ class HUE(SmartPlugin): - PLUGIN_VERSION = "1.4.3" + PLUGIN_VERSION = "1.4.4" def __init__(self, smarthome, hue_ip = '', hue_user = '', hue_port = '80', cycle_lamps = '10', cycle_bridges = '60', default_transitionTime = '0.4'): diff --git a/hue/plugin.yaml b/hue/plugin.yaml index 1123cffaa..1cbfe03de 100755 --- a/hue/plugin.yaml +++ b/hue/plugin.yaml @@ -11,7 +11,7 @@ plugin: # documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/41379-philips-hue-plugin-neu-v1-0-released - version: 1.4.3 # Plugin version + version: 1.4.4 # Plugin version sh_minversion: 1.3c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False From 5b09293d9efb42bc48425ec97385de437c79c526 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sat, 17 Nov 2018 15:21:48 +0100 Subject: [PATCH 422/705] AVM: extended Webif display of API to show descriptions --- avm/__init__.py | 1 - avm/locale.yaml | 3 ++- avm/plugin.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/avm/__init__.py b/avm/__init__.py index 9968cddeb..8f56277c4 100644 --- a/avm/__init__.py +++ b/avm/__init__.py @@ -2051,7 +2051,6 @@ def init_webinterface(self): import cherrypy - class WebInterface(SmartPluginWebIf): def __init__(self, webif_dir, plugin): diff --git a/avm/locale.yaml b/avm/locale.yaml index 2f0670309..f15475058 100755 --- a/avm/locale.yaml +++ b/avm/locale.yaml @@ -8,4 +8,5 @@ plugin_translations: 'Letztes Update': {'de': '=', 'en': 'Last Update', 'fr': ''} 'Letzter Change': {'de': '=', 'en': 'Last Change', 'fr': ''} 'Plugin-API': {'de': '=', 'en': 'Plugin API', 'fr': ''} - 'Call Monitor Items': {'de': '=', 'en': '=', 'fr': ''} \ No newline at end of file + 'Call Monitor Items': {'de': '=', 'en': '=', 'fr': ''} + 'Parameter': {'de': '=', 'en': 'Parameters', 'fr': ''} \ No newline at end of file diff --git a/avm/plugin.yaml b/avm/plugin.yaml index e132c0400..0c4ba503f 100755 --- a/avm/plugin.yaml +++ b/avm/plugin.yaml @@ -193,7 +193,7 @@ plugin_functions: start_call: type: void description: - de: "Startet einen anruf an eine übergebene Telefonnummer (intern oder extern)." + de: "Startet einen Anruf an eine übergebene Telefonnummer (intern oder extern)." en: "Starts a call for a given phone number (internal or external)." parameters: phone_number: From 4261615633857ab53f9c3e22a810191b710e2579 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sat, 17 Nov 2018 15:22:27 +0100 Subject: [PATCH 423/705] AVM: added detail blocks --- avm/webif/templates/index.html | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/avm/webif/templates/index.html b/avm/webif/templates/index.html index b023c20e8..f496b8e9f 100644 --- a/avm/webif/templates/index.html +++ b/avm/webif/templates/index.html @@ -63,11 +63,35 @@ {% endblock %} {% block bodytab2 %}
-
    - {% for function in p.metadata.get_plugin_function_defstrings(with_type=True, with_default=True) %} -
  • {{ function }}
  • + {% for function, dict in p.metadata.plugin_functions.items() %} +
    +
    + {{ dict['type'] }} {{ function }}({% if dict['parameters'] is not none %}{% for name, paramdict in dict['parameters'].items() %}{{ name }}: {{ paramdict['type'] }}{% endfor %}{% endif %}) +
    +
    + DE: {{ dict['description']['de'] }}
    + EN: {{ dict['description']['en'] }}
    + {% if dict['parameters'] is not none %} +
    +
    + {{ _('Parameter') }}: +
    +
    +
      + {% for name, paramdict in dict['parameters'].items() %} +
    • + {{ name }}: {{ paramdict['type'] }}
      + DE: {{ paramdict['description']['de'] }}
      + EN: {{ paramdict['description']['en'] }} +
    • + {% endfor %} +
    +
    +
    + {% endif %} +
    +
    {% endfor %} -
{% endblock %} {% block bodytab3 %} From 6c2a187f7311ce20955545be91f01a4f5cd6baf7 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sat, 17 Nov 2018 15:27:58 +0100 Subject: [PATCH 424/705] AVM: added spaces to plugin.yaml --- avm/plugin.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/avm/plugin.yaml b/avm/plugin.yaml index 0c4ba503f..e79599458 100755 --- a/avm/plugin.yaml +++ b/avm/plugin.yaml @@ -317,8 +317,8 @@ plugin_functions: get_calllist: type: list(dict(str)) description: - de: "Ermittelt ein Array mit dicts aller Einträge der Anrufliste (Attribute 'Id','Type','Caller','Called','CalledNumber','Name','Numbertype','Device','Port','Date','Duration' (some optional))." - en: "Returns an array of dicts with all calllist entries (attributes 'Id','Type','Caller','Called','CalledNumber','Name','Numbertype','Device','Port','Date','Duration' (some optional))." + de: "Ermittelt ein Array mit dicts aller Einträge der Anrufliste (Attribute 'Id', 'Type', 'Caller', 'Called', 'CalledNumber', 'Name', 'Numbertype', 'Device', 'Port', 'Date',' Duration' (einige optional))." + en: "Returns an array of dicts with all calllist entries (attributes 'Id', 'Type', 'Caller', 'Called', 'CalledNumber', 'Name', 'Numbertype', 'Device', 'Port', 'Date', 'Duration' (some optional))." parameters: filter_incoming: type: str From df228b257f6be652f8f7bc921f475201288d64b6 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sat, 17 Nov 2018 16:07:48 +0100 Subject: [PATCH 425/705] AVM: description in configured language (de and en possible) --- avm/__init__.py | 1 + avm/plugin.yaml | 4 ++-- avm/webif/templates/index.html | 21 ++++++++++++--------- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/avm/__init__.py b/avm/__init__.py index 8f56277c4..bcc2bb180 100644 --- a/avm/__init__.py +++ b/avm/__init__.py @@ -540,6 +540,7 @@ def __init__(self, sh, *args, **kwargs): self._call_monitor_incoming_filter = self.get_parameter_value('call_monitor_incoming_filter') self._cycle = int(self.get_parameter_value('cycle')) + self._sh = sh # Response Cache: Dictionary for storing the result of requests which is used for several different items, refreshed each update cycle. Please use distinct keys! self._response_cache = dict() self._calllist_cache = [] diff --git a/avm/plugin.yaml b/avm/plugin.yaml index e79599458..422859ab9 100755 --- a/avm/plugin.yaml +++ b/avm/plugin.yaml @@ -213,8 +213,8 @@ plugin_functions: set_call_origin: type: void description: - de: "Setzt den 'call origin', bspw. vor dem Aufruf von 'start_call'" - en: "Sets the 'call origin', e.g. before running 'start_call'" + de: "Setzt den 'call origin', bspw. vor dem Aufruf von 'start_call'." + en: "Sets the 'call origin', e.g. before running 'start_call'." parameters: phone_name: type: mac diff --git a/avm/webif/templates/index.html b/avm/webif/templates/index.html index f496b8e9f..14a857089 100644 --- a/avm/webif/templates/index.html +++ b/avm/webif/templates/index.html @@ -2,6 +2,11 @@ {% set tab1title = _('AVM Items') %} {% set tab2title = _('Plugin-API') %} {% set tab3title = _('Call Monitor Items') %} +{% set language = p._sh.get_defaultlanguage() %} +{% if language not in ['en','de'] %} +{% set language = 'en' %} +{% endif %} + {% block headtable %}
@@ -65,24 +70,22 @@
{% for function, dict in p.metadata.plugin_functions.items() %}
-
+
{{ dict['type'] }} {{ function }}({% if dict['parameters'] is not none %}{% for name, paramdict in dict['parameters'].items() %}{{ name }}: {{ paramdict['type'] }}{% endfor %}{% endif %})
-
- DE: {{ dict['description']['de'] }}
- EN: {{ dict['description']['en'] }}
+
+ {{ dict['description'][language] }}
{% if dict['parameters'] is not none %}
-
+
{{ _('Parameter') }}:
-
+
    {% for name, paramdict in dict['parameters'].items() %} -
  • +
  • {{ name }}: {{ paramdict['type'] }}
    - DE: {{ paramdict['description']['de'] }}
    - EN: {{ paramdict['description']['en'] }} + {{ paramdict['description'][language] }}
  • {% endfor %}
From d5ab0edbb2ce3060c88de35f35f236358eddd6e3 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Fri, 23 Nov 2018 14:17:16 +0100 Subject: [PATCH 426/705] Nuki: added lock release to finally clause --- nuki/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nuki/__init__.py b/nuki/__init__.py index 53e368efe..147d48121 100644 --- a/nuki/__init__.py +++ b/nuki/__init__.py @@ -304,12 +304,12 @@ def _api_call(self, base_url, endpoint=None, nuki_id=None, token=None, action=No response = requests.get(url=urllib.parse.urljoin(base_url, endpoint), params=payload) self.logger.debug("Plugin '{}': finishing API Call to Nuki Bridge at {}.".format(self.get_shortname(), url)) response.raise_for_status() - lock = False - self.logger.debug("Plugin '{}': Lock removed.".format(self.get_shortname())) return json.loads(response.text) except Exception as ex: - lock = False self.logger.error(ex) + finally: + lock = False + self.logger.debug("Plugin '{}': Lock removed.".format(self.get_shortname())) def get_event_items(self): return nuki_event_items From 642f17607fe72f53fbe52f7a499479928937ad85 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sat, 24 Nov 2018 15:02:50 +0100 Subject: [PATCH 427/705] XMPP: Fix logger initialization by trying to setup again at later time Sometimes the plugin is not already configured and setup but a log message should be logged via XMPP. This patch will log a message initially when trying to setup the logger and will skip the message. When another message is logged the initialization is tried again and in case the plugin is then configured properly it will log via XMPP. --- xmpp/__init__.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/xmpp/__init__.py b/xmpp/__init__.py index d8e86706b..0f2367ed1 100755 --- a/xmpp/__init__.py +++ b/xmpp/__init__.py @@ -122,6 +122,8 @@ def send(self, to, msgsend, mt='chat'): class XMPPLogHandler(logging.Handler): + _errors = [] + def __init__(self, xmpp_plugin, xmpp_receiver, xmpp_receiver_type='chat'): logging.Handler.__init__(self) self._plugin = None @@ -130,15 +132,18 @@ def __init__(self, xmpp_plugin, xmpp_receiver, xmpp_receiver_type='chat'): self._xmpp_receiver_type = xmpp_receiver_type def emit(self, record): - if self._plugin is None: + if self._plugin is None and Plugins.get_instance() is not None: self._plugin = Plugins.get_instance().return_plugin(self._xmpp_plugin) if self._plugin is None: - logging.getLogger(__name__).error('Can not get XMPP plugin for {} - disabling XMPP logging!'.format(self._xmpp_plugin)) - self._plugin = False + if self._xmpp_plugin not in self._errors: + self._errors.append(self._xmpp_plugin) + logging.getLogger(__name__).error('Can not get plugin \'{}\' used to log messages via XMPP - trying later!'.format(self._xmpp_plugin)) + else: + logging.getLogger(__name__).error('Can not get XMPP plugin \'{}\' - trying again later!'.format(self._xmpp_plugin)) else: logging.getLogger(__name__).info('Configured XMPP logging using pluing {}'.format(self._xmpp_plugin)) - if self._plugin is not False: + if self._plugin is not None: self._plugin.send(self._xmpp_receiver, self.format(record), self._xmpp_receiver_type) From 359cf3120ff0a115359e928af8099bd06096ab11 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sat, 24 Nov 2018 16:38:13 +0100 Subject: [PATCH 428/705] Simulation: setting logged plugin version from class attribute --- simulation/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simulation/__init__.py b/simulation/__init__.py index 18dc34e75..a8124caae 100644 --- a/simulation/__init__.py +++ b/simulation/__init__.py @@ -52,7 +52,7 @@ class Simulation(SmartPlugin): def __init__(self, sh, *args, **kwargs): self.logger = logging.getLogger(__name__) - self.logger.info('Init Simulation release 1.5.0.6') + self.logger.info('Init Simulation release %s' % self.PLUGIN_VERSION) self.shtime = Shtime.get_instance() self._datafile = self.get_parameter_value('data_file') self.lastday = '' From 182b0487aa865d6e67d7bfe8855f1a15e89e91ca Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Wed, 28 Nov 2018 16:58:27 +0100 Subject: [PATCH 429/705] fixed response handling, updated webif --- avdevice/AVDeviceFunctions.py | 13 +++++-------- avdevice/__init__.py | 8 +++++++- avdevice/webif/templates/index.html | 29 ++++++++++++++++++++++++----- 3 files changed, 36 insertions(+), 14 deletions(-) diff --git a/avdevice/AVDeviceFunctions.py b/avdevice/AVDeviceFunctions.py index 17168c9e9..1c440b217 100755 --- a/avdevice/AVDeviceFunctions.py +++ b/avdevice/AVDeviceFunctions.py @@ -344,8 +344,8 @@ def __init__(self, commandinfo, reverseinfo, value, name, specialparse, logger): self.logger = logger self.logger.log(VERBOSE1, - "Creating Response {}: Create response command {}, reverse {}, value {}".format( - self._name, commandinfo, reverseinfo, value)) + "Creating Response {}: Create response command {} with expected response {}, reverse {} with expected response {}, value {}".format( + self._name, commandinfo, self._splitresponse, reverseinfo, self._splitreverse, value)) def _finalize(self, responselist, reverselist, func_type): replacedresponse = "|".join(responselist) @@ -406,7 +406,6 @@ def response_power(self): for splitre in self._splitresponse: valuelength = splitre.count('*') if valuelength > 0 or 'R' in self._commandinfo[5]: - responselist = [] if self._commandinfo[6].lower() in ['1', 'true', 'yes', 'on']: replacedvalue = '0' else: @@ -424,7 +423,6 @@ def response_standard(self): for splitre in self._splitresponse: valuelength = splitre.count('*') if valuelength > 0 or 'R' in self._commandinfo[5]: - responselist = [] replacedresponse = splitre.split('*')[0].strip() if splitre.count('?') == 1: replacedresponse = re.sub('[?]', '', replacedresponse) @@ -441,8 +439,6 @@ def response_in_decrease(self): for counting, splitre in enumerate(self._splitresponse): valuelength = reverselength = splitre.count('*') if valuelength > 0 or 'R' in self._commandinfo[5]: - responselist = [] - reverselist = [] replacedresponse = re.sub('[*]', '', splitre.strip()) if splitre.count('?') == 1: replacedresponse = re.sub('[?]', '', replacedresponse) @@ -472,9 +468,10 @@ def response_off(self): reverselist = [] for counting, splitre in enumerate(self._splitresponse): valuelength = reverselength = splitre.count('*') + self.logger.log(VERBOSE2, + "Response Off {}: valuelength: {}, splitre: {}".format( + self._name, valuelength, splitre)) if valuelength > 0 or 'R' in self._commandinfo[5]: - responselist = [] - reverselist = [] replacedreverse = '' replacedresponse = splitre.replace('*******', 'STANDBY') replacedresponse = replacedresponse.replace('*****', 'CLOSE') diff --git a/avdevice/__init__.py b/avdevice/__init__.py index a65018be0..12383f9e2 100755 --- a/avdevice/__init__.py +++ b/avdevice/__init__.py @@ -815,6 +815,8 @@ def _sortbuffer(buffer, bufferlist): def _clear_history(self, part): if part == 'keep': self._keep_commands.clear() + elif part == 'send': + self._send_commands[:] = [] else: self._send_history[part].clear() @@ -3063,6 +3065,7 @@ def index(self, action=None, item_id=None, item_path=None, reload=None): keep_cleared = False command_cleared = False query_cleared = False + send_cleared = False if action is not None: if action == "reload": self.plugin._initialize() @@ -3072,6 +3075,9 @@ def index(self, action=None, item_id=None, item_path=None, reload=None): if action == "clear_query_history": self.plugin._clear_history('query') query_cleared = True + if action == "clear_send": + self.plugin._clear_history('send') + send_cleared = True if action == "clear_command_history": self.plugin._clear_history('command') command_cleared = True @@ -3083,5 +3089,5 @@ def index(self, action=None, item_id=None, item_path=None, reload=None): # add values to be passed to the Jinja2 template eg: tmpl.render(p=self.plugin, interface=interface, ...) return tmpl.render(p=self.plugin, config_reloaded=config_reloaded, query_cleared=query_cleared, - command_cleared=command_cleared, keep_cleared=keep_cleared, + command_cleared=command_cleared, keep_cleared=keep_cleared, send_cleared=send_cleared, language=self.plugin._sh.get_defaultlanguage(), now=self.plugin.shtime.now()) diff --git a/avdevice/webif/templates/index.html b/avdevice/webif/templates/index.html index d5235f21f..60b1eb0ae 100755 --- a/avdevice/webif/templates/index.html +++ b/avdevice/webif/templates/index.html @@ -10,6 +10,9 @@ window.location.href = final; }; } +document.addEventListener("DOMContentLoaded", function() { + mainpage(); +}); {% endblock scripts %} @@ -98,7 +101,7 @@ Additional buttons for the web interface (if any are needed) - displayed below the headtable-section --> {% block buttons %} -{% if 1==1 %} + {% if config_reloaded %} @@ -110,7 +113,6 @@
{% endif %} -{% endif %} {% endblock %} {% block bodytab1 %} @@ -128,7 +130,7 @@ {% for item in p.init.get_items('zone0') %} - {% if p.has_iattr(item.conf, 'avdevice_zone0') %} + {% if p.has_iattr(item.conf, 'avdevice_zone0') or p.has_iattr(item.conf, 'avdevice') %}
@@ -138,7 +140,7 @@
{{ item._path }} {{ item() }}
{% else %}
- {{ _('Es sind keine Item in dieser Zone definiert.') }} + {{ _('Es sind keine Items in dieser Zone definiert.') }}
{% endif %} @@ -277,6 +279,23 @@ Sending Command {{ p._sendingcommand }} + + Commandlist + + + {% if command_cleared %} + + {% else %} + {{ p._send_commands }} + {% endif %} + + +
@@ -290,7 +309,7 @@
{% if item_count_zone1>0 %}
- {{ _('Die folgenden Items sind dieser Instanz des Database Plugins zugewiesen') }}: + {{ _('Die folgenden Items sind dieser Instanz des AVDevice Plugins zugewiesen') }}:
From 9b94e6c96e7139e94b688232f7900f8209a3c0cf Mon Sep 17 00:00:00 2001 From: msinn Date: Fri, 30 Nov 2018 20:48:41 +0100 Subject: [PATCH 430/705] mqtt: Adjustments to readme --- mqtt/README.md | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/mqtt/README.md b/mqtt/README.md index 08515a95a..6f18ddf15 100644 --- a/mqtt/README.md +++ b/mqtt/README.md @@ -192,7 +192,7 @@ path to certificate files Example configuration in yaml-format: ```yaml -alarm_in_ +alarm_in: # messages coming from the alarm panel # (called 'alarm/out' by the alarm panel) name: alarm_test_mqtt_in @@ -207,27 +207,7 @@ alarm_out: ``` -### Example: items.yaml -Example configuration in the old conf-format: - -``` -[[alarm_in_]] - # messages coming from the alarm panel - # (called 'alarm/out' by the alarm panel) - name = alarm_test_mqtt_in - type = foo - mqtt_topic_in = 'alarm/out' - -[[alarm_out]] - # messages published, to be read by the alarm panel - name = alarm_test_mqtt_out - type = foo - mqtt_topic_out = 'alarm/in' - -``` - - -Datatype foo delivers the raw data from the MQTT message to the item (as an array of bytes). +Datatype **foo** delivers the raw data from the MQTT message to the item (as an array of bytes). **NEW:** You can use any of the other datatypes. If you use any of those datatypes, the data from the mqtt message will be casted to the desired format. From f754280d0d8f96c0f7e4ebc9959d13f6a0889b58 Mon Sep 17 00:00:00 2001 From: jentz1986 Date: Tue, 11 Dec 2018 09:41:37 +0100 Subject: [PATCH 431/705] Update __init__.py --- avm/__init__.py | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/avm/__init__.py b/avm/__init__.py index bcc2bb180..500d82283 100644 --- a/avm/__init__.py +++ b/avm/__init__.py @@ -57,6 +57,7 @@ def __init__(self, host, port, callback, call_monitor_incoming_filter, plugin_in self._items_outgoing = [] # items for outgoing calls self._duration_item = dict() # 2 items, on for counting the incoming, one for counting the outgoing call duration self._call_active = dict() + self._listen_active = False self._call_active['incoming'] = False self._call_active['outgoing'] = False self._call_incoming_cid = dict() @@ -68,12 +69,17 @@ def connect(self): """ Connects to the call monitor of the AVM device """ + if self._listen_active: + self.logger.debug("MonitoringService: Connect called while listen active") + return + self.conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: self.conn.connect((self._host, self._port)) self._listen_thread = threading.Thread(target=self._listen, name="MonitoringService_{}".format( self._plugin_instance.get_fullname())).start() + self.logger.debug("MonitoringService: connection established") except Exception as e: self.conn = None self.logger.error("MonitoringService: Cannot connect to " + self._host + " on port: " + str( @@ -84,6 +90,7 @@ def disconnect(self): """ Disconnects from the call monitor of the AVM device """ + self.logger.debug("MonitoringService: disconnecting") self._listen_active = False self._stop_counter('incoming') self._stop_counter('outgoing') @@ -231,18 +238,22 @@ def _parse_line(self, line): self.logger.debug(line) line = line.split(";") - if line[1] == "RING": - call_from = line[3] - call_to = line[4] - self._trigger(call_from, call_to, line[0], line[2], line[1], '') - elif line[1] == "CALL": - call_from = line[4] - call_to = line[5] - self._trigger(call_from, call_to, line[0], line[2], line[1], line[3]) - elif line[1] == "CONNECT": - self._trigger('', '', line[0], line[2], line[1], line[3]) - elif line[1] == "DISCONNECT": - self._trigger('', '', '', line[2], line[1], '') + try: + if line[1] == "RING": + call_from = line[3] + call_to = line[4] + self._trigger(call_from, call_to, line[0], line[2], line[1], '') + elif line[1] == "CALL": + call_from = line[4] + call_to = line[5] + self._trigger(call_from, call_to, line[0], line[2], line[1], line[3]) + elif line[1] == "CONNECT": + self._trigger('', '', line[0], line[2], line[1], line[3]) + elif line[1] == "DISCONNECT": + self._trigger('', '', '', line[2], line[1], '') + except Exception as e: + self.logger.error("MonitoringService: " + type(e) + " while handling Callmonitor response: " + str(e)) + return def _trigger(self, call_from, call_to, time, callid, event, branch): """ @@ -637,6 +648,11 @@ def _update_loop(self): self._update_myfritz(item) # empty response cache self._response_cache = dict() + + if self._call_monitor: + if not self.alive: + return + self._monitoring_service.connect() def get_calllist_from_cache(self): """ @@ -1065,6 +1081,8 @@ def reboot(self): self._session.post(url, data=soap_data, timeout=self._timeout, headers=headers, auth=HTTPDigestAuth(self._fritz_device.get_user(), self._fritz_device.get_password()), verify=self._verify) + if self._call_monitor: + self._monitoring_service.disconnect() except Exception as e: self.logger.error("Exception when sending POST request: %s" % str(e)) return From 6e3eb49b650f35e38cd3d9cfabd26767b5dd99a6 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Tue, 11 Dec 2018 19:49:12 +0100 Subject: [PATCH 432/705] Added aerosilent exos --- drexelundweiss/README.md | 8 ++ drexelundweiss/__init__.py | 4 +- drexelundweiss/aerosilent_exos.txt | 148 +++++++++++++++++++++++++++++ drexelundweiss/plugin.yaml | 4 +- 4 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 drexelundweiss/aerosilent_exos.txt diff --git a/drexelundweiss/README.md b/drexelundweiss/README.md index 634d0dcfe..1620e2d82 100644 --- a/drexelundweiss/README.md +++ b/drexelundweiss/README.md @@ -4,6 +4,13 @@ This plugin uses the D&W USB service interface for connection, so you don't need ## Changelog +1.5.2: +* Added aerosilent exos +* Updated README + +1.5.1: +* Adapted plugin to use newer functions and logging parameters + 1.3.0: * Ignore wrong device info and use backup device id (set correct number for your DuW device from list below) * Retry reading lines to prevent wrong data (set value in conf file) @@ -21,6 +28,7 @@ The plugin detects the connected device type automatically: * aerosilent bianco: 13 * aerosilent business: 15 * aerosilent centro: 8 + * aerosilent exos: 25 * aerosilent micro: 3 * aerosilent primus: 1 * aerosilent stratos: 17 diff --git a/drexelundweiss/__init__.py b/drexelundweiss/__init__.py index dd8cf2d10..b9106782c 100755 --- a/drexelundweiss/__init__.py +++ b/drexelundweiss/__init__.py @@ -38,7 +38,7 @@ class DuW(SmartPlugin): ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.5.1" + PLUGIN_VERSION = "1.5.2" def __init__(self, smarthome): self._name = self.get_fullname() @@ -95,6 +95,8 @@ def __init__(self, smarthome): smarthome.base_dir + '/plugins/drexelundweiss/aerosilent_business.txt'} self.devl[17] = {'device': 'aerosilent stratos', 'cmdpath': smarthome.base_dir + '/plugins/drexelundweiss/aerosilent_stratos.txt'} + self.devl[25] = {'device': 'aerosilent exos', 'cmdpath': + smarthome.base_dir + '/plugins/drexelundweiss/aerosilent_exos.txt'} except Exception as err: self.logger.error("Error on init {}.".format(err)) self._init_complete = False diff --git a/drexelundweiss/aerosilent_exos.txt b/drexelundweiss/aerosilent_exos.txt new file mode 100644 index 000000000..9ef3876a9 --- /dev/null +++ b/drexelundweiss/aerosilent_exos.txt @@ -0,0 +1,148 @@ +;;;;;;; +5328;Absenkung der Lüfterstufe 1;30;70;1;0;R/W;LU +1066;Aktive Lüfterstufe;0;4;1;0;R;LU +1444;Anforderung Brand;0;1;1;0;R/W;LU +1292;Anforderung der Ventilatoren durch Wärmepumpe;0;1;1;0;R;LU +1336;Anforderung der Ventilatoren durch Zonenregelung;0;1;1;0;R;LU +1338;Anforderung Disbalance (Boilerüberwärmung);0;1;1;0;R;LU +1356;Anforderung LST3 Feuchte;0;1;1;0;R;LU +1450;Anforderung Nachtkühlung;0;1;1;0;R;LU +1218;Anforderung: Beschattung;0;1;1;0;R;LU +1216;Anforderung: Bypassklappe;0;1;1;0;R;LU +1462;Anforderung: Extern-Heizstufe 2;0;1;1;0;R;LU +228;Anforderung: LST3_EXT;0;1;1;0;R;LU +1032;Anforderung: Raum-Heizstufe ;0;1;1;0;R;LU +1034;Anforderung: Raum-Heizstufe 2;0;1;1;0;R;LU +1198;Anforderung: Sole für Außenlufterwärmung;0;1;1;0;R;LU +1322;Anforderung: Sommerautomatik;0;1;1;0;R;LU +1422;Anforderung: Sperre Venti bei Abtauen;0;1;1;0;R;LU +202;Außenluft;-28000;100000;100;1;R;LU +5304;Außenluftfühler vorhanden?;0;1;1;0;R;LU +286;Außentemp.;-28000;100000;100;1;R;LU +1412;Außentemperatur (gedämpft);-50000000;50000000;100000;1;R;LU +5668;Außentemperatur Nachtauskühlung;5000;20000;100;1;R/W;LU +5632;Außentemperatur vorhanden;0;1;1;0;R;LU +5336;Beschattungsfunktion;0;1;1;0;R;LU +5002;Betriebsar;0;7;1;0;R/W;LU +1300;Betriebsart Sommerautomatik;0;2;1;0;R;LU +902;Betriebsstunden: Abluftventilator;0;600000000;60;0;R;LU +964;Betriebsstunden: Beschattung;0;600000000;60;0;R;LU +932;Betriebsstunden: Bypassklappe;0;600000000;60;0;R;LU +928;Betriebsstunden: Feinstaubfilter;0;600000000;60;0;R;LU +940;Betriebsstunden: Frostschutzeinrichtung;0;600000000;60;0;R;LU +926;Betriebsstunden: Grobstaubfilter;0;600000000;60;0;R;LU +912;Betriebsstunden: Heizstufe 1;0;600000000;60;0;R;LU +914;Betriebsstunden: Heizstufe 2;0;600000000;60;0;R;LU +962;Betriebsstunden: Lüfterstufe 0;0;600000000;60;0;R;LU +904;Betriebsstunden: Lüfterstufe 1;0;600000000;60;0;R;LU +906;Betriebsstunden: Lüfterstufe 2;0;600000000;60;0;R;LU +908;Betriebsstunden: Lüfterstufe 3;0;600000000;60;0;R;LU +944;Betriebsstunden: Reduzierte Lüfterstufe;0;600000000;60;0;R;LU +970;Betriebsstunden: Sole-Kreis Außenluft;0;600000000;60;0;R;LU +900;Betriebsstunden: Zuluftventilator;0;600000000;60;0;R;LU +838;Brandmeldealarm;0;1;1;0;R;LU +5068;Brandmeldeanlage vorhanden?;0;1;1;0;R;LU +230;CO2;100;1950;1;0;R;LU +1048;CO2-Messung;0;1;1;0;R/W;LU +5054;CO2-Sensor vorhanden?;0;1;1;0;R;LU +5210;Datum;0;99999999;1;0;R/W;LU +5020;Drehzahl Abluftventilator;0;10000;100;0;R/W;LU +1094;Drehzahl Abluftventilator;0;10000;100;0;R;LU +1092;Drehzahl Zuluftventilator;0;10000;100;0;R;LU +5018;Drehzahl Zuluftventilator;0;10000;100;0;R/W;LU +1232;Druckdifferenz Abluft;0;5000;1;1;R;LU +1230;Druckdifferenz Zuluft;0;5000;1;1;R;LU +5330;Erhöhung der Lüfterstufe 3;30;100;1;0;R/W;LU +5034;Feinstaubfilter vorhanden?;0;1;1;0;R;LU +1042;Feinstaubfilter wechseln!;0;127;1;0;R;LU +7004;Feinstaubfilter wechseln!;0;1;1;0;R;LU +5032;Feinstaubfilter: Standzeit;131400;1051200;60;0;R;LU +5384;Funktion "Sommerautomatik";0;1;1;0;R;LU +5492;Funktion HEIZUNG+;0;1;1;0;R/W;LU +5000;Gerätetyp;1;92;1;0;R;LU +946;Gesamt beförderte Kubikmeter;0;600000000;1;0;R;LU +960;Gesamt beförderte Luftmenge seit Filterwechsel;0;600000000;1;0;R;LU +5360;Grenztemperatur für Vereisungsschutz;-40000;-8000;1000;0;R/W;LU +5154;Grobstaubfilter vorhanden?;0;1;0;0;R;LU +7002;Grobstaubfilter wechseln!;0;1;1;0;R;LU +1040;Grobstaubfilter wechseln!;0;127;1;0;R;LU +5164;Grobstaubfilter: Betriebsart Filterüberwachung;1;3;1;0;R;LU +5166;Grobstaubfilter: Maximales Fördervolumen;100000;1500000;1;0;R;LU +5030;Grobstaubfilter: Standzeit;131400;1051200;60;0;R;LU +1178;Hardwaretype;1;6;1;0;R;LU +5672;Hysterese Nachtauskühlung Außenluft;2000;5000;100;1;R/W;LU +5676;Hysterese Nachtauskühlung Differenz Raum außen;1000;5000;100;1;R/W;LU +5670;Hysterese Nachtauskühlung Raum;2000;5000;100;1;R/W;LU +7000;Information;0;2147483647;1;0;R;LU +1186;Ist-Drehzahl Abluftventilator;0;5000;1;0;R;LU +1184;Ist-Drehzahl Zuluftventilator;0;5000;1;0;R;LU +1240;Ist-Volumenstrom Abluft;0;1000;1;0;R;LU +1238;Ist-Volumenstrom Zuluft;0;1000;1;0;R;LU +238;Kontakt: Brandmeldealarm;0;1;1;0;R;LU +5192;Kühlung vorhanden?;0;1;1;0;R;LU +5270;Maximal zulässige Drehzahl Abluftventilator;1500;6000;1;0;R/W;LU +5268;Maximal zulässige Drehzahl Zuluftventilator;1500;6000;1;0;R/W;LU +5530;Minimale Drehzahl Abluftventilator;0;10000;100;0;R/W;LU +5528;Minimale Drehzahl Zuluftventilator;0;10000;100;0;R/W;LU +5674;Nachtauskühlung Differenz Raum zu Außenluft;2000;10000;100;1;R/W;LU +5678;Nachtauskühlung vorhanden;0;1;1;0;R;LU +5168;Pelletofen vorhanden?;0;1;1;0;R;LU +5282;Pelletofen: Anlaufverzögerung;1;60;1;0;R;LU +5284;Pelletofen: Mindestlaufzeit;1;60;1;0;R;LU +200;Raum;-28000;100000;100;1;R/W;LU +282;Raumfeuchte;500;100000;100;1;R/W;LU +5558;Raumfeuchte Vorhanden;0;1;1;0;R;LU +5016;Raum-Soll;14000;26000;100;1;R/W;LU +5666;Raumsollwert Nachtauskühlung;18000;28000;100;1;R/W;LU +5338;Raumtemperatur: Beschattung;20000;26000;100;1;R/W;LU +252;Relaiskontakt: EXT (LU);0;1;1;0;R;LU +226;Revisionstüre;0;1;1;0;R;LU +1084;Soll-Volumenstrom Abluft;0;1000;1;0;R;LU +5060;Soll-Volumenstrom Lüfterstufe 2;40;600;1;0;R/W;LU +1082;Soll-Volumenstrom Zuluft;0;1000;1;0;R;LU +5496;Sollwert-Erhöhung Funktion HEIZUNG+;300;2000;100;1;R/W;LU +5390;Sommerautomatik Schaltpunkt 1 Zuluftbetrieb;0;2400;1;0;R/W;LU +5392;Sommerautomatik Schaltpunkt 2 Normalbetrieb;0;2400;1;0;R/W;LU +5394;Sommerautomatik Schaltpunkt 3 Abluftbetrieb;0;2400;1;0;R/W;LU +5396;Sommerautomatik Schaltpunkt 4 Normalbetrieb;0;2400;1;0;R/W;LU +826;Störung: Abluftventilator;0;1;1;0;R;LU +832;Störung: CO2-Sensor;0;1;1;0;R;LU +7544;Störung: Fühler Außentemperatur;0;1;1;0;R;LU +7564;Störung: Fühler Außentemperatur Timeout;0;1;1;0;R;LU +806;Störung: Temperaturfühler Außenluft;0;1;1;0;R;LU +804;Störung: Temperaturfühler Raum;0;1;1;0;R;LU +7504;Störung: Temperaturfühler Sole Außenluft;0;1;1;0;R;LU +840;Störung: Wert nicht zulässig;0;3;1;0;R;LU +824;Störung: Zuluftventilator;0;1;1;0;R;LU +800;Summenstörung;0;2147483647;1;0;R;LU +7500;Summenstörung 2;0;2147483647;1;0;R;LU +7566;Summenstörung 3;0;2147483647;1;0;R;LU +1156;SW-Version;0;1000000;1;0;R;LU +1174;Tag;1;7;1;0;R;LU +5340;Temperatur Außenluft: Beschattung;12000;22000;100;1;R/W;LU +5452;Temperatur Außenluft: Bypass Kühlung Aus (Bypass öffnen);20000;35000;1000;0;R/W;LU +5450;Temperatur Außenluft: Bypass Kühlung Ein (Bypass schliessen);20000;35000;1000;0;R/W;LU +5084;Temperatur Außenluft: Bypass öffnen;10000;20000;1000;0;R/W;LU +5086;Temperatur Außenluft: Bypass schließen;10000;20000;1000;0;R/W;LU +5206;Temperatur Außenluft: Frostschutz;-5000;0;100;1;R/W;LU +5090;Temperatur Außenluft: Frostschutz aus;-10000;5000;1000;0;R/W;LU +5088;Temperatur Außenluft: Frostschutz ein;-10000;5000;1000;0;R/W;LU +5200;Temperatur Außenluft: Kühlung aus;16000;22000;1000;0;R/W;LU +5198;Temperatur Außenluft: Kühlung ein;17000;23000;1000;0;R/W;LU +5422;Temperatur Außenluft: Reduktion Luftmenge 10%;-20000;0;100;1;R/W;LU +5424;Temperatur Außenluft: Reduktion Luftmenge 20%;-30000;-10000;100;1;R/W;LU +5386;Temperatur Außenluft: Sommerautomatik aktivieren;10000;19000;1000;0;R/W;LU +5388;Temperatur Außenluft: Sommerautomatik deaktivieren;20000;30000;1000;0;R/W;LU +206;Temperatur: Sole nach Außenluftvorwärmung;-28000;100000;100;1;R;LU +7508;Time-Out: Solltemperatur Raum;0;1;1;0;R;LU +7506;Time-Out: Temperaturfühler Raum;0;1;1;0;R;LU +5212;Uhrzeit;0;235959;1;0;R/W;LU +5442;Uhrzeit und Datum verschicken;0;1;1;0;R;LU +1294;Vereisungsschutz;0;1;1;0;R;LU +5026;Volumenstrombalance Zuluft - Abluft;-50;30;1;0;R/W;LU +1044;Wärmepumpe;0;1;1;0;R;LU +1358;Zeitprogramm Lüftung;0;3;1;0;R/W;LU +1360;Zeitprogramm Lüftung + CO2;0;4;1;0;R/W;LU +1448;Zeitprogramm Nachtkühlung;0;1;1;0;R/W;LU +5494;Zeitspanne Funktion HEIZUNG+;1800;14400;60;0;R/W;LU +5038;Zeitspanne Funktion PARTY;600;14400;60;0;R/W;LU diff --git a/drexelundweiss/plugin.yaml b/drexelundweiss/plugin.yaml index e092a086c..466dc1464 100755 --- a/drexelundweiss/plugin.yaml +++ b/drexelundweiss/plugin.yaml @@ -11,7 +11,7 @@ plugin: # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/34582-drexel-weiss-plugin - version: 1.5.1 # Plugin version + version: 1.5.2 # Plugin version sh_minversion: 1.5 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance @@ -73,4 +73,4 @@ item_attributes: type: int description: de: 'Register für Lüftung entsprechend Textdatei' - en: 'Register for ventilation based on text file' + en: 'Register for ventilation based on text file' From ed806e9ab97ac38a034a13f82b506892569e97cd Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Wed, 12 Dec 2018 19:49:33 +0100 Subject: [PATCH 433/705] stateengine: fixed docu full example --- stateengine/webif/templates/doku15.html | 32 ++++++++++++------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/stateengine/webif/templates/doku15.html b/stateengine/webif/templates/doku15.html index 04a1a9015..f51bf04a0 100755 --- a/stateengine/webif/templates/doku15.html +++ b/stateengine/webif/templates/doku15.html @@ -111,25 +111,25 @@

Items zum Prüfen

gt43k: type: bool - name: Flag: Helligkeit größer als 43 kLux + name: Flag Helligkeit größer als 43 kLux eval: sh.beispiel.wetterstation.helligkeit() > 43000 eval_trigger beispiel.wetterstation.helligkeit gt35k: type: bool - name: Flag: Helligkeit größer als 35 kLux + name: Flag Helligkeit größer als 35 kLux eval: sh.beispiel.wetterstation.helligkeit() > 35000 eval_trigger beispiel.wetterstation.helligkeit gt25k: type: bool - name: Flag: Helligkeit größer als 25 kLux + name: Flag Helligkeit größer als 25 kLux eval: sh.beispiel.wetterstation.helligkeit() > 25000 eval_trigger beispiel.wetterstation.helligkeit gt20k: type: bool - name: Flag: Helligkeit größer als 20 kLux + name: Flag Helligkeit größer als 20 kLux eval: sh.beispiel.wetterstation.helligkeit() > 20000 eval_trigger beispiel.wetterstation.helligkeit @@ -312,8 +312,8 @@

Default-Konfiguration

# Einstieg in "Nacht": Wenn enter: # - es zwischen 16:00 und 08:00 Uhr ist - se_min_time: 08:00 - se_max_time: 16:00 + se_min_time: '08:00' + se_max_time: '16:00' se_negate_time: True # - die Helligkeit höchstens 90 Lux beträgt se_max_brightness: 90 @@ -336,8 +336,8 @@

Default-Konfiguration

se_min_brightness: 90 se_max_brightness: 250 # - es zwischen 00:00 und 12:00 Uhr ist - se_min_time: 00:00 - se_max_time: 12:00 + se_min_time: '00:00' + se_max_time: '12:00' # Zustand "Abends" Abends: @@ -357,8 +357,8 @@

Default-Konfiguration

se_min_brightness: 90 se_max_brightness: 250 # - es zwischen 12:00 und 24:00 Uhr ist - se_min_time: 12:00 - se_max_time: 24:00 + se_min_time: '12:00' + se_max_time: '24:00' # Anmerkung: "24:00" ist eigentlich eine ungültige Zeit. Sie wird aber automatisch zu 23:59:59 umgewandelt # Zustand "Tag" @@ -376,8 +376,8 @@

Default-Konfiguration

# Einstieg in "Tag": Wenn enter: # - es zwischen 06:30 und 21:30 Uhr ist - se_min_time: 06:30 - se_max_time: 21:30 + se_min_time: '06:30' + se_max_time: '21:30'

Automatisierung Raffstore 1

@@ -654,8 +654,8 @@

Automatisierung Raffstore 2

enter_schlafenszeit_woche: # Einstieg in "Nacht": Wenn # - es zwischen 21:00 und 07:00 Uhr ist - se_min_time: 07:00 - se_max_time: 21:00 + se_min_time: '07:00' + se_max_time: '21:00' se_negate_time: True # - der Wochentag zwischen Montag und Freitag liegt se_min_weekday: 0 @@ -664,8 +664,8 @@

Automatisierung Raffstore 2

enter_schlafenszeit_wochenende: # Einstieg in "Nacht": Wenn # - es zwischen 21:00 und 08:30 Uhr ist - se_min_time: 08:30 - se_max_time: 21:00 + se_min_time: '08:30' + se_max_time: '21:00' se_negate_time: True # - der Wochentag Samstag oder Sonntag ist se_value_weekday: 5 | 6 From ae6dee9c31a39365bdde96c3b04941223a1f9630 Mon Sep 17 00:00:00 2001 From: msinn Date: Thu, 13 Dec 2018 16:46:45 +0100 Subject: [PATCH 434/705] Several plugins: changes to metadata --- avdevice/plugin.yaml | 2 +- avm/plugin.yaml | 2 +- backend/plugin.yaml | 2 +- cli/plugin.yaml | 2 +- database/plugin.yaml | 2 +- dlms/plugin.yaml | 2 +- enigma2/plugin.yaml | 2 +- homematic/plugin.yaml | 2 +- knx/plugin.yaml | 2 +- mqtt/plugin.yaml | 2 +- openweathermap/plugin.yaml | 2 +- visu_smartvisu/plugin.yaml | 2 +- visu_websocket/plugin.yaml | 2 +- webservices/plugin.yaml | 1 + wunderground/plugin.yaml | 2 +- 15 files changed, 15 insertions(+), 14 deletions(-) diff --git a/avdevice/plugin.yaml b/avdevice/plugin.yaml index 63d66b710..389c15c81 100755 --- a/avdevice/plugin.yaml +++ b/avdevice/plugin.yaml @@ -10,7 +10,7 @@ plugin: state: develop keywords: av denon pioneer epson oppo player amp receiver projector rs232 telnet tcpip -# documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page +# documentation: http://smarthomeng.de/user/plugins/avdevice/user_doc.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1097870-neues-plugin-av-device-f%C3%BCr-yamaha-pioneer-denon-etc version: 1.5.0 # Plugin version diff --git a/avm/plugin.yaml b/avm/plugin.yaml index 422859ab9..642a92a4c 100755 --- a/avm/plugin.yaml +++ b/avm/plugin.yaml @@ -9,7 +9,7 @@ plugin: tester: Sandman60, cmalo # keywords: iot xyz state: 'qa-passed' - documentation: http://smarthomeng.de/user/plugins_doc/config/avm.html + documentation: http://smarthomeng.de/user/plugins/avm/user_doc.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/934835-avm-plugin version: 1.5.4 # Plugin version diff --git a/backend/plugin.yaml b/backend/plugin.yaml index 56bbb0d34..7e1ce9961 100755 --- a/backend/plugin.yaml +++ b/backend/plugin.yaml @@ -48,7 +48,7 @@ plugin: maintainer: psilo909, msinn, bmxp tester: Sandman60 # keywords: iot xyz -# documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page + documentation: http://smarthomeng.de/user/plugins/backend/user_doc.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/959964-support-thread-für-das-backend-plugin version: 1.4.14 # Plugin version diff --git a/cli/plugin.yaml b/cli/plugin.yaml index 7661b8d06..36b264c2b 100755 --- a/cli/plugin.yaml +++ b/cli/plugin.yaml @@ -10,7 +10,7 @@ plugin: tester: onkelandy, Sandman60, ohinckel state: qa-passed # keywords: iot xyz -# documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page + documentation: http://smarthomeng.de/user/plugins/cli/user_doc.html version: 1.4.2 # Plugin version sh_minversion: 1.4 # minimum shNG version to use this plugin diff --git a/database/plugin.yaml b/database/plugin.yaml index f6cb6623d..e4ddad07f 100755 --- a/database/plugin.yaml +++ b/database/plugin.yaml @@ -9,7 +9,7 @@ plugin: tester: psilo909, onkelandy, brandst state: ready keywords: database -# documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page + documentation: http://smarthomeng.de/user/plugins/database/user_doc.html version: 1.4.1 # Plugin version sh_minversion: 1.4c # minimum shNG version to use this plugin diff --git a/dlms/plugin.yaml b/dlms/plugin.yaml index 8e09ac4b0..d3b702d32 100644 --- a/dlms/plugin.yaml +++ b/dlms/plugin.yaml @@ -9,7 +9,7 @@ plugin: # tester: # Who tests this plugin? state: ready keywords: dlms obis smartmeter -# documentation: https://github.com/smarthomeNG/smarthome/wiki/DLMS-Plugin # url of documentation (wiki) page + documentation: http://smarthomeng.de/user/plugins/dlms/user_doc.html # support: https://knx-user-forum.de/forum/supportforen/smarthome-py version: 1.5.1 # Plugin version diff --git a/enigma2/plugin.yaml b/enigma2/plugin.yaml index 52eb8bdd2..72d98fad9 100755 --- a/enigma2/plugin.yaml +++ b/enigma2/plugin.yaml @@ -9,7 +9,7 @@ plugin: tester: Sandman60, msinn state: 'qa-passed' # keywords: iot xyz - documentation: http://smarthomeng.de/user/plugins_doc/config/enigma2.html # url of documentation (wiki) page +# documentation: http://smarthomeng.de/user/plugins/enigma2/user_doc.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/943871-enigma2-plugin version: 1.4.11 # Plugin version diff --git a/homematic/plugin.yaml b/homematic/plugin.yaml index 70bbd10ca..f63f2ae75 100755 --- a/homematic/plugin.yaml +++ b/homematic/plugin.yaml @@ -10,7 +10,7 @@ plugin: state: qa-passed # tester: efgh # Who tests this plugin? # keywords: kwd1 kwd2 # keywords, where applicable -# documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page + documentation: http://smarthomeng.de/user/plugins/homematic/user_doc.html # support: https://knx-user-forum.de/forum/supportforen/smarthome-py # Following entries are for Smart-Plugins: diff --git a/knx/plugin.yaml b/knx/plugin.yaml index 6ea324c51..986f55746 100755 --- a/knx/plugin.yaml +++ b/knx/plugin.yaml @@ -10,7 +10,7 @@ plugin: tester: psilo909, onkelandy, Sandman60, brandst state: qa-passed # keywords: iot xyz -# documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page + documentation: http://smarthomeng.de/user/plugins/knx/user_doc.html version: 1.4.6 # Plugin version sh_minversion: 1.4 # minimum shNG version to use this plugin diff --git a/mqtt/plugin.yaml b/mqtt/plugin.yaml index 8395971ef..352826825 100755 --- a/mqtt/plugin.yaml +++ b/mqtt/plugin.yaml @@ -50,7 +50,7 @@ plugin: maintainer: msinn # tester: # Who tests this plugin? keywords: iot -# documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page + documentation: http://smarthomeng.de/user/plugins/mqtt/user_doc.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1089334-neues-mqtt-plugin version: 1.4.7 # Plugin version diff --git a/openweathermap/plugin.yaml b/openweathermap/plugin.yaml index a4f543b44..3c5f3ce1a 100644 --- a/openweathermap/plugin.yaml +++ b/openweathermap/plugin.yaml @@ -9,7 +9,7 @@ plugin: tester: psilo909 state: qa-passed # keywords: iot xyz - documentation: '' + documentation: 'http://smarthomeng.de/user/plugins/openweathermap/user_doc.html' support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/1246998-support-thread-zum-openweathermap-plugin' keywords: weather version: 1.5.0.2 # Plugin version diff --git a/visu_smartvisu/plugin.yaml b/visu_smartvisu/plugin.yaml index 348763916..ad7ed4bf9 100755 --- a/visu_smartvisu/plugin.yaml +++ b/visu_smartvisu/plugin.yaml @@ -9,7 +9,7 @@ plugin: tester: psilo909 state: qa-passed # keywords: iot xyz -# documentation: https://github.com/smarthomeNG/smarthome/wiki/Visu_Unterstuetzung # url of documentation (wiki) page + documentation: http://smarthomeng.de/user/plugins/visu_smartvisu/user_doc.html version: 1.3.4 # Plugin version sh_minversion: 1.3 # minimum shNG version to use this plugin diff --git a/visu_websocket/plugin.yaml b/visu_websocket/plugin.yaml index 09b0c5307..87ac1a0dd 100755 --- a/visu_websocket/plugin.yaml +++ b/visu_websocket/plugin.yaml @@ -9,7 +9,7 @@ plugin: tester: psilo909 state: qa-passed # keywords: iot xyz - documentation: https://github.com/smarthomeNG/smarthome/wiki/Visu_Unterstuetzung # url of documentation (wiki) page + documentation: http://smarthomeng.de/user/plugins/visu_websocket/user_doc.html version: 1.4.5 # Plugin version sh_minversion: 1.4c # minimum shNG version to use this plugin diff --git a/webservices/plugin.yaml b/webservices/plugin.yaml index 8dc22ae27..1cbdd8887 100755 --- a/webservices/plugin.yaml +++ b/webservices/plugin.yaml @@ -10,6 +10,7 @@ plugin: state: qa-passed keywords: REST, API, Webservice documentation: https://www.smarthomeng.de/?category_name=plugins&s=webservices +# documentation: http://smarthomeng.de/user/plugins/webservices/user_doc.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1163886-support-thread-f%C3%BCr-das-webservices-plugin version: 1.5.0.5 # Plugin version diff --git a/wunderground/plugin.yaml b/wunderground/plugin.yaml index 49fb71c58..323b738df 100644 --- a/wunderground/plugin.yaml +++ b/wunderground/plugin.yaml @@ -9,7 +9,7 @@ plugin: tester: msinn # Who tests this plugin? state: 'qa-passed' keywords: weather -# documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page + documentation: http://smarthomeng.de/user/plugins/wunderground/user_doc.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/959964-support-thread-für-das-backend-plugin version: 1.4.8 # Plugin version From 74d557ba783ba121e68adea3107017d16fa6324f Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 13 Dec 2018 18:17:40 +0100 Subject: [PATCH 435/705] AVM: added implementation to check for connection failures (exceptions on request) and disconnection from callmonitor in case of exception. after the first exception device is set as disconnected and no further errors are logged, as soon as connection is back (request succuessful) all is starting from the beginning --- avm/__init__.py | 187 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 159 insertions(+), 28 deletions(-) diff --git a/avm/__init__.py b/avm/__init__.py index 500d82283..2a0316c2e 100644 --- a/avm/__init__.py +++ b/avm/__init__.py @@ -72,7 +72,7 @@ def connect(self): if self._listen_active: self.logger.debug("MonitoringService: Connect called while listen active") return - + self.conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: self.conn.connect((self._host, self._port)) @@ -416,6 +416,7 @@ def __init__(self, host, port, ssl, username, password, identifier='default'): self._username = username self._password = password self._identifier = identifier + self._available = True self._items = [] def get_identifier(self): @@ -466,6 +467,22 @@ def is_ssl(self): """ return self._ssl + def is_available(self): + """ + Returns information if the device is currently available + + :return: boolean, if device is available + """ + return self._available + + def set_available(self, is_available): + """ + Sets the boolean, if the device is available + + :param is_available: boolean of the availability status + """ + self._available = is_available + def get_user(self): """ Returns the user for the FritzDevice @@ -648,12 +665,18 @@ def _update_loop(self): self._update_myfritz(item) # empty response cache self._response_cache = dict() - + if self._call_monitor: if not self.alive: return self._monitoring_service.connect() + def set_device_availability(self, availability): + self._fritz_device.set_available(availability) + self.logger.debug('Availability for FritzDevice set to %s' % availability) + if not availability and self._call_monitor: + self._monitoring_service.disconnect() + def get_calllist_from_cache(self): """ returns the cached calllist when all items are initialized. The filter set by plugin.conf is applied. @@ -859,9 +882,13 @@ def update_item(self, item, caller=None, source=None, dest=None): auth=HTTPDigestAuth(self._fritz_device.get_user(), self._fritz_device.get_password()), verify=self._verify) except Exception as e: - self.logger.error( + if self._fritz_device.is_available(): + self.logger.error( "Exception when sending POST request for updating item towards the FritzDevice: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) if self.get_iattr_value(item.conf, 'avm_data_type') == 'wlanconfig': # check if item was guest wifi item and remaining time is set as item.. @@ -896,8 +923,12 @@ def get_contact_name_by_phone_number(self, phone_number=''): self._fritz_device.get_password()), verify=self._verify) xml = minidom.parseString(response.content) except Exception as e: - self.logger.error("Exception when sending POST request or parsing response: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request or parsing response: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) pb_url_xml = xml.getElementsByTagName('NewPhonebookURL') if len(pb_url_xml) > 0: @@ -906,8 +937,13 @@ def get_contact_name_by_phone_number(self, phone_number=''): pb_result = self._session.get(pb_url, timeout=self._timeout, verify=self._verify) pb_xml = minidom.parseString(pb_result.content) except Exception as e: - self.logger.error("Exception when sending GET request or parsing response: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending GET request or parsing response: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) + contacts = pb_xml.getElementsByTagName('contact') if len(contacts) > 0: for contact in contacts: @@ -946,8 +982,12 @@ def get_phone_numbers_by_name(self, name=''): self._fritz_device.get_password()), verify=self._verify) xml = minidom.parseString(response.content) except Exception as e: - self.logger.error("Exception when sending POST request or parsing response: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request or parsing response: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) pb_url_xml = xml.getElementsByTagName('NewPhonebookURL') if len(pb_url_xml) > 0: @@ -956,8 +996,12 @@ def get_phone_numbers_by_name(self, name=''): pb_result = self._session.get(pb_url, timeout=self._timeout, verify=self._verify) pb_xml = minidom.parseString(pb_result.content) except Exception as e: - self.logger.error("Exception when sending GET request or parsing response: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending GET request or parsing response: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) contacts = pb_xml.getElementsByTagName('contact') result_numbers = {} @@ -1008,8 +1052,12 @@ def get_calllist(self, filter_incoming=''): self._fritz_device.get_password()), verify=self._verify) xml = minidom.parseString(response.content) except Exception as e: - self.logger.error("Exception when sending POST request or parsing response: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request or parsing response: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) calllist_url_xml = xml.getElementsByTagName('NewCallListURL') if (len(calllist_url_xml) > 0): @@ -1019,8 +1067,12 @@ def get_calllist(self, filter_incoming=''): calllist_result = self._session.get(calllist_url, timeout=self._timeout, verify=self._verify) calllist_xml = minidom.parseString(calllist_result.content) except Exception as e: - self.logger.error("Exception when sending GET request or parsing response: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending GET request or parsing response: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) calllist_entries = calllist_xml.getElementsByTagName('Call') result_entries = [] @@ -1084,8 +1136,12 @@ def reboot(self): if self._call_monitor: self._monitoring_service.disconnect() except Exception as e: - self.logger.error("Exception when sending POST request: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) def wol(self, mac_address): """ @@ -1125,7 +1181,12 @@ def get_hosts(self, only_active): self._fritz_device.get_password()), verify=self._verify) except Exception as e: - self.logger.error("Exception when sending POST request: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request: %s" % str(e)) + self.set_device_availability(False) + return + if not self._fritz_device.is_available(): + self.set_device_availability(True) xml = minidom.parseString(response.content) @@ -1158,7 +1219,12 @@ def get_host_details(self, index): self._fritz_device.get_password()), verify=self._verify) except Exception as e: - self.logger.error("Exception when sending POST request: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request: %s" % str(e)) + self.set_device_availability(False) + return + if not self._fritz_device.is_available(): + self.set_device_availability(True) xml = minidom.parseString(response.content) host = { @@ -1189,8 +1255,12 @@ def reconnect(self): auth=HTTPDigestAuth(self._fritz_device.get_user(), self._fritz_device.get_password()), verify=self._verify) except Exception as e: - self.logger.error("Exception when sending POST request: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) def get_call_origin(self): """ @@ -1210,8 +1280,12 @@ def get_call_origin(self): self._fritz_device.get_password()), verify=self._verify) except Exception as e: - self.logger.error("Exception when sending POST request: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) xml = minidom.parseString(response.content) @@ -1247,8 +1321,12 @@ def get_phone_name(self, index=1): self._fritz_device.get_password()), verify=self._verify) except Exception as e: - self.logger.error("Exception when sending POST request: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) xml = minidom.parseString(response.content) @@ -1278,8 +1356,12 @@ def set_call_origin(self, phone_name): auth=HTTPDigestAuth(self._fritz_device.get_user(), self._fritz_device.get_password()), verify=self._verify) except Exception as e: - self.logger.error("Exception when sending POST request: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) def start_call(self, phone_number): """ @@ -1300,8 +1382,12 @@ def start_call(self, phone_number): auth=HTTPDigestAuth(self._fritz_device.get_user(), self._fritz_device.get_password()), verify=self._verify) except Exception as e: - self.logger.error("Exception when sending POST request: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) def cancel_call(self): """ @@ -1319,8 +1405,12 @@ def cancel_call(self): auth=HTTPDigestAuth(self._fritz_device.get_user(), self._fritz_device.get_password()), verify=self._verify) except Exception as e: - self.logger.error("Exception when sending POST request: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) def is_host_active(self, mac_address): """ @@ -1380,8 +1470,12 @@ def _update_myfritz(self, item): self._fritz_device.get_password()), verify=self._verify) xml = minidom.parseString(response.content) except Exception as e: - self.logger.error("Exception when sending POST request or parsing response: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request or parsing response: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) tag_content = xml.getElementsByTagName('NewEnabled') if len(tag_content) > 0: @@ -1417,8 +1511,12 @@ def _update_host(self, item): self._fritz_device.get_password()), verify=self._verify) xml = minidom.parseString(response.content) except Exception as e: - self.logger.error("Exception when sending POST request: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) tag_content = xml.getElementsByTagName('NewActive') if len(tag_content) > 0: @@ -1490,8 +1588,12 @@ def _update_home_automation(self, item): xml = minidom.parseString(response.content) except Exception as e: - self.logger.error("Exception when sending POST request or parsing response: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request or parsing response: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) if self.get_iattr_value(item.conf, 'avm_data_type') == 'aha_device': element_xml = xml.getElementsByTagName('NewSwitchState') @@ -1557,8 +1659,12 @@ def _update_fritz_device_info(self, item): self._fritz_device.get_password()), verify=self._verify) except Exception as e: - self.logger.error("Exception when sending POST request: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) self._response_cache["dev_info_" + action] = response.content else: self.logger.debug("Accessing DeviceInfo reponse cache for action %s!" % action) @@ -1627,8 +1733,12 @@ def _update_tam(self, item): self._fritz_device.get_password()), verify=self._verify) except Exception as e: - self.logger.error("Exception when sending POST request: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) self._response_cache["tam_" + action] = response.content else: self.logger.debug("Accessing TAM reponse cache for action %s!" % action) @@ -1662,8 +1772,12 @@ def _update_tam(self, item): try: message_result = self._session.get(message_url, timeout=self._timeout, verify=self._verify) except Exception as e: - self.logger.error("Exception when sending GET request: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending GET request: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) self._response_cache["tam_messages"] = message_result.content else: self.logger.debug("Accessing TAM reponse cache for action %s!" % action) @@ -1728,8 +1842,12 @@ def _update_wlan_config(self, item): verify=self._verify) except Exception as e: - self.logger.error("Exception when sending POST request: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) self._response_cache["wlanconfig_%s_%s" % (item.conf['avm_wlan_index'], action)] = response.content else: self.logger.debug("Accessing TAM reponse cache for action %s!" % action) @@ -1790,8 +1908,12 @@ def _update_wan_dsl_interface_config(self, item): self._fritz_device.get_password()), verify=self._verify) except Exception as e: - self.logger.error("Exception when sending POST request: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) self._response_cache["wan_dsl_interface_config_" + action] = response.content else: self.logger.debug("Accessing TAM reponse cache for action %s!" % action) @@ -1862,8 +1984,12 @@ def _update_wan_common_interface_configuration(self, item): self._fritz_device.get_password()), verify=self._verify) except Exception as e: - self.logger.error("Exception when sending POST request: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) self._response_cache["wan_common_interface_configuration_" + action] = response.content else: self.logger.debug("Accessing TAM reponse cache for action %s!" % action) @@ -1972,8 +2098,12 @@ def _update_wan_ip_connection(self, item): self._fritz_device.get_password()), verify=self._verify) except Exception as e: - self.logger.error("Exception when sending POST request: %s" % str(e)) + if self._fritz_device.is_available(): + self.logger.error("Exception when sending POST request: %s" % str(e)) + self.set_device_availability(False) return + if not self._fritz_device.is_available(): + self.set_device_availability(True) self._response_cache["wan_ip_connection_" + action] = response.content else: self.logger.debug("Accessing TAM reponse cache for action %s!" % action) @@ -2070,6 +2200,7 @@ def init_webinterface(self): import cherrypy + class WebInterface(SmartPluginWebIf): def __init__(self, webif_dir, plugin): From 3e17918da70995d374bc2058e1f833bfa1381ed3 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 13 Dec 2018 18:24:13 +0100 Subject: [PATCH 436/705] AVM: added check for NewSwitchState of UNDEFINED or TOGGLE, which are currently not supported --- avm/__init__.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/avm/__init__.py b/avm/__init__.py index 2a0316c2e..5c32eeb8e 100644 --- a/avm/__init__.py +++ b/avm/__init__.py @@ -884,7 +884,7 @@ def update_item(self, item, caller=None, source=None, dest=None): except Exception as e: if self._fritz_device.is_available(): self.logger.error( - "Exception when sending POST request for updating item towards the FritzDevice: %s" % str(e)) + "Exception when sending POST request for updating item towards the FritzDevice: %s" % str(e)) self.set_device_availability(False) return if not self._fritz_device.is_available(): @@ -1598,7 +1598,11 @@ def _update_home_automation(self, item): if self.get_iattr_value(item.conf, 'avm_data_type') == 'aha_device': element_xml = xml.getElementsByTagName('NewSwitchState') if len(element_xml) > 0: - item(element_xml[0].firstChild.data) + if element_xml[0].firstChild.data not in ['UNDEFINED', 'TOGGLE']: + item(element_xml[0].firstChild.data) + else: + self.logger.error( + 'NewSwitchState für AHA Device has a non-supported value of %s' % element_xml[0].firstChild.data) for child in item.return_children(): if self.has_iattr(child.conf, 'avm_data_type'): if self.get_iattr_value(child.conf, 'avm_data_type') == 'temperature': From a0277439d4dd427436b753c223da4840609a769f Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 13 Dec 2018 18:26:20 +0100 Subject: [PATCH 437/705] AVM: added function to proccess TOGGLE value (experimental) --- avm/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/avm/__init__.py b/avm/__init__.py index 5c32eeb8e..2093bf654 100644 --- a/avm/__init__.py +++ b/avm/__init__.py @@ -1600,6 +1600,9 @@ def _update_home_automation(self, item): if len(element_xml) > 0: if element_xml[0].firstChild.data not in ['UNDEFINED', 'TOGGLE']: item(element_xml[0].firstChild.data) + elif element_xml[0].firstChild.data in 'TOGGLE': + value = item() + item(not value) else: self.logger.error( 'NewSwitchState für AHA Device has a non-supported value of %s' % element_xml[0].firstChild.data) From bc22a8ff0d94995170a114a1ddd011a0663d7fe1 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Thu, 13 Dec 2018 18:43:51 +0100 Subject: [PATCH 438/705] AVM: upgraded Plugin version and fixed typo --- avm/__init__.py | 16 ++++++++-------- avm/plugin.yaml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/avm/__init__.py b/avm/__init__.py index 2093bf654..86676385a 100644 --- a/avm/__init__.py +++ b/avm/__init__.py @@ -505,7 +505,7 @@ class AVM(SmartPlugin): Main class of the Plugin. Does all plugin specific stuff and provides the update functions for the different TR-064 services on the FritzDevice """ - PLUGIN_VERSION = "1.5.4" + PLUGIN_VERSION = "1.5.5" _header = {'SOAPACTION': '', 'CONTENT-TYPE': 'text/xml; charset="utf-8"'} _envelope = """ @@ -1674,7 +1674,7 @@ def _update_fritz_device_info(self, item): self.set_device_availability(True) self._response_cache["dev_info_" + action] = response.content else: - self.logger.debug("Accessing DeviceInfo reponse cache for action %s!" % action) + self.logger.debug("Accessing DeviceInfo response cache for action %s!" % action) try: xml = minidom.parseString(self._response_cache["dev_info_" + action]) @@ -1748,7 +1748,7 @@ def _update_tam(self, item): self.set_device_availability(True) self._response_cache["tam_" + action] = response.content else: - self.logger.debug("Accessing TAM reponse cache for action %s!" % action) + self.logger.debug("Accessing TAM response cache for action %s!" % action) try: xml = minidom.parseString(self._response_cache["tam_" + action]) @@ -1787,7 +1787,7 @@ def _update_tam(self, item): self.set_device_availability(True) self._response_cache["tam_messages"] = message_result.content else: - self.logger.debug("Accessing TAM reponse cache for action %s!" % action) + self.logger.debug("Accessing TAM response cache for action %s!" % action) try: message_xml = minidom.parseString(self._response_cache["tam_messages"]) @@ -1857,7 +1857,7 @@ def _update_wlan_config(self, item): self.set_device_availability(True) self._response_cache["wlanconfig_%s_%s" % (item.conf['avm_wlan_index'], action)] = response.content else: - self.logger.debug("Accessing TAM reponse cache for action %s!" % action) + self.logger.debug("Accessing TAM response cache for action %s!" % action) try: xml = minidom.parseString(self._response_cache["wlanconfig_%s_%s" % (item.conf['avm_wlan_index'], action)]) @@ -1923,7 +1923,7 @@ def _update_wan_dsl_interface_config(self, item): self.set_device_availability(True) self._response_cache["wan_dsl_interface_config_" + action] = response.content else: - self.logger.debug("Accessing TAM reponse cache for action %s!" % action) + self.logger.debug("Accessing TAM response cache for action %s!" % action) try: xml = minidom.parseString(self._response_cache["wan_dsl_interface_config_" + action]) @@ -1999,7 +1999,7 @@ def _update_wan_common_interface_configuration(self, item): self.set_device_availability(True) self._response_cache["wan_common_interface_configuration_" + action] = response.content else: - self.logger.debug("Accessing TAM reponse cache for action %s!" % action) + self.logger.debug("Accessing TAM response cache for action %s!" % action) try: xml = minidom.parseString(self._response_cache["wan_common_interface_configuration_" + action]) @@ -2113,7 +2113,7 @@ def _update_wan_ip_connection(self, item): self.set_device_availability(True) self._response_cache["wan_ip_connection_" + action] = response.content else: - self.logger.debug("Accessing TAM reponse cache for action %s!" % action) + self.logger.debug("Accessing TAM response cache for action %s!" % action) try: xml = minidom.parseString(self._response_cache["wan_ip_connection_" + action]) diff --git a/avm/plugin.yaml b/avm/plugin.yaml index 642a92a4c..6634a0cfb 100755 --- a/avm/plugin.yaml +++ b/avm/plugin.yaml @@ -12,7 +12,7 @@ plugin: documentation: http://smarthomeng.de/user/plugins/avm/user_doc.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/934835-avm-plugin - version: 1.5.4 # Plugin version + version: 1.5.5 # Plugin version sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance From 9c877624321fa93e8668cf24adfd72a86c33b2bf Mon Sep 17 00:00:00 2001 From: msinn Date: Thu, 13 Dec 2018 22:54:53 +0100 Subject: [PATCH 439/705] Several plugins: changes to metadata --- apcups/plugin.yaml | 8 ++++++++ appletv/plugin.yaml | 7 +++++++ avdevice/plugin.yaml | 8 ++++++++ avm/plugin.yaml | 4 ++-- darksky/plugin.yaml | 9 ++++++++- database/plugin.yaml | 6 ++++++ dlms/plugin.yaml | 12 ++++++------ enigma2/plugin.yaml | 4 ++-- homematic/plugin.yaml | 8 ++++++++ knx/plugin.yaml | 7 +++++++ kodi/plugin.yaml | 7 +++++++ kostal/plugin.yaml | 10 +++++++++- lirc/plugin.yaml | 7 +++++++ logo/plugin.yaml | 10 +++++++++- miflora/plugin.yaml | 7 +++++++ mpd/plugin.yaml | 7 +++++++ mqtt/plugin.yaml | 7 +++++++ openweathermap/plugin.yaml | 8 +++++++- prowl/plugin.yaml | 10 +++++++++- slack/plugin.yaml | 8 ++++++++ smarttv/plugin.yaml | 8 ++++++++ sml/plugin.yaml | 6 ++++++ visu_smartvisu/plugin.yaml | 9 ++++++++- withings_health/plugin.yaml | 7 +++++++ wol/plugin.yaml | 9 +++++++-- wunderground/plugin.yaml | 13 +++++++------ 26 files changed, 182 insertions(+), 24 deletions(-) diff --git a/apcups/plugin.yaml b/apcups/plugin.yaml index d045fe410..eac716c3e 100755 --- a/apcups/plugin.yaml +++ b/apcups/plugin.yaml @@ -43,6 +43,14 @@ parameters: de: 'Zyklus-Zeit zum Update der Items mit Werten von APCaccess' en: time to update the items with values from apcaccess + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' + + item_attributes: # Definition of item attributes defined by this plugin apcups: diff --git a/appletv/plugin.yaml b/appletv/plugin.yaml index 87e23062d..e5d583c4a 100755 --- a/appletv/plugin.yaml +++ b/appletv/plugin.yaml @@ -34,6 +34,13 @@ parameters: en: 'Login ID of the device. Can be found in the web interface.' fr: "ID de connexion de l'appareil. Peut être trouvé sur l'interface web" + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' + #item_attributes: # Definition of item attributes defined by this plugin diff --git a/avdevice/plugin.yaml b/avdevice/plugin.yaml index 389c15c81..d083af7c7 100755 --- a/avdevice/plugin.yaml +++ b/avdevice/plugin.yaml @@ -191,6 +191,13 @@ parameters: de: "Verbindet sich das Plugin, werden die Werte automatisch abgefragt, auch wenn kein Depend=Init im Item angegeben ist. Sollen nur Items abgefragt werden, bei denen das depend-Attribut auf init gesetzt ist, sollte dieser Wert auf False gestellt werden." en: "As soon as the plugin connects to the device the values get queried automatically even if the Depend=Init is not set in the items. If you want to query only those items that are set explicitly change this value to False." + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' + item_attributes: avdevice_zone0_depend: type: list(str) @@ -336,6 +343,7 @@ item_attributes: de: 'Über dieses Attribut lässt sich ein anderes Item auf einen bestimmten Wert setzen, sobald das Plugin sich mit dem Gerät verbindet. Der Wert muss bereits als avdevice-Attribut bei einem anderen Item hinterlegt sein.' en: 'This attribute changes the value of another item to a specific value as soon as the plugin connects to the device. The value has to exist as an avdevice-attribute on another item.' + logic_parameters: NONE # Definition of logic parameters defined by this plugin diff --git a/avm/plugin.yaml b/avm/plugin.yaml index 6634a0cfb..098108bd6 100755 --- a/avm/plugin.yaml +++ b/avm/plugin.yaml @@ -79,8 +79,8 @@ parameters: type: str default: '' description: - de: '(optional) Eindeutiger Identifier für die Instanz des Plugins, also für jedes FritzDevice. Kann bei nur einem Gerät / Single Instance Betrieb des Plugins entfallen.' - en: '(optional) Unique identifier for each FritzDevice / each instance of the plugin. Can be skipped if only one device is used / the plugin is operated single instance.' + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' item_attributes: # Definition of item attributes defined by this plugin diff --git a/darksky/plugin.yaml b/darksky/plugin.yaml index dcdba2d2a..83ce39054 100644 --- a/darksky/plugin.yaml +++ b/darksky/plugin.yaml @@ -62,7 +62,14 @@ parameters: description: de: '(optional) Zeit zwischen zwei Updateläufen. Default ist 300 Sekunden.' en: '(optional) Time period between two update cycles. Default is 300 seconds.' - + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' + + item_attributes: # Definition of item attributes defined by this plugin ds_matchstring: diff --git a/database/plugin.yaml b/database/plugin.yaml index e4ddad07f..42f2e1740 100755 --- a/database/plugin.yaml +++ b/database/plugin.yaml @@ -48,6 +48,12 @@ parameters: description: de: 'Genauigkeit der aus der Datenbank ausgelesenen Werte (Nachkommastellen).' en: 'Precision of values read from database (digits after comma).' + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' item_attributes: diff --git a/dlms/plugin.yaml b/dlms/plugin.yaml index d3b702d32..c40f1f58c 100644 --- a/dlms/plugin.yaml +++ b/dlms/plugin.yaml @@ -21,12 +21,6 @@ plugin: parameters: # Definition of parameters to be configured in etc/plugin.yaml - instance: - type: foo - default: 0 - description: - de: 'Instanz des Plugins' - en: 'Plugin instance' serialport: type: str description: @@ -86,6 +80,12 @@ parameters: description: de: 'derzeit nicht genutzt' en: 'not used currently' + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' item_attributes: # Definition of item attributes defined by this plugin diff --git a/enigma2/plugin.yaml b/enigma2/plugin.yaml index 72d98fad9..e3ee60b46 100755 --- a/enigma2/plugin.yaml +++ b/enigma2/plugin.yaml @@ -73,8 +73,8 @@ parameters: type: str default: '' description: - de: '(optional) Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einem Gerät / Single Instance Betrieb des Plugins entfallen.' - en: '(optional) Unique identifier for each instance of the plugin. Can be skipped if only one device is used / the plugin is operated single instance.' + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' item_attributes: diff --git a/homematic/plugin.yaml b/homematic/plugin.yaml index f63f2ae75..71802a190 100755 --- a/homematic/plugin.yaml +++ b/homematic/plugin.yaml @@ -70,6 +70,14 @@ parameters: de: 'Dauer des Anlernmodus der HomeMatic CCU2 Zentrale nach Aktivierung durch das Web Interface' en: 'Duration of learnmode of the HomeMatic CCU2 gateway after activation through the web interface' + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' + + item_attributes: # Definition of item attributes defined by this plugin diff --git a/knx/plugin.yaml b/knx/plugin.yaml index 986f55746..0476b7d28 100755 --- a/knx/plugin.yaml +++ b/knx/plugin.yaml @@ -88,6 +88,13 @@ parameters: de: 'Wenn diese Option auf "True" gesetzt ist, werden die Statistikfunktionen aktiviert um Daten erfassen' en: 'if set to True, the statistic functions are enabled to collect data' + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' + item_attributes: diff --git a/kodi/plugin.yaml b/kodi/plugin.yaml index 385385f74..a03c12a43 100755 --- a/kodi/plugin.yaml +++ b/kodi/plugin.yaml @@ -32,6 +32,13 @@ parameters: description: en: 'English description' + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' + item_attributes: # Definition of item attributes defined by this plugin diff --git a/kostal/plugin.yaml b/kostal/plugin.yaml index 3764e3d4d..e48fb4a4d 100755 --- a/kostal/plugin.yaml +++ b/kostal/plugin.yaml @@ -19,7 +19,15 @@ plugin: parameters: # Definition of parameters to be configured in etc/plugin.yaml - + +# instance: +# type: str +# default: '' +# description: +# de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' +# en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' + + item_attributes: # Definition of item attributes defined by this plugin diff --git a/lirc/plugin.yaml b/lirc/plugin.yaml index 76bea48b7..3055af8d3 100644 --- a/lirc/plugin.yaml +++ b/lirc/plugin.yaml @@ -34,3 +34,10 @@ parameters: description: de: 'Der Port auf dem lircd lauscht.' en: 'The port that is used by lircd.' + + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' diff --git a/logo/plugin.yaml b/logo/plugin.yaml index e47458e64..ef8bac8da 100755 --- a/logo/plugin.yaml +++ b/logo/plugin.yaml @@ -19,7 +19,15 @@ plugin: parameters: # Definition of parameters to be configured in etc/plugin.yaml - + +# instance: +# type: str +# default: '' +# description: +# de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' +# en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' + + item_attributes: # Definition of item attributes defined by this plugin diff --git a/miflora/plugin.yaml b/miflora/plugin.yaml index 981da8077..1ac4868d5 100644 --- a/miflora/plugin.yaml +++ b/miflora/plugin.yaml @@ -36,6 +36,13 @@ parameters: de: '(optional) Dieser Parameter muss normalerweise nicht angegeben werden. Er erlaubt es die Update-Frquenz anzupassen (Standard: alle 300 Sekunden).' en: "(optional) This parameter usually doesn't have to be specified. It allows to change the update frequency (cycle every 300 seconds)." + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' + item_attributes: # Definition of item attributes defined by this plugin diff --git a/mpd/plugin.yaml b/mpd/plugin.yaml index 4a5cb20a7..d742f6e82 100755 --- a/mpd/plugin.yaml +++ b/mpd/plugin.yaml @@ -42,3 +42,10 @@ parameters: description: de: 'Gibt an nach wie vielen Sekunden die Statusitems aktualisiert werden' en: 'The time interval that will be used for update the status items' + + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' diff --git a/mqtt/plugin.yaml b/mqtt/plugin.yaml index 352826825..a8b471392 100755 --- a/mqtt/plugin.yaml +++ b/mqtt/plugin.yaml @@ -332,6 +332,13 @@ parameters: This parameter defines the default access control for items, which have no individual access control configured. ' + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' + item_attributes: # Definition of item attributes defined by this plugin diff --git a/openweathermap/plugin.yaml b/openweathermap/plugin.yaml index 3c5f3ce1a..d0cfd37b8 100644 --- a/openweathermap/plugin.yaml +++ b/openweathermap/plugin.yaml @@ -62,7 +62,13 @@ parameters: description: de: '(optional) Zeit zwischen zwei Updateläufen. Default ist 300 Sekunden.' en: '(optional) Time period between two update cycles. Default is 300 seconds.' - + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' + item_attributes: # Definition of item attributes defined by this plugin owm_matchstring: diff --git a/prowl/plugin.yaml b/prowl/plugin.yaml index 5a086046e..abef17af3 100755 --- a/prowl/plugin.yaml +++ b/prowl/plugin.yaml @@ -19,7 +19,15 @@ plugin: parameters: # Definition of parameters to be configured in etc/plugin.yaml - + +# instance: +# type: str +# default: '' +# description: +# de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' +# en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' + + item_attributes: # Definition of item attributes defined by this plugin diff --git a/slack/plugin.yaml b/slack/plugin.yaml index 45742aef4..3fbf3287c 100644 --- a/slack/plugin.yaml +++ b/slack/plugin.yaml @@ -28,6 +28,14 @@ parameters: en: 'Slack token for API access to one or more channels in a single Slack workspace' mandatory: True + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' + + item_attributes: NONE # Definition of item attributes defined by this plugin diff --git a/smarttv/plugin.yaml b/smarttv/plugin.yaml index 7a7df7ca8..b6525445a 100755 --- a/smarttv/plugin.yaml +++ b/smarttv/plugin.yaml @@ -52,6 +52,14 @@ parameters: de: '(optional) Verzögerung in Sekunden, falls mehr als eine Taste gesendet wird. Reduziert Probleme, wenn bspw. TV-Programme wie "135" aufgerufen werden. Default: 1' en: '(optional) Specify a delay (in seconds), in case more than 1 key is sent. Reduces problems when switching e.g. to TV programs with numbers like "135". Default: 1.' + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' + + item_attributes: # Definition of item attributes defined by this plugin smarttv: diff --git a/sml/plugin.yaml b/sml/plugin.yaml index 80d6c73e4..851b10da6 100755 --- a/sml/plugin.yaml +++ b/sml/plugin.yaml @@ -44,6 +44,12 @@ parameters: description: de: '(optional) Legt ein Gerät fest von dem die Daten ausgelesen werden' en: '(optional) Specifies a device from which the data is read' + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' item_attributes: # Definition of item attributes defined by this plugin diff --git a/visu_smartvisu/plugin.yaml b/visu_smartvisu/plugin.yaml index ad7ed4bf9..42cfc21aa 100755 --- a/visu_smartvisu/plugin.yaml +++ b/visu_smartvisu/plugin.yaml @@ -57,7 +57,14 @@ parameters: de: 'Standardmäßig werden Widgets aus den Plugins in die smartVISU kopiert und eingebunden. Dieses kann verhindert werden, wenn dieser Parameter auf False gesetzt wird.' en: 'By default, the visu plugin handles smartVISU widgets. If your run into problems, you can disable the widget handling by setting this attribute to False.' - + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' + + item_attributes: # Definition of item attributes defined by this plugin # visu_acl: # defined in visu_websocket diff --git a/withings_health/plugin.yaml b/withings_health/plugin.yaml index f9e1a4e4f..3f8eb5786 100644 --- a/withings_health/plugin.yaml +++ b/withings_health/plugin.yaml @@ -51,6 +51,13 @@ parameters: de: 'Dieser Parameter muss normalerweise nicht angegeben werden. Er erlaubt es die Update-Frquenz anzupassen (Standard: alle 600 Sekunden). Mit dem Standardwert werden die Daten von Nokia Health alle 5 Minuten aktualisiert.' en: "This parameter usually doesn't have to be specified. It allows to change the update frequency (cycle every 300 seconds). As a standard, the plugin updates the Nokia Health data every 5 minutes." + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' + item_attributes: # Definition of item attributes defined by this plugin diff --git a/wol/plugin.yaml b/wol/plugin.yaml index bb2c6b2b8..b9247543d 100755 --- a/wol/plugin.yaml +++ b/wol/plugin.yaml @@ -19,9 +19,14 @@ plugin: restartable: unknown classname: WakeOnLan # class containing the plugin -parameters: NONE +parameters: # Definition of parameters to be configured in etc/plugin.yaml - + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' item_attributes: # Definition of item attributes defined by this plugin diff --git a/wunderground/plugin.yaml b/wunderground/plugin.yaml index 323b738df..06a3254b5 100644 --- a/wunderground/plugin.yaml +++ b/wunderground/plugin.yaml @@ -10,7 +10,7 @@ plugin: state: 'qa-passed' keywords: weather documentation: http://smarthomeng.de/user/plugins/wunderground/user_doc.html - support: https://knx-user-forum.de/forum/supportforen/smarthome-py/959964-support-thread-für-das-backend-plugin + support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1059124-neues-wunderground-plugin version: 1.4.8 # Plugin version sh_minversion: 1.4c # minimum shNG version to use this plugin @@ -61,11 +61,12 @@ parameters: The subtrees defined by item_subtree for the different instances must not intersect!' -# instance: -# type: str -# description: -# de: 'Name der Plugin Instanz (SmartHomeNG Standard-Parameter). Die Angabe ist notwendig, wenn Wetterdaten für mehrere Orte über mehrere Plugin-Instanzen abgefragt werden sollen.' -# en: 'Name of the plugin instance (SmartHomeNG standard parameter). This is important if you define multiple weather locations using multiple instances of the wunderground plugin.' + instance: + type: str + default: '' + description: + de: 'Eindeutiger Identifier für die Instanz des Plugins. Kann bei nur einer konfigurierten Instanz des Plugins entfallen.' + en: 'Unique identifier for each instance of the plugin. Can be omitted if only one device instance of the plugin is configured.' From 63c538ccea17625cdc618413328388cb2ff53485 Mon Sep 17 00:00:00 2001 From: jentz1986 Date: Fri, 14 Dec 2018 10:14:37 +0100 Subject: [PATCH 440/705] Added all item to ETS-OPC (.esf-File) comparison MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Creates the following output at the end of the report. (Example lines only) A type comparison has to be done manually e.g. in Excel. But with this output gaps/delta between ETS Configuration and Items can be easily spotted. Folgende Items sind mit Bezug zu KNX konfiguriert: ====================================================================== item |type |dpt |GA |bindtype |ETS Name ------------------------------------------------------------------------------------------------------------------------------------------------------------------- wurzel.zentral.klingelknopf | bool| 1| 0/3/5|knx_listen| in ETS => Globale Daten.Meldungen.Türklingel Klingeln wurzel.zentral.klingelknopf | bool| 1| 0/3/5|knx_send | in ETS => Globale Daten.Meldungen.Türklingel Klingeln Folgende GAs sind in ETS konfiguriert: ====================================================================== GA|ETS Name |ETS Typ |#Items | DPT| Type| BindType|Item ---------------------------------------------------------------------------------------------------------------------------------------------------------------- 0/0/14|Gerätefehler Dimmaktor 4Kanal EG |EIS 1 'Switching' (1 Bit) | 1 | 1| bool|knx_listen|wurzel.stoerungen.geraetefehlerDimmaktorEg 0/0/15|Gerätefehler Dimmaktor 2Kanal EG |EIS 1 'Switching' (1 Bit) | 0 | N/A| ?| knx_?|NICHT ALS ITEM ANGELEGT --- knx/Check_KNX.py | 116 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 1 deletion(-) diff --git a/knx/Check_KNX.py b/knx/Check_KNX.py index 266f59ba8..cdd8fe1ba 100644 --- a/knx/Check_KNX.py +++ b/knx/Check_KNX.py @@ -125,8 +125,122 @@ # those defined in both should be cross checked for plausibility according to the data point types # eg. a 1-Bit in ETS should match a boolean in SmartHomeNG + out += nl+nl+"Folgende Items sind mit Bezug zu KNX konfiguriert:"+nl + out += "="*70+nl + + max_len_id = 0 for item in sh.return_items(): - pass + len_id = len(item.id()) + if len_id > max_len_id: + max_len_id = len_id + + fmtStrg = "{0:<" + str(max_len_id) + "}" + + out += fmtStrg.format("item") + for ct in ("type", "dpt", "GA", "bindtype"): + out += sep + "{0:<10}".format(ct) + out += sep + "ETS Name" + out += nl + out += "-"*(max_len_id+98) +nl + + item_ga = {} + + for item in sh.return_items(): + item_prefix = fmtStrg.format(item.id()) + item_prefix += "{1}{0:>10}".format(item.type(), sep) + + if "knx_dpt" in item.conf: + item_prefix += "{1}{0:>10}".format(item.conf["knx_dpt"], sep) + item_num = 0 + + for ct in ("knx_listen", "knx_init", "knx_cache", "knx_send", "knx_status", "knx_reply", "knx_poll"): + if ct in item.conf: + ele = item.conf[ct] + if isinstance(ele, list): + for ga in ele: + ets_name = "" + if ga in ets_ga: + ets_name = ets_ga.get(ga).get('name') + if ets_name: + ets_name = " in ETS => {0}.{1}.{2}".format(ets_ga.get(ga).get('main'), ets_ga.get(ga).get('middle'), ets_name ) + else: + ets_name = " in ETS unbekannt" + else: + ets_name = " in ETS unbekannt" + + to_add = { + 'item_path':item.id(), + 'item_type':item.type(), + 'dpt':item.conf["knx_dpt"], + 'bind_type':ct} + + if ga not in item_ga: + item_ga[ga] = [] + item_ga[ga].append(to_add) + + out += "{2}{1}{0:>10}{1}{3:<10}{1}{4}".format(ga, sep, item_prefix, ct, ets_name) + nl + item_num += 1 + else: + ga = ele + + ets_name = "" + if ga in ets_ga: + ets_name = ets_ga.get(ga).get('name') + if ets_name: + ets_name = " in ETS => {0}.{1}.{2}".format(ets_ga.get(ga).get('main'), ets_ga.get(ga).get('middle'), ets_name ) + else: + ets_name = " in ETS unbekannt" + else: + ets_name = " in ETS unbekannt" + + to_add = { + 'item_path':item.id(), + 'item_type':item.type(), + 'dpt':item.conf["knx_dpt"], + 'bind_type':ct} + + if ga not in item_ga: + item_ga[ga] = [] + item_ga[ga].append(to_add) + + out += "{2}{1}{0:>10}{1}{3:<10}{1}{4}".format(ga, sep, item_prefix, ct, ets_name) + nl + item_num += 1 + + if item_num == 0: + out += "{2}{1}{0:>10}{1}{3:<10}{1}{4}".format(" ", sep, item_prefix, "- undef -", " ") + nl + + + out += nl+nl+"Folgende GAs sind in ETS konfiguriert:"+nl + out += "="*70+nl + + max_len_ga = 0 + max_len_ga_tp = 0 + for ga in ets_ga: + len_ga = len(ets_ga.get(ga).get('name')) + len_ga_tp = len(ets_ga.get(ga).get('type')) + if len_ga > max_len_ga: + max_len_ga = len_ga + if len_ga_tp > max_len_ga_tp: + max_len_ga_tp = len_ga_tp + + fmt_string = "{0:>10}{1}{2:<"+str(max_len_ga)+"}{1}{3:<"+str(max_len_ga_tp)+"}{1}" + + header = fmt_string.format("GA", sep, "ETS Name", "ETS Typ") + header += "{5:>6} {0}{3:>10}{0}{4:>10}{0}{1:>10}{0}{2}".format(sep, "BindType", "Item", "DPT", "Type", "#Items") + nl + + out += header + out += "-" * len(header) + nl + + for ga in sorted(ets_ga): + ga_prefix = fmt_string.format(ga, sep, ets_ga.get(ga).get('name'), ets_ga.get(ga).get('type')) + + if ga in item_ga: + item_list = item_ga.get(ga) + item_list_len = len(item_list) + for it in item_list: + out += ga_prefix + "{5:>6} {0}{3:>10}{0}{4:>10}{0}{1:>10}{0}{2}".format(sep, it.get('bind_type'), it.get('item_path'), it.get('dpt'), it.get('item_type'), item_list_len) + nl + else: + out += ga_prefix + "{5:>6} {0}{3:>10}{0}{4:>10}{0}{1:>10}{0}{2}".format(sep, "knx_?", "NICHT ALS ITEM ANGELEGT", "N/A", "?", 0) + nl try: f = open(outfile, 'w') From 207bce2970e632191b6c3c13ad37a282372574f5 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sat, 15 Dec 2018 18:11:29 +0100 Subject: [PATCH 441/705] OWM: replace darksky --- openweathermap/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openweathermap/__init__.py b/openweathermap/__init__.py index b0e97780a..728f2b0e2 100644 --- a/openweathermap/__init__.py +++ b/openweathermap/__init__.py @@ -127,7 +127,7 @@ def _update(self): # if a value was found, store it to item if wrk is not None: - item(wrk, 'DarkSky') + item(wrk, 'OpenWeatherMap') self.logger.debug('_update: Value "{0}" written to item'.format(wrk)) return From 9db3e0be62e563289d64d6434ca8c88ff30f9ee4 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 15 Dec 2018 21:29:58 +0100 Subject: [PATCH 442/705] uzsu plugin: add requirements --- uzsu/requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 uzsu/requirements.txt diff --git a/uzsu/requirements.txt b/uzsu/requirements.txt new file mode 100644 index 000000000..0b62d4fc4 --- /dev/null +++ b/uzsu/requirements.txt @@ -0,0 +1 @@ +scipy>=1.1.0 \ No newline at end of file From d7de4c8e9be7aaf7b98b7b9e2fc8d3a6873dfc35 Mon Sep 17 00:00:00 2001 From: msinn Date: Sun, 16 Dec 2018 22:51:53 +0100 Subject: [PATCH 443/705] small fixes to miflora metadata and to visu_smartvisu --- miflora/plugin.yaml | 4 ++-- visu_smartvisu/__init__.py | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/miflora/plugin.yaml b/miflora/plugin.yaml index 1ac4868d5..fcce0e7e2 100644 --- a/miflora/plugin.yaml +++ b/miflora/plugin.yaml @@ -21,14 +21,14 @@ plugin: parameters: # Definition of parameters to be configured in etc/plugin.yaml - bt_addr: + bt_addr: type: str mandatory: True description: de: 'Bluetooth-Adresse des MiFlora Pflanzensensors (mit "hcitool lescan" herauszufinden).' en: 'Bluetooth address of MiFlora plant sensor (find out with "hcitool lescan").' - cycle: + cycle: type: int default: 300 mandatory: False diff --git a/visu_smartvisu/__init__.py b/visu_smartvisu/__init__.py index 867c6ee42..28a0d1576 100755 --- a/visu_smartvisu/__init__.py +++ b/visu_smartvisu/__init__.py @@ -131,6 +131,8 @@ def get_smartvisu_version(self): content = '' with open(os.path.join(self.smartvisu_dir, 'version-info.php'), 'r') as content_file: content = content_file.read() + if content.find('2.9') > -1: + return '2.9' if content.find('2.8') > -1: return '2.8' if os.path.isdir(os.path.join(self.smartvisu_dir, 'pages')): @@ -301,10 +303,10 @@ def pages(self): # for item in self._sh.find_items('sv_page'): for item in self.items.find_items('sv_page'): - if item.conf['sv_page'] == 'seperator': + if item.conf['sv_page'] in ['separator', 'seperator']: nav_lis += self.parse_tpl('navi_sep.html', [('{{ name }}', str(item))]) continue - elif item.conf['sv_page'] == 'cat_seperator': + elif item.conf['sv_page'] in ['cat_separator', 'cat_seperator']: cat_lis += self.parse_tpl('navi_sep.html', [('{{ name }}', str(item))]) continue elif ((item.conf['sv_page'] == 'overview') or (item.conf['sv_page'] == 'cat_overview')) and (not 'sv_overview' in item.conf): From 9b46f0cb73752e47c5db187ef94af1e6b0f83875 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 17 Dec 2018 15:46:14 +0100 Subject: [PATCH 444/705] AVM: trying to connect to monitoringservice (in update loop) only in case device is available --- avm/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/avm/__init__.py b/avm/__init__.py index 86676385a..caaa88cb8 100644 --- a/avm/__init__.py +++ b/avm/__init__.py @@ -669,7 +669,8 @@ def _update_loop(self): if self._call_monitor: if not self.alive: return - self._monitoring_service.connect() + if self._fritz_device.is_available(): + self._monitoring_service.connect() def set_device_availability(self, availability): self._fritz_device.set_available(availability) @@ -707,7 +708,7 @@ def parse_item(self, item): 'call_event_outgoing', 'last_number_outgoing', 'last_called_number_outgoing', 'call_event', 'call_direction', 'monitor_trigger']: - # initally - if item empty - get data from calllist + # initially - if item empty - get data from calllist if self.get_iattr_value(item.conf, 'avm_data_type') == 'last_caller_incoming' and item() == '': if not self.get_calllist_from_cache() is None: for element in self.get_calllist_from_cache(): From 178388a9853559987e57736c7a52bc34f5301bf4 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 17 Dec 2018 15:50:55 +0100 Subject: [PATCH 445/705] AVM: set restartable to true --- avm/plugin.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/avm/plugin.yaml b/avm/plugin.yaml index 098108bd6..e5340da5e 100755 --- a/avm/plugin.yaml +++ b/avm/plugin.yaml @@ -16,6 +16,7 @@ plugin: sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance + restartable: True classname: AVM # class containing the plugin parameters: From 36a7732ae463d8cb272ec3c1b4f08494a9d92904 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 17 Dec 2018 15:52:08 +0100 Subject: [PATCH 446/705] AVM: set minversion to 1.5b, set normal version to 1.5.6 --- avm/__init__.py | 2 +- avm/plugin.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/avm/__init__.py b/avm/__init__.py index caaa88cb8..7c1e1674f 100644 --- a/avm/__init__.py +++ b/avm/__init__.py @@ -505,7 +505,7 @@ class AVM(SmartPlugin): Main class of the Plugin. Does all plugin specific stuff and provides the update functions for the different TR-064 services on the FritzDevice """ - PLUGIN_VERSION = "1.5.5" + PLUGIN_VERSION = "1.5.6" _header = {'SOAPACTION': '', 'CONTENT-TYPE': 'text/xml; charset="utf-8"'} _envelope = """ diff --git a/avm/plugin.yaml b/avm/plugin.yaml index e5340da5e..96bb09e73 100755 --- a/avm/plugin.yaml +++ b/avm/plugin.yaml @@ -12,8 +12,8 @@ plugin: documentation: http://smarthomeng.de/user/plugins/avm/user_doc.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/934835-avm-plugin - version: 1.5.5 # Plugin version - sh_minversion: 1.4c # minimum shNG version to use this plugin + version: 1.5.6 # Plugin version + sh_minversion: 1.5b # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance restartable: True From fe2045b2768eb377277c3dc9b17e5e5d957a93f9 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 17 Dec 2018 16:17:17 +0100 Subject: [PATCH 447/705] Database: added cleanup method to web Gui --- database/__init__.py | 278 +++++++++++--------- database/locale.yaml | 11 +- database/webif/templates/base_database.html | 1 + database/webif/templates/index.html | 9 + 4 files changed, 177 insertions(+), 122 deletions(-) diff --git a/database/__init__.py b/database/__init__.py index 8e92b8d04..de2df1fee 100644 --- a/database/__init__.py +++ b/database/__init__.py @@ -59,26 +59,30 @@ class Database(SmartPlugin): - ALLOW_MULTIINSTANCE = True PLUGIN_VERSION = '1.4.1' # SQL queries: {item} = item table name, {log} = log table name # time, item_id, val_str, val_num, val_bool, changed _setup = { - '1' : ["CREATE TABLE {log} (time BIGINT, item_id INTEGER, duration BIGINT, val_str TEXT, val_num REAL, val_bool BOOLEAN, changed BIGINT);", "DROP TABLE {log};"], - '2' : ["CREATE TABLE {item} (id INTEGER, name varchar(255), time BIGINT, val_str TEXT, val_num REAL, val_bool BOOLEAN, changed BIGINT);", "DROP TABLE {item};"], - '3' : ["CREATE UNIQUE INDEX {log}_{item}_id_time ON {log} (item_id, time);", "DROP INDEX {log}_{item}_id_time;"], - '4' : ["CREATE INDEX {log}_{item}_id_changed ON {log} (item_id, changed);", "DROP INDEX {log}_{item}_id_changed;"], - '5' : ["CREATE UNIQUE INDEX {item}_id ON {item} (id);", "DROP INDEX {item}_id;"], - '6' : ["CREATE INDEX {item}_name ON {item} (name);", "DROP INDEX {item}_name;"] + '1': [ + "CREATE TABLE {log} (time BIGINT, item_id INTEGER, duration BIGINT, val_str TEXT, val_num REAL, val_bool BOOLEAN, changed BIGINT);", + "DROP TABLE {log};"], + '2': [ + "CREATE TABLE {item} (id INTEGER, name varchar(255), time BIGINT, val_str TEXT, val_num REAL, val_bool BOOLEAN, changed BIGINT);", + "DROP TABLE {item};"], + '3': ["CREATE UNIQUE INDEX {log}_{item}_id_time ON {log} (item_id, time);", "DROP INDEX {log}_{item}_id_time;"], + '4': ["CREATE INDEX {log}_{item}_id_changed ON {log} (item_id, changed);", + "DROP INDEX {log}_{item}_id_changed;"], + '5': ["CREATE UNIQUE INDEX {item}_id ON {item} (id);", "DROP INDEX {item}_id;"], + '6': ["CREATE INDEX {item}_name ON {item} (name);", "DROP INDEX {item}_name;"] } def __init__(self, smarthome, driver, connect, prefix="", cycle=60, precision=2): self._sh = smarthome self.shtime = Shtime.get_instance() self.items = Items.get_instance() - + self.logger = logging.getLogger(__name__) self._dump_cycle = int(cycle) self._precision = int(precision) @@ -90,16 +94,17 @@ def __init__(self, smarthome, driver, connect, prefix="", cycle=60, precision=2) self._buffer_lock = threading.Lock() self._dump_lock = threading.Lock() - self._db = lib.db.Database(("" if prefix == "" else prefix.capitalize() + "_") + "Database", driver, Utils.string_to_list(connect)) + self._db = lib.db.Database(("" if prefix == "" else prefix.capitalize() + "_") + "Database", driver, + Utils.string_to_list(connect)) self._initialized = False self._initialize() - smarthome.scheduler.add('Database dump ' + self._name + ("" if prefix == "" else " [" + prefix + "]"), self._dump, cycle=self._dump_cycle, prio=5) + smarthome.scheduler.add('Database dump ' + self._name + ("" if prefix == "" else " [" + prefix + "]"), + self._dump, cycle=self._dump_cycle, prio=5) self.init_webinterface() return - def parse_item(self, item): self.logger.debug(item.conf) if self.has_iattr(item.conf, 'database'): @@ -116,11 +121,13 @@ def parse_item(self, item): try: cache = self.readItem(str(item.id()), cur=cur) if cache is not None: - value = self._item_value_tuple_rev(item.type(), cache[COL_ITEM_VAL_STR:COL_ITEM_VAL_BOOL+1]) + value = self._item_value_tuple_rev(item.type(), cache[COL_ITEM_VAL_STR:COL_ITEM_VAL_BOOL + 1]) last_change = self._datetime(cache[COL_ITEM_TIME]) - prev_change = self._fetchone('SELECT MAX(time) from {log} WHERE item_id = :id', {'id':cache[COL_ITEM_ID]}, cur=cur) + prev_change = self._fetchone('SELECT MAX(time) from {log} WHERE item_id = :id', + {'id': cache[COL_ITEM_ID]}, cur=cur) if value is not None and prev_change is not None: - item.set(value, 'Database', prev_change=self._datetime(prev_change[0]), last_change=last_change) + item.set(value, 'Database', prev_change=self._datetime(prev_change[0]), + last_change=last_change) self._buffer_insert(item, [(self._timestamp(self.shtime.now()), None, value)]) except Exception as e: self.logger.error("Reading cache value from database for {} failed: {}".format(item.id(), e)) @@ -143,37 +150,42 @@ def update_item(self, item, caller=None, source=None, dest=None): if acl is 'rw': start = self._timestamp(item.prev_change()) end = self._timestamp(item.last_change()) - last = None if len(self._buffer[item]) == 0 or self._buffer[item][-1][1] is not None else self._buffer[item][-1] + last = None if len(self._buffer[item]) == 0 or self._buffer[item][-1][1] is not None else \ + self._buffer[item][-1] if last: # update current value with duration self._buffer[item][-1] = (last[0], end - start, last[2]) - else: # append new value with none duration + else: # append new value with none duration self._buffer[item].append((start, end - start, item.prev_value())) # add current value with None duration self._buffer[item].append((end, None, item())) - def dump(self, dumpfile, id = None, time = None, time_start = None, time_end = None, changed = None, changed_start = None, changed_end = None, cur = None): + def dump(self, dumpfile, id=None, time=None, time_start=None, time_end=None, changed=None, changed_start=None, + changed_end=None, cur=None): self.logger.info("Starting file dump to {} ...".format(dumpfile)) item_ids = self.readItems(cur=cur) if id is None else [self.readItem(id, cur=cur)] s = ';' - h = ['item_id', 'item_name', 'time', 'duration', 'val_str', 'val_num', 'val_bool', 'changed', 'time_date', 'changed_date'] + h = ['item_id', 'item_name', 'time', 'duration', 'val_str', 'val_num', 'val_bool', 'changed', 'time_date', + 'changed_date'] f = open(dumpfile, 'w') f.write(s.join(h) + "\n") for item in item_ids: self.logger.debug("... dumping item {}/{}".format(item[1], item[0])) - rows = self.readLogs(item[0], time=time, time_start=time_start, time_end=time_end, changed=changed, changed_start=changed_start, changed_end=changed_end, cur=cur) + rows = self.readLogs(item[0], time=time, time_start=time_start, time_end=time_end, changed=changed, + changed_start=changed_start, changed_end=changed_end, cur=cur) for row in rows: cols = [] for key in [COL_ITEM_ID, COL_ITEM_NAME]: cols.append(item[key]) - for key in [COL_LOG_TIME, COL_LOG_DURATION, COL_LOG_VAL_STR, COL_LOG_VAL_NUM, COL_LOG_VAL_BOOL, COL_LOG_CHANGED]: + for key in [COL_LOG_TIME, COL_LOG_DURATION, COL_LOG_VAL_STR, COL_LOG_VAL_NUM, COL_LOG_VAL_BOOL, + COL_LOG_CHANGED]: cols.append(row[key]) for key in [COL_ITEM_ID, COL_LOG_CHANGED]: - cols.append('' if row[key] is None else datetime.datetime.fromtimestamp(row[key]/1000.0)) + cols.append('' if row[key] is None else datetime.datetime.fromtimestamp(row[key] / 1000.0)) cols = map(lambda col: '' if col is None else col, cols) cols = map(lambda col: str(col) if not '"' in str(col) else col.replace('"', '\\"'), cols) f.write(s.join(cols) + "\n") @@ -205,17 +217,20 @@ def id(self, item, create=True, cur=None): def insertItem(self, name, cur=None): id = self._fetchone("SELECT MAX(id) FROM {item};", cur=cur) - self._execute(self._prepare("INSERT INTO {item}(id, name) VALUES(:id, :name);"), {'id':1 if id[0] == None else id[0]+1, 'name':name}, cur=cur) - id = self._fetchone("SELECT id FROM {item} where name = :name;", {'name':name}, cur=cur) + self._execute(self._prepare("INSERT INTO {item}(id, name) VALUES(:id, :name);"), + {'id': 1 if id[0] == None else id[0] + 1, 'name': name}, cur=cur) + id = self._fetchone("SELECT id FROM {item} where name = :name;", {'name': name}, cur=cur) return int(id[0]) def updateItem(self, id, time, duration=0, val=None, it=None, changed=None, cur=None): - params = {'id':id, 'time':time, 'changed':changed} + params = {'id': id, 'time': time, 'changed': changed} params.update(self._item_value_tuple(it, val)) - self._execute(self._prepare("UPDATE {item} SET time = :time, val_str = :val_str, val_num = :val_num, val_bool = :val_bool, changed = :changed WHERE id = :id;"), params, cur=cur) + self._execute(self._prepare( + "UPDATE {item} SET time = :time, val_str = :val_str, val_num = :val_num, val_bool = :val_bool, changed = :changed WHERE id = :id;"), + params, cur=cur) def readItem(self, id, cur=None): - params = {'id':id} + params = {'id': id} if type(id) == str: return self._fetchone("SELECT {item_columns} from {item} WHERE name = :id;", params, cur=cur) return self._fetchone("SELECT {item_columns} from {item} WHERE id = :id;", params, cur=cur) @@ -224,41 +239,50 @@ def readItems(self, cur=None): return self._fetchall("SELECT {item_columns} from {item};", cur=cur) def deleteItem(self, id, cur=None): - params = {'id':id} + params = {'id': id} self.deleteLog(id, cur=cur) self._execute(self._prepare("DELETE FROM {item} WHERE id = :id;"), params, cur=cur) def insertLog(self, id, time, duration=0, val=None, it=None, changed=None, cur=None): - params = {'id':id, 'time':time, 'changed':changed, 'duration':duration} + params = {'id': id, 'time': time, 'changed': changed, 'duration': duration} params.update(self._item_value_tuple(it, val)) - self._execute(self._prepare("INSERT INTO {log}(item_id, time, val_str, val_num, val_bool, duration, changed) VALUES (:id,:time,:val_str,:val_num,:val_bool,:duration,:changed);"), params, cur=cur) + self._execute(self._prepare( + "INSERT INTO {log}(item_id, time, val_str, val_num, val_bool, duration, changed) VALUES (:id,:time,:val_str,:val_num,:val_bool,:duration,:changed);"), + params, cur=cur) def updateLog(self, id, time, duration=0, val=None, it=None, changed=None, cur=None): - params = {'id':id, 'time':time, 'changed':changed, 'duration':duration} + params = {'id': id, 'time': time, 'changed': changed, 'duration': duration} params.update(self._item_value_tuple(it, val)) - self._execute(self._prepare("UPDATE {log} SET duration = :duration, val_str = :val_str, val_num = :val_num, val_bool = :val_bool, changed = :changed WHERE item_id = :id AND time = :time;"), params, cur=cur) + self._execute(self._prepare( + "UPDATE {log} SET duration = :duration, val_str = :val_str, val_num = :val_num, val_bool = :val_bool, changed = :changed WHERE item_id = :id AND time = :time;"), + params, cur=cur) - def readLog(self, id, time, cur = None): - params = {'id':id, 'time':time} + def readLog(self, id, time, cur=None): + params = {'id': id, 'time': time} return self._fetchall("SELECT {log_columns} FROM {log} WHERE item_id = :id AND time = :time;", params, cur=cur) - def readLogs(self, id, time = None, time_start = None, time_end = None, changed = None, changed_start = None, changed_end = None, cur = None): - condition, params = self._slice_condition(id, time=time, time_start=time_start, time_end=time_end, changed=changed, changed_start=changed_start, changed_end=changed_end) + def readLogs(self, id, time=None, time_start=None, time_end=None, changed=None, changed_start=None, + changed_end=None, cur=None): + condition, params = self._slice_condition(id, time=time, time_start=time_start, time_end=time_end, + changed=changed, changed_start=changed_start, changed_end=changed_end) return self._fetchall("SELECT {log_columns} FROM {log} WHERE " + condition, params, cur=cur) - def deleteLog(self, id, time = None, time_start = None, time_end = None, changed = None, changed_start = None, changed_end = None, cur = None): - condition, params = self._slice_condition(id, time=time, time_start=time_start, time_end=time_end, changed=changed, changed_start=changed_start, changed_end=changed_end) + def deleteLog(self, id, time=None, time_start=None, time_end=None, changed=None, changed_start=None, + changed_end=None, cur=None): + condition, params = self._slice_condition(id, time=time, time_start=time_start, time_end=time_end, + changed=changed, changed_start=changed_start, changed_end=changed_end) self._execute(self._prepare("DELETE FROM {log} WHERE " + condition), params, cur=cur) - def _slice_condition(self, id, time = None, time_start = None, time_end = None, changed = None, changed_start = None, changed_end = None): + def _slice_condition(self, id, time=None, time_start=None, time_end=None, changed=None, changed_start=None, + changed_end=None): params = { - 'id' : id, - 'time' : time, 'time_flag' : 1 if time == None else 0, - 'time_start' : time_start, 'time_start_flag' : 1 if time_start == None else 0, - 'time_end' : time_end, 'time_end_flag' : 1 if time_end == None else 0, - 'changed' : changed, 'changed_flag' : 1 if changed == None else 0, - 'changed_start' : changed_start, 'changed_start_flag' : 1 if changed_start == None else 0, - 'changed_end' : changed_end, 'changed_end_flag' : 1 if changed_end == None else 0 + 'id': id, + 'time': time, 'time_flag': 1 if time == None else 0, + 'time_start': time_start, 'time_start_flag': 1 if time_start == None else 0, + 'time_end': time_end, 'time_end_flag': 1 if time_end == None else 0, + 'changed': changed, 'changed_flag': 1 if changed == None else 0, + 'changed_start': changed_start, 'changed_start_flag': 1 if changed_start == None else 0, + 'changed_end': changed_end, 'changed_end_flag': 1 if changed_end == None else 0 } condition = "(item_id = :id ) AND " + \ @@ -275,27 +299,27 @@ def db(self): def _item_value_tuple(self, item_type, item_val): if item_type == 'num': - val_str = None - val_num = float(item_val) - val_bool = int(bool(item_val)) + val_str = None + val_num = float(item_val) + val_bool = int(bool(item_val)) elif item_type == 'bool': - val_str = None - val_num = float(item_val) - val_bool = int(bool(item_val)) + val_str = None + val_num = float(item_val) + val_bool = int(bool(item_val)) else: - val_str = str(item_val) - val_num = None - val_bool = int(bool(item_val)) + val_str = str(item_val) + val_num = None + val_bool = int(bool(item_val)) - return {'val_str':val_str, 'val_num':val_num, 'val_bool':val_bool} + return {'val_str': val_str, 'val_num': val_num, 'val_bool': val_bool} def _item_value_tuple_rev(self, item_type, item_val_tuple): if item_type == 'num': - return None if item_val_tuple[1] is None else float(item_val_tuple[1]) + return None if item_val_tuple[1] is None else float(item_val_tuple[1]) elif item_type == 'bool': - return None if item_val_tuple[2] is None else bool(int(item_val_tuple[2])) + return None if item_val_tuple[2] is None else bool(int(item_val_tuple[2])) else: - return None if item_val_tuple[0] is None else str(item_val_tuple[0]) + return None if item_val_tuple[0] is None else str(item_val_tuple[0]) def _datetime(self, ts): return datetime.datetime.fromtimestamp(ts / 1000, self.shtime.tzinfo()) @@ -335,9 +359,12 @@ def _dump(self, finalize=False, items=None): if not self._db.lock(300): self._buffer_insert(item, tuples) if finalize: - self.logger.error("Database: can't dump {} items due to fail to acquire lock!".format(len(self._buffer))) + self.logger.error( + "Database: can't dump {} items due to fail to acquire lock!".format(len(self._buffer))) else: - self.logger.error("Database: can't dump {} items due to fail to acquire lock - will try on next dump".format(len(self._buffer))) + self.logger.error( + "Database: can't dump {} items due to fail to acquire lock - will try on next dump".format( + len(self._buffer))) self._dump_lock.release() return @@ -405,10 +432,10 @@ def _buffer_insert(self, item, tuples): return tuples def _expression(self, func): - expression = {'params' : {'op':'!=', 'value':'0'}, 'finalizer' : None} + expression = {'params': {'op': '!=', 'value': '0'}, 'finalizer': None} if ':' in func: expression['finalizer'] = func[:func.index(":")] - func = func[func.index(":")+1:] + func = func[func.index(":") + 1:] if func is 'count' or func.startswith('count'): parts = re.match('(count)((<>|!=|<|=|>)(\d+))?', func) func = 'count' @@ -421,8 +448,8 @@ def _expression(self, func): def _finalize(self, func, tuples): if func == 'diff': final_tuples = [] - for i in range(1, len(tuples)-1): - final_tuples.append((tuples[i][0], tuples[i][1] - tuples[i-1][1])) + for i in range(1, len(tuples) - 1): + final_tuples.append((tuples[i][0], tuples[i][1] - tuples[i - 1][1])) return final_tuples else: return tuples @@ -430,26 +457,26 @@ def _finalize(self, func, tuples): def _series(self, func, start, end='now', count=100, ratio=1, update=False, step=None, sid=None, item=None): init = not update if sid is None: - sid = item + '|' + func + '|' + str(start) + '|' + str(end) + '|' + str(count) + sid = item + '|' + func + '|' + str(start) + '|' + str(end) + '|' + str(count) func, expression = self._expression(func) queries = { - 'avg' : 'MIN(time), ' + self._precision_query('AVG(val_num * duration) / AVG(duration)'), - 'avg.order' : 'ORDER BY time ASC', - 'count' : 'MIN(time), SUM(CASE WHEN val_num{op}{value} THEN 1 ELSE 0 END)'.format(**expression['params']), - 'min' : 'MIN(time), MIN(val_num)', - 'max' : 'MIN(time), MAX(val_num)', - 'on' : 'MIN(time), ' + self._precision_query('SUM(val_bool * duration) / SUM(duration)'), - 'on.order' : 'ORDER BY time ASC', - 'sum' : 'MIN(time), SUM(val_num)', - 'raw' : 'time, val_num', - 'raw.order' : 'ORDER BY time ASC', - 'raw.group' : '' + 'avg': 'MIN(time), ' + self._precision_query('AVG(val_num * duration) / AVG(duration)'), + 'avg.order': 'ORDER BY time ASC', + 'count': 'MIN(time), SUM(CASE WHEN val_num{op}{value} THEN 1 ELSE 0 END)'.format(**expression['params']), + 'min': 'MIN(time), MIN(val_num)', + 'max': 'MIN(time), MAX(val_num)', + 'on': 'MIN(time), ' + self._precision_query('SUM(val_bool * duration) / SUM(duration)'), + 'on.order': 'ORDER BY time ASC', + 'sum': 'MIN(time), SUM(val_num)', + 'raw': 'time, val_num', + 'raw.order': 'ORDER BY time ASC', + 'raw.group': '' } if func not in queries: raise NotImplementedError - order = '' if func+'.order' not in queries else queries[func+'.order'] - group = 'GROUP BY ROUND(time / :step)' if func+'.group' not in queries else queries[func+'.group'] + order = '' if func + '.order' not in queries else queries[func + '.order'] + group = 'GROUP BY ROUND(time / :step)' if func + '.group' not in queries else queries[func + '.group'] logs = self._fetch_log(item, queries[func], start, end, step=step, count=count, group=group, order=order) tuples = logs['tuples'] if tuples: @@ -474,27 +501,28 @@ def _series(self, func, start, end='now', count=100, ratio=1, update=False, step return { 'cmd': 'series', 'series': tuples, 'sid': sid, - 'params' : {'update': True, 'item': item, 'func': func, 'start': logs['iend'], 'end': end, 'step': logs['step'], 'sid': sid}, - 'update' : self.shtime.now() + datetime.timedelta(seconds=int(logs['step'] / 1000)) + 'params': {'update': True, 'item': item, 'func': func, 'start': logs['iend'], 'end': end, + 'step': logs['step'], 'sid': sid}, + 'update': self.shtime.now() + datetime.timedelta(seconds=int(logs['step'] / 1000)) } def _single(self, func, start, end='now', item=None): func, expression = self._expression(func) queries = { - 'avg' : self._precision_query('AVG(val_num * duration) / AVG(duration)'), - 'count' : 'SUM(CASE WHEN val_num{op}{value} THEN 1 ELSE 0 END)'.format(**expression['params']), - 'min' : 'MIN(val_num)', - 'max' : 'MAX(val_num)', - 'on' : self._precision_query('SUM(val_bool * duration) / SUM(duration)'), - 'sum' : 'SUM(val_num)', - 'raw' : 'val_num', - 'raw.order' : 'ORDER BY time DESC', - 'raw.group' : '' + 'avg': self._precision_query('AVG(val_num * duration) / AVG(duration)'), + 'count': 'SUM(CASE WHEN val_num{op}{value} THEN 1 ELSE 0 END)'.format(**expression['params']), + 'min': 'MIN(val_num)', + 'max': 'MAX(val_num)', + 'on': self._precision_query('SUM(val_bool * duration) / SUM(duration)'), + 'sum': 'SUM(val_num)', + 'raw': 'val_num', + 'raw.order': 'ORDER BY time DESC', + 'raw.group': '' } if func not in queries: self.logger.warning("Unknown export function: {0}".format(func)) return - order = '' if func+'.order' not in queries else queries[func+'.order'] + order = '' if func + '.order' not in queries else queries[func + '.order'] logs = self._fetch_log(item, queries[func], start, end, order=order) if logs['tuples'] is None: return @@ -525,7 +553,7 @@ def _fetch_log(self, item, columns, start, end, step=None, count=100, group='', if self._buffer[_item] != []: self._dump(items=[_item]) - params = {'id':id, 'time_start':istart, 'time_end':iend, 'inow':inow, 'step':step} + params = {'id': id, 'time_start': istart, 'time_end': iend, 'inow': inow, 'step': step} duration_now = "COALESCE(duration, :inow - time)" # Duration calculation (S=Start, E=End): @@ -550,12 +578,12 @@ def _fetch_log(self, item, columns, start, end, step=None, count=100, group='', # Create base query including the replaced columns query = ( - "SELECT " + columns + " FROM {log} WHERE " - "item_id = :id AND " - "time >= (SELECT COALESCE(MAX(time), 0) FROM {log} WHERE item_id = :id AND time < :time_start) AND " - "time <= :time_end AND " - "time + duration_now > (SELECT COALESCE(MAX(time), 0) FROM {log} WHERE item_id = :id AND time < :time_start) " - "" + group + " " + order + "SELECT " + columns + " FROM {log} WHERE " + "item_id = :id AND " + "time >= (SELECT COALESCE(MAX(time), 0) FROM {log} WHERE item_id = :id AND time < :time_start) AND " + "time <= :time_end AND " + "time + duration_now > (SELECT COALESCE(MAX(time), 0) FROM {log} WHERE item_id = :id AND time < :time_start) " + "" + group + " " + order ) # Replace duration_now with value from start time til current time to @@ -565,12 +593,12 @@ def _fetch_log(self, item, columns, start, end, step=None, count=100, group='', logs = self._fetchall(query, params) return { - 'tuples' : logs, - 'item' : _item, - 'istart' : istart, - 'iend' : iend, - 'step' : step, - 'count' : count + 'tuples': logs, + 'item': _item, + 'istart': istart, + 'iend': iend, + 'step': step, + 'count': count } def _fetchone(self, query, params={}, cur=None): @@ -612,11 +640,12 @@ def _initialize(self): if not self._db.connected(): self._db.connect() if not self._initialized: - self._db.setup({i: [self._prepare(query[0]), self._prepare(query[1])] for i, query in self._setup.items()}) + self._db.setup( + {i: [self._prepare(query[0]), self._prepare(query[1])] for i, query in self._setup.items()}) self._initialized = True except Exception as e: - self.logger.error("Database: initialization failed: {}".format(e)) - return False + self.logger.error("Database: initialization failed: {}".format(e)) + return False return True def _parse_ts(self, frame): @@ -686,6 +715,7 @@ def init_webinterface(self): return True + # ------------------------------------------ # Webinterface of the plugin # ------------------------------------------ @@ -713,7 +743,6 @@ def __init__(self, webif_dir, plugin): self.tplenv = self.init_template_environment() - @cherrypy.expose def index(self, reload=None, action=None, item_id=None, item_path=None, day=None, month=None, year=None, time_orig=None, changed_orig=None): @@ -726,6 +755,7 @@ def index(self, reload=None, action=None, item_id=None, item_path=None, day=None """ item = self.plugin.get_sh().return_item(item_path) delete_triggered = False + cleanup_triggered = False if action is not None: if action == "delete_log" and item_id is not None: if time_orig is not None and changed_orig is not None: @@ -734,14 +764,14 @@ def index(self, reload=None, action=None, item_id=None, item_path=None, day=None else: self.plugin.deleteLog(item_id) delete_triggered = True - if action == "item_details" and item_id is not None: + elif action == "item_details" and item_id is not None: if day is not None and month is not None and year is not None: time_start = time.mktime(datetime.datetime.strptime("%s/%s/%s" % (month, day, year), - "%m/%d/%Y").timetuple())*1000 + "%m/%d/%Y").timetuple()) * 1000 else: now = self.plugin.shtime.now() time_start = time.mktime(datetime.datetime.strptime("%s/%s/%s" % (now.month, now.day, now.year), - "%m/%d/%Y").timetuple())*1000 + "%m/%d/%Y").timetuple()) * 1000 time_end = time_start + 24 * 60 * 60 * 1000 tmpl = self.tplenv.get_template('item_details.html') @@ -754,24 +784,28 @@ def index(self, reload=None, action=None, item_id=None, item_path=None, day=None if key not in [COL_LOG_TIME, COL_LOG_CHANGED]: value_dict[key] = row[key] else: - value_dict[key] = datetime.datetime.fromtimestamp(row[key]/1000, tz=self.plugin.shtime.tzinfo()) + value_dict[key] = datetime.datetime.fromtimestamp(row[key] / 1000, + tz=self.plugin.shtime.tzinfo()) value_dict["%s_orig" % key] = row[key] log_array.append(value_dict) reversed_arr = log_array[::-1] return tmpl.render(p=self.plugin, items=sorted(self.items.return_items(), key=lambda k: str.lower(k['_path']), - reverse=False), item = item, + reverse=False), item=item, tabcount=1, action=action, item_id=item_id, item_path=item_path, language=self.plugin._sh.get_defaultlanguage(), now=self.plugin.shtime.now(), log_array=reversed_arr, day=day, month=month, year=year, - delete_triggered=delete_triggered) + delete_triggered=delete_triggered, cleanup_triggered=cleanup_triggered) + elif action == "cleanup": + self.plugin.cleanup() + cleanup_triggered = True tmpl = self.tplenv.get_template('index.html') return tmpl.render(p=self.plugin, items=sorted(self.items.return_items(), key=lambda k: str.lower(k['_path']), reverse=False), - tabcount=1, action=action, item_id=item_id, delete_triggered=delete_triggered) - + tabcount=1, action=action, item_id=item_id, delete_triggered=delete_triggered, + cleanup_triggered=cleanup_triggered) @cherrypy.expose def item_csv(self, item_id): @@ -787,34 +821,36 @@ def item_csv(self, item_id): log_array = [] for row in rows: value_dict = {} - for key in [COL_LOG_TIME, COL_LOG_ITEM_ID, COL_LOG_DURATION, COL_LOG_VAL_STR, COL_LOG_VAL_NUM, COL_LOG_VAL_BOOL, COL_LOG_CHANGED]: + for key in [COL_LOG_TIME, COL_LOG_ITEM_ID, COL_LOG_DURATION, COL_LOG_VAL_STR, COL_LOG_VAL_NUM, + COL_LOG_VAL_BOOL, COL_LOG_CHANGED]: value_dict[key] = row[key] log_array.append(value_dict) reversed_arr = log_array[::-1] - csv_file_path = '%s/var/db/%s_item_%s.csv' % (self.plugin._sh.base_dir, self.plugin.get_instance_name(), item_id) + csv_file_path = '%s/var/db/%s_item_%s.csv' % ( + self.plugin._sh.base_dir, self.plugin.get_instance_name(), item_id) with open(csv_file_path, 'w', encoding='utf-8') as f: writer = csv.writer(f, dialect="excel") writer.writerow(['time', 'item_id', 'duration', 'val_str', 'val_num', 'val_bool', 'changed']) for dataset in reversed_arr: - writer.writerow([dataset[0], dataset[1], dataset[2], dataset[3], dataset[4], dataset[5], dataset[6]]) + writer.writerow( + [dataset[0], dataset[1], dataset[2], dataset[3], dataset[4], dataset[5], dataset[6]]) cherrypy.request.fileName = csv_file_path cherrypy.request.hooks.attach('on_end_request', self.download_complete) return cherrypy.lib.static.serve_download(csv_file_path) - def download_complete(self): os.unlink(cherrypy.request.fileName) - @cherrypy.expose def db_dump(self): """ returns the smarthomeNG sqlite database as download """ - self.plugin.dump('%s/var/db/smarthomedb_%s.dump' % (self.plugin.get_sh().base_dir, self.plugin.get_instance_name())) + self.plugin.dump( + '%s/var/db/smarthomedb_%s.dump' % (self.plugin.get_sh().base_dir, self.plugin.get_instance_name())) mime = 'application/octet-stream' return cherrypy.lib.static.serve_file( "%s/var/db/smarthomedb_%s.dump" % (self.plugin.get_sh().base_dir, self.plugin.get_instance_name()), diff --git a/database/locale.yaml b/database/locale.yaml index e4eb6b683..3e1484b2b 100644 --- a/database/locale.yaml +++ b/database/locale.yaml @@ -62,4 +62,13 @@ plugin_translations: 'en': 'Delete Value' 'Zeige Einträge vom': 'de': 'Zeige Einträge vom' - 'en': 'Show entries from' \ No newline at end of file + 'en': 'Show entries from' + 'Datenbank-Cleanup': + 'de': '=' + 'en': 'Database Cleanup' + 'Datenbank-Cleanup wurde erfolgreich initiiert!': + 'de': '=' + 'en': 'Database cleanup successfully initiated!' + 'Das Löschen von Einträgen, für die es keine Items mehr gibt, kann noch kurze Zeit dauern, da die Ausführung erst nach Abschluß der bestehenden Transaktionen erfolgen kann': + 'de': '=' + 'en': 'The cleanup of entries, for which no items exist anymore, can take a while, as it can only be processed after the end of already existing database transactions.' \ No newline at end of file diff --git a/database/webif/templates/base_database.html b/database/webif/templates/base_database.html index 7c8b4edbd..48b3308c2 100644 --- a/database/webif/templates/base_database.html +++ b/database/webif/templates/base_database.html @@ -46,4 +46,5 @@ {% block buttons %} + {% endblock buttons %} \ No newline at end of file diff --git a/database/webif/templates/index.html b/database/webif/templates/index.html index 907372c9a..6e95fe22c 100644 --- a/database/webif/templates/index.html +++ b/database/webif/templates/index.html @@ -19,6 +19,15 @@ {% endif %} +{% if cleanup_triggered %} + +{% endif %}
{{ _('Die folgenden Items sind dieser Instanz des Database Plugins zugewiesen') }}: From d956bbf861e6d86144a874e69489c76e12e991bf Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 17 Dec 2018 16:25:16 +0100 Subject: [PATCH 448/705] Database: added "." --- database/locale.yaml | 2 +- database/webif/templates/index.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/database/locale.yaml b/database/locale.yaml index 3e1484b2b..f20842a78 100644 --- a/database/locale.yaml +++ b/database/locale.yaml @@ -69,6 +69,6 @@ plugin_translations: 'Datenbank-Cleanup wurde erfolgreich initiiert!': 'de': '=' 'en': 'Database cleanup successfully initiated!' - 'Das Löschen von Einträgen, für die es keine Items mehr gibt, kann noch kurze Zeit dauern, da die Ausführung erst nach Abschluß der bestehenden Transaktionen erfolgen kann': + 'Das Löschen von Einträgen, für die es keine Items mehr gibt, kann noch kurze Zeit dauern, da die Ausführung erst nach Abschluß der bestehenden Transaktionen erfolgen kann.': 'de': '=' 'en': 'The cleanup of entries, for which no items exist anymore, can take a while, as it can only be processed after the end of already existing database transactions.' \ No newline at end of file diff --git a/database/webif/templates/index.html b/database/webif/templates/index.html index 6e95fe22c..5ffc2ecb3 100644 --- a/database/webif/templates/index.html +++ b/database/webif/templates/index.html @@ -22,7 +22,7 @@ {% if cleanup_triggered %}
{% endblock headtable %} -{% block buttons %} - - -{% endblock buttons %} \ No newline at end of file diff --git a/database/webif/templates/index.html b/database/webif/templates/index.html index 5ffc2ecb3..7844be609 100644 --- a/database/webif/templates/index.html +++ b/database/webif/templates/index.html @@ -57,3 +57,7 @@ {% endfor %} {% endblock bodytab1 %} +{% block buttons %} + + +{% endblock buttons %} \ No newline at end of file From 1346aaa134219938ac04b98d2ea443011b58efe0 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 17 Dec 2018 16:33:51 +0100 Subject: [PATCH 450/705] Database: added reference to new Items Lib --- database/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/database/__init__.py b/database/__init__.py index de2df1fee..efd1dee91 100644 --- a/database/__init__.py +++ b/database/__init__.py @@ -753,7 +753,8 @@ def index(self, reload=None, action=None, item_id=None, item_path=None, day=None :return: contents of the template after beeing rendered """ - item = self.plugin.get_sh().return_item(item_path) + if item_path is not None: + item = Items.return_item(item_path) delete_triggered = False cleanup_triggered = False if action is not None: From 5216ad740eb443eeb52a2ea2924e1c0d6494a7af Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 17 Dec 2018 16:34:39 +0100 Subject: [PATCH 451/705] Database: upgrade version to 1.5 core --- database/__init__.py | 2 +- database/plugin.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/database/__init__.py b/database/__init__.py index efd1dee91..9070ebd9a 100644 --- a/database/__init__.py +++ b/database/__init__.py @@ -60,7 +60,7 @@ class Database(SmartPlugin): ALLOW_MULTIINSTANCE = True - PLUGIN_VERSION = '1.4.1' + PLUGIN_VERSION = '1.5.2' # SQL queries: {item} = item table name, {log} = log table name # time, item_id, val_str, val_num, val_bool, changed diff --git a/database/plugin.yaml b/database/plugin.yaml index 42f2e1740..13995f3d0 100755 --- a/database/plugin.yaml +++ b/database/plugin.yaml @@ -11,8 +11,8 @@ plugin: keywords: database documentation: http://smarthomeng.de/user/plugins/database/user_doc.html - version: 1.4.1 # Plugin version - sh_minversion: 1.4c # minimum shNG version to use this plugin + version: 1.5.2 # Plugin version + sh_minversion: 1.5b # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance restartable: unknown From 03b4498da7817bb0b615a37b5f6ec25a1dbae5c3 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 17 Dec 2018 16:39:25 +0100 Subject: [PATCH 452/705] Database: corrected use of item lib from webif --- database/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/__init__.py b/database/__init__.py index 9070ebd9a..2c12e4b7f 100644 --- a/database/__init__.py +++ b/database/__init__.py @@ -754,7 +754,7 @@ def index(self, reload=None, action=None, item_id=None, item_path=None, day=None :return: contents of the template after beeing rendered """ if item_path is not None: - item = Items.return_item(item_path) + item = self.plugin.items.return_item(item_path) delete_triggered = False cleanup_triggered = False if action is not None: From 86d0f4e9822e6458977d631b1254d9be178430c3 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 17 Dec 2018 18:12:15 +0100 Subject: [PATCH 453/705] AVM: use of p.get_sh in web interface --- avm/webif/templates/index.html | 33 +-------------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/avm/webif/templates/index.html b/avm/webif/templates/index.html index 14a857089..04a1799b2 100644 --- a/avm/webif/templates/index.html +++ b/avm/webif/templates/index.html @@ -2,7 +2,7 @@ {% set tab1title = _('AVM Items') %} {% set tab2title = _('Plugin-API') %} {% set tab3title = _('Call Monitor Items') %} -{% set language = p._sh.get_defaultlanguage() %} +{% set language = p.get_sh().get_defaultlanguage() %} {% if language not in ['en','de'] %} {% set language = 'en' %} {% endif %} @@ -66,37 +66,6 @@
{% endblock %} -{% block bodytab2 %} -
- {% for function, dict in p.metadata.plugin_functions.items() %} -
-
- {{ dict['type'] }} {{ function }}({% if dict['parameters'] is not none %}{% for name, paramdict in dict['parameters'].items() %}{{ name }}: {{ paramdict['type'] }}{% endfor %}{% endif %}) -
-
- {{ dict['description'][language] }}
- {% if dict['parameters'] is not none %} -
-
- {{ _('Parameter') }}: -
-
-
    - {% for name, paramdict in dict['parameters'].items() %} -
  • - {{ name }}: {{ paramdict['type'] }}
    - {{ paramdict['description'][language] }} -
  • - {% endfor %} -
-
-
- {% endif %} -
-
- {% endfor %} -
-{% endblock %} {% block bodytab3 %} {% if p._call_monitor %} From 6a643d719f36884698fb41b04d5cacea2f494250 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 17 Dec 2018 18:12:34 +0100 Subject: [PATCH 454/705] Database: added plugin api overview to webif (every page!) --- database/__init__.py | 4 +-- database/locale.yaml | 5 ++- database/webif/templates/base_database.html | 35 +++++++++++++++++++++ database/webif/templates/index.html | 3 +- database/webif/templates/item_details.html | 2 +- 5 files changed, 44 insertions(+), 5 deletions(-) diff --git a/database/__init__.py b/database/__init__.py index 2c12e4b7f..8d11115ee 100644 --- a/database/__init__.py +++ b/database/__init__.py @@ -794,7 +794,7 @@ def index(self, reload=None, action=None, item_id=None, item_path=None, day=None return tmpl.render(p=self.plugin, items=sorted(self.items.return_items(), key=lambda k: str.lower(k['_path']), reverse=False), item=item, - tabcount=1, action=action, item_id=item_id, item_path=item_path, + tabcount=2, action=action, item_id=item_id, item_path=item_path, language=self.plugin._sh.get_defaultlanguage(), now=self.plugin.shtime.now(), log_array=reversed_arr, day=day, month=month, year=year, delete_triggered=delete_triggered, cleanup_triggered=cleanup_triggered) @@ -805,7 +805,7 @@ def index(self, reload=None, action=None, item_id=None, item_path=None, day=None tmpl = self.tplenv.get_template('index.html') return tmpl.render(p=self.plugin, items=sorted(self.items.return_items(), key=lambda k: str.lower(k['_path']), reverse=False), - tabcount=1, action=action, item_id=item_id, delete_triggered=delete_triggered, + tabcount=2, action=action, item_id=item_id, delete_triggered=delete_triggered, cleanup_triggered=cleanup_triggered) @cherrypy.expose diff --git a/database/locale.yaml b/database/locale.yaml index f20842a78..851c10b11 100644 --- a/database/locale.yaml +++ b/database/locale.yaml @@ -71,4 +71,7 @@ plugin_translations: 'en': 'Database cleanup successfully initiated!' 'Das Löschen von Einträgen, für die es keine Items mehr gibt, kann noch kurze Zeit dauern, da die Ausführung erst nach Abschluß der bestehenden Transaktionen erfolgen kann.': 'de': '=' - 'en': 'The cleanup of entries, for which no items exist anymore, can take a while, as it can only be processed after the end of already existing database transactions.' \ No newline at end of file + 'en': 'The cleanup of entries, for which no items exist anymore, can take a while, as it can only be processed after the end of already existing database transactions.' + 'Plugin-API': {'de': '=', 'en': 'Plugin API', 'fr': ''} + 'Database Items': {'de': '=', 'en': '=', 'fr': ''} + 'Parameter': {'de': '=', 'en': 'Parameters', 'fr': ''} \ No newline at end of file diff --git a/database/webif/templates/base_database.html b/database/webif/templates/base_database.html index 9f027b9fd..11306a26a 100644 --- a/database/webif/templates/base_database.html +++ b/database/webif/templates/base_database.html @@ -1,4 +1,6 @@ {% extends "base_plugin.html" %} +{% set tab2title = _('Plugin-API') %} +{% set language = p.get_sh().get_defaultlanguage() %} {%- block scripts %} {{ super() }} @@ -44,3 +46,36 @@
{% endblock headtable %} +{% block bodytab2 %} +
+ {% for function, dict in p.metadata.plugin_functions.items() %} +
+
+ {{ dict['type'] }} {{ function }}({% if 'parameters' in dict %}{% if dict['parameters'] is not none %}{% for name, paramdict in dict['parameters'].items() %}{{ name }}: {{ paramdict['type'] }}{% endfor %}{% endif %}{% endif %}) +
+
+ {{ dict['description'][language] }}
+ {% if 'parameters' in dict %} + {% if dict['parameters'] is not none %} +
+
+ {{ _('Parameter') }}: +
+
+
    + {% for name, paramdict in dict['parameters'].items() %} +
  • + {{ name }}: {{ paramdict['type'] }}
    + {{ paramdict['description'][language] }} +
  • + {% endfor %} +
+
+
+ {% endif %} + {% endif %} +
+
+ {% endfor %} +
+{% endblock bodytab2 %} \ No newline at end of file diff --git a/database/webif/templates/index.html b/database/webif/templates/index.html index 7844be609..00d3b8957 100644 --- a/database/webif/templates/index.html +++ b/database/webif/templates/index.html @@ -1,5 +1,5 @@ {% extends "base_database.html" %} - +{% set tab1title = _('Database Items') %} {% block bodytab1 %}
{{ _('Die folgenden Items sind dieser Instanz des Database Plugins zugewiesen') }}: @@ -60,5 +67,5 @@ {% block buttons %} - + {% endblock buttons %} \ No newline at end of file From c59bb850ad99d0f6f81beab335ddb2b649ebf6bd Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Tue, 18 Dec 2018 00:14:14 +0100 Subject: [PATCH 464/705] stateengine plugin: docu and widget update - added and fixed documentation as rst files instead of web interface - added smartvisu widget including example --- stateengine/README.md | 11 +- stateengine/__init__.py | 2 +- stateengine/plugin.yaml | 6 +- .../sv_widgets/stateengine.example.html | 52 ++ stateengine/sv_widgets/stateengine.js | 55 ++ .../sv_widgets/widget_stateengine.html | 19 + stateengine/user_doc.rst | 27 + stateengine/user_doc/user_doc1.rst | 59 ++ stateengine/user_doc/user_doc10.rst | 96 +++ stateengine/user_doc/user_doc11.rst | 22 + stateengine/user_doc/user_doc12.rst | 72 ++ stateengine/user_doc/user_doc13.rst | 321 ++++++++ stateengine/user_doc/user_doc14.rst | 19 + stateengine/user_doc/user_doc15.rst | 675 +++++++++++++++++ stateengine/user_doc/user_doc2.rst | 115 +++ stateengine/user_doc/user_doc3.rst | 204 ++++++ stateengine/user_doc/user_doc4.rst | 165 +++++ stateengine/user_doc/user_doc5.rst | 300 ++++++++ stateengine/user_doc/user_doc6.rst | 94 +++ stateengine/user_doc/user_doc7.rst | 277 +++++++ stateengine/user_doc/user_doc8.rst | 288 ++++++++ stateengine/user_doc/user_doc9.rst | 99 +++ stateengine/webif/templates/doku1.html | 123 ---- stateengine/webif/templates/doku10.html | 128 ---- stateengine/webif/templates/doku11.html | 88 --- stateengine/webif/templates/doku12.html | 121 --- stateengine/webif/templates/doku13.html | 304 -------- stateengine/webif/templates/doku14.html | 85 --- stateengine/webif/templates/doku15.html | 687 ------------------ stateengine/webif/templates/doku2.html | 132 ---- stateengine/webif/templates/doku3.html | 203 ------ stateengine/webif/templates/doku4.html | 185 ----- stateengine/webif/templates/doku5.html | 266 ------- stateengine/webif/templates/doku6.html | 157 ---- stateengine/webif/templates/doku7.html | 260 ------- stateengine/webif/templates/doku8.html | 234 ------ stateengine/webif/templates/doku9.html | 146 ---- stateengine/webif/templates/index.html | 59 +- 38 files changed, 2974 insertions(+), 3182 deletions(-) create mode 100755 stateengine/sv_widgets/stateengine.example.html create mode 100755 stateengine/sv_widgets/stateengine.js create mode 100755 stateengine/sv_widgets/widget_stateengine.html create mode 100755 stateengine/user_doc.rst create mode 100755 stateengine/user_doc/user_doc1.rst create mode 100644 stateengine/user_doc/user_doc10.rst create mode 100644 stateengine/user_doc/user_doc11.rst create mode 100644 stateengine/user_doc/user_doc12.rst create mode 100644 stateengine/user_doc/user_doc13.rst create mode 100644 stateengine/user_doc/user_doc14.rst create mode 100644 stateengine/user_doc/user_doc15.rst create mode 100644 stateengine/user_doc/user_doc2.rst create mode 100644 stateengine/user_doc/user_doc3.rst create mode 100644 stateengine/user_doc/user_doc4.rst create mode 100644 stateengine/user_doc/user_doc5.rst create mode 100644 stateengine/user_doc/user_doc6.rst create mode 100644 stateengine/user_doc/user_doc7.rst create mode 100644 stateengine/user_doc/user_doc8.rst create mode 100644 stateengine/user_doc/user_doc9.rst delete mode 100755 stateengine/webif/templates/doku1.html delete mode 100755 stateengine/webif/templates/doku10.html delete mode 100755 stateengine/webif/templates/doku11.html delete mode 100755 stateengine/webif/templates/doku12.html delete mode 100755 stateengine/webif/templates/doku13.html delete mode 100755 stateengine/webif/templates/doku14.html delete mode 100755 stateengine/webif/templates/doku15.html delete mode 100755 stateengine/webif/templates/doku2.html delete mode 100755 stateengine/webif/templates/doku3.html delete mode 100755 stateengine/webif/templates/doku4.html delete mode 100755 stateengine/webif/templates/doku5.html delete mode 100755 stateengine/webif/templates/doku6.html delete mode 100755 stateengine/webif/templates/doku7.html delete mode 100755 stateengine/webif/templates/doku8.html delete mode 100755 stateengine/webif/templates/doku9.html diff --git a/stateengine/README.md b/stateengine/README.md index f0ccd0d0d..f2f6f7514 100755 --- a/stateengine/README.md +++ b/stateengine/README.md @@ -8,17 +8,22 @@ Finite state machine plugin for smarthomeNG, previously known as AutoBlind If you require support, please raise an issue at GitHub: ## Documentation -The manual can be found in the Wiki at GitHub: . +The manual can be found on the official SmarthomeNG plugin documentation: . +A "Getting Started" blog entry can be found at the [SmarthomeNG Blog] +(https://www.smarthomeng.de/starting-with-state-machine-automation-autoblind-plugin) ## Configuration ### plugin.yaml -See the [manual at GitHub](https://github.com/i-am-offline/smarthome.plugin.autoblind/wiki) +See the [manual at SmarthomeNG](https://www.smarthomeng.de/user/plugins/stateengine/user_doc.html) ### items.yaml -See the [manual at GitHub](https://github.com/i-am-offline/smarthome.plugin.autoblind/wiki) +See the [manual at SmarthomeNG](https://www.smarthomeng.de/user/plugins/stateengine/user_doc.html) ## Changelog +### v1.4.2 +* Added and fixed documentation (onkelandy) + ### v1.4.1 * Added to official develop repository (onkelandy) * Renamed to StateEngine (onkelandy) diff --git a/stateengine/__init__.py b/stateengine/__init__.py index e654b0cb6..dc9a1c55e 100755 --- a/stateengine/__init__.py +++ b/stateengine/__init__.py @@ -32,7 +32,7 @@ class StateEngine(SmartPlugin): - PLUGIN_VERSION = '1.4.1' + PLUGIN_VERSION = '1.4.2' # Constructor # noinspection PyUnusedLocal,PyMissingConstructor diff --git a/stateengine/plugin.yaml b/stateengine/plugin.yaml index 01b008bcd..8c398f585 100755 --- a/stateengine/plugin.yaml +++ b/stateengine/plugin.yaml @@ -5,10 +5,10 @@ plugin: description: de: 'Zustandsautomat für SmarthomeNG, ehemals AutoBlind' en: 'Finite state machine for SmarthomeNG, previously known as AutoBlind' - mainainer: i-am-offline - documentation: https://github.com/i-am-offline/smarthome.plugin.autoblind/wiki + maintainer: i-am-offline, onkelandy + documentation: https://www.smarthomeng.de/user/plugins/stateengine/user_doc.html - version: 1.4.1 + version: 1.4.2 sh_minversion: 1.4.1 multi_instance: False classname: StateEngine diff --git a/stateengine/sv_widgets/stateengine.example.html b/stateengine/sv_widgets/stateengine.example.html new file mode 100755 index 000000000..eeb10fb33 --- /dev/null +++ b/stateengine/sv_widgets/stateengine.example.html @@ -0,0 +1,52 @@ +/** +* ----------------------------------------------------------------------------- +* @package smartVISU +* @author Martin Gleiß +* @copyright 2012 - 2015 +* @license GPL [http://www.gnu.de] +* ----------------------------------------------------------------------------- +*/ +{% extends "base.html" %} + + +{% import "widgets/stateengine.html" as stateengine %} +{% import "basic.html" as basic %} + +{% block content %} +
Here you could define any basic widget you want
+
+

Changing the state via menu changes the icon of the stateengine widget. This demo is limited but in a real world scenario the widget would work like followed. Of course you can set either the locked item or the release item to empty to change the behaviour of the widget.

+ Short click/tap:
+ If the item is in any state but locked, the stateengine item would change to locked mode
+ If the item is in locked state, the stateengine would leave locked mode and retrigger evaluation (not working in this demo)
+ If the item is in suspended mode the release state would be triggered instead of the locked (not working in this demo)
+

+ Long click/tap:
+ Open a popup window with further widgets (limited function in this demo)
+ For this demo this is achieved by using javascript, but in a real world example you can use the approach mentioned in the README. + +

+ + +
Example:
+ {% filter trim|escape|nl2br %}{% verbatim %} + {{ stateengine.state('updatestuff', 'stateengine_item', 'lockitem', 'releaseitem', 'icons/ws/secur_locked.svg, icons/ws/time_manual_mode.svg, icons/ws/time_automatic.svg', 'locked,suspended,standard', 'popupstuff') }} + {% endverbatim %}{% endfilter %} +
+
+ {{ basic.select('', 'stateengine_item', '', ['locked', 'suspended', 'standard'], '', ['locked', 'suspended', 'standard']) }} + {{ stateengine.state('updatestuff', 'stateengine_item', 'lockitem', 'releaseitem', 'icons/ws/secur_locked.svg, icons/ws/time_manual_mode.svg, icons/ws/time_automatic.svg', 'locked,suspended,standard', 'popupstuff') }} +
+ +
+ +{% endblock %} diff --git a/stateengine/sv_widgets/stateengine.js b/stateengine/sv_widgets/stateengine.js new file mode 100755 index 000000000..115a012af --- /dev/null +++ b/stateengine/sv_widgets/stateengine.js @@ -0,0 +1,55 @@ +// ----- stateenginestatus ------------------------------------------------------ + +$.widget("sv.stateengine", $.sv.widget, { + + initSelector: '[data-widget="stateengine.state"]', + + options: { + + }, + _update: function (response) { + // get list of values and images + list_val = this.element.attr('data-vals').explode(); + list_img = this.element.attr('data-img').explode(); + + // get the index of the value received + idx = list_val.indexOf(response.toString()); + + // update the image + $('#' + this.element.attr("id") + ' img').attr('src', list_img[idx]); + + $('#' + this.element.attr("id")).show(); + console.log('ID '+this.element.attr('id')+' image '+list_img[idx]); + // memorise the index for next use + this.element.val(idx); + }, + + _events: { + 'taphold': function (event, response) { + event.preventDefault(); + event.stopPropagation(); + console.log('Long press '+this.element.attr('rel')); + + $("#"+this.element.attr('rel')).popup( "open" ); + return false; + }, + 'tap': function (event, response) { + if (this.element.attr('lock-item') == '' && this.element.attr('release-item') == '') { + $("#"+this.element.attr('rel')).popup( "open" ); + } + else if (list_val[idx] == 'locked' && this.element.attr('lock-item') != ''){ + io.write(this.element.attr('lock-item'), (this.element.val() == this.element.attr('data-val-on') ? this.element.attr('data-val-off') : this.element.attr('data-val-on')) ); + console.log('Short press lock '+this.element.attr('rel')); + } + else if (list_val[idx] == 'suspended' && this.element.attr('release-item') != ''){ + io.write(this.element.attr('release-item'), true ); + console.log('Short press release '+this.element.attr('rel')); + } + else { + io.write(this.element.attr('lock-item'), (this.element.val() == this.element.attr('data-val-on') ? this.element.attr('data-val-off') : this.element.attr('data-val-on')) ); + console.log('Short press else '+this.element.val()+', setting lock item '+ this.element.attr('lock-item')); + } + } + } + +}); diff --git a/stateengine/sv_widgets/widget_stateengine.html b/stateengine/sv_widgets/widget_stateengine.html new file mode 100755 index 000000000..1f469293d --- /dev/null +++ b/stateengine/sv_widgets/widget_stateengine.html @@ -0,0 +1,19 @@ +/** +* Extended Autostate widget: showing an icon depending on the state an item is in (using autoblind plugin). Popup on longpress. +* +* @param {id=} unique id for this widget (optional) +* @param {item} an item the state should be shown for +* @param {item=} lock state item for your item (optional) +* @param {release=} release state item for your item. If available this state is activated when you click on the icon (optional) +* @param {image[]} array of icons to be shown corresponding to the values stated in the next attribute +* @param {text[]} array of values corresponding to the icons stated in the previous attribute +* @param {text} id of the popup widget to open on longpress +*/ +{% macro state(id, item, lock, release, pic, val, popup) %} + {% import "basic.html" as basic %} + + {{ basic.icon(pic[0]|deficon('time_automatic'), 'icon0') }} + +{% endmacro %} diff --git a/stateengine/user_doc.rst b/stateengine/user_doc.rst new file mode 100755 index 000000000..f7f6ded9c --- /dev/null +++ b/stateengine/user_doc.rst @@ -0,0 +1,27 @@ +.. index:: Plugins; Stateengine +.. index:: Stateengine + +Stateengine +########### + +Konfiguration +============= + +.. toctree:: + :numbered: + + user_doc/user_doc1.rst + user_doc/user_doc2.rst + user_doc/user_doc3.rst + user_doc/user_doc4.rst + user_doc/user_doc5.rst + user_doc/user_doc6.rst + user_doc/user_doc7.rst + user_doc/user_doc8.rst + user_doc/user_doc9.rst + user_doc/user_doc10.rst + user_doc/user_doc11.rst + user_doc/user_doc12.rst + user_doc/user_doc13.rst + user_doc/user_doc14.rst + user_doc/user_doc15.rst diff --git a/stateengine/user_doc/user_doc1.rst b/stateengine/user_doc/user_doc1.rst new file mode 100755 index 000000000..6714650a2 --- /dev/null +++ b/stateengine/user_doc/user_doc1.rst @@ -0,0 +1,59 @@ +.. index:: Plugins; Stateengine; Allgemein +.. index:: Allgemein + +Allgemein +######### + +.. important:: + + Es ist nicht empfehlenswert das stateengine Plugin + für sicherheitsrelevante Zustände, wie zum Beispiel das Hochfahren + von Jalousien bei zu viel Wind, zu verwenden. Sicherheitsrelevante + Funktionen müssen so einfach wie möglich aufgebaut sein. Es wird + daher dringend dazu geraten, solche Funktionen unabhängig von + smarthomeNG und dem stateengine Plugin zu realisieren. Für das + Hochfahren von Jalousien bei Windalarm beispielsweise sollte die + Sperrfunktionalität verwendet werden, über die alle aktuellen + Jalousieaktoren verfügen! + +.. rubric:: Funktionalität + :name: funktionalitaet + +Über zusätzliche Items in den items/\*.conf-Dateien können Objekte +definiert werden, die eine beliebige Anzahl benutzerdefinierter +Zustand haben. Jeder Zustand kann Sets von Einstiegs- und +Ausstiegsbedingungen haben, sowie diverse Aktionen auslösen, wenn +der Zustand aktiv wird. In regelmäßigen Intervallen werden die +Zustände für jedes Objekt geprüft. + +- Wenn die Ausstiegsbedingungen des aktuellen Zustands nicht + erfüllt sind bleibt das Objekt im aktuellen Zustand. +- Wenn der aktuelle Zustand verlassen werden kann werden alle + Zustände in der Reihenfolge, in der sie in der + Konfigurationsdatei definiert sind, abgeprüft. +- Der erste Zustand bei dem eine Gruppe Einstiegsbedingungen + vollständig erfüllt ist, wird zum aktuellen Zustand. Die + Aktionen, die für diesen Zustand definiert sind, werden + ausgeführt. +- Wenn kein passender Zustand gefunden wird passiert nichts. Das + Objekt verbleibt im vorherigen Zustand. + +Die folgenden Bedingungen können Teil der Bedingungsgruppen sein: + +- Tageszeit (Minimum, Maximum, Wert) +- Wochentag (Minimum, Maximum, Wert) +- Azimut der Sonne (Minimum, Maximum, Wert) +- Altitude der Sonne (Minimum, Maximum, Wert) +- Alter des aktuellen Zustands (Minimum, Maximum, Wert) +- Zufallszahl (Minimum, Maximum, Wert) +- Vorheriger Zustand (Wert) +- Trigger-Objekt, dass die Zustandsermittlung ausgelöst hat + +Zusätzlich können beliebige Items als Bedingungen geprüft werden +(Minimum, Maximum oder Wert) + +Der ursprüngliche Zweck dieses Plugins war es, Jalousien zu +steuern. Mit den steigenden Anforderungen hat es sich jedoch zu +einem flexiblen Zustandsautomaten entwickelt, mit dem nahezu alles +gesteuert werden kann. Im Prinzip ist es ein `endlicher +Automat `_. diff --git a/stateengine/user_doc/user_doc10.rst b/stateengine/user_doc/user_doc10.rst new file mode 100644 index 000000000..394916455 --- /dev/null +++ b/stateengine/user_doc/user_doc10.rst @@ -0,0 +1,96 @@ +.. index:: Plugins; Stateengine; Vordefinierte Funktionen +.. index:: Vordefinierte Funktionen + +Vordefinierte Funktionen +######################## + +.. rubric:: Vordefinierte Funktionen + :name: vordefiniertefunktionen + +Das stateengine Plugin stellt verschiedene vordefinierte +Funktionen zur Verfügung die einfach für +``se_set_`` und ``se_run_`` Aktionen +verwendet werden können. Diese Funktionen sind in einer Klasse +enthalten, die bei Bedarf für das Ausführen der Aktion +instanziiert wird. Die folgenden Funktionen können verwendet +werden: + +.. rubric:: Winkel zum Nachführen der Jalousielamellen auf Basis des Sonnenstands berechnen + :name: winkel + +.. code-block:: yaml + + stateengine_eval.sun_tracking() + + +.. rubric:: Zufallszahl + :name: zufallszahl + +.. code-block:: yaml + + stateengine_eval.get_random_int(min,max) + +Über ``min`` und ``max`` kann die kleinste/größte Nummer, die +zurückgegeben werden soll, festgelegt werden. ``min`` und +``max`` können weggelassen werden, in diesem Fall sind die +Vorgabewerte 0 für ``min`` und 255 für ``max``. + +.. rubric:: Shell-Kommando ausführen + :name: shellkommandoausfhren + +.. code-block:: yaml + + stateengine_eval.execute(command) + +Führt das Shell-Kommando ``command`` aus + +.. rubric:: Wert einer Variable ermitteln + :name: werteinervariableermitteln + +.. code-block:: yaml + + stateengine_eval.get_variable(varname) + +Liefert den Wert der :ref:`Variablen` ``varname`` + +.. rubric:: Item-Id relativ zum Objekt-Item ermitteln + :name: itemidrelativzumobjektitemermitteln + +.. code-block:: yaml + + stateengine_eval.get_relative_itemid(subitem_id) + +Eine Item-Id relativ zur Item-Id des Objekt-Items wird ermittelt. +Die Ermittlung erfolgt dabei mit der gleichen Rotine, die zur +relativen Ermittlung von Items verwendet wird. + +.. rubric:: Item-Wert relativ zum Objekt-Item ermitteln + :name: itemwertrelativzumobjektitemermitteln + +.. code-block:: yaml + + stateengine_eval.get_relative_itemvalue(subitem_id) + +Der Wert eines Items relativ zur Item-Id des Objekt-Items wird +ermittelt. Die Ermittlung erfolgt dabei mit der gleichen Rotine, +die zur relativen Ermittlung von Items verwendet wird. + +.. rubric:: Suspend-Ende in einen Text einsetzen + :name: suspendendeineinentexteinsetzen + +.. code-block:: yaml + + stateengine_eval.insert_suspend_time(suspend_item_id, suspend_text="Ausgesetzt bis %X") + +Das Ende der Suspend-Zeit wird in den Text ``suspend_text`` +eingesetzt. Im Text sind daher entsprechende Platzhalter +vorzusehen (Siehe `strftime() and strptime() +Behavior `_). +Wird kein ``suspend_text`` angegeben, so wird als Vorgabewert +"Ausgesetzt bis %X" verwendet. + +Zur Ermittlung des Endes der Suspend-Zeit muss über +``suspend_item_id`` ein Item angegeben werden, dessen Wert bei +Eintritt in den Suspend-Status geändert wird. Über das Alter des +Werts in diesem Item wird die bereits abgelaufene Suspend-Zeit +bestimmt. diff --git a/stateengine/user_doc/user_doc11.rst b/stateengine/user_doc/user_doc11.rst new file mode 100644 index 000000000..a119b7287 --- /dev/null +++ b/stateengine/user_doc/user_doc11.rst @@ -0,0 +1,22 @@ +.. index:: Plugins; Stateengine; Variablen +.. index:: Variablen +.. _Variablen: + +Variablen +######### + +.. rubric:: Variablen + :name: variablen + +Mit dem Datentyp AbValue kann +auf Variablen des Plugins zugegriffen werden. Derzeit stehen +folgende Variablen zur Verfügung: + +| **item.suspend_time:** +| *Die Suspend-Time des Items* + +| **current.state_id:** +| *Die Id des Status, der gerade geprüft wird* + +| **current.state_name:** +| *Der Name des Status, der gerade geprüft wird* diff --git a/stateengine/user_doc/user_doc12.rst b/stateengine/user_doc/user_doc12.rst new file mode 100644 index 000000000..6cd2c1642 --- /dev/null +++ b/stateengine/user_doc/user_doc12.rst @@ -0,0 +1,72 @@ +.. index:: Plugins; Stateengine; Sperren +.. index:: Sperren +.. _Lock-Zustand: + +Sperren +####### + +.. rubric:: Lock - Sperren der automatischen Zustandsermittlung + :name: lock + +Für das Sperren der automatischen Zustandsermittlung führt man ein +Sperr-Item ein, dass beispielsweise über einen Taster änderbar +ist. + +Die Sperre soll aktiv sein, wenn das Sperr-Item den Wert ``True`` +hat. + +.. rubric:: Das Sperr-Item + :name: dassperritem + +Das Sperritem definiert man wie folgt: + +.. code-block:: yaml + + beispiel: + lock: + item: + type: bool + name: Sperr-Item + visu_acl: rw + cache: on + + +.. rubric:: Der Sperrzustand + :name: dersperrzustand + +Der Sperrzustand geht allen anderen Zuständen vor und wird deshalb +als erster Zustand definiert. + +Zudem muss eine Änderung des Sperr-Items direkt eine +Zustandsermittlung auslösen, das Sperr-Item wird daher in die +Liste der ``eval_trigger`` aufgenommen. + +Einstiegsbedingung für den Sperrzustand ist nun einfach, dass das +Sperr-Item den Wert ``True`` hat. Für das Sperr-Item werden in +diesem Beispiel keinerlei Aktionen definiert. Solange also das +Sperr-Item aktiv ist, passiert: nichts. + +.. code-block:: yaml + + beispiel: + lock: + rules: + # Sperr-Item zu eval_trigger: + eval_trigger: + - + - beispiel.lock.item + + # Items für Bedingungen und Aktionen + se_item_lock: beispiel.lock.item + + lock: + type: foo + name: Manuell gesperrt + + enter: + se_value_lock: true + + +Bei der Zustandsermittlung die Reihenfolge der Definition der +Zustände relevant. Da der Sperrzustand allen anderen Zuständen +vorgeht ist er üblicherweise der erste Zustand in der Definition. diff --git a/stateengine/user_doc/user_doc13.rst b/stateengine/user_doc/user_doc13.rst new file mode 100644 index 000000000..cde9d60a6 --- /dev/null +++ b/stateengine/user_doc/user_doc13.rst @@ -0,0 +1,321 @@ +.. index:: Plugins; Stateengine; Aussetzen +.. index:: Aussetzen + +Aussetzen +######### + +.. rubric:: Suspend - Zeitweises Deaktivieren der automatischen Zustandsermittlung nach manuellen Aktionen + :name: suspend + +Eine besondere Anforderung: Nach bestimmten manuellen Aktionen (z. +B. über einen Taster, die Visu, o. ä.) soll die automatische +Zustandsermittlung für eine gewisse Zeit ausgesetzt werden. Nach +Ablauf dieser Zeit soll die Automatik wieder aktiv werden. + +Für dieses Verhalten sind zunächst einige weitere Steueritems +erforderlich, dann kann das Verhalten in einem Zustand abgebildet +werden. + +.. rubric:: Das "Suspend"-Item + :name: dassuspenditem + +Zunächst wird ein "Suspend"-Item benötigt. Dieses Item zeigt zum +einen die zeitweise Deaktivierung an, außerdem kann die +Deaktivierung über dieses Item vorzeitig beendet werden: + +.. code-block:: yaml + + beispiel: + suspend: + suspend: + type: bool + name: Suspend-Item + visu_acl: rw + + +.. rubric:: Das "Manuell"-Item + :name: dasmanuellitem + +Ein weiteres Item wird benötigt, um alle Aktionen, die den +Suspend-Zustand auslösen sollen, zu kapseln. Dieses Item ist das +"Manuell"-Item. Es wird so angelegt, dass der Wert dieses Items +bei jeder manuellen Betätigung invertiert wird: + +.. code-block:: yaml + + beispiel: + suspend: + manuell: + type: bool + name: Manuelle Bedienung + eval_trigger: + - beispiel.item1 + - beispiel.item2 + - .... + se_manual_invert = true + + +In das Attribut ``eval_trigger`` werden alle Items eingetragen, +deren Änderung als manuelle Betätigung gewertet werden soll. +Änderungen an diesen Items, die vom stateengine-Plugin selbst +vorgenommen wurden, werden dabei automatisch ausgefiltert um +Endlosschleifen zu verhindern. + +Das Attribut ``se_manual_invert: true`` veranlasst das +stateengine-Plugin dabei, den Wert des Items bei Änderungen zu +invertieren, wie es für das Auslösen des Suspend-Zustands +erforderlich ist. + +Das Manuell-Item kann noch wesentlich komplexer ausgestaltet +werden. Beispielsweise können Änderungen durch bestimmte +Ereignisse ausgeschlossen werden. + +.. rubric:: Der Suspend-Zustand + :name: dersuspendzustand + +Mit diesen beiden Items kann nun ein einfacher Suspend-Zustand +definiert werden. Als Aktion im Suspend-Zustand wird dabei die +Sonderaktion "suspend" verwendet. Diese hat zwei Parameter: + +.. code-block:: yaml + + se_special_suspend: suspend:, + + +Der Suspend-Zustand sieht damit wie folgt aus: + +.. code-block:: yaml + + suspend: + type: foo + name: Ausgesetzt + + on_enter_or_stay: + type: foo + name: Ausführen immer wenn ein Zustand aktiv ist + + # Suspend-Item setzen + se_special_suspend: suspend:test.suspend.suspend,test.suspend.manuell + + on_leave: + type: foo + name: Ausführen beim Verlassen des Zustands + + # Suspend-Item zurücksetzen + se_set_suspend: False + + enter_manuell: + type: foo + name: Bedingung: Suspend beginnen + + #Bedingung: Manuelle Aktion wurde durchgeführt + se_value_trigger_source: test.suspend.manuell + + enter_stay: + type: foo + name: Bedingung: Im Suspend verbleiben + + #Bedingung: Suspend ist aktiv + se_value_laststate: var:current.state_id + + #Bedingung: Suspendzeit ist noch nicht abgelaufen + se_agemax_manuell: var:item.suspend_time + + #Bedingung: Suspend-Item wurde nicht extern geändert + se_value_suspend: True + + +Bei der Zustandsermittlung die Reihenfolge der Definition der +Zustände relevant. Da der Suspend-Zustand anderen Zuständen +vorgehen sollte steht er üblicherweise sehr weit vorrne in der +Reihenfolge. In der Regel wird der Suspend-Zustand in der +Definition der zweite Zustand, nach dem +:ref:`Lock-Zustand` sein. + +.. rubric:: Komplettes Beispiel + :name: komplettesbeispiel + +Baut man die einzelnen Teile zusammen erhält man die folgende +Konfiguration. + +.. code-block:: yaml + + item: + type: foo + name: stateengine Suspend Beispiel + + suspend: + type: bool + name: Suspend-Item + visu_acl: rw + + manuell: + type: bool + name: Manuelle Bedienung + eval_trigger: + - beispiel.item1 + - beispiel.item2 + se_manual_invert: true + + rules: + type: bool + name: Automatik Test Suspend + se_plugin: active + + # Sowohl das Manuell- als auch das Suspend-Item müssen eine Zustandsermittlung auslösen + eval_trigger: + - test.suspend.manuell + - test.suspend.suspend + + #Items für Bedingungen und Aktionen zuweisen + se_item_suspend: test.suspend.suspend + se_item_manuell: test.suspend.manuell + + suspend: + type: foo + name: Ausgesetzt + + on_enter_or_stay: + se_action_suspend: + - 'function: special' + - 'value: suspend:..suspend, ..manuell' + - 'repeat: True' + - 'order: 1' + se_action_suspend_end: + - 'function: set' + - "to: eval:stateengine_eval.insert_suspend_time('..suspend', suspend_text='%X')" + - 'repeat: True' + - 'order: 2' + se_action_retrigger: + - 'function: set' + - 'to: True' + - 'delay: var:item.suspend_remaining' + - 'repeat: True' + - 'order: 3' + + on_leave: + se_action_suspend: + - 'function: set' + - 'to: False' + se_action_suspend_end: + - 'function: set' + - 'to: ' + + enter_manuell: + se_value_trigger_source: eval:stateengine_eval.get_relative_itemid('..manuell') + se_value_suspend_active: 'True' + + enter_stay: + name: Bedingung Im Suspend verbleiben + #Bedingung: Suspend ist aktiv + se_value_laststate: var:current.state_id + #Bedingung: Suspendzeit ist noch nicht abgelaufen + se_agemax_manuell: var:item.suspend_time + #Bedingung: Suspend-Item wurde nicht extern geändert + se_value_suspend: True + + +.. rubric:: Dauer der zeitweisen Deaktivierung + :name: dauerderzeitweisendeaktivierung + +Die Dauer der zeitweisen Deaktivierung wird in der +Plugin-Konfiguration über die Einstellung ``suspend_time_default`` +angegeben. Vorgabewert sind 3600 Sekunden (1 Stunde). Wenn die +Dauer der zeitweisen Deaktivierung für ein einzelnes Objekt-Item +abweichend sein soll, kann dort das Attribut + +.. code-block:: yaml + + se_suspend_time: + +angegeben werden. Der Parameter verwendet den Datentyp AbValue + +.. rubric:: Erweiterte Funktionen des "Manuell"-Items für den Suspend-Zustand + :name: erweiterte + +.. rubric:: Bestimmte Item-Änderungen nicht als "manuelle Bedienung" auswerten + :name: bestimmteitem + +In bestimmten Fällen ist es erforderlich, das Item-Änderungen, die +durch bestimmte Aufrufe ausgelöst werden, nicht als manuelle +Betätigung gewertet werden. Hierzu zählt zum Beispiel die +Rückmeldung der Raffstore-Position nach dem Verfahren durch den +Jalousieaktor. Hierfür stehen zwei für das Manuell-Item weitere +Attribute bereit: + +| **as_manual_include** +| *Liste der Aufrufe, die als "manuelle Betätigung" gewertet + werden sollen* + +| **as_manual_exclude** +| *Liste der Aufrufe, die nicht als "manuelle Betätigung" gewertet + werden sollen* + +Bei beiden Attributen wird eine Liste von Elementen angegeben. Die +einzelnen Elemente bestehen dabei aus dem Aufrufenden +(``Caller``) einem Doppelpunkt und der Quelle (``Source``). +Mehrere Elemente werden durch "|" getrennt bzw. im yaml als Liste deklariert. +Für ``Caller`` und ``Source`` kann dabei jeweils auch "*" angegeben werden, dies +bedeutet, dass der jeweilige Teil nicht berücksichtigt werd. + +Wenn bei der Prüfung festgestellt wird, dass ein Wert über eine +Eval-Funktionalität geändert wurde, so wird die Änderung +zurückverfolgt bis zur ursprünglichen Änderung, die die Eval-Kette +ausgelöst hat. Diese ursprüngliche Änderung wird dann geprüft. + +Der Wert von ``Caller`` zeigt an, welche Funktionalität das Item +geändert hat. Der Wert von ``Source`` ist Abhängig vom Caller. +Häufig verwendete ``Caller`` sind: + +- ``Init``: Initialisierung von smarthomeNG. ``Source`` ist + in der Regel leer +- ``Visu``: Änderung über die Visualisierung (Visu-Plugin). + ``Source`` beinhaltet die IP und den Port der Gegenstelle +- ``KNX``: Änderung über das KNX-Plugin. ``Source`` ist die + physische Adresse des sendenden Geräts + +Wenn ``se_manual_include`` oder ``se_manual_exclude`` angegeben +sind, muss ``se_manual_invert`` nicht angegeben werden. + +.. code-block:: yaml + + beispiel: + suspend: + manuell: + type: bool + name: Manuelle Bedienung + eval_trigger: + - beispiel.item1 + - beispiel.item2 + se_manual_exclude: + - KNX:1.1.42 + - Init:* + + +Hier werden alle Änderungen der Items ``beispiel.item1`` und +``beispiel.item2`` als manuelle Betätigung gewertet, sofern Sie +nicht durch das KNX-Gerät mit der physischen Adresse 1.1.42 oder +durch die Initialisierung von smarthomeNG erfolgt sind. + +.. rubric:: Erweitertes Logging für das Manuell-Item: + :name: erweitertesloggingfrdasmanuellitem + +Sofern im Manuell-Item die Attribute ``se_manual_include`` bzw. +``se_manual_exclude`` verwendet werden, ist auch hier eine +Protokollierung mittels des erweiterten Loggings möglich. Dazu +muss das Item, unter dem das Log geführt wird über das zusätzliche +Attribut ``se_manual_logitem`` angegeben werden. Hier wird man als +Item in der Regel das Manuell-Item angeben: + +.. code-block:: yaml + + beispiel: + suspend: + manuell: + .... + se_manual_logitem: beispiel.suspend.manuell + + +Wird statt ``se_manual_include`` oder ``se_manual_exclude`` nur +``se_manual_invert`` verwendet, ist kein erweitertes Logging +möglich. diff --git a/stateengine/user_doc/user_doc14.rst b/stateengine/user_doc/user_doc14.rst new file mode 100644 index 000000000..32e67addf --- /dev/null +++ b/stateengine/user_doc/user_doc14.rst @@ -0,0 +1,19 @@ +.. index:: Plugins; Stateengine; CLI +.. index:: CLI + +CLI +### + +.. rubric:: Zusätzliche Kommandos für das CLI Plugin + :name: cli + +Sofern die eingesetzte smarthomeNG-Version dies unterstützt, +registriert das stateengine-Plugin zwei eigene Kommandos beim +CLI-Plugin. + +| **se_list** +| *Zeigt eine Liste der Objekt-Items, für die das + stateengine-Plugin aktiv ist* + +| **se_detail ** +| *Zeigt Details zum Objekt Item* diff --git a/stateengine/user_doc/user_doc15.rst b/stateengine/user_doc/user_doc15.rst new file mode 100644 index 000000000..76c63833b --- /dev/null +++ b/stateengine/user_doc/user_doc15.rst @@ -0,0 +1,675 @@ +.. index:: Plugins; Stateengine; Beispiel +.. index:: Beispiel + +Beispiel +######## + +.. rubric:: Vollständiges Beispiel + :name: vollstndigesbeispiel + +In diesem Beispiel soll die Automatisierung eines Raffstores +gezeigt werden. Folgende Zustände sollen abgedeckt werden: + +- Sperre über Sperr-Item +- Zeitweises Deaktivieren ("Suspend") bei manuellen Aktionen +- Nachführen der Lamellen zum Sonnenstand bei großer Helligkeit +- Nacht +- Morgens +- Abends +- Tag + +Dabei sollen möglichst viele Features des stateengine Plugins +verwendet werden + +.. rubric:: Items zum Prüfen + :name: itemszumprfen + +Zuerst benötigen wir ein paar Items, die nachher als Bedingungen +abgeprüft werden sollen: + +.. code-block:: yaml + + beispiel: + steckdosen: + type: bool + + licht: + type: bool + + wetterstation: + helligkeit: + name: Helligkeit + type: num + + gt43k: + type: bool + name: Flag Helligkeit größer als 43 kLux + eval: sh.beispiel.wetterstation.helligkeit() > 43000 + eval_trigger beispiel.wetterstation.helligkeit + + gt35k: + type: bool + name: Flag Helligkeit größer als 35 kLux + eval: sh.beispiel.wetterstation.helligkeit() > 35000 + eval_trigger beispiel.wetterstation.helligkeit + + gt25k: + type: bool + name: Flag Helligkeit größer als 25 kLux + eval: sh.beispiel.wetterstation.helligkeit() > 25000 + eval_trigger beispiel.wetterstation.helligkeit + + gt20k: + type: bool + name: Flag Helligkeit größer als 20 kLux + eval: sh.beispiel.wetterstation.helligkeit() > 20000 + eval_trigger beispiel.wetterstation.helligkeit + + temperatur: + name: Temperatur + type: num + + +.. rubric:: Trigger + :name: trigger + +Da wir mehrere Raffstores automatisieren wollen und alle +Raffstores gleichzeitig fahren sollen, brauchen wir einen externen +Trigger, auf den dann alle Automatiken hören: + +.. code-block:: yaml + + beispiel: + trigger: + raffstore: + type: bool + name: Gemeinsamer Trigger für alle Raffstores + enforce_updates: yes + cycle: 300 = 1 + + +In diesem Fall wird die Zustandsermittlung alle 300 Sekunden (5 +Minuten) ausgelöst. + +.. rubric:: Default-Konfiguration + :name: defaultkonfiguration + +Nun kommt die Default-Konfiguration. Sie ist unabhängig von +konkreten zu automatisierenden Objekten. Sie beinhaltet jedoch +umfangreiche Einstellungen, so dass die zu automatisierenden +Objekte, die die Einstellungen aus der Default-Konfiguration +verwenden, oft sehr simpel aufgebaut werden können. + +.. code-block:: yaml + + beispiel: + default: + raffstore: + # Item für Helligkeit außen + se_item_brightness: beispiel.wetterstation.helligkeit + # Item für Temperatur außen + se_item_temperature: beispiel.wetterstation.temperatur + # Item das anzeigt, ob die Helligkeit außen mehr als 25kLux beträgt + se_item_brightnessGt25k: beispiel.wetterstation.helligkeit.gt25k + # Item das anzeigt, ob die Helligkeit außen mehr als 43kLux beträgt + se_item_brightnessGt43k: beispiel.wetterstation.helligkeit.gt43k + # Item für Behanghöhe + se_item_hoehe: ...hoehe + # Keine Änderung der Behanghöhe wenn Abweichung kleiner 10 + se_mindelta_hoehe: 10 + # Item für Lamellenwinkel + se_item_lamelle: ...lamelle + # Keine Änderung des Lamellenwinkels wenn Abweichung kleiner 5 + se_mindelta_lamelle: 5 + # "Manuell" Item + se_item_manuell: ..manuell + # "Lock" Item + se_item_lock: ..lock + # "Suspend" Item + se_item_suspend: ..suspend + + # Zustand "Sperre über Sperr-Item" + Lock: + type: foo + name: Automatik manuell gesperrt + # Aktionen: + # - "Suspend"-Item ggf. zurücksetzen + se_set_suspend: False + # sonst nichts tun + enter + # Einstieg in "Lock": Wenn + # - das "Lock"-Item gesetzt ist + se_value_lock: True + + # Zustand "Zeitweises Deaktivieren bei manuellen Aktionen" + Suspend: + type: foo + name: Ausgesetzt + + on_enter_or_stay: + se_action_suspend: + - 'function: special' + - 'value: suspend:..suspend, ..manuell' + - 'repeat: True' + - 'order: 1' + se_action_suspend_end: + - 'function: set' + - "to: eval:stateengine_eval.insert_suspend_time('..suspend', suspend_text='%X')" + - 'repeat: True' + - 'order: 2' + se_action_retrigger: + - 'function: set' + - 'to: True' + - 'delay: var:item.suspend_remaining' + - 'repeat: True' + - 'order: 3' + + on_leave: + se_action_suspend: + - 'function: set' + - 'to: False' + se_action_suspend_end: + - 'function: set' + - 'to: ' + + enter_manuell: + se_value_trigger_source: eval:stateengine_eval.get_relative_itemid('..manuell') + se_value_suspend_active: 'True' + + enter_stay: + name: Bedingung Im Suspend verbleiben + #Bedingung: Suspend ist aktiv + se_value_laststate: var:current.state_id + #Bedingung: Suspendzeit ist noch nicht abgelaufen + se_agemax_manuell: var:item.suspend_time + #Bedingung: Suspend-Item wurde nicht extern geändert + se_value_suspend: True + + # Zustand "Nachführen der Lamellen zum Sonnenstand bei großer Helligkeit", Gebäudeseite 1 + Nachfuehren_Seite_Eins: + type: foo + name: Tag (nachführen) + # Aktionen: + # - Behang ganz herunterfahren + se_set_hoehe: value:100 + # - Lamellen zur Sonne ausrichten + se_set_lamelle: eval:stateengine_eval.sun_tracking() + # - "Suspend"-Item ggf. zurücksetzen + se_set_suspend: False + + # Einstieg in "Nachführen": Wenn + enter: + # - das Flag "Helligkeit > 43kLux" seit mindestens 60 Sekunden gesetzt ist + se_value_brightnessGt43k: true + se_agemin_brightnessGt43k: 60 + # - die Sonnenhöhe mindestens 18° ist + se_min_sun_altitude: 18 + # - die Sonne aus Richtung 130° bis 270° kommt + se_min_sun_azimut: 130 + se_max_sun_azimut: 270 + # - es draußen mindestens 22° hat + se_min_temperature: 22 + + # Hysterese für Helligkeit: Wenn + enter_hysterese: + # ... wir bereits in "Nachführen" sind + se_value_laststate: var:current.state_id + # .... das Flag "Helligkeit > 25kLux" gesetzt ist + se_value_brightnessGt25k: true + # ... die Sonnenhöhe mindestens 18° ist + se_min_sun_altitude: 18 + # ... die Sonne aus Richtung 130° bis 270° kommt + se_min_sun_azimut: 130 + se_max_sun_azimut: 270 + # Anmerkung: Hier keine erneute Prüfung der Temperatur, damit Temperaturschwankungen nicht + # zum Auf-/Abfahren der Raffstores führen + + # Verzögerter Ausstieg nach Unterschreitung der Mindesthelligkeit: Wenn + enter_delay: + # ... wir bereits in "Nachführen" sind + se_value_laststate: var:current.state_id + # .... das Flag "Helligkeit > 25kLux" nicht (!) gesetzt ist, aber diese Änderung nicht mehr als 20 Minuten her ist + se_value_brightnessGt25k: false + se_agemax_brightnessGt25k: 1200 + # ... die Sonnenhöhe mindestens 18° ist + se_min_sun_altitude: 18 + # ... die Sonne aus Richtung 130° bis 270° kommt + se_min_sun_azimut: 130 + se_max_sun_azimut: 270 + # Anmerkung: Auch hier keine erneute Prüfung der Temperatur, damit Temperaturschwankungen nicht + # zum Auf-/Abfahren der Raffstores führen + + # Zustand "Nachführen der Lamellen zum Sonnenstand bei großer Helligkeit", Gebäudeseite 2 + Nachfuehren_Seite_Zwei: + type: foo + # Einstellungen des Vorgabezustands "Nachfuehren_Seite_Eins" übernehmen + se_use: beispiel.default.raffstore.Nachfuehren_Seite_Eins + + # Sonnenwinkel in den Bedingungsgruppen anpassen + enter: + # ... die Sonne aus Richtung 220° bis 340° kommt + se_min_sun_azimut: 220 + se_max_sun_azimut: 340 + + enter_hysterese: + # ... die Sonne aus Richtung 220° bis 340° kommt + se_min_sun_azimut: 220 + se_max_sun_azimut: 340 + + :enter_delay: + # ... die Sonne aus Richtung 220° bis 340° kommt + se_min_sun_azimut: 220 + se_max_sun_azimut: 340 + + # Zustand "Nacht" + Nacht: + type: foo + name: Nacht + # Aktionen: + # - Behang ganz herunterfahren + se_set_hoehe: value:100 + # - Lamellen ganz schließen + se_set_lamelle: value:0 + # - "Suspend"-Item ggf. zurücksetzen + se_set_suspend: False + + # Einstieg in "Nacht": Wenn + enter: + # - es zwischen 16:00 und 08:00 Uhr ist + se_min_time: '08:00' + se_max_time: '16:00' + se_negate_time: True + # - die Helligkeit höchstens 90 Lux beträgt + se_max_brightness: 90 + + # Zustand "Morgens" + Morgens: + type: foo + name: Dämmerung Morgens + # Aktionen: + # - Behang ganz herunterfahren + se_set_hoehe: value:100 + # - Lamellen ca 45° nach unten + se_set_lamelle: value:25 + # - "Suspend"-Item ggf. zurücksetzen + se_set_suspend: False + + # Einstieg in "Morgens": Wenn + enter: + # - die Helligkeit zwischen 90 und 250 Lux beträgt + se_min_brightness: 90 + se_max_brightness: 250 + # - es zwischen 00:00 und 12:00 Uhr ist + se_min_time: '00:00' + se_max_time: '12:00' + + # Zustand "Abends" + Abends: + type: foo + name: Dämmerung Abends + # Aktionen: + # - Behang ganz herunterfahren + se_set_hoehe: value:100 + # - Lamellen ca 45° nach oben + se_set_lamelle: value:75 + # - "Suspend"-Item ggf. zurücksetzen + se_set_suspend: False + + # Einstieg in "Abends": Wenn + enter: + # - die Helligkeit zwischen 90 und 250 Lux beträgt + se_min_brightness: 90 + se_max_brightness: 250 + # - es zwischen 12:00 und 24:00 Uhr ist + se_min_time: '12:00' + se_max_time: '24:00' + # Anmerkung: "24:00" ist eigentlich eine ungültige Zeit. Sie wird aber automatisch zu 23:59:59 umgewandelt + + # Zustand "Tag" + Tag: + type: foo + name: Tag (statisch) + # Aktionen: + # - Behang ganz hochfahren + se_set_hoehe: value:0 + # - Lamellen auf den Standardwert bei ganz hochgefahrenem Behang + se_set_lamelle: value:100 + # - "Suspend"-Item ggf. zurücksetzen + se_set_suspend: False + + # Einstieg in "Tag": Wenn + enter: + # - es zwischen 06:30 und 21:30 Uhr ist + se_min_time: '06:30' + se_max_time: '21:30' + + +.. rubric:: Automatisierung Raffstore 1 + :name: automatisierungraffstore1 + +Jetzt wollen wir den ersten Raffstore automatisieren. Einige Items +dazu haben wir sowieso schon, da der Raffstore über diese Items +gesteuert wird. + +.. code-block:: yaml + + beispiel: + raffstore1: + name: Raffstore Beispiel 1 + + aufab: + type: bool + name: Raffstore auf/ab fahren + enforce_updates: on + + step: + type: bool + name: Raffstore Schritt fahren/stoppen + enforce_updates: on + + hoehe: + type: num + name: Behanghöhe des Raffstores + + lamelle: + type: num + name: Lamellenwinkel des Raffstores + + +Jetzt kommen noch die Items zur Automatisierung und schließlich +das stateengine Objekt-Item hinzu: + +.. code-block:: yaml + + beispiel: + raffstore1: + automatik: + lock: + type: bool + name: Sperr-Item + visu_acl: rw + cache: on + + suspend: + type: bool + name: Suspend-Item + visu_acl: rw + # Achtung: Beim "Suspend"-Item niemals "enforce_updates = yes" setzen! Das führt dazu dass das Setzen des + # Suspend-Items bei der Initialisierung zu einem endlosen sofortigen Wiederaufruf der Statusermittlung führt! + + state_id: + type: str + name: Id des aktuellen Zustands + visu_acl: r + cache: on + + state_name: + type: str + name: Name des aktuellen Zustands + visu_acl: r + cache: on + + manuell: + type: bool + name: Manuelle Bedienung + # Änderungen dieser Items sollen als manuelle Bedienung gewertet werden + eval_trigger: + - beispiel.raffstore1.aufab + - beispiel.raffstore1.step + - beispiel.raffstore1.hoehe + - beispiel.raffstore1.lamelle + # Änderungen, die ursprünglich von diesen Triggern (:) ausgelöst wurden, sollen nicht als manuelle Bedienung gewertet werden + se_manual_exclude: + - KNX:y.y.y + - Init:* + + rules: + type: bool + name: Automatik Raffstore 1 + se_plugin: active + # Erste Zustandsermittlung nach 30 Sekunden + se_startup_delay: 30 + # Über diese Items soll die Statusermittlung ausgelöst werden + eval_trigger: beispiel.trigger.raffstore | beispiel.raffstore1.automatik.anwesenheit | beispiel.raffstore1.automatik.manuell | beispiel.raffstore1.automatik.lock | beispiel.raffstore1.automatik.suspend + # In dieses Item soll die Id des aktuellen Zustands geschrieben werden + se_laststate_item_id: ..state_id + # In dieses Item soll der Name des aktuellen Zustands geschrieben werden + se_laststate_item_name: ..state_name + + Lock: + # Zustand "Lock": Nur die Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Lock + + Suspend: + # Zustand "Suspend": Nur die Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Suspend + + Nachfuehren: + # Zustand "Nachfuehren": Nur die Vorgabeeinstellungen übernehmen (Gebäudeseite 2) + se_use: beispiel.default.raffstore.Nachfuehren_Seite_Zwei + + Nacht: + # Zustand "Nacht": Nur die Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Nacht + + Morgens: + # Zustand "Morgens": Nur die Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Morgens + + Abends: + # Zustand "Abends": Nur die Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Abends + + Tag: + # Zustand "Tag": Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Tag + + +.. rubric:: Automatisierung Raffstore 2 + :name: automatisierungraffstore2 + +Der zweite Raffstore ist ein komplexeres Beispiel. Hier werden +nicht nur die Vorgabewerte übernommen, hier werden komplett neue +Bedingungsgruppen definiert, sowie vorhandene Bedingungsgruppen +abgeändert. + +.. code-block:: yaml + + beispiel: + raffstore2: + name: Raffstore Beispiel 2 + + aufab: + type: bool + name: Raffstore auf/ab fahren + enforce_updates: on + + step: + type: bool + name: Raffstore Schritt fahren/stoppen + enforce_updates: on + + hoehe: + type: num + name: Behanghöhe des Raffstores + + lamelle: + type: num + name: Lamellenwinkel des Raffstores + + automatik: + lock: + type: bool + name: Sperr-Item + visu_acl: rw + cache: on + + suspend: + type: bool + name: Suspend-Item + visu_acl: rw + # Achtung: Beim "Suspend"-Item niemals "enforce_updates = yes" setzen! Das führt dazu dass das Setzen des + # Suspend-Items bei der Initialisierung zu einem endlosen sofortigen Wiederaufruf der Statusermittlung führt! + + state_id: + type: str + name: Id des aktuellen Zustands + visu_acl: r + cache: on + + state_name: + type: str + name: Name des aktuellen Zustands + visu_acl: r + cache: on + + manuell: + type: bool + name: Manuelle Bedienung + # Änderungen dieser Items sollen als manuelle Bedienung gewertet werden + eval_trigger: + - beispiel.raffstore2.aufab + - beispiel.raffstore2.step + - beispiel.raffstore2.hoehe + - beispiel.raffstore2.lamelle + # Änderungen, die ursprünglich von diesen Triggern (:) ausgelöst wurden, sollen nicht als manuelle Bedienung gewertet werden + se_manual_exclude: + - KNX:y.y.y + - Init:* + + anwesenheit: + type: bool + name: Anwesenheit im Raum + eval: or + eval_trigger: + - beispiel.steckdosen + - beispiel.licht + + rules: + type: bool + name: Automatik Raffstore 2 + se_plugin: active + # Erste Zustandsermittlung nach 30 Sekunden + se_startup_delay: 30 + # Über diese Items soll die Statusermittlung ausgelöst werden + eval_trigger: beispiel.trigger.raffstore | beispiel.raffstore2.automatik.anwesenheit | beispiel.raffstore2.automatik.manuell | beispiel.raffstore2.automatik.lock | beispiel.raffstore2.automatik.suspend + # In dieses Item soll die Id des aktuellen Zustands geschrieben werden + se_laststate_item_id: ..state_id + # In dieses Item soll der Name des aktuellen Zustands geschrieben werden + se_laststate_item_name: ..state_name + # Dieses Item zeigt die Anwesenheit im Raum + se_item_anwesend: ..anwesenheit + # Item das anzeigt, ob die Helligkeit außen mehr als 35kLux beträgt + se_item_brightnessGt35k: beispiel.wetterstation.helligkeit.gt35k + # Item das anzeigt, ob die Helligkeit außen mehr als 20Lux beträgt + se_item_brightnessGt20k: beispiel.wetterstation.helligkeit.gt20k + + Lock: + # Zustand "Lock": Nur die Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Lock + + Suspend: + # Zustand "Suspend": Nur die Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Suspend + + Nachfuehren: + # Zustand "Nachführen": Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Nachfuehren_Seite_Eins + + # ..und jetzt verändern wir das ganze, in dem wir abhängig vom "Anwesend"-Flag andere + # Grenzwerte für die Helligkeit setzen. + + # Erst definieren wir mal zusätzliche Einstiegsbedingungen, die die neuen Grenzwerte beinhalten: + :enter_anwesend: + # Einstieg in "Nachführen" bei Anwesenheit: Wenn + # - das Flag "Anwesenheit" gesetzt ist + se_value_anwesend: true + # - das Flag "Helligkeit > 35kLux" seit mindestens 60 Sekunden gesetzt ist (also 8k Lux früher als in "enter") + se_value_brightnessGt35k: true + se_agemin_brightnessGt35k: 60 + # - die Sonnenhöhe mindestens 15° ist (also 3° früher als in "enter") + se_min_sun_altitude: 15 + # - die Sonne aus Richtung 110° bis 270° kommt (also 20° früher als in "enter" + se_min_sun_azimut: 110 + se_max_sun_azimut: 270 + + enter_anwesend_hysterese: + # Hysterese für Helligkeit bei Anwesenheit: Wenn + # - das Flag "Anwesenheit" gesetzt ist + se_value_anwesend: true + # ... wir bereits in "Nachführen" sind + se_value_laststate: var:current.state_id + # .... das Flag "Helligkeit > 20kLux" gesetzt ist (also 5 kLux früher als in "enter_hysterese") + se_value_brightnessGt20k: true + # ... die Sonnenhöhe mindestens 15° ist (Übernahme aus "enter_anwesend") + se_min_sun_altitude: 15 + # ... die Sonne aus Richtung 110° bis 270° kommt (Übernahme aus "enter_anwesend") + se_min_sun_azimut: 110 + se_max_sun_azimut: 270 + + enter_anwesend_delay: + # Verzögerter Ausstieg nach Unterschreitung der Mindesthelligkeit bei Anwesenheit: Wenn + # - das Flag "Anwesenheit" gesetzt ist + se_value_anwesend: true + # ... wir bereits in "Nachführen" sind + se_value_laststate: var:current.state_id + # .... das Flag "Helligkeit > 20kLux" nicht (!) gesetzt ist, aber diese Änderung nicht mehr als 20 Minuten her ist + se_value_brightnessGt20k: false + se_agemax_brightnessGt20k: 1200 + # ... die Sonnenhöhe mindestens 15° ist (Übernahme aus "enter_anwesend") + se_min_sun_altitude: 15 + # ... die Sonne aus Richtung 110° bis 270° kommt (Übernahme aus "enter_anwesend") + se_min_sun_azimut: 110 + se_max_sun_azimut: 270 + + # Jetzt müssen wir die vorhandenen Bedingungen noch erweitern (sie gelten ja nur noch, wenn "Anwesenheit" nicht gesetzt ist) + enter: + # Einstieg in "Nachführen": Wenn zusätzlich + # - das Flag "Anwesenheit" nicht gesetzt ist + se_value_anwesend: false + + enter_hysterese: + # Hysterese für Helligkeit: Wenn zusätzlich + # - das Flag "Anwesenheit" nicht gesetzt ist + se_value_anwesend: false + + enter_delay: + # Verzögerter Ausstieg nach Unterschreitung der Mindesthelligkeit: Wenn zusätzlich + # - das Flag "Anwesenheit" nicht gesetzt ist + se_value_anwesend: false + + Nacht: + # Zustand "Nacht": Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Nacht + # .. und zwei weitere Einstiegsbedingungen definieren + + enter_schlafenszeit_woche: + # Einstieg in "Nacht": Wenn + # - es zwischen 21:00 und 07:00 Uhr ist + se_min_time: '07:00' + se_max_time: '21:00' + se_negate_time: True + # - der Wochentag zwischen Montag und Freitag liegt + se_min_weekday: 0 + se_max_weekday: 4 + + enter_schlafenszeit_wochenende: + # Einstieg in "Nacht": Wenn + # - es zwischen 21:00 und 08:30 Uhr ist + se_min_time: '08:30' + se_max_time: '21:00' + se_negate_time: True + # - der Wochentag Samstag oder Sonntag ist + se_value_weekday: 5 | 6 + + Morgens: + # Zustand "Morgens": Nur die Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Morgens + + Abends: + # Zustand "Abends": Nur die Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Abends + + Tag: + # Zustand "Tag": Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Tag diff --git a/stateengine/user_doc/user_doc2.rst b/stateengine/user_doc/user_doc2.rst new file mode 100644 index 000000000..41ef47ecc --- /dev/null +++ b/stateengine/user_doc/user_doc2.rst @@ -0,0 +1,115 @@ +.. index:: Plugins; Stateengine; Pluginkonfiguration +.. index:: Pluginkonfiguration + +Pluginkonfiguration +################### + +.. rubric:: Konfiguration des Plugins + :name: konfigurationdesplugins + +Um das StateEngine Plugin zu verwenden müssen die folgenden Zeilen +in die plugin.yaml Datei der smarthomeNG Installation eingetragen +werden. + +.. code-block:: yaml + + stateengine: + class_name: StateEngine + class_path: plugins.stateengine + #startup_delay_default: 10 + #suspend_time_default: 3600 + #log_level: 0 + #log_directory: var/log/StateEngine/ + #log_maxage: 0 + + +Auskommentierte Attribute sind Vorgabewerte, die nach den eigenen +Bedürfnissen angepasst werden können. + +| **startup_delay_default (optional):** +| *Vorgabewert für die Startverzögerung der ersten + Zustandsermittlung beim Start von smarthomeNG* + +Beim Starten von smarthomeNG dauert es üblicherweise einige +Sekunden, bis alle Items initialisiert sind. Um zu verhindern, +dass die erste Zustandsermittlung stattfindet, bevor alle Items +ihren Initialwert haben, wird die erste Zustandsermittlung +verzögert. Die Dauer der Verzögerung kann bei den Objekt-Items +angegeben werden. Wenn bei einem Objekt-Item kein Wert angegeben +ist, wird der hier angegebene Standardwert verwendet. Wenn kein +abweichender Standardwert in der Plugin-Konfiguration angegeben +ist, ist der Vorgabewert 10 Sekunden. + +Folgende Werte sind möglich: + +| *Zahl größer 0:* +| Angabe der Startverzögerung in Sekunden. Während der + Startverzögerung sind die Auslöser der Zustandsermittlung + inaktiv. Sie werden erst nach Ablauf der Startverzögerung und + der ersten Zustandsermittlung aktiviert. + +| *0:* +| Keine Startverzögerung. Die erste Zustandsermittlung wird direkt + nach der Initialisierung des Objekt-Items durchgeführt. + Anschließend werden die Auslöser für die Zustandsermittung + aktiviert. + +| *-1:* +| Es wird keine erste Zustandsermittlung durchgeführt. Nach der + Initialisierung des Objekt-Items sind alle Auslöser für die + Zustandsermittlung aktiv. + +| **suspend_time_default (optional):** +| *Vorgabezeit zur Unterbrechung der automatischen Steuerung nach + manuellen Aktionen* + +Nach manuellen Aktionen kann die Automatik für eine bestimmte Zeit +Unterbrochen werden. Die Dauer dieser Unterbrechungen kann bei den +Objekt-Items angegeben werden. Die Einheit für den Wert sind +Sekunden. Wenn bei einem Objekt-Item kein Wert angegeben ist, wird +der hier angegebene Standardwert verwendet. Wenn kein abweichender +Standardwert in der Plugin-Konfiguration angegeben ist, ist der +Vorgabewert 3600 Sekunden (1 Stunde) + +| **log_level(optional):** +| *Erweiterte Protokollierung: Loglevel (0: aus, 1: Info, 2: + Debug* + +Die erweiterte Protokollierung wird über das Setzen des Loglevels +auf 1 (Info) oder 2 (Debug) aktiviert. Wenn der Parameter nicht +angegeben ist, ist die erweiterte Protokollierung deaktiviert. + +| **log_directory (optional):** +| *Erweiterte Protokollierung: Verzeichnis für die + Protokolldateien* + +| Die Logdateien der erweiterten Protokollierung werden in das + hier angegebene Verzeichnis geschrieben. +| Wenn der angegebene Verzeichnisname mit "/" beginnt wird er als + absoluter Verzeichnisname behandelt. Alle anderen + Verzeichnisnamen werden als Unterverzeichnisse des smarthomeNG + Basisverzeichnisses behandelt. Das angegebene Verzeichnis wird + angelegt, wenn es nicht existiert. +| Wenn hier kein abweichendes Verzeichnis angegeben ist, wird das + Verzeichnis ``/var/log/AutoState/`` + verwendet. + +| **log_maxage (optional):** +| *Erweiterte Protokollierung: Anzahl der Tage, nach der die + Dateien im Verzeichnis ``log_directory`` wieder gelöscht + werden sollen* + +| Alte Protokolldateien können nach einer bestimmten Zeit + automatisch gelöscht werden. Diesen Parameter wird die Anzahl + der Tage festgelegt, nachdem die Dateien gelöscht werden sollen. + Das Löschen ist ausgesetzt solange der Parameter den Wert 0 hat. + Wenn der Parameter auf einen anderen Wert gesetzt wird, wird das + Alter der Dateien im Protokollverzeichnis ``log_directory`` + täglich geprüft und überalterte Dateien werden gelöscht. + +.. important:: + + Die Löschfunktionalität prüft und löscht alle + Dateien im Protokollverzeichnis, ob sie Protokolldateien sind + oder nicht. Daher sollten keine anderen Dateien in diesem + Verzeichnis abgelegt werden! diff --git a/stateengine/user_doc/user_doc3.rst b/stateengine/user_doc/user_doc3.rst new file mode 100644 index 000000000..8560830b2 --- /dev/null +++ b/stateengine/user_doc/user_doc3.rst @@ -0,0 +1,204 @@ +.. index:: Plugins; Stateengine; Objekt-Item +.. index:: Objekt-Item + +Objekt-Item +########### + +.. rubric:: Die Grundkonfiguration für eine Automatik: Das Objekt-Item + :name: diegrundkonfiguration + +Für jedes Objekt, dass mit dem StateEngine Plugin gesteuert werden +soll, ist ein Item erforderlich, dass alle Konfigurationsdaten für +dieses Objekt enthält. Dieses Item wird aus "Objekt-Item" +bezeichnet. Es können beliebig viele Objekt-Items und damit +beliebig viele Automatiken angelegt werden. + +.. rubric:: Grundlegende Einstellungen + :name: grundlegendeeinstellungen + +Über die folgenden Attribute werden die grundlegenden +Einstellungen für eine Automatik festgelegt + +.. code-block:: yaml + + beispiel: + raffstore1: + automatik: + rules: + type: bool + name: Automatik Raffstore 1 + se_plugin: active + se_startup_delay: 30 + se_laststate_item_id: beispiel.raffstore1.automatik.state_id + se_laststate_item_name: beispiel.raffstore1.automatik.state_name + se_repeat_actions: true + se_suspend_time: 7200 + + +| **type (obligatorisch):** +| *Datentp des Items* + +Für das Objekt-Item muss immer der Datentyp "bool" verwendet +werden + +| **name (optional):** +| *Name des Items* + +Wenn das Attribut nicht angegeben ist, wird die Id des Items als +Name verwendet. + +| **se_plugin (obligatorisch):** +| *Kennzeichnet das Item als Objekt-Item des StateEngine-Plugins* + +Der Wert dieses Attributs muss zwingend ``active`` sein, damit +das Plugin das Item berücksichtigt. Zu Debuggingzwecken kann der +Wert dieses Attributs auf einen anderen Wert geändert werden, +dadurch wird das Plugin das Objekt ignorieren. + +| **se_startupdelay (optional):** +| *Startverzögerung der ersten Zustandsermittlung beim Start von + smarthomeNG* + +| Beim Starten von smarthomeNG dauert es üblicherweise einige + Sekunden, bis alle Items initialisiert sind. Um zu verhindern, + dass die erste Zustandsermittlung stattfindet, bevor alle Items + ihren Initialwert haben, wird die erste Zustandsermittlung + verzögert. Erst nach der ersten Zustandsermittlung werden alle + Auslöser und Funktionen vollständig aktiviert. + Zustandsermittlungen, die durch Items oder Timer vor Ablauf der + Startverzögerung ausgelöst werden, werden nicht durchgeführt. + Die zulässigen Werte für ``se_startup_delay`` sind identisch + mit den zulässigen Werten für den Plugin-Parameter + ``startup_delay_default``. +| Der Parameter verwendet den Datentyp AbValue + +| **se_laststate_item_id (optional):** +| *Id des Items, in dem die Id des aktuellen Zustands abgelegt wird* + +In das hier angegebene Item wird die Id des aktuellen Zustands +abgelegt. Das Item kann mit dem Attribut ``cache: yes`` +versehen werden, dann bleibt der vorherige Zustand bei einem +Neustart von smarthomeNG erhalten. Wenn das Item +``se_laststate_item_id`` nicht angegeben ist, wird der aktuelle +Zustand nur im Plugin gespeichert und geht mit einem Neustart von +smarthomeNG verloren. + +Sofern verwendet, sollte das Item für ``se_laststate_item_id`` +wie folgt definiert werden + +.. code-block:: yaml + + beispiel: + raffstore1: + automatik: + state_id: + type: str + name: Id des aktuellen Zustands + visu_acl: r + cache: yes + + +| **se_laststate_item_name (optional):** +| *Id des Items, in dem der Name des aktuellen Zustands abgelegt wird* + +In das hier angegebene Item wird der Name des aktuellen Zustands +abgelegt. Das Item kann für Displayzwecke verwendet werden. Wenn +das Item ``se_laststate_item_name`` nicht angegeben ist, steht +der Name des aktuellen Zustands nicht zur Verfügung + +Sofern verwendet, sollte das Item für ``se_laststate_item_name`` +wie folgt definiert werden + +.. code-block:: yaml + + beispiel: + raffstore1: + automatik: + state_name: + type: str + name: Name des aktuellen Zustands + visu_acl: r + cache: yes + + +| **se_repeat_actions (optional):** +| *Wiederholen der Aktionen bei unverändertem Zustand* + +Im Normalfall werden Aktionen jedesmal ausgeführt wenn der +aktuelle Zustand neu ermittelt wurde. Dies ist unabhängig davon, +ob sich der Zustand bei der Neuermittlung geändert hat oder nicht. +Dieses Verhalten kann über die Angabe von +``se_repeat_actions: false`` umgestellt werden. Wenn das +Attribut auf ``false`` gesetzt ist, werden Aktionen nur +ausgeführt, wenn sich der Zustand tatsächlich geändert hat. Der +Parameter verwendet den Datentyp AbValue + +| **se_suspendtime (optional):** +| *Zeit zur Unterbrechung der automatischen Steuerung nach + manuellen Aktionen* + +Nach manuellen Aktionen kann die Automatik für eine bestimmte Zeit +Unterbrochen werden. Die Dauer dieser Unterbrechungen wird hier +angegeben. Die Einheit für den Wert sind Sekunden. Wenn bei einem +Objekt-Item kein Wert angegeben ist, wird der in der +Pluginkonfiguration angegebene Standardwert +(se_suspend_time) verwendet. Der Parameter verwendet den +Datentyp AbValue + +.. rubric:: Einstellungen zum Auslösen der Zustandsermittlung + :name: einstellungenzumauslsenderzustandsermittlung + +Eine Neuermittlung des aktuellen Zustands wird jedesmal +durchgeführt, wenn ein Wert für das Objekt-Item geschrieben wird. +Somit können die Standardmöglichkeiten von smarthomeNG wie +``cycle``, ``crontab`` und ``eval_trigger`` verwendet +werden, um die Neuermittlung des aktuellen Zustands auszulösen. + +.. code-block:: yaml + + beispiel: + rafffstore2: + automatik: + rules: + <...> + cycle: 300 + crontab: + - 0 5 * * + - 0 6 * * + eval_trigger: + - beispiel.trigger.raffstore + - beispiel.raffstore2.automatik.anwesenheit + + +Details zu diesen Attributen können der `smarthomeNG +Dokumentation `_ +entnommen werden. + +Um die Konfiguration einfach zu halten, verändert das Plugin +einige Einstellungen des Objekt-Items. Folgende Erleichterungen +werden dabei vorgenommen: + +- Es ist nicht erforderlich mit ``cycle`` bzw. ``crontab`` + Werte anzugeben. Das StateEngine Plugin ergänzt diese + automatisch, sofern erforderlich. Statt ``cycle: 300 = 1`` ist + es ausreichend, wenn man ``cycle: 300`` angibt. + +- Es ist nicht erforderlich das Attribut ``eval = (irgendwas)`` + anzugeben, wenn ``eval_trigger`` verwendet wird. Das + StateEngine plugin ergänzt dies automatisch, sofern + erforderlich. + +- ``crontab: init`` funktioniert nicht für das StateEngine + Plugin. Die Neuberechnung des ersten Zustands nach dem Start + von smarthomeNG wird über das Attribut ``se_startup_delay`` + gesteuert. + +Es ist auch möglich andere Wege zu verwenden, um den Wert des +Objekt-Items zu setzen: + +- Zuweisung einer hörenden KNX Gruppenadresse zum Objekt-Item und + Senden eines Wertes auf diese Gruppenadresse. + +- Setzen des Werts des Objekt-Items aus einer Logik, einer + anderen Automatik oder sogar aus der selben Automatik (ggf. mit + Verzögerung). diff --git a/stateengine/user_doc/user_doc4.rst b/stateengine/user_doc/user_doc4.rst new file mode 100644 index 000000000..053436cc6 --- /dev/null +++ b/stateengine/user_doc/user_doc4.rst @@ -0,0 +1,165 @@ +.. index:: Plugins; Stateengine; Zustand-Item +.. index:: Zustand-Item + +Zustand-Item +############ + +.. rubric:: Zustände: Das Zustands-Item + :name: daszustandsitem + +Alle Items unterhalb des Objekt-Items beschreiben Zustände des +Objekts ("Zustands-Item"). Die Ids der Zustands-Items sind +beliebig. Sie werden als Werte für das über +``se_laststate_item_id`` angegebene Item verwendet um den +aktuellen Zustand abzulegen. + +.. code-block:: yaml + + beispiel: + raffstore1: + automatik: + rules: + Tag: + type: foo + name: Tag + se_name: eval: sh.eine_funktion() + + +| **type (obligatorisch):** +| *Datentp des Items* + +Für das Zustands-Item muss immer der Datentyp "foo" verwendet +werden + +| **name (optional):** +| *Name des Zustands* + +Der Name des Zustands wird im Protokoll sowie als Wert für das +über ``se_laststate_item_name`` angegebene Item verwendet. Wenn +kein Name angegeben ist, wird hier ebenfalls die Id des +Zustands-Items verwendet. + +| **se_name (optional):** +| *Ermittlung des Namens des Zustands* + +| Über das Attribut ``se_name`` kann der im Attribut ``name`` + überschrieben werden. Dies wirkt sich jedoch nur auf den Wert + aus, der in das über ``se_laststate_item_name`` angegebene + Item geschrieben wird. Im Protokoll wird immer der über das + Attribut ``name`` angegebene Wert verwendet. +| Der Parameter verwendet den Datentyp AbValue + +.. rubric:: Bedingungsgruppen + :name: bedingungsgruppen + +Jeder Zustand kann eine beliebige Anzahl von Bedingungsgruppen +haben. Jede Bedingungsgruppe definiert ein Set an Bedingungen das +überprüft wird, wenn der aktuelle Status neu ermittelt wird. +Sobald die Bedingungen einer Bedingungsgruppe vollständig erfüllt +sind, kann der Status aktiv werden. + +Jede Bedingungsgruppe wird durch ein Item +("Bedingungsgruppen-Item") unterhalb des Zustands-Items +abgebildet. Eine Bedingungsgruppe kann beliebig viele Bedingungen +umfassen. Bedingungen werden als Attribute im +Bedingungsgruppen-Item definiert. Details zu den Bedingungen +werden im Abschnitt :ref:`Bedingungen` erläutert. + +Die folgenden Regeln kommen zur Anwendung: + +- Zustände und Bedingungsgruppen werden in der Reihenfolge + geprüft, in der sie in der Konfigurationsdatei definiert sind. + +- Eine einzelne Bedingungsgruppe ist erfüllt, wenn alle + Bedingungen, die in der Bedingungsgruppe definiert sind, + erfüllt sind (UND-Verknüpfung). Einschränkungen, die in der + Bedingungsgruppe nicht definiert sind, werden nicht geprüft. + +- Ein Zustand kann aktueller Zustand werden, wenn eine beliebige + der definierten Bedingungsgruppen des Zustands erfüllt ist. Die + Prüfung ist mit der ersten erfüllten Bedingungsgruppe beendet + (ODER-Verknüpfung). + +- Ein Zustand der keine Bedingungsgruppen hat kann immer + aktueller Zustand werden. Solch ein Zustand kann als + Default-Zustand am Ende der Zustände definiert werden. + +.. rubric:: Aktionen + :name: aktionen + +Jeder Zustand kann eine beliebige Anzahl an Aktionen definieren. +Sobald ein Zustand aktueller Zustand wird werden die Aktionen des +Zustands ausgeführt. Für die Aktionen gibt es vier Ereignisse, die +festlegen, wann eine Aktion ausgeführt wird: + +- **on_enter**: Aktionen, die beim erstmaligen Aktivieren des + Zustands ausgeführt werden + +- **on_stay**: Aktionen, die ausgeführt werden, wenn der Zustand + zuvor bereits aktiv war und weiterhin aktiv bleibt. + +- **on_enteror_stay**: Aktionen, die ausgeführt werden, wenn der + Zustand aktiv ist, unabhängig davon, ob er bereits zuvor aktiv + war oder nicht. + +- **on_leave**: Aktionen, die ausgeführt werden, direkt bevor ein + anderer Zustand aktiv wird. + + Details zu den Aktionen werden im Abschnitt + :ref:`Aktionen` erläutert. + +.. rubric:: Items + :name: items + +Bedingungen und Aktionen beziehen sich überlicherweise auf Items. +Diese Items müssen auf Ebene des Objekt-Items über das Attribut +``se_item_`` bekannt gemacht werden. + +.. rubric:: Beispiel + :name: beispiel + +.. code-block:: yaml + + beispiel: + raffstore1: + automatik: + rules: + + + Tag: + type: foo + name: Tag + + enter: + + Nacht: + type: foo + name: Nacht + + enter_toodark: + + enter_toolate: + + + +| **Attribute se_item_height und se_item_lamella:** +| *Definition der Items, die durch die Aktionen + se_set_height und se_set_lamella verändert werden* + +Die Items werden durch ihre Item-Id angegeben + +| **Attribut nam:** +| *Name des Zustands* + +Der Name wird in das über ``se_laststate_item_name`` definierte +Item geschrieben, wenn der Zustand aktueller Zustand wird. Dieser +Wert kann z. B. in einer Visualisierung dargestellt werden. + +| **Attribute se_set_height und se_set_leave:** +| *Neue statische Werte für die Items die über + se_item_height und se_item_leave festgelegt wurden* + +| **Untergeordnete Items enter, enter_toodark und + enter_toolate:** +| *Bedingungsgruppen die erfüllt sein müssen, damit ein Zustand + aktueller Zustand werden kann* diff --git a/stateengine/user_doc/user_doc5.rst b/stateengine/user_doc/user_doc5.rst new file mode 100644 index 000000000..a6e51ef92 --- /dev/null +++ b/stateengine/user_doc/user_doc5.rst @@ -0,0 +1,300 @@ +.. index:: Plugins; Stateengine; Bedingungen +.. index:: Bedingungen +.. _Bedingungen: + +Bedingungen +########### + +.. rubric:: Bedingungen + :name: bedingungen + +Jede Bedingung erfordert drei Dinge: + +- Einen Namen der die Bedingung und die zugehörigen Elemente + identifiziert +- Grenzwerte um zu prüfen, ob die Bedingung erfüllt ist +- Eine Möglichkeit den aktuellen Wert zu ermitteln, gegen den die + Grenzwerte geprüft werden + +.. rubric:: Name der Bedingung + :name: namederbedingung + +Der Name der Bedingung ist beliebig und wird lediglich zur +Benennung der Attribute verwendet. Die Namen aller Attribute, die +zu einer Bedingung gehören, folgen dem Muster +``se__``. Es gibt verschiedene +"besondere" Bedingungsnamen, die später erläutert werden. + +.. rubric:: Grenzwerte + :name: grenzwerte + +Die Grenzwerte einer Bedingung werden in den Bedingungsgruppen +definiert. Die folgenden Grenzwerte sind möglich: + +.. rubric:: Minimum + :name: minimum + +.. code-block:: yaml + + se_min_: [Wert] + +Die Bedingung ist erfüllt, wenn der aktuelle Wert großer als das +angegebene Minimum ist. Fur das Attribut wird der Datentyp +AbValue verwendet. + +.. rubric:: Maximum + :name: maximum + +.. code-block:: yaml + + se_max_: [Wert] + +Die Bedingung ist erfüllt, wenn der aktuelle Wert kleiner als das +angegebene Maximum ist. Fur das Attribut wird der Datentyp +AbValue verwendet. + +.. rubric:: Bestimmter Wert + :name: bestimmterwert + +.. code-block:: yaml + + se_value_: [Wert] + +Die Bedingung ist erfüllt, wenn der aktuelle Wert gleich dem +angegebenen Wert ist. Fur das Attribut wird der Datentyp +AbValue verwendet. + +Für den Fall, dass der Wert aus Festwerten stammt (``[Wert]`` +ist ``value: [Festwert]``) kann auch eine Wertliste angegeben +werden: + +.. code-block:: yaml + + se_value_: value:[Wert1]|[Wert2]|(...)[WertN] + +In diesem Fall ist die Bedingung erfüllt, wenn der aktuelle Wert +in der Wertliste enthalten ist. + +.. rubric:: Negieren + :name: negieren + +.. code-block:: yaml + + se_negate_: True|False + +Die gesamte Bedingung (Minimum, Maximum und Wert) wird negiert +(umgekehrt). Für das Attribut wird der Datentyp Boolean verwendet, +zulässige Werte sind "true", "1", "yes", "on" bzw. "false", "0", +"no", "off" + +.. rubric:: Mindestalter + :name: mindestalter + +.. code-block:: yaml + + se_agemin_: [Wert] + +Die Bedingung ist erfüllt, wenn das Alter des Items, dass zur +Ermittlung des Werts angegeben ist, größer als das angegebene +Mindestalter ist. Fur das Attribut wird der Datentyp +AbValue verwendet. + +.. rubric:: Höchstalter + :name: hchstalter + +.. code-block:: yaml + + se_agemax_: [Wert] + +Die Bedingung ist erfüllt, wenn das Alter des Items, dass zur +Ermittlung des Werts angegeben ist, kleiner als das angegebene +Höchstalter ist. Fur das Attribut wird der Datentyp +AbValue verwendet. + +.. rubric:: Altersbedingung negieren + :name: altersbedingungnegieren + +.. code-block:: yaml + + se_agenegate_: True|False + +Die Altersbedingung (Mindestalter, Höchstalter) wird negiert +(umgekehrt). Fur das Attribut wird der Datentyp Boolean verwendet, +zulässige Werte sind "true", "1", "yes", "on" bzw. "false", "0", +"no", "off" + +.. rubric:: Bereitstellung des aktuellen Werts + :name: bereitstellungdesaktuellenwerts + +Der aktuelle Wert kann entweder über ein Item oder über eine +Eval-Funktion bereitgestellt werden. Wenn beides angegeben ist +wird das Item verwendet und die Eval-Funktion ignoriert. + +Der Name des Items, über das der aktuelle Wert abgerufen werden +soll, wird auf Ebene des Objekt-Items über das Attribut +``se_item_`` angegeben. Die Eval-Funktion, über +die der aktuelle Wert abgerufen werden soll, wird auf Ebene des +Objekt-Items über das Attribut +``se_eval_`` angegeben. Der Bedingungsname in ``se_item`` bzw. ``se_eval`` +muss mit den Bedingungsnamen in den Bedingungen korrespondieren. + +Das sich Altersbedingungen auf das Alter der hinterlegten Items +beziehen können ``se_agemin_``, +``se_agemax_`` und +``se_agenegate_`` nur verwendet werden, wenn der +aktuelle Wert über ein Item bereitgestellt wird. + +.. rubric:: Beispiel + :name: beispiel + +.. code-block:: yaml + + beispiel: + raffstore1: + automatik: + rules: + <...> + se_item_height: beispiel.raffstore1.hoehe + se_item_lamella: beispiel.raffstore1.lamelle + se_item_brightness: beispiel.wetterstation.helligkeit + Daemmerung: + type: foo + name: Dämmerung + + enter: + se_min_brightness: 500 + se_max_brightness: value:1000 + + Nacht: + type: foo + name: Nacht + + enter_todark: + se_max_brightness: 500 + + Sonder: + type: foo + name: Ein spezielles Bedingungsset + + enter: + se_min_brightness: item:test.wert + se_max_brightness: eval:sh.test.wert() + 500 + + +.. rubric:: "Besondere" Bedingungen + :name: besonderebedingungen + +Das Plugin stellt die Werte für einige "besondere" Bedingungen +automatisch bereit. Für diese Bedingungen muss daher kein Item und +keine Eval-Funktion zur Ermittlung des aktuellen Werts angegeben +werden. Die "besonderen" Bedingungen werden über reservierte +Bedingungsnamen gekennzeichnet. Diese Bedingungsnamen dürfen daher +nicht für andere Bedingungen verwendet werden. + +Die folgenden "besonderen" Bedingungsnamen können verwendet werden + +.. rubric:: time + :name: time + +*Aktuelle Uhreit* + +Die Werte für ``se_value_time``, ``se_min_time`` und +``se_max_time`` müssen im Format "hh:mm" (":") angegeben werden. +Es wird ein 24 Stunden-Zeitformat verwendet. Beispiele: "08:00" +oder "13:37". Um das Ende des Tages anzugeben kann der Wert +"24:00" verwendet werden, der für die Prüfungen automatisch zu +"23:59:59" konvertiert wird. Wichtig sind die Anführungszeichen +oder Hochkommas! + +.. rubric:: weekday + :name: weekday + +*Wochentag* + +0 = Montag, 1 = Dienstag, 2 = Mittwoch, 3 = Donnerstag, 4 = +Freitag, 5 = Samstag, 6 = Sonntag + +.. rubric:: month + :name: month + +*Monat* + +1 = Januar, ..., 12 = Dezember + +.. rubric:: sun_azimut + :name: sun_azimut + +*Sonnenstand (Horizontalwinkel)* + +Der Azimut (Horizontalwinkel) ist die Kompasrichtung in der die +Sonne steht. Der Azimut wird von smarthomeNg auf Basis der +aktuellen Zeit sowie der konfigurierten geographischen Position +berechnet. Siehe auch `SmarthomeNg +Dokumentation `_ +für Voraussetzungen zur Berechnung der Sonnenposition. +Beispielwerte: 0 → Sonne exakt im Norden, 90 → Sonne exakt im +Osten, 180 → Sonne exakt im Süden, 270 → Sonne exakt im Westen + +.. rubric:: sun_altitude + :name: sun_altitude + +*Sonnenstand (Vertikalwinkel)* + +Die Altitude (Vertikalwikel) ist der Winkel, in dem die Sonne über +dem Horizont steht. Die Altitude wird von smarthomeNg auf Basis +der aktuellen Zeit sowie der konfigurierten geographischen +Position berechnet. Siehe auch `SmarthomeNG +Dokumentation `_ +für Voraussetzungen zur Berechnung der Sonnenposition. Werte: +negativ → Sonne unterhalb des Horizonts, 0 → +Sonnenaufgang/Sonnenuntergang, 90 → Sonne exakt im Zenith +(passiert nur in äquatorialen Bereichen) + +.. rubric:: age + :name: age + +*Zeit seit der letzten Änderung des Zustands (Sekunden)* + +Das Alter wird über die letzte Änderung des Items, dass als +``se_laststate_item_id`` angegeben ist, ermittelt. + +.. rubric:: random + :name: random + +*Zufallszahl zwischen 0 und 100* + +Wenn etwas zufällig mit einer Wahrscheinlichkeit von 60% passieren +soll, kan beispielsweise die Bedingung ``max_random: 60`` +verwendet werden. + +.. rubric:: laststate + :name: laststate + +*Id des Zustandsitems des aktuellen Status* + +Wichtig: Hier muss die vollständige Item-Id angegeben werden + +.. rubric:: trigger_item, trigger_caller, trigger_source, trigger_dest + :name: trigger_itemtrigger_callertrigger_sourcetrigger_dest + +*item, caller, source und dest-Werte durch die die +Zustandsermittlung direkt ausgelöst wurde* + +Über diese vier Bedingungen kann der direkte Auslöser der +Zustandsermittlung abgeprüft werden, also die Änderung, die +smarthomeNG veranlasst, die Zustandsermittlung des +stateengine-Plugins aufzurufen. + +.. rubric:: original_item, original_caller, original_source + :name: original_itemoriginal_calleroriginal_source + +*item, caller, source und dest-Werte durch die die +Zustandsermittlung ursprünglich ausgelöst wurde* + +Über diese vier Bedingungen kann der ursprüngliche Auslöser der +Zustandsermittlung abgeprüft werden. Beim Aufruf der +Zustandsermittung über einen ``eval_trigger`` Eintrag wird über +``trigger_caller`` beispielsweise nur ``Eval`` weitergegeben. +In den drei ``original_*`` Bedingungen wird in diesem Fall der +Auslöser der Änderung zurückverfolgt und der Einstieg in die +``Eval``-Kette ermittelt. diff --git a/stateengine/user_doc/user_doc6.rst b/stateengine/user_doc/user_doc6.rst new file mode 100644 index 000000000..54405d7e4 --- /dev/null +++ b/stateengine/user_doc/user_doc6.rst @@ -0,0 +1,94 @@ +.. index:: Plugins; Stateengine; Ausführungszeitpunkt +.. index:: Ausführungszeitpunkt + +Ausführungszeitpunkt +#################### + +.. rubric:: Aktionen - Ausführungszeitpunkt + :name: aktionenausfhrungszeitpunkt + +Um festzulegen, wann die Aktionen eines Zustands ausgeführt +werden, gibt es vier Ereignisse, denen die Aktionen zugeordnet +werden können: Für jedes dieser Ereignisse wird ein Item unterhalb +des Zustands-Items angelegt, unterhalb dem die jeweiligen Aktionen +als Attribute definiert werden. + +- **on_enter**: Aktionen, die beim erstmaligen Aktivieren des + Zustands ausgeführt werden +- **on_stay**: Aktionen, die ausgeführt werden, wenn der Zustand + zuvor bereits aktiv war und weiterhin aktiv bleibt. +- **on_enter_or_stay**: Aktionen, die ausgeführt werden, wenn der + Zustand aktiv ist, unabhängig davon, ob er bereits zuvor aktiv + war oder nicht. +- **on_leave**: Aktionen, die ausgeführt werden, direkt bevor ein + anderer Zustand aktiv wird. + +Aktionen können auch ohne diese Ereigniss-Items direkt im +Zustands-Item definiert werden. Solche Aktionen werden analog zum +Ereignis ``on_enter_or_stay`` behandelt. + +**Beispiel** + +.. code-block:: yaml + + test: + type: foo + + events: + name: stateengine Event Beispiel + type: foo + + item: + name: Dummy Item + type: bool + value: False + + rules: + type: bool + name: Automatik Test Event + # Dies ist ein Objekt-Item für das stateengine-Plugin: + se_plugin: active + + state1: + type: foo + name: Status 1 + + on_enter: + type: foo + name: Ausführen immer wenn ein Zustand gerade aktiv geworden ist + <... Aktionen ...> + + on_stay: + type: foo + name: Ausführen immer wenn ein Zustand aktiv geworden ist und bereits vorher aktiv war + <... Aktionen ...> + + on_enter_or_stay: + type: foo + name: Ausführen immer wenn ein Zustand aktiv ist + <... Aktionen ...> + + on_leave: + type: foo + name: Ausführen beim Verlassen des Zustands + <... Aktionen ...> + + enter_1: + type: foo + name: Bedingung 1 + <...Einstiegs-Bedingungsset 1...> + + enter_2: + type: foo + name: Bedingung 2 + <...Einstiegs-Bedingungsset 2...> + + state2: + type: foo + name: Status 2 + <... Weitere Bedingungssets und Aktionsgruppen ...> + + state3: + type: foo + name: Status 3 + <... Weitere Bedingungssets und Aktionsgruppen ...> diff --git a/stateengine/user_doc/user_doc7.rst b/stateengine/user_doc/user_doc7.rst new file mode 100644 index 000000000..7929d1faf --- /dev/null +++ b/stateengine/user_doc/user_doc7.rst @@ -0,0 +1,277 @@ +.. index:: Plugins; Stateengine; Aktionen - einzeln +.. index:: Aktionen - einzeln + +Aktionen - einzeln +################## + +.. rubric:: Aktionen - Einzelvariante + :name: aktioneneinzelvariante + +Bei der Einzelvariante zur Definition von Aktionen werden alle +Parameter einer Aktion in separaten Attributen definiert. Über den +gemeinsamen Aktionsnamen gehören die Attribute einer Aktion +zusammen. + +Ähnlich wie Bedingungen benötigen auch Aktionen einen Namen. Der +Name ist auch hier beliebig und wird lediglich in der Benennung +der Attribute verwendet. Die Namen aller Attribute, die zu einer +Bedingung gehören, folgen dem Muster ``se__``. + +.. rubric:: Aktion: Item auf einen Wert setzen + :name: aktionitemaufeinenwertsetzen + +.. code-block:: yaml + + se_set_ + +Das Item, dass verändert werden soll, muss auf Ebene des +Objekt-Items über das Attribut ``se_item_`` +angegeben werden. + +Das Attribut ``se_set_`` nutzt den Datentyp +AbValue. Der Wert, auf den das +Item gesezt wird kann dadurch als statischer Wert, als Wert eines +Items oder als Ergebnis der Ausführung einer Funktion festgelegt +werden. + +**Minimumabweichung:** Es ist möglich eine Minimumabweichung für +Änderungen zu definieren. Wenn die Differenz zwischen dem +aktuellen Wert des Items und dem ermittelten neuen Wert kleiner +ist als die festgelegte Minimumabweichung wird keine Änderung +vorgenommen. Die Minimumabweichung wird über das Attribut +``se_mindelta_`` auf der Ebene des Objekt-Items +festgelegt. Auch hier wird der Datentyp +AbValue verwendet. + +.. rubric:: Aktion: Item zwangsweise auf einen Wert setzen + :name: aktionitemzwangsweiseaufeinenwertsetzen + +.. code-block:: yaml + + se_force_ + +Diese Aktion funktioniert analog zu ``se_set_``. +Einziger Unterschied ist, dass die Wertänderung erzwungen wird: +Wenn das Item bereits den zu setzenden Wert hat, dann ändert +smarthomeNG das Item nicht. Selbst wenn beim Item das Attribut +``enforce_updates: yes`` gesetzt ist, wird zwar der Wert neu +gesetzt, der von smarthomeNG Änderungszeit nicht neu gesetzt. Mit +dem Attribut ``se_force_`` wird das Plugin den Wert +des Items bei Bedarf zuerst auf einen anderen Wert ändern und dann +auf dem Zielwert setzen. Damit erfolgt auf jeden Fall eine +Wertänderung (ggf. sogar zwei) mit allen damit in Zusammenhang +stehenden Änderungen (eval's, Aktualisierung der Änderungszeiten, +etc). + +.. rubric:: Aktion: Ausführen einer Funktion + :name: aktionausfhreneinerfunktion + +.. code-block:: yaml + + se_run_: eval:(Funktion) + +Die Angabe ist vergleichbar mit dem Ausführen einer Funktion zur +Ermittlung des Werts für ein Item, hier wird jedoch kein Item +benötigt. Außerdem wird der Rückgabewert der Funktion ignoriert. + +.. rubric:: Aktion: Auslösen einer Logikausführung + :name: aktionauslseneinerlogikausfhrung + +.. code-block:: yaml + + se_trigger_ + +Um beim Auslösen einen Wert an die Logik zu übergeben, kann dieser +Wert im Attribut über die Angabe von ``:`` hinter dem +Logiknamen angegeben werden. + +**Beispiel:** + +.. code-block:: yaml + + se_trigger_: meineLogik:Zu übergebender Wert + +.. rubric:: Aktion: Alle Items, die ein bestimmtes Attribut haben, + auf den Wert dieses Attributs setzen + :name: aktionalleitemsdieeinbestimmtesattributhabenaufdenwertdiesesattributssetzen + +.. code-block:: yaml + + se_byattr_ + +Mit diesem Attribut wird der Name eines anderen (beliebigen) +Attributs angegeben. Beim Ausführen werden alle Items +herausgesucht, die das angegebene Attribut enthalten. Diese Items +werden auf den Wert gesetzt, der dem genannten Attribut in den +Items jeweils zugewiesen ist. + +**Beispiel:** + +.. code-block:: yaml + + se_byattr_: mein_eigenes_Attribut + +sucht alle Items heraus, bei denen das Attribut +``mein_eigenes_Attribut`` angegeben ist. Ein Item + +.. code-block:: yaml + + dummy: + type: num + mein_eigenes_Attribut: 42 + +| wird dann auf ``42`` gesetzt. +| Ein anderes Item + +.. code-block:: yaml + + dummy2: + type: str + mein_eigenes_Attribut: Rums + +wird gleichzeitig auf ``Rums`` gesetzt. + +.. rubric:: Aktion: Sondervorgänge + :name: aktionsondervorgnge + +.. code-block:: yaml + + se_special_: (Sondervorgang) + +Für bestimmte Sondervorgänge sind besondere Aktionen im Plugin +definiert (z. B. für das Suspend). Diese werden jedoch nicht hier +erläutert, sondern an den Stellen, andenen Sie verwendet werden. + +.. rubric:: Verzögertes Ausführen einer Aktion + :name: verzgertesausfhreneineraktion + +.. code-block:: yaml + + se_delay_ + +Über das Attribut wird die Verzögerung angegeben, nach der die +Aktion ausgeführt werden soll. Die Angabe erfolgt in Sekunden oder +mit dem Suffix "m" in Minuten. + +.. code-block:: yaml + + se_delay_: 30 --> 30 Sekunden + se_delay_: 30m --> 30 Minuten + +| Der Timer zur Ausführung der Aktion nach der angegebenen + Verzögerung wird entfernt, wenn eine gleichartike Aktion + ausgeführt werden soll (egal ob verzögert oder nicht). Wenn also + die Verzögerung größer als der ``cycle`` ist, wird die Aktion + nie durchgeführt werden, es sei denn die Aktion soll nur + einmalig ausgeführt werden. +| Das Attribut ``se_delay_`` verwendet den + Datentyp AbValue + +.. rubric:: Wiederholen einer Aktion + :name: wiederholeneineraktion + +.. code-block:: yaml + + se_repeat_ + +Über das Attribut wird unabhängig vom globalen Setting für das +stateengine Item festgelegt, ob eine Aktion auch beim erneuten +Eintritt in den Status ausgeführt wird oder nicht. + +.. code-block:: yaml + + se_repeat_: True # Aktion wird bei jedem Mal aufs neue ausgeführt + se_repeat_: False # Aktion wird nur beim ersten Eintritt in den Status ausgeführt + + +.. rubric:: Festlegen der Ausführungsreihenfolge von Aktionen + :name: festlegenderausfhrungsreihenfolgevonaktionen + +.. code-block:: yaml + + se_order_ + +Die Reihenfolge, in der die Aktionen ausgeführt werden, ist nicht +zwingend die Reihenfolge in der die Attribute definiert sind. In +den meisten Fällen ist dies kein Problem da die Aktionen +voneinander unabhängig sind und daher in beliebiger Reihenfolge +ausgeführt werden können. In Einzelfällen kann es jedoch +erforderlich sein, mehrere Aktionen in einer bestimmten +Reihenfolge auszuführen. Dies kann über das Attribut +``se_order_`` erfolgen. Mit diesem Attribut wird der +Aktion eine Zahl zugewiesen. Aktionen werden in aufsteigender +Reihenfolge der zugewiesenen Zahlen ausgeführt. + +Es ist möglich zwei Aktionen die gleiche Zahl zuzuweisen, die +Reihenfolge der beiden Aktionen untereinander ist dann wieder +undefiniert. Innerhalb der gesamten Aktionen werden die beiden +Aktionen jedoch an der angegebenen Position ausgeführt. + +Wird für eine Aktion kein Reihenfolgenwert angegeben, wird +implizit der Wert 1 verwendet. + +Das Attribut ``se_order_`` verwendet den Datentyp +AbValue + +**Beispiel zur Ausführungsreihenfolge:** + +.. code-block:: yaml + + beispiel: + automatik: + rules: + <...> + Zustand1: + se_order_aktion1: 3 + se_order_aktion2: 2 + se_order_aktion3: 1 + se_order_aktion4: 2 + + +Die Reihenfolge der Aktionen hier wird wie folgt sein: + +#. aktion3 +#. aktion2, aktion4 ODER aktion4, aktion2 +#. aktion 1 + +Ist zusätzlich eine aktion5 definiert, die keine Reihenfolge +festgelegt hat, wird die Reihenfolge der Aktionen wie folgt sein: + +#. aktion3, aktion5 ODER aktion5, aktion3 +#. aktion2, aktion4 ODER aktion4, aktion2 +#. aktion 1 + +.. rubric:: Beispiel zu Aktionen + :name: beispielzuaktionen + +.. code-block:: yaml + + beispiel: + raffstore: + automatik: + rules: + <...> + se_item_height: beispiel.raffstore1.hoehe + se_mindelta_height: 10 + se_item_lamella: beispiel.raffstore1.lamelle + se_mindelta_lamella: 5 + Daemmerung: + <...> + se_set_height: value:100 + se_set_lamella: value:25 + <...> + Nacht: + <...> + se_set_height: value:100 + se_set_lamella: value:0 + <...> + Nachfuehren: + <...> + se_set_height: value:100 + se_set_lamella: eval:stateengine_eval.sun_tracking() + <...> + Sonder: + <...> + se_trigger_logic1: myLogic:42 + se_delay_logic1: 10 + <...> diff --git a/stateengine/user_doc/user_doc8.rst b/stateengine/user_doc/user_doc8.rst new file mode 100644 index 000000000..42dcb8d7c --- /dev/null +++ b/stateengine/user_doc/user_doc8.rst @@ -0,0 +1,288 @@ +.. index:: Plugins; Stateengine; Aktionen - kombiniert +.. index:: Aktionen - kombiniert +.. _Aktionen: + +Aktionen - kombiniert +##################### + +.. rubric:: Aktionen - Kombinierte Variante + :name: aktionenkombiniertevariante + +Bei der kombinierten Variante zur Definition von Aktionen werden +alle Parameter einer Aktion in einem Attribut definiert. Über den +Aktionsnamen werden lediglich eventuelle Items zugeordnet. Die +einzelnen Parameter werden bei conf-Files in der +Listenschreibweise mit dem Zeichen ``|`` getrennt aufgelistet: + +.. code-block:: none + + se_action_: function: | (evtl. Detailparameter zur Funktion) | delay: | order: | repeat: + +Bei yaml Files werden die Parameter mittels Aufzählungszeichen "-" +untereinander definiert: + +.. code-block:: yaml + + se_action_: + - function: + - Detailparameter der Funktion, z.B. "to: .." + - delay: + - order: + - repeat: + +Die Parameter haben dabei folgende Bedeutung: + +.. rubric:: delay: ```` + :name: delaydelay + +Über ```` wird die Verzögerung angegeben, nach der die +Aktion ausgeführt werden soll. + +Der Parameter ist optional und kann auch weggelassen werden. In +diesem Fall wird die Aktion sofort ausgeführt. + +Die Angabe erfolgt in Sekunden oder mit dem Suffix "m" in Minuten. + +.. code-block:: yaml + + delay: 30 --> 30 Sekunden + delay: 30m --> 30 Minuten + +| Der Timer zur Ausführung der Aktion nach der angegebenen + Verzögerung wird entfernt, wenn eine gleichartike Aktion + ausgeführt werden soll (egal ob verzögert oder nicht). Wenn also + die Verzögerung größer als der ``cycle`` ist, wird die Aktion + nie durchgeführt werden, es sei denn die Aktion soll nur + einmalig ausgeführt werden. +| Für den Wert von ```` wird der Datentyp + AbValue verwendet. + +.. rubric:: repeat: ```` + :name: repeatrepeat + +.. code-block:: yaml + + se_repeat_ + +Über das Attribut wird unabhängig vom globalen Setting für das +stateengine Item festgelegt, ob eine Aktion auch beim erneuten +Eintritt in den Status ausgeführt wird oder nicht. + +.. code-block:: yaml + + se_repeat_: True # Aktion wird bei jedem Mal aufs neue ausgeführt + se_repeat_: False # Aktion wird nur beim ersten Eintritt in den Status ausgeführt + +.. rubric:: order: ```` + :name: orderorder + +Die Reihenfolge, in der die Aktionen ausgeführt werden, ist nicht +zwingend die Reihenfolge in der die Attribute definiert sind. In +den meisten Fällen ist dies kein Problem da die Aktionen +voneinander unabhängig sind und daher in beliebiger Reihenfolge +ausgeführt werden können. In Einzelfällen kann es jedoch +erforderlich sein, mehrere Aktionen in einer bestimmten +Reihenfolge auszuführen. Dies kann über den Parameter +``order: `` erfolgen. Mit diesem Attribut wird der Aktion +eine Zahl zugewiesen. Aktionen werden in aufsteigender Reihenfolge +der zugewiesenen Zahlen ausgeführt. + +Der Parameter ist optional und kann auch weggelassen werden. Für +Aktionen, denen keine Reihenfolge explizit zugewiesen wurde, wird +der Reihenfolgenwert 1 verwendet. + +Es ist möglich zwei Aktionen die gleiche Zahl zuzuweisen, die +Reihenfolge der beiden Aktionen untereinander ist dann wieder +undefiniert. Innerhalb der gesamten Aktionen werden die beiden +Aktionen jedoch an der angegebenen Position ausgeführt. + +Für den Wert von ```` wird der Datentyp +AbValue verwendet. + +.. rubric:: function: ```` + :name: functionfunc + +| Mit dem Parameter ```` wird die auszuführende Funktion + festgelegt. In Abhängigkeit zur gewählten Funktion werden + zusätzliche Detailparameter erforderlich. +| Folgende Werte sind möglich: + +.. rubric:: Funktion ``set``: Item auf einen Wert setzen + :name: funktionsetitemaufeinenwertsetzen + +.. code-block:: yaml + + se_action_: + - function: set + - to: + - force: [True/False] + +Das Item, dass verändert werden soll, muss auf Ebene des +Objekt-Items über das Attribut ``se_item_`` +angegeben werden. + +Der Parameter ``to: `` legt fest, auf welchen Wert das Item +gesetzt werden soll. Für ```` wird der Datentyp +AbValue verwendet. Der Wert, +auf den das Item gesezt wird kann dadurch als statischer Wert, als +Wert eines Items oder als Ergebnis der Ausführung einer Funktion +festgelegt werden. + +**Erzwingen der Wertänderung:** Über den optionalen Parameter +``force: [True/False]`` kann eine Wertänderung erzwungen werden: +Wenn das Item bereits den zu setzenden Wert hat, dann ändert +smarthomeNG das Item nicht. Selbst wenn beim Item das Attribut +``enforce_updates: yes`` gesetzt ist, wird zwar der Wert neu +gesetzt, der von smarthomeNG Änderungszeit nicht neu gesetzt. Wird +der Parameter ``force: True`` gesetzt, so wird das Plugin den Wert +des Items bei Bedarf zuerst auf einen anderen Wert ändern und dann +auf dem Zielwert setzen. Damit erfolgt auf jeden Fall eine +Wertänderung (ggf. sogar zwei) mit allen damit in Zusammenhang +stehenden Änderungen (eval's, Aktualisierung der Änderungszeiten, +etc). + +**Minimumabweichung:** Es ist möglich eine Minimumabweichung für +Änderungen zu definieren. Wenn die Differenz zwischen dem +aktuellen Wert des Items und dem ermittelten neuen Wert kleiner +ist als die festgelegte Minimumabweichung wird keine Änderung +vorgenommen. Die Minimumabweichung wird über das Attribut +``se_mindelta_`` auf der Ebene des Objekt-Items +festgelegt. Auch hier wird der Datentyp +AbValue verwendet. + +.. rubric:: Funktion ``run``: Ausführen einer Funktion + :name: funktionrunausfhreneinerfunktion + +.. code-block:: yaml + + se_action_: + - function: run + - eval:(Funktion) + +Die Angabe ist vergleichbar mit dem Ausführen einer Funktion zur +Ermittlung des Werts für ein Item, hier wird jedoch kein Item +benötigt. Außerdem wird der Rückgabewert der Funktion ignoriert. + +.. rubric:: Funktion ``trigger``: Auslösen einer Logikausführung + :name: funktiontriggerauslseneinerlogikausfhrung + +.. code-block:: yaml + + se_action_: + - function: trigger + - logic: + - value: + +Löst die Ausführung der Logik ````\ aus. Um beim +Auslösen einen Wert an die Logik zu übergeben, kann dieser Wert +über die Angabe von ``value: `` hinter dem Logiknamen +angegeben werden. Wenn kein Wert übergeben werden soll lässt man +den Teil weg. + +.. rubric:: Funktion ``byattr``: Alle Items, die ein bestimmtes + Attribut haben, auf den Wert dieses Attributs setzen + :name: funktionbyattralleitemsdieeinbestimmtesattributhabenaufdenwertdiesesattributssetzen + +.. code-block:: yaml + + se_action_: + - function: byattr + - attribute: + +Mit dieser Funktion wird der Name eines anderen (beliebigen) +Attributs angegeben. Beim Ausführen werden alle Items +herausgesucht, die das angegebene Attribut enthalten. Diese Items +werden auf den Wert gesetzt, der dem genannten Attribut in den +Items jeweils zugewiesen ist. + +**Beispiel:** + +.. code-block:: yaml + + se_action_: + - function: byattr + - attribute: mein_eigenes_Attribut + +sucht alle Items heraus, bei denen das Attribut +``mein_eigenes_Attribut`` angegeben ist. Ein Item + +.. code-block:: yaml + + dummy1: + type: num + mein_eigenes_Attribut: 42 + +| wird dann auf ``42`` gesetzt. +| Ein anderes Item + +.. code-block:: yaml + + dummy2: + type: str + mein_eigenes_Attribut: Rums + + +wird gleichzeitig auf ``Rums`` gesetzt. + +.. rubric:: Funktion ``special``: Sondervorgänge + :name: funktionspecialsondervorgnge + +.. code-block:: yaml + + se_action_: + - function: special + - value: + +Für bestimmte Sondervorgänge sind besondere Aktionen im Plugin +definiert (z. B. für das Suspend). Diese werden jedoch nicht hier +erläutert, sondern an den Stellen, andenen Sie verwendet werden. + +.. rubric:: Beispiel zu Aktionen + :name: beispielzuaktionen + +.. code-block:: yaml + + beispiel: + raffstore: + automatik: + rules: + <...> + se_item_height: beispiel.raffstore1.hoehe + se_mindelta_height: 10 + se_item_lamella: beispiel.raffstore1.lamelle + se_mindelta_lamella: 5 + Daemmerung: + <...> + se_action_height: + - function: set + - to: value:100 + se_action_lamella: + - function: set + - to: value:25 + <...> + Nacht: + <...> + se_action_height: + - function: set + - to: value:100 + se_action_lamella: + - function: set + - to: value:0 + <...> + Nachfuehren: + <...> + se_action_height: + - function: set + - to: value:100 + se_action_lamella: + - function: set + - to: eval:stateengine_eval.sun_tracking() + <...> + Sonder: + <...> + se_action_logic1: + - function: trigger + - logic: myLogic + - value:42 + - delay: 10 + <...> diff --git a/stateengine/user_doc/user_doc9.rst b/stateengine/user_doc/user_doc9.rst new file mode 100644 index 000000000..1f8c0a6d4 --- /dev/null +++ b/stateengine/user_doc/user_doc9.rst @@ -0,0 +1,99 @@ +.. index:: Plugins; Stateengine; Vorgabezustände +.. index:: Vorgabezustände + +Vorgabezustände +############### + +.. rubric:: Vorgabezustände verwenden + :name: vorgabezustndeverwenden + +Es ist möglich Vorgabezustände in der Konfiguration zu definieren +und diese später für konkrete Objekte anzuwenden. Dabei können im +konkreten Zustand auch Einstellungen des Vorgabezustands +überschrieben werden. + +Vorgabezustände werden als Item an beliebiger Stelle innerhalb der +Item-Struktur definiert. Es ist sinnvoll, die Vorgabezustände +unter eingem gemeinsamen Item zusammenzufassen. Innerhalb der +Vorgabezustand-Items stehen die gleichen Möglichkeiten wie in +normalen Zustands-Items zur Verfügung. Das dem +Vorgabezustands-Item übergeordnete Item darf nicht das Attribut +``se_plugin: active`` haben. Im Item über dem +Vorgabezustands-Item können jedoch Items über +``se_item_`` angegeben werden. Diese +stehen in den Vorgabezuständen und in den von den Vorgabezuständen +abgeleiteten Zuständen zur Verfügung und müssen so nicht jedes mal +neu definiert werden. + +Im konkreten Zustands-Item kann das Vorgabezustand-Item über das +Attribut + +.. code-block:: yaml + + se_use: + +eingebunden werden. Die Vorgabezustand-Items können geschachtelt +werden, dass heißt ein Vorgabezustand kann also selbst wiederum +über ``se_use`` von einem weiteren Vorgabezustand abgeleitet +werden. Um unnötige Komplexität und Zirkelbezüge zu vermeiden ist +die maximale Tiefe jedoch auf 5 Ebenen begrenzt. + +.. rubric:: Beispiel + :name: beispiel + +.. code-block:: yaml + + beispiel: + default: + <...> + se_item_height: ...hoehe + Nacht: + <...> + enter: + (...) + se_set_height: value:100 + se_set_lamella: 0 + Morgens: + <...> + enter: + <...> + se_set_height: value:100 + se_set_lamella: 25 + + Abends: + <...> + enter: + <...> + se_set_height: value:100 + se_set_lamella: 75 + + Tag: + <...> + enter: + <...> + se_set_height: value:0 + se_set_lamella: 100 + + beispiel + raffstore1: + automatik: + rules: + <...> + se_item_lamella: beispiel.raffstore1.lamelle + Nacht: + se_use: beispiel.default.Nacht + enter_additional: + <... zusätzliche Einstiegsbedingung ...> + Morgens: + se_use: beispiel.default.Morgens + Abends: + se_use: beispiel.default.Abends + enter: + <... Änderungen an der Einstiegsbedingung des Vorgabezustands ...> + Nachfuehren: + <...> + name: Zusätzlicher Zustand, der nicht aus den Vorgabezuständen kommt + se_set_height: value:100 + se_set_lamella: eval:stateengine_eval.sun_tracking() + Tag: + se_use: stateengine.default.day diff --git a/stateengine/webif/templates/doku1.html b/stateengine/webif/templates/doku1.html deleted file mode 100755 index 903423d8e..000000000 --- a/stateengine/webif/templates/doku1.html +++ /dev/null @@ -1,123 +0,0 @@ -{% extends "base_plugin.html" %} -{% block scripts %} -{{ super() }} - -{% endblock scripts %} -{% set logo_frame = false %} - - -{% set item_count = p.__items|length %} -{% set tab1title = "_('Dokumentation')" %} -{% set tab2title = "Items" %} -{% set tabcount = 1 %} - -{% block headtable %} - - - - - - - - - - - - - - - - - - - - - - - - - -
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
-{% endblock headtable %} - - -{% block bodytab1 %} - -
- -
-

stateengine Plugin für smarthomeNG - Deutsche Dokumentation

- -

Warnung

- -

Wichtig: - Es ist nicht empfehlenswert das stateengine Plugin für sicherheitsrelevante Zustände, wie zum Beispiel das Hochfahren von Jalousien bei zu viel Wind, zu verwenden. Sicherheitsrelevante Funktionen müssen so einfach wie möglich aufgebaut sein. Es wird daher dringend dazu geraten, solche Funktionen unabhängig von smarthomeNG und dem stateengine Plugin zu realisieren. Für das Hochfahren von Jalousien bei Windalarm beispielsweise sollte die Sperrfunktionalität verwendet werden, über die alle aktuellen Jalousieaktoren verfügen!

- -

Funktionalität

- -

Über zusätzliche Items in den items/*.conf-Dateien können Objekte definiert werden, die eine beliebige Anzahl benutzerdefinierter Zustand haben. Jeder Zustand kann Sets von Einstiegs- und Ausstiegsbedingungen haben, sowie diverse Aktionen auslösen, wenn der Zustand aktiv wird. In regelmäßigen Intervallen werden die Zustände für jedes Objekt geprüft.

- -
    -
  • Wenn die Ausstiegsbedingungen des aktuellen Zustands nicht erfüllt sind bleibt das Objekt im aktuellen Zustand.
  • - -
  • Wenn der aktuelle Zustand verlassen werden kann werden alle Zustände in der Reihenfolge, in der sie in der Konfigurationsdatei definiert sind, abgeprüft.
  • - -
  • Der erste Zustand bei dem eine Gruppe Einstiegsbedingungen vollständig erfüllt ist, wird zum aktuellen Zustand. Die Aktionen, die für diesen Zustand definiert sind, werden ausgeführt.
  • - -
  • Wenn kein passender Zustand gefunden wird passiert nichts. Das Objekt verbleibt im vorherigen Zustand.
  • -
- -

Die folgenden Bedingungen können Teil der Bedingungsgruppen sein:

- -
    -
  • Tageszeit (Minimum, Maximum, Wert)
  • - -
  • Wochentag (Minimum, Maximum, Wert)
  • - -
  • Azimut der Sonne (Minimum, Maximum, Wert)
  • - -
  • Altitude der Sonne (Minimum, Maximum, Wert)
  • - -
  • Alter des aktuellen Zustands (Minimum, Maximum, Wert)
  • - -
  • Zufallszahl (Minimum, Maximum, Wert)
  • - -
  • Vorheriger Zustand (Wert)
  • - -
  • Trigger-Objekt, dass die Zustandsermittlung ausgelöst hat
  • -
- -

Zusätzlich können beliebige Items als Bedingungen geprüft werden (Minimum, Maximum oder Wert)

- -

Der ursprüngliche Zweck dieses Plugins war es, Jalousien zu steuern. Mit den steigenden Anforderungen hat es sich jedoch zu einem flexiblen Zustandsautomaten entwickelt, mit dem nahezu alles gesteuert werden kann. Im Prinzip ist es ein endlicher Automat.

-
- - -
-{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku10.html b/stateengine/webif/templates/doku10.html deleted file mode 100755 index 72e6fe6b2..000000000 --- a/stateengine/webif/templates/doku10.html +++ /dev/null @@ -1,128 +0,0 @@ -{% extends "base_plugin.html" %} -{% block scripts %} -{{ super() }} - -{% endblock scripts %} -{% set logo_frame = false %} - - -{% set item_count = p.__items|length %} -{% set tab1title = "StateEngine" %} -{% set tabcount = 1 %} - -{% block headtable %} - - - - - - - - - - - - - - - - - - - - - - - - - -
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
-{% endblock headtable %} - - -{% block bodytab1 %} - -
- -
-

Vordefinierte Funktionen

- -

Das stateengine Plugin stellt verschiedene vordefinierte Funktionen zur Verfügung die einfach für "se_set_<Aktionsname>" und "se_run_<Aktionsname>" Aktionen verwendet werden können. Diese Funktionen sind in einer Klasse enthalten, die bei Bedarf für das Ausführen der Aktion instanziiert wird. Die folgenden Funktionen können verwendet werden:

- -

Winkel zum Nachführen der Jalousielamellen auf Basis des Sonnenstands berechnen

- -
stateengine_eval.sun_tracking()
-    
- -

Zufallszahl

- -
stateengine_eval.get_random_int(min,max)
-    
- -

Über "min" und "max" kann die kleinste/größte Nummer, die zurückgegeben werden soll, festgelegt werden. "min" und "max" können weggelassen werden, in diesem Fall sind die Vorgabewerte 0 für min und 255 für max.

- -

Shell-Kommando ausführen

- -
stateengine_eval.execute(command)
-    
- -

Führt das Shell-Kommando "command" aus

- -

Wert einer Variable ermitteln

- -
stateengine_eval.get_variable(varname)
-    
- -

Liefert den Wert der [[Variablen|Doku-De-Variablen]] "varname"

- -

Item-Id relativ zum Objekt-Item ermitteln

- -
stateengine_eval.get_relative_itemid(subitem_id)
-    
- -

Eine Item-Id relativ zur Item-Id des Objekt-Items wird ermittelt. Die Ermittlung erfolgt dabei mit der gleichen Rotine, die zur [[relativen Ermittlung von Items|Doku-De-Grundsaetzliches-Relative-Itemangaben]] verwendet wird.

- -

Item-Wert relativ zum Objekt-Item ermitteln

- -
stateengine_eval.get_relative_itemvalue(subitem_id)
-    
- -

Der Wert eines Items relativ zur Item-Id des Objekt-Items wird ermittelt. Die Ermittlung erfolgt dabei mit der gleichen Rotine, die zur [[relativen Ermittlung von Items|Doku-De-Grundsaetzliches-Relative-Itemangaben]] verwendet wird.

- -

Suspend-Ende in einen Text einsetzen

- -
stateengine_eval.insert_suspend_time(suspend_item_id, suspend_text="Ausgesetzt bis %X")
-    
- -

Das Ende der Suspend-Zeit wird in den Text "suspend_text" eingesetzt. Im Text sind daher entsprechende Platzhalter vorzusehen (Siehe strftime() and strptime() Behavior). Wird kein "suspend_text" angegeben, so wird als Vorgabewert "Ausgesetzt bis %X" verwendet.

- -

Zur Ermittlung des Endes der Suspend-Zeit muss über "suspend_item_id" ein Item angegeben werden, dessen Wert bei Eintritt in den Suspend-Status geändert wird. Über das Alter des Werts in diesem Item wird die bereits abgelaufene Suspend-Zeit bestimmt.

-
-
-{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku11.html b/stateengine/webif/templates/doku11.html deleted file mode 100755 index 5d97895b2..000000000 --- a/stateengine/webif/templates/doku11.html +++ /dev/null @@ -1,88 +0,0 @@ -{% extends "base_plugin.html" %} -{% block scripts %} -{{ super() }} - -{% endblock scripts %} -{% set logo_frame = false %} - - -{% set item_count = p.__items|length %} -{% set tab1title = "StateEngine" %} -{% set tabcount = 1 %} - -{% block headtable %} - - - - - - - - - - - - - - - - - - - - - - - - - -
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
-{% endblock headtable %} - - -{% block bodytab1 %} - -
- -
-

Variablen

- -

Mit dem [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] kann auf Variablen des Plugins zugegriffen werden. Derzeit stehen folgende Variablen zur Verfügung:

- -

item.suspendtime:
- _Die Suspend-Time des Items

- -

current.stateid: - _Die Id des Status, der gerade geprüft wird

- -

current.statename: - _Der Name des Status, der gerade geprüft wird

-
-
-{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku12.html b/stateengine/webif/templates/doku12.html deleted file mode 100755 index 2092bae59..000000000 --- a/stateengine/webif/templates/doku12.html +++ /dev/null @@ -1,121 +0,0 @@ -{% extends "base_plugin.html" %} -{% block scripts %} -{{ super() }} - -{% endblock scripts %} -{% set logo_frame = false %} - - -{% set item_count = p.__items|length %} -{% set tab1title = "StateEngine" %} -{% set tabcount = 1 %} - -{% block headtable %} - - - - - - - - - - - - - - - - - - - - - - - - - -
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
-{% endblock headtable %} - - -{% block bodytab1 %} - -
- -
-

Lock - Sperren der automatischen Zustandsermittlung

- -

Für das Sperren der automatischen Zustandsermittlung führt man ein Sperr-Item ein, dass beispielsweise über einen Taster änderbar ist.

- -

Die Sperre soll aktiv sein, wenn das Sperr-Item den Wert True hat.

- -

Das Sperr-Item

- -

Das Sperritem definiert man wie folgt:

- -
beispiel:
-        lock:
-            item:
-                type: bool
-                name: Sperr-Item
-                visu_acl: rw
-                cache: on
-    
- -

Der Sperrzustand

- -

Der Sperrzustand geht allen anderen Zuständen vor und wird deshalb als erster Zustand definiert.

- -

Zudem muss eine Änderung des Sperr-Items direkt eine Zustandsermittlung auslösen, das Sperr-Item wird daher in die Liste der eval_trigger aufgenommen.

- -

Einstiegsbedingung für den Sperrzustand ist nun einfach, dass das Sperr-Item den Wert True hat. Für das Sperr-Item werden in diesem Beispiel keinerlei Aktionen definiert. Solange also das Sperr-Item aktiv ist, passiert: nichts.

- -
beispiel:
-        lock:
-            rules:
-                # Sperr-Item zu eval_trigger:
-                eval_trigger: <andere Einträge> | beispiel.lock.item
-
-                # Items für Bedingungen und Aktionen
-                se_item_lock: beispiel.lock.item
-
-                lock:
-                    type: foo
-                    name: Manuell gesperrt
-
-                    enter:
-                        se_value_lock: true
-    
- -

Bei der Zustandsermittlung die Reihenfolge der Definition der Zustände relevant. Da der Sperrzustand allen anderen Zuständen vorgeht ist er üblicherweise der erste Zustand in der Definition.

-
-
-{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku13.html b/stateengine/webif/templates/doku13.html deleted file mode 100755 index 82d2047e0..000000000 --- a/stateengine/webif/templates/doku13.html +++ /dev/null @@ -1,304 +0,0 @@ -{% extends "base_plugin.html" %} -{% block scripts %} -{{ super() }} - -{% endblock scripts %} -{% set logo_frame = false %} - - -{% set item_count = p.__items|length %} -{% set tab1title = "StateEngine" %} -{% set tabcount = 1 %} - -{% block headtable %} - - - - - - - - - - - - - - - - - - - - - - - - - -
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
-{% endblock headtable %} - - -{% block bodytab1 %} - -
- -
-

Suspend - Zeitweises Deaktivieren der automatischen Zustandsermittlung nach manuellen Aktionen

- -

Eine besondere Anforderung: Nach bestimmten manuellen Aktionen (z. B. über einen Taster, die Visu, o. ä.) soll die automatische Zustandsermittlung für eine gewisse Zeit ausgesetzt werden. Nach Ablauf dieser Zeit soll die Automatik wieder aktiv werden.

- -

Für dieses Verhalten sind zunächst einige weitere Steueritems erforderlich, dann kann das Verhalten in einem Zustand abgebildet werden.

- -

Das "Suspend"-Item

- -

Zunächst wird ein "Suspend"-Item benötigt. Dieses Item zeigt zum einen die zeitweise Deaktivierung an, außerdem kann die Deaktivierung über dieses Item vorzeitig beendet werden:

- -
beispiel:
-        suspend:
-            suspend:
-                type: bool
-                name: Suspend-Item
-                visu_acl: rw
-    
- -

Das "Manuell"-Item

- -

Ein weiteres Item wird benötigt, um alle Aktionen, die den Suspend-Zustand auslösen sollen, zu kapseln. Dieses Item ist das "Manuell"-Item. - Es wird so angelegt, dass der Wert dieses Items bei jeder manuellen Betätigung invertiert wird:

- -
beispiel:
-        suspend:
-            manuell:
-                type: bool
-                name: Manuelle Bedienung
-                eval_trigger: beispiel.item1 | beispiel.item2 | ...
-                se_manual_invert = true
-    
- -

In das Attribut eval_trigger werden alle Items eingetragen, deren Änderung als manuelle Betätigung gewertet werden soll. Änderungen an diesen Items, die vom stateengine-Plugin selbst vorgenommen wurden, werden dabei automatisch ausgefiltert um Endlosschleifen zu verhindern.

- -

Das Attribut se_manual_invert: true veranlasst das stateengine-Plugin dabei, den Wert des Items bei Änderungen zu invertieren, wie es für das Auslösen des Suspend-Zustands erforderlich ist.

- -

Das Manuell-Item kann noch wesentlich komplexer ausgestaltet werden. Beispielsweise können Änderungen durch bestimmte Ereignisse ausgeschlossen werden. Details hierzu finden sich auf der Seite [[Erweiterte Funktionen des "Manuell"-Items für den Suspend-Zustand|Doku-De-BesondereZustaende-Suspend-Manuell]].

- -

Der Suspend-Zustand

- -

Mit diesen beiden Items kann nun ein einfacher Suspend-Zustand definiert werden. Als Aktion im Suspend-Zustand wird dabei die Sonderaktion "suspend" verwendet. Diese hat zwei Parameter:

- -
se_special_suspend: suspend:<Suspend-Item>,<Manuell-Item>
-    
- -

Der Suspend-Zustand sieht damit wie folgt aus:

- -
suspend:
-        type: foo
-        name: Ausgesetzt
-
-        on_enter_or_stay:
-            type: foo
-            name: Ausführen immer wenn ein Zustand aktiv ist
-
-            # Suspend-Item setzen
-            se_special_suspend: suspend:test.suspend.suspend,test.suspend.manuell
-
-        on_leave:
-            type: foo
-            name: Ausführen beim Verlassen des Zustands
-
-            # Suspend-Item zurücksetzen
-            se_set_suspend: False
-
-       enter_manuell:
-            type: foo
-            name: Bedingung: Suspend beginnen
-
-            #Bedingung: Manuelle Aktion wurde durchgeführt
-            se_value_trigger_source: test.suspend.manuell
-
-        enter_stay:
-            type: foo
-            name: Bedingung: Im Suspend verbleiben
-
-            #Bedingung: Suspend ist aktiv
-            se_value_laststate: var:current.state_id
-
-            #Bedingung: Suspendzeit ist noch nicht abgelaufen
-            se_agemax_manuell: var:item.suspend_time
-
-            #Bedingung: Suspend-Item wurde nicht extern geändert
-            se_value_suspend: True
-    
- -

Bei der Zustandsermittlung die Reihenfolge der Definition der Zustände relevant. Da der Suspend-Zustand anderen Zuständen vorgehen sollte steht er üblicherweise sehr weit vorrne in der Reihenfolge. In der Regel wird der Suspend-Zustand in der Definition der zweite Zustand, nach dem [[Lock-Zustand|Doku-De-BesondereZustaende-Lock]] sein.

- -

Komplettes Beispiel

- -

Baut man die einzelnen Teile zusammen erhält man die folgende Konfiguration.

- -

test: - type: foo

- -
    suspend:
-            type: foo
-            name: stateengine Suspend Beispiel
-
-            suspend:
-                type: bool
-                name: Suspend-Item
-                visu_acl: rw
-
-            manuell:
-                type: bool
-                name: Manuelle Bedienung
-                eval_trigger: beispiel.item1 | beispiel.item2 | ...
-                se_manual_invert: true
-
-            rules:
-                type: bool
-                name: Automatik Test Suspend
-                se_plugin: active
-
-                # Sowohl das Manuell- als auch das Suspend-Item müssen eine Zustandsermittlung auslösen
-                eval_trigger: test.suspend.manuell | test.suspend.suspend
-
-                #Items für Bedingungen und Aktionen zuweisen
-                se_item_suspend: test.suspend.suspend
-                se_item_manuell: test.suspend.manuell
-
-                suspend:
-                    type: foo
-                    name: Ausgesetzt
-
-                    on_enter_or_stay:
-                        type: foo
-                        name :Ausführen immer wenn ein Zustand aktiv ist
-
-                        # Suspend-Item setzen
-                        se_special_suspend: suspend:test.suspend.suspend,test.suspend.manuell
-
-                    on_leave:
-                        type: foo
-                        name: Ausführen beim Verlassen des Zustands
-
-                        # Suspend-Item zurücksetzen
-                        se_set_suspend: False
-
-                    enter_manuell:
-                        type: foo
-                        name: Bedingung: Suspend beginnen
-
-                        #Bedingung: Manuelle Aktion wurde durchgeführt
-                        se_value_trigger_source_ test.suspend.manuell
-
-                    enter_stay:
-                        type: foo
-
-                        name: Bedingung: Im Suspend verbleiben
-
-                        #Bedingung: Suspend ist aktiv
-                        se_value_laststate: var:current.state_id
-
-                        #Bedingung: Suspendzeit ist noch nicht abgelaufen
-                        se_agemax_manuell: var:item.suspend_time
-
-                        #Bedingung: Suspend-Item wurde nicht extern geändert
-                        se_value_suspend: True
-    
- -

Dauer der zeitweisen Deaktivierung

- -

Die Dauer der zeitweisen Deaktivierung wird in der Plugin-Konfiguration über die Einstellung suspend_time_default angegeben. Vorgabewert sind 3600 Sekunden (1 Stunde). - Wenn die Dauer der zeitweisen Deaktivierung für ein einzelnes Objekt-Item abweichend sein soll, kann dort das Attribut

- -
    se_suspend_time: <Sekunden>
-    
- -

angegeben werden.
- Der Parameter verwendet den [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]]

- -

Erweiterte Funktionen des "Manuell"-Items für den Suspend-Zustand

- -

Bestimmte Item-Änderungen nicht als "manuelle Bedienung" auswerte

- -

In bestimmten Fällen ist es erforderlich, das Item-Änderungen, die durch bestimmte Aufrufe ausgelöst werden, nicht als manuelle Betätigung gewertet werden. Hierzu zählt zum Beispiel die Rückmeldung der Raffstore-Position nach dem Verfahren durch den Jalousieaktor. - Hierfür stehen zwei für das Manuell-Item weitere Attribute bereit:

- -

asmanualinclude
- Liste der Aufrufe, die als "manuelle Betätigung" gewertet werden sollen

- -

asmanualexclude
- Liste der Aufrufe, die nicht als "manuelle Betätigung" gewertet werden sollen

- -

Bei beiden Attributen wird eine Liste von Elementen angegeben. Die einzelnen Elemente bestehen dabei aus dem Aufrufenden ("Caller") einem Doppelpunkt und der Quelle ("Source"). Mehrere Elemente werden durch "|" getrennt. Für "Caller" und "Source" kann dabei jeweils auch "*" angegeben werden, dies bedeutet, dass der jeweilige Teil nicht berücksichtigt werd.

- -

Wenn bei der Prüfung festgestellt wird, dass ein Wert über eine Eval-Funktionalität geändert wurde, so wird die Änderung zurückverfolgt bis zur ursprünglichen Änderung, die die Eval-Kette ausgelöst hat. Diese ursprüngliche Änderung wird dann geprüft.

- -

Der Wert von "Caller" zeigt an, welche Funktionalität das Item geändert hat. Der Wert von "Source" ist Abhängig vom Caller. Häufig verwendete "Caller" sind:

- -
    -
  • "Init": Initialisierung von smarthomeNG. "Source" ist in der Regel leer
  • - -
  • "Visu": Änderung über die Visualisierung (Visu-Plugin). "Source" beinhaltet die IP und den Port der Gegenstelle
  • - -
  • "KNX": Änderung über das KNX-Plugin. "Source" ist die physische Adresse des sendenden Geräts
  • -
- -

Wenn se_manual_include oder se_manual_exclude angegeben sind, muss se_manual_invert nicht angegeben werden.

- -
beispiel:
-        suspend:
-            manuell:
-                type: bool
-                name: Manuelle Bedienung
-                eval_trigger: beispiel.item1 | beispiel.item2 | ...
-                se_manual_exclude: KNX:1.1.42 | Init:*
-    
- -

Hier werden alle Änderungen der Items beispiel.item1 und beispiel.item2 als manuelle Betätigung gewertet, sofern Sie nicht durch das KNX-Gerät mit der physischen Adresse 1.1.42 oder durch die Initialisierung von smarthomeNG erfolgt sind.

- -

Erweitertes Logging für das Manuell-Item:

- -

Sofern im Manuell-Item die Attribute se_manual_include bzw. se_manual_exclude verwendet werden, ist auch hier eine Protokollierung mittels des erweiterten Loggings möglich. Dazu muss das Item, unter dem das Log geführt wird über das zusätzliche Attribut se_manual_logitem angegeben werden. Hier wird man als Item in der Regel das Manuell-Item angeben:

- -
beispiel:
-        suspend:
-            manuell:
-                type: bool
-                name: Manuelle Bedienung
-                eval_trigger: beispiel.item1 | beispiel.item2 | ...
-                se_manual_exclude: KNX:1.1.42 | Init:*
-                se_manual_logitem: beispiel.suspend.manuell
-    
- -

Wird statt se_manual_include oder se_manual_exclude nur se_manual_invert verwendet, ist kein erweitertes Logging möglich.

-
-
-{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku14.html b/stateengine/webif/templates/doku14.html deleted file mode 100755 index acf7d2a52..000000000 --- a/stateengine/webif/templates/doku14.html +++ /dev/null @@ -1,85 +0,0 @@ -{% extends "base_plugin.html" %} -{% block scripts %} -{{ super() }} - -{% endblock scripts %} -{% set logo_frame = false %} - - -{% set item_count = p.__items|length %} -{% set tab1title = "StateEngine" %} -{% set tabcount = 1 %} - -{% block headtable %} - - - - - - - - - - - - - - - - - - - - - - - - - -
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
-{% endblock headtable %} - - -{% block bodytab1 %} - -
- -
-

Zusätzliche Kommandos für das CLI Plugin

- -

Sofern die eingesetzte smarthomeNG-Version dies unterstützt, registriert das stateengine-Plugin zwei eigene Kommandos beim CLI-Plugin.

- -

se_list
- Zeigt eine Liste der Objekt-Items, für die das stateengine-Plugin aktiv ist

- -

se_detail <Id eines Objekt-Items>
- Zeigt Details zum Objekt Item

-
-
-{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku15.html b/stateengine/webif/templates/doku15.html deleted file mode 100755 index f51bf04a0..000000000 --- a/stateengine/webif/templates/doku15.html +++ /dev/null @@ -1,687 +0,0 @@ -{% extends "base_plugin.html" %} -{% block scripts %} -{{ super() }} - -{% endblock scripts %} -{% set logo_frame = false %} - - -{% set item_count = p.__items|length %} -{% set tab1title = "StateEngine" %} -{% set tabcount = 1 %} - -{% block headtable %} - - - - - - - - - - - - - - - - - - - - - - - - - -
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
-{% endblock headtable %} - - -{% block bodytab1 %} - -
- -
-

Vollständiges Beispiel

- -

In diesem Beispiel soll die Automatisierung eines Raffstores gezeigt werden. Folgende Zustände sollen abgedeckt werden:

- -
    -
  • Sperre über Sperr-Item
  • - -
  • Zeitweises Deaktivieren ("Suspend") bei manuellen Aktionen
  • - -
  • Nachführen der Lamellen zum Sonnenstand bei großer Helligkeit
  • - -
  • Nacht
  • - -
  • Morgens
  • - -
  • Abends
  • - -
  • Tag
  • -
- -

Dabei sollen möglichst viele Features des stateengine Plugins verwendet werden

- -

Items zum Prüfen

- -

Zuerst benötigen wir ein paar Items, die nachher als Bedingungen abgeprüft werden sollen:

- -
beispiel:
-        steckdosen:
-            type: bool
-
-        licht:
-            type: bool
-
-        wetterstation:
-            helligkeit:
-                name: Helligkeit
-                type: num
-
-                gt43k:
-                    type: bool
-                    name: Flag Helligkeit größer als 43 kLux
-                    eval: sh.beispiel.wetterstation.helligkeit() > 43000
-                    eval_trigger beispiel.wetterstation.helligkeit
-
-                gt35k:
-                    type: bool
-                    name: Flag Helligkeit größer als 35 kLux
-                    eval: sh.beispiel.wetterstation.helligkeit() > 35000
-                    eval_trigger beispiel.wetterstation.helligkeit
-
-                gt25k:
-                    type: bool
-                    name: Flag Helligkeit größer als 25 kLux
-                    eval: sh.beispiel.wetterstation.helligkeit() > 25000
-                    eval_trigger beispiel.wetterstation.helligkeit
-
-                gt20k:
-                    type: bool
-                    name: Flag Helligkeit größer als 20 kLux
-                    eval: sh.beispiel.wetterstation.helligkeit() > 20000
-                    eval_trigger beispiel.wetterstation.helligkeit
-
-            temperatur:
-        name: Temperatur
-        type: num
-    
- -

Trigger

- -

Da wir mehrere Raffstores automatisieren wollen und alle Raffstores gleichzeitig fahren sollen, brauchen wir einen externen Trigger, auf den dann alle Automatiken hören:

- -
beispiel:
-        trigger:
-            raffstore:
-                type: bool
-                name: Gemeinsamer Trigger für alle Raffstores
-                enforce_updates: yes
-                cycle: 300 = 1
-    
- -

In diesem Fall wird die Zustandsermittlung alle 300 Sekunden (5 Minuten) ausgelöst.

- -

Default-Konfiguration

- -

Nun kommt die Default-Konfiguration. Sie ist unabhängig von konkreten zu automatisierenden Objekten. Sie beinhaltet jedoch umfangreiche Einstellungen, so dass die zu automatisierenden Objekte, die die Einstellungen aus der Default-Konfiguration verwenden, oft sehr simpel aufgebaut werden können.

- -
beispiel:
-        default:
-            raffstore:
-                # Item für Helligkeit außen
-                se_item_brightness: beispiel.wetterstation.helligkeit
-                # Item für Temperatur außen
-                se_item_temperature: beispiel.wetterstation.temperatur
-                # Item das anzeigt, ob die Helligkeit außen mehr als 25kLux beträgt
-                se_item_brightnessGt25k: beispiel.wetterstation.helligkeit.gt25k
-                # Item das anzeigt, ob die Helligkeit außen mehr als 43kLux beträgt
-                se_item_brightnessGt43k: beispiel.wetterstation.helligkeit.gt43k
-                # Item für Behanghöhe
-                se_item_hoehe: ...hoehe
-                # Keine Änderung der Behanghöhe wenn Abweichung kleiner 10
-                se_mindelta_hoehe: 10
-                # Item für Lamellenwinkel
-                se_item_lamelle: ...lamelle
-                # Keine Änderung des Lamellenwinkels wenn Abweichung kleiner 5
-                se_mindelta_lamelle: 5
-                # "Manuell" Item
-                se_item_manuell: ..manuell
-                # "Lock" Item
-                se_item_lock: ..lock
-                # "Suspend" Item
-                se_item_suspend: ..suspend
-
-                # Zustand "Sperre über Sperr-Item"
-                Lock:
-                    type: foo
-                    name: Automatik manuell gesperrt
-                    # Aktionen:
-                    # - "Suspend"-Item ggf. zurücksetzen
-                    se_set_suspend: False
-                    # sonst nichts tun
-                    enter
-                        # Einstieg in "Lock": Wenn
-                        # - das "Lock"-Item gesetzt ist
-                        se_value_lock: True
-
-                # Zustand "Zeitweises Deaktivieren bei manuellen Aktionen"
-                Suspend:
-                    type: foo
-                    name: Ausgesetzt
-                    # Namensermittlung über eval-Funktion
-                    se_name: eval:stateengine_eval.insert_suspend_time("..suspend", "Automatik ausgesetzt bis %X")
-                    # Aktionen:
-                    # - "Suspend"-Item setzen
-                    se_set_suspend: True
-                    # sonst nichts tun
-
-                    # Einstieg in "Suspend": Wenn
-                    enter_manuell:
-                        # - die Zustandsermittlung über das "Manuell"-Item ausgelöst wurde
-                        se_value_trigger_source: eval:    stateengine_eval.get_relative_itemid("..manuell")
-
-                    # Verbleib in "Suspend": Wenn
-                    enter_stay:
-                        # - wir bereits in "Suspend" sind
-                        se_value_laststate: var:current.state_id
-                        # - wir weniger 3600 Sekunden im Suspend-Zustand sind
-                        se_agemax_suspend: 3600
-                        # - das "Suspend"-Item nicht von irgendwo anders auf "False" gesetzt wurde
-                        se_value_suspend: True
-
-                # Zustand "Nachführen der Lamellen zum Sonnenstand bei großer Helligkeit", Gebäudeseite 1
-                Nachfuehren_Seite_Eins:
-                    type: foo
-                    name: Tag (nachführen)
-                    # Aktionen:
-                    # - Behang ganz herunterfahren
-                    se_set_hoehe: value:100
-                    # - Lamellen zur Sonne ausrichten
-                    se_set_lamelle: eval:stateengine_eval.sun_tracking()
-                    # - "Suspend"-Item ggf. zurücksetzen
-                    se_set_suspend: False
-
-                    # Einstieg in "Nachführen": Wenn
-                    enter:
-                        # - das Flag "Helligkeit > 43kLux" seit mindestens 60 Sekunden gesetzt ist
-                        se_value_brightnessGt43k: true
-                        se_agemin_brightnessGt43k: 60
-                        # - die Sonnenhöhe mindestens 18° ist
-                        se_min_sun_altitude: 18
-                        # - die Sonne aus Richtung 130° bis 270° kommt
-                        se_min_sun_azimut: 130
-                        se_max_sun_azimut: 270
-                        # - es draußen mindestens 22° hat
-                        se_min_temperature: 22
-
-                    # Hysterese für Helligkeit: Wenn
-                    enter_hysterese:
-                        # ... wir bereits in "Nachführen" sind
-                        se_value_laststate: var:current.state_id
-                        # .... das Flag "Helligkeit > 25kLux" gesetzt ist
-                        se_value_brightnessGt25k: true
-                        # ... die Sonnenhöhe mindestens 18° ist
-                        se_min_sun_altitude: 18
-                        # ... die Sonne aus Richtung 130° bis 270° kommt
-                        se_min_sun_azimut: 130
-                        se_max_sun_azimut: 270
-                        # Anmerkung: Hier keine erneute Prüfung der Temperatur, damit Temperaturschwankungen nicht
-                        # zum Auf-/Abfahren der Raffstores führen
-
-                    # Verzögerter Ausstieg nach Unterschreitung der Mindesthelligkeit: Wenn
-                    enter_delay:
-                        # ... wir bereits in "Nachführen" sind
-                        se_value_laststate: var:current.state_id
-                        # .... das Flag "Helligkeit > 25kLux" nicht (!) gesetzt ist, aber diese Änderung nicht mehr als 20 Minuten her ist
-                        se_value_brightnessGt25k: false
-                        se_agemax_brightnessGt25k: 1200
-                        # ... die Sonnenhöhe mindestens 18° ist
-                        se_min_sun_altitude: 18
-                        # ... die Sonne aus Richtung 130° bis 270° kommt
-                        se_min_sun_azimut: 130
-                        se_max_sun_azimut: 270
-                        # Anmerkung: Auch hier keine erneute Prüfung der Temperatur, damit Temperaturschwankungen nicht
-                        # zum Auf-/Abfahren der Raffstores führen
-
-                # Zustand "Nachführen der Lamellen zum Sonnenstand bei großer Helligkeit", Gebäudeseite 2
-                Nachfuehren_Seite_Zwei:
-                    type: foo
-                    # Einstellungen des Vorgabezustands "Nachfuehren_Seite_Eins" übernehmen
-                    se_use: beispiel.default.raffstore.Nachfuehren_Seite_Eins
-
-                    # Sonnenwinkel in den Bedingungsgruppen anpassen
-                    enter:
-                        # ... die Sonne aus Richtung 220° bis 340° kommt
-                        se_min_sun_azimut: 220
-                        se_max_sun_azimut: 340
-
-                    enter_hysterese:
-                        # ... die Sonne aus Richtung 220° bis 340° kommt
-                        se_min_sun_azimut: 220
-                        se_max_sun_azimut: 340
-
-                    :enter_delay:
-                        # ... die Sonne aus Richtung 220° bis 340° kommt
-                        se_min_sun_azimut: 220
-                        se_max_sun_azimut: 340
-
-                # Zustand "Nacht"
-                Nacht:
-                    type: foo
-                    name: Nacht
-                    # Aktionen:
-                    # - Behang ganz herunterfahren
-                    se_set_hoehe: value:100
-                    # - Lamellen ganz schließen
-                    se_set_lamelle: value:0
-                    # - "Suspend"-Item ggf. zurücksetzen
-                    se_set_suspend: False
-
-                    # Einstieg in "Nacht": Wenn
-                    enter:
-                        # - es zwischen 16:00 und 08:00 Uhr ist
-                        se_min_time: '08:00'
-                        se_max_time: '16:00'
-                        se_negate_time: True
-                        # - die Helligkeit höchstens 90 Lux beträgt
-                        se_max_brightness: 90
-
-                # Zustand "Morgens"
-                Morgens:
-                    type: foo
-                    name: Dämmerung Morgens
-                    # Aktionen:
-                    # - Behang ganz herunterfahren
-                    se_set_hoehe: value:100
-                    # - Lamellen ca 45° nach unten
-                    se_set_lamelle: value:25
-                    # - "Suspend"-Item ggf. zurücksetzen
-                    se_set_suspend: False
-
-                    # Einstieg in "Morgens": Wenn
-                    enter:
-                        # - die Helligkeit zwischen 90 und 250 Lux beträgt
-                        se_min_brightness: 90
-                        se_max_brightness: 250
-                        # - es zwischen 00:00 und 12:00 Uhr ist
-                        se_min_time: '00:00'
-                        se_max_time: '12:00'
-
-                # Zustand "Abends"
-                Abends:
-                    type: foo
-                    name: Dämmerung Abends
-                    # Aktionen:
-                    # - Behang ganz herunterfahren
-                    se_set_hoehe: value:100
-                    # - Lamellen ca 45° nach oben
-                    se_set_lamelle: value:75
-                    # - "Suspend"-Item ggf. zurücksetzen
-                    se_set_suspend: False
-
-                    # Einstieg in "Abends": Wenn
-                    enter:
-                        # - die Helligkeit zwischen 90 und 250 Lux beträgt
-                        se_min_brightness: 90
-                        se_max_brightness: 250
-                        # - es zwischen 12:00 und 24:00 Uhr ist
-                        se_min_time: '12:00'
-                        se_max_time: '24:00'
-                        # Anmerkung: "24:00" ist eigentlich eine ungültige Zeit. Sie wird aber automatisch zu 23:59:59 umgewandelt
-
-                # Zustand "Tag"
-                Tag:
-                    type: foo
-                    name: Tag (statisch)
-                    # Aktionen:
-                    # - Behang ganz hochfahren
-                    se_set_hoehe: value:0
-                    # - Lamellen auf den Standardwert bei ganz hochgefahrenem Behang
-                    se_set_lamelle: value:100
-                    # - "Suspend"-Item ggf. zurücksetzen
-                    se_set_suspend: False
-
-                    # Einstieg in "Tag": Wenn
-                    enter:
-                        # - es zwischen 06:30 und 21:30 Uhr ist
-                        se_min_time: '06:30'
-                        se_max_time: '21:30'
-    
- -

Automatisierung Raffstore 1

- -

Jetzt wollen wir den ersten Raffstore automatisieren. Einige Items dazu haben wir sowieso schon, da der Raffstore über diese Items gesteuert wird.

- -
beispiel:
-        raffstore1:
-            name: Raffstore Beispiel 1
-
-            aufab:
-                type: bool
-                name: Raffstore auf/ab fahren
-                enforce_updates: on
-
-            step:
-                type: bool
-                name: Raffstore Schritt fahren/stoppen
-                enforce_updates: on
-
-            hoehe:
-                type: num
-                name: Behanghöhe des Raffstores
-
-            lamelle:
-                type: num
-                name: Lamellenwinkel des Raffstores
-    
- -

Jetzt kommen noch die Items zur Automatisierung und schließlich das stateengine Objekt-Item hinzu:

- -
beispiel:
-        raffstore1:
-            automatik:
-                lock:
-                    type: bool
-                    name: Sperr-Item
-                    visu_acl: rw
-                    cache: on
-
-                suspend:
-                    type: bool
-                    name: Suspend-Item
-                    visu_acl: rw
-                    # Achtung: Beim "Suspend"-Item niemals "enforce_updates = yes" setzen! Das führt dazu dass das Setzen des
-                    # Suspend-Items bei der Initialisierung zu einem endlosen sofortigen Wiederaufruf der Statusermittlung führt!
-
-                state_id:
-                    type: str
-                    name: Id des aktuellen Zustands
-                    visu_acl: r
-                    cache: on
-
-                state_name:
-                    type: str
-                    name: Name des aktuellen Zustands
-                    visu_acl: r
-                    cache: on
-
-                manuell:
-                    type: bool
-                    name: Manuelle Bedienung
-                    # Änderungen dieser Items sollen als manuelle Bedienung gewertet werden
-                    eval_trigger: beispiel.raffstore1.aufab | beispiel.raffstore1.step | beispiel.raffstore1.hoehe | beispiel.raffstore1.lamelle
-                    # Änderungen, die ursprünglich von diesen Triggern (<caller>:<source>) ausgelöst wurden, sollen nicht als manuelle Bedienung gewertet werden
-                    se_manual_exclude: KNX:y.y.y | Init:*
-
-                rules:
-                    type: bool
-                    name: Automatik Raffstore 1
-                    se_plugin: active
-                    # Erste Zustandsermittlung nach 30 Sekunden
-                    se_startup_delay: 30
-                    # Über diese Items soll die Statusermittlung ausgelöst werden
-                    eval_trigger: beispiel.trigger.raffstore | beispiel.raffstore1.automatik.anwesenheit | beispiel.raffstore1.automatik.manuell | beispiel.raffstore1.automatik.lock | beispiel.raffstore1.automatik.suspend
-                    # In dieses Item soll die Id des aktuellen Zustands geschrieben werden
-                    se_laststate_item_id: ..state_id
-                    # In dieses Item soll der Name des aktuellen Zustands geschrieben werden
-                    se_laststate_item_name: ..state_name
-
-                    Lock:
-                        # Zustand "Lock": Nur die Vorgabeeinstellungen übernehmen
-                        se_use: beispiel.default.raffstore.Lock
-
-                    Suspend:
-                        # Zustand "Suspend": Nur die Vorgabeeinstellungen übernehmen
-                        se_use: beispiel.default.raffstore.Suspend
-
-                    Nachfuehren:
-                        # Zustand "Nachfuehren": Nur die Vorgabeeinstellungen übernehmen (Gebäudeseite 2)
-                        se_use: beispiel.default.raffstore.Nachfuehren_Seite_Zwei
-
-                    Nacht:
-                        # Zustand "Nacht": Nur die Vorgabeeinstellungen übernehmen
-                        se_use: beispiel.default.raffstore.Nacht
-
-                    Morgens:
-                        # Zustand "Morgens": Nur die Vorgabeeinstellungen übernehmen
-                        se_use: beispiel.default.raffstore.Morgens
-
-                    Abends:
-                        # Zustand "Abends": Nur die Vorgabeeinstellungen übernehmen
-                        se_use: beispiel.default.raffstore.Abends
-
-                    Tag:
-                        # Zustand "Tag": Vorgabeeinstellungen übernehmen
-                        se_use: beispiel.default.raffstore.Tag
-    
- -

Automatisierung Raffstore 2

- -

Der zweite Raffstore ist ein komplexeres Beispiel. Hier werden nicht nur die Vorgabewerte übernommen, hier werden komplett neue Bedingungsgruppen definiert, sowie vorhandene Bedingungsgruppen abgeändert.

- -
beispiel:
-        raffstore2:
-            name: Raffstore Beispiel 2
-
-            aufab:
-                type: bool
-                name: Raffstore auf/ab fahren
-                enforce_updates: on
-
-            step:
-                type: bool
-                name: Raffstore Schritt fahren/stoppen
-                enforce_updates: on
-
-            hoehe:
-                type: num
-                name: Behanghöhe des Raffstores
-
-            lamelle:
-                type: num
-                name: Lamellenwinkel des Raffstores
-
-            automatik:
-                lock:
-                    type: bool
-                    name: Sperr-Item
-                    visu_acl: rw
-                    cache: on
-
-                suspend:
-                    type: bool
-                    name: Suspend-Item
-                    visu_acl: rw
-                    # Achtung: Beim "Suspend"-Item niemals "enforce_updates = yes" setzen! Das führt dazu dass das Setzen des
-                    # Suspend-Items bei der Initialisierung zu einem endlosen sofortigen Wiederaufruf der Statusermittlung führt!
-
-                state_id:
-                    type: str
-                    name: Id des aktuellen Zustands
-                    visu_acl: r
-                    cache: on
-
-                state_name:
-                    type: str
-                    name: Name des aktuellen Zustands
-                    visu_acl: r
-                    cache: on
-
-                manuell:
-                    type: bool
-                    name: Manuelle Bedienung
-                    # Änderungen dieser Items sollen als manuelle Bedienung gewertet werden
-                    eval_trigger: beispiel.raffstore2.aufab | beispiel.raffstore2.step | beispiel.raffstore2.hoehe | beispiel.raffstore2.lamelle
-                    # Änderungen, die ursprünglich von diesen Triggern (<caller>:<source>) ausgelöst wurden, sollen nicht als manuelle Bedienung gewertet werden
-                    se_manual_exclude: KNX:y.y.y | Init:*
-
-                anwesenheit:
-                    type: bool
-                    name: Anwesenheit im Raum
-                    eval: or
-                    eval_trigger: beispiel.steckdosen | beispiel.licht
-
-                rules:
-                    type: bool
-                    name: Automatik Raffstore 2
-                    se_plugin: active
-                    # Erste Zustandsermittlung nach 30 Sekunden
-                    se_startup_delay: 30
-                    # Über diese Items soll die Statusermittlung ausgelöst werden
-                    eval_trigger: beispiel.trigger.raffstore | beispiel.raffstore2.automatik.anwesenheit | beispiel.raffstore2.automatik.manuell | beispiel.raffstore2.automatik.lock | beispiel.raffstore2.automatik.suspend
-                    # In dieses Item soll die Id des aktuellen Zustands geschrieben werden
-                    se_laststate_item_id: ..state_id
-                    # In dieses Item soll der Name des aktuellen Zustands geschrieben werden
-                    se_laststate_item_name: ..state_name
-                    # Dieses Item zeigt die Anwesenheit im Raum
-                    se_item_anwesend: ..anwesenheit
-                    # Item das anzeigt, ob die Helligkeit außen mehr als 35kLux beträgt
-                    se_item_brightnessGt35k: beispiel.wetterstation.helligkeit.gt35k
-                    # Item das anzeigt, ob die Helligkeit außen mehr als 20Lux beträgt
-                    se_item_brightnessGt20k: beispiel.wetterstation.helligkeit.gt20k
-
-                    Lock:
-                        # Zustand "Lock": Nur die Vorgabeeinstellungen übernehmen
-                        se_use: beispiel.default.raffstore.Lock
-
-                    Suspend:
-                        # Zustand "Suspend": Nur die Vorgabeeinstellungen übernehmen
-                        se_use: beispiel.default.raffstore.Suspend
-
-                    Nachfuehren:
-                        # Zustand "Nachführen": Vorgabeeinstellungen übernehmen
-                        se_use: beispiel.default.raffstore.Nachfuehren_Seite_Eins
-
-                        # ..und jetzt verändern wir das ganze, in dem wir abhängig vom "Anwesend"-Flag andere
-                        # Grenzwerte für die Helligkeit setzen.
-
-                        # Erst definieren wir mal zusätzliche Einstiegsbedingungen, die die neuen Grenzwerte beinhalten:
-                        :enter_anwesend:
-                            # Einstieg in "Nachführen" bei Anwesenheit: Wenn
-                            # - das Flag "Anwesenheit" gesetzt ist
-                            se_value_anwesend: true
-                            # - das Flag "Helligkeit > 35kLux" seit mindestens 60 Sekunden gesetzt ist (also 8k Lux früher als in "enter")
-                            se_value_brightnessGt35k: true
-                            se_agemin_brightnessGt35k: 60
-                            # - die Sonnenhöhe mindestens 15° ist (also 3° früher als in "enter")
-                            se_min_sun_altitude: 15
-                            # - die Sonne aus Richtung 110° bis 270° kommt (also 20° früher als in "enter"
-                            se_min_sun_azimut: 110
-                            se_max_sun_azimut: 270
-
-                        enter_anwesend_hysterese:
-                            # Hysterese für Helligkeit bei Anwesenheit: Wenn
-                            # - das Flag "Anwesenheit" gesetzt ist
-                            se_value_anwesend: true
-                            # ... wir bereits in "Nachführen" sind
-                            se_value_laststate: var:current.state_id
-                            # .... das Flag "Helligkeit > 20kLux" gesetzt ist (also 5 kLux früher als in "enter_hysterese")
-                            se_value_brightnessGt20k: true
-                            # ... die Sonnenhöhe mindestens 15° ist (Übernahme aus "enter_anwesend")
-                            se_min_sun_altitude: 15
-                            # ... die Sonne aus Richtung 110° bis 270° kommt (Übernahme aus "enter_anwesend")
-                            se_min_sun_azimut: 110
-                            se_max_sun_azimut: 270
-
-                        enter_anwesend_delay:
-                            # Verzögerter Ausstieg nach Unterschreitung der Mindesthelligkeit bei Anwesenheit: Wenn
-                            # - das Flag "Anwesenheit" gesetzt ist
-                            se_value_anwesend: true
-                            # ... wir bereits in "Nachführen" sind
-                            se_value_laststate: var:current.state_id
-                            # .... das Flag "Helligkeit > 20kLux" nicht (!) gesetzt ist, aber diese Änderung nicht mehr als 20 Minuten her ist
-                            se_value_brightnessGt20k: false
-                            se_agemax_brightnessGt20k: 1200
-                            # ... die Sonnenhöhe mindestens 15° ist (Übernahme aus "enter_anwesend")
-                            se_min_sun_altitude: 15
-                            # ... die Sonne aus Richtung 110° bis 270° kommt (Übernahme aus "enter_anwesend")
-                            se_min_sun_azimut: 110
-                            se_max_sun_azimut: 270
-
-                        # Jetzt müssen wir die vorhandenen Bedingungen noch erweitern (sie gelten ja nur noch, wenn "Anwesenheit" nicht gesetzt ist)
-                        enter:
-                            # Einstieg in "Nachführen": Wenn zusätzlich
-                            # - das Flag "Anwesenheit" nicht gesetzt ist
-                            se_value_anwesend: false
-
-                        enter_hysterese:
-                            # Hysterese für Helligkeit: Wenn zusätzlich
-                            # - das Flag "Anwesenheit" nicht gesetzt ist
-                            se_value_anwesend: false
-
-                        enter_delay:
-                            # Verzögerter Ausstieg nach Unterschreitung der Mindesthelligkeit:  Wenn zusätzlich
-                            # - das Flag "Anwesenheit" nicht gesetzt ist
-                            se_value_anwesend: false
-
-                    Nacht:
-                        # Zustand "Nacht": Vorgabeeinstellungen übernehmen
-                        se_use: beispiel.default.raffstore.Nacht
-                        # .. und zwei weitere Einstiegsbedingungen definieren
-
-                        enter_schlafenszeit_woche:
-                            # Einstieg in "Nacht": Wenn
-                            # - es zwischen 21:00 und 07:00 Uhr ist
-                            se_min_time: '07:00'
-                            se_max_time: '21:00'
-                            se_negate_time: True
-                            # - der Wochentag zwischen Montag und Freitag liegt
-                            se_min_weekday: 0
-                            se_max_weekday: 4
-
-                        enter_schlafenszeit_wochenende:
-                            # Einstieg in "Nacht": Wenn
-                            # - es zwischen 21:00 und 08:30 Uhr ist
-                            se_min_time: '08:30'
-                            se_max_time: '21:00'
-                            se_negate_time: True
-                            # - der Wochentag Samstag oder Sonntag ist
-                            se_value_weekday: 5 | 6
-
-                    Morgens:
-                        # Zustand "Morgens": Nur die Vorgabeeinstellungen übernehmen
-                        se_use: beispiel.default.raffstore.Morgens
-
-                    Abends:
-                        # Zustand "Abends": Nur die Vorgabeeinstellungen übernehmen
-                        se_use: beispiel.default.raffstore.Abends
-
-                    Tag:
-                        # Zustand "Tag": Vorgabeeinstellungen übernehmen
-                        se_use: beispiel.default.raffstore.Tag
-    
-
-
-{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku2.html b/stateengine/webif/templates/doku2.html deleted file mode 100755 index 6d70cc4df..000000000 --- a/stateengine/webif/templates/doku2.html +++ /dev/null @@ -1,132 +0,0 @@ -{% extends "base_plugin.html" %} -{% block scripts %} -{{ super() }} - -{% endblock scripts %} -{% set logo_frame = false %} - - -{% set item_count = p.__items|length %} -{% set tab1title = "StateEngine" %} -{% set tabcount = 1 %} - -{% block headtable %} - - - - - - - - - - - - - - - - - - - - - - - - - -
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
-{% endblock headtable %} - - -{% block bodytab1 %} - -
- -
-

Konfiguration des Plugins

- -

Um das StateEngine Plugin zu verwenden müssen die folgenden Zeilen in die plugin.yaml Datei der smarthomeNG Installation eingetragen werden.

- -
stateengine:
-        class_name: StateEngine
-        class_path: plugins.stateengine
-        #startup_delay_default: 10
-        #suspend_time_default: 3600
-        #log_level: 0
-        #log_directory: var/log/StateEngine/
-        #log_maxage: 0
-    
- -

Auskommentierte Attribute sind Vorgabewerte, die nach den eigenen Bedürfnissen angepasst werden können.

- -

startup_delay_default (optional):
- Vorgabewert für die Startverzögerung der ersten Zustandsermittlung beim Start von smarthomeNG

- -

Beim Starten von smarthomeNG dauert es üblicherweise einige Sekunden, bis alle Items initialisiert sind. Um zu verhindern, dass die erste Zustandsermittlung stattfindet, bevor alle Items ihren Initialwert haben, wird die erste Zustandsermittlung verzögert. Die Dauer der Verzögerung kann bei den Objekt-Items angegeben werden. Wenn bei einem Objekt-Item kein Wert angegeben ist, wird der hier angegebene Standardwert verwendet. Wenn kein abweichender Standardwert in der Plugin-Konfiguration angegeben ist, ist der Vorgabewert 10 Sekunden.

- -

Folgende Werte sind möglich:

- -

Zahl größer 0:
- Angabe der Startverzögerung in Sekunden. Während der Startverzögerung sind die Auslöser der Zustandsermittlung inaktiv. Sie werden erst nach Ablauf der Startverzögerung und der ersten Zustandsermittlung aktiviert.

- -

0:
- Keine Startverzögerung. Die erste Zustandsermittlung wird direkt nach der Initialisierung des Objekt-Items durchgeführt. Anschließend werden die Auslöser für die Zustandsermittung aktiviert.

- -

-1:
- Es wird keine erste Zustandsermittlung durchgeführt. Nach der Initialisierung des Objekt-Items sind alle Auslöser für die Zustandsermittlung aktiv.

- -

suspend_time_default (optional):
- Vorgabezeit zur Unterbrechung der automatischen Steuerung nach manuellen Aktionen

- -

Nach manuellen Aktionen kann die Automatik für eine bestimmte Zeit Unterbrochen werden. Die Dauer dieser Unterbrechungen kann bei den Objekt-Items angegeben werden. Die Einheit für den Wert sind Sekunden. Wenn bei einem Objekt-Item kein Wert angegeben ist, wird der hier angegebene Standardwert verwendet. Wenn kein abweichender Standardwert in der Plugin-Konfiguration angegeben ist, ist der Vorgabewert 3600 Sekunden (1 Stunde)

- -

log_level(optional):
- _Erweiterte Protokollierung: Loglevel (0: aus, 1: Info, 2: Debug

- -

Die erweiterte Protokollierung wird über das Setzen des Loglevels auf 1 (Info) oder 2 (Debug) aktiviert. Wenn der Parameter nicht angegeben ist, ist die erweiterte Protokollierung deaktiviert.

- -

log_directory (optional):
- _Erweiterte Protokollierung: Verzeichnis für die Protokolldateien

- -

Die Logdateien der erweiterten Protokollierung werden in das hier angegebene Verzeichnis geschrieben.
- Wenn der angegebene Verzeichnisname mit "/" beginnt wird er als absoluter Verzeichnisname behandelt. Alle anderen Verzeichnisnamen werden als Unterverzeichnisse des smarthomeNG Basisverzeichnisses behandelt. - Das angegebene Verzeichnis wird angelegt, wenn es nicht existiert.
- Wenn hier kein abweichendes Verzeichnis angegeben ist, wird das Verzeichnis <smarthome_base_directory>/var/log/AutoState/ verwendet.

- -

log_maxage (optional):
- _Erweiterte Protokollierung: Anzahl der Tage, nach der die Dateien im Verzeichnis "log_directory" wieder gelöscht werden sollen

- -

Alte Protokolldateien können nach einer bestimmten Zeit automatisch gelöscht werden. Diesen Parameter wird die Anzahl der Tage festgelegt, nachdem die Dateien gelöscht werden sollen. Das Löschen ist ausgesetzt solange der Parameter den Wert 0 hat. Wenn der Parameter auf einen anderen Wert gesetzt wird, wird das Alter der Dateien im Protokollverzeichnis "log_directory" täglich geprüft und überalterte Dateien werden gelöscht.
- Wichtig: Die Löschfunktionalität prüft und löscht alle Dateien im Protokollverzeichnis, ob sie Protokolldateien sind oder nicht. Daher sollten keine anderen Dateien in diesem Verzeichnis abgelegt werden!

- -
-
-{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku3.html b/stateengine/webif/templates/doku3.html deleted file mode 100755 index d8a34ddc5..000000000 --- a/stateengine/webif/templates/doku3.html +++ /dev/null @@ -1,203 +0,0 @@ -{% extends "base_plugin.html" %} -{% block scripts %} -{{ super() }} - -{% endblock scripts %} -{% set logo_frame = false %} - - -{% set item_count = p.__items|length %} -{% set tab1title = "StateEngine" %} -{% set tabcount = 1 %} - -{% block headtable %} - - - - - - - - - - - - - - - - - - - - - - - - - -
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
-{% endblock headtable %} - - -{% block bodytab1 %} - -
- -
-

Die Grundkonfiguration für eine Automatik: Das Objekt-Item

- -

Für jedes Objekt, dass mit dem StateEngine Plugin gesteuert werden soll, ist ein Item erforderlich, dass alle Konfigurationsdaten für dieses Objekt enthält. Dieses Item wird aus "Objekt-Item" bezeichnet. - Es können beliebig viele Objekt-Items und damit beliebig viele Automatiken angelegt werden.

- -

Grundlegende Einstellungen

- -

Über die folgenden Attribute werden die grundlegenden Einstellungen für eine Automatik festgelegt

- -
beispiel:
-        raffstore1:
-            automatik:
-                rules:
-                    type: bool
-                    name: Automatik Raffstore 1
-                    se_plugin: active
-                    se_startup_delay: 30
-                    se_laststate_item_id: beispiel.raffstore1.automatik.state_id
-                    se_laststate_item_name: beispiel.raffstore1.automatik.state_name
-                    se_repeat_actions: true
-                    se_suspend_time: 7200
-    
- -

type (obligatorisch):
- Datentp des Items

- -

Für das Objekt-Item muss immer der Datentyp "bool" verwendet werden

- -

name (optional):
- Name des Items

- -

Wenn das Attribut nicht angegeben ist, wird die Id des Items als Name verwendet.

- -

se_plugin (obligatorisch):
- _Kennzeichnet das Item als Objekt-Item des StateEngine-Plugins

- -

Der Wert dieses Attributs muss zwingend "active" sein, damit das Plugin das Item berücksichtigt. Zu Debuggingzwecken kann der Wert dieses Attributs auf einen anderen Wert geändert werden, dadurch wird das Plugin das Objekt ignorieren.

- -

se_startupdelay (optional):
- Startverzögerung der ersten Zustandsermittlung beim Start von smarthomeNG

- -

Beim Starten von smarthomeNG dauert es üblicherweise einige Sekunden, bis alle Items initialisiert sind. Um zu verhindern, dass die erste Zustandsermittlung stattfindet, bevor alle Items ihren Initialwert haben, wird die erste Zustandsermittlung verzögert. Erst nach der ersten Zustandsermittlung werden alle Auslöser und Funktionen vollständig aktiviert. Zustandsermittlungen, die durch Items oder Timer vor Ablauf der Startverzögerung ausgelöst werden, werden nicht durchgeführt. - Die zulässigen Werte für "se_startup_delay" sind identisch mit den zulässigen Werten für den Plugin-Parameter "startup_delay_default".
- Der Parameter verwendet den [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]]

- -

se_laststateitemid (optional):
- _Id des Items, in dem die Id des aktuellen Zustands abgelegt wird

- -

In das hier angegebene Item wird die Id des aktuellen Zustands abgelegt. Das Item kann mit dem Attribut "cache = yes" versehen werden, dann bleibt der vorherige Zustand bei einem Neustart von smarthomeNG erhalten. Wenn das Item "se_laststate_item_id" nicht angegeben ist, wird der aktuelle Zustand nur im Plugin gespeichert und geht mit einem Neustart von smarthomeNG verloren.

- -

Sofern verwendet, sollte das Item für "se_laststate_item_id" wie folgt definiert werden

- -
beispiel:
-        raffstore1:
-            automatik:
-                state_id:
-                    type: str
-                    name: Id des aktuellen Zustands
-                    visu_acl: r
-                    cache: yes
-    
- -

se_laststateitemname (optional):
- _Id des Items, in dem der Name des aktuellen Zustands abgelegt wird

- -

In das hier angegebene Item wird der Name des aktuellen Zustands abgelegt. Das Item kann für Displayzwecke verwendet werden. Wenn das Item "se_laststate_item_name" nicht angegeben ist, steht der Name des aktuellen Zustands nicht zur Verfügung

- -

Sofern verwendet, sollte das Item für "se_laststate_item_name" wie folgt definiert werden

- -
beispiel:
-        raffstore1:
-            automatik:
-                state_name:
-                    type: str
-                    name: Name des aktuellen Zustands
-                    visu_acl: r
-                    cache: yes
-    
- -

se_repeatactions (optional):
- Wiederholen der Aktionen bei unverändertem Zustand

- -

Im Normalfall werden Aktionen jedesmal ausgeführt wenn der aktuelle Zustand neu ermittelt wurde. Dies ist unabhängig davon, ob sich der Zustand bei der Neuermittlung geändert hat oder nicht. - Dieses Verhalten kann über die Angabe von "se_repeat_actions = false" umgestellt werden. Wenn das Attribut auf "false" gesetzt ist, werden Aktionen nur ausgeführt, wenn sich der Zustand tatsächlich geändert hat. - Der Parameter verwendet den [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]]

- -

se_suspendtime (optional):
- Zeit zur Unterbrechung der automatischen Steuerung nach manuellen Aktionen

- -

Nach manuellen Aktionen kann die Automatik für eine bestimmte Zeit Unterbrochen werden. Die Dauer dieser Unterbrechungen wird hier angegeben. Die Einheit für den Wert sind Sekunden. Wenn bei einem Objekt-Item kein Wert angegeben ist, wird der in der Pluginkonfiguration angegebene Standardwert (suspendtimedefault) verwendet. - Der Parameter verwendet den [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]]

- -

Einstellungen zum Auslösen der Zustandsermittlung

- -

Eine Neuermittlung des aktuellen Zustands wird jedesmal durchgeführt, wenn ein Wert für das Objekt-Item geschrieben wird. Somit können die Standardmöglichkeiten von smarthomeNG wie "cycle", "crontab" und "eval_trigger" verwendet werden, um die Neuermittlung des aktuellen Zustands auszulösen.

- -
beispiel:
-        rafffstore2:
-            automatik:
-                rules:
-                    <...>
-                    cycle: 300
-                    crontab: 0 5 * * | 0 6 * *
-                    eval_trigger: beispiel.trigger.raffstore | beispiel.raffstore2.automatik.anwesenheit
-    
- -

Details zu diesen Attributen können der smarthomeNG Dokumentation entnommen werden.

- -

Um die Konfiguration einfach zu halten, verändert das Plugin einige Einstellungen des Objekt-Items. - Folgende Erleichterungen werden dabei vorgenommen:

- -
    -
  • Es ist nicht erforderlich mit "cycle" bzw. "crontab" Werte anzugeben. Das StateEngine Plugin ergänzt diese automatisch, sofern erforderlich. Statt "cycle = 300=1" ist es ausreichend, wenn man "cycle = 300" angibt.

  • - -
  • Es ist nicht erforderlich das Attribut "eval = (irgendwas)" anzugeben, wenn "eval_trigger" verwendet wird. Das StateEngine plugin ergänzt dies automatisch, sofern erforderlich.

  • - -
  • "crontab = init" funktioniert nicht für das StateEngine Plugin. Die Neuberechnung des ersten Zustands nach dem Start von smarthomeNG wird über das Attribut "se_startup_delay" gesteuert.

  • -
- -

Es ist auch möglich andere Wege zu verwenden, um den Wert des Objekt-Items zu setzen:

- -
    -
  • Zuweisung einer hörenden KNX Gruppenadresse zum Objekt-Item und Senden eines Wertes auf diese Gruppenadresse.

  • - -
  • Setzen des Werts des Objekt-Items aus einer Logik, einer anderen Automatik oder sogar aus der selben Automatik (ggf. mit Verzögerung).

  • -
- -
-
-{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku4.html b/stateengine/webif/templates/doku4.html deleted file mode 100755 index b6a371bac..000000000 --- a/stateengine/webif/templates/doku4.html +++ /dev/null @@ -1,185 +0,0 @@ -{% extends "base_plugin.html" %} -{% block scripts %} -{{ super() }} - -{% endblock scripts %} -{% set logo_frame = false %} - - -{% set item_count = p.__items|length %} -{% set tab1title = "StateEngine" %} -{% set tabcount = 1 %} - -{% block headtable %} - - - - - - - - - - - - - - - - - - - - - - - - - -
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
-{% endblock headtable %} - - -{% block bodytab1 %} - -
- -
-

Zustände: Das Zustands-Item

- -

Alle Items unterhalb des Objekt-Items beschreiben Zustände des Objekts ("Zustands-Item"). Die Ids der Zustands-Items sind beliebig. Sie werden als Werte für das über "se_laststate_item_id" angegebene Item verwendet um den aktuellen Zustand abzulegen.

- -
beispiel:
-        raffstore1:
-            automatik:
-                rules:
-                    Tag:
-                        type: foo
-                        name: Tag
-                        se_name: eval: sh.eine_funktion()
-    
- -

type (obligatorisch):
- Datentp des Items

- -

Für das Zustands-Item muss immer der Datentyp "foo" verwendet werden

- -

name (optional):
- Name des Zustands

- -

Der Name des Zustands wird im Protokoll sowie als Wert für das über "se_laststate_item_name" angegebene Item verwendet. Wenn kein Name angegeben ist, wird hier ebenfalls die Id des Zustands-Items verwendet.

- -

se_name (optional):
- _Ermittlung des Namens des Zustands

- -

Über das Attribut "se_name" kann der im Attribut "name" überschrieben werden. Dies wirkt sich jedoch nur auf den Wert aus, der in das über "se_laststate_item_name" angegebene Item geschrieben wird. Im Protokoll wird immer der über das Attribut "name" angegebene Wert verwendet.
- Der Parameter verwendet den [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]]

- -

Bedingungsgruppen

- -

Jeder Zustand kann eine beliebige Anzahl von Bedingungsgruppen haben. Jede Bedingungsgruppe definiert ein Set an Bedingungen das überprüft wird, wenn der aktuelle Status neu ermittelt wird. Sobald die Bedingungen einer Bedingungsgruppe vollständig erfüllt sind, kann der Status aktiv werden.

- -

Jede Bedingungsgruppe wird durch ein Item ("Bedingungsgruppen-Item") unterhalb des Zustands-Items abgebildet. Eine Bedingungsgruppe kann beliebig viele Bedingungen umfassen. Bedingungen werden als Attribute im Bedingungsgruppen-Item definiert. Details zu den Bedingungen werden im Abschnitt [[Bedingungen|Doku-De-Bedingungen]] erläutert.

- -

Die folgenden Regeln kommen zur Anwendung:

- -
    -
  • Zustände und Bedingungsgruppen werden in der Reihenfolge geprüft, in der sie in der Konfigurationsdatei definiert sind.

  • - -
  • Eine einzelne Bedingungsgruppe ist erfüllt, wenn alle Bedingungen, die in der Bedingungsgruppe definiert sind, erfüllt sind (UND-Verknüpfung). Einschränkungen, die in der Bedingungsgruppe nicht definiert sind, werden nicht geprüft.

  • - -
  • Ein Zustand kann aktueller Zustand werden, wenn eine beliebige der definierten Bedingungsgruppen des Zustands erfüllt ist. Die Prüfung ist mit der ersten erfüllten Bedingungsgruppe beendet (ODER-Verknüpfung).

  • - -
  • Ein Zustand der keine Bedingungsgruppen hat kann immer aktueller Zustand werden. Solch ein Zustand kann als Default-Zustand am Ende der Zustände definiert werden.

  • -
- -

Aktionen

- -

Jeder Zustand kann eine beliebige Anzahl an Aktionen definieren. Sobald ein Zustand aktueller Zustand wird werden die Aktionen des Zustands ausgeführt. - Für die Aktionen gibt es vier Ereignisse, die festlegen, wann eine Aktion ausgeführt wird:

- -
    -
  • on_enter: Aktionen, die beim erstmaligen Aktivieren des Zustands ausgeführt werden

  • - -
  • on_stay: Aktionen, die ausgeführt werden, wenn der Zustand zuvor bereits aktiv war und weiterhin aktiv bleibt.

  • - -
  • on_enteror_stay: Aktionen, die ausgeführt werden, wenn der Zustand aktiv ist, unabhängig davon, ob er bereits zuvor aktiv war oder nicht.

  • - -
  • on_leave: Aktionen, die ausgeführt werden, direkt bevor ein anderer Zustand aktiv wird.

    - -

    Details zu den Aktionen werden im Abschnitt [[Aktionen|Doku-De-Aktionen]] erläutert.

  • -
- -

Items

- -

Bedingungen und Aktionen beziehen sich überlicherweise auf Items. Diese Items müssen auf Ebene des Objekt-Items über das Attribut "se_item_<Bedingungsname/Aktionsname>" bekannt gemacht werden.

- -

Beispiel

- -
beispiel:
-        raffstore1:
-            automatik:
-                rules:
-                    <Allgemeine Objektkonfiguration>
-
-                    Tag:
-                        type: foo
-                        name: Tag
-                        <Aktionen bei Zustand "Tag">
-                        enter:
-                            <Bedingungen>
-                    Nacht:
-                        type: foo
-                        name: Nacht
-                        <Aktionen bei Zustand "Nacht">
-                        enter_todark:
-                            <Bedingungen um den Zustand anzusteuern, wenn es zu dunkel ist>
-                        enter_tolate:
-                            <Bedingungen um den Zustand anzusteuern, wenn es zu spät ist>
-    
- -

Attribute "se_item_height" und "se_item_lamella":
- Definition der Items, die durch die Aktionen "se_set_height" und "se_set_lamella" verändert werden

- -

Die Items werden durch ihre Item-Id angegeben

- -

Attribut "name":
- Name des Zustands

- -

Der Name wird in das über "se_laststate_item_name" definierte Item geschrieben, wenn der Zustand aktueller Zustand wird. Dieser Wert kann z. B. in einer Visualisierung dargestellt werden.

- -

Attribute "se_set_height" und "se_set_leave":
- Neue statische Werte für die Items die über "se_item_height" und "se_item_leave" festgelegt wurden

- -

Untergeordnete Items "enter", "enter_todark" und "enter_tolate":
- Bedingungsgruppen die erfüllt sein müssen, damit ein Zustand aktueller Zustand werden kann

- -
-
-{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku5.html b/stateengine/webif/templates/doku5.html deleted file mode 100755 index 531bf3686..000000000 --- a/stateengine/webif/templates/doku5.html +++ /dev/null @@ -1,266 +0,0 @@ -{% extends "base_plugin.html" %} -{% block scripts %} -{{ super() }} - -{% endblock scripts %} -{% set logo_frame = false %} - - -{% set item_count = p.__items|length %} -{% set tab1title = "StateEngine" %} -{% set tabcount = 1 %} - -{% block headtable %} - - - - - - - - - - - - - - - - - - - - - - - - - -
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
-{% endblock headtable %} - - -{% block bodytab1 %} - -
- -
-

Bedingungen

- -

Jede Bedingung erfordert drei Dinge:

- -
    -
  • Einen Namen der die Bedingung und die zugehörigen Elemente identifiziert
  • - -
  • Grenzwerte um zu prüfen, ob die Bedingung erfüllt ist
  • - -
  • Eine Möglichkeit den aktuellen Wert zu ermitteln, gegen den die Grenzwerte geprüft werden
  • -
- -

Name der Bedingung

- -

Der Name der Bedingung ist beliebig und wird lediglich zur Benennung der Attribute verwendet. Die Namen aller Attribute, die zu einer Bedingung gehören, folgen dem Muster "se_<Funktion>_<Bedingungsname>". Es gibt verschiedene "besondere" Bedingungsnamen, die später erläutert werden.

- -

Grenzwerte

- -

Die Grenzwerte einer Bedingung werden in den Bedingungsgruppen definiert. Die folgenden Grenzwerte sind möglich:

- -

Minimum

- -
    se_min_<Bedingungsname>: [Wert]
-    
- -

Die Bedingung ist erfüllt, wenn der aktuelle Wert großer als das angegebene Minimum ist. - Fur das Attribut wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet.

- -

Maximum

- -
    se_max_<Bedingungsname>: [Wert]
-    
- -

Die Bedingung ist erfüllt, wenn der aktuelle Wert kleiner als das angegebene Maximum ist. - Fur das Attribut wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet.

- -

Bestimmter Wert

- -
    se_value_<Bedingungsname>: [Wert]
-    
- -

Die Bedingung ist erfüllt, wenn der aktuelle Wert gleich dem angegebenen Wert ist. - Fur das Attribut wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet.

- -

Für den Fall, dass der Wert aus Festwerten stammt ("[Wert]" ist "value: [Festwert]") kann auch eine Wertliste angegeben werden:

- -
    se_value_<Bedingungsname>: value:[Wert1]|[Wert2]|(...)[WertN]
-    
- -

In diesem Fall ist die Bedingung erfüllt, wenn der aktuelle Wert in der Wertliste enthalten ist.

- -

Negieren

- -
    se_negate_<Bedingungsname>: True|False
-    
- -

Die gesamte Bedingung (Minimum, Maximum und Wert) wird negiert (umgekehrt). - Für das Attribut wird der Datentyp Boolean verwendet, zulässige Werte sind "true", "1", "yes", "on" bzw. "false", "0", "no", "off"

- -

Mindestalter

- -
    se_agemin_<Bedingungsname>: [Wert]
-    
- -

Die Bedingung ist erfüllt, wenn das Alter des Items, dass zur Ermittlung des Werts angegeben ist, größer als das angegebene Mindestalter ist. - Fur das Attribut wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet.

- -

Höchstalter

- -
    se_agemax_<Bedingungsname>: [Wert]
-    
- -

Die Bedingung ist erfüllt, wenn das Alter des Items, dass zur Ermittlung des Werts angegeben ist, kleiner als das angegebene Höchstalter ist. - Fur das Attribut wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet.

- -

Altersbedingung negieren

- -
    se_agenegate_<Bedingungsname>: True|False
-    
- -

Die Altersbedingung (Mindestalter, Höchstalter) wird negiert (umgekehrt). - Fur das Attribut wird der Datentyp Boolean verwendet, zulässige Werte sind "true", "1", "yes", "on" bzw. "false", "0", "no", "off"

- -

Bereitstellung des aktuellen Werts

- -

Der aktuelle Wert kann entweder über ein Item oder über eine Eval-Funktion bereitgestellt werden. Wenn beides angegeben ist wird das Item verwendet und die Eval-Funktion ignoriert.

- -

Der Name des Items, über das der aktuelle Wert abgerufen werden soll, wird auf Ebene des Objekt-Items über das Attribut "se_item_<Bedingungsname>" angegeben. - Die Eval-Funktion, über die der aktuelle Wert abgerufen werden soll, wird auf Ebene des Objekt-Items über das Attribut "se_eval_<Bedingungsname>'" angegeben. Der Bedingungsname in "se_item" bzw. "se_eval'" muss mit den Bedingungsnamen in den Bedingungen korrespondieren.

- -

Das sich Altersbedingungen auf das Alter der hinterlegten Items beziehen können "se_agemin_<Bedingungsname>", "se_agemax_<Bedingungsname>" und "se_agenegate_<Bedingungsname>" nur verwendet werden, wenn der aktuelle Wert über ein Item bereitgestellt wird.

- -

Beispiel

- -
beispiel:
-        raffstore1:
-            automatik:
-                rules:
-                    <...>
-                    se_item_height: beispiel.raffstore1.hoehe
-                    se_item_lamella: beispiel.raffstore1.lamelle
-                    se_item_brightness: beispiel.wetterstation.helligkeit
-                    Daemmerung:
-                        type: foo
-                        name: Dämmerung
-                        <Aktionen>
-                        enter:
-                            se_min_brightness: 500
-                            se_max_brightness: value:1000
-
-                    Nacht:
-                        type: foo
-                        name: Nacht
-                        <Aktionen>
-                        enter_todark:
-                            se_max_brightness: 500
-
-                    Sonder:
-                        type: foo
-                        name: Ein spezielles Bedingungsset
-                        <Aktionen>
-                        enter:
-                            se_min_brightness: item:test.wert
-                            se_max_brightness: eval:sh.test.wert() + 500
-    
- -

"Besondere" Bedingungen

- -

Das Plugin stellt die Werte für einige "besondere" Bedingungen automatisch bereit. Für diese Bedingungen muss daher kein Item und keine Eval-Funktion zur Ermittlung des aktuellen Werts angegeben werden. - Die "besonderen" Bedingungen werden über reservierte Bedingungsnamen gekennzeichnet. Diese Bedingungsnamen dürfen daher nicht für andere Bedingungen verwendet werden.

- -

Die folgenden "besonderen" Bedingungsnamen können verwendet werden

- -

time

- -

Aktuelle Uhreit

- -

Die Werte für "se_value_time", "se_min_time" und "se_max_time" müssen im Format "hh:mm" (":") angegeben werden. Es wird ein 24 Stunden-Zeitformat verwendet. Beispiele: "08:00" oder "13:37". Um das Ende des Tages anzugeben kann der Wert "24:00" verwendet werden, der für die Prüfungen automatisch zu "23:59:59" konvertiert wird.

- -

weekday

- -

Wochentag

- -

0 = Montag, 1 = Dienstag, 2 = Mittwoch, 3 = Donnerstag, 4 = Freitag, 5 = Samstag, 6 = Sonntag

- -

month

- -

_Monat | 1 = Januar, ..., 12 = Dezember

- -

sun_azimut

- -

Sonnenstand (Horizontalwinkel)

- -

Der Azimut (Horizontalwinkel) ist die Kompasrichtung in der die Sonne steht. Der Azimut wird von smarthomeNg auf Basis der aktuellen Zeit sowie der konfigurierten geographischen Position berechnet. Siehe auch SmarthomeNg Dokumentation für Voraussetzungen zur Berechnung der Sonnenposition. Beispielwerte: 0 → Sonne exakt im Norden, 90 → Sonne exakt im Osten, 180 → Sonne exakt im Süden, 270 → Sonne exakt im Westen

- -

sun_altitude

- -

Sonnenstand (Vertikalwinkel)

- -

Die Altitude (Vertikalwikel) ist der Winkel, in dem die Sonne über dem Horizont steht. Die Altitude wird von smarthomeNg auf Basis der aktuellen Zeit sowie der konfigurierten geographischen Position berechnet. Siehe auch SmarthomeNG Dokumentation für Voraussetzungen zur Berechnung der Sonnenposition. Werte: negativ → Sonne unterhalb des Horizonts, 0 → Sonnenaufgang/Sonnenuntergang, 90 → Sonne exakt im Zenith (passiert nur in äquatorialen Bereichen)

- -

age

- -

Zeit seit der letzten Änderung des Zustands (Sekunden)

- -

Das Alter wird über die letzte Änderung des Items, dass als se_laststate_item_id angegeben ist, ermittelt.

- -

random

- -

Zufallszahl zwischen 0 und 100

- -

Wenn etwas zufällig mit einer Wahrscheinlichkeit von 60% passieren soll, kan beispielsweise die Bedingung max_random = 60 verwendet werden.

- -

laststate

- -

Id des Zustandsitems des aktuellen Status

- -

Wichtig: Hier muss die vollständige Item-Id angegeben werden

- -

trigger_item, trigger_caller, trigger_source, trigger_dest

- -

item, caller, source und dest-Werte durch die die Zustandsermittlung direkt ausgelöst wurde

- -

Über diese vier Bedingungen kann der direkte Auslöser der Zustandsermittlung abgeprüft werden, also die Änderung, die smarthomeNG veranlasst, die Zustandsermittlung des stateengine-Plugins aufzurufen.

- -

original_item, original_caller, original_source

- -

item, caller, source und dest-Werte durch die die Zustandsermittlung ursprünglich ausgelöst wurde

- -

Über diese vier Bedingungen kann der ursprüngliche Auslöser der Zustandsermittlung abgeprüft werden. Beim Aufruf der Zustandsermittung über einen "eval_trigger" Eintrag wird über "trigger_caller" beispielsweise nur "Eval" weitergegeben. In den drei "original_*" Bedingungen wird in diesem Fall der Auslöser der Änderung zurückverfolgt und der Einstieg in die "Eval"-Kette ermittelt.

-
-
-{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku6.html b/stateengine/webif/templates/doku6.html deleted file mode 100755 index b0bbb501f..000000000 --- a/stateengine/webif/templates/doku6.html +++ /dev/null @@ -1,157 +0,0 @@ -{% extends "base_plugin.html" %} -{% block scripts %} -{{ super() }} - -{% endblock scripts %} -{% set logo_frame = false %} - - -{% set item_count = p.__items|length %} -{% set tab1title = "StateEngine" %} -{% set tabcount = 1 %} - -{% block headtable %} - - - - - - - - - - - - - - - - - - - - - - - - - -
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
-{% endblock headtable %} - - -{% block bodytab1 %} - -
- -
-

Aktionen - Ausführungszeitpunkt

- -

Um festzulegen, wann die Aktionen eines Zustands ausgeführt werden, gibt es vier Ereignisse, denen die Aktionen zugeordnet werden können: - Für jedes dieser Ereignisse wird ein Item unterhalb des Zustands-Items angelegt, unterhalb dem die jeweiligen Aktionen als Attribute definiert werden.

- -
    -
  • on_enter: Aktionen, die beim erstmaligen Aktivieren des Zustands ausgeführt werden
  • - -
  • on_stay: Aktionen, die ausgeführt werden, wenn der Zustand zuvor bereits aktiv war und weiterhin aktiv bleibt.
  • - -
  • on_enter_or_stay: Aktionen, die ausgeführt werden, wenn der Zustand aktiv ist, unabhängig davon, ob er bereits zuvor aktiv war oder nicht.
  • - -
  • on_leave: Aktionen, die ausgeführt werden, direkt bevor ein anderer Zustand aktiv wird.
  • -
- -

Aktionen können auch ohne diese Ereigniss-Items direkt im Zustands-Item definiert werden. Solche Aktionen werden analog zum Ereignis on_enter_or_stay behandelt.

- -

Beispiel

- -
test:
-        type: foo
-
-        events:
-            name: stateengine Event Beispiel
-            type: foo
-
-            item:
-                name: Dummy Item
-                type: bool
-                value: False
-
-            rules:
-                type: bool
-                name: Automatik Test Event
-                # Dies ist ein Objekt-Item für das stateengine-Plugin:
-                se_plugin: active
-
-                state1:
-                    type: foo
-                    name: Status 1
-
-                    on_enter:
-                    type: foo
-                    name: Ausführen immer wenn ein Zustand gerade aktiv geworden ist
-                    <... Aktionen ...>
-
-                    on_stay:
-                    type: foo
-                    name: Ausführen immer wenn ein Zustand aktiv geworden ist und bereits vorher aktiv war
-                    <... Aktionen ...>
-
-                    on_enter_or_stay:
-                    type: foo
-                    name: Ausführen immer wenn ein Zustand aktiv ist
-                    <... Aktionen ...>
-
-                    on_leave:
-                    type: foo
-                    name: Ausführen beim Verlassen des Zustands
-                    <... Aktionen ...>
-
-                    enter_1:
-                    type: foo
-                    name: Bedingung 1
-                    <...Einstiegs-Bedingungsset 1...>
-
-                    enter_2:
-                    type: foo
-                    name: Bedingung 2
-                    <...Einstiegs-Bedingungsset 2...>
-
-                state2:
-                    type: foo
-                    name: Status 2
-                    <... Weitere Bedingungssets und Aktionsgruppen ...>
-
-                state3:
-                    type: foo
-                    name: Status 3
-                    <... Weitere Bedingungssets und Aktionsgruppen ...>
-    
-
-
-{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku7.html b/stateengine/webif/templates/doku7.html deleted file mode 100755 index aa24c261b..000000000 --- a/stateengine/webif/templates/doku7.html +++ /dev/null @@ -1,260 +0,0 @@ -{% extends "base_plugin.html" %} -{% block scripts %} -{{ super() }} - -{% endblock scripts %} -{% set logo_frame = false %} - - -{% set item_count = p.__items|length %} -{% set tab1title = "StateEngine" %} -{% set tabcount = 1 %} - -{% block headtable %} - - - - - - - - - - - - - - - - - - - - - - - - - -
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
-{% endblock headtable %} - - -{% block bodytab1 %} - -
- -
-

Aktionen - Einzelvariante

- -

Bei der Einzelvariante zur Definition von Aktionen werden alle Parameter einer Aktion in separaten Attributen definiert. Über den gemeinsamen Aktionsnamen gehören die Attribute einer Aktion zusammen.

- -

Ähnlich wie Bedingungen benötigen auch Aktionen einen Namen. Der Name ist auch hier beliebig und wird lediglich in der Benennung der Attribute verwendet. Die Namen aller Attribute, die zu einer Bedingung gehören, folgen dem Muster "se_<Funktion>_<Aktionsname>".

- -

Aktion: Item auf einen Wert setzen

- -
    se_set_<Aktionsname>
-    
- -

Das Item, dass verändert werden soll, muss auf Ebene des Objekt-Items über das Attribut "se_item_<Aktionsname>" angegeben werden.

- -

Das Attribut "se_set_<Aktionsname>" nutzt den [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]]. Der Wert, auf den das Item gesezt wird kann dadurch als statischer Wert, als Wert eines Items oder als Ergebnis der Ausführung einer Funktion festgelegt werden.

- -

Minimumabweichung: - Es ist möglich eine Minimumabweichung für Änderungen zu definieren. Wenn die Differenz zwischen dem aktuellen Wert des Items und dem ermittelten neuen Wert kleiner ist als die festgelegte Minimumabweichung wird keine Änderung vorgenommen. Die Minimumabweichung wird über das Attribut "se_mindelta_<Aktionsname>" auf der Ebene des Objekt-Items festgelegt. Auch hier wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet.

- -

Aktion: Item zwangsweise auf einen Wert setzen

- -
    se_force_<Aktionsname>
-    
- -

Diese Aktion funktioniert analog zu se_set_<Aktionsname>. Einziger Unterschied ist, dass die Wertänderung erzwungen wird: Wenn das Item bereits den zu setzenden Wert hat, dann ändert smarthomeNG das Item nicht. Selbst wenn beim Item das Attribut enforce_updates = yes gesetzt ist, wird zwar der Wert neu gesetzt, der von smarthomeNG Änderungszeit nicht neu gesetzt. Mit dem Attribut se_force_<Aktionsname> wird das Plugin den Wert des Items bei Bedarf zuerst auf einen anderen Wert ändern und dann auf dem Zielwert setzen. Damit erfolgt auf jeden Fall eine Wertänderung (ggf. sogar zwei) mit allen damit in Zusammenhang stehenden Änderungen (eval's, Aktualisierung der Änderungszeiten, etc).

- -

Aktion: Ausführen einer Funktion

- -
    se_run_<Aktionsname>: eval:(Funktion)
-    
- -

Die Angabe ist vergleichbar mit dem Ausführen einer Funktion zur Ermittlung des Werts für ein Item, hier wird jedoch kein Item benötigt. Außerdem wird der Rückgabewert der Funktion ignoriert.

- -

Aktion: Auslösen einer Logikausführung

- -
    se_trigger_<Aktionsname>
-    
- -

Um beim Auslösen einen Wert an die Logik zu übergeben, kann dieser Wert im Attribut über die Angabe von :<Wert> hinter dem Logiknamen angegeben werden.

- -

Beispiel:

- -
    se_trigger_<Aktionsname>: meineLogik:Zu übergebender Wert
-    
- -

Aktion: Alle Items, die ein bestimmtes Attribut haben, auf den Wert dieses Attributs setzen

- -
    se_byattr_<Aktionsname>
-    
- -

Mit diesem Attribut wird der Name eines anderen (beliebigen) Attributs angegeben. Beim Ausführen werden alle Items herausgesucht, die das angegebene Attribut enthalten. Diese Items werden auf den Wert gesetzt, der dem genannten Attribut in den Items jeweils zugewiesen ist.

- -

Beispiel:

- -
    se_byattr_<Aktionsname>: mein_eigenes_Attribut
-    
- -

sucht alle Items heraus, bei denen das Attribut "mein_eigenes_Attribut" angegeben ist. - Ein Item

- -
    dummy:
-            type: num
-            mein_eigenes_Attribut: 42
-    
- -

wird dann auf "42" gesetzt.
- Ein anderes Item

- -
    dummy2:
-            type: str
-            mein_eigenes_Attribut: Rums
-    
- -

wird gleichzeitig auf "Rums" gesetzt.

- -

Aktion: Sondervorgänge

- -
    se_special_<Aktionsname>: (Sondervorgang)
-    
- -

Für bestimmte Sondervorgänge sind besondere Aktionen im Plugin definiert (z. B. für das Suspend). Diese werden jedoch nicht hier erläutert, sondern an den Stellen, andenen Sie verwendet werden.

- -

Verzögertes Ausführen einer Aktion

- -
    se_delay_<Aktionsname>
-    
- -

Über das Attribut wird die Verzögerung angegeben, nach der die Aktion ausgeführt werden soll. Die Angabe erfolgt in Sekunden oder mit dem Suffix "m" in Minuten.

- -
    se_delay_<Aktionsname>: 30         --> 30 Sekunden
-        se_delay_<Aktionsname>: 30m        --> 30 Minuten
-    
- -

Der Timer zur Ausführung der Aktion nach der angegebenen Verzögerung wird entfernt, wenn eine gleichartike Aktion ausgeführt werden soll (egal ob verzögert oder nicht). Wenn also die Verzögerung größer als der "cycle" ist, wird die Aktion nie durchgeführt werden, es sei denn die Aktion soll nur einmalig ausgeführt werden.
- Das Attribut "se_delay_<Aktionsname>" verwendet den [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]]

- -

Wiederholen einer Aktion

- -
    se_repeat_<Aktionsname>
-    
- -

Über das Attribut wird unabhängig vom globalen Setting für das stateengine Item festgelegt, ob eine Aktion auch beim erneuten Eintritt in den Status ausgeführt wird oder nicht.

- -
    se_delay_<Aktionsname>: True    # Aktion wird bei jedem Mal aufs neue ausgeführt
-        se_delay_<Aktionsname>: False   # Aktion wird nur beim ersten Eintritt in den Status ausgeführt
-    
- -

Festlegen der Ausführungsreihenfolge von Aktionen

- -
    se_order_<Aktionsname>
-    
- -

Die Reihenfolge, in der die Aktionen ausgeführt werden, ist nicht zwingend die Reihenfolge in der die Attribute definiert sind. In den meisten Fällen ist dies kein Problem da die Aktionen voneinander unabhängig sind und daher in beliebiger Reihenfolge ausgeführt werden können. In Einzelfällen kann es jedoch erforderlich sein, mehrere Aktionen in einer bestimmten Reihenfolge auszuführen. Dies kann über das Attribut se_order_<Aktionsname> erfolgen. Mit diesem Attribut wird der Aktion eine Zahl zugewiesen. Aktionen werden in aufsteigender Reihenfolge der zugewiesenen Zahlen ausgeführt.

- -

Es ist möglich zwei Aktionen die gleiche Zahl zuzuweisen, die Reihenfolge der beiden Aktionen untereinander ist dann wieder undefiniert. Innerhalb der gesamten Aktionen werden die beiden Aktionen jedoch an der angegebenen Position ausgeführt.

- -

Wird für eine Aktion kein Reihenfolgenwert angegeben, wird implizit der Wert 1 verwendet.

- -

Das Attribut "se_order_<Aktionsname>" verwendet den [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]]

- -

Beispiel zur Ausführungsreihenfolge:

- -
beispiel:
-        automatik:
-            rules:
-                <...>
-                Zustand1:
-                    se_order_aktion1: 3
-                    se_order_aktion2: 2
-                    se_order_aktion3: 1
-                    se_order_aktion4: 2
-    
- -

Die Reihenfolge der Aktionen hier wird wie folgt sein:

- -
    -
  1. aktion3
  2. - -
  3. aktion2, aktion4 ODER aktion4, aktion2
  4. - -
  5. aktion 1
  6. -
- -

Ist zusätzlich eine aktion5 definiert, die keine Reihenfolge festgelegt hat, wird die Reihenfolge der Aktionen wie folgt sein:

- -
    -
  1. aktion3, aktion5 ODER aktion5, aktion3
  2. - -
  3. aktion2, aktion4 ODER aktion4, aktion2
  4. - -
  5. aktion 1
  6. -
- -

Beispiel zu Aktionen

- -
beispiel:
-        raffstore:
-            automatik:
-                rules:
-                    <...>
-                    se_item_height: beispiel.raffstore1.hoehe
-                    se_mindelta_height: 10
-                    se_item_lamella: beispiel.raffstore1.lamelle
-                    se_mindelta_lamella: 5
-                    Daemmerung:
-                        <...>
-                        se_set_height: value:100
-                        se_set_lamella: value:25
-                        <...>
-                    Nacht:
-                        <...>
-                        se_set_height: value:100
-                        se_set_lamella: value:0
-                        <...>
-                    Nachfuehren:
-                        <...>
-                        se_set_height: value:100
-                        se_set_lamella: eval:stateengine_eval.sun_tracking()
-                        <...>
-                    Sonder:
-                        <...>
-                        se_trigger_logic1: myLogic:42
-                        se_delay_logic1: 10
-                        <...>
-    
-
-
-{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku8.html b/stateengine/webif/templates/doku8.html deleted file mode 100755 index 070198cbf..000000000 --- a/stateengine/webif/templates/doku8.html +++ /dev/null @@ -1,234 +0,0 @@ -{% extends "base_plugin.html" %} -{% block scripts %} -{{ super() }} - -{% endblock scripts %} -{% set logo_frame = false %} - - -{% set item_count = p.__items|length %} -{% set tab1title = "StateEngine" %} -{% set tabcount = 1 %} - -{% block headtable %} - - - - - - - - - - - - - - - - - - - - - - - - - -
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
-{% endblock headtable %} - - -{% block bodytab1 %} - -
- -
-

Aktionen - Kombinierte Variante

- -

Bei der kombinierten Variante zur Definition von Aktionen werden alle Parameter einer Aktion in einem Attribut definiert. Über den Aktionsnamen werden lediglich eventuelle Items zugeordnet. - Die einzelnen Parameter werden bei conf-Files in der Listenschreibweise mit dem Zeichen | getrennt aufgelistet:

- -
 se_action_<Aktionsname>: function: <func> | (evtl. Detailparameter zur Funktion) | delay: <delay> | order: <order> | repeat: <repeat>
-    
- -

Bei yaml Files werden die Parameter mittels Aufzählungszeichen "-" untereinander definiert:

- -
 se_action_<Aktionsname>:
-        - function: <func>
-        - Detailparameter der Funktion, z.B. "to: .."
-        - delay: <delay>
-        - order: <order>
-        - repeat: <repeat>
-    
- -

Die Parameter haben dabei folgende Bedeutung:

- -

delay: <delay>

- -

Über <delay> wird die Verzögerung angegeben, nach der die Aktion ausgeführt werden soll.

- -

Der Parameter ist optional und kann auch weggelassen werden. In diesem Fall wird die Aktion sofort ausgeführt.

- -

Die Angabe erfolgt in Sekunden oder mit dem Suffix "m" in Minuten.

- -
    delay: 30         --> 30 Sekunden
-        delay: 30m        --> 30 Minuten
-    
- -

Der Timer zur Ausführung der Aktion nach der angegebenen Verzögerung wird entfernt, wenn eine gleichartike Aktion ausgeführt werden soll (egal ob verzögert oder nicht). Wenn also die Verzögerung größer als der "cycle" ist, wird die Aktion nie durchgeführt werden, es sei denn die Aktion soll nur einmalig ausgeführt werden.
- Für den Wert von <delay> wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet.

- -

repeat: <repeat>

- -
    se_repeat_<Aktionsname>
-    
- -

Über das Attribut wird unabhängig vom globalen Setting für das stateengine Item festgelegt, ob eine Aktion auch beim erneuten Eintritt in den Status ausgeführt wird oder nicht.

- -
    se_delay_<Aktionsname>: True    # Aktion wird bei jedem Mal aufs neue ausgeführt
-        se_delay_<Aktionsname>: False   # Aktion wird nur beim ersten Eintritt in den Status ausgeführt
-    
- -

order: <order>

- -

Die Reihenfolge, in der die Aktionen ausgeführt werden, ist nicht zwingend die Reihenfolge in der die Attribute definiert sind. In den meisten Fällen ist dies kein Problem da die Aktionen voneinander unabhängig sind und daher in beliebiger Reihenfolge ausgeführt werden können. In Einzelfällen kann es jedoch erforderlich sein, mehrere Aktionen in einer bestimmten Reihenfolge auszuführen. Dies kann über den Parameter order: <order> erfolgen. Mit diesem Attribut wird der Aktion eine Zahl zugewiesen. Aktionen werden in aufsteigender Reihenfolge der zugewiesenen Zahlen ausgeführt.

- -

Der Parameter ist optional und kann auch weggelassen werden. Für Aktionen, denen keine Reihenfolge explizit zugewiesen wurde, wird der Reihenfolgenwert 1 verwendet.

- -

Es ist möglich zwei Aktionen die gleiche Zahl zuzuweisen, die Reihenfolge der beiden Aktionen untereinander ist dann wieder undefiniert. Innerhalb der gesamten Aktionen werden die beiden Aktionen jedoch an der angegebenen Position ausgeführt.

- -

Für den Wert von <order> wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet.

- -

function: <func>

- -

Mit dem Parameter <func> wird die auszuführende Funktion festgelegt. In Abhängigkeit zur gewählten Funktion werden zusätzliche Detailparameter erforderlich.
- Folgende Werte sind möglich:

- -

Funktion set: Item auf einen Wert setzen

- -
se_action_<Aktionsname>: function: set | to: <val> | force: [True/False]
-    
- -

Das Item, dass verändert werden soll, muss auf Ebene des Objekt-Items über das Attribut "se_item_<Aktionsname>" angegeben werden.

- -

Der Parameter to: <val> legt fest, auf welchen Wert das Item gesetzt werden soll. Für <val> wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet. Der Wert, auf den das Item gesezt wird kann dadurch als statischer Wert, als Wert eines Items oder als Ergebnis der Ausführung einer Funktion festgelegt werden.

- -

Erzwingen der Wertänderung: - Über den optionalen Parameter force: [True/False] kann eine Wertänderung erzwungen werden: Wenn das Item bereits den zu setzenden Wert hat, dann ändert smarthomeNG das Item nicht. Selbst wenn beim Item das Attribut enforce_updates = yes gesetzt ist, wird zwar der Wert neu gesetzt, der von smarthomeNG Änderungszeit nicht neu gesetzt. Wird der Parameter force: True gesetzt, so wird das Plugin den Wert des Items bei Bedarf zuerst auf einen anderen Wert ändern und dann auf dem Zielwert setzen. Damit erfolgt auf jeden Fall eine Wertänderung (ggf. sogar zwei) mit allen damit in Zusammenhang stehenden Änderungen (eval's, Aktualisierung der Änderungszeiten, etc).

- -

Minimumabweichung: - Es ist möglich eine Minimumabweichung für Änderungen zu definieren. Wenn die Differenz zwischen dem aktuellen Wert des Items und dem ermittelten neuen Wert kleiner ist als die festgelegte Minimumabweichung wird keine Änderung vorgenommen. Die Minimumabweichung wird über das Attribut "se_mindelta_<Aktionsname>" auf der Ebene des Objekt-Items festgelegt. Auch hier wird der [[Datentyp AbValue|Doku-De-Grundsaetzliches-AbValue]] verwendet.

- -

Funktion run: Ausführen einer Funktion

- -
se_action_<Aktionsname>: function: run | eval:(Funktion)
-    
- -

Die Angabe ist vergleichbar mit dem Ausführen einer Funktion zur Ermittlung des Werts für ein Item, hier wird jedoch kein Item benötigt. Außerdem wird der Rückgabewert der Funktion ignoriert.

- -

Funktion trigger: Auslösen einer Logikausführung

- -
se_action_<Aktionsname>: function: trigger | logic: <Logikname> | value: <Wert>
-    
- -

Löst die Ausführung der Logik <Logikname>aus. Um beim Auslösen einen Wert an die Logik zu übergeben, kann dieser Wert über die Angabe von value: <Wert> hinter dem Logiknamen angegeben werden. Wenn kein Wert übergeben werden soll lässt man den Teil weg.

- -

Funktion byattr: Alle Items, die ein bestimmtes Attribut haben, auf den Wert dieses Attributs setzen

- -
se_action_<Aktionsname>: function: byattr | attribute: <Attributname>
-    
- -

Mit dieser Funktion wird der Name eines anderen (beliebigen) Attributs angegeben. Beim Ausführen werden alle Items herausgesucht, die das angegebene Attribut enthalten. Diese Items werden auf den Wert gesetzt, der dem genannten Attribut in den Items jeweils zugewiesen ist.

- -

Beispiel:

- -
    se_action_<Aktionsname>: function: byattr | attribute: mein_eigenes_Attribut
-    
- -

sucht alle Items heraus, bei denen das Attribut "mein_eigenes_Attribut" angegeben ist. - Ein Item

- -
    dummy1:
-            type: num
-            mein_eigenes_Attribut: 42
-    
- -

wird dann auf "42" gesetzt.
- Ein anderes Item

- -
    dummy2:
-            type: str
-            mein_eigenes_Attribut: Rums
-    
- -

wird gleichzeitig auf "Rums" gesetzt.

- -

Funktion special: Sondervorgänge

- -
se_action_<Aktionsname>: function: special | value: <Sondervorgang>
-    
- -

Für bestimmte Sondervorgänge sind besondere Aktionen im Plugin definiert (z. B. für das Suspend). Diese werden jedoch nicht hier erläutert, sondern an den Stellen, andenen Sie verwendet werden.

- -

Beispiel zu Aktionen

- -
beispiel:
-        raffstore:
-            automatik:
-                rules:
-                    <...>
-                    se_item_height: beispiel.raffstore1.hoehe
-                    se_mindelta_height: 10
-                    se_item_lamella: beispiel.raffstore1.lamelle
-                    se_mindelta_lamella: 5
-                    Daemmerung:
-                        <...>
-                        se_action_height: function: set | to: value:100
-                        se_action_lamella: function: set | to: value:25
-                        <...>
-                    Nacht:
-                        <...>
-                        se_action_height: function: set | to: value:100
-                        se_action_lamella: function: set | to: value:0
-                        <...>
-                    Nachfuehren:
-                        <...>
-                        se_action_height: function: set | to: value:100
-                        se_action_lamella: function: set | to: eval:stateengine_eval.sun_tracking()
-                        <...>
-                    Sonder:
-                        <...>
-                        se_action_logic1: function: trigger | logic: myLogic | value:42 | delay: 10
-                        <...>
-    
-
-
-{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/doku9.html b/stateengine/webif/templates/doku9.html deleted file mode 100755 index 74787fc68..000000000 --- a/stateengine/webif/templates/doku9.html +++ /dev/null @@ -1,146 +0,0 @@ -{% extends "base_plugin.html" %} -{% block scripts %} -{{ super() }} - -{% endblock scripts %} -{% set logo_frame = false %} - - -{% set item_count = p.__items|length %} -{% set tab1title = "StateEngine" %} -{% set tabcount = 1 %} - -{% block headtable %} - - - - - - - - - - - - - - - - - - - - - - - - - -
Log Level{{ p.get_parameter_value_for_display('log_level') }}Log Folder{{ p.get_parameter_value_for_display('log_directory') }}
Startup Delay{{ p.get_parameter_value_for_display('startup_delay_default') }}Suspend Time{{ p.get_parameter_value_for_display('suspend_time_default') }}
Items{{ item_count }}
-{% endblock headtable %} - - -{% block bodytab1 %} - -
- -
-

Vorgabezustände verwenden

- -

Es ist möglich Vorgabezustände in der Konfiguration zu definieren und diese später für konkrete Objekte anzuwenden. Dabei können im konkreten Zustand auch Einstellungen des Vorgabezustands überschrieben werden.

- -

Vorgabezustände werden als Item an beliebiger Stelle innerhalb der Item-Struktur definiert. Es ist sinnvoll, die Vorgabezustände unter eingem gemeinsamen Item zusammenzufassen. Innerhalb der Vorgabezustand-Items stehen die gleichen Möglichkeiten wie in normalen Zustands-Items zur Verfügung. Das dem Vorgabezustands-Item übergeordnete Item darf nicht das Attribut "se_plugin: active" haben. Im Item über dem Vorgabezustands-Item können jedoch Items über "se_item_<Bedingungsname|Aktionsname>" angegeben werden. Diese stehen in den Vorgabezuständen und in den von den Vorgabezuständen abgeleiteten Zuständen zur Verfügung und müssen so nicht jedes mal neu definiert werden.

- -

Im konkreten Zustands-Item kann das Vorgabezustand-Item über das Attribut

- -
se_use: <Id des Vorgabezustand-Item>
-    
- -

eingebunden werden. Die Vorgabezustand-Items können geschachtelt werden, dass heißt ein Vorgabezustand kann also selbst wiederum über se_use von einem weiteren Vorgabezustand abgeleitet werden. Um unnötige Komplexität und Zirkelbezüge zu vermeiden ist die maximale Tiefe jedoch auf 5 Ebenen begrenzt.

- -

Beispiel

- -
beispiel:
-        default:
-            <...>
-            se_item_height: ...hoehe
-            Nacht:
-                <...>
-                enter:
-                    (...)
-                se_set_height: value:100
-                se_set_lamella: 0
-            Morgens:
-                <...>
-                enter:
-                    <...>
-                se_set_height: value:100
-                se_set_lamella: 25
-
-            Abends:
-                <...>
-                enter:
-                    <...>
-                se_set_height: value:100
-                se_set_lamella: 75
-
-            Tag:
-                <...>
-                enter:
-                    <...>
-                se_set_height: value:0
-                se_set_lamella: 100
-
-    beispiel
-        raffstore1:
-            automatik:
-                rules:
-                    <...>
-                    se_item_lamella: beispiel.raffstore1.lamelle
-                    Nacht:
-                        se_use: beispiel.default.Nacht
-                        enter_additional:
-                            <... zusätzliche Einstiegsbedingung ...>
-                    Morgens:
-                        se_use: beispiel.default.Morgens
-                    Abends:
-                        se_use: beispiel.default.Abends
-                        enter:
-                            <... Änderungen an der Einstiegsbedingung des Vorgabezustands ...>
-                    Nachfuehren:
-                        <...>
-                        name: Zusätzlicher Zustand, der nicht aus den Vorgabezuständen kommt
-                        se_set_height: value:100
-                        se_set_lamella: eval:stateengine_eval.sun_tracking()
-                    Tag:
-                        se_use: stateengine.default.day
-    
-
-
-{% endblock bodytab1 %} diff --git a/stateengine/webif/templates/index.html b/stateengine/webif/templates/index.html index 903423d8e..009bd8eaf 100755 --- a/stateengine/webif/templates/index.html +++ b/stateengine/webif/templates/index.html @@ -53,69 +53,16 @@ {% block bodytab1 %}
-
-

stateengine Plugin für smarthomeNG - Deutsche Dokumentation

+

stateengine Plugin für smarthomeNG

Warnung

Wichtig: Es ist nicht empfehlenswert das stateengine Plugin für sicherheitsrelevante Zustände, wie zum Beispiel das Hochfahren von Jalousien bei zu viel Wind, zu verwenden. Sicherheitsrelevante Funktionen müssen so einfach wie möglich aufgebaut sein. Es wird daher dringend dazu geraten, solche Funktionen unabhängig von smarthomeNG und dem stateengine Plugin zu realisieren. Für das Hochfahren von Jalousien bei Windalarm beispielsweise sollte die Sperrfunktionalität verwendet werden, über die alle aktuellen Jalousieaktoren verfügen!

-

Funktionalität

- -

Über zusätzliche Items in den items/*.conf-Dateien können Objekte definiert werden, die eine beliebige Anzahl benutzerdefinierter Zustand haben. Jeder Zustand kann Sets von Einstiegs- und Ausstiegsbedingungen haben, sowie diverse Aktionen auslösen, wenn der Zustand aktiv wird. In regelmäßigen Intervallen werden die Zustände für jedes Objekt geprüft.

- -
    -
  • Wenn die Ausstiegsbedingungen des aktuellen Zustands nicht erfüllt sind bleibt das Objekt im aktuellen Zustand.
  • - -
  • Wenn der aktuelle Zustand verlassen werden kann werden alle Zustände in der Reihenfolge, in der sie in der Konfigurationsdatei definiert sind, abgeprüft.
  • - -
  • Der erste Zustand bei dem eine Gruppe Einstiegsbedingungen vollständig erfüllt ist, wird zum aktuellen Zustand. Die Aktionen, die für diesen Zustand definiert sind, werden ausgeführt.
  • - -
  • Wenn kein passender Zustand gefunden wird passiert nichts. Das Objekt verbleibt im vorherigen Zustand.
  • -
- -

Die folgenden Bedingungen können Teil der Bedingungsgruppen sein:

- -
    -
  • Tageszeit (Minimum, Maximum, Wert)
  • - -
  • Wochentag (Minimum, Maximum, Wert)
  • - -
  • Azimut der Sonne (Minimum, Maximum, Wert)
  • - -
  • Altitude der Sonne (Minimum, Maximum, Wert)
  • - -
  • Alter des aktuellen Zustands (Minimum, Maximum, Wert)
  • - -
  • Zufallszahl (Minimum, Maximum, Wert)
  • - -
  • Vorheriger Zustand (Wert)
  • - -
  • Trigger-Objekt, dass die Zustandsermittlung ausgelöst hat
  • -
- -

Zusätzlich können beliebige Items als Bedingungen geprüft werden (Minimum, Maximum oder Wert)

- -

Der ursprüngliche Zweck dieses Plugins war es, Jalousien zu steuern. Mit den steigenden Anforderungen hat es sich jedoch zu einem flexiblen Zustandsautomaten entwickelt, mit dem nahezu alles gesteuert werden kann. Im Prinzip ist es ein endlicher Automat.

+

Doku

+

Die Dokumentation findet sich auf der SmarthomeNG Webseite.

From c7c348c6bdf2e937ac127e814b1e0f7832fcddb5 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Tue, 18 Dec 2018 14:22:19 +0100 Subject: [PATCH 465/705] Alexa4P3: added new version of alexa plugin which cares for v3 payload. will replace old alexa plugin beginning with release 1.6 --- alexa4p3/Create IAM-role and Lambda.pdf | Bin 0 -> 5768481 bytes alexa4p3/Hoerprobe.mp3 | Bin 0 -> 107352 bytes alexa4p3/README.md | 572 ++++++++++++++++++++++++ alexa4p3/__init__.py | 200 +++++++++ alexa4p3/_config.yml | 1 + alexa4p3/action.py | 213 +++++++++ alexa4p3/actions_lock.py | 35 ++ alexa4p3/actions_percentage.py | 67 +++ alexa4p3/actions_temperature.py | 108 +++++ alexa4p3/actions_turn.py | 27 ++ alexa4p3/aws_lambda.js | 57 +++ alexa4p3/device.py | 110 +++++ alexa4p3/nginx.md | 176 ++++++++ alexa4p3/p3_action.py | 292 ++++++++++++ alexa4p3/plugin.yaml | 25 ++ alexa4p3/requirements.txt | 1 + alexa4p3/service.py | 534 ++++++++++++++++++++++ 17 files changed, 2418 insertions(+) create mode 100644 alexa4p3/Create IAM-role and Lambda.pdf create mode 100644 alexa4p3/Hoerprobe.mp3 create mode 100644 alexa4p3/README.md create mode 100644 alexa4p3/__init__.py create mode 100644 alexa4p3/_config.yml create mode 100644 alexa4p3/action.py create mode 100644 alexa4p3/actions_lock.py create mode 100644 alexa4p3/actions_percentage.py create mode 100644 alexa4p3/actions_temperature.py create mode 100644 alexa4p3/actions_turn.py create mode 100644 alexa4p3/aws_lambda.js create mode 100644 alexa4p3/device.py create mode 100644 alexa4p3/nginx.md create mode 100644 alexa4p3/p3_action.py create mode 100644 alexa4p3/plugin.yaml create mode 100644 alexa4p3/requirements.txt create mode 100644 alexa4p3/service.py diff --git a/alexa4p3/Create IAM-role and Lambda.pdf b/alexa4p3/Create IAM-role and Lambda.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c3a48fe3433af8b5579291c30079daed6ab7d590 GIT binary patch literal 5768481 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 qeyzjPp}fi4;h-zU^r4c@R^8TUAIaNyH?? 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 HA5O?RebH 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%0D>iz1WDS&@uKg! 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%0A^P>U64*lX6wmC)N?b{4I1P{fX=j+xgfkxrP+ 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

PW7TCyu|)^Qf+Xx4Ft4kg#KPd~ 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�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

    <_M(K`A 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 DP02V$PSCy`oKCfAw!^JB$iuSGnl>_i5 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

    A#BE4RsaHrjpUkqFQ~Dq+eoChA&^Lfm%ct)hzT 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%0Ab0u%{@rNzYwqTPCiL-A-6 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 z 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 *oE0vi11-0;3B7$7 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∋s7H&vBrdFUt8`nxU-e& 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�C#AFKhqmg#S&&lFB!z~tO(jCeyLEk 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ⅆ@Zo~~4by*(G^e(0;a$RgGaQ{=icrlp-Q6G|Dl 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

    64Rk|nu_yY)eic7hO@Fq#b)j)p$U9ZVVAA|(5 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�_dW*XPdhk#0FF&j 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%0D6Eupqk`H{ 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�a5(cLM1k_PTOD5_w3Eir}AkrW8~ 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∈^$I{3DQ91b6R{!@r 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

    B?MR`-~)t}tcF+jlbw^505X2$;{w%2bsf;}AgZ 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Ⓢ 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%0DUipL7Eh&1V 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 z z2UJY07Zq{{xR}cmCJ%hF@Yo&TZxbWhPa`=_%UImD1V+yGDFuSSi!sIuLW;wfHQPKh z^V+$*Q$y*rDVJI+S14H2q0?2DD?Q=uXgwOp+spi;Yue$}p^{IOc)H7*hxuUb#p1zg z5A)1=jWaX1`U{J<`X!{^CExg>0*ynv77z!F1Oj*JVjg_85Az;}UmA&9%EMK;?>aiO z!}3{5E_Z>DlA#hTshp@bEIo`Z3q@?0wl`JRO${91Hyw<)J1r&1HkzJ$&pl0G z%_bwaKt70CgY3uNz0$RJ@9-dw+cCN{JG@LR(7Klu$4q(6;O2}$v>;I>o=NJ4OM?Ro z6S{_Rw03_CtXU#wb>#!uys~BG{Vw4vQY3`N4e>jT-6?phFO>t>koNbneJVp9RP2Y@Awi(n^0f-Cy?cs@Pnt)&Tzm+PWSsH#6 zWxjkaIX|LlIj9eVDIAQC`bv_`2rj#4=Qh1-UG6m-f*zz{c69F^UPy^|<5%ON8<5k8 zXte>p(l=8E7fUOVAC|@Lvo0+4UP^tsX_5`_k3QRZ%4Qa@HJO{Na0_QALF7}YSP!b` z><#L3%fz)%N%3^0QHw<5lX2gdtV@{&?ts!AXB!w8Qi>w3Y}4GxK!rm+hliA)2gM=N z&CxnB$@gL(Es6Z0BY>I^FrHfKPeAy=BKx~8i4jI_e8pkDr*npTcj7+%3kltS?ZqEl zoYsGX93R~ecR`M-a}A(cKL5(j`Tx|E?n{IY zM|EF%J*$N4SGgHs{=|MYeBzVQ%;kU;SxDZmjGXJie_hQteNw8|_{7h;P{{Z(Gvvmm z)AH)(CUp&by(k<*A)(DIg20H4#sKyD=IXrdEzq-(6d=DAw++zg(l40A@N$#DxpsXp zgds6lU_!yFO$aXS*>&a|nKbOAiaPJnj+o!mjjy`bty6pHs->`YwLd}E)&&z;ojFzF zroaXvEI2_G{z)>IGMO4Wuu85*ykSdc%gK3UC3VT*Ow{oZ^Qo+q^)&&m#6u*+;p-sB4I`6C~om_N&?v|MC*>k){I#;~(LV5-}>@d<8vE1_Nr88z4TV~cRnBe`)#v5e6 zvg6i$oi=IsIPK(3LROsOwkta8pnxQpr1LopT>T2^4xen(`Y}u1X));xmwEr{VSdEj zsx*^de1qSR$flDS;Q8FTJ-JR;Q2_S&7-G&^S$g~P~w75X^4~YDY?hBP` zc578a;kFm73U;5fEkC*}J817_W1w9&pNJGmsS6<~w!=^GxTeny$z#gOmtm}!M-T5g z9_KmFBb57BvE>+cb$PdC1T7UlP3FoOoq_Zc2vde>XS)L=M&{H{A56TlrQ$H2BYml$ zs6K;JS1J4EWeo2o(nr!2%Jo51 zDUH&tQd(j`aL#g5Edn5u_*kSQtLIKUSkN;q&AbSrgs1z^^!Sa~K~wyEA=nP?xw1Wm z(KVX3I=Nd_9{&6>(c4|1b8fsb?&+zDQsY0{Zyd|Dz1I{-7ui>~us__QSC1}brbE>0 zjr@RL!R|srhk~o=Yp`c@DiB?)uRr<^k5>xS^d6hS9f-ldAQN2q2e(t+`Y&#|LKs(m z{Ax+N3-wVNHagLH&V{oo;b-@~DxLT4-|Re&`r(+HSj1H>Q;mzILGqYSayU6o)f9{M z@xh1p@0Rq|5Rwrl%}>2bjn7y)mt1;wAp7ygzw6i5y=!%lOA=g?R2bU#IFW-{)b20$ zC!o?o5ba^5sjv!*+nnAUDD>@AX8(z~r!uVxL4pQjRpl#rhTRyx-Hlrs0!7XG0(QPKEu$@mE|Z}oQd5! z>ok5eauxCeewK@$&e`1II$M9k*C*aHVRV9!$Ik0v%lfoPtqholVg$em9(lp?zWor= zGvyVky5-|CD_?Rbg2uE~@}03DjN%j{^?@c@7wm}YxBKyj!R*2J`^_~cgAwWvb@PSO z$0B3L!!{YL*_IVtn37uLNf2wv3<>e?ExSWdX@RX&rH552mxCaO$M^LlZxc8AGMsmF zsu-?a9~ra-#`U3X&Sk^JKVGVJWZW&e(0Hmap%cLrXIU8^fc@KG&X%^h)%5fx2Uv^t zGO4JlrL~J_5A&uvOH=EDot4WW_*mCEj#h;HNQ6yANIRs7ky-6iTeA0led6s7Q0%g` zai`=QFX-(|W`n4wHKNAbXn zn)A0FTF&r!xuxl8j`6I%oj4cMdE0CNr~)0g6UJHF zjI0Mvu*G567DD8HFDm7$+Z!rwpgp0_sO=Eel@hqHjXmE=T@~gSj%b#|T>t$1dV9bF zVlkBqLHKseL;F!VU@(p4(nvkrDZ);8n*!@;4w2WbA7RekcWXWFP3nE$O9^JQrsjQ& zIL`)GjD@sW4CyM=jfIpwtQ*|%W~|O1D3FJpU_S(8-EUm}w20e^cKrJk0|#)(KxB0EI_MlE%l^jmD};Gc7aKthsRdawDA$Z)-xtsDdsZHOsNe z`ugKm(hkgQ*{0!2jXP<24j>Z+=$zLSIm&b7{@jvI@22_YzUvy|W1)rWa4{E-1_*tY z)bn3~5B|Fw^kZCbWIw-zgl&(4pI^8^_B8GovwW^5LXzz#+@{m|s&cBt;G8eUvn~ga zHix*=b@y&}(~~*tmDRpE_(a3J)?7u|n&3r_L@u7p=pWC*ktFTlK(p6$?Q|~n+5)&k zgGs#ba*qeQ9x=r4tH z-*eO2C+ag7xs+7pxg}GW>})^1wF83($-vIGQRuWY;4+J?qM1E0;!`ogRei@gXpncq>%;YvH;oBqOXwew#R4)j;Qa*RiPrJIJT zc5;$TEQO#3zNo!nQKfn4m!SDIB5;h@x+5~Rk+!vJRZAUo#5nSYqo z_$USX+H2VHv`cUH-zDgheYb3!b^I66({!d{g!3|niN=eO@5C0JA6*plTnp8-&B9--2|zW6(XNd-bnNoI6pO!H-KLqqc!i4vudx?tr? z4q+|iP_p?PeZ0pb{~_^$hR((M$0pBtBy3H`(H5_x#GqMDn12Y{N7_WR+Dlfl8O3-uc&uRk{D}^;>Xl&?(t)>LQY%DpFT$I^{YtZ!JA4Qf^{ z%?LL?VU+7tVM=qnwR@NO8V^cyxH$+_v+%gmbRwx-qq?-O^$UN@F3L5oh{ksJd|wih zv=8#)r}FLpeCMuD*93ErI z=&3KOtdx-t#og#OP;wVWXXWMS_RdJHj1@=Rg9+^$oYjuVj?$v&I!!wjSTz%}4wOEq zGk*cZFU7*;pPX^O{lX^L$p1Rq&v)b^=x6+!VeK)TpK@$JphRTa;~e+ay<7 zINBzzj7*$KquCF0s^={Z^7St)Hr*S1^9HMOJ<^}jUgx@mYT04VGSJVyjcg4dZuY67 z&wBqs%=kLvtBG;9eiS$!xEs;0&fUS}K4sSVTO)keR_%KNhaU_l?$})`RwPu}G{vu^ zQ%9ER6Gj~q$8?X(7+jDNUJ`&dA>y7AlKbZ$aS`M=rE}&B0`JpwUU})d`j>msT4fOD zPaPWx9IegB4NeDQC=h3+o(fC_W(}ZAL$tI$mPh7{?Esd@;nY1Ebh+`#)?`_m&cWSj z`;^eBI^}|y9lH$)V0cj8{hOzs-C=kxaP@>@Dyu!)1J*$2bgRTmgE=3YOMjt}`)A~7 zFeNDX+=Wan&V$zQR6`D@8~}2Y*F%hk|K#2?FAdJ^n@&45yQymLzQ>NY@wLo$#qOJy zFSJ=FOT5imRFX^bqMm-_a$jB`o-csFhp+bAMiM1runCqNbuH6l5vmV|| zgcY-|r3n)V!+DN{txaOvbeO_jhmuX}BL`BQ)VISyG$ejJg#bPt6Vdk-IJf~jMH99A zt?ln`+@Ro>JTyBXB_F^s|IInv$s08X-Rn8ypNnpuTA9eza^beYFYwq_(1cCiM%l{P zI&%61W*X?;PCZey$&Nox7=fuCAgn3OpcvbqNkK5UuHVC@f*T0y&qoG&8f=lzDQ^Js z=q78R{?q(8x-66E5DE0q0+ef1xDb|mu}u?pm4hsNSEH$zv4o$=ZLu46m!BWk(vYRy zMq8*p7JF`=Xl*{oU-CZ;?v@z%_s<3^DgR7u0XC%CvATyzBM!IhoDQdCnsT+xzm1KN zziP~9BUhhO=Rc>!N?sw;%!of$nVn_)sf3{Nf=AnD^$EAiR z4P8RFQ|fGIPK?%BCq6s;o|BQjnggp}qtxQeEL`@fTbqQab+g-177FsRRjk#u6pfYP zbzkH;HnL4=iukK`P)%#6Qn5EOz$*5)nrJE+L}&qYw5NZ{+`9g)@7tBcvmjW{-IS&o z;o~r+OB9GqDMpbs!kWvRjkx<7XPuT#B5*;r^qoQPCMBg>e1F{f^{L>OXzwQDls9D| zfqj7?D8(GQ+2+z5%vMo_TGo(epB1WJBh}(5^0`y+@fJ=YAl^LH>~<|cMs=v3=IVuL zp|3>(o&$mAu2HUBewSiGGI30^vzv>6eAb)I?V;}PUHPF@&u7@vqvSc$ekpB{I#&$y zLr)Ae^eJU5YNidlG{+Rjq}^@VY`yDwtx-ru815zcfHiw)e>fEAY_@DX<~(;$vSi`2 zT5JK%%_8G_%ztMV<&94=UrCLXU9e@fLI7Us);ve%E{G7I*f~ z9(lo2)RZiHF7tk)GcF6Iw@Zj*Z3)RP3{dYahqH#m_Fy&N%f1Y}5!hFwkj~4!xxK#B zdE+X995v?0sgJeGx;h`451}rU$#iRe`SuOtW0&b%zud>L9d~i_I+hWUmj+rJ`Snpo z>~D}|p7{XPt$@5g0K=l|wNx$~e&_bo5pLBXWv-+3O4d#h0BIYa-Ajj8hM3QSM2qj= zM}aiU9G&ePi;wj9{yx$l`tbupJky4AXWn5n%caM`p#>|0fbE8<$72tFpvp&dQ;PlS z>|s7+AUd+?Srt8e_bFR#8XWGnaSl7hG&9FU?dh31*1d5XnyMXYu^Numw452sYaKV$k(lqeQ(G zo(~EycqWffvwoEnRpI~VGDGeF<-bXezbwg}?MnJZg8l=QNImgirYQe8!~I{H#r(HF zaQy$F(bDbdnsNBjVgpY2y64q_JppE;ocbytmzs8R36{5{ zMcNgw`cFoy&*<8e<~>DQGJtNtK-}6Q3{HDg&M6%RiUp4X;n1)NbA-C@q4d7arwu(q zG<-jNsuwOgE_8n3;u3y?(F4ll^>zEMb@^5^xr{^O=)qcWI6~_OOBO_HA%B#7peoL_ z4^H*5;(c}bJh-?zzVQ$$-&Z&OFBPXmv>LN>J& zQsP+j@E@MglAuRAS%Ss^7OFEFfHCFOKH4hq75PFARUXfgA*wGNjU`9P?W>LMEDxMn z;08V2{m9NAWGE&{w%OzJmrfcQRer4ooBe(7*weq}axYf$L-^cVMk?s5LIy#~fCY}8 z=s5XkLcz4b3t07Eb?KejI^f; zNaQ`BzsgyC!e1omtYNGT0Q#<@msWWU^4f{ve%3In^T-u1Rh4kmgy-mH3o~l8ju3t; zyQydvO*8MqID@Iqwc^}yzn3lf!)V}y00a>xK^Aczf?=p%ZZ??uy7sc-8E?CZqusOdO?aV z-we&1J1P8wJz%(TIf?k&#>HDZQFyTZAh_=S_aj~I&YA!j+4^wN@(zOFj!Do!hh^-g zC>i8&`o8IUv*c}4N19=dBi_8jljq|tVaDmRC1(Rtm(5T?t#7cUMDN2nJ4?FL5cyzR zr{_=Zp>)E7L?{OPG$qGCE60GCpQeJNVG$0eDAbaiW_;Q$#5GbE^#Ko4v!9QbVPXE1 zxm6pyQ)fX(MH;#;TZO4tH#Hc8ps0nopDpdCq7d8;ZCM0Df(k6$;flY=0>F$;g! z@%_iuGvq3#@o%SjK8YNAiMrOb1#AFLhq6&_kOL||LE`gW)F^U)L-l__fNF_ zzkX^1pMHb<>_;qm`!M9y;lZ3K6)E<`t`Qa@>i9W~v58gel zE6L|QC7pp9Ozo5O5?^W(qrQ2odRdlbN>Ky*e(kjyMtk2>@?CY0H(wMouQg1(ml_@2 zena{Q>RmO&-_*gAIns+*sIJ~~DO>HzV+LZmaNMOmgxUhnhjZo~B>i=j7ch*9ZqN+Z z6Ptyw7Wq)%I`p9iP#{W8QoP}w+=c>_$s9YFr(nnR9k_n@ zBX*A7p87rUPF0nr!o6bxUn(+O#1k`7*X|^as)7eSQ}6w&t-`;&_>LIz**t7&ZlZ7# zlAVHhpM~xYKEz0CEwh*5_=dE_avkbF9RcPPq#CrUdmL`Bz zzHt6m&{028bWr%Y{!t}oSEr>*gRYKXqX5W_9!uZp`+iFz&wWr(e;dmueOKR|o^Is@ za2o|-skp$>jYRe6L*QxnHH}o-rJu6i8gPNE--uL#uIJn8AbC@}OX-_1u-q7~!m_l` zfZkB8J(W9ibr^`G1Ucw(c)J+7G^Yr%-qOJ+ zjJ(svS8sM_;Cjsw+aqa!j)(JNKAXXA^F@*_)t(S*)9BCh7ofv?N(THG!x@-eW+9zZPm}?N zlWUya&^we-)3WrHuqU-mmBlAaM9-ePCy0WK#a~REMhge-JPf)P{lD(-h+aO_t2S89 zK`I={#r=Oq=J?&pxeAHWhMz=w-z$yKM)E1QPJ80>9X$@mw_?%Zb#vEy|KR~8B5RU& zUeh0VsOB2P?f67Aw;W`^kXgG+U<-if&rE|?G!k@|1@GOY_0OZDI;k3MK%+_1m;3kB za|&J9drtXqfhCQ<4fkG*HnZ*?pnr-U|Js-9tMh_4@vK8(Leh<|8PBVS@-+Q%V_#$` ztMuOm;q2sFo(%(@4|IKY2N-O2qqITKJ;B-N({;}ae9a<8ls zc8PtY=0h@zL=5~?qmgAGDwZenv?*NQt{cAEu%AQPtBY=CV>YY}&ax9`p6mmLt`F4@ z#2Ku|nXdl;If{!`byj5k@$(fwHEL*`Ks}cK{8yrK|LGTImdZ9P5{@f)3|>Oa;u!;( zuB?^d>JEa{3A ze_yFm*PFs0h2+N#@mi!GX@uRE4I#V_t6S)Q$h*wlp;=@}wjg86bTapxhT^RVj@`!k zFly!ss(xneq-&;1yuhoZCc-J;))vGoR3*4u(P>LIBw%bAW%=^j#%fs+`$33Q8#i)Y zMP-(RM_3BD)Uu;(1)MKRe$Rd`s^KxkD2AvxL4O@~TQdTOuKQL$&%Kx(QpvDiDKOVS zRU=Tw&v3BqM@d>F2QpCc9#<|&uvtW&--m6i7OYcd@(Cy7rxRScp6Cu8_}RrYaj5mk zE`Ma1$zMNh&OOw)xc{AZs`lKU*KR>+_Py7Y?0jky_oplElbSIi9S|=x3x)%8wA{J) zSMpp+`d+hVLBX0hV`&do_&KDmT|2*V2F?dsvh;mIMtakryjI6c)Mp=y8EKw#x4Wah zC_W$AA98Gx=Pc31r~-a{4&CIpx*L4G*Q{ zwPvo>wjzE8Kz8zdp^Io&%f|$`7l0c}Y9KdZ_pZzUX2JV@YRJWUbRuRJ)U$dgPfumt zc>6Bt3R|DkA$gUZz`5qV)eMu0Q-i-nLGVvXbwmSqn{bM+SPqVjM}PbdsrIq+dh?ai z(c$WNYH08u9#y%M00U<=>14(LE9-6TznJ~G= z=XCg!B*-4vkOfBRNshMvV2A%XxK@1y^tSkL-~qfe+0pz)mRxINmgx0yjZ<&GsV&$Q z?r52ydDS;AR0<9c6$6`WDXXa0b12$-fSY@Al2iYXB4c|YT%KksI^;4e7D*1IL|Mp@ z3ywxWFu<9DxBu{*;VP$*rxzu4*ZWHI5TTXqt1L&KESBW+SN?aZKADkh4(ANne3?(q zK{Yi;+j{Di8$G8f2v(!JEQP$Mnjcr1=3#NCZ6rp^X{)10$$JIe>)GV9T15?Gx_8v) zU7u1ep0T7Axh0H<9U}=RIM!+eET?|Ge=A9BC=Da0aBud(mDo6?opj6Q?@KRY8`!YUmuCS+LK$yb<7c;!Fx^-pug zF)zmB6SBZAu=y$QnLzJN~~A9jHIz}ElVacsMdb)F4CU;hGQ2}={mH}=Oz4h z`yZaShhppYDIaqTPP&A^V7_YM?>z4eguy57&`uW%tl)J_#`K?SIY|X>ounV`3od}9836n{^aV+S)k+8 zr=5+!$V0Q?>q3glA|Ew7do#Dp-6>Dk@`M2r**k#mFj1+kEK#oKTYU-IK~a{y)Ci~-tlfbTNC)# zcCsuaOu^P_zM`%j={1tSStxrLWB?xQT9P`?Re2YPMLcBZPw+dm$LNYr)4;qF!IV)F*A#Co;W+N*?(}Y!c1~rxdI@g62|PN zj$I6MYtCvabx8>vxaf^&6U^1#~K%!0!C^RGO%@KkN`uflf1EiFBmku zly#TopX9x0ww_$jcY{i{1bdcHl5^xd0wa?iJpNb3KR1Hx*F;i8c&I`9#Kou~doG$& zX(VT|^%7|DlIt}*-jp)hrXCH_v$-QokIkRkbboy%$2)Z9>THtHPYZbF6PFBZ(XaAe zG08A9!6hg>ISg9){i*_KBu1@ILBK*D&b-d)Y1IHWSt4V?grcso4c&x8>ZUDM-k|A% z^&2PSs!3NJyL~%?AruICyjYfBq3LTG;rdA9Vh`r5s=^ojh(D^xhua>)#s-|==1f9V z->zqEp8UvMPK&PBCku`mf(hPZs0wW}ige&d*-;a_UF+CRH%TAu#lgZ+RX2XNN!z0= zq4!E#++n++GTB=tGYOBCfL#gVOb1IV{k*b znhq12#Nrril#i{4S#VfIrgDW2%gUCD4Bf_lQ4v{A-8bBr|7t1DzW!CrD|wsmPTQj# z(7OCTJcdI|+0ZlrX^SEd#I}9DJNWO%wN>}#9^aVuw#D#P13q?Z1bv_B3u#d)O=|)| zT6%INB{ACm++ljIYyTibbrd*^g6RcAis$&LD)ytz$PI((6D?CJ$JyyFt!y0+Pm*}+ zATtdLg@t;)v1-0hr=6M;f>G)pcE>|ZBP1Uxd2l-$6oo4DYvGHTS~fDYA6nF+NqPeg zGjRIVYcul5KbUTt*OI_xQD}u`5rGR~;rkCZ_&ZhNQKj#v3X+;yUy&pTZF!2F&VeXZ zG1oQqX;2>7TxPhw%H8$>;fjL3>x1sT>BWKLMz<>ELLbi+OU*(k{=~6*s{JSg8T)gv zqDIQvOsX?+Je%6=A+lNB2gVRw%Y@e_xGqR|QWGm$6^5K1shotG55#CA6RIs-JXyOGYd?wCcT@P%Es+<}Sqlr8V zQZ#!0R0B^jC9YVTU8Og7Nk6MTazFxxtMqs{dT#V4rUFPz z&d{$Dnfkq^5Twv~2RD>$a1Ex6kA`#+0Zu>7TdDB&FyUBTjhRSc;3Y|Z_M1t+e|S!r z#!z`-Ondq`jIoqPeh7l|q?$R4z!F$XruQ3rTll)6@$&rryF* z5Vx#t>Xc8Hd`Te$BRHPS>Q{;mlP`AvE@BN=1%sMzhI zYIUKj?T~BF?MFVl!;M>dzExQ$dafYUqFRdY5>p|=&Q!S?*rQCpkfH!{T9%2tnS!rO zT=~yt=D*whpg(dA1-Y$uhfiMK&HeEAhjS?w|L~+}k}&^~@5(%SYacj$S>>y~#OS^q zX8e>YOtJ^cX?(XKar-L5fYpPV?{L_|iH_h_@T+?=bKGW~#&0~W@HGRGZoX!4g6pAO zOA?ce<2=|`VPg?kMr)kD>I769kx->vgEN1 z#!ly$9S*5W@*kk}<=OD**n~1~w=<+`mQytNIfK|M4KV9b=I#4&Y7~7tyQflqM+O)k<+H$;89+UMo zBV5^`8xGvTdfQr}frM&8!MO$fV{bZwqZIW8lj*ARrJ3$$@Tm_5p2t5GF-^_;X7x9q zC*#AXkT=0-Gn}>$s4<|E+If;z*hFX)+q(@K6J)_$9QTnFj)AHyYjWl33@e&*^K@pJK_&8 z6~;y<-f4f@W+SBz;F%A^ri_@zugH54xK`o8h1#FHuyPde^Qf<(?x&_vw;!%f}Mhv(P zV+n4Vvv7DNsuNX^M3Pz9n}2nv2FdoPvwbOTfB)oDnyLf5!hA-gnJQgN?!5HZ zW$eT^_6dIRxMruo*7Z1-Zn#8P>*__;P0HcI(WQMqS6A^vljp3^)&Mul46f3efLJR< z<^9ZlhL2*Yta&eQWucJjblj-X9G3f63vp-GrjrP!%*LxJ?3mQ!=*WjbSTy*i1*WNpx@4XQ5`fbp@nNX--QMc`SMfN@ zo;|&hkJ$#53Jq~(nuh5)_Jn4%$e7w-c>rP%dq)SXv-@gYgXzAJtYaX|Wp)Z2s#EtR zE_$;z7tb#W&>z4vN??CHaKBj=bQ|%3l4mVITRO;9o9%a>GWYO_)n~ z<@$>q9{=z-W>U(ms=FD%4okUBi^Yr3e20xU(`AYKNRCp-#69+#jl1?EQ8&C93hQI7 z>+|su!cwu=2uS~ z7D#K^?D-e>sd%94tB6X^jOmgYCExrwFa%1oSx^y*uw_qih4N9O2B)HA*|a}5R&xp? zRC7AQBC=gY@O6Y(ljA@l&G&C}{=R4#FXw zuU?q){(C!;Lk!G&*)}N)Rjv{a9B#BDmabLjA8>RQ-Go*Re5I&OK-1|wOlL|lu&BDc zjPLk)AN;1%!0v-0q~<}+x8sOAZ?+yt$MpGmj5vXEhu5r&xZh|>y#F@D$+Rpu(DPQt z?T|35V4pk+esC_qkAOfXlo|gx(5*@`{Qv7nbyges8TpcG`S$UKZzdPMjdxXypQLwT zoI`?p6zg--9u|2dYWf3o>T=Wjw1Ge3lT?CaV5;O1e4Y}T=&cZE?`x+wN8cF*F%AhM z2Rk>x`+{s8m+qm7!eN z#+iuA8_2iJX1D3q7*~N2U56tkDUL(iAW%Z4d{RM6;LYGkSoaM6M#;hJ#>MbzRujeb zkQ5$c%q(14f{Hs2*!eQ@jmz}~_7!tF<2EGWu?!L9+Z#qIaZ&(+M$ebvSYdIERo=~c zt**=RWZ$G=J(X~p`2?~R`@Ed991es*-9R8XvFr&~I{V7)RFK=nff=yPl-FyxuKV5l zo6u}$r7D8&V5axa@84W%GYrr9t1D}t70fBbs31U#r7Z`BWouOxP&97T1Oqn*gX*9k z4;&`{;rSXF(1Fj_A0dgdxh(L`-2uT*%Pf>}GaWi5FcqD9e9Z<=L1yx^~{@}Vd_&>&`YIZ}0m)r#3^jYOO&ARWp! zfxv+{%py!r^(Sp8>T-nsh!VUC2md1^Y`2H?2+VB^*31c+$|@N*K-u<&Vt)zn{5=~x zIPgbCWY=j^(-Y&!CK?PkhNr=NX_3a#W&LQZwwWu$Nt#oV2GCPAF&_AWeeIAhU(h97 zz#AdsH=~7)4^$u?jtVm!^;l2t2QHp9gPLNJTk^rhuZ-mT?%C69|_X|C%d^dmaoU1hp_Q zdw3cg(*+7K|C$x{J?eV>dVl)Kx9&AyCAA07ip*nb?Z@%ckBG0YHVVvp>rPi#XEgrK z`%Rxcn8(f1X_a>$#V20N`kNhrh0?fn@JeFnp~${^Blp>U!3}nrBCOwBA)8N8(6obC zQ;6<}JG{j9Eqn}$%+8m+_c0zGVNQR;cZ`l z&v!kC$$~F=h<5CZ9(+nJdWT;`H|{Q!Ks}zzO1j1)kjNDE?-BY_>l=?d8YsH}HK#9g zKOYc|L4f zpFA_7M^VX+H`W}r?mTCqxP1Vy0d-jx_Fq!?ORhawDca>+`O!2u67`=oAep9=A zX(W&`$#XzdOTfc859{b^g845N^wb0@FIfvduKIbmiutN zE;y^}!Fg~vIO=+f9m(bKfaUj91J{^I%8WIR!KJe&Q(O46Sq?E>bhmpZXZ(}J>?kaH z7&ZsnW?s!%UjA4kU{P{|HokkyesSOIK%Hg@SO5SnDhRjR}NADX|i;P_S zxQsfUw=$>3shl$xS07A&nR|Aq_ zN>h47UyyCWaw8YVDk_<9AJjDH{RBzt&e=Ofx_mDp$Nl2TYI0|)>p?cY%pEu}d}6>~ z;<|!Qg6p)sc@a2`Ia@;}yxbSu6)Vj;XSZ2y&_`HgH1JO;l{&vxKrs!ddO@vPN;2kO&%Ta~z9OfanGO77{&HT z*Lj!F=S=?M{ZtHx^(J2K(&{eq<4SSW0@Lin7OK*=?d_Q!Pm1LYqsYo+B4RmsmCnJh zGMG#1qhAg$)C{le-}9J)U7K*Nr*x*n%kQ~gaJlzH#+=~cp#u*YKYx&Q^ zUIIs`tvTOa=L^C8cKW<@V%9uXEw@nAW0du zsw71Tg_wiW&0fN)Kn{bLYG8>X`39?yCUQ9WJF@&Ap587Hvt`0zX>b3Fva?SbS%3NE)rKfZws70xOp-FM4qVxdDRhB)zuMo{NbG@=fY7Pu zC22g)6yasoPE$JU!Q#+D?%6r ziUEt6+RU{%*B$RIZGy)uq{VbmUFe&hYl13RZnI?)byK9~lb`OS0t^64s%Q$6Q$ zGpFg)1$r70ypq=XH2c1H$&BWZB_la*$Bb1QsRr9y3JBv?8T_vgxk(Et$`}?r{P+6?<3Y#Z)?m_r z1r1h9D1B2jl<_|;-~N>p#Xnzj-7+@nI@{cJT_drcMOr7-9l??6lINiAy7!|UzQ<*L z*8D#IYp0d`{;;w#+Fe>O*{{)oJaTxEP5YuRz~%W` zo|YMSwXdRs#cn#!;*0nbpgYtk%3WQd8YY>w|YuCw&e@xK|0?^ot}Sb{|nya6Tk@fMf9+ zS+DXv;c8CEJ6)vqRjwL+ru428IjU3js-^Kgh7=u%?Vmd&yOM+8YZeN8ti(X`*@>tX z@`l{X#(F@<-aumWy=lwi9g&qGl}46)OIyIufCP-5h_>-3K+T!j%G2i+qmR&?dd>tc z*@Rp8+gz4&p-7pMJ`LgeEUluU zCJGOqC?>=S-Lg9M^hmb%7r{!vC|W^HEfEE8nW;d~Rd)tgwf$@>OsZ7(dbN1-=6rk0*m6=m#)p8lGtTj98+l%@p$zW zv&*SF$dpK}ve3$Ajor6;k4Q~S4#nuTn7++dINYE4HW5;tMVrgq|7KhC@c^t6@ZMsA z0jysmF^RBWfg}|!ZOu&*$~eBE5x;FffJX6=VCMH5IS%+c^?cFd0yM4B2 zDQ=wSZu?K)6C_-yd&Zy>H=54_%TlptctLPy&EK3^G$F^YMYxq1&(C~ydz^Xu3b+D7J1+K>67Y%F^ z*Z2=R-RcTruaBA}O@bP#gYs^8XOE^}m(nct-lfXeZaGiZW`-0iEE(PS^FxeCMIONR zbvdB~Eo!h~OxIZpU*haE6rbw!%foTMP-*r)bQGnxv}B~UW^`o>KDBl}#1naR+|6-0 zdjyq?4k(8@C-u>P?Ut#}uI2~acKrPnPV4@rr8;GAJ8Sl6kesdiEGx}toZ&lw8N7=Y zODz{&Dw8xl6le6}s6cAp&$S?~$z$S-?*GQ#dq*|Zt$U*Z0cnDuf?z?KbWplf5h(%b zO^5+$Qeueo8c-CJCekHzY0{;H0HH`15Rfi`5CQ3gPU!e8-@V^`-hIY7-`VGWcib`V zy=VQwSY*v-K4s1|*PPFM=I=3>0TLjTK{xVozz?j8e62t<`9x{<(G!&KmbCB-qmvz4 z07k;}dY@9C2Yjv1AO$){>DUwt5#ccI9RaJC$Soaxi-@$c=kvnKHy)C%S#NMm>n0Ti zh>SfA5SnvtV(=K3jHd4=t>m44t@24^iFSGy=FVQY7BBCbx`0~rT$USgJ$D2k5F!Ty zy1Xo~ONg2U(k+sH7Q&0!UArn5yI$syZ)cD~^4?dLX>Z#HyiwHIYMXZji4lSy%-p7?O;zU zriyrqa5H*lZEG)f-`>l~*4|L#9<7*}lbwg-joWv`Z_$cr+B-Qodfbqb1n%!SdARG_ zyQw1J&k!#5E*>{zX~oo?o_g53iQQK{lCz1CWuD?2qfWyuU9pKtxKav(z-SbU*?0c@R0ko1EedB_#y~@DvF= z2T?FlGIQQmp}JsTeU{7hqWFuLENbq1<;|B22R3*lY}|rrXjxbsD{W&+ku(-6mxwXBs zOWNB%IQ*>_8R*R4)B^tghk5}Y}^KDS$HI;c{hKn_J?NwnqtBKmo)o_V*jQW4n%*33~0PFOdw^@ z$?@NgP@H*t?d)JMCGZdXFOX|v=yQ2NI$BT(Nl5u%=k@7HIHetjO(g(Vtr@ibJyZDQ zs%g;n6649yMap-`@cvUI=Pyu`&GQPza`RuH{v74KRectff6$VDQEGPpz+m6~0ujpZ znxFk%{0p=&$Zc?)>cc~>Q|Hz~lfCdKH zq&Lco902gE?Qd9a^0k!dC^v$^r*zo0at%3o8PsdgEuP&>#t(u$=XaE~KwHtlO6ZnXuy4LUSZf^h*gnO-<;0HXfD8hK{vep&y*>h%A-h;K$m z*#UPDOVg_Pi1JRN#g2IN!DVY;BxXDjxNhnX^%EfpA|2kkex@3g#5cEuvxnbif6Nqp(@uPO zcTC9J1s?ySn+KYCcwwj}QxtQ3%+&GmIag|lU!X$D&)drXzK-p9J_x%q?2#!N0*Nq9)b>p0R*Kn4~fQxu`NRgkeq!T@Ys^T9zADVLVP?Rk0gkaV3yzY{Vh=utL^BDlMI&bWyZProwIH`@GzckhSaykDohAFiR&+d~G?k}sOn zRypy8IK1h(+>`lO>u!eiHXr4} zDX#W4{3>&X0bnjR(gY(nQ5l9gl6IXxh`=Z%FWrT@XpTuo@EAyLgxRy*7bbIE{jIV{ zZ??ifNgMCXycz?I-bdnHDE$%q`SV99fVD3Co3-53Ypcw;Lh|2e-{|Ii{3qY1<9TW| zuj&=PWHsOZ1!`E@|Hi6%j`%0_3$gcD@E^8zQ?IEqw*jbiZgi_Zr23O{isTo}`J~q; zHm@l}E{oPdrkaj?5{<8^wtXQG;}y5asM`Sy8Zo6J zrjA6MPe^NIvD)(|*E2m8&;3zH?SE7UY=ZKIsKweO7%p8rOt3pXghM8S=A^Khl+imW-qvOuJa$WZbQJ7SP!ArzrnPHFMom7s>h=UM}g| zi2V2WrvA6ykpF6<>#tMlgV5lpYuu;za1JK{8oxkUw4lSOf7-xgkoDluqGkbpgPn97 zvV&GX3iF@o^hCV1JUgghG8;_=KFM~SVWeG*g<(EfOdyzB*}1!}3TrZo=X{dTXeRgR z-!#>&GNG+W+Awm`o=>S;zvSROkcUw(jL)@*Vnmxw6R}{Kf$Fp*mx<_WAgA8 z&^ri`n`||Cq(xZq=joBqq#Y{LS zZ$n6@n@Ar1R{R%klt_mx{$eBD&#O+WC^syak0%2x3+{MSy_m}q=cQ93YFDJz!5~+w zE{-wID`Pn^((NXSSjf|5T;B)K^UbcGt*`Nsa+I_!)0X_qTkjQY#PsA{I`w04|K$a# z;CQ&9&bVsg-svxpV$)8T)z7Cxx~Xt)C0NizebO(`;4C7!#|Ja391^w}FGQoM#2Q!U(GwR^j@Zd*x@VtvCmf2L_K zQA}(Z=o$v`q>Y}$Ec#IuxtBP-TW0lR$j<({`uV$ax?bvg*{-dem|K34w`WTQb7IkH zZE5RSm4>(e>HGbctS+*0ApSGOMZ$~<`e%EqttyqG^2TvaIPdo8a8nerSet^SdP*Q& z_D9rRll%H06JVPAgUqscyI2Q&r&k42(7s>>FvYMsYzjH`YucA9`vtnmvC)?pwDa&( zIA|K;dU`SFFXcFvPgxI^0dS$^rsMZP|E@}dlQOFVC*WaW(D9p~qJ67{B497I5SU{D z(;50DVE&*MJ=1x53Bxh1L23w^%Lk&70Eg@r=V{q=PDi+xY*?J8lmljAy717q9IQHD)^7g&LHWZwC8AGA{P= zxOaRm;x4#sf8(9XkC!I&D;IRNp6Tm2qw;lut%V;v#?$qe9?E(08nhQlu9!IG*TFJu zmu`1nn!CRLPab|U!_RlCrL~`a9c|%Zs`M0k5gbHIQT+{bx8q z6a?OYT^Xr;0?(Yl%FqE%uEGi{Xaee#m1quEiEyRAK2T3&@2dJDL z{sPHSMZb6C9~e~rDUug7))sVlK9jLz@h>xRTF~rkm7UBNj-X7crb$FrCc|&&NToXi zO%6dEPE&k94%>)+j+A~@OxQXaX{+*n0yvZ)m9Qwi-Aw=CD^#Ah(Bc*I7yX8cpZv|{ z*}CU*X)l>cUb}M-xvo5=oj7VrA~_!x!gC!mZFmJ^3k*}{VpHwug4`#gCC04m<^rL2 z@Po^~y&0=7X5V{=aDZzzmBM&F?LT+gb3dCQzJHrDl%m{d?&suXqO~w%S1n#3c5`MT6m-9 z5YC$%Ed=)EAhs$ib{~gUC60}Tl12bKt6(1k-n=$51tZ<=M3*2W+t8XfMcSOVdO4$v z#m_&>R^TQXx>%@fPYIda95V2mNXVO&;VJXkT2AW>vm8Xdl7c1nJ6z0V13UTW)qY4I zuDhEnQU^)}&;vN|(aig=Ap`3>Z-_1d5)QeoP9M8&K#Ee3hVs8ag3ro7u?*%|8hx7l zEFTc{t^K<5r8JK+r*E-PjtWmiVE(h1j>|fc=aY&1M z<;<$fIzoHKN25%S#9%Zvodas<3itT*u*vQZp2*6IN5l4DUkq&+c(J5-aK*75QE`Z? z6#ma&gg@7D{Ac7w=~}JXp_UKCu9>9Y<^BqP@$MGZHFfuFnFS4a!mvk0;7CdArj^*0 zPZ#zYl=gav$FeJTSMS)k%6GfiIeve9?;g=I^{vD~`VJZM#Mc`Dw&MIfx0_swJwq?H zX14)9ns2ltuaf%jD%KzKt@|O@lMZZ4$gF!V20O%0e)-Z$&dln31XK_=`kaepoBBF; z(4BXwVQ-?{ju?|T-ml+{5Im&iw`o}$uwWyzu6P}bl`gEohdS}nDy>GH8$aXkPj%M0dNb=ojzQ- z`_Lp@MKbnEGVQI;Z$fbCvyrEE-zaRRtk2v>EQnu-xy`h8o#4%pONO{jq<{5UZL*O2 z=rh3oh#ea(%wg{0tV@UqrMQ1{c<-vi_RZ(qfbR5Gh}18-0W;i_ij8Z^TI5r%`jZ&fnCo5*D4)&+xtb0DQXF zb6gH69jd}p>XK{k`htz-)nP#GaaX3W2FbVnCF{h(wnTWI^Uo81p4GS~pKo7vX2kr+x}<|v0YgEaN);0 zcP}s_10S8<*Joj}ey8x&Wez~C^3;5wu>(jm|NK*bW$#bw|3K`&QQxv9yY&lXm82YV zk@D3;yK@p(YBhuEa&B_}0(sB%FQCX<&(%-ejUaA^k^L5(1A&bme2z)xR^?0-pd2nN z1n8xkYX8ui`qLNoCo*oI{y~1~n<;#2;_G83WTWeiJKN>gXNh~Rhx#nrJdQcyoj2+d z4AklG-W=OgZ~!z1WS4BicQ>Cdzk45jLP+{8dMo1gb2ZXI+w+A!a>dTS_Y}gLEGi648yBE0fn|L9Y%sO<+mb^`Df%#0_Ev7Z4zr7#g z>fx%wZgk0)E$%+ zvqo)0bWijUnhf!qT+%J#Z{$S8Z*n<(a$)f^cL2TP)`BnWS*;y6^#l7F^f2E@nt!7I z;stbbtpUv^V8G2De#@H73sXC*9CMAItcW7JzxQYFJaY2Y$(R)u7&8=hGKEd+f;S#& zC1T>Pw3*tyd$UD+`8*I>(d0wRo=fh;AIs_U zmfO5Y=bmAV*lWB#tY9yB$`Cu-a-F3ixZem!ViMQ)987V6O%2PBXBTN%Yh7z8r**Q% z6=%+^6?CDyV|P{g-Re5Iuj!$khu|2h;OYL zn5PbdWX8e__ri~n*P}9hV2?IV;@NR4W7UaX@-Fpna*s47q;fC zp!XUdmB$0Scl>?KIV*f0Fthxf+ll#i@&a5o@<}FmLO5m-m6mogmFE69YyC~^gcIt% zqj6%0>3tCa6S`FCK|ur!zm^zSh=i%1EgJXl%2{{#7P#dWVbPvDMQjH{ioEcEvF^GxlWvQw~USGyxg&GoYPSE9V>$$|y2^S)gWnDczNrupA$*k(ZP)o)#W?F41 zPWAX^E%jslyUkO)k-_3h*1cCN>P$y!H5M-UipAdF?o8-Af_+56w%wMkf+a#&}M9 zD!06yr!aathpUjF@F`HV5&YWmy@-JF%1_eUzRso`irL~%zwZmTxZ zh%-O@8vfxv4^yqU`0dn@IwLKevXJourKH^@LKba~-Ao)F>RTeV2Zg%SB?7+tGP-?% z8!2s=Z3{>@Tm4RDy3dSBhoxB*o2^PrqFbS&GxvJ05d<43C*n1-3enL(;gCm&yqW&l zGMWiwe(xwZ6+u5*>z$xHlh!6-+y9P$prX(mL#?;Z{|Q`pY+a*CMCggH@#Y3EcWT4}tCmzD(n;P=X7|zP^{Gxp019ILUgPN8r;X!VQ%*3J_bW)h z?eAgiYs8Z0CO%;6=cUC|WBBKv14cZSx^)Ll_u>O~U*+s9j)@en9v&{37F+8KTja9! z^x&UCNCEvONRtLdA+7z8A4G&zEs$KPgy*o0{82}_W&vM(GcQxOu?DC5<5H&g1+q_# zRpj0+yu~TUjUOsSJ4_BD#(QER#BDTj1rC5zmiPFi%$^P1(FxMts7@1KW?#iM9tOAd^?t5C@FBR-b+$( z5o?cCPn_Xub&cB6L)}hgV9>E9iV&|@+*9ZuB%PuqVVZmK@n%H;3!`C`s!oOhr!Nqg?5WC$xXwkTT7DjJ;f)&d8G_bOS1 zd5Mz}Un`6>iYbTGVDiUxl>Kea3C;9Rpo#Ke?BFyST{G<2BOp4pFc%_8I`j38{;eNB ze@4|T!{ora;U#=_OLggq1(zY44aebe&Mr)50h`gMlsf%8=(n>iQ}P@6QRkNT5hh1Q zIO-{5AKn+$nlx|Km<1D~TFT8?1;5MkU6ciDB$rli>p;{odM4Rxyt1`!`3pZs$Ml|* zmSnYQZ(^JKXG$dQ4xume4WSh8L5QY$;+I8O28?ULY~)&*iS%FE1T1x(jH+e@qi}*( zr!c8pRfMU9IwU-|Ct;SqS*WWgkw98aIVgol)ivfd?{{tBJ!T7aW>hFY)KtHPuEp?z!MU%B1Ua%I)-~7NFdo#m$Dy-zJ z52kahj-`BBhw=V^i074Fuc`U@J7Q(0%~!$HZ&J&ny7>AoU%qyZ20W4`6hOPaK38$@ zS^=5rERr*5B{_G%?W^FF*%rl;8${WdO-U?G@^lIL`A{rhb4pf~c%|ZI^ttCs)~Rlw z66xA&LvGsriF-%2R+BV~2N*4p0|D&>4HV4zIujR?EI z5A9*hy+;~CH%D9HrnrZt(=kR~vutWm8Op8HSiK?W_1-0S&79?q__P!kWvRN|fkntz zqvXC&>x$jY8f-%%)bJXY{gBAbS_mwe)z#F_kVa)M0c@RWt6&WaJ< z`D8m#g@n2>nG>v6%DUZ96U^Ca^A{+5SC7iEazA(s{0Tc)JQEA+DnqkWZW-G;>T|xU zwb2AUUI5vlT8v!%t?WvQ;8>od^u%4MNZ-1NF*^*rG0by|b10B&>D&kDtQnKj))5gA z;WbZ1(H~W10Ir}ZkC#a^?+eSb6jx{J?6vpO`%>oj;w4x3dVn*lpA)gpwrq{MzD53} zR-|P&AdwBPpG(Q7=1r^VgHbU_&Y4ScQI-8ypF?`*l7gjU?ajTOdPNyTP}&$rUcD|v zDO=}K7`Uu!wxv4;9l@7YNzDZg7#`{5ZaXjeN~0@BJI~E1eybJ4;Jre zH<dEv2Z5z#<(u7IL$bud6?(BDKMA3eTaI7k)T?J?&;?zUqgr z8Jawwo%h73*&ZHoAs!X)SX*u%PG6k5zpa#%#fOyi9@n7;(|8#NAk2eK=CglkOn|oY z7Np%)GVHR~FTbifuY!pN|>dK-jT1+L^X~8vx3s&AMzIvG+337 zJb^raB@Z??Ur(3oSlZ5fWS)2s-B(kSC}7CVf#MX`;MA|^;CUP}E1a3iEXcjCqVx2? z?38k2sUde@^^o;uHs9Gg!=Qb}_HC%?N_pRY%4}2cPQ+y^^@h`-ktd10re9TDFW*m} z=A;7C``bK~5HBJMv%YwVsxzK5trFnf1gkZUnH^N2;36iw<(CBcjS_SR;v0Ms`_d)I zGIZaE*_pA{9_?P6?uE8bouWxsw_$_h{mA1DQjUwmkU7h|fXLj7*(o}1c#LuU zV;VCyqnE+XwN`=|+URZ5I+(|3jx!kJo z8EpvNiRzK)TwXXE^T?zuB#ue-dErC;C(y|fRm8Y@v1eT#AxT;AAZHG?I+bK5!b?mO z2vYb^x56^kRaFLbr8Um|>>qg}!aD-HUyLl0FTT$P+lBGm_MI}wc&sPU)AOc_!7Qz& zM6lh+Q(hHy8nd5~A%;T}hx_8wG>5!Koq@dKnCczufaTbt<6^qZ{Vu)ZyHNGC zwQ6)+W6IRTUS;L@ju1Y;Y2V%<-^s7)lwa?YGfRbKJC7-b`C_oN;Feb5tCsN31>%%f zURY*dJg`#cv+_LfCoo|B@t4*PDXheGykUJS8hMAF#NqE5GgiSOy93h&Qtfih@&O-- z^D+0+&6B#fFKPL9+^$!{`dZ#Yfu(cC#+y#HHz5smIMOnIpSXUkpH{D*_H+|$r=jdy zw_aohLz)!1RM+TC_ru4Dy*m@=TJi4Ufe&|Wwt1dB#6MT#qt(-OQe;N1@AKe~cu-hB zp`zE~SWB}58T-8kR`2pN0ahEYyk)#EIFrt_8Z4RC`qKgUe@SoRIh zoNlc6y{dDTs?K<(Q?=P<@0mbLWk~f+U7XGhWXd`8vcSM7+W2SMNO5jY;{*Ykfc7gY z=rzh&ZiqA3#y*ZjNMI+(^vdwR{Z`6lvH;5 z8n2yac9<}IoZB<}of4uxQSmy)`#|!?D(L=vQI3s;|tK30y817Qi$KDUSZVok+q)h()gZ~;>DM36o*e$L?HS!S(00q8tMfpu2 z`LOVhVc~j*58C#(Y%i_^v5b=gNaNmaXTX=g%!)RCsQQ^O3@@rq^Ms2i0MSWK@8&M1 zAk>1Ip(j0N4J)8=AVsBD~(Fe z2olYrOjwoZwUrrPGvuRxoaEftc_tg~DXaKiAFZYB5Y#+=(kscAQ)_vs+=QraxZAB^ zG<4s4EA8HQH5<*kASu_U_g*Vm_xFTwzIAP;ii2-l`sju_;AD;b#Cqk?dmK7t#ore< zc2run98pCU@zE!)_3#1a*)j?rm6}*hc$x~GFlnSyE!cpLb@+HnylVzsNH>ReuPK{WR1a4bt@!uKO?$U`Itlh%Em|(k z304FE#qG~J35j#_^7>%25>cf|fqS>VF9RP3i0){m@CBjwPxR^3KVQE}PGj_iDsf3E zddDlseP|dyUbSa>>}lmU!n*h`z$K7bY*1C!nWnbnNmD&`o!baRw3YyapyNN2l39L} z!%Yas(WI(pG=`i zMMf}4Y4vS1;)P7CGppQu#7u+_I&^d${V?{h&kMr@Ri)57^TvhS&3GdFEQ5S-4!ePA zgDC^t9K4}Tcajrsr` zf23^#jBetC%kr*Yx!A5%ci=%!0vNDG;4a;Y!d;B?scXDx!^k>DHzkg`W-vj1MM!#V zf0$rd?X)s_s*$RFq%i5Ul+!xh#O$BrM_K0K@-xC`&9FlVNf>6h z>L_B-x*}bLtMe&O-S+wRZAx+Q4bEB+h++io*d2e$#*>SYs7%M8t5YoUR^#AUywQBF z?C{&z2p7eKVbPMn4a0#Fh$*@xQ29k&Zq)MllBF2>b&Im|0D`@5;el^y&r%mTS6JI} z78E|l)1fI0Q#0LOK;hg`7{3@NAeH={RakU6n$ecEK}x5Izk0~hZ~3X(MzramM+TYL zYXu`1>ziW%SENY8R93zMX-vSwZkt(?#qRN4*HC6p%lAB{1}+RN<0?jhPW;YT`DS@o zLw)aj{O~$91+@k5*T7rAJr<86-8ZC9c1r@+W-SLxB^xYZDSO&c(sTJ$_34vs>tsh( ziAA-^&mG5u%XK4rSe6N>uS0>ik)}suRuBYMDb8`xal?NLWx%kHK?e%7~LzBNi#eD%E_9KH>?kEZs`b0Zf z=AibR!CKJ4@WR#l36xoN%0%_~?A674Oo6+yU1Bn#_fuArL@uzt8~8EKw2W*Yaw!`cEyMUT_8KuBT(o}cvLYZLMFRFpnatB&2$QP6gHCI$~2;MVL~xDv-QP*ZApNf^}ig=bFPvM-4n zuXb;x@DX(IEFonT-fn{B8ra_gt9SJP25wGjsgL}Pmt|V^2UuHg)^D@+9EJiUUV!7Q^GzW@l(9N;9q)n$o)7xbjSQA~$zxLAiV`fAz;{Ykq0t z$~*?)D}Y9(zs2vYol@bappyqvBCn4`{qfFEFi@#i84klq%xyf|n+=eJIG5Yas-xv# zB-EOq<(400-r*V~pazBW=GS@fIX8|3De!GaUS&VX&vzi$7VX<_Y#VGScoQbr-zI#t z1S1enl18P?q_@HJ@}z@2Nb-xh?;&@?>7>c}*+)MX2|&%es#kZgLt_j6Cu4V})r?## z>%uD-Ad0(78bH!`>-SCIJ{7dkg zsHJr`7<%VtHMR&2_sv!7PRS!|!A8F&$>cSfq9?{|D>pS-dpX)q`8V>KN>v>E?LRd8 zvXbm~QIB|t$_cM~t_oNQ9p%f{MY>;X@-+06>lP3b(%L&YH(xt@nUrvX92W}uId*W> zD}N&!+PG<%ThKgHM6Dp1;rF&Cpgcg# zyU@q)KHgdzqc3NU{E_miV~@uq?Hh;A^^eoCI)oZlX6uIhbi173n#vN0cFvy9m#G(R zu$lRhRH%ncOH9HB>?{^~+{5tg4*jcG+r;>+i!9)T2+T(5mSyQd+X&EwL{EhxkeA1WdSpe%LP zPT(Jg?h}xrx%prq7titFh?w^B?r0a>e@lsLUteCegR2^4Rf0x!n`FUOx&#qA z!jm|!#+9_)N{s4D%)a}~N(P(7zQy2`#elPU_?0A>|3{}y4U#*OV(C?~%frcN@wsG; zBsLR@JAFc^izAOD3wp;3by4e^_r{gGy$?#UQA8;&P-af0xePZd0-wVC7SY(77E3hD3 zE$GJA@(Dl|dSN^0U5U(wC`MG+eJRW<$kJ#z8E+PB5Lw-KDds(|awQ;{40xaJM{a-qwIBaR3H5_nW_S>qJ zKR&45nw-m+mWW|Yno$qetT%C=v5yf^|6%{u_5`BKUTJ-SPTe< zxC-Ed5T_7n7&DonbT{W^-4x9J9m#{OfU>!=bVy*|;mT4VSM{h8C+}3r$L|l#d5^wN zepSWcky%gP>v(f|c^!2}v2VGCk6uEiX3Gl64u`1WHgq5jX@}TktqjHCv@sFQgCo)y zdZdo0;Zn5E#%iEQ%26PpLsch{(5LydH=c^O=Jl6IFgG{&=C{G*XCYy_oUUVR;AVXz~{J>PJN2$Ragp0bNcr;KN}D@YtkfA{e>-Du3`3(u?95!?bV zgb<~Xbr&^byIJ5198b>QSAD#8BURMtSpQi%CL|*@qe?eWrz2;ien{`0vkJINRkIc< zIxruZs(5E6Be6ilMMmo+z4WQ1eE&JU84+oyl8_Hka$+<8(Ul1w=6N=fX1~Y4CoT%3 z3fZl@E)%-LMK!u<=0e@#`F!w;4JmqkV;Fz+wXX0IDT85cC&9!m&kH&`7C>}CU|HU# za*GJeVzl1KJ3C_`IbY!iE+sl_L`3;2@uyqMk63M?Nme6h?bIc81w$n(9V31Y}%>Ly9P;{OT8|BEWnm`eKlyZ_@-zB1_Ygt?C2iCl}65V6IKnuf4xK zK~Rt+vT6M8kS&1EvkMWV%+231kk=GTd%Ze-F6bCF3Jf4Uo^mHcxle(;~6#()Dkzls9M$6HWuWN0)lB)pZ?@&;ao8(rm%r zHW0rWw?0>0r;&Gju4b@a)!m-~I8Wv%Bg1u4vcBrVQ-i5Hl54SKg(QTj2-UcRy_q!Q zv1PTioRTscO2L_zj8(b0oDlm)6YGX_zJApBF6U;kbtGRJJ^nH0xby?2PRHuYdeUdV zkg}E(tJmyi;e6%8aE~`tUpyxqaWd+fBMP6xr<3IU02H3-7tPt1WZryS=7n|1dsph@ z!yHM04{m)k=I-9zM-zLICTpc-p7U?TT7oDMlII|Lqq~e3RXu&F>JMkz5l(X1EJLU5 zb3!_W4)il^_bXpt zN9E8R$WjSUb}!OTP3DRhc&)E4ffenOUO&QXU$)8H3v(Ln(jwu}a7G>UzEr`|l<=?= zQ5iC5(XzI8WCGt+RGOcM2(5G45-x}gyCzIx8yzDaC-hNstH}V#P#xB{8iBdyihsU~ z1G+S=zEAGrBY~mFLqTWl?4Je}Pj?L}dYM@&T8f%<(6J2iTC+-Y8e^kYIu#? zfX5+@Il}DJFZBpFX5ryXoUn0rHw$^FC?*S5mQ~S!O-=0T-QQ8lEbjda1Z|nuwGtQ8 zJFi4-A6KNuqE&unP$1&y7l?2F8w+EF z+Q~uF`f#JXVAh;Ou4BsU+q93n(tZZA|IepT10g;-)P8 zjYU}hRwe@j5FfuH*aM(y*clWP*<~LXypJ!|D5R%nY|SNyusE`9cD9vK1!#^)HsK6) z&KlHW26xY%^o7?6)W$vh1qy=}UZB9fyjt=8RPCww^@B_4*W3&~Ou)q8{!K#u zQ|T5-Kx_wkN-mHnv=h`eG-hSx>wCqtPVeom@|DRYRyUsvy^VH4*t~hEu)@mSQCRkU zqYM0$wnz68=&28y_1)Xy7jqicMy&cLG?Es&C!ix!g$tJ`1wEYFh5Tzgs|nbmzNQUP z6Vbj2`K!AnV-YSx(}5wSkB&8lc4bw;g)8sOmn*WHFAYb~(|_t1NY2&A&cz3m)5mIy ziqRje+{@OUe(AKBI?3%>8ZLnEfg|yX^XM`T2i<38qekEoi}1M0wFy&w!U0ymoV_gS z7@Tk6V=+T$pI@6Iw4Yx-eUgEsaAV%O!h0c}=BAOOPUPfy`7z;a;xl(d(BlT^{Us>G z>r{TJaDH3<;)sH?wi;$u}+ zZBkl6PRWq2OCsUx#IRHb`%8o# zuw9l{Kfyg3e&)n2c_fT!PvO#U9=>jmI8oLc4FGl>Xe^U6n}Zy(R-_LlWw@3ygQsj2 zSLv9O18PfgyxZJY>OXGfQ=k^-^Y3(I4@%w1OWMNnQp-D|7re$BwHH;RH18SzSQiW^ zZ`$Tl_OnQHC>4RLCOE>TxIb-4DQa|7qwM5ZYF+cSFHD-_b-R4B^^U;$SNdMN5BXJ3Z5KM0U8@kpBpb#4?JlEvei(&Vy|gro=~F~x{O+U)Lq^bSFiqU>(yEk znU05zt?t9MhdE0fhDmV-fy>Z!K310kMZ-IeTCUBOI)!fqm7KcFt1$!a@;hEDcKbne z%TqENJb~muh(wqq)NM?2gH%x9cRw03|bHB?E@6Jhc z_SUJbGkja8?8J6YhM>Wp&oeQ)4()OEm>f1VAcboYdSrXiTPffor?s_Wf^yDOfV$K1 zWz?6=CnX=3<+vb^mW)&j#)F<{4rn(zg+;86k-h!g!!7*AE2K-_$!4j;xM=7tCiG}! zH3{o5WmfsNzBeyJ2&2pXAwMkJRCmBcfkf(ul*EQKjO7cvpc-q;=w@$cIZ~snB8c^> z*3(F4LQ6Fe?1#HIwmIiwxO2HWszN>W(fJoj9xHWqdBdBPsTSUa=~#ch9=Y`T;9CXft#^Nc#a6da~V&}H!53hx*#m2943vT0rC?+8$9SORAtF0 z|BgGUX5y`4sc5lrGNnrDK@DT&Iv_4Hxiueg#s%BQ3O&iYvChEOjO5c{-$7IG;+Rg( zd=75Zg`o@1#$S56TDlHf`MNq}hEbiCXJmu*=O?lO4>5 z54Fad46JIEVV@}D6X@?cFXpZdyA?R}P>cehB+(vCwRU61wW#5~z#WT_T@=(MsnWX= zc_-oM=AZ>I$dzWyt|&T8mll)|_6yw$m;Bz15_g?$`rJso!*!%&YhBHXdqfU$VC!2o z0ILh?`}+$TVhL#b?2&QzWcE6RLT`6HE zLYp6bB|`hd*761ONeg7K>D$Ml92M$$LBc}9p*lS;_ugEMNSj`f!iH#j8yfDxkuIYJ zY8Jg#M$RSbISRRY1MS@kheAa>IPcLVwB1`vWhS4aw(Hjhv)S__Jrb)n(sC@)=0?K` zOHXt}t+%szxtNpen7MTrw2CCoY@wFh+~gAY7+-W>ErJ!9G-5kf<9-_!av-$Ra14{9OKZ|`b3`El*@M+mIbE$NOPwe2wTMb@yt}uVt6oWB zXOy^4nHJm0M5BP^jJvNpD{dcFegoY*U(=eiHLNd{NiWiY2g zo2+j{;T}XWZ3seI;Ax52g8vg%=J$4LHWR_IudiI*${gKxJ^2}1=^m@?FKU6%_GpsI zD1>UhmiTElpnh7G{=uxtaD*qNgyS#BK-+p2_yXb+&RaRO!fV zcc7$WSVOZyuOtgg#qs7<<(iB-X1~bw`39%C`uuKBz34OQl>*TKyE%_B$w&UO+uEqT z!L=?WxM3w^av_UV@0_l<-u>aD{GRI&Pq6>!+#Vvku@imlJ$$SN&s#KQ7fqXCb6JD0 z;SoD*yVUoAbc8k<+Oj!b4mMh0(w(o6Z5u+t*+~i~=}~Iv(X}JrOOj(vR+ z4&Sbwui<^%WuAeS}gb1N*X$nY(00|+| zYY3gt;`h2w+xtG}KF@ddy=UKVf7d@VdFP!qYv!F|1jn zT}>z}5=@Vt^iyazp3C}*K=U@#ugQQPjYH5kHQ~-lB6HUl^6n9y+>NDn@3vJc(G=ZVBa(5t$w}k6 z<-@#wakd6Y;Q<{czT;e7yNCjh{GB^&X~2=foyLz?Z(yy(EEhd$G=Ctvb5GH^{VePT zagm>jDzGKb1^ptC^<&BA-8%o8(#eI@%$$iu`{dh}U%q1d%Pk%2k`&4|=T-*2#e0R; z@Q1?P7bY9y3YHS(`74KD!drGUWoac}`$jDm1Cf_QuUthq zUhr%;;Z!(hzw4f4V5wb^P^Q$${2GOvueorjh!S8lXN56j~; zeZ}I}iX|L9nD9AukfUAWh5hjj8cP!rym*Xcy)Ecx*20)14eK2(=yPq*WJ=P$Al^6LC-6SGTV7SavBV z-Ef;O>1BA_HAT<`N9(DB^Maj5IRd^X@%}I7;Swe;gI$0I_;!lB8Kt*CIsTYA%u%T z^b576_lSV;=>0h*)4XTSRFjJ7m_(rUKWQl0IRjc2PtD~vOhF)g8w-&&FECOm#6i@w zQfR6w^xv#U(91cC-5j#v(YcXhfFkjuRCj#q0q4ZeZl`@>gLvu(q20VT5eLXbQ#Sv7R73y`n4HE-979HF_KZ zvDz7P6Ea0j^T7ne$zrjUTMH1lA(ct#~e*YLEEXfdjl{_PTAW z=ou1+1AA*yl4O62&B%sYq7;4m`_hV5)tK{{uuWx3Tc_i1P8|=8Zjv~Gis#xa5_wdf z(!YZn6TjVLOQi$m;oS)G$|b84$4nNWcK*EmzA8>rf-ug7Zpn~B$#=f_l3LehEuwS+ z-$?n!DLaeZZg-}k+bwF(#uy@xQ2f9}{Y*b})-OcV-8p|Z5g{2HEJ+_-6ruvnZ@a!ec7o1sjta!1*u7tTF zB^0EIr%qwQEKY+c2x~0fsrxXfGqda^ECGa=U=iOy68+eIinGV~JJav5E=s^oN5sd* zj)ngdoPw`Fmj1cQ()XFCV69UV6waLvcSYYCW<7O@ZhtO}xCUSg{55KiC38*m<)_yQ zlR&a)kaH{PtySdx*0W)4?u@!)VTXAk+)k+vX>s{kdAoZ{ zyjSv%7yUQKZC<3H`8gHaBm7ROLwTdil_u&YsgJiNXz1*3)5!~K7zK}Eh2ts5dW<=) z1Y3UMwqy;NRV=MxL%T=s_@UotaIqO^vkMmBwicwlwHfavVsN%T3CM`YA6nGTpEUn; ze0xPffU?V(=Y7Q^wy~#~j6ELWcO}kzih9s4L)#fxIqGACQFvpFrU!Cw_2a3!08~%u zb3hvDo7tKgqx4zW^rdsx2Z8|XzY9ZK>WDWS%i7J-2 zLD1?9;3du9Wid9s9f&Bs|B+k>hyoe-gQ^n%Px zq0qMA(C6^rRLZfapYBRvw95Yej@swR7|y3K*Vbu0}oBFmM@x23KlwIZohe zPb;ADw$`WG^cnXsf30i%y>7&>>+Z4J99(3#>G3TWcAp<%YNN1zzf+B{eWhFz+Hr}l zLQ&0+)*cu=1j2|X0hUeQd42Uf<@ES2pmy>{%Nf6v6>Yy1nfkw1uHZ7pRJ93$?^}hM zvt;tfhaf1dsG;`dLM5>Cu@6I@1zy@u-#QV)J}TrJUF8=>TV*S6n22)ui^5~zFyjY# zP`ikVvt04VGk4?)sW})2hD{-i7!L0G2OmMA+dz*wGM-dy$anAX$#3#sYK=Hg`3z zKsevQr^MQSQyG#5%chm0zpi*TgXj&ouivzoTRdTG@1(6d7IP^Pb!WT%hN98a2k4q^ zAzg`j0Iik&E`X$L322)RNUz9us|l6GFEd>QfLR*?u26n9e_wH(+R~b$hU!^(7l2_q z%>;Ze+)%Jh;%&?Xm$>C=4n-rC3WB21shY&%L22y$D~{Vi|D-l2*A)WQFJo1~1qO>( z^q|)-Pcx~Wq3M*P_)G0VTkD!oas2WrMcLln25$hJ_ZQK@mbMf%x-oQ-?k|@kENg#h z9cq&(^9mW!%hdcpoAKcStpo6EIK)2Rxu*Y^!v4T{+M7p2(}Hq1h1K=ZN7d9%(a)Hz zZ__c2*vV&FvUXEg{~|*FxJ13p2i6PQVqAwqi9% z`ur0?vA3iAmMty^yxUT*yzAogb9dC78}!}EZ${uNbhI9*HfUR9AmZm~D{kEq zCNi0()QlHDOkEl~D!E3?n%hyJ@)u0wnpBRN%Ag=cu54wTT9jrjS=fXaUXo`RhVdlW z*1yheisagiTUn`6nY(?TZy`0uTdkBgDxJ%gzZud{tD`ZPP)7KYAsuFKZ+zRiMDvEr zV96=_)C#~O9b12`+}bq*)opuPkRX_rM{LQ6kXCM5hqhh`Xz3-S9eadCnE|JA-68nu zlfGROrJeVEK!CVBCacUcLLDL7#GlN;!O)`QJei}MJ^aCBby(g@!3I^QTHu#9WGI$* z&ae1jG#Wx>6@OS;urd&-GNxLlvXh7qN>km~2dMEVmN8T7>*dnK}@iAw=lgp zRqm~u&7FGdE^w;PshLxR{P?dal}%V3NA(61gscT|vguRrc@kKEEh)%+-7v&g(6ZRm zJK$_|sMHnHoWccXEUs$2Gy3?3*G|R#nw1jS@|$8GE}LX7>gWsJGANN5nkykb9k;%l z>$fb(ujX7CuM3ff@S5Mz$-Ar@#LkoDd6d%L!0%Hx(McB<3sZSe2z4TJlkTjm>#VJ2 zKywe}8Y&a9AC1#fdLADCO3fR14+ljPsE7 z0m#`HOQ@nnI7udOJidFHas66!!MI3tAtX64?x&hy9Wq9p1g7hvE}L<)@+%7-xmLT_ z)*pF-`u07n3OJ8wn4rWxP!Ens$m_&BUeX@scU5~>B3+p%J|&YAZE#bNE52nBBevDrCe)dMx1uvn8T;f~qRna!4-haZbw9#=YCnss+Fh>Z(h znD%Mgt&(k;%4jBrD=@gy(qr+563D^%l*yW`$*q3#AvkxXpONELJNfQ|kD)kD+t)LC z0=ZP9V;5E1(1{!c+)L&Kwzh(I-Awc*dep>JQ5eI)V$CquAwCoCtkB@$AwQCi9uBFt z?rrp8Y_)WDr{KlcS0l}J4ApFmDJ{?19180gK8@{;K5uW?@!}50&$zQ}m%v3J_~Zi* zLQO*rAwS9Zt$FsO+Kt#M@cy>92fndxY{7Lq=EHB`yuL3eEUW;I6B1IY$>IF4t z&8&N!|5~43_jG$7Xx78oQ+CE}@eaRusgX5G!4@ma#kA={C$sN|Pnji-C`{2l>_oEp zRHHY#^;=9td)q=|ci zj};wUT3-Mn)Db&~6Te7s9hQ8RYJa>HU=ZK+cT8$}+;=6c#AW_Lw~!5`ydK?~PCu+W zt$%aiPz2BJn@)$TQn#n>P{WQL;r6zPiuQ7e3vVU6&p#x;XL^k%6T3Hdmy?e@)OWaF zc~kvzV06rJE3piBT<;7Y&4Xq$uM--r?2umiQ(!yxRbub*FV(AgY(n_}*zB|S0q|hg z)x7|g?*cgUys55Wda!q1`5ynSOzmMXMG=!a@oLeBmxRB!e`H6aQi)>>D(yeczDyAs zi(gF}_rIMf!C)|>&JW4H9<#w0@k)2q!)5O;-M^#jM1^r_O;?9~IzVmie^*}}?zB<% zDFyT~I-Vw+%!k9jXfIZ0@V*7t%)`qkv}*q%`_A8F-|ywAnFjj)m$oncqwRaB=+D1s zZcfeEF5rNqGllM5 zRKD{!!R3-Bl=0Pfc2a>Tfxow{df6eo)xa+3iSLpnH?nVadPDqVW{E2sAh_i(g8LVE zD7?v(;2QIrfgRijl>RHhfy(ut!@AFh(x&}nl_>wogFPlwg3e$;wkEm5BeOc0>$AGRJv#>9-w1eo?CmT#ELb@IJ3_4Z3^e(o>;=+rNxgVRzDm;=}J6 zCs%dAJ^%*0e}M5Z9c6GFw~|fheX5>(F?Dv!U$hol;#OxdcwZYhT2OKVTtoF9E+mV< zA#-5B`MwYMoYt>9{!<0e`l;`&+x$azaX|JgAZq^jeZbcZ_>tGzC<>eZCP3HT-_`!0 z%h@`jwBnTFUSGTVjU8afBPj~QkazNh#g(-7-*a9qIQZnz{oB^>QNy_YGUR~fd`COG z&Ii(_owcg^yY#MS5As8S7*(M4rvO6N+#bsHFU{XA{1Etf{@q#O>gZjM`N0N?A}-;M zL`fsd^Awv|5s8*7*uS=Kl;PTcK46%Fj#*)1uh9W_L(%?v-tL=Xwjd{$t1K+D!m&-htP(}DNd8-?-tp}1T=Wu`mhQSr{tLgN=yr8G)uN^2d zUP5myHG}WD(RT|}%4T1P%%y8y{kn0xV_*APih;Nt-#<0m{-DC!K+>ha+23+?{QC`5 zN@xIy^zvw%>`KFaz3*X8Zop^oPv1c0q2EAT9E$AV-#{)>d;&1>?@$6|Gyxy*_Y_$Z zPW;wU`k(neC_VypSgnoz?rr(c9{i0B{A(BNpRU56IEJfrQ>1BrL+fBxfs~9N%Spj} zmhCFvJB%amX_2o*+r0eo+gIoDJ1!bG4wIIv#V-3gt^lh)!_>|Q$QZ`9d1LqTW8B6ZdqS_ zaq8Tbi{Ik|w>0&t*M8J{T>te9w36CD5XDXJzvr zf&%A%BwDv& zm)-Am_=M5QfufDK}k#AXMylEucjn(Eit+tMzXk}7-(?V8R@ zM1xvR;14+s+}BOPS|SeF>MbrpH|m$TER2U%#3VkvX=klTp3Es@Rfg|jU!dv`Qn!sY zF`Idgc8wxR=Nt@{!Nx^CK7%Bkv>lJaqWpNr0m1aJ-Xgc3(q>`+| zyCH1~Yf-8Jg`;CM%EFqkyBa(M&bbS2XH33$sNTBUUll7EiB*!d<{SCBnW5ZE+1|jo zd_qG-$75;rI!{n%f{45ik6RUq*}{3 zByT1Pnt5Rp(bs2RF-8b`>-EjTT2QlQL>)urC)>ut}j~{D{!%p_OE@g!+6H*xA%> zNf14NWo zvvdZ4`gOhqZVZVzyxU*Re5BhPEBKhzbZ+X4mIvPuntz-5(adPfsg}u~9-N%Tewc>q zL@o}-mow-T*A1*aa-S}5v(=q+t}YwUn!H``u&~o9GIx?js=A^6!r)|GK91m7oi?b7 z$NIB-nrcz|_h($d?2<3=XAX<o&(EK3tMAkb<6dDgC&5N|J0}ahG9K-pV3p&cc%B z+M;1(=}~DO7WXVWE^>D_J_%L)uxi&JnvQ+qVZv%dvdOk?DaL(RP<(rUs9`jXKQGUA zXgVazu)eY=oq(}Rnh-nClfR^Ou6{&1Lf$V%tVMpU?Hn4`8D!3!{-O6&Eys(UJmJd@MeANjcnaqcM=Y2yd^IH z+&*^N*;YbjK2C10y?_42St$Kc^`^pb+DCH#yftm-nGsnNl^_R&OFRxftGNvYl{3rk zN3oBKdqgyiOG;XEQ{l+fT46M~7Xtu2P96Ff%c9y3h09+xijRBhG_NkVvR@c6Mv=7l zhX<%jT3y%0Id7i517dsJB=hoV=4natI!nZesqn$&DOMUi9@Q53UYZt!%wyNQJQ=z5 zuud|+Xt-TBSY5!m$W&~h_Ttx~H)DjO=~K0zC9Fns9H?Q`6*pavwMq_ zGl)>FMiID2n{C7HoITmiEp^h_DqSg2O8?j?MOab$nd%`Ef(!kKCL8C$0Ho=>U;uW-9>5^zU~F{Hld( z06SQ8r~=+>Ua^0Z=EN0gmBZlb-hEQ^H_+XS6x$8IiIHM?wjdvW{ySaX$U)?mIK`Ou zBkhxBqYeu5a|#Dr0i@zVOclEYD&$usawW7s3jU)$qSg8P`y*SeC{I(00j#Cb+Dnq9 z5~{pD$rA4hwW+88YtJpgI`}uL|A+DZA3vU78}@(B|Ng8rj1;Fq^qQbmyHTkV)^3K% zXCuUzSYGgrp2$2&)R>Z+{=y~W(j(`jcn&yOQ7T@R;~PDhQ&L=a-OBt;r}L>ys(-#D z{uuth?fU=b$$SCGv;P~h{qJMp{2D+x;mcPy)Ob~OUGQg>kkgdU(k0MAD&t9e>97vYYD5bg!q{mNsG<~0?lI*w8h^9 z(c-zWqh}`~{P68NmfSa`%)&eM&XV&&*As|SO##UU2aiXC+4KkE$Jr5sU}G11vlB(A zf)Z0U1|OE1uq0I1T^;9u&5bkaV~9#fyKFxxC0PwUf}tYN6eGi))?c=rqT$?a?M)e30_QoXY!EEVZwiA}+mtB&Js?*lkh7_KN-t;c%^N@;CwUH8IUY zj)CbwwYg-*um!WzueZZOG$HiLxtnp#Z;ePag&#%T^!a#i8emFuR3uuR)xnwCH3ubu{R&R)|QhK1Q0x{#c$1g>g_uNr~VCl_MwUalJq8k__x-bF}R>j}|uTJ3l zlqP$n+UC~jjo#B`(FwHyKA2l|9+-7CDYHwB_2p(ecEk17c}i=R&C&&7DSB(|6>FU% zMlYJdd>rI2$;WI@J<3&NjftI~+oVqWd`jRPX6HuZjv({prO8_Wv1l~b#J$pWxNd26 ztVpORWKGw2UR0XP!g(Cr7VhC>Lx+;!pl zxnbGFua-lH{zByX8YL0RH0gI=fDv>o?E^twNVQLl?WL7XIW_>z}* z&z$J1sZx#?H*Zb7$-vOhtCl-0?TnDF-z@Mk`KT;g;epXfs&+PGD8fiOEOA|l&ysdg z)92?aBHHrnJ%qtl3!Qu9hV>?5AmeC%!9$CTkL2saTR?i?6ci~ar2>fu1X(%bSm6H%MJ-H@83F?}t) zM7g>jKKyPW;d$Y&H^67EfV0cU;L)$k{-BNEf5^1@lk%Nic}QIveCZ1)aCGL_knP$< zP$Y}P=an!MG5ydE({XQY5SNmzo6A%wLp>o!Y(VKv`T|sIPtTEa)WYqQfz( zNFL=VJ;TUXXWoD28rMD+2m;Di_$cgtb(r~aF$0*Ie~3H#zka1`fcF9zf;a$xh)=*u znQ8p$pm%SQ_K2)-s6kQaSpN-_e*PN>Km85V+IQvuyZ?$ud|oYZP^UkLkEJ@=RJ4Ee zo&WG}QC$CKyZ3)+x%(&0{z+4t{;xhUdFS=rHW=+>S?$*nb_Q@abdq?!ORi|0+6oLA z5#YL^@@%wOC@ZfeZe#C$4ALj_M8+!xdRJnYw|vEv2CYUta&1LAzDC-QFau-XDZNo_ zGbi!nRK(|jOqL8BD;Dg`M^y&|{Qa0Jzqu{@Z+C_KK0tMNCvqTAx*UP|2I~D{wmX{n z{=lUC@DMl}_=SP?96w5nh8=3DVt6va zsQzZ)lRh}6$@)(v^%eYoe} zKpIvrPPOK8SdqpO`zdP|*M{&xD$f(%o?#>e6&mhaV^){DjT z0SL!l8LWef-#Y*}?=>O=Bl=j~@v_e5=YwS9Z=@&pfF7q2}Wy2EJ?Pig;0DiN}m(ox*a=!@7>yH#MdvHFS3w9vG^p zs9e4^u%qdiGl#f4{?|Ov2Q0+##=Gk`k5AvSUk2ffZ zt=fvGpBc8>!`kyZOy|Vfz6XXrL{h|8w)lM z`ghXGKYzL^Fp4ux7aZ$pyoTPjW&`^QtEVppyi71Du*t8EN}4O^X3)f{V@waqj8qaD zJJmG14$8W>7R95PNL4NJ^rZPIKV22HMAs3s(XfcC34^7Jd=89-uKGHrY`}=MMIhm< znC8ua`h(u3YA^jIDQ;q3xoNJ&>@d$c!+;sp6?fer`)Pr@I;hwVzmW_;e`_v&QpbS@gVkj|d>AY1Nwvb2dl_pq_j_o# zq4D~DWg}#Ni*KODwmWxrP-c63;pBshpnsHt*r7nWWyaekVud0Vh7d46Cwj1=P4Rmk zrI=&mUYiS^I-=EG8+q+I>PADW9opsuxg}%b^5zap3FR?C%FB-^PhGtN8mO$Q8Z0G< zAIYPc!PJiunS|keDl9h&&lHB;(g%S+Ux8@CkPNEB9j$`}eFj%HU-r#01!9(>3DsW< zwJ+V7|M(3g7f0T|c%sj1Euhy5=wmR&k4JxK;D-i&XyAti{y+^VGc5@G6#PfIAO7m| z`JG;fe{vN4Z$CNw?>U+=0$ke6Jk}FV_7<^Fz$u2a_XOmq)Ui|^RN{0)eA20Z!gCFzY$G7nR&w4V!HQNP>BE1zWT2^hJT-K|(YBhW*#^jeI@?qu^$MYN-dB1J z`I5{+%4wAbD8CP-Y^Oe2LPgSGJn0$E@|wK0(LM1`R-;%+$BN2^UnQYS%&`D;@n!XF zm>FzO$9@&#z2MYYZ@|V7i}oEaDVd22AF;w}B}jRoDu*^wh|$u-S8k%%DPp?{p@3BK3LfaRU*Cpq_hkZF>QxM z3J>ohCU#`@40rO>G(>H$i02RX3pQ)&H2LK2=dZxwA)Xg@N&-$uwVP;7o90YoVJgjJ z<^cp^%_CG?PI6+#m~dVWSDjeN@TONL%QfcB-EL$itif&elupsDTnzm4Kmc`GEr&-= z*a*I{#LdUW$$V&OD2sYgKvNZwyXP>DDzJ7iOFQt9z!S`K7BbFOXM|4h1DrZ?A}~k& zn*J?eI*0164!5z@lMBfco({$oY<+F%s^>-8d!Ke2I~N!*xxrOkAc$IhENskquVkM= zIoEzL&9A79*MHYtm8V>S+=0Z?y4eOTERV2Ulb824euYL0t+EEahXFa%-PA)Y$wcGCmBI0amMy$d3y!kaUW+EA0OgFNlxFgk=t-%l72b8TR|V@* zuO>E_Surc;TdnOTm1<>7;>~57pGS%5o!2ldkQThaj#RofvTH4(M?NyfaqpL0ZZ73r zVLifBKGVvM*PqES5w;n?L*ZJl<>~$Vn=Wp5^ZpE6hxEQ~6oC+?qhB-DS$V@762s+R z6^j(S79X{=y>K_8UXA4cr1ND5Y)wzsQ%$%?bub=BBsPL;k}(1!YF!39g9$blo_Q|C zXb2dpVL$R-D)zn&g%OHT-WhhDaXYv*kC1JxOJ3|Wht|cOH(MGx!Etm5lv7n3eq(N%t;gVmi?`+weSO}gU4VMiUV8h-M8fKcgpUo%*YiW_hgyp z)hpiICADOtXLZWf$jE2xm_n(L6lTYNu(LzT(L_$R`CzAHZOe?lw2@)q8|a*@OBpHF zPvNIwtEBsbQy*UR3~Z%p$n52GJtE=XsD8#UQ?Z8A@LLE@rXVXbs^aT-p%dRg3Bz07 zMl4bF`e*b9nyN#p!5H1f3`t;9I}sXY~(ske^XGm^ZLmtGEmxuII4fZtW4;i5h<+t5QA z;509fh{xq<76&6$tKm%BP!A6W~OiexxB|61sfZdy)lx2>)wC-Y+_gi+fB z54M+7+CJm|)WPKq$rTwF>f22wUKU|g zEl}*Vdcdd=IL~`rH;7B8Kp=Kze#hQ~r7SVcOV{1mzGHz#L&;b)tzBn!Y@-d~(;&BM zFjYq(*0BrivEzp^E7X(MVdRQ-d2-7Jl8^G#oPWY%dO zEhXj>9>IHvOlMUSR!62xmxgb(HOhh)`PW%Wtb+HRW7J8WL3vP z`%6;vU;ie??SFy6d-D9>GDQB!K)&A@%6+fzi0_#Di{`k7>SLP)hTlLhoDRj-9Yg&2 zw5A)JHK0?(@NGeYrUI*wp(K7R_9tw%UL`n(s#?pYe*3n7$F%UP83uHdu$P5C{LCK zqDwIykSgCDspbWVilnZ`Sw@umNQb1?^IuHOd2D-fW8K}&%o~e$ecU!~7O0Pzn_iKG z6ye{Qm^#PJA(i9Q{a}6~4y3Lf(eQTT0>VX6`D>3`Ce6b7A)6if`HA_{YC}(hEU4pa zHv>Ea+tu$|K3+YTzFa2lyH(hn%37dVTKo}f%jhY=R{Gs`JoccOdn}$ov4wNgyG!K6CR!MEWApcT8R-XmM~U4#tu84L_^z@x{9((CNO2wLXF8_OdTLND8P=oZOLufVEg53p|ky>%c1G^u)3+7P(qTZ-YT&yK1sY}bD_AM8n^p&vbrAI)X)!??b#6> zJF`09EKj*c03sF+*>iE8j-N0AksWJ>FRu0rJG2$U7`q)W0-+##*W7KcK6!fe3_8ux z_H|CEp?{AAm(A|HK^?&XgRc`ylagjimKKGcpvLM$Oo>fUh+~R;1ZiXqOTI+g9L;)o zos1!W22x4mw0zhJqE&tcE7*$7J@8(^=k#sk zT^%#h#m52E<9jxuqhR&QHQUyV;AF#AXt-!lqxb+Jak=FNBrsCJD5OgPBN=J^<;kj z&d|Bch>9DL-V8-b&YkcFLvc8t#7cE_(Uiq8+@#~HlHkOxwQr!a?x;Ry@5~c7qvIkR#zMAm6UbKdemfVl zDSE&4qVQo&O2XkTqMGQE%;aw@&W9)I3+OfZyAIdG{kEH|oayJwswQb$6i7yF zj)zw#F0+FLKxH-h5YY2J*`|-b3d0&wBO;0;9(0riwfPcj6a#fS~)x z&_Zi@sR}D=V5XkBbzpYYhNJUTx2}yx;sW5#?x!;KO*p+s!nW(Yo zPD12`JtOnj+lyd|!!&idMfZjyu?c^)K6G++Q}WccL?h z&0lPiu&E~GY%b%#xO(cfOXTxS5#IQ=43Zjo>?mhaL#l;+%*=eFzNwOBkL>u?rRgB$ zq(VKkF`p~lvldI**4J9Yh{!hjOzeBJT+ixa5pq1d;*bHK$qNvM!~C?;5wxS%n&&5b zUmRXbmmYMKRh=}uVDHcIzG=kw=DD1Lah|Q!)xswfWzsiXIf5ge z;;xu>;C$5xo1(Lj2B~GdW?j`zW!r5Nfnf#>whD-m;I=`-mSIyuMh?WRGOw-r8;GL3 z>`-g6ggGNbdVBT5jw$_GgtSCrwgczJVKp+!nL}{svqzGgVp*Yq-n#hu8De6ZvAbgc zWZ3;784PV0d^(>dB`c?Pt}8k3HcoVJw}02MNuzY&cE;e=*K8 zo7sA3i^%H9IM_ygypK1r%2>8C=dKauD^0zGj+K+Qc(>I*F0BM*llSEv26CK|df-R4mz@F3@0y1FiRL^}Tb*E)Zy=FHwZvqzWb$r8 z`5KvT-{(N{b`+dv49S3Q9F|vmUC;H|u_EBAZgsRf#i3C*+{lQ~ zB2)ByoIAn8hvkDByMD`Hmd{3;;BIBb(8%q+{{?o=ubp!gL4U*O_#-?1yP5pXZz-sO zaGCG_;JeyC)C>0eJ(A5p7WRu1f3R+T=RNi*Z}vRU)4d$B7eE{6Z+6HhFgX{!H!F3t z7qFHo!e$5Dkm?5DlfHq@Q2zMihf01-h9957kCoxan)qWk_CER(BBt^bzF{iAW-JYkNe+$nh|#H7C=C8>dyi%$g$ubPcho}zbOCuUx@R1z*hMIFud-F723_pJ&T_)z&8I@;RDFG(4o z4Mr{{CDGl1P>RR)-VA!scQ(;R76j_J76)+z?FBV1@M9M6 zm*Bo~lW?_`N9(ESoONrqJ9%4If~xAif$YIu5CQPs(;F9Kc`=+f0;ykkP~MRk(|ML- z3=?do&nGkty6Dp{9bsjJ(@Ni@S{w1<6FT*?W)d5Fv??`wQ{2nz`if5M5>ETkh9*z2 zdQT7!6dtZ?X6%HTP&RzID`Rr=>~*W4cUBuIx2&VN(w&~^EgCzlvb>2igT8BaNhWsI zeoZ!k+gd&5E*>&4h``$KgX1vDH7 zwc*4#=9|Z!UKOx8!oIS(Ejz-aysTY_Ihrm|>#{CouO7Ug*KLJf&P&HRJ)x$N6W_>&zxVT5>c$qov{3k=X>VJj zX>P7T#3#TfQD1IiX{YWfF)X5_KsdpO2OGDW*tF}ARc@P8^)~2(=d~m! ziEeZyQq=0_`^#1I3U8gpqMtEyR(+V`ff~bij zTymY330skjW6_*6`L&l%w(rBWz%^y0)3k=gu6oj46uG5#12$_S-F(AoXOKPaQi70< z!!^a9vzWNQZWnm3#k1BzH8lu!2N2aJ2|j>2`Y1|(ZYIyZqR#aq?C3yG6`Z5dhQnaD zrDE`rXL-wh@NiiQW4ZNFg)H^0!L~12d3F*+%sFCyK!$wD zKWvFySR`+x4B$9TJ2v)Aq$j2Kwx^#TGMRe6t{LaVNvYQ2b>Z2?T3I&bVaxQlx(kr% z0oY2Dy4j|g_bQ#e1|JH!KY@=s2(DXC3VLcDHbrdR*VBGb@i}TYCb08sym_y{$44*w zf_W>ldsC9i52g0X8$3>MPk%|zSXy}+ z2XXI%G-z(+<24RTSIF}@nLUo;Z*KMavUq>p*HNv`0Iq*%_n-^9u^Rc? zW^4HL^tvlo%0ssZ*YGNJalSkIX+x54RAGpZ5dUS{tFYb6`&ZsIDi0+ByXH($2l@12 z^Wvv8Si#hQ*}Gm(mnpWiDgLdu0TtVFa&C`IeNH=~S(C!v;;KJ!5w5aKHmADw&_Gru zkT`Av06gwcypJ=v&{OV^WKXu=_gElLrDv>5sSisu*eVagrs@;h7sj%Uml*TCaF!x7 z_g9;)e!P4<_TDqf*qh;+NeFL2sab13@S>mapdMB=K>;_sqvd9GWRljXirUtYu<0L$ zGzzY*!sQTYi3sy+1>)4tge+07jP%cxSOwV}H;aTelKQ^~gPSTm4dd zq9~I%>jv)0o$A3dxM(*yrCMHrg(PApD)MCAG)@>%oTDM+5mVXDG^u)ZI_~FfS-1Q_ zHDW`fg^tFUg2EeuZri?mTJ9q#M}m@wjUxb#ST+9<1e#)k`v$+xsR*qKU(z936DtC-^K3lv5>3Q&6N6kQfQhnEpA?} zZv;%24Eh8(p4&i}R(U`MAgVK}f_>L{RaFv83L0w59akI8)RC1rg!4Q zaRY|~9uFJxykpa0hIwt9h|O@h%nJC=g%IAwz2&m_TDq9sW$2s#a^)> zNE1-$C7{xzzo>Kr(n}~RHN=3F&>>cou7o1}6$m{AnZWu0`eFP_{VhH?qxgYWc$fU=+=SXu^L(GA6LKYf(wc zZPjw-ojl7Aow8P59GMe)p=BoIWsV3k6f)Fv!n&U7pk37j{1&;iE8D6*N!9*53CXJg zVJo~Bpy`RX#iqYV^C#Q=yme~!u`KRbx=pXBjTLGi8ywZ3>Rwbih`_l$_pnEuFSUR% zypzpsK;G$!bnY2$nt{}g)B;UF^P+g(dj*zWh23rt@!_b?<`MatQ0{X9O2>WN77&+msNT~Lr;Ye1~~vdvah`=gDD4ECaA5eN+kQwSPbIE_U1R$)mp?^ zTDX1Py0zMvOE_?v%bh*(^>|~n{Bo{JdBL^K3&nL6Hm9!0I;1oNMuKAZN#I~`<-7Zx zPpla>>b?vBKsb2R{bFd#$5AK{D%hSYxF(SxkDqAv>9Hkz#-CR~`(}RK*K|hERPFC3I1Pld%3doz^KK zjtah#6LJuMTh4u*SG!1K$>@o&3j1ZNSLD z`r@58kr;=RY>-8goI_lC69Y+ipAAc$i`7(pQZxqP&7{9^u%0XjIW>Pjy>d)`MvB>b z6n{%JK7i1a$@)vb`JO03K(j}k6M85hbDtxLP^veg4t#IfR$1C384oi>GY-f05L zLwoHB3A3Nw(tBJ3U;s8dukaq*?DhjqVG*q7h4$PVM@Z?TB#!xp`O&NPdb zk3f8KooWKcL@Xx4NYh!Q?;qpSCa!Pf(92Ca)WagFA3(C$v$5$3!L`s9kt<{xiT^f+x zh|I`GEA{{eeiSP&`TbHI~rgWu)4Vz~Qq0%c(O z(^q~=1E{`a^9Fb#mGWKg4c9+Yn$xdNl}=)^Lxs@QK&Awm8Ko!f!hj4H`wnb8psjvs zI)$|hA>Nni!|>qWyb9U$$xaOSNRIRAf*dIH*~PfK(mbQJ)&53XmO!r=vMtF*2CJP-Z6%MtQB>;E*M zJ`)IS&N-I!Gt&XL-+2V=;Lf`aO`&W>&Hckb>2rO(Yzxq@b^%2M2L@c;*@->QR5WO# zU0aa2xde6IajJT4QrC%qi7kpE;#sI{;Ulav2fuVt+8%rI{Z4|i)CS;9!DceL^f=6lU9 zgzOlMG)bO{SMaI89LQT}2RA2LC*37gwsPoP=U%*cZ3O#dx!x)leRzSgO&hJsQ7bF6 zNbK2bWb+m|$CdKlw{Q>9QI%pN&!E8J;dX2p5GL%?RGKNYFd);euR}eCx(Dn4l&c_c zkR4Xkq_rK@mLxyQl-zZ3ZqNF|A++mF)E#E&xt6q++bxhE^c41SFY|pkn)FFN>d8=S zMD@(hQggzfuY+!WEBurx~v7 zg*kt_R_rz2x|3LTOHJ+ikx?FLRa_vR8_(wOUv1#dj0|%bH93@>fjVcVZYjJ!JVh`8 z?8IyieUx{_B!GWv9X zm;7z8C-i)-48g)gkMnN$kM!>2Z%@Q%`gdzrobtO*jM`={9h$8~zRp#bWuPbEJuX0F z0ox>&a%pF&DU6+Yfgl;zV?!%l&jpoo`(r+4uYYzwm4p)1Q!N-ZGrD^Sh?3@k^-ku{ zp^;CKyOQVvfQWF2IF!CZYbU9L`g^N1sBJAzERG#PbRCc1^UM@qk!=}eLfEHd=bJA5 zG%cOJ$a!=z>%poi(iQ1_DI^bQ2fKC-mb|F!;iGM#*m|`4^s=GQB2&Eg-!$~zfxwno zl}ur%BO@OgNgF;8h&0ZX+)XIhHQfsbn6_H@ah5bd;zB;=pN;61H#y4p>HYL$H@BC` zim$g5N>G-#sT0h;C~-VYVtaJPU6QGn#@n&IO0@$))SWsKg!-_3V_BAUwdbxq|D@~T zH67R*I&~^|H9JvHxdM5il>K-j0To{=o^)FT^Fk^3bz9jzd$?gIe)n^+9fjiXhr`oI z;lt;+cE9s4@dUzXnc|V2=x;Y({C*KqR?KVu4ca@2UzPXmNu|SP)rKC$C69EQvDtp+ z@Fdlx8hvbD5+I|MdRzQS&n9OV#PlXtn)!mFh_jF&gI9X*g^;2z#~V z(5>0$SwUE3x=*ueGXBt*hKwKGO+9{fCtzSA$H8!O{${#WX77D52Z;Kav$s7Bf*w5X zn<;oKfa5MC204!7=1DL z;wDv_(MJ`K86$x^yg}BM8M@3*uELXVuTB$*6U+@2{K*F2>LH8Fc&jwrEYrU;gEq6i zxH&ZEzT5Y&+@VAw1>j?8q^r2|rP@6e-ugJ=YP%U1gT_FP{rQxilJ>MNC7wk79jWIgA4iK5sEbmX3`)*I6Par%B+B0>- zQ7y*je(V_4$Ht$ZOFI!&Amlydi0n?KvCbVjB+qfzXA$?zR@BRqU;XbfqWvGH75+cW zL;myZ!2fC8@qb<*FOsOffuU|p%Kjy16I}Vk}CZuEzZ-59Evyel9(ZRjRQZP3)M*pxX zHWvPhtyr76TDqE{EREjM*)@`%8m&Yl8&x&zKig5xYukRr`(C;%ygV1bZ^QmQrRYb)W1oDS3X9)W2 z^mm=05pzYPbre9r%sNx8GYOWnkgmdd-$evItwZ?x&v=CjS2q^pDsp{>+}qDCW8A9k zO&5r2I58B=D|mdZ_dP&NPY$)3|5P5OnN=CqkhxN)8P^sFf;RW9T5B0o=&|Kd;ZOf#*JiCzt^M6 zuwuG6KVTBs($J7Qs9HIYdhb^f;#L%IvC?Yb|516&TN(_|t7wR2kUdp4LhF@rm3?8k0d zM%La}V!SbOEr7drp_Qr*ih*^WAn2Po!>RZZX1^*kbYOMvbG!Ng$#Mo#LCvGZCA8S$ znLO{zE=n6|Ikni7({+AFX&ZF4ntjbiHW zM4B#quGa76@@8hI%u zo$F08!AW5K%$c%L3aK#WxsTLQVn)v_V^`kuXXL;O*zqBJtrE(gD!W!bP$tz-19r7e z`vtFV75*E#J8I7;m>G_kc-SX-`94}bs zHLpNJp$DbgG>id6m?7Ftp8on_j-e7z6I|;z;4q)vj8p~gAlQeXn0B*liBwnje=Jms z^h1j8#}0dzV0hpc9KtDPk~o(@FZS{g_LX+Tr;+ER{!P}Nl={)H*8ZS*FCr-%^oK(% zg*T7XU|T&5BYN$ps-=zM56$@5QZHzDP^5BI!x^WDws1$EfRSY{?0!fzAR8b9~w5%Xv zRD=J8-f9B&gaZ1dgE|d>CAXm?xjp zI5)uGqn!uwf<8(3oVD|K3|mST$(xbt;a8kl5&HnTMl9X$l-8pB;oz56&;meYC7ODl zm>^Om^T7w~EuWM_CsqxC@fV6}hA;;fQ;tT(xMq`4JNkLZjjQK8F&_FPZ71ejC2hN; zbiW_Y2sdNp8oNYO-M+t$=LV74H&V zVFI?_=`JQMn2}Sl`B}EHn@;@l&`SBsLuA1q3%7dknd{RktYaPHewHf5!Y20GY`aSO z3b0u%IJmhhUaY`V79Z?#cLNm}N{t<nJLL|F7Te3u|w#7AB^Gi&VB-Z6#iY+ zZ-U+3#YPPtq!)G}>FX+?jYuQagQ@su9n`R`V(ASv?ZtC{I5>b&Y-Gs<8CLfD{^2<0 z2Y;u~e{ezn;v3tvRjoJLVzGkKP#>s|8y1_UCO=~R>4*$-R`s;U_!(fU7sm^r+f<0Z z_Mo$EY%KoJgfMD405u3Uw{q#FPR1 zA|B1U*ftR*5jF6EWi}cCM0@8dvSCbqvqXs^FDun8@yYc=uiFRTgF}zY+BAf)#d=th z3!vXU?cU{Lpi1$8#8ykJG(d}Nkm2GIv+#3$<6$B{)~Fk+pTD3EmMvG)_LN|tNbefm zn%gUJj)}cp%!dFN6V~B{LP~m}QGkG_vdED^GQs z+bPh08E1P97Yy*|crgIeGm^3-l^W9#BYXDwihbV|3k+P=$JL})2d2yMHVQw;A0|f( zX3jPunxLF&R_W%y(Jvg}@1DUfqeGG`hPL8z93q`HvH_|;u=Rq*J) z9Y0?@POLDyB-0($pHq(*tQ%9k3&i%E#szcwkb|4|*B|e?PfQr|$ZUkG5mV{1b;S6| zd}bL?AptX)?9x-2qg?zo$8TBl#1qsmwPQk49O*5foMrEY@|`7*JBXL@D?Vp_RN)nS ztm5~!!%X=ZDSPp$H?fe2?xxIy-|g!oQyetLBx`rVh3w8JS8_gH=&w$BK0v|9k*1#; zn`JDa$VSd&NI)Y|`ry9tDb)4&9_ZN||PiOh$eLRf}Kn~kLXmCShua?Gd@*q{a*o(U{@-}x)KQeR|^H=r19ha6Mzs_zb(Kdp-2V7)x9wEEr zAxq(S7H41N=n@PD7mYG|7rYa7awtLsjyBM692Xlj(&QR%_Z86exiKbI!4O&b(Q3qc zaGvADl?Y<7YI$5^3vQT!3wH^In#2S6+r2U&rkNn%0TlPNoF$(Y4)hoSnwVffbn(r? zcLoGt;U!r^g70N!A0kbSpMS|}E`;2F5kBo7#H3PfmLji-{$RLcMq+7P#(y|uBev(o z*(%j8G#w^;YVE86Si58|1t65c)h2FZ@;-yrd#6D|>V~b4fAG`vJ3d*Nc+s$6Q_~>$ z_7--zRzIq%%)gko!9`kMM#jZIER;c$ae1Xe7;FB#b}l{(X{6nI#*lhi$hqORX*8{MTBZZSdghAP$7Go$kfP6W@(HlG?}?h zY29y2^K85N@&0kR2hkqN!h&(Lsu_v1_V3U0@ra6EPgT>u9ht?>?yy z=1_BxiCVuCw}@M2ax3g8I1O(Rm@YbsWGBt+>XdU} z0o~~yu~-YM)Uziy>_Nxw&RcER-_y*dSSF{BC*ulC7%Lc==d*svL0}{JZ=2C!rM#_x z54F2G;o$9hTbG)Kv{_aAtJ{Q`7FWNy^1}SNJ{ud!3r<;g)uwVNW`4S|4pcJ(E!3e3 zYGzj4%!W)o^zPFIxvWNMcm+0ezQi6_wl-XN_lM(5&ez;NVU5Q0D`;}-jYlp$86q?N z|9C$3+wfVkw>GZGO*2(tE}$Xvn^Cc6Q&ySpx`EJ1bt8o6IIxqq?m#($0M_!qG-!IBijoBrEm_pybG2S``(ZL z#hCL~Mn&Qi zO2i-$#G-ezws8e`1NQ-EmhvbTXybB$Tv!{$oq$!lx;{ygYa2B*_+c}VX+7Td;>TO7 z$H{)yrvkI7RYvkF!=gICf|lI$`rAp>n5UTV?L)!nOj;Sy#Tor2Ya$mdK1}b!$3Ri8 zkRQHu`b|s*y=|>ud_!2GPBh?gd8o%NBe~Gu4_#!E5KQqNDNF-8cDp$h14_I#6ZdMY zu=&|TETvJSTvTsHU7u>Q1ldIF@(E-YppE<3&()kb`eSfcm@rI1QZU2yP;ocJ(Mt2nAx zS{VbaSCtEvtzQReR2N^T^UZl#VNF8;L?D%wRtP3eflXO1ffWtq&J5Swz(^!< zP{XTsP$>_!Of!IhN!_V<-1o#antUpOW~xZ{7(T4}+^ zVmrv?6aY^jl|+|iIVsny%Lg9hr&3v6e>lj4@$kE}IbTI$lVv{ceUoD4yta2I;GnQ} zN&Xg3hT$pU7r#f8uXwLglt#OX(tksZ*0BSmek!}wy*ifxalW`#Gf(>Ub45;6`$nu{ zIoMV@Lp0!Q`|a9nm7n%j972WzYC^I`9a-t3w#DpRKWi4}i7rZDe10osnr(&H8M1n-sP5Z9?b?)E?tr}rRKbva2{!tHX4A8)! zhMfXRmqtOLqMh}#R?M5pgI;?onMJ>wFwNUEhN#ZTN-FJ90?VQZGLOEILmjbiv1h$f z!60gqQ5-WFxRauZ*xL~(kUP7%w94NNPf~PA7=x-w!WqH)RtI@D+tu*s*pbnZLmv1u z2k$gInQBH>U@&lz=|KY+Qgh3=FFzR{6h6f#1W^@ShqFhKBLSfTLqk3q zxY<~#s;u8zblW(6J@n4f!@%B{K(dT$*!}8kVhY{7A7Rtoj~~$0l`e zZ{RWlOm+iG+9#np?O`o=sP<<_t&T*0+qWwnA56~1^YcX?Y~0pNJo-X?&}Nv&bYm7@ zQLnN&%^ZLJI{t>~-u*P{M@w4Y1`9RY6~X&E!K78y79~DyT1#?oNp*eh`iH~rQkSUl zTJ&$;6wbz)H;ana()E^^4r*gn=9+2`*OClxC(tA!`Y50x zjoC8)*~+CI3!5znE1u_^`L^w19!1`F_mp%2OZ>2#sIW;yGxKL7)qNG08-otgd{z0V z0gXlBusI~qs;uL3xWU>1p?ICdW?f_;9ij%UY?rBYTi0^v*7$|`sC@2IrTjN2;oF(FhU11uOjK^& zQeW2(>6g`x+uKrEWD^V2ug?Dum(2gCtKI*Z1OAK3q)uHa91p?S6E-PNg=`IR(R);l zl$V=h?p~=ww=BL-1Yf%7coC`Uc5gPhnLWC<>F2&=JbqrQ0RFqk_t3aNm&B$6T-?2} zZN?A(8LrPBbM%nLO4WY}4rb~6emAD+{)a=CF8GJzgd%+1THpkd#3!3o%n!9|O-lPC?_dSu56sH^>E_KP^{OPo3 zH~+a+cJ3d$7q`^J)<$wz@6Bst4j<5dsiO}rGz=W9M=!O4a4VQ zBXGuW(jN}dLHPBV$Uhtk>lc@WY!BZ#c^)3vvCF_(yz3YKe*Ev1`MU`IZjZl6@E0Th zhJ*hz1En&iPaPoBCpVF7#1SeEb{7pyT_0i zGv{6QlKan8(*L_IWdFZ<@$STbv5{J*Ty@={>3JJek^Ob}ZrO>FXH9HVUUo5`#wMV) zKN5)U8DKIl9x!!S)<^!n_xHN|T@!!z!(S};i;;ih!{6BWzcVjL^Wy(6*>U)rCjY-j zKL1xG)Z~VMCgrmx70xYDWpn$(0XoLR%1(FO&W>K7J!#4u%(3RK@x68R>=B(?*D`b6 zN(dE)6 zU~cE|ug`j&LsA}S_C?=nH@tpHw^-s|MEKo$FuIXns%wE&9hB}FPUp@suD!Bti^V1Q!`#_e`>u=7oYqqbqN|cvSlDhCq-@I+Y?a*}YvYK{{&Z_SkOeAfLqv`#mw`!quaVC@?DbCPmoZ zwx>|Oe;9M_gKWo4CvpJ>-{}78!CLyAXtD4v;8k!H!CKr(ZE%L@_0=>ELKuPLri(BO z+ehHgrPF=;jSGFAMQI})Nga9dfYr*2NA4HTzqTH3vaP5@cqd1e+&{f8o--4Kd*yl8 z&hTuB5g_+y)fGMUy1FMp4Jld61$(uG;lflh#H6uvaidK#upa8uL@;-e)u5r09WYLW zDEVJh@1U4c`H$`s=B|-G@^}qAui*`9`Xb`3~16gK7x| zDZ4t`v8y}pp>!3X*aIz84KJ6PIKJB8wDOg=B%;5bScX*CL_qT>iU~BILWrqUHGYSKV03Y-zjVu)9 z78LK3a=Qh3^n4l?*_J}($_4X&Yb^NgeYTHj1wKCi)px-XxvnNmJuW!SE%>#YzkcPC zOvkL`Bb$d2Z%e!7uQm19kZ{gkotfqkn7Bx25dxcoy%(R7H3Ke0;7yDjON(nv9h@|r z_vZT*%?=8iv|v*M?@7X+kE?sW(!2rn8WlL$qZ)|!j$Uq?kGWiXrYl#;Y9nGa;B9=Y zbU7i%XnxoLC|(Yg+5}N>?(F%@jS{cIOtW3fQq;&{VtG0g_j9$&sq_ZVKy3|{`M{FF=r>1@*PkQXIj^ z(E1WkUxzIH1 zs*1Jjb(asddM>iF=Czf3u%^&Z1gKcpt6tIr(P-p-&)c?UP>ew!L{zcyB1|I7mKY$} ziof;@n{}X0-6NV3D=M*2xS1+%*lYcztDlz7cSp-z>Tb+dluXlTHcn2E8ZKkn)}$KD z^qA|iu+95pAW#{&e%;cx=`+vVfC&kuv5B(|hC$RDaCD*H;j#nAfW^(jJJC(LfN2AZ zB(vs?QwZo>If(rJVYQVkQ6#3lwtyIH|Esn zzfChSRu;<)*Lvdai8?eZ^-W}>dz#Mq{uagBG@1(z*I1KFJu{Q=IEPi|o-=&9*5Cu* zaFNuxSO2aYx87G%Z)sNuH`AX+bLaMTLAZ0Ka|m9hU`v>DOhDkUe?%~79}gxCE>E^uNLvxo=ggvSDtrvo=>; zHe<0BS3T=AOah{^jK&hnw*k@%WiBf9$&pzO<&2*j10sh%w-1l371d0XqdE10ix$ol zDpPvH3jL@?2cI=RJOEUTDXQ5d$sK?BCF)V3o9?R_1N1c1l=D4ID|l2L4i_7lVuhrY{7ip{A&pv6X~)TrK|%J!~zpg;>(}9Qr*&ETrIdMEJ4S zlIK6ZI%m}9RxE7T)jTx4FMg(*6IX3((^x$lQMQjO_pctjtDrJ>La9EuISVY?V%=9% z8d%F7+#MxE0jCS};bT#5gx@tp#&n%^WVvsIG0A8r%vkr>R=dxFsp2*?e0(tn-@=57 zxJ2oMN#+97B=h6)4jSqaQE|yGe)>IAwym7^+dl4^65GvHuwpy4Whh_udqfg1@2$9K zUEVB_)EizqE2OtoxXg|_@e2)I`(>Itl7@z8N98=a#C* z%%1VbJxhZiso3B9vidlgkyi>@!lFuggCB04Kf~8mno=NGJDdz`oJaVm`nniW+6DpD*qkvngHXoobGVZbUPi>bM_Bm$6~nrRCH+?I)dJ-COl- zGdZ*6asu+vyTMJaY&2-?hp1Tmgni1%&inDdUtKtTGhOzPwaEAFeFPqv30~ggRR}69 z)rnPC9xEa`zCKt)+ zWzf)dN*6plY!?l_*QXso~jU{YEH7sBVg@3TR7bEjcD>ngG&$IKw! z%+D0XUW(F@&0hWAUv++yE%84C|W1Dl44-b=73TMvS1Kbc2t!g5S& z3%<))U$G5!a&q3Qod2G_9lxu1A=MqFlW=93_l{HkWXE#XB`jQi*68VF-)Jevx5@TA zuJ@kz%Alg00+TIF_v~x)$zuUZOdoc(S68uR6Ks|?GO}&j|sKs})I_kA@7^|ZPR$YO|mzNw7|RZRD>`)OwjbEUs?m8zP`Qkzn1M`YF= z4hpf5aL7~lyWca*XbptaogEO^#H=Q8YYZkG;knyd#1i-!i1OLjYaDi1Uv7iSeUfd3 za$7h$IcERiIIgnVb3@4VXri5!Zs};TUZb>@i(#=;YX&o*|8itKy4oZ0&bDGHPpCq) zmZ$tj7b@5Yy;==I$B`}|CeeZm0-Lql!osWDh{8oUne(=vzb~>rM%3>6bnQ~$Y3>>g zWA5`)N{B}(g_+4E3#7iR}Wkh z!q!0|Gw4aU1U1HahcI3>7u-UfYijJY4$Q!V*A%{`=iY)JF(`F3n0%3}88jNiYqK`~ zer@)&WU_Ls$HP}Wf>q{SM^kt)7JmC0JJn!kGKnrr55f)~&wQt#N+J&z(WjTQYHF&( zy!x+4gsr}Pm&CIDt#HNcAU(Kfaa%wyXCPg3kkSK#p05h6tolUnF;Y#*b$zjXs}NC} zCUQ{3o7CQSm&`h&C1ML{aayia|HHAo?Y|q!O{RyMsx#%S#%pay+Ac>8x?Fgsq(gVP z3Q5b1{HnUHT>A;pX3xB_^w(bEjtHJYI+k{Gm7W1SX1Y&r z5m(*r6?&ewirewXid#ts{NdOvIhgc5ytCT>Iy9hoaj(f{^b0#o^?tnj)S~-nzI~kt z?BV;1@GPXO`o}jiRtOBZaC%>|&lk@QMi_8+K(VQ;eQm+)DBy6#>tOCwX#{*%uW<49 zLh#}31O?#`Xq1UY#%0OO<8{#zA6=!YO}O6=7F_DLlZp0`wZCVcRW#a^o!a!9lL@Pg6n|z|r5rS1_RH27Hq( z<|^FN!@g}n$~LAzYGU|%D#`zZo=u6aRo0FJP>W~=0fp0xomAzs-5m;$Cm7BnOOZNC zL?;0->Y@mS{p_Jr5%Sua7@-3`Ptq%F5qYbyW!pd$@EBSt#&O&Sw6IFv^4~eyGkg9{ z{Oyq(X(Ob#$J|{Iy3xowESPe)Q3(;HZ|&W2DIl)l(H!1vQVIZT2yRGj@YSP)p`#C_ zcTcsGw*GKLH)%}rF_gm}BwNHC@4B{d?Ul6i8T$tTWrp`O9`s*+Z*zUk9H^dhP!T1h zy&y43Z!Sdmr4eds-22J`w*6_=8zA(WY|cIZ zP62s|JG{`F9^;A2Cxa&2J-)ehhDyK(lbX?2+$NY{TC1?b2) z@;FI+eeAR1gX*qJ<~MJh5sT>J*ST{cH3!^ag|tyGDQO;Ul}Juz2-!AORuY=WDupvq z&N*i^0!$E4B#P)HgaB)(ARs^>N@I%ctw3%*WjQL}WG3`4f$)<`>VrP75p~S@a{8%P zTlzWK6~jz%KT+w^cCTcMnswY&`4;Q5Z8B@Ikn})i<+i%?W4Y-tV zO4@iv@afyBru^#s$xc@CPEhBy#n<#}akT1tK zx50g!6nwe=PD6q^OoA|H8D44i+2T1~wbdgZ88oszGOBEwWBlQjZ)*FqmGRP!Aam;B zRt2INJ<^#U!sx6OKELZb36Ht;PeWx!;ey5DU?=pJd8mNCo1oY?z9;c2r{|Qc;}?b! zuA(IGejhMVGcs_|-;%x96Ju;1wPb3$Zq&18SU$nH<}{$4Q5@3IV>Gyx<6va@5JQ9+ z488rGsB`B&{ztsD^&FpOFx}L#%FM~aKg!%xW@jteCAf#rEc13w^O#b4xkV~!;p(B; z+{@CapYT(dIFJUJA@Beo{|vgNoGECMk*1+WHJqwXDfH}q(`0c>lx|Jlxco8wbOXX_ zs?pCyO>7d4oi41mwOPjgB)}WvkqR{f@O?j0m=80I>|WU>pwlUG&e3Hz&tz2GM92)t zcE`~k=@>Ez*IK^nrzeKHDfP4ZU#=3#6S`8WT#FaD$_n1@^?>yKA=Pi~i4JteU2wQJ z$+pH_s@^(q3Om8QUr&4s)Z%WL35I;4@*WhhE>Gqtd^?mhnj~n7qjtTQ+Nvob(MEFe za{sDA}m z7|0~w!0TL>>x*2ia?Vz{@Ud)7XhId@@s3JRWmJ|L~;rE*9) z*r%;1vxL2WGkTEq)|8PwK%}x_)BUx)iQ=~_z7?>fEB_8XW9a7r5^_-OlunZ7n>shU z&j!Kd^B;fA=$@`P$HSAE?P!H&<1{jV$c?yg}4BEG#n7-RVJ0cQ-6p zB{lxQc8c*`h}*uIk$`eImt~@{SyvMsUSdI*uO^Qhi5YfXyI}qz^@nbv;SW@*^uEgz z-|(zta`*^Pf8U8>A6Y);lu_SqvE8>{>(A6*G$rrXM$mdjI&G&E-bY6`}J^Fs_7zDRAv3?W;Z@n!ZFrd_-H47h#YE&seDkH!s=M ze7&mmHdp`Y=Of30A58qfHZ%Cx1xlZ6Z{;GKBUxQ-e2dLTHoqOsE#3N4}<$(>LBI^6NR{G!`x{d8&k zHDs4ipar|WwLJqXd_27% zPCwctt32a#=H2tRyKf{LdbpiYH;|R{8B~1pl;^#sRqM_NYtfqLCIcierz+;KhvXzE z6E&SJ-eAGjf!ii;#qJg~EXI<2=|@)6ZHA$N8amuRlt)S^-gpmfBZ+O zw}m#ABA=`b`JPceTARwF>cfgg^8n-NyZHzo9WGlJzDS50@2>&n%^_cH(mVA4{<>~sC;L!DZ{u@}F*YcLgd*KTNgMo>-l_%Et*vmdtZ)1S!V9^$++&&+f)JZ$<7_#KB`gUdn0d_AE zGUy+6!++4%%hx9y_jvgv^opwRGq9r4O%A&Vn!MGbzLmSP>7Y^1uyh>-=7&>gLO2qp zDNaKZQo{*+<=qzXwiTcIJV{RZ%j1z-MelTVI(4Fh8aUJ6uVBmP1DCoAqp8vu$Yw*` z?UGO-z(ef-{gV5bmntVT;#@Nu@*0xkH-n(Ge4xY(t5gNykIgb#dH;I5Y<1X4+y_PN z*6Aeyk%AOSXhNUlWM1n*c$@jI*@HDb)M3l^pz}GH?Qd3fStIf`HbJ_y6WAo zucUp!qHeS&g3Iyl}yEg{rBCL_gP@9CnRWsVJHpT)v>}QiHrq6G zGdC~7XHPN`p>ky^{l(@&V1jJBLq(?TdtW)~{5O@X5`$w*n~qsu88GzcUBlF0t9&QE zJqkfuJbH&oJ@_SUL@Rts@Euga+B%f`ygi}jUxY=N+bqtkqHW1V%^CO#7HHRRVqUU- zgaz{S^yNgoT~0P@I{s?gHhQ?L(?~2~C>(vatd!rPRL0VI9r4;JG$k~fy*B>Cn_0Tc z`i*z{ezmF5X7x(eLKvR`JqQpoHG8r$M>A5)Z>-( zTbE8x^>X~4K2Ef8Vxs1L6wd5OnXLTeMgX^sSV$d@y#6Q#i_`4Jssdek0?!3@mRRGB z0bGd72SIR|5~=5HNN*|IMI%JV2mg(|_l{<}kN>}WU03%WRMFDb-W~S5szuRIn?z`9 zMueI{jJ8H=RfTZXtPv|hO9mpeW>HikR3cHkMi4Yc&^y21ANM);-`{iYbMA4De>tBx z`Mlq+@pwL;%SxRUik+|m!*}mPl_T5GfJZ>CKvnl~#dwhrn&Qx}iG6HM-T2c{d{_L^Pl5|WnT@ukC2-2hM6S#Q ztDz$6YPWCG!e)K&-rTy4(7Fw;+{KA&s;5p(h%Jl&eYduvuh!!lU-zUN`XHTsPYEau zeiK1FH|6tqec;W&B$}HUpkkxH9X#zxg@tZ;@l8SR_G9wCmn}->&Xz7hxYZf64l$Rk zV@LWX(t;4q+oZ`e@)I5DAfK%IC2b>Ye>-Eq^A*eFg{NcZVAfYBP1dC#nGnH2lfQtq zl9{fGd3Lm1TzBDMx|Ak8L|u-!K)NgS3QmCClr zIb&k|F=^~Z)(R-yL-wuHg`39D^gVnJJv{a!XOyR3U1ITgH0ONonCu3thv+f1^eH9i zq(h!Z@U)CTH6z1R!@Y(v>YjTiW)l9(CTs|&bx>?0kZ4{`aOE@!ubws*nn7)esFzcV6%N zbUWv@6a#=!rDdhr(kZ)3<)CYizdf&yE!0ES!JD@8OG-@XmXiqm?CZJH8tvZ7lrGB) z8uS7Oq9dhic55KHvFNbzy=?z)65?7{U--1vaYFqwU~rJj=)|O@iBh(`oTsCssi6%G zM?f@e$g)fGz{4)J#lDRyoiTsie_Fg)2Tj{YRmnmTwE9Nx$3k-NOE0iv=Z{$C*c?9p z9HL0NxM-G?){I5dn7{2uSxvM+)}&(J84-o^GdtIQ<8ZSSXF7rqp$~N`k4ll=?)%{E zveXos57VG;riN1QH^PjhaftmS^I?oS~t(h-+5Vf@%)$5Ph-#j z+jF#X_Q!wgEO9}06;Hc&mq!5dOMZu<3*SE0&Et($N?A*$I!2g1GfQT2>Z(eJ3s7+7 z;7+7Q-6!0z7e@?MqclUhCz#(+cf90Xw}L8EICy8kofdJ9GMGCK0R%E~I50T{aL8CLONuj}pet1Z3VRJ~ZanDBhohPC zsr~EAKU@*v7aDEpcN-?7mIkXw#4H5KBejSHs6V`pSomvT(SUs`)l7dKh4mxyo0S-q z;T~#>(w-JAxR%{-(5X&Y0O5vt|C$Q;4eQo^N)bG^)e@;Wz1wNyv zH*RO}(ksb_TX)Vn{?+d$-1V57$RniG?vE){>JP1|#OsM#-Vf*73)e$gq}0~tTnmG# zA-YbFLg~j~-xVM=fPX#L~ zdlFwROCyo<4{KZ z*Mj|N#uj(#nCm@i3N8$il8J1Cjyb?O+PTL}BkB^si6qU;YPy;~&%V93*bN-&puf{U zIUIZ<d zB$zPLcRPXUzj7nhX~kYW(S5z_lH#K;%tO~gr-xOWE(k%P4%U^hp0NdR-&ym+Qqn(J6zAi_zz(YW!8sq{OGxGUUK|+uZlQ ziw(xeqd96$)Ak>7sk>neuvtZ6*Cz_uDRw5Wmt)!x$VZabw;P$ z&&ECD#3^Zi+0U@K+ua%&^E>A>E#>@l-?^X9z9_KsD!u=#sc}#%>4@}1X0&u`ZZ;dp zU3zvSyh2B95UPxMPuDmAkpBaH>=-DEcMSs^?b&wn&>uz4sgpF*;y-82y2 zi&*oI3l@Ll&}2l10=ME-8-I%?i-zQWJ#$qoEXf?7TAWJ1gT)cp)uNE2MbfhZn|y0} ze{+|BSRdXxu?nQ-1v4)fv??v&1lo@*p?Y9-NT5cmd1lBU9W?2eSj1X-#GvFt8w&Z#L4qvugcyNI>(A5f0{rr^B@Q$lkPUx6 zl(}e7e>Svsh&6)H!O=#tE!a*u6Klf3IXESaloRn94~GB|040sK|JI za5#rJbwYi)we`=T%+11sf1(}=O`Ei9Z~(+up^jgX_w+V%o;^_V(=7^1oD&T#^vbOF zJrd_T`QPaZHPuo4h+gTzW0)Cp2N*drra)Gcwzf*U%V6#Vl}<xhj3fhe2`fYK4VHHtzpF~M-#y}7AScrgumkD4yglII zR3|2Q+6bnybG9T?%X?Ifhp23X5}PvSMwxW`r0RJ>Zv7tVITrJR4j{rwpv3 zq?d`I)|L-e3bGYtx?ST{%9eI3IM0-7QuWCA-X2IG635q{bT=eix`K?+DOBvJk^J%l zbTq@_b~0pf9Of16UE`St2bi!RrNdEd{BgWA1^NJuzyuN~aC(1PMr&u;?)gP=F?}J& zUqB0zcp_y=$#EQw!sD?W^*vIJ3{B+Wl%C^>AM0>Q#W(+r!e>eQ#Ysul3|}2-(%g(> zNU{=H{l9AZWxv=VEseevZ_+fdjc`Bum;wWgzpJan`#0>A!}o)$U}#e*(DhBE1A3w9 z1=Y&4@oi_VUF4g&21l;Z+`~r!@6EzfZha_FXll7e?X+#bx1p&{0;5AoL4mySN+JyA zmLr&1QAHW@IWWcdABbW->LQ%eCP%vxo8i^lHl{J>q~47LgDoBIV23h#)N|rOpYgk3 zmgGdi?UX0KYkb68N*CEHPv`kDHj`S61Lh2Vm$fTGiykO`9X|T{;6$E83=ffWV84jy z{O5m|Df0hBWz*At#g)@u@yP|Y>bYxSI!4>=#SoU@Xvi5?Ydn(LuJLX$>y8Vv4~}D% zl@*~}p2d~kCP|0lV6QJ7r^k!f(5SYQUpcXEFvvs725fQZJKzYG&K z?h>MZoxEiDTFI@p^e&|W57HyXY2`dOl%h2pjyQqGDnhLzXRVU#V#5PmvM0eP} z13z4|l`q@M=Hp`+`E&%|cKzU-HGh#$3@0x6#bYMMwz_r;6HB*qD=_oKx zG5pUCie;a^JTjWqcbZ`QyYyX?kI*A`p_BIoKDV8xn(|I*M>&tzVt1x3lo>!)?-_r1 zf7G>fJ4CdHjh~~j`cRG8+hW*n5=_k<3-t*+kljb^!KMt3gSX8OgamGZeA2_>LmmL6 zxe5>|n!jWdWRmduamume{;*7o4LO_d94v?)HF@q4R&W)qf6!1`xN|*gY&BzpmwN#nm*Za@oD-x_2>!urW*6 zb=m!~*4XNa^;vl^r7fcc)BZDUK416~=}fOLG)D>d0cR(A9%A6wkkTcdZ0& zZKC+$pr%C0OT;V(%Bw@m_6}^tGyyd{84E>YB56wjwP%FzsSZ&gk28TyV+i*0#Qnsz z`7eJCCAnT;A4r3?M;}LB^H;Sz^J~|*KBmaTXI1%qcu;tg`IS`vL!~=FQ=$}!Pil4L#668Scc%aqWV5Ya#H_$hotrAif1hIN&{^Xv*F>WERJJv zZ7r`=or~Yu!Q&evpir%YT?Y(p#E%XEUWhf@BFd*y;pE>y=ptRF?L_Hz0O#0e)}2<0 zG>Mbq@Yn~KmQd~I`>0Z_j^Xc*13Qy?KNY{2<-{AERG;aRK1n`Ki47oNJTn^`Yf#x> zAe_{S5Q?u<)R)$LjY(4?-((P0F$fsE@$0tR&!ePgEHM&CBPm#v?Dmkhxx}f2Xe-fh zqu+r>0V4NxETar0$4P(Z+MV!~W3K;3c(99{6x8IA5MQR5HM$%uP#emmSW$zrRBgR` zUq!Df-ppmn+QtJyE%p+r0jog(jra8zvTIsBpIfyBtB<$1`u=@ZYiM@`hr z6TKHdpdN8Zpuc-hdqLkFzpfVaeXiZ`q_}{*ZDmcr?W=NG{DHvoD#?QGv`L$-9Tct& zwMA*bHuL663o}b`OMPA?6oX@tCupj!LXO*i4s}G|Aq+=4NE2gfeB3N4^nnrn#eLk@ zT2lftvQIC0e^&k8$-Tw4C4^>o7MjJOqg_CKfG(5`cV|98nv|c z{O2Q2|NYT-7T_f)b)3(Tg^N5dE3{Zb1Ma*m1RvXeg)(elq%kDkrBAmRYA|JU@Z<)qF@$25u5e! zAt_JB2=`8i!B{dcbjj*9kn=I-+&Fl<*d13-eRQc*d)P=SWx(?ZP#W$LATlF(kUp=G~Z-;*^b}zbx7gOLX_q$GAsEwO-{5u6tut$LrlI- zwXxmy$80mYcGWB4KS!F({g+DZx}wykQUxveJ&t(e2_wwvN?WNSE7>J@1-TtMYN<$V^?>f5Ts4YP z>D<-h=J8=Q6xMM&*0`xa;TO9`CPyRwM#~%H?Z%Ls_wLNvy|{9tzO5BgWjkB_bh*&0 z-y&Zd4qz(qWP7~FU7bXyTIpIdxXgT43t&d(4seL1)uZQdCp7f?Z$0s!L@r?P)r!HS z)JDvtI487m3ft<&;HI%JMMtLne(j&VU$nKuoQH zFtsqYc2I8~S?hX{e|~LrF0`>d(q=!WrbRNWuhT`s^5S;rKwpPQbYc0xC`*VxRmxFv z@!SaJt>Ui}P|Yh>+IUWaja{<*hwnFC@~NuH(G%o{%oCHj5evA|rtzv(hJwltcVVfD zHXJ!Zb!EX>aytSmt)4myHO+`}m88vZU74w4BQ@+J2k9XJ6%e6_Oqu zCcB!?-rB%9Bl3kj4H|={Y&*KXQR%cAbrA^UT1S*e$qjSEa>C-PEY6hE+HNP+Q~KA- zL(yK*i;M%!{leepE`+54I7ic`l&%^{zl2Sa-5znyqC%oz6~KFvZ&MPF%(jf|?@gli zI-g9xB+f0_IgC_|LYa9q^APJaFXH+NE&$*+)OXUa;9{1T3aeb$NI&iUJss>p8{OQP z`fG?EK`PqO^C4{T^R2LrN0zT6TCmD^FW+6s+6u>UKt)ZFyxt)FmATOSdHFOc#}h(| zp^-a7+4XP53muGYa}X}7Wu+Mt_QfUNuzTZJk`PedufDt-pHjTb$jPp2qW3@)pfm;P z9P;$Jm)Zqn4D{f}_dN)-9GV?1PieOE9HpDP+=EG>N<&$X(y<)?`37U(*C~}xw7PE_ zZbqT-Gx??wRhdln=IVUvs7nGWry4CB5+}i*Qrm^t?2tv+SYCKqivGFn*3TlD2Rdtd zb0yW=)W^g4g&dtTCq*$a^**ki;YtN^Dn+sf9(gX{?*Htf{coSlna2Q{F16V>q)cj( zNdETdhdh4x7gUxkf&`4|+d@vrr~xtcDGU8hzSE}G(JSi!V{Q{aW){x~P3EbEZH77A z8}i@`q@kTy+pg^*7Nm0X64RJF&X7m$N9nVE#YPTZ9y-M_O~;qIu`W0<^$-X05wLxl z@i;(-(_NSz`Tx1GeRW3ENDjeL)rt;p7U^Q4q@w;2F@t5TH6LW=hUa z(Kpg$N-5g=1O5VeIHGD%eq^!B@?DqO#lv|kxBu5$u@fRElMoE1bI-obZH;9)P!8q> zTXvxnBB}NvZthGon^6z`WPFTaU#PUnfLZ>tHu`xrQA}TZBzYKBcS*p{SKrnVUYUQ_q+E~`IRE_VmU`qkexa*Ij3A~h|ITU?S7nOB zF^6F_Tkx%Fe7Vetwm@1}sZYfEmoGA{#`s@I`$Y(IPmt%(W{}W&ihqzW_>F4bfp{*@ zW;vYa#r5cH{;}RXn9dQ`24N? zuH`(hw_ywIS^1ilE=EoY5VV~Wl)MA>!q*g&m{8ZPnv%B#)G^l@98&=Vqe&rH{lpnK zP^ca3&~9)9+al;4t;Ey+1S!_f;McaFyuQBcvhq3~o`;fo?s~Uk$x`@8O8Ihmsk569 zY~0!kRcIoaU(k%5073C0Rc~)PCcA9pu_@~rNXsU`7(2Mh)$(f7{<~(ia$vsB=N2W} zW|aDLd*URC0RygVfiAV5UhDT6iYlIYb685|Z_Uq!%Al7o!TKzV=Bgg=Me9nx=Hc>w zjt&7W9t6UBlSr!D`9g{Yb(!P?V0z#x`^mISAAYCNE5vhoYO87U%>AGK3_L%w3|hFB zxf8=+sSN2l%E8=-3Io~w0No$SkH?hR2S|Uys|?_AJ8wo&TkA~ z9pN*Uo4;!IaUR!dPX_RPp+m^ngP1c-{x#kIjYapn3Mk5q{)SqUHS2M`tT z8TRIxIs60Hw#tYVjFvMZk@(RXK}+EpvT|TmCLQj#R8+s8?~CjI$7zj~JC$f-L83L^ ztzf)oA5QZZd#k$k={8H_y>Y>vZE%@08`hwAwz=FzZ3b^AKOD1lQCWQ*zZ&IF$o#Anc|}5n9X@IpHg7YwloD7p4UI-?JA(_RUVey1?<8o$Ci6L4Vk3Q+@?;1#>^^xjD{x zAFZ0Z1SqXp{f4T>tMaR;5(mzi+BiQo*DJq5MYa;~a=Q1Q>c>y+SYN^lrFo1m1;AC2 z74ag{Y2U!Cr?B2Wv9?Uq$?w=BYc-(Y*}T$4?8R-WeT=7Rp9@sVT7M+-*C2#M9N{FT zYQ(IlMUiJpuH8fre)kstJJRMU$A>y)Oy$ily7lOnighE11Wjl2ZLuQ5QtW&V_B7tR;<=l({ zA{^!#x~qrampRPtG(Z07v>r1l#Ziu(y4LD8!F638{S+g!|72n=>b2-LV=iih(erx0 zyKbpRJLC6!Yw6#mUY+oqkmD!X?ee(2}bodTv^qVXt-YLuPxQHd0hVadUj} zBh#w;SfmimR?SvR6~SK&n)6fF{J-KHn#VC=CX*(eg@1t;fRwP-_MC%;9KY9-&#n(i zQ;P@`tTK4+eJsn&J-;aHUv<=Do(1KOLa`kU_*)*}WS7gACB`lD2ht5#e-HRViY)J{ zp7yPnwv>`nzvqH!Gk*?|u4p+)_2Wn8Z8)xz;z`Z$+HUMNs4K_ijdG+$WtiLJWZR+A z;pRRNAwK0@W@D^-)zd?lS*02lS{sXxxwuaPlKb?bq$p}qMTSeu5EE3)r(i*2wnab% z7FteitTIr&@Zgj^eDT|x7_UNkafO46dwi1{P*GU9!5E(-K2u+ZUpE-}bEwbqlmEn? zKK}$9FEp%?pg)s%L!j0w#Ej0`fex5l((l=YDBbO+JI^^qQI(YVKZllRt`PpDZITFB z;c7z;PB~3P-q|i(qdp#;gBl2fmo!wO{0}8AckWTl@wW9xZ@<5t@q!U?da8jfJ5*%B zXNh{Lc-pjqcP_Zro%S1Sx4Dw~;FF+&DHtF*nq8l&Udt?{N2$yP#TRm;IWceW=H!@e z@e8=zem}&-8Rx8_NIj*Ln|e37pbxo{&HrU(56FX_pGb-KLp6IG@4Yk23z4S%IW#{j z?&d+0Brh$p=zb0JrhRAEwy0xO5C%v-y%Nsk5$XsBz?I1B+rkx*O0*IUk-1cix3&km z|824aB-?7yK5OF<^2$sDqUWYZM*t@Lxk+s>3_w=b>d*D zT|>r>D&6?PSVWXIY_D5VtZCpic-Z~wt*%@AK=srU(B4@nIMPnadVr2!)g);W2#`ge zvXVDpam1OXh`n1WstZ-AG^#1tHY-j1OKW{X?T1Bf&H-t<53z4yaA7R$)dT!Tk|Sez zH*&=A{HO-;;$9nUwy(hUMMwB;hE^Hm zNedx2It z2OHvFa^_Gvlz5#z)u$%>OqO6*jlmymYHpO;V!6ZE6grXcdmrCoC&UNY*?$ft_rZb( z$@_VcZdjjFQ~g0x_8Bs1s_3Dq?|#d=dTQj<(um0QZ?6`|YOk%FP6!w5?Z0wJ?s4hG z2(W!sZ?i+IR%2g1S&Lc+1P)bdAjm-Surt{`O|$l9xaVS>%M{v6AN(WqFh5TL$kyE^YN^O3GbD z$r=Yo*K)&Uu7yAbN*C3eqFNk+H_iHGq?B{)JS?g)28ja~sel^*o7pJeWpwaJWkk({ z-F}{~LPey(sIJ_Z-yLESw8-21vTt~IsV6|yNdMbAVWSMd>{$sL+!HRdM}~O8$-cv^ zF118HsRYF0XTN}2xcrjkl=suv*ft6pKx(*;(ramt-~8RWG(5~P`ND`NZAVo`%9GdT z>Ux=9gncU23JZb;g#*2^(l#W|5va;OQ6^ zBp}zNDq+qxwnFh5+MbV+hbKV4@S6ELTzBZXf40lN)K0%tSaLc1Y0Zi(;yEG7Aa6ur zyz+ub>>uk}r^90+SElW(WJFaG(AtID%BrZA=)vghF$TCXw~{SIUTWRDO6A94z&6&^ zn^kyv#5nz%+pSY#$tNdurM(}WkJ=E(PQd4z5 zBSc~1*tSWV%k}Ma*z*>VwfKoRMdeNA8LVaI`ocP6P@X*evOt}h9q|ey^WVQ0rVE-H z5{I$6W_6WvR)yJWa=lQ%4wwSXSsY}IK3Hh8WuAyU8{#qFXMZuS1OZ&i$18x`r+)hr zDJ}nOC&UQd=bY*)(4ww3KcW9lzy|E6mFS^L?s<8HKm{&zN`0%T2FxH;6O4P>;tzS& z6;B&lWeNdPnZGNKQ>g#}x8n;Kzm-LnoKjKGs3VIPg-HXAnqt4fjoy=%P@+?3CtnsOKWU2}$s8PAU zf50B@^1Dge&Ei6wmIoZt#V592oz1hMx(1Ze>tR75-f55avz1h1{t0XS%+&A1`o`;26A$^#3^_u&}F=q^l#y&dGN( z&#=Ka;z<|6tA4Z)x5rzDSke4Nj=BmwPJOxsCjUbPX5ig#YqpOYNLJF zEYIn_$k&vjK*=6ac!)^Ab6}Sl1>LO`lNV6F%o27NH>Tgy+Vt)_Hd?Y55Wmaj0q_|qcA zG^(-fmGXs3A+N8fya;oro^o`fa~W%V$j{=AH8L}(QrH%)*_y~2tlDxD7$I7lDR_Bi z+5n6xUnzeMd88V4w>M41`suosSbo?~faw?wiyAk<%q@w?MTOX_Nb<&mr8g4B>yydh z58P544WmYdigS)}W7Z}*Erlk+ zV!MGY*npC2e{G8DiJK1l2N(Tqu{;V>Bv6a;Jx}?TX@Fnc`wAO>wh+BiXUVGUt9@8e z-nX($&&;d&bEpYb&7j$3dKh*4!1_ikM&R~7J*wDRvP_h3^RMXs13kVAcD?6zeHj>{ zL1?*_W}ma#&R^cn&>vMSNCqZtrH7yJ*6Cz^o^#1{eT(4)S=DU21CAQ) z2_`z!`_b2VSK2br=0?kCQ&-TvraW@ZRFzXJzBeB==Ci@|=je@8PNfv%w5R))9HN(wFQ|4NjS=yn?>-Y22zN+b|Q#QJq^j2T0>e&EC zHer`H{tcHBia>&^6A^Mvj3D1a|Ar3e)kmKzymm}|r$w!}fu?x#9~gE|80dXSwxWb+ zS=Ks%U=bKpDOX0xe@H{&B8Ntq5$okD2rvJ5?;!qas%|y8`st9Gs7j(XoO^%@id0-y z#<9&{HwW4l72J`O<7bPNB_4CrdrR2TYKn`Ws@@&xr9^L$`-OzHd?v`>@RYsE2HyC9 z>EdRRm0)iU(5cJRx`{(GuxfkPR+jeEOu*XzjU@cGR47xFxx??6)crG z!Pqn74S1`!aQ_E`kQoQprhzg1Y3$mmD$z{fk#p;g%N+ahEf5Ao^PtmSuH7 znOgZeQ{MOw5wB&=6eF>?m6P28mfo^XP&vhT5FB%^&qJiW#I-N1D9gOjT$dGK__@N_ zT_L#E*s&n;eg}TltaMR-G+)M|ug;-`*g|);IC4Mx%vJg5<)^aB+>EjneqREoFm|B$ z>b8Aw{3OiFDl2#GgsTd&F{M*DO-Zov^qr_G6c6G#|VfH6m!(PAKE?Og+_>nl%E4)>{G%#^{o3tI3~yQGPiiH@T;cF4uqq)N;j)`+Y$2#Mji;JNA;~-@b5|#rw3dI28&E$q zy&a~k>!dbwaJ40CaUG63NpJE`{F!c6T%$m8XQxuNr^$kuk5 z!G5W7SBQ;8ULRO(rz%pn$T(lf4li6@#mWoUf{-KRZT(g7%fErYvSaGmo&Dv>xZ6|L zGaV5R=-<2JKg{49`vThcobLjhOIG?> zH?pG2HkQq`NH4{c>l`nu-%(s@xp`f*jn1sB6uUwLn8;F; z_Sz3^9F)>&5fBuYhf8*5Ehdp?WrC3-Jjv?nyOS|(jKSBnR~;e>-d8Xjf7HBx8gvcS z;Q;YNKXh_Oyg$E|{4V{2R8Y4Wou^&i#540`!#d97{l=s!H6SLqD3vbGrFQczz2k&{bxc6tG{Sd)G~8 zaJN;)-!eBe+WE7IQkjQ`iQ}NU!8`{1lCX+thy4Lc3@{6whOA+b%JE(>)foJD3#Z^8!`)N%R!oTHv z0MFOkfx+Od*{x95zSaWz)mvYSE2=J4hVf2Vh1!Q^WCQ|928ah#AT%mfK|HRh_&m?lx=wFlaBGP-)0A&2)L;ga#OXR+g4D0PO4q5 zBatmYqzbfqG17iz1$wm(w`kTPU6nae@3QRdprq9caq0yUwZIclNLkbKJ^6J!R>t9g zHTa|1GJMKXX1O(HkbpcVqr)G5`Ax*;xp@!x7~rA?EG&0ImbVUe^SL{q`RD}N`l>Hu z9>3UDGtqP8EO?i`wSX^}|Ev07kj_Gv0JlRYri4%>ry!GA!oDjfF+Jf@gYT~fFpYEH zyff}HdUxT3_V}8-+E7%X0e>TR&ZdFt&^~%_m!B`b&=iezE0NT8lj>|`q<<%WOL$fv z4v{z{=*IjaqgLNPMaL}vITW^^eYYjmIv{!xPtBGmk7I`}?PpjG3{-K=>|_M{R^@DM zfPFdrMi%zYm1N~j(yvIjH6P1MKJXl7?VFKN>oK(GJta(YK%e{Qu{*vfVWd%`#|@{G z(>GF|CVXqDX>?Z3&5hX1a}!k(0R)zZ=5s$T&Yms3jxyJzmLF!1m zxVT+-n;do|ye0&3oIe#7-4_X_DoQ0?k{Uh;vN)XabtX11AWsY_RH(f=}?%k9X0){0O9l6*qe}+04Q(x1}zl$#(fSywx1)I%Uw7CJ@&B zSzmDNZ0s~l!<@1VXpX=|l%*=|X|r*+<9Vuy*M?80>l{%o8u%@G*6u%z%kuRd(*<|v zL1xY*UO!8DKis7fIA9;8$h&15jehm^vI@&8B|PhGkJA{`OA5UjoJ$}er+*i|IM5sk z**DvDeG_q-|C&WjG9B#dW7};`h%K4ru>MtYWs{yJxYoryXK-X+5~c)M~Co+hP0TT2ahe6|``^XKjt6klCWbfD-@jfRC&9`2%D%PuMj6$mo-!eZ$)X~~ z!|=tHR%su%xiO+UuFw7)a+-7Ohj5*D^4ta{=AO*^sh^%P7Tqtfoo$s=Fd3x}XYvnE zzYQQ07NxFSyQ~brL8&(yH?TmxXEuJNKTJByV7sx zaFWx}KAmbt6a4K;&hzrb@fGa~WwkR(h08;jU)IvGlZE1RP^5Mg^!{iWRqdLHIf>7t zLon`1>8w+wMsFWbC%<|-WA2`Rc*7*3qt}k+Q?*xzk!4s;@k}JQnyf3O36vf-ymMK= z8zJJ?PmNb+5g*q9loXedQK~KMjBOjPFHLa|6g72De9thuQzWvhYAWF?jNEM18g`Uou)QDJ!&+NP zu17@<6S!%gMA3HXLu5wZIOrW|Q5g0UZEtFQt*EM#c2?!}8De6jj&f^=hj@N~T*1Ji zdB<(Q0rH2J(=DrW*I|`bes)(&NAJcqM~x{Pc|f54Ag~@>31Fx?Y#sU5k20cCn6)=V zSz^+6%SIBqvU%DQ-Yu%bc&MuYgm`eVrA4HEY^f=PM%yQ^j$QoGcczymdA(3k--Y?# z<&c5n^did9Moy~n=TXxD2o$GVmALm8`{oZgDvmWa>>Y7mStE& z9j2VJ$B!aRbbmx4*RoyI_1t#5`N7ayYy9gt{}>_;gUJN|2hV$?oOk*6>&}b4G85}M z!RtS7F)mm=3s74eP(Tt@RN>psY%c;82~Tdx!sqy8MxnF=lDCTFH1Xx#p46r0XH@>* zKr9pm@eH<8gT<3t{-NjwlsfI{a&Qhvy^LRX`rzeYXHco)vqH8{!l9wn3#vvhq$0mP ziL25wyI5H(Wf8pFI-%Wf`Wx1$P)f9*>wB5X-~Nd_DGd1=!B{K6Jp$0zX1`x@yphd+Tkl5ge`?Z2jni&43cqo}5_O z`mUc(Zsq#!$qn#QdEI*N1Un&0(vEz8`z!>`%NM za&})X7QeIcdE#ix4c6kvFcT{(EO&A%e(xG$5+Lm_vK?{rEfVa6yKQ+|XxaZ{r`Lu> z0yEG}{*+%=Z|Nt2DjIgrv`Gce)DNYb|Ah27RqB{K);MCA{N2&*^0gqljHNw`?3j!2 z=p}O|z?5aiLP2?Vp%=qIo!XZhId>4eeg8IXV!S?0t#s?uv+R1+H$(4N+}}^fJKpS; ztnN^mu!CZ*l&sxL9W`ib=wZTG$C zP=X(-da;ku{6N(Y?X*;bf*5C{RawnhucEPtNwX9;V^!%Dlzi~!5G&uw&U%Ri(d1f! zNYwxhZU`qdwt~J*y0@K(R4c)PC$^)VmQ^lU=bS);5O&QbFS=k)j{_lh{_#8g zP@*8X_?P7g@yUU!{Be@tPL<_*y^GCNgXX{igT7V2av3WJRO7UoCIfauB-CdsdinZl z@JfC)+QY_hKYMlWZe z3qy`x?+`8$xtHuoK(mqxY_t3Hm6et1#!GxVEgC4F65Vsp0D=0#4G7G`0}Y6h`%7vb z9vB2mWc$Lj>rtln?(5gll8{ps5TFablun+1Es1*IK!m_g-4aU9PI&m)?Q^=t-yPw6 zl)ka7k{s20K1yX-t0aWnSR{?bq9NegU{<-3Spgru(u36UQv0L}x4i_Y6izb?{;ehd z@fTaIBb=UpgbmF6M!&z2lSRwGN6RN`=d{!B{rms9+`a$b>-zsSUe|y9Prki}9{<1d z*8|!=>^}Y%_kZ)p1Mn53;^$*pS_fX1%!!;-4NluR1u6W^5kH8N{bwoS|MHdlKSer! zox8vJ;cVBdwigChn>Bcjd=y2GgUya>R*FLJldKxuUrCg8&VIQfSzrI|VXB~G{nejx zwKUGv+sL0E2QPqijG(JJLHnrcD8VjUP1g=FrC$3%Z~z0hpM zQTXB_GaTtuy+9`)pr#c1rLQ@dz3zF%J&u$%wGC(wkBfb|o}QjJ+RnNBcY3@#$dFELzYny3XT%BX;R0~>|32hZ_Q3OVcts%p*U`IDV z%{en5#)1e!zW@1UjRH^S-|Otj0&DGbv15`B1H6Y-AImkoNsZ>EH&L@1GdLG4T)$3r zR@3aUgHMmjTxMy>m71h=B<&Y!;{J!`?d+dm{ZT7&Ge-&+N)XYFzTTL9y6{=1Q6msSn_+f)Docti4*COUm6A9k2VPMm3t^1nD)E!|LqZLUX|QJ z2df2lT9-noe4D(ii#dE@4x}kje|*Rkv*d-iEwepY^o64vsm>RzCl9%Atwzb(zN4#k zXIiGuB_+2r{ z>d#OBOEkDtGGP)GERjs8eBa1_?H#_s1x&mT@OM`F`8v&GGNl=v#ZLBO(6hegQ3$ zVJd1-e!bU>yGCe|>E-y$-iv-hvxZMlroK=#btOZ=5A9`sbvEU4~84UReWtt&kE;5l>LxXNXSB37pNolc#8ynm} zuhRJ&t$u(@);7#Iw zrS1v;wUS5M>DcZ-wWHrR$iue~S`>QhBC!%oGP$gbymlO(=vd zVZo*50HRIHC?uMKiCO~A}NdL{$IJl6n-rGB;XLzD43sI@8><2@t z63(wYqtNTRXX|m*5ACiTDLz+_Q;|VKiz+a+11bt~CbFDI2DHy(&rqG53@hd zi5-Q?>1c$kde;WoQ>U}r_@;}ep#E1FYIC?cy?jjjokwk2DHm5$->JGdS6Sb??y8g^ z4zne*pm^_2QxYZ+FDK^;RTFlaKohV|7fAfsNWnUir8~3FDYM0jGKx5&nl_xvCPs^?|bqKWT)v)gTGNL6a z$f=b5u?A0bl3a~aoGA(BLf@CtBQ&sYm%gyn_`v6;9p_x!Z;5d9do;llc>*?*;GI{R z-Xl;|XT13NRn3PqGrzO9Q<_Y{dQ_12Xbyx6DX+SS49tw^9NX_XkSimV@uM05rvIb* z?EmH~;C~v{{(pJg|7YG}^1cVh4n}s5y~3})2D&7FutZzVGn|$Td|!ZnjP>6@yt$tF zu1}yJS63MQUTxQTBjx{K@4cg%>eh8}>4$vs2!ICU*Dx;&Z12 zn+RDpEcZcVwceLXfxQdcE+yNLHtgVv=a%O8t*&#Jg{$@mnNzM=@za+_-Q(@PdmFk( zcY9Z%qoAz@3O2P3@KQ#YK-zfqANBTOj%@tXQERr}ZZ;5qD&piE=xi8h3>w-hOf69n zJ=(b@55063-$67Mr7Zk z!OV4ZTl?AN=VLGjUl5vrdCclnn88*oSZ5$(?z6hY6mct4?JqXOV-bFuM`j{vpR>5j zf+8SYk;K%{HwuT%l&sDeock7&+Y-I@;(_r6KmBrwjcvm;%-UVLCVkFvx!TH;4m1kY zxoe_Au(nC{54N2%tW+2RtgVrhOoi(M8fLZanCc5unZZVQD0Bj?u1{#Z?Q-Q{iy;A) zsuhisO8Yg)W zzRzE_&$OS{F-PZq znd;2e>ALsfgg!P%!DA>zUeIm-6(sAFX~gnZ>3hWZEXSkB{Ei1~qhbfLkyLH>W=pqV z@YJ7@5XO$s>*tY~(4Txog8J5@7$4JMDKkDopMt>U+%y2tX?lEWaRe7vLd!0d>A-^m z?HJi!rit=4+q~lm?&AYVUqya##9W5++AqYQNggYCJN2CUk5VwDfVb~ zS427PBUPJ1hQ@i``LA+PiS5o3{eI|&y-q|Gw^$wF-ADoX44W+R7*B*` z6l*3{n=BQU0fCNwO=*eymjZG(`cw!*Vg_>7bJozc&#mlIM=59HF3mYeTAqejw%*jl zbMGAi3VA8k(t)O6e?1=BtYZQ`dSkBqVQ$6JA8Yq7BBp~6CEwM`jk~6ll3Q@nK*sJJ z=wwBK<<%tfzzmxv46q)}7Ci(K9aW_PrvYaR*bZEqgY&6&L-~bS1pt84y6#yvp#?2L zYf0XI(ONG`AAA;GXbLW!+m-4Uuv5dHT>LPiJw%ip0bS~{9}uiN9>~$;^HnorPy#@m z&MAUs=W3?!Qc$6Wn_lLD%y#t;76qFgdfqZ6G~0AfDliA(iWjf;i!}e4dMz)V-79P58oon8bM-9LO6=s%g zb3xNnJ3honJu$$JGewbEcJu%0CiYMCW&f=GeGjGfYkQBO)yz+mdm|i|^>J*kl%R=+ zeTIgkMuIN!PfoNMdZ*}bWhs;9_1JDE;vI|!j5^KXu1Or*FM5QEw64Nt5>6CzdHYqY zeC4Y#IUT6>Lqn3MUu8%wTONOhutx%2v+~T3&m>ekshd`QzRK#0W?pC7b<{KUQf78Q zZfQMaT!40t7md}U?jG+J!%Xa58CpB88*VpIJnfJeR75)WVe#D_R>c0$d~wP)(X+ea z6H?jy1efO_gXNJoy9lr4H3Ar%AkZ_DU=h3sA6i1UYaZ{-^Lo2w6 z3To3EPH)H?Pt2azHn_P9u#^}hnP@-}K~;EXXb6?A%Y3U@J(?9Bj+$G!&#PtXks0{- z@b|d70Nm}*d-HW5B|Sjxy0Kp8UDLvyu*&V)-RpnWAG7Z&NsfQnD;X|l=+ZGRDy$H~ zd(t=zRnZND71YWNdp!HBRfW?y7C$+f^QW*x-A-LZ&o7Q4%2vg!WoonnYk;sLk64!U zmJN2YIA-heR7R*XbpCZ$WaCL>fxwR@3BWmA8#YQxU>iXzZb zvX98zT~}ZzGc-l^pgs1F9}lOcBO4ASWjzsjw%BrkartGLIexQjZhfw#66J)iTU z$iil=b|~a5T=DLbywWw?7hAo5`=A~tf2r}~&no038~g}z@<(PCBk&gom?`=Nzz9a1 z2w-;?h}%kM#uIC*vy5;ZwL9;l2P#mT#w^n_`|oL8$~&t&Hzy*-;y2pDJ*A|Muj@SR z>GSW_0})mB?ab4&fj{?t-gyC0W~)maO?Y^EtKlK_XHo+Tn5C83&lJnAj?YmdIK` zL3nO+fcct-R`9}3W#4PztOOMWc?(m;c?a$;bd79+y6oBS50a2u?Yb`zPwp>uH8qD- zfKngzn4I=xXXu8i0EZ~%`J1vSU73>x9x3m^ zLO5dyM^nthMx!ceS zZ!De+3z34`Z?vnLI&Q7)d9fTB1ZHYs;UZpoiUmiyIW+gvG0dO}SBJtVLr!6mK(^4~ zCFooFeIEN!p6Ps_d!}9aUQ4DdWW>uhMX1bXHIsq|HCP}Ft6VC;nVPkc4QR!;fJj=) zVgHj2(Jn6>%@ngeoleemTiYdV{>Yo&WwZ5j$_edPVuZ6j@?iE)PyFQJbC*iu@VQ$$ zp9NpTZ*K8Z@~6lw5g1rCgPH-EM^nyapw(ro3veK?Ugt0K2rpX;)V7D6Jb4vjc;F>CAch-boz3S$iuK8dzX>b*Q2 z))zlWFs?K-LBK3PuETo-c$!ej0tuG68*=|Uz}Z&{roeWWa8Y%1U!sx6=Zg z=<9v+yB>p;H+?KH0bm5xw&$>qqH?j$4&UM; zGQ8QevRg%9pn^7uoFpo|Ii=a=bSM43d^{&Z$8~CZ(QnQ8JfPXm+ARC^sHKpl zsJVHL)9Z?Hi9r{yYYNZKKRtw*X%>QO@|UU(d8I+t|A0DRwruw-AuHg_@2`YT)ki<3 zTLwS&Z#{VZ&%ts<|IqF;LR=squ+{hSQESNr2_@aSm^CeL6Qx|WdaZ~PtUt1(gk*Fm zGzx^}G4S3(q>In}%-z^0z>_ye{q;;ZKCKGGZh$z4+e;QKor>bv8m>^FNL-OwPF;+M zhlZfS(@+aWdI)|S60&mwlRwo5Z`r51W#*O*&j<850fScypMHp4qXHdn9y|QH$i`nt z^wawx#qs!btQaCAGV6tT;*wh9)%~}3iY40{V9W1=@_V{BZ1Ft|<|1p1=B35r$4|%U zhKb$F?lG5S|F~(3*M0w8!kSPv96dZYw5#?;CS}=QL+r+-m|LIjC@u|O;^Yw0Ek73G zeV^d%bQUhj#~Tc=ARYxx6H}kcfA@eMtM_BVT3c?I^7% zzFlz>j#kj=pBv}ur{2vaD_q-{rBvzztPk_%VM@WDIuVZ^hs3^W_Gp8EC5HK}6Yp+wPRgy%>8!J|D0fp2fW*xzLNaf@I5 zVNp;B{|5YntxkKz7BODDDGvPc*Y%eJ|JFD6c!+orM}P`H-+}cu)Jk?M4qKnF=zIYK z^|cXLrINeW$mM~Do~9n(Yy0VfJM^TDZ$h;H%=36nNA++oAz5rDxo)|y@{VzxiPb`& zmysAij~STJoCWl^E!egxyX`y1e1oAMvS=W}6!*HA?cO@$-vu78ojuFi5%fC-{&b<3 za!#$t%)+GSp7%zesp^oE7kcRW0ObuKy2jgQkYI_+KzMJM4H6$=Y~?CH(>=hYh5OAd zOzk-i9qbIr-v$G*P#XEgVORCSeHnJs+rYhNdV=k!AbX=O!i+YNNpVY1=P`pVWOo~M zw6C-GNKU8kY%0nN&HaV>zD~y3t|zTy&8d@@&!zCSO2oNblHt60)afH_d`_rcluscBK?WevRVR1F(AgRhR((s>ooAt}9@V-)!k6#=-n_A{agYdVwyox;?8^tVZo4#mYj0`#iADi%!GO3!pLiDln|Y8t3W&G#++|@)3$M?lk>>@HLx&uMm(`F z;qA}+veDx1YjI1d18G4Tm$rgi)C9!}QlCtQPdRqt{u+H-d=R zbqrkhK`IBVfdT&XWE9l-sQ*Dn9dHoOjp9OI>|!6x4$_Z!R6)R7OgGPrJ*bno}(UU?8>p}85|0cL=l z5^c?2HeYF|BD&x|5X8c@OlyerL7kf)Xa};kzE?ZeU)6Qr#oA6tYaGO;SIYKibre&S z{M&k)nJC?M9nJeO`i`x>!Ro<=03r@1@`a+@>w znRX_pi$@N}^|iZCtXHipiPJTn^TxVWjU#DJFk%ha9_>V_eeRw9XtU-8q+lvq-U%IU ziN+7lRdqjRl#qH%gjzpb=C$W*(n8hiao!|DbE1UZJRP!%TfGh~;6QJyOV*H$JBJ zfHcP@uYHJ8HE?|sWFY=k)5lGj;hnm~ewwVycbn`e4?+dxVokvnc@cCrKQX6reV+b_ zH=5KQyHu;=1Pz>17mg~714kHSml-Q7_ljqG$y(~4PA-|?h(aY42tye=DC<(CR%0zt zM+K?h3y-v^nbLAci99=SRsH!5j`wQNFQ zNzADQAZ&B|hZUWP_lO-1)+XiW9$5&F8Um+U)UCb{P|VKLh0Wdj!qYxO1CC1J0#=TI z;Xy_w0E)ByOFl5yFgNS-WKVJE42x#1E4D(gzq1mx@?}Kt=Zx&(6rth9_~17wcf}mW z49!Ap?0UQ1SJ{gH#*s`M>)PhoPmzZXEu$$@fX z%}hB|Iy7K^A`cltqF}Z5?Z*0NK56nsso1M9Ls7C&m?C=II#FaM;bxlmHO5aB9$)ROjm`o9gf7>uk(JUX9|C7=<{31 zjzOaz))+NdDHKRncU&G$zz!S>d2lE6xKknY{PYsKbGLZyUcAk6=z>^t!>k7(Hz#Wt zGCjq%gTo+Av1H45lkp9FgXm#dX_;j-Hl!q7qW}WwoQObC)64-*A3F?z;LretR<>`iZS`m0;`ZV@ zZymowVM@j)uGqCrmc6DA*a$f^&vT$Z9Tpw9mnE6?h`8g^qck|uNi`wacls5{n8^a) z7>DmA=m-Qk>{7RWMA1fRzzxZGwok~aD$?fs3xOgM-NPB z8tY#*&o|zCCqwb0+L4%)*~&f(-+Cl95VU>X)qTnpO3&}}TZT5CQ;m+S#q(m5-p`*h zFTL+X2D2aGRD#TSaQrKNgZS5!kc5J$^QQ-+$S?U=GAQ=8Tv57Q19+dcQ_^Z^BTRDA znoYxZs}H^V;roj>`yyp9kXY6w`4%x~C)IMclC{TH*n%JW%s2F-)@ zaXSq(tBmN;)~}X92K?kZ{A#xKVU9VRkqV0+?si`~x3;pw{SRu&SxSa^=Jgz*-#WdKFvzz+sInIh}dv(V>TNbtwSb3H5f>1cmuF&tceB2zY%}dEZRFJPZ6GT zA-+2`du?tgs@0^nl~7-myjSq#liu~Pk&Oxjfsukbu9jX0opP0=jW>_JROc_;YNT~q znkuD&6r)eS4-+4vKdd%({_0G=Pgco7f(0AzQhqiVW_}B6!D|HirW!8#xOwHJMcPy# za9)%i;b3RL`%*}m@!XLvhwg=C=Y4pL5X)j2LNDl3Y(DAvgR~v&S4)s!@*`cjH_NqL zoD72;x-uzTs6&lc-3_MoNH ze%jdf=oitq@|7Z-Q8zWt5BiZ~3wr8uT-+n}D%715C?SWzYfOm8dm=~?SiI25rpe!! z)jhQk6YQ$OAi4i+>=1MqcDe#7c4GiD)|}`LRoFXLHJuvqJh}3`(zi30=sxpo#VXpZ zG9Y_!XppWu?VCT z57%#-m;JGo<~Zvtfce-&T!bQk?kT2)$tDhsl_RNL5{HjnIZir2i67`ID;=1I^J=@U znJKjAGui&dWCMb`ai=WUU#NY08SFpg6u5v=;r)WX4+@ScapaO0)u(I}o*Y9f9Oh41k3%SO{4a2(FW|EF*_)44=Aa0@<93uQvtx{(@_Hv?HL#(yGb&50T zj@4-wT(qEDTg#wI`o*JIOHfz^GL%dqT4Mu#knUl!pF4iU*Q-JL@Sy|psClf4_)B$R z?OlU;gJOmK_cfw(^@^^@#W;@(YhlX@0MSo5f3p3jgU}as9b?TQ*7)r7Z1XAqh+asV zB?1A4`>;c@6Tdj-6sfj9M+Wv($0>GSH7QfA?^ATMRSSNC*E&l6sC>W|6C=46_8fib z+T^mh+_RLPC*IQqmb~K`1AEP#8_kvBp~E7jK7+-oD{Z|q13SZDapD_tWc~JoaWXT= zt&zCl0{3!#0C{|5Cq*Kas!^b}RtyK^jhK8zDx98Cb_*VSVjXE3if=E+WOm*kiEz{t#R>un>zs zrfQEVae*W#DxFfGH{wYjmXzB$?a>W#&7X#;LeD1;Y9Cr%eE3=V;eg<=#K1?X*5z|O2pAzru}PGO&kms(KqN6_ z6Y!V(GD3Z7W^QUKu5-c33+0xXu;K@NpG@kGiVpPkDpMHvS}A~V#R3m-Bq@lQFW(F= zjz76M{=UXHr%3dyjqXk_LTM7?RSZbcgjoQ}81Nm*KZ~~3Iw{1#A$Lpav4Ny7DEJ|+ zICHu^{o#vlD$C4f;G>pr{7K$SY_5UahtlECcxE7b2Mm8>5q(AOR(M4yoIEnPx2X{h zAA=R4g5thvCJdml@7%*Lb@L^JVN)e)@o7`nxf~=(x(|=NsYy1O^zA*q_Jsmt1!gI) z)mKxQib;U7x_MuP@~ol^BI_LTo>#V}_Igk774P)QE>!`PvGjme_j2XB z0^T4rK71a!SV(pft_C_lik&kz)Egg+?uS}nSDIet;PJvb(@8qxum@g}Rd;Oly>nl_ zl`+#aCe&6;*qwDOv}@2(L2kKscWzPCDd2v@6TdmDII1Ri=7izGodr{0>Ooeeu?8Abb`idOOoVG?WmrC-V1B?&(hOs&FoOIfcn5R+RTsFmfoc& zbl6>=z_JSHY20jMN`n7N3){rQVQdbntx({Jc+^+cloQ)WmP{cDQl=#MIURbeGo)V4 z9L1q;4CdN!OYD%=Ed2;36u%JZ+QoKZ7~foR{iJz!5nHa{*o;+G(B-1o58toC^?9i( zNdxY=S>`V+E_G`w>wdWdYv4PtrqA6H8)HtbCnH#>6vO4BowQu+^x#%M?uZPAVA@7a z%CjV*>x5r!gw;ECNa$@_h2)OtN~JCh-A)89h`hou4JeW!*41VNnS{ow+M609Z$-b3 zx*RPvH9QR%Hxu45v`TYgqyp+4$#-NvYpBbhR28>=-ZUW@SN*nZwB1LR`a9UStp&xMn%hNBJ7pzT~Q z;>X!A&T@MC_A&3NCnepdtN?0V&JDY3M$kyn_24d)05QjW-{#Vz=kzrS$P< zd4m2w1xCm5mgk0_xXE$;fADBeuz}Qxao(+=ogXS;Ew>C4Q+{z=gkEPgvprFNyyOV? z`Wue*zn6(G&PJpk`1!;Be<+Lk?=0Q_Q_|P|Ay_oWKNyAnJAdz=4?6c3S=O70)Z1c{ zTUS-im3TF>JM*3T#X*~38?FBkj$-!ijPdTX^!7{-{Qm6sefj-N{GJcL*Mi?`66^|!`ODX?>ISj zsehA~{d=x<`^Ub_p{lnZ{<*^1zcVWS+tUx_vfZBPjpAc^d_h=-0HXH}vBF>IL7Yh8 z-G^WyJDqQqM^q{nFE3Vjx7cqFe!99HJX&-tw{n8(lhKf{gV63-vpzOsYpev%h7CpZ zW|2Yc)RRku#S*kU!W^y}5K)Zl%(D@H7Sb^Kmg{=Xg#hwMH6#gQLAnzVPt3%+Ax zP{8KewcKM3ZL?jn?=U}$Z`-qt&DYA}jMyx`sCWC7t2L~ct>=0xRcvGXDI5MI_`)*x zZ6;{KegEw8VfdI!DBA|TOhJrISEUL^Gw^M_yVBI-Y-)KMyP%(8?Z|HQRoSS@ONS>Q zH_RJP|KfO=z&44IE5WeO0|j}C|3?O28aJ+YKFn?51j5fBuAv2SbPp_`|fel%8?q2*>Z_^1pMYy2^&b^aRQyc!J!B zppShp)wnJcQi5B#=Vt0Rlt|Z=7Z>(Q&%@diTLz1aH9r(?n9-X%V6^U{b)}SgAH>|F z#z{(gxHI1S*?1D^>=!ZKRZtX$65xkh$*dWh8Ok5B2B>kQsv4{n7;2f^z2E%gUGM~A znBa}Fji(eHJIC%`Nppoc?T*Yaa{4_6pVybr%1q=y>ge)Un@S}4&zi^nBF8xql*k%v z*B5p}!d)w(Q#~pYi1j7VSGG6W26SDnf^vLr#?ZI^>! z?ohTFcNgSkZbd-U+RHj~m1cs7i0<66VpYo*aq-S;4Il;aqP#?=zl5@-C3sE*G=oF$ z0z^3i4E))jtF%{P;^W-<+{&b51R??^E{W%phZ?HJb2)u0 zmx`9xJNbWcaMy1I1~@z3w~;eM%)oi&GWPFhQf=+Rl}f2fZM;#vX%JD`KStp^s65}6+u%J18!m>ZXOadNED5<<40#HSQ3}le=a<3)(+C|>2;`IeP3KW#|^0j%?8YYuMEAP zqCdTIwd$ZG$;X9b_h4I9WO@k!wYNI6geC9)fQ1$t#^a^eh<(D%3sRLhpBkosO;_?_?t_603gqb6@gqZJO+`Weg5H*2C*_udut`ums7TRPi6vtI!Yqn;+4| zHSq@W@x1p>-GPy~~>2(oMiC(7o&Au&*^rEjdBD{!)?H+qIP+Ys*S=(CnfMt#tb3_-yv#oz zJoXo6>E9@g|0lmX7PEI}TcLQ*d=(z;-+N~J`M$PZ!A~dP?Si@LZr4k_-nGtdb+INm1?Rs_} zoz{?ulrg%N(RQgPPS`zaIZOuTg*mI2{lNQb#4(cL@THq2g_ELn7u?U)dLkWW7^sPO zKJ-xPZpFyZP^jl}cunLv>0{hFIWsqQe5Kgky+UCPp8IfyQ&Tgpsc*wvyxnE23D80U zMS0OH{E(O)2KG^IU-yiRvG|P+!$Udl@nHH+S&y$>e3@J(*}gCp4^>@W8!!~>$-O}g zNWUoKv=9+&Vi~};tiZ5&w$FafvrTOiOULl>dBWLWYosa@E5;fU@6wy0*Yace;(cbi zTW*#|Oy9bcSQ|ehYgsH_%b8jV*8m^}nS(4g)BWm8Bl*yZ99eSb)yby4EwcIb%n$q7 zwc(1qJP=LuI2EW?d;Mj!V)4-eXu(JqiFNJ@=rDo3jG(gL%Vk7EcJW z#;Po}Z0sOTj=DAfaJIDVUdeKVArkl*TS@3)`^iGLvl*cctA8}BH1umjg=yP~Tet9e zcQK7uEWw{(oXvs8cO`w-+{N`AbFK{X*9xcDSpk@;`zCtDiX z(x?UdHnq=<3apmr5vDYdxjYDd$=E#m+)D{y}QGr|So==`YcCt-<^#D7&Z^psV73wT3SL~@6g60vA^+gg z%jSMplV2R;;B{ap88ofA%IJi^z(jV_9%JAPbT`0Vp@`MpEZ3*PP7z2t(O>Dh6NW36 z07>D1(y^I5uDJF*V}m|}26L*!x6_BbIBz}Z@*d_KtXSv(-E9ptHZT}oC`Y5Pab}3J zAB^-OQ!QT;%kW%ss;R$)7X-Db0)@MqTGHC9f{?7UC^nrPF3>%`jlnOb&Age8>k2|l z^tOGvdh7H|g)ixSo)C{&^qTD5ik}CTlJZF zW4_)zDnbbC$eTzXAJP^rweaADwPgDH`gTWxoirw9h{SH zP?R;$FVCIgOhaH<`^)cpL#4yjAufH7_1sRl4DBh5YbCgwCL0xdeDFlT-nn}}(Pkc> zxXD-+{cgf_{L}vUUA}}*0Tq={VS7aF#hRRAff_Ss+$L$C$H36)i&f!9>if656;0(E z4GV4on!If5+x?hv-lGuwO6Csjr$&J1%` zlLRf$Fu`x%OA+R!IJh%H6A(vhR>DG(OXs?v+RN;RK{v5HP8&CowU?q7ug8%0r0p6j zSnEp4KJK+F6}scds?0AJO)ydbmk!U*>HFg>y5Pwbd69xGN z5de-sq0ZOO(?s+WXuNwo!1E~+TtC>vvCmFg{{lu7;Qz-V8YTaGIL0bxH6nL4sf~JO z)#!y%*rid5W-o|X;n(4RT-zephf%6+diHLWsOsUDw^P|jhoL$TW=JmZY=f=N;M=$V zY>bG>(>FzEqz~|34fsWt%DE@3ffuact{vXhw~FHb_V$q$rY-NzjMAiD+tZJ5Pj+v0 z?Ww)!?H>ZXbbGy-9DMRG4&j4i`>11k>sf2!6F2Yc)&9w@;QFv`?|E=VGs?x+dqCgd z2?u_E`|msR`Fwm!2Lu9QQX|#J`pg|K}h&e;p{_sNBBO$nK?a z^B2cnoHW}^`qu67m9}UvN#7P1to=_-9Af6M53eJ~X6OIj>-29+X1`zkSLP6x+4{t! zS9&zi%+0>+Tl!+rb2mlle^YKg|AbwFKJ||-LH`|I-2XWf;6Hzg{YQS`uPgN3Z{Pik zc`)Pur!4ivtzR zwm)I70v|p8@&U(gdouj557#Z;U;d<9H7UNbMcc(8_Zr~LsHDh2D%Yg&zi$Jk2qU2vLg2DRB#kv3DC_BUkN1p-V2sk?=KGP zW4|~QD_P?O^Kk0kq2J^E^!xt)eja|$x8Li-@Adche(`%h=J*{y{A+~wJ3jjzPySV8 z|2tm)onQRU-+t$tzw`Ou_``2}=bsFZVvFEM(a!f%I@m_5hqUa^!@t-J{o;`PUjdGR z*LEoH{yn|DdiehW^5hr9Zo)^)H4ekSykNs?#s3Dc?Y5_|g+qTYc*q6`w^-;IHWEi; zjr}VUw;*OTP6<5!?xtAGO4bX>lwX2?v@%#u$xIA$}4$7nwa@Ft|{a{aqnYww#Fkb$; zCUjscziG&<=nk_)eir9x8?jdJ9C%w-GNKD~rjdJ`Zq-t+n!254`obaZ&Wn4*nOfzh zuLW1*;;a$I3fiAefV4dRR6cQjNKO1qSy4|NY&x@f`6Fe2Ir=V>VAp7~yn@A|Os(Ql z1FK(z4{6$NMMwvSRt0S3qU()hXf;EvF9#Gbm5ZV}jr;1%2dXlg6xEGi9928-c~xjJ z-PK7df-8>>V~;8u2FCY~c5S9;Sxiq{^Y8D6+dp`u*Ur9qiEP_A<0Cf*4R! z9fI)#Ft6|3grD56dR%NS+&UiG%S{RLoW3#2|B%$DSXh@jH+j1JmSAdkB&YiFh1i~; zS4yrj4PUHh)EHCu5HHO3VRU!*?j_P zK6?{BIVbxJF-3~TOXp+@>k6t?16x4H;9pv{UyR}p!rA`CY{1@YK43SH+=$d#WIcYS zzBtlQl{4|Ax1?fMrKudzRL-`DT@l1>liEc?n%mAZno+CZh~f_m_?n{bsl1euJ?WuJ zZ6MUQ!g)JjUew4e?k=K@LDJJe{4oMJg}WM+)&sVdF&q&%H`CV|de;giwwWPieHM>FSk70E%$@?c z7lXyg1e*PPKwtpDJ~;oZiu!4jzVC<2PrZ8c`uy{wJgONU`pW4WQ|S^*h(P4$_Y8JB zj5j&pPMDnLx~!@jVoO&ipfRMlGP7iHh~c*V5;9g9v%CE25djlNJ3{_xu9o6k=Aha- zMEdF_c<=J4;G>ZyK=UO7_Ywa2-r=>v?6i`(VR;N8gF&H4xz@u#CxPc~XvP3MK8D_* z##HTX6qUgHAtye=;-xYY9+_!P*-g!4v3=7>YEaMu&Nc%|dBE8VDEw74tg@8X|LNU2ukJPyJEtYuT_*Oj_RZS@j z$P?VpXbeSlkCUAurdte=f2>g2*(O{m;Vyv>%F69d9BNY{i~_%&8^$%<4Qs+*73y}k zY`mmz2*k+^pu_|w%nxrP z$7Wu^8WqO(uPJ8-eYg(TqoPSkqICtfbZ?oSzZ_A(Z9jrKa$?A>5I0^h70Umyz zhuRH2D|4fygD#1HSQCfeW8gFIXQv?g{~S*B|B1YaLnI77(sqk>l`w%na^%d^= z!4G$uKlx&eC}PZADza)SAD61SF5nxl`+dQb0J~-fcBUr0&)lUd%4cV;naKmxN;`}- z00xzv6z49l;6kzm23=+(KH7V7JM^m^>ivT5Mf`{U3dMX321CSD;u_1DFSMrZzvL&^ zeRkXVc>f^8JVyFxZS$^VCe90}Kv`T&gOTo+cAJL36$SKk1ZUw|dB1c0JS z`vR@k?gzaE8btVQu#1(3Y6K^)NAkY-D^q#uH6K%AV}1NxkGDE5ouC=!O!Q!e z?jXz|>W}g!vaS1zr1NJyNwgHqzEam^T)pEk#zQ=ESEsG^J$TnH-mURN-ZblrgVi6c z>>hs-4F=F-IbqA!zu)3_;yU}BZ!^|EyfAniDIc4 zK2yHfJ)#sdj&UsN8(D`7Y)9yE1tnSic-XJ|Gqb#)=UTAYiF>V*Nea~l3bjOU(tL}w zP+76AA1&KatJrOTIG;DSc{@GWa@}}%c3@y}??*2Wm@3|{sL1xzoT4IODK9wZcH!jW z`sDhOJMkUD8&Wau=M_05pRrpqc%ZNZ09$<>MOdPPA+5% z1*+NM4*-Wb^L!|_fa(rEjsUzapIDc?j(_u7@`7e0mvqld@6$I1aId}EL zXYgZfOzp4N5IMKpsWtdPJ@!T1jhJs z13^h7~|sz9?&YzhleyF-4L@-8J|KXZ3PPIBh77^KL}G8ebZ=Kv{3)t^O|FqTciWI zGcwokNs|1X=u3wU_!9CWT!beSkC#<5tasRf>=McsKv0j1Fl~;16}ri%C$3&-x8Jzo zoUkEHY!(dawIM3_#{oo67mw(}ESCI%S^=j{oOE+DmSVSpd|I0F^k$Is<($dV20+)U zon7eV!H%U3$61+XSO0xrXdrfptQ0&~(znvvmaXarRX!Z9X*`~J!i#R{;K;|Tlp>U@ zJ$5hZ@`Z`RVw;MEE@FYWg8D%cnqW4EgQzgIEbX%7);0p|Y(v$Ewg5YSiu0`%d>il4 z6#tXL_Xq2MSjPTL4!KSfr4i% zI^ryolsDD~Kv0HhlZs=*8B&<^YAc=6ozBlM_E_ogLu3C?!SRpaevHHk$9ri4oa8X< zRHl_TMpMp>*6qETbh^k+orqg?-)<#V|v??9tz()ICF$;>gq zvS~A9Z6eCFmWE<2=hfHtQDmLZ-pkCU?mAL*fPD%|3k6M~D=p5fp@EJ4i$e58VHwIM zP08SmYl?a~H~06rH!HkL6Yf3AMN!;$+`Gk~n_wW2Tb9E7&erpmT#}RG@%w0i6+ATpYv2z?=txs2DG=D|GZ* z`=v)%X}W@X7VdkJhno!Gyv&1Igp1{MGmDT=yzZmI=FKv8hhe(BmRgP<1X#NzNntwf zZa6{$AK{Rkd;WhurFg6=eEyTa+Y6mHZJ;z2V|gU`TOa?NTxopb?bF@Xj|%&3=|!{D z7{HFxB3d5SfcjooAfUEk!YY-=iBA)jDb2k#IQfcM$LMI)V?@>K9~q39JX<=cVFpI#R{&@x8AazgX|RIps>`Mh5(b^ znp&xDMT6$NJjP(C+OGVjQ(xCCLacaP;g(AGWxmw8l*!BBg6B8-_-eE|F3Cx}Je>KE zV-u~Z&Tf1Zq1X`!l|o5j%Grx4D6_KKwCOaybWeNLIjMNwvErR8L@fK!>ZOs20?)Z? z8MmdAZEw#!FAjJ(a#fJ+Z_pM&kQ<_4v4MS;Hz@KdOB-O6j)k$WT9yG^!D|RYRRD&* zNBf!^Z$nTEA?A$S$XDV_C8qI(`b_HOy6!Q|iQ~#kVIOpC%*HUXBk^1EZTFkKlX^TC zrq;=JP^flikGX62FOJk!Vg_=vQ{~s?ZBEOB=kW)rwhHiC*W`hN^X@ciO%*?zvIZyMl07^uCGw+$p?%oQ?HDVow*Pi7=P z-2Nzg@7AS&ZK9OZ4U>FFNyHKnDP5emywv~EpesdZYH@jRWQ$3MYVF9Ycarz6uc{RV zVG*X7$EHp3b^Tsf7Q@=>U%DpV*y@fEdZuM#>~qvawll$1(G0SmB}HL2%+>}hK#Ke; z%2p7bicDIcLoI6f@fNmc$Ye5lEHLH~<_C;kNOVvYIo2r}F5-?C?4#~8~P44#X)>;68!XZbyUJpXx( zbFOpF`}6+1&*z-$I-kP{oVi>QQ1xMK5bEOMQly;U-lFn1Op`e}?XFZQoS#|=^Px9y zOe?b-uQf65l2>Q`ID`V>;ABI!z1lW7123Lx)+82!ie9}EEPvOC?d{~vpggvx*~(7~ z(neykG0JI&I<1aSqE-&9iYbRXbqoT-LbR&s9+ zcy`&e=24F}Q0C(yhAY#hc{7=1%BNZ`oJaQX=W}u-2rDoLHwP2(en0VXT9LV@{)4qZ z9`|PI#?n$>m?=MFZVGJZ$>2sYbf}`jJx{uI2Cp^g7<2DwVfT1Ahu;si+y@Qc-^Yos zc9S(Xr@b^?Jo^*<ltug?V~{h|EhEr*>*^-<}IciiHLC~xxV?*2g^~H-`pU-B92U%OWf8U z97MZ(&n<8siTJdkgm!|p&6li?sp`2D72DqaZhB7IPI9D);vJ0hnbMm86{XIY=@FL? zL*ZNk=dNwZR-`qIzIe%qw6?jQ4#pGGx3^HnP&I5zfh+5P0%E=3RmwV{=_@tz`tL~X6 zQ9E4Kk717Yn$Qljdo)8c6kTtB_pgO|p&8Z9>GjRHvP!P*8O4RZ92KQtqxAR4y6KfH zF&HL$+Ie7fN5pN~l0BJH1+TDz*`o^!VPAn4(~Cu5uXe*rmeY4+sv_Oghup%q zA|SD)dal!cqIpVb##@@sCicPJiVns#je5INJagrV`P-IbbMBNO;D(7Hm8cdkR|_B6-NKf8U!u6=+C;28l(OSXRZXxqG+#|qzswSP())M0MhV|c8|;cRsoGQ;Q&>`KuY0jdSd zSxdA5=cNSI&S*w%2Juo&@{*)LlU=6j{IrtNB3&DF9l!a-grXwnku;ku@TTWQiwZ;K zEpsb(@L*}!t39S2j)e*q)PN0mO`*8p-=$JgEl~7B^{&RqTE6`SY#Di>932GS)vfu`CRW6)fV+hj zqa@j4Ty8T`qGl#(KO3T`U!wrKYoew+SF&!f&@R?fL+(1M)>X>l^{`uDT}n+^4mxu#pzH?Ex3BzfXT@8uU7LIreYFicJ2e7h_0U(|GOQ?y)T^?_%I|2W zj!S%{jE`_vX{CD3YmD=tq5b?iJ@m15}Erkgod zNiBKz%CC$m%V=6PA)8~WW>70;6A=HJ#_jw7TbyCexkS}-L;R|3tAid7Xhe!QSDLXO ziDChvYx=ie+@n=3p}*m7pNVwrjhb#^VOvwS@C?`G(t@nq)w+Je= zxST;VeWmqD0WG5?TF}`9J;@p7tf-WfRcd|HN=05UR`2OFi_RoQ!BA052DP+>m0$R7 zbsaiL{eWR~5>4`LTTZQ*vz6FrYIt(#>k}Sa*oOY+vBoCeLcj8oA;;eGlvbJ@2|+(8 zQ8X<^iu|^UF>F2$U7yPL+$(rK~>>^5Xm-DLqvzow*eDm^p6MLTI z;$k9SZ`!7y?3LMG%1ZZmO2H=Ly(GUl#=r7wzP4Q*EC#U zRwg`R67K&IpK78wo+r7zY<-vgc?>kq+QcPLmoE@FmBJJAY!Q(p^3aUA2YWW}?Auob zPU2}JV459)ZNZ>z34Rgx5g4y3Mevi21UH1CM?_*3u5_uuBegfatrX8cA!GO@i5VLj z;AAe75AH`hI9B*g=f|@kqMvne!uY>6az)$@))l$fMtb%KS9Yn+Z53sk2Q8IVi8|)A z&g-e8v7>z$k%x=(EL*8nd9;cn$Pazl2H+AxqQLVyHp9O}%Ju?`$tl;}GwWm+jbwCM zUF(PM&nIBH+9-bN4CqrFND) zxRjKE?pXAQfiAL|#cSI8MDDF$N4idfxiUO8^6}i?;@DnS347yA*gKa~s){RaMbcz` ziJE-R$n5)tktFZ_htz}z-F7YtOJd+h@jr76I6p$^OsQ(c zL5ANUbNa!&`DKo;J%$cut@^3|^)NmMH-rC-VyF=`T$JPvaoh*ad&(fYC-y$8NJ?B1 zy^dUE|cr20%}hiMi0l;B8;5NL5(U9vk5xU(8X&i)?a|8_P)=kC{d2%xtkuh5YaWHUcjq4vmJ)E z9)}V%Ce)~Y5U9$WuzIhq-9%l0#?2Jnya<~rp>lin)qg-b_uaW-NZdIhzjLd)G|!f! zpkI_aUuL%&D)RKa)~i904~527mv&SX;|inqxEb!W#8B|(z&&DkMh2VaoqxFI;Hp1j zlM+0|Ce(-)-NXFyOXxdFPouE+5L%TQuE;mv1Id+fQ&j!cZC=|I=jErer)y7drE1hj!wapLL)KsxVKtwC}tRjjFS9OL4n_L`m z*A>Yl@6|IreWQd;SM9Yp`~DTfNk7KL=UpW)B7(GByi5kSVYbylHa8-l=^E4FOsbVO zp0Jhd14Jk*%7KOnm#>HbRucS1=D?h+6yEz|Lxz=PUUJNt7zRS-bjWv`03mC|OK-^Q z?4>Tuwng7-UH!Z5Q;%=Z%$%zl+H1$G0joBij#zoE5_zYp+FE^dAuiUxZ+7X7Ew$Ky z^#sgMFG7wK%AzfQ)+fIF^2)k7qr(lW9#v6=&j@l)Gw`kb+63hbg3E5=?)%;6Swjnu zM{8Ax5;skf0Tj%-O(-#g)xVnerdL#a>2fM+DadF4B9dn|Zaa6?+8Ny_Nlz_@GgW<842d7iaH)_CA)`JWNz?-&o{#wSsEpyRDy1Hc{^B7ZQ?qKlR zc`v?tB!sbMY-M$VT&h7=@@9!{2kee>yg)qDHPtrj_JrWZbLyf>Fh{AxiD9B zdRI5gBVQ|Kl$3y5A)YU8axiqKM^1+bn%9)gXsY6hteW&Q9J2Z#e><0#rh1Ljv; zTR2OPc{)Ns4w-6wU-EFLTmfFv}Tv3z{6NHJ|w;pPHi34Up!>GfLrd}D6Z)1 zo9_6wf(Qlg7N+Um$dh)}lLwE@l>(t2@tf75wtOcUqS3RjUJXHR>;v={ivXfFUOV-< z#9a^53N`J@#R^^8o-IsX-sbYINh_{mpmHd3!ntrasN!yVWZIx=;g#%#n0cXcLu~~5 z!q9Z;lOIK=E(LA91ap6qsYhxCW3uhMZbq3k$9I3|Y6ipGx)!=Lx)Lizfo9cJ<$R>a zNa~=9QD-^6I@icl!M=v2(w- z#8#TqR9*#lsrnURIW7YuG}GJ|)6wdog)zR+YEj!KHC%la2{9RyDlY0+PH&!)a%(>A z=a+(d*R#xD4m8jx)4(pq-ta8U&YyYQP|g|miJOGmqg)istwrrJID($zG0+I+Pjxnx z+H>D>EGiOoRc?q)qU|kJv0L{bH`A?_*K)~Gbeg^W-F{W!ny~yLhyA(bkr(pvstTk# z+=_gH0wdL|txg8kj`c&C*<#uKvtzwBl`<}hc?{lMql3`cIO72S66FVPjTJ0JVD_s} zyWx6{Byq->zjHDFOq z(UiDGCiO;oIN16`M)*kc-Wr%MEXvJ#OA3?m4mxl(Exn+(2K8b{MXGG1m2x61q)I3Q zDyio0)RM>bwb`ZI)p0TKk>QqpRLm#!ACc34-MY4QA?twxxenuGbag!s69U|S2>h(^mwdK!n$*r*3x73WBEC!~A*b&APNR8QoFiDWBt>88#=x4`B9DYvejCOqFG|bio96EK zl&ct4L-N8Ef)O^rr zAQLv@IaH*`UmK@o3$>~0R&m?O=WWInmBw{w7!?L<^-0NAq$6Uh;wwvcM7}Q;1WJ~y z4qWsSykAmOR8>@2T3Dv&nPXeb_i9qJOE`*4@9A(|pu{jwop{^Li&c@f7nVTEgN<}-Pqp2`H%EDiMaKWMW za%7UfSCp6U`_6n*DJZ!D*I@tET7I|6rGz!w92)^4Uw z1uCW~kydT3P-D->JsTHyT6WF8Zp&t_saV@FS@laMjt!(eH{#%oFlHp(oit||pkx!Y zdR046dR0nMv|G_w^h2dSfzNSo@p5WZ|FzzU-nhP2W0X$i;8-HwOYj@UBFic+H0J}< zeHIrw>2NxaI@;NSvf6|@^xn|3h0yYozHjbjoVCkP(F`imMMjrw&3BGCjc_GQ^G3_0 zxL1y~?U`oxI(C-qQs2X4CU&WmzZI4tUn|9kUk@TF$ z%4#3&Cehux7Szn#93fAtva^I4Ge} zn_I+8WBwDk)zsR|tAgy0-WG3&zPS(BjKG|7x?y~kquXUeYcm=Z-X;rP%Sg$V_RyNE zH639ATwO~koxLY780e2KIKR0AShtYA;7bdPqKtJ&k)qIlS7W70ACZta73Z?tt-C(J zrw}u8ZG$w8;Zwuir!^ZEGeecOaho>nDinJ4Nsv$2sR&b;yY`(2IxjAId|J*ozy5_S zPM@KjGeXHYRjYhB`huSk&*!&Y>XA|ImDQzPJk~IS(Y$JBzW5Q1x#-w2IG*lDYh*pR z!A)ku3iD7aRLCH|E-pVdeXiCmVYwb7^r}q=8Eg?(UZ-l*US+yROn(Y5Ez_@P@V9iM7M6F4p|(!pI+2qO~PLPQGXMeC7PTNI>B})!8VT z#O=!6)^fuZeWg|drERIyPVip$ysqi)jEacL4Gkq_3+qr*c`V0VTwPxlEcJ&X)IRc- zXf!0DZ}kp4`?q^<6iZHA|118Bx{F0zYIVaIt3=f4ICsORk?8aa<1=~MF(KYr8Jp?- z?aESydf!ZBdaCZGrTcH&B$}nvif9fEK1h9U{nGC3*Gn!>`PPJ~>fRPpSC%SVnabdH zF2H9Be!0!#EoL*#^&#PLZX$|=8(-dp`r2~a7&1Y=8y%7#FB_6R`r}I)cu{5f&TX4l zBk`Z7Q=%`rMy=c;22M~KbS?^bBVTWQu`j5$?Jo^PR<_J?gV|Z{-rYNg8C|^Hhr~h* z`U$2ft_|RY?N_S0sl+ErKfzvSPH8`V$my2mhKP}VCq{81dhk<_x^|ib|MV)dBE<=& zpJOb8$!ieFAnl&3@v^nH$?F<2RJLlRq$WJZiUrjTF3`n1w-FgzDr%LP?#_ikLuUhR zxWilA!YQl1oq7z+zeu2!$ja*uuCQf=S=-L^ce;&6#VI<^fcF!pfV+w0Rn0CCTIoA3 zZXRA&k`k^|RQ47aU9*2E`yP1lP!?X1nVj*=J%(AES4evop{m0c5epfE*J4Oz73eBF zAcTxm?>&@X2!g`X7OUVdkXqBd-YSM}Jr!Lsd@VL+IS_WXmVy5y_8m<&pNPF}@W-~! zuF?pt>g{GtFNElPUdeo~@xX$4V{Yt|{?XwQk393P{-Wx^zYOT>5mb1$JVTZ4r4K?w ztuPM5;jzK$Z)(r_0qHkJ93c@>=pQX_zKQPf(u$@jGQK&}--$FT`xdIT4VXkM+5#<62r*4V-Uye#@WqUkNynv@*^+0uJ`{U3Z~--_E&qI^iIN80G}x%BAfrT=n$-n2zq{=q zHru7zH|;X=sgmcz7B{P{zW_gcD4WM~>~dwLaZ1X}+G|K4(@0EuMXIwir8q+6(~o(s zuD+{Omuh|eiDzcH3k^n6w+e6x@nA;dp2#ha<*~~Wj>t_nZxhVqasmH3<$1#09w%_) zdw%o+lTNgMfVq9Y#w}}^sV@we@l)ScU-i%a{p#zoIR7UfD;B9XVVh;%5lCfC><*tw zOxe9orDo?HRSb5^X$&sY7I_yxIY~~jX;_I2rDo0SP~oi)gI%F8+-vHtv%XChuKR$Do@A6p;e&U99>9b6arfl{*sgZL6zK zfBg8He93R+`hza*4-v*PL+dF1i0ZN~9s^MWYcKiK9`MVoIxw3oYzq~nrn}*l8zx&G zBe86e#P=ZYLwE~+)s^PI&WvjpKK(p*Lve$vB&ev^<-#c;7BN3*y-Ykry{4z6(K;;& zqgvg~ViW!DFTLy1R2NDEzEjEbI{3&nas+7^t+%?OIdY~*MO38u93H@M(miYVDz3zKo-Fro1X)ltdxp3<}}0?7+Bk2PgQ>MSBU0{ zVeqXaI$3b4(D7kiO*@-3^Q2M~RQ{!lc4F@~##~_DM1}v_)R<;M8Z;H%N?NPZ6*R4B zoYvwv_Ov&*t>GK0R4s&{y?xC9;lIw+B{J!Z8n`iRh16ZU<3JfM!ZuGIA$|SrSHF8q z?0&aY0yt+kT+1a?%8m8MTrl#`a!-|dbxoDBA=J(8LaW>qS_bITxU%MEjiRuxk-^h+ z5e8Cx`V50(_12P`7`*cPJS`ivyv%uek>>ZF7DpItsGv2h1bgrJh9CBAt8>(OOAYn-3tOGNG8BGs31%iCu(9w>DgT{}D8wnTekK*)!ZKf<-X$Y@Q6 zb%7Uhg-01vg=nsS<{2JE*X21TlDEZ@YD&NHpz2x@8!KanYJQx4Cv_b;OFQnx55{wE zfwh|U7mO*RkJdz4DzU**gW1_7F21nTL|GHVjqV7xb0J$g7&oJgost;b%rt6Xc4h`y zAic*o^lq>(q|C+};##z+Th)VES2;U#Zp8FKFGghRQNk@}C-D#dGbBS-?dTfyY#Q`w zB3x!qnw`BKOe>bFtu3o$^TFLvN9tzxUvXBO1<)%NEKF1Vg!55!+a8@!QI%uLOicfM zd`WfE7bF!cGm%_ldgcuEO;=iIT}GN!1~;R!|JV2;_{`XoDPnJ7b>EMVNYxFRM~Pxc zUX@ID3&c4+?))b3u>8C0Lt@*qTM?v#hQUAmZlc+8ZpB{fo- z<2j0*oSl&WG$_$Yo)LV?IGQ;d#ui0@XU>e@dU=yr|>W2xvdH1p-q7Z|2aPeEW zyw8}nmwnCPR{T;>+!niwYK8Ce4^5*?7QcbFpa{MuXpO7U;^i^-y3n~*cU@zVt3zs; z*WJ$7Yo}Gk3R++Eo)MbiysVjGL!hE?x|&@S96xA}P??$K%I}7nq;!gu=v7wQM2&!P zb*>p@lo>-_ZhQ${9{76Bn!mjc3)gx5wP_qXo_KO$J}vQrw0bA_HrSH?`I~YdN~tCM zr8t=xHsMD@D2Dp}QXL&j%;|nbNzW?eVg{!y{l(Rs(bcN%-9cp!2m7(5wKWIB{v_BTA76THs0Zomi!{m3Z%Dn3hk4wqQUK`D%+jE@M{w! zFRl^DCpc#GKgTroE9Wed&yv#cKJCOXHM#1vwKz>Zc^ILhlfqP5T|ByM%rd09yo@$M z&-Iq+hE>pHOKMj~3^q9zsp#wLOX>4#)hw^}tQhos2Qzq4N`UX72zL7b6@m~3UIEiD z*e4yb8}=5pf&kxX1?uhHhvP)N%o=6F-on3nL*}UWf$)7`hY8GR#oF*4G7e#XGS9Zf z1|IK80W)GPd46`?=~pD)8-@HXBD)V{s_iN4gXzA(^}H86n{*nvp4-4M11tCVIlY%7Q)_=MJf_NiS3TnBJ~ zsrZk2&c1_gR79*GHb4~AW`9?G z4So^`CU(F5=i?53+XR1-`lqkdd(=x#U8p~r3?OiiZJe3i13y8;iR>MrcL0svAvDk( zI6F@E(LWD2J3tgntaUi-dg0yZqcMVsrj8M0aZG|Qq7KFc<_0^&!h#LU^9wQ1J;9&E zT{k(wt9moSG>-c3w^UWTM?I#(2f>Yj4Ww;^vExh*8pVk3HM4E*1IKo(`s}*N4*!-D z+2IBb_7H7z5bdPRy{3Jj@%K;M1nzQire8xiw635Kd|ZaH0r#(;Amg&k;KTlaHufzD z?E%5mK}iHr%Ng3D{ILaMG`aWu$SlW$Z)83u*x@gto{)(!^oU8f@(!tQ`^e6inD;QB z*nP_7?XE+133s6iA@j5Q0C*G8;;)~s?|~AQQ9y72uU-3P{{S5Kt~7XAIbzrSh{zxJ zf%(N>l{yblk$toqxDTkA;=w1G{NkTb)vXI1C9hlcWZ~h+%?AUO0`vvqi%C(xjJalt zS6k~=JVFOzd*B{glS^ijs+7Af2iym9qAYpVBiIfJwWk0!7TO8sQ~R-Xz#i;AkgV{_ zM-Iz@9R_`*fS?2i{d0%u(CQ$vpc#){>9E)VYj;3TN^JO(21NZzN8JFE!GVqoLJc}N zdy*G8&OIiERlxWn#)-pv9pIwJ8g$0qY5+y594NT)r- zG3&w(tARjN{K2}ziXcz+;#A@2$$w}~`4epBw0 zCwL$hn<(5L`XML;8JB7L{D*T5xE(+^*9JN2tJ;AQRUJTxKM=NpLt#6#s>x&UUJj4$ zy(^|$LSPf!2Ou7JL?@Vx^{5yK#(*0LMk-k%2*{xpfLZczCJ&`O7Sq5idA6YV9Kae2 z>Y>Lzp#DoX4=j0D4RrwFp@aM?M9FHg_s9s|4+m8YM5hImOzGdccJvE)AK;M;9J1t~ zN8Rn9?SIJ!2;iab&8Gh;0)p3NrR#;$;8XuR`Of4h>cA3zw2oRyV%t8s5Bx5qc4VA2 z5aL6DDO#fk6=B=&j|YJUge=f*fqDLZ{2Esv2=9#K{4cs3s8Z2^7{eE6|6szQu>9*W z8k1k$_Q3s)fAuFZZ2Q!o{eg^2H5l_Dw!srPM~#8l!#B?Us~Y^P3n=3(Hj{y)$1!H&uu%wpWhVA)@8^s6B1SfCCWa6lCdH?i`+8bz%n22bt? z{>g#I@UO1o;PXt6CHs;G1oTR&d5~qOUo1mc`7IGZ`+Wf!_0Lbf0|(Ofge;No_-VH6 zIPZtjE{kc;kH>&~;{iD!J7(|wG0tuz#UReA;G{=;tp10kSf$ztUq9^w;GJ$D7l#^U z5Fi&F;dB2k^R~T_zNMRS;&i~~&htFnPNtn!! zJtpeG2tn&0w*8Jsc--7U$7>*q;L$iUh2whLP;l}CKg9VBvO^nqMtk>wV4$8KqUE{> zPLl;k)8w%&9L9e0=3vYqZ=52Zr~TQa#$;ni~Q)G#M06a}J2{*n@xnq0i1696Jka4hu z%-5HKIx9{FQhP8B+0-Uv9 zPJu2(m5*3IG!Zxeux}2(sZ?{TnFm`hlqkr!5r1IAg8~5!;-IP>JjRsZ90r?WJ{aIL z*8>NghWrAaLIX5CGsw1rHAKOllmgh6hC->7|81m0-*W)f35+Ohk7*B%;SY5>_UzdN_*2Sbb*ch2!3W!S zpiZX8>hw=R6z;dZmIw#xwD^ZQ9r`WEmLqlgWyV92IsO)>U-UeP4`wq6%8-9KL?Y!s z8hlKDFpB?Eb%-Vr#@Bw6=nxyoZ&5x{4$uJVe`=f$whcZ*-*6Ni9J!kB|15-%jdRB! zA3ez)bhJP{we4fp4s0DvIeqTXKb@NfKg;4+UsKa>{r@%3sve5(v3nkc8QyUw za5U<`XO5zS#I>-c!hHb#dzxdFYGlLmPOYYg}wf_9^0O`#Pf)Z*KRP>`r0t^a3`8^u-aoEDTtttb~0>|;sGwfJ?49PC? zI3zxZ8&Lm>8^Dm@KjNX!t{5;@ocy(RI*i5+00x7$QLv%S-t=7 z=DTXd+kghI-_<~s-9>=Q;Y7stsXt~YFpiQum=urVsDl{_jHCV;i1n19#f%_<+jQd` zVfG)w9>y6gj(_^huW09JSqO^RKioNzCdK|$w*M&#K)u;L2tS=6bH_?_ut4}l9~Q@B zavn3|Pof`0vWMg}#YfwL0{NRRpgA$!%I*I)OpV=c3;XObDPp@+?E-eL)td6#zH)ZUPYXH8B}Pv+4nm zVznkk)9o#Uuv(bCVtaTGthH{4un!P7$1Xe#7l3H-gS?tu~WEr$tFg%H)bzJ{1xoac=8ErLs!*cdA;#%n?$4g9Gpwt z30i8!Ds!zV{skfl4@U^^8t{={y|1p=q&nI%xWaTgHl96i4K1|bPyM1MzdEJ%vXRBu|Ly0C!}qt)B*dM-eObsua#3fxZ8ztx*#A@BfW4nx(QoIMMRvuT_s7_MAyxV<7!K8Ya% z|3-9nOx{Q@AmhK8n8YoIm--*TOnjMh}0^@%51q+tX4|7 zi#D1@eIF1nU@tCQIZg7qB!O*faUb}Q6iGa9@P;`PU1=3T^W>)maZjfQ zlU9l*Qmpv3XZG?4)dC@8gs+xqxrDZ4L?&HVoaC7i;_q-%wUwrKkF8MDhbG6dlzo+s)O}4%#Fgh~kE&UMw*#0?UsJ_}N~hKVRVp zlTFLFQq>&%dgGbcn;Q?3PK2t>8q-`~E~}Qs?Otd#J)b$>zpUI^yc{2fzd{m-4n8N= zU`iGczx#m6>C2j=*Qnb9L=qFK&&aivmcF+DE(O{Y-YOc7gjRZhQX0BE4Wb&G1Jw?cC51W>!GF)des=;|Z2%1nH;|I+>Nq&Q2x#1(XvsVLtfQkI6YpA`(WHOroD; zWa~1#`q$tR((sLWQlXIYMUc0y!*+x@A`1D_ZXz8NCyDB=UuZuiERZK8oIYS0P&yd#QhSpS;?me;#@u_h&T$9Pl3WkD#h$A z0{8}p_5csTtESb7e>s}mX(6PHB@u<%#ZX8haH;WgJC_eLDRIyT`Lza67O`@^-Gm7r zdcY-_IA3z-EFfu-B$Ek{gwM+Xz$PO`j#PND!5xs0J`0#ANF<*`Z>%SiP`A4ScY0PG z{2QLE(d_l0rjG@dBCNnNxO!%Wa9AW3DnPn@_m%Ru0|Ypl_X=U z4iEq^awJAhI2ypQUD`t(pycTCp$2|VS(N7x`O4S}jm^uEa9Yy<_NN`>NEo&^X^1XC zOdl<35-U!vIv`AVd@`0J>xF{1JBZfT7gX43EJzq9gMb^t4U=(l3=JRm90A`@k~Bap zA$aztInZGDMFcp1h9!iZVziW^to8mcAO?t*g-3nP zTl9ynU%EcE!u#^SIfI@A$)LZ z@g3V|y24A|%$C%i#Q2O%aIQF0l0!-7szOCtnn!6+(R1@<&*_wD)ryc8Molb<5w$bP zF)-I#u9N4kg>ap#`A`;6pS&u=cjr35Iw>>9;451Nx@qL++O$3gHUt-Z9hK2Ri9!oY?LJaLc&6PZZr`5*kWwpds45Lb#3h*auEFuekV% z2(5r0Wc@6y&#nGyzd~zRzL(bzU$y`&uAdqY?_Aa~X)tORMiH*a<_UJkVr0;ydzy7KVe^}Os z&cnS!FSC>Bn4hhy<)V$cKA5H*IZodGU2rYv{kiTRaln1MI6%0ct-u}Fy@l_c6dVv! z#W!KCYA4uUa+=>=bl&xSijb$GIezeZg( zS(N;8_o=++mhOu0YV4q7nU3o6nF*A^&+Ui@PA^+DXOJ=mF)Hbp7Sb_Qm{V*;;`-l& zu;8q^2@~NPwlRdLtdZ0%q{y_jn{AiuTDLZM)|(X7ATF(8Ef{!>NsU5{@62S3hv@40 z*;7i_|Mm^_4Ik?6XlA3+YN&rOXX5LgK0k-hX~tws{#aY{`>JzeOMzHQFQ_w3!#J;d zMz_CTb%qknHol`%)G4h-#*6fa7v5huZLXQygh;Pv3+wtMeXk`e+tGnEM~M*DHeU)? zhE!oz`h_wV`dX$i7aa=tL=a<6n{3>^kz+FA7}E$uKB?XOcE^d#_I?>2A>r+&-O!R2 zanw`z3;IHNta0mjju2;|(wxz$#*@C?oLG#hzlC;nl38GgL^DsDCR7z_JRoMyS@5K0 za_PEfeu%`U3<2!|a}R#a>H=%iQ7;mRA3@AnebiEvUcmS4rtUl+(R|Fw{#d^ZW*V6! zwvn(%3uF03S?EH0ILZco##MI=r-5&AvK>$4<$EiFH{nSs4m1#@zrLC(aBFJ4AZ5IH z!vuO)Ldtl<>)q_+IIVyDy*~y2qIU&X60YaSwW58AUTnKM7Jv`_yG?wyuVA1wSQ*zmS#f^VH{hJ@J~p ze?5K?Lp&$B`yN$D*J(Ob%iq&!{61I_w-~MLw7VXWD!%2C;%y#+4GNrf_z8RWx08V?!Wa}>7b(ZnzyLra~t?R%7Yui7Sd|Wivlf0 z+YApnQeOH7Q`y^lwkl~Rqz|Ww_KT#BOmhuYS|q9l6emngy9h4cS=CP1_JY+Kdl2OlEX-)my1g2lke=u5T!xGujob5gg*4Qh-%XZfu##oP(gtht_f|r;{ZfMScYSAr zH%{8p#wN<$zr%A1acByg5R=#{3Kb^T13kcLI% z!u-;!o5Rt3HmFMeeru${xL}}&K0$1P-=nr)Vn_a++s%Y`5?d+u0paTf^M6+|lGUD3 zpjR8uVrX(#@pNmYb+#_x=`L*2p+WC$K{yFgG`a4=3|15>`>(lYJ-NUjDGPPCaOn9fN zt6!y%XusX+tnQTLIHLgk5xjIrNK1QQS^s_Zoq6cFfRv zuCN3n43+CShZKG3cR)8S+*rk5ARgy>=_$49UUFB55}2 zLp+?66a`d0w37pt9fIA}PduSa1K7C>L;%z*4Nxr;n0&HCV2~No;=i4>znr4~7l>;*ZJ}XBwiv)Kl zdUj@f=nIUz6gM zke6~~0M{c)XBg3PMC@P&PC1hM;F$h1o`AAbRIwR+aezs+-3Dj0Kep(YT|osoTj7tnO*&&a<@l)_R$2JS<(p9}^q_r?n}K5@Ft93ay)KQDK#o`eRV zm=$kG1Gwb2)lZyo2k`-Stw=ZyIKtuE&VZI9=gwlS-T_UJg#kN%S`mbz9R&WwGYSB%H;uPYKmSWqHvx9#(x&f07R1Wi6|KkxD( z>H+t`5;p4qp7}2mJ`@cMQ=7@B#YQm=rNGJA0yQIb;y-aeOUjKb1jo4hzaz?dA$S{a zAbm!m2=I1N1hB}5n5+Z;rw)^hCzCf!b;s%4+i8Do z-p1x@UdG!#+TsqWqI+@ZtFcrTF@oxZP#naof`i2Hns-1~5;KZN|H}iwx#L zY$Zd>bX{W#?mwGKBU(G3lihnKMb3d%M&P;j(k9y(2?{+`MDIQCb`$97@@V3oMq4M( z6)C0;jr`DG;4yQ+?RpPBvin=muLN-|$bfwG(bFf2vxP=TS*_g^xOw88p90|-3-yb2 z^xh`bPUF>2$>DM(ANLxnL+iipjgaBo{gx}Lb|6UK#()Z9G)9XSTO#PVecSeexp`mvnTVyWRCL8Cx zdLdAXf)|ut^qDLIFa8!5oTontW_`(@Liv`7^RlBxSvRKMOf0%h-VBTC9sO#Si@j20R4ebb-Pg znER4mvBIfhlRrnSo=c!F`IMzklb&7`6HzX-Wcm{>MzPF*`?+~5T5W7 ztc%frZmzicm6A4pVQvv^oGz*WlU_*MVJ+{DWbxv!Z6!H^x^SeDM-k4^4y&N&V4-E2stFQ=7#lN4h zC3Q8dXS;A&R4oHm!-1^O?cyv6e2k1>;OBlZGC(J;hM9<>riu`*w6l3`U+n4GJGp`k zTvrkMTtnSmr99z5oeoP9E)Lq68;b>sp3>sm1vAb+2FzDA#dbr#w z76Rq``KvRFt$;`WQo%mJ4cQTg|JX?e-+9=P@|qVjyMV8=Yqh<*_knf0F&g;FNAS2X zena*Fj>2MiqrjJqtwstz^sPp4r6G7v)OF2tr5EE<1;ZtB8(^<&OqbTTlUqe_;Zvi- z%PKg?LeIXCIFVMz|EAkE3v1#&xq;D@`=tade)H`<(!vdpAtr?F_M=A%8tdYA4c;&g z4fr*6k_{+U3)i~9Zv*rOSDOWaw@*34S-+WF&!>P{iPXq><*TrK~;QM`r0IV{O-6H)mUvse}J^1 z8}6c))!^{;7ZamDvvi{PPV(Y))loO1+1tO$G`O18vXbovcrs$?>r8m?ugBYIJiW2< zfp+6)@Hx~~J5FVb!cl z>Ye?^u#4F<)2r87-K)EQ-F^Q}@T z@bziq?cgdAUpw1Zg#YyVQCIgWwF5Lbn|pI=QK>m?z7Hm$`uW&PN**=Kvjj6b_ee8s zdt26GHjp12aw#N-u?K2=(3N9^@dP5O{?_0qdHey;t_&tddgd%4u`&NeI*B3b+XVlOGThFW5%v9>Z3_SMd!&{?~2 z^jKM|FWp>g&QwlPOnrM{YmBSvjbo4n-s>}y;Sw3n{B_%P@6APXunMa>Z>~RsP~urC zvT}pC;X!iZjTXS4{q9Fm-}qkBx^1nG-7Q5R&^&p`@z7_Q`&E)DSeEHgvU{5DLVDsp z*Y`CwY+Cw$M6=}{M=@SQQL^Fo`;Oc!k?UNM=;kE_f+%)P0`2aWei6#)Chq0x_9-bY z6zHsulUctHuGKaaCDuvuUDjRUm8CSl6b!c%|<`Lj(Gde20xLl>`JIK>fGC|bLG0cMlcC^?&D__SVxDefD zDXX9Ga>u+=mqCc|OLX~w(yttsf65;>ab^weD*?S(BbB#aF4^QQ z55-tlRCtH)Jo)>kD@9o~ZVy~m-(B$a;dOE#D%bk2qaNsqm&U(wNmG@OAw+ZpDh5f# zYSKcMHyf{YkJEXWcmo@>D6Hazppes>Yr;(`?pa%en){&T0k31KRC-;+R)U+gc zl~DD1xQ)!)W62x6jHnls+Q>MlreyH-A3$E}G0xPI-n$iF93yoJ9pST_auKH7ovG%h zUx}~c%{bi<8x^I-U>E27-3)W9|qj#a|WBqLF3l)6G>!lHvz@2+_o!92mTCdqE z9o6T8Vcc&#R~%lfqie98Im^?^UgohC5RYLO+avE?+I=Q|=8 zZ{$Eho#lk1BW-p5VthpNzS9GSNAr-X;1iVeC2fn#=HPXa`{1R}omBd(_4HS}YkNq+ z4XPTYqORxgpXzoWs>G*O)Vn&C&Ml%D&)C5T&(#Q6XT8|FkZij~TMy@g5p+Dhnts)B z%Gckv7rF7eTJ}fj?f4r*nNO}`trZ4uyA?8Tb<)@J-3Kz$I7TmGkefk?1*pDY>s9#idsQ%U7*pK#u=(H1GIZ%AlcDy zEL?*@E2)5Phkh50KRbjI5D$q1*j~~AZ#OsX&Oxgqp(m7VMhkrhnF)wVxq(*T(_Ew$ zS^{X05|xDhJN*C#c*JifFjD*(}b2b>2fBZCIOBP2H zo{xDDCQC$@9Sg=%!rc&B=>A|B4NQ8F#bK)!KbOV!Sd9Vr|N08!jkGXo7s-M3c)Y(V zT~<+)F%F=nIyjL97@`to306h1L6vp}N_X_jANknVV`Ah$1MmthTMNK>K22{AtdX*# zX_n_>Qk~3CmEqyg-;}dhjF1C4WoW*KIN%Qxb*|j?1OLm}!HIC~g5nhh=B8ad7?&X# zl!VLTEydfTxl4s$C}DN8WqWOh67Iypr$NIA2rR9!k|o;rJ5a))uazaDTFZkMp`(j^ zN7@4{Ry7*Fu+M}T6K5PL^yi_PkSAo!TU`Gjx9s0$ng^f)?8pJMiHkuKKok?SIQQ+* zLCe|iHF zn)q+L)bW*>3uWHS{TF5#z$w_&;t$vXCeYEPb!0e`BL26tOp@($0GisOC!pE66$56b z0_(BaXn9+*MD#%&x8NBg+#}m3A9KJBSqAK(1c98l_GrDyiFsq;j~~(nQ^@_RD=>_i zK4?!MvAkfP-yS-b@KwFo*zwaZGkN#lwnf!*^D*&M{ZAAW_?u~sxHzC1xRNumdq^)h z*MJ2{yPem@D!CJ}Nc5H`zv>%IJj=w;hcOFe=u}_y^jdiNoq?N>B`!>7C9124U;ZGSfTWlcXB=VSRIXg02z5?=3#BxiEZ$JJAD`UBek^ zf*%AbC!Onush?hTSOt~wetbOgF^fEhW*hTnLL>t>5&tRHt3{)=Oq$kj)AcgiD2kA7 ztz=N+^mgGOlp$xW5fR~BA%b~?>c}RaVzlO5(?VFZ`p-HQYoDAiu|Iyk{6f}XySJQD zYPGovoxZBCN5I$nCmMJ>^jc91a8DE;oX{tjs%hdVb4##FLbcY^cc37I?|8kTjaO~> z>pb(8grT#7FnP{62->q9)m51Yv9Ad=*={L=?m>C;Hq3~QPqaESUcH~9I>~onNm6*I zP4UdKFBD*b>+^h0+nHnl5URK0h=U%JotT73FLm1CZ?_7GrA`(MNZQvP6=np#oL83D zny0^{&EM}B{hp+U-?PNIGpbPTT!VOBlmY9MfH(C9(SGmbL&&W00Zvf;<<$=jcbeL> zULiC_zDW;)#OW0ltQwtE349l*_60<;>y%N38E%w|fZKpc(W&Tn>XYPNyoI^tix_?#qIaSYuODY&Uu>>WUh10V2fimnaWBqfwXSS9YT#X{*R6 zCNy}W$?g6A7rh3Wbm%n3p(ZhE*k7j4@RZ`D$08am_q#sosx#|(dyu2pQ)gnfP@U&` z@8`Lx$ul?ic_sMRN78LE8iN-$>bKz@rf$DLyT%v4xBCx3VsrX*#WzafJqJ?^YzOur z%6h`(;+)BV&%=r^UFQ+|tJR0zHr)hCSUNtkJ_E zKCmte5?xaOwq1lu0k_sVr(Z*}sVSqBuaErcR}_1?8oVaPrNM&8 z)DIP0T)LMB6(Q6To{3xS*^MxVen+hw4maCL z@EnAvMNd}J7&U(u^2i(6ZCt10T$;Cge_$faegc55Q5{` zEF?ucSbuQf3M2Rf5IDYF-5pf%^&(KpPf~zj`>FSrKfuTAQ*g)Daxr1%iW?aGY4um` zlqFB02zYOW6?F+xn_t1Tg94iAGoh_?}&ulPrl@63E zOWsLH&g@|Q*9+MQ23L7 zWb0UV%Q)tUW2kCkO4G_h5$v`S3|1Lse4uUxcj{+&0#{?8oxi{|BkM7k+`Tqz`Ypeb z*UEJx^zf3rTlf z_VmOT?!Ns4M9tL+5fTzkpnviha66L4C7uSIf5aNSU_h3dF$%<7O=kjVz$Z7*m3(jn z>UwWKDd`3vL((%JlO=X-0)3;)ZAJ_5H~=+KdMh&XaQGDpffQL1zESrJB$SV9!V<+qKc{U=*qk5+vsLe7xHiFv?gQdUwa z>t@jrD&)hCG!vWw0{aNMxTJ#bj!%R!4d0S;Zhk7z1F(%wrJT0w2}dY0=dKVf=VNo7 zS>6V9ss=&47HRA571F&pL`o}H^Fh^%vmGSirD3_a7u96VI@rDk<0^pfMp95qQQzn? zSs&{0>FkKPuScIrNwW9k=h)xQn~h^ypH$N1i12`oQuKyGlWK;S7uK-bl4&GSpax~6 z0K+(mx`qT)St$6*TIMv-H*`PD6ty%X)7UwARnv4=qA4@J+%|m$up^3d6Vmdg%E@F7Iybdwlx_kS`5>w4aWzhY2-BH$^~OaW zsT`}OL-8K^h_M05gB{|t6_%{y1{#`eJ|Q1O1BD1#q;eVXNmeG6xqdSfhYeDH9qnZ~ zPmTdBGk+ZmhD3L=P3r5cY;y?56aG*}c2n2j2(16awqL4L7`*~FjNN`S zF?DkS-ZQPQ<#VcEVJFuE+8l`VL1{L)eY}*DUXrQNn87TbQp)e6aki!DVP6lPAwF(a zmZIzAIrH?R&4hRu?~_r{T-Adl6#{#C6Oj|Awl3l2R=T{K(SWFtY}W)ZVFEWE44%E| zx^UE$4V+S@?ykU?L1Mt$Hi&yF>7Q#L9N;2-os@N*DVko`VPzw>O+?rea(Ntb!`6b2RM*>^+ObYuCNz(tmU5R(7aY`NK?r$`i zSP^CuR{?xy2TISMt?j($h;XQGrMGHHCvJIsx+K~RMS-0jwX^3$oNx-lX9E^~ag7!pg zZU}}fUXoHi7NcfX2|KU`AFv08B>%>OCh{!CLdi~l&ys?K=F9yj%0M7H8|8_{^aFH{ z{B+*9(ZcxV_9+A(kjco$V8b|&B|x@LVEpANXjPbtPoQ6bXLbJM@iow*Qzi!r_s%{0 z0XhcJQ818}ovnot#X>eNCFR(P>$84Ye*e`g+feeb+@}eSfNbz*FlyxQ&5!~#|3HFY z#E?A!!ll9zOaLdV+)c0TuNacK8JDAAba88!9|RxbF^hu7eO~e0jj|&2?6apgJ|IRl z9}6Q9G#ZG+ULt1z^aY77aWx!3QBIwS`q~$z_uWVIhfD+$#wxvL)e|Z_fZ?Ws-F#)) z0r>7Kwife><6zL_6Ub;K%mGbsO<)dzW?Vw)=rlR-))$QRSm(NfrpB&j&5kS{A_z42 zzJriO97#J+&4k|ZAISn2hhRj}EfE1mGNr`wLHryJLj#c8x$KvZW0yP)>Ye046+q4{ zn+CvL1F6o(ruz+gW(#XH8UVK+C*a#-_Gk)O~ zV+{s_v;sTxpt(!$@0E`cuLwpMb3quSfVlMphV%*Ja43CPY#2g|31yqifvtfv_vxR+ zl7ku8V5HRF3$zM{c1{I>43-!``{Jh6GL(pz&Nh@Vc}#;HEeP)toKP8XhdS(b{n{{^ zB94w*y~2T7-nxCmpT5iUJ(tYy;|R)XJZ7?^{$7N$+{Den|{mIN%!Hg(n$O z>|g*TMf6{W;O_eKMFvWQl=nMe`bXrnj?L>@$kl-*jjYpzB1Jd7jHU_uV43Q8za}-~ zgGm`1?7B}rb}c}gkj&;}QN1K9i@0BI)k@VHAn!vs0!O1fOk32)S}^S#eh{Q9y#JkH zf#3f8R%}l^r|W|>tC4T#L7(>0z6ZC#Z?nkqk^=kWTWQ7mG+)Bo#}2thxzA`T6q;@9 zu-Y!Ltme6;r30B;lCF9OQ9Ot^*ob|*&FhU_ubTz}0*O(TE2>=TH;+RdNm=fTbEB~- zvz+xf8$H3|k`8N?%n6pT&y0+M%lc;ZYKBz#w!w(9HpIZPfX3>WJi*tLQ_49Te(my9 za>9`;v4Cs3C9juEgTTQuktLqZs{u($g?mg7~{ZZ7_gavn7i!esLg6 zA90P0W}u-5p)^7=cO?Iai3I-vz(X7Do-BUwHVEh=!VZ|g2pzJtM+^Nl_zQF%1CkdE zh&yoECk=#B_=)CYF!F-S4&Vj>p01}mE%{jcZ{-1u5_>c}ro>;MM}-=62xJGT1Dvs& z-uY;qyZM-OpE&XXWtL!wtP;5k!J?FmiJF?N#>Qnoz)n5b0dVXjd4Q;19qf>C$m7R+ zvc#Y}id5D5A|G?y0{q(V=-mPL+0m3RO8o&li#{z3Fptj!h?@FZJ9tdCDq8fg@Llf3 zKoIdQC&E=8?lV|};TzH?9O5*^8+Vf9x-A)SweV6L`QtgEK>6BL&2!EIO|p*>oE2~% zWY(@XJ84hjZ-^R_$sn& zB?JzY`R5n)-iGl10rI-SLw?AtX9p98Ol185QfbG*oXaap3lP=v2cQo59OAkybAElA zaD(&jNwP=vfX>aG)eXLL;v?iBDi}oqCfx0GK}*;2din4IvEZxGl2Yq=b&gkEmS--~ ziyn_h=f5!r);!crwWW){+}Uo?Aifu#W1`iN+SOS?~2MqIBljz!ewAF!Kx zR{xYXns`O$Hl1w2mHV1~4Nek4wIEvB=D&O`-Slw4U|_vir@eY6bAgAu&9vprByKUv z70mGR9c*9@npCsoOtiZ{K-Cl4JvA&D4-mnEg8{yL zw+4X_-<7NmLk2<_{D}iWWaoskl`MXHHt0u92aP9yk{JSsAUu{P&@V+Fg`$D(!SGK? zhwNzngfYOgG3k;}3I%rwEnw9X^gJq&1L(@km-%=pgd2^Tj8(v64bT@$PLu*L_(`6x zgp!1g-(2Nmx$0Dxkf==#9ide<+bEq z0Ab)B1=a+NGJ#ht{8us?vcyt2ogfSBS-=bea}9Q2a3p&IJ(Pe18cK^4I|h|iHt4_J z%LL?Xy^79hqfT?8H}^Y1IVs>t5EmS?)}E}IXKDucY`oowbiP4Y!P z)f14+89a!w`X`_BF<(7J1(gB2Xka1)9%~&4>$0l>CvFYxRYx>AP=q$!0X(gNvHxR1 z03uVNwFxvq`nCZw1)}cDW3-L+m(X<22Y2qaRBETm?R^1;^u9*|xDd6o!DmF4L2;gh1prA(AafDa7>)kH z4TLWLwj@$n|8-WAFeqPx6A7-~e-ewO`wn#VV}}0kmu~^aUutJx#G&Xwj8}&SZa(lo zh&3c2n6TDG!x8qYE;Y_*5~ZV99PT6F{M(_WU4iGP6Ph5v%&|199!xLA95y4$>V{(I+Y>4+~Z%=Com z?~SA+pRSjsr{7x}K4s_Eb~gBY&t2cRy6e7uZDqsv!p7Ud%0@>~4xi7^!P?WFiC;|M z2|k~ajf0)NCzFsMcrWMR>7ixg{@m61t*eWTizkyPKA(ca8&4Z|z8BB+Uf5Wz23fq{;JiH(Vgfq{vG zg^h`ghl_`Yhl`7gPe4S7kADvz7nkrp;XNW^;`_vSge0US#H8Ro@!u~&!vH@6ehL#4 zhZr9hAN=qC&Fjy1fCLwv4kr`?jRZg^LBk+H`_l(7f;3{G{p0#e@81gzBoPZ62Nw^Y z0DJ&)A3z6x8yyn^3kwqyd^ZSuAHXERB7MmJ44X{*HO?b9a)Eb=1-Q&|wcQjtlcy|C zE#2Sa;Zr`KqNZVe%*M{aDJUc?A}S{S{Dr)NqLQ+TuAaVup^>qPm9>qnoxOvjho_gf zkFTG9Sa?KaRP=|Kq~w&;wDivznO_Qvic3n%$}8&X8z7BM%`L4xy?y-ygFl9br>19S z=jMMcK-Xa#n_JsEyLFF0eR_dAJ_Hv|yD@Cy0YI1sO?)-E`R}R9XJC_yi+!Vu$lq$Ka z1`#_>`@fTKCI_#aUL=V^)g;h=`B~8#@|@dIVaCVQ>9OBgmVDZd<-6NkmNyN0bGhJU zKStukHbj58I?T~@&GIwu(ZHh4%;6h8ua8okbAIT`9DoB zO>xSW&~`o%Q`}F^*2}C9qOWex$ujX1ZXabyv7YidKe=AG+dYw{3>2B|s|&9Y?O&wnu|~7LnrVy$z?u=Lb-Qj`da2U&4jOPOT&@w?a!!f}eimzkE(u zvB#qJwTg;4K0jty$f7Zqq3ER@#REHME75WVmC@a4u-&VsM)h6J?m)X4Y^iWzMYz>r z;Zj|~xU|q8tc|SuwEfhuchqUn+g!41iuY?lRF6MP=H+g?k1kKEIw7kiv?@bHBODw0 zgjfnK`$ZbSlNeW;Q&{G<#-%Z5{Pm8a^pI(PH26q` zWP5i@2U)8M1G_mk6mHKI>wK)TPH(?yIIyp5f{s3(Yns-}jmn!%0-KKD)F7U&g~SK? zoF2f4`|j|$nAcZvF-6>#)N}&c-=78Lcz@bvAIx}c{5G7V8E!ORLnshdewC97IiT=v zQq9zkyB+dWFIKOB(6b+>-trV31=ZLOEjCyfB%k5`vK@#jF?O7$D@M5&NM_1*DtEeeh<;w7&QdPa%Np!H#+x5$Nkn?WV zyz?kArmw0F{5lrNw&u(bVDII6-_ZbS_H{mXgwTET(LkhJ#ZPid>W9jMvi=4a_QP#S z2};8j?D9j%!<_b8GO-FbciY_L)5ZSIhw#qA)9cPBuc7Sr(n!SZ%id0EPtzP@ltV4;UY*v9CpU9;GA( zOkKsI>1I%+wM)N2IIV73`b2z6IFXv^6U(O$%-jHPK}xQ&Wy+IOx4Q5Yj%hE3G-nPu z;rcm&YuHpC&%6*MHfgt56*?0~!BVnCwP>~p)z}kl02>TIJdbP>ax2UF*fA89Y8z)D z60`)%mg6drT-hW?!-J>2j-`mr`-3bIib2tX6EqIyzps&vH-}(nuC$^t4bD9a=c?5p zlSQAoMYCORX+8v4h+d*M7#(i5U0SkYkK%iOwxbb1nbMT*>cv`5O{p|dy%Sv*uQBzs zVM{@$d??!2xWBwiH)~PeKyt`_rQCtbAt=ivtJOQIL0$A*Mas)<%V(B{QJ~3uk0HQ> zntnU(^xR}#5^cjZ`YPQ(xd35)qFLYm-p)-j!Pl0ADuqJ_=hJPIKw@I3UmuL++hl>* zk%>pR^JEXF3(CMBY@ThJu0d2IZec4qKAoX>(q_RNR>1^TzPuMltX4N$V=@Pp@emLG z2*fC3Z5O5U(F&A5dcqWAxYXy26yLf=oTEnKwwwdOzoupm4Y< zzx{i0Qlxq@lL7ZMt$5>v8lm|eDtR@rzrr+A)zD^KL!Cyol_?)b7@_}}om)UIIX?8F zYIic#hm|2QrBmx;^38&T-_>IeJ=o^YDp%#^39lTB=k2~LCmOA3Q-8`LsD2wyWFsETCRR<#wTR-_x*=TgrGc4el(HT$^F~IRfzdU&wg)mkfvhkc_gw zWISlF;Y)e6iSpK1u^w~Gewp{&5Nwh4CJ?8x@q_cmDlsDSjG8s_aF@i9z0rMOQAMl` z66W?pl>fwBJpSp}u9?*{e45unZ7wtoOY_lqHX0PJhYD~*GwTZG~CGDe=1 zIk3HigSq`ar5bf3n{t_8uZN8Gj$y-}X1DsaVee;)#a&9cD8ei#>1SfwL^SBmw)T%3 zTTM=!drFVXdg`Gn2c1c7$mttWVGjVTf;WNov z1sZuw>pnBF@9xjg-y$-7i#c@WIEF87LloBfEwy|iRawtlBgY82rJcci-{oBm$D(_VPrw`O65k5uF)n}64d-q(v8U8p8#U5Y-;@}&m0-jtyQ074v z^K7>0r-r>bx7Pnv)flT!GrK!i^yP3XGD$O)&rRJ>Sz$>0<3ec&Oo4wV*?wQYOs>d= z;!CP^O{G?fPSNHeL}#|F#@oMcjxg<&&Kl<;L{@5v+ahl3bc6|ELdu8ar*`Vv`p=uY6eI8D` z;`(AubgMNKr_ZzoZN=U@S7HXq4`U?S4RMa&7t`UQHTA7>IVv>u;aBF#=66mCTBK6i zYTn$6j(;p@s^t=<+&293Lq+GAdtlX>Xpd%Ug|lEfr<(>z(J5+6jCYxn3 zrcK9V+mY9xEM3BF+Xzg6y*o`CMLl!`&)*sAAh>{$Y^0L6t8mW^QPohTrdmAc>dcy& z^^UxTr9`tqwXE`o83EI6wcFtO_Sx^0CzF9^;ZOuwoT6@q@eyuW(b^tVxzk|AB@MyR zY?-R2R-IDTZ`Rlm`_RF|Ol-`j!6YTyk79Nc8h90PtLpo9zox`A&@QhR>Ri*^A=694 zbJt&ze+AWO$4baH5H0YD>u!3pRAimNfnQG%YgnAY0V~c>$%d52gs=T>LE%_F1QcNwz3s!k+*K(F(wP9UVnD_KFF+7qvUDcfHd}y|tD>V5K5htCo zUTK4fg3*TDH#J4%I*F>RG$fSZo>;CjEA;-9tH%XWgO5d*sZ~fl=eg30k^}vo1#w{X>Nqb0vtMuU8yNz}+%c2$=Usu zX%p}rLLM9ivR0ZS6#EQ_z1DAoEXP&rX4&R5k7s&nWv97AY?E9$8Y$yg*%zrl>-^ju zA)%fw%2E;KHH8G|gcq97p741|6-rxtC`wSFs&U=YD|W9bMYJF@jgvJQB}v|+%$hVsQ;J;W zgge_8)9-)6sWOB&_#D?}8*~ap<#?nl(*+V(g8HV?h7X1dsdc|sXt(Au$6nTDd5JBx zSRLQa#imPbLX<1d@`RCZ5tAiILxkOHhblztjv0I`Vni!IUWOF;jqAf zPl)ji(-!bu|0VvJy;iyA{!>WtWq^UdlfF76_$0MMe?Dhiqe?{?R-k@cS5|y)xzK@a zBqYK#32vaiKkZ}pV|I^@ZGWeSfTNvp-C|)w0fN8)J9p&Lq|F`Z!LeKN_tLMR)?l8| zuJewu^P+lUjR6-4(R`$h;n1%^rg>hT=>ffR4c*PCdc9+3c4g0rQ>(^zN>DZywHf)+Hs z9{sKIa~VO7=}$+c^SS5t7rqc#bI%>3=}gprlQurbQh0q-kMBEN7ju==`+Am3aHpK}IGjw%}-qyj`U>-+d=yK_YKx1dh;>}g|+KC#^ElTC+ zM{I`&0dyMQD(YWY8Q>Pk`=0mC`Mr62YEY?5Fd`CEi(ipqy>hL$G?n6N^SH)#Ttk0% zkj%h)JF2miy)r1gnA+r)je@~`Z|rW5jjR6rX&>3rvJ-T9bi3oO$&Y7qoEOq*hnjTX zY`87aPq~TW%b<99d=n~0u{*6S$Dx>N>MVFRtuEOhdDFPL2>L5_%0U=q-A`z{3^|lX zraSjB{Be3vp`*BMjq^Iau$kQNv4LZ3NYb`wA&#`ECiP9T7(w>8Qe%Y@nnng)t*gYk ztF<3lsO&B zBSnh9B?eGTvk!VJyyB!6bz4pqI$k@|j+B@cfBU>@+($U2q=#!|oPzbKKEfg^V}omU z#Ld%zrBdUg%9Q4+K8G@UC)i~``5Bj@50_#|j<{oo*i1-U?E1>FNZ@GE*RM%X^~UA2 zbRWSyXo#W(b~nsf6=nbis|Y$ZBWY?PkA-^a7doBJzZT6oTz$$5GUEHV;G5DDnp z>U9iXJW-k1;imiA(8a<=_uS`Fc@@^x7NlCBL-a(yNvHa1F&D3!@A!N*jZ4W>`-S;q z#O0dlNtF0(tPBZibzS}Wcc@EPDUvO1;2gyQopC142{v25<<;M4&Kp;zaUfhbB2t1r zi5cC9h7ypee6@3ZpF(FE*A&&9!)T{2Dg;g|os@>7=dx3Ig_pjXr@^x11 zQqfJ}$QS2d7d%#1m52aX-iJ>9nLuqg<&M^=OAcJ5XXVjp=F-B7pf@GunG)aDdl@c% zV(tR_9|nmZUVYun+!=8gCsrgDkD1jSP;doNzbVBu9G&GOsVtogjfQkL1ocJ~@{-;p!5i)hpnU!QInEWxg@R`a&CI5xA1{MiNzGK9xKt82`& zu8s#TBVH8kcvr@B?-*8_WRvA4B18eKiX<<$hFUj-&X=j_rMC`4Lf%Q+8ak;WeghiU zE`u~-#gSF&Vgagi*ZDVe8{&Z<6y|)iT?nAkre(vEkg+jFsKk0;u=I?iSs7A~CMv-z z4}W!WuySd|H}j--g=!`j_JG7;wXJF9a6Om3_}=EpnObz&SXQF%dQ?(@Nj626rx{cQ z?2NMXW#>V~%ZU^#mSo45M{OdrHb?BUl_&Dzm1!I%Jl*Vi4XJ7ElaBWqAu2Sck?;qD zv;nJ_NX}N*_lAL!Xel%&%%--xAw^ed8tBT$f`>0<6LjuxEqh1ABH92 z96FVe9wl2EWILH#B`e9vTB@$LDcLu=F|J8GtT;b6j#!WMoZN?c1lJ#DAKi8;iV1IV zi1y3zx0_DsbllKf)R3WOEbd)eME~ZkWsH|(S|zN~D1V&c;Pe`%Te(~5_QlL(@D2PW z9`{;^T?@qm8PFvNL2)cvh-oN`(UNwQfqqbXr|{N5w~{Jf+(qll|LQ z2fBrl5`TBT9^IFfl~D-@)orGSs$NT`Kn=|LGx7?i)OHQ8@(sQyyT~WcRIh{^Cl=0#ctRtn*n@*#Shhl4z?sd2XImTl)Ub`xdyz!?;p6*#2i(s*sN^WyTaEl{dv#)ip!Ge? zdI2J)&~oFUfT7kv_)f&scD=XD^5=?_Vsn?JnT`&zvIXIF3ieKO&l%_27Kp3Ac3W)G z;uFc|w>ryvxipAkzb}DW6R!~&6^w+6rTZuhi~BBZ@5f9x#4=CxG#eU*lX~K(q!}L7 zzW*+s@cbT)V+lINgX6;J?23{?SKGbm81MMKVVa`s?BryVDU6~$d!`l#;Pahv8^uWZf&lPUajd%@43w806 zgum1qFRwnQOm!ttb#8PDJ$sO3!CHWora1U6Do#z>=v#d7SQn>OUh9TN@R+vOqpay7 zKP!r&lq!EWMQ;JOJ{aB6sKO;(J}kRJPTOf=sB1g0CS&MKw1v;_cG4txVs3?IUK$@P zB`2}(v-0p1-M2<{{!qv%$hlgkVN+d$OQJC{;1v<(w;l|b5ppy(rsCGSPeHdhA(xac zzM3Y5qiA+kNrmqB%FxhYRwnAQ=5evLCwR*7EP#)}&aZHFdXFw!>MX2`C`1F~sk|E-q0zPSb-@00 z0hxIn1H;Ycl8}4;#YJC{$@%4z&wkofA|uDm{bt2uP|L7 zv_lq|=KHP6Cc@s3WdBlI6fKnV$Bjw{2F7J8S3+E?Pk+rq=Yb~TVa>>z43UF0MFXf0 zPQn$AuZE7SB3ydR)Jug{tbW~^u!%DB=SC(~MU`jT8pR|xaE{f7>1=K5l+5rAPtTc1 zyJV^^bAGj$brQ<#Jr$Jb@sFE<+Q8wJX5~TweNL; z$m+=&^OOUC>Rhc~8A3VOYd=L{`coe~Hl%Qg85Rh(AiOzJZy&pFI=U46$>x!lK< z%6ZLP(sPV;E6vWA`zK?`3|=N((`yE7y!?GYAZ@>zWfme3Xj7(G>D$$BQe?3ZtiN6C z@wV&N+YziZ27}jE_FL#LqVf`7ViSaZr;9o6oxak0t#0umt+nHUK|_~^n!K@Lm3X~R zN|y6MrOVMl&1(7R+`vQG|9r>P|B>C@|C5IqV2I=##|W7mLW+VBGh*_PvoCd5Nhn1` zNQQygI3Juc)#{6rNTzKT%uK|hF3NV)LMeVM_suU z?Hd1vP>!+a0DR>D?oDH8x0;8IVny;J7U85YFo}lei?2WQo~}Z>Gw;ER)7(PKt8{aw zX~CN}J=GESzCR=Sa%+A2?315Unx%5Jc*Bm0`0(vzP!`ISx4$Io7qX#7_HREf^iYW| zbj{a(!GRAe5Z)X5b#TmyMFr1~@_BjyD%MT42xkMoL>x+!Kj(XQv^|NG|GNKa(8FzmUM%feBlnkbN`ms|Sn&^!xP*S-qpUSu zz6i!!c|1ujKXKkdg>0Q)IGaB2chZpy1sU^~j{o}ee+&ySAc&xifSRaWwvT;tt-@KA zAq5tD(|fI5c~=3I0VB#^cNCutk%#fWRDPetfrBHdH%7NVkNPxSyZ77hh@i|@Zm_Qw z$%F7)ACE#Y%^jv|Wc96(&Uhg%ae4ZGKH&Z|Bwff^a@`nb6h0(3@`-BBB_{dhQA4Xl z$fujC+VkZ%N?Ly(t={RmQoBDo15#MuUAZ?CZIakPi?cjA1Hy{CNCUY_e5ZRD2s%4YkMnIQueBD;hwJ>@ z+tnlEv2~;3q6qz8ohO=a6R<=IhdZ^qFyx#ZkJWIeW|>qZ+mxa31p?#m$K%q;e2Wqwn?4mtJt130>eRB56j z5P3+jHpU_jl3(PA6~vsL===e?T?)aZn3<4Dy+6RNO$7Ll)w{C)diuY3@?Y!Zzjnj_ z_Y#6p3Nhau%!2TNRatZg^G(})gHwLCd_Y;R$nqxFTA6dpTK{!Qq9&*Krdyaf zsawzVA~Z|`Cej7Xru?P&oEC0M5(>VGUTqpbls z0afb=0^(K+d#O0NpB&yH^FM<}^T?bsdCS*3oQzJ7TWqf~=hD4+Qn$W-UdDurDL#)E zpjJY1wFt3#K1)~oS7!{Z1r}}D1m}y+f6o$+ds6x$UI@SJivj@R<0W+Be^__Yot8!; zEh@ko%oLM+kT~y)y2ZU#vxam-vQ(^Sr9@R>3Zra{?`)74`vbJeqg5Y+*-rUlB`GR8 zBR2T%?fVloM%M}FRT+=ki5I$mwMx_vWiA*L;%sNB4&QR75p%ddutgP{pfbmoVMd-a zJD~e7pL0=QwTQJGnKL^^+>q5dnTw+U3z?57!T8UC?0eFpC@@8ds1qG2J0VTu3w8$) zm}}RrGU^VpBaVE-a~$5|u=QRvMRNCu!`BE)Uu>zFB^$3)PM`T_#?y-Y!|^9z77)4V zdQB*=Gk3e+sny1V$P?aABbYSTQ9NJGJ#nxSZCZ7{GYE)|n)Ire3J!TCEkE63TmTCU zg`T<|F|I9Z4l>|O3surT9@I@%N#b#*dYw_CRFF~^U7YCcoCC1F`yuJc#+kCrX8ZDS zNp*t9*O7nqY)`y(jlzEbmd{Io=iS}0{Q=a4^^aeLyzjJ=(u_t7wBbsqdwlnwk3ur8 zxzesGJ3?h*P>WaOF$xZbhjr0K=j3Gs=T8Rkeq5C6YG_DBxs*Q8WBM=C;-9OIc$aZQ zE#$tJCW0;My98fECz=Jd)7!lj3Yxf_k|^vhzhaY*EIzG}+Eg=}W*tj>{A}*8OK8o3 z{VFs2hLyO=BGkr3SN;;xP{BJIJF8MrIf0})$Aj^bJi$rbE5eC(tJ8Vd>X98RFM5Rv zzWrg{m0GiKpN1C#CmJSDT~-iHJOAnM<()oebFQ$B()ZZc7EZ4iMfgX*8LP`U#8u=& zR_m4*oNQ(fTXRGuiJ0lx2qo$AZjP=mj)R4QC-a+*h~evcq=N&QzX0$=tC88cN`R*y zC;H4>V~DlV`9kSz^KjAbmke!}oyU5@J7I%wfvjDVf%2!5o_?1Jl$ymOn8A-|l5CF* z*2*3*+O`Dv4zgLMV_*pRd8v4eKN-nTNvRCrHIL`t+{)6t*{s;D@nW~oFr_llt&B{X z9oD<6m|T{2@OZW;Kce1a<~$^E@Nd^x2wzZ>*vMYfE@w&2Np8si>A=Yy1Mm;U)VbVycVE$Iw{EF;1zaJT7em zEoGMNno{{x$BN+@Seb%4k6wjtY?jYfeB$+L*C@}MEVa|ygaud47|kd{%1)u#OM2!( z{?5X}q0(K05%E1O=+`C@AGv_t{Km6V+wjWq`uigspV$+AUhEs_!6}}MmU6o7B)4s8 zCp#v$sh}pgp!0DX^wu{TCIS)u{8bu;J4vOu#cX1Fx+$E`Qx)xvg;-VvlDuPd-CVLx z4b>6OxB5uZQ|#h$Bj3tinz73D#mgjLp3Ru6sbeLhenGbpNg`>x=UXG(Z^Q_@D{Hta zX)fV78gt&8&2rw?CiS$M0{0 zCt5|~k)pXYr`7+Bz4r`idT;l=S<4EDDAEK0mENUySfZ4KMUW1mDLp_yO6bK#kt%@@ zr3xV+C7_THT0m(^moA}6=p{g?p?Y%f`|M|)z3+2o&Y5}UnR90Qh8f^R@=tzO`CaAn zeLg42ND|6>@2C>)%;#appZ#W z+0A3Uz};v*uO-)Ybd+Crh7^T>@h|2Rd9pTF(r#yB84vcuTga0N*C!I|;Fe&8FoN;Y zwA3j=-hfG~O>cIoJ%QGAM}ew6e>5tf?>~VB`QNhiwE?wR%}kX)mTZ%K??f0jtmEHq z@{VUKb>s&czpx#AWjBQ(v!=s5dP~}MEy7cmUM@j@WMTta4)Q~zX^{dmdK?w6giioDM#bR)rxeEtS zL9$X{RSF{BWQDst-q0lr1&B;bG*gs*#y%?^Y*eFMYUA44a(KSGd5Nk@bluu`&U4y< zDw(l*$NPXT^TP4RZUK1phA`bFr?0wF_Fv^YhKvA?rP|`_E%#mtOpw`n;E85A69a;Q zIv~vDW09$$f>k3_5Jt=wx1Qx==v)q8squ^as>+`Bp(1t8A(5GO&~uf2&aJ#g2gCNx zH{`sp$z_ZcBJtn)8?S%s$-ArfZh4C*N&LO0{ptzd^l-Gb^322K;T+Mg?}TB!OoCn5 zAP-SR)i+7XAlxQMvv*1o{Gl!*nfPG}7nvk9BZgEdJ?l)Rncn2IC?&St?vg&mpSa3F z8?(<{GBU4E9$Ykth##ER3mEMBZnzMK5!BW$Q)SU6Kf_%4dOZfEO|~$zBUe>+jm96f z$eJLP#HMt*#ysSS{s^PzpmNrX$>D;{NN>Aar~N^hz*UfcjNZl-C5h7vv@905;VLkwK3&D5Z3Kc1D-xym*IJ33(L(wwD9;ticcCiS82 z*(fLvalJ3RHH#@GAt8KwVO(5SZUI|~IW)_HbaW$wg1lC6lAd#XZ8k>FGlg4c&QtBj z%*P%N%Gcih{uo#Py~bc6a{tiG&i2~##u+R?)E`aSicbYItHjEfq{4kAMRr*SZv*H0wB8tfl(LVEoqv~Ge3$YbmxB0M ziiDHSsGS|kBwP4qfT7q&xUZkdh#hzlcMk?33BU3@c=MqIH@IDIs1R1x0hkg-uMgE- zL>x;{o$P6x&M=GbO+u^nDKX*qXX{{7yrUDXqjPp6#qkufTNQrD{?r2EbiJ{-yVljk zA@vr;&fEj|YV}cRa|pBZI?fjHc(HJ*0**tYYLc)x<>9m>6=D~tAgHSPTLKR}|cH`*0@)K^5$u5DgTy@{_5i#BVj2yFA+^7$>rW16edqLXO9LUpem@l@PdO%evLT*{faY z4)*ST#r+&^Z2f{fDh;a@p$Bm^@Rt!Ib?NMSKkHO*p3WA>%iYZjRBg3{xPl>Q?>;Kb zWl=p*s#1a^e7#d3*#%;CI_%%T^R_d>LH4VT2CrD*T^yF5Q`^WB$2t#xl!%8GX4KUI z10bc37M~U_iF~8eYeV?5=fUIE;r}ZrDu4 zO%`V{CUYrH)LFsKbCoLafPG6uYHQM}ryNi_I%BUyN3v-xEKzLknB@R*V{9+7{43_l zi+_|Q&(ZjjFX|N&C^x>S_Qz-n*?d8VtA9sxus5mn1a3o=Wa}3v!mj*XwWM|xcuVPT zr`)oqh}ni^@QBA#Ek3?SA1UzQ`zOMeV#76Nmm_-%t^Q&+(j0&N#BV5Nk1TrFJ)i75 z%vEpUyGWQ|#jC601eVopXbavBubbEJ`2V6qaTRGXaBJ-B1BNv3(%uPg6Q@TKC>qA9NG`0JuIFBAl@AKwms%dM{G&JfpRx^f2%!c0FqLREjib(nO^tRkpm>2o$GP#Us1id_T?Z$PB-U%jk;m3E*d zaP#3l6@L)eq!r)nGQ;2=>h`*V_R-j{*^TX{Fj@sqORCPb<~hFD(XY#3GjUS_narBZ z@)T@$?L?<0`!2gw=csqEQq0CACCt?|biyhifbEH?1C#(#f$T~g5pVK%gn%*K3R&s$ zCD1ymU9#1Ih&csbd-o=@NmNe?nA&?R5$yKW;ije#IGmqiNLzf#B9Y~EhSil$qfc|5 z6zW9+AMOtcyaMt&s||Iggi#hb8}o%oS`X*k85cF-=P$Zv0eP{+#r(>wN*+(e zqm=l$t#)*Bz9$s=gt4l=KRERi5qLN;-;i|O)%9`WP0s>c=!lH6N?%^}%T^H7Uot8b zo=z@+`;22;s*Jr?xIxH~5id2{kqC?`L}0=%azKI64oi+ewoJm~7uDAcsp3T^il?P# z^ugy$hRfB>XOrB_x5!7G>g?M(VUQpJ3CB$3h1^Sga{1c}8H%@J9*?ZLz?|%x#1iK) zBBKfQfsO860JK1!*$62!LcXpu@g-VY;qETHp4OGhwjW!~vun`c7|vy;a&L|H?`Pqt zs1H;JU@eue+}`SIAvH2Ac%eGaa#(7@2;SP|i^VijW_mwf5wrRF`Mf0(F@o?CC;^=f z`YskNG*<`Y^5?FuQi=#^e#cO?8AMZKD|2XtnO(jSG0adBVv4+*R0$&st#qpS)pi+! zrJNS0-1ePPEVuBqdw!fEah@o61}DZ~JZIO|#4q1&{Fq>Tthi=}FIs+o<>_MQlPPY! zMYr?sg?8vRvIt8|hRf>KYa82d1Nh^5jjy$ha4ngtlWr_YRmzAl9a+4$Zo2 z*zSH90uKcB?N`r5jdK`&hiS1c+cQ#MmIve8c-bhRceJ7b2)orap?_ifn^R`L5_CW2 zqR<2GLkGo3=v)5)84%Xp99J@e&=-zC1MGu9ojT%8u7g#hQ_7{_B-QG&jat)a&?*or z$hkcYvP=(H7~M}=*hr*stfv-GU9@Heha*MPwusD3{gqRzHKDMK{4mC^;SxIKPr)8H zY=E0`dNCZ&%{XR0At8S4AHp7vEbuuwS8j&62<6P9T-fOA)YQiP{C6OYA4klsz5|C& zmt;egk41_#6vn3GtE(F#a5F|f8d_Iir5-`e+!Ew7zWc??K^fDx>#IHuO_TSObA!L@ zM0~L6D7$4`jo(a+E$C=d6oZu-=K$Fp5&EMDar+h8Z7e+txZgNzlIT2*8Rt~%QXh6) z@Q55J3+q%(&bHj1s%^k4x2uUa6zzm-9N!Jrvv9ZoIiiWA-=XluL-)EHF7NhUz%gEm zHK?sihG_o4Gu8>jk1WKMLmLokx}z?MZ3c`C)yB=A&_LY7UEgT)OU}4PRL=<32x-Z^ zG9-3ugw?&tMGRidfg@U)gf{5lS;;+PvJil%!UOG7I5z4AP1cv1r9&;WoOL;fE~1Eg z9(Clnpr^D4rnA_w?o!f&Q_edzv(se$+u1V87J~%96FVyl`xA{Mcu+ltL!_a>TJWa7 zV2FEp&hAn%hr_s7Sm#K6P`w%44_RNB>0#_??mU5%7MGXL8|VK#h6KA1HowN%^Z0k< zZAC95GcP7wt@H^}BTm@r$XDxxEfg%SIKI&x@=ASLq%+y=50eJvC{Guzn3ty2+hWnm z1aNa>0h+sA&A<#(qQv=Sw0hpYKWlaoRM22y;v1fUAPa{<%JhFmDu>HZgMRWwJNyZg zylQ6{9#sxr<+rgW|M|sVlCZm_-(rN*XYHWGrJCFmxW6c)E2P>I{C1?rje+?<3PJys zQ2OAV0bvoB?&Gc%C}m(;T61%DrArRdr69~$Hom=04!~O02R1a+TUh>}mSG?>7hJbe zTKnmP8C#U<0E!-l&wS%135AZm5N677@=qSqrwH0 zhs_`sYwB;SZFd4@?41z}9$~f)RRKYfEFYSE|i zk`6WZFn%;JJ@jg!$^^1qR$I6+2q4^~1hsF*5~W+CZV=s@_$VDYq#W7R7VZ(k$J{Op zyqg5(Jgsz5SNGh-Li=gjH^nMNT{5aD$=YnuB&nP{+W&C3-pF8lr9Keq;UdVZ53t`j z01?3^1`yy%VPT~k#JX@`Cj1;OrTtTI-e+Fnfya5Xjo)ifC7xAY(I*Ob@6ZRPrIN92 z{*3{*ZXqHj06vHDs>@1q8jRT*-8X5P*}Cd6wq&6hds-gJ z8H}7WT0bPw)E~xbh+|))UL3@%lFmA&ZmZ&6eUj)fiw?do_{l=-($R#HIjI_@Kwnhj zGMtbOo8r>i0)DjI52Iv$yc3(a@#PZ!h$&jap@VQKmTJA%+%n~3Mxees{@Z#rlrVhc zokp^`?Dez0)-Aq+eL#N2`mTj?(iOP=ywo3VuIg~lo zaMZ4>;{&|fT?P{uKf=N{3+$M$SD#kl=yx~clsvcUVDtf^0YZa$y2CyeV{I11qC&5` z8ARG*uTiz-mp^raU)2m=w8L|DGvsq2P`a`yl7Qa(?JHdimjtH9G%5-+)AG`Fu_#_Zr(qmqic(!|R=RHkfx^zW0H34MpoquTWQOE3e4li8RTE zR`pVt8AlI;zk_=nW4h#EoHob)BFOcgS0C?7$$DNv#RYh;mja*K9nSXGPrz+I86yrW zg?lf5n6@5UDlGLYt8FFj6Eu9Fr_^n;Mu+-CONkl9w^|IE^1*Am&GjECQ8ClUpNaUk zlp9pYY&nm=X5R{NvQvqTy zMJkSZUr#fd26ZZ;1u|-Dl}X~Nz*VVuPtP!5fMZ?Q@eas=xoy5;NQav*xk+jC?Cyyq zRJs2r4%yZ2QDrFFYduYWbS)@NNp?!*WvYzou3=$o0DPkkd zn%iUV7)_0!l@#k72mSmO5BMY$hSGBPjS!Y*`36?NsubDjF1E@5;(?2c$h3po%p-`y zWaPOMkKra+_cQq{>n-Q$o1-UcB}}TGdR#9GXUR|M08SkH7M8c!vZVxSKxPQ3LYc4k zQiT45(Kfma0~%ep_kGZrgxq?xXHzIlrSwC9hpeG}pRAujKz)aezqrjbVU8~?^3sVJ z^)+peA^${aB;29I;p7QLC+2Oq3W;$orj7s~vWTAd91WqD+SlbV{Mh4{VZ6la7(XPR zf<>**ZqybPjb^-hT^fYr;dCGT}!>(l@LHX8Vo5CH&vwn~ zgat6&Kr|v9*_B7mY)Fujvq5;j%r`+RNFL>kmN@#jCXcF>_uVD_H?)8zFt*#-%t*e+hCeJU5O?P;2?`#HG;7P)``b_|hY;6G>B2Ph^^wr%e<&blE&ji|Rr=x`46?LkK_BWYAh}mrTyk zE9XfQ0KNdzsarmrvw}7*!a;{1w0nx=M7jxaxYT+uRcKe&z-O9(Jg=1{1njMR^3Wbil3| zF(K67M^wsY+1O#5MK6?lvXjnYSu=@898Ku}2mBK(PRqkRU1;SHMBeAJ zG>+Itj!Q|657&rpxjC4e z;di?3B$>9*sDe@GM_D9f)QAk_-Z70}r*j^I6Z6mIO?5<{MmF;I2Oy;c6H+`E(jut?P zoUMhHqKXA7NSQCP;DL+2Rk>RU2QYwI`3g`0#kB^MD;9g*APQ#pmbI)xpc%t9GWjU|}>ukTIgqbVKD7x8M=!3pNW0o?jGj6Aib1(2DxK}NSq!t<@h^I7t3 zS$n$K(ChgorK9(X$z1h|)P<`yLL(C?^4=pqhmaD4F*CBj;qK`?q}a`^*Kl~TDS2SQ zH_+rD4L6EvVh;DErci81rwznquz7Kdq|NO9OHx>vXVRmrHF_W31AorZ{;P}n;TfjB zpG?lD0w7!pt7iO0YsT4?o$>{PQ_3ac7|Gx!w+52~nEiHqg>N#C@^)|iKxWfmv4~FL zUVTESR?s`3;Y5a*on%q8aEH-rJ`S&N8&W^3mHQdP2s9u`{J~apob>Ls{B=oh;&zC{ ze2h&@>IPWBnrGJh8T79X?a3d(XS0rGghL?2YgmO(EJeK0CeWNu-JwCbFx{sY9n@_h z&vFpLFFXwbd7N~cA*IEPJ*Q3l8XheKHc-~uLYe;|CR`lMz+*#WbK@eETBq+&ct&d^ zaeoBCc*+hlM(_Uks&0(gD^ru-!ppu&su2l83)-8l8v5yC^e)@jg%Gm6>vhc|+RHQT zcM)+IzA|m&gvE5xV}OGZ%wNfE)b?XK#yL0szaO58t|joB1_h4GUdI#M&L=qxUQ|@{0?x=HT!_l-Q^EktU0@1mYkB z&uu3U4@|2X#VLUb^EnCy0RVzTX$KR)2X@me(WQC>o2kRZNK4QxnrEAt2*otrOQyWI zGyXBucQ5t3>ZbnOE2i8kK81D=^bj1X>5Rvxztw46c%1?fJMLJ`%0@9j4FGt7&GY$P zc@mf)DM*LZRT*EOnFRN?VQ5&upenzvdC1dktaF*R_w#SrZS%6UR8y?Dql6Hk&xcFTu#Mb zBbXNE8-k9e+AAOCjN%uTp`6Hj5JZH?}5=P;Y%r=;@&=G?KKPooCey}V?8=FZV^wN36+KC{0~Yf)_S z1;1=>X4}{Z@Oj`qu9n9l`e*bJg;>!w6c5k~Y28 zId|gri!KWAi*Cpe5%!kvXXU$oQ<7#dmBzMYNa!7jnx)}WS{&xdDeGEWuTRqgH?yL$ zmi9Y(pa=aPD|uQ!@I46c;<0I3(iuZjJByat;y(5~V|O^Y>p)REYd_}L4|k1)hSIHB_x*N~m~JN}OtCT%-s!frP__9OS3M{*&q1p z6GnoqwihPuB48F?Ptsppy8SZ#ls##Adt1ZFQ|rNEnQ6>jmSS^zSws1K$i{2vnfS?H zILf8u6H|^j+qEXynnvuHlruiY2;UwsyJS)xZR!8)^Lvv*CiGL$C!~)bi$QSg6A_?z z7%)5i{T^Y`In8hebKpAS0m2!1DusAfrX?g1RO~QSHeShHQADG;3v0ny$4>TxxHyGV zgJajDA&0F+M9Bp10J*>&mtR{GJo~2O&y3fmx34Vy`6-#U{?d|e@n*56VlCHp5U}Yc z-ZfSQ#Uk2!r6R-D+$+WJgH@pcSVF}p8UE$i@Wi90_QqFInQZ6yW&1 zoav7wn!>OM%Kgu{tS;?GRV7?~VwG|wAu9Idnu*0cH5zH3udzXmIOfuU(--;BdED68 zJmtGsowD6MlQUmV%ua&>W{{&z^5Fo=rIZsjik2DWywM!={CJMy5tHWNdF-+1#Yu_l z9UsYtWznLESFY)?J}LN^R$_u|H_duiGZ8*8kJyZ`4e(iNDl!EI%;{A6iFFD(BPOcw z2KYlSFy+!$hj@E|#_yYz>UvD+^_u9@YB!G9-EIvoPTZA}W9yhfk<<-M^V1#Ca5}kU zv8TKF(IpI6?9&th7*zM_!7I~xW5nrlVS3YGppIo4Ew5ZvEAco|oUs_iPxl?!;atbd z^RPkf4NF%ds#Bo`(_o$_3C|rL>5DlN71UL z`E2e$F-bdOXA%6&MjmGoD%Fy=>2lN1u6;_0uunLevQyj0va{}|I?XAyG1CY8(fkjW zcYcw5u>JP&G0;%DO_etXqm2(!uU3bIoG(ye;6V>TZeK}zZfJwhM1k9VFch0v z4Ll<5gUBA^Ab*7QSbA1^`P4*^#|BxgXfG(NVbvRwhjnN_71MJMH*oVkM=KP-M?;Ge ziXA32aL?M`D(-xy+`PjVXwvk!^RP~(^tE}J*bsGrrk-tX{1wq987|q;xjinA*q6&T zBjrmv7R-7lOWF1+U=e$x`z!e?T$W@@(l0vZ6DdP(y%9H`cuQV|CW`q+bIFPY$J#sc z``0cn03$^1d;z~aS$SP^AH?Bpf6~VR%$|pQC70Q9Upj)A=9i5wOk1o@%uHJ}Bn(x# zJuE%;fvBGCPL|*TGJ*8tegyf05c6_)Rn>ROw@CSLZKDel;aYXW^1XU3`!D9L+sl_j z15uiJ`!Q2W%FU)ptJ>(hLK8oUi>A|@j3=qoaWq}br;VB>0FpQzt>MQImtb9h(M zXFq}Zg+%|JFsyFmk=YYufv?2;a3@A&pn^0$nVy?;c<`sKEvt*}>3T|rxl;yREHGWf z%v@BETLsvyKMe#LA!kQGkd@N(j6p~-o0xYtt}#Sv4=I%?sudD0GorSP6KFmy)Rghy z8l}OvXnZ7hs;& zni)+=Q-ys&Y$6{FtSX?YVUvwxHfq}#8dVQ3U+K+92TD>nVD1(&1X@V3Q^DoD-FzZh?Jb}N&M^Z{U&)t5^ zWm}@Q$I~_vZdkdN!NrR#Tdkh@vHTrJcx76%S^dz)S4Sgo>Ai6B%Ri%8vphf8wiNNd zr}&&CMGF0*`xxDSmgw>JM8s>qd3=JVV4}A^LXxy>&t=@2iN#4q9)0`4m=sA2IqSau zl)P|xG383TslZb7=MGTF+U#ld$TG0eB_Js3QWUg5fkq^pqb9M(2VfxTG}zS98w%?U zqnef0*TN~?nHm+xXO2PVJ_VDibD2P6%h&yrPWn@dd!P(`&K5P^0@MHpjg0&XjwaWY;+VUi#Hp_8Cn;Y@HQOlgxgctFzqoYl7akC z(LmAGVb##Cp=!tZp~W02f#|z0&YLkw=pUzF{HClda7!>6t=uJRX%aBe5H`5DA3C$X zqb7-Q9s&r~SDHwz>}9PGbRhVtPVX5T!h|bp9+#$I&)BB$YrnCkTQ6Ho^FB>59sR9o ziSRkAOlo@Q(8&3QypRkEty>_w*^oiyp7`l2qYSp63x1u?g-5~MzA8F)bM-+*)%I0zrOIgics+Al|oA=_U;uo!h z0BtUjZNUL;3R28QAlq>S;|XbKswm7(-`o@xovBnc0b0&v4ni8HirrvNG5;RqX;Vx8 zDacPrYIfbnGoJS?S2OjP1v;HOf4x0`mIGCn{Y#XOY*=*@2W7kCHgv27%Ha)x7At|Y zT1zZA97-*AZsJXz=uk57$)~%oA3$7kapykey=$?Llrj7i+M11LSkY(rU5_E4Rvg`i}wOu60`-s9DAo zwux?(1JU5g(?R#6kUID%fH?d9*fMn~u5rojdMvT<vkhcUJN~2tmm5 zbe-#h`!#s1OeqDH0zjrVc%`c8N{Zw}UI=(BFs$&K1&}FEEE8V8s;0dHe<@$VSL9n=@W(mW5hR zNo6>jMUE(Fc%%5zZ`nrNvb{S5p0Z!^nav~Wb<`u{Fy1FYl#5V4-Kqia0MD=}=3wrJ z!_eH(5DS2$^N{U?jl9I?Itk7g&GNoVZctX*kgrJdSP?(J zq|zmI3^W;-n9jsz;oEyh40KO76HFaQc(M~|=0>Jcr#p7Xm_z{u|apl z#R&dNbb5DXTWM>@-gf)IbO8V$ii!)Q0hQdh8KaV;SS6)T!1N0+7jfqN9qMZs`o9(z1RYd8=t+aMewBybjKtK%{l zW#!rizwR7pA$IH+ogf%m)JjW4=SaoT&;V{Gj5;F1X27GF{=`Z zw%TdAXtUF0?SP?BA{)1VGGQ{e(!2^HprYvx%pzL&^dsb(mDYy8QMB59Zc+PNL$zL= z7?u!c+>gvh+85qM$o5J}PKP*Wy4WD%3>UCz`iqih_N2?kINxY>1u-cpMyrl{;N}>y z0nqU_hCd981#_8UR4YKlpj4PrkO#r};n z8NePN6NFTBdAv4-qnB!UKF2&HhS>5###)Ek>VSpb3%t7fe#vDShBoiOhSpPlcpj`w zKIbfEeXt6tYG@~Fr|H5GkOcvZdrF6_mGI_MW=OeZKdC2-5hQ)*?<`$2e@n=B3p8eS zO|^c3O0Kp^2|VW%waV3g>G3lh#a%QPZ#8nFqhNBn#O9(Ri595uR2o?|XJ3|{YJw*n zc*q5%n}(vLO5`y`MCMxR9tC({LWwE+ur_LWpeZ&Ch1t1k=;;n^ydRc=;twUZ0E~Lk zI}Y;<*OnG9ox8QwIv6cx=EN76U94O&_yMCdV?HxGt>~1EHaYMy=UgdzK2kCJ4UuKEo9*R9mV0B7o3l(C+Mw=| zL>m#!T7Wxn>C2g#ld`vW?+$LV(bL5OybwhN<|c{os)VF+xNmx0CL9dh9^E!P{E=T2 z`MvpOK*F(xN$Xc7K#7efK2p%&-R&1NamvLzOl=iCufA33=5s0aI6Fh<7sT#8idM6i zDOwTOv+pxm^bMj`N{4PYR=Va4U_3^|YnFrqNe49_2ibAu1z3Q!je*UB{zgmElx0U~ zdT3201Z6WNAWmno-bzZj zW<&McX;C~Xr%=5&7JQ^6`0tp6q(8BybUzL_|C84@*Q3t-us)t-NPy!1@6C)f&_lP-a6-QBpjZWTuZQ(oEOF5-2PxjNU z6G{90<{7^`P}&ZBGg-lRLRr^Zt9j3~t|;xv`W;NHO1(7+N{S*J_1 zi_GPL+m^g0l}KLOS^7&Vy|$&s>1JNLyLYq;(h#G?!+cf97G}N^-YsOCxb$nwX})@j zR=m1H6bZuJYSJ%Q?zkxa^ijwF>IJW;^5I8xq@#bLCrHi{Ss-7`!MYLpFzA_|%s($oTF|fMI~`{LbxV4BQZ@W`EuljHGG_50zOet<4b6U4^JW)N!VlWAJcVf~k( zsGs3u4u|Tv8M|GJrCq*fd<=~Wq$NsI>iZeJiX80&3#+A39AkoVWkpX6X;n>B*wcN< zSH9H6s`XXiU)ns_l6I5gbw|Rqy@3Yw;*hT;Aq}F4sMwg=*eKKTkqX%i#zUn@>5fDT zP^Y;4epOgu4q1|AnHwVB=yOE(S0z`Cdq*>nlS+ zhvhtd+CxhTl^bFA?Kd-riBAvC#J?1hHiHS~72WBRrD4_{huIhxZ-}U$)oh6uZ9a<$-voBo(}WT)cbE(kOY_JW&Z`CihB+2L}+&xHrV zg*}9&;wfW#qJjiaZoR@110Nok;>jSOm>Z{BGVHSy<}X+aH-! znp9Ub+KB1I@f1w>0#*Z4Pwr5IZh>tXXWQ?s5cf7;lTl&src6y5IPQ`h8FRk0(^A$6 znH0HbZcEN% zq#qNB*NSzog|_BQN!fX*sEF&3yM|qYHnB?rXrYXt^wMG4gQ6~vACEl>@2nYJh1UL} z6ENea(Syd3KVw_{i>L_(4TCsIZKkl+xt62sqo%qKGn3OR&ns*n2)6As7A|hj9b}#K zD06=-Wfz7Nvtzww11(1BMF{Hf=Ag0$Xy!nP7)!CT2Bc1T#zsXMPdMsOGNJDdL-evXcvk?y-j;uS4 zNy8%Ua!-UwK4{~;JED*k=h$$M`_+z*l%QWZ^zm&L?RB-l4X+Zk$&FVT@D%>Rv80LW zng)EueiZ?(59~%3%jVMh(>m=66S})#JG|$r#a90pt(Y^Wk#O;Hs)J7BkWZrqN@w=? zI<#!&a&jK;4y#=2Qb^EUIf-a4SfKX0*$Y6~K76r6ZB2poIIKaw#-t{@YtVBFin(Nb z?3#UGl6@RD!n0Jf(x7R%QIrOde?>|8q7@sdLOE|QJ}RLQrgcN|V|AL@)>xc^#>KGi zrxO|6?+T7!^r2t+(fkHCo{o-Vu8KHObd{4P$D*PL=D56dDX<<*eG~P zctp4iXoHUM${e%%=F@ckL~=OX&Sx$xMit2 zAkwy~Z6nvr#wrAY2l^vKyL?0OqMnrm!ERCU={^J9k*v|eq z8^6(jvCpiw(0Ucc{3HPw!*c;;sN_JPXp|UCAlzYUpZtVtuL$(nknvigY8*X>W>8z# zf^??~1&KTgu0zIQg`>?HW4a!zfG)q#oo%Ipv9vU#A$C4FOO0l8+pYV4)JFjZQ&%ID z?CXy~`By){Xov(hPYy6v$@osP=$#RPde3ix9evOAWS>=a)wU&b~_X9lv5wHYTg+MSHY}>DiAh`-}fAFd5zKG#|2%8c9uo!0Rk+liCjIO#_Vrw zO>NTj066X3NBc=hiu6z@OrthK#JOX4QnjSxsox)+oSpBl#y`_S&QL`hPI9$6q7HWR zPUXif>zc^LpCf-imtOcs+urboq?+*yo46$heCS4k(z`$Nj&xW`}05$Wta-7>?S4e4qta zCO)D(O%5-%>IrSJH}|x#dD(|bYaG5b)cZyE#{F!d_@rDTjrm_*OYa{q^<@2RRBLfF zMEZ#PjElB4JY-B$uI19gLTGYw%+9T6JQ~Merw+Bv9Mu%2mLVQ~* zn?!>%+5}}xGgW>#>hNL;nJcQRb^IPp(%R@BC=sO-1={3Y(LeAY@=@+XXBND_pX$Hz zcO{s0Mz42lFlivML)-3eO#9Y84N!mr-u=ji13t~CO(Xw#9^Y~N%h50X-#l{_|8nM1 zX_nMFTYSa@`_Gn?a(b1INo&jVe`H8e%TK8^LwITTFNVZVGuqfzqZ2L~D(B^YFeJXC zTbf)^Kga&nj`V-geV^SLq8U>CzZjCO`j?Ysc3Y)h$rdzcgcOE7g(8@AT^3{jRI`J9O!H#D~p2 zR4R%-Sy*Vk{hbCV{<>>T?2k5rl>vL1%+|NCDr%~_I7f6<-arJ>=P=Qi7z<0G$8 zXi&CrwTi48K0f6R)9rq_hDn45A1kteF)})?HTQDg)xUP1Qok7&y&sZIzm?OU_is_@ zKiHDbzZoszpMmGMz5Fwl{`LX?o*(@7YyZsT{)5f@r$p{|{P|~c`a7ond&2!YPx$8@ z;&(px@0Y#bKH|5J_>Y(J-#+5EkNA%Tq2E5@{~RCjyK?ut9{FFQ%G$pyZ9FWAZBVK7 z{t@T&xkc19P?(|glHlvxbgFRiuZnVyzwb#tX3V=bW$5EQS%h$rNxV%H7%G&*e>g9! z+zPwRp*72}m7z6n_i^SIokn;x?PtX4=IArg{`^(ddrF#o^_irpkO;ATr`x_WU5Ki0 z)6d|IPK-I9&lwms*U&U}2w2A_Y3lcg-#-5=JNNDJ{qwx{&p*0A{NDh^GynNa<=DWc z*JB6#i|+NvLbgSaxOXa1;QYO9$2V|$MU|dczR#bD{P~OSgg?k(SHWZEpuPAP9q0RV zXV)7lkGOC?$0S<8FY(bIG?MAm*eMeje@dZM6gx!dXmh6CYiBVSn=>kH=5&sgE~-U| z)=hq3f%!!j4vwP4(`n6e(=aXhWfs5ank2QT?R0!wNmEhZN6MmR*z-;tpD|N)H=36{ zMw&MhjLu~Ky7c=k{QeYvpM~ER@!K!__Kv?}#P3M?J74&nHT^HgflhHkR(0F!GOFh-`V+%+pG4KjXhN>Ypipo8t|Z5?{~a%Sxfohp!SPV;W?k{;FbXUdJ> zO?!y|0{cLPbCTw6kFx&QX|Z3aT!+=8OI_Q|WP?(w^NA^iqeJUbxZ)s@wIQM9C>e2O zG-E(h9ZP6>8=G|I%v7D!`|J{suI)5e3zBj(+=)67@snV+Qgh^;G^;W{3=IgmQ;)43 zx!as9=MVKmzsq+Q{99^UF1Pl|Uz+>xuQ0O)qgu}xx6aB)d914+A;haW*E1KlXFq=W zaB6Vl8LKn=FFN=I+WiRmiw;}a@sI{snAkd?9r9N;tzh>X!KPnS;Xi|mer#{gy!kAg znYa4uC_d zXCbR=i!S`ATP-ySb#qH|x{io^b#C}Xn55>z9voyqxqxe|Sqr+kBS`~PSbK_n0yu{I z)(KeBv@MFBsr!(aUpL)Z(_)p6dNsogJJ!0|e;RjoyJ>X8D`W4ZQtg{Q>UEPtbEj}N z@8u5e1^>TYpTzadA|8v08Kn->bnbKN>P!GDO*E!~!lA?j_gj)2Fa%_0Y!cZ!oIYvx z|N8HWCOvhcjaP1Kns6!MLRoNLYv|PC^9X-uv}1k7B<*pvg6@3fk)@||J69R&e@pjC zY{@Ni0!FkeJ9E5t!h9`?3Qg|g?)h{xnXAw@a35O={I`FYHEz-d+CHtDZ{}$`x`X%f z;%+zBRwX+d7)&H^+@Pa}-@M|bOMeJ3O{T7kfLjz)0S*+;T{g1HgHk*xy;;bzmf{nO z@lwBE(*FVaX+Y3jdSSaz^Fb*p^;w-y#zU1ydRkz>jtFi)2br}v|BG%A(aeLBY%dl# zh;P_kppnl8VJAwes?O0g$mC1gPg|o2C2PdgsEGZR5>WFoALLN!(a{Lf@MCPlEANR882-H!_}eQF~wnSf|L}GR8JOG)5V-gmOj=$ zvfoU_cpO^FlX4EBm4-IJ=^AK=aG08KCSsNzJEquOF&0FI-q?ZgFaiF%K*>cfuBJR# z$*QV42RBZflaxW?NmR!nBU|D3{1=+FeUp9L8K(_tQ}w+xV2Y@8qaR38c*J2Luvz{a zt~Us{HT}-F+|$x=x`ih{&q+;AhN1Ms`|4^LIGO@3FNYM$f6hu-)?J6^kOy!Fip>uk z3*Y~nKt@OHn4~1`RJt|gR>#rVC}~6Kk)oLPfcQm~K0uDlvrt~Wo5taT>6YVwQ*z~Z zlkj-Sy}%RhQ>IL(|B1E-$tOGnH6C2m{e=t-kwQJCJal`_+RE6;x?Rw~eo0WWP?>H{ zJQw@^v@qM!;EWwAts`=}*4I_G4^V-fWYYv=C-794347w(mS-~gW0Jy@i}|zI39onnA{F&FiB~^)l6Y?DkCmek5_{b46$OCLS3j(BUZi_- zm04K`UvdcqVh(Vl7cE0^bnq$+HnKr{U?nzFlky~2eTh`NeI3SL{+yooBKrL*t6gfN zAc$Is(zb;|mcd8`($nfor%*k%iN=sYOl%wG7-CxNh!b`loO<$}cVkxnxOwwr4g4lx z@#g`kL%vk(W0Foa;B$?5aEmvAAHbO{wT~uI@rU7r6fo{cFr} zz4PKCPP|jCHw!ZNle_g?$MU4kGHJkLsCZe~`P25uOouMAAQg)xWR1CbkJ5r>;ejdo zl#scCm-Z3xB8Ou*5ZBK?;pAYholnJG{yCp4D`~TR5{@j+L3+L%5W+RjE}jMsZg#c* z$4Z+VOvAxwU=E8kuHAO3tBW7x|CAL__3@$oA01ZD(>`zLFj|Yig7BRxT3-~^G%cm# z#}2Vb(g6Cejy^V{8c+1s=b>xj9ZEo`(Eor2wJ9 zAVIYQv?(VH4(h+VwrzbVW2oOl8TL zm?XOKn4Yjz2CdZ~BL=EX?!CY4Ep-R`BCPBkyIQbuAzWAa@_XmBb-I%5Igpg!xQE%@ zB|*-O9`Yrt*fv!uWQC25t<8kPXXJIAz~=&&TgB_{D+^rnr7_~beOI&VT$&w(M?x`q z2J7S5&PA0x6=#8g_1j^U{Pyn)l1oagmx-?VWveWQ7VP%`zUpuLz6}`2oIL+fq5zUI zbm%TyM`n$OATO)JAN@D>-aD-6_e&d$Vnan#ItVCTs`L&vN{9jJB@~q+A%sW`NQsJo zbm?D1lP)DhAP@;9N)-^0E&+mobOMALs&9TXJF`3AnYnh~-I?opch`R@S3WtP=Q+>0 z@8_KRwlg#sn7$MrFa=`fkjgx?u(b5FN(bhef5K<3>XdhI_?@tZ%ze>dh}lx>@annT zut#yJ8P=Fg#23FRB$Cpj4c zm0w++KpYQ7S>6XE7KF^>U-ICPvX|~I5%`Pnm*LvFha&vo!W+Ch@HOy*p3NJ zV~qae+g$kPjoFUD1<(;o9vQ`(d=geWvYXad@*lswbt|ep!)H4OCT-q;-2ltbIK>B<4WbM5#u_l9 z^Q*Nw$FhEV9Opd>5Kr*+mTC1#4xyGxK6Vz9c73=^k3Jy~_%2D}L*gTb68)E-A2D)$ z;rgP8vGGWrHG~w7j5{)xB$z@p!D_Ewy--DQ(aPJu@bL@=85P^u+gXq9J;rR&hJpFg z%iOO`IvK}jVg?P|F5TRQ2G8m$H`Y`lRxP=hW41t8+C6d`P#RwUfb+-r-8`35Qc4a& zS2l7uzo`Cv*$or>H0YDHs2Y?Mbr_Ij$1Na(MwiwULrUPl(S0x6fjr>QAZkgyZjza% z-eR*Ffe>sV)ugfElLT*&j!in`Kw>86Cb;D)&O+VInkQ!wIuh26J;R6+n{5!-uSy)2 zxa^1Zog=`UQ6u2hRLp#=<3Rl#$DB$3K+Eu+jRosFWrRCB)}pcsF9Dkx)M%=nGVGU2jc;s z-m|bIYb&>_&=KyM17Uoe)z@*q^p`h{6TZe|yFIh*GkGo==+IH!e}L;hbbl4{D+B2^ z8D)e`vQ*!{&3YoebZI{%w9tN;yShE0kfiI3hQ}PR`l>tx9-ihkSt5ak=!vu~30mDp zU;b>-Pk87=dOrR0YMsz=X`b_=xWxNHKRQxlNy?m$m@ma>QrlUj9J!>> z;OC0IG}#W7j@H$5qak(eR&KL%Vhp{jjRMe`#v4iZ)U-;aaLON{Rm)fOu2ka*@67We zi2-w0gTA)S#(aXgJi=fK#uGPZ!JXvPKoUjWr&im$J3oEHB&am-`C>3{Px|py z&5OPHkoMwxlIV>7FRqV7%+dNOB%SeEz=zn)L{$?t>U{_KN(wy(dn{mo1Ck_=4Ldy1 zQShxGqNWdB?#*G`z2f`@z85Zq7#)MFA9jGmPgm%PN?Dor6%VW-hq2pb%4& z4%C5(4BAI37v)5j2YJyzQ^YG1{tz2#V;=m2P5Yd!UCJQ2X`=Dl$laSVL*Pn7`1j81 z(EDX!RyQx^N7;@K8&csmJ(RYQhmanF{kHR9>&3iEM5whBrT~8FEJmeu~pp91gVZ6M1oNr*YAk!#&|G z%0C^OLYB4J)ah_P`q5~uEdiQ99)R`y63`j8&eD+un~7jy^5P~GD64o&pYp=ir#iK1X5f&m==4OjXZ^UTTJr%^c27ZRaUu=tIPr~Q>5uvcQX%u1Ip)r z19X75IX*B*90cC`hr`}$7qK1mQX0HR%~M9*}udH?Vpc$TUet8c1o_TSr{>F?*$$MwHMRc)z%%q7OTtLmVU6rT zAgWfRN~m?ehW3X^(u1$%f@le-kgoXW(C~-P?woA^1V!Y843mWk5mUs7_y~&VNV%c| z!=hSSsoyWm&*80kLaJ46%=O5=yw9g9GbiY*$G-ee;Fx5W$X%TIv89g)? zQTD@X^@@&$Tu|A|cj++Qjt-%#JbW)0#>E&~h^~`wNbOCCS7cS{@ykDHRn|3>gj>QfuK2kC8JhQWAu^!v=wcV`f=}0 zY*E*yUl7^;sIF!+W(Ez|i$0c5JN{sKY_Y&F9&(MY82A17bJ{Wc{GkASK0ml%2i0_A z2U~fR?MCS(X`$r(4tLrnp99uDFq|I^!^b!=e;!nrHPb3&yq2)t+7`SXEXL4Igl3P< z0FT}u^1uokCV$jh<|(9c>->s2)=zk~7UgXE4N-CD@uu_%-k}#-p0t|>sv+GDS8zv2 z9qQB19duDJ`KAHAr`Uyl7&kWMS~+8!tI)w6=8G?_(@worPpJNjVTDMK%c(}rL#}A+ z&?$U4s$zP`Mzr3cW_%)`?ba9V5&Z+t27;sNd^NxaFSUc^Y-33o*qXD{iq(j^y+1vv zHAX|n;3?) zXV+q)ZB9vsJzP^Yz~5JAGi}uiTs^N8_U2 z(9kKoFu4M!PYqgqG!=^cWq%K<8fBCaK3x#sIchr24LBUHr%g(~qcZH=8&Ken-u2_V z@Npd<2H#GXk})59lqTULSQmB3Xf8PB!RR&h=KPBnnA+P~pO4MN_ksG_8?7OGzmbzyHp2Tv@}R zbA9*DpoaRC`UT!ctw+_Kio7 ze*;bw!w&c0AvO5BZsn*l&x3=Q{Wo0&3rOP3&zr zx9&y%74(<2#=HB0LXWQ}zt)xH%sQdbD&rT+gAp|LmXU!;r{jw2T+zmUqdyihl1t5y z!w;d_+AgU_{5Z>DQaM6)AA@b)rFKs*g`6Y~YDi{rR2=Z7z~9?;@z(9_rknjJ3y8X_ z{2Hk?&fD7e3(<=MUC+hbbQ9SWUk2HX9ns zYCt-O$+O(wYt4Zgo0*#FK5SDMtGQ)-LiGk^Tj-l#Ra@DE@?R0MSVPXO0q8UYfn>Ys zKJd`C--vRj1K(8_)CJ0SRw=rdDlviEb0pyMDeQQYS>R1LE1fbqy3wx)H)-=8Ov0Sj@m zxso}5Y87KvD|}iCqmZ>THw#4?P*bo4vwfU~e0_BN_0<6T0dU>Q1a8e0EBL*hpFeW@ zf&8AN~2TiC>AsuGNcCg+9MWVVcW zmK(2qq-qg!48rNGI-a{NEua8gjLIDw+mq#z%=7=1b;E}b9%Xd(Ea|g(M>DAj7+ATJ zNZLt8KQyW`>yIV(lY33YTAQxsr+Y;Ru{2U+$I&5PX+7d2!`%dYSWeaYPOM~&a)`h! zl|4I{)hs$T7=yUu33ZGOPMYftVutGyRVYQ8Z&HI ziM@p#apk!Y$CvA2!$t3dRB4FZ#^@5JC(DMfT2`usp#9NL#>(%^DO^kkUO#NP=na_( zC{cTxdo<6bux}^Dc7Vr!6Z0BKDmJ&*>YI=vc|XTWz(Pn_(ph|!e2g_X91T?-|K`>g z{zIXW?9r-b@8TwD0T``y_2h)Y7u($Y_*yRxu9F!@*|@?*?D&KoqySeBM?$T;^s4HR z!*K1ViptLk8;!jX^(|XW!RV)nKz!U>(bNY;Chaz3f6*pFYTD1SntnlUA2r{$R2KrI z6*?FGqeR0$qKiqqWZuQg@9H@{^h0xB`+lhaUGnyU$bNvbb6~akqA1f*#=wBz2%%;O z6Syc;J?ct}_+sOdB-+BnV)z}4n>=T)lW!};EuA1dQ8gave3cy+6S93S?u6X+E)n?= z#Y7Ja(?#QIUtbUXIt7AqppR+Qs@rs0^DvWAb^{fH+)0Elm&WdXZ?7J3OwnMGiPpL% zOABx#WoVD8xkPyF(4|P^m<3kBGO!MAjVHk+on#2GNBIm!VXl7nS!`Ns=jvVx1y4uy`OMiyN@--p@1afk$k(XtJ37fB*FFxqul7Vti*3D5_wj;KL7r~I zZ{;hF2KGQ<7LUxNGji5AYW0yPC+EOOsbFm3{C6ZJt zH0Awc)^Cx#`0a3XVet7YQrUcR*WLQ2_Hb1-WEjs2l{2OrXIgZ0B7`nXTpb&Jdkhqpt z5Heo5^lofy!OxzbmIjrMos!7ZNt{->m`1v|ERuH0Fa1<1I(t9w%%J&!Hd#h+gPAqQ zoCvjmp`aqei49xP4hZycY)y1D>OzfI!D>^=n)A8knpk!0tlMr<;HT=Hlw-@I@&c-I z3)^5%R$c~I~?UDTck?f*f6)7 z5?rBH6bAy$@-uPuEHN1wlZ5HoA}-S^zZfhE%Id2(IvA^FZob%+slJqiNN7)htqHT2 zD4)w8Y2dRq&_uP+ZI*{aWD#^xN1L=4iW0qi?ZpcNG)D-Y&afRQMYS7FDy1nn0U7q* zEDNR1TGwOZtaRC2k_8$2f!3g_$@PndJ~@h_zX4hk%IZa{qaAC0o(2WLsVDPgd9UFj z*n`>aNIktGoXIawi#c%HSRSZNivdS7Ao6NxuFwCB%_m;;rMpAiI8-m9h0HA*1kBad z;feKX@LUg~D`mJJ6zy6eL~VJq!mwI!Gtliy0R#b;u$MNtVpeRRQ325zGL)^(W9&2y zG&s_zueNhlnqNVOY-da=;F4!ifvF}Qh8u|n;%g~|LBZWLxtiHn8+eMvEzCtJalGMBKtTvp zED)$=F1%h_#CB@3mj8M0=!R;vPk}`>D|)tY&wbF@WFu^rr*KdJtCSp&4Ci>BP%Lx1 zeqH%Xrf7=|6FxfR1TDP<1%My2z>54Y03A-ak>j|-FF7km!u@_3>aJq0~LUq+-$qh><#Kf@9`+vST!F(;PITs;SwmI z_Ru7Z=#M5!JWMnqLES3mR<>kbT%oO546JCoGM^+yl}m=OFOYn?r>}_Qx%CCG+z)`$BiTSwUK`KXE+Nn?wIpplyR0+Rh$M=gi*CsSVB z-bRf0$pCq=*J*I<5;u;@*eVt!|t(!h_tKl=^H zOL-P@L3M3civxt6lAm&ZYXAB0P?Dxy7$hIR6F|+%{0Zw8ZN0oiXpM-hzlS{COmC@w zQjqmtYKllmldI0$?4K4v?GGuz{?w1_68?mYc&W1m@SN1`#e-2-I>o7zw>l4e_A zsT>aaS`Ea&A&k$)hH|{iagkYOx`yt%*W$N6QwN1OXCS+{tQCDrDWTvDC+-a|U@7GsVtWT_FwNYQ|syxlI(1vGtBr}?G zcuMOcFIR{M;oMB4>w~)>I(bMO(ngyw5z9I&sUx0f5wv<_helYt4?wkwwMH!01ZhT7 z5mZ)-0e^AjKH>GR0n@1yBu4DePFZ5;M#Fb&p_bTp&)U%gT&wM@3#*t8kFLQ%Gqga60Gn!;z4EbJv|~V$h_NB>y-9SVOuk>r{D%s98w{A5SZ`mdZlZdv6=fy-ZvuW#)Pkh z5lCSrGrfY9k9SZ?yNc3ylXlO9da-!wFR86iwq(LzRdvjw={#x@=RD3SHTOPwzZXDO zLie(Ci&@SdOU#ZCKP5r8Y!4|IzTz=QgKG&XA}Pi8mPQbJWbDlF_exMfKH)E|n*+Y1 z^=wl|H|m*0cUIG<)MXzBC`TX^LD=d5_+LL$m2@i5qB_DEsZY8#GGFj6;U#UC?tu)| zq5g%Ldo?u}uRZO#`+cC%yBXWj^9|cTJPd*v%2w>R8%nn?#X=_hn~&MU3r<~~kdDo< zT~NB*{Eiz^dwo;d;Qh54aQ*Fz8F_KEGV!*p5<`iZlr-97i4eItV)B#r*U7aXsm1js z$=Jhw5K4dfHvmy3W3sMPoP(nts`V8N_`*R=9G*tLh(>;#gT$R*xB)&qzXmO#=P*@h z-P6BlZ6sV}=!Hk(f@9`c!%qW> z*)&W0vqLx#%ar;u+;BKpWcmx%!(Ne{n(TXK+E>8+YtHeGa^`22%jvOZ)zNryyS-|t zk8Rxo)|V(#SIE8OqnWomU})4yB16&oIX@~Q-7(>86KTO_FYrZib1wp!s z5G_fS2F#ticbt;0DmgdvxwZvXw5q9>dO-^I);h+f!uEpdmQ^$b!@Vc%VS8TIpe}1` zP2~Zw3f!?dOLRyte6n?C_Y4VfesqjPCexlA*ryxTlS00Ce$>apy^~l1%3o)OUOdlM zif(w`Bi-+9DCJ6lOGzb~%)z0AhT%@Magm|8))L((BxJLC#JtO?4pzN-w9^Ipi#7(f zv)k4*uv5PKX3XBmxw2pV)oPLfzvpj&eu7_Yo!1*4rijPJHUn0Xt=4#_I-SBj#|gW@ zUQnZXAIqtuOipE=^2v1D8m~sY&8YgCRMzngnHSPqz2QV=?tx~paL`}ER7qtu1wzb- z*i|D5iqeO^ZqI98l}|L=T>&fN`KFn9Ht2)%yydlfj-@N4IZK%CzPci|rKF3pS*O|1 z6JRGgdQjdq4P3@#9vCq}tdw6fM{U)uT@6y7CR!TrnYr8J>4EqndW9^7`vrs$=IRR&xPb*q=F|~S z3qIs(zxEW<0M>m?H(|OoQ0b|&Qf0%Ty_t*q+sezaxYVWB^RHlB-YVWk^vAbH=Hs!QmYrQpWK(ctn(gO2iaM9v2vUbUGA!>B1ce}0QTNu$?mm}+(Ft@P+K z4YmG*kT&B%p2)$-DuIZDA7muJw?$;eTGc5#eW5*%AFEN4WTCGIc3)AXV^X3Pm2*k;WU`GVarOu@NEh79vV)IwZ7f%5 zbT!+vjzHRVXCNtM8m8=Z-o7HaS?u+x@Vg`P8`E%W=Uc&<@5OTEN^!a6-@B4}4X^qe znp4%hVp2zv40nmGYX=>rTh*yiR3?LbG%X-09wJd{GY0jq+f70mu6cjiSh}kHMVlEo z)$K<*XpYouERrI>(@@&!Ni}Jbl@|lDjjdM7pOj5x1Z=4W+EiiAIxW^Y)TJoHTvy9h z>v6&NN2*>IH%wScsfTPregnq3*3=z178(`Pn+UP9N2~8jm({@CHKm2k`HQAD#CM46 z2}v+p1G`Ly>kJ68U^bnnRUcoAKc+k<@qZf{H}-I?6|vJIH80i)udze z^6kf#pSfnSG~gQt^OG(JHoougVEa`n;&k_&Bv;J~Mq^)9URB+!w~4O|db-SArs^sQ znbn?Nb~h6Ze6do{AYa;e=atZTL)o|DVAZ~2VYr(J9;gCJ*%Os^@LlOo*?xdFo((gA zPENc6FHA}fKzH3VdeckNWI+7-He>#8+$=W7+@71+U%7%!qq`w?vvo>;25iPmSu*u# zB)r_%o=cybORGkvknx*qm?K2_w8dATzW)P`wD zu+6l3y0H)3J^zM@(s+@Z6yY|u&+C%g4Cu#TfdR~_coP-b1fT4O>uMz|U2-dfnML<) zi0$ioTH2SQjXF(;#tSl%7`hJFX`QKHs0=2^T?TotpnKA3PSYbK?$0x!W&n*xr+TP`P&+ zVer>$tvhkD?9}Q{Vwb?)W-(c321gomuzEd7#L~H8DTkG67<7oSO{GYc-VEApjc_Ha z1wia!Yio$^a(G%qbv8{$;|A=f5%a{NT0P&TAt@fUAj0El|^Pq+FB6v;~Yckq76IdaiLq*RYIucr|*xDwVyIHc(~#i6Mr#EpObpW zBQ=~Q(x3SpO5%u+PIF*Q>O=5AGNooV_L`w^Te@PZ8V+rD40u`-9ng+tlCicti3rf2g+MesIMfpe^_zp?=!X0!+ z-q-ixI^MrhJ-tn^yJ0F+r*D;Ly151Ad2va;ph1jSpk&gWv~BbXXl@3KV}zdT~}92Z=qKn@pen~5B|st6mqpW zgBQ!?4L!}~hhUHocgs9iD{&BOpl*lTE6;A(Yxp&^R#1ks8Qv}FXx90b!M{;jYBPB$ z&G6{g7<8i7xoF8oHx#Rf`l)HKUH-l%8XRGaLvKs^JpI)4MMze9&fkj<^k^*qc8S$% zVK?Z8F3YfGygIEWmM(1H;F19u1$Pz>0Mmv|i*je_a5~N6X!eNgw2Iv^d1YYy#6Pf! ztTLn^g}l?RV5i2<*o6%kSj79`LwLe>dRM;li<8g9P349I@$b%_nrh<+JpEx)7}#rX z|I}p-EAL56oRHozx+EPmh5ZLMY-v>Tb7F*Gxr;ei!d69_7_+-q(x7GO}+!C zHFX1lhYD%UbnDEMC5zOP+y`5vHlcQ_b zNmrblO}=pHiSxKVZcBLW9AE|n4p`Q78rmuP1rh3$T}Tg7#~nM)jGGN%8 zs(-13hMKO&eMn37 zMTU`7tVJ1l)cF-1MRc#-I{oJ7h%MS`QSG?|P?sdM_jBfHW#wEIVY$3WQ8?(Lxz1W3 zrl_ITDIYUp$&VZWE5vn8Z7gvcwWd$pWxn#|!}t;@Kec9uRG#;gx096*B6+3r!&H25 z5z-JAM}VDmU6wEcZ_j7qf`>8*{zusM26CjJK86#gF2+p1jhS-t z=QkV1nXSi$)ubcXleBUrJrcD09bJt%zo@%h)BoZh6T6IyT4-r>`;o>R+wrNosE!VB zQVRUGA+1{jiLpa!j8HcI0PQ(Km0Qme$(^z$0mBs10t3t1pJl0j7asBjIh=xw<&PMQ z@F4ElvQ+FbJ*#!d1bTjYJ1Hxwp;vcN$H0Mmw#r8RL*1u6RbiS4fg{{F#pW{lXe@a( zTfg>R3g~!(Fj7SxVK+MC9|{_nMx25wtDzzlQDg?9MC3b`5S;=#m=Q4==Xp@t=t^V6Y5`{`{JV%jCdE=bK52qFf5cB zoBTH~9Z|USfG1WNQ*ri6CRSRq=*3LEH>KwjAfL!GAc=Bk)N1KykxTuS)!i#OTy2KS zWGDtQfl(Y<3@n|5D~5dBae&dH*;%6qm?89r< z)Xz5=A5Hk-`=ocEi+oE<8^L>~qZi1}3b^)a>W{{h7m;0!8`Xq8(bx5iN@0bEf1$F%it;ie7U2k(6q z^UZD!8^}d>%w@5|mNghS??PsH82Uf5-*Z6Rfs=0|5R{?L*C} zH3i<~FbgFUTGYPl77||r3j8qUF{-R_#so7Was4cUceC5#l9iE5wTHY#u#D;$3~6M4 zR0cENv`DfE;x4awEi+l2S%*}0I0yQmKY3b1Q#5>gEO70T-v5TvZb1mvpmQzXa)c}q zgs z=Wiac@-M&t2|px*W;`{<*Z-u{r-fxU(gaX)c+>p+*^`AtHIp!28Q|Dq$Sjevycw`I zXBKcRW2uyc`3<0up`r*;jsd;E)m3lA&o!nchf9if;;3+R43Q#P|M9b9|JZ>uO@iw?m{M0mkfI;c6H0Qym5KvWUwK* zTz+=MDX9`j>P<89qb}B4=Gxg}-~3un3->)&FCh}2o3}WuB)7O>YpoaPvup9a#hg?B z@so>I7B@b(f0IWOGM8ceuIbA~RR(G>p8{BUq{49Q^ zP1gsx!?S0^>RG1jK%jN_81zc48l7hV$=gXy<2LWPoAYVhn+;Df_pVY^XXL)C(f_Kn zWG4aEskDn7RUYW5lbA@cPkc5x+O4S!4=jb-j5H>K?9ze@Xm@-xk<-!%Q}N7F;bDPA zR$T}vOoL=shS%!_o(G>#VoA|QDmWs~>vy|k6d4)^ix$=lq%wni8n#C3%FFuu!t{Z@ zq2SduBy6(0uHpHzlPgWHi7*tN<3l1xCHw%puYXKxvnl^n=^-c%U(L1pEU2yIrRI1M zrkf|G(uGairgvy%2N=l3E$+fLCiesLI=A9aE}GB+n?kr9PJ`TQ$TFGRFyDTsnmE@x z^&6vOkF0ZKallXP;IhjZ*GzKO%G9%p?@VaV?|2$6ZqF_4!Y~nUpa#UMWnmafq6A&F z5xYf}s6e)+ZYG+ zVCyJcGG=`vpD;RRkvP0$zY*+HGi*4lKmq&mKDDp@uDEwB2U)5FKM6HV1uLzxx`2G; zKC(xJkA8HPlUxEZjUJ6gnG|#0H5;iPm^T6`J4-kq!n`(ufI1-bhIoRJd12JMed}K zU0?W@$u^k(hh`T3Cr4yMtA^}4aW{HGl$bSnP8#v6?#P%mi5YTU^R87S;F9+ekDZac zY-5#v1N!b#+c07ziM@h3lvufT2^-9pCrpf3?MGDYDWAt^efUOi;?=dvG=5kz%X*8X z?CI4pwPYP+Ht&Pm&CJBqqmjFW<#Aa@?t^1LFW69?DBQl=6Y2N^>>-sqjL3JA1(z44WIvDIQO{!8b;CLCI1 z*^5;gHi7^}GxZOuOok1Sv4lVh`G_TKz{al2Y|MRYpmwF0G$({aY&-h?+{i82_ zPkA0W`asKgCR;2syE((#%6OO6tPT}jly!`?FHAW)_OL^sR*xY;H46bot(wY)Rw1`+ zX;n?!;W^V>3H*15MvPKjF_cs1PPY4;00mbvj`qE~u-eA&e@4tMP?%SgV!m&uS_&Id zvAHR+9LzGp?z4<% zoDHgrCFpjN^5n#h$MMoINxdDi4F6W}ZD^WaaX|MJk_^BL6l7`t$cS#5WijmuudWOS z_GP_rG1UG70W5O1A{zXupR`1gG5(dsc|Je7<|=~$oA=9CepeNWSZCQRr+fuQ601zM zj3x#;8e}l$eacKu#e?8o!mcT?RbmrKOI&sw(cqs-cevm`(w6$1?+w8r+(U9}Z~E0R zv&c}nx0=CM03*@uUL8X8ypiqTKyrpqLB9t%kn7rL7Vwbq}> zrRh;wEaVTRsqL?R(i;`a{Il9y_VF>29#W=;splwC!_xy_<)pr*%;Wu2EcnGBUyHgg zUUaM_m`mI>u6H!B3NN3OH!rYjP6gH!u-Pe#444#2Tdc9uZZ=`ggY8tiAFnxKxQur+ zMhrVzOE_YahM_9?>0;xD612LXbrTXTsEZ23tJaflmK>hdd2Ykp-Q7_EZ-f7GOGB3p zfTVD_s`iT*A=uli{hZOl1ayp)UatXLv*)_b!iHcN09eN$*hx0Qlr#5Hx#x{5N2sSnT9BAmAKL@aIda&mn9KMW?+J@Eb}; zc}M(OmPvB~{yl3Fvj<~=l!U?Qy}kf0w_By+W8 z%>P_V!Y5fx&X3bCGy^}|Gxlj+qv_pWw~RP7quW2@I;Ct9kf=2O)WzjZeMhXpkxu@zOc-QLx2`ll-U7R=Hb=B9BL06E0_Xzi?%kLh!hePmdJ#JJM#E zqk~RRP1;V-;Uh^ndE?G>*DZjL^g@~7m8h+tyEU&qEtsVeRn9|8Oh56`x1S6|y_Zl;({AzJHT z9SRPttCsY2;fTWKddmE3Gc&9MkS99W| zkbd3?v-5!2Ai6z@z(~Yzz;YY&(Fs?EynmWE{tx!2M(GSeBb(t^uAMv8Z@sXL&CDrj zN7eu23vKZr3CHIec0XN|ykBTouD?ih^f}%XUxvGf zO(gPs6?q$WEklo|=4=7LKRZg>ZEdtfz#!c)o{_eB01WB1!8gSk&fE0|@t%DnI*c_nBGg2+dbsy< zA{F`yK`L!$Tp8BR1OAUf6~UGa!~wD--5-?Ue7?r$k67?Ci!2N zQyy|&OL(RB{p_5~;SGn%wIj~ofOdyN)+N+o=52n@T6EiR6Tq81%GbZ2 zRn1@K)=dhW*7vnD>F=>dSXlKh`MeCNgn>GXS{&p(K? z61ozg)H?R)BFX6ZOzUqz>p#>484+Qq1($x*x{}PXI9&=56eK~1D@sZ9HmwR2)r_tt z2$^!&=fY(lGDXuTUf*9_*hZafEwx)tSl-tkl7>%Lr=svh-K=my0m{V7P|1kvPOI}O zoW{1r1w#}2qcRzkuzb=J(ZYyM%((jvhHy5#8x0kXJBgb5)i{8|;J%%A19m^L|hbkQ6p;q7fx3f>W($h^+{<4j5c{-FcipSq$+B{b8_L-$&?-Zan2(`Ql z${m%uawRIN@|f7&h%H9_J%o4e{J&^#ov>eS3AxZ%{i(8X#0M0u{@S(RRp19ZVO>t~ zPQ!E8-`-gU=Ix2u`GI@ajnj;{ z&HB(+CF4cp6NF72?THRUb&MrMvm9GRffLTdvNW)W<&b0KgzJ{t+TW|4i#dc`wxb@G?Y(hk)tC85}adZt@wCZXL8yu>FP)X_GO!w9H0-=Sre0O?Yk9@_+tA0 ze#$)fQ*8W~)SLe+FT($xbpQXcw0W|j_stu*a9^4d!v*PuFQeKBvlY zVYVrvy=@w!il-8&i?x4cgeaUS`um}GJ-y|aEfqw+NPL|KZGjlj)eAGX`ygvc_Z(J5PP&6^4m6*fqNK3BYfRF!ndD4HveC8;DxKLp98}LdB zM0bKP-gavsUf=n?%D=vj809&RGNY$Vfk7gzmEWRtY=aqoiM~Pp{L`O6{81=5qkXf^ZYTp zdHeCXYMEo%eR+m`VRUuzcu)O%E>#S)*li_xrHV8TS{LP zysJ10EA|zl^Y@aPz<=fKQHL7ZJM`AK+%&r0$iF8|e*;EEkE87Vwu(QYnwx(EoU-?C zBKiM)rObSkh*~HZNBxX8`G?i+zuZP-cWXY6IQK6terLb`23*u)2@<1rr$t~6fz;#n zX8T*it05h*oNQ)$@*5$!JyhPqJ2s^fB7e(6+40 z-vtJXh&2sE)70+X7c#gpmGPtWhdO$ZsrO&unF1)CLv{t-L( zN9q-+p>6yZ5QnfrUis!mj`UW%mZ<)et5eHDOfv>a8s+|@%2;{3xRjKDb9%kt2v&W^Q*IJ z|AW2v4r=Oa+eWcsLj>svsPx`@vjGNv0qH^rs7MJhASLvoC`uJgC=x)Vmk=T)0TPN* z1q6gZkU)a;8hVL<_~m)N?>*;y?>T>*IWzB>Gv{+A|Loa&X78+7Yu)#Kt^2wz|CyvT zqH<|x#ssWih#aZU(6s)YCjJT>3TQI)3Pk@LV!q8W6tBC|-Xhe{qhTJ=kvEgb4HN_?6dQR~wSY z=Fai*L5}uYnYSO|rM}+wiBCFEroB{=_d7!mxc+0NKd_h(bGc6N!-qW8=j#o zX>56g28cv14L`P)QT$f_==n3jR~Gz2P)E*}GSU{XP_QIS5Ns6)bD+vPthmO$T(U}e zurkpz8<|e|t!c18ZeqKC=)92}gA>xczs^1XMfxWhE-S(tENO~cr_zTsmb_iehpt5_ z2ts3#Jw|Ewc^`WV8>h^$3uF~X=UNp>*IIF2q@S1%(v^#rhw#Usw+_MP`N<#pp#TfdsKYhNyjJI5d>4)|T=sd^=mc|X+k=G5% z(`=&m2_$tvNPgmIZwctO7@Oehi&bZAqw9X1y(O4eAz@Q8T*}=Gv9b*GP1r@LW2lqz z6sp4*SS5yUD3z~=>Ic_OLqKk+AP~4Fv6=*YX@wi1x00c}-fy#>THFp)nRfoP{&N3# zk8n;%357NeTArW)Ja+BUS7H%uqVUYqT;dk@RNs`D`?j^bfOPxk<acLLm zL&B#){TCgLCgapFDp1)lPmYlps$j05sSVZE zz5s;NdW^P%v$MSB?|>(FvGCm;yfDo zA9;^S)>hf%7)@b$Mnvh-2T3Lq?{uf#FkDE|WzYkBeGZUl&$CC-{bf%sN%|zV;9=iK zFDrgp4h*rviVKFRYqguf#ie$jKapwiZ2DOsE6MXfyJF#}qz+i8d%eh=BdN_brbe@u zyjo7TI{86Z2lhbo(DM7Cekr5hvT6|d8IQ8jAuzJxAa~N*!_R|>;~*+ChnSimG(7t2p3_r8*@%CufhYK@jHKE*8ulMRd_6ni zU@zOyKBbpPTuN4xR7to+s=BzxTEPmAFyu3u|JkuQP7Rd9J`TM-S;ZDOx8_391LOy% zksR=(d%Z~pn~0$>@^l=)5X+?rex)gq2kxsq3boN3UDFY+5WBqoK-Z;86bgz zrrVJF+0Lcr-g=4cwNjd+ic4*U4Gffu73TR_ScJ%LF~x^nSe9Mba8dCn_(ZH+K>ZpD=Xo~bem-g+PLl%k8NNg|DPaD&o(0ZI`E+EKR;xaYZEyl- zuk6*{z9M%mKFhAuv2lMHaI?L5l)1RwNkAtYGvRn9a;|}uwG#%iwBYgDHDIk-ZzJ>Y zP#Q6b>3&{M(cKc+<+JBXdQ-7CZ<*G4@Ff?HTAKm zsfIL~jo%prKUYMqM4-pXU&ky2t&>a{i$5pbx@@gsnBjD_+CA_DQP6bJp)1_jR`T5a zyVGJha*N%0fF)dbWvHXQ87+0%eLE4a9;tcA$#7er0BpcM#7$?iGtBiAF(!p(1yn}0 z$&fev$2ku1Av>Nni$|^*cReMx_(V$;&OCHd^X?x-H1MpiO0o?-MQ2(?zdW)mR?#*Cvzx0-@ zF2*KeS&|EZoHLOZcw6|gI4-?irYdO$T+Na)gHE;lgZ~<>%_Y;tn>NOGN&HE)5;`7j!YX$M zF&7|oAM*so6bkyolHmv_s*kuBJNa<~%^HE0f$do(QlP)UKexjvYTK%6{iD;9DF)oa zvgFlpYxo6`^OGBGc*h8OgS`H-Gp_zQ7*nu0DZ~2BcJ!=V(6O3rS6MwZs1~};{3Y-2 z_GqNfK%*Y9(L9`6JbpL4Z@ilrwRg6I> zAEU0w3Hcz>)cEQ!*?=P==qx^M?vmf9)R)~CZ{9mwEQ5@JOitC$p6koRA2u{}o3hcY zU?robU1)qg;$Di|89Sdem4f+-@d0FlIRqjC$0^tckkb+~Ha*%z&iDMp3Np|w*7uhJ zeF`Rk&|R?GRkM=lN*2>=h`Y6}{K{V!LeZCu>W9+BASi08 zR7Ty26XH2c4^u;pndDEH?Sd4LpQBD4T?@AuR0rFC7SMB?*@u1O8PNeIeFH}DWekg^ zue85-Z$`*{d%P@i;{=Lq>&n_ADt;CKz7myis2KGVdl_nQdDwgVAj#hJ{n&U@dWaCy zzVU?LSy%D+^A*latP}|=P_wlC{9!{MW)TB!;$yV7Me(ae zaV^MBDsnGfUlO@EZm}C-&Og`FI}1uVHfi7WRX0WJRIr>YyM2Zqu1p4JVE-)=YH#`M zKZ>dUxhL&^qf5`|9ADP9UKOw=6sG3Ge-nG|yGA1p_R zz^=N&*S0fXo!rpc3L$=t2^OhNZHz|Oyt@=0%T2fio5i*Gu3bda^J%od`-W z*^tA_QU7=L(0Z$nD_da$XP4NZ0T1_Wu_A!;O@Xq>wkpNVDl5I2_auUR*qtAUTPsk&6jtmG+kbBoVcZ4}!hby6_>iafFn=)! zl|6O4;EO?$_tkePcPJ<-qF0I|mZl{v5f=LvkS4|r)v|`?i@^QlBgo_9wg}v6#cDww zonJiDeD^m$=g5k{46zqL!iG;Z-2tCZvkS$!%u$8zbe4mlt20ax&CYG*K{93e% z1V3M^99Ld*P#x$zw{%Uk^7hGx2>vTd_X^7}E^byFP-;qfb4DkvVOqGd!HR5Ionl>+ zBh8gdcQvqIGt&G$G>qXl%SU*18C!IrzXI()H(#KKEB<6M_(mBAZFsUHtzuW6HC9g< z22-=Mgl(-^%Hz%>uZwCKS=SKdo?CqNiYU*ww9bm`Nqe&vn1{*Rqaf@NwX%Ly5W>C0 z(!Qrr=Pm6AG=^!!19WP4*VqT$iGS8&o7vSSPD7k853j(5Ld@$B-w1{Y0iHE5Qz@=% zZ{}Avs7|l&?{&}2(lp<@9eY|YZrOIAWZFufe7yrdoEEKnHuM$ zQAj~5axS3>4bseOifeq*A7gmVyGh=QlJ>fYL24mfEQWY{lMT6?yB^oxEBdGRO0`7X{< z1hS-gJxllo+I(pS=kX{;`P8|QA$BG&knJvE9OV%W$I{QAH)MygzED$ z?|PCi$%{?R43#zR-LafmHQ-@%^xw^KAmB-M%rXR9p*BN)B4UNFdHc~UE@0<9)#Q9g zC5PypOXVe>>2S$BWU<^GDVwk^qp|!5!C|BAn)0DWGWKI*%6Q0BO*QnO%X!uCTaEVy zp~`y~nC%l6d0~P*_DFZ#B^oCrFr_czL>PP$@Y|z}VEdssV)m=;NxQ0EuG)*AS@cR` z-MdTrxm#~@6~0Oe&8(|etDpchsHwC#%>`!o8)tHc)o29SK55EoPY`T-a9+Lm@cIV1 zbaE_;%V89fR6I@rPmGNLFpv#rDu|NK%h~#vbUu#9Q07*AWxK&KPNj<4834R55VRo3J#v1U1@71yR9b3VhPz5;auxy7P1eb^K zW!CFqUFhORF`AB~gNrJNFqc%y(gAwH2DQ?!wq6wDGv&jva3oT{A&mUk8m07XX@9v# zD7#c&z~hZJzqQsW{9DzumT04Hr_!oN_1SNjg7B?9%`r_fb?e^6Q~Kxa$>meGBmS_Q z`Q1Y`a@Foz_DIP?o4yxps9HGh>igic6wt>0rc|A-YJXYRIhMVMu%Gmbn4eOI5B8iD z2!JPa?+0XjoG$mYlC0y zrK<_IB2+*;L+Q>5ZK0q=*(cQ@7wDx4FFflqIUW|WhRIC(OR3X8retMfVB3r)LFbXi zY)sf@&o4L6T|d9X>lL#RIEK9%7E0;vrIF1Q>9Wm7ToZ5dfzDI=@)ujpNshzrLpVc@ z#lS#hM3Dq)d~Dq8X{A%#qa^ADxyfOGQ#?5(SLbc9q=$5!V}FL)U^=lWt7{2S-AFId z@gFvF?#Tq&Rt&FJ)H-2n8b>N#MYS8g-U?URn20^()~GG=nix&@2Vqt-!l3>QVu?A8 zcg54crqA}=7Cn1e^eI38T+0-X1ga#pSrIw9k5MdIC`-v!KYcXx=x95KT9FKqw@X}T z5(*bgpHhgK(vK90rCs=b_4^~u(3sjdMFm(u6Y-@R>x=Y{Yp`Od>)Br=L^qkMK?S}}^8VMO;?)a?qSi7b4zpEVfOm;IU($9F}N_jZ|y1bdVc)K)HtHrR9M38 z{_C#je8(Dsly&pmce7~aZF>y~j1IJ+*k=H_pi}%TQgC9C;{I;>{?1sb&!e=XUjZOX zk5h!VZa20%woFZBPuWP-Uw!eRGP%`#+{hHZ!DnJD!*N z@pGR<>mS6ku&|tAIrc_&?Wvk%Ov_-dmDAwMM_C`}1xWAx<)-4UM`fKH&V~0)QcZyc z1c^1Dcd1|xt$!z=P*2C*+Q|rye>Qku?Lf0tok>NY1hWIpQSpW{KYj~~lB>}wXRf{j znpy@WR38!a1y)fIi~#hO+nHXbdqk9r8hH_8J*?J$vyMUEh+ei{KdPc>LnBOXqo(F9 zblj0ekncC;4$bK>n9r5V{3e_sl}$U{c$;@lpIS)8yxi5v;vdjR7q}5k+KZMDra#R? zkaYGBit6nzO6qkSgn7}joku{Lp|yqr1~N2Yl-iN1?=F@5P+N_M0*k@b4N_m|m)i~8 z`1Cm@MOi7&z%S@A0x~%%F4eu3(P2)QyP1Yb=66Po~BFdtq2y zvGdW6A(L+{Po)xkXuISw;>=*cl2t9y($N_bz}&2=DF?EFc7IrEcstNwdwcTK#+CuP z%nOR4S_I`of?N-b>>m(gB=7sFZF|I5Daus?TJ1FDK-|=aE-Hvxs}No67% zn0{AwO`+&aiN zAwty6Cus8fmg$cdk9;mI@9A*o#8jyF-g3D>acZ1xdMExZ33_r>X|q6V#s1-!2P!7k zmR*9hc7Oc}S7xHl!k9tui=rgPWR%>VoQT$DMU|M_%oMY_P2Or5Qyk02k8yJWjC`2C@1V*X~JakmY3aH^1b;HR#BwWsSb>ZUqIW;qcd zNFUTeaUd;8A*~7kr9WN@bHQ~p+X=mE@`mxF;(?i@FlxHG#hVF!cwyDi03)s>1fTwP zNqPJS$Pu!~32u9Sz3#&lg>SY#!-hpHd&ak4+g&0Ta4WC8NoP%9(=b*85~JIt~{cShKg-EqTe3H8{OoVz47x`NcI zI}1>Dj55}Fq5rC&Q?KBf6WR@6eW`^M?dw?KY^HDZs%a^q!HU?FV27kBwK__-1JkB%%TTjU=oM{(K(Sh~4JNAGpH6R`Ux zy=ez+NYj^A2x0>YMy(AVOD)<-NJ^JY%8Kl*SZze_JwaH`RXK|HM#3smjOd%^Kak7xQxKp1#4p1Flk+?tTSC-kQi>e@nY)r8@1{@2C+lcO9#|1G&FEtP}Za&Ta=@q*6Paz zKX7-6Mx26x$(5`bgxkH>IwgDNzyLrO4QS*jP4rIPmz5xS738yf2wk?cKzkXU^9w?n zRR=a^4$C^MM|Jckh_KTGdK6iMzx@C~s)4=_=NBElb0spxx_Mk7>cb6HAfFR+m#U8Y zwRwx7&}I~>DG=<(v3)q$#Uj>N_=lmE4|^#x;};Xof)z1!V-`THt=YvklwJxZ)=iI^KA#w z0@>k8*#AfrWHKFB`mN@F{%M!qBWVt&D5EjdW|hUGCH)v?BM z_p9-jIyqBVVy<#td{^)>T{g(dzi~|=D69)WEn35%2vrniQ*m+m!CILZeDZaQURhVc zj=hB)Z4((8Rski9#O)+mv>AvFE5PN0EHhTU*H$OO(>W`9R7J24pXso$9FJFfc%MBy_8cDI_`+kn~Thcs+4& zwE&;eex3eKGnW;rctJH{F`bi0-UoNKp(o23 zITjx#KaLdKdE@G%>Z8%eaqImcu$PbJ38zkC>AiTaAp?$XbI=EUySsmJs{d0qOL9KR zz^zBl9*X3Kdoa{}N*T9rktkgf>*U-hSn#UTS2s6k?%ANgM>8_>qI|Zt{HC14?I>vz zh-mD_UOO9ayRbmjy2Wb)A&9WZIxVAYd`TzZJJkgYZbQoC-x;*ftsrx>edE4C%K#JK zt0oErJu$bpySvf-{nx+fi;zT&)8 zX#QrSn3r#&kiG_SFDS=IZ7v2AJFF~%;xf@P%K!ixN0Bk5&^DNmztxTxyC(XPP zIW1{N=h7!VTDLy7`m0Z!Oa{kW7~C3r>@QqWs@hVeb8D+0Nr1CncV@y?sxLpmA5!>u zrGkhHE0m5X%Eus}Y0B{^TUWEpG{egy_GNZ8;PP>6d&{Obn|82j?IQ_VMGVF>)aCgh ze?G8$ahKv;j9J(X8kq31`>tmt(=!L|@-8fhmKMs3R&fBFx~-%TkPUFQstNhEQsYEM zfT*MXM6ux-knFjvVOcG7mn0W$QC|q-RyIi2gheU__YH+dlr5q5UhOPX1#bn{$c919 z^e<8FQl3U%ykl|M6r5(Puo=0os#m4tCa0X2RA}epVAHs_ENlx^_r70{?*V^2=0|)w zQGX6H$qz4vo0 zP!&h*Z7W~-bVo_--0`O$(`+VhF#qIE4!HJ)c4hnR+K*>Lw_Ix;h4N zaQ>Z2e_R{Xlr{zRzxpppxXaab!lhH}2}jp9&X8@HK62SA`u4Xg*LS{!-r@bMj>*6A zUFFxFHHQ?>r`#uWnc|rXX5@>=OmCl%1B-*uLB|k-KsvgyeDM3=Wt-_U?cvHP)?pO$ z)dTs}VFY!%3Zzp@Kfht`0fg?6BextM(O zH`+jk;bTiy&(sDC2g8p_8aFnJ;Idp2E7}Ga9+I8YnQV_#_*u!IDIJ>kiFxYs{OS;>B%ZxqVK$2wN z+5>|Xa^x+BrX_p1)uyD?Hi2TYy5dehKE4V|)Oh}~yXoR;+@LMjP)=Ju@8ao#rXWXV z=@(r-ltQ$iM2*qbj?7l&H7CHfHP|EN;1^ck;f)uUTWH+8sE%w%p$p@Ul=`t!FbJf^ z#)OeN9_iJh3mKRJPWwzu%2)fuhsa?6oygnc$b~bx5yOJOEs>S+s9r zCJudqh;O6-X-B)DALqLHS?fUxbS9Dm^q|~Pk^J@4c+N^F34$XA;12+u> zufK9jdt|2;cV5X*DlbWDAj@O-VSf*I)jW=j>8352ZVreFl=idhT%z4eRM@Mr&Bw=6 zpWv1wZsYQF*_THTO zMSyqk!!nZ#i@l|0qjlmnqG8}gh}R$yMl_a&Vc}2i$UKTDzibH?)i@$qrmL(87R*A$ zu##bD5YvkzW?<@S!h?9K)S=uT{PJWn?R@Y9McLXE&Y=GHkKbip7`#k`TffY; zQm@aKlXf!qAXt!*S;=%m_WSC-WxXxfyM!yT-6o$Y34OK#rimf0wMGLWvedER z+PQxUgIf%{5zTf8fJ;$Np2;=PrT-nfVWqgNuPKh5KZ;{LauP84!y;}c;!rrTrM|1W zBJ!W^Sni;hwn0k&5ARqr3+H3Mnc-*w88sWmY-pT88C07!&ndbYd|}3@69>$qU_jyz zOZP6b0kTUi!aY6en|{gx>!A`mop}y-CzGkBOkwiI#RmSzXIL{o@UtPV`8TJ}Ar@kI zh%_NXf(~0pEj~rHvK%oTX}1B*n~hAR!A;=5{}TJ(7yTW&zmwtbI{Lda{M}UlhKaus z_HWMcH{JT1K>p3W|6SDlttS4~M}JGpzs2%joZ&BW@)vaa3#0u-Apc^j|G$BwTd;?h z|FG=V1=_g0tasNsaqxe@--Wv)VwvW`&!eCg`%GEkU*N&!UlPgXgKNK%fAlk<^y5e5 zoNXptzey~N`VS=C)qv@{!w5>JGrQ#Oy!gYSz$W^K1yQo!tMG^AeHi~P`+vbb!(y+^ zzMucLyPAG|bNl0S&;KgA`TtBl|9kc9|JD$oCXNiQ{$YuT%06N8CftsJ$vu?$PG7@f z=7t(>mzwQ@1zXA5&}_$(-y$8SaV)UW&2vG8YbL?>Zi|6#e*ptxb!LUxv4Pu-)a zjXkrvTX4+1<~@re|J%!Wqpx4PPG0JEaJc_0Ec-t?kHZr-BImm|8keG;9ERh6e={Vk zpU&7#QVY*diK=ey{XI#<7D9yxm-d!K&M1UW2#!kb_ILK=jQ1X3MHX{BNEY28K?geF z6I4OM{(wB;_(bW>@MDM0i!T;$9{>KoGDYkEbN~IAdh=oU&7=K4EIOy(oZcjTLA|Qa z3r_o0GrH3&EE`*{Fq`3k;dvTu^+M}Hi#qtnIPcSwrytyk8F&&dk_*IWJX1Sxz@g`c z6b31_$LAIYI10wHPCpdzVDWy!?C0Vx8p2xU?lRF#?oWcg+p*$(x(y>oHN+PBEwur&(#{FmYS{&~V_%k#I2fr+eW~-CQ>& z&~25y>uT$|(afoAJ|QUgy{jjJE}^UUR;L#kIwIp(2yWbPz8^V!SfNwWLD zo{iKRARTD72_!Y__Sd=k%iMVRZYZ4U=|{jlmxb#G7I<9IVJ|#+{$H+b$8w66P?6XR zBLeX5{tK$TUMnAys@mvR68horhYZ_3&Y1eNMfHVY(yzR0cHCD|gnof@kSm@xJddIK zs~MBoyw)41tF>R7k|rUm;x-;q@haxSCv!e>7YeAh*(M2iZ6X1owU0fVYm~OV?91q9 zjIEG#zG7*8^+3P^ZUstqf93qHd~tuav7MZ$jNnr!uJ*fEA^yrZ{${kUj#B^a#Q4F0 zS&Q_HZ~!0_0FJ!Sm+fiicQ0r*FtVAXE~|Q*6*S`d-LV7O<8U!uHs!;Px!ur4P2F-0 z!gzH&lw>;7?L^Fs?_R1%=q#!W{4rXjBCNC;VwDz)LMF-hqcuI-wKYeLG$y(vzN%SVf_%6Z4NX#_hFBVO9DuWS zi?#aC%SelkU$7hM_O8&Ofn$5t4Dk=dqfk_*as_>tFRh~sJo#-IWfK4(l)pmoek z^~`=NE4P2wf3e|>Hb!PJ^-PEV000~c#`dae*~S3+vYbCb3?-)d6%W$@hxB@(oY)%J zt!ZHGr-lQIF*@5$4SA#CZO<7Q&9gT~524RMVppEs&?>!GdP)KAZHKfl&TIzm8=&Bv zSaWl|io=m=M{MB8uxIVk@D6T;UV9()Z>GlSlaxa{)Hsu|NE|EdPObu1p4NSR#0>Xt zuOEc&7Q+-Q)Uz|1?|x*4S5_6KOxq4_B?{+r~lA%(?vC6l58xh zBS#|Nr?Astxr^?&sq`_`^My1LgJM?DAUwrP%9l7FY0Py2QR> zHi4_BvR@kp2!Kj(yQw26^O1w^u(0ik`7#YPx-rSFI{v7`I1Hj%(*P5E%y~xU^Cds_ zlh%+;&srF13~oWd*t+TMX3FKC9k^+SBO%Dd zCAImDEPLc)=Ra=&m(_=~w;r0n&ul7Ow7s8o{6@PBQw@Y(x-9JMa{%|IH>NvNO>Dzh zd#r)!eWuHUi|8PNT7X5;#JO-l!Gg|e%rx{oRnn2n{(8mxD(%jG>_uRc#;glR{jXX`RZeR5_ zr5xJz6CZGpECh1I(K`}O z<^kxF)_n3;`F})3a8TMfh3@ic7X!oYcRw9AW?H)kkw#1whh!q>-&vT$8n%5lEu8U> zpe`JGk{^SkM_LFmbP{x{Rj6fj6f$C;_)fRRbCb{Yp+K4mOZ|yigIB4BwB8n7w4xYo zBrITUPWx!}oZl#o7Kq!PFvB+T4~9E2LPQcKJ||86i`SX)Sc#8^5*XWeeJiOhOESe< z@8jdm6TgU&u)4Vvk($I}AuHg12@z1(km8)2wi~K%B30LA?C3n9;PdJaOHX7vZoAUC zXPWn!&zi#af+Egn2(wZ!B+xy5d+0$1ePBRnI_W3dRkrKLFJ0ccC_P3^A;?P3_J%>` zJt`;$ZFH&j)iobo*=EA>8u%-6+NITGeYbGRcj~Nhx@$?)<8MjDU`$tI%coj1SKe%~ zIyYSoe!|9=FN*M+YyDv$5M^(yRt`()J5X}$wj6DjSS!Rr!Hw#K+Ay?t#Q`=+gbfy8 z!OnOV99L1U-g@;@@;{Y?#`-#C{HQPN0!(RhY!)e{SKUh2v-ZUqS)ffFz3RajS&TM# zID2I+|IERFKS;8BEq`u=T0N3!Qi#p}K7yPwc`3S~60Gl2F}HE-K0lovuv|ZQOyeJS z2P@Sppl6cvZa*In@YUCg?}99b#U-$~6%vWCDk+xFZ&-r_uZ#i4;AK$f{z|KnspjVu zhc_XUQFOsEnAc*_{p&+&=rOgdmc-2`Y4=kFy<|1nzCX6}z&BBUgQUo*o1-+P>g9NC zx6to~HS2r6x5vcd{meNM5MKM@9=#Kj4E%^~mCxfZvb`h_W`_ja88as=Sf@|twESq$ zEMlOKI6aX6G!xTWXy+pgRzaQh3BGBU-75uSf?Jf~o?mVh;91qo#(jx{W*G)qrK8;k zQpNeOQGLOt=%m@+-(+Od8#-849|W~Y!+2FBX&*6j!uW`DG&cAelU|)a^rX2;t^$4v zMK-1&y`weH3ksi5KJj9~>vvYFgC&%fgk{bZFdZw4Z{({-6qN-8?d-vNi}t}TKtcRm zZ9;g^$NMnlfkvrVB8vsL3M$b};T?{SsmH>Io5WCqZ*^a~E#qnSwPuu&iCUFr zXvG{3^UWTQA9>5WDVgMEp)8<5X%&_E%&nz==422?lGWUtlM0#GRCzgkx75U=R3C7Y znT-0gOmltm1(}Q<~Q|uA`RBQBWWX>O%o%<0hjl< zoNBCKiW<16*UO`64eC>1k@kK0;#jrwNZ&%InuIGDLF4#V!G9t(?D zj#qrDsOiN5Dq=YOjA=p2)e2hd*7@W&F6Td1tykpo#-Vm6+R|R!BN?YY42lxleffO% z)f+x){%g69-IMn?kEvG|Y7Ga7VZ_}Jn48C%TbM3**#nk=LOk7#qk^&aLIP$%-uR|v zg8qX`pOv&(-+F1B97_FOb0N3Pi{SmbXaXwGd&uKxn*!8tpB;+U`k7?xke$qOtV`le zDI6v~H&*40Au1{t%+~I}OhwjHJVhvueQ(vZ-sBfL8byV$u)UX`-O{Vod+=)0twVK> zjTvbIiXF`d5+F^z;*xt3Io|?)F7;(=dCjl?TK4I`MShKeM2Zd6v$=Ec`FkZrM!YQT~#z;h%cRp%X=TT8dd%Z7*R*ypGg5+iI^@$%A% zb~|HID*?5zkCt}V&@A7`YrX#bZF^DTMWvvNzIS+QcEbq=0Kd*Yr*Ztw9FsfwtW(jq zPi3G(ufJQbVPt!DWM)54HYc8T9KT^5EPDW(-{A7=^wHzdu-CL4?f%L2W-55v^JCzJ z0=e>nSFC*3!rLeR+dBFG;G=CWIA96OYlPmKW=^d!KoDweqwsL&v z#iZQ(5wHLG{wRfAtyNH!*nRjyR3i|fe5W|#lGK?0LTGgKe-G^!wE{#;&+z=~;>3K6 zuU8pXhePG&#zw-BIus2WLnrB%D_B7@+!Iw2aPL=5PC$%)y*X={COqUCQ?@?r zWp8Pjq%M|HpDq(0xaSmr+lvG=vY*S^cn_H>CAH$`=B8y^-_^3i4I?b<>La$R;SoKF4uqfi=`293jo6HIGL6}@@Ea?~JwR!U>T;(Cmx-uqTzz#|q3LS^v2DQBuo z)^J3+Od4h@%vO9&tDSn=11A4?SNkbL?l!_aU0l;y#dptY=6>kgbRvJ3!;o)-&zeg{ z=akae&$UF%At#w9QpC5yIrz5q;95F;fTyk=GO1BX%uxCf_xRi><%Othmc3c;)6MqM z`h)mFevELM1w{=*8(EgDD1!T;mRWTIa@Pp=31JwUX)lh@C4%w(O_xcchC;*HDaaZe zw5<4=l2qIJ3$A;%g6U#Q{g`RV(f+i$`}jED(?P(Kc7dC7Atyi0c(;5|cxkIORGxjO z7(%g&`K4`FX<-JGK+ewDEkm&{+lEse2JZaAAb+UcQuMuXz90p|mo_ zhpUW;>8^$=A4Et7f)!#g@42t0yGSa;zc*mh@%c64orJw7g5QkarIhgPjIbrPc3u|1 zDGRh)0xKRDf=pSb>j_{99NqS7rlMD7R@?l>fqd?Tg*0!?>zmMtBEk{jm=u3I8 zhzi@fW;3C{r4Ql^pJ~{MJGGhu_}pTkkI$I^;HJt?wr{tROSLM#;mf65J#9wqSmHKSyDV0O;Ij^m3nacPzY3r0n4HXpoKr^(7>J(V8T|gMUeqckoHWF@oIx{SA zBwn)G>=|NA4bsXdDs=@Lo;Z)9B$=u&juaX=df%%GOsy#7C1udMj*R*0?3su~aj$(^ zv0Ca>j$(DGkYX1v#8jbo0(<)_dy56%k}&56rx)rZA{e1~Vf1D}NcsTJ3(Gg4;zx;M z6odjJD&(#9XK&n!TtBrwEYkyeDktL#09=oI9Lorir z6yU#~tp4b|-0M@mTc^JE=ej6=8EP9s+eHqll$rw^7EdnuOMXimu?OicM!=>gH^<>} z;urMKglV_%y{9cIKspeG>fK`tEA(DLO}D~*u;wI<7*)a)qlD37eoEtd4dClk>Nra~ zSK!`Re^oJSos;ioUUFS9dm@Gv`v95tY&W6U+R8}T>>(mTLU=08mjXJt~pq`<>10ju9LWm06E#LOBx5vGODmn_Hh78X($JV1&V zz^05sKuFm^T&KCW$yu>k?o~=Sp_o;+-HWoqJREUY?sTZzxPW?G4Xq6B?%N%+Ok30& zC^{pL@Ka*gKC1Rkd{CP^RX_RODp3@uYeXt3Km^YDl}zEuBS|^t%hp9j$8iALQnB$= z(~E34IA1HfKysMu=CG9u6iiAwO2OtBJp0*TJ;#W*Uyq6T-smP>4Q@b_y42o5oWMwWxu7@{)jl z9c{s;&ivD?^mSab>cWMc#l)cw!^XL^@hTUMX`e2nb>_PgpWxr)-AwGUU#yk^5Aw)g zd~q)>p!48j{;A)G>85(fIkY1WtWze}rb306Z;HwG^G!8d%0J!Q$&>l3(K^B!*HPMG zWr@!k{KN8DM1`~lRM=13rn9#@s|;=f?L6rp1%~H$aoe@N8B=ex^3TH9Q^brPj03)~ z2sgcUOqnWN*^RdfT?<)+Zu=(GLa{_0|IB2SP@2p#^tRpMuOjTi(G0V8v+n%9IIvg= zG8}^ifT+T3rqWZ1T9=K#v^4WFXMu( zj|L_>j;TvDjx9AVS73C*8q)|B6pTV_G*g_$?EoKvf^CH?<{!cI=pl!?QyC4GxfAz; zjrCPzrRjJl>6m!X8I3A{QjY(_Cad_Dmp;xQQ6;+Oem;?rDBa?2`m)E&?f_^0YKMZ3 zf{RO>Hgs_WvqS451U+l8@F;`&F)}T1LW=XTpwxPdB1?=OL>Z*o8s6gVglCeIiODQfR}tisDvO3n}TJ z%#5&gd&B1KDX;*FNOOzQYWo4-a$q@G&9PTkQsr-zjfKeT{R;6WF6`Qkm1fni3@Ppg z{bAv4^v2gl>GC`JJZ~_`gAl;Iuby8)5f=BeapS7vr4D;q2WsB84|_g6V0qf8Qd6G^ zGy`=AM{Yth_9;h1FVBzl6*V;lBZYlMzstXdkw3La2XCNvsm*sidj>L|Qp zaw=f4ARPr%`_0twc&2H)E*VS5DPHP@N))0Y>F0|=qE}Z9b@ru-Qj4EySf79@(mrd8 z>U-r4+960N<{77%DO6L77~(9wjH%G*`AorWr@fn4P-K5~G*HrY z5$Uf7+tqp;ugs}}e)lbYg^QC{v`~9u6rdTh36PwdLyZvLq#p*#pptRs`=bG+Bbg1`*=k;GIRN&Cozao z-^|N%KbIl zi;BwU6C>Iz9Pa>~Hos?iJ?8s)J!YZU^#%1)@?wqT;gNK?)ZgAC{r3jK)u$t54>Vnd zYCJM+m?(&KSSDB}_`-AVK-dQnWjyCOk&nx8<>Q_Dsw~t_6;Ja20yr-^1e@ zu|X5vt*_N*Bd~>ZT)K~LHu&blf1O(epEh&QTujIP!Toia|&a6S|9?UhD5XZfVlNrPt#7-HH_5C)2&srt*!0_GSR~_4Jj!jVL2VuE(^# z53qUYkoOPEc@TKxMDRZoKTNo@G|#m3JH(~FsJzuD%=#`9db~2aSZngp;zQ5DoQ_Xh z%#(P8xB14(&~)L>toL4Ri>pX2+>K39M`5Bb_lzXggde?ab+6WD;{5vFt|g=Er@r-W z&`?0*IjsN}1_0@_(GkB#{uZ!IgeY>J{}GFX{z@B>LCCqif1j__w-WGku4JT`>EC)$ z&C!LLRnl=exuBSfG%WdT6={EeZK4BrH{7pegi-q2mD1u|2|(+IJWj1hCh41)ZbWp( z)nLqk8}P=QSJ!SRY}=D~JP1$lck5J+XPh$D$RVzEsQn(*)VDXn)f~b{*01cuTMkS_ z$*a{)?B%G2+ph<;VL1*TuCJEnhU?Xau_;;)D9DF{Jk!v=LV4q_n%|hkDRSQLOydtP zp;N(tu17yiKU1=UtcnR(wF6Uy)ci2#HHv0_l~ZNfJ}$9g{isi%$<{}@w07352WAb! zlLqd;Zp}G{J!)Uin`oo)g{A6rpy5+rv2c+Zxph6w9~Lq2OS)Ms`e(~L?VF^zro<`WC}al zKAe0X$p>Bz{f*Dze))YVG(~e4_(0v*^|+({if@lz;E#7^TqjT7zSfy;x?06t0pT?v zW5e~v307XK6q`W{tfr3D?Cp4)SxZu24Z03=C#6i1i$2gg3Dyn)y;k)&23Z%K+S!Xa z)cshL6Op^PPo<&rpn-2EzIam%;w18F@mNkHUzwsG(`i)KS0+*l9ZDs>{_|eS)_aX8 zZ^vfZ;O>VWcwlB02nIV@7#5v%P1@#VfEB>x@uXFjs67FwwIyHiE4y)uR=i$2H9PU@ zP3T3n=n5*2P!0qK&^LT`bD8c2vYXXdV% zbM9GZ)_gc~?%bJgtoK8Bci8OxJkPIPb|c-9;_vJ6_qIGJ@UH_knRkToQg(GDFchhG z&HOW0gV9klQ(+8u%q8)#M=Y81+-2S?yV zFPna)4ja@FN?L)A&=_$>H}<9SY`fTYJ2bbFoxLBLRjj=teb=eP%5n$EZ_(g+m|_#U zS+;hB-20s-Gj9X>B4nr%QVL{>dmG+)P4D{;COd^lQ{VcCRC|4)%Z;gcp1%2;7f611 zl>0uv!`soxczmd9ajHgF+w^2*hV||DJ>P$v-s^vzZm6l~=23{?Bh1DXYpmsE>?d+A znj(HKqgdIG=GxHu7g-CGR-(>Au`vZ|$Tt-K{Lnv)?*4Ktp}`L{lhAmE!e&L@ zinv1OsBl~A3{^JgT7?CrW9VUGHpAkPjYtTZlgHjeL@h<#b?`bpV#eoz`Gy*0t%5+(}*H{$yC^xQF?r)BU;B&tR8FQn&lMH@~XnM za2ylirW=J~t@G^TD>H@-Z8|UH)Kq({*0h#23)e&Kgp3z~4x=V1Q(RW{z-ifWK;As% zb_<-_)7R9~VK4;1-h^7!O0TFRPMu{l+Fjx}O~j9G0znlLZ@Sr+FW_|MV;7DWRax%? zW0-bi#>x@7jcIj5TU_xnq?J(Mp<3*SGYnaqG{DU>;JxGqo$yGiywpErvR_TG2cNhz{Qf zU5?z)&go{Gg_#uTP1ut&actMR>e{n=}1Fx18E$3bsjtO%6HHX*NEp^L%l%E-1e(Ka!zN zZvH}X>uSq-C32y8RNKY}d4JCKTh)mBUNC=PqJ;i;2aDvmt4lZLr93uLZhp?WIRe4H zIHxi{z2_obvuC^D1v+xnTf=DU8>2wodIOl!;rNW&pl)>n+G^NOi8UbHGtv1ZCDwtp zQMWk2&VCrJG&-NeYc&ZO5I79RhV**g`g!`&ck$=X&15xD!bPRqg?k|tNXT9Japh4A z4wdfM6D7jiSYXk86s#_Ie5^`K;-Z*GG`d_3@SqX%+i>rLc-v1Q{@4?sykXbB)qksu zy7Nig)lW%nAE2mKUX^h})8rf|;rk1}&xg=XlDDRnPyJwrfh@oQ{K1hbp18LLhr_w<-xVQvXM{)0$brQPssbW?$UT5)eMa%DzM0-)M! zCSyQTBgr&4l8k?kx}UEda*3frf9PIqyi-Uu0oIbu>R?3lIcmoqNUT*0GnREkU{+eg zjt>WvA1W+-1c6L$D*qZ%_LyG$$vrHP*KfUeN4?uJdvVY}p<{Sh|7)~-oh1O^poR!x znwzSAIXiy4SSgrftlUUzP<>gK-zAcase@6iC_WEHz+JY}d=yUt=1-&k4cBI_F%<%| z@9f%+1+RZ|NXoBDE$&l&SGsSUdvu|vaa>zWi%SP(Y?5nLl$PJp$8VczY1?3eFG2fF z>96F=)F8~7T*pe9I;8yebA+{SHUbCLH?lFqPQBn5k!(L=Qta!1uGXxKB;pJgA>>|N z=6w+<%5$xRaB8pxHd2hY%>7c!$CN1FhmOdY^N;mjAS)DOJFI<=@rpL$!=nvt8A1&c z(<;;J4-V1Q3mChIXv`Q^+!AV{DtSywb>7X!Y~~iYU|pEBqbP6tQA~6tHj9&L^*8q?Xn8hH1&RKu^tyiM+ts3AiiA*%cib++dhcKoOnb8Wf6% zjtntHL6jTozxxB0Ym*gEdrcIEIc(#N4%|<0YNrHK{6ecsrF9b#bNI$DyfCS|mZ>-; zc`MKCEM~7XsR5LYhgjwRd1qOhob6P0K?@XG@p7(dEEgd@=&W=yAl01g65)r^{V~JM zZ1rNYJW5MI<|V7c0rqRWSl(EHwZIf;Dd|ij8e?OfnbdvnO@TuCgVG*04l+%h?JnvU z0@48Lv2@zBFjZTu4k`MOT2{2axy%oOS-f^CqZx3d48hz6>;mP*sWud`7LiM2$t0o@ zdqAssJdYN4Q+$}h5C){F66|35E49%s8K9*yC}vEnC8#ZSWt@6lKfDliGv74^h0o=`uMFqjJJ$7zw|-742$oNggB5tQ`_dw zwcUL=PdskVa*mrL8PhED9h+mx+RBij&dkeVzZS1UeqDd^2w}YWr$Dm06=RIX5Dxq} zHw)MGEXMm}0C&@XiCGT<^4z|=m;`F2WpB)tV&oKKf-9l^!x`9y?cn^Abm&;fbuXe3 zowef6nwEJa{TV{Cz^Clbc|W;^ajWN#WqgNN{vj^f@4MvqI1q`OmVPQ2ZEfIskT-%P zl4p@x4+}$qD{_eDR|BD<<;I93Z(X4_@{yDMRY{Vcj2$$)l@>Tk6u<~1q^G^mH@KvL5@7J7WZ-OS1-CNAgK*R9Zc{X`U*9v6@J!Z16Rus zH2(srV%`0T`0aODabI7C7p%CDAwBw8S-PLq=5*pKeJwOcJc8fZ=5A`-R!<>9aLaFV zs!6ye_4fvInC>>aW*S_xtn

    HC+vX$D0yD{TnLtMO(LGZ&7>A^5Ey(tO81)S=^+g zq_YUGSNOsluyQI+_~8$pQIPyVv_owtITKLM!zWifxc;zp}U zcWm+$?6MvT9S$2R$Q?ayT*$V=Xa>921l<`vfHh^?nIZ)aevshKln0D!_2lxZhfH#= zJTqltj|(F9Tetdg)Y9E)kC39|=XP=BAG>W&3k)$qVtundXPi!!s+7ZU{aRhFS~`js zmHsKxVA0Ht744rS+gxUmrn$HEvoHtkUt_xRItcwn+k(j7C`_gqeg~=1I`J7eqQkDM zXIi%laaC0=ju8A)@0RqpKZS$W=AYCjun#rpwc^|@b7k=ev$Qq8gOUk{gZ&Dplu&ox zGJ}uN8|e@Ag$2^TOw`xR6%K7(sNB!Ml$YK8G-*OEo|g?c3{%4E7b5!5aW|lFHa2}) z;O}Ji+{L)9+Q5^yJ+__S$2(#_Al|)}W7Ppz`C63Z=u_3iM`Eo>K z!PWCUw~Gz+P4DR)hvpKnHow+v!o8bQOcC{Ss_=-vELS~3?#?#xg2-pFB?0h%nd7bc zPAR*q1#WCfHggi(Udw0x?&L`6TkHY%M^e1ZTW&riJr$tw-NsDD$Cv^D>E&Y@OAAT< ze_7%LS6^%pYypdBAde36>%SskE;1!L4z*|xFtNLk;F)XSRNA=3Mi-zql?Hfr1f8k) zgrJ%*lN2OsN6$s=#c9lAan&Xo_y1AYKug-+2rg8*!Kxb=&i7=J*K#fQZeWhEi2^A& zSlvIfWlIB4mcYVuz-l<&*Hf5 zQN|6(JF6L42k(?>YQA9(dkrBa9WY-@S6GD0i`a)JJJoD8%1YJNrS2gDhAfxHIMP*J zJOed~6`sAEY#JMjGxxU4L9UBJY)vu&5}F`Puu@P@kDYPvC&>ywfq@nd9_qVx&pCzQ zHm|95&VZxVeaD}k>2@?;n%cBrM?C)tdyyCEK%ui<-L`xx1}aaqjM*le{N&aqpRa4V zfkY~@O>B58GG1DxI}B&uKB#lW&kXS2$E!|km&&c+2i3o7GeO~*^9*@(+c;S?T8D=) z)AedvI`r(eT6Nz1gA7wWm*LZ#CZQ}f@s7&MjZY1e+$u&0m|_l1t?xnUAjJ9KjrCYw z+Q>9&C8f$XcZy)N>fEF1f>N z_+{x>t0t|CZ93FyKhqsZLkB|EE25K&ThMW8z;jW)5IS4Q6tz|KBK4U$`G7g4HPL_9 zqV8XU3|@LUtI>P%*Vw934z59y<-+dTSj3J%`qz!zFqqVSY1k%tZErDa5n`}oM*Ds^ zvTDZ1Hv|R0&?wn2nKE`in8|5@;B9sL2NEs@c!Y zj()49bSX4*)}6+!2+Y{XsezIL3nFySg~=Flyzw32q(Z?XzBFBq3CO;>*4>WC(Sb-M zVtsC&Z*bht@Y{O(KTJil2v4Mcu!}m$6H3hxF0|f99_B8+W+FqJZkzpIvvX5zxUl}V zIo3~Ct&0J{i8kZ1B+al*fGe7h&I?Vh$nwE`SZBUA zsLx=sLn=s{qjBz6@73yYzken)q^N$HTZ8RUX?TKpxT@yj@r3N2WMRXO6$BuMrQsG_ z0|sW~9}+3wy}M{V_5oIDqEJ&!{idsyCV)wj#P2YT0IeM-a@RXwr7LpI)G<(y66fkw zS8vF{J})e}Pup%aUl!)vU(BxA7 zc5wD>3e(g5;)y?x6e9oce#rk~*`w%v6Dwb(gc`8>l|#Mx$J19e2@Msu`?V~-dD#EI zXUYFsy7Wth%XL+Bn`c;eeNOlI{G)SYyZ;7$@M`;f^yr_OfAj3Wa*zJkU?2aBt;m#V z5GZ;X-i+&iTd*W>LB%)ekPVW*M-gR2NS|5{`Ztt$4dU-m>1)7$^^D!HqgjWn`{wJ= z5(OK#8+um3coyi;j1CqqssFew7GEcr{l|w%VJj85Ip#g#7p%aG1P8GOr!Cq74em6@ z!H~P=n=dYiPkwRfbw;l$n#q1!YL{U zW1BUD9PY{7Oyq6ttMj_-^atd;xASmTXUuXG2Kl0)s@^s4s=Vp%wAcJ$5vM?^CH)a~ zvT}E%wjruil_zH9ZWXR~703J3^5+tZs^tH-LqT(ZI{??3cV^H-+i>2T6H?C`J^KRS zCk$M>aFBfET`M}xXh(`gFpCAgX^!oZw+Yjm7y2|QUcBEW@EuKn1;g(vHPo9z#??92P4nr zBlX;VD)kcOK9C97`}_cNH{LA|c$3Lm)Z)t-xF7!OX##nO<%IZWF_ygWngp31MTjdV z%)~u774t^7T$$wEF zAeJ(k-_9lR2bj00+16*qYXgc_>O=c}`M;iA%arj*=|7whsJ_fr%g$TcaphpmAk8nW z#snE=Qljh6S;F8$Vh0tssNpIp*uYJ=hU=i!P=2*N6F@?@Mt zm!ziJRZR4krS}zXUMS&b3i*aB4CvN9CGWyg6M&)LsAv75Ze1oS#DFE|O}JwzmAh57qudgX3=})(jeI-%jYga;IlG;m1>inR0443`*YH z0E?#u;(w2krP^nr;a8badRD|4<`I46kK;GM;^5Y^I@+DfMh+)a9(`av@kWZfytJPc zfD+xKg20t2IWMHR_CUI51DNWW|K!U#Ff0>6P3_VVr$!6GFYisAZ2M>Q%Mb~r;uxx$ zp|8dRGZjzpf!^j(@@)%0%jK1m)x-%rX{V(`wPD;~#-kJF;q)`Vafcw2PyY0--X&2o zlCJ-kMIYPAlq$1*fp6C*z98(dgKshkFW@<)BZX#lCT#`8_Ln7n#7A-FqxWGnoyiHg z0v~jz;20-Y!1Rg&<|nmf{?aAdQR5hKo(W7JdtSZ2EQ@|Zz1St8W@dAJ0oM-Rbqrx1 zKX2-pc&%K?5(sy5afjo7d?!O?(qXjHM|dlm!h6g!BlwqPR*{L=_N-}Udj8T3X=8B1 z-{V$lsWX3BPWUP@>@0pYggyC>*KmuYmHDQR=jUMwJ6q8Ib8X7H(E_A{SRIi7j&^+B z07(I?UxoX=o#}R1^&|0*aMY5vWlFWHiM3DO)!!i&^HaLk6s{Sr5I_NXzaRC4C%4cM zVsQQ`2KOEFkbh(GL#6$xTZ)0t-kjq$>oqxPH?sEczX?U=cPjdyx3K>&{Bi!{HRL3< zbFc+ex9FUrpyM~fZU$6sAN(`qscPh|L{hOj)7HY)!)dPABKnMrh4kXp)o>1#xnYRC zse|)!h4qPryc1+xoVM32_zZQ3Hg^!a;i-BoIc%NLYgRKD!PBQLBa^7B+%e;}^<#45 zwWcJhCfoLO1=@${xcl$+dmVGvh5S$4zyI-9^#Az(;HTW#;9QWZ=zC}3(Y;>OV`?za zL@?BVAuX2Yn%CO1eh_|sKK{dj+2=B)9%N2ViZNbANvt$>Y|DOZ?~pUBl9nd*dYA+w$5Lc%)@j4*w!KZ1H4tj?=Q>!u-ny5y73Ky`Q#m@D zZ&y-V=6ZXlP5~N6uh-ye1|RZroK}(sXg8b=jem3slm5-@y!LRMDdLIhi{QMvN2kXG ztepQ$OzR+gle7WXjoKZpznwcJZ4L)MGhV?ShwHA$1s~r3%hI`eP8$9=>FB~V;}NrM zu0NHg`_1t9j3-C!#kEOKlx8|ZtEGd-dV^?$sh_s{=j`Hb3H zymsi_c8Wzz=$m~&e=Y0N!oB5ELD)iiIt|h=b}-@S*xthz0v=6iBC-bg=xYY8 z?E-;#Y^Vk}0?wxk#U)H%q>LQtl#&P9j<9e2Lht`GqAKG{BXo{#xxb!B6ke$%r$0Xv zlN{51;f=f86-yPe%8oSJ|MjxPI${g9Jt*;)#S@A!$gSK{UcLKF&L>c9sA|0o1_L^p ztSt}Wpy(KN(UWi&-K4CH=&$#Q?l3T;olzi6Irz&`{)i)J zEBCyiazP}n4k)taXVI1=d(0HCb53u}FK4yR744Pk86W3x*P)Kr0TM$8!S1{22@J)6 zs+s*bswvs<#~A+A7(OaDaE^m(YN~y^DKVG-O538l--T_{wBEBDUQPk}q_y#7hOjg` zXJMlNF0rNB07{@JShfx2_~im7{1;;z^ZOvYm;)U!b$#{(%`wD}nn~VN-_gEH#5yl1S4 znJR06GE(Oy8&mzn;NSPQ&V*QG&mC;som1j*lb<0ccg!B!Jsi7{8lA|%J>+nThZFe9_u<@3xiosvS!;MJ(iw|LnRJvBD(uxzVl5q;*qm55G^~Zud6|QflFE z!Qb+Km|ua|^4K-Yj=idxI%j|#S=x5jnRsn4H>q*0+^B5x&$SQVfA$+9vg&NQ2HUJ4 z#$Lrp{4MLRi&Cp!_n5uVr^#12X>!Iqo}v!^XPC=)w^^# z83Ocw$jeC{FNQ_T&$PQ&)W{L}Q*<*)oH37|UhsH~`b~*f;}W|tS{wzKNwJKt*D(dA ztl;r|>tXMQ8WG0f?RP>f;*zLSsphD>14qZ^bZs!rfo?#xLDP+?Ci6+>@oxEii0{!1 z?q9&Wg@br%8C%gdQIV~7JaYTx;m8xSTk(0Xv`XU<7pz|)OTGJaBjq%M&B@-y)BW8| zhe2*-0d5s2J4XL}9}l*^iiz&F695iwxuh!igMc;$?;bi_TWDYB4i!cu`6(Pw3&3MF z>oM-1Gg;rdaOB1EdcA&F<;ymi0|6)7x#gft5DcaTu6R~MEy_JqkApG3o^&$uM&{QA`;{+wMP z+4nW2%i1;>NzUeHMd)7b9(UYGX6?-39Vbt?56XhAUvZVW;R^4P=+7rxYO7++uL=*rdhh;SG^%)lnC*v`SJDlPyKzy@LRXjkRz%G|v{;RBOKH+MD7NA%D!A-Q*d{S=(e^ zd{OO2E*E;>jFS1%-jo9bdIwwCMi-@GX&}1CVAwSX&;UgqxHm>Whnfk1KN@>Eyyel4 zf}QC3_<1_+^n=T68ObpVH|EdSmhvs`?ueuK?{ypY$u%@*sXk8~+uZjzw%FI`o-Nv( z8*iFmT4yu~?*UcHr;E{a4r&MG**tcm`)i0kneNOrq$33~Q7s>Kqd4h&;tyZ^ngLc2 z0{n9Qg>1ake$oqMzb2cC(DL}5W1V{dC=T|eW@N5TeHvVf1X6=~c8aCA-LnUg$43PJ z8qDsTuX#Lt)&4Jwx)xsMlBhn~v;){l$1XJR^>dCVB9Gj?}LWrVNG@U;cgtFA&;qB zWHgaImAo`f_)(t_0YL>|&<5A?CIO3wk35u(oHS?BY%CHAbK=Ps`+owSA|av>OGN^P z-@)-~)l|b2=6QKvr5V>Pa}Ht02=T`3SZ`c#ZFxG%#eYDSS`T;a%_qDg`sWh+pv2?m ziaf#5A~J2p0Sq{8`|6)GP)Qn3&f&AOcad+DFPVYi(D+(LKQF191eU-x(Fa@xZ`=ZJ zQgtEpZNlMk%JN?pENpRoipgaWq%E>kzNkBs8iN>n$Hg{HKzne zJ6PbSCpj6;+vegQnu2VIE~d|J^<;%qAx!0VoyW}WwlOrq_e!oc6V`Wr0`*9X=FDR} zkXg6;O>{CQz%`07l>0w$>~!_w5DjY5m;OApAw|=zSo$rmBH)MedDjdx_1sA%%M-h0 zKPB~_6o=6@|tRC8=>zg(evlpSHo@x+}{tNit$83=Y{VB zQroq<-ZuhHW7Uq#a;gGN7Fz^mQtVRSX8ia$Fg^L5SRns!{SH1?4z%Z;F$h)wr<2OY z-8MDcRF)+IZBi{9C0_W?IIlXEjq8a03DiYxE*^-!*W=zA31DAFP( z+Ny>#(A!Xj^Y%u%qtxQ7Ct(q!=!Fgoq%_hj)v4#eOc`(Dfs$In(OFDI zTO_~86M5Fddw7jpm-~ueKH7|DWt9w(&}vP){@@VIFv>E)skQcGUJgd+DqIe-V+Z&3 z9oJgke|wC?Y)zna-4r;NiM2^Yf~ks|RGY$+;9%7wL#cGlz+dlg^omt=mi@6j@gWb2 z75b8C6IW7KAa#i+!$zSOZCjTa_JwLG`4Q~4oAU-KKKmcX zRg~E2Cx_@fOaf~oj2S4dbdAZk(FCdA!#KKbN@YFeXRC_gwtz{$TwehN3DqSyalLRI zTJlbv?*85(F=h!JbOdb{T(ZkojMDOI$h=_z?vsGQH@navqp&MOkq((f z3liLbZ0q&ru_3&o6ZG2HdqTD2H)Dz(y>3Z=$9_(8pyyG%7uUL?Ey5)IkU1A^#;Ym_ zkkH7ADP99RGgYAik1~Ky$S^24|5Vtoqr^&@&JD(3rIWc*E0gJhvm#>?-Mt-DMtKc4 zfbWIFwc``v^^+Gd1~w8xJm=2Y&@ij|9n54~n_sAfVm`!#s{gLhuyRD%{H^b?#(UDE z=|j`j_&EQa_}p>3VAqO)#xP-!-VF8}Ni>)(#(m%&U01ddtl@`W;O_KE9u|fQ*hob7 z?#QM9TWf@yq?=A%b^8;~AvZXbn{Vn?QJfmqb!6Vw2PeYYMe&3=Mv@DX+6Ep|y+fON zX7SD445Zw{dJ%G_=AQ7V%_Dkc#hhCF<TQTdMx%!P3BV$Yx2XodnsWqgL^Sg z{&P`Bp(N(4?vSrp?JvupVGhP8-?GwIxQc=#tMM{pooCeKIcA)fE}!pAG~+x4Q5;>K z6sf2>p0Q;bOOeQud&_4hf6w}Ql#%w+F9Q=+Xb`fDDU}P}nE})M*!|5pOg$~V6UI-Rbiw*n)Lu!b8-B?uG*F|?#ci?pJYW0$zgjxIxr6BLL*_1Wna#j60XYs%>T&bc`(JkTf-_lBQ^esl*nK<;Lf4* z_OLz-m531>jlX)}gkTO_gJiJ9xmlnY_a0B0^#&71ra#aYd_1_09iFIR&R9Pf$d_M) z^0VC?j5uH9dGjq-S_mDzkL#fN8zY&9T@dLah_!5FM;(C zTq43qNzoQhS5evf%Ysia6`5YPsHOV&1Q)CxdBl{t+1wKgBYe zgEB67Wj?w<3Q9}~3n{b1dagTv>Z!MWVj)*&<)^U7TZZ$aW+%}MT)J*ipU(U^;0y>e z=Sn&+SwBuGRc}%M88%S!Okzcj9A>B+bV+`jxO{K$mcnj!hJ)(}8;WIRCKXLNdUGA+HHur8;&bZ*jJx(EU*{i3~ zeW~L`*Sm+>#yd@>t*6r9r2d!86ulQap%-$SP(oT}J7%URU`^etjK00`;a^LQN;K=c z%kO+cT^z|@LLKP*!E?w|h;I7TY{z#V6oYcs6BDqLfFBymDBq{^0*W4jO3#@)$n!8v z(wYk)>$|kMsPzG7K2TpjnoSvR`$!wuzD{2!p+g-FB@7@A416lSL?+7Oy>~EUXUBpISgV{vq; z`m!|EWnp)?*tfsj+D7v!h{QKmd}gc%0A6f5+INv656mrhT(X=Yj=$HoD}!oKz;PA6 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 z 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%0Db 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 TD^ofGVp+LAor0t9 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

    MBX*m!eAEvBB&`VHj z3`d#9rzQh!K}6>vWiu48MpI>_nqj^J-;3cUP1y_Rt#>E$L~a2|Y=-&)Ka3-s$8@l6 zxCaWm4lxS5#%Btis?57GXy|C{+N;25%Wh4^TQFAL@8Zn-#<0j>po~@YT#1-^g zf~0wKk)p#=7Ildr-HTL>2v9;>IN?nLd{S%Dy{DMQdE8s<96_44In%pQ3Jkw7L$g7E zr1;vi_09;nqb{+gFSi%(J=Qm{c%$r7#u#NtsTICfyVq{Baj4!8U4nH3)H6xwn(554 zc<7vwVlA!cXpksF1$*VB*BB3rA;w1u+vMc~<;5WU4&?LT$;~5~HDa_DkUM&Y{j~l~ zNVs@KD;yY1u*_`1aO5iV|cY)#qb*A;S`Y+XYvyQ7s*p+c`S+U1y$zbHo@Qdb$IdURdg`h?Vyje`4Y+ znpCs-`YVP@82PFCuNg6!a+Pz_Fsc+~7Re^top9;O^36MgU=^IcVVc(H`iO^-MU5b8 z&;aeior+oAR3mX|iGgr>q*aM7KF@OWq5-su2r!BbS)p&VjWR;m;~Rv(Odqa42P}KN z%U#Tn#*bVII4=Ko{#Rr6+FNZC(_;fpIhr?KTF3fNg=&0$M6TS+I@*SffSxv3c4WaV z9e*N6$b$_~$5l5WX1aXzz>oMQo8N@rMj`6R_zds0g=LS5!*b6nI!`hg0%CD@RyOJ} zo|!^!T%?DVs6L?Dz|Py=h2wG}EOdOgo`IF9o5#(Wce-5mch|_N!<(R>p%Y&cSX;+C z$6^D#)9Xjbo}?rjDqgDy8||k}NxU@j6qS+HljOWK+ag zX1OWYB+af7wkb2bL3bkWIZX;*3*rJ)lajb>;gCQd5h|VPPoR-Xvd=FUn~sj#E5q+S z5{b!st;bdx3DmZR`{o%A52W9%3mihoY0pb(du%5!pr8}aboep+X6 zCoL0-#Uvo~DcdG7RQ5NS_n+hjnH$xIhNh<7P{9TImxjGh`TVo+EvilLMYi>4uM+s= zn1t1JL}zM~BBT!d2q!^6QLe?yZ-@7P(3do_-!v-1>h0Kdc$m1j4@4%Uj`Vq$1@uZ5 zZmI+Ih<`l4&=xMRXFqi;^Odp_FfL-_DS^sB>zcP@wb`Ae;?EQYtHijW?uDQO>~V{N2=P`ge@p??tan5nX(Tty}!VS zicE98ueH*pu!vd~i2$`?dlJ)Dveq_=11q=6Yol9<{zyez&)aQ43$ZWnUIg0KMP+o0!yXx`J+cZl;`*fm!%0Ah ziO;Jn(^ljyI|T-<(7}!?L+S~tR}H)T(8+;y-m$UJ!UmYS^6V6_#L91WLL_~`GA66| z8Ff)LakeGuA;eqZ&gZj6gXws==O>y3W)qed@zOeSr%DxMkrzA7G z&$O|8@p%4BP)l@e69*mrQAb*y%_nfCo_t>(Bhfrd=Vv6|ynfi0*uNW48&|tq8L)eE zg1oY+cOBZ}$g$S=Cj8D`v~BvswB42vk7R%U^Gk;eQRRa$7x~}b5SYWEtKrrLzgAm5 z3tPS_K=-cxE$7lbh$&XRRa-<`bd^;lH3YRJ@h6M?h}EvSm4l!x*v0C)*`;npq^Cgj zAzf3~<>EwYBgxW1YAk>M7~94^qsty9x&Df(lB+_T>C(MVMm4R-aKSuQ`graLmw%M* z@geos1|M1+DVbc+pCY~q*^N~uJTM7VDbmu;j1&0r`D}Tb+}(QvHpTBh zjJjTQ;iY2RP3H*Fui@ECD7$tW zHS%${>sUrWMXq`37gdGOR3>@-O1t^g~vkzW^1(7=v$wEZ0%H4 zzd-7i6NS1p&0g zq?)*aeIdzcC-+zUsRUoEAM;h~50XchsB&l?b2{^AIWJ1ho$}`VTreLrGba12=Is>^8SDP| ztYCn=uDe4nmNT1AlRfWrjJQM+kjMqOCtpDcgO1Y#c55y1<+{v_ekD;i8eoX9IT0{8$Q_is-7ivA>h5T0k@&@7 z&QewOg*93rH$KVn4o=HJ;kr2+tkdu+QbbjKkb>V0zEM{13EDVpm(g5z8E}efYRZ-w zHT8PMSoM)NpfT0oyNBeHcJcnMqtIQ?*V#II1vi*aU>$Zo*=v~u*=w9xc9>K8=qk#m1oRljo^rYvl;X) zD!j>POxV&EBNCD!jcXIHJOTE$hN-!=u2D@=^#D&#F|p19H0){sqM1JJO3$9 ze0ufUmKmBnB8~2lzV7W|1m?8Tprxb^T*}1p9Z5wf)xo8-r#id7uda}KRHg?$<;do5 z`6VUlR=CVJX9{Rv&|CK)uPbdeM>qusPyL>zWF7GYpHty@54oc#0>3wq|6AV$wTrh~ z-ORuQX^uE!;{iklCB-he0PP~-uGS%^2Vb8>`G$8xD{!ICBslmEc&Of+BLVBinJ$Wy zsUFsG9%?Bo4i`V^lbedTYPaZcYkl)OU^rK$*5nmQd|;dPo?zW|Kx@y-sVY!OpDdh` zR@y#yG=!T4W@jkIwV0X@uT&TAFJmhpj3?JQe+0HCkf% zdrr+jro+)~!*>aP3~Y;6rZ0C~lVaP6Gmlm}pOp#kzU}W`Tl9&RBGxhE!rK(@be1Ok z+P8VPNVy*ts^M)x5H0d`P--^7TvFw`*KQmP#{0sR$P==S0W?+4iHgE8;{y88woA#8 z%U;$b`{g~#(sXp|A@QnB4%-qG)0VS#(mjp{rOV$#!_tWP%0rbu+S=v!W~wi+#E98{ z)0hV-BVTk;R;kcYN+(oZVuH5X!2d=m44p2dkv^ z`FJM)+od!+(40tQNsr(j-1<-nVP zodve1H$KITQ*3qw-qEC6ChF|`O*k?D{;0^Thl8^YyA?a8s8of3yg(0~UUk0i zqv}B65F@9-t6COsl2K1vb^K9vWxTghFdodaRbOI**gP^)A%Pif|yz>pchy;R<-Ki&?7}#B4qBLD zWeNs4pDJ=*Glu%P^lQ~TEnuSSF;*ar0?M%#DUZ8StV%~HQHLux`bKB(N z;<)snyq2bulQQ?gkq%d5W8}e@-^Nlnve-}RDPpza{PDMeX+yidv5HG83hW;S@$y8-=ijLAJ%4hySSL%gq2V>59?k@lmc!_wwcAj+d=n=0(zlf zq}l>$W2Q+Z0zQ3+jJY;OFBm6N77qtFy; zbE<16-TR4~{}kD1rLWVD$7jYhNA??v@g|{srK7F4uC2iir7|Zil01hNF(X~Hu!_T( zbZ_jun@y;Mo0X;2O60q(HHK#O=Q-pH=Hmun1UYvjhIW6vr{pfmXx$`Rr{>8MCyezl zEW|#AJH!PI^z?)w_*=Q^AD%9{EqTh)f`x^bg+&I|ZRtF(8mw&_QaJ%}xoCj4xK*4M zBgbLdCP@LC+}q@uO;HmS?J1t0$e;?wYHL@pP1&&^ANp6NU>r(wF6dz+wN;90dfEXP=li z^;~28c|@}gZ)qKeV~l9cx;Z9mjih)!3G{w=m0Tkya_g18aLL^T&fDy9ZtWo96)9{>1S2BGyH!A1W)fsR+&=<$#c*$>gmzhzxG}^unRHiGAQ=#Jz zc=fdq($SN@|8YGh9AT6)Ce^|2$JpgFEySBAJY9z-!wbbqq^^2q%!xC~Q#epvS_pVh()-3uh_+mG7Vu=kf^_l30#2dfH$7IP}BpW$R*h%=_0YC@*#v z=N*E(X|{N=WS><^1~9nF`L}s~Z{N%cGh{&vuWz+J6Rk~?iS@6XO)kD)}qLXFRs!qVQmHJ=J1xfG4lC^f5#H#Z0S098<4AZ4lp6T0O2 zVC+4`AJk`=2L}0Uc677p@u23ApaOEc=Dlv9+|x|poP8L?+nk^u0dh89q;$<{|e>n+dAK}@}Q`>${6{f{#P0WH~lWmO5q#S}}Md~;tfj8kB& z$ZS4Jledkl(plm%eEatPttqgXr>(DkhtvkXE_A2D54cQiz*Ft}s+9K^4WwXQ?eezx zI*DRPnIm_G#50&KT=@K`YCO;VA0!Y+Sx{s1QRsVlzs;MGSETW6Rczj;Qimx!$!h zD$~ik$>BuAg@j_{*2J~F=oS@}2?FyF0Ae?(V08n06KHw+u;u$}FY`H9h(o|HLc zNhwGRwukp#9iTH<-(hixX0}V@=^m1^uW&GyHiw5A3)A*<2 zr2xrCuLs-=vS?lBY0!Ln+nRSRu#M5c5FLeT@w$0b@@K&<$aFIt1h}a$2ELPQnl4r_ z0Z6UrRp~=1Zzsj*=#~E-f6q2_*Ho4X`#?#5%n{k zT|=|Q4oU=7wQj|D*rDi1CNR`W?fx>I_fYlw$@gb{q4FJj#rBtc!6}YPI8|8XgoG>> zd%He=zMx@~Ox5O@vTBLmOTsRxB9WioVaMcZ7ln8!x|Mz-e>hovR}KG7bJ&>6e|Y2V zd2kS;+47)O7=eHfC6}3GuruzD)8@){XUtS~Jyy>o1XZaWmQW}h^NCfxbq4*Ax`eDe zNu!hP^w;zV5_iFg&feFl9wIgDXcV;3Nj z_93u~L+0TIXRO7d~rB`DQNb2BJhF-=ap9r=Tv)D57r@nwPZ!Bjj&_Js! zT}&8h7BADGTaWJ%I~VRch!GeNqx8|ovUE27guAAYIc}svQ1Zf1TX&+w9$^;QZj+nN0 zD6CZbaK~u&dQk;dvUS2xbbA+tG7G3us!~FBD?&UW1E|BRt1URE$-^98JNJV)!}A%` zWI6;VI5>P-;Z9TBjWVEuz^{fbt_v;K;EJA$=-r{TB@zQmrO_OGXr|EiRtc9^f3hHU z!fJg-o+HDLsv0{^taO|zj&c4uH*}lEO#W~@cLXfiL$s<^QOZmTmV|g3bQjjX{frF) zM7{L#6Ke=)$}2g;Fehk$t#h2TZ`0K$Y!$}!ctY%3rR+BfCY04Z;jv8fn@-~_g+E_&Y(<> zDACjs`0~&*2tWkbNlJG=Ma?SU9G+fs+!=Bh0Asi01KC zGaO7VT}GwUIF_T+mK>euT^qz}%za=!)onmvhsD52RMLz}rW>M=_$KVev@ZK%2C^VM z&_8eSbdwFC?_dX^#^X==Udqkx(f!5wmWceNXCM2JlAD|M>TUdv)2Nr!p@5wjO-BpH zbAb-U9lsG%nrS=@sl)F*7f_i&d<~m-YCqCEG^95u)YO^0j<{@j^qhcT$M7=AIdsVN z9ssG_SO$K>+Bno3zSi_68`N4|ZI!01czZwLW^X+9Vl7NeOgh2Q*l_q>#Z1>FU`>Bg zoj8Ff*v2puI$8nm=5i?Yj_eOO&PM?&29SK+3^CXJ;C!kE(s&0&T1(;a4ceSKsd2-? zJSZAWZ92YR1}ft0K~FY8De?@q*=6ugim7WU-_2hh53|JQS$;7C)h4uM^lG3$ZKjC? z8KWDq{x@&THlTYOe8M|F48kOBx+WePK)h2*l3{ILp6|e;l!z;Y*>H*DvU>JOB8Q{l zdfpW6Ym|SM%pmQnA=Z_ zyGw)`OL43l6pU#r-5+7_Xf9#3Q=$h%1-AERzWTTobr;9qp@b2~Sw_;*(&xfPM+sQ& zKGO`a{Ajz8611VQWn7AKBsDD@{n=dl9xAbe1$`lvP--HJlnacv@iPvrJ|>L zK22rf^<%hFe5p{oj4!r*a9r9v#UVzs-wc&r=XTZBm@01!_sV5B_j}Ri`iACG9;5vO zDrSk?V>2?F609bWz9rz^OH5Gt{h@l{0A>BU+TM~arf3U{J`4X`czNYrB`t&cYs+Z^ zUboxjv;??m3MKJCdq|eX<=?lWwZ6*3=MOMXl`eY};9ZG#3u=Sv%6nK*jf`^#tgWr- z5EZCHy34uj4{jW`BUETxslF!%OVOKH7E4Q(|Hj^%N3-4U>)(2J9+eu3RtMBf%{7#} zT0>~4m}9Ee6lth==5DK6bH&ugRFViHv?OBIQdEdpQbEkKAgGx>xzBUX*=L{UIeVY| z8`e61>_3yN@Xcp^SMvG1uj_hUY^3>Umq*}?>;(4`NhU$p4?m9pW|0>6T9DiAa=Blwa5R9 zJouO7=EV&y1GXhMDVEmCo}+m-qV38y@E6;Y&U993&u4Svi6;r)H>z2sv6}4L2Q0;) zgk}8wc$du=|F_oX&(|*RwgR;dSs4O`%ExoNY>mtZ{8zi8e(ptFvcr|W5ibAWxopoU zrU-<+>3FJEhW}k=!dCvB>i1%7OXhs#z_$HX-}E|d#D4**Yc2$mNpB8QtJw+K)cCEp zY194FYGTxWX*7jACg)G74yxXc4ZHh#>V=R6US#EA07qoJ-e6AXV;%uE|B?P_klz@c zAX4m6GQAQC(26e9inYihRO`u4VGKe`y5p0fIs&(PtG9irhIZB)7Q4^b*w`LlXe^T! zPE8{GE0B!q+@Ibr3j(Z1ZX}1UFK?@&ceizo(MR|b2~4fBz^gLjPukM76bClFEaIq2LL?~gCFmxYI1L@L2V2Hec)8s{+DD{!4P0ZuB|*2 zD3{X_Xw$C!#6@n}hp4n5wa&*!@|vFdvR{Y zr|U<)e3|&10F8|s(PM!~Oj*009Eq}OIAk!uX5nZ5;PiHcOQEjDXQRc`%E3Y06);qn z66GE$wyNO`*01(kp8NfRfO(x`NHqT=j~D5@4*)`+6g;ng{)x*DNpLs(06q8~QZ2TZ zy;7BDI6OVb7vbcn=pjw0o4z$wGLpYjx4ppNTNlm%SmU28*q_+;9EWlxf~u&}69WXp zz=_JR5OaiAn7EwollKpuUgva(brk2OjJJVVjko4FBh6VQG*?}gBErOvADWzs`Z!gU zTyDQoJJ6cy2x-LWkzFQ+W-}lah0PdpU`?AgvwYe=oY4_&GbX;Bb?x;Ov;Li?!Y{VR z%6}k?_eH#AhzE!tmDhDP6SV?JBJ0eV#~!0GYe<#otYG}oaHj1J2;i;iJ))vOpjzHSX-WS?*3DRZvYBWo9jbXf>d`fSJ^2Mo& zQ8v3Tl28{_Bvq+CxtG=V^b5ej%IFK0eAwoCrwK%DW`L12xbwEzqWD)C!-`2yzkI}V zI8dj#P}6BL2oew=Dr>yTY71ad4D?nzvBmVjHx_9&bv!HPWj!+EFKsd&wW($$fz_We zt}9d{8#v(l;3?LrbJsg^qRN%ePO_jzlQkh83879WD&$DORK==N4Kt4Qf?!{pB^RZi zU{1=cBsG&POlk&n2$#SSZ#2(W#ZdV0VLdjG&+{DY_=n0gAyn)&_D+69^+a;3?Im*) z3Bq)Ac6mx6xnTvAf;kDR8wAumTX8{@sXl$t)Dp*Ht4!UHfY{BSE@&|fSwM0J6jj74 zlftj#S9wY&?vICgYvBVEZF^>kA^IIt_1PsFjWb$lA~ItqpP-{}0It8dh&gHDAxXFI z1g&j)Cu72+*9|=6=nw$SB(lo?n+e83&OEh0WvsTpKP;a{>xuE+lWw+C#r_1JXh3Zv z0R*a|I?^lOmY0LnqwyfcU-!7}iObH8-x)?Jli(D|`{S8UMP~VQSiKt9{H$!OOR@w@ zPnemGIEUt4yx&`v&tiBrONe^OXw20%jW0u!JD&0_C&FfU9t48MqI`Gl1 zHdZoDfs=xuT$1<=oAz@;=FvgWN~tohI2@m@*DO(S2`xsT81=rc3LlCTm~od^6MMq- znTf5PH&BCd(ad=eIw1r_sD2@9&j3`{x=?Gqx@a8Rv^c@yUSC@+_k*bo-FF$-SS&qj zjJtmfzVq98iNpIcBUH}w?Um{ZY(I`zR@6&GDdXp{K4x2)f_qAm&3kQ{*4BVf^{Pv0aHUC^gaxl8kzL8I}216TOSJUpXm)%EiGVbC2owKvxZ)r zr$#(wQezm7y~~ew09@gAw1c#P@a~UqH*Jppu$hiOGiwCp<_D zJbZ_rb_}ItNo!$lVYkDx5K6>^yih zCdHW#8sdq=`BvFbcxFhVmA`3>x3~K(>`BwN;5eH0@9*k!Cm8Ni!#lj}K1XU~ zeZwi;WT9H1*UaU%oik(RBkNT-!3>B?Y84BPcPkaG1ToND$^df?%&WCP&w(; zjUU`)00@+U3;-z7D26)Aq=P^*XvE6DI)X3Ok z`hvBpfj5lg?eVO7k-l4K(%t=lmov`d$BsI|dq;?c5e};D{`+U# ze4chdk93)AhXgPG*uHiP+Z z@p`8li!JL;5=QGn94y0uDV9>sFlSyqm56fRtFn8S?)Tsw@O7;}q;C-R9=tj)^X+V9 zqG{Zr5;Yq4Go}v*^-*TfmS>d(69?uRQ&&jvhP=c^eyI|<=W z*pEkFz5Dt1OWh~AnW9bAf2J?C*BgU@-yXSFQ{qD~L&oZ5!rtVgEpZ(mKRxO=eVy~< z?@+Z*n@Q8_Hp&0z*6D;u9!pl!)A-%>cGdLSGw_6MU9D< z>e0CZ8Pb|`n^`MvzdPBB`UBju=8q*@6E0(5dvQCq%I~(kc#YGtGixi1(yEIf!V~D_ zdMhK2xQ{uKDOJceU7n_|7F$KaDWxkCX@?;-fc)uVq^O88Yp1@e(xmm${_b`J^V$S8 zL2>26_Dxb)IBEJB;cV>ppXz&ijpGyWN!MY${B1$!Y2efF$y@W_gb`lEx?C#%2MV#u?v!g)gFshR?3 zXR6k>>CC^)!EvlLY`-q;FjY%=j zcm%dKFakjg#P75W)!Sm5`*YiwfEEb|17t`W=>)gUi%Hf)2iJ8fzZRc|Zdx<5F$D`- zufC365UJrUA0BmIcULhCVBQ*7L00nc&+l=pedM^Veb!#~d(mf92vVamQ0+E`%+-HA zZ+uf!QiL&$t}B8J02+<6z3qFTs!%&Mf-q~!nu5Y?B6-Pssimtl_$zmV9t=-zSyV$) z!{FA$$)+y;?W6WRhg|#D`xuIYKmBU!y8R?$PjBp<-7CDsqnsr3{=vI1S8iLRiNJMz z%A{tBe23>Ls2PTYx%lW#CWfyO=)dDUj;`Bolkd1nXyr4h?x5iH5S>AtKBRGyCgj%q9q=&OKz=5F z_Afe>fW2yY3&PPx>~T<-Z%?)@8+i5JPRfU&oDaSwD4 z;Vx$cqrHuhHX^ehXY^9cNj_zbeYq`By?(nnFmPD<*#jsD;{pCO&ARVBpw`x-86U6} zRZ=-pD^C`RK4+=*gS=l2R-|D=P@52lvtLB8XsXR28LVa%`e=3k7u(r-fx5H?sN_6t ztiqVk>`h@_Pp|^!bMyGZO(aOI!q=pfftT6~IwMz^$Wv(5JJ!;sSpeMyR>I-ZrWaAA z#uot=v^Xn~Ac*xV)Hca{+QGo}i?Ehy8rvOmLo?gBl>>`S2&b^?bNr3IS! z^&+pw8krnVS;=pGvN~MbS3bWwbXn=h^@w-2YC*NQsydAkyXxGeug`W z0a+W{oZhUy3G`)q5Ag$C&f4dx$Y?}$et$8+gY1@WF_KncIFTG@hN|7V-&cFjnYp4z zG`=7`lZ4(rugI`$;kDTMM4~>KQGR&}6|kqVupr|UA#JZe$fds^tmCl-;$EEe;z$&B zl?cT)$W|m z#P_7IUu;iRqO~@DhM7wru6#H7@w13E6aDvA`v3fi{x>h-Z@(Sr$+GNRjHqwue1TMc z8Tl_T5!zp&aQ?lC?g;z+jgJ>vUj7M1+F2hX?k9Ccj&4fLN9-DMn;qT~TS_!!4XKZg zv0$}B?7MTLyGOfE8vecYKayDN+xLrYvEi^Un62yM8MXKQ7cvUY-?BmuXuR1|Om1}5 zNr(IZ-)61|d`_i*n6C~oXtPnHU+pdfF@`Q4SRWeqCkSAk`@jw@W3_j`Qn^DuaNP~CH0X}EGTa2URrH4t}PmdqfZ2< zt-bU=^4dRPQU6h4_+O?X(Qd!@gabu)H32Y5R*Ju^^mT{2(Z-${Ra%k~l}3BHX$ze^LKCf)|2%pe?Lz^A2j3Wq`*OqfsnAU>zx4xn~OxAo%0K zd_JsJ3qv*Jh zyJHrcoGXW))bq#9Qb%HgLzB9qTOFT6GcH-&cA&#;Mr+n0e3q;$n8s1EejoPLT_^6! zL|oL4m#TJBNxJ*Z4fpv&-pS`j>OuNrOcRX@5?S2QS>h6&I-Wx~EX5?Wo`V>7?&fi1G3bwx*s?ZkpvMz0jSC{ol`fu)Ss#evj@3Rwo{px}v z;_6Q%-tQ^Z%_wx24~%Jh+_&86<*5+`{7mw%;CSnq!fe(qJbB6-=-s7X5BHzJ+josn zjSx$g!YQ*x^bIBWB6o;g31Ys~PDSz3BzvQ(U%T-+J*IIZ`-EYQ7UPs+DpmS?$7a1{ z)-1~2Wiys^Fte(>v{RnoKD$RS>C!RU-`Z354;^iHMb;H>1Shl8bu-6{3K%>U$^H<% znsTG|YPm$l$<=di{(`r(1oqi9RKmPB{i{DSrQZyecwF+>My8W#y)ql5m-_UoD>3NP z244B;b&}S80We7!A_VPGSQ2MoVBl@6AL=kN6h4I8E14Teo>cj|?OAJ`Z^(4`+Ey3{ z=Bc8>uG!%^=RS)cLDd*5+-B9(;$QqO987Wd@*QzHXqK_q6<6+!-<*Ld!Ilvt+^(I4 z2P{9`!UWs{;9qXEXN~EfaXLUAoYCDl8%C%+hWndB9}1Mb|f-XkW*xxhWzhLka%=XMg?FEgh`0_B zIw;ELqvBNMGy;D{qW)rY|HU@g)U>I*oAQfIAoRSC%Pvao0emnp*(eF-n)G?E*X0QJ z3F|fQBGhEeTO);3F$~(smA7Y2@5ACRwm+J|hZ|$~8J+&P!lKM}aA;u(7GaAu-alP) z@E&-O7R>X388EI%oG`q0Vs7-(zDUHx-q3@FitZ%>*1A+iI$KTxc;(DAP5JGc3r9ex z+jnO0kCIdM(Z!1JLrdSfWg4EaK=r;dks?e_-j1lNAK47?5Bo6ZC&I0Cw%pM%Bvjf% zCcaiytb*`pjZ6Uih|xcuaQlRwu*IF2QA?!SaEWbUjgGw$Y10rJA~IZ{mu;Xz*ki2A zJz?HRb2!5)%sq8jhO~W+UKi{?-sg2O*?E-w{>QA_mHjU<^t{c$XveLx^kzz-`4oIJtq1oskYv9$?_qCQhnlEHApAe07JjjLs2LSPf~86X zJ7<@YQ4OwHa`mDtjnOu)@GIXG$QU63bq&!>AU7ZM0yW7>)vkuUMzVg;5-OmyPLb-{ zH;DLO(dqwbkp4$@lb38*0oiZYR!Y}Dx{*KT{>y%E^FIjvEVlL?-)jb^cv#Q{`+EjUDrh+aO;u>fTqG^gIJmGajPvJ?e&Oh$sf@bdh4O+#YNV zk2>}0M%sgQTcFVAh?Mu8Jy}KC-Zdt)6|=-f2X`J1?L**ELp|csoTuEb3$-UvS zm{KIr;3`|gteKUvcNJVvV#o2066J*%0^W}t}lkk+(~^1(-R47 zZjmD_*{>l*dhbe^(boP zkYgL&Pso^4G&B^cMMU7=M+$lyfPV}{c}gWJJYB;Z#Rp0nr2_i%t96Y~nYIiM-?62B zySx10JINMjaJ*63p9+DdIpOv}2HoB>Ughqc;eEIr)R6kXL8f24rvuY6UL$A{cFmNT z{#HZ1DA0cfCe#$~=z1lv2U1>O-P+OaP?MQvM{k;O*;7MnYfC-sCNe@x`~kXNmUW&N4oRAd zJ-!T|CizgS-iYyw%m>d)qd&g7*I!cllQaEN$IMxVo<*%&WZrXlQ2X;AbQ7dhz4ghZ z{-@`K&SX=R3H=Nssy{`u7m-z*Q4^aCP6iw-H&{Gjil>w*1d%QY{kq-k#Z(RQnA#3ivHvEm4}F|9i`rR_4VF@?C5)7Go;^T zy${OivNi2AyTdNJ1|?iRP;Vk9I$XLr4C6+8#HuxK)H7>z&|A!pxg(Rl=U*LOLkxOFtI@pjst46{5N|-%1wJD z@4_~RmxiD^+}GTgT}{ACt*ksA1*es^c_i}bo(izGa{{%_LKQevYmPgFjyd)e%$aQ_ zjT$XNe*!h@4x|grW3cQlo7Aq5fa>`n%C6ws6KsO10tu3-!qP`IT*qeOCt(VQJkDEj zzI$P6RBNXB3=%nyg*qQ^Cd3NsYxcrUCjbPkW>QoG-n9ycJ6_l0@!kY7N05O4|wk3Ky&qqw0L-Z~rwU6%J7~Pjq|Y{n4LbLZ`ojR zl!Zm3-BR_hBPs~wLinJ3h5PZ>^mVSA&URwy0 znCXG}<;r>ozYu`(a1loqc;ot1-ZU4wIwskqHUl!3b=dDvx38QxEV;edI?7#IYo2Gj z{q&IMM3k)Jfds2sXmx-X30i2kfV)Zuc;e_v_)*8e6p7S5okH6*i_EN8ZX_sj(KHs6 z>Dr$EY11Np;ody?u6t!G!g30;hatOvAR)1D;;nR=)k52M4od6Xy%Q=DQu=cwh#J4x z0;@cY-|{x_N!7AHY2ewnoB%pB*^BgrO8S&$8L|Wr-uo&6hek+Bxzo>W8|XH$a<=~?zxgw-~+Zd3|vMIyU1lmuo(XBO)EtuB)#YP6zm zrz&-3FNBlKT~LVHv8+4!RSwkb+ubek$i+jcRgYNS{ac%AT-D)OQ@WizA_o%>-o51h zL^@L{96l}!S`w!LxgW-Re61pzdC;6sXYndAbPP8rgLM7SywHT(ZfLCMWmw}#)0s@t9;g4t-rpuyESxC;+z>u#O?Y4F4R_7MZb@|IU z6JxdNGD4NVFQ|Tb9mp9vs7;Co$KwxBj>@Ui{O3(mCveg7b_bS_Mz=enQd>xv76IG*#_%2$^6|ys8N3PDC?%^EA}`P-9Br){fljS8#{Rc zIcdG}q+e4iez&mOFjmHykbHLHnuyX zXG0AqN4ZAkEm`5&I4$0$lNYz`9nM1zZ4|HvAqu84X37)g<7}U#0stxkbhr^CG?W5LBgvP6OfcVx zaedx!P)Gy2l0*Ep6ZnW%@3u1@F*~bP_uYb}s_Q?Td{sZB8Pn4AD1K=?iqtWjYTaiv zEW9qFEx&fmg?sdE5jw8aDEt@On&A#cG(-i(1&YMon&j?GnHqW(LV1~zW#B5OYP*b_%2+%_3yG&%~Qq$ zTNJ97Czw~#Agq8V0Nh*coic2fj$cSWl&xO1t!{{)Z6ItnAOkTE4?8}EsVr@(g?%G( zG*-~eyW@cj{ATHOxJBxZXq3E2;R*UxArjVcL^MErt*uUYY{$-NJjA>4jQI^FT1;Gg zAXP~yHnsS!vywBv$D<__QUoxv$hbnoh%B!=B}RtyYlNxPTS`N@|+_Jm5$>fo|%$D$`fS8Q>{HZ_Dkpqa$oUu>0!HigY3yqJ-d zUl7*XTC-?Z_1<0C+R0J7oU@okEl%N@)#_oZVdYYdhkii$6<|UqiOwPXhk=Yx_L!dX zZ-)$*%HiLpZ=CCuEwp4$E1*onr;LZ;$tgo+TS2zsboISXE(Q**oZ>uVTAJvEn&xE) z1jNReOfOGiG%X1@abmz;js2t8$zgf>P}Tb0WhtrUT9raOnl<$0vhB0J=?|QCpE)YR z2CZl+fz)=m?r`%1@6f(TcZ=LJF-$-49lCw5Mp6aYzyd^lun~92yW&&r3+;b}PgRRo zLgP-`VXD32rv=vl_TuZUR4FMbUo0y&Xjt~L>tT7cG=m}i)GCh{&1U{UhfSjB54NLh zY{y}$q~gq(6;Z6G#n3`W?x{XjZ5zBtBoE-LQw@LlSA(DbT8;UQFuIFkWjQ|oVw;2h z&hy`}-~F{2@Bi$hqZ!pK{SlkP(jPnjknBFe{?7)+|Bu)2KQ=H5dQBK}-g7MpbZz3< zt+9rJGbi->f7CU0oeP3odfu2T!QNq{XA26xzWB7Tf3~io&+lxOGEFi|TkPr>FC07jDQ&kh(-l421=iJN^CiwI`~E8# z?~gyhc-&GiPdPjm2%QgSO{zMcZC+h(^$f=!@%Vpladti?u_Z+IL|}2Ck=BvG28V1q zX~?v{wDvBvNi*68bJI*ltEopXcoN0)I~$l#yGdl zDEe8f5=BErO2K;Mw7F>Iho7?LVC_TG8ws0MA|p3-pA0YL7lAfEnJsAVccq#5L+tJf zu$mrm!pPIW8daNQ`WYXuqJvCA%uK9h&2)+>B-CVjCbl-kJUd|l5Uh;Zd$?`ds1l&& zlDj(EqO2*UEMSVhiM_Mxb*7J2X?n;uA4iN0N@gojV&TNd#LaQ-VpEN{?~CPXm#2Bd!A+Gee z=Txvag>i)fax8k4B(G|HO+2QeV!50D8oK$x^@AhP{%h;U8nWLkeMtX$idf0?z!Dh7vXvWmL}P!m}@s5Fdf z?jhB5yR*xZiFu)MGM}Xlo$);-olo_qp4Fo(pOh6D3k|% zfr;NEe{CPn(lL;BuvRi67kbk)esT#|4z~G7I!F*E*&&w~C45H!qOhA)Bgu(MQ{xw$ z@Dv02>CoZY{PaEBK;041)rhaxUa6#~(;VJPF$mJUO^7$IU89cI*QPqX69C$@B?P%x zA6oM{bimfGTS!|wIx!{B&0~AvaErNIUDL=XhdeleJskQJ03r%B3wb<#u+oHifbdkZcS?XsVcQam7$Dm8ZJRol_}c!~Y6>mj8%&#hI~@>FFvrWQ%zn49 zG7wnHyGCzKeVv4|(ui`poRosSDyFN1wTQo!`4Itgu-YqgpLfftku*-*#~Q9-xHHhY znG0B5pt`!-P|Br&h2>$-3s7Hzpq;9 zhcoF4BM{z-ZvBrh-p{6qB>e7u>PM?kQW9Ck$UvjZSQNQ~qh=%gM6;y_p)&-B;J!Y) zU_m{m!=y*v@kU3fg$Pj#7^%4Zgz)3^d9@`|*d#uloDc5&5X8IGb5ofc|+LtUf@<{Pd9 zK4Y?lx!UjU?U$`}@Ol5}YFG2~ZJ}m5F9pUrfxR4Q%9p{7?<^x+2+-FRP<;YVm7Y4k zmQpUy-j{>r#w(TKhxkt${3-p&<8_&6FAwZaI>sZyk16 zDvi`roA9c{xs*&O3n$3?P3u@-Vk1@S(&6#>^ckuFh45oyRj>f@lb*%>u{?hH!B!7s z{?uBj4EJOlKdQ0Xs)rm#CYeyvrUJT8q8b?H^fRCgVrY-J3oFbL*Tsq0Ai8VK zM>aqh31S%#&zkoqC;OWK%Trfd8TXwhwBGV&pD;cF^$L7lj6)GuLv-BzLW0r`4|{iQ z-q_?5Y^;u>q-Uc2bCk@%0Ff9Wv+LL<1SinPnh>I^@rhyy7|rTb29Ru7AuA-GzNCt_ zI9YLdpqga+Inxa0S1b}z0j~ym1z$6E-_=c?I4^6`{gWZn2kKEeWlvi%Zg?U3a)I}_ zy{gb-^PU&i3y)n4D#o1Zw=K7{4+oc4E!c`mcp@%zeMdAlwi)ogkliFy%1EnR8arij5vnp-2+QrRCZdXK)1D2sYk zoE2cA%zu+c@>ogxxdg=D00e1v$Hnsuw5@Zelqe*{^_xwbY>lL4!KlEn@Pk-P$4mgcImWr>}U4nd`8QGk4f7^#5D^?5#6$F^`7O6~v^ve~n#pi}22|eLO?KRo_xC z-)lQz7&SLrd1zPd|1V1H+JdBjI(DAo5=B=|rO2sGrFpP@c#UV9Wc_Px8E+GtdWOhW9WSiJBs^2@hPP|`1I}#?3FE2~Oa$DTbRDAG5?Q8jxw>hty@i(@W~<9_h-LJ|J*Nxh5zZ%aeALx%r_p&o zOln6mE<>Xees3FnsehDnl26-gs+7+o$4+{Oi#0iD_!<)A<2|}EoruOS1U-x>?`pz^ zDKF}k^=pKRwmZ4ze$naZELrX-I@N)BsBivn3QfEb4I; zBaCpD<*5xia511Jz_J`BT-qZHU(5r`!Y#nhe1Zd(u&YH^pEmPHm15}b!4{|I zMeaw9`lS0FzA`#f5#grH&`Lc!vDkj;h)nmW3{ZJk>QJ(6U7FuJBWoN6shmsBpBN~? z`HP1Pe-3VzRQx$Z0q(I%mN}O#-9xFtHFY(10%LkjS1+hDJ(2Dz0Ra>h1dNU>UPL4m z2Km8!Z&)MK7G{EOJ-487+jTy4y#4y#^^V>w@otEB*8~8(3A7suaP@#K<(0ZMOQ2Ov z3i-RkH^7iOSbGR~tIX0feY_UM@E^(>E$?dFaUEFpV1xpKydpT>8b+`(jq~_v`Bs(P zBk=k9FOB++k16#grks!Cu~9>ik(!FEl@&V&MyQ255MbX6EWCwRh^z)3)j#mMY#_rq3+vm(aw8 zU39aY#I#{TPhe6RFf_KFM4fsxW9Tenh3>#fqE^TSQ&mJy4?9{Y(KBsvi70Nbt|We| znD(3&-l27}c!O-J9}8qk(j4@hFG3S9FO~zJr1=DGVx1L6K1fA^yz>T;M=?fXu!;=N z59;f7>niPHi?Y#l1vsQ4N3pa>SE9j#8F#XA`*>FVWh(u6`oeMB@bKzA7H-pK*aJCw;DZPgF9=h|HwgyOx#B zG^j|>cxTd*03p50E1WT@N$yxzKpmN{$D`uEZYTal_&4L$Qep_;Nv~~9< z=Iy>^-U!|O;@QVf63y!>2vvI;Eg?Q$P%iBGCLM8E0fU4`$@n;m0SBiRYNLk7zi*a<-Dr^f3@`x;VL_DPc!H|B@!*@WpV=RZARLf-kr2bVrM&ZA zlUMyA#h^}4&4Fk6A>|_PVvNje6d(J}H`~DQL!oV>h?NiZ)_T^VM$F7)AbtlO_Cpyh ziO0F%oJl1UBgj>pBTsQ1^>XDP%DP|6r6H2PKHm@Ms!Jir&+&w5nKCs?0~~`J`<7g6 zGQ?%T^a&T@4!`wNhyYg3!!5XCuVMf{?F}QIjW|D2k*WG@$emnqF*!dkZTaC8wUi%-@+f;Rv{Z%oHoA`Ljo!7U~rprPqN!Nq?-g#D)p?Y}QrANl=%pb2d+V$(kNAQg7J z1wGY}be!Br)029yZl3?ZKkm}Nz~zLGf~nj$r%!TI$vCwIg3*u-OS$!>#U+PnB<~9* z&V=S_eU%lgiv(F))2y}=Aj{cTjbyJaCTjj6l0ah(rrj>GbOG?7h@4&7b&l3k>L+wR zg_g%>!3iVj09Eg`P#J3YdX0zCJld7lBDANv&yWz}1MOmJFW6Qj#0-yKa;17nqD+M0 zAB4@1pdKIbNdO#82rC5S4;g%qaW{Dh3h*CbL?{IOTgk6D&wmvuJq~RzD1NqFim^rr z1kx;R0_}s&6bMJg9|?GNf&1Q*K(=fN383k#j5>IIG;z&<(I8y1%YCYI7j>t~MywKlHHB%b5nsMxCLTOcOgljwZy3WMu#3c!+o zj}_p%8lc{?=XwF&1gyJK)CmZ%P08)(8&DCugU<7cb4o>%)xJg4_L)%n;hyEQnMf{5 zB0zb!xkd&5ba~_4|DiGUKd0q?FU#>Ck5;EyFpS9w_ATm8x1vk;qc^#`k4}dCmHFi_ zOspGo;VDOcbX&2$n6GJu^88|htFC4oHfOQwHvvzIa=tZRO`7);I>Q!vjk)LeXZbVB zR1nNI@Amhu=RZ!%`8JN|nexBr^E-lS=L*KW`^Dx04}3UR#!x@2D|mO(U%saAu8OP) zw{405i-((&wiuoc;RWiD#Tj7{Sgp2Qg~`R71TEer#?-tsTeYbFK=1M%_Su{ zV(xL5CyP`Kysq@wL_KRQFwll+TD$ng9H7NYp(^gr0pvyWv^2gx>6J%McC{otSNQ;L znR$486cezCx9vO|LU7wN{`}1IdcRch3d3m>=EDgTU`SS3{dR#}=v6l*6+(&!m?Fw! zA-hNkC2n`G!m9}56}7wnYE~^KpWR@4bR25@(>P~mQFJS!o}L-uVDH0{bdIJnsnOK0 znx~m>;#4oBr%6_MOAvGIXD~GGMiec!$z)ypLz%w`kkz{i zcz&^2%4=xqH<|Yw7FifE!(ji}GS7*+Eae@uxb)Xi`oVPt+pUx2&Df$*<8g;`Zo6AA@HTexd)AbpZ@WVNEfjo#L>VCrPQ@Ed37UUl7j z+D07kK#Vw5#^Z9$D&NX5IX^u0cLHsX*m2)xPDcuA?bir<@SzK`<-4 zQNFCRHZn>U!6$vWmDcm|EGO#q+p~%<%8vdK$a7f!Hq}7FATx_sjIiRpZje)+nat`_ zPTo?A4Q*@iUTT^FeIvcL`Whk*Y_$f1rsHG z_z)FwU5+|LXl-9?Dk79vZq#gpbNwbLxScbu#Xh_MU(gg_3a0z;w|bqE*tD$3w%K`+ zWL8GLQs#N=BJRwyGkmXYZxvCn29(f}Ji<~Q`jmkh(J$z0Q_;b!B05m)+r&HwV~RLj z%U^-n!~+WFp;}%ohOU7u^FezyHSthv&f&sr?{$jwerx~z_g$O$>CW-!dlPF5oTGtZ zUw*8_#qIG~031|IeeJ4X5#GhbhW$N^I*dZMq|p6c5g-!s^nm3|11-{@@QW?_j%b77 z5U!;3GkUv*5iZitDvQBfR#JE3l>O3uL zw=>4rkIm7q_u~UWsy}fLhX(JLgNTWz((<5hv#hOu;A1^Pr_S<8bACtf)7TOCA&Oii zp0?(3Mi%KV-fq5J=v`Q6<~(BU-Tew|U}|uXhZG0+8v%8Me|pV6w_ifD+vfixyXb#6 zh+43yiDo%JDOv~T-F_qgqiO1Y|1*EFl>RSW1=kUa&CM=gd3C?i*#g}E!`^$xHKDHQ zqF9z)!9oX7dPfkX!x9%IVCY3cQv@M|(0f%BkS<-i(n1R;1OfqqRHaLRAb}9+HFQWI z0dLkmGka#u?0wJdxifptzQ;e{_k%zZKEAiV&+}A33&79nX>dWUGdhw=bY}zTc77of zHovZtZgQyz)|lV^$oA42F%PevW|tben9Zl=&js~CAJN98GOjp2ZbL$*n9Kb z3X{7PP50^N#Q$%}VK@fLOD4Yshl}pc1}b;9{bp;P#KU1n-45z-xgdYbE>rJU_8AsL z)Gp^Uu}~med<3>SruR%WWZLt}aI?xlS-<%Fm+iKX&fib!3OjjhQ)r8->8r)Ldh3&@ zpvl$5@xzI&rJ(uH8NKneiMBc>P(r(x%{j+(Lmkdngv)!^UGpvJDmQq!o^%!@3acy{ zi&oWNy8`i(AE*^lryL3@lG25>t+&}yDLJG64r;?KFyOh+J^JhMz1`zry^ud;FRDg0H6w67Osxougmmv-ASBD8 zB<)dgRN_mX0=FK`(+u~|o_;*X)L@YPo=>n*rba%Gl`2hk-@4h;4kSl@r@u@t(EXS^ zP+PmjlBwcK zsq~6rMxC3)REq5F(tVujO(OLitd`EqpWyD2IwN0+@_VQ&iS0Ck2{o#Md9z41G6(bH zFp(Wa#ok8wa?|!FrI>bX%F~NQ=jxIcFg-%cfh9QHQd6udL;EI|)n;8yKCp_cr-wn1 ziHHUXuijNfu(T=iO}}H*ExGXNG#*|pKhxMZO>9&C8V-hq_G~hYG}=QaiHr%bNO58M zU7(C$tpKY4t2Cx>Gida-!iS)ytxOM)P;qh5vuytqEBr|F1YQpB`@yf}6A}uZ?hXRy zJ1KH_2_Lknpe8GMj6{0zLH?(^CAH2g)z*R|cZXih(gb~9_%(G5P# z0(vvNF4LJVwo}0A0*;+4jtWtAXMc7NODI zcp6<3=OtYmHDUA_$rS$rX5paR)ntHmf2gz%4N!|!=s)$43t&-kAGl_j~XEDC0eepXbb0ZBPT58lig>}&t>ZNrJ%M{-4F-Cd4 z?7-}y!r9>%gVglja?)ZKslcM8!-Ouqi1dKbh(@u2ba1eHL0{gJk^YTL85Hw_1oa0r10clO%N_m95@4;QfpsbCI6 zrCuHQR}F~=T2yr+oO7kO%vwX){4_f8Khu)qlx?y$4Eh#j3m$&8ViJ@XljH)D@X?iR+3p#OS;-96a70U!O=WV- z+EqBW9KuznZ!-h=_EU=qxTANLjdcB@S`$rO&Lvo_(F`+I`yMru+_o4afcVugvD|Yx!j* zJN1zQGgc}VftO)+rCzumAhX#GFyHPrOP?XMy@l37y3zb(T}7Z!zRm#wRD0eIv)Ft6 z9#zBUtfRBTS=Nf1cQ3ssa%yew$W5(G_K;|F%^Bu+mkJ6?FLUI}YT5-Y~e}2}jyH(+1)97p&DK)Ffd(>RkyC^xBH8(_p%E#u+)=e&$ zzFIKoAFXk`J&#lQe>rz97L?Fhwu~C zHI3umTxUB5BS?mR9_%)+RoF6J8O|uEsh3-P998>hwEvikRR8$?c&>(siD@=X*;OZ} z(yppJ23TqlD4m7I0(Wme{ZPqJQua9w+9i;pR*~McT#N(tYV8OXQ8A|TRxXV>VvbJkQy;U^5B>LDpt#ck zU$%p>sxcZhIc%civEzH>0_2YP(r}V)Macvq9`3DU1;PhOgbdb5Lyskcc$%>AAQ>=? zpW!+=e&v(X2eAHXT7sucV$1-u5JR%3n(fiz+cWrZyi86fxt%|Qak5^~7T>@}8+sVH=netufvzwSbZcNy@5VhG z0Kz|$k25e!_R03rv9^bHY&j4gP*ljOI$OF0B|%R%?K_Td{yKIDO@HltbLHeC;ey|u zu|N7qcZP>Q6_difyO0egRBe&o`p{Fz`7e33>CtJM|f8h z0D;|}GGnQgkcmK#asmYMA$yi3P~&J~n*fu+)Kc(8(DgCTvQ1*zFQiL!TNUb8f#P4bxkN<=Gr1Zz&_w22j2onmtixhV=@N(w6UL1@!RQ zrOjhAD1dKFU5=5il(u_{nb9A5i~qXP`ENrV-aH!|JOlTfQSG#%*V*F5$zc$jV$OtK zikjx4a&Nzanx#PIZ?-Z%r-c&uEbaAVOtDv*Er|SR0~jlBo=!t!Gft-r=v?vfhR}o` za%J+sdp$oNalA8Tw79`S)!C{|Upv~wDRMsOWFS~M-pkA_m?^gqnLwsQ#+jb-y>=%a zz>?&0Hj0P#4wcnjR8&u{DsEbBlap zxp6{^Rc>A9UO8TnMYQg`J5mP zyx1P#k|UGW>^dX%j070k6UmCn(G^@b(>JJf1p!GurH(sN+7niB738xr$fr4&^;iVT(R5?y9M0VQoM8uw zu1{VVAavhlqS~z5Wzg5#4lPgyf_Qt8!l2qX$8}Se=V$288x-8U3ouu-r}kS8AKLADARDWi;R!cewp^olM?zR2>ACkB zbGM|$=({(Askq$K5^}tMWwf5hhlxQB(bh9FFrx4cE=hw&l55q+Uo(-Na^(^SzRXM$ z?g8Sa1eG)rhw*TXrXs3M-P5^D#U%+`#L{KaSeU}@q?eypNCcS#G-r(N7f;TWn(Ti8ZyJs5QU3BBLz0k6((rN2hkgu;( zH)PbAI2<0mKQb?~zN4;!Bdt~BR_SKdhGtfwRs51$uLf~%Hd^B*SMM(4F0A?}5Q`_8 z@KTz*`Ti0-i4(s>jYH*3jTWR9PmN^8IrkKuqjIb(fE^%3(7?}ywi`WJNgo%~3}NYI z{S<1Y_90$in<$p$V>WLvO50}K^6c`xDVh9at7 zD;E7(15tFnI~?DPkf$OTufG@G@zH;|xayQ%ty3ie7}@Bx_rf_q9|25^OUoO2lyco5 zQ?3INlS>Vm%bsDI37>;qXT&47!n$m(fw86_*T`i3VJfg-c}~Zf|9WX6k+{CWF1e=B zHJ9p-XUjH%>l(J{LbtmC>Z`@2%65oom*pO*Bpu@oCKI8~r$Sv9GcN-UC~y&T+UZGt5n^9O%AKc7>Yu#X zyKZX2KWtem)G3y^pr5?3V@cCfrAc*($f3)G6h^@OdD71&@PXCtLr%5Yly32O?LJz- zn4;TC_Dl4JPGWe{d*>xjO*V-;;W4(C3(Fa6Qj@b{|Is==@ zdzpK3Os0x~1~9GdkCy3Q;|!whUa9!@m3dTps5}lap%m0G>PjyZT&`%onN>yh^$mU~ zsBO5oNXP_vgNTPk_Kt`qg3T8Hf`w}2u{7$XMY=|=veaBL{Ff%=W!otW+b0~48zx9- zeXXuQv%IL58nB}EM57ost}0wP8{I=fagr?p9j9bz>SfPK!Rc10yjx_mS^nB-y!dDB znk~~f&hWvgD;b_M&7PpVPPT_aM;ZHRffmIOf1mRVX8?t+q7Cd@ZM&nHNkDNEC%6@4 zeLz@vRg<}ImK8)SY+gtTGSIy-c`QIFDxM-qC4*O)8jLfWQ#b5#`V|LpF&+BIc9Tb5 zuf4^rr0Yh#V#;~0Zm(B9RCT2J>@V|@h|nhew3=6^{p0U;V!}#ej72d}epHw41x>U z`SeB>%FvRV&b4LbWUzRRwm6`R&<_z2lJF0l#Kx9YeNK37NL4~@IXkqzegl#G7H126 z@Q|Y1aruPL#S1H4d>MAQMz-B+k$#rcRBu9coV>EcU@-~VhQ%ox>EsmGftTaX66H5g z1|jJ_;PqWl@rY3~qOL{F?`#)Omx4=7c^s%C>xik>KtXjJ*gW5mA}RHy*r7xB{<->F z&dz{aN?vBgrMmf`l9mS0va*VJT{XnTB2ib@AoAWJp$0r&zq(1qujf$6kLmR{=h^tn@6&P0Tb9RX)6a52Ud9_|Laov-%35he4h@!|t z_Fah*jKK(lmK^}Fyi37aWD*Y4oVMKB=o^M@fQQXo=i{wZEz}BIY$tyxo$A`0&i;_?%q=~Bx>|hQ2XL2efNL$O9qRr!+g5|pqwucI$Y#&C~ zcU7+}wTuUNC9p{(GS+^~y$@yUi*oyZmzAGA%7jmM#V5tSeBQ7Yf3$3FGo+azxR$k` zyVTjWl{w^Tt|;P|<#IGH#v|msT&aPo@~-IpHz+vbo6qb*R)yU>PaQcQWpAx!FP3f$ zIG*gJGt0OLaBTIsrq)3`>)O+8a!Ai+cehli7CjOod6n!aOPWbSaWa zl6&B48In(1CXGLr{}l!T5K^Z}bL=7tdPt2}Qrz&oCSL(nu%&LaiM!fcEj zo~glve7THzAgayRSIMStXL{xR4d~;N#;BVSJjyVIN6}tjIZ9xItct6Dw+^0UQcz$@ zBZc-?ge*MS1{>~Q&G~KmzDKLa_%@~GdZS^;oHHg`cR#-D+Yh?UA{nW4HV<;!Md%sG z+3GZ0SKEwiL!Uiku_+1yKBuVSS`#V6_PNFJ*2eKijA`i_dr4toRtm_}7Xbwtn~mv# zdwu46-A%e3%tsjEM#?lK9ta)e1>S9NE@40UeOgEMlVL*jVbkQbB%3BP(lI}wx@O#?h!JYh z+%IDPt*6Jx`~ARy_)%7E>0quxpbjAe?a*K0oCLHQ8xCPu$-GxP!%0gYV${V(Kre>* zG9)T(v>Q;i3kDp>IH#4$jx`IfFBj7WW+o4cJ(b$U{1hbjy*ZxV^eU}g|C}a1)eo#K zAeBk)nbrWHFMF_DcOIdV7HKQ})BbR~iPRSVFUbo@rZBHu;*{=s0nO)pMini-c-BIG zQ8d|JK%)eGI#QH%-@9SdKIt}NUpKF>R@(fh$ujQ8v7xb#>BS36j8jA1OGXT%wQVlh z&0rd7vZrt_6smSlnavuPs&Mnr6DHVQhZa%?Sa+B67w+l>nva{4t2*dkwp@ExyJ^BFI5dy=7=PYGXV$pZpI5Z!qPq8m=a0@kx_e^ilChInsbPLiNmlx! z1|j|=Q>a9M3uY0d`79+ijnk+=H|1u^ZuIK2BxrLM$+meExGLs6$ps6#yO|fKBr=l) z)inA_d@@wqav8jDX1agnHA)O0qsyo*UD=n^?)LIL@07)-PmSe~6~ekod!=yW;uRq; zj})Oc1Dv9V(EaVg+5WzFBTp4#?I|dDV7Ht!Y2GM%T8z+iuuvA*za!^?_x!RaX4AT_ zFcux8Jfkyxy1QuH#ykc<#NHRc1-hSUE?VqU z7#jz#9|$IdV28>&nN!f}2p)EwGq?wCm|hDwk=Bw-UodRByAV5U1ne<{WJ)EGU2}S=pH95n z=c<&zmt#JdR?(Ox`tkMGI*pmE4-KDom9wWf4YI35v^SbyLb@JEodH9i##)l%X1&QP z&v~+isZ{|>7ehjxsBP*YZeOXrgRAB!t>8O>ZV4n_%al4}bAh|4vH{A7FU@%9%27tU zXsEhukqoPS_$T%Q= zP81w4iWxQU@9wse5s{GyOfy(;62ps|^*FVhP_lseg?8Kv;oQ2H>pZtPI*@{5%7c{r zCIi6rzc*5}TrpCc>qbP~l#t`*edbZ-``e~xtff$G_qt%$V4AR0cx844@y0=eJjWER zC%PSBW11XWU}P^ck(UX?H(SotCQms*#jb;7&@HE%9KDtGI*7A_^ss2}a%POT#!aTD zj?S#N)#Im5`GJIfjZF8q*TDDL2|q8JN8?yBjdEtAj_+mGC5O2|Yw6v`cQlITQtEWY z^jmGg#sx94Gv$T}yupLsYAdGh3yn@X-g4zu9?fhuvY!}hHwO~mIVv2{Ai-6o2w6~Z zj`RV=3Zu*MR{U{_4p&;EJ-`52R*y5ju+&N8N)TX6Op4KW_c65Sk%D^kh%0pN1!$W! zst!=6RnyHWcqvsqOFs=Kq9vo{l4q{9 zfx*oH-e0W%<$L6-HC7&DJIX$a`nniz#^F?Fu`%lQBC`9Lo*}y#t8H1~pjwG7 z#6Iq8tao7Vqp1zM5z|D?yR76W)y{*r{&j>4aA|t6*?JvA2Mu(2`(9-9VMY>7B- z{(f1u!&+_=7VCW*>dq8Z>=fYf%@QZtW>d!w9bir9eTDSm0Z-OkeRJZn(wmSW06*-e zS?GK-E_m1nHSwF{qPUiZ_`qEwy?zb%;TqCLNZQWuyrb&VtRo)7Eo1b}E$mxqNNUq@ z+XpO>s_7?vrlBc*xzC`p>H(Bho@UkP$v<7bJxMS(0fE@ScR9ju!Prqx^E%qUfANfG+OJidDnVm~7a#I7OKc+Yt zR=`<-+CAM!Hm?yooMqi&jFYfXx%9+BgMO)kWF&v}(F~R-IARb3kPSrSHuVdEh71hC z)|DhE@~b`}LS%=TJXZ3e=IDCRnUCg6n_v~T<35d#@tBoyCO4O7csbeo)RFC3tJu;D z{;`_caG|jd+m*tVu{ao%r!YG?+7}$S1C-ZZ?zHkihd6$X6TZ_n>^eSd8XeH+Y2=zw zE);r!3Gvjy7mi8bVO~qEVv(Vz2W)9vOA8WGk8jAeYc`b2LG(Tpf1M%aB9&6TvltZ2o^GS zh2RQ{ak|(cV9_9JQMrL(O`Pkc<6hP4O#=RHcod{4Z9Z@MJ%?k zH$|o!jk(}NUSlW2eWluao}H>iHeg_;sg_D(>nq!yMRo)U1)tQMhW9j%E&c|V%;wjz zMS53tnCWK>ff^);8LN3Y{6;}Ahil*ZzEe@vn(NF(s8PqYmM$UKP}Z*_h|3pn>%&G3 z$y(9h+vlFi*UHvRT$t#{5`&8cbs99hnA;$hDI|6D43uX(1S-mFR5-2r%s-ojXt+l= z&eH;f9OZ)ct2@!h-I}T8g$GtbLq1?Z7`U!*nm^NQ!9~}KHb@#@ok{5EcWniIjyjfp zB&uNa4H#Oq4AQN6YVRvnyMcSz4q>Xk{mZEBgMCC(>uZ`!I4)BO;VyFZ8O9wf>+1(M zE$!rAAJ#Y02Ff?y?^@Y0Y1a*3n}e~#r8DQ3!S|A}+w%c|W!nq;v}nQBS=X|~-o>`? z7G+PMZI*VT^AhsVILew> zg#4ge7Fi$mfqXrYq`*eExJQ4{F`&5lJvm*!HYwOfb4R6P!&4&NWuS<)<91Uug*DyZ z@RKCnb07nWPe{|J;z&HFsS?wStVX})+vrrY5D3lFAt80v_CPsT^h)2IbGa42G8Jf! zWO=3$*VgbL?2g<0(>DWNW=6k>dn5;R9L?)10kmlw(6q8J(m9I1V!Zn4wQ4P(B6`Sp zEDnF3TQE_rEDRt(cOnS@FEdUxZ|GmyyZh<}v+!|CKgre9ad%l?zd;2-XLtDZB<`jh0gzl~@9i);rD+J-v^_!_SPccCKTtc#{_=QeRxEIB}ZcGM#50eaKC+&2(h=S`go~2v^N= z-48mYq%RMEzLIp(!*Zv*;$9>_r#oRROap{}BMbeY<5njf#ZK}5pc@|DGe%NcZficp zmTBBL@%hTj<@+aT2mfET0{9=0S~(%pLJhiqeE5S-;Y=*mZE(4hEqPvcptAR#PtSF?%M1A29oPNRq}$hB(!`QCq? z`_DV`(^h}_nV&xLXKeZzSAXUNKXb94dF0Rh{b%j*pRJpGQR3nGevpTCLqYNd-lp_0{n4M z{-4uZ|NB{z&wZZ%f)$hhxTXG0 z%P0}gC22FM$4)J~50#95(1jwZjvtm)uXAkFP*wX>|IGvWz4e~xLE7N_4y|wWf;Pt- zy0fKsbc|^^kcttX9-yeUQ`>2B7v;1*Q+uZ>iK6|3ZmvhPF;a2ucN_pc`4L;y(RF&- z@(zJ0@`El}@aOCNJhy+4d(iR!cH^)7e&bvIeB({6+H>})Ex()3O3SVe^`GtPPv%2N zKZvA?a+)1Sg+_;N?5F;q>rOHEz2ZAT+w%O~tX}?ZRuX?Os}P$7uFVhLHivx2v}Sh; z&g=&rzk&UvJi)d1cYFIcul~Ee5f4J&hPJhihAyR(VaK$MS{rJHdb-xu)`7N}$)g+Kt3{rpRQ{!jjJw}0NQ{}MY{`&U8nFInS1 zMc;q#KK?oS{slMjzoPG7@CN@JeSf~tU-Pg(kM3XRVn1))UyiCj?dT5$z)u(S*K(HjS{us@qo|3T%m|Nc(e-_Q;Ig$^(` z89LY)O3*o$zS5_Zm2g0Er7VYbJ+GnXpFIwqI6k!5dMDc6T~8w>_4z@EPNzCvytD11 zx`=PtDEdLicJk-%{5*r7_u!{3{PYJued5o!@c+BmD5Y@v|0{{>-#XO=y8fW!VhBaI z47@0~7xwB;3)?ule?5(poBkRscnd@)c!K`H?z_vl-?zE{`_rm_xL3Gz`=5^K@A}U9 zX$18NuT=>)i@y$K-B-IAx%?|9@ec#_e;Km>PR)OY_)GX79{zhm2maQ(`S-MiGYtO_ zy9hpEZO>JuL%669w&qD~gJi)7Sm3OfQ?O>+G0zqd9px#r3+GR~aj)`gQO)(YsVpbo zyPa6J^oH@hdAthS=q^WB5yD3IhHC0!xpzj@t31;pa+K#bV0qSy>eKW%*%_bo>AZ2z z>A?skR`9IEO)_D6PJx=)@_O$;G&1LM6Te0VH43CQkx|nsHpVKdY>731#eLSeY7l;| zw9&^S#W^h}wRUyRk1S+yS;L!mqSUldS>6I-jon^;Pv1tEu=pIJ)N+)!u}70aGEMxR z7cEP|DZ`1#*VZfRxb?4ciMZ>|(cBX3g6zFlySwPbS^Rphedr(W$u9ehku(G!jF*EC zC!BV2E_m}|5oH=F&33!UB>Yit178&pKC81#m7NJxeH8#E8_*OX^{J|uJ#f>n%ORKy zoB%3m#DeiEHD2xDeRaJO=jh<`1T2;nxQ*IO)ta!-5L((Ftz9NT{Kod|W4w+w$|V90 zt*zH5mN)pwB<=7G>Wzzl$eCUAncB_$aDm8MTPYzIyppZ#vGX~FS7p|GPM*xOHwReT zU-{%h=LJi@KRZf;qo^8ZL*W%!mK2N3sUYOoyPdOpd}htO*;PdwkP?!+?$Pxc08KU2 z@9us)IcpO{*w5NpfK8vH8g1sOlbcJwIR(UFTZ9QVGs`SuvoD7{pYt0QjY~& zoy?)-Po#Qey!Ojeb$sR~bLMHhHRZ#_;j`f0)wfalW+_63>Eb<;sEPjd{fR2Q!lppV zlSx0RvHfCH(3o^r=EEE=?5)MLO_mkXN`doaz^ z4djf1w#*ho(b@H$gj&60ybJcgmCTx}a#X2u%MpERYa_Dh`eqhjG^;K59Ac|;Zyh#s zw#KA3>0Xjnk_^&gThLOX@7*@Qk}g0J{6rvTF@$(wsE}aRmzsle*(k3?tvQ5;f({FL zwq}HOiiT8NEM!T+M@&U8DAqK_6xrXUd{ra3E>?Jpg?3DxyQwhMWGprYVo`r1XNN+DH6 zC#D9A)8(?NCR!}AXh@(FK>&yE^z@G9G&1S+-IWljtqb6dqifqfl1NXzRR}J&o5)MHER0SpXGR?R?S7 zM;~2PIHrQ^zf$jS9x`o7gnJ#a>u(;#<(Apo+$b*KZVMCG*1#tt)3oTb?Vc7nuqX_U z4`E@*{d)nf8yb4p3x<#aOXLc~`-=G}`2LW$e_E->GT#rn7jh-FDDb%RGb-fhL(_vz zqYhIawyBq!`!iTp>7^=!T$7V3l0f9Xwed^j`0<=8&#dP>M){k*UlT7+beHC3W^bW- z{#0VQwjt3g8L3k^PLmypI6nhp2Rz7u6^}L99v&`_0k71B;&?vi-X=G1L8iGP&3V0NrVn7Z z#cbaN-VbkFZcpZVaQU*mssoLVR@*dnqdBcK7;ZF=IR<>^!f{htxvB?S>6ysxK_cKY zjo@JZA9OJ`450Jv>TaJj(l5JMuWKCqpo@_C^@bOB^Q9hF`qy({6_8tMe)FQAfIXKO z%uftXCTJRHGf$B88O%kx`kW(ocEfGQHA@sJ?|=-l^o1H(qvUg zPV?E!g;fF|PkBGK@u&n1bx=lGIa3aP%T-wiFkZOUJ}c=pyCLyJ8??KSelG@HrdVYh z=Ka*-gmz&ww!D5Be&EVUxmPu|pf}@6)43ym%BvozMnN}TH9dH`l^P^6qkL^xA8dPf zqA*O0I(mUGygDwdevo69@A3N!ZzpA(Ty|Hc%lieEl2GfJKB389C988p`MF<>mKj#5 ziB-}RpDD`ldEDoxfj{VeIf;2fZkBif4^n;)nEs+<&lQ%#J7(_P-~c`i4CH+N95!xh zXqNHd1N(DM5hWD;%~I8a!@^l8)DE|Zo5b$Sqnj_^{Y&l#LoVN+-ufK*eQPo59a*+m zZ=_$A^aKb?=4pVgZ$XSg7jKP7fK z2@b~zJH@8U$Oyr7#EQcDas$-@!fl^>Oga| zkI1Xj=?T&WC6BE9=2WX^1L_?qI$TJ#UsR$oWHBfsqJIRJ3&hSO&X!^bmd)0g+ zyRuQSMaCskq2L_my@sM;a?<)_LC*%EC2(cDovgS28yWhYDDXW#t{4)+mo_%-QW{#m zMD+G_9`ux%(87pyKccfcV~S(A&B7{xUTI3>X348%^C)ce=n)n>92fCwQCsaaGf8Qg zCu)s`&ct{7`!*9Yw#5r5!qi`}DtE~su8Tp6TM{pi*}~@zd*=5=`zyjlFC^K+_+NRDle{$FD*=a`o*E5P&2` z4}kvtm!U?Fytx9u1u-w}jTNJa$h69hYf}Qadk0opUDqHQvp15gEvzXkRJiMm>YCmr zWyUNjL|_$pth6ZXtz;xy4Ni4)eVTnyf&-oZgue(kLv z$u|$K&Cn%2;)Sv#-JYA%i;#aN+Hibf?8b53N8y0LfW&eUuM{7h-sW{`--q6n*sqV{;I2`4Ma0an%AvAc_;HdiAnSiA#AfGox#;0}+A|}%!{)=(D{v6r9-vI9l zu3I})6xjBy3Aouf6FROptr<;Yymsvx`>^uHhAM-M7}lw&ZP4RhXSpDQvWnF3|4ok# z^<-?JTfYAxWIzs8k6$z-5q*jql9oku0V=r5UthL9IJJKp;)`tbqQH78;iX^v7Wc(B z1>&jdTg;D8TN`nRev!}2ScT%+cgtp`IuK7^a836cR%outsb1D!DFA`^Gk05iS6q_g z(LDvF?7JyB^R<2zF8H~1m24L zY^o3e=daqj1&T9eoqyf#y6?w!nj&{K!m|9DZ_Uo|spvMZ0;5x+&D3k2zN-OQ2jF2n zi!2R9K`boJhU12zl^C;k2pW|u3!yOi(Q9Ht7?!7)et*+Cgh(IeL(`mcb1QS1{{Eub z^jvvr@3RB}_Y*@`pDTNuU?0osFex_-G={NxSaCc-W(KeA$uAojgVj<(I_3=}%2KLA z`D=%y_pN>P$hIvf#+UNWBC4)X)wUMGLpKM;^lQJ?=7=BmyF70S#vnT38J63|bY*vR z?<w0>=j!iit?kdk1KAK)F-_OPO|zS%Oj-q(wR_)WcP;p{^?M!M-^83H@^= z#_v{&9U&4QP@98MdNFXS0l4JBQK@%X9g%dsXA|LK;X}Xv`9l3?dH3?QRed;+xAcCS zBt#IduYO?csYcOAXh$8=by5{`5)z1@C zW{9~Y4~s?-{zFd-cIb~VdD|B8_@}Sl zo@00>b6{@%L2popUZOl$FZuY1)pSS;b0=XY(Bhq~?MItOi$CbnM`m?Rms!@vax_urn9ltN8lL~t86Srkl@HDJgYI4A zv05@sSnb{WEx)`6^+|HK(Rk6=t7bj!Nq(n_=mO^d(Ej^3-N7kw)x`lD%CaiC>_WZm z>~YXMZ3<0$w&-`_EWZz>d|cdqe2wndE@3IpM_*#z%tCr2%?Jx5~{@zRl%uy%j<|-G_Ys|Gs!g*`LaNN z&^O>@8G^7S-ax}co-vEO%lS5el!$usO;rLWeLv7NMW#`whsa;MgStH$-ApnYu1s^) z;~n08R=W{(++9Uj3VlM@hw`rEhGxZm^8seLf5s22k(P~QyEWjhb9FiEw7PMh@cGM9 z5j_NyBe4jzsm(S!#*;bf61RNY4&$>5t@=5szUk!`YHMr5M|(Qmc}4C#*ZN5G{Wd=P zVUe+7x>xqxDujAqm4_dhgIVcbFdSN5gb+zT=srn*Cl`G0O{-yWlBMVT{N{AIy_+F_ zMqO9Zy*`aT&-SMT4&(az=8)qAyx|ZHf(%=7TqwBdFdQl(%NYVL5HTQs%-7_PMj88> zscmlyW&qvcQjoTU zjmWX)1IQMA8?#S3^P3g;+{EjLt;7Y>*S#WYFH$NW_`mMa)Yp`|G2);7l+!;`ryo(+ zawd;@wa1CsaHw!%+rTH(*R?)B??w~L5(d8aEw*!^Z4fpI!$rRRXv^_Vic50HtzkY~ z8;F}|H1{SYgC}YLEx*YF)TlVV;DEr!)j0rt2jRTsL+n?*5`ZV$m*KWd`=P)mthfdB z?d^IOc}{STQsQFh<*HDT?hyC1tR?A#!goj)>}oLA@g#a1KiENkX`)r8&l8VtzjW0~ z8+-5WJPw7SM-VI&xEGLjTf?@?aB#wrfovW43_C^7HYfzw|3|+m~ zs7qsYJ|O#cUAv}ujCo-#O6#S9>xHCq(MsXkZ!$Qp0XUb9l9FT7CZ~|mscWe5PQqp* z_vEtFK{WxL=uDr=!?mJv*I&*bSsic>wzmKK( zZtRKdS;mXOJ~fo#h=h5OBdplC#*s^Ucj*e+4LJpXQFVu0#bu&o5hzPTkh<;u8y(TH zIB9-h{;fvjrF$B37d&IxhKAk4Tzzl{f^BBI2;_vzf_6T1AE4|t+GBv6s&E7a0XMym zI^oSZM}5Wq?~&Kwai5~)?diG_ZUf8u-_TmTa&j`lmvMMkS4EL!0xmt1HRcxLEjG;|mdQE&7E!w$D+&H%h79ynBfCa81)yEF?@;_A{pB z7uA4+*9jRaFJ?IvEi>8AC4FDfalM4(Rs=u1qm(H6{!*il1LS2aX>SH4VyItgc*oZu zC6%(>sA?4$qH&{ar|a?tZytd*vl|Eml2f7X?lS_Tw!^zbMJ<0r$IOGd7OQH1$3e&2 zU(CLjnmMoQOX;z+6JV@+sTFA`bVAKGa=NrIE6&^q({qS~UTYrnCWVBxZz(>s@-!IU zV^^f;oJ$()sn61DFsxGi@-|E8b;P{>#ixoj!0;q8IqoZh?Sw~A9m?@xWgo&Y~E@EL*X{X$x5Gi(&(ImXxp*JY#(;S`J%X&-j zPS4eN4R_?MD8o;hpZ4cW3&8931-{FEe(E-b=1(aw|RYx=1iMeGB zoftxGy9?U8>0_ruV9|$B|b@2nH#*CBLR+< ztp^8DgpfYmmS#-;CcGw{drfyv&o7_cw6 z$hFfV^uc>RKm547V2cRBrkQVtMs*!z`4N5mh4L)H)0yOx>-?b;z3|B8Vb!&X3ddKC zT>L%)vFEx!7Y~SJlr&DHVORZjRH?s!Hu`*O#|A!TjB(&^=4dM zj(^Fwy7wh~)g5+BDDPom)(cS6Pzk3x4$i{GFv(oOI9VZeuVn4xx(Rgrp=%LR9hIo9 zR|cHGQ1(Ycu{AKCBFGhE>_5ecq#1Zh13S)3nr77 z3ujBd+%T76LSve96P^)W_JPZ&yZfa=^1d!wU(XSG1t?0dAu2M@70-;tpqDtP)R;9&Pi zVa6w$H;D%b5fxJCn&y>kETOOcVie{EWD{(V&96C796wZ4yt7~ipy>_Ep!TdxDf#e+>7t+YdE9vk2G(7f+CFh#) zi&!^stEciVNo=t{q|q6%zKf0@5-R88JX&2w3hQk(Q&V#?9hW80LVivnIt`-hQMq!9 zesj&WsIV!ci@&6Zq5*is9u7|3oMu*(shQtHWCA8etFp|hM{W%3q4Y2-;-)S6uFYxD z`|6acC~Jo5+=Ywft0~)sj=zOowickUGccy4uoI z01Ndmf*B?^Q)v-JKrECvf?Kb{bMi;cDBtbi!d--Ag=h8{T-vmn(1G$g8{g^CdiTBj z4=m@LF8(A!uR35ai_Mzqnvb$B2uMm4B6>9|Frk_#K|W?ufYWVLCx;N>4|~FWpWh&|%DKGS(q_u^80Vucq&@G_+cEXo zSpz%tl~zU7FCPo>HcR`OA$6CAG3Z-ifHuKxpMQxv{vqy7& zx`*wOIw4o?)>Oo@+cMn(N8yeF?=qSyeN0}Vwb?%*YyxrnQneee6PNWNMy;H&AI)p$ zo79W*`jQqddP>H^l5PZ#brWLg?(-5^8n)Xr*4M}KGh>K^4cw{`1Y{a$Ep*sz6~aWp z6QR)G1KH&Mhm5#wCui=nx@^INx${HWH)5VG0819#SlY5Pafqkd9)P8+1JD@Fwg?Sz z3fW&{iweN17W*4zfj($lmI8AeO#=s99I4h&kNSTod(WUI+wgl36?<2@ASxhDKzbEK zYCu3jClnQt5<}>bZoxvAE?t4p15%PeAc-iTbg7YqBy^;NK!AkM-py}zXaBn&c6Rqm zCLi+5Jej*(_jS&>&ta4}U4P=G^`JFVSRwcK)c_|R+JJv}fYT^eE3gt$w}~7<_xl0! zT{6NC-LSZ*;K}KIy^YXc!0b>&dH)k1Ic#EmFAs3C6yiU8!^zW@_%`s%@%n;af5xi{ z=6|C(>A$g_Q1`I9?9aBj<<%3nsXajnY-e>gjuS4uFK2Z^<-yA}I%Trtp{J`7-TR&C zMd{mm+rFm9cfIf@zDml5k$Pu#qBJq?Q4tq_))-pM&j=VA1PLJvVZ4&t)N6bLeC+wv zF9s+UJWVs#oQZ$_4%JgBcEesKe2P=b^24&mt>$QTGr0Aj_-wgdjy*qd??o~gu#*Rk zs#;OYE-^tijL<3VW2$O}o3O%f#{ItE_A3}#=d!;~D%+TiN&kR`t!80XO2R>g)O}4= z8JWPe2qV{BC$-@f@LvLcCuizF7rYk+U3-?>VMdUJJPA^t7{5&tYq7l{Q&_IC)vr>J z{*SiP-5JG5aF_2y_s|H3M`JRwsgvLJ__iV}6gmj#A%Mg}`n^ADS$BJt1)hHHNS?Qi zoiw@jP2+|C1)ivXHrYza!d(IOs0=%UkAI5u5H1QeRBrfI)Uza9!qet@orCj?<=vJO@8-oNvkY>-%^Z z%;qTMG=G=PjOKfmfT-rdW2>l@1?Iyd@O3+hM$%wy!PbFxaYLlldPE6^LKc4K&A+Pr zHe5(wC@-Lq^`+(5+~A{d;o-)H5eJCYa-MUry~Tb4rqS(U9AlXUrf@`o9=A|%RL4EmMA)KNhqJ}y(+AHd7;!(iPteT|CQ3q8g>>AfKPLP z4$d#NRNJHT%ooVnaB3iYutVVtNww+euFsmE*c(R(0&+XcDa#X$#`6(Q|8dE1T%b_) z-jOT0(jl2`v}fC{#0XhZXfV;CQ|{QF(l{i1%~Za_XwB0?ZB6P{fM8y)#K_J4ug%h$ zV%%PVi_Z17^WudGRv>TMKbEVil`V~Dd9zDyjmBtgz*i65E8J5F4t3L9pWiM+M)0t# z+u;w;>h3-bh5V*YPFeR8U+0+Gi*aqKD!cW&IfJ1lWd~@`e_S~=LKVX)b|DJ|+pgOW zs{=M9+tu(dHj)2+O?Y1FMM;A$JoPcYTkik2CQykJGqhn~5j;+doEZj>(-hRUuH-x8 z%_SLW7><~u`!+f42B)zsn%YjC%39u)t$5qUWGtc0m=&+jww3fA5MSRC>3{uRco^c; z`VZe<9Zr!0MeKg1+G5b2JJHt}1ZWFMsduI@J)p{WywRD;0Ud}3X?m-BMNMRtYUO-` z#(+olev>B@^K(U;i*%FJuve@hxbZ+Vc~ZD|b+!>e?Qap!j;Ns0SNju0<8&{LuGJu3 zD6HMyv+ah8d~axWj3gwQee{&#QG9SgdDY){))E-%7NZNIkZE2F=S$0-(W0{d>PW6S zg)_vRh4was8PSVw1!$Cmu4^0L5I`s0Sng|1K_<_qBiVj0xoOA5UpoP#hqJY)6nt@d z{2r}%1%Y}Z%@~`DP(dtE)#oAZ=F1N_byY|9`oB4d1=J31-=O6>RPfL{dG1Tf4el(p z?%DH}%l%Zt+WpK``lgH$u;>=mT%LtRP?#|R_sTn6#pTj~PB{nlL-S~GxYGgg%CeF8e(@m?iQ6mw6&Gnzxg=EdK_yDm z6p6!)<%YPU+*GR!Z>5AuWJ#a?JqtI4N~=z&voz`snupz1ZPteOMvMLh?Ls^6U8ixQ z>ko3;;3s+%uhIy~{$2nx~ z@oPd4tO=Tq)V^Z^V$B2I!|ScAXTx|f&b|E~#|+Ib+Eap;E>1?_vfX2>?y1YVL>i6U zsY7nHHMAaf4HGq}w#YZ2&#ccKX;8+WSX+mbJ675$qSD1OOYX)b^SR;wxQ6RQGk4?q z-N|EtHbd}3P zH*+H#A4>G`8&HnIC6bBmhLE%$Z@124F6I74@czrro7CU! zM#1Q{P@ns7(hx82OH^^D*b<9%HLBJc%KN>c;IYrc2iBswk8aO=2vy$Qu>C>`SgAWS zTcuI@xvPw|*^w;>Fq0ha4mwdj+kblq35u}yY96V*iEhrCIU9>MfhC!R^N*Jy}6d{IV%v`mfm~|68Zj-Z+Y$)myzlve-Utc{em2wbHYJ-DWiI#STZ`aCG%? zlOm`(memh$6&OxDH}{E!hj!?Dqv+?HT^=iZElUsh;Bb39ccpIzx2KQ;^x-HKf#FL` zo+2`A87ZjV;i~3Y5S)6|g=7Mg>&I2ezbHKZTI{(*mC}Ok;Yg_YxV$+Xbx=3v)Cu0O`N@BI1+8$sB1_1nS~%MW?q+^XI_{Z5 z=Ev##9^I=){`FXx$)DLAu}3l>(M59T+q{}o8RrQ-{O(~*Pgcy;Ew=N_+O9d+LQtVr zZhU5TFxmLMwqXlJj4{~%UejLsl}2x5Q|^32;UP0`xhgOwyMRJQ?$l0KwS|yo$_Edl z?HzCgP*HriYx1{o*0@%pkkZl*cCF`#UzRC8{87%;=k|BGv_BqgO42TeA!f1<+UAf^ zA~Q7@%AT($?W&pen5ra83ae8y@h?0XQNDCnKd8bb?2(0z{YJArWZ1O*lK(~f$I5@a zatCQrAu+{J#=~0A-^=b~GZy18=ePU5)%x=Si8-5PetBlJ7g2ZcNstuU_EX2|{G(T2 z+XV+TW>seLX9W=ji2t~tYT5lw!=R+@+XTCqc4@s96_RL0t#S`w$q^seR z&aS^C@~W$K)tjdR$2`=hRKxw7`?V<1+c9 zv$r#e3v34EKdz7h%DBbqYfE_|y@#{!77hHH(^1%nCOv9uC~{AFT*#!zew34Y0gYt{ zI>s6rCtOK9w%76W!bPrg<7=7e=Jtr4N;MkBKBaKbHT~ll5VBgQ@WV`Y47ClahC^s% z{f)Cf)cG8QV#7J?5c9JeD+Dmz26N*y|2$?9U(pE{eALGm}KI!*Ou1)V{Fg> z)0ezfirc6xqpdKIBY1Eic8|Aor)avlHpiZP^AZ$^Xuo?+yo zp4QamwA;Fy4dYBR;__rBZU^7R99|BxHrs_pEENN&YjkKH#^J_J>U2W&=T!s=n6}^c zkr`L!s`BkK(@*}jy43Y&k*WIzlw60gQ2Y#m`Vt9Mcu>lQ(K(q)J%If_vfj+#JE%&6 zoO3`0NPI~gadnAx?n#`0tl3{nG48rSR-oyC{?CBM__bnA^sijzJ|zKL+ca7jQk!Bt zKIrC3+ht;`fXPW44`lQ5VrUuTkeG)h5pFV&#y%S!Y{wY#^FK!DCh%n-1mR3%L z4Jd`O9jiE@=VpUs%QD;}ANPfVfe(*%GN;dLfmg!n{NT+Eo46qn#JdiPS%*XabD7xV zt}9ssnzJhDR&Ke`a-GqN;Q7Cmk|NhRPQRR&k~X2QsUF_mQPNy|?+Ua{7Lz%sAX?37 z8wsWvIfcG>ZpZ!ULd3a3>84o@@uN-;T%uA&EK7~eLIWm9Zn?j5T(?*@;j3st$qwq7 z2Pq4HO1YlXPBguSwZx%2;A`4iVPSS>RUqlF49-0-TX78?V>%=2`W0nTAx3^QPYTPI zf{F=R1us)n)|mUc$;t>=Wt43~3^d_l8AE|qYZ`e8??r-lBW=!4{N|nWJ3j)I^L~8eld=V{BD)7f0W7z9?oavND zVR7!5Y={Hfr*7uM?P3o4T2xy_K^ySTc*T10{TO_d25q|I>B-l~wr9~$*{+?LaJCTA=V3Ty+^bpk*l{_5`Crhd+Y8L zO~P^G7M%!-iD-!(pumEUC*J96n&~`J3o=-A$q*nyl*`LJ3b^JcCJ-<=(`fIzw6r6u zt&Pj&oD|NvYvC1KRhH=yAl%^E)k8jL>~-to*s+7YBxR5>B)GT5-Y3(X$Jnu_{!D59 z6|T84vnvS!V9xf=z_{7$kIL5#H_zPN|D}r#_7E z;L5rqa8&W_Cldj#?i{a5H|12k=ZzCu(pXRm`8|K}gt4bO&edm0x!ig?{V_vGwQ|T_g2tN`z4738Ng{ zwde^;6#e|c$S=usjNP~93FtygvYsjvk|GcH?|7W-Ljt+S+|%Wi*iq@t9~JAD@83@k zhzUyAOG@JJD!fiuX#QY{$@u(r&oqoS_s;W!MC9Lz(UT7=+1X<2x8fv){7Re52n-Cw z6cx(WTvrsn~$kxy!br85=d0XB15f#eq`kS zNt;}y*c-KTO}Kd0yxH!W_uvNq55A>x#nH0Vx~Vra;~IC?B*KOv6el}dNxAywWyJv* zw)kXmR^`O*L@&dF3OQ|eV>ojQwl8G0;UmZw!xMZK>$w^`aOWB7jX4B0qS`mogudJ@ z`iTc;v%09KAe{b7^%85e$P13d%meYWY&mjVrlnKGZh6$5k$Cel>YBsf1gjmyS9d2L zVpFd~VNMV^C(1BGOa=-i_;-kF??ChwCAL1 zp2I-PT^}Cu;lEad9BNkx$T`R)Dr#dpIZ|JtJ_fNiFL?NSJ!JFTN3ovc7d|X>85~v4 zb%PBP@P@VHc$E>_Q+fl~el^>EwUCmemm{^4KCNb6`4rQZb;=VIa7T^*LStXY5gtRy z0rnF{t(DE6D>D8WqIa^;zLacycVH{F>9(qvMDSKaOcY`hW)E66i@x>JPQEjr1-pCq z=5=ra2c{Ez7!A!}D7^!y1%3NuV%cW91ue!8W=Ft~1+)pK2e8$8nKr_~0l?TIPS%_{yYyqAPvG!;!7c%P4*4x=eV215JJ>?WKG}SUiOpqQN_t08qYj`N^vVC z22CE9fiLw86A5_BBrq};hKHn&lMGl1WM|6wO2otx8N4~XJnyJ0`O?_nXm5pS{4Wpk zSx`!&c%fCk&7k)ffN}Wb&+IoHy8)RiX|(>8HB@0P%`cnLayfGp+R71Lcc%pq238`V zh{RUCc#P2iqJoG;FdR$OlDu`>1Lfr@Pn4hBly0sth4~#57_j1LaS6+4@i z$hftCz-nG8((}5Qz3?9Lnoml++nK1cvwPitK08F=@?bI_GNhA~>Qk}k+N<=C-vTOu z`2O$-R}wCF*H=|#Y!5nLCy&L_?pajmcoe&Mr|rBE3uj(7Tkom=>jF>#it&bc+nr4+ z72aPqWYYsx|{2W=O^a|mkh z+}K^uE!KO+$@iK@sG=aP4o;t11^oRk@Yky&1HK+~?^fid8FLRQ1JQSLtz%&8SUFxZ zmYG_EA&=KZbce*iU08LsO^{y;I8vbPefLG-62X&!ulz48S6MS_Wwgp>GFv&wc>rT< z1zs44;O)!q$S5dcg@N`(4p$^$V4n@yAB?1jkb2o2Z z{A}28>r%@+4yovCk9NiRG#v<84nnb4Wm4a<3lI@(C)e_YEDlZoJlOdi^Txq^sYN-YbPhY0>P+Ip> z3L_29IL5yW-qY#xb6gm{C<;`(jzj(%c`Z>0xD{rP9jwStd(+`s< zzz#bnlq10%Z^6G)?>@IZ{(Z2wP*#S`8*Z0>ldf-`b-0}FayXb{)WcjDQit!7fa{S4 zAL@*+*0ji&=?v&@TKnZy6)%+ZlupwF_wD!O{?WbhO%87r$~Pox%b}G-)JGIRZd400 z_lIH?n937B$<{BJn71<|iu~&1_ZF97^WDmSBIUH%698x?OR2-;Ueu%qjt@<=Hfag# zzst+_B?msZnm(VcfCr1S?MMqLG7TAZ#i6023Cs^W*0KjI2AH#MC}*fFNV4B`Fu#p5qYUAotkmuYRv5FLUuQU!5S2nll0_4?5Hqx7E|o0k}n;a0z3ISiOU z*dPeC_n!lH+}Kz$3twp6{Sam zX;Ph|0E#sJIWgVZZ`XN^py3^G;R0MsscO*I3RxxZk;~5&mdCA!NlQ#lfth)mmtyxzVu<02# ztgx0Qh^n7M=$5-OrZ(bL$-uld@r)c&P$h${8Db5lFjE^W*XWInDk;RX(`BteOgW_$ zQ0`V|ka#F{J!Sb8fJpvfA?*94FHP){Aip^5pU-HwV#ZgRcnLIwT6oQT8cG>fC<#BV z!#ZwX-jI;3x=^z;>O8VDTVprJF&dyaC>Jr~)(wdqgM@oKQ6ES z7q(h1HxmLMf15OA^Pl_6eI@4UjNO^BxtS76#Y}ebXht1aWt+6H<=_D?n3kFG-|?<& zvCAtjl?WcTAgdrsi?gM@G+{>(NdHN|V z`}~=Yv5BYLRckKp!A!$D?l z%lXB{3)B3PzgujwvU8JhMk_Hy$!XQ^ZJ~sS?q~SCxME zz&-8+z8qBjz`U*1T_FkM^^`)>tGkx8O9>9of_3(e2=-j5ASg7o2Bf8|;p2QXCYrYa z=ql7dPb!Uf9o2J#rIlRMSVe9^fxl9bofW8wMfRVMu+DF0iRQ1=P(HuJy8!=6pfIsZG{6T4@t$hZ_A`Bt8^ao*e)l9Wgy9=PQS5{jz=~C1G z;Qyiv{$KjT|A&kH{~vCG{r~^T|HVU8^zI+)lG2#ppojl))qVVrYwPBHQPBS_;`x8Y zKA#E~g>!|f@bMg3z|{RTmy6y7(;_;A;H!mB@sqr$gw+a9fLW#KYrm(~n`_?(gD|zR zX4+i$7&y;)9Fy%B|IN;?khnz3(ZJs;EK2IXcy8yI={o#idm%?Q40iqbUpLBM zfwwq@&RC+^_v^3or^2T^B(DuI6~LgmOssC`f#0M}#c~J)pGV!@q=BC}Mv4tJdEdG9 zXS?66y{6P@%A0cfsO9BU_}`7p$$#^XTt~iZoZqz1AGDHyrXvaca0N+Zx=*FP+0r&F z8jXpO!~ZP7X4X3I%dT&i6;$}tQ+(xk{~3ok!;9PKqm|{>y0Fj@i`^a|bbK@B^>OMCz4NY1MEe4X{tXMYJ||M^=V#xqinmWV zE7g!ntly}8G8Mzx=4G&V_wejHp1iC|?L)rn>%o-%ZVr0nrxX(ukDd+uv*S@Lq6hqz z#aMwHl&S@(TqcoTrS^;WSc}D3TP`_X*W`kA%PY;n-2330NeIS}`<5b8hQyTY$E9Y79E;pLHP>xUUAYsYSwFkf!0bE0)v{DZd88M4FL;`8qpT^9412p(c? zC4nOW>n1_ha7C3V_3;*AMln--XeuPe-~(pIA_Njq=CgZ_&i^5n8AQR3Ew{8VB;?f% zn2~G0dd~EGNohMRT*{^i;m_EcA5K?A+e0Lx_7HBF_Htcr9QP$wRGqqlHXH^iAm=p@ z!hcO)NGc;uw3n~&qY$1PD5;dm90!O?@QxX%r{d{l{$Iv2Zs`gjoNXE^_4(tI0#jvXzWC!5hW0rE z^b^ZBburutd6|*&sq&xx$y+X^a6!cI8}ipBiQ==*3s5a_A#C|#nonxZE z;~JD8XV5|HNb?Qw4O}jCIqkRST6*DR(VXm?`$w2B>;(mmX`*H_?CPEo(iZ}uV-bTU zQ6UWFxs1^a3Qe!YD0FBEL&5{Wb#HLI%_Aklons7=_@-6d@wR=_1cCeFaT(l(b_Pj3 zCtcEfb^D&~-fklkAyiy~9prqNgGwm|2bITwkfhKk*Z$5OudnjCDoE_8;n9PTODi%b zuhbmnI&%64?NL+^73l*ksg{%^6mclkAnMv;DBJD8RKW`zJjWS)9w3Lf;XMpRKeUjY zq9hfYLtv#~BE0ac-}1&J$>`bVTapPGmtH)zH}1Ysud`5Q6NoSPkBi|4BB6gEAjnCx z(4_dtb7NhY1CC{x3u`5V7ufmqmC*efnup)uG%n8TTCpoRjWr(rme=u?yV~Cy z_pfM-*;%%K;#v-f*Q8?bng6rktmk9iQ|G@J^8wxa()P*+@S;BlfmyBVB|i^u5^A>( z9;|KB_yx$qU?}5o?&rHtUC-=fCWylFYXR1xflBc!{hXvFSv`B4F_>>izSOWG=dS+i-#@3$#tDAsx>VzTQDZ5|(;1ivz%Jq` z1vKOqTed_MAaQCdnHmJ5L!$lqs%!R@8#Y8%(Hvm!qpJBY!{EjvkYY9M0#T{%OLy!_ zT%eO0b65MlEHGBN3X~CdlaP4~!Ab($uxw;I?0x|gJjU5zi()`odDFDaKId;^s#wci zI&e>vC|}07JU9VYGI^CMlMFhUd|%|EiV?$7Ii6$ru-V`q`dXu_9F7{Y{6oZxj^92wv^xPVuF&q!Btwo#H_a3i;LW8_#SC( zkRR(dT*A7W79E3$x#E7WE+89!Dj1=UeBLrnKRsIN(0tbG@zI<=RdwWo&eR^{;9_(7ngu_{jnasf-nRrOONTB(Fy125+t z@bq~vvm#Sh84=ynYgZPWf-9b))13Hq>dy{L4U~(OpdXGT%;k&Yeqvm;K_mOACGim7Yq)#kbIw-0_9*!Ls%;MKvOuoH{Uo8% zC;SJ_`4BP9Sz-J5(zF!${DuYB5KI)b91~j!k63xxykDda-O&3vz^v01dFlR0Ey(rn zgWW{fU9we$91>#@y^(*oU-S5`M>p4zrT9#F`+U1B&RkI4MK9}u%1YPB$dzX!<|Bq! zT}B~x{nvwy6D?k~E|Zf#RU1e({_P?-F~&0`$*lfsI$`4P856K`;r5aEtN6~CE*<~D5FQUwONr~cni*gYSd6stf7tIRyu;BC50Y!tJ>!0@y zF~lj8N{QLC$75voGkhv4C75-bZA8EQ@JftcbFyCSp=dmlxuBghESrGDU6#OBc+c~n z4d|da2XQIu?wWM~hsA{$Uizke1ciJMS^J(Ed3*if zU;!UUaJXz#o#Xa$=FKRk?d=8N^N&4Wwn?pmlJ%V$x`x@$bJ^xaWxK2;1{fg!e4Ybb z2KckRIdEOUu7-|kfagp#BK((4>K!P{JjQ$4(Ol-2ur-7oSj8(`7zhw)F3y{KTgDu# zb5fzsrESChNgFe4K>v!07Y;mQ(lll3-WFcR;KsJaD&2oYL=NNgghSg)yb3ip@jaA1 zHwmK1=i{?Hm2UAI^CHfIJs?E6)*hHv8moGSg&ise>=%*;5=_=Fka+xQlm-o9smzA5Mb+*K){W4YFOAkk1lm3}Qu>zH|OtRO|Gj^lV z*OoX`SWwvQ`pQnPd&|oTr15$7C!%f@!` zsa1J)ympv?=(Z%)|F}v^X&6H-$se?nKX;LZ)#a0B4=;DT*QC)r<%fQJs}3tuPz2Zl zA1J*s_E*v$vi0d^K{)fnlDOW#X%rcd)F zML%sBRZV)ZY5S_KJstm?xGe52(-mK()>Y2sAwGMI z%aG8-8C?P=84rRV)bBc@9JD;_4%@EmpV*gMKgh}nfg6QYTnn3Rh|8Hv{KnTHDAqoa znDz@MocwvkSsJNfyTVtBwe=9~kzEWJknsg>wTSzJ-y%`C?p{qsW^$GTSl7M0SW*6uq;8#cE&)M!4>tQW=VKdz&&m~{mt z7W&5rcValWwLoZ@GP8=ykz4)qA^2v}NcJZ+9{}qo}YmZp$Za_sj(PJ`FC$wY$`kzmEFr&%Vu#t*Mmw zk4v7p595erb9ufB?itCImvFw@#z?R}uSd!b-MW6m2k8o&nRRNyG-3)JViiH}$zoED z-_IB3KMohF#Jw~YxthRv!c)4g%kt3vZ$-6*1vX^g)?uD^CsFitn@;M>Hv+2XfdWWm zzI!R~SHfE{zH|By)Ne|HFZlbDKJeTgwdLzBYvTaDgNC~*S=kP^GNp#?U0b3&dV9SX z1Po-N`fsk)dsKh)?x@@Caj}iF<_jVZ&pusb$(}u5XqElm$cFXu#^vOUs1FuC{QV)+ zyiEMPncR98%%*xM0-CLg-zvlEZ1aswLqBjt?f2BWHXpr_qC@J2jb2WqIo>pVwEtV5 z+gM;uxc*-ASJY~2P|RF+8TLweWL=;KzzE$MitlmZm?nm^Ax}}+>$N|PFs=q>8yCvG zD*3Yea))I#hE3-fER#95u5;zx%AN{HXL1EtqqPzqG#)IyKqU{1bEi75#_%R6-$tcEI_zdO=7*k`?N`va0`tTZo{#;xes_BIw0Maw+DB(Cv3KcF=fe;h7E#$T4$*iy z6;z%RiYgkij)SOO(>~z09aU&E@Rln^V=x#r672mI;NkiXQUIFI$$b0ux90B~c0GYX zL7;9FHKMezpb6wu?d`Fe9-lB~B%Te{uFKuT(e$L66yAnI-W8^E=(F_Ydgou~XHMP7 zlFb5kJei9twZhpp@QQQ!Uo^3+loVK<$%cISI${@G2Z1aimUAPA@+p<*p?`DpV@~vm zXnU)3kt(CbqqCzrCJ|EazdP0zK}Coz4RYurq?D{TJ3(6ybYpQpbq`# z2m}4tJ1DA+?msSb^eCk0isab{g*<6d z$w!k4UshTXK{7rzw!0F%jCVBl%I-BOxT;N6dUk)O$y$>`-$2Wb`SeOczuBD2KwOO9 z;{tBJ+K$iM*Tx+_{{Haz?8}uc5u6K#RfhBS%p){Q@~dwq^M<%^ofJ2n*jJ2~)q@VenIz~!T1+ZOUmVii zb9kzv&XDA;-F;gA&Uo&{fSxP{W6L-=e#zpy89BEEAFYS>zB<-!lGPp zTO;^`wwZj4TAb~y2#T;_skUVektfhAt3B5750J^*lFhjRuqOfKX7%k5-=uS$>XF|% z-ontuZ0oOO;sl1Vm7qhND0{6n==+F62kCMLJ z@VDv{NIS(H|Ksjl*^*oybg{obCY_@dE)NDdoqdJUN$5D z$ubt){xvzKDC!BLbWw0PZn?vfNL$DFi{!xqD-;{1o<0 z>v@`|B;H`Lfcc$R+qVg5zAIzkf0DY2Bwzavd>F zFpb1WVL8#Z*UA^r5uoydy?YmbWC_V9!HW4nd7!jIKL~{O^Zlbzp7$zlZz}~CYwvQ8 zxs6}A2nNwbBvw89MGjpr@GVXiy{m0XQZ|k_FeEws3J}e?i!KC2&Yaa$GHic#%~rO; z{)}QSTGOl?33b&wF~3p`=`Crw-Xo)v0H&@36b#eM(bX_YD+e)f{hN0ZI|>woMTFrr zAKi`kJeT}Xq<||kp2dAGog&^+BJdyAov>(^9_M`myy@HY@l%Z2jTnt;g`Y8het+B1 zFI}<{=}NC#&f>2cQ7`a3pCQJo@4WU};O%4f6PHUZ-QwxFfvk*TW?G}01%=|wyv5^T zX=WY*=I9|;Hnge!F>l=j9L3%YFRw{W=W0$RJJQyGe2#o4ewbf9aqeU6+JK=BX6Vr9-jq?hdf%l&Ed3vkD(Ds&6K09Mrv5cXO9}4=a!4Jig@N zd*e}_acG6`*7uow&t6s4AwbL&1kGOBnXEJdsO&O0bE`@^YM(>A-HX>k|CEyijr(mQ z3~aE<1D7Cgv|svH-w8bK<@omZk+}O8KwKzI%`@ptC1CPW`KFuuI~FRNvW!p#nM~AS zRsQ4BCV^KbPV4<3pMdC@jdUKC2#l2E$dv=cC`l3>uxspxd`>qXw0Q_}3w^EyNdF2h z&OT_)bq|N={b&brm?aBWb&l!xYiZ60TstyhX-ec?lSPnG+gQliuhnjH+hdbuyqWOp z4&(`eM|y$zkZr_GJufLU*(skoJ9$WS%&WP4HoJhGSyV2QG8ZpY{!>KRdQ?@!Ob%?@ z*fM(lcZ=G>iHpJ;2EwVYHc&_SHa>;FEex9#Xg8J@5%Sreo8QsY`!v^5C4=_~Bps41 z_0n$?O}iC|D-%I4vq4SY3SY`UYl@C7k%53E?e$A(MH z&5=UcXus-~+|o2O%ho+NIbnT>1xg58FEJQ>H?!=Fst!ggn+M&1y;HuEMfHMR6BCfQ z|04L@2`)jKOoX4STtt|gZ%k}f_8L7(4zE(cE}(Z;&3x^ZLp>&RW>4^|fT$d7nXe+RDkzw~**?HfS+ltQ!LLl&JF&FPdjf zwgyat`aOQ)Cxq7OrE#D^ltGwx#rYP%{$D!-X>O@g<^G!OyQARnKs@%Ed;dgbWC0oV zPr}0ZD!lD_!iag~mIa&oH9_=8)G32n6Sc}JEBQL89JY_4bMrGmG3WE~L@7vLgojAA zkxka+a^6xGAU8%8yOv5w%=TXl6S<+up|4RvfhBu8yh@b z5oIR#hw78W4ye7~JHVsY0X4I06-H6neb}%Tyx#Znnnm4)6xpr$fW6hj&Fiz%Sq04O zmf?_o2eX9$VKvBE6TfuYW}0f68nO0w-RmFUdS=B1AGy?Cv?a)Hy7KpeLK=OU$V`N) zwU78{_72hkMWnjz(IW<*tdIQM^+Y1z`Ghzqv_ik4>%E~yniSu0_f}S@lq4>KS)Ip> zEB_zRP!edhw!i@m=VYuM(005WZk<#1NbY}rj^PAA`d(kHz5rmi>xzk_i3xzjTqx~| zVV_}M;uYyg<)eaXpRA4{K-Icl60OLCD{1JG1sGcuRm_>r{1mH2X^xN;p}RO)SsE$U zl?s8>tgtG>?%dMeSrxh}GC->IOJ8`2j;vEYYI~cmKO7Hq4C}Jp2DGnG&d6eEYY2Ji z_OXQwR^)$N!DOnr`<(Z3(aAQ=YM*fX)O*|Ojo;!IcqUQ9X^l9hSYOOAicUdYQ`yVI~bQm70BCjj(FFTNOP;Nb1`mLoci(PZJen>J?S6M_3|O-{>LT21P6RiCac@TgwG z&?x9CUm^I1tZ(MQe_qv#2X>`?O0BqYdQNlMaZzIix#$Nha&kL_FgS|SxhkrnmSRAn zmhm_Pg--#k6f2hP$W6CaKoIiCYwQ;YS}7{-4CqdLt$=V({YlT`3EWQ|{JG!0lJPqX zjpsBdVUUo<=w&i&4V0ox0RPYbalp0K#jO&o3dVNKzcl&Run5Mc?XKg0oSiGL2VY^N zKBz7j|EHWdg+>WKn+B@#Epg5;Q##`uIJjtf@nwO)fN;tl88^%USSiuYeDp)XC5PPv zcU*b+>+PFWDi5?nW$#{2A^(1=WPB=4pZNWg>7Yub-m@8k`Jo&-dYKMs;z)il%w@n* zKlF!;Y%~hQg7!?{*UPtV9u%PMut857j7}11tF?yy+8-FN(vIF0xFYc8KQ6`NAEz|B zJIk>d4m~oxP&pOkLC9_YMSLD~sGCfuTF}8h+TBc0tHmD@k@zP2 z=#9A=YpFZjvTsa+@;N33!@0RJKH`TC;ZYnrl&=;K{BtRCstgM-HPi*aE`go9&WC>M zKK5ef&t>}w$YI}%vF)k4TfJA`OzXFEJ+2o!(G((FZPrMpj=0hYu4s~F?MxY`8wJUR zFClk*aHN$XCl%2nPToQVxDvklib+HR8IDB!N}neoI;!uy;!RYJTvlvJKFNE@EdNET zu{tA}3Y*dT#7tjI-?MaAD>&Rk1)^il)bhKJY?CEBV0^6iTa)C;8nt>|Zsi+N2`94{ ze0k>vPRnS`ov|e}j=*!-IQKNSH5BTr^YtP1@ePh5pN+z}alkA3MC6TiN?z3Q?aclk zzb_khy@Ys$kC!LPR2z1k69Dc#)-xYNg>>qCMU!|nay{*QcK_E-s&NFJfz(aDTzl~SGtin z0H=0kR6nAPoR}%lsVX9$@17e;%~r1Wa@hfW1&71CkaA-k;faLvnqKdT(K&{T3OW=4?xwj zY-7d5=xEx3yN9Xznfw*Vp&u}v?VJ6(u54dpWECl*=g>Niyk`KcfB8_^RlwmzfRPG7 z@U+mIFD|BlWyiPq0e1ai7`(3wVKZ>Pm4lJmAr_v6&$8 z99-_T889Z1+C$}Vs5@aLFD+$BAVDFJ^bCU=2qKAzNA8!I&N@Ul_ttA1!{07DfJ>T1 z+&f$e9$DwngE^24OhOMK)Y?{B-M^rbNZ}#*uc&wyXiPqL;1r~$f0&3N{yNK-^dL;z zh0CnyuA2UKdo{CRY#XAsHvtF-4=`82j_)j`0})6-Xlug0uwC7VNzikJ_u=B9&hPSE z$(dNbr}l9-UR`W78!j77RyFEXB)|T>rFq-7#Y?cRQ65?(lR|!mpKg+|UQ9?hbP!Ds zjEQOckL#lL_UY*ro^jPA@3#JcN{|6q<;Bm(ru%)6@4qGcUoawqYv9Laf=Zd`ko{rz zGpY(9^ z;S%evb<)pj*`ufI{{0N`Fkzh;A{p)v$0rp{76orx@B(uyH7(Xi(Mcpb7HFtxjpKiI zro>py-d?U|nZ_I6ll9PzYy9=X`zK8w--iN@@={wXPr?LvXC+iOBzR-iZ)a!qmy^Sm zWim?aaFD!ov{e{DPp@fr%MI2DS?@KChgdRJY)Ac&a>hhXYR|HLoU^sRn8OPhu2YVW zq>gc2(AOFE(J;%kw*YOVUWfVxR7%45W7>@r46~`Q(Sev)X9KEHWo=8PQ3dGE zgYkt^G_jZGJk6AOW5Y_16LtRlwSPiYt*IKY$uytnM(z2Q7UubuuCYk2r)-Ohzc2v` zn11kbI*RbmC2u-3C+yBo8-l7iS$AfZhE`J!J1f#Tm^mL-1C)3i`YN>Y?57Lb_7Hgo zo~EWW#sY_^P{-0>^I%p>OFohXUF-!%jhkBxyTRZA>mN+pk`>S^n1cDy(-4t1LMqYp zhADTkDr3JOS#9u!_Rp*NbC=HBWG*b@<4~kEBH+**?2CPPkoY3ou%->k0T@ZZ@m;qC zRO>pyc;iIs*M9_b5CWCc+RLEP)Vf>D(uM>c-hTx+{s^KIZ>JX~??t4_sYR3*li=fB z-&i+$TB(~$jn3Py@hhCscmKQewL2h2?o}&)tWI1uwDByYG*(nP(JN7SGe5wP+LWzL z{Xckrs8!~g6kJ4)6KInr1!pm;_h}xwvr~tuFYO}^U_k7s7~jhI{#E$=z&TtOm#q{Dv9e!<*}d{ynQ@udGLi!ZOVH*MiQ zL1F04fO+TwXZ>YZ=4R@7MMz$EKoJ7nvY_SWk=ykB^QFuDyU8W0oy5V2Adiq+C0`yf z5tzG5*wcIDAQDe8+ZkLE$ZlpFy2pj^HzgJyj@m|>S-MA2Cxcjer?=u3N5xY>V_(pt z0$6gJ#Sy1LVkyQt>tp6w@xi3hD|b(8bl)9ZZj0BdXhue_BkNeQIhKiD(&ja_IG~xr zdi=f_;s2F(l{R4cN^|ha!U7b@wx$qg-}1B2(yF#dLHE!Bi`ye2cPys&H2o6Q9nM1K zdR$M9pMCUi#XnnMv#m}wJN$y+Aa`<)zGzSy)eGA4i@~`lHv>O41_VMWmIrQC{p9WO zL!7fnXzKK570`hhbHo~}=qFVZ1`Er&;&Xd@4cds5>_|+Fwcz2}9HX8GEQ&09AFd{YWXV|p2}(wC z6v>jas7MkJ0m%{@L_o1GX!b!TjGtSJ;?l=4U+s{K& zU3IJK-gDDA=f3wnDROI9H#*$)=nA z=;-9jZuw3-b87`PuN;O4N@_bXX&WA2sn^fdj)@;2A$hU#wynL8mLJ@5^Z8oUD$bHa zm33F26+V2yJm6g3yYrxk&!F_`TjFa5FRbw1==qi$n&7lHW!&tDSqKg%G%;mWkrV5V znMs9hZX&uTY@802+IvX$J@7P1*_0e+QiQak_U;^|R57nlB#J#h3}2Cr=kFYvt`iV& zpG^TPpzmt)gK_%m(6gl_kMf5Nm@h;cN)t1###U*BKq6EX-xs((%*iK-&6CR*(7dgo z$YIVVP&PEN+BJw5IkkRRdA>L0Ts}oMcEzkSR+Eu#L4I~>)UHAP>u5RCFcW-6iVImlkI2*N!f|%Fd1>(0drPSG!aG%F!LR zTsNr#V%*FI5HiGT{Y(U;jg)v$-VRRbV00N)ob1rdfU(4Z0O+Ii-Vl=&D*Jx%T%-7c zRX8HCRMw<~Mu00VRrA_bzTmC6^8Rca0V7aw=jN`GZF3D(*CA<=!-GNek#xcS^`H>1-yF^jT7?}_|id_5fPoU5v;ifyaI z?$^2B%xF8nV{UgPX=ZB;KWAljrD)ceRo9q}3aX8YTTv8rh%H=(O$JkJTZ^hd8`+*- zt;;qXx9Yf9E&rS&IKF}}jpZ)8{(L(tg)?c*%V<)Ol6+SAlq!&ZY1APocy_SlP_MLa zHvE*au^h=6&D-om4`Qd+n)#fG>D((G>NsY zAn4|Cu;ccEdD}=Kk9gqn)Z~(~Q_yuo4L7-jTr1fXaMPtY)%m_qW;^!bVg7M6E;bBS$8 z+Fc5r*)TM#7H)5sdK1maN@9k~17x(7{G1oG_gr|I=3iw0`D)Mf)5Z zmI@62I!E3F=MSQz*ip=|)iv}wx2bKvSWryZFiOn!A=UZl92bK5l^z0aExFGOEkAKVKZe#DK7)2DA zgA-Cyx0%yH?df>gLRwx{iC<^`aye9g z()L=iY2=dX;OQvC1lW4qg3;E(3(&0`cX$khY8X2fE^r?M4=RVj4|fw&!v zDT0h9*jIKcJlGz9t}BDS&E}kBpEcN)9hpkw`T1+TsX&|=cl z?HLgXc;8zgtL0Z-WFH;_*RaM@6c4>BBbFr@g2Z|m%2Hejx_pxTob(c1{dS(`uxNEZ zO%&BtB-z1zAx(4tc9nirBnyI*9vj-l2=aIC%UFXXo`Le`k%{2uP@z^TA`qiw7W7?N=K7&r#b zbhjS^S$+wa|G&LKRXMkl9YhZ@ypeBbfjNhHH41wP)5aB}a_VS-7MnA0@Yh*iOuQCfO%< zlgxd}SzO%QgnA_DkMw&Dj}I7gISy}GEmwiz3aa1M9!b)2cs$Ll+JHS+Mi^(^Ls`0B z5#D??H2IZ(K}_R8sbO>74e4fX?47o{=DT;F9JUBG=%FQTs(=(^YWq&7kA@#S%Sf_v zD=Qcr%Wae1sGbUaU+9?L@KH|W1@HLCi*xm#yz;DhKhB-M#k2A0dtPf7t!=}qbvM@hoTyh!RR$39=ElyM3(yh0`b{-9jytX*ZmTQ) z*slaBJJ%CCQ^iVCw*7*AY>#hdSeo zyaz(>r9+i1vUobrmOEwB$kdk~HfFBO54~Dnk zYpyKO-@gTiZ^VP!yc9)rmIXRzU$>0h-MF9kN(QEPhpI zKGC&Jd&A7xO;sMdwHUp3%&Sd`%fsOvSv`jt6RjV2>_Uw2wpG}@OpbxZZjf?Ku}qpY zzh+PH^hCYBq8(n1WlzW1Wd~h;Q-7B9bI%l&_-ARgd+jSK6<=1)M5_pFUw0?@*qi7M zdi8on+k^^rGhbA?c4gadv`pE+{I}Q0(?}kb1s}Hb=4X_aR#nxcuAq`v8VXHY`|+YV zY`A%JF_HnOddzQGTU?o)ZEWLK7nfqisfWa=t9bTeo|ObEPAChO3=CIi#jS`wf0XBG zx9^zImLZ$7DDuK#2`8XQPr5Ht@Je^h{fi@zqe+DsQ~C+@&fn{>%n0RqI2AlB+cfh{{M82^Dd_Yk@wFpg%VYWZxRKPtPam)Z-Vcq`WI6o21xu08{aJ4Z&4=)oT@pD$nLXIE|}%wEEoK zA^TdJc-p&9xw!dwv(Fj_UDmI)Fzvn|w(R!h;Zc9Xy{r`B{Xo6^+FQHLQ9ZrcCD_g$ zZwKmsb36GDf}OLGoN*Y0EmInUqOoJ!X7*H@g{NFR8_uy0&bv%%lY3x<1~p`qtd8WP zAW_D?JUKTnSTi)h)te*fO~p8Cm=US0%K)$bv$A=!rT$aPAFz%A4^r(X?CtA%;G!dQ zEpmxRJ1TQUoGvYF!mCrUs;aWI;$=;B!kKbkDn;{%75#2G<^zRQ zdGzi~U0e&gacUjmP2>?O=h5&npgEE*+(IIK?`@I7buv=ZqBFRL>6pU#q{1TO^#gIM zaD(gTUk{g8CFP-7O&M`XW6=cu^x|M>6SIB8X**2MOY59fc~+Hl7dKL4pX~=; z-iq@Q)gcEA%T{oMn%M?~o$FeLMUNSrAJRu`C&`!7QS^DT(i!c`8BNtrgoh=(bdwx0 zncbc!vuQybCa)~afjXE+;)~p2AxXH?<_AmS3g0W?sLtY{C+a(UBN@Gd`_Y zhlXn_5f&?=Xc%vRJdg0+h>JXg>hDvHsC5qy(^Kr*w&Q8)n+v+^=3CE-Vbx2e8se$0 zN2o{jpr*x`lu#U*XwEGzjgRTEu&cFsuqryw>D4Alr%FCI?t7a5MCJLmcXwO)Q1zzb zPGI$%*ZK8$C0OnL#FR3vY2$F}v#HoYB*VR+hK4=G+i|aSpV;IpT1H>$u8$VxF}iMk zD^3URoHi$LilY}db0_BRHnEpxuD5wsT-n*^@)a*<^INC(N-BbM7&5CjyRwBU2Nex3 z_qgck^(}f{x3xv$dG}O2x4&4evT^F|>5&MgU_tl0qnY1#V@=PEMJn> zfgNt|;uOXeh!5|Ai>W*Kn2DaZ*E5mC8c-|S-v`W1T#sHECh2YvY805@ zoR_Cob(=1~Am&!AL%aJ_GHtDB$*8mc?2@Q)dVZ}wbRloPlODZnuSbIW9)U`{W=)?; z<)hb(GQ0VT1B$nd9jy)r*-0q5v04G+k+9pFLt9gm%khW&sVN*G)@p`hdsZ$ilyn9i zAgb;4Q&=j#+WL?iUG9`!0Gz%toEF(_p;6PfouVhVu~R!2``nUTu4n#A6%~FOwF+gO zE@#xMSFHtM_>?NLBny){{eET91%Qy{7BGo+I`3APKLbJIX#o?9e>($q5aoMwJ1lW^YXYw+V#=Dy2*msxA z3cRWf693c7PndkuMhB-o4Ud7FZwrq|`UXBFATBKAk~j)NH-#-FcX2^$ue-ttPK;#U zI>LATI5afLapNZB-mS7&=^0zY#}7L{veTpp_vTfGL>qa*&Ivaur6{~Ejz>myCYFsP ztZ?m6Kg>L5-etBSBZ_ENxoi+8AAGM90tUNIuqoTm>4cLIXoCT zPk3|(@`fTm8=Wfe)YNQpez(9hHS-Wh&4^8fSvFgjv*BLV6Y4#cDgnf5zIU*!=?Id{ za#$s4zgNAicQRmO=j~flc24T{&{!S5L4XxuEm|4)jB8E>cEc?N=lpP|%8U4HCN;ws z9VlNg()CfLMoTPR@Q@(bHp%48u((Z+Abo#(MTSejNTW<^yEO>ff{1`B)03kk^ zkveK0O~P7t*dxs@~q4tu$qa)x2Y-&8Jdba(&u;V6|TgPT;7YD)6%IY04ieD}JQ+ zhwn6JbvpA=x1C9;$vCi^!byj`K_#6CR^sQ0R95JD$~?=lwgk5-u8|zSyScbD00OV@ z^TyK(s#D`L5hCkWeNdAe{4mewN1UsRQ{KITYs_Rk@2S@|4(kn3Q7cv1i*>SPXoF(~ zEtHb%H*Y^1EXZGTe4Bmv?iJ0%?F_ZDP&h}UB!9f zh1fY8F5DO9Wn(sIB@aJDVLpC;xQRd6NVVKxFm0_^c;KNS$zP^;V3_UYD*Rj#B&X^% z+Fp>9ck>v3#o=+DE@d6wP9bptaef2W;TrUg(f)iB+^eJEn!>nEnH3|Gp|TAYbws+U z*iL~bv3mVf)Zsl>mbw1R(FYv(HA9E{kDNo@t=!JV_UtT;9-S+2)OzbJ3eghC;q0nIZphAcM6e0*J5#+cLpa=7a4*C2!$?wSr0%j2% z0}~4y=MKhuHnp;}i z+IxEY`UeI-3=L0xoSvDToBy=1xUsply|cTwe*ixz7X(24p;+MezbqFh1PBUP6JSMv z<$|ENo)nx24gCxc2C=jTrm_9$v%J1oB$pze6xU%h@@cMjm{?Q_X~ zU%~GGsgnI%uwTkG4B(u5_QzF=E4hm=&=>R{`#WifV(NPb;H60-xT@ zuuT`-wf7fibE=HrLCQb}clIMr8KzV$F>(2as@t$%xkJEG=q;RAJ65-{7fr#bvwHpJ zcnCo}HTM}|%4u=<4kDK${|IU{D7|yx>ZJucdzzw%kd`~w2x5HS%%j5G>GIwwd&CZ$ zile*HCR=oGJ*s3CpmW2_;^~`9g~OJlhOCZm6AisR&6p|0+jdUEZjxcri!Y4L+Ae;P z*88K-iY zO)s2Y1Jw;MG|T9wt$qV8ck2@?yQLg)y9M~E8MWP%aV@(oWy(EVl9sWhvc;j}Op&OpK^A?Mt8?yiPWydWH13gSsfY7b;+BONa zj^#wC?YhCQ=iY{zxi~MMp6*$x>L?FOzN?t+0!Iu8M zV*Y;ojr}y&j|2~?l0zi0={2+&nm+ns zr(i@|>p~^i?$h8)r__)NW3m^6sTHVP972MNJw)GP;6hs z7A$`1GP>wJ0xpb8-aQ5;>eQmHKbi}72puoC#!qt0F@WT}lIoSQHs=>zZM~K!*CUcO zH;MB8c@*y(N3Dw>&!H@g88&UcAB#z;DBH#auZFeq4O~arQwG`D$(Qzu`aE=u<~ghe#2F zf4}%cAhZAp@K0w?&is<*t6%cq1;t;x`1w)4a^tUG`%LueTm}-oZlwSukZBQ&r_)wQ z288x{(_oNs3P;(I#M+fD{u#oBPSNWHDCe=602v~i%_w~yP2c-@Syk&Rm1}G-D+fkn zW>&hb*&N11tvWhvl=5YW(BfZBb=XN*$wQ-R^Jh(sCU;BomtLb+)NbHE=X{pelyh4* z+>2l1@)i?$X}y0O(`8IE>y$jqa>Lu&pZb(WyB?&yNKZl-h%}d53T9fc7G7QsHz+v< z!XLxvXKv?uTIxuUxn(!9)N~=B>(3jn>NFSIyLmx5Lmi(CEuO}*TS**uQ$A&3f18d) zHsP5~l$*T>qp-O@e0}LCLw$i&bT?Ql+scjOnh|Gy#|@72Er|tXr-z#LuFu|Ub2yk# zJpU=#?%r7C;thIm7cKsyW8elj+kQexJbe+=WBx6z<=?qoJgR1^j1@JC7PIF*`Y+jF z{N?b!(U?Ik4xLsOUUQ{n zoA5+{+e-zY_#+8U3VTvYroXnNpMmEh!yxc{gML{J4mz(}B;nft)CAf)h!j2s2GjA+ zNSs0l25a<}KSU5sW%loAC!Rl??aqHNn9Bw4PuN|JkWig$TwP0yrD&$>;Bu{0q21k4 zgl8mY&gBWNair;(n_Kj%h~r7(A$ZpV{WuCPAn2!#=r5JMgbL{Mdx=nAj@<}-SL}oR z2K8KFLit-S$->Rc4w(n}g*!+KW8){b)sMXUL+1Cz!)t|_I2{H zOc(|`oI;LCb3?(b}N<18!bFXcy#V6Z=Pj8%Q}Hk-Y!9=Ki(I>I0~M{4dl$rTR*U8g2w^*kE*R zvkfomuB$06w@8nB^V?$Ok5zik?M+lUDQ5Z+m-Aj=tOmN$tJda?mw3Z`&nqBc#Dhup zb69=KHCKk(Q>tB(9eXL8)YM>G^o8*Y4jBzhlQUP$H}S9JH4vMtQPMrFBpE3m-aL}F zHUnLc(%ns>Af+@X@$7>r40=Z^Ce(%IiFW_2l=8y{FK?s4kGyJSYP7=-=W)7uJ}9Rp zi9sS4Qqh@9VDSi|S|kYOMejGc#oj#qc3A95`MUeOE3J2#xEAsiw$mxr*+=;?2?7)t zlLz%hEp%i1c^Qf3SoX~2&U+eW5lT6f zrq1e)KKS~k$*05QjpftsZZ4na=#^z7ey7w>g%fbCLRDzh-Chlei6GSNox_j1P}$R${PG$%kE zE#}`Iz`kq{K;RR&I;Nqtu@s#VSeM|t&{qVJlEw&VWIBG{e|;_fYwJ(|9NX{}oamLX z$bQMmk4qtcxF!7g8%Uf<08r}xAo&wt2Pm$SvnY;>lI(!+4t*>@0}pTa!S|A%mBN&G zx|xoerg5MS>C8do0P}s`+Q6SpcvAk8f=B%#hp)%|Klh7pTT%&Fvb?~G`u5WgW`8Y+ zuxVMA4BzC3^#7hF`Bhu`Yj4140>`R0e7^;0lpn^GlZOAJ1^?Iff#1wGN?3*u@jr?F zWVPs|Mg86iK?!ZDtK_LZ!%Y)tjF1Ri81SLB;d>vT8aC;nFG6}3(pm)wd+P{VNLW8nJ3j{cr#3f_{6iSYwmoK08z@GObig&_Dfys=ic zNMZGN*b1s2dAZ#vTCQ#Lb8+)~4-)L%0vErykR(15zZ?Tz1@x=nZU&Iz8C(v%COMXb zM8NjdA-gZ3)q+O{(DiiG70{dMVs{7@VoD10SL%V@I`FU*IuQ?2d;woP9YR^<@2jh* zl#0a-lY9nn4QKpZi{}n6dq+VhDn8%QO`n;zw*mv}woHD3<>=7v{QtV1{hMRwUpbNe!CCQ_$bhrkKV;)ZFLZjB zzU6=lSj_o%7B{|DPXEj=R1idvA@2pw3;QRUYf~$1DQLq2~2Kt*V z^B)YbKR7OYw$}cvdi~w!_r>t>E2Ga}10ne9YxNfd!QXU3mI5h`fdrHt5gz8oP1gZaV2OCubc6R+#qo&NDadz2(6<%kmbrtD82OX0O<}+@!cB zRqDW2EX4N6UA=sE3-cM`;e3Bq@QQ6kUe`!l@#ELna9s8B%2c1hOXRPuy;L_yuPQPT zy|A|cqJ-fZw251oCEl{x)wNWax_OUgDfURm22)k-M|vJE-F0V@Mn4D`#maC^Gz%I;=O-b3Z z@J#ItqNDm$od+a_6^%!$Y=&5z;F&;$$&!hcg}wo5c+7oe_nTT8F9l85IQw{+Zmx3p zRZ)lW^^)|7M$H5s72sMpdU$5f!RP1a^{dj9uUMB<0&#)0V2X>L(;u z+b(|}A9nE8k{vtEvwuvGy!fl(osIvRRg)~kkZ z)n8W<+prJ2CdzZYR;js^Sj5c>M#f(hd@ z!-KO7ns4C`Y;3c=a%p0I&W)Z^1Ly_zzolM)&~J@f2p za76vE5rp!QmVK1Dq;d0dm)ZFzlyytVL0tJwJ@uT?wh>Hh7xFaT1v40f5lz6iNg&Pl zO}Mj~6J~_pFJN^pNIghIOQUY1K(k*{QF_zgDDcT_OHs5m+2xb`PIkvLf0K))QtI)J zrPR_b?U45(8tsMK5xR?tIcg^G^7(vd}cUw2)Q=H|A29<-Bow zFi~?cXA=u0OPXWal45n}d4jJNS^fg!=lh)X%@OI_bJjPy%_8-+ck^Efn64D?>Y0jYLnK$`uo zR}RDyLK+(|ds99~I2}D5?UoMuW1pv0;Ndsl`9}r@G$z(I1_CXqQ=lclV3_@X+Kzz>;5Tj8j)( zc`lZ9XlT(px&Co|8oyMR`4MrpYES=zhn`KGS{<8LRrLdK<+{U$nyoN*4#GQH5~#|; zyIqQO>vmdOwzB&~0L3BhD|wgi$c=_4**9^f-G%$QJ$PtlB@-_t;(xx`t2DWHDf{s& zuf{tTkrvdmrqEe@!(SNOYfinI+DkmT1nV=AFq&f9LsyFen`>6-k@G?j@#CvrF9B)OYzh z2f^T=lfGE;VPo3Z4?){-ZDc`DLHqi6asOC;_Y};NKT>(vO?hPR^nTLHlKqpFr(G zteBC#Cg{Z&Dj_!f1OqtMuAenkgBv+Yu*nMC($;)mr|rx%i32!;szB&Qaes**F5S}s zA9^XgTRP2is4S@B9e@aExmcOw=IGms`7TM}r(-;S8uAo_E`832_7^Gq=&SElY)CsGNXv@s=qK! z==U?_NVZP}H_2@sp&uLr4P+zlk?)gCMcV>~Vr|CmQHXW-d-^(qDE5l!cf_{wkJ?w} zsd*L_)--nyj{$Ws!X=#4g#0Y44w()LYYZZj&~*x?*7Mx;$mQlS@GefROuh>H@yH{E zQ9-iiE_ude3;xQ=oj%cM)dCw1*94k?OYeeQO{<#uWcFbN@5nmgi#lA6*cgSAncuIiQNE*|j9# zLZ<(;Z=_6jH6~b?$LDX5`Kb0hUB2{8=V7PU8(fPewZfevSIi1uD%Eq9u>;pX#LDCO zxO!H#NQYlFWU*QHUECR-BC4`%W=eD82}Cz!SUq^iWSX5#vJH!X@hSD2X^03rJU@eV zEy`umRotzE^C8`G`L}u`M02;_cG9vFUs&strId8m5VbSKu>&H?@L4bj^rg z-HJj48xK5M`(z2JWGJs$OpjxI1DOcY9Ezpw4xJf$(=CsC=hCG)ftE2Qf*7Q@B)nhE z^~jmT1>|ixoF7ISR0&L+n=`kWj;^Mp++Nt%IP#{SqZMmL9$=!_+x7@^1mbmpQnnw6 z-`Nj@#?M?$G~h8ynz(oO#Ua+%=IIDl_ewkNs~ny%o?V+W_sz{C6Yk;81}3!FjE2u% zeoc6lH$UvtW4;R^&xx}z)=%JLiLb+t0Z%~?J~mhQ6eMH81JPq{&p#aldkrAYjP857e@iaB z^0;An)J%jDT2iOGenm|oYO4z^QoxJ$O>OoexadWX+&_Vtb{NTnS~@j|GTqYaJ_gpn z&CED}SpPQka0&PT?A?3bX`^7?K2zU|y#`eiPzO3S zY=`h}*gpmsrD%12(#w8bBl%jJ`ipMNHOY~zq%8W9ROYyYg9{Yo?a&k7Jy z49=boGU;%2sj{DQ@)Nq`w}kx{UwfL9js_Y(Uvo74M7Hw7*}~mwql1HBI|EgygP3=jXT%mqAGG_oUw?@OPI0mhH-2XphOl(S{Ul{@-`c zvd|M(YhPqEx!PI~7Wse+c`5CI~C) zUZ#ciof5BAtR_HNiU{Ppg=A8l}C<7 zvoa{&$*D0wzqx&tsx0V9VW>)Kec0x|i1~g*s;%XmZ^Th45hYgWYq`6O5k;b2_^fCJ zs+?ze-P}asUcDi3i!84k@=LdY`*YCJMzeYlOqpa!DKyi?%eqFGwP)EnR_2Cl-sxTM zi^Zj7Ql)jDaLS=&PH21gX)73Kungd%q8 z%)A_z>r!M^pmDBik@P; zDpuXII}nYt5B>dJ0x4F)wX(X+aBj~QRKG#WbhEs={_AS(aJ*A>TWe(jJy2+UYW%0R)_lf8{@wBa3(^?O+fU|0jU#KCm=zZMq=-7KE|%Sr=9HfD znFeW3q&k!-P4DRtJu*WTUXcnWgDoZ@UxEAMo+JV%8r|Q}K?|hg#KAU}Y>t6zg9qww zV!N*^6-^#~^r5CvBy&OGTU7zU%(za(0Ja#nt$3Ivim*-3oz)AxA<6DE76ks-tOLKBwZJ;D*LK&ES{1jT8s9uRU3djqW_zZ1sD&m{f$~wP3+JWnW|3*h0@hUm%`rfh zpN-ewbCU4h)BJ{3)9~EQs040MTn2QW)|%>8On0B4y+vE6}<_0+{{3 zmEa5`W@L|#C_BjD_cyi6?bAc><(06=!Ae3UJqx<((*Q!k;BQW#T6S%5n5fCR9mpHYYW>M1Eecp(Ubiyv^5LPz;sZv`{< zzvQJMU4ivi{_Te!(iO?+o)KhK;U)?9Ss2j)^$drcA5X6nteI5d^a z=Xhr(ozLaSwo6@ny^xO6c~*{h835Tnd)dp(r*Fz%39`B#q}o2C%;bY;B+~sD(l^8_ z>>y3cZua7uxqZI9t$*x%sDT?p5k>B3hRQ<7+BFNxPN)*#Gn&Q1p85FIe8`ccQF~Z} zJ2Cc?3+hV#zIBiQa90-^IU$d^!Sn@;kEr;V`M_n){(3iih2^385L6%gRE2cxt8-)6 zdWjcr^6ETBktoB`5`!e*w$;ihtx|$3yA<*23Uy~AuSJK)%+pxFHEuG6&C&SuuoE{) zIbeLm7fQFgWK?cwJF@$*(!y3SWWIMv?&F6$m3QSzxbMzl;TA_Iw6!Q<+TOo7dUHxA zw#T`*3{^R8MxVD_kxbViZo zAZB`21KdTQdx|`O#Wc%i3t)dg}c<2j&=23cf$2pDPZ*$0It&U3Uk>+>eS5G zG@@g@iJPa<7^r97ntbQ?{z~=*L4x?D1*s<9mI^sN-4DV*m}u8FdV!yJH@>NEEa@mp zp1#?9?*OF< zxr?(EX2m(FpZ7bxs{d2_l=MLNf$qdkkJ=G#7kUr~KloenLhF@*Y+uTD@Htqk`Wxq# zq#0Nwvb6Hb;k1|qUD@No$8WXnnx2~>JeZ`hNM8yQnah1xs(=9-T7`SX^9}D(D z3jGI`LKJVZ$#1cp&)^6@YB&h0e#)tu$Wbk}871Q0!dlpP%o-TwCx4apg3>@R zV>D+=u=i0&!aT(>Af_op6-O}|+4`Ish0+CzE&OIatgII^*J9ZZ&5p8;a%6ENmqU`^ z4gCRBW1TVhu9hYVFQ?fVRtAj2mky&On*p2$epONF%4%uWq6~~d^ zRAY`Yu3!A2S_+Qehn2izRJaX7T5+NbT9`u59grp!^h%Kt>GEr1&Z+|)z&XX4?PXR9 z^|LVp-cDIYe3V1Ye0zqH`KQ#DTJ3a9V7t~Bk6%n)D4_JcvTf3UDY4DLF+-rSu`qXb z)*Nl>J{hjd%vSRfFRM=6GG+*! z*2dKn7Frpkf6PC!mqa|=9Ln(H40+ZvcEp~A@yT{NravSYvPB36?~n`yM4tg@W&v6O zs|3QC!0E{7H=lrJ)*@o9@4fo>s58Gqlh#%(xv_r z^H&R!J|8$I-Z?LY@%ig>amX=yKn8CmaOS!OeshDj)q#)r@#H`Mgz&6@WZ$qkkmY+1 z(E-wX9|H+s@`){w^7{~Z3w#vx9moQ{c5p)feGKsZ2NPpS*Ddw-bzz#G@a{S8QcoOg zrTs|r^6g{v4vC%>&W{%53ECFS5x!krn98$l;6O71vUR+TM!HpkJRR{Yh%Gyi#)I>O zTqYKvyOy@q0b>WmswC%=KpHwX2WY1N$my{;b3&5?(s_J;z;_vZ*$(iog0z`oz@+oS zq9wz%&mAM&@t_NG@`a}Rg&z>~9sN!HfV*iM3qSY)aVXF~n1YOA4{pX;u=1q3(F$cY z2N*<{T%c5nt}{r~I7pk-K0Ef)48^L5+cb9|v#L?H+C1*A8>G}4NS

    6lsD#k|b7H zi1DPl_LSjmS(j*$oCif>^VX*2oUlPBiL}96+EL@v_9~@fQi#X#*$jvwVaBCIvc+Ry zAbqzN-en@=O}W`wlS(bg={UGX$CD}$MD}LIp)u^xI3zGk<%7nYd9uwsOfr-}FZ(gq z(%QLFMNQgL47{|DCZNl;C44KZ(eM}0)QOEecrqvo_)r}K_En5wdA#yHzE4RLZv`;Z zTcNvdUQQ5O7n;v@j9igN09_;3CM^nBO)dxjVD?J)Zh*Q17H3LE#mh*1TB64^7HBva zu|vTZo8Zk?xE!XLp4S*EPTrLYNw&yFh4DLs*t}NKw4EdG%=^Nf!;HM6lvLU`sm_$) z7BZ|f%V&8wWxe7u>bq`;tl+w2i+U+aECf~Pg1YA$C#De7b()?D_!egN&J4$PA@LhB zMMAM8gAA3G(9CsiFU;E_;ZJlV%dWC9^S*RKC3-wKe;@~?No~n_Itbq;kVdN%jiD@f z{Z5VefL>VauAUugp{V>|e<6?f!w`62f&;}XNV18*9mnQT`7rrvFQHsRf?RerC$m!Y z0)e7~zLv20C>K-uy|$Kt=Q*!V-%xX$y)`UMekaMGB6*rtzI}+Y<#uGmlRh)ZyLT@X z)H8T0(fO)lJICSfCb^$*CI)j|*k)OoqS$yC{k2cE<0nWAb#N`gk(ETro?CYpC{x}_ zcn)l-vxwo+$AsIDROY;bUZ>wVI#YdHNPO89lUwyuc<38Mrr-_iHdICmjHr>dW59<1 zj(okzdb7%s_SWI0*Nx_<_ybw0I??ELKJjSpfr!Qk37F&(eAKJnsD|*?({ce4DE~>;4h6Fj5s%#AWU|pkKPQ+@Y#Tw8k58! zS3W>yc-hRtsnoBOHZ$wo#Ad|hz9)o?f&2p1`NDPdGvM!wb6@y;{-q=6KYsEjrcpFr zk<0l^A*AF{DgZC#)0ZKNldQmtG^=a@B%P@G*^Zwq?lU^#+Vmho2Ipx+I=%7dh4p{o*1~|TA6Y`m zfDi@EOK}WNw4W$b_YN6Dhxs*K&G;XGviEIa8TKho$CqM!G8dR0m-+R8V@t~zARl>( zfhLEtb4u!6Z~oOR)XazW$-=VJRkKy|y=h8fO{GQ0K;=743$g-IGaXHrlsB;yQ?ItR zpE$vGUVbPPwE;tl%?monxHV z>>Es?ajE*uBSzI~4JrC(C`{>S4205@n8oQP?0M`NtlAnrdE7v{OwPYDY(6hvWDdE3 zyLnC`#<3g&LFxH2=JSZXKqMj!$?nr9a0A+T54r|wdmnS~zF+w+gYWI&|LMLk*8=*O zBP~(Nx>_Xa7}}rPwwQpHs|Y|$F&$+iHO$y_dkUDCi*j_kMqAhJQZwVE3$rG`NnyOdrF<4-3 z@P7!__WA4!_!l$P&&xibg50o^j?sl8fKxH;-@+o)GA-3D#eBc{fvQ+k3uSVw=_t7O zRVow*a6j>&q4*FwAyfbk;9|F#W*BdFIiMpzRy9i6UmV)T$kuYrjNYBh=S*0aSV`0n z=aYcB=H(FkUg43BQ*YrDNGt*Y-FI`B0_}wvM1j%y$YlCv-`dNDr*!Z$cx8O>=S|-T zqej2kO_zNI*!GXo({odFRvwT*AZ39}Q+2|J1r2mB=fmq`BVH&($R)Ytw$I#GWJ#^r z%Pv~xog*l#?^?yl_fh3*sjQ{d!k;~H2@{lGU9)`MOa3?;T`|tzig^5cfJtM z!|S7}Q%6CoHWev_uN>^gWcf5zAl5yjh{;P95YLn~mvhE_6M;Q5osY^GwKzXqPbY!J0%qYAzCpUX1fDQBEy}9j-ylW3Q`>t zy6beKHBwdw;IeO($DEcu!QHob{u_KqA8*jz`^GvADQOe~ZBzmIt>^o>5Ew>?1UL*K zbKxn{yC1v`Zo_EBLKcETb1rpExJ0J?ufzj4|TdawghY(qdc>vQxQxFz8ShkC~V z3b=oRfqwmi(P_y~m{Z{hjH+W`di$%VKZZ8)woA^h7$I;Z5kAlcW6vwcKstSZwg6L&!*g7S2)A$%5e9H>{EQhXx|29GQ>px^(9&vee0_mj*=GFWdXbb#5 zlXZNx5rU5jPP~>9RF)vyna!#+<7to<;Bwx0zq(B&PaAjPG8V_&wFAaaF$)HR? zS4q$^2lFet!%dR&=U-&kPCxf*`nWB3C;>D;Sp8RS+zPY5Pu#4Tr% z;N8}KROo!J$i^=?8*g?wdGoH^sjdz-4OY*jJ-c-W+z))95+us@Zk+6A&P9>@VG+$S zpKwh(Wge}xl1Pv}CdH|i-$?V_+DxTs=mW3ZS$>WAdGzU{+V}R@7PheVk--4ki%c>t z3ixj36N8=F=2`)LZKjfp5BW@Jal%u#L60(5PR#K;4tuUnoB0>L#^l=KQIV94Dy`b^ ztXA&#B-i9CppS96Vdu>dX)<>p-jYoP#e(GPDve5HRTx2wh7W*4c!X8U!(=i2&7GOP z8Z8UO6@Ael*i*<;`$mRf-Zn>_&w>;+P7V?F(o}5s2B>x_*)(n!X;y}ek_BMn*z&mH zKKHD9;O>%jFZh+c}+oBSfIY^Crd3`2C z{qJs~oPzS7I;4NPfuOP1738`aL=eH-H zic{fIW$U=WuIIQCX2M*UQ|^^sW3zJD<2F26bTOe_rSP>yX>b>wy$ji)gIaY>;xSo# z$oOsQ#)FrhAF8{E4BQP&!TW9|8yO|#-8&Qmr=Y7nm6n@rSR$7YF^jZYPYyD zW3V`f?QXB~yW`irUfLyZM|ujKzqCxCC^Sxrhm-V;!JwEnsL~xOm4l%ZBeL5 z)r6(Pa5^D{@9u-dvIKW3-24`s$K?h4u<4QJ_z0^sNo$*zn=dgU12;Q^nz-4}59C`a zC1&_~trK5;tjIscp6YY-3SYc?FMG)|10YqX^}5Rb=9NSGhHhgDipLG1+6||7)Gvlr zb8x3QRBrYZbIwkElD+rf22KtYX0C0tZ}tFeWxo8u9oOhAQf8E$dr;=$W4!6q)Kq-z zlT7Grh)W-0^c1xH2J3)Y_!JZky>JS$hAy?H=+vfcD(Tn2PeCXA44bf;=ZcHzcW?Gl zXbqHvQyCLpJL$hyufmVQIpqM`@3JVqS})?o10$3h?^O=pE9aHl-K_i&*2qD9=_TE( z&0FnbtN8{4$GRI2wj>5#zvWFeSFf4~=DeK9R3vnJKyI3e15R8-7440_5!3G$vd4YQ zeJ_Ac-&R2_*Bzd3!eWLyJii|^Fk1duYfrjs?(JPg(!hA$ix|BbvAX;sCe|i~887l_ zQWhQfAsAltpS4HF9=Mpx(D~|vUCRk_OqirD%Fi|HNU&j`Oh)c1+ANcF zU09gm8E(_(2Mm~$hPn1lWv~0JSK638uT@payOWBDZn({;hBk!eE?+PkhNVr*dWhPY z?oK6sioRxl3UV==3u-BI(0K~Q^0e0=Q+O5HD3tR?M{h~@&ZiOcZVPgQ{bT`k&5yoG z`cl{K)--hv%iFL|YzXphbT{*w4G&ajE%x1afhxp5avy7bHgF-(QF7$T)h`!O0Na@V zyunE0SV4!fi!Y_fe6MQ6817z@43pJ#G|4)t_VG7&(TXE_b&bYZ{dL)$;kNg|B@+_Y z6#d6VK0adgxRbN*rokr@PwE~Y&roXA65n)#WO&58i#u89i;l}0b?4?V=XmbMO-wRdmYLE4_X$?amGJJaBZDIB-1b=hlvN%nRE_xfD;8(h!dZeqw8P{W5Rl#qlY zY}{^JI9!G6-NH$+mJCqhX|nHVxo<1bwzH)62|NAT;iixZ(#o$_F<66P9cGVOW%MZs zB%1M9mIKOp)~-=h8*{hKM&nP^s)>Ljp0IY4 z$X;f42V1fq?N*LLQHJ|Wluj4r)Xk?4#dNxpMg5d~;tk)v4H*`G%2=iriJZD2(>VdQ18{e)*_iH_TL zp*lWhvu!|#@?#oZCrqn(cuh+D%e*6g&a{m+8dT}&o@>~O7e-x@dlB-?gqVi$>YIk) zm(^Lzj3qnh%caPcG^Ixmi?u%n7N3HMEOZqj-V7{1>Nn53e@8m2EP;PtXL|6>SmX)& zBuVAebNRYth7D-wb~r<$+pX~NXHKtPe6TZdw6Sy8P1u}{UTlTYFuThg1<&Hem6&h# zI}hM-h3a^A41Zw1GF$;Mo5=ga{;^7%ds-A4-+3&R*XJB%}Cemmsj*^TTANGKF}?la9E^4_YefC zfh#so5Q!L^6z}Hm%XKArwd_K#uBI53Z;BzdYMjRxE0(&o+VP_!iV(-Zk=dsNzFBtS z&Txs(Gt8`cZ|<@FO2>!%?q@bvy6$lHGJU+lEtZnU*3kHH?pbv3tK;Wxgxgd^GbsZ!jE) z*rNysYXKe{`79Elz#!ZYZ!JXbkZTavilkz*&In?mR~%~Esfv}0Xk}fWyA)Njyu}2E zB#hqA6|H*3{)&cG{&AM#)p%XF-irg##ooD?*=V!2t@p;OgYpj$(hQj%GDUp|D)R?u zl^?Bb#;5Mz94uFswK8G2?y+ycbr98xPAOj!ElW9F0V!L0n{vddnw05DnP^VE$7_2( zSJ}!v&!OU-PO0g(#jGRSd_kwavIM(s{1rJ_cKfz1`!-!2ea9EK*QWN545;5t>lk@3 zIoh0pFmdzVsw1S*iDAX!Aef9thm#r^4pz~7dkhB3Bl)nU*Z0^7v4|qdZDUHNhhr&A zL*uT$?tk4EYVoL>`aYHNRJQ&&o%~Rx{WvZ&`Eq}y`Q@=)vzF55ozEcQD>hd$KMe+2 zU%hJOAvaDJGVOWm#`W2orWx26I8ON!NaD&XY&U)x6Xv9rAv?PCD`fUpQgRoq| zme*iS>(K>p4Fwu}e<`Z`(<_dKAjJDE^wmnQQZ|+S{EpT14yy$I>nB&{9rau+men>s zy(>Kl%WWSms{x{p;T>BwQPZEc(EI&CUW@8Gb;qzDi*rFbG?D4~2ayMj!@;JANKFOXZ4-mgfH>t6fJXFB{L4QsM4fUhFZd+k$)+0JbwVcPlCPr+ z?ASbUZSm@NBDD6Ve#e4j3M2qf0sle5HwOU$Hb`NenO^s^gr7m2;@}ko*qOD)uv=0` zS>zMjVCL-?yQAs^6WU=@Pa}%B;Yp8HWZRhRUIy^(ZZ(j{${;o9vHNm&*`wL5_vU=& zX4S!F+QxXJ?!dF)9qtEvI~`Zo#;C21m)3tB-xyVK)-2pyf~qyDtVEGUSnAl`Q{Zy6 z^TlI7c>F>0)()FppQs%yRtL3b=UFGHG4s7185f(X+hia1g#HRWZ`-9Z9qtN)mu^a2 z59=aP+LPvr_e_y5xPlmori#N~UT<6JF-Q)G>v=<4?cb^~;*k9G9$26iWhUgRr|%-k z0xOufLBr?cr4p-rcvK5W@&HhrIf9a3&9oXZ~FlGSc^o<}O_Jj59w+M{~4V1|*k zfk1qQ(cA9U?iL!{{)Pj_MDzq}oiGK;0vS4GN+u~)vuDu+opYI@Rd|cQ0!(n{#Zt&( zK_(2|R*nu%nsw_VTmGG@&+lXN0Lr`{HwpjIEyF+i-@rlp5t9`NI+v^38y;1D8gEhy zr{M-$w~d%&kw&7TV!`B87H!=;na}muChs4(!t?Siu3dSPU+yr_x}_dHvt$q}Sa~%Q z?w&=p3a>GkUEhB=ahRifAax2_3prju(3zY7|2qdkjGj;+=u=K4pmU0d9>`QEbU70` z2YiWF0q)@-%~Oza&4D6tA&)>BYF zDFPs&go6=e<%nE$gmTT%i->*ylpUba*i+CEuqg#)0kmSe2X{|FCHTLN3o=at?YBVy z&*2UK!w2O7EqwIwCeN|7aS&nUU72B-HKeUB{P(y5`xLJH$9SyBr**oGoVnS2z|Cn@ma_i{lA04i_|VG&M33Y||sA1nBXK+ZNu*g_kkMMsbw!dL7i8u%%N1 z+`BEhz0U*nCk*KbQ9CPcRM@5*-ytb|>pQG9llW27FsvP+O}Tm?gD$uRc}`MQpke7` zhMzFkzEUoV9Oml~WaJ{o>bDwF7#sds+i9{TiSl8n zY2>PqMpARZ%~x|#CGiijBJ^Qq?=%v7TlI@?Fti(at~x{#>+LQI9y`blpuJfWwNkR_ zs5EJw7ig>N&Lk=G(YH2;*U%EsH7G+nX}q{cGo_eIW8d^WUg(=Mlx~(#oO17&F@*@S zD8Dg*AaE*k5`wL^g*y_L5%g=r1FFW@8Jrt=21|s&>0(Hf# z*Yx**S&--Q4_^WdS<%o%V{ZCa(F_t; z#bC%!&CI$JG&s*fTEwX(OM0c;^wv^&zM|G0e!^Fyp`BGSdW3uxV3aBXiP{+?d@5*j zPPr!}e`Qv(D&)qzc6sogEORFfOSVAW45dk;V%AQ7mQ%`3&pQg4o9_0DZf`4r55@OR zz;R6JA1amC?DS}rp12;6Ou>}qbe`1D-%e8kEx_Ei zB-QVEhI|r^DVvQS<{PE2LqTnww2K*j3 z9RdM7(iw?C(J~1vss2g?k?FReh)BE?I8A-{-o?Da+yEJm3PZEYCd@=uU~v8i7(`A{ zm4R*8;)#BE@Y5IJN__UWies8TwW93q9Dd?=26B)4C`y6ojg?AMgL-3GCyqqp^K-Xt92WRo^&71fCHhfxz3ilQS6YRj4-7ouvM=L! zTCoitGnjL;FlQQOzttbu9Mh-b>y-GahVg6`Kc8MU{BWGmt2up0{R_PkcAKUdr~)usD{H`&Kl1K6pD52nYNG zxPkrl(7MKJ2Iux-GvYV7*+)wINGt=RIY{bZsZ#Do_<2Y*JIfk(?XbqZHkUFPxu`W- zgk4eSjw_dX!{ci5CUy`K)ipbXSE@UgOc+0tiWyw(%pg&4+Ym)s6uP?%M6Dn&s(2qn z{#X?MCV&E&Iwc$kwfr~F|4Z$_O*L5v%W*c+b>=m+Qv+h-aQATK=W!<+2 zplpMbKw_IGrpR)?b7B1(-{lW)rHqPr8yF}%(5`E#=l#Sd#;NyW5qBhSlKaexWWR7i zHo?x)c_ky-rTs*}7)fHHlZ_2UC0#<3uws{|S;soam8*EbC0%YAM$;U@eHK;xiI{5x$q;N`W<>wcl;;BYG&l(1bBLFx- z!XD9XqyNB2Skm$FvjoGUsTSI7KgeG-vPnX}XD0I;E6>zzJ=1N;x&)j4L+D_*c>z&o z|JkUXf6{vm{XNJ^C{F(uTs+IK!}9kq>J}(H%^=+Q3<6D=u4eDjOuMmqf$#!7*%Q_s z!j~WrQtx+PI7V1@G$V(Ma~mZkO$$JRhz#s`NmLnVt1=(J^u7!@@)TUgZA{+HvVu$d zJ@n>3VDlTOeaF(@^AJV!e1rYZy!s2s|H0Swfm$&v$in{`p`^d(G6k<+9rzuO@*gPx z*n98?yeY(SB8gxZRSVIPs%Y}SQm$ncMyOFF9!ae+T+Mb}Ao8W2LnX8)i-I4Jzny@v zV&)b~Z{cA)Y^qN}@|(yK6?Hu})%F{b7d-_nF})ZHxW`_H8b}%Gxh44-sw1)15&KVC zt>2ECfmt)>#_zv#TfzZ25tx2M!3B)we`eNU4xnf1vNH;7pwFGl^|QwFgpu;d0(DX-Cuo98icz6YQDSnn+icVAb4glm zPkO~B78g@`!b7s|mQP$_YaaLWA zjFy4MV0Rk^HoC}Sr_GeP1sZ;ut2YLTF$y-N$-K zwgu|MKBwU>N?oInB3E}$rpie$A0MR&$y=lqy6#v;jrAn=t?$1wc_S3jf0t~3RyN8oyeKfO zndO)2O@HIbn-18Mzq7Oa|NKDzkA?#Vs%>KaEAmCV0cRN+SFaKzra$}g0qgF2m4Jpp z7H{T^a8#qhJNlJ)FyN0ZE?*G;3a+Rw3$hcvh^Z7QeEm`O0@20(9ESXBsCgKSCF)Ra<7h#C z>(M9M&4TEq*wRoSQeWrF2~;cUgYo+OfjZuMgIDka+YG{Jfi7F&FOoeEam64!te4El z(}jy94WsQ9oMugid?b6QGY4-)f|>##RZY-1WFnb(nPeh`0hNq}BqhGpwR_bCz8lSk zQ;`IC{nlb(7;tIr(99rh1=K#vO^gIaPU*ES2@01Tsx9$DjVKN$5o^u`VN3yGylF+j z185v*hr|MdxjbNOtBk{nk)0Y%h(LNtTHAk*2Dkk4tS(0cyPhN$8pfhHnCc|EA~=~T zaxS>5_pKWx)cdx^Fx@8n_}cv%v; z&PlZJQ`Ga2cXm0wJEdTJ=_^dd4{RCWi*(q1}_lW5VELm=MLJ)c1E?^a7%mi zu@>DcxK<5Ys)Ez-p+Q4 z6lA8f(|G5^7c$VV3lSEOHU|M1n_Gg%y~TLZ9rn4dbs=K-ma**ehnE@@`tU-h9gGO_XloHmela z(;XrlAJte+%Fa=U7sc6Y>-M~YCU{+Th4cjQ;{{OnDjtpjNwHDESu$2HWY_%2M*Pq} zRG`*2k0?@s?*kW|%aIrPdz6c{ru!Vf39@=-xPb1_Fq^!FM!+05b|! zf^##7kjdT8H>0I_?0GBMQNO4PRUULD`=cFnu32-wYm=++`aGrMWm<^D&UE4!cACIe z+NGc^Yw}uSq;v{9pH{te<`IZL)5a^n#znZAotVn9%Tv72eoDgiYL3HhO?qc^NZ`0- z=0@M)B4;A>_6zFeX|g$f(#za))fXQlHqmzw+h^11+yDWwROVgv3d{5Mu5Uu;gcxg_i7+Vq#t~w&{c9bmCO?} zXcdkaSE&HGEik7vA}-#8WsLbRcH(48ga_fLtSux9_dDKtlNp&Nt_ETu139Hi{;320 zuYLa)%l-G(iTL~XeJMs(T0@`Oom69oi4t?{7BZ2Y7{7?MBzw<7fM(^zzoA(HK3j2( zFM4-TZaK?L*5U)V+sVf_%93F#VzFFt{Bbj$9!;nB)E3j&;BHtHs~2b z6CaE?$h0eKgD-3~Br&(!Rb3y=TC`=&Q)0GHT*h6{k*1fv)F`I3cB8OM$RKSdO;mdF zQH@GoUNFgQErb80v29vXy*C@O;zNf6!#<~x)VMv`I}f_s4Tz3|y^%{?K-+?2-U91> zQt5o1&mQu`S)z`W*n1@@Z4>pUUL%QFh2y@CpnM$mO3Dqd@jB~>Ho7Exo*cvOGku%+ z*3>!7a3Am+sdcaYjMAf)LU*_v*e2wr5tdvTCOISCV^}}N>x30nh;iA;R@tauuI^0(QKsiW|7R7x1h=N=NUe&q7i)&0E;eO0wq>g z5ksSsVVWjs08PJg#jc@`q<1bzi3jd^d|CV z_`l$aZ$l;?SW(rw44}Vf#F62Q8(qz`VRdXi$d8=8`k zB&RlbPeE5GYOLRh=8R&Hw46MA+gLvpP*>r2Y9*EiPc%kN563n zKp`jdNvUz5mGnlQ^wocvp1esEW1Osz^z8_YN8g1Mv~Pzhsem6Y7dd5Z~82+ozV#V>VEly zzmV`1o6kw>|77j_!K?o)7a6iQnOh=2xC;AMAe2!VM2K3Q6UqREDS(3w=%{1o_k|n( zK$PFS^p}kzhu~ux`k!VE4!d*5sdEQ9I z$JVxSjq&Jt>dY6hq4e~E!&i?7Vm{be3CcLX@a|Hub)US*ym$lOE7s8od-2WP2pLCd zqFXp`$YqEwHcW0R5a>lsBm#H)hl{8IMMz@lS zR)&m^O?KV9TJPtx^@u@)dhD<#`Gs5lN~gh6Z!z~~YL_gB#=Kq9)c(>zuNG7{2)HAj z6vAemj3?E$P{Yz@BFj-y6u-Vr6F4Oe6^9Ovs#NuL5{eUnYW;~Uf#g+i8-=#0TikKB zTMgZMPL>gQQ0gX*U5OmA<4D*nHToMjyzL3KlSj;lh5-HPS` z&#I6M3UtabtR@>G;=Z&BP!+DM-v}vvEf=1g?eMuE$|ElPA%zRNHJ81Y64ykyumx}j z&NbKDTIvvkl1osjr^>RXNPNu`TcK+f9;)}1NuL69< zf9Ep!YxVs!Pk&yIm>B6FU44wS4ADm*^!Zk@z4@3+JpLmYc5f5R%0GaeR0AnZaD5^L zS0Qq5vW0jJ@)AX)G6oLBwJOO5RX*JQTE^^l!8m#1j``6+oF`^r_vu#)Na^S;kx0EdaWCV3XP` zGr1{{Dn7WIJ9kM+MJPH9G$X)FhE7%0Lv5g~T%sKBjGmMeyoY1J7-onk&4&{M2l#c~ z(pF;D(O<68_MM7)y6U=;OBavSSyeo0jdWUB`W#Vy0$y=^Mt>$L1p(@k*Phi<@ebIJ2op1&;7og)fijhvY@;y+JP`vY6|mp%J0wP(m&OfopC$urrhSOML_ zio;BJ6m~WV^P)xEFcxxqpKtaH84HND5!!H5LggKjQ_{tRVk(B`<3LiM389r`hbXh!?&{Z_(TJx)hS2tg4g za6l4yCXpgtP^20XRV=4$vqQ@p7JPc6qB~vd9MLkZtvZF#c%mSx?8QM_V9UIcSvzmQ zQ0(drj#J=rK~UR8On(4zxEU&khw}L{gn!JwiSMf@tm?MggiJvlheNN(sd@34*?6wE zFP_Ad>#>7W!)VNr(AAR65g9n!wD~g?0J~gKfFCR zw{+S0?Kz}0P$E>He2l)Q3ly_oA9bQC3LnMy5=87uPpN%ED&qA?E_wVtw@c_O9t-JW zU6kI_7bva7akbq7Ga+O%#ydQ3VCgnViWA1sNC1B5;OB9KU z`&o%S&wMpzg{8wL@#^q5X|$e|mhS*`+2OLW9|$TB7I-d1UdM5ONen~tdz0Hc4hMla zQg2b~iJd~@ev!f!#$}KGE55aU5v@+UFRQq;fP-iUYb;v=50Mg z;x0E6!HklE?V6p5<50`qC*`*_bT~pwohDhkxUwo34t5vuawi7u-5@JHJ+Z9>PXcrc znxWZ7`7_*NKdS)H!vc1P{%ApHBYTl*>XxgYzV6}%(&iOuFNMA|wT-D+`zWta9B z5wl>WqJlv{^%@`>`fo%z!S?ZaRP-P0Xn$i1|G>fmikuX)u?thOknP%eb ztv*!Z*^I2^T687GF#A6f)WzOLi%+S)vFgw#NQ@H~jMXI0fezYBB^1{sddh{^vPHFb zp|rP0qH>S;lBNG|+*jv^^NU7RgtBw4Je43`Vvs+|40DQg{~KZAnlg@Am=u<#6cR;x z9lA(NHONzj4{p27Y_UJhbekw>5bHiFEfEhoy4Z7pw6!a7jh?rZ;w)s3d$9RjRMeyd zkA~J)#Nl=ns^z*OMFkoKm>hnLNqGE*CjFC2;0t$o0^-Tk@*$HdF^~yV7vHZnwfJBk1+2m`>;8u&^1>LitM;t#bWG zS2{$L;)sND44P$#t&uabXLAE)Dpk-ILO^*APCaFf5t64&MieRi+&RJ%lvT-#8#=S1J)+#a- zJ*J2g^(^$7CHs3it2sNEz2uCqsf0z0=&@YT6r)wAnxs$k4Xd3UKF5M9jtmh>L<;(w zNn&X9wWD|%lv`mqcn%ZeiJ!ndJx1#Hq?KA5P&Et*Wl*t*QI(K=ywS~3{`TnWfA$?U zvF7arem2d7JqzD=c3ozV3|8;PapJ}ja`0Tlz(#F$Sd`X!d9redF1>Z-K~AJr47Ipr zfobQH$sObbrA76y(VK#;yYCWCS!nvZ4U+qGk;B4)^^%4peE{rw z3`KgFZ-ceV-6VTqHJklFiFx;lZD_Rk1m}8;FK@R&m(V5)5Rn<#;es-91H z83u5oxva}tUe~NrH)R}}lOb;<|A5Sm6J&L(qFkSA!AZ!yhu3YCr`~6@*dT{2^``TM zysB4K(f$REPz-?8xxqH(?F%ls%V>yB_nGZf%zqKW5$MdodC|%=A5q}*8vkvL7AX2p z{l5{%5G{~@6nU?tmr<8ss=}ME7HwweAVKc6W4B zq2E@b6KgW7;I(@hbJW=g5U#TQ*gab_rgQx6=XnXKo{{M#<49eBjQLc+Yy|< z#~{!w(}mgMhN5W|9u`&CI`4fc2bufP&3mFUpbO%J@>W*7!HnekF#brOIdK7jy;Q@8 z&7JHl6MjCOT{3m8b=@@nAY3Ek50wr4xh1b9W+=lZlbrcbTQc*COyVtbbjRho>zbvR zhm?EkwJiBGH3PShk85X*hJ3nQfJjBK!qlwDh*rGuFgO}-vXOE&8P8=IDkLuv?|d#W zzcV^OuScL?C5}`HeG3r+eU&KM9Ae{m5j0vePV*c@ajpaKfAKs1=e?r-cMjoyvUo;c z!Y4Ra4Me|)k5n`VIsF-mE_}n(=&fomQZMf0{Z#a|b0ffD6-KTAq~-v( zVL^qBp_F=TS3y`H`CrozGy&H*!{6&3|A!CXXYt0WRY#JRiTKZqoo}6d0W86aQ4*a+ z0GgC=fzZ{0RP1jN<-pW7qM>~W2p|Y{0pf%;hoa3BK z;zSTStB5EiL8{q^g7&4Hzoe{(zb{j>)O`w~hwfybwV=BV(6)VV;p(Bow-&%PQ;ese ztgFYtKm~#qwE$_v_kPcskcBLDd~1TBDgQuOn&vZaq2xm6iqCeI9`N4dP(%{IvCa&{ zDaCn1rs#o|AU|4)vd14fg!Y{eZQ|c;_ivosInxCqsph<|&@r0!37{n_!iLf z-!_N;w!Tor7`q@nRo{dG{hvPEe;;H2+G_Y~UjJIl<}ZEyrLSMMp#L`W{TB}ZRva>f zHi~J*9bLBXoLCW+6-(Y;MM?R&^{f2$D1!!YRspqT6rex0@!uUF{_fMv*?EZc1Yom0 zKM@*4WSP!MoAxTR+ro8 zRCEa~P?-{(f(ky&EueoOBI`5>(=!o#F~j<3`iZaiHIXMA1N~#-hFh_MOhH(p-pz_L zGMF~22J)usRx>Ws27VMtk;0cQfH^VVF1-kJ8e1h5=;FP@?&rkuE{aa;bEkKuB)LihDi&c_uoa#UeOuz} z-t(6vqyKY%AsJcKiQo1XTogD3Q6gfW5H%=+Ha5Wsd89^3w(!!X4t6ih6<2S3tpK^qlRqMY?;K2s|N4CPsQw4|*uSmG)aX*iIU5Iy8^6&aAB!G56N63jINtip5T4dH5` zfwB7aM5WS3=2a)--wrbo8_NOtju}aPo*n z>_iff+_a45X<9)TL5hFO->zK8=P(kD&z9R;PZxlo?8^B5-LbV*)%+GAr}qB6MG*EdV#56n+_A( zSXf%QReLKyiX3Dx>T?^FKv2rT8`Q*6I8u@F}h3lrv@Jk+z!j~05Gn6|sd5mjx5f&mYqkbqPC|tBYYb+J*+l|CX<`{ZWjAl%Z zh7>^>4R(>D(s?*2M~t)CYUs`q6(-3~$!ES~E+dBu`|_jScI8vp&hq(a!34 z4YyvE$kG!?pgeEn6l`($fIDQN9D!1p>ZDvUla4IqX6Q&0j!gIRTf8E8CTjXo^!0|E zRlq@a&QEl_EnXn`ryxJaa)}UpM^;PRD zlL23R@8Df8#_@we63ipn%(YU6X|;`p6jqBb+xhh1^hA$ymj` z|28qmKcOu+UbM3ldp251fEGtZULNmo)T{<){T-vrFoYv8w%D=DUV8h*Fi75`=-KOf z$(l6|0$pMmAFZr8<7r8inlEcuwFfh>*dK@_ zEo4%02(Q><2fy7@A1TLr6}FJtB$gNY;^zP9E#m9;sGegJ82m2*|GDp+lkg0voSi^1HpIS%$m7^rUbE6>0uQj$CWEE(*hh>&Fcm4!a^8cWDb+V0NL);6QL zQa?9E!s(Q$&j$H|;1K}b8P}424g&+}eM4Wt%-#mK>Im)N3mwg3;^ND^i4TcKi;1+Z zSxz1|!MOK(k(oSrdD-5trDY=J9EAPeqgGj-5-Gp9DwS3IbP=2YCgT(XPXfc@y;@-OR%2Qi6KSm_bN#IY>^E3xj;M>d%vJMR_y1Q>H9@ zprvB!XnS63U+ost>@eEH4a6xZkTMnmBzyt5Bm}cn(Y%qbl8}<6C18NvPx`NZK2T;PJ#e4Ql96HdbYd(J99WYa?j)2b$)s#Y*02meC|gYyWZZjAX$WQ zB))tOK_S^eVJ#z+K^%EZCQZ^CB)B|^crHq`>nRYhsGf^lI; zwD_$b^~g+^WLPR0C@Q;nQ?xixq@xwMS6RJdkr?gyZWj4OXS(i@rMHUI85+qFAO$u< zu|QAX%;|H{*)iCNJX#Pqw1u$AYK@D_UrytA#xM0u9m2{XfuaXf1TWnR;9iTZ{Ya0( zA>E#iBt6KOl;pUb=F9$+tT~F{dJdx(aNNOq$ap00>Ml|;R&MjOYt_xMWl8!8K7TX` zhcX67r>dV{1xWfql1c&Ao}8X(6fz0JoU(WNO0e!I0bR8Bc^ia zE;a!LI_tJiL18YZppNQOP=)CncHprX0rcZr=-kLDXq3<1zX3smCf;`P9JrhSs>iKe z5|o^TOcr?66xY)1@k94;DboOw{=hnbA`occmzU5_LHE{AK?ydeAlr}aq`+4&s$ci< zNDa;IFK^Kt@ zWi9ZcCKz}zrUzQDeJ;X4ETfLv%4_gj2`4uM(PesYI!k3yz4{1D;aTl#$P6+jESfap5P&mabf z!NH^fxR<-v4Ig{ZCl8PeKnYxrYJf3eJ~*kkXPxqpW^5<3ZJtz=9YK8;AXwA}h6O>) zX10^!@4G6VC_|4cfZ7nz=a^}SE{6gW0U~!sW6!{P{(|n;7t&(^QEsLjzBmOP*a5<2 zqD*t3Xr$Rt1*e&jCgvZrtV3Eyj`H_q%d9*6S9W<}l}n0|oUZwRCPg785$C{6Dc-^k zfld}^G($~1XpSfVxI~!DlU@QIc|vEX&d|C76k6nShj3K@r~&jL1uT=Vs0TnW4Q-eb zIs+rZ>&h9bMN^*K*9D|@qFwV9!a(!D`0;%Kptu|#>zwK1tSLZ8-YZ8U-&Wz-6F^0r zklC>VV7Wd%lcSlv>p6Co&VF^iI!=JL0qH|`tbzGD155K8mbeFh!P~h${s3@dDQC;! z$7@#s8RQ=u)KI54)c^|(7$tD4iSPFfac9c@cs9F;eGU@n{J1pYBJeBu$outY55&(5 z%Ir4HM*JC|IhE$|_dW2T`zFBZI$vz_7Z5b4F+M+LXCKG~NRBWG+VFk82j|ct0M@{F z9L02gh2*cs%IpZjb=Eep;?vIz*mrbw(roM#p(*|}3aiHrPtcD^&R^$UQOfx-X@-{jEn z1Q0u9$L5=T0K_inhoC`r1>^wy;y2^s03`Tr{halPbPDpVogx3tGYkM)I$xpnV`SK8 z%N??Prr2{6bk@cBdUQOK_3<&VLe6nBPl})c1BUl(aOWoAZ0Z2s&`-2m7S2t_*{lF4 zQ97O^L%*)$pEI9H`HpYObNh0J$zR70RC)2Oz0iHk3z*-psKC>QP61^Q!hs9%A2I`= z%MD0+0nz+jiqHl?rpx2M=}#13q&hZeq4{C;0FhAxjD1HU3yAq&UOZ?y=4}PM+dq^G zMqndF0#-;+6#ba#+bGUVU(Ft1NPaV1=3_B1Gk6zJ!%r0exCWWfY;;3@%CYgx)ScP2 zZ{zdo?!1qX1PtWFA+#CTe!dz>_p99QinM1x#XsavIY)AY(L8luD`aYY7ANJ0>HO>( zSaMb=9TmEBk_@bb%C7@|pbr;0pWttl^R{8w6#yOh>%MV5>mRQJd*u)5baaYlMFLXn zKB4#~`l2m-vss!AV9tl-fT23GO5aDbkh0(M+eaJZfLMP{gljih96Fi54_LHce|G~I zv^QYO$bN$7YH z|ECnrVEcY1e-+@%`3BLiQV`uky@&hlfW zwllG2gMV?>_GIdTiprfZ(ekG;24g&cW2H79#{6@tYmtb_{N%c#ZkGMu@dcnL|3sD$ z|6ru?iD=gb^jH5XCO_{5>hsEb<_~4|3MttF_Jz>*g1P^nV?>zEGY@`t!2X=TKluCo z09*+8yR-mIc;>OniJlg0Q~acR6_~)fKTJ>L3m@Z)YFOHRfZ?{o4lyU3u-cP0S@R7- zZ0e3$;sj2ZHePqY`upvG6PrLh>Cp$Ce@T?@iA2?r2LJ^|oCOSNJ16z?vGU-ti0wZG z2yhZm>4BBnz~!!NqklJ!Crkt8HvhgEqUc|^+jUr$9Pqbb{LUXoHLTFD*NNho4}EaI zFaq&YDW}4K^^p40cc0Ab4WLB+t;R!t3OHcdPs=f}>+pvqI-&39Pc>j5z>F3AHNF$O zar}#2{6lp2fl~_hX2IzEM2$b?i~_^62TV?w*I&+;`A@Y0-mCGSCg3KJfkH=w<*&BP z7~`{fBIkcv>JyE)2n<|fB&PLWuG;{(?_ZRz@fSbv2a#xe&b_~F@`({d0lD`JuzZeK z|EJP{1Frrle82MyxS+r7_n-H>{D7`)w;qR|NY$TO*9){^`(I7UztQ+#CGzLJoLH$N zfcAbJo)(aBzmwTwF+Te@cN_no*+;-zaQL?VujUa*^A89ZrC-F+i{!-Ip1k{CEY-=q zt$)S{f6nT!UiB~Qb;8I$Wsm<4*+a4H{3&QaBz$ov@`wU&`NQKU6m7GBu;BkQUK&8G zGvpMje>)<8VjQs2#7_V4PQODN3LuEUjn)0cnjJ96aq0Q+-0*Pv)HjBY#^bAXWcZt|KcfmBfPPoE;Kv=m0@z;_ z_xH%=1h)SLwH;YDb+JF7j%uI3{4mIeO=t^Wl;tWPirAm*<;kxkpt4Vsguvy zc=(_SuCFBB1EY-|w=1?8-OvUfT zPNV1`k5v4;>qn%}b<1R_EC?R8goL1dh7BaK&`PT}BrZt`8Oe*M60Gg+q{6AYyuryQ zTP{daZ|ac&6!p?U3=--jmvBN7$$4U3kVFDIIM?oThs+N@U?L7&$4;pwZlQzSZ$YF| z_aaH9+VHAAiu-d4zRxn@uJ}@TY}Dpe^o;3+iF3PZE#KQ9pSo}M6VXz90S^(BZ^~>R zz8h&@uGliI1Q_i`Gz<~$$E%9p`G!2;K}vLV-R`#ZgB0f3m=xBm!B@}94sh@o!=W+j zeW4-a;V%vzr&gmGVsltM2$BO*r$${Zx;EcgM-66IB-*KMl@7-#Llb{L5#J|S={HYJ+&r;tgZ;Q=oDpp z%0MPa47T*j@G5Z$s|*^uUj9N(aVS&lUCM)3-(Ja|HnJA0uR0KlL~{mVH73Ut7RRq{ z4&=O9p2B~{WZJ2(_$WDi?(>_Eeolt;1`p0NsSQur$ff%QfkI23C?BH(anD_ zafxaD0U1@^ZloVcE`~xl!&_N8QDwTCEAXqT_Y1+|APXNH&Mc*X3?2B0Hkql`IU*(djfO7;hg8 z2qo#H85ACi>cx~z%0@h%G<0blXTX$AIh@P`D|^w&AGep*nhpKNvq`;x9WSegmW^wVQDr=MnPvShS(nb z0m({nzf~zugngl*_PpusnNkXRMOF|KNP3Zm`Ih6_0hL&+QM6 z9^)B)#W$M^?&@f;N6;I$YS=Xb)fd^q}aw225HKE6gc?X_)vs9RoZrz zY(9(P4aiyz9SEI|SnB4bMKu5dQM_@AUU=nm{gBw*bD^p&18Bu1WrJ@AfrZkrDhcT+}?wnJ1 zNlK5#ErVvV_TcMUHkX0z6=QKJFGZqK$tI&lLLs3p7MVl>`c@ ziDa`3JXD8`9Q4u$7PNMEQX`=ZH+jH~#~5Oc}`4OEU_12H)bepiR}N}|`0kYuD11i{OJ)wz*kB+(6P zn^ec!67PUG9r80Ev1FfaJm$=pL`bVUdAt}(QTv(*5ji>mas`E2XA&WS$jt3j$mvrm zJkO;|3wa9Tr~(n-$(tch0o!%PT@0*MhBGi_L7z6dfo=O;*HC0;_TGTNWKqU|>yS*; z!(e$V8jmO z>`4PvN4OwKMpl-P%?XdrYFqx&?9EDXIPo{CR@2;K%~ zB!$F3cj-Y0a*|XCrLbxR^8vJwgDu0M3p1=G5Ixf&b1by}lcU|RFgtLmOias6ap8;{e>OXh6=-?B1&zjZs zpvV=5xga3VC~|?_buPS{{o+j)$eCzCkWgU6s5&ev8NmqH<%f6;;YSccjI)-x5K9O__tg_RqaUvUS|k|3?gxQk z5q;2ok40~F{E9Y!O7np~E0eNq%AX@ zpX#cQJY$O})(M~D52;kGnN)#Rwij{i1!&s-@!DkVdj~&=_`#2LuZwnBL>$L zppU5G-g1UOb~&XI|wnI|Ec4Y!>Qx& zJgaygPu57j8{eZaeM6BlnBk>J@6oRm&fegFW%R>l2*09JUG?LJLT~gB<<*lw?Zsn)Q_a^EM7EfbQi&jOa*|wE2*Tpd^yi~v>3yE z*)f))^<(b56zXW^5RMcwN5kdHfdsb)Xu}ncD}&^NiD63@s_)ZW*s8tBH3U0Qb!o%J znNp*itzaI`a%ux8I_aDww|A(+x=HL7Uvwfx5S4((+^I3kyIdbWccok&KjW`?B(Kw+ zJytKNyJEnisZ9RyrH#SBLXKuz@z{aM`K1o~!hNmU@RTTYoLIGT%LA3IiRd_q;zXVK zq}+VoL-}!Uo2a@eI?Mt*ls5y-9;i6gHfJK~-1T7mCgWtb-09~|-Odu;-V8F+?Vgw~ zOsBdXw8x~Vmn#f+us+QGj^#@4jJYN)ZP0qc?|DipecOi*mqzQ4)36AeQa#S6Q;&5v zyY{$WBfq}C^HON%dn5W#7ygvNO++=qgx1

    R{|z{*vYXYuvec5hlGM-`6wtZgUS} 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 z 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

    @jMLlvhgKKNj= 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 z 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 XCS7bNKDwi+|M}o{hO& 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

    Co0^X{)f=A>tyO6L-FPCoZk_BN^J+RhuvcMD$0 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 z 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

    q>R9%5l~W5TcROb+!e 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%0Aw<0;cY&FVbcPPHu5woVn0C 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

    F5^!p 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 literal 0 HcmV?d00001 diff --git a/alexa4p3/Hoerprobe.mp3 b/alexa4p3/Hoerprobe.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..22f98f325ae02c1f8e89fa2e3f24a44a7d235087 GIT binary patch literal 107352 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

    (|ceK~mxxD4{Rxe-G9g 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

    
    +Alexa4P3:
    +    class_name: Alexa4P3
    +    class_path: plugins.alexa4p3
    +    service_port: 9000
    +
    + +Das ursprünglich Plugin kann deaktiviertwerden : + +
    
    +#alexa:
    +#    class_name: Alexa
    +#    class_path: plugins.alexa
    +#    service_port: 9000
    +
    + +Idealerweise kopiert man sich seine ganzen conf/yaml Files aus dem Items-Verzeichnis. +und ersetzt dann die "alten" Actions durch die "Neuen". Nachdem der Skill auf Payload V3 umgestellt wurde +muss ein Discover durchgeführt werden. Im besten Fall funktioniert dann alles wie gewohnt. + +In den Items sind die "neuen" V3 Actions zu definieren : + +Zum Beispiel : + +PayloadV2 : turnon +PayloadV3 : TurnOn + +Die Actions unterscheiden sich zwischen Payload V2 und V3 oft nur durch Gross/Klein-Schreibung + +## Icons / Catagories +Optional kann im Item angegeben werden welches Icon in der Alexa-App verwendet werden soll : + + alexa_icon = "LIGHT" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ValueDescriptionNotes
    ACTIVITY_TRIGGERDescribes a combination of devices set to a specific state, when the state change must occur in a specific order. For example, a "watch Netflix" scene might require the: 1. TV to be powered on & 2. Input set to HDMI1.Applies to Scenes
    CAMERAIndicates media devices with video or photo capabilities. 
    CONTACT_SENSORIndicates an endpoint that detects and reports changes in contact between two surfaces. 
    DOORIndicates a door. 
    DOORBELLIndicates a doorbell. 
    LIGHTIndicates light sources or fixtures. 
    MICROWAVEIndicates a microwave oven endpoint. 
    MOTION_SENSORIndicates an endpoint that detects and reports movement in an area. 
    OTHERAn endpoint that cannot be described in one of the other categories. 
    SCENE_TRIGGERDescribes a combination of devices set to a specific state, when the order of the state change is not important. For example a bedtime scene might include turning off lights and lowering the thermostat, but the order is unimportant.Applies to Scenes
    SMARTLOCKIndicates an endpoint that locks. 
    SMARTPLUGIndicates modules that are plugged into an existing electrical outlet.Can control a variety of devices.
    SPEAKERIndicates the endpoint is a speaker or speaker system. 
    SWITCHIndicates in-wall switches wired to the electrical system.Can control a variety of devices.
    TEMPERATURE_SENSORIndicates endpoints that report the temperature only.The endpoint's temperature data is not shown in the Alexa app.
    THERMOSTATIndicates endpoints that control temperature, stand-alone air conditioners, or heaters with direct temperature control. 
    TVIndicates the endpoint is a television. 
    +default = "Switch" (vergleiche : https://developer.amazon.com/docs/device-apis/alexa-discovery.html#display-categories ) + +Optional kann im Item angegeben werden ob es durch Amazon abgefragt werden kann : +
    
    +	alexa_retrievable = true
    +
    + +default = false +**==!! Achtung das sorgt für Traffic auf der Lambda bei Benutzung der Alexa-App !!==** + + +Die sonstigen Parameter aus dem ursprüngliche Alexa-Plugin bleiben erhalten und werden weiterhin genutzt. +(alexa_name / alexa_device / alexa_description / alexa_actions /alexa_item_range) + +Beispiel für Item im .conf-Format: + +
    
    +[OG]
    +    [[Flur]]
    +        name = Flur_Obeschoss
    +        [[[Spots]]]
    +        alexa_name = "Licht Flur OG"
    +        alexa_device = Licht_Flur_OG
    +	alexa_actions = "TurnOn TurnOff"
    +        alexa_icon = "LIGHT"
    +        type = bool
    +        visu_acl = rw
    +        knx_dpt = 1
    +        knx_listen = 1/1/107
    +        knx_send = 1/1/107
    +        enforce_updates = true
    +            [[[[dimmen]]]]
    +                type = num
    +                alexa_device = Licht_Flur_OG
    +                alexa_actions = "AdjustBrightness SetBrightness"
    +                alexa_retrievable= True
    +                alexa_item_range = 0-255
    +                visu_acl = rw
    +                knx_dpt = 5
    +                knx_listen = 1/4/100
    +                knx_send = 1/3/100
    +                knx_init = 1/4/100
    +                enforce_updates = true
    +        [[[Treppe]]]
    +        type = bool
    +        visu_acl = rw
    +        knx_dpt = 1
    +        knx_listen = 1/1/133
    +        knx_send = 1/1/133
    +        enforce_updates = true
    +
    +
    + +im .yaml-Format : + +
    
    +%YAML 1.1
    +---
    +
    +OG:
    +
    +    Flur:
    +        name: Flur_Obeschoss
    +        Spots:
    +            alexa_name: Licht Flur OG
    +            alexa_device: Licht_Flur_OG
    +            alexa_actions: TurnOn TurnOff
    +            alexa_icon: LIGHT
    +            type: bool
    +            visu_acl: rw
    +            knx_dpt: 1
    +            knx_listen: 1/1/107
    +            knx_send: 1/1/107
    +            enforce_updates: 'true'
    +            dimmen:
    +                type: num
    +                alexa_device: Licht_Flur_OG
    +                alexa_actions: AdjustBrightness SetBrightness
    +                alexa_retrievable: 'True'
    +                alexa_item_range: 0-255
    +                visu_acl: rw
    +                knx_dpt: 5
    +                knx_listen: 1/4/100
    +                knx_send: 1/3/100
    +                knx_init: 1/4/100
    +                enforce_updates: 'true'
    +        Treppe:
    +            type: bool
    +            visu_acl: rw
    +            knx_dpt: 1
    +            knx_listen: 1/1/133
    +            knx_send: 1/1/133
    +            enforce_updates: 'true'
    +
    + +## Entwicklung / Einbau von neuen Fähigkeiten +Um weitere Actions hinzuzufügen muss die Datei p3_actions.py mit den entsprechenden Actions ergänzt werden. +(wie ursprünglich als selbstregistrierende Funktion) + +
    
    +
    +@alexa('action_name', 'directive_type', 'response_type','namespace',[]) // in der Datei p3_actions.py
    +@alexa('TurnOn', 'TurnOn', 'powerState','Alexa.PowerController',[]) // in der Datei p3_actions.py
    +
    +
    + +Hierbei ist zu beachten, das für die jeweilige Action die folgenden Paramter übergeben werden : + +action_name = neuer Action-Name z.B.: TurnOn (gleich geschrieben wie in der Amazon-Beschreibung - auch Gross/Klein) + +directive_type = gleich wie action_name (nur notwendig wegen Kompatibilität V2 und V3) + +response_type = Property des Alexa Interfaces +siehe Amazon z.B. : https://developer.amazon.com/docs/device-apis/alexa-brightnesscontroller.html#properties + +namespace = NameSpace des Alexa Interfaces +siehe Amazon z.B.: https://developer.amazon.com/docs/device-apis/list-of-interfaces.html + +[] = Array für Abhängigkeiten von anderen Capabilties (z.B. beim Theromcontroller ThermostatMode und TargetTemperatur) + +In der "service.py" muss für den ReportState der Rückgabewert für die neue Action hinzugefügt werden. +(siehe Quellcode) + +## Alexa-ThermostatController + Thermosensor + +Es kann nun via Alexa die Solltemperatur verändert werden und der Modus des Thermostaten kann umgestellt werden. +Die Konfiguration der YAML-Datei sieht wie folgt aus + +Es müssen beim Thermostaten in YAML die Einträge für : +alexa_thermo_config, alexa_icon, alexa_actions vorgenommen werden. + +alexa_thermo_config = "0:AUTO 1:HEAT 2:COOL 3:ECO 4:ECO" +Hierbei stehen die Werte für für die KNX-Werte von DPT 20 + +
    
    +$00 Auto
    +$01 Comfort
    +$02 Standby
    +$03 Economy
    +$04 Building Protection
    +
    + +Die Modi AUTO / HEAT / COOL / ECO / OFF entsprechen den Alexa-Befehlen aus dem Theromstatconroller +siehe Amazon : https://developer.amazon.com/docs/device-apis/alexa-property-schemas.html#thermostatmode + +
    
    +alexa_icon = "THERMOSTAT" = Thermostatcontroller
    +
    +alexa_icon = "TEMPERATURE_SENSOR" = Temperatursensor
    +
    + +### Thermostatsensor + +Der Temperartursensor wird beim Item der Ist-Temperatur hinterlegt. +Der Thermostatconroller wird beim Thermostat-Item hinterlegt. An Amazon werden die Icons als Array übertragen. +Die Abfrage der Ist-Temperatur muss mit der Action "ReportTemperature" beim Item der Ist-Temperatur hinterlegt werden. + +
    
    +alexa_actions : "ReportTemperature"
    +
    + +Alexa wie ist die Temperatur in der Küche ? + +### Verändern der Temperatur (SetTargetTemperature AdjustTargetTemperature) + +
    
    +alexa_actions = "SetTargetTemperature AdjustTargetTemperature"
    +
    + +Hiermit werden die Solltemperatur auf einen Wert gesetzt oder die Temperatur erhöht. +Diese Actions müssen beim Item des Soll-Wertes des Thermostaten eingetragen werden + +Alexa erhöhe die Temperatur in der Küche um zwei Grad + +Alexa stelle die Temperatur in der Küche auf zweiundzwanzig Grad + +### Thermostatmode + +alexa_actions = "SetThermostatMode" + +Hier wird das Item des Modus angesteuert. Diese Action muss beim Item des Thermostat-Modes eingetragen werden. +Falls keine Modes angegeben wurden wird "0:AUTO" als default gesetzt + +Alexa stelle den Thermostaten Küche auf Heizen + + +
    
    +%YAML 1.1
    +---
    +EG:
    +    name: EG
    +    sv_page: cat_seperator
    +    Kueche:
    +        temperature:
    +            name: Raumtemperatur
    +            alexa_description : "Küche Thermostat"
    +            alexa_name : "Küche Thermostat"
    +            alexa_device : thermo_Kueche 
    +            alexa_thermo_config : "0:AUTO 1:HEAT 2:OFF 3:ECO 4:ECO"
    +            alexa_icon : "THERMOSTAT"
    +            actual:
    +                type: num
    +                sqlite: 'yes'
    +                visu: 'yes'
    +                knx_dpt: 9
    +                initial_value: 21.8
    +                alexa_device : thermo_Kueche 
    +                alexa_retrievable : True
    +                alexa_actions : "ReportTemperature"
    +                alexa_icon : "TEMPERATURE_SENSOR"
    +            SollBasis:
    +                type: num
    +                visu_acl: rw
    +                knx_dpt: 9
    +                initial_value: 21.0
    +                alexa_device : thermo_Kueche 
    +                alexa_actions : "SetTargetTemperature AdjustTargetTemperature"
    +            Soll:
    +                type: num
    +                sqlite: 'yes'
    +                visu: 'yes'
    +                visu_acl: rw
    +                knx_dpt: 9
    +                initial_value: 21.0
    +                alexa_device : thermo_Kueche 
    +            mode:
    +                type: num
    +                visu_acl: rw
    +                knx_dpt: 20
    +                initial_value: 1.0
    +                alexa_device : thermo_Kueche 
    +                alexa_actions : "SetThermostatMode"
    +            state:
    +                type: bool
    +                visu_acl: r
    +                sqlite: 'yes'
    +                visu: 'yes'
    +                knx_dpt: 1
    +                cache: true
    +                alexa_device : thermo_Kueche 
    +
    + +Beispiel für einen MDT-Glastron, der Modus wird auf Objekt 12 in der ETS-Parametrierung gesendet (Hierzu eine entsprechende +Gruppenadresse anlegen) + +
    
    + temperature:
    +            name: Raumtemperatur
    +            alexa_description : "Küche Thermostat"
    +            alexa_name : "Küche Thermostat"
    +            alexa_device : thermo_Kueche 
    +            alexa_thermo_config : "0:AUTO 1:HEAT 2:OFF 3:ECO 4:ECO"
    +            alexa_icon : "THERMOSTAT"
    +        plan:
    +            type: num
    +            visu_acl: rw
    +            database@mysqldb: init
    +            knx_dpt: 9
    +            knx_send: 2/1/2
    +            knx_listen: 2/1/2
    +            knx_cache: 2/1/2
    +            alexa_device : thermo_Kueche 
    +            alexa_actions : "SetTargetTemperature AdjustTargetTemperature"
    +        state:
    +            type: num
    +            visu_acl: r
    +            database@mysqldb: init
    +            knx_dpt: 9
    +            knx_listen: 2/1/1
    +            knx_cache: 2/1/1
    +            alexa_device : thermo_Kueche 
    +            alexa_retrievable : True
    +            alexa_actions : "ReportTemperature"
    +            alexa_icon : "TEMPERATURE_SENSOR"
    +        mode:
    +            type: num
    +            visu_acl: rw
    +            knx_dpt: 20
    +            initial_value: 1.0
    +            alexa_device : thermo_Kueche 
    +            alexa_actions : "SetThermostatMode"
    +
    +        humidity:
    +            type: num
    +            visu_acl: r
    +            database@mysqldb: init
    +            knx_dpt: 9
    +            knx_listen: 2/1/5
    +            knx_cache: 2/1/5
    +
    +        actor_state:
    +            type: num
    +            visu_acl: r
    +            database@mysqldb: init
    +            knx_dpt: '5.001'
    +            knx_listen: 2/1/3
    +            knx_cache: 2/1/3
    +
    +
    + +## Alexa-PowerController + +Alexa schalte das Licht im Flur OG ein + +Mit dem PowerController können beliebige Geräte ein und ausgeschalten werden. +Folgende Paramter sind anzugeben : + +
    
    +	    alexa_actions = "TurnOn TurnOff"
    +
    + +Beispiel + +
    
    +        [[[Licht]]]
    +        type = bool
    +        alexa_name = "Licht Büro"
    +        alexa_description = "Licht Büro"
    +	    alexa_actions = "TurnOn TurnOff"
    +        alexa_retrievable = true
    +        alexa_icon = "LIGHT"
    +        visu_acl = rw
    +        knx_dpt = 1
    +        knx_listen = 1/1/105
    +        knx_send = 1/1/105
    +        enforce_updates = true
    +
    + +## Alexa-BrightnessController +Alexa stelle das Licht am Esstisch auf fünfzig Prozent +Alexa dimme das Licht am Esstisch um zehn Prozent +Folgende Parameter sind anzugeben : + +
    
    +	    alexa_actions = "AdjustBrightness SetBrightness"
    +        alexa_item_range = 0-255
    +
    + +Es kann der BrightnessController mit dem PowerController kombiniert werden + +Beispiel : +
    
    +    [[[Licht_Esstisch]]]
    +    type = bool
    +    alexa_name = "Licht Esstisch"
    +    alexa_actions = "TurnOn TurnOff"
    +    alexa_device = licht_esstisch
    +    alexa_description = "Licht Esstisch"
    +    alexa_icon = "SWITCH"
    +    alexa_retrievable= True
    +    visu_acl = rw
    +	knx_dpt = 1
    +	knx_listen = 1/1/9
    +	knx_send = 1/1/9
    +    enforce_updates = true
    +        [[[[dimmen]]]]
    +        type = num
    +        alexa_device = licht_esstisch
    +        alexa_actions = "AdjustBrightness SetBrightness"
    +        alexa_retrievable= True
    +        alexa_item_range = 0-255
    +        visu_acl = rw
    +        knx_dpt = 5
    +        knx_listen = 1/4/9
    +        knx_send = 1/3/9
    +        knx_init = 1/4/9
    +        enforce_updates = true
    +
    + +## Alexa-PowerLevelController +tbd +## Alexa-PercentageController +tbd +## Alexa-LockController +tbd +## Alexa-CameraStreamContoller +tbd +## Alexa-SceneController + +Alexa aktiviere Szene kommen + +Mit dem Scene-Controller können Szenen aufgerufen werden. +Folgende Parameter sind anzugeben: +
    
    +alexa-actions = "Activate"
    +alexa_item_turn_on = 3
    +alexa_icon = "SCENE_TRIGGER"
    +
    + +Das "alexa_item_turn_on" ist die Nummer der Szene die aufgerufen werden soll. + + +Beispiel Konfiguration : +
    
    +        scene:
    +            type: num
    +            name: scene_kommen
    +            alexa_description : "Szene Kommen"
    +            alexa_name : "Szene Kommen"
    +            alexa_device : Szene_Kommen
    +            alexa_icon : "SCENE_TRIGGER"
    +            alexa_item_turn_on : 3
    +            alexa_actions : "Activate"
    +            alexa_retrievable : false
    +
    diff --git a/alexa4p3/__init__.py b/alexa4p3/__init__.py new file mode 100644 index 000000000..547522ce7 --- /dev/null +++ b/alexa4p3/__init__.py @@ -0,0 +1,200 @@ +# !/usr/bin/env python3 +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2016 Kai Meder +# fork 2018 Andre Kohler +######################################################################### +# This file is part of SmartHomeNG. +# +# SmartHomeNG is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# SmartHomeNG is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with SmartHomeNG. If not, see . +######################################################################### + +from lib.model.smartplugin import SmartPlugin +import logging + +from .device import AlexaDevices, AlexaDevice +from .action import AlexaActions +from .service import AlexaService + +from . import actions_turn +from . import actions_temperature +from . import actions_percentage +from . import actions_lock +from . import p3_action + + +class Alexa4P3(SmartPlugin): + PLUGIN_VERSION = "1.0.0.0.0" + ALLOW_MULTIINSTANCE = False + + def __init__(self, sh, service_host='0.0.0.0', service_port=9000, service_https_certfile=None, + service_https_keyfile=None): + self.logger = logging.getLogger(__name__) + self.sh = sh + self.devices = AlexaDevices() + self.actions = AlexaActions(self.sh, self.logger, self.devices) + self.service = AlexaService(self.logger, self.PLUGIN_VERSION, self.devices, self.actions, + service_host, int(service_port), service_https_certfile, service_https_keyfile) + + def run(self): + self.validate_devices() + self.create_alias_devices() + self.service.start() + self.alive = True + + def stop(self): + self.service.stop() + self.alive = False + + def parse_item(self, item): + # device/appliance + self.logger.debug('Parse-Item') + device_id = None + if 'alexa_device' in item.conf: + device_id = item.conf['alexa_device'] + # supported actions/directives + action_names = None + if 'alexa_actions' in item.conf: + action_names = list(map(str.strip, item.conf['alexa_actions'].split(' '))) + self.logger.debug("Alexa: {}-actions = {}".format(item.id(), action_names)) + for action_name in action_names: + if action_name and self.actions.by_name(action_name) is None: + self.logger.error( + "Alexa: invalid alexa action '{}' specified in item {}, ignoring item".format(action_name, + item.id())) + return None + + # friendly name + name = None + name_is_explicit = None + if 'alexa_name' in item.conf: + name = item.conf['alexa_name'] + name_is_explicit = True + elif action_names and 'name' in item.conf: + name = item.conf['name'] + name_is_explicit = False + + # deduce device-id from name + if name and not device_id: + device_id = AlexaDevice.create_id_from_name(name) + + # skip this item if no device could be determined + if device_id: + self.logger.debug("Alexa: {}-device = {}".format(item.id(), device_id)) + else: + return None # skip this item + + # create device if not yet existing + if not self.devices.exists(device_id): + self.devices.put(AlexaDevice(device_id)) + + device = self.devices.get(device_id) + + # types + if 'alexa_types' in item.conf: + device.types = list(map(str.strip, item.conf['alexa_types'].split(' '))) + self.logger.debug("Alexa: {}-types = {}".format(item.id(), device.types)) + + # friendly name + if name and (not device.name or name_is_explicit): + self.logger.debug("Alexa: {}-name = {}".format(item.id(), name)) + if device.name and device.name != name: + self.logger.warning( + "Alexa: item {} is changing device-name of {} from '{}' to '{}'".format(item.id(), device_id, + device.name, name)) + device.name = name + + # friendly description + if 'alexa_description' in item.conf: + descr = item.conf['alexa_description'] + self.logger.debug("Alexa: {}-description = {}".format(item.id(), descr)) + if device.description and device.description != descr: + self.logger.warning( + "Alexa: item {} is changing device-description of {} from '{}' to '{}'".format(item.id(), device_id, + device.description, + descr)) + device.description = descr + + # alias names + if 'alexa_alias' in item.conf: + alias_names = list(map(str.strip, item.conf['alexa_alias'].split(','))) + for alias_name in alias_names: + self.logger.debug("Alexa: {}-alias = {}".format(item.id(), alias_name)) + device.alias.append(alias_name) + + # value-range + if 'alexa_item_range' in item.conf: + item_min_raw, item_max_raw = item.conf['alexa_item_range'].split('-') + item_min = float(item_min_raw.strip()) + item_max = float(item_max_raw.strip()) + item.alexa_range = (item_min, item_max) + self.logger.debug("Alexa: {}-range = {}".format(item.id(), item.alexa_range)) + + # special turn on/off values + if 'alexa_item_turn_on' in item.conf or 'alexa_item_turn_off' in item.conf: + turn_on = item.conf['alexa_item_turn_on'] if 'alexa_item_turn_on' in item.conf else True + turn_off = item.conf['alexa_item_turn_off'] if 'alexa_item_turn_off' in item.conf else False + item.alexa_range = (turn_on, turn_off) + self.logger.debug("Alexa: {}-range = {}".format(item.id(), item.alexa_range)) + # =============================================== + # P3 - Properties + # =============================================== + if 'alexa_thermo_config' in item.conf: # only for Version 1.0.0.0.0 + thermo_config = item.conf['alexa_thermo_config'] + device.thermo_config = item.conf['alexa_thermo_config'] + self.logger.debug("Alexa: {}-Thermo-Config = {}".format(item.id(), device.thermo_config)) + # Icon for Alexa-App - default = SWITCH + if 'alexa_icon' in item.conf: + icon = item.conf['alexa_icon'] + if not icon in str(device.icon): + device.icon.append(icon) + self.logger.debug("Alexa: {}-added alexa_icon = {}".format(item.id(), device.icon)) + # allows to get status of ITEM, default = false + if 'alexa_retrievable' in item.conf: + retrievable = item.conf['alexa_retrievable'] + device.retrievable = retrievable + self.logger.debug("Alexa: {}-alexa_retrievable = {}".format(item.id(), device.retrievable)) + + if 'alexa_proactivelyReported' in item.conf: + proactivelyReported = item.conf['alexa_proactivelyReported'] + device.proactivelyReported = proactivelyReported + self.logger.debug("Alexa: {}-alexa_proactivelyReported = {}".format(item.id(), device.proactivelyReported)) + + # register item-actions with the device + if action_names: + for action_name in action_names: + device.register(action_name, item) + self.logger.info("Alexa: {} supports {} as device {}".format(item.id(), action_names, device_id, + device.supported_actions())) + + return None + + def _update_values(self): + return None + + def validate_devices(self): + for device in self.devices.all(): + self.logger.debug("Alexa: validating device {}".format(device.id)) + if not device.validate(self.logger): + raise ValueError("Alexa: invalid device {}".format(device.id)) + + def create_alias_devices(self): + for device in self.devices.all(): + alias_devices = device.create_alias_devices() + for alias_device in alias_devices: + self.logger.info( + "Alexa: device {} aliased '{}' via {}".format(device.id, alias_device.name, alias_device.id)) + self.devices.put(alias_device) + + self.logger.info("Alexa: providing {} devices".format(len(self.devices.all()))) diff --git a/alexa4p3/_config.yml b/alexa4p3/_config.yml new file mode 100644 index 000000000..c4192631f --- /dev/null +++ b/alexa4p3/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-cayman \ No newline at end of file diff --git a/alexa4p3/action.py b/alexa4p3/action.py new file mode 100644 index 000000000..07207e790 --- /dev/null +++ b/alexa4p3/action.py @@ -0,0 +1,213 @@ +# +# https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/smart-home-skill-api-reference +# +import uuid +from datetime import datetime + + +import sys + +action_func_registry = [] + +# action-func decorator +def alexa(action_name, directive_type, response_type, namespace, properties ): + def store_metadata(func): + func.alexa_action_name = action_name + func.alexa_directive_type = directive_type + func.alexa_response_type = response_type + func.alexa_namespace = namespace + func.alexa_properties = properties + + action_func_registry.append( func ) + return func + return store_metadata + + +class AlexaActions(object): + def __init__(self, sh, logger, devices): + self.actions = {} + self.actions_by_directive = {} + for func in action_func_registry: + logger.debug("Alexa: initializing action {}".format(func.alexa_action_name)) + action = AlexaAction(sh, logger, devices, func, func.alexa_action_name, func.alexa_directive_type, func.alexa_response_type,func.alexa_namespace, func.alexa_properties) + self.actions[action.name] = action + self.actions_by_directive[action.directive_type] = action + + def by_name(self, name): + return self.actions[name] if name in self.actions else None + + def for_directive(self, directive): + return self.actions_by_directive[directive] if directive in self.actions_by_directive else None + + + +class AlexaAction(object): + def __init__(self, sh, logger, devices, func, action_name, directive_type, response_type, namespace,properties): + self.sh = sh + self.logger = logger + self.devices = devices + self.func = func + self.name = action_name + self.directive_type = directive_type + self.response_type = response_type + #P3 Properties + self.namespace = namespace + self.response_Value = None + self.properties = properties + + def __call__(self, payload): + return self.func(self, payload) + + def items(self, device_id): + device = self.devices.get(device_id) + return device.items_for_action(self.name) if device else [] + + def item_range(self, item, default=None): + return item.alexa_range if hasattr(item, 'alexa_range') else default + + def header(self, name=None): + return { + 'messageId': uuid.uuid4().hex, + 'name': name if name else self.response_type, + 'namespace': 'Alexa.ConnectedHome.Control', + 'payloadVersion': '2' + } + + def respond(self, payload={}): + return { + 'header': self.header(), + 'payload': payload + } + # find Value for Key in Json-structure + # needed for Alexa Payload V3 + def search(self,p, strsearch): + if type(p) is dict: # im Dictionary nach 'language' suchen + if strsearch in p: + tokenvalue = p[strsearch] + if not tokenvalue is None: + return tokenvalue + else: + for i in p: + tokenvalue = self.search(p[i], strsearch) # in den anderen Elementen weiter suchen + if not tokenvalue is None: + return tokenvalue + def replace(self,p, strsearch, newValue): + if type(p) is dict: # im Dictionary nach 'language' suchen + if strsearch in p: + tokenvalue = p[strsearch] + p[strsearch] = newValue + if not tokenvalue is None: + return tokenvalue + else: + for i in p: + tokenvalue = self.search(p, strsearch)(p[i], strsearch) # in den anderen Elementen weiter suchen + if not tokenvalue is None: + return tokenvalue + def GenerateThermoList(self, myModes, listType): + mylist = myModes.split(' ') + myValueList = {} + myModeList = {} + for i in mylist: + key=i.split(':') + myValueList[key[0]]=key[1] + myModeList[key[1]] = key[0] + if listType == 1: + return myValueList + elif listType == 2: + return myModeList + + def p3_AddDependencies(self, orgDirective, dependency, myEndPointID): + now = datetime.now().isoformat() + myTimeStamp = now[0:22]+'Z' + + + for addDependencies in dependency: + AlexaItem = self.devices.get(myEndPointID) + #myItems = AlexaItem.action_items() + # walk over all Items examp..: Item: OG.Flur.Spots.dimmen / Item: OG.Flur.Spots + for myAction in AlexaItem.action_items: + if myAction == addDependencies: # Action für dieses Device gefunden + myitem = AlexaItem.action_items[myAction][0] + myAddValue = myitem() + myAddName = None + if myAction == 'SetThermostatMode': + myModes = AlexaItem.thermo_config + myValueList = self.GenerateThermoList(myModes,1) + myMode = self.search(myValueList, str(int(myAddValue))) + + myAddName = { + "namespace": "Alexa.ThermostatController", + "name": "thermostatMode", + "value": myMode, + "timeOfSample": myTimeStamp, + "uncertaintyInMilliseconds": 5000 + } + elif myAction == 'SetTargetTemperature': + myAddName = { + "namespace": "Alexa.ThermostatController", + "name": "targetSetpoint", + "value": { + "value": myAddValue, + "scale": "CELSIUS" + }, + "timeOfSample": myTimeStamp, + "uncertaintyInMilliseconds": 5000 + } + if myAddName != None: + orgDirective['context']['properties'].append(myAddName) + + return orgDirective + + def p3_respond(self, Request): + myEndpoint = self.search(Request,'endpoint') + myScope = self.search(Request,'scope') + myEndPointID = self.search(Request,'endpointId') + myHeader = self.search(Request,'header') + now = datetime.now().isoformat() + myTimeStamp = now[0:22]+'Z' + self.replace(myHeader,'messageId',uuid.uuid4().hex) + self.replace(myHeader,'name','Response') + self.replace(myHeader,'namespace','Alexa') + + + myReponse = { + "context": { + "properties": [ { + "namespace": self.namespace, + "name": self.response_type, + "value": self.response_Value, + "timeOfSample": myTimeStamp, + "uncertaintyInMilliseconds": 5000 + } ] + }, + "event": { + "header": myHeader + , + "endpoint" : { + "scope": myScope, + "endpointId": myEndPointID + }, + "payload": {} + } + } + + + + + # Check for special needs of dependencies + if len(self.properties) != 0: + myReponse = self.p3_AddDependencies(myReponse, self.properties,myEndPointID) + + + + + + return myReponse + + +# https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/smart-home-skill-api-reference#error-messages +def error(self, error_type, payload={}): + return { + 'header': self.header(error_type), + 'payload': payload + } diff --git a/alexa4p3/actions_lock.py b/alexa4p3/actions_lock.py new file mode 100644 index 000000000..5716e30ab --- /dev/null +++ b/alexa4p3/actions_lock.py @@ -0,0 +1,35 @@ +from datetime import date +from .action import alexa + +DEFAULT_RANGE = (True, False) + +@alexa('getLockState', 'GetLockStateRequest', 'GetLockStateResponse','',[]) +def get_lock_state(self, payload): + items = self.items( payload['appliance']['applianceId'] ) + + current_lock_state = None + for item in items: + locked, unlocked = self.item_range(item, DEFAULT_RANGE) + self.logger.info("Alexa: getLockState({})".format(item.id(), on)) + current_lock_state = 'LOCKED' if item() == locked else 'UNLOCKED' + + return self.respond({ + 'lockState': current_lock_state, + 'applianceResponseTimestamp': date.today().isoformat() + }) + +@alexa('setLockState', 'SetLockStateRequest', 'SetLockStateConfirmation','',[]) +def set_lock_state(self, payload): + items = self.items( payload['appliance']['applianceId'] ) + requested_state = payload['lockState'] + + actual_lock_state = None + for item in items: + locked, unlocked = self.item_range(item, DEFAULT_RANGE) + self.logger.info("Alexa: setLockState({}, {})".format(item.id(), locked)) + item( locked if requested_state == 'LOCKED' else unlocked ) + actual_lock_state = 'LOCKED' if item() == locked else 'UNLOCKED' + + return self.respond({ + 'lockState': actual_lock_state + }) diff --git a/alexa4p3/actions_percentage.py b/alexa4p3/actions_percentage.py new file mode 100644 index 000000000..fd51e5469 --- /dev/null +++ b/alexa4p3/actions_percentage.py @@ -0,0 +1,67 @@ +import os +import sys + + +from .action import alexa + +DEFAULT_RANGE = (0, 100) + +def what_percentage(value, range): + _min, _max = range + return ( (value - _min) / (_max - _min) ) * 100 + +def calc_percentage(percent, range): + _min, _max = range + return (_max - _min) * (percent / 100) + _min + +def clamp_percentage(percent, range): + _min, _max = range + return min(_max, max(_min, percent)) + +@alexa('setPercentage', 'SetPercentageRequest', 'SetPercentageConfirmation','',[]) +def set_percentage(self, payload): + device_id = payload['appliance']['applianceId'] + items = self.items(device_id) + new_percentage = float( payload['percentageState']['value'] ) + + for item in items: + item_range = self.item_range(item, DEFAULT_RANGE) + item_new = calc_percentage(new_percentage, item_range) + self.logger.info("Alexa: setPercentage({}, {:.1f})".format(item.id(), item_new)) + item( item_new ) + + return self.respond() + +@alexa('incrementPercentage', 'IncrementPercentageRequest', 'IncrementPercentageConfirmation','',[]) +def incr_percentage(self, payload): + device_id = payload['appliance']['applianceId'] + items = self.items(device_id) + percentage_delta = float( payload['deltaPercentage']['value'] ) + + for item in items: + item_range = self.item_range(item, DEFAULT_RANGE) + item_now = item() + percentage_now = what_percentage(item_now, item_range) + percentage_new = clamp_percentage(percentage_now + percentage_delta, item_range) + item_new = calc_percentage(percentage_new, item_range) + self.logger.info("Alexa: incrementPercentage({}, {:.1f})".format(item.id(), item_new)) + item( item_new ) + + return self.respond() + +@alexa('decrementPercentage', 'DecrementPercentageRequest', 'DecrementPercentageConfirmation','',[]) +def decr_percentage(self, payload): + device_id = payload['appliance']['applianceId'] + items = self.items(device_id) + percentage_delta = float( payload['deltaPercentage']['value'] ) + + for item in items: + item_range = self.item_range(item, DEFAULT_RANGE) + item_now = item() + percentage_now = what_percentage(item_now, item_range) + percentage_new = clamp_percentage(percentage_now - percentage_delta, item_range) + item_new = calc_percentage(percentage_new, item_range) + self.logger.info("Alexa: decrementPercentage({}, {:.1f})".format(item.id(), item_new)) + item( item_new ) + + return self.respond() diff --git a/alexa4p3/actions_temperature.py b/alexa4p3/actions_temperature.py new file mode 100644 index 000000000..8bdad105f --- /dev/null +++ b/alexa4p3/actions_temperature.py @@ -0,0 +1,108 @@ +from .action import alexa + +DEFAULT_RANGE = (16, 26) + +def clamp_temp(temp, range): + _min, _max = range + return min(_max, max(_min, temp)) + +@alexa('setTargetTemperature', 'SetTargetTemperatureRequest', 'SetTargetTemperatureConfirmation','',[]) +def set_target_temp(self, payload): + device_id = payload['appliance']['applianceId'] + items = self.items(device_id) + + target_temp = float( payload['targetTemperature']['value'] ) + previous_temp = items[0]() if items else 0 + + for item in items: + item_range = self.item_range(item, DEFAULT_RANGE) + item_new = clamp_temp(target_temp, item_range) + self.logger.info("Alexa: setTargetTemperature({}, {:.1f})".format(item.id(), item_new)) + item( item_new ) + + new_temp = items[0]() if items else 0 + + return self.respond({ + 'targetTemperature': { + 'value': new_temp + }, + 'temperatureMode': { + 'value':'AUTO' + }, + 'previousState':{ + 'targetTemperature': { + 'value': previous_temp + }, + 'mode': { + 'value':'AUTO' + } + } + }) + +@alexa('incrementTargetTemperature', 'IncrementTargetTemperatureRequest', 'IncrementTargetTemperatureConfirmation','',[]) +def incr_target_temp(self, payload): + device_id = payload['appliance']['applianceId'] + items = self.items(device_id) + + delta_temp = float( payload['deltaTemperature']['value'] ) + previous_temp = items[0]() if items else 0 + + for item in items: + item_range = self.item_range(item, DEFAULT_RANGE) + item_now = item() + item_new = clamp_temp(item_now + delta_temp, item_range) + self.logger.info("Alexa: incrementTargetTemperature({}, {:.1f})".format(item.id(), item_new)) + item( item_new ) + + new_temp = items[0]() if items else 0 + + return self.respond({ + 'targetTemperature': { + 'value': new_temp + }, + 'temperatureMode':{ + 'value':'AUTO' + }, + 'previousState':{ + 'targetTemperature': { + 'value': previous_temp + }, + 'mode': { + 'value':'AUTO' + } + } + }) + +@alexa('decrementTargetTemperature', 'DecrementTargetTemperatureRequest', 'DecrementTargetTemperatureConfirmation','',[]) +def decr_target_temp(self, payload): + device_id = payload['appliance']['applianceId'] + items = self.items(device_id) + + delta_temp = float( payload['deltaTemperature']['value'] ) + previous_temp = items[0]() if items else 0 + + for item in items: + item_range = self.item_range(item, DEFAULT_RANGE) + item_now = item() + item_new = clamp_temp(item_now - delta_temp, item_range) + self.logger.info("Alexa: decrementTargetTemperature({}, {:.1f})".format(item.id(), item_new)) + item( item_new ) + + new_temp = items[0]() if items else 0 + + return self.respond({ + 'targetTemperature': { + 'value': new_temp + }, + 'temperatureMode':{ + 'value':'AUTO' + }, + 'previousState':{ + 'targetTemperature': { + 'value': previous_temp + }, + 'mode': { + 'value':'AUTO' + } + } + }) diff --git a/alexa4p3/actions_turn.py b/alexa4p3/actions_turn.py new file mode 100644 index 000000000..db3cfef5d --- /dev/null +++ b/alexa4p3/actions_turn.py @@ -0,0 +1,27 @@ +from .action import alexa + +DEFAULT_RANGE = (True, False) + +@alexa('turnOn', 'TurnOnRequest', 'TurnOnConfirmation','',[]) +def turn_on(self, payload): + items = self.items( payload['appliance']['applianceId'] ) + + for item in items: + on, off = self.item_range(item, DEFAULT_RANGE) + self.logger.info("Alexa: turnOn({}, {})".format(item.id(), on)) + if on != None: + item( on ) + + return self.respond() + +@alexa('turnOff', 'TurnOffRequest', 'TurnOffConfirmation','',[]) +def turn_off(self, payload): + items = self.items( payload['appliance']['applianceId'] ) + + for item in items: + on, off = self.item_range(item, DEFAULT_RANGE) + self.logger.info("Alexa: turnOff({}, {})".format(item.id(), off)) + if off != None: + item( off ) + + return self.respond() diff --git a/alexa4p3/aws_lambda.js b/alexa4p3/aws_lambda.js new file mode 100644 index 000000000..c0f27850d --- /dev/null +++ b/alexa4p3/aws_lambda.js @@ -0,0 +1,57 @@ +/* +You need to specify the following environmental variables in the lambda function: +- SMARTHOME_HOST + foobar.dyndns.tld +- SMARTHOME_PORT + 443 - endpoint must be https enabled! +- SMARTHOME_PATH + '/' +- SMARTHOME_AUTH + 'user:password' +*/ +exports.handler = function(event, context, callback) { + var data = JSON.stringify(event) + + var options = { + hostname: process.env.SMARTHOME_HOST, + port: process.env.SMARTHOME_PORT, + path: process.env.SMARTHOME_PATH, + method: 'POST', + auth: process.env.SMARTHOME_AUTH, + headers: { + 'Content-Type': 'application/json', + 'Content-Length': Buffer.byteLength(data) + } + }; + + var https = require('https'); + var req = https.request(options, (res) => { + console.log(`HTTP ${res.statusCode}`); + res.setEncoding('utf8'); + + var responseData = ''; + res.on('data', (dataChunk) => { + responseData += dataChunk + }); + res.on('end', () => { + console.log('raw response:', responseData) + + var response = JSON.parse(responseData); + if (res.statusCode == 200) { + console.info('OK', JSON.stringify(response)) + callback(null, response); + } else { + console.error('Failed', JSON.stringify(response)) + callback('DependentServiceUnavailableError'); + } + }); + }); + req.on('error', (e) => { + console.error('request failed', e); + callback(e); + }); + + console.log('requesting', data) + req.write(data); + req.end(); +} diff --git a/alexa4p3/device.py b/alexa4p3/device.py new file mode 100644 index 000000000..8bc94a7e1 --- /dev/null +++ b/alexa4p3/device.py @@ -0,0 +1,110 @@ +class AlexaDevices(object): + def __init__(self): + self.devices = {} + + def exists(self, id): + return id in self.devices + + def get(self, id): + return self.devices[id] + + def put(self, device): + self.devices[device.id] = device + + def all(self): + return list( self.devices.values() ) + +class AlexaDevice(object): + def __init__(self, id): + self.id = id + self.name = None + self.description = None + self.action_items = {} + self.types = [] + self.alias = [] + #P3 - Properties - A.Kohler + self.thermo_config = '0:AUTO' # default if nothing is in Config-File + self.icon = [] + self.retrievable = False + self.proactivelyReported = False + + @classmethod + def create_id_from_name(cls, name): + import unicodedata + import re + id = name.strip() + id = unicodedata.normalize('NFKD', id).encode('ascii', 'ignore').decode('ascii') + id = id.lower() + return re.sub('[^a-z0-9_-]', '-', id) + + def register(self, action_name, item): + if action_name in self.action_items: + self.action_items[action_name].append(item) + else: + self.action_items[action_name] = [item] + + def supported_actions(self): + return list( self.action_items.keys() ) + + def supports_action(self, action_name): + return action_name in self.action_items + + def backed_items(self): + item_set = set() + for items in self.action_items.values(): + for item in items: + item_set.add( item ) + return list( item_set ) + + def items_for_action(self, action_name): + return self.action_items[action_name] if action_name in self.action_items else [] + + def item_range(self, item): + return self.item_ranges[item] if item in self.item_ranges else None + + def create_alias_devices(self): + alias_devices = [] + for idx, alias_name in enumerate(self.alias): + alias_device_id = "{}-alias{}".format(self.id, idx+1) + + alias_device = AlexaDevice(alias_device_id) + alias_device.name = alias_name + alias_device.description = self.description + alias_device.action_items = self.action_items + alias_device.types = self.types + + alias_devices.append( alias_device ) + + return alias_devices + + def validate(self, logger): + if not self.id: + msg = "Alexa-Device {}: empty identifier".format(self.id) + logger.error(msg) + return False + elif len(self.id) > 128: + msg = "Alexa-Device: {}: identifier '{}' too long >128".format(self.id, self.id) + logger.error(msg) + return False + + if not self.name: + msg = "Alexa-Device {}: empty name".format(self.id) + logger.error(msg) + return False + elif len(self.name) > 128: + msg = "Alexa-Device: {}: name '{}' too long >128".format(self.id, self.name) + logger.error(msg) + return False + + if not self.description: + logger.warning("Alexa-Device {}: empty description, fallback to name '{}' - please set `alexa_description`".format(self.id, self.name)) + self.description = self.name + elif len(self.description) > 128: + msg = "Alexa-Device {}: description '{}' too long >128".format(self.id, self.description) + logger.error(msg) + return False + + if not self.action_items: + logger.warning("Alexa-Device {}: no actions/items registered - please set `alexa_actions`".format(self.id)) + + return True diff --git a/alexa4p3/nginx.md b/alexa4p3/nginx.md new file mode 100644 index 000000000..1cda6067a --- /dev/null +++ b/alexa4p3/nginx.md @@ -0,0 +1,176 @@ +# NGINX +Nginx is a reverse-proxy that exposes web-services on HTTP/80 and HTTPS/443 and routes the request to the actual servers for processing. +So you can serve multiple services using a single nginx instance and let nginx do the tedious part of doing SSL-termination, authentication etc. + +Using Nginx you can: +- expose your router's public IP with HTTP & HTTPS on the Internet +- make multiple web-services from multiple local servers available by letting nginx dispatch to the right service +- HTTPS/SSL/TLS termination - including nice integration with https://letsencrypt.org/ +- simple and widely supported http basic authentication (that is perfectly safe over SSL/TLS) +- very lightweight, minimal memory footprint + +# Install (debian) +`sudo apt-get install nginx` + +# /etc/nginx/nginx.conf +``` +user www-data; +worker_processes 2; +pid /run/nginx.pid; + +events { + worker_connections 768; + # multi_accept on; +} + +http { + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + types_hash_max_size 2048; + server_tokens off; + + # server_names_hash_bucket_size 64; + # server_name_in_redirect off; + + include /etc/nginx/mime.types; + default_type application/octet-stream; + + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE + ssl_prefer_server_ciphers on; + + access_log /var/log/nginx/access.log; + error_log /var/log/nginx/error.log; + + gzip on; + gzip_disable "msie6"; + + # gzip_vary on; + # gzip_proxied any; + # gzip_comp_level 6; + # gzip_buffers 16 8k; + # gzip_http_version 1.1; + # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; + + # include /etc/nginx/conf.d/*.conf; + include /etc/nginx/sites-enabled/*; +} +``` + +# /etc/nginx/include.d/common +``` +# letsencrypt shizzle +ssl_certificate /etc/letsencrypt/live/YOUR-HOME.DYNDNS.TLD/fullchain.pem; +ssl_certificate_key /etc/letsencrypt/live/YOUR-HOME.DYNDNS.TLD/privkey.pem; + +ssl_stapling on; +ssl_stapling_verify on; + +# maintain the .well-known directory alias for letsencrypt & renewals +location /.well-known { + auth_basic off; + alias /var/www/.well-known; +} +``` + +# /etc/nginx/sites-available/your-home +``` +# SSL-Redirect & LetsEncrypt Endpoint +server { + listen 80 default_server; + + # redirect every requested $host (any, even invalid ones) to its SSL URL + location / { + return 301 https://$host$request_uri; + } + + # LetsEncrypt Endpoint + location /.well-known { + alias /var/www/.well-known; + } +} + +# Sitemap +server { + listen 443 ssl default_server; + + access_log /var/log/nginx/sitemap.log combined; + auth_basic "YOUR-HOME.DYNDNS.TLD"; + auth_basic_user_file /etc/nginx/htpasswd; + include /etc/nginx/include.d/common; + + #add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; + + location / { + root /var/www/sitemap; + index index.html; + } +} + +# Alexa +server { + listen 443 ssl; + server_name ALEXA.YOUR-HOME.DYNDNS.TLD; + access_log /var/log/nginx/alexa.log combined; + auth_basic "Alexa"; + auth_basic_user_file /etc/nginx/htpasswd.alexa; + include /etc/nginx/include.d/common; + + location / { + proxy_pass http://192.168.X.Y:9000/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } +} + +# ANOTHER-SERVICE.YOUR-HOME.DYNDNS.TLD +server { + listen 443 ssl; + server_name ANOTHER-SERVICE.YOUR-HOME.DYNDNS.TLD; + access_log /var/log/nginx/ANOTHER-SERVICE.log combined; + auth_basic "ANOTHER-SERVICE"; + auth_basic_user_file /etc/nginx/htpasswd; + include /etc/nginx/include.d/common; + + location / { + proxy_pass http://192.168.X.Z/; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } +} +``` + +# /etc/nginx/sites-enabled/your-home +just create a symlink in `/etc/nginx/sites-enabled/` that points to your config: +`sudo ln -s /etc/nginx/sites-enabled/your-home /etc/nginx/sites-available/your-home` + +# Sitemap +You can create a Sitemap at /var/www/sitemap/index.html to give a nice overview of your services +``` + + + + YOU-HOME + + + + + +``` + +# User & Passwords +/etc/nginx/htpasswd +format is `user:password` +generate passwords using `openssl passwd "YOUR-PASSWORD"` + +# Let's Encrypt SSL Certificate +- download certbot from https://certbot.eff.org/ +- create certificates: `sudo certbot certonly --webroot -w /var/www -d YOUR-HOME.DYNDNS.TLD -d ALEXA.YOUR-HOME.DYNDNS.TLD -d ANOTHER-SERVICE.YOUR-HOME.DYNDNS.TLD` + +further reading http://serverfault.com/questions/768509/lets-encrypt-with-an-nginx-reverse-proxy/784940#784940 diff --git a/alexa4p3/p3_action.py b/alexa4p3/p3_action.py new file mode 100644 index 000000000..c1937aad8 --- /dev/null +++ b/alexa4p3/p3_action.py @@ -0,0 +1,292 @@ +''' +Created on 23.06.2018 + +@author: akohler +''' +import os +import sys +import uuid +from datetime import datetime + + + + +from .action import alexa + +DEFAULT_RANGE = (0, 100) +DEFAULT_RANGE_LOGIC = (True, False) + +def what_percentage(value, range): + _min, _max = range + return ( (value - _min) / (_max - _min) ) * 100 + +def calc_percentage(percent, range): + _min, _max = range + return (_max - _min) * (percent / 100) + _min + +def clamp_percentage(percent, range): + _min, _max = range + return min(_max, max(_min, percent)) + +DEFAULT_TEMP_RANGE = (16, 26) + +def clamp_temp(temp, range): + _min, _max = range + return min(_max, max(_min, temp)) + + +#====================================================== +# Start - A.Kohler +# P3 - Directives +#====================================================== +# Alexa ThermostatController + +@alexa('SetThermostatMode', 'SetThermostatMode', 'thermostatMode','Alexa.ThermostatController',['SetTargetTemperature']) +def SetThermostatMode(self, directive): + # define Mode-Lists + device_id = directive['endpoint']['endpointId'] + items = self.items(device_id) + + AlexaItem = self.devices.get(device_id) + myModes = AlexaItem.thermo_config + myValueList = self.GenerateThermoList(myModes,1) + myModeList = self.GenerateThermoList(myModes,2) + + # End of Modes-List + + + new_Mode = directive['payload']['thermostatMode']['value'] + + + + item_new = myModeList[new_Mode] + for item in items: + self.logger.info("Alexa: SetThermostatMode({}, {})".format(item.id(), item_new)) + item( item_new ) + + #new_temp = items[0]() if items else 0 + + self.response_Value = new_Mode + myValue = self.p3_respond(directive) + return myValue + +@alexa('AdjustTargetTemperature', 'AdjustTargetTemperature', 'targetSetpoint','Alexa.ThermostatController',['SetThermostatMode']) +def AdjustTargetTemperature(self, directive): + device_id = directive['endpoint']['endpointId'] + items = self.items(device_id) + + delta_temp = float( directive['payload']['targetSetpointDelta']['value'] ) + previous_temp = items[0]() if items else 0 + + for item in items: + item_range = self.item_range(item, DEFAULT_TEMP_RANGE) + item_new = clamp_temp(previous_temp + delta_temp, item_range) + self.logger.info("Alexa: AdjustTargetTemperature({}, {:.1f})".format(item.id(), item_new)) + item( item_new ) + + new_temp = items[0]() if items else 0 + + self.response_Value = None + self.response_Value = { + "value": new_temp, + "scale": "CELSIUS" + } + myValue = self.p3_respond(directive) + return myValue + +@alexa('SetTargetTemperature', 'SetTargetTemperature', 'targetSetpoint','Alexa.ThermostatController',['SetThermostatMode']) +def SetTargetTemperature(self, directive): + device_id = directive['endpoint']['endpointId'] + items = self.items(device_id) + + target_temp = float( directive['payload']['targetSetpoint']['value'] ) + previous_temp = items[0]() if items else 0 + + for item in items: + item_range = self.item_range(item, DEFAULT_TEMP_RANGE) + item_new = clamp_temp(target_temp, item_range) + self.logger.info("Alexa: SetTargetTemperature({}, {:.1f})".format(item.id(), item_new)) + item( item_new ) + + new_temp = items[0]() if items else 0 + + self.response_Value = None + self.response_Value = { + "value": new_temp, + "scale": "CELSIUS" + } + myValue = self.p3_respond(directive) + return myValue + + + +# Alexa PowerController + +@alexa('TurnOn', 'TurnOn', 'powerState','Alexa.PowerController',[]) +def TurnOn(self, directive): + device_id = directive['endpoint']['endpointId'] + items = self.items(device_id) + + for item in items: + on, off = self.item_range(item, DEFAULT_RANGE_LOGIC) + self.logger.info("Alexa: turnOn({}, {})".format(item.id(), on)) + if on != None: + item( on ) + self.response_Value = 'ON' + myValue = self.p3_respond(directive) + return myValue + +@alexa('TurnOff', 'TurnOff', 'powerState','Alexa.PowerController',[]) +def TurnOff(self, directive): + device_id = directive['endpoint']['endpointId'] + items = self.items(device_id) + + for item in items: + on, off = self.item_range(item, DEFAULT_RANGE_LOGIC) + self.logger.info("Alexa: turnOff({}, {})".format(item.id(), off)) + if off != None: + item( off ) + self.response_Value = 'OFF' + return self.p3_respond(directive) + + +# Alexa-Doorlock Controller + +@alexa('Lock', 'Lock', 'LockConfirmation','Alexa.LockController',[]) +def Lock(self, directive): + device_id = directive['endpoint']['endpointId'] + items = self.items(device_id) + + for item in items: + on, off = self.item_range(item, DEFAULT_RANGE_LOGIC) + self.logger.info("Alexa: Lock({}, {})".format(item.id(), on)) + if on != None: + item( on ) + self.response_Value = None + self.response_Value = 'LOCKED' + + return self.p3_respond(directive) + +@alexa('Unlock', 'Unlock', 'UnlockConfirmation','Alexa.LockController',[]) +def Unlock(self, directive): + device_id = directive['endpoint']['endpointId'] + items = self.items(device_id) + + for item in items: + on, off = self.item_range(item, DEFAULT_RANGE_LOGIC) + self.logger.info("Alexa: Unlock({}, {})".format(item.id(), off)) + if off != None: + item( off ) + self.response_Value = None + self.response_Value = 'UNLOCKED' + + return self.p3_respond(directive) + + +# Alexa-Brightness-Controller + +@alexa('AdjustBrightness', 'AdjustBrightness', 'brightness','Alexa.BrightnessController',[]) +def AdjustBrightness(self, directive): + device_id = directive['endpoint']['endpointId'] + items = self.items(device_id) + + percentage_delta = float( directive['payload']['brightnessDelta'] ) + + for item in items: + item_range = self.item_range(item, DEFAULT_RANGE) + item_now = item() + percentage_now = what_percentage(item_now, item_range) + percentage_new = clamp_percentage(percentage_now + percentage_delta, item_range) + item_new = calc_percentage(percentage_new, item_range) + self.logger.info("Alexa P3: AdjustBrightness({}, {:.1f})".format(item.id(), item_new)) + item( item_new ) + self.response_Value = None + self.response_Value = int(percentage_new) + + return self.p3_respond(directive) + +@alexa('SetBrightness', 'SetBrightness', 'brightness','Alexa.BrightnessController',[]) +def SetBrightness(self, directive): + device_id = directive['endpoint']['endpointId'] + items = self.items(device_id) + new_percentage = float( directive['payload']['brightness'] ) + + for item in items: + item_range = self.item_range(item, DEFAULT_RANGE) + item_new = calc_percentage(new_percentage, item_range) + self.logger.info("Alexa P3: SetBrightness({}, {:.1f})".format(item.id(), item_new)) + item( item_new ) + self.response_Value = None + self.response_Value = int(new_percentage) + + return self.p3_respond(directive) + + + +# Alexa-Percentage-Controller + +@alexa('AdjustPercentage', 'AdjustPercentage', 'percentage','Alexa.PercentageController',[]) +def AdjustPercentage(self, directive): + device_id = directive['endpoint']['endpointId'] + items = self.items(device_id) + + percentage_delta = float( directive['payload']['percentageDelta'] ) + + for item in items: + item_range = self.item_range(item, DEFAULT_RANGE) + item_now = item() + percentage_now = what_percentage(item_now, item_range) + percentage_new = clamp_percentage(percentage_now + percentage_delta, item_range) + item_new = calc_percentage(percentage_new, item_range) + self.logger.info("Alexa P3: AdjustPercentage({}, {:.1f})".format(item.id(), item_new)) + item( item_new ) + self.response_Value = None + self.response_Value = int(new_percentage) + + return self.p3_respond(directive) + +@alexa('SetPercentage', 'SetPercentage', 'percentage','Alexa.PercentageController',[]) +def SetPercentage(self, directive): + device_id = directive['endpoint']['endpointId'] + items = self.items(device_id) + new_percentage = float( directive['payload']['percentage'] ) + + for item in items: + item_range = self.item_range(item, DEFAULT_RANGE) + item_new = calc_percentage(new_percentage, item_range) + self.logger.info("Alexa P3: SetPercentage({}, {:.1f})".format(item.id(), item_new)) + item( item_new ) + self.response_Value = None + self.response_Value = int(new_percentage) + + return self.p3_respond(directive) + +# Scene Controller + +@alexa('Activate', 'Activate', 'ActivationStarted','Alexa.SceneController',[]) +def Activate(self, directive): + device_id = directive['endpoint']['endpointId'] + items = self.items(device_id) + new_percentage = float( directive['payload']['percentage'] ) + + for item in items: + on, off = self.item_range(item, DEFAULT_RANGE_LOGIC) + item_new = on # Should be the No. of the Scene + self.logger.info("Alexa P3: Activate Scene ({}, {})".format(item.id(), item_new)) + item( item_new ) + self.response_Value = None + self.response_Value = item_new + + return self.p3_respond(directive) + + +#====================================================== +# No directives only Responses for Reportstate +#====================================================== +@alexa('ReportTemperature', 'ReportTemperature', 'temperature','Alexa.TemperatureSensor',[]) +def ReportTemperature(self, directive): + print ("") +#====================================================== +# Ende - A.Kohler +#====================================================== + diff --git a/alexa4p3/plugin.yaml b/alexa4p3/plugin.yaml new file mode 100644 index 000000000..f09561110 --- /dev/null +++ b/alexa4p3/plugin.yaml @@ -0,0 +1,25 @@ +# Metadata for the Smart-Plugin +plugin: + # Global plugin attributes + type: web # plugin type (gateway, interface, protocol, system, web) + description: + de: 'Plugin zur Ansteuerung von SmartHomeNG via Amazon Echo / Alexa, **seit SmartHomeNG v1.3** supports Payload V3' + en: '' + maintainer: AndreK + tester: ???????? +# keywords: iot xyz +# documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page + support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1021150-amazon-alexa-plugin + + version: 1.0.0.0.0 # Plugin version + sh_minversion: 1.3 # minimum shNG version to use this plugin +# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) + multi_instance: False # plugin supports multi instance + classname: Alexa4P3 # class containing the plugin + +parameters: + # Definition of parameters to be configured in etc/plugin.yaml + +item_attributes: + # Definition of item attributes defined by this plugin + diff --git a/alexa4p3/requirements.txt b/alexa4p3/requirements.txt new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/alexa4p3/requirements.txt @@ -0,0 +1 @@ + diff --git a/alexa4p3/service.py b/alexa4p3/service.py new file mode 100644 index 000000000..394e008f1 --- /dev/null +++ b/alexa4p3/service.py @@ -0,0 +1,534 @@ +# https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/steps-to-create-a-smart-home-skill +# https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/smart-home-skill-api-reference +import os +import sys +from argparse import Namespace + + + + +from http.server import BaseHTTPRequestHandler, HTTPServer +import ssl +import json +import uuid +from datetime import datetime + + + +DEFAULT_RANGE = (0, 100) +DEFAULT_RANGE_LOGIC = (True, False) + +def what_percentage(value, range): + _min, _max = range + return ( (value - _min) / (_max - _min) ) * 100 + + + +class AlexaService(object): + def __init__(self, logger, version, devices, actions, host, port, auth=None, https_certfile=None, https_keyfile=None): + self.logger = logger + self.version = version + self.devices = devices + self.actions = actions + + self.logger.info("Alexa: service setup at {}:{}".format(host, port)) + + handler_factory = lambda *args: AlexaRequestHandler(logger, version, devices, actions, *args) + self.server = HTTPServer((host, port), handler_factory) + + if https_certfile: # https://www.piware.de/2011/01/creating-an-https-server-in-python/ + self.logger.info("Alexa: enabling SSL/TLS support with cert-file {} & key-file {}".format(https_certfile, https_keyfile)) + # TODO: client-certificates can be handled here as well: https://docs.python.org/2/library/ssl.html + self.server.socket = ssl.wrap_socket(self.server.socket, server_side=True, certfile=https_certfile, keyfile=https_keyfile) + + def start(self): + self.logger.info("Alexa: service starting") + self.server.serve_forever() + + def stop(self): + self.logger.info("Alexa: service stopping") + self.server.shutdown() + +class AlexaRequestHandler(BaseHTTPRequestHandler): + def __init__(self, logger, version, devices, actions, *args): + self.logger = logger + self.version = version + self.devices = devices + self.actions = actions + BaseHTTPRequestHandler.__init__(self, *args) + + # find Value for Key in Json-structure + # needed for Alexa Payload V3 + + def search(self,p, strsearch): + if type(p) is dict: + if strsearch in p: + tokenvalue = p[strsearch] + if not tokenvalue is None: + return tokenvalue + else: + for i in p: + tokenvalue = self.search(p[i], strsearch) + if not tokenvalue is None: + return tokenvalue + def replace(self,p, strsearch, newValue): + if type(p) is dict: + if strsearch in p: + tokenvalue = p[strsearch] + p[strsearch] = newValue + if not tokenvalue is None: + return tokenvalue + else: + for i in p: + tokenvalue = self.search(p[i], strsearch) + if not tokenvalue is None: + return tokenvalue + + def GenerateThermoList(self, myModes, listType): + mylist = myModes.split(' ') + myValueList = {} + myModeList = {} + for i in mylist: + key=i.split(':') + myValueList[key[0]]=key[1] + myModeList[key[1]] = key[0] + if listType == 1: + return myValueList + elif listType == 2: + return myModeList + def do_POST(self): + + self.logger.debug("{} {} {}".format(self.request_version, self.command, self.path)) + try: + length = int(self.headers.get('Content-Length')) + data = self.rfile.read(length).decode('utf-8') + req = json.loads(data) + #====================================== + # test Payloadversion + #====================================== + payloadVersion = self.search( req,'payloadVersion') + #====================================== + # PayloadVersion = 2 -> Standard Handling + #====================================== + + if payloadVersion == '2': + + self.logger.debug("Alexa: received Request with payload : 2") + header = req['header'] + payload = req['payload'] + + if header['namespace'] == 'Alexa.ConnectedHome.System': + return self.handle_system(header, payload) + + elif header['namespace'] == 'Alexa.ConnectedHome.Discovery': + return self.handle_discovery(header, payload) + + elif header['namespace'] == 'Alexa.ConnectedHome.Control': + return self.handle_control(header, payload) + + else: + msg = "unknown `header.namespace` '{}'".format(header['namespace']) + self.logger.error(msg) + self.send_error(400, explain=msg) + #====================================== + # PayloadVersion = 3 -> new Handling + #====================================== + elif payloadVersion == '3': + self.logger.debug("Alexa: received Request with payload : 3") + mydirective = self.search( req,'directive') + header = self.search( req,'header') + payload = self.search( req,'payload') + if header['namespace'] == 'Alexa.Discovery': + return self.p3_handle_discovery(header, payload) + if header['namespace'] == 'Alexa': + return self.p3_handle_control(header, payload,mydirective) + + if mydirective != None: + return self.p3_handle_control(header, payload,mydirective) + except Exception as e: + self.send_error(500, explain=str(e)) + + def respond(self, response): + data = json.dumps(response).encode('utf-8') + self.send_response(200) + self.send_header('Content-Type', 'application/json') + self.send_header('Content-Length', len(data)) + self.end_headers() + self.wfile.write(data) + #======================================================== + # A.Kohler 22.06.2018 + #======================================================== + + def handle_system(self, header, payload): + directive = header['name'] + self.logger.debug("Alexa: system-directive '{}' received".format(directive)) + + if directive == 'HealthCheckRequest': + self.respond(self.confirm_health(payload)) + else: + msg = "unknown `header.name` '{}'".format(directive) + self.logger.error(msg) + self.send_error(400, explain=msg) + + def confirm_health(self, payload): + requested_on = payload['initiationTimestamp'] + self.logger.debug("Alexa: confirming health as requested on {}".format(requested_on)) + return { + 'header': self.header('HealthCheckResponse', 'Alexa.ConnectedHome.System'), + 'payload': { + 'description': 'The system is currently healthy', + 'isHealthy': True + }} + + def handle_discovery(self, header, payload): + directive = header['name'] + self.logger.debug("AlexaP3: discovery-directive '{}' received".format(directive)) + + if directive == 'DiscoverAppliancesRequest': + self.respond(self.discover_appliances()) + else: + msg = "unknown `header.name` '{}'".format(directive) + self.logger.error(msg) + self.send_error(400, explain=msg) + + + # Handling für Payload V3 Discovery + + def p3_handle_discovery(self, header, payload): + directive = header['name'] + self.logger.debug("AlexaP3: discovery-directive '{}' received".format(directive)) + + if directive == 'Discover': + self.respond(self.p3_discover_appliances()) + else: + msg = "unknown `header.name` '{}'".format(directive) + self.logger.error(msg) + self.send_error(400, explain=msg) + + def p3_discover_appliances(self): + discovered = [] + for device in self.devices.all(): + mycapabilities = [] + + newcapa = {"type": "AlexaInterface", + "interface": "Alexa", + "version": "3" + } + mycapabilities.append(newcapa) + + # Standard capability for Connectivity + newcapa = {"type": "AlexaInterface", + "interface": "Alexa.EndpointHealth", + "version": "3", + "properties": { + "supported": [ + { + "name": "connectivity" + } + ], + "proactivelyReported": False, + "retrievable": True + } + } + mycapabilities.append(newcapa) + + # Start - Check Namespaces for Actions + myNameSpace = {} + myItems = device.backed_items() + for Item in myItems: + # Get all Actions for this item + action_names = list( map(str.strip, Item.conf['alexa_actions'].split(' ')) ) + # über alle Actions für dieses item + for myActionName in action_names: + myAction = self.actions.by_name(myActionName) + if myAction.namespace not in str(myNameSpace): + myNameSpace[myAction.namespace] = myAction.response_type + + for NameSpace in myNameSpace: + print (NameSpace, 'correspondend to ', myNameSpace[NameSpace]) + # End - Check Namespaces + + + + if len(myNameSpace) != 0: + for NameSpace in myNameSpace: + + newcapa = {} + newcapa = { + "type": "AlexaInterface", + "interface": NameSpace, + "version": "3", + "properties": { + "supported": [ + { + "name": myNameSpace[NameSpace] + } + ], + "proactivelyReported": device.proactivelyReported, + "retrievable": device.retrievable + } + } + # Check of special NameSpace + if NameSpace == 'Alexa.ThermostatController': + AlexaItem = self.devices.get(device.id) + myModeList = self.GenerateThermoList(AlexaItem.thermo_config, 2) + myModes = [] + for mode in myModeList: + myModes.append(mode) + mysupported = { + "supportsScheduling": False, + "supportedModes": + myModes + } + newcapa['properties']['configuation'] = mysupported + mysupported=[ + {"name" : 'thermostatMode'}, + {"name" : 'targetSetpoint'} + ] + newcapa['properties']['supported'] = mysupported + + + + # End Check special Namespace + mycapabilities.append(newcapa) + if device.icon == None: + device.icon = ["SWITCH"] + appliance = { + "endpointId": device.id, + "friendlyName": device.name, + "description": "smarthomeNG.alexa-device", + "manufacturerName": "smarthomeNG.alexa P3", + "displayCategories": + device.icon, + "cookie": { + 'extraDetail{}'.format(idx+1) : item.id() for idx, item in enumerate(device.backed_items()) + }, + "capabilities" : + mycapabilities + } + discovered.append(appliance) + return { + "event": { + "header": { + "namespace": "Alexa.Discovery", + "name": "Discover.Response", + "payloadVersion": "3", + "messageId": uuid.uuid4().hex + }, + "payload": { + "endpoints": + discovered + } + } + } + + + # https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/smart-home-skill-api-reference#discovery-messages + + def discover_appliances(self): + discovered = [] + for device in self.devices.all(): + appliance = { + 'actions': device.supported_actions(), + 'additionalApplianceDetails': { + 'item{}'.format(idx+1) : item.id() for idx, item in enumerate(device.backed_items()) + }, + 'applianceId': device.id, + 'friendlyDescription': device.description, + 'friendlyName': device.name, + 'isReachable': True, + 'manufacturerName': 'smarthomeNG.alexa', + 'modelName': 'smarthomeNG.alexa-device', + 'version': self.version + } + if device.types: + appliance['applianceTypes'] = device.types + discovered.append(appliance) + + return { + 'header': self.header('DiscoverAppliancesResponse', 'Alexa.ConnectedHome.Discovery'), + 'payload': { + 'discoveredAppliances': discovered + } + } + # ================================================ + # Resportstate for all devices + # ================================================ + + def p3_ReportState(self, directive): + now = datetime.now().isoformat() + myTimeStamp = now[0:22]+'Z' + device_id = directive['endpoint']['endpointId'] + + AlexaItem = self.devices.get(device_id) + myItems = AlexaItem.backed_items() + Properties = [] + # walk over all Items examp..: Item: OG.Flur.Spots.dimmen / Item: OG.Flur.Spots + for Item in myItems: + # Get all Actions for this item + action_names = list( map(str.strip, Item.conf['alexa_actions'].split(' ')) ) + # über alle Actions für dieses item + for myActionName in action_names: + myAction = self.actions.by_name(myActionName) + # all informations colletec (Namespace, ResponseTyp, ..... + # check if capabilitie is alredy in + self.logger.info("Alexa: ReportState", Item._name) + if myAction.response_type not in str(Properties): + Propertyname = myAction.response_type + if myAction.namespace == "Alexa.PowerController": + myValue=Item() + if myValue == 0: + myValue = 'OFF' + elif myValue == 1: + myValue = 'ON' + elif myAction.namespace == "Alexa.BrightnessController": + item_range = Item.alexa_range + item_now = Item() + myValue = int(what_percentage(item_now, item_range)) + + elif myAction.namespace == "Alexa.LockController": + myValue = 'LOCKED' + + elif myAction.namespace == "Alexa.PercentageController": + item_range = Item.alexa_range + item_now = Item() + myValue = int(what_percentage(item_now, item_range)) + + elif myAction.namespace == "Alexa.ThermostatController" and myAction.response_type == 'targetSetpoint': + item_now = Item() + myValue = { + "value": item_now, + "scale": "CELSIUS" + } + elif myAction.namespace == "Alexa.ThermostatController" and myAction.response_type == 'thermostatMode': + item_now = Item() + myModes = AlexaItem.thermo_config + myValueList = self.GenerateThermoList(myModes,1) + myIntMode = int(item_now) + myMode = self.search(myValueList, str(myIntMode)) + + myValue = myMode + + elif myAction.namespace == 'Alexa.TemperatureSensor': + item_now = Item() + myValue = { + "value": item_now, + "scale": "CELSIUS" + } + MyNewProperty = { + "namespace":myAction.namespace, + "name":Propertyname, + "value":myValue, + + "timeOfSample":myTimeStamp, + "uncertaintyInMilliseconds":1000 + } + Properties.append(MyNewProperty) + + # Add the EndpointHealth Property + MyNewProperty ={ + "namespace": "Alexa.EndpointHealth", + "name": "connectivity", + "value": { + "value": "OK" + }, + "timeOfSample": myTimeStamp, + "uncertaintyInMilliseconds": 5000 + } + Properties.append(MyNewProperty) + + myEndpoint = self.search(directive,'endpoint') + myScope = self.search(directive,'scope') + myEndPointID = self.search(directive,'endpointId') + myHeader = self.search(directive,'header') + now = datetime.now().isoformat() + myTimeStamp = now[0:22]+'Z' + self.replace(myHeader,'messageId',uuid.uuid4().hex) + self.replace(myHeader,'name','StateReport') + self.replace(myHeader,'namespace','Alexa') + + + myResponse = { + "context": { + "properties": Properties + }, + "event": { + "header": myHeader + , + "endpoint" : { + "scope": myScope, + "endpointId": myEndPointID + }, + "payload": {} + } + } + + + + return myResponse + + def p3_handle_control(self, header, payload,mydirective): + directive = header['name'] + + self.logger.debug("Alexa: control-directive '{}' received".format(directive)) + if header['name'] == 'ReportState': + directive = header['namespace']+header['name'] + try: + self.respond( self.p3_ReportState(mydirective)) + return + except Exception as e: + self.logger.error("Alexa P3: execution of control-directive '{}' failed: {}".format(directive, e)) + self.respond({ + 'header': self.header('DriverInternalError', 'Alexa.ConnectedHome.Control'), + 'payload': {} + }) + return + + + action = self.actions.for_directive(directive) + if action: + try: + self.respond( action(mydirective) ) + except Exception as e: + self.logger.error("Alexa P3: execution of control-directive '{}' failed: {}".format(directive, e)) + self.respond({ + 'header': self.header('DriverInternalError', 'Alexa.ConnectedHome.Control'), + 'payload': {} + }) + else: + self.logger.error("Alexa P3: no action implemented for directive '{}'".format(directive)) + self.respond({ + 'header': self.header('UnexpectedInformationReceivedError', 'Alexa.ConnectedHome.Control'), + 'payload': {} + }) + + + def handle_control(self, header, payload): + directive = header['name'] + self.logger.debug("Alexa: control-directive '{}' received".format(directive)) + + action = self.actions.for_directive(directive) + if action: + try: + self.respond( action(payload) ) + except Exception as e: + self.logger.error("Alexa: execution of control-directive '{}' failed: {}".format(directive, e)) + self.respond({ + 'header': self.header('DriverInternalError', 'Alexa.ConnectedHome.Control'), + 'payload': {} + }) + else: + self.logger.error("Alexa: no action implemented for directive '{}'".format(directive)) + self.respond({ + 'header': self.header('UnexpectedInformationReceivedError', 'Alexa.ConnectedHome.Control'), + 'payload': {} + }) + + def header(self, name, namespace): + return { + 'messageId': uuid.uuid4().hex, + 'name': name, + 'namespace': namespace, + 'payloadVersion': '2' + } + From 73462a0a454a21517ab45e1d14cd72767a0e470e Mon Sep 17 00:00:00 2001 From: psilo909 Date: Tue, 18 Dec 2018 16:28:40 +0100 Subject: [PATCH 466/705] AVM: added webfunction for reconnection of internet (WAN) --- avm/__init__.py | 4 ++++ avm/locale.yaml | 10 +++++++++- avm/webif/templates/index.html | 5 +++-- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/avm/__init__.py b/avm/__init__.py index abfc7a253..10b59d517 100644 --- a/avm/__init__.py +++ b/avm/__init__.py @@ -2256,3 +2256,7 @@ def index(self, reload=None, action=None): @cherrypy.expose def reboot(self): self.plugin.reboot() + + @cherrypy.expose + def reconnect(self): + self.plugin.reconnect() diff --git a/avm/locale.yaml b/avm/locale.yaml index afc11879c..e5eb69216 100755 --- a/avm/locale.yaml +++ b/avm/locale.yaml @@ -22,4 +22,12 @@ plugin_translations: 'Wollen Sie das Gerät wirklich neu starten?': 'de': '=' 'en': 'Do you really want to reboot the device?' - 'fr': '' \ No newline at end of file + 'fr': '' + 'Reconnect WAN': {'de': '=', 'en': '=', 'fr': ''} + 'Wollen Sie die Internetverbindung wirklich neu aufbauen?n?': + 'de': '=' + 'en': 'Do you really want to reconnect the internet connection?' + 'fr': '' + + + diff --git a/avm/webif/templates/index.html b/avm/webif/templates/index.html index 71d586ee4..6303a809b 100644 --- a/avm/webif/templates/index.html +++ b/avm/webif/templates/index.html @@ -55,8 +55,9 @@ {% endblock %} -{% block buttons %} - +{% block buttons %} + + {% endblock buttons %} {% block bodytab1 %} From 57b50910566ba52852b891fdeb7b7ec6b76b73e1 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Wed, 19 Dec 2018 07:35:01 +0100 Subject: [PATCH 467/705] drexelundweiss Plugin: Update aerosilent Exos --- drexelundweiss/aerosilent_exos.txt | 300 +++++++++++++++-------------- 1 file changed, 152 insertions(+), 148 deletions(-) diff --git a/drexelundweiss/aerosilent_exos.txt b/drexelundweiss/aerosilent_exos.txt index 9ef3876a9..bb740bb51 100644 --- a/drexelundweiss/aerosilent_exos.txt +++ b/drexelundweiss/aerosilent_exos.txt @@ -1,148 +1,152 @@ -;;;;;;; -5328;Absenkung der Lüfterstufe 1;30;70;1;0;R/W;LU -1066;Aktive Lüfterstufe;0;4;1;0;R;LU -1444;Anforderung Brand;0;1;1;0;R/W;LU -1292;Anforderung der Ventilatoren durch Wärmepumpe;0;1;1;0;R;LU -1336;Anforderung der Ventilatoren durch Zonenregelung;0;1;1;0;R;LU -1338;Anforderung Disbalance (Boilerüberwärmung);0;1;1;0;R;LU -1356;Anforderung LST3 Feuchte;0;1;1;0;R;LU -1450;Anforderung Nachtkühlung;0;1;1;0;R;LU -1218;Anforderung: Beschattung;0;1;1;0;R;LU -1216;Anforderung: Bypassklappe;0;1;1;0;R;LU -1462;Anforderung: Extern-Heizstufe 2;0;1;1;0;R;LU -228;Anforderung: LST3_EXT;0;1;1;0;R;LU -1032;Anforderung: Raum-Heizstufe ;0;1;1;0;R;LU -1034;Anforderung: Raum-Heizstufe 2;0;1;1;0;R;LU -1198;Anforderung: Sole für Außenlufterwärmung;0;1;1;0;R;LU -1322;Anforderung: Sommerautomatik;0;1;1;0;R;LU -1422;Anforderung: Sperre Venti bei Abtauen;0;1;1;0;R;LU -202;Außenluft;-28000;100000;100;1;R;LU -5304;Außenluftfühler vorhanden?;0;1;1;0;R;LU -286;Außentemp.;-28000;100000;100;1;R;LU -1412;Außentemperatur (gedämpft);-50000000;50000000;100000;1;R;LU -5668;Außentemperatur Nachtauskühlung;5000;20000;100;1;R/W;LU -5632;Außentemperatur vorhanden;0;1;1;0;R;LU -5336;Beschattungsfunktion;0;1;1;0;R;LU -5002;Betriebsar;0;7;1;0;R/W;LU -1300;Betriebsart Sommerautomatik;0;2;1;0;R;LU -902;Betriebsstunden: Abluftventilator;0;600000000;60;0;R;LU -964;Betriebsstunden: Beschattung;0;600000000;60;0;R;LU -932;Betriebsstunden: Bypassklappe;0;600000000;60;0;R;LU -928;Betriebsstunden: Feinstaubfilter;0;600000000;60;0;R;LU -940;Betriebsstunden: Frostschutzeinrichtung;0;600000000;60;0;R;LU -926;Betriebsstunden: Grobstaubfilter;0;600000000;60;0;R;LU -912;Betriebsstunden: Heizstufe 1;0;600000000;60;0;R;LU -914;Betriebsstunden: Heizstufe 2;0;600000000;60;0;R;LU -962;Betriebsstunden: Lüfterstufe 0;0;600000000;60;0;R;LU -904;Betriebsstunden: Lüfterstufe 1;0;600000000;60;0;R;LU -906;Betriebsstunden: Lüfterstufe 2;0;600000000;60;0;R;LU -908;Betriebsstunden: Lüfterstufe 3;0;600000000;60;0;R;LU -944;Betriebsstunden: Reduzierte Lüfterstufe;0;600000000;60;0;R;LU -970;Betriebsstunden: Sole-Kreis Außenluft;0;600000000;60;0;R;LU -900;Betriebsstunden: Zuluftventilator;0;600000000;60;0;R;LU -838;Brandmeldealarm;0;1;1;0;R;LU -5068;Brandmeldeanlage vorhanden?;0;1;1;0;R;LU -230;CO2;100;1950;1;0;R;LU -1048;CO2-Messung;0;1;1;0;R/W;LU -5054;CO2-Sensor vorhanden?;0;1;1;0;R;LU -5210;Datum;0;99999999;1;0;R/W;LU -5020;Drehzahl Abluftventilator;0;10000;100;0;R/W;LU -1094;Drehzahl Abluftventilator;0;10000;100;0;R;LU -1092;Drehzahl Zuluftventilator;0;10000;100;0;R;LU -5018;Drehzahl Zuluftventilator;0;10000;100;0;R/W;LU -1232;Druckdifferenz Abluft;0;5000;1;1;R;LU -1230;Druckdifferenz Zuluft;0;5000;1;1;R;LU -5330;Erhöhung der Lüfterstufe 3;30;100;1;0;R/W;LU -5034;Feinstaubfilter vorhanden?;0;1;1;0;R;LU -1042;Feinstaubfilter wechseln!;0;127;1;0;R;LU -7004;Feinstaubfilter wechseln!;0;1;1;0;R;LU -5032;Feinstaubfilter: Standzeit;131400;1051200;60;0;R;LU -5384;Funktion "Sommerautomatik";0;1;1;0;R;LU -5492;Funktion HEIZUNG+;0;1;1;0;R/W;LU -5000;Gerätetyp;1;92;1;0;R;LU -946;Gesamt beförderte Kubikmeter;0;600000000;1;0;R;LU -960;Gesamt beförderte Luftmenge seit Filterwechsel;0;600000000;1;0;R;LU -5360;Grenztemperatur für Vereisungsschutz;-40000;-8000;1000;0;R/W;LU -5154;Grobstaubfilter vorhanden?;0;1;0;0;R;LU -7002;Grobstaubfilter wechseln!;0;1;1;0;R;LU -1040;Grobstaubfilter wechseln!;0;127;1;0;R;LU -5164;Grobstaubfilter: Betriebsart Filterüberwachung;1;3;1;0;R;LU -5166;Grobstaubfilter: Maximales Fördervolumen;100000;1500000;1;0;R;LU -5030;Grobstaubfilter: Standzeit;131400;1051200;60;0;R;LU -1178;Hardwaretype;1;6;1;0;R;LU -5672;Hysterese Nachtauskühlung Außenluft;2000;5000;100;1;R/W;LU -5676;Hysterese Nachtauskühlung Differenz Raum außen;1000;5000;100;1;R/W;LU -5670;Hysterese Nachtauskühlung Raum;2000;5000;100;1;R/W;LU -7000;Information;0;2147483647;1;0;R;LU -1186;Ist-Drehzahl Abluftventilator;0;5000;1;0;R;LU -1184;Ist-Drehzahl Zuluftventilator;0;5000;1;0;R;LU -1240;Ist-Volumenstrom Abluft;0;1000;1;0;R;LU -1238;Ist-Volumenstrom Zuluft;0;1000;1;0;R;LU -238;Kontakt: Brandmeldealarm;0;1;1;0;R;LU -5192;Kühlung vorhanden?;0;1;1;0;R;LU -5270;Maximal zulässige Drehzahl Abluftventilator;1500;6000;1;0;R/W;LU -5268;Maximal zulässige Drehzahl Zuluftventilator;1500;6000;1;0;R/W;LU -5530;Minimale Drehzahl Abluftventilator;0;10000;100;0;R/W;LU -5528;Minimale Drehzahl Zuluftventilator;0;10000;100;0;R/W;LU -5674;Nachtauskühlung Differenz Raum zu Außenluft;2000;10000;100;1;R/W;LU -5678;Nachtauskühlung vorhanden;0;1;1;0;R;LU -5168;Pelletofen vorhanden?;0;1;1;0;R;LU -5282;Pelletofen: Anlaufverzögerung;1;60;1;0;R;LU -5284;Pelletofen: Mindestlaufzeit;1;60;1;0;R;LU -200;Raum;-28000;100000;100;1;R/W;LU -282;Raumfeuchte;500;100000;100;1;R/W;LU -5558;Raumfeuchte Vorhanden;0;1;1;0;R;LU -5016;Raum-Soll;14000;26000;100;1;R/W;LU -5666;Raumsollwert Nachtauskühlung;18000;28000;100;1;R/W;LU -5338;Raumtemperatur: Beschattung;20000;26000;100;1;R/W;LU -252;Relaiskontakt: EXT (LU);0;1;1;0;R;LU -226;Revisionstüre;0;1;1;0;R;LU -1084;Soll-Volumenstrom Abluft;0;1000;1;0;R;LU -5060;Soll-Volumenstrom Lüfterstufe 2;40;600;1;0;R/W;LU -1082;Soll-Volumenstrom Zuluft;0;1000;1;0;R;LU -5496;Sollwert-Erhöhung Funktion HEIZUNG+;300;2000;100;1;R/W;LU -5390;Sommerautomatik Schaltpunkt 1 Zuluftbetrieb;0;2400;1;0;R/W;LU -5392;Sommerautomatik Schaltpunkt 2 Normalbetrieb;0;2400;1;0;R/W;LU -5394;Sommerautomatik Schaltpunkt 3 Abluftbetrieb;0;2400;1;0;R/W;LU -5396;Sommerautomatik Schaltpunkt 4 Normalbetrieb;0;2400;1;0;R/W;LU -826;Störung: Abluftventilator;0;1;1;0;R;LU -832;Störung: CO2-Sensor;0;1;1;0;R;LU -7544;Störung: Fühler Außentemperatur;0;1;1;0;R;LU -7564;Störung: Fühler Außentemperatur Timeout;0;1;1;0;R;LU -806;Störung: Temperaturfühler Außenluft;0;1;1;0;R;LU -804;Störung: Temperaturfühler Raum;0;1;1;0;R;LU -7504;Störung: Temperaturfühler Sole Außenluft;0;1;1;0;R;LU -840;Störung: Wert nicht zulässig;0;3;1;0;R;LU -824;Störung: Zuluftventilator;0;1;1;0;R;LU -800;Summenstörung;0;2147483647;1;0;R;LU -7500;Summenstörung 2;0;2147483647;1;0;R;LU -7566;Summenstörung 3;0;2147483647;1;0;R;LU -1156;SW-Version;0;1000000;1;0;R;LU -1174;Tag;1;7;1;0;R;LU -5340;Temperatur Außenluft: Beschattung;12000;22000;100;1;R/W;LU -5452;Temperatur Außenluft: Bypass Kühlung Aus (Bypass öffnen);20000;35000;1000;0;R/W;LU -5450;Temperatur Außenluft: Bypass Kühlung Ein (Bypass schliessen);20000;35000;1000;0;R/W;LU -5084;Temperatur Außenluft: Bypass öffnen;10000;20000;1000;0;R/W;LU -5086;Temperatur Außenluft: Bypass schließen;10000;20000;1000;0;R/W;LU -5206;Temperatur Außenluft: Frostschutz;-5000;0;100;1;R/W;LU -5090;Temperatur Außenluft: Frostschutz aus;-10000;5000;1000;0;R/W;LU -5088;Temperatur Außenluft: Frostschutz ein;-10000;5000;1000;0;R/W;LU -5200;Temperatur Außenluft: Kühlung aus;16000;22000;1000;0;R/W;LU -5198;Temperatur Außenluft: Kühlung ein;17000;23000;1000;0;R/W;LU -5422;Temperatur Außenluft: Reduktion Luftmenge 10%;-20000;0;100;1;R/W;LU -5424;Temperatur Außenluft: Reduktion Luftmenge 20%;-30000;-10000;100;1;R/W;LU -5386;Temperatur Außenluft: Sommerautomatik aktivieren;10000;19000;1000;0;R/W;LU -5388;Temperatur Außenluft: Sommerautomatik deaktivieren;20000;30000;1000;0;R/W;LU -206;Temperatur: Sole nach Außenluftvorwärmung;-28000;100000;100;1;R;LU -7508;Time-Out: Solltemperatur Raum;0;1;1;0;R;LU -7506;Time-Out: Temperaturfühler Raum;0;1;1;0;R;LU -5212;Uhrzeit;0;235959;1;0;R/W;LU -5442;Uhrzeit und Datum verschicken;0;1;1;0;R;LU -1294;Vereisungsschutz;0;1;1;0;R;LU -5026;Volumenstrombalance Zuluft - Abluft;-50;30;1;0;R/W;LU -1044;Wärmepumpe;0;1;1;0;R;LU -1358;Zeitprogramm Lüftung;0;3;1;0;R/W;LU -1360;Zeitprogramm Lüftung + CO2;0;4;1;0;R/W;LU -1448;Zeitprogramm Nachtkühlung;0;1;1;0;R/W;LU -5494;Zeitspanne Funktion HEIZUNG+;1800;14400;60;0;R/W;LU -5038;Zeitspanne Funktion PARTY;600;14400;60;0;R/W;LU +;;;;;;; +5328;Absenkung der Luefterstufe 1;30;70;1;0;R/W;LU +1066;Aktive Luefterstufe;0;4;1;0;R;LU +1444;Anforderung Brand;0;1;1;0;R/W;LU +1292;Anforderung der Ventilatoren durch Waermepumpe;0;1;1;0;R;LU +1336;Anforderung der Ventilatoren durch Zonenregelung;0;1;1;0;R;LU +1338;Anforderung Disbalance (Boilerueberwaermung);0;1;1;0;R;LU +1356;Anforderung LST3 Feuchte;0;1;1;0;R;LU +1450;Anforderung Nachtkuehlung;0;1;1;0;R;LU +1218;Anforderung: Beschattung;0;1;1;0;R;LU +1216;Anforderung: Bypassklappe;0;1;1;0;R;LU +1462;Anforderung: Extern-Heizstufe 2;0;1;1;0;R;LU +228;Anforderung: LST3_EXT;0;1;1;0;R;LU +1032;Anforderung: Raum-Heizstufe;0;1;1;0;R;LU +1034;Anforderung: Raum-Heizstufe 2;0;1;1;0;R;LU +1198;Anforderung: Sole fuer Aussenlufterwaermung;0;1;1;0;R;LU +1322;Anforderung: Sommerautomatik;0;1;1;0;R;LU +1422;Anforderung: Sperre Venti bei Abtauen;0;1;1;0;R;LU +202;Aussenluft;-28000;100000;100;1;R;LU +5304;Aussenluftfuehler vorhanden?;0;1;1;0;R;LU +286;Aussentemp.;-28000;100000;100;1;R;LU +1412;Aussentemperatur (gedaempft);-50000000;50000000;100000;1;R;LU +5668;Aussentemperatur Nachtauskuehlung;5000;20000;100;1;R/W;LU +5632;Aussentemperatur vorhanden;0;1;1;0;R;LU +5336;Beschattungsfunktion;0;1;1;0;R;LU +5002;Betriebsart;0;5;1;0;R/W;LU +1300;Betriebsart Sommerautomatik;0;2;1;0;R;LU +902;Betriebsstunden: Abluftventilator;0;600000000;60;0;R;LU +964;Betriebsstunden: Beschattung;0;600000000;60;0;R;LU +932;Betriebsstunden: Bypassklappe;0;600000000;60;0;R;LU +928;Betriebsstunden: Feinstaubfilter;0;600000000;60;0;R;LU +940;Betriebsstunden: Frostschutzeinrichtung;0;600000000;60;0;R;LU +926;Betriebsstunden: Grobstaubfilter;0;600000000;60;0;R;LU +912;Betriebsstunden: Heizstufe 1;0;600000000;60;0;R;LU +914;Betriebsstunden: Heizstufe 2;0;600000000;60;0;R;LU +962;Betriebsstunden: Luefterstufe 0;0;600000000;60;0;R;LU +904;Betriebsstunden: Luefterstufe 1;0;600000000;60;0;R;LU +906;Betriebsstunden: Luefterstufe 2;0;600000000;60;0;R;LU +908;Betriebsstunden: Luefterstufe 3;0;600000000;60;0;R;LU +944;Betriebsstunden: Reduzierte Luefterstufe;0;600000000;60;0;R;LU +970;Betriebsstunden: Sole-Kreis Aussenluft;0;600000000;60;0;R;LU +900;Betriebsstunden: Zuluftventilator;0;600000000;60;0;R;LU +838;Brandmeldealarm;0;1;1;0;R;LU +5068;Brandmeldeanlage vorhanden?;0;1;1;0;R;LU +230;CO2;100;1950;1;0;R;LU +1048;CO2-Messung;0;1;1;0;R/W;LU +5054;CO2-Sensor vorhanden?;0;1;1;0;R;LU +5210;Datum;0;99999999;1;0;R/W;LU +5020;Drehzahl Abluftventilator;0;10000;100;0;R/W;LU +1094;Drehzahl Abluftventilator;0;10000;100;0;R;LU +1092;Drehzahl Zuluftventilator;0;10000;100;0;R;LU +5018;Drehzahl Zuluftventilator;0;10000;100;0;R/W;LU +1232;Druckdifferenz Abluft;0;5000;1;1;R;LU +1230;Druckdifferenz Zuluft;0;5000;1;1;R;LU +5330;Erhoehung der Luefterstufe 3;30;100;1;0;R/W;LU +5034;Feinstaubfilter vorhanden?;0;1;1;0;R;LU +1042;Feinstaubfilter wechseln!;0;127;1;0;R;LU +7004;Feinstaubfilter wechseln!;0;1;1;0;R;LU +5032;Feinstaubfilter: Standzeit;131400;1051200;60;0;R;LU +5384;Funktion "Sommerautomatik";0;1;1;0;R;LU +5492;Funktion HEIZUNG+;0;1;1;0;R/W;LU +5000;Geraetetyp;1;92;1;0;R;LU +946;Gesamt befoerderte Kubikmeter;0;600000000;1;0;R;LU +960;Gesamt befoerderte Luftmenge seit Filterwechsel;0;600000000;1;0;R;LU +5360;Grenztemperatur fuer Vereisungsschutz;-40000;-8000;1000;0;R/W;LU +5154;Grobstaubfilter vorhanden?;0;1;0;0;R;LU +7002;Grobstaubfilter wechseln!;0;1;1;0;R;LU +1040;Grobstaubfilter wechseln!;0;127;1;0;R;LU +5164;Grobstaubfilter: Betriebsart Filterueberwachung;1;3;1;0;R;LU +5166;Grobstaubfilter: Maximales Foerdervolumen;100000;1500000;1;0;R;LU +5030;Grobstaubfilter: Standzeit;131400;1051200;60;0;R;LU +1178;Hardwaretype;1;6;1;0;R;LU +5672;Hysterese Nachtauskuehlung Aussenluft;2000;5000;100;1;R/W;LU +5676;Hysterese Nachtauskuehlung Differenz Raum aussen;1000;5000;100;1;R/W;LU +5670;Hysterese Nachtauskuehlung Raum;2000;5000;100;1;R/W;LU +7000;Information;0;2147483647;1;0;R;LU +1186;Ist-Drehzahl Abluftventilator;0;5000;1;0;R;LU +1184;Ist-Drehzahl Zuluftventilator;0;5000;1;0;R;LU +1240;Ist-Volumenstrom Abluft;0;1000;1;0;R;LU +1238;Ist-Volumenstrom Zuluft;0;1000;1;0;R;LU +238;Kontakt: Brandmeldealarm;0;1;1;0;R;LU +5192;Kuehlung vorhanden?;0;1;1;0;R;LU +5270;Maximal zulaessige Drehzahl Abluftventilator;1500;6000;1;0;R/W;LU +5268;Maximal zulaessige Drehzahl Zuluftventilator;1500;6000;1;0;R/W;LU +5530;Minimale Drehzahl Abluftventilator;0;10000;100;0;R/W;LU +5528;Minimale Drehzahl Zuluftventilator;0;10000;100;0;R/W;LU +5674;Nachtauskuehlung Differenz Raum zu Aussenluft;2000;10000;100;1;R/W;LU +5678;Nachtauskuehlung vorhanden;0;1;1;0;R;LU +5168;Pelletofen vorhanden?;0;1;1;0;R;LU +5282;Pelletofen: Anlaufverzoegerung;1;60;1;0;R;LU +5284;Pelletofen: Mindestlaufzeit;1;60;1;0;R;LU +200;Raum;-28000;100000;100;1;R/W;LU +282;Raumfeuchte;500;100000;100;1;R/W;LU +5558;Raumfeuchte Vorhanden;0;1;1;0;R;LU +5016;Raum-Soll;14000;26000;100;1;R/W;LU +5666;Raumsollwert Nachtauskuehlung;18000;28000;100;1;R/W;LU +5338;Raumtemperatur: Beschattung;20000;26000;100;1;R/W;LU +252;Relaiskontakt: EXT (LU);0;1;1;0;R;LU +226;Revisionstuere;0;1;1;0;R;LU +1084;Soll-Volumenstrom Abluft;0;1000;1;0;R;LU +5060;Soll-Volumenstrom Luefterstufe 2;40;600;1;0;R/W;LU +1082;Soll-Volumenstrom Zuluft;0;1000;1;0;R;LU +5496;Sollwert-Erhoehung Funktion HEIZUNG+;300;2000;100;1;R/W;LU +5390;Sommerautomatik Schaltpunkt 1 Zuluftbetrieb;0;2400;1;0;R/W;LU +5392;Sommerautomatik Schaltpunkt 2 Normalbetrieb;0;2400;1;0;R/W;LU +5394;Sommerautomatik Schaltpunkt 3 Abluftbetrieb;0;2400;1;0;R/W;LU +5396;Sommerautomatik Schaltpunkt 4 Normalbetrieb;0;2400;1;0;R/W;LU +826;Stoerung: Abluftventilator;0;1;1;0;R;LU +832;Stoerung: CO2-Sensor;0;1;1;0;R;LU +7544;Stoerung: Fuehler Aussentemperatur;0;1;1;0;R;LU +7564;Stoerung: Fuehler Aussentemperatur Timeout;0;1;1;0;R;LU +806;Stoerung: Temperaturfuehler Aussenluft;0;1;1;0;R;LU +804;Stoerung: Temperaturfuehler Raum;0;1;1;0;R;LU +7504;Stoerung: Temperaturfuehler Sole Aussenluft;0;1;1;0;R;LU +840;Stoerung: Wert nicht zulaessig;0;3;1;0;R;LU +824;Stoerung: Zuluftventilator;0;1;1;0;R;LU +800;Summenstoerung;0;2147483647;1;0;R;LU +7500;Summenstoerung 2;0;2147483647;1;0;R;LU +7566;Summenstoerung 3;0;2147483647;1;0;R;LU +1156;SW-Version;0;1000000;1;0;R;LU +1174;Tag;1;7;1;0;R;LU +5340;Temperatur Aussenluft: Beschattung;12000;22000;100;1;R/W;LU +5452;Temperatur Aussenluft: Bypass Kuehlung Aus (Bypass oeffnen);20000;35000;1000;0;R/W;LU +5450;Temperatur Aussenluft: Bypass Kuehlung Ein (Bypass schliessen);20000;35000;1000;0;R/W;LU +5084;Temperatur Aussenluft: Bypass oeffnen;10000;20000;1000;0;R/W;LU +5086;Temperatur Aussenluft: Bypass schliessen;10000;20000;1000;0;R/W;LU +5206;Temperatur Aussenluft: Frostschutz;-5000;0;100;1;R/W;LU +5090;Temperatur Aussenluft: Frostschutz aus;-10000;5000;1000;0;R/W;LU +5088;Temperatur Aussenluft: Frostschutz ein;-10000;5000;1000;0;R/W;LU +5200;Temperatur Aussenluft: Kuehlung aus;16000;22000;1000;0;R/W;LU +5198;Temperatur Aussenluft: Kuehlung ein;17000;23000;1000;0;R/W;LU +5422;Temperatur Aussenluft: Reduktion Luftmenge 10%;-20000;0;100;1;R/W;LU +5424;Temperatur Aussenluft: Reduktion Luftmenge 20%;-30000;-10000;100;1;R/W;LU +5386;Temperatur Aussenluft: Sommerautomatik aktivieren;10000;19000;1000;0;R/W;LU +5388;Temperatur Aussenluft: Sommerautomatik deaktivieren;20000;30000;1000;0;R/W;LU +206;Temperatur: Sole nach Aussenluftvorwaermung;-28000;100000;100;1;R;LU +7508;Time-Out: Solltemperatur Raum;0;1;1;0;R;LU +7506;Time-Out: Temperaturfuehler Raum;0;1;1;0;R;LU +5212;Uhrzeit;0;235959;1;0;R/W;LU +5442;Uhrzeit und Datum verschicken;0;1;1;0;R;LU +1294;Vereisungsschutz;0;1;1;0;R;LU +5026;Volumenstrombalance Zuluft - Abluft;-50;30;1;0;R/W;LU +1044;Waermepumpe;0;1;1;0;R;LU +1358;Zeitprogramm Lueftung;0;3;1;0;R/W;LU +1360;Zeitprogramm Lueftung + CO2;0;4;1;0;R/W;LU +1448;Zeitprogramm Nachtkuehlung;0;1;1;0;R/W;LU +5494;Zeitspanne Funktion HEIZUNG+;1800;14400;60;0;R/W;LU +5038;Zeitspanne Funktion PARTY;600;14400;60;0;R/W;LU +5274;CO2-Zielwert Luefterstufe0;400;600;1;0;R/W;LU +5276;CO2-Zielwert Luefterstufe1;601;799;1;0;R/W;LU +5278;CO2-Zielwert Luefterstufe2;800;999;1;0;R/W;LU +5280;CO2-Zielwert Luefterstufe3;1000;1500;1;0;R/W;LU \ No newline at end of file From 6a18a7040908fa330021cac32c0269597e26de3c Mon Sep 17 00:00:00 2001 From: msinn Date: Thu, 20 Dec 2018 12:57:30 +0100 Subject: [PATCH 468/705] knx: Implemented dpt 17.001 --- knx/README.md | 1 + knx/dpts.py | 14 ++++++++++++++ knx/plugin.yaml | 8 ++++++++ 3 files changed, 23 insertions(+) diff --git a/knx/README.md b/knx/README.md index 7c6a578e5..cdd02ead5 100644 --- a/knx/README.md +++ b/knx/README.md @@ -91,6 +91,7 @@ The following datapoint types are supported: | 16 | 14 byte | str | 14 characters (ASCII) | 16.001 | 14 byte | str | 14 characters (8859_1) | 17 | 8 bit | num | Scene: 0 - 63 +| 17.001 | 8 bit | num | Scene: 1 - 64 | 20 | 8 bit | num | HVAC: 0 - 255 | 24 | var | str | unlimited string (8859_1) | 232 | 3 byte | list | RGB: [0, 0, 0] - [255, 255, 255] diff --git a/knx/dpts.py b/knx/dpts.py index 5452b1d3a..7f19dc2db 100644 --- a/knx/dpts.py +++ b/knx/dpts.py @@ -265,6 +265,16 @@ def de17(payload): return struct.unpack('>B', payload)[0] & 0x3f +def en17001(value): + return [0, (int(value) & 0x3f) - 1] + + +def de17001(payload): + if len(payload) != 1: + return None + return (struct.unpack('>B', payload)[0] & 0x3f) + 1 + + def en20(value): return [0, int(value) & 0xff] @@ -338,6 +348,8 @@ def dega(string): '16001': de16001, '16.001': de16001, '17': de17, + '17001': de17001, + '17.001': de17001, '20': de20, '24': de24, '232': de232, @@ -368,6 +380,8 @@ def dega(string): '16001': en16001, '16.001': en16001, '17': en17, + '17001': en17001, + '17.001': en17001, '20': en20, '24': en24, '232': en232, diff --git a/knx/plugin.yaml b/knx/plugin.yaml index 0476b7d28..9cc7733f8 100755 --- a/knx/plugin.yaml +++ b/knx/plugin.yaml @@ -124,6 +124,8 @@ item_attributes: - '16001' - '16.001' - '17' + - '17001' + - '17.001' - '20' - '24' - '232' @@ -151,6 +153,7 @@ item_attributes: - 'Zeichenkette [8859_1] (14 Byte) -> str' - 'Zeichenkette [8859_1] (14 Byte) -> str' - 'Szenennummer: 0 - 63 (8 Bit) -> num' + - 'Szenennummer: 1 - 64 (8 Bit) -> num' - 'HVAC: 0 - 255 (8 Bit) -> num' - 'Unlimitierte Zeichenkette [8859_1] (var) -> str' - 'RGB: [0, 0, 0] - [255, 255, 255] (3 Byte) -> list' @@ -177,6 +180,7 @@ item_attributes: - 'String [8859_1] (14 Byte) -> str' - 'String [8859_1] (14 Byte) -> str' - 'Scene number: 0 - 63 (8 Bit) -> num' + - 'Scene number: 1 - 64 (8 Bit) -> num' - 'HVAC: 0 - 255 (8 Bit) -> num' - 'unlimited string [8859_1] (var) -> str' - 'RGB: [0, 0, 0] - [255, 255, 255] (3 Byte) -> list' @@ -303,6 +307,8 @@ plugin_functions: - '16001' - '16.001' - '17' + - '17001' + - '17.001' - '20' - '24' - '232' @@ -330,6 +336,7 @@ plugin_functions: - 'Zeichenkette [8859_1] (14 Byte) -> str' - 'Zeichenkette [8859_1] (14 Byte) -> str' - 'Szenennummer: 0 - 63 (8 Bit) -> num' + - 'Szenennummer: 1 - 64 (8 Bit) -> num' - 'HVAC: 0 - 255 (8 Bit) -> num' - 'Unlimitierte Zeichenkette [8859_1] (var) -> str' - 'RGB: [0, 0, 0] - [255, 255, 255] (3 Byte) -> list' @@ -356,6 +363,7 @@ plugin_functions: - 'String [8859_1] (14 Byte) -> str' - 'String [8859_1] (14 Byte) -> str' - 'Scene number: 0 - 63 (8 Bit) -> num' + - 'Scene number: 1 - 64 (8 Bit) -> num' - 'HVAC: 0 - 255 (8 Bit) -> num' - 'unlimited string [8859_1] (var) -> str' - 'RGB: [0, 0, 0] - [255, 255, 255] (3 Byte) -> list' From 9289bf04a3830a2a4d710a2ebe94bca2e250d90b Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Thu, 20 Dec 2018 14:01:59 +0100 Subject: [PATCH 469/705] UZSU Plugin: Update documentation and dict handling --- uzsu/README.md | 66 ++++++++++++------- uzsu/__init__.py | 10 ++- uzsu/plugin.yaml | 46 +++++++++++++- uzsu/user_doc.rst | 151 ++++++++++++++++++++++++++++++++++++++++++++ uzsu/uzsu_webif.png | Bin 0 -> 716534 bytes 5 files changed, 243 insertions(+), 30 deletions(-) create mode 100755 uzsu/user_doc.rst create mode 100644 uzsu/uzsu_webif.png diff --git a/uzsu/README.md b/uzsu/README.md index 672adf8d8..63bf4f8d9 100755 --- a/uzsu/README.md +++ b/uzsu/README.md @@ -9,11 +9,22 @@ Calculating of sunset/sunrise in triggers, requires installation of ephem (which Calculating interpolation requires installation of scipy. Install with: pip3 install scipy +Update your Python packages first (but make sure they still meet the requirements for smarthomeng)! + On Raspberry debian stretch you also have to run: -apt-get install libatlas-base-dev +sudo apt install libatlas-base-dev + +If that does not work you can use: +sudo apt update +sudo apt install -y python3-scipy ## Changelog +### v1.5.3 +* Remove useless dictionary parts from uzsu items (to make double entry check work better) +* Added SciPy as a requirements +* Added User Documentation + ### v1.5.2 * Make the plugin compatible with the master 1.5.1 version * Correctly write cache file when changing the uzsu item @@ -34,19 +45,18 @@ apt-get install libatlas-base-dev ### plugin.yaml +If remove_duplicates is set to True (default), existing entries with exactly the same settings except the value get replaced by the new entry. + ```yaml uzsu: class_name: UZSU class_path: plugins.uzsu + #remove_duplicates: True ``` ### items.yaml -#### uzsu -You have to specify an item with `type = dict` and with the `uzsu_item` attribute set to the path of the item which will be set by this item. The dict has to have two keys. `active` which says if the whole list of entries should be active or not and `list` which contains a list of all entries (see the Item Data Format section for more details). - -From version 1.4.1 on you can also specify an `interpolation` dictionary. - +You have to specify an item with `type: dict` and with the `uzsu_item` attribute set to the path of the item which will be set by this item. The hierarchy doesn't matter but it is recommended to define the UZSU item as a child of the item to be set and use the relative item reference '..' for the uzsu_item parameter. It is highly recommended to specify the ``cache: True`` as well for persistent storage of the UZSU information. ```yaml # items/my.yaml @@ -55,13 +65,16 @@ someroom: someitem: type: int - anotheritem: + UZSU: type: dict - uzsu_item: someroom.someitem #using smarthomeNG 1.5.1 develop you can use '..' to define a relative item + uzsu_item: someroom.someitem #using smarthomeNG 1.6 you can use '..' to define a relative item cache: 'True' -``` -If you specify the ``cache: True`` as well, then your switching entries will be there even if you restart smarthome.py (sometimes didn't work correctly with plugin version < 1.5.2). + active: #This can be used to simply (de)activate your uzsu via an item call + type: bool + eval: sh...activate(value) + visu_acl: rw +``` ## Item Data Format @@ -71,14 +84,16 @@ Each UZSU item is of type list. Each list entry has to be a dict with specific k * __value__: the value which will be set to the item. -* __active__: `True` if the entry is activated, `False` if not. A deactivated entry is stored to the database but doesn't trigger the setting of the value. It can be enabled later with the `update` method. +* __active__: `True` if the entry is activated, `False` if not. A deactivated entry is stored to the database but doesn't trigger the setting of the value. It can be enabled with the `activate` function. * __time__: time as string to use sunrise/sunset arithmetics like in the crontab eg. `17:008:00`, `17:008:00``, ``17:00`_ beschrieben festgelegt werden. + + +Interpolation +============= + +.. important:: + + Wenn die Interpolation aktiviert ist, wird das UZUS Item im gegebenen Intervall aktualisiert, auch wenn der nächste UZSU Eintrag über die Tagesgrenze hinaus geht. Gibt es beispielsweise heute um 23:00 einen Eintrag mit dem Wert 100 und morgen um 1:00 einen Eintrag mit dem Wert 0, wird zwischen den beiden Zeitpunkten der Wert kontinuierlich abnehmen. Bei linearer Interpolation wird um Mitternacht der Wert 50 geschrieben. + +Interpolation ist ein eigenes Dict innerhalb des UZSU Dictionary mit folgenden Einträgen: + +- **type**: string, setzt die mathematische Interpolationsfunktion cubic, linear oder none. Ist der Wert cubic oder linear gesetzt, wird der für die aktuelle Zeit interpolierte Wert sowohl beim Pluginstart als auch im entsprechenden Intervall gesetzt. + +- **interval**: integer, setzt den zeitlichen Abstand (in Sekunden) der automatischen UZSU Auslösungen + +- **initage**: integer, definiert die Anzahl Sekunden, innerhalb der beim Pluginstart etwaige versäumte UZSU Einträge gesucht werden sollen. Diese Einstellung ist obsolet, wenn die Interpolation nicht auf none ist, weil dann beim Pluginstart der errechnete Wert automatisch gesetzt wird. + +- **itemtype**: Der Item-Typ des uzsu_item, das durch die UZSU gesetzt werden soll. Dieser Wert wird beim Pluginstart automatisch ermittelt und sollte nicht verändert werden. + +- **initizialized**: bool, wird beim Pluginstart automatisch gesetzt, sobald ein gültiger Eintrag innerhalb der initage Zeit gefunden wurde und diese Initialisierung tatsächlich ausgeführt wurde. + + +Funktionen +========== + +UZSU Items können über folgende Funktion z.B. in Logiken oder eval-Aufrufen abgefragt oder verändert werden. + +.. code-block:: python + + # Abfrage des nächsten Aktualisierungszeitpunkts + sh.eg.wohnen.kugellampe.uzsu.planned() + + # Abfrage, ob die uzsu aktiv ist oder nicht. + sh.eg.wohnen.kugellampe.uzsu.activate() + + # Setzen, ob die uzsu aktiv ist oder nicht. True: aktivieren, False: deaktivieren + sh.eg.wohnen.kugellampe.uzsu.activate(True/False) + + # Abfrage der Interpolationseinstellungen + sh.eg.wohnen.kugellampe.uzsu.interpolation() + + # Setzen der Interpolationseinstellungen + sh.eg.wohnen.kugellampe.uzsu.interpolation(type='linear/none/cubic', interval=5, backintime=0) + + # Beim Aufrufen mit dem Parameter True werden die Einträge der UZSU gelöscht. VORSICHT! + sh.eg.wohnen.kugellampe.uzsu.clear(True) + + +Webinterface +============ + +Das Webinterface bietet folgende Informationen: + +- **UZSUs**: Liste aller UZSU Items mit farbkodierter Information über den Status (inaktiv, aktiv, Problem) + +- **UZSU Items**: Info zu den Items, die über die UZSU geschaltet werden (inkl. Typ) + +- **UZSU Item Werte**: Aktueller Wert des UZSU Items, geplanter nächster Wert und Zeitpunkt der Schaltung + +- **UZSU Interpolation**: Interpolationstyp und Intervall + +- **UZSU Init**: Back in Time bz.w init age Wert + +- **UZSU dict**: Durch Klicken auf eine Zeile wird das gesamte Dictionary einer UZSU angezeigt. + +.. image:: uzsu_webif.png + :height: 1632px + :width: 3286px + :scale: 25% + :alt: Web Interface + :align: center + + +Beispiel +======== + +Folgender Python Aufruf bzw. Dictionary Eintrag schaltet das Licht jeden zweiten Tag um 16:30 auf den Wert 100% und deaktiviert es um 17:30 Uhr. Dazwischen wird im Abstand von 5 Minuten der Wert linear interpoliert. Um 17:00 Uhr ist er somit bei 50%. + +.. code:: python + + sh.eg.wohnen.leuchte.uzsu({'active':True, 'list':[ + {'value':100, 'active':True, 'rrule':'FREQ=DAILY;INTERVAL=2', 'time': '16:30'}, + {'value':0, 'active':True, 'rrule':'FREQ=DAILY;INTERVAL=2', 'time': '17:30'}], + {'interval': 5, 'type': 'cubic', 'initialized': False, 'itemtype': 'num', 'initage': 0} + }) + + +Weitere Infos +============= + +Beispiele und zusätzliche Infos können im `SmarthomeNG Blog `_ gefunden werden. + + +SmartVISU +========= + +Das UZSU plugin wird durch die smartVISU2.9 sowohl in Form eines Popups als auch einer grafischen Darstellung unterstützt. diff --git a/uzsu/uzsu_webif.png b/uzsu/uzsu_webif.png new file mode 100644 index 0000000000000000000000000000000000000000..b4cc223652ee59c1b98502d2ae6838eb6c2f7701 GIT binary patch literal 716534 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
    1WHY=uCA$h*xGF8;H3;hq_~O*;4QFjP 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 z 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
  1. `JVC0Kc{eTXsmm|grk4Rr{TP~H=an|Z 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
      b`**x0N!*+6W1UriRJ0 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 Ggm&fZQ3!;#ubC=>Zz2BbC9G}Bp0D^jL$oXde2 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 q&NU+ZzT;V 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

      R9>ltGUiCQ@@F~17?$rsq%=2Tuj*8 zj9$G8?2ec&_63w;Xz)T`Sso1thV88gpJ4N zYVG2t(R>j&#O7i5b21ys%m3W-rm}GTYl)qCh6irC>z+F}cF9UM#BF1BN4opsACxaT z=h|90%^bk=4&)eKV|!@y;35J}irDXLN%lbKa_B=UnLH9=sH`9P3Nk+I)2UM9B?fQj z$+TVYTkVT5V@hX-dM#tjn2qANYgJk#oe)NQx0{ zCw#Onvh_*V?Ct31;DWsL^^6k11%)^ROyAZCub-=XK?``^5b4ha%8{oG@ZeJglzv!e zj#3}54E7&|@dDNTV5^Y`a~ZCf_Of%QeDe&DZra``U@P`J#!V&bzhc5JSU{|Bj-VsGmF!f)uL}tPzE6hT^NEAW zwN$A%m3UVLGI*ylc~chswU~Qy^dTs@73DNzTj;r8?ofWNltju~^UmgDMH2N;oLETY z9O98@e;vUFnr&T8784`4HGym_(t(abu|P%6o%C6PTE&M(J6-t10R1%)`gM5s9-&<` z&ha44a-N&^GPIp+O|^D)SR_GAC-OErB7cCdso{(N*b0_V{hyltcitiOn7iV;I~*s& zC!JBANH(dp{os*@_Lc@=1Iv z%ELN|kkCgbJvyu@E@}uORkN26o2at#98~xnwN8HV#f$-5G?PgYX2yQ!U4l-G_a`;T zv-Tu#Fk--e4~{8k;=m{Syngb~YFn-un2M|$VR%BnsN+wNg*3+ZUkXK+zP-zI3O`ux?Gf0X8b*8 zK=1X}wk!LwIC*tCp1l#EhPRV9nNp>#X%dcz!7fHYK zH0@NTR3gQktp8_k8@)%12$Vl=czlaR|MFk!mO2@jek>GcQ|s#VJ&^@-+-yHxNS=Xw zbEiHOy!hYuhF{@S6GctCAN{X3P&mZv^~$aWxovRKw5J-hIi(eBAsiD*_3d^RZ4qhR z4ME?_yE8Z(`E+P=oyol$?$tjt5|`A+Do#90h0mne>Au3(4{6Fms*ubkru!N2u8kCh zY6-iaIYqboiA-POgO~#PHkx#k*Bu*bZ1qtKK@_s3ZdV0skJ5J0a9(zVy}*5umg3Wb zG7?i%aJ+wq)y(0r0!h&o1Zk5LEuBdho*9mpsF4p@?lV85a+>?2kpuNt=HYz&UE9Vf zP*i=W`sEJ3i4<@6c81>69ha2$a_8?SVLfER&CvF)!9lN@qrZQ zs>5js_RB$LY@3~wu!+B}4b8Ec?A(Gc)xAa#!ZtSqPbvF}vsb7xR^fu*Y`zzX5 zZDc7G)&qYw8wr#DQ$GqN!UPtcNI2mmy_eCW)cB`B36%PbS=#CDStW5WT%_ZRr@lMo z>f$NQf#>=8PxF6TPVjj0K7DOmCEM`7FlICrN!+EU`1!2oqMeo7*7OA&xQ%rCn>r+l z)~)SfrPd(?P|mX&X;lEoOg?4_Jg(|h?kk@G7?>JsR&=5NDbRz}_{BBc$w_$!6&l<0 zV0t`R>ln~*ymzDcKl)KP|7;`P!=N8b$|{SGCggJ43Yvl+m+G2h{~TjR>RzuMU3!57 zZxSNs`;0oydM~`U;*@E9+>?SirSfr?1fyxTsgN);GrJ@~A!{6-`GIJHcx;zk!cBe8 zV#hP9J?_m_`lw&^-Fiwf`%(r_nue2)(^nN}x!tK>qeqYlD)Sufa-wYDL#rL79$t@z zuUM{Vo<$~X*`z`ydzVrniCk9?%e%LzJtM6KE-2~Kd)U8jc0|Dzbj#XX7bW%i^b8Ac^r2ODx1CuWqQV84a)q zKDZD@l`5g)a#!YtEUpIxrAMuLfj1FHaXD{;Js8sGD~QZPJv%Rwn@b-RdO_Ag^|fmj zR0DOA<^n(X(&>m^WKh>A&+tq;&ab>$@3&#_x8E;sKQ|OdV8RO+I75O>rX&+#{1TSJ zdTF|cY~)=^t#&K^++R+qU|}SZ5I_FftIrtcf|{f4*vB68LC)AtDq}pAd2XE&?bnR$ zm8ztZmW<6dE+@xD3ksx=JbUl}seLAgB__BjWV2cCF_>9=}c_Ke^msfL610qQ}93>Uflc|5`2xRbBtJHt7 zCsg3lrP=t;&qRj!PwPwD-2DD`v5Cmqo~UdgS!Am{affp&i(pqcE2ksdIqr2EF0z>g zB(5u!9VbCJN0{7uvm|R335R7b?~2dF+g<&phXq*wntcjcnV!C_eTu`eZaS?bffnFp zH*#-{g@naHsefVU4;2Kq=Exja#0pJv=B~E1ViSACDHv!>UNZ3R=sJ+AzI@Ds)5K4i zw6PEbVxM=_d}lCvDrYlNEi+bz+()FMz#mzJ`z7RzTJFR)s193vEW(ttFzJ)D9X1@G zXQ3#_u_d%>DD1DCxo5bPQRb+w>$PdzC?b} za}ZOOHmtQ5(YM+am!QJ;HpKb4-#m9hik=RLoQ!E`PD%X=;HfZqA1ilT=Cwl+|Jf8) zHCQ!~rIR8*Nm)heqf~Dz*Mkflgc$?%Ygqz3&mpir4a%w-;n8rE4zbb9u7PqsA^;@9 zzA2d(mDm%iH$_{;^Vt|!h*W^jFHCh6P}c1TT-=<>R(-~|Y3&_cKb@o05A2o++-u(w zIF&M0JD}CF;FG!H8Aw%XO6?6tI;lkbbv+BcxS7+ttQXaPkw}eT-jXk+ZV4V(Cvci= z5-+xMHb?$b-pA481XyhUVM>IGGSBmlK+hyVPh_3iXoX;4Q+~6iQs2di)|!=+K^C`G z(55gcAL4SrY)wD(%it5&w^cRDuK+?=%>7R&AKv!u6Ec@F915MH3q4ox8Sn=#+(#b{LXoW)?7WB8U(f-K%! zdE{IG-q&Ie{pxnTqriA509S%4_gbYut3G^JTVu5P$sYjpPSM&-oenkvy_4+f;>1w( zbOgLDx2X@FaX`nGrYI1_(}H%gq$^>t`K?B2MmI{ur0YP77xtxaq(KGqN$gk0rCoNhOyf-b6i*snp+AG^6BU2~r@ z`s7=z?qCYwcv7tXrxgfuX#7KDV@~dieXlJz(6EC7B5jg9yC7fqXr)2TmfmK3LpIW! z#20e$WD7<{gx51o$m#9?2`68-{kW+k%@L|p0G0|-Gk0ozzawl$Ef6)p{iL(1&n-m=u z1YNhG^|}ha84+10{kZuBVgG(k4;o!GY24OAbj|LLZ*rRLFW-@(mW57M8&sTB?HxP6 z7wEA)Kn~#Ka>lMs;5}0jIrk}*WY-w=4wI8#l*#Vu+J(e&r75~>H`?uc+Q4N3%huJ3 z{i=|Zg|67N;Y)<{!_uL~f4bt1dOL$Z|7s`#vVj3Fj=sCW7B?BjEFNPi1fQ}ru#NmF zf{R~WCv0iYH9SZ7qL0M-FH_)2|9U)iC4bp86*HWnjCOHG-6E!KwnL1;Xp`|_qssd= z<@HOz)K(c5D|q7Yh(-Z1=~|4KJ7>5@|Mf}S&9ckm{$YcUm*>)@;HL}^jpnrI&acY5 ztoF`!07)FB>I`L?mAIGSAZM`&!o+#$v!mk1^j5?8uSe#0s=SZlNi^3y)UhpsZY4EH+{L5>=5jxZ15pK`*(mu|7 zHzV*o*}_+N{8_9@Mpu&08!Z;YXeR7xkGd+Hq{>}t%FW_kN}6OR`>3oe@A6yTdO=p<>?6v zMkbIc!u{qRbsgwp)qb#0>K_#tUiZL5RKda*_z@ed zr?@RQi=E*Fw=&M7?NoEBcqbEf%xywu(5gQJ!`q1YvLls?C(9nDU*`su(AhS=#7(f9 zBak_`Sm7jJ8;?kk@L3@REz$F@SVI>%X=~Pr%QT7vZnuNtIQ{9x%^S(ljZeA$?I8uN zhr1dI%0Hx>|G>r3aifeYQS^{dHoHe0l`U=OH+8Zr2y7E~3=wp>^BJ#fpI zgRN+NjiDI71)8CnZdt^9Z0R~e6_{Ge0Un9zG_F38mUnPFQyC*E_RsSS;)$@^%we?Z zuHiU>drn25LEd;Rxx%vE2ZR>sN1KS z?+f2=+y=R1J|S++ECPQ1e&m!KYdQhPWG#$Mi6j@7J~hK48dNw;0)I7 zeQ9>m*HAq4)=}y8y9doUz#Ky!@WhB&-#Y54J3UO;k73;dTbHke8^pJ(H*xj_#MSFu zCQq9L$jq(jfSo0kXe2mcOX-s_$h67E-YG=8S1G_Mvx2v(AP66!11>|=gg8^rcz1iMzs4~VK zp=!S)!;r{2`CJwp-nKD|_=t(k?)h)@38Q>BenDLeh2GO3Q8u6$$1eYT;ozFfsx20Y zQc^(qE=Efg1Kbbc>_>gT5fE{gy*MmyDmkDNPirCg2VW2VgRjT#qw}FyH-u<^)IGj! z-MpIHLAK}|If#dHjjIAyz~Vv)tgQ@b21+DqqkR1sKX)gO>vK+4 zq*G-dEr*Tv?r(4g-(>S)a?%#hJ8Nb%p}2j^-t-1U`5j$D;i3z?6Sp_HQ_2jnY8PDd z#2379$v}n^)P07^OyymdkiLn}v4IDMa({SF^lc?DOXjyro{3@?yZ(#S?eui8G|?Pj zXhM;>uS0FiF*r;^51#lfK%sk`&;b_aWpl^L5<<(4ftZlm;HsycBraZ#uTk-~5` zc3n-X{#x>wJB%1q4$JutiZM@!X7eKxJrKiDspQT*HaE8ORE7n6aa=rh|MBqcS=?d=1 zgZvc3emg}fVYO4ru1&oB9%@?Ym##P>6!%TkmBnae&VBwX=ojZd@4q3=Ae+F}!;j&( zQy*5Osg=^$E7>j`3Ro!ub%*nIOh)^Uo%Ez%eem`l7A?^Zg^Pirip zCMkim4R?zeG6Lk~RoO!FKp6paGE?vXBs;S)2trA*orjrZ^w5{xpGAOvg!2FRR;bJ4 zSaZNXcNk-WE^|u*`L!i8r~QtNHYX3->XbE0y8TO-wofVA>S59mYL_=`y7v>0^mX@y z1;13=YIXXi<+k=IzKFyI%?p2!9gO#zWzsGvx#M|65jtI!`5-7DPDwM zye_+ArKhXYOmZ)q^EvzL9hy)d3$zmQa^@m#-W`!yZ1=*)5>oe++?2i5^XHvz1SSQ) z3Cp(*Bzm60-7{z^v44_Vn%_A4oEPb&y``t*-tXR4F3u#+wKpBR z$ef{sUi^|T8wVc``Wbv9rUbwu1F^$Yos*hVneyUab6WM;`ku>{rJd1EA+yH@ytR7w zwiC%f%T?YkL=nXuzB9+18^$-OsZS3B~A+q%1MS$7L{ zY&Co15EA@HbIZ5^kRs^u!XndmFxR!xIMfJFklC(%2{cuF5~`w$J1Ns0$hZBj_Qj^p zt#^Zx&OkzS*I4vsnrOJ&j)z`6M<+d3i;gGvQMct$mf;6RGUegs_N_qB!=HPI1{;{J z{EFbX%O86+eB3rBdPeo_LVs#YpNYYrr)s=$@=8!PMb23t{afXBex!rIaXpD9?A*&` zU}AkpijYrhLNr3GxHVBU|Hz?p+kG5)={9Gk?SowBe>noetwbzfjzdTL_sTAa9c$5; zATT41-iUCyhs3{2+(&#NFHJPQ|B{r(hGilRPgP@}{5#B9FZtK6kD^t20_q94AQDgscqW8P|9yIEWW z3PDv9|MHsUKwYx`a)fc{=`t8l{WCDK-z`;wBhxL(9db$qE1x_OTXflXj}=9#a!+$6 zo8yLX4IXn}2v!V}N7L=?PiYwws629X)C9yXVvek!Rk9l1KL{&(`z_L${p#Bj&Puex zr}U8Z`XXqC*7gO`7US;{5weCRzOKEXY6y!wuu5X58)&G(LF7VJiGPrt|e%{=u#V+q!p$>1~z)gl@^ zE0$ZK=%q6i=gXAlzm^Dz%x|jRVZ{Q;Upz3HAN{s5)jE)6alq4;rgRFj-m#z?1eLYqB=V}TW*_a?m?(k4p|8w za`>)D7{cZL+kB+e+bBFTu?8UDb7mI}fpelI~Y& z54;ZjZV&c0t9Wrc=gnpV-O2CI1yKWZ(_p<&uEPr@0%~6TCyc1oZhuLmI6#E#wxE1b zYqC;^)Vvfk!#)YXoV|2pKx7Ni!};j*fTTy`@yF!eP1YtI+Kd}gyW^qHteAglxhfc^ zgH710h_Lffx1RjyXG6xf>)qEz+)wg-(~m$ElFid4BT+&HTRdEjJKKNqf(8$?rpbqg zFd`?4fWSg5(vGX1tFZG3sr$I?`7MyCj@P|abW#|^H4%KQjU13*{+ZvnVY8uX?>HcVPG2GvEO=x=OK{C?LXz+>7Jf5*ng<67 zZj{O-CBFP+`kvP+)lSf#%Qfs>&aMrBPjGNm_;B{{y;G^5#W*3bB?C4Xem$hNvYb7g>w7-?}!I&~kQ}lGzajn9B%(QFkyEYrU&l5N8yGcVL z^MVS>;+8)Ju-I7_M~L@|)nYBT!J|A`qeY|ObvLw|vci>Pog5!0W;mbd+M&R)NJ@_? zi}}U<%Vb-Uj3eoveHc5@BPgzYdmar4mQpg4A77q(81HO7_4p(IcF;7~BJ^*XUjkqm zi$6q3<6sg!(;{{(-dP*1Jhqii}AJpI<7`>YYLnvG*t8Xi0?N>8*1wxh4ND`MRelPY4iMEB6@t z{ePwXAj99`pw9N5lRnoPN3laE{OI?MEMnu@hE|&xdyq)HF8j=AmrOXR_!><=%=+VZ zASXSuG0;+V=c6@cc}osf^?8;TL~71m;Ln8;P%O{Ti2j#!9EL4`3IMQLU^;z#^CY8; zJxg|J63K@G%?!Q3%JrXQy?Y8|cJiYrM68=E04U9PGg1NapC|6yNI6W{)7_7>aPguq zzTpGIzu@~6rgAe)R|h?PQD{L4&)Nwm)WNFsBqcG+S{+poO)?#(O}TosoHRc3`ppJM zL9kOY(=In9bvppz%sKT{AAK~W`MRB8h`OHIUuv&gH33Ft{L(7_9Qt=vjb%TMWkP(| z=Y2xjN->MRgL489JQAH!7n~w|zOjhxeNE;7FC4$c$tU+@bhR;{GY<})-c7+Y#JAzt zHc9b8BF!MRhj(5IhQDWm*hs2B)6E`^-Fi7Py!>XG(6?T`pb(y5;LzBd3g5Gz9Lv`< zfn4oxkU?TFKD?U7*!NpG4e&X=BXY+Ur%fe;F}FVGtVI-FAbN}ttp)Eg8%^RZn)yob);N)ge`v}{duV9v{ zeoWbHipY`uuWGNq&lF(h(T*AZ%U;SAJD-~xd&S-mVR={Eu=&t1-(Rp=puhg=9AVcP z(M9wc8jdb{?Ov=9#ePvOqX3`rNqnk)Et0ow=($RkCw5X^U4#Y&yfDGGL56qi9`HyN zWbX(XLgLf^B>Id}CsKfl(CbR5H5L__L^E=j@*pqIsW*O(SY%ZHv8aK!oCxy`c%=Ng zET_BSc__fltuNu>Lr<_6PZAr(cZnVyAt7}3={`CCGLAi)D7p2clXFY7biOCQxThG_IW_5%Y?rF{9JL$G3X zNs7})_%1JJkVbduY6eW~ZU*6*t| zVH?|FHkyX|4=L`pFGA`>%l=k%@Adfh+la@f>Xoj6d?n$WW45Sx{j^v>8woxKi*$@h z29kGxnsMH5ZNptrpmc!yxc>KM>^BACyA+R%X_XiVcU8kax}(YGp%Xf?G9k1*Z~3C_ ztaLfJoxt##9%r8foHoC-rE*ol*mOX@>YsMA0Q54?^~NXw?tk2h;q`_j%ryFJd#E27 zmX5@KE>AEO1aPCa-lqy-stdxq!zVkB*8R^&toJV{ujH6gwdwFHn8VrA3)wjYCIrSg z5vInO#rUt+Z*IoR*=(MhQNm9x(&K1z)kldxH0$R>f+9KB3{B3#rG*d-fy#lb(E&p) zy@Nh>qZ|vFaF$~Uzl?ym-3+If;Lg*19LIg~_+(c8NQS*WYXg5E^;P$S-2MMoA&TSv zCyzcE0drjS8T07B47kz9_p4!M5{^r4r>Ppcw@n-RHEo&Fik-&B!V7($jrNhI6o_a2 zfG-z=p)(tHPfcq(v``JlKby%us=^+W6LI7?Kwyhbk=Ih}5}?b&B;PL^e~InGrk&3! zLmjId>p;o%u&ZR*e2LD*80Wp^{IF;rD551fh3|3_>T-rH_Q2hR^G2rOo@%F8dBbHSGAlz#+xtY8&z&Q<6s;f7% zl}Dt(b2ba-8sHFqA&%;9;w2rnr?VAW(pl6yLMy6n`ZDvJnzr?1u#rvDa14P7zFlUS zbwgZ#7LPt?8{YTCa;;4t99bN36})uki1f5Np=pGOqc_Qkc~tez(sSg~-vsXjZra{) z9~z%ls0IiG1#O-5x9(aUJ$lDK^Q@O{=$|TUEqWZz@1lO9(peSGAVhQO=sk{+S1oGB zVtTo8(gzKz{@pIP3ee5ilaKL0q+yJH?3CI<^hBxqj5y+4;ne}8<;`oq9(<(Haz3v^ z3K(SLtjmDH38?{bz#}WM*&djMEPam&Bye&I&mP9%@sw5uQ7xVOp;e{zLpqtDV-YS1 z_4qgXH+%POw@;Cfqg>=5cpM(KN{w5oNY!XU5SF}Su|VMvYwA?z>}TE2io|Dz!y})% z%4OZ@r9lSFnrf2zmI{(#^OsMVp|1aeP%@yK1G`i~G-CdZ{RVEARpKY$X8p*+E;L z>cd5W-2b*_q@W||eW9hI>ek@nM6&0%jJD36Uc5K!DRGY=ig(!Wzz?5@Wkk-!X4NOf zFr0=&cCLMWQE%icbAPlRwv)LH4V})v=$wQW%cJu0=T^?}sl>Rn?|t0wNMNlrFF;K? z_2`yh^)>O-pU^+w)W4NW`QKN&^Y7J0Cp2-yke~r5UvJCY6 z8)_vcRnPXNc7pOaues3z8Yvb0P^^E?+zjR!O$(s)DoGM0&axLVlqul?`A>g72sQ!` zz~+kV8G>DhFasRcMyA&@`gF!Uq$IWSm3z(st4`YaM$$1)CBN+{aeb6;AfvOEqgZqP z7A{x$4j|S^l$EOpjmHI0&)@xbLqVuT@&g$GB%RD3$25cx({b5yJjUo(mL6u*lK8$Z z><(UTT)y;fd^`*f)`b{=rm1)4;uW)qDV%i&EI-S6t0AFrnKx9DK0+YQ)O@fS5#Q|t z{b2G6xWFJVzZMHIRQT>jPz#YI*2SNNb*+*`e@I7ejHCY{!Rxidn`nQ3>JU+Yrp7mI zKNUukn<43pSgP>&l5;mGy}JYo_fJ>2llZ$`I#11Z)(Q!%D_$mkXOfV3irWT4Fs}+J zqx5Jmn_Qn+>I}es%~2C+SMNM!JLI{;?G0yZf?>EIKcfF*lm>_+rE&knOkdsG$*;VA zOaPC|eLIOKKSbr_)V(W4;B63WyWA42_!H4|zGypC1bw$MLdWfsczVs&OeJ#jf79BwJt`f&V<7a_! z$sHAhsE1ualHYdfX;X)))A=Z_rN|KxT#MDf2CDs(wo=~R&QRxQbK9mjjK|8EGE|bf z=bqiAyw6vOe9U}@@=LB&?t{dI#UvFa1AjZ`5B0uWZ;F;%VEaCejHqKND_lNqHt8z? z6RWx&mpu%!UEx|c0zHoGAZB^+INd&?YaBK7PU@I5?P-I#LJCp}yt%dqZMYqDQZGBN zQt_)HI?oQj()HL_4NZnCpSAD>S`^25*>KVE|N7^9>*DT2jGU2NS(0C83109?rF@>Y z9%9o=#9HlsN5Ra5vyY;U$DF^hlkgA6FV~gc?Q)E^+fN_L^fzZF@@h7o!ZDbJ_csap zs>Hu?PW;aUZTJ_Rsj@<}-gHSgkm~K}_5J*xF~lknhA*eS_|vc}oL&BFgZtzw`}Q4r zy74pXP9+D6v6VCheH=5u7`DSM>_*&1&%*wQnK;! zm`2jryV+KpeqQR66*s?6-azG?2odQLdm8GGuY}MH%)40R@3=)i&Wy2+{$j^xK4Cw` zQCj_-g(iGHXTmkDLTStYLVCnt#Tu3J1aNkqy{Y_rq{O%{XM?r7Gj_;BBrg0Gi`Bys zO=};mjZSD93}f~+=gz+1E?6g#XZrUq$*9i^fB_vflyIilT#2*SI8cW#xel=0&OFfv zwhjmE-;2l5d7+%%eK#K2@OjgSMm_#ax05%^#s)#`BrGhjYV&~T zv?tA!ZO;p~iA^_{fQexxID)M*AwDbnF$f=)NgQnd9;g+79fM}V(_Q|l?TON^oo7sy zyhw@LSvDTaQK&F6q8-M3k;^9Q4=6DZ8iPuCqVw$wIDgKzkKRfv;QRbK%>Vy?;`&05jU55OyMQCPc5)zBp}K!E=6yb^8!> zqNco+;nml=cRIsuq%x1)u^)H>@-K7W_r_X<-r|WmKb}Gx!JH@Iq}yv^P`K@AAgE)LL3;={6rLELbNb|-53SS2P8H)6u?_K# z$fxh+yY2nst59hse2mpz+}9p!=>#@MPH60yPvZ_830`2jNt#zFUUKZ|8gdNh@HPS` zw+)5Ke-n`mL~YJIwkHU}L2!utwki9=ls_(JNpL0S{^($xbJrEo(dD%S>99cK+@NO& z>70Y-agh$}Pms#y7ww*FKA=V_v*}UF!u)9zV^D~k{82N?*whDeN?m9pfrSVV8)X2R z)rR*J?DvH&EEI}j*qj+Vl{Qif-^0?A4WSEk{k3zWhk4qHp*z&YTJw%alUc2@RevK92p z$Wuk0#TQ+;W0;lal&i*j7F`nP6rw12<(w39?K&|$XeIrCTe?jYOI@))8KUciEtpavGcFzNv&SN97T+?)?&F?8I ziphRXXhV6XRDVbd&)@>B_@jF~XRX^D1Ip3L0Odwmrm$k#h4$HY@}@@OZ!Vs(Q%6PY zf8F6Laqq`tPpQnV;q`bXX2}nlB_|H|8*C!fDW>OGZsiwdrq4B2PdryTHy7(XqF3b$ zjH#62A${gOKQvUUb_-A*nstpBEUr)`t{=M8BIb z%N;0^|4M~{s>dYnY|RF#Wj!&)MZRP6@i`lMf7H^p7XYS=+i<*cM4ZHkk%zG$G&kjz zfXKE(V>!)w6v`X+5?=N~GUa3EeA}%c$f6T!rO1n3Q)~R*)-`*z^Nh&K%nBR-c)R_6 zH1&#|$RYNB%bh?;8)h*4%rsFyDGMY~ZVy(q*QWJa2=#EO4t2(}8KyndNMLdZ*Wv+x zE!ZGMa72PLD!rM6smFoy3#yXP_Pt}(o;SM?%_jVxFi#krPQ9_mxpz^M1;93-(5PwH z_`k*czcjA@KYvof?cd*^y-EiXnm3Kx0)lG3!2TvEef}b~>f@YuKYO#(C%@Ob?Kit0 zjF2xebPsd%HGlu0iZ9B6clvfH&X}Sbbl!A^JxvD?m(r&0^PoRC;b3bmk&564RPFd6 zt1E8=mQJYk4crBXZ6X}Mc}$cv8(Vv0GG1mB)5#j?b6Q$U5A2|D@6M8kqM2GcjcOF} zNC%WL<3(WEpxjV>e97R{0>3W_gw19@kQz`PH1WFQtu;;Cf^Kp{Kw??3@90xewTPaF#?V@V57H?P*ysL%MbO(@0SW{;U3k&7aQZZ9}Lms9Mm7`+7(`bUU z4S4Ro6Ke%rQ6&GYW+OsL00Fxved@X2rjfS0D&3&q`t6eK!e)l^&Ykaysn_qD49rMt zC@hJH7#!N4iERk7?HrSSWL&0NW;Oy)v>O78 zzT8Wn=E;+DKRT)bo2u-HVQq22Jkd|ln;WcfWf9Pin^*zCGqGZU{3#AD{)d=H+g-Z} zF*T~X$EEf(h|4nvK3lU?xC0yB&d)eIi6gaSB=Y`}5nXH}L`8AAZ0j52`&;fhN*7&H zh4#GEj#Y=H1QtpcVhzR_{{oJ#abAhjPeys>g_%H#a=JCEdL^^`Z(fH+ub0|HuzJBZ zFMSFi*dIG>!Gn;)!vjC=4JYos1Jv%ZcQ3c^Q(9f#*2xN@xHMQSLOO@x8RlMbvGO9e z6uswDxjft&B0~wdO=_>cbaZj*WLBD%oR|x_&tQM1D_YVl7J$?lcpH%Ur;O?x9^O#c zVcu11os*|6BPLE!If$D=E-xUpq6H!2c~eoPI&o8QtXlENMXL?jrgeXyhLq)~WWk7& zV4O#J4>Z(Ak9p4tjt;WD3l1Bos^(q=&aUhpVaBb!G){J zn!6*2t#XZ=ddcL1)Zve7whb}O{o)6g=Xfv;mV)g0nG@6ZZ&mQ7I!Rei?^#fXMK;H> zBt(DMO(YB2NM!ulqodTU)%JR)ty42b6;rbTU3qS3_+w>u33>MA9#)xf7eoew(qv1@ zHTHy;Ue=(2UY&Ny`kwqr^L6iv_bPGY@6{Fe#Za$J@b9-yd@%dLaB_3iXR*AI6!pB= zoiO8y7&=@>_L_osBV?WOp3TqpY1%hEC)1f_qMIkyG;m9`G6%tZE8(prYDNbyZ7X(h zxp17b&6v3Hv7MH{&d2qKla4|$-t2W|4WDmZ;V$CE#_SGBzqnX~IPF><9G)muo(v+m zU>7oy%$MDt&SL8`?JL~J(`Awq+rfb9vP&{c3YfzW#1ynyBfQz2&e(P>->OyUz7m+H zjz6zBg{Cp6{DWc7f_htYABkS;_h7J$dgA2qENaj)$?<2T-Te$ee2k3Cix+fLN@7F@fcuO{`?#0E^GP2 z?2fJg{kMYz zTyg7048Ku4{BRw)G33OUTy;L8`NbrKLZC%z2;QcLjeX`vY=K8}R>(HCQ%dG4`NMRW zWh^P&5mq477hs&>_HGGae#OA}*)#2Cw>VKjd)QvY8Th*0iNUG(w-(J?@*zRh|6=HIyze&5UjTpBcjKn z-1vhbc-FU3b-ii^_T+AW9Yi?Vt{1X1WOx@N?w2Au z+EHF)L1y`*dBnGz;Ff*WDb*E9dN^-Xa4(MO*w7vd)gWQSDA5GWqgL?c5}+?KFH_k{ z+W|NZ=J1l>dRGKa4!W0+TFrUoJB_<`iq~|e-QtsoZl|7j(_Kk~`ip-F^W@e&(vHsd z;8&Pr_qN&w;^t7{f@3PROmviZdwNVFS*RZvy+OR6_vgV)6ddd~c?^eaoD_$#}nr@e*rlQET zRLis>wlgal($oMcJz}oMLbQ4+cfw|y0d8STwGSeI&3`SomRYeT$GRU!$>2* zK?<6q6H7MkFBBi{ASgVZvYAFot1g00lMMd?B31l$uan-$Tw<+E06ukSWl8$a$F2O= z|KcV3ny1zxSeHl_4&dCL$@o#qS-wWWLXFC#z|4n7R^YzbWpz)nTL`KChkho55x~r0n~wKb;BRQNbiQ#ES|+3*6%98wPm47#n~BgSUz% zUji3dxRi32d?dEfAMIm}e`Pp~x)$u;;{D2FazZRzj0cD!jQn`Ufzh){CNblzX)@9j zZn-((H|ZDLhfC|XyL`%NfL1T67yq%$qDivDN}0sydaD_Yy!mJv$%L9D6c$>mb`;}E zoe?H-W=!QUwJF0N6ue?i%6=?C(U{yY9i><$!_bBMq8!5KmW@h*!1&@k-qjP|m1XNd zgA~GC=-|lF2@@J8U#c*2xUvvSXt1Zpp>RJLK2L>_DCcVGIWtQ}CHrE=pi)GUYJ`KwgA; zb@vN*PAcR7ykKgPb>thk*URjVKshO7iMY%Sm?c-EH*jXxBor$-vQJAp@w&G@&IAh# zY^WaYdx^HOk^XuQ?t1QiQ16?MlfJkwMv!#}QS4m<<@KCn(@LCuT4MG0SS#0#VjIX~ zG1&o5a)c3DA+GdgK;Rvh=%mqVP33uG`{(+=oh_6uDC+(RoOY1$qfq|O6)$HL@)7$G zIzdqEeRQJhz$cQ)EE~JyKepQul`%GUc`j?!;|X5mJj{K32|RGUYK878g(pv&yge6Wb^Oi#Co6*pVpch`I7trY!fXCs8k-Wts7SZJ3<148UfiOGaoH*B%MyRNy6>|sh_yUEP(0nl? z`OyJU$HvvtTVMurY7$iUQutIEyO|ru+t~c&Np)QGkKP$Dv7Z|^Te?n`_rzTDe4pVW zQl1;Q}CR(`2vsu>&Ai8g-(}^hF=5CE&g*_rv(T1gflz zJe8{<)`x~g5miVLV&oL@AWMM1tifWA{^>(1fi}CVqyNp|i&(GN=~~^bFI3%k#UA`n zD`6(d7R3=+I;p)OB>Hr^^j}MaV3WtDivmsWoD_a9p1kvg=K?@t7wTUS=v(qvv7NZ3 zr5Bsm8K?D-bmV_E3v{usjrQw5;7YIm)mqRGE zdFXHO5X8HUO1uH&zfSy{`Pk8c+SpUV}DAm#%f+h zSDJs{DOsX<=;0#6#(zQru%atPekc=aQ-qHR9TD5dgX!NKRD<(hFi@w3f<#CXVu;7WXY?B`uiY7tYVKX`O1 zi_*O8)9@u1Y*xWg+)$+W6iNLAjTS!D%za5Y!m`A<_u*_;bZ1*n7l5%dMsQ^tk>s6G<0*oL=KyFKLZ3tLYTJ$LW~E+(^}kXkPDq zyj{$svrmix8TRbYLa;dpbRsJ%5V{dvnds-Jb z_B2CGq3(MoPcDP)TX9=nu}Pdcj>2(vKgQRcRj+H<$azKi%ec&tB5-Sknloe;^$ z1o^;v*~Qcyw_{o~v-d#-;BXuP3wCXv8Jx#8 zimADSMj1UoUjL>*6M%XUgcjepJg`|H65vulUgYCaEKYUM8w^q7<%Zf(qZ_ z25)|m;lqK`#j?%fmA9&(0LTH5J*9MXNy$5kHR{4zp|%Bo|~hA=|)HqHPUE_%bKl{XZj+ z&}?|W!d5+G9A6{hZp2Nvt+951j+@BYyXdW04*yuC%Ubw?V&S3Zx47)f8zfPXJ z4U=zhLUQK~FY+>8Wj`xJMo7H7+4`&X5=Il`TciYw?3G0ZZNeZ*6i?U@E06p&P3?cz0$|Gkp@7>)hti=Joh%d+1=uect<(tR z46s@)uPnPZ7zd@Cj;5Kaf_|zHo-vj=Q&+}x?&Gi!m$Hd&bK>9eOl|5l?N2m_hS*dv z8FXG$9shFdWA%JQPt>k0MpFxYKKh%?<~SV%AOT`viOB{RSmTz7X>7 z2Y#|6_KVl2vY@2Uh2G8?KJ%t{5)3H`ztlRi%+DX}?aE2S3 z&fK+Gt=FNFMK=pXLWMkYa3MSNMyU&R_WN}Ek_xE5!Mjo}LU>!XzInP>+j*ap-d$@i zlWNVyRXd>5Njl#0il@1rQfmNrQ$(n&qyDHUhQT$EfzFMi%3SvLlVz?|8e?lkoJD?~ z*k+Hh$9z<-DjHE;g@e)OLY6&ynf0<`J$^U0UBhOK=9bDvb!ri7Y?al6D=TAh-_g5; zg3CHc-oh)hSrrF*y=NI*Mx(xi(id)wQ6zAXR?9bgzvShSUW!2pcA5Xip3Ebl zORA)j!GEV*q+LFj6x6`#u_7sxgz=uT`@=KO!tO-Q;93v0a6A60goO#Xc z*y8!z2$ayLd$;5sDY~ZV*k${6%|@m$Q6UivD1Rn6DHYtz$tHml&U*Pu%jCe?eQp)| zEyewe4?GrZn2z_9kGB_*1@7y((&ng@caE;>ACY!>!*smg zRTdA^5@C;+$qtqt^D~})Hi=&Nk{)PyLO}^7jg_30O^d%YfdWRo5=nha25<3f%iLx} z_${2gWtJW}>>P5ltF9fLSY({xo29~vG{$)ZF8yl^sXAv1J$leT8zIpt$G4cj_QXs6 zxi?oY+gdm}eU=jcwg14Z*3G!vkzUtL|l!d;Y*^P`cnP+EsNFM{k97+W^WtJ-2|{`y##u1}e>Xxcc7~YM4rCgn0j5 zK=}7i5r^Ze#$1*SLRS*(3#F%$y2PKER7+lz5R~N2ys$?_PUTTb*Ep7!*lFiJ3Br-& z5#PPb+RMT4iT9&%GjcI}?CztgNI;0!v~b^>W~k~H>MN<0(VOPg>V&-@Je-ay&hZ@) z*zUHhq|S3G&Nb5Ugsjz0H5D!|l)f;6KDY4+B~dAD+{m4y6XoMxQusXZd4GtmZLRM* zJKJZjrBWQn#v1He;ptW^UmXZyI(YE{D}na(!ro{&(RoXWWPn*SP7z^ zs&$#Q&3n)Fd?Lf4mrj!tN0nJLpL*$WI91U-$5P2yPgx}eu5E~lCtOkMqK2P+Pjin5 zs_l=J?EXrP^(#cXpHKG2S^!(sl-g)R1>z6+~`_tmfwTqdqeaQ@Zr;`a8(>5Zf&$2wa zJ>Z?*-o)w^Dt;550PR(W0EyD7eSABD&nmNp+Er7$7I0Gp;pqxFR&hU8a*20UNu@%4<|L^F z`4eYkOgjCX{TmY?B{Fvc>>3r`Ch4nRz&uzcYQ-~+v^%0`9;_O?!+XH4s2!0 z3gX|@vfd9iwUOjiGNDf}a!q|s)c-S-cd%2YkH zXtlRa#V*%sSLSwpa&r;r=J(7!S~1mhv7Y}`rF&L-Zd=HxVLj+{p@TnCaZ-V!4bwM@ zUuZmkuF0<5C%}U8i|4>|Kt^ScDb%jJu83!RQ0PQY?Mc10fUVI%iKDdb7y_c3BRoXK z_SSw_TIL?J@EO@InFVaBR=a2Zl(0t_o;}KYz?1ZHJb2zRt>$OjcGpSZlaaQ>RyG(S zM1g1TjJ;A^>Ea0%8`S{aj#qf$^Ucz!FWMwngjXrYd3gt{lSk|?V1y+4!zktc9P8HZNs>(a7gQP?ALE+D z9{MyLa$5v26!sY5T4LEGEeeYAO+Iz6R+>!>H zl+_>bcSww~CRvxlK=@62e?^Fmwee6S8^8-%PqN1iIfDRP7CYh%!HiN96`Gmvd=*6z z2Pf12nB4(q{zMO1{auY24f}2H{z}ubqdoiW!dSsmUc)^D(@@&gwLuKjvCV#7dJB#?Ca@~ z@9@qh{dd6ZLBx$$&`KURj@)*a!E&L*-(A}GJo`Pz&h`mB!uuF`v_h84=?*_kU{i}; zk)RZbpVVb<=&g=>=Ji7(2Z0>vW!+%RR4PA{>dTv7YyPM&K*c;t< zEL?Twnq3^cep#e@D4Aqdxw-V%cg3gYp?BH4u=f7s;wd+TG?`s`^pMIPX0VYf`>la; zLDcb`%J!q-cK_)HLG2bTw~+~cp)#QhifX0kybp1cM!gA26W1jSvEhgC$nz$K?Ju|& zryR1P-j|&CnOUxYSq73vy4BLhEruuqZ5noL}Vf~w z4+Ckm)cgwVUuDbBKy#2in64<-C8lg+L6ic=uMw-N*B-Zm7DtRdg|mS-xsf|8+A?ExJ*hge&Y?h%Y#L`Px}&( z>t6X3!sp-LGSp+PgiZqHAS1>#`WE>-gL0*2SZ~L>(`}V&PlaqiKD!JOn7o;|K05!> zyf~o$q`s^ub@R>r4b{($K%Qds>L}ulCYZQbjqHbo6qr9-vlZqZojYA2+9j^6bUDAa24DRp+oa@weE2!(r>bQD@S3l1v~cIwI~_#CU0au1c4g)oZSt{qH6I2!&M+u3F(} zYgt#NDUP-K9c>?v+$7})xUzg3s$@qzVZWcD*hKt&1Mc2P?|6yrg{_e}!pxj)D|4~L z>Aa`#fkjc=k@j77cTNuV_dM-$N`KRz*~;tM$Bx{_j>dgSXkg>w5YZyMZ&i~ow5$FkR*BOG!%i*SRZM@TW!V2+Ec5UD|6GvK9cuF_-KfJzz(W zUN{k6`^f*$qx>yNL*5hfme4stZ%( zq|?3>;Ji0(3$}~9p{pi;;#oTvx}(4GL_3kp%Wa=REW>@_)+5E1{>GB%i~pDva}Y-P z-Hqv^VE&$_UQ~+r?wcOvkk}*6YMBpd&MKHD9&QF=0rPTG<@`@j;qms~1M!G!94EZC z=Ra89h#Kg!R0xwv=``wII+n6Ll~a~Bc{B&wyOgcwV2a2yNA|ld*E+L*ocbCSx?|Gn zcOokzxzx@Ol3%s%Ax4eH8DjcO6~;047ID>j{1$ID`Oy;TRvXx0b+td`-z|nJbo4_* zPNxSa3}x}Cef377+5d?Mh4#_axxk*tdk68=L<7--eiYWWIPP~bz8Axvvew;;XT&}1 z!WOGCM5+;#HNN$ve6iu1k}ad>gi$~x>=a>Y(dKMGT-!;zoA zz*AHDaSJ*E?-_)Ety<@;NL|Spq{w^53#2~%pMV|psCWkcVgc$}tBo|`f2wPL`~a@_ z0ZlCif+j>T%r+*kE@@cUMZDU_KS}n%fhePc5#u{_fk>f98A1!gwLmBKE-iM)*bLF|pB`^7pj}4LFO-L13?a8= zfZ`t1hM2z^fky0sU*2ilb4)iaEnoWGREEo1>hkb6eRp zT3XH`a4u^VUgJ}=VXb{;FLE$p@ooy+>z=)2Z-?!e@Xe6Goc603P*NSYa^KlCz+B_M zxe_jd`_z;5Wt`U5NDB0G5({np`-EyKaFQx6BrGu2IK?bxs1rjGgfSr4%0luMg44nqr9a8PN&oA;Cl!Sc6YO*gWs{CE^2auww;S z1_#6eg(**@m-;s|-i@eEPsTWD9O|t}kUQ)tDCA`E&LRV|*6v;botPxiu%mTDk<0vH zID1(F`nO47LPpJIO%{r`@1f_aD85jAkgV+tWR=&jO|$%`dXWKBw;P`sjnClKgoH7D z3D?JU)k4IeF2DPL+*%oZO+HjvzwqsHmqaRYwQaYIyrQAwah_S!!MUo5$+9DUpm=IA zWxPYChpU2VhQ0j4?W5P8jAi9#18vG6!$m#bYqHMkoLNFpmur-{#IxwNdy(^e|Nr~m zEM<6Hrtn+OHN$beT=f`w*G-98ZuR>G2OeF}tr#4(8_*ujUgRF>PxY7D_K&x=E+6d~ zSok)-R?6EneWLhnAMvSzXN2qZIRY+0j*Xo?Z`hpzUyeKS?wht&m|@CNxGw#vZtw|e(Y|a-(e+YVhS?5YxHK({(9g);uSRbxZoSI!LB+LJa+}IV zDrm$;te-o}Y}(9-WR3bSyoUqH1Ga(aX#{?EctpSj5D@zi2_)u_&7HQ6N~)ro*ZxZo z@IUy$TQ|rDs*~uDk1Caz_dOgi|DCz?F!*9p%EBLT`vCbwP8xSosYK~>pwytqU%UAW zI_mrSFqLs0ZQ)hR5z+}oA$+7{wF`?zF(*7bmHzKO_TSOU;CHXjjh40d&hVc?+3QCM z*dPFIZsXdgVS#R-X1_a@t!6N|t@jU?`oe!W?e5e}Cb(9^6pZgu|EKr=MN$QD;Xie! ze0Nmnio&Nvw}dvEtvE{Bu5vBY>&EYQTTA`N1txucEN@Bq|FPnE{UqN{VSC~Zr`_XCQd~&sb)BkRS$A_;NPF|e}hOT3EW}mcBh6bLRPQ104B8pXl0p9D0x?Q{FT7QAtq$ zY4zn9PRCjUrMYA4%f4%|&7MekmO{QHcHX7tSBkgp&}yQ6+UX@2w#!r)(bfERm+(pz zns@@p$v`n@mBEpCGYo&BjM zn`pW#OkZ5T;r9yCU^O3L%pczi&)VYz3)SE%ddPnlCSPVxXhr?W=e8JEZ@#Dr_tbL5 zu603Pw$};Ik5GtQlM<}l(S;E$DywrqH?-LtwHPo{+j zYF+E8K1cmZam2twOoV~(!mwPu0c~5~MIw6$4-Bgddt(CoGOly;h=|5FKN^fX$n&?A2_rO8A+z7oU2Zhj+aFX!ZrDn& z4K~_au19ld$`KMr776?D2ZCz$YX-A~TbX=fCFUN#jp}CuM_z^NB=GoXxF78z+aOIq zPI}8#DH{LFo1J!Eu>$Ww$Mk%^FIgU4@)ZIXY8j)yrX?88uLrF=es>$dfr@1KuaJ}O zwrHfb(OHUI@6ugQ?^3oS1`1d$QK4GUkV}1~SwP~IOGJ9#mXJmG>%}Q75_9scx;vjT zGwA|VS5i-yA0kv&-?W`Hje@~t#J@QeNBcv=qoLBh)q6>H>l+i>$-}8lc#=jXB6*>} z6zNj*a912^HC!4C?xd%{AQWn+^$Mfx`Fp(q%dSY3ebBe{2!fU`^(E7U-5Z+vLt%xw zlQ*kz2!*339thtkYT(=7n&EA+>68{3XygqFFBmTGM+IKp%$3sgw5s8CjXS);ueeJG z@>14N+LPI5uAHdK+}ANqpSnoFCN5wUWlySt=aI~*3p0|?8*6Omx zieXp$8H@V`dwuBDK(JI_10#rGb z@&;+O6A_>uFGhpH4>|G`T69f?vh&aR^~+#@7$s_g{QT$0t;aMdvP>e>CXCA2qwy7? zwez2gaR}N)Xn!nQyAYGx;}Y9wf{Jv%Vk z0#7QMC@~w|Dw%lnB{z)9Z_6P65apaZwhg%XE=|YansZ5BX6dKbx}LwR>r~_c|25z6^ql&hpiR|Y)Uu@ok&^!Jr*G?hI*L)?ZVlHwMk=F7vv|5 zz-rr#pwZh~xx#k~H8zJ|NipCL7g`|Mo|{NYrX&K{X7hyfKN^N!=t^hV;FR6!lO58R zK^n7KL*Wf*ew)dF`#{>+3Z_f%CQTcmYyoif(yQ1pl9srYb%%Wj#pm zChhBKrui+arh8G2UuW~{CSG3o)oYoRUGAB!=5E(tv){T7Z_j@5SHu?&aC?mYh8I%g zLrdR^D~b>)SoBtcy#>;zuZG2x}d!+o!&k zXAw5{^0F_|EUu9&n@0s;u`xpzf4vNB(Aa=6MQTk*>7Q$i(o_BUs;|Ddq7%Wn5~BL; z%T1FtcXouKUi(t_?LV%l7IU-zWyeUym$&0recYa|J!}>nhB1~Kd@E`-kDf`5pQQM( zsqTtvwgRMR>YbIXbgrpq%cHcBuZ-#18HC(IX)rFBmQ>1~2)#xg=CJ@~+d|P^Lmz9M zbx&_^=S8mZZ@j{Ey-=a_TMQLm#SHh#qre0yRX!Ba=j9!9Y{#z`6F2^y{J6GF(|QaO zr(K)nXscLA6s>w6gD!f1SvQMOapwwd4b6T}YE9QpvU?xq>XNp{J1oT|3du+KqlD-o z3T9NWZKN=FJ)K?Ysu&>DpBuQGg{$vRowUU(w68{s?D<<6NYm6y>68Z7$d7LPs-h>x zl$VK2<%DIknlH);R*Pg^k4lUy=4(9r!2bN_1qzmDngkUnj9m9^aiazxSbu--#)k|< zqb3BJpkf>4V?|)t+DEB5j^FeqVI&2GQ|#wOriT{E?h?;?!+_6A4Orhjq7*T_Asr59 z;S@H75(veHp!G8Z#v_avJkQ?crrAmy=?Nq{Y^I@o2oZQslgSKKgI3JbE4Y{eMVec| z1?B}(_IJo7;~^eM9%@iP*`5?Bpb@}{$3(JESl^cflZw-QDC>-sSYU>D=~{*P!wR-E zYyPO4JF{UBM(5wKUUta!_}Ry&?sC3cKFrf_fu?qEAi|?@xRu=s+2-NT+|Jm6=vkg! zmfc+nvUMXtQDhI1ewW{A2MwvLor%L-*FVoSdRN+>g!sxPtGw$ckl`;PKI#DMi#YcFN|ENB(|qW-~GmE~$RmQwah0mFvSrod7LF%w=21-oOZ zWXG}lItIcOSasd+bgUAu{tD z^-n5Tl?8C@!SbOE*ZsWR!bu=UD3W%6ZwJa;zK_ z_aL3>Tdzp2L3sN&z}k~mT3T-3$1^yt)Yf3B1g5y1b;;B5O7j^*M!zB}AF5S8P|5-k zl+zKtD{VKFJh`ii!hskIv4PHao&=l_M@hVJa}2jvFQmp3k%G{};Y*Zh*tv0n!fNVM z@b5}VoVsC#UenCVpcERXNVnTLoGvjb963zp3(h~^92Bg0q9BveCIZ42Be}%QHR_I ze$?HNKC8uAYqU$E<^HDf7u^WT*|F+C8i+`q0A>Q=L4qAGj3K}a4f?YH$x5n_K1TU5i8 zI+~bu%eR=SZErtNpm(H-5VuUMJNW^sMFL3al$TWOK)3YDh85qq+<4+3+*WWLbfPNFGYW?#k2TebSo6olpN*mDTj?h%!L9H0 zCO4vLx1F#Y@4ZN9LuCW3mKPS>gihbh&{$V*Ssvp-m&=4}!mbaf*A4iY3|hOGjn67I zjowPqz^^0O>-L4^%b5sI!?&RBBZi0Bzd!JZa^I@9<7B~`5l-t*sR?8q?`hDaio-O5 z{7OoNaC(CVHe(J~ev1Y~uw+%2lR$SFlHk^r}@!=(G1t`|@e&sh|HWy@gx$WsxsW$HFc4Be=sISiWrKpDJU|HRf;H z%ne_nP$*?H-j-&nVr$z?gfs2k&~bIZWWDbMy87;YYZW}(_lr^!biQnOmNcqzvv;~} zUe8x{bM5xOEV!qE!{YA18EA>x4xfRZ8ZD~VIcLZ_G(M$NwGzVgv#Dr?gN)UYlI-GO zbE=(RtiFHZZF$#Ryi~P7cLcx@>U?G3M5jSHi z8*6q?UpPO3*#{D@YbTynC1y|>T)%=-Pda=ZS1Yiu6tt-BX3Dj27V51|<{uy$K3i}T z{2=@?@kgqduM!n|6#d zGOwNe-A7B%dm-{cle|gCWmKXl`i%?|2Cu2!ebZ;oFzOudr(v_ta10e+-VYM6nS8=- zj~)G*pqKuv`#gixT&L0FYg9tf=MPX;5xvo$?jW;2hBC$M>=B|?ZS^i%i!zLQ>ZaiMywTI3Rr;M)+&qP% zAF0if%vr~Xdt1Dpf8j*AjcdEP&KqjXOEyz*-X~Cx+xaNYPNM;daYdhBd6N;PGNR2+ zb^U1`jv0kT<96pEJco|0JK6xo&ZCF1eBO02!Y9$eruM*0IX_?lf=+>4T+*M=QAM6TxoakZOo)-bUcfKIIIK{eA~L=d32k z4S!{SPPKVM_7_5dM-`R-H*dt7B+-7DG-h@j$Mw2(cY+a0+ez?~%kV1Wc*Ti9T9f5s zHOe^}(Oa?n6N>Y|UJ{SdTdhA*Y5bZWcY-*;^^1?u;Z}|&i3#+x=`Oq4J%6{dAXX|n zE!I@>`KnhA$2B_k+7&t+Zd}+cCpv{)1zfltu6}a2ZTGq0dF)$LX4C!EZH;Bl=4m-Z z-aAI#PMi1Vu3=g&#P!mMFWgkE?P7yx?O}-)1F50;C;d>=$uFlg2I4ekeeN3bTwDr; zRp&#H$bqJ{@jbJelLzJHy%k2u^T|O{P9ne<{Z&n&c7$nLA!kh6^nb0#{)Tc6`F@#~ZD)P<2*eZH7zNE^VP`DehK^ySo>6 zhXSF&-5r7_xI4w&-L-gecPsAh{-^uf``|yw;d_>AW}Y=`-E$h{)pt!pkU+9>*OJS% zVs{g99lOJVPjN%I^Z`1}TD6?bFvFlf(b|=(4a@49Q`?<{!TU{6Qy||YzxI%=N-JO zN7pVE%>|aoSZEZfC(~P<)V4dmd)q$A-!4C~WKIpJr{T({laL*T*ml^cn zn`!|&2~K%HP18tx6U-F28D}Kb7Fq#9@1sB)H0F6gbzsr;<#{`5&u^9w;UrZjm`uuk zNLcK5Crr01Ke5)!iEILF8dt2T7dN8j#HdhMFq@&nEI1@ef%Wvr{->Lo!Fpz={+eiC zS~dtWxYa1+g|v2`wb1l;iF010)8^%7pf6QKocSbSFON()-xN;<@39>xBN>6Ig9WJr3&O2IAozCwo60)jG5X*aNe7Hp zkc&>?EmxP2O^d9@Wz`Ty|3(36xJ*G&G8m}bOoB!0wYU;LQ&bb&VNk?$Fj3{QljAJh zb2PAkL)=uFS)7@^dT*7?YmjOv)!+FOHdY@cd=W#7+rlu{?LguzffYV9P>ksTTVEhRjh{`QR(iL!TaZHK=fjQHDC! z8(=MK>8$}rsvR`FV)vg>L3tY?>ipMBT|E!}g>}_mE_0fQR2tan1r*8{ zjQV?%j5AkWeU>*SL!$mH7nMy{>Ik_xJYqmZKCfkg=A|X3Jh}8dYuST)UX2>FRUWf4 z0{(3s5=EjPqC)~A?8Q(6Arx^Wp4fBVt#G@YPc?1j!`4)%9$p=3o(F|=b08QtoUtnF zxMaZ9)h}5w+W0LEg4-liLH+kv*v8tciSt#~>rZzXc80AAP)n(LgW>nOS4>GcA+0UC z0>98>)tU^JaPEuLj%<{@!C=b(^l!@1UV8DZ5NvuPu7&6X~E5hpeQbjmzr`ZeyV5tEA z!E(i}!zcaT8kLLcl+`!Wr>)Kqnay|&^Ea6Om=kK)W?UmrOP^0qC!!}c3kQQ^FMQf!c$-T~U zYr}9zHe8kq*)*FLY-KBvU z=T?^xxM{ZDC&F9#R+LO}R6k9n7jb<&8+-ZWr=3g-gQJ>m`iVdVE9bo4;Ufm}M6W8XTymU)p zbsTq9A2>;gl*7>3F(>KP?U;#xYO1dqQs5C%*48o%{xeir$q>-GIT3W~DY`yK<3b z%lKs2)Iz9aA;58L@aEF7>Bw$PgQmP8tiZYCManZ$_RqSr^=CzbkeoG)51Hu1VLzl`rAh)LhCJ!!yf@6e zd@pjc7e}b{1AidYo3UOdqsi8&F)-QkyFW3K7IF8<-+x--A8jGbq>pgX{yChxQ%j=)5 z1K~%>jYxrHaQJwC3+O)Z*mHfo*!o?b$q2Y5Zfm*6Qe?@!ym%h0lrfZid^bmhAC}F9 z&a^yRz9gN`sJ4=`OFI3SOK9GSYUCxZ2xn$hSoy^|K`6f5%u2c)7069>`Uhzb zMjy#gv0fhkFqB}a>h&6Pfl4q`wa;?d95XF%J;bPZ$UA2H6n<HpTV1mdBn;NQC|nKv0SDCM9ThXrxM>a~;$oUV8Ok5uk+}0AR5H=Fek8<0S!{hi zalvDsV40Mr{K`h_m~Ipe-472*H1f{yz&`1{7g)~rW4FP*)2+ULKbC#MIl|PjoWsIq zbG_Q5u)EZ^bJL>3*AGibd{uS+p&-a%b}ZU%@bZobCC=R2-sX98A!%C|Ipv-=v%xaA zB~7&^p`bjHMUOX1#I{`#l}3;L8~&QBn)bB-XuT?Re&U>+zFi@T<+E-T)N1R$`1S!$ z)$H}XKtt?cmsL`-(2~goAx@Mqs;mpaEr;$i@Knc9ckj|Aqvm}=Wil79WX}bBgiIBE z6HV?J)^cn7Ly} z`9=1h)RAbxc5e*zRtY8VGNz-*I>;bfraA?Bb78ew-jSCu3!tx&+-X;Tlbb!%WCd3_ z%_0Bc`SENwbn}um4V&!*LO;EJ_U}ej|M^~gIkEd1HB|F15Wje$(pED2vuXPS`W!DL z)Qe-uNThCui**_M4zD6f7$JE#p0Pj5uVCl3?a3>3xs6Z!a~ITPc8&J;jAYE&1iy5l zsvl2d;eRT{XZ8a0aLyilwc8A65b1trUcdLS_re#k#EdkTb5$6&GS^{4k87O)%N_ba z@rAxM>U2j{G(Dy?hx?lBZnV@+i}5w(D>T9Y1~XB+Zke=jU?Bsol z3PbyFsb0S*3fTSS(51og5ti)3(XGE)FBJqc&3Q*QZbO776bU$p@H6cTT0T0d+qVUW z4t+SqgE!^iB?wi(gsH%fgs@rEKE{yv!$;4j!?7RqG}A+J>fHtfK8<#(Ne1t@%gI+W3CS zoX2Og^q)^Z&PPOxXgBLE#qRlUn=P3-HRcvgvbS0HMi(i2kgq)g5ZM;iW*Y2=;c)p3 z!+8_#S`hG@sGR?747g@648&3cU{zG<5_gimgAbvfv z;fGSr2>T2gqq!UFH%csIq`+9LTU&OcJbEWQ>9b-lAkS&X4)MY2L7o;02+Z97y%O1J zIw33a#a+&$B}YaM8k$!3SmVA5?~nGOCcy^P{c+g&DWGVxVlL>#<8oN|=mv2pkR4bC z&sSk#w~)Kx&L3~R?C>xJz2?fBr_d|I-eq7N=#Axsm06m zd?M7Dn9`F~a}d2ICV#1ac0|iic_rF@f_i#GT{qYyYP>oPsFXCmc2gSxPvACtc%hgt z6olj6xNkyLFQx&BO5o)3y3EGO7tH}pg0Z)jbq}V$p-0qjn%2*V*sqR$ERh?!2GFH8 z0WtoE1iII{Uv_^;OCM4VFi%-f@KgglT0%RZ>}XX(_;?*NLU*W8=*wvPjE8Z+7r=;d z({S|7T$TRte=LB2mF`3LzM2Peg7m`)i#4nfSA-H$>-^sG!?4rBkcS)(pZv3V7uF=f zqw#80zJA^uh#;;{>)gqXC|2Q&fcOXuDilki7>8Cq+e*g4tm59w;~YfCCyYWit`s>A zI-;0P^J}ox-qricAvFNwLNe|B77ph07+KQ-PNrgffi`!+f8q5{I6&qt-nUU zMp-Mq&25eAChRV*8$uO`=uED<>FeFu>%y&!TOq*nVsB1uG|O0vJqkum zWMawr-K<<_X%kDFZ~xivD%n-Yd!R}GIU;M}udLn-ioVC{q)waWdXdeq-LyX_osRjz zwiXtSaY;_${iYL5`0a?(w#KxKt?hcAJ?DS{n5BXCZ~^u<95KSywkv1KFDL)n#F8a* z-9zOBgyX5vxCfG^yWm+>73e_tEf{N2B{g5{hXaW1p<6GyUAqkZi$3h-97E8`bL?_G z^g!m3(FPTco}-2zWUo++ycG6R=p~uw&5u8;%}9u$o1~vZv#2Y0*`;K_bLG?79qE*f zJUB{Dq^O)WBM>6@&K?#tr2Y>V2oqWMh`LiljKr?u!U=L~yH*Qy!(ZXdvN2<0GvIEv zW>z;r8$OP}(H5&e%XHyky{M62KPc%pUD{;Cz(_l9W!W8}Ctujx42oS$WV;GU)f)Jd zeN18?;0z@Rk4BQ9YJwLGL5U?T-=T<}V$S|XyqB)%Y>uancDzuBSmSs}+F2!qJ^W`N zznpAG?H6MAv#IT;MgNj-!WP47zX{Kl8qgZN-q?;AzPR>At!vFkjL8IOBo&I}^iQ+$ zRp20rd(Zz)JZUA<_wV@>dX%jl<|H+DsZ+)G$-$fMi%<(8BqG!H}D)sYEp&jg#gHBelIsjP0P=mV=f7_&|StWudn&4J}xFc)a*;k2+nax=;i@(lPcy z2)5QrWgx7#M=57C{bTXdE|t(-@F*GLo!IRXO7zn*K-(pSZ4#S+qEOgFmdrt>t zxDC_6+#h0}4OC&1>ikx(wM#e@a7=PH2X)sJnUqRIEZesPo8dyMAj3CldNg31d(OqIUTHo{sGtIbLb<$38CfAa-+;{ z#82ak{*X9g-HIR^_Mb3CyzE`L$utl%3AQC2AaKMRH5K>YYNQ~{mI0XoCw;tHJ_ovSbQI4ct zu-k-Pr6bpkwhN<$AUxHw!=?3$IRk!WR~ceCYujBlQ}vgV*GmVa8E^lvKd zv2~$viQnr&$e4XsqOY&YyD#)ruEcNaWKyHSVnTZuWRC?{DC|+p1H35RQH(Y^K*kHL|}DHR>7Pdq$`=>oNG*hQ(lr zd7&X!OB=IO%t+o1Pl*SWs{}I-^F0e=%fS$DOCipqn1DKcKetkd`*WGSgj3P>Tdyw_ zN+r*s#F(Pc?+119I6Vo{|3bdPhfDGFBnNFp`eqv1m>vZoF zwM~f+IJ$$g!xAWDWm7%e(Io1CF3UXxv5ZMnLB>NeG(~v=^@WK9tbKtSr6}kH*0w;69ylh->>28tbmXR484Y_AaQ*EBo>@U4ZujO-wqYfvS`< z@P^rCf*bgIR!*Gk&Ww=Nt($b==?SpKTOkt>I@$!(Z4WF=dU@FNELxZ#HGAC0$x}{j zQ@S+$XBj$g@`GHaRU%Tg1W{X1f1gI!#=Tl_bs`z2{-=u$GueD#=sgQEMf$+6SD`Hs z_>%LK>ngir6rXTKIo7CKokm+<B?TvEisI%=;dnKREr7G+xqJ^J^KNKPR%=^yd2|Oy|8syR3JqHaD6>^OknYBW zM{g!TWd@}{_afiQg+72H;CPd%@@VEA;y{ijB~umqeLmtJCvV*Ff3MF&hxy`{RxnC| zRb6SNQm3ragYj%s`K7o(>;4v4{ay)>dq$odnVy}sRx#lz-QMfLYN<7T{qk-vY9H_O zuml&fq`-$Cql;~0h3QL0f&-0L1(L@2w;VgxQcQ~M9cTNFII9>WfI7tTjqwJbx?r3dIoXJ9q{)ZV~g@bR>i-yp%<6>UX$cjxINndev*?m zA#|=VCLEjQ(|yp~dP2ShQbo1gdxxB*G-dPSy1dzKfwVJi$+tY=T-iEEbjh*b_I>UG zBpznE{)PPaRt|NUxElCgbP|Vh1$}CNn2GdRHqLhrCMF>lzRV3TecMBMG=u}}zF2i1uv1mqYZ*jwi64RID;efXK-NS{x5P57XQY&1^ntj2~_lE}WCTg$eY~y`2)T;xD`&Kq~zm@x#ftQ$McY zWx}=)-Yk;ruJ)m7dwG*YXghsKdZOM3$4o6;SeF*vU5olsxH~!5w|D0AMDrkH@>^G8 zEZ;4J!<`@zk&!1-7ahMqEQxP9AOey5UNz}QqBtSJMue;8@7K7;^r@>}O6%-pc|2pR zR8-@hYo1}*A<`j_arr94i?4qK)E>(osEMa4J295@e`?}PtXnmWZ7#D>%Pn}0^mzssJ9|&kTK$xMeiaJ zm>v74VjJ@2#bM~ZZ8(pq&2vq7$RF>nYRL-oB2_BR5C@lq{EZ>iQj6F4@H~_9e-K(3 zNWEQR5}O%~mZ-vj4|lCYE7>?@#;J%Krk*S}I#@}4g2e*JEyPkJjqtgQzy-#G%Mo^f zngV1bh!<&gcXQOpjXJ*9b0y_t7(kD4q{OPB#DKmq&iAI zIhEBSns_N0oEPmBe=`*+imEX_*TlZ3^ECV1O+)t~K`&ml4cB(5*A^Qj78jr{uH#Wv z$1quQIMDSs$o_Px4s-2crH5O-pWr;-r};XCki~_8qrc+&K0hf&Yy?jTz{0m4sqi5)Kl%O^`hw3v7$i(MJt2GHb=G z&AVIxvye!N>B$;=*qSzsXZkLBeO#8<-dKN|PBk;$+>BJf2p>V$=ELyuo|QU*a1dW> zVhB_o&|0rbQG6O~NUnTyR08oIxHTG2dC&x+CEpATm;y`hqu!`hYcU0!9!T_6-d4U?lC@o3e08VAvZU&u$11~l zzEbbe`9Ry(#(#iSM8l7(W$gs(h#V&I9ctLc6Jb$Q1y4>TrB248Wo>6&97OEUb{2ih z#*DmXcC*oR!N;D?gK*dwXCV@_)VyyGGGCyv+!81WgxpAIUe0L3h{J}+f=%H|<@FJ? z#^Yw$uJIFnPL~~j9^jA+4MQn6pHSD>NGaprwb61-c$*ZqiSB%u!@=*N-Xd>DA(NsK zw_5%EE+uyWdF6VxXh4V+CKbVuqf}lq(E+hkD2i@MkkdRE7!L-Nyv{Y`64U>6G~&Bl z+~_}i)m3 z*9!<2e#|A4D6T2zqB`P!)WanY&?#DJkl`Ynp9r>vA`V$;t}k5_wjAl>@~)7u)W(Zj-wsk&;KpGxelk#p2yqwO|7s`4BXqHQ!`l3z}ThW{N5PUy9NagiIB9KgWwG1oMJ;-kaNzGdHD*f0Nd%I z<4IMAc=ZGPftPyz4aSv*)S!OrwfrHpk{5)@d7q_bA_YW+1o6TF)-11CE-Q>7+4NVz zntv-AmhkF+@|JndEeJQa8#jpu>Y1@u(8RiQ+7dDJ#xmjDgVF_YHvgbD-ibl-pd%$- zhTBBzqSA%{W}}wddiEKC!Wo4Y03UlieN8^?kzG)htFX$ADcKNFo(pq8;UuD94>NMD z$JFdsu6>ptf?jVgW7=3We&54aw$*MGcjw%5m*rYnrZ|@71QEuCkUvz41`eVQKj%$=*c@%KaEgmIyv$-`QR5FTUE*fyMQw6vkxN`Uy z+peAR{}cankuiee^?vrpr+i7znpf8SB5vKnrQoc0VlLE}>R4jeX8OMRAB4c59rA%r zAIw%pv()~+ptE|Cy#AxvdM#>RSl{-uI{l!x5KfAe$N$mvvOx+Fh~8 zc7R|6+$Mg5-=|Y6@o-BkOqfB{=1c}m2@VJ+t#E|V{!$}b{A-%_J38z!NW?dI_mz!_ zp{fFSPR22REIups!O;tKn|DNPts=B6_rKr0&QU~oy%kU}zg?jlJ9_jSHo4GV@2|#C zAA|~nb$;H48$(pQbk$>+sQM;j-KKf(0zP}wlXO__h`Koj49FD4yiWn~NrSz8Fa@B^ zAFbbrcrn<)*a`2QbzCS%#)~xSPa*mga@|}$T=)qK>E?=0P8NVUVVaslc9KM6<1T1Y zoU6kd#9i&L)45m(rgg$8xeM1|gZrw|x%zQm#9euDl|6}2BUbUc#xjWIT|l->vupsa6y zdMH*1BS0$7Ma^9YTeC~g2EEA`|M8GZ%J*g87@3Pf(Tp9>4TLFK{&pjY{qd`(+T%ui zLRYjN&)GO6e_5~pyKDfp`sNgf`5tJclW5Y#T8V)Q3|Ni~gDQ^vy&p zk-6cD*(&&Nh(Sgw&0aCPew{!cm8-9Jdf&=al*i=5H2V;7(pbtt`^&GS?q@~EeTtwh z?mtaeFlNhDY6~ewCOh1~zq%j66|8J%ytl)FYNM~5=N&*c?58elvX8uLsS67#^(ve7 zC?j0|hz%m|UxyrCU%S?Y{&_oOKEA#JZ{+D(I(&L#fhaFzby_KQE!F;Y>SA*VOT|+d z5yPWOAGQh*2h^(1wg=-xy9$ETqPy(Wijl_cb4%@Y+{?3sW~Q4iB<=Fs0xp`${onR3 zgn)Y$27QN1-MDZ*^m9H=jhE*E_N6EZh#pW#sLbuXSZ4)&dAIda3&Owb(D7QUtX|D( zu4J~4Q_Jwwm)?qFc2@ci>hG#lkaISQyCD^2!e<+7b@CJ3=l2Vl19_qYlZJgHU(K~r zZS{caQJ=<(zjkC$m7Z(N$H#JbFoq;V+=@}{z_n*;)08Slk+;MKuR)Iad6g<=-~)Ce z=Gx{H#2OOW%GVM;8^K!?l(m58Lh_COwoV|aS4XId}l0)GB)QI(J= zZk`sN&40U&VUxS!I9Hpmwy`g3AuD>%lxJPW%4W9p_oR9?nqgXEJ!R>C?J>q7qGBlW zI3av~AT+!V8TUfCdLu@C4N89W2CkRUdQO*JBy;jUg9095G|b}9I9Guokv4T)!o`8B3Q2-cyIJAwgWF#?8P*HV^z>; zVhi27EtqAZ8jXp^`EUzHM@J$DdJKRTA+6xu<##NPy@x~IG`=@<9a zG_yUDvaAPS;9HpeDT*@}q(J%om2(Cxq)}O<>tM4w*v{a!Ov0Iad144hEp;`hHcKs-KTI90XOS}j$ z3#%_84yp_qwUq^>d*i%C(A9)mNE{q%$UIvY7jhFqr>}V0Tgw(2X<^YI`MPkk<-zAZs9w*AO#G`|-|#bAYENTJ>ZD%o;J(vrCkaZiB|^9f3FSoArPxpBo!1Sne(RQpNRjS7M%uTo%+q- z3XJiUtC&H2ai?AHeAm&on=y8;7g8L(_7xU?PS&?u$VKe7MZL;U$UG@euA}giQbRhG z@Y0So>5fxO?iTEMPYYIbZBm7ldV{q{;H>%S)MC}Qpg$O04c>9cW~oYIdYjfvyqN2S1H`9^8#(m`ioN zRjZWL2|S3mpyaQC{=4Db5eNgNSRJ?2pc%P_mKnVLz-LjLTiQPjm+^T!G`Ke+tR}qI zde|Q+J&iVj2?<>>dNW`A--lObejFXMey1LZBMO|Y&3aKU?lntgenqD*bM#E7i>_coXYZy-)jv|tOf#!Y^>Mr3Pqi`2D`bs-y>OgvhRLEp1C*^80SK zh&0!*he>Z1p&>vfO2MU?%||_wLknD&U)#l@n#Wz5tnCJ{=vNzl;5Zbsm^P9M=7WJ9C=ovDY~UaOV?=uWf$qD@FyMs~ zukKJ^U&&e|Q!e5=ec};O{)w-@H0nTa!4y5I|K+yQEEgt`h&mg?mOP94Z1p{o0}BbvS7q>E_l@fY_?UvEi9Hc zD&$S2+0vKbaq-Ee6h$*G6PjgvhRIxOq~k-$rITBr`CMdL^ncA3=(a=&4cJBgN|GrO$xezKb^f#@EEI>enmO9ofZz z%TH00_b%Z3Rb`rugO|SIx137`{8d_QNQlAH!}2WA#wHSDBAvy2Il0D3-J(Cwo{IEO zq3<8oq0n{pr0ookW42ZJ4TN$bpJl#?fFUY@Wi{_ZXQ`ekySmCxmH?>%DLL2Utcxim z($Rn%(=X$MlA3)gRAcEv=7e%o6eP=HQr))0$xOf!!aP(fc&NOdT{MF|jhFqUjAcqS{ zRSKXVeTBCQzyN`QB6hKQS4&%3y?;XpL=z+>Pn@EDSKCA0$^@5O?Yv568`5uP|Y*4x{!tq*9> zdrJ6=_hyK%gr90!BA=i>P6Vh0m8~5!Vc?!P3ZNE4w|f2f+p{i{Z?xW=-wPT%jQJPC zH7JLxl*1aXlAwke`LZS+Z{Zyf&NxwSt=+h~7-stWl89Cfw9i`fX+r6GVDp}m2%HV8 z?xK-Ej(J}I-}BKqv@~>mnrKRqp}t~3N8H^Kc$=dxks-`Q`f!E_d=|l+09)t=WeAYU zzY)6%yD=t9^5X>0ZnX-|uHM|&Gm*4h3j(+w*gEH}fUcYlzNyNgwUl|cIn z@7(ONfvKgQiY8?}|ADt*hCd5)rz;1#7KGaTIbe9<4FlQh;WNMn(l6LV*#jINzy1W} zJJyg6DEZGf$Hy-NO*OJGOIuvgN?VfLf@whXB-lckuzd0JX^(i!S&}+A!FuqrrlY=T zv6p$e>!`eXS%|9mvKtNg%v%AQB>fi_Q|ba)!xZ=g_5zY_>{=FX?7=~|-NQ01N)8OG zZTX)(_!KeM{8%~8guhO;afJPxJXHC>*#0K2mX3Iapxy21&uV~fAss#0{HacUZs{>w z*Uj-2eIfr)u6uep2t*=5ahu<57*V47;P&G5=Xes}K}TC2Rzpl33%&~)>wOYax}W@L z9SJpKlC?R;|Iy0+zS``gDa9Gq&$@8BjICrTQckqKByqp*!*pmMZuDX<#dyR_QB86$8;eCzZf|&~UCx!~&qg-~J z&ys6Kej(Mtqa=%lCWJq<@#q)DQOH8cD20EGt!5=KG7-XWmH#~dz%I-@sy}fr79M5H zA9%2KJ5=fF?kj5mf_vu>$+y*q;G13Wua8!|~|ji5#cYo^Qfltwa}O(EA{s4k0{3^9ONz>=e7x3J=|M z$BjcTLLgZy=0iC0CzF>#^x6Y|W+WspiNqI{nM$nkp>urZsz=fOI9bSN`XfA_huLRr zN@dG%RCqwm1T9LaMx4Y}{%Q)nt-$GcA+)Ls*LJuDDgn2#IY|Wgto;XkAVmsaLzug9 zM)Gd%%K7!x?k za+2iKT$i?OzCGji6x6!mH+eTa;0)G%0n7y^4ZE3Sxn~Q7s#4fBlB}LwR?y8XfNNV7 zQWn9=^A|x+|9~}1w)4NceHf!<+75|N|EHf`$5K&9QGpRujVP$<)|_pwiQ!ynGczg> z!{&>-P|Dd#pZ{`z#E+XXYO-w7JzTozMx6EI3C#4nJ<|WnM;}C7)>~HwAuGy4znwTz z;cBaXuW$u9$OaP7MozahdW;>UCN*qcdo`V9Ki`YvF3|&SGn6`VJD2^gM=mb&G_#82DzWXc$o%H+y?I>A8A zb-$!)xW087oqCG-__g*I-)FZEIb#J;-#ghek7tnOGj`C|h%tdI9lG8Vp z!=hW=$DA(V8b4!h0y8pk+^MH0L~t)BDl6s>G)ErH%EZOU2j+SY`{0{6zJ9B)HE{$n zNgAT7+%Wq!_rx2qJX{@%Vx|T9ci}=ix56_d0Fq7oQpMlmAh5I9i@kM?j=i&eZc5A+ zzGDuUv7g>9m?(acHvmr2<#8c63oJPF$$G0VVcAy__$iOWDcoU}3ip2x?~$f7Sm`>~ z5?l5iYMckT|KV+In{?2+F)ZEt?-_>J#t9|QymQEY)Bsm$(@T2;^vuj95%wN2fRo~` zN?_vd1DEy=b|bVoje8*6jjRk-S!`)uvaJ3lX}8XjL|WMwXy<43MfG{l(1|L|1DC%= zLG-Dd_>#h^>d~ia0JGEq_9`{$7IMG?&b?zUI}~%1rghViH{>6 zFb2E^3z@xa@`XQsmcm=8m(|@js9+{uhr&0Kj+gM~{`NGzld`RL^Jjh6ZE2?T3`IdO z2#{~Sm@RvMNt+0WV)f{K)~RP$8c*MynAGqdW5PI3fOepJnKA=#r51!^GidEWbh3Q` z7@_p;ghqpH9!0I{73r=gvAp{m99DbjH_?)F59)$6?$h)3Tv%djcn@*q>QI55+#(HVQ# zN^pqwx$OKp--W1PkU?)b8pGJZo*q80cl_>pMYbL3ium4+bx^JGX^d~(V(*fLV zhFYEDsjZ4L=>^`)C%HuIMMM<;qREA)5?2HhzlJ?yal}qxulr3ye?5_^ZQ*a?yTKe( ztp-3`jRt?+$s#JN9B4?#g8&DiQqJ9?{NejPJ1K^WSz+7*^{e46KWX!NFCX&00s|vfUDMk`E6fq&7vz?h`u6OPUwV)@AGSO>3y-=RHk}Qoh&dC*11k-s zCE|<6Tsy=W(X@pM-7Z$ZJrg0|eUB-^^N^*XI^6h0XyvmN9* zK^bxvUe-ocIqo#+hQp7FZed6rCcBczx z5t9DX%=mpQWvO-U)XXb#gZ&}-EAo3jv;bkesNMYFF;#zcN%l@}B9f)|wR`j!1<@40 zn7vM@ko9E;G&ah2-8af5@U$rrx3Wgiw@7cotJj(Mmq(axti(`4zT+-slp$LZx|g#1 z^N+vZfl=wRUD^w~G)hRMg6;|rRjibZhDzP~iv>~zzFIi2z=L|ifDtsEF4lrlTjewi zUH#_#EE~HRP@*L5XFp+McLbV7d)R=BJJi{-ku&?pwovE`Xv_XcubVJURFh`LE;+(l~T?T4X8=*0eF zrWdUwv8bhMZHe-Pb_09`qG{G6XbC{Jy$NUyl~mLO&sI+Js*WFea+XboU}jEpp3W8C zKu_Zdf&L4~U{zTyg$2wUh0~g1@8uoqr*c_I4pl*DRT4o%520~E2zyk+Z;Y41U}#$0 zf?&xMw@$&fT!9FyI9zyB*mM}e5g+L@V5a6*`c*ZbrZKt5>sp+%r7!HR{f`UN#K zhOoVG9%YovdKu6&`IvVjw{_!DwhP7`|3|Vid`|=gG;hzO!9RVo4Kp| z_SzwRPC|eOG^2Kb`Ref*g(4ITIK{wz)3lJuU;T{kT|q(`4tp~`@W_vH>X=Uc`{<& z6}$52k*(4S7>NqB-Lsu)_Z^*ajEv{;DE6ev>px+FOI+I{SB(;MzA9Kp2_8`p-aLO_ z?<z-N~y;Lvm15s;OrObRME*x^=Lb1h1nc&Y+?*6%*_QsbN0>UAuvVwW#9O|Q_7 zpi$TeupgK8>~Tu#p7g|>i%iGh@=~z&;9k1(r_ndpWk+dglC&4{0C+U^KP%^Q@_H-7 zX`IC36O}l$oS0{nb?3~dzL}nR{cTH~5_&BfR8x&8zz?m4$jBHDr4|jQDVBbt{vnE-b6iIt8VXk{@4~Dmn#yWnF?7a%$G7J_&a>`$cIRz+ zD#tdxcWZIlxtAeyc6H}@c9kZ{AsR(_hAH9P-jC!OwD@~Za&FGU_^ErUeZj)`daZh$Hz;rI#q z>#>|^+TdYkHi_-Y&YQpPIYr7G##`w9?M8XEoiz zWbA!}TQTH7F(MWZE~@^F7`Jps6oso8FNS$ZR4J^$Z+DA`LtX-%$NsdXY{9Yz61h+L zV3Kg|B^rM1QB=e%b^&Ot3g$$;?KG`dDyCaHiPUooPa1+g9j9=NsQ@t>-(hc0KP4HwNBPFTfCa5Vnk}na`9N#^3O*_$XW_F0TF+@jLYZA|}V4}Oee5+D0 zM^(tu^~+V8&~L0Z5a`x9`5AEA{Xp}O9o?~pr}ACeEJdaqKj^QSImd4NM&WRz3j+D9 z`;^oyp(J@;I+I%+%2_oxW?CX3iMMjl4ZjD{?er_)a3lCR5)-bO<+Z>b;#&$u_}4>( zVV@iZ$(EYB9hRP9&V-I((b*Z@-pJbWTj<%z=zi5yw(zv0o7ahryT2DY-s4hazETAd z+ug65n>)8d+TQLT1EUKMmVRnslumv2snbY!orx;7(2_(FFKeyrlw`ZNv!t|Q?k?@k zbb6Lf{ZrzqIk|;osx`mVctWb-n`T6$F9iGsdRlFqyI9SA6-ieRlJ$&KToIgUEqA~} z^BsUyH;43T*@tNUWfY*sd9nAo&x+>R>77#(>gZ^V9w5?iQc5UD!xUb*tbjYpXU-lP zG-NV{y&)bhbruz5x-)50nQJ?h#IqXK)S=&^`@AgeC))3xcVeh+qqLl&iWVZvnK0LAt)-^x@2mXwYokBVpj#`r)v|OD#dlZFhY{L?xVN3cC393)p zwdF~!fIlyhytfWN3^>eGuvB=WbRi!+^omX9og>Q-64Hy1+aHM@==XrF=W^BNSCkv| z8+uFechZ5`C~p#f)prRf*lXHWJ}y@FrUFt<$;~Ur_?qak`K$gs>RrY&ulcyo4r3!a z5)=0(|AFzm2_X!!Fk|o`=T3-7vNFDoP%tk#wk)}Tq_KIr@A5nCe~D<>0R5pcl9*LrJNCVGcpw8^F}50A*f2DcV#r3HH^@vGEVls12`+9 z^hBjW!zS6)(+5T@T)LT0Wb$Lk?Ul?C+1x@UlZNsy?YWUjhulT1@dMR=JnGHyGFChX z=jxhEG9UXNZevx?s>`gzyvl3XRX_Iok}{pURN0O+|mgZ3N$-|PQ8*9 z6nGY8T84g?B^?^jvt~YzE2#&vKZ{LkdD`I*NZJZ*!}Jfj#s=bH>47WJVEwcZ zepgXy7)T~Q#~5pgiN`ZQ-EMi=GTPcyl!YosbHz@ZwkqI0tDGPhxqUwJaNtFX$F`yog>h5oE-wbOgp>cB#p4t0ZkF6zj%MU2}I-By!#{4E^mBt@} z(M49yF-c@)%&Op2>lH3dL0?dp&%=-=%UC3if0by?CUw=c&Wn>r-&5lSlV@7221`pz z7iy+H>b8J!iS2SCJq+z6qc?6t#?H9jCd5bzE7*PVHA&=_NyV!F>mceQ4-myBfB*CJ zZ!sB6+TiI7328Qjn1p^$6V%!{eIlVkKw=}J;@M>Z9TzNB}uCro$CW!zi=&EW;Vlk(!bOGBYOMfH{GAF zJxIsUA87@Ak$_GLT||Bef*NG(cm!u^dHh=|e^hKKU;dpD&p6}T5QER%?i+JovT5%> zk@?r<{QqF%8RL7CEAfR4h@|&%~{1p zUQzR6>Jukk80IO~7W2fm=>V70CLx5j%A03a*l(K36{dKYQ>Hrn06Jyk+C14%SClVi z9O6R*N%0`~?i}^7ME&+uVyVB+`}o$l9eU$_IKIT(MW&Aj5T_WG%JBX8&J8iHw7Irm zmP+@|g`A0CGKN#WC6)bL41yXOvalX?}AfR zu@+&PK{*hCetSP#r2XWUHM4H3Su(VLiq829~B~s8*6>eh<>v7Y9B*q=+P8_+2)rjg;uXXF7 z1UoYcxLG28ExF5#=+b34n3}(K1x2ZUo3!DkXB_!DbxbSPR3$u@cxO}rB)S*uuR}KN zIl}Rr?Ur26a{?5#S>AS!IpSj*<)UEo+`GdL<${?A6SOP!iB0$PP4`KGS!k)iLdQ}a zI=kd5oLH;dJZIPi#p2!9>+jH?Lod^X!k-#LOXaBxv;K)Bj>)QdY9bkqL#jxd!>OC` zxqMH$jo0q!OFXru*Cm7W+WdXA#S+=6cM9(#M&1FF<{Q*)b6&4}U1`3oc&F)qr19rR zxva6xij$7U;b8#zCnZ$faZe)eJQLo7PdDaJ5kmmU7aSv5lXRd@Hb1qaj?nKecF@ck zp%@~PVr^r7y76TnwG9=BY^IWd_Il5rkEhyu{+B7TL5c!rV}bl6bLqi!>~XqE74av@@xYG6;*#@t02L^N@wlAXAl9j`DWRe7;!&X1P}Ot(kMUI=4Re@!w;wSOs;aO zvUq?iXlV&l&V*i`HAof7rwPn9{)ZBlLPBkF4TiKXd{@{+kuJmDpFr}tIGgtrc9w0W zSRlWKF*4d-83u6vQHSM8+_;dQPyQ#$;$Dm4m^B;^4+^!V#yN_nPwZc{#WICn7-*_c zSxSv^N+lXbR;Vr1MVYc`>Est4>5f~QPd${3PT$t3M?IS$lDQ=MO!@r0!5mO*ER5PM-48KTSaY`ik>Nh|ZJ^=E-{|S{L`7A!Qf0#}C%7Ym zH)x}o10Z(?F!L3F4!wrV_XPt-d2cP#+@(d@aMJFBZKuofVx#4lEk5UYZy-Ic`fgRd z{|QT9$(y8mcbiQ+aSMs|af}|QwFiiB_@_PvR;M8 zIXZd?oZgL2OP3D*_bJYq)t69u_+J7Lo{v$=$j>Ofx#^j&=o@2+titIR;y>m-)yKar z`Rc(ZvFkn}rEegrao$!SjU0S(n7zm<*Tp~{e(E1~7T$V#Aq`PqqdU;M87OoNdS;Xo z9;9+QH8@Pva`IABa$~yJwdSfd&uAH!JTu>!QucmSJ`CeKqKVK!aPVcG-`f~VAIIc+ zi5)#+9RoPC%j!FNhFu$$(uq!oL(b!`fJq*{zkBzI|4r%C)9%GRL^eW|r0Y*!d|m%R zrx@L)TNTDrmUxQ2?c|HN)&xZ?`R+E1I_%xoGWsK^KSh6r9o!U0)=sP{?e8e2UzEh~ zx2D~PjS}*Gp!VQ7Xryc%dp^KkcpLCATG|34L)nEKoIPyK!M(Jnt^5rmku-6fJKIU( zrAE*{So#{G{V9f(!K4M?Sxa|d-<<>MH~*CN%lKx=r~+!Y`ybWm=@!Df*Oe)DQ0j3t z{)fFXCK)NtSLuCYQ*NUzNy~Tr2s&|^p zL(TrA1w~&Cd%ZrU6(1{d109SF>Z)}(Y-=MHr~q(cmkp23agaf7R=5^qV({0Fnw<)C zGf>-1%g}q(2VSaHvNEZwSI*{ZfiL`s6fNDZ+*q5MO5h_iD%^(=^)6`I_kjgVhD>!- z51UAgYnNNMO_rIQIOVU>wdF6gT*}dZBUxH1|5+T_E9zp0i^il+ZR+tU(D6Z`*0``~ zqCvH5Q*xz9+SH3qpz?f3_NbCe$@w-^iZwL<--vFzzkXZT*x8(w>JKrBjvwPY9;uY~oWf|*SDHFhvrCFZ(4^CZM@E@WV|$!$2C zM9<(k9q>b@24eLxWy{alY_0fYL45OHdFsJ!X#74W!*CT&_sqE%j?Rd}e}i`&TfO(7 zP#-P1Dhkh2Hrk`8q;(Csi{>L+&d~d;WZT$EeSVkpObBDJUi5>S4W1@mXy{8)%R?K$9~-n!;aT2ooF2urqzi5~G5h+VxK zlRk{|TZ(KxVQqqU2p%H#{|kyI1H8m{^lasI=<*IJL7HG$-@ zx`TcC4MaNy39%V%LjXN(A4Gowbz|fZr-h4He=2hsh?h+G!$_F67bK==ZR9zl#3!bI z95G_ORctK7S)@a=OW^K;>&$4Mp1V=QDfq^Rbq~fUPi%5IO7h@zQkhU(>j!__S zw-7*^g32SDrSzahYoD|946w+<_qNrC@5j4}YtKXo$zN*YAAF4BEb7lC-tc-I9yj zBs`?6=EmIyBvBRI%H8~|zuTWnLxtLZ_Ex1_^}F-*#RDkSc2wl6y07noXRWt8$o(kN zeNJOlANP>6jmTi4YuiNU);wpn@?z?3{u0BjphfC`t#MCpyRK>&PIJI;k^FlUVk+LJ zEW7<-UzxO|_3;KC={y$UrwJ>l=TCEgiTGoO$((2G#0^5xIILe~0oDG1=+nIH(l;B( z8j8ICNpor;gh7nSMd`eJz;d+!kC{F{A&ymT!*tQhvDC8{+|uUXKY0NoovybT_7gwJ z&6Jq;l@vOoJCCj&{ETu?k5f;1jV6nJ7VY=mM(CU04qrv~@=N|9X1u)1X5WZt@Nxpx zT-P3aW)CtZjb8#NglXe`f<;ee8J?g1zg++?xG}=Xy(Epw994)uZ`Yc8nKqtmx%}y& zIdERo%08i{+Nn0*kGN`sE*s1&6lIS}D)p-^Eif{q8%Z!~K-_d#)|h2{3zr&UgaC2J zW{!I9Q`mTyf?PdYF@Qg1@E`EX0WsFRzw2d}+e+_MI#ar`SWX%3@DI~1Bg8jYV@#yE zi~m}>K1j1se#CbpEF7is2z)No<+-(HH%>Sf5b;uLTvbGMiDVAm7pT19z!DXXp~B)O zdMtL#AiMg1B2Rt^87@PE1_H>HyEYzzJnvvQor=>!SbA_w<*tmnyM|8S1iQ@8Ki{tkN1hvY=QH&<^5wIG2d7HyU|-ev*`h3)5rS=_nrEL| z?^i7W$ElKR<=m-JfkPyU{z#k<6w!6q`ZVwNUvEho{0zaiqD03ZATe<1l9~Iw`kvS87+X%H(9*O-1JhnxbeG!_6RJKyJA)r*OKL^VER70TR+K-$C2z4-=bv|W;x??-g}Ip+SsWbJ z813D@K1*Oz+v?i>duY+NFKkV*ME{A0)ZfT2WUQ(27BM##x@4~GWk29v; zZYLV;GVVE5x5XC#p@#Oz;U>1J;RvJO^LD2tD0txlM?!qtEx!NM5RJkP$A6xq;|S^GxGc99KKdhD``wGV-tAYFC|>IN8PCPg@!RY%nhne=n%)VE^shASwTxH%ywStHQ6t6 zEWAkoeUVX`xlj&E7$^*j>}7(8bY@e}PDKRrcecN@do%5{ZEsmlEUCr(&RA;~^W{oB z2(#&2tgIu}LuC|s#> zj?e-`euQYP(zDsaKRTY=^mkPSgaHf%Jd8i%K8R5C^)V=l)15zl6=CrKl@%gQiEXopAdqyip+ogt%#tMWm9~dv z-yLhr%E&j9$l+@r>c_RIHp_3DSt||+Cria84u1O+(KL5h1Pt!Ndp(B;=qjmc_oR_6w!H#%dWARQTZShT7<{oFP zGP{&?CQm`$qLW&!2!G@oU-zXq(XT5Gs~oP}Ftv%by!HFw5|?O{ zbjnnC;h!W1`{bN4qG5#h&b=`Cw0E{Lwv}Z+3fx38O$FxGMX7>-B6iVn%~4oS>=)2CBEsiWZpDCVk{}xO{8p8c&Hh#3c5g4c^>P(*MeTy1(Z`#om8$>s4PE&h z<^_=YK&#TX`(~pq1{XlNB5=uryw`#atnVlIw2wQLi^#COvEz0$-pcUxYg-m@k)A7T z*Ha+5djKmhFWN1(gnkkgnc$H$3e5b;yJ7_(5xt)@Lc$J*j?Cs0x1%=PF!PG4tw}v% zMYY!u-Ks-Y;FjHO_ODk=-C-|d?b>)ZyIP7gH*)ztY^}GZRQ>S)kBta)%x#l>A~4 z?l`kt@<-xk$IAa;adVf)tLm7Tf89G@U)IL#kJKIS6LAx;hmJAB@)T_$dDsc9U-cdl z6VnyG-wp|eS|PD=PU$|%VVaoiTAk~`IK%G7q$<&ghaVG!6H1roi?PVnex9hraXk&P=_2Ui_nnznz6njYw!< z<0`YS1HMn|u~l*T-f|_D-dQtNjs2ikr%(DpS|E-@BO7Q-rIE-Mkoz;+@6p$+f9b70 z??MWIwR%|J3us9?|D#87RBE)zZz2baYGY}3b~m@q`SEzF#^ImB+9+P}4y6z;R!1e8SAC1FbTIh=D z^u;y6tj?w2S~cB+reG+w;DVdy)egVP(sZ4-rJedC%_3$!sY`Xl5>7eYMcZIcG1%bN zyefZF5OHq(eXc^x9QU80J(&hZxxB&~V~)lZ;REXKL0HSnh4PzHUJgomR3`F6K}Bns zLrXk&e$u(4?ruvsr~#NFndU8A$Uaf5u|dbJJ#qMndI6$p0Q*t-02ipRKIFB@)Yzw^<-EAJb~(L&|Vp?Qf>WKLGcJ_ zyH6IZd5M3~c9Z%^M5KeG!Hl$E?e%Wzw2cU5X_VuQS@nD zLwL$`XZvZcn2l20=fOR6t?zlP%2MfEs;1=X{v^n`g%QVGn9FjD(TED!LPSyPF!sV42>M<3m9W#0) z~Hy%=cl%u1wVmKg(27GGX}kVLKN?E z#S*dveoi}`eYNz9uyCgT0~pC!;H;7;%wpkC@YIY(+%~4w+*RJHDw>8sCe_?C`33KO z=P>UTHlv;TMyRrb@W##_l7mf(m4Cp;qfSvA^6|=bOV3uon1SAsTe|)M@Wt2CWJieg zfhNNdsQ=SLFfM)mgzZle8;1p&KL&4#4x!?&Vy4iZNx&?Uq*gwp(h%}xb(wrHFo7iE zZvZRxNX4g1*_(1VkAR&P@TKR$GRYnX(V^F}3Zbq(sji;t5~yT{aMa?<9T$D;NA_L3 zYbtoxxfGSf)k==fZS0gseWUruD-j#ONJiT-5Af$9!>$$Mfo7hl%IY~ihuK8gJFIfM zYNB$x&^Qqe|3!Y%S3{Yur3J$t{2=%k-vN&aR~{vuU2mPnVeC}mI@m3aFK47WAWIQq z^Z6Z5Kp25#_i^In!J^r#DV~DzVJAoK6$yciEH>K13< zKD+OmRS`e6u=4LCEAz=WdaJ(`Nu;rP&>Py58y2Dga$6k6L)_5-%T}R-@L-sLIH`HN z;wLjU?t|SrXmOm@<)*mjMkH*fsMbwePK!uUG&6;|M{87fKe4=0TnU~_yt${bc)2F$ zJ+P{onh8+alc!yO51XFhwyuxiA%kCxO4z3LXCbHmLUf?S}MiA z&N=m*T6AQ@NAvjB{jT$AXK}7RV)LuWc>LFiaVnl4{DRo*rA*Y}ZiEg?UcNadq4xL9 zZW%4H*1oYM7jc}Sh`G2O6d_e}@O-Q|b4t-y{9`S(r(Xw=YT~gMI}0hRI47+jXf1({ zN2jA#uWF|;KaaI>Pn1l6V{b-to}kDeW;t8Ar&hDuZI8zIFQA6y+;*rIU68HyL?r+Djv@G?|2zWz3We2V*RW!m?5xzmzS zSL%mWq9h=e$z6%{a4&(iB0OAiSV;p0;h59oo>X2>fVG&7qE#<(tH6GuH|6u14-Hg}7JIiVJG!wL0rQNG&nSMu+V&Ul7d+E5Nrk|FMXzE=aQJdCE zCt_cCJ_HuM&-56HG32l0ja<=$?8p-uGuu59_1Z%xm=a()Th!G^8=1@_a7J62#LPu_ zZ>7*y@f4?Sdu;bj-?GS{UO8!srtu6HyE-F4rudcv>>;ZZnS9e0OOSS(>OqC|8m=`( zh`$Eo5R@4PZGuIT9eMpMyl@Ol*BPXx4r`T%|NcQc4|L z1x?jTXC~}!QS9BBb))h-I`4Kmkn9`}ij-X-PhIpogX?~(W*EbNl{QNKT9tJI8Dd_g zYnO`6HUA?5)+Ok-_|vWx4&lMG=UBvn>YwY_eKafZQS|w%G7p?%a*}lln=5K-y8pE0 zh-)N!c|gb?X|3uSdFBhXU7npcNBz=VHf&{Y`@vt`j`=^p=2a{D7s0euAFwa+d&|gJ z;X!yHY*j{sd7@X>)CE<+u7qPUEV4F`sj*uuQ;?&&b>O!bE+|#%J5>QT{1=AK3T3ypv*}g=%f0|wAI9J?&w&3 zj6R)bp?ScN`oUz{^^n^Q;&28={$S6CHvf0+C(9okx+;2$BItz>udYor>)9nQ8u=zt_>h@42T0Cy-lE;eAE>Z9)M?Frt_r=eRqTdF9xM zz@WpYdz3F={Vy~|P}^+ImzSX)MdZOnKiXxbNmt$OGGe5S%;G9zCna~;=-ilY_K!Y| z@g5x1rJ1F~wPDPDK&TwFNAxW|R>-@*)7IHl>Sufu*(AL3?kQQQi+;jwE=4Dm8=g$K zq`op(W1vRN@~EjCv8mQwC}rAwu0B3ND#)l*{IT`{pjMK+oS+YUFG;uAvTW0d$&x6_ zA6_u!sTFUtm1}SiE}Nxpm+h{01}GjN?R~K*oZ}Z~QH9WMRgAxsHg{3~WK&a|5X{Sl zpLl}vQ}@fHNgv71zeb^KA(OS)LyHvYQ?H{CJv^pmjaSod4$o#>wN@{(ej#mHSZHl5 z{MwV6xZS!mWeM%?3rDIem1B)9Wl!ba1^ua`9gnQ; z&@)cSOP&Z5|6{i0&xv#JDl-+=bgsCM2lH+puYN>wKtr$7lNu*^j^y7;j&}v(JA3fd zVyE@Kh^&`tya`)^2?1^q_Z9{T6-ni!t{urlH783x-JJ6QJTN8X0wW{@q7H5{eA9fD z^tATBgjgIMODn52H|e>iN1u)`g-ZlR-b+6*G-mzdeVWjwD^eZ_K!?F9htL zGad!Wliu?UIcRV2`xwAq$hV}M^{oj#y$>3PJ>AJrcmdMP8J$WBK(0oQ)ykz*pHn(f z5<@9CuA*|78z9%of$p116h=%Jg>Qhi<=lRp*b?9C~*GOfM{x1;e*x&MQKg+2C8P zP`sWbEG(@Mn&uo4(_~v@ImXhK`82X!d)b5>mJ8djL&edamhzkjX$+^d=$=t2yd$%E%h>Z za}uCKU7fTdIGrJ3^g4xEW;A@LnS8ZU$T;z7RaN-qa!)U*Tbu_I$5P=fMTXZ^G!*uk z8@Iq-7DSdrr3N{iO~YH=&@NlfkRyj@Do*=NDktxlIcXeKXTod3aatQ5 zv=x24;FN+jIizUcP0|AVY>zy+UDWH8TT}R6_Fs9loJrFN^A~dXB3&T}CLL}e5m!sZ zM6ZS|N=9GHsFc|@$Sj=`j0%8J^0b^c^OK@_Ex-3U^mKMG+Q`3B%BMik97Ri$B_$q9 zP*SHIydswnx|??9)a-MzB_zEMlKd=#1{w~ObHTaRr-)YEHd>*-XS?|!Y@nfLyzDmA z@zC9+aVnnLXpxZCrw|XC;4bpMKB{opuB352SUUrS+n*g$anAs!n6NyXn`n^#gkXRh z=7~bKO-TeYB(a@}ZL-K#>C3<-^S=R#DG#xw553*y zKC}fBW2c-v<9yY6QrZ`Toa%L{$l^?-WNeC1IdqL+na3S?y1k;1FLA=6pqA}3Q%Zh) z{rNP>3s*yJk8O<4DyS&k=_ZzgVKPWTRGCeRqI%HAdT2Q?*y}aL)EC=n7+dEy<-4 zd}LL9zCzMgzSqke-1_>#YGp||;?pW$s6eV`kk1KP>&ziLsn7+Dl&?&FC@;2IzKml8 zO}8?gnuc`U77w3G%Hc(!=@0&Y^oLfTb5l4Q+X{1zIS)jAoauh*S>q5DzKCcJ6(0it}7wt_PApDE`NOFkccBk%00oHg= zqBzv8>5U{FWI+-Sd+1$ThD5u}`JlR&ffxlS1H)m{++yZniIggfjua17?O?W#N~ie# zML4_(XdXr1nWA7ipMv-1d9&?vj?ble2XZuVCp%6MC9xy~{%HJy?Xct2VG^)>+LZuP z=J7CJli}#FClkq&^;{d=et_c?U1MWXzS-YUHhg zQXy_`Tb$vdfpmRoP6@qLAQDnlWPzC}Bu?WM*GQi^r_$H<;cr_3CQ3TGJo5mZnaClXZHOZL zeMXo>@G5qSqzs1$@F-`k(8cK)M#bz1z~6Gt=a4`2iB0S_m|%kmYfy8)H(E*t|{G zUS+MY`&e+5_j~2eot!HoRN`^mrvHaVId>!57zuC`y+|A!7%4c}A3?PlI{rUtYO$?j zWmckevk7%=WWVwv)2>_=%g^`dQ%gJ?yuCwwS(ki^1A9}&w)P)weM}W?x)dSYhk^_p zcuSeRIxJ=8TW=U}$uWNY!Sun1aVpx5?-ju^Ce^PXh@Cb=|Da1mJ9bs) zCC6t2`o3G*65hvZWtD9R<~xctA@vBN;!(Kk|9M#h=Cs!(-n`D%LGe85AJsJq%zDC> zPMUj^3nSDS_<(8ygE9*SOHrlWI}JOuAtcoN@ATL|4A0*r#2N1LetKcn{l!V}WqOv0!^cK9({ksaMDKoH_GrAplirXZlWR2h5ghW0FC|T1IJu7~=fLI>8qmFb?^AtG?lG_m z*PJ;WOPK1(_NlBd(d3<355TcsI16jl?XD`4cAn_vtG92Y90PL5s3gZ%9Yy=2{$@xt zMkRllY_hH+aXE5^|Lt*L#&03yt{!3!9F;`x$U|?n2Z+1XaSG&jWXf;bQz{>3*1MGcv3#a%&N->R zvA5|L@|W;JJ5tjcY4?(3_)#qW>GOG~kuQe7Ca+S<+E!WYHPPxsC^3uv-aJWF=lx8A z#G}t!8y&_S*PP|SDdo&~hZV)PP%m;RAY+52|5`tq zJ&y^s9X2h~ernW!bL)ZE<%l<$X8IU(mHbU3*YAo`0ajB{&z0_18GT;Z4$j8~0Uf^8 z(qC#^aqX+KiLPCc3V-sgw{KPDwXIKh*ylL(+0Z#{vA8<)*56IRapmmAt?Z*K_n<`- zxBQFL{n&k2Uzz+$xl!XPiQx`jeB+?ry7JKDQ2sg?U2DRjKEiw;xO-x ztnYE*LA z>ZEZ4n&?4TW6U0)SMTzzJD|6nT|XP%{jc(i0oW=dTos&Ua#v}-CVcg#iNGPWP(kLq z&m!ZYO1I^HZ&;H{45P5|huWz){~pXo@Ebgi*Cv~UpG!}_9zc>muqp1BJ@Y)i-HEfS zj~!>>RQMPXgZ6KUaEI7M&Px9nx`4BUt)ecBYCb&J9e%30fdY0fQAUY^(}e9Ey{Uh zAsw((nQ=C2;8po{aCR!Nsy1!mg+Te5!GZM}-pYIvO$wx~^!;p6vGHqFeZKrnxgm?| zlrVz3qQnm!w1GF@~OtM0_zJ=4`D2-WR3t^fBj0+A$Z* z40@x7OZCIp{I8nCtr>01As&#nKSEOJKUR=eB*4f{c<820W8D3wG?OZl!zF#E-8N)h z4>g>*7=#dta@q@K8G6aSYH6Jv$w0x#^Iu>->g!t{{%>d%7@d#DYTq+vS@lC(r?#4E zQ>%X7ZGxAhm35@E{T(O2ZqP;y!y6pJ0Q3q%BRh^trkcSD_c7}7+pP!#hqUi zJu&wu_uaU5lLdu#0FJSZc0@k#iK_!GOa-}=kMUj_9Sf`sS>zQC+@`)pNvU&YmTF>-*Yc>zs6o^QeO|0 z`y1Xy@AdC2ptG%APIe6k-EVs^9B z^L|o|uWXn9-jj^^dw3VK`GO&C=^y-z?NQsF9rw&$@mCkVRv-HWK#&cx1PuAuY z!(bbg53I}z-tuEYr~~DpCBn6>wavSfWh*!uN8-04HMAY@UNFU?afB(>b_5TF#t|CB zuQBx4KU8;oc;K3THZT^jM@{+b|=7YRoab4^feZybJ+EP_nm~ga0}*3bfcKI`&sDY@;Pau}On(6V79)GKpGmy3 zgHk1au;xp%f940KUcDh@80MZahO8FP%c{FR;{&ZY)X?Fp7nSs%-uP$xyI8EHr>W9L z@{89GJ|v@eI#ekNrO~`o=*nlJQ6g2}XA>-%=Q;S?Z033JCYQN>vZ@cFoQ1C;u3VKl z^iow;Fx)u@L+LA*XT_$Wl*(o<=KEQUJOxAN9L51&bEz(=+@)8l^eGz3yMRWJ?vU#h z0pnHNJL$Lab_EpytCqPMyniu;t8E9cwVUM%sMq+?aUq{nPHFB#itQfAwQ4q1a#%io zQX)LZ=any1I-M`NZLgSmSEMPv%^-qn01F;6e<17Oi(s22r0z%wn|wRKvPz`YH;D}O zOwabUFO>&b?u4liCn?-+1irk@29H?t0&O(gVY%N+CHG40DY4s!hvVyv`1{bQnKa4k zH{`{9bLA$Lm?7p~*(*f8Y6h2)ofYyWMt^68Qe)A&D#qC5Xou2tIEl|cF-uoTyMuDi z}umafUGV8ei^%jNd`&(caoKsO|Y-9te4^SuG32CtVCW~wx z#)~KOid_`PNF-}4gXuzkXizQE^HFID$4Z==z)vjG@=XOn$1=#N``}SjC+yINwIN`! z-sUtJ14!?=5vuStsB0D>jdqbXh+8llPlMi z4xa%Whnwx%6oY2er!cX?=|;gRhLN8_V(B1H%K7dGp$UO*$vG@LdH5PY*xpFc)5^Ih zC4{b7t&d2;YVFOu&5%*K4m!qOZ#U2o|6qUp*ciGgfbr|s>)&Y-g8L5(Di%&1rZR(8 z*osR`E(rfGx?y1 zgORCF_A2n#M^)0NJO@Zbu+`qgEqLCcN@`QgkJ36rkg_m*rJ*&p%YExR?wlq0e^vTA z0vsOE|Elx`8p?maRVS3YsX0!c@%+g1?Lx-n*W0~$hY7|SdI!eZC~yWn#n;~uNN%^b z32?N$2|ZInOG{)TnJJ2q;mfYJgZa01L9M*sr31=qn(e>jx&6S@e_L5BNp4D(x2~S` zrCL=b5kH8S?)BoTQy5R_yH_GXhQZ$Rt62W2CutT#OIAbJiK!aVY%6u?#LNTi5vfOC zYy3?}@Cbg#fh=fPGO8mmWqagVUV<2|w3XJZkUBvO*EU(+sf=;pyxU0frN1p2{Cp*y zrEO!gR{@*f2`CLgL#kjVO6kxKM`z!S z4x{2OS0tG}$2twSm*0s0CTXirg|rf0Q*FM@^C?o()?e8ZTP@-NF%hcD@(&SDA;ry% zKSHFf=VFm{tI}|rE=Coaq2iN01VwxyNV!`C+UX*3E8*^9&++~p&;~M`e--pQAx8H2 z%N3$iP=(~1q5h8-%KF{rX!8c9*eW*AzoqOoxz`4L_DfVtZb9qwAG7~D?yBm{*z{&g zK{1vov6W0-BL+PZt_mV7IxXVx>&yTH%DUzX(b@&1_Pi!*XRO-Gp)QT2@Z6gNtUvo+ z(6Vyui86D&X>~WA1K9?l`v~-WSiN~?NH?Ni;{Fwj;p1iqsv^R))jtr`itBC7j+^8;pCG8C+^mir>?&5cH9 z+}!6gn~x;Z&ma)JU6v6K*)t8+-^0}b;EZ@UOvQGdMxXC?SIJ0_EHzqw5&N2R!mJHw zs(Z4?Gx+S{h|}Mk+>=yr)We8W1-)mimn%K7!~yr&2m9`~82M~{C_Drvy2s-q*f7%3 z(kmwl*WTDbzxhYdU<7ql`u^3RN12r|-23rqSMnDIir-%q|2x!SeDroRe$>M_C#vru znskFD6h}ZE1B5JiNCHXS!)*7Ri(nSCfmHiW7%+q zCmf1yUfO&qInVa@k~NrVF5Wv2r0pS`P3IU!09 z`a%8s(`VfNPmtTmO7cHIJ#Q-JYOQ*4s@FOO-mVb;(SrNp3UfRfZnRbh(l@ENvw#!? z(c$A+gOKKVemMogJkjmRiv)EQ z!|1kTfnb7+>7b^o1G(cA*woQJU@#&yCct6TV2MvEywsUt$Hc4|@-20Jverz%MV8$i z`ul|vMEng0o7u}!UHx@yd-{WKD5vi}e1hDQKO{cKv8C0f)IoOf>Ma?^DgO z$rui)3BoB=aB-g>;?2%v=~UMr35iReh~ocfQ~ae(gYz#yO#8H>v!ZKMh7VGj;%I*5 zMLmUEN)>dB$*l#ZY%IKqVDO#VFWR0ZA zk|w$)`e)bp@Uhz!%fig{uB~c##uhST`}X14qxwvV_Lx?x#GzY2?+D+97QL|nZ?jGKE1BYI4h!QSem^2-;q#@`tBlCLgvZ)+S2EyL z$-jecl|j2^#WAeO&l859nKijHAbu3dPECPhx92mbFFD2t!YWTeQ-g?$Ld|_+n=hRx zAZqO@GuXEZ30wD4-{U(_c-Qk02x|FLzq|Y0H)=&;BMP8e=11>8&%6uh zRk~2gXAjSVxGh6B-oN-mS7CHD#AT;7ZxHnDL9bwKN~<740!?}g?Ta3F8jXr@UmEEG}@=o7hfP!-LSWz-ZS7-#ohYmV9&b!Z1!TxNYGfGVMjXkfEkA zUDt1{r#zp?UCmw{uaE%a%NE#23Sra_-x+FTv(R;r{VqA`aWC@K8S%3zk?Z3%sc*g5 zb)9wCGoLWNaZivKJb(K3Okut8$jo9O%&g|MJpcK-WbdJOP`?`coRf-H#Ys^ntG4wX615wX42; z8mvxEROs1XUUpH-a404wp6Ta~C?B&KAG;gpToEjcUuU%_-koPVRq90ve%F%0f_fWL zi|hMtFfAb9VnaI`p-R&YptCu=Y^ToQJGOQGCTFwk5*n&7RZzC*6r4yVuRxtaDU%wrwlhpbn~tVdOS*lOix3e%P3SZUV-$EV1=G zdX)BO)0j|G*NSR7SRb$zwH)XPK^sB>4;)0>9If<`UsJ+tLADmCQTr1{RPrKZ*-<}e zwJ$7{s?eWg-@ReFRy!~I%Bz=aovQiBI7in0I6#)j$viqem&io)aY)lC^no<&0asy! zGeE*CTL+=iQYd7IKm#EcFrQe`A8at6|A2W1<-0d{`UrW#A1kg@CD`&*d8=gLWd<$p zw~acz28MoP-oXkjN{B@I;_)Y+

      x#^vcQ>*KtaYWi2pdYHf;nNvL@E(wV(Qa5BAR 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℘ z_MeUVi$GYlYhj9mI+*}rOfetyuug3PBvb^Wto( z>f{I0b00<4>hbv1iReQj$t-(O*^K3%jLa-33w#WS|N#RtD- zCZh>D%$SI5jio+f!5mm-Ka{|y%N+?4>+MX0XB>1}IiY)|&j6S9(( z7?@W&Zme2oy`Vk?^HD<K1Z6g6FFWs*R*l z`X$<~jMRO_`9()w31MY> zO?~k#&hH1D9xLrzQn=qbJwi5!+WyLIfxQ=5Jn6cWnAII8Lm@J%+K`gO_lSoDqoA85 zCjUYT9<&-M-f8&%J0ivN}u)((*Gx7cd>al6dUG z3V}S<)0OJ3gVWjY?m-m~ykG;ccurwfx1j0Blxtmg=q@h>2SiBlYdbnoA;uivz7H79 zZ1K$Y;?x5S-*SRrF=Du{=KixBVABKmxe9EcRk*qqh)bXlSlGF0rB{J?%A4E3I z+J(3FimTqFQ#9Uw0OW1)y)w0&sytCCBOFHLp&n=J{oZz#lh$D5mQyy|ID#{+juhW$w$8r*uC>RM&>S=V3l(@^`B0CK7uz`F29h}lT69rBa*9F&adQ;(7)y_<^j6P2}k;u+xOW{)oYg7FLcCxnC%P>p#JF%}~AxiTM> z9bXdqzp@GcR9G<5u6PIbvh93no{c}a#Qx4YrNn|Qh!#^ zg0>OvnGI=10S3RNFeEax;f}|=G;@@s_WvlaT^(~K*dc1AG2G7n%%X&x_{Ff6M~dU| zQuSzFFGgALJgC$k0jDE!_2GDyG!-l**Rcq1J$V3K5?3<9bxxyxxwJZG zLtkuO$Sj1gzJ!b+5gg3@;o%eA>Aq>c`AO}Ph>@D-$gbe(+cPO3FoBD3`k9X3-1hBD zcX`AxPxr#JZgV5p5&FO)(kWtm*|?35O_d^i6ceG{v^e7h%6!ef+P9Nd8(h)XmaEMX z{_py%PE)Ta)z3El3`9t8uYzqII&V(q$)pY#J$W2ZDTP5I1od5>PUl+eatHTi%34CJ zSnPH@X`_0`RS%=9E7_rVTcpHkNnuFY;KO#-%_)N6nr-!ZGW4qh*9BN&;aj_>@%wmF z9b)tLqm{VppL1t*cJpyMc<-4(?j?3_xPJvNl4SnqNFK7zk*q`NNS3t1n*$2V{u_Y& z*UKNt0xBpo!QuqmUg1W|-X-X@BG9@bdv86vl^nbtZwE}5KdL!>RY5t6R8R*41e9ev zTcoNV^Z7c69wJ3CcDoxF>QTu#=J%*35hO{u;}@r;60aU4K)E_?4gKHj9{NtkE;sU3 z@11Z)V|k_Mj~C2RQINUPJq-juj9fXnF5q#`yL|=Dw}A(r*0#><{pCSt+7=_C_#YFg zoZ=_#LAL>p{l@NI@#)&%;{7v=NfO{e+A>=pPojKS<7$S(1HXz~>o;KX%b&&3g$6_t zrEF}>PS2ipZ;=au^lQ{R(c>Ja^`N?M$Q#i#kI05(-@0%>DE-t)H6f8D*)(8m-sHiJ z1NOSje`jBba5M0yr8pL<{&S9+Rq$D5@uYF#K=eV3?8@6w)N(h{80 z^(_&=Ai;~AAi;GEZlg#{3K#i{lI{|MAAKLZ*~-y~6KfHlQr*1rjeR)-zQVo#g7hkB zu(kT6APid5;@D}fY1?}xbIUwIVXz;S(Gm%waS_Cy@d^>wA}>0CrfOkM@-S8zFr<1% zTrpAtxyU8aBY#$6DUG?^jp#m#XflQDFTrko5Jc?J4!-S#QqA^MX%^rDIm5;%xbbyb z=T!?~>ri&-us6#5^`TCWwn5Pe4NvK=CU}4SSPZG;1OBi9<(y;COQnS)gT#=CfWeERaBS})vCS;W% zS&smikTucV?+YP*gbJvj%_O2f?dBjBwH5iScr*uIfvPfupfEifzk9#nWiYN?mk;F80*k?rcvE$5>_k=zXuhx<^1HiL5V@!F(i$nrYt0!5FIhz&FuX6i3q;whFS!LGh3zQ5g>KXu6g)zymvt~ zN~>3OfRmjO>Q2?{T*u@UdQnuPL$G?EcImpmS^+}N6OARK@8u{CN19C>{0`S<0TU_| zTh=(a9bMl%%Y*Jrdl!R*8d@brJ044rH-8IWAYRuKWk=uMz^;z~YD+00oUg z_=m0(MCBK>U#z14lTRSDhjlR2jgSU!MDgd(n(GvZW@w9d>}k;upLK^eXH?>T^?tZn z4nz`7y+19xmK}cy*=;nH9cF9*Z4OS2Q57**Qf?P-xeI;=&%VmKTv%e`<#pzhfiE@PV*@uDkK7F-LaFZL8K3 zTPwj0CK&oj21dv~r+G3vOn1}k`Z$`L%V|B)_O>x&R4E&Nek;j@zjlx$t=B(s6BD!| z(5$m;i0-Z?2TPmi6;wqJr>0k1<(f4lCqunMGBFrFd@x))BKy4P5%V`j^`OoqZlxT! zSQxzT4IUJo2tP1NPH-x|w7zbUZ7K6nWiii(i(C{t0iy62BLbmNKq&h3aK;_m4iVSUPm8 z1STa=nlCr1I#te`o6_q>n97#k!SwFnU@m>)6rjL~7Q&eEaPQ)1(tWs=L}l_S;~wV+ zk1=l^I0ov~AG4g~M*<6%CC6k~xb%q^7x*FiQu!i?9HZ&sC!f;yN{9BG&CyGot&sZUYkoU>QzObXw{D=4)HLX(h~P9)z~B>TMExzg3Yb7OUfG-W`tTTFJRc2 ztm`3ATRi~HfJuo3YTH)L=1F?Q7$XzIygZq%4v@`neK2Kji@8 zFX#8Pq*E+B{b{K)v~-1Ukff)i<;?x@vZXVwypr2oMlko<<`LgHCLH0a^TcjTrcs27 zx!hg{J>~O*uQL)SDHI(Zzt?aW9!Os}0gG$2BgieV?!hZej-ve_nma*GTRPnm&oMfT z|C)y?4K$@ko?vQZ^JIxAyOu!5L=7l@(9sdNQpuS7-mnkH@kz-}oBb88;XB;F0@d+_y z6sE`Pi@Sc_-k)j$-iivdkkyA3iV7+~Ze0v#z0jetaZf67a9f1c?NtcNh(zfR87f{W z%qElJGud+AaL%8YqXros9dxi0Wuxhd7Z`Sr5)`OB)+~w<-$l@@Oa!r*7Km*VVIpl z^m|$L@Q>`YmzEQIrU+zP0>-`MD zWcSO2zW%~HdT5i=eQ4S&Uk){ZFrSP5goiq<@L5Q7SquHMrc0Uqyyl^T%F{3_Q+t3znIQ|Br4oFZ!{ojY$J*MUUt@zCEpbBnBl_mR1c zdvbx_>EW%E&V{GBjzusJ9W_-}6vv0}8LJP~TT}EDU-9-GjosB~NObhAdQoO_v-z^$ zAeUu6)YB(+V;wx$pBL4iNRqrBcu^)@;LM-q)#l(CJGV7z-6n!q?k3PL$`JwgqJPP> zKBkX(g*Xg)sOH0i?dj*R;bkYa!L1(qSD5Q@6r{GF8N`Hs-kt>{e6<<#u5J4IICI0^ zJ)$~J=Z_@8aU0g1aS&xUhk0nV{z%S!9afWofnm>*K}-T(ytJMid0HSs&k`Q=I$SbV3{!61tQ-PN5ZZ3O|a$}q3C;(U!R9Hc;j(8C7L~{ zm!zU{yLo>JfLw3!unzNd9Y1mWGeyL+#YY8a-qomBiJVp3 zBTO=vP)ysSC8T*Po+Mz+4(B2#M6twZnDg$(auA)N*!MJM@FzS*U9aBWKjj=%SSa*( z5+%D{jBJq}(|RIbA5h>%9M~Is(TNjMOyo~^wH~V8pW)_Qm#NNnanW6ygI7Wv;Uj;w zJ8Qu90$A;vJ(-rdfS;`an)9>bTTwJQ$=8A*VEyg!O`qeohAk?0TDc#eIOF02+Eja1 zLvl{xw&is1y*|rS|Iti1Rtp1#XqnYLs-zKjwi%f(%#NmUKi5YJ@d7xDky0s*#qw;d zkAN=w>&iCY%pR%ixd&w&2pwZ)Gb&Gb7Co=p<=XINaZ!x}Tma4G#2hDFVPV4kpiDsQ zTWE#F0Y{M9dmJ6>DyCr^)|C7=`=!L+FZg!U$Mh^}@aMz^>t+H*oai%MouxMmbZP!4 z0Nf+_vf}#Ugnwf8+q=Cf!Y}1JkL9GL$h?9=CP~c(k?TD8CA~0meG}aHWb|R*w+s); zX=~~Zv2JCju5NF4s^4y+EL^OMY@{B_R&XcQE2)w&Neg@W^MX8VV~}mhi-{Lrti1#O ze8{UK#zJ0O%MX|=EhIk6vjcB!+|}W~7fscv`^l&Q?Fe2lxH25~E!+UY^(sd<_QAR8 zC&Y`nrmgMr4fS9%FAhWHlx|1>IqU}EDv4qEbE3cN;zfKiF;yhRwv8}32=Z;&^^t7CxydV~xwW%Izv@J)85YZ$#bNMt477-#U z;1SAA0X>~GzoO8>{aJzdXb5xR|5<=W+EXKzBJAU4O~@w6K=gef5`SrvbuGFSIl6@q zR*;$|OH^+!5M%~x^=_H_m1oYcHV=meZzd+nyvDgK0ar_kN-D z-kNn^A3v-%lKpWX*+6egA0IOtTaH4mzK*V_W;FtSi(5Mr9{nI9*KO6#zBTn#2X@k{ zx_{3^XPQ4p2j(^UqSNcKs58L{Yg*RhcoIg{mHFUQ3XRn{$w8_i`Ycyd7H$~K&i4%m zj?`1{ETJ5rP4s9d zsi{^I`US8Ks;Z*ap><%VwE5ePy%JABtop;|CEOo*KE?KMY?Jq?IEc+>xJ$r;{Jxds z_{^!#=~ka96tR<*%>Bv4^Joy#oE9F_eGjvg*q{OMk6>WNNq;5yxFU|<+CYfoVkOsAwPx5^*J?7^y zPNrt77sREMw{f;}7+*&rot55Ct8Ywo$)WD?_ZG?t$jcE#HwLGEyTjzq zBF7-ulZcYJX0T}44=veM$k;E>sJjZF9c}w*PvRSjduu!%-kfAy_^7Ox0^hz}Fv|Op z`#OMFJXVt_aoh9hiY-juBD9j1be{(Iw0k1$;QHcgZR{nM@jR%(XfHX)(lx|G2K^| z@TNdFLr=E-77jwywie@NqR5#0LJo?%+soB99}&BYuVf_zx%|u&M2hO?KNOzBIx#(= zPsuuN&B(37vDZIRyA{8G;A$3*CClbeBH;Oy+7^{VkM6ZctgjJFv9wJ>_vOA22m#!7 zuYz)p!wlww?fkV;>Um{AZjF+MBD4WIRGX)#J!~P%*c|FZcu_PAca=yqybL?kpJ%P2eswsAoMC?iwvl6PJsSonT{ZG;jw3HHTR%b zit$cvsvin5cjD1S_@rz>ANHmGWtod>;*RiUv8nTtNpLmP25VS`6B=dmtnRN8hhG|@ zq#bo5ToA+aj-Z-qDn%ZUGifC@+JDTur_Of#+0&HLNw!vd4K}V)Vmt z$Jf%wPHeLa>SUvHUgNOEB^crC}fz}x$R=bI~t^ET8 zGFcu4oTS_Rh-8EK2ZIgHh$pI_wqN|mh@*uyspEwzByz(Q^U!^Ro{F9bxQ_Unus%Q& zdGwE7P67)r`&KkZ*Q&|BTB_{o4g1|J^vPsFLxn3(M)o7kt3m$R44YL{Wbu9M{oRa{ z+P9Wui5FXZG>0d*N$IdeZXqQ7i66cV(otsJPGXWecxHzL%&ienB*P<*0})u)fy}s? zvDXNzJ&~r%wRcK*A^p>MSxWS1($Z*i2f@b}Lz0D#&B=&vEzIbJd#9Y6@jOH#_aAON-FLmcwjUkI z(;S&}Z^B-t8RxT1;ETIj+{)P3_b$4JTL#Y&lPr#2J<#yh-Xzu3*cTu8Jp3xtM*KVp zrTm2qsK=edqN!zC%jn2TO-sIrSYPe$h?@>(ePPZH0(}O(QviLo#!A-?66A+UgKeNdgmN}f34@v&vdE5owL$D_B% zA@Lz}^$1{j)aX8ZO+#Qkkn9GwD zGBP@1i)u}N60hha!j+);iPaFj(k5Vf?2ZM4OK!;V!m#C=d_^6Hbq!1gY= zDlj3M*k0J4(7WFuFQ~NA7iS~Q2@|#dViR&V7K*UccGUuDPN;f+sv}tu&PW0h2?TwlM@pynzWj!_aHlTarA*bFaQ0Ut2hnb>V&XeFbw*Kow<| zePsuzF!(eD-G;1Lp;zy6U-DyD2wMg-h>==uQdu~X`bclUxQWA=Gsrk>@}e{!j!e<* zd5%O3(>RE@BGjQEB})hJLv3go5NhXb$mkd4xmRX0QwCp{`ducoIaqT>Y`dhiF< z`M;uR@&t#T-3z@7E)yV8!ZTS%>~}BpI${hdQ5+t`@$1<5E#gt()F4h4Oo2ut#5tu;(ac zX1k!?*2c_}NzQ{%f0-aS&s=I+tRDJ#Oa8XqWvKkB9$hl46 z=ECB9AN7XEZ1s3N!9e+THAZZ)IS?p*(HBz&108{iRM&Q+UA(xwJcp#rgZ!=8K`K4k z_?WKn=A_F)GV1lG&qvFG(?ez5e^AiD)C%g_GTySfYowSJZl@`i&$`!GyOSj?vr~io z1Mf$F98>=gJyZ!pwDT-3$`3r4oS<^URS9tyRn|Gf#E|R%&T|~J|5ej9_34yrp|(C5 zJ30B5j}hCCN1I^F&Q%Z^-9~DeCTTj~w?F-9or^Wh=?B*-c$K18MtDhky$xBXzHDAc ze+hc?NKhCOEYItw=$*;sVSUEI{G}HQ_JcWO{phMN{e`R!zTcV48#Bw|JWuc9d~&)d z_fLiVJDc*SU)DC+2f}(QBOcZbOEM5y6sA`^74Ju)$KDc-*y{|PVvZ3qK8jsV(X(Eo zp3v*gNZz#G@haZNyNccv8ccoS5?rcIb)Df1P)roeaid*Mtg~ zV16Dx^q?Kbd+O;NS{{U>4Ucd}3LY!>>N{C!pSSf}r!)>)>*qqHwv_>9H|gsXDB~7W z*C<{XRqhDYL-4Xkk7j1bc;Qdy@b9)cwZq%@C+rGCuO5oxlU-I&uVWccZtvuE$7Rc8 zif6l*W9}rEYK$PFqB7`Thws3hf2p-PIL|wKSkKA+xs>eEtQv06Sief?TY`JkekqB+MpjjMJH9zAnXj>WY&-$?n{i^ob%AtfxY(K7mvVs&x_AopRh3&0L4YaFZzrCh8y+FFV{8 zuC{fL8k!cLCaPGriiwAj7t<>9ukxmAZfo_U-!yNHPjMH>dJnF$^s$xd;^eYKPxZu~ zbW}NLy(cN7DnZByp)D<1RT193YY(AT4{E7lqKA(&w<;ZP_ere?{s>&W{H(+k;@Vbwx?Vvc2UvM)&8}0 z*6?D9pdNlRl*iByCrEp^daX#SKc~`@O|RXPoi9y(}}&G85%T7<4!)t5}n|+is|7Y zomi2zIHWumX6GMnb7zv^{SZdXV-R$ZGs2mn8PdqHvy}ZhMZA!rV8snjnjYrlT$)ss3yR*S2Yk>D!2>z=VPNRD#^uILCcaF+GX~sVLWXR$u1;ejx6ngF=hFz+Y5|k#HIb&r*KyJ@jI?d zCJdXzMi>K4Pk9@r`$`{$hJa8yawj84JgDj;+U_8M^kg}X9{oNNtna1bV|9e$*OMzNLg49%Ox71E(;Fdex%@$325&=QuxsAG-)mC;j5Oja3&oY%%$W5p%*m zZVN+~MXa&xMpTx=VBLXXR7(0QmRv2Qd8NDen>MMmp3*R6GW)mkSkNT56f1Nc@l)YD zMQ$UssSGg>jwwYCmvf^iU^*-b1yCM8eNYNfzx)5`>?@$+T9&mFLV^Vd9^Bm$+zG*D zaM$1rFc91!5L^a#clW_9!JXg^!QI{e;oSHBciy|_%DSv!t z!5k3*v+@Vh^2P-ncmQ~;iNpMN+IPNOQ0wAPoQ3~;{i_gaGLA#f6R7tu7{6fY3Ha|? z00ZFV1KQ1veh`GX z7uJwI?W&c}(pKss7tcQWbo&%=c`#5~;f0TMSeH}17zXD(y+gZ^K& z;avDM_FefZiSeVinS+HBzGs54roK*;8JkQnwW4mFc$oDMV+L3-&5eikyoFQH>ut15 zsyBOsrB2pUF+^Pq>@w6UfmcRh&)jd-u$K|R#RxIM(2DT6gf}MK)5~2_*eF)x&V`=B z6))+A7Ws)!A8>ItpzgbA%arBGW;|-&A3Y~jNgd=G$q|3e1HQDTp?74f2&AKq=wJ(GeM4o;sne7Hf1ah6YkWF#* zJ~&~8Q|HN($ns9KKzuk_O;Gv;lIp*3U?q&7D3qZhEe=)>tGnNaa?Lx7*~{jqIqVgb z=wj`RZ=U3&GsgnMKo%(>*A9v_hY87;;jgb{zhv)6vYcEsDr#dzZ;jEj>K z$R1RUWkUUN8n{93+vO+mqu+&2y!sm|5^e)hSCX$va#flp&E7sRg;YU=0C^NAJ?4_uOFWrARMbB^TD_1s5$Tc40pR0CEe30U9z4rW5iXPej>8 z90-O?vI&N|jnq<1x#nso)JDP6yI4)ayrW=B$JKY)gsqyN1RSkEWu%a@O$D-Gd6G%mlheSgI~Qy$WPI7z z>82q9mbpnSyak(q`!x8Abu=AwkV`*f$PEC|A2MR@XEj%7GM4MbqU2+ zBdw4&fs{AMy=w*X)CGqlgQEDar1C1i(o<)dNtCrg6b~LX%`cp{MHY#QAf4d^9>59t zRo?dZ!WQ?w1XE*Qd&e>Vv|xi zc&J#~94Wy}y`*v(e&$b*kfQypND1&#yRR}NKpATukh`RLbNgBr7;AUx$6r-=eDB`B zdRN5$J2P_`4;V;7=*O<`uqgcCg2LRIa3t5t+&R;7g{opNgD$;$kTDZ2(qgX<$T8QY zd(W4GID+j#|EVT+junykU<55F59JV}p|eYM;tXN=yWjUW3P0m*ol)RtzyQCs&C%nWkrX^$s8>aFPvn|M1VkI`D3bk28qn79%9EwNyA;{K7TR4i3 z8XALnv3!r2Y%D=$!M3e4&`M6wXp-c;N%!+XAiv9?^-`UmB733B$mR1gB9m191?jJ? z-amWfIpI)#OJB7>Y!`c~m^y}@atEPzD!eq*-1r>i84t+ZS%&xE);Xk78HpXM70!F* z#Q|tAebZOCE{N?07iya6_gG^QiI0SFXsGWK`_XImJ}yz&J#JS5*K$UBAZ^ijR;2OU z`Zfx-mjudo48YKf>w7R)Fu00ftM|2>L?lup)C_LQ_az@LkaehHHD9!z{?)BUsUWMI zgQtLq#B-?hnoxAjWPBz>24|##vd6+~sK}Owfp=Dnn{jG9>269XM+6m1E&-4|5})e8 z-S&kXxNKc#3rq+LKfojPaL+n`B)fbTUBgA)_!&Q2>yW!ps=yu|X0 zi|87N+x%cg*;V+=)dy+zdO*Ae$Xt6VKfz>#0K~12-*cUAZdJ~x>V|gHGicaz z9>`C-Vv4<4QRdPb)4z-uUb%QXzRsH;rALSt1Sw#d<qOg zsf`_=^>J^;DO#7hKak}^`Wue@9`&Pvr}EhKa}2WWNpm<-8rLSn7nPmw-MuQm_2D%& z-2pFCqf6bSpLh9LLiCX4u-9#juLxu14r6-&`dpR4o3LeW1= zKbo+EJo(8KRQrMT)O~y%B$*KB(|T#z~%(Dx&Sp zQm-D29=+&E&_>0(ei@AO>tNu|{ZZ2VE2DYE>T#z&k)(%Gm{OJ%oqR~JAzgkvXu=kW z!*Y#=P-SX#br1X3w)>rcK4laKOhB!|j@`9U&buqkm=pW2d}#Mk-HL3Qx07+LyIJ9Fw>Tbr@G0>A~0+@r#vYs3O}lmY`8t%oIk)5qix z*JUo=nBveI{PV%^)C$l|;g#}bZnOq0Ha100aJt6pfSPtHQws4=no7W;dx8J1oUPzy z*~%L8-qr<*3LWJGrM7`P+;$+)YMdumY1n2;)=-XL98t?!6mcN0Z=sCzr6S3`v-O+_ zwK?mE&3Y{KggvW*5Q1N@Bz?8w6l*hDQY|&77sV-KbX(V-sXfW`@^5&0BZbZJ+uMH- zJrsOc)=ffpHe`)e_4Q+5C`s&V$79VkkVC%+#-6(7%9^lb&x(O9I?Tno$8u1bkWlVC z>zjeyj8+93sCx0SZMxpw_Kl2A?qh4Pt@IHBLaaXcQE5W((x9bEQjEI$#?OjYKYAu} zcRLx{j4h(sM4eqzZRLO+s-jCIREDy)8S`j(#3*oc%jr4nJcw4edGmfmihf2?r!bPs zO(ef42^QJi=>l$bO3}|BSvC2Sr^ZT04xgL)P4MYeG4^Zck8roEnl71uF!KIM6=oX2%_uFH_RquMwV2*Pm(NO#$Jt6b%WDWx=GF1=^#JN(%C-9}uhlEu+D-weCt0 zM=`A7HzDfp4EDCHV%qhHy}o77`;xbaq=;$(S;eyo*t2s*M2SZMZ{_(zNZ)SVAI`3u zQm@D-7Ad7(e|9@*y6b$7<)rq2M zN{HS78V83K8b{U4sIzYGC|6&tataZlAN;7p>8aWsPJ-USG=a2CKH>Zvtht#6kh`hK zKTd*oJ`c<@REc?p>^Y#2#d(P}Ztn>8{}@ zs*l08DqKK6W<*x#s?wPrA_Dt5aVk$r?`Rl}^3WbklPT5@HCIgGOk*p@1herN9Oq(A zLg-j;zpcI)$yQz|=p$h4UwX}RyE}1?!wU5V`{2n3-?|*c^@lJkbBUC)_vVI=o^(QX6xIFnz)`13_< z32?(?peyv3@nJJeKQb~{98RX+bDs|8f~70BD7Wl?`V%tfvXkG>ijpWEC6^#2o;bCS zZa{7^b?O5Bq$<PS{wP`5(QKuJO~{ zi;?_2eDW(10qQ%>P4P~4vg6X1NJ_{XUU*~Ec^SQ)O!ypoY(wl-+LG}@&PDI{ldU@n zOv10%Cxp@vGnjk7yGk`I`48ye_9_WWXZ{|uo+&Bmuln3Aw0a2}%mUybG#!z?AuDkQ za1K!kg{vM*x0(d2X?R`hkMhlT86bM8Lb`i>cTSYRVByTK?r9z1k#0B=j1l@DC_}lm zC_{ZUxwq^9=GahN!0gWqOdz$4kch{LbHQbuR>AN-=V|;gR?mbpXrlddAy%9`-O44O z24H|_-ryoS!jEV-UhmUuPr;4NyF#xcXS$Cy%=I;-@6B@KHVy4pjlRKnzo>kVx zdR0wRJ*Qk+=O8z)+{c#_LPK^HCXuu`e)g)e=zEyx??f1JMsMI}D649YaNZyXn zbl2;p`|{?&rFob-7UF8}z&5w~cFNv15o^FUdjwK_KP*fER>)%Fg3Q+ps)qRitB*QphB}dpX zaRQJfX4XMM>Qz;TVIdY@PXdXpqtBY@nKLKW29m$dY$-VFV~Qrx8O8lmb&VCDFw%KxDuVJ)dmtp{&-N4Cd|j(0UU*pY6{T0wqiEW zdB`42XMSEgLCKF2rN|T(vFZtTbR7;`4EX$piie59);bWK;K-o^7ROSFW4h3ol2g_9 zdPNV)MH&_%X;>aK0jz~5(Lqz{`&mw1IrC!IX3Hsvx@{k6*T~N-0Gbf>b@N0=J>J0j3Ylr<0Bk6ujpH3U&#`z@)|QRU$|?F77$05T5PLPt|>kXvb-reLT}jyqMOEK~pZZ9__WGN^iR(0sh} zu91n%f>|F>azbx>4~+>lfzLLJ#=3iI1>&yN+BTwVcZIQ`|l8tC&2+7e9Y)?%3) zKVbMx|IJ#VUCUNYmOKzqZPSu1d@r|+w3C-gp|?ON@Cr~ zA3HO~#)Gow$n!o?IBKqiDz{C&O6K;_1YN_#N~UOA$~GlXhZe8q7kdHOOT8E|aiL)8 zSTk{0T~;IQs?b4-CNVw+Au6SoS7ZZTLxg$+|JiUKhmWa)l?~g#X3ptb91Hi#vXBwp z7`C7jVf>NBP~$k4et#`3VVu4za63hcDa)0AFWF=L?{?iVzzo}TF}!pQL(^^JFeU<& zqsK$(ZRE+Cj0NVjI_=GGX8llZ*Hqh01=y|3VlM<`ZbQ7X9gQOa0Z7ke357%lHQC82obA}^NJ8*Bi^Hb#ZaK8DUHTkTmRZ}5uD47*Uk zWbZC$Jt!-!e@G;`fP%2S`$~}+A;w*ZMJVEQiY$&ZL1ob)r)>Txv-4^Fe?-zwX;IE= z5mHg|ngNrpO^w!&ZJ8aMDTeIRI&GerJqBaXTke2|+XpE2TQ@mz8zf97pz^_h4nRPF z&65WeQp#?pZyZXEHgPDq4*g2pICAf^CRFgGW7ken(m!)dKAOCSx@hjg(l9|12Z3`F zM7D2G=A~K;W2|)#V^q0u!ii03!Y>rAR!-%ZAYhV z7kkxYkW9i&$PVM;UTr`OEW(;PP3Q_erCM|#-xK{FGzporx6sb$aCYhe(hUIND1KDr zHe)noZfWgup1TWtKEJ&1URGAs`B9!-$Bqs(H*DyMk%=P*?6!?02iLO(MSKQCYw(|< z0%!Q}G>hL(*fCuWZb?Tfw{#;Zy(HrQrj6EXs(3ZGddUr{C z6=1(CV(Fw`-c4m&+QfJ^D{<~|!x^Nj=hQ%o1^?|+KJ~9|=$hD)+C3zX=TP#o+^&UV ziyA7foL8O0g01|{PiV=y6Sy~Zx}QNgwZdBS7)OE=*dMo?Z(5a=>Sv@~l8ZnGn=aXF zP=4t4_kjT13Mh+Z)HDM2pJucCkyY6E4$7h)n@`XI7)5jF1DfE?R%<*m{C1bivgaB# zi`?=fHTQiHIfjc)i7O7CzASuBCe{?HF^LJ+ea-fW?-a%)rJALs zmuokzD<6O8BQ#egO3@pLev>~_;x69W@5zz)S=n6pzT#Gl%_$OObq-$y%CY&LD zJ{+Huvk(}Hcm-XxEiJr0hADN^Yr&bZ=Hi>~$ZO{F#oF~>zo+e)Q|!j+JJI1DZYRgF z`@V39nV*JG6JT6&=C63fwZRJw!gQ_mQ1xA?9)+pSozAcn3DC|TWP0Abj&W1vxVR6E zZ`RNy+H%Ld9#Ey@%+4?~rhB%jb=E()qKKP@kWUo2JAM@RKtztQ>V97g<+W%kG-_aB zI*gD#xxAjBZlb<8w{7Wqzswo3+drjfY!pl ztn?)BOH)GuxO)-ttJCVvvfk=W0x&$q2?!cxo)bj(Xxf+*NL&Cc4AD+lQ$W+euv z64pK=9wO_j-rM~2Yr#vd9dR(%*ySqt)Co=M`%(Cb|E!k}5S4}qa7_fM+0 z{c$Tr5$Ztpg>D{}_#``GOxXuUQ0eNy*FrIQLWr>`;M!s<6A8NcE5cG+LmAq1?U97d zH-=`9>t>mflef8$7Sj8n^92RSS48m)NoQbYRe+i%Oe%B$M;Wtch1gbdW9f)=tVDmE z=x~8e!kBY5`Js^x`Y=UkWOA%Mxwjl>K{w5unX12~v#a$PDL?#IR)&Peab8k+eD?y! zvhA1Bxn6AxCeZ*je(1mY+bxAmo7UF4s?7_Lv-z_NL&}H=1`4?p**)mT=OC_UigUNB>dljjBOaDfhQ!57%_-x_hYY(OYYSF%YwCtk zeZ~F*mH2In-6IS%K@NLRKG)4&sj^)sW}A)4lyhX#qe0U2tr#xjlY{!N&UWtxCz&st zE_YoZ&3yZQZpW_po}L25*b`CN0lSWDKF((1#`a{v;4RX8ZZQC}FT3o;#KBi9RQ{TW zR>dPC?Z<;kZn%0tT(=npWxDhIOpN-2P9S33=?v(iLO_(wu=_otG*zq=EQ;!{F}=i5 zopr}|DCde#(4D58$c3rzjw<{+K@k0A))E|%C$@&!8H0gSivcTjZ>tf(BFmKSwVGCI zO8?T^aB15%ZVgds;$^E7`ZT_DvA)sueMGQ}3}MIq7J^M>lYPJXRCdJXvH%#x+AWGB zVYNWuo`6-@4a}`8DeYCos!fadkzME?U#i`vD#==0c~up)h1wNGY*Ory0oq@ z#0cbH?#XK$Iww1JY4U~>L(v%gCRD$YPQn}=p#0?tl6PC2)d-|h^}sZoy@^4&16C-f5=!cs@b%)H6(lb>V_EWo9Hgq6x<8#< z&f>i9cuzLfo6Y?XQXu|Z@h)QzW19||R!JulG}*x;?V(6l(kJmT41n~Yw}#T_17~h+RZvI*v z(V6f5wF9xvN1L}BxW+{{nC@;&0C@3M1z#pI9PlqzuPK_1fjx7bRqm9c;SV|70>v&} z82zxotzF8<@(uAI5yk6}U-Za?4zPkwdwVIvY`+`3B>yQKb_&ANxw*-XE+=xG-(hqA}cZqeVaW*Qe?QxOX zWFlYq5oThv=&+Om_G(LW0Od96VN}abQ$lvad*Zhq*}UCFDJtD3DJHQe(&%sULen+! zF-x4v8q(>)eOaqIC843jJQt~!HF)xcJe4t^>|{ST$ej&TH6_&+LAd-1;<2GfPY37q zJ-PdsKnZg#Pr;Xt%x;LPxS0$8@&Iis>lm23w0LUPtus9ztS(|JYLquyw2l!@yoFWV zR_yb}BjqhVp)PljD3)7PK|G!9Zyyha$AsJ2w{2u41r)yGWn8#G(6y}AMX=Jcl_7A z#1J0;*nVm{W|Km?qnQJPJSW}xaAI>@%p>lR4ZAWBzVv1n z9*&}|^;hoxdXi<%IArsdgV{XuGNpmwtI#irfyht?Qz_(AD0Gj2HD2hvL&cDG4!a^I zywFFhCOv*67s<+A20C{FxMlB;6EHZy@y}NJ+H&poPiz;^|MXAYKgUDc z;u6E;(iNpwvqnY06(FT+G!Y2n7F@S2;yJG>KcK|8w%B~__z-A*J#dP(8Nb1uH&`%_ z?Vk+|QahM?XcnxV#46jdL>XiA4h+V2e*P)E|D);S>W@9ln!HD+J+lr0Zbb0@+u;Rv zrnD6FB*Dogm->q^L@6TXCwFWul36!F7rr25)B&`X7xh1Wy3f8kEQgAQ7<)&JwDQ%3t zsI!b{-U`iX_(-N)AbU>drIRuG6pU-XCeJALikDKbPqwe8U8kKR%!cWc)@(x?PZnV% z8g`)vv#Ra|Z(0`eLfYo))81OUUT%@48jAPNY=`)wv5 zO+M=Gd#&F&p`qN479HbvuylU?rU=PPl+%8=VR6Du-I!sST8evx(B)onEH5}+L6&}U zznJ2%f8y#Moo+C)Q|l*>=9M!pAxf|}*C&^bhEllsx|-EbOx)D@Ic>f!G$_Ape9^4N z>2@fZL?infoZH_SyDQxJx~AK8w;*nJ&r?Z^7JkNh%W;q!YvH7&kQ4@}pZu>odrtup$Qq}kLw-+~hzb)9eU56UdTYDPmdu?;8{=om^Y);Wa z_v}{%G~1KZ)Nde0&7HV>{f>)eu<#(F$hD9xAmZg~hKZCf_%FkbZhE*8Q`xQO;lIO# zDc|(eB^Y9FpweYF>qbgV+MLG$OwO?b1j>WMuU$(SF-MWpnHo))1e+wT8dY+5#1uHe zza8QUeoFHbTcrKkVs;>aAhL3-OSrYBJYt%ezZK8k5ubj#rV5TD0e;qP9DGM6FG`iy7(B`H8irc`7{{YQPm0OIICFnd7ynH%Bc*W|=Zerc>?`da#aD|xlkPLS5 zc5TvKqM6-TdlJoPu*N)!IuwWzwr~e9I{lp-{YDOb36`&iw)V+@lm=W`);Y;JjSmkn4i*B4w3<%oKMCyrbT} zrPMAL_(PRBOeAU5JtTiHU!h_1%c#WOp`JL}jSe<)GRt>=^(|q4j>GZ{2WIJZo}0ZH z+Fj{qY*)b))W|h|XU^tw@7j4rdx8WEbO3xT@ zId-den1^k5kN$?fHcwWayxWR$6)}XK8jvpHS;*+ipFBfk!N>l>92A%3x?>llfcX@S zLj+f&CAzd6wQ`zI-cWK7a^DuGzaGrH%utTn)fy`jn;<` zPR-2jLwt74YoJ~o4hPP0Gn-Iaye!AquwJ}^@psDDEC%fSVfL=VRkFG>*bx90!D0y& z!{^X6>(IeaFKAS@>T3~?ElKkRn}AqQV4_4HyAsg%)O}h?MT=w9aYsWOhp#7jz>hX| zFMe$J&6(9#>=O|cpCdAM0~P#qW#gWtaYb{<6*OQwe-K-m6!S|ELJU|B&sxmHdAc(v?Kwb78!uuktu`%$rS$ zsi2A$VTU<=^7tCj#-~T+;i5}$A>ZaMcyZxUcpo8s-5SMNLKn;DZx1q=T4Mul9iAdy zuj=U$$058H6!nhop&{WF){&4${&ur3>9Ti6Rx6N0U`!zuol$`9%V<*-34VnB78{Shpiab+z_6_& zIGBh;X7`Z%$;Bn6E492K6O701rsAz!fZ`hS(q>{FN{##?nDlk;Vtva>rOB8wwxw(l zTE>c}V{Ikvgow}z%q1CMi~L|QUAGWJU1qgZ=dJoAiyjd4eX+Vg&)N#v3Va0?zp9L) zT^O-rjJIngiJntd&PePh(ktcp8PZ{c^8girfJwVPt~h9nolO0Aqbpo!_6-KP0oL8) zWcYo9M<2dr?rqy7(2yKyk1If-3p>O>+nJgRoa`G!aD0(KG@bUz*hnO9FtNINM) zf-&&yrW?7o6C62N zgrQU(pGB?g_{~>XkXzA7G*%v!ZHbjhRmFtRF1F@iTc7Q^ zC3i*aYk?%g?=F=!CPKrU0rCd}1P(vAHggpSA~V&4VMtKmlIegKbE!$aef=V{fmlLh zlpx%ad_cH$1`lt5RTtvY&QdznqGL8GU!`p7dI4OxbxqcXP6K?YqY0Ezy$oud&W^;1 z19kCaU6s@%1}#Wf$-O?C#pyfjcC!#bjJG^uL+Rg4bi+M$qP`K%jD)HuT~UV>``Qa9 z6y}-r^UYak!=(cI=#Q77+|K;^iTZ~kv&(UBO41S6Eir~`#GBEU*sdKZy|MyH1ftxEE9{9%K=mAp)&s-7(q3sN)=m*sm?d*l%E>Q(2C9{_B~K;YRsSASo!FK zKbEcsIkH(%VBkg;nFi%7QQ2Gyeb?HC6cMun&__eZPUl0tFUnEz+g!u^bB?pMw-#LH z%A(NUi58obgBwYAxBGak(G|7gjLsq}=U}paBMY>2xL^ZYW8t6H@r}<`k$+m+~@}SGSc(zrl zXjjXI;R;CY%$H|sc9>IfO2H@m(DP6_y2MREiVpO~?5KMZau-pY&jH@#;3UiAuniK7 zFE;!JJ%!iAzD@e}M$yGHXn6TUk4h5-x2Nx3DtJp9qcZxtG2J0@KKBpEPo`C+ZEbrk z3eM@mE5HPo8LscM4_PKfLfMuGg$xa@pnF&X+b^6~;XH7K(ETetQ6vuv#|wpA5t|4q z-KjL2;^%J(h?E4KGyl7UFuc2|VTzOBRKG+6y<}hZ#)Pgip97DwC$}uH!*Ei@8IF0+>NVvzto6ojTE~O%3+0IXkN_l zX>h{9Z+#~6ZgBRhc36IjB;8z8>V}15%;=Qb-u`Q~1>)d0c3$uI!?6o1gl`(fITZ}K zb^)X8XTZUmqG-EL?MHL2y6?2AwCnINYlHAGDFqk59W`%?iz<+b=vqy%!*~Q6554ou z=Ndtrlik~JO9GyF9JX(B`#pY)VHD!(0M;Sv9 z{lS?C430Cm*XYI8T}5q8r=O>S1XQ~{N`~{ogD__sy6iV5$$OW1rC2cge_V62&MC75 zYT^|Ek6Nb-3vc*Q;4f$&N2EP&H-AyaqpmbM(;h=%$A_97iE`elBCxpM^w;IeTmP@- zx_xA^@u7z}XFJ)e5h|9VY`Sj_YX_+DhXdcxFfXC{Dn;QKw!5Ujl74AS$XNHT>`kU&4UyjZQiVxn4=ev8z z_9YjuZZWTz!#P84)9grNwG~7>u2mxmgK7MKkR)Dyo!>MXOvU1Jnj19an~Dof5g}*d zAxIQH@6`!9HuQCvPlLi&ew#}S;1o8s;1r|ttWV^iWo;o9WDeVO-3MoeR4Dn{IwzJd z-%qjAteRqva?X{q&Y|EfG2r@yq2Hn)tBR5LU~9hBkL^&fr>mY*eX!2I$Co@aa(=wd z*91VUe<75;l;w7!t*B}xm~LwGm@V=sUN?qb&3qROd@NC@U0se7b}L*J{g|K7FkpeY zp~Di|9m;5fS<{(LozgAT(0p8rJ=w)XmNBH#ooPap-0!G7_K`6w)ut*r{*(#tv!R%s zhh<)-vt0v=Kqm{yt}}L6qF{XR`JG_m*1#7={)U{;&rag|CzPH|zM%k<`--CZ%`NR3 zYcBq+;41S0Zo1{<%%&l$=h&V6Ts@9BaWf;j$FCxK>w07QGT@zd{0ys)CGj&5+W5{} z`QC&h&Efb__z=taiIj{38dP4qOFthxv9*?2y>dfb2KHe)_&-xddl~&f{~}=oYUFY` zK=;zMg{efcFO}6S7?#rN>T5J+mBq%v;gqVL5t>POJMZtZ(|-;JQ+M8$cuwTUA2w_o z8AZTAO9$`~Ay%OlPg|@R19gd@rk1}LqH`5ZvSCWfm#Ya+k2@t*vMw9lpP!J}ISBJe zw$_l}a0w1m2b|f^%(0QG?EN?qD>Bs=hhlVyt;9L3^+W>sjl5Wc4rc3)X2`BI^Y}T2 z`w7WI7m^S{#nHGSC@;9i9=bsW{O&U;vgQ#>)1BRa z>FHx###*0#rH_xU;bZ9rS63))houjw<7+%A+be7vu$X7on7?`b>ZNeR#))h8YhcpP zpV54IgvM7^k*eC${t^xGwNUi)o3KZYkZyoS|92jZ3x4j>EiX3Hg9k(_}q5 zGy!-3{kH@R)}CGtIfFWSQPaXedA@?8FImeH?=(XtnT-4uOp;rVZvi~UE&Gh10|G46 z*y@OzMn;qWu$?>5=EjdTC-NE*ttj6C)heU=D;v?B1YbUr^aR1*VXq_zFsaASNr#dU zP9~@``9FT&UtW95%DiaDy9%2gC5uy!bIj2x^J6EZwA?AMHDt$r&h7g4O^8HYT#jj0 zgdl(tV!tPjVX`RlT46Qdg-UFB_JOq~ZC|utFw|h;DDT9B&4P!;uN{xNP>EdgkTyF! zM;kRLd4beCRhFH!DWUkpX*!xC)Y|)()bCGP2=;$a!yz@5Hvh)q;PzHfZV1JaCn2p- zkTFPnc3nz+9BnlYOv9?W_M7WDLOFw0K&vNWWB1 z+sw8*b)&qX#T`ia?iV~nu`7F^aMRV*kQE3`#rTN zPQ~MD0U%uIy5eyo>Uf7~pKB7*q+nd5?mxl9x!A`^@azrE`BQ%1$ zj+~Z(F%f-x!JB+~c8AfZ#xwWA`0wN2@Gyyw(3B*+bESW!a?m}B9RXTEH*Cpg2Qy*Y zc<+u-Uz(>s6k32$+CHkxcF-SMpUI>_{U6os``fc~0-!lfJ1e1ze=&G}lCwq1Y#Qi^uOzPCK*l_6f*@Dqr0~WK(uyhpXnR8Kl*tQ7Wa?Xgl`b?-Yb< zU{C$?7KdTYAFoJW`#j~99HwWEH>Pf;yf^*pQgZ+Mt2e@WhYQ{$XbRrrxbWvIt!xb+ zu{oHdW=goN*#4h`DVn>)v$lX>)I8Bz7OVe9_6bK7tO;Lfr3(HSkxPr=Fwz_XGb|gP&S{Tziq- zJ$9YRz4WvIv}DWvxo`jLqdzL)bCy+E1&*AyM*L5f10R{aTp1(I`-AF<%vF!LlbNS1 zD=WsxtHs6Enf>wpx*4vNPq(G))J@SVhpEf~TGVwYoC_3x{n6*{dVfaiX9fm=V3l5BH8I zcliNaO&&Z8+zp05H(k9b@-Y5#P@d9R`@c(`PZ?f=9 z>GyxlB|mvMU9quuZZ4+}#NqM!ZHtLzmHN0{WG-cKuG2DVqtj9=ZY%j;KS}_`OS_dw z_YI>G_{9r27D*8y<<>`IXNMc}`s+R0>*Etaum6#|zv~8A?F;9=f3;SA$HVwt$C}&n zTfNjJ-lh1Pt-dD4fPF_5?3T?V{8nSfq-jI3tFEN90qPo!8V>}==F8rM%?9ef?9=}e z^}l;0dE(^b*1VB7O%vy z(6L(^UBJja_kY&3cEG0{7)jv6wJbZo1@<3}5AHxG-B2T!&2aCQ(rEb~i|Id^&oZqH z`yive+Z6Ggd+nt$mz@*~y^>j1p*%J(gsH2)R+WD~GTzBl^34)e^H?pPfsdNbBPF_a zNjMgo*lJR)bwxVgWlSlnmBQ)&#gzZO5J2A{A^T;ql0#uyJhyNcH#lTmnkv4f%sd5Q zNRBy&g6gQ{MpLbx%YVIu{jrMvWvhSao962*X;NuBsat3lU29M7q7p5*8>)L#in@~G zUdKc&nSmfyD5~?EBPWUfqNTqa>x$SgL$Ka!v&myN@h*s!jK7>bcdZ*wP8NN_+*_D zpbkgS`BhP3>pgbj`2C3hi{a85>wh3l$1X_gar~P+qqk-{{oxbh=H1O^I!P@@bL81< zP7ctCv7s1SE~aX6K5C9yP~MaJ$LsPx)`vjE7={=Tb8_}^(}BsYVI@@v)8tVTbS2y> zGiG9%62Vs9{GOLi{?L%L;Bw@W>oV^8pQ)UxcMWBPi(?swlfclxTX3N;m2eKZ|vG`jixBqIfe~u z4oH|a~Nml`nx|))j zYO`*L)qwzy1tWPXqw#}9B~@KuRC`?6e|<0AVl7_$JG(7l_gGDh7wzu-rS&_2OUwr-_UIMN_ literal 0 HcmV?d00001 From d576eefd1bf3d9b4716c724a44e1f5c10bb2077d Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Thu, 20 Dec 2018 15:53:32 +0100 Subject: [PATCH 470/705] fixed doc --- uzsu/README.md | 2 +- uzsu/plugin.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/uzsu/README.md b/uzsu/README.md index 63bf4f8d9..d7e4df54e 100755 --- a/uzsu/README.md +++ b/uzsu/README.md @@ -99,7 +99,7 @@ Interpolation is a separate dict within the uzsu dict-entry with the following k * __interval__: integer, sets the time span in seconds between the automatic triggers based on the interpolation calculation -* __initage__: integer, sets the amount of seconds the plugin should go back in time at startup to find the last UZSU item and triggers that right on startup of the plugin. This is useless if interpolation is active as the interpolated time will get set on init anyhow. +* __initage__: integer, sets the amount of minutes the plugin should go back in time at startup to find the last UZSU item and triggers that right on startup of the plugin. This is useless if interpolation is active as the interpolated time will get set on init anyhow. * __itemtype__: the type of the item that should be changed by the UZSU. This is set automatically on init and should not be touched. diff --git a/uzsu/plugin.yaml b/uzsu/plugin.yaml index 36fdcaaea..a8d97bbde 100755 --- a/uzsu/plugin.yaml +++ b/uzsu/plugin.yaml @@ -70,5 +70,5 @@ plugin_functions: type: int default: 0 description: - de: "Maximales Alter eines UZSU Eintrags in Sekunden, um beim Plugin-Start versäumte Einträge nachzuholen." - en: "maximum age of an uzsu entry in seconds to be catched up at the plugin start" + de: "Maximales Alter eines UZSU Eintrags in Minuten, um beim Plugin-Start versäumte Einträge nachzuholen." + en: "maximum age of an uzsu entry in minutes to be catched up at the plugin start" From 04f034032f895d05c54b2b1418842d6c463a6787 Mon Sep 17 00:00:00 2001 From: Foxi352 Date: Thu, 20 Dec 2018 17:00:33 +0100 Subject: [PATCH 471/705] pushover: Converted to new network lib. Added attachment parameter for messages --- pushover/README.md | 13 +- pushover/__init__.py | 50 ++++---- pushover/_pv_1_3_1/README.md | 76 ++++++++++++ pushover/_pv_1_3_1/__init__.py | 142 ++++++++++++++++++++++ pushover/_pv_1_3_1/plugin.yaml | 40 ++++++ pushover/{ => _pv_1_3_1}/requirements.txt | 0 pushover/plugin.yaml | 14 ++- 7 files changed, 302 insertions(+), 33 deletions(-) create mode 100644 pushover/_pv_1_3_1/README.md create mode 100755 pushover/_pv_1_3_1/__init__.py create mode 100755 pushover/_pv_1_3_1/plugin.yaml rename pushover/{ => _pv_1_3_1}/requirements.txt (100%) diff --git a/pushover/README.md b/pushover/README.md index 1e718fd6d..678c2feb1 100644 --- a/pushover/README.md +++ b/pushover/README.md @@ -4,14 +4,14 @@ Pushover is one out of many push services, which is compatible with Android, IOS ## Requirements -### Python libraries -* requests - [install instructions](http://docs.python-requests.org/en/latest/user/install/#install "http://docs.python-requests.org/en/latest/user/install/#install") - -### Other * Pushover API-KEY - get it from [__here__](https://pushover.net/apps/ "https://pushover.net/apps/") for free, after registration. --- ## Changelog +__2018-10-04__: + +* Use new lib.network +* Added possibility to attach images __2017-08-13__: @@ -55,6 +55,7 @@ Send a message to your device. * __device__: defines and/or override the globally defined name of the receiving device * __userKey__: defines and/or override the globally defined user-key of the receiving user * __apiKey__: defines and/or override the globally defined api-key of the sending application +* __attachment__: adds a path/filename of a file (mostly images) to attach to the push message All params can set to None (only message not), so they will not be set or in case of device, userKey and apiKey the global vars will be used. @@ -73,4 +74,8 @@ sh.po("Warning", "Your door is not locked!", 1) # send simple message to device with id: e6653 sh.po("Simple Test", "This is my test message", None, None, None, None, None, None, "e6653") +# send a message with an attached image (camera snapshot for example) +sh.po(title="Simple Test", message="This is my test message", attachment="/tmp/snapshot.jpg") + + ``` diff --git a/pushover/__init__.py b/pushover/__init__.py index 49c3cabde..942f529d6 100755 --- a/pushover/__init__.py +++ b/pushover/__init__.py @@ -21,26 +21,27 @@ # along with SmartHomeNG If not, see . ######################################################################### -import logging -from lib.model.smartplugin import SmartPlugin +from lib.model.smartplugin import * +from lib.network import Http import time import json -import requests + class Pushover(SmartPlugin): - ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.3.1.0" + PLUGIN_VERSION = "1.6.1.0" _url = "https://api.pushover.net/1/messages.json" - def __init__(self, sh, apiKey=None, userKey=None, device=None): - self._sh = sh - self.logger = logging.getLogger(__name__) - self._apiKey = apiKey - self._userKey = userKey - self._device = device + def __init__(self, sh, *args, **kwargs): + from bin.smarthome import VERSION + if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': + self.logger = logging.getLogger(__name__) + self._apiKey = self.get_parameter_value('apiKey') + self._userKey = self.get_parameter_value('userKey') + self._device = self.get_parameter_value('device') + self._po = Http() def run(self): pass @@ -48,16 +49,15 @@ def run(self): def stop(self): pass - def __call__(self, title=None, message='', priority=None, retry=None, expire=None, sound=None, url=None, url_title=None, device=None, userKey=None, apiKey=None): + def __call__(self, title=None, message='', priority=None, retry=None, expire=None, sound=None, url=None, url_title=None, device=None, userKey=None, apiKey=None, attachment=None): data = {} - headers = {'User-Agent': "SmartHomeNG", 'Content-Type': "application/x-www-form-urlencoded"} data['timestamp'] = int(time.time()) if title: - data['title'] = title[:250].encode() + data['title'] = title[:250] - data['message'] = message[:1000].encode() + data['message'] = message[:1000] if priority: if isinstance(priority, int) and priority >= -2 and priority <= 2: @@ -122,20 +122,22 @@ def __call__(self, title=None, message='', priority=None, retry=None, expire=Non elif self._device: data['device'] = self._device - try: - resp = requests.post(self._url, headers=headers, data=data) + if attachment: + files = {'attachment': open(attachment, 'rb')} + else: + files = {} - # read json response on successful status 200 - if (resp.status_code == 200): - json_data = resp.json() + try: + json_data = self._po.post_json(self._url, json=data, files=files) + (_status_code, _reason) = self._po.response_status() # process response - if (resp.status_code == 200 and json_data['status'] == 1): + if (_status_code == 200 and json_data['status'] == 1): self.logger.debug("Pushover returns: Notification successful submitted.") - elif (resp.status_code == 429): + elif (_status_code == 429): self.logger.warning("Pushover returns: Message limits have been reached.") else: - self.logger.warning("Pushover returns: {0} - {1}".format(resp.status_code, resp.text)) + self.logger.warning("Pushover returns: {0} - {1}".format(_status_code, _reason)) except Exception as e: - self.logger.warning("Could not send Pushover notification: {0}. Error: {1}".format(event, e)) + self.logger.warning("Could not send Pushover notification. Error: {}".format(e)) diff --git a/pushover/_pv_1_3_1/README.md b/pushover/_pv_1_3_1/README.md new file mode 100644 index 000000000..1e718fd6d --- /dev/null +++ b/pushover/_pv_1_3_1/README.md @@ -0,0 +1,76 @@ +# Pushover + +Pushover is one out of many push services, which is compatible with Android, IOS and Windows Clients. This plugin make it possible to push messages to your clients from SmartHomeNG. + +## Requirements + +### Python libraries +* requests - [install instructions](http://docs.python-requests.org/en/latest/user/install/#install "http://docs.python-requests.org/en/latest/user/install/#install") + +### Other +* Pushover API-KEY - get it from [__here__](https://pushover.net/apps/ "https://pushover.net/apps/") for free, after registration. + +--- +## Changelog + +__2017-08-13__: + +* Initial version + +--- +## Configuration + +### plugin.yaml + +```yaml +po: + class_name: Pushover + class_path: plugins.pushover + apiKey: + userKey: +# device: +``` + +Description of the attributes: + +* __apiKey__: set api-key globally of the sending application +* __userKey__: set user-key globally so it will be used as defaul receiving user - you can override this on each call +* __device__: set receiving device globally to filter the receive device - you can override this on each call - you can define multiple devices seperated by comma - this is optional - without all devices will receive messages + +--- +## Usage: + +### sh.po(title, message [, priority] [, retry] [, expire] [, sound] [, url] [, url_title] [, device] [, userKey] [, apiKey]) +Send a message to your device. + +#### Parameters +* __title__: The title of the message +* __message__: The message - some html code possible, read https://pushover.net/api#html +* __priority__: Priority of the message - read https://pushover.net/api#priority +* __retry__: when Emergency priority set, this specifies how often (in seconds) the Pushover servers will send the same notification to the user - read https://pushover.net/api#priority +* __expire__: when Emergency priority set, this specifies how many seconds your notification will continue to be retried for (every retry seconds) - read https://pushover.net/api#priority +* __sound__: override a user's default tone choice on a per-notification basis - read https://pushover.net/api#sounds +* __url__: adds a supplementary URL that is not included in the message text, but available for the user to click on - read https://pushover.net/api#urls +* __url_title__: the title for the a supplementary URL - read https://pushover.net/api#urls +* __device__: defines and/or override the globally defined name of the receiving device +* __userKey__: defines and/or override the globally defined user-key of the receiving user +* __apiKey__: defines and/or override the globally defined api-key of the sending application + +All params can set to None (only message not), so they will not be set or in case of device, userKey and apiKey the global vars will be used. + +#### Example +```python + +# send simple message, without title (this are the min. params you need, if you defined userKey and apiKey globally) +sh.po(None, "This is my test message.") + +# send simple message, with title +sh.po("Simple Test", "This is my test message.") + +# send a high priority message +sh.po("Warning", "Your door is not locked!", 1) + +# send simple message to device with id: e6653 +sh.po("Simple Test", "This is my test message", None, None, None, None, None, None, "e6653") + +``` diff --git a/pushover/_pv_1_3_1/__init__.py b/pushover/_pv_1_3_1/__init__.py new file mode 100755 index 000000000..b847aa562 --- /dev/null +++ b/pushover/_pv_1_3_1/__init__.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python +# vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab +######################################################################### +# Copyright 2017 Thomas Creutz thomas.creutz@gmx.de +######################################################################### +# This file is part of SmartHomeNG +# https://github.com/smarthomeNG/smarthome +# http://knx-user-forum.de/ +# +# SmartHomeNG is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# SmartHomeNG is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with SmartHomeNG If not, see . +######################################################################### + +from lib.model.smartplugin import * +from lib.network import Http + +import time +import json + +class Pushover(SmartPlugin): + + PLUGIN_VERSION = "1.6.1.0" + + _url = "https://api.pushover.net/1/messages.json" + + def __init__(self, sh, *args, **kwargs): + from bin.smarthome import VERSION + if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': + self.logger = logging.getLogger(__name__) + self._apiKey = self.get_parameter_value('apiKey') + self._userKey = self.get_parameter_value('userKey') + self._device = self.get_parameter_value('device') + self._po = Http(); + + def run(self): + pass + + def stop(self): + pass + + def __call__(self, title=None, message='', priority=None, retry=None, expire=None, sound=None, url=None, url_title=None, device=None, userKey=None, apiKey=None, attachment=None): + data = {} + + data['timestamp'] = int(time.time()) + + if title: + data['title'] = title[:250] + + data['message'] = message[:1000] + + if priority: + if isinstance(priority, int) and priority >= -2 and priority <= 2: + data['priority'] = priority + + if retry and priority == 2: + if isinstance(retry, int) and retry >= 30: + data['retry'] = retry + else: + data['retry'] = 30 + self.logger.error("Pushover message retry need at least 30 secounds! I set it to 30!") + elif not retry and priority == 2: + self.logger.error("Pushover message priority = 2 need retry to be set, degrade priority to 1!") + data['priority'] = 1 + + if expire and priority == 2: + if isinstance(expire, int) and expire > 10800: + data['expire'] = expire + else: + data['expire'] = 10800 + self.logger.error("Pushover message expire need at most 10800 secounds! I set it to 10800.") + elif not expire and priority == 2: + self.logger.error("Pushover message priority = 2 need expire to be set, degrade priority to 1!") + data['priority'] = 1 + + # delete not used vars + if data['priority'] < 2: + if 'expire' in data: + del data['expire'] + if 'retry' in data: + del data['retry'] + + else: + self.logger.error("Pushover message priority need to be a number between -2 and 2!") + + if sound: + data['sound'] = sound + + if url: + data['url'] = url[:512] + if url_title: + data['url_title'] = url_title[:100] + + if userKey: + data['user'] = userKey + elif self._userKey: + data['user'] = self._userKey + else: + self.logger.error("Pushover needs a userKey") + return + + if apiKey: + data['token'] = apiKey + elif self._apiKey: + data['token'] = self._apiKey + else: + self.logger.error("Pushover needs a apiKey") + return + + if device: + data['device'] = device + elif self._device: + data['device'] = self._device + + if attachment: + files = {'attachment': open(attachment, 'rb')} + else: + files = {} + + try: + json_data = self._po.post_json(self._url, json=data, files=files) + (_status_code, _reason) = self._po.response_status() + + # process response + if (_status_code == 200 and json_data['status'] == 1): + self.logger.debug("Pushover returns: Notification successful submitted.") + elif (_status_code == 429): + self.logger.warning("Pushover returns: Message limits have been reached.") + else: + self.logger.warning("Pushover returns: {0} - {1}".format(_status_code, _reason)) + + except Exception as e: + self.logger.warning("Could not send Pushover notification. Error: {}".format(e)) diff --git a/pushover/_pv_1_3_1/plugin.yaml b/pushover/_pv_1_3_1/plugin.yaml new file mode 100755 index 000000000..adf4443dc --- /dev/null +++ b/pushover/_pv_1_3_1/plugin.yaml @@ -0,0 +1,40 @@ +# Metadata for the Smart-Plugin +plugin: + # Global plugin attributes + type: web # plugin type (gateway, interface, protocol, system, web) + description: # Alternative: description in multiple languages + de: 'Anbindung des Pushover Dienstes' + en: 'Connect to the Pushover Service' + maintainer: 'Thomas Creutz' + + version: 1.3.1.0 # Plugin version + sh_minversion: 1.2 # minimum shNG version to use this plugin + multi_instance: False # plugin supports multi instance + classname: Pushover # class containing the plugin + +parameters: + # Definition of parameters to be configured in etc/plugin.yaml + apiKey: + type: str + mandatory: True + description: + de: 'Der API Schlüssel' + en: 'The API key' + + userKey: + type: str + mandatory: True + description: + de: 'Der Benutzer Schlüssel, an den die Meldungen versendet werden' + en: 'The user key, which receive the messages' + + device: + type: str + mandatory: False + description: + de: 'Das Gerät des Benutzer' + en: 'The device of the user' + +item_attributes: + # Definition of item attributes defined by this plugin + diff --git a/pushover/requirements.txt b/pushover/_pv_1_3_1/requirements.txt similarity index 100% rename from pushover/requirements.txt rename to pushover/_pv_1_3_1/requirements.txt diff --git a/pushover/plugin.yaml b/pushover/plugin.yaml index adf4443dc..3f49ad8b4 100755 --- a/pushover/plugin.yaml +++ b/pushover/plugin.yaml @@ -5,11 +5,12 @@ plugin: description: # Alternative: description in multiple languages de: 'Anbindung des Pushover Dienstes' en: 'Connect to the Pushover Service' - maintainer: 'Thomas Creutz' + fr: "Connexion au service Pushover" - version: 1.3.1.0 # Plugin version - sh_minversion: 1.2 # minimum shNG version to use this plugin - multi_instance: False # plugin supports multi instance + maintainer: 'Thomas Creutz' + version: 1.6.1.0 # Plugin version + sh_minversion: 1.5 # minimum shNG version to use this plugin + multi_instance: True # plugin supports multi instance classname: Pushover # class containing the plugin parameters: @@ -20,13 +21,15 @@ parameters: description: de: 'Der API Schlüssel' en: 'The API key' + fr: 'Clé API' userKey: type: str mandatory: True description: de: 'Der Benutzer Schlüssel, an den die Meldungen versendet werden' - en: 'The user key, which receive the messages' + en: 'The user key, which receives the messages' + fr: "La clé de l'utilisateur qui reçoit les messages" device: type: str @@ -34,6 +37,7 @@ parameters: description: de: 'Das Gerät des Benutzer' en: 'The device of the user' + fr: "Appareil de l'utilisateur" item_attributes: # Definition of item attributes defined by this plugin From 3faef5d35eae3886125f72e00b16a4f0c0b124e1 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Thu, 20 Dec 2018 21:35:42 +0100 Subject: [PATCH 472/705] Update README.md --- stateengine/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/stateengine/README.md b/stateengine/README.md index f2f6f7514..e1a6ec8f8 100755 --- a/stateengine/README.md +++ b/stateengine/README.md @@ -12,7 +12,9 @@ The manual can be found on the official SmarthomeNG plugin documentation: Date: Fri, 21 Dec 2018 10:02:22 +0100 Subject: [PATCH 473/705] backend: Update to documentation page --- backend/user_doc.rst | 11 ++- backend/user_doc/assets/backend_itemtree.jpg | Bin 0 -> 163801 bytes .../user_doc/assets/backend_logik_editor.jpg | Bin 0 -> 185221 bytes .../user_doc/assets/backend_logikliste.jpg | Bin 0 -> 187699 bytes .../user_doc/assets/backend_systeminfo.jpg | Bin 0 -> 94431 bytes backend/user_doc/backend.rst | 69 ++++++++++++++++++ backend/user_doc/items.rst | 21 ++++++ backend/user_doc/logiken.rst | 36 +++++++++ 8 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 backend/user_doc/assets/backend_itemtree.jpg create mode 100644 backend/user_doc/assets/backend_logik_editor.jpg create mode 100644 backend/user_doc/assets/backend_logikliste.jpg create mode 100644 backend/user_doc/assets/backend_systeminfo.jpg create mode 100644 backend/user_doc/backend.rst create mode 100644 backend/user_doc/items.rst create mode 100644 backend/user_doc/logiken.rst diff --git a/backend/user_doc.rst b/backend/user_doc.rst index 738984c71..214c6c3b5 100755 --- a/backend/user_doc.rst +++ b/backend/user_doc.rst @@ -30,7 +30,7 @@ Außerdem kann das Webinterface direkt über ``http://smarthome.local:8383/backe Beispiele --------- -Das Backend Plugin liefert zahlreiche Infroamtionen, die zum Beispiel bei der Fehlersuche +Das Backend Plugin liefert zahlreiche Infroamtionen, die zum Beispiel bei der Fehlersuche hilfreich sind. Inzwischen kann man damit auch eine Reihe von Administrationsaufgaben erledigen. .. image:: assets/backend_systeminfo.jpg @@ -40,3 +40,12 @@ Genauer ist das unter :doc:`/backend/backend` beschrieben. Die Konfiguration de Plugins ist unter :doc:`/plugins_doc/config/backend` ausführlich beschrieben. + +.. toctree:: + :maxdepth: 4 + :hidden: + :titlesonly: + + user_doc/backend + user_doc/items + user_doc/logiken diff --git a/backend/user_doc/assets/backend_itemtree.jpg b/backend/user_doc/assets/backend_itemtree.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a7f3e09bc1868dbb577d26213587f6edd49f11a9 GIT binary patch literal 163801 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 z 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�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 H_G~93IWQx{h}8tC~~fp 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 literal 0 HcmV?d00001 diff --git a/backend/user_doc/assets/backend_logikliste.jpg b/backend/user_doc/assets/backend_logikliste.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9eb2af83095f63e1031f603b1b6c19dfbe4fd159 GIT binary patch literal 187699 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 z�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

      Rw=6t(Xi#BU+0q%5Df$VKytZ|= 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 z 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≥h&n=|5jB`~SQj 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 literal 0 HcmV?d00001 diff --git a/backend/user_doc/assets/backend_systeminfo.jpg b/backend/user_doc/assets/backend_systeminfo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..fd622a6dfb1ccbba5bb5546cadae6da8cabce76f GIT binary patch literal 94431 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:8383 + +Ab SmartHomeNG v1.4 erreichen sie die Administrations GUI (je nach Konfiguration von SmartHomeNG) +nur über den Aufruf: + +.. code:: + + http://:8383/backend + + +Ein Beispiel Schirm mit allgemeinen Informationen über SmartHomeNG und das System auf dem +SmartHomeNG läuft: + +.. image:: assets/backend_systeminfo.jpg + :class: screenshot + + + +.. toctree:: + :maxdepth: 4 + :hidden: + :titlesonly: + + items + logiken diff --git a/backend/user_doc/items.rst b/backend/user_doc/items.rst new file mode 100644 index 000000000..3bd8f26d5 --- /dev/null +++ b/backend/user_doc/items.rst @@ -0,0 +1,21 @@ +.. index:: Administrations GUI; Items + +##### +Items +##### + +Iin der graphischen Oberfläche steht eine Übersicht über alle definierten Items zur Verfügung. + + +.. index:: Item Tree + +Item Tree +========= + +Der Item Tree ermöglicht die Ansicht der Attribute aller Items. Außerdem ist es möglich den +Wert des jeweiligen Items zu setzen. + +.. image:: assets/backend_itemtree.jpg + :class: screenshot + + diff --git a/backend/user_doc/logiken.rst b/backend/user_doc/logiken.rst new file mode 100644 index 000000000..618fa31cd --- /dev/null +++ b/backend/user_doc/logiken.rst @@ -0,0 +1,36 @@ +.. index:: Administrations GUI; Logiken + +####### +Logiken +####### + +Ab SmartHomeNG v1.4 stehen in der graphischen Oberfläche Funktionen zur Verfügung, mit der +Logiken vollständig verwaltet (erstellt, geändert und konfiguriert) werden können. + + +.. index:: Logik Liste + +Logik Liste +=========== + +Die Logik Liste zeigt die Übersicht aller Logiken mit Informationen zu ihrer Konfiguration an. + +.. image:: assets/backend_logikliste.jpg + :class: screenshot + +Aus dieser Liste heraus kann man die Logiken triggern, neu laden, aktivieren bzw. deaktivieren, +entladen und löschen. Ein Klick auf den Dateinamen führt in den Logik Editor. + + + +.. index:: Logik Editor + +Logik Editor +============ + +Im Logik Editor können die Konfigurationsparameter einer Logik angepasst werden und der Code +der Logik kann editiert werden. + +.. image:: assets/backend_logik_editor.jpg + :class: screenshot + From 8bdfa8ca2cc4e6e3f67c430d9e336825c6c7be78 Mon Sep 17 00:00:00 2001 From: msinn Date: Fri, 21 Dec 2018 10:23:42 +0100 Subject: [PATCH 474/705] backend: Documentation changes --- backend/user_doc.rst | 69 ++++++++++++++++++++++++++++-------- backend/user_doc/backend.rst | 69 ------------------------------------ 2 files changed, 54 insertions(+), 84 deletions(-) delete mode 100644 backend/user_doc/backend.rst diff --git a/backend/user_doc.rst b/backend/user_doc.rst index 214c6c3b5..f138eff3a 100755 --- a/backend/user_doc.rst +++ b/backend/user_doc.rst @@ -1,30 +1,70 @@ .. index:: Plugins; backend (Backend Administrationsoberfläche) .. index:: backend +.. index:: Administrations GUI +.. index:: Webinterfaces; Administrations GUI (Backend) backend ####### -Konfiguration -============= +Seit SmartHomeNG v1.2 steht eine graphische Oberfläche zur Verfügung, die bei der Administration +von SmartHomeNG hilft. -Die Informationen zur Konfiguration des Plugins sind unter :doc:`/plugins_doc/config/backend` beschrieben. +Diese Oberfläche wird durch das **Backend Plugin** zur Verfügung gestellt. Dazu implementiert +SmartHomeNG einen eigenen Webserver, der in der Standardkonfiguration auf **Port 8383** hört. -Web Interface -============= +Das Backen Plugin liefert Informationen über die aktuelle SmartHomeNG Installation. Im Moment +dient es als Support-Tool, um anderen Benutzern bei einer Installation zu helfen, die nicht +ordnungsgemäß ausgeführt wird. + +Einige Höhepunkte: + +eine Liste der installierten Python-Module wird gegenüber den verfügbaren Versionen von PyPI angezeigt +eine Liste von Elementen und ihren Attributen wird angezeigt +eine Liste von Logiken und ihrer nächsten Ausführungszeit +eine Liste der aktuellen Scheduler und ihrer nächsten Ausführungszeit +Direkter Download der sqlite Datenbank (falls Plugin verwendet wird) und smarthome.log +Einige Informationen über häufig verwendete Daemons wie knxd / eibd sind enthalten +unterstützt die Standardauthentifizierung +mehrsprachige Unterstützung +Es gibt jedoch nur einen grundlegenden Schutz vor unbefugtem Zugriff oder Verwendung des Plugins. Seien Sie also vorsichtig, wenn Sie es mit Ihrem Netzwerk aktivieren. + + +Die GUI ermöglicht bereits einige Administrations Tasks direkt durchzuführen. Dazu gehören: + +- Setzen von Item Werten +- Erstellen, Änden und Löschen von Python Logiken +- Konfiguration von Lokigen +- Das Enablen und Disablen von Logiken + + +Die Administrations GUI wird durch folgenden Aufruf gestartet: + +.. code:: -Das backend Plugin verfügt über ein Webinterface, mit dessen Hilfe die Items die das Plugin nutzen -übersichtlich dargestellt werden. Außerdem können Statistiken über die KNX Aktivität angezeigt -werden. + http://:8383 +Ab SmartHomeNG v1.4 erreichen sie die Administrations GUI (je nach Konfiguration von SmartHomeNG) +nur über den Aufruf: -Aufruf des Webinterfaces ------------------------- +.. code:: -Das Plugin kann aus dem backend aufgerufen werden. Dazu auf der Seite Plugins in der entsprechenden -Zeile das Icon in der Spalte **Web Interface** anklicken. + http://:8383/backend + + +Ein Beispiel Schirm mit allgemeinen Informationen über SmartHomeNG und das System auf dem +SmartHomeNG läuft: + +.. image:: user_doc/assets/backend_systeminfo.jpg + :class: screenshot + + + +Konfiguration +============= + +Die Informationen zur Konfiguration des Plugins sind unter :doc:`/plugins_doc/config/backend` beschrieben. -Außerdem kann das Webinterface direkt über ``http://smarthome.local:8383/backend``. Beispiele @@ -33,7 +73,7 @@ Beispiele Das Backend Plugin liefert zahlreiche Infroamtionen, die zum Beispiel bei der Fehlersuche hilfreich sind. Inzwischen kann man damit auch eine Reihe von Administrationsaufgaben erledigen. -.. image:: assets/backend_systeminfo.jpg +.. image:: user_doc/assets/backend_systeminfo.jpg :class: screenshot Genauer ist das unter :doc:`/backend/backend` beschrieben. @@ -46,6 +86,5 @@ Die Konfiguration de Plugins ist unter :doc:`/plugins_doc/config/backend` ausfü :hidden: :titlesonly: - user_doc/backend user_doc/items user_doc/logiken diff --git a/backend/user_doc/backend.rst b/backend/user_doc/backend.rst deleted file mode 100644 index 53a91a136..000000000 --- a/backend/user_doc/backend.rst +++ /dev/null @@ -1,69 +0,0 @@ -.. index:: Plugins; Backend (Administrations GUI) -.. index:: Administrations GUI -.. index:: Webinterfaces; Administrations GUI (Backend) - -################### -Administrations GUI -################### - -Seit SmartHomeNG v1.2 steht eine graphische Oberfläche zur Verfügung, die bei der Administration -von SmartHomeNG hilft. - -Diese Oberfläche wird durch das **Backend Plugin** zur Verfügung gestellt. Dazu implementiert -SmartHomeNG einen eigenen Webserver, der in der Standardkonfiguration auf **Port 8383** hört. - - -Das Backen Plugin liefert Informationen über die aktuelle SmartHomeNG Installation. Im Moment -dient es als Support-Tool, um anderen Benutzern bei einer Installation zu helfen, die nicht -ordnungsgemäß ausgeführt wird. - -Einige Höhepunkte: - -eine Liste der installierten Python-Module wird gegenüber den verfügbaren Versionen von PyPI angezeigt -eine Liste von Elementen und ihren Attributen wird angezeigt -eine Liste von Logiken und ihrer nächsten Ausführungszeit -eine Liste der aktuellen Scheduler und ihrer nächsten Ausführungszeit -Direkter Download der sqlite Datenbank (falls Plugin verwendet wird) und smarthome.log -Einige Informationen über häufig verwendete Daemons wie knxd / eibd sind enthalten -unterstützt die Standardauthentifizierung -mehrsprachige Unterstützung -Es gibt jedoch nur einen grundlegenden Schutz vor unbefugtem Zugriff oder Verwendung des Plugins. Seien Sie also vorsichtig, wenn Sie es mit Ihrem Netzwerk aktivieren. - - -Die GUI ermöglicht bereits einige Administrations Tasks direkt durchzuführen. Dazu gehören: - -- Setzen von Item Werten -- Erstellen, Änden und Löschen von Python Logiken -- Konfiguration von Lokigen -- Das Enablen und Disablen von Logiken - - -Die Administrations GUI wird durch folgenden Aufruf gestartet: - -.. code:: - - http://:8383 - -Ab SmartHomeNG v1.4 erreichen sie die Administrations GUI (je nach Konfiguration von SmartHomeNG) -nur über den Aufruf: - -.. code:: - - http://:8383/backend - - -Ein Beispiel Schirm mit allgemeinen Informationen über SmartHomeNG und das System auf dem -SmartHomeNG läuft: - -.. image:: assets/backend_systeminfo.jpg - :class: screenshot - - - -.. toctree:: - :maxdepth: 4 - :hidden: - :titlesonly: - - items - logiken From 355047671b942f391f85517167dd65120e234390 Mon Sep 17 00:00:00 2001 From: msinn Date: Fri, 21 Dec 2018 10:42:32 +0100 Subject: [PATCH 475/705] backend: Documentation changes --- backend/user_doc.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/backend/user_doc.rst b/backend/user_doc.rst index f138eff3a..dd8a55404 100755 --- a/backend/user_doc.rst +++ b/backend/user_doc.rst @@ -76,9 +76,12 @@ hilfreich sind. Inzwischen kann man damit auch eine Reihe von Administrationsauf .. image:: user_doc/assets/backend_systeminfo.jpg :class: screenshot -Genauer ist das unter :doc:`/backend/backend` beschrieben. -Die Konfiguration de Plugins ist unter :doc:`/plugins_doc/config/backend` ausführlich beschrieben. +Neues Adiministrations-Interface +-------------------------------- + +Das neu ab SmartHomeNG v1.6 hinzukommende graphische Administrations-Interface ist unter :doc:`/admin/admin` beschrieben. + .. toctree:: From 4c70df2f7f1ce94dfc5b1bd42bcf90cb03718e1f Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Fri, 21 Dec 2018 14:54:13 +0100 Subject: [PATCH 476/705] Improved init command handling init commands now always are sent first (after power commands) --- avdevice/__init__.py | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/avdevice/__init__.py b/avdevice/__init__.py index 12383f9e2..330d04e55 100755 --- a/avdevice/__init__.py +++ b/avdevice/__init__.py @@ -1943,6 +1943,7 @@ def _duplicateindex(seq, seqitem): elif not self._send_commands == [] and not data == 'waiting': reorderlist = [] index = 0 + # Moving query commands to the back of the command list and power commands to the front for command in self._send_commands: command_split = command.split(';')[0] try: @@ -1952,22 +1953,23 @@ def _duplicateindex(seq, seqitem): if commanditem: command = '{};{}'.format(command_split, commanditem) self.logger.log(VERBOSE1, - "Parsing Input {}: Adding command commandsplit {}, commanditem {}. Command: {}".format( + "Parsing Input {}: Reorder command commandsplit {}, commanditem {}. Command: {}".format( self._name, command_split, commanditem, command)) if command_split in self._query_commands: reorderlist.append(command) elif command_split in self._power_commands: self.logger.log(VERBOSE1, - "Parsing Input {}: Adding command and ordering power command {} to first position.".format( + "Parsing Input {}: Reorder power command {} to first position.".format( self._name, command)) reorderlist.insert(0, command) index += 1 else: reorderlist.insert(index, command) self.logger.log(VERBOSE1, - "Parsing Input {}: Adding command {} to position {}.".format( + "Parsing Input {}: Reorder command {} to position {}.".format( self._name, command, index)) index += 1 + self._send_commands = reorderlist self.logger.debug( 'Parsing Input {}: Newly sorted send commands at end of parsing: {}'.format(self._name, @@ -2672,7 +2674,31 @@ def _replace_setcommand(replace_commandinfo, replace_dict, replace_command, repl else: reorderlist.insert(index, command) index += 1 - self._send_commands = reorderlist + # Moving init commands to the front of the command list + newreorderlist = [] + for command in reorderlist: + try: + commanditem = command.split(';')[1] + except Exception: + commanditem = None + for zone in range(self._number_of_zones, -1, -1): + for entry in self._init_commands['zone{}'.format(zone)]: + try: + compareitem = self._init_commands['zone{}'.format(zone)][entry].get('Item').id() + self.logger.log(VERBOSE2, + "Updating Item {}: Compare {} with {}.".format(self._name, commanditem, compareitem)) + if commanditem == compareitem: + self.logger.log(VERBOSE1, + "Updating Item {}: Reorder init command {} from zone {} to start of command list.".format( + self._name, command, zone)) + newreorderlist.insert(0, command) + except Exception as err: + self.logger.log(VERBOSE1, + "Updating Item {}: Problem with command reorder in zone {}: {}.".format( + self._name, zone, err)) + pass + reorderlist = [i for i in reorderlist if not i in newreorderlist] + self._send_commands = newreorderlist + reorderlist self._sendingcommand = self._send_commands[0] try: From 9c7001f60281809b640190b40aaa5fb7dcf0e745 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Fri, 21 Dec 2018 15:43:47 +0100 Subject: [PATCH 477/705] Update README.md --- mpd/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mpd/README.md b/mpd/README.md index da936a676..091367fba 100644 --- a/mpd/README.md +++ b/mpd/README.md @@ -10,7 +10,7 @@ For more information about MPD and it's commands see http://www.musicpd.org/doc/ ### plugin.yaml ```yaml -mpd: +mpd_bath: class_name: MPD class_path: plugins.mpd instance: bathroom @@ -18,7 +18,7 @@ mpd: port: 6601 # cycle: 2 -mpd: +mpd_kitchen: class_name: MPD class_path: plugins.mpd instance: kitchen @@ -122,7 +122,7 @@ mpd_command # If prefixed by '+' or '-', then the time is relative to the current playing position stop # bool, Stops playing crossfade # num, Sets crossfading between songs - mixrampdb # num, Sets the threshold at which songs will be overlapped. Like crossfading but doesn't + mixrampdb # num, Sets the threshold at which songs will be overlapped. Like crossfading but doesn't # fade the track volume, just overlaps mixrampdelay # num, Additional time subtracted from the overlap calculated by mixrampdb setvol # num, Sets volume to VOL, the range of volume is 0-100 @@ -140,7 +140,7 @@ mpd_rawcommand mpd_database Implements commands that are used to control the database. - update # str, Updates the music database: find new files, remove deleted files, + update # str, Updates the music database: find new files, remove deleted files, # update modified files. is a particular directory or song/file to update # If you do not specify it, everything is updated rescan # str, Same as update, but also rescans unmodified files From 2fa65bcb70e2c104d96aa0058f823a7b3a174e2b Mon Sep 17 00:00:00 2001 From: msinn Date: Fri, 21 Dec 2018 20:14:46 +0100 Subject: [PATCH 478/705] knx: Bugfix to metadata --- knx/plugin.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/knx/plugin.yaml b/knx/plugin.yaml index 9cc7733f8..adddde7d1 100755 --- a/knx/plugin.yaml +++ b/knx/plugin.yaml @@ -337,6 +337,7 @@ plugin_functions: - 'Zeichenkette [8859_1] (14 Byte) -> str' - 'Szenennummer: 0 - 63 (8 Bit) -> num' - 'Szenennummer: 1 - 64 (8 Bit) -> num' + - 'Szenennummer: 1 - 64 (8 Bit) -> num' - 'HVAC: 0 - 255 (8 Bit) -> num' - 'Unlimitierte Zeichenkette [8859_1] (var) -> str' - 'RGB: [0, 0, 0] - [255, 255, 255] (3 Byte) -> list' @@ -364,6 +365,7 @@ plugin_functions: - 'String [8859_1] (14 Byte) -> str' - 'Scene number: 0 - 63 (8 Bit) -> num' - 'Scene number: 1 - 64 (8 Bit) -> num' + - 'Scene number: 1 - 64 (8 Bit) -> num' - 'HVAC: 0 - 255 (8 Bit) -> num' - 'unlimited string [8859_1] (var) -> str' - 'RGB: [0, 0, 0] - [255, 255, 255] (3 Byte) -> list' From 3cf50da63eec5bfbea697bf374d0cd514b5a3f00 Mon Sep 17 00:00:00 2001 From: msinn Date: Fri, 21 Dec 2018 20:20:35 +0100 Subject: [PATCH 479/705] knx: Bugfix for metadata --- knx/plugin.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/knx/plugin.yaml b/knx/plugin.yaml index adddde7d1..8c617dc11 100755 --- a/knx/plugin.yaml +++ b/knx/plugin.yaml @@ -154,6 +154,7 @@ item_attributes: - 'Zeichenkette [8859_1] (14 Byte) -> str' - 'Szenennummer: 0 - 63 (8 Bit) -> num' - 'Szenennummer: 1 - 64 (8 Bit) -> num' + - 'Szenennummer: 1 - 64 (8 Bit) -> num' - 'HVAC: 0 - 255 (8 Bit) -> num' - 'Unlimitierte Zeichenkette [8859_1] (var) -> str' - 'RGB: [0, 0, 0] - [255, 255, 255] (3 Byte) -> list' @@ -181,6 +182,7 @@ item_attributes: - 'String [8859_1] (14 Byte) -> str' - 'Scene number: 0 - 63 (8 Bit) -> num' - 'Scene number: 1 - 64 (8 Bit) -> num' + - 'Scene number: 1 - 64 (8 Bit) -> num' - 'HVAC: 0 - 255 (8 Bit) -> num' - 'unlimited string [8859_1] (var) -> str' - 'RGB: [0, 0, 0] - [255, 255, 255] (3 Byte) -> list' From 798434cbefd169f551ff2eed51668392d9e10e23 Mon Sep 17 00:00:00 2001 From: msinn Date: Fri, 21 Dec 2018 20:38:16 +0100 Subject: [PATCH 480/705] openweathermap, stateengine, uzsu: Small documentation fixes --- openweathermap/user_doc.rst | 16 ++++++++-------- stateengine/user_doc.rst | 2 +- uzsu/user_doc.rst | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/openweathermap/user_doc.rst b/openweathermap/user_doc.rst index 163f50799..641745a04 100644 --- a/openweathermap/user_doc.rst +++ b/openweathermap/user_doc.rst @@ -1,9 +1,9 @@ -.. index:: Plugins; DarkSky (darksky.net / forecast.io Wetterdaten) +.. index:: Plugins; openweathermap (darksky.net / forecast.io Wetterdaten) .. index:: DarkSky -.. index:: Wetter; darksky +.. index:: Wetter; openweathermap -darksky -####### +openweathermap +############## Konfiguration ============= @@ -15,12 +15,12 @@ Web Interface ============= Das darksky Plugin verfügt über ein Webinterface, mit dessen Hilfe die Items die das Plugin nutzen -übersichtlich dargestellt werden. +übersichtlich dargestellt werden. -.. important:: +.. important:: Das Webinterface des Plugins kann mit SmartHomeNG v1.4.2 und davor **nicht** genutzt werden. - Es wird dann nicht geladen. Diese Einschränkung gilt nur für das Webinterface. Ansonsten gilt + Es wird dann nicht geladen. Diese Einschränkung gilt nur für das Webinterface. Ansonsten gilt für das Plugin die in den Metadaten angegebene minimale SmartHomeNG Version. @@ -39,7 +39,7 @@ Beispiele Folgende Informationen können im Webinterface angezeigt werden: -Oben rechts werden allgemeine Parameter zum Plugin angezeigt. +Oben rechts werden allgemeine Parameter zum Plugin angezeigt. Im ersten Tab werden die Items angezeigt, die das darksky Plugin nutzen: diff --git a/stateengine/user_doc.rst b/stateengine/user_doc.rst index f7f6ded9c..488821c94 100755 --- a/stateengine/user_doc.rst +++ b/stateengine/user_doc.rst @@ -1,7 +1,7 @@ .. index:: Plugins; Stateengine .. index:: Stateengine -Stateengine +stateengine ########### Konfiguration diff --git a/uzsu/user_doc.rst b/uzsu/user_doc.rst index 58d18ad7f..d00083d15 100755 --- a/uzsu/user_doc.rst +++ b/uzsu/user_doc.rst @@ -1,7 +1,7 @@ -.. index:: Plugins; UZSU -.. index:: UZSU +.. index:: Plugins; uzsu +.. index:: uzsu -UZSU +uzsu #### Konfiguration From 7bc0dd6c1040719f57c8fc907fe97744a096f86c Mon Sep 17 00:00:00 2001 From: msinn Date: Sat, 22 Dec 2018 13:34:53 +0100 Subject: [PATCH 481/705] admin module: Div. updates --- backend/utils.py | 87 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 6 deletions(-) diff --git a/backend/utils.py b/backend/utils.py index b580b4e78..95e493915 100755 --- a/backend/utils.py +++ b/backend/utils.py @@ -113,8 +113,8 @@ def _get_translation_for_block(lang, txt, block): blockdict = translation_dict.get('_' + block, {}) return blockdict.get(txt, '') - - + + def _get_translation(txt, block): """ Get translation with fallback to english and further fallback to german @@ -137,12 +137,12 @@ def _get_translation(txt, block): logger.info("Language '{0}': Translation for '{1}' is missing".format('en', txt)) tr = translation_dict_de.get(txt, '') return tr - + def translate(txt, block=''): """ returns translated text - + This function extends the jinja2 template engine """ logger = logging.getLogger(__name__) @@ -180,7 +180,7 @@ def parse_requirements(file_path): line = rline.lower().strip() else: line = line[0:line.find("#")].lower().strip() - + if len(line) > 0: if ">" in line: if line[0:line.find(">")].lower().strip() in req_dict: @@ -226,7 +226,82 @@ def get_process_info(command, wait=True): if wait: ## Wait for date to terminate. Get return returncode ## p_status = p.wait() - return str(result, encoding='utf-8', errors='strict') + return str(result, encoding='utf-8', errors='strict')3rdpartylicenses.txt +assets +color.c7a33805ffda0d32bd2a.png +fa-brands-400.3f4d4ad447e748754e99.svg +fa-brands-400.a31c967484b343189fc5.eot +fa-brands-400.dec02372212aab5a2e52.ttf +fa-brands-400.e4a6cecbe2bb89b0722b.woff2 +fa-brands-400.eef6051639f95300dbf0.woff +fa-regular-400.0e2e26fb3527ae47f9eb.ttf +fa-regular-400.52899632324b722c9c79.woff +fa-regular-400.b5a61b229c9c92a6ac21.svg +fa-regular-400.c38ef825039cbe8ec76d.eot +fa-regular-400.dd25437adf06f377113f.woff2 +fa-solid-900.3f759796d3d16b843484.svg +fa-solid-900.09bc9e8c7d6dfdace635.woff +fa-solid-900.baa1e2496e8c71f63658.eot +fa-solid-900.e143b57de78138e6d596.ttf +fa-solid-900.fd531d212b567d6049f4.woff2 +favicon.ico +hue.0614c27197fc3ce572e1.png +index.html +line.567f57385ea3dde2c9ae.gif +loading.8732a6660b528fadfaeb.gif +main.b7498a334d5bb97ef8e4.js +password-meter.d59e6dc2616c53ce8e77.png +polyfills.d1c7bf4a2ae7c3435f95.js +primeicons.38d77552b0353684a208.svg +primeicons.71bb3d79dcf18b45ae84.woff +primeicons.473e2a746d3c151d7dca.ttf +primeicons.b8eccb1059ea5faaf6d8.eot +roboto-v15-latin-regular.3d3a53586bd78d1069ae.svg +roboto-v15-latin-regular.7e367be02cd17a96d513.woff2 +roboto-v15-latin-regular.9f916e330c478bbfa2a0.eot +roboto-v15-latin-regular.16e1d930cf13fb7a9563.woff +roboto-v15-latin-regular.38861cba61c66739c145.ttf +runtime.ec2944dd8b20ec099bf3.js +scripts.bf34f41efa4f4868edea.js +slider_handles.1868e2550c9853a938a6.png +styles.b129e6ddb26879580c4a.css3rdpartylicenses.txt +color.c7a33805ffda0d32bd2a.png +fa-brands-400.3f4d4ad447e748754e99.svg +fa-brands-400.a31c967484b343189fc5.eot +fa-brands-400.dec02372212aab5a2e52.ttf +fa-brands-400.e4a6cecbe2bb89b0722b.woff2 +fa-brands-400.eef6051639f95300dbf0.woff +fa-regular-400.0e2e26fb3527ae47f9eb.ttf +fa-regular-400.52899632324b722c9c79.woff +fa-regular-400.b5a61b229c9c92a6ac21.svg +fa-regular-400.c38ef825039cbe8ec76d.eot +fa-regular-400.dd25437adf06f377113f.woff2 +fa-solid-900.3f759796d3d16b843484.svg +fa-solid-900.09bc9e8c7d6dfdace635.woff +fa-solid-900.baa1e2496e8c71f63658.eot +fa-solid-900.e143b57de78138e6d596.ttf +fa-solid-900.fd531d212b567d6049f4.woff2 +favicon.ico +hue.0614c27197fc3ce572e1.png +index.html +line.567f57385ea3dde2c9ae.gif +loading.8732a6660b528fadfaeb.gif +main.8aa979b98626a369d1e4.js +password-meter.d59e6dc2616c53ce8e77.png +polyfills.d1c7bf4a2ae7c3435f95.js +primeicons.38d77552b0353684a208.svg +primeicons.71bb3d79dcf18b45ae84.woff +primeicons.473e2a746d3c151d7dca.ttf +primeicons.b8eccb1059ea5faaf6d8.eot +roboto-v15-latin-regular.3d3a53586bd78d1069ae.svg +roboto-v15-latin-regular.7e367be02cd17a96d513.woff2 +roboto-v15-latin-regular.9f916e330c478bbfa2a0.eot +roboto-v15-latin-regular.16e1d930cf13fb7a9563.woff +roboto-v15-latin-regular.38861cba61c66739c145.ttf +runtime.ec2944dd8b20ec099bf3.js +scripts.bf34f41efa4f4868edea.js +slider_handles.1868e2550c9853a938a6.png +styles.b129e6ddb26879580c4a.css def os_with_systemd(): From 511ecf309f17655127e6b88c566791af1a4aa095 Mon Sep 17 00:00:00 2001 From: msinn Date: Sat, 22 Dec 2018 13:37:57 +0100 Subject: [PATCH 482/705] backend: Undo unwanted changes --- backend/user_doc/backend.rst | 69 ++++++++++++++++++++++++++++++++ backend/utils.py | 77 +----------------------------------- 2 files changed, 70 insertions(+), 76 deletions(-) create mode 100644 backend/user_doc/backend.rst diff --git a/backend/user_doc/backend.rst b/backend/user_doc/backend.rst new file mode 100644 index 000000000..53a91a136 --- /dev/null +++ b/backend/user_doc/backend.rst @@ -0,0 +1,69 @@ +.. index:: Plugins; Backend (Administrations GUI) +.. index:: Administrations GUI +.. index:: Webinterfaces; Administrations GUI (Backend) + +################### +Administrations GUI +################### + +Seit SmartHomeNG v1.2 steht eine graphische Oberfläche zur Verfügung, die bei der Administration +von SmartHomeNG hilft. + +Diese Oberfläche wird durch das **Backend Plugin** zur Verfügung gestellt. Dazu implementiert +SmartHomeNG einen eigenen Webserver, der in der Standardkonfiguration auf **Port 8383** hört. + + +Das Backen Plugin liefert Informationen über die aktuelle SmartHomeNG Installation. Im Moment +dient es als Support-Tool, um anderen Benutzern bei einer Installation zu helfen, die nicht +ordnungsgemäß ausgeführt wird. + +Einige Höhepunkte: + +eine Liste der installierten Python-Module wird gegenüber den verfügbaren Versionen von PyPI angezeigt +eine Liste von Elementen und ihren Attributen wird angezeigt +eine Liste von Logiken und ihrer nächsten Ausführungszeit +eine Liste der aktuellen Scheduler und ihrer nächsten Ausführungszeit +Direkter Download der sqlite Datenbank (falls Plugin verwendet wird) und smarthome.log +Einige Informationen über häufig verwendete Daemons wie knxd / eibd sind enthalten +unterstützt die Standardauthentifizierung +mehrsprachige Unterstützung +Es gibt jedoch nur einen grundlegenden Schutz vor unbefugtem Zugriff oder Verwendung des Plugins. Seien Sie also vorsichtig, wenn Sie es mit Ihrem Netzwerk aktivieren. + + +Die GUI ermöglicht bereits einige Administrations Tasks direkt durchzuführen. Dazu gehören: + +- Setzen von Item Werten +- Erstellen, Änden und Löschen von Python Logiken +- Konfiguration von Lokigen +- Das Enablen und Disablen von Logiken + + +Die Administrations GUI wird durch folgenden Aufruf gestartet: + +.. code:: + + http://:8383 + +Ab SmartHomeNG v1.4 erreichen sie die Administrations GUI (je nach Konfiguration von SmartHomeNG) +nur über den Aufruf: + +.. code:: + + http://:8383/backend + + +Ein Beispiel Schirm mit allgemeinen Informationen über SmartHomeNG und das System auf dem +SmartHomeNG läuft: + +.. image:: assets/backend_systeminfo.jpg + :class: screenshot + + + +.. toctree:: + :maxdepth: 4 + :hidden: + :titlesonly: + + items + logiken diff --git a/backend/utils.py b/backend/utils.py index 95e493915..3e38de343 100755 --- a/backend/utils.py +++ b/backend/utils.py @@ -226,82 +226,7 @@ def get_process_info(command, wait=True): if wait: ## Wait for date to terminate. Get return returncode ## p_status = p.wait() - return str(result, encoding='utf-8', errors='strict')3rdpartylicenses.txt -assets -color.c7a33805ffda0d32bd2a.png -fa-brands-400.3f4d4ad447e748754e99.svg -fa-brands-400.a31c967484b343189fc5.eot -fa-brands-400.dec02372212aab5a2e52.ttf -fa-brands-400.e4a6cecbe2bb89b0722b.woff2 -fa-brands-400.eef6051639f95300dbf0.woff -fa-regular-400.0e2e26fb3527ae47f9eb.ttf -fa-regular-400.52899632324b722c9c79.woff -fa-regular-400.b5a61b229c9c92a6ac21.svg -fa-regular-400.c38ef825039cbe8ec76d.eot -fa-regular-400.dd25437adf06f377113f.woff2 -fa-solid-900.3f759796d3d16b843484.svg -fa-solid-900.09bc9e8c7d6dfdace635.woff -fa-solid-900.baa1e2496e8c71f63658.eot -fa-solid-900.e143b57de78138e6d596.ttf -fa-solid-900.fd531d212b567d6049f4.woff2 -favicon.ico -hue.0614c27197fc3ce572e1.png -index.html -line.567f57385ea3dde2c9ae.gif -loading.8732a6660b528fadfaeb.gif -main.b7498a334d5bb97ef8e4.js -password-meter.d59e6dc2616c53ce8e77.png -polyfills.d1c7bf4a2ae7c3435f95.js -primeicons.38d77552b0353684a208.svg -primeicons.71bb3d79dcf18b45ae84.woff -primeicons.473e2a746d3c151d7dca.ttf -primeicons.b8eccb1059ea5faaf6d8.eot -roboto-v15-latin-regular.3d3a53586bd78d1069ae.svg -roboto-v15-latin-regular.7e367be02cd17a96d513.woff2 -roboto-v15-latin-regular.9f916e330c478bbfa2a0.eot -roboto-v15-latin-regular.16e1d930cf13fb7a9563.woff -roboto-v15-latin-regular.38861cba61c66739c145.ttf -runtime.ec2944dd8b20ec099bf3.js -scripts.bf34f41efa4f4868edea.js -slider_handles.1868e2550c9853a938a6.png -styles.b129e6ddb26879580c4a.css3rdpartylicenses.txt -color.c7a33805ffda0d32bd2a.png -fa-brands-400.3f4d4ad447e748754e99.svg -fa-brands-400.a31c967484b343189fc5.eot -fa-brands-400.dec02372212aab5a2e52.ttf -fa-brands-400.e4a6cecbe2bb89b0722b.woff2 -fa-brands-400.eef6051639f95300dbf0.woff -fa-regular-400.0e2e26fb3527ae47f9eb.ttf -fa-regular-400.52899632324b722c9c79.woff -fa-regular-400.b5a61b229c9c92a6ac21.svg -fa-regular-400.c38ef825039cbe8ec76d.eot -fa-regular-400.dd25437adf06f377113f.woff2 -fa-solid-900.3f759796d3d16b843484.svg -fa-solid-900.09bc9e8c7d6dfdace635.woff -fa-solid-900.baa1e2496e8c71f63658.eot -fa-solid-900.e143b57de78138e6d596.ttf -fa-solid-900.fd531d212b567d6049f4.woff2 -favicon.ico -hue.0614c27197fc3ce572e1.png -index.html -line.567f57385ea3dde2c9ae.gif -loading.8732a6660b528fadfaeb.gif -main.8aa979b98626a369d1e4.js -password-meter.d59e6dc2616c53ce8e77.png -polyfills.d1c7bf4a2ae7c3435f95.js -primeicons.38d77552b0353684a208.svg -primeicons.71bb3d79dcf18b45ae84.woff -primeicons.473e2a746d3c151d7dca.ttf -primeicons.b8eccb1059ea5faaf6d8.eot -roboto-v15-latin-regular.3d3a53586bd78d1069ae.svg -roboto-v15-latin-regular.7e367be02cd17a96d513.woff2 -roboto-v15-latin-regular.9f916e330c478bbfa2a0.eot -roboto-v15-latin-regular.16e1d930cf13fb7a9563.woff -roboto-v15-latin-regular.38861cba61c66739c145.ttf -runtime.ec2944dd8b20ec099bf3.js -scripts.bf34f41efa4f4868edea.js -slider_handles.1868e2550c9853a938a6.png -styles.b129e6ddb26879580c4a.css + return str(result, encoding='utf-8', errors='strict') def os_with_systemd(): From 70c4d7464873b85d7ee086afb54b85645544302a Mon Sep 17 00:00:00 2001 From: msinn Date: Sat, 22 Dec 2018 13:39:22 +0100 Subject: [PATCH 483/705] backend: Undoing unwanted changes --- backend/user_doc/backend.rst | 69 ------------------------------------ 1 file changed, 69 deletions(-) delete mode 100644 backend/user_doc/backend.rst diff --git a/backend/user_doc/backend.rst b/backend/user_doc/backend.rst deleted file mode 100644 index 53a91a136..000000000 --- a/backend/user_doc/backend.rst +++ /dev/null @@ -1,69 +0,0 @@ -.. index:: Plugins; Backend (Administrations GUI) -.. index:: Administrations GUI -.. index:: Webinterfaces; Administrations GUI (Backend) - -################### -Administrations GUI -################### - -Seit SmartHomeNG v1.2 steht eine graphische Oberfläche zur Verfügung, die bei der Administration -von SmartHomeNG hilft. - -Diese Oberfläche wird durch das **Backend Plugin** zur Verfügung gestellt. Dazu implementiert -SmartHomeNG einen eigenen Webserver, der in der Standardkonfiguration auf **Port 8383** hört. - - -Das Backen Plugin liefert Informationen über die aktuelle SmartHomeNG Installation. Im Moment -dient es als Support-Tool, um anderen Benutzern bei einer Installation zu helfen, die nicht -ordnungsgemäß ausgeführt wird. - -Einige Höhepunkte: - -eine Liste der installierten Python-Module wird gegenüber den verfügbaren Versionen von PyPI angezeigt -eine Liste von Elementen und ihren Attributen wird angezeigt -eine Liste von Logiken und ihrer nächsten Ausführungszeit -eine Liste der aktuellen Scheduler und ihrer nächsten Ausführungszeit -Direkter Download der sqlite Datenbank (falls Plugin verwendet wird) und smarthome.log -Einige Informationen über häufig verwendete Daemons wie knxd / eibd sind enthalten -unterstützt die Standardauthentifizierung -mehrsprachige Unterstützung -Es gibt jedoch nur einen grundlegenden Schutz vor unbefugtem Zugriff oder Verwendung des Plugins. Seien Sie also vorsichtig, wenn Sie es mit Ihrem Netzwerk aktivieren. - - -Die GUI ermöglicht bereits einige Administrations Tasks direkt durchzuführen. Dazu gehören: - -- Setzen von Item Werten -- Erstellen, Änden und Löschen von Python Logiken -- Konfiguration von Lokigen -- Das Enablen und Disablen von Logiken - - -Die Administrations GUI wird durch folgenden Aufruf gestartet: - -.. code:: - - http://:8383 - -Ab SmartHomeNG v1.4 erreichen sie die Administrations GUI (je nach Konfiguration von SmartHomeNG) -nur über den Aufruf: - -.. code:: - - http://:8383/backend - - -Ein Beispiel Schirm mit allgemeinen Informationen über SmartHomeNG und das System auf dem -SmartHomeNG läuft: - -.. image:: assets/backend_systeminfo.jpg - :class: screenshot - - - -.. toctree:: - :maxdepth: 4 - :hidden: - :titlesonly: - - items - logiken From a7e08220ca98efa3496f58c888ca6d3b0667dcf1 Mon Sep 17 00:00:00 2001 From: Bernd Meiners Date: Sat, 22 Dec 2018 17:37:37 +0100 Subject: [PATCH 484/705] inor bugfix and prepare for SHNG 1.6 --- dlms/__init__.py | 32 +++++++++++++++++++++++++++----- dlms/conversion.py | 2 ++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/dlms/__init__.py b/dlms/__init__.py index 765df0f89..77003774d 100644 --- a/dlms/__init__.py +++ b/dlms/__init__.py @@ -31,24 +31,32 @@ __revision__ = "0.1" __docformat__ = 'reStructuredText' +import sys import logging import datetime from lib.module import Modules from lib.model.smartplugin import * from lib.utils import Utils +from lib.shtime import Shtime +shtime = Shtime.get_instance() import time -import serial import re from threading import Semaphore +try: + import serial + REQUIRED_PACKAGE_IMPORTED = True +except: + REQUIRED_PACKAGE_IMPORTED = False + from . import dlms from . import conversion class DLMS(SmartPlugin, conversion.Conversion): - PLUGIN_VERSION = "1.5.1" + PLUGIN_VERSION = "1.5.2" """ This class provides a Plugin for SmarthomeNG which reads out a smartmeter. @@ -80,10 +88,18 @@ def __init__(self, sh, *args, **kwargs ): reset_baudrate = True no_waiting = False """ - self.logger = logging.getLogger(__name__) + from bin.smarthome import VERSION + if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': + self.logger = logging.getLogger(__name__) + self.logger.debug("init {}".format(__name__)) self._init_complete = False + # Exit if the required package(s) could not be imported + if not REQUIRED_PACKAGE_IMPORTED: + self.logger.error("{}: Unable to import Python package 'pyserial'".format(self.get_fullname())) + return + self._instance = self.get_parameter_value('instance') # the instance of the plugin for questioning multiple smartmeter self._update_cycle = self.get_parameter_value('update_cycle') # the frequency in seconds how often the device should be accessed @@ -125,7 +141,7 @@ def run(self): """ self.logger.debug("Plugin '{}': run method called".format(self.get_fullname())) self.alive = True - self.scheduler_add('DLMS', self._update_values_callback, prio=5, cycle=self._update_cycle) + self.scheduler_add('DLMS', self._update_values_callback, prio=5, cycle=self._update_cycle, next=shtime.now()) self.logger.debug("run dlms") def stop(self): @@ -272,6 +288,9 @@ def _update_items( self, Code, Values): except KeyError as e: self.logger.warning("Key error '{}' while setting item {} for Obis Code {} to " "Key '{}' in '{}'".format(str(e), item, Code, Key, Values[Index])) + except NameError as e: + self.logger.warning("Name error '{}' while setting item {} for Obis Code {} to " + "Key '{}' in '{}'".format(str(e), item, Code, Key, Values[Index])) def _update_values(self, readout): """ @@ -335,7 +354,10 @@ def _update_values(self, readout): values.append( { 'Value': v } ) # uncomment the following line to check the generation of the values dictionary # self.logger.debug("{:40} ---> {}".format(line, Values)) - self._update_items(obis_code, values) + try: + self._update_items(obis_code, values) + except: + self.logger.error("tried to update items for Obis Code {} to Values {} failed with {}".format(obis_code, values, sys.exc_info()[0])) # ------------------------------------------ # Webinterface of the plugin diff --git a/dlms/conversion.py b/dlms/conversion.py index cc801024f..6c2a5f103 100644 --- a/dlms/conversion.py +++ b/dlms/conversion.py @@ -28,6 +28,8 @@ __revision__ = "0.1" __docformat__ = 'reStructuredText' +import datetime + class Conversion: def _to_datetime_ZST10(self, text): """ From 8f91bf55ad23f7f901d28da2455c5087b74b7b29 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 22 Dec 2018 17:41:29 +0100 Subject: [PATCH 485/705] Update documentation and metadata info --- stateengine/plugin.yaml | 276 ++++++++++- stateengine/user_doc.rst | 10 +- stateengine/user_doc/user_doc1.rst | 41 +- stateengine/user_doc/user_doc10.rst | 106 +---- stateengine/user_doc/user_doc11.rst | 75 ++- stateengine/user_doc/user_doc12.rst | 317 +++++++++++-- stateengine/user_doc/user_doc13.rst | 329 +------------- stateengine/user_doc/user_doc14.rst | 680 +++++++++++++++++++++++++++- stateengine/user_doc/user_doc15.rst | 675 --------------------------- stateengine/user_doc/user_doc2.rst | 231 +++++----- stateengine/user_doc/user_doc3.rst | 325 ++++++------- stateengine/user_doc/user_doc4.rst | 346 ++++++++------ stateengine/user_doc/user_doc5.rst | 361 +++------------ stateengine/user_doc/user_doc6.rst | 282 ++++++++---- stateengine/user_doc/user_doc7.rst | 338 +++++++------- stateengine/user_doc/user_doc8.rst | 348 +++----------- stateengine/user_doc/user_doc9.rst | 171 ++++--- 17 files changed, 2364 insertions(+), 2547 deletions(-) delete mode 100644 stateengine/user_doc/user_doc15.rst diff --git a/stateengine/plugin.yaml b/stateengine/plugin.yaml index 8c398f585..21cb3bf30 100755 --- a/stateengine/plugin.yaml +++ b/stateengine/plugin.yaml @@ -1,48 +1,123 @@ # Metadata for the StateEngine plugin plugin: # Global plugin attributes - type: system # plugin type (gateway, interface, protocol, system, web) + type: system description: de: 'Zustandsautomat für SmarthomeNG, ehemals AutoBlind' en: 'Finite state machine for SmarthomeNG, previously known as AutoBlind' + description_long: + de: 'Der ursprüngliche Zweck dieses Plugins war es, Jalousien zu + steuern. Mit den steigenden Anforderungen hat es sich jedoch zu + einem flexiblen Zustandsautomaten entwickelt, mit dem nahezu alles + gesteuert werden kann. Im Prinzip ist es ein `endlicher + Automat `_. + Dabei arbeitet das Plugin nicht mit Events, die zu konkreten Zuständen + führen, sondern mit einer hierarchischen Evaluierung der Zustände. + ' + en: 'Initially this plugin was used to automatically control blinds. + Meanwhile it is a flexible fully featured `finite state machine + `_. It does not + work with typical events to define which state is evaluated next but + with hierarchical states. + ' maintainer: i-am-offline, onkelandy documentation: https://www.smarthomeng.de/user/plugins/stateengine/user_doc.html + support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1303071-stateengine-plugin-support version: 1.4.2 sh_minversion: 1.4.1 multi_instance: False classname: StateEngine + attribute_prefix: se parameters: # Definition of parameters to be configured in etc/plugin.yaml startup_delay_default: type: int default: 10 + valid_min: -1 + valid_max: 600 description: de: 'Vorgabe für Verzögerung der ersten Zustandsermittlung beim Start' en: 'Default delay for first state determination at startup' - valid_min: -1 - valid_max: 600 + description_long: + de: '**Vorgabewert für die Startverzögerung der ersten Zustandsermittlung beim Start von smarthomeNG:**\n + Beim Starten von smarthomeNG dauert es üblicherweise einige + Sekunden, bis alle Items initialisiert sind. Um zu verhindern, + dass die erste Zustandsermittlung stattfindet, bevor alle Items + ihren Initialwert haben, wird die erste Zustandsermittlung + verzögert. Die Dauer der Verzögerung kann bei den Objekt-Items + angegeben werden. Wenn bei einem Objekt-Item kein Wert angegeben + ist, wird der hier angegebene Standardwert verwendet. + \n + - Zahl größer 0: + Angabe der Startverzögerung in Sekunden. Während der + Startverzögerung sind die Auslöser der Zustandsermittlung + inaktiv.\n + - 0: + Keine Startverzögerung. Die erste Zustandsermittlung wird direkt + nach der Initialisierung des Objekt-Items durchgeführt.\n + - -1: + Es wird keine erste Zustandsermittlung durchgeführt.\n + \n + Ohne Angabe dieses Parameters wird der Standardwert von 10 Sekunden angenommen. + ' + en: '**Default delay for first state determination at startup:**\n + - digit higher than 0: start delay in seconds\n + - 0: no start delay, immediate init\n + - -1: no init\n + \n + ' suspend_time_default: type: int default: 3600 + valid_min: 1 + valid_max: 86400 description: de: 'Vorgabezeit zur Unterbrechung der automatischen Steuerung nach manuellen Aktionen' en: 'Default suspend duration after manual actions' - valid_min: 1 - valid_max: 86400 + description_long: + de: '**Vorgabezeit zur Unterbrechung der automatischen Steuerung nach manuellen Aktionen:**\n + Nach manuellen Aktionen kann die Automatik für eine bestimmte Zeit + Unterbrochen werden. Die Dauer dieser Unterbrechungen kann bei den + Objekt-Items angegeben werden. Die Einheit für den Wert sind + Sekunden. Wenn bei einem Objekt-Item kein Wert angegeben ist, wird + der hier angegebene Standardwert verwendet. Wenn kein abweichender + Standardwert in der Plugin-Konfiguration angegeben ist, ist der + Vorgabewert 3600 Sekunden (1 Stunde) + ' + en: '**Default suspend duration after manual actions**: + After a manual change of the item the automatic evaluation is paused. + This value defines the duration of the pause in seconds if the + value is not defined in the object item itself. + ' log_level: type: int default: 0 - description: - de: 'Erweiterte Protokollierung: Loglevel (0: aus, 1: Info, 2: Debug)' - en: 'Extended Logging: Loglevel (0: off, 1: Info, 2: Debug)' valid_list: - 0 - 1 - 2 + valid_list_description: + de: ['deaktiviert', 'Info', 'Debug'] + en: ['deactivated', 'Info', 'Debug'] + description: + de: 'Erweiterte Protokollierung: Loglevel (0: aus, 1: Info, 2: Debug)' + en: 'Extended Logging: Loglevel (0: off, 1: Info, 2: Debug)' + description_long: + de: '**Erweiterte Protokollierung:**\n + Bei einem Wert von 1 oder 2 wird pro Item eine eigene Logdatei im unter log_directory + angegebenen Verzeichnis angelegt. + Wenn der Parameter nicht angegeben oder auf 0 gestellt ist, + ist die erweiterte Protokollierung deaktiviert. + ' + en: '**Extended Logging**:\n + If 1 or 2 is given there will be a seperate log file for each item in the folder + defined as log_directory. + If the parameter is absent or set to 0 no extended logging is active + ' log_directory: type: str @@ -50,13 +125,196 @@ parameters: description: de: 'Erweiterte Protokollierung: Verzeichnis für die Protokolldateien' en: 'Extended Logging: Directory for log files' - + description_long: + de: '**Verzeichnis für die Protokolldateien:**\n + Die Logdateien der erweiterten Protokollierung werden in das + hier angegebene Verzeichnis geschrieben. + Wenn der angegebene Verzeichnisname mit "/" beginnt wird er als + absoluter Verzeichnisname behandelt. Alle anderen + Verzeichnisnamen werden als Unterverzeichnisse des smarthomeNG + Basisverzeichnisses behandelt. Das angegebene Verzeichnis wird + angelegt, wenn es nicht existiert. + Wenn hier kein abweichendes Verzeichnis angegeben ist, wird das + Verzeichnis ``/var/log/AutoState/`` + verwendet. + ' + en: '**Directory for log files**:\n + If the parameter is absent the log files will be saved to + ``/var/log/AutoState/`` + ' log_maxage: type: int default: 0 description: de: 'Erweiterte Protokollierung: Anzahl der Tage, nach der die Dateien im Verzeichnis für die Protokolldateien wieder gelöscht werden sollen' en: 'Extended Logging: Number of days after which the files in the directory for log files should be deleted' + description_long: + de: '**Log Rotation für erweiterte Protokollierung:**\n + Alte Protokolldateien können nach einer bestimmten Zeit + automatisch gelöscht werden. Durch diesen Parameter wird die Anzahl + der Tage festgelegt, nach der die Dateien gelöscht werden sollen. + Das Löschen ist ausgesetzt, solange der Parameter den Wert 0 hat. + Wenn der Parameter auf einen anderen Wert gesetzt wird, wird das + Alter der Dateien im Protokollverzeichnis ``log_directory`` + täglich geprüft und überalterte Dateien werden gelöscht.\n + \n + **Achtung:**\n + Die Löschfunktionalität prüft und löscht alle + Dateien im Protokollverzeichnis, ob sie Protokolldateien sind + oder nicht. Daher sollten keine anderen Dateien in diesem + Verzeichnis abgelegt werden! + ' + en: '**Log rotation for extended logging:**\n + If this parameter is not set to 0 older log files get deleted after + the given amount of days from the ``log_directory``.\n + \n + **Warning:**\n + Everything gets deleted from the given directory, not just log files! + ' item_attributes: # Definition of item attributes defined by this plugin + type: + type: string + valid_list: + - 'bool' + valid_list_description: + de: ['Der Item Typ muss auf bool gestellt werden!'] + en: ['The item type has to be set to bool'] + description: + de: 'Datentyp des Objekt-Items. Muss "bool" sein.' + en: 'Data type of the object item. Has to be "bool"' + + se_plugin: + type: string + mandatory: True + valid_list: + - 'active' + - 'inactive' + valid_list_description: + de: ['Aktiviert die State Machine', 'Jeder andere Wert deaktiviert die State Machine'] + en: ['Activates the state machine', 'Any other value deactivates the state machine'] + description: + de: 'Kennzeichnet das Item als Objekt-Item des StateEngine-Plugins. Ist der Wert nicht "active", werden keine Zustände evaluiert.' + en: 'Makes the StateEngine-Plugin aware of this item as an object item. If the value is not "active", the state are not evaluated.' + + se_startup_delay: + type: int + valid_min: -1 + valid_max: 600 + description: + de: 'Vorgabe für Verzögerung der ersten Zustandsermittlung beim Start' + en: 'Default delay for first state determination at startup' + description_long: + de: '**Startverzögerung der ersten Zustandsermittlung beim Start von smarthomeNG:**\n + Beim Starten von smarthomeNG dauert es üblicherweise einige + Sekunden, bis alle Items initialisiert sind. Um zu verhindern, + dass die erste Zustandsermittlung stattfindet, bevor alle Items + ihren Initialwert haben, wird die erste Zustandsermittlung + verzögert. Zustandsermittlungen, die durch Items oder Timer vor Ablauf der + Startverzögerung ausgelöst werden, werden nicht durchgeführt. + Die zulässigen Werte für ``se_startup_delay`` sind identisch + mit den zulässigen Werten für den Plugin-Parameter + ``startup_delay_default``. + ' + en: '**Delay for first state determination at startup:**\n + All evaluations are suspended until the startup delay has passed. + The values for ``se_startup_delay`` are the same as for the plugin + parameter ``startup_delay_default``. + ' + + se_laststate_item_name: + type: string + description: + de: 'Id des Items, in dem der Name des aktuellen Zustands abgelegt wird' + en: 'Id of the item that saves the name of the current state' + description_long: + de: '**Id des Items, in dem der Name des aktuellen Zustands abgelegt wird:**\n + In das hier verknüpfte Item wird der Name des aktuellen Zustands + abgelegt. Das Item kann für Displayzwecke verwendet werden. Wenn + das Item ``se_laststate_item_name`` nicht angegeben ist, steht + der Name des aktuellen Zustands nicht zur Verfügung. + ' + en: '**Id of the item that saves the name of the current state:**\n + The item defined here saves the name of the current state for + visualization purposes. If ``se_laststate_item_name`` is not defined + you cannot access the name of the current state. + ' + + se_laststate_item_id: + type: string + description: + de: 'Id des Items, in dem die ID des aktuellen Zustands abgelegt wird' + en: 'Id of the item that saves the ID of the current state' + description_long: + de: '**Id des Items, in dem der aktuelle Zustand abgelegt wird:**\n + In das hier verknüpfte Item wird die Id des aktuellen Zustands + abgelegt. Das Item kann mit dem Attribut ``cache: yes`` + versehen werden, dann bleibt der vorherige Zustand bei einem + Neustart von smarthomeNG erhalten. Wenn das Item nicht angegeben ist, + wird der aktuelle Zustand nur im Plugin gespeichert und geht mit + einem Neustart von smarthomeNG verloren. + ' + en: '**Id of the item that saves the id of the current state:**\n + In combination with the attribute ``cache: yes`` the defined item + can be used to load the last state after the plugin start. Otherwise + it does not know the last valid state before a system restart. + ' + + se_repeat_actions: + type: bool + description: + de: 'Wiederholen der Aktionen bei unverändertem Zustand' + en: 'Repeat actions on eval even if the state stays the same' + description_long: + de: '**Wiederholen der Aktionen bei unverändertem Zustand:**\n + Im Normalfall werden Aktionen jedesmal ausgeführt wenn der + aktuelle Zustand neu ermittelt wurde. Dies ist unabhängig davon, + ob sich der Zustand bei der Neuermittlung geändert hat oder nicht. + Durch die Angabe von ``se_repeat_actions: false`` werden die Aktionen + nur beim erstmaligen Aktivieren des Zustands ausgeführt. Diese Option + ist auch für jede Aktion separat verfügbar, um vom hier angegebenen + Wert abzuweichen. + ' + en: '**Repeat actions on eval even if the state stays the same:**\n + Generally actions are executed every time a state is entered, even if + the state does not change. By setting ``se_repeat_actions: false`` + the actions are exclusively when entering the first state the first time. + This option is also available for every action seperately to overrule this setting. + ' + + se_suspend_time: + type: int + valid_min: 1 + valid_max: 86400 + description: + de: 'Dauer der Unterbrechung der automatischen Steuerung nach manuellen Aktionen' + en: 'Suspend duration after manual actions' + description_long: + de: '**Unterbrechung der automatischen Steuerung nach manuellen Aktionen:**\n + Nach manuellen Aktionen kann die Automatik für eine bestimmte Zeit + Unterbrochen werden. Wird die Dauer nicht im Objekt-Item definiert, + wird die Standarddauer aus der Plugin Konfiguration oder der Standardwert + von 3600 Sekunden (1 Stunde) angenommen. + ' + en: '**Suspend duration after manual actions**: + After a manual change of the item the automatic evaluation is paused. + If this value is not defined in the object item, the default value + from the plugin configuration or the default value of 3600 seconds (1 hour) + is used. + ' + + se_item_suspend_end: + type: string + description: + de: 'Id des Items, in dem das Ende der Suspendzeit abgelegt werden soll' + en: 'Id of the item that saves the suspend end time' + description_long: + de: '**Id des Items, in dem das Ende der Suspendzeit abgelegt werden soll:**\n + Für Visualisierungszwecke kann der Inhalt des hier verknüpften Items + angezeigt werden. Dadurch ist ersichtlich, bis wann die Statusevaluierung + noch ausgesetzt wird. + ' + en: '**Id of the item that saves the suspend end time:**\n + To visualize the end time of the suspend state. + ' diff --git a/stateengine/user_doc.rst b/stateengine/user_doc.rst index f7f6ded9c..64be04140 100755 --- a/stateengine/user_doc.rst +++ b/stateengine/user_doc.rst @@ -1,14 +1,13 @@ -.. index:: Plugins; Stateengine -.. index:: Stateengine +.. index:: Plugins; stateengine +.. index:: stateengine -Stateengine +stateengine ########### -Konfiguration +Dokumentation ============= .. toctree:: - :numbered: user_doc/user_doc1.rst user_doc/user_doc2.rst @@ -24,4 +23,3 @@ Konfiguration user_doc/user_doc12.rst user_doc/user_doc13.rst user_doc/user_doc14.rst - user_doc/user_doc15.rst diff --git a/stateengine/user_doc/user_doc1.rst b/stateengine/user_doc/user_doc1.rst index 6714650a2..2f33239b2 100755 --- a/stateengine/user_doc/user_doc1.rst +++ b/stateengine/user_doc/user_doc1.rst @@ -6,7 +6,7 @@ Allgemein .. important:: - Es ist nicht empfehlenswert das stateengine Plugin + Es ist nicht empfehlenswert, das stateengine Plugin für sicherheitsrelevante Zustände, wie zum Beispiel das Hochfahren von Jalousien bei zu viel Wind, zu verwenden. Sicherheitsrelevante Funktionen müssen so einfach wie möglich aufgebaut sein. Es wird @@ -19,24 +19,19 @@ Allgemein .. rubric:: Funktionalität :name: funktionalitaet -Über zusätzliche Items in den items/\*.conf-Dateien können Objekte +Über zusätzliche Items in den items/\*.yaml Dateien können Objekt-Items definiert werden, die eine beliebige Anzahl benutzerdefinierter -Zustand haben. Jeder Zustand kann Sets von Einstiegs- und -Ausstiegsbedingungen haben, sowie diverse Aktionen auslösen, wenn -der Zustand aktiv wird. In regelmäßigen Intervallen werden die -Zustände für jedes Objekt geprüft. - -- Wenn die Ausstiegsbedingungen des aktuellen Zustands nicht - erfüllt sind bleibt das Objekt im aktuellen Zustand. -- Wenn der aktuelle Zustand verlassen werden kann werden alle - Zustände in der Reihenfolge, in der sie in der - Konfigurationsdatei definiert sind, abgeprüft. -- Der erste Zustand bei dem eine Gruppe Einstiegsbedingungen - vollständig erfüllt ist, wird zum aktuellen Zustand. Die - Aktionen, die für diesen Zustand definiert sind, werden - ausgeführt. -- Wenn kein passender Zustand gefunden wird passiert nichts. Das - Objekt verbleibt im vorherigen Zustand. +Zustände haben. Jeder Zustand kann Sets von Einstiegsbedingungen haben +und diverse Aktionen auslösen, wenn der Zustand aktiv wird. + +In regelmäßigen Intervallen werden die Zustände für jedes Objekt der angegebenen +Reihe nach geprüft. Der erste Zustand, bei dem eine Gruppe Einstiegsbedingungen +vollständig erfüllt ist, wird zum aktuellen Zustand. Die +Aktionen, die für diesen Zustand definiert sind, werden ausgeführt. + +Wenn kein passender Zustand gefunden wird, passiert nichts. Das Objekt verbleibt im vorherigen Zustand. +Dies kann in manchen Fällen Sinn machen, meist bietet es sich aber an, +einen Standardzustand ganz am Ende festzulegen, der keine Eingangsbedingungen hat. Die folgenden Bedingungen können Teil der Bedingungsgruppen sein: @@ -47,13 +42,7 @@ Die folgenden Bedingungen können Teil der Bedingungsgruppen sein: - Alter des aktuellen Zustands (Minimum, Maximum, Wert) - Zufallszahl (Minimum, Maximum, Wert) - Vorheriger Zustand (Wert) -- Trigger-Objekt, dass die Zustandsermittlung ausgelöst hat +- Trigger-Objekt, das die Zustandsermittlung ausgelöst hat -Zusätzlich können beliebige Items als Bedingungen geprüft werden +Zusätzlich können beliebige Items (z.B. Temperatur) als Bedingungen geprüft werden (Minimum, Maximum oder Wert) - -Der ursprüngliche Zweck dieses Plugins war es, Jalousien zu -steuern. Mit den steigenden Anforderungen hat es sich jedoch zu -einem flexiblen Zustandsautomaten entwickelt, mit dem nahezu alles -gesteuert werden kann. Im Prinzip ist es ein `endlicher -Automat `_. diff --git a/stateengine/user_doc/user_doc10.rst b/stateengine/user_doc/user_doc10.rst index 394916455..38d7eef80 100644 --- a/stateengine/user_doc/user_doc10.rst +++ b/stateengine/user_doc/user_doc10.rst @@ -1,96 +1,22 @@ -.. index:: Plugins; Stateengine; Vordefinierte Funktionen -.. index:: Vordefinierte Funktionen +.. index:: Plugins; Stateengine; Variablen +.. index:: Variablen +.. _Variablen: -Vordefinierte Funktionen -######################## +Variablen +######### -.. rubric:: Vordefinierte Funktionen - :name: vordefiniertefunktionen +Mit dem Datentyp AbValue kann +auf Variablen des Plugins zugegriffen werden. Derzeit stehen +folgende Variablen zur Verfügung: -Das stateengine Plugin stellt verschiedene vordefinierte -Funktionen zur Verfügung die einfach für -``se_set_`` und ``se_run_`` Aktionen -verwendet werden können. Diese Funktionen sind in einer Klasse -enthalten, die bei Bedarf für das Ausführen der Aktion -instanziiert wird. Die folgenden Funktionen können verwendet -werden: +| **item.suspend_time:** +| *Die Suspend-Time des Items* -.. rubric:: Winkel zum Nachführen der Jalousielamellen auf Basis des Sonnenstands berechnen - :name: winkel +| **item.suspend_remaining:** +| *Die übrige Dauer des Suspend Zustands* -.. code-block:: yaml +| **current.state_id:** +| *Die Id des Status, der gerade geprüft wird* - stateengine_eval.sun_tracking() - - -.. rubric:: Zufallszahl - :name: zufallszahl - -.. code-block:: yaml - - stateengine_eval.get_random_int(min,max) - -Über ``min`` und ``max`` kann die kleinste/größte Nummer, die -zurückgegeben werden soll, festgelegt werden. ``min`` und -``max`` können weggelassen werden, in diesem Fall sind die -Vorgabewerte 0 für ``min`` und 255 für ``max``. - -.. rubric:: Shell-Kommando ausführen - :name: shellkommandoausfhren - -.. code-block:: yaml - - stateengine_eval.execute(command) - -Führt das Shell-Kommando ``command`` aus - -.. rubric:: Wert einer Variable ermitteln - :name: werteinervariableermitteln - -.. code-block:: yaml - - stateengine_eval.get_variable(varname) - -Liefert den Wert der :ref:`Variablen` ``varname`` - -.. rubric:: Item-Id relativ zum Objekt-Item ermitteln - :name: itemidrelativzumobjektitemermitteln - -.. code-block:: yaml - - stateengine_eval.get_relative_itemid(subitem_id) - -Eine Item-Id relativ zur Item-Id des Objekt-Items wird ermittelt. -Die Ermittlung erfolgt dabei mit der gleichen Rotine, die zur -relativen Ermittlung von Items verwendet wird. - -.. rubric:: Item-Wert relativ zum Objekt-Item ermitteln - :name: itemwertrelativzumobjektitemermitteln - -.. code-block:: yaml - - stateengine_eval.get_relative_itemvalue(subitem_id) - -Der Wert eines Items relativ zur Item-Id des Objekt-Items wird -ermittelt. Die Ermittlung erfolgt dabei mit der gleichen Rotine, -die zur relativen Ermittlung von Items verwendet wird. - -.. rubric:: Suspend-Ende in einen Text einsetzen - :name: suspendendeineinentexteinsetzen - -.. code-block:: yaml - - stateengine_eval.insert_suspend_time(suspend_item_id, suspend_text="Ausgesetzt bis %X") - -Das Ende der Suspend-Zeit wird in den Text ``suspend_text`` -eingesetzt. Im Text sind daher entsprechende Platzhalter -vorzusehen (Siehe `strftime() and strptime() -Behavior `_). -Wird kein ``suspend_text`` angegeben, so wird als Vorgabewert -"Ausgesetzt bis %X" verwendet. - -Zur Ermittlung des Endes der Suspend-Zeit muss über -``suspend_item_id`` ein Item angegeben werden, dessen Wert bei -Eintritt in den Suspend-Status geändert wird. Über das Alter des -Werts in diesem Item wird die bereits abgelaufene Suspend-Zeit -bestimmt. +| **current.state_name:** +| *Der Name des Status, der gerade geprüft wird* diff --git a/stateengine/user_doc/user_doc11.rst b/stateengine/user_doc/user_doc11.rst index a119b7287..b3ef0b040 100644 --- a/stateengine/user_doc/user_doc11.rst +++ b/stateengine/user_doc/user_doc11.rst @@ -1,22 +1,65 @@ -.. index:: Plugins; Stateengine; Variablen -.. index:: Variablen -.. _Variablen: +.. index:: Plugins; Stateengine; Sperren +.. index:: Sperren +.. _Lock-Zustand: -Variablen -######### +Sperren +####### -.. rubric:: Variablen - :name: variablen +Für das Sperren der automatischen Zustandsermittlung führt man ein +Sperr-Item ein, das beispielsweise über einen Taster oder die Visu änderbar +ist. -Mit dem Datentyp AbValue kann -auf Variablen des Plugins zugegriffen werden. Derzeit stehen -folgende Variablen zur Verfügung: +Die Sperre soll aktiv sein, wenn das Sperr-Item den Wert ``True`` +hat. -| **item.suspend_time:** -| *Die Suspend-Time des Items* +.. rubric:: Das Sperr-Item + :name: dassperritem -| **current.state_id:** -| *Die Id des Status, der gerade geprüft wird* +Das Sperritem definiert man wie folgt: -| **current.state_name:** -| *Der Name des Status, der gerade geprüft wird* +.. code-block:: yaml + + beispiel: + lock: + item: + type: bool + name: Sperr-Item + visu_acl: rw + cache: on + +.. rubric:: Der Sperrzustand + :name: dersperrzustand + +Eine Änderung des Sperr-Items muss direkt eine +Zustandsermittlung auslösen, das Sperr-Item wird daher in die +Liste der ``eval_trigger`` aufgenommen. + +Einstiegsbedingung für den Sperrzustand ist nun einfach, dass das +Sperr-Item den Wert ``True`` hat. Für das Sperr-Item werden in +diesem Beispiel keinerlei Aktionen definiert. Solange also das +Sperr-Item aktiv ist, passiert nichts. + +.. code-block:: yaml + + beispiel: + jalousie1: + rules: + # Sperr-Item zu eval_trigger: + eval_trigger: + - + - beispiel.lock.item + + # Items für Bedingungen und Aktionen + se_item_lock: beispiel.lock.item #Siehe Beispiel oben + + locked: + type: foo + name: Manuell gesperrt + + enter: + se_value_lock: true + + +Bei der Zustandsermittlung ist die Reihenfolge der +Zustände relevant. Da der Sperrzustand allen anderen Zuständen +vorgeht, ist er üblicherweise der erste Zustand in der Definition. diff --git a/stateengine/user_doc/user_doc12.rst b/stateengine/user_doc/user_doc12.rst index 6cd2c1642..e289acdb1 100644 --- a/stateengine/user_doc/user_doc12.rst +++ b/stateengine/user_doc/user_doc12.rst @@ -1,72 +1,295 @@ -.. index:: Plugins; Stateengine; Sperren -.. index:: Sperren -.. _Lock-Zustand: +.. index:: Plugins; Stateengine; Aussetzen +.. index:: Aussetzen -Sperren -####### +Aussetzen +######### -.. rubric:: Lock - Sperren der automatischen Zustandsermittlung - :name: lock +Eine besondere Anforderung: Nach bestimmten manuellen Aktionen (z. +B. über einen Taster, die Visu, o. ä.) soll die automatische +Zustandsermittlung für eine gewisse Zeit ausgesetzt werden. Nach +Ablauf dieser Zeit soll die Automatik wieder aktiv werden. -Für das Sperren der automatischen Zustandsermittlung führt man ein -Sperr-Item ein, dass beispielsweise über einen Taster änderbar -ist. +Für dieses Verhalten sind zunächst einige weitere Steueritems +erforderlich, dann kann das Verhalten in einem Zustand abgebildet +werden. -Die Sperre soll aktiv sein, wenn das Sperr-Item den Wert ``True`` -hat. +.. rubric:: Das "Suspend"-Item + :name: dassuspenditem -.. rubric:: Das Sperr-Item - :name: dassperritem +Zunächst wird ein "Suspend"-Item benötigt. Dieses Item zeigt zum +einen die zeitweise Deaktivierung an, zum, anderen kann die +Deaktivierung über dieses Item vorzeitig beendet werden: -Das Sperritem definiert man wie folgt: +.. code-block:: yaml + + beispiel: + raffstore1: + automatik: + + suspend: + type: bool + knx_dpt: 1 + visu_acl: rw + cache: 'True' + +.. rubric:: Das "Manuell"-Item + :name: dasmanuellitem + +Ein weiteres Item wird benötigt, um alle Aktionen, die den +Suspend-Zustand auslösen sollen, zu kapseln. Dieses Item ist das +"Manuell"-Item. Es wird so angelegt, dass der Wert dieses Items +bei jeder manuellen Betätigung invertiert wird: .. code-block:: yaml - beispiel: - lock: - item: - type: bool - name: Sperr-Item - visu_acl: rw - cache: on + beispiel: + raffstore1: + automatik: + + manuell: + type: bool + se_manual_invert: 'True' + se_manual_exclude: + - database:* + - KNX:1.1.4 + eval_trigger: + - taster1 + - taster2 + +In das Attribut ``eval_trigger`` werden alle Items eingetragen, +deren Änderung als manuelle Betätigung gewertet werden soll. +Das Attribut ``se_manual_invert: true`` veranlasst das +stateengine-Plugin dabei, den Wert des Items bei Änderungen zu +invertieren, wie es für das Auslösen des Suspend-Zustands +erforderlich ist. -.. rubric:: Der Sperrzustand - :name: dersperrzustand +In bestimmten Fällen ist es erforderlich, das Item-Änderungen, die +durch bestimmte Aufrufe ausgelöst werden, nicht als manuelle +Betätigung gewertet werden. Hierzu zählt zum Beispiel die +Rückmeldung der Raffstore-Position nach dem Verfahren durch den +Jalousieaktor. Hierfür stehen zwei für das Manuell-Item weitere +Attribute bereit: -Der Sperrzustand geht allen anderen Zuständen vor und wird deshalb -als erster Zustand definiert. +| **as_manual_include** +| *Liste der Aufrufe, die als "manuelle Betätigung" gewertet + werden sollen* -Zudem muss eine Änderung des Sperr-Items direkt eine -Zustandsermittlung auslösen, das Sperr-Item wird daher in die -Liste der ``eval_trigger`` aufgenommen. +| **as_manual_exclude** +| *Liste der Aufrufe, die nicht als "manuelle Betätigung" gewertet + werden sollen* -Einstiegsbedingung für den Sperrzustand ist nun einfach, dass das -Sperr-Item den Wert ``True`` hat. Für das Sperr-Item werden in -diesem Beispiel keinerlei Aktionen definiert. Solange also das -Sperr-Item aktiv ist, passiert: nichts. +Bei beiden Attributen wird eine Liste von Elementen angegeben. Die +einzelnen Elemente bestehen dabei aus dem Aufrufenden +(``Caller``) einem Doppelpunkt und der Quelle (``Source``). Ohne Leerzeichen! +Mehrere Elemente werden durch "|" getrennt bzw. im yaml als Liste deklariert. +Für ``Caller`` und ``Source`` kann dabei jeweils auch ``"*"`` angegeben werden, dies +bedeutet, dass der jeweilige Teil nicht berücksichtigt werd. + +Wenn bei der Prüfung festgestellt wird, dass ein Wert über eine +Eval-Funktionalität geändert wurde, so wird die Änderung +zurückverfolgt bis zur ursprünglichen Änderung, die die Eval-Kette +ausgelöst hat. Diese ursprüngliche Änderung wird dann geprüft. + +Der Wert von ``Caller`` zeigt an, welche Funktionalität das Item +geändert hat. Der Wert von ``Source`` ist Abhängig vom Caller. +Häufig verwendete ``Caller`` sind: + +- ``Init``: Initialisierung von smarthomeNG. ``Source`` ist + in der Regel leer +- ``Visu``: Änderung über die Visualisierung (Visu-Plugin). + ``Source`` beinhaltet die IP und den Port der Gegenstelle +- ``KNX``: Änderung über das KNX-Plugin. ``Source`` ist die + physische Adresse des sendenden Geräts + +Wenn ``se_manual_include`` oder ``se_manual_exclude`` angegeben +sind, muss ``se_manual_invert`` nicht angegeben werden. + +.. rubric:: Der Suspend-Zustand + :name: dersuspendzustand + +Mit diesen beiden Items kann nun ein einfacher Suspend-Zustand +definiert werden. Als Aktion im Suspend-Zustand wird dabei die +Sonderaktion "suspend" verwendet. Diese hat zwei Parameter: .. code-block:: yaml - beispiel: - lock: + se_special_suspend: suspend:, + + +Der Suspend-Zustand sieht damit wie folgt aus: + +.. code-block:: yaml + + beispiel: + raffstore1: + automatik: + rules: + suspend: + type: foo + name: Ausgesetzt + + on_enter_or_stay: + type: foo + name: Ausführen immer wenn ein Zustand aktiv ist + + # Suspend-Item setzen + se_special_suspend: suspend:beispiel.raffstore1.automatik.suspend,beispiel.raffstore1.automatik.manuell + + on_leave: + type: foo + name: Ausführen beim Verlassen des Zustands + + # Suspend-Item zurücksetzen + se_set_suspend: False + + enter_manuell: + type: foo + name: Bedingung: Suspend beginnen + + #Bedingung: Manuelle Aktion wurde durchgeführt + se_value_trigger_source: beispiel.raffstore1.automatik.manuell + + enter_stay: + type: foo + name: Bedingung: Im Suspend verbleiben + + #Bedingung: Suspend ist aktiv + se_value_laststate: var:current.state_id + + #Bedingung: Suspendzeit ist noch nicht abgelaufen + se_agemax_manuell: var:item.suspend_time + + #Bedingung: Suspend-Item wurde nicht extern geändert + se_value_suspend: True + + +Da der Suspend-Zustand anderen Zuständen +vorgehen sollte steht er üblicherweise sehr weit vorrne in der +Reihenfolge. In der Regel wird der Suspend-Zustand in der +Definition der zweite Zustand nach dem :ref:`Lock-Zustand` sein. + +.. rubric:: Komplettes Beispiel + :name: komplettesbeispiel + +Baut man die einzelnen Teile zusammen erhält man die folgende +Konfiguration. + +.. code-block:: yaml + + beispiel: + raffstore1: + automatik: + type: foo + name: stateengine Suspend Beispiel + + suspend: + type: bool + name: Suspend-Item + visu_acl: rw + + manuell: + type: bool + name: Manuelle Bedienung + eval_trigger: + - beispiel.item1 + - beispiel.item2 + se_manual_invert: true + rules: - # Sperr-Item zu eval_trigger: + type: bool + name: Automatik Test Suspend + se_plugin: active + + # Sowohl das Manuell- als auch das Suspend-Item müssen eine Zustandsermittlung auslösen eval_trigger: - - - - beispiel.lock.item + - beispiel.raffstore1.automatik.manuell + - beispiel.raffstore1.automatik.suspend - # Items für Bedingungen und Aktionen - se_item_lock: beispiel.lock.item + #Items für Bedingungen und Aktionen zuweisen + se_item_suspend: beispiel.raffstore1.automatik.suspend + se_item_manuell: beispiel.raffstore1.automatik.manuell + se_suspend_time: 300 - lock: + suspend: type: foo - name: Manuell gesperrt + name: Ausgesetzt + + on_enter_or_stay: + se_action_suspend: + - 'function: special' + - 'value: suspend:..suspend, ..manuell' + - 'repeat: True' + - 'order: 1' + se_action_suspend_end: + - 'function: set' + - "to: eval:stateengine_eval.insert_suspend_time('..suspend', suspend_text='%X')" + - 'repeat: True' + - 'order: 2' + se_action_retrigger: + - 'function: set' + - 'to: True' + - 'delay: var:item.suspend_remaining' + - 'repeat: True' + - 'order: 3' + + on_leave: + se_action_suspend: + - 'function: set' + - 'to: False' + se_action_suspend_end: + - 'function: set' + - 'to: ' + + enter_manuell: + se_value_trigger_source: eval:stateengine_eval.get_relative_itemid('..manuell') + se_value_suspend_active: 'True' + + enter_stay: + name: Bedingung Im Suspend verbleiben + #Bedingung: Suspend ist aktiv + se_value_laststate: var:current.state_id + #Bedingung: Suspendzeit ist noch nicht abgelaufen + se_agemax_manuell: var:item.suspend_time + #Bedingung: Suspend-Item wurde nicht extern geändert + se_value_suspend: True + + +.. rubric:: Dauer der zeitweisen Deaktivierung + :name: dauerderzeitweisendeaktivierung + +Die Dauer der zeitweisen Deaktivierung wird in der +Plugin-Konfiguration über die Einstellung ``suspend_time_default`` +angegeben. Vorgabewert sind 3600 Sekunden (1 Stunde). Wenn die +Dauer der zeitweisen Deaktivierung für ein einzelnes Objekt-Item +abweichend sein soll, kann dort das Attribut + +.. code-block:: yaml + + se_suspend_time: + +angegeben werden. Der Parameter kann auch durch ein Item festgelegt werden. + +.. rubric:: Erweitertes Logging für das Manuell-Item: + :name: erweitertesloggingfrdasmanuellitem + +Sofern im Manuell-Item die Attribute ``se_manual_include`` bzw. +``se_manual_exclude`` verwendet werden, ist eine +Protokollierung mittels des erweiterten Loggings möglich. Dazu +muss das Item, unter dem das Log geführt wird, über das zusätzliche +Attribut ``se_manual_logitem`` angegeben werden. Hier wird man als +Item in der Regel das Manuell-Item angeben: + +.. code-block:: yaml - enter: - se_value_lock: true + beispiel: + raffstore1: + automatik: + manuell: + .... + se_manual_logitem: beispiel.raffstore1.automatik.manuell -Bei der Zustandsermittlung die Reihenfolge der Definition der -Zustände relevant. Da der Sperrzustand allen anderen Zuständen -vorgeht ist er üblicherweise der erste Zustand in der Definition. +Wird statt ``se_manual_include`` oder ``se_manual_exclude`` nur +``se_manual_invert`` verwendet, ist kein erweitertes Logging +möglich. diff --git a/stateengine/user_doc/user_doc13.rst b/stateengine/user_doc/user_doc13.rst index cde9d60a6..4878d1325 100644 --- a/stateengine/user_doc/user_doc13.rst +++ b/stateengine/user_doc/user_doc13.rst @@ -1,321 +1,16 @@ -.. index:: Plugins; Stateengine; Aussetzen -.. index:: Aussetzen +.. index:: Plugins; Stateengine; CLI +.. index:: CLI -Aussetzen -######### +CLI +### -.. rubric:: Suspend - Zeitweises Deaktivieren der automatischen Zustandsermittlung nach manuellen Aktionen - :name: suspend +Sofern die eingesetzte smarthomeNG-Version dies unterstützt, +registriert das stateengine-Plugin zwei eigene Kommandos beim +CLI-Plugin. -Eine besondere Anforderung: Nach bestimmten manuellen Aktionen (z. -B. über einen Taster, die Visu, o. ä.) soll die automatische -Zustandsermittlung für eine gewisse Zeit ausgesetzt werden. Nach -Ablauf dieser Zeit soll die Automatik wieder aktiv werden. +| **se_list** +| *Zeigt eine Liste der Objekt-Items, für die das + stateengine-Plugin aktiv ist* -Für dieses Verhalten sind zunächst einige weitere Steueritems -erforderlich, dann kann das Verhalten in einem Zustand abgebildet -werden. - -.. rubric:: Das "Suspend"-Item - :name: dassuspenditem - -Zunächst wird ein "Suspend"-Item benötigt. Dieses Item zeigt zum -einen die zeitweise Deaktivierung an, außerdem kann die -Deaktivierung über dieses Item vorzeitig beendet werden: - -.. code-block:: yaml - - beispiel: - suspend: - suspend: - type: bool - name: Suspend-Item - visu_acl: rw - - -.. rubric:: Das "Manuell"-Item - :name: dasmanuellitem - -Ein weiteres Item wird benötigt, um alle Aktionen, die den -Suspend-Zustand auslösen sollen, zu kapseln. Dieses Item ist das -"Manuell"-Item. Es wird so angelegt, dass der Wert dieses Items -bei jeder manuellen Betätigung invertiert wird: - -.. code-block:: yaml - - beispiel: - suspend: - manuell: - type: bool - name: Manuelle Bedienung - eval_trigger: - - beispiel.item1 - - beispiel.item2 - - .... - se_manual_invert = true - - -In das Attribut ``eval_trigger`` werden alle Items eingetragen, -deren Änderung als manuelle Betätigung gewertet werden soll. -Änderungen an diesen Items, die vom stateengine-Plugin selbst -vorgenommen wurden, werden dabei automatisch ausgefiltert um -Endlosschleifen zu verhindern. - -Das Attribut ``se_manual_invert: true`` veranlasst das -stateengine-Plugin dabei, den Wert des Items bei Änderungen zu -invertieren, wie es für das Auslösen des Suspend-Zustands -erforderlich ist. - -Das Manuell-Item kann noch wesentlich komplexer ausgestaltet -werden. Beispielsweise können Änderungen durch bestimmte -Ereignisse ausgeschlossen werden. - -.. rubric:: Der Suspend-Zustand - :name: dersuspendzustand - -Mit diesen beiden Items kann nun ein einfacher Suspend-Zustand -definiert werden. Als Aktion im Suspend-Zustand wird dabei die -Sonderaktion "suspend" verwendet. Diese hat zwei Parameter: - -.. code-block:: yaml - - se_special_suspend: suspend:, - - -Der Suspend-Zustand sieht damit wie folgt aus: - -.. code-block:: yaml - - suspend: - type: foo - name: Ausgesetzt - - on_enter_or_stay: - type: foo - name: Ausführen immer wenn ein Zustand aktiv ist - - # Suspend-Item setzen - se_special_suspend: suspend:test.suspend.suspend,test.suspend.manuell - - on_leave: - type: foo - name: Ausführen beim Verlassen des Zustands - - # Suspend-Item zurücksetzen - se_set_suspend: False - - enter_manuell: - type: foo - name: Bedingung: Suspend beginnen - - #Bedingung: Manuelle Aktion wurde durchgeführt - se_value_trigger_source: test.suspend.manuell - - enter_stay: - type: foo - name: Bedingung: Im Suspend verbleiben - - #Bedingung: Suspend ist aktiv - se_value_laststate: var:current.state_id - - #Bedingung: Suspendzeit ist noch nicht abgelaufen - se_agemax_manuell: var:item.suspend_time - - #Bedingung: Suspend-Item wurde nicht extern geändert - se_value_suspend: True - - -Bei der Zustandsermittlung die Reihenfolge der Definition der -Zustände relevant. Da der Suspend-Zustand anderen Zuständen -vorgehen sollte steht er üblicherweise sehr weit vorrne in der -Reihenfolge. In der Regel wird der Suspend-Zustand in der -Definition der zweite Zustand, nach dem -:ref:`Lock-Zustand` sein. - -.. rubric:: Komplettes Beispiel - :name: komplettesbeispiel - -Baut man die einzelnen Teile zusammen erhält man die folgende -Konfiguration. - -.. code-block:: yaml - - item: - type: foo - name: stateengine Suspend Beispiel - - suspend: - type: bool - name: Suspend-Item - visu_acl: rw - - manuell: - type: bool - name: Manuelle Bedienung - eval_trigger: - - beispiel.item1 - - beispiel.item2 - se_manual_invert: true - - rules: - type: bool - name: Automatik Test Suspend - se_plugin: active - - # Sowohl das Manuell- als auch das Suspend-Item müssen eine Zustandsermittlung auslösen - eval_trigger: - - test.suspend.manuell - - test.suspend.suspend - - #Items für Bedingungen und Aktionen zuweisen - se_item_suspend: test.suspend.suspend - se_item_manuell: test.suspend.manuell - - suspend: - type: foo - name: Ausgesetzt - - on_enter_or_stay: - se_action_suspend: - - 'function: special' - - 'value: suspend:..suspend, ..manuell' - - 'repeat: True' - - 'order: 1' - se_action_suspend_end: - - 'function: set' - - "to: eval:stateengine_eval.insert_suspend_time('..suspend', suspend_text='%X')" - - 'repeat: True' - - 'order: 2' - se_action_retrigger: - - 'function: set' - - 'to: True' - - 'delay: var:item.suspend_remaining' - - 'repeat: True' - - 'order: 3' - - on_leave: - se_action_suspend: - - 'function: set' - - 'to: False' - se_action_suspend_end: - - 'function: set' - - 'to: ' - - enter_manuell: - se_value_trigger_source: eval:stateengine_eval.get_relative_itemid('..manuell') - se_value_suspend_active: 'True' - - enter_stay: - name: Bedingung Im Suspend verbleiben - #Bedingung: Suspend ist aktiv - se_value_laststate: var:current.state_id - #Bedingung: Suspendzeit ist noch nicht abgelaufen - se_agemax_manuell: var:item.suspend_time - #Bedingung: Suspend-Item wurde nicht extern geändert - se_value_suspend: True - - -.. rubric:: Dauer der zeitweisen Deaktivierung - :name: dauerderzeitweisendeaktivierung - -Die Dauer der zeitweisen Deaktivierung wird in der -Plugin-Konfiguration über die Einstellung ``suspend_time_default`` -angegeben. Vorgabewert sind 3600 Sekunden (1 Stunde). Wenn die -Dauer der zeitweisen Deaktivierung für ein einzelnes Objekt-Item -abweichend sein soll, kann dort das Attribut - -.. code-block:: yaml - - se_suspend_time: - -angegeben werden. Der Parameter verwendet den Datentyp AbValue - -.. rubric:: Erweiterte Funktionen des "Manuell"-Items für den Suspend-Zustand - :name: erweiterte - -.. rubric:: Bestimmte Item-Änderungen nicht als "manuelle Bedienung" auswerten - :name: bestimmteitem - -In bestimmten Fällen ist es erforderlich, das Item-Änderungen, die -durch bestimmte Aufrufe ausgelöst werden, nicht als manuelle -Betätigung gewertet werden. Hierzu zählt zum Beispiel die -Rückmeldung der Raffstore-Position nach dem Verfahren durch den -Jalousieaktor. Hierfür stehen zwei für das Manuell-Item weitere -Attribute bereit: - -| **as_manual_include** -| *Liste der Aufrufe, die als "manuelle Betätigung" gewertet - werden sollen* - -| **as_manual_exclude** -| *Liste der Aufrufe, die nicht als "manuelle Betätigung" gewertet - werden sollen* - -Bei beiden Attributen wird eine Liste von Elementen angegeben. Die -einzelnen Elemente bestehen dabei aus dem Aufrufenden -(``Caller``) einem Doppelpunkt und der Quelle (``Source``). -Mehrere Elemente werden durch "|" getrennt bzw. im yaml als Liste deklariert. -Für ``Caller`` und ``Source`` kann dabei jeweils auch "*" angegeben werden, dies -bedeutet, dass der jeweilige Teil nicht berücksichtigt werd. - -Wenn bei der Prüfung festgestellt wird, dass ein Wert über eine -Eval-Funktionalität geändert wurde, so wird die Änderung -zurückverfolgt bis zur ursprünglichen Änderung, die die Eval-Kette -ausgelöst hat. Diese ursprüngliche Änderung wird dann geprüft. - -Der Wert von ``Caller`` zeigt an, welche Funktionalität das Item -geändert hat. Der Wert von ``Source`` ist Abhängig vom Caller. -Häufig verwendete ``Caller`` sind: - -- ``Init``: Initialisierung von smarthomeNG. ``Source`` ist - in der Regel leer -- ``Visu``: Änderung über die Visualisierung (Visu-Plugin). - ``Source`` beinhaltet die IP und den Port der Gegenstelle -- ``KNX``: Änderung über das KNX-Plugin. ``Source`` ist die - physische Adresse des sendenden Geräts - -Wenn ``se_manual_include`` oder ``se_manual_exclude`` angegeben -sind, muss ``se_manual_invert`` nicht angegeben werden. - -.. code-block:: yaml - - beispiel: - suspend: - manuell: - type: bool - name: Manuelle Bedienung - eval_trigger: - - beispiel.item1 - - beispiel.item2 - se_manual_exclude: - - KNX:1.1.42 - - Init:* - - -Hier werden alle Änderungen der Items ``beispiel.item1`` und -``beispiel.item2`` als manuelle Betätigung gewertet, sofern Sie -nicht durch das KNX-Gerät mit der physischen Adresse 1.1.42 oder -durch die Initialisierung von smarthomeNG erfolgt sind. - -.. rubric:: Erweitertes Logging für das Manuell-Item: - :name: erweitertesloggingfrdasmanuellitem - -Sofern im Manuell-Item die Attribute ``se_manual_include`` bzw. -``se_manual_exclude`` verwendet werden, ist auch hier eine -Protokollierung mittels des erweiterten Loggings möglich. Dazu -muss das Item, unter dem das Log geführt wird über das zusätzliche -Attribut ``se_manual_logitem`` angegeben werden. Hier wird man als -Item in der Regel das Manuell-Item angeben: - -.. code-block:: yaml - - beispiel: - suspend: - manuell: - .... - se_manual_logitem: beispiel.suspend.manuell - - -Wird statt ``se_manual_include`` oder ``se_manual_exclude`` nur -``se_manual_invert`` verwendet, ist kein erweitertes Logging -möglich. +| **se_detail ** +| *Zeigt Details zum Objekt Item* diff --git a/stateengine/user_doc/user_doc14.rst b/stateengine/user_doc/user_doc14.rst index 32e67addf..17a466929 100644 --- a/stateengine/user_doc/user_doc14.rst +++ b/stateengine/user_doc/user_doc14.rst @@ -1,19 +1,671 @@ -.. index:: Plugins; Stateengine; CLI -.. index:: CLI +.. index:: Plugins; Stateengine; Beispiel +.. index:: Beispiel -CLI -### +Beispiel +######## -.. rubric:: Zusätzliche Kommandos für das CLI Plugin - :name: cli +In diesem Beispiel soll die Automatisierung eines Raffstores +gezeigt werden. Folgende Zustände sollen abgedeckt werden: -Sofern die eingesetzte smarthomeNG-Version dies unterstützt, -registriert das stateengine-Plugin zwei eigene Kommandos beim -CLI-Plugin. +- Sperre über Sperr-Item +- Zeitweises Deaktivieren ("Suspend") bei manuellen Aktionen +- Nachführen der Lamellen zum Sonnenstand bei großer Helligkeit +- Nacht +- Morgens +- Abends +- Tag -| **se_list** -| *Zeigt eine Liste der Objekt-Items, für die das - stateengine-Plugin aktiv ist* +Dabei sollen möglichst viele Features des stateengine Plugins +verwendet werden -| **se_detail ** -| *Zeigt Details zum Objekt Item* +.. rubric:: Items zum Prüfen + :name: itemszumprfen + +Zuerst benötigen wir ein paar Items, die nachher als Bedingungen +abgeprüft werden sollen: + +.. code-block:: yaml + + beispiel: + steckdosen: + type: bool + + licht: + type: bool + + wetterstation: + helligkeit: + name: Helligkeit + type: num + + gt43k: + type: bool + name: Flag Helligkeit größer als 43 kLux + eval: sh.beispiel.wetterstation.helligkeit() > 43000 + eval_trigger: beispiel.wetterstation.helligkeit + + gt35k: + type: bool + name: Flag Helligkeit größer als 35 kLux + eval: sh.beispiel.wetterstation.helligkeit() > 35000 + eval_trigger: beispiel.wetterstation.helligkeit + + gt25k: + type: bool + name: Flag Helligkeit größer als 25 kLux + eval: sh.beispiel.wetterstation.helligkeit() > 25000 + eval_trigger: beispiel.wetterstation.helligkeit + + gt20k: + type: bool + name: Flag Helligkeit größer als 20 kLux + eval: sh.beispiel.wetterstation.helligkeit() > 20000 + eval_trigger: beispiel.wetterstation.helligkeit + + temperatur: + name: Temperatur + type: num + +.. rubric:: Trigger + :name: trigger + +Da wir mehrere Raffstores automatisieren wollen und alle +Raffstores gleichzeitig fahren sollen, brauchen wir einen externen +Trigger, auf den dann alle Automatiken hören: + +.. code-block:: yaml + + beispiel: + trigger: + raffstore: + type: bool + name: Gemeinsamer Trigger für alle Raffstores + enforce_updates: yes #Wichtig! + cycle: 300 = 1 + + +In diesem Fall wird die Zustandsermittlung alle 300 Sekunden (5 +Minuten) ausgelöst. + +.. rubric:: Default-Konfiguration + :name: defaultkonfiguration + +Nun kommt die Default-Konfiguration. Sie ist unabhängig von +konkreten zu automatisierenden Objekten. Sie beinhaltet jedoch +umfangreiche Einstellungen, so dass die zu automatisierenden +Objekte, die die Einstellungen aus der Default-Konfiguration +verwenden, oft sehr simpel aufgebaut werden können. + +.. code-block:: yaml + + beispiel: + default: + raffstore: + # Item für Helligkeit außen + se_item_brightness: beispiel.wetterstation.helligkeit + # Item für Temperatur außen + se_item_temperature: beispiel.wetterstation.temperatur + # Item das anzeigt, ob die Helligkeit außen mehr als 25kLux beträgt + se_item_brightnessGt25k: beispiel.wetterstation.helligkeit.gt25k + # Item das anzeigt, ob die Helligkeit außen mehr als 43kLux beträgt + se_item_brightnessGt43k: beispiel.wetterstation.helligkeit.gt43k + # Item für Behanghöhe + se_item_hoehe: ...hoehe + # Keine Änderung der Behanghöhe wenn Abweichung kleiner 10 + se_mindelta_hoehe: 10 + # Item für Lamellenwinkel + se_item_lamelle: ...lamelle + # Keine Änderung des Lamellenwinkels wenn Abweichung kleiner 5 + se_mindelta_lamelle: 5 + # "Manuell" Item + se_item_manuell: ..manuell + # "Lock" Item + se_item_lock: ..lock + # "Suspend" Item + se_item_suspend: ..suspend + + # Zustand "Sperre über Sperr-Item" + Lock: + type: foo + name: Automatik manuell gesperrt + # Aktionen: + # - "Suspend"-Item ggf. zurücksetzen + se_set_suspend: False + # sonst nichts tun + enter + # Einstieg in "Lock": Wenn + # - das "Lock"-Item gesetzt ist + se_value_lock: True + + # Zustand "Zeitweises Deaktivieren bei manuellen Aktionen" + Suspend: + type: foo + name: Ausgesetzt + + on_enter_or_stay: + se_action_suspend: + - 'function: special' + - 'value: suspend:..suspend, ..manuell' + - 'repeat: True' + - 'order: 1' + se_action_suspend_end: + - 'function: set' + - "to: eval:stateengine_eval.insert_suspend_time('..suspend', suspend_text='%X')" + - 'repeat: True' + - 'order: 2' + se_action_retrigger: + - 'function: set' + - 'to: True' + - 'delay: var:item.suspend_remaining' + - 'repeat: True' + - 'order: 3' + + on_leave: + se_action_suspend: + - 'function: set' + - 'to: False' + se_action_suspend_end: + - 'function: set' + - 'to: ' + + enter_manuell: + se_value_trigger_source: eval:stateengine_eval.get_relative_itemid('..manuell') + se_value_suspend_active: 'True' + + enter_stay: + name: Bedingung Im Suspend verbleiben + #Bedingung: Suspend ist aktiv + se_value_laststate: var:current.state_id + #Bedingung: Suspendzeit ist noch nicht abgelaufen + se_agemax_manuell: var:item.suspend_time + #Bedingung: Suspend-Item wurde nicht extern geändert + se_value_suspend: True + + # Zustand "Nachführen der Lamellen zum Sonnenstand bei großer Helligkeit", Gebäudeseite 1 + Nachfuehren_Seite_Eins: + type: foo + name: Tag (nachführen) + # Aktionen: + # - Behang ganz herunterfahren + se_set_hoehe: value:100 + # - Lamellen zur Sonne ausrichten + se_set_lamelle: eval:stateengine_eval.sun_tracking() + # - "Suspend"-Item ggf. zurücksetzen + se_set_suspend: False + + # Einstieg in "Nachführen": Wenn + enter: + # - das Flag "Helligkeit > 43kLux" seit mindestens 60 Sekunden gesetzt ist + se_value_brightnessGt43k: true + se_agemin_brightnessGt43k: 60 + # - die Sonnenhöhe mindestens 18° ist + se_min_sun_altitude: 18 + # - die Sonne aus Richtung 130° bis 270° kommt + se_min_sun_azimut: 130 + se_max_sun_azimut: 270 + # - es draußen mindestens 22° hat + se_min_temperature: 22 + + # Hysterese für Helligkeit: Wenn + enter_hysterese: + # ... wir bereits in "Nachführen" sind + se_value_laststate: var:current.state_id + # .... das Flag "Helligkeit > 25kLux" gesetzt ist + se_value_brightnessGt25k: true + # ... die Sonnenhöhe mindestens 18° ist + se_min_sun_altitude: 18 + # ... die Sonne aus Richtung 130° bis 270° kommt + se_min_sun_azimut: 130 + se_max_sun_azimut: 270 + # Anmerkung: Hier keine erneute Prüfung der Temperatur, damit Temperaturschwankungen nicht + # zum Auf-/Abfahren der Raffstores führen + + # Verzögerter Ausstieg nach Unterschreitung der Mindesthelligkeit: Wenn + enter_delay: + # ... wir bereits in "Nachführen" sind + se_value_laststate: var:current.state_id + # .... das Flag "Helligkeit > 25kLux" nicht (!) gesetzt ist, aber diese Änderung nicht mehr als 20 Minuten her ist + se_value_brightnessGt25k: false + se_agemax_brightnessGt25k: 1200 + # ... die Sonnenhöhe mindestens 18° ist + se_min_sun_altitude: 18 + # ... die Sonne aus Richtung 130° bis 270° kommt + se_min_sun_azimut: 130 + se_max_sun_azimut: 270 + # Anmerkung: Auch hier keine erneute Prüfung der Temperatur, damit Temperaturschwankungen nicht + # zum Auf-/Abfahren der Raffstores führen + + # Zustand "Nachführen der Lamellen zum Sonnenstand bei großer Helligkeit", Gebäudeseite 2 + Nachfuehren_Seite_Zwei: + type: foo + # Einstellungen des Vorgabezustands "Nachfuehren_Seite_Eins" übernehmen + se_use: beispiel.default.raffstore.Nachfuehren_Seite_Eins + + # Sonnenwinkel in den Bedingungsgruppen anpassen + enter: + # ... die Sonne aus Richtung 220° bis 340° kommt + se_min_sun_azimut: 220 + se_max_sun_azimut: 340 + + enter_hysterese: + # ... die Sonne aus Richtung 220° bis 340° kommt + se_min_sun_azimut: 220 + se_max_sun_azimut: 340 + + :enter_delay: + # ... die Sonne aus Richtung 220° bis 340° kommt + se_min_sun_azimut: 220 + se_max_sun_azimut: 340 + + # Zustand "Nacht" + Nacht: + type: foo + name: Nacht + # Aktionen: + # - Behang ganz herunterfahren + se_set_hoehe: value:100 + # - Lamellen ganz schließen + se_set_lamelle: value:0 + # - "Suspend"-Item ggf. zurücksetzen + se_set_suspend: False + + # Einstieg in "Nacht": Wenn + enter: + # - es zwischen 16:00 und 08:00 Uhr ist + se_min_time: '08:00' + se_max_time: '16:00' + se_negate_time: True + # - die Helligkeit höchstens 90 Lux beträgt + se_max_brightness: 90 + + # Zustand "Morgens" + Morgens: + type: foo + name: Dämmerung Morgens + # Aktionen: + # - Behang ganz herunterfahren + se_set_hoehe: value:100 + # - Lamellen ca 45° nach unten + se_set_lamelle: value:25 + # - "Suspend"-Item ggf. zurücksetzen + se_set_suspend: False + + # Einstieg in "Morgens": Wenn + enter: + # - die Helligkeit zwischen 90 und 250 Lux beträgt + se_min_brightness: 90 + se_max_brightness: 250 + # - es zwischen 00:00 und 12:00 Uhr ist + se_min_time: '00:00' + se_max_time: '12:00' + + # Zustand "Abends" + Abends: + type: foo + name: Dämmerung Abends + # Aktionen: + # - Behang ganz herunterfahren + se_set_hoehe: value:100 + # - Lamellen ca 45° nach oben + se_set_lamelle: value:75 + # - "Suspend"-Item ggf. zurücksetzen + se_set_suspend: False + + # Einstieg in "Abends": Wenn + enter: + # - die Helligkeit zwischen 90 und 250 Lux beträgt + se_min_brightness: 90 + se_max_brightness: 250 + # - es zwischen 12:00 und 24:00 Uhr ist + se_min_time: '12:00' + se_max_time: '24:00' + # Anmerkung: "24:00" ist eigentlich eine ungültige Zeit. Sie wird aber automatisch zu 23:59:59 umgewandelt + + # Zustand "Tag" + Tag: + type: foo + name: Tag (statisch) + # Aktionen: + # - Behang ganz hochfahren + se_set_hoehe: value:0 + # - Lamellen auf den Standardwert bei ganz hochgefahrenem Behang + se_set_lamelle: value:100 + # - "Suspend"-Item ggf. zurücksetzen + se_set_suspend: False + + # Einstieg in "Tag": Wenn + enter: + # - es zwischen 06:30 und 21:30 Uhr ist + se_min_time: '06:30' + se_max_time: '21:30' + + +.. rubric:: Automatisierung Raffstore 1 + :name: automatisierungraffstore1 + +Jetzt wollen wir den ersten Raffstore automatisieren. Einige Items +dazu haben wir sowieso schon, da der Raffstore über diese Items +gesteuert wird. + +.. code-block:: yaml + + beispiel: + raffstore1: + name: Raffstore Beispiel 1 + + aufab: + type: bool + name: Raffstore auf/ab fahren + enforce_updates: on + + step: + type: bool + name: Raffstore Schritt fahren/stoppen + enforce_updates: on + + hoehe: + type: num + name: Behanghöhe des Raffstores + + lamelle: + type: num + name: Lamellenwinkel des Raffstores + + +Jetzt kommen noch die Items zur Automatisierung und schließlich +das stateengine Objekt-Item hinzu: + +.. code-block:: yaml + + beispiel: + raffstore1: + automatik: + lock: + type: bool + name: Sperr-Item + visu_acl: rw + cache: on + + suspend: + type: bool + name: Suspend-Item + visu_acl: rw + # Achtung: Beim "Suspend"-Item niemals "enforce_updates = yes" setzen! Das führt dazu dass das Setzen des + # Suspend-Items bei der Initialisierung zu einem endlosen sofortigen Wiederaufruf der Statusermittlung führt! + + state_id: + type: str + name: Id des aktuellen Zustands + visu_acl: r + cache: on + + state_name: + type: str + name: Name des aktuellen Zustands + visu_acl: r + cache: on + + manuell: + type: bool + name: Manuelle Bedienung + # Änderungen dieser Items sollen als manuelle Bedienung gewertet werden + eval_trigger: + - beispiel.raffstore1.aufab + - beispiel.raffstore1.step + - beispiel.raffstore1.hoehe + - beispiel.raffstore1.lamelle + # Änderungen, die ursprünglich von diesen Triggern (:) ausgelöst wurden, sollen nicht als manuelle Bedienung gewertet werden + se_manual_exclude: + - KNX:y.y.y + - Init:* + + rules: + type: bool + name: Automatik Raffstore 1 + se_plugin: active + # Erste Zustandsermittlung nach 30 Sekunden + se_startup_delay: 30 + # Über diese Items soll die Statusermittlung ausgelöst werden + eval_trigger: beispiel.trigger.raffstore | beispiel.raffstore1.automatik.anwesenheit | beispiel.raffstore1.automatik.manuell | beispiel.raffstore1.automatik.lock | beispiel.raffstore1.automatik.suspend + # In dieses Item soll die Id des aktuellen Zustands geschrieben werden + se_laststate_item_id: ..state_id + # In dieses Item soll der Name des aktuellen Zustands geschrieben werden + se_laststate_item_name: ..state_name + + Lock: + # Zustand "Lock": Nur die Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Lock + + Suspend: + # Zustand "Suspend": Nur die Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Suspend + + Nachfuehren: + # Zustand "Nachfuehren": Nur die Vorgabeeinstellungen übernehmen (Gebäudeseite 2) + se_use: beispiel.default.raffstore.Nachfuehren_Seite_Zwei + + Nacht: + # Zustand "Nacht": Nur die Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Nacht + + Morgens: + # Zustand "Morgens": Nur die Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Morgens + + Abends: + # Zustand "Abends": Nur die Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Abends + + Tag: + # Zustand "Tag": Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Tag + + +.. rubric:: Automatisierung Raffstore 2 + :name: automatisierungraffstore2 + +Der zweite Raffstore ist ein komplexeres Beispiel. Hier werden +nicht nur die Vorgabewerte übernommen, hier werden komplett neue +Bedingungsgruppen definiert, sowie vorhandene Bedingungsgruppen +abgeändert. + +.. code-block:: yaml + + beispiel: + raffstore2: + name: Raffstore Beispiel 2 + + aufab: + type: bool + name: Raffstore auf/ab fahren + enforce_updates: on + + step: + type: bool + name: Raffstore Schritt fahren/stoppen + enforce_updates: on + + hoehe: + type: num + name: Behanghöhe des Raffstores + + lamelle: + type: num + name: Lamellenwinkel des Raffstores + + automatik: + lock: + type: bool + name: Sperr-Item + visu_acl: rw + cache: on + + suspend: + type: bool + name: Suspend-Item + visu_acl: rw + # Achtung: Beim "Suspend"-Item niemals "enforce_updates = yes" setzen! Das führt dazu dass das Setzen des + # Suspend-Items bei der Initialisierung zu einem endlosen sofortigen Wiederaufruf der Statusermittlung führt! + + state_id: + type: str + name: Id des aktuellen Zustands + visu_acl: r + cache: on + + state_name: + type: str + name: Name des aktuellen Zustands + visu_acl: r + cache: on + + manuell: + type: bool + name: Manuelle Bedienung + # Änderungen dieser Items sollen als manuelle Bedienung gewertet werden + eval_trigger: + - beispiel.raffstore2.aufab + - beispiel.raffstore2.step + - beispiel.raffstore2.hoehe + - beispiel.raffstore2.lamelle + # Änderungen, die ursprünglich von diesen Triggern (:) ausgelöst wurden, sollen nicht als manuelle Bedienung gewertet werden + se_manual_exclude: + - KNX:y.y.y + - Init:* + + anwesenheit: + type: bool + name: Anwesenheit im Raum + eval: or + eval_trigger: + - beispiel.steckdosen + - beispiel.licht + + rules: + type: bool + name: Automatik Raffstore 2 + se_plugin: active + # Erste Zustandsermittlung nach 30 Sekunden + se_startup_delay: 30 + # Über diese Items soll die Statusermittlung ausgelöst werden + eval_trigger: beispiel.trigger.raffstore | beispiel.raffstore2.automatik.anwesenheit | beispiel.raffstore2.automatik.manuell | beispiel.raffstore2.automatik.lock | beispiel.raffstore2.automatik.suspend + # In dieses Item soll die Id des aktuellen Zustands geschrieben werden + se_laststate_item_id: ..state_id + # In dieses Item soll der Name des aktuellen Zustands geschrieben werden + se_laststate_item_name: ..state_name + # Dieses Item zeigt die Anwesenheit im Raum + se_item_anwesend: ..anwesenheit + # Item das anzeigt, ob die Helligkeit außen mehr als 35kLux beträgt + se_item_brightnessGt35k: beispiel.wetterstation.helligkeit.gt35k + # Item das anzeigt, ob die Helligkeit außen mehr als 20Lux beträgt + se_item_brightnessGt20k: beispiel.wetterstation.helligkeit.gt20k + + Lock: + # Zustand "Lock": Nur die Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Lock + + Suspend: + # Zustand "Suspend": Nur die Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Suspend + + Nachfuehren: + # Zustand "Nachführen": Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Nachfuehren_Seite_Eins + + # ..und jetzt verändern wir das ganze, in dem wir abhängig vom "Anwesend"-Flag andere + # Grenzwerte für die Helligkeit setzen. + + # Erst definieren wir mal zusätzliche Einstiegsbedingungen, die die neuen Grenzwerte beinhalten: + :enter_anwesend: + # Einstieg in "Nachführen" bei Anwesenheit: Wenn + # - das Flag "Anwesenheit" gesetzt ist + se_value_anwesend: true + # - das Flag "Helligkeit > 35kLux" seit mindestens 60 Sekunden gesetzt ist (also 8k Lux früher als in "enter") + se_value_brightnessGt35k: true + se_agemin_brightnessGt35k: 60 + # - die Sonnenhöhe mindestens 15° ist (also 3° früher als in "enter") + se_min_sun_altitude: 15 + # - die Sonne aus Richtung 110° bis 270° kommt (also 20° früher als in "enter" + se_min_sun_azimut: 110 + se_max_sun_azimut: 270 + + enter_anwesend_hysterese: + # Hysterese für Helligkeit bei Anwesenheit: Wenn + # - das Flag "Anwesenheit" gesetzt ist + se_value_anwesend: true + # ... wir bereits in "Nachführen" sind + se_value_laststate: var:current.state_id + # .... das Flag "Helligkeit > 20kLux" gesetzt ist (also 5 kLux früher als in "enter_hysterese") + se_value_brightnessGt20k: true + # ... die Sonnenhöhe mindestens 15° ist (Übernahme aus "enter_anwesend") + se_min_sun_altitude: 15 + # ... die Sonne aus Richtung 110° bis 270° kommt (Übernahme aus "enter_anwesend") + se_min_sun_azimut: 110 + se_max_sun_azimut: 270 + + enter_anwesend_delay: + # Verzögerter Ausstieg nach Unterschreitung der Mindesthelligkeit bei Anwesenheit: Wenn + # - das Flag "Anwesenheit" gesetzt ist + se_value_anwesend: true + # ... wir bereits in "Nachführen" sind + se_value_laststate: var:current.state_id + # .... das Flag "Helligkeit > 20kLux" nicht (!) gesetzt ist, aber diese Änderung nicht mehr als 20 Minuten her ist + se_value_brightnessGt20k: false + se_agemax_brightnessGt20k: 1200 + # ... die Sonnenhöhe mindestens 15° ist (Übernahme aus "enter_anwesend") + se_min_sun_altitude: 15 + # ... die Sonne aus Richtung 110° bis 270° kommt (Übernahme aus "enter_anwesend") + se_min_sun_azimut: 110 + se_max_sun_azimut: 270 + + # Jetzt müssen wir die vorhandenen Bedingungen noch erweitern (sie gelten ja nur noch, wenn "Anwesenheit" nicht gesetzt ist) + enter: + # Einstieg in "Nachführen": Wenn zusätzlich + # - das Flag "Anwesenheit" nicht gesetzt ist + se_value_anwesend: false + + enter_hysterese: + # Hysterese für Helligkeit: Wenn zusätzlich + # - das Flag "Anwesenheit" nicht gesetzt ist + se_value_anwesend: false + + enter_delay: + # Verzögerter Ausstieg nach Unterschreitung der Mindesthelligkeit: Wenn zusätzlich + # - das Flag "Anwesenheit" nicht gesetzt ist + se_value_anwesend: false + + Nacht: + # Zustand "Nacht": Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Nacht + # .. und zwei weitere Einstiegsbedingungen definieren + + enter_schlafenszeit_woche: + # Einstieg in "Nacht": Wenn + # - es zwischen 21:00 und 07:00 Uhr ist + se_min_time: '07:00' + se_max_time: '21:00' + se_negate_time: True + # - der Wochentag zwischen Montag und Freitag liegt + se_min_weekday: 0 + se_max_weekday: 4 + + enter_schlafenszeit_wochenende: + # Einstieg in "Nacht": Wenn + # - es zwischen 21:00 und 08:30 Uhr ist + se_min_time: '08:30' + se_max_time: '21:00' + se_negate_time: True + # - der Wochentag Samstag oder Sonntag ist + se_value_weekday: 5 | 6 + + Morgens: + # Zustand "Morgens": Nur die Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Morgens + + Abends: + # Zustand "Abends": Nur die Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Abends + + Tag: + # Zustand "Tag": Vorgabeeinstellungen übernehmen + se_use: beispiel.default.raffstore.Tag diff --git a/stateengine/user_doc/user_doc15.rst b/stateengine/user_doc/user_doc15.rst deleted file mode 100644 index 76c63833b..000000000 --- a/stateengine/user_doc/user_doc15.rst +++ /dev/null @@ -1,675 +0,0 @@ -.. index:: Plugins; Stateengine; Beispiel -.. index:: Beispiel - -Beispiel -######## - -.. rubric:: Vollständiges Beispiel - :name: vollstndigesbeispiel - -In diesem Beispiel soll die Automatisierung eines Raffstores -gezeigt werden. Folgende Zustände sollen abgedeckt werden: - -- Sperre über Sperr-Item -- Zeitweises Deaktivieren ("Suspend") bei manuellen Aktionen -- Nachführen der Lamellen zum Sonnenstand bei großer Helligkeit -- Nacht -- Morgens -- Abends -- Tag - -Dabei sollen möglichst viele Features des stateengine Plugins -verwendet werden - -.. rubric:: Items zum Prüfen - :name: itemszumprfen - -Zuerst benötigen wir ein paar Items, die nachher als Bedingungen -abgeprüft werden sollen: - -.. code-block:: yaml - - beispiel: - steckdosen: - type: bool - - licht: - type: bool - - wetterstation: - helligkeit: - name: Helligkeit - type: num - - gt43k: - type: bool - name: Flag Helligkeit größer als 43 kLux - eval: sh.beispiel.wetterstation.helligkeit() > 43000 - eval_trigger beispiel.wetterstation.helligkeit - - gt35k: - type: bool - name: Flag Helligkeit größer als 35 kLux - eval: sh.beispiel.wetterstation.helligkeit() > 35000 - eval_trigger beispiel.wetterstation.helligkeit - - gt25k: - type: bool - name: Flag Helligkeit größer als 25 kLux - eval: sh.beispiel.wetterstation.helligkeit() > 25000 - eval_trigger beispiel.wetterstation.helligkeit - - gt20k: - type: bool - name: Flag Helligkeit größer als 20 kLux - eval: sh.beispiel.wetterstation.helligkeit() > 20000 - eval_trigger beispiel.wetterstation.helligkeit - - temperatur: - name: Temperatur - type: num - - -.. rubric:: Trigger - :name: trigger - -Da wir mehrere Raffstores automatisieren wollen und alle -Raffstores gleichzeitig fahren sollen, brauchen wir einen externen -Trigger, auf den dann alle Automatiken hören: - -.. code-block:: yaml - - beispiel: - trigger: - raffstore: - type: bool - name: Gemeinsamer Trigger für alle Raffstores - enforce_updates: yes - cycle: 300 = 1 - - -In diesem Fall wird die Zustandsermittlung alle 300 Sekunden (5 -Minuten) ausgelöst. - -.. rubric:: Default-Konfiguration - :name: defaultkonfiguration - -Nun kommt die Default-Konfiguration. Sie ist unabhängig von -konkreten zu automatisierenden Objekten. Sie beinhaltet jedoch -umfangreiche Einstellungen, so dass die zu automatisierenden -Objekte, die die Einstellungen aus der Default-Konfiguration -verwenden, oft sehr simpel aufgebaut werden können. - -.. code-block:: yaml - - beispiel: - default: - raffstore: - # Item für Helligkeit außen - se_item_brightness: beispiel.wetterstation.helligkeit - # Item für Temperatur außen - se_item_temperature: beispiel.wetterstation.temperatur - # Item das anzeigt, ob die Helligkeit außen mehr als 25kLux beträgt - se_item_brightnessGt25k: beispiel.wetterstation.helligkeit.gt25k - # Item das anzeigt, ob die Helligkeit außen mehr als 43kLux beträgt - se_item_brightnessGt43k: beispiel.wetterstation.helligkeit.gt43k - # Item für Behanghöhe - se_item_hoehe: ...hoehe - # Keine Änderung der Behanghöhe wenn Abweichung kleiner 10 - se_mindelta_hoehe: 10 - # Item für Lamellenwinkel - se_item_lamelle: ...lamelle - # Keine Änderung des Lamellenwinkels wenn Abweichung kleiner 5 - se_mindelta_lamelle: 5 - # "Manuell" Item - se_item_manuell: ..manuell - # "Lock" Item - se_item_lock: ..lock - # "Suspend" Item - se_item_suspend: ..suspend - - # Zustand "Sperre über Sperr-Item" - Lock: - type: foo - name: Automatik manuell gesperrt - # Aktionen: - # - "Suspend"-Item ggf. zurücksetzen - se_set_suspend: False - # sonst nichts tun - enter - # Einstieg in "Lock": Wenn - # - das "Lock"-Item gesetzt ist - se_value_lock: True - - # Zustand "Zeitweises Deaktivieren bei manuellen Aktionen" - Suspend: - type: foo - name: Ausgesetzt - - on_enter_or_stay: - se_action_suspend: - - 'function: special' - - 'value: suspend:..suspend, ..manuell' - - 'repeat: True' - - 'order: 1' - se_action_suspend_end: - - 'function: set' - - "to: eval:stateengine_eval.insert_suspend_time('..suspend', suspend_text='%X')" - - 'repeat: True' - - 'order: 2' - se_action_retrigger: - - 'function: set' - - 'to: True' - - 'delay: var:item.suspend_remaining' - - 'repeat: True' - - 'order: 3' - - on_leave: - se_action_suspend: - - 'function: set' - - 'to: False' - se_action_suspend_end: - - 'function: set' - - 'to: ' - - enter_manuell: - se_value_trigger_source: eval:stateengine_eval.get_relative_itemid('..manuell') - se_value_suspend_active: 'True' - - enter_stay: - name: Bedingung Im Suspend verbleiben - #Bedingung: Suspend ist aktiv - se_value_laststate: var:current.state_id - #Bedingung: Suspendzeit ist noch nicht abgelaufen - se_agemax_manuell: var:item.suspend_time - #Bedingung: Suspend-Item wurde nicht extern geändert - se_value_suspend: True - - # Zustand "Nachführen der Lamellen zum Sonnenstand bei großer Helligkeit", Gebäudeseite 1 - Nachfuehren_Seite_Eins: - type: foo - name: Tag (nachführen) - # Aktionen: - # - Behang ganz herunterfahren - se_set_hoehe: value:100 - # - Lamellen zur Sonne ausrichten - se_set_lamelle: eval:stateengine_eval.sun_tracking() - # - "Suspend"-Item ggf. zurücksetzen - se_set_suspend: False - - # Einstieg in "Nachführen": Wenn - enter: - # - das Flag "Helligkeit > 43kLux" seit mindestens 60 Sekunden gesetzt ist - se_value_brightnessGt43k: true - se_agemin_brightnessGt43k: 60 - # - die Sonnenhöhe mindestens 18° ist - se_min_sun_altitude: 18 - # - die Sonne aus Richtung 130° bis 270° kommt - se_min_sun_azimut: 130 - se_max_sun_azimut: 270 - # - es draußen mindestens 22° hat - se_min_temperature: 22 - - # Hysterese für Helligkeit: Wenn - enter_hysterese: - # ... wir bereits in "Nachführen" sind - se_value_laststate: var:current.state_id - # .... das Flag "Helligkeit > 25kLux" gesetzt ist - se_value_brightnessGt25k: true - # ... die Sonnenhöhe mindestens 18° ist - se_min_sun_altitude: 18 - # ... die Sonne aus Richtung 130° bis 270° kommt - se_min_sun_azimut: 130 - se_max_sun_azimut: 270 - # Anmerkung: Hier keine erneute Prüfung der Temperatur, damit Temperaturschwankungen nicht - # zum Auf-/Abfahren der Raffstores führen - - # Verzögerter Ausstieg nach Unterschreitung der Mindesthelligkeit: Wenn - enter_delay: - # ... wir bereits in "Nachführen" sind - se_value_laststate: var:current.state_id - # .... das Flag "Helligkeit > 25kLux" nicht (!) gesetzt ist, aber diese Änderung nicht mehr als 20 Minuten her ist - se_value_brightnessGt25k: false - se_agemax_brightnessGt25k: 1200 - # ... die Sonnenhöhe mindestens 18° ist - se_min_sun_altitude: 18 - # ... die Sonne aus Richtung 130° bis 270° kommt - se_min_sun_azimut: 130 - se_max_sun_azimut: 270 - # Anmerkung: Auch hier keine erneute Prüfung der Temperatur, damit Temperaturschwankungen nicht - # zum Auf-/Abfahren der Raffstores führen - - # Zustand "Nachführen der Lamellen zum Sonnenstand bei großer Helligkeit", Gebäudeseite 2 - Nachfuehren_Seite_Zwei: - type: foo - # Einstellungen des Vorgabezustands "Nachfuehren_Seite_Eins" übernehmen - se_use: beispiel.default.raffstore.Nachfuehren_Seite_Eins - - # Sonnenwinkel in den Bedingungsgruppen anpassen - enter: - # ... die Sonne aus Richtung 220° bis 340° kommt - se_min_sun_azimut: 220 - se_max_sun_azimut: 340 - - enter_hysterese: - # ... die Sonne aus Richtung 220° bis 340° kommt - se_min_sun_azimut: 220 - se_max_sun_azimut: 340 - - :enter_delay: - # ... die Sonne aus Richtung 220° bis 340° kommt - se_min_sun_azimut: 220 - se_max_sun_azimut: 340 - - # Zustand "Nacht" - Nacht: - type: foo - name: Nacht - # Aktionen: - # - Behang ganz herunterfahren - se_set_hoehe: value:100 - # - Lamellen ganz schließen - se_set_lamelle: value:0 - # - "Suspend"-Item ggf. zurücksetzen - se_set_suspend: False - - # Einstieg in "Nacht": Wenn - enter: - # - es zwischen 16:00 und 08:00 Uhr ist - se_min_time: '08:00' - se_max_time: '16:00' - se_negate_time: True - # - die Helligkeit höchstens 90 Lux beträgt - se_max_brightness: 90 - - # Zustand "Morgens" - Morgens: - type: foo - name: Dämmerung Morgens - # Aktionen: - # - Behang ganz herunterfahren - se_set_hoehe: value:100 - # - Lamellen ca 45° nach unten - se_set_lamelle: value:25 - # - "Suspend"-Item ggf. zurücksetzen - se_set_suspend: False - - # Einstieg in "Morgens": Wenn - enter: - # - die Helligkeit zwischen 90 und 250 Lux beträgt - se_min_brightness: 90 - se_max_brightness: 250 - # - es zwischen 00:00 und 12:00 Uhr ist - se_min_time: '00:00' - se_max_time: '12:00' - - # Zustand "Abends" - Abends: - type: foo - name: Dämmerung Abends - # Aktionen: - # - Behang ganz herunterfahren - se_set_hoehe: value:100 - # - Lamellen ca 45° nach oben - se_set_lamelle: value:75 - # - "Suspend"-Item ggf. zurücksetzen - se_set_suspend: False - - # Einstieg in "Abends": Wenn - enter: - # - die Helligkeit zwischen 90 und 250 Lux beträgt - se_min_brightness: 90 - se_max_brightness: 250 - # - es zwischen 12:00 und 24:00 Uhr ist - se_min_time: '12:00' - se_max_time: '24:00' - # Anmerkung: "24:00" ist eigentlich eine ungültige Zeit. Sie wird aber automatisch zu 23:59:59 umgewandelt - - # Zustand "Tag" - Tag: - type: foo - name: Tag (statisch) - # Aktionen: - # - Behang ganz hochfahren - se_set_hoehe: value:0 - # - Lamellen auf den Standardwert bei ganz hochgefahrenem Behang - se_set_lamelle: value:100 - # - "Suspend"-Item ggf. zurücksetzen - se_set_suspend: False - - # Einstieg in "Tag": Wenn - enter: - # - es zwischen 06:30 und 21:30 Uhr ist - se_min_time: '06:30' - se_max_time: '21:30' - - -.. rubric:: Automatisierung Raffstore 1 - :name: automatisierungraffstore1 - -Jetzt wollen wir den ersten Raffstore automatisieren. Einige Items -dazu haben wir sowieso schon, da der Raffstore über diese Items -gesteuert wird. - -.. code-block:: yaml - - beispiel: - raffstore1: - name: Raffstore Beispiel 1 - - aufab: - type: bool - name: Raffstore auf/ab fahren - enforce_updates: on - - step: - type: bool - name: Raffstore Schritt fahren/stoppen - enforce_updates: on - - hoehe: - type: num - name: Behanghöhe des Raffstores - - lamelle: - type: num - name: Lamellenwinkel des Raffstores - - -Jetzt kommen noch die Items zur Automatisierung und schließlich -das stateengine Objekt-Item hinzu: - -.. code-block:: yaml - - beispiel: - raffstore1: - automatik: - lock: - type: bool - name: Sperr-Item - visu_acl: rw - cache: on - - suspend: - type: bool - name: Suspend-Item - visu_acl: rw - # Achtung: Beim "Suspend"-Item niemals "enforce_updates = yes" setzen! Das führt dazu dass das Setzen des - # Suspend-Items bei der Initialisierung zu einem endlosen sofortigen Wiederaufruf der Statusermittlung führt! - - state_id: - type: str - name: Id des aktuellen Zustands - visu_acl: r - cache: on - - state_name: - type: str - name: Name des aktuellen Zustands - visu_acl: r - cache: on - - manuell: - type: bool - name: Manuelle Bedienung - # Änderungen dieser Items sollen als manuelle Bedienung gewertet werden - eval_trigger: - - beispiel.raffstore1.aufab - - beispiel.raffstore1.step - - beispiel.raffstore1.hoehe - - beispiel.raffstore1.lamelle - # Änderungen, die ursprünglich von diesen Triggern (:) ausgelöst wurden, sollen nicht als manuelle Bedienung gewertet werden - se_manual_exclude: - - KNX:y.y.y - - Init:* - - rules: - type: bool - name: Automatik Raffstore 1 - se_plugin: active - # Erste Zustandsermittlung nach 30 Sekunden - se_startup_delay: 30 - # Über diese Items soll die Statusermittlung ausgelöst werden - eval_trigger: beispiel.trigger.raffstore | beispiel.raffstore1.automatik.anwesenheit | beispiel.raffstore1.automatik.manuell | beispiel.raffstore1.automatik.lock | beispiel.raffstore1.automatik.suspend - # In dieses Item soll die Id des aktuellen Zustands geschrieben werden - se_laststate_item_id: ..state_id - # In dieses Item soll der Name des aktuellen Zustands geschrieben werden - se_laststate_item_name: ..state_name - - Lock: - # Zustand "Lock": Nur die Vorgabeeinstellungen übernehmen - se_use: beispiel.default.raffstore.Lock - - Suspend: - # Zustand "Suspend": Nur die Vorgabeeinstellungen übernehmen - se_use: beispiel.default.raffstore.Suspend - - Nachfuehren: - # Zustand "Nachfuehren": Nur die Vorgabeeinstellungen übernehmen (Gebäudeseite 2) - se_use: beispiel.default.raffstore.Nachfuehren_Seite_Zwei - - Nacht: - # Zustand "Nacht": Nur die Vorgabeeinstellungen übernehmen - se_use: beispiel.default.raffstore.Nacht - - Morgens: - # Zustand "Morgens": Nur die Vorgabeeinstellungen übernehmen - se_use: beispiel.default.raffstore.Morgens - - Abends: - # Zustand "Abends": Nur die Vorgabeeinstellungen übernehmen - se_use: beispiel.default.raffstore.Abends - - Tag: - # Zustand "Tag": Vorgabeeinstellungen übernehmen - se_use: beispiel.default.raffstore.Tag - - -.. rubric:: Automatisierung Raffstore 2 - :name: automatisierungraffstore2 - -Der zweite Raffstore ist ein komplexeres Beispiel. Hier werden -nicht nur die Vorgabewerte übernommen, hier werden komplett neue -Bedingungsgruppen definiert, sowie vorhandene Bedingungsgruppen -abgeändert. - -.. code-block:: yaml - - beispiel: - raffstore2: - name: Raffstore Beispiel 2 - - aufab: - type: bool - name: Raffstore auf/ab fahren - enforce_updates: on - - step: - type: bool - name: Raffstore Schritt fahren/stoppen - enforce_updates: on - - hoehe: - type: num - name: Behanghöhe des Raffstores - - lamelle: - type: num - name: Lamellenwinkel des Raffstores - - automatik: - lock: - type: bool - name: Sperr-Item - visu_acl: rw - cache: on - - suspend: - type: bool - name: Suspend-Item - visu_acl: rw - # Achtung: Beim "Suspend"-Item niemals "enforce_updates = yes" setzen! Das führt dazu dass das Setzen des - # Suspend-Items bei der Initialisierung zu einem endlosen sofortigen Wiederaufruf der Statusermittlung führt! - - state_id: - type: str - name: Id des aktuellen Zustands - visu_acl: r - cache: on - - state_name: - type: str - name: Name des aktuellen Zustands - visu_acl: r - cache: on - - manuell: - type: bool - name: Manuelle Bedienung - # Änderungen dieser Items sollen als manuelle Bedienung gewertet werden - eval_trigger: - - beispiel.raffstore2.aufab - - beispiel.raffstore2.step - - beispiel.raffstore2.hoehe - - beispiel.raffstore2.lamelle - # Änderungen, die ursprünglich von diesen Triggern (:) ausgelöst wurden, sollen nicht als manuelle Bedienung gewertet werden - se_manual_exclude: - - KNX:y.y.y - - Init:* - - anwesenheit: - type: bool - name: Anwesenheit im Raum - eval: or - eval_trigger: - - beispiel.steckdosen - - beispiel.licht - - rules: - type: bool - name: Automatik Raffstore 2 - se_plugin: active - # Erste Zustandsermittlung nach 30 Sekunden - se_startup_delay: 30 - # Über diese Items soll die Statusermittlung ausgelöst werden - eval_trigger: beispiel.trigger.raffstore | beispiel.raffstore2.automatik.anwesenheit | beispiel.raffstore2.automatik.manuell | beispiel.raffstore2.automatik.lock | beispiel.raffstore2.automatik.suspend - # In dieses Item soll die Id des aktuellen Zustands geschrieben werden - se_laststate_item_id: ..state_id - # In dieses Item soll der Name des aktuellen Zustands geschrieben werden - se_laststate_item_name: ..state_name - # Dieses Item zeigt die Anwesenheit im Raum - se_item_anwesend: ..anwesenheit - # Item das anzeigt, ob die Helligkeit außen mehr als 35kLux beträgt - se_item_brightnessGt35k: beispiel.wetterstation.helligkeit.gt35k - # Item das anzeigt, ob die Helligkeit außen mehr als 20Lux beträgt - se_item_brightnessGt20k: beispiel.wetterstation.helligkeit.gt20k - - Lock: - # Zustand "Lock": Nur die Vorgabeeinstellungen übernehmen - se_use: beispiel.default.raffstore.Lock - - Suspend: - # Zustand "Suspend": Nur die Vorgabeeinstellungen übernehmen - se_use: beispiel.default.raffstore.Suspend - - Nachfuehren: - # Zustand "Nachführen": Vorgabeeinstellungen übernehmen - se_use: beispiel.default.raffstore.Nachfuehren_Seite_Eins - - # ..und jetzt verändern wir das ganze, in dem wir abhängig vom "Anwesend"-Flag andere - # Grenzwerte für die Helligkeit setzen. - - # Erst definieren wir mal zusätzliche Einstiegsbedingungen, die die neuen Grenzwerte beinhalten: - :enter_anwesend: - # Einstieg in "Nachführen" bei Anwesenheit: Wenn - # - das Flag "Anwesenheit" gesetzt ist - se_value_anwesend: true - # - das Flag "Helligkeit > 35kLux" seit mindestens 60 Sekunden gesetzt ist (also 8k Lux früher als in "enter") - se_value_brightnessGt35k: true - se_agemin_brightnessGt35k: 60 - # - die Sonnenhöhe mindestens 15° ist (also 3° früher als in "enter") - se_min_sun_altitude: 15 - # - die Sonne aus Richtung 110° bis 270° kommt (also 20° früher als in "enter" - se_min_sun_azimut: 110 - se_max_sun_azimut: 270 - - enter_anwesend_hysterese: - # Hysterese für Helligkeit bei Anwesenheit: Wenn - # - das Flag "Anwesenheit" gesetzt ist - se_value_anwesend: true - # ... wir bereits in "Nachführen" sind - se_value_laststate: var:current.state_id - # .... das Flag "Helligkeit > 20kLux" gesetzt ist (also 5 kLux früher als in "enter_hysterese") - se_value_brightnessGt20k: true - # ... die Sonnenhöhe mindestens 15° ist (Übernahme aus "enter_anwesend") - se_min_sun_altitude: 15 - # ... die Sonne aus Richtung 110° bis 270° kommt (Übernahme aus "enter_anwesend") - se_min_sun_azimut: 110 - se_max_sun_azimut: 270 - - enter_anwesend_delay: - # Verzögerter Ausstieg nach Unterschreitung der Mindesthelligkeit bei Anwesenheit: Wenn - # - das Flag "Anwesenheit" gesetzt ist - se_value_anwesend: true - # ... wir bereits in "Nachführen" sind - se_value_laststate: var:current.state_id - # .... das Flag "Helligkeit > 20kLux" nicht (!) gesetzt ist, aber diese Änderung nicht mehr als 20 Minuten her ist - se_value_brightnessGt20k: false - se_agemax_brightnessGt20k: 1200 - # ... die Sonnenhöhe mindestens 15° ist (Übernahme aus "enter_anwesend") - se_min_sun_altitude: 15 - # ... die Sonne aus Richtung 110° bis 270° kommt (Übernahme aus "enter_anwesend") - se_min_sun_azimut: 110 - se_max_sun_azimut: 270 - - # Jetzt müssen wir die vorhandenen Bedingungen noch erweitern (sie gelten ja nur noch, wenn "Anwesenheit" nicht gesetzt ist) - enter: - # Einstieg in "Nachführen": Wenn zusätzlich - # - das Flag "Anwesenheit" nicht gesetzt ist - se_value_anwesend: false - - enter_hysterese: - # Hysterese für Helligkeit: Wenn zusätzlich - # - das Flag "Anwesenheit" nicht gesetzt ist - se_value_anwesend: false - - enter_delay: - # Verzögerter Ausstieg nach Unterschreitung der Mindesthelligkeit: Wenn zusätzlich - # - das Flag "Anwesenheit" nicht gesetzt ist - se_value_anwesend: false - - Nacht: - # Zustand "Nacht": Vorgabeeinstellungen übernehmen - se_use: beispiel.default.raffstore.Nacht - # .. und zwei weitere Einstiegsbedingungen definieren - - enter_schlafenszeit_woche: - # Einstieg in "Nacht": Wenn - # - es zwischen 21:00 und 07:00 Uhr ist - se_min_time: '07:00' - se_max_time: '21:00' - se_negate_time: True - # - der Wochentag zwischen Montag und Freitag liegt - se_min_weekday: 0 - se_max_weekday: 4 - - enter_schlafenszeit_wochenende: - # Einstieg in "Nacht": Wenn - # - es zwischen 21:00 und 08:30 Uhr ist - se_min_time: '08:30' - se_max_time: '21:00' - se_negate_time: True - # - der Wochentag Samstag oder Sonntag ist - se_value_weekday: 5 | 6 - - Morgens: - # Zustand "Morgens": Nur die Vorgabeeinstellungen übernehmen - se_use: beispiel.default.raffstore.Morgens - - Abends: - # Zustand "Abends": Nur die Vorgabeeinstellungen übernehmen - se_use: beispiel.default.raffstore.Abends - - Tag: - # Zustand "Tag": Vorgabeeinstellungen übernehmen - se_use: beispiel.default.raffstore.Tag diff --git a/stateengine/user_doc/user_doc2.rst b/stateengine/user_doc/user_doc2.rst index 41ef47ecc..6b6d277cd 100644 --- a/stateengine/user_doc/user_doc2.rst +++ b/stateengine/user_doc/user_doc2.rst @@ -1,115 +1,134 @@ -.. index:: Plugins; Stateengine; Pluginkonfiguration -.. index:: Pluginkonfiguration +.. index:: Plugins; Stateengine; Konfiguration +.. index:: Konfiguration -Pluginkonfiguration -################### +Konfiguration +############# -.. rubric:: Konfiguration des Plugins - :name: konfigurationdesplugins +.. important:: + + Detaillierte Informationen zur Konfiguration des Plugins sind unter :doc:`/plugins_doc/config/stateengine` zu finden. -Um das StateEngine Plugin zu verwenden müssen die folgenden Zeilen -in die plugin.yaml Datei der smarthomeNG Installation eingetragen -werden. +.. rubric:: Pluginkonfiguration + :name: pluginkonfiguration .. code-block:: yaml + #etc/plugin.yaml stateengine: - class_name: StateEngine - class_path: plugins.stateengine - #startup_delay_default: 10 - #suspend_time_default: 3600 - #log_level: 0 - #log_directory: var/log/StateEngine/ - #log_maxage: 0 - - -Auskommentierte Attribute sind Vorgabewerte, die nach den eigenen -Bedürfnissen angepasst werden können. - -| **startup_delay_default (optional):** -| *Vorgabewert für die Startverzögerung der ersten - Zustandsermittlung beim Start von smarthomeNG* - -Beim Starten von smarthomeNG dauert es üblicherweise einige -Sekunden, bis alle Items initialisiert sind. Um zu verhindern, -dass die erste Zustandsermittlung stattfindet, bevor alle Items -ihren Initialwert haben, wird die erste Zustandsermittlung -verzögert. Die Dauer der Verzögerung kann bei den Objekt-Items -angegeben werden. Wenn bei einem Objekt-Item kein Wert angegeben -ist, wird der hier angegebene Standardwert verwendet. Wenn kein -abweichender Standardwert in der Plugin-Konfiguration angegeben -ist, ist der Vorgabewert 10 Sekunden. - -Folgende Werte sind möglich: - -| *Zahl größer 0:* -| Angabe der Startverzögerung in Sekunden. Während der - Startverzögerung sind die Auslöser der Zustandsermittlung - inaktiv. Sie werden erst nach Ablauf der Startverzögerung und - der ersten Zustandsermittlung aktiviert. - -| *0:* -| Keine Startverzögerung. Die erste Zustandsermittlung wird direkt - nach der Initialisierung des Objekt-Items durchgeführt. - Anschließend werden die Auslöser für die Zustandsermittung - aktiviert. - -| *-1:* -| Es wird keine erste Zustandsermittlung durchgeführt. Nach der - Initialisierung des Objekt-Items sind alle Auslöser für die - Zustandsermittlung aktiv. - -| **suspend_time_default (optional):** -| *Vorgabezeit zur Unterbrechung der automatischen Steuerung nach - manuellen Aktionen* - -Nach manuellen Aktionen kann die Automatik für eine bestimmte Zeit -Unterbrochen werden. Die Dauer dieser Unterbrechungen kann bei den -Objekt-Items angegeben werden. Die Einheit für den Wert sind -Sekunden. Wenn bei einem Objekt-Item kein Wert angegeben ist, wird -der hier angegebene Standardwert verwendet. Wenn kein abweichender -Standardwert in der Plugin-Konfiguration angegeben ist, ist der -Vorgabewert 3600 Sekunden (1 Stunde) - -| **log_level(optional):** -| *Erweiterte Protokollierung: Loglevel (0: aus, 1: Info, 2: - Debug* - -Die erweiterte Protokollierung wird über das Setzen des Loglevels -auf 1 (Info) oder 2 (Debug) aktiviert. Wenn der Parameter nicht -angegeben ist, ist die erweiterte Protokollierung deaktiviert. - -| **log_directory (optional):** -| *Erweiterte Protokollierung: Verzeichnis für die - Protokolldateien* - -| Die Logdateien der erweiterten Protokollierung werden in das - hier angegebene Verzeichnis geschrieben. -| Wenn der angegebene Verzeichnisname mit "/" beginnt wird er als - absoluter Verzeichnisname behandelt. Alle anderen - Verzeichnisnamen werden als Unterverzeichnisse des smarthomeNG - Basisverzeichnisses behandelt. Das angegebene Verzeichnis wird - angelegt, wenn es nicht existiert. -| Wenn hier kein abweichendes Verzeichnis angegeben ist, wird das - Verzeichnis ``/var/log/AutoState/`` - verwendet. - -| **log_maxage (optional):** -| *Erweiterte Protokollierung: Anzahl der Tage, nach der die - Dateien im Verzeichnis ``log_directory`` wieder gelöscht - werden sollen* - -| Alte Protokolldateien können nach einer bestimmten Zeit - automatisch gelöscht werden. Diesen Parameter wird die Anzahl - der Tage festgelegt, nachdem die Dateien gelöscht werden sollen. - Das Löschen ist ausgesetzt solange der Parameter den Wert 0 hat. - Wenn der Parameter auf einen anderen Wert gesetzt wird, wird das - Alter der Dateien im Protokollverzeichnis ``log_directory`` - täglich geprüft und überalterte Dateien werden gelöscht. + plugin_name: stateengine + #startup_delay_default: 10 + #suspend_time_default: 3600 + #log_level: 0 + #log_directory: var/log/StateEngine/ + #log_maxage: 0 -.. important:: +.. rubric:: Objekt-Item + :name: objektitem + +Für jedes Item, für das eine State Machine angelegt werden soll, muss ein "Objekt-Item" erstellt werden. +Es wird empfohlen, dieses mit dem Namen ``rules`` als Child-Item unter das Item, das automatisiert werden soll, zu legen. +Im Beispiel wird zudem ein Item ``automatik`` definiert, da so auch die speziellen Items zur State Engine +übersichtlich gruppiert werden können. + +.. code-block:: yaml + + #items/item.yaml + beispiel: + raffstore1: + automatik: + rules: + type: bool + eval: True + #name: Automatik Raffstore 1 + se_plugin: active + se_laststate_item_id: beispiel.raffstore1.automatik.state_id + se_laststate_item_name: beispiel.raffstore1.automatik.state_name + #se_startup_delay: 30 + #se_repeat_actions: true + #se_suspend_time: 7200 + +Eine Neuermittlung des aktuellen Zustands wird jedesmal +durchgeführt, wenn ein Wert für das Objekt-Item geschrieben wird. +Somit können die Standardmöglichkeiten von smarthomeNG wie +``cycle``, ``crontab`` und ``eval_trigger`` verwendet +werden, um die Neuermittlung des aktuellen Zustands auszulösen. +Details zu diesen Attributen können der `smarthomeNG +Dokumentation `_ +entnommen werden. + +Bei jedem Aufruf des Objekt-Items werden die Zustände hierarchisch evaluiert. +Zuerst wird also der erste Status getestet. Kann dieser nicht aktiviert werden, +folgt der darunter angegebene, etc. Details hierzu finden sich im nächsten Teil +der Dokumentation. + +Ein vollständiges Objekt-Item könnte wie folgt aussehen: + +.. code-block:: yaml - Die Löschfunktionalität prüft und löscht alle - Dateien im Protokollverzeichnis, ob sie Protokolldateien sind - oder nicht. Daher sollten keine anderen Dateien in diesem - Verzeichnis abgelegt werden! + #items/item.yaml + beispiel: + raffstore1: + automatik: + settings: + suspendduration: + type: num + visu_acl: rw + cache: 'True' + + some_targetvalue: + type: num + visu_acl: rw + cache: 'True' + + stateengine_id: + type: str + visu_acl: r + cache: 'on' + + stateengine_name: + type: str + visu_acl: r + cache: 'on' + + stateengine_suspend_end: + type: str + visu_acl: ro + cache: 'on' + + lock: + type: bool + knx_dpt: 1 + visu_acl: rw + cache: 'on' + + suspend: + type: bool + knx_dpt: 1 + visu_acl: rw + cache: 'True' + + manuell: + type: bool + se_manual_invert: 'True' + se_manual_exclude: + - database:* + - KNX:1.1.4 + eval_trigger: + - taster1 + - taster2 + + rules: + type: bool + se_plugin: active + se_startup_delay: 300 + se_repeat_actions: False + se_laststate_item_id: ..stateengine_id + se_laststate_item_name: ..stateengine_name + se_item_suspend_end: ..stateengine_suspend_end + se_suspend_time: eval:stateengine_eval.get_relative_itemvalue('..settings.suspendduration') * 60 + eval: True + eval_trigger: + - some_trigger_object_id + + state1: + se_use: default.state1 #Wird in weiterer Folge erläutert diff --git a/stateengine/user_doc/user_doc3.rst b/stateengine/user_doc/user_doc3.rst index 8560830b2..3c3e002d0 100644 --- a/stateengine/user_doc/user_doc3.rst +++ b/stateengine/user_doc/user_doc3.rst @@ -1,204 +1,147 @@ -.. index:: Plugins; Stateengine; Objekt-Item -.. index:: Objekt-Item +.. index:: Plugins; Stateengine; Zustand-Item +.. index:: Zustand-Item -Objekt-Item -########### +Zustand-Item +############ -.. rubric:: Die Grundkonfiguration für eine Automatik: Das Objekt-Item - :name: diegrundkonfiguration +.. rubric:: Zustände: Das Zustands-Item + :name: daszustandsitem -Für jedes Objekt, dass mit dem StateEngine Plugin gesteuert werden -soll, ist ein Item erforderlich, dass alle Konfigurationsdaten für -dieses Objekt enthält. Dieses Item wird aus "Objekt-Item" -bezeichnet. Es können beliebig viele Objekt-Items und damit -beliebig viele Automatiken angelegt werden. - -.. rubric:: Grundlegende Einstellungen - :name: grundlegendeeinstellungen - -Über die folgenden Attribute werden die grundlegenden -Einstellungen für eine Automatik festgelegt +Alle Items unterhalb des Objekt-Items (z.B. ``rules``) +beschreiben Zustände des Objekts ("Zustands-Item"). +Die Ids der Zustands-Items sind +beliebig. Sie werden als Werte für das über +``se_laststate_item_id`` angegebene Item verwendet, um den +aktuellen Zustand abzulegen. .. code-block:: yaml beispiel: - raffstore1: - automatik: - rules: - type: bool - name: Automatik Raffstore 1 - se_plugin: active - se_startup_delay: 30 - se_laststate_item_id: beispiel.raffstore1.automatik.state_id - se_laststate_item_name: beispiel.raffstore1.automatik.state_name - se_repeat_actions: true - se_suspend_time: 7200 - - -| **type (obligatorisch):** -| *Datentp des Items* - -Für das Objekt-Item muss immer der Datentyp "bool" verwendet -werden + raffstore1: + automatik: + rules: + Tag: + name: Tag + se_name: eval: sh.eine_funktion() | **name (optional):** -| *Name des Items* - -Wenn das Attribut nicht angegeben ist, wird die Id des Items als -Name verwendet. - -| **se_plugin (obligatorisch):** -| *Kennzeichnet das Item als Objekt-Item des StateEngine-Plugins* - -Der Wert dieses Attributs muss zwingend ``active`` sein, damit -das Plugin das Item berücksichtigt. Zu Debuggingzwecken kann der -Wert dieses Attributs auf einen anderen Wert geändert werden, -dadurch wird das Plugin das Objekt ignorieren. - -| **se_startupdelay (optional):** -| *Startverzögerung der ersten Zustandsermittlung beim Start von - smarthomeNG* - -| Beim Starten von smarthomeNG dauert es üblicherweise einige - Sekunden, bis alle Items initialisiert sind. Um zu verhindern, - dass die erste Zustandsermittlung stattfindet, bevor alle Items - ihren Initialwert haben, wird die erste Zustandsermittlung - verzögert. Erst nach der ersten Zustandsermittlung werden alle - Auslöser und Funktionen vollständig aktiviert. - Zustandsermittlungen, die durch Items oder Timer vor Ablauf der - Startverzögerung ausgelöst werden, werden nicht durchgeführt. - Die zulässigen Werte für ``se_startup_delay`` sind identisch - mit den zulässigen Werten für den Plugin-Parameter - ``startup_delay_default``. -| Der Parameter verwendet den Datentyp AbValue - -| **se_laststate_item_id (optional):** -| *Id des Items, in dem die Id des aktuellen Zustands abgelegt wird* - -In das hier angegebene Item wird die Id des aktuellen Zustands -abgelegt. Das Item kann mit dem Attribut ``cache: yes`` -versehen werden, dann bleibt der vorherige Zustand bei einem -Neustart von smarthomeNG erhalten. Wenn das Item -``se_laststate_item_id`` nicht angegeben ist, wird der aktuelle -Zustand nur im Plugin gespeichert und geht mit einem Neustart von -smarthomeNG verloren. - -Sofern verwendet, sollte das Item für ``se_laststate_item_id`` -wie folgt definiert werden - -.. code-block:: yaml - - beispiel: - raffstore1: - automatik: - state_id: - type: str - name: Id des aktuellen Zustands - visu_acl: r - cache: yes - - -| **se_laststate_item_name (optional):** -| *Id des Items, in dem der Name des aktuellen Zustands abgelegt wird* - -In das hier angegebene Item wird der Name des aktuellen Zustands -abgelegt. Das Item kann für Displayzwecke verwendet werden. Wenn -das Item ``se_laststate_item_name`` nicht angegeben ist, steht -der Name des aktuellen Zustands nicht zur Verfügung - -Sofern verwendet, sollte das Item für ``se_laststate_item_name`` -wie folgt definiert werden - -.. code-block:: yaml - - beispiel: - raffstore1: - automatik: - state_name: - type: str - name: Name des aktuellen Zustands - visu_acl: r - cache: yes - - -| **se_repeat_actions (optional):** -| *Wiederholen der Aktionen bei unverändertem Zustand* - -Im Normalfall werden Aktionen jedesmal ausgeführt wenn der -aktuelle Zustand neu ermittelt wurde. Dies ist unabhängig davon, -ob sich der Zustand bei der Neuermittlung geändert hat oder nicht. -Dieses Verhalten kann über die Angabe von -``se_repeat_actions: false`` umgestellt werden. Wenn das -Attribut auf ``false`` gesetzt ist, werden Aktionen nur -ausgeführt, wenn sich der Zustand tatsächlich geändert hat. Der -Parameter verwendet den Datentyp AbValue - -| **se_suspendtime (optional):** -| *Zeit zur Unterbrechung der automatischen Steuerung nach - manuellen Aktionen* - -Nach manuellen Aktionen kann die Automatik für eine bestimmte Zeit -Unterbrochen werden. Die Dauer dieser Unterbrechungen wird hier -angegeben. Die Einheit für den Wert sind Sekunden. Wenn bei einem -Objekt-Item kein Wert angegeben ist, wird der in der -Pluginkonfiguration angegebene Standardwert -(se_suspend_time) verwendet. Der Parameter verwendet den -Datentyp AbValue - -.. rubric:: Einstellungen zum Auslösen der Zustandsermittlung - :name: einstellungenzumauslsenderzustandsermittlung - -Eine Neuermittlung des aktuellen Zustands wird jedesmal -durchgeführt, wenn ein Wert für das Objekt-Item geschrieben wird. -Somit können die Standardmöglichkeiten von smarthomeNG wie -``cycle``, ``crontab`` und ``eval_trigger`` verwendet -werden, um die Neuermittlung des aktuellen Zustands auszulösen. +| *Name des Zustands* +Der Name des Zustands wird im Protokoll sowie als Wert für das +über ``se_laststate_item_name`` angegebene Item verwendet. Wenn +kein Name angegeben ist, wird hier die Id des +Zustands-Items verwendet. + +| **se_name (optional):** +| *Ermittlung des Namens des Zustands* +| Über das Attribut ``se_name`` kann der im Attribut ``name`` angegebene Wert + überschrieben werden. Dies wirkt sich jedoch nur auf den Wert + aus, der in das über ``se_laststate_item_name`` angegebene + Item geschrieben wird. Im Protokoll wird immer der über das + Attribut ``name`` angegebene Wert verwendet. + +.. rubric:: Bedingungsgruppen + :name: bedingungsgruppen + +Jeder Zustand kann eine beliebige Anzahl von Bedingungsgruppen +haben. Jede Bedingungsgruppe definiert ein Set an Bedingungen das +überprüft wird, wenn der aktuelle Status neu ermittelt wird. +Sobald die Bedingungen einer Bedingungsgruppe vollständig erfüllt +sind, kann der Status aktiv werden. + +Jede Bedingungsgruppe wird durch ein Item +("Bedingungsgruppen-Item") unterhalb des Zustands-Items +abgebildet. Eine Bedingungsgruppe kann beliebig viele Bedingungen +umfassen. Bedingungen werden als Attribute im +Bedingungsgruppen-Item definiert. Details zu den Bedingungen +werden im Abschnitt :ref:`Bedingungen` erläutert. + +Die folgenden Regeln kommen zur Anwendung: + +- Zustände und Bedingungsgruppen werden in der Reihenfolge + geprüft, in der sie in der Konfigurationsdatei definiert sind. + +- Eine einzelne Bedingungsgruppe ist erfüllt, wenn alle + Bedingungen, die in der Bedingungsgruppe definiert sind, + erfüllt sind (UND-Verknüpfung). + +- Ein Zustand kann aktueller Zustand werden, wenn eine beliebige + der definierten Bedingungsgruppen des Zustands erfüllt ist. Die + Prüfung ist mit der ersten erfüllten Bedingungsgruppe beendet + (ODER-Verknüpfung). + +- Ein Zustand, der keine Bedingungsgruppen hat, kann immer + aktueller Zustand werden. Solch ein Zustand kann als + Default-Zustand am Ende der Zustände definiert werden. + +.. rubric:: Aktionen + :name: aktionen + +Jeder Zustand kann eine beliebige Anzahl an Aktionen definieren. +Sobald ein Zustand aktueller Zustand wird, werden die Aktionen des +Zustands ausgeführt. Für die Aktionen gibt es vier Ereignisse, die +festlegen, wann eine Aktion ausgeführt wird. + + Details zu den Aktionen werden im Abschnitt + :ref:`Aktionen` erläutert. + +.. rubric:: Items + :name: items + +Bedingungen und Aktionen beziehen sich überlicherweise auf Items. +Diese Items müssen auf Ebene des Objekt-Items über das Attribut +``se_item_`` bekannt gemacht werden. + +.. rubric:: Beispiel + :name: beispiel .. code-block:: yaml beispiel: - rafffstore2: - automatik: - rules: - <...> - cycle: 300 - crontab: - - 0 5 * * - - 0 6 * * - eval_trigger: - - beispiel.trigger.raffstore - - beispiel.raffstore2.automatik.anwesenheit - - -Details zu diesen Attributen können der `smarthomeNG -Dokumentation `_ -entnommen werden. - -Um die Konfiguration einfach zu halten, verändert das Plugin -einige Einstellungen des Objekt-Items. Folgende Erleichterungen -werden dabei vorgenommen: - -- Es ist nicht erforderlich mit ``cycle`` bzw. ``crontab`` - Werte anzugeben. Das StateEngine Plugin ergänzt diese - automatisch, sofern erforderlich. Statt ``cycle: 300 = 1`` ist - es ausreichend, wenn man ``cycle: 300`` angibt. - -- Es ist nicht erforderlich das Attribut ``eval = (irgendwas)`` - anzugeben, wenn ``eval_trigger`` verwendet wird. Das - StateEngine plugin ergänzt dies automatisch, sofern - erforderlich. - -- ``crontab: init`` funktioniert nicht für das StateEngine - Plugin. Die Neuberechnung des ersten Zustands nach dem Start - von smarthomeNG wird über das Attribut ``se_startup_delay`` - gesteuert. - -Es ist auch möglich andere Wege zu verwenden, um den Wert des -Objekt-Items zu setzen: - -- Zuweisung einer hörenden KNX Gruppenadresse zum Objekt-Item und - Senden eines Wertes auf diese Gruppenadresse. - -- Setzen des Werts des Objekt-Items aus einer Logik, einer - anderen Automatik oder sogar aus der selben Automatik (ggf. mit - Verzögerung). + raffstore1: + automatik: + rules: + + se_mindelta_lamella: 10 + se_item_height: beispiel.raffstore1.hoehe + se_item_lamella: beispiel.raffstore1.lamelle + se_item_brightness: beispiel.wetterstation.helligkeit + + Nacht: + name: Nacht + on_enter_or_stay: + se_set_height: 100 + se_set_lamella: 100 + enter_toodark: + se_max_brightness: 25 + enter_toolate: + + + Tag: + name: Tag + on_enter_or_stay: + se_set_hoehe: 0 + enter: + + +| **Attribute se_item_height und se_item_lamella:** +| *Definition der Items, die durch die Aktionen + se_set_height und se_set_lamella verändert werden* +Die Items werden durch ihre Item-Id angegeben + +| **Attribut name:** +| *Name des Zustands* +Der Name wird in das über ``se_laststate_item_name`` definierte +Item geschrieben, wenn der Zustand aktueller Zustand wird. Dieser +Wert kann z. B. in einer Visualisierung dargestellt werden. + +| **Attribute se_set_height und se_set_lamella:** +| *Neu zu setzende Werte für die Items, die über + se_item_height und se_item_lamella festgelegt wurden* + +| **Attribut se_mindelta_lamella:** +| *Nur, wenn sich Lamellen min. um x Grad ändern würden, werden sie aktualisiert.* + +| **Untergeordnete Items enter, enter_toodark und + enter_toolate:** +| *Bedingungsgruppen die erfüllt sein müssen, damit ein Zustand + aktueller Zustand werden kann* diff --git a/stateengine/user_doc/user_doc4.rst b/stateengine/user_doc/user_doc4.rst index 053436cc6..f68f09b43 100644 --- a/stateengine/user_doc/user_doc4.rst +++ b/stateengine/user_doc/user_doc4.rst @@ -1,119 +1,133 @@ -.. index:: Plugins; Stateengine; Zustand-Item -.. index:: Zustand-Item +.. index:: Plugins; Stateengine; Bedingungen +.. index:: Bedingungen +.. _Bedingungen: -Zustand-Item -############ +Bedingungen +########### -.. rubric:: Zustände: Das Zustands-Item - :name: daszustandsitem +.. rubric:: Grundlagen + :name: grundlagen -Alle Items unterhalb des Objekt-Items beschreiben Zustände des -Objekts ("Zustands-Item"). Die Ids der Zustands-Items sind -beliebig. Sie werden als Werte für das über -``se_laststate_item_id`` angegebene Item verwendet um den -aktuellen Zustand abzulegen. +Jede Bedingung erfordert drei Dinge: + +- Einen Namen, der die Bedingung und die zugehörigen Elemente + identifiziert +- Grenzwerte um zu prüfen, ob die Bedingung erfüllt ist +- Eine Möglichkeit, den aktuellen Wert zu ermitteln, gegen den die + Grenzwerte geprüft werden + +.. rubric:: Name der Bedingung + :name: namederbedingung + +Der Name der Bedingung ist beliebig und wird lediglich zur +Benennung der Attribute verwendet. Die Namen aller Attribute, die +zu einer Bedingung gehören, folgen dem Muster +``se__``. Es gibt verschiedene +"besondere" Bedingungsnamen, die später erläutert werden. + +.. rubric:: Grenzwerte + :name: grenzwerte + +Die Grenzwerte einer Bedingung werden in den Bedingungsgruppen +definiert. Die folgenden Grenzwerte sind möglich: + +**Minimum** .. code-block:: yaml - beispiel: - raffstore1: - automatik: - rules: - Tag: - type: foo - name: Tag - se_name: eval: sh.eine_funktion() + se_min_: [Wert] +Die Bedingung ist erfüllt, wenn der aktuelle Wert größer als das +angegebene Minimum ist. -| **type (obligatorisch):** -| *Datentp des Items* +**Maximum** -Für das Zustands-Item muss immer der Datentyp "foo" verwendet -werden +.. code-block:: yaml -| **name (optional):** -| *Name des Zustands* + se_max_: [Wert] -Der Name des Zustands wird im Protokoll sowie als Wert für das -über ``se_laststate_item_name`` angegebene Item verwendet. Wenn -kein Name angegeben ist, wird hier ebenfalls die Id des -Zustands-Items verwendet. +Die Bedingung ist erfüllt, wenn der aktuelle Wert kleiner als das +angegebene Maximum ist. -| **se_name (optional):** -| *Ermittlung des Namens des Zustands* +**Bestimmter Wert** -| Über das Attribut ``se_name`` kann der im Attribut ``name`` - überschrieben werden. Dies wirkt sich jedoch nur auf den Wert - aus, der in das über ``se_laststate_item_name`` angegebene - Item geschrieben wird. Im Protokoll wird immer der über das - Attribut ``name`` angegebene Wert verwendet. -| Der Parameter verwendet den Datentyp AbValue +.. code-block:: yaml -.. rubric:: Bedingungsgruppen - :name: bedingungsgruppen + se_value_: [Wert] -Jeder Zustand kann eine beliebige Anzahl von Bedingungsgruppen -haben. Jede Bedingungsgruppe definiert ein Set an Bedingungen das -überprüft wird, wenn der aktuelle Status neu ermittelt wird. -Sobald die Bedingungen einer Bedingungsgruppe vollständig erfüllt -sind, kann der Status aktiv werden. +Die Bedingung ist erfüllt, wenn der aktuelle Wert gleich dem +angegebenen Wert oder gleich einem der in einer Liste angegebenen Wert ist. -Jede Bedingungsgruppe wird durch ein Item -("Bedingungsgruppen-Item") unterhalb des Zustands-Items -abgebildet. Eine Bedingungsgruppe kann beliebig viele Bedingungen -umfassen. Bedingungen werden als Attribute im -Bedingungsgruppen-Item definiert. Details zu den Bedingungen -werden im Abschnitt :ref:`Bedingungen` erläutert. +.. code-block:: yaml -Die folgenden Regeln kommen zur Anwendung: + se_value_: + - [Wert1] + - [Wert2] + - [WertN] -- Zustände und Bedingungsgruppen werden in der Reihenfolge - geprüft, in der sie in der Konfigurationsdatei definiert sind. +**Negieren** -- Eine einzelne Bedingungsgruppe ist erfüllt, wenn alle - Bedingungen, die in der Bedingungsgruppe definiert sind, - erfüllt sind (UND-Verknüpfung). Einschränkungen, die in der - Bedingungsgruppe nicht definiert sind, werden nicht geprüft. +.. code-block:: yaml -- Ein Zustand kann aktueller Zustand werden, wenn eine beliebige - der definierten Bedingungsgruppen des Zustands erfüllt ist. Die - Prüfung ist mit der ersten erfüllten Bedingungsgruppe beendet - (ODER-Verknüpfung). + se_negate_: True|False -- Ein Zustand der keine Bedingungsgruppen hat kann immer - aktueller Zustand werden. Solch ein Zustand kann als - Default-Zustand am Ende der Zustände definiert werden. +Die gesamte Bedingung (Minimum, Maximum und Wert) wird negiert +(umgekehrt). Für das Attribut wird der Datentyp Boolean verwendet, +zulässige Werte sind "true", "1", "yes", "on" bzw. "false", "0", +"no", "off" -.. rubric:: Aktionen - :name: aktionen +**Mindestalter** -Jeder Zustand kann eine beliebige Anzahl an Aktionen definieren. -Sobald ein Zustand aktueller Zustand wird werden die Aktionen des -Zustands ausgeführt. Für die Aktionen gibt es vier Ereignisse, die -festlegen, wann eine Aktion ausgeführt wird: +.. code-block:: yaml + + se_agemin_: [Wert] + +Die Bedingung ist erfüllt, wenn das Alter des Items, dass zur +Ermittlung des Werts angegeben ist, größer als das angegebene +Mindestalter ist. + +**Höchstalter** + +.. code-block:: yaml + + se_agemax_: [Wert] + +Die Bedingung ist erfüllt, wenn das Alter des Items, dass zur +Ermittlung des Werts angegeben ist, kleiner als das angegebene +Höchstalter ist. -- **on_enter**: Aktionen, die beim erstmaligen Aktivieren des - Zustands ausgeführt werden +**Altersbedingung negieren** + +.. code-block:: yaml -- **on_stay**: Aktionen, die ausgeführt werden, wenn der Zustand - zuvor bereits aktiv war und weiterhin aktiv bleibt. + se_agenegate_: True|False -- **on_enteror_stay**: Aktionen, die ausgeführt werden, wenn der - Zustand aktiv ist, unabhängig davon, ob er bereits zuvor aktiv - war oder nicht. +Die Altersbedingung (Mindestalter, Höchstalter) wird negiert +(umgekehrt). Für das Attribut wird der Datentyp Boolean verwendet, +zulässige Werte sind "true", "1", "yes", "on" bzw. "false", "0", +"no", "off" -- **on_leave**: Aktionen, die ausgeführt werden, direkt bevor ein - anderer Zustand aktiv wird. +.. rubric:: Bereitstellung des zu setzenden Werts + :name: bereitstellungdesaktuellenwerts - Details zu den Aktionen werden im Abschnitt - :ref:`Aktionen` erläutert. +Der zu setzende Wert kann entweder über einen statischen Wert, ein Item oder über eine +Eval-Funktion bereitgestellt werden. Wenn beides angegeben ist, +wird das Item verwendet und die Eval-Funktion ignoriert. -.. rubric:: Items - :name: items +Der Name des Items, über das der aktuelle Wert abgerufen werden +soll, wird auf Ebene des Objekt-Items über das Attribut +``se_item_`` angegeben. Die Eval-Funktion, über +die der aktuelle Wert abgerufen werden soll, wird auf Ebene des +Objekt-Items über das Attribut +``se_eval_`` angegeben. Der Bedingungsname +in ``se_item`` bzw. ``se_eval`` +muss mit den Bedingungsnamen in den Bedingungen korrespondieren. -Bedingungen und Aktionen beziehen sich überlicherweise auf Items. -Diese Items müssen auf Ebene des Objekt-Items über das Attribut -``se_item_`` bekannt gemacht werden. +Da sich Altersbedingungen auf das Alter der hinterlegten Items +beziehen, können ``se_agemin_``, +``se_agemax_`` und +``se_agenegate_`` nur verwendet werden, wenn der +aktuelle Wert über ein Item bereitgestellt wird. .. rubric:: Beispiel :name: beispiel @@ -121,45 +135,121 @@ Diese Items müssen auf Ebene des Objekt-Items über das Attribut .. code-block:: yaml beispiel: - raffstore1: - automatik: - rules: - - - Tag: - type: foo - name: Tag - - enter: - - Nacht: - type: foo - name: Nacht - - enter_toodark: - - enter_toolate: - - - -| **Attribute se_item_height und se_item_lamella:** -| *Definition der Items, die durch die Aktionen - se_set_height und se_set_lamella verändert werden* - -Die Items werden durch ihre Item-Id angegeben - -| **Attribut nam:** -| *Name des Zustands* - -Der Name wird in das über ``se_laststate_item_name`` definierte -Item geschrieben, wenn der Zustand aktueller Zustand wird. Dieser -Wert kann z. B. in einer Visualisierung dargestellt werden. - -| **Attribute se_set_height und se_set_leave:** -| *Neue statische Werte für die Items die über - se_item_height und se_item_leave festgelegt wurden* - -| **Untergeordnete Items enter, enter_toodark und - enter_toolate:** -| *Bedingungsgruppen die erfüllt sein müssen, damit ein Zustand - aktueller Zustand werden kann* + raffstore1: + automatik: + rules: + <...> + se_item_height: beispiel.raffstore1.hoehe + se_item_lamella: beispiel.raffstore1.lamelle + se_item_brightness: beispiel.wetterstation.helligkeit + Daemmerung: + type: foo + name: Dämmerung + + enter: + se_min_brightness: 500 + se_max_brightness: value:1000 + + Nacht: + type: foo + name: Nacht + + enter_toodark: + se_max_brightness: 500 + + Sonder: + type: foo + name: Ein spezielles Bedingungsset + + enter: + se_min_brightness: item:test.wert + se_max_brightness: eval:sh.test.wert() + 500 + + +.. rubric:: "Besondere" Bedingungen + :name: besonderebedingungen + +Das Plugin stellt die Werte für einige "besondere" Bedingungen +automatisch bereit. Für diese Bedingungen muss daher kein Item und +keine Eval-Funktion zur Ermittlung des aktuellen Werts angegeben +werden. Die "besonderen" Bedingungen werden über reservierte +Bedingungsnamen gekennzeichnet. Diese Bedingungsnamen dürfen daher +nicht für andere Bedingungen verwendet werden. + +Die folgenden "besonderen" Bedingungsnamen können verwendet werden + +**time** +*Aktuelle Uhreit* +Die Werte für ``se_value_time``, ``se_min_time`` und +``se_max_time`` müssen im Format "hh:mm" (":") angegeben werden. +Es wird ein 24 Stunden-Zeitformat verwendet. Beispiele: "08:00" +oder "13:37". Um das Ende des Tages anzugeben kann der Wert +"24:00" verwendet werden, der für die Prüfungen automatisch zu +"23:59:59" konvertiert wird. Wichtig sind die Anführungszeichen +oder Hochkommas! + +**weekday** +*Wochentag* +0 = Montag, 1 = Dienstag, 2 = Mittwoch, 3 = Donnerstag, 4 = +Freitag, 5 = Samstag, 6 = Sonntag + +**month** +*Monat* +1 = Januar, ..., 12 = Dezember + +**sun_azimut** +*Sonnenstand (Horizontalwinkel)* +Der Azimut (Horizontalwinkel) ist die Kompassrichtung, in der die +Sonne steht. Der Azimut wird von smarthomeNg auf Basis der +aktuellen Zeit sowie der konfigurierten geographischen Position +berechnet. Siehe auch `SmarthomeNg +Dokumentation `_ +für Voraussetzungen zur Berechnung der Sonnenposition. +Beispielwerte: 0 → Sonne exakt im Norden, 90 → Sonne exakt im +Osten, 180 → Sonne exakt im Süden, 270 → Sonne exakt im Westen + +**sun_altitude** +*Sonnenstand (Vertikalwinkel)* +Die Altitude (Vertikalwikel) ist der Winkel, in dem die Sonne über +dem Horizont steht. Die Altitude wird von smarthomeNg auf Basis +der aktuellen Zeit sowie der konfigurierten geographischen +Position berechnet. Siehe auch `SmarthomeNG +Dokumentation `_ +für Voraussetzungen zur Berechnung der Sonnenposition. Werte: +negativ → Sonne unterhalb des Horizonts, 0 → +Sonnenaufgang/Sonnenuntergang, 90 → Sonne exakt im Zenith +(passiert nur in äquatorialen Bereichen) + +**age** +*Zeit seit der letzten Änderung des Zustands (Sekunden)* +Das Alter wird über die letzte Änderung des Items, das als +``se_laststate_item_id`` angegeben ist, ermittelt. + +**random** +*Zufallszahl zwischen 0 und 100* +Wenn etwas zufällig mit einer Wahrscheinlichkeit von 60% passieren +soll, kan beispielsweise die Bedingung ``max_random: 60`` +verwendet werden. + +**laststate** +*Id des Zustandsitems des aktuellen Status* +Wichtig: Hier muss die vollständige Item-Id angegeben werden + +**trigger_item, trigger_caller, trigger_source, trigger_dest** +*item, caller, source und dest-Werte, durch die die +Zustandsermittlung direkt ausgelöst wurde* +Über diese vier Bedingungen kann der direkte Auslöser der +Zustandsermittlung abgeprüft werden, also die Änderung, die +smarthomeNG veranlasst, die Zustandsermittlung des +stateengine-Plugins aufzurufen. + +**original_item, original_caller, original_source** +*item, caller, source und dest-Werte, durch die die +Zustandsermittlung ursprünglich ausgelöst wurde* +Über diese vier Bedingungen kann der ursprüngliche Auslöser der +Zustandsermittlung abgeprüft werden. Beim Aufruf der +Zustandsermittung über einen ``eval_trigger`` Eintrag wird über +``trigger_caller`` beispielsweise nur ``Eval`` weitergegeben. +In den drei ``original_*`` Bedingungen wird in diesem Fall der +Auslöser der Änderung zurückverfolgt und der Einstieg in die +``Eval``-Kette ermittelt. diff --git a/stateengine/user_doc/user_doc5.rst b/stateengine/user_doc/user_doc5.rst index a6e51ef92..1e7c0fb2b 100644 --- a/stateengine/user_doc/user_doc5.rst +++ b/stateengine/user_doc/user_doc5.rst @@ -1,300 +1,83 @@ -.. index:: Plugins; Stateengine; Bedingungen -.. index:: Bedingungen -.. _Bedingungen: +.. index:: Plugins; Stateengine; Ausführungszeitpunkt +.. index:: Ausführungszeitpunkt -Bedingungen -########### +Ausführungszeitpunkt +#################### -.. rubric:: Bedingungen - :name: bedingungen +Um festzulegen, wann die Aktionen eines Zustands ausgeführt +werden, gibt es vier Ereignisse, denen die Aktionen zugeordnet +werden können: Für jedes dieser Ereignisse wird ein Item unterhalb +des Zustands-Items angelegt, unterhalb dem die jeweiligen Aktionen +als Attribute definiert werden. -Jede Bedingung erfordert drei Dinge: +- **on_enter**: Aktionen, die nur beim erstmaligen Aktivieren des + Zustands ausgeführt werden -- Einen Namen der die Bedingung und die zugehörigen Elemente - identifiziert -- Grenzwerte um zu prüfen, ob die Bedingung erfüllt ist -- Eine Möglichkeit den aktuellen Wert zu ermitteln, gegen den die - Grenzwerte geprüft werden +- **on_stay**: Aktionen, die nur ausgeführt werden, wenn der Zustand + zuvor bereits aktiv war und weiterhin aktiv bleibt. -.. rubric:: Name der Bedingung - :name: namederbedingung +- **on_enter_or_stay**: Aktionen, die ausgeführt werden, wenn der + Zustand aktiv ist, unabhängig davon, ob er bereits zuvor aktiv + war oder nicht. -Der Name der Bedingung ist beliebig und wird lediglich zur -Benennung der Attribute verwendet. Die Namen aller Attribute, die -zu einer Bedingung gehören, folgen dem Muster -``se__``. Es gibt verschiedene -"besondere" Bedingungsnamen, die später erläutert werden. +- **on_leave**: Aktionen, die ausgeführt werden, direkt bevor ein + anderer Zustand aktiv wird. -.. rubric:: Grenzwerte - :name: grenzwerte +Aktionen können auch direkt im Zustands-Item definiert werden. +Solche Aktionen werden analog zum Ereignis ``on_enter_or_stay`` behandelt. -Die Grenzwerte einer Bedingung werden in den Bedingungsgruppen -definiert. Die folgenden Grenzwerte sind möglich: - -.. rubric:: Minimum - :name: minimum - -.. code-block:: yaml - - se_min_: [Wert] - -Die Bedingung ist erfüllt, wenn der aktuelle Wert großer als das -angegebene Minimum ist. Fur das Attribut wird der Datentyp -AbValue verwendet. - -.. rubric:: Maximum - :name: maximum - -.. code-block:: yaml - - se_max_: [Wert] - -Die Bedingung ist erfüllt, wenn der aktuelle Wert kleiner als das -angegebene Maximum ist. Fur das Attribut wird der Datentyp -AbValue verwendet. - -.. rubric:: Bestimmter Wert - :name: bestimmterwert - -.. code-block:: yaml - - se_value_: [Wert] - -Die Bedingung ist erfüllt, wenn der aktuelle Wert gleich dem -angegebenen Wert ist. Fur das Attribut wird der Datentyp -AbValue verwendet. - -Für den Fall, dass der Wert aus Festwerten stammt (``[Wert]`` -ist ``value: [Festwert]``) kann auch eine Wertliste angegeben -werden: - -.. code-block:: yaml - - se_value_: value:[Wert1]|[Wert2]|(...)[WertN] - -In diesem Fall ist die Bedingung erfüllt, wenn der aktuelle Wert -in der Wertliste enthalten ist. - -.. rubric:: Negieren - :name: negieren +**Beispiel** .. code-block:: yaml - se_negate_: True|False - -Die gesamte Bedingung (Minimum, Maximum und Wert) wird negiert -(umgekehrt). Für das Attribut wird der Datentyp Boolean verwendet, -zulässige Werte sind "true", "1", "yes", "on" bzw. "false", "0", -"no", "off" - -.. rubric:: Mindestalter - :name: mindestalter - -.. code-block:: yaml - - se_agemin_: [Wert] - -Die Bedingung ist erfüllt, wenn das Alter des Items, dass zur -Ermittlung des Werts angegeben ist, größer als das angegebene -Mindestalter ist. Fur das Attribut wird der Datentyp -AbValue verwendet. - -.. rubric:: Höchstalter - :name: hchstalter - -.. code-block:: yaml - - se_agemax_: [Wert] - -Die Bedingung ist erfüllt, wenn das Alter des Items, dass zur -Ermittlung des Werts angegeben ist, kleiner als das angegebene -Höchstalter ist. Fur das Attribut wird der Datentyp -AbValue verwendet. - -.. rubric:: Altersbedingung negieren - :name: altersbedingungnegieren - -.. code-block:: yaml - - se_agenegate_: True|False - -Die Altersbedingung (Mindestalter, Höchstalter) wird negiert -(umgekehrt). Fur das Attribut wird der Datentyp Boolean verwendet, -zulässige Werte sind "true", "1", "yes", "on" bzw. "false", "0", -"no", "off" - -.. rubric:: Bereitstellung des aktuellen Werts - :name: bereitstellungdesaktuellenwerts - -Der aktuelle Wert kann entweder über ein Item oder über eine -Eval-Funktion bereitgestellt werden. Wenn beides angegeben ist -wird das Item verwendet und die Eval-Funktion ignoriert. - -Der Name des Items, über das der aktuelle Wert abgerufen werden -soll, wird auf Ebene des Objekt-Items über das Attribut -``se_item_`` angegeben. Die Eval-Funktion, über -die der aktuelle Wert abgerufen werden soll, wird auf Ebene des -Objekt-Items über das Attribut -``se_eval_`` angegeben. Der Bedingungsname in ``se_item`` bzw. ``se_eval`` -muss mit den Bedingungsnamen in den Bedingungen korrespondieren. - -Das sich Altersbedingungen auf das Alter der hinterlegten Items -beziehen können ``se_agemin_``, -``se_agemax_`` und -``se_agenegate_`` nur verwendet werden, wenn der -aktuelle Wert über ein Item bereitgestellt wird. - -.. rubric:: Beispiel - :name: beispiel - -.. code-block:: yaml - - beispiel: - raffstore1: - automatik: - rules: - <...> - se_item_height: beispiel.raffstore1.hoehe - se_item_lamella: beispiel.raffstore1.lamelle - se_item_brightness: beispiel.wetterstation.helligkeit - Daemmerung: - type: foo - name: Dämmerung - - enter: - se_min_brightness: 500 - se_max_brightness: value:1000 - - Nacht: - type: foo - name: Nacht - - enter_todark: - se_max_brightness: 500 - - Sonder: - type: foo - name: Ein spezielles Bedingungsset - - enter: - se_min_brightness: item:test.wert - se_max_brightness: eval:sh.test.wert() + 500 - - -.. rubric:: "Besondere" Bedingungen - :name: besonderebedingungen - -Das Plugin stellt die Werte für einige "besondere" Bedingungen -automatisch bereit. Für diese Bedingungen muss daher kein Item und -keine Eval-Funktion zur Ermittlung des aktuellen Werts angegeben -werden. Die "besonderen" Bedingungen werden über reservierte -Bedingungsnamen gekennzeichnet. Diese Bedingungsnamen dürfen daher -nicht für andere Bedingungen verwendet werden. - -Die folgenden "besonderen" Bedingungsnamen können verwendet werden - -.. rubric:: time - :name: time - -*Aktuelle Uhreit* - -Die Werte für ``se_value_time``, ``se_min_time`` und -``se_max_time`` müssen im Format "hh:mm" (":") angegeben werden. -Es wird ein 24 Stunden-Zeitformat verwendet. Beispiele: "08:00" -oder "13:37". Um das Ende des Tages anzugeben kann der Wert -"24:00" verwendet werden, der für die Prüfungen automatisch zu -"23:59:59" konvertiert wird. Wichtig sind die Anführungszeichen -oder Hochkommas! - -.. rubric:: weekday - :name: weekday - -*Wochentag* - -0 = Montag, 1 = Dienstag, 2 = Mittwoch, 3 = Donnerstag, 4 = -Freitag, 5 = Samstag, 6 = Sonntag - -.. rubric:: month - :name: month - -*Monat* - -1 = Januar, ..., 12 = Dezember - -.. rubric:: sun_azimut - :name: sun_azimut - -*Sonnenstand (Horizontalwinkel)* - -Der Azimut (Horizontalwinkel) ist die Kompasrichtung in der die -Sonne steht. Der Azimut wird von smarthomeNg auf Basis der -aktuellen Zeit sowie der konfigurierten geographischen Position -berechnet. Siehe auch `SmarthomeNg -Dokumentation `_ -für Voraussetzungen zur Berechnung der Sonnenposition. -Beispielwerte: 0 → Sonne exakt im Norden, 90 → Sonne exakt im -Osten, 180 → Sonne exakt im Süden, 270 → Sonne exakt im Westen - -.. rubric:: sun_altitude - :name: sun_altitude - -*Sonnenstand (Vertikalwinkel)* - -Die Altitude (Vertikalwikel) ist der Winkel, in dem die Sonne über -dem Horizont steht. Die Altitude wird von smarthomeNg auf Basis -der aktuellen Zeit sowie der konfigurierten geographischen -Position berechnet. Siehe auch `SmarthomeNG -Dokumentation `_ -für Voraussetzungen zur Berechnung der Sonnenposition. Werte: -negativ → Sonne unterhalb des Horizonts, 0 → -Sonnenaufgang/Sonnenuntergang, 90 → Sonne exakt im Zenith -(passiert nur in äquatorialen Bereichen) - -.. rubric:: age - :name: age - -*Zeit seit der letzten Änderung des Zustands (Sekunden)* - -Das Alter wird über die letzte Änderung des Items, dass als -``se_laststate_item_id`` angegeben ist, ermittelt. - -.. rubric:: random - :name: random - -*Zufallszahl zwischen 0 und 100* - -Wenn etwas zufällig mit einer Wahrscheinlichkeit von 60% passieren -soll, kan beispielsweise die Bedingung ``max_random: 60`` -verwendet werden. - -.. rubric:: laststate - :name: laststate - -*Id des Zustandsitems des aktuellen Status* - -Wichtig: Hier muss die vollständige Item-Id angegeben werden - -.. rubric:: trigger_item, trigger_caller, trigger_source, trigger_dest - :name: trigger_itemtrigger_callertrigger_sourcetrigger_dest - -*item, caller, source und dest-Werte durch die die -Zustandsermittlung direkt ausgelöst wurde* - -Über diese vier Bedingungen kann der direkte Auslöser der -Zustandsermittlung abgeprüft werden, also die Änderung, die -smarthomeNG veranlasst, die Zustandsermittlung des -stateengine-Plugins aufzurufen. - -.. rubric:: original_item, original_caller, original_source - :name: original_itemoriginal_calleroriginal_source - -*item, caller, source und dest-Werte durch die die -Zustandsermittlung ursprünglich ausgelöst wurde* - -Über diese vier Bedingungen kann der ursprüngliche Auslöser der -Zustandsermittlung abgeprüft werden. Beim Aufruf der -Zustandsermittung über einen ``eval_trigger`` Eintrag wird über -``trigger_caller`` beispielsweise nur ``Eval`` weitergegeben. -In den drei ``original_*`` Bedingungen wird in diesem Fall der -Auslöser der Änderung zurückverfolgt und der Einstieg in die -``Eval``-Kette ermittelt. + test: + events: + name: stateengine Event Beispiel + type: foo + + item: + name: Dummy Item + type: bool + value: False + + rules: + type: bool + name: Automatik Test Event + # Dies ist ein Objekt-Item für das stateengine-Plugin: + se_plugin: active + + state1: + type: foo + name: Status 1 + + on_enter: + name: Ausführen immer wenn ein Zustand gerade aktiv geworden ist + <... Aktionen ...> + + on_stay: + name: Ausführen immer wenn ein Zustand aktiv geworden ist und bereits vorher aktiv war + <... Aktionen ...> + + on_enter_or_stay: + name: Ausführen immer wenn ein Zustand aktiv ist + <... Aktionen ...> + + on_leave: + name: Ausführen beim Verlassen des Zustands + <... Aktionen ...> + + enter_1: + name: Bedingung 1 + <...Einstiegs-Bedingungsset 1...> + + enter_2: + name: Bedingung 2 + <...Einstiegs-Bedingungsset 2...> + + state2: + name: Status 2 + <... Weitere Bedingungssets und Aktionsgruppen ...> + + state3: + name: Status 3 + <... Weitere Bedingungssets und Aktionsgruppen ...> diff --git a/stateengine/user_doc/user_doc6.rst b/stateengine/user_doc/user_doc6.rst index 54405d7e4..558ad69d2 100644 --- a/stateengine/user_doc/user_doc6.rst +++ b/stateengine/user_doc/user_doc6.rst @@ -1,94 +1,214 @@ -.. index:: Plugins; Stateengine; Ausführungszeitpunkt -.. index:: Ausführungszeitpunkt +.. index:: Plugins; Stateengine; Aktionen - einzeln +.. index:: Aktionen - einzeln -Ausführungszeitpunkt -#################### +Aktionen - einzeln +################## -.. rubric:: Aktionen - Ausführungszeitpunkt - :name: aktionenausfhrungszeitpunkt +Bei der Einzelvariante zur Definition von Aktionen werden alle +Parameter einer Aktion in separaten Attributen definiert. Über den +gemeinsamen Aktionsnamen gehören die Attribute einer Aktion +zusammen. -Um festzulegen, wann die Aktionen eines Zustands ausgeführt -werden, gibt es vier Ereignisse, denen die Aktionen zugeordnet -werden können: Für jedes dieser Ereignisse wird ein Item unterhalb -des Zustands-Items angelegt, unterhalb dem die jeweiligen Aktionen -als Attribute definiert werden. +Ähnlich wie Bedingungen benötigen auch Aktionen einen Namen. Der +Name ist auch hier beliebig und wird lediglich in der Benennung +der Attribute verwendet. Die Namen aller Attribute, die zu einer +Bedingung gehören, folgen dem Muster ``se__``. -- **on_enter**: Aktionen, die beim erstmaligen Aktivieren des - Zustands ausgeführt werden -- **on_stay**: Aktionen, die ausgeführt werden, wenn der Zustand - zuvor bereits aktiv war und weiterhin aktiv bleibt. -- **on_enter_or_stay**: Aktionen, die ausgeführt werden, wenn der - Zustand aktiv ist, unabhängig davon, ob er bereits zuvor aktiv - war oder nicht. -- **on_leave**: Aktionen, die ausgeführt werden, direkt bevor ein - anderer Zustand aktiv wird. +.. rubric:: Aktion: Item auf einen Wert setzen + :name: aktionitemaufeinenwertsetzen -Aktionen können auch ohne diese Ereigniss-Items direkt im -Zustands-Item definiert werden. Solche Aktionen werden analog zum -Ereignis ``on_enter_or_stay`` behandelt. +.. code-block:: yaml + + se_set_ + +Das Item, das verändert werden soll, muss auf Ebene des +Objekt-Items über das Attribut ``se_item_`` +angegeben werden. + +Der Wert, auf den das Item gesezt wird, kann als statischer Wert, als Wert eines +Items oder als Ergebnis der Ausführung einer Funktion festgelegt +werden. + +.. rubric:: Aktion: Minimumabweichung + :name: minimumabweichung + +Es ist möglich, eine Minimumabweichung für +Änderungen zu definieren. Wenn die Differenz zwischen dem +aktuellen Wert des Items und dem ermittelten neuen Wert kleiner +ist als die festgelegte Minimumabweichung wird keine Änderung +vorgenommen. Die Minimumabweichung wird über das Attribut +``se_mindelta_`` auf der Ebene des Objekt-Items +festgelegt. + +.. rubric:: Aktion: Item zwangsweise auf einen Wert setzen + :name: aktionitemzwangsweiseaufeinenwertsetzen -**Beispiel** +.. code-block:: yaml + + se_force_ + +Diese Aktion funktioniert analog zu ``se_set_``. +Einziger Unterschied ist, dass die Wertänderung erzwungen wird: +Wenn das Item bereits den zu setzenden Wert hat, dann ändert +smarthomeNG das Item nicht. Selbst wenn beim Item das Attribut +``enforce_updates: yes`` gesetzt ist, wird zwar der Wert neu +gesetzt, der von smarthomeNG die Änderungszeit nicht neu gesetzt. Mit +dem Attribut ``se_force_`` wird das Plugin den Wert +des Items bei Bedarf zuerst auf einen anderen Wert ändern und dann +auf dem Zielwert setzen. Damit erfolgt auf jeden Fall eine +Wertänderung (ggf. sogar zwei) mit allen damit in Zusammenhang +stehenden Änderungen (eval's, Aktualisierung der Änderungszeiten, +etc). + +.. rubric:: Aktion: Ausführen einer Funktion + :name: aktionausfuehreneinerfunktion .. code-block:: yaml - test: - type: foo + se_run_: eval:(Funktion) - events: - name: stateengine Event Beispiel - type: foo +Die Angabe ist vergleichbar mit dem Ausführen einer Funktion zur +Ermittlung des Werts für ein Item, hier wird jedoch kein Item +benötigt. Außerdem wird der Rückgabewert der Funktion ignoriert. + +.. rubric:: Aktion: Auslösen einer Logikausführung + :name: aktionauslseneinerlogikausfhrung + +.. code-block:: yaml + + se_trigger_: meineLogik:Zu übergebender Wert + +Um beim Auslösen einen Wert an die Logik zu übergeben, kann dieser +Wert im Attribut über die Angabe von ``: `` hinter dem +Logiknamen angegeben werden. + +.. rubric:: Aktion: Alle Items, die ein bestimmtes Attribut haben, + auf den Wert dieses Attributs setzen + :name: aktionalleitemsdieeinbestimmtesattributhabenaufdenwertdiesesattributssetzen + +.. code-block:: yaml + + se_byattr_: mein_eigenes_Attribut + +Mit diesem Attribut wird der Name eines anderen (beliebigen) +Attributs angegeben. Beim Ausführen werden alle Items +herausgesucht, die das angegebene Attribut enthalten. Diese Items +werden auf den Wert gesetzt, der dem genannten Attribut in den +Items jeweils zugewiesen ist. + +.. code-block:: yaml + + dummy: + type: num + mein_eigenes_Attribut: 42 + +| wird dann auf ``42`` gesetzt. +| Ein anderes Item + +.. code-block:: yaml - item: - name: Dummy Item - type: bool - value: False + dummy2: + type: str + mein_eigenes_Attribut: Rums + +wird gleichzeitig auf ``Rums`` gesetzt. + +.. rubric:: Aktion: Sondervorgänge + :name: aktionsondervorgnge + +.. code-block:: yaml + + se_special_: (Sondervorgang) + +Für bestimmte Sondervorgänge sind besondere Aktionen im Plugin +definiert (z. B. für das Suspend). Diese werden jedoch nicht hier +erläutert, sondern an den Stellen, an denen Sie verwendet werden. + +.. rubric:: Verzögertes Ausführen einer Aktion + :name: verzgertesausfhreneineraktion + +.. code-block:: yaml + + se_delay_: 30 (Sekunden)|30m (Minuten) + +Über das Attribut wird die Verzögerung angegeben, nach der die +Aktion ausgeführt werden soll. Die Angabe erfolgt in Sekunden oder +mit dem Suffix "m" in Minuten. + +Der Timer zur Ausführung der Aktion nach der angegebenen +Verzögerung wird entfernt, wenn eine gleichartike Aktion +ausgeführt werden soll (egal ob verzögert oder nicht). Wenn also +die Verzögerung größer als der ``cycle`` ist, wird die Aktion +nie durchgeführt werden, es sei denn die Aktion soll nur +einmalig ausgeführt werden. + +.. rubric:: Wiederholen einer Aktion + :name: wiederholeneineraktion + +.. code-block:: yaml + + se_repeat_: True|False + +Über das Attribut wird unabhängig vom globalen Setting für das +stateengine Item festgelegt, ob eine Aktion auch beim erneuten +Eintritt in den Status ausgeführt wird oder nicht. + +.. rubric:: Festlegen der Ausführungsreihenfolge von Aktionen + :name: festlegenderausfhrungsreihenfolgevonaktionen + +.. code-block:: yaml + + se_order_ + se_order_aktion1: 3 + se_order_aktion2: 2 + se_order_aktion3: 1 + se_order_aktion4: 2 + +Die Reihenfolge, in der die Aktionen ausgeführt werden, ist nicht +zwingend die Reihenfolge in der die Attribute definiert sind. In +den meisten Fällen ist dies kein Problem, da die Aktionen +voneinander unabhängig sind und daher in beliebiger Reihenfolge +ausgeführt werden können. In Einzelfällen kann es jedoch +erforderlich sein, mehrere Aktionen in einer bestimmten +Reihenfolge auszuführen. + +Es ist möglich, zwei Aktionen die gleiche Zahl zuzuweisen, die +Reihenfolge der beiden Aktionen untereinander ist dann wieder +zufällig. Innerhalb der gesamten Aktionen werden die beiden +Aktionen jedoch an der angegebenen Position ausgeführt. + +.. rubric:: Beispiel zu Aktionen + :name: beispielzuaktionen + +.. code-block:: yaml + beispiel: + raffstore: + automatik: rules: - type: bool - name: Automatik Test Event - # Dies ist ein Objekt-Item für das stateengine-Plugin: - se_plugin: active - - state1: - type: foo - name: Status 1 - - on_enter: - type: foo - name: Ausführen immer wenn ein Zustand gerade aktiv geworden ist - <... Aktionen ...> - - on_stay: - type: foo - name: Ausführen immer wenn ein Zustand aktiv geworden ist und bereits vorher aktiv war - <... Aktionen ...> - - on_enter_or_stay: - type: foo - name: Ausführen immer wenn ein Zustand aktiv ist - <... Aktionen ...> - - on_leave: - type: foo - name: Ausführen beim Verlassen des Zustands - <... Aktionen ...> - - enter_1: - type: foo - name: Bedingung 1 - <...Einstiegs-Bedingungsset 1...> - - enter_2: - type: foo - name: Bedingung 2 - <...Einstiegs-Bedingungsset 2...> - - state2: - type: foo - name: Status 2 - <... Weitere Bedingungssets und Aktionsgruppen ...> - - state3: - type: foo - name: Status 3 - <... Weitere Bedingungssets und Aktionsgruppen ...> + <...> + se_item_height: beispiel.raffstore1.hoehe + se_mindelta_height: 10 + se_item_lamella: beispiel.raffstore1.lamelle + se_mindelta_lamella: 5 + + Daemmerung: + <...> + se_set_height: value:100 + se_set_lamella: value:25 + <...> + Nacht: + <...> + se_set_height: value:100 + se_set_lamella: value:0 + <...> + Sonnenstand: + <...> + se_set_height: value:100 + se_set_lamella: eval:stateengine_eval.sun_tracking() + <...> + Sonder: + <...> + se_trigger_logic1: myLogic:42 + se_delay_logic1: 10 + <...> diff --git a/stateengine/user_doc/user_doc7.rst b/stateengine/user_doc/user_doc7.rst index 7929d1faf..2795b2ceb 100644 --- a/stateengine/user_doc/user_doc7.rst +++ b/stateengine/user_doc/user_doc7.rst @@ -1,124 +1,180 @@ -.. index:: Plugins; Stateengine; Aktionen - einzeln -.. index:: Aktionen - einzeln +.. index:: Plugins; Stateengine; Aktionen - kombiniert +.. index:: Aktionen - kombiniert +.. _Aktionen: -Aktionen - einzeln -################## +Aktionen - kombiniert +##################### -.. rubric:: Aktionen - Einzelvariante - :name: aktioneneinzelvariante +Bei der kombinierten Variante zur Definition von Aktionen werden +alle Parameter einer Aktion in einem Attribut definiert. Über den +Aktionsnamen werden lediglich eventuelle Items zugeordnet. Die +einzelnen Parameter werden bei conf-Files in der +Listenschreibweise mit dem Zeichen ``|`` getrennt aufgelistet: -Bei der Einzelvariante zur Definition von Aktionen werden alle -Parameter einer Aktion in separaten Attributen definiert. Über den -gemeinsamen Aktionsnamen gehören die Attribute einer Aktion -zusammen. +.. code-block:: none -Ähnlich wie Bedingungen benötigen auch Aktionen einen Namen. Der -Name ist auch hier beliebig und wird lediglich in der Benennung -der Attribute verwendet. Die Namen aller Attribute, die zu einer -Bedingung gehören, folgen dem Muster ``se__``. + se_action_: function: | (evtl. Detailparameter zur Funktion) | delay: | order: | repeat: -.. rubric:: Aktion: Item auf einen Wert setzen - :name: aktionitemaufeinenwertsetzen +Bei yaml Files werden die Parameter mittels Aufzählungszeichen "-" +untereinander definiert: .. code-block:: yaml - se_set_ + se_action_: + - function: + - Detailparameter der Funktion, z.B. "to: .." + - delay: + - order: + - repeat: -Das Item, dass verändert werden soll, muss auf Ebene des -Objekt-Items über das Attribut ``se_item_`` -angegeben werden. +Die Parameter haben dabei folgende Bedeutung: + +.. rubric:: delay: ```` + :name: delay + +Über den optionalen Parameter ```` wird die Verzögerung angegeben, nach der die +Aktion ausgeführt werden soll. + +Die Angabe erfolgt in Sekunden oder mit dem Suffix "m" in Minuten. + +.. code-block:: yaml -Das Attribut ``se_set_`` nutzt den Datentyp -AbValue. Der Wert, auf den das -Item gesezt wird kann dadurch als statischer Wert, als Wert eines -Items oder als Ergebnis der Ausführung einer Funktion festgelegt -werden. + delay: 30 --> 30 Sekunden + delay: 30m --> 30 Minuten -**Minimumabweichung:** Es ist möglich eine Minimumabweichung für -Änderungen zu definieren. Wenn die Differenz zwischen dem -aktuellen Wert des Items und dem ermittelten neuen Wert kleiner -ist als die festgelegte Minimumabweichung wird keine Änderung -vorgenommen. Die Minimumabweichung wird über das Attribut -``se_mindelta_`` auf der Ebene des Objekt-Items -festgelegt. Auch hier wird der Datentyp -AbValue verwendet. +| Der Timer zur Ausführung der Aktion nach der angegebenen + Verzögerung wird entfernt, wenn eine gleichartike Aktion + ausgeführt werden soll (egal ob verzögert oder nicht). Wenn also + die Verzögerung größer als der ``cycle`` ist, wird die Aktion + nie durchgeführt werden, es sei denn die Aktion soll nur + einmalig ausgeführt werden. -.. rubric:: Aktion: Item zwangsweise auf einen Wert setzen - :name: aktionitemzwangsweiseaufeinenwertsetzen +.. rubric:: repeat: ```` + :name: repeat .. code-block:: yaml - se_force_ + repeat: True|False + +Über das Attribut wird unabhängig vom globalen Setting für das +stateengine Item festgelegt, ob eine Aktion auch beim erneuten +Eintritt in den Status ausgeführt wird oder nicht. + +.. rubric:: order: ```` + :name: order + +Die Reihenfolge, in der die Aktionen ausgeführt werden, ist nicht +zwingend die Reihenfolge in der die Attribute definiert sind. In +den meisten Fällen ist dies kein Problem da die Aktionen +voneinander unabhängig sind und daher in beliebiger Reihenfolge +ausgeführt werden können. In Einzelfällen kann es jedoch +erforderlich sein, mehrere Aktionen in einer bestimmten +Reihenfolge auszuführen. Dies kann über den Parameter +``order: `` erfolgen. Mit diesem Attribut wird der Aktion +eine Zahl zugewiesen. Aktionen werden in aufsteigender Reihenfolge +der zugewiesenen Zahlen ausgeführt. -Diese Aktion funktioniert analog zu ``se_set_``. -Einziger Unterschied ist, dass die Wertänderung erzwungen wird: +Der Parameter ist optional und kann auch weggelassen werden. Für +Aktionen, denen keine Reihenfolge explizit zugewiesen wurde, wird +der Reihenfolgenwert 1 verwendet. + +Es ist möglich zwei Aktionen die gleiche Zahl zuzuweisen, die +Reihenfolge der beiden Aktionen untereinander ist dann wieder +undefiniert. Innerhalb der gesamten Aktionen werden die beiden +Aktionen jedoch an der angegebenen Position ausgeführt. + +.. code-block:: yaml + + order: 1|2|... + +.. rubric:: function: ```` + :name: function + +| Mit dem Parameter ```` wird die auszuführende Funktion + festgelegt. In Abhängigkeit zur gewählten Funktion werden + zusätzliche Detailparameter erforderlich. +| Folgende Werte sind möglich: + +**Funktion ``set``: Item auf einen Wert setzen** + +.. code-block:: yaml + + se_action_: + - function: set + - to: + - force: [True/False] + +Das Item, das verändert werden soll, muss auf Ebene des +Objekt-Items über das Attribut ``se_item_`` +angegeben werden. + +Der Parameter ``to: `` legt fest, auf welchen Wert das Item +gesetzt werden soll. Der Wert, +auf den das Item gesezt wird, kann als statischer Wert, als +Wert eines Items oder als Ergebnis der Ausführung einer Funktion +festgelegt werden. Wichtig ist, dass bei z.B. ``to: item:`` +nach dem item: kein Leerzeichen eingesetzt werden darf! + +Über den optionalen Parameter +``force: [True/False]`` kann eine Wertänderung erzwungen werden: Wenn das Item bereits den zu setzenden Wert hat, dann ändert smarthomeNG das Item nicht. Selbst wenn beim Item das Attribut ``enforce_updates: yes`` gesetzt ist, wird zwar der Wert neu -gesetzt, der von smarthomeNG Änderungszeit nicht neu gesetzt. Mit -dem Attribut ``se_force_`` wird das Plugin den Wert +gesetzt, der von smarthomeNG Änderungszeit nicht neu gesetzt. Wird +der Parameter ``force: True`` gesetzt, so wird das Plugin den Wert des Items bei Bedarf zuerst auf einen anderen Wert ändern und dann auf dem Zielwert setzen. Damit erfolgt auf jeden Fall eine Wertänderung (ggf. sogar zwei) mit allen damit in Zusammenhang stehenden Änderungen (eval's, Aktualisierung der Änderungszeiten, etc). -.. rubric:: Aktion: Ausführen einer Funktion - :name: aktionausfhreneinerfunktion +**Funktion ``run``: Ausführen einer Funktion** .. code-block:: yaml - se_run_: eval:(Funktion) + se_action_: + - function: run + - eval:(Funktion) Die Angabe ist vergleichbar mit dem Ausführen einer Funktion zur Ermittlung des Werts für ein Item, hier wird jedoch kein Item benötigt. Außerdem wird der Rückgabewert der Funktion ignoriert. -.. rubric:: Aktion: Auslösen einer Logikausführung - :name: aktionauslseneinerlogikausfhrung +**Funktion ``trigger``: Auslösen einer Logikausführung** .. code-block:: yaml - se_trigger_ + se_action_: + - function: trigger + - logic: + - value: -Um beim Auslösen einen Wert an die Logik zu übergeben, kann dieser -Wert im Attribut über die Angabe von ``:`` hinter dem -Logiknamen angegeben werden. +Löst die Ausführung der Logik ```` aus. Um beim +Auslösen einen Wert an die Logik zu übergeben, kann dieser Wert +über die Angabe von ``value: `` hinter dem Logiknamen +angegeben werden. Wenn kein Wert übergeben werden, soll lässt man +den Teil weg. -**Beispiel:** +**Funktion ``byattr``: Alle Items, die ein bestimmtes + Attribut haben, auf den Wert dieses Attributs setzen** .. code-block:: yaml - se_trigger_: meineLogik:Zu übergebender Wert + se_action_: + - function: byattr + - attribute: -.. rubric:: Aktion: Alle Items, die ein bestimmtes Attribut haben, - auf den Wert dieses Attributs setzen - :name: aktionalleitemsdieeinbestimmtesattributhabenaufdenwertdiesesattributssetzen - -.. code-block:: yaml - - se_byattr_ - -Mit diesem Attribut wird der Name eines anderen (beliebigen) +Mit dieser Funktion wird der Name eines anderen (beliebigen) Attributs angegeben. Beim Ausführen werden alle Items herausgesucht, die das angegebene Attribut enthalten. Diese Items werden auf den Wert gesetzt, der dem genannten Attribut in den Items jeweils zugewiesen ist. -**Beispiel:** - .. code-block:: yaml - se_byattr_: mein_eigenes_Attribut - -sucht alle Items heraus, bei denen das Attribut -``mein_eigenes_Attribut`` angegeben ist. Ein Item - -.. code-block:: yaml - - dummy: + dummy1: type: num - mein_eigenes_Attribut: 42 + : 42 | wird dann auf ``42`` gesetzt. | Ein anderes Item @@ -127,120 +183,23 @@ sucht alle Items heraus, bei denen das Attribut dummy2: type: str - mein_eigenes_Attribut: Rums + : Rums + wird gleichzeitig auf ``Rums`` gesetzt. -.. rubric:: Aktion: Sondervorgänge - :name: aktionsondervorgnge +**Funktion ``special``: Sondervorgänge** .. code-block:: yaml - se_special_: (Sondervorgang) + se_action_: + - function: special + - value: Für bestimmte Sondervorgänge sind besondere Aktionen im Plugin definiert (z. B. für das Suspend). Diese werden jedoch nicht hier erläutert, sondern an den Stellen, andenen Sie verwendet werden. -.. rubric:: Verzögertes Ausführen einer Aktion - :name: verzgertesausfhreneineraktion - -.. code-block:: yaml - - se_delay_ - -Über das Attribut wird die Verzögerung angegeben, nach der die -Aktion ausgeführt werden soll. Die Angabe erfolgt in Sekunden oder -mit dem Suffix "m" in Minuten. - -.. code-block:: yaml - - se_delay_: 30 --> 30 Sekunden - se_delay_: 30m --> 30 Minuten - -| Der Timer zur Ausführung der Aktion nach der angegebenen - Verzögerung wird entfernt, wenn eine gleichartike Aktion - ausgeführt werden soll (egal ob verzögert oder nicht). Wenn also - die Verzögerung größer als der ``cycle`` ist, wird die Aktion - nie durchgeführt werden, es sei denn die Aktion soll nur - einmalig ausgeführt werden. -| Das Attribut ``se_delay_`` verwendet den - Datentyp AbValue - -.. rubric:: Wiederholen einer Aktion - :name: wiederholeneineraktion - -.. code-block:: yaml - - se_repeat_ - -Über das Attribut wird unabhängig vom globalen Setting für das -stateengine Item festgelegt, ob eine Aktion auch beim erneuten -Eintritt in den Status ausgeführt wird oder nicht. - -.. code-block:: yaml - - se_repeat_: True # Aktion wird bei jedem Mal aufs neue ausgeführt - se_repeat_: False # Aktion wird nur beim ersten Eintritt in den Status ausgeführt - - -.. rubric:: Festlegen der Ausführungsreihenfolge von Aktionen - :name: festlegenderausfhrungsreihenfolgevonaktionen - -.. code-block:: yaml - - se_order_ - -Die Reihenfolge, in der die Aktionen ausgeführt werden, ist nicht -zwingend die Reihenfolge in der die Attribute definiert sind. In -den meisten Fällen ist dies kein Problem da die Aktionen -voneinander unabhängig sind und daher in beliebiger Reihenfolge -ausgeführt werden können. In Einzelfällen kann es jedoch -erforderlich sein, mehrere Aktionen in einer bestimmten -Reihenfolge auszuführen. Dies kann über das Attribut -``se_order_`` erfolgen. Mit diesem Attribut wird der -Aktion eine Zahl zugewiesen. Aktionen werden in aufsteigender -Reihenfolge der zugewiesenen Zahlen ausgeführt. - -Es ist möglich zwei Aktionen die gleiche Zahl zuzuweisen, die -Reihenfolge der beiden Aktionen untereinander ist dann wieder -undefiniert. Innerhalb der gesamten Aktionen werden die beiden -Aktionen jedoch an der angegebenen Position ausgeführt. - -Wird für eine Aktion kein Reihenfolgenwert angegeben, wird -implizit der Wert 1 verwendet. - -Das Attribut ``se_order_`` verwendet den Datentyp -AbValue - -**Beispiel zur Ausführungsreihenfolge:** - -.. code-block:: yaml - - beispiel: - automatik: - rules: - <...> - Zustand1: - se_order_aktion1: 3 - se_order_aktion2: 2 - se_order_aktion3: 1 - se_order_aktion4: 2 - - -Die Reihenfolge der Aktionen hier wird wie folgt sein: - -#. aktion3 -#. aktion2, aktion4 ODER aktion4, aktion2 -#. aktion 1 - -Ist zusätzlich eine aktion5 definiert, die keine Reihenfolge -festgelegt hat, wird die Reihenfolge der Aktionen wie folgt sein: - -#. aktion3, aktion5 ODER aktion5, aktion3 -#. aktion2, aktion4 ODER aktion4, aktion2 -#. aktion 1 - .. rubric:: Beispiel zu Aktionen :name: beispielzuaktionen @@ -257,21 +216,36 @@ festgelegt hat, wird die Reihenfolge der Aktionen wie folgt sein: se_mindelta_lamella: 5 Daemmerung: <...> - se_set_height: value:100 - se_set_lamella: value:25 + se_action_height: + - function: set + - to: value:100 + se_action_lamella: + - function: set + - to: value:25 <...> Nacht: <...> - se_set_height: value:100 - se_set_lamella: value:0 + se_action_height: + - function: set + - to: value:100 + se_action_lamella: + - function: set + - to: value:0 <...> Nachfuehren: <...> - se_set_height: value:100 - se_set_lamella: eval:stateengine_eval.sun_tracking() + se_action_height: + - function: set + - to: value:100 + se_action_lamella: + - function: set + - to: eval:stateengine_eval.sun_tracking() <...> Sonder: <...> - se_trigger_logic1: myLogic:42 - se_delay_logic1: 10 + se_action_logic1: + - function: trigger + - logic: myLogic + - value: 42 + - delay: 10 <...> diff --git a/stateengine/user_doc/user_doc8.rst b/stateengine/user_doc/user_doc8.rst index 42dcb8d7c..784e2fb05 100644 --- a/stateengine/user_doc/user_doc8.rst +++ b/stateengine/user_doc/user_doc8.rst @@ -1,288 +1,78 @@ -.. index:: Plugins; Stateengine; Aktionen - kombiniert -.. index:: Aktionen - kombiniert -.. _Aktionen: - -Aktionen - kombiniert -##################### - -.. rubric:: Aktionen - Kombinierte Variante - :name: aktionenkombiniertevariante - -Bei der kombinierten Variante zur Definition von Aktionen werden -alle Parameter einer Aktion in einem Attribut definiert. Über den -Aktionsnamen werden lediglich eventuelle Items zugeordnet. Die -einzelnen Parameter werden bei conf-Files in der -Listenschreibweise mit dem Zeichen ``|`` getrennt aufgelistet: - -.. code-block:: none - - se_action_: function: | (evtl. Detailparameter zur Funktion) | delay: | order: | repeat: - -Bei yaml Files werden die Parameter mittels Aufzählungszeichen "-" -untereinander definiert: - -.. code-block:: yaml - - se_action_: - - function: - - Detailparameter der Funktion, z.B. "to: .." - - delay: - - order: - - repeat: - -Die Parameter haben dabei folgende Bedeutung: - -.. rubric:: delay: ```` - :name: delaydelay - -Über ```` wird die Verzögerung angegeben, nach der die -Aktion ausgeführt werden soll. - -Der Parameter ist optional und kann auch weggelassen werden. In -diesem Fall wird die Aktion sofort ausgeführt. - -Die Angabe erfolgt in Sekunden oder mit dem Suffix "m" in Minuten. - -.. code-block:: yaml - - delay: 30 --> 30 Sekunden - delay: 30m --> 30 Minuten - -| Der Timer zur Ausführung der Aktion nach der angegebenen - Verzögerung wird entfernt, wenn eine gleichartike Aktion - ausgeführt werden soll (egal ob verzögert oder nicht). Wenn also - die Verzögerung größer als der ``cycle`` ist, wird die Aktion - nie durchgeführt werden, es sei denn die Aktion soll nur - einmalig ausgeführt werden. -| Für den Wert von ```` wird der Datentyp - AbValue verwendet. - -.. rubric:: repeat: ```` - :name: repeatrepeat - -.. code-block:: yaml - - se_repeat_ - -Über das Attribut wird unabhängig vom globalen Setting für das -stateengine Item festgelegt, ob eine Aktion auch beim erneuten -Eintritt in den Status ausgeführt wird oder nicht. - -.. code-block:: yaml - - se_repeat_: True # Aktion wird bei jedem Mal aufs neue ausgeführt - se_repeat_: False # Aktion wird nur beim ersten Eintritt in den Status ausgeführt - -.. rubric:: order: ```` - :name: orderorder - -Die Reihenfolge, in der die Aktionen ausgeführt werden, ist nicht -zwingend die Reihenfolge in der die Attribute definiert sind. In -den meisten Fällen ist dies kein Problem da die Aktionen -voneinander unabhängig sind und daher in beliebiger Reihenfolge -ausgeführt werden können. In Einzelfällen kann es jedoch -erforderlich sein, mehrere Aktionen in einer bestimmten -Reihenfolge auszuführen. Dies kann über den Parameter -``order: `` erfolgen. Mit diesem Attribut wird der Aktion -eine Zahl zugewiesen. Aktionen werden in aufsteigender Reihenfolge -der zugewiesenen Zahlen ausgeführt. - -Der Parameter ist optional und kann auch weggelassen werden. Für -Aktionen, denen keine Reihenfolge explizit zugewiesen wurde, wird -der Reihenfolgenwert 1 verwendet. - -Es ist möglich zwei Aktionen die gleiche Zahl zuzuweisen, die -Reihenfolge der beiden Aktionen untereinander ist dann wieder -undefiniert. Innerhalb der gesamten Aktionen werden die beiden -Aktionen jedoch an der angegebenen Position ausgeführt. - -Für den Wert von ```` wird der Datentyp -AbValue verwendet. - -.. rubric:: function: ```` - :name: functionfunc - -| Mit dem Parameter ```` wird die auszuführende Funktion - festgelegt. In Abhängigkeit zur gewählten Funktion werden - zusätzliche Detailparameter erforderlich. -| Folgende Werte sind möglich: - -.. rubric:: Funktion ``set``: Item auf einen Wert setzen - :name: funktionsetitemaufeinenwertsetzen - -.. code-block:: yaml - - se_action_: - - function: set - - to: - - force: [True/False] - -Das Item, dass verändert werden soll, muss auf Ebene des -Objekt-Items über das Attribut ``se_item_`` -angegeben werden. - -Der Parameter ``to: `` legt fest, auf welchen Wert das Item -gesetzt werden soll. Für ```` wird der Datentyp -AbValue verwendet. Der Wert, -auf den das Item gesezt wird kann dadurch als statischer Wert, als -Wert eines Items oder als Ergebnis der Ausführung einer Funktion -festgelegt werden. - -**Erzwingen der Wertänderung:** Über den optionalen Parameter -``force: [True/False]`` kann eine Wertänderung erzwungen werden: -Wenn das Item bereits den zu setzenden Wert hat, dann ändert -smarthomeNG das Item nicht. Selbst wenn beim Item das Attribut -``enforce_updates: yes`` gesetzt ist, wird zwar der Wert neu -gesetzt, der von smarthomeNG Änderungszeit nicht neu gesetzt. Wird -der Parameter ``force: True`` gesetzt, so wird das Plugin den Wert -des Items bei Bedarf zuerst auf einen anderen Wert ändern und dann -auf dem Zielwert setzen. Damit erfolgt auf jeden Fall eine -Wertänderung (ggf. sogar zwei) mit allen damit in Zusammenhang -stehenden Änderungen (eval's, Aktualisierung der Änderungszeiten, -etc). - -**Minimumabweichung:** Es ist möglich eine Minimumabweichung für -Änderungen zu definieren. Wenn die Differenz zwischen dem -aktuellen Wert des Items und dem ermittelten neuen Wert kleiner -ist als die festgelegte Minimumabweichung wird keine Änderung -vorgenommen. Die Minimumabweichung wird über das Attribut -``se_mindelta_`` auf der Ebene des Objekt-Items -festgelegt. Auch hier wird der Datentyp -AbValue verwendet. - -.. rubric:: Funktion ``run``: Ausführen einer Funktion - :name: funktionrunausfhreneinerfunktion - -.. code-block:: yaml - - se_action_: - - function: run - - eval:(Funktion) - -Die Angabe ist vergleichbar mit dem Ausführen einer Funktion zur -Ermittlung des Werts für ein Item, hier wird jedoch kein Item -benötigt. Außerdem wird der Rückgabewert der Funktion ignoriert. - -.. rubric:: Funktion ``trigger``: Auslösen einer Logikausführung - :name: funktiontriggerauslseneinerlogikausfhrung - -.. code-block:: yaml - - se_action_: - - function: trigger - - logic: - - value: - -Löst die Ausführung der Logik ````\ aus. Um beim -Auslösen einen Wert an die Logik zu übergeben, kann dieser Wert -über die Angabe von ``value: `` hinter dem Logiknamen -angegeben werden. Wenn kein Wert übergeben werden soll lässt man -den Teil weg. - -.. rubric:: Funktion ``byattr``: Alle Items, die ein bestimmtes - Attribut haben, auf den Wert dieses Attributs setzen - :name: funktionbyattralleitemsdieeinbestimmtesattributhabenaufdenwertdiesesattributssetzen - -.. code-block:: yaml - - se_action_: - - function: byattr - - attribute: - -Mit dieser Funktion wird der Name eines anderen (beliebigen) -Attributs angegeben. Beim Ausführen werden alle Items -herausgesucht, die das angegebene Attribut enthalten. Diese Items -werden auf den Wert gesetzt, der dem genannten Attribut in den -Items jeweils zugewiesen ist. - -**Beispiel:** - -.. code-block:: yaml - - se_action_: - - function: byattr - - attribute: mein_eigenes_Attribut - -sucht alle Items heraus, bei denen das Attribut -``mein_eigenes_Attribut`` angegeben ist. Ein Item - -.. code-block:: yaml - - dummy1: - type: num - mein_eigenes_Attribut: 42 - -| wird dann auf ``42`` gesetzt. -| Ein anderes Item - -.. code-block:: yaml - - dummy2: - type: str - mein_eigenes_Attribut: Rums - - -wird gleichzeitig auf ``Rums`` gesetzt. - -.. rubric:: Funktion ``special``: Sondervorgänge - :name: funktionspecialsondervorgnge +.. index:: Plugins; Stateengine; Vorgabezustände +.. index:: Vorgabezustände + +Vorgabezustände +############### + +Es ist möglich, Vorgabezustände in der Konfiguration zu definieren +und diese später für konkrete Objekte anzuwenden. Dabei können im +konkreten Zustand auch Einstellungen des Vorgabezustands +überschrieben werden. + +Vorgabezustände werden als Item an beliebiger Stelle innerhalb der +Item-Struktur definiert. Es ist sinnvoll, die Vorgabezustände +unter einem gemeinsamen Item namens ``default`` zusammenzufassen. Innerhalb der +Vorgabezustand-Items stehen die gleichen Möglichkeiten wie in +normalen Zustands-Items zur Verfügung. Das dem +Vorgabezustands-Item übergeordnete Item darf nicht das Attribut +``se_plugin: active`` haben, da diese Items nur Vorlagen und keine +tatsächlichen State Machines darstellen. Im Item über dem +Vorgabezustands-Item können jedoch Items über +``se_item_`` angegeben werden. Diese +stehen in den Vorgabezuständen und in den von den Vorgabezuständen +abgeleiteten Zuständen zur Verfügung und müssen so nicht jedes Mal +neu definiert werden. + +Im konkreten Zustands-Item kann das Vorgabezustand-Item über das +Attribut .. code-block:: yaml - se_action_: - - function: special - - value: + se_use: -Für bestimmte Sondervorgänge sind besondere Aktionen im Plugin -definiert (z. B. für das Suspend). Diese werden jedoch nicht hier -erläutert, sondern an den Stellen, andenen Sie verwendet werden. +eingebunden werden. Die Vorgabezustand-Items können geschachtelt +werden, das heißt ein Vorgabezustand kann also selbst wiederum +über ``se_use`` von einem weiteren Vorgabezustand abgeleitet +werden. Um unnötige Komplexität und Zirkelbezüge zu vermeiden, ist +die maximale Tiefe jedoch auf 5 Ebenen begrenzt. -.. rubric:: Beispiel zu Aktionen - :name: beispielzuaktionen +.. rubric:: Beispiel + :name: beispiel .. code-block:: yaml beispiel: - raffstore: - automatik: - rules: - <...> - se_item_height: beispiel.raffstore1.hoehe - se_mindelta_height: 10 - se_item_lamella: beispiel.raffstore1.lamelle - se_mindelta_lamella: 5 - Daemmerung: - <...> - se_action_height: - - function: set - - to: value:100 - se_action_lamella: - - function: set - - to: value:25 - <...> - Nacht: - <...> - se_action_height: - - function: set - - to: value:100 - se_action_lamella: - - function: set - - to: value:0 - <...> - Nachfuehren: - <...> - se_action_height: - - function: set - - to: value:100 - se_action_lamella: - - function: set - - to: eval:stateengine_eval.sun_tracking() - <...> - Sonder: - <...> - se_action_logic1: - - function: trigger - - logic: myLogic - - value:42 - - delay: 10 - <...> + default: + <...> + se_item_height: ...hoehe + Nacht: + <...> + enter: + (...) + se_set_height: value:100 + se_set_lamella: 0 + Morgens: + <...> + enter: + <...> + se_set_height: value:100 + se_set_lamella: 25 + + raffstore1: + lamelle: + type: num + hoehe: + type: num + + automatik: + rules: + <...> + se_item_lamella: beispiel.raffstore1.lamelle + Nacht: + se_use: beispiel.default.Nacht + enter_additional: + <... zusätzliche Einstiegsbedingung ...> + enter: + <... Änderungen an der Einstiegsbedingung des Vorgabezustands ...> + Morgens: + se_use: beispiel.default.Morgens diff --git a/stateengine/user_doc/user_doc9.rst b/stateengine/user_doc/user_doc9.rst index 1f8c0a6d4..6c3eafe07 100644 --- a/stateengine/user_doc/user_doc9.rst +++ b/stateengine/user_doc/user_doc9.rst @@ -1,99 +1,88 @@ -.. index:: Plugins; Stateengine; Vorgabezustände -.. index:: Vorgabezustände - -Vorgabezustände -############### - -.. rubric:: Vorgabezustände verwenden - :name: vorgabezustndeverwenden - -Es ist möglich Vorgabezustände in der Konfiguration zu definieren -und diese später für konkrete Objekte anzuwenden. Dabei können im -konkreten Zustand auch Einstellungen des Vorgabezustands -überschrieben werden. - -Vorgabezustände werden als Item an beliebiger Stelle innerhalb der -Item-Struktur definiert. Es ist sinnvoll, die Vorgabezustände -unter eingem gemeinsamen Item zusammenzufassen. Innerhalb der -Vorgabezustand-Items stehen die gleichen Möglichkeiten wie in -normalen Zustands-Items zur Verfügung. Das dem -Vorgabezustands-Item übergeordnete Item darf nicht das Attribut -``se_plugin: active`` haben. Im Item über dem -Vorgabezustands-Item können jedoch Items über -``se_item_`` angegeben werden. Diese -stehen in den Vorgabezuständen und in den von den Vorgabezuständen -abgeleiteten Zuständen zur Verfügung und müssen so nicht jedes mal -neu definiert werden. - -Im konkreten Zustands-Item kann das Vorgabezustand-Item über das -Attribut +.. index:: Plugins; Stateengine; Vordefinierte Funktionen +.. index:: Vordefinierte Funktionen + +Vordefinierte Funktionen +######################## + +Das stateengine Plugin stellt verschiedene vordefinierte +Funktionen zur Verfügung, die einfach für +``se_set_`` und ``se_run_`` Aktionen +verwendet werden können: + +.. rubric:: Winkel zum Nachführen der Jalousielamellen auf Basis des Sonnenstands + :name: winkel + +.. code-block:: yaml + + stateengine_eval.sun_tracking() + + +.. rubric:: Zufallszahl + :name: zufallszahl + +.. code-block:: yaml + + stateengine_eval.get_random_int(min,max) + +Über ``min`` und ``max`` kann die kleinste/größte Nummer, die +zurückgegeben werden soll, festgelegt werden. ``min`` und +``max`` können weggelassen werden, in diesem Fall sind die +Vorgabewerte 0 für ``min`` und 255 für ``max``. + +.. rubric:: Shell-Kommando ausführen + :name: shellkommandoausfhren + +.. code-block:: yaml + + stateengine_eval.execute(command) + +Führt das Shell-Kommando ``command`` aus + +.. rubric:: Wert einer Variable ermitteln + :name: werteinervariableermitteln + +.. code-block:: yaml + + stateengine_eval.get_variable(varname) + +Liefert den Wert der :ref:`Variablen` ``varname`` + +.. rubric:: Item-Id relativ zum Objekt-Item ermitteln + :name: itemidrelativzumobjektitemermitteln .. code-block:: yaml - se_use: + stateengine_eval.get_relative_itemid(subitem_id) -eingebunden werden. Die Vorgabezustand-Items können geschachtelt -werden, dass heißt ein Vorgabezustand kann also selbst wiederum -über ``se_use`` von einem weiteren Vorgabezustand abgeleitet -werden. Um unnötige Komplexität und Zirkelbezüge zu vermeiden ist -die maximale Tiefe jedoch auf 5 Ebenen begrenzt. +Eine Item-Id relativ zur Item-Id des Objekt-Items wird ermittelt. -.. rubric:: Beispiel - :name: beispiel +.. rubric:: Item-Wert relativ zum Objekt-Item ermitteln + :name: itemwertrelativzumobjektitemermitteln .. code-block:: yaml - beispiel: - default: - <...> - se_item_height: ...hoehe - Nacht: - <...> - enter: - (...) - se_set_height: value:100 - se_set_lamella: 0 - Morgens: - <...> - enter: - <...> - se_set_height: value:100 - se_set_lamella: 25 - - Abends: - <...> - enter: - <...> - se_set_height: value:100 - se_set_lamella: 75 - - Tag: - <...> - enter: - <...> - se_set_height: value:0 - se_set_lamella: 100 - - beispiel - raffstore1: - automatik: - rules: - <...> - se_item_lamella: beispiel.raffstore1.lamelle - Nacht: - se_use: beispiel.default.Nacht - enter_additional: - <... zusätzliche Einstiegsbedingung ...> - Morgens: - se_use: beispiel.default.Morgens - Abends: - se_use: beispiel.default.Abends - enter: - <... Änderungen an der Einstiegsbedingung des Vorgabezustands ...> - Nachfuehren: - <...> - name: Zusätzlicher Zustand, der nicht aus den Vorgabezuständen kommt - se_set_height: value:100 - se_set_lamella: eval:stateengine_eval.sun_tracking() - Tag: - se_use: stateengine.default.day + stateengine_eval.get_relative_itemvalue(subitem_id) + +Der Wert eines Items relativ zur Item-Id des Objekt-Items wird +ermittelt. + +.. rubric:: Suspend-Ende in einen Text einsetzen + :name: suspendendeineinentexteinsetzen + +.. code-block:: yaml + + stateengine_eval.insert_suspend_time(suspend_item_id, suspend_text="Ausgesetzt bis %X") + +Das Ende der Suspend-Zeit wird in den Text ``suspend_text`` +eingesetzt. Im Text sind daher entsprechende Platzhalter +vorzusehen (Siehe `strftime() and strptime() +Behavior `_). +Wird kein ``suspend_text`` angegeben, so wird als Vorgabewert +"Ausgesetzt bis %X" verwendet. + +Zur Ermittlung des Endes der Suspend-Zeit muss über +``suspend_item_id`` ein Item angegeben werden, dessen Wert bei +Eintritt in den Suspend-Status geändert wird. Über das Alter des +Werts in diesem Item wird die bereits abgelaufene Suspend-Zeit +bestimmt. Dies könnte auch über ein relatives Item angegeben werden, +wobei dieses unbedingt in Anführungszeichen gesetzt werden muss, z.B. ``'..suspend'`` From 6054e1651fac4f064235e1f18ebb8a84c0842fa6 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sun, 23 Dec 2018 16:23:03 +0100 Subject: [PATCH 486/705] Update doc and return values for functions --- uzsu/README.md | 133 ------------------------------------------- uzsu/__init__.py | 7 +++ uzsu/plugin.yaml | 111 +++++++++++++++++++++++++++++++----- uzsu/user_doc.rst | 51 ++++++----------- uzsu/user_doc_en.rst | 129 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 249 insertions(+), 182 deletions(-) create mode 100755 uzsu/user_doc_en.rst diff --git a/uzsu/README.md b/uzsu/README.md index d7e4df54e..f885528a3 100755 --- a/uzsu/README.md +++ b/uzsu/README.md @@ -2,22 +2,6 @@ Provides universal time switches for items (German: *U*niverselle *Z*eit*s*chalt *U*hr) -## Requirements - -Calculating of sunset/sunrise in triggers, requires installation of ephem (which should already be part of core) - -Calculating interpolation requires installation of scipy. Install with: -pip3 install scipy - -Update your Python packages first (but make sure they still meet the requirements for smarthomeng)! - -On Raspberry debian stretch you also have to run: -sudo apt install libatlas-base-dev - -If that does not work you can use: -sudo apt update -sudo apt install -y python3-scipy - ## Changelog ### v1.5.3 @@ -40,120 +24,3 @@ sudo apt install -y python3-scipy * Fixed uzsu evaluation for entries without an rrule setting (day of week) * Automatic deactivating older entries when new entry for exactly the same time (and day) is created (only works with specific VISU widgets) * Improved error handling (detecting wrong items to be set by UZSU, empty entries, etc.) - -## Configuration - -### plugin.yaml - -If remove_duplicates is set to True (default), existing entries with exactly the same settings except the value get replaced by the new entry. - -```yaml -uzsu: - class_name: UZSU - class_path: plugins.uzsu - #remove_duplicates: True -``` - -### items.yaml - -You have to specify an item with `type: dict` and with the `uzsu_item` attribute set to the path of the item which will be set by this item. The hierarchy doesn't matter but it is recommended to define the UZSU item as a child of the item to be set and use the relative item reference '..' for the uzsu_item parameter. It is highly recommended to specify the ``cache: True`` as well for persistent storage of the UZSU information. - -```yaml -# items/my.yaml -someroom: - - someitem: - type: int - - UZSU: - type: dict - uzsu_item: someroom.someitem #using smarthomeNG 1.6 you can use '..' to define a relative item - cache: 'True' - - active: #This can be used to simply (de)activate your uzsu via an item call - type: bool - eval: sh...activate(value) - visu_acl: rw -``` - -## Item Data Format - -Each UZSU item is of type list. Each list entry has to be a dict with specific key and value pairs. Here are the possible keys and what their for: - -* __dtstart__: a datetime object. Exact datetime as start value for the rrule algorithm. Important e.g. for FREQ=MINUTELY rrules (optional). - -* __value__: the value which will be set to the item. - -* __active__: `True` if the entry is activated, `False` if not. A deactivated entry is stored to the database but doesn't trigger the setting of the value. It can be enabled with the `activate` function. - -* __time__: time as string to use sunrise/sunset arithmetics like in the crontab eg. `17:008:00`, `17:00`_ gefunden werden. - - -SmartVISU -========= - -Das UZSU plugin wird durch die smartVISU2.9 sowohl in Form eines Popups als auch einer grafischen Darstellung unterstützt. diff --git a/uzsu/user_doc_en.rst b/uzsu/user_doc_en.rst new file mode 100755 index 000000000..c46556e10 --- /dev/null +++ b/uzsu/user_doc_en.rst @@ -0,0 +1,129 @@ +.. index:: Plugins; uzsu +.. index:: uzsu + +uzsu +#### + +Configuration +============= + +.. important:: + + Please find detailed information on the configuration at :doc:`/plugins_doc/config/uzsu`. + + +.. code-block:: yaml + + # etc/plugin.yaml + uzsu: + plugin_name: uzsu + #remove_duplicates: True + + +.. code-block:: yaml + + # items/my.yaml + someroom: + + someitem: + type: num + + UZSU: + type: dict + uzsu_item: someroom.someitem #With SmarthomeNG 1.6+ you can use '..' instead + cache: 'True' + + active: # You can use this item to easily (de)activate your UZSU via logics or visu. + type: bool + eval: sh...activate(value) + visu_acl: rw + +SmartVISU +========= + +There is a widget available which gives an interface to the UZSU. If you have problems please consult the corresponding forum. It is recommended to use the widget to create UZSU entries. The following information on data format can be skipped. + +Data format +=========== + +Each UZSU item is of type list. Each list entry has to be a dict with specific key and value pairs. Here are the possible keys and what their for: + +- **dtstart**: a datetime object. Exact datetime as start value for the rrule algorithm. Important e.g. for FREQ=MINUTELY rrules (optional). + +- **value**: the value which will be set to the item. + +- **active**: `True` if the entry is activated, `False` if not. A deactivated entry is stored to the database but doesn't trigger the setting of the value. It can be enabled with the `activate` function. + +- **time**: time as string to use sunrise/sunset arithmetics like in the crontab eg. `17:008:00`, `17:00`_ for more examples and getting started info. From a5af3af137352b647d554a587ec070206218632b Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 24 Dec 2018 07:43:40 +0100 Subject: [PATCH 487/705] Darksky: added map_icon method --- darksky/__init__.py | 30 ++++++++++++++++++++++++++++++ darksky/plugin.yaml | 13 ++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/darksky/__init__.py b/darksky/__init__.py index 7d0d646f8..df1fea8c9 100644 --- a/darksky/__init__.py +++ b/darksky/__init__.py @@ -158,6 +158,36 @@ def get_forecast(self): json_obj = response.json() return json_obj + def map_icon(self, icon): + """ + Maps the icons from darksky.net to the icons in SmartVisu + + :param icon icon to map, as string. + :return SmartVisu icon as string. + """ + if icon == 'clear-day': + return 'sun_1' + elif icon == 'clear-night': + return 'sun_1' + elif icon == 'partly-cloudy-day': + return 'sun_4' + elif icon == 'partly-cloudy-night': + return 'sun_4' + elif icon == 'fog': + return 'sun_6' + elif icon == 'rain': + return 'cloud_8' + elif icon == 'wind': + return 'sun_10' + elif icon == 'snow': + return 'sun_12' + elif icon == 'cloudy': + return 'cloud_4' + elif icon == 'sleet': + return 'cloud_11' + else: + return 'high' + def parse_item(self, item): """ Default plugin parse_item method. Is called when the plugin is initialized. Selects each item corresponding to diff --git a/darksky/plugin.yaml b/darksky/plugin.yaml index 83ce39054..490ebb30b 100644 --- a/darksky/plugin.yaml +++ b/darksky/plugin.yaml @@ -79,6 +79,17 @@ item_attributes: de: 'Matchstring basierend auf der Response des "Forecast Request" aus https://darksky.net/dev/docs (Example Request), bspw. "currently/temperature". Ausnahmen: Im Fall von "alerts" wird ein Item vom Typ "list" benötigt, der Wert "alerts_string" schreibt die Alerts-Liste in einen HTML String. Das Array in "flags/sources" wird in ein "str" Item gemerged.' en: 'Matchstring according to the response of the "forecast request" described in https://darksky.net/dev/docs (Example Request), e.g. "currently/temperature". Exceptions: In case of "alerts" an item of type "list" will be filled with raw data, the value "alerts_string" creates a html string with alerts data. The array "flags/sources" will be merged to a string.' -plugin_functions: NONE +plugin_functions: # Definition of function interface of the plugin + map_icon: + type: str + description: + de: "Gibt das SmartVisu Icon zum übergebenen DarkSky Icon zurück." + en: "Returns the SmartVisu icon to the provided DarkSky icon." + parameters: + icon: + type: str + description: + de: "Icon als String." + en: "Icon as string." From fb660e50788e3c034c5c111be51bd5cbb228a5ed Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 24 Dec 2018 08:15:42 +0100 Subject: [PATCH 488/705] Darksky: added example for generating SV icon --- darksky/README.md | 6 ++++++ darksky/plugin.yaml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/darksky/README.md b/darksky/README.md index 205384039..68114d14c 100644 --- a/darksky/README.md +++ b/darksky/README.md @@ -70,6 +70,12 @@ darksky: icon: type: str ds_matchstring: currently/icon + + # create item with icon representation for SmartVisu + icon_sv: + type: str + eval_trigger: darksky.currently.icon + eval: sh.weather_darksky.map_icon(sh.darksky.currently.icon()) nearestStormDistance: type: num diff --git a/darksky/plugin.yaml b/darksky/plugin.yaml index 490ebb30b..d5cc26fc1 100644 --- a/darksky/plugin.yaml +++ b/darksky/plugin.yaml @@ -16,7 +16,7 @@ plugin: sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance - restartable: unknown + restartable: True classname: DarkSky # class containing the plugin parameters: From ee10ef25b2b99db9d7e1acacc14fa9f14e3e683f Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 24 Dec 2018 08:35:10 +0100 Subject: [PATCH 489/705] Darksky: added example to access forcast for day0 (can be adapted for other days similarly) --- darksky/README.md | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/darksky/README.md b/darksky/README.md index 68114d14c..099b415b7 100644 --- a/darksky/README.md +++ b/darksky/README.md @@ -173,7 +173,34 @@ darksky: icon: type: str - ds_matchstring: daily/icon + ds_matchstring: daily/icon + + data: + type: list + ds_matchstring: daily/data + cache: 'yes' + + day0: + date: + type: str + eval_trigger: darksky.daily.data + eval: datetime.datetime.fromtimestamp(sh.darksky.daily.data()[0]['time']).strftime('%a %d.%m.%Y') + + icon: + type: str + eval_trigger: darksky.daily.data + eval: sh.darksky.daily.data()[0]['icon'] + + icon_sv: + type: str + eval_trigger: darksky.daily.day0.icon + eval: sh.darksky_weather.map_icon(sh.darksky.daily.day0()) + + temperature_max: + type: num + eval_trigger: darksky.daily.data + eval: sh.darksky.daily.data()[0]['temperatureMax'] + alerts: From 984d197a20da246a7af9f7ed40200106ffa7a4f5 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 24 Dec 2018 08:40:32 +0100 Subject: [PATCH 490/705] Darksky: corrected items and added comments --- darksky/README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/darksky/README.md b/darksky/README.md index 099b415b7..a5979a902 100644 --- a/darksky/README.md +++ b/darksky/README.md @@ -71,7 +71,7 @@ darksky: type: str ds_matchstring: currently/icon - # create item with icon representation for SmartVisu + # create item with icon representation for SmartVisu, won't show up in Plugin's Web Interface icon_sv: type: str eval_trigger: darksky.currently.icon @@ -173,13 +173,19 @@ darksky: icon: type: str - ds_matchstring: daily/icon + ds_matchstring: daily/icon + + icon_sv: + type: str + eval_trigger: darksky.daily.icon + eval: sh.darksky_weather.map_icon(sh.darksky.daily.icon()) data: type: list ds_matchstring: daily/data cache: 'yes' + # all day0 child items wont show up in WebIf of plugin! Use item tree to check! day0: date: type: str @@ -190,11 +196,11 @@ darksky: type: str eval_trigger: darksky.daily.data eval: sh.darksky.daily.data()[0]['icon'] - + icon_sv: type: str eval_trigger: darksky.daily.day0.icon - eval: sh.darksky_weather.map_icon(sh.darksky.daily.day0()) + eval: sh.darksky_weather.map_icon(sh.darksky.daily.day0.icon()) temperature_max: type: num From daf5fef0c52d53b0073398fe0671b778c4917852 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 24 Dec 2018 08:51:35 +0100 Subject: [PATCH 491/705] Darksky: added examples for day1 and day2 forecast to readme --- avdevice/denon-avr6300.txt | 115 +++++++++++++++++++++++++++++++++++++ darksky/README.md | 43 +++++++++++++- 2 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 avdevice/denon-avr6300.txt diff --git a/avdevice/denon-avr6300.txt b/avdevice/denon-avr6300.txt new file mode 100644 index 000000000..5300530a0 --- /dev/null +++ b/avdevice/denon-avr6300.txt @@ -0,0 +1,115 @@ +ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MINVALUE; MAXVALUE; RESPONSETYPE + +# General Commands +0; power; on; PWON|PWON; PW?; PW**; RW +0; power; off; PWSTANDBY; PW?; PW*******; RW +0; eco; set; ECO*; ECO?; ECO*; RW; ; ; ; str|bool +0; up; ; MNCUP; ; ; W +0; down; ; MNCDN; ; ; W +0; left; ; MNCLT; ; ; W +0; right; ; MNCRT; ; ; W +0; enter; ; MNENT; ; ; W +0; info; ; MNINF; ; ; W +0; menu; on; MNMEN ON; MNMEN?; MNMEN **; RW +0; menu; off; MNMEN OFF; MNMEN?; MNMEN ***; RW +# Firmware response often hast problems. Not recommended to implement this command. +#0; firmware; ; ; UGIDN; UGIDN ************|UGIDN **; R +# The display command is only working with receivers without HEOS +#0; display; ; NSE; NSE; NSA*|NSE*; RW; ; ; ; str + + +# Zone 1 +1; power; on; ZMON; ZM?; ZM**; RW +1; power; off; ZMOFF; ZM?; ZM***; RW +1; mute; on; MUON; MU?; MU**; RW +1; mute; off; MUOFF; MU?; MU***; RW +1; sleep; set; SLP***; SLP?; SLP***; RW; ; 0; 120; num|bool +1; standby; set; STBY***; STBY?; STBY***; RW; ; ; ; ; denon_standby +1; volume; set; MV**; MV?; MV**|MV***; RW; ; 30; 90; num; denon_volume +1; volume+; increase; MVUP; ; MV; W +1; volume-; decrease; MVDOWN; ; MV; W +1; volumelow; ; MV50; MV?; MV50; W; ; ; ; num +1; volumehigh; ; MV75; MV?; MV75; W; ; ; ; num +1; volumemax; set; MVMAX **; MV?; MVMAX **|MVMAX ***; RW; ; ; ; ; denon_volume +1; input; set; SI*; SI?; SI*; RW; ; ; ; str +1; mode; set; MS*; MS?; MS*; RW; ; ; ; str +1; audioinput; set; SD*; SD?; SD*; RW; ; ; ; str +1; videoinput; set; SV*; SV?; SV*; RW; ; ; ; str|bool + +# Finetuning +1; tone; on; PSTONE CTRL ON; PSTONE CTRL ?; PSTONE CTRL **; RW +1; tone; off; PSTONE CTRL OFF; PSTONE CTRL ?; PSTONE CTRL ***; RW +1; bass; set; PSBAS **; PSBAS ?; PSBAS **; RW; ; 40; 60 +1; trebble; set; PSTRE **; PSTRE ?; PSTRE **; RW; ; 40; 60 +1; bass+; increase; PSBAS UP; ; PSBAS; W +1; bass-; decrease; PSBAS DOWN; ; PSBAS; W +1; trebble+; increase; PSTRE UP; ; PSTRE; W +1; trebble-; decrease; PSTRE DOWN; ; PSTRE; W +1; dialogtoggle; on; PSDIL ON; PSDIL ?; PSDIL **; RW +1; dialogtoggle; off; PSDIL OFF; PSDIL ?; PSDIL ***; RW +1; dialog; set; PSDIL **; PSDIL ?; PSDIL **; RW; ; 0; 62 +1; subwoofertoggle; on; PSSWL ON; PSSWL ?; PSSWL **; RW +1; subwoofertoggle; off; PSSWL OFF; PSSWL ?; PSSWL ***; RW +1; subwoofer; set; PSSWL **; PSSWL ?; PSSWL **; RW; ; 0; 62 +1; cinemaeq; on; PSCINEMA EQ.ON; PSCINEMA EQ. ?; PSCINEMA EQ.**; RW +1; cinemaeq; off; PSCINEMA EQ.OFF; PSCINEMA EQ. ?; PSCINEMA EQ.***; RW +1; mainspeakers; set; PSSP:*; PSSP: ?; PSSP:*; RW; ; ; ; str +1; dynamicrange+; increase; PVENH UP; PVENH ?; PVENH; W +1; dynamicrange-; decrease; PVENH DOWN; PVENH ?; PVENH; W +1; dynamicrange; set; PVENH **; PVENH ?; PVENH **; RW; ; 0; 12 + +# Seperate Volume Control +1; volumefl; set; CVFL **; CV?; CVFL **|CVFL ***; RW; ; 0; 62; num; denon_volume +1; volumefl+; increase; CVFL UP; CV?; CVFL; W +1; volumefl-; decrease; CVFL DOWN; CV?; CVFL; W +1; volumefr; set; CVFR **; CV?; CVFR **|CVFR ***; RW; ; 0; 62; num; denon_volume +1; volumefr+; increase; CVFL UP; CV?; CVFR; W +1; volumefr-; decrease; CVFR DOWN; CV?; CVFR; W +1; volumec; set; CVC **; CV?; CVC **|CVC ***; RW; ; 0; 62; num; denon_volume +1; volumec+; increase; CVC UP; CV?; CVC; W +1; volumec-; decrease; CVC DOWN; CV?; CVC; W +1; volumec; set; CVC **; CV?; CVC **|CVC ***; RW; ; 0; 62; num; denon_volume +1; volumec+; increase; CVC UP; CV?; CVC; W +1; volumec-; decrease; CVC DOWN; CV?; CVC; W +1; volumesl; set; CVSL **; CV?; CVSL **|CVSL ***; RW; ; 0; 62; num; denon_volume +1; volumesl+; increase; CVSL UP; CV?; CVSL; W +1; volumesl-; decrease; CVSL DOWN; CV?; CVSL; W +1; volumesr; set; CVSR **; CV?; CVSR **|CVSR ***; RW; ; 0; 62; num; denon_volume +1; volumesr+; increase; CVSR UP; CV?; CVSR; W +1; volumesr-; decrease; CVSR DOWN; CV?; CVSR; W + +# Videoparams +1; aspectratio; set; VSASP*; VSASP ?; VSASP*; RW; ; ; ; str +1; monitorout; set; VSMONI*; VSMONI ?; VSMONI*; RW; ; ; ; int|str +1; resolution; set; VSSC*; VSSC ?; VSSC*; RW; ; ; ; str +1; audioout; set; VSAUDIO *; VSAUDIO ?; VSAUDIO *; RW; ; ; ; str +1; videoprocessing; set; VSVPM*; VSVPM ?; VSVPM*; RW; ; ; ; str +1; stretch; set; VSVST*; VSVST ?; VSVST*; RW; ; ; ; bool + +# Zone 2 +2; power; on; Z2ON; Z2?; Z2**; RW +2; power; off; Z2OFF; Z2?; Z2***; RW +2; input; set; Z2*; Z2?; Z2*; RW; ; ; ; str +2; mute; on; Z2MUON; Z2MU?; Z2MU**; RW +2; mute; off; Z2MUOFF; Z2MU?; Z2MU***; RW +2; volume+; increase; Z2UP; ; Z2; W +2; volume-; decrease; Z2DOWN; ; Z2; W +2; volumelow; ; Z250; MV?; Z250; W; ; ; ; num +2; volumehigh; ; Z275; MV?; Z275; W; ; ; ; num +2; volume; set; Z2**; Z2?; Z2**; RW; num; 0; 90 +2; standby; set; Z2STBY*; Z2STBY?; Z2STBY*; RW; ; ; ; str|bool +2; sleep; set; Z2SLP***; Z2SLP?; Z2SLP***; RW; ; 0; 120; num|bool + +# Zone 3 +3; power; on; Z3ON; Z3?; Z3**; RW +3; power; off; Z3OFF; Z3?; Z3***; RW +3; input; set; Z3*; Z3?; Z3*; RW; ; ; ; str +3; mute; on; Z3MUON; Z3MU?; Z3MU**; RW +3; mute; off; Z3MUOFF; Z3MU?; Z3MU***; RW +3; volume+; increase; Z3UP; ; Z3; W +3; volume-; decrease; Z3DOWN; ; Z3; W +3; volumelow; ; Z350; MV?; Z350; W; ; ; ; num +3; volumehigh; ; Z375; MV?; Z375; W; ; ; ; num +3; volume; set; Z3**; Z3?; Z3**; RW; num; 0; 90 +3; standby; set; Z3STBY*; Z3STBY?; Z3STBY*; RW; ; ; ; str|bool +3; sleep; set; Z3SLP***; Z3SLP?; Z3SLP***; RW; ; 0; 120; num|bool diff --git a/darksky/README.md b/darksky/README.md index a5979a902..1dcfe4f96 100644 --- a/darksky/README.md +++ b/darksky/README.md @@ -185,7 +185,7 @@ darksky: ds_matchstring: daily/data cache: 'yes' - # all day0 child items wont show up in WebIf of plugin! Use item tree to check! + # all day0, day1, day2 ... items won't show up in WebIf of plugin! Use item tree to check! day0: date: type: str @@ -206,7 +206,48 @@ darksky: type: num eval_trigger: darksky.daily.data eval: sh.darksky.daily.data()[0]['temperatureMax'] + + day1: + date: + type: str + eval_trigger: darksky.daily.data + eval: datetime.datetime.fromtimestamp(sh.darksky.daily.data()[1]['time']).strftime('%a %d.%m.%Y') + + icon: + type: str + eval_trigger: darksky.daily.data + eval: sh.darksky.daily.data()[1]['icon'] + + icon_sv: + type: str + eval_trigger: darksky.daily.day1.icon + eval: sh.darksky_weather.map_icon(sh.darksky.daily.day1.icon()) + + temperature_max: + type: num + eval_trigger: darksky.daily.data + eval: sh.darksky.daily.data()[1]['temperatureMax'] + + day2: + date: + type: str + eval_trigger: darksky.daily.data + eval: datetime.datetime.fromtimestamp(sh.darksky.daily.data()[2]['time']).strftime('%a %d.%m.%Y') + + icon: + type: str + eval_trigger: darksky.daily.data + eval: sh.darksky.daily.data()[2]['icon'] + + icon_sv: + type: str + eval_trigger: darksky.daily.day2.icon + eval: sh.darksky_weather.map_icon(sh.darksky.daily.day2.icon()) + temperature_max: + type: num + eval_trigger: darksky.daily.data + eval: sh.darksky.daily.data()[2]['temperatureMax'] alerts: From 93271ca11adf3d0cb012603c00c55b1e144c2d49 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 24 Dec 2018 08:53:37 +0100 Subject: [PATCH 492/705] Darksky: upgraded version due to new api function --- darksky/README.md | 2 +- darksky/__init__.py | 4 ++-- darksky/plugin.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/darksky/README.md b/darksky/README.md index 1dcfe4f96..f0d5bda15 100644 --- a/darksky/README.md +++ b/darksky/README.md @@ -1,6 +1,6 @@ # darksky.net / forecast.io -#### Version 1.5.0.1 +#### Version 1.5.0.2 This plugins can be used retrieve weather information from darksky.net / forecast.io. diff --git a/darksky/__init__.py b/darksky/__init__.py index df1fea8c9..b45cdb465 100644 --- a/darksky/__init__.py +++ b/darksky/__init__.py @@ -2,7 +2,7 @@ # ######################################################################### # Copyright 2018 René Frieß rene.friess(a)gmail.com -# Version 1.5.0.1 +# Version 1.5.0.2 ######################################################################### # # This file is part of SmartHomeNG. @@ -32,7 +32,7 @@ class DarkSky(SmartPlugin): - PLUGIN_VERSION = "1.5.0.1" + PLUGIN_VERSION = "1.5.0.2" _base_forecast_url = 'https://api.darksky.net/forecast/%s/%s,%s' diff --git a/darksky/plugin.yaml b/darksky/plugin.yaml index d5cc26fc1..180355937 100644 --- a/darksky/plugin.yaml +++ b/darksky/plugin.yaml @@ -12,7 +12,7 @@ plugin: documentation: 'https://www.smarthomeng.de/user/plugins/darksky/user_doc.html' support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/1244744-neues-plugin-wetterdaten-via-darksky-net-forecast-io' keywords: weather - version: 1.5.0.1 # Plugin version + version: 1.5.0.2 # Plugin version sh_minversion: 1.4c # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance From 200ad1092a9bf8e0e1453b1df6e379a56dcb0a15 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 24 Dec 2018 08:55:27 +0100 Subject: [PATCH 493/705] Darksky: updated link to forum in readme --- darksky/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/darksky/README.md b/darksky/README.md index f0d5bda15..0b2ac6158 100644 --- a/darksky/README.md +++ b/darksky/README.md @@ -5,7 +5,7 @@ This plugins can be used retrieve weather information from darksky.net / forecast.io. ## Support -Support is provided trough the support thread within the smarthomeNG forum: [Smarthome.py](https://knx-user-forum.de/forum/supportforen/smarthome-py) +Support is provided trough the support thread within the smarthomeNG forum: [Neues Plugin: Wetterdaten via darksky.net / forecast.io](https://knx-user-forum.de/forum/supportforen/smarthome-py/1244744-neues-plugin-wetterdaten-via-darksky-net-forecast-io) ### Requirements From 83439ddaafc969a2b5e67aae683a0445c21b9515 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Wed, 26 Dec 2018 14:56:03 +0100 Subject: [PATCH 494/705] Update metadata and documentation --- avdevice/README.md | 441 +----------------------------- avdevice/avdevice_webif.png | Bin 0 -> 413502 bytes avdevice/plugin.yaml | 224 +++++++++++---- avdevice/requirements.txt | 1 + avdevice/user_doc.rst | 449 ++++++++++++++++++++++++++++++ avdevice/user_doc_en.rst | 530 ++++++++++++++++++++++++++++++++++++ 6 files changed, 1148 insertions(+), 497 deletions(-) create mode 100644 avdevice/avdevice_webif.png create mode 100644 avdevice/requirements.txt create mode 100755 avdevice/user_doc.rst create mode 100755 avdevice/user_doc_en.rst diff --git a/avdevice/README.md b/avdevice/README.md index c1be2b1a6..5ddfc9a2c 100755 --- a/avdevice/README.md +++ b/avdevice/README.md @@ -1,16 +1,9 @@ # AV Device -## Requirements -If you want to connect to your device via RS232 (recommended) you need to install: -Serial Python module +## Documentation -Install it with: -sudo pip3 install serial --upgrade - -## Supported Hardware - -Hopefully several different AV devices based on TCP or Serial RS232 connections -Tested with Pioneer (< 2016 models) and Denon AV receivers, Epson projector Oppo Bluray player +For info on the features and the different command files, etc. see the [User Documentation](https://www.smarthomeng.de/user/plugins/avdevice/user_doc.html "Manual") +For info on how to configure the plugin see the [Configuration Documentation](https://www.smarthomeng.de/plugins_doc/config/avdevice "Configuration") ## Changelog @@ -53,431 +46,3 @@ Tested with Pioneer (< 2016 models) and Denon AV receivers, Epson projector Oppo ### v1.3.2 * Added and tested full Denon support - - -## Configuration - -### plugin.yaml - -``` -# etc/plugin.yaml -avdevice: - class_name: AVDevice - class_path: plugins.avdevice - model: sc-lx86 - #instance: pioneer_one - tcp_ip: 10.0.0.130 - #tcp_port: 23 - #tcp_timeout: 1 - rs232_port: /dev/ttyUSB1 - #rs232_baudrate: 9600 - #rs232_timeout: 0.1 - #ignoreresponse: 'RGB,RGC,RGD,GBH,GHH,VTA,AUA,AUB' - #forcebuffer: 'GEH01020, GEH04022, GEH05024' - #inputignoredisplay: '' - #dependson_item: '' - #dependson_value: True - #errorresponse: E02, E04, E06 - #resetonerror: False - #depend0_power0: False - #depend0_volume0: False - #sendretries: 10 - #resendwait: 1.0 - #reconnectretries: 13 - #reconnectcycle: 10 - #secondstokeep: 50 - #responsebuffer: 5 - #autoreconnect: false - #update_exclude: '' -``` - - -#### Attributes: - -* `model`: string. name of AV device. Has to correspond to a text file with the same name in the folder plugins/avdevice. -* `instance`: string. define instance name, each device needs an individual instance name! -* `tcp_ip`: IP address -* `tcp_port`: TCP/IP port -* `tcp_timeout`: TCP/IP timeout -* `rs232_port`: If you use a RS232 cable to communicate with your device (highly recommended!) define the interface port -* `rs232_baudrate`: baudrate for RS232 -* `rs232_timeout`: timeout for RS232 -* `ignoreresponse`: list of values. the plugin doesn't care about responses from the device starting with the given values. List responses for menu navigation, etc. For Pioneer receivers the following list is recommended: RGB, RGC, RGD, GBH, GHH, VTA, AUA, AUB -* `forcedbuffer`: list of strings. If for whatever reason you don't want to buffer the response from your device you can still define specific responses that should get buffered. This is important for responses that change very quickly. Artist, title, radio station, etc. are examples that should be put here. Furthermore the response buffer from the device usually gets cleaned of duplicate values. If you need to keep specific answers in the buffer even as duplicates, define them here, too. This could be relevant for multiple "cursor up" or "cursor down" commands. For Pioneer receivers the following list is recommended: GEH01020, GEH04022, GEH05024, R. -* `inputignoredisplay`: list of int. The value of the LCD display on your receiver might get updated very often, e.g. when it shows song titles as a scrolling text. To avoid constant display updates and therefore possible confusion with relevant answers of your device listing source inputs like internet radio, LAN streaming, etc. here is highly recommended. For Pioneer receivers the following list is recommended: 26,38,40,41,44,17,02,48,0 -* `dependson_item`: item. If given item has given value the commands are sent to the device, otherwise they are not. Relevant if you have your device connected to a power socket that can be turned off. -* `dependson_value`: boolean. If given item has given value the commands are sent to the device, otherwise they are not. Relevant if you have your device connected to a power socket that can be turned off. -* `errorresponse`: list of strings. The standard error responses from your device. For Pioneer receivers they are "E" followed by a number. If no values are provided error answers from your device might get recognized much slower but actually should still get recognized. -* `resetonerror`: boolean. Reset the value of the item that could not be updated. E.g. you set the volume of zone 2 to "100". If either the dependson item is off or the device sends an error response or after several connection and send retries the expected response is not received, the volume item gets set to value it had before you sent the command. That way you avoid having a wrong value displayed in your Visu. -* `depend0_power0`: boolean. If the dependson item is off the power off all zones are set to off. This is especially relevant for a correct representation in your Visu when you have a powered on device but turn off the power socket. -* `depend0_volume0`: boolean. Same as above but in this case the volume is set to 0 for all zones. This is for Visu purposes only. -* `sendretries`: integer. This value defines how often a command should be sent when receiving a wrong answer from the device. -* `resendwait`: float. Seconds the plugin should wait between each resend retry. -* `reconnectretries`: integer. If the plugin can not connect to the device it retries this often. This is especially useful for TCP connections on devices that are plugged into a switchable socket as most receivers need about 40-50 seconds to boot their network device. -* `secondstokeep`: integer. Seconds the plugin should temporarily save a command to retry later on after establishing a connection. This is especially useful for TCP connections on devices that are plugged into a switchable socket as most receivers need about 40-50 seconds to boot their network device. -* `responsebuffer`: integer or boolean. Set this to a number to collect quickly received responses in a buffer and evaluate them collectively. The standard value should be fine and prevent responses getting lost. Some receivers might first respond to a command with an update of the display and then with the actual value. The buffer ensures the correct evaluation of the response. -* `autoreconnect`: boolean. Automatically tries to reconnect if no response is received or connection is lost. This should not be necessary as the plugin always tries to reconnect before sending a command. -* `update_exclude`: string. Define smarthomeNG callers that should be ignored if they change an item. An example would be on_update or on_change. If you use i.e. on_update on an item using avdevice you might get stuck in an endless loop. Use this attribute to avoid this. -* `statusquery`: bool. If set to true (default) value will get queried after connection or manual statusupdate. If set to false only those items with depend=init will get updated. - -### items.yaml - -#### avdevice_zone[0-4]@[instance]: [command] - -Specifiy the zone number and instance. If you don't use zones you can either use "avdevice" or "avdevice_zone0" as attributes. - -The command has to correspond to a "base" command in the relevant text configuration file in the avdevice plugin folder named the same as the "model" configured in plugin.yaml. -It is important to set the correct type for each item. The Pioneer RS232 codeset expects bool and int types only. -For example to set the listening mode to "pure direct", the item has to be int and you set it to the value "8". If you want to use the "translation-feature" you should set the item to "foo". This feature is explained later. - -Full item examples are included as separate yaml files for Pioneer and Denon devices. In general the items are setup the same, independent of the AV device model. The examples include the tested items/commands and allow easy copy/paste. - -You can use two special avdevice attribute values if you want: -* `avdevice: statusupdate`: Use this item to trigger a full statusupdate. All query commands regarding the currently powered on zones are sent. This is especially useful if you have a power socket you can switch on or off and want to update all items on connection. -* `avdevice: reload`: Use this item to reload your text configurations. This re-reads the config as well as translation files and recreates all functions and commands. This is useful if you find an error in your configuration file or if you want to add new commands while smarthomeNG is running. You don't need to restart the plugin to reload the config! - -#### Example - -``` -# items/my.yaml -Pioneer: - type: foo - - Update: - type: bool - visu_acl: rw - avdevice: statusupdate - enforce_updates: 'yes' - - Reload: - type: bool - visu_acl: rw - avdevice: reload - enforce_updates: 'yes' - - Power: - type: bool - visu_acl: rw - avdevice_zone1: power - -``` -#### avdevice_zone[0-4]_speakers@[instance]: [command] - -Specifiy the zone number and instance. -Speakers Items are special and should be set up the way mentioned in the following example. 1 and 2 correspond to the value the speaker command expects (for example for Pioneer receivers < 2016). - -#### Example - -``` -# items/my.yaml -Pioneer: - type: foo - - Speakers: - type: num - visu_acl: rw - avdevice_zone1: speakers - - SpeakerA: - type: bool - visu_acl: rw - avdevice_zone1_speakers: 1 - - SpeakerB: - type: bool - visu_acl: rw - avdevice_zone1_speakers: 2 - -``` - -#### avdevice_zone[0-4]_depend@[instance]: [command] - -Specifiy the zone number and instance. -The depend attribute lets you specifiy for each item if it depends on another item/function. If you define such a dependency several things will happen: -- The item only gets updated/changed if the dependency is fullfilled -- Query command of the item will get removed from the queue if the dependency is not fullfilled -- Query command of the item will (only) get added if one of the "master" items gets changed and the dependency is fullfilled. -- After connecting to the device the query command of an item only gets added if you add "init" to the dependency configuration. - -You can use multiple depend items and attributes even for different zones. You can even define "and/or" for the dependencies by adding up to four different groups (a, b, c, d) after the value seperated by a comma ",". - -You can not only define a "master" item but also a "master value" and several standard python comparison operators. - -If you don't set an operator and value, "==" and "True" is assumed. If you don't set a group, group "a" is assumed. This means, if you add several dependent function without a group, the functions will get evaluated as "or" and dependency is fullfilled as soon as one of the functions/items corresponds to the given value. - -The example below shows the following dependencies: -- The disctype will always be queried after connecting to the device (as long as you have specified a query command in the command-file) -- Audio language and encoding will be queried after connecting to the device or as soon as the item with the "play" function (Oppo.Play) is True -- The track will get updated/queried if these dependencies are fullfilled: (play is True or status is play) AND verbose is set to 2 AND audiotype is either PCM or PCM 44.1/16 -- The trackname will get updated/queried if these dependencies are fullfilled: (play is True or status is play) AND verbose is set to 2 AND audiotype is either PCM or PCM 44.1/16 AND disctpye is one of these three values: DVD-AUDIO, CDDA, DATA-DISC - -#### Example - -``` -# items/my.yaml -Oppo: - type: foo - - Power: - visu_acl: rw - type: bool - avdevice@oppo: power - - Verbose: - visu_acl: rw - type: num - cache: 'false' - enforce_updates: 'yes' - avdevice@oppo: verbose - - Status: - visu_acl: rw - type: str - cache: 'False' - enforce_updates: 'yes' - avdevice@oppo: status - on_change: - - ..Pause = True if value == 'PAUSE' else False - - ..Stop = True if not (value == 'PLAY' or value == 'PAUSE' or value == 'INVALID') else False - - ..Play = True if value == 'PLAY' else False - - Play: - visu_acl: rw - type: bool - enforce_updates: 'yes' - avdevice@oppo: play - - Disctype: - visu_acl: rw - type: str - cache: 'False' - enforce_updates: 'yes' - avdevice@oppo: disctype - avdevice_depend@oppo: init - - Audio: - type: foo - - Language: - visu_acl: rw - type: str - cache: 'False' - enforce_updates: 'yes' - avdevice@oppo: audiolanguage - avdevice_depend@oppo: - - play - - init - - Encoding: - visu_acl: rw - type: str - cache: 'False' - enforce_updates: 'yes' - avdevice@oppo: audiotype - avdevice_depend@oppo: - - play - - init - - Track: - visu_acl: rw - type: num - cache: 'False' - enforce_updates: 'yes' - avdevice@oppo: audiotrack - avdevice_depend@oppo: - - play = True, a - - status = PLAY, a - - verbose = 2, b - - audiotype = PCM, c - - audiotype = PCM 44.1/16, c - - Trackname: - visu_acl: rw - type: str - avdevice@oppo: trackname - avdevice_depend@oppo: - - disctype = DVD-AUDIO, a - - disctype = CDDA, a - - disctype = DATA-DISC, a - - play = True, b - - status = PLAY, b - - audiotype = PCM, c - - audiotype = PCM 44.1/16, c - - verbose = 2, d -``` - -#### avdevice_zone[0-4]_init@[instance]: [command] - -Specifiy the zone number and instance. -The init attribute lets you set a specific command to a specific value as soon as the device is connected. For example if you want to always unmute your device as soon as the plugin connects to it (at startup and after turning on the power socket or reconnecting the cable) you can define an additional item with the attribute "avdevice_init". The value of that item (Oppo.Verbose.Init) gets written to the linked item (Oppo.Verbose). - -You can use multiple init items and attributes even for different zones. - -#### Example - -``` -# items/my.yaml -Oppo: - type: foo - Verbose: - type: bool - visu_acl: rw - avdevice_zone1: verbose - - Init: - visu_acl: rw - type: bool - cache: 'true' - value: 2 - avdevice_zone1_init: verbose - -Pioneer: - type: foo - - Zone1: - type: foo - - Mute: - type: bool - visu_acl: rw - avdevice_zone1: mute - - Init: - visu_acl: rw - type: bool - cache: 'true' - value: True - avdevice_zone1_init: mute - - Zone2: - type: foo - - Mute: - type: bool - visu_acl: rw - avdevice_zone2: mute - - Init: - visu_acl: rw - type: bool - cache: 'true' - value: True - avdevice_zone2_init: mute - -``` - -### model.txt - -#### ZONE;FUNCTION;FUNCTIONTYPE;SEND;QUERY;RESPONSE;READWRITE;INVERTRESPONSE;MINVALUE;MAXVALUE;RESPONSETYPE;TRANSLATIONFILE - -Configure your commands depending on your model and manufacturer. You have to name the file the same as configured in the plugin.yaml as "model". E.g. if you've configured "model: vsx-923" you name the file "vsx-923.txt" - -Each line holds one specific command that should be sent to the device. You also specify the zone, the query command, response command, etc. You can comment out lines by placing a # in front of the line. You can also comment a whole block by using ''' at the beginning and end of a block. - -* `zone`: Number of zone. Has to correspond to the attribute in item.yaml. E.g. for zone 1 use "avdevice_zone1: command". Zone 0 holds special commands like navigating in the menu, display reponse, information about currently playing songs, etc. - -* `function`: name of the function. You can name it whatever you like. You reference this value in the item using avdevice_zoneX: function. - -* `functiontype`: for boolean functions use "on" or "off". For commands setting a specific value like source, input mode, volume, etc. use "set". To increase or decrease a value use the corresponding "increase" or "decrease". For everything else leave empty! - -* `send`: the command to be sent, e.g. power off is "PF" for Pioneer receivers. You can use a pipe "|" if more than one command should be sent. Add an integer or float to specify a pause in seconds between the commands, like "PO|2|PO". That might be necessary for power on commands via RS232, e.g. for Pioneer receivers to power on "PO|PO" forces the plugin to send the "PO" command twice. Use stars "\*" to specify the format of the value to be sent. Let's say your device expects the value for volume as 3 digits, a "\*\*\*VL" ensures that even setting the volume to "5" sends the command as "005VL" - -* `query`: Query command. This is usually useful after setting up the connection or turning on the power. This command gets also used if the plugin doesn't receive the correct answer after sending a command. It is recommended to leave this value empty for all functions except on, off and set. - -* `response`: The expected response after sending a command. Use "none" if you don't want to wait for the correct response. You can use stars "\*" again to ensure that the exact correct value is set. Example: You set the volume to 100. If you want to ensure that the device responds with any value for volume just use "VOL" here (or whatever response your device sends). If you want to ensure that the device is set to a volume of 100, use stars as placeholders, e.g. "VOL\*\*\*" for 3 digits. You can even specify multiple response possibilities separated by "|". - -* `readwrite`: R for read only, W for write only, RW for Read and Write. E.g. display values are read only whereas turning the volume up might be a write operation only. Setting this correctly ensures a fast and reliable plugin operation - -* `invertresponse`: some devices are stupid enough to reply with a "0" for "on" and "1" for "off". E.g. a Pioneer receiver responds with "PWR0" if the device is turned on. Configure with "yes" if your device is quite stupid, too. - -* `minvalue`: You can define the minimum value for setting a specific function. This might be most relevant for setting the volume or bass/trebble values. If you configure this with "-3" and set the bass to "-5" (via Visu or CLI) the value will get clamped by the plugin and set to "-3". - -* `maxvalue`: You can define the maximum value for setting a specific function. This might be most relevant for setting the volume. If you configure this with "100" and set the volume to "240" (via Visu or CLI) the value will get clamped by the plugin and set to "100". - -* `responsetype`: Defines the type of the response value and can be set to "bool", "num" or "str" or a mixture of them (separated by a pipe "|" or comma ","). Most response types are set automatically on startup but you can force a specific type using this value. It is recommended to use the values suggested in the txt files that come with the plugin. - -* `translationfile`: If you want to translate a specific value/code to something else, define a txt file here that holds the information on how to translate which value - -#### Example - -``` -# plugins/avdevice/pioneer.txt -ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MINVALUE; MAXVALUE; RESPONSETYPE; TRANSLATIONFILE -1; power; on; PO|PO; ?P; PWR*; RW; yes -1; power; off; PF; ?P; PWR*; RW; yes -1; volume+; increase; VU; ; VOL; W -1; volume-; decrease; VD; ; VOL; W -1; volume; set; ***VL; ?V; VOL***; RW; ; 80; 185 -1; input; set; **FN; ?F; FN**; RW -1; speakers; set; *SPK; ?SPK; SPK*; RW -''' -#commented out from here -2; power; on; APO|APO; ?AP; APR*; RW; yes -2; power; off; APF; ?AP; APR*; RW; yes -0; title; ; ; ; GEH01020; R -0; station; ; ; ; GEH04022; R -0; genre; ; ; ; GEH05024; R -#commented out until here -''' -0; display; ; ?FL; ?FL; FL******************************; R -1; input; set; **FN; ?F; FN**; RW; ; ; ; ; pioneer_input -1; mode; set; ****SR; ?S; SR****; RW; ; ; ; num; pioneer_SR -1; playingmode; ; ?L; ?L; LM****; R; ; ; ; str,int; pioneer_LM -#0; test; ; ; ; noidea; R (commented out) -``` - -### Translation - -Define a filename that contains translations in your main model.txt as seen above. -You could create a file called denon_volume.txt and link it in your model.txt file to convert 3 digit volume to a float. Denon receivers handle e.g. 50.5 as 505. If you want to use value limits or visualize the volume correctly in your VISU you should use the following translation file: - -``` -# plugins/avdevice/denon_volume.txt -CODE; TRANSLATION -***; **.* -``` - -Pioneer receivers use numbers to define input source or listening mode what is very cryptic and not very user friendly. Therefore you should use the relevant files in the plugins folder like pioneer_input. That file looks something like this: - -``` -# plugins/avdevice/pioneer_input.txt -CODE; TRANSLATION -00; PHONO -01; CD -02; TUNER -``` - -Now, when the plugin receives FN01 as a response, the response gets converted to "CD". Vice versa you can even update your item to "CD" and the plugin will send "01FN" as a command. It is advised to define the according item as type=foo so you can either use a number or string, just the way you like. - -### Wildcards - -For the model.txt file you can use question marks as a wild card if the response of the device includes information for several different items. This is the case with a lot of responses from Oppo bluray players. - -Use a "?" for "any single character", use "??" for "two characters of any value" and so on. If the length of the wildcard can differ, use a "?{str}" meaning that the plugin expects a string of any given length. - -The definition for audiotype in the example means that the expected response consists of: -"@QAT OK " in the beginning followed by a single character followed by a "/" and another single character again. After that is the relevant part of the response, the value of the item, defined by exactly three digits/characters. Behind that is a blank and any value consisting of five characters or digits. - -The example definition for audiotrack means that the response can be: "@UAT " followed by any word/number without a specific length, followed by a blank and the real value consisting of two characters. The response could also start with "@QTK OK " followed by the relevant value consisting of exactly one digit/character. After that there will be a "/" and any character/digit. It is important to add the "/?" in the end because the plugin also compares the length of the response with the expected length (calculated from the response in the command-file). It is not relevant, if you use a {str} in your response because then the length can not be determined. - -This feature is still under development. Feel free to experiment with it and post your experience in the knx-forum. - -#### Example - -``` -# plugins/avdevice/oppo-udp203.txt -ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MINVALUE; MAXVALUE; RESPONSETYPE; TRANSLATIONFILE -0; audiotype; ; ; #QAT; @QAT OK ?/? *** ?????; R; ; ; ; str -0; audiotrack; ; #AUD; #QTK; @UAT ?{str} **|@QTK OK */?; RW; ; ; ; num -``` - -## Troubleshooting -1.) Have a look at the smarthome logfile. If you can't figure out the reason for your problem, change the verbose level in logging.yaml. -You can use level 10 (=DEBUG), 9 (VERBOSE1) and 8 (VERBOSE2) as debugging levels. - -2.) Concerning send and response entries in the textfile, make sure the number of stars correspond to the way your device wants to receive the command or sends the response. -Example 1: Your Pioneer receiver expects the value for the volume as three digits. So the command needs three stars. If you now set the item to a value with only two digits, like 90, the plugin converts the command automatically to have a leading 0. -Example 2: Your Denon receiver responds with values like ON, OFF or STANDBY to power commands. Replace every character with a star! ON = 2 stars, OFF = 3 stars, etc. -Example 3: Sending or receiving strings of different length like "CD", "GAME", etc. should be set up with one star only. Alternatively you can use "*{str}". Set the responsetype accordingly! - -3.) Set the response type in the textfile to the correct value. The plugin tries to anticipate the correct value but that doesn't always work. The sleep timer of Denon devices is a wonderfully sick example: You can set values between 1 and 120 to set the timer in minutes. If you want to turn it off, the receiver expects the value "OFF" instead of a zero. The plugin fixes that problem if you set the responsetype to bool|num. As soon as you set the item to 0, it magically converts that value to "OFF" and the other way around when receiving "OFF". diff --git a/avdevice/avdevice_webif.png b/avdevice/avdevice_webif.png new file mode 100644 index 0000000000000000000000000000000000000000..80fac8751bf4a843ef3974a789f5a84d78280f9b GIT binary patch literal 413502 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 Hz5~R6y|BbM!rKg8R#N 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 b>>6$BW3{+XZV2~2`lox@@KTwUQ^bD&j(UR! literal 0 HcmV?d00001 diff --git a/avdevice/plugin.yaml b/avdevice/plugin.yaml index 63d66b710..4f9b97a50 100755 --- a/avdevice/plugin.yaml +++ b/avdevice/plugin.yaml @@ -4,12 +4,30 @@ plugin: type: interface # plugin type (gateway, interface, protocol, system, web) description: de: 'Steuerung von diversen AV Geräten über TCP/IP und RS232 Schnittstelle, **seit SmartHomeNG v1.3**' - en: 'Controlling AV devices via TCP/IP and RS232' + en: 'Controlling AV devices via TCP/IP and RS232, **since SmartHomeNG v1.3**' + description_long: + de: 'Steuerung von diversen AV Geräten über TCP/IP und RS232 Schnittstelle.\n + Das Plugin unterstützt eine Vielzahl von AV-Geräten und wurde mit folgenden Geräten getestet:\n + - Pioneer AV Receiver < 2016\n + - Denon AV Receiver > 2016\n + - Epson Projektor < 2010\n + - Oppo UHD Player\n + ' + en: 'Controlling AV devices via TCP/IP and RS232\n + The plugin supports a variety of AV devices and was tested with the following models:\n + - Pioneer AV Receiver < 2016\n + - Denon AV Receiver > 2016\n + - Epson Projektor < 2010\n + - Oppo UHD Player\n + ' + requirements: + de: 'pyserial Python Modul' + en: 'pyserial python module' maintainer: onkelandy tester: Foxi352 # Who tests this plugin? state: develop - keywords: av denon pioneer epson oppo player amp receiver projector rs232 telnet tcpip + keywords: av denon pioneer epson oppo player amp receiver projector rs232 telnet tcpip remote control # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1097870-neues-plugin-av-device-f%C3%BCr-yamaha-pioneer-denon-etc @@ -27,15 +45,20 @@ parameters: default: '' mandatory: True description: - de: 'Name des Geräts. Muss mit dem Namen der Textdatei unter plugins/avdevice korrelieren, die sämtliche Befehle beinhaltet.' - en: 'Name of AV device. Has to correspond to a text file with the same name in the folder plugins/avdevice including all commands.' + de: 'Name des Geräts. Es ist notwendig, eine Text-Datei mit dem hier angegebenen Dateinamen (Endung txt) + im Pluginunterordner ``models`` anzulegen. Der Aufbau dieser Datei wird im user_doc detailliert beschrieben.' + en: 'Name of AV device. A text file with the same name (suffix txt) has to be created in the plugins subfolder + ``models``. The setup of that command file is explained in more detail in the user_doc.' update_exclude: type: str default: '' description: - de: "Caller, bei denen kein Itemupdate vollzogen werden soll. Dies ist hilfreich, um beispielsweise mittels on_change Items abhängig von einem anderen Item zu aktualisieren, ohne dass die Updatefunktion des Plugins getriggert wird (z.B. für play/stop/pause). Es können mehrere durch Komma getrennte Einträge definiert werden." - en: "Define calles that shouldn't trigger an item update. This is helpful if you want to change values of items based on other items by using on_change or on_update functions. In that case the plugin wouldn't update the dependent item additionally (e.g. play/pause/stop). You can define a list of callers delimited by ," + de: 'Caller, bei denen kein Itemupdate vollzogen werden soll.' + en: 'Define callers that should not trigger an item update.' + description_long: + de: 'Caller, bei denen kein Itemupdate vollzogen werden soll. Dies ist hilfreich, um beispielsweise mittels on_change Items abhängig von einem anderen Item zu aktualisieren, ohne dass die Updatefunktion des Plugins getriggert wird (z.B. für play/stop/pause). Es können mehrere durch Komma getrennte Einträge definiert werden.' + en: 'Define callers that should not trigger an item update. This is helpful if you want to change values of items based on other items by using on_change or on_update functions. In that case the plugin would not update the dependent item additionally (e.g. play/pause/stop). You can define a list of callers delimited by ,' tcp_ip: type: ip @@ -83,6 +106,9 @@ parameters: type: str default: 'RGB,RGC,RGD,GBH,GHH,VTA,AUA,AUB' description: + de: "Das Plugin ignoriert Antworten die mit den hier angegebenen Werten starten." + en: "The plugin doesn't care about responses from the device starting with the given values." + description_long: de: "Das Plugin ignoriert Antworten die mit den hier angegebenen Werten starten, beispielsweise Rückmeldungen für die Menünavigation, etc. Der Defaultwert ist für Pioneer Receiver empfohlen." en: "The plugin doesn't care about responses from the device starting with the given values. List responses for menu navigation, etc. The default value is recommended for Pioneer receivers." @@ -90,6 +116,9 @@ parameters: type: str default: 'GEH01020,GEH04022,GEH05024,R' description: + de: "Auf alle Fälle zu puffernde Antworten." + en: "Answers to be buffered in any case." + description_long: de: "Wenn aus irgendeinem Grund die Antworten nicht gepuffert werden sollen, können hier dennoch Antworten definiert werden, die sehr wohl gepuffert werden. Dies ist besonders wichtig bei Informationen, die schnell hintereinander gesendet werden bzw. wechseln wie Künstler, Musiktitel, Radiostation, etc. Der Defaultwert ist für Pioneer Receiver empfohlen." en: "If for whatever reason you don't want to buffer the response from your device you can still define specific responses that should get buffered. This is important for responses that change or get sent very quickly. Artist, title, radio station, etc. are examples that should be put here. The default value is recommended for Pioneer receivers." @@ -97,6 +126,9 @@ parameters: type: str default: '' description: + de: "Quellen, bei denen Displayupdated ignoriert werden." + en: "Sources where display updates should be ignored." + description_long: de: "Die LCD Anzeige auf dem Gerät wird mitunter sehr häufig aktualisiert, zB bei einem scrollenden Text bei Songtiteln. Um ein ständiges Update und dadurch Konflikte mit tatsächlich relevanten Rückmeldungen zu vermeiden, können hier Source Typen hinterlegt werden. Internet Radio, LAN Streaming, etc. werden empfohlen. Für Pioneer-Receiver werden empfohlen: 26,38,40,41,44,17,02,48,0" en: "The value of the LCD display on your receiver might get updated very often, e.g. when it shows song titles as a scrolling text. To avoid constant display updates and therefore possible confusion with relevant answers of your device listing source inputs like internet radio, LAN streaming, etc. here is highly recommended. For Pioneer receivers use: 26,38,40,41,44,17,02,48,0" @@ -104,6 +136,9 @@ parameters: type: str default: '' description: + de: "Master-Item, das für Senden von Befehlen einen bestimmten Wert haben muss." + en: "Master item that has to be set to a specific value before commands are sent." + description_long: de: "Wenn das angegebene Item den angegebenen Wert erhält, werden die Befehle gesendet, ansonsten nicht. Das ist insbesondere dann sinnvoll, wenn das Gerät an einer schaltbaren Steckdose hängt." en: " If given item has given value the commands are sent to the device, otherwise they are not. Relevant if you have your device connected to a power socket that can be turned off." @@ -111,6 +146,9 @@ parameters: type: bool default: True description: + de: "Wert für das Master-Item." + en: "Value for the master item." + description_long: de: "Wenn das angegebene Item den angegebenen Wert erhält, werden die Befehle gesendet, ansonsten nicht. Das ist insbesondere dann sinnvoll, wenn das Gerät an einer schaltbaren Steckdose hängt." en: " If given item has given value the commands are sent to the device, otherwise they are not. Relevant if you have your device connected to a power socket that can be turned off." @@ -118,6 +156,9 @@ parameters: type: str default: 'E02,E04,E06' description: + de: "Standard Fehlermeldungen des Geräts." + en: "The standard error responses from your device." + description_long: de: "Standard Fehlermeldungen des Geräts, bei Pioneer beispielsweise ein 'E' gefolgt von einer Nummer. Werden diese Antworten hier nicht angegeben, werden Rückmeldungen unter Umständen deutlich langsamer verarbeitet, aber voraussichtlich trotzdem erkannt." en: "The standard error responses from your device. For Pioneer receivers they are 'E' followed by a number. If no values are provided error answers from your device might get recognized much slower but actually should still get recognized." @@ -125,6 +166,9 @@ parameters: type: bool default: False description: + de: "Zurücksetzen des Items auf den vorigen Wert, wenn kein Update durchgeführt werden konnte." + en: "Reset the value of the item that could not be updated." + description_long: de: "Zurücksetzen des Items auf den vorigen Wert, wenn kein Update durchgeführt werden konnte, zB das Setzen der Lautstärke in einer abgeschalteten Zone. Sobald das dependson Item ausgeschaltet wird oder mehrere Verbindungs- und Sendeversuche fehlgeschlagen sind, wird das Item zurückgesetzt, damit keine falschen Werte in der Visu angezeigt werden." en: "Reset the value of the item that could not be updated. E.g. you set the volume of zone 2 when it is not powered on. If either the dependson item is off or the device sends an error response or after several connection and send retries the expected response is not received, the item gets set to the value it had before you sent the command. That way you avoid having a wrong value displayed in your Visu." @@ -132,6 +176,9 @@ parameters: type: bool default: False description: + de: "Wenn das dependson Item abgeschaltet ist, werden alle Poweritems ebenfalls auf 0 gesetzt." + en: "If the dependson item is off the power off all zones are set to off." + description_long: de: "Wenn das dependson Item abgeschaltet ist, werden alle Poweritems ebenfalls auf 0 gesetzt. Das ist dann relevant, wenn beispielsweise das Gerät eingeschaltet ist, die Steckdose aber ausgeschaltet wird. Durch Aktivieren dieser Funktion werden automatisch die Poweritems auf 0 gesetzt." en: "If the dependson item is off the power off all zones are set to off. This is especially relevant for a correct representation in your Visu when you have a powered on device but turn off the power socket." @@ -139,8 +186,11 @@ parameters: type: bool default: False description: - de: "Wie beim obigen Attribut dient auch diese Funktion zum korrekten Update der Visu auf den Lautstärkewert 0, sobald das dependson Item deaktiviert wird (zB Ausschalten der Steckdose)." - en: "Same as above but in this case the volume is set to 0 for all zones. This is for Visu purposes only." + de: "Wenn das dependson Item abgeschaltet ist, werden Volume Items ebenfalls auf 0 gesetzt." + en: "If the dependson item is off the volumes are set to 0." + description_long: + de: "Wenn das dependson Item abgeschaltet ist, werden alle Volume Items ebenfalls auf 0 gesetzt. Das ist dann relevant, wenn beispielsweise das Gerät eingeschaltet ist, die Steckdose aber ausgeschaltet wird. Durch Aktivieren dieser Funktion werden automatisch die Poweritems auf 0 gesetzt." + en: "If the dependson item is off the power off all zones are set to off. This is especially relevant for a correct representation in your Visu when you have a powered on device but turn off the power socket." sendretries: type: int @@ -160,6 +210,9 @@ parameters: type: int default: 13 description: + de: "Anzahl der Verbindungsversuche bei Verbindungsproblemen." + en: "If the plugin can not connect to the device it retries this often." + description_long: de: "Anzahl der Verbindungsversuche bei Verbindungsproblemen. Das ist insbesondere bei TCP Verbindungen von Geräten relevant, die an schaltbaren Steckdosen hängen, da diese oftmals 30-40 Sekunden zum Hochfahren benötigen." en: "If the plugin can not connect to the device it retries this often. This is especially useful for TCP connections on devices that are plugged into a switchable socket as most receivers need about 40-50 seconds to boot their network device." @@ -167,6 +220,9 @@ parameters: type: int default: 50 description: + de: "Dauer in Sekunden, wie lange ein Kommando, das nicht erfolgreich war in einem Zwischenspeicher aufbewahrt werden soll." + en: "Seconds the plugin should temporarily save a command to retry later on after establishing a connection." + description_long: de: "Dauer in Sekunden, wie lange ein Kommando, das nicht erfolgreich war in einem Zwischenspeicher aufbewahrt werden soll. Dies ist besonders bei TCP Verbindungen mit Geräten an schaltbaren Steckdosen relevant, da diese ofmals 30-40 Sekunden zum Hochfahren benötigen." en: "Seconds the plugin should temporarily save a command to retry later on after establishing a connection. This is especially useful for TCP connections on devices that are plugged into a switchable socket as most receivers need about 40-50 seconds to boot their network device." @@ -174,6 +230,9 @@ parameters: type: int default: 5 description: + de: "Der Puffer sorgt dafür, dass schnell hintereinander eintreffende Rückmeldungen evaluiert werden." + en: "The buffer ensures the correct evaluation of multiple quick responses." + description_long: de: "Schnell hintereinander empfangene Werte werden bei einer negativen Attributangabe im Puffer gespeichert und gemeinsam verarbeitet. Der Standardwert sollte dafür sorgen, dass keine Antworten verloren gehen. Einige Receiver antworten unter Umständen immer zuerst mit der Angabe zum auf dem Display gezeigten Wert. Der Puffer sorgt dafür, dass auch eine nachfolgende Rückmeldung evaluiert wird." en: "Set this to a number to collect quickly received responses in a buffer and evaluate them collectively. The standard value should be fine and prevent responses getting lost. Some receivers might first respond to a command with an update of the display and then with the actual value. The buffer ensures the correct evaluation of the response." @@ -181,6 +240,9 @@ parameters: type: bool default: False description: + de: "Automatischer Versuch, sich mit dem Gerät zu verbinden, wenn keine Rückmeldung kommt oder die Verbindung verloren wurde." + en: "Automatically tries to reconnect if no response is received or connection is lost." + description_long: de: "Automatischer Versuch, sich mit dem Gerät zu verbinden, wenn keine Rückmeldung kommt oder die Verbindung verloren wurde. Dies sollte nicht notwendig sein, da das Plugin ohnehin bei jedem neuen Senden eines Befehls einen Verbindungsaufbauversuch startet." en: "Automatically tries to reconnect if no response is received or connection is lost. This should not be necessary as the plugin always tries to reconnect before sending a command." @@ -188,111 +250,156 @@ parameters: type: bool default: True description: + de: "Statusabfrage bei Verbindungsherstellung" + en: "Status query on connection" + description_long: de: "Verbindet sich das Plugin, werden die Werte automatisch abgefragt, auch wenn kein Depend=Init im Item angegeben ist. Sollen nur Items abgefragt werden, bei denen das depend-Attribut auf init gesetzt ist, sollte dieser Wert auf False gestellt werden." en: "As soon as the plugin connects to the device the values get queried automatically even if the Depend=Init is not set in the items. If you want to query only those items that are set explicitly change this value to False." item_attributes: + + avdevice_depend: + type: list(str) + description: + de: 'Hier wird der Funktionsname ohne Zonenbezug eingefügt, von dem das Aktualisieren des Items abhängig sein soll.' + en: 'Insert a function name without a zone your item should be depending on.' + description_long: + de: 'Hier wird der Funktionsname ohne Zonenbezug eingefügt, von dem das Aktualisieren des Items abhängig sein soll. Der Bass des Verstärkers lässt sich beispielsweise nur ändern, wenn Tone aktiviert ist. ``tone = True`` führt dazu, dass das Item nur geändert wird, wenn die Bedingung erfüllt ist. Mehrere Bedingungen werden als ``oder`` interpretiert. Eine genauere Beschreibung ist in den user_doc zu finden.' + en: 'Insert a function name without a zone your item should be depending on. For exmaple changing the Bass value of your amp is only useful/possible, if tone is activated. ``tone = True`` makes sure, that the item only gets updated if the dependency is fullfilled. Multiple entries are interepreted as ``or``. You find detailled information in the user_doc.' + avdevice_zone0_depend: type: list(str) description: - de: 'Hier wird der Funktionsname eingefügt, von dem ein Item abhängig sein soll. Der Bass des Verstärkers lässt sich beispielsweise nur ändern, wenn Tone aktiviert ist. "tone = True" führt dazu, dass das Item nur geändert wird, wenn die Bedingung erfüllt ist. Mehrere Bedingungen werden als "oder" interpretiert.' - en: 'Insert a function name your item should be depending on. For exmaple changing the Bass value of your amp is only useful/possible, if tone is activated. "tone = True" makes sure, that the item only gets updated if the dependency is fullfilled. Multiple entries are interepreted as "or".' + de: 'Hier wird der Funktionsname für Zone 0 eingefügt, von dem das Aktualisieren des Items abhängig sein soll.' + en: 'Insert a function name for zone 0 your item should be depending on.' + description_long: + de: 'Hier wird der Funktionsname für Zone 0 eingefügt, von dem das Aktualisieren des Items abhängig sein soll. Der Bass des Verstärkers lässt sich beispielsweise nur ändern, wenn Tone aktiviert ist. ``tone = True`` führt dazu, dass das Item nur geändert wird, wenn die Bedingung erfüllt ist. Mehrere Bedingungen werden als ``oder`` interpretiert.' + en: 'Insert a function name for zone 0 your item should be depending on. For exmaple changing the Bass value of your amp is only useful/possible, if tone is activated. ``tone = True`` makes sure, that the item only gets updated if the dependency is fullfilled. Multiple entries are interepreted as ``or``.' avdevice_zone1_depend: type: list(str) description: - de: 'Hier wird der Funktionsname eingefügt, von dem ein Item abhängig sein soll. Der Bass des Verstärkers lässt sich beispielsweise nur ändern, wenn Tone aktiviert ist. "tone = True" führt dazu, dass das Item nur geändert wird, wenn die Bedingung erfüllt ist. Mehrere Bedingungen werden als "oder" interpretiert.' - en: 'Insert a function name your item should be depending on. For exmaple changing the Bass value of your amp is only useful/possible, if tone is activated. "tone = True" makes sure, that the item only gets updated if the dependency is fullfilled. Multiple entries are interepreted as "or".' + de: 'Hier wird der Funktionsname für Zone 1 eingefügt, von dem das Aktualisieren des Items abhängig sein soll.' + en: 'Insert a function name for zone 1 your item should be depending on.' + description_long: + de: 'Hier wird der Funktionsname für Zone 1 eingefügt, von dem das Aktualisieren des Items abhängig sein soll. Der Bass des Verstärkers lässt sich beispielsweise nur ändern, wenn Tone aktiviert ist. ``tone = True`` führt dazu, dass das Item nur geändert wird, wenn die Bedingung erfüllt ist. Mehrere Bedingungen werden als ``oder`` interpretiert.' + en: 'Insert a function name for zone 1 your item should be depending on. For exmaple changing the Bass value of your amp is only useful/possible, if tone is activated. ``tone = True`` makes sure, that the item only gets updated if the dependency is fullfilled. Multiple entries are interepreted as ``or``.' avdevice_zone2_depend: type: list(str) description: - de: 'Hier wird der Funktionsname eingefügt, von dem ein Item abhängig sein soll. Der Bass des Verstärkers lässt sich beispielsweise nur ändern, wenn Tone aktiviert ist. "tone = True" führt dazu, dass das Item nur geändert wird, wenn die Bedingung erfüllt ist. Mehrere Bedingungen werden als "oder" interpretiert.' - en: 'Insert a function name your item should be depending on. For exmaple changing the Bass value of your amp is only useful/possible, if tone is activated. "tone = True" makes sure, that the item only gets updated if the dependency is fullfilled. Multiple entries are interepreted as "or".' + de: 'Hier wird der Funktionsname für Zone 2 eingefügt, von dem das Aktualisieren des Items abhängig sein soll.' + en: 'Insert a function name for zone 2 your item should be depending on.' + description_long: + de: 'Hier wird der Funktionsname für Zone 2 eingefügt, von dem das Aktualisieren des Items abhängig sein soll. Der Bass des Verstärkers lässt sich beispielsweise nur ändern, wenn Tone aktiviert ist. ``tone = True`` führt dazu, dass das Item nur geändert wird, wenn die Bedingung erfüllt ist. Mehrere Bedingungen werden als ``oder`` interpretiert.' + en: 'Insert a function name for zone 2 your item should be depending on. For exmaple changing the Bass value of your amp is only useful/possible, if tone is activated. ``tone = True`` makes sure, that the item only gets updated if the dependency is fullfilled. Multiple entries are interepreted as ``or``.' avdevice_zone3_depend: type: list(str) description: - de: 'Hier wird der Funktionsname eingefügt, von dem ein Item abhängig sein soll. Der Bass des Verstärkers lässt sich beispielsweise nur ändern, wenn Tone aktiviert ist. "tone = True" führt dazu, dass das Item nur geändert wird, wenn die Bedingung erfüllt ist. Mehrere Bedingungen werden als "oder" interpretiert.' - en: 'Insert a function name your item should be depending on. For exmaple changing the Bass value of your amp is only useful/possible, if tone is activated. "tone = True" makes sure, that the item only gets updated if the dependency is fullfilled. Multiple entries are interepreted as "or".' + de: 'Hier wird der Funktionsname für Zone 3 eingefügt, von dem das Aktualisieren des Items abhängig sein soll.' + en: 'Insert a function name for zone 3 your item should be depending on.' + description_long: + de: 'Hier wird der Funktionsname für Zone 3 eingefügt, von dem das Aktualisieren des Items abhängig sein soll. Der Bass des Verstärkers lässt sich beispielsweise nur ändern, wenn Tone aktiviert ist. ``tone = True`` führt dazu, dass das Item nur geändert wird, wenn die Bedingung erfüllt ist. Mehrere Bedingungen werden als ``oder`` interpretiert.' + en: 'Insert a function name for zone 3 your item should be depending on. For exmaple changing the Bass value of your amp is only useful/possible, if tone is activated. ``tone = True`` makes sure, that the item only gets updated if the dependency is fullfilled. Multiple entries are interepreted as ``or``.' avdevice_zone4_depend: type: list(str) description: - de: 'Hier wird der Funktionsname eingefügt, von dem ein Item abhängig sein soll. Der Bass des Verstärkers lässt sich beispielsweise nur ändern, wenn Tone aktiviert ist. "tone = True" führt dazu, dass das Item nur geändert wird, wenn die Bedingung erfüllt ist. Mehrere Bedingungen werden als "oder" interpretiert.' - en: 'Insert a function name your item should be depending on. For exmaple changing the Bass value of your amp is only useful/possible, if tone is activated. "tone = True" makes sure, that the item only gets updated if the dependency is fullfilled. Multiple entries are interepreted as "or".' + de: 'Hier wird der Funktionsname für Zone 4 eingefügt, von dem das Aktualisieren des Items abhängig sein soll.' + en: 'Insert a function name for zone 4 your item should be depending on.' + description_long: + de: 'Hier wird der Funktionsname für Zone 4 eingefügt, von dem das Aktualisieren des Items abhängig sein soll. Der Bass des Verstärkers lässt sich beispielsweise nur ändern, wenn Tone aktiviert ist. ``tone = True`` führt dazu, dass das Item nur geändert wird, wenn die Bedingung erfüllt ist. Mehrere Bedingungen werden als ``oder`` interpretiert.' + en: 'Insert a function name for zone 4 your item should be depending on. For exmaple changing the Bass value of your amp is only useful/possible, if tone is activated. ``tone = True`` makes sure, that the item only gets updated if the dependency is fullfilled. Multiple entries are interepreted as ``or``.' - avdevice_depend: - type: list(str) + avdevice: + type: str description: - de: 'Hier wird der Funktionsname eingefügt, von dem ein Item abhängig sein soll. Der Bass des Verstärkers lässt sich beispielsweise nur ändern, wenn Tone aktiviert ist. "tone = True" führt dazu, dass das Item nur geändert wird, wenn die Bedingung erfüllt ist. Mehrere Bedingungen werden als "oder" interpretiert.' - en: 'Insert a function name your item should be depending on. For exmaple changing the Bass value of your amp is only useful/possible, if tone is activated. "tone = True" makes sure, that the item only gets updated if the dependency is fullfilled. Multiple entries are interepreted as "or".' + de: 'Das Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei im Ordner models hinterlegt ist, zB power oder volume' + en: 'This attribute has to be followed by one of the commands declared in the device text file in the models folders like power or volume' + description_long: + de: 'Das Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei im Ordner models hinterlegt ist, zB power oder volume\n + Außerdem gibt es zwei spezielle Parameter, die bei Bedarf eingesetzt werden können:\n + - **avdevice: statusupdate**: Dieses Item wird genutzt, um eine komplette Statusabfrage durchzuführen. + Es werden alle Query-Kommandos an das Gerät geschickt, was vor allem nach dem + Einschalten einer geschaltenen Steckdose relevant ist.\n + - **avdevice: reload**: Dieses Item wird genutzt, um die Textkonfiguration neu zu laden. + Dadurch werden das Kommando-File im models Ordner sowie die Dateien im translations Ordner + neu gelesen. So ist ein Ausbessern von Befehlen ohne Plugin-Neustart möglich.\n + ' + en: 'This attribute has to be followed by one of the commands declared in the + device text file in the models folders like power or volume\n + You can use two special avdevice attribute values if you want:\n + - **avdevice: statusupdate**: Use this item to trigger a full + statusupdate. All query commands regarding the currently powered on + zones are sent. This is especially useful if you have a power socket you + can switch on or off and want to update all items on connection.\n + - **avdevice: reload**: Use this item to reload your text configurations. + This re-reads the config as well as translation files and recreates all + functions and commands. This is useful if you find an error in your + configuration file or if you want to add new commands while smarthomeNG + is running. You don’t need to restart the plugin to reload the config!\n + ' avdevice_zone0: type: str description: - de: 'Obiges Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei hinterlegt ist, zB power oder volume' - en: 'This attribute has to be followed by one of the commands declared in the device text file like power or volume' + de: 'Das Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei für Zone 0 hinterlegt ist, zB power oder volume.' + en: 'This attribute has to be followed by one of the commands declared in the device text file for zone 0 like power or volume' avdevice_zone1: type: str description: - de: 'Obiges Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei hinterlegt ist, zB power oder volume' - en: 'This attribute has to be followed by one of the commands declared in the device text file like power or volume' + de: 'Das Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei für Zone 1 hinterlegt ist, zB power oder volume' + en: 'This attribute has to be followed by one of the commands declared in the device text file for zone 1 like power or volume' avdevice_zone2: type: str description: - de: 'Obiges Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei hinterlegt ist, zB power oder volume' - en: 'This attribute has to be followed by one of the commands declared in the device text file like power or volume' + de: 'Das Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei für Zone 2 hinterlegt ist, zB power oder volume' + en: 'This attribute has to be followed by one of the commands declared in the device text file for zone 2 like power or volume' avdevice_zone3: type: str description: - de: 'Obiges Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei hinterlegt ist, zB power oder volume' - en: 'This attribute has to be followed by one of the commands declared in the device text file like power or volume' + de: 'Das Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei für Zone 3 hinterlegt ist, zB power oder volume' + en: 'This attribute has to be followed by one of the commands declared in the device text file for zone 3 like power or volume' avdevice_zone4: type: str description: - de: 'Obiges Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei hinterlegt ist, zB power oder volume' - en: 'This attribute has to be followed by one of the commands declared in the device text file like power or volume' - - avdevice: - type: str - description: - de: 'Obiges Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei hinterlegt ist, zB power oder volume' - en: 'This attribute has to be followed by one of the commands declared in the device text file like power or volume' + de: 'Das Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei für Zone 4 hinterlegt ist, zB power oder volume' + en: 'This attribute has to be followed by one of the commands declared in the device text file for zone 4 like power or volume' avdevice_zone0_speakers: type: str description: - de: 'Soll zwischen Lautsprecher A, B und AB umgeschaltet werden, bietet es sich an, dies über dieses Attribut zu definieren. Als Wert muss hier der zu sendende Wert angegeben werden.' - en: 'If you want to switch between A, B or AB speaker setups you can use this attribue. The value has to be identical to the value the device expects.' + de: 'Soll in Zone 0 zwischen Lautsprecher A, B und AB umgeschaltet werden, bietet es sich an, dies über dieses Attribut zu definieren. Als Wert muss hier der zu sendende Wert angegeben werden.' + en: 'If you want to switch between A, B or AB speaker setups in zone 0 you can use this attribue. The value has to be identical to the value the device expects.' avdevice_zone1_speakers: type: str description: - de: 'Soll zwischen Lautsprecher A, B und AB umgeschaltet werden, bietet es sich an, dies über dieses Attribut zu definieren. Als Wert muss hier der zu sendende Wert angegeben werden.' - en: 'If you want to switch between A, B or AB speaker setups you can use this attribue. The value has to be identical to the value the device expects.' + de: 'Soll in Zone 1 zwischen Lautsprecher A, B und AB umgeschaltet werden, bietet es sich an, dies über dieses Attribut zu definieren. Als Wert muss hier der zu sendende Wert angegeben werden.' + en: 'If you want to switch between A, B or AB speaker setups in zone 1 you can use this attribue. The value has to be identical to the value the device expects.' avdevice_zone2_speakers: type: str description: - de: 'Soll zwischen Lautsprecher A, B und AB umgeschaltet werden, bietet es sich an, dies über dieses Attribut zu definieren. Als Wert muss hier der zu sendende Wert angegeben werden.' - en: 'If you want to switch between A, B or AB speaker setups you can use this attribue. The value has to be identical to the value the device expects.' + de: 'Soll in Zone 2 zwischen Lautsprecher A, B und AB umgeschaltet werden, bietet es sich an, dies über dieses Attribut zu definieren. Als Wert muss hier der zu sendende Wert angegeben werden.' + en: 'If you want to switch between A, B or AB speaker setups in zone 2 you can use this attribue. The value has to be identical to the value the device expects.' avdevice_zone3_speakers: type: str description: - de: 'Soll zwischen Lautsprecher A, B und AB umgeschaltet werden, bietet es sich an, dies über dieses Attribut zu definieren. Als Wert muss hier der zu sendende Wert angegeben werden.' - en: 'If you want to switch between A, B or AB speaker setups you can use this attribue. The value has to be identical to the value the device expects.' + de: 'Soll in Zone 3 zwischen Lautsprecher A, B und AB umgeschaltet werden, bietet es sich an, dies über dieses Attribut zu definieren. Als Wert muss hier der zu sendende Wert angegeben werden.' + en: 'If you want to switch between A, B or AB speaker setups in zone 3 you can use this attribue. The value has to be identical to the value the device expects.' avdevice_zone4_speakers: type: str description: - de: 'Soll zwischen Lautsprecher A, B und AB umgeschaltet werden, bietet es sich an, dies über dieses Attribut zu definieren. Als Wert muss hier der zu sendende Wert angegeben werden.' - en: 'If you want to switch between A, B or AB speaker setups you can use this attribue. The value has to be identical to the value the device expects.' + de: 'Soll in Zone 4 zwischen Lautsprecher A, B und AB umgeschaltet werden, bietet es sich an, dies über dieses Attribut zu definieren. Als Wert muss hier der zu sendende Wert angegeben werden.' + en: 'If you want to switch between A, B or AB speaker setups in zone 4 you can use this attribue. The value has to be identical to the value the device expects.' avdevice_speakers: type: str @@ -303,32 +410,32 @@ item_attributes: avdevice_zone0_init: type: str description: - de: 'Über dieses Attribut lässt sich ein anderes Item auf einen bestimmten Wert setzen, sobald das Plugin sich mit dem Gerät verbindet. Der Wert muss bereits als avdevice-Attribut bei einem anderen Item hinterlegt sein.' - en: 'This attribute changes the value of another item to a specific value as soon as the plugin connects to the device. The value has to exist as an avdevice-attribute on another item.' + de: 'Über dieses Attribut lässt sich ein anderes Item in Zone 0 auf einen bestimmten Wert setzen, sobald das Plugin sich mit dem Gerät verbindet. Der Wert muss bereits als avdevice-Attribut bei einem anderen Item hinterlegt sein.' + en: 'This attribute changes the value of another item in zone 0 to a specific value as soon as the plugin connects to the device. The value has to exist as an avdevice-attribute on another item.' avdevice_zone1_init: type: str description: - de: 'Über dieses Attribut lässt sich ein anderes Item auf einen bestimmten Wert setzen, sobald das Plugin sich mit dem Gerät verbindet. Der Wert muss bereits als avdevice-Attribut bei einem anderen Item hinterlegt sein.' - en: 'This attribute changes the value of another item to a specific value as soon as the plugin connects to the device. The value has to exist as an avdevice-attribute on another item.' + de: 'Über dieses Attribut lässt sich ein anderes Item in Zone 1 auf einen bestimmten Wert setzen, sobald das Plugin sich mit dem Gerät verbindet. Der Wert muss bereits als avdevice-Attribut bei einem anderen Item hinterlegt sein.' + en: 'This attribute changes the value of another item in zone 1 to a specific value as soon as the plugin connects to the device. The value has to exist as an avdevice-attribute on another item.' avdevice_zone2_init: type: str description: - de: 'Über dieses Attribut lässt sich ein anderes Item auf einen bestimmten Wert setzen, sobald das Plugin sich mit dem Gerät verbindet. Der Wert muss bereits als avdevice-Attribut bei einem anderen Item hinterlegt sein.' - en: 'This attribute changes the value of another item to a specific value as soon as the plugin connects to the device. The value has to exist as an avdevice-attribute on another item.' + de: 'Über dieses Attribut lässt sich ein anderes Item in Zone 2 auf einen bestimmten Wert setzen, sobald das Plugin sich mit dem Gerät verbindet. Der Wert muss bereits als avdevice-Attribut bei einem anderen Item hinterlegt sein.' + en: 'This attribute changes the value of another item in zone 2 to a specific value as soon as the plugin connects to the device. The value has to exist as an avdevice-attribute on another item.' avdevice_zone3_init: type: str description: - de: 'Über dieses Attribut lässt sich ein anderes Item auf einen bestimmten Wert setzen, sobald das Plugin sich mit dem Gerät verbindet. Der Wert muss bereits als avdevice-Attribut bei einem anderen Item hinterlegt sein.' - en: 'This attribute changes the value of another item to a specific value as soon as the plugin connects to the device. The value has to exist as an avdevice-attribute on another item.' + de: 'Über dieses Attribut lässt sich ein anderes Item in Zone 3 auf einen bestimmten Wert setzen, sobald das Plugin sich mit dem Gerät verbindet. Der Wert muss bereits als avdevice-Attribut bei einem anderen Item hinterlegt sein.' + en: 'This attribute changes the value of another item in zone 3 to a specific value as soon as the plugin connects to the device. The value has to exist as an avdevice-attribute on another item.' avdevice_zone4_init: type: str description: - de: 'Über dieses Attribut lässt sich ein anderes Item auf einen bestimmten Wert setzen, sobald das Plugin sich mit dem Gerät verbindet. Der Wert muss bereits als avdevice-Attribut bei einem anderen Item hinterlegt sein.' - en: 'This attribute changes the value of another item to a specific value as soon as the plugin connects to the device. The value has to exist as an avdevice-attribute on another item.' + de: 'Über dieses Attribut lässt sich ein anderes Item in Zone 4 auf einen bestimmten Wert setzen, sobald das Plugin sich mit dem Gerät verbindet. Der Wert muss bereits als avdevice-Attribut bei einem anderen Item hinterlegt sein.' + en: 'This attribute changes the value of another item in zone 4 to a specific value as soon as the plugin connects to the device. The value has to exist as an avdevice-attribute on another item.' avdevice_init: type: str @@ -341,4 +448,3 @@ logic_parameters: NONE plugin_functions: NONE # Definition of function interface of the plugin - diff --git a/avdevice/requirements.txt b/avdevice/requirements.txt new file mode 100644 index 000000000..24b4c2f60 --- /dev/null +++ b/avdevice/requirements.txt @@ -0,0 +1 @@ +pyserial>=3.0 diff --git a/avdevice/user_doc.rst b/avdevice/user_doc.rst new file mode 100755 index 000000000..ae43046fe --- /dev/null +++ b/avdevice/user_doc.rst @@ -0,0 +1,449 @@ +.. index:: Plugins; avdevice +.. index:: avdevice + +avdevice +######## + +Konfiguration +============= + +.. important:: + +Die Informationen zur Konfiguration des Plugins sind unter :doc:`/plugins_doc/config/avdevice` beschrieben. + +.. code-block:: yaml + + # etc/plugin.yaml + avdevice: + class_name: AVDevice + class_path: plugins.avdevice + model: sc-lx86 + #instance: pioneer_one + tcp_ip: 10.0.0.130 + #tcp_port: 23 + #tcp_timeout: 1 + rs232_port: /dev/ttyUSB1 + #rs232_baudrate: 9600 + #rs232_timeout: 0.1 + #ignoreresponse: 'RGB,RGC,RGD,GBH,GHH,VTA,AUA,AUB' + #forcebuffer: 'GEH01020, GEH04022, GEH05024' + #inputignoredisplay: '' + #dependson_item: '' + #dependson_value: True + #errorresponse: E02, E04, E06 + #resetonerror: False + #depend0_power0: False + #depend0_volume0: False + #sendretries: 10 + #resendwait: 1.0 + #reconnectretries: 13 + #reconnectcycle: 10 + #secondstokeep: 50 + #responsebuffer: 5 + #autoreconnect: false + #update_exclude: '' + +Items +===== + +avdevice_zone[0-4]@[Instanz]: [Funktion] +---------------------------------------- + +Angabe der Zonennummer und Instanz. Wenn keine Zonen verwendet werden, können +entweder ``avdevice`` oder ``avdevice_zone0`` als Attribute verwendet werden. + +Der angegebene Befehl muss einem Befehl in der Konfigurationsdatei im avdevice-Plugin-Ordner entsprechen. +Die Konfigurationsdatei ist mit dem gleichen Namen wie ``model`` in plugin.yaml abzuspeichern. + +Es ist wichtig, für jedes Item den korrekten Typ zu deklarieren. Der Pioneer RS232-Codesatz erwartet Bool- und Int-Typen. +Wenn beispielsweise der Wiedergabemodus auf "Pure Direct" eingestellt werden soll, muss das Item als "int" oder "num" deklariert sein +und der Wert des Items auf "8" gesetzt werden. Soll das ``translation-feature`` verwendet werden, muss das Item auf ``foo`` +gesetzt werden. Das Feature wird später im Detail erklärt. + +Vollständige Item-Beispiele sind als separate YAML-Dateien für Pioneer und +Denon-Geräte im models-Ordner enthalten. Die Beispiele erlauben einfaches Kopieren/Einfügen der Befehle für andere Modelle +der gleichen Hersteller. + +Die speziellen Attributwere statusupdate und reload werden in :doc:`/plugins_doc/config/avdevice` detailliert beschrieben. + + +avdevice_zone[0-4]_speakers@[Instanz]: [Funktion] +------------------------------------------------- + +Angabe der Zonennummer und Instanz. Dieses Attribut wird genutzt, um zwischen Speakers A, B und AB hin und herzuschalten. +Lautsprecher-Items sollten wie im folgenden Beispiel konfiguriert werden. Die Zahlen 1 und 2 entsprechen dabei den +Werten von Pioneer Receivern < 2016 für die Speaker Commands (SPK1, SPK2). + +.. code-block:: yaml + + # items/my.yaml + Pioneer: + type: foo + + Speakers: + type: num + visu_acl: rw + avdevice_zone1: speakers + + SpeakerA: + type: bool + visu_acl: rw + avdevice_zone1_speakers: 1 + + SpeakerB: + type: bool + visu_acl: rw + avdevice_zone1_speakers: 2 + + +avdevice_zone[0-4]_depend@[Instanz]: [Funktion] +----------------------------------------------- + +Angabe der Zonennummer und Instanz. +Mit dem Attribut depend wird für ein Item definiert, dass es von anderen Items bzw. Funktionen abhängt. +Ist eine solche Abhängigkeit definiert, werden folgende Dinge berücksichtigt: + +- Das Item wird nur aktualisiert, wenn die Abhängigkeit erfüllt ist. + +- Eine momentan laufende Statusabfrage zum Item wird abgebrochen und aus der Kommando-Liste gelöscht. + +- Eine Statusabfrage wird erst hinzugefügt, sobald das Master-Item geändert und die Abhängigkeit erfüllt wird. + +- Nach dem Verbinden mit dem Gerät wird die Statusabfrage nur dann durchgeführt, wenn die Dependency auf ``init`` gestellt ist. + +Es können mehrere abhängige Elemente und Attribute verwendet werden. Es ist sogar möglich, ``und/oder`` für die Abhängigkeiten zu definieren, +indem bis zu vier verschiedene Gruppen (a, b, c, d) mit einem Komma ``,`` getrennt dem Wert angehängt wird. + +Neben der Angabe eines ``Master Items`` ist auch die Angabe eines ``Master Werts`` möglich, +wobei sämtliche Python Vergleichsoperatoren genutzt werden können. Ist kein Operator oder Wert gesetzt, +wird ``==`` und ``True`` angenommen. Ist keine Gruppe deklariert, wird die Gruppe ``a`` angenommen, wodurch +die Abhängigkeiten als ``or`` evaluiert werden. + +Das folgende Beispiel zeigt diese Abhängigkeiten: + +- Der Disktyp wird immer sofort nach einer neuen Verbindung mit dem Gerät abgefragt, sofern ein Query-Command im Textfile angegeben ist. + +- Tonencoding und -sprache werden nach der Verbindung abgefragt oder sobald auf ``play`` gedrückt wurde + +- Die Tracknummer wird unter folgenden Bedingungen abgefragt oder aktualisiert: play ODER status sind wahr UND +Verbose ist auf 2 gesetzt UND der Audiotyp ist entweder PCM ODER PCM 44.1/16 + +- Der Trackname wird aktualisiert/abgefragt, wenn folgende Bedingung erfüllt ist: (play == True OR status == "play") AND verbose == 2 AND audiotype == (PCM or PCM 44.1/16) AND disctpye == (DVD-AUDIO or CDDA or DATA-DISC) + + +.. code-block:: yaml + + # items/my.yaml + Oppo: + type: foo + + Power: + visu_acl: rw + type: bool + avdevice@oppo: power + + Verbose: + visu_acl: rw + type: num + cache: 'false' + enforce_updates: 'yes' + avdevice@oppo: verbose + + Status: + visu_acl: rw + type: str + cache: 'False' + enforce_updates: 'yes' + avdevice@oppo: status + on_change: + - ..Pause = True if value == 'PAUSE' else False + - ..Stop = True if not (value == 'PLAY' or value == 'PAUSE' or value == 'INVALID') else False + - ..Play = True if value == 'PLAY' else False + + Play: + visu_acl: rw + type: bool + enforce_updates: 'yes' + avdevice@oppo: play + + Disctype: + visu_acl: rw + type: str + cache: 'False' + enforce_updates: 'yes' + avdevice@oppo: disctype + avdevice_depend@oppo: init + + Audio: + type: foo + + Language: + visu_acl: rw + type: str + cache: 'False' + enforce_updates: 'yes' + avdevice@oppo: audiolanguage + avdevice_depend@oppo: + - play + - init + + Encoding: + visu_acl: rw + type: str + cache: 'False' + enforce_updates: 'yes' + avdevice@oppo: audiotype + avdevice_depend@oppo: + - play + - init + + Track: + visu_acl: rw + type: num + cache: 'False' + enforce_updates: 'yes' + avdevice@oppo: audiotrack + avdevice_depend@oppo: + - play = True, a + - status = PLAY, a + - verbose = 2, b + - audiotype = PCM, c + - audiotype = PCM 44.1/16, c + + Trackname: + visu_acl: rw + type: str + avdevice@oppo: trackname + avdevice_depend@oppo: + - disctype = DVD-AUDIO, a + - disctype = CDDA, a + - disctype = DATA-DISC, a + - play = True, b + - status = PLAY, b + - audiotype = PCM, c + - audiotype = PCM 44.1/16, c + - verbose = 2, d + +avdevice_zone[0-4]_init@[Instanz]: [Funktion] +--------------------------------------------- + +Angabe der Zonennummer und Instanz. +Das init Attribut ermöglich es, ein spezielles Kommando mit einem konkreten Wert sofort nach der Verbindung zum AV Gerät zu senden. +Möchte man beispielsweise bei einem Gerät das Verbose Leven auf 2 setzen, sobald eine Verbindung aufgebaut ist (beim Plugin-Start oder +erneuten Verbindung bei schaltbaren Steckdosen), kann "avdevice_init" genutzt werden. Der Wert des Items (Oppo.Verbose.Init) wird automatisch +an den Befehl "Verbose" angehängt, der wiederum durch Oppo.Verbose aus dem Textfile zugeordnet wird. + +Es ist möglich, mehrere Init Items für verschiedene Zonen zu verwenden. + +.. code-block:: yaml + + # items/my.yaml + Oppo: + type: foo + Verbose: + type: bool + visu_acl: rw + avdevice_zone1: verbose + + Init: + visu_acl: rw + type: bool + cache: 'true' + value: 2 + avdevice_zone1_init: verbose + + Pioneer: + type: foo + + Zone1: + type: foo + + Mute: + type: bool + visu_acl: rw + avdevice_zone1: mute + + Init: + visu_acl: rw + type: bool + cache: 'true' + value: True + avdevice_zone1_init: mute + + Zone2: + type: foo + + Mute: + type: bool + visu_acl: rw + avdevice_zone2: mute + + Init: + visu_acl: rw + type: bool + cache: 'true' + value: True + avdevice_zone2_init: mute + + +Kommandos +========= + +Die RS232 oder IP-Befehle des Geräts werden in einer Text Datei im Ordner +models abgelegt. Die Datei muss gleich heißen wie das in der plugin.yaml angegebene Modell. +Wurde beispielsweise ``model: vsx-923`` definiert, muss die Datei ``vsx-923.txt`` heißen. + +Jede Zeile beinhaltet einen konkreten Befehl, der an das Gerät gesendet werden soll. +Zudem werden Zone, Statusabfrage, Rückmeldewert, etc. definiert. Es ist möglich, Kommentare +mittels ``#`` und ``’’’`` am Beginn von Zeilen bzw. Blöcken auszukommentieren. + +- ``zone``: Zonennummer. Muss mit der Zonennummer im item.yaml übereinstimmen, als z.B. “avdevice_zone1: function". Die Zone 0 beinhaltet allgemeine Kommandos wie Menünavigation, Displayanzeige, Infos zum aktuellen Song, etc. + +- ``function``: Die Funktion kann nach Lust und Laune benannt werden und wird entsprechend als Attributwert über “avdevice: function" referenziert. + +- ``functiontype``: Für boolsche Funktionen sollte hier "on" oder "off" genutzt werden. Für das Setzen von Quellen, Lautstärkewerten, etc. wird "set" genutzt. Um die Lautstärke oder andere Werte schrittweise zu erhöhen wird "increase" genutzt, um sie zu verringern "decrease". Für andere Funktionen sollte dieser Wert leer gelassen werden. + +- ``send``: Das Kommando, das gesendet werden soll, also beispielsweise "PF" zum Ausschalten von Pioneer Verstärkern. Die Pipe “\|” kann genutzt werden, um mehrere Kommandos zu senden. Eine ganze Zahl kann genutzt werden, um eine Pause zwischen zwei Kommandos in Sekunden anzugeben. Beispielsweise sendet “PO\|2\|PO” zwei Mal den Befehl "PO" mit 2 Sekunden Pause dazwischen. Dies ist teilweise beim Senden von "Power On" über RS232 notwendig. Ein Stern “\*” kann als Platzhalter für den zu sendenden Wert genutzt werden. Wird ein Item mit dem Befehl “\*\*\*VL” beispielsweise auf 5 gestellt, wird das Kommando automatisch richtig auf “005VL” formatiert. + +- ``query``: Statusabfrage. Diese wird für gewöhnlich beim ersten Verbinden und beim Einschalten einer Zone benötigt, um die korrekten Werte auszulesen. Weiters wird das Kommando genutzt, um sicherzustellen, dass ein Befehl richtig beim Gerät ankommt. Es wird empfohlen, diesen Befehl nur bei on, off und set zu nutzen. + +- ``response``: Die erwartete Antwort nach dem Senden eines Befehls. "none" führt dazu, dass auf keine Antwort gewartet wird. Ansonsten funktioniert die Schreibweise gleich wie bei send. Auch hier ist es möglich, mehrere Antworten durch “\|” getrennt anzugeben. + +- ``readwrite``: R steht für "nur lesen", W für "nur schreiben" und RW für beides. Beispielsweise sind Displayanzeigen reine Lesewerte, wohingegen ein Erhöhen der Lautstärke keine Antwort erwartet und somit ein reiner Schreibwert ist. Ein richtiges Setzen dieses Wert ermöglicht einen schnellen und zuverlässigen Betrieb des Plugins. + +- ``invertresponse``: Einige Geräte reagieren mit gänzlich unlogischen Antworten, beispielsweise mit "0" für ON und "1" für OFF. Wird dieser Wert auf "yes" gesetzt, wird dieser Dummheit entgegengewirkt. + +- ``minvalue``: Minimumwert für eine Funktion, beispielsweise zum Limitieren von Lautstärken oder Bass-Einstellungen. Wird hier beispielsweise "-3" angegeben und der Wert in der Visu oder CLI versehentlich auf "-5" gestellt, wird der Wert automatisch auf "-3" limitiert. + +- ``maxvalue``: Maximum für eine Funktion, beispielsweise zum Limitieren von Lautstärken oder Bass-Einstellungen. Wird hier beispielsweise "100" angegeben und der Wert in der Visu oder CLI versehentlich auf "120" gestellt, wird der Wert automatisch auf "100" limitiert. + +- ``responsetype``: Definiert den Typ der Antwort: "bool", "num", "str" oder eine durch “\|” oder Komma “,” getrennte Mischung. Die meisten Antworttypen werden beim Pluginstart automatisch eruiert. Sollte ein Kommando aber nicht wie gewünscht funktionieren, kann hier der Wert in Anlehnung an die Beispiel Textfiles manuell gesetzt werden. + +- ``translationfile``: Soll ein Wert/Code in einen anderen übersetzt werden, wird hier der Name einex Text-Files angegeben, das im Unterordner translations angelegt werden muss. Dieses Feature wird später im Detail erklärt. + +.. code-block:: none + + # plugins/avdevice/pioneer.txt + ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MINVALUE; MAXVALUE; RESPONSETYPE; TRANSLATIONFILE + 1; power; on; PO|PO; ?P; PWR*; RW; yes + 1; power; off; PF; ?P; PWR*; RW; yes + 1; volume+; increase; VU; ; VOL; W + 1; volume-; decrease; VD; ; VOL; W + 1; volume; set; ***VL; ?V; VOL***; RW; ; 80; 185 + 1; input; set; **FN; ?F; FN**; RW + 1; speakers; set; *SPK; ?SPK; SPK*; RW + ''' + #commented out from here + 2; power; on; APO|APO; ?AP; APR*; RW; yes + 2; power; off; APF; ?AP; APR*; RW; yes + 0; title; ; ; ; GEH01020; R + 0; station; ; ; ; GEH04022; R + 0; genre; ; ; ; GEH05024; R + #commented out until here + ''' + 0; display; ; ?FL; ?FL; FL******************************; R + 1; input; set; **FN; ?F; FN**; RW; ; ; ; ; pioneer_input + 1; mode; set; ****SR; ?S; SR****; RW; ; ; ; num; pioneer_SR + 1; playingmode; ; ?L; ?L; LM****; R; ; ; ; str,int; pioneer_LM + #0; test; ; ; ; noidea; R (commented out) + + +Übersetzungen +============= + +Durch das Erstellen einer Datei namens denon_volume.txt und das Verlinken auf diese Datei +in der Model-Textdatei durch Angabe von "denon_volume" am Ende einer Kommandozeile können +Kommando-Werte in andere Werte übersetzt werden. Beispielsweise ist für Denon Verstärker ein +Kommawert wie 50,5 immer 505. Um dies korrekt in einer Visu darzustellen, sollte folgender Eintrag +im entsprechenden translation Textfile definiert sein: + +.. code-block:: none + + # plugins/avdevice/denon_volume.txt + CODE; TRANSLATION + ***; **.* + +Pioneer Versärker nutzen Nummern, um Quellen und Hörmodi zu definieren, was nicht +sonderlich nutzerfreundlich ist. Einträge wie im folgenden Beispiel zu sehen in einer Datei +namens translations/pioneer_input.txt +und die Angabe dieser Datei in models/model.txt beheben das Problem: + +.. code-block:: none + + # plugins/avdevice/pioneer_input.txt + CODE; TRANSLATION + 00; PHONO + 01; CD + 02; TUNER + +Wenn das Plugin den Wert FN01 erhält, wird das Item mit der entsprechenden +Funktion automatisch auf "CD" statt auf "1" gestellt. Umgekehrt wird auch +der Befehl korrekt umgewandelt, sobald das Item entsprechend über eine Visu +aktualisiert wird. Es wird empfohlen, den Typ des Items auf "foo" zu setzen. + + +Wildcards +========= + +Für die Antworten in der model.txt Datei ist es möglich, unbekannte +Teile der Antwort mittels "?" zu integrieren. Dies ist vor allem bei +Oppo Playern relevant. + +Die Anzahl der Fragezeichen wird durch die Anzahl an Buchstaben oder Ziffern +bestimmt. Ist die Länge des unbekannten Ausdrucks unbekannt, kann ein “?{str}” +genutzt werden. + +.. code-block:: none + + # plugins/avdevice/oppo-udp203.txt + ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MINVALUE; MAXVALUE; RESPONSETYPE; TRANSLATIONFILE + 0; audiotype; ; ; #QAT; @QAT OK ?/? *** ?????; R; ; ; ; str + 0; audiotrack; ; #AUD; #QTK; @UAT ?{str} **|@QTK OK */?; RW; ; ; ; num + +Der Rückmeldung für den Audiotyp im oben angegebenen Beispiel besteht folglich aus: +"@QAT OK" zu Beginn und zwei Ziffern hintereinander, die durch einen Schrägstrich +getrennt sind. Welche Ziffern das sind, soll egal sein. Danach folgt der relevante Teil +der Antwort, der aus drei Zeichen besteht. Hinten kommen nochmals fünf unbekannte Zeichen. + +Das Beispiel zum Audiotrack bedeutet Folgendes: +Auf “@UAT” folgt ein Wort beliebiger Länge und nach einem Leerzeichen der relevante +Wert mit zwei Zeichen. Alternativ kann die Antwort auch mit "@QTK OK" beginnen, +wobei dann der relevante Teil der Antwort direkt nach einem Leerzeichen folgt. Das +darauf folgende "/?" ist deshalb wichtig, weil auch die Gesämtlänge der Antwort für +die richtige Zuordnung eine Rolle spielt (außer bei der Angabe von {str}). + +Dieses Feature befindet sich immer noch in der Entwicklung. Erfahrungen bitte im Support Thread +im KNX-Forum teilen. + +Webinterface +============ + +Das Webinterface kann genutzt werden, um die Items und deren Werte auf einen Blick zu sehen, +die dem Plugin zugeordner sind. Außerdem können Historien von Kommandos und Abfragen +eingesehen und die Kommando-Dateien neu geladen werden. + +.. image:: avdevice_webif.png + :height: 1618px + :width: 3338px + :scale: 25% + :alt: Web Interface + :align: center + +Fehlerbehebung +============== +1.) Webinterface: Hier können Kommando-Protokolle eingesehen werden. + +2.) Smarthome Log-Files: Hier können neben dem sonst üblichen DEBUG +Level auch die Zahlen 9 (=VERBOSE1) und 8 (VERBOSE2) deklariert werden. + +3.) Die Anzahl der Sterne in den Kommandos und Antworten im Text-File muss +unbedingt mit der Anzahl an Ziffern oder Buchstaben übereinstimmen, die vom Gerät erwartet +wird. Pioneer Receiver benötigen beispielsweise für die Lautstärke drei Sterne, +Denon Geräte für ON zwei Sterne, für OFF drei Sterne, etc. Ist unklar, wie lange +eine Antwort sein wird (z.B. CD oder GAME) sollte "\*{str}" genutzt werden. Es wird +also eine unbestimmte Anzahl an Buchstaben erwartet. + +4.) Der "Response Type" im Textfile muss unbedingt mit dem erwarteten Wert übereinstimmen oder +sollte im Zweifelsfall leer gelassen werden. Für die Timerfunktion von Denon Verstärkern +muss der Typ z.B. auf "bool|num" gestellt werden, da sowohl OFF als auch eine Zahl gesendet/empfangen +werden kann. Durch diese Angabe von bool und num wird eine 0 automatisch in OFF umgewandelt und umgekehrt. diff --git a/avdevice/user_doc_en.rst b/avdevice/user_doc_en.rst new file mode 100755 index 000000000..64969dbc4 --- /dev/null +++ b/avdevice/user_doc_en.rst @@ -0,0 +1,530 @@ +.. index:: Plugins; avdevice +.. index:: avdevice + +avdevice +######## + +Configuration +============= + +.. important:: + +You can find the configuration information at :doc:`/plugins_doc/config/avdevice`. + +.. code-block:: yaml + + # etc/plugin.yaml + avdevice: + class_name: AVDevice + class_path: plugins.avdevice + model: sc-lx86 + #instance: pioneer_one + tcp_ip: 10.0.0.130 + #tcp_port: 23 + #tcp_timeout: 1 + rs232_port: /dev/ttyUSB1 + #rs232_baudrate: 9600 + #rs232_timeout: 0.1 + #ignoreresponse: 'RGB,RGC,RGD,GBH,GHH,VTA,AUA,AUB' + #forcebuffer: 'GEH01020, GEH04022, GEH05024' + #inputignoredisplay: '' + #dependson_item: '' + #dependson_value: True + #errorresponse: E02, E04, E06 + #resetonerror: False + #depend0_power0: False + #depend0_volume0: False + #sendretries: 10 + #resendwait: 1.0 + #reconnectretries: 13 + #reconnectcycle: 10 + #secondstokeep: 50 + #responsebuffer: 5 + #autoreconnect: false + #update_exclude: '' + +Items +===== + +avdevice_zone[0-4]@[instance]: [function] +---------------------------------------- + +Specifiy the zone number and instance. If you don’t use zones you can +either use ``avdevice`` or ``avdevice_zone0`` as attributes. + +The command has to correspond to a command in the relevant text +configuration file in the avdevice plugin folder named the same as the +``model`` configured in plugin.yaml. It is important to set the correct +type for each item. The Pioneer RS232 codeset expects bool and int types +only. For example to set the listening mode to "pure direct", the item +has to be int and you set it to the value "8". If you want to use the +``translation-feature`` you should set the item to ``foo``. This feature is +explained later. + +Full item examples are included as separate yaml files for Pioneer and +Denon devices. The examples include the tested items/commands and +allow easy copy/paste. + +Special attribute values (statusupdate and reload) are described at :doc:`/plugins_doc/config/avdevice`. + + +avdevice_zone[0-4]_speakers@[instance]: [function] +------------------------------------------------- + +Specifiy the zone number and instance. This attribute is used to switch between +Speaker A, B and AB layout. Speakers Items are special and +should be set up the way mentioned in the following example. 1 and 2 +correspond to the value the speaker command expects (for example for +Pioneer receivers < 2016). + +.. code-block:: yaml + + # items/my.yaml + Pioneer: + type: foo + + Speakers: + type: num + visu_acl: rw + avdevice_zone1: speakers + + SpeakerA: + type: bool + visu_acl: rw + avdevice_zone1_speakers: 1 + + SpeakerB: + type: bool + visu_acl: rw + avdevice_zone1_speakers: 2 + + +avdevice_zone[0-4]_depend@[instance]: [function] +----------------------------------------------- + +Specifiy the zone number and instance. The depend attribute lets you +specifiy for each item if it depends on another item/function. If you +define such a dependency several things will happen: + +- The item only gets updated/changed if the dependency is fullfilled + +- Query command of the item will get removed from the queue if the dependency is not +fullfilled + +- Query command of the item will (only) get added if one of +the master items gets changed and the dependency is fullfilled. + +- After connecting to the device the query command of an item only gets +added if you add ``init`` to the dependency configuration. + +You can use multiple depend items and attributes even for different +zones. You can even define ``and/or`` for the dependencies by adding up to +four different groups (a, b, c, d) after the value seperated by a comma +``,``. + +You can not only define a ``master item`` but also a ``master value`` and +several standard python comparison operators. + +If you don’t set an operator and value, ``==`` and ``True`` is assumed. If +you don’t set a group, group ``a`` is assumed. This means, if you add +several dependent function without a group, the functions will get +evaluated as ``or`` and dependency is fullfilled as soon as one of the +functions/items corresponds to the given value. + +The example below shows the following dependencies: + +- The disctype will always be queried after connecting to the device (as long as you have +specified a query command in the command-file) + +- Audio language and encoding will be queried after connecting to the device or as so +on as +the item with the ``play`` function (Oppo.Play) is True +- The track will get updated/queried if these dependencies are fullfilled: (play is True +or status is play) AND verbose is set to 2 AND audiotype is either PCM +or PCM 44.1/16 + +- The trackname will get updated/queried if these +dependencies are fullfilled: (play is True or status is play) AND +verbose is set to 2 AND audiotype is either PCM or PCM 44.1/16 AND +disctpye is one of these three values: DVD-AUDIO, CDDA, DATA-DISC + +.. code-block:: yaml + + # items/my.yaml + Oppo: + type: foo + + Power: + visu_acl: rw + type: bool + avdevice@oppo: power + + Verbose: + visu_acl: rw + type: num + cache: 'false' + enforce_updates: 'yes' + avdevice@oppo: verbose + + Status: + visu_acl: rw + type: str + cache: 'False' + enforce_updates: 'yes' + avdevice@oppo: status + on_change: + - ..Pause = True if value == 'PAUSE' else False + - ..Stop = True if not (value == 'PLAY' or value == 'PAUSE' or value == 'INVALID') else False + - ..Play = True if value == 'PLAY' else False + + Play: + visu_acl: rw + type: bool + enforce_updates: 'yes' + avdevice@oppo: play + + Disctype: + visu_acl: rw + type: str + cache: 'False' + enforce_updates: 'yes' + avdevice@oppo: disctype + avdevice_depend@oppo: init + + Audio: + type: foo + + Language: + visu_acl: rw + type: str + cache: 'False' + enforce_updates: 'yes' + avdevice@oppo: audiolanguage + avdevice_depend@oppo: + - play + - init + + Encoding: + visu_acl: rw + type: str + cache: 'False' + enforce_updates: 'yes' + avdevice@oppo: audiotype + avdevice_depend@oppo: + - play + - init + + Track: + visu_acl: rw + type: num + cache: 'False' + enforce_updates: 'yes' + avdevice@oppo: audiotrack + avdevice_depend@oppo: + - play = True, a + - status = PLAY, a + - verbose = 2, b + - audiotype = PCM, c + - audiotype = PCM 44.1/16, c + + Trackname: + visu_acl: rw + type: str + avdevice@oppo: trackname + avdevice_depend@oppo: + - disctype = DVD-AUDIO, a + - disctype = CDDA, a + - disctype = DATA-DISC, a + - play = True, b + - status = PLAY, b + - audiotype = PCM, c + - audiotype = PCM 44.1/16, c + - verbose = 2, d + +avdevice_zone[0-4]_init@[instance]: [function] +--------------------------------------------- + +Specifiy the zone number and instance. +The init attribute lets you set a specific command to a specific value as soon as the device is connected. For example if you want to always set the verbose level to 2 as soon as the plugin connects to it (at startup and after turning on the power socket or reconnecting the cable) you can define an additional item with the attribute "avdevice_init". The value of that item (Oppo.Verbose.Init) gets appended to the command linked to the verbose item (Oppo.Verbose). + +You can use multiple init items and attributes even for different zones. + +.. code-block:: yaml + + # items/my.yaml + Oppo: + type: foo + Verbose: + type: bool + visu_acl: rw + avdevice_zone1: verbose + + Init: + visu_acl: rw + type: bool + cache: 'true' + value: 2 + avdevice_zone1_init: verbose + + Pioneer: + type: foo + + Zone1: + type: foo + + Mute: + type: bool + visu_acl: rw + avdevice_zone1: mute + + Init: + visu_acl: rw + type: bool + cache: 'true' + value: True + avdevice_zone1_init: mute + + Zone2: + type: foo + + Mute: + type: bool + visu_acl: rw + avdevice_zone2: mute + + Init: + visu_acl: rw + type: bool + cache: 'true' + value: True + avdevice_zone2_init: mute + + +Commands +======== + +Configure your commands depending on your model and manufacturer. You +have to name the file the same as configured in the plugin.yaml as +“model”. E.g. if you’ve configured ``model: vsx-923`` you name the file +``vsx-923.txt`` + +Each line holds one specific command that should be sent to the device. +You also specify the zone, the query command, response command, etc. You +can comment out lines by placing a ``#`` in front of the line. You can also +comment a whole block by using ``’’’`` at the beginning and end of a block. + +- ``zone``: Number of zone. Has to correspond to the attribute in + item.yaml. E.g. for zone 1 use “avdevice_zone1: command”. Zone 0 + holds special commands like navigating in the menu, display reponse, + information about currently playing songs, etc. + +- ``function``: name of the function. You can name it whatever you + like. You reference this value in the item using avdevice_zoneX: + function. + +- ``functiontype``: for boolean functions use “on” or “off”. For + commands setting a specific value like source, input mode, volume, + etc. use “set”. To increase or decrease a value use the corresponding + “increase” or “decrease”. For everything else leave empty! + +- ``send``: the command to be sent, e.g. power off is “PF” for Pioneer + receivers. You can use a pipe “\|” if more than one command should be + sent. Add an integer or float to specify a pause in seconds between + the commands, like “PO\|2\|PO”. That might be necessary for power on + commands via RS232, e.g. for Pioneer receivers to power on “PO|PO” + forces the plugin to send the “PO” command twice. Use stars “\*” to + specify the format of the value to be sent. Let’s say your device + expects the value for volume as 3 digits, a “\*\*\*VL” ensures that + even setting the volume to “5” sends the command as “005VL” + +- ``query``: Query command. This is usually useful after setting up the + connection or turning on the power. This command gets also used if + the plugin doesn’t receive the correct answer after sending a + command. It is recommended to leave this value empty for all + functions except on, off and set. + +- ``response``: The expected response after sending a command. Use + “none” if you don’t want to wait for the correct response. Use “\*” the same way + as with the send command. You can even specify multiple response + possibilities separated by “\|”. + +- ``readwrite``: R for read only, W for write only, RW for Read and + Write. E.g. display values are read only whereas turning the volume + up might be a write operation only. Setting this correctly ensures a + fast and reliable plugin operation + +- ``invertresponse``: some devices are stupid enough to reply with a + “0” for “on” and “1” for “off”. E.g. a Pioneer receiver responds with + “PWR0” if the device is turned on. Configure with “yes” if your + device is quite stupid, too. + +- ``minvalue``: You can define the minimum value for setting a specific + function. This might be most relevant for setting the volume or + bass/trebble values. If you configure this with “-3” and set the bass + to “-5” (via Visu or CLI) the value will get clamped by the plugin + and set to “-3”. + +- ``maxvalue``: You can define the maximum value for setting a specific + function. This might be most relevant for setting the volume. If you + configure this with “100” and set the volume to “240” (via Visu or + CLI) the value will get clamped by the plugin and set to “100”. + +- ``responsetype``: Defines the type of the response value and can be + set to “bool”, “num” or “str” or a mixture of them (separated by a + pipe “\|” or comma “,”). Most response types are set automatically on + startup but you can force a specific type using this value. It is + recommended to use the values suggested in the txt files that come + with the plugin. + +- ``translationfile``: If you want to translate a specific value/code + to something else, define the name of a txt file in the translation folder + here that holds the information on how to translate which value. This feature + is described later in more detail. + +.. code-block:: none + + # plugins/avdevice/pioneer.txt + ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MINVALUE; MAXVALUE; RESPONSETYPE; TRANSLATIONFILE + 1; power; on; PO|PO; ?P; PWR*; RW; yes + 1; power; off; PF; ?P; PWR*; RW; yes + 1; volume+; increase; VU; ; VOL; W + 1; volume-; decrease; VD; ; VOL; W + 1; volume; set; ***VL; ?V; VOL***; RW; ; 80; 185 + 1; input; set; **FN; ?F; FN**; RW + 1; speakers; set; *SPK; ?SPK; SPK*; RW + ''' + #commented out from here + 2; power; on; APO|APO; ?AP; APR*; RW; yes + 2; power; off; APF; ?AP; APR*; RW; yes + 0; title; ; ; ; GEH01020; R + 0; station; ; ; ; GEH04022; R + 0; genre; ; ; ; GEH05024; R + #commented out until here + ''' + 0; display; ; ?FL; ?FL; FL******************************; R + 1; input; set; **FN; ?F; FN**; RW; ; ; ; ; pioneer_input + 1; mode; set; ****SR; ?S; SR****; RW; ; ; ; num; pioneer_SR + 1; playingmode; ; ?L; ?L; LM****; R; ; ; ; str,int; pioneer_LM + #0; test; ; ; ; noidea; R (commented out) + + +Translations +============ + +You could create a file called denon_volume.txt and link it +in your model.txt file to convert 3 digit volume to a float. Denon +receivers handle e.g. 50.5 as 505. If you want to use value limits or +visualize the volume correctly in your VISU you should use the following +translation file: + +.. code-block:: none + + # plugins/avdevice/denon_volume.txt + CODE; TRANSLATION + ***; **.* + +Pioneer receivers use numbers to define input source or listening mode +what is very cryptic and not very user friendly. Therefore you should +use the relevant files in the plugins folder like pioneer_input. That +file looks something like this: + +.. code-block:: none + + # plugins/avdevice/pioneer_input.txt + CODE; TRANSLATION + 00; PHONO + 01; CD + 02; TUNER + +Now, when the plugin receives FN01 as a response, the response gets +converted to “CD”. Vice versa you can even update your item to “CD” and +the plugin will send “01FN” as a command. It is advised to define the +according item as ``type: foo`` so you can either use a number or string, +just the way you like. + + +Wildcards +========= + +For the model.txt file you can use question marks as a wild card if the +response of the device includes information for several different items. +This is the case with a lot of responses from Oppo bluray players. + +Use a “?” for “any single character”, use “??” for “two characters of +any value” and so on. If the length of the wildcard can differ, use a +“?{str}” meaning that the plugin expects a string of any given length. + +The definition for audiotype in the example means that the expected +response consists of: “@QAT OK” in the beginning followed by a single +character followed by a “/” and another single character again. After +that is the relevant part of the response, the value of the item, +defined by exactly three digits/characters. Behind that is a blank and +any value consisting of five characters or digits. + +The example definition for audiotrack means that the response can be: +“@UAT” followed by any word/number without a specific length, followed +by a blank and the real value consisting of two characters. The response +could also start with “@QTK OK” followed by the relevant value +consisting of exactly one digit/character. After that there will be a +“/” and any character/digit. It is important to add the “/?” in the end +because the plugin also compares the length of the response with the +expected length (calculated from the response in the command-file). It +is not relevant, if you use a {str} in your response because then the +length can not be determined. + +This feature is still under development. Feel free to experiment with it +and post your experience in the knx-forum. + +.. code-block:: none + + # plugins/avdevice/oppo-udp203.txt + ZONE; FUNCTION; FUNCTIONTYPE; SEND; QUERY; RESPONSE; READWRITE; INVERTRESPONSE; MINVALUE; MAXVALUE; RESPONSETYPE; TRANSLATIONFILE + 0; audiotype; ; ; #QAT; @QAT OK ?/? *** ?????; R; ; ; ; str + 0; audiotrack; ; #AUD; #QTK; @UAT ?{str} **|@QTK OK */?; RW; ; ; ; num + + +Webinterface +============ + +Use the web interface to see which item using the plugin is set to which value. +Furthermore you can see a history of the commands and queries being sent by the +plugin. You can also use the web interface to reload your configuration file. + +.. image:: avdevice_webif.png + :height: 1618px + :width: 3338px + :scale: 25% + :alt: Web Interface + :align: center + +Troubleshooting +=============== +1.) Have a look at the webinterface. You'll figure out the item ids and values +as well as a history of the commands. + +2.) Have a look at the smarthome logfile. If you can’t figure out the +reason for your problem, change the verbose level in logging.yaml. You +can use level 10 (=DEBUG), 9 (VERBOSE1) and 8 (VERBOSE2) as debugging +levels. + +3.) Concerning send and response entries in the text file, make sure the +number of stars correspond to the way your device wants to receive the +command or sends the response. Example 1: Your Pioneer receiver expects +the value for the volume as three digits. So the command needs three +stars. If you now set the item to a value with only two digits, like 90, +the plugin converts the command automatically to have a leading 0. +Example 2: Your Denon receiver responds with values like ON, OFF or +STANDBY to power commands. Replace every character with a star! ON = 2 +stars, OFF = 3 stars, etc. Example 3: Sending or receiving strings of +different length like “CD”, “GAME”, etc. should be set up with one star +only. Alternatively you can use "\*{str}". Set the responsetype +accordingly! + +4.) Set the response type in the textfile to the correct value. The +plugin tries to anticipate the correct value but that doesn’t always +work. The sleep timer of Denon devices is a wonderfully sick example: +You can set values between 1 and 120 to set the timer in minutes. If you +want to turn it off, the receiver expects the value “OFF” instead of a +zero. The plugin fixes that problem if you set the responsetype to +bool|num. As soon as you set the item to 0, it magically converts that +value to “OFF” and the other way around when receiving “OFF”. From 19bb69e2df252c8cd794a0572bdb8058d561749f Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Wed, 26 Dec 2018 14:59:12 +0100 Subject: [PATCH 495/705] Update README.md --- stateengine/README.md | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/stateengine/README.md b/stateengine/README.md index e1a6ec8f8..8e01867be 100755 --- a/stateengine/README.md +++ b/stateengine/README.md @@ -4,23 +4,9 @@ Created by i-am-offline ## Description Finite state machine plugin for smarthomeNG, previously known as AutoBlind -## Support -If you require support, please raise an issue at GitHub: - ## Documentation -The manual can be found on the official SmarthomeNG plugin documentation: . - -A "Getting Started" blog entry can be found at the [SmarthomeNG Blog] -(https://www.smarthomeng.de/starting-with-state-machine-automation-autoblind-plugin) - -## Configuration -If you have already setup the older autoblind plugin you can use the shell script in the plugin directory to convert your item.yaml files. - -### plugin.yaml -See the [manual at SmarthomeNG](https://www.smarthomeng.de/user/plugins/stateengine/user_doc.html) - -### items.yaml -See the [manual at SmarthomeNG](https://www.smarthomeng.de/user/plugins/stateengine/user_doc.html) +For info on the features and the different command files, etc. see the [User Documentation](https://www.smarthomeng.de/user/plugins/stateengine/user_doc.html "Manual") +For info on how to configure the plugin see the [Configuration Documentation](https://www.smarthomeng.de/plugins_doc/config/stateengine "Configuration") ### smartvisu widget Copy stateengine.example.html from the sv_widgets folder to your smartvisu/dropins/widgets folder and use the URL in your browser: From 96869bffe715538c44674e275017646254fbaf99 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Wed, 26 Dec 2018 15:00:58 +0100 Subject: [PATCH 496/705] Update README.md --- uzsu/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/uzsu/README.md b/uzsu/README.md index f885528a3..d116386ac 100755 --- a/uzsu/README.md +++ b/uzsu/README.md @@ -1,6 +1,12 @@ # UZSU -Provides universal time switches for items (German: *U*niverselle *Z*eit*s*chalt *U*hr) +## Description +Provides universal time switches for items + +## Documentation + +For info on the features and detailed setup see the [User Documentation](https://www.smarthomeng.de/user/plugins/uzsu/user_doc.html "Manual") +For info on how to configure the plugin see the [Configuration Documentation](https://www.smarthomeng.de/plugins_doc/config/uzsu "Configuration") ## Changelog From 9866da3cb2721a355af73e97697db0eeed4ca853 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Wed, 26 Dec 2018 15:02:35 +0100 Subject: [PATCH 497/705] Update README.md --- stateengine/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stateengine/README.md b/stateengine/README.md index 8e01867be..2b14a34ee 100755 --- a/stateengine/README.md +++ b/stateengine/README.md @@ -5,7 +5,7 @@ Created by i-am-offline Finite state machine plugin for smarthomeNG, previously known as AutoBlind ## Documentation -For info on the features and the different command files, etc. see the [User Documentation](https://www.smarthomeng.de/user/plugins/stateengine/user_doc.html "Manual") +For info on the features and detailed setup see the [User Documentation](https://www.smarthomeng.de/user/plugins/stateengine/user_doc.html "Manual") For info on how to configure the plugin see the [Configuration Documentation](https://www.smarthomeng.de/plugins_doc/config/stateengine "Configuration") ### smartvisu widget From d10cba709d73b1a89f34178b65877942fc09ba96 Mon Sep 17 00:00:00 2001 From: Andre K Date: Wed, 26 Dec 2018 22:59:18 +0100 Subject: [PATCH 498/705] Test for PullRequest --- alexa4p3/Hoerprobe.mp3 | Bin 107352 -> 0 bytes alexa4p3/README.md | 76 +++++++++++------- alexa4p3/__init__.py | 98 ++++++++++++++--------- alexa4p3/_config.yml | 1 - alexa4p3/action.py | 39 ++++++++- alexa4p3/device.py | 3 + alexa4p3/nginx.md | 176 ----------------------------------------- alexa4p3/p3_action.py | 35 +++++++- alexa4p3/service.py | 46 ++++++++--- 9 files changed, 212 insertions(+), 262 deletions(-) delete mode 100644 alexa4p3/Hoerprobe.mp3 delete mode 100644 alexa4p3/_config.yml delete mode 100644 alexa4p3/nginx.md diff --git a/alexa4p3/Hoerprobe.mp3 b/alexa4p3/Hoerprobe.mp3 deleted file mode 100644 index 22f98f325ae02c1f8e89fa2e3f24a44a7d235087..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 107352 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

      (|ceK~mxxD4{Rxe-G9g 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�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 L|G)gdPvE}*n-Sqr diff --git a/alexa4p3/README.md b/alexa4p3/README.md index b034b8e1d..99b8fe6a5 100644 --- a/alexa4p3/README.md +++ b/alexa4p3/README.md @@ -8,22 +8,23 @@ ## Table of Content 1. [Generell](#generell) -2. [Icon / Display Categories](#icons) -3. [Entwicklung / Einbau von neuen Skills](#entwicklung) -4. [Alexa-ThermostatController](#thermostatcontroller) + [Thermosensor](#thermostatsensor) -5. [Alexa-PowerController](#powercontroller) -6. [Alexa-BrightnessController](#brightnesscontroller) -7. [Alexa-PowerLevelController](#powerlevelcontroller) -8. [Alexa-PercentageController](#percentagecontroller) -9. [Alexa-LockController](#lockcontroller) -10. [Alexa-CameraStreamController](#camerastreamcontroller) -11. [Alexa-SceneController](#scenecontroller) +2. [Change Log](#changelog) +3. [Icon / Display Categories](#Icons) +4. [Entwicklung / Einbau von neuen Skills](#Entwicklung) +5. [Alexa-ThermostatController](#ThermostatController) + [Thermosensor](#Thermostatsensor) +6. [Alexa-PowerController](#PowerController) +7. [Alexa-BrightnessController](#BrightnessController) +8. [Alexa-PowerLevelController](#PowerLevelController) +9. [Alexa-PercentageController](#PercentageController) +10. [Alexa-LockController](#LockController) +11. [Alexa-CameraStreamController](#CameraStreamController) +12. [Alexa-SceneController](#SceneController) # -------------------------------------- -## Generell +##Generell Die Daten des Plugin müssen in den Ordner /usr/local/smarthome/plugins/alexa4p3/ (wie gewohnt) Die Rechte entsprechend setzen. @@ -63,12 +64,24 @@ PayloadV2 : turnon PayloadV3 : TurnOn Die Actions unterscheiden sich zwischen Payload V2 und V3 oft nur durch Gross/Klein-Schreibung - -## Icons / Catagories +##Change Log +###24.12.2018 +- CameraStream Controller eingebaut +- Doku für CameraStreamController erstellt +- Doku für PercentageController erstellt +- Bug Fix für fehlerhafte Testfunktionen aus der Lambda + +###12.12.2018 +- Scene Controller eingebaut +- Doku für Scene Controller erstellt +- PercentageController eingebaut + +##Icons / Catagories Optional kann im Item angegeben werden welches Icon in der Alexa-App verwendet werden soll : - - alexa_icon = "LIGHT" - +

      
      +alexa_icon = "LIGHT"
      +
      +
       
      @@ -165,6 +178,7 @@ Optional kann im Item angegeben werden welches Icon in der Alexa-App verwendet w
           
      +
      default = "Switch" (vergleiche : https://developer.amazon.com/docs/device-apis/alexa-discovery.html#display-categories ) Optional kann im Item angegeben werden ob es durch Amazon abgefragt werden kann : @@ -260,7 +274,7 @@ OG: enforce_updates: 'true' -## Entwicklung / Einbau von neuen Fähigkeiten +##Entwicklung / Einbau von neuen Fähigkeiten Um weitere Actions hinzuzufügen muss die Datei p3_actions.py mit den entsprechenden Actions ergänzt werden. (wie ursprünglich als selbstregistrierende Funktion) @@ -288,7 +302,7 @@ siehe Amazon z.B.: https://developer.amazon.com/docs/device-apis/list-of-interfa In der "service.py" muss für den ReportState der Rückgabewert für die neue Action hinzugefügt werden. (siehe Quellcode) -## Alexa-ThermostatController + Thermosensor +## Alexa-ThermostatController + Thermosensor Es kann nun via Alexa die Solltemperatur verändert werden und der Modus des Thermostaten kann umgestellt werden. Die Konfiguration der YAML-Datei sieht wie folgt aus @@ -316,7 +330,7 @@ alexa_icon = "THERMOSTAT" = Thermostatcontroller alexa_icon = "TEMPERATURE_SENSOR" = Temperatursensor -### Thermostatsensor +###Thermostatsensor Der Temperartursensor wird beim Item der Ist-Temperatur hinterlegt. Der Thermostatconroller wird beim Thermostat-Item hinterlegt. An Amazon werden die Icons als Array übertragen. @@ -328,7 +342,7 @@ alexa_actions : "ReportTemperature" Alexa wie ist die Temperatur in der Küche ? -### Verändern der Temperatur (SetTargetTemperature AdjustTargetTemperature) +###Verändern der Temperatur (SetTargetTemperature AdjustTargetTemperature)
      
       alexa_actions = "SetTargetTemperature AdjustTargetTemperature"
      @@ -341,7 +355,7 @@ Alexa erhöhe die Temperatur in der Küche um zwei Grad
       
       Alexa stelle die Temperatur in der Küche auf zweiundzwanzig Grad
       
      -### Thermostatmode
      +###Thermostatmode
       
       alexa_actions = "SetThermostatMode"
       
      @@ -465,7 +479,7 @@ Gruppenadresse anlegen)
       
       
      -## Alexa-PowerController +## Alexa-PowerController Alexa schalte das Licht im Flur OG ein @@ -493,7 +507,7 @@ Beispiel enforce_updates = true -## Alexa-BrightnessController +## Alexa-BrightnessController Alexa stelle das Licht am Esstisch auf fünfzig Prozent Alexa dimme das Licht am Esstisch um zehn Prozent Folgende Parameter sind anzugeben : @@ -534,15 +548,17 @@ Beispiel : enforce_updates = true -## Alexa-PowerLevelController +## Alexa-PowerLevelController tbd -## Alexa-PercentageController +## Alexa-PercentageController tbd -## Alexa-LockController +## Alexa-LockController tbd -## Alexa-CameraStreamContoller -tbd -## Alexa-SceneController +## Alexa-CameraStreamContoller + + + +## Alexa-SceneController Alexa aktiviere Szene kommen @@ -569,4 +585,4 @@ Beispiel Konfiguration : alexa_item_turn_on : 3 alexa_actions : "Activate" alexa_retrievable : false - + \ No newline at end of file diff --git a/alexa4p3/__init__.py b/alexa4p3/__init__.py index 547522ce7..94ab6d213 100644 --- a/alexa4p3/__init__.py +++ b/alexa4p3/__init__.py @@ -1,4 +1,5 @@ -# !/usr/bin/env python3 + +#!/usr/bin/env python3 # vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab ######################################################################### # Copyright 2016 Kai Meder @@ -19,9 +20,15 @@ # You should have received a copy of the GNU General Public License # along with SmartHomeNG. If not, see . ######################################################################### +import os +import sys + + from lib.model.smartplugin import SmartPlugin import logging +import json + from .device import AlexaDevices, AlexaDevice from .action import AlexaActions @@ -34,12 +41,14 @@ from . import p3_action + + + class Alexa4P3(SmartPlugin): PLUGIN_VERSION = "1.0.0.0.0" ALLOW_MULTIINSTANCE = False - def __init__(self, sh, service_host='0.0.0.0', service_port=9000, service_https_certfile=None, - service_https_keyfile=None): + def __init__(self, sh, service_host='0.0.0.0', service_port=9000, service_https_certfile=None, service_https_keyfile=None): self.logger = logging.getLogger(__name__) self.sh = sh self.devices = AlexaDevices() @@ -57,22 +66,22 @@ def stop(self): self.service.stop() self.alive = False + def parse_item(self, item): # device/appliance self.logger.debug('Parse-Item') device_id = None if 'alexa_device' in item.conf: device_id = item.conf['alexa_device'] - # supported actions/directives + + #supported actions/directives action_names = None if 'alexa_actions' in item.conf: - action_names = list(map(str.strip, item.conf['alexa_actions'].split(' '))) + action_names = list( map(str.strip, item.conf['alexa_actions'].split(' ')) ) self.logger.debug("Alexa: {}-actions = {}".format(item.id(), action_names)) for action_name in action_names: if action_name and self.actions.by_name(action_name) is None: - self.logger.error( - "Alexa: invalid alexa action '{}' specified in item {}, ignoring item".format(action_name, - item.id())) + self.logger.error("Alexa: invalid alexa action '{}' specified in item {}, ignoring item".format(action_name, item.id())) return None # friendly name @@ -84,7 +93,9 @@ def parse_item(self, item): elif action_names and 'name' in item.conf: name = item.conf['name'] name_is_explicit = False - + + if name == 'Doorcam': + # deduce device-id from name if name and not device_id: device_id = AlexaDevice.create_id_from_name(name) @@ -93,26 +104,24 @@ def parse_item(self, item): if device_id: self.logger.debug("Alexa: {}-device = {}".format(item.id(), device_id)) else: - return None # skip this item + return None # skip this item # create device if not yet existing if not self.devices.exists(device_id): - self.devices.put(AlexaDevice(device_id)) + self.devices.put( AlexaDevice(device_id) ) device = self.devices.get(device_id) # types if 'alexa_types' in item.conf: - device.types = list(map(str.strip, item.conf['alexa_types'].split(' '))) + device.types = list( map(str.strip, item.conf['alexa_types'].split(' ')) ) self.logger.debug("Alexa: {}-types = {}".format(item.id(), device.types)) # friendly name if name and (not device.name or name_is_explicit): self.logger.debug("Alexa: {}-name = {}".format(item.id(), name)) if device.name and device.name != name: - self.logger.warning( - "Alexa: item {} is changing device-name of {} from '{}' to '{}'".format(item.id(), device_id, - device.name, name)) + self.logger.warning("Alexa: item {} is changing device-name of {} from '{}' to '{}'".format(item.id(), device_id, device.name, name)) device.name = name # friendly description @@ -120,15 +129,12 @@ def parse_item(self, item): descr = item.conf['alexa_description'] self.logger.debug("Alexa: {}-description = {}".format(item.id(), descr)) if device.description and device.description != descr: - self.logger.warning( - "Alexa: item {} is changing device-description of {} from '{}' to '{}'".format(item.id(), device_id, - device.description, - descr)) + self.logger.warning("Alexa: item {} is changing device-description of {} from '{}' to '{}'".format(item.id(), device_id, device.description, descr)) device.description = descr # alias names if 'alexa_alias' in item.conf: - alias_names = list(map(str.strip, item.conf['alexa_alias'].split(','))) + alias_names = list( map(str.strip, item.conf['alexa_alias'].split(',')) ) for alias_name in alias_names: self.logger.debug("Alexa: {}-alias = {}".format(item.id(), alias_name)) device.alias.append(alias_name) @@ -136,23 +142,43 @@ def parse_item(self, item): # value-range if 'alexa_item_range' in item.conf: item_min_raw, item_max_raw = item.conf['alexa_item_range'].split('-') - item_min = float(item_min_raw.strip()) - item_max = float(item_max_raw.strip()) + item_min = float( item_min_raw.strip() ) + item_max = float( item_max_raw.strip() ) item.alexa_range = (item_min, item_max) self.logger.debug("Alexa: {}-range = {}".format(item.id(), item.alexa_range)) # special turn on/off values if 'alexa_item_turn_on' in item.conf or 'alexa_item_turn_off' in item.conf: - turn_on = item.conf['alexa_item_turn_on'] if 'alexa_item_turn_on' in item.conf else True + turn_on = item.conf['alexa_item_turn_on'] if 'alexa_item_turn_on' in item.conf else True turn_off = item.conf['alexa_item_turn_off'] if 'alexa_item_turn_off' in item.conf else False item.alexa_range = (turn_on, turn_off) self.logger.debug("Alexa: {}-range = {}".format(item.id(), item.alexa_range)) - # =============================================== - # P3 - Properties - # =============================================== - if 'alexa_thermo_config' in item.conf: # only for Version 1.0.0.0.0 + #=============================================== + #P3 - Properties + #=============================================== + # ---- Start CamerStreamController + if 'alexa_camera' in item.conf: + camera_setting = item.conf['alexa_camera'] + camera_setting = json.loads(camera_setting) + device.camera_setting=camera_setting + self.logger.debug("Alexa: {}-Camera-Config = {}".format(item.id(), device.camera_setting)) + + #if 'alexa_camera_uri' in item.conf: + # alexa_camera_uri = item.conf['alexa_camera'] + # device.camera_uri = alexa_camera_uri + # self.logger.debug("Alexa: {}-Camera-Uri = {}".format(item.id(), device.camera_uri)) + + if 'alexa_camera_imageUri' in item.conf: + alexa_camera_imageUri = item.conf['alexa_camera_imageUri'] + device.camera_imageUri = alexa_camera_imageUri + self.logger.debug("Alexa: {}-Camera-Image-Uri = {}".format(item.id(), device.camera_imageUri)) + # ---- Ende CamerStreamController + + + + if 'alexa_thermo_config' in item.conf: thermo_config = item.conf['alexa_thermo_config'] - device.thermo_config = item.conf['alexa_thermo_config'] + device.thermo_config =item.conf['alexa_thermo_config'] self.logger.debug("Alexa: {}-Thermo-Config = {}".format(item.id(), device.thermo_config)) # Icon for Alexa-App - default = SWITCH if 'alexa_icon' in item.conf: @@ -165,18 +191,19 @@ def parse_item(self, item): retrievable = item.conf['alexa_retrievable'] device.retrievable = retrievable self.logger.debug("Alexa: {}-alexa_retrievable = {}".format(item.id(), device.retrievable)) - + + if 'alexa_proactivelyReported' in item.conf: proactivelyReported = item.conf['alexa_proactivelyReported'] device.proactivelyReported = proactivelyReported self.logger.debug("Alexa: {}-alexa_proactivelyReported = {}".format(item.id(), device.proactivelyReported)) - + + # register item-actions with the device if action_names: for action_name in action_names: device.register(action_name, item) - self.logger.info("Alexa: {} supports {} as device {}".format(item.id(), action_names, device_id, - device.supported_actions())) + self.logger.info("Alexa: {} supports {} as device {}".format(item.id(), action_names, device_id, device.supported_actions())) return None @@ -193,8 +220,7 @@ def create_alias_devices(self): for device in self.devices.all(): alias_devices = device.create_alias_devices() for alias_device in alias_devices: - self.logger.info( - "Alexa: device {} aliased '{}' via {}".format(device.id, alias_device.name, alias_device.id)) - self.devices.put(alias_device) + self.logger.info("Alexa: device {} aliased '{}' via {}".format(device.id, alias_device.name, alias_device.id)) + self.devices.put( alias_device ) - self.logger.info("Alexa: providing {} devices".format(len(self.devices.all()))) + self.logger.info("Alexa: providing {} devices".format( len(self.devices.all()) )) diff --git a/alexa4p3/_config.yml b/alexa4p3/_config.yml deleted file mode 100644 index c4192631f..000000000 --- a/alexa4p3/_config.yml +++ /dev/null @@ -1 +0,0 @@ -theme: jekyll-theme-cayman \ No newline at end of file diff --git a/alexa4p3/action.py b/alexa4p3/action.py index 07207e790..77c1a9a73 100644 --- a/alexa4p3/action.py +++ b/alexa4p3/action.py @@ -92,7 +92,7 @@ def search(self,p, strsearch): if not tokenvalue is None: return tokenvalue def replace(self,p, strsearch, newValue): - if type(p) is dict: # im Dictionary nach 'language' suchen + if type(p) is dict: if strsearch in p: tokenvalue = p[strsearch] p[strsearch] = newValue @@ -100,9 +100,10 @@ def replace(self,p, strsearch, newValue): return tokenvalue else: for i in p: - tokenvalue = self.search(p, strsearch)(p[i], strsearch) # in den anderen Elementen weiter suchen + tokenvalue = self.replace(p[i], strsearch,newValue) if not tokenvalue is None: return tokenvalue + def GenerateThermoList(self, myModes, listType): mylist = myModes.split(' ') myValueList = {} @@ -159,6 +160,7 @@ def p3_AddDependencies(self, orgDirective, dependency, myEndPointID): return orgDirective def p3_respond(self, Request): + myEndpoint = self.search(Request,'endpoint') myScope = self.search(Request,'scope') myEndPointID = self.search(Request,'endpointId') @@ -191,8 +193,37 @@ def p3_respond(self, Request): } } + # Check for Special Response-Type + if self.namespace == 'Alexa.SceneController': + + self.replace(myReponse,'context',{}) + self.replace(myReponse,'payload',{ + "cause" : { + "type" : "VOICE_INTERACTION" + }, + "timestamp" : myTimeStamp + }) + self.replace(myReponse,'namespace',self.namespace) + self.replace(myReponse,'name',self.response_type,) - + elif self.namespace == 'Alexa.CameraStreamController': + self.replace(myReponse,'context',{}) + self.replace(myReponse,'payload',{ + "cameraStreams" :[ { + "uri": "rtsp://username:password@link.to.video:443/feed1.mp4", + #"expirationTime": "2017-02-03T16:20:50.52Z", !! Not needed + "idleTimeoutSeconds": 300, + "protocol": "RTSP", + "resolution": { + "width": 1920, + "height": 1080 + }, + "authorizationType": "BASIC", + "videoCodec": "H264", + "audioCodec": "AAC" + }], + "imageUri": "https://username:password@link.to.image/image.jpg" + }) # Check for special needs of dependencies if len(self.properties) != 0: @@ -202,6 +233,8 @@ def p3_respond(self, Request): + + return myReponse diff --git a/alexa4p3/device.py b/alexa4p3/device.py index 8bc94a7e1..8d9399734 100644 --- a/alexa4p3/device.py +++ b/alexa4p3/device.py @@ -27,6 +27,9 @@ def __init__(self, id): self.icon = [] self.retrievable = False self.proactivelyReported = False + self.camera_setting = {} + self.camera_uri = None + self.camera_imageUri = None @classmethod def create_id_from_name(cls, name): diff --git a/alexa4p3/nginx.md b/alexa4p3/nginx.md deleted file mode 100644 index 1cda6067a..000000000 --- a/alexa4p3/nginx.md +++ /dev/null @@ -1,176 +0,0 @@ -# NGINX -Nginx is a reverse-proxy that exposes web-services on HTTP/80 and HTTPS/443 and routes the request to the actual servers for processing. -So you can serve multiple services using a single nginx instance and let nginx do the tedious part of doing SSL-termination, authentication etc. - -Using Nginx you can: -- expose your router's public IP with HTTP & HTTPS on the Internet -- make multiple web-services from multiple local servers available by letting nginx dispatch to the right service -- HTTPS/SSL/TLS termination - including nice integration with https://letsencrypt.org/ -- simple and widely supported http basic authentication (that is perfectly safe over SSL/TLS) -- very lightweight, minimal memory footprint - -# Install (debian) -`sudo apt-get install nginx` - -# /etc/nginx/nginx.conf -``` -user www-data; -worker_processes 2; -pid /run/nginx.pid; - -events { - worker_connections 768; - # multi_accept on; -} - -http { - sendfile on; - tcp_nopush on; - tcp_nodelay on; - keepalive_timeout 65; - types_hash_max_size 2048; - server_tokens off; - - # server_names_hash_bucket_size 64; - # server_name_in_redirect off; - - include /etc/nginx/mime.types; - default_type application/octet-stream; - - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE - ssl_prefer_server_ciphers on; - - access_log /var/log/nginx/access.log; - error_log /var/log/nginx/error.log; - - gzip on; - gzip_disable "msie6"; - - # gzip_vary on; - # gzip_proxied any; - # gzip_comp_level 6; - # gzip_buffers 16 8k; - # gzip_http_version 1.1; - # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; - - # include /etc/nginx/conf.d/*.conf; - include /etc/nginx/sites-enabled/*; -} -``` - -# /etc/nginx/include.d/common -``` -# letsencrypt shizzle -ssl_certificate /etc/letsencrypt/live/YOUR-HOME.DYNDNS.TLD/fullchain.pem; -ssl_certificate_key /etc/letsencrypt/live/YOUR-HOME.DYNDNS.TLD/privkey.pem; - -ssl_stapling on; -ssl_stapling_verify on; - -# maintain the .well-known directory alias for letsencrypt & renewals -location /.well-known { - auth_basic off; - alias /var/www/.well-known; -} -``` - -# /etc/nginx/sites-available/your-home -``` -# SSL-Redirect & LetsEncrypt Endpoint -server { - listen 80 default_server; - - # redirect every requested $host (any, even invalid ones) to its SSL URL - location / { - return 301 https://$host$request_uri; - } - - # LetsEncrypt Endpoint - location /.well-known { - alias /var/www/.well-known; - } -} - -# Sitemap -server { - listen 443 ssl default_server; - - access_log /var/log/nginx/sitemap.log combined; - auth_basic "YOUR-HOME.DYNDNS.TLD"; - auth_basic_user_file /etc/nginx/htpasswd; - include /etc/nginx/include.d/common; - - #add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; - - location / { - root /var/www/sitemap; - index index.html; - } -} - -# Alexa -server { - listen 443 ssl; - server_name ALEXA.YOUR-HOME.DYNDNS.TLD; - access_log /var/log/nginx/alexa.log combined; - auth_basic "Alexa"; - auth_basic_user_file /etc/nginx/htpasswd.alexa; - include /etc/nginx/include.d/common; - - location / { - proxy_pass http://192.168.X.Y:9000/; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } -} - -# ANOTHER-SERVICE.YOUR-HOME.DYNDNS.TLD -server { - listen 443 ssl; - server_name ANOTHER-SERVICE.YOUR-HOME.DYNDNS.TLD; - access_log /var/log/nginx/ANOTHER-SERVICE.log combined; - auth_basic "ANOTHER-SERVICE"; - auth_basic_user_file /etc/nginx/htpasswd; - include /etc/nginx/include.d/common; - - location / { - proxy_pass http://192.168.X.Z/; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - } -} -``` - -# /etc/nginx/sites-enabled/your-home -just create a symlink in `/etc/nginx/sites-enabled/` that points to your config: -`sudo ln -s /etc/nginx/sites-enabled/your-home /etc/nginx/sites-available/your-home` - -# Sitemap -You can create a Sitemap at /var/www/sitemap/index.html to give a nice overview of your services -``` - - - - YOU-HOME - - - - - -``` - -# User & Passwords -/etc/nginx/htpasswd -format is `user:password` -generate passwords using `openssl passwd "YOUR-PASSWORD"` - -# Let's Encrypt SSL Certificate -- download certbot from https://certbot.eff.org/ -- create certificates: `sudo certbot certonly --webroot -w /var/www -d YOUR-HOME.DYNDNS.TLD -d ALEXA.YOUR-HOME.DYNDNS.TLD -d ANOTHER-SERVICE.YOUR-HOME.DYNDNS.TLD` - -further reading http://serverfault.com/questions/768509/lets-encrypt-with-an-nginx-reverse-proxy/784940#784940 diff --git a/alexa4p3/p3_action.py b/alexa4p3/p3_action.py index c1937aad8..9e6847355 100644 --- a/alexa4p3/p3_action.py +++ b/alexa4p3/p3_action.py @@ -152,7 +152,7 @@ def TurnOff(self, directive): # Alexa-Doorlock Controller -@alexa('Lock', 'Lock', 'LockConfirmation','Alexa.LockController',[]) +@alexa('Lock', 'Lock', 'lockState','Alexa.LockController',[]) def Lock(self, directive): device_id = directive['endpoint']['endpointId'] items = self.items(device_id) @@ -167,7 +167,7 @@ def Lock(self, directive): return self.p3_respond(directive) -@alexa('Unlock', 'Unlock', 'UnlockConfirmation','Alexa.LockController',[]) +@alexa('Unlock', 'Unlock', 'lockState','Alexa.LockController',[]) def Unlock(self, directive): device_id = directive['endpoint']['endpointId'] items = self.items(device_id) @@ -267,7 +267,7 @@ def SetPercentage(self, directive): def Activate(self, directive): device_id = directive['endpoint']['endpointId'] items = self.items(device_id) - new_percentage = float( directive['payload']['percentage'] ) + for item in items: on, off = self.item_range(item, DEFAULT_RANGE_LOGIC) @@ -279,6 +279,35 @@ def Activate(self, directive): return self.p3_respond(directive) +# CameraStreamController +@alexa('InitializeCameraStreams', 'InitializeCameraStreams', 'cameraStreamConfigurations','Alexa.CameraStreamController',[]) +def InitializeCameraStreams(self, directive): + device_id = directive['endpoint']['endpointId'] + items = self.items(device_id) + for item in items: + self.logger.info("Alexa P3: CameraStream Init ({})".format(item.id())) + + + return self.p3_respond(directive) + +# CameraStreamController +@alexa('AcceptGrant', 'AcceptGrant', 'AcceptGrant.Response','Alexa.Authorization',[]) +def AcceptGrant(self, directive): + self.logger.info("Alexa P3: AcceptGrant received ({})") + myResponse = { + "event": { + "header": { + "messageId": "", + "namespace": "Alexa.Authorization", + "name": "AcceptGrant.Response", + "payloadVersion": "3" + }, + "payload": { + } + } + } + self.replace(myResponse,'messageId',uuid.uuid4().hex) + return myResponse #====================================================== # No directives only Responses for Reportstate diff --git a/alexa4p3/service.py b/alexa4p3/service.py index 394e008f1..a18a96ad9 100644 --- a/alexa4p3/service.py +++ b/alexa4p3/service.py @@ -80,7 +80,7 @@ def replace(self,p, strsearch, newValue): return tokenvalue else: for i in p: - tokenvalue = self.search(p[i], strsearch) + tokenvalue = self.replace(p[i], strsearch,newValue) if not tokenvalue is None: return tokenvalue @@ -97,14 +97,13 @@ def GenerateThermoList(self, myModes, listType): elif listType == 2: return myModeList def do_POST(self): - self.logger.debug("{} {} {}".format(self.request_version, self.command, self.path)) try: length = int(self.headers.get('Content-Length')) data = self.rfile.read(length).decode('utf-8') req = json.loads(data) #====================================== - # test Payloadversion + # Test Payloadversion #====================================== payloadVersion = self.search( req,'payloadVersion') #====================================== @@ -140,11 +139,17 @@ def do_POST(self): payload = self.search( req,'payload') if header['namespace'] == 'Alexa.Discovery': return self.p3_handle_discovery(header, payload) - if header['namespace'] == 'Alexa': + elif header['namespace'] == 'Alexa': return self.p3_handle_control(header, payload,mydirective) - if mydirective != None: + elif mydirective != None: return self.p3_handle_control(header, payload,mydirective) + else: + msg = "unknown `header.namespace` '{}'".format(header['namespace']) + self.logger.error(msg) + self.send_error(400, explain=msg) + else: + self.send_error(500,"Request with unknown Payload '{}'".format(payloadVersion)) except Exception as e: self.send_error(500, explain=str(e)) @@ -185,6 +190,7 @@ def handle_discovery(self, header, payload): self.logger.debug("AlexaP3: discovery-directive '{}' received".format(directive)) if directive == 'DiscoverAppliancesRequest': + #myResponse = self.discover_appliances() self.respond(self.discover_appliances()) else: msg = "unknown `header.name` '{}'".format(directive) @@ -286,8 +292,21 @@ def p3_discover_appliances(self): {"name" : 'targetSetpoint'} ] newcapa['properties']['supported'] = mysupported - - + + + + if NameSpace == 'Alexa.SceneController': + newcapa={"type": "AlexaInterface", + "interface": NameSpace, + "version": "3", + "supportsDeactivation" : False + } + if NameSpace == 'Alexa.CameraStreamController': + newcapa={"type": "AlexaInterface", + "interface": NameSpace, + "version": "3", + "cameraStreamConfigurations" : device.camera_setting + } # End Check special Namespace mycapabilities.append(newcapa) @@ -296,8 +315,8 @@ def p3_discover_appliances(self): appliance = { "endpointId": device.id, "friendlyName": device.name, - "description": "smarthomeNG.alexa-device", - "manufacturerName": "smarthomeNG.alexa P3", + "description": "SmartHomeNG", + "manufacturerName": "SmarthomeNG", "displayCategories": device.icon, "cookie": { @@ -307,6 +326,7 @@ def p3_discover_appliances(self): mycapabilities } discovered.append(appliance) + return { "event": { "header": { @@ -337,8 +357,8 @@ def discover_appliances(self): 'friendlyDescription': device.description, 'friendlyName': device.name, 'isReachable': True, - 'manufacturerName': 'smarthomeNG.alexa', - 'modelName': 'smarthomeNG.alexa-device', + 'manufacturerName': 'SmartHomeNG', + 'modelName': 'SmartHomeNG', 'version': self.version } if device.types: @@ -362,7 +382,8 @@ def p3_ReportState(self, directive): AlexaItem = self.devices.get(device_id) myItems = AlexaItem.backed_items() - Properties = [] + Properties = [] + myValue = None # walk over all Items examp..: Item: OG.Flur.Spots.dimmen / Item: OG.Flur.Spots for Item in myItems: # Get all Actions for this item @@ -484,7 +505,6 @@ def p3_handle_control(self, header, payload,mydirective): }) return - action = self.actions.for_directive(directive) if action: try: From 9dd40709595d541ccc249ac72a05f9031d7219e0 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Thu, 27 Dec 2018 09:04:59 +0100 Subject: [PATCH 499/705] fixed documentation warnings --- avdevice/plugin.yaml | 4 ++++ avdevice/user_doc.rst | 5 ++--- avdevice/user_doc_en.rst | 37 ++++++++++++++----------------------- 3 files changed, 20 insertions(+), 26 deletions(-) diff --git a/avdevice/plugin.yaml b/avdevice/plugin.yaml index 4f9b97a50..8b53aaf46 100755 --- a/avdevice/plugin.yaml +++ b/avdevice/plugin.yaml @@ -8,6 +8,7 @@ plugin: description_long: de: 'Steuerung von diversen AV Geräten über TCP/IP und RS232 Schnittstelle.\n Das Plugin unterstützt eine Vielzahl von AV-Geräten und wurde mit folgenden Geräten getestet:\n + \n - Pioneer AV Receiver < 2016\n - Denon AV Receiver > 2016\n - Epson Projektor < 2010\n @@ -15,6 +16,7 @@ plugin: ' en: 'Controlling AV devices via TCP/IP and RS232\n The plugin supports a variety of AV devices and was tested with the following models:\n + \n - Pioneer AV Receiver < 2016\n - Denon AV Receiver > 2016\n - Epson Projektor < 2010\n @@ -320,6 +322,7 @@ item_attributes: description_long: de: 'Das Attribut muss mit dem Kommando ergänzt werden, das in der Text Datei im Ordner models hinterlegt ist, zB power oder volume\n Außerdem gibt es zwei spezielle Parameter, die bei Bedarf eingesetzt werden können:\n + \n - **avdevice: statusupdate**: Dieses Item wird genutzt, um eine komplette Statusabfrage durchzuführen. Es werden alle Query-Kommandos an das Gerät geschickt, was vor allem nach dem Einschalten einer geschaltenen Steckdose relevant ist.\n @@ -330,6 +333,7 @@ item_attributes: en: 'This attribute has to be followed by one of the commands declared in the device text file in the models folders like power or volume\n You can use two special avdevice attribute values if you want:\n + \n - **avdevice: statusupdate**: Use this item to trigger a full statusupdate. All query commands regarding the currently powered on zones are sent. This is especially useful if you have a power socket you diff --git a/avdevice/user_doc.rst b/avdevice/user_doc.rst index ae43046fe..44a67c14a 100755 --- a/avdevice/user_doc.rst +++ b/avdevice/user_doc.rst @@ -9,7 +9,7 @@ Konfiguration .. important:: -Die Informationen zur Konfiguration des Plugins sind unter :doc:`/plugins_doc/config/avdevice` beschrieben. + Die Informationen zur Konfiguration des Plugins sind unter :doc:`/plugins_doc/config/avdevice` beschrieben. .. code-block:: yaml @@ -125,8 +125,7 @@ Das folgende Beispiel zeigt diese Abhängigkeiten: - Tonencoding und -sprache werden nach der Verbindung abgefragt oder sobald auf ``play`` gedrückt wurde -- Die Tracknummer wird unter folgenden Bedingungen abgefragt oder aktualisiert: play ODER status sind wahr UND -Verbose ist auf 2 gesetzt UND der Audiotyp ist entweder PCM ODER PCM 44.1/16 +- Die Tracknummer wird unter folgenden Bedingungen abgefragt oder aktualisiert: play ODER status sind wahr UND Verbose ist auf 2 gesetzt UND der Audiotyp ist entweder PCM ODER PCM 44.1/16 - Der Trackname wird aktualisiert/abgefragt, wenn folgende Bedingung erfüllt ist: (play == True OR status == "play") AND verbose == 2 AND audiotype == (PCM or PCM 44.1/16) AND disctpye == (DVD-AUDIO or CDDA or DATA-DISC) diff --git a/avdevice/user_doc_en.rst b/avdevice/user_doc_en.rst index 64969dbc4..613d3a2ad 100755 --- a/avdevice/user_doc_en.rst +++ b/avdevice/user_doc_en.rst @@ -9,7 +9,7 @@ Configuration .. important:: -You can find the configuration information at :doc:`/plugins_doc/config/avdevice`. + You can find the configuration information at :doc:`/plugins_doc/config/avdevice`. .. code-block:: yaml @@ -47,7 +47,7 @@ Items ===== avdevice_zone[0-4]@[instance]: [function] ----------------------------------------- +----------------------------------------- Specifiy the zone number and instance. If you don’t use zones you can either use ``avdevice`` or ``avdevice_zone0`` as attributes. @@ -69,7 +69,7 @@ Special attribute values (statusupdate and reload) are described at :doc:`/plugi avdevice_zone[0-4]_speakers@[instance]: [function] -------------------------------------------------- +-------------------------------------------------- Specifiy the zone number and instance. This attribute is used to switch between Speaker A, B and AB layout. Speakers Items are special and @@ -100,7 +100,7 @@ Pioneer receivers < 2016). avdevice_zone[0-4]_depend@[instance]: [function] ------------------------------------------------ +------------------------------------------------ Specifiy the zone number and instance. The depend attribute lets you specifiy for each item if it depends on another item/function. If you @@ -108,14 +108,11 @@ define such a dependency several things will happen: - The item only gets updated/changed if the dependency is fullfilled -- Query command of the item will get removed from the queue if the dependency is not -fullfilled +- Query command of the item will get removed from the queue if the dependency is not fullfilled -- Query command of the item will (only) get added if one of -the master items gets changed and the dependency is fullfilled. +- Query command of the item will (only) get added if one of the master items gets changed and the dependency is fullfilled. -- After connecting to the device the query command of an item only gets -added if you add ``init`` to the dependency configuration. +- After connecting to the device the query command of an item only gets added if you add ``init`` to the dependency configuration. You can use multiple depend items and attributes even for different zones. You can even define ``and/or`` for the dependencies by adding up to @@ -133,20 +130,14 @@ functions/items corresponds to the given value. The example below shows the following dependencies: -- The disctype will always be queried after connecting to the device (as long as you have -specified a query command in the command-file) +- The disctype will always be queried after connecting to the device (as long as you have specified a query command in the command-file) -- Audio language and encoding will be queried after connecting to the device or as so -on as -the item with the ``play`` function (Oppo.Play) is True -- The track will get updated/queried if these dependencies are fullfilled: (play is True -or status is play) AND verbose is set to 2 AND audiotype is either PCM -or PCM 44.1/16 +- Audio language and encoding will be queried after connecting to the device or as so on as the item with the ``play`` function (Oppo.Play) is True + +- The track will get updated/queried if these dependencies are fullfilled: (play is True or status is play) AND verbose is set to 2 AND audiotype is either PCM or PCM 44.1/16 + +- The trackname will get updated/queried if these dependencies are fullfilled: (play is True or status is play) AND verbose is set to 2 AND audiotype is either PCM or PCM 44.1/16 AND disctpye is one of these three values: DVD-AUDIO, CDDA, DATA-DISC -- The trackname will get updated/queried if these -dependencies are fullfilled: (play is True or status is play) AND -verbose is set to 2 AND audiotype is either PCM or PCM 44.1/16 AND -disctpye is one of these three values: DVD-AUDIO, CDDA, DATA-DISC .. code-block:: yaml @@ -242,7 +233,7 @@ disctpye is one of these three values: DVD-AUDIO, CDDA, DATA-DISC - verbose = 2, d avdevice_zone[0-4]_init@[instance]: [function] ---------------------------------------------- +---------------------------------------------- Specifiy the zone number and instance. The init attribute lets you set a specific command to a specific value as soon as the device is connected. For example if you want to always set the verbose level to 2 as soon as the plugin connects to it (at startup and after turning on the power socket or reconnecting the cable) you can define an additional item with the attribute "avdevice_init". The value of that item (Oppo.Verbose.Init) gets appended to the command linked to the verbose item (Oppo.Verbose). From 619c30830e05f31cc326323371d80b5d099c8cff Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Thu, 27 Dec 2018 09:29:12 +0100 Subject: [PATCH 500/705] fixed documentation --- stateengine/plugin.yaml | 34 +++++++++++--------- stateengine/user_doc/user_doc10.rst | 16 ++++----- stateengine/user_doc/user_doc12.rst | 10 +++--- stateengine/user_doc/user_doc13.rst | 9 +++--- stateengine/user_doc/user_doc3.rst | 50 ++++++++++++++--------------- stateengine/user_doc/user_doc4.rst | 2 +- stateengine/user_doc/user_doc6.rst | 6 ++-- stateengine/user_doc/user_doc7.rst | 29 ++++++++--------- stateengine/user_doc/user_doc8.rst | 2 +- 9 files changed, 79 insertions(+), 79 deletions(-) diff --git a/stateengine/plugin.yaml b/stateengine/plugin.yaml index 21cb3bf30..2a87c852c 100755 --- a/stateengine/plugin.yaml +++ b/stateengine/plugin.yaml @@ -48,26 +48,30 @@ parameters: ihren Initialwert haben, wird die erste Zustandsermittlung verzögert. Die Dauer der Verzögerung kann bei den Objekt-Items angegeben werden. Wenn bei einem Objekt-Item kein Wert angegeben - ist, wird der hier angegebene Standardwert verwendet. + ist, wird der hier angegebene Standardwert verwendet.\n \n - - Zahl größer 0: - Angabe der Startverzögerung in Sekunden. Während der - Startverzögerung sind die Auslöser der Zustandsermittlung - inaktiv.\n - - 0: - Keine Startverzögerung. Die erste Zustandsermittlung wird direkt - nach der Initialisierung des Objekt-Items durchgeführt.\n - - -1: - Es wird keine erste Zustandsermittlung durchgeführt.\n + - Zahl größer 0: + Angabe der Startverzögerung in Sekunden. Während der + Startverzögerung sind die Auslöser der Zustandsermittlung + inaktiv.\n + - 0: + Keine Startverzögerung. Die erste Zustandsermittlung wird direkt + nach der Initialisierung des Objekt-Items durchgeführt.\n + - -1: + Es wird keine erste Zustandsermittlung durchgeführt.\n \n Ohne Angabe dieses Parameters wird der Standardwert von 10 Sekunden angenommen. ' en: '**Default delay for first state determination at startup:**\n - - digit higher than 0: start delay in seconds\n - - 0: no start delay, immediate init\n - - -1: no init\n - \n - ' + At smarthome startup some items might not be initialized correctly. + To avoid a wrong state evaluation the evaluation can be postponed by the + given amount of seconds. + \n + - digit higher than 0: start delay in seconds\n + - 0: no start delay, immediate init\n + - -1: no init\n + \n + ' suspend_time_default: type: int diff --git a/stateengine/user_doc/user_doc10.rst b/stateengine/user_doc/user_doc10.rst index 38d7eef80..96ebebf3c 100644 --- a/stateengine/user_doc/user_doc10.rst +++ b/stateengine/user_doc/user_doc10.rst @@ -9,14 +9,14 @@ Mit dem Datentyp AbValue kann auf Variablen des Plugins zugegriffen werden. Derzeit stehen folgende Variablen zur Verfügung: -| **item.suspend_time:** -| *Die Suspend-Time des Items* +**item.suspend_time:** +*Die Suspend-Time des Items* -| **item.suspend_remaining:** -| *Die übrige Dauer des Suspend Zustands* +**item.suspend_remaining:** +*Die übrige Dauer des Suspend Zustands* -| **current.state_id:** -| *Die Id des Status, der gerade geprüft wird* +**current.state_id:** +*Die Id des Status, der gerade geprüft wird* -| **current.state_name:** -| *Der Name des Status, der gerade geprüft wird* +**current.state_name:** +*Der Name des Status, der gerade geprüft wird* diff --git a/stateengine/user_doc/user_doc12.rst b/stateengine/user_doc/user_doc12.rst index e289acdb1..330342b13 100644 --- a/stateengine/user_doc/user_doc12.rst +++ b/stateengine/user_doc/user_doc12.rst @@ -71,13 +71,11 @@ Rückmeldung der Raffstore-Position nach dem Verfahren durch den Jalousieaktor. Hierfür stehen zwei für das Manuell-Item weitere Attribute bereit: -| **as_manual_include** -| *Liste der Aufrufe, die als "manuelle Betätigung" gewertet - werden sollen* +**as_manual_include** +*Liste der Aufrufe, die als "manuelle Betätigung" gewertet werden sollen* -| **as_manual_exclude** -| *Liste der Aufrufe, die nicht als "manuelle Betätigung" gewertet - werden sollen* +**as_manual_exclude** +*Liste der Aufrufe, die nicht als "manuelle Betätigung" gewertet werden sollen* Bei beiden Attributen wird eine Liste von Elementen angegeben. Die einzelnen Elemente bestehen dabei aus dem Aufrufenden diff --git a/stateengine/user_doc/user_doc13.rst b/stateengine/user_doc/user_doc13.rst index 4878d1325..b4287494e 100644 --- a/stateengine/user_doc/user_doc13.rst +++ b/stateengine/user_doc/user_doc13.rst @@ -8,9 +8,8 @@ Sofern die eingesetzte smarthomeNG-Version dies unterstützt, registriert das stateengine-Plugin zwei eigene Kommandos beim CLI-Plugin. -| **se_list** -| *Zeigt eine Liste der Objekt-Items, für die das - stateengine-Plugin aktiv ist* +**se_list** +*Zeigt eine Liste der Objekt-Items, für die das stateengine-Plugin aktiv ist* -| **se_detail ** -| *Zeigt Details zum Objekt Item* +**se_detail ** +*Zeigt Details zum Objekt Item* diff --git a/stateengine/user_doc/user_doc3.rst b/stateengine/user_doc/user_doc3.rst index 3c3e002d0..e60925442 100644 --- a/stateengine/user_doc/user_doc3.rst +++ b/stateengine/user_doc/user_doc3.rst @@ -24,20 +24,22 @@ aktuellen Zustand abzulegen. name: Tag se_name: eval: sh.eine_funktion() -| **name (optional):** -| *Name des Zustands* +**name (optional):** +*Name des Zustands* + Der Name des Zustands wird im Protokoll sowie als Wert für das über ``se_laststate_item_name`` angegebene Item verwendet. Wenn kein Name angegeben ist, wird hier die Id des Zustands-Items verwendet. -| **se_name (optional):** -| *Ermittlung des Namens des Zustands* -| Über das Attribut ``se_name`` kann der im Attribut ``name`` angegebene Wert - überschrieben werden. Dies wirkt sich jedoch nur auf den Wert - aus, der in das über ``se_laststate_item_name`` angegebene - Item geschrieben wird. Im Protokoll wird immer der über das - Attribut ``name`` angegebene Wert verwendet. +**se_name (optional):** +*Ermittlung des Namens des Zustands* + +Über das Attribut ``se_name`` kann der im Attribut ``name`` angegebene Wert +überschrieben werden. Dies wirkt sich jedoch nur auf den Wert +aus, der in das über ``se_laststate_item_name`` angegebene +Item geschrieben wird. Im Protokoll wird immer der über das +Attribut ``name`` angegebene Wert verwendet. .. rubric:: Bedingungsgruppen :name: bedingungsgruppen @@ -74,7 +76,7 @@ Die folgenden Regeln kommen zur Anwendung: Default-Zustand am Ende der Zustände definiert werden. .. rubric:: Aktionen - :name: aktionen + :name: aktionenintro Jeder Zustand kann eine beliebige Anzahl an Aktionen definieren. Sobald ein Zustand aktueller Zustand wird, werden die Aktionen des @@ -92,7 +94,7 @@ Diese Items müssen auf Ebene des Objekt-Items über das Attribut ``se_item_`` bekannt gemacht werden. .. rubric:: Beispiel - :name: beispiel + :name: beispielzustand .. code-block:: yaml @@ -123,25 +125,23 @@ Diese Items müssen auf Ebene des Objekt-Items über das Attribut enter: -| **Attribute se_item_height und se_item_lamella:** -| *Definition der Items, die durch die Aktionen - se_set_height und se_set_lamella verändert werden* +**Attribute se_item_height und se_item_lamella:** +*Definition der Items, die durch die Aktionen se_set_height und se_set_lamella verändert werden* + Die Items werden durch ihre Item-Id angegeben -| **Attribut name:** -| *Name des Zustands* +**Attribut name:** +*Name des Zustands* + Der Name wird in das über ``se_laststate_item_name`` definierte Item geschrieben, wenn der Zustand aktueller Zustand wird. Dieser Wert kann z. B. in einer Visualisierung dargestellt werden. -| **Attribute se_set_height und se_set_lamella:** -| *Neu zu setzende Werte für die Items, die über - se_item_height und se_item_lamella festgelegt wurden* +**Attribute se_set_height und se_set_lamella:** +*Neu zu setzende Werte für die Items, die über se_item_height und se_item_lamella festgelegt wurden* -| **Attribut se_mindelta_lamella:** -| *Nur, wenn sich Lamellen min. um x Grad ändern würden, werden sie aktualisiert.* +**Attribut se_mindelta_lamella:** +*Nur, wenn sich Lamellen min. um x Grad ändern würden, werden sie aktualisiert.* -| **Untergeordnete Items enter, enter_toodark und - enter_toolate:** -| *Bedingungsgruppen die erfüllt sein müssen, damit ein Zustand - aktueller Zustand werden kann* +**Untergeordnete Items enter, enter_toodark und enter_toolate:** +*Bedingungsgruppen die erfüllt sein müssen, damit ein Zustand aktueller Zustand werden kann* diff --git a/stateengine/user_doc/user_doc4.rst b/stateengine/user_doc/user_doc4.rst index f68f09b43..bf71f7de2 100644 --- a/stateengine/user_doc/user_doc4.rst +++ b/stateengine/user_doc/user_doc4.rst @@ -130,7 +130,7 @@ beziehen, können ``se_agemin_``, aktuelle Wert über ein Item bereitgestellt wird. .. rubric:: Beispiel - :name: beispiel + :name: beispielbedingungen .. code-block:: yaml diff --git a/stateengine/user_doc/user_doc6.rst b/stateengine/user_doc/user_doc6.rst index 558ad69d2..a77db0874 100644 --- a/stateengine/user_doc/user_doc6.rst +++ b/stateengine/user_doc/user_doc6.rst @@ -102,8 +102,8 @@ Items jeweils zugewiesen ist. type: num mein_eigenes_Attribut: 42 -| wird dann auf ``42`` gesetzt. -| Ein anderes Item +wird dann auf ``42`` gesetzt. +Ein anderes Item .. code-block:: yaml @@ -178,7 +178,7 @@ zufällig. Innerhalb der gesamten Aktionen werden die beiden Aktionen jedoch an der angegebenen Position ausgeführt. .. rubric:: Beispiel zu Aktionen - :name: beispielzuaktionen + :name: beispielzuaktioneneinzeln .. code-block:: yaml diff --git a/stateengine/user_doc/user_doc7.rst b/stateengine/user_doc/user_doc7.rst index 2795b2ceb..838f64493 100644 --- a/stateengine/user_doc/user_doc7.rst +++ b/stateengine/user_doc/user_doc7.rst @@ -42,12 +42,12 @@ Die Angabe erfolgt in Sekunden oder mit dem Suffix "m" in Minuten. delay: 30 --> 30 Sekunden delay: 30m --> 30 Minuten -| Der Timer zur Ausführung der Aktion nach der angegebenen - Verzögerung wird entfernt, wenn eine gleichartike Aktion - ausgeführt werden soll (egal ob verzögert oder nicht). Wenn also - die Verzögerung größer als der ``cycle`` ist, wird die Aktion - nie durchgeführt werden, es sei denn die Aktion soll nur - einmalig ausgeführt werden. +Der Timer zur Ausführung der Aktion nach der angegebenen +Verzögerung wird entfernt, wenn eine gleichartike Aktion +ausgeführt werden soll (egal ob verzögert oder nicht). Wenn also +die Verzögerung größer als der ``cycle`` ist, wird die Aktion +nie durchgeführt werden, es sei denn die Aktion soll nur +einmalig ausgeführt werden. .. rubric:: repeat: ```` :name: repeat @@ -90,10 +90,10 @@ Aktionen jedoch an der angegebenen Position ausgeführt. .. rubric:: function: ```` :name: function -| Mit dem Parameter ```` wird die auszuführende Funktion - festgelegt. In Abhängigkeit zur gewählten Funktion werden - zusätzliche Detailparameter erforderlich. -| Folgende Werte sind möglich: +Mit dem Parameter ```` wird die auszuführende Funktion +festgelegt. In Abhängigkeit zur gewählten Funktion werden +zusätzliche Detailparameter erforderlich. +Folgende Werte sind möglich: **Funktion ``set``: Item auf einen Wert setzen** @@ -155,8 +155,7 @@ Auslösen einen Wert an die Logik zu übergeben, kann dieser Wert angegeben werden. Wenn kein Wert übergeben werden, soll lässt man den Teil weg. -**Funktion ``byattr``: Alle Items, die ein bestimmtes - Attribut haben, auf den Wert dieses Attributs setzen** +**Funktion ``byattr``: Alle Items, die ein bestimmtes Attribut haben, auf den Wert dieses Attributs setzen** .. code-block:: yaml @@ -176,8 +175,8 @@ Items jeweils zugewiesen ist. type: num : 42 -| wird dann auf ``42`` gesetzt. -| Ein anderes Item +wird dann auf ``42`` gesetzt. +Ein anderes Item .. code-block:: yaml @@ -201,7 +200,7 @@ definiert (z. B. für das Suspend). Diese werden jedoch nicht hier erläutert, sondern an den Stellen, andenen Sie verwendet werden. .. rubric:: Beispiel zu Aktionen - :name: beispielzuaktionen + :name: beispielzuaktionenkombiniert .. code-block:: yaml diff --git a/stateengine/user_doc/user_doc8.rst b/stateengine/user_doc/user_doc8.rst index 784e2fb05..a944eacdd 100644 --- a/stateengine/user_doc/user_doc8.rst +++ b/stateengine/user_doc/user_doc8.rst @@ -37,7 +37,7 @@ werden. Um unnötige Komplexität und Zirkelbezüge zu vermeiden, ist die maximale Tiefe jedoch auf 5 Ebenen begrenzt. .. rubric:: Beispiel - :name: beispiel + :name: vorgabebeispiel .. code-block:: yaml From 6449575a78c488c9234340273e7d7c6cced0b443 Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Thu, 27 Dec 2018 10:25:51 +0100 Subject: [PATCH 501/705] update metadata and README --- gpio/README.md | 53 +-------------------------------------- gpio/plugin.yaml | 64 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 53 insertions(+), 64 deletions(-) diff --git a/gpio/README.md b/gpio/README.md index 9663f71c0..c26cefaf4 100755 --- a/gpio/README.md +++ b/gpio/README.md @@ -1,59 +1,8 @@ # GPIO - -## Requirements - -RPi.GPIO Python module - -Install it with: -``` -sudo pip3 install RPi.GPIO --upgrade -``` - -## Supported Hardware - -Raspberry Pi all versions (tested on Raspberry Pi 1 revision 2) - ## Configuration -### plugin.yaml - -```yaml -GPIO: - class_name: Raspi_GPIO - class_path: plugins.gpio -# mode: BOARD -``` - -#### `mode` -Define the GPIO PIN Mode that you use to declare the pin numbers. If not set, default is BOARD - -Possible modes: BOARD or BCM. More information can be found here: -http://raspberrypi.stackexchange.com/questions/12966/what-is-the-difference-between-board-and-bcm-for-gpio-pin-numbering - - -### items.yaml - -#### gpio_in - -Define the pin number of your Raspberry Pi that should be read, i.e. where a sensor is attached. Beware that the number has to follow the rules of the "mode" you have defined in the plugin.yaml (Board or BCM). - -#### gpio_out - -Define the pin number of your Raspberry Pi that should be written, i.e. where a LED is attached. Beware that the number has to follow the rules of the "mode" you have defined in the plugin.yaml (Board or BCM). The Output-Pin will also automatically be read by the plugin as Input. - -#### Example - -```yaml -item1: - type: bool - visu_acl: ro - gpio_in: 10 -item2: - type: bool - visu_acl: rw - gpio_out: 13 -``` +Information can be found at the [Configuration Documentation](https://www.smarthomeng.de/user/plugins_doc/config/gpio.html) ## Changelog 1.0 diff --git a/gpio/plugin.yaml b/gpio/plugin.yaml index 34e5be7d2..031d56986 100755 --- a/gpio/plugin.yaml +++ b/gpio/plugin.yaml @@ -4,12 +4,29 @@ plugin: type: interface # plugin type (gateway, interface, protocol, system, web) description: de: 'GPIO Unterstützung für Rasberry Pi, **seit SmartHomeNG v1.3**' - en: '' + en: 'GPIO support for Raspberry Pi, **since SmarthomeNG v1.3**' + description_long: + de: 'GPIO Unterstützung für den Rasberry Pi.\n + Dieses Plugin unterstützt über das RPi.GPIO Modul das Einbinden von externen Sensoren und Aktoren, + die direkt am Raspberry Pi angeschlossen werden. Damit ist es beispielsweise möglich, + den Zustand von Reedkontakten einzulesen oder LEDs zu aktivieren und beispielsweise eine + `Posteinwurferkennung `_ zu basteln. + Leider sind die GPIOs für die Raspberry Pi <=3+ rein digital, sodass anaolge Signale z.B. + eines Distanzsensors nur über Umwege abgegriffen werden können. + ' + en: 'GPIO support for the Raspberry Pi.\n + This plugin supports the implementation of external sensors and actors directly connected to the + Raspberry Pi using the RPi.GPIO module. This makes it possible to get values of reed sensors or + activate LED lights like it is used for `smart mailboxes `_. + The GPIOs of the Raspberry Pi <=3+ are limited to digital signals. If you want to attach a distance + sensor or other hardware providing analog signals you have to use additional hardware. + ' maintainer: onkelandy tester: cmalo, ohinckel -# keywords: iot xyz -# documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page -# support: https://knx-user-forum.de/forum/supportforen/smarthome-py + requirements: + de: 'RPi.GPIO Python Modul' + en: 'RPi.GPIO python module' + keywords: iot gpio raspberrypi version: 1.4.1 # Plugin version sh_minversion: 1.4 # minimum shNG version to use this plugin @@ -29,8 +46,17 @@ parameters: - 'BOARD' - 'BCM' description: - de: 'BOARD oder BCM, abhängig davon, nach welcher Methode die Pins zugewiesen werden sollen.' - en: 'BOARD or BCM, depending on how to assign the pins.' + de: 'Zuweisungsmethode der Pinbelegung.' + en: 'Method of pin assignment' + description_long: + de: '**Zuweisungsmethode der Pinbelegung.**\n + Hier wird der GPIO PIN Modus deklariert, der die Nummerierung der Pins definiert. + `Mehr Infos über GPIO Header `_ + ' + en: '**Method of pin assignment**\n + Define the GPIO PIN Mode that you use to declare the pin numbers. + `More info on GPIO headers `_ + ' bouncetime: type: int @@ -39,17 +65,31 @@ parameters: description: de: 'Prellzeit in ms, um Änderungen innerhalb kurzer Zeit zu verhindern.' en: 'bouncetime in ms to avoid multiple events in a short time period.' + item_attributes: # Definition of item attributes defined by this plugin - gpio_in: type: int description: - de: 'Pin Nummer für den GPIO Eingang. Die Nummer hängt vom Modus in den Plugin-Paramtern ab!' - en: 'Pin number of the GPIO input. Depends on the mode you have set in the plugin parameters!' + de: 'Pin Nummer für den GPIO Eingang.' + en: 'Pin number of the GPIO input.' + description_long: + de: '**Pin Nummer für den GPIO Eingang.**\n + Angabe der Pin Nummer, an der beispielsweise ein Sensor o.ä. angeschlossen ist. Die Nummer hängt vom Modus in den Plugin-Paramtern ab! + ' + en: '**Pin number of the GPIO input.**\n + Define the pin number of your Raspberry Pi that should be read, i.e. where a sensor is attached. Beware that the number has to follow the rules of the "mode" you have defined in the plugin.yaml (Board or BCM). + ' + gpio_out: type: int description: - de: 'Pin Nummer für den GPIO Ausgang. Die Nummer hängt vom Modus in den Plugin-Paramtern ab! Der Ausgang wird zum Pluginstart automatisch aktualisiert, sollte also nicht im Item als gpio_in und gpio_out definiert werden.' - en: 'Pin number of the GPIO output. Depends on the mode you have set in the plugin parameters! Do not set gpio_in and gpio_out for the same item as the output item will get initialized at plugin start automatically.' - \ No newline at end of file + de: 'Pin Nummer für den GPIO Ausgang.' + en: 'Pin number of the GPIO output.' + description_long: + de: '**Pin Nummer für den GPIO Ausgang.**\n + Die Nummer hängt vom Modus in den Plugin-Paramtern ab! Der Ausgang wird zum Pluginstart automatisch aktualisiert, sollte also nicht im Item als gpio_in und gpio_out definiert werden. + ' + en: '**Pin number of the GPIO output.**\n + Define the pin number of your Raspberry Pi that should be written, i.e. where a LED is attached. Beware that the number has to follow the rules of the "mode" you have defined in the plugin.yaml (Board or BCM). The Output-Pin will also automatically be read by the plugin as Input. + ' From 845673cb7d0a13d614320f929d4a8794e3c90f1a Mon Sep 17 00:00:00 2001 From: henfri Date: Thu, 27 Dec 2018 18:10:32 +0100 Subject: [PATCH 502/705] Update __init__.py Fix of bug (logger.error wants one parameter only. See https://knx-user-forum.de/forum/supportforen/smarthome-py/1089334-neues-mqtt-plugin?p=1303134#post1303134 --- mqtt/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mqtt/__init__.py b/mqtt/__init__.py index bb60ad9b8..1249f79dd 100644 --- a/mqtt/__init__.py +++ b/mqtt/__init__.py @@ -421,7 +421,7 @@ def ConnectToBroker(self): try: self._client.connect(self.broker_ip, self.broker_port, 60) except ERROR as e: - self.logger.error(self.get_loginstance()+'Connection error:', e) + self.logger.error(self.get_loginstance()+'Connection error: {0}'.format(e)) return False return True From d67e6f3dc0faa555d09c91ff5bd0dbba29472e36 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sat, 29 Dec 2018 10:29:54 +0100 Subject: [PATCH 503/705] Database: Catch exception while rollback in dump In case the database server is not reachable the dump will fail and the rollback will also not work correctly. This will keep the plugin in a wrong state (e.g. locks are still locked and blocks further dumps or database interactions). See also https://github.com/smarthomeNG/smarthome/issues/302 --- database/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) mode change 100644 => 100755 database/__init__.py diff --git a/database/__init__.py b/database/__init__.py old mode 100644 new mode 100755 index d4ecaa0c4..7f18ec175 --- a/database/__init__.py +++ b/database/__init__.py @@ -407,7 +407,10 @@ def _dump(self, finalize=False, items=None): self._db.commit() except Exception as e: self.logger.warning("Database: problem updating {}: {}".format(item.id(), e)) - self._db.rollback() + try: + self._db.rollback() + except Exception as er: + self.logger.warning("Database: Error rolling back transaction: {}".format(er)) finally: if cur is not None: cur.close() From f91d74fef002c9877b68782ac6b277566242f44a Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Sat, 29 Dec 2018 12:52:23 +0100 Subject: [PATCH 504/705] change string to str --- stateengine/plugin.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/stateengine/plugin.yaml b/stateengine/plugin.yaml index 2a87c852c..773cdaa8a 100755 --- a/stateengine/plugin.yaml +++ b/stateengine/plugin.yaml @@ -179,7 +179,7 @@ parameters: item_attributes: # Definition of item attributes defined by this plugin type: - type: string + type: str valid_list: - 'bool' valid_list_description: @@ -190,7 +190,7 @@ item_attributes: en: 'Data type of the object item. Has to be "bool"' se_plugin: - type: string + type: str mandatory: True valid_list: - 'active' @@ -228,7 +228,7 @@ item_attributes: ' se_laststate_item_name: - type: string + type: str description: de: 'Id des Items, in dem der Name des aktuellen Zustands abgelegt wird' en: 'Id of the item that saves the name of the current state' @@ -246,7 +246,7 @@ item_attributes: ' se_laststate_item_id: - type: string + type: str description: de: 'Id des Items, in dem die ID des aktuellen Zustands abgelegt wird' en: 'Id of the item that saves the ID of the current state' @@ -309,7 +309,7 @@ item_attributes: ' se_item_suspend_end: - type: string + type: str description: de: 'Id des Items, in dem das Ende der Suspendzeit abgelegt werden soll' en: 'Id of the item that saves the suspend end time' From 512586c438fbe1c38f7f8cfab834ee8b46d05dd9 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sat, 29 Dec 2018 18:27:05 +0100 Subject: [PATCH 505/705] Darksky: added reference to https://darksky.net/dev/docs to README --- darksky/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/darksky/README.md b/darksky/README.md index 0b2ac6158..5145e97ad 100644 --- a/darksky/README.md +++ b/darksky/README.md @@ -37,7 +37,8 @@ weather_darksky: ### Example: items.yaml -Example configuration of an item-tree for the darksky plugin in yaml-format: +Example configuration of an item-tree for the darksky plugin in yaml-format. For the meaning of some of the matchstrings +please directly consult https://darksky.net/dev/docs: ```yaml From 9781a54e1c75ec13d8e4630c301d616279784baf Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 30 Dec 2018 10:32:44 +0100 Subject: [PATCH 506/705] Backend: fixed check vs all.txt to now check conf-all.txt --- backend/BackendSysteminfo.py | 4 ++-- backend/plugin.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/BackendSysteminfo.py b/backend/BackendSysteminfo.py index 22edfa9c7..2733904a0 100755 --- a/backend/BackendSysteminfo.py +++ b/backend/BackendSysteminfo.py @@ -443,9 +443,9 @@ def get_requirements_info(self, req_group='base'): if req_group == 'base': req_dict_base = parse_requirements(os.path.join(self._sh_dir, 'requirements', 'base.txt')) # req_dict_base = self.shpypi.parse_requirementsfile(os.path.join(self._sh_dir, 'requirements', 'base.txt')) - dummy = self.shpypi.parse_requirementsfile(os.path.join(self._sh_dir, 'requirements', 'all.txt')) + dummy = self.shpypi.parse_requirementsfile(os.path.join(self._sh_dir, 'requirements', 'conf-all.txt')) dummy = self.shpypi.test_base_requirements() - dummy = self.shpypi.test_requirements(os.path.join(self._sh_dir, 'requirements', 'all.txt')) + dummy = self.shpypi.test_requirements(os.path.join(self._sh_dir, 'requirements', 'conf-all.txt')) dummy = self.shpypi.get_packagelist() self.logger.warning("get_requirements_info: get_packagelist = {}".format(dummy)) diff --git a/backend/plugin.yaml b/backend/plugin.yaml index 7e1ce9961..71b45b5fa 100755 --- a/backend/plugin.yaml +++ b/backend/plugin.yaml @@ -51,7 +51,7 @@ plugin: documentation: http://smarthomeng.de/user/plugins/backend/user_doc.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/959964-support-thread-für-das-backend-plugin - version: 1.4.14 # Plugin version + version: 1.5.15 # Plugin version sh_minversion: 1.5b # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance From 5f86b2a1b4ffcb188d6c5695d76f3a94027a97de Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sun, 30 Dec 2018 10:33:44 +0100 Subject: [PATCH 507/705] Database: Change error handling by throwing the exception in failures Catching the exception and just ignoreing (by returning None) is bad since the outer code can not decide if it was an error or if there is no data. Exceptions are more precise and the outer code can decide what to do. Also update some logging statements, formatting, wording and removed some debug log. In case an error occurs in _dump() the dumped item will be restored in the buffer list to dump it in the next cycle (this will not lose the data). --- database/__init__.py | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/database/__init__.py b/database/__init__.py index 7f18ec175..70bee165a 100755 --- a/database/__init__.py +++ b/database/__init__.py @@ -406,11 +406,12 @@ def _dump(self, finalize=False, items=None): self._db.commit() except Exception as e: - self.logger.warning("Database: problem updating {}: {}".format(item.id(), e)) + self.logger.warning("Database: Problem dumping {}: {}".format(item.id(), e)) try: self._db.rollback() except Exception as er: - self.logger.warning("Database: Error rolling back transaction: {}".format(er)) + self._buffer_insert(item, tuples) + self.logger.warning("Database: Error rolling back: {}".format(er)) finally: if cur is not None: cur.close() @@ -616,7 +617,6 @@ def _execute(self, query, params, cur=None): self._query(self._db.execute, query, params, cur) def _query(self, func, query, params, cur=None): - self.logger.debug(query) if not self._initialize(): return None if cur is None: @@ -632,10 +632,12 @@ def _query(self, func, query, params, cur=None): try: tuples = func(self._prepare(query), params, cur=cur) except Exception as e: - self.logger.warning("Database: Running query {}: {}".format(query_readable, e)) - if cur is None: - self._db.release() - self.logger.debug("Fetch {}: {}".format(query_readable, tuples)) + self.logger.error("Database: Error for query {}: {}".format(query_readable, e)) + raise e + finally: + if cur is None: + self._db.release() + self.logger.debug("Database: Fetch {}: {}".format(query_readable, tuples)) return tuples def _initialize(self): @@ -647,7 +649,7 @@ def _initialize(self): {i: [self._prepare(query[0]), self._prepare(query[1])] for i, query in self._setup.items()}) self._initialized = True except Exception as e: - self.logger.error("Database: initialization failed: {}".format(e)) + self.logger.error("Database: Initialization failed: {}".format(e)) return False return True From 76341c66f0ca66b1520e5f11adabd3e0147a2b92 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sun, 30 Dec 2018 11:19:39 +0100 Subject: [PATCH 508/705] XMPP: Reconnect in case of error in connected handler According to the docs the exeception occured on get_roster() should be handled. This will happen when a timeout occurs (e.g. due to network problems). In such a case try to reconnect to the server to recover the connection. --- xmpp/__init__.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/xmpp/__init__.py b/xmpp/__init__.py index 0f2367ed1..808b4490e 100755 --- a/xmpp/__init__.py +++ b/xmpp/__init__.py @@ -84,10 +84,14 @@ def __call__(self, to, msgsend): pass def handleXMPPConnected(self, event): - self.xmpp.sendPresence(pstatus="Send me a message") - self.xmpp.get_roster() - for chat in self._join: - self.xmpp.plugin['xep_0045'].joinMUC(chat, self.xmpp.boundjid.bare, wait=True) + try: + self.xmpp.sendPresence(pstatus="Send me a message") + self.xmpp.get_roster() + for chat in self._join: + self.xmpp.plugin['xep_0045'].joinMUC(chat, self.xmpp.boundjid.bare, wait=True) + except Exception as e: + self.logger.error("XMPP: Reconnecting, because can not set/get presence/roster: {}".format(e)) + self.xmpp.reconnect() def handleIncomingMessage(self, msg): """ From ae32f3cdc9b3f81d5695e3464039aebe8d73b187 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Sun, 30 Dec 2018 14:30:38 +0100 Subject: [PATCH 509/705] XMPP: Fix recursive logging on plugin setup error --- xmpp/__init__.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/xmpp/__init__.py b/xmpp/__init__.py index 808b4490e..b5b380ab5 100755 --- a/xmpp/__init__.py +++ b/xmpp/__init__.py @@ -141,9 +141,7 @@ def emit(self, record): if self._plugin is None: if self._xmpp_plugin not in self._errors: self._errors.append(self._xmpp_plugin) - logging.getLogger(__name__).error('Can not get plugin \'{}\' used to log messages via XMPP - trying later!'.format(self._xmpp_plugin)) - else: - logging.getLogger(__name__).error('Can not get XMPP plugin \'{}\' - trying again later!'.format(self._xmpp_plugin)) + logging.getLogger(__name__).error('Can not get XMPP plugin \'{}\' used to log messages via XMPP - trying later!'.format(self._xmpp_plugin)) else: logging.getLogger(__name__).info('Configured XMPP logging using pluing {}'.format(self._xmpp_plugin)) From ac8a6702654b9923268d11bb78aeb9999baa8225 Mon Sep 17 00:00:00 2001 From: henfri Date: Sun, 30 Dec 2018 15:50:56 +0100 Subject: [PATCH 510/705] [darksky-plugin] update of readme with relative items I think it is better to use relative items here. This way, it is likely, that a user can just copy and paste this code, even if he uses a different item structure as root of the weather. --- darksky/README.md | 48 +++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/darksky/README.md b/darksky/README.md index 5145e97ad..a0112498a 100644 --- a/darksky/README.md +++ b/darksky/README.md @@ -190,65 +190,65 @@ darksky: day0: date: type: str - eval_trigger: darksky.daily.data - eval: datetime.datetime.fromtimestamp(sh.darksky.daily.data()[0]['time']).strftime('%a %d.%m.%Y') + eval_trigger: ...data + eval: datetime.datetime.fromtimestamp(sh....data()[0]['time']).strftime('%a %d.%m.%Y') icon: type: str - eval_trigger: darksky.daily.data - eval: sh.darksky.daily.data()[0]['icon'] + eval_trigger: ...data + eval: sh....data()[0]['icon'] icon_sv: type: str - eval_trigger: darksky.daily.day0.icon - eval: sh.darksky_weather.map_icon(sh.darksky.daily.day0.icon()) + eval_trigger: ...data.day0.icon + eval: sh.darksky_weather.map_icon(sh...day0.icon()) temperature_max: type: num - eval_trigger: darksky.daily.data - eval: sh.darksky.daily.data()[0]['temperatureMax'] + eval_trigger: ...data.data + eval: sh....data()[0]['temperatureMax'] day1: date: type: str - eval_trigger: darksky.daily.data - eval: datetime.datetime.fromtimestamp(sh.darksky.daily.data()[1]['time']).strftime('%a %d.%m.%Y') + eval_trigger: ...data.data + eval: datetime.datetime.fromtimestamp(sh....data()[1]['time']).strftime('%a %d.%m.%Y') icon: type: str - eval_trigger: darksky.daily.data - eval: sh.darksky.daily.data()[1]['icon'] + eval_trigger: ...data.data + eval: sh....data()[1]['icon'] icon_sv: type: str - eval_trigger: darksky.daily.day1.icon - eval: sh.darksky_weather.map_icon(sh.darksky.daily.day1.icon()) + eval_trigger: ...data.day1.icon + eval: sh.darksky_weather.map_icon(sh....data.day1.icon()) temperature_max: type: num - eval_trigger: darksky.daily.data - eval: sh.darksky.daily.data()[1]['temperatureMax'] + eval_trigger: ...data.data + eval: sh....data()[1]['temperatureMax'] day2: date: type: str - eval_trigger: darksky.daily.data - eval: datetime.datetime.fromtimestamp(sh.darksky.daily.data()[2]['time']).strftime('%a %d.%m.%Y') + eval_trigger: ...data.data + eval: datetime.datetime.fromtimestamp(sh....data()[2]['time']).strftime('%a %d.%m.%Y') icon: type: str - eval_trigger: darksky.daily.data - eval: sh.darksky.daily.data()[2]['icon'] + eval_trigger: ...data.data + eval: sh....data()[2]['icon'] icon_sv: type: str - eval_trigger: darksky.daily.day2.icon - eval: sh.darksky_weather.map_icon(sh.darksky.daily.day2.icon()) + eval_trigger: ...data.day2.icon + eval: sh.darksky_weather.map_icon(sh....data.day2.icon()) temperature_max: type: num - eval_trigger: darksky.daily.data - eval: sh.darksky.daily.data()[2]['temperatureMax'] + eval_trigger: ...data.data + eval: sh....data()[2]['temperatureMax'] alerts: From 972d4853902289dbc8a559b3e80ef7653110f01c Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 30 Dec 2018 16:27:24 +0100 Subject: [PATCH 511/705] Alexa4p3: fix for empty if from last PR --- alexa4p3/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/alexa4p3/__init__.py b/alexa4p3/__init__.py index 94ab6d213..e5fc71804 100644 --- a/alexa4p3/__init__.py +++ b/alexa4p3/__init__.py @@ -93,9 +93,10 @@ def parse_item(self, item): elif action_names and 'name' in item.conf: name = item.conf['name'] name_is_explicit = False - + if name == 'Doorcam': - + pass + # deduce device-id from name if name and not device_id: device_id = AlexaDevice.create_id_from_name(name) From 95696ea7999097bcdbdf00306f29f616bed0df9e Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 30 Dec 2018 16:28:18 +0100 Subject: [PATCH 512/705] Backend: fix for version upgrade --- backend/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/__init__.py b/backend/__init__.py index 9fd070d04..1a7f8c180 100755 --- a/backend/__init__.py +++ b/backend/__init__.py @@ -49,7 +49,7 @@ class BackendServer(SmartPlugin): the update functions for the items """ - PLUGIN_VERSION = '1.4.14' + PLUGIN_VERSION = '1.5.15' def __init__(self, sh, updates_allowed='True', developer_mode="no", pypi_timeout=5): From 32aa0a42d2166dddb87566d3d75f32c96d8cbdb3 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 30 Dec 2018 16:38:17 +0100 Subject: [PATCH 513/705] Darksky: fixed readme for day 0 and icons --- darksky/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/darksky/README.md b/darksky/README.md index a0112498a..b4497456d 100644 --- a/darksky/README.md +++ b/darksky/README.md @@ -178,8 +178,8 @@ darksky: icon_sv: type: str - eval_trigger: darksky.daily.icon - eval: sh.darksky_weather.map_icon(sh.darksky.daily.icon()) + eval_trigger: ..icon + eval: sh.darksky_weather.map_icon(sh...icon()) data: type: list @@ -200,12 +200,12 @@ darksky: icon_sv: type: str - eval_trigger: ...data.day0.icon - eval: sh.darksky_weather.map_icon(sh...day0.icon()) + eval_trigger: ..icon + eval: sh.darksky_weather.map_icon(sh...icon()) temperature_max: type: num - eval_trigger: ...data.data + eval_trigger: ...data eval: sh....data()[0]['temperatureMax'] day1: From 3ddfdfe3a0b3afa5eaf09dc1cba2f441b468201d Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 30 Dec 2018 16:41:25 +0100 Subject: [PATCH 514/705] Darksky: fix for relative notation for day1 and day2 --- darksky/README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/darksky/README.md b/darksky/README.md index b4497456d..10eaac6ad 100644 --- a/darksky/README.md +++ b/darksky/README.md @@ -211,43 +211,43 @@ darksky: day1: date: type: str - eval_trigger: ...data.data + eval_trigger: ...data eval: datetime.datetime.fromtimestamp(sh....data()[1]['time']).strftime('%a %d.%m.%Y') icon: type: str - eval_trigger: ...data.data + eval_trigger: ...data eval: sh....data()[1]['icon'] icon_sv: type: str - eval_trigger: ...data.day1.icon - eval: sh.darksky_weather.map_icon(sh....data.day1.icon()) + eval_trigger: ..icon + eval: sh.darksky_weather.map_icon(sh...icon()) temperature_max: type: num - eval_trigger: ...data.data + eval_trigger: ...data eval: sh....data()[1]['temperatureMax'] day2: date: type: str - eval_trigger: ...data.data + eval_trigger: ...data eval: datetime.datetime.fromtimestamp(sh....data()[2]['time']).strftime('%a %d.%m.%Y') icon: type: str - eval_trigger: ...data.data + eval_trigger: ...data eval: sh....data()[2]['icon'] icon_sv: type: str - eval_trigger: ...data.day2.icon - eval: sh.darksky_weather.map_icon(sh....data.day2.icon()) + eval_trigger: ..icon + eval: sh.darksky_weather.map_icon(sh...icon()) temperature_max: type: num - eval_trigger: ...data.data + eval_trigger: ...data eval: sh....data()[2]['temperatureMax'] alerts: From 78b33a4737240e883cbca18519be62c06c890af0 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 30 Dec 2018 16:50:09 +0100 Subject: [PATCH 515/705] Darksky: more relative icons --- darksky/README.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/darksky/README.md b/darksky/README.md index 10eaac6ad..526204a7f 100644 --- a/darksky/README.md +++ b/darksky/README.md @@ -75,8 +75,8 @@ darksky: # create item with icon representation for SmartVisu, won't show up in Plugin's Web Interface icon_sv: type: str - eval_trigger: darksky.currently.icon - eval: sh.weather_darksky.map_icon(sh.darksky.currently.icon()) + eval_trigger: ..icon + eval: sh.weather_darksky.map_icon(sh...icon()) nearestStormDistance: type: num @@ -155,6 +155,12 @@ darksky: icon: type: str ds_matchstring: minutely/icon + + # create item with icon representation for SmartVisu, won't show up in Plugin's Web Interface + icon_sv: + type: str + eval_trigger: ..icon + eval: sh.weather_darksky.map_icon(sh...icon()) hourly: @@ -165,6 +171,12 @@ darksky: icon: type: str ds_matchstring: hourly/icon + + # create item with icon representation for SmartVisu, won't show up in Plugin's Web Interface + icon_sv: + type: str + eval_trigger: ..icon + eval: sh.weather_darksky.map_icon(sh...icon()) daily: From bf2b516794a5fa79d9bb91e0670d3098d72bbd27 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 30 Dec 2018 16:52:09 +0100 Subject: [PATCH 516/705] Darksky: fixed reference to plugin name in README --- darksky/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/darksky/README.md b/darksky/README.md index 526204a7f..623c3bcaf 100644 --- a/darksky/README.md +++ b/darksky/README.md @@ -191,7 +191,7 @@ darksky: icon_sv: type: str eval_trigger: ..icon - eval: sh.darksky_weather.map_icon(sh...icon()) + eval: sh.weather_darksky.map_icon(sh...icon()) data: type: list @@ -213,7 +213,7 @@ darksky: icon_sv: type: str eval_trigger: ..icon - eval: sh.darksky_weather.map_icon(sh...icon()) + eval: sh.weather_darksky.map_icon(sh...icon()) temperature_max: type: num @@ -234,7 +234,7 @@ darksky: icon_sv: type: str eval_trigger: ..icon - eval: sh.darksky_weather.map_icon(sh...icon()) + eval: sh.weather_darksky.map_icon(sh...icon()) temperature_max: type: num @@ -255,7 +255,7 @@ darksky: icon_sv: type: str eval_trigger: ..icon - eval: sh.darksky_weather.map_icon(sh...icon()) + eval: sh.weather_darksky.map_icon(sh...icon()) temperature_max: type: num From 93be4c1e73fe2bd31c369c5a21dcb7671b639d95 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 30 Dec 2018 18:21:49 +0100 Subject: [PATCH 517/705] Backend: increased offset of codemirror for logics editor (offset did not fit after update of codemirror, other pages are working) --- backend/webif/static/js/logics_view_functions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/webif/static/js/logics_view_functions.js b/backend/webif/static/js/logics_view_functions.js index 3627efbb6..77a49d4e9 100755 --- a/backend/webif/static/js/logics_view_functions.js +++ b/backend/webif/static/js/logics_view_functions.js @@ -9,8 +9,8 @@ $('#rulers').click(function(e) { switchRulers(); }); -window.addEventListener("resize", function(){resizeCodeMirror(logicsCodeMirror, 15)}, false); -resizeCodeMirror(logicsCodeMirror, 15); +window.addEventListener("resize", function(){resizeCodeMirror(logicsCodeMirror, 90)}, false); +resizeCodeMirror(logicsCodeMirror, 90); var dict = []; var watch_items_dict = []; From efbbcd4a97463ec5fd6bdff7dcf69834e34d3ab9 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Sun, 30 Dec 2018 18:24:02 +0100 Subject: [PATCH 518/705] Backend: added 5px more offset, due to firefox --- backend/webif/static/js/logics_view_functions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/webif/static/js/logics_view_functions.js b/backend/webif/static/js/logics_view_functions.js index 77a49d4e9..d7ed58267 100755 --- a/backend/webif/static/js/logics_view_functions.js +++ b/backend/webif/static/js/logics_view_functions.js @@ -9,8 +9,8 @@ $('#rulers').click(function(e) { switchRulers(); }); -window.addEventListener("resize", function(){resizeCodeMirror(logicsCodeMirror, 90)}, false); -resizeCodeMirror(logicsCodeMirror, 90); +window.addEventListener("resize", function(){resizeCodeMirror(logicsCodeMirror, 95)}, false); +resizeCodeMirror(logicsCodeMirror, 95); var dict = []; var watch_items_dict = []; From eef33b1021a13673afb24df6ba1c41d1d0656961 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 31 Dec 2018 07:52:18 +0100 Subject: [PATCH 519/705] Alexa4p3: removed unneccassary if --- alexa4p3/__init__.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/alexa4p3/__init__.py b/alexa4p3/__init__.py index e5fc71804..4a873628f 100644 --- a/alexa4p3/__init__.py +++ b/alexa4p3/__init__.py @@ -94,9 +94,6 @@ def parse_item(self, item): name = item.conf['name'] name_is_explicit = False - if name == 'Doorcam': - pass - # deduce device-id from name if name and not device_id: device_id = AlexaDevice.create_id_from_name(name) From 18499798a34a2ee010524c48d8d9220a067eb9e1 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 31 Dec 2018 11:22:09 +0100 Subject: [PATCH 520/705] Database: accessing item path in webif via property now. upgraded version --- database/__init__.py | 2 +- database/plugin.yaml | 2 +- database/webif/templates/index.html | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/database/__init__.py b/database/__init__.py index 70bee165a..26553b85d 100755 --- a/database/__init__.py +++ b/database/__init__.py @@ -60,7 +60,7 @@ class Database(SmartPlugin): ALLOW_MULTIINSTANCE = True - PLUGIN_VERSION = '1.5.2' + PLUGIN_VERSION = '1.5.7' # SQL queries: {item} = item table name, {log} = log table name # time, item_id, val_str, val_num, val_bool, changed diff --git a/database/plugin.yaml b/database/plugin.yaml index 13995f3d0..77c97088e 100755 --- a/database/plugin.yaml +++ b/database/plugin.yaml @@ -11,7 +11,7 @@ plugin: keywords: database documentation: http://smarthomeng.de/user/plugins/database/user_doc.html - version: 1.5.2 # Plugin version + version: 1.5.7 # Plugin version sh_minversion: 1.5b # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance diff --git a/database/webif/templates/index.html b/database/webif/templates/index.html index cc497a414..1396f6169 100644 --- a/database/webif/templates/index.html +++ b/database/webif/templates/index.html @@ -51,13 +51,13 @@ {% for item in items %} {% if p.has_iattr(item.conf, 'database') %} - {{ item._path }} + {{ item.property.path }} {{ item() }} {{ p.id(item, create=False) }} - - + + {% endif %} From d34b407a7f2fb31ac74a8f4b1f0572bc53155e31 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 31 Dec 2018 11:26:57 +0100 Subject: [PATCH 521/705] AVM: accessing item properties via property in webif --- avm/webif/templates/index.html | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/avm/webif/templates/index.html b/avm/webif/templates/index.html index 6303a809b..8f1167e7a 100644 --- a/avm/webif/templates/index.html +++ b/avm/webif/templates/index.html @@ -82,12 +82,12 @@ {% set instance_key = "avm_data_type" %} {% endif %} - {{ item.id() }} - {{ item.type() }} + {{ item.property.path }} + {{ item.property.type }} {{ item.conf[instance_key] }} {{ item() }} - {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} - {{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }} + {{ item.property.last_update.strftime('%d.%m.%Y %H:%M:%S') }} + {{ item.property.last_change.strftime('%d.%m.%Y %H:%M:%S') }} {% endfor %} @@ -147,12 +147,12 @@ {% set instance_key = "avm_data_type" %} {% endif %} - {{ item.id() }} - {{ item.type() }} + {{ item.property.path }} + {{ item.property.type }} {{ item.conf[instance_key] }} {{ item() }} - {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }} - {{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }} + {{ item.property.last_update.strftime('%d.%m.%Y %H:%M:%S') }} + {{ item.property.last_change.strftime('%d.%m.%Y %H:%M:%S') }} {% endfor %} {% for item in p._monitoring_service.get_trigger_items() %} From 359d570a05fd2c2e02c384436bb818328975e474 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 31 Dec 2018 11:35:13 +0100 Subject: [PATCH 522/705] Webservices: access via property, layout adjustments --- webservices/webif/templates/index.html | 30 +++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/webservices/webif/templates/index.html b/webservices/webif/templates/index.html index d97a23af5..4145bb8e8 100755 --- a/webservices/webif/templates/index.html +++ b/webservices/webif/templates/index.html @@ -30,13 +30,13 @@

      JbC(S z5eJ#lTM>Jr7*Vh0sQfwPjEil3TmLEl##9-SA}Kv69b}2I9V|PjUv)|{#Lkzcc0^)5 z627e@XmphEkeBa`*0T3R`zZ2WRGwzjZ#Pfqs0+{*Sg*tWP&ON0A`Gu7jKW4>WUfy| zO?|(bw_5m+d%jK1GGD4TjojuI-aMwzjV6-dN-D>?{To${V$_o4bzVBK=!TQ$)Sy5HNr5ZK*h3uT{k|Z2YWQbv_p@{kW z$QS1Cc-N7OtQ_S%2#-ge-Jjl8wJ*g5LeEVh@gWQ`EsmPwM@w(UgGvtGV8|FbYXV~r z?&E|gLdc(~ucpsMz3CT}rMq(}wa$RcDypF0+%zcBuc6EI z`XbCvIL1*q8#pqHt{kCjE?LGqzSBRoeGY2xFNsDsRDN(h2!Cdtoc@B!?D73F|68|m z+8tE|YZcYh^hWR+PvOWiT0{CdFmrnr6B`wTj(g@GuJ!NX?7zjYE4`YfN7cJsjpBhr z3wa8Fh*JE5-mb*wEwO0?8}`<5Kc!jHHorPN$rI~Ij`<@3eslNGRlHA64{2JVBG@8pd;|Ad)R^eeqN zEFm_Ur2bL9p?|BI#eAs$wV0HRq;yN&a!jzq^)!x0S6X0f$uGF}u=%~ApKSP@@Ie0E zgd|1qXrWBDmLc4&qw8hQz0vs?6(^^JpryRB#hvPTq{mso8#g3)zu3NqtkfI7$u5Pl z1uo4Y4T)A#38L8ptKK-X1>7j>7mQh{Mo7P2O%1lhG~v+oiI?rb{&)NE2As?58DJIC zXnC?j;JQS;U;2r84KgL^=ZcJzZMw%@tsX`8#@@Ay$8=20DQ!A_(wjpy$cI_A>p17T z(*D})Hg}p02W@vo(?`ap-+7n1e2P@7+6*Anc`L&&d4Xn`F z*JBY)NuT%mwtCkOqsmX~J&WbhR#CJxhsmnlR}B+2k3jp0`}3l|_U4P(q6;cBjME)* zMM~)+`xgfCo`cab2_4F8laBrszX(gjtoXp=R41(?FZ}nQR~YdT-^3;;2|q=co*NP zmKO#T=iDbn_wBbtve{B1t~o!Do8r9RP2)5D>e8SVpUmgig_Tbch@XE;gFd0gNz*eV zKqxX95-QF~h(;-!9q3?0*jC}hjj+Yv(;s37|=?cvU025Ez)Qtvc-r1Nit!t z{@plLry*BWC>g=ko^8C@IuK;)VhuDrL8ce#gX(y?N5E>w${XZrC9Pd8RPjnodIe>I zK;=7Y;Xu^pvD@mFsU!O$tXGMwuNYu{;z_!}LHNNyZV#<=98;)5TbDfeCxXJMGzr`Q z36eG?zoeKxd&UYhu8-#AbD{so#_&H-VM}%Jbn^81QPW4I@r|-X&Q|u+8{ayYvRhV! zqb%P`@f$s*G}eEfKD9G|l`7%Lzwc>FYX3ndgd>U1!-KN`_J!bv5yL*XT+GcLKYvC2 z)UONwI_WZQ7wvPtuj_-CIr$NU|y`DgU@b`9K#6rpovxO#As;W0QhkCZ{I- zOIz9SSawDe?IN^Rh40}9@ZIU#(I&chPfuR5Gq`bYEvLsrqOxFI>1laaBP$~|c2qzw zZ5Hk=iu*GGRazI3`h_nj$I>x-!Y>ym7%#o_b#Hle9T}Lo>{02HcqYY^bKjflxzfU} z2D!TlfuHja_h9${E|Xc8{*!*8ht}Nw1I(!d1>IOp$s-F>HC0JS0ZsNQfz&{A-7uHvUs_&UqUhyrm^zhKEBr0b~ za2O_APh^3TQipFk+=Cd11X<~G+d#vGxnh>bTj3O$Grd+8xSDSQay68fC1hGaaTJ9L zM-l8umK$}OJcX;q_u_o1M@};E$zGHJc-XJJqSQGx@NUbk=^{6{6*n{?+p=KszQ+v0 z9Qp_r2dyCWEhn}p5PLrCwCjGiJ7eyQX=-%#bfl0+)@m{8qcFLs5CWu~5$mVRt}26Q zk!3v}`ee2@O}xD{VQQY>w11)?a&%Uj@S)NL%&j~)7d-jt+(@v$9>g`j>I>8&<*aLZ zL%ipVqNkQyNQ7Y4x~FGYKW}DM)I~51D@n%DR^uHzhW(!iQ|}LnK5@w_ zAaIl7su;HBs>sWIJGfC)k`Vzi1DEPm2_6wI-%>V512VlZ9_)p+Q!nQYEg=(nAH1}RV8q_PSW4(5B5?@i^T(8-@B#mP|^7ejJLe_3_55z6fSd=nj!;12^%?!3j1 z6o3KUdhVkmBvRQ0z1(~tqf&hmA%@hB9fS=W0u*X1{$fQ{KB;j3?&5dAB*qUIO9Nyf zt@t{_Mhtq`kA`{eqo2*>&sP#C)u?H2&xZkWQWo(1TTTNB$7H_Z|NGBs<9}9c;dC-^C>+f$>(J{LeuY2?IuQ#RAbDljq0qejd58yo4aKk1!1E1cO)h+;F zy`$-J)5i3Ot?84r%CTCO4gmmdT z!HqAbZYZ`>zQEMt$B>kI>KmL9_MjU$*;6=&-!*b&Xt(VCO0<3x@P$v$#(KR%Z6MlA z&F$bWAk@u!^+N&o-qNj8-HCdqxj<+2Pn?X$2hshXgz^IjMC!xxa51_TkDbv`_KfcO z$Cp8EZ|Z}s-Mx-3Rx1G3yL;QMbC*!EE9V9=8@iVw>7(qBcd8$<@@+7`Uctwc^Yiz{ zg0>e|1t^+@v37OxKMU$~y(H%u7p}IN?&7WjI}*wd)D!4js=_6vW4DwJGLt)JjumgE zx3??N`#%kcz~YLwEUD49_~>1Lkhg{M;k>mJVw(RA_Uq9i0S=n$Tu>V{R#ajqavjC* zwsR$Jx9n}nClG>Rg=|e*IcYaDPV5$Z`QEi>bwO3YMY!*$SM0<*!|?g1X~_k*o@aJv zf=11i!7?iy3IrZT(B*~6KrZG!E1SJocmbevq`-gBIL)0Eo(OGU_8E1WYsq2D%7(~@ z91kdnY;cZ~V0K-G==$j*JjaiI1=%ep9%Q9*EBC|HWUaZsls?hcAHm&TAPzBp=0Uwy zQ`*wFp+Ps=p07I)WbGO0w>;EQT7m6Iv2)K@+1ywsi5o1PsX*)(Ni1{ZEAPtj1ShKF zib%n-V(WLv0cPAKI{gf4>udRnVg3vUUR*Ez8YcMA1Fls5K(kCjg1~8~9m8_G+{(zQS$j$?wg4>b8?*@uGpt_$AF-uSa~YP1}D z^`k_)EcWMPhAm2+<%HndRzL?sY{DR7{F+kd4&VCVEBlVpW#sbx5#C10Cwr>!8Ch@D zuB>Oxq8#0Q9`xV!iZvQ;a`4Xy=_DZMx&blhIu*0ML|mLOH9dOC)eiy37VUC86=PR- zQ!Z9@NM}&0>YYz!Vhu)p9VW$l_8XKRPnlt4hzcEW{+dp|FIj1nhN=1jTW#WZLjnqr z$54Zc-J{n>yq1rayFS5Skxy6tIWrGufMW6bPPDTl?)xw_cWx3j@uR1A?qV>(I$U)on!#K5#lpEF7&zMhXfCr8bxUP}g za@9}t&$q=#(&I-(N3cc#-umIDBCGWpQj;GuvB7Y#(mF$JD7D)86LH$3iZ?x{e2wq%z3n!8%siP6>x6PQfmQ0AFD8uhLBR-hEtvrcm z=zsH%?P=(DSnno|gzoPKu6SjgChxuGua)sKut>wc?vM+bmEz0Mo*$~cPv>9YwdFK? zLEUd9sDScDDJD^HEZG0C#-gLglckndYZdUEk`hUvl3@!URo2>ff*#U_Hs&whxIt;5 zApKe!{I{$P-oV?D;dFcJiLx}BG`cKfHcrdEID3)hRW5 zmJ4Zk&IV94e-V6Wx-RW5g^B(|O4PD>W-@*)Z)(8Y8URYn=c37DsbO;O$gG=})hX4A zdi1*FHVz;X1FfG>a}WbzoQlU%IT%m9JqOz_@uIFRn`6@S`7*=m;yOR#!XXou$!x7O*oDKt{*(qVnLG(EjWAlsmE+pB&T&evi5Gnmy-QBFfPv93 zOb+h9QIprIOn=Z`qX{ZEd`Wx8MJ-AyZ`~IU`Qe%_=_P8S^J8CR#qEcYLM^T(t$E!W z)l#S==A10+`YD5!vIvNXua4co2Q8s@d@lp;4_!j6AoZ#OI} zh}}Rqx$$vuMNRuCP7A=`xHOPiMiaF9Z5?xGm8PaAW3zMI;Iu1%@2Kl76|lnk>7i0t z1^6Pp_8qJPCPzRKFqgZ5sR|Ggn*C5adNWuArwUWf8zS8fsUr~%G>&Ztu{$tcvtk5? zH*8=&&px@@J@;)&YfniCX5y`v!e%dL7#-{0?>3zL#jDBZiHDZ^_8?ZESE%MB4Qv%6^nSL6V7j0}q~~cb@sVdst*-Y-_`lpp?L5fVtVX&CihU|SzzK_X)ClB6 zyHRM+XNb3%BI6u=BT>#$TvM_BsrE5Mzwi!d?1&e=RdsB1ylWU4V1)tS66xOgQ`jsC z)H<8#F`hO|{{q*hdR?UocGO1c|4_+Q?b9wDQxU%7IYGx0W^?87>hS$5;hQ;e4Hwsk zLZRMZD{X6ktyG^PuQzQ0)1;4s{WK&Wuveoi=0RH0*NHHc79I{Qy8oY}MWG5=G~iB3 zz=IF7*^qp(ja`XGBWeN)>5-zIFtTP$#i1=h)&vffK1QjE?%M7WLV9baFXW9H4M93G zB#eB#rDNMO8{p;=g4{;*yExQ1=-whfCD*L$3GE0X6tdPEN~Kf#D|o0Ov*vuiko{br zz_JZ|mBYTi*zv{&F1*41VoH9iGsuo$S8!c;*!XjNPG2tonSGxn(~$(Cw&iiwzd|xliXJK zT2JEx$t9~etzBxF4F5wX~9Z;;Fe5cXKMh^-Z7|-)y-jVGtrHG~{Ra&Nx))J?-LUN_~?CD2LLc zG(cf=;D`}m4cF{C!@P*ICkF*rIHFR9+X|>4ejC1ANk0`$GD{Y#RB`N34p76L{Zt*n zuRAU5XeM=`&;iiTQ&}*)m+g3tDSsn+8l~kVL6|GLuHAR#e}PPYAk0lDm`5=e=F`uG zVTFfIT5MqiGz>lY|y`7zLE{DRNP?DJ;~u7_A5;9pq(5xD@C(S*vppH zf*j)eYw`rMiW1J`{5^Aca5-^~N5{4i8|OxO7#CATg@rc~jz1 zzDF5Jd?(>Tlv;q63;#T3al4QP;jmY&Nb>&efn*%Dv34EfG9hHRu{v5{+*G$DD0BKu zp$xxJU6$g0NW@>~BOOxyB-rvlmjJ9)v@w%0m=cbH(-C=l=_tjmrJG9l^-8CfCp{XF zYR<*K@gIr>Ol&u;F?loAtH$T6ZE4N2b4Rbhwa!G8xtEzHkdy?lob^RwLqzg5lfPy| zo{lKP4xh5kmhms*S8^VApL)M`Jbn{69#}vwH&fD2dDoh=GJd39G`>kZkEOBC%4rO4 zrsN&D_=A&<#9Ijg;^#X*spQx#)!Tpq0ybzFd;ioZ%6%u9o2=B=;H|Kbde~@lrTCo3 zvkG&P-pzM$Jm(U|!9`Mbtvc9UpD)EsZlWH9fnZigrXw!%5V00DB+c&=H{TbOj(SD;F+}(O7))}a^>Ew3(Og<{UhHiXXz^W4Xz^*~(oQ)WoL>vm72s(peKRj-$ljrGr^w??q?*Y;N3y~E?pff4z6 zvf~FtgWpQv-_s=&%(=zwef0-p%>-%lK0edY>^IP3uiSqe{UKAWWFwSx#_jbU*jr)Q z8<}c_ROMJH$Q&xfo2@Lkk^jJMNuqf6t(s|Z3);JHBPL5_KqiNF(^8{jsvj{DFUWPk z0zp#r(*5!)C)%sMt7hfXE-A9Y@MJx2UrqASMu9ST}l^!8Tber47n9Viv;i6nx*L$G> zU&D^$YKJB#o#KbN%Bt7OS(c(EpoN_3qFVSBYjP2RG7&1vzf$}59nK zIcYEaLLbm7Z7NM4B`UXxuoS={_jztLb2v_zh~*uJ)Q8q{Kbgjb_UW0acq*{W)Dz>aPW&p2_gZMln|84$+KDRSzeam}js`HUHP20cXBPT4OoyDrdhvL~KK#g3c>@1P z*uLX*+hB(Ms?CHQ$bAgX1XqD&t&job6x7ZY%en5*7VAs8W4>JXVG+tRNXx2sVR_!8l z!vxEMW5Z6PaU6sWJA)r?h~yb+Il5PXMrtRH@>(*;fd0>o0GP2!d=mkKf_-4y$nC(= z6vVONh|oLQ0krkY{TUH8OW7HmB;*Y1WqXGnwMD!C9+WG~j3r})JucVY{sH-T={?(W z`*be@9VXg_5&uCL!fGIDqTT+y=|T3?3(@_J#=6ATRq*Scw8_m3w|CcPUtRT`f|8TA zWNvlnl04eBE!SC}4((`uC|hQu(xO{Ky*~%I^qS?;b`oFTZKi^Q*C(1hd{xPJ+$<~9 z)>Ex(_cG0zT%kEoy_VPhUHE&XLQaX{MmX#bpP?jFQeDo?@Y?dE!}RbIgI@ly%JX@J zx+V?RPw6~LqAYDb3deA^TY9I3Ne3ITT2R-$)>sEEMBT2j4!&1k+^{F}WkumR&z6Ck zC!^>|qa&ReRCw57$*mVNxIsfl^BYLUA$J4a=VriotFU1vk39pdhzR6MO;;uenF!qd^u__k;uUtTARM!dt zKQwE?$4TW0A49i1+l{s?p#5V;1DQE-WLCKSJ`A=R-%IpYLOhM6_q3ZVhGXKxa!K(X zHgeyd)SQA5R17kkl=(FApT+Yk=8!8c=PWw##)l>H% zW#Wz(kdBTjlM7;x$LzAXI-Q7FSBNQ04Ak6#6J0R@cXZAXDVYDQXc-kWFBF(#MBh>| z*KwvgPRX)y9!#GUXWYXnz{Q+_lQJ#)!gUN^`5W%=?qn=Z~P(u*Akq+ zrTjv^;s(za8GiTo)xO?W?%-o(Jm8^a6Du{zj`QQ3M%0Ln8l;+=>ppY{I?CZ_Z3189Y*X_huormk zB=ieC#YQF0$1Y3Ysa5tesK|gC0pvldF$^x^cxgs3u2+YwZ;xP%ow#N9@021Aacx%) z}=YDWU_=!&D zlK}q{+2xOKaQdUd$u7UOnV%+q`x;G5)SoQmPr1|EI(MO7;j#2-{=Gt2i8`KM!NwdT zqi>0Pb}XLIl>In&UD{-5Uc!xJnoE!EHVvu(Pj<-XD%yG~LL6rZgSaXQO?`{VU_b4lHUXfQ1wZZZ0Q8-GGGMRaASw0n4I7V3o+4a)@hfGM}L3&AD{d4AcW@O!_uak+D4C_s%x#Re^I%#PBRdK?YM#0 zvig5v4buQB;aIBjP4yGqQ@b-@ortiwqRY3iENG zd^20BMI#l|ns5{Uz?Qo~Uh!}Dnf&-+DchWv4B5Z*lzp|)q z-0Y<0|Cg4LgQF zW$@>**$v#H{-6|7!?Dz|WxYArirO3m^YCX`1!AOE0vJ$Bam#I}#mjxMt;`P8^>&tH z_i~w0L;W-I#DC}R{?)@*A>Xp!L`Z31BnTa(&@N>E!H51UCp8B@`c`QJ)}@^b|4YT+ z|IRtz#oh=P7(QCF`%k>_|G)Evm?+-pPBSrdwW9eSkMN5K-jnH zbN=7L`VUyLe*mff>ec_Zu>SpC;6Jw!{}(LQf`r;ubv4>k^*B9#Jv$fMQWre8o4=0L z)w;Y?P+(~gtt;aqsCr`#c&LA6rMh`-Z$iA7m6|l_r8KAtd+d9UCEg^Z377>w-Mxw4 zTm$3*R6zLe=P&iTFF~q;&eq2dAEEL-WbWBOIuesowLYJj>k^w%^;w?V^lsCqxs&kP zoa3IOdzSf?B?o(gFp59q5LI}kY;!j?1C1muO>RlbI}94U=+m8ffM76E@nQHLC%$|) zMVa)U*@zHUoE7;bWj7Nsmkc?G>mQ#93(d_E<9Q!fP+zJ&r)Fz)vX^IpVWWB?!js{z zl;t@%OUipY^xisOjhm}|l?TTd96%Y~th7bD%YjkxS8N?qQefqr>?p=2t3cpOAEvqfqRE=7Lzs&Odkd9oectlEWm?_mxHmbv4a}Cj zS&r)73!FJFi8s5qYmB$B0MNglZQ=@n?y2I{!E?N9i_YxJAv_0DX=M$@br)O+hSNu7 z{Ne}(Pdr8+=9}xj%w*--%wK4zKz=k-0>=$^g`qw>*%>D1Z%rWDIkLV zLChgMH|K_j8%ZRykuiR;K3{&gKzm~mqt6k}@GT&(vRPtME&(uM7Q%WM3CGmNKs~?&ExBFX`zMnZwbJ*P_GrwZ|92Gp3c-LOP z`yxWk27qxw`F-~)Xdrvimla`npm9{t7;I5$EBTPCRO0TDd^NTzcs|Ks-0&*(lq6}I zg0==*g|CiMO@iRVno-%aV!ymx{V{BvRziZ9HqB=q92q#)Vl&}_1@i3hwc2W)=U zK<1sx9H@B_S9ezqHYK6@v~~Hbes#}OoJBvyE%?$HG$xI@Fr^_$@WKP&66_Pr|P9KHP( zh&|FD5eCQ2<3M8lRyz<9X(F8E%5-EWdd%LsT#X&OG44nI_9}3L1`qw=r9dF{oHtIi`FD36x>DJrdcrzuZ&RG;`b9ZqT zUcW*$J@kuMSE+}tv>qOBd-o{|K}+Nx%oX;mz0+h~das|>c!z!4PghzbSB?QhS}3gT zo^>X{jx!AUTZ&A*bWI&b8@zRcylpNS^``Fcwu>n3Nous!o-S8iP=*Vf-dY?7)HiTd zVyp5}6xMkkR<4sH7PfnfOgozwT*g`99HsH0^GLAsCuufN6IX`=ci6a7l!t+xn8bqCRHob9oIl?FTV zt}M|>AOpN-mYoLM*bX+@iAAml*s21_59%K!nEhpZ9dadaZbma*8r=MJ2AsOFsW)e_ z1Ynw)XQ7MpQqpUlaw3`2F=(t}Nfdv|5$r0H8mKoDF+T49oGY;{=O+p5XYeAI9PwP- z=BOJ@^hCz^&*blr-*l zo{scUi>n33$L|6r_%24=jeuwyjE^~IADEr(TdsSkBg$raMO_F0_}~TuJdjS z(}L#e%9}Yihp_z$n>i)bm9@`l=8W6*^8zqQWaCHbDG!jyjzh@0(T|X156L-*8LR1) zhbcwy#f+P~*1`G%&%pI`6E{o|x1FocJo=+w>J%o3H7cvDUzQ$jwEr3(E|CpXhh}bv+WWrE1&fW`oaj8}lWX%1#+kWDpWPSjL5Jgm=*2d5pyDj0p zbPhvc$BE(3n|4}MljT<+caTAOa4oAtT4wz>sSeRa?xj98MZ-(Gy^cHRsn}WK1QT$W z!;CeWQs~%vbW3?*HNhjo16YLYV=cHcN0(yHG_A@$1lPH#Yyyw{rK3*7Cm6Zr8Cvb- z19P-QNtCippNDb5ICy{zJY^-XCaBQ|#7ZbjxdF%&yuqjKDgOXU&>DT=X)sjUpFhA* z5llYs-vABZGa2iMhABprWW5s!YUVU66hEBTlj;lW-iuR2RgHuWHPt;Q2=?SRD__5| z+xGiTwTAg@QAh%0zZCkin2DKmJ+d`Kg}nu^ftGjGMdm<*3XE!|!aX^br=;6KJ67a# zrKkQTmxIKr z_AId7B-SGCT25eOxqD-uf9~L53wtUqPNC?v4dh<5G<=Wbb|F@O$3Y+}NqJF|za+-g zW+(UAcT`aLy6UkHQ5g1g=$GK z8#hsL`h5CmyAkUvV_y53aKqI1uz^@fZ}d}Sle!%==5?mg72jNH76JZdl@D)$`&Qib znqF9qeYNZ$Szn8ky5zu>@Gqysx~?Zr#7UfMGd?fwU(13=j@yDXMn4-vvV`F`b)AL~ zVy|TT)B{__s}}t4!aB$#gOr<>yt|&4uLS+-zw&K5GLW5aLpKSTZ){a)^c~Ay%GP$Z32`Y%u)lfV=Q%lfnyPkksUH;6 zjJ*6zb6p&CX*S4n4q&D`jA@~5AM=cJBc%On4X9lSyvy-QmX_+LTFzz(Qx$L6PudyB zfhTvzPt{-F4E$Soec$(sOUV`FEtOyOm*}0lrcIJuS_eG-%kPV^p5g*b1*)}rZ57mC zt6%W5>7_b_e;^e>N_Sv7YfMHWu=WGGUfP4e%=qm%9je9amI4#i>#=xRwx>TzM25SW zhu@R-k{Dq?+q>Y-oD#mHGm9fd&+fDo1pk0FTe8xQO9NrXb`m@L%DB9VsKK=G=EiWa z000rZ1!v1@pxsNU;W_(-SAOj6@S3~bHBbKz7ox!|d1x}1bJ?vcMKx*s3PZK+UuyVC z@n#8qX~0Vk=PRqKTu$1@FGfM~P2>nC*PX9JHeH5aD3zoxOxvF>g_BNR0NnXbEd{=# zJ=NKJ98iV4UDs}gDdB?yu`&5ub;sxicyiNdaRYBtfsQH`OCVVE2l>_PX0qRJ2QJqUhPa$v$9rB&r&LbO70jr$Mg@`${cv> z5IP6~+n!rG^XNk)eK$jCfyUII%luEFlNKBiqU$HuV*r9>oSKycpRposl$Yg3;= zhW~jYtoTEhf|pD_k4n)`A9)E}h4sgr)+0X59cf21dk@pMea|&(h<@GLH-_yWI7RpR z-u7+JJuZffw-(FX;UQEK%{4M@IcYZLQu!GNYno9ta$oR)lSlLEN7QpxJB4LDp;hcm za|GawblmceTwXFe3Ffdztg7`^>G0rs)^PuDrSE>W*ERz!XB*iCmHXw-LkJ_E0I$*5 z_0^$UrOL%9wESaV$FlKqA+mhtsS%IbFih5ah~eB;0pdFvEOep-okYcwBHFq;x}7n% zskeEi0|c3rUc0~dv7$yWyq={gQWDCvxoD6`t;YVWsp}QGw&-#G;ji%iphk5O=b{a+ zU5X2Q1}-8Bj0Z2|)Dh-a-32&96mlEE5ER9VX+AJ14W13a@J|B+9%0}hyiGrEu5M~~ z;*80I3P6(3iBUogYk+!3S?f-qQPoU+DE!T!bwhVEqB^KCfAdEW6Xu`nnicRaM=Dtw z1Ob%G&^Ubv+qVC9s|WClKbz1y{hGt+M&tV$E<*f?qVqgkW`vqvW?;zCeS_k1fU_*) zr*6Q8m~AXgWUo$gS#&{aaDYOLy&`q+b5!2O3CDZQvzkgacW|#2{GNq4z1tHj{iGyx zkt<~IvG)pzuV^qLQ;_P3Bu7SgXM}g#So6yyqw9BuEJ2#uf=@@pB-FZm#Bje$* z=a$Wk?PiJJUk~ejb~ELLmv@qGJDW#sPN8`EHxQ&8uT9EGN=iJ{Vy2CAiP;T*rj`Aw z^0hRK>3?25cF!-ITi)6KbxCc)iS)GfMa-v%IZR?(bfXzbT5)>Rtb3)ROYw6@t_IOR zypzhx+-w8e9CNLG{T?8?)A`CG4+h(_S6-LBH;Z7ErR1#_=Vk34ZC2bjBp5!s-;!1g z-O$c7j^kR^1ObeQ>kP^WbH(|0eTeGYQ^T7R2qUjssFF{yWBmc4)* znnbK;cRBqvx`WqnTVF8cL1R3bffzRF;86zgvEk zy=UDe<{N-c5M@-6#10{;&&Mw0fb=I52?&6># zts@En3eKClaqfeBuC9i*B4Hhq4XXXf~hhWIQ ziaU+_BEU5b45d+_Jy`hjMf7IRg`5iyLCXN{_o!Oq9^ijfDtc61Erwu-3DV=;uEvs{ zlua^yKT>5hFTb4RE3N9%<&d{~U&)T34;h^zUZ_l_Cq>~`M_s~KO zRY6)pk={YN5Q-2&fDm$D_xGJ|eCLjR&N%1(zQ1%Z2I0;7JnLD{nsd#$#Qa`SkXBqp zG@t!pK>CGH4l)n4dVWxzID(Z=E4{n6x;|9Vr_*yurN^tY^t0XGV@cBb>lC9J>a|(H z%-x=uwS~$_n*fKGG?F#ZyfMYO`>y_E_w9vpTIRK0+nM&sm%wLG@P$-@ zf5G*xvl4Ab3Qg_7$SuM#vJ*@X8g^=#U;Hj8Zf*mSsZe3sgB-dT2T za4ziAsHA%2Ew4y!Ed)7vnnEz|J1CCRUMadWdR&sK>7vw}e#S9V!Q7k( zSa8jjB%lHWM>vyvP_n-i`0^rCwAj0pLFxpmR?p>+c_XD{U}4hAJ7a<$7RFInZ&m7k zet4&^qQnSi=By}yWSv~lqI}kMPji!5B%rp-sm)W)YxE=^CINBN;Un$a7ziHBc{XY_ zW&MonY)?tph8QJ=wKsC5_~e<;+muR4#G`yO6Do>S6?@#AVnSLur3g_X22Clv>vMz> zXCp-CmUn=ya$)kVfLx@j#0(n;Gemz^ZPi-EWWP=RNNs zvr>+>pN#~`(WjF>>!ng)G9zSJ!$Bf{XE_n&8^6UEhrN^$;!d1TnilT19zIZykBiAn z9KrQkD9oKJ!e}c{(s4x(In+GHBI2vR$V7d-)4@O$D^)14g>45~zCz0N_>~X4TdYLa z`^p88=X)F0U9^@bjWgCi>uNLwCaYFG-=seoX`sH8UZv7ICw3f6L= zex&#jVe=Chgn;%@l{1Oj`jiBzU5+*A3PRd67Ge|2y3ZaCd%nu_&oyE`?pmWexu+k-=-~d_Ga3DlqN+9a!ww-8ad6!O>_^(UN5LB!vsb+#*M!c3k zGb%8}iHW+IxUXN%d_d@PE9=RN=#S8~(d;2mTeT$1$a%ZY<(*7UZ&ik5W*N;rBlqL_ zgzY~rWfB&y{AFd*Ug3qo?;w2?*ESTOS-kjpSQ@1DA;FZpm^opgE_eMC-Cl= zU&7lFF$M9Rhx)tYMj#_B#h+U#k4UP;UU;93X3*K%JN=#WOg7Kc<|3su3T;e8*nW#l zk5@(-r0MaVQ{XdOwB|k^tH&X^5e#PI)9PI3^X&;OyjylmzXls$n}65O8hdm>WIwR= zDE!LH=tL)#yY{*5Rp&qrRNqFHVlz+^z20{!mx1AhL++RNI5~`%^>jaYnklDZHJA_^ zg^P{DA;9aG;E-1av4~l>HG?|jZ465oP6Md7W^Z9wUO%EulVN!M?j7w@dJ8Lk{B=dB(|>V-MtnIJfNQY7 z(ZKO7m#ypVrkfT|g_UR^6ZU25N;`Iuh>nV@{LnQ3lpFirq3wIb5W%I;S`mKZyriKM z-#}7tVnLWttm;nK*071@=cDB)SZ3o+%j?!l5f_qYNxs?{TNJpJ zCYfLZk`$*z=tjQqPA$#|?HOQcs7n;ZR_Pq3Z3Rzh-K$XNaoB+^c?Ac!y*~LFNos7K zEAWXRzO;%U>K~`v&=oNSJ89cWa-;Nhw3*KGMicmiM>@2CCin8K&E@pH%?E`?%k0*5 zKG1eH$1i%*Y-9$J^b=cUF?XVTDsPuxMr+9xitSrVW$3JY=(4ZLAnesk@obqID; zgbot8pt zyrO&9CWothab*7p&($-_O|^nBpTYhd^=*1k-78i`y!WMOgkx>{$9`_SGhHA8*z@Fq{hN1*(|LocRMrOOUnbr2BvI0qt zk^L61eLz3mPw!nt@8wqOJ33)3g!K93%v2|yIISvnsZj2bqpNhzY~h1jD1Jy zIh6}29XyR#ajX%H^t{MHXJK~v{-3$2H`R(t-t z;0qWQA)7&8t_xoCJ;bX^>(gXuKzdIMwOeZ>5P2Y#M@@1f=fA3|d%t;F{#Q`U%Zmhb zl`Qo7c}lnr-z`o9wYVLrPLc(@F2auN1`NV1vG+f1q4$0{p4P0;urwC=;)gi3Uh$ z!Ax;v=GsN0$^tkvX(3rQzh_HpcqA=LyHc6E?V?{)deajgCfg!zTQs3s0%|{Xha6+W z2haSpfsL@RuqxG>L~EVW*$}P&a01CVz7ja?h9cfIjkpH&Oz5upRgg(FtJO*J7t5Nz zX773O2=~jY^J==0v$XGt*$_|P5Tsy7KTS3YTxqWtOSxdivs3UHq;xW>k;-?KllY39 zfo8C&h(Dq)lNxtV$l&0fEtiYkIANxEDR_XNhjXpby=s3rDTX}dK&L2uU_wr0c}va} z8SG}bOSRjx;kdMl4nQ742XwMPq;u$l=8D|TRE)iu5P7vvDFE7vA%+qOk8x; zGoQ2tYf8^h)aH=clW`m`JC?3qFYwuLE}Y8=;f z&$RNk?+Bv!h6u|}94|eG)FuezYdhCIoiM!!+RG0)o7f9SCF~=39QL#>b-e4ZJt!S| zUne(f1bu4T^Ih1O%}Hs28f~@KV3-!GAY|y^aBAVjbW@mPpUS?z{hpV0*&g`oa=Zf^ zqR)`}85?Pf5hy%2$6CVZb z*bG$5Lml`ibf3bjeIIJugx++#eYe;xRZYV$`_u~Os&#m%X?m{~s!`BE_>eXahXGg8PLG-${iG-s?Y<|TIZqOS2^ z%z&%-!pT8@qcZ4ZCYzH^-HkuPG+59exxPcs=e4Pnnr#YP)K8KN$^7DM0}F@`=@>FN zIr(6iX)+z0^h%@-#hRHSmVnI$ z@YK{Xbfh$-s@U|at&-{2yIZ`D>aDNq^dMiFsMG@Y^J-BhD#NvaS^rd(`-B8E7HXP# zmR=%y_D_=S9o>ZO4{-M5o*yjbWgKN65ggn=0FFmw$sPmf#(8`^VgrQLP*QCoez~sC z8c5Fe5@RaQXzKk}^!Y-(*78J><$X&1K5*!*sg1dR6Xu7nm-l3=<8w?XZwQ9B{J1YO zqtPU5;7YgseSFY!O9x}wr#CmSO?_RFQk`uGw4r#LCrJJYSov-OqGsH!s34*gDgp)-IMO^XqG zgGyk9vg^KeiJ2bKTiw8%G;k|0siNa$t~}Q@&A>B>U6mkck{3gMFsM)7Pv&CgGrhja zps|kE4JoS);8y;Slb6-yxF_c;Zn)rR)y8tC-AFFG?|j(~uDgiq=mIQjMEEc)-HpT6 zCNo6Oz;#K>0ZbV~%JEJ=(Itd$x66J=aNs06%`_jYZonug(VS6pzU1N6(_ICw*}F2p zf$}ksaCQ#PP1hgKTVH5caR7y^!#(v}yRx-lU|HvaWg4jHCPJkNXSETTCZ2s{%Ul4L|9=NI~ha}Of` zFX0E3xS5&-DCyR)F_*SmNrKDziPDuR0^2*7nxr2?qw8C1EI?_jf&cplTEYylG2>#FDWlQ zGa^^8;>Qd-s^ua`sG}A8U2ke&f zH$|F}95aFWBqK_cOWsGA{lmKn$8J)I(-@meY>ONB9>sVwF zb90airW{Q_7~iU~@+*Pj=4@?$-P#*&mU2-f2j|CjG`*F2)L}4zvVf4oMf~!W2IuWy zt85F4ER0*%*X6xfRF1T%Vjfi(>`pf8JuO%1+hSZfTKsvkc&4~IY1TIqZ8Ob7PnqV~ zLwxMGSYw&o-@GD#8_mseiEc}UXksRw(eq=O(|#w_QHt{I9ublUwUV-%u5RvHA{Xv6 zx|pN21i{gIWEFgH?DlBYce<(Ue#Br{0v<&RP*_;H#U!Bu0RRDK;^NR6(ja0ZPwB#e zf!qqLJ0-f$XOH0sJ|0jY%r5Ek0(A!&9pERrS`5B*$YFd#P@kY0_SGx11H=Ps=h0V~JqAw*(Z*l3@!Br!e!jw}(J+!yFs zq`7Nf(SA%B)9d|CN)c$S>b#@s;6?@5xXz&!U?sMvTk| z(gk82H8eyT--*klRgjh%86n&9=6`s71s$_}Xw5S>f5=L!gvUBK3XKlrMAEhI6f4(S8q6cik=cdASrHKF@4X>C|HFt@QH1SV3K$tGvNQw-i+G z#I=4yAM43bLOlNy-i_t0h(ynmQ0k3Rk5U$n*|uTUo{$DTQOav{(_@Jd={)TuHsnDy z*DKPDJlkp&Lix^!*Gz!?;oF9@XMVaF6N?ij?4{+v0rsffa)nl3X}2rAUoD0X)v_Bb z(O&s_hGjP)k+j{&$e-q^ywjyNoS-KtdGwD^v+I+SlIyNyH@j7Et<`kE{EPpLXss^< z{@9KRXHlR@eCUZRgHA`!kZtsuVluxDM0bi+-l-Q!Vc;Y6x9P_Vn#|D$AkB>ATOhir z)H{FvS#$~mOYYqN^QpxK~AMibl z_LObOJMFpL;F5}EDU*6_vBU+H%wx{XbiOm27MZa!V<&j3Ykqm4pPSzN{^y8}*HISo zX2o=a8ooRMmkttcG;h>?jDufYAj5FKrMzrxO#Foyxwf+;Vm*Q z8I^^uIl%nsb_q%Q&pxxN14C|RCEd%o4BON2WF{lnsh8E$jo<0)q|rJLs#}hXNl}Pt zc>m%lv1>@ZybTlMb?&7BQ9AgNvT?0$&E8`sxFa|mN0}@i?WNUiaL}J=rqgXXDZ_@F zo->|9Ye)px>(a<64>@c==Q=8n8GlDidd;wCIRvOhBeaI#5N(LC9C004FeEj-sdOvw`!@6-tuf`J4DM0oR_DQ&BDKf6>rtbUo_wlZZi1N-^ewIj)A`FW1-hF4|9)RWykTaOS5L{b(sp&*x zXizSxahsC+fk`OaNS2UxGy`0zhGJ(21S1^`~Lm zsCUY(*f#itx}~eg3^(N1GIr%Hrz5kFwQrCyP1N9p(v9vmErUWJm9eaE-*?KY!(2nK z>fBy1@NrBQQ#5KPM6z%7E!WTsR2%wy4$d|F{076#GJxuzv+PTJ{UYwHAf`wSU1IfG zrswlaRF>{QYU~H#CUb0HST%KbGG*`#_KblU!bvd*17`o9BiSYv>*0|6l=PB27(Zd`cEZA^8&SK z&*ubq29%+%xrkX4{Uf(+&m`uL{^ku- zz{L#b$6X!=?&DzY5qnYoOj^;v%ya;M#n0HW-pxOyb~cf_49oh!AI^{A$p87Z;nqJA z&W)JpG7l>Is`lgQC$qBZi$1g2B;!>xvqBLoGj*dFnxc7*cbOJMwhsXEDod*07_{(W z0r536)0Yo*Z!F_hSt)=VBvF(Rs5Xx6IgOaFcxR)TVlQ}NV+x9h@wYzu_#xK+D?NBI zrlj?Fy0-f#JvO`8qO-#Q?>KM+j-bb~W5B#ft;d`|a*Gygr%?*6z619FE{Q67>yukv z7JF>6M_Zz`BkS^N@Q0jCMhN181>||Eq&@>h8rf0bGw&!b$V> z_=uL9ul!U0{0m{OD!cwfa=UcvL5&#f%lR|-ei>UcD>una7Die@ScgcdrzNiGh@0;h8(_DM($H7t3$&?TxujTEFsP+9? zaS-&&CXjXbW}@SG25K@`$6!xU8ax;z2c{I$eFgXm!q@|9&16lt515Nj?RYzkSX5o2 zdLMiAZD2k3BfK=Hu1T>I*)|H$@LN)}J`-!XTrUS{pntwru~wBN)t(zQhrGhbg{*w= zE{u|ukC);KpsT}tHU5r^(in0(Li_Yt!`3RLj9^fb=hN?HpDM+TVuTHu;j!PlBDA*p zO7dEDG)oratOeLh7Qd4qtvtz#rjK8n{S~P@;y#D@hdz!juiQg^_>{24dMlRIfBfsR z2_WmWi`rN+oiE8cVLiisuqd8+$~oU4Av=O;l`@x3yv-Zy@aSkWk&<3HhOA0?+1dRA zJ30eGkc{UA5Xl5otTE39^{gH~TDBVm@*&N=+;H-ncJno>d0A{LlL;W%w5p1zS9A>h z9!ic$H5I2%5Dfnw%;}V;|A=PHb))wFI$)Nvn*=3K4F7Bnje?7-ez>h%rYLWb+U39@ zulQFY4I`g&<8Cik1MCwp0H@WSJ?;6}BY=5GzJ^_SrMat8uzD_IkP_@A3%Jy3?KZCD z1`kEf!1m)0OoQ!KrdIzE=r&RdzeBuMYI4EC-sDlcFe`UgKndunkehPfRA7pxs#qp{ z+#rFy!})O$7LnvF4y#}9Dfn=aA~g#@Y@A}tE=)f*@ubUy;Iy*|*vCtrj_M)R*6Itt z@mB@IqEW1yX%e!o!@AIO&}pc$VAwBA^W)ZY_fLbX>P5HO#nqqOr~L3}(AN@`oqf(6 z=J%Qg6MW5IY4L(2_kC%Fdj^{E=1bBh0d>}45`2P-!Yya-V}(y{|5h+0MAM`hdSzTx zJ)Z}9;*MygjOtD+o;zJ7M?c$W{mxQ(7W9f#M|h8C{9Taw?|jLK4V-Lg_qVR5O`Jcv zI0{^K^7d*x`kV>D#iDGL-s5Py&3v)O|{DsQx%FOGCI^`89dWPzauwR$LxC@o69zjpOcQ{ zd3$B=+{l3EWjtg2=%NI#P2Kk6fU3@3iSiN1F5Fw<_OD#1Q9^apQ$s{Y7E<1%(XvM; zVDV-hpH}IwG)}IwdZ}_|` z;U$+ITVs_+Cw;n!X4U&xD#v9%EY>C^&`uZTN}tg95VQ=`{71PV#)lnpe<81v#g-q7 zT8@JS7tWg0BWJ_{XO^6T#}1~C+m~=l5oDxjV^^g@0OFDFB-;r3-mn|?ZRxcgUCh{Z zr-yq?6EGye3a@2N(-ssc4N~Hjwy;i)%HTSCWkdNYJNsAQ*-#$Ej9agt&$sZGhu^cg z)Yg{ltsI?zqIX9vT||<&`Xsn zw@B&;JjT$C_)`KXvxvI&>6Vh+=MNvNGd_EQireK@n6&v; z49org5PZx4qDz93=X|>VfN27%r=b{tgW*TtVRwp$ z&Ca}?a3&yQaRHzywT#7)1c0V)VbJ!vjpc=>_345ep=6>Mof1&6`!6JtaKAuw1FK zH~>iC13Zgf3~dD$gi*ec?*k5cpS${&xZ57m7atk%c-te4r2GHkiDdpG61z%7KnNUw>z|MllxF z;~X}c#8sX_sb|PtV9Pvp^Nps(LyPe76=&H(5>61A@jSaZx{MY^ODM>Wa_X_#J#*v) zgNLtxf6@si*-;7J1G(7T$6rDY6u@%jRo5T!p<3Dpg3AxYo*xwHY>k|%XI~J@k^)_d z)iL@&9@*$WaQbF5Xb$e*UvUl3X7&2lRS>)lqQGZ{k9IQd_GP|En_YtzkQ6O1C4{y6 zx{zdK2@MG9+(zT;w5$@ud@&-iIwAhe+$1Mk<*lC__|tP=!wlOHaXu{;!ab+$(#=}7 zhQ&q}itT!fMichjn0xd7n>v=6~+!^ZPQ^yeJwx{L8U!Kb|X?l)wG@RlbgDbb4Y8 zILz`zW(^%q;Hl1$099LBZ3YC?_uTf(8{-Ydf%X+28^**m8C--E!wLfarIjt9VH4Su196__m%oyM1 zO}=#3N{k=#q`2LvMP`d#vxKefQf-M{RSj$ASAjh>be-88&E5{zxQFJ|7;5EHcuRO~ zbdYJeN8f!X%Poc_?6-@&-0eD3h8Bm_vNm~4u^J2V)N|eHi!t{LM57Htp!-CPjy%7WJLvf%me^Jw>LF{vVx{X z>&CrGUB-TJ`Ei9rAm!%#z`IOHdA|l2(xM^#gRv&y4$kSOPkJ1LZesBIBhd6`NZJ#p zJ~0Z?`O110P#+m`VK}qfpN1 zioiLhrhKx0p*R0ZvVb!|mC5BJsKo$^kZf}xHJ7w{Azln$kDgAxreh-bLrqFCB{F=y zBaL>(@Ru0eRBuolY|>ZW-`CZL@KF6312*I9J^luL#~R9&>D&6`0WtPo(wuRn0PmtG zduRLPoj8YqTm(vSkLpBw?T_soc zs(#Tf*F73KZrZ%kqg&{Sd`N-s^&7mr_q^?-@6)GNEp5fIB$X>Ig&2W`2g!V@k(D(d zpfz=lTW2P8qQCz*i;Hc%f9%v@T=e~DK3rr@;K$>NibzFE5EQt_` za%*UH^eFE)(JWZhbdf(z@p9~^nG&;E>Hc)K8K{)d+>=*Gwo!SHdeF}>!!YwnOG{xs zzQ5{_vEC0(JAfZ!NKD`av+PSRkayh$u~Z*^3_2IK**x_*DcIUQKVs|2$5vU?!qB~I z!i8(LgH+!P97rbR7^|;7F2NrJlXR^dKqoG+={XQY+ zPL2|4cLkmGsmyu2ie*&WgHXRzbsn3$?xcQd573dSria*OS{BDj_p|y`TzHT?n^015 zCV(;z^RkY`?!%j^-?U=O=l7Q5ko9LZJ*I(t7BOz7oICr*AjYkvrQ~Z|_psy-?ojTC z2T&GdNtOqHXLM^RGf2rwjYEDK_vGoMA8q9JXw>6N-`r=09~*`E85cqfnICT>W=^X2 zL^K?XG8*-d{#fRmr69(G%ROF|;**3YkEt?3Q!*=g&prB@t9*ajE~d~5iIVnn>j;T{ z?Cimy49X+Pe4@o!^mIZsJn7TD)(yrhG*AVL=61d|!JN$Tv6*QG2&E6Y*FDSTvXKu3 z)ntowbbuLYNe8qNCbc-42ys2L^`Q`P>}M@Mopk@5w%o#=+7!j>o_{|i^Hz(hm2x-I zow(Wd#xO8^)!3~7!tSR!_p@1AlDJ*kZ)QZ3@eGoyl%2j4y?o&*& z%(?8D(&Sb}JMq~U=r~oZ*u=E+vV9MNa9R&+H+P&y=$OGFKOa4dO%~3n{_!eKMQ4Ko zAW+nS-trcV$PSmiq{h3VYlUZsj&7V}oEp!n$@B2v$AvzrY9m1v5UY1?9}HHvF8r9c zCd#lncM9Len*h*mw$C2@qK-c4`kC&Qx2LM#pBKD#sT(X*#s*Gk7U@TE=!4YyI@!Az zM)zyFe;B;`TceT>VPDz=;08o>iGUz=-37IRz_mH^*n)eHkvb_SqiBTo$OXZqtjOLS z6JW$8v4cf%k*z}DZF62`sYGGm>Y;gM!Tn}r{hwN-Nou6QT%U;Xur$ZT6fP?6-OMYCaR?Hkh7o=p~OB5>ddsdhe!c<97B94PIll&Mb1-ez@w zPm?gZVO^ZR?JBi5uU6~R$8rmYjvsk6XihNLykJgguuoB8h z)b4_nqv{A@>2;u^NBBbJL#6B3w`{WH7<|)z)s45hg(UE83x=XfK6W-b$q4EFw6F@F4^kN zCM>d7kL2(&2WP5*GE!8f$Vgl%AcQgeR(z~w-4FL!-<<*o22jBOgO9m;qEY&5?qiOS4 za*a+yvVs^y`ENANLGbmQ_=CyE-;41=lJ0172Hxw@s9;(gA)$HJ|~KPERI z>UR&^iDEKb*St~dA0<$jDRic0UB5jY#|afnNw}r8_Oa-y&97GmZ^iLz2vn7WT=+Dx z;y0%Ck^G1a0k+aT z-We@jeY~gLs_U(bhUQ7-@Wqads`&u!EQg;aUj;?AWa7Wx+<0h`IT#rPjC7Yu z=N=GF;8K&_isSI8ORN(4(8G;-&d?+FW@rA367n@TLbXgU@4(p4%SFTXd;ku=kN6&R z?Zbl5Gw@%9hH-Ewte~O=t9U=GoR*K`cXK=gw)OJKtmZ|JLt0SiU#(VdXO`%va>(Xf z!3cEWFJ!1Z*2@DVqcOp@oY18)I_l2fI@HZtvjYEJ6bpSh?K#m?gHDuTQmM2vKmpnY zK*MLJ(={9k=;1K0C$79+Yj$N@gtW}fdVX`e1jW$6A;->hZc)RFS9mAHe2AT(N9|&; zH^^NpNN91tr-Vgo(GFg7FOZ-hBIe)nY_GTSwHhhKc;K@c9rvPvW&B5I*Am&^R}IV$ zsw!_eiC;?a5d5<`dHn7OOjT)?s4(4ve2^lz;rix58Rm7j6Xi#OrsoS6P?PENqN~?m zUs0Pk*jlEnghl^xK+eHh?t%|Ydymcl`r|v*Ck|Y%?Krl2SQ&ONK8;pxiBoWJKFNjQXwTfOIg=3k8z`xp?;1E> z;G#vy8X`%lD61}|(m6j3C;?T-6^02hMz$LytH`j@XB~+xXvYW>?u(48Wuw6ji@cv+kD0iM4 zXhwtCIsQ<}F*!-74M$3k*WqZdf2+MT>;xc9Wllmwz;0!(udc5oIsBVbTSdf$y}nmU zWpj`}b9k+^Tq_7$+rGZ>Sfj*oWK$GZr^1B?5gWFF=2BgOszD=;dT-fCo{JjWNU z)*{m&->NKF9+U^xC8_Y9EZ5%{C<2Qy5WZ5&1k9m>-b-z)*pK3JPT)El@o1B>{*ZmR zI~38N>0romxY{Sf*++DgnQ#+9NU&56GzO$FOt?AGP1uKP8=NPA?fG4<$1pM^jH=CE zg-RxXLuj=rjQM?cqfX(RE5bg?^kw%GHAhNU6r`z7-4<%e9nYRQBdwky_D^pWk$#Nqz#SrJt3P; zY^@#8keupOsSDmn%W8S-#qB%wEl1Zu;^%gfNYRR%dig_>%07h;miBgSlyr zm_TgFHD*7Wgb|@1)A4g{bsGFEE~6n{6Fb8Ey-npikLn%QZ2lcAocJjpLL_OUZ|+Qn4J&>27}xXe9RbuU&Q z(n8%>Okp1>ovna-2iKy?O&>e_{#o7gZj$~M;^dqu>yGRWQU>d_FC7i^ihq!!ky9JG zN%!0hXbt~E!w$SoA0bgOjdyI7`b?GvwOHAts#^#Podu}yE)*Z>eSh-7TcFlyy)+#x z{T>(V`IJo5lGvGdH@3x!*lA@DNI}Je2UDk*J6l*A`CbJ2^*7DLr3iQ1 z^l5i^FXL5>Vtkb_Alipow`ldxiqFzh}QNZ6@=aHh~R)w^#{%rN04p&st=zdIpEW=xiv^Co7V^fDG#ilL` zjEMm~U(kaNCp^R?u$`!egYs>qz~SK^so)n+T3?=Ua*Pl?EvnE`KmmkFDUROYwY16ikLM36~EmSFeEh!Zz-Fm;P#^FIqON_-*TzkV895N zl`&J)qknKaiW~8B{yO*!b<(100-OgtN{#PkY>;Py7~(hFUZr%t+DW{#PMrnn{l?xY zW+viAEw^wiDsGPQkdnt9%*B=*GSm{zo^}cx=Sy8ok~X|H(8jF|PTcoZY|qYIK10Y&Y#5B_1-LZ=-&QN1ZYDvT3z)?_k&typ3^=` z%k5`M&4{9P;vE6MVnj4%9+FvD1!TEs+D?X43K&83GftO&%RfSKvAte7-$im4iw+ys z1MRfw05bmNxTH0)bA9+wI8NFdkh|*7*U0}zIf7UX+PM8>vRR^&9^3pOO$j|~5nXj& zqcNEq7=kJ6hv**D+-;N{*=C#>y50U?2t^XUv^|CQOpKPpO?2?%sgVWt;32%yX4c0lQhZ+O&-on+ zwWkTsw=}5-VC#i8zLI%z7a%jtP3LkhlszL*S*}v`kQ0Iy!tfA0itG4rD0SDGeyyua z%*j#WxSK1ZDed@$gRn;{VUrrrMdW;r_@@j-8z#|Q|F}k~jSH7tU15!dZO5ujh)6I%&1_o#QMxJXcP(?m`e*Vg<_H<3Fh-qOy*o|EKxJ1T`W&^fYAlcgQ~+sA+`btBH5YLck!sub|3ww zn5^%JhwOyD+D~mOfrXyYkDa^n25D<|l4io~?(KudC*H=*yENGQ7CYaZ7>O|9d z7U80`p@_0LpqX1=%z%|i89~#R0=V@z8+@mnWm}b0sH1OF`t+S76VRDOx?_!ABf`74 z;$uzk)Bq!^M75F%{^4u%c9|V;MyWvIx~L6EX>g&+O9}F&elRz2uAa=T1l=93Bf0Y0 zkTH55I>Pa@w31jupUh~(-C~;wlV*;wOBqt7SJ9bpo)$57y%2iyPyT9}BWjY|pifh<)N-ZtNs-IxZ;oG9N_`|lxt+Deg4nYUE*6Zyk z)KRUErsvK$ek=8=xao~pwqQ3w_`VsOK?)Hc^%eJhnmhE81iOg!>Nioq9pP*uYX}W~ zVG?dwZSs0^@=80Mf_nVD6oscuE$d z&Yn~ovJNxN@$=(yUEu;P(3>O=@1#m0a zss2;B@28X)7EvuLVxF|^Gi=+A9B^LAy~D+tPon`{idrcVajx-G3J$qvDF1Y?4*2)} zLIy6@Q6e297WQVXx}-n}&}fv=%a#8W&Q~BYXeu>?@08I`@Bn56H3AY1_ZwqIQ+MOP zel`TpH0+C!`{rsbnH)?&LIPZqZlYumi;m ztAbhhxabIZ-3a)#kRFt?pvF9QFlI#QF}8M!iVWJXTbF6bU-%w0w#eK;M!%G)mo*c! z`a;ujdF-gR$yduLA$%Oty4WCcv##gs%kdLzmPuXlBi!FVZ3O$`d!2s+h#yp9F2DMA8sSR668sckC$fFs8(R|d z2Hp5sc|u*Q&+l~lQ3LY%RGP^n?zhV=!Xy=g_O*3Q&u_p8>qSrVI}5uhGJBIVg>!$G zq|KXeY}#e!Do12y z`Z8=WBW^RRTxt15uo;<`pXbQYYSc(wfC?1BTHO`X%>nT)aI+cNu2eZEfo?ic&5uHxZp_ z=j2uJ(STq#4r+#Uzv;%SDK09pjS%19?sMFBzwV6c$M;xoI$=GfXJ%p*0|}v?m2SnT1K#&dT(T=N;eb(J^|G>G8;Zy#!^(V(yKtD%lZ^(*g_zZ?m0YgPH!8 zBP4R_-Yhr=OxBm&cJ^;+{vRR#(E=)+($LtKo zq~KyROr-v=rT%v=`Zo_o3%G06&^kc{01qdz_g}*MV`9;kePXY6oP8vuc!;q%Ev9Mr zSXUhegvz~t5+&yP@5(?O7s$2Wz9F|Z={@*Sb0-x_D;Bw_aYZDw{Cm| zCe;1M%LE8Ga|mE{X$6@i(IjW$VtKE&_~qFVt@b8(*@59H|9Q3k{r8-&06VPy9hb*% z(Zu6By?qCS8qYN;p1$=(D4#B4ZLOaY2^%~TGc0q3f$#n8-f}cB-=iPm`}Co@^h}n& z;nmC?n6~_5*B#JBOjdti|9Aj0pbU(p;@vs$CcW`)81*dGTBi6<51{@huv>U7{<&N5 zzQ1?N&S`=7f4f_r122(^LuL6lm2g|y+=`bi#cVDq+E|)dd42V!j=ftzvC0VPF)wdl z+%;glPU>X@BDJq~1_a?mzKVM2#eiUKXKg3WMzCi{K6qA{`Ul?S&31BGLLa;jx^Rk4jQ^|Br|K z*U$ggpIns%*qqj6Ii?~0UUc)n`PxaqM`=laz3`tl%m2$GehC3wHU~mVT~L1y)%ay^Y5)e|2J#!|2NhDc%%ORP4z!J5pKWv?>5!j zR+T>kowPg+zkLhlRCt848L+8IAR4t|@relnZb_lr3wg$>LVzJhTccrHzCoL@?%vu* z`7L!%JS;x_zrEr7drWFZ?_|EstI`hY@S@Q>35cYlVy|4Pau3avO zGA864QUfi2nv0{?$wcw`!8mQmc7$!nHp=QYe`A*D3Iqh8(n6Cij=( zWL=GyUX|`JgduwYrhdy`8ZFgEoc@*8|N8P%5;86EyFP`4ftKR`I$QF8ny2aL3m$w% z%fFVDD%bvTw|rYY1A1LfqBPbloOE8lG>wIp03I@rS?Efcy6L|CyNcHz3Hxu~PGf#| ziZReU`=?HaFO*w=Ey@?}Usq+?O1xqZc4orOSEx7+@Z^HBb(@75JZ{6kO8#F$oqz4` z85K3DhzgYf*W>>V@cv1nTW7l&HU6;(!o%0ohBeL={pW^l_T*dp>mts6`;{Nu$^Pcd zUU%I2?U3#iYkoZUr$;o;m7uNS`eEVa#(4&0f*J8%U#{kKM|G#QB?IzsF_wgf99LKb z)$LrAJr;r*-`3RBYGC!bIq|O5kT&GFK#MS@jzY;oaar1oR8ClXRW)I!}?RSpEGa zx&qtW!;#p6;a;S5S>Vn8;Yz@NCFnmnToLvg?1u3reH(Y*I%Cppmg*# z`#nHXSQ2a;D#o)vZL4QE)u(j1D(3#s zFD7$MI4=MN(Mt$dZ#3uOg{V_!$7N?!=~p~pj5mJz^mp~83y5Fvv*E-? zQ}@s=Q+8`9dT!4~KX86CB481Tq*n{Mf6dCE^8~q7zes4Acf+>ely_J-P-UnMe_#i z=_0?3_&ir*&V3#bep?P?dpGD=RN@DagnIu0v`?LxlT`K^QJcG4y+m*j+4}l^xP%A} zE5#?s-qCUo7Gv)c+=|a7t^%g~OI6wqdP1jPXTP7s(4HR9AEq;)c=jA{^;u4=?S<gHy4VxmTitz5!SSP*By z@NB2B#QeV4QQzjlD-kpk@x#eRZ8+R!Z~oe3$x3xStnba`SdFfb-4d8~c;Z;MQD0P; z>DRvbBco+M`G9$KZg=Hc|9qrR5#g)YZs&AG3n8dg0DZEMu_EnAIHokQy@0&QXly;m z4eObK*7rGaFnjX10RC;vfBZ9emzuRA-@h-8U-9(+m4ZK?fBg9zP|lJgy{%2LIP<52 zhe}MU5x*4y?lpL`PwQhs}Db#Kum@cn+=;sEK*(=+XrtqB}X_?pD zDW2x%V-M`l$2y5!ceHrQswX55{X0^}`sCKR3sVV?A5>AFZvLA8*~J8hGXqAVXI8oV zk_HM$>|)G=csG}}a5>q<#s5kr41ug)d3|(Z4XSfJ|DXteb1kLBb5nDXsJTucEKqSMw@ww zI*l@xn>JEkFHW@(>!P;D8KbtB$c`oXRyh8aBqn?yX_Bp8j5FEk=Fcu0pXFqM#hTvf z6VVH&G4`DQcne+`2uV%A6S~HCz3ij?e+2nO4lS+^2OX;x>}4DYiP$b^F$`c5*Ph)8 zg8$44@YwUZPVJdVwzr{5zGnc1fc2jApp}Ohlrg z`LoE-LncCJwC!?qs?DWR3Mo*?|JE9?zE&`~a@|;e>RbPJwtv^Qj!E8^O$bM%)Mi-w z*NX{~!D1!e7t(48mqbT>Sk%$c(kq)-5q)TpW75>MlD)1l4`-`_7G!s?O?$NVH{2BE z`$mh|$e(7}cl&^(?+AlS#qZq2y0g)eY zBIkk2p_8PN>}BS;!D6fL1>>nosZAicE21a|DZ^uTMaAb_o8F7tbSN7f0ywT;z+l|< zUW`q^?UV`p!(i?KNfxuO=@ne^zZuKlEgMWP$~~Oq$RzqpS0B0Owvkv26sxfF4(>>U zQ3Y68(rZD++w2~P*OXfop);w0hN38J$*-es%VadmtH;7Twt#*R?q$JVl)teg`uTeD z@(5Mn{oJ4de_foBjLrNY3?hG%**KmdG5e(cFRvm>l1umh2jr4uFnW|su#r$T7j~tt z%caysZT8L1P7Q1?zW*rE@GuTBRyko!dZbnDZ>`MrdR6P%d#PI&zRn$*9ECvxxs31a z?zaXjSD{yQgJ#5TT-a}scxl|u((5me<~r(I40`PPQL~e{8*pvpNcZ|D4!zvjiq1u{ zem2)VM(?$a4O;mOz@^d;=j|Cz%id{GUExr8rgfCSY4+x{HoiT_Lhyrn5wP|6VTwk- zS&8Mk;+Gx=ku=5}5_4RO(}DGmzWsQ01)>t&i=}F%7iizE)7q_VE*a0(VL>Kji6}a# zi$CGYfP>@Xi~>&rK=?Q!gj&J+V%OTTQm0%l^yCp`Yv2P-d|f*}bgosj`l6xfgJ7|u zQ6sNrOR90>)*OSWDRY{@)oXueB9{^he(Rh`x$|jHZN7O9J)N#khp-sw&e*O%%qkS@F1iz?(u|ChypECOO&QOP4R%71)4+Mh$1 zSN>>$jY8R0bj>b4$~2y0k%F$b1w^db!0AS}(D|2jip;W@a4T+wUn{Lt=^cfbnb!BK z|8hEKU`hS&VBk-hVD?)R>Kx!gr!}GJ;zE3v{4_U5(7-+OdXLNvhoV8w50^@J?26k0 zGMyVr#AQ4NaU33d_F=Y?SBpneT~A6+x{Tzl^Nw9~g~#7oDAw(j!qC2c5R z74qQS^O6PentmILoZulAMh{%KK$?r0q>aTX0L5r;pV0kYFCw$;CIxz~wEMG7mF@ZFmr~ zpG8~H4_b>agy!ctQEV6@Av*4Op7W@K>VRUk;iuqK@4;}hqI|Nb&|3HNXHSICViNZg zE~C4$1^WHaGQh^?i5t@k&KJMlq%+0@GvR-Z3!mTyOgBb7--uy8o*w5PaO}!G(zK+K zcxT_9ZeG|y9s*cFCclY&ULL;+MaLMxWJDQ^$Kh~3mi+cMZNtUD_?9EniU<+6!ySf3 zmvN$iuMy%cG7q7e8Dx=#NAgXn3jh2(l+GwW&u)dEQ%9H)t=E~Qj-%zP0lgox^a0;Z z_^JH8%N!1)_7P-L&OtU7Ll1?^I~8!%oeF#;Y+K|1amVSts@xw2ehTkA$^Q+796PH_ zPW|ik>z+aqEDKxytm8gzVHFRZYa0nY+OF9^ZR~_RbB*yPR#?bM9p^J4Wd(B4QXF5_ z;$U+PdZumD>|(C3qcV#rJv`Mck;qus@C9JKz3SW(eqXWrp7nL5v-f%E>l4E?CVT(hW&4G}OLvXm*=SYd4nM?Aq*{!PxPs>{W zO|-;^+?%Q5R_v!O-05j_%+aw{*li`Vnf;;lGVSdxkZDvFfmH;5JUMo}UwcD#NYnL3 z5q2>ivy{Bj6dis7gCv~5$DB-F1+e>mZ*bFN>61Y$#!~4~994fzIDz3lBj@svH`Bve zcM@8B2`%RS@|-aK78SXMz2K+!Thxl_XfF>?Bn@MagZECh9Z8#~2KE@`S{3Vp%DEN? z{G(5c&>t9Q%SDp7RN8y#e}GZO=g{punex(HB>B?pv9AwQmaFbbTPh~RFa$hq3tIDD z{2}e=IM2q%&4}?dxKg!qnntI`FyQh#wDCEL^*d#r6iA`XY?uth_bXLdQJYy?C9>{K zzd66i$tw3^yp_d(^QJeSnGK-7uf%p7u6_FPKN!O&q|T#-HS-yS=O-z@YrkN&4;PW5;Fx7)u;8UJ?%{Rg7`^;n+~2}17jo7G)CJ<=eO#iol!k>wx5J7s$14&J#KM3RBoy|R~-yXc) z87};{Wc<&s4Zcl!$%~gMfAA!K9{C?A^`z~$5qE=E*`DJ3A57l=^x6lcmwf#pMDZW6 z_mls{OQk%ERkr=7IRAfx&Mz*I0Bz^dM)7@VC4D zgWb5vNt%wX=D>essa$_sDzgt&vZp5chaUf@(f)rxOsZMflK$&1fPdla|1UD9^+GAoOUW1GK?moH2?8)V#!iF(mbJeWU`lSJ~;L&<8#OS(Iy_*glSSijTlqRu72J$~r}knf$o zEoh5s2d4mX#U#!allCc3@P*LD>luu*4*E`6?x5g&_55kOSFO^!T{YBExr>}4S?0~% zdJm}2URZtKaTQis6EqNuf8#tvf3`dap{e^}gzzBjGOEu`jL-nVFZHbtM@=kYgW<8= zMXT%(Y*U;rw#n`=&9nF@d(6Xq^TKx@qxDu5!k>M{ncxz&-^s*#n-oaGmL>g(g`Kq% zY%_ts-q5m=Un6Th=|DLo@Hnx`9j0AW5P<&(ihp@@C2xo+R(AN>TgEiw1@>kZhpX}! zJ8_D;5JayJvYly}hix!=BPst~r@bZgRoABvlH%7wqbyAoyIHivXodc^4Z(vovJRZL)Y4)s)*BFK=bkVyxklmzlEqC3BZ^uJ$idp%OcHuDJfPaABzS_tRG%t1Qr{vS@$2 z>VrU=Y{`aK8?7}k`v*eFrZn^FKPjCD`cNB-gll*@nef$6Y4T5&c=K%5z;YDBRY=vU zLp1FVW?Duptu30ZN`l1}?^fi;(2r9qJQKe%;LHr1%u&L1J1>az%+6i^!2otm(3ego z$yCmlrYaMDuemXTyDi>cdHvl%Fg&KaXyy5%EYPpl8CW{k=^BlxMWzeq2R6hI6T9;J zkW!#|eI~0EtKV$2YQBL88<1s&ALyEK++^$_KrxNOPk36gq4wL{&toGCw0q)CX+Oy; zu%wbaAoX4@cXJ*}0>R0~(@4NmJCk=iDng4`c0UDYg$1g`OMTbQS-*x|no z0%dE#aHT16g;($zZ8l$zR_jY0z@<}-E_-XJem zJ^UA+^j|#b0C1B4z*~HW=cdQ9X1=wRQnqlr-;}&aE%#>~1~~RNAwIu0uzEayS5(|d z7{d_0b1PUixY3uNx{=-pnVd0eXWuyt@kq4*@xKbxpzK*V-~byS@DCWeHs*-EwC9Yp zpKV!G|3mpFVvSq@8G3yp&4MJ)0a1F9Lw~bkoo`0o?n#!xU@MTK?>?WdbmT#^2K6=LKWS2k>_zue7r!j$jWO&Ft6 z&{2QM=Hi-hTy2UUTC#p{NH|?%MYtNa`mV3P$tQZk zBeM zz0rghv0xWt{l~EL#l=493cHP`?HNo=aaWeqSlHMS!;@6!3(zs4v%N6}X=Dw8ghOk8aSidnKj9Piq|i&cs&uRl*?NG2pl_m2c+#D93IgwRyu)n(I2 zg7sVYO7wm9mu<|<(<4HM&G(}kSg-_NWAXy&rEj8g6?A{$2dnQlJ zrxd(yIcb;9v&{+mpkCCTD>wh-A-GtFj4X8J%Uf+V+deQnTcXDTE2^5fM4y`Z#)?a< zz1vn{{`>gLg>$JMg>KFXrrhl`2-2k)^4wm{3(4_Y`{v49|fTNlqUt@>1E7E?TdhTC>cUeIR!j9b%Ic)t^BnG#BPP&aNNdid}N|E=Ee zCl(N;v55TfzA!Eyx0Rsts=JiS@~9VFWW|;0!Q-@`8L+ZaK-_!)mGsh2Qd{DmR5aY5 zEWrqStN6^kz3M0{DO9@uX-a-!ClS8LXuHW=E7hGGYkcUlN2-4j-UJMaw>}v^u+^u3wJM0GF2pFyRRT&D>Nx$9c0z}*MdEdQa zC2Xb_-Vy>+x)wR+Ro#eI;rbC&wAw9#$Qx)hA688a&-*R|n2VDFq|EBperD5we=FmV z;kRhVmsqx2i~w`?d4X%kqI1-maN|D&7R%e zJipWwO=)|eJ4lS11mkadZ{BwG(8G=g4+O4np6BysX&9ApO9?V6AEK8_@n8C~q#(r2)T{ueb6VpCUtJA>-Us*yPkM_GLVS{Iyz>YOTUDUHbgACGun9Qn` zDfL#uPC16$X1bX$y4QL<)Xb%w-R#--P(r7uKUeq@ZtvxBM)4Itga{FwJKC;2Y@rUN z-NQ-hWa~CmTg>8DJ0^+FG}zDdYBdQn-j1L7=qMrOl_ueQ#dn z?UWU1eUT0Q4)@E`@7}#ba=+{%591Amk6w5U4wLorh z98x1zBd@)*5vohYAdU(>Zm-;KYkyVw?{mAz1I>TXLl!d zeHPX~B`7M%Tp50)l>T@{e{6rI8NTQJ9_JG6lDNK|rKpbCj#%wX;g<0|wwNs5_XwIV z^t!{aU9e15N-qU369}mkNbF}=3Et$7gGvSR+9GXC;_PuYMEU)`<{*y(8+oHL=Okt; zSK)KaCyvQD+u?Xwg7{jUT#ZR+whXIsa&`XibMY436A-`v+JEoWDilMp z`XNoRU87m{lWQRS+QWK4RK^ZN<`U^t)$W?Bqo_1Cs&$fY7_WEUop8N+?%_3+!`aQT z7Iwx9Vw3wI9B2`PgJ8V~0h+7)Nwq=sT2uFjS==8q_lfdwXZe{%9Z67pzFT4_s)0)8 zg|xQLE+)@arNo3RF7R~`LMd6!DoEEYL@%8q1UvBLDDS7YM}^ zYuZ}WSh=23!?Jt+PUgcSDLzHe?IWLsrrFkgw~{;*yzSw>@jKD^#e8q|cM(kT_sA`W zd{%wp62Fz0E_Vuw%^)6@_|IGSs^z=~73d-Crf&GoIdx27{2;iR17ldbf3O%$0oVqe zL(udf5P|jRB(eT4G}U4*!YpImM>_j+bVltmFeP0i_i$EBLALCzg-64wfMM!E8B@r* zE%PS2hNZ`uNl*&Y?H}7D$!a0L8T)fDa@1dhEAJp{uxh0|g%VptjSM{gbT#T*CLJHd zeg6EI2k^jO_Q=yLE8utRHWU38CZAaE7Mp4Hz8C#?b7ZH>IV=i-t?3K#wZ(WtP#eGM zW_hA}z$!MTu&tFLr9KtvDhS-+_EQu<%pGWO_0O(i@T1klgXoAZ z&HA7V5TVc5Udp%F-lV>%ZkB{O8Q%lhdJ@uyJTEnyeE@i4<6+6SX9=Thg(dpgre)UN z#16Df{NH-j&ioYmuVc7DD&9Sqg7P$hJGdD-m| zzsK6m)BdgXyD7eI-&}L6(9w+@2Q9Uz8TKG5OXR^*2_yeMf@GH9sw<^x$npGx+dAnV z1&h@kK{f@V0uu!xt?o|_?hGzAN~m_bjG%(rl)*2g8_4@X&_q61|BxWS+lM87D@vRG zDnsGmJN5_+S;nkbhEp-(qjr_02sPw@!t6P zhLLWt7^yCLxiWb8tGAu#jm-L|;&rn3_EkEF!hLaOr}<`G zYjHh<)z>XA>77uy))R+V@id2cxyCXOD8Cx}bc$P;%RO)VZp!7t>&B zhTc=G_bQ4YXNb@;Ysu4F*jJ&)5HcQubObX3K{jzi*!Jf6 zqt*VvcH^`yle+e|U^pH)F?5z+g51yDr)a0X39_{P>>#`a&1>UspuVs#14mrB+t=J6 zp@_w{Hno!@W~V{kzsB0SsgD*OQ}I_HKI5y+ReXd6qagOT-T?54#*4oRwXb zuBE(s?xIJOnjb1O2+l@sbw&HGK^4d-ec~wjx`?hlUH!aI7H7*&CO&ZHw|Z~>+O@Y_ zis%v1VTxgg=I3d7V=QKXq#IuY4pwdDx9@8tVah!wRp3VuFaqZupzaDdOfa{9 zvDN*Ul$fZ6A7;k5ePw9oP;ylwNVq;5d@TE2^qJ_iHAWyg>j|X2c4n--whAK!6N6J6 zH1m+H!9Q$M1n<(Nth?FG$U6|P&&a>vyEG&Jd8WpJ_$<;cHY5KL@1lYO_(*uHZ@ym~Nd;|+XMZeKS6g=|yGX2QwMi$te49U&zz%7&U*$CX zh+lB(kE93LtkE%#?dLC^`!qXMJX=@DdQK#vq{HSMuoQ#|e(R!ruye~hS|Z1MR#4?5 znQF-Lm-eg}>!C}cx|!JHgU#3lPanV$gI2-Lct7NqueGq~v>?7@&JI}}O^|MBXbMH}XcfZj=!uo8lRn-+~^NK0h{mN8C27pEwbaRwK zvVBrJbqu+6IEsoHOq%m`lNOEHmWWb!y9p4h?}I~_88zDiGNes?x3T!*>_o-GTEwT6 zVdvt;R+A~wsoodfGC`{bQageHQ>vO8=m|;$)=*O{1r~Vg zZE7mu%WQymbZNq|jMwb=xQZ>Y9@}3Sizv3;_XsNo!j)RpypS1t*^*pctK)=7m$Z}P zM;=&=x?_WV*~EOF)N$9_t66J_omcD%#^(Yw>`YQA@#X-BSF>$7b+2sWOB>4!i*N8q zVcqZ^8@12nQ@-DSbak3%11f1`k!0Pd4yp)wLU&*a&1c~H)&V?cMBQFLIj%k zomEQkiJP9iScfivkAf%)jm$RV^DQkM)y)ay>w=bq>ywKj?=cU4zsEd2YsF==Hp!N% zdUv_Ls~aMCHE?1yd8=7t@4YGvnV4Og++-{K0VD#@nTrGfO)ve(3};v_{|+{(QNV@= z4bBUC$mr|z#ByW%UW@5zDXkMc%0y4T39H@hwq29x&XafAJBP4y;OXm{PUxvWs+*PJ zE)dF@qF}8IT)Uuyrp@TG2%Hz3b}hdT5qK_NZt(?YJ8*|WQ)%|ULF*h)~Oeg zDh!6qA2fp7$Q}i_Moug|O)OaG?P-`rC8#fV(}4NC1{!XuKQ+*>w$7ahtWwAP+C+1E z1xXCYn07m6ZGM{5mHLFJqh6ZhdTwC?!Tr2QzacN6Jk`jRb5^T)?5tM2eErHI`Nj_e zi*9A<8>5lB>01}*9k%zD7#?O4(sQK!l%Q;6`wU7Y18ePXr{Bryovq7vL5lVFou0bpT6&A zRYp06%q|%mq};-LZ1ugJg^In50kWmZ1vtC6#4A`7xUJNjD^h~o;thLL<;BTkvl6wW z`y*EJ$$&9${1NNz>Dld!4q;pah0EUHFWUX8U*FZW0NC!C<~$Gshe8^1_f9Zrm%;ac zn8uOwAqP}5@?7Kjk8yxKc;3zSdQYe<_qe4Bu6wAvib{s(G3ZgU*MS*oMjBT;LWp%_ z@t!^JKtez_h$I9g_Z2|;&IHro6;PlYdJA4WyilN$z=b4z-eP?ca z9oY`f)Q#V~n-Iu9C@Z2>{Ae@K(88{U#yE9~YRZ4cZuGOutw=juPV<@Ue$x(Tw1DV~ zNHJ)RUS*-mx;z9sLX1gRK4EZdthbEj#J%#Ig-3qdcL@gB7s^f!(PaN=?Ws@gQ_DGE zjk0BPl)w!yTt8M6LqN68qwt6doE&} zY)Fef$C+m^5_c)v4$?L zPw6vFIutspOZjzk+&>FcASiNN*{DY8_puuZq$^vqW31__7@q`Ll{mL_fwByp9#K97 zDX4s*d_B`>974_T=Gldkczdq0Z}n~oVeLP*XpTj9xc41@J?B20i;9J3JZi6Y)4S{S zHpSxSr3Y}%?<=1c4(TaX275uDP4%*!7VgMRwzzf)!2LBU9>AZ*6*NKcPke5^N%J$a zMP)`s4#^#2D3O6OYd`OJFXc7te`wA&Lar&e46P|NwZ$%xFL(6A&j?@-(+zCX7~-O2 zEuLSG_t79_j?5sS$8{V))05qp4fICb=%;}(t0o+PU_ITc8)NCOn_E*`mj~ce4>}++ zj_gX`NJ>`SZ2Fz2a1K=eWnV5djO#?qlHwUFn&FZp{%DtY(`KiMp+S5VqW2E8-}Tt7 zGD>derO@%C4+nID&w*C3W8Y-5?Ug&!sSj_;K)p+)CGM0trrK~e$$77Pac3?UaeyNz z4|&%5{k{F4GG`9xWUMDfDF@_OgU@o8IVJ*p&#eu= zIt%bHnZ0MhR^_@a*4U%!wg@y6Q8dx$-t9u52FBTg^YD#<9J!-p->=4lXG;)mZCBur zlNQ=c?wlxD9E9&RC+x{DIz~1id;%-8REzrWCW-Y9Z4OFx508Z7ASf8TgiR16QMSjs zM9{dVj?3EGs2%gze7*g8{%oh2zY<^s4vhF@Z6UF?H@YOfKHL9YOvfN33pj;%sOGs5 z>56=qCQJSip30Fq%s%W=DdDk+%JI*A-*`56Um853614XzwYYjboe7&wmLrSF41uHM zz2_n2@b$t+u&)ogfn0vy62h4a6GqM)TQDe~v)+8SlD)?)Xagv&c_TCL`Glf;u=T{R z`$_s8Wq7rRT}f!*PJ$d>jPa5U`S9%QeK3Bp7)F#bavq{-qv4zC-@;V~>lg+gGC0N> zN335$?}Vh5zoZUsOf6l#aP+jyDYi~f>{ve}IWOZ?opRJW?*`ROvSVk;^8p)8BCQi| zOyN}l;S*z0+zQLI!M`rlEac(4aD(Id?I2+nx|$#xU*;M4s#{a&hxoLEXr3C!Q9|r| zPKNI|p>@;JPrI^ppg*Y=I!<5{PCU3*;GZjJ3Y$XGlPr~tPWtBAnjq3@6Dj3%kHrKR zMhJ9;QOAcE0x+h+1LntCU)_xGkJ}G|4Na;a&a(d+Op}IjGvi3pn^=&ba16Am7k!64 z+z@AXJ5Jb2b?k#UVXN1x3VqJGiL}Tw(>GZFLMdA|7O|-&hs1SiAr!8cd}?jSlSpZ@ zv>>m6fp?n`md4Vh0vAliv%vcsx14!SFPA;>Ik!S`{S`d zc#!Zc&(zk4J)#qJrU?KDrjYLP>%6cUUklhTn!!ct`tN!h_vEc#*n2AG1Q<-x1PmgR zAo0V+lj)GnaM$h^L9@SBYo$T!Cw6z3(Zt)($1ejqXmow~9*CE9q9S(JmV@ zr3EWHB)cp3XjC@r@5`3t3TIwBNaKaKG;6KTS(XQqZE}0Bw={cM3VOP)EDJKWeH}FW zEbL9Hd*7;4h8F5)AJCG1pJx%G`iAkzmOBmFff0q7n?(P77C@F`M%9eB&m=VRQ4AVK|On_3};PR4D{ ze@awKqU4wQQJ;?y}Su%Cy4K*YL9E9i<|1p;>@>BuMnOJx334dj^Vt zWc_Fn)u~6DtsZuzU} zsP1Hc@5*p>4q%FxNRzHDK^;`(! z^K{wrUY{+-S!;m1jWSh`J~0!Q*+2bUUe`lXuP6LiuWa`xl__J2?1jx{|1< zbs_zc1+&~c){CRmId2qxW}M*@F|w8hKehMSE4;`MvF~s_!Zz9Z#5*#T3r(%S3V7Dk zo{GPaTW&JvotR(VF6`~REp(P-Mm9y=+ZA5~(U~I7&tLf~%j`B@Rc_)9Bdzk9X_$)F z1TDMxLGU35(f(A1y?3Rfxt7<+uS)dAD>f{GF z?$=hvg8g5BW|Q;9YNjS5(q^?*q=Wkpt9ik~boZbg49sUcH(IicCqC)OTMCMe;)i!{ zmBD``3s!vJXj%0ZpDsJg78{^24jiTQT$~zpIf=EbihSckuG>o=@OAKoo{H#g_Iarw z!iyq{${wqN`It4?&5|ABR@EEZyB>LIn#WUhJ$lTYh|Y)1L}5(!bba?FvML!dGe_En zq9urU9*48nI}YdDIz3r-CZ-Z(FV0hY)c5jwqEs}tF0rOU@WlAz8uY;r$Hjwq&$6Rk z|CCotpEhLE0>H;F0xlmK23&5y*F)?LEpM>*(3fxsMHw=k!UjnWc*4FcoiOvR5i?m$ChSnW>|s_;e6Y_T(QR%%~c#hsr{z=d45c{ zMOG(TRboDg@pD}hZ2YIHrkgFM!EPj$h&EtEa>vRQ1r^^vFOo@ol@3e}iTZ*Wadm7P zO}~LhkV#LX3U4sB>T*sD`kxE*k15SB3x2Z6aEbN;)pwZwD2QikHX*97j+-fQ&@?*U z9(c2~@T*u4cuoG~$;QP=z2g=j1lKazoKx5i<_O)wrB(?zbdfhCXO@h@Tn_UDTx=JIYQKy2jq`) z-M$GNKJ4iH+up^DkeO-vo~ z8?HpLC2I8xu>kskwi7ius0q>w^p`p8WjHi$61(z87jyE1<7vtxnD!Oc+ z6dD|RA)1;@i;g_;^`*RAXSk~0!XcW>>fbd z?tH}h)Mmn9yHN^x6adq*vM^DFSr#;O1{ni;iJg{VmHb=mhMA@t{@U|q&I}7p zORJeanLw6wSG+@FZ_8!16CTHmkm9@*(!KE!{_OeTh9~wYNx_Qt0{zK=GUfA1A&S5^ zE-9}{%nt6{*)u9#Nf3O(JCNq`d`kA`{diC=-P5Jyg+yOL9aTN3eH@M2(Iz=M{N%Yg zS*xzfiGr=C?9`=47p1*vhd#E-25W42yjx|2eX5TVS}RirPy?^1P-AX*W<^ZbScDiR z*{-XU+%NECj!#E^Zg&T8zrQnDLBi~o<-ej}UgcLn_Tq!m2f|j!Gl?1yS4dU}0kNXj z++w<$`DXdDMLJ?J%md@R1q(cgOis`=XGr!H#EW}6ukFu#^+Wfgi3xF@1;@6c8y)%u z%z@%z%z>rS(#5X#9H7=m8KbfE+5J%i#-8@!q9-Owac~Dk`E0O@g)SSK@<4qtbs$B- zlJ(~?z*oKNoZGEtrloq=wATXrYlXKRdx0Y46lwc*dk;)LHxVvRlJ=GM+{cwMZJ1oN zEC}G=g1BYtU(R$3VIm=S`#cN0!S(rkTbXeJ^@dui5lWgb<>?06Wk!Ba;x#^o{deB> z5@oIubjoeDa8c6rTuo2|JHfs=YB)%MUvzQKk=Wyi84F{#4J>JTbRdqXK{iyQ?6JXg zGW)@FiTVx1By^TZ(Se^JYU+sZ;C2=BE}Day)!)G9+^QP@d*^L)Wqhiy2W=`f~0(cj!6|~ zwaKReQj%dD)<{$3yI8qhgw#E>{4`jm1+*FDpVW>2=DZ!gW&A>3S4cQEMX*b>OnY)D zvN~nOlN)~R!2@ zr1|JkW^H5z4I+6OXP2+77v4 ziIioem0cMQa!H)P1J5g~3P8lu@Isme!+`hI(O9y%F0$Db|UQx#RzyiXHa?a0H zqJhOmO_m$UnB;H=)`<%P`B*_Exw0~J%ZVB=b^SL z-`%rao#r>hvTWANzVK=QGavikE8e)0mkS&B+XGAA`*6Zx4@Y#JD_YeQ@2?oyF+I^b z(3Luz$HQMEGiuk{suj+=xB}x=o7Xp&Mx@AT^@%EXp;ojD5(6s($6thZ?A0w8;+O_-8v_^;EGkn+Ed4c&`g$ z=(a^$?H)9KeegkVDrsd z;)_Uf=_H3BiZKBK*Yh2Tn@eLg`Lvf+E9xd2Vu1lxg$upT$Pq#5Jd_sk^^m7NP<@43 z;npjDaC4c9NF7{jF>UxkMgF(EpAeI;E&5Q;P3v(v*Vc~rtz!YwL~qq^A8#=Ss6#KR zAKI6R3PVK0p4u8!gZvkauCNpDt>aA`R|D60CPDI7sw^`gQrwA{@H-gVeq%s)(*GL8fdxuZS}JoL%Db>CbUTQZho~uNK_JO>nK<7e`J=$ZugUsyIyl@K_=~_& zv|I%jp*|(k3=t2~l#Kr+r;Wtcc@BJou!!+H2wurIfdO@4{+$uWrW-Bp7?bhKc-I;d z`xa{21h?iCaACSJt7iRULgK5b;7lOwysO0vOO4wlR~E+z)OvY~BZQsNx}fFudfR0E z9T+`)WdrO^T0-8hm@t^`)_H)?Z4S8WH#{Icb$J4lY7R$H&fr@d4K1z5tHxhO6E~(X zTTa(g2IM4v>tf5wB6pd$cAY~0t80?*Ng?_FN3GX@a$reMxdr>qf7?%srJi;C zuVnga))_=tqmkY6D}l=i_RqAQ+~{?uKf*qzXSfshlgN~~Q>gH+SOq>g^+L96#@RpI zb?r`aIohk|iBMnn8)^9A5tvzkTkiUoenWLck+~svt%TF|d(79V7g=Ch=QO;N#9i<> zFCDVF;`>11hqt0Gi=2b~8TZ&L>me^z!0`PQG8qseesaxqUb0r^!>#xv^Nn~}`HlVT z_m(^;-^~Ovj&d&Z{k#1hKN@|cJh*Q2=c-S+I!saKyzA$-2)$Aa34F)$)@DB8zE=oL zAPl)+qiV?z|5Kz1O?j=iM+U(GNPOTHYE$~LKg64622ef`o3WlG7>9zkTk`VqLOg;A zxUQHD`3aU=%3I>Jm2&p-Q1eDZ)Ad@>kN2b2(^0muTQt=rnwy*D#*MnsjAiFv5aQgt z)o?%kb9ttb@S%g6HEEvaU;g_>y(d*AyvOs0->B*3WbY~~cL{^t&Go3|35?>7Pv!?3 z_kTUbCbN1P1{i!&%=t%nYO-$~!?843Y!#tRHHBsWmccmif3Ww~QE_$4zGy;_00Baf zK(OHM?hxGF-QArAI)nswcXxMpcXxMp_kNvk?{n_i=X~G3_uaAIUvH1GdW;@xb+2As zb5_;-RsE`_eH_FRd%-1m@AkXe{gc|-k$GcQI}4t?)0#hYoISve^pALv=kg-X&Qwxe zx;O=CZwX)3A)t1kwkcC&%t0*h!4hXrh}+0U644`1LHPM7L06}0h;err+jy{+Oi|`n z(1T56Ua0B%#`hbiPAs`?g&`xm$7Dr(w3rzAny=&{cTN%?y$nkGaHX>1xipF#c;=V3 zVy&Ea^>?TARKdiRwKgIRk0*4ud-xiH&rX8zc+iBMre1h6M`@1Z{3K3AR5x(OgLCu? z!{`sASS-p{oan=;Np-s7yECn!(O_01AOMX^JLsa;AunKXUhReY+~)CY*gqK$sWB$; zO3BP5j^*SybB%qDs)Jr{RBQQZU}vVdYve^eQebjoHAm$LTtXvW@S>PPrS8$9sUwFU zv&y^_DUQigt@HT9-eL6JEd7b3M4sljb`x8(ovg^OFNlotE@Q$ILk$F_r3xG}Inyih zN1)Y8tKt&`g*|X(s-&21WLtud({_o^56om1AM&{ymHg0~O0g%H6TDTg@Uz5_+b}Ld zJy+A&G|$jc_rOOM}VM+FPogXf5|9Oikfj&`2At#q}H?h+CoiSNW+3$CuIGq7RGM;g8BAQkY z#14+?7P_T57(AZD5Yi$%${>ynk5_xvq1o!Q-0vJ6&wwnOu9HU~t%NcP1ZK)WfsB2e>ntYZxEN%roQ)lM(a9tzS00!- zj(29cWYk?yoOv`@iBpo2MvJ2?o=4Q`*FS?vt&^Zh_{pc+hvVj}LL+cyPOMg=wuM%3 zZNGdE*;D=LaTX>=FQdx9)k5qbB$vA*Bsc%0ZYofFEgpM1bg9d$?<5fb?ia>cL%K@@ zGS)~yU)+8y|kSB9;$6egx%7~W4(EYv&5#8f?CX?^PsSq4(Ix63FIK;J3m;9n_KRa>>arLF>ZWX=sw@WVp4I9W6 zelavzaxbXCWe)9Va3b&4Ed=xdoQrP4c0O#~3@WAd#(_k4D;u9~v`iBJYBI*IshMngr6=fO*KA3wh;!NjpROks56}R;u+140Ki{C|^Fu1Z` z<#z4HG-k|qY9_;@#C&AJ7_3xyWPUef1IG@ z*1V>yrPwGJ3}r_w<<6Ev^KO#BN$w;{gE;CD=8DqH^$M+I7fWO2Zi8#ZwC3|61N+r7 zgO-Ol^YA5~gRgbJqr|gF*0>{&oy%n>jY@_Whas2epR?Y%`FXXfG_Kyh^GlYdSLPV4 zcGQMjJkpGNbiB@4wY|>S6>*lB0`FrAHhXbd4J|!XBV6G54eJd7*68TV8U7B(vl=F+ zmzV+rGmxn0KBz>UO+!uj9lk6A5Qm`RLGo1pnl}+)&*vQO4{(Kj$gF1Ih@Tjb5PErgSOT5YH zz0g*?>UaxYhBglLcW<6$hi8dZYEvxH$RYgwz@^_}()2m)Y z&1vS^c#u`+?l7le880>)>?{n)_In#%sPNmMc)qXi?ISInf=sO-y48ISxcQ(PW;|N`%`2}Gl zKe^OE`s8@>Z3!K84&zVlRIzBI;}o4I)a>TvmV3(7$ig=}luqruL32gX!i7S= zB>mj7;#Rky7RH>WaHl@?sq!{srE*u;DJC7Ox1vA zW}y)_ReM1nhk9#c*c9`0kn~}J1}0+uQELjB(ps?`BXv?DX?)$g5>}YD?|9!lh&x zw#Uv7qEBB`HPuLy+NQHbEYD5itX`8EZaq$UK4z1|ntb!|*VuV(4Yf_migg&W2m4(; z61cVmaPW##>4PsLI@Y;rlY0g@ndLl~i{GG0!;I>JoA;kXhi$q{nmt`I~>*+}=%Rc(w+)qHu5J;i&;j0L4j+E379II!vcVH^yd9`YEg?qig9r0garl zpK3zMr@+*DpyTJJh_%&JJI_Xd$i1Tr?S%LVRn^rHg5F~RBR4o#^?F{_9jqS3!ebWt z!@$MEQR~xCqT!tL6ZvsR;4)&eabKfZTn?+?3+@RWX7TZ&y4j0y>I=U_Zc~;*NHt?- z?3g~akDm`ixwS3_E2~d+*Id1Q|1i^|a@vO!piZfdI;m8hVPC?9HPPMaQFLpN81+K5 zqDQ5W^C})UT;xi?>Md>ITXoKRo*bOqm%VL?S7Gy$K$l&T6s{WFbKmW8EcTI#wh zXE3Pep!l{uLB3_CH6(edEg;h1(`Hw*Fk+Yf|azT zarXToqxE`>Ay8~j!NHuz(?&a_+RMV?+O1=$kYKN7m+>+smVPSUUN>a+y>fy57<@;}goWBB8bVaVf)7 za(%5vp&Z6CV=mTLhn?04*f`fmE-rX2C&hPO{$TzDkw@HW07l!XFG6#ExhE{=xQ)_SCnPZB>cX2p#$QjN@ zPrFS|B~)G)xl|^&R)?EE9Q6ys_(X*0kLnF5h-ANv^Reh%aiy=RJ5@7Mw}dP0?H-ly zIi5~5wmw8?xrvluy1tU*6v&jZv>Y`+g;W-m^dMn?&bz%lVo z;p4A*6H~ABH4{=0-OqD)IrZpwv-)WYnWYHLZ%h_>bMaIS!XOV9rd~J5MPa>ceitVB zy>R;9hFw=EO#{Ky5hP_Nz{R6ee}$oIl)AC{>sSZl996qzhJEQ1%{o)_HG# z%5=|;V|p@pCS4f1?~#PlDAZJ{)dCyDY!qOCC=BQNb=VI#qUXPyWi7(B!b-!A(~X&l z+$HuE>Ql|fpyge4W>jT12V2C#RVTk{;HlEi;A_i6d)e`YHYeQNOjdAG0MZ<^?593q z@~jfW=pYIspT|~-43Z0}HOfp!L)BD1c#p`}(P7<(H*yhh^Kz5D`}|DmVIe)-o;RPA zq+MIWyEH)!Q{<3Mv&RGb`ZILZ?)V!^$0DH4obSg94oAV$l-Eky>P=cX4LhMN8zJ0? z1_jmEk+|uI z6KA2CU@mV+UFPU+s?nj!vSIE6fyBUm5x4#NueS))m!M?i*xv}iRJT83ieD>Yz+vQM zq;hv^XfkE250s_ju8n)mDFcJG)6#e&z1(UbGX$)njcRr4>P)F4@@iymNjX`F$aSm< zK{}3%-QhRNAQa~UzYHt0Kq`ZaFzQB9Y}|}`*E7}&pl{BGkQR>RpH6636G>Lt@(E)N zIbUd7JhQm&f9;bV|7M%~X7oz4o78eYuO0RupQ2dH`qwGuFfA_;Af#P~&SWRQjKH$r zIxBNX&NUV&{kSAk-96N_Sxv$1*q+hZK@m#mel$( z$x%F1&}F%GFxPNfaWETZ*QdYTVBY{8&GivSR=*$B<0#d_@Ks(7$?v}!i z|CGuZi%>YBcya{s(g~|8UgpXl!UXgRq0(4~q7EKvr{rdE9W8y=^03_4cVv4zjk{Hl zvZ}!2a-_iXGF5?Qm^USoP6s35;(zqtpq6F(=mc0Z&Rb|vU#Gt0ppXU#H}6DN{$ zXB&5&GP3%;WcvGJ3O}C}#|xP5CT$`OHb<2d1B_qp&y$hw*JXwmpbau6rx)BujG#?S zA5U-md{_4AYj^>Y2mNFvVLR}`EDRW}BVdy>$z0*Iywqo5tRxgYB!m-l>9;^y5C~0d z?P*%Y+i4KK0WPZZXuEDsSxGx4T^?(%aSKNSG3$8h&6T)YQtMEbAQjVl5oTW}HZC>f z&I*=XeOD0SoSIa#4Z9NxnVenJf62Yr9fIwhOJ=fKq#2n#%Z5Dw_3$6idoj)NyJ6m(*n;_oU8z__#9PSNzzM0xo2DCX|?X)jJkqw^?yO_#+*D zOyt(O4+QfVM;}krW<6OP-aa*BNET?8-o3%2J9{hLAFy|4mK5Vgn4@0H-8$mRCvV*( zc6wv70Wj9a6|Y&-aB@}T^ls~zec;{GR!r|anjz4w)oHMjDeV9oFmNSaocrC<++gTa z2n$`A=lz4p&OGLo>d?!GeBrI43*bKZe*uyId}n*}K3YjPgfkeBi-A(qBI-^Vgh&p=9ykh+e;;qpH9R$64VA@RBUUV z&!cH!cSD>MFBtkcfxjrxe`=ejV@fCM2mOvchk2k9JLcV@oMX3|%1&m^r5&wH!QIY^ zU7o;sCdtBzd2qSG%KeB{_RVGLOAsZ@UVy~vH*k}IQ5)+IHlll6R?A5yUNO^Ng~Ak0 zdsv*DR9Vtq4jkW(2u@L+S_~=B6-6m(6j^vHmCT*$?9(34Mxyf7snSG=9LHRBM#GFa zu>n&*+VVY%;&0rB!v2U7VRq=P#$8bw9ekrkpbovG-8nUoLfZFg<-&Tu&L*Gx4DhOkq9k z&0@Av_hwEsz~R>~3;l}h$)v7f2(-2Km2Tpy#-&o+6|$*Q%4_WNuE3o2XmC2)m-r$I zn1sE)K8(UDi<{nA8*GXj;bsz@(_XtiTCU%k#eJc5~B%TqFQG^(3>Ncw^VMBo|fsP&2B6Y5!zY6k!#fYaHD3y#H*h@44y zrT$H!xuc2<70b_KLq8j+`7=k|+Bu+8%o2o{-d`8ZNBu}PU}OA};_T7p z*lG!5G4&epw8W(F1$mEjk#~~GS%ZJ$DC|Hd$V5E*yyoo*-UH`xlT)x~XzkE+k_#A! zDW$(`i9^nkQJvuFErkJ&Ctf#ZcpqND{9F+$QA({D@HcLwmd{R{P44(zJDzXd=b&!&)<&r}U*8dc37J$vxo_)OGLPGepi>&r~4pxLRYnRNSEb}-h}%>WDFCyCl#Y_kfG?c2{at&+RoJy@gP(VB=L*|7{fs=mZ& z9H;x~9u|{NeHB2Nd^(<*-G}LjUav8qac^j|R^;dk-Lm#8uJ`OqRo;h=b#oxJUp;u- z3FbmZqsz})JYJ#%Gr>on-uhpu1HwW_9aXI9_{DBNb7LjDx`#1;Q7nJ#1~+ARdi7lg z)3{j609zF&6(bu8FQiPe_BI$~X1ET$=0EC`+r?AeXpsiI^O_8aauJJk>ZA^Zn{tk% z+87;1r{3kM;R;2&O)O~*vjBLYj#l-L%1PARGsf^5dbv+?HGWfQHF(jv&|6Np^4>N+ z9lu%WeR6`#|N4C{$%F#P!J#vUbo&|YI!-k+W!GgpR1&$^c~h~B%QK%A?r|*LU$%v5|dHpMSK=y9IWEJnMHeTD!OYu!{-qz1KCPa2+3m7a!_;*(^RWg5Q(Ry1I#%K|QPhLKZcI7RB=Tvpg| z&sz7$=&&A8rfnMR*j^KdQC4p;e7<<8!I@jhuK`b{1?~W6Iti?bWn#GEA6>HNu+H3% zPq5M=-@s;n@;4m)Fvu%E&?rL&x?jcdB1CK9p6ly8=)*(T8{}QKhn9Wah-GZi%)ugs z49VDZbik4Di-*@RAROeSTIAVssf+iEfRcSh&daIGn+2a-*57`Rc!1f#ONAmF5s-TQ zIvWa-L*i0Xyao1FSxnU#y_@T|ISTN@{X;Y)r zfRFXtGx6I`U;pgDh=8PF?@4r}N#*p_Iq{T&v^Zox7k_=dfLwMudzYVFqDmpF-Q;z= zREvb;`zz@aawTvKwKC`{cz23dj?R*)DZfd{vdmqg-Zo=ZY|1w@4#ww?>D) z_w+qe7biVyJ;ecddR^XMm6=>Ca#kuCRDf_(%z3f{~-?#1t8P4*v7@aM`G<&+-ddM|*Tb|R# zo-_>*Xfs;HYg{gT|`ui*=tvZ?b+XieuAX6ne$*U%P_#dGZzipMGtT_@^Ni7xkJRPJ#5 z%H7Df3Pm(exgkK67tKQi&6q$Qr)A;}x;OcEy$a-7||G=@h zhYZ!H6TqpTG?udegG_M;RaUX_+Aj2rMgeIi*=1!GnLL?t$}IR5Nvt{Qxe8*efXgDo z{xU15SeKxMw3#*MEVgzRVV%--BS@7wLXj5sP^A#Fs7X4oMmuq_$eXpb#v_#Gh@lh3 zz?xf*F*g$bi?=09uvYdU2|+$)R`Bgb-(;xMQj1hawvB#_DknXlV(X06V6NzFQv&Ii zzeTPm{F(;C=d=?~TwaIh{vV57w7k|`rNHXP4nvAa6{vXkr#iZ}!z6EU>Vv1+b%yW{ zV+{<&jjn3+k`E-WU+Y*nSMIZ}V(>Oh&Khb)IHAd9%03nWWQa;miC6a+NN}UwLGS8T zpXve*u6hEccsaDKddu#>)c_Mc=7gvB=oEV^XsXcRH}jgbSo{VKl(h$o@I@)^51&`J zt~$jSWgqr}WbMuIyw-1}R91eSl@&^=CQLk0r!_~pVgmqp&MgZW8nMwMNEU+L)5T@n zlYMQ^g_abT`DGtl6>OdqhSNx$sEpX+7V3L9yLdl+^=5+1jAsnOiw5o|lY`2sSQK72 zh(WNd=oLc>Ojiroy+4o#tEazwd+-zQY8^FdJ$XczaucJSvhAws9X>E5eq@WhL<+*$ z!TU~AC&`;;H-x=|M*}NiEdC%8>FXXNke25jb?g4I&3yyr-YV>*e7(_T%La6r)T{EC zxKw=D*7JN6YOsc=#`wG~(N(hidck}@+j*vE-JU4*oJBS}Y#C-B`E+p7RF}*LCN=7v zu%bbvX&ypW3;1+HJl^#{H165^erF@G5Y<>=CK8ZF>pr-D^(3(Qv=D8qwD79mNxjy6 zSJ)OZhI+I#1+t7G>vbz>K~e&IivH3{_-95FY)Sh?AmVcMr3gr&FLv_!E*g$S@MtGn zXp7eZ=F;!sc;$391$Oj5?u{a3rl-I0sl;;}j*ni^6RY!iVY?l$OQt02hGefehesyY zW;}35HU5-*&*FM2fepH5{1C`%06i7}+#GY-l;Im65EXQAD!pS14bT_Sv%`l5oqg?< z;3$O?2gsI3`ff!cz4++Y0*1fx#7UK+5OF8$3ZS|zTn*5ByaI`F_0RX<14MRr@X0dp zSJfWOPAFr!q=FO%qm&Rw#n?a91mD~A?ufyius`SomPM~Yq+J3Kx#g`(E;)MTE0Be< zjz|-iNCmP->_1U(EtPdJaTDtM_=g&2#^4MKHUW+=iz4+kjLSu6wMf2DZPifIIz&*GMNX^yM6t1i z_N`FQcA3%6g2=7kMyV(9$5AVBP=|x(R=AayVdP$`w~qg3={2k~#+)4N;5t2(9O^i7 zxq!?OsS8IouJXQbu|G8QD)QT}uMH$GZsHTIIL{J@;rC<`pu2&Si^lXzDBFwrXVX3AB5g}@EXB4 zG7f8yw>e+%oGR)<1l8a|*5KVBFG2r8wYKal|AWZlw@4rGiS2O=i;?e_NMZ7VzZVj? zJ)L_K4ZxLOc&A+Z%`I?iFH1`CxXv%sJk}AluVL`E(%Y6$3;hd*$<}!=A7hwVij*= z2TAB)T>j0_x{d5&hJ`T@X{bkB1{K(MchP-K%w!IF#uRo1o^?87aVM~qf<-m;)VjCW2^_TJI*3IEp9Qp0(GZIe}bvmj@p znmVP7D=e+$&WHeR&SR@7vzn3H?o2!R=~~Ous{k{NGf+!E3_3=}1Dx!s{&o8Kzpn=S zDIubP+e*$m8iwSc{yOX+n$~EbU|%GUkw`k|B~7o3*Le{y=+^_9zFsREXBkaH*`n7o zlh=wBY00@26A<8Qz%4DT}J;nC)Bfv!Xa-(664bmMY@o?&{D0*j11Jmmz{w9 z2Mq?Ng9mvpDcdfoYQZC}=BwpCk@LJYIW#p+9(ikWwFZLI>4)*j58kG6N1&-ry3rWZ#{Nc}Au z7+j5Q;{M-;^S|rx*O)hG7V-(_f5^&EXnjbAb7Em8gm#;$4%Ptr;z6bT9>f4k461=t zxzMdEj=v;~YiGv>)uW`PK7a6m+M+i;hi4bF!!Awmz!A4@z@^frA$`@RgV<{o+-q~n zd|GSc>zF~IbA5DJzr2WN%7G-Fn}C~x+L8|YhX>Qe_>}%^fMGmHj6yufOOsGMJoi)f zHKL5Y&o$~V4DsKsGv6p=zG@WXH+Qgd{Y#GUu-`WfYv^VB-~94Ff3E*>bz2f_9@z=A zVg5A_$OrKt3cle(yhSkMKg@zZ^;iE#C;u(P|06N|mofd5&;MJ9eu%NYDEsehG0^MmXS!TOAGgkPm9(39BivHmZ6UVm8G3KISF>(GDZ-~YSI`N#Fe zKV1FF`yPBl-pharqJPmq`NxC(8v(TV*+2ZwKY4`z-K9$(@C`2s(=h%m#Q*z2|F;nT z?`8L&6Zzjl{Qs2@$?sHC@%Sv;Z;hwtCmNpOdi~eBmG@!0-59!6pkhnLEkLv=15WqJ&1Cr~998B#F8 zA4^X@3NWbp13qjc|Atp&RWub11Lp+1j#v8|ETmZ458-B(zBFqLA!?|no_j-;=%`IU z=Y9yAH)fGBUi(1Oka^>$-f4|jk30N@5B1g)055jCNGNFx1);|$6@70!oiUi<7c1(w zJIUv|8*kI~MOvcL*=e>Qs^kR%tc*jcmtjf}cFjJ@frrrc8%XzDd4He0ZBvIL# ze_&p)ytzNTJ$y&Q_hL|H@3%OH57p<2Brf*-@VbM9#SWaAl%$8o^gC65V}^Er626B% z|4}az9uO=T#fZ4M28>AgVm{y}i6B+6FVGG724^uEKE&D$+k?_24DG`>7#bqwBcxO~ zDi7lO$5Y!JjZ9zdf8bhr?Rr@TWl;-j-B6OHd2Gxs+mG=-@51kuYPSKROhDixmD^j8XpWRS< z0u!A0qx)<`@63E#>hV+ALS9bmnRG8KQ?HAlnu5MTcMwk;gK$fp<-`&>Cr4pmTAPlT zaRF79GznsHi(jsSM2st`2!FWFGBeI*P1D?Jn6Ah|tE?2YC$VlbCsPsC;!A;QlnwLG zi$C&l_khbMk4-z&9sk6%C_bK#<8$8`{V(Q8Co1h> zGui#@O!qu7vm>Sd0dD>mCx4j?_UD!T?W;bV<*hI87N)(RqjJl7D*@JnopBk@hNe)# zjj}OVk$wz$T|Z|o4yWebJl1x3 z4-8ZoLYi~-QVQd~3H56kkKURF9cRD)tgb6^f16$Ks>&=C#-fjq>4B|l%vwgQ$Ok9a zt{`Woii~H%FQKWeh77R?JIXdTBH)SE8w6cynj9clx&`l5nkAH%KmfX6&BO+J7V zKyzvPQFEu6bj`8J5Pj|HstGj&`!htpp;^DQ{K2==*p! zm(EA#IpuIG9G?5^Dhy`rukeAU`ESTA6za@ED>Q-+Ft7R+ zE_4jx#qhlaYiQhc7ICu^KFN=x8Q%Yt0I+g1irDOR7~H+7uE?VpAU1)0r+d3Qg`U8VRO6&V2rlxENRo>WL#!Jn~z3W$BIh9fVnHI(u zv-{+rxABHxvoY2p@(1hi zn~W!KO~TH<$sFUi%s=elb>-h{Zs&if;nL6VYU+2T)jf{}YGTwU1RDu7NwKmv(1~GU zwj$1Oacr`yy@p_YL(eO}I?foZ3!ez>UMMh*wkdFEP9&T)XF2pM6x8%32ypnBnjM3J zy@ao9G0Tom(^1>z_9=?sLz;F(yDd?A*;|v3T^9(ZZp91)Zm;8`PYj~ODd0^0p9*}N z{Vm0;VTAX=&jU4AH*a3dzYBQ;YIONS3*KVo8}Jmt+)Tehmf^D~6RgM;l9s%hQXA|( z@rOw|dqc2_8V=m@4adZw&kN6(RO5hnh^FnLDm^%)c=C4q74};YG(r#ui@h6hyBR4y z=AQ4!Kp5IPdZt4VV8Kw{VJ0a;r~`x^L@3fD9*O=g0Ar8t`Ld?wfYx z4Q?oj=$OjWw00~9L)WlOJd8+ylx6i>S*${nU@UaEKGE>@Uj(|L6u1 zmiJ@-Vo~rl?Kf5lT0Sz@3J_TXQob4;ST&8`uS==jGeoC-DETgjQfO~5AZzUCUw&OF z`;_9WD20Qw*<_glmc~MF)LMutgcd-yHEUJ+wcfpYn(ADsn4iR2glb%ZXam^>4m|Dx z{T^IER3|L-4DQqAt?9||)p50M$V+k^f>MiyNXaHW-xt18{|9c^a6a5mzjc!bre$1N zog9QQ`b(V_J{tI8uUUWD_a`5T!Gh#6qS!WOKNR7|i)57Sz1_8;`VVWPqs^6@3T3jxT_Dn27o4z(|RNI5ik0W07T zoxP* zZzlaB`fB8UMiqD_xxV}z)n}r9BQ}BT%aI(x=-tNnlNH-}lgq`zI@v-!jzDobMh@$6 z$1ZOBe&vEXP61=#||)8P~T4E_*QdRH^8c>y)zc z90cR2MTuLKnkP1 z|GeSQMI<(M;y|}^Xe*9~xs#Kc+^uyNQ8(_KkI=@873C_*vFy4`eo;S3imUvL4| z<_o&muFvEVvk@AF7t_Tiq185O@Lb_jxRq1cZw?z9CRc|8<`m}E($|Xbq1^UwXh^KG zs^7w72YcS)$$y|`)rq=ZBeH6r%V{M$xPIh%rP{jOERSWOxgAiR_MAU<)e3lgkdP(1 z=@|4aA_nGaB5>+_Yj9eGElPP^fn5(H;{L^&;b>m*$;pfnanVZnGNpSjJ^IeT?_yzr zaq@P4r=?hNF<3+4C~i}2v+{1w?w&0t(ypMSyD~ zTv;;BSuoG&4SC?R?aQPWp?IB4QW4b7^0wlh2Mg4-gq8&_*%owxiu}+vZysJ6^-I}= z3c;M6k4k2+NkZ*N?_R*t>F5gsuDi-$*fokY$VKWxa+$|~MttNV++zkH`S|YOUKqjS z`y*>=%!U7p3Zn~3E01=+D3o}tjoV(FjXVu!w&o(R)82Q*j{`{_*qtUYxunN=Qr?bt~WXW#2UF(T-ul<#R|9i2V(h&e_EI*;!YW?p4bEvjodE9u%~b!H1g*I!D^qazo3b;58O<2}Z1 zWIzd_tV^GclmZf0_5&lFieS;C1%x(EiUbt zSIOs;JqPU(1~sJ9{XTLo1P59~%H$&|W_%WNgp!ZnpzQQAHsYt&73Y%W9bS(U(h`QiZm*XS5aTC2^2|FXdQPrUs5 zjV{|KjEF$y3I)9Nyrx+FBtqM(;dr~Stb;L?^ls$ueH?X}`eRk8(ldTTyFmqa8czH= zcO5wSpdAj!Ld2RQ{b`J-(sgTNpve*H8@jc4e@~lhn-A5}2|W)@wC1K@iC81>C8#>Rf~|$+L#zetK)p zLgO^~)l6&kJ8*>^DMaV~feFQFZNdMtz#a3#;pC?INtE%+?aW5_oW!15@)E?x?zWc6 zRaZW{BilOs(F~K?{UWZ;y*17B54qe~#2Gm&`@R}s*r;;k3n3&ePC{TJSOwn~YDV5*UhQT~WYd;v7@cG^RgC=HT zGDBe;tX`HA49mh^MvYIZ{;%gIPux-%%~ z?dkI((_IwRP>`~XR+~I9$a>{R3KCzzR)O_0sa@TbNv}=KYo;#qEzgB$CIaK&j_6;WKQoCjkwGMc##E#hw0X6`ASr>BAD`t)4WpG2n|T9y zXO0}c3+yP>T2*ZdJu^7F^CrIPvEM>hUkGifr0ZR51zd#BNEe+%9GGlsQ=9NSpmUNK z6s3{&DLc)akRi!_+~+MvR4OCx<3EbS8)u;qWLy=`Zm)lzV7*0IVkzY%~KBlM)(O@stohjf`GH8uy znydV65O?oNDwc8e<hSk#^wDvdMhz%9VKVQy(OV z55l}cXh{L%1_QSQWt*Ai$ue@#xSOiqXSbnwDR9X}G%%aNE^Ys2!Sl;A_$wnOraO28 zTxLtoyoWeysuR&6^9_d5mpK5V(IXYB_5+>L4t4hK;j^;GQ>{v0r>HdxH<}l*qGDvo zVgWV0ygQhFCxk%-Y29AUZGt1#VS%8l=EK%GIY6HKc;v&|GqJC2u<@Q+LxaauvyLrQ zXb4tg(51+6{>#O$O$4kGY6jA6r#L;&unqmUmz+tMfIp8fU{pW~r|OR!)Rntl4R#+K zcChopgfL^tQD7xjt*F}X&u~mbTiU90(KcCee!*pm(WmK#<*DuF9J+uaaPk-TELl`^T(!c=`d0hUiCFskQcU4RK0;;c zJElsFk*)0Nm93YUJd)dal_u}$|L`n}*QJeKvSe}Z=5X<6P!naTT-R*7b{bAG^-Ga* zRc2p%ifVW(F6QoT@wqxfe4+ca6-V1`(NDRc2?77m`e6H)f68)-;^ZXiOMtSy!zL5O;RI*-){Q zIPL98uSB@d6Woli(3Vhhs43^dxsPL}Pn#HM`p0bx_LB!j8ay{_J9PE>p`hnm)~$k+ z{cjRuY4S#xHw`@_0A8+sM?4`^E9yx{IrW%wDN~)u5)=%G{u*B$P`0m{oW(dPa)U$L zMx2+|x12WZXsjGMQ5yEomVGGX_}<@O}@N1DK5;wx0 z-e*Uw?6O*skF}KPV@=9Z-}AwC4F zU_l@=a&Xr8-P!;tEM>Ufx8^54!I`&Z zbPFW|tm6l=$7HV_DfI{gqe^4i*XI=nle6$wXNi{0EI-L8&{QrY$8N&nfpM8;BV?uJ zQ58;~;1r$$nCIlDMNAG7Ws!;o){{zsgGN+nuPW+p1BO&dBOL@_%`*JSqBA6Pnl%D5 z?N*IN^qWQaq!K4pbOv_P>NfJQ4_ZOPyX+AQZ1zKN2?AxzyWsioX=Eh-P=auew-z5Hwk4ba3NkPSnh?%{Xvl{plDpBOM#laIG<4Q# zrBj`wNqcz%dI3G+-tk4DJ>Rjc69NcC-e!Z^;q5CM%|rO5o03+(KS`9vgrvW_KhDCj zKa9;BCb*bD=S`8Ht~k;wegPLtwPFl)r!`F3bmlv7vt3VEGkN4cDZI2FsX8|SD3r^; z)3?ZnBp(ycS{5oeHAwzlFzzlPG`(Y9|qHKG^O_q7Hg(PxY<#NZ3pt zVG;Jt4DF&Ve5?GAUI5on0SMLTiN#lw8-ZoF1{b+I>dDj+v|-|0y=eZ4eFZKTE@d+o zv3l|>FXr$frG0!8-DvquP1vlcA-+Zg&v|8Y8A>Z$wBj7pnb}*`wK86qwnoVw#wn@w z$EVQIpaDnJ0Fjn7ukX9F?iJn9ipO>`B0(uUfdZsYvTV6B()KzD^V@35jmTkv_TtCQ zM!KHZ;x;i1Xkp)wSa@A{Ysu|s+8S`ts;s*ZR5ZQk6S7PJPijmBc~g{TgIru{`{Lw# z_Kh#^DCNu(-0_YD`fTR(Jm+BG(x)q#moKY}oQQEfc^6VuBg*Qn-nDWXe1Xdeerc^j z<3$fm5idNJV6@_QQU%7Hi&MeQtlYg9FNVvZblp`Ly$k+EM~1%QIw@$S&_pZ1>w`#@CI=2mDb8`jLpqQ{y6XG%OrO+zH&! zl)$z}jAX!SsVt(Fd)5JiwyhSLy0GT6P=*|~A(yqN@3u>f#!~Y6OjfBztl8md%~Q$L zq)p9pE+PQuSIfN%RG7gY3Z>=FLTT51OEw^yOli8Uf@UIYcDW9!PGhiN8RrWCMLdsf z>tje>s!d86O^lFYp4DdwH$a-Jri!i;A+g^% zUoOjTea3Gh+g5{8JRL3Ylc}{;98S4%TJ+;`l3wdJSLiozNt&u&6@xNg=2=9A&>5^_ zGYH~KO)KEbY*6GZm6^sCP<_ERbwEbgY2;zpP=n#ZPH|1nJ90pU&1w@A!6H}VZ=#kJ z={1g7r?Kj4^V^)2KfQG=C;tMfpRRz@bZDr?1G4#YPimVvQDqSA5cT^Zz!~c=SV`Cp z#Z3BnGJlU;h>71kWp?7(LHZqjs)ww!KB~g#6P&?II&t$@{i6y5Y|hkuZZW2GBomYk z9q1Dzs{1$ak5cGstW#uwd$mpj^kh4DEGSN+F$1b#x+2|WzF@;u!}zX6AeO{!O2o2A z5>mdKIpB-h@39hQ%VG!j5Aih=^-=)`*(4uCxKsq`%bd3+e_|V-xNOrU6r3ij46vp# z7~<3`1J=wdIBcX;4cM+zTThK2WM5>lVn@bFt8wfxrqoa9a?L8CE7hsi)sN6k#@))H zoX(0Ytoa5LL+){AzC_n0w+FVo&Jkahh-f{;5)@5nU4%l?AV8?=knVVvsTNlt-owAd zF@&a&Ff{ksfgIIXql|mi6+9nCIHXQbYj`$!je~Vx*x(klO}{#d{zWi`F8O^hRnHgX z%Q>F3<>&(^`I;DZzr?uA+wdlDAb#!3h(dh!c4DLL|3lhW0L8g2>jnY|5`qK?9(-_j z5AG0baMwYCJA@D*c(B1exVyUr_rW2!LvRLtlYQPh=j>N|-+OM|DyW(oiogC|tG~5c zzV24{Tx8I4nb5pV9IKkJ(gZheb zZVK}{ggUS;tb|*tmlEg~#1b1yxKxU))fDDT_j~zM&!?2@O;HEa-aH=JZ?2v@vdwP? zZ<$tokNHYqFa9mzmRx}qGP)WOsuRHx!ZuW=a9+V%DdYM&SsXvBM_uw4kf*4@3lFkl z0!HR_(JZMfaZ_YGuilK6ZtoAIF2S|Cl&hy<=%GvtTOaOgv~=Y5R9g88+2BkO=xs8rZP2kQBRcs#b zB<8lawFF$uTPJv}T{;bIeC*PuuVYfDEtt%mWqoHT&rl1r#v^;F25!W=n4|e0@fP0a z*g#h6tOFeu61_pGMMY_$Z&f@hjSJ#ksvkIGFd(HGnh}9&M|w+s?N`&5Qwn}f$+?jb zDia9$#v=(JiC;7E18qf;ROGRZ!dG$6HG`WeQ2`kp@EjAOA*tNb9_)VtqxIzB($ z(7F!4h)qu5LsyI90x!R?K-}e0B1j;@n;pCPo}pJdkdY!bxy%#p{DxHy=l7NSri(5KPr=MScI_<%NFS zv2IW%7i30KVXU2q;jts<*Z7_vgW}O46bG5z7qe7U#?S}{bQ@(OG1F#|Rx>~lL$s;F z#+9T73)1I`i-1Un1B~BO))cE_Ppr6Y8LgaM+{|e+h*Ck+`pa+;Ne+}bu9*!-7(PQ) zDXRpzi~fJA@;_-qFwQcCT%{z}a%qBsTixfcNC(!Y=fzo4m}9L#Qog9PXH2oppB(^6 zo~7VIqc3|8FAcxMU#%*hUoHq*eJL)(#x>Mr6)d?bk|ZV^+nvuiwT5AIFiPq zHRDtnaX-?8wR`nCihTH*>iqU@AAzs=j%B|JF1+oGT0SHLWv7jM=zR)6!(9!&vSa$v ztMK`0`$Qt8OUGQfefuQBG<&Y1E$hBo!!N$85OwOxcg9ZxL3^B4MhiuLBz~T0%3PZ0 z)dHNQ0yD#Ski2zpiqHl^hgxs(yU1JqAKTRl5P_|3rE*nRUW;7TQ1K2IN0?gyuAPq1 zHlX%Y;b|b}=7H4sEfsD&%+{a=_u9OSj>Ds2u*LiV3TVR0udoYPvO4LpFBMejs$x=C z)M&Gd^-jYs$9wK*d?_$Z6URH;YqCt?W2Cu)zo*tcKrMVR-g1&HQ-4!h+vxd}o!1>I zq3EKBDit@AXVWuERTPsQqiB*7+o-bYh;P1>d9&+>FR^Gdec4eHf>>xfHlhHeq-}Bu z1JDBo;Rt91g=@qSnhv`4Rgi3*<4{`_@oRBE=+wt$t;HRICa_hKfo%M~Z)V)(!tA-Y zjaBj$8TRL7CD%JQ(JTv@W^YFe7MMzf@Gp5uE=5)p*ByzalJdC*8+vLjHv><;U7Xk2 z2^+jaT~p#gUDMWeDh9RcNliRuxb8}DFMWAG=FkK46Onf#BD*fw_EL)D+hDhl!jKS2 z3-D|n0QS}moX@PxQt4;W?`w+UHPH(|gMT>99{o*!r$`qWwQW^k(Oa}^3@s9d?0Ei0 zD9riMrvW^%#3ulr#=ZDf&(?WRxxux>!7hZGie5A;A0D%I5?u0!Sk)S%TBf(3-+Jpj zMV>`%W?=@|B%eizXQ|GnV4+XxTDk!Fdq!@Q>5C!!x$SJJ+V#uEWR17B*O^Q|2trCy zctMn&{J0gq79Nx!s;y(~kR|Y#uf%Ka%B`j7QqhohqrNT;XX7+}<;s3_0u=C!_Ayin z9x4w5E+tv+21BFAy7T*}?;$Sdr%{FvSW??AbuaanEo|I!XbcBUqc~+fiUVUqj1@+m z*1np0kx<@z{hL&j;mw=3TA`eM+m~3C`^xPNY+GNRoab>R6U)-10fcMX5@bD3N{Vhi ziY1G$7MNmE94|-wB#eDb^UZyFE*zdM>(O9Tli(F}N&9R(Xsevj@?XAD(CXupu(24S zhzulLHeh4~lH+=(Pcz)?mcjYJi5uKZ-OE-ZPn~Jjf6Yz}$}rKlhMyOaK;U<=PL`Fc z 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%0AR5mo~NeZQ$i}c%yJ|<)HThTZ9Pca?jfIe2&m9 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

  2. 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�QP0rTa#r|nQ42j#tJME@i#=e^t|*M{;wCR*ggal5p^60Fxm8C)DU^G#*G zR7%d)oC0{YReetIbT70<-D03+wB*kzeexo;<pffN*I8?uI%EPCxz8^}m+pW65)1PEJ=MLC=K?J^YOZ(c_C3TB z)6l8aZvC)wJlnPY)vl+-`6*CPn37gd!JnC0h-p-U5+jJ|_a^KVHulgctz_3HFL^#7-IyIpE_3Vu$^r)wrzKw9>5jzgYc^ zd;q!{A5iQr#~f=*+N}%^>xO7u!O^T;CEB~E*>5ab)%n8ZFQN^9^{>1>s@Zw*ZCl^i z00_BY2g20tj!kWVPrb?@9iBPV+E=1Q;sHTAN*nw(?jk4af|uGC0aCx7eR|^4OrMGhLiw(9;z1XEl+fOIk9~=z{lK&+qSIXKw=+y63cK%fB*eL`YT# zt-U7QIt&!IVdNxKUWqxc(^~^~V7{5^d2voweP!3?dH4 zJ4)Su-zq=kN~+{z$Ex*1X*4`FrI-N^k7#-mR>7|^{fN-RELWXKLvWai!2C}h+G!?! zsBsp?1u03^tRaPIUN}qoIW|feoFv^&-rSWw5iCc6hmv2o*ujLZWUPiy-Px(v@yetz z@Jxyi#5Tx^iURDo&*$9L)6AWnV>Vqy!|XZ2#|l^vv70BbZ+VLWbKsb0U)?5rSZ&KBq2s`F(=v$ z-yZ!MkQ0<4q+;kUKXAU%vxkZe!AQz=MVUdvwfF2sI#a$| z8;1CB0+?u|3ZxBy^88RiZwvo9w{(2MNl2>XETO1GcqJDgkHAmKL|`>_E5gpg8h_7d zSyN2!>CIaThrr`H?oanIK(B|(ErEC-I!2Lw+9BN_Y{h%u`X$pwjAX)U=?5vJ?Zdlw z0)CyI-(&N)C9k`h_anM&K8KX<$6EC@z2Y70YFzCVEA{yMnde)B;i5@{!&SRW#!aaV_yehkMj8EY&yB(P9}QYuT+xiX4c1%{_+DJc(OzB1PjEP?b?es;>6G z*r40D;DOLdlxZXZqGWZv!rumT>Crh>oZ5S}>s6by-v5-6b#I}U)oxl+Z$$V7aZ7>J-;PfgTrSyoZ!I)mfvY)!;a=+b5qX%`r!VZ(no^KN=7CA#Nn2!N+_VOffZdn8G2-U@9#Zuf>5;W5gg< zMDZ8<@{yD%C|Dk=wS(S>SkP*qI$|>K9BKXwJ z0^&ekH;c)D;-4)ud#FhO0$&!ghfX=9dsx~7{2Zs?XM?=CvhEsODP65|w&j&gI$Tw? z*@rnV)>!KQsBm7t)uKxcgEP#CyfTIF_CM)!-$KYO5Zo01U4QcPSR%AW;?D5xUx|-L zcfUR~f5oQk&2|evK^YNEaN1ICo3HOZDuWiy<)UJ~|&NS%J+G@8|oATSLnvlk-nlKl|ip zo>UoLfHoHF{hVR11ZKW|yD*%$Io#f=dYjJ99+52Lsd@I{qxZ+p=XZl1GID?EUp?uU zd*S`*<9Ca{5kE_iB1dL2dsb6^vr~crWNQLY3g}Ggi+rvWSJE4j9iKCM9`bsC`S`Ta zllajTKy(BKu%gvb+vI(;W7Yx!*%DB^c8| zQhw>|F3?;6$Tn}~*4<&O=ed@0z0^JXr7DKTT0ZgVIm423L2BNOo?O4g+Mn<{3ADn< z_Ylc&Fh&*m3>@NtweIT%hbn*LXZxp5qng7w!h!SyEf8oUO<> z3ft{qW3BkEf>p`@;mz)La0r5 z_IJ4MRa3q%#WbAZIhGo|-17a>hhW>_wr##Yltmw2{&u=IOR=!lh+D^UU%2VtH~j)O z`*551;>w?9J7Xrl#3iz>3o0LnQ5=@68RF*8n5hI%J!~15Aaensr1L>UrDg?fiwGh1 zASj=`oDn0Q(k<}A8{zq^`><5dUNhs7VT&*2BSH_pOQ)&-E`DAj;_xK8 zCN+b)Y%sB#gNr@_DMriO+t$Y0p}Ng|#=vkcl1dUuvlq(Gd~Y7l^~IlIb~v28 zdNhRs`HC4(HT>Z6F;>RYU=6#@LtvpE%e{;EGEsWo@jiE9NGy%c zWaCDZ>$i6jT;89whLc${c01CJ!V{-Uf^^H7@~1d~l6jJVmH=UuY;S6sNoC+6qum6V zZ*(?iDy9aFB{_60;u%pE34d%6i$#?55}%+E1gA)!i%9e;)TSye8oVbHojnpHPo>5U zjHLl(_Tqc?`Z6V=wnky}9;quOlpw?MS}sTG^HoM&(-~H3I0#p*L7FiQ+}o{e!6{l3 ziXrTW_pjE{C%g>0sFSJ5wnJ!QM%yWZZvBnp-?hFTsoqj@uD@EomD8$lyS{J_es?&k zBm3Is_DIMtXrU{`n3qx`<0vYL8csU8lpl@Dp2DKQ(NV-LOhI@xloHqE0c=zijLam4 zRcre%{&BQsK8KOzqoSg~^h)Cek67{kt@=Ft4}~ZGLx`u11+})dmt`E+#f+}{{Z&7y zNZyWxNrC%8gGWWAHWO2(r6N0hlV9zck^R`Nm4IPwoT|FVd(IHBog>UJu=_srn3RF8 z>)N`>`&pE5dykO{|ND^(^`-1$gFgd)&XtLN(xK}`=X71)=(x4NtDJnM{f%2kww-<4 za;8>`ESD2Qgb@ym5vNp9mTyI#`TAiAK2U8E17+1aDFALZ%y0t}PLa54CSZz6LMex_ zLlceE2L2IjY@}yPX>)P5R1fJIQqb$Dp81_B&V!7EMV`UEu;d^L57;T9jin47yGK>8 z!Jcv&Q7ji-F;}P4oz0VVjef_Yo9CiAQ{ZGD)$THW^oOE4;R2axL$F&=F)Y~_JbW|0 zMxza`wpbmIR&EVXw@d|%Bkhsrz=4rd`y?!B62#pf4G3y{PH|Rq z*kMW9D!V&ElM{r(+0t6OhOKCK8Sa)Ou23?Zy7p>{5#Y-{&IO0oQ$Qkk$ESWgA)A4# z{M?A*=(87D|p4+&zlD>2;u>(nbL z8LIpiLzhIX&d67$tSxLXXQV2!F(>~9rQov5(mH6|@BDSsRNQLzYx9skNLVLCU-TCy z@(-)ez1iDMTZE=gO=gjW9X~1z*WC$@x)0LQ);EdqZb9nnCri^PXYQiNs+<$I=AFgl z4@kbTa@ELxp#m~F=|HEpd#1}ZkF~#Q9n!3IOtHco*46_zooFn~E8cakQQC0!inE z>fYLXotvd!HdaVn>k>oJ**h>OOJ^Z?tlql!G}f%o*xhtu-M7KT$~~SJS*qMm8FC}> zBXR{dBA5y5FPFKLQZ$Lqy$0F|hoin@#YilUiF$|%UDH{XUizYrFeAGr`s~5ILb}DM^L0 z&6D8i$`k<$47iNFmuIoyWf9A-cP0W<2}1oj4iK!9EHkoww^0nl*AV469l7LbO=z)d z()Be1i`tWy_c|*I86J>f75n4tj)4(O?Ht=%WI?s5pEpl6B!nu%odI1mbp8eD0B?r^ za5g43$S0ixpyD3_cj2MlAdhL8P-i@2375GQx2xWUj^l`$R#Llr)4Jg9VVG-0d*2nX zWCxjP^Sh55o_ucT(7a@K?H*9&@#(J5#F?Dxc0X?N(}6!#5p2IjpoQ4pT4pV!+|p5o!>3jK(#xJrXxhgsF*`!~1AQ<$rK{0{Sk$w;MJ)feN68q)?W z&zUHR(?6S#?(-VNp3w)K)Ek*)$pko$fNkvDM)B33r3&d0<{)W3HqOn~ipH$tXfB4* zvN-TIjprtKQ@Io~b`MB|N3}Rt%X3pxB}O!A=*DaKGFjQQyX32bZBFR|7^Vz*N-W$= zxYz8dc}Pp+_POh$isfg#XxzF{siY|NrjS%_lA^{Z3xv$XK+^atx~s`WJjY=2E#pQUAgjO6}ercW;WO5E7^3!%&FDm0AT=}Di#lNaPpZIeSA(I z&Ns;YPh4t7D_HWvKPrx;P+dU6%ms~ow0LEV!#0;t?z)8OfdaJYm*g`w3BZJ7f=!p9 z0s*Gg;h}u}t0QhTWnNX|FU-7M{>mGuOanx_dHfD^=k^lzbg{odkb)$?4;2y#%#+kU zu1b>gexCwM1odta2agCn1RCF_0v~IL`w^kmULy%jeu|`Q!NtnXFlCGRS49U9b`8hQ zmIIZH393@AsZ_M}=?ZO^^1m5H52oT_KHuo~;xdO=PlF6)IyGwQ!lORva?U7!DWIq8 z`u>%W$|*ZK;GqjtFR%aBt^SiMjd|Vpj`dz1IlIu2LQ=*d^6MExQ zJlah9c~df<3v$t3{_B0l! z)x~)=4cZi!R7d^vXAP*mVq6Q!E0{P`n>|QuqE!#lfdx!gyhS6YEgvgDCNq_VZt7P& z{$zWih!MxbC30%wwz=8!PV*N`epL-7Gn8-v_4V;kV0#8tUMMPs{?MYES_0ccT$33^ zr)^yz=H{N9s$f<+5|0@)R!z@dP$x!`%$k2+6o&aFS&t%$j4mEU+2RjGh3{NLEhu8Ly4GS7iuh@<;R`wq z=p1p}apjABviT)+)6vM*=qDo@kVSYT-FuBTB;8A9DK~u`)?93P$*HfBG+Csab{jQ5 z5MOGU7b2c;a9(!6(~gNz;~=A_%=N)tDvFl*-M4QJO{8=Ju3tSWf9EM|5CgtmbMU5DpO98W$(z27)gowFl`I*Aw1f^3h}Ky>5)!vJmt~=4edkYZvARbVxu!+^D9GYdN`~uni@YY zEaZ5ZDN?u{c&O7bqv{vamO840jeIgz7=XFrD;0mZm4vj_!e$c=ZX4p445NE@ zhd1llSt7U@PAT~A&=FjThqqY7wTj|=EK`OID>J-`yduMERP$|2dJY@vlp z(0_5ckwB9F`VhSkX!v24>s+QD)G)#K{m=uV5w{yLPl?vQfk_FQQcdE5XJFK;xfuol z4h0#uO>&!*=0@QQTUcB{`Uw#TyAS%4YFUBr-sp7vZM_2xzNo zJqzKuoQ*kJo_Ar_#Y#3JX1M6J;jj9<)N}mIA8XHB$ zY{LG4Wz*z@Lq$&{q?3aNJ>!Ew3PHHeMr|U#44y+u8MUG1QPzGfPs}FW6xIHbJ|~gX z3W*P++$Dnkzcz%^1dL$g^Gm9Ela=vxTw3&$^HiY&b*P63{Gj(&mIWkmQz@%1`tYg< z8#7ms`U(X&qmd#_I;e;>%B*)uKGl`=`o_{=$m`OB`Qk=Z5FH~Vn#u~aiD*mxZ6;_AlxtIXp0S zJ>!WG{s0$tl;xe_&^$oR^zQ}6uG$tzlYUuu+xwX$P!~{nI7lOQ^(7ZtM1*28oq^vzVNysHsePr+EN(eQzS?EFyVC2tjN>_{1JL zbFGqp?MHQvU{Fj=lG!{PU1@%AKU017JHI|;)F;l^g6;#QYMQ_u=pAc>i}$a=k7`Dh zKC$#>n#6|WD{#6C4)+4u_LiHp=m4oiu>0BZf-VIuZkUriBwe>pVEh*Uzd-?Lknzxl z_z-l$ERVlK;3!h&=Qb@&)H{Vb!*Nbg9ahUt2_d>ootkm?zF6QeS&5$S^Qj`zcnWE zC@H1o4v=u9$DV+J#;p{;0ExOD&%4aL7gdeL*{ZUVFeur$N}5f|5Jcx8R;(>`*g<9%>=Fe@gbpEzg=P8$`BT z#6|Y`3(w~QhNnoG)$ZW;1~i0128#ya1V{1x6Zl`KNr;ra6N~-QR2H>^Ogoe9-cU;p zNumQRj8b_EFNXF3<71anJUh-vFF5xMIbWyz!!!EIK)D_L4-D{~R0bH-A)q|cJ# zxlVrH!HNv|X3a<_1~_P-Gam_Bs^ZtN(hVVr7g5V9mYOHi{oqfutNkiL9i}`WJ!Lon zLyuV%=Td$#^$B|TaybJY0EM@{Lhr}i5R&QzND?b#L70oH(RYY4FtG(+5s*BSo~=CX z2&1j)~OJ{j4VXnbvMY8hg5jtm9eF&+Jkv}r}KDQntjvaVZ77+Yk_ zJ)@EwO!Q-`R|99NPqxLR;sB~wN$R=ER|-QT*!=X%2%`cFHt3?5nv9idtoM-MB=~Qr z-@7#F>2hHoeMKSS{N)oBx`k@=Bd|N9ka)S#3kRbS@2$1~d=Arn5Z*qpM;=>ST!+N| z6}G?=#yB&!FJ0@qy`6Meqd6EtuY2dV2QyU>`%-7nBgo$Yk7$hBbc{Z&4=)E*jle|w z$DOw+Guyqs73O437(9K6MK;h5UjvqaojXO=5TdJmCo!=tmExQo{dh2P)2g@gj31PJp;+X>2sci zB*DxNO4{zD7qn244m+Q^winbW!yhzFM?2W4d}gLgv%4aWleT;=LwNfmtFF;SjRMD& zU+9~LF4}C{SNV(n-l%2ri=`b^wcU|X9&Bfl-=LbhRzO>~9OcXx57VBWvV(~W4bhz; z1GsZt`0WJwHNbTrW%JI!AQFUj?7Mxib_2y^h+JBITDqZ#ngv+1YMWdeM=0OtP~TB9 zvJI$DP$#v?EMLU{;D{31fLcR55*k@+RH-(ukKz;!Hr^`wCjeL)S=2?bI=Lk9noH@& zQK8>-_MmC(>7rs3L<$=cq~;9bS0gV|<2%`8w0QCeDVa8!rAuweL6;5wp=>^->iUIY z2?e<(=oWXL%^$DU<(HJxQsOl_Sic(Ssf8Qsljgr}U}gX;5!z4jvffYda~Q~JbTT%v z4L9WgwM{TTfSPO^GZrd~y%L68I5b&rSWtZ)5qemcqkil|sR(i5f1}(RBiw1?$!<80KwYda+vG4`y&q(W%ev`?0N4%Suv zQu|Fi-Xz9*$%B)Y!6t{Bob`+Q@8nY_A#&!NQ}}(@_G3|)nuHY19DV`ByUpI{mwpWM ztX$$vHjJy1RH4$AS=Xf#QLpr8qQP=HoLZe*ZN2sqh5E>v7PWO1 z#D~nLH5a9_swS|-90i%vv#j;qrss;**z8q%R>}3$+HW=OC&>y~Z@G*XuQY2;a(*!j zetj{nlh1D|*q3>vd8ExQPrxgPfx$c-s&tj3y~>RD6+Z~p_}qxq?YxzYRtASa0`qKl zI6b@MlfjF>P}-Tz7H<5ifnezv&-k$xWqG@k9)Ep`w(NH&Q7s}QY&|n8dpQ>v4yK-`3mG2X zoBpo9>9B%iSAE5>xOWkmonYqz%$zdaGACv>eNz3+YKUb}f!@qx)0_9i&nwHI8@Tt` zMbM@|=J>2T*moj!yjzSeyh!!v@9-BTz4&cB&hZ9o$Atrv>)feIy-GFT`q-8@=3t|-FH3IP|m{->qCIoLmyH|5$XlytuLJ&#?NwW`4o`t zQPcJR^w)?TF?3S#M@bd_%Fg2-0G0xbM_WQ;EsQJlk`DZ=v2X!sOKrc1EaSFb*oROU z;j_qkF8b@<3E4Lz;E1ZL9Svi<*1g~*bW&pEjG9u#sr-wuAj<$(Tg|7~FqBx|on~9h zYUZhfvOPPW6H_+Anvu~f`|E~T1<<$>+emRe5?_R3el6#E)T(XAiaEXNXGqwadcdY` zn(S7C83hJqo%@E7UX8e<=gD_IF-hhO-ecm!l+K>E$)zJ%raGOVa;KOdebRrrUJzOp z`W_@3zsky&b2`NKnY1xs_vE!4sKQ=qIiE3Ay;c*_D>dlW2(B3azFw11sMr@iK*W0% zJtPl3Tlay27|GO?#({2CqMVdOkd55CbTK8z^XIV+zs|MXS4(Ib`~@wezy%~XEj>k3 z;9g3F#aL+_ySJ1F+^>6Qb+Q}1wDD5}EVDD{R=j^bg+lgGIi%)pw3n^4=7$ugEg5{_ z%NHkBq2>5W#A8B|!}%<4Oy2tc*N13SGUy&&xtX^@RZ$PKT&x+E@}0lZoJdh``Ijxf zKY_BV*B|RveBY0D(oz6!sn`75i(P*5*+%d%s~C0FFCSS<1u#Q)vZ+Rh6>t>r=$!hG zOHm#;>QNOraI*)kLVj%T++ zuXx5WMSu=w4O>~ERaYcK0oe_LXqfHC17GD1aK&c*I!6kLq_-=lT^rL|JG3FOIs!qg_at^?@`B0)dQKDoH=p~JD)mg2 z{b^tZO9BvNAc}50=@U_YmPW#Ybp!>;Xo51SnVm>@h?fmB5~)C(WbCt(7WH{WGP)JX z>;Zj&Zy)KRf8U?*M})pa(u~KjlYfuI=TK)IWfnxWkE#Kx+go;2In*7F!DNbC#}Grq zEZP_$xkyJ!G-$0_IqyWDSV%RKGkkkFei~rS)7ajTIRG%`<)D2>10OjkZk%<`2@@^! zzvO)inYdnkrL(}mlblxM{f7mk)$w_0Pw#jK=a;h0ne0kFLxcy_w`3YxW68pK(1YVd zpalhSt+`Ked#8>l7w;ji*h*@`A-T0)(12PZwOgjnn^c&rmWp%N&z7+EC-L_Lci^+n zAN6+Rs+P8VMnQ^bc{Ci=q*l_6>@>dR-?UlbSIo>{Z~Z#^^bUQE8mTSQH0LVLQ}^g& zQqtc1lpRN<0%ADh8PBFKX8v#-4TAQ5)Oz4UeYP&iFE;tQC=;}(8z@#YShPUjjz-w6 z$tF69MwClcH$k-rxqO}kB2x^QiOo^0YecKd9@p~sCy3h;)l8&uVba`eW4W=&%jD!X zG1nRYrrp0cX>G{02OY191vR{#!!{LWPubd6kWXj-Q3;qC+vaAed2)j-5eU)g#l^w7 ztCFw;7tG)cfuXrvefI|S-HoRa7s5}nvOXEm1#Zu@bhzsIfN#BRJ-f@W^(#%oc(Xy6%|oy06z zx%DLA^aTOwnHsj3R!mZT?9d<0(xhAwp%;NCLos)~z5{Nz)=)khhEU~! z7msTtdByW;V2$x+RYiW@sOt8YDzccw#8)5zf|Ok>vu`H-&gqaigK{Cv6p0H;RF1+- z6IS=Y23&8JNDQz!Rz3=$j4GgV_AD_+h@tNUg8la_5!q zan>3OTHQ^ETBr2_56-l!hvtv2gb!EEWcYKo>R$^peI>+|LXKZ$!MB*=j@X zm)B`65ijqQd;q>~c%VSsp^8j2yWa2Cybx63rMg$iQ3sT*ni7fnZ;~y74NDIa#}E?Q zCTK}gIHF`##j!>A-b#8|5sE&8A)`_bnG`%pLI8{QRhlMW)W(Y%Td$W#XwpBM`2nYC z6RPpf?E2&xjJc*{=rLQ_WQ=rKSw!9i6oi~EzPEPJ;TRV9wUne{>sLSP{(cw0F+J{K z_S96OgNSD?>icY(2WH*W!Tij79~@5Hhc!!RowiMKX&@Z z;;ctz4T&jGXQSSmnh2@Y90t0iEwid5%%IOxEy5d58I{boN%G;;d zh-YE6*M2xLmF^Lti%1%S$3NCf1Z}IsBd0J^7#B-Yl$n8E{?c)w9IU2a01FSs~b z;QH3b&N&|ElmsL~<}h+|_7RN6j8YQh&0H>%5uh^C!GXzXyx8A!au|{!w^eOg!&)Po z`m3s#HmXCI&tfkP*KK@sQbJd3j*doxvwc-S-zO`E$h^3;uE6Gf7keV%P=8Pi+2o+P?EV#lay5lf}t$ifqSHjbXr4EB~ zHeGYq4xe88yVj{iW2wEDlY$!;8tz&N$tE(k1EQs4IUjglGZI7;G-b1$)cKm=SAr=n z_*#ClXHR2{@Eb^wkdxds4Nt{V&vsR(?*rd+KvJ6ZX|%EL0Z+LesLrZv1~!~?W-bFky3qYG;V5)h6*M} ztp9Qnj}QmE?5Db$Xj<}n_;_)m(t~!Aykhz5hp*~tp&#?t^fyv+XQj*PsM9u% zi>uoO!VRR}zt}`w;ZnuPwgCh2oh%8YRn4-AbXjK}E`O93V_!xS&^1`Gsat&gaD9G+ z11|Q`eeth`&LgRJ|NCPl7OH$i2tay{O5kP2b6`^L*V_$RnkPzAEdKgwlMg5tgw1af031z<@RL$!R^Fui zo_Lb@o%Kt;(X3!`O}XT->3eT7mdjNbmSyud_u)=cm+coYQ5D3WO^RqaFQ2zRqw=Pr z>NH#x()d$EXUgk&tb8BDp`zWRL38p1g}O4Se8luC3A~j3yBxn4b+iSAQTIgYAtk+D})vMx- z)1Q~|wSKnD-n3U=AaS4Kn#24EJfpWZ zzxA<(9@Gbt$7%cF6kPaUAIgGPe<0yD7Y*K5hq5$Vlb#JU6Jk>3!tg^2nTl5v#q-TPDZ#dIKMHFD zUd#pv#53<~q-Yj!7~z(KlH@W0O8RwVGM2_-#(^Bw+~vdx)s>hYOrzswbq8IfJ>PhY zWx*@;lZLG~vC5M_S;SwCzty)pP-=qFmhy^OWpmWpT7AWIn|w~VZ|oOqXr$E3gHJ0L zbSywjG!H9jhAaKpf&9_09&6Z~5w7caIx)Vd?N>6y1j_`-v(&5VuGt6~PSX^gvsZ`N zjyUhQ;ep95sj|voG%84AK?6<=aZv)$&mP5ff_4Sr)!6GP$nHjl)__1|;we(PZ2u9V zhg0zB#~OObIo}_TLFAaVIBhs>Rjk?PvCd?y)Sp3s+P8`YIge5 z+5Gc6mT|XSpXbT#(w^xePmEID`n-JQn@HMQf*!ze8Q6i@{j~30=O$@ZM+?-W@w6kc z^X#gHGVW*EQDrtT3Q?pw`IU*90e)sZt~@^8=OUi#p#3Dz?y; zL&03-@o;=u^Lz>eUDfz~EBXsuJk8l<8uC&(L5_?P`uL1i5_|h9As*bx17RCcH{P*< zy&1aa^z7=ormv{Ov@ewXW3U41jMKC2D0b}~t>s@s!#AXN5e1G$tY zp`Q}lR}TX=@rha3i+3?TyQjo&2ILIA2FkSyJaa9QsD$c8Xu-vx(f5-aO z{}3V-su+HFVpA-!xAGaP4?<%&IWrIPIwd>0E=!PBKrOcl_)Bk8t z{8ila1o7Zx-FhqL&fe(wtrwPOxlgqDr0mHX`;Y3 za{4@bYwU_-a38Qhj5t2R>%~MY_T^iiP_j-gx4on>eE;BwVjcQ(#HRxJBN z9!+DIC1|p1ndz9<;*Q3rtfYg<8|eF7%23C}7hWa}N8q5OL6)hX?p^(>Ar$KI|7JOi z|Cm#+CEtKDyXOT@qH$TU+2ajq?kq5uy|&Du+3m@WYIDA;bLxj9`B6;MZiO{q=$G*+X}|JG_Fc zg>;qhX57U2XDE+468&|AD)|H0%4MIX`K#!chas6y+~^ZwHk!4%>ULDWarsJ zbAaFG1QN%LDp}0p`v^VsFxcXW@^U6)1q#^s%Q-nSXjySoZj+M`?l%&+aHL>~Ch=0* zp73?aSjyh$X>3}x#g~(o-%A81*Eg$3!TwRQwlCQ#o{b?+my{n=u3pDZt)0c}t$s>n zK1HNS?ul&jb26~J;D(9d=ev2%Fcm~9@8nQXGZZ#Zx%y^L!w935`ReR;h3DECnsy=5 zCA}pYV=3RfL|3*s=Clb}uI~N(;+a*hjGL;^??M#oWS1{+)|}X>{F<}Q+I%tH%C14F zm_l@E&Ix1;iARbrdGrhP@e)8rgwkqH6&VQ^DviCf+wSZ&*WMYHV@9`JfF-R9z)yLV z_Mn&j*WeqrHzN_q?}`yE@a;FwMchUfNfQ*(0V5cmGT{O>GBfN>&yaz*0gNyK-TR*m zG`s!Jr2j@vTj`t=OESQA`hjh>Z!h7(b3)@AvbaXpbXBYS-0}rn7RKjwS)g^zp6Azl zaGScc%%6eWs;58nmW19Jsh31&>e|{P@aEUJsPx`vu=u zSbK(uk!U#MO^#&1%ga_O6?=P;yj6N=71^REiR=?+A0q9p1T{%hbN5e6L@a;oelgP&3bY?b#4G z-a14$2n!BMe57}6!(y8mjvmp-BuZn1l$R;&}PNQkk_ZF)Pe+w zMW65zZ&)fIFM1lkWT&*r0URvO6~DTj8Y#!S%~8Pec}gj1Oq`5mNK+I$&=mp z;wLG}eq#fpa@&jo(<*+!g{iktdrf8Z1V&cuq);N}ZJO{^jDQGRH9Xa^#`UG+ks~aP zirU1WfZ?Vgp}`aeh)bQw;Xrc1S6cqBz3Yl=YW=bb2!v(`gx(>P&=I5v5<-HZhu%RF zs+3C?5S1QUkltJ9gkA+i1ws*`G-;w&sZvCxs(|{Rc<;=^JkRT#_j4Y;_1k-YXYaMv z&b2CNQ3zjr#^LZ361WqLzi#qcM@~{!9347wA zcXr>#HjE1N+DHQ>PB1@8tmKReTKX!5vV*JQs>hJ8l_m($c|Y#S54+f}fF|WZWZi=x z19VhQqMbfFvdTb1$J$>DR07IZdk|FLR0C}5^0I*uiTQNB72cSSU)?mgXI^!ah6P*F zPF?-+VEhR~MfG8Gtaz(oOuvbI%j=fSPi`e-F_K*r~q1%XkH4PbAblR)= z>wvut9sp!?yGQWlWSwJx1$@+?Z8O@M-$lvxMM;WCr$OrPwu9N&3k{?}^^wIhw`XiO zt7J3+oMrMwJOz&vUs^|0KTS9h=RWmb+#4-s+x|3t$Z7T{4a|Xa4J&4^w|#XolQ)ug zdBq|hZ1hN%YZA<@Dh@bxU2Kw1>~J-@HFR5CpL!R)UTg+sZ3wT6T{{a5x^C*RF`KA9 zSPLWI!m{(`TG|EP*gvtCE|{r3TE!^!J6eS*k#Af(0$9C`)rmQ(^-@yQ9L>GT_vlAh zP$si$ri0Q&EhjnmB}b%sql2X!i?1g_DzC73K262x4x>X!mtzb6Z1*M#ZDaT{+3R3_ z(I-I^kLm5{{`_TOZ<)F6WFc)V@YTk1jDHp}JpEgm4l+~GjkZ2zk3B{R&1{f32krMF zV)HGBB4Cx}Aof71*%X5$rGW}0M^^DT)7_6$UNL4@#l-u4caTkxX|-8Xa@l_)beVz> zrKcd>LCJCyeNR~lg@Rf`MP{*Rm(mV-3}Amb;M-J*DLILCaWLD-kO!n;#9H0@Wnk*O zV7fC|em#6yKf6Rib}xGoxBdy8w)sRs^jE_%4X-!5uQi;7brI)`hF4V!@_r2Eso9VtnzW2V??Zu%rb8_K-yL#xd!1+> z@<#uZ!waS5W4V%qrBN8k89!9U+=KL_zqmRf=u=YibG65f#wQUUGvVY+zi79-D`c~t zFuLhd=nE(gUSC|os46ljD`6DGKF5a? zB_910gH05uCMq3qCqwL2phm}QoX=duiS|}TeOSC;xl)+5L`5UP-5Kh&%hVKKR=Y{6 zHz{ZcOIQZY-A3hVO@6i7*U?IvK-%!%`WoHIa>-vP!#wGr&m}>eWNu6vAX|>wV|j^$ z-}3XiFCJ!$>U8)M7&dB@twltiSv8AfjE&CzUe7^wiXGL6Ctm#P|Hrk4XaB<_5$h0% zq12&!HPvtfF>5gpSHWaLjUGZd{MW}Hp;05%0roOE`*$p$8ncOr?}K9X!+7G!VvAx2xyBkCwW!<@et5l2zg zFn&_>{mX7mLbY=|C2;cDRD*+Z85C2#&9nLD=KREFwkBx{ z5w9bmkM{gK;uVD>d`%%l=fd0?ua?MmVc!n*S)MNTLI8Rd_h|{}=+=tG#*x@~vqw%n zx9XekwHmk?;hBTKmh%ln&1HWN;zG&`j#z8x;qRl) zwMgIYcMA%)bO&(#Ch%(F`-SMS6{n1xsHd^R`M~nm-mG7OVhy}OiNnDv4<6k1L-siK zACwcI2AT6@;Pg`AUCZYYG3^Q>&YWFK^igZ83(_;a#hwOK9>&K%@@b0@&r%~RwuG@e zhjKD9?ySlIwm#}Sir_t{@Hu7Ma9G3;)y%ieP;gC61|a1aN1c}*iuTtO2F%H`ficiR^zpf+^el?nLXAG z8K-Qzp|$7u3vhG_m9FmULHg)?y%#;pRS$AsQ5%@v^_l@XWX6R z_+oWaRnwT-*L%NoR3pO0_>jF$u2&J(F3!7Bzu>+=ak&97TZw(frj=Et9QNK|xU{TT zn87J+%nqN^?1h*u2M59=Ox#^Vjnj>*b{=XQXrMbDtI3Ogppdb$w`qo!(`Lc+#K8*- zNP9}&i%nYJ*-Y|xQbpP07iRgM4VDiI4wi6fj5YOAN878R8EeGkmemu%1 zvoIogK(KGr{0*eiO=V{=abc^`Yp{=I$tXrSL+bhAOh1nucF~YF_RqKg&E_J01#d4hsO&pTy28M zR&44gTJ#HmoER-*RX2Fh`80}PDhwJ|m?12H!ZbX6E$whGSk(L?h)mU7 zF0~-T@eL{?Wx#&k{7{kj#HCVTV2a?A%H0QVmM1Q8ridei@z7x6tA%I%;dQ8Ig`-Yg zX-K~}nH{Zzq54(^5@~Aq*}A=i%FK3J;=(=AteR|Q1C-I7`{Nk5&L`@<m<<94=z34cr~^y(&WE}GH{FnXjfuQ z`kEW;EWcK%Hh~)k{z2#x7vN8plO@CcAoR4aamp&!-n%rWWCv?=jeoL|Rp#fzqb|=Y zvxh>7mhEO3THDV@Ps-5TJr62+EEJ%uOawcCZ$@|Iwd`)GCKI`c#uphSG=_#4M9>Hm zA19#a+K&Pyt)yJ;^wD5Z_g1N>juSyIR{qjgSct&Ql3!+%M1>=4^|eO9=j4?KqNUHr zo=?Nvu4(`qD=n#LiUJpd1s}MCj9Wv*4e_wteANb4fOws&#!Ybh60L}MsN%XGkNbXm zIq}I&cN6IkRqRI+R*Kc=;xGC>Ela*>pXl8_RUIN}0d0iYHA~}cD$**@rlMZbSTW-g zqtR!p=DfXCSV2UHl3wx1<6HK`#@~531JH!F&P^5VBh9l-*yLRp`^`t)Tc( z&{kOFs5_u79amkU3XhB&7(Fd06rB- z?KGP~5^Zz-arL3pA$|NmSGg;Hnm#psR^5iF*x-b6R_j4MxDsFLBmOv@!Z$m4x>`AF zXBWc49YIoUUKETG=VI%LkuE7WLio?E{-oIbD%a?vS{SU6T7r zZ+Bo|UREPyrs)^7Vfq?W&~l=?b>VVCI-kKCQoT#IxTPKQt8{U}AczfEQ}ar+K$ka9 zeAzcCj<&+KO%KMuN=()Eb!m|A=rMrPm zH1r=`(FVeRHbh&?5c>IL^gVI<8p)BM5in%TN!q6#U_x#fkIQ_oI7nR1Gsl3_sS$e_ zxxhRL9T-GJ+mDKM0{d5%>59k4amLBkzC2S#;>Fh;|K?{4h}wH=nj}ruSeL`q&VH zL9aAz<)0X$w6^d6i;%wJ#%0P)p|5Mu$45-Ue)CBaf1Pw-j~;EivWqf8V`Z0mQ%|uB zgidWl+mt#M%#~y3m_OP}BLJvOO8@y&>D{f^ruWwE9Lp(Y0iIU*uL>ooN#CU5vmtzIA0{$XJO{{tlMBZJD!71IgbZ443uu}tu#k7oSk9?7Ylcq(c@R@uD`cIvY(4KR zP4@>OioQ!FPUz3?5JD0AC(CswF&7PSZG*$*X1etGkdvMVIOofW7~uTcogN6=txUCo zJJZU3AtUP(>RO_LNG4?*uGP$bZWiX2NI3j9VF1NSHE2%b%_~WsA$`f+n@6-S!Lmlf zr|dXjL1)*)@)h>-&BqC&23|)yxu1X^FhLIKVK)n)&ppIH)Hy)hKDYb=l+wLONOEQG zFR53JdDKsg?K~Ec5a!m(^)!!vep7zDSc(|LcPqI+3&9&9Ph5))dklnkZ|Izc8nLS! zmZU_v*yR$BZ0~Z0Kx(kSCh^*up^@DmjfbX9>r58Xto(E%6BZJd^My8jMd@V z)=sXj$tM{uw!Rb0S(6_Z5K&>FO^V^}-uVw}HJvU8ay*f7rf)zdMLC8KosO0KWCXsE zEk`8Vr&~E0ZQD&^_@YwZxc1L+a=Ea#K~M}8{;inAXOdivyj{2Z8*eHQS{f~|8)AHT z9D!RlaZl|piAUc0u1&5|>0(s9FXd2FXq5T5REQGX@^&f^@Q6MqV(Ol7d@m*+PSJP$ zi6L&vTE4V3{N#zk2IaQhyY8idcT*Rt7@8-Fp}0RPFWaS_GRZ*J|@CnSBo4ox1lJ76vNiDtnVvnJRFal6D57cJOYLoR zP;<<@f+WAWa|@*QZrA=jGUsTl z{?=L?GOwcl@jfF5ymg_UeK0%(0f4jsg?jlQ!!qo(TRtl&)=QFJ`bnOobr7g-Mu zwZQb2EvvHPI>ERHaT5B|g(1tGxB=^`nnc|CQB{4>Cyiziz05<|TMhklZ&pAH_P!~Uov$?VPQ(=(5Ju%#*2qTBF+T#fJ2&k{FqjpB=#d+}OEW?VG2U71Rk{L1LQ zh%6RhsV4l?3{P|m+E{Vb(T@6WetW0CtzJUTKM<%r(@>rv4CFfTd9R(XHkxMzXS}v* zyQV6WwZTfSF;jE2mjpLwnqJ~6N~nx&gY(NO=;hWko8GDJ;>dw`NuRUPXe+~-@nY`|7?GF=)&9V5%?t%Yqr_$ZV$lR!p% zUr0vePmbTkGyNEi^0`&@E$=G!Nb#HxmGOltBO_}5YMr|;6C3EYrR|wB#Ja&ZlB`&5 z&7{q>ajrjUGppBOKPj_?OLJo$mHvD*H zAI|7gAQ|f40$AGnM+P_v$~}N^>XVK3B-n7IDnj&baOY$>-Ihf`(RHuQTe3XL#|MIf z1kS~_w!0?X`;HaF zlC!_@S-lkNcziGL;mcQ|cj(q}4l~!s`q>Gt3_3=owMGMLC!8+(+&{t!&u3&Y7)~KB z6nxn}^_!q?8_yHl@cXA3uVF3JhqQKn0!yp|0UzogwmBmIbKl_~2_8j0G(;J(Qkp(o z6mbfrwXG#(n)6#ZnpNyk-3dnDbS38wj1^Pqo$?pGqZ{rbcNURtOXfAsLMf3iPh0B4bVQ%KJ{gf5_x;sz9s|T`L_lU zGAZ`o+*v)^-YS*d6SZbzpx>Pek{$Lnlv{6HUbX>@S@wy*TTV;Q!Eww-VREcIx~ne^ z$Z%^L!o_ZP{E9`*yDbN0bLiZ;iQ!!MvgWjV{fcjR!p$d|ov?D|$tzK0mf)L_r|pT& zSts$I>KyW0T%-x87XQhMm8G?BoFC(yZqHDx|Nc+Uf7c;q3K`24Pgazxx?G~w`+xf4 L|G)gdPvE}*n-Sqr literal 0 HcmV?d00001 diff --git a/alexa4p3/README.md b/alexa4p3/README.md new file mode 100644 index 000000000..b034b8e1d --- /dev/null +++ b/alexa4p3/README.md @@ -0,0 +1,572 @@ +# Alexa4PayloadV3 + + + + + + +## Table of Content + +1. [Generell](#generell) +2. [Icon / Display Categories](#icons) +3. [Entwicklung / Einbau von neuen Skills](#entwicklung) +4. [Alexa-ThermostatController](#thermostatcontroller) + [Thermosensor](#thermostatsensor) +5. [Alexa-PowerController](#powercontroller) +6. [Alexa-BrightnessController](#brightnesscontroller) +7. [Alexa-PowerLevelController](#powerlevelcontroller) +8. [Alexa-PercentageController](#percentagecontroller) +9. [Alexa-LockController](#lockcontroller) +10. [Alexa-CameraStreamController](#camerastreamcontroller) +11. [Alexa-SceneController](#scenecontroller) + + + +# -------------------------------------- + +## Generell + +Die Daten des Plugin müssen in den Ordner /usr/local/smarthome/plugins/alexa4p3/ (wie gewohnt) +Die Rechte entsprechend setzen. + +Das Plugin sollte ohne Änderungen die ursprünglichen Funktionen von Payload V2 +weiterverarbeiten können. + +Um die neuen Payload-Features nutzen zu können muss lediglich die Skill-Version in der Amazon Hölle auf PayLoad Version 3 umgestellt werden. Alles andere kann unverändert weiterverwendet werden. + +Das Plugin muss in der plugin.yaml eingefügt werden : + +

    m}~n+g}8E0 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�rT=7Vdz3mMBmjwK%)xaT4G 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°Iw0Bq~5wT0vQ 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�)7DIru58IaHrnR_u)SR*B<#Nx@-F< zD&Hw`Otc#!y84W=%I5La<)Z{G?Z8(d0oINSML?Z!9iZQ$=HzzK(#}_tmW+HM{Xc&Q zy}>wJ9DN(~Q@`Uxtg6ICMvZB}gVQ(D@^MA!xf9k+;Tm;wm6es-{JZ^wVyvY8%5{O@ zBF$@x&ibUuZ#()w(m)!-uGItTeUo-G0-Rd=^*S?qSK~##rBU{#cYWEbUb_5z?itL| zDsBf)XJRI8dG*yB$b#%zhsdE+@S2%$gY7SaLt)c8R~z8JC?{IaIMo4(u<#(U!h=6Y z@0((riYmt-~&*LOO4ww(QnX7|D~ZCk*0u9s3;`CGpR$Dh0` zrj`t-oQ2xNzejI=OgLd%hC}!UI=d9=tQ`&La6E{5ny7$83s^H); znSzhg(EYg^i2!S&!$4;RfaK!6gZaaNW!4o=XxyI5ZvqsQTLn1~mmEGtFKe1CbGW1f zR6vsIyj9J>rCP;{5t%Ph8BRTKZnY7Q7$x0Ewa^q-l(V7}Dzf8OtQ|vE;f-q!1GGUU z{jlZ}Mq)iX^-gW!vc+q4@c9UD*8zPgg!T^=AjRPJzu?6Xgq{q~!^I-~4u{9T|5`a$ zdiX`0e{A2$NRa6NmHGVfLs#tA;&EpmLX_B2eo_(BC-qo$$w1{LTtw#qSwLm{3A|JN z(}IuNR2v_qW50<(3P`tXI-M;?{V@wY`TyBaMOujCp&38Hs2|xTZyoO=*C5@0avE%d z$A*$OI&6|5$k=1kLI)$?XFYl3JNaz|d0v!V3WX7ZV~#&ol(Cl2OAJgBMd zroyWLv*}Ne7wy(>q{IVznKIYh6)7W1&&vK0csc8rHnN9$g3R`P%J4acFDHi74R^r} z9J?#SHK?HpCMBCz5n{($%)<<&TSIe*N{g|c~?j4 zuLMl3m{V{t-~1%k4I>8}}=Bl6;50hP&JuZRg*zu zP$bGfAhm;Sc|HjJ5NEcE^!g2i?XuNZ@`>SV0GTuMR`4>H$^dwL@A#OCd#d%x0OxK= zb%^nbbo{Ei^69VVuoK$RZzWq&Phb9BH;uxoR{i4x2&W>#s}0Z^T0hwd4}F z_$Up8=8`L_bTF|qTogc;}9dcL}o-Lg{ z`%SbMzD8oa4eHZ!56hnp8~6T|G;H6Rs{W}(aKz;JY}EE>qi0uj;dEoYFW<#T*_VqU z%7gA4_wy2ygZqg@U^6hvIvZO>q3W>sorP?3%8~k9nf$71QU9R$cyA};g zmk0^F1`{A{7poRpD&_D^J?zpb0|fPlsZRt2LVC)sS-nET%JVAG;twrS{o^xcH)x%l zApjLpk{w?1&c@PG&(Wl08?y~8j{uhIN2F|^ehmNg5zCht4F7M62$~Bmu|6>s|Q_lyM#9t9s7|1 zn*Bgk3(`XU^BlHaI@adi`WO8hySnvDqb#Kar~3Wg_}y8M&$i3BTfz_jjYkh3i^)Gl zupT7%yXEk;|CyvtTJ{E>fTPm+-KYZ1l@ZpkoX?bWE<9ou#vf>I93tUUNg>(=C&Ktk ziU3s9;I7{DYd;KcGOPqC*x^jkI#o>*U_)1G>!wl&v5em3AA7i7LA=bj0FKCK+Jb;Y zD7xGmDLXka6cp}P&MpF@>%c{w2(=xW1CiX2yLFo65gjX$Zh7hO(0 z_x%OrogDI&DM#3wBUz^Q;-p+rZLU=q#g+ArG&lmP}bt;4r!s^Wa1Kg{N8H?zK zBAQ>kbD0Z)+X=nOE{&TAZ86)`^B?zKXB5;JmPNbkr9mAlN+X+IZ&*KkyknLFWlp_K zc-lSTEnl{m0PCZ`U`u!uj?+bL+?fA?tVD?wCFPK_b)4q?;%7}r{Vu=l>NdBQs_ze= zht?KPySlWUDhYa0hwERQYJ^R_xwkR@Tvo|Z z^={cGY_DuN2V=uCR@c>$%3mHAk~U6nq}Y25;fOx7CDlPRyVHAwa6lpYYHa&QNqX~1XFy|_9HBzHbVixkxFU!Y` zbIw`uMN&ZVYAkG!E!g8E@$C{a{Y6*T*NQ6wU0+`vIBX5nkv(Brt*7N51KmX^P-|8zXR!Fk5_qDHm?eF#Z3IaB1dAB>N zg>29lc2|{)+>%`+)EdXn=&{cpGgODo(kZBS5xhaMux1#hYpL(`B1EH@wpB~ZIH1SC ze9ESVThIg7*N-=feT(V_*rPAP^wPtGDT~+DQkU6W$C#mKw%V5O1#W!0qwq23oAgpo zG5ed3o5>g+DGR{Wz&SU^%t{g|eqk^#xr zd&IrI70RrJWY#204wQAj`N{W0+jo4L=Zp>fDi(9y;y0M1#eZv4%VK8%l# z*ezYp)8&&CRv>1mS=&r5ePh#~+SpLw{wyya z>34kG-S32&!M}bhd5Cp3gS*%5#E%0$G#ni|KM?YvB z*nC{Zfm(yg&)-%ZY&c7587P&p(w+(SB!l8?SIYma6vc zGS^_7%?xAS(u+ni!v5Gg8()tc)9jKiX>I zW_GqV%HoEhq57da(MEM@K|vR(-GA}KuOw=AzngLW3-N9Qb5oWIihal0nsU%ThjOP= z*lr^3HAB54>575gIm~p_OjznB21Ap~arhJpoZ{vVmU;+qZp-Y2L2j&5TCehNjP?g; z=Zaf2UqYvRf7x=q<}pwFQ7^}olq6uaLjxb3c8T1OLY`OUCxr=w>0}&Gjf0>P2%~F? z9jK@u%#g7*;u7|38Q^oC@MA5vIV%6Yocf4UfA=QQ_W~oK=-i0ou?9bLqsvG~6a)fy zVmVK+Q&f-&!`-#k8fIpy9(E(I@)u^uZWWF^kFZ=vMXN-dQBMen!^d%Rzq5L}GX%U~ zrvCnO!82E$mz6ygU!QNDy=hVMj@Ra3G))AFPH~_$q|~k)s4dl;iKqu4)2WRaCOh8S z0}^lsG?3k$!vu|SH%;)HU(WOLDb`&e@t-7BwJ$kEOG6D}k{FU<{~Rt6#{SNA$(C5z z2$&^oHB(S;&3e%v*Xy*8vvp4dh2O~-bDX+9%>XYDf5K1@=I;N zB?_Rn?%nb6;@C3E<0<=tf6e<^|Kvm3nbZE~^kZ*2)Jd{~M`8+lvp-8T^(UDP1@c$G zyiGNoO{E~}aF3O|?V3hPF6v#A2a0n6qj!E#MNSuF_r_sekQq3sGVts297%#B>-f;@ zXm`phfs0y2H^T_&)@He2ldaFl(qd9${$eJ$QTiLfmVn5JN!66~uNZ{4W-OuVr=aRg zw*c4OyuyYBF=RwS1lQBd_Op_B-;6_H&ndFvm}vulMoQbHdSq27O1l5s=STOlM19lk z&K0-0mH})M`wi#-yo20J?FElAq4%Y3VO;+9>)&929!d8yYwk)h&ZVdjz~Ah4#%*5!we{S>=2EoP1#+&2hPu^4rfD5>Yq zNTrX0dq%EnK*x)Aq4UE}{Sr1?nFSHdv7I6@rA}Twn7k@+ z(4%6d7We~}#rSyc)k`~4vVH@dlZ~<3`+x=Ee1=EPh|;~C_X!WYN@{Ci(2Ui9>OkBI z$_VtY_uIM&GKiQ|%eeAi-+Eg|BZlNW>k+puvd;f5VB#dE;x#4({epD){u_NJl@!LCwgzbH{1 z3=As^s)HOTdwvq|jiptGzWpjYbS)ZW@2AmhR)~pdtjE^Yq0Q8BSmne-1xk_oZD#re zH!oxl8-*6aFZG(5W<%gzF2vOnNc4bS*ELAdg|{Z>xig!5tS%od7R-)lC}X&+9k5l? z&SBnpsAmOF7sFS=`#=kGxLF`(82p>#R%fUs%XGo%as#s#<}-oluVD&qnqabLH?(s! z+)e8~#Tq{(-kJHF)IVBr_GN5j8bkZ-kL=2F1(p|Aiy2qFF)&;gD7f;xnwepAqlF9|Y*! zll}hW`iA({6N4uMh)TYB8mL+YXBFaXEl%5>Vy2}%2ASy!=??^4U@UJiSa%=iMkF&24eeCJxCs(zE;GOS4{nwwT`WlJd+?bx4ehyG& z6!o4TrJ;mMdQ!=qwiWC{4P2!g!O9riQx%wztV+f7ca5-3&s0L4*M(Y~PSy=9hZ?*L z#${AWu(%TQN@Llrvqh$AHBMT_4Bv8X0T~K(g}ASa2gJ~)Q~=AhfhG< zqv%#;_R>n2`rp1g#}}N>X)~TkVsv$U94-Q|Og*u2uGo^Gvvv(iVR_z~$GVhHs|(|U zd~8oJgp1~2s}4IehYpL@spo|qhhI5i@R!~g8QlmnLeK( zn4Q2(BS*3d2z<*FjU%tDhPV5OE6ReXcZun3PpGGC)n9?$KfG(=zW{(~$WY;OR3K#= z7zp(A_SE=hldEOW?hL8Bd#if0CPWTzKyYO&2zK@*mLq!_i~W=!KZl~ zAt%T2eX%(``IVcS>^~RSK+|ulL%kpy5?N&^LA3&6SZnB$lFlk~A1K8FbgjWzkyXK+ zETN9@lWR%aLF`iRX+e5H?JhOEcRP5mxL1T&W?W`?a+q% zzqGgU?GZSeoT4my^QXhNIt`+!K_J!Aw6r?a7(8F~3oZz3vu-soDWZ+ot5NA)a+u|u z0bL%ru#DZbv(!0($aW&H^&m)NHC{6bj&x;UXE}@_-U&XAf`E4PU|yRRdRuH?UXy5 zH)qPIHEFrvJme-MNIej@p65UBf1t3vIJ+?MxaK;Q-4-QsEAP97a^%z7XWAUPmGX!D z9j$zf@!c{K@=tejW@?Ci+hlo)6wCZfx$J0PpPAZBrn+*&6u}#U(3OYFEgM1CYbKEN zs%&vVMpr%503Dc)#*?v8OeOOg(-%)K8Yqdqqmgrb-=A_L9CmiV^&#IYr+OOZX&u9} zu?^EHv|@&PSYD}p)ul_*Y1y8|2O}Oc-nLQ@!yRKk5YVN3Jt(nWX&e-$Fx9rRK~*U6 zzfn2$ng}mf@IIqmX?#_Bxvxcy^3g4k*X&>MQp#8(M9!3Bma;*ftdBP zpWjBAdP<~7JgDNmKmE^g_2XmMbH%^xy4KUK$);aN@|LU{&=rPKjIq*-4fAw$oc97X zB_H}0A#tjU*46o_%fVzR1L!o3CMwr>wigc;g>eZ?vIVI3kas>VXbo1=M^zR)bu!c~ zD2rUDuiMt*g4@(jyl8uu*Tp!6<#x(rQK0v14tEbAzU2JV47YTYZwdP|JNUv&CrtL}nE@?zg1 zBm53irQIG6v^ESPP9EbFxKSi8rBdfcf-3LaUzKk9y}PYDFJugc}w;Lz}IBP}Sn?>Z;R;9+I{xQq6Xh z#nX0nS8qyX@{!heOq^bG`?y#Uo6up;_2`KemO0( zVj5OsR|C7(&od5eGv{H;0SaFI;<~s6%F}N-l>DKf=)JBu4O7EB+&IpCBAy$r^E|00>lsV)a?;EU z#%uOt1v%Q*wX!a|>6UpR*~nA7kpS#E1CX_G9ZIsR`dC?KZ5k9HRi+So@I0xMQSy>8 zo)7YrpHAk>ravv26n91NN%(4Ay`(Xo+$$q-MI~>ab+8@5mJW7FlIxo$(0XqACtwQb z2uk#WuSB+{tzU%R+SPq^@CEwX38ZG-#&TZ8 zrbKvV{L}i33}WZKTqmWW^yP&PE+h$E$e2w9_(SC%MhGyaCZ#%F-ulc`a6XZs-Qv&} z9}R3o*Rh~0pN`%=?(CN02r`=SR{YE8srAM9tL`x+{er(_7UwQ^D23?C$|ev3wry;4 z$X%Ee$ALEmWG9i_bh2g#0NL=fTaC?w+sz>xcF9vi@lKorhkq?b@aTyK7qp3TE7ofk z&Fh`7A5ajr7`)*vV%nL}-qDWDe%N;Z64dveFtUzkhPGgf5UgDf*tT^P1pB8Ot`ZOT zMw+aXttfZ#N>n3-Kg$KB(!21K^L<(xb;4}&x?u3;qqQW4wHtI|QdLyY0i=-dd^m6y z7eGXgyV07wp4#{m(mAhOy#NU=G2@+pZ%jI}jUf6x%^b)4L6|*0D#~h+uHTgU+uBuu&>Mqj#q*R-AJjdCg0K_0DV5G%5YT6Zhu8YMDY7|dfS6Cc_Q;|LiqIjjG4u->kOwbG>j)?L|5(M z2A6q@)6I3~m~ffkrZ)YP>`Eonp|$nP&v|Rec7{V-Lmq7~#guoORDI7!AUmZqW>Agy z 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

9Ln^~m9r5F`J^XGHG8I$4 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≠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

- - - @@ -48,14 +48,14 @@ {% for item in value %} - - - {% endfor %} @@ -67,14 +67,14 @@ {% for item in item_data %} - - - {% endfor %} From ab6ad475f174dd61e466c1ad8421b16dfd1ad56d Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 31 Dec 2018 11:35:52 +0100 Subject: [PATCH 523/705] Webservices: updated minversion --- webservices/plugin.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webservices/plugin.yaml b/webservices/plugin.yaml index 1cbdd8887..3ff8a0c45 100755 --- a/webservices/plugin.yaml +++ b/webservices/plugin.yaml @@ -14,7 +14,7 @@ plugin: support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1163886-support-thread-f%C3%BCr-das-webservices-plugin version: 1.5.0.5 # Plugin version - sh_minversion: 1.5 # minimum shNG version to use this plugin + sh_minversion: 1.5b # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance restartable: unknown From 894aabafe9a0f849fa384809133e6d5506e85e8d Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 31 Dec 2018 12:21:46 +0100 Subject: [PATCH 524/705] Darksky: changed access to item properties --- darksky/webif/templates/index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/darksky/webif/templates/index.html b/darksky/webif/templates/index.html index e12934b3f..38877d1f6 100644 --- a/darksky/webif/templates/index.html +++ b/darksky/webif/templates/index.html @@ -28,12 +28,12 @@
Darksky Plugin Items ({{ p.get_items()|length }})
{% for key, item in p.get_items().items() %} - - + + - - + + {% endfor %} From 6dff86e5d9752d4450d5d47b2366efaa274fc200 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 31 Dec 2018 12:26:27 +0100 Subject: [PATCH 525/705] OpenWeatherMap: access to items now via property --- openweathermap/__init__.py | 2 +- openweathermap/plugin.yaml | 4 ++-- openweathermap/webif/templates/index.html | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/openweathermap/__init__.py b/openweathermap/__init__.py index 728f2b0e2..409cb5fd7 100644 --- a/openweathermap/__init__.py +++ b/openweathermap/__init__.py @@ -32,7 +32,7 @@ class OpenWeatherMap(SmartPlugin): - PLUGIN_VERSION = "1.5.0.2" + PLUGIN_VERSION = "1.5.0.3" _base_url = 'https://api.openweathermap.org/%s' _base_img_url = 'https://tile.openweathermap.org/map/%s/%s/%s/%s.png?appid=%s' diff --git a/openweathermap/plugin.yaml b/openweathermap/plugin.yaml index d0cfd37b8..3091524ba 100644 --- a/openweathermap/plugin.yaml +++ b/openweathermap/plugin.yaml @@ -12,8 +12,8 @@ plugin: documentation: 'http://smarthomeng.de/user/plugins/openweathermap/user_doc.html' support: 'https://knx-user-forum.de/forum/supportforen/smarthome-py/1246998-support-thread-zum-openweathermap-plugin' keywords: weather - version: 1.5.0.2 # Plugin version - sh_minversion: 1.4c # minimum shNG version to use this plugin + version: 1.5.0.3 # Plugin version + sh_minversion: 1.5b # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: True # plugin supports multi instance restartable: unknown diff --git a/openweathermap/webif/templates/index.html b/openweathermap/webif/templates/index.html index ffb4b6aad..7f6b1d85d 100644 --- a/openweathermap/webif/templates/index.html +++ b/openweathermap/webif/templates/index.html @@ -29,12 +29,12 @@
OpenWeatherMap Plugin Items ({{ p.get_items()|length }})
{% for key, item in p.get_items().items() %} - - + + - - + + {% endfor %} From 55f56dfc488335804e4925a9440387f1ba622293 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 31 Dec 2018 12:34:27 +0100 Subject: [PATCH 526/705] Nuki: updated to item property --- nuki/__init__.py | 28 +++++++++++++++++----------- nuki/plugin.yaml | 6 +++--- nuki/webif/templates/index.html | 28 ++++++++++++++-------------- 3 files changed, 34 insertions(+), 28 deletions(-) diff --git a/nuki/__init__.py b/nuki/__init__.py index 147d48121..9cb2d3d40 100644 --- a/nuki/__init__.py +++ b/nuki/__init__.py @@ -70,7 +70,7 @@ def handle_connection(self): state_name = nuki_bridge_response['stateName'] self.plugin.logger.debug( "Plugin '{pluginname}' - NukiTCPDispatcher: Status Smartlock: ID: {nuki_id} Status: {state_name}". - format(pluginname=self.plugin.get_shortname(), nuki_id=nuki_id, state_name=state_name)) + format(pluginname=self.plugin.get_shortname(), nuki_id=nuki_id, state_name=state_name)) conn.send(b"HTTP/1.1 200 OK\nContent-Type: text/html\n\n") Nuki.update_lock_state(nuki_id, nuki_bridge_response) @@ -80,7 +80,7 @@ def handle_connection(self): class Nuki(SmartPlugin): - PLUGIN_VERSION = "1.5.0.4" + PLUGIN_VERSION = "1.5.0.5" ALLOW_MULTIINSTANCE = False def __init__(self, sh, *args, **kwargs): @@ -151,7 +151,7 @@ def stop(self): def parse_item(self, item): if self.has_iattr(item.conf, 'nuki_id'): - self.logger.debug("Plugin '{0}': parse item: {1}".format(self.get_shortname(), item)) + self.logger.debug("Plugin '{0}': parse item: {1}".format(self.get_shortname(), item.property.path)) nuki_id = self.get_iattr_value(item.conf, 'nuki_id') if self.has_iattr(item.conf, 'nuki_trigger'): @@ -169,7 +169,7 @@ def parse_item(self, item): nuki_battery_items[item] = int(nuki_id) else: self.logger.warning("Plugin '{pluginname}': Item {item} defines a Nuki ID but no nuki trigger! " - "This item has no effect.".format(pluginname=self.get_shortname(), item=item)) + "This item has no effect.".format(pluginname=self.get_shortname(), item=item.property.path)) return return self.update_item @@ -191,7 +191,8 @@ def update_item(self, item, caller=None, source=None, dest=None): if response is not None: if response['success']: # self._get_nuki_status() - self.logger.info("Plugin '{0}': update item: {1}".format(self.get_shortname(), item.id())) + self.logger.info( + "Plugin '{0}': update item: {1}".format(self.get_shortname(), item.property.path)) else: self.logger.error("Plugin '{}': no response.".format(self.get_shortname())) @@ -253,8 +254,9 @@ def _register_callback(self): response = self._api_call(self._base_url, endpoint='callback/add', token=self._token, callback_url=self._callback_url) if not response['success']: - self.logger.warning("Plugin '{pluginname}': Error establishing the callback url: {message}".format - (pluginname=self.get_shortname(), message=response['message'])) + self.logger.warning( + "Plugin '{pluginname}': Error establishing the callback url: {message}".format + (pluginname=self.get_shortname(), message=response['message'])) else: self.logger.info("Plugin '{}': Callback URL registered.".format (self.get_shortname())) @@ -300,7 +302,9 @@ def _api_call(self, base_url, endpoint=None, nuki_id=None, token=None, action=No if id is not None: payload['id'] = id url = urllib.parse.urljoin(base_url, endpoint) - self.logger.debug("Plugin '{}': starting API Call to Nuki Bridge at {} with payload {}.".format(self.get_shortname(), url, payload)) + self.logger.debug( + "Plugin '{}': starting API Call to Nuki Bridge at {} with payload {}.".format(self.get_shortname(), url, + payload)) response = requests.get(url=urllib.parse.urljoin(base_url, endpoint), params=payload) self.logger.debug("Plugin '{}': finishing API Call to Nuki Bridge at {}.".format(self.get_shortname(), url)) response.raise_for_status() @@ -407,11 +411,13 @@ def index(self, reload=None): @cherrypy.expose def triggerAction(self, path, value): if path is None: - self.plugin.logger.error("Plugin '{}': Path parameter is missing when setting action item value!".format(self.get_shortname())) + self.plugin.logger.error( + "Plugin '{}': Path parameter is missing when setting action item value!".format(self.get_shortname())) return if value is None: - self.plugin.logger.error("Plugin '{}': Value parameter is missing when setting action item value!".format(self.get_shortname())) + self.plugin.logger.error( + "Plugin '{}': Value parameter is missing when setting action item value!".format(self.get_shortname())) return item = self.plugin.items.return_item(path) item(int(value), caller=self.plugin.get_shortname(), source='triggerAction()') - return \ No newline at end of file + return diff --git a/nuki/plugin.yaml b/nuki/plugin.yaml index b2c517c19..4c58dfb5f 100755 --- a/nuki/plugin.yaml +++ b/nuki/plugin.yaml @@ -12,9 +12,9 @@ plugin: # documentation: https://github.com/smarthomeNG/smarthome/wiki/CLI-Plugin # url of documentation (wiki) page support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1052437-nuki-smartlock-plugin-support-thread - version: 1.5.0.4 # Plugin version - sh_minversion: 1.5 # minimum shNG version to use this plugin -# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) + version: 1.5.0.5 # Plugin version + sh_minversion: 1.5b # minimum shNG version to use this plugin +# sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance restartable: unknown classname: Nuki # class containing the plugin diff --git a/nuki/webif/templates/index.html b/nuki/webif/templates/index.html index 158b654b5..726c3d815 100644 --- a/nuki/webif/templates/index.html +++ b/nuki/webif/templates/index.html @@ -44,8 +44,8 @@
{{ _('Nuki Event Items') }} ({{ p.get_event_items()|length }})
{% for item, value in p.get_event_items().items() %} - - + + - - + + {% endfor %} @@ -100,10 +100,10 @@
{{ _('Nuki Action Items') }} ({{ p.get_action_items()|length }})
{% for item, value in p.get_action_items().items() %} - - - - + + + + - - + + {% for item, value in p.get_battery_items().items() %} - - + + - - + + {% endfor %} From 881d2187528c7a6f57980a9c66bcdfceb6399f36 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Mon, 31 Dec 2018 12:45:22 +0100 Subject: [PATCH 527/705] SMA EM: switched item access in webif to property --- sma_em/__init__.py | 2 +- sma_em/plugin.yaml | 4 ++-- sma_em/webif/templates/index.html | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sma_em/__init__.py b/sma_em/__init__.py index b37e68e32..602e37fa3 100644 --- a/sma_em/__init__.py +++ b/sma_em/__init__.py @@ -33,7 +33,7 @@ class SMA_EM(SmartPlugin): ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION = "1.5.0.3" + PLUGIN_VERSION = "1.5.0.4" # listen to the Multicast; SMA-Energymeter sends its measurements to 239.12.255.254:9522 MCAST_GRP = '239.12.255.254' diff --git a/sma_em/plugin.yaml b/sma_em/plugin.yaml index a472deb8e..ca378e48b 100755 --- a/sma_em/plugin.yaml +++ b/sma_em/plugin.yaml @@ -12,8 +12,8 @@ plugin: documentation: http://smarthomeng.de/user/plugins_doc/config/sma_em.html support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1030610-sma_em-plugin - version: 1.5.0.3 # Plugin version - sh_minversion: 1.4c # minimum shNG version to use this plugin + version: 1.5.0.4 # Plugin version + sh_minversion: 1.5b # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance restartable: unknown diff --git a/sma_em/webif/templates/index.html b/sma_em/webif/templates/index.html index 20ed4e9da..99dbe1879 100644 --- a/sma_em/webif/templates/index.html +++ b/sma_em/webif/templates/index.html @@ -46,12 +46,12 @@
SMA EM Items ({{ p.get_items()|length }})
{% for key, item in p.get_items().items() %} - - + + - - + + {% endfor %} From a25e312da60e2e0f084cf54c8c8f6fbfe3845098 Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Tue, 1 Jan 2019 20:22:06 +0100 Subject: [PATCH 528/705] Database: Add new countall function to get amount of log entries returned --- database/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/database/__init__.py b/database/__init__.py index 70bee165a..4e3fbb3e4 100755 --- a/database/__init__.py +++ b/database/__init__.py @@ -467,6 +467,7 @@ def _series(self, func, start, end='now', count=100, ratio=1, update=False, step 'avg': 'MIN(time), ' + self._precision_query('AVG(val_num * duration) / AVG(duration)'), 'avg.order': 'ORDER BY time ASC', 'count': 'MIN(time), SUM(CASE WHEN val_num{op}{value} THEN 1 ELSE 0 END)'.format(**expression['params']), + 'countall' : 'MIN(time), COUNT(*)', 'min': 'MIN(time), MIN(val_num)', 'max': 'MIN(time), MAX(val_num)', 'on': 'MIN(time), ' + self._precision_query('SUM(val_bool * duration) / SUM(duration)'), @@ -515,6 +516,7 @@ def _single(self, func, start, end='now', item=None): queries = { 'avg': self._precision_query('AVG(val_num * duration) / AVG(duration)'), 'count': 'SUM(CASE WHEN val_num{op}{value} THEN 1 ELSE 0 END)'.format(**expression['params']), + 'countall' : 'COUNT(*)', 'min': 'MIN(val_num)', 'max': 'MAX(val_num)', 'on': self._precision_query('SUM(val_bool * duration) / SUM(duration)'), From aca8059bec3282e1f6bec4125219ccf37d52fda9 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 2 Jan 2019 10:41:51 +0100 Subject: [PATCH 529/705] Database: added possibility to determine number of values in log table for each item via web interface --- database/__init__.py | 7 +++++++ database/webif/templates/index.html | 28 ++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/database/__init__.py b/database/__init__.py index 348cad8d5..d320d64d5 100755 --- a/database/__init__.py +++ b/database/__init__.py @@ -863,3 +863,10 @@ def db_dump(self): @cherrypy.expose def cleanup(self): self.plugin.cleanup() + + @cherrypy.expose + @cherrypy.tools.json_out() + def countall(self, item_path): + if item_path is not None: + item = self.plugin.items.return_item(item_path) + return int(item.db('countall', 0)) diff --git a/database/webif/templates/index.html b/database/webif/templates/index.html index 1396f6169..6f27c409b 100644 --- a/database/webif/templates/index.html +++ b/database/webif/templates/index.html @@ -14,8 +14,8 @@ {% endif %} @@ -27,13 +27,36 @@ + + +
@@ -57,6 +80,7 @@
From 91921aeb52dcf9f2b05722d119bdc66da27a9401 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 2 Jan 2019 10:53:29 +0100 Subject: [PATCH 530/705] Database: fixed bug with 0 values in log table, added translations --- database/__init__.py | 8 ++++++-- database/locale.yaml | 11 ++++++++++- database/webif/templates/index.html | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/database/__init__.py b/database/__init__.py index d320d64d5..dc0268e41 100755 --- a/database/__init__.py +++ b/database/__init__.py @@ -771,7 +771,7 @@ def index(self, reload=None, action=None, item_id=None, item_path=None, day=None else: self.plugin.deleteLog(item_id) delete_triggered = True - elif action == "item_details" and item_id is not None: + if action == "item_details" and item_id is not None: if day is not None and month is not None and year is not None: time_start = time.mktime(datetime.datetime.strptime("%s/%s/%s" % (month, day, year), "%m/%d/%Y").timetuple()) * 1000 @@ -869,4 +869,8 @@ def cleanup(self): def countall(self, item_path): if item_path is not None: item = self.plugin.items.return_item(item_path) - return int(item.db('countall', 0)) + count = item.db('countall', 0) + if count is not None: + return int(count) + else: + return 0 diff --git a/database/locale.yaml b/database/locale.yaml index 0adb3381a..b24aab6b5 100644 --- a/database/locale.yaml +++ b/database/locale.yaml @@ -77,4 +77,13 @@ plugin_translations: 'Parameter': {'de': '=', 'en': 'Parameters', 'fr': ''} 'Wollen Sie alle Datensätze ohne zugehöriges Item wirklich löschen?': 'de': '=' - 'en': 'Do you really want to delete all data sets without corresponding item?' \ No newline at end of file + 'en': 'Do you really want to delete all data sets without corresponding item?' + 'Anzahl Einträge in LOG Tabelle für Item': + 'de': '=' + 'en': 'Number of data sets in LOG table for item' + 'Loading...': + 'de': '=' + 'en': '=' + 'Anzahl Datensätze in LOG Tabelle': + 'de': '=' + 'en': 'Number of data sets in LOG table' \ No newline at end of file diff --git a/database/webif/templates/index.html b/database/webif/templates/index.html index 6f27c409b..2dc1a4792 100644 --- a/database/webif/templates/index.html +++ b/database/webif/templates/index.html @@ -80,7 +80,7 @@ From 8b674a862fcf5ac46b78dd54927fec8c9b1a6c08 Mon Sep 17 00:00:00 2001 From: psilo909 Date: Wed, 2 Jan 2019 10:59:17 +0100 Subject: [PATCH 531/705] Database: added support thread url --- database/plugin.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/database/plugin.yaml b/database/plugin.yaml index 77c97088e..110a1e7a7 100755 --- a/database/plugin.yaml +++ b/database/plugin.yaml @@ -10,6 +10,7 @@ plugin: state: ready keywords: database documentation: http://smarthomeng.de/user/plugins/database/user_doc.html + support: https://knx-user-forum.de/forum/supportforen/smarthome-py/1021844-neues-database-plugin version: 1.5.7 # Plugin version sh_minversion: 1.5b # minimum shNG version to use this plugin From d5fecfe29a46c4c290d34e560f7d6748cb488caf Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Wed, 2 Jan 2019 21:56:24 +0100 Subject: [PATCH 532/705] Update user docu --- stateengine/user_doc/user_doc10.rst | 4 +- stateengine/user_doc/user_doc3.rst | 40 +++--------- stateengine/user_doc/user_doc4.rst | 49 ++++++--------- stateengine/user_doc/user_doc5.rst | 96 +++++++++++++---------------- stateengine/user_doc/user_doc6.rst | 66 ++++++++++---------- 5 files changed, 104 insertions(+), 151 deletions(-) diff --git a/stateengine/user_doc/user_doc10.rst b/stateengine/user_doc/user_doc10.rst index 96ebebf3c..6c7088584 100644 --- a/stateengine/user_doc/user_doc10.rst +++ b/stateengine/user_doc/user_doc10.rst @@ -5,9 +5,7 @@ Variablen ######### -Mit dem Datentyp AbValue kann -auf Variablen des Plugins zugegriffen werden. Derzeit stehen -folgende Variablen zur Verfügung: +Im Plugin stehen folgende Variablen zur Verfügung: **item.suspend_time:** *Die Suspend-Time des Items* diff --git a/stateengine/user_doc/user_doc3.rst b/stateengine/user_doc/user_doc3.rst index e60925442..84131ebb8 100644 --- a/stateengine/user_doc/user_doc3.rst +++ b/stateengine/user_doc/user_doc3.rst @@ -89,7 +89,8 @@ festlegen, wann eine Aktion ausgeführt wird. .. rubric:: Items :name: items -Bedingungen und Aktionen beziehen sich überlicherweise auf Items. +Bedingungen und Aktionen beziehen sich überlicherweise auf Items wie beispielsweise +die Höhe einer Jalousie oder die Außenhelligkeit. Diese Items müssen auf Ebene des Objekt-Items über das Attribut ``se_item_`` bekannt gemacht werden. @@ -103,45 +104,22 @@ Diese Items müssen auf Ebene des Objekt-Items über das Attribut automatik: rules: - se_mindelta_lamella: 10 se_item_height: beispiel.raffstore1.hoehe - se_item_lamella: beispiel.raffstore1.lamelle se_item_brightness: beispiel.wetterstation.helligkeit Nacht: name: Nacht on_enter_or_stay: se_set_height: 100 - se_set_lamella: 100 enter_toodark: se_max_brightness: 25 - enter_toolate: - - Tag: - name: Tag - on_enter_or_stay: - se_set_hoehe: 0 - enter: - - -**Attribute se_item_height und se_item_lamella:** -*Definition der Items, die durch die Aktionen se_set_height und se_set_lamella verändert werden* - -Die Items werden durch ihre Item-Id angegeben - -**Attribut name:** -*Name des Zustands* - -Der Name wird in das über ``se_laststate_item_name`` definierte -Item geschrieben, wenn der Zustand aktueller Zustand wird. Dieser -Wert kann z. B. in einer Visualisierung dargestellt werden. - -**Attribute se_set_height und se_set_lamella:** -*Neu zu setzende Werte für die Items, die über se_item_height und se_item_lamella festgelegt wurden* +**Attribut se_item_height:** +*Definition des Items, das durch die Aktion se_set_height verändert wird* -**Attribut se_mindelta_lamella:** -*Nur, wenn sich Lamellen min. um x Grad ändern würden, werden sie aktualisiert.* +**Attribut se_item_brightness:** +*Definition des Items, dessen Wert für die Bedingung abgefragt werden soll* -**Untergeordnete Items enter, enter_toodark und enter_toolate:** -*Bedingungsgruppen die erfüllt sein müssen, damit ein Zustand aktueller Zustand werden kann* +Im Beispiel wird also im Zustand Nacht das Item ``beispiel.raffstore1.hoehe`` auf +den Wert 100 gesetzt, sobald ``beispiel.wetterstation.helligkeit`` den Wert 25 +übersteigt. diff --git a/stateengine/user_doc/user_doc4.rst b/stateengine/user_doc/user_doc4.rst index bf71f7de2..ab272a37e 100644 --- a/stateengine/user_doc/user_doc4.rst +++ b/stateengine/user_doc/user_doc4.rst @@ -5,8 +5,8 @@ Bedingungen ########### -.. rubric:: Grundlagen - :name: grundlagen +.. rubric:: Grundlagen von Bedingungen + :name: grundlagenbedingungen Jede Bedingung erfordert drei Dinge: @@ -82,7 +82,7 @@ zulässige Werte sind "true", "1", "yes", "on" bzw. "false", "0", se_agemin_: [Wert] -Die Bedingung ist erfüllt, wenn das Alter des Items, dass zur +Die Bedingung ist erfüllt, wenn das Alter des Items, das zur Ermittlung des Werts angegeben ist, größer als das angegebene Mindestalter ist. @@ -92,7 +92,7 @@ Mindestalter ist. se_agemax_: [Wert] -Die Bedingung ist erfüllt, wenn das Alter des Items, dass zur +Die Bedingung ist erfüllt, wenn das Alter des Items, das zur Ermittlung des Werts angegeben ist, kleiner als das angegebene Höchstalter ist. @@ -111,27 +111,23 @@ zulässige Werte sind "true", "1", "yes", "on" bzw. "false", "0", :name: bereitstellungdesaktuellenwerts Der zu setzende Wert kann entweder über einen statischen Wert, ein Item oder über eine -Eval-Funktion bereitgestellt werden. Wenn beides angegeben ist, -wird das Item verwendet und die Eval-Funktion ignoriert. - -Der Name des Items, über das der aktuelle Wert abgerufen werden -soll, wird auf Ebene des Objekt-Items über das Attribut -``se_item_`` angegeben. Die Eval-Funktion, über -die der aktuelle Wert abgerufen werden soll, wird auf Ebene des -Objekt-Items über das Attribut -``se_eval_`` angegeben. Der Bedingungsname -in ``se_item`` bzw. ``se_eval`` -muss mit den Bedingungsnamen in den Bedingungen korrespondieren. - -Da sich Altersbedingungen auf das Alter der hinterlegten Items -beziehen, können ``se_agemin_``, -``se_agemax_`` und -``se_agenegate_`` nur verwendet werden, wenn der -aktuelle Wert über ein Item bereitgestellt wird. +Eval-Funktion bereitgestellt werden. + +Der Name des Items wird auf Ebene des Objekt-Items über das Attribut +``se_item_`` angegeben und in der Bedingung mit dem +gleichen Bedingungsnamen referenziert. + .. rubric:: Beispiel :name: beispielbedingungen +Im folgenden Beispiel wird der Zustand "Daemmerung" eingenommen, sobald +die Helligkeit (über se_item_brightness definiert) zwischen 500 und 1000 Lux liegt. + +Der Zustand "Sonder" wird eingenommen, sobald die Helligkeit mindestens dem im +Item test.wert hinterlegten Wert entspricht, aber nicht mehr als 500 Einheiten +über diesem Wert liegt. + .. code-block:: yaml beispiel: @@ -139,8 +135,6 @@ aktuelle Wert über ein Item bereitgestellt wird. automatik: rules: <...> - se_item_height: beispiel.raffstore1.hoehe - se_item_lamella: beispiel.raffstore1.lamelle se_item_brightness: beispiel.wetterstation.helligkeit Daemmerung: type: foo @@ -148,14 +142,7 @@ aktuelle Wert über ein Item bereitgestellt wird. enter: se_min_brightness: 500 - se_max_brightness: value:1000 - - Nacht: - type: foo - name: Nacht - - enter_toodark: - se_max_brightness: 500 + se_max_brightness: 1000 Sonder: type: foo diff --git a/stateengine/user_doc/user_doc5.rst b/stateengine/user_doc/user_doc5.rst index 1e7c0fb2b..093244c15 100644 --- a/stateengine/user_doc/user_doc5.rst +++ b/stateengine/user_doc/user_doc5.rst @@ -23,61 +23,49 @@ als Attribute definiert werden. - **on_leave**: Aktionen, die ausgeführt werden, direkt bevor ein anderer Zustand aktiv wird. -Aktionen können auch direkt im Zustands-Item definiert werden. -Solche Aktionen werden analog zum Ereignis ``on_enter_or_stay`` behandelt. - **Beispiel** .. code-block:: yaml - test: - events: - name: stateengine Event Beispiel - type: foo - - item: - name: Dummy Item - type: bool - value: False - - rules: - type: bool - name: Automatik Test Event - # Dies ist ein Objekt-Item für das stateengine-Plugin: - se_plugin: active - - state1: - type: foo - name: Status 1 - - on_enter: - name: Ausführen immer wenn ein Zustand gerade aktiv geworden ist - <... Aktionen ...> - - on_stay: - name: Ausführen immer wenn ein Zustand aktiv geworden ist und bereits vorher aktiv war - <... Aktionen ...> - - on_enter_or_stay: - name: Ausführen immer wenn ein Zustand aktiv ist - <... Aktionen ...> - - on_leave: - name: Ausführen beim Verlassen des Zustands - <... Aktionen ...> - - enter_1: - name: Bedingung 1 - <...Einstiegs-Bedingungsset 1...> - - enter_2: - name: Bedingung 2 - <...Einstiegs-Bedingungsset 2...> - - state2: - name: Status 2 - <... Weitere Bedingungssets und Aktionsgruppen ...> - - state3: - name: Status 3 - <... Weitere Bedingungssets und Aktionsgruppen ...> + test: + events: + name: stateengine Event Beispiel + type: foo + + rules: + type: bool + name: Automatik Test Event + # Dies ist ein Objekt-Item für das stateengine-Plugin: + se_plugin: active + + state1: + type: foo + name: Status 1 + + on_enter: + name: Ausführen immer wenn ein Zustand gerade aktiv geworden ist + <... Aktionen ...> + + on_stay: + name: Ausführen immer wenn ein Zustand aktiv geworden ist und bereits vorher aktiv war + <... Aktionen ...> + + on_enter_or_stay: + name: Ausführen immer wenn ein Zustand aktiv ist + <... Aktionen ...> + + on_leave: + name: Ausführen beim Verlassen des Zustands + <... Aktionen ...> + + enter_1: + name: Bedingung 1 + <...Einstiegs-Bedingungsset 1...> + + enter_2: + name: Bedingung 2 + <...Einstiegs-Bedingungsset 2...> + + state2: + name: Status 2 + <... Weitere Bedingungssets und Aktionsgruppen ...> diff --git a/stateengine/user_doc/user_doc6.rst b/stateengine/user_doc/user_doc6.rst index a77db0874..0565d05ed 100644 --- a/stateengine/user_doc/user_doc6.rst +++ b/stateengine/user_doc/user_doc6.rst @@ -4,7 +4,9 @@ Aktionen - einzeln ################## -Bei der Einzelvariante zur Definition von Aktionen werden alle +Es gibt zwei Möglichkeiten, Aktionen zu definieren. + +Bei der Einzelvariante werden alle Parameter einer Aktion in separaten Attributen definiert. Über den gemeinsamen Aktionsnamen gehören die Attribute einer Aktion zusammen. @@ -29,37 +31,6 @@ Der Wert, auf den das Item gesezt wird, kann als statischer Wert, als Wert eines Items oder als Ergebnis der Ausführung einer Funktion festgelegt werden. -.. rubric:: Aktion: Minimumabweichung - :name: minimumabweichung - -Es ist möglich, eine Minimumabweichung für -Änderungen zu definieren. Wenn die Differenz zwischen dem -aktuellen Wert des Items und dem ermittelten neuen Wert kleiner -ist als die festgelegte Minimumabweichung wird keine Änderung -vorgenommen. Die Minimumabweichung wird über das Attribut -``se_mindelta_`` auf der Ebene des Objekt-Items -festgelegt. - -.. rubric:: Aktion: Item zwangsweise auf einen Wert setzen - :name: aktionitemzwangsweiseaufeinenwertsetzen - -.. code-block:: yaml - - se_force_ - -Diese Aktion funktioniert analog zu ``se_set_``. -Einziger Unterschied ist, dass die Wertänderung erzwungen wird: -Wenn das Item bereits den zu setzenden Wert hat, dann ändert -smarthomeNG das Item nicht. Selbst wenn beim Item das Attribut -``enforce_updates: yes`` gesetzt ist, wird zwar der Wert neu -gesetzt, der von smarthomeNG die Änderungszeit nicht neu gesetzt. Mit -dem Attribut ``se_force_`` wird das Plugin den Wert -des Items bei Bedarf zuerst auf einen anderen Wert ändern und dann -auf dem Zielwert setzen. Damit erfolgt auf jeden Fall eine -Wertänderung (ggf. sogar zwei) mit allen damit in Zusammenhang -stehenden Änderungen (eval's, Aktualisierung der Änderungszeiten, -etc). - .. rubric:: Aktion: Ausführen einer Funktion :name: aktionausfuehreneinerfunktion @@ -177,6 +148,37 @@ Reihenfolge der beiden Aktionen untereinander ist dann wieder zufällig. Innerhalb der gesamten Aktionen werden die beiden Aktionen jedoch an der angegebenen Position ausgeführt. +.. rubric:: Aktion: Minimumabweichung + :name: minimumabweichung + +Es ist möglich, eine Minimumabweichung für +Änderungen zu definieren. Wenn die Differenz zwischen dem +aktuellen Wert des Items und dem ermittelten neuen Wert kleiner +ist als die festgelegte Minimumabweichung wird keine Änderung +vorgenommen. Die Minimumabweichung wird über das Attribut +``se_mindelta_`` auf der Ebene des Objekt-Items +festgelegt. + +.. rubric:: Aktion: Item zwangsweise auf einen Wert setzen + :name: aktionitemzwangsweiseaufeinenwertsetzen + +.. code-block:: yaml + + se_force_ + +Diese Aktion funktioniert analog zu ``se_set_``. +Einziger Unterschied ist, dass die Wertänderung erzwungen wird: +Wenn das Item bereits den zu setzenden Wert hat, dann ändert +smarthomeNG das Item nicht. Selbst wenn beim Item das Attribut +``enforce_updates: yes`` gesetzt ist, wird zwar der Wert neu +gesetzt, der von smarthomeNG die Änderungszeit nicht neu gesetzt. Mit +dem Attribut ``se_force_`` wird das Plugin den Wert +des Items bei Bedarf zuerst auf einen anderen Wert ändern und dann +auf dem Zielwert setzen. Damit erfolgt auf jeden Fall eine +Wertänderung (ggf. sogar zwei) mit allen damit in Zusammenhang +stehenden Änderungen (eval's, Aktualisierung der Änderungszeiten, +etc). + .. rubric:: Beispiel zu Aktionen :name: beispielzuaktioneneinzeln From 30c5b1b54b60107ddc1249eee47839337265a28a Mon Sep 17 00:00:00 2001 From: Onkel Andy Date: Wed, 2 Jan 2019 22:03:00 +0100 Subject: [PATCH 533/705] Update user_doc1.rst --- stateengine/user_doc/user_doc1.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/stateengine/user_doc/user_doc1.rst b/stateengine/user_doc/user_doc1.rst index 2f33239b2..97cef16ff 100755 --- a/stateengine/user_doc/user_doc1.rst +++ b/stateengine/user_doc/user_doc1.rst @@ -16,6 +16,12 @@ Allgemein Sperrfunktionalität verwendet werden, über die alle aktuellen Jalousieaktoren verfügen! +.. rubric:: Einführung + :name: einfuehrungstateengine + +Als Einstieg in das Plugin empfiehlt es sich, den `Blogeintrag `_ +auf der SmarthomeNG Seite zu lesen! + .. rubric:: Funktionalität :name: funktionalitaet From 2213ffd3fe929e9860938ae06c3ce4aff3f44ac8 Mon Sep 17 00:00:00 2001 From: bmxp Date: Thu, 3 Jan 2019 00:19:49 +0100 Subject: [PATCH 534/705] implemented a basic webinterface, introduced changed plugin params, added bye_message, updated plugin.yaml --- telegram/__init__.py | 222 ++++++++++++++++------ telegram/assets/webif1.png | Bin 0 -> 51968 bytes telegram/assets/webif2.png | Bin 0 -> 33851 bytes telegram/plugin.yaml | 40 +++- telegram/webif/static/img/plugin_logo.svg | 17 ++ telegram/webif/static/img/readme.txt | 6 + telegram/webif/templates/index.html | 75 ++++++++ 7 files changed, 299 insertions(+), 61 deletions(-) create mode 100644 telegram/assets/webif1.png create mode 100644 telegram/assets/webif2.png create mode 100644 telegram/webif/static/img/plugin_logo.svg create mode 100644 telegram/webif/static/img/readme.txt create mode 100644 telegram/webif/templates/index.html diff --git a/telegram/__init__.py b/telegram/__init__.py index 84c0348a0..744324541 100644 --- a/telegram/__init__.py +++ b/telegram/__init__.py @@ -30,27 +30,35 @@ # sudo pip install -r requirements.txt or pip install -r requirements.txt import time -import random +#import random import datetime import logging -import urllib3 -import telegram -import telegram.ext -from telegram.ext import Updater -from telegram.ext import CommandHandler -from telegram.ext import MessageHandler, Filters - -from lib.model.smartplugin import SmartPlugin -from lib.logic import Logics +#import urllib3 import re +from lib.model.smartplugin import * +from lib.logic import Logics + +try: + import telegram + import telegram.ext + from telegram.error import TelegramError + from telegram.ext import Updater + from telegram.ext import CommandHandler + from telegram.ext import MessageHandler, Filters + REQUIRED_PACKAGE_IMPORTED = True +except: + REQUIRED_PACKAGE_IMPORTED = False + + + PLUGIN_ATTR_TOKEN = 'token' PLUGIN_ATTR_CHAT_IDS = 'trusted_chat_ids' ITEM_ATTR_MESSAGE = 'telegram_message' # Send message on item change ITEM_ATTR_INFO = 'telegram_info' # read items with specific item-values ITEM_ATTR_TEXT = 'telegram_text' # write message-text into the item -ITEM_ATTR_MATCHREGEX = 'telegram_value_match_regex' # check a value against a condition before sending a message +ITEM_ATTR_MATCHREGEX = 'telegram_value_match_regex' # check a value against a condition before sending a message MESSAGE_TAG_ID = '[ID]' MESSAGE_TAG_NAME = '[NAME]' @@ -61,21 +69,50 @@ class Telegram(SmartPlugin): - PLUGIN_VERSION = "1.4.4" + PLUGIN_VERSION = "1.5.0" ALLOW_MULTIINSTANCE = False _items = [] # Storage Array for all items using telegram attributes ITEM_ATTR_MESSAGE - _items_info = {} # dict used whith the info-command: key = attibute_value, val= item_list ITEM_ATTR_INFO + _items_info = {} # dict used whith the info-command: key = attribute_value, val= item_list ITEM_ATTR_INFO _items_text_message = [] # items in which the text message is written ITEM_ATTR_TEXT _chat_ids = [] # array whith registred chat_ids # called, before items are loaded - def __init__(self, smarthome, token='dummy', trusted_chat_ids='none', name='SH Telegram Gateway', welcome_msg='SmarthomeNG Telegram Plugin is up and running'): - self._sh = smarthome - self.logger = logging.getLogger(__name__) + def __init__(self, sh, *args, **kwargs): + """ + Initializes the Telegram Plugin + The params may be obtained through get_parameter_value(parameter_name) + + """ + + from bin.smarthome import VERSION + if '.'.join(VERSION.split('.', 2)[:2]) <= '1.5': + self.logger = logging.getLogger(__name__) + + self.logger.debug("init {}".format(__name__)) + self._init_complete = False + + # Exit if the required package(s) could not be imported + if not REQUIRED_PACKAGE_IMPORTED: + self.logger.error("{}: Unable to import Python package 'python-telegram-bot'".format(self.get_fullname())) + return + + #self._instance = self.get_parameter_value('instance') # the instance of the plugin + self._name = self.get_parameter_value('name') + self._token = self.get_parameter_value('token') + trusted_chat_ids = self.get_parameter_value('trusted_chat_ids') + self._chat_ids = list(map(int, trusted_chat_ids.split(','))) + + if len(self._chat_ids) < 1: + self.logger.info("No trusted chat ids configured!") + + self._welcome_msg = self.get_parameter_value('welcome_msg') + self._bye_msg = self.get_parameter_value('bye_msg') + self._long_polling_timeout = self.get_parameter_value('long_polling_timeout') + # the Updater class continuously fetches new updates from telegram and passes them on to the Dispatcher class. - self._updater = Updater(token=token) + self._updater = Updater(token=self._token) self._bot = self._updater.bot self.logger.info("Telegram bot is listening: {0}".format(self._bot.getMe())) @@ -88,25 +125,15 @@ def __init__(self, smarthome, token='dummy', trusted_chat_ids='none', name='SH T dispatcher.add_handler(CommandHandler('hide', self.cHandler_hide)) dispatcher.add_handler(CommandHandler('list', self.cHandler_list)) dispatcher.add_handler(CommandHandler('info', self.cHandler_info)) + dispatcher.add_handler(CommandHandler('subscribe', self.cHandler_subscribe)) dispatcher.add_handler(CommandHandler('lo', self.cHandler_lo)) dispatcher.add_handler(CommandHandler('tr', self.cHandler_tr, pass_args=True)) - - dispatcher.add_handler( MessageHandler(Filters.text, self.mHandler)) - - #self._updater.start_polling() # (poll_interval=0.0, timeout=10, network_delay=None, clean=False, bootstrap_retries=0, read_latency=2.0, allowed_updates=None) - - self._chat_ids = list(map(int, trusted_chat_ids.split(','))) - if len(self._chat_ids) < 1: - self.logger.info("No trusted chat ids configured!") - - self._name = name - - self._msg_broadcast(welcome_msg) + dispatcher.add_handler( MessageHandler(Filters.text, self.mHandler)) + self.init_webinterface() - # triggered by sh.telegram(msg) - # def __call__(self, msg): - # self._msg_broadcast(msg) + self.logger.debug("init done") + self._init_complete = True def __call__(self, msg, chat_id=None): if chat_id == None: @@ -114,29 +141,38 @@ def __call__(self, msg, chat_id=None): else: self._msg_broadcast(msg, chat_id) - - # called once at startup after all items are loaded def run(self): + """ + This is called when the plugins thread is about to run + """ self.alive = True self.logics = Logics.get_instance() # Returns the instance of the Logics class, to be used to access the logics-api - - self._updater.start_polling() # (poll_interval=0.0, timeout=10, network_delay=None, clean=False, bootstrap_retries=0, read_latency=2.0, allowed_updates=None) - - # if you want to create child threads, do not make them daemon = True! - # They will not shutdown properly. (It's a python bug) - - - # close files and data connections + q = self._updater.start_polling(timeout=self._long_polling_timeout) # (poll_interval=0.0, timeout=10, network_delay=None, clean=False, bootstrap_retries=0, read_latency=2.0, allowed_updates=None) + self.logger.debug("started polling the updater, Queue is {}".format(q)) + self._msg_broadcast(self._welcome_msg) + self.logger.debug("sent welcome message {}") + def stop(self): self.alive = False + """ + This is called when the plugins thread is about to stop + """ try: - self.logger.info("stop updater") + self.logger.debug("stop telegram plugin") + self._msg_broadcast(self._bye_msg) + self.logger.debug("sent bye message") + # Todo: we need to wait until the bye message was sent self._updater.stop() + self.logger.debug("telegram plugin stopped") except: pass # called for each item during startup, items.yaml contains the "attibute: value" entries def parse_item(self, item): + """ + Default plugin parse_item method. Is called when the plugin is initialized. + :param item: The item to process. + """ if ITEM_ATTR_MESSAGE in item.conf: self.logger.debug("parse item: {0}".format(item)) value = item.conf[ITEM_ATTR_MESSAGE] @@ -202,8 +238,6 @@ def update_item(self, item, caller=None, source=None, dest=None): else: item_name = 'NONAME' - # TODO: item.__changed_by - # replace Tags with id,value,caller,source,dest,... msg_txt = msg_txt_tmpl.replace(MESSAGE_TAG_ID, item_id) msg_txt = msg_txt.replace(MESSAGE_TAG_NAME, item_name) @@ -223,9 +257,12 @@ def _msg_broadcast(self, msg, chat_id=None): for cid in self.get_chat_id_list(chat_id): try: self._bot.sendMessage(chat_id=cid, text=msg) - except: - self.logger.error("could not broadcast to chat id [%d]" % cid) - + except TelegramError as e: + self.logger.error("could not broadcast to chat id [{}] due to error {}".format(cid,e)) + except Exception as e: + self.logger.debug("Exception '{0}' occurred, please inform plugin author!".format(e)) + + def _photo_broadcast(self, photofile, msg, chat_id=None): for cid in self.get_chat_id_list(chat_id): try: @@ -265,7 +302,7 @@ def cHandler_time(self, bot, update): # /help: show available commands as keyboard def cHandler_help(self, bot, update): - bot.send_message(chat_id=update.message.chat_id, text=self.translate("choose"), reply_markup={"keyboard":[["/hide"], ["/time","/list"], ["/lo","/info"]]}) + bot.send_message(chat_id=update.message.chat_id, text=self.translate("choose"), reply_markup={"keyboard":[["/hide","/subscribe"], ["/time","/list"], ["/lo","/info"]]}) # /hide: hide keyboard def cHandler_hide(self, bot, update): @@ -280,6 +317,10 @@ def cHandler_list(self, bot, update): def cHandler_info(self, bot, update): bot.send_message(chat_id=update.message.chat_id, text=self.translate("Infos from the items:"), reply_markup={"keyboard":self.create_info_reply_markup()}) + # /info: show item-menu with registered items with specific attribute + def cHandler_subscribe(self, bot, update): + bot.send_message(chat_id=update.message.chat_id, text=self.translate("Your chat id is '{}'".format(update.message.chat_id))) + # /xx show registered items and value with specific attribute/key def cHandler_info_attr(self, bot, update): c_key = update.message.text.replace("/", "", 1) @@ -359,8 +400,81 @@ def build_menu(self, buttons, n_cols, header_buttons=None, footer_buttons=None): if footer_buttons: menu.append(footer_buttons) return menu - -# if __name__ == '__main__': -# logging.basicConfig(level=logging.DEBUG) -# myplugin = PluginName('smarthome-telegram') -# myplugin.run() + + def init_webinterface(self): + """ + Initialize the web interface for this plugin + + This method is only needed if the plugin is implementing a web interface + """ + try: + self.mod_http = Modules.get_instance().get_module('http') # try/except to handle running in a core version that does not support modules + except: + self.mod_http = None + if self.mod_http == None: + self.logger.error("Plugin '{}': Not initializing the web interface".format(self.get_shortname())) + return False + + import sys + if not "SmartPluginWebIf" in list(sys.modules['lib.model.smartplugin'].__dict__): + self.logger.warning("Plugin '{}': Web interface needs SmartHomeNG v1.5 and up. Not initializing the web interface".format(self.get_shortname())) + return False + + # set application configuration for cherrypy + webif_dir = self.path_join(self.get_plugin_dir(), 'webif') + config = { + '/': { + 'tools.staticdir.root': webif_dir, + }, + '/static': { + 'tools.staticdir.on': True, + 'tools.staticdir.dir': 'static' + } + } + + # Register the web interface as a cherrypy app + self.mod_http.register_webif(WebInterface(webif_dir, self), + self.get_shortname(), + config, + self.get_classname(), self.get_instance_name(), + description='') + + return True + +# ------------------------------------------ +# Webinterface of the plugin +# ------------------------------------------ + +import cherrypy +from jinja2 import Environment, FileSystemLoader + +class WebInterface(SmartPluginWebIf): + + def __init__(self, webif_dir, plugin): + """ + Initialization of instance of class WebInterface + + :param webif_dir: directory where the webinterface of the plugin resides + :param plugin: instance of the plugin + :type webif_dir: str + :type plugin: object + """ + self.logger = logging.getLogger(__name__) + self.webif_dir = webif_dir + self.plugin = plugin + self.tplenv = self.init_template_environment() + + + @cherrypy.expose + def index(self, reload=None): + """ + Build index.html for cherrypy + + Render the template and return the html file to be delivered to the browser + + :return: contents of the template after beeing rendered + """ + tmpl = self.tplenv.get_template('index.html') + # add values to be passed to the Jinja2 template eg: tmpl.render(p=self.plugin, interface=interface, ...) + return tmpl.render(p=self.plugin, ) + diff --git a/telegram/assets/webif1.png b/telegram/assets/webif1.png new file mode 100644 index 0000000000000000000000000000000000000000..eb833903e34ae14878ca5b675a6b089f1336a6a2 GIT binary patch literal 51968 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 literal 0 HcmV?d00001 diff --git a/telegram/plugin.yaml b/telegram/plugin.yaml index 81cf53a46..8dc2805db 100644 --- a/telegram/plugin.yaml +++ b/telegram/plugin.yaml @@ -6,24 +6,22 @@ plugin: de: 'Anbindung des Telegram Service (verwendet python-telegram-bot Package statt telepot Package)' en: 'Connects to the telegram service (uses python-telegram-bot package instead of telebot package)' maintainer: gamade, ivan73, bmxp -# tester: state: ready # tester: # Who tests this plugin? -# keywords: iot xyz -# documentation: https://github.com/smarthomeNG/smarthome/wiki/... # url of documentation (wiki) page + keywords: telegram chat messenger photo + documentation: http://smarthomeng.de/user/plugins/telegram/user_doc.html # support: https://knx-user-forum.de/forum/supportforen/smarthome-py - version: 1.4.4 # Plugin version + version: 1.5.0 # Plugin version sh_minversion: 1.3 # minimum shNG version to use this plugin # sh_maxversion: # maximum shNG version to use this plugin (leave empty if latest) multi_instance: False # plugin supports multi instance - restartable: unknown + restartable: True classname: Telegram # class containing the plugin parameters: # Definition of parameters to be configured in etc/plugin.yaml token: - type: str type: str description: de: 'geteilter geheimer Schlüssel zur Authentifizierung bei Telegram' @@ -35,6 +33,35 @@ parameters: de: 'Liste von Chat IDs denen vertraut wird' en: 'list of trusted chat ids' + name: + type: str + default: 'SmartHomeNG Telegram Gateway' + description: + de: 'Name um diese Instanz zu identifizieren' + en: 'used to identify this Telegram Instance' + + long_polling_timeout: + type: num + # 2 minutes should be long enough to avoid problems with too many connections to telegram server + default: 120 + description: + de: 'Zeit nachdem eine neue Verbindung zum Telegram Server aufgebaut um Updates zu holen' + en: 'Time after a new link to telegram server will be established to get updates' + + welcome_msg: + type: str + default: 'SmarthomeNG Telegram Plugin is up and running' + description: + de: 'Willkommensnachricht, wird an alle vertrauenswürdigen Clients beim Start des Plugins gesendet' + en: 'Welcome message, will be sent to all trusted chat clients at plugin start' + + bye_msg: + type: str + default: 'SmartHomeNG Telegram Plugin stops' + description: + de: 'Endenachricht, wird an alle vertrauenswürdigen Clients beim Stop des Plugins gesendet' + en: 'Bye message, will be sent to all trusted chat clients at plugin stop' + item_attributes: # Definition of item attributes defined by this plugin telegram_message: @@ -66,4 +93,3 @@ logic_parameters: NONE plugin_functions: NONE # Definition of function interface of the plugin - diff --git a/telegram/webif/static/img/plugin_logo.svg b/telegram/webif/static/img/plugin_logo.svg new file mode 100644 index 000000000..62cef3b8d --- /dev/null +++ b/telegram/webif/static/img/plugin_logo.svg @@ -0,0 +1,17 @@ + + + + + + + + + diff --git a/telegram/webif/static/img/readme.txt b/telegram/webif/static/img/readme.txt new file mode 100644 index 000000000..1a7c55eef --- /dev/null +++ b/telegram/webif/static/img/readme.txt @@ -0,0 +1,6 @@ +This directory is for storing images that are used by the web interface. + +If you want to have your own logo on the top of the web interface, store it here and name it plugin_logo.. + +Extension can be png, svg or jpg + diff --git a/telegram/webif/templates/index.html b/telegram/webif/templates/index.html new file mode 100644 index 000000000..3ff93b61d --- /dev/null +++ b/telegram/webif/templates/index.html @@ -0,0 +1,75 @@ +{% extends "base_plugin.html" %} + +{% set logo_frame = false %} +{% set item_count = items|length %} + +{% block headtable %} +
+ REST + Simple + Type
- {{item.id()}} + + {{item.property.path}} - {{item.id()}} + + {{item.property.path}} - {{item.type()}} + + {{item.property.type}}
- {{item.id()}} + + {{item.property.path}} - {{item.id()}} + + {{item.property.path}} - {{item.type()}} + + {{item.property.type}}
{{ item.id() }}{{ item.type() }}{{ item.property.path }}{{ item.property.type }} {{ key }} {{ item() }}{{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }}{{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }}{{ item.property.last_update.strftime('%d.%m.%Y %H:%M:%S') }}{{ item.property.last_change.strftime('%d.%m.%Y %H:%M:%S') }}
{{ item.id() }}{{ item.type() }}{{ item.property.path }}{{ item.property.type }} {{ key }} {% if key in ['precipitation_new', 'clouds_new', 'pressure_new', 'wind_new', 'temp_new'] %}{{ item() }}{% else %} {{ item() }} {% endif %}{{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }}{{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }}{{ item.property.last_update.strftime('%d.%m.%Y %H:%M:%S') }}{{ item.property.last_change.strftime('%d.%m.%Y %H:%M:%S') }}
{{ item.id() }}{{ item.type() }}{{ item.property.path }}{{ item.property.type }} {{ value }} {{ item() }} @@ -60,8 +60,8 @@
{{ _('Nuki Event Items') }} ({{ p.get_event_items()|length }})
{% if item() == 254 %}({{ _('motor blocked') }}){% endif %} {% if item() == 255 %}({{ _('undefined') }}){% endif %}
{{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }}{{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }}{{ item.property.last_update.strftime('%d.%m.%Y %H:%M:%S') }}{{ item.property.last_change.strftime('%d.%m.%Y %H:%M:%S') }}
{{ item.id() }}{{ item.type() }}{{ item._enforce_updates }}
{{ item.property.path }}{{ item.property.type }}{{ item.property.enforce_updates }} {{ value }} {{ item() }} @@ -114,8 +114,8 @@
{{ _('Nuki Action Items') }} ({{ p.get_action_items()|length }})
{% if item() == 4 %}({{ _('lockAndGo') }}){% endif %} {% if item() == 5 %}({{ _('lockAndGoWithUnlatch') }}){% endif %}
{{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }}{{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }}{{ item.property.last_update.strftime('%d.%m.%Y %H:%M:%S') }}{{ item.property.last_change.strftime('%d.%m.%Y %H:%M:%S') }}
@@ -164,16 +164,16 @@
{{ _('Nuki Battery Items') }} ({{ p.get_battery_items()|length }})
{{ item.id() }}{{ item.type() }}{{ item.property.path }}{{ item.property.type }} {{ value }} {{ item() }} {% if item() == 0 %}({{ _('Batteries are good. No need to replace it.') }}){% endif %} {% if item() == 1 %}({{ _('Batteries are low. Please replace as soon as possible!') }}){% endif %} {{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }}{{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }}{{ item.property.last_update.strftime('%d.%m.%Y %H:%M:%S') }}{{ item.property.last_change.strftime('%d.%m.%Y %H:%M:%S') }}
{{ item.id() }}{{ item.type() }}{{ item.property.path }}{{ item.property.type }} {{ key }} {{ item() }}{{ item.last_update().strftime('%d.%m.%Y %H:%M:%S') }}{{ item.last_change().strftime('%d.%m.%Y %H:%M:%S') }}{{ item.property.last_update.strftime('%d.%m.%Y %H:%M:%S') }}{{ item.property.last_change.strftime('%d.%m.%Y %H:%M:%S') }}
+
- +
+ + + + + + + + + + + + + + + + + +
{{ _('Long Polling Timeout') }}{{ p._long_polling_timeout ~ _(' Sekunden')}}
{{ _('Willkommensnachricht') }}{{ p._welcome_msg }}
{{ _('Ende Nachricht') }}{{ p._bye_msg }}
+{% endblock headtable %} + + +{% block buttons %} +{% if 1==2 %} + + + +{% endif %} +{% endblock %} + + +{% set tabcount = 2 %} + + +{% if item_count==0 %} + {% set start_tab = 1 %} +{% endif %} + + + +{% set tab1title = "TAB1" %} +{% block bodytab1 %} +
+ {% autoescape false %} + {{ r | replace("\r\n", "
") }} + {% endautoescape %} +
+{% endblock bodytab1 %} + + + +{% set tab2title = "TAB2" %} +{% block bodytab2 %} +
+ {% for item in items %} +
{{ item }}
+ {% endfor %} +
+{% endblock bodytab2 %} From e2ab610b00ee4ff8fc58421013ec5e5e020e822e Mon Sep 17 00:00:00 2001 From: Oliver Hinckel Date: Thu, 3 Jan 2019 06:25:47 +0100 Subject: [PATCH 535/705] Database: Add `countall` function to README --- database/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/database/README.md b/database/README.md index ab74425df..f990b69ef 100644 --- a/database/README.md +++ b/database/README.md @@ -121,6 +121,7 @@ Supported functions are: * `avg`: for the average value * `count`: for the amount of values not "0" (more examples: `count>10`, `count<10`, `count=10`) + * `countall`: for the amount of values (without checking any condition) * `max`: for the maximum value * `min`: for the minimum value * `on`: percentage (as float from 0.00 to 1.00) where the value has been greater than 0. From cf1f39e4b0c90739adf7136b3a69fee0642ceb7a Mon Sep 17 00:00:00 2001 From: msinn Date: Thu, 3 Jan 2019 09:20:58 +0100 Subject: [PATCH 536/705] stateengine: documentation changes --- stateengine/user_doc/user_doc5.rst | 4 +++- stateengine/user_doc/user_doc8.rst | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/stateengine/user_doc/user_doc5.rst b/stateengine/user_doc/user_doc5.rst index 093244c15..f6c841b56 100644 --- a/stateengine/user_doc/user_doc5.rst +++ b/stateengine/user_doc/user_doc5.rst @@ -23,7 +23,9 @@ als Attribute definiert werden. - **on_leave**: Aktionen, die ausgeführt werden, direkt bevor ein anderer Zustand aktiv wird. -**Beispiel** + +Beispiel +-------- .. code-block:: yaml diff --git a/stateengine/user_doc/user_doc8.rst b/stateengine/user_doc/user_doc8.rst index a944eacdd..9c715dc61 100644 --- a/stateengine/user_doc/user_doc8.rst +++ b/stateengine/user_doc/user_doc8.rst @@ -36,7 +36,7 @@ werden, das heißt ein Vorgabezustand kann also selbst wiederum werden. Um unnötige Komplexität und Zirkelbezüge zu vermeiden, ist die maximale Tiefe jedoch auf 5 Ebenen begrenzt. -.. rubric:: Beispiel +.. rubric:: Beispiel X :name: vorgabebeispiel .. code-block:: yaml From a558ce4cc46eb352cb70850b3eca27ff43e291bb Mon Sep 17 00:00:00 2001 From: msinn Date: Thu, 3 Jan 2019 09:40:02 +0100 Subject: [PATCH 537/705] stateengine: documentation changes --- stateengine/user_doc/user_doc11.rst | 10 ++++++---- stateengine/user_doc/user_doc5.rst | 1 + stateengine/user_doc/user_doc8.rst | 4 ++-- stateengine/user_doc/user_doc9.rst | 10 ++++++---- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/stateengine/user_doc/user_doc11.rst b/stateengine/user_doc/user_doc11.rst index b3ef0b040..9d7acc9a1 100644 --- a/stateengine/user_doc/user_doc11.rst +++ b/stateengine/user_doc/user_doc11.rst @@ -12,8 +12,9 @@ ist. Die Sperre soll aktiv sein, wenn das Sperr-Item den Wert ``True`` hat. -.. rubric:: Das Sperr-Item - :name: dassperritem + +Das Sperr-Item +-------------- Das Sperritem definiert man wie folgt: @@ -27,8 +28,9 @@ Das Sperritem definiert man wie folgt: visu_acl: rw cache: on -.. rubric:: Der Sperrzustand - :name: dersperrzustand + +Der Sperrzustand +---------------- Eine Änderung des Sperr-Items muss direkt eine Zustandsermittlung auslösen, das Sperr-Item wird daher in die diff --git a/stateengine/user_doc/user_doc5.rst b/stateengine/user_doc/user_doc5.rst index f6c841b56..d46cedbb8 100644 --- a/stateengine/user_doc/user_doc5.rst +++ b/stateengine/user_doc/user_doc5.rst @@ -5,6 +5,7 @@ Ausführungszeitpunkt #################### Um festzulegen, wann die Aktionen eines Zustands ausgeführt +Um festzulegen, wann die Aktionen eines Zustands ausgeführtbeding werden, gibt es vier Ereignisse, denen die Aktionen zugeordnet werden können: Für jedes dieser Ereignisse wird ein Item unterhalb des Zustands-Items angelegt, unterhalb dem die jeweiligen Aktionen diff --git a/stateengine/user_doc/user_doc8.rst b/stateengine/user_doc/user_doc8.rst index 9c715dc61..bc9a4b904 100644 --- a/stateengine/user_doc/user_doc8.rst +++ b/stateengine/user_doc/user_doc8.rst @@ -36,8 +36,8 @@ werden, das heißt ein Vorgabezustand kann also selbst wiederum werden. Um unnötige Komplexität und Zirkelbezüge zu vermeiden, ist die maximale Tiefe jedoch auf 5 Ebenen begrenzt. -.. rubric:: Beispiel X - :name: vorgabebeispiel +Beispiel +-------- .. code-block:: yaml diff --git a/stateengine/user_doc/user_doc9.rst b/stateengine/user_doc/user_doc9.rst index 6c3eafe07..cdac7838e 100644 --- a/stateengine/user_doc/user_doc9.rst +++ b/stateengine/user_doc/user_doc9.rst @@ -9,16 +9,17 @@ Funktionen zur Verfügung, die einfach für ``se_set_`` und ``se_run_`` Aktionen verwendet werden können: -.. rubric:: Winkel zum Nachführen der Jalousielamellen auf Basis des Sonnenstands - :name: winkel + +Winkel zum Nachführen der Jalousielamellen auf Basis des Sonnenstands +--------------------------------------------------------------------- .. code-block:: yaml stateengine_eval.sun_tracking() -.. rubric:: Zufallszahl - :name: zufallszahl +Zufallszahl +----------- .. code-block:: yaml @@ -29,6 +30,7 @@ zurückgegeben werden soll, festgelegt werden. ``min`` und ``max`` können weggelassen werden, in diesem Fall sind die Vorgabewerte 0 für ``min`` und 255 für ``max``. + .. rubric:: Shell-Kommando ausführen :name: shellkommandoausfhren From 04b6ea33dfa8cc183df3431dd75e04b66b0af19e Mon Sep 17 00:00:00 2001 From: msinn Date: Thu, 3 Jan 2019 10:17:22 +0100 Subject: [PATCH 538/705] Documentation changes --- stateengine/user_doc/user_doc11.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/stateengine/user_doc/user_doc11.rst b/stateengine/user_doc/user_doc11.rst index 9d7acc9a1..b6153a791 100644 --- a/stateengine/user_doc/user_doc11.rst +++ b/stateengine/user_doc/user_doc11.rst @@ -1,6 +1,5 @@ .. index:: Plugins; Stateengine; Sperren .. index:: Sperren -.. _Lock-Zustand: Sperren ####### From b15d87c9de2b9a813ffaeeaf84cd4e665acbedc9 Mon Sep 17 00:00:00 2001 From: msinn Date: Thu, 3 Jan 2019 11:15:37 +0100 Subject: [PATCH 539/705] Documentation updates --- stateengine/user_doc/user_doc11.rst | 1 + stateengine/user_doc/user_doc8.rst | 4 ++-- wettercom/README.md | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/stateengine/user_doc/user_doc11.rst b/stateengine/user_doc/user_doc11.rst index b6153a791..9d7acc9a1 100644 --- a/stateengine/user_doc/user_doc11.rst +++ b/stateengine/user_doc/user_doc11.rst @@ -1,5 +1,6 @@ .. index:: Plugins; Stateengine; Sperren .. index:: Sperren +.. _Lock-Zustand: Sperren ####### diff --git a/stateengine/user_doc/user_doc8.rst b/stateengine/user_doc/user_doc8.rst index bc9a4b904..a944eacdd 100644 --- a/stateengine/user_doc/user_doc8.rst +++ b/stateengine/user_doc/user_doc8.rst @@ -36,8 +36,8 @@ werden, das heißt ein Vorgabezustand kann also selbst wiederum werden. Um unnötige Komplexität und Zirkelbezüge zu vermeiden, ist die maximale Tiefe jedoch auf 5 Ebenen begrenzt. -Beispiel --------- +.. rubric:: Beispiel + :name: vorgabebeispiel .. code-block:: yaml diff --git a/wettercom/README.md b/wettercom/README.md index 7aeb24672..ac31bf8ff 100755 --- a/wettercom/README.md +++ b/wettercom/README.md @@ -13,8 +13,8 @@ wetter.com account with project, recommended: 3 days, all data transmitted wettercom: class_name: wettercom class_path: plugins.wettercom - apikey: - project: + # apikey: + # project: ``` add your project on wetter.com and paste API-key and project name From a9655bfa634e481529b9766edbf3c8f01a3b3a61 Mon Sep 17 00:00:00 2001 From: msinn Date: Thu, 3 Jan 2019 12:02:38 +0100 Subject: [PATCH 540/705] Documentation changes --- ebus/{README_old.md => README.md.old} | 0 wettercom/README.md | 2 -- 2 files changed, 2 deletions(-) rename ebus/{README_old.md => README.md.old} (100%) diff --git a/ebus/README_old.md b/ebus/README.md.old similarity index 100% rename from ebus/README_old.md rename to ebus/README.md.old diff --git a/wettercom/README.md b/wettercom/README.md index ac31bf8ff..16f7a3198 100755 --- a/wettercom/README.md +++ b/wettercom/README.md @@ -27,8 +27,6 @@ Create a yaml file in the items folder with the following content or copy the fi #### Example ```yaml -%yaml 1.1 ---- wetter: vorhersage: heute: From 247f6e1c8a71b9e98d61c19bc2f4239ee16d66ee Mon Sep 17 00:00:00 2001 From: msinn Date: Thu, 3 Jan 2019 12:03:29 +0100 Subject: [PATCH 541/705] backend: Removed previous version 1.3.5 --- backend/_pv_1_3_5/BackendBlockly.py | 144 - backend/_pv_1_3_5/BackendCore.py | 1034 -- backend/_pv_1_3_5/README.md | 107 - backend/_pv_1_3_5/__init__.py | 215 - backend/_pv_1_3_5/locale/de.json | 194 - backend/_pv_1_3_5/locale/en.json | 192 - backend/_pv_1_3_5/locale/fr.json | 221 - backend/_pv_1_3_5/locale/pl.json | 191 - backend/_pv_1_3_5/plugin.yaml | 24 - backend/_pv_1_3_5/requirements.txt | 3 - .../_pv_1_3_5/static/blockly/CONTRIBUTING.md | 5 - backend/_pv_1_3_5/static/blockly/LICENSE | 177 - backend/_pv_1_3_5/static/blockly/README.md | 8 - .../static/blockly/accessible/README | 54 - .../blockly/accessible/app.component.js | 77 - .../blockly/accessible/audio.service.js | 57 - .../blockly/accessible/clipboard.service.js | 172 - .../blockly/accessible/field.component.js | 138 - .../blockly/accessible/libs/Rx.umd.min.js | 321 - .../accessible/libs/angular2-all.umd.min.js | 18 - .../accessible/libs/angular2-polyfills.min.js | 1 - .../blockly/accessible/libs/es6-shim.min.js | 12 - .../blockly/accessible/media/accessible.css | 12 - .../static/blockly/accessible/media/click.mp3 | Bin 2304 -> 0 bytes .../static/blockly/accessible/media/click.ogg | Bin 4865 -> 0 bytes .../static/blockly/accessible/media/click.wav | Bin 3782 -> 0 bytes .../blockly/accessible/media/delete.mp3 | Bin 3123 -> 0 bytes .../blockly/accessible/media/delete.ogg | Bin 5731 -> 0 bytes .../blockly/accessible/media/delete.wav | Bin 9164 -> 0 bytes .../static/blockly/accessible/messages.js | 73 - .../accessible/notifications.service.js | 46 - .../accessible/toolbox-tree.component.js | 159 - .../blockly/accessible/toolbox.component.js | 148 - .../blockly/accessible/translate.pipe.js | 34 - .../static/blockly/accessible/tree.service.js | 491 - .../blockly/accessible/utils.service.js | 74 - .../accessible/workspace-tree.component.js | 392 - .../blockly/accessible/workspace.component.js | 94 - .../static/blockly/blockly_compressed.js | 1457 --- .../static/blockly/blockly_uncompressed.js | 1674 --- .../static/blockly/blocks_compressed.js | 149 - .../_pv_1_3_5/static/blockly/core/block.js | 1364 -- .../static/blockly/core/block_render_svg.js | 969 -- .../static/blockly/core/block_svg.js | 1629 --- .../_pv_1_3_5/static/blockly/core/blockly.js | 453 - .../_pv_1_3_5/static/blockly/core/blocks.js | 33 - .../_pv_1_3_5/static/blockly/core/bubble.js | 579 - .../_pv_1_3_5/static/blockly/core/comment.js | 278 - .../static/blockly/core/connection.js | 615 - .../static/blockly/core/connection_db.js | 301 - .../static/blockly/core/constants.js | 202 - .../static/blockly/core/contextmenu.js | 148 - backend/_pv_1_3_5/static/blockly/core/css.js | 782 -- .../_pv_1_3_5/static/blockly/core/events.js | 818 -- .../_pv_1_3_5/static/blockly/core/field.js | 495 - .../static/blockly/core/field_angle.js | 294 - .../static/blockly/core/field_checkbox.js | 117 - .../static/blockly/core/field_colour.js | 234 - .../static/blockly/core/field_date.js | 346 - .../static/blockly/core/field_dropdown.js | 320 - .../static/blockly/core/field_image.js | 171 - .../static/blockly/core/field_label.js | 104 - .../static/blockly/core/field_number.js | 101 - .../static/blockly/core/field_textinput.js | 327 - .../static/blockly/core/field_variable.js | 155 - .../_pv_1_3_5/static/blockly/core/flyout.js | 1364 -- .../static/blockly/core/flyout_button.js | 169 - .../static/blockly/core/generator.js | 369 - backend/_pv_1_3_5/static/blockly/core/icon.js | 203 - .../_pv_1_3_5/static/blockly/core/inject.js | 378 - .../_pv_1_3_5/static/blockly/core/input.js | 241 - backend/_pv_1_3_5/static/blockly/core/msg.js | 62 - .../_pv_1_3_5/static/blockly/core/mutator.js | 389 - .../_pv_1_3_5/static/blockly/core/names.js | 143 - .../_pv_1_3_5/static/blockly/core/options.js | 231 - .../static/blockly/core/procedures.js | 287 - .../blockly/core/rendered_connection.js | 395 - .../static/blockly/core/scrollbar.js | 750 -- .../_pv_1_3_5/static/blockly/core/toolbox.js | 650 - .../_pv_1_3_5/static/blockly/core/tooltip.js | 286 - .../_pv_1_3_5/static/blockly/core/trashcan.js | 332 - .../_pv_1_3_5/static/blockly/core/utils.js | 668 - .../static/blockly/core/variables.js | 273 - .../_pv_1_3_5/static/blockly/core/warning.js | 185 - .../static/blockly/core/widgetdiv.js | 152 - .../static/blockly/core/workspace.js | 501 - .../static/blockly/core/workspace_svg.js | 1401 --- backend/_pv_1_3_5/static/blockly/core/xml.js | 566 - .../static/blockly/core/zoom_controls.js | 239 - .../static/blockly/dart_compressed.js | 92 - .../static/blockly/demos/code/style.css | 163 - .../static/blockly/generators/dart.js | 280 - .../static/blockly/generators/dart/colour.js | 128 - .../static/blockly/generators/dart/lists.js | 452 - .../static/blockly/generators/dart/logic.js | 125 - .../static/blockly/generators/dart/loops.js | 163 - .../static/blockly/generators/dart/math.js | 487 - .../blockly/generators/dart/procedures.js | 109 - .../static/blockly/generators/dart/text.js | 297 - .../blockly/generators/dart/variables.js | 46 - .../static/blockly/generators/javascript.js | 323 - .../blockly/generators/javascript/colour.js | 103 - .../blockly/generators/javascript/lists.js | 394 - .../blockly/generators/javascript/logic.js | 126 - .../blockly/generators/javascript/loops.js | 175 - .../blockly/generators/javascript/math.js | 411 - .../generators/javascript/procedures.js | 109 - .../blockly/generators/javascript/text.js | 304 - .../generators/javascript/variables.js | 46 - .../static/blockly/generators/lua.js | 194 - .../static/blockly/generators/lua/colour.js | 90 - .../static/blockly/generators/lua/lists.js | 365 - .../static/blockly/generators/lua/logic.js | 125 - .../static/blockly/generators/lua/loops.js | 166 - .../static/blockly/generators/lua/math.js | 425 - .../blockly/generators/lua/procedures.js | 111 - .../static/blockly/generators/lua/text.js | 294 - .../blockly/generators/lua/variables.js | 46 - .../static/blockly/generators/php.js | 308 - .../static/blockly/generators/php/colour.js | 105 - .../static/blockly/generators/php/lists.js | 504 - .../static/blockly/generators/php/logic.js | 126 - .../static/blockly/generators/php/loops.js | 164 - .../static/blockly/generators/php/math.js | 372 - .../blockly/generators/php/procedures.js | 123 - .../static/blockly/generators/php/text.js | 250 - .../blockly/generators/php/variables.js | 46 - .../static/blockly/generators/python.js | 290 - .../blockly/generators/python/colour.js | 86 - .../static/blockly/generators/python/lists.js | 355 - .../static/blockly/generators/python/logic.js | 127 - .../static/blockly/generators/python/loops.js | 211 - .../static/blockly/generators/python/math.js | 388 - .../blockly/generators/python/procedures.js | 124 - .../static/blockly/generators/python/text.js | 253 - .../blockly/generators/python/variables.js | 46 - .../_pv_1_3_5/static/blockly/i18n/common.py | 234 - .../static/blockly/i18n/create_messages.py | 149 - .../static/blockly/i18n/dedup_json.py | 73 - .../static/blockly/i18n/js_to_json.py | 120 - .../static/blockly/i18n/json_to_js.py | 185 - .../_pv_1_3_5/static/blockly/i18n/tests.py | 47 - .../static/blockly/i18n/xliff_to_json.py | 232 - .../static/blockly/javascript_compressed.js | 91 - .../static/blockly/lua_compressed.js | 74 - .../_pv_1_3_5/static/blockly/media/1x1.gif | Bin 43 -> 0 bytes .../_pv_1_3_5/static/blockly/media/click.mp3 | Bin 2304 -> 0 bytes .../_pv_1_3_5/static/blockly/media/click.ogg | Bin 4865 -> 0 bytes .../_pv_1_3_5/static/blockly/media/click.wav | Bin 3782 -> 0 bytes .../_pv_1_3_5/static/blockly/media/delete.mp3 | Bin 3123 -> 0 bytes .../_pv_1_3_5/static/blockly/media/delete.ogg | Bin 5731 -> 0 bytes .../_pv_1_3_5/static/blockly/media/delete.wav | Bin 9164 -> 0 bytes .../static/blockly/media/disconnect.mp3 | Bin 1586 -> 0 bytes .../static/blockly/media/disconnect.ogg | Bin 4404 -> 0 bytes .../static/blockly/media/disconnect.wav | Bin 1492 -> 0 bytes .../static/blockly/media/handclosed.cur | Bin 326 -> 0 bytes .../static/blockly/media/handdelete.cur | Bin 766 -> 0 bytes .../static/blockly/media/handopen.cur | Bin 198 -> 0 bytes .../_pv_1_3_5/static/blockly/media/quote0.png | Bin 796 -> 0 bytes .../_pv_1_3_5/static/blockly/media/quote1.png | Bin 738 -> 0 bytes .../static/blockly/media/sprites.png | Bin 4146 -> 0 bytes .../static/blockly/media/sprites.svg | 74 - backend/_pv_1_3_5/static/blockly/msg/js/ar.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/az.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/ba.js | 391 - .../_pv_1_3_5/static/blockly/msg/js/bcc.js | 391 - .../static/blockly/msg/js/be-tarask.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/bg.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/bn.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/br.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/ca.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/cs.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/da.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/de.js | 391 - .../_pv_1_3_5/static/blockly/msg/js/diq.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/el.js | 391 - .../_pv_1_3_5/static/blockly/msg/js/en-gb.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/en.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/es.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/et.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/fa.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/fi.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/fr.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/he.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/hi.js | 391 - .../_pv_1_3_5/static/blockly/msg/js/hrx.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/hu.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/ia.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/id.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/is.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/it.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/ja.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/ko.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/lb.js | 391 - .../_pv_1_3_5/static/blockly/msg/js/lki.js | 391 - .../_pv_1_3_5/static/blockly/msg/js/lrc.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/lt.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/mk.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/ms.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/nb.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/nl.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/oc.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/pl.js | 391 - .../_pv_1_3_5/static/blockly/msg/js/pms.js | 391 - .../_pv_1_3_5/static/blockly/msg/js/pt-br.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/pt.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/ro.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/ru.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/sc.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/sd.js | 391 - .../_pv_1_3_5/static/blockly/msg/js/shn.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/sk.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/sl.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/sq.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/sr.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/sv.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/ta.js | 391 - .../_pv_1_3_5/static/blockly/msg/js/tcy.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/th.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/tl.js | 391 - .../_pv_1_3_5/static/blockly/msg/js/tlh.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/tr.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/uk.js | 391 - backend/_pv_1_3_5/static/blockly/msg/js/vi.js | 391 - .../static/blockly/msg/js/zh-hans.js | 391 - .../static/blockly/msg/js/zh-hant.js | 391 - .../_pv_1_3_5/static/blockly/msg/json/ar.json | 316 - .../_pv_1_3_5/static/blockly/msg/json/az.json | 296 - .../_pv_1_3_5/static/blockly/msg/json/ba.json | 210 - .../static/blockly/msg/json/bcc.json | 289 - .../static/blockly/msg/json/be-tarask.json | 314 - .../_pv_1_3_5/static/blockly/msg/json/bg.json | 312 - .../_pv_1_3_5/static/blockly/msg/json/bn.json | 156 - .../_pv_1_3_5/static/blockly/msg/json/br.json | 315 - .../_pv_1_3_5/static/blockly/msg/json/ca.json | 293 - .../_pv_1_3_5/static/blockly/msg/json/cs.json | 331 - .../_pv_1_3_5/static/blockly/msg/json/da.json | 303 - .../_pv_1_3_5/static/blockly/msg/json/de.json | 350 - .../static/blockly/msg/json/diq.json | 171 - .../_pv_1_3_5/static/blockly/msg/json/el.json | 336 - .../static/blockly/msg/json/en-gb.json | 139 - .../_pv_1_3_5/static/blockly/msg/json/en.json | 371 - .../_pv_1_3_5/static/blockly/msg/json/es.json | 321 - .../_pv_1_3_5/static/blockly/msg/json/et.json | 310 - .../_pv_1_3_5/static/blockly/msg/json/fa.json | 309 - .../_pv_1_3_5/static/blockly/msg/json/fi.json | 330 - .../_pv_1_3_5/static/blockly/msg/json/fr.json | 325 - .../_pv_1_3_5/static/blockly/msg/json/he.json | 277 - .../_pv_1_3_5/static/blockly/msg/json/hi.json | 251 - .../static/blockly/msg/json/hrx.json | 289 - .../_pv_1_3_5/static/blockly/msg/json/hu.json | 327 - .../_pv_1_3_5/static/blockly/msg/json/ia.json | 298 - .../_pv_1_3_5/static/blockly/msg/json/id.json | 335 - .../_pv_1_3_5/static/blockly/msg/json/is.json | 357 - .../_pv_1_3_5/static/blockly/msg/json/it.json | 317 - .../_pv_1_3_5/static/blockly/msg/json/ja.json | 328 - .../_pv_1_3_5/static/blockly/msg/json/ko.json | 376 - .../_pv_1_3_5/static/blockly/msg/json/lb.json | 126 - .../static/blockly/msg/json/lki.json | 296 - .../static/blockly/msg/json/lrc.json | 133 - .../_pv_1_3_5/static/blockly/msg/json/lt.json | 257 - .../_pv_1_3_5/static/blockly/msg/json/mk.json | 112 - .../_pv_1_3_5/static/blockly/msg/json/ms.json | 314 - .../_pv_1_3_5/static/blockly/msg/json/nb.json | 324 - .../_pv_1_3_5/static/blockly/msg/json/nl.json | 361 - .../_pv_1_3_5/static/blockly/msg/json/oc.json | 122 - .../_pv_1_3_5/static/blockly/msg/json/pl.json | 345 - .../static/blockly/msg/json/pms.json | 314 - .../static/blockly/msg/json/pt-br.json | 327 - .../_pv_1_3_5/static/blockly/msg/json/pt.json | 326 - .../static/blockly/msg/json/qqq.json | 372 - .../_pv_1_3_5/static/blockly/msg/json/ro.json | 318 - .../_pv_1_3_5/static/blockly/msg/json/ru.json | 320 - .../_pv_1_3_5/static/blockly/msg/json/sc.json | 299 - .../_pv_1_3_5/static/blockly/msg/json/sd.json | 126 - .../static/blockly/msg/json/shn.json | 108 - .../_pv_1_3_5/static/blockly/msg/json/sk.json | 304 - .../_pv_1_3_5/static/blockly/msg/json/sl.json | 360 - .../_pv_1_3_5/static/blockly/msg/json/sq.json | 305 - .../_pv_1_3_5/static/blockly/msg/json/sr.json | 332 - .../_pv_1_3_5/static/blockly/msg/json/sv.json | 337 - .../static/blockly/msg/json/synonyms.json | 1 - .../_pv_1_3_5/static/blockly/msg/json/ta.json | 298 - .../static/blockly/msg/json/tcy.json | 307 - .../_pv_1_3_5/static/blockly/msg/json/th.json | 311 - .../_pv_1_3_5/static/blockly/msg/json/tl.json | 305 - .../static/blockly/msg/json/tlh.json | 182 - .../_pv_1_3_5/static/blockly/msg/json/tr.json | 351 - .../_pv_1_3_5/static/blockly/msg/json/uk.json | 332 - .../_pv_1_3_5/static/blockly/msg/json/vi.json | 298 - .../static/blockly/msg/json/zh-hans.json | 336 - .../static/blockly/msg/json/zh-hant.json | 319 - .../_pv_1_3_5/static/blockly/msg/messages.js | 1113 -- .../static/blockly/php_compressed.js | 84 - .../static/blockly/python_compressed.js | 79 - backend/_pv_1_3_5/static/codemirror/AUTHORS | 625 - .../_pv_1_3_5/static/codemirror/CHANGELOG.md | 984 -- .../static/codemirror/CONTRIBUTING.md | 88 - backend/_pv_1_3_5/static/codemirror/LICENSE | 19 - backend/_pv_1_3_5/static/codemirror/README.md | 34 - .../codemirror/addon/comment/comment.js | 206 - .../addon/comment/continuecomment.js | 85 - .../static/codemirror/addon/dialog/dialog.css | 32 - .../static/codemirror/addon/dialog/dialog.js | 157 - .../codemirror/addon/display/autorefresh.js | 47 - .../codemirror/addon/display/fullscreen.css | 6 - .../codemirror/addon/display/fullscreen.js | 41 - .../static/codemirror/addon/display/panel.js | 123 - .../codemirror/addon/display/placeholder.js | 62 - .../static/codemirror/addon/display/rulers.js | 51 - .../codemirror/addon/edit/closebrackets.js | 202 - .../static/codemirror/addon/edit/closetag.js | 169 - .../codemirror/addon/edit/continuelist.js | 51 - .../codemirror/addon/edit/matchbrackets.js | 122 - .../static/codemirror/addon/edit/matchtags.js | 66 - .../codemirror/addon/edit/trailingspace.js | 27 - .../codemirror/addon/fold/brace-fold.js | 105 - .../codemirror/addon/fold/comment-fold.js | 59 - .../static/codemirror/addon/fold/foldcode.js | 150 - .../codemirror/addon/fold/foldgutter.css | 20 - .../codemirror/addon/fold/foldgutter.js | 146 - .../codemirror/addon/fold/indent-fold.js | 44 - .../codemirror/addon/fold/markdown-fold.js | 49 - .../static/codemirror/addon/fold/xml-fold.js | 182 - .../codemirror/addon/hint/anyword-hint.js | 41 - .../static/codemirror/addon/hint/css-hint.js | 60 - .../static/codemirror/addon/hint/html-hint.js | 348 - .../codemirror/addon/hint/javascript-hint.js | 155 - .../codemirror/addon/hint/show-hint.css | 36 - .../static/codemirror/addon/hint/show-hint.js | 438 - .../static/codemirror/addon/hint/sql-hint.js | 271 - .../static/codemirror/addon/hint/xml-hint.js | 110 - .../addon/lint/coffeescript-lint.js | 41 - .../static/codemirror/addon/lint/css-lint.js | 35 - .../static/codemirror/addon/lint/html-lint.js | 46 - .../codemirror/addon/lint/javascript-lint.js | 136 - .../static/codemirror/addon/lint/json-lint.js | 31 - .../static/codemirror/addon/lint/lint.css | 73 - .../static/codemirror/addon/lint/lint.js | 239 - .../static/codemirror/addon/lint/yaml-lint.js | 28 - .../static/codemirror/addon/merge/merge.css | 113 - .../static/codemirror/addon/merge/merge.js | 795 -- .../static/codemirror/addon/mode/loadmode.js | 64 - .../static/codemirror/addon/mode/multiplex.js | 123 - .../codemirror/addon/mode/multiplex_test.js | 33 - .../static/codemirror/addon/mode/overlay.js | 90 - .../static/codemirror/addon/mode/simple.js | 213 - .../codemirror/addon/runmode/colorize.js | 40 - .../addon/runmode/runmode-standalone.js | 157 - .../codemirror/addon/runmode/runmode.js | 72 - .../codemirror/addon/runmode/runmode.node.js | 179 - .../addon/scroll/annotatescrollbar.js | 118 - .../codemirror/addon/scroll/scrollpastend.js | 48 - .../addon/scroll/simplescrollbars.css | 66 - .../addon/scroll/simplescrollbars.js | 152 - .../codemirror/addon/search/jump-to-line.js | 49 - .../addon/search/match-highlighter.js | 165 - .../addon/search/matchesonscrollbar.css | 8 - .../addon/search/matchesonscrollbar.js | 97 - .../static/codemirror/addon/search/search.js | 252 - .../codemirror/addon/search/searchcursor.js | 189 - .../codemirror/addon/selection/active-line.js | 72 - .../addon/selection/mark-selection.js | 118 - .../addon/selection/selection-pointer.js | 98 - .../static/codemirror/addon/tern/tern.css | 87 - .../static/codemirror/addon/tern/tern.js | 701 -- .../static/codemirror/addon/tern/worker.js | 44 - .../static/codemirror/addon/wrap/hardwrap.js | 144 - .../static/codemirror/bin/authors.sh | 6 - .../_pv_1_3_5/static/codemirror/bin/compress | 92 - backend/_pv_1_3_5/static/codemirror/bin/lint | 3 - .../_pv_1_3_5/static/codemirror/bin/release | 38 - .../static/codemirror/bin/source-highlight | 48 - .../static/codemirror/bin/upload-release.js | 35 - .../_pv_1_3_5/static/codemirror/bower.json | 17 - .../static/codemirror/doc/activebookmark.js | 57 - .../_pv_1_3_5/static/codemirror/doc/docs.css | 271 - .../static/codemirror/doc/internals.html | 504 - .../_pv_1_3_5/static/codemirror/doc/logo.png | Bin 9310 -> 0 bytes .../_pv_1_3_5/static/codemirror/doc/logo.svg | 181 - .../static/codemirror/doc/manual.html | 3433 ------ .../static/codemirror/doc/realworld.html | 187 - .../static/codemirror/doc/releases.html | 1386 --- .../static/codemirror/doc/reporting.html | 61 - .../static/codemirror/doc/upgrade_v2.2.html | 96 - .../static/codemirror/doc/upgrade_v3.html | 230 - .../static/codemirror/doc/upgrade_v4.html | 144 - .../static/codemirror/doc/yinyang.png | Bin 4633 -> 0 bytes .../_pv_1_3_5/static/codemirror/index.html | 199 - .../static/codemirror/keymap/emacs.js | 414 - .../static/codemirror/keymap/sublime.js | 589 - .../_pv_1_3_5/static/codemirror/keymap/vim.js | 5088 -------- .../static/codemirror/lib/codemirror.css | 341 - .../static/codemirror/lib/codemirror.js | 9113 -------------- .../static/codemirror/mode/apl/apl.js | 174 - .../static/codemirror/mode/apl/index.html | 72 - .../codemirror/mode/asciiarmor/asciiarmor.js | 73 - .../codemirror/mode/asciiarmor/index.html | 46 - .../static/codemirror/mode/asn.1/asn.1.js | 204 - .../static/codemirror/mode/asn.1/index.html | 77 - .../codemirror/mode/asterisk/asterisk.js | 196 - .../codemirror/mode/asterisk/index.html | 154 - .../codemirror/mode/brainfuck/brainfuck.js | 85 - .../codemirror/mode/brainfuck/index.html | 85 - .../static/codemirror/mode/clike/clike.js | 785 -- .../static/codemirror/mode/clike/index.html | 360 - .../static/codemirror/mode/clike/scala.html | 767 -- .../static/codemirror/mode/clike/test.js | 55 - .../static/codemirror/mode/clojure/clojure.js | 306 - .../static/codemirror/mode/clojure/index.html | 91 - .../static/codemirror/mode/cmake/cmake.js | 97 - .../static/codemirror/mode/cmake/index.html | 129 - .../static/codemirror/mode/cobol/cobol.js | 255 - .../static/codemirror/mode/cobol/index.html | 210 - .../mode/coffeescript/coffeescript.js | 355 - .../codemirror/mode/coffeescript/index.html | 740 -- .../codemirror/mode/commonlisp/commonlisp.js | 124 - .../codemirror/mode/commonlisp/index.html | 177 - .../static/codemirror/mode/crystal/crystal.js | 391 - .../static/codemirror/mode/crystal/index.html | 119 - .../static/codemirror/mode/css/css.js | 825 -- .../static/codemirror/mode/css/gss.html | 103 - .../static/codemirror/mode/css/gss_test.js | 17 - .../static/codemirror/mode/css/index.html | 75 - .../static/codemirror/mode/css/less.html | 152 - .../static/codemirror/mode/css/less_test.js | 54 - .../static/codemirror/mode/css/scss.html | 157 - .../static/codemirror/mode/css/scss_test.js | 110 - .../static/codemirror/mode/css/test.js | 200 - .../static/codemirror/mode/cypher/cypher.js | 150 - .../static/codemirror/mode/cypher/index.html | 63 - .../static/codemirror/mode/cypher/test.js | 37 - .../_pv_1_3_5/static/codemirror/mode/d/d.js | 218 - .../static/codemirror/mode/d/index.html | 273 - .../static/codemirror/mode/dart/dart.js | 157 - .../static/codemirror/mode/dart/index.html | 71 - .../static/codemirror/mode/diff/diff.js | 47 - .../static/codemirror/mode/diff/index.html | 117 - .../static/codemirror/mode/django/django.js | 356 - .../static/codemirror/mode/django/index.html | 73 - .../codemirror/mode/dockerfile/dockerfile.js | 79 - .../codemirror/mode/dockerfile/index.html | 73 - .../static/codemirror/mode/dtd/dtd.js | 142 - .../static/codemirror/mode/dtd/index.html | 89 - .../static/codemirror/mode/dylan/dylan.js | 344 - .../static/codemirror/mode/dylan/index.html | 407 - .../static/codemirror/mode/dylan/test.js | 88 - .../static/codemirror/mode/ebnf/ebnf.js | 195 - .../static/codemirror/mode/ebnf/index.html | 102 - .../static/codemirror/mode/ecl/ecl.js | 206 - .../static/codemirror/mode/ecl/index.html | 52 - .../static/codemirror/mode/eiffel/eiffel.js | 160 - .../static/codemirror/mode/eiffel/index.html | 429 - .../static/codemirror/mode/elm/elm.js | 205 - .../static/codemirror/mode/elm/index.html | 61 - .../static/codemirror/mode/erlang/erlang.js | 619 - .../static/codemirror/mode/erlang/index.html | 76 - .../static/codemirror/mode/factor/factor.js | 83 - .../static/codemirror/mode/factor/index.html | 77 - .../static/codemirror/mode/fcl/fcl.js | 173 - .../static/codemirror/mode/fcl/index.html | 108 - .../static/codemirror/mode/forth/forth.js | 180 - .../static/codemirror/mode/forth/index.html | 75 - .../static/codemirror/mode/fortran/fortran.js | 188 - .../static/codemirror/mode/fortran/index.html | 81 - .../static/codemirror/mode/gas/gas.js | 345 - .../static/codemirror/mode/gas/index.html | 68 - .../static/codemirror/mode/gfm/gfm.js | 130 - .../static/codemirror/mode/gfm/index.html | 93 - .../static/codemirror/mode/gfm/test.js | 236 - .../static/codemirror/mode/gherkin/gherkin.js | 178 - .../static/codemirror/mode/gherkin/index.html | 48 - .../_pv_1_3_5/static/codemirror/mode/go/go.js | 186 - .../static/codemirror/mode/go/index.html | 85 - .../static/codemirror/mode/groovy/groovy.js | 230 - .../static/codemirror/mode/groovy/index.html | 84 - .../static/codemirror/mode/haml/haml.js | 161 - .../static/codemirror/mode/haml/index.html | 79 - .../static/codemirror/mode/haml/test.js | 97 - .../codemirror/mode/handlebars/handlebars.js | 62 - .../codemirror/mode/handlebars/index.html | 79 - .../mode/haskell-literate/haskell-literate.js | 43 - .../mode/haskell-literate/index.html | 282 - .../static/codemirror/mode/haskell/haskell.js | 267 - .../static/codemirror/mode/haskell/index.html | 73 - .../static/codemirror/mode/haxe/haxe.js | 515 - .../static/codemirror/mode/haxe/index.html | 124 - .../mode/htmlembedded/htmlembedded.js | 28 - .../codemirror/mode/htmlembedded/index.html | 60 - .../codemirror/mode/htmlmixed/htmlmixed.js | 152 - .../codemirror/mode/htmlmixed/index.html | 100 - .../static/codemirror/mode/http/http.js | 113 - .../static/codemirror/mode/http/index.html | 45 - .../static/codemirror/mode/idl/idl.js | 290 - .../static/codemirror/mode/idl/index.html | 64 - .../static/codemirror/mode/index.html | 165 - .../codemirror/mode/javascript/index.html | 114 - .../codemirror/mode/javascript/javascript.js | 797 -- .../codemirror/mode/javascript/json-ld.html | 72 - .../static/codemirror/mode/javascript/test.js | 307 - .../mode/javascript/typescript.html | 61 - .../static/codemirror/mode/jinja2/index.html | 54 - .../static/codemirror/mode/jinja2/jinja2.js | 142 - .../static/codemirror/mode/jsx/index.html | 89 - .../static/codemirror/mode/jsx/jsx.js | 148 - .../static/codemirror/mode/jsx/test.js | 69 - .../static/codemirror/mode/julia/index.html | 195 - .../static/codemirror/mode/julia/julia.js | 410 - .../codemirror/mode/livescript/index.html | 459 - .../codemirror/mode/livescript/livescript.js | 280 - .../static/codemirror/mode/lua/index.html | 85 - .../static/codemirror/mode/lua/lua.js | 159 - .../codemirror/mode/markdown/index.html | 361 - .../codemirror/mode/markdown/markdown.js | 813 -- .../static/codemirror/mode/markdown/test.js | 989 -- .../codemirror/mode/mathematica/index.html | 72 - .../mode/mathematica/mathematica.js | 176 - .../static/codemirror/mode/mbox/index.html | 44 - .../static/codemirror/mode/mbox/mbox.js | 129 - .../_pv_1_3_5/static/codemirror/mode/meta.js | 212 - .../static/codemirror/mode/mirc/index.html | 160 - .../static/codemirror/mode/mirc/mirc.js | 193 - .../static/codemirror/mode/mllike/index.html | 179 - .../static/codemirror/mode/mllike/mllike.js | 208 - .../codemirror/mode/modelica/index.html | 67 - .../codemirror/mode/modelica/modelica.js | 245 - .../static/codemirror/mode/mscgen/index.html | 151 - .../static/codemirror/mode/mscgen/mscgen.js | 175 - .../codemirror/mode/mscgen/mscgen_test.js | 83 - .../codemirror/mode/mscgen/msgenny_test.js | 76 - .../static/codemirror/mode/mscgen/xu_test.js | 86 - .../static/codemirror/mode/mumps/index.html | 85 - .../static/codemirror/mode/mumps/mumps.js | 148 - .../static/codemirror/mode/nginx/index.html | 181 - .../static/codemirror/mode/nginx/nginx.js | 178 - .../static/codemirror/mode/nsis/index.html | 80 - .../static/codemirror/mode/nsis/nsis.js | 95 - .../codemirror/mode/ntriples/index.html | 45 - .../codemirror/mode/ntriples/ntriples.js | 186 - .../static/codemirror/mode/octave/index.html | 83 - .../static/codemirror/mode/octave/octave.js | 135 - .../static/codemirror/mode/oz/index.html | 59 - .../_pv_1_3_5/static/codemirror/mode/oz/oz.js | 252 - .../static/codemirror/mode/pascal/index.html | 61 - .../static/codemirror/mode/pascal/pascal.js | 109 - .../static/codemirror/mode/pegjs/index.html | 66 - .../static/codemirror/mode/pegjs/pegjs.js | 114 - .../static/codemirror/mode/perl/index.html | 75 - .../static/codemirror/mode/perl/perl.js | 837 -- .../static/codemirror/mode/php/index.html | 64 - .../static/codemirror/mode/php/php.js | 234 - .../static/codemirror/mode/php/test.js | 154 - .../static/codemirror/mode/pig/index.html | 53 - .../static/codemirror/mode/pig/pig.js | 178 - .../codemirror/mode/powershell/index.html | 204 - .../codemirror/mode/powershell/powershell.js | 396 - .../static/codemirror/mode/powershell/test.js | 72 - .../codemirror/mode/properties/index.html | 53 - .../codemirror/mode/properties/properties.js | 78 - .../codemirror/mode/protobuf/index.html | 64 - .../codemirror/mode/protobuf/protobuf.js | 68 - .../static/codemirror/mode/pug/index.html | 70 - .../static/codemirror/mode/pug/pug.js | 591 - .../static/codemirror/mode/puppet/index.html | 121 - .../static/codemirror/mode/puppet/puppet.js | 220 - .../static/codemirror/mode/python/index.html | 198 - .../static/codemirror/mode/python/python.js | 340 - .../static/codemirror/mode/python/test.js | 30 - .../static/codemirror/mode/q/index.html | 144 - .../_pv_1_3_5/static/codemirror/mode/q/q.js | 139 - .../static/codemirror/mode/r/index.html | 88 - .../_pv_1_3_5/static/codemirror/mode/r/r.js | 171 - .../codemirror/mode/rpm/changes/index.html | 66 - .../static/codemirror/mode/rpm/index.html | 149 - .../static/codemirror/mode/rpm/rpm.js | 109 - .../static/codemirror/mode/rst/index.html | 535 - .../static/codemirror/mode/rst/rst.js | 557 - .../static/codemirror/mode/ruby/index.html | 183 - .../static/codemirror/mode/ruby/ruby.js | 285 - .../static/codemirror/mode/ruby/test.js | 14 - .../static/codemirror/mode/rust/index.html | 64 - .../static/codemirror/mode/rust/rust.js | 71 - .../static/codemirror/mode/rust/test.js | 39 - .../static/codemirror/mode/sas/index.html | 81 - .../static/codemirror/mode/sas/sas.js | 316 - .../static/codemirror/mode/sass/index.html | 66 - .../static/codemirror/mode/sass/sass.js | 414 - .../static/codemirror/mode/scheme/index.html | 77 - .../static/codemirror/mode/scheme/scheme.js | 249 - .../static/codemirror/mode/shell/index.html | 66 - .../static/codemirror/mode/shell/shell.js | 140 - .../static/codemirror/mode/shell/test.js | 58 - .../static/codemirror/mode/sieve/index.html | 93 - .../static/codemirror/mode/sieve/sieve.js | 193 - .../static/codemirror/mode/slim/index.html | 96 - .../static/codemirror/mode/slim/slim.js | 575 - .../static/codemirror/mode/slim/test.js | 96 - .../codemirror/mode/smalltalk/index.html | 68 - .../codemirror/mode/smalltalk/smalltalk.js | 168 - .../static/codemirror/mode/smarty/index.html | 138 - .../static/codemirror/mode/smarty/smarty.js | 225 - .../static/codemirror/mode/solr/index.html | 57 - .../static/codemirror/mode/solr/solr.js | 104 - .../static/codemirror/mode/soy/index.html | 68 - .../static/codemirror/mode/soy/soy.js | 303 - .../static/codemirror/mode/soy/test.js | 83 - .../static/codemirror/mode/sparql/index.html | 61 - .../static/codemirror/mode/sparql/sparql.js | 180 - .../codemirror/mode/spreadsheet/index.html | 42 - .../mode/spreadsheet/spreadsheet.js | 112 - .../static/codemirror/mode/sql/index.html | 86 - .../static/codemirror/mode/sql/sql.js | 413 - .../static/codemirror/mode/stex/index.html | 110 - .../static/codemirror/mode/stex/stex.js | 251 - .../static/codemirror/mode/stex/test.js | 123 - .../static/codemirror/mode/stylus/index.html | 106 - .../static/codemirror/mode/stylus/stylus.js | 769 -- .../static/codemirror/mode/swift/index.html | 88 - .../static/codemirror/mode/swift/swift.js | 210 - .../static/codemirror/mode/swift/test.js | 149 - .../static/codemirror/mode/tcl/index.html | 142 - .../static/codemirror/mode/tcl/tcl.js | 139 - .../static/codemirror/mode/textile/index.html | 191 - .../static/codemirror/mode/textile/test.js | 417 - .../static/codemirror/mode/textile/textile.js | 469 - .../codemirror/mode/tiddlywiki/index.html | 154 - .../codemirror/mode/tiddlywiki/tiddlywiki.css | 14 - .../codemirror/mode/tiddlywiki/tiddlywiki.js | 308 - .../static/codemirror/mode/tiki/index.html | 95 - .../static/codemirror/mode/tiki/tiki.css | 26 - .../static/codemirror/mode/tiki/tiki.js | 312 - .../static/codemirror/mode/toml/index.html | 73 - .../static/codemirror/mode/toml/toml.js | 88 - .../static/codemirror/mode/tornado/index.html | 63 - .../static/codemirror/mode/tornado/tornado.js | 68 - .../static/codemirror/mode/troff/index.html | 146 - .../static/codemirror/mode/troff/troff.js | 84 - .../codemirror/mode/ttcn-cfg/index.html | 115 - .../codemirror/mode/ttcn-cfg/ttcn-cfg.js | 214 - .../static/codemirror/mode/ttcn/index.html | 118 - .../static/codemirror/mode/ttcn/ttcn.js | 283 - .../static/codemirror/mode/turtle/index.html | 50 - .../static/codemirror/mode/turtle/turtle.js | 162 - .../static/codemirror/mode/twig/index.html | 45 - .../static/codemirror/mode/twig/twig.js | 141 - .../static/codemirror/mode/vb/index.html | 102 - .../_pv_1_3_5/static/codemirror/mode/vb/vb.js | 276 - .../codemirror/mode/vbscript/index.html | 55 - .../codemirror/mode/vbscript/vbscript.js | 350 - .../codemirror/mode/velocity/index.html | 120 - .../codemirror/mode/velocity/velocity.js | 201 - .../static/codemirror/mode/verilog/index.html | 120 - .../static/codemirror/mode/verilog/test.js | 273 - .../static/codemirror/mode/verilog/verilog.js | 675 - .../static/codemirror/mode/vhdl/index.html | 95 - .../static/codemirror/mode/vhdl/vhdl.js | 189 - .../static/codemirror/mode/vue/index.html | 69 - .../static/codemirror/mode/vue/vue.js | 70 - .../static/codemirror/mode/webidl/index.html | 71 - .../static/codemirror/mode/webidl/webidl.js | 195 - .../static/codemirror/mode/xml/index.html | 61 - .../static/codemirror/mode/xml/test.js | 51 - .../static/codemirror/mode/xml/xml.js | 394 - .../static/codemirror/mode/xquery/index.html | 210 - .../static/codemirror/mode/xquery/test.js | 67 - .../static/codemirror/mode/xquery/xquery.js | 437 - .../static/codemirror/mode/yacas/index.html | 87 - .../static/codemirror/mode/yacas/yacas.js | 204 - .../mode/yaml-frontmatter/index.html | 121 - .../mode/yaml-frontmatter/yaml-frontmatter.js | 68 - .../static/codemirror/mode/yaml/index.html | 80 - .../static/codemirror/mode/yaml/yaml.js | 118 - .../static/codemirror/mode/z80/index.html | 53 - .../static/codemirror/mode/z80/z80.js | 116 - .../_pv_1_3_5/static/codemirror/package.json | 48 - .../static/codemirror/rollup.config.js | 18 - .../static/codemirror/test/comment_test.js | 114 - .../static/codemirror/test/doc_test.js | 371 - .../static/codemirror/test/driver.js | 138 - .../static/codemirror/test/emacs_test.js | 147 - .../static/codemirror/test/index.html | 264 - .../_pv_1_3_5/static/codemirror/test/lint.js | 19 - .../static/codemirror/test/mode_test.css | 23 - .../static/codemirror/test/mode_test.js | 192 - .../static/codemirror/test/multi_test.js | 285 - .../static/codemirror/test/phantom_driver.js | 31 - .../_pv_1_3_5/static/codemirror/test/run.js | 31 - .../static/codemirror/test/scroll_test.js | 115 - .../static/codemirror/test/search_test.js | 62 - .../static/codemirror/test/sql-hint-test.js | 189 - .../static/codemirror/test/sublime_test.js | 307 - .../_pv_1_3_5/static/codemirror/test/test.js | 2200 ---- .../static/codemirror/test/vim_test.js | 4073 ------ .../static/codemirror/theme/3024-day.css | 41 - .../static/codemirror/theme/3024-night.css | 39 - .../static/codemirror/theme/abcdef.css | 32 - .../codemirror/theme/ambiance-mobile.css | 5 - .../static/codemirror/theme/ambiance.css | 74 - .../static/codemirror/theme/base16-dark.css | 38 - .../static/codemirror/theme/base16-light.css | 38 - .../static/codemirror/theme/bespin.css | 34 - .../static/codemirror/theme/blackboard.css | 32 - .../static/codemirror/theme/cobalt.css | 25 - .../static/codemirror/theme/colorforth.css | 33 - .../static/codemirror/theme/dracula.css | 40 - .../static/codemirror/theme/duotone-dark.css | 35 - .../static/codemirror/theme/duotone-light.css | 36 - .../static/codemirror/theme/eclipse.css | 23 - .../static/codemirror/theme/elegant.css | 13 - .../static/codemirror/theme/erlang-dark.css | 34 - .../static/codemirror/theme/hopscotch.css | 34 - .../static/codemirror/theme/icecoder.css | 43 - .../static/codemirror/theme/isotope.css | 34 - .../static/codemirror/theme/lesser-dark.css | 47 - .../static/codemirror/theme/liquibyte.css | 95 - .../static/codemirror/theme/material.css | 53 - .../_pv_1_3_5/static/codemirror/theme/mbo.css | 37 - .../static/codemirror/theme/mdn-like.css | 46 - .../static/codemirror/theme/midnight.css | 45 - .../static/codemirror/theme/monokai.css | 36 - .../static/codemirror/theme/neat.css | 12 - .../_pv_1_3_5/static/codemirror/theme/neo.css | 43 - .../static/codemirror/theme/night.css | 27 - .../static/codemirror/theme/panda-syntax.css | 85 - .../static/codemirror/theme/paraiso-dark.css | 38 - .../static/codemirror/theme/paraiso-light.css | 38 - .../codemirror/theme/pastel-on-dark.css | 52 - .../static/codemirror/theme/railscasts.css | 34 - .../static/codemirror/theme/rubyblue.css | 25 - .../static/codemirror/theme/seti.css | 44 - .../static/codemirror/theme/solarized.css | 169 - .../static/codemirror/theme/the-matrix.css | 30 - .../theme/tomorrow-night-bright.css | 35 - .../theme/tomorrow-night-eighties.css | 38 - .../static/codemirror/theme/ttcn.css | 64 - .../static/codemirror/theme/twilight.css | 32 - .../static/codemirror/theme/vibrant-ink.css | 34 - .../static/codemirror/theme/xq-dark.css | 53 - .../static/codemirror/theme/xq-light.css | 43 - .../static/codemirror/theme/yeti.css | 44 - .../static/codemirror/theme/zenburn.css | 37 - .../_pv_1_3_5/static/css/bootstrap-reload.css | 20 - .../_pv_1_3_5/static/css/bootstrap-theme.css | 587 - .../static/css/bootstrap-theme.css.map | 1 - .../static/css/bootstrap-theme.min.css | 6 - .../static/css/bootstrap-theme.min.css.map | 1 - .../static/css/bootstrap-treeview.css | 37 - .../static/css/bootstrap-treeview.min.css | 1 - backend/_pv_1_3_5/static/css/bootstrap.css | 6757 ---------- .../_pv_1_3_5/static/css/bootstrap.css.map | 1 - .../_pv_1_3_5/static/css/bootstrap.min.css | 6 - .../static/css/bootstrap.min.css.map | 1 - backend/_pv_1_3_5/static/css/font-awesome.css | 2337 ---- .../_pv_1_3_5/static/css/font-awesome.min.css | 4 - .../_pv_1_3_5/static/fonts/FontAwesome.otf | Bin 134808 -> 0 bytes .../static/fonts/fontawesome-webfont.eot | Bin 165742 -> 0 bytes .../static/fonts/fontawesome-webfont.svg | 2671 ---- .../static/fonts/fontawesome-webfont.ttf | Bin 165548 -> 0 bytes .../static/fonts/fontawesome-webfont.woff | Bin 98024 -> 0 bytes .../static/fonts/fontawesome-webfont.woff2 | Bin 77160 -> 0 bytes .../fonts/glyphicons-halflings-regular.eot | Bin 20127 -> 0 bytes .../fonts/glyphicons-halflings-regular.svg | 288 - .../fonts/glyphicons-halflings-regular.ttf | Bin 45404 -> 0 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 23424 -> 0 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 18028 -> 0 bytes backend/_pv_1_3_5/static/img/NIC.svg | 1877 --- backend/_pv_1_3_5/static/img/cache.svg | 31 - backend/_pv_1_3_5/static/img/clock.svg | 107 - backend/_pv_1_3_5/static/img/cpu.svg | 1543 --- backend/_pv_1_3_5/static/img/db_backup.svg | 424 - backend/_pv_1_3_5/static/img/favicon.ico | Bin 26166 -> 0 bytes backend/_pv_1_3_5/static/img/hd.svg | 8781 ------------- backend/_pv_1_3_5/static/img/home.svg | 179 - backend/_pv_1_3_5/static/img/knxd.svg | 1246 -- backend/_pv_1_3_5/static/img/knxd_service.png | Bin 15788 -> 0 bytes backend/_pv_1_3_5/static/img/knxd_socket.png | Bin 15365 -> 0 bytes backend/_pv_1_3_5/static/img/languages.svg | 199 - backend/_pv_1_3_5/static/img/logfile.svg | 64 - backend/_pv_1_3_5/static/img/logo_big.png | Bin 19632 -> 0 bytes backend/_pv_1_3_5/static/img/logo_long.png | Bin 3508 -> 0 bytes .../static/img/logo_small_120x120.png | Bin 5134 -> 0 bytes .../static/img/logo_small_152x152.png | Bin 6289 -> 0 bytes .../_pv_1_3_5/static/img/logo_small_32x32.png | Bin 1330 -> 0 bytes .../_pv_1_3_5/static/img/logo_small_76x76.png | Bin 3323 -> 0 bytes backend/_pv_1_3_5/static/img/password.svg | 50 - backend/_pv_1_3_5/static/img/preferences.svg | 72 - backend/_pv_1_3_5/static/img/python.png | Bin 9445 -> 0 bytes backend/_pv_1_3_5/static/img/reboot.svg | 33 - .../_pv_1_3_5/static/img/terminal-server.svg | 77 - backend/_pv_1_3_5/static/img/tux_hdd.svg | 7661 ------------ backend/_pv_1_3_5/static/img/user.svg | 1300 -- backend/_pv_1_3_5/static/js/backend.js | 0 .../_pv_1_3_5/static/js/bootstrap-reload.js | 68 - .../static/js/bootstrap-reload.min.js | 1 - .../_pv_1_3_5/static/js/bootstrap-treeview.js | 1249 -- .../static/js/bootstrap-treeview.min.js | 1 - backend/_pv_1_3_5/static/js/bootstrap.js | 2377 ---- backend/_pv_1_3_5/static/js/bootstrap.min.js | 7 - .../static/js/google-prettify/lang-aea.js | 18 - .../static/js/google-prettify/lang-agc.js | 18 - .../static/js/google-prettify/lang-apollo.js | 18 - .../static/js/google-prettify/lang-basic.js | 18 - .../static/js/google-prettify/lang-cbm.js | 18 - .../static/js/google-prettify/lang-cl.js | 18 - .../static/js/google-prettify/lang-clj.js | 17 - .../static/js/google-prettify/lang-css.js | 18 - .../static/js/google-prettify/lang-dart.js | 19 - .../static/js/google-prettify/lang-el.js | 18 - .../static/js/google-prettify/lang-erl.js | 18 - .../static/js/google-prettify/lang-erlang.js | 18 - .../static/js/google-prettify/lang-fs.js | 18 - .../static/js/google-prettify/lang-go.js | 17 - .../static/js/google-prettify/lang-hs.js | 18 - .../static/js/google-prettify/lang-lasso.js | 19 - .../js/google-prettify/lang-lassoscript.js | 19 - .../static/js/google-prettify/lang-latex.js | 17 - .../static/js/google-prettify/lang-lgt.js | 18 - .../static/js/google-prettify/lang-lisp.js | 18 - .../static/js/google-prettify/lang-ll.js | 17 - .../static/js/google-prettify/lang-llvm.js | 17 - .../static/js/google-prettify/lang-logtalk.js | 18 - .../static/js/google-prettify/lang-ls.js | 19 - .../static/js/google-prettify/lang-lsp.js | 18 - .../static/js/google-prettify/lang-lua.js | 18 - .../static/js/google-prettify/lang-matlab.js | 29 - .../static/js/google-prettify/lang-ml.js | 18 - .../static/js/google-prettify/lang-mumps.js | 18 - .../static/js/google-prettify/lang-n.js | 19 - .../static/js/google-prettify/lang-nemerle.js | 19 - .../static/js/google-prettify/lang-pascal.js | 18 - .../static/js/google-prettify/lang-proto.js | 17 - .../static/js/google-prettify/lang-r.js | 18 - .../static/js/google-prettify/lang-rd.js | 17 - .../static/js/google-prettify/lang-rkt.js | 18 - .../static/js/google-prettify/lang-rust.js | 20 - .../static/js/google-prettify/lang-s.js | 18 - .../static/js/google-prettify/lang-scala.js | 18 - .../static/js/google-prettify/lang-scm.js | 18 - .../static/js/google-prettify/lang-splus.js | 18 - .../static/js/google-prettify/lang-sql.js | 18 - .../static/js/google-prettify/lang-ss.js | 18 - .../static/js/google-prettify/lang-swift.js | 18 - .../static/js/google-prettify/lang-tcl.js | 18 - .../static/js/google-prettify/lang-tex.js | 17 - .../static/js/google-prettify/lang-vb.js | 19 - .../static/js/google-prettify/lang-vbs.js | 19 - .../static/js/google-prettify/lang-vhd.js | 19 - .../static/js/google-prettify/lang-vhdl.js | 19 - .../static/js/google-prettify/lang-wiki.js | 18 - .../static/js/google-prettify/lang-xq.js | 19 - .../static/js/google-prettify/lang-xquery.js | 19 - .../static/js/google-prettify/lang-yaml.js | 18 - .../static/js/google-prettify/lang-yml.js | 18 - .../static/js/google-prettify/prettify.css | 1 - .../static/js/google-prettify/prettify.js | 46 - .../static/js/google-prettify/run_prettify.js | 63 - .../js/google-prettify/skins/desert.css | 1 - .../static/js/google-prettify/skins/doxy.css | 1 - .../skins/sons-of-obsidian.css | 1 - .../js/google-prettify/skins/sunburst.css | 1 - backend/_pv_1_3_5/static/js/jquery-3.2.1.js | 10253 ---------------- .../_pv_1_3_5/static/js/jquery-3.2.1.min.js | 4 - .../static/js/logics_blockly_code.js | 240 - backend/_pv_1_3_5/static/js/npm.js | 13 - backend/_pv_1_3_5/static/shblocks/sh_items.js | 211 - backend/_pv_1_3_5/static/shblocks/sh_logic.js | 115 - .../_pv_1_3_5/static/shblocks/sh_notify.js | 95 - backend/_pv_1_3_5/static/shblocks/sh_time.js | 122 - backend/_pv_1_3_5/static/shblocks/sh_tools.js | 115 - .../_pv_1_3_5/static/shblocks/sh_trigger.js | 224 - backend/_pv_1_3_5/templates/base.html | 55 - .../templates/conf_yaml_converter.html | 44 - backend/_pv_1_3_5/templates/disclosure.html | 183 - backend/_pv_1_3_5/templates/items.html | 251 - backend/_pv_1_3_5/templates/log_view.html | 67 - backend/_pv_1_3_5/templates/logging.html | 55 - backend/_pv_1_3_5/templates/logics.html | 163 - .../_pv_1_3_5/templates/logics_blockly.html | 79 - .../templates/logics_blockly_toolbox.html | 278 - backend/_pv_1_3_5/templates/logics_view.html | 79 - .../_pv_1_3_5/templates/logics_view.html.off | 98 - backend/_pv_1_3_5/templates/main.html | 38 - backend/_pv_1_3_5/templates/navbar.html | 54 - backend/_pv_1_3_5/templates/plugins.html | 72 - backend/_pv_1_3_5/templates/schedules.html | 49 - backend/_pv_1_3_5/templates/services.html | 207 - backend/_pv_1_3_5/templates/system.html | 101 - backend/_pv_1_3_5/templates/threads.html | 30 - backend/_pv_1_3_5/templates/visu.html | 57 - backend/_pv_1_3_5/tests/cptestcase.py | 102 - backend/_pv_1_3_5/utils.py | 163 - 891 files changed, 233868 deletions(-) delete mode 100755 backend/_pv_1_3_5/BackendBlockly.py delete mode 100755 backend/_pv_1_3_5/BackendCore.py delete mode 100644 backend/_pv_1_3_5/README.md delete mode 100755 backend/_pv_1_3_5/__init__.py delete mode 100755 backend/_pv_1_3_5/locale/de.json delete mode 100755 backend/_pv_1_3_5/locale/en.json delete mode 100755 backend/_pv_1_3_5/locale/fr.json delete mode 100755 backend/_pv_1_3_5/locale/pl.json delete mode 100755 backend/_pv_1_3_5/plugin.yaml delete mode 100755 backend/_pv_1_3_5/requirements.txt delete mode 100755 backend/_pv_1_3_5/static/blockly/CONTRIBUTING.md delete mode 100755 backend/_pv_1_3_5/static/blockly/LICENSE delete mode 100755 backend/_pv_1_3_5/static/blockly/README.md delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/README delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/app.component.js delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/audio.service.js delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/clipboard.service.js delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/field.component.js delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/libs/Rx.umd.min.js delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/libs/angular2-all.umd.min.js delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/libs/angular2-polyfills.min.js delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/libs/es6-shim.min.js delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/media/accessible.css delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/media/click.mp3 delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/media/click.ogg delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/media/click.wav delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/media/delete.mp3 delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/media/delete.ogg delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/media/delete.wav delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/messages.js delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/notifications.service.js delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/toolbox-tree.component.js delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/toolbox.component.js delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/translate.pipe.js delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/tree.service.js delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/utils.service.js delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/workspace-tree.component.js delete mode 100755 backend/_pv_1_3_5/static/blockly/accessible/workspace.component.js delete mode 100755 backend/_pv_1_3_5/static/blockly/blockly_compressed.js delete mode 100755 backend/_pv_1_3_5/static/blockly/blockly_uncompressed.js delete mode 100755 backend/_pv_1_3_5/static/blockly/blocks_compressed.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/block.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/block_render_svg.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/block_svg.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/blockly.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/blocks.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/bubble.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/comment.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/connection.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/connection_db.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/constants.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/contextmenu.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/css.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/events.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/field.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/field_angle.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/field_checkbox.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/field_colour.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/field_date.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/field_dropdown.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/field_image.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/field_label.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/field_number.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/field_textinput.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/field_variable.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/flyout.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/flyout_button.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/generator.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/icon.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/inject.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/input.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/msg.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/mutator.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/names.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/options.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/procedures.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/rendered_connection.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/scrollbar.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/toolbox.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/tooltip.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/trashcan.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/utils.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/variables.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/warning.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/widgetdiv.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/workspace.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/workspace_svg.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/xml.js delete mode 100755 backend/_pv_1_3_5/static/blockly/core/zoom_controls.js delete mode 100755 backend/_pv_1_3_5/static/blockly/dart_compressed.js delete mode 100755 backend/_pv_1_3_5/static/blockly/demos/code/style.css delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/dart.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/dart/colour.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/dart/lists.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/dart/logic.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/dart/loops.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/dart/math.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/dart/procedures.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/dart/text.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/dart/variables.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/javascript.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/javascript/colour.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/javascript/lists.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/javascript/logic.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/javascript/loops.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/javascript/math.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/javascript/procedures.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/javascript/text.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/javascript/variables.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/lua.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/lua/colour.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/lua/lists.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/lua/logic.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/lua/loops.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/lua/math.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/lua/procedures.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/lua/text.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/lua/variables.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/php.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/php/colour.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/php/lists.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/php/logic.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/php/loops.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/php/math.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/php/procedures.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/php/text.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/php/variables.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/python.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/python/colour.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/python/lists.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/python/logic.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/python/loops.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/python/math.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/python/procedures.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/python/text.js delete mode 100755 backend/_pv_1_3_5/static/blockly/generators/python/variables.js delete mode 100755 backend/_pv_1_3_5/static/blockly/i18n/common.py delete mode 100755 backend/_pv_1_3_5/static/blockly/i18n/create_messages.py delete mode 100755 backend/_pv_1_3_5/static/blockly/i18n/dedup_json.py delete mode 100755 backend/_pv_1_3_5/static/blockly/i18n/js_to_json.py delete mode 100755 backend/_pv_1_3_5/static/blockly/i18n/json_to_js.py delete mode 100755 backend/_pv_1_3_5/static/blockly/i18n/tests.py delete mode 100755 backend/_pv_1_3_5/static/blockly/i18n/xliff_to_json.py delete mode 100755 backend/_pv_1_3_5/static/blockly/javascript_compressed.js delete mode 100755 backend/_pv_1_3_5/static/blockly/lua_compressed.js delete mode 100755 backend/_pv_1_3_5/static/blockly/media/1x1.gif delete mode 100755 backend/_pv_1_3_5/static/blockly/media/click.mp3 delete mode 100755 backend/_pv_1_3_5/static/blockly/media/click.ogg delete mode 100755 backend/_pv_1_3_5/static/blockly/media/click.wav delete mode 100755 backend/_pv_1_3_5/static/blockly/media/delete.mp3 delete mode 100755 backend/_pv_1_3_5/static/blockly/media/delete.ogg delete mode 100755 backend/_pv_1_3_5/static/blockly/media/delete.wav delete mode 100755 backend/_pv_1_3_5/static/blockly/media/disconnect.mp3 delete mode 100755 backend/_pv_1_3_5/static/blockly/media/disconnect.ogg delete mode 100755 backend/_pv_1_3_5/static/blockly/media/disconnect.wav delete mode 100755 backend/_pv_1_3_5/static/blockly/media/handclosed.cur delete mode 100755 backend/_pv_1_3_5/static/blockly/media/handdelete.cur delete mode 100755 backend/_pv_1_3_5/static/blockly/media/handopen.cur delete mode 100755 backend/_pv_1_3_5/static/blockly/media/quote0.png delete mode 100755 backend/_pv_1_3_5/static/blockly/media/quote1.png delete mode 100755 backend/_pv_1_3_5/static/blockly/media/sprites.png delete mode 100755 backend/_pv_1_3_5/static/blockly/media/sprites.svg delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/ar.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/az.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/ba.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/bcc.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/be-tarask.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/bg.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/bn.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/br.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/ca.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/cs.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/da.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/de.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/diq.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/el.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/en-gb.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/en.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/es.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/et.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/fa.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/fi.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/fr.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/he.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/hi.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/hrx.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/hu.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/ia.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/id.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/is.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/it.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/ja.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/ko.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/lb.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/lki.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/lrc.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/lt.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/mk.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/ms.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/nb.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/nl.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/oc.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/pl.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/pms.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/pt-br.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/pt.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/ro.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/ru.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/sc.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/sd.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/shn.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/sk.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/sl.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/sq.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/sr.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/sv.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/ta.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/tcy.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/th.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/tl.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/tlh.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/tr.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/uk.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/vi.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/zh-hans.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/js/zh-hant.js delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/ar.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/az.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/ba.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/bcc.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/be-tarask.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/bg.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/bn.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/br.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/ca.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/cs.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/da.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/de.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/diq.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/el.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/en-gb.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/en.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/es.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/et.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/fa.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/fi.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/fr.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/he.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/hi.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/hrx.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/hu.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/ia.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/id.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/is.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/it.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/ja.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/ko.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/lb.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/lki.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/lrc.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/lt.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/mk.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/ms.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/nb.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/nl.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/oc.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/pl.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/pms.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/pt-br.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/pt.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/qqq.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/ro.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/ru.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/sc.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/sd.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/shn.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/sk.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/sl.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/sq.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/sr.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/sv.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/synonyms.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/ta.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/tcy.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/th.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/tl.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/tlh.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/tr.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/uk.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/vi.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/zh-hans.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/json/zh-hant.json delete mode 100755 backend/_pv_1_3_5/static/blockly/msg/messages.js delete mode 100755 backend/_pv_1_3_5/static/blockly/php_compressed.js delete mode 100755 backend/_pv_1_3_5/static/blockly/python_compressed.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/AUTHORS delete mode 100755 backend/_pv_1_3_5/static/codemirror/CHANGELOG.md delete mode 100755 backend/_pv_1_3_5/static/codemirror/CONTRIBUTING.md delete mode 100755 backend/_pv_1_3_5/static/codemirror/LICENSE delete mode 100755 backend/_pv_1_3_5/static/codemirror/README.md delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/comment/comment.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/comment/continuecomment.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/dialog/dialog.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/dialog/dialog.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/display/autorefresh.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/display/fullscreen.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/display/fullscreen.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/display/panel.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/display/placeholder.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/display/rulers.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/edit/closebrackets.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/edit/closetag.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/edit/continuelist.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/edit/matchbrackets.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/edit/matchtags.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/edit/trailingspace.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/fold/brace-fold.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/fold/comment-fold.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/fold/foldcode.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/fold/foldgutter.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/fold/foldgutter.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/fold/indent-fold.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/fold/markdown-fold.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/fold/xml-fold.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/hint/anyword-hint.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/hint/css-hint.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/hint/html-hint.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/hint/javascript-hint.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/hint/show-hint.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/hint/show-hint.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/hint/sql-hint.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/hint/xml-hint.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/lint/coffeescript-lint.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/lint/css-lint.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/lint/html-lint.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/lint/javascript-lint.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/lint/json-lint.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/lint/lint.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/lint/lint.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/lint/yaml-lint.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/merge/merge.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/merge/merge.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/mode/loadmode.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/mode/multiplex.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/mode/multiplex_test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/mode/overlay.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/mode/simple.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/runmode/colorize.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/runmode/runmode-standalone.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/runmode/runmode.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/runmode/runmode.node.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/scroll/annotatescrollbar.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/scroll/scrollpastend.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/scroll/simplescrollbars.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/scroll/simplescrollbars.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/search/jump-to-line.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/search/match-highlighter.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/search/matchesonscrollbar.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/search/matchesonscrollbar.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/search/search.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/search/searchcursor.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/selection/active-line.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/selection/mark-selection.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/selection/selection-pointer.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/tern/tern.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/tern/tern.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/tern/worker.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/addon/wrap/hardwrap.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/bin/authors.sh delete mode 100755 backend/_pv_1_3_5/static/codemirror/bin/compress delete mode 100755 backend/_pv_1_3_5/static/codemirror/bin/lint delete mode 100755 backend/_pv_1_3_5/static/codemirror/bin/release delete mode 100755 backend/_pv_1_3_5/static/codemirror/bin/source-highlight delete mode 100755 backend/_pv_1_3_5/static/codemirror/bin/upload-release.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/bower.json delete mode 100755 backend/_pv_1_3_5/static/codemirror/doc/activebookmark.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/doc/docs.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/doc/internals.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/doc/logo.png delete mode 100755 backend/_pv_1_3_5/static/codemirror/doc/logo.svg delete mode 100755 backend/_pv_1_3_5/static/codemirror/doc/manual.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/doc/realworld.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/doc/releases.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/doc/reporting.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/doc/upgrade_v2.2.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/doc/upgrade_v3.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/doc/upgrade_v4.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/doc/yinyang.png delete mode 100755 backend/_pv_1_3_5/static/codemirror/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/keymap/emacs.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/keymap/sublime.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/keymap/vim.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/lib/codemirror.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/lib/codemirror.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/apl/apl.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/apl/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/asciiarmor/asciiarmor.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/asciiarmor/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/asn.1/asn.1.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/asn.1/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/asterisk/asterisk.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/asterisk/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/brainfuck/brainfuck.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/brainfuck/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/clike/clike.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/clike/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/clike/scala.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/clike/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/clojure/clojure.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/clojure/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/cmake/cmake.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/cmake/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/cobol/cobol.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/cobol/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/coffeescript/coffeescript.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/coffeescript/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/commonlisp/commonlisp.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/commonlisp/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/crystal/crystal.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/crystal/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/css/css.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/css/gss.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/css/gss_test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/css/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/css/less.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/css/less_test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/css/scss.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/css/scss_test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/css/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/cypher/cypher.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/cypher/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/cypher/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/d/d.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/d/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/dart/dart.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/dart/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/diff/diff.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/diff/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/django/django.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/django/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/dockerfile/dockerfile.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/dockerfile/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/dtd/dtd.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/dtd/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/dylan/dylan.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/dylan/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/dylan/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/ebnf/ebnf.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/ebnf/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/ecl/ecl.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/ecl/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/eiffel/eiffel.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/eiffel/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/elm/elm.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/elm/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/erlang/erlang.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/erlang/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/factor/factor.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/factor/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/fcl/fcl.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/fcl/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/forth/forth.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/forth/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/fortran/fortran.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/fortran/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/gas/gas.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/gas/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/gfm/gfm.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/gfm/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/gfm/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/gherkin/gherkin.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/gherkin/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/go/go.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/go/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/groovy/groovy.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/groovy/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/haml/haml.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/haml/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/haml/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/handlebars/handlebars.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/handlebars/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/haskell-literate/haskell-literate.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/haskell-literate/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/haskell/haskell.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/haskell/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/haxe/haxe.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/haxe/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/htmlembedded/htmlembedded.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/htmlembedded/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/htmlmixed/htmlmixed.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/htmlmixed/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/http/http.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/http/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/idl/idl.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/idl/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/javascript/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/javascript/javascript.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/javascript/json-ld.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/javascript/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/javascript/typescript.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/jinja2/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/jinja2/jinja2.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/jsx/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/jsx/jsx.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/jsx/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/julia/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/julia/julia.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/livescript/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/livescript/livescript.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/lua/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/lua/lua.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/markdown/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/markdown/markdown.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/markdown/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/mathematica/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/mathematica/mathematica.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/mbox/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/mbox/mbox.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/meta.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/mirc/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/mirc/mirc.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/mllike/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/mllike/mllike.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/modelica/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/modelica/modelica.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/mscgen/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/mscgen/mscgen.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/mscgen/mscgen_test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/mscgen/msgenny_test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/mscgen/xu_test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/mumps/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/mumps/mumps.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/nginx/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/nginx/nginx.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/nsis/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/nsis/nsis.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/ntriples/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/ntriples/ntriples.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/octave/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/octave/octave.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/oz/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/oz/oz.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/pascal/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/pascal/pascal.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/pegjs/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/pegjs/pegjs.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/perl/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/perl/perl.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/php/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/php/php.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/php/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/pig/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/pig/pig.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/powershell/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/powershell/powershell.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/powershell/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/properties/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/properties/properties.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/protobuf/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/protobuf/protobuf.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/pug/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/pug/pug.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/puppet/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/puppet/puppet.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/python/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/python/python.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/python/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/q/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/q/q.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/r/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/r/r.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/rpm/changes/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/rpm/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/rpm/rpm.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/rst/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/rst/rst.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/ruby/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/ruby/ruby.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/ruby/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/rust/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/rust/rust.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/rust/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/sas/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/sas/sas.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/sass/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/sass/sass.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/scheme/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/scheme/scheme.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/shell/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/shell/shell.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/shell/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/sieve/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/sieve/sieve.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/slim/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/slim/slim.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/slim/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/smalltalk/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/smalltalk/smalltalk.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/smarty/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/smarty/smarty.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/solr/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/solr/solr.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/soy/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/soy/soy.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/soy/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/sparql/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/sparql/sparql.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/spreadsheet/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/spreadsheet/spreadsheet.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/sql/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/sql/sql.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/stex/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/stex/stex.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/stex/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/stylus/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/stylus/stylus.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/swift/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/swift/swift.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/swift/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/tcl/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/tcl/tcl.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/textile/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/textile/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/textile/textile.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/tiddlywiki/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/tiddlywiki/tiddlywiki.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/tiddlywiki/tiddlywiki.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/tiki/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/tiki/tiki.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/tiki/tiki.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/toml/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/toml/toml.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/tornado/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/tornado/tornado.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/troff/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/troff/troff.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/ttcn-cfg/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/ttcn-cfg/ttcn-cfg.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/ttcn/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/ttcn/ttcn.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/turtle/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/turtle/turtle.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/twig/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/twig/twig.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/vb/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/vb/vb.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/vbscript/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/vbscript/vbscript.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/velocity/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/velocity/velocity.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/verilog/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/verilog/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/verilog/verilog.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/vhdl/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/vhdl/vhdl.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/vue/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/vue/vue.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/webidl/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/webidl/webidl.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/xml/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/xml/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/xml/xml.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/xquery/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/xquery/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/xquery/xquery.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/yacas/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/yacas/yacas.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/yaml-frontmatter/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/yaml-frontmatter/yaml-frontmatter.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/yaml/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/yaml/yaml.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/z80/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/mode/z80/z80.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/package.json delete mode 100755 backend/_pv_1_3_5/static/codemirror/rollup.config.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/test/comment_test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/test/doc_test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/test/driver.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/test/emacs_test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/test/index.html delete mode 100755 backend/_pv_1_3_5/static/codemirror/test/lint.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/test/mode_test.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/test/mode_test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/test/multi_test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/test/phantom_driver.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/test/run.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/test/scroll_test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/test/search_test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/test/sql-hint-test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/test/sublime_test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/test/test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/test/vim_test.js delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/3024-day.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/3024-night.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/abcdef.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/ambiance-mobile.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/ambiance.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/base16-dark.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/base16-light.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/bespin.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/blackboard.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/cobalt.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/colorforth.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/dracula.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/duotone-dark.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/duotone-light.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/eclipse.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/elegant.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/erlang-dark.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/hopscotch.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/icecoder.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/isotope.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/lesser-dark.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/liquibyte.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/material.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/mbo.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/mdn-like.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/midnight.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/monokai.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/neat.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/neo.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/night.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/panda-syntax.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/paraiso-dark.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/paraiso-light.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/pastel-on-dark.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/railscasts.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/rubyblue.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/seti.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/solarized.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/the-matrix.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/tomorrow-night-bright.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/tomorrow-night-eighties.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/ttcn.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/twilight.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/vibrant-ink.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/xq-dark.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/xq-light.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/yeti.css delete mode 100755 backend/_pv_1_3_5/static/codemirror/theme/zenburn.css delete mode 100755 backend/_pv_1_3_5/static/css/bootstrap-reload.css delete mode 100755 backend/_pv_1_3_5/static/css/bootstrap-theme.css delete mode 100755 backend/_pv_1_3_5/static/css/bootstrap-theme.css.map delete mode 100755 backend/_pv_1_3_5/static/css/bootstrap-theme.min.css delete mode 100755 backend/_pv_1_3_5/static/css/bootstrap-theme.min.css.map delete mode 100755 backend/_pv_1_3_5/static/css/bootstrap-treeview.css delete mode 100755 backend/_pv_1_3_5/static/css/bootstrap-treeview.min.css delete mode 100755 backend/_pv_1_3_5/static/css/bootstrap.css delete mode 100755 backend/_pv_1_3_5/static/css/bootstrap.css.map delete mode 100755 backend/_pv_1_3_5/static/css/bootstrap.min.css delete mode 100755 backend/_pv_1_3_5/static/css/bootstrap.min.css.map delete mode 100755 backend/_pv_1_3_5/static/css/font-awesome.css delete mode 100755 backend/_pv_1_3_5/static/css/font-awesome.min.css delete mode 100755 backend/_pv_1_3_5/static/fonts/FontAwesome.otf delete mode 100755 backend/_pv_1_3_5/static/fonts/fontawesome-webfont.eot delete mode 100755 backend/_pv_1_3_5/static/fonts/fontawesome-webfont.svg delete mode 100755 backend/_pv_1_3_5/static/fonts/fontawesome-webfont.ttf delete mode 100755 backend/_pv_1_3_5/static/fonts/fontawesome-webfont.woff delete mode 100755 backend/_pv_1_3_5/static/fonts/fontawesome-webfont.woff2 delete mode 100755 backend/_pv_1_3_5/static/fonts/glyphicons-halflings-regular.eot delete mode 100755 backend/_pv_1_3_5/static/fonts/glyphicons-halflings-regular.svg delete mode 100755 backend/_pv_1_3_5/static/fonts/glyphicons-halflings-regular.ttf delete mode 100755 backend/_pv_1_3_5/static/fonts/glyphicons-halflings-regular.woff delete mode 100755 backend/_pv_1_3_5/static/fonts/glyphicons-halflings-regular.woff2 delete mode 100755 backend/_pv_1_3_5/static/img/NIC.svg delete mode 100755 backend/_pv_1_3_5/static/img/cache.svg delete mode 100755 backend/_pv_1_3_5/static/img/clock.svg delete mode 100755 backend/_pv_1_3_5/static/img/cpu.svg delete mode 100755 backend/_pv_1_3_5/static/img/db_backup.svg delete mode 100755 backend/_pv_1_3_5/static/img/favicon.ico delete mode 100755 backend/_pv_1_3_5/static/img/hd.svg delete mode 100755 backend/_pv_1_3_5/static/img/home.svg delete mode 100755 backend/_pv_1_3_5/static/img/knxd.svg delete mode 100755 backend/_pv_1_3_5/static/img/knxd_service.png delete mode 100755 backend/_pv_1_3_5/static/img/knxd_socket.png delete mode 100755 backend/_pv_1_3_5/static/img/languages.svg delete mode 100755 backend/_pv_1_3_5/static/img/logfile.svg delete mode 100755 backend/_pv_1_3_5/static/img/logo_big.png delete mode 100755 backend/_pv_1_3_5/static/img/logo_long.png delete mode 100755 backend/_pv_1_3_5/static/img/logo_small_120x120.png delete mode 100755 backend/_pv_1_3_5/static/img/logo_small_152x152.png delete mode 100755 backend/_pv_1_3_5/static/img/logo_small_32x32.png delete mode 100755 backend/_pv_1_3_5/static/img/logo_small_76x76.png delete mode 100755 backend/_pv_1_3_5/static/img/password.svg delete mode 100755 backend/_pv_1_3_5/static/img/preferences.svg delete mode 100755 backend/_pv_1_3_5/static/img/python.png delete mode 100755 backend/_pv_1_3_5/static/img/reboot.svg delete mode 100755 backend/_pv_1_3_5/static/img/terminal-server.svg delete mode 100755 backend/_pv_1_3_5/static/img/tux_hdd.svg delete mode 100755 backend/_pv_1_3_5/static/img/user.svg delete mode 100755 backend/_pv_1_3_5/static/js/backend.js delete mode 100755 backend/_pv_1_3_5/static/js/bootstrap-reload.js delete mode 100755 backend/_pv_1_3_5/static/js/bootstrap-reload.min.js delete mode 100755 backend/_pv_1_3_5/static/js/bootstrap-treeview.js delete mode 100755 backend/_pv_1_3_5/static/js/bootstrap-treeview.min.js delete mode 100755 backend/_pv_1_3_5/static/js/bootstrap.js delete mode 100755 backend/_pv_1_3_5/static/js/bootstrap.min.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-aea.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-agc.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-apollo.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-basic.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-cbm.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-cl.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-clj.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-css.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-dart.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-el.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-erl.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-erlang.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-fs.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-go.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-hs.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-lasso.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-lassoscript.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-latex.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-lgt.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-lisp.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-ll.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-llvm.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-logtalk.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-ls.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-lsp.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-lua.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-matlab.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-ml.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-mumps.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-n.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-nemerle.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-pascal.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-proto.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-r.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-rd.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-rkt.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-rust.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-s.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-scala.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-scm.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-splus.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-sql.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-ss.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-swift.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-tcl.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-tex.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-vb.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-vbs.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-vhd.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-vhdl.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-wiki.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-xq.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-xquery.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-yaml.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/lang-yml.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/prettify.css delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/prettify.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/run_prettify.js delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/skins/desert.css delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/skins/doxy.css delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/skins/sons-of-obsidian.css delete mode 100755 backend/_pv_1_3_5/static/js/google-prettify/skins/sunburst.css delete mode 100755 backend/_pv_1_3_5/static/js/jquery-3.2.1.js delete mode 100755 backend/_pv_1_3_5/static/js/jquery-3.2.1.min.js delete mode 100755 backend/_pv_1_3_5/static/js/logics_blockly_code.js delete mode 100755 backend/_pv_1_3_5/static/js/npm.js delete mode 100755 backend/_pv_1_3_5/static/shblocks/sh_items.js delete mode 100755 backend/_pv_1_3_5/static/shblocks/sh_logic.js delete mode 100755 backend/_pv_1_3_5/static/shblocks/sh_notify.js delete mode 100755 backend/_pv_1_3_5/static/shblocks/sh_time.js delete mode 100755 backend/_pv_1_3_5/static/shblocks/sh_tools.js delete mode 100755 backend/_pv_1_3_5/static/shblocks/sh_trigger.js delete mode 100755 backend/_pv_1_3_5/templates/base.html delete mode 100755 backend/_pv_1_3_5/templates/conf_yaml_converter.html delete mode 100755 backend/_pv_1_3_5/templates/disclosure.html delete mode 100755 backend/_pv_1_3_5/templates/items.html delete mode 100755 backend/_pv_1_3_5/templates/log_view.html delete mode 100755 backend/_pv_1_3_5/templates/logging.html delete mode 100755 backend/_pv_1_3_5/templates/logics.html delete mode 100755 backend/_pv_1_3_5/templates/logics_blockly.html delete mode 100755 backend/_pv_1_3_5/templates/logics_blockly_toolbox.html delete mode 100755 backend/_pv_1_3_5/templates/logics_view.html delete mode 100755 backend/_pv_1_3_5/templates/logics_view.html.off delete mode 100755 backend/_pv_1_3_5/templates/main.html delete mode 100755 backend/_pv_1_3_5/templates/navbar.html delete mode 100755 backend/_pv_1_3_5/templates/plugins.html delete mode 100755 backend/_pv_1_3_5/templates/schedules.html delete mode 100755 backend/_pv_1_3_5/templates/services.html delete mode 100755 backend/_pv_1_3_5/templates/system.html delete mode 100755 backend/_pv_1_3_5/templates/threads.html delete mode 100755 backend/_pv_1_3_5/templates/visu.html delete mode 100755 backend/_pv_1_3_5/tests/cptestcase.py delete mode 100755 backend/_pv_1_3_5/utils.py diff --git a/backend/_pv_1_3_5/BackendBlockly.py b/backend/_pv_1_3_5/BackendBlockly.py deleted file mode 100755 index b628e6fa0..000000000 --- a/backend/_pv_1_3_5/BackendBlockly.py +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf8 -*- -######################################################################### -# Copyright 2016- René Frieß rene.friess@gmail.com -# Martin Sinn m.sinn@gmx.de -# Bernd Meiners -# Christian Strassburg c.strassburg@gmx.de -# Dirk Wallmeier dirk@wallmeier.info -######################################################################### -# Backend plugin for SmartHomeNG -# -# This plugin is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This plugin is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this plugin. If not, see . -######################################################################### - -import cherrypy -from .utils import * -from lib.logic import Logic - -# from jinja2 import Environment, FileSystemLoader - -from .utils import * -from cherrypy.lib.static import serve_file - - -class BackendBlocklyLogics: - """ - Google Blockly for Logics - """ - - @cherrypy.expose - def logics_blockly_html(self): - self.find_visu_plugin() - - tmpl = self.env.get_template('logics_blockly.html') - return tmpl.render(smarthome=self._sh, - dyn_sh_toolbox=self._DynToolbox(self._sh), lang=translation_lang, - develop=self.developer_mode, - visu_plugin=(self.visu_plugin is not None)) - - def _DynToolbox(self, sh): - return "\n" + self._build_item_block_tree(self._sh.return_items()) - - def _build_item_block_tree(self, items, cname="Items"): - """ - recursive definiert - """ - items_sorted = sorted(items, key=lambda k: str.lower(k['_path']), - reverse=False) - if len(items_sorted) == 0: - return '' - else: - # self.logger.debug("\n" + cname + "\n" + - # "|".join(i._name for i in items_sorted)) - parent_items_sorted = [] - last_parent_item = None - for item in items_sorted: - if last_parent_item is None or last_parent_item._path not in item._path: - parent_items_sorted.append(item) - last_parent_item = item - - xml = '\n'.format( - cname, len(parent_items_sorted)) - for item in parent_items_sorted: - xml += self._build_item_block(item) - xml += self._build_item_block_tree( - item.return_children(), item._name) - return xml + '\n' - - def _build_item_block(self, item): - if item._type in ['bool', 'num', 'str']: - n, p, t = item._name, item._path, item.type() - if n == p: - n = "".join(x.title() for x in p.split('.')) - block = ''.format(n) - block += ' {0}{1}{2}'.format( - n, p, t) - block += '\n' - return block - else: - return '\n' - - @cherrypy.expose - def logics_blockly_load(self): - fn_xml = self._sh._logic_dir + "blockly_logics.xml" - return serve_file(fn_xml, content_type='application/xml') - - @cherrypy.expose - def logics_blockly_save(self, py, xml): - self._pycode = py - self._xmldata = xml - fn_py = self._sh._logic_dir + "blockly_logics.py" - fn_xml = self._sh._logic_dir + "blockly_logics.xml" - self.logger.debug( - "Backend: logics_html: SAVE PY blockly logic = {0}\n '{1}'".format(fn_py, py)) - with open(fn_py, 'w') as fpy: - fpy.write(py) - self.logger.debug( - "Backend: logics_html: SAVE XML blockly logic = {0}\n '{1}'".format(fn_xml, xml)) - with open(fn_xml, 'w') as fxml: - fxml.write(xml) - - code = self._pycode - bytecode = compile(code, '', 'exec') - s = [] - for name in self._sh.scheduler: - if name.startswith('blockly_runner'): - # logger.info('Blockly Logics: remove '+ name) - s.append(name) - for name in s: - self._sh.scheduler.remove(name) - - for line in code.splitlines(): - if line and line.startswith('#?#'): - id, __, trigger = line[3:].partition(':') - by, __, val = trigger.partition('=') - by = by.strip() - val = val.strip() - # logger.info('Blockly Logics: {} => {} :: {}'.format(id, by, val)) - logic = Logic(self._sh, 'blockly_runner_' + id, - {'bytecode': bytecode, }) - if by == 'cycle': - self._sh.scheduler.add( - 'blockly_runner_' + id, logic, prio=3, cron=None, cycle=val) - # logger.info('Blockly Logics: cycles => '+ val) - elif by == 'crontab': - self._sh.scheduler.add( - 'blockly_runner_' + id, logic, prio=3, cron=val, cycle=None) - # logger.info('Blockly Logics: crontabs => '+ val) - elif by == 'watchitem': - logic.watch_item = val - # item = self._sh.return_item(val) - # item.add_logic_trigger(logic) - # logger.info('Blockly Logics: watchitems => '+ val) diff --git a/backend/_pv_1_3_5/BackendCore.py b/backend/_pv_1_3_5/BackendCore.py deleted file mode 100755 index 5b0d962e9..000000000 --- a/backend/_pv_1_3_5/BackendCore.py +++ /dev/null @@ -1,1034 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf8 -*- -######################################################################### -# Copyright 2016- René Frieß rene.friess@gmail.com -# Martin Sinn m.sinn@gmx.de -# Bernd Meiners -# Christian Strassburg c.strassburg@gmx.de -######################################################################### -# Backend plugin for SmartHomeNG -# -# This plugin is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This plugin is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this plugin. If not, see . -######################################################################### - -import cherrypy -import platform -import collections -import datetime -import pwd -import html -import subprocess -import socket -import sys -import threading -import os -import lib.config -import lib.logic # zum Test -from lib.model.smartplugin import SmartPlugin -from .utils import * - -import lib.item_conversion - -class Backend: - - def find_visu_plugin(self): - """ - look for the configured instance of the visu protocol plugin. - """ - if self.visu_plugin is not None: - return - - for p in self._sh._plugins: - if p.__class__.__name__ == "WebSocket": - self.visu_plugin = p - if self.visu_plugin is not None: - try: - self.visu_plugin_version = self.visu_plugin.get_version() - except: - self.visu_plugin_version = '1.0.0' - self.visu_plugin_build = self.visu_plugin_version[4:] - if self.visu_plugin_build < '2': - self.visu_plugin = None - self.logger.warning( - "Backend: visu protocol plugin v{0} is too old to support BackendServer, please update".format( - self.visu_plugin_version)) - - - def render_template(self, tmpl_name, **kwargs): - """ - - Render a template and add vars needed gobally (for navigation, etc.) - - :param tmpl_name: Name of the template file to be rendered - :param **kwargs: keyworded arguments to use while rendering - - :return: contents of the template after beeing rendered - - """ - self.find_visu_plugin() - tmpl = self.env.get_template(tmpl_name) - return tmpl.render(develop=self.developer_mode, - smarthome=self._sh, - visu_plugin=(self.visu_plugin is not None), - yaml_converter=lib.item_conversion.is_ruamelyaml_installed(), - **kwargs) - - - # ----------------------------------------------------------------------------------- - # MAIN - # ----------------------------------------------------------------------------------- - - @cherrypy.expose - def index(self): - - return self.render_template('main.html') - - @cherrypy.expose - def main_html(self): - - return self.render_template('main.html') - - - # ----------------------------------------------------------------------------------- - # SYSTEMINFO - # ----------------------------------------------------------------------------------- - - @cherrypy.expose - def system_html(self): - now = datetime.datetime.now().strftime('%d.%m.%Y %H:%M') - system = platform.system() - vers = platform.version() - # node = platform.node() - node = socket.getfqdn() - arch = platform.machine() - user = pwd.getpwuid(os.geteuid()).pw_name # os.getlogin() - python_packages = self.getpackages() - - req_dict = {} - req_dict_base = parse_requirements("%s/requirements/base.txt" % self._sh_dir) - - # parse plugins and look for requirements - _conf = lib.config.parse(self._sh._plugin_conf) - - plugin_names = [] - for plugin in _conf: - plugin_name = _conf[plugin]['class_path'].strip() - if not plugin_name in plugin_names: # only unique plugin names, e.g. if multiinstance is used - plugin_names.append(plugin_name) - - req_dict = req_dict_base.copy() - for plugin_name in plugin_names: - file_path = "%s/%s/requirements.txt" % (self._sh_dir, plugin_name.replace("plugins.", "plugins/")) - if os.path.isfile(file_path): - plugin_dict = parse_requirements(file_path) - for key in plugin_dict: - if key not in req_dict: - req_dict[key] = plugin_dict[key] + ' (' + plugin_name.replace('plugins.', '') + ')' - else: - req_dict[key] = req_dict[key] + '
' + plugin_dict[key] + ' (' + plugin_name.replace( - 'plugins.', '') + ')' - - ip = self._bs.get_local_ip_address() - - space = os.statvfs(self._sh_dir) - freespace = space.f_frsize * space.f_bavail / 1024 / 1024 - - get_uptime = subprocess.Popen('uptime', stdout=subprocess.PIPE) - uptime = get_uptime.stdout.read().decode() - # return SmarthomeNG runtime - rt = str(self._sh.runtime()) - daytest = rt.split(' ') - if len(daytest) == 3: - days = int(daytest[0]) - hours, minutes, seconds = [float(val) for val in str(daytest[2]).split(':')] - else: - days = 0 - hours, minutes, seconds = [float(val) for val in str(daytest[0]).split(':')] - sh_uptime = self.age_to_string(days, hours, minutes, seconds) - - pyversion = "{0}.{1}.{2} {3}".format(sys.version_info[0], sys.version_info[1], sys.version_info[2], - sys.version_info[3]) - - return self.render_template('system.html', - now=now, system=system, sh_vers=self._sh.env.core.version(), sh_dir=self._sh_dir, - vers=vers, node=node, arch=arch, user=user, freespace=freespace, - uptime=uptime, sh_uptime=sh_uptime, pyversion=pyversion, - ip=ip, python_packages=python_packages, requirements=req_dict) - - - def get_process_info(self, command): - """ - returns output from executing a given command via the shell. - """ - self.find_visu_plugin() - ## get subprocess module - import subprocess - - ## call date command ## - p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) - - # Talk with date command i.e. read data from stdout and stderr. Store this info in tuple ## - # Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. - # Wait for process to terminate. The optional input argument should be a string to be sent to the child process, or None, if no data should be sent to the child. - (result, err) = p.communicate() - - ## Wait for date to terminate. Get return returncode ## - p_status = p.wait() - return str(result, encoding='utf-8', errors='strict') - - def getpackages(self): - """ - returns a list with the installed python packages and its versions - """ - self.find_visu_plugin() - - # check if pypi service is reachable - if self.pypi_timeout <= 0: - pypi_available = False - pypi_unavailable_message = translate('PyPI Prüfung deaktiviert') - else: - pypi_available = True - try: - import socket - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.settimeout(self.pypi_timeout) - sock.connect(('pypi.python.org', 443)) - sock.close() - except: - pypi_available = False - pypi_unavailable_message = translate('PyPI nicht erreichbar') - - import pip - import xmlrpc - installed_packages = pip.get_installed_distributions() - pypi = xmlrpc.client.ServerProxy('https://pypi.python.org/pypi') - packages = [] - for dist in installed_packages: - package = {} - package['key'] = dist.key - package['version_installed'] = dist.version - if pypi_available: - try: - available = pypi.package_releases(dist.project_name) - try: - package['version_available'] = available[0] - except: - package['version_available'] = '-' - except: - package['version_available'] = [translate('Keine Antwort von PyPI')] - else: - package['version_available'] = pypi_unavailable_message - packages.append(package) - - sorted_packages = sorted([(i['key'], i['version_installed'], i['version_available']) for i in packages]) - return sorted_packages - - - # ----------------------------------------------------------------------------------- - # SERVICES - # ----------------------------------------------------------------------------------- - - @cherrypy.expose - def services_html(self): - """ - shows a page with info about some services needed by smarthome - """ - knxd_service = self.get_process_info("systemctl status knxd.service") - smarthome_service = self.get_process_info("systemctl status smarthome.service") - knxd_socket = self.get_process_info("systemctl status knxd.socket") - - knxdeamon = '' - if self.get_process_info("ps cax|grep eibd") != '': - knxdeamon = 'eibd' - if self.get_process_info("ps cax|grep knxd") != '': - if knxdeamon != '': - knxdeamon += ' and ' - knxdeamon += 'knxd' - - sql_plugin = False - database_plugin = [] - - for x in self._sh._plugins: - if x.__class__.__name__ == "SQL": - sql_plugin = True - break - elif x.__class__.__name__ == "Database": - database_plugin.append(x.get_instance_name()) - - return self.render_template('services.html', - knxd_service=knxd_service, knxd_socket=knxd_socket, knxdeamon=knxdeamon, - smarthome_service=smarthome_service, lang=get_translation_lang(), - sql_plugin=sql_plugin, database_plugin=database_plugin) - - - @cherrypy.expose - def reload_translation_html(self, lang=''): - if lang != '': - load_translation(lang) - else: - load_translation(get_translation_lang()) - return self.index() - - @cherrypy.expose - def reboot(self): - passwd = request.form['password'] - rbt1 = subprocess.Popen(["echo", passwd], stdout=subprocess.PIPE) - rbt2 = subprocess.Popen(["sudo", "-S", "reboot"], stdin=rbt1. - stdout, stdout=subprocess.PIPE) - print(rbt2.communicate()[0]) - return redirect('/services.html') - - def validate_date(self, date_text): - try: - datetime.datetime.strptime(date_text, '%Y-%m-%d') - return True - except ValueError: - return False - - @cherrypy.expose - def db_dump_html(self, plugin): - """ - returns the smarthomeNG sqlite database as download - """ - if (plugin == "sqlite_old"): - self._sh.sql.dump('%s/var/db/smarthomedb.dump' % self._sh_dir) - mime = 'application/octet-stream' - return cherrypy.lib.static.serve_file("%s/var/db/smarthomedb.dump" % self._sh_dir, mime, - "%s/var/db/" % self._sh_dir) - elif plugin != "": - for x in self._sh._plugins: - if isinstance(x, SmartPlugin): - if x.get_instance_name() == plugin: - x.dump('%s/var/db/smarthomedb_%s.dump' % (self._sh_dir, plugin)) - mime = 'application/octet-stream' - return cherrypy.lib.static.serve_file("%s/var/db/smarthomedb_%s.dump" % (self._sh_dir, plugin), - mime, "%s/var/db/" % self._sh_dir) - return - - # ----------------------------------------------------------------------------------- - - @cherrypy.expose - def conf_yaml_converter_html(self, convert=None, conf_code=None, yaml_code=None): - if convert is not None: - ydata = lib.item_conversion.parse_for_convert(conf_code=conf_code) - if ydata != None: - yaml_code = lib.item_conversion.convert_yaml(ydata) - else: - conf_code = '' - yaml_code = '' - return self.render_template('conf_yaml_converter.html', conf_code=conf_code, yaml_code=yaml_code) - - - # ----------------------------------------------------------------------------------- - # ITEMS - # ----------------------------------------------------------------------------------- - - @cherrypy.expose - def items_html(self): - """ - display a list of items - """ - return self.render_template('items.html', item_count=self._sh.item_count, - items=sorted(self._sh.return_items(), key=lambda k: str.lower(k['_path']), reverse=False) ) - - - @cherrypy.expose - def items_json_html(self): - """ - returns a list of items as json structure - """ - items_sorted = sorted(self._sh.return_items(), key=lambda k: str.lower(k['_path']), reverse=False) - parent_items_sorted = [] - for item in items_sorted: - if "." not in item._path: - if item._name not in ['env_daily', 'env_init', 'env_loc', 'env_stat'] and item._type == 'foo': - parent_items_sorted.append(item) - - item_data = self._build_item_tree(parent_items_sorted) - return json.dumps(item_data) - - @cherrypy.expose - def cache_check_json_html(self): - """ - returns a list of items as json structure - """ - cache_path = "%s/var/cache/" % self._sh_dir - from os import listdir - from os.path import isfile, join - onlyfiles = [f for f in listdir(cache_path) if isfile(join(cache_path, f))] - not_item_related_cache_files = [] - for file in onlyfiles: - if not file.find(".") == 0: # filter .gitignore etc. - item = self._sh.return_item(file) - if item is None: - file_data = {} - file_data['last_modified'] = datetime.datetime.fromtimestamp( - int(os.path.getmtime(cache_path + file)) - ).strftime('%Y-%m-%d %H:%M:%S') - file_data['created'] = datetime.datetime.fromtimestamp( - int(os.path.getctime(cache_path + file)) - ).strftime('%Y-%m-%d %H:%M:%S') - file_data['filename'] = file - not_item_related_cache_files.append(file_data) - - return json.dumps(not_item_related_cache_files) - - @cherrypy.expose - def cache_file_delete_html(self, filename=''): - """ - deletes a file from cache - """ - if len(filename) > 0: - file_path = "%s/var/cache/%s" % (self._sh_dir, filename) - os.remove(file_path); - - return - - @cherrypy.expose - def create_hash_json_html(self, plaintext): - return json.dumps(create_hash(plaintext)) - - @cherrypy.expose - def item_change_value_html(self, item_path, value): - """ - returns a list of items as json structure - """ - item_data = [] - item = self._sh.return_item(item_path) - if self.updates_allowed: - item(value, caller='Backend') - - return - - def disp_str(self, val): - s = str(val) - if s == 'False': - s = '-' - elif s == 'None': - s = '-' - return s - - def age_to_string(self, days, hours, minutes, seconds): - s = '' - if days > 0: - s += str(int(days)) + ' ' - if days == 1: - s += translate('Tag') - else: - s += translate('Tage') - s += ', ' - if (hours > 0) or (s != ''): - s += str(int(hours)) + ' ' - if hours == 1: - s += translate('Stunde') - else: - s += translate('Stunden') - s += ', ' - if (minutes > 0) or (s != ''): - s += str(int(minutes)) + ' ' - if minutes == 1: - s += translate('Minute') - else: - s += translate('Minuten') - s += ', ' - if days > 0: - s += str(int(seconds)) - else: - s += str("%.2f" % seconds) - s += ' ' + translate('Sekunden') - return s - - def disp_age(self, age): - days = 0 - hours = 0 - minutes = 0 - seconds = age - if seconds >= 60: - minutes = int(seconds / 60) - seconds = seconds - 60 * minutes - if minutes > 59: - hours = int(minutes / 60) - minutes = minutes - 60 * hours - if hours > 23: - days = int(hours / 24) - hours = hours - 24 * days - return self.age_to_string(days, hours, minutes, seconds) - - @cherrypy.expose - def item_detail_json_html(self, item_path): - """ - returns a list of items as json structure - """ - item_data = [] - item = self._sh.return_item(item_path) - if item is not None: - if item.type() is None or item.type() is '': - prev_value = '' - value = '' - else: - prev_value = item.prev_value() - value = item._value - - if isinstance(prev_value, datetime.datetime): - prev_value = str(prev_value) - - if 'str' in item.type(): - value = html.escape(value) - prev_value = html.escape(prev_value) - - cycle = '' - crontab = '' - for entry in self._sh.scheduler._scheduler: - if entry == item._path: - if self._sh.scheduler._scheduler[entry]['cycle']: - cycle = self._sh.scheduler._scheduler[entry]['cycle'] - if self._sh.scheduler._scheduler[entry]['cron']: - crontab = html.escape(str(self._sh.scheduler._scheduler[entry]['cron'])) - break - - changed_by = item.changed_by() - if changed_by[-5:] == ':None': - changed_by = changed_by[:-5] - - if item.prev_age() < 0: - prev_age = '' - else: - prev_age = self.disp_age(item.prev_age()) - if str(item._cache) == 'False': - cache = 'off' - else: - cache = 'on' - if str(item._enforce_updates) == 'False': - enforce_updates = 'off' - else: - enforce_updates = 'on' - - item_conf_sorted = collections.OrderedDict(sorted(item.conf.items(), key=lambda t: str.lower(t[0]))) - if item_conf_sorted.get('sv_widget', '') != '': - item_conf_sorted['sv_widget'] = self.html_escape(item_conf_sorted['sv_widget']) - - logics = [] - for trigger in item.get_logic_triggers(): - logics.append(self.html_escape(format(trigger))) - triggers = [] - for trigger in item.get_method_triggers(): - trig = format(trigger) - trig = trig[1:len(trig) - 27] - triggers.append(self.html_escape(format(trig.replace("<", "")))) - - data_dict = {'path': item._path, - 'name': item._name, - 'type': item.type(), - 'value': value, - 'age': self.disp_age(item.age()), - 'last_update': str(item.last_update()), - 'last_change': str(item.last_change()), - 'changed_by': changed_by, - 'previous_value': prev_value, - 'previous_age': prev_age, - 'previous_change': str(item.prev_change()), - 'enforce_updates': enforce_updates, - 'cache': cache, - 'eval': html.escape(self.disp_str(item._eval)), - 'eval_trigger': self.disp_str(item._eval_trigger), - 'cycle': str(cycle), - 'crontab': str(crontab), - 'autotimer': self.disp_str(item._autotimer), - 'threshold': self.disp_str(item._threshold), - 'config': json.dumps(item_conf_sorted), - 'logics': json.dumps(logics), - 'triggers': json.dumps(triggers), - } - - # cast raw data to a string - if item.type() in ['foo', 'list', 'dict']: - data_dict['value'] = str(item._value) - data_dict['previous_value'] = str(prev_value) - - item_data.append(data_dict) - return json.dumps(item_data) - else: - self.logger.error("Requested item %s is None, check if item really exists." % item_path) - return - - def _build_item_tree(self, parent_items_sorted): - item_data = [] - - for item in parent_items_sorted: - nodes = self._build_item_tree(item.return_children()) - tags = [] - tags.append(len(nodes)) - item_data.append({'path': item._path, 'name': item._name, 'tags': tags, 'nodes': nodes}) - - return item_data - - - # ----------------------------------------------------------------------------------- - # LOGICS - # ----------------------------------------------------------------------------------- - - @cherrypy.expose - def logics_html(self, logic=None, trigger=None, reload=None, enable=None, savereload=None, unload=None, configload=None, add=None): - """ - returns information to display a list of all known logics - """ - # process actions triggerd by buttons on the web page - self.process_logics_action(logic, trigger, reload, enable, savereload, None, unload, configload, add) - - # create a list of dicts, where each dict contains the information for one logic - logics = [] - for ln in self._sh.return_logics(): - logic = dict() - logic['name'] = self._sh.return_logic(ln).name - logic['enabled'] = self._sh.return_logic(ln).enabled - logic['filename'] = self._sh.return_logic(ln).filename - logic['userlogic'] = (os.path.basename(os.path.dirname(logic['filename'])) == 'logics') - logic['crontab'] = self._sh.return_logic(ln).crontab - logic['cycle'] = self._sh.return_logic(ln).cycle - logic['watch_items'] = [] - if hasattr(self._sh.return_logic(ln), 'watch_item'): - logic['watch_items'] = self._sh.return_logic(ln).watch_item - logics.append(logic) -# self.logger.warning("Backend: logics_html: - logic = {}, enabled = {}, filename = {}, userlogic = {}, watch_items = {}".format(str(logic['name']), str(logic['enabled']), str(logic['filename']), str(logic['userlogic']), str(logic['watch_items'])) ) - - newlogics = sorted(self.logic_findnew(logics), key=lambda k: k['name']) - - logics_sorted = sorted(logics, key=lambda k: k['name']) - return self.render_template('logics.html', updates=self.updates_allowed, logics=logics_sorted, newlogics=newlogics) - - - @cherrypy.expose - def logics_view_html(self, file_path, logic, trigger=None, reload=None, enable=None, savereload=None, logics_code=None): - """ - returns information to display a logic in an editor window - """ - # process actions triggerd by buttons on the web page - self.process_logics_action(logic, trigger, reload, enable, savereload, logics_code, None, None, None) - mylogic = self._sh.return_logic(logic) - - fobj = open(file_path) - file_lines = [] - for line in fobj: - file_lines.append(self.html_escape(line)) - fobj.close() - - return self.render_template('logics_view.html', logic=mylogic, logic_lines=file_lines, file_path=file_path, - updates=self.updates_allowed) - - # ----------------------------------------------------------------------------------- - - def process_logics_action(self, logic=None, trigger=None, reload=None, enable=None, savereload=None, logics_code=None, unload=None, configload=None, add=None): - self.logger.debug( - "Backend: logics_html: trigger = '{0}', reload = '{1}', enable='{2}', savereload='{3}'".format(trigger, reload, - enable, savereload)) - if enable is not None: - self.logic_enable(logic) - - if trigger is not None: - self.logic_trigger(logic) - - if reload is not None: -# self.logic_reloadcode(logic) # old way to reload a logic (only generate new byte code from python source) - self.logic_unload(logic) - self.logic_configload(logic) - self.logic_trigger(logic) - - if unload is not None: - self.logic_unload(logic) - - if configload is not None: - self.logic_configload(logic) - - if add is not None: - self.logic_configload(logic) - - if savereload is not None: - self.logic_save(logic, logics_code) - - self.logic_unload(logic) - self.logic_configload(logic) - self.logic_trigger(logic) - return - - - def logic_enable(self, logic): - self.logger.debug("Backend: logics[_view]_html: Enable/Disable logic = '{0}'".format(logic)) - if self.updates_allowed: - if logic in self._sh.return_logics(): - mylogic = self._sh.return_logic(logic) - if mylogic.enabled: - mylogic.disable() - else: - mylogic.enable() - else: - self.logger.warning("Backend: Logic '{0}' not found, cannot be be enabled/disabled".format(logic)) - else: - self.logger.warning("Backend: Logic enabling/disabling is not allowed. (Change 'updates_allowed' in plugin.conf") - - - def logic_trigger(self, logic): - self.logger.debug("Backend: logics[_view]_html: Trigger logic = '{0}'".format(logic)) - if self.updates_allowed: - if logic in self._sh.return_logics(): - self._sh.trigger(logic, by='Backend') - else: - self.logger.warning("Backend: Logic '{0}' not found".format(logic)) - else: - self.logger.warning("Backend: Logic triggering is not allowed. (Change 'updates_allowed' in plugin.conf") - - - def logic_unload(self, logic): - self.logger.warning("Backend: logics[_view]_html: Unload logic = '{0}'".format(logic)) - mylogic = self._sh.return_logic(logic) - mylogic.enabled = False - mylogic.cycle = None - mylogic.crontab = None - - # Scheduler entfernen - self._sh.scheduler.remove(logic) - - # watch_items entfernen - if hasattr(mylogic, 'watch_item'): - if isinstance(mylogic.watch_item, str): - mylogic.watch_item = [mylogic.watch_item] - for entry in mylogic.watch_item: - # item hook - for item in self._sh.match_items(entry): - try: - item.remove_logic_trigger(mylogic) - except: - self.logger.error("Backend: logics[_view]_html: Unload logic = '{0}' - cannot remove logic_triggers".format(logic)) - mylogic.watch_item = [] - - - def logic_configload(self, logic): - self.logger.warning("Backend: logics[_view]_html: load logic with config = '{}'".format(logic)) - - _config = {} - _config.update(self._sh._logics._read_logics(self._sh._logic_conf_basename, self._sh._logic_dir)) -# self.logger.warning("Backend: logics[_view]_html: _config[{}] = '{}'".format(str(logic), str(_config[logic]))) - - newlogic = lib.logic.Logic(self._sh, logic, _config[logic]) - if hasattr(newlogic, 'bytecode'): - self._sh._logics._logics[logic] = newlogic - self._sh.scheduler.add(logic, newlogic, newlogic.prio, newlogic.crontab, newlogic.cycle) - # plugin hook - # item hook - if hasattr(newlogic, 'watch_item'): - if isinstance(newlogic.watch_item, str): - newlogic.watch_item = [newlogic.watch_item] - for entry in newlogic.watch_item: - for item in self._sh.match_items(entry): - item.add_logic_trigger(newlogic) - - - def logic_save(self, logic, logics_code): - self.logger.debug("Backend: logics_view_html: Save logic = '{0}'".format(logic)) - - if self.updates_allowed: - if logic in self._sh.return_logics(): - mylogic = self._sh.return_logic(logic) - - f = open(mylogic.filename, 'w') - f.write(logics_code) - f.close() - - -# for name in _config: -# logger.debug("Logic: {}".format(name)) -# logic = Logic(self._sh, name, _config[name]) -# if hasattr(logic, 'bytecode'): -# self._logics[name] = logic -# self._sh.scheduler.add(name, logic, logic.prio, logic.crontab, logic.cycle) -# else: -# continue -# # plugin hook -# for plugin in self._sh._plugins: -# if hasattr(plugin, PLUGIN_PARSE_LOGIC): -# update = plugin.parse_logic(logic) -# if update: -# logic.add_method_trigger(update) - - - def logic_findnew(self, loadedlogics): - - _config = {} - _config.update(self._sh._logics._read_logics(self._sh._logic_conf_basename, self._sh._logic_dir)) - -# self.logger.warning("Backend (logic_findnew): _config = '{}'".format(_config)) - newlogics = [] - for configlogic in _config: - found = False - for l in loadedlogics: - if configlogic == str(l['name']): - found = True - if not found: - - newlogics.append({'name': configlogic, 'filename': _config[configlogic]['filename'] }) -# self.logger.warning("Backend (logic_findnew): newlogics = '{}'".format(newlogics)) - return newlogics - - - def logic_reloadcode(self, logic): - self.logger.debug("Backend: logics[_view]_html: Reload logic = '{0}'".format(logic)) - if self.updates_allowed: - if logic in self._sh.return_logics(): - mylogic = self._sh.return_logic(logic) - self.logger.info("Backend: logics_html: Reload logic='{0}', filename = '{1}'".format(logic, - os.path.basename( - mylogic.filename))) - mylogic.generate_bytecode() - self._sh.trigger(logic, by='Backend', value="Init") - else: - self.logger.warning("Backend: Logic '{0}' not found".format(logic)) - else: - self.logger.warning("Backend: Logic reloads are not allowed. (Change 'updates_allowed' in plugin.conf") - - - # ----------------------------------------------------------------------------------- - # SCHEDULERS - # ----------------------------------------------------------------------------------- - - @cherrypy.expose - def schedules_html(self): - """ - display a list of all known schedules - """ - return self.render_template('schedules.html') - - - # ----------------------------------------------------------------------------------- - # PLUGINS - # ----------------------------------------------------------------------------------- - - @cherrypy.expose - def plugins_html(self): - """ - display a list of all known plugins - """ - conf_plugins = {} - _conf = lib.config.parse(self._sh._plugin_conf) - for plugin in _conf: - # self.logger.warning("plugins_html: class_name='{0}', class_path='{1}'".format(_conf[plugin]['class_name'], _conf[plugin]['class_path'])) - conf_plugins[_conf[plugin]['class_name']] = {} - conf_plugins[_conf[plugin]['class_name']] = _conf[plugin] - # self.logger.warning("plugins_html: conf_plugins='{0}'".format(conf_plugins)) - - plugins = [] - for x in self._sh._plugins: - plugin = dict() - plugin['classname'] = x.__class__.__name__ - plugin['classpath'] = conf_plugins[x.__class__.__name__]['class_path'] - plugin['attributes'] = conf_plugins[x.__class__.__name__] - if isinstance(x, SmartPlugin): - plugin['smartplugin'] = True - plugin['instancename'] = x.get_instance_name() - plugin['multiinstance'] = x.is_multi_instance_capable() - plugin['version'] = x.get_version() - else: - plugin['smartplugin'] = False - plugins.append(plugin) - plugins_sorted = sorted(plugins, key=lambda k: k['classpath']) - - return self.render_template('plugins.html', plugins=plugins_sorted) - - - # ----------------------------------------------------------------------------------- - # THREADS - # ----------------------------------------------------------------------------------- - - @cherrypy.expose - def threads_html(self): - """ - display a list of all threads - """ - threads = [] - for t in threading.enumerate(): - thread = dict() - thread['sort'] = str(t.name).lower() - thread['name'] = t.name - thread['id'] = t.ident - thread['alive'] = t.is_alive() - threads.append(thread) - threads_sorted = sorted(threads, key=lambda k: k['sort']) - threads_count = len(threads_sorted) - - return self.render_template('threads.html', threads=threads_sorted, threads_count=threads_count) - - - # ----------------------------------------------------------------------------------- - # LOGGING - # ----------------------------------------------------------------------------------- - - @cherrypy.expose - def logging_html(self): - """ - display a list of all loggers - """ - loggerDict = {} - # Filter to get only active loggers - for l in logging.Logger.manager.loggerDict: - if (logging.getLogger(l).level > 0) or (logging.getLogger(l).handlers != []): - loggerDict[l] = logging.Logger.manager.loggerDict[l] - - - # get information about active loggers - loggerList_sorted = sorted(loggerDict) - loggerList_sorted.insert(0, "root") # Insert information about root logger at the beginning of the list - loggers = [] - for ln in loggerList_sorted: - if ln == 'root': - logger = logging.root - else: - logger = logging.getLogger(ln) - l = dict() - l['name'] = logger.name - l['disabled'] = logger.disabled - - # get information about loglevels - if logger.level == 0: - l['level'] = '' - elif logger.level in logging._levelToName: - l['level'] = logging._levelToName[logger.level] - else: - l['level'] = logger.level - - l['filters'] = logger.filters - - # get information about handlers and filenames - l['handlers'] = list() - l['filenames'] = list() - for h in logger.handlers: - l['handlers'].append(h.__class__.__name__) - try: - fn = str(h.baseFilename) - except: - fn = '' - l['filenames'].append(fn) - - loggers.append(l) - - return self.render_template('logging.html', loggers=loggers) - - - @cherrypy.expose - def log_view_html(self, text_filter='', log_level_filter='ALL', page=1, logfile='smarthome.log'): - """ - returns the smarthomeNG logfile as view - """ - log = '/var/log/' + os.path.basename(logfile) - log_name = self._sh_dir + log - fobj = open(log_name) - log_lines = [] - start = (int(page) - 1) * 1000 - end = start + 1000 - counter = 0 - log_level_hit = False - total_counter = 0 - for line in fobj: - line_text = self.html_escape(line) - if log_level_filter != "ALL" and not self.validate_date(line_text[0:10]) and log_level_hit: - if start <= counter < end: - log_lines.append(line_text) - counter += 1 - else: - log_level_hit = False - if (log_level_filter == "ALL" or line_text.find(log_level_filter) in [19, 20, 21, 22, - 23]) and text_filter in line_text: - if start <= counter < end: - log_lines.append(line_text) - log_level_hit = True - counter += 1 - fobj.close() - num_pages = -(-counter // 1000) - if num_pages == 0: - num_pages = 1 - return self.render_template('log_view.html', - current_page=int(page), pages=num_pages, - logfile=os.path.basename(log_name), log_lines=log_lines, text_filter=text_filter) - - - @cherrypy.expose - def log_dump_html(self, logfile='smarthome.log'): - """ - returns the smarthomeNG logfile as download - """ - log = '/var/log/' + os.path.basename(logfile) - log_name = self._sh_dir + log - mime = 'application/octet-stream' - return cherrypy.lib.static.serve_file(log_name, mime, log_name) - - # ----------------------------------------------------------------------------------- - # VISU - # ----------------------------------------------------------------------------------- - - @cherrypy.expose - def visu_html(self): - """ - display a list of all connected visu clients - """ - clients = [] - if self.visu_plugin is not None: - if self.visu_plugin_build == '2': - for c in self.visu_plugin.return_clients(): - client = dict() - deli = c.find(':') - client['ip'] = c[0:c.find(':')] - client['port'] = c[c.find(':') + 1:] - try: - client['name'] = socket.gethostbyaddr(client['ip'])[0] - except: - client['name'] = client['ip'] - clients.append(client) - - if self.visu_plugin_build > '2': - # self.logger.warning("BackendServer: Language '{0}' not found, using standard language instead".format(language)) - # yield client.addr, client.sw, client.swversion, client.hostname, client.browser, client.browserversion - # for c, sw, swv, ch in self.visu_plugin.return_clients(): - for clientinfo in self.visu_plugin.return_clients(): - c = clientinfo.get('addr', '') - client = dict() - deli = c.find(':') - client['ip'] = c[0:c.find(':')] - client['port'] = c[c.find(':') + 1:] - try: - client['name'] = socket.gethostbyaddr(client['ip'])[0] - except: - client['name'] = client['ip'] - client['sw'] = clientinfo.get('sw', '') - client['swversion'] = clientinfo.get('swversion', '') - client['hostname'] = clientinfo.get('hostname', '') - client['browser'] = clientinfo.get('browser', '') - client['browserversion'] = clientinfo.get('browserversion', '') - clients.append(client) - - clients_sorted = sorted(clients, key=lambda k: k['name']) - - self.find_visu_plugin() - return self.render_template('visu.html', - visu_plugin_build=self.visu_plugin_build, - clients=clients_sorted) - - - # ----------------------------------------------------------------------------------- - # DISCLOSURE - # ----------------------------------------------------------------------------------- - - @cherrypy.expose - def disclosure_html(self): - """ - display disclosure - """ - return self.render_template('disclosure.html') - diff --git a/backend/_pv_1_3_5/README.md b/backend/_pv_1_3_5/README.md deleted file mode 100644 index ac606aed8..000000000 --- a/backend/_pv_1_3_5/README.md +++ /dev/null @@ -1,107 +0,0 @@ -# Backend GUI v1.3.5 (up to shNG v1.3) - -This plugin delivers information about the current SmartHomeNG installation. Right now it serves as a support tool for helping other users with an installation that does not run properly. Some highlights: - -* a list of installed python modules is shown versus the available versions from PyPI -* a list of items and their attributes is shown -* a list of logics and their next execution time -* a list of current schedulers and their next execution time -* direct download of sqlite database (if plugin is used) and smarthome.log -* some information about frequently used daemons like knxd/eibd is included -* supports basic authentication -* multi-language support - -There is however only basic protection against unauthorized access or use of the plugin so be careful when enabling it with your network. - -Call the backend-webserver: **```http://:8383```** - -Support is provided through the support thread within the smarthomeNG forum: - -[knx-user-forum.de/forum/supportforen/smarthome-py/959964-support-thread-f%C3%BCr-das-backend-plugin](https://knx-user-forum.de/forum/supportforen/smarthome-py/959964-support-thread-für-das-backend-plugin) - -## Requirements - -This plugin is running under Python >= 3.4 as well as the libs cherrypy and jinja2. You can install them with: -``` -(sudo apt-get install python-cherrypy) -sudo pip3 install cherrypy -(sudo apt-get install python-jinja2) -sudo pip3 install jinja2 -``` - -And please pay attention that the libs are installed for Python3 and not an older Python 2.7 that is probably installed on your system. - -The log level filter in the log file view will only work with "%(asctime)s %(levelname)-8s" in the beginning of the configured format! Dateformat needs to be datefmt: '%Y-%m-%d %H:%M:%S' - -### Running this plugin under Python 3.2 -If you really need to run this plugin under Python 3.2 you may not use the newest version of all packages. The packages **Jinja2** and **MarkupSafe** have dropped support for Python 3.2. Make sure to install the following older versions into your Phython3.2 environment, as newer versions are not compatible with Python 3.2 any more: - -``` -- Jinja2 v2.6 -- MarkupSafe v0.15 -``` - - - -To support visualization, the visu_websocket plugin has to be used. It has to be PLUGIN_VERSION >= "1.1.2". - - -## Configuration - -### plugin.yaml - -```yaml -BackendServer: - class_name: BackendServer - class_path: plugins.backend - #ip: xxx.xxx.xxx.xxx - #port: 8383 - #updates_allowed: 'True' - #threads: 8 - #user: admin - #password: very_secure_password - #hashed_password: 1245a9633edf47b7091f37c4d294b5be5a9936c81c5359b16d1c4833729965663f1943ef240959c53803fedef7ac19bd59c66ad7e7092d7dbf155ce45884607d - #language: en - #developer_mode: 'on' - #pypi_timeout: 5 -``` - -#### ip -IP address to start the backend server. Usually it doesnot need to be configured. - -If not configured the standard ip address of the system is used. If you like to restrict the usage of the BackendServer to the system itself (the browser ist running on the smarthomeNG system itself), you can configure the ip to 127.0.0.1. In this case, the BackendServer is only available through the localhost address. - -#### port -The port on which the backend server listens. By default port **`8383`** is used. - -#### updates_allowed - -By default, the backend server allows updates to the running smarthomeNG instance. For instance, it is possible to trigger or to reload a logic. Setting **`updates_allowed`** to **`False`**, you can disable these features. - -#### threads - -Number of worker threads to start by cherrypy (default 8, which may be too much for slow CPUs) - -#### user (optional) - -The user for basic authentication. If left out, the user name is set as "admin" - -#### password (optional) - -The plaintext password for basic authentication. If you want to store your password as hash, use 'hashed_password' instead. If both "password" and "hashed_password" are left out, basic authentication is disabled. - -#### hashed_password (optional) - -The password for basic authentication as hash value. Can be used instead of "password" if you do not want a plaintext password in your config file. If both "password" and "hashed_password" are left out, basic authentication is disabled. Currently hashed_password is the SHA-512 hash value of the password. To create the hash for your password, you can use function "Create password hash" on page "Services" in the backend. - -#### language (optional) - -You can specify a language to use for the plugin. Besides the standard language (german) which is used, if this parameter isn't set, you can specify english (for the time being). The language is specified by **``en``** - -#### developer_mode (optional) - -You may specify develper_mode = on, if you are developiing within the backend plugin. At the moment, the only thing that changes is an additional button **``reload translation``** on the services page - -#### pypi_timeout (optional) - -Timeout for PyPI accessibility check (seconds). PyPI is queried on page "Systeminfo" to compare installed python module versions with current versions if accessible. If you receive the message "PyPI inaccessible" on systems with internet access you may increase the value. On systems where PyPI can not be reached (no/restricted internet access) you may set the timeout to 0 which disables the PyPI queries. diff --git a/backend/_pv_1_3_5/__init__.py b/backend/_pv_1_3_5/__init__.py deleted file mode 100755 index 28157b769..000000000 --- a/backend/_pv_1_3_5/__init__.py +++ /dev/null @@ -1,215 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf8 -*- -######################################################################### -# Copyright 2016- René Frieß rene.friess@gmail.com -# Martin Sinn m.sinn@gmx.de -# Bernd Meiners -# Christian Strassburg c.strassburg@gmx.de -######################################################################### -# Backend plugin for SmartHomeNG -# -# This plugin is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This plugin is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this plugin. If not, see . -######################################################################### - -import cherrypy -import logging -import platform -import collections -import datetime -import pwd -import html -import os -import json -import subprocess -import socket -import sys -import threading -import lib.config -from lib.model.smartplugin import SmartPlugin -from lib.utils import Utils -from jinja2 import Environment, FileSystemLoader - -from .BackendCore import Backend as BackendCore -from .BackendBlockly import BackendBlocklyLogics -from .utils import * - - - -class BackendServer(SmartPlugin): - ALLOW_MULTIINSTANCE = False - PLUGIN_VERSION='1.3.5' - - def my_to_bool(self, value, attr='', default=False): - try: - result = self.to_bool(value) - except: - result = default - self.logger.error("BackendServer: Invalid value '"+str(value)+"' configured for attribute "+attr+" in plugin.conf, using '"+str(result)+"' instead") - return result - - def get_local_ip_address(self): - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - s.connect(("10.10.10.10", 80)) - return s.getsockname()[0] - - def __init__(self, sh, port=None, threads=8, ip='', updates_allowed='True', user="admin", password="", hashed_password="", language="", developer_mode="no", pypi_timeout=5): - self.logger = logging.getLogger(__name__) - self._user = user - self._password = password - self._hashed_password = hashed_password - - if self._password is not None and self._password != "" and self._hashed_password is not None and self._hashed_password != "": - self.logger.warning("BackendServer: Both 'password' and 'hashed_password' given. Ignoring 'password' and using 'hashed_password'!") - self._password = None - - if self._password is not None and self._password != "" and (self._hashed_password is None or self._hashed_password == ""): - self.logger.warning("BackendServer: Giving plaintext password in configuration is insecure. Consider using 'hashed_password' instead!") - self._hashed_password = None - - if (self._password is not None and self._password != "") or (self._hashed_password is not None and self._hashed_password != ""): - self._basic_auth = True - else: - self._basic_auth = False - self._sh = sh - - if self.is_int(port): - self.port = int(port) - else: - self.port = 8383 - if port is not None: - self.logger.error("BackendServer: Invalid value '"+str(port)+"' configured for attribute 'port' in plugin.conf, using '"+str(self.port)+"' instead") - - if self.is_int(threads): - self.threads = int(threads) - else: - self.threads = 8 - self.logger.error("BackendServer: Invalid value '"+str(threads)+"' configured for attribute 'thread' in plugin.conf, using '"+str(self.threads)+"' instead") - - if ip == '': - ip = self.get_local_ip_address() - self.logger.debug("BackendServer: Using local ip address '{0}'".format(ip)) - else: - pass - # if not self.is_ip(ip): - # self.logger.error("BackendServer: Invalid value '"+str(ip)+"' configured for attribute ip in plugin.conf, using '"+str('0.0.0.0')+"' instead") - # ip = '0.0.0.0' - language = language.lower() - if language != '': - if not load_translation(language): - self.logger.warning("BackendServer: Language '{0}' not found, using standard language instead".format(language)) - self.developer_mode = self.my_to_bool(developer_mode, 'developer_mode', False) - - self.updates_allowed = self.my_to_bool(updates_allowed, 'updates_allowed', True) - - if self.is_int(pypi_timeout): - self.pypi_timeout = int(pypi_timeout) - else: - self.pypi_timeout = 5 - if pypi_timeout is not None: - self.logger.error("BackendServer: Invalid value '" + str(pypi_timeout) + "' configured for attribute 'pypi_timeout' in plugin.conf, using '" + str(self.pypi_timeout) + "' instead") - - current_dir = os.path.dirname(os.path.abspath(__file__)) - self.logger.debug("BackendServer running from '{}'".format(current_dir)) - - config = {'global': { - 'engine.autoreload.on': False, - 'tools.staticdir.debug': True, - 'tools.trailing_slash.on': False, - 'log.screen': False - }, - '/': { - 'tools.auth_basic.on': self._basic_auth, - 'tools.auth_basic.realm': 'earth', - 'tools.auth_basic.checkpassword': self.validate_password, - 'tools.staticdir.root': current_dir, - }, - '/static': { - 'tools.staticdir.on': True, - 'tools.staticdir.dir': os.path.join(current_dir, 'static') - } - } - from cherrypy._cpserver import Server - self._server = Server() - self._server.socket_host = ip - self._server.socket_port = int(self.port) - self._server.thread_pool = self.threads - self._server.subscribe() - - self._cherrypy = cherrypy - self._cherrypy.config.update(config) - self._cherrypy.tree.mount(Backend(self, self.updates_allowed, language, self.developer_mode, self.pypi_timeout), '/', config = config) - - def run(self): - self.logger.debug("BackendServer: rest run") - self._server.start() - #self._cherrypy.engine.start() - self.logger.debug("BackendServer: engine started") - #cherrypy.engine.block() - self.alive = True - - def stop(self): - self.logger.debug("BackendServer: shutting down") - self._server.stop() - #self._cherrypy.engine.exit() - self.logger.debug("BackendServer: engine exited") - self.alive = False - - def parse_item(self, item): - pass - - def parse_logic(self, logic): - pass - - def update_item(self, item, caller=None, source=None, dest=None): - pass - - def validate_password(self, realm, username, password): - if username != self._user or password is None or password == "": - return False - - if self._hashed_password is not None: - return Utils.check_hashed_password(password, self._hashed_password) - elif self._password is not None: - return password == self._password - - return False - - - -class Backend(BackendCore, BackendBlocklyLogics): - env = Environment(loader=FileSystemLoader(os.path.dirname(os.path.abspath(__file__))+'/templates')) - env.globals['get_basename'] = get_basename - env.globals['is_userlogic'] = is_userlogic - env.globals['_'] = translate - - def __init__(self, backendserver=None, updates_allowed=True, language='', developer_mode=False, pypi_timeout = 5): - self.logger = logging.getLogger(__name__) - self._bs = backendserver - self._sh = backendserver._sh - self.language = language - self.updates_allowed = updates_allowed - self.developer_mode = developer_mode - self.pypi_timeout = pypi_timeout - - self._sh_dir = self._sh.base_dir - self.visu_plugin = None - self.visu_plugin_version = '1.0.0' - - def html_escape(self, str): - return html_escape(str) - - -#if __name__ == "__main__": -# server = BackendServer( None, port=8080, ip='0.0.0.0') -# server.run() diff --git a/backend/_pv_1_3_5/locale/de.json b/backend/_pv_1_3_5/locale/de.json deleted file mode 100755 index 7124515ad..000000000 --- a/backend/_pv_1_3_5/locale/de.json +++ /dev/null @@ -1,194 +0,0 @@ -{ - "Scheduler": "Scheduler", - "Logik": "Logik", - "Systemlogiken": "Systemlogiken", - "Neue Logiken (nicht geladen)": "Neue Logiken (nicht geladen)", - "nächste Ausführung": "nächste Ausführung", - "Cycle": "Cycle", - "Crontab": "Crontab", - "Dateiname": "Dateiname", - "Aktionen": "Aktionen", - "Items": "Items", - "Item": "Item", - "gesamt": "gesamt", - "Suchen": "Suchen", - "Suche zurücksetzen": "Zurücksetzen", - "Alle aufklappen": "Alle aufklappen", - "Alle zuklappen": "Alle zuklappen", - "Itempfad suchen...": "Itempfad suchen...", - "Item im Baum auswählen um Details einzusehen!": "Item im Baum auswählen um Details einzusehen!", - "Item-Informationen": "Item-Informationen", - "Attribut": "Attribut", - "Wert": "Wert", - "Pfad": "Pfad", - "Name": "Name", - "Typ": "Typ", - - "Änderungsinformationen": "Änderungsinformationen", - "Letztes Update": "Letztes Update", - "Letzte Änderung": "Letzte Änderung", - "Geändert durch": "Geändert durch", - "age": "Alter", - "vorheriger Wert": "vorheriger Wert", - "previous change": "vorherige Änderung", - "previous age": "vorheriges Alter", - - "Evaluation und Trigger": "Initialisierungs-, Evaluations- und Trigger-Konfiguration", - "Plugin spezifische Attribute": "Plugin spezifische Konfigurationen", - "Verbundene Logiken": "Verbundene Logiken", - "Verbundene Trigger": "Verbundene Trigger", - "Willkommen im Backend von": "Willkommen im Backend von", - "Eigenschaft": "Eigenschaft", - "IP": "IP Adresse", - "Betriebssystem": "Betriebssystem", - "Architektur": "Architektur", - "Benutzer": "Benutzer", - "Freier Speicher": "Freier Speicher", - "Datum": "Datum", - "Zeit": "Zeit", - "Tag": "Tag", - "Tage": "Tage", - "Stunde": "Stunde", - "Stunden": "Stunden", - "Minute": "Minute", - "Minuten": "Minuten", - "Sekunden": "Sekunden", - "Betriebszeit": "Betriebszeit", - "Python Version": "Python Version", - "in": "in", - "installierte Version": "installierte Version", - "Neuste Version": "Neuste Version", - "Keine Antwort von PyPI": "Keine Antwort von PyPI", - "PyPI nicht erreichbar": "PyPI nicht erreichbar", - "PyPI Prüfung deaktiviert": "PyPI Prüfung deaktiviert", - "Dienst": "Dienst", - "Status": "Status", - "Aktion": "Aktion", - "Root-Passwort": "Root-Passwort", - "Neu starten": "System neu starten", - "Dienst für die KNX Unterstützung": "Dienst für die KNX Unterstützung", - "Nicht aktiv": "Nicht aktiv", - "Sprache des Backends": "Sprache des Backends", - "Logfile speichern": "Logfile speichern", - "Logfile ansehen": "Logfile ansehen", - "Logger ansehen": "Logger ansehen", - "Datenbank-Dump": "Datenbank-Dump", - "Übersetzung neu laden": "Übersetzung neu laden", - "Auf Deutsch wechseln": "Auf Deutsch wechseln", - "Auf Englisch wechseln": "Auf Englisch wechseln", - "Auf Französisch wechseln": "Auf Französisch wechseln", - "Auf Polnisch wechseln": "Auf Polnisch wechseln", - "Nr.": "Nr.", - "Type": "Type", - "Plugin": "Plugin", - "Classname": "Classname", - "Instanz": "Instanz", - "Version": "Version", - "Mehrere Instanzen möglich": "Mehrere Instanzen möglich", - "Ja": "Ja", - "Nein": "Nein", - "Thread": "Thread", - "Thread-Id": "Thread-Id", - "Aktiv": "Aktiv", - "Visu Client": "Visu Client", - "Port": "Port", - "Client Software": "Client Software", - "Browser": "Browser", - "No active clients": "Keine aktiven Clients", - "Die eingegebenen Daten sind kein numerischer Wert": "Die eingegebenen Daten sind kein numerischer Wert", - "Filter": "Filter", - "Logfile": "Log-Datei", - "Dateien ohne zugehöriges Item im /var/cache Verzeichnis": "Dateien ohne zugehöriges Item im /var/cache Verzeichnis", - "Letzte Modifikation": "Letzte Modifikation", - "Erstellungsdatum": "Erstellungsdatum", - "no data available": "keine Daten verfügbar", - "logger name": "Logger Name", - "disabled": "disabled", - "level": "Level", - "filters": "Filter(s)", - "handlers": "Handler(s)", - "logfiles": "Logfile(s)", - "Logging": "Logging", - "Passwort anzeigen": "Passwort anzeigen", - "SmartHomeNG Version": "SmartHomeNG Version", - "Watch_Items": "Watch_Items", - "Anforderungen": "Anforderungen", - "Übersicht": "Übersicht", - "Eingabe im .CONF Format": "Eingabe im .CONF Format", - "Ergebnis im .YAML Format": "Ergebnis im .YAML Format", - - - "_items": { - "path": "Pfad", - "name": "Name", - "type": "Typ (type)", - "value": "Wert (value)", - "cache": "cache", - "enforce_updates": "enforce_updates", - "eval": "eval", - "eval_trigger": "eval_trigger", - "cycle": "cycle", - "crontab": "crontab", - "autotimer": "autotimer", - "threshold": "threshold" - }, - - "_threads": { - "True": "Ja", - "False": "Nein" - }, - - "_disclosure": { - "Lizenz": "Lizenz", - "Link": "Link", - "Name": "Name", - "disclosure_title": "Offenlegung von Open Source Software Komponenten des SmartHomeNG BackendServer Plugins", - "Verwendete Open Source Software Komponenten": "Verwendete Open Source Software Komponenten", - "Icons/Bilder": "Icons/Bilder", - "Alle Icons und Bilder kommen von": "Alle Icons und Bilder kommen von " - }, - - "_button": { - "smarthomeNG starten": "SmartHomeNG starten", - "knxd service starten": "knxd service starten", - "knxd socket starten": "knxd socket starten", - "smarthomeNG beenden": "SmartHomeNG beenden", - "knxd service beenden": "knxd service beenden", - "knxd socket beenden": "knxd socket beenden", - "Filter anwenden": "Filter anwenden", - "Cacheprüfung": "Cacheprüfung", - "Passwort-Hash erzeugen": "Passwort-Hash erzeugen", - "Englisch": "English", - "Deutsch": "Deutsch", - "Französisch": "French", - "Polnisch": "Polish", - "Auslösen": "Auslösen", - "Neu Laden": "Neu Laden", - "Deaktivieren": "Deaktivieren", - "Aktivieren": "Aktivieren", - "Hinzufügen": "Hinzufügen", - "Leeren" : "Leeren", - "Schließen": "Schließen", - "Änderungen verwerfen" : "Änderungen verwerfen", - "Blöcke speichern" : "Blöcke speichern", - "Beenden" : "Beenden", - "Speichern" : "Speichern", - "Speichern_und_Neu_Laden" : "Speichern und neu laden", - "Löschen" : "Löschen", - "Konvertieren": "Konvertieren" - }, - - "_menu": { - "Systeminfo": "Systeminfo", - "Dienste": "Dienste", - "CONF-YAML Konverter": "CONF-YAML Konverter", - "Items": "Items", - "Logiken": "Logiken", - "Blockly-Logiken-Editor": "Blockly-Logiken-Editor", - "Scheduler": "Scheduler", - "Plugins": "Plugins", - "Threads": "Threads", - "Visu": "Visu", - "Disclosure": "Disclosure" - } -} diff --git a/backend/_pv_1_3_5/locale/en.json b/backend/_pv_1_3_5/locale/en.json deleted file mode 100755 index 2758acf9e..000000000 --- a/backend/_pv_1_3_5/locale/en.json +++ /dev/null @@ -1,192 +0,0 @@ -{ - "Scheduler": "Scheduler", - "Logik": "Logic", - "Systemlogiken": "System Logics", - "nächste Ausführung": "next execution", - "Cycle": "Cycle", - "Crontab": "Crontab", - "Dateiname": "Filename", - "Aktionen": "Actions", - "Items": "Items", - "Item": "Item", - "gesamt": "total", - "Suchen": "Search", - "Suche zurücksetzen": "Reset search", - "Alle aufklappen": "Unfold All", - "Alle zuklappen": "Fold All", - "Itempfad suchen...": "Search Itempath...", - "Item im Baum auswählen um Details einzusehen!": "Select item in tree to see details!", - "Item-Informationen": "Item Information", - "Attribut": "attribute", - "Wert": "value", - "Pfad": "path", - "Name": "name", - "Typ": "type", - - "Änderungsinformationen": "Information about changes", - "Letztes Update": "last update", - "Letzte Änderung": "last change", - "Geändert durch": "changed by", - "age": "age", - "vorheriger Wert": "previous value", - "previous change": "previous change", - "previous age": "previous age", - - "Evaluation und Trigger": "Initialization, Evaluation and Trigger Configuration", - "Plugin spezifische Attribute": "Plugin specific configurations", - "Verbundene Logiken": "Bound Logics", - "Verbundene Trigger": "Bound Triggers", - "Willkommen im Backend von": "Welcome to the backend of", - "Eigenschaft": "Property", - "IP": "IP Address", - "Betriebssystem": "Operating System", - "Architektur": "Architecture", - "Benutzer": "User", - "Freier Speicher": "Free disk space", - "Datum": "Date", - "Zeit": "Time", - "Tag": "day", - "Tage": "days", - "Stunde": "hour", - "Stunden": "hours", - "Minute": "minute", - "Minuten": "minutes", - "Sekunden": "seconds", - "Betriebszeit": "Uptime", - "Python Version": "Python Version", - "in": "in", - "installierte Version": "installed Version", - "Neuste Version": "Newest Version", - "Keine Antwort von PyPI": "No answer from PyPI", - "PyPI nicht erreichbar": "PyPI inaccessible", - "PyPI Prüfung deaktiviert": "PyPI check disabled", - "Dienst": "Service", - "Status": "Status", - "Aktion": "Action", - "Root-Passwort": "root password", - "Neu starten": "Restart system", - "Dienst für die KNX Unterstützung": "Service for KNX support", - "Nicht aktiv": "Not active", - "Sprache des Backends": "Language of Backend", - "Logfile speichern": "Save logfile", - "Logfile ansehen": "View logfile", - "Logger ansehen": "View loggers", - "Datenbank-Dump": "Dump database", - "Übersetzung neu laden": "Reload translation", - "Auf Deutsch wechseln": "Switch to German", - "Auf Englisch wechseln": "Switch to English", - "Auf Französisch wechseln": "Switch to French", - "Auf Polnisch wechseln": "Switch to Polish", - "Nr.": "No.", - "Type": "Type", - "Plugin": "Plugin", - "Classname": "Classname", - "Instanz": "Instance", - "Version": "Version", - "Mehrere Instanzen möglich": "Multiple Instances possible", - "Ja": "Yes", - "Nein": "No", - "Thread": "Thread", - "Thread-Id": "Thread-Id", - "Aktiv": "Active", - "Visu Client": "Visu Client", - "Port": "Port", - "Client Software": "Client Software", - "Browser": "Browser", - "No active clients": "No active clients", - "Die eingegebenen Daten sind kein numerischer Wert": "Die eingegebenen Daten sind kein numerischer Wert", - "Filter": "Filter", - "Logfile": "Logfile", - "Dateien ohne zugehöriges Item im /var/cache Verzeichnis": "Files without corresponding item in /var/cache folder", - "Letzte Modifikation": "Last Modification", - "Erstellungsdatum": "Created", - "no data available": "no data available", - "logger name": "Logger Name", - "disabled": "Disabled", - "level": "Level", - "filters": "Filter(s)", - "handlers": "Handler(s)", - "logfiles": "Logfile(s)", - "Logging": "Logging", - "Passwort anzeigen": "Show Password", - "SmartHomeNG Version": "SmartHomeNG Version", - "Watch_Items": "Watch_Items", - "Anforderungen": "Requirements", - "Übersicht": "Overview", - "Eingabe im .CONF Format": "Input in .CONF format", - "Ergebnis im .YAML Format": "Result in .YAML format", - - "_items": { - "path": "Pfad", - "name": "name", - "type": "type", - "value": "value", - "cache": "cache", - "enforce_updates": "enforce_updates", - "eval": "eval", - "eval_trigger": "eval_trigger", - "cycle": "cycle", - "crontab": "crontab", - "autotimer": "autotimer", - "threshold": "threshold" - }, - - "_threads": { - "True": "Yes", - "False": "No" - }, - - - "_disclosure": { - "Lizenz": "License", - "Link": "Link", - "Name": "Name", - "disclosure_title": "Disclosure of Open Source Software Components deployed in SmartHomeNG BackendServer Plugin", - "Verwendete Open Source Software Komponenten": "Open Source Software Components used for the Plugin", - "Icons/Bilder": "Icons/Images", - "Alle Icons und Bilder kommen von": "All icons and images are taken from " - }, - - "_button": { - "Auslösen": "Trigger", - "Neu Laden": "Reload", - "smarthomeNG starten": "Start SmartHomeNG", - "knxd service starten": "Start knxd service", - "knxd socket starten": "Start knxd socket", - "smarthomeNG beenden": "Stop SmartHomeNG", - "knxd service beenden": "Stop knxd service", - "knxd socket beenden": "Stop knxd socket", - "Filter anwenden": "Apply Filter", - "Cacheprüfung": "Cache Check", - "Passwort-Hash erzeugen": "Create Password Hash", - "Englisch": "English", - "Deutsch": "Deutsch", - "Französisch": "French", - "Polnisch": "Polish", - "Deaktivieren": "Disable", - "Aktivieren": "Enable", - "Leeren" : "Clear", - "Schließen": "Close", - "Änderungen verwerfen" : "Undo Changes", - "Blöcke speichern" : "Save Blocks", - "Beenden" : "Stop", - "Speichern" : "Save", - "Speichern_und_Neu_Laden" : "Save and Reload", - "Löschen" : "Delete", - "Konvertieren": "Convert" - }, - - "_menu": { - "Systeminfo": "Systeminfo", - "Dienste": "Services", - "Items": "Items", - "Logiken": "Logics", - "Blockly-Logiken-Editor": "Blockly Logics Editor", - "Scheduler": "Scheduler", - "Plugins": "Plugins", - "Threads": "Threads", - "Visu": "Visu", - "Disclosure": "Disclosure", - "CONF-YAML Konverter": "CONF-YAML Converter" - } -} diff --git a/backend/_pv_1_3_5/locale/fr.json b/backend/_pv_1_3_5/locale/fr.json deleted file mode 100755 index a4a6acdff..000000000 --- a/backend/_pv_1_3_5/locale/fr.json +++ /dev/null @@ -1,221 +0,0 @@ -{ - "Scheduler": "Planificateur", - "Logik": "Logique", - "Systemlogiken": "Logiques système", - "Nutzerlogiken": "Logiques utilisateur", - "Neue Logiken (nicht geladen)": "Nouvelles logiques (non encore chargées)", - "nächste Ausführung": "Prochaine exécution", - "Cycle": "Cycle", - "Crontab": "Crontab", - "Crontab(s)": "Crontab(s)", - "Dateiname": "Nom du fichier", - "Aktionen": "Actions", - "Items": "Objets", - "Item": "Objet", - "gesamt": "total", - "Suchen": "Chercher", - "Suche zurücksetzen": "Réinitialiser", - "Alle aufklappen": "Montrer tout", - "Alle zuklappen": "Cacher tout", - "Itempfad suchen...": "Chercher chemin...", - "Item im Baum auswählen um Details einzusehen!": "Choisir un objet dans l'arborescence pour afficher les détails!", - "Item-Informationen": "Informations sur l'objet", - "Attribut": "Attribut", - "Wert": "Valeur", - "Pfad": "Chemin", - "Name": "Nom", - "Typ": "Type", - - "Änderungsinformationen": "Informations sur les modifications", - "Letztes Update": "Dernière mise à jour", - "Letzte Änderung": "Dernière modification", - "Geändert durch": "Modifié par", - "age": "Âge", - "aktueller": "actuel", - "vorheriger": "précédent", - "vorheriger Wert": "Valeur précédente", - "previous change": "Modification précédente", - "previous age": "Âge précédent", - - "Evaluation und Trigger": "Configuration de l'initialisation, de l'évaluation et des déclencheurs", - "Plugin spezifische Attribute": "Attributs spécifiques à l'extension", - "Plugin Metadaten": "Métadonnées de l'extension", - "Verbundene Logiken": "Logiques connexes", - "Verbundene Trigger": "Déclencheurs connexes", - "Willkommen im Backend von": "Bienvenue au Backend de", - "Eigenschaft": "Propriété", - "IP": "Adresse IP", - "Betriebssystem": "Système d'exploitation", - "Architektur": "Architecture", - "Benutzer": "Utilisateur", - "Freier Speicher": "Mémoire libre", - "Datum": "Date", - "Zeit": "Heure", - "Tag": "jour", - "Tage": "jours", - "Stunde": "heure", - "Stunden": "heures", - "Minute": "minute", - "Minuten": "minutes", - "Sekunden": "secondes", - "Betriebszeit": "Temps en service", - "Python Version": "Version Python", - "in": "dans", - "installierte Version": "Version installée", - "Neuste Version": "Dernière version", - "Keine Antwort von PyPI": "Pas de réponse de PyPI", - "PyPI nicht erreichbar": "PyPI non accessible", - "PyPI Prüfung deaktiviert": "Vérification PyPI désactivée", - "Dienst": "Service", - "Status": "Etat", - "Aktion": "Action", - "Root-Passwort": "Mot de passe 'root'", - "Neu starten": "Redémarrer le système", - "Dienst für die KNX Unterstützung": "Service pour le support du KNX", - "Nicht aktiv": "Inactif", - "Sprache des Backends": "Langue du backend", - "Logfile speichern": "Sauvegarder fichier journal", - "Logfile ansehen": "Afficher journal", - "Logger ansehen": "Afficher journalisateurs", - "Datenbank-Dump": "Dump de la base de données", - "Übersetzung neu laden": "Recharger traduction", - "Auf Deutsch wechseln": "Basculer vers l'allemand", - "Auf Englisch wechseln": "Basculer vers l'anglais", - "Auf Polnisch wechseln": "Basculer vers le polonais", - "Nr.": "N°", - "Type": "Type", - "Plugin": "Extension", - "Classname": "Nom de la classe", - "Instanz": "Instance", - "Version": "Version", - "Mehrere Instanzen möglich": "Supporte plusieurs instances", - "Ja": "Oui", - "Nein": "Non", - "Thread": "Tâche", - "Thread-Id": "Id de tâche", - "Aktiv": "Active", - "Visu Client": "Client Visu", - "Port": "Port", - "Client Software": "Logiciel client", - "Browser": "Navigateur", - "No active clients": "Pas de clients actifs", - "Die eingegebenen Daten sind kein numerischer Wert": "Les valeurs entrées ne sont pas numériques", - "Filter": "Filtre", - "Logfile": "Fichier log", - "Dateien ohne zugehöriges Item im /var/cache Verzeichnis": "Fichiers dans le répertoire /var/cache sans objet associé", - "Letzte Modifikation": "Dernière modification", - "Erstellungsdatum": "Date de création", - "no data available": "pas de données disponibles", - "logger name": "Nom du journalisateur", - "disabled": "Désactivé", - "level": "Niveau", - "filters": "Filtres", - "handlers": "Gestionnaire", - "logfiles": "Fichier(s) journal", - "Logging": "Journalisation", - "Passwort anzeigen": "Afficher mot de passe", - "SmartHomeNG Version": "Version de SmartHomeNG", - "Watch_Items": "Objets surveillés", - "Watch_Item(s)": "Objet(s) surveillé(s)", - "Anforderungen": "Version demandée", - "Übersicht": "Aperçu", - "Eingabe im .CONF Format": "Entrée en format .CONF", - "Ergebnis im .YAML Format": "Résultat en format .YAML", - "Wartung": "Maintenance", - "Tester": "Testeur", - "Beschreibung": "Description", - "Documentation": "Documentation", - "Support": "Support", - "Drücken Sie F11 für den Vollbildmodus, wenn der Cursor im Editorfenster ist. Mit F11 oder ESC verlassen Sie den Vollbildmodus wieder.": "Appuyez F11 si le curseur est dans la fenêtre de l'éditeur pour passer en mode plein-écran. Appuyez F11 ou ESC pour sortir du mode plein-écran.", - "Zeilenumbruch" : "Coupure de ligne", - "Strg + Space: Autovervollständigen von Python Befehlen. Strg + i: Autovervollständigen von Item-Pfaden.": "Appuyez ctrl-espace pour activer le complètement automatique des commandes Python. Appuyez ctrl-i pour activer le complètement automatique des chemins des objets.", - "Hilfe": "Aide", - "help_search_1": "Ctrl-F / Cmd-F: Démarrer la recherche", - "help_search_2": "Ctrl-G / Cmd-G: Prochain résultat", - "help_search_3": "Shift-Ctrl-G / Shift-Cmd-G: Résultat précédent", - "help_search_4": "Shift-Ctrl-F / Cmd-Option-F: Remplacer", - "help_search_5": "Shift-Ctrl-R / Shift-Cmd-Option-F: Remplacer tout", - "help_search_6": "Alt-F: Recherche persistente (dialogue ne se ferme pas, pour prochain résultat, Shift-Entrée pour résultat précédent)", - "help_search_7": "Alt-G: Sauter vers ligne", - "Suche": "Chercher", - "Hilfslinien": "Lignes de séparation", - "PyPI Check": "Vérification PyPI", - "Systemeigenschaften": "Propriétés du système", - "Sie verlieren ggf. Ihre letzten, nicht gespeicherten Eingaben!": "Si vous ne sauvegardez pas vous perdez toutes modifications!", - - "_items": { - "path": "Chemin", - "name": "Nom", - "type": "Type (type)", - "value": "Valeur (value)", - "cache": "cache", - "enforce_updates": "enforce_updates", - "eval": "eval", - "eval_trigger": "eval_trigger", - "cycle": "cycle", - "crontab": "crontab", - "autotimer": "autotimer", - "threshold": "threshold" - }, - - "_threads": { - "True": "Oui", - "False": "Non" - }, - - "_disclosure": { - "Lizenz": "Licence", - "Link": "Lien", - "Name": "Nom", - "disclosure_title": "Déclaration des composantes Open Source utilisées dans le serveur Backend de SmartHomeNG", - "Verwendete Open Source Software Komponenten": "Composantes Open Source utilisées", - "Icons/Bilder": "Icônes/Images", - "Alle Icons und Bilder kommen von": "Toutes les images et icônes parviennent de" - }, - - "_button": { - "Auslösen": "Déclencher", - "Neu Laden": "Recharger", - "smarthomeNG starten": "démarrer SmartHomeNG", - "knxd service starten": "démarrer service knxd", - "knxd socket starten": "démarrer socket knxd", - "smarthomeNG beenden": "arrêter SmartHomeNG", - "knxd service beenden": "arrêter service knxd", - "knxd socket beenden": "arrêter socket knxd", - "Filter anwenden": "Appliquer le filtre", - "Cacheprüfung": "Test du cache", - "Passwort-Hash erzeugen": "Mot de passe créer hachage", - "Englisch": "Anglais", - "Deutsch": "Allemand", - "Französisch": "Français", - "Polnisch": "Polonais", - "Deaktivieren": "Désactiver", - "Aktivieren": "Activer", - "Hinzufügen": "Ajouter", - "Leeren" : "Vider", - "Schließen": "Fermer", - "Änderungen verwerfen" : "Annuler modifications", - "Blöcke speichern" : "Enregistrer les blocs", - "Beenden" : "Terminer", - "Speichern" : "Sauvegarder", - "Speichern_und_Neu_Laden" : "Sauvegarder et recharger", - "Speichern_Neu_Laden_und_Triggern": "Sauvegarder, recharger et déclencher", - "Löschen" : "Supprimer", - "Konvertieren": "Convertir", - "Neue Blockly Logik": "Nouvelle logique 'Blockly'" - }, - - "_menu": { - "Systeminfo": "Info système", - "Dienste": "Services", - "Items": "Objets", - "Logiken": "Logiques", - "Blockly-Logiken-Editor": "Blockly - Editeur de Logiques", - "Scheduler": "Planificateur", - "Plugins": "Extensions", - "Threads": "Tâches", - "Visu": "Visu", - "Disclosure": "Déclaration", - "CONF-YAML Konverter": "Convertisseur .conf vers .yaml" - } -} diff --git a/backend/_pv_1_3_5/locale/pl.json b/backend/_pv_1_3_5/locale/pl.json deleted file mode 100755 index 0a23e96e7..000000000 --- a/backend/_pv_1_3_5/locale/pl.json +++ /dev/null @@ -1,191 +0,0 @@ -{ - "Scheduler": "Planista", - "Logik": "Logika", - "Systemlogiken": "Logika systemowa", - "nächste Ausführung": "Następne wykonanie", - "Cycle": "Cykl", - "Crontab": "Harmonogram", - "Dateiname": "Nazwa pliku", - "Aktionen": "Akcje", - "Items": "Itemy", - "Item": "Item", - "gesamt": "w sumie", - "Suchen": "Szukaj", - "Suche zurücksetzen": "Reset wyszukiwania", - "Alle aufklappen": "Rozwiń wszystko", - "Alle zuklappen": "Zwiń wszystko", - "Itempfad suchen...": "Szukaj Itemów...", - "Item im Baum auswählen um Details einzusehen!": "Wybierz Item aby zobaczyć szczegóły!", - "Item-Informationen": "Informacje o Itemie", - "Attribut": "atrybut", - "Wert": "wartość", - "Pfad": "ścieżka", - "Name": "nazwa", - "Typ": "typ", - - "Änderungsinformationen": "Inormacje o zmianach", - "Letztes Update": "ostatnia aktualizacja", - "Letzte Änderung": "ostatnia zmiana", - "Geändert durch": "zmieniono przez", - "age": "czas aktualnej wartości", - "vorheriger Wert": "poprzednia wartość", - "previous change": "poprzednia zmiana", - "previous age": "czas poprzedniej wartości", - - "Evaluation und Trigger": "Inicjalizacja, ewaluacja i wyzwalacze", - "Plugin spezifische Attribute": "Konfiguracja pluginów", - "Verbundene Logiken": "Powiązana Logika", - "Verbundene Trigger": "Powiązane wyzwalacze", - "Willkommen im Backend von": "Witaj w backendzie", - "Eigenschaft": "Atrybut", - "IP": "Adres IP", - "Betriebssystem": "System operacyjny", - "Architektur": "Architektura", - "Benutzer": "Użytkownik", - "Freier Speicher": "Wolne miejsce", - "Datum": "Data", - "Zeit": "Czas", - "Tag": "dzień", - "Tage": "dni", - "Stunde": "godzina", - "Stunden": "godzin", - "Minute": "minuta", - "Minuten": "minut", - "Sekunden": "sekund", - "Betriebszeit": "Czas pracy", - "Python Version": "Wersja Pythona", - "installierte Version": "Zainstalowana wersja", - "Neuste Version": "Najnowsza wersja", - "Keine Antwort von PyPI": "Brak odpowiedzi z PyPI", - "PyPI nicht erreichbar": "PyPI niedostępne", - "PyPI Prüfung deaktiviert": "sprawdzanie PyPI wyłączone", - "Dienst": "Usługa", - "Status": "Status", - "Aktion": "Akcja", - "Root-Passwort": "Hasło roota", - "Neu starten": "Restart systemu", - "Dienst für die KNX Unterstützung": "Usługa KNX", - "Nicht aktiv": "Nieaktywne", - "Sprache des Backends": "Język", - "Logfile speichern": "Zapisz log", - "Logfile ansehen": "Przeglądaj log", - "Logger ansehen": "Przeglądaj loggery", - "Datenbank-Dump": "Pobierz bazę danych", - "Übersetzung neu laden": "Przeładuj tłumaczenie", - "Auf Deutsch wechseln": "Przełącz na nimiecki", - "Auf Englisch wechseln": "Przełącz na angielski", - "Auf Französisch wechseln": "Przełącz na francuski", - "Auf Polnisch wechseln": "Przełącz na polski", - "Nr.": "Nr", - "Type": "Typ", - "Plugin": "Plugin", - "Classname": "Nazwa klasy", - "Instanz": "Instancja", - "Version": "Wersja", - "Mehrere Instanzen möglich": "Możliwe wiele instancji", - "Ja": "Tak", - "Nein": "Nie", - "Thread": "Wątki", - "Thread-Id": "Id Wątku", - "Aktiv": "Aktywny", - "Visu Client": "Klient Visu", - "Port": "Port", - "Client Software": "Oprogramowanie klienta", - "Browser": "Przeglądarka", - "No active clients": "Brak aktywnych klientów", - "Die eingegebenen Daten sind kein numerischer Wert": "Wprowadzona wartość nie jest liczbą", - "Filter": "Filtr", - "Logfile": "Log", - "Dateien ohne zugehöriges Item im /var/cache Verzeichnis": "Pliki w var/cache bez odpowiadającego im Itema", - "Letzte Modifikation": "Ostatnia modyfikacja", - "Erstellungsdatum": "Utworzono", - "no data available": "brak danych", - "logger lame": "Nazwa Loggera", - "disabled": "Wyłączony", - "level": "Poziom", - "filters": "Filtry", - "handlers": "Handlery", - "logfiles": "Log", - "Logging": "Logowanie", - "Passwort anzeigen": "pokaż", - "SmartHomeNG Version": "Wersja SmartHomeNG", - "Watch_Items": "Obserwowane Itemy", - "Anforderungen": "Wymagania", - "Übersicht": "Badanie", - "Eingabe im .CONF Format": "Eingabe im .CONF Format", - "Ergebnis im .YAML Format": "Ergebnis im .YAML Format" - - "_items": { - "path": "ścieżka", - "name": "nazwa", - "type": "typ", - "value": "wartość", - "cache": "pamięć podręczna", - "enforce_updates": "wymuszone aktualizacje", - "eval": "ewaluacja", - "eval_trigger": "wyzwalacze ewaluacji", - "cycle": "cykl", - "crontab": "harmonogram", - "autotimer": "autotimer", - "threshold": "próg" - }, - - "_threads": { - "True": "Tak", - "False": "Nie" - }, - - - "_disclosure": { - "Lizenz": "Licencja", - "Link": "Link", - "Name": "Nazwa", - "disclosure_title": "Deklaracja oprogramowania Open Source wykorzystanego w SmartHomeNG przez plugin 'backend'", - "Verwendete Open Source Software Komponenten": "Wykaz użytego oprogramowania Open Source", - "Icons/Bilder": "Ikony/Obrazy", - "Alle Icons und Bilder kommen von": "Wszystkie ikony i obrazy pochodzą z" - }, - - "_button": { - "Auslösen": "Uruchom", - "Neu Laden": "Przeładuj", - "smarthomeNG starten": "Start SmartHomeNG", - "knxd service starten": "Start usługi knxd", - "knxd socket starten": "Start socketa knxd", - "smarthomeNG beenden": "Stop SmartHomeNG", - "knxd service beenden": "Stop usługi knxd", - "knxd socket beenden": "Stop socketa knxd", - "Filter anwenden": "Zastosuj filtr", - "Cacheprüfung": "Sprawdź pamięć podręczną", - "Passwort-Hash erzeugen": "Utwórz zahashowane hasło", - "Englisch": "English", - "Deutsch": "Deutsch", - "Französisch": "French", - "Polnisch": "Polski", - "Deaktivieren": "Wyłącz", - "Aktivieren": "Włącz", - "Leeren" : "Wyczyść", - "Schließen": "Zamknij", - "Änderungen verwerfen" : "Cofnij Zmiany", - "Blöcke speichern" : "Zapisz Bloki", - "Beenden" : "Stop", - "Speichern" : "Zapisz", - "Speichern_und_Neu_Laden" : "Zapisz i przeładuj", - "Löschen" : "Skasuj" - "Konvertieren": "Konvertieren" - }, - - "_menu": { - "Systeminfo": "System", - "Dienste": "Usługi", - "Items": "Itemy", - "Logiken": "Logika", - "Blockly-Logiken-Editor": "Edytor logiki Blockly", - "Scheduler": "Planista", - "Plugins": "Pluginy", - "Threads": "Wątki", - "Visu": "Visu", - "Disclosure": "Deklaracja", - "CONF-YAML Konverter": "CONF-YAML Konverter" - } -} diff --git a/backend/_pv_1_3_5/plugin.yaml b/backend/_pv_1_3_5/plugin.yaml deleted file mode 100755 index 8164922bb..000000000 --- a/backend/_pv_1_3_5/plugin.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Metadata for the Smart-Plugin -plugin: - # Global plugin attributes - type: system # plugin type (gateway, interface, protocol, system, web) - subtype: core # plugin subtype (if applicable) - description: # Alternative: description in multiple languages - de: 'Web Interface zur Anzeige von Informationen zum System und SmartHomeNG Backend-Daten' - en: 'webinterface for displaying system information and SmartHomeNG backend data' - maintainer: psilo909, msinn, bmxp - tester: Sandman60 -# keywords: iot xyz -# documentation: https://github.com/smarthomeNG/plugins/blob/develop/mqtt/README.md # url of documentation (wiki) page - - version: 1.3.5 # Plugin version - sh_minversion: 1.3 # minimum shNG version to use this plugin - sh_maxversion: 1.3a # maximum shNG version to use this plugin (leave empty if latest) - multi_instance: False # plugin supports multi instance - -parameters: - # Definition of parameters to be configured in etc/plugin.yaml - -item_attributes: - # Definition of item attributes defined by this plugin - diff --git a/backend/_pv_1_3_5/requirements.txt b/backend/_pv_1_3_5/requirements.txt deleted file mode 100755 index 5940e8d8e..000000000 --- a/backend/_pv_1_3_5/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -cherrypy>=8.1.2 -jinja2>=2.9 -python-dateutil>=2.5.3 \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/CONTRIBUTING.md b/backend/_pv_1_3_5/static/blockly/CONTRIBUTING.md deleted file mode 100755 index 8cfd55151..000000000 --- a/backend/_pv_1_3_5/static/blockly/CONTRIBUTING.md +++ /dev/null @@ -1,5 +0,0 @@ -# Contributing to Blockly - -Please make pull requests against develop, not master. If your patch needs to go into master immediately, include a note in your PR. - -For more information, head over to the [Blockly Developers site](https://developers.google.com/blockly/guides/modify/contributing). diff --git a/backend/_pv_1_3_5/static/blockly/LICENSE b/backend/_pv_1_3_5/static/blockly/LICENSE deleted file mode 100755 index 6a1992987..000000000 --- a/backend/_pv_1_3_5/static/blockly/LICENSE +++ /dev/null @@ -1,177 +0,0 @@ - - Apache License - Version 2.0, January 2011 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS diff --git a/backend/_pv_1_3_5/static/blockly/README.md b/backend/_pv_1_3_5/static/blockly/README.md deleted file mode 100755 index fd626a49a..000000000 --- a/backend/_pv_1_3_5/static/blockly/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# Blockly - -Google's Blockly is a web-based, visual programming editor. Users can drag -blocks together to build programs. All code is free and open source. - -**The project page is https://developers.google.com/blockly/** - -![](https://developers.google.com/blockly/images/sample.png) diff --git a/backend/_pv_1_3_5/static/blockly/accessible/README b/backend/_pv_1_3_5/static/blockly/accessible/README deleted file mode 100755 index 37ea67879..000000000 --- a/backend/_pv_1_3_5/static/blockly/accessible/README +++ /dev/null @@ -1,54 +0,0 @@ -Accessible Blockly -================== - -Google's Blockly is a web-based, visual programming editor that is accessible -to blind users. - -The code in this directory renders a version of the Blockly toolbox and -workspace that is fully keyboard-navigable, and compatible with most screen -readers. - -In the future, Accessible Blockly may be modified to suit accessibility needs -other than visual impairments. Note that deaf users are expected to continue -using Blockly over Accessible Blockly. - - -Using Accessible Blockly in Your Web App ----------------------------------------- -The demo at blockly/demos/accessible covers the absolute minimum required to -import Accessible Blockly into your web app. You will need to import the files -in the same order as in the demo: utils.service.js will need to be the first -Angular file imported. - -When the DOMContentLoaded event fires, call ng.platform.browser.bootstrap() on -the main component to be loaded. This will usually be blocklyApp.AppView, but -if you have another component that wraps it, use that one instead. - - -Customizing the Toolbar and Audio ---------------------------------- -The Accessible Blockly workspace comes with a customizable toolbar. - -To customize the toolbar, you will need to declare an ACCESSIBLE_GLOBALS object -in the global scope that looks like this: - - var ACCESSIBLE_GLOBALS = { - toolbarButtonConfig: [], - mediaPathPrefix: null - }; - -The value corresponding to 'toolbarButtonConfig' can be modified by adding -objects representing buttons on the toolbar. Each of these objects should have -two keys: - - - 'text' (the text to display on the button) - - 'action' (the function that gets run when the button is clicked) - -In addition, if you want audio to be played, set mediaPathPrefix to the -location of the accessible/media folder. - - -Limitations ------------ -- We do not support having multiple Accessible Blockly apps in a single webpage. -- Accessible Blockly does not support the use of shadow blocks. diff --git a/backend/_pv_1_3_5/static/blockly/accessible/app.component.js b/backend/_pv_1_3_5/static/blockly/accessible/app.component.js deleted file mode 100755 index e1c4329d3..000000000 --- a/backend/_pv_1_3_5/static/blockly/accessible/app.component.js +++ /dev/null @@ -1,77 +0,0 @@ -/** - * AccessibleBlockly - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the 'License'); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an 'AS IS' BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Angular2 Component that details how the AccessibleBlockly - * app is rendered on the page. - * @author madeeha@google.com (Madeeha Ghori) - */ - -blocklyApp.workspace = new Blockly.Workspace(); - -blocklyApp.AppView = ng.core - .Component({ - selector: 'blockly-app', - template: ` - - - - - - -
- {{'TOOLBOX_LOAD'|translate}} - - {{'WORKSPACE_LOAD'|translate}} -
- - - - - - - - - - - - - - - `, - directives: [blocklyApp.ToolboxComponent, blocklyApp.WorkspaceComponent], - pipes: [blocklyApp.TranslatePipe], - // All services are declared here, so that all components in the - // application use the same instance of the service. - // https://www.sitepoint.com/angular-2-components-providers-classes-factories-values/ - providers: [ - blocklyApp.ClipboardService, blocklyApp.NotificationsService, - blocklyApp.TreeService, blocklyApp.UtilsService, - blocklyApp.AudioService] - }) - .Class({ - constructor: [blocklyApp.NotificationsService, function(_notificationsService) { - this.notificationsService = _notificationsService; - }], - getStatusMessage: function() { - return this.notificationsService.getStatusMessage(); - } - }); diff --git a/backend/_pv_1_3_5/static/blockly/accessible/audio.service.js b/backend/_pv_1_3_5/static/blockly/accessible/audio.service.js deleted file mode 100755 index c358c083b..000000000 --- a/backend/_pv_1_3_5/static/blockly/accessible/audio.service.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * AccessibleBlockly - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the 'License'); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an 'AS IS' BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Angular2 Service that plays audio files. - * @author sll@google.com (Sean Lip) - */ - -blocklyApp.AudioService = ng.core - .Class({ - constructor: [function() { - // We do not play any audio unless a media path prefix is specified. - this.canPlayAudio = false; - if (ACCESSIBLE_GLOBALS.hasOwnProperty('mediaPathPrefix')) { - this.canPlayAudio = true; - var mediaPathPrefix = ACCESSIBLE_GLOBALS['mediaPathPrefix']; - this.AUDIO_PATHS_ = { - 'connect': mediaPathPrefix + 'click.mp3', - 'delete': mediaPathPrefix + 'delete.mp3' - }; - } - - // TODO(sll): Add ogg and mp3 fallbacks. - this.cachedAudioFiles_ = {}; - }], - play_: function(audioId) { - if (this.canPlayAudio) { - if (!this.cachedAudioFiles_.hasOwnProperty(audioId)) { - this.cachedAudioFiles_[audioId] = new Audio( - this.AUDIO_PATHS_[audioId]); - } - this.cachedAudioFiles_[audioId].play(); - } - }, - playConnectSound: function() { - this.play_('connect'); - }, - playDeleteSound: function() { - this.play_('delete'); - } - }); diff --git a/backend/_pv_1_3_5/static/blockly/accessible/clipboard.service.js b/backend/_pv_1_3_5/static/blockly/accessible/clipboard.service.js deleted file mode 100755 index 05b0afe63..000000000 --- a/backend/_pv_1_3_5/static/blockly/accessible/clipboard.service.js +++ /dev/null @@ -1,172 +0,0 @@ -/** - * AccessibleBlockly - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the 'License'); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an 'AS IS' BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Angular2 Service that handles the clipboard and marked spots. - * @author madeeha@google.com (Madeeha Ghori) - */ - -blocklyApp.ClipboardService = ng.core - .Class({ - constructor: [ - blocklyApp.NotificationsService, blocklyApp.UtilsService, - blocklyApp.AudioService, - function(_notificationsService, _utilsService, _audioService) { - this.clipboardBlockXml_ = null; - this.clipboardBlockPreviousConnection_ = null; - this.clipboardBlockNextConnection_ = null; - this.clipboardBlockOutputConnection_ = null; - this.markedConnection_ = null; - this.notificationsService = _notificationsService; - this.utilsService = _utilsService; - this.audioService = _audioService; - }], - areConnectionsCompatible_: function(blockConnection, connection) { - // Check that both connections exist, that it's the right kind of - // connection, and that the types match. - return Boolean( - connection && blockConnection && - Blockly.OPPOSITE_TYPE[blockConnection.type] == connection.type && - connection.checkType_(blockConnection)); - }, - isCompatibleWithClipboard: function(connection) { - var previousConnection = this.clipboardBlockPreviousConnection_; - var nextConnection = this.clipboardBlockNextConnection_; - var outputConnection = this.clipboardBlockOutputConnection_; - return Boolean( - this.areConnectionsCompatible_(connection, previousConnection) || - this.areConnectionsCompatible_(connection, nextConnection) || - this.areConnectionsCompatible_(connection, outputConnection)); - }, - getMarkedConnectionBlock: function() { - if (!this.markedConnection_) { - return null; - } else { - return this.markedConnection_.getSourceBlock(); - } - }, - isMovableToMarkedConnection: function(block) { - // It should not be possible to move any ancestor of the block containing - // the marked spot to the marked spot. - if (!this.markedConnection_) { - return false; - } - - var markedSpotAncestorBlock = this.getMarkedConnectionBlock(); - while (markedSpotAncestorBlock) { - if (markedSpotAncestorBlock.id == block.id) { - return false; - } - markedSpotAncestorBlock = markedSpotAncestorBlock.getParent(); - } - - return this.canBeCopiedToMarkedConnection(block); - }, - canBeCopiedToMarkedConnection: function(block) { - if (!this.markedConnection_ || - !this.markedConnection_.getSourceBlock().workspace) { - return false; - } - - var potentialConnections = [ - block.outputConnection, - block.previousConnection, - block.nextConnection - ]; - - var that = this; - return potentialConnections.some(function(connection) { - return that.areConnectionsCompatible_( - connection, that.markedConnection_); - }); - }, - markConnection: function(connection) { - this.markedConnection_ = connection; - this.notificationsService.setStatusMessage(Blockly.Msg.MARKED_SPOT_MSG); - }, - cut: function(block) { - this.copy(block); - block.dispose(true); - }, - copy: function(block) { - this.clipboardBlockXml_ = Blockly.Xml.blockToDom(block); - this.clipboardBlockPreviousConnection_ = block.previousConnection; - this.clipboardBlockNextConnection_ = block.nextConnection; - this.clipboardBlockOutputConnection_ = block.outputConnection; - }, - pasteFromClipboard: function(inputConnection) { - var connection = inputConnection; - // If the connection is a 'previousConnection' and that connection is - // already joined to something, use the 'nextConnection' of the - // previous block instead in order to do an insertion. - if (inputConnection.type == Blockly.PREVIOUS_STATEMENT && - inputConnection.isConnected()) { - connection = inputConnection.targetConnection; - } - - var reconstitutedBlock = Blockly.Xml.domToBlock(blocklyApp.workspace, - this.clipboardBlockXml_); - switch (connection.type) { - case Blockly.NEXT_STATEMENT: - connection.connect(reconstitutedBlock.previousConnection); - break; - case Blockly.PREVIOUS_STATEMENT: - connection.connect(reconstitutedBlock.nextConnection); - break; - default: - connection.connect(reconstitutedBlock.outputConnection); - } - this.audioService.playConnectSound(); - this.notificationsService.setStatusMessage( - this.utilsService.getBlockDescription(reconstitutedBlock) + ' ' + - Blockly.Msg.PASTED_BLOCK_FROM_CLIPBOARD_MSG); - return reconstitutedBlock.id; - }, - pasteToMarkedConnection: function(block) { - var xml = Blockly.Xml.blockToDom(block); - var reconstitutedBlock = Blockly.Xml.domToBlock( - blocklyApp.workspace, xml); - - var potentialConnections = [ - reconstitutedBlock.outputConnection, - reconstitutedBlock.previousConnection, - reconstitutedBlock.nextConnection - ]; - - var connectionSuccessful = false; - for (var i = 0; i < potentialConnections.length; i++) { - if (this.areConnectionsCompatible_( - this.markedConnection_, potentialConnections[i])) { - this.markedConnection_.connect(potentialConnections[i]); - this.audioService.playConnectSound(); - connectionSuccessful = true; - break; - } - } - - if (!connectionSuccessful) { - console.error('ERROR: Could not connect block to marked spot.'); - return; - } - - this.markedConnection_ = null; - - return reconstitutedBlock.id; - } - }); diff --git a/backend/_pv_1_3_5/static/blockly/accessible/field.component.js b/backend/_pv_1_3_5/static/blockly/accessible/field.component.js deleted file mode 100755 index e10323db7..000000000 --- a/backend/_pv_1_3_5/static/blockly/accessible/field.component.js +++ /dev/null @@ -1,138 +0,0 @@ -/** - * AccessibleBlockly - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the 'License'); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an 'AS IS' BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Angular2 Component that details how a Blockly.Field is - * rendered in the toolbox in AccessibleBlockly. Also handles any interactions - * with the field. - * @author madeeha@google.com (Madeeha Ghori) - */ - -blocklyApp.FieldComponent = ng.core - .Component({ - selector: 'blockly-field', - template: ` - - - - -
- -
    -
  1. - -
  2. -
-
- -
- // Checkboxes are not currently supported. -
- - - `, - inputs: ['field', 'index', 'parentId', 'disabled', 'mainFieldId'], - pipes: [blocklyApp.TranslatePipe] - }) - .Class({ - constructor: [blocklyApp.UtilsService, function(_utilsService) { - this.optionText = { - keys: [] - }; - this.utilsService = _utilsService; - }], - ngOnInit: function() { - var elementsNeedingIds = this.generateElementNames(this.field); - // Warning: this assumes that the elements returned by - // this.generateElementNames() are unique. - this.idMap = this.utilsService.generateIds(elementsNeedingIds); - }, - generateAriaLabelledByAttr: function(mainLabel, secondLabel) { - return mainLabel + ' ' + secondLabel; - }, - generateElementNames: function() { - var elementNames = []; - if (this.isDropdown()) { - var keys = this.getOptions(); - for (var i = 0; i < keys.length; i++){ - elementNames.push(keys[i], keys[i] + 'Button'); - } - } - return elementNames; - }, - isNumberInput: function() { - return this.field instanceof Blockly.FieldNumber; - }, - isTextInput: function() { - return this.field instanceof Blockly.FieldTextInput && - !(this.field instanceof Blockly.FieldNumber); - }, - isDropdown: function() { - return this.field instanceof Blockly.FieldDropdown; - }, - isCheckbox: function() { - return this.field instanceof Blockly.FieldCheckbox; - }, - isTextField: function() { - return !(this.field instanceof Blockly.FieldTextInput) && - !(this.field instanceof Blockly.FieldDropdown) && - !(this.field instanceof Blockly.FieldCheckbox); - }, - hasVisibleText: function() { - var text = this.field.getText().trim(); - return !!text; - }, - getOptions: function() { - if (this.optionText.keys.length) { - return this.optionText.keys; - } - var options = this.field.getOptions_(); - for (var i = 0; i < options.length; i++) { - var tuple = options[i]; - this.optionText[tuple[1]] = tuple[0]; - this.optionText.keys.push(tuple[1]); - } - return this.optionText.keys; - }, - handleDropdownChange: function(field, text) { - if (text == 'NO_ACTION') { - return; - } - if (this.field instanceof Blockly.FieldVariable) { - Blockly.FieldVariable.dropdownChange.call(this.field, text); - } else { - this.field.setValue(text); - } - } - }); diff --git a/backend/_pv_1_3_5/static/blockly/accessible/libs/Rx.umd.min.js b/backend/_pv_1_3_5/static/blockly/accessible/libs/Rx.umd.min.js deleted file mode 100755 index 818717409..000000000 --- a/backend/_pv_1_3_5/static/blockly/accessible/libs/Rx.umd.min.js +++ /dev/null @@ -1,321 +0,0 @@ -(function(t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"===typeof define&&define.amd?define([],t):("undefined"!==typeof window?window:"undefined"!==typeof global?global:"undefined"!==typeof self?self:this).Rx=t()})(function(){return function a(b,e,h){function k(f,d){if(!e[f]){if(!b[f]){var c="function"==typeof require&&require;if(!d&&c)return c(f,!0);if(m)return m(f,!0);c=Error("Cannot find module '"+f+"'");throw c.code="MODULE_NOT_FOUND",c;}c=e[f]={exports:{}}; -b[f][0].call(c.exports,function(a){var c=b[f][1][a];return k(c?c:a)},c,c.exports,a,b,e,h)}return e[f].exports}for(var m="function"==typeof require&&require,l=0;lf?-1:1;n=f*Math.floor(Math.abs(n));n=0>=n?0:n>g?g:n}this.arr=c;this.idx=d;this.len=n}a.prototype[m.SymbolShim.iterator]=function(){return this};a.prototype.next=function(){return this.idxc)this.delayTime=0;g&&"function"===typeof g.schedule||(this.scheduler=k.asap)}h(f,a);f.create=function(a,c,g){void 0===c&&(c=0);void 0===g&&(g=k.asap);return new f(a,c,g)};f.dispatch=function(a){return a.source.subscribe(a.subscriber)};f.prototype._subscribe=function(a){a.add(this.scheduler.schedule(f.dispatch,this.delayTime,{source:this.source, -subscriber:a}))};return f}(b.Observable);e.SubscribeOnObservable=a},{"../Observable":3,"../scheduler/asap":215,"../util/isNumeric":233}],107:[function(a,b,e){function h(a){var n=a.source;a=a.subscriber;var b=n.callbackFunc,l=n.args,e=n.scheduler,h=n.subject;if(!h){var h=n.subject=new c.AsyncSubject,r=function u(){for(var a=[],c=0;c=a.count?f.complete():(f.next(g[d]),f.isUnsubscribed||(a.index=d+1,this.schedule(a)))}; -d.prototype._subscribe=function(a){var g=this.array,n=g.length,f=this.scheduler;if(f)a.add(f.schedule(d.dispatch,0,{array:g,index:0,count:n,subscriber:a}));else{for(f=0;fd)this.period=0;c&&"function"===typeof c.schedule||(this.scheduler=m.asap)}h(f,a);f.create=function(a,c){void 0===a&&(a=0);void 0===c&& -(c=m.asap);return new f(a,c)};f.dispatch=function(a){var c=a.subscriber,g=a.period;c.next(a.index);c.isUnsubscribed||(a.index+=1,this.schedule(a,g))};f.prototype._subscribe=function(a){var c=this.period;a.add(this.scheduler.schedule(f.dispatch,c,{index:0,subscriber:a,period:c}))};return f}(b.Observable);e.IntervalObservable=a},{"../Observable":3,"../scheduler/asap":215,"../util/isNumeric":233}],117:[function(a,b,e){var h=this&&this.__extends||function(a,b){function f(){this.constructor=a}for(var d in b)b.hasOwnProperty(d)&& -(a[d]=b[d]);a.prototype=null===b?Object.create(b):(f.prototype=b.prototype,new f)};b=a("../Observable");var k=a("../util/noop");a=function(a){function b(){a.call(this)}h(b,a);b.create=function(){return new b};b.prototype._subscribe=function(a){k.noop()};return b}(b.Observable);e.InfiniteObservable=a},{"../Observable":3,"../util/noop":236}],118:[function(a,b,e){var h=this&&this.__extends||function(a,b){function l(){this.constructor=a}for(var f in b)b.hasOwnProperty(f)&&(a[f]=b[f]);a.prototype=null=== -b?Object.create(b):(l.prototype=b.prototype,new l)};a=function(a){function b(l,f,d){a.call(this);this.start=l;this.end=f;this.scheduler=d}h(b,a);b.create=function(a,f,d){void 0===a&&(a=0);void 0===f&&(f=0);return new b(a,f,d)};b.dispatch=function(a){var b=a.start,d=a.index,c=a.subscriber;d>=a.end?c.complete():(c.next(b),c.isUnsubscribed||(a.index=d+1,a.start=b+1,this.schedule(a)))};b.prototype._subscribe=function(a){var f=0,d=this.start,c=this.end,g=this.scheduler;if(g)a.add(g.schedule(b.dispatch, -0,{index:f,end:c,start:d,subscriber:a}));else{do{if(f++>=c){a.complete();break}a.next(d++);if(a.isUnsubscribed)break}while(1)}};return b}(a("../Observable").Observable);e.RangeObservable=a},{"../Observable":3}],119:[function(a,b,e){var h=this&&this.__extends||function(a,b){function l(){this.constructor=a}for(var f in b)b.hasOwnProperty(f)&&(a[f]=b[f]);a.prototype=null===b?Object.create(b):(l.prototype=b.prototype,new l)};a=function(a){function b(l,f){a.call(this);this.error=l;this.scheduler=f}h(b, -a);b.create=function(a,f){return new b(a,f)};b.dispatch=function(a){a.subscriber.error(a.error)};b.prototype._subscribe=function(a){var f=this.error,d=this.scheduler;d?a.add(d.schedule(b.dispatch,0,{error:f,subscriber:a})):a.error(f)};return b}(a("../Observable").Observable);e.ErrorObservable=a},{"../Observable":3}],120:[function(a,b,e){var h=this&&this.__extends||function(a,c){function g(){this.constructor=a}for(var n in c)c.hasOwnProperty(n)&&(a[n]=c[n]);a.prototype=null===c?Object.create(c):(g.prototype= -c.prototype,new g)},k=a("../util/isNumeric");b=a("../Observable");var m=a("../scheduler/asap"),l=a("../util/isScheduler"),f=a("../util/isDate");a=function(a){function c(c,n,b){void 0===c&&(c=0);a.call(this);this.period=n;this.scheduler=b;this.dueTime=0;k.isNumeric(n)?this._period=1>Number(n)&&1||Number(n):l.isScheduler(n)&&(b=n);l.isScheduler(b)||(b=m.asap);this.scheduler=b;this.dueTime=f.isDate(c)?+c-this.scheduler.now():c}h(c,a);c.create=function(a,d,b){void 0===a&&(a=0);return new c(a,d,b)};c.dispatch= -function(a){var d=a.index,b=a.period,f=a.subscriber;f.next(d);"undefined"===typeof b?f.complete():f.isUnsubscribed||("undefined"===typeof this.delay?this.add(this.scheduler.schedule(c.dispatch,b,{index:d+1,period:b,subscriber:f})):(a.index=d+1,this.schedule(a,b)))};c.prototype._subscribe=function(a){a.add(this.scheduler.schedule(c.dispatch,this.dueTime,{index:0,period:this._period,subscriber:a}))};return c}(b.Observable);e.TimerObservable=a},{"../Observable":3,"../scheduler/asap":215,"../util/isDate":232, -"../util/isNumeric":233,"../util/isScheduler":235}],121:[function(a,b,e){var h=this&&this.__extends||function(a,d){function c(){this.constructor=a}for(var g in d)d.hasOwnProperty(g)&&(a[g]=d[g]);a.prototype=null===d?Object.create(d):(c.prototype=d.prototype,new c)};a=a("../Subscriber");e.buffer=function(a){return this.lift(new k(a))};var k=function(){function a(d){this.closingNotifier=d}a.prototype.call=function(a){return new m(a,this.closingNotifier)};return a}(),m=function(a){function d(c,g){a.call(this, -c);this.buffer=[];this.notifierSubscriber=null;this.notifierSubscriber=new l(this);this.add(g._subscribe(this.notifierSubscriber))}h(d,a);d.prototype._next=function(a){this.buffer.push(a)};d.prototype._error=function(a){this.destination.error(a)};d.prototype._complete=function(){this.destination.complete()};d.prototype.flushBuffer=function(){var a=this.buffer;this.buffer=[];this.destination.next(a);this.isUnsubscribed&&this.notifierSubscriber.unsubscribe()};return d}(a.Subscriber),l=function(a){function d(c){a.call(this, -null);this.parent=c}h(d,a);d.prototype._next=function(a){this.parent.flushBuffer()};d.prototype._error=function(a){this.parent.error(a)};d.prototype._complete=function(){this.parent.complete()};return d}(a.Subscriber)},{"../Subscriber":7}],122:[function(a,b,e){var h=this&&this.__extends||function(a,b){function d(){this.constructor=a}for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);a.prototype=null===b?Object.create(b):(d.prototype=b.prototype,new d)};a=a("../Subscriber");e.bufferCount=function(a,b){void 0=== -b&&(b=null);return this.lift(new k(a,b))};var k=function(){function a(b,d){this.bufferSize=b;this.startBufferEvery=d}a.prototype.call=function(a){return new m(a,this.bufferSize,this.startBufferEvery)};return a}(),m=function(a){function b(d,c,g){a.call(this,d);this.bufferSize=c;this.startBufferEvery=g;this.buffers=[[]];this.count=0}h(b,a);b.prototype._next=function(a){var c=this.count+=1,g=this.destination,n=this.bufferSize,b=this.buffers,f=b.length,l=-1;0===c%(null==this.startBufferEvery?n:this.startBufferEvery)&& -b.push([]);for(c=0;c=d[0].time-b.now();)d.shift().notification.observe(g);0(b||0)?Number.POSITIVE_INFINITY:b;return this.lift(new h.ExpandOperator(a,b,l))}},{"./expand-support":145}],147:[function(a,b,e){var h=this&&this.__extends|| -function(a,c){function b(){this.constructor=a}for(var f in c)c.hasOwnProperty(f)&&(a[f]=c[f]);a.prototype=null===c?Object.create(c):(b.prototype=c.prototype,new b)};b=a("../Subscriber");var k=a("../util/tryCatch"),m=a("../util/errorObject");e.filter=function(a,c){return this.lift(new l(a,c))};var l=function(){function a(c,d){this.select=c;this.thisArg=d}a.prototype.call=function(a){return new f(a,this.select,this.thisArg)};return a}(),f=function(a){function c(c,b,f){a.call(this,c);this.thisArg=f; -this.count=0;this.select=b}h(c,a);c.prototype._next=function(a){var c=k.tryCatch(this.select).call(this.thisArg||this,a,this.count++);c===m.errorObject?this.destination.error(m.errorObject.e):Boolean(c)&&this.destination.next(a)};return c}(b.Subscriber)},{"../Subscriber":7,"../util/errorObject":230,"../util/tryCatch":241}],148:[function(a,b,e){var h=this&&this.__extends||function(a,d){function c(){this.constructor=a}for(var b in d)d.hasOwnProperty(b)&&(a[b]=d[b]);a.prototype=null===d?Object.create(d): -(c.prototype=d.prototype,new c)};b=a("../Subscriber");var k=a("../Subscription");e._finally=function(a){return this.lift(new m(a))};var m=function(){function a(d){this.finallySelector=d}a.prototype.call=function(a){return new l(a,this.finallySelector)};return a}(),l=function(a){function d(c,d){a.call(this,c);this.add(new k.Subscription(d))}h(d,a);return d}(b.Subscriber)},{"../Subscriber":7,"../Subscription":8}],149:[function(a,b,e){var h=this&&this.__extends||function(a,d){function b(){this.constructor= -a}for(var f in d)d.hasOwnProperty(f)&&(a[f]=d[f]);a.prototype=null===d?Object.create(d):(b.prototype=d.prototype,new b)};b=a("../Subscriber");var k=a("../util/tryCatch"),m=a("../util/errorObject"),l=a("../util/EmptyError");e.first=function(a,d,b){return this.lift(new f(a,d,b,this))};var f=function(){function a(c,d,b,f){this.predicate=c;this.resultSelector=d;this.defaultValue=b;this.source=f}a.prototype.call=function(a){return new d(a,this.predicate,this.resultSelector,this.defaultValue,this.source)}; -return a}(),d=function(a){function d(b,g,f,l,e){a.call(this,b);this.predicate=g;this.resultSelector=f;this.defaultValue=l;this.source=e;this.index=0;this.hasCompleted=!1}h(d,a);d.prototype._next=function(a){var c=this.destination,d=this.predicate,b=this.resultSelector,g=this.index++,f=!0;if(d&&(f=k.tryCatch(d)(a,g,this.source),f===m.errorObject)){c.error(m.errorObject.e);return}if(f){if(b&&(a=k.tryCatch(b)(a,g),a===m.errorObject)){c.error(m.errorObject.e);return}c.next(a);c.complete();this.hasCompleted= -!0}};d.prototype._complete=function(){var a=this.destination;this.hasCompleted||"undefined"===typeof this.defaultValue?this.hasCompleted||a.error(new l.EmptyError):(a.next(this.defaultValue),a.complete())};return d}(b.Subscriber)},{"../Subscriber":7,"../util/EmptyError":223,"../util/errorObject":230,"../util/tryCatch":241}],150:[function(a,b,e){var h=this&&this.__extends||function(a,b){function d(){this.constructor=a}for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);a.prototype=null===b?Object.create(b): -(d.prototype=b.prototype,new d)},k=a("../Subscription");a=a("../Observable");b=function(a){function b(){a.call(this);this.attemptedToUnsubscribePrimary=!1;this.count=0}h(b,a);b.prototype.setPrimary=function(a){this.primary=a};b.prototype.unsubscribe=function(){this.isUnsubscribed||this.attemptedToUnsubscribePrimary||(this.attemptedToUnsubscribePrimary=!0,0===this.count&&(a.prototype.unsubscribe.call(this),this.primary.unsubscribe()))};return b}(k.Subscription);e.RefCountSubscription=b;a=function(a){function b(d, -c,g){a.call(this);this.key=d;this.groupSubject=c;this.refCountSubscription=g}h(b,a);b.prototype._subscribe=function(a){var c=new k.Subscription;this.refCountSubscription&&!this.refCountSubscription.isUnsubscribed&&c.add(new m(this.refCountSubscription));c.add(this.groupSubject.subscribe(a));return c};return b}(a.Observable);e.GroupedObservable=a;var m=function(a){function b(d){a.call(this);this.parent=d;d.count++}h(b,a);b.prototype.unsubscribe=function(){this.parent.isUnsubscribed||this.isUnsubscribed|| -(a.prototype.unsubscribe.call(this),this.parent.count--,0===this.parent.count&&this.parent.attemptedToUnsubscribePrimary&&(this.parent.unsubscribe(),this.parent.primary.unsubscribe()))};return b}(k.Subscription);e.InnerRefCountSubscription=m},{"../Observable":3,"../Subscription":8}],151:[function(a,b,e){var h=this&&this.__extends||function(a,c){function d(){this.constructor=a}for(var b in c)c.hasOwnProperty(b)&&(a[b]=c[b]);a.prototype=null===c?Object.create(c):(d.prototype=c.prototype,new d)};b=a("../Subscriber"); -var k=a("../Observable"),m=a("../Subject"),l=a("../util/Map"),f=a("../util/FastMap"),d=a("./groupBy-support"),c=a("../util/tryCatch"),g=a("../util/errorObject");e.groupBy=function(a,c,d){return new n(this,a,c,d)};var n=function(a){function c(d,b,g,f){a.call(this);this.source=d;this.keySelector=b;this.elementSelector=g;this.durationSelector=f}h(c,a);c.prototype._subscribe=function(a){var c=new d.RefCountSubscription;a=new p(a,c,this.keySelector,this.elementSelector,this.durationSelector);c.setPrimary(this.source.subscribe(a)); -return c};return c}(k.Observable);e.GroupByObservable=n;var p=function(a){function b(c,d,g,f,n){a.call(this);this.refCountSubscription=d;this.keySelector=g;this.elementSelector=f;this.durationSelector=n;this.groups=null;this.destination=c;this.add(c)}h(b,a);b.prototype._next=function(a){var b=c.tryCatch(this.keySelector)(a);if(b===g.errorObject)this.error(b.e);else{var n=this.groups,e=this.elementSelector,k=this.durationSelector;n||(n=this.groups="string"===typeof b?new f.FastMap:new l.Map);var h= -n.get(b);h||(n.set(b,h=new m.Subject),n=new d.GroupedObservable(b,h,this.refCountSubscription),k&&(k=c.tryCatch(k)(new d.GroupedObservable(b,h)),k===g.errorObject?this.error(k.e):this.add(k._subscribe(new q(b,h,this)))),this.destination.next(n));e?(a=c.tryCatch(e)(a),a===g.errorObject?this.error(a.e):h.next(a)):h.next(a)}};b.prototype._error=function(a){var c=this,b=this.groups;b&&b.forEach(function(b,d){b.error(a);c.removeGroup(d)});this.destination.error(a)};b.prototype._complete=function(){var a= -this,c=this.groups;c&&c.forEach(function(c,b){c.complete();a.removeGroup(c)});this.destination.complete()};b.prototype.removeGroup=function(a){this.groups.delete(a)};return b}(b.Subscriber),q=function(a){function c(b,d,g){a.call(this,null);this.key=b;this.group=d;this.parent=g}h(c,a);c.prototype._next=function(a){this.group.complete();this.parent.removeGroup(this.key)};c.prototype._error=function(a){this.group.error(a);this.parent.removeGroup(this.key)};c.prototype._complete=function(){this.group.complete(); -this.parent.removeGroup(this.key)};return c}(b.Subscriber)},{"../Observable":3,"../Subject":6,"../Subscriber":7,"../util/FastMap":224,"../util/Map":226,"../util/errorObject":230,"../util/tryCatch":241,"./groupBy-support":150}],152:[function(a,b,e){var h=this&&this.__extends||function(a,b){function c(){this.constructor=a}for(var g in b)b.hasOwnProperty(g)&&(a[g]=b[g]);a.prototype=null===b?Object.create(b):(c.prototype=b.prototype,new c)};b=a("../Subscriber");var k=a("../util/noop");e.ignoreElements= -function(){return this.lift(new m)};var m=function(){function a(){}a.prototype.call=function(a){return new l(a)};return a}(),l=function(a){function b(){a.apply(this,arguments)}h(b,a);b.prototype._next=function(a){k.noop()};return b}(b.Subscriber)},{"../Subscriber":7,"../util/noop":236}],153:[function(a,b,e){var h=this&&this.__extends||function(a,b){function d(){this.constructor=a}for(var f in b)b.hasOwnProperty(f)&&(a[f]=b[f]);a.prototype=null===b?Object.create(b):(d.prototype=b.prototype,new d)}; -b=a("../Subscriber");var k=a("../util/tryCatch"),m=a("../util/errorObject"),l=a("../util/EmptyError");e.last=function(a,b,d){return this.lift(new f(a,b,d,this))};var f=function(){function a(c,b,d,f){this.predicate=c;this.resultSelector=b;this.defaultValue=d;this.source=f}a.prototype.call=function(a){return new d(a,this.predicate,this.resultSelector,this.defaultValue,this.source)};return a}(),d=function(a){function b(d,g,f,e,l){a.call(this,d);this.predicate=g;this.resultSelector=f;this.defaultValue= -e;this.source=l;this.hasValue=!1;this.index=0;"undefined"!==typeof e&&(this.lastValue=e,this.hasValue=!0)}h(b,a);b.prototype._next=function(a){var c=this.predicate,b=this.resultSelector,d=this.destination,g=this.index++;if(c)if(c=k.tryCatch(c)(a,g,this.source),c===m.errorObject)d.error(m.errorObject.e);else{if(c){if(b&&(a=k.tryCatch(b)(a,g),a===m.errorObject)){d.error(m.errorObject.e);return}this.lastValue=a;this.hasValue=!0}}else this.lastValue=a,this.hasValue=!0};b.prototype._complete=function(){var a= -this.destination;this.hasValue?(a.next(this.lastValue),a.complete()):a.error(new l.EmptyError)};return b}(b.Subscriber)},{"../Subscriber":7,"../util/EmptyError":223,"../util/errorObject":230,"../util/tryCatch":241}],154:[function(a,b,e){var h=this&&this.__extends||function(a,c){function b(){this.constructor=a}for(var f in c)c.hasOwnProperty(f)&&(a[f]=c[f]);a.prototype=null===c?Object.create(c):(b.prototype=c.prototype,new b)};b=a("../Subscriber");var k=a("../util/tryCatch"),m=a("../util/errorObject"); -e.map=function(a,c){if("function"!==typeof a)throw new TypeError("argument is not a function. Are you looking for `mapTo()`?");return this.lift(new l(a,c))};var l=function(){function a(c,b){this.project=c;this.thisArg=b}a.prototype.call=function(a){return new f(a,this.project,this.thisArg)};return a}(),f=function(a){function c(c,b,f){a.call(this,c);this.project=b;this.thisArg=f;this.count=0}h(c,a);c.prototype._next=function(a){a=k.tryCatch(this.project).call(this.thisArg||this,a,this.count++);a=== -m.errorObject?this.error(m.errorObject.e):this.destination.next(a)};return c}(b.Subscriber)},{"../Subscriber":7,"../util/errorObject":230,"../util/tryCatch":241}],155:[function(a,b,e){var h=this&&this.__extends||function(a,b){function d(){this.constructor=a}for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);a.prototype=null===b?Object.create(b):(d.prototype=b.prototype,new d)};a=a("../Subscriber");e.mapTo=function(a){return this.lift(new k(a))};var k=function(){function a(b){this.value=b}a.prototype.call= -function(a){return new m(a,this.value)};return a}(),m=function(a){function b(d,c){a.call(this,d);this.value=c}h(b,a);b.prototype._next=function(a){this.destination.next(this.value)};return b}(a.Subscriber)},{"../Subscriber":7}],156:[function(a,b,e){var h=this&&this.__extends||function(a,b){function c(){this.constructor=a}for(var g in b)b.hasOwnProperty(g)&&(a[g]=b[g]);a.prototype=null===b?Object.create(b):(c.prototype=b.prototype,new c)};b=a("../Subscriber");var k=a("../Notification");e.materialize= -function(){return this.lift(new m)};var m=function(){function a(){}a.prototype.call=function(a){return new l(a)};return a}(),l=function(a){function b(c){a.call(this,c)}h(b,a);b.prototype._next=function(a){this.destination.next(k.Notification.createNext(a))};b.prototype._error=function(a){var b=this.destination;b.next(k.Notification.createError(a));b.complete()};b.prototype._complete=function(){var a=this.destination;a.next(k.Notification.createComplete());a.complete()};return b}(b.Subscriber)},{"../Notification":2, -"../Subscriber":7}],157:[function(a,b,e){var h=a("../observable/fromArray"),k=a("./mergeAll-support"),m=a("../scheduler/queue"),l=a("../util/isScheduler");e.merge=function(){for(var a=[],b=0;b -a?-1:a)};return c}(b.Subscriber)},{"../Subscriber":7,"../observable/empty":109}],176:[function(a,b,e){var h=this&&this.__extends||function(a,b){function c(){this.constructor=a}for(var g in b)b.hasOwnProperty(g)&&(a[g]=b[g]);a.prototype=null===b?Object.create(b):(c.prototype=b.prototype,new c)};a=a("../Subscriber");e.retry=function(a){void 0===a&&(a=0);return this.lift(new k(a,this))};var k=function(){function a(b,c){this.count=b;this.source=c}a.prototype.call=function(a){return new m(a,this.count, -this.source)};return a}(),m=function(a){function b(c,d,n){a.call(this);this.destination=c;this.count=d;this.source=n;c.add(this);this.lastSubscription=this}h(b,a);b.prototype._next=function(a){this.destination.next(a)};b.prototype.error=function(a){this.isUnsubscribed||(this.unsubscribe(),this.resubscribe())};b.prototype._complete=function(){this.unsubscribe();this.destination.complete()};b.prototype.resubscribe=function(a){void 0===a&&(a=0);var b=this.lastSubscription,d=this.destination;d.remove(b); -b.unsubscribe();a=new l(this,this.count,a+1);this.lastSubscription=this.source.subscribe(a);d.add(this.lastSubscription)};return b}(a.Subscriber),l=function(a){function b(c,d,n){void 0===n&&(n=0);a.call(this,null);this.parent=c;this.count=d;this.retried=n}h(b,a);b.prototype._next=function(a){this.parent.destination.next(a)};b.prototype._error=function(a){var b=this.parent,d=this.retried,f=this.count;f&&d===f?b.destination.error(a):b.resubscribe(d)};b.prototype._complete=function(){this.parent.destination.complete()}; -return b}(a.Subscriber)},{"../Subscriber":7}],177:[function(a,b,e){var h=this&&this.__extends||function(a,c){function b(){this.constructor=a}for(var d in c)c.hasOwnProperty(d)&&(a[d]=c[d]);a.prototype=null===c?Object.create(c):(b.prototype=c.prototype,new b)};b=a("../Subscriber");var k=a("../Subject"),m=a("../util/tryCatch"),l=a("../util/errorObject");e.retryWhen=function(a){return this.lift(new f(a,this))};var f=function(){function a(c,b){this.notifier=c;this.source=b}a.prototype.call=function(a){return new d(a, -this.notifier,this.source)};return a}(),d=function(a){function b(c,d,g){a.call(this);this.destination=c;this.notifier=d;this.source=g;c.add(this);this.lastSubscription=this}h(b,a);b.prototype._next=function(a){this.destination.next(a)};b.prototype.error=function(c){var b=this.destination;if(!this.isUnsubscribed){a.prototype.unsubscribe.call(this);if(!this.retryNotifications){this.errors=new k.Subject;var d=m.tryCatch(this.notifier).call(this,this.errors);if(d===l.errorObject)b.error(l.errorObject.e); -else{this.retryNotifications=d;var f=new g(this);this.notificationSubscription=d.subscribe(f);b.add(this.notificationSubscription)}}this.errors.next(c)}};b.prototype.destinationError=function(a){this.tearDown();this.destination.error(a)};b.prototype._complete=function(){this.destinationComplete()};b.prototype.destinationComplete=function(){this.tearDown();this.destination.complete()};b.prototype.unsubscribe=function(){this.lastSubscription===this?a.prototype.unsubscribe.call(this):this.tearDown()}; -b.prototype.tearDown=function(){a.prototype.unsubscribe.call(this);this.lastSubscription.unsubscribe();var c=this.notificationSubscription;c&&c.unsubscribe()};b.prototype.resubscribe=function(){var a=this.destination,b=this.lastSubscription;a.remove(b);b.unsubscribe();b=new c(this);this.lastSubscription=this.source.subscribe(b);a.add(this.lastSubscription)};return b}(b.Subscriber),c=function(a){function c(b){a.call(this,null);this.parent=b}h(c,a);c.prototype._next=function(a){this.parent.destination.next(a)}; -c.prototype._error=function(a){this.parent.errors.next(a)};c.prototype._complete=function(){this.parent.destinationComplete()};return c}(b.Subscriber),g=function(a){function c(b){a.call(this,null);this.parent=b}h(c,a);c.prototype._next=function(a){this.parent.resubscribe()};c.prototype._error=function(a){this.parent.destinationError(a)};c.prototype._complete=function(){this.parent.destinationComplete()};return c}(b.Subscriber)},{"../Subject":6,"../Subscriber":7,"../util/errorObject":230,"../util/tryCatch":241}], -178:[function(a,b,e){var h=this&&this.__extends||function(a,b){function c(){this.constructor=a}for(var g in b)b.hasOwnProperty(g)&&(a[g]=b[g]);a.prototype=null===b?Object.create(b):(c.prototype=b.prototype,new c)};a=a("../Subscriber");e.sample=function(a){return this.lift(new k(a))};var k=function(){function a(b){this.notifier=b}a.prototype.call=function(a){return new m(a,this.notifier)};return a}(),m=function(a){function b(c,d){a.call(this,c);this.notifier=d;this.hasValue=!1;this.add(d._subscribe(new l(this)))} -h(b,a);b.prototype._next=function(a){this.lastValue=a;this.hasValue=!0};b.prototype.notifyNext=function(){this.hasValue&&(this.hasValue=!1,this.destination.next(this.lastValue))};return b}(a.Subscriber),l=function(a){function b(c){a.call(this,null);this.parent=c}h(b,a);b.prototype._next=function(){this.parent.notifyNext()};b.prototype._error=function(a){this.parent.error(a)};b.prototype._complete=function(){this.parent.notifyNext()};return b}(a.Subscriber)},{"../Subscriber":7}],179:[function(a,b, -e){function h(a){var c=a.delay;a.subscriber.notifyNext();this.schedule(a,c)}var k=this&&this.__extends||function(a,c){function b(){this.constructor=a}for(var f in c)c.hasOwnProperty(f)&&(a[f]=c[f]);a.prototype=null===c?Object.create(c):(b.prototype=c.prototype,new b)};b=a("../Subscriber");var m=a("../scheduler/asap");e.sampleTime=function(a,c){void 0===c&&(c=m.asap);return this.lift(new l(a,c))};var l=function(){function a(c,b){this.delay=c;this.scheduler=b}a.prototype.call=function(a){return new f(a, -this.delay,this.scheduler)};return a}(),f=function(a){function c(c,b,f){a.call(this,c);this.delay=b;this.scheduler=f;this.hasValue=!1;this.add(f.schedule(h,b,{subscriber:this,delay:b}))}k(c,a);c.prototype._next=function(a){this.lastValue=a;this.hasValue=!0};c.prototype.notifyNext=function(){this.hasValue&&(this.hasValue=!1,this.destination.next(this.lastValue))};return c}(b.Subscriber)},{"../Subscriber":7,"../scheduler/asap":215}],180:[function(a,b,e){var h=this&&this.__extends||function(a,c){function b(){this.constructor= -a}for(var f in c)c.hasOwnProperty(f)&&(a[f]=c[f]);a.prototype=null===c?Object.create(c):(b.prototype=c.prototype,new b)};b=a("../Subscriber");var k=a("../util/tryCatch"),m=a("../util/errorObject");e.scan=function(a,c){return this.lift(new l(a,c))};var l=function(){function a(c,b){this.accumulator=c;this.seed=b}a.prototype.call=function(a){return new f(a,this.accumulator,this.seed)};return a}(),f=function(a){function c(c,b,f){a.call(this,c);this.accumulator=b;this.accumulatorSet=!1;this.seed=f;this.accumulator= -b;this.accumulatorSet="undefined"!==typeof f}h(c,a);Object.defineProperty(c.prototype,"seed",{get:function(){return this._seed},set:function(a){this.accumulatorSet=!0;this._seed=a},enumerable:!0,configurable:!0});c.prototype._next=function(a){this.accumulatorSet?(a=k.tryCatch(this.accumulator).call(this,this.seed,a),a===m.errorObject?this.destination.error(m.errorObject.e):(this.seed=a,this.destination.next(this.seed))):(this.seed=a,this.destination.next(a))};return c}(b.Subscriber)},{"../Subscriber":7, -"../util/errorObject":230,"../util/tryCatch":241}],181:[function(a,b,e){function h(){return new m.Subject}var k=a("./multicast"),m=a("../Subject");e.share=function(){return k.multicast.call(this,h).refCount()}},{"../Subject":6,"./multicast":165}],182:[function(a,b,e){var h=this&&this.__extends||function(a,b){function d(){this.constructor=a}for(var f in b)b.hasOwnProperty(f)&&(a[f]=b[f]);a.prototype=null===b?Object.create(b):(d.prototype=b.prototype,new d)};b=a("../Subscriber");var k=a("../util/tryCatch"), -m=a("../util/errorObject"),l=a("../util/EmptyError");e.single=function(a){return this.lift(new f(a,this))};var f=function(){function a(b,c){this.predicate=b;this.source=c}a.prototype.call=function(a){return new d(a,this.predicate,this.source)};return a}(),d=function(a){function b(d,g,f){a.call(this,d);this.predicate=g;this.source=f;this.seenValue=!1;this.index=0}h(b,a);b.prototype.applySingleValue=function(a){this.seenValue?this.destination.error("Sequence contains more than one element"):(this.seenValue= -!0,this.singleValue=a)};b.prototype._next=function(a){var b=this.predicate,c=this.index++;b?(b=k.tryCatch(b)(a,c,this.source),b===m.errorObject?this.destination.error(b.e):b&&this.applySingleValue(a)):this.applySingleValue(a)};b.prototype._complete=function(){var a=this.destination;0 -this.total&&this.destination.next(a)};return b}(a.Subscriber)},{"../Subscriber":7}],184:[function(a,b,e){var h=this&&this.__extends||function(a,b){function c(){this.constructor=a}for(var g in b)b.hasOwnProperty(g)&&(a[g]=b[g]);a.prototype=null===b?Object.create(b):(c.prototype=b.prototype,new c)};a=a("../Subscriber");e.skipUntil=function(a){return this.lift(new k(a))};var k=function(){function a(b){this.notifier=b}a.prototype.call=function(a){return new m(a,this.notifier)};return a}(),m=function(a){function b(c, -d){a.call(this,c);this.notifier=d;this.notificationSubscriber=null;this.notificationSubscriber=new l(this);this.add(this.notifier.subscribe(this.notificationSubscriber))}h(b,a);b.prototype._next=function(a){this.notificationSubscriber.hasValue&&this.destination.next(a)};b.prototype._error=function(a){this.destination.error(a)};b.prototype._complete=function(){this.notificationSubscriber.hasCompleted&&this.destination.complete();this.notificationSubscriber.unsubscribe()};b.prototype.unsubscribe=function(){this._isUnsubscribed|| -(this._subscription?(this._subscription.unsubscribe(),this._isUnsubscribed=!0):a.prototype.unsubscribe.call(this))};return b}(a.Subscriber),l=function(a){function b(c){a.call(this,null);this.parent=c;this.hasCompleted=this.hasValue=!1}h(b,a);b.prototype._next=function(a){this.hasValue=!0};b.prototype._error=function(a){this.parent.error(a);this.hasValue=!0};b.prototype._complete=function(){this.hasCompleted=!0};return b}(a.Subscriber)},{"../Subscriber":7}],185:[function(a,b,e){var h=this&&this.__extends|| -function(a,b){function g(){this.constructor=a}for(var f in b)b.hasOwnProperty(f)&&(a[f]=b[f]);a.prototype=null===b?Object.create(b):(g.prototype=b.prototype,new g)};b=a("../Subscriber");var k=a("../util/tryCatch"),m=a("../util/errorObject");e.skipWhile=function(a){return this.lift(new l(a))};var l=function(){function a(b){this.predicate=b}a.prototype.call=function(a){return new f(a,this.predicate)};return a}(),f=function(a){function b(c,f){a.call(this,c);this.predicate=f;this.skipping=!0;this.index= -0}h(b,a);b.prototype._next=function(a){var b=this.destination;if(!0===this.skipping){var c=this.index++,c=k.tryCatch(this.predicate)(a,c);c===m.errorObject?b.error(c.e):this.skipping=Boolean(c)}!1===this.skipping&&b.next(a)};return b}(b.Subscriber)},{"../Subscriber":7,"../util/errorObject":230,"../util/tryCatch":241}],186:[function(a,b,e){var h=a("../observable/fromArray"),k=a("../observable/ScalarObservable"),m=a("../observable/empty"),l=a("./concat-static"),f=a("../util/isScheduler");e.startWith= -function(){for(var a=[],b=0;bthis.total)throw new k.ArgumentOutOfRangeError;}a.prototype.call=function(a){return new f(a,this.total)};return a}(),f=function(a){function b(c,f){a.call(this,c);this.total=f;this.count=0}h(b,a);b.prototype._next= -function(a){var b=this.total;++this.count<=b&&(this.destination.next(a),this.count===b&&this.destination.complete())};return b}(b.Subscriber)},{"../Subscriber":7,"../observable/empty":109,"../util/ArgumentOutOfRangeError":222}],192:[function(a,b,e){var h=this&&this.__extends||function(a,b){function f(){this.constructor=a}for(var e in b)b.hasOwnProperty(e)&&(a[e]=b[e]);a.prototype=null===b?Object.create(b):(f.prototype=b.prototype,new f)};b=a("../Subscriber");var k=a("../util/noop");e.takeUntil=function(a){return this.lift(new m(a))}; -var m=function(){function a(b){this.notifier=b}a.prototype.call=function(a){return new l(a,this.notifier)};return a}(),l=function(a){function b(c,e){a.call(this,c);this.notifier=e;this.notificationSubscriber=null;this.notificationSubscriber=new f(c);this.add(e.subscribe(this.notificationSubscriber))}h(b,a);b.prototype._complete=function(){this.destination.complete();this.notificationSubscriber.unsubscribe()};return b}(b.Subscriber),f=function(a){function b(c){a.call(this,null);this.destination=c} -h(b,a);b.prototype._next=function(a){this.destination.complete()};b.prototype._error=function(a){this.destination.error(a)};b.prototype._complete=function(){k.noop()};return b}(b.Subscriber)},{"../Subscriber":7,"../util/noop":236}],193:[function(a,b,e){var h=this&&this.__extends||function(a,b){function f(){this.constructor=a}for(var e in b)b.hasOwnProperty(e)&&(a[e]=b[e]);a.prototype=null===b?Object.create(b):(f.prototype=b.prototype,new f)};b=a("../Subscriber");var k=a("../util/tryCatch"),m=a("../util/errorObject"); -e.takeWhile=function(a){return this.lift(new l(a))};var l=function(){function a(b){this.predicate=b}a.prototype.call=function(a){return new f(a,this.predicate)};return a}(),f=function(a){function b(c,f){a.call(this,c);this.predicate=f;this.index=0}h(b,a);b.prototype._next=function(a){var b=this.destination,c=k.tryCatch(this.predicate)(a,this.index++);c==m.errorObject?b.error(c.e):Boolean(c)?b.next(a):b.complete()};return b}(b.Subscriber)},{"../Subscriber":7,"../util/errorObject":230,"../util/tryCatch":241}], -194:[function(a,b,e){var h=this&&this.__extends||function(a,b){function c(){this.constructor=a}for(var d in b)b.hasOwnProperty(d)&&(a[d]=b[d]);a.prototype=null===b?Object.create(b):(c.prototype=b.prototype,new c)},k=a("../observable/fromPromise");b=a("../Subscriber");var m=a("../util/tryCatch"),l=a("../util/isPromise"),f=a("../util/errorObject");e.throttle=function(a){return this.lift(new d(a))};var d=function(){function a(b){this.durationSelector=b}a.prototype.call=function(a){return new c(a,this.durationSelector)}; -return a}(),c=function(a){function b(c,d){a.call(this,c);this.durationSelector=d}h(b,a);b.prototype._next=function(a){if(!this.throttled){var b=this.destination,c=m.tryCatch(this.durationSelector)(a);c===f.errorObject?b.error(f.errorObject.e):(l.isPromise(c)&&(c=k.PromiseObservable.create(c)),this.add(this.throttled=c._subscribe(new g(this))),b.next(a))}};b.prototype._error=function(b){this.clearThrottle();a.prototype._error.call(this,b)};b.prototype._complete=function(){this.clearThrottle();a.prototype._complete.call(this)}; -b.prototype.clearThrottle=function(){var a=this.throttled;a&&(a.unsubscribe(),this.remove(a),this.throttled=null)};return b}(b.Subscriber),g=function(a){function b(c){a.call(this,null);this.parent=c}h(b,a);b.prototype._next=function(a){this.parent.clearThrottle()};b.prototype._error=function(a){this.parent.error(a)};b.prototype._complete=function(){this.parent.clearThrottle()};return b}(b.Subscriber)},{"../Subscriber":7,"../observable/fromPromise":115,"../util/errorObject":230,"../util/isPromise":234, -"../util/tryCatch":241}],195:[function(a,b,e){function h(a){a.subscriber.clearThrottle()}var k=this&&this.__extends||function(a,b){function f(){this.constructor=a}for(var e in b)b.hasOwnProperty(e)&&(a[e]=b[e]);a.prototype=null===b?Object.create(b):(f.prototype=b.prototype,new f)};b=a("../Subscriber");var m=a("../scheduler/asap");e.throttleTime=function(a,b){void 0===b&&(b=m.asap);return this.lift(new l(a,b))};var l=function(){function a(b,d){this.delay=b;this.scheduler=d}a.prototype.call=function(a){return new f(a, -this.delay,this.scheduler)};return a}(),f=function(a){function b(c,f,e){a.call(this,c);this.delay=f;this.scheduler=e}k(b,a);b.prototype._next=function(a){this.throttled||(this.add(this.throttled=this.scheduler.schedule(h,this.delay,{subscriber:this})),this.destination.next(a))};b.prototype.clearThrottle=function(){var a=this.throttled;a&&(a.unsubscribe(),this.remove(a),this.throttled=null)};return b}(b.Subscriber)},{"../Subscriber":7,"../scheduler/asap":215}],196:[function(a,b,e){var h=this&&this.__extends|| -function(a,b){function f(){this.constructor=a}for(var e in b)b.hasOwnProperty(e)&&(a[e]=b[e]);a.prototype=null===b?Object.create(b):(f.prototype=b.prototype,new f)};b=a("../Subscriber");var k=a("../scheduler/queue"),m=a("../util/isDate");e.timeout=function(a,b,f){void 0===b&&(b=null);void 0===f&&(f=k.queue);var e=m.isDate(a);a=e?+a-f.now():a;return this.lift(new l(a,e,b,f))};var l=function(){function a(b,d,f,e){this.waitFor=b;this.absoluteTimeout=d;this.errorToSend=f;this.scheduler=e}a.prototype.call= -function(a){return new f(a,this.absoluteTimeout,this.waitFor,this.errorToSend,this.scheduler)};return a}(),f=function(a){function b(c,f,e,l,k){a.call(this,c);this.absoluteTimeout=f;this.waitFor=e;this.errorToSend=l;this.scheduler=k;this._previousIndex=this.index=0;this._hasCompleted=!1;this.scheduleTimeout()}h(b,a);Object.defineProperty(b.prototype,"previousIndex",{get:function(){return this._previousIndex},enumerable:!0,configurable:!0});Object.defineProperty(b.prototype,"hasCompleted",{get:function(){return this._hasCompleted}, -enumerable:!0,configurable:!0});b.dispatchTimeout=function(a){var b=a.subscriber;a=a.index;b.hasCompleted||b.previousIndex!==a||b.notifyTimeout()};b.prototype.scheduleTimeout=function(){var a=this.index;this.scheduler.schedule(b.dispatchTimeout,this.waitFor,{subscriber:this,index:a});this.index++;this._previousIndex=a};b.prototype._next=function(a){this.destination.next(a);this.absoluteTimeout||this.scheduleTimeout()};b.prototype._error=function(a){this.destination.error(a);this._hasCompleted=!0}; -b.prototype._complete=function(){this.destination.complete();this._hasCompleted=!0};b.prototype.notifyTimeout=function(){this.error(this.errorToSend||Error("timeout"))};return b}(b.Subscriber)},{"../Subscriber":7,"../scheduler/queue":216,"../util/isDate":232}],197:[function(a,b,e){var h=this&&this.__extends||function(a,b){function d(){this.constructor=a}for(var f in b)b.hasOwnProperty(f)&&(a[f]=b[f]);a.prototype=null===b?Object.create(b):(d.prototype=b.prototype,new d)},k=a("../scheduler/queue"), -m=a("../util/isDate");b=a("../OuterSubscriber");var l=a("../util/subscribeToResult");e.timeoutWith=function(a,b,d){void 0===d&&(d=k.queue);var e=m.isDate(a);a=e?+a-d.now():a;return this.lift(new f(a,e,b,d))};var f=function(){function a(b,c,d,f){this.waitFor=b;this.absoluteTimeout=c;this.withObservable=d;this.scheduler=f}a.prototype.call=function(a){return new d(a,this.absoluteTimeout,this.waitFor,this.withObservable,this.scheduler)};return a}(),d=function(a){function b(d,f,g,e,l){a.call(this,null); -this.destination=d;this.absoluteTimeout=f;this.waitFor=g;this.withObservable=e;this.scheduler=l;this.timeoutSubscription=void 0;this._previousIndex=this.index=0;this._hasCompleted=!1;d.add(this);this.scheduleTimeout()}h(b,a);Object.defineProperty(b.prototype,"previousIndex",{get:function(){return this._previousIndex},enumerable:!0,configurable:!0});Object.defineProperty(b.prototype,"hasCompleted",{get:function(){return this._hasCompleted},enumerable:!0,configurable:!0});b.dispatchTimeout=function(a){var b= -a.subscriber;a=a.index;b.hasCompleted||b.previousIndex!==a||b.handleTimeout()};b.prototype.scheduleTimeout=function(){var a=this.index;this.scheduler.schedule(b.dispatchTimeout,this.waitFor,{subscriber:this,index:a});this.index++;this._previousIndex=a};b.prototype._next=function(a){this.destination.next(a);this.absoluteTimeout||this.scheduleTimeout()};b.prototype._error=function(a){this.destination.error(a);this._hasCompleted=!0};b.prototype._complete=function(){this.destination.complete();this._hasCompleted= -!0};b.prototype.handleTimeout=function(){if(!this.isUnsubscribed){var a=this.withObservable;this.unsubscribe();this.destination.add(this.timeoutSubscription=l.subscribeToResult(this,a))}};return b}(b.OuterSubscriber)},{"../OuterSubscriber":4,"../scheduler/queue":216,"../util/isDate":232,"../util/subscribeToResult":239}],198:[function(a,b,e){var h=this&&this.__extends||function(a,b){function d(){this.constructor=a}for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);a.prototype=null===b?Object.create(b): -(d.prototype=b.prototype,new d)};a=a("../Subscriber");e.toArray=function(){return this.lift(new k)};var k=function(){function a(){}a.prototype.call=function(a){return new m(a)};return a}(),m=function(a){function b(d){a.call(this,d);this.array=[]}h(b,a);b.prototype._next=function(a){this.array.push(a)};b.prototype._complete=function(){this.destination.next(this.array);this.destination.complete()};return b}(a.Subscriber)},{"../Subscriber":7}],199:[function(a,b,e){var h=a("../util/root");e.toPromise= -function(a){var b=this;a||(h.root.Rx&&h.root.Rx.config&&h.root.Rx.config.Promise?a=h.root.Rx.config.Promise:h.root.Promise&&(a=h.root.Promise));if(!a)throw Error("no Promise impl found");return new a(function(a,f){var d;b.subscribe(function(a){return d=a},function(a){return f(a)},function(){return a(d)})})}},{"../util/root":238}],200:[function(a,b,e){var h=this&&this.__extends||function(a,b){function f(){this.constructor=a}for(var e in b)b.hasOwnProperty(e)&&(a[e]=b[e]);a.prototype=null===b?Object.create(b): -(f.prototype=b.prototype,new f)};b=a("../Subscriber");var k=a("../Subject");e.window=function(a){return this.lift(new m(a))};var m=function(){function a(b){this.closingNotifier=b}a.prototype.call=function(a){return new l(a,this.closingNotifier)};return a}(),l=function(a){function b(c,e){a.call(this,c);this.destination=c;this.closingNotifier=e;this.add(e._subscribe(new f(this)));this.openWindow()}h(b,a);b.prototype._next=function(a){this.window.next(a)};b.prototype._error=function(a){this.window.error(a); -this.destination.error(a)};b.prototype._complete=function(){this.window.complete();this.destination.complete()};b.prototype.openWindow=function(){var a=this.window;a&&a.complete();var a=this.destination,b=this.window=new k.Subject;a.add(b);a.next(b)};return b}(b.Subscriber),f=function(a){function b(c){a.call(this,null);this.parent=c}h(b,a);b.prototype._next=function(){this.parent.openWindow()};b.prototype._error=function(a){this.parent._error(a)};b.prototype._complete=function(){this.parent._complete()}; -return b}(b.Subscriber)},{"../Subject":6,"../Subscriber":7}],201:[function(a,b,e){var h=this&&this.__extends||function(a,b){function c(){this.constructor=a}for(var g in b)b.hasOwnProperty(g)&&(a[g]=b[g]);a.prototype=null===b?Object.create(b):(c.prototype=b.prototype,new c)};b=a("../Subscriber");var k=a("../Subject");e.windowCount=function(a,b){void 0===b&&(b=0);return this.lift(new m(a,b))};var m=function(){function a(b,c){this.windowSize=b;this.startWindowEvery=c}a.prototype.call=function(a){return new l(a, -this.windowSize,this.startWindowEvery)};return a}(),l=function(a){function b(c,d,e){a.call(this,c);this.destination=c;this.windowSize=d;this.startWindowEvery=e;this.windows=[new k.Subject];this.count=0;d=this.windows[0];c.add(d);c.next(d)}h(b,a);b.prototype._next=function(a){for(var b=0this.index};a.prototype.hasCompleted=function(){return this.array.length===this.index};return a}(),q=function(a){function b(c,d,f,e){a.call(this,c);this.parent=d;this.observable=f;this.index=e;this.stillUnsubscribed=!0;this.buffer=[];this.isComplete=!1}h(b,a);b.prototype[d.SymbolShim.iterator]=function(){return this};b.prototype.next=function(){var a=this.buffer;return 0===a.length&&this.isComplete? -{done:!0}:{value:a.shift(),done:!1}};b.prototype.hasValue=function(){return 0=b?this.scheduleNow(a,d):this.scheduleLater(a,b,d)};a.prototype.scheduleNow= -function(a,b){return(new h.QueueAction(this,a)).schedule(b)};a.prototype.scheduleLater=function(a,b,d){return(new k.FutureAction(this,a)).schedule(d,b)};return a}();e.QueueScheduler=a},{"./FutureAction":212,"./QueueAction":213}],215:[function(a,b,e){a=a("./AsapScheduler");e.asap=new a.AsapScheduler},{"./AsapScheduler":211}],216:[function(a,b,e){a=a("./QueueScheduler");e.queue=new a.QueueScheduler},{"./QueueScheduler":214}],217:[function(a,b,e){var h=this&&this.__extends||function(a,b){function e(){this.constructor= -a}for(var f in b)b.hasOwnProperty(f)&&(a[f]=b[f]);a.prototype=null===b?Object.create(b):(e.prototype=b.prototype,new e)};a=function(a){function b(){a.call(this);this._value=void 0;this._isScalar=this._hasNext=!1}h(b,a);b.prototype._subscribe=function(b){this.completeSignal&&this._hasNext&&b.next(this._value);return a.prototype._subscribe.call(this,b)};b.prototype._next=function(a){this._value=a;this._hasNext=!0};b.prototype._complete=function(){var a=-1,b=this.observers,d=b.length;this.observers= -void 0;this.isUnsubscribed=!0;if(this._hasNext)for(;++ad?1:d;this._windowTime=1>c?1:c;this.scheduler=f}h(b,a);b.prototype._next=function(b){var c=this._getNow();this.events.push(new m(c,b));this._trimBufferThenGetEvents(c);a.prototype._next.call(this,b)};b.prototype._subscribe=function(b){for(var c=this._trimBufferThenGetEvents(this._getNow()),f=-1,e=c.length;!b.isUnsubscribed&& -++fb&&(k=Math.max(k,h-b));0o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=n(5),a=n(6),c=n(7),u=function(e){function t(t){e.call(this),this.attributeName=t}return r(t,e),Object.defineProperty(t.prototype,"token",{get:function(){return this},enumerable:!0,configurable:!0}),t.prototype.toString=function(){return"@Attribute("+s.stringify(this.attributeName)+")"},t=i([s.CONST(),o("design:paramtypes",[String])],t)}(c.DependencyMetadata);t.AttributeMetadata=u;var p=function(e){function t(t,n){var r=void 0===n?{}:n,i=r.descendants,o=void 0===i?!1:i,s=r.first,a=void 0===s?!1:s;e.call(this),this._selector=t,this.descendants=o,this.first=a}return r(t,e),Object.defineProperty(t.prototype,"isViewQuery",{get:function(){return!1},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"selector",{get:function(){return a.resolveForwardRef(this._selector)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"isVarBindingQuery",{get:function(){return s.isString(this.selector)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"varBindings",{get:function(){return this.selector.split(",")},enumerable:!0,configurable:!0}),t.prototype.toString=function(){return"@Query("+s.stringify(this.selector)+")"},t=i([s.CONST(),o("design:paramtypes",[Object,Object])],t)}(c.DependencyMetadata);t.QueryMetadata=p;var l=function(e){function t(t,n){var r=(void 0===n?{}:n).descendants,i=void 0===r?!1:r;e.call(this,t,{descendants:i})}return r(t,e),t=i([s.CONST(),o("design:paramtypes",[Object,Object])],t)}(p);t.ContentChildrenMetadata=l;var h=function(e){function t(t){e.call(this,t,{descendants:!0,first:!0})}return r(t,e),t=i([s.CONST(),o("design:paramtypes",[Object])],t)}(p);t.ContentChildMetadata=h;var f=function(e){function t(t,n){var r=void 0===n?{}:n,i=r.descendants,o=void 0===i?!1:i,s=r.first,a=void 0===s?!1:s;e.call(this,t,{descendants:o,first:a})}return r(t,e),Object.defineProperty(t.prototype,"isViewQuery",{get:function(){return!0},enumerable:!0,configurable:!0}),t.prototype.toString=function(){return"@ViewQuery("+s.stringify(this.selector)+")"},t=i([s.CONST(),o("design:paramtypes",[Object,Object])],t)}(p);t.ViewQueryMetadata=f;var d=function(e){function t(t){e.call(this,t,{descendants:!0})}return r(t,e),t=i([s.CONST(),o("design:paramtypes",[Object])],t)}(f);t.ViewChildrenMetadata=d;var y=function(e){function t(t){e.call(this,t,{descendants:!0,first:!0})}return r(t,e),t=i([s.CONST(),o("design:paramtypes",[Object])],t)}(f);t.ViewChildMetadata=y},function(e,t){(function(e){function n(e){return e.name}function r(){k=!0}function i(){if(k)throw"Cannot enable prod mode after platform setup.";N=!1}function o(){return N}function s(e){return e}function a(){return function(e){return e}}function c(e){return void 0!==e&&null!==e}function u(e){return void 0===e||null===e}function p(e){return"string"==typeof e}function l(e){return"function"==typeof e}function h(e){return l(e)}function f(e){return"object"==typeof e&&null!==e}function d(e){return e instanceof x.Promise}function y(e){return Array.isArray(e)}function v(e){return"number"==typeof e}function m(e){return e instanceof t.Date&&!isNaN(e.valueOf())}function g(){}function _(e){if("string"==typeof e)return e;if(void 0===e||null===e)return""+e;if(e.name)return e.name;var t=e.toString(),n=t.indexOf("\n");return-1===n?t:t.substring(0,n)}function b(e){return e}function C(e,t){return e}function P(e,t){return e===t||"number"==typeof e&&"number"==typeof t&&isNaN(e)&&isNaN(t)}function w(e){return e}function R(e){return u(e)?null:e}function E(e){return u(e)?!1:e}function O(e){return null!==e&&("function"==typeof e||"object"==typeof e)}function S(e){console.log(e)}function D(e,t,n){for(var r=t.split("."),i=e;r.length>1;){var o=r.shift();i=i.hasOwnProperty(o)&&c(i[o])?i[o]:i[o]={}}(void 0===i||null===i)&&(i={}),i[r.shift()]=n}function T(){if(u(q))if(c(Symbol)&&c(Symbol.iterator))q=Symbol.iterator;else for(var e=Object.getOwnPropertyNames(Map.prototype),t=0;t=0&&e[r]==t;r--)n--;e=e.substring(0,n)}return e},e.replace=function(e,t,n){return e.replace(t,n)},e.replaceAll=function(e,t,n){return e.replace(t,n)},e.slice=function(e,t,n){return void 0===t&&(t=0),void 0===n&&(n=null),e.slice(t,null===n?void 0:n)},e.replaceAllMapped=function(e,t,n){return e.replace(t,function(){for(var e=[],t=0;te?-1:e>t?1:0},e}();t.StringWrapper=j;var V=function(){function e(e){void 0===e&&(e=[]),this.parts=e}return e.prototype.add=function(e){this.parts.push(e)},e.prototype.toString=function(){return this.parts.join("")},e}();t.StringJoiner=V;var M=function(e){function t(t){e.call(this),this.message=t}return I(t,e),t.prototype.toString=function(){return this.message},t}(Error);t.NumberParseError=M;var B=function(){function e(){}return e.toFixed=function(e,t){return e.toFixed(t)},e.equal=function(e,t){return e===t},e.parseIntAutoRadix=function(e){var t=parseInt(e);if(isNaN(t))throw new M("Invalid integer literal when parsing "+e);return t},e.parseInt=function(e,t){if(10==t){if(/^(\-|\+)?[0-9]+$/.test(e))return parseInt(e,t)}else if(16==t){if(/^(\-|\+)?[0-9ABCDEFabcdef]+$/.test(e))return parseInt(e,t)}else{var n=parseInt(e,t);if(!isNaN(n))return n}throw new M("Invalid integer literal when parsing "+e+" in base "+t)},e.parseFloat=function(e){return parseFloat(e)},Object.defineProperty(e,"NaN",{get:function(){return NaN},enumerable:!0,configurable:!0}),e.isNaN=function(e){return isNaN(e)},e.isInteger=function(e){return Number.isInteger(e)},e}();t.NumberWrapper=B,t.RegExp=x.RegExp;var L=function(){function e(){}return e.create=function(e,t){return void 0===t&&(t=""),t=t.replace(/g/g,""),new x.RegExp(e,t+"g")},e.firstMatch=function(e,t){return e.lastIndex=0,e.exec(t)},e.test=function(e,t){return e.lastIndex=0,e.test(t)},e.matcher=function(e,t){return e.lastIndex=0,{re:e,input:t}},e}();t.RegExpWrapper=L;var F=function(){function e(){}return e.next=function(e){return e.re.exec(e.input)},e}();t.RegExpMatcherWrapper=F;var W=function(){function e(){}return e.apply=function(e,t){return e.apply(null,t)},e}();t.FunctionWrapper=W,t.looseIdentical=P,t.getMapKey=w,t.normalizeBlank=R,t.normalizeBool=E,t.isJsObject=O,t.print=S;var U=function(){function e(){}return e.parse=function(e){return x.JSON.parse(e)},e.stringify=function(e){return x.JSON.stringify(e,null,2)},e}();t.Json=U;var H=function(){function e(){}return e.create=function(e,n,r,i,o,s,a){return void 0===n&&(n=1),void 0===r&&(r=1),void 0===i&&(i=0),void 0===o&&(o=0),void 0===s&&(s=0),void 0===a&&(a=0),new t.Date(e,n-1,r,i,o,s,a)},e.fromISOString=function(e){return new t.Date(e)},e.fromMillis=function(e){return new t.Date(e)},e.toMillis=function(e){return e.getTime()},e.now=function(){return new t.Date},e.toJson=function(e){return e.toJSON()},e}();t.DateWrapper=H,t.setValueOnPath=D;var q=null;t.getSymbolIterator=T}).call(t,function(){return this}())},function(e,t,n){function r(e){for(var n in e)t.hasOwnProperty(n)||(t[n]=e[n])}var i=n(7);t.InjectMetadata=i.InjectMetadata,t.OptionalMetadata=i.OptionalMetadata,t.InjectableMetadata=i.InjectableMetadata,t.SelfMetadata=i.SelfMetadata,t.HostMetadata=i.HostMetadata,t.SkipSelfMetadata=i.SkipSelfMetadata,t.DependencyMetadata=i.DependencyMetadata,r(n(8));var o=n(10);t.forwardRef=o.forwardRef,t.resolveForwardRef=o.resolveForwardRef;var s=n(11);t.Injector=s.Injector;var a=n(13);t.Binding=a.Binding,t.ProviderBuilder=a.ProviderBuilder,t.ResolvedFactory=a.ResolvedFactory,t.Dependency=a.Dependency,t.bind=a.bind,t.Provider=a.Provider,t.provide=a.provide;var c=n(19);t.Key=c.Key,t.TypeLiteral=c.TypeLiteral;var u=n(21);t.NoProviderError=u.NoProviderError,t.AbstractProviderError=u.AbstractProviderError,t.CyclicDependencyError=u.CyclicDependencyError,t.InstantiationError=u.InstantiationError,t.InvalidProviderError=u.InvalidProviderError,t.NoAnnotationError=u.NoAnnotationError,t.OutOfBoundsError=u.OutOfBoundsError;var p=n(22);t.OpaqueToken=p.OpaqueToken},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(5),s=function(){function e(e){this.token=e}return e.prototype.toString=function(){return"@Inject("+o.stringify(this.token)+")"},e=r([o.CONST(),i("design:paramtypes",[Object])],e)}();t.InjectMetadata=s;var a=function(){function e(){}return e.prototype.toString=function(){return"@Optional()"},e=r([o.CONST(),i("design:paramtypes",[])],e)}();t.OptionalMetadata=a;var c=function(){function e(){}return Object.defineProperty(e.prototype,"token",{get:function(){return null},enumerable:!0,configurable:!0}),e=r([o.CONST(),i("design:paramtypes",[])],e)}();t.DependencyMetadata=c;var u=function(){function e(){}return e=r([o.CONST(),i("design:paramtypes",[])],e)}();t.InjectableMetadata=u;var p=function(){function e(){}return e.prototype.toString=function(){return"@Self()"},e=r([o.CONST(),i("design:paramtypes",[])],e)}();t.SelfMetadata=p;var l=function(){function e(){}return e.prototype.toString=function(){return"@SkipSelf()"},e=r([o.CONST(),i("design:paramtypes",[])],e)}();t.SkipSelfMetadata=l;var h=function(){function e(){}return e.prototype.toString=function(){return"@Host()"},e=r([o.CONST(),i("design:paramtypes",[])],e)}();t.HostMetadata=h},function(e,t,n){var r=n(7),i=n(9);t.Inject=i.makeParamDecorator(r.InjectMetadata),t.Optional=i.makeParamDecorator(r.OptionalMetadata),t.Injectable=i.makeDecorator(r.InjectableMetadata),t.Self=i.makeParamDecorator(r.SelfMetadata),t.Host=i.makeParamDecorator(r.HostMetadata),t.SkipSelf=i.makeParamDecorator(r.SkipSelfMetadata)},function(e,t,n){function r(e){return u.isFunction(e)&&e.hasOwnProperty("annotation")&&(e=e.annotation),e}function i(e,t){if(e===Object||e===String||e===Function||e===Number||e===Array)throw new Error("Can not use native "+u.stringify(e)+" as constructor");if(u.isFunction(e))return e;if(e instanceof Array){var n=e,i=e[e.length-1];if(!u.isFunction(i))throw new Error("Last position of Class method array must be Function in key "+t+" was '"+u.stringify(i)+"'");var o=n.length-1;if(o!=i.length)throw new Error("Number of annotations ("+o+") does not match number of arguments ("+i.length+") in the function: "+u.stringify(i));for(var s=[],a=0,c=n.length-1;c>a;a++){var l=[];s.push(l);var h=n[a];if(h instanceof Array)for(var f=0;f0&&(this.provider0=t[0].provider,this.keyId0=t[0].getKeyId(),this.visibility0=t[0].visibility),n>1&&(this.provider1=t[1].provider,this.keyId1=t[1].getKeyId(),this.visibility1=t[1].visibility),n>2&&(this.provider2=t[2].provider,this.keyId2=t[2].getKeyId(),this.visibility2=t[2].visibility),n>3&&(this.provider3=t[3].provider,this.keyId3=t[3].getKeyId(),this.visibility3=t[3].visibility),n>4&&(this.provider4=t[4].provider,this.keyId4=t[4].getKeyId(),this.visibility4=t[4].visibility),n>5&&(this.provider5=t[5].provider,this.keyId5=t[5].getKeyId(),this.visibility5=t[5].visibility),n>6&&(this.provider6=t[6].provider,this.keyId6=t[6].getKeyId(),this.visibility6=t[6].visibility),n>7&&(this.provider7=t[7].provider,this.keyId7=t[7].getKeyId(),this.visibility7=t[7].visibility),n>8&&(this.provider8=t[8].provider,this.keyId8=t[8].getKeyId(),this.visibility8=t[8].visibility),n>9&&(this.provider9=t[9].provider,this.keyId9=t[9].getKeyId(),this.visibility9=t[9].visibility)}return e.prototype.getProviderAtIndex=function(e){if(0==e)return this.provider0;if(1==e)return this.provider1;if(2==e)return this.provider2;if(3==e)return this.provider3;if(4==e)return this.provider4;if(5==e)return this.provider5;if(6==e)return this.provider6;if(7==e)return this.provider7;if(8==e)return this.provider8;if(9==e)return this.provider9;throw new a.OutOfBoundsError(e)},e.prototype.createInjectorStrategy=function(e){return new v(e,this)},e}();t.ProtoInjectorInlineStrategy=f;var d=function(){function e(e,t){var n=t.length;this.providers=o.ListWrapper.createFixedSize(n),this.keyIds=o.ListWrapper.createFixedSize(n),this.visibilities=o.ListWrapper.createFixedSize(n);for(var r=0;n>r;r++)this.providers[r]=t[r].provider,this.keyIds[r]=t[r].getKeyId(),this.visibilities[r]=t[r].visibility}return e.prototype.getProviderAtIndex=function(e){if(0>e||e>=this.providers.length)throw new a.OutOfBoundsError(e);return this.providers[e]},e.prototype.createInjectorStrategy=function(e){return new m(this,e)},e}();t.ProtoInjectorDynamicStrategy=d;var y=function(){function e(e){this.numberOfProviders=e.length,this._strategy=e.length>l?new d(this,e):new f(this,e)}return e.prototype.getProviderAtIndex=function(e){return this._strategy.getProviderAtIndex(e)},e}();t.ProtoInjector=y;var v=function(){function e(e,n){this.injector=e,this.protoStrategy=n,this.obj0=t.UNDEFINED,this.obj1=t.UNDEFINED,this.obj2=t.UNDEFINED,this.obj3=t.UNDEFINED,this.obj4=t.UNDEFINED,this.obj5=t.UNDEFINED,this.obj6=t.UNDEFINED,this.obj7=t.UNDEFINED,this.obj8=t.UNDEFINED,this.obj9=t.UNDEFINED}return e.prototype.resetConstructionCounter=function(){this.injector._constructionCounter=0},e.prototype.instantiateProvider=function(e,t){return this.injector._new(e,t)},e.prototype.attach=function(e,t){var n=this.injector;n._parent=e,n._isHost=t},e.prototype.getObjByKeyId=function(e,n){var i=this.protoStrategy,o=this.injector;return i.keyId0===e&&r(i.visibility0,n)?(this.obj0===t.UNDEFINED&&(this.obj0=o._new(i.provider0,i.visibility0)),this.obj0):i.keyId1===e&&r(i.visibility1,n)?(this.obj1===t.UNDEFINED&&(this.obj1=o._new(i.provider1,i.visibility1)),this.obj1):i.keyId2===e&&r(i.visibility2,n)?(this.obj2===t.UNDEFINED&&(this.obj2=o._new(i.provider2,i.visibility2)),this.obj2):i.keyId3===e&&r(i.visibility3,n)?(this.obj3===t.UNDEFINED&&(this.obj3=o._new(i.provider3,i.visibility3)),this.obj3):i.keyId4===e&&r(i.visibility4,n)?(this.obj4===t.UNDEFINED&&(this.obj4=o._new(i.provider4,i.visibility4)),this.obj4):i.keyId5===e&&r(i.visibility5,n)?(this.obj5===t.UNDEFINED&&(this.obj5=o._new(i.provider5,i.visibility5)),this.obj5):i.keyId6===e&&r(i.visibility6,n)?(this.obj6===t.UNDEFINED&&(this.obj6=o._new(i.provider6,i.visibility6)),this.obj6):i.keyId7===e&&r(i.visibility7,n)?(this.obj7===t.UNDEFINED&&(this.obj7=o._new(i.provider7,i.visibility7)),this.obj7):i.keyId8===e&&r(i.visibility8,n)?(this.obj8===t.UNDEFINED&&(this.obj8=o._new(i.provider8,i.visibility8)),this.obj8):i.keyId9===e&&r(i.visibility9,n)?(this.obj9===t.UNDEFINED&&(this.obj9=o._new(i.provider9,i.visibility9)),this.obj9):t.UNDEFINED},e.prototype.getObjAtIndex=function(e){if(0==e)return this.obj0;if(1==e)return this.obj1;if(2==e)return this.obj2;if(3==e)return this.obj3;if(4==e)return this.obj4;if(5==e)return this.obj5;if(6==e)return this.obj6;if(7==e)return this.obj7;if(8==e)return this.obj8;if(9==e)return this.obj9;throw new a.OutOfBoundsError(e)},e.prototype.getMaxNumberOfObjects=function(){return l},e}();t.InjectorInlineStrategy=v;var m=function(){function e(e,n){this.protoStrategy=e,this.injector=n,this.objs=o.ListWrapper.createFixedSize(e.providers.length),o.ListWrapper.fill(this.objs,t.UNDEFINED)}return e.prototype.resetConstructionCounter=function(){this.injector._constructionCounter=0},e.prototype.instantiateProvider=function(e,t){return this.injector._new(e,t)},e.prototype.attach=function(e,t){var n=this.injector;n._parent=e,n._isHost=t},e.prototype.getObjByKeyId=function(e,n){for(var i=this.protoStrategy,o=0;oe||e>=this.objs.length)throw new a.OutOfBoundsError(e);return this.objs[e]},e.prototype.getMaxNumberOfObjects=function(){return this.objs.length},e}();t.InjectorDynamicStrategy=m;var g=function(){function e(e,t){this.provider=e,this.visibility=t}return e.prototype.getKeyId=function(){return this.provider.key.id},e}();t.ProviderWithVisibility=g;var _=function(){function e(e,t,n,r){void 0===t&&(t=null),void 0===n&&(n=null),void 0===r&&(r=null),this._depProvider=n,this._debugContext=r,this._isHost=!1,this._constructionCounter=0,this._proto=e,this._parent=t,this._strategy=e._strategy.createInjectorStrategy(this)}return e.resolve=function(e){return s.resolveProviders(e)},e.resolveAndCreate=function(t){var n=e.resolve(t);return e.fromResolvedProviders(n)},e.fromResolvedProviders=function(t){var n=t.map(function(e){return new g(e,h.Public)}),r=new y(n);return new e(r,null,null)},e.fromResolvedBindings=function(t){return e.fromResolvedProviders(t)},e.prototype.debugContext=function(){return this._debugContext()},e.prototype.get=function(e){return this._getByKey(u.Key.get(e),null,null,!1,h.PublicAndPrivate)},e.prototype.getOptional=function(e){return this._getByKey(u.Key.get(e),null,null,!0,h.PublicAndPrivate)},e.prototype.getAt=function(e){return this._strategy.getObjAtIndex(e)},Object.defineProperty(e.prototype,"parent",{get:function(){return this._parent},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"internalStrategy",{get:function(){return this._strategy},enumerable:!0,configurable:!0}),e.prototype.resolveAndCreateChild=function(t){var n=e.resolve(t);return this.createChildFromResolved(n)},e.prototype.createChildFromResolved=function(t){var n=t.map(function(e){return new g(e,h.Public)}),r=new y(n),i=new e(r,null,null);return i._parent=this,i},e.prototype.resolveAndInstantiate=function(t){return this.instantiateResolved(e.resolve([t])[0])},e.prototype.instantiateResolved=function(e){return this._instantiateProvider(e,h.PublicAndPrivate)},e.prototype._new=function(e,t){if(this._constructionCounter++>this._strategy.getMaxNumberOfObjects())throw new a.CyclicDependencyError(this,e.key);return this._instantiateProvider(e,t)},e.prototype._instantiateProvider=function(e,t){if(e.multiProvider){for(var n=o.ListWrapper.createFixedSize(e.resolvedFactories.length),r=0;r0?this._getByDependency(e,E[0],n):null,i=O>1?this._getByDependency(e,E[1],n):null,o=O>2?this._getByDependency(e,E[2],n):null,s=O>3?this._getByDependency(e,E[3],n):null,c=O>4?this._getByDependency(e,E[4],n):null,u=O>5?this._getByDependency(e,E[5],n):null,p=O>6?this._getByDependency(e,E[6],n):null,l=O>7?this._getByDependency(e,E[7],n):null,h=O>8?this._getByDependency(e,E[8],n):null,f=O>9?this._getByDependency(e,E[9],n):null,d=O>10?this._getByDependency(e,E[10],n):null,y=O>11?this._getByDependency(e,E[11],n):null,v=O>12?this._getByDependency(e,E[12],n):null,m=O>13?this._getByDependency(e,E[13],n):null,g=O>14?this._getByDependency(e,E[14],n):null,_=O>15?this._getByDependency(e,E[15],n):null,b=O>16?this._getByDependency(e,E[16],n):null,C=O>17?this._getByDependency(e,E[17],n):null,P=O>18?this._getByDependency(e,E[18],n):null,w=O>19?this._getByDependency(e,E[19],n):null}catch(S){throw(S instanceof a.AbstractProviderError||S instanceof a.InstantiationError)&&S.addKey(this,e.key),S}var D;try{switch(O){case 0:D=R();break;case 1:D=R(r);break;case 2:D=R(r,i);break;case 3:D=R(r,i,o);break;case 4:D=R(r,i,o,s);break;case 5:D=R(r,i,o,s,c);break;case 6:D=R(r,i,o,s,c,u);break;case 7:D=R(r,i,o,s,c,u,p);break;case 8:D=R(r,i,o,s,c,u,p,l);break;case 9:D=R(r,i,o,s,c,u,p,l,h);break;case 10:D=R(r,i,o,s,c,u,p,l,h,f);break;case 11:D=R(r,i,o,s,c,u,p,l,h,f,d);break;case 12:D=R(r,i,o,s,c,u,p,l,h,f,d,y);break;case 13:D=R(r,i,o,s,c,u,p,l,h,f,d,y,v);break;case 14:D=R(r,i,o,s,c,u,p,l,h,f,d,y,v,m);break;case 15:D=R(r,i,o,s,c,u,p,l,h,f,d,y,v,m,g);break;case 16:D=R(r,i,o,s,c,u,p,l,h,f,d,y,v,m,g,_);break;case 17:D=R(r,i,o,s,c,u,p,l,h,f,d,y,v,m,g,_,b);break;case 18:D=R(r,i,o,s,c,u,p,l,h,f,d,y,v,m,g,_,b,C);break;case 19:D=R(r,i,o,s,c,u,p,l,h,f,d,y,v,m,g,_,b,C,P);break;case 20:D=R(r,i,o,s,c,u,p,l,h,f,d,y,v,m,g,_,b,C,P,w)}}catch(S){throw new a.InstantiationError(this,S,S.stack,e.key)}return D},e.prototype._getByDependency=function(e,n,r){var i=c.isPresent(this._depProvider)?this._depProvider.getDependency(this,e,n):t.UNDEFINED;return i!==t.UNDEFINED?i:this._getByKey(n.key,n.lowerBoundVisibility,n.upperBoundVisibility,n.optional,r)},e.prototype._getByKey=function(e,t,n,r,i){return e===b?this:n instanceof p.SelfMetadata?this._getByKeySelf(e,r,i):n instanceof p.HostMetadata?this._getByKeyHost(e,r,i,t):this._getByKeyDefault(e,r,i,t)},e.prototype._throwOrNull=function(e,t){if(t)return null;throw new a.NoProviderError(this,e)},e.prototype._getByKeySelf=function(e,n,r){var i=this._strategy.getObjByKeyId(e.id,r);return i!==t.UNDEFINED?i:this._throwOrNull(e,n)},e.prototype._getByKeyHost=function(e,n,r,i){var o=this;if(i instanceof p.SkipSelfMetadata){if(o._isHost)return this._getPrivateDependency(e,n,o);o=o._parent}for(;null!=o;){var s=o._strategy.getObjByKeyId(e.id,r);if(s!==t.UNDEFINED)return s;if(c.isPresent(o._parent)&&o._isHost)return this._getPrivateDependency(e,n,o);o=o._parent}return this._throwOrNull(e,n)},e.prototype._getPrivateDependency=function(e,n,r){var i=r._parent._strategy.getObjByKeyId(e.id,h.Private);return i!==t.UNDEFINED?i:this._throwOrNull(e,n)},e.prototype._getByKeyDefault=function(e,n,r,i){var o=this;for(i instanceof p.SkipSelfMetadata&&(r=o._isHost?h.PublicAndPrivate:h.Public,o=o._parent);null!=o;){var s=o._strategy.getObjByKeyId(e.id,r);if(s!==t.UNDEFINED)return s;r=o._isHost?h.PublicAndPrivate:h.Public,o=o._parent}return this._throwOrNull(e,n)},Object.defineProperty(e.prototype,"displayName",{get:function(){return"Injector(providers: ["+i(this,function(e){return' "'+e.key.displayName+'" '}).join(", ")+"])"},enumerable:!0,configurable:!0}),e.prototype.toString=function(){return this.displayName},e}();t.Injector=_;var b=u.Key.get(_)},function(e,t,n){function r(e){return o.isJsObject(e)?o.isArray(e)||!(e instanceof t.Map)&&o.getSymbolIterator()in e:!1}function i(e,t){if(o.isArray(e))for(var n=0;n-1?(e.splice(n,1),!0):!1},e.clear=function(e){e.length=0},e.isEmpty=function(e){return 0==e.length},e.fill=function(e,t,n,r){void 0===n&&(n=0),void 0===r&&(r=null),e.fill(t,n,null===r?e.length:r)},e.equals=function(e,t){if(e.length!=t.length)return!1;for(var n=0;nr&&(n=s,r=a)}}return n},e}();t.ListWrapper=h,t.isListLikeIterable=r,t.iterateListLike=i;var f=function(){var e=new t.Set([1,2,3]);return 3===e.size?function(e){return new t.Set(e)}:function(e){var n=new t.Set(e);if(n.size!==e.length)for(var r=0;ro?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},m=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},g=n(5),_=n(14),b=n(12),C=n(16),P=n(19),w=n(7),R=n(21),E=n(10),O=function(){function e(e,t,n,r,i){this.key=e,this.optional=t,this.lowerBoundVisibility=n,this.upperBoundVisibility=r,this.properties=i}return e.fromKey=function(t){return new e(t,!1,null,null,[])},e}();t.Dependency=O;var S=g.CONST_EXPR([]),D=function(){function e(e,t){var n=t.useClass,r=t.useValue,i=t.useExisting,o=t.useFactory,s=t.deps,a=t.multi;this.token=e,this.useClass=n,this.useValue=r,this.useExisting=i,this.useFactory=o,this.dependencies=s,this._multi=a}return Object.defineProperty(e.prototype,"multi",{get:function(){return g.normalizeBool(this._multi)},enumerable:!0,configurable:!0}),e=v([g.CONST(),m("design:paramtypes",[Object,Object])],e)}();t.Provider=D;var T=function(e){function t(t,n){var r=n.toClass,i=n.toValue,o=n.toAlias,s=n.toFactory,a=n.deps,c=n.multi;e.call(this,t,{useClass:r,useValue:i,useExisting:o,useFactory:s,deps:a,multi:c})}return y(t,e),Object.defineProperty(t.prototype,"toClass",{get:function(){return this.useClass},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"toAlias",{get:function(){return this.useExisting},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"toFactory",{get:function(){return this.useFactory},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"toValue",{get:function(){return this.useValue},enumerable:!0,configurable:!0}),t=v([g.CONST(),m("design:paramtypes",[Object,Object])],t)}(D);t.Binding=T;var A=function(){function e(e,t,n){this.key=e,this.resolvedFactories=t,this.multiProvider=n}return Object.defineProperty(e.prototype,"resolvedFactory",{get:function(){return this.resolvedFactories[0]},enumerable:!0,configurable:!0}),e}();t.ResolvedProvider_=A;var I=function(){function e(e,t){this.factory=e,this.dependencies=t}return e}();t.ResolvedFactory=I,t.bind=r,t.provide=i;var x=function(){function e(e){this.token=e}return e.prototype.toClass=function(e){if(!g.isType(e))throw new _.BaseException('Trying to create a class provider but "'+g.stringify(e)+'" is not a class!');return new D(this.token,{useClass:e})},e.prototype.toValue=function(e){return new D(this.token,{useValue:e})},e.prototype.toAlias=function(e){if(g.isBlank(e))throw new _.BaseException("Can not alias "+g.stringify(this.token)+" to a blank value!");return new D(this.token,{useExisting:e})},e.prototype.toFactory=function(e,t){if(!g.isFunction(e))throw new _.BaseException('Trying to create a factory provider but "'+g.stringify(e)+'" is not a function!');return new D(this.token,{useFactory:e,deps:t})},e}();t.ProviderBuilder=x,t.resolveFactory=o,t.resolveProvider=s,t.resolveProviders=a;var N=function(){function e(e,t){this.key=e,this.resolvedFactory=t}return e}()},function(e,t,n){function r(e){return new TypeError(e)}function i(){throw new c("unimplemented")}var o=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},s=n(15),a=n(15);t.ExceptionHandler=a.ExceptionHandler;var c=function(e){function t(t){void 0===t&&(t="--"),e.call(this,t),this.message=t,this.stack=new Error(t).stack}return o(t,e),t.prototype.toString=function(){return this.message},t}(Error);t.BaseException=c;var u=function(e){function t(t,n,r,i){e.call(this,t),this._wrapperMessage=t,this._originalException=n,this._originalStack=r,this._context=i,this._wrapperStack=new Error(t).stack}return o(t,e),Object.defineProperty(t.prototype,"wrapperMessage",{get:function(){return this._wrapperMessage},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"wrapperStack",{get:function(){return this._wrapperStack},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"originalException",{get:function(){return this._originalException},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"originalStack",{get:function(){return this._originalStack},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"context",{get:function(){return this._context},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"message",{get:function(){return s.ExceptionHandler.exceptionToString(this)},enumerable:!0,configurable:!0}),t.prototype.toString=function(){return this.message},t}(Error);t.WrappedException=u,t.makeTypeError=r,t.unimplemented=i},function(e,t,n){var r=n(5),i=n(14),o=n(12),s=function(){function e(){this.res=[]}return e.prototype.log=function(e){this.res.push(e)},e.prototype.logError=function(e){this.res.push(e)},e.prototype.logGroup=function(e){this.res.push(e)},e.prototype.logGroupEnd=function(){},e}(),a=function(){function e(e,t){void 0===t&&(t=!0),this._logger=e,this._rethrowException=t}return e.exceptionToString=function(t,n,r){void 0===n&&(n=null),void 0===r&&(r=null);var i=new s,o=new e(i,!1);return o.call(t,n,r),i.res.join("\n")},e.prototype.call=function(e,t,n){void 0===t&&(t=null),void 0===n&&(n=null);var i=this._findOriginalException(e),o=this._findOriginalStack(e),s=this._findContext(e);if(this._logger.logGroup("EXCEPTION: "+this._extractMessage(e)),r.isPresent(t)&&r.isBlank(o)&&(this._logger.logError("STACKTRACE:"),this._logger.logError(this._longStackTrace(t))),r.isPresent(n)&&this._logger.logError("REASON: "+n),r.isPresent(i)&&this._logger.logError("ORIGINAL EXCEPTION: "+this._extractMessage(i)),r.isPresent(o)&&(this._logger.logError("ORIGINAL STACKTRACE:"),this._logger.logError(this._longStackTrace(o))),r.isPresent(s)&&(this._logger.logError("ERROR CONTEXT:"),this._logger.logError(s)),this._logger.logGroupEnd(),this._rethrowException)throw e},e.prototype._extractMessage=function(e){return e instanceof i.WrappedException?e.wrapperMessage:e.toString()},e.prototype._longStackTrace=function(e){return o.isListLikeIterable(e)?e.join("\n\n-----async gap-----\n"):e.toString()},e.prototype._findContext=function(e){try{return e instanceof i.WrappedException?r.isPresent(e.context)?e.context:this._findContext(e.originalException):null}catch(t){return null}},e.prototype._findOriginalException=function(e){if(!(e instanceof i.WrappedException))return null;for(var t=e.originalException;t instanceof i.WrappedException&&r.isPresent(t.originalException);)t=t.originalException;return t},e.prototype._findOriginalStack=function(e){if(!(e instanceof i.WrappedException))return null;for(var t=e,n=e.originalStack;t instanceof i.WrappedException&&r.isPresent(t.originalException);)t=t.originalException,t instanceof i.WrappedException&&r.isPresent(t.originalException)&&(n=t.originalStack);return n},e}();t.ExceptionHandler=a},function(e,t,n){var r=n(17),i=n(17);t.Reflector=i.Reflector,t.ReflectionInfo=i.ReflectionInfo;var o=n(18);t.reflector=new r.Reflector(new o.ReflectionCapabilities)},function(e,t,n){function r(e,t){s.StringMapWrapper.forEach(t,function(t,n){return e.set(n,t)})}var i=n(5),o=n(14),s=n(12),a=function(){function e(e,t,n,r,i){this.annotations=e,this.parameters=t,this.factory=n,this.interfaces=r,this.propMetadata=i}return e}();t.ReflectionInfo=a;var c=function(){function e(e){this._injectableInfo=new s.Map,this._getters=new s.Map,this._setters=new s.Map,this._methods=new s.Map,this._usedKeys=null,this.reflectionCapabilities=e}return e.prototype.isReflectionEnabled=function(){return this.reflectionCapabilities.isReflectionEnabled()},e.prototype.trackUsage=function(){this._usedKeys=new s.Set},e.prototype.listUnusedKeys=function(){var e=this;if(null==this._usedKeys)throw new o.BaseException("Usage tracking is disabled");var t=s.MapWrapper.keys(this._injectableInfo);return t.filter(function(t){return!s.SetWrapper.has(e._usedKeys,t)})},e.prototype.registerFunction=function(e,t){this._injectableInfo.set(e,t)},e.prototype.registerType=function(e,t){this._injectableInfo.set(e,t)},e.prototype.registerGetters=function(e){r(this._getters,e)},e.prototype.registerSetters=function(e){r(this._setters,e)},e.prototype.registerMethods=function(e){r(this._methods,e)},e.prototype.factory=function(e){if(this._containsReflectionInfo(e)){var t=this._getReflectionInfo(e).factory;return i.isPresent(t)?t:null}return this.reflectionCapabilities.factory(e)},e.prototype.parameters=function(e){if(this._injectableInfo.has(e)){var t=this._getReflectionInfo(e).parameters;return i.isPresent(t)?t:[]}return this.reflectionCapabilities.parameters(e)},e.prototype.annotations=function(e){if(this._injectableInfo.has(e)){var t=this._getReflectionInfo(e).annotations;return i.isPresent(t)?t:[]}return this.reflectionCapabilities.annotations(e)},e.prototype.propMetadata=function(e){if(this._injectableInfo.has(e)){var t=this._getReflectionInfo(e).propMetadata;return i.isPresent(t)?t:{}}return this.reflectionCapabilities.propMetadata(e)},e.prototype.interfaces=function(e){if(this._injectableInfo.has(e)){var t=this._getReflectionInfo(e).interfaces;return i.isPresent(t)?t:[]}return this.reflectionCapabilities.interfaces(e)},e.prototype.getter=function(e){return this._getters.has(e)?this._getters.get(e):this.reflectionCapabilities.getter(e)},e.prototype.setter=function(e){return this._setters.has(e)?this._setters.get(e):this.reflectionCapabilities.setter(e)},e.prototype.method=function(e){return this._methods.has(e)?this._methods.get(e):this.reflectionCapabilities.method(e)},e.prototype._getReflectionInfo=function(e){return i.isPresent(this._usedKeys)&&this._usedKeys.add(e),this._injectableInfo.get(e)},e.prototype._containsReflectionInfo=function(e){return this._injectableInfo.has(e)},e.prototype.importUri=function(e){return this.reflectionCapabilities.importUri(e)},e}();t.Reflector=c},function(e,t,n){var r=n(5),i=n(14),o=function(){function e(e){this._reflect=r.isPresent(e)?e:r.global.Reflect}return e.prototype.isReflectionEnabled=function(){return!0},e.prototype.factory=function(e){switch(e.length){case 0:return function(){return new e};case 1:return function(t){return new e(t)};case 2:return function(t,n){return new e(t,n)};case 3:return function(t,n,r){return new e(t,n,r)};case 4:return function(t,n,r,i){return new e(t,n,r,i)};case 5:return function(t,n,r,i,o){return new e(t,n,r,i,o)};case 6:return function(t,n,r,i,o,s){return new e(t,n,r,i,o,s)};case 7:return function(t,n,r,i,o,s,a){return new e(t,n,r,i,o,s,a)};case 8:return function(t,n,r,i,o,s,a,c){return new e(t,n,r,i,o,s,a,c)};case 9:return function(t,n,r,i,o,s,a,c,u){return new e(t,n,r,i,o,s,a,c,u)};case 10:return function(t,n,r,i,o,s,a,c,u,p){return new e(t,n,r,i,o,s,a,c,u,p)};case 11:return function(t,n,r,i,o,s,a,c,u,p,l){return new e(t,n,r,i,o,s,a,c,u,p,l)};case 12:return function(t,n,r,i,o,s,a,c,u,p,l,h){return new e(t,n,r,i,o,s,a,c,u,p,l,h)};case 13:return function(t,n,r,i,o,s,a,c,u,p,l,h,f){return new e(t,n,r,i,o,s,a,c,u,p,l,h,f)};case 14:return function(t,n,r,i,o,s,a,c,u,p,l,h,f,d){return new e(t,n,r,i,o,s,a,c,u,p,l,h,f,d)};case 15:return function(t,n,r,i,o,s,a,c,u,p,l,h,f,d,y){return new e(t,n,r,i,o,s,a,c,u,p,l,h,f,d,y)};case 16:return function(t,n,r,i,o,s,a,c,u,p,l,h,f,d,y,v){return new e(t,n,r,i,o,s,a,c,u,p,l,h,f,d,y,v)};case 17:return function(t,n,r,i,o,s,a,c,u,p,l,h,f,d,y,v,m){return new e(t,n,r,i,o,s,a,c,u,p,l,h,f,d,y,v,m)};case 18:return function(t,n,r,i,o,s,a,c,u,p,l,h,f,d,y,v,m,g){return new e(t,n,r,i,o,s,a,c,u,p,l,h,f,d,y,v,m,g)};case 19:return function(t,n,r,i,o,s,a,c,u,p,l,h,f,d,y,v,m,g,_){return new e(t,n,r,i,o,s,a,c,u,p,l,h,f,d,y,v,m,g,_)};case 20:return function(t,n,r,i,o,s,a,c,u,p,l,h,f,d,y,v,m,g,_,b){return new e(t,n,r,i,o,s,a,c,u,p,l,h,f,d,y,v,m,g,_,b)}}throw new Error("Cannot create a factory for '"+r.stringify(e)+"' because its constructor has more than 20 arguments")},e.prototype._zipTypesAndAnnotaions=function(e,t){var n;n="undefined"==typeof e?new Array(t.length):new Array(e.length);for(var i=0;i1){var t=r(s.ListWrapper.reversed(e)),n=t.map(function(e){return a.stringify(e.token)});return" ("+n.join(" -> ")+")"}return""}var o=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},s=n(12),a=n(5),c=n(14),u=function(e){function t(t,n,r){e.call(this,"DI Exception"),this.keys=[n],this.injectors=[t],this.constructResolvingMessage=r,this.message=this.constructResolvingMessage(this.keys)}return o(t,e),t.prototype.addKey=function(e,t){this.injectors.push(e),this.keys.push(t),this.message=this.constructResolvingMessage(this.keys)},Object.defineProperty(t.prototype,"context",{get:function(){return this.injectors[this.injectors.length-1].debugContext()},enumerable:!0,configurable:!0}),t}(c.BaseException);t.AbstractProviderError=u;var p=function(e){function t(t,n){e.call(this,t,n,function(e){var t=a.stringify(s.ListWrapper.first(e).token);return"No provider for "+t+"!"+i(e)})}return o(t,e),t}(u);t.NoProviderError=p;var l=function(e){function t(t,n){e.call(this,t,n,function(e){return"Cannot instantiate cyclic dependency!"+i(e)})}return o(t,e),t}(u);t.CyclicDependencyError=l;var h=function(e){function t(t,n,r,i){e.call(this,"DI Exception",n,r,null),this.keys=[i],this.injectors=[t]}return o(t,e),t.prototype.addKey=function(e,t){this.injectors.push(e),this.keys.push(t)},Object.defineProperty(t.prototype,"wrapperMessage",{get:function(){var e=a.stringify(s.ListWrapper.first(this.keys).token);return"Error during instantiation of "+e+"!"+i(this.keys)+"."},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"causeKey",{get:function(){return this.keys[0]},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"context",{get:function(){return this.injectors[this.injectors.length-1].debugContext()},enumerable:!0,configurable:!0}),t}(c.WrappedException);t.InstantiationError=h;var f=function(e){function t(t){e.call(this,"Invalid provider - only instances of Provider and Type are allowed, got: "+t.toString())}return o(t,e),t}(c.BaseException);t.InvalidProviderError=f;var d=function(e){function t(n,r){e.call(this,t._genMessage(n,r))}return o(t,e),t._genMessage=function(e,t){for(var n=[],r=0,i=t.length;i>r;r++){var o=t[r];a.isBlank(o)||0==o.length?n.push("?"):n.push(o.map(a.stringify).join(" "))}return"Cannot resolve all parameters for "+a.stringify(e)+"("+n.join(", ")+"). Make sure they all have valid type or annotations."},t}(c.BaseException);t.NoAnnotationError=d;var y=function(e){function t(t){e.call(this,"Index "+t+" is out-of-bounds.")}return o(t,e),t}(c.BaseException);t.OutOfBoundsError=y;var v=function(e){function t(t,n){e.call(this,"Cannot mix multi providers and regular providers, got: "+t.toString()+" "+n.toString())}return o(t,e),t}(c.BaseException);t.MixingMultiProvidersWithRegularProvidersError=v},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(5),s=function(){function e(e){this._desc=e}return e.prototype.toString=function(){return"Token "+this._desc},e=r([o.CONST(),i("design:paramtypes",[String])],e)}();t.OpaqueToken=s},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=n(5),a=n(7),c=n(24),u=function(e){function t(t){var n=void 0===t?{}:t,r=n.selector,i=n.inputs,o=n.outputs,s=n.properties,a=n.events,c=n.host,u=n.bindings,p=n.providers,l=n.exportAs,h=n.queries;e.call(this),this.selector=r,this._inputs=i,this._properties=s,this._outputs=o,this._events=a,this.host=c,this.exportAs=l,this.queries=h,this._providers=p,this._bindings=u}return r(t,e),Object.defineProperty(t.prototype,"inputs",{get:function(){return s.isPresent(this._properties)&&this._properties.length>0?this._properties:this._inputs},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"properties",{get:function(){return this.inputs},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"outputs",{get:function(){return s.isPresent(this._events)&&this._events.length>0?this._events:this._outputs},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"events",{get:function(){return this.outputs},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"providers",{get:function(){return s.isPresent(this._bindings)&&this._bindings.length>0?this._bindings:this._providers},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"bindings",{get:function(){return this.providers},enumerable:!0,configurable:!0}),t=i([s.CONST(),o("design:paramtypes",[Object])],t)}(a.InjectableMetadata);t.DirectiveMetadata=u;var p=function(e){function t(t){var n=void 0===t?{}:t,r=n.selector,i=n.inputs,o=n.outputs,s=n.properties,a=n.events,u=n.host,p=n.exportAs,l=n.moduleId,h=n.bindings,f=n.providers,d=n.viewBindings,y=n.viewProviders,v=n.changeDetection,m=void 0===v?c.ChangeDetectionStrategy.Default:v,g=n.queries,_=n.templateUrl,b=n.template,C=n.styleUrls,P=n.styles,w=n.directives,R=n.pipes,E=n.encapsulation;e.call(this,{selector:r,inputs:i,outputs:o,properties:s,events:a,host:u,exportAs:p,bindings:h,providers:f,queries:g}),this.changeDetection=m,this._viewProviders=y,this._viewBindings=d,this.templateUrl=_,this.template=b,this.styleUrls=C,this.styles=P,this.directives=w,this.pipes=R,this.encapsulation=E,this.moduleId=l}return r(t,e),Object.defineProperty(t.prototype,"viewProviders",{get:function(){return s.isPresent(this._viewBindings)&&this._viewBindings.length>0?this._viewBindings:this._viewProviders},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"viewBindings",{get:function(){return this.viewProviders},enumerable:!0,configurable:!0}),t=i([s.CONST(),o("design:paramtypes",[Object])],t)}(u);t.ComponentMetadata=p;var l=function(e){function t(t){var n=t.name,r=t.pure;e.call(this),this.name=n,this._pure=r}return r(t,e),Object.defineProperty(t.prototype,"pure",{get:function(){return s.isPresent(this._pure)?this._pure:!0},enumerable:!0,configurable:!0}),t=i([s.CONST(),o("design:paramtypes",[Object])],t)}(a.InjectableMetadata);t.PipeMetadata=l;var h=function(){function e(e){this.bindingPropertyName=e}return e=i([s.CONST(),o("design:paramtypes",[String])],e)}();t.InputMetadata=h;var f=function(){function e(e){this.bindingPropertyName=e}return e=i([s.CONST(),o("design:paramtypes",[String])],e)}();t.OutputMetadata=f;var d=function(){function e(e){this.hostPropertyName=e}return e=i([s.CONST(),o("design:paramtypes",[String])],e)}();t.HostBindingMetadata=d;var y=function(){function e(e,t){this.eventName=e,this.args=t}return e=i([s.CONST(),o("design:paramtypes",[String,Array])],e)}();t.HostListenerMetadata=y},function(e,t,n){var r=n(25);t.ChangeDetectionStrategy=r.ChangeDetectionStrategy,t.ExpressionChangedAfterItHasBeenCheckedException=r.ExpressionChangedAfterItHasBeenCheckedException,t.ChangeDetectionError=r.ChangeDetectionError,t.ChangeDetectorRef=r.ChangeDetectorRef,t.WrappedValue=r.WrappedValue,t.SimpleChange=r.SimpleChange,t.IterableDiffers=r.IterableDiffers,t.KeyValueDiffers=r.KeyValueDiffers},function(e,t,n){var r=n(26),i=n(27),o=n(28),s=n(29),a=n(5),c=n(30);t.ASTWithSource=c.ASTWithSource,t.AST=c.AST,t.AstTransformer=c.AstTransformer,t.PropertyRead=c.PropertyRead,t.LiteralArray=c.LiteralArray,t.ImplicitReceiver=c.ImplicitReceiver;var u=n(31);t.Lexer=u.Lexer;var p=n(32);t.Parser=p.Parser;var l=n(33);t.Locals=l.Locals;var h=n(34);t.DehydratedException=h.DehydratedException,t.ExpressionChangedAfterItHasBeenCheckedException=h.ExpressionChangedAfterItHasBeenCheckedException,t.ChangeDetectionError=h.ChangeDetectionError;var f=n(35);t.ChangeDetectorDefinition=f.ChangeDetectorDefinition,t.DebugContext=f.DebugContext,t.ChangeDetectorGenConfig=f.ChangeDetectorGenConfig;var d=n(36);t.ChangeDetectionStrategy=d.ChangeDetectionStrategy,t.CHANGE_DETECTION_STRATEGY_VALUES=d.CHANGE_DETECTION_STRATEGY_VALUES;var y=n(37);t.DynamicProtoChangeDetector=y.DynamicProtoChangeDetector;var v=n(51);t.JitProtoChangeDetector=v.JitProtoChangeDetector;var m=n(40);t.BindingRecord=m.BindingRecord,t.BindingTarget=m.BindingTarget;var g=n(41);t.DirectiveIndex=g.DirectiveIndex,t.DirectiveRecord=g.DirectiveRecord;var _=n(42);t.DynamicChangeDetector=_.DynamicChangeDetector;var b=n(44);t.ChangeDetectorRef=b.ChangeDetectorRef;var C=n(26);t.IterableDiffers=C.IterableDiffers;var P=n(28);t.KeyValueDiffers=P.KeyValueDiffers;var w=n(38);t.WrappedValue=w.WrappedValue,t.SimpleChange=w.SimpleChange,t.keyValDiff=a.CONST_EXPR([a.CONST_EXPR(new s.DefaultKeyValueDifferFactory)]),t.iterableDiff=a.CONST_EXPR([a.CONST_EXPR(new i.DefaultIterableDifferFactory)]),t.defaultIterableDiffers=a.CONST_EXPR(new r.IterableDiffers(t.iterableDiff)),t.defaultKeyValueDiffers=a.CONST_EXPR(new o.KeyValueDiffers(t.keyValDiff))},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(5),s=n(14),a=n(12),c=n(6),u=function(){function e(e){this.factories=e}return e.create=function(t,n){if(o.isPresent(n)){var r=a.ListWrapper.clone(n.factories);return t=t.concat(r),new e(t)}return new e(t)},e.extend=function(t){return new c.Provider(e,{useFactory:function(n){if(o.isBlank(n))throw new s.BaseException("Cannot extend IterableDiffers without a parent injector");return e.create(t,n)},deps:[[e,new c.SkipSelfMetadata,new c.OptionalMetadata]]})},e.prototype.find=function(e){var t=this.factories.find(function(t){return t.supports(e)});if(o.isPresent(t))return t;throw new s.BaseException("Cannot find a differ supporting object '"+e+"'")},e=r([c.Injectable(),o.CONST(),i("design:paramtypes",[Array])],e)}();t.IterableDiffers=u},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s); -return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(5),s=n(14),a=n(12),c=n(5),u=function(){function e(){}return e.prototype.supports=function(e){return a.isListLikeIterable(e)},e.prototype.create=function(e){return new p},e=r([o.CONST(),i("design:paramtypes",[])],e)}();t.DefaultIterableDifferFactory=u;var p=function(){function e(){this._collection=null,this._length=null,this._linkedRecords=null,this._unlinkedRecords=null,this._previousItHead=null,this._itHead=null,this._itTail=null,this._additionsHead=null,this._additionsTail=null,this._movesHead=null,this._movesTail=null,this._removalsHead=null,this._removalsTail=null}return Object.defineProperty(e.prototype,"collection",{get:function(){return this._collection},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"length",{get:function(){return this._length},enumerable:!0,configurable:!0}),e.prototype.forEachItem=function(e){var t;for(t=this._itHead;null!==t;t=t._next)e(t)},e.prototype.forEachPreviousItem=function(e){var t;for(t=this._previousItHead;null!==t;t=t._nextPrevious)e(t)},e.prototype.forEachAddedItem=function(e){var t;for(t=this._additionsHead;null!==t;t=t._nextAdded)e(t)},e.prototype.forEachMovedItem=function(e){var t;for(t=this._movesHead;null!==t;t=t._nextMoved)e(t)},e.prototype.forEachRemovedItem=function(e){var t;for(t=this._removalsHead;null!==t;t=t._nextRemoved)e(t)},e.prototype.diff=function(e){if(c.isBlank(e)&&(e=[]),!a.isListLikeIterable(e))throw new s.BaseException("Error trying to diff '"+e+"'");return this.check(e)?this:null},e.prototype.onDestroy=function(){},e.prototype.check=function(e){var t=this;this._reset();var n,r,i=this._itHead,o=!1;if(c.isArray(e)){var s=e;for(this._length=e.length,n=0;n"+c.stringify(this.currentIndex)+"]"},e}();t.CollectionChangeRecord=l;var h=function(){function e(){this._head=null,this._tail=null}return e.prototype.add=function(e){null===this._head?(this._head=this._tail=e,e._nextDup=null,e._prevDup=null):(this._tail._nextDup=e,e._prevDup=this._tail,e._nextDup=null,this._tail=e)},e.prototype.get=function(e,t){var n;for(n=this._head;null!==n;n=n._nextDup)if((null===t||to?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(5),s=n(14),a=n(12),c=n(6),u=function(){function e(e){this.factories=e}return e.create=function(t,n){if(o.isPresent(n)){var r=a.ListWrapper.clone(n.factories);return t=t.concat(r),new e(t)}return new e(t)},e.extend=function(t){return new c.Provider(e,{useFactory:function(n){if(o.isBlank(n))throw new s.BaseException("Cannot extend KeyValueDiffers without a parent injector");return e.create(t,n)},deps:[[e,new c.SkipSelfMetadata,new c.OptionalMetadata]]})},e.prototype.find=function(e){var t=this.factories.find(function(t){return t.supports(e)});if(o.isPresent(t))return t;throw new s.BaseException("Cannot find a differ supporting object '"+e+"'")},e=r([c.Injectable(),o.CONST(),i("design:paramtypes",[Array])],e)}();t.KeyValueDiffers=u},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(12),s=n(5),a=n(14),c=function(){function e(){}return e.prototype.supports=function(e){return e instanceof Map||s.isJsObject(e)},e.prototype.create=function(e){return new u},e=r([s.CONST(),i("design:paramtypes",[])],e)}();t.DefaultKeyValueDifferFactory=c;var u=function(){function e(){this._records=new Map,this._mapHead=null,this._previousMapHead=null,this._changesHead=null,this._changesTail=null,this._additionsHead=null,this._additionsTail=null,this._removalsHead=null,this._removalsTail=null}return Object.defineProperty(e.prototype,"isDirty",{get:function(){return null!==this._additionsHead||null!==this._changesHead||null!==this._removalsHead},enumerable:!0,configurable:!0}),e.prototype.forEachItem=function(e){var t;for(t=this._mapHead;null!==t;t=t._next)e(t)},e.prototype.forEachPreviousItem=function(e){var t;for(t=this._previousMapHead;null!==t;t=t._nextPrevious)e(t)},e.prototype.forEachChangedItem=function(e){var t;for(t=this._changesHead;null!==t;t=t._nextChanged)e(t)},e.prototype.forEachAddedItem=function(e){var t;for(t=this._additionsHead;null!==t;t=t._nextAdded)e(t)},e.prototype.forEachRemovedItem=function(e){var t;for(t=this._removalsHead;null!==t;t=t._nextRemoved)e(t)},e.prototype.diff=function(e){if(s.isBlank(e)&&(e=o.MapWrapper.createFromPairs([])),!(e instanceof Map||s.isJsObject(e)))throw new a.BaseException("Error trying to diff '"+e+"'");return this.check(e)?this:null},e.prototype.onDestroy=function(){},e.prototype.check=function(e){var t=this;this._reset();var n=this._records,r=this._mapHead,i=null,o=null,a=!1;return this._forEach(e,function(e,c){var u;null!==r&&c===r.key?(u=r,s.looseIdentical(e,r.currentValue)||(r.previousValue=r.currentValue,r.currentValue=e,t._addToChanges(r))):(a=!0,null!==r&&(r._next=null,t._removeFromSeq(i,r),t._addToRemovals(r)),n.has(c)?u=n.get(c):(u=new p(c),n.set(c,u),u.currentValue=e,t._addToAdditions(u))),a&&(t._isInRemovals(u)&&t._removeFromRemovals(u),null==o?t._mapHead=u:o._next=u),i=r,o=u,r=null===r?null:r._next}),this._truncate(i,r),this.isDirty},e.prototype._reset=function(){if(this.isDirty){var e;for(e=this._previousMapHead=this._mapHead;null!==e;e=e._next)e._nextPrevious=e._next;for(e=this._changesHead;null!==e;e=e._nextChanged)e.previousValue=e.currentValue;for(e=this._additionsHead;null!=e;e=e._nextAdded)e.previousValue=e.currentValue;this._changesHead=this._changesTail=null,this._additionsHead=this._additionsTail=null,this._removalsHead=this._removalsTail=null}},e.prototype._truncate=function(e,t){for(;null!==t;){null===e?this._mapHead=null:e._next=null;var n=t._next;this._addToRemovals(t),e=t,t=n}for(var r=this._removalsHead;null!==r;r=r._nextRemoved)r.previousValue=r.currentValue,r.currentValue=null,this._records["delete"](r.key)},e.prototype._isInRemovals=function(e){return e===this._removalsHead||null!==e._nextRemoved||null!==e._prevRemoved},e.prototype._addToRemovals=function(e){null===this._removalsHead?this._removalsHead=this._removalsTail=e:(this._removalsTail._nextRemoved=e,e._prevRemoved=this._removalsTail,this._removalsTail=e)},e.prototype._removeFromSeq=function(e,t){var n=t._next;null===e?this._mapHead=n:e._next=n},e.prototype._removeFromRemovals=function(e){var t=e._prevRemoved,n=e._nextRemoved;null===t?this._removalsHead=n:t._nextRemoved=n,null===n?this._removalsTail=t:n._prevRemoved=t,e._prevRemoved=e._nextRemoved=null},e.prototype._addToAdditions=function(e){null===this._additionsHead?this._additionsHead=this._additionsTail=e:(this._additionsTail._nextAdded=e,this._additionsTail=e)},e.prototype._addToChanges=function(e){null===this._changesHead?this._changesHead=this._changesTail=e:(this._changesTail._nextChanged=e,this._changesTail=e)},e.prototype.toString=function(){var e,t=[],n=[],r=[],i=[],o=[];for(e=this._mapHead;null!==e;e=e._next)t.push(s.stringify(e));for(e=this._previousMapHead;null!==e;e=e._nextPrevious)n.push(s.stringify(e));for(e=this._changesHead;null!==e;e=e._nextChanged)r.push(s.stringify(e));for(e=this._additionsHead;null!==e;e=e._nextAdded)i.push(s.stringify(e));for(e=this._removalsHead;null!==e;e=e._nextRemoved)o.push(s.stringify(e));return"map: "+t.join(", ")+"\nprevious: "+n.join(", ")+"\nadditions: "+i.join(", ")+"\nchanges: "+r.join(", ")+"\nremovals: "+o.join(", ")+"\n"},e.prototype._forEach=function(e,t){e instanceof Map?e.forEach(t):o.StringMapWrapper.forEach(e,t)},e}();t.DefaultKeyValueDiffer=u;var p=function(){function e(e){this.key=e,this.previousValue=null,this.currentValue=null,this._nextPrevious=null,this._next=null,this._nextAdded=null,this._nextRemoved=null,this._prevRemoved=null,this._nextChanged=null}return e.prototype.toString=function(){return s.looseIdentical(this.previousValue,this.currentValue)?s.stringify(this.key):s.stringify(this.key)+"["+s.stringify(this.previousValue)+"->"+s.stringify(this.currentValue)+"]"},e}();t.KVChangeRecord=p},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=n(12),o=function(){function e(){}return e.prototype.visit=function(e){return null},e.prototype.toString=function(){return"AST"},e}();t.AST=o;var s=function(e){function t(t,n,r){e.call(this),this.prefix=t,this.uninterpretedExpression=n,this.location=r}return r(t,e),t.prototype.visit=function(e){return e.visitQuote(this)},t.prototype.toString=function(){return"Quote"},t}(o);t.Quote=s;var a=function(e){function t(){e.apply(this,arguments)}return r(t,e),t.prototype.visit=function(e){},t}(o);t.EmptyExpr=a;var c=function(e){function t(){e.apply(this,arguments)}return r(t,e),t.prototype.visit=function(e){return e.visitImplicitReceiver(this)},t}(o);t.ImplicitReceiver=c;var u=function(e){function t(t){e.call(this),this.expressions=t}return r(t,e),t.prototype.visit=function(e){return e.visitChain(this)},t}(o);t.Chain=u;var p=function(e){function t(t,n,r){e.call(this),this.condition=t,this.trueExp=n,this.falseExp=r}return r(t,e),t.prototype.visit=function(e){return e.visitConditional(this)},t}(o);t.Conditional=p;var l=function(e){function t(t,n,r){e.call(this),this.receiver=t,this.name=n,this.getter=r}return r(t,e),t.prototype.visit=function(e){return e.visitPropertyRead(this)},t}(o);t.PropertyRead=l;var h=function(e){function t(t,n,r,i){e.call(this),this.receiver=t,this.name=n,this.setter=r,this.value=i}return r(t,e),t.prototype.visit=function(e){return e.visitPropertyWrite(this)},t}(o);t.PropertyWrite=h;var f=function(e){function t(t,n,r){e.call(this),this.receiver=t,this.name=n,this.getter=r}return r(t,e),t.prototype.visit=function(e){return e.visitSafePropertyRead(this)},t}(o);t.SafePropertyRead=f;var d=function(e){function t(t,n){e.call(this),this.obj=t,this.key=n}return r(t,e),t.prototype.visit=function(e){return e.visitKeyedRead(this)},t}(o);t.KeyedRead=d;var y=function(e){function t(t,n,r){e.call(this),this.obj=t,this.key=n,this.value=r}return r(t,e),t.prototype.visit=function(e){return e.visitKeyedWrite(this)},t}(o);t.KeyedWrite=y;var v=function(e){function t(t,n,r){e.call(this),this.exp=t,this.name=n,this.args=r}return r(t,e),t.prototype.visit=function(e){return e.visitPipe(this)},t}(o);t.BindingPipe=v;var m=function(e){function t(t){e.call(this),this.value=t}return r(t,e),t.prototype.visit=function(e){return e.visitLiteralPrimitive(this)},t}(o);t.LiteralPrimitive=m;var g=function(e){function t(t){e.call(this),this.expressions=t}return r(t,e),t.prototype.visit=function(e){return e.visitLiteralArray(this)},t}(o);t.LiteralArray=g;var _=function(e){function t(t,n){e.call(this),this.keys=t,this.values=n}return r(t,e),t.prototype.visit=function(e){return e.visitLiteralMap(this)},t}(o);t.LiteralMap=_;var b=function(e){function t(t,n){e.call(this),this.strings=t,this.expressions=n}return r(t,e),t.prototype.visit=function(e){return e.visitInterpolation(this)},t}(o);t.Interpolation=b;var C=function(e){function t(t,n,r){e.call(this),this.operation=t,this.left=n,this.right=r}return r(t,e),t.prototype.visit=function(e){return e.visitBinary(this)},t}(o);t.Binary=C;var P=function(e){function t(t){e.call(this),this.expression=t}return r(t,e),t.prototype.visit=function(e){return e.visitPrefixNot(this)},t}(o);t.PrefixNot=P;var w=function(e){function t(t,n,r,i){e.call(this),this.receiver=t,this.name=n,this.fn=r,this.args=i}return r(t,e),t.prototype.visit=function(e){return e.visitMethodCall(this)},t}(o);t.MethodCall=w;var R=function(e){function t(t,n,r,i){e.call(this),this.receiver=t,this.name=n,this.fn=r,this.args=i}return r(t,e),t.prototype.visit=function(e){return e.visitSafeMethodCall(this)},t}(o);t.SafeMethodCall=R;var E=function(e){function t(t,n){e.call(this),this.target=t,this.args=n}return r(t,e),t.prototype.visit=function(e){return e.visitFunctionCall(this)},t}(o);t.FunctionCall=E;var O=function(e){function t(t,n,r){e.call(this),this.ast=t,this.source=n,this.location=r}return r(t,e),t.prototype.visit=function(e){return this.ast.visit(e)},t.prototype.toString=function(){return this.source+" in "+this.location},t}(o);t.ASTWithSource=O;var S=function(){function e(e,t,n,r){this.key=e,this.keyIsVar=t,this.name=n,this.expression=r}return e}();t.TemplateBinding=S;var D=function(){function e(){}return e.prototype.visitBinary=function(e){return e.left.visit(this),e.right.visit(this),null},e.prototype.visitChain=function(e){return this.visitAll(e.expressions)},e.prototype.visitConditional=function(e){return e.condition.visit(this),e.trueExp.visit(this),e.falseExp.visit(this),null},e.prototype.visitPipe=function(e){return e.exp.visit(this),this.visitAll(e.args),null},e.prototype.visitFunctionCall=function(e){return e.target.visit(this),this.visitAll(e.args),null},e.prototype.visitImplicitReceiver=function(e){return null},e.prototype.visitInterpolation=function(e){return this.visitAll(e.expressions)},e.prototype.visitKeyedRead=function(e){return e.obj.visit(this),e.key.visit(this),null},e.prototype.visitKeyedWrite=function(e){return e.obj.visit(this),e.key.visit(this),e.value.visit(this),null},e.prototype.visitLiteralArray=function(e){return this.visitAll(e.expressions)},e.prototype.visitLiteralMap=function(e){return this.visitAll(e.values)},e.prototype.visitLiteralPrimitive=function(e){return null},e.prototype.visitMethodCall=function(e){return e.receiver.visit(this),this.visitAll(e.args)},e.prototype.visitPrefixNot=function(e){return e.expression.visit(this),null},e.prototype.visitPropertyRead=function(e){return e.receiver.visit(this),null},e.prototype.visitPropertyWrite=function(e){return e.receiver.visit(this),e.value.visit(this),null},e.prototype.visitSafePropertyRead=function(e){return e.receiver.visit(this),null},e.prototype.visitSafeMethodCall=function(e){return e.receiver.visit(this),this.visitAll(e.args)},e.prototype.visitAll=function(e){var t=this;return e.forEach(function(e){return e.visit(t)}),null},e.prototype.visitQuote=function(e){return null},e}();t.RecursiveAstVisitor=D;var T=function(){function e(){}return e.prototype.visitImplicitReceiver=function(e){return e},e.prototype.visitInterpolation=function(e){return new b(e.strings,this.visitAll(e.expressions))},e.prototype.visitLiteralPrimitive=function(e){return new m(e.value)},e.prototype.visitPropertyRead=function(e){return new l(e.receiver.visit(this),e.name,e.getter)},e.prototype.visitPropertyWrite=function(e){return new h(e.receiver.visit(this),e.name,e.setter,e.value)},e.prototype.visitSafePropertyRead=function(e){return new f(e.receiver.visit(this),e.name,e.getter)},e.prototype.visitMethodCall=function(e){return new w(e.receiver.visit(this),e.name,e.fn,this.visitAll(e.args))},e.prototype.visitSafeMethodCall=function(e){return new R(e.receiver.visit(this),e.name,e.fn,this.visitAll(e.args))},e.prototype.visitFunctionCall=function(e){return new E(e.target.visit(this),this.visitAll(e.args))},e.prototype.visitLiteralArray=function(e){return new g(this.visitAll(e.expressions))},e.prototype.visitLiteralMap=function(e){return new _(e.keys,this.visitAll(e.values))},e.prototype.visitBinary=function(e){return new C(e.operation,e.left.visit(this),e.right.visit(this))},e.prototype.visitPrefixNot=function(e){return new P(e.expression.visit(this))},e.prototype.visitConditional=function(e){return new p(e.condition.visit(this),e.trueExp.visit(this),e.falseExp.visit(this))},e.prototype.visitPipe=function(e){return new v(e.exp.visit(this),e.name,this.visitAll(e.args))},e.prototype.visitKeyedRead=function(e){return new d(e.obj.visit(this),e.key.visit(this))},e.prototype.visitKeyedWrite=function(e){return new y(e.obj.visit(this),e.key.visit(this),e.value.visit(this))},e.prototype.visitAll=function(e){for(var t=i.ListWrapper.createFixedSize(e.length),n=0;n=t.$TAB&&e<=t.$SPACE||e==H}function p(e){return e>=k&&U>=e||e>=T&&I>=e||e==N||e==t.$$}function l(e){if(0==e.length)return!1;var n=new G(e);if(!p(n.peek))return!1;for(n.advance();n.peek!==t.$EOF;){if(!h(n.peek))return!1;n.advance()}return!0}function h(e){return e>=k&&U>=e||e>=T&&I>=e||e>=S&&D>=e||e==N||e==t.$$}function f(e){return e>=S&&D>=e}function d(e){return e==j||e==A}function y(e){return e==t.$MINUS||e==t.$PLUS}function v(e){switch(e){case M:return t.$LF;case V:return t.$FF;case B:return t.$CR;case L:return t.$TAB;case W:return t.$VTAB;default:return e}}var m=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},g=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},_=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},b=n(8),C=n(12),P=n(5),w=n(14);!function(e){e[e.Character=0]="Character",e[e.Identifier=1]="Identifier",e[e.Keyword=2]="Keyword",e[e.String=3]="String",e[e.Operator=4]="Operator",e[e.Number=5]="Number"}(t.TokenType||(t.TokenType={}));var R=t.TokenType,E=function(){function e(){}return e.prototype.tokenize=function(e){for(var t=new G(e),n=[],r=t.scanToken();null!=r;)n.push(r),r=t.scanToken();return n},e=g([b.Injectable(),_("design:paramtypes",[])],e)}();t.Lexer=E;var O=function(){function e(e,t,n,r){this.index=e,this.type=t,this.numValue=n,this.strValue=r}return e.prototype.isCharacter=function(e){return this.type==R.Character&&this.numValue==e},e.prototype.isNumber=function(){return this.type==R.Number},e.prototype.isString=function(){return this.type==R.String},e.prototype.isOperator=function(e){return this.type==R.Operator&&this.strValue==e},e.prototype.isIdentifier=function(){return this.type==R.Identifier},e.prototype.isKeyword=function(){return this.type==R.Keyword},e.prototype.isKeywordVar=function(){return this.type==R.Keyword&&"var"==this.strValue},e.prototype.isKeywordNull=function(){return this.type==R.Keyword&&"null"==this.strValue},e.prototype.isKeywordUndefined=function(){return this.type==R.Keyword&&"undefined"==this.strValue},e.prototype.isKeywordTrue=function(){return this.type==R.Keyword&&"true"==this.strValue},e.prototype.isKeywordFalse=function(){return this.type==R.Keyword&&"false"==this.strValue},e.prototype.toNumber=function(){return this.type==R.Number?this.numValue:-1},e.prototype.toString=function(){switch(this.type){case R.Character:case R.Identifier:case R.Keyword:case R.Operator:case R.String:return this.strValue;case R.Number:return this.numValue.toString();default:return null}},e}();t.Token=O,t.EOF=new O(-1,R.Character,0,""),t.$EOF=0,t.$TAB=9,t.$LF=10,t.$VTAB=11,t.$FF=12,t.$CR=13,t.$SPACE=32,t.$BANG=33,t.$DQ=34,t.$HASH=35,t.$$=36,t.$PERCENT=37,t.$AMPERSAND=38,t.$SQ=39,t.$LPAREN=40,t.$RPAREN=41,t.$STAR=42,t.$PLUS=43,t.$COMMA=44,t.$MINUS=45,t.$PERIOD=46,t.$SLASH=47,t.$COLON=58,t.$SEMICOLON=59,t.$LT=60,t.$EQ=61,t.$GT=62,t.$QUESTION=63;var S=48,D=57,T=65,A=69,I=90;t.$LBRACKET=91,t.$BACKSLASH=92,t.$RBRACKET=93;var x=94,N=95,k=97,j=101,V=102,M=110,B=114,L=116,F=117,W=118,U=122;t.$LBRACE=123,t.$BAR=124,t.$RBRACE=125;var H=160,q=function(e){function t(t){e.call(this),this.message=t}return m(t,e),t.prototype.toString=function(){return this.message},t}(w.BaseException);t.ScannerError=q;var G=function(){function e(e){this.input=e,this.peek=0,this.index=-1,this.length=e.length,this.advance()}return e.prototype.advance=function(){this.peek=++this.index>=this.length?t.$EOF:P.StringWrapper.charCodeAt(this.input,this.index)},e.prototype.scanToken=function(){for(var e=this.input,n=this.length,i=this.peek,o=this.index;i<=t.$SPACE;){if(++o>=n){i=t.$EOF;break}i=P.StringWrapper.charCodeAt(e,o)}if(this.peek=i,this.index=o,o>=n)return null;if(p(i))return this.scanIdentifier();if(f(i))return this.scanNumber(o);var s=o;switch(i){case t.$PERIOD:return this.advance(),f(this.peek)?this.scanNumber(s):r(s,t.$PERIOD);case t.$LPAREN:case t.$RPAREN:case t.$LBRACE:case t.$RBRACE:case t.$LBRACKET:case t.$RBRACKET:case t.$COMMA:case t.$COLON:case t.$SEMICOLON:return this.scanCharacter(s,i);case t.$SQ:case t.$DQ:return this.scanString();case t.$HASH:case t.$PLUS:case t.$MINUS:case t.$STAR:case t.$SLASH:case t.$PERCENT:case x:return this.scanOperator(s,P.StringWrapper.fromCharCode(i));case t.$QUESTION:return this.scanComplexOperator(s,"?",t.$PERIOD,".");case t.$LT:case t.$GT:return this.scanComplexOperator(s,P.StringWrapper.fromCharCode(i),t.$EQ,"=");case t.$BANG:case t.$EQ:return this.scanComplexOperator(s,P.StringWrapper.fromCharCode(i),t.$EQ,"=",t.$EQ,"=");case t.$AMPERSAND:return this.scanComplexOperator(s,"&",t.$AMPERSAND,"&");case t.$BAR:return this.scanComplexOperator(s,"|",t.$BAR,"|");case H:for(;u(this.peek);)this.advance();return this.scanToken()}return this.error("Unexpected character ["+P.StringWrapper.fromCharCode(i)+"]",0),null},e.prototype.scanCharacter=function(e,t){return assert(this.peek==t),this.advance(),r(e,t)},e.prototype.scanOperator=function(e,t){return assert(this.peek==P.StringWrapper.charCodeAt(t,0)),assert(C.SetWrapper.has(z,t)),this.advance(),s(e,t)},e.prototype.scanComplexOperator=function(e,t,n,r,i,o){assert(this.peek==P.StringWrapper.charCodeAt(t,0)),this.advance();var a=t;return this.peek==n&&(this.advance(),a+=r),P.isPresent(i)&&this.peek==i&&(this.advance(),a+=o),assert(C.SetWrapper.has(z,a)),s(e,a)},e.prototype.scanIdentifier=function(){assert(p(this.peek));var e=this.index;for(this.advance();h(this.peek);)this.advance();var t=this.input.substring(e,this.index);return C.SetWrapper.has(K,t)?o(e,t):i(e,t)},e.prototype.scanNumber=function(e){assert(f(this.peek));var n=this.index===e;for(this.advance();;){if(f(this.peek));else if(this.peek==t.$PERIOD)n=!1;else{if(!d(this.peek))break;this.advance(),y(this.peek)&&this.advance(),f(this.peek)||this.error("Invalid exponent",-1),n=!1}this.advance()}var r=this.input.substring(e,this.index),i=n?P.NumberWrapper.parseIntAutoRadix(r):P.NumberWrapper.parseFloat(r);return c(e,i)},e.prototype.scanString=function(){assert(this.peek==t.$SQ||this.peek==t.$DQ);var e=this.index,n=this.peek;this.advance();for(var r,i=this.index,o=this.input;this.peek!=n;)if(this.peek==t.$BACKSLASH){null==r&&(r=new P.StringJoiner),r.add(o.substring(i,this.index)),this.advance();var s;if(this.peek==F){var c=o.substring(this.index+1,this.index+5);try{s=P.NumberWrapper.parseInt(c,16)}catch(u){this.error("Invalid unicode escape [\\u"+c+"]",0)}for(var p=0;5>p;p++)this.advance()}else s=v(this.peek),this.advance();r.add(P.StringWrapper.fromCharCode(s)),i=this.index}else this.peek==t.$EOF?this.error("Unterminated quote",0):this.advance();var l=o.substring(i,this.index);this.advance();var h=l;return null!=r&&(r.add(l),h=r.toString()),a(e,h)},e.prototype.error=function(e,t){var n=this.index+t;throw new q("Lexer Error: "+e+" at column "+n+" in expression ["+this.input+"]")},e}();t.isIdentifier=l;var z=C.SetWrapper.createFromList(["+","-","*","/","%","^","=","==","!=","===","!==","<",">","<=",">=","&&","||","&","|","!","?","#","?."]),K=C.SetWrapper.createFromList(["var","null","undefined","true","false","if","else"])},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=n(8),a=n(5),c=n(14),u=n(12),p=n(31),l=n(16),h=n(30),f=new h.ImplicitReceiver,d=/\{\{(.*?)\}\}/g,y=function(e){function t(t,n,r,i){e.call(this,"Parser Error: "+t+" "+r+" ["+n+"] in "+i)}return r(t,e),t}(c.BaseException),v=function(){function e(e,t){void 0===t&&(t=null),this._lexer=e,this._reflector=a.isPresent(t)?t:l.reflector}return e.prototype.parseAction=function(e,t){this._checkNoInterpolation(e,t);var n=this._lexer.tokenize(e),r=new m(e,t,n,this._reflector,!0).parseChain();return new h.ASTWithSource(r,e,t)},e.prototype.parseBinding=function(e,t){var n=this._parseBindingAst(e,t);return new h.ASTWithSource(n,e,t)},e.prototype.parseSimpleBinding=function(e,t){var n=this._parseBindingAst(e,t);if(!g.check(n))throw new y("Host binding expression can only contain field access and constants",e,t);return new h.ASTWithSource(n,e,t)},e.prototype._parseBindingAst=function(e,t){var n=this._parseQuote(e,t);if(a.isPresent(n))return n;this._checkNoInterpolation(e,t);var r=this._lexer.tokenize(e); -return new m(e,t,r,this._reflector,!1).parseChain()},e.prototype._parseQuote=function(e,t){if(a.isBlank(e))return null;var n=e.indexOf(":");if(-1==n)return null;var r=e.substring(0,n).trim();if(!p.isIdentifier(r))return null;var i=e.substring(n+1);return new h.Quote(r,i,t)},e.prototype.parseTemplateBindings=function(e,t){var n=this._lexer.tokenize(e);return new m(e,t,n,this._reflector,!1).parseTemplateBindings()},e.prototype.parseInterpolation=function(e,t){var n=a.StringWrapper.split(e,d);if(n.length<=1)return null;for(var r=[],i=[],o=0;o0))throw new y("Blank expressions are not allowed in interpolated strings",e,"at column "+this._findInterpolationErrorColumn(n,o)+" in",t);var c=this._lexer.tokenize(s),u=new m(e,t,c,this._reflector,!1).parseChain();i.push(u)}}return new h.ASTWithSource(new h.Interpolation(r,i),e,t)},e.prototype.wrapLiteralPrimitive=function(e,t){return new h.ASTWithSource(new h.LiteralPrimitive(e),e,t)},e.prototype._checkNoInterpolation=function(e,t){var n=a.StringWrapper.split(e,d);if(n.length>1)throw new y("Got interpolation ({{}}) where expression was expected",e,"at column "+this._findInterpolationErrorColumn(n,1)+" in",t)},e.prototype._findInterpolationErrorColumn=function(e,t){for(var n="",r=0;t>r;r++)n+=r%2===0?e[r]:"{{"+e[r]+"}}";return n.length},e=i([s.Injectable(),o("design:paramtypes",[p.Lexer,l.Reflector])],e)}();t.Parser=v;var m=function(){function e(e,t,n,r,i){this.input=e,this.location=t,this.tokens=n,this.reflector=r,this.parseAction=i,this.index=0}return e.prototype.peek=function(e){var t=this.index+e;return t"))e=new h.Binary(">",e,this.parseAdditive());else if(this.optionalOperator("<="))e=new h.Binary("<=",e,this.parseAdditive());else{if(!this.optionalOperator(">="))return e;e=new h.Binary(">=",e,this.parseAdditive())}},e.prototype.parseAdditive=function(){for(var e=this.parseMultiplicative();;)if(this.optionalOperator("+"))e=new h.Binary("+",e,this.parseMultiplicative());else{if(!this.optionalOperator("-"))return e;e=new h.Binary("-",e,this.parseMultiplicative())}},e.prototype.parseMultiplicative=function(){for(var e=this.parsePrefix();;)if(this.optionalOperator("*"))e=new h.Binary("*",e,this.parsePrefix());else if(this.optionalOperator("%"))e=new h.Binary("%",e,this.parsePrefix());else{if(!this.optionalOperator("/"))return e;e=new h.Binary("/",e,this.parsePrefix())}},e.prototype.parsePrefix=function(){return this.optionalOperator("+")?this.parsePrefix():this.optionalOperator("-")?new h.Binary("-",new h.LiteralPrimitive(0),this.parsePrefix()):this.optionalOperator("!")?new h.PrefixNot(this.parsePrefix()):this.parseCallChain()},e.prototype.parseCallChain=function(){for(var e=this.parsePrimary();;)if(this.optionalCharacter(p.$PERIOD))e=this.parseAccessMemberOrMethodCall(e,!1);else if(this.optionalOperator("?."))e=this.parseAccessMemberOrMethodCall(e,!0);else if(this.optionalCharacter(p.$LBRACKET)){var t=this.parsePipe();if(this.expectCharacter(p.$RBRACKET),this.optionalOperator("=")){var n=this.parseConditional();e=new h.KeyedWrite(e,t,n)}else e=new h.KeyedRead(e,t)}else{if(!this.optionalCharacter(p.$LPAREN))return e;var r=this.parseCallArguments();this.expectCharacter(p.$RPAREN),e=new h.FunctionCall(e,r)}},e.prototype.parsePrimary=function(){if(this.optionalCharacter(p.$LPAREN)){var e=this.parsePipe();return this.expectCharacter(p.$RPAREN),e}if(this.next.isKeywordNull()||this.next.isKeywordUndefined())return this.advance(),new h.LiteralPrimitive(null);if(this.next.isKeywordTrue())return this.advance(),new h.LiteralPrimitive(!0);if(this.next.isKeywordFalse())return this.advance(),new h.LiteralPrimitive(!1);if(this.optionalCharacter(p.$LBRACKET)){var t=this.parseExpressionList(p.$RBRACKET);return this.expectCharacter(p.$RBRACKET),new h.LiteralArray(t)}if(this.next.isCharacter(p.$LBRACE))return this.parseLiteralMap();if(this.next.isIdentifier())return this.parseAccessMemberOrMethodCall(f,!1);if(this.next.isNumber()){var n=this.next.toNumber();return this.advance(),new h.LiteralPrimitive(n)}if(this.next.isString()){var r=this.next.toString();return this.advance(),new h.LiteralPrimitive(r)}throw this.index>=this.tokens.length?this.error("Unexpected end of expression: "+this.input):this.error("Unexpected token "+this.next),new c.BaseException("Fell through all cases in parsePrimary")},e.prototype.parseExpressionList=function(e){var t=[];if(!this.next.isCharacter(e))do t.push(this.parsePipe());while(this.optionalCharacter(p.$COMMA));return t},e.prototype.parseLiteralMap=function(){var e=[],t=[];if(this.expectCharacter(p.$LBRACE),!this.optionalCharacter(p.$RBRACE)){do{var n=this.expectIdentifierOrKeywordOrString();e.push(n),this.expectCharacter(p.$COLON),t.push(this.parsePipe())}while(this.optionalCharacter(p.$COMMA));this.expectCharacter(p.$RBRACE)}return new h.LiteralMap(e,t)},e.prototype.parseAccessMemberOrMethodCall=function(e,t){void 0===t&&(t=!1);var n=this.expectIdentifierOrKeyword();if(this.optionalCharacter(p.$LPAREN)){var r=this.parseCallArguments();this.expectCharacter(p.$RPAREN);var i=this.reflector.method(n);return t?new h.SafeMethodCall(e,n,i,r):new h.MethodCall(e,n,i,r)}if(!t){if(this.optionalOperator("=")){this.parseAction||this.error("Bindings cannot contain assignments");var o=this.parseConditional();return new h.PropertyWrite(e,n,this.reflector.setter(n),o)}return new h.PropertyRead(e,n,this.reflector.getter(n))}return this.optionalOperator("=")?(this.error("The '?.' operator cannot be used in the assignment"),null):new h.SafePropertyRead(e,n,this.reflector.getter(n))},e.prototype.parseCallArguments=function(){if(this.next.isCharacter(p.$RPAREN))return[];var e=[];do e.push(this.parsePipe());while(this.optionalCharacter(p.$COMMA));return e},e.prototype.parseBlockContent=function(){this.parseAction||this.error("Binding expression cannot contain chained expression");for(var e=[];this.index":return"operation_greater_then";case"<=":return"operation_less_or_equals_then";case">=":return"operation_greater_or_equals_then";default:throw new h.BaseException("Unsupported operation "+e)}}function c(e){switch(e){case"+":return y.ChangeDetectionUtil.operation_add;case"-":return y.ChangeDetectionUtil.operation_subtract;case"*":return y.ChangeDetectionUtil.operation_multiply;case"/":return y.ChangeDetectionUtil.operation_divide;case"%":return y.ChangeDetectionUtil.operation_remainder;case"==":return y.ChangeDetectionUtil.operation_equals;case"!=":return y.ChangeDetectionUtil.operation_not_equals;case"===":return y.ChangeDetectionUtil.operation_identical;case"!==":return y.ChangeDetectionUtil.operation_not_identical;case"<":return y.ChangeDetectionUtil.operation_less_then;case">":return y.ChangeDetectionUtil.operation_greater_then;case"<=":return y.ChangeDetectionUtil.operation_less_or_equals_then;case">=":return y.ChangeDetectionUtil.operation_greater_or_equals_then;default:throw new h.BaseException("Unsupported operation "+e)}}function u(e){return l.isPresent(e)?""+e:""}function p(e){var t=e.length,n=t>0?e[0]:null,r=t>1?e[1]:null,i=t>2?e[2]:null,o=t>3?e[3]:null,s=t>4?e[4]:null,a=t>5?e[5]:null,c=t>6?e[6]:null,p=t>7?e[7]:null,l=t>8?e[8]:null,f=t>9?e[9]:null;switch(t-1){case 1:return function(e){return n+u(e)+r};case 2:return function(e,t){return n+u(e)+r+u(t)+i};case 3:return function(e,t,s){return n+u(e)+r+u(t)+i+u(s)+o};case 4:return function(e,t,a,c){return n+u(e)+r+u(t)+i+u(a)+o+u(c)+s};case 5:return function(e,t,c,p,l){return n+u(e)+r+u(t)+i+u(c)+o+u(p)+s+u(l)+a};case 6:return function(e,t,p,l,h,f){return n+u(e)+r+u(t)+i+u(p)+o+u(l)+s+u(h)+a+u(f)+c};case 7:return function(e,t,l,h,f,d,y){return n+u(e)+r+u(t)+i+u(l)+o+u(h)+s+u(f)+a+u(d)+c+u(y)+p};case 8:return function(e,t,h,f,d,y,v,m){return n+u(e)+r+u(t)+i+u(h)+o+u(f)+s+u(d)+a+u(y)+c+u(v)+p+u(m)+l};case 9:return function(e,t,h,d,y,v,m,g,_){return n+u(e)+r+u(t)+i+u(h)+o+u(d)+s+u(y)+a+u(v)+c+u(m)+p+u(g)+l+u(_)+f};default:throw new h.BaseException("Does not support more than 9 expressions")}}var l=n(5),h=n(14),f=n(12),d=n(30),y=n(38),v=n(42),m=n(41),g=n(49),_=n(50),b=n(48),C=function(){function e(e){this._definition=e,this._propertyBindingRecords=r(e),this._eventBindingRecords=i(e),this._propertyBindingTargets=this._definition.bindingRecords.map(function(e){return e.target}),this._directiveIndices=this._definition.directiveRecords.map(function(e){return e.directiveIndex})}return e.prototype.instantiate=function(e){return new v.DynamicChangeDetector(this._definition.id,e,this._propertyBindingRecords.length,this._propertyBindingTargets,this._directiveIndices,this._definition.strategy,this._propertyBindingRecords,this._eventBindingRecords,this._definition.directiveRecords,this._definition.genConfig)},e}();t.DynamicProtoChangeDetector=C,t.createPropertyRecords=r,t.createEventRecords=i;var P=function(){function e(){this.records=[]}return e.prototype.add=function(e,t,n){var r=f.ListWrapper.last(this.records);l.isPresent(r)&&r.bindingRecord.directiveRecord==e.directiveRecord&&(r.lastInDirective=!1);var i=this.records.length;this._appendRecords(e,t,n);var o=f.ListWrapper.last(this.records);l.isPresent(o)&&o!==r&&(o.lastInBinding=!0,o.lastInDirective=!0,this._setArgumentToPureFunction(i))},e.prototype._setArgumentToPureFunction=function(e){for(var t=this,n=e;ne},e.operation_greater_then=function(e,t){return e>t},e.operation_less_or_equals_then=function(e,t){return t>=e},e.operation_greater_or_equals_then=function(e,t){return e>=t},e.cond=function(e,t,n){return e?t:n},e.mapFn=function(e){function t(t){for(var n=s.StringMapWrapper.create(),r=0;rt?null:e[t-1]},e.callPipeOnDestroy=function(e){c.implementsOnDestroy(e.pipe)&&e.pipe.ngOnDestroy()},e.bindingTarget=function(e,t,n,r,i){return new u.BindingTarget(e,t,n,r,i)},e.directiveIndex=function(e,t){return new p.DirectiveIndex(e,t)},e.looseNotIdentical=function(e,t){return!i.looseIdentical(e,t)},e.uninitialized=i.CONST_EXPR(new Object),e}();t.ChangeDetectionUtil=m},function(e,t){function n(e){return e.constructor.prototype.ngOnDestroy}t.implementsOnDestroy=n},function(e,t,n){var r=n(5),i="directiveLifecycle",o="native",s="directive",a="elementProperty",c="elementAttribute",u="elementClass",p="elementStyle",l="textNode",h="event",f="hostEvent",d=function(){function e(e,t,n,r,i){this.mode=e,this.elementIndex=t,this.name=n,this.unit=r,this.debug=i}return e.prototype.isDirective=function(){return this.mode===s},e.prototype.isElementProperty=function(){return this.mode===a},e.prototype.isElementAttribute=function(){return this.mode===c},e.prototype.isElementClass=function(){return this.mode===u},e.prototype.isElementStyle=function(){return this.mode===p},e.prototype.isTextNode=function(){return this.mode===l},e}();t.BindingTarget=d;var y=function(){function e(e,t,n,r,i,o,s){this.mode=e,this.target=t,this.implicitReceiver=n,this.ast=r,this.setter=i,this.lifecycleEvent=o,this.directiveRecord=s}return e.prototype.isDirectiveLifecycle=function(){return this.mode===i},e.prototype.callOnChanges=function(){return r.isPresent(this.directiveRecord)&&this.directiveRecord.callOnChanges},e.prototype.isDefaultChangeDetection=function(){return r.isBlank(this.directiveRecord)||this.directiveRecord.isDefaultChangeDetection()},e.createDirectiveDoCheck=function(t){return new e(i,null,0,null,null,"DoCheck",t)},e.createDirectiveOnInit=function(t){return new e(i,null,0,null,null,"OnInit",t)},e.createDirectiveOnChanges=function(t){return new e(i,null,0,null,null,"OnChanges",t)},e.createForDirective=function(t,n,r,i){var o=i.directiveIndex.elementIndex,a=new d(s,o,n,null,t.toString());return new e(s,a,0,t,r,null,i)},e.createForElementProperty=function(t,n,r){var i=new d(a,n,r,null,t.toString());return new e(o,i,0,t,null,null,null)},e.createForElementAttribute=function(t,n,r){var i=new d(c,n,r,null,t.toString());return new e(o,i,0,t,null,null,null)},e.createForElementClass=function(t,n,r){var i=new d(u,n,r,null,t.toString());return new e(o,i,0,t,null,null,null)},e.createForElementStyle=function(t,n,r,i){var s=new d(p,n,r,i,t.toString());return new e(o,s,0,t,null,null,null)},e.createForHostProperty=function(t,n,r){var i=new d(a,t.elementIndex,r,null,n.toString());return new e(o,i,t,n,null,null,null)},e.createForHostAttribute=function(t,n,r){var i=new d(c,t.elementIndex,r,null,n.toString());return new e(o,i,t,n,null,null,null)},e.createForHostClass=function(t,n,r){var i=new d(u,t.elementIndex,r,null,n.toString());return new e(o,i,t,n,null,null,null)},e.createForHostStyle=function(t,n,r,i){var s=new d(p,t.elementIndex,r,i,n.toString());return new e(o,s,t,n,null,null,null)},e.createForTextNode=function(t,n){ -var r=new d(l,n,null,null,t.toString());return new e(o,r,0,t,null,null,null)},e.createForEvent=function(t,n,r){var i=new d(h,r,n,null,t.toString());return new e(h,i,0,t,null,null,null)},e.createForHostEvent=function(t,n,r){var i=r.directiveIndex,o=new d(f,i.elementIndex,n,null,t.toString());return new e(f,o,i,t,null,null,r)},e}();t.BindingRecord=y},function(e,t,n){var r=n(5),i=n(36),o=function(){function e(e,t){this.elementIndex=e,this.directiveIndex=t}return Object.defineProperty(e.prototype,"name",{get:function(){return this.elementIndex+"_"+this.directiveIndex},enumerable:!0,configurable:!0}),e}();t.DirectiveIndex=o;var s=function(){function e(e){var t=void 0===e?{}:e,n=t.directiveIndex,i=t.callAfterContentInit,o=t.callAfterContentChecked,s=t.callAfterViewInit,a=t.callAfterViewChecked,c=t.callOnChanges,u=t.callDoCheck,p=t.callOnInit,l=t.changeDetection;this.directiveIndex=n,this.callAfterContentInit=r.normalizeBool(i),this.callAfterContentChecked=r.normalizeBool(o),this.callOnChanges=r.normalizeBool(c),this.callAfterViewInit=r.normalizeBool(s),this.callAfterViewChecked=r.normalizeBool(a),this.callDoCheck=r.normalizeBool(u),this.callOnInit=r.normalizeBool(p),this.changeDetection=l}return e.prototype.isDefaultChangeDetection=function(){return i.isDefaultChangeDetectionStrategy(this.changeDetection)},e}();t.DirectiveRecord=s},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=n(5),o=n(14),s=n(12),a=n(43),c=n(38),u=n(36),p=n(48),l=function(e){function t(t,n,r,i,o,a,c,u,p,l){e.call(this,t,n,r,i,o,a),this._records=c,this._eventBindings=u,this._directiveRecords=p,this._genConfig=l,this.directives=null;var h=c.length+1;this.values=s.ListWrapper.createFixedSize(h),this.localPipes=s.ListWrapper.createFixedSize(h),this.prevContexts=s.ListWrapper.createFixedSize(h),this.changes=s.ListWrapper.createFixedSize(h),this.dehydrateDirectives(!1)}return r(t,e),t.prototype.handleEventInternal=function(e,t,n){var r=this,i=!1;return this._matchingEventBindings(e,t).forEach(function(e){var t=r._processEventBinding(e,n);t===!1&&(i=!0)}),i},t.prototype._processEventBinding=function(e,t){var n=s.ListWrapper.createFixedSize(e.records.length);n[0]=this.values[0];for(var r=0;r=0;--t){var n=e[t];n.callAfterContentInit&&this.state==u.ChangeDetectorState.NeverChecked&&this._getDirectiveFor(n.directiveIndex).ngAfterContentInit(),n.callAfterContentChecked&&this._getDirectiveFor(n.directiveIndex).ngAfterContentChecked()}},t.prototype.afterViewLifecycleCallbacksInternal=function(){for(var e=this._directiveRecords,t=e.length-1;t>=0;--t){var n=e[t];n.callAfterViewInit&&this.state==u.ChangeDetectorState.NeverChecked&&this._getDirectiveFor(n.directiveIndex).ngAfterViewInit(),n.callAfterViewChecked&&this._getDirectiveFor(n.directiveIndex).ngAfterViewChecked()}},t.prototype._updateDirectiveOrElement=function(t,n){if(i.isBlank(n.directiveRecord))e.prototype.notifyDispatcher.call(this,t.currentValue);else{var r=n.directiveRecord.directiveIndex;n.setter(this._getDirectiveFor(r),t.currentValue)}this._genConfig.logBindingUpdate&&e.prototype.logBindingUpdate.call(this,t.currentValue)},t.prototype._addChange=function(t,n,r){return t.callOnChanges()?e.prototype.addChange.call(this,r,n.previousValue,n.currentValue):r},t.prototype._getDirectiveFor=function(e){return this.directives.getDirectiveFor(e)},t.prototype._getDetectorFor=function(e){return this.directives.getDetectorFor(e)},t.prototype._check=function(e,t,n,r){return e.isPipeRecord()?this._pipeCheck(e,t,n):this._referenceCheck(e,t,n,r)},t.prototype._referenceCheck=function(t,n,r,i){if(this._pureFuncAndArgsDidNotChange(t))return this._setChanged(t,!1),null;var o=this._calculateCurrValue(t,r,i);if(this.strategy===u.ChangeDetectionStrategy.OnPushObserve&&e.prototype.observeValue.call(this,o,t.selfIndex),t.shouldBeChecked()){var s=this._readSelf(t,r);if(c.ChangeDetectionUtil.looseNotIdentical(s,o)){if(t.lastInBinding){var a=c.ChangeDetectionUtil.simpleChange(s,o);return n&&this.throwOnChangeError(s,o),this._writeSelf(t,o,r),this._setChanged(t,!0),a}return this._writeSelf(t,o,r),this._setChanged(t,!0),null}return this._setChanged(t,!1),null}return this._writeSelf(t,o,r),this._setChanged(t,!0),null},t.prototype._calculateCurrValue=function(e,t,n){switch(e.mode){case p.RecordType.Self:return this._readContext(e,t);case p.RecordType.Const:return e.funcOrValue;case p.RecordType.PropertyRead:var r=this._readContext(e,t);return e.funcOrValue(r);case p.RecordType.SafeProperty:var r=this._readContext(e,t);return i.isBlank(r)?null:e.funcOrValue(r);case p.RecordType.PropertyWrite:var r=this._readContext(e,t),s=this._readArgs(e,t)[0];return e.funcOrValue(r,s),s;case p.RecordType.KeyedWrite:var r=this._readContext(e,t),a=this._readArgs(e,t)[0],s=this._readArgs(e,t)[1];return r[a]=s,s;case p.RecordType.Local:return n.get(e.name);case p.RecordType.InvokeMethod:var r=this._readContext(e,t),c=this._readArgs(e,t);return e.funcOrValue(r,c);case p.RecordType.SafeMethodInvoke:var r=this._readContext(e,t);if(i.isBlank(r))return null;var c=this._readArgs(e,t);return e.funcOrValue(r,c);case p.RecordType.KeyedRead:var u=this._readArgs(e,t)[0];return this._readContext(e,t)[u];case p.RecordType.Chain:var c=this._readArgs(e,t);return c[c.length-1];case p.RecordType.InvokeClosure:return i.FunctionWrapper.apply(this._readContext(e,t),this._readArgs(e,t));case p.RecordType.Interpolate:case p.RecordType.PrimitiveOp:case p.RecordType.CollectionLiteral:return i.FunctionWrapper.apply(e.funcOrValue,this._readArgs(e,t));default:throw new o.BaseException("Unknown operation "+e.mode)}},t.prototype._pipeCheck=function(e,t,n){var r=this._readContext(e,n),i=this._pipeFor(e,r);if(!i.pure||this._argsOrContextChanged(e)){var o=this._readArgs(e,n),s=i.pipe.transform(r,o);if(e.shouldBeChecked()){var a=this._readSelf(e,n);if(c.ChangeDetectionUtil.looseNotIdentical(a,s)){if(s=c.ChangeDetectionUtil.unwrapValue(s),e.lastInBinding){var u=c.ChangeDetectionUtil.simpleChange(a,s);return t&&this.throwOnChangeError(a,s),this._writeSelf(e,s,n),this._setChanged(e,!0),u}return this._writeSelf(e,s,n),this._setChanged(e,!0),null}return this._setChanged(e,!1),null}return this._writeSelf(e,s,n),this._setChanged(e,!0),null}},t.prototype._pipeFor=function(e,t){var n=this._readPipe(e);if(i.isPresent(n))return n;var r=this.pipes.get(e.name);return this._writePipe(e,r),r},t.prototype._readContext=function(e,t){return-1==e.contextIndex?this._getDirectiveFor(e.directiveIndex):t[e.contextIndex]},t.prototype._readSelf=function(e,t){return t[e.selfIndex]},t.prototype._writeSelf=function(e,t,n){n[e.selfIndex]=t},t.prototype._readPipe=function(e){return this.localPipes[e.selfIndex]},t.prototype._writePipe=function(e,t){this.localPipes[e.selfIndex]=t},t.prototype._setChanged=function(e,t){e.argumentToPureFunction&&(this.changes[e.selfIndex]=t)},t.prototype._pureFuncAndArgsDidNotChange=function(e){return e.isPureFunction()&&!this._argsChanged(e)},t.prototype._argsChanged=function(e){for(var t=e.args,n=0;n0);r.set(f.selfIndex,y.selfIndex)}}return i(t)}function i(e){for(var t=[],n=h.ListWrapper.createFixedSize(e.length),r=new h.Map,i=0;ii+1){var c=a(s,t,r);t.push(c),n[c.fixedArgs[0]]=c}}else{var c=a(s,t,r);t.push(c),r.set(s.selfIndex,c.selfIndex)}}return t}function o(e,t,n,r){var i=s(e,t,n);return l.isPresent(i)?(e.lastInBinding?(t.push(u(e,i.selfIndex,t.length+1)),i.referencedBySelf=!0):e.argumentToPureFunction&&(i.argumentToPureFunction=!0),i):(r&&n.push(e.selfIndex),t.push(e),e)}function s(e,t,n){return t.find(function(t){return-1==n.indexOf(t.selfIndex)&&t.mode!==f.RecordType.DirectiveLifecycle&&p(t,e)&&t.mode===e.mode&&l.looseIdentical(t.funcOrValue,e.funcOrValue)&&t.contextIndex===e.contextIndex&&l.looseIdentical(t.name,e.name)&&h.ListWrapper.equals(t.args,e.args)})}function a(e,t,n){var r=e.args.map(function(e){return c(n,e)}),i=c(n,e.contextIndex),o=t.length+1;return new f.ProtoRecord(e.mode,e.name,e.funcOrValue,r,e.fixedArgs,i,e.directiveIndex,o,e.bindingRecord,e.lastInBinding,e.lastInDirective,e.argumentToPureFunction,e.referencedBySelf,e.propertyBindingIndex)}function c(e,t){var n=e.get(t);return l.isPresent(n)?n:t}function u(e,t,n){return new f.ProtoRecord(f.RecordType.Self,"self",null,[],e.fixedArgs,t,e.directiveIndex,n,e.bindingRecord,e.lastInBinding,e.lastInDirective,!1,!1,e.propertyBindingIndex)}function p(e,t){var n=l.isBlank(e.directiveIndex)?null:e.directiveIndex.directiveIndex,r=l.isBlank(e.directiveIndex)?null:e.directiveIndex.elementIndex,i=l.isBlank(t.directiveIndex)?null:t.directiveIndex.directiveIndex,o=l.isBlank(t.directiveIndex)?null:t.directiveIndex.elementIndex;return n===i&&r===o}var l=n(5),h=n(12),f=n(48);t.coalesce=r},function(e,t,n){var r=n(52),i=function(){function e(e){this.definition=e,this._factory=this._createFactory(e)}return e.isSupported=function(){return!0},e.prototype.instantiate=function(e){return this._factory(e)},e.prototype._createFactory=function(e){return new r.ChangeDetectorJITGenerator(e,"util","AbstractChangeDetector","ChangeDetectorStatus").generate()},e}();t.JitProtoChangeDetector=i},function(e,t,n){var r=n(5),i=n(14),o=n(12),s=n(43),a=n(38),c=n(48),u=n(53),p=n(54),l=n(55),h=n(36),f=n(37),d="isChanged",y="changes",v=function(){function e(e,t,n,r){this.changeDetectionUtilVarName=t,this.abstractChangeDetectorVarName=n,this.changeDetectorStateVarName=r;var i=f.createPropertyRecords(e),o=f.createEventRecords(e),s=e.bindingRecords.map(function(e){return e.target});this.id=e.id,this.changeDetectionStrategy=e.strategy,this.genConfig=e.genConfig,this.records=i,this.propertyBindingTargets=s,this.eventBindings=o,this.directiveRecords=e.directiveRecords,this._names=new u.CodegenNameUtil(this.records,this.eventBindings,this.directiveRecords,this.changeDetectionUtilVarName),this._logic=new p.CodegenLogicUtil(this._names,this.changeDetectionUtilVarName,this.changeDetectorStateVarName,this.changeDetectionStrategy),this.typeName=u.sanitizeName("ChangeDetector_"+this.id)}return e.prototype.generate=function(){var e="\n "+this.generateSource()+"\n return function(dispatcher) {\n return new "+this.typeName+"(dispatcher);\n }\n ";return new Function(this.abstractChangeDetectorVarName,this.changeDetectionUtilVarName,this.changeDetectorStateVarName,e)(s.AbstractChangeDetector,a.ChangeDetectionUtil,h.ChangeDetectorState)},e.prototype.generateSource=function(){return"\n var "+this.typeName+" = function "+this.typeName+"(dispatcher) {\n "+this.abstractChangeDetectorVarName+".call(\n this, "+JSON.stringify(this.id)+", dispatcher, "+this.records.length+",\n "+this.typeName+".gen_propertyBindingTargets, "+this.typeName+".gen_directiveIndices,\n "+l.codify(this.changeDetectionStrategy)+");\n this.dehydrateDirectives(false);\n }\n\n "+this.typeName+".prototype = Object.create("+this.abstractChangeDetectorVarName+".prototype);\n\n "+this.typeName+".prototype.detectChangesInRecordsInternal = function(throwOnChange) {\n "+this._names.genInitLocals()+"\n var "+d+" = false;\n var "+y+" = null;\n\n "+this._genAllRecords(this.records)+"\n }\n\n "+this._maybeGenHandleEventInternal()+"\n\n "+this._maybeGenAfterContentLifecycleCallbacks()+"\n\n "+this._maybeGenAfterViewLifecycleCallbacks()+"\n\n "+this._maybeGenHydrateDirectives()+"\n\n "+this._maybeGenDehydrateDirectives()+"\n\n "+this._genPropertyBindingTargets()+"\n\n "+this._genDirectiveIndices()+"\n "},e.prototype._genPropertyBindingTargets=function(){var e=this._logic.genPropertyBindingTargets(this.propertyBindingTargets,this.genConfig.genDebugInfo);return this.typeName+".gen_propertyBindingTargets = "+e+";"},e.prototype._genDirectiveIndices=function(){var e=this._logic.genDirectiveIndices(this.directiveRecords);return this.typeName+".gen_directiveIndices = "+e+";"},e.prototype._maybeGenHandleEventInternal=function(){var e=this;if(this.eventBindings.length>0){var t=this.eventBindings.map(function(t){return e._genEventBinding(t)}).join("\n");return"\n "+this.typeName+".prototype.handleEventInternal = function(eventName, elIndex, locals) {\n var "+this._names.getPreventDefaultAccesor()+" = false;\n "+this._names.genInitEventLocals()+"\n "+t+"\n return "+this._names.getPreventDefaultAccesor()+";\n }\n "}return""},e.prototype._genEventBinding=function(e){var t=this,n=[];return this._endOfBlockIdxs=[],o.ListWrapper.forEachWithIndex(e.records,function(r,i){var o;o=r.isConditionalSkipRecord()?t._genConditionalSkip(r,t._names.getEventLocalName(e,i)):r.isUnconditionalSkipRecord()?t._genUnconditionalSkip(r):t._genEventBindingEval(e,r),o+=t._genEndOfSkipBlock(i),n.push(o)}),'\n if (eventName === "'+e.eventName+'" && elIndex === '+e.elIndex+") {\n "+n.join("\n")+"\n }"},e.prototype._genEventBindingEval=function(e,t){if(t.lastInBinding){var n=this._logic.genEventBindingEvalValue(e,t),r=this._genMarkPathToRootAsCheckOnce(t),i=this._genUpdatePreventDefault(e,t);return n+"\n"+r+"\n"+i}return this._logic.genEventBindingEvalValue(e,t)},e.prototype._genMarkPathToRootAsCheckOnce=function(e){var t=e.bindingRecord;return t.isDefaultChangeDetection()?"":this._names.getDetectorName(t.directiveRecord.directiveIndex)+".markPathToRootAsCheckOnce();"},e.prototype._genUpdatePreventDefault=function(e,t){var n=this._names.getEventLocalName(e,t.selfIndex);return"if ("+n+" === false) { "+this._names.getPreventDefaultAccesor()+" = true};"},e.prototype._maybeGenDehydrateDirectives=function(){var e=this._names.genPipeOnDestroy();e&&(e="if (destroyPipes) { "+e+" }");var t=this._names.genDehydrateFields();return e||t?this.typeName+".prototype.dehydrateDirectives = function(destroyPipes) {\n "+e+"\n "+t+"\n }":""},e.prototype._maybeGenHydrateDirectives=function(){var e=this._logic.genHydrateDirectives(this.directiveRecords),t=this._logic.genHydrateDetectors(this.directiveRecords);return e||t?this.typeName+".prototype.hydrateDirectives = function(directives) {\n "+e+"\n "+t+"\n }":""},e.prototype._maybeGenAfterContentLifecycleCallbacks=function(){var e=this._logic.genContentLifecycleCallbacks(this.directiveRecords);if(e.length>0){var t=e.join("\n");return"\n "+this.typeName+".prototype.afterContentLifecycleCallbacksInternal = function() {\n "+t+"\n }\n "}return""},e.prototype._maybeGenAfterViewLifecycleCallbacks=function(){var e=this._logic.genViewLifecycleCallbacks(this.directiveRecords);if(e.length>0){var t=e.join("\n");return"\n "+this.typeName+".prototype.afterViewLifecycleCallbacksInternal = function() {\n "+t+"\n }\n "}return""},e.prototype._genAllRecords=function(e){var t=[];this._endOfBlockIdxs=[];for(var n=0;na;++a)this._sanitizedNames[a+1]=r(""+this._records[a].name+a);for(var u=0;ua;++a)l.push(r(""+p.records[a].name+a+"_"+u));this._sanitizedEventNames.set(p,l)}}return e.prototype._addFieldPrefix=function(e){return""+d+e},e.prototype.getDispatcherName=function(){return this._addFieldPrefix(u)},e.prototype.getPipesAccessorName=function(){return this._addFieldPrefix(h)},e.prototype.getProtosName=function(){return this._addFieldPrefix(f)},e.prototype.getDirectivesAccessorName=function(){return this._addFieldPrefix(c)},e.prototype.getLocalsAccessorName=function(){return this._addFieldPrefix(p)},e.prototype.getStateName=function(){return this._addFieldPrefix(s)},e.prototype.getModeName=function(){return this._addFieldPrefix(l)},e.prototype.getPropertyBindingIndex=function(){return this._addFieldPrefix(a)},e.prototype.getLocalName=function(e){return"l_"+this._sanitizedNames[e]},e.prototype.getEventLocalName=function(e,t){return"l_"+this._sanitizedEventNames.get(e)[t]},e.prototype.getChangeName=function(e){return"c_"+this._sanitizedNames[e]},e.prototype.genInitLocals=function(){for(var e=[],n=[],r=0,i=this.getFieldCount();i>r;++r)if(r==t.CONTEXT_INDEX)e.push(this.getLocalName(r)+" = "+this.getFieldName(r));else{var s=this._records[r-1];if(s.argumentToPureFunction){var a=this.getChangeName(r);e.push(this.getLocalName(r)+","+a),n.push(a)}else e.push(""+this.getLocalName(r))}var c=o.ListWrapper.isEmpty(n)?"":n.join("=")+" = false;";return"var "+e.join(",")+";"+c},e.prototype.genInitEventLocals=function(){var e=this,n=[this.getLocalName(t.CONTEXT_INDEX)+" = "+this.getFieldName(t.CONTEXT_INDEX)];return this._sanitizedEventNames.forEach(function(r,i){for(var o=0;o1?"var "+n.join(",")+";":""},e.prototype.getPreventDefaultAccesor=function(){return"preventDefault"},e.prototype.getFieldCount=function(){return this._sanitizedNames.length},e.prototype.getFieldName=function(e){return this._addFieldPrefix(this._sanitizedNames[e])},e.prototype.getAllFieldNames=function(){for(var e=[],t=0,n=this.getFieldCount();n>t;++t)(0===t||this._records[t-1].shouldBeChecked())&&e.push(this.getFieldName(t));for(var r=0,i=this._records.length;i>r;++r){var o=this._records[r];o.isPipeRecord()&&e.push(this.getPipeName(o.selfIndex))}for(var s=0,a=this._directiveRecords.length;a>s;++s){var c=this._directiveRecords[s];e.push(this.getDirectiveName(c.directiveIndex)),c.isDefaultChangeDetection()||e.push(this.getDetectorName(c.directiveIndex))}return e},e.prototype.genDehydrateFields=function(){var e=this.getAllFieldNames();return o.ListWrapper.removeAt(e,t.CONTEXT_INDEX),o.ListWrapper.isEmpty(e)?"":(e.push(this._utilName+".uninitialized;"),e.join(" = "))},e.prototype.genPipeOnDestroy=function(){var e=this;return this._records.filter(function(e){return e.isPipeRecord()}).map(function(t){return e._utilName+".callPipeOnDestroy("+e.getPipeName(t.selfIndex)+");"}).join("\n")},e.prototype.getPipeName=function(e){return this._addFieldPrefix(this._sanitizedNames[e]+"_pipe")},e.prototype.getDirectiveName=function(e){return this._addFieldPrefix("directive_"+e.name)},e.prototype.getDetectorName=function(e){return this._addFieldPrefix("detector_"+e.name)},e}();t.CodegenNameUtil=v},function(e,t,n){var r=n(5),i=n(55),o=n(48),s=n(36),a=n(14),c=function(){function e(e,t,n,r){this._names=e,this._utilName=t,this._changeDetectorStateName=n,this._changeDetection=r}return e.prototype.genPropertyBindingEvalValue=function(e){var t=this;return this._genEvalValue(e,function(e){return t._names.getLocalName(e)},this._names.getLocalsAccessorName())},e.prototype.genEventBindingEvalValue=function(e,t){var n=this;return this._genEvalValue(t,function(t){return n._names.getEventLocalName(e,t)},"locals")},e.prototype._genEvalValue=function(e,t,n){var r,s=-1==e.contextIndex?this._names.getDirectiveName(e.directiveIndex):t(e.contextIndex),c=e.args.map(function(e){return t(e)}).join(", ");switch(e.mode){case o.RecordType.Self:r=s;break;case o.RecordType.Const:r=i.codify(e.funcOrValue);break;case o.RecordType.PropertyRead:r=this._observe(s+"."+e.name,e);break;case o.RecordType.SafeProperty:var u=this._observe(s+"."+e.name,e);r=this._utilName+".isValueBlank("+s+") ? null : "+this._observe(u,e);break;case o.RecordType.PropertyWrite:r=s+"."+e.name+" = "+t(e.args[0]);break;case o.RecordType.Local:r=this._observe(n+".get("+i.rawString(e.name)+")",e);break;case o.RecordType.InvokeMethod:r=this._observe(s+"."+e.name+"("+c+")",e);break;case o.RecordType.SafeMethodInvoke:var p=s+"."+e.name+"("+c+")";r=this._utilName+".isValueBlank("+s+") ? null : "+this._observe(p,e);break;case o.RecordType.InvokeClosure:r=s+"("+c+")";break;case o.RecordType.PrimitiveOp:r=this._utilName+"."+e.name+"("+c+")";break;case o.RecordType.CollectionLiteral:r=this._utilName+"."+e.name+"("+c+")";break;case o.RecordType.Interpolate:r=this._genInterpolation(e);break;case o.RecordType.KeyedRead:r=this._observe(s+"["+t(e.args[0])+"]",e);break;case o.RecordType.KeyedWrite:r=s+"["+t(e.args[0])+"] = "+t(e.args[1]);break;case o.RecordType.Chain:r="null";break;default:throw new a.BaseException("Unknown operation "+e.mode)}return t(e.selfIndex)+" = "+r+";"},e.prototype._observe=function(e,t){return this._changeDetection===s.ChangeDetectionStrategy.OnPushObserve?"this.observeValue("+e+", "+t.selfIndex+")":e},e.prototype.genPropertyBindingTargets=function(e,t){var n=this,o=e.map(function(e){if(r.isBlank(e))return"null";var o=t?i.codify(e.debug):"null";return n._utilName+".bindingTarget("+i.codify(e.mode)+", "+e.elementIndex+", "+i.codify(e.name)+", "+i.codify(e.unit)+", "+o+")"});return"["+o.join(", ")+"]"},e.prototype.genDirectiveIndices=function(e){var t=this,n=e.map(function(e){return t._utilName+".directiveIndex("+e.directiveIndex.elementIndex+", "+e.directiveIndex.directiveIndex+")"});return"["+n.join(", ")+"]"},e.prototype._genInterpolation=function(e){for(var t=[],n=0;n=0;--i){var o=e[i];o.callAfterContentInit&&t.push("if("+this._names.getStateName()+" "+n+" "+this._changeDetectorStateName+".NeverChecked) "+this._names.getDirectiveName(o.directiveIndex)+".ngAfterContentInit();"),o.callAfterContentChecked&&t.push(this._names.getDirectiveName(o.directiveIndex)+".ngAfterContentChecked();")}return t},e.prototype.genViewLifecycleCallbacks=function(e){for(var t=[],n=r.IS_DART?"==":"===",i=e.length-1;i>=0;--i){var o=e[i];o.callAfterViewInit&&t.push("if("+this._names.getStateName()+" "+n+" "+this._changeDetectorStateName+".NeverChecked) "+this._names.getDirectiveName(o.directiveIndex)+".ngAfterViewInit();"),o.callAfterViewChecked&&t.push(this._names.getDirectiveName(o.directiveIndex)+".ngAfterViewChecked();")}return t},e}();t.CodegenLogicUtil=c},function(e,t){function n(e){return JSON.stringify(e)}function r(e){return"'"+e+"'"}function i(e){return e.join(" + ")}t.codify=n,t.rawString=r,t.combineGeneratedStrings=i},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(5);!function(e){e[e.Emulated=0]="Emulated",e[e.Native=1]="Native",e[e.None=2]="None"}(t.ViewEncapsulation||(t.ViewEncapsulation={}));var s=t.ViewEncapsulation;t.VIEW_ENCAPSULATION_VALUES=[s.Emulated,s.Native,s.None];var a=function(){function e(e){var t=void 0===e?{}:e,n=t.templateUrl,r=t.template,i=t.directives,o=t.pipes,s=t.encapsulation,a=t.styles,c=t.styleUrls;this.templateUrl=n,this.template=r,this.styleUrls=c,this.styles=a,this.directives=i,this.pipes=o,this.encapsulation=s}return e=r([o.CONST(),i("design:paramtypes",[Object])],e)}();t.ViewMetadata=a},function(e,t,n){var r=n(9);t.Class=r.Class},function(e,t,n){var r=n(5);t.enableProdMode=r.enableProdMode},function(e,t,n){var r=n(5);t.Type=r.Type;var i=n(60);t.EventEmitter=i.EventEmitter;var o=n(14);t.WrappedException=o.WrappedException;var s=n(15);t.ExceptionHandler=s.ExceptionHandler},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=n(5),o=n(61);t.PromiseWrapper=o.PromiseWrapper,t.Promise=o.Promise;var s=n(62),a=n(63),c=n(64),u=n(62);t.Observable=u.Observable;var p=n(62);t.Subject=p.Subject;var l=function(){function e(){}return e.setTimeout=function(e,t){return i.global.setTimeout(e,t)},e.clearTimeout=function(e){i.global.clearTimeout(e)},e.setInterval=function(e,t){return i.global.setInterval(e,t)},e.clearInterval=function(e){i.global.clearInterval(e)},e}();t.TimerWrapper=l;var h=function(){function e(){}return e.subscribe=function(e,t,n,r){return void 0===r&&(r=function(){}),n="function"==typeof n&&n||i.noop,r="function"==typeof r&&r||i.noop,e.subscribe({next:t,error:n,complete:r})},e.isObservable=function(e){return!!e.subscribe},e.hasSubscribers=function(e){return e.observers.length>0},e.dispose=function(e){e.unsubscribe()},e.callNext=function(e,t){e.next(t)},e.callEmit=function(e,t){e.emit(t)},e.callError=function(e,t){e.error(t)},e.callComplete=function(e){e.complete()},e.fromPromise=function(e){return a.PromiseObservable.create(e)},e.toPromise=function(e){return c.toPromise.call(e)},e}();t.ObservableWrapper=h;var f=function(e){function t(t){void 0===t&&(t=!0),e.call(this),this._isAsync=t}return r(t,e),t.prototype.emit=function(t){e.prototype.next.call(this,t)},t.prototype.next=function(t){e.prototype.next.call(this,t)},t.prototype.subscribe=function(t,n,r){var i,o=function(e){return null},s=function(){return null};return t&&"object"==typeof t?(i=this._isAsync?function(e){setTimeout(function(){return t.next(e)})}:function(e){t.next(e)},t.error&&(o=this._isAsync?function(e){setTimeout(function(){return t.error(e)})}:function(e){t.error(e)}),t.complete&&(s=this._isAsync?function(){setTimeout(function(){return t.complete()})}:function(){t.complete()})):(i=this._isAsync?function(e){setTimeout(function(){return t(e)})}:function(e){t(e)},n&&(o=this._isAsync?function(e){setTimeout(function(){return n(e)})}:function(e){n(e)}),r&&(s=this._isAsync?function(){setTimeout(function(){return r()})}:function(){r()})),e.prototype.subscribe.call(this,i,o,s)},t}(s.Subject);t.EventEmitter=f},function(e,t){var n=function(){function e(){}return e.resolve=function(e){return Promise.resolve(e)},e.reject=function(e,t){return Promise.reject(e)},e.catchError=function(e,t){return e["catch"](t)},e.all=function(e){return 0==e.length?Promise.resolve([]):Promise.all(e)},e.then=function(e,t,n){return e.then(t,n)},e.wrap=function(e){return new Promise(function(t,n){try{t(e())}catch(r){n(r)}})},e.scheduleMicrotask=function(t){e.then(e.resolve(null),t,function(e){})},e.isPromise=function(e){return e instanceof Promise},e.completer=function(){var e,t,n=new Promise(function(n,r){e=n,t=r});return{promise:n,resolve:e,reject:t}},e}();t.PromiseWrapper=n},function(t,n){t.exports=e},function(e,n){e.exports=t},function(e,t){e.exports=n},function(e,t,n){function r(e){return[f.provide(d.APP_COMPONENT,{useValue:e}),f.provide(d.APP_COMPONENT_REF_PROMISE,{useFactory:function(t,n,r){var i;return t.loadAsRoot(e,null,r,function(){n._unloadComponent(i)}).then(function(e){return i=e,h.isPresent(e.location.nativeElement)&&r.get(m.TestabilityRegistry).registerApplication(e.location.nativeElement,r.get(m.Testability)),e})},deps:[g.DynamicComponentLoader,D,f.Injector]}),f.provide(e,{useFactory:function(e){return e.then(function(e){return e.instance})},deps:[d.APP_COMPONENT_REF_PROMISE]})]}function i(){return new l.NgZone({enableLongStackTrace:h.assertionsEnabled()})}function o(e){if(w.lockMode(),h.isPresent(R)){if(v.ListWrapper.equals(E,e))return R;throw new _.BaseException("platform cannot be initialized with different sets of providers.")}return a(e)}function s(){h.isPresent(R)&&(R.dispose(),R=null)}function a(e){E=e;var t=f.Injector.resolveAndCreate(e);return R=new S(t,function(){R=null,E=null}),c(t),R}function c(e){var t=e.getOptional(d.PLATFORM_INITIALIZER);h.isPresent(t)&&t.forEach(function(e){return e()})}function u(e){var t=e.getOptional(d.APP_INITIALIZER);h.isPresent(t)&&t.forEach(function(e){return e()})}var p=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},l=n(66),h=n(5),f=n(6),d=n(67),y=n(60),v=n(12),m=n(68),g=n(69),_=n(14),b=n(77),C=n(97),P=n(45),w=n(5);t.createNgZone=i;var R,E;t.platform=o,t.disposePlatform=s;var O=function(){function e(){}return Object.defineProperty(e.prototype,"injector",{get:function(){return _.unimplemented()},enumerable:!0,configurable:!0}),e}();t.PlatformRef=O;var S=function(e){function t(t,n){e.call(this),this._injector=t,this._dispose=n,this._applications=[],this._disposeListeners=[]}return p(t,e),t.prototype.registerDisposeListener=function(e){this._disposeListeners.push(e)},Object.defineProperty(t.prototype,"injector",{get:function(){return this._injector},enumerable:!0,configurable:!0}),t.prototype.application=function(e){var t=this._initApp(i(),e);return t},t.prototype.asyncApplication=function(e,t){var n=this,r=i(),o=y.PromiseWrapper.completer();return r.run(function(){y.PromiseWrapper.then(e(r),function(e){h.isPresent(t)&&(e=v.ListWrapper.concat(e,t)),o.resolve(n._initApp(r,e))})}),o.promise},t.prototype._initApp=function(e,t){var n,r,i=this;return e.run(function(){t=v.ListWrapper.concat(t,[f.provide(l.NgZone,{useValue:e}),f.provide(D,{useFactory:function(){return r},deps:[]})]);var o;try{n=i.injector.resolveAndCreateChild(t),o=n.get(_.ExceptionHandler),e.overrideOnErrorHandler(function(e,t){return o.call(e,t)})}catch(s){h.isPresent(o)?o.call(s,s.stack):h.print(s.toString())}}),r=new T(this,e,n),this._applications.push(r),u(n),r},t.prototype.dispose=function(){v.ListWrapper.clone(this._applications).forEach(function(e){return e.dispose()}),this._disposeListeners.forEach(function(e){return e()}),this._dispose()},t.prototype._applicationDisposed=function(e){v.ListWrapper.remove(this._applications,e)},t}(O);t.PlatformRef_=S;var D=function(){function e(){}return Object.defineProperty(e.prototype,"injector",{get:function(){return _.unimplemented()},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"zone",{get:function(){return _.unimplemented()},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"componentTypes",{get:function(){return _.unimplemented()},enumerable:!0,configurable:!0}),e}();t.ApplicationRef=D;var T=function(e){function t(t,n,r){var i=this;e.call(this),this._platform=t,this._zone=n,this._injector=r,this._bootstrapListeners=[],this._disposeListeners=[],this._rootComponents=[],this._rootComponentTypes=[],this._changeDetectorRefs=[],this._runningTick=!1,this._enforceNoNewChanges=!1,h.isPresent(this._zone)&&y.ObservableWrapper.subscribe(this._zone.onTurnDone,function(e){i._zone.run(function(){i.tick()})}),this._enforceNoNewChanges=h.assertionsEnabled()}return p(t,e),t.prototype.registerBootstrapListener=function(e){this._bootstrapListeners.push(e)},t.prototype.registerDisposeListener=function(e){this._disposeListeners.push(e)},t.prototype.registerChangeDetector=function(e){this._changeDetectorRefs.push(e)},t.prototype.unregisterChangeDetector=function(e){v.ListWrapper.remove(this._changeDetectorRefs,e)},t.prototype.bootstrap=function(e,t){var n=this,i=y.PromiseWrapper.completer();return this._zone.run(function(){var o=r(e);h.isPresent(t)&&o.push(t);var s=n._injector.get(_.ExceptionHandler);n._rootComponentTypes.push(e);try{var a=n._injector.resolveAndCreateChild(o),c=a.get(d.APP_COMPONENT_REF_PROMISE),u=function(e){n._loadComponent(e),i.resolve(e)},p=y.PromiseWrapper.then(c,u);h.IS_DART&&y.PromiseWrapper.then(p,function(e){}),y.PromiseWrapper.then(p,null,function(e,t){return i.reject(e,t)})}catch(l){s.call(l,l.stack),i.reject(l,l.stack)}}),i.promise.then(function(e){var t=n._injector.get(C.Console),r=h.assertionsEnabled()?"in the development mode. Call enableProdMode() to enable the production mode.":"in the production mode. Call enableDevMode() to enable the development mode.";return t.log("Angular 2 is running "+r),e})},t.prototype._loadComponent=function(e){var t=b.internalView(e.hostView).changeDetector;this._changeDetectorRefs.push(t.ref),this.tick(),this._rootComponents.push(e),this._bootstrapListeners.forEach(function(t){return t(e)})},t.prototype._unloadComponent=function(e){v.ListWrapper.contains(this._rootComponents,e)&&(this.unregisterChangeDetector(b.internalView(e.hostView).changeDetector.ref),v.ListWrapper.remove(this._rootComponents,e))},Object.defineProperty(t.prototype,"injector",{get:function(){return this._injector},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"zone",{get:function(){return this._zone},enumerable:!0,configurable:!0}),t.prototype.tick=function(){if(this._runningTick)throw new _.BaseException("ApplicationRef.tick is called recursively");var e=t._tickScope();try{this._runningTick=!0,this._changeDetectorRefs.forEach(function(e){return e.detectChanges()}),this._enforceNoNewChanges&&this._changeDetectorRefs.forEach(function(e){return e.checkNoChanges()})}finally{this._runningTick=!1,P.wtfLeave(e)}},t.prototype.dispose=function(){v.ListWrapper.clone(this._rootComponents).forEach(function(e){return e.dispose()}),this._disposeListeners.forEach(function(e){return e()}),this._platform._applicationDisposed(this)},Object.defineProperty(t.prototype,"componentTypes",{get:function(){return this._rootComponentTypes},enumerable:!0,configurable:!0}),t._tickScope=P.wtfCreateScope("ApplicationRef#tick()"),t}(D);t.ApplicationRef_=T},function(e,t,n){var r=n(12),i=n(5),o=n(60),s=n(45),a=function(){function e(e,t){this.error=e,this.stackTrace=t}return e}();t.NgZoneError=a;var c=function(){function e(e){var t=e.enableLongStackTrace;this._runScope=s.wtfCreateScope("NgZone#run()"),this._microtaskScope=s.wtfCreateScope("NgZone#microtask()"),this._pendingMicrotasks=0,this._hasExecutedCodeInInnerZone=!1,this._nestedRun=0,this._inVmTurnDone=!1,this._pendingTimeouts=[],i.global.zone?(this._disabled=!1,this._mountZone=i.global.zone,this._innerZone=this._createInnerZone(this._mountZone,t)):(this._disabled=!0,this._mountZone=null),this._onTurnStartEvents=new o.EventEmitter(!1),this._onTurnDoneEvents=new o.EventEmitter(!1),this._onEventDoneEvents=new o.EventEmitter(!1),this._onErrorEvents=new o.EventEmitter(!1)}return e.prototype.overrideOnTurnStart=function(e){this._onTurnStart=i.normalizeBlank(e)},Object.defineProperty(e.prototype,"onTurnStart",{get:function(){return this._onTurnStartEvents},enumerable:!0,configurable:!0}),e.prototype._notifyOnTurnStart=function(e){var t=this;e.call(this._innerZone,function(){t._onTurnStartEvents.emit(null)})},e.prototype.overrideOnTurnDone=function(e){this._onTurnDone=i.normalizeBlank(e)},Object.defineProperty(e.prototype,"onTurnDone",{get:function(){return this._onTurnDoneEvents},enumerable:!0,configurable:!0}),e.prototype._notifyOnTurnDone=function(e){var t=this;e.call(this._innerZone,function(){t._onTurnDoneEvents.emit(null)})},e.prototype.overrideOnEventDone=function(e,t){var n=this;void 0===t&&(t=!1);var r=i.normalizeBlank(e);t?this._onEventDone=function(){n._pendingTimeouts.length||r()}:this._onEventDone=r},Object.defineProperty(e.prototype,"onEventDone",{get:function(){return this._onEventDoneEvents},enumerable:!0,configurable:!0}),e.prototype._notifyOnEventDone=function(){var e=this;this.runOutsideAngular(function(){e._onEventDoneEvents.emit(null)})},Object.defineProperty(e.prototype,"hasPendingMicrotasks",{get:function(){return this._pendingMicrotasks>0},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"hasPendingTimers",{get:function(){return this._pendingTimeouts.length>0},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"hasPendingAsyncTasks",{get:function(){return this.hasPendingMicrotasks||this.hasPendingTimers},enumerable:!0,configurable:!0}),e.prototype.overrideOnErrorHandler=function(e){this._onErrorHandler=i.normalizeBlank(e)},Object.defineProperty(e.prototype,"onError",{get:function(){return this._onErrorEvents},enumerable:!0,configurable:!0}),e.prototype.run=function(e){if(this._disabled)return e();var t=this._runScope();try{return this._innerZone.run(e)}finally{s.wtfLeave(t)}},e.prototype.runOutsideAngular=function(e){return this._disabled?e():this._mountZone.run(e)},e.prototype._createInnerZone=function(e,t){var n,o=this._microtaskScope,a=this;return n=t?r.StringMapWrapper.merge(Zone.longStackTraceZone,{onError:function(e){a._notifyOnError(this,e)}}):{onError:function(e){a._notifyOnError(this,e)}},e.fork(n).fork({$run:function(e){return function(){try{return a._nestedRun++,a._hasExecutedCodeInInnerZone||(a._hasExecutedCodeInInnerZone=!0,a._notifyOnTurnStart(e),a._onTurnStart&&e.call(a._innerZone,a._onTurnStart)),e.apply(this,arguments)}finally{if(a._nestedRun--,0==a._pendingMicrotasks&&0==a._nestedRun&&!this._inVmTurnDone){if(a._hasExecutedCodeInInnerZone)try{this._inVmTurnDone=!0,a._notifyOnTurnDone(e),a._onTurnDone&&e.call(a._innerZone,a._onTurnDone)}finally{this._inVmTurnDone=!1,a._hasExecutedCodeInInnerZone=!1}0===a._pendingMicrotasks&&(a._notifyOnEventDone(),i.isPresent(a._onEventDone)&&a.runOutsideAngular(a._onEventDone))}}}},$scheduleMicrotask:function(e){return function(t){a._pendingMicrotasks++;var n=function(){var e=o();try{t()}finally{a._pendingMicrotasks--,s.wtfLeave(e)}};e.call(this,n)}},$setTimeout:function(e){return function(t,n){for(var i=[],o=2;o")),t.APP_COMPONENT=s.CONST_EXPR(new o.OpaqueToken("AppComponent")),t.APP_ID=s.CONST_EXPR(new o.OpaqueToken("AppId")),t.APP_ID_RANDOM_PROVIDER=s.CONST_EXPR(new o.Provider(t.APP_ID,{useFactory:r,deps:[]})),t.PLATFORM_INITIALIZER=s.CONST_EXPR(new o.OpaqueToken("Platform Initializer")),t.APP_INITIALIZER=s.CONST_EXPR(new o.OpaqueToken("Application Initializer")),t.PACKAGE_ROOT_URL=s.CONST_EXPR(new o.OpaqueToken("Application Packages Root URL"))},function(e,t,n){function r(e){y=e}var i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=n(6),a=n(12),c=n(5),u=n(14),p=n(66),l=n(60),h=function(){function e(e){this._pendingCount=0,this._callbacks=[],this._isAngularEventPending=!1,this._watchAngularEvents(e)}return e.prototype._watchAngularEvents=function(e){var t=this;l.ObservableWrapper.subscribe(e.onTurnStart,function(e){t._isAngularEventPending=!0}),e.runOutsideAngular(function(){l.ObservableWrapper.subscribe(e.onEventDone,function(n){e.hasPendingTimers||(t._isAngularEventPending=!1,t._runCallbacksIfReady())})})},e.prototype.increasePendingRequestCount=function(){return this._pendingCount+=1,this._pendingCount},e.prototype.decreasePendingRequestCount=function(){if(this._pendingCount-=1,this._pendingCount<0)throw new u.BaseException("pending async requests below zero");return this._runCallbacksIfReady(),this._pendingCount},e.prototype.isStable=function(){return 0==this._pendingCount&&!this._isAngularEventPending},e.prototype._runCallbacksIfReady=function(){var e=this;this.isStable()&&l.PromiseWrapper.resolve(null).then(function(t){for(;0!==e._callbacks.length;)e._callbacks.pop()()})},e.prototype.whenStable=function(e){this._callbacks.push(e),this._runCallbacksIfReady()},e.prototype.getPendingRequestCount=function(){return this._pendingCount},e.prototype.isAngularEventPending=function(){return this._isAngularEventPending},e.prototype.findBindings=function(e,t,n){return[]},e.prototype.findProviders=function(e,t,n){return[]},e=i([s.Injectable(),o("design:paramtypes",[p.NgZone])],e)}();t.Testability=h;var f=function(){function e(){this._applications=new a.Map,y.addToWindow(this)}return e.prototype.registerApplication=function(e,t){this._applications.set(e,t)},e.prototype.getTestability=function(e){return this._applications.get(e)},e.prototype.getAllTestabilities=function(){return a.MapWrapper.values(this._applications)},e.prototype.findTestabilityInTree=function(e,t){return void 0===t&&(t=!0),y.findTestabilityInTree(this,e,t)},e=i([s.Injectable(),o("design:paramtypes",[])],e)}();t.TestabilityRegistry=f;var d=function(){function e(){}return e.prototype.addToWindow=function(e){},e.prototype.findTestabilityInTree=function(e,t,n){return null},e=i([c.CONST(),o("design:paramtypes",[])],e)}();t.setTestabilityGetter=r;var y=c.CONST_EXPR(new d)},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=n(6),a=n(70),c=n(5),u=n(81),p=function(){function e(){}return Object.defineProperty(e.prototype,"hostView",{get:function(){return this.location.parentView},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"hostComponent",{get:function(){return this.instance},enumerable:!0,configurable:!0}),e}();t.ComponentRef=p;var l=function(e){function t(t,n,r,i,o){e.call(this),this._dispose=o,this.location=t,this.instance=n,this.componentType=r,this.injector=i}return r(t,e),Object.defineProperty(t.prototype,"hostComponentType",{get:function(){return this.componentType},enumerable:!0,configurable:!0}),t.prototype.dispose=function(){this._dispose()},t}(p);t.ComponentRef_=l;var h=function(){function e(){}return e}();t.DynamicComponentLoader=h;var f=function(e){function t(t,n){e.call(this),this._compiler=t,this._viewManager=n}return r(t,e), -t.prototype.loadAsRoot=function(e,t,n,r){var i=this;return this._compiler.compileInHost(e).then(function(o){var s=i._viewManager.createRootHostView(o,t,n),a=i._viewManager.getHostElement(s),u=i._viewManager.getComponent(a),p=function(){c.isPresent(r)&&r(),i._viewManager.destroyRootHostView(s)};return new l(a,u,e,n,p)})},t.prototype.loadIntoLocation=function(e,t,n,r){return void 0===r&&(r=null),this.loadNextToLocation(e,this._viewManager.getNamedElementInComponentView(t,n),r)},t.prototype.loadNextToLocation=function(e,t,n){var r=this;return void 0===n&&(n=null),this._compiler.compileInHost(e).then(function(i){var o=r._viewManager.getViewContainer(t),s=o.createHostView(i,o.length,n),a=r._viewManager.getHostElement(s),c=r._viewManager.getComponent(a),u=function(){var e=o.indexOf(s);-1!==e&&o.remove(e)};return new l(a,c,e,null,u)})},t=i([s.Injectable(),o("design:paramtypes",[a.Compiler,u.AppViewManager])],t)}(h);t.DynamicComponentLoader_=f},function(e,t,n){function r(e){return e instanceof d.CompiledHostTemplate}function i(e,t){return e._createProtoView(t)}var o=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},s=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},a=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},c=n(71),u=n(6),p=n(5),l=n(14),h=n(60),f=n(16),d=n(96),y=function(){function e(){}return e}();t.Compiler=y;var v=function(e){function t(t){e.call(this),this._protoViewFactory=t}return o(t,e),t.prototype.compileInHost=function(e){var t=f.reflector.annotations(e),n=t.find(r);if(p.isBlank(n))throw new l.BaseException("No precompiled template for component "+p.stringify(e)+" found");return h.PromiseWrapper.resolve(this._createProtoView(n))},t.prototype._createProtoView=function(e){return this._protoViewFactory.createHost(e).ref},t.prototype.clearCache=function(){this._protoViewFactory.clearCache()},t=s([u.Injectable(),a("design:paramtypes",[c.ProtoViewFactory])],t)}(y);t.Compiler_=v,t.internalCreateProtoView=i},function(e,t,n){function r(e,t){return e._createComponent(t)}function i(e,t,n){return e._createEmbeddedTemplate(t,n)}function o(e,t,n,r,i,o,u){var p=null,l=null;if(i>0&&(p=n[n.length-i]),d.isBlank(p)&&(i=-1),o>0){var h=n[n.length-o];d.isPresent(h)&&(l=h.protoElementInjector)}d.isBlank(l)&&(o=-1);var f=null,y=!1,v=u.directives.map(function(t){return s(e,t)});u instanceof S.BeginComponentCmd?f=v[0]:u instanceof S.EmbeddedTemplateCmd&&(y=!0);var m=null,g=u.variableNameAndValues.length>0;if(v.length>0||g||y){var _=new Map;y||(_=a(u.variableNameAndValues,v)),m=C.ProtoElementInjector.create(l,r,v,d.isPresent(f),o,_),m.attributes=c(u.attrNameAndValues,!1)}return new b.ElementBinder(r,p,i,m,f,t)}function s(e,t){var n=e.resolve(t);return C.DirectiveProvider.createFromType(t,n)}function a(e,t){for(var n=new Map,r=0;ro?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},h=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},f=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},d=n(5),y=n(72),v=n(6),m=n(73),g=n(74),_=n(76),b=n(79),C=n(80),P=n(92),w=n(93),R=n(94),E=n(56),O=n(95),S=n(96),D=n(72),T=n(67),A=function(){function e(e,t,n,r,i,o){this._renderer=e,this._platformPipes=t,this._directiveResolver=n,this._viewResolver=r,this._pipeResolver=i,this._appId=o,this._cache=new Map,this._nextTemplateId=0}return e.prototype.clearCache=function(){this._cache.clear()},e.prototype.createHost=function(e){var t=e.template,n=this._cache.get(t.id);if(d.isBlank(n)){var r={},i=this._appId+"-"+this._nextTemplateId++;this._renderer.registerComponentTemplate(new y.RenderComponentTemplate(t.id,i,E.ViewEncapsulation.None,t.commands,[])),n=new _.AppProtoView(t.id,t.commands,_.ViewType.HOST,!0,t.changeDetectorFactory,null,new g.ProtoPipes(r)),this._cache.set(t.id,n)}return n},e.prototype._createComponent=function(e){var t=this,n=this._cache.get(e.templateId);if(d.isBlank(n)){var r=e.directives[0],i=this._viewResolver.resolve(r),o=e.templateGetter(),s=p(o.styles,[]),a=this._appId+"-"+this._nextTemplateId++;this._renderer.registerComponentTemplate(new y.RenderComponentTemplate(o.id,a,e.encapsulation,o.commands,s));var c=this._flattenPipes(i).map(function(e){return t._bindPipe(e)});n=new _.AppProtoView(o.id,o.commands,_.ViewType.COMPONENT,!0,o.changeDetectorFactory,null,g.ProtoPipes.fromProviders(c)),this._cache.set(o.id,n),this._initializeProtoView(n,null)}return n},e.prototype._createEmbeddedTemplate=function(e,t){var n=new _.AppProtoView(t.templateId,e.children,_.ViewType.EMBEDDED,e.isMerged,e.changeDetectorFactory,c(e.variableNameAndValues,!0),new g.ProtoPipes(t.pipes.config));return e.isMerged&&this.initializeProtoViewIfNeeded(n),n},e.prototype.initializeProtoViewIfNeeded=function(e){if(!e.isInitialized()){var t=this._renderer.createProtoView(e.templateId,e.templateCmds);this._initializeProtoView(e,t)}},e.prototype._initializeProtoView=function(e,t){var n=new I(e,this._directiveResolver,this);S.visitAllCommands(n,e.templateCmds);var r=new _.AppProtoViewMergeInfo(n.mergeEmbeddedViewCount,n.mergeElementCount,n.mergeViewCount);e.init(t,n.elementBinders,n.boundTextCount,r,n.variableLocations)},e.prototype._bindPipe=function(e){var t=this._pipeResolver.resolve(e);return m.PipeProvider.createFromType(e,t)},e.prototype._flattenPipes=function(e){var t=[];return d.isPresent(this._platformPipes)&&u(this._platformPipes,t),d.isPresent(e.pipes)&&u(e.pipes,t),t},e=l([v.Injectable(),f(1,v.Optional()),f(1,v.Inject(O.PLATFORM_PIPES)),f(5,v.Inject(T.APP_ID)),h("design:paramtypes",[D.Renderer,Array,P.DirectiveResolver,w.ViewResolver,R.PipeResolver,String])],e)}();t.ProtoViewFactory=A;var I=function(){function e(e,t,n){this._protoView=e,this._directiveResolver=t,this._protoViewFactory=n,this.variableLocations=new Map,this.boundTextCount=0,this.boundElementIndex=0,this.elementBinderStack=[],this.distanceToParentElementBinder=0,this.distanceToParentProtoElementInjector=0,this.elementBinders=[],this.mergeEmbeddedViewCount=0,this.mergeElementCount=0,this.mergeViewCount=1}return e.prototype.visitText=function(e,t){return e.isBound&&this.boundTextCount++,null},e.prototype.visitNgContent=function(e,t){return null},e.prototype.visitBeginElement=function(e,t){return e.isBound?this._visitBeginBoundElement(e,null):this._visitBeginElement(e,null,null),null},e.prototype.visitEndElement=function(e){return this._visitEndElement()},e.prototype.visitBeginComponent=function(e,t){var n=r(this._protoViewFactory,e);return this._visitBeginBoundElement(e,n)},e.prototype.visitEndComponent=function(e){return this._visitEndElement()},e.prototype.visitEmbeddedTemplate=function(e,t){var n=i(this._protoViewFactory,e,this._protoView);return e.isMerged&&this.mergeEmbeddedViewCount++,this._visitBeginBoundElement(e,n),this._visitEndElement()},e.prototype._visitBeginBoundElement=function(e,t){d.isPresent(t)&&t.isMergable&&(this.mergeElementCount+=t.mergeInfo.elementCount,this.mergeViewCount+=t.mergeInfo.viewCount,this.mergeEmbeddedViewCount+=t.mergeInfo.embeddedViewCount);var n=o(this._directiveResolver,t,this.elementBinderStack,this.boundElementIndex,this.distanceToParentElementBinder,this.distanceToParentProtoElementInjector,e);this.elementBinders.push(n);for(var r=n.protoElementInjector,i=0;i=0;n--)c.isPresent(t[n+this.elementOffset])&&t[n+this.elementOffset].ngAfterContentChecked()},e.prototype.notifyAfterViewChecked=function(){for(var e=this.proto.elementBinders.length,t=this.elementInjectors,n=e-1;n>=0;n--)c.isPresent(t[n+this.elementOffset])&&t[n+this.elementOffset].ngAfterViewChecked()},e.prototype.getDirectiveFor=function(e){var t=this.elementInjectors[this.elementOffset+e.elementIndex];return t.getDirectiveAtIndex(e.directiveIndex)},e.prototype.getNestedView=function(e){var t=this.elementInjectors[e];return c.isPresent(t)?t.getNestedView():null},e.prototype.getContainerElement=function(){return c.isPresent(this.containerElementInjector)?this.containerElementInjector.getElementRef():null},e.prototype.getDebugContext=function(e,t){try{var n=this.elementOffset+e,i=n1)throw new c.BaseException("A directive injectable can contain only one of the following @Attribute or @Query.")},t.createFrom=function(e){return new t(e.key,e.optional,e.lowerBoundVisibility,e.upperBoundVisibility,e.properties,t._attributeName(e.properties),t._query(e.properties))},t._attributeName=function(e){var t=e.find(function(e){return e instanceof d.AttributeMetadata});return a.isPresent(t)?t.attributeName:null},t._query=function(e){return e.find(function(e){return e instanceof d.QueryMetadata})},t}(l.Dependency);t.DirectiveDependency=A;var I=function(e){function t(t,n,r,i,o,s){e.call(this,t,[new f.ResolvedFactory(n,r)],!1),this.metadata=i,this.providers=o,this.viewProviders=s,this.callOnDestroy=b.hasLifecycleHook(O.LifecycleHooks.OnDestroy,t.token)}return s(t,e),Object.defineProperty(t.prototype,"displayName",{get:function(){return this.key.displayName},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"queries",{get:function(){if(a.isBlank(this.metadata.queries))return[];var e=[];return p.StringMapWrapper.forEach(this.metadata.queries,function(t,n){var r=w.reflector.setter(n);e.push(new N(r,t))}),e},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"eventEmitters",{get:function(){return a.isPresent(this.metadata)&&a.isPresent(this.metadata.outputs)?this.metadata.outputs:[]},enumerable:!0,configurable:!0}),t.createFromProvider=function(e,n){a.isBlank(n)&&(n=new _.DirectiveMetadata);var r=f.resolveProvider(e),i=r.resolvedFactories[0],o=i.dependencies.map(A.createFrom),s=a.isPresent(n.providers)?n.providers:[],c=n instanceof _.ComponentMetadata&&a.isPresent(n.viewProviders)?n.viewProviders:[];return new t(r.key,i.factory,o,n,s,c)},t.createFromType=function(e,n){var r=new l.Provider(e,{useClass:e});return t.createFromProvider(r,n)},t}(f.ResolvedProvider_);t.DirectiveProvider=I;var x=function(){function e(e,t,n,r){this.viewManager=e,this.view=t,this.elementRef=n,this.templateRef=r,this.nestedView=null}return e}();t.PreBuiltObjects=x;var N=function(){function e(e,t){this.setter=e,this.metadata=t}return e}();t.QueryMetadataWithSetter=N;var k=function(){function e(e,t){this.eventName=e,this.getter=t}return e.prototype.subscribe=function(e,t,n){var r=this,i=this.getter(n);return u.ObservableWrapper.subscribe(i,function(n){return e.triggerEventHandlers(r.eventName,n,t)})},e}();t.EventEmitterAccessor=k;var j=function(){function e(e,t,n,o,s,a){this.parent=e,this.index=t,this.distanceToParent=o,this.directiveVariableBindings=a,this._firstProviderIsComponent=s;var c=n.length;this.protoInjector=new h.ProtoInjector(n),this.eventEmitterAccessors=p.ListWrapper.createFixedSize(c);for(var u=0;c>u;++u)this.eventEmitterAccessors[u]=r(n[u]);this.protoQueryRefs=i(n)}return e.create=function(t,n,r,i,o,s){var a=[];return e._createDirectiveProviderWithVisibility(r,a,i),i&&e._createViewProvidersWithVisibility(r,a),e._createProvidersWithVisibility(r,a),new e(t,n,a,o,i,s)},e._createDirectiveProviderWithVisibility=function(t,n,r){t.forEach(function(i){n.push(e._createProviderWithVisibility(r,i,t,i))})},e._createProvidersWithVisibility=function(e,t){var n=[];e.forEach(function(e){n=p.ListWrapper.concat(n,e.providers)});var r=l.Injector.resolve(n);r.forEach(function(e){return t.push(new h.ProviderWithVisibility(e,h.Visibility.Public))})},e._createProviderWithVisibility=function(e,t,n,r){var i=e&&n[0]===t;return new h.ProviderWithVisibility(r,i?h.Visibility.PublicAndPrivate:h.Visibility.Public)},e._createViewProvidersWithVisibility=function(e,t){var n=l.Injector.resolve(e[0].viewProviders);n.forEach(function(e){return t.push(new h.ProviderWithVisibility(e,h.Visibility.Private))})},e.prototype.instantiate=function(e){return new M(this,e)},e.prototype.directParent=function(){return this.distanceToParent<2?this.parent:null},Object.defineProperty(e.prototype,"hasBindings",{get:function(){return this.eventEmitterAccessors.length>0},enumerable:!0,configurable:!0}),e.prototype.getProviderAtIndex=function(e){return this.protoInjector.getProviderAtIndex(e)},e}();t.ProtoElementInjector=j;var V=function(){function e(e,t,n){this.element=e,this.componentElement=t,this.injector=n}return e}(),M=function(e){function t(t,n){var r=this;e.call(this,n),this._preBuiltObjects=null,this._proto=t,this._injector=new l.Injector(this._proto.protoInjector,null,this,function(){return r._debugContext()});var i=this._injector.internalStrategy;this._strategy=i instanceof h.InjectorInlineStrategy?new U(i,this):new H(i,this),this.hydrated=!1,this._queryStrategy=this._buildQueryStrategy()}return s(t,e),t.prototype.dehydrate=function(){this.hydrated=!1,this._host=null,this._preBuiltObjects=null,this._strategy.callOnDestroy(),this._strategy.dehydrate(),this._queryStrategy.dehydrate()},t.prototype.hydrate=function(e,t,n){this._host=t,this._preBuiltObjects=n,this._reattachInjectors(e),this._queryStrategy.hydrate(),this._strategy.hydrate(),this.hydrated=!0},t.prototype._debugContext=function(){var e=this._preBuiltObjects,t=e.elementRef.boundElementIndex-e.view.elementOffset,n=this._preBuiltObjects.view.getDebugContext(t,null);return a.isPresent(n)?new V(n.element,n.componentElement,n.injector):null},t.prototype._reattachInjectors=function(e){a.isPresent(this._parent)?a.isPresent(e)?(this._reattachInjector(this._injector,e,!1),this._reattachInjector(e,this._parent._injector,!1)):this._reattachInjector(this._injector,this._parent._injector,!1):a.isPresent(this._host)?a.isPresent(e)?(this._reattachInjector(this._injector,e,!1),this._reattachInjector(e,this._host._injector,!0)):this._reattachInjector(this._injector,this._host._injector,!0):a.isPresent(e)&&this._reattachInjector(this._injector,e,!0)},t.prototype._reattachInjector=function(e,t,n){e.internalStrategy.attach(t,n)},t.prototype.hasVariableBinding=function(e){var t=this._proto.directiveVariableBindings;return a.isPresent(t)&&t.has(e)},t.prototype.getVariableBinding=function(e){var t=this._proto.directiveVariableBindings.get(e);return a.isPresent(t)?this.getDirectiveAtIndex(t):this.getElementRef()},t.prototype.get=function(e){return this._injector.get(e)},t.prototype.hasDirective=function(e){return a.isPresent(this._injector.getOptional(e))},t.prototype.getEventEmitterAccessors=function(){return this._proto.eventEmitterAccessors},t.prototype.getDirectiveVariableBindings=function(){return this._proto.directiveVariableBindings},t.prototype.getComponent=function(){return this._strategy.getComponent()},t.prototype.getInjector=function(){return this._injector},t.prototype.getElementRef=function(){return this._preBuiltObjects.elementRef},t.prototype.getViewContainerRef=function(){return new S.ViewContainerRef_(this._preBuiltObjects.viewManager,this.getElementRef())},t.prototype.getNestedView=function(){return this._preBuiltObjects.nestedView},t.prototype.getView=function(){return this._preBuiltObjects.view},t.prototype.directParent=function(){return this._proto.distanceToParent<2?this.parent:null},t.prototype.isComponentKey=function(e){return this._strategy.isComponentKey(e)},t.prototype.getDependency=function(e,t,n){var r=n.key;if(t instanceof I){var i=n,o=t,s=D.instance();if(r.id===s.viewManagerId)return this._preBuiltObjects.viewManager;if(a.isPresent(i.attributeName))return this._buildAttribute(i);if(a.isPresent(i.queryDecorator))return this._queryStrategy.findQuery(i.queryDecorator).list;if(i.key.id===D.instance().changeDetectorRefId){if(o.metadata instanceof _.ComponentMetadata){var c=this._preBuiltObjects.view.getNestedView(this._preBuiltObjects.elementRef.boundElementIndex);return c.changeDetector.ref}return this._preBuiltObjects.view.changeDetector.ref}if(i.key.id===D.instance().elementRefId)return this.getElementRef();if(i.key.id===D.instance().viewContainerId)return this.getViewContainerRef();if(i.key.id===D.instance().templateRefId){if(a.isBlank(this._preBuiltObjects.templateRef)){if(i.optional)return null;throw new l.NoProviderError(null,i.key)}return this._preBuiltObjects.templateRef}}else if(t instanceof E.PipeProvider&&n.key.id===D.instance().changeDetectorRefId){var c=this._preBuiltObjects.view.getNestedView(this._preBuiltObjects.elementRef.boundElementIndex);return c.changeDetector.ref}return h.UNDEFINED},t.prototype._buildAttribute=function(e){var t=this._proto.attributes;return a.isPresent(t)&&t.has(e.attributeName)?t.get(e.attributeName):null},t.prototype.addDirectivesMatchingQuery=function(e,t){var n=a.isBlank(this._preBuiltObjects)?null:this._preBuiltObjects.templateRef;e.selector===g.TemplateRef&&a.isPresent(n)&&t.push(n),this._strategy.addDirectivesMatchingQuery(e,t)},t.prototype._buildQueryStrategy=function(){return 0===this._proto.protoQueryRefs.length?L:this._proto.protoQueryRefs.length<=F.NUMBER_OF_SUPPORTED_QUERIES?new F(this):new W(this)},t.prototype.link=function(e){e.addChild(this); -},t.prototype.unlink=function(){this.remove()},t.prototype.getDirectiveAtIndex=function(e){return this._injector.getAt(e)},t.prototype.hasInstances=function(){return this._proto.hasBindings&&this.hydrated},t.prototype.getHost=function(){return this._host},t.prototype.getBoundElementIndex=function(){return this._proto.index},t.prototype.getRootViewInjectors=function(){if(!this.hydrated)return[];var e=this._preBuiltObjects.view,t=e.getNestedView(e.elementOffset+this.getBoundElementIndex());return a.isPresent(t)?t.rootElementInjectors:[]},t.prototype.ngAfterViewChecked=function(){this._queryStrategy.updateViewQueries()},t.prototype.ngAfterContentChecked=function(){this._queryStrategy.updateContentQueries()},t.prototype.traverseAndSetQueriesAsDirty=function(){for(var e=this;a.isPresent(e);)e._setQueriesAsDirty(),e=e.parent},t.prototype._setQueriesAsDirty=function(){this._queryStrategy.setContentQueriesAsDirty(),a.isPresent(this._host)&&this._host._queryStrategy.setViewQueriesAsDirty()},t}(T);t.ElementInjector=M;var B=function(){function e(){}return e.prototype.setContentQueriesAsDirty=function(){},e.prototype.setViewQueriesAsDirty=function(){},e.prototype.hydrate=function(){},e.prototype.dehydrate=function(){},e.prototype.updateContentQueries=function(){},e.prototype.updateViewQueries=function(){},e.prototype.findQuery=function(e){throw new c.BaseException("Cannot find query for directive "+e+".")},e}(),L=new B,F=function(){function e(e){var t=e._proto.protoQueryRefs;t.length>0&&(this.query0=new G(t[0],e)),t.length>1&&(this.query1=new G(t[1],e)),t.length>2&&(this.query2=new G(t[2],e))}return e.prototype.setContentQueriesAsDirty=function(){a.isPresent(this.query0)&&!this.query0.isViewQuery&&(this.query0.dirty=!0),a.isPresent(this.query1)&&!this.query1.isViewQuery&&(this.query1.dirty=!0),a.isPresent(this.query2)&&!this.query2.isViewQuery&&(this.query2.dirty=!0)},e.prototype.setViewQueriesAsDirty=function(){a.isPresent(this.query0)&&this.query0.isViewQuery&&(this.query0.dirty=!0),a.isPresent(this.query1)&&this.query1.isViewQuery&&(this.query1.dirty=!0),a.isPresent(this.query2)&&this.query2.isViewQuery&&(this.query2.dirty=!0)},e.prototype.hydrate=function(){a.isPresent(this.query0)&&this.query0.hydrate(),a.isPresent(this.query1)&&this.query1.hydrate(),a.isPresent(this.query2)&&this.query2.hydrate()},e.prototype.dehydrate=function(){a.isPresent(this.query0)&&this.query0.dehydrate(),a.isPresent(this.query1)&&this.query1.dehydrate(),a.isPresent(this.query2)&&this.query2.dehydrate()},e.prototype.updateContentQueries=function(){a.isPresent(this.query0)&&!this.query0.isViewQuery&&this.query0.update(),a.isPresent(this.query1)&&!this.query1.isViewQuery&&this.query1.update(),a.isPresent(this.query2)&&!this.query2.isViewQuery&&this.query2.update()},e.prototype.updateViewQueries=function(){a.isPresent(this.query0)&&this.query0.isViewQuery&&this.query0.update(),a.isPresent(this.query1)&&this.query1.isViewQuery&&this.query1.update(),a.isPresent(this.query2)&&this.query2.isViewQuery&&this.query2.update()},e.prototype.findQuery=function(e){if(a.isPresent(this.query0)&&this.query0.protoQueryRef.query===e)return this.query0;if(a.isPresent(this.query1)&&this.query1.protoQueryRef.query===e)return this.query1;if(a.isPresent(this.query2)&&this.query2.protoQueryRef.query===e)return this.query2;throw new c.BaseException("Cannot find query for directive "+e+".")},e.NUMBER_OF_SUPPORTED_QUERIES=3,e}(),W=function(){function e(e){this.queries=e._proto.protoQueryRefs.map(function(t){return new G(t,e)})}return e.prototype.setContentQueriesAsDirty=function(){for(var e=0;e0?this.list.first:null):this.protoQueryRef.setter(e,this.list)}this.list.notifyOnChanges()}},e.prototype._update=function(){var e=[];if(this.protoQueryRef.query.isViewQuery){var t=this.originator.getView(),n=t.getNestedView(t.elementOffset+this.originator.getBoundElementIndex());a.isPresent(n)&&this._visitView(n,e)}else this._visit(this.originator,e);this.list.reset(e)},e.prototype._visit=function(e,t){for(var n=e.getView(),r=n.elementOffset+e._proto.index,i=r;ir&&(a.isBlank(o)||a.isBlank(o.parent)||n.elementOffset+o.parent._proto.indexo?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},a=n(6),c=n(5),u=n(14),p=n(76),l=n(77),h=n(72),f=n(82),d=n(85),y=n(86),v=n(45),m=n(71),g=function(){function e(){}return e.prototype.getHostElement=function(e){var t=l.internalView(e);if(t.proto.type!==p.ViewType.HOST)throw new u.BaseException("This operation is only allowed on host views");return t.elementRefs[t.elementOffset]},e}();t.AppViewManager=g;var _=function(e){function t(t,n,r,i,o){e.call(this),this._viewPool=t,this._viewListener=n,this._utils=r,this._renderer=i,this._createRootHostViewScope=v.wtfCreateScope("AppViewManager#createRootHostView()"),this._destroyRootHostViewScope=v.wtfCreateScope("AppViewManager#destroyRootHostView()"),this._createEmbeddedViewInContainerScope=v.wtfCreateScope("AppViewManager#createEmbeddedViewInContainer()"),this._createHostViewInContainerScope=v.wtfCreateScope("AppViewManager#createHostViewInContainer()"),this._destroyViewInContainerScope=v.wtfCreateScope("AppViewMananger#destroyViewInContainer()"),this._attachViewInContainerScope=v.wtfCreateScope("AppViewMananger#attachViewInContainer()"),this._detachViewInContainerScope=v.wtfCreateScope("AppViewMananger#detachViewInContainer()"),this._protoViewFactory=o}return r(t,e),t.prototype.getViewContainer=function(e){var t=l.internalView(e.parentView);return t.elementInjectors[e.boundElementIndex].getViewContainerRef()},t.prototype.getNamedElementInComponentView=function(e,t){var n=l.internalView(e.parentView),r=e.boundElementIndex,i=n.getNestedView(r);if(c.isBlank(i))throw new u.BaseException("There is no component directive at element "+r);var o=i.proto.variableLocations.get(t);if(c.isBlank(o))throw new u.BaseException("Could not find variable "+t);return i.elementRefs[i.elementOffset+o]},t.prototype.getComponent=function(e){var t=l.internalView(e.parentView),n=e.boundElementIndex;return this._utils.getComponentInstance(t,n)},t.prototype.createRootHostView=function(e,t,n){var r=this._createRootHostViewScope(),i=l.internalProtoView(e);this._protoViewFactory.initializeProtoViewIfNeeded(i);var o=t;c.isBlank(o)&&(o=i.elementBinders[0].componentDirective.metadata.selector);var s=this._renderer.createRootHostView(i.render,i.mergeInfo.embeddedViewCount+1,o),a=this._createMainView(i,s);return this._renderer.hydrateView(a.render),this._utils.hydrateRootHostView(a,n),v.wtfLeave(r,a.ref)},t.prototype.destroyRootHostView=function(e){var t=this._destroyRootHostViewScope(),n=l.internalView(e);this._renderer.detachFragment(n.renderFragment),this._renderer.dehydrateView(n.render),this._viewDehydrateRecurse(n),this._viewListener.onViewDestroyed(n),this._renderer.destroyView(n.render),v.wtfLeave(t)},t.prototype.createEmbeddedViewInContainer=function(e,t,n){var r=this._createEmbeddedViewInContainerScope(),i=l.internalProtoView(n.protoViewRef);if(i.type!==p.ViewType.EMBEDDED)throw new u.BaseException("This method can only be called with embedded ProtoViews!");return this._protoViewFactory.initializeProtoViewIfNeeded(i),v.wtfLeave(r,this._createViewInContainer(e,t,i,n.elementRef,null))},t.prototype.createHostViewInContainer=function(e,t,n,r){var i=this._createHostViewInContainerScope(),o=l.internalProtoView(n);if(o.type!==p.ViewType.HOST)throw new u.BaseException("This method can only be called with host ProtoViews!");return this._protoViewFactory.initializeProtoViewIfNeeded(o),v.wtfLeave(i,this._createViewInContainer(e,t,o,e,r))},t.prototype._createViewInContainer=function(e,t,n,r,i){var o,s=l.internalView(e.parentView),a=e.boundElementIndex,u=l.internalView(r.parentView),h=r.boundElementIndex,f=u.getNestedView(h);n.type===p.ViewType.EMBEDDED&&c.isPresent(f)&&!f.hydrated()?(o=f,this._attachRenderView(s,a,t,o)):(o=this._createPooledView(n),this._attachRenderView(s,a,t,o),this._renderer.hydrateView(o.render)),this._utils.attachViewInContainer(s,a,u,h,t,o);try{this._utils.hydrateViewInContainer(s,a,u,h,t,i)}catch(d){throw this._utils.detachViewInContainer(s,a,t),d}return o.ref},t.prototype._attachRenderView=function(e,t,n,r){var i=e.elementRefs[t];if(0===n)this._renderer.attachFragmentAfterElement(i,r.renderFragment);else{var o=e.viewContainers[t].views[n-1];this._renderer.attachFragmentAfterFragment(o.renderFragment,r.renderFragment)}},t.prototype.destroyViewInContainer=function(e,t){var n=this._destroyViewInContainerScope(),r=l.internalView(e.parentView),i=e.boundElementIndex;this._destroyViewInContainer(r,i,t),v.wtfLeave(n)},t.prototype.attachViewInContainer=function(e,t,n){var r=this._attachViewInContainerScope(),i=l.internalView(n),o=l.internalView(e.parentView),s=e.boundElementIndex;return this._utils.attachViewInContainer(o,s,null,null,t,i),this._attachRenderView(o,s,t,i),v.wtfLeave(r,n)},t.prototype.detachViewInContainer=function(e,t){var n=this._detachViewInContainerScope(),r=l.internalView(e.parentView),i=e.boundElementIndex,o=r.viewContainers[i],s=o.views[t];return this._utils.detachViewInContainer(r,i,t),this._renderer.detachFragment(s.renderFragment),v.wtfLeave(n,s.ref)},t.prototype._createMainView=function(e,t){var n=this._utils.createView(e,t,this,this._renderer);return this._renderer.setEventDispatcher(n.render,n),this._viewListener.onViewCreated(n),n},t.prototype._createPooledView=function(e){var t=this._viewPool.getView(e);return c.isBlank(t)&&(t=this._createMainView(e,this._renderer.createView(e.render,e.mergeInfo.embeddedViewCount+1))),t},t.prototype._destroyPooledView=function(e){var t=this._viewPool.returnView(e);t||(this._viewListener.onViewDestroyed(e),this._renderer.destroyView(e.render))},t.prototype._destroyViewInContainer=function(e,t,n){var r=e.viewContainers[t],i=r.views[n];this._viewDehydrateRecurse(i),this._utils.detachViewInContainer(e,t,n),i.viewOffset>0?this._renderer.detachFragment(i.renderFragment):(this._renderer.dehydrateView(i.render),this._renderer.detachFragment(i.renderFragment),this._destroyPooledView(i))},t.prototype._viewDehydrateRecurse=function(e){e.hydrated()&&this._utils.dehydrateView(e);for(var t=e.viewContainers,n=e.viewOffset,r=e.viewOffset+e.proto.mergeInfo.viewCount-1,i=e.elementOffset,o=n;r>=o;o++)for(var s=e.views[o],a=0;a=0;p--)this._destroyViewInContainer(s,i,p)}},t=i([a.Injectable(),s(4,a.Inject(a.forwardRef(function(){return m.ProtoViewFactory}))),o("design:paramtypes",[d.AppViewPool,y.AppViewListener,f.AppViewManagerUtils,h.Renderer,Object])],t)}(g);t.AppViewManager_=_},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(6),s=n(12),a=n(80),c=n(5),u=n(76),p=n(83),l=n(84),h=n(74),f=function(){function e(){}return e.prototype.getComponentInstance=function(e,t){var n=e.elementInjectors[t];return n.getComponent()},e.prototype.createView=function(e,t,n,r){for(var i=t.fragmentRefs,o=t.viewRef,h=e.mergeInfo.elementCount,f=e.mergeInfo.viewCount,d=s.ListWrapper.createFixedSize(h),y=s.ListWrapper.createFixedSize(h),v=s.ListWrapper.createFixedSize(h),m=s.ListWrapper.createFixedSize(h),g=s.ListWrapper.createFixedSize(f),_=0,b=0,C=0,P=s.ListWrapper.createFixedSize(f),w=0;f>w;w++){var R=P[w],E=c.isPresent(R)?m[R]:null,O=c.isPresent(E)?v[R].view:null,S=c.isPresent(R)?O.proto.elementBinders[R-O.elementOffset].nestedProtoView:e,D=null;(0===w||S.type===u.ViewType.EMBEDDED)&&(D=i[C++]);var T=new u.AppView(r,S,w,_,b,S.protoLocals,o,D,E);g[w]=T,c.isPresent(R)&&(v[R].nestedView=T);for(var A=[],I=w+1,x=0;x=0;l--)c.isPresent(p.parent)&&o.rootElementInjectors[l].link(p.parent);p.traverseAndSetQueriesAsDirty()},e.prototype.detachViewInContainer=function(e,t,n){var r=e.viewContainers[t],i=r.views[n];e.elementInjectors[t].traverseAndSetQueriesAsDirty(),i.changeDetector.remove(),s.ListWrapper.removeAt(r.views,n);for(var o=0;o=o;){var a=e.views[o],p=a.proto;if(a!==e&&a.proto.type===u.ViewType.EMBEDDED)o+=a.proto.mergeInfo.viewCount;else{a!==e&&(t=null,i=null,n=a.containerElementInjector,r=n.getComponent()),a.context=r,a.locals.parent=i;for(var l=p.elementBinders,f=0;f=n;n++){var r=e.views[n];if(r.hydrated()){c.isPresent(r.locals)&&r.locals.clearValues(),r.context=null,r.changeDetector.dehydrate();for(var i=r.proto.elementBinders,o=0;oo?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},s=n(6),a=n(5),c=n(12);t.APP_VIEW_POOL_CAPACITY=a.CONST_EXPR(new s.OpaqueToken("AppViewPool.viewPoolCapacity"));var u=function(){function e(e){this._pooledViewsPerProtoView=new c.Map,this._poolCapacityPerProtoView=e}return e.prototype.getView=function(e){var t=this._pooledViewsPerProtoView.get(e);return a.isPresent(t)&&t.length>0?t.pop():null},e.prototype.returnView=function(e){var t=e.proto,n=this._pooledViewsPerProtoView.get(t);a.isBlank(n)&&(n=[],this._pooledViewsPerProtoView.set(t,n));var r=n.lengtho?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(6),s=function(){function e(){}return e.prototype.onViewCreated=function(e){},e.prototype.onViewDestroyed=function(e){},e=r([o.Injectable(),i("design:paramtypes",[])],e)}();t.AppViewListener=s},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=n(12),o=n(14),s=n(5),a=n(77),c=function(){function e(){}return e.prototype.clear=function(){for(var e=this.length-1;e>=0;e--)this.remove(e)},Object.defineProperty(e.prototype,"length",{get:function(){return o.unimplemented()},enumerable:!0,configurable:!0}),e}();t.ViewContainerRef=c;var u=function(e){function t(t,n){e.call(this),this.viewManager=t,this.element=n}return r(t,e),t.prototype._getViews=function(){var e=this.element,t=a.internalView(e.parentView).viewContainers[e.boundElementIndex];return s.isPresent(t)?t.views:[]},t.prototype.get=function(e){return this._getViews()[e].ref},Object.defineProperty(t.prototype,"length",{get:function(){return this._getViews().length},enumerable:!0,configurable:!0}),t.prototype.createEmbeddedView=function(e,t){return void 0===t&&(t=-1),-1==t&&(t=this.length),this.viewManager.createEmbeddedViewInContainer(this.element,t,e)},t.prototype.createHostView=function(e,t,n){return void 0===e&&(e=null),void 0===t&&(t=-1),void 0===n&&(n=null),-1==t&&(t=this.length),this.viewManager.createHostViewInContainer(this.element,t,e,n)},t.prototype.insert=function(e,t){return void 0===t&&(t=-1),-1==t&&(t=this.length),this.viewManager.attachViewInContainer(this.element,t,e)},t.prototype.indexOf=function(e){return i.ListWrapper.indexOf(this._getViews(),a.internalView(e))},t.prototype.remove=function(e){void 0===e&&(e=-1),-1==e&&(e=this.length-1),this.viewManager.destroyViewInContainer(this.element,e)},t.prototype.detach=function(e){return void 0===e&&(e=-1),-1==e&&(e=this.length-1),this.viewManager.detachViewInContainer(this.element,e)},t}(c);t.ViewContainerRef_=u},function(e,t,n){function r(e,t){if(!(t instanceof i.Type))return!1;var n=t.prototype;switch(e){case o.LifecycleHooks.AfterContentInit:return!!n.ngAfterContentInit;case o.LifecycleHooks.AfterContentChecked:return!!n.ngAfterContentChecked;case o.LifecycleHooks.AfterViewInit:return!!n.ngAfterViewInit;case o.LifecycleHooks.AfterViewChecked:return!!n.ngAfterViewChecked;case o.LifecycleHooks.OnChanges:return!!n.ngOnChanges;case o.LifecycleHooks.DoCheck:return!!n.ngDoCheck;case o.LifecycleHooks.OnDestroy:return!!n.ngOnDestroy;case o.LifecycleHooks.OnInit:return!!n.ngOnInit;default:return!1}}var i=n(5),o=n(89);t.hasLifecycleHook=r},function(e,t){!function(e){e[e.OnInit=0]="OnInit",e[e.OnDestroy=1]="OnDestroy",e[e.DoCheck=2]="DoCheck",e[e.OnChanges=3]="OnChanges",e[e.AfterContentInit=4]="AfterContentInit",e[e.AfterContentChecked=5]="AfterContentChecked",e[e.AfterViewInit=6]="AfterViewInit",e[e.AfterViewChecked=7]="AfterViewChecked"}(t.LifecycleHooks||(t.LifecycleHooks={}));var n=t.LifecycleHooks;t.LIFECYCLE_HOOKS_VALUES=[n.OnInit,n.OnDestroy,n.DoCheck,n.OnChanges,n.AfterContentInit,n.AfterContentChecked,n.AfterViewInit,n.AfterViewChecked]},function(e,t,n){var r=n(12),i=n(5),o=n(60),s=function(){function e(){this._results=[],this._emitter=new o.EventEmitter}return Object.defineProperty(e.prototype,"changes",{get:function(){return this._emitter},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"length",{get:function(){return this._results.length},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"first",{get:function(){return r.ListWrapper.first(this._results)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"last",{get:function(){return r.ListWrapper.last(this._results)},enumerable:!0,configurable:!0}),e.prototype.map=function(e){return this._results.map(e)},e.prototype.filter=function(e){return this._results.filter(e); -},e.prototype.reduce=function(e,t){return this._results.reduce(e,t)},e.prototype.toArray=function(){return r.ListWrapper.clone(this._results)},e.prototype[i.getSymbolIterator()]=function(){return this._results[i.getSymbolIterator()]()},e.prototype.toString=function(){return this._results.toString()},e.prototype.reset=function(e){this._results=e},e.prototype.notifyOnChanges=function(){this._emitter.emit(this)},e}();t.QueryList=s},function(e,t){t.EVENT_TARGET_SEPARATOR=":";var n=function(){function e(e,t,n){this.fieldName=e,this.eventName=t,this.isLongForm=n}return e.parse=function(n){var r=n,i=n,o=!1,s=n.indexOf(t.EVENT_TARGET_SEPARATOR);return s>-1&&(r=n.substring(0,s).trim(),i=n.substring(s+1).trim(),o=!0),new e(r,i,o)},e.prototype.getFullName=function(){return this.isLongForm?""+this.fieldName+t.EVENT_TARGET_SEPARATOR+this.eventName:this.eventName},e}();t.EventConfig=n},function(e,t,n){function r(e){return e instanceof p.DirectiveMetadata}var i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=n(6),a=n(5),c=n(14),u=n(12),p=n(3),l=n(16),h=function(){function e(){}return e.prototype.resolve=function(e){var t=l.reflector.annotations(s.resolveForwardRef(e));if(a.isPresent(t)){var n=t.find(r);if(a.isPresent(n)){var i=l.reflector.propMetadata(e);return this._mergeWithPropertyMetadata(n,i)}}throw new c.BaseException("No Directive annotation found on "+a.stringify(e))},e.prototype._mergeWithPropertyMetadata=function(e,t){var n=[],r=[],i={},o={};return u.StringMapWrapper.forEach(t,function(e,t){e.forEach(function(e){if(e instanceof p.InputMetadata&&(a.isPresent(e.bindingPropertyName)?n.push(t+": "+e.bindingPropertyName):n.push(t)),e instanceof p.OutputMetadata&&(a.isPresent(e.bindingPropertyName)?r.push(t+": "+e.bindingPropertyName):r.push(t)),e instanceof p.HostBindingMetadata&&(a.isPresent(e.hostPropertyName)?i["["+e.hostPropertyName+"]"]=t:i["["+t+"]"]=t),e instanceof p.HostListenerMetadata){var s=a.isPresent(e.args)?e.args.join(", "):"";i["("+e.eventName+")"]=t+"("+s+")"}e instanceof p.ContentChildrenMetadata&&(o[t]=e),e instanceof p.ViewChildrenMetadata&&(o[t]=e),e instanceof p.ContentChildMetadata&&(o[t]=e),e instanceof p.ViewChildMetadata&&(o[t]=e)})}),this._merge(e,n,r,i,o)},e.prototype._merge=function(e,t,n,r,i){var o=a.isPresent(e.inputs)?u.ListWrapper.concat(e.inputs,t):t,s=a.isPresent(e.outputs)?u.ListWrapper.concat(e.outputs,n):n,c=a.isPresent(e.host)?u.StringMapWrapper.merge(e.host,r):r,l=a.isPresent(e.queries)?u.StringMapWrapper.merge(e.queries,i):i;return e instanceof p.ComponentMetadata?new p.ComponentMetadata({selector:e.selector,inputs:o,outputs:s,host:c,exportAs:e.exportAs,moduleId:e.moduleId,queries:l,changeDetection:e.changeDetection,providers:e.providers,viewProviders:e.viewProviders}):new p.DirectiveMetadata({selector:e.selector,inputs:o,outputs:s,host:c,exportAs:e.exportAs,queries:l,providers:e.providers})},e=i([s.Injectable(),o("design:paramtypes",[])],e)}();t.DirectiveResolver=h},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(6),s=n(56),a=n(23),c=n(5),u=n(14),p=n(12),l=n(16),h=function(){function e(){this._cache=new p.Map}return e.prototype.resolve=function(e){var t=this._cache.get(e);return c.isBlank(t)&&(t=this._resolve(e),this._cache.set(e,t)),t},e.prototype._resolve=function(e){var t,n;if(l.reflector.annotations(e).forEach(function(e){e instanceof s.ViewMetadata&&(n=e),e instanceof a.ComponentMetadata&&(t=e)}),!c.isPresent(t)){if(c.isBlank(n))throw new u.BaseException("No View decorator found on component '"+c.stringify(e)+"'");return n}if(c.isBlank(t.template)&&c.isBlank(t.templateUrl)&&c.isBlank(n))throw new u.BaseException("Component '"+c.stringify(e)+"' must have either 'template', 'templateUrl', or '@View' set.");if(c.isPresent(t.template)&&c.isPresent(n))this._throwMixingViewAndComponent("template",e);else if(c.isPresent(t.templateUrl)&&c.isPresent(n))this._throwMixingViewAndComponent("templateUrl",e);else if(c.isPresent(t.directives)&&c.isPresent(n))this._throwMixingViewAndComponent("directives",e);else if(c.isPresent(t.pipes)&&c.isPresent(n))this._throwMixingViewAndComponent("pipes",e);else if(c.isPresent(t.encapsulation)&&c.isPresent(n))this._throwMixingViewAndComponent("encapsulation",e);else if(c.isPresent(t.styles)&&c.isPresent(n))this._throwMixingViewAndComponent("styles",e);else{if(!c.isPresent(t.styleUrls)||!c.isPresent(n))return c.isPresent(n)?n:new s.ViewMetadata({templateUrl:t.templateUrl,template:t.template,directives:t.directives,pipes:t.pipes,encapsulation:t.encapsulation,styles:t.styles,styleUrls:t.styleUrls});this._throwMixingViewAndComponent("styleUrls",e)}return null},e.prototype._throwMixingViewAndComponent=function(e,t){throw new u.BaseException("Component '"+c.stringify(t)+"' cannot have both '"+e+"' and '@View' set at the same time\"")},e=r([o.Injectable(),i("design:paramtypes",[])],e)}();t.ViewResolver=h},function(e,t,n){function r(e){return e instanceof u.PipeMetadata}var i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=n(6),a=n(5),c=n(14),u=n(3),p=n(16),l=function(){function e(){}return e.prototype.resolve=function(e){var t=p.reflector.annotations(s.resolveForwardRef(e));if(a.isPresent(t)){var n=t.find(r);if(a.isPresent(n))return n}throw new c.BaseException("No Pipe decorator found on "+a.stringify(e))},e=i([s.Injectable(),o("design:paramtypes",[])],e)}();t.PipeResolver=l},function(e,t,n){var r=n(6),i=n(5);t.PLATFORM_DIRECTIVES=i.CONST_EXPR(new r.OpaqueToken("Platform Directives")),t.PLATFORM_PIPES=i.CONST_EXPR(new r.OpaqueToken("Platform Pipes"))},function(e,t,n){function r(e,t,n){void 0===n&&(n=null);for(var r=0;ro?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},s=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},a=n(5),c=n(14),u=n(72),p=(n(3),n(3));t.ViewEncapsulation=p.ViewEncapsulation;var l=function(){function e(e){this.template=e}return e=o([a.CONST(),s("design:paramtypes",[h])],e)}();t.CompiledHostTemplate=l;var h=function(){function e(e,t,n,r){this.id=e,this.changeDetectorFactory=t,this.commands=n,this.styles=r}return e=o([a.CONST(),s("design:paramtypes",[String,Function,Array,Array])],e)}();t.CompiledComponentTemplate=h;var f=a.CONST_EXPR([]),d=function(){function e(e,t,n){this.value=e,this.isBound=t,this.ngContentIndex=n}return e.prototype.visit=function(e,t){return e.visitText(this,t)},e=o([a.CONST(),s("design:paramtypes",[String,Boolean,Number])],e)}();t.TextCmd=d;var y=function(){function e(e,t){this.index=e,this.ngContentIndex=t,this.isBound=!1}return e.prototype.visit=function(e,t){return e.visitNgContent(this,t)},e=o([a.CONST(),s("design:paramtypes",[Number,Number])],e)}();t.NgContentCmd=y;var v=function(e){function t(){e.apply(this,arguments)}return i(t,e),Object.defineProperty(t.prototype,"variableNameAndValues",{get:function(){return c.unimplemented()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"eventTargetAndNames",{get:function(){return c.unimplemented()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"directives",{get:function(){return c.unimplemented()},enumerable:!0,configurable:!0}),t}(u.RenderBeginElementCmd);t.IBeginElementCmd=v;var m=function(){function e(e,t,n,r,i,o,s){this.name=e,this.attrNameAndValues=t,this.eventTargetAndNames=n,this.variableNameAndValues=r,this.directives=i,this.isBound=o,this.ngContentIndex=s}return e.prototype.visit=function(e,t){return e.visitBeginElement(this,t)},e=o([a.CONST(),s("design:paramtypes",[String,Array,Array,Array,Array,Boolean,Number])],e)}();t.BeginElementCmd=m;var g=function(){function e(){}return e.prototype.visit=function(e,t){return e.visitEndElement(t)},e=o([a.CONST(),s("design:paramtypes",[])],e)}();t.EndElementCmd=g;var _=function(){function e(e,t,n,r,i,o,s,a){this.name=e,this.attrNameAndValues=t,this.eventTargetAndNames=n,this.variableNameAndValues=r,this.directives=i,this.encapsulation=o,this.ngContentIndex=s,this.templateGetter=a,this.isBound=!0}return Object.defineProperty(e.prototype,"templateId",{get:function(){return this.templateGetter().id},enumerable:!0,configurable:!0}),e.prototype.visit=function(e,t){return e.visitBeginComponent(this,t)},e=o([a.CONST(),s("design:paramtypes",[String,Array,Array,Array,Array,Number,Number,Function])],e)}();t.BeginComponentCmd=_;var b=function(){function e(){}return e.prototype.visit=function(e,t){return e.visitEndComponent(t)},e=o([a.CONST(),s("design:paramtypes",[])],e)}();t.EndComponentCmd=b;var C=function(){function e(e,t,n,r,i,o,s){this.attrNameAndValues=e,this.variableNameAndValues=t,this.directives=n,this.isMerged=r,this.ngContentIndex=i,this.changeDetectorFactory=o,this.children=s,this.isBound=!0,this.name=null,this.eventTargetAndNames=f}return e.prototype.visit=function(e,t){return e.visitEmbeddedTemplate(this,t)},e=o([a.CONST(),s("design:paramtypes",[Array,Array,Array,Boolean,Number,Function,Array])],e)}();t.EmbeddedTemplateCmd=C,t.visitAllCommands=r},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(6),s=n(5),a=function(){function e(){}return e.prototype.log=function(e){s.print(e)},e=r([o.Injectable(),i("design:paramtypes",[])],e)}();t.Console=a},function(e,t,n){var r=n(66);t.NgZone=r.NgZone,t.NgZoneError=r.NgZoneError},function(e,t,n){var r=n(72);t.Renderer=r.Renderer,t.RenderViewRef=r.RenderViewRef,t.RenderProtoViewRef=r.RenderProtoViewRef,t.RenderFragmentRef=r.RenderFragmentRef,t.RenderViewWithFragments=r.RenderViewWithFragments,t.RenderTemplateCmd=r.RenderTemplateCmd,t.RenderTextCmd=r.RenderTextCmd,t.RenderNgContentCmd=r.RenderNgContentCmd,t.RenderBeginElementCmd=r.RenderBeginElementCmd,t.RenderBeginComponentCmd=r.RenderBeginComponentCmd,t.RenderEmbeddedTemplateCmd=r.RenderEmbeddedTemplateCmd,t.RenderBeginCmd=r.RenderBeginCmd,t.RenderComponentTemplate=r.RenderComponentTemplate},function(e,t,n){var r=n(92);t.DirectiveResolver=r.DirectiveResolver;var i=n(93);t.ViewResolver=i.ViewResolver;var o=n(70);t.Compiler=o.Compiler;var s=n(81);t.AppViewManager=s.AppViewManager;var a=n(90);t.QueryList=a.QueryList;var c=n(69);t.DynamicComponentLoader=c.DynamicComponentLoader;var u=n(83);t.ElementRef=u.ElementRef;var p=n(84);t.TemplateRef=p.TemplateRef;var l=n(77);t.ViewRef=l.ViewRef,t.ProtoViewRef=l.ProtoViewRef;var h=n(87);t.ViewContainerRef=h.ViewContainerRef;var f=n(69);t.ComponentRef=f.ComponentRef},function(e,t,n){function r(e){return new l(u.internalView(e.parentView),e.boundElementIndex)}function i(e){return e.map(function(e){return e.nativeElement})}var o=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},s=n(5),a=n(14),c=n(76),u=n(77),p=function(){function e(){}return Object.defineProperty(e.prototype,"componentInstance",{get:function(){return a.unimplemented()},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"nativeElement",{get:function(){return a.unimplemented()},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"elementRef",{get:function(){return a.unimplemented()},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"children",{get:function(){return a.unimplemented()},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"componentViewChildren",{get:function(){return a.unimplemented()},enumerable:!0,configurable:!0}),e.prototype.query=function(e,t){void 0===t&&(t=h.all);var n=this.queryAll(e,t);return n.length>0?n[0]:null},e.prototype.queryAll=function(e,t){void 0===t&&(t=h.all);var n=t(this);return n.filter(e)},e}();t.DebugElement=p;var l=function(e){function t(t,n){e.call(this),this._parentView=t,this._boundElementIndex=n,this._elementInjector=this._parentView.elementInjectors[this._boundElementIndex]}return o(t,e),Object.defineProperty(t.prototype,"componentInstance",{get:function(){return s.isPresent(this._elementInjector)?this._elementInjector.getComponent():null},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"nativeElement",{get:function(){return this.elementRef.nativeElement},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"elementRef",{get:function(){return this._parentView.elementRefs[this._boundElementIndex]},enumerable:!0,configurable:!0}),t.prototype.getDirectiveInstance=function(e){return this._elementInjector.getDirectiveAtIndex(e)},Object.defineProperty(t.prototype,"children",{get:function(){return this._getChildElements(this._parentView,this._boundElementIndex)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"componentViewChildren",{get:function(){var e=this._parentView.getNestedView(this._boundElementIndex);return s.isPresent(e)&&e.proto.type===c.ViewType.COMPONENT?this._getChildElements(e,null):[]},enumerable:!0,configurable:!0}),t.prototype.triggerEventHandler=function(e,t){this._parentView.triggerEventHandlers(e,t,this._boundElementIndex)},t.prototype.hasDirective=function(e){return s.isPresent(this._elementInjector)?this._elementInjector.hasDirective(e):!1},t.prototype.inject=function(e){return s.isPresent(this._elementInjector)?this._elementInjector.get(e):null},t.prototype.getLocal=function(e){return this._parentView.locals.get(e)},t.prototype._getChildElements=function(e,n){var r=this,i=[],o=null;s.isPresent(n)&&(o=e.proto.elementBinders[n-e.elementOffset]);for(var a=0;ao?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(5),s=n(60),a=n(2),c=n(107),u=function(){function e(){}return e.prototype.createSubscription=function(e,t){return s.ObservableWrapper.subscribe(e,t,function(e){throw e})},e.prototype.dispose=function(e){s.ObservableWrapper.dispose(e)},e.prototype.onDestroy=function(e){s.ObservableWrapper.dispose(e)},e}(),p=function(){function e(){}return e.prototype.createSubscription=function(e,t){return e.then(t)},e.prototype.dispose=function(e){},e.prototype.onDestroy=function(e){},e}(),l=new p,h=new u,f=function(){function e(e){this._latestValue=null,this._latestReturnedValue=null,this._subscription=null,this._obj=null,this._strategy=null,this._ref=e}return e.prototype.ngOnDestroy=function(){o.isPresent(this._subscription)&&this._dispose()},e.prototype.transform=function(e,t){return o.isBlank(this._obj)?(o.isPresent(e)&&this._subscribe(e),this._latestValue):e!==this._obj?(this._dispose(),this.transform(e)):this._latestValue===this._latestReturnedValue?this._latestReturnedValue:(this._latestReturnedValue=this._latestValue,a.WrappedValue.wrap(this._latestValue))},e.prototype._subscribe=function(e){var t=this;this._obj=e,this._strategy=this._selectStrategy(e),this._subscription=this._strategy.createSubscription(e,function(n){return t._updateLatestValue(e,n)})},e.prototype._selectStrategy=function(t){if(o.isPromise(t))return l;if(s.ObservableWrapper.isObservable(t))return h;throw new c.InvalidPipeArgumentException(e,t)},e.prototype._dispose=function(){this._strategy.dispose(this._subscription),this._latestValue=null,this._latestReturnedValue=null,this._subscription=null,this._obj=null},e.prototype._updateLatestValue=function(e,t){e===this._obj&&(this._latestValue=t,this._ref.markForCheck())},e=r([a.Pipe({name:"async",pure:!1}),a.Injectable(),i("design:paramtypes",[a.ChangeDetectorRef])],e)}();t.AsyncPipe=f},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=n(5),o=n(14),s=function(e){function t(t,n){e.call(this,"Invalid argument '"+n+"' for pipe '"+i.stringify(t)+"'")}return r(t,e),t}(o.BaseException);t.InvalidPipeArgumentException=s},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(5),s=n(2),a=n(107),c=function(){function e(){}return e.prototype.transform=function(t,n){if(void 0===n&&(n=null),o.isBlank(t))return t;if(!o.isString(t))throw new a.InvalidPipeArgumentException(e,t);return t.toUpperCase()},e=r([o.CONST(),s.Pipe({name:"uppercase"}),s.Injectable(),i("design:paramtypes",[])],e)}();t.UpperCasePipe=c},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(5),s=n(2),a=n(107),c=function(){function e(){}return e.prototype.transform=function(t,n){if(void 0===n&&(n=null),o.isBlank(t))return t;if(!o.isString(t))throw new a.InvalidPipeArgumentException(e,t);return t.toLowerCase()},e=r([o.CONST(),s.Pipe({name:"lowercase"}),s.Injectable(),i("design:paramtypes",[])],e)}();t.LowerCasePipe=c},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(5),s=n(2),a=function(){function e(){}return e.prototype.transform=function(e,t){return void 0===t&&(t=null),o.Json.stringify(e)},e=r([o.CONST(),s.Pipe({name:"json",pure:!1}),s.Injectable(),i("design:paramtypes",[])],e)}();t.JsonPipe=a},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(5),s=n(14),a=n(12),c=n(2),u=n(107),p=function(){function e(){}return e.prototype.transform=function(t,n){if(void 0===n&&(n=null),o.isBlank(n)||0==n.length)throw new s.BaseException("Slice pipe requires one argument");if(!this.supports(t))throw new u.InvalidPipeArgumentException(e,t);if(o.isBlank(t))return t;var r=n[0],i=n.length>1?n[1]:null;return o.isString(t)?o.StringWrapper.slice(t,r,i):a.ListWrapper.slice(t,r,i)},e.prototype.supports=function(e){return o.isString(e)||o.isArray(e)},e=r([c.Pipe({name:"slice",pure:!1}),c.Injectable(),i("design:paramtypes",[])],e)}();t.SlicePipe=p},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(5),s=n(113),a=n(2),c=n(12),u=n(107),p="en-US",l=function(){function e(){}return e.prototype.transform=function(t,n){if(o.isBlank(t))return null;if(!this.supports(t))throw new u.InvalidPipeArgumentException(e,t);var r=o.isPresent(n)&&n.length>0?n[0]:"mediumDate";return o.isNumber(t)&&(t=o.DateWrapper.fromMillis(t)),c.StringMapWrapper.contains(e._ALIASES,r)&&(r=c.StringMapWrapper.get(e._ALIASES,r)),s.DateFormatter.format(t,p,r)},e.prototype.supports=function(e){return o.isDate(e)||o.isNumber(e)},e._ALIASES={medium:"yMMMdjms","short":"yMdjm",fullDate:"yMMMMEEEEd",longDate:"yMMMMd",mediumDate:"yMMMd",shortDate:"yMd",mediumTime:"jms",shortTime:"jm"},e=r([o.CONST(),a.Pipe({name:"date",pure:!0}),a.Injectable(),i("design:paramtypes",[])],e)}();t.DatePipe=l},function(e,t){function n(e){return 2==e?"2-digit":"numeric"}function r(e){return 4>e?"short":"long"}function i(e){for(var t,i={},o=0;o=3?i.month=r(s):i.month=n(s);break;case"d":i.day=n(s);break;case"E":i.weekday=r(s);break;case"j":i.hour=n(s);break;case"h":i.hour=n(s),i.hour12=!0;break;case"H":i.hour=n(s),i.hour12=!1;break;case"m":i.minute=n(s);break;case"s":i.second=n(s);break;case"z":i.timeZoneName="long";break;case"Z":i.timeZoneName="short"}o=t}return i}!function(e){e[e.Decimal=0]="Decimal",e[e.Percent=1]="Percent",e[e.Currency=2]="Currency"}(t.NumberFormatStyle||(t.NumberFormatStyle={}));var o=t.NumberFormatStyle,s=function(){function e(){}return e.format=function(e,t,n,r){var i=void 0===r?{}:r,s=i.minimumIntegerDigits,a=void 0===s?1:s,c=i.minimumFractionDigits,u=void 0===c?0:c,p=i.maximumFractionDigits,l=void 0===p?3:p,h=i.currency,f=i.currencyAsSymbol,d=void 0===f?!1:f,y={minimumIntegerDigits:a,minimumFractionDigits:u,maximumFractionDigits:l};return y.style=o[n].toLowerCase(),n==o.Currency&&(y.currency=h,y.currencyDisplay=d?"symbol":"code"),new Intl.NumberFormat(t,y).format(e)},e}();t.NumberFormatter=s;var a=new Map,c=function(){function e(){}return e.format=function(e,t,n){var r=t+n;if(a.has(r))return a.get(r).format(e);var o=new Intl.DateTimeFormat(t,i(n));return a.set(r,o),o.format(e)},e}();t.DateFormatter=c},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=n(5),a=n(14),c=n(113),u=n(2),p=n(12),l=n(107),h="en-US",f=s.RegExpWrapper.create("^(\\d+)?\\.((\\d+)(\\-(\\d+))?)?$"),d=function(){function e(){}return e._format=function(t,n,r,i,o){if(void 0===i&&(i=null),void 0===o&&(o=!1),s.isBlank(t))return null;if(!s.isNumber(t))throw new l.InvalidPipeArgumentException(e,t);var u=1,p=0,d=3;if(s.isPresent(r)){var y=s.RegExpWrapper.firstMatch(f,r);if(s.isBlank(y))throw new a.BaseException(r+" is not a valid digit info for number pipes");s.isPresent(y[1])&&(u=s.NumberWrapper.parseIntAutoRadix(y[1])),s.isPresent(y[3])&&(p=s.NumberWrapper.parseIntAutoRadix(y[3])),s.isPresent(y[5])&&(d=s.NumberWrapper.parseIntAutoRadix(y[5]))}return c.NumberFormatter.format(t,h,n,{minimumIntegerDigits:u,minimumFractionDigits:p,maximumFractionDigits:d,currency:i,currencyAsSymbol:o})},e=i([s.CONST(),u.Injectable(),o("design:paramtypes",[])],e)}();t.NumberPipe=d;var y=function(e){function t(){e.apply(this,arguments)}return r(t,e),t.prototype.transform=function(e,t){var n=p.ListWrapper.first(t);return d._format(e,c.NumberFormatStyle.Decimal,n)},t=i([s.CONST(),u.Pipe({name:"number"}),u.Injectable(),o("design:paramtypes",[])],t)}(d);t.DecimalPipe=y;var v=function(e){function t(){e.apply(this,arguments)}return r(t,e),t.prototype.transform=function(e,t){var n=p.ListWrapper.first(t);return d._format(e,c.NumberFormatStyle.Percent,n)},t=i([s.CONST(),u.Pipe({name:"percent"}),u.Injectable(),o("design:paramtypes",[])],t)}(d);t.PercentPipe=v;var m=function(e){function t(){e.apply(this,arguments)}return r(t,e),t.prototype.transform=function(e,t){var n=s.isPresent(t)&&t.length>0?t[0]:"USD",r=s.isPresent(t)&&t.length>1?t[1]:!1,i=s.isPresent(t)&&t.length>2?t[2]:null;return d._format(e,c.NumberFormatStyle.Currency,i,n,r)},t=i([s.CONST(),u.Pipe({name:"currency"}),u.Injectable(),o("design:paramtypes",[])],t)}(d);t.CurrencyPipe=m},function(e,t,n){function r(e){for(var n in e)t.hasOwnProperty(n)||(t[n]=e[n])}var i=n(116);t.NgClass=i.NgClass;var o=n(117);t.NgFor=o.NgFor;var s=n(118);t.NgIf=s.NgIf;var a=n(119);t.NgStyle=a.NgStyle;var c=n(120);t.NgSwitch=c.NgSwitch,t.NgSwitchWhen=c.NgSwitchWhen,t.NgSwitchDefault=c.NgSwitchDefault,r(n(121));var u=n(122);t.CORE_DIRECTIVES=u.CORE_DIRECTIVES},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(5),s=n(2),a=n(12),c=function(){function e(e,t,n,r){this._iterableDiffers=e,this._keyValueDiffers=t,this._ngEl=n,this._renderer=r,this._initialClasses=[]}return Object.defineProperty(e.prototype,"initialClasses",{set:function(e){this._applyInitialClasses(!0),this._initialClasses=o.isPresent(e)&&o.isString(e)?e.split(" "):[],this._applyInitialClasses(!1),this._applyClasses(this._rawClass,!1)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"rawClass",{set:function(e){this._cleanupClasses(this._rawClass),o.isString(e)&&(e=e.split(" ")),this._rawClass=e,o.isPresent(e)?a.isListLikeIterable(e)?(this._differ=this._iterableDiffers.find(e).create(null),this._mode="iterable"):(this._differ=this._keyValueDiffers.find(e).create(null),this._mode="keyValue"):this._differ=null},enumerable:!0,configurable:!0}),e.prototype.ngDoCheck=function(){if(o.isPresent(this._differ)){var e=this._differ.diff(this._rawClass);o.isPresent(e)&&("iterable"==this._mode?this._applyIterableChanges(e):this._applyKeyValueChanges(e))}},e.prototype.ngOnDestroy=function(){this._cleanupClasses(this._rawClass)},e.prototype._cleanupClasses=function(e){this._applyClasses(e,!0),this._applyInitialClasses(!1)},e.prototype._applyKeyValueChanges=function(e){var t=this;e.forEachAddedItem(function(e){t._toggleClass(e.key,e.currentValue)}),e.forEachChangedItem(function(e){t._toggleClass(e.key,e.currentValue)}),e.forEachRemovedItem(function(e){e.previousValue&&t._toggleClass(e.key,!1)})},e.prototype._applyIterableChanges=function(e){ -var t=this;e.forEachAddedItem(function(e){t._toggleClass(e.item,!0)}),e.forEachRemovedItem(function(e){t._toggleClass(e.item,!1)})},e.prototype._applyInitialClasses=function(e){var t=this;this._initialClasses.forEach(function(n){return t._toggleClass(n,!e)})},e.prototype._applyClasses=function(e,t){var n=this;o.isPresent(e)&&(o.isArray(e)?e.forEach(function(e){return n._toggleClass(e,!t)}):e instanceof Set?e.forEach(function(e){return n._toggleClass(e,!t)}):a.StringMapWrapper.forEach(e,function(e,r){e&&n._toggleClass(r,!t)}))},e.prototype._toggleClass=function(e,t){if(e=e.trim(),e.length>0)if(e.indexOf(" ")>-1)for(var n=e.split(/\s+/g),r=0,i=n.length;i>r;r++)this._renderer.setElementClass(this._ngEl,n[r],t);else this._renderer.setElementClass(this._ngEl,e,t)},e=r([s.Directive({selector:"[ngClass]",inputs:["rawClass: ngClass","initialClasses: class"]}),i("design:paramtypes",[s.IterableDiffers,s.KeyValueDiffers,s.ElementRef,s.Renderer])],e)}();t.NgClass=c},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(2),s=n(5),a=function(){function e(e,t,n,r){this._viewContainer=e,this._templateRef=t,this._iterableDiffers=n,this._cdr=r}return Object.defineProperty(e.prototype,"ngForOf",{set:function(e){this._ngForOf=e,s.isBlank(this._differ)&&s.isPresent(e)&&(this._differ=this._iterableDiffers.find(e).create(this._cdr))},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"ngForTemplate",{set:function(e){s.isPresent(e)&&(this._templateRef=e)},enumerable:!0,configurable:!0}),e.prototype.ngDoCheck=function(){if(s.isPresent(this._differ)){var e=this._differ.diff(this._ngForOf);s.isPresent(e)&&this._applyChanges(e)}},e.prototype._applyChanges=function(e){var t=[];e.forEachRemovedItem(function(e){return t.push(new c(e,null))}),e.forEachMovedItem(function(e){return t.push(new c(e,null))});var n=this._bulkRemove(t);e.forEachAddedItem(function(e){return n.push(new c(e,null))}),this._bulkInsert(n);for(var r=0;rr;r++)this._viewContainer.get(r).setLocal("last",r===i-1)},e.prototype._perViewChange=function(e,t){e.setLocal("$implicit",t.item),e.setLocal("index",t.currentIndex),e.setLocal("even",t.currentIndex%2==0),e.setLocal("odd",t.currentIndex%2==1)},e.prototype._bulkRemove=function(e){e.sort(function(e,t){return e.record.previousIndex-t.record.previousIndex});for(var t=[],n=e.length-1;n>=0;n--){var r=e[n];s.isPresent(r.record.currentIndex)?(r.view=this._viewContainer.detach(r.record.previousIndex),t.push(r)):this._viewContainer.remove(r.record.previousIndex)}return t},e.prototype._bulkInsert=function(e){e.sort(function(e,t){return e.record.currentIndex-t.record.currentIndex});for(var t=0;to?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(2),s=n(5),a=function(){function e(e,t){this._viewContainer=e,this._templateRef=t,this._prevCondition=null}return Object.defineProperty(e.prototype,"ngIf",{set:function(e){!e||!s.isBlank(this._prevCondition)&&this._prevCondition?e||!s.isBlank(this._prevCondition)&&!this._prevCondition||(this._prevCondition=!1,this._viewContainer.clear()):(this._prevCondition=!0,this._viewContainer.createEmbeddedView(this._templateRef))},enumerable:!0,configurable:!0}),e=r([o.Directive({selector:"[ngIf]",inputs:["ngIf"]}),i("design:paramtypes",[o.ViewContainerRef,o.TemplateRef])],e)}();t.NgIf=a},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(2),s=n(5),a=function(){function e(e,t,n){this._differs=e,this._ngEl=t,this._renderer=n}return Object.defineProperty(e.prototype,"rawStyle",{set:function(e){this._rawStyle=e,s.isBlank(this._differ)&&s.isPresent(e)&&(this._differ=this._differs.find(this._rawStyle).create(null))},enumerable:!0,configurable:!0}),e.prototype.ngDoCheck=function(){if(s.isPresent(this._differ)){var e=this._differ.diff(this._rawStyle);s.isPresent(e)&&this._applyChanges(e)}},e.prototype._applyChanges=function(e){var t=this;e.forEachAddedItem(function(e){t._setStyle(e.key,e.currentValue)}),e.forEachChangedItem(function(e){t._setStyle(e.key,e.currentValue)}),e.forEachRemovedItem(function(e){t._setStyle(e.key,null)})},e.prototype._setStyle=function(e,t){this._renderer.setElementStyle(this._ngEl,e,t)},e=r([o.Directive({selector:"[ngStyle]",inputs:["rawStyle: ngStyle"]}),i("design:paramtypes",[o.KeyValueDiffers,o.ElementRef,o.Renderer])],e)}();t.NgStyle=a},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},s=n(2),a=n(5),c=n(12),u=a.CONST_EXPR(new Object),p=function(){function e(e,t){this._viewContainerRef=e,this._templateRef=t}return e.prototype.create=function(){this._viewContainerRef.createEmbeddedView(this._templateRef)},e.prototype.destroy=function(){this._viewContainerRef.clear()},e}(),l=function(){function e(){this._useDefault=!1,this._valueViews=new c.Map,this._activeViews=[]}return Object.defineProperty(e.prototype,"ngSwitch",{set:function(e){this._emptyAllActiveViews(),this._useDefault=!1;var t=this._valueViews.get(e);a.isBlank(t)&&(this._useDefault=!0,t=a.normalizeBlank(this._valueViews.get(u))),this._activateViews(t),this._switchValue=e},enumerable:!0,configurable:!0}),e.prototype._onWhenValueChanged=function(e,t,n){this._deregisterView(e,n),this._registerView(t,n),e===this._switchValue?(n.destroy(),c.ListWrapper.remove(this._activeViews,n)):t===this._switchValue&&(this._useDefault&&(this._useDefault=!1,this._emptyAllActiveViews()),n.create(),this._activeViews.push(n)),0!==this._activeViews.length||this._useDefault||(this._useDefault=!0,this._activateViews(this._valueViews.get(u)))},e.prototype._emptyAllActiveViews=function(){for(var e=this._activeViews,t=0;to?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},a=n(5),c=n(60),u=n(2),p=n(126),l=n(128),h=n(129),f=n(130),d=n(131),y=a.CONST_EXPR(new u.Provider(l.NgControl,{useExisting:u.forwardRef(function(){return v})})),v=function(e){function t(t,n,r,i){e.call(this),this._parent=t,this._validators=n,this._asyncValidators=r,this.update=new c.EventEmitter,this._added=!1,this.valueAccessor=f.selectValueAccessor(this,i)}return r(t,e),t.prototype.ngOnChanges=function(e){this._added||(this.formDirective.addControl(this),this._added=!0),f.isPropertyUpdated(e,this.viewModel)&&(this.viewModel=this.model,this.formDirective.updateModel(this,this.model))},t.prototype.ngOnDestroy=function(){this.formDirective.removeControl(this)},t.prototype.viewToModelUpdate=function(e){this.viewModel=e,c.ObservableWrapper.callEmit(this.update,e)},Object.defineProperty(t.prototype,"path",{get:function(){return f.controlPath(this.name,this._parent)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"formDirective",{get:function(){return this._parent.formDirective},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"validator",{get:function(){return f.composeValidators(this._validators)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"asyncValidator",{get:function(){return f.composeAsyncValidators(this._asyncValidators)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"control",{get:function(){return this.formDirective.getControl(this)},enumerable:!0,configurable:!0}),t=i([u.Directive({selector:"[ngControl]",bindings:[y],inputs:["name: ngControl","model: ngModel"],outputs:["update: ngModelChange"],exportAs:"ngForm"}),s(0,u.Host()),s(0,u.SkipSelf()),s(1,u.Optional()),s(1,u.Self()),s(1,u.Inject(d.NG_VALIDATORS)),s(2,u.Optional()),s(2,u.Self()),s(2,u.Inject(d.NG_ASYNC_VALIDATORS)),s(3,u.Optional()),s(3,u.Self()),s(3,u.Inject(h.NG_VALUE_ACCESSOR)),o("design:paramtypes",[p.ControlContainer,Array,Array,Array])],t)}(l.NgControl);t.NgControlName=v},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=n(125),o=n(14),s=function(e){function t(){e.apply(this,arguments),this.name=null,this.valueAccessor=null}return r(t,e),Object.defineProperty(t.prototype,"validator",{get:function(){return o.unimplemented()},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"asyncValidator",{get:function(){return o.unimplemented()},enumerable:!0,configurable:!0}),t}(i.AbstractControlDirective);t.NgControl=s},function(e,t,n){var r=n(2),i=n(5);t.NG_VALUE_ACCESSOR=i.CONST_EXPR(new r.OpaqueToken("NgValueAccessor"))},function(e,t,n){function r(e,t){var n=l.ListWrapper.clone(t.path);return n.push(e),n}function i(e,t){h.isBlank(e)&&s(t,"Cannot find control"),h.isBlank(t.valueAccessor)&&s(t,"No value accessor for"),e.validator=d.Validators.compose([e.validator,t.validator]),e.asyncValidator=d.Validators.composeAsync([e.asyncValidator,t.asyncValidator]),t.valueAccessor.writeValue(e.value),t.valueAccessor.registerOnChange(function(n){t.viewToModelUpdate(n),e.updateValue(n,{emitModelToViewChange:!1}),e.markAsDirty()}),e.registerOnChange(function(e){return t.valueAccessor.writeValue(e)}),t.valueAccessor.registerOnTouched(function(){return e.markAsTouched()})}function o(e,t){h.isBlank(e)&&s(t,"Cannot find control"),e.validator=d.Validators.compose([e.validator,t.validator]),e.asyncValidator=d.Validators.composeAsync([e.asyncValidator,t.asyncValidator])}function s(e,t){var n=e.path.join(" -> ");throw new f.BaseException(t+" '"+n+"'")}function a(e){return h.isPresent(e)?d.Validators.compose(e.map(_.normalizeValidator)):null}function c(e){return h.isPresent(e)?d.Validators.composeAsync(e.map(_.normalizeValidator)):null}function u(e,t){if(!l.StringMapWrapper.contains(e,"model"))return!1;var n=e.model;return n.isFirstChange()?!0:!h.looseIdentical(t,n.currentValue)}function p(e,t){if(h.isBlank(t))return null;var n,r,i;return t.forEach(function(t){t instanceof y.DefaultValueAccessor?n=t:t instanceof m.CheckboxControlValueAccessor||t instanceof v.NumberValueAccessor||t instanceof g.SelectControlValueAccessor?(h.isPresent(r)&&s(e,"More than one built-in value accessor matches"),r=t):(h.isPresent(i)&&s(e,"More than one custom value accessor matches"),i=t)}),h.isPresent(i)?i:h.isPresent(r)?r:h.isPresent(n)?n:(s(e,"No valid value accessor for"),null)}var l=n(12),h=n(5),f=n(14),d=n(131),y=n(132),v=n(133),m=n(134),g=n(135),_=n(136);t.controlPath=r,t.setUpControl=i,t.setUpControlGroup=o,t.composeValidators=a,t.composeAsyncValidators=c,t.isPropertyUpdated=u,t.selectValueAccessor=p},function(e,t,n){function r(e){return a.PromiseWrapper.isPromise(e)?e:c.ObservableWrapper.toPromise(e)}function i(e,t){return t.map(function(t){return t(e)})}function o(e){var t=e.reduce(function(e,t){return s.isPresent(t)?u.StringMapWrapper.merge(e,t):e},{});return u.StringMapWrapper.isEmpty(t)?null:t}var s=n(5),a=n(61),c=n(60),u=n(12),p=n(2);t.NG_VALIDATORS=s.CONST_EXPR(new p.OpaqueToken("NgValidators")),t.NG_ASYNC_VALIDATORS=s.CONST_EXPR(new p.OpaqueToken("NgAsyncValidators"));var l=function(){function e(){}return e.required=function(e){return s.isBlank(e.value)||""==e.value?{required:!0}:null},e.minLength=function(t){return function(n){if(s.isPresent(e.required(n)))return null;var r=n.value;return r.lengtht?{maxlength:{requiredLength:t,actualLength:r.length}}:null}},e.nullValidator=function(e){return null},e.compose=function(e){if(s.isBlank(e))return null;var t=e.filter(s.isPresent);return 0==t.length?null:function(e){return o(i(e,t))}},e.composeAsync=function(e){if(s.isBlank(e))return null;var t=e.filter(s.isPresent);return 0==t.length?null:function(e){var n=i(e,t).map(r);return a.PromiseWrapper.all(n).then(o)}},e}();t.Validators=l},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(2),s=n(129),a=n(5),c=a.CONST_EXPR(new o.Provider(s.NG_VALUE_ACCESSOR,{useExisting:o.forwardRef(function(){return u}),multi:!0})),u=function(){function e(e,t){this._renderer=e,this._elementRef=t,this.onChange=function(e){},this.onTouched=function(){}}return e.prototype.writeValue=function(e){var t=a.isBlank(e)?"":e;this._renderer.setElementProperty(this._elementRef,"value",t)},e.prototype.registerOnChange=function(e){this.onChange=e},e.prototype.registerOnTouched=function(e){this.onTouched=e},e=r([o.Directive({selector:"input:not([type=checkbox])[ngControl],textarea[ngControl],input:not([type=checkbox])[ngFormControl],textarea[ngFormControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]",host:{"(input)":"onChange($event.target.value)","(blur)":"onTouched()"},bindings:[c]}),i("design:paramtypes",[o.Renderer,o.ElementRef])],e)}();t.DefaultValueAccessor=u},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(2),s=n(129),a=n(5),c=a.CONST_EXPR(new o.Provider(s.NG_VALUE_ACCESSOR,{useExisting:o.forwardRef(function(){return u}),multi:!0})),u=function(){function e(e,t){this._renderer=e,this._elementRef=t,this.onChange=function(e){},this.onTouched=function(){}}return e.prototype.writeValue=function(e){this._renderer.setElementProperty(this._elementRef,"value",e)},e.prototype.registerOnChange=function(e){this.onChange=function(t){e(a.NumberWrapper.parseFloat(t))}},e.prototype.registerOnTouched=function(e){this.onTouched=e},e=r([o.Directive({selector:"input[type=number][ngControl],input[type=number][ngFormControl],input[type=number][ngModel]",host:{"(change)":"onChange($event.target.value)","(input)":"onChange($event.target.value)","(blur)":"onTouched()"},bindings:[c]}),i("design:paramtypes",[o.Renderer,o.ElementRef])],e)}();t.NumberValueAccessor=u},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(2),s=n(129),a=n(5),c=a.CONST_EXPR(new o.Provider(s.NG_VALUE_ACCESSOR,{useExisting:o.forwardRef(function(){return u}),multi:!0})),u=function(){function e(e,t){this._renderer=e,this._elementRef=t,this.onChange=function(e){},this.onTouched=function(){}}return e.prototype.writeValue=function(e){this._renderer.setElementProperty(this._elementRef,"checked",e)},e.prototype.registerOnChange=function(e){this.onChange=e},e.prototype.registerOnTouched=function(e){this.onTouched=e},e=r([o.Directive({selector:"input[type=checkbox][ngControl],input[type=checkbox][ngFormControl],input[type=checkbox][ngModel]",host:{"(change)":"onChange($event.target.checked)","(blur)":"onTouched()"},bindings:[c]}),i("design:paramtypes",[o.Renderer,o.ElementRef])],e)}();t.CheckboxControlValueAccessor=u},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0; -},o=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},s=n(2),a=n(60),c=n(129),u=n(5),p=u.CONST_EXPR(new s.Provider(c.NG_VALUE_ACCESSOR,{useExisting:s.forwardRef(function(){return h}),multi:!0})),l=function(){function e(){}return e=r([s.Directive({selector:"option"}),i("design:paramtypes",[])],e)}();t.NgSelectOption=l;var h=function(){function e(e,t,n){this._renderer=e,this._elementRef=t,this.onChange=function(e){},this.onTouched=function(){},this._updateValueWhenListOfOptionsChanges(n)}return e.prototype.writeValue=function(e){this.value=e,this._renderer.setElementProperty(this._elementRef,"value",e)},e.prototype.registerOnChange=function(e){this.onChange=e},e.prototype.registerOnTouched=function(e){this.onTouched=e},e.prototype._updateValueWhenListOfOptionsChanges=function(e){var t=this;a.ObservableWrapper.subscribe(e.changes,function(e){return t.writeValue(t.value)})},e=r([s.Directive({selector:"select[ngControl],select[ngFormControl],select[ngModel]",host:{"(change)":"onChange($event.target.value)","(input)":"onChange($event.target.value)","(blur)":"onTouched()"},bindings:[p]}),o(2,s.Query(l,{descendants:!0})),i("design:paramtypes",[s.Renderer,s.ElementRef,s.QueryList])],e)}();t.SelectControlValueAccessor=h},function(e,t){function n(e){return void 0!==e.validate?function(t){return e.validate(t)}:e}t.normalizeValidator=n},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},a=n(5),c=n(12),u=n(60),p=n(2),l=n(128),h=n(131),f=n(129),d=n(130),y=a.CONST_EXPR(new p.Provider(l.NgControl,{useExisting:p.forwardRef(function(){return v})})),v=function(e){function t(t,n,r){e.call(this),this._validators=t,this._asyncValidators=n,this.update=new u.EventEmitter,this.valueAccessor=d.selectValueAccessor(this,r)}return r(t,e),t.prototype.ngOnChanges=function(e){this._isControlChanged(e)&&(d.setUpControl(this.form,this),this.form.updateValueAndValidity({emitEvent:!1})),d.isPropertyUpdated(e,this.viewModel)&&(this.form.updateValue(this.model),this.viewModel=this.model)},Object.defineProperty(t.prototype,"path",{get:function(){return[]},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"validator",{get:function(){return d.composeValidators(this._validators)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"asyncValidator",{get:function(){return d.composeAsyncValidators(this._asyncValidators)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"control",{get:function(){return this.form},enumerable:!0,configurable:!0}),t.prototype.viewToModelUpdate=function(e){this.viewModel=e,u.ObservableWrapper.callEmit(this.update,e)},t.prototype._isControlChanged=function(e){return c.StringMapWrapper.contains(e,"form")},t=i([p.Directive({selector:"[ngFormControl]",bindings:[y],inputs:["form: ngFormControl","model: ngModel"],outputs:["update: ngModelChange"],exportAs:"ngForm"}),s(0,p.Optional()),s(0,p.Self()),s(0,p.Inject(h.NG_VALIDATORS)),s(1,p.Optional()),s(1,p.Self()),s(1,p.Inject(h.NG_ASYNC_VALIDATORS)),s(2,p.Optional()),s(2,p.Self()),s(2,p.Inject(f.NG_VALUE_ACCESSOR)),o("design:paramtypes",[Array,Array,Array])],t)}(l.NgControl);t.NgFormControl=v},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},a=n(5),c=n(60),u=n(2),p=n(129),l=n(128),h=n(124),f=n(131),d=n(130),y=a.CONST_EXPR(new u.Provider(l.NgControl,{useExisting:u.forwardRef(function(){return v})})),v=function(e){function t(t,n,r){e.call(this),this._validators=t,this._asyncValidators=n,this._control=new h.Control,this._added=!1,this.update=new c.EventEmitter,this.valueAccessor=d.selectValueAccessor(this,r)}return r(t,e),t.prototype.ngOnChanges=function(e){this._added||(d.setUpControl(this._control,this),this._control.updateValueAndValidity({emitEvent:!1}),this._added=!0),d.isPropertyUpdated(e,this.viewModel)&&(this._control.updateValue(this.model),this.viewModel=this.model)},Object.defineProperty(t.prototype,"control",{get:function(){return this._control},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"path",{get:function(){return[]},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"validator",{get:function(){return d.composeValidators(this._validators)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"asyncValidator",{get:function(){return d.composeAsyncValidators(this._asyncValidators)},enumerable:!0,configurable:!0}),t.prototype.viewToModelUpdate=function(e){this.viewModel=e,c.ObservableWrapper.callEmit(this.update,e)},t=i([u.Directive({selector:"[ngModel]:not([ngControl]):not([ngFormControl])",bindings:[y],inputs:["model: ngModel"],outputs:["update: ngModelChange"],exportAs:"ngForm"}),s(0,u.Optional()),s(0,u.Self()),s(0,u.Inject(f.NG_VALIDATORS)),s(1,u.Optional()),s(1,u.Self()),s(1,u.Inject(f.NG_ASYNC_VALIDATORS)),s(2,u.Optional()),s(2,u.Self()),s(2,u.Inject(p.NG_VALUE_ACCESSOR)),o("design:paramtypes",[Array,Array,Array])],t)}(l.NgControl);t.NgModel=v},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},a=n(2),c=n(5),u=n(126),p=n(130),l=n(131),h=c.CONST_EXPR(new a.Provider(u.ControlContainer,{useExisting:a.forwardRef(function(){return f})})),f=function(e){function t(t,n,r){e.call(this),this._validators=n,this._asyncValidators=r,this._parent=t}return r(t,e),t.prototype.ngOnInit=function(){this.formDirective.addControlGroup(this)},t.prototype.ngOnDestroy=function(){this.formDirective.removeControlGroup(this)},Object.defineProperty(t.prototype,"control",{get:function(){return this.formDirective.getControlGroup(this)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"path",{get:function(){return p.controlPath(this.name,this._parent)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"formDirective",{get:function(){return this._parent.formDirective},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"validator",{get:function(){return p.composeValidators(this._validators)},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"asyncValidator",{get:function(){return p.composeAsyncValidators(this._asyncValidators)},enumerable:!0,configurable:!0}),t=i([a.Directive({selector:"[ngControlGroup]",providers:[h],inputs:["name: ngControlGroup"],exportAs:"ngForm"}),s(0,a.Host()),s(0,a.SkipSelf()),s(1,a.Optional()),s(1,a.Self()),s(1,a.Inject(l.NG_VALIDATORS)),s(2,a.Optional()),s(2,a.Self()),s(2,a.Inject(l.NG_ASYNC_VALIDATORS)),o("design:paramtypes",[u.ControlContainer,Array,Array])],t)}(u.ControlContainer);t.NgControlGroup=f},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},a=n(5),c=n(12),u=n(60),p=n(2),l=n(126),h=n(130),f=n(131),d=a.CONST_EXPR(new p.Provider(l.ControlContainer,{useExisting:p.forwardRef(function(){return y})})),y=function(e){function t(t,n){e.call(this),this._validators=t,this._asyncValidators=n,this.form=null,this.directives=[],this.ngSubmit=new u.EventEmitter}return r(t,e),t.prototype.ngOnChanges=function(e){if(c.StringMapWrapper.contains(e,"form")){var t=h.composeValidators(this._validators);this.form.validator=f.Validators.compose([this.form.validator,t]);var n=h.composeAsyncValidators(this._asyncValidators);this.form.asyncValidator=f.Validators.composeAsync([this.form.asyncValidator,n]),this.form.updateValueAndValidity({onlySelf:!0,emitEvent:!1})}this._updateDomValue()},Object.defineProperty(t.prototype,"formDirective",{get:function(){return this},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"control",{get:function(){return this.form},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"path",{get:function(){return[]},enumerable:!0,configurable:!0}),t.prototype.addControl=function(e){var t=this.form.find(e.path);h.setUpControl(t,e),t.updateValueAndValidity({emitEvent:!1}),this.directives.push(e)},t.prototype.getControl=function(e){return this.form.find(e.path)},t.prototype.removeControl=function(e){c.ListWrapper.remove(this.directives,e)},t.prototype.addControlGroup=function(e){var t=this.form.find(e.path);h.setUpControlGroup(t,e),t.updateValueAndValidity({emitEvent:!1})},t.prototype.removeControlGroup=function(e){},t.prototype.getControlGroup=function(e){return this.form.find(e.path)},t.prototype.updateModel=function(e,t){var n=this.form.find(e.path);n.updateValue(t)},t.prototype.onSubmit=function(){return u.ObservableWrapper.callEmit(this.ngSubmit,null),!1},t.prototype._updateDomValue=function(){var e=this;this.directives.forEach(function(t){var n=e.form.find(t.path);t.valueAccessor.writeValue(n.value)})},t=i([p.Directive({selector:"[ngFormModel]",bindings:[d],inputs:["form: ngFormModel"],host:{"(submit)":"onSubmit()"},outputs:["ngSubmit"],exportAs:"ngForm"}),s(0,p.Optional()),s(0,p.Self()),s(0,p.Inject(f.NG_VALIDATORS)),s(1,p.Optional()),s(1,p.Self()),s(1,p.Inject(f.NG_ASYNC_VALIDATORS)),o("design:paramtypes",[Array,Array])],t)}(l.ControlContainer);t.NgFormModel=y},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},a=n(60),c=n(12),u=n(5),p=n(2),l=n(126),h=n(124),f=n(130),d=n(131),y=u.CONST_EXPR(new p.Provider(l.ControlContainer,{useExisting:p.forwardRef(function(){return v})})),v=function(e){function t(t,n){e.call(this),this.ngSubmit=new a.EventEmitter,this.form=new h.ControlGroup({},null,f.composeValidators(t),f.composeAsyncValidators(n))}return r(t,e),Object.defineProperty(t.prototype,"formDirective",{get:function(){return this},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"control",{get:function(){return this.form},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"path",{get:function(){return[]},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"controls",{get:function(){return this.form.controls},enumerable:!0,configurable:!0}),t.prototype.addControl=function(e){var t=this;a.PromiseWrapper.scheduleMicrotask(function(){var n=t._findContainer(e.path),r=new h.Control;f.setUpControl(r,e),n.addControl(e.name,r),r.updateValueAndValidity({emitEvent:!1})})},t.prototype.getControl=function(e){return this.form.find(e.path)},t.prototype.removeControl=function(e){var t=this;a.PromiseWrapper.scheduleMicrotask(function(){var n=t._findContainer(e.path);u.isPresent(n)&&(n.removeControl(e.name),n.updateValueAndValidity({emitEvent:!1}))})},t.prototype.addControlGroup=function(e){var t=this;a.PromiseWrapper.scheduleMicrotask(function(){var n=t._findContainer(e.path),r=new h.ControlGroup({});f.setUpControlGroup(r,e),n.addControl(e.name,r),r.updateValueAndValidity({emitEvent:!1})})},t.prototype.removeControlGroup=function(e){var t=this;a.PromiseWrapper.scheduleMicrotask(function(){var n=t._findContainer(e.path);u.isPresent(n)&&(n.removeControl(e.name),n.updateValueAndValidity({emitEvent:!1}))})},t.prototype.getControlGroup=function(e){return this.form.find(e.path)},t.prototype.updateModel=function(e,t){var n=this;a.PromiseWrapper.scheduleMicrotask(function(){var r=n.form.find(e.path);r.updateValue(t)})},t.prototype.onSubmit=function(){return a.ObservableWrapper.callEmit(this.ngSubmit,null),!1},t.prototype._findContainer=function(e){return e.pop(),c.ListWrapper.isEmpty(e)?this.form:this.form.find(e)},t=i([p.Directive({selector:"form:not([ngNoForm]):not([ngFormModel]),ngForm,[ngForm]",bindings:[y],host:{"(submit)":"onSubmit()"},outputs:["ngSubmit"],exportAs:"ngForm"}),s(0,p.Optional()),s(0,p.Self()),s(0,p.Inject(d.NG_VALIDATORS)),s(1,p.Optional()),s(1,p.Self()),s(1,p.Inject(d.NG_ASYNC_VALIDATORS)),o("design:paramtypes",[Array,Array])],t)}(l.ControlContainer);t.NgForm=v},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},s=n(2),a=n(128),c=n(5),u=function(){function e(e){this._cd=e}return Object.defineProperty(e.prototype,"ngClassUntouched",{get:function(){return c.isPresent(this._cd.control)?this._cd.control.untouched:!1},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"ngClassTouched",{get:function(){return c.isPresent(this._cd.control)?this._cd.control.touched:!1},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"ngClassPristine",{get:function(){return c.isPresent(this._cd.control)?this._cd.control.pristine:!1},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"ngClassDirty",{get:function(){return c.isPresent(this._cd.control)?this._cd.control.dirty:!1},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"ngClassValid",{get:function(){return c.isPresent(this._cd.control)?this._cd.control.valid:!1},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"ngClassInvalid",{get:function(){return c.isPresent(this._cd.control)?!this._cd.control.valid:!1},enumerable:!0,configurable:!0}),e=r([s.Directive({selector:"[ngControl],[ngModel],[ngFormControl]",host:{"[class.ng-untouched]":"ngClassUntouched","[class.ng-touched]":"ngClassTouched","[class.ng-pristine]":"ngClassPristine","[class.ng-dirty]":"ngClassDirty","[class.ng-valid]":"ngClassValid","[class.ng-invalid]":"ngClassInvalid"}}),o(0,s.Self()),i("design:paramtypes",[a.NgControl])],e)}();t.NgControlStatus=u},function(e,t,n){var r=n(5),i=n(127),o=n(137),s=n(138),a=n(139),c=n(140),u=n(141),p=n(132),l=n(134),h=n(133),f=n(142),d=n(135),y=n(144),v=n(127);t.NgControlName=v.NgControlName;var m=n(137);t.NgFormControl=m.NgFormControl;var g=n(138);t.NgModel=g.NgModel;var _=n(139);t.NgControlGroup=_.NgControlGroup;var b=n(140);t.NgFormModel=b.NgFormModel;var C=n(141);t.NgForm=C.NgForm;var P=n(132);t.DefaultValueAccessor=P.DefaultValueAccessor;var w=n(134);t.CheckboxControlValueAccessor=w.CheckboxControlValueAccessor;var R=n(133);t.NumberValueAccessor=R.NumberValueAccessor;var E=n(142);t.NgControlStatus=E.NgControlStatus;var O=n(135);t.SelectControlValueAccessor=O.SelectControlValueAccessor,t.NgSelectOption=O.NgSelectOption;var S=n(144);t.RequiredValidator=S.RequiredValidator,t.MinLengthValidator=S.MinLengthValidator,t.MaxLengthValidator=S.MaxLengthValidator;var D=n(128);t.NgControl=D.NgControl,t.FORM_DIRECTIVES=r.CONST_EXPR([i.NgControlName,a.NgControlGroup,o.NgFormControl,s.NgModel,c.NgFormModel,u.NgForm,d.NgSelectOption,p.DefaultValueAccessor,h.NumberValueAccessor,l.CheckboxControlValueAccessor,d.SelectControlValueAccessor,f.NgControlStatus,y.RequiredValidator,y.MinLengthValidator,y.MaxLengthValidator])},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},s=n(2),a=n(5),c=n(131),u=n(5),p=a.CONST_EXPR(new s.Provider(c.NG_VALIDATORS,{useValue:c.Validators.required,multi:!0})),l=function(){function e(){}return e=r([s.Directive({selector:"[required][ngControl],[required][ngFormControl],[required][ngModel]",providers:[p]}),i("design:paramtypes",[])],e)}();t.RequiredValidator=l;var h=a.CONST_EXPR(new s.Provider(c.NG_VALIDATORS,{useExisting:s.forwardRef(function(){return f}),multi:!0})),f=function(){function e(e){this._validator=c.Validators.minLength(u.NumberWrapper.parseInt(e,10))}return e.prototype.validate=function(e){return this._validator(e)},e=r([s.Directive({selector:"[minlength][ngControl],[minlength][ngFormControl],[minlength][ngModel]",providers:[h]}),o(0,s.Attribute("minlength")),i("design:paramtypes",[String])],e)}();t.MinLengthValidator=f;var d=a.CONST_EXPR(new s.Provider(c.NG_VALIDATORS,{useExisting:s.forwardRef(function(){return y}),multi:!0})),y=function(){function e(e){this._validator=c.Validators.maxLength(u.NumberWrapper.parseInt(e,10))}return e.prototype.validate=function(e){return this._validator(e)},e=r([s.Directive({selector:"[maxlength][ngControl],[maxlength][ngFormControl],[maxlength][ngModel]",providers:[d]}),o(0,s.Attribute("maxlength")),i("design:paramtypes",[String])],e)}();t.MaxLengthValidator=y},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(2),s=n(12),a=n(5),c=n(124),u=function(){function e(){}return e.prototype.group=function(e,t){void 0===t&&(t=null);var n=this._reduceControls(e),r=a.isPresent(t)?s.StringMapWrapper.get(t,"optionals"):null,i=a.isPresent(t)?s.StringMapWrapper.get(t,"validator"):null,o=a.isPresent(t)?s.StringMapWrapper.get(t,"asyncValidator"):null;return new c.ControlGroup(n,r,i,o)},e.prototype.control=function(e,t,n){return void 0===t&&(t=null),void 0===n&&(n=null),new c.Control(e,t,n)},e.prototype.array=function(e,t,n){var r=this;void 0===t&&(t=null),void 0===n&&(n=null);var i=e.map(function(e){return r._createControl(e)});return new c.ControlArray(i,t,n)},e.prototype._reduceControls=function(e){var t=this,n={};return s.StringMapWrapper.forEach(e,function(e,r){n[r]=t._createControl(e)}),n},e.prototype._createControl=function(e){if(e instanceof c.Control||e instanceof c.ControlGroup||e instanceof c.ControlArray)return e;if(a.isArray(e)){var t=e[0],n=e.length>1?e[1]:null,r=e.length>2?e[2]:null;return this.control(t,n,r)}return this.control(e)},e=r([o.Injectable(),i("design:paramtypes",[])],e)}();t.FormBuilder=u,t.FORM_PROVIDERS=a.CONST_EXPR([u]),t.FORM_BINDINGS=t.FORM_PROVIDERS},function(e,t,n){var r=n(5),i=n(123),o=n(115);t.COMMON_DIRECTIVES=r.CONST_EXPR([o.CORE_DIRECTIVES,i.FORM_DIRECTIVES])},function(e,t,n){function r(e){for(var n in e)t.hasOwnProperty(n)||(t[n]=e[n])}r(n(148)),r(n(149)),r(n(150))},function(e,t,n){function r(){return new m}function i(e){var t=s(e);return t&&t[g.Scheme]||""}function o(e,t,n,r,i,o,s){var a=[];return d.isPresent(e)&&a.push(e+":"),d.isPresent(n)&&(a.push("//"),d.isPresent(t)&&a.push(t+"@"),a.push(n),d.isPresent(r)&&a.push(":"+r)),d.isPresent(i)&&a.push(i),d.isPresent(o)&&a.push("?"+o),d.isPresent(s)&&a.push("#"+s),a.join("")}function s(e){return d.RegExpWrapper.firstMatch(_,e)}function a(e){if("/"==e)return"/";for(var t="/"==e[0]?"/":"",n="/"===e[e.length-1]?"/":"",r=e.split("/"),i=[],o=0,s=0;s0?i.pop():o++;break;default:i.push(a)}}if(""==t){for(;o-->0;)i.unshift("..");0===i.length&&i.push(".")}return t+i.join("/")+n}function c(e){var t=e[g.Path];return t=d.isBlank(t)?"":a(t),e[g.Path]=t,o(e[g.Scheme],e[g.UserInfo],e[g.Domain],e[g.Port],t,e[g.QueryData],e[g.Fragment])}function u(e,t){var n=s(encodeURI(t)),r=s(e);if(d.isPresent(n[g.Scheme]))return c(n);n[g.Scheme]=r[g.Scheme];for(var i=g.Scheme;i<=g.Port;i++)d.isBlank(n[i])&&(n[i]=r[i]);if("/"==n[g.Path][0])return c(n);var o=r[g.Path];d.isBlank(o)&&(o="/");var a=o.lastIndexOf("/");return o=o.substring(0,a+1)+n[g.Path],n[g.Path]=o,c(n)}var p=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},l=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},h=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},f=n(6),d=n(5),y=n(67),v=n(6);t.createWithoutPackagePrefix=r,t.DEFAULT_PACKAGE_URL_PROVIDER=new v.Provider(y.PACKAGE_ROOT_URL,{useValue:"/"});var m=function(){function e(e){void 0===e&&(e=null),d.isPresent(e)&&(this._packagePrefix=d.StringWrapper.stripRight(e,"/")+"/")}return e.prototype.resolve=function(e,t){var n=t;return d.isPresent(e)&&e.length>0&&(n=u(e,n)),d.isPresent(this._packagePrefix)&&"package"==i(n)&&(n=n.replace("package:",this._packagePrefix)),n},e=p([f.Injectable(),h(0,f.Inject(y.PACKAGE_ROOT_URL)),l("design:paramtypes",[String])],e)}();t.UrlResolver=m,t.getUrlScheme=i;var g,_=d.RegExpWrapper.create("^(?:([^:/?#.]+):)?(?://(?:([^/?#]*)@)?([\\w\\d\\-\\u0100-\\uffff.%]*)(?::([0-9]+))?)?([^?#]+)?(?:\\?([^#]*))?(?:#(.*))?$");!function(e){e[e.Scheme=1]="Scheme",e[e.UserInfo=2]="UserInfo",e[e.Domain=3]="Domain",e[e.Port=4]="Port",e[e.Path=5]="Path",e[e.QueryData=6]="QueryData",e[e.Fragment=7]="Fragment"}(g||(g={}))},function(e,t){var n=function(){function e(){}return e.prototype.get=function(e){return null},e}();t.XHR=n},function(e,t,n){function r(e){for(var n in e)t.hasOwnProperty(n)||(t[n]=e[n])}function i(){return new C.ChangeDetectorGenConfig(l.assertionsEnabled(),!1,!0)}var o=n(151),s=n(152);t.TemplateCompiler=s.TemplateCompiler;var a=n(153);t.CompileDirectiveMetadata=a.CompileDirectiveMetadata,t.CompileTypeMetadata=a.CompileTypeMetadata,t.CompileTemplateMetadata=a.CompileTemplateMetadata;var c=n(156);t.SourceModule=c.SourceModule,t.SourceWithImports=c.SourceWithImports;var u=n(95);t.PLATFORM_DIRECTIVES=u.PLATFORM_DIRECTIVES,t.PLATFORM_PIPES=u.PLATFORM_PIPES,r(n(159));var p=n(167);t.TEMPLATE_TRANSFORMS=p.TEMPLATE_TRANSFORMS;var l=n(5),h=n(6),f=n(167),d=n(168),y=n(175),v=n(176),m=n(157),g=n(161),_=n(166),b=n(152),C=n(25),P=n(70),w=n(151),R=n(173),E=n(177),O=n(148),S=n(25);t.COMPILER_PROVIDERS=l.CONST_EXPR([S.Lexer,S.Parser,d.HtmlParser,f.TemplateParser,y.TemplateNormalizer,v.RuntimeMetadataResolver,O.DEFAULT_PACKAGE_URL_PROVIDER,g.StyleCompiler,_.CommandCompiler,m.ChangeDetectionCompiler,new h.Provider(C.ChangeDetectorGenConfig,{useFactory:i,deps:[]}),b.TemplateCompiler,new h.Provider(w.RuntimeCompiler,{useClass:o.RuntimeCompiler_}),new h.Provider(P.Compiler,{useExisting:w.RuntimeCompiler}),E.DomElementSchemaRegistry,new h.Provider(R.ElementSchemaRegistry,{useExisting:E.DomElementSchemaRegistry}),O.UrlResolver])},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=n(70),a=n(71),c=n(152),u=n(6),p=function(e){function t(){e.apply(this,arguments)}return r(t,e),t}(s.Compiler);t.RuntimeCompiler=p;var l=function(e){function t(t,n){e.call(this,t),this._templateCompiler=n}return r(t,e),t.prototype.compileInHost=function(e){var t=this;return this._templateCompiler.compileHostComponentRuntime(e).then(function(e){return s.internalCreateProtoView(t,e)})},t.prototype.clearCache=function(){e.prototype.clearCache.call(this),this._templateCompiler.clearCache()},t=i([u.Injectable(),o("design:paramtypes",[a.ProtoViewFactory,c.TemplateCompiler])],t)}(s.Compiler_);t.RuntimeCompiler_=l},function(e,t,n){function r(e){if(!e.isComponent)throw new f.BaseException("Could not compile '"+e.type.name+"' because it is not a component.")}function i(e){return e.name+"Template"}function o(e){return i(e)+"Getter"}function s(e){var t=e.substring(0,e.length-S.MODULE_SUFFIX.length);return t+".template"+S.MODULE_SUFFIX}function a(e,t){for(var n=0;n0;n||t.push(e)}),t}var p=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},l=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},h=n(5),f=n(14),d=n(12),y=n(60),v=n(96),m=n(153),g=n(6),_=n(156),b=n(157),C=n(161),P=n(166),w=n(167),R=n(175),E=n(176),O=n(166),S=n(155),D=function(){function e(e,t,n,r,i,o){this._runtimeMetadataResolver=e,this._templateNormalizer=t,this._templateParser=n,this._styleCompiler=r,this._commandCompiler=i,this._cdCompiler=o,this._hostCacheKeys=new Map,this._compiledTemplateCache=new Map,this._compiledTemplateDone=new Map,this._nextTemplateId=0}return e.prototype.normalizeDirectiveMetadata=function(e){return e.isComponent?this._templateNormalizer.normalizeTemplate(e.type,e.template).then(function(t){return new m.CompileDirectiveMetadata({type:e.type,isComponent:e.isComponent,dynamicLoadable:e.dynamicLoadable,selector:e.selector,exportAs:e.exportAs,changeDetection:e.changeDetection,inputs:e.inputs,outputs:e.outputs,hostListeners:e.hostListeners,hostProperties:e.hostProperties,hostAttributes:e.hostAttributes,lifecycleHooks:e.lifecycleHooks,template:t})}):y.PromiseWrapper.resolve(e)},e.prototype.compileHostComponentRuntime=function(e){var t=this._hostCacheKeys.get(e);if(h.isBlank(t)){t=new Object,this._hostCacheKeys.set(e,t);var n=this._runtimeMetadataResolver.getMetadata(e);r(n);var i=m.createHostComponentMeta(n.type,n.selector);this._compileComponentRuntime(t,i,[n],new Set)}return this._compiledTemplateDone.get(t).then(function(e){return new v.CompiledHostTemplate(e)})},e.prototype.clearCache=function(){this._hostCacheKeys.clear(),this._styleCompiler.clearCache(),this._compiledTemplateCache.clear(),this._compiledTemplateDone.clear()},e.prototype._compileComponentRuntime=function(e,t,n,r){var i=this,o=u(n),s=this._compiledTemplateCache.get(e),a=this._compiledTemplateDone.get(e);if(h.isBlank(s)){var c,p=[],l=[],f=h.stringify(t.type.runtime)+"Template"+this._nextTemplateId++;s=new v.CompiledComponentTemplate(f,function(e){return c(e)},l,p),this._compiledTemplateCache.set(e,s),r.add(e),a=y.PromiseWrapper.all([this._styleCompiler.compileComponentRuntime(t.template)].concat(o.map(function(e){return i.normalizeDirectiveMetadata(e)}))).then(function(e){var n=[],o=e.slice(1),s=i._templateParser.parse(t.template.template,o,t.type.name),a=i._cdCompiler.compileComponentRuntime(t.type,t.changeDetection,s);c=a[0];var u=e[0];u.forEach(function(e){return p.push(e)});var h=i._compileCommandsRuntime(t,s,a,r,n);return h.forEach(function(e){return l.push(e)}),y.PromiseWrapper.all(n)}).then(function(t){return d.SetWrapper["delete"](r,e),s}),this._compiledTemplateDone.set(e,a)}return s},e.prototype._compileCommandsRuntime=function(e,t,n,r,i){var o=this,s=this._commandCompiler.compileComponentRuntime(e,t,n,function(e){var t=e.type.runtime,n=o._runtimeMetadataResolver.getViewDirectivesMetadata(e.type.runtime),s=d.SetWrapper.has(r,t),a=o._compileComponentRuntime(t,e,n,r);return s||i.push(o._compiledTemplateDone.get(t)),function(){return a}});return s.forEach(function(e){e instanceof v.BeginComponentCmd&&e.templateGetter()}),s},e.prototype.compileTemplatesCodeGen=function(e){var t=this;if(0===e.length)throw new f.BaseException("No components given");var n=[],a=[],c=[];e.forEach(function(e){var i=e.component;if(r(i),c.push(i),t._processTemplateCodeGen(i,e.directives,n,a),i.dynamicLoadable){var o=m.createHostComponentMeta(i.type,i.selector);c.push(o),t._processTemplateCodeGen(o,[i],n,a)}}),d.ListWrapper.forEachWithIndex(c,function(e,t){var r,s=e.type.moduleUrl+"|"+e.type.name,c=h.IS_DART?"const":"new",u=c+" "+O.TEMPLATE_COMMANDS_MODULE_REF+"CompiledComponentTemplate('"+s+"',"+a[t].join(",")+")"; -r=e.type.isHost?c+" "+O.TEMPLATE_COMMANDS_MODULE_REF+"CompiledHostTemplate("+u+")":u;var p=i(e.type);n.push(""+S.codeGenExportVariable(p)+r+";"),n.push(S.codeGenValueFn([],p,o(e.type))+";")});var u=e[0].component.type.moduleUrl;return new _.SourceModule(""+s(u),n.join("\n"))},e.prototype.compileStylesheetCodeGen=function(e,t){return this._styleCompiler.compileStylesheetCodeGen(e,t)},e.prototype._processTemplateCodeGen=function(e,t,n,r){var i=u(t),o=this._styleCompiler.compileComponentCodeGen(e.template),s=this._templateParser.parse(e.template.template,i,e.type.name),p=this._cdCompiler.compileComponentCodeGen(e.type,e.changeDetection,s),l=this._commandCompiler.compileComponentCodeGen(e,s,p.expressions,c);a(o.declarations,n),a(p.declarations,n),a(l.declarations,n),r.push([p.expressions[0],l.expression,o.expression])},e=p([g.Injectable(),l("design:paramtypes",[E.RuntimeMetadataResolver,R.TemplateNormalizer,w.TemplateParser,C.StyleCompiler,P.CommandCompiler,b.ChangeDetectionCompiler])],e)}();t.TemplateCompiler=D;var T=function(){function e(e,t){this.component=e,this.directives=t}return e}();t.NormalizedComponentWithViewDirectives=T},function(e,t,n){function r(e,t){var n=c.CssSelector.parse(t)[0].getMatchingElementTemplate();return d.create({type:new h({runtime:Object,name:"Host"+e.name,moduleUrl:e.moduleUrl,isHost:!0}),template:new f({template:n,templateUrl:"",styles:[],styleUrls:[],ngContentSelectors:[]}),changeDetection:s.ChangeDetectionStrategy.Default,inputs:[],outputs:[],host:{},lifecycleHooks:[],isComponent:!0,dynamicLoadable:!1,selector:"*"})}var i=n(5),o=n(12),s=n(25),a=n(56),c=n(154),u=n(155),p=n(89),l=/^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))$/g,h=function(){function e(e){var t=void 0===e?{}:e,n=t.runtime,r=t.name,o=t.moduleUrl,s=t.isHost;this.runtime=n,this.name=r,this.moduleUrl=o,this.isHost=i.normalizeBool(s)}return e.fromJson=function(t){return new e({name:t.name,moduleUrl:t.moduleUrl,isHost:t.isHost})},e.prototype.toJson=function(){return{name:this.name,moduleUrl:this.moduleUrl,isHost:this.isHost}},e}();t.CompileTypeMetadata=h;var f=function(){function e(e){var t=void 0===e?{}:e,n=t.encapsulation,r=t.template,o=t.templateUrl,s=t.styles,c=t.styleUrls,u=t.ngContentSelectors;this.encapsulation=i.isPresent(n)?n:a.ViewEncapsulation.Emulated,this.template=r,this.templateUrl=o,this.styles=i.isPresent(s)?s:[],this.styleUrls=i.isPresent(c)?c:[],this.ngContentSelectors=i.isPresent(u)?u:[]}return e.fromJson=function(t){return new e({encapsulation:i.isPresent(t.encapsulation)?a.VIEW_ENCAPSULATION_VALUES[t.encapsulation]:t.encapsulation,template:t.template,templateUrl:t.templateUrl,styles:t.styles,styleUrls:t.styleUrls,ngContentSelectors:t.ngContentSelectors})},e.prototype.toJson=function(){return{encapsulation:i.isPresent(this.encapsulation)?i.serializeEnum(this.encapsulation):this.encapsulation,template:this.template,templateUrl:this.templateUrl,styles:this.styles,styleUrls:this.styleUrls,ngContentSelectors:this.ngContentSelectors}},e}();t.CompileTemplateMetadata=f;var d=function(){function e(e){var t=void 0===e?{}:e,n=t.type,r=t.isComponent,i=t.dynamicLoadable,o=t.selector,s=t.exportAs,a=t.changeDetection,c=t.inputs,u=t.outputs,p=t.hostListeners,l=t.hostProperties,h=t.hostAttributes,f=t.lifecycleHooks,d=t.template;this.type=n,this.isComponent=r,this.dynamicLoadable=i,this.selector=o,this.exportAs=s,this.changeDetection=a,this.inputs=c,this.outputs=u,this.hostListeners=p,this.hostProperties=l,this.hostAttributes=h,this.lifecycleHooks=f,this.template=d}return e.create=function(t){var n=void 0===t?{}:t,r=n.type,s=n.isComponent,a=n.dynamicLoadable,c=n.selector,p=n.exportAs,h=n.changeDetection,f=n.inputs,d=n.outputs,y=n.host,v=n.lifecycleHooks,m=n.template,g={},_={},b={};i.isPresent(y)&&o.StringMapWrapper.forEach(y,function(e,t){var n=i.RegExpWrapper.firstMatch(l,t);i.isBlank(n)?b[t]=e:i.isPresent(n[1])?_[n[1]]=e:i.isPresent(n[2])&&(g[n[2]]=e)});var C={};i.isPresent(f)&&f.forEach(function(e){var t=u.splitAtColon(e,[e,e]);C[t[0]]=t[1]});var P={};return i.isPresent(d)&&d.forEach(function(e){var t=u.splitAtColon(e,[e,e]);P[t[0]]=t[1]}),new e({type:r,isComponent:i.normalizeBool(s),dynamicLoadable:i.normalizeBool(a),selector:c,exportAs:p,changeDetection:h,inputs:C,outputs:P,hostListeners:g,hostProperties:_,hostAttributes:b,lifecycleHooks:i.isPresent(v)?v:[],template:m})},e.fromJson=function(t){return new e({isComponent:t.isComponent,dynamicLoadable:t.dynamicLoadable,selector:t.selector,exportAs:t.exportAs,type:i.isPresent(t.type)?h.fromJson(t.type):t.type,changeDetection:i.isPresent(t.changeDetection)?s.CHANGE_DETECTION_STRATEGY_VALUES[t.changeDetection]:t.changeDetection,inputs:t.inputs,outputs:t.outputs,hostListeners:t.hostListeners,hostProperties:t.hostProperties,hostAttributes:t.hostAttributes,lifecycleHooks:t.lifecycleHooks.map(function(e){return p.LIFECYCLE_HOOKS_VALUES[e]}),template:i.isPresent(t.template)?f.fromJson(t.template):t.template})},e.prototype.toJson=function(){return{isComponent:this.isComponent,dynamicLoadable:this.dynamicLoadable,selector:this.selector,exportAs:this.exportAs,type:i.isPresent(this.type)?this.type.toJson():this.type,changeDetection:i.isPresent(this.changeDetection)?i.serializeEnum(this.changeDetection):this.changeDetection,inputs:this.inputs,outputs:this.outputs,hostListeners:this.hostListeners,hostProperties:this.hostProperties,hostAttributes:this.hostAttributes,lifecycleHooks:this.lifecycleHooks.map(function(e){return i.serializeEnum(e)}),template:i.isPresent(this.template)?this.template.toJson():this.template}},e}();t.CompileDirectiveMetadata=d,t.createHostComponentMeta=r},function(e,t,n){var r=n(12),i=n(5),o=n(14),s="",a=i.RegExpWrapper.create("(\\:not\\()|([-\\w]+)|(?:\\.([-\\w]+))|(?:\\[([-\\w*]+)(?:=([^\\]]*))?\\])|(\\))|(\\s*,\\s*)"),c=function(){function e(){this.element=null,this.classNames=[],this.attrs=[],this.notSelectors=[]}return e.parse=function(t){for(var n,s=[],c=function(e,t){t.notSelectors.length>0&&i.isBlank(t.element)&&r.ListWrapper.isEmpty(t.classNames)&&r.ListWrapper.isEmpty(t.attrs)&&(t.element="*"),e.push(t)},u=new e,p=i.RegExpWrapper.matcher(a,t),l=u,h=!1;i.isPresent(n=i.RegExpMatcherWrapper.next(p));){if(i.isPresent(n[1])){if(h)throw new o.BaseException("Nesting :not is not allowed in a selector");h=!0,l=new e,u.notSelectors.push(l)}if(i.isPresent(n[2])&&l.setElement(n[2]),i.isPresent(n[3])&&l.addClassName(n[3]),i.isPresent(n[4])&&l.addAttribute(n[4],n[5]),i.isPresent(n[6])&&(h=!1,l=u),i.isPresent(n[7])){if(h)throw new o.BaseException("Multiple selectors in :not are not supported");c(s,u),u=l=new e}}return c(s,u),s},e.prototype.isElementSelector=function(){return i.isPresent(this.element)&&r.ListWrapper.isEmpty(this.classNames)&&r.ListWrapper.isEmpty(this.attrs)&&0===this.notSelectors.length},e.prototype.setElement=function(e){void 0===e&&(e=null),this.element=e},e.prototype.getMatchingElementTemplate=function(){for(var e=i.isPresent(this.element)?this.element:"div",t=this.classNames.length>0?' class="'+this.classNames.join(" ")+'"':"",n="",r=0;r"},e.prototype.addAttribute=function(e,t){void 0===t&&(t=s),this.attrs.push(e),t=i.isPresent(t)?t.toLowerCase():s,this.attrs.push(t)},e.prototype.addClassName=function(e){this.classNames.push(e.toLowerCase())},e.prototype.toString=function(){var e="";if(i.isPresent(this.element)&&(e+=this.element),i.isPresent(this.classNames))for(var t=0;t0&&(e+="="+r),e+="]"}return this.notSelectors.forEach(function(t){return e+=":not("+t+")"}),e},e}();t.CssSelector=c;var u=function(){function e(){this._elementMap=new r.Map,this._elementPartialMap=new r.Map,this._classMap=new r.Map,this._classPartialMap=new r.Map,this._attrValueMap=new r.Map,this._attrValuePartialMap=new r.Map,this._listContexts=[]}return e.createNotMatcher=function(t){var n=new e;return n.addSelectables(t,null),n},e.prototype.addSelectables=function(e,t){var n=null;e.length>1&&(n=new p(e),this._listContexts.push(n));for(var r=0;r0&&(i.isBlank(this.listContext)||!this.listContext.alreadyMatched)){var r=u.createNotMatcher(this.notSelectors);n=!r.match(e,null)}return n&&i.isPresent(t)&&(i.isBlank(this.listContext)||!this.listContext.alreadyMatched)&&(i.isPresent(this.listContext)&&(this.listContext.alreadyMatched=!0),t(this.selector,this.cbContext)),n},e}();t.SelectorContext=l},function(e,t,n){function r(e){return f.StringWrapper.replaceAllMapped(e,d,function(e){return"-"+e[1].toLowerCase()})}function i(e){return f.StringWrapper.replaceAllMapped(e,y,function(e){return e[1].toUpperCase()})}function o(e){return f.isBlank(e)?null:"'"+a(e,v)+"'"}function s(e){return f.isBlank(e)?null:'"'+a(e,m)+'"'}function a(e,t){return f.StringWrapper.replaceAllMapped(e,t,function(e){return"$"==e[0]?f.IS_DART?"\\$":"$":"\n"==e[0]?"\\n":"\r"==e[0]?"\\r":"\\"+e[0]})}function c(e){return f.IS_DART?"const "+e+" = ":"var "+e+" = exports['"+e+"'] = "}function u(e){return f.IS_DART?"const "+e:"new "+e}function p(e,t,n){return void 0===n&&(n=""),f.IS_DART?n+"("+e.join(",")+") => "+t:"function "+n+"("+e.join(",")+") { return "+t+"; }"}function l(e){return f.IS_DART?"'${"+e+"}'":e}function h(e,t){var n=f.StringWrapper.split(e.trim(),/\s*:\s*/g);return n.length>1?n:t}var f=n(5),d=/([A-Z])/g,y=/-([a-z])/g,v=/'|\\|\n|\r|\$/g,m=/"|\\|\n|\r|\$/g;t.MODULE_SUFFIX=f.IS_DART?".dart":".js",t.camelCaseToDashCase=r,t.dashCaseToCamelCase=i,t.escapeSingleQuoteString=o,t.escapeDoubleQuoteString=s,t.codeGenExportVariable=c,t.codeGenConstConstructorCall=u,t.codeGenValueFn=p,t.codeGenToString=l,t.splitAtColon=h},function(e,t,n){function r(e){return"#MODULE["+e+"]"}var i=n(5),o=/#MODULE\[([^\]]*)\]/g;t.moduleRef=r;var s=function(){function e(e,t){this.moduleUrl=e,this.sourceWithModuleRefs=t}return e.prototype.getSourceWithImports=function(){var e=this,t={},n=[],r=i.StringWrapper.replaceAllMapped(this.sourceWithModuleRefs,o,function(r){var o=r[1],s=t[o];return i.isBlank(s)&&(o==e.moduleUrl?s="":(s="import"+n.length,n.push([o,s])),t[o]=s),s.length>0?s+".":""});return new u(r,n)},e}();t.SourceModule=s;var a=function(){function e(e,t){this.declarations=e,this.expression=t}return e}();t.SourceExpression=a;var c=function(){function e(e,t){this.declarations=e,this.expressions=t}return e}();t.SourceExpressions=c;var u=function(){function e(e,t){this.source=e,this.imports=t}return e}();t.SourceWithImports=u},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(156),s=n(52),a=n(158),c=n(5),u=n(25),p=n(160),l=n(155),h=n(6),f="AbstractChangeDetector",d="ChangeDetectionUtil",y="ChangeDetectorState",v=o.moduleRef("package:angular2/src/core/change_detection/abstract_change_detector"+l.MODULE_SUFFIX),m=o.moduleRef("package:angular2/src/core/change_detection/change_detection_util"+l.MODULE_SUFFIX),g=o.moduleRef("package:angular2/src/core/change_detection/pregen_proto_change_detector"+l.MODULE_SUFFIX),_=o.moduleRef("package:angular2/src/core/change_detection/constants"+l.MODULE_SUFFIX),b=function(){function e(e){this._genConfig=e}return e.prototype.compileComponentRuntime=function(e,t,n){var r=this,i=a.createChangeDetectorDefinitions(e,t,this._genConfig,n);return i.map(function(e){return r._createChangeDetectorFactory(e)})},e.prototype._createChangeDetectorFactory=function(e){if(c.IS_DART||!this._genConfig.useJit){var t=new u.DynamicProtoChangeDetector(e);return function(e){return t.instantiate(e)}}return new s.ChangeDetectorJITGenerator(e,d,f,y).generate()},e.prototype.compileComponentCodeGen=function(e,t,n){var r=a.createChangeDetectorDefinitions(e,t,this._genConfig,n),i=[],u=0,l=r.map(function(t){var n,r;if(c.IS_DART){n=new p.Codegen(g);var a="_"+t.id,l=0===u&&e.isHost?"dynamic":""+o.moduleRef(e.moduleUrl)+e.name;n.generate(l,a,t),i.push(a+".newChangeDetector"),r=n.toString()}else n=new s.ChangeDetectorJITGenerator(t,""+m+d,""+v+f,""+_+y),i.push("function(dispatcher) { return new "+n.typeName+"(dispatcher); }"),r=n.generateSource();return u++,r});return new o.SourceExpressions(l,i)},e=r([h.Injectable(),i("design:paramtypes",[u.ChangeDetectorGenConfig])],e)}();t.ChangeDetectionCompiler=b},function(e,t,n){function r(e,t,n,r){var o=[],s=new h(null,o,t);return p.templateVisitAll(s,r),i(o,e,n)}function i(e,t,n){var r=o(e);return e.map(function(e){var i=t.name+"_"+e.viewIndex;return new u.ChangeDetectorDefinition(i,e.strategy,r[e.viewIndex],e.bindingRecords,e.eventRecords,e.directiveRecords,n)})}function o(e){var t=s.ListWrapper.createFixedSize(e.length);return e.forEach(function(e){var n=a.isPresent(e.parent)?t[e.parent.viewIndex]:[];t[e.viewIndex]=n.concat(e.variableNames)}),t}var s=n(12),a=n(5),c=n(16),u=n(25),p=n(159),l=n(89);t.createChangeDetectorDefinitions=r;var h=function(){function e(e,t,n){this.parent=e,this.allVisitors=t,this.strategy=n,this.boundTextCount=0,this.boundElementCount=0,this.variableNames=[],this.bindingRecords=[],this.eventRecords=[],this.directiveRecords=[],this.viewIndex=t.length,t.push(this)}return e.prototype.visitEmbeddedTemplate=function(t,n){this.boundElementCount++,p.templateVisitAll(this,t.outputs);for(var r=0;r0||this.outputs.length>0||this.exportAsVars.length>0||this.directives.length>0},e.prototype.getComponent=function(){return this.directives.length>0&&this.directives[0].directive.isComponent?this.directives[0].directive:null},e}();t.ElementAst=l;var h=function(){function e(e,t,n,r,i,o,s){this.attrs=e,this.outputs=t,this.vars=n,this.directives=r,this.children=i,this.ngContentIndex=o,this.sourceSpan=s}return e.prototype.visit=function(e,t){return e.visitEmbeddedTemplate(this,t)},e}();t.EmbeddedTemplateAst=h;var f=function(){function e(e,t,n,r){this.directiveName=e,this.templateName=t,this.value=n,this.sourceSpan=r}return e.prototype.visit=function(e,t){return e.visitDirectiveProperty(this,t)},e}();t.BoundDirectivePropertyAst=f;var d=function(){function e(e,t,n,r,i,o){this.directive=e,this.inputs=t,this.hostProperties=n,this.hostEvents=r,this.exportAsVars=i,this.sourceSpan=o}return e.prototype.visit=function(e,t){return e.visitDirective(this,t)},e}();t.DirectiveAst=d;var y=function(){function e(e,t,n){this.index=e,this.ngContentIndex=t,this.sourceSpan=n}return e.prototype.visit=function(e,t){return e.visitNgContent(this,t)},e}();t.NgContentAst=y,function(e){e[e.Property=0]="Property",e[e.Attribute=1]="Attribute",e[e.Class=2]="Class",e[e.Style=3]="Style"}(t.PropertyBindingType||(t.PropertyBindingType={}));t.PropertyBindingType;t.templateVisitAll=r},function(e,t){var n=function(){function e(e){}return e.prototype.generate=function(e,t,n){throw"Not implemented in JS"},e.prototype.toString=function(){throw"Not implemented in JS"},e}();t.Codegen=n},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(156),s=n(56),a=n(149),c=n(5),u=n(60),p=n(162),l=n(148),h=n(163),f=n(155),d=n(6),y=n(164),v=function(){function e(e,t){this._xhr=e,this._urlResolver=t,this._styleCache=new Map,this._shadowCss=new p.ShadowCss}return e.prototype.compileComponentRuntime=function(e){var t=e.styles,n=e.styleUrls;return this._loadStyles(t,n,e.encapsulation===s.ViewEncapsulation.Emulated)},e.prototype.compileComponentCodeGen=function(e){var t=e.encapsulation===s.ViewEncapsulation.Emulated;return this._styleCodeGen(e.styles,e.styleUrls,t)},e.prototype.compileStylesheetCodeGen=function(e,t){var n=h.extractStyleUrls(this._urlResolver,e,t);return[this._styleModule(e,!1,this._styleCodeGen([n.style],n.styleUrls,!1)),this._styleModule(e,!0,this._styleCodeGen([n.style],n.styleUrls,!0))]},e.prototype.clearCache=function(){this._styleCache.clear()},e.prototype._loadStyles=function(e,t,n){var r=this,i=t.map(function(e){var t=""+e+(n?".shim":""),i=r._styleCache.get(t);return c.isBlank(i)&&(i=r._xhr.get(e).then(function(t){var i=h.extractStyleUrls(r._urlResolver,e,t);return r._loadStyles([i.style],i.styleUrls,n)}),r._styleCache.set(t,i)),i});return u.PromiseWrapper.all(i).then(function(t){var i=e.map(function(e){return r._shimIfNeeded(e,n)});return t.forEach(function(e){return i.push(e)}),i})},e.prototype._styleCodeGen=function(e,t,n){for(var r=this,i=c.IS_DART?"const":"",s=e.map(function(e){return f.escapeSingleQuoteString(r._shimIfNeeded(e,n))}),a=0;a0?o.push(c):(o.length>0&&(r.push(o.join("")),n.push(D),o=[]),n.push(c)),c==O&&i++}return o.length>0&&(r.push(o.join("")),n.push(D)),new A(n.join(""),r)}var s=n(12),a=n(5),c=function(){function e(){this.strictStyling=!0}return e.prototype.shimCssText=function(e,t,n){return void 0===n&&(n=""),e=r(e),e=this._insertDirectives(e),this._scopeCssText(e,t,n)},e.prototype._insertDirectives=function(e){return e=this._insertPolyfillDirectivesInCssText(e),this._insertPolyfillRulesInCssText(e)},e.prototype._insertPolyfillDirectivesInCssText=function(e){return a.StringWrapper.replaceAllMapped(e,u,function(e){return e[1]+"{"})},e.prototype._insertPolyfillRulesInCssText=function(e){return a.StringWrapper.replaceAllMapped(e,p,function(e){var t=e[0];return t=a.StringWrapper.replace(t,e[1],""),t=a.StringWrapper.replace(t,e[2],""),e[3]+t})},e.prototype._scopeCssText=function(e,t,n){var r=this._extractUnscopedRulesFromCssText(e);return e=this._insertPolyfillHostInCssText(e),e=this._convertColonHost(e),e=this._convertColonHostContext(e),e=this._convertShadowDOMSelectors(e),a.isPresent(t)&&(e=this._scopeSelectors(e,t,n)),e=e+"\n"+r,e.trim()},e.prototype._extractUnscopedRulesFromCssText=function(e){for(var t,n="",r=a.RegExpWrapper.matcher(l,e);a.isPresent(t=a.RegExpMatcherWrapper.next(r));){var i=t[0];i=a.StringWrapper.replace(i,t[2],""),i=a.StringWrapper.replace(i,t[1],t[3]),n+=i+"\n\n"}return n},e.prototype._convertColonHost=function(e){return this._convertColonRule(e,y,this._colonHostPartReplacer)},e.prototype._convertColonHostContext=function(e){return this._convertColonRule(e,v,this._colonHostContextPartReplacer)},e.prototype._convertColonRule=function(e,t,n){return a.StringWrapper.replaceAllMapped(e,t,function(e){if(a.isPresent(e[2])){for(var t=e[2].split(","),r=[],i=0;i","+","~"],i=e,o="["+t+"]",c=0;c0&&!s.ListWrapper.contains(r,t)&&!a.StringWrapper.contains(t,o)){var n=/([^:]*)(:*)(.*)/g,i=a.RegExpWrapper.firstMatch(n,t);a.isPresent(i)&&(e=i[1]+o+i[2]+i[3])}return e}).join(u)}return i},e.prototype._insertPolyfillHostInCssText=function(e){return e=a.StringWrapper.replaceAll(e,P,f),e=a.StringWrapper.replaceAll(e,C,h)},e}();t.ShadowCss=c;var u=/polyfill-next-selector[^}]*content:[\s]*?['"](.*?)['"][;\s]*}([^{]*?){/gim,p=/(polyfill-rule)[^}]*(content:[\s]*['"](.*?)['"])[;\s]*[^}]*}/gim,l=/(polyfill-unscoped-rule)[^}]*(content:[\s]*['"](.*?)['"])[;\s]*[^}]*}/gim,h="-shadowcsshost",f="-shadowcsscontext",d=")(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)",y=a.RegExpWrapper.create("("+h+d,"im"),v=a.RegExpWrapper.create("("+f+d,"im"),m=h+"-no-combinator",g=[/>>>/g,/::shadow/g,/::content/g,/\/deep\//g,/\/shadow-deep\//g,/\/shadow\//g],_="([>\\s~+[.,{:][\\s\\S]*)?$",b=a.RegExpWrapper.create(h,"im"),C=/:host/gim,P=/:host-context/gim,w=/\/\*[\s\S]*?\*\//g,R=/(\s*)([^;\{\}]+?)(\s*)((?:{%BLOCK%}?\s*;?)|(?:\s*;))/g,E=/([{}])/g,O="{",S="}",D="%BLOCK%",T=function(){function e(e,t){this.selector=e,this.content=t}return e}();t.CssRule=T,t.processRules=i;var A=function(){function e(e,t){this.escapedString=e,this.blocks=t}return e}()},function(e,t,n){function r(e){if(o.isBlank(e)||0===e.length||"/"==e[0])return!1;var t=o.RegExpWrapper.firstMatch(c,e);return o.isBlank(t)||"package"==t[1]||"asset"==t[1]}function i(e,t,n){var i=[],c=o.StringWrapper.replaceAllMapped(n,a,function(n){var s=o.isPresent(n[1])?n[1]:n[2];return r(s)?(i.push(e.resolve(t,s)),""):n[0]});return new s(c,i)}var o=n(5),s=function(){function e(e,t){this.style=e,this.styleUrls=t}return e}();t.StyleWithImports=s,t.isStyleUrlResolvable=r,t.extractStyleUrls=i;var a=/@import\s+(?:url\()?\s*(?:(?:['"]([^'"]*))|([^;\)\s]*))[^;]*;?/g,c=/^([a-zA-Z\-\+\.]+):/g},function(e,t,n){function r(e){var t=e.styles;if(e.encapsulation===l.ViewEncapsulation.Emulated){t=h.ListWrapper.createFixedSize(e.styles.length);for(var n=0;ni.length){var f,d=h.ListWrapper.createFixedSize(p);for(f=0;fo?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},f=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},d=n(5),y=n(12),v=n(96),m=n(159),g=n(156),_=n(155),b=n(6);t.TEMPLATE_COMMANDS_MODULE_REF=g.moduleRef("package:angular2/src/core/linker/template_commands"+_.MODULE_SUFFIX);var C="$implicit",P="class",w="style",R=function(){function e(){}return e.prototype.compileComponentRuntime=function(e,t,n,r){var i=new S(new E(e,r,n),0);return m.templateVisitAll(i,t),i.result},e.prototype.compileComponentCodeGen=function(e,t,n,r){var i=new S(new O(e,r,n),0);return m.templateVisitAll(i,t),new g.SourceExpression([],u(i.result))},e=h([b.Injectable(),f("design:paramtypes",[])],e)}();t.CommandCompiler=R;var E=function(){function e(e,t,n){this.component=e,this.componentTemplateFactory=t,this.changeDetectorFactories=n}return e.prototype._mapDirectives=function(e){return e.map(function(e){return e.type.runtime})},e.prototype.createText=function(e,t,n){return new v.TextCmd(e,t,n)},e.prototype.createNgContent=function(e,t){return new v.NgContentCmd(e,t)},e.prototype.createBeginElement=function(e,t,n,r,i,o,s){return new v.BeginElementCmd(e,t,n,r,this._mapDirectives(i),o,s)},e.prototype.createEndElement=function(){return new v.EndElementCmd},e.prototype.createBeginComponent=function(e,t,n,r,i,o,s){var a=this.componentTemplateFactory(i[0]);return new v.BeginComponentCmd(e,t,n,r,this._mapDirectives(i),o,s,a)},e.prototype.createEndComponent=function(){return new v.EndComponentCmd},e.prototype.createEmbeddedTemplate=function(e,t,n,r,i,o,s){return new v.EmbeddedTemplateCmd(t,n,this._mapDirectives(r),i,o,this.changeDetectorFactories[e],s)},e}(),O=function(){function e(e,t,n){this.component=e,this.componentTemplateFactory=t,this.changeDetectorFactoryExpressions=n}return e.prototype.createText=function(e,n,r){return new T(_.codeGenConstConstructorCall(t.TEMPLATE_COMMANDS_MODULE_REF+"TextCmd")+"("+_.escapeSingleQuoteString(e)+", "+n+", "+r+")")},e.prototype.createNgContent=function(e,n){return new T(_.codeGenConstConstructorCall(t.TEMPLATE_COMMANDS_MODULE_REF+"NgContentCmd")+"("+e+", "+n+")")},e.prototype.createBeginElement=function(e,n,r,i,o,s,a){var c=u(n);return new T(_.codeGenConstConstructorCall(t.TEMPLATE_COMMANDS_MODULE_REF+"BeginElementCmd")+"("+_.escapeSingleQuoteString(e)+", "+c+", "+(u(r)+", "+u(i)+", "+p(o)+", "+s+", "+a+")"))},e.prototype.createEndElement=function(){return new T(_.codeGenConstConstructorCall(t.TEMPLATE_COMMANDS_MODULE_REF+"EndElementCmd")+"()")},e.prototype.createBeginComponent=function(e,n,r,i,o,s,a){var c=u(n);return new T(_.codeGenConstConstructorCall(t.TEMPLATE_COMMANDS_MODULE_REF+"BeginComponentCmd")+"("+_.escapeSingleQuoteString(e)+", "+c+", "+(u(r)+", "+u(i)+", "+p(o)+", "+l(s)+", "+a+", "+this.componentTemplateFactory(o[0])+")"))},e.prototype.createEndComponent=function(){return new T(_.codeGenConstConstructorCall(t.TEMPLATE_COMMANDS_MODULE_REF+"EndComponentCmd")+"()")},e.prototype.createEmbeddedTemplate=function(e,n,r,i,o,s,a){return new T(_.codeGenConstConstructorCall(t.TEMPLATE_COMMANDS_MODULE_REF+"EmbeddedTemplateCmd")+"("+u(n)+", "+u(r)+", "+(p(i)+", "+o+", "+s+", "+this.changeDetectorFactoryExpressions[e]+", "+u(a)+")"))},e}(),S=function(){function e(e,t){this.commandFactory=e,this.embeddedTemplateIndex=t,this.result=[],this.transitiveNgContentCount=0}return e.prototype._readAttrNameAndValues=function(e,t){var n=o(r(this,t,[]));return e.forEach(function(e){y.StringMapWrapper.forEach(e.hostAttributes,function(e,t){var r=n[t];n[t]=d.isPresent(r)?a(t,r,e):e})}),s(n)},e.prototype.visitNgContent=function(e,t){return this.transitiveNgContentCount++,this.result.push(this.commandFactory.createNgContent(e.index,e.ngContentIndex)),null},e.prototype.visitEmbeddedTemplate=function(t,n){var r=this;this.embeddedTemplateIndex++;var i=new e(this.commandFactory,this.embeddedTemplateIndex);m.templateVisitAll(i,t.children);var o=i.transitiveNgContentCount>0,s=[];t.vars.forEach(function(e){s.push(e.name),s.push(e.value.length>0?e.value:C)});var a=[];return y.ListWrapper.forEachWithIndex(t.directives,function(e,t){e.visit(r,new D(t,[],[],a))}),this.result.push(this.commandFactory.createEmbeddedTemplate(this.embeddedTemplateIndex,this._readAttrNameAndValues(a,t.attrs),s,a,o,t.ngContentIndex,i.result)),this.transitiveNgContentCount+=i.transitiveNgContentCount,this.embeddedTemplateIndex=i.embeddedTemplateIndex,null},e.prototype.visitElement=function(e,t){var n=this,o=e.getComponent(),s=r(this,e.outputs,[]),a=[];d.isBlank(o)&&e.exportAsVars.forEach(function(e){a.push(e.name),a.push(null)});var c=[];y.ListWrapper.forEachWithIndex(e.directives,function(e,t){e.visit(n,new D(t,s,a,c))}),s=i(s);var u=this._readAttrNameAndValues(c,e.attrs);return d.isPresent(o)?(this.result.push(this.commandFactory.createBeginComponent(e.name,u,s,a,c,o.template.encapsulation,e.ngContentIndex)),m.templateVisitAll(this,e.children),this.result.push(this.commandFactory.createEndComponent())):(this.result.push(this.commandFactory.createBeginElement(e.name,u,s,a,c,e.isBound(),e.ngContentIndex)),m.templateVisitAll(this,e.children),this.result.push(this.commandFactory.createEndElement())),null},e.prototype.visitVariable=function(e,t){return null},e.prototype.visitAttr=function(e,t){return t.push(e.name),t.push(e.value),null},e.prototype.visitBoundText=function(e,t){return this.result.push(this.commandFactory.createText(null,!0,e.ngContentIndex)),null},e.prototype.visitText=function(e,t){return this.result.push(this.commandFactory.createText(e.value,!1,e.ngContentIndex)),null},e.prototype.visitDirective=function(e,t){return t.targetDirectives.push(e.directive),m.templateVisitAll(this,e.hostEvents,t.eventTargetAndNames),e.exportAsVars.forEach(function(e){t.targetVariableNameAndValues.push(e.name),t.targetVariableNameAndValues.push(t.index)}),null},e.prototype.visitEvent=function(e,t){return t.push(e.target),t.push(e.name),null},e.prototype.visitDirectiveProperty=function(e,t){return null},e.prototype.visitElementProperty=function(e,t){return null},e}(),D=function(){function e(e,t,n,r){this.index=e,this.eventTargetAndNames=t,this.targetVariableNameAndValues=n,this.targetDirectives=r}return e}(),T=function(){function e(e){this.value=e}return e}()},function(e,t,n){function r(e){return p.StringWrapper.split(e.trim(),/\s+/g)}function i(e,t){var n=new _.CssSelector,i=v.splitNsName(e)[1];n.setElement(i);for(var o=0;oo?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},a=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},c=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},u=n(12),p=n(5),l=n(2),h=n(5),f=n(14),d=n(25),y=n(168),v=n(172),m=n(171),g=n(159),_=n(154),b=n(173),C=n(174),P=n(163),w=n(169),R=n(155),E=/^(?:(?:(?:(bind-)|(var-|#)|(on-)|(bindon-))(.+))|\[\(([^\)]+)\)\]|\[([^\]]+)\]|\(([^\)]+)\))$/g,O="template",S="template",D="*",T="class",A=".",I="attr",x="class",N="style",k=_.CssSelector.parse("*")[0];t.TEMPLATE_TRANSFORMS=h.CONST_EXPR(new l.OpaqueToken("TemplateTransforms"));var j=function(e){function t(t,n){e.call(this,n,t)}return o(t,e),t}(m.ParseError);t.TemplateParseError=j;var V=function(){function e(e,t,n,r){this._exprParser=e,this._schemaRegistry=t,this._htmlParser=n,this.transforms=r}return e.prototype.parse=function(e,t,n){var r=new M(t,this._exprParser,this._schemaRegistry),i=this._htmlParser.parse(e,n),o=w.htmlVisitAll(r,i.rootNodes,W),s=i.errors.concat(r.errors);if(s.length>0){var a=s.join("\n");throw new f.BaseException("Template parse errors:\n"+a)}return p.isPresent(this.transforms)&&this.transforms.forEach(function(e){o=g.templateVisitAll(e,o)}),o},e=s([l.Injectable(),c(3,l.Optional()),c(3,l.Inject(t.TEMPLATE_TRANSFORMS)),a("design:paramtypes",[d.Parser,b.ElementSchemaRegistry,y.HtmlParser,Array])],e)}();t.TemplateParser=V;var M=function(){function e(e,t,n){var r=this;this._exprParser=t,this._schemaRegistry=n,this.errors=[],this.directivesIndex=new Map,this.ngContentCount=0,this.selectorMatcher=new _.SelectorMatcher,u.ListWrapper.forEachWithIndex(e,function(e,t){var n=_.CssSelector.parse(e.selector);r.selectorMatcher.addSelectables(n,e),r.directivesIndex.set(e,t)})}return e.prototype._reportError=function(e,t){this.errors.push(new j(e,t.start))},e.prototype._parseInterpolation=function(e,t){var n=t.start.toString();try{return this._exprParser.parseInterpolation(e,n)}catch(r){return this._reportError(""+r,t),this._exprParser.wrapLiteralPrimitive("ERROR",n)}},e.prototype._parseAction=function(e,t){var n=t.start.toString();try{return this._exprParser.parseAction(e,n)}catch(r){return this._reportError(""+r,t),this._exprParser.wrapLiteralPrimitive("ERROR",n)}},e.prototype._parseBinding=function(e,t){var n=t.start.toString();try{return this._exprParser.parseBinding(e,n)}catch(r){return this._reportError(""+r,t),this._exprParser.wrapLiteralPrimitive("ERROR",n)}},e.prototype._parseTemplateBindings=function(e,t){var n=t.start.toString();try{return this._exprParser.parseTemplateBindings(e,n)}catch(r){return this._reportError(""+r,t),[]}},e.prototype.visitText=function(e,t){var n=t.findNgContentIndex(k),r=this._parseInterpolation(e.value,e.sourceSpan);return p.isPresent(r)?new g.BoundTextAst(r,n,e.sourceSpan):new g.TextAst(e.value,n,e.sourceSpan)},e.prototype.visitAttr=function(e,t){return new g.AttrAst(e.name,e.value,e.sourceSpan)},e.prototype.visitElement=function(e,t){var n=this,r=e.name,o=C.preparseElement(e);if(o.type===C.PreparsedElementType.SCRIPT||o.type===C.PreparsedElementType.STYLE)return null;if(o.type===C.PreparsedElementType.STYLESHEET&&P.isStyleUrlResolvable(o.hrefAttr))return null;var s=[],a=[],c=[],u=[],l=[],h=[],f=[],d=!1,y=[];e.attrs.forEach(function(e){s.push([e.name,e.value]);var t=n._parseAttr(e,s,a,u,c),r=n._parseInlineTemplateBinding(e,f,l,h);t||r||y.push(n.visitAttr(e,null)),r&&(d=!0)});var m,_=v.splitNsName(r.toLowerCase())[1],b=_==O,R=i(r,s),E=this._createDirectiveAsts(e.name,this._parseDirectives(this.selectorMatcher,R),a,b?[]:c,e.sourceSpan),S=this._createElementPropertyAsts(e.name,a,E),D=w.htmlVisitAll(o.nonBindable?U:this,e.children,F.create(E)),T=d?null:t.findNgContentIndex(R);if(o.type===C.PreparsedElementType.NG_CONTENT)p.isPresent(e.children)&&e.children.length>0&&this._reportError(" element cannot have content. must be immediately followed by ",e.sourceSpan),m=new g.NgContentAst(this.ngContentCount++,T,e.sourceSpan);else if(b)this._assertAllEventsPublishedByDirectives(E,u),this._assertNoComponentsNorElementBindingsOnTemplate(E,S,e.sourceSpan),m=new g.EmbeddedTemplateAst(y,u,c,E,D,T,e.sourceSpan);else{this._assertOnlyOneComponent(E,e.sourceSpan);var A=c.filter(function(e){return 0===e.value.length});m=new g.ElementAst(r,y,S,u,A,E,D,T,e.sourceSpan)}if(d){var I=i(O,f),x=this._createDirectiveAsts(e.name,this._parseDirectives(this.selectorMatcher,I),l,[],e.sourceSpan),N=this._createElementPropertyAsts(e.name,l,x);this._assertNoComponentsNorElementBindingsOnTemplate(x,N,e.sourceSpan),m=new g.EmbeddedTemplateAst([],[],h,x,[m],t.findNgContentIndex(I),e.sourceSpan)}return m},e.prototype._parseInlineTemplateBinding=function(e,t,n,r){var i=null;if(e.name==S)i=e.value;else if(e.name.startsWith(D)){var o=e.name.substring(D.length);i=0==e.value.length?o:o+" "+e.value}if(p.isPresent(i)){for(var s=this._parseTemplateBindings(i,e.sourceSpan),a=0;a-1&&this._reportError('"-" is not allowed in variable names',n),r.push(new g.VariableAst(e,t,n))},e.prototype._parseProperty=function(e,t,n,r,i){this._parsePropertyAst(e,this._parseBinding(t,n),n,r,i)},e.prototype._parsePropertyInterpolation=function(e,t,n,r,i){var o=this._parseInterpolation(t,n);return p.isPresent(o)?(this._parsePropertyAst(e,o,n,r,i),!0):!1},e.prototype._parsePropertyAst=function(e,t,n,r,i){r.push([e,t.source]),i.push(new L(e,t,!1,n))},e.prototype._parseAssignmentEvent=function(e,t,n,r,i){this._parseEvent(e+"Change",t+"=$event",n,r,i)},e.prototype._parseEvent=function(e,t,n,r,i){var o=R.splitAtColon(e,[null,e]),s=o[0],a=o[1];i.push(new g.BoundEventAst(a,s,this._parseAction(t,n),n))},e.prototype._parseLiteralAttr=function(e,t,n,r){r.push(new L(e,this._exprParser.wrapLiteralPrimitive(t,""),!0,n))},e.prototype._parseDirectives=function(e,t){var n=this,r=[];return e.match(t,function(e,t){r.push(t)}),u.ListWrapper.sort(r,function(e,t){var r=e.isComponent,i=t.isComponent;return r&&!i?-1:!r&&i?1:n.directivesIndex.get(e)-n.directivesIndex.get(t)}),r},e.prototype._createDirectiveAsts=function(e,t,n,r,i){var o=this,s=new Set,a=t.map(function(t){var a=[],c=[],u=[];o._createDirectiveHostPropertyAsts(e,t.hostProperties,i,a),o._createDirectiveHostEventAsts(t.hostListeners,i,c),o._createDirectivePropertyAsts(t.inputs,n,u);var p=[];return r.forEach(function(e){(0===e.value.length&&t.isComponent||t.exportAs==e.value)&&(p.push(e),s.add(e.name))}),new g.DirectiveAst(t,u,a,c,p,i)});return r.forEach(function(e){e.value.length>0&&!u.SetWrapper.has(s,e.name)&&o._reportError('There is no directive with "exportAs" set to "'+e.value+'"',e.sourceSpan)}),a},e.prototype._createDirectiveHostPropertyAsts=function(e,t,n,r){var i=this;p.isPresent(t)&&u.StringMapWrapper.forEach(t,function(t,o){var s=i._parseBinding(t,n);r.push(i._createElementPropertyAst(e,o,s,n))})},e.prototype._createDirectiveHostEventAsts=function(e,t,n){var r=this;p.isPresent(e)&&u.StringMapWrapper.forEach(e,function(e,i){r._parseEvent(i,e,t,[],n)})},e.prototype._createDirectivePropertyAsts=function(e,t,n){if(p.isPresent(e)){var r=new Map;t.forEach(function(e){var t=r.get(e.name);(p.isBlank(t)||t.isLiteral)&&r.set(e.name,e)}),u.StringMapWrapper.forEach(e,function(e,t){var i=r.get(e);p.isPresent(i)&&n.push(new g.BoundDirectivePropertyAst(t,i.name,i.expression,i.sourceSpan))})}},e.prototype._createElementPropertyAsts=function(e,t,n){var r=this,i=[],o=new Map;return n.forEach(function(e){e.inputs.forEach(function(e){o.set(e.templateName,e)})}),t.forEach(function(t){!t.isLiteral&&p.isBlank(o.get(t.name))&&i.push(r._createElementPropertyAst(e,t.name,t.expression,t.sourceSpan))}),i},e.prototype._createElementPropertyAst=function(e,t,n,r){var i,o,s=null,a=t.split(A);return 1===a.length?(o=this._schemaRegistry.getMappedPropName(a[0]),i=g.PropertyBindingType.Property,this._schemaRegistry.hasProperty(e,o)||this._reportError("Can't bind to '"+o+"' since it isn't a known native property",r)):a[0]==I?(o=a[1],i=g.PropertyBindingType.Attribute):a[0]==x?(o=a[1],i=g.PropertyBindingType.Class):a[0]==N?(s=a.length>2?a[2]:null,o=a[1],i=g.PropertyBindingType.Style):(this._reportError("Invalid property name '"+t+"'",r),i=null),new g.BoundElementPropertyAst(o,i,n,s,r)},e.prototype._findComponentDirectiveNames=function(e){var t=[];return e.forEach(function(e){var n=e.directive.type.name;e.directive.isComponent&&t.push(n)}),t},e.prototype._assertOnlyOneComponent=function(e,t){var n=this._findComponentDirectiveNames(e);n.length>1&&this._reportError("More than one component: "+n.join(","),t)},e.prototype._assertNoComponentsNorElementBindingsOnTemplate=function(e,t,n){var r=this,i=this._findComponentDirectiveNames(e);i.length>0&&this._reportError("Components on an embedded template: "+i.join(","),n),t.forEach(function(e){r._reportError("Property binding "+e.name+" not used by any directive on an embedded template",n)})},e.prototype._assertAllEventsPublishedByDirectives=function(e,t){var n=this,r=new Set;e.forEach(function(e){u.StringMapWrapper.forEach(e.directive.outputs,function(e,t){r.add(e)})}),t.forEach(function(e){(p.isPresent(e.target)||!u.SetWrapper.has(r,e.name))&&n._reportError("Event binding "+e.fullName+" not emitted by any directive on an embedded template",e.sourceSpan)})},e}(),B=function(){function e(){}return e.prototype.visitElement=function(e,t){var n=C.preparseElement(e);if(n.type===C.PreparsedElementType.SCRIPT||n.type===C.PreparsedElementType.STYLE||n.type===C.PreparsedElementType.STYLESHEET)return null;var r=e.attrs.map(function(e){return[e.name,e.value]}),o=i(e.name,r),s=t.findNgContentIndex(o),a=w.htmlVisitAll(this,e.children,W);return new g.ElementAst(e.name,w.htmlVisitAll(this,e.attrs),[],[],[],[],a,s,e.sourceSpan)},e.prototype.visitAttr=function(e,t){return new g.AttrAst(e.name,e.value,e.sourceSpan)},e.prototype.visitText=function(e,t){var n=t.findNgContentIndex(k);return new g.TextAst(e.value,n,e.sourceSpan)},e}(),L=function(){function e(e,t,n,r){this.name=e,this.expression=t,this.isLiteral=n,this.sourceSpan=r}return e}();t.splitClasses=r;var F=function(){function e(e,t){this.ngContentIndexMatcher=e,this.wildcardNgContentIndex=t}return e.create=function(t){if(0===t.length||!t[0].directive.isComponent)return W;for(var n=new _.SelectorMatcher,r=t[0].directive.template.ngContentSelectors,i=null,o=0;o0?t[0]:null},e}(),W=new F(new _.SelectorMatcher,null),U=new B},function(e,t,n){function r(e,t){return c.isPresent(e)?"@"+e+":"+t:t}function i(e,t,n){return c.isBlank(e)&&(e=d.getHtmlTagDefinition(t).implicitNamespacePrefix,c.isBlank(e)&&c.isPresent(n)&&(e=d.getNsPrefix(n.name))),r(e,t)}var o=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},s=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},a=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},c=n(5),u=n(12),p=n(169),l=n(6),h=n(170),f=n(171),d=n(172),y=function(e){function t(t,n,r){e.call(this,n,r),this.elementName=t}return o(t,e),t.create=function(e,n,r){return new t(e,n,r)},t}(f.ParseError);t.HtmlTreeError=y;var v=function(){function e(e,t){this.rootNodes=e,this.errors=t}return e}();t.HtmlParseTreeResult=v;var m=function(){function e(){}return e.prototype.parse=function(e,t){var n=h.tokenizeHtml(e,t),r=new g(n.tokens).build();return new v(r.rootNodes,n.errors.concat(r.errors))},e=s([l.Injectable(),a("design:paramtypes",[])],e)}();t.HtmlParser=m;var g=function(){function e(e){this.tokens=e,this.index=-1,this.rootNodes=[],this.errors=[],this.elementStack=[],this._advance()}return e.prototype.build=function(){for(;this.peek.type!==h.HtmlTokenType.EOF;)this.peek.type===h.HtmlTokenType.TAG_OPEN_START?this._consumeStartTag(this._advance()):this.peek.type===h.HtmlTokenType.TAG_CLOSE?this._consumeEndTag(this._advance()):this.peek.type===h.HtmlTokenType.CDATA_START?(this._closeVoidElement(),this._consumeCdata(this._advance())):this.peek.type===h.HtmlTokenType.COMMENT_START?(this._closeVoidElement(),this._consumeComment(this._advance())):this.peek.type===h.HtmlTokenType.TEXT||this.peek.type===h.HtmlTokenType.RAW_TEXT||this.peek.type===h.HtmlTokenType.ESCAPABLE_RAW_TEXT?(this._closeVoidElement(),this._consumeText(this._advance())):this._advance();return new v(this.rootNodes,this.errors)},e.prototype._advance=function(){var e=this.peek;return this.index0&&"\n"==t[0]){var n=this._getParentElement();c.isPresent(n)&&0==n.children.length&&d.getHtmlTagDefinition(n.name).ignoreFirstLf&&(t=t.substring(1))}t.length>0&&this._addToParent(new p.HtmlTextAst(t,e.sourceSpan))},e.prototype._closeVoidElement=function(){if(this.elementStack.length>0){var e=u.ListWrapper.last(this.elementStack);d.getHtmlTagDefinition(e.name).isVoid&&this.elementStack.pop()}},e.prototype._consumeStartTag=function(e){for(var t=e.parts[0],n=e.parts[1],r=[];this.peek.type===h.HtmlTokenType.ATTR_NAME;)r.push(this._consumeAttr(this._advance()));var o=i(t,n,this._getParentElement()),s=!1;this.peek.type===h.HtmlTokenType.TAG_OPEN_END_VOID?(this._advance(),s=!0,null!=d.getNsPrefix(o)||d.getHtmlTagDefinition(o).isVoid||this.errors.push(y.create(o,e.sourceSpan.start,'Only void and foreign elements can be self closed "'+e.parts[1]+'"'))):this.peek.type===h.HtmlTokenType.TAG_OPEN_END&&(this._advance(),s=!1);var a=this.peek.sourceSpan.start,c=new p.HtmlElementAst(o,r,[],new f.ParseSourceSpan(e.sourceSpan.start,a));this._pushElement(c),s&&this._popElement(o)},e.prototype._pushElement=function(e){if(this.elementStack.length>0){var t=u.ListWrapper.last(this.elementStack);d.getHtmlTagDefinition(t.name).isClosedByChild(e.name)&&this.elementStack.pop()}var n=d.getHtmlTagDefinition(e.name),t=this._getParentElement();if(n.requireExtraParent(c.isPresent(t)?t.name:null)){var r=new p.HtmlElementAst(n.parentToAdd,[],[e],e.sourceSpan);this._addToParent(r),this.elementStack.push(r),this.elementStack.push(e)}else this._addToParent(e),this.elementStack.push(e)},e.prototype._consumeEndTag=function(e){var t=i(e.parts[0],e.parts[1],this._getParentElement());d.getHtmlTagDefinition(t).isVoid?this.errors.push(y.create(t,e.sourceSpan.start,'Void elements do not have end tags "'+e.parts[1]+'"')):this._popElement(t)||this.errors.push(y.create(t,e.sourceSpan.start,'Unexpected closing tag "'+e.parts[1]+'"')); -},e.prototype._popElement=function(e){for(var t=this.elementStack.length-1;t>=0;t--){var n=this.elementStack[t];if(n.name==e)return u.ListWrapper.splice(this.elementStack,t,this.elementStack.length-t),!0;if(!d.getHtmlTagDefinition(n.name).closedByParent)return!1}return!1},e.prototype._consumeAttr=function(e){var t=r(e.parts[0],e.parts[1]),n=e.sourceSpan.end,i="";if(this.peek.type===h.HtmlTokenType.ATTR_VALUE){var o=this._advance();i=o.parts[0],n=o.sourceSpan.end}return new p.HtmlAttrAst(t,i,new f.ParseSourceSpan(e.sourceSpan.start,n))},e.prototype._getParentElement=function(){return this.elementStack.length>0?u.ListWrapper.last(this.elementStack):null},e.prototype._addToParent=function(e){var t=this._getParentElement();c.isPresent(t)?t.children.push(e):this.rootNodes.push(e)},e}()},function(e,t,n){function r(e,t,n){void 0===n&&(n=null);var r=[];return t.forEach(function(t){var o=t.visit(e,n);i.isPresent(o)&&r.push(o)}),r}var i=n(5),o=function(){function e(e,t){this.value=e,this.sourceSpan=t}return e.prototype.visit=function(e,t){return e.visitText(this,t)},e}();t.HtmlTextAst=o;var s=function(){function e(e,t,n){this.name=e,this.value=t,this.sourceSpan=n}return e.prototype.visit=function(e,t){return e.visitAttr(this,t)},e}();t.HtmlAttrAst=s;var a=function(){function e(e,t,n,r){this.name=e,this.attrs=t,this.children=n,this.sourceSpan=r}return e.prototype.visit=function(e,t){return e.visitElement(this,t)},e}();t.HtmlElementAst=a,t.htmlVisitAll=r},function(e,t,n){function r(e,t){return new te(new _.ParseSourceFile(e,t)).tokenize()}function i(e){var t=e===E?"EOF":m.StringWrapper.fromCharCode(e);return'Unexpected character "'+t+'"'}function o(e){return'Unknown entity "'+e+'" - use the "&#;" or "&#x;" syntax'}function s(e){return!a(e)||e===E}function a(e){return e>=O&&T>=e||e===Z}function c(e){return a(e)||e===H||e===V||e===k||e===I||e===U}function u(e){return($>e||e>Q)&&(q>e||e>G)&&(M>e||e>L)}function p(e){return e==B||e==E||!d(e)}function l(e){return e==B||e==E||!f(e)}function h(e){return e===W||e===E}function f(e){return e>=$&&Q>=e}function d(e){return e>=$&&X>=e||e>=M&&L>=e}function y(e){for(var t,n=[],r=0;r=this.length)throw this._createError(i(E),this._getLocation());this.peek===S?(this.line++,this.column=0):this.peek!==S&&this.peek!==D&&this.column++,this.index++,this.peek=this.index>=this.length?E:m.StringWrapper.charCodeAt(this.inputLowercase,this.index)},e.prototype._attemptChar=function(e){return this.peek===e?(this._advance(),!0):!1},e.prototype._requireChar=function(e){var t=this._getLocation();if(!this._attemptChar(e))throw this._createError(i(this.peek),t)},e.prototype._attemptChars=function(e){for(var t=0;tr.offset&&o.push(this.input.substring(r.offset,this.index));this.peek!==t;)o.push(this._readChar(e))}return this._endToken([this._processCarriageReturns(o.join(""))],r)},e.prototype._consumeComment=function(e){var t=this;this._beginToken(C.COMMENT_START,e),this._requireChar(j),this._endToken([]);var n=this._consumeRawText(!1,j,function(){return t._attemptChars("->")});this._beginToken(C.COMMENT_END,n.sourceSpan.end),this._endToken([])},e.prototype._consumeCdata=function(e){var t=this;this._beginToken(C.CDATA_START,e),this._requireChars("cdata["),this._endToken([]);var n=this._consumeRawText(!1,K,function(){return t._attemptChars("]>")});this._beginToken(C.CDATA_END,n.sourceSpan.end),this._endToken([])},e.prototype._consumeDocType=function(e){this._beginToken(C.DOC_TYPE,e),this._attemptUntilChar(H),this._advance(),this._endToken([this.input.substring(e.offset+2,this.index-1)])},e.prototype._consumePrefixAndName=function(){for(var e=this.index,t=null;this.peek!==F&&!u(this.peek);)this._advance();var n;this.peek===F?(this._advance(),t=this.input.substring(e,this.index-1),n=this.index):n=e,this._requireUntilFn(c,this.index===n?1:0);var r=this.input.substring(n,this.index);return[t,r]},e.prototype._consumeTagOpen=function(e){var t,n=this._savePosition();try{if(!f(this.peek))throw this._createError(i(this.peek),this._getLocation());var r=this.index;for(this._consumeTagOpenStart(e),t=this.inputLowercase.substring(r,this.index),this._attemptUntilFn(s);this.peek!==V&&this.peek!==H;)this._consumeAttributeName(),this._attemptUntilFn(s),this._attemptChar(U)&&(this._attemptUntilFn(s),this._consumeAttributeValue()),this._attemptUntilFn(s);this._consumeTagOpenEnd()}catch(o){if(o instanceof ee)return this._restorePosition(n),this._beginToken(C.TEXT,e),void this._endToken(["<"]);throw o}var a=b.getHtmlTagDefinition(t).contentType;a===b.HtmlTagContentType.RAW_TEXT?this._consumeRawTextWithTagClose(t,!1):a===b.HtmlTagContentType.ESCAPABLE_RAW_TEXT&&this._consumeRawTextWithTagClose(t,!0)},e.prototype._consumeRawTextWithTagClose=function(e,t){var n=this,r=this._consumeRawText(t,W,function(){return n._attemptChar(V)?(n._attemptUntilFn(s),n._attemptChars(e)?(n._attemptUntilFn(s),n._attemptChar(H)?!0:!1):!1):!1});this._beginToken(C.TAG_CLOSE,r.sourceSpan.end),this._endToken([null,e])},e.prototype._consumeTagOpenStart=function(e){this._beginToken(C.TAG_OPEN_START,e);var t=this._consumePrefixAndName();this._endToken(t)},e.prototype._consumeAttributeName=function(){this._beginToken(C.ATTR_NAME);var e=this._consumePrefixAndName();this._endToken(e)},e.prototype._consumeAttributeValue=function(){this._beginToken(C.ATTR_VALUE);var e;if(this.peek===k||this.peek===I){var t=this.peek;this._advance();for(var n=[];this.peek!==t;)n.push(this._readChar(!0));e=n.join(""),this._advance()}else{var r=this.index;this._requireUntilFn(c,1),e=this.input.substring(r,this.index)}this._endToken([this._processCarriageReturns(e)])},e.prototype._consumeTagOpenEnd=function(){var e=this._attemptChar(V)?C.TAG_OPEN_END_VOID:C.TAG_OPEN_END;this._beginToken(e),this._requireChar(H),this._endToken([])},e.prototype._consumeTagClose=function(e){this._beginToken(C.TAG_CLOSE,e),this._attemptUntilFn(s);var t;t=this._consumePrefixAndName(),this._attemptUntilFn(s),this._requireChar(H),this._endToken(t)},e.prototype._consumeText=function(){var e=this._getLocation();this._beginToken(C.TEXT,e);for(var t=[this._readChar(!0)];!h(this.peek);)t.push(this._readChar(!0));this._endToken([this._processCarriageReturns(t.join(""))])},e.prototype._savePosition=function(){return[this.peek,this.index,this.column,this.line,this.tokens.length]},e.prototype._restorePosition=function(e){this.peek=e[0],this.index=e[1],this.column=e[2],this.line=e[3];var t=e[4];te.length-1&&(t=e.length-1);for(var n=t,r=0,i=0;100>r&&t>0&&(t--,r++,"\n"!=e[t]||3!=++i););for(r=0,i=0;100>r&&n]"+e.substring(this.location.offset,n+1);return this.msg+' ("'+o+'"): '+this.location},e}();t.ParseError=i;var o=function(){function e(e,t){this.start=e,this.end=t}return e.prototype.toString=function(){return this.start.file.content.substring(this.start.offset,this.end.offset)},e}();t.ParseSourceSpan=o},function(e,t,n){function r(e){var t=u[e.toLowerCase()];return s.isPresent(t)?t:p}function i(e){if("@"!=e[0])return[null,e];var t=s.RegExpWrapper.firstMatch(l,e);return[t[1],t[2]]}function o(e){return i(e)[0]}var s=n(5);t.NAMED_ENTITIES=s.CONST_EXPR({Aacute:"Á",aacute:"á",Acirc:"Â",acirc:"â",acute:"´",AElig:"Æ",aelig:"æ",Agrave:"À",agrave:"à",alefsym:"ℵ",Alpha:"Α",alpha:"α",amp:"&",and:"∧",ang:"∠",apos:"'",Aring:"Å",aring:"å",asymp:"≈",Atilde:"Ã",atilde:"ã",Auml:"Ä",auml:"ä",bdquo:"„",Beta:"Β",beta:"β",brvbar:"¦",bull:"•",cap:"∩",Ccedil:"Ç",ccedil:"ç",cedil:"¸",cent:"¢",Chi:"Χ",chi:"χ",circ:"ˆ",clubs:"♣",cong:"≅",copy:"©",crarr:"↵",cup:"∪",curren:"¤",dagger:"†",Dagger:"‡",darr:"↓",dArr:"⇓",deg:"°",Delta:"Δ",delta:"δ",diams:"♦",divide:"÷",Eacute:"É",eacute:"é",Ecirc:"Ê",ecirc:"ê",Egrave:"È",egrave:"è",empty:"∅",emsp:" ",ensp:" ",Epsilon:"Ε",epsilon:"ε",equiv:"≡",Eta:"Η",eta:"η",ETH:"Ð",eth:"ð",Euml:"Ë",euml:"ë",euro:"€",exist:"∃",fnof:"ƒ",forall:"∀",frac12:"½",frac14:"¼",frac34:"¾",frasl:"⁄",Gamma:"Γ",gamma:"γ",ge:"≥",gt:">",harr:"↔",hArr:"⇔",hearts:"♥",hellip:"…",Iacute:"Í",iacute:"í",Icirc:"Î",icirc:"î",iexcl:"¡",Igrave:"Ì",igrave:"ì",image:"ℑ",infin:"∞","int":"∫",Iota:"Ι",iota:"ι",iquest:"¿",isin:"∈",Iuml:"Ï",iuml:"ï",Kappa:"Κ",kappa:"κ",Lambda:"Λ",lambda:"λ",lang:"⟨",laquo:"«",larr:"←",lArr:"⇐",lceil:"⌈",ldquo:"“",le:"≤",lfloor:"⌊",lowast:"∗",loz:"◊",lrm:"‎",lsaquo:"‹",lsquo:"‘",lt:"<",macr:"¯",mdash:"—",micro:"µ",middot:"·",minus:"−",Mu:"Μ",mu:"μ",nabla:"∇",nbsp:" ",ndash:"–",ne:"≠",ni:"∋",not:"¬",notin:"∉",nsub:"⊄",Ntilde:"Ñ",ntilde:"ñ",Nu:"Ν",nu:"ν",Oacute:"Ó",oacute:"ó",Ocirc:"Ô",ocirc:"ô",OElig:"Œ",oelig:"œ",Ograve:"Ò",ograve:"ò",oline:"‾",Omega:"Ω",omega:"ω",Omicron:"Ο",omicron:"ο",oplus:"⊕",or:"∨",ordf:"ª",ordm:"º",Oslash:"Ø",oslash:"ø",Otilde:"Õ",otilde:"õ",otimes:"⊗",Ouml:"Ö",ouml:"ö",para:"¶",permil:"‰",perp:"⊥",Phi:"Φ",phi:"φ",Pi:"Π",pi:"π",piv:"ϖ",plusmn:"±",pound:"£",prime:"′",Prime:"″",prod:"∏",prop:"∝",Psi:"Ψ",psi:"ψ",quot:'"',radic:"√",rang:"⟩",raquo:"»",rarr:"→",rArr:"⇒",rceil:"⌉",rdquo:"”",real:"ℜ",reg:"®",rfloor:"⌋",Rho:"Ρ",rho:"ρ",rlm:"‏",rsaquo:"›",rsquo:"’",sbquo:"‚",Scaron:"Š",scaron:"š",sdot:"⋅",sect:"§",shy:"­",Sigma:"Σ",sigma:"σ",sigmaf:"ς",sim:"∼",spades:"♠",sub:"⊂",sube:"⊆",sum:"∑",sup:"⊃",sup1:"¹",sup2:"²",sup3:"³",supe:"⊇",szlig:"ß",Tau:"Τ",tau:"τ",there4:"∴",Theta:"Θ",theta:"θ",thetasym:"ϑ",thinsp:" ",THORN:"Þ",thorn:"þ",tilde:"˜",times:"×",trade:"™",Uacute:"Ú",uacute:"ú",uarr:"↑",uArr:"⇑",Ucirc:"Û",ucirc:"û",Ugrave:"Ù",ugrave:"ù",uml:"¨",upsih:"ϒ",Upsilon:"Υ",upsilon:"υ",Uuml:"Ü",uuml:"ü",weierp:"℘",Xi:"Ξ",xi:"ξ",Yacute:"Ý",yacute:"ý",yen:"¥",yuml:"ÿ",Yuml:"Ÿ",Zeta:"Ζ",zeta:"ζ",zwj:"‍",zwnj:"‌"}),function(e){e[e.RAW_TEXT=0]="RAW_TEXT",e[e.ESCAPABLE_RAW_TEXT=1]="ESCAPABLE_RAW_TEXT",e[e.PARSABLE_DATA=2]="PARSABLE_DATA"}(t.HtmlTagContentType||(t.HtmlTagContentType={}));var a=t.HtmlTagContentType,c=function(){function e(e){var t=this,n=void 0===e?{}:e,r=n.closedByChildren,i=n.requiredParents,o=n.implicitNamespacePrefix,c=n.contentType,u=n.closedByParent,p=n.isVoid,l=n.ignoreFirstLf;this.closedByChildren={},this.closedByParent=!1,s.isPresent(r)&&r.length>0&&r.forEach(function(e){return t.closedByChildren[e]=!0}),this.isVoid=s.normalizeBool(p),this.closedByParent=s.normalizeBool(u)||this.isVoid,s.isPresent(i)&&i.length>0&&(this.requiredParents={},this.parentToAdd=i[0],i.forEach(function(e){return t.requiredParents[e]=!0})),this.implicitNamespacePrefix=o,this.contentType=s.isPresent(c)?c:a.PARSABLE_DATA,this.ignoreFirstLf=s.normalizeBool(l)}return e.prototype.requireExtraParent=function(e){if(s.isBlank(this.requiredParents))return!1;if(s.isBlank(e))return!0;var t=e.toLowerCase();return 1!=this.requiredParents[t]&&"template"!=t},e.prototype.isClosedByChild=function(e){return this.isVoid||s.normalizeBool(this.closedByChildren[e.toLowerCase()])},e}();t.HtmlTagDefinition=c;var u={area:new c({isVoid:!0}),embed:new c({isVoid:!0}),link:new c({isVoid:!0}),img:new c({isVoid:!0}),input:new c({isVoid:!0}),param:new c({isVoid:!0}),hr:new c({isVoid:!0}),br:new c({isVoid:!0}),source:new c({isVoid:!0}),track:new c({isVoid:!0}),wbr:new c({isVoid:!0}),p:new c({closedByChildren:["address","article","aside","blockquote","div","dl","fieldset","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","hr","main","nav","ol","p","pre","section","table","ul"],closedByParent:!0}),thead:new c({closedByChildren:["tbody","tfoot"]}),tbody:new c({closedByChildren:["tbody","tfoot"],closedByParent:!0}),tfoot:new c({closedByChildren:["tbody"],closedByParent:!0}),tr:new c({closedByChildren:["tr"],requiredParents:["tbody","tfoot","thead"],closedByParent:!0}),td:new c({closedByChildren:["td","th"],closedByParent:!0}),th:new c({closedByChildren:["td","th"],closedByParent:!0}),col:new c({requiredParents:["colgroup"],isVoid:!0}),svg:new c({implicitNamespacePrefix:"svg"}),math:new c({implicitNamespacePrefix:"math"}),li:new c({closedByChildren:["li"],closedByParent:!0}),dt:new c({closedByChildren:["dt","dd"]}),dd:new c({closedByChildren:["dt","dd"],closedByParent:!0}),rb:new c({closedByChildren:["rb","rt","rtc","rp"],closedByParent:!0}),rt:new c({closedByChildren:["rb","rt","rtc","rp"],closedByParent:!0}),rtc:new c({closedByChildren:["rb","rtc","rp"],closedByParent:!0}),rp:new c({closedByChildren:["rb","rt","rtc","rp"],closedByParent:!0}),optgroup:new c({closedByChildren:["optgroup"],closedByParent:!0}),option:new c({closedByChildren:["option","optgroup"],closedByParent:!0}),pre:new c({ignoreFirstLf:!0}),listing:new c({ignoreFirstLf:!0}),style:new c({contentType:a.RAW_TEXT}),script:new c({contentType:a.RAW_TEXT}),title:new c({contentType:a.ESCAPABLE_RAW_TEXT}),textarea:new c({contentType:a.ESCAPABLE_RAW_TEXT,ignoreFirstLf:!0})},p=new c;t.getHtmlTagDefinition=r;var l=/^@([^:]+):(.+)/g;t.splitNsName=i,t.getNsPrefix=o},function(e,t){var n=function(){function e(){}return e.prototype.hasProperty=function(e,t){return!0},e.prototype.getMappedPropName=function(e){return e},e}();t.ElementSchemaRegistry=n},function(e,t,n){function r(e){var t=null,n=null,r=null,o=!1;e.attrs.forEach(function(e){var i=e.name.toLowerCase();i==a?t=e.value:i==l?n=e.value:i==p?r=e.value:e.name==y&&(o=!0)}),t=i(t);var g=e.name.toLowerCase(),_=v.OTHER;return s.splitNsName(g)[1]==c?_=v.NG_CONTENT:g==f?_=v.STYLE:g==d?_=v.SCRIPT:g==u&&r==h&&(_=v.STYLESHEET),new m(_,t,n,o)}function i(e){return o.isBlank(e)||0===e.length?"*":e}var o=n(5),s=n(172),a="select",c="ng-content",u="link",p="rel",l="href",h="stylesheet",f="style",d="script",y="ngNonBindable";t.preparseElement=r,function(e){e[e.NG_CONTENT=0]="NG_CONTENT",e[e.STYLE=1]="STYLE",e[e.STYLESHEET=2]="STYLESHEET",e[e.SCRIPT=3]="SCRIPT",e[e.OTHER=4]="OTHER"}(t.PreparsedElementType||(t.PreparsedElementType={}));var v=t.PreparsedElementType,m=function(){function e(e,t,n,r){this.type=e,this.selectAttr=t,this.hrefAttr=n,this.nonBindable=r}return e}();t.PreparsedElement=m},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(153),s=n(5),a=n(14),c=n(60),u=n(149),p=n(148),l=n(163),h=n(6),f=n(56),d=n(169),y=n(168),v=n(174),m=function(){function e(e,t,n){this._xhr=e,this._urlResolver=t,this._htmlParser=n}return e.prototype.normalizeTemplate=function(e,t){var n=this;if(s.isPresent(t.template))return c.PromiseWrapper.resolve(this.normalizeLoadedTemplate(e,t,t.template,e.moduleUrl));if(s.isPresent(t.templateUrl)){var r=this._urlResolver.resolve(e.moduleUrl,t.templateUrl);return this._xhr.get(r).then(function(i){return n.normalizeLoadedTemplate(e,t,i,r)})}throw new a.BaseException("No template specified for component "+e.name)},e.prototype.normalizeLoadedTemplate=function(e,t,n,r){var i=this,s=this._htmlParser.parse(n,e.name);if(s.errors.length>0){var c=s.errors.join("\n");throw new a.BaseException("Template parse errors:\n"+c)}var u=new g;d.htmlVisitAll(u,s.rootNodes);var p=t.styles.concat(u.styles),h=u.styleUrls.filter(l.isStyleUrlResolvable).map(function(e){return i._urlResolver.resolve(r,e)}).concat(t.styleUrls.filter(l.isStyleUrlResolvable).map(function(t){return i._urlResolver.resolve(e.moduleUrl,t)})),y=p.map(function(e){var t=l.extractStyleUrls(i._urlResolver,r,e);return t.styleUrls.forEach(function(e){return h.push(e)}),t.style}),v=t.encapsulation;return v===f.ViewEncapsulation.Emulated&&0===y.length&&0===h.length&&(v=f.ViewEncapsulation.None),new o.CompileTemplateMetadata({encapsulation:v,template:n,templateUrl:r,styles:y,styleUrls:h,ngContentSelectors:u.ngContentSelectors})},e=r([h.Injectable(),i("design:paramtypes",[u.XHR,p.UrlResolver,y.HtmlParser])],e)}();t.TemplateNormalizer=m;var g=function(){function e(){this.ngContentSelectors=[],this.styles=[],this.styleUrls=[],this.ngNonBindableStackCount=0}return e.prototype.visitElement=function(e,t){var n=v.preparseElement(e);switch(n.type){case v.PreparsedElementType.NG_CONTENT:0===this.ngNonBindableStackCount&&this.ngContentSelectors.push(n.selectAttr);break;case v.PreparsedElementType.STYLE:var r="";e.children.forEach(function(e){e instanceof d.HtmlTextAst&&(r+=e.value)}),this.styles.push(r);break;case v.PreparsedElementType.STYLESHEET:this.styleUrls.push(n.hrefAttr)}return n.nonBindable&&this.ngNonBindableStackCount++,d.htmlVisitAll(this,e.children),n.nonBindable&&this.ngNonBindableStackCount--,null},e.prototype.visitAttr=function(e,t){return null},e.prototype.visitText=function(e,t){return null},e}()},function(e,t,n){function r(e,t){var n=[];return l.isPresent(t)&&i(t,n),l.isPresent(e.directives)&&i(e.directives,n),n}function i(e,t){for(var n=0;n0?n:"package:"+n+P.MODULE_SUFFIX}return _.reflector.importUri(e)}var a=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},c=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},u=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},p=n(6),l=n(5),h=n(14),f=n(153),d=n(23),y=n(92),v=n(93),m=n(88),g=n(89),_=n(16),b=n(6),C=n(95),P=n(155),w=n(148),R=function(){function e(e,t,n){this._directiveResolver=e,this._viewResolver=t,this._platformDirectives=n,this._cache=new Map}return e.prototype.getMetadata=function(e){var t=this._cache.get(e);if(l.isBlank(t)){var n=this._directiveResolver.resolve(e),r=null,i=null,o=null;if(n instanceof d.ComponentMetadata){var a=n;r=s(e,a);var c=this._viewResolver.resolve(e);i=new f.CompileTemplateMetadata({encapsulation:c.encapsulation,template:c.template,templateUrl:c.templateUrl,styles:c.styles,styleUrls:c.styleUrls}),o=a.changeDetection}t=f.CompileDirectiveMetadata.create({selector:n.selector,exportAs:n.exportAs,isComponent:l.isPresent(i),dynamicLoadable:!0,type:new f.CompileTypeMetadata({name:l.stringify(e),moduleUrl:r,runtime:e}),template:i,changeDetection:o,inputs:n.inputs,outputs:n.outputs,host:n.host,lifecycleHooks:g.LIFECYCLE_HOOKS_VALUES.filter(function(t){return m.hasLifecycleHook(t,e)})}),this._cache.set(e,t)}return t},e.prototype.getViewDirectivesMetadata=function(e){for(var t=this,n=this._viewResolver.resolve(e),i=r(n,this._platformDirectives),s=0;so?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=n(6),a=n(5),c=n(12),u=n(178),p=n(172),l=n(173),h=a.CONST_EXPR({xlink:"http://www.w3.org/1999/xlink",svg:"http://www.w3.org/2000/svg"}),f=function(e){function t(){e.apply(this,arguments),this._protoElements=new Map}return r(t,e),t.prototype._getProtoElement=function(e){var t=this._protoElements.get(e);if(a.isBlank(t)){var n=p.splitNsName(e);t=a.isPresent(n[0])?u.DOM.createElementNS(h[n[0]],n[1]):u.DOM.createElement(n[1]),this._protoElements.set(e,t)}return t},t.prototype.hasProperty=function(e,t){if(-1!==e.indexOf("-"))return!0;var n=this._getProtoElement(e);return u.DOM.hasProperty(n,t)},t.prototype.getMappedPropName=function(e){var t=c.StringMapWrapper.get(u.DOM.attrToPropMap,e);return a.isPresent(t)?t:e},t=i([s.Injectable(),o("design:paramtypes",[])],t)}(l.ElementSchemaRegistry);t.DomElementSchemaRegistry=f},function(e,t,n){function r(e){i.isBlank(t.DOM)&&(t.DOM=e)}var i=n(5);t.DOM=null,t.setRootDomAdapter=r;var o=function(){function e(){}return e}();t.DomAdapter=o},function(e,t,n){function r(e,n){u.reflector.reflectionCapabilities=new p.ReflectionCapabilities;var r=s.isPresent(n)?[t.BROWSER_APP_PROVIDERS,n]:t.BROWSER_APP_PROVIDERS;return u.platform(a.BROWSER_PROVIDERS).application(r).bootstrap(e)}var i=n(180);t.AngularEntrypoint=i.AngularEntrypoint;var o=n(181);t.BROWSER_PROVIDERS=o.BROWSER_PROVIDERS,t.ELEMENT_PROBE_BINDINGS=o.ELEMENT_PROBE_BINDINGS,t.ELEMENT_PROBE_PROVIDERS=o.ELEMENT_PROBE_PROVIDERS,t.inspectNativeElement=o.inspectNativeElement,t.BrowserDomAdapter=o.BrowserDomAdapter,t.By=o.By,t.Title=o.Title,t.DOCUMENT=o.DOCUMENT,t.enableDebugTools=o.enableDebugTools,t.disableDebugTools=o.disableDebugTools;var s=n(5),a=n(181),c=n(147),u=n(2),p=n(18),l=n(199),h=n(147),f=n(6);t.BROWSER_APP_PROVIDERS=s.CONST_EXPR([a.BROWSER_APP_COMMON_PROVIDERS,c.COMPILER_PROVIDERS,new f.Provider(h.XHR,{useClass:l.XHRImpl})]),t.bootstrap=r},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(5),s=function(){function e(e){this.name=e}return e=r([o.CONST(),i("design:paramtypes",[String])],e)}();t.AngularEntrypoint=s},function(e,t,n){function r(){return new c.ExceptionHandler(l.DOM,!s.IS_DART)}function i(){return l.DOM.defaultDoc()}function o(){C.BrowserDomAdapter.makeCurrent(),w.wtfInit(),P.BrowserGetTestability.init()}var s=n(5),a=n(6),c=n(2),u=n(104),p=n(68),l=n(178),h=n(182),f=n(184),d=n(185),y=n(187),v=n(188),m=n(196),g=n(196),_=n(195),b=n(189),C=n(197),P=n(200),w=n(201),R=n(183),E=n(187);t.DOCUMENT=E.DOCUMENT;var O=n(202);t.Title=O.Title;var S=n(203);t.DebugElementViewListener=S.DebugElementViewListener,t.ELEMENT_PROBE_PROVIDERS=S.ELEMENT_PROBE_PROVIDERS,t.ELEMENT_PROBE_BINDINGS=S.ELEMENT_PROBE_BINDINGS,t.inspectNativeElement=S.inspectNativeElement,t.By=S.By;var D=n(197);t.BrowserDomAdapter=D.BrowserDomAdapter;var T=n(206);t.enableDebugTools=T.enableDebugTools,t.disableDebugTools=T.disableDebugTools,t.BROWSER_PROVIDERS=s.CONST_EXPR([c.PLATFORM_COMMON_PROVIDERS,new a.Provider(c.PLATFORM_INITIALIZER,{useValue:o,multi:!0})]),t.BROWSER_APP_COMMON_PROVIDERS=s.CONST_EXPR([c.APPLICATION_COMMON_PROVIDERS,u.FORM_PROVIDERS,new a.Provider(c.PLATFORM_PIPES,{useValue:u.COMMON_PIPES,multi:!0}),new a.Provider(c.PLATFORM_DIRECTIVES,{useValue:u.COMMON_DIRECTIVES,multi:!0}),new a.Provider(c.ExceptionHandler,{useFactory:r,deps:[]}),new a.Provider(y.DOCUMENT,{useFactory:i,deps:[]}),new a.Provider(R.EVENT_MANAGER_PLUGINS,{useClass:h.DomEventsPlugin,multi:!0}),new a.Provider(R.EVENT_MANAGER_PLUGINS,{useClass:f.KeyEventsPlugin,multi:!0}),new a.Provider(R.EVENT_MANAGER_PLUGINS,{useClass:d.HammerGesturesPlugin,multi:!0}),new a.Provider(v.DomRenderer,{useClass:v.DomRenderer_}),new a.Provider(c.Renderer,{useExisting:v.DomRenderer}),new a.Provider(g.SharedStylesHost,{useExisting:m.DomSharedStylesHost}),m.DomSharedStylesHost,p.Testability,_.BrowserDetails,b.AnimationBuilder,R.EventManager]),t.initDomAdapter=o},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=n(178),a=n(2),c=n(183),u=function(e){function t(){e.apply(this,arguments)}return r(t,e),t.prototype.supports=function(e){return!0},t.prototype.addEventListener=function(e,t,n){var r=this.manager.getZone(),i=function(e){return r.run(function(){return n(e)})};this.manager.getZone().runOutsideAngular(function(){s.DOM.on(e,t,i)})},t.prototype.addGlobalEventListener=function(e,t,n){var r=s.DOM.getGlobalEventTarget(e),i=this.manager.getZone(),o=function(e){return i.run(function(){return n(e)})};return this.manager.getZone().runOutsideAngular(function(){return s.DOM.onAndCancel(r,t,o)})},t=i([a.Injectable(),o("design:paramtypes",[])],t)}(c.EventManagerPlugin);t.DomEventsPlugin=u},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},s=n(5),a=n(14),c=n(6),u=n(66),p=n(12);t.EVENT_MANAGER_PLUGINS=s.CONST_EXPR(new c.OpaqueToken("EventManagerPlugins"));var l=function(){function e(e,t){var n=this;this._zone=t,e.forEach(function(e){return e.manager=n}),this._plugins=p.ListWrapper.reversed(e)}return e.prototype.addEventListener=function(e,t,n){var r=this._findPluginFor(t);r.addEventListener(e,t,n)},e.prototype.addGlobalEventListener=function(e,t,n){var r=this._findPluginFor(t);return r.addGlobalEventListener(e,t,n)},e.prototype.getZone=function(){return this._zone},e.prototype._findPluginFor=function(e){for(var t=this._plugins,n=0;no?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=n(178),a=n(5),c=n(12),u=n(183),p=n(6),l=["alt","control","meta","shift"],h={alt:function(e){return e.altKey},control:function(e){return e.ctrlKey},meta:function(e){return e.metaKey},shift:function(e){return e.shiftKey}},f=function(e){function t(){e.call(this)}return r(t,e),t.prototype.supports=function(e){return a.isPresent(t.parseEventName(e))},t.prototype.addEventListener=function(e,n,r){var i=t.parseEventName(n),o=t.eventCallback(e,c.StringMapWrapper.get(i,"fullKey"),r,this.manager.getZone());this.manager.getZone().runOutsideAngular(function(){s.DOM.on(e,c.StringMapWrapper.get(i,"domEventName"),o)})},t.parseEventName=function(e){var n=e.toLowerCase().split("."),r=n.shift();if(0===n.length||!a.StringWrapper.equals(r,"keydown")&&!a.StringWrapper.equals(r,"keyup"))return null;var i=t._normalizeKey(n.pop()),o="";if(l.forEach(function(e){c.ListWrapper.contains(n,e)&&(c.ListWrapper.remove(n,e),o+=e+".")}),o+=i,0!=n.length||0===i.length)return null;var s=c.StringMapWrapper.create();return c.StringMapWrapper.set(s,"domEventName",r),c.StringMapWrapper.set(s,"fullKey",o),s},t.getEventFullKey=function(e){var t="",n=s.DOM.getEventKey(e);return n=n.toLowerCase(),a.StringWrapper.equals(n," ")?n="space":a.StringWrapper.equals(n,".")&&(n="dot"),l.forEach(function(r){if(r!=n){var i=c.StringMapWrapper.get(h,r);i(e)&&(t+=r+".")}}),t+=n},t.eventCallback=function(e,n,r,i){return function(e){a.StringWrapper.equals(t.getEventFullKey(e),n)&&i.run(function(){return r(e)})}},t._normalizeKey=function(e){switch(e){case"esc":return"escape";default:return e}},t=i([p.Injectable(),o("design:paramtypes",[])],t)}(u.EventManagerPlugin);t.KeyEventsPlugin=f},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=n(186),a=n(5),c=n(14),u=n(6),p=function(e){function t(){e.apply(this,arguments)}return r(t,e),t.prototype.supports=function(t){if(!e.prototype.supports.call(this,t))return!1;if(!a.isPresent(window.Hammer))throw new c.BaseException("Hammer.js is not loaded, can not bind "+t+" event");return!0},t.prototype.addEventListener=function(e,t,n){var r=this.manager.getZone();t=t.toLowerCase(),r.runOutsideAngular(function(){var i=new Hammer(e);i.get("pinch").set({enable:!0}),i.get("rotate").set({enable:!0}),i.on(t,function(e){r.run(function(){n(e)})})})},t=i([u.Injectable(),o("design:paramtypes",[])],t)}(s.HammerGesturesPluginCommon);t.HammerGesturesPlugin=p},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=n(183),o=n(12),s={pan:!0,panstart:!0,panmove:!0,panend:!0,pancancel:!0,panleft:!0,panright:!0,panup:!0,pandown:!0,pinch:!0,pinchstart:!0,pinchmove:!0,pinchend:!0,pinchcancel:!0,pinchin:!0,pinchout:!0,press:!0,pressup:!0,rotate:!0,rotatestart:!0,rotatemove:!0,rotateend:!0,rotatecancel:!0,swipe:!0,swipeleft:!0,swiperight:!0,swipeup:!0,swipedown:!0,tap:!0},a=function(e){function t(){e.call(this)}return r(t,e),t.prototype.supports=function(e){return e=e.toLowerCase(),o.StringMapWrapper.contains(s,e)},t}(i.EventManagerPlugin);t.HammerGesturesPluginCommon=a},function(e,t,n){var r=n(6),i=n(5);t.DOCUMENT=i.CONST_EXPR(new r.OpaqueToken("DocumentToken"))},function(e,t,n){function r(e){return e}function i(e){return e.nodes}function o(e,t){var n=R.DOM.parentElement(e);if(t.length>0&&d.isPresent(n)){var r=R.DOM.nextSibling(e);if(d.isPresent(r))for(var i=0;io?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},p=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},l=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},h=n(6),f=n(189),d=n(5),y=n(14),v=n(196),m=n(45),g=n(2),_=n(183),b=n(187),C=n(164),P=n(165),w=n(3),R=n(178),E=n(194),O=d.CONST_EXPR({xlink:"http://www.w3.org/1999/xlink",svg:"http://www.w3.org/2000/svg"}),S="template bindings={}",D=/^template bindings=(.*)$/g,T=function(e){function t(){e.apply(this,arguments)}return c(t,e),t.prototype.getNativeElementSync=function(e){return r(e.renderView).boundElements[e.boundElementIndex]},t.prototype.getRootNodes=function(e){return i(e)},t.prototype.attachFragmentAfterFragment=function(e,t){var n=i(e);if(n.length>0){var r=n[n.length-1],s=i(t);o(r,s),this.animateNodesEnter(s)}},t.prototype.animateNodesEnter=function(e){for(var t=0;to?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(6),s=n(190),a=n(195),c=function(){function e(e){this.browserDetails=e}return e.prototype.css=function(){return new s.CssAnimationBuilder(this.browserDetails)},e=r([o.Injectable(),i("design:paramtypes",[a.BrowserDetails])],e)}();t.AnimationBuilder=c},function(e,t,n){var r=n(191),i=n(192),o=function(){function e(e){this.browserDetails=e,this.data=new r.CssAnimationOptions}return e.prototype.addAnimationClass=function(e){return this.data.animationClasses.push(e),this},e.prototype.addClass=function(e){return this.data.classesToAdd.push(e),this},e.prototype.removeClass=function(e){return this.data.classesToRemove.push(e),this},e.prototype.setDuration=function(e){return this.data.duration=e,this},e.prototype.setDelay=function(e){return this.data.delay=e,this},e.prototype.setStyles=function(e,t){return this.setFromStyles(e).setToStyles(t)},e.prototype.setFromStyles=function(e){return this.data.fromStyles=e,this},e.prototype.setToStyles=function(e){return this.data.toStyles=e,this},e.prototype.start=function(e){return new i.Animation(e,this.data,this.browserDetails)},e}();t.CssAnimationBuilder=o},function(e,t){var n=function(){function e(){this.classesToAdd=[],this.classesToRemove=[],this.animationClasses=[]}return e}();t.CssAnimationOptions=n},function(e,t,n){var r=n(5),i=n(193),o=n(194),s=n(12),a=n(178),c=function(){function e(e,t,n){var i=this;this.element=e,this.data=t,this.browserDetails=n,this.callbacks=[],this.eventClearFunctions=[],this.completed=!1,this._stringPrefix="",this.startTime=r.DateWrapper.toMillis(r.DateWrapper.now()),this._stringPrefix=a.DOM.getAnimationPrefix(),this.setup(),this.wait(function(e){return i.start()})}return Object.defineProperty(e.prototype,"totalTime",{get:function(){var e=null!=this.computedDelay?this.computedDelay:0,t=null!=this.computedDuration?this.computedDuration:0;return e+t},enumerable:!0,configurable:!0}),e.prototype.wait=function(e){this.browserDetails.raf(e,2)},e.prototype.setup=function(){null!=this.data.fromStyles&&this.applyStyles(this.data.fromStyles),null!=this.data.duration&&this.applyStyles({transitionDuration:this.data.duration.toString()+"ms"}),null!=this.data.delay&&this.applyStyles({transitionDelay:this.data.delay.toString()+"ms"})},e.prototype.start=function(){this.addClasses(this.data.classesToAdd),this.addClasses(this.data.animationClasses),this.removeClasses(this.data.classesToRemove),null!=this.data.toStyles&&this.applyStyles(this.data.toStyles);var e=a.DOM.getComputedStyle(this.element);this.computedDelay=i.Math.max(this.parseDurationString(e.getPropertyValue(this._stringPrefix+"transition-delay")),this.parseDurationString(this.element.style.getPropertyValue(this._stringPrefix+"transition-delay"))),this.computedDuration=i.Math.max(this.parseDurationString(e.getPropertyValue(this._stringPrefix+"transition-duration")),this.parseDurationString(this.element.style.getPropertyValue(this._stringPrefix+"transition-duration"))),this.addEvents()},e.prototype.applyStyles=function(e){var t=this;s.StringMapWrapper.forEach(e,function(e,n){var i=o.camelCaseToDashCase(n);r.isPresent(a.DOM.getStyle(t.element,i))?a.DOM.setStyle(t.element,i,e.toString()):a.DOM.setStyle(t.element,t._stringPrefix+i,e.toString())})},e.prototype.addClasses=function(e){for(var t=0,n=e.length;n>t;t++)a.DOM.addClass(this.element,e[t])},e.prototype.removeClasses=function(e){for(var t=0,n=e.length;n>t;t++)a.DOM.removeClass(this.element,e[t])},e.prototype.addEvents=function(){var e=this;this.totalTime>0?this.eventClearFunctions.push(a.DOM.onAndCancel(this.element,a.DOM.getTransitionEnd(),function(t){return e.handleAnimationEvent(t)})):this.handleAnimationCompleted()},e.prototype.handleAnimationEvent=function(e){var t=i.Math.round(1e3*e.elapsedTime);this.browserDetails.elapsedTimeIncludesDelay||(t+=this.computedDelay),e.stopPropagation(),t>=this.totalTime&&this.handleAnimationCompleted()},e.prototype.handleAnimationCompleted=function(){this.removeClasses(this.data.animationClasses),this.callbacks.forEach(function(e){return e()}),this.callbacks=[],this.eventClearFunctions.forEach(function(e){return e()}),this.eventClearFunctions=[],this.completed=!0},e.prototype.onComplete=function(e){return this.completed?e():this.callbacks.push(e),this},e.prototype.parseDurationString=function(e){var t=0;if(null==e||e.length<2)return t;if("ms"==e.substring(e.length-2)){var n=r.NumberWrapper.parseInt(this.stripLetters(e),10);n>t&&(t=n)}else if("s"==e.substring(e.length-1)){var o=1e3*r.NumberWrapper.parseFloat(this.stripLetters(e)),n=i.Math.floor(o);n>t&&(t=n)}return t},e.prototype.stripLetters=function(e){return r.StringWrapper.replaceAll(e,r.RegExpWrapper.create("[^0-9]+$",""),"")},e}();t.Animation=c},function(e,t,n){var r=n(5);t.Math=r.global.Math,t.NaN=typeof t.NaN},function(e,t,n){function r(e){return o.StringWrapper.replaceAllMapped(e,s,function(e){return"-"+e[1].toLowerCase()})}function i(e){return o.StringWrapper.replaceAllMapped(e,a,function(e){return e[1].toUpperCase()})}var o=n(5),s=/([A-Z])/g,a=/-([a-z])/g;t.camelCaseToDashCase=r,t.dashCaseToCamelCase=i},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(6),s=n(193),a=n(178),c=function(){function e(){this.elapsedTimeIncludesDelay=!1,this.doesElapsedTimeIncludesDelay()}return e.prototype.doesElapsedTimeIncludesDelay=function(){var e=this,t=a.DOM.createElement("div");a.DOM.setAttribute(t,"style","position: absolute; top: -9999px; left: -9999px; width: 1px;\n height: 1px; transition: all 1ms linear 1ms;"),this.raf(function(n){a.DOM.on(t,"transitionend",function(n){var r=s.Math.round(1e3*n.elapsedTime);e.elapsedTimeIncludesDelay=2==r,a.DOM.remove(t)}),a.DOM.setStyle(t,"width","2px")},2)},e.prototype.raf=function(e,t){void 0===t&&(t=1);var n=new u(e,t);return function(){return n.cancel()}},e=r([o.Injectable(),i("design:paramtypes",[])],e)}();t.BrowserDetails=c;var u=function(){function e(e,t){this.callback=e,this.frames=t,this._raf()}return e.prototype._raf=function(){var e=this;this.currentFrameId=a.DOM.requestAnimationFrame(function(t){return e._nextFrame(t)})},e.prototype._nextFrame=function(e){this.frames--,this.frames>0?this._raf():this.callback(e)},e.prototype.cancel=function(){a.DOM.cancelAnimationFrame(this.currentFrameId),this.currentFrameId=null},e}()},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},a=n(178),c=n(6),u=n(12),p=n(187),l=function(){function e(){this._styles=[],this._stylesSet=new Set}return e.prototype.addStyles=function(e){var t=this,n=[];e.forEach(function(e){u.SetWrapper.has(t._stylesSet,e)||(t._stylesSet.add(e),t._styles.push(e),n.push(e))}),this.onStylesAdded(n)},e.prototype.onStylesAdded=function(e){},e.prototype.getAllStyles=function(){return this._styles},e=i([c.Injectable(),o("design:paramtypes",[])],e)}();t.SharedStylesHost=l;var h=function(e){function t(t){e.call(this),this._hostNodes=new Set,this._hostNodes.add(t.head)}return r(t,e),t.prototype._addStylesToHost=function(e,t){for(var n=0;n0},t.prototype.tagName=function(e){return e.tagName},t.prototype.attributeMap=function(e){for(var t=new Map,n=e.attributes,r=0;r=200&&300>=i?t.resolve(r):t.reject("Failed to load "+e,null)},n.onerror=function(){t.reject("Failed to load "+e,null)},n.send(),t.promise},t}(s.XHR);t.XHRImpl=a},function(e,t,n){var r=n(5),i=n(178),o=n(2),s=function(){function e(e){this._testability=e}return e.prototype.isStable=function(){return this._testability.isStable()},e.prototype.whenStable=function(e){this._testability.whenStable(e)},e.prototype.findBindings=function(e,t,n){return this.findProviders(e,t,n)},e.prototype.findProviders=function(e,t,n){return this._testability.findBindings(e,t,n)},e}(),a=function(){function e(){}return e.init=function(){o.setTestabilityGetter(new e)},e.prototype.addToWindow=function(e){r.global.getAngularTestability=function(t,n){void 0===n&&(n=!0);var r=e.findTestabilityInTree(t,n);if(null==r)throw new Error("Could not find testability for element.");return new s(r)},r.global.getAllAngularTestabilities=function(){var t=e.getAllTestabilities();return t.map(function(e){return new s(e)})}},e.prototype.findTestabilityInTree=function(e,t,n){if(null==t)return null;var o=e.getTestability(t);return r.isPresent(o)?o:n?i.DOM.isShadowRoot(t)?this.findTestabilityInTree(e,i.DOM.getHost(t),!0):this.findTestabilityInTree(e,i.DOM.parentElement(t),!0):null},e}();t.BrowserGetTestability=a},function(e,t){function n(){}t.wtfInit=n},function(e,t,n){var r=n(178),i=function(){function e(){}return e.prototype.getTitle=function(){return r.DOM.getTitle()},e.prototype.setTitle=function(e){r.DOM.setTitle(e)},e}();t.Title=i},function(e,t,n){function r(e){for(var n in e)t.hasOwnProperty(n)||(t[n]=e[n])}var i=n(178);t.DOM=i.DOM,t.setRootDomAdapter=i.setRootDomAdapter,t.DomAdapter=i.DomAdapter;var o=n(188);t.DomRenderer=o.DomRenderer;var s=n(187);t.DOCUMENT=s.DOCUMENT;var a=n(196);t.SharedStylesHost=a.SharedStylesHost,t.DomSharedStylesHost=a.DomSharedStylesHost;var c=n(182);t.DomEventsPlugin=c.DomEventsPlugin;var u=n(183);t.EVENT_MANAGER_PLUGINS=u.EVENT_MANAGER_PLUGINS,t.EventManager=u.EventManager,t.EventManagerPlugin=u.EventManagerPlugin,r(n(204)),r(n(205))},function(e,t,n){var r=n(5),i=n(178),o=function(){function e(){}return e.all=function(){return function(e){return!0}},e.css=function(e){return function(t){return r.isPresent(t.nativeElement)?i.DOM.elementMatches(t.nativeElement,e):!1}},e.directive=function(e){return function(t){return t.hasDirective(e)}},e}();t.By=o},function(e,t,n){function r(e,t){c.isPresent(e)&&h.DOM.isElementNode(e)&&h.DOM.setData(e,y,t.join(m))}function i(e){var t=h.DOM.getData(e,y);return c.isPresent(t)?t.split(m).map(function(e){return c.NumberWrapper.parseInt(e,10)}):null}function o(e){var t=i(e);if(c.isPresent(t)){var n=_.get(t[0]);if(c.isPresent(n))return new d.DebugElement_(n,t[1])}return null}var s=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},a=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},c=n(5),u=n(12),p=n(6),l=n(86),h=n(178),f=n(72),d=n(101),y="ngid",v="ng.probe",m="#",g=new u.Map,_=new u.Map,b=0;t.inspectNativeElement=o;var C=function(){function e(e){this._renderer=e,h.DOM.setGlobalVar(v,o)}return e.prototype.onViewCreated=function(e){var t=b++;_.set(t,e),g.set(e,t);for(var n=0;nc||s.DOM.performanceNow()-a<500;)this.appRef.tick(),c++;var u=s.DOM.performanceNow();t&&r&&o.window.console.profileEnd(n);var p=(u-a)/c;o.window.console.log("ran "+c+" change detection cycles"),o.window.console.log(i.NumberWrapper.toFixed(p,2)+" ms per check")},e}();t.AngularProfiler=c},function(e,t){var n=window;t.window=n,t.document=window.document,t.location=window.location,t.gc=window.gc?function(){return window.gc()}:function(){return null},t.performance=window.performance?window.performance:null,t.Event=window.Event,t.MouseEvent=window.MouseEvent,t.KeyboardEvent=window.KeyboardEvent,t.EventTarget=window.EventTarget,t.History=window.History,t.Location=window.Location,t.EventListener=window.EventListener},function(e,t,n){var r=n(2),i=n(210),o=n(218),s=n(222),a=n(221),c=n(223),u=n(216),p=n(220),l=n(212);t.Request=l.Request;var h=n(219);t.Response=h.Response;var f=n(211);t.Connection=f.Connection,t.ConnectionBackend=f.ConnectionBackend;var d=n(221);t.BrowserXhr=d.BrowserXhr;var y=n(216);t.BaseRequestOptions=y.BaseRequestOptions,t.RequestOptions=y.RequestOptions;var v=n(220);t.BaseResponseOptions=v.BaseResponseOptions,t.ResponseOptions=v.ResponseOptions;var m=n(218);t.XHRBackend=m.XHRBackend,t.XHRConnection=m.XHRConnection;var g=n(222);t.JSONPBackend=g.JSONPBackend,t.JSONPConnection=g.JSONPConnection;var _=n(210);t.Http=_.Http,t.Jsonp=_.Jsonp;var b=n(213);t.Headers=b.Headers;var C=n(215);t.ResponseType=C.ResponseType,t.ReadyState=C.ReadyState,t.RequestMethod=C.RequestMethod;var P=n(217);t.URLSearchParams=P.URLSearchParams,t.HTTP_PROVIDERS=[r.provide(i.Http,{useFactory:function(e,t){return new i.Http(e,t)},deps:[o.XHRBackend,u.RequestOptions]}),a.BrowserXhr,r.provide(u.RequestOptions,{useClass:u.BaseRequestOptions}),r.provide(p.ResponseOptions,{useClass:p.BaseResponseOptions}),o.XHRBackend],t.HTTP_BINDINGS=t.HTTP_PROVIDERS,t.JSONP_PROVIDERS=[r.provide(i.Jsonp,{useFactory:function(e,t){return new i.Jsonp(e,t)},deps:[s.JSONPBackend,u.RequestOptions]}),c.BrowserJsonp,r.provide(u.RequestOptions,{useClass:u.BaseRequestOptions}),r.provide(p.ResponseOptions,{useClass:p.BaseResponseOptions}),r.provide(s.JSONPBackend,{useClass:s.JSONPBackend_})],t.JSON_BINDINGS=t.JSONP_PROVIDERS},function(e,t,n){function r(e,t){return e.createConnection(t).response}function i(e,t,n,r){var i=e;return c.isPresent(t)?i.merge(new f.RequestOptions({method:t.method||n,url:t.url||r,search:t.search,headers:t.headers,body:t.body})):c.isPresent(n)?i.merge(new f.RequestOptions({method:n,url:r})):i.merge(new f.RequestOptions({url:r}))}var o=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},s=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},a=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},c=n(5),u=n(14),p=n(2),l=n(211),h=n(212),f=n(216),d=n(215),y=function(){function e(e,t){this._backend=e,this._defaultOptions=t}return e.prototype.request=function(e,t){var n;if(c.isString(e))n=r(this._backend,new h.Request(i(this._defaultOptions,t,d.RequestMethod.Get,e)));else{if(!(e instanceof h.Request))throw u.makeTypeError("First argument must be a url string or Request instance.");n=r(this._backend,e)}return n},e.prototype.get=function(e,t){return r(this._backend,new h.Request(i(this._defaultOptions,t,d.RequestMethod.Get,e)))},e.prototype.post=function(e,t,n){return r(this._backend,new h.Request(i(this._defaultOptions.merge(new f.RequestOptions({body:t})),n,d.RequestMethod.Post,e)))},e.prototype.put=function(e,t,n){return r(this._backend,new h.Request(i(this._defaultOptions.merge(new f.RequestOptions({body:t})),n,d.RequestMethod.Put,e)))},e.prototype["delete"]=function(e,t){return r(this._backend,new h.Request(i(this._defaultOptions,t,d.RequestMethod.Delete,e)))},e.prototype.patch=function(e,t,n){return r(this._backend,new h.Request(i(this._defaultOptions.merge(new f.RequestOptions({body:t})),n,d.RequestMethod.Patch,e)))},e.prototype.head=function(e,t){return r(this._backend,new h.Request(i(this._defaultOptions,t,d.RequestMethod.Head,e)))},e=s([p.Injectable(),a("design:paramtypes",[l.ConnectionBackend,f.RequestOptions])],e)}();t.Http=y;var v=function(e){function t(t,n){e.call(this,t,n)}return o(t,e),t.prototype.request=function(e,t){var n;if(c.isString(e)&&(e=new h.Request(i(this._defaultOptions,t,d.RequestMethod.Get,e))),!(e instanceof h.Request))throw u.makeTypeError("First argument must be a url string or Request instance.");return e.method!==d.RequestMethod.Get&&u.makeTypeError("JSONP requests must use GET request method."),n=r(this._backend,e)},t=s([p.Injectable(),a("design:paramtypes",[l.ConnectionBackend,f.RequestOptions])],t)}(y);t.Jsonp=v},function(e,t){var n=function(){function e(){}return e}();t.ConnectionBackend=n;var r=function(){function e(){}return e}();t.Connection=r},function(e,t,n){var r=n(213),i=n(214),o=n(5),s=function(){function e(e){var t=e.url;if(this.url=e.url,o.isPresent(e.search)){var n=e.search.toString();if(n.length>0){var s="?";o.StringWrapper.contains(this.url,"?")&&(s="&"==this.url[this.url.length-1]?"":"&"),this.url=t+s+n}}this._body=e.body,this.method=i.normalizeMethodName(e.method),this.headers=new r.Headers(e.headers)}return e.prototype.text=function(){return o.isPresent(this._body)?this._body.toString():""},e}();t.Request=s},function(e,t,n){var r=n(5),i=n(14),o=n(12),s=function(){function e(t){var n=this;return t instanceof e?void(this._headersMap=t._headersMap):(this._headersMap=new o.Map,void(r.isBlank(t)||o.StringMapWrapper.forEach(t,function(e,t){n._headersMap.set(t,o.isListLikeIterable(e)?e:[e])})))}return e.fromResponseHeaderString=function(t){return t.trim().split("\n").map(function(e){return e.split(":")}).map(function(e){var t=e[0],n=e.slice(1);return[t.trim(),n.join(":").trim()]}).reduce(function(e,t){var n=t[0],r=t[1];return!e.set(n,r)&&e},new e)},e.prototype.append=function(e,t){var n=this._headersMap.get(e),r=o.isListLikeIterable(n)?n:[];r.push(t),this._headersMap.set(e,r)},e.prototype["delete"]=function(e){this._headersMap["delete"](e)},e.prototype.forEach=function(e){this._headersMap.forEach(e)},e.prototype.get=function(e){return o.ListWrapper.first(this._headersMap.get(e))},e.prototype.has=function(e){return this._headersMap.has(e)},e.prototype.keys=function(){return o.MapWrapper.keys(this._headersMap)},e.prototype.set=function(e,t){var n=[];if(o.isListLikeIterable(t)){var r=t.join(",");n.push(r)}else n.push(t);this._headersMap.set(e,n)},e.prototype.values=function(){return o.MapWrapper.values(this._headersMap)},e.prototype.toJSON=function(){return r.Json.stringify(this.values())},e.prototype.getAll=function(e){var t=this._headersMap.get(e);return o.isListLikeIterable(t)?t:[]},e.prototype.entries=function(){throw new i.BaseException('"entries" method is not implemented on Headers class')},e}();t.Headers=s},function(e,t,n){function r(e){if(o.isString(e)){var t=e;if(e=e.replace(/(\w)(\w*)/g,function(e,t,n){return t.toUpperCase()+n.toLowerCase()}),e=s.RequestMethod[e],"number"!=typeof e)throw a.makeTypeError('Invalid request method. The method "'+t+'" is not supported.')}return e}function i(e){return"responseURL"in e?e.responseURL:/^X-Request-URL:/m.test(e.getAllResponseHeaders())?e.getResponseHeader("X-Request-URL"):void 0}var o=n(5),s=n(215),a=n(14);t.normalizeMethodName=r,t.isSuccess=function(e){return e>=200&&300>e},t.getResponseURL=i;var c=n(5);t.isJsObject=c.isJsObject},function(e,t){!function(e){e[e.Get=0]="Get",e[e.Post=1]="Post",e[e.Put=2]="Put",e[e.Delete=3]="Delete",e[e.Options=4]="Options",e[e.Head=5]="Head",e[e.Patch=6]="Patch"}(t.RequestMethod||(t.RequestMethod={}));t.RequestMethod;!function(e){e[e.Unsent=0]="Unsent",e[e.Open=1]="Open",e[e.HeadersReceived=2]="HeadersReceived",e[e.Loading=3]="Loading",e[e.Done=4]="Done",e[e.Cancelled=5]="Cancelled"}(t.ReadyState||(t.ReadyState={}));t.ReadyState;!function(e){e[e.Basic=0]="Basic",e[e.Cors=1]="Cors",e[e.Default=2]="Default",e[e.Error=3]="Error",e[e.Opaque=4]="Opaque"}(t.ResponseType||(t.ResponseType={}));t.ResponseType},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=n(5),a=n(213),c=n(215),u=n(2),p=n(217),l=n(214),h=function(){function e(e){var t=void 0===e?{}:e,n=t.method,r=t.headers,i=t.body,o=t.url,a=t.search;this.method=s.isPresent(n)?l.normalizeMethodName(n):null,this.headers=s.isPresent(r)?r:null,this.body=s.isPresent(i)?i:null,this.url=s.isPresent(o)?o:null,this.search=s.isPresent(a)?s.isString(a)?new p.URLSearchParams(a):a:null}return e.prototype.merge=function(t){return new e({method:s.isPresent(t)&&s.isPresent(t.method)?t.method:this.method,headers:s.isPresent(t)&&s.isPresent(t.headers)?t.headers:this.headers,body:s.isPresent(t)&&s.isPresent(t.body)?t.body:this.body,url:s.isPresent(t)&&s.isPresent(t.url)?t.url:this.url,search:s.isPresent(t)&&s.isPresent(t.search)?s.isString(t.search)?new p.URLSearchParams(t.search):t.search.clone():this.search})},e}();t.RequestOptions=h;var f=function(e){function t(){e.call(this,{method:c.RequestMethod.Get,headers:new a.Headers})}return r(t,e),t=i([u.Injectable(),o("design:paramtypes",[])],t)}(h);t.BaseRequestOptions=f},function(e,t,n){function r(e){void 0===e&&(e="");var t=new o.Map;if(e.length>0){var n=e.split("&");n.forEach(function(e){var n=e.split("="),r=n[0],o=n[1],s=i.isPresent(t.get(r))?t.get(r):[];s.push(o),t.set(r,s)})}return t}var i=n(5),o=n(12),s=function(){function e(e){void 0===e&&(e=""),this.rawParams=e,this.paramsMap=r(e)}return e.prototype.clone=function(){var t=new e;return t.appendAll(this),t},e.prototype.has=function(e){return this.paramsMap.has(e)},e.prototype.get=function(e){var t=this.paramsMap.get(e);return o.isListLikeIterable(t)?o.ListWrapper.first(t):null},e.prototype.getAll=function(e){var t=this.paramsMap.get(e);return i.isPresent(t)?t:[]},e.prototype.set=function(e,t){var n=this.paramsMap.get(e),r=i.isPresent(n)?n:[];o.ListWrapper.clear(r),r.push(t),this.paramsMap.set(e,r)},e.prototype.setAll=function(e){var t=this;e.paramsMap.forEach(function(e,n){var r=t.paramsMap.get(n),s=i.isPresent(r)?r:[];o.ListWrapper.clear(s),s.push(e[0]),t.paramsMap.set(n,s)})},e.prototype.append=function(e,t){var n=this.paramsMap.get(e),r=i.isPresent(n)?n:[];r.push(t),this.paramsMap.set(e,r)},e.prototype.appendAll=function(e){var t=this;e.paramsMap.forEach(function(e,n){for(var r=t.paramsMap.get(n),o=i.isPresent(r)?r:[],s=0;so?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(215),s=n(219),a=n(213),c=n(220),u=n(2),p=n(221),l=n(5),h=n(62),f=n(214),d=function(){function e(e,t,n){var r=this;this.request=e,this.response=new h.Observable(function(i){var u=t.build();u.open(o.RequestMethod[e.method].toUpperCase(),e.url);var p=function(){var e=l.isPresent(u.response)?u.response:u.responseText,t=a.Headers.fromResponseHeaderString(u.getAllResponseHeaders()),r=f.getResponseURL(u),o=1223===u.status?204:u.status;0===o&&(o=e?200:0);var p=new c.ResponseOptions({body:e,status:o,headers:t,url:r});l.isPresent(n)&&(p=n.merge(p));var h=new s.Response(p);return f.isSuccess(o)?(i.next(h),void i.complete()):void i.error(h)},h=function(e){var t=new c.ResponseOptions({body:e,type:o.ResponseType.Error});l.isPresent(n)&&(t=n.merge(t)),i.error(new s.Response(t))};return l.isPresent(e.headers)&&e.headers.forEach(function(e,t){return u.setRequestHeader(t,e.join(","))}),u.addEventListener("load",p),u.addEventListener("error",h),u.send(r.request.text()),function(){u.removeEventListener("load",p),u.removeEventListener("error",h),u.abort()}})}return e}();t.XHRConnection=d;var y=function(){function e(e,t){this._browserXHR=e,this._baseResponseOptions=t}return e.prototype.createConnection=function(e){return new d(e,this._browserXHR,this._baseResponseOptions)},e=r([u.Injectable(),i("design:paramtypes",[p.BrowserXhr,c.ResponseOptions])],e)}();t.XHRBackend=y},function(e,t,n){var r=n(5),i=n(14),o=n(214),s=function(){function e(e){this._body=e.body,this.status=e.status,this.statusText=e.statusText,this.headers=e.headers,this.type=e.type,this.url=e.url}return e.prototype.blob=function(){throw new i.BaseException('"blob()" method not implemented on Response superclass')},e.prototype.json=function(){var e;return o.isJsObject(this._body)?e=this._body:r.isString(this._body)&&(e=r.Json.parse(this._body)),e},e.prototype.text=function(){return this._body.toString()},e.prototype.arrayBuffer=function(){throw new i.BaseException('"arrayBuffer()" method not implemented on Response superclass')},e}();t.Response=s},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=n(2),a=n(5),c=n(213),u=n(215),p=function(){function e(e){var t=void 0===e?{}:e,n=t.body,r=t.status,i=t.headers,o=t.statusText,s=t.type,c=t.url;this.body=a.isPresent(n)?n:null,this.status=a.isPresent(r)?r:null,this.headers=a.isPresent(i)?i:null,this.statusText=a.isPresent(o)?o:null,this.type=a.isPresent(s)?s:null,this.url=a.isPresent(c)?c:null}return e.prototype.merge=function(t){return new e({body:a.isPresent(t)&&a.isPresent(t.body)?t.body:this.body,status:a.isPresent(t)&&a.isPresent(t.status)?t.status:this.status,headers:a.isPresent(t)&&a.isPresent(t.headers)?t.headers:this.headers,statusText:a.isPresent(t)&&a.isPresent(t.statusText)?t.statusText:this.statusText,type:a.isPresent(t)&&a.isPresent(t.type)?t.type:this.type,url:a.isPresent(t)&&a.isPresent(t.url)?t.url:this.url})},e}();t.ResponseOptions=p;var l=function(e){function t(){e.call(this,{status:200,statusText:"Ok",type:u.ResponseType.Default,headers:new c.Headers})}return r(t,e),t=i([s.Injectable(),o("design:paramtypes",[])],t)}(p);t.BaseResponseOptions=l},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(2),s=function(){function e(){}return e.prototype.build=function(){return new XMLHttpRequest},e=r([o.Injectable(),i("design:paramtypes",[])],e)}();t.BrowserXhr=s},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=n(211),a=n(215),c=n(219),u=n(220),p=n(2),l=n(223),h=n(14),f=n(5),d=n(62),y="JSONP injected script did not invoke callback.",v="JSONP requests must use GET request method.",m=function(){function e(){}return e}();t.JSONPConnection=m;var g=function(e){function t(t,n,r){var i=this;if(e.call(this),this._dom=n,this.baseResponseOptions=r,this._finished=!1,t.method!==a.RequestMethod.Get)throw h.makeTypeError(v);this.request=t,this.response=new d.Observable(function(e){i.readyState=a.ReadyState.Loading;var o=i._id=n.nextRequestID();n.exposeConnection(o,i);var s=n.requestCallback(i._id),p=t.url;p.indexOf("=JSONP_CALLBACK&")>-1?p=f.StringWrapper.replace(p,"=JSONP_CALLBACK&","="+s+"&"):p.lastIndexOf("=JSONP_CALLBACK")===p.length-"=JSONP_CALLBACK".length&&(p=p.substring(0,p.length-"=JSONP_CALLBACK".length)+("="+s));var l=i._script=n.build(p),h=function(t){if(i.readyState!==a.ReadyState.Cancelled){if(i.readyState=a.ReadyState.Done,n.cleanup(l),!i._finished){var o=new u.ResponseOptions({body:y,type:a.ResponseType.Error,url:p});return f.isPresent(r)&&(o=r.merge(o)),void e.error(new c.Response(o))}var s=new u.ResponseOptions({body:i._responseData,url:p});f.isPresent(i.baseResponseOptions)&&(s=i.baseResponseOptions.merge(s)),e.next(new c.Response(s)),e.complete()}},d=function(t){if(i.readyState!==a.ReadyState.Cancelled){i.readyState=a.ReadyState.Done,n.cleanup(l);var o=new u.ResponseOptions({body:t.message,type:a.ResponseType.Error});f.isPresent(r)&&(o=r.merge(o)),e.error(new c.Response(o))}};return l.addEventListener("load",h),l.addEventListener("error",d),n.send(l),function(){i.readyState=a.ReadyState.Cancelled,l.removeEventListener("load",h),l.removeEventListener("error",d),f.isPresent(l)&&i._dom.cleanup(l)}})}return r(t,e),t.prototype.finished=function(e){this._finished=!0,this._dom.removeConnection(this._id),this.readyState!==a.ReadyState.Cancelled&&(this._responseData=e)},t}(m);t.JSONPConnection_=g;var _=function(e){function t(){e.apply(this,arguments)}return r(t,e),t}(s.ConnectionBackend);t.JSONPBackend=_;var b=function(e){function t(t,n){e.call(this),this._browserJSONP=t,this._baseResponseOptions=n}return r(t,e),t.prototype.createConnection=function(e){return new g(e,this._browserJSONP,this._baseResponseOptions)},t=i([p.Injectable(),o("design:paramtypes",[l.BrowserJsonp,u.ResponseOptions])],t)}(_);t.JSONPBackend_=b},function(e,t,n){function r(){return null===u&&(u=a.global[t.JSONP_HOME]={}),u}var i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=n(2),a=n(5),c=0;t.JSONP_HOME="__ng_jsonp__";var u=null,p=function(){function e(){}return e.prototype.build=function(e){var t=document.createElement("script");return t.src=e,t},e.prototype.nextRequestID=function(){return"__req"+c++},e.prototype.requestCallback=function(e){return t.JSONP_HOME+"."+e+".finished"},e.prototype.exposeConnection=function(e,t){var n=r();n[e]=t},e.prototype.removeConnection=function(e){var t=r();t[e]=null},e.prototype.send=function(e){document.body.appendChild(e)},e.prototype.cleanup=function(e){e.parentNode&&e.parentNode.removeChild(e)},e=i([s.Injectable(),o("design:paramtypes",[])],e)}();t.BrowserJsonp=p},function(e,t,n){function r(e){for(var n in e)t.hasOwnProperty(n)||(t[n]=e[n])}function i(e,t,n,r){var i=new P.RootRouter(e,t,n);return r.registerDisposeListener(function(){return i.dispose()}),i}function o(e){if(0==e.componentTypes.length)throw new T.BaseException("Bootstrap at least one component before injecting Router.");return e.componentTypes[0]}var s=n(225);t.Router=s.Router;var a=n(241);t.RouterOutlet=a.RouterOutlet;var c=n(243);t.RouterLink=c.RouterLink;var u=n(229);t.RouteParams=u.RouteParams,t.RouteData=u.RouteData;var p=n(244);t.PlatformLocation=p.PlatformLocation;var l=n(226);t.RouteRegistry=l.RouteRegistry,t.ROUTER_PRIMARY_COMPONENT=l.ROUTER_PRIMARY_COMPONENT;var h=n(238);t.LocationStrategy=h.LocationStrategy,t.APP_BASE_HREF=h.APP_BASE_HREF;var f=n(245);t.HashLocationStrategy=f.HashLocationStrategy;var d=n(246);t.PathLocationStrategy=d.PathLocationStrategy;var y=n(237);t.Location=y.Location,r(n(236)),r(n(247));var v=n(242);t.CanActivate=v.CanActivate;var m=n(229);t.Instruction=m.Instruction,t.ComponentInstruction=m.ComponentInstruction;var g=n(2);t.OpaqueToken=g.OpaqueToken;var _=n(244),b=n(238),C=n(246),P=n(225),w=n(241),R=n(243),E=n(226),O=n(237),S=n(2),D=n(5),T=n(14);t.ROUTER_DIRECTIVES=D.CONST_EXPR([w.RouterOutlet,R.RouterLink]),t.ROUTER_PROVIDERS=D.CONST_EXPR([E.RouteRegistry,D.CONST_EXPR(new S.Provider(b.LocationStrategy,{useClass:C.PathLocationStrategy})),_.PlatformLocation,O.Location,D.CONST_EXPR(new S.Provider(P.Router,{useFactory:i,deps:D.CONST_EXPR([E.RouteRegistry,O.Location,E.ROUTER_PRIMARY_COMPONENT,S.ApplicationRef])})),D.CONST_EXPR(new S.Provider(E.ROUTER_PRIMARY_COMPONENT,{useFactory:o,deps:D.CONST_EXPR([S.ApplicationRef])}))]),t.ROUTER_BINDINGS=t.ROUTER_PROVIDERS},function(e,t,n){function r(e,t){var n=v;return p.isPresent(e.child)&&(n=r(e.child,p.isPresent(t)?t.child:null)),n.then(function(n){if(0==n)return!1;if(e.component.reuse)return!0;var r=y.getCanActivateHook(e.component.componentType);return p.isPresent(r)?r(e.component,p.isPresent(t)?t.component:null):!0})}var i=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},o=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},s=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},a=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},c=n(60),u=n(12),p=n(5),l=n(14),h=n(2),f=n(226),d=n(237),y=n(239),v=c.PromiseWrapper.resolve(!0),m=c.PromiseWrapper.resolve(!1),g=function(){function e(e,t,n){this.registry=e,this.parent=t,this.hostComponent=n,this.navigating=!1,this._currentInstruction=null,this._currentNavigation=v,this._outlet=null,this._auxRouters=new u.Map,this._subject=new c.EventEmitter}return e.prototype.childRouter=function(e){return this._childRouter=new b(this,e)},e.prototype.auxRouter=function(e){return new b(this,e)},e.prototype.registerPrimaryOutlet=function(e){if(p.isPresent(e.name))throw new l.BaseException("registerPrimaryOutlet expects to be called with an unnamed outlet.");return this._outlet=e,p.isPresent(this._currentInstruction)?this.commit(this._currentInstruction,!1):v},e.prototype.registerAuxOutlet=function(e){var t=e.name;if(p.isBlank(t))throw new l.BaseException("registerAuxOutlet expects to be called with an outlet with a name.");var n=this.auxRouter(this.hostComponent);this._auxRouters.set(t,n),n._outlet=e;var r;return p.isPresent(this._currentInstruction)&&p.isPresent(r=this._currentInstruction.auxInstruction[t])?n.commit(r):v},e.prototype.isRouteActive=function(e){for(var t=this;p.isPresent(t.parent)&&p.isPresent(e.child);)t=t.parent,e=e.child;return p.isPresent(this._currentInstruction)&&this._currentInstruction.component==e.component},e.prototype.config=function(e){var t=this;return e.forEach(function(e){t.registry.config(t.hostComponent,e)}),this.renavigate()},e.prototype.navigate=function(e){var t=this.generate(e);return this.navigateByInstruction(t,!1)},e.prototype.navigateByUrl=function(e,t){var n=this;return void 0===t&&(t=!1),this._currentNavigation=this._currentNavigation.then(function(r){return n.lastNavigationAttempt=e,n._startNavigating(),n._afterPromiseFinishNavigating(n.recognize(e).then(function(e){return p.isBlank(e)?!1:n._navigate(e,t)}))})},e.prototype.navigateByInstruction=function(e,t){var n=this;return void 0===t&&(t=!1),p.isBlank(e)?m:this._currentNavigation=this._currentNavigation.then(function(r){return n._startNavigating(),n._afterPromiseFinishNavigating(n._navigate(e,t))})},e.prototype._navigate=function(e,t){var n=this;return this._settleInstruction(e).then(function(t){return n._routerCanReuse(e)}).then(function(t){return n._canActivate(e)}).then(function(r){return r?n._routerCanDeactivate(e).then(function(r){return r?n.commit(e,t).then(function(t){return n._emitNavigationFinish(e.toRootUrl()),!0}):void 0}):!1})},e.prototype._settleInstruction=function(e){var t=this;return e.resolveComponent().then(function(n){e.component.reuse=!1;var r=[];return p.isPresent(e.child)&&r.push(t._settleInstruction(e.child)),u.StringMapWrapper.forEach(e.auxInstruction,function(e,n){r.push(t._settleInstruction(e))}), -c.PromiseWrapper.all(r)})},e.prototype._emitNavigationFinish=function(e){c.ObservableWrapper.callEmit(this._subject,e)},e.prototype._afterPromiseFinishNavigating=function(e){var t=this;return c.PromiseWrapper.catchError(e.then(function(e){return t._finishNavigating()}),function(e){throw t._finishNavigating(),e})},e.prototype._routerCanReuse=function(e){var t=this;return p.isBlank(this._outlet)?m:this._outlet.routerCanReuse(e.component).then(function(n){return e.component.reuse=n,n&&p.isPresent(t._childRouter)&&p.isPresent(e.child)?t._childRouter._routerCanReuse(e.child):void 0})},e.prototype._canActivate=function(e){return r(e,this._currentInstruction)},e.prototype._routerCanDeactivate=function(e){var t=this;if(p.isBlank(this._outlet))return v;var n,r=null,i=!1,o=null;return p.isPresent(e)&&(r=e.child,o=e.component,i=e.component.reuse),n=i?v:this._outlet.routerCanDeactivate(o),n.then(function(e){return 0==e?!1:p.isPresent(t._childRouter)?t._childRouter._routerCanDeactivate(r):!0})},e.prototype.commit=function(e,t){var n=this;void 0===t&&(t=!1),this._currentInstruction=e;var r=v;if(p.isPresent(this._outlet)){var i=e.component;r=i.reuse?this._outlet.reuse(i):this.deactivate(e).then(function(e){return n._outlet.activate(i)}),p.isPresent(e.child)&&(r=r.then(function(t){return p.isPresent(n._childRouter)?n._childRouter.commit(e.child):void 0}))}var o=[];return this._auxRouters.forEach(function(t,n){p.isPresent(e.auxInstruction[n])&&o.push(t.commit(e.auxInstruction[n]))}),r.then(function(e){return c.PromiseWrapper.all(o)})},e.prototype._startNavigating=function(){this.navigating=!0},e.prototype._finishNavigating=function(){this.navigating=!1},e.prototype.subscribe=function(e){return c.ObservableWrapper.subscribe(this._subject,e)},e.prototype.deactivate=function(e){var t=this,n=null,r=null;p.isPresent(e)&&(n=e.child,r=e.component);var i=v;return p.isPresent(this._childRouter)&&(i=this._childRouter.deactivate(n)),p.isPresent(this._outlet)&&(i=i.then(function(e){return t._outlet.deactivate(r)})),i},e.prototype.recognize=function(e){var t=this._getAncestorInstructions();return this.registry.recognize(e,t)},e.prototype._getAncestorInstructions=function(){for(var e=[],t=this;p.isPresent(t.parent)&&p.isPresent(t.parent._currentInstruction);)t=t.parent,e.unshift(t._currentInstruction);return e},e.prototype.renavigate=function(){return p.isBlank(this.lastNavigationAttempt)?this._currentNavigation:this.navigateByUrl(this.lastNavigationAttempt)},e.prototype.generate=function(e){var t=this._getAncestorInstructions();return this.registry.generate(e,t)},e}();t.Router=g;var _=function(e){function t(t,n,r){var i=this;e.call(this,t,null,r),this._location=n,this._locationSub=this._location.subscribe(function(e){i.recognize(e.url).then(function(t){i.navigateByInstruction(t,p.isPresent(e.pop)).then(function(n){if(!p.isPresent(e.pop)||"hashchange"==e.type){var r=t.toUrlPath(),o=t.toUrlQuery();r.length>0&&(r="/"+r),"hashchange"==e.type?t.toRootUrl()!=i._location.path()&&i._location.replaceState(r,o):i._location.go(r,o)}})})}),this.registry.configFromComponent(r),this.navigateByUrl(n.path())}return i(t,e),t.prototype.commit=function(t,n){var r=this;void 0===n&&(n=!1);var i=t.toUrlPath(),o=t.toUrlQuery();i.length>0&&(i="/"+i);var s=e.prototype.commit.call(this,t);return n||(s=s.then(function(e){r._location.go(i,o)})),s},t.prototype.dispose=function(){p.isPresent(this._locationSub)&&(c.ObservableWrapper.dispose(this._locationSub),this._locationSub=null)},t=o([h.Injectable(),a(2,h.Inject(f.ROUTER_PRIMARY_COMPONENT)),s("design:paramtypes",[f.RouteRegistry,d.Location,p.Type])],t)}(g);t.RootRouter=_;var b=function(e){function t(t,n){e.call(this,t.registry,t,n),this.parent=t}return i(t,e),t.prototype.navigateByUrl=function(e,t){return void 0===t&&(t=!1),this.parent.navigateByUrl(e,t)},t.prototype.navigateByInstruction=function(e,t){return void 0===t&&(t=!1),this.parent.navigateByInstruction(e,t)},t}(g)},function(e,t,n){function r(e){return e.reduce(function(e,t){if(l.isString(t)){var n=t;return e.concat(n.split("/"))}return e.push(t),e},[])}function i(e){return u.ListWrapper.maximum(e,function(e){return e.specificity})}function o(e,t){if(l.isType(e)){var n=f.reflector.annotations(e);if(l.isPresent(n))for(var r=0;ro?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},a=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},c=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},u=n(12),p=n(60),l=n(5),h=n(14),f=n(16),d=n(2),y=n(227),v=n(228),m=n(232),g=n(229),_=n(235),b=n(231),C=p.PromiseWrapper.resolve(null);t.ROUTER_PRIMARY_COMPONENT=l.CONST_EXPR(new d.OpaqueToken("RouterPrimaryComponent"));var P=function(){function e(e){this._rootComponent=e,this._rules=new u.Map}return e.prototype.config=function(e,t){t=_.normalizeRouteConfig(t,this),t instanceof y.Route?_.assertComponentExists(t.component,t.path):t instanceof y.AuxRoute&&_.assertComponentExists(t.component,t.path);var n=this._rules.get(e);l.isBlank(n)&&(n=new m.ComponentRecognizer,this._rules.set(e,n));var r=n.config(t);t instanceof y.Route&&(r?o(t.component,t.path):this.configFromComponent(t.component))},e.prototype.configFromComponent=function(e){var t=this;if(l.isType(e)&&!this._rules.has(e)){var n=f.reflector.annotations(e);if(l.isPresent(n))for(var r=0;r0?t[t.length-1].component.componentType:this._rootComponent,s=this._rules.get(o);if(l.isBlank(s))return C;var a=n?s.recognizeAuxiliary(e):s.recognize(e),c=a.map(function(e){return e.then(function(e){if(e instanceof v.PathMatch){var n=t.length>0?[t[t.length-1]]:[],i=r._auxRoutesToUnresolved(e.remainingAux,n),o=new g.ResolvedInstruction(e.instruction,null,i);if(e.instruction.terminal)return o;var s=t.concat([o]);return r._recognize(e.remaining,s).then(function(e){return l.isBlank(e)?null:e instanceof g.RedirectInstruction?e:(o.child=e,o)})}if(e instanceof v.RedirectMatch){var o=r.generate(e.redirectTo,t);return new g.RedirectInstruction(o.component,o.child,o.auxInstruction)}})});return!l.isBlank(e)&&""!=e.path||0!=a.length?p.PromiseWrapper.all(c).then(i):p.PromiseWrapper.resolve(this.generateDefault(o))},e.prototype._auxRoutesToUnresolved=function(e,t){var n=this,r={};return e.forEach(function(e){r[e.path]=new g.UnresolvedInstruction(function(){return n._recognize(e,t,!0)})}),r},e.prototype.generate=function(e,t,n){void 0===n&&(n=!1);var i=r(e),o=u.ListWrapper.first(i),s=u.ListWrapper.slice(i,1);if(""==o)t=[];else if(".."==o){for(t.pop();".."==u.ListWrapper.first(s);)if(s=u.ListWrapper.slice(s,1),t.pop(),t.length<=0)throw new h.BaseException('Link "'+u.ListWrapper.toJSON(e)+'" has too many "../" segments.')}else if("."!=o){var a=this._rootComponent,c=null;t.length>1?(a=t[t.length-1].component.componentType,c=t[t.length-2].component.componentType):1==t.length&&(a=t[0].component.componentType,c=this._rootComponent);var p=this.hasRoute(o,a),f=l.isPresent(c)&&this.hasRoute(o,c);if(f&&p){var d='Link "'+u.ListWrapper.toJSON(e)+'" is ambiguous, use "./" or "../" to disambiguate.';throw new h.BaseException(d)}f&&t.pop(),s=e}if(""==s[s.length-1]&&s.pop(),s.length<1){var d='Link "'+u.ListWrapper.toJSON(e)+'" must include a route name.';throw new h.BaseException(d)}for(var y=this._generate(s,t,n),v=t.length-1;v>=0;v--){var m=t[v];y=m.replaceChild(y)}return y},e.prototype._generate=function(e,t,n){var r=this;void 0===n&&(n=!1);var i=t.length>0?t[t.length-1].component.componentType:this._rootComponent;if(0==e.length)return this.generateDefault(i);var o=0,s=e[o];if(!l.isString(s))throw new h.BaseException('Unexpected segment "'+s+'" in link DSL. Expected a string.');if(""==s||"."==s||".."==s)throw new h.BaseException('"'+s+'/" is only allowed at the beginning of a link DSL.');var a={};if(o+10?[t[t.length-1]]:[],y=this._generate(p,d,!0);f[y.component.urlPath]=y,o+=1}var v=this._rules.get(i);if(l.isBlank(v))throw new h.BaseException('Component "'+l.getTypeNameForDebugging(i)+'" has no route config.');var m=(n?v.auxNames:v.names).get(s);if(!l.isPresent(m))throw new h.BaseException('Component "'+l.getTypeNameForDebugging(i)+'" has no route named "'+s+'".');if(!l.isPresent(m.handler.componentType)){var _=m.generateComponentPathValues(a);return new g.UnresolvedInstruction(function(){return m.handler.resolveComponentType().then(function(i){return r._generate(e,t,n)})},_.urlPath,_.urlParams)}var b=n?v.generateAuxiliary(s,a):v.generate(s,a),C=e.slice(o+1),P=new g.ResolvedInstruction(b,null,f);if(l.isPresent(b.componentType)){var w=null;if(o+1o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(5),s=function(){function e(e){this.configs=e}return e=r([o.CONST(),i("design:paramtypes",[Array])],e)}();t.RouteConfig=s;var a=function(){function e(e){var t=e.path,n=e.component,r=e.name,i=e.data,o=e.useAsDefault;this.aux=null,this.loader=null,this.redirectTo=null,this.path=t,this.component=n,this.name=r,this.data=i,this.useAsDefault=o}return e=r([o.CONST(),i("design:paramtypes",[Object])],e)}();t.Route=a;var c=function(){function e(e){var t=e.path,n=e.component,r=e.name;this.data=null,this.aux=null,this.loader=null,this.redirectTo=null,this.useAsDefault=!1,this.path=t,this.component=n,this.name=r}return e=r([o.CONST(),i("design:paramtypes",[Object])],e)}();t.AuxRoute=c;var u=function(){function e(e){var t=e.path,n=e.loader,r=e.name,i=e.data,o=e.useAsDefault;this.aux=null,this.path=t,this.loader=n,this.name=r,this.data=i,this.useAsDefault=o}return e=r([o.CONST(),i("design:paramtypes",[Object])],e)}();t.AsyncRoute=u;var p=function(){function e(e){var t=e.path,n=e.redirectTo;this.name=null,this.loader=null,this.data=null,this.aux=null,this.useAsDefault=!1,this.path=t,this.redirectTo=n}return e=r([o.CONST(),i("design:paramtypes",[Object])],e)}();t.Redirect=p},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=n(5),o=n(14),s=n(61),a=n(12),c=n(229),u=n(230),p=function(){function e(){}return e}();t.RouteMatch=p;var l=function(e){function t(t,n,r){e.call(this),this.instruction=t,this.remaining=n,this.remainingAux=r}return r(t,e),t}(p);t.PathMatch=l;var h=function(e){function t(t,n){e.call(this),this.redirectTo=t,this.specificity=n}return r(t,e),t}(p);t.RedirectMatch=h;var f=function(){function e(e,t){this.path=e,this.redirectTo=t,this._pathRecognizer=new u.PathRecognizer(e),this.hash=this._pathRecognizer.hash}return e.prototype.recognize=function(e){var t=null;return i.isPresent(this._pathRecognizer.recognize(e))&&(t=new h(this.redirectTo,this._pathRecognizer.specificity)),s.PromiseWrapper.resolve(t)},e.prototype.generate=function(e){throw new o.BaseException("Tried to generate a redirect.")},e}();t.RedirectRecognizer=f;var d=function(){function e(e,t){this.path=e,this.handler=t,this.terminal=!0,this._cache=new a.Map,this._pathRecognizer=new u.PathRecognizer(e),this.specificity=this._pathRecognizer.specificity,this.hash=this._pathRecognizer.hash,this.terminal=this._pathRecognizer.terminal}return e.prototype.recognize=function(e){var t=this,n=this._pathRecognizer.recognize(e);return i.isBlank(n)?null:this.handler.resolveComponentType().then(function(e){var r=t._getInstruction(n.urlPath,n.urlParams,n.allParams);return new l(r,n.nextSegment,n.auxiliary)})},e.prototype.generate=function(e){var t=this._pathRecognizer.generate(e),n=t.urlPath,r=t.urlParams;return this._getInstruction(n,r,e)},e.prototype.generateComponentPathValues=function(e){return this._pathRecognizer.generate(e)},e.prototype._getInstruction=function(e,t,n){if(i.isBlank(this.handler.componentType))throw new o.BaseException("Tried to get instruction before the type was loaded.");var r=e+"?"+t.join("?");if(this._cache.has(r))return this._cache.get(r);var s=new c.ComponentInstruction(e,t,this.handler.data,this.handler.componentType,this.terminal,this.specificity,n);return this._cache.set(r,s),s},e}();t.RouteRecognizer=d},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=n(12),o=n(5),s=n(60),a=function(){function e(e){this.params=e}return e.prototype.get=function(e){return o.normalizeBlank(i.StringMapWrapper.get(this.params,e))},e}();t.RouteParams=a;var c=function(){function e(e){void 0===e&&(e=o.CONST_EXPR({})),this.data=e}return e.prototype.get=function(e){return o.normalizeBlank(i.StringMapWrapper.get(this.data,e))},e}();t.RouteData=c,t.BLANK_ROUTE_DATA=new c;var u=function(){function e(){this.auxInstruction={}}return Object.defineProperty(e.prototype,"urlPath",{get:function(){return this.component.urlPath},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"urlParams",{get:function(){return this.component.urlParams},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"specificity",{get:function(){var e=0;return o.isPresent(this.component)&&(e+=this.component.specificity),o.isPresent(this.child)&&(e+=this.child.specificity),e},enumerable:!0,configurable:!0}),e.prototype.toRootUrl=function(){return this.toUrlPath()+this.toUrlQuery()},e.prototype._toNonRootUrl=function(){return this._stringifyPathMatrixAuxPrefixed()+(o.isPresent(this.child)?this.child._toNonRootUrl():"")},e.prototype.toUrlQuery=function(){return this.urlParams.length>0?"?"+this.urlParams.join("&"):""},e.prototype.replaceChild=function(e){return new p(this.component,e,this.auxInstruction)},e.prototype.toUrlPath=function(){return this.urlPath+this._stringifyAux()+(o.isPresent(this.child)?this.child._toNonRootUrl():"")},e.prototype.toLinkUrl=function(){return this.urlPath+this._stringifyAux()+(o.isPresent(this.child)?this.child._toLinkUrl():"")},e.prototype._toLinkUrl=function(){return this._stringifyPathMatrixAuxPrefixed()+(o.isPresent(this.child)?this.child._toLinkUrl():"")},e.prototype._stringifyPathMatrixAuxPrefixed=function(){var e=this._stringifyPathMatrixAux();return e.length>0&&(e="/"+e),e},e.prototype._stringifyMatrixParams=function(){return this.urlParams.length>0?";"+this.component.urlParams.join(";"):""},e.prototype._stringifyPathMatrixAux=function(){return o.isBlank(this.component)?"":this.urlPath+this._stringifyMatrixParams()+this._stringifyAux()},e.prototype._stringifyAux=function(){var e=[];return i.StringMapWrapper.forEach(this.auxInstruction,function(t,n){e.push(t._stringifyPathMatrixAux())}),e.length>0?"("+e.join("//")+")":""},e}();t.Instruction=u;var p=function(e){function t(t,n,r){e.call(this),this.component=t,this.child=n,this.auxInstruction=r}return r(t,e),t.prototype.resolveComponent=function(){return s.PromiseWrapper.resolve(this.component)},t}(u);t.ResolvedInstruction=p;var l=function(e){function t(t,n){e.call(this),this.component=t,this.child=n}return r(t,e),t.prototype.resolveComponent=function(){return s.PromiseWrapper.resolve(this.component)},t.prototype.toLinkUrl=function(){return""},t.prototype._toLinkUrl=function(){return""},t}(u);t.DefaultInstruction=l;var h=function(e){function t(t,n,r){void 0===n&&(n=""),void 0===r&&(r=o.CONST_EXPR([])),e.call(this),this._resolver=t,this._urlPath=n,this._urlParams=r}return r(t,e),Object.defineProperty(t.prototype,"urlPath",{get:function(){return o.isPresent(this.component)?this.component.urlPath:o.isPresent(this._urlPath)?this._urlPath:""},enumerable:!0,configurable:!0}),Object.defineProperty(t.prototype,"urlParams",{get:function(){return o.isPresent(this.component)?this.component.urlParams:o.isPresent(this._urlParams)?this._urlParams:[]},enumerable:!0,configurable:!0}),t.prototype.resolveComponent=function(){var e=this;return o.isPresent(this.component)?s.PromiseWrapper.resolve(this.component):this._resolver().then(function(t){return e.child=t.child,e.component=t.component})},t}(u);t.UnresolvedInstruction=h;var f=function(e){function t(t,n,r){e.call(this,t,n,r)}return r(t,e),t}(p);t.RedirectInstruction=f;var d=function(){function e(e,n,r,i,s,a,c){void 0===c&&(c=null),this.urlPath=e,this.urlParams=n,this.componentType=i,this.terminal=s,this.specificity=a,this.params=c,this.reuse=!1,this.routeData=o.isPresent(r)?r:t.BLANK_ROUTE_DATA}return e}();t.ComponentInstruction=d},function(e,t,n){function r(e){return c.isBlank(e)?null:e.toString()}function i(e){e.startsWith("/")&&(e=e.substring(1));var t=s(e),n=[],r=0;if(t.length>98)throw new u.BaseException("'"+e+"' has more than the maximum supported number of segments.");for(var i=t.length-1,o=0;i>=o;o++){var a,l=t[o];if(c.isPresent(a=c.RegExpWrapper.firstMatch(m,l)))n.push(new y(a[1])),r+=100-o;else if(c.isPresent(a=c.RegExpWrapper.firstMatch(g,l)))n.push(new v(a[1]));else if("..."==l){if(i>o)throw new u.BaseException('Unexpected "..." before the end of the path for "'+e+'".');n.push(new f)}else n.push(new d(l)),r+=100*(100-o)}var h=p.StringMapWrapper.create();return p.StringMapWrapper.set(h,"segments",n),p.StringMapWrapper.set(h,"specificity",r),h}function o(e){return e.map(function(e){return e instanceof v?"*":e instanceof f?"...":e instanceof y?":":e instanceof d?e.path:void 0}).join("/")}function s(e){return e.split("/")}function a(e){if(c.StringWrapper.contains(e,"#"))throw new u.BaseException('Path "'+e+'" should not include "#". Use "HashLocationStrategy" instead.');var t=c.RegExpWrapper.firstMatch(_,e);if(c.isPresent(t))throw new u.BaseException('Path "'+e+'" contains "'+t[0]+'" which is not allowed in a route config.')}var c=n(5),u=n(14),p=n(12),l=n(231),h=function(){function e(e){var t=this;this.map={},this.keys={},c.isPresent(e)&&p.StringMapWrapper.forEach(e,function(e,n){t.map[n]=c.isPresent(e)?e.toString():null,t.keys[n]=!0})}return e.prototype.get=function(e){return p.StringMapWrapper["delete"](this.keys,e),this.map[e]},e.prototype.getUnused=function(){var e=this,t={},n=p.StringMapWrapper.keys(this.keys);return n.forEach(function(n){return t[n]=p.StringMapWrapper.get(e.map,n)}),t},e}(),f=function(){function e(){this.name=""}return e.prototype.generate=function(e){return""},e.prototype.match=function(e){return!0},e}(),d=function(){function e(e){this.path=e,this.name=""}return e.prototype.match=function(e){return e==this.path},e.prototype.generate=function(e){return this.path},e}(),y=function(){function e(e){this.name=e}return e.prototype.match=function(e){return e.length>0},e.prototype.generate=function(e){if(!p.StringMapWrapper.contains(e.map,this.name))throw new u.BaseException("Route generator for '"+this.name+"' was not included in parameters passed.");return r(e.get(this.name))},e}(),v=function(){function e(e){this.name=e}return e.prototype.match=function(e){return!0},e.prototype.generate=function(e){return r(e.get(this.name))},e}(),m=/^:([^\/]+)$/g,g=/^\*([^\/]+)$/g,_=c.RegExpWrapper.create("//|\\(|\\)|;|\\?|="),b=function(){function e(e){this.path=e,this.terminal=!0,a(e);var t=i(e);this._segments=t.segments,this.specificity=t.specificity,this.hash=o(this._segments);var n=this._segments[this._segments.length-1];this.terminal=!(n instanceof f)}return e.prototype.recognize=function(e){for(var t,n=e,r={},i=[],o=0;o=0;n-=1)t=new p(e[n],t);return t}function i(e){var t=c.RegExpWrapper.firstMatch(h,e);return c.isPresent(t)?t[0]:""}function o(e){var t=[];return c.isPresent(e)&&a.StringMapWrapper.forEach(e,function(e,n){1==e?t.push(n):t.push(n+"="+e)}),t}var s=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},a=n(12),c=n(5),u=n(14),p=function(){function e(e,t,n,r){void 0===t&&(t=null),void 0===n&&(n=c.CONST_EXPR([])),void 0===r&&(r=null),this.path=e,this.child=t,this.auxiliary=n,this.params=r}return e.prototype.toString=function(){return this.path+this._matrixParamsToString()+this._auxToString()+this._childString()},e.prototype.segmentToString=function(){return this.path+this._matrixParamsToString()},e.prototype._auxToString=function(){return this.auxiliary.length>0?"("+this.auxiliary.map(function(e){return e.toString()}).join("//")+")":""},e.prototype._matrixParamsToString=function(){return c.isBlank(this.params)?"":";"+o(this.params).join(";")},e.prototype._childString=function(){return c.isPresent(this.child)?"/"+this.child.toString():""},e}();t.Url=p;var l=function(e){function t(t,n,r,i){void 0===n&&(n=null),void 0===r&&(r=c.CONST_EXPR([])),void 0===i&&(i=null),e.call(this,t,n,r,i)}return s(t,e),t.prototype.toString=function(){return this.path+this._auxToString()+this._childString()+this._queryParamsToString()},t.prototype.segmentToString=function(){return this.path+this._queryParamsToString()},t.prototype._queryParamsToString=function(){return c.isBlank(this.params)?"":"?"+o(this.params).join("&")},t}(p);t.RootUrl=l,t.pathSegmentsToUrl=r;var h=c.RegExpWrapper.create("^[^\\/\\(\\)\\?;=&#]+"),f=function(){function e(){}return e.prototype.peekStartsWith=function(e){return this._remaining.startsWith(e)},e.prototype.capture=function(e){if(!this._remaining.startsWith(e))throw new u.BaseException('Expected "'+e+'".');this._remaining=this._remaining.substring(e.length)},e.prototype.parse=function(e){return this._remaining=e,""==e||"/"==e?new p(""):this.parseRoot()},e.prototype.parseRoot=function(){this.peekStartsWith("/")&&this.capture("/");var e=i(this._remaining);this.capture(e);var t=[];this.peekStartsWith("(")&&(t=this.parseAuxiliaryRoutes()),this.peekStartsWith(";")&&this.parseMatrixParams();var n=null;this.peekStartsWith("/")&&!this.peekStartsWith("//")&&(this.capture("/"),n=this.parseSegment());var r=null;return this.peekStartsWith("?")&&(r=this.parseQueryParams()),new l(e,n,t,r)},e.prototype.parseSegment=function(){if(0==this._remaining.length)return null;this.peekStartsWith("/")&&this.capture("/");var e=i(this._remaining);this.capture(e);var t=null;this.peekStartsWith(";")&&(t=this.parseMatrixParams());var n=[];this.peekStartsWith("(")&&(n=this.parseAuxiliaryRoutes());var r=null;return this.peekStartsWith("/")&&!this.peekStartsWith("//")&&(this.capture("/"),r=this.parseSegment()),new p(e,r,n,t)},e.prototype.parseQueryParams=function(){var e={};for(this.capture("?"),this.parseParam(e);this._remaining.length>0&&this.peekStartsWith("&");)this.capture("&"),this.parseParam(e);return e},e.prototype.parseMatrixParams=function(){for(var e={};this._remaining.length>0&&this.peekStartsWith(";");)this.capture(";"),this.parseParam(e);return e},e.prototype.parseParam=function(e){var t=i(this._remaining);if(!c.isBlank(t)){this.capture(t);var n=!0;if(this.peekStartsWith("=")){this.capture("=");var r=i(this._remaining);c.isPresent(r)&&(n=r,this.capture(n))}e[t]=n}},e.prototype.parseAuxiliaryRoutes=function(){var e=[];for(this.capture("(");!this.peekStartsWith(")")&&this._remaining.length>0;)e.push(this.parseSegment()),this.peekStartsWith("//")&&this.capture("//");return this.capture(")"),e},e}();t.UrlParser=f,t.parser=new f,t.serializeParams=o},function(e,t,n){var r=n(5),i=n(14),o=n(12),s=n(60),a=n(228),c=n(227),u=n(233),p=n(234),l=function(){function e(){this.names=new o.Map,this.auxNames=new o.Map,this.auxRoutes=new o.Map,this.matchers=[],this.defaultRoute=null}return e.prototype.config=function(e){var t;if(r.isPresent(e.name)&&e.name[0].toUpperCase()!=e.name[0]){var n=e.name[0].toUpperCase()+e.name.substring(1);throw new i.BaseException('Route "'+e.path+'" with name "'+e.name+'" does not begin with an uppercase letter. Route names should be CamelCase like "'+n+'".')}if(e instanceof c.AuxRoute){t=new p.SyncRouteHandler(e.component,e.data);var o=e.path.startsWith("/")?e.path.substring(1):e.path,s=new a.RouteRecognizer(e.path,t);return this.auxRoutes.set(o,s),r.isPresent(e.name)&&this.auxNames.set(e.name,s),s.terminal}var l=!1;if(e instanceof c.Redirect){var h=new a.RedirectRecognizer(e.path,e.redirectTo);return this._assertNoHashCollision(h.hash,e.path),this.matchers.push(h),!0}e instanceof c.Route?(t=new p.SyncRouteHandler(e.component,e.data),l=r.isPresent(e.useAsDefault)&&e.useAsDefault):e instanceof c.AsyncRoute&&(t=new u.AsyncRouteHandler(e.loader,e.data),l=r.isPresent(e.useAsDefault)&&e.useAsDefault);var s=new a.RouteRecognizer(e.path,t);if(this._assertNoHashCollision(s.hash,e.path),l){if(r.isPresent(this.defaultRoute))throw new i.BaseException("Only one route can be default");this.defaultRoute=s}return this.matchers.push(s),r.isPresent(e.name)&&this.names.set(e.name,s),s.terminal},e.prototype._assertNoHashCollision=function(e,t){this.matchers.forEach(function(n){if(e==n.hash)throw new i.BaseException("Configuration '"+t+"' conflicts with existing route '"+n.path+"'")})},e.prototype.recognize=function(e){var t=[];return this.matchers.forEach(function(n){var i=n.recognize(e);r.isPresent(i)&&t.push(i)}),t},e.prototype.recognizeAuxiliary=function(e){var t=this.auxRoutes.get(e.path);return r.isPresent(t)?[t.recognize(e)]:[s.PromiseWrapper.resolve(null)]},e.prototype.hasRoute=function(e){return this.names.has(e)},e.prototype.componentLoaded=function(e){return this.hasRoute(e)&&r.isPresent(this.names.get(e).handler.componentType)},e.prototype.loadComponent=function(e){return this.names.get(e).handler.resolveComponentType()},e.prototype.generate=function(e,t){var n=this.names.get(e);return r.isBlank(n)?null:n.generate(t)},e.prototype.generateAuxiliary=function(e,t){var n=this.auxNames.get(e);return r.isBlank(n)?null:n.generate(t)},e}();t.ComponentRecognizer=l},function(e,t,n){var r=n(5),i=n(229),o=function(){function e(e,t){void 0===t&&(t=null),this._loader=e,this._resolvedComponent=null,this.data=r.isPresent(t)?new i.RouteData(t):i.BLANK_ROUTE_DATA}return e.prototype.resolveComponentType=function(){var e=this;return r.isPresent(this._resolvedComponent)?this._resolvedComponent:this._resolvedComponent=this._loader().then(function(t){return e.componentType=t,t})},e}();t.AsyncRouteHandler=o},function(e,t,n){var r=n(60),i=n(5),o=n(229),s=function(){function e(e,t){this.componentType=e,this._resolvedComponent=null,this._resolvedComponent=r.PromiseWrapper.resolve(e),this.data=i.isPresent(t)?new o.RouteData(t):o.BLANK_ROUTE_DATA}return e.prototype.resolveComponentType=function(){return this._resolvedComponent},e}();t.SyncRouteHandler=s},function(e,t,n){function r(e,t){if(e instanceof s.AsyncRoute){var n=i(e.loader,t);return new s.AsyncRoute({path:e.path,loader:n,name:e.name,data:e.data,useAsDefault:e.useAsDefault})}if(e instanceof s.Route||e instanceof s.Redirect||e instanceof s.AuxRoute)return e;if(+!!e.component+ +!!e.redirectTo+ +!!e.loader!=1)throw new c.BaseException('Route config should contain exactly one "component", "loader", or "redirectTo" property.');if(e.as&&e.name)throw new c.BaseException('Route config should contain exactly one "as" or "name" property.');if(e.as&&(e.name=e.as),e.loader){var n=i(e.loader,t);return new s.AsyncRoute({path:e.path,loader:n,name:e.name,useAsDefault:e.useAsDefault})}if(e.aux)return new s.AuxRoute({path:e.aux,component:e.component,name:e.name});if(e.component){if("object"==typeof e.component){var r=e.component;if("constructor"==r.type)return new s.Route({path:e.path,component:r.constructor,name:e.name,data:e.data,useAsDefault:e.useAsDefault});if("loader"==r.type)return new s.AsyncRoute({path:e.path,loader:r.loader,name:e.name,useAsDefault:e.useAsDefault});throw new c.BaseException('Invalid component type "'+r.type+'". Valid types are "constructor" and "loader".')}return new s.Route(e)}return e.redirectTo?new s.Redirect({path:e.path,redirectTo:e.redirectTo}):e}function i(e,t){return function(){return e().then(function(e){return t.configFromComponent(e),e})}}function o(e,t){if(!a.isType(e))throw new c.BaseException('Component for route "'+t+'" is not defined, or is not a class.')}var s=n(236),a=n(5),c=n(14);t.normalizeRouteConfig=r,t.assertComponentExists=o},function(e,t,n){var r=n(227),i=n(9),o=n(227);t.Route=o.Route,t.Redirect=o.Redirect,t.AuxRoute=o.AuxRoute,t.AsyncRoute=o.AsyncRoute,t.RouteConfig=i.makeDecorator(r.RouteConfig)},function(e,t,n){function r(e,t){return e.length>0&&t.startsWith(e)?t.substring(e.length):t}function i(e){return/\/index.html$/g.test(e)?e.substring(0,e.length-11):e}function o(e){return/\/$/g.test(e)&&(e=e.substring(0,e.length-1)),e}var s=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},a=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},c=n(238),u=n(60),p=n(2),l=function(){function e(e){ -var t=this;this.platformStrategy=e,this._subject=new u.EventEmitter;var n=this.platformStrategy.getBaseHref();this._baseHref=o(i(n)),this.platformStrategy.onPopState(function(e){u.ObservableWrapper.callEmit(t._subject,{url:t.path(),pop:!0,type:e.type})})}return e.prototype.path=function(){return this.normalize(this.platformStrategy.path())},e.prototype.normalize=function(e){return o(r(this._baseHref,i(e)))},e.prototype.prepareExternalUrl=function(e){return e.length>0&&!e.startsWith("/")&&(e="/"+e),this.platformStrategy.prepareExternalUrl(e)},e.prototype.go=function(e,t){void 0===t&&(t=""),this.platformStrategy.pushState(null,"",e,t)},e.prototype.replaceState=function(e,t){void 0===t&&(t=""),this.platformStrategy.replaceState(null,"",e,t)},e.prototype.forward=function(){this.platformStrategy.forward()},e.prototype.back=function(){this.platformStrategy.back()},e.prototype.subscribe=function(e,t,n){return void 0===t&&(t=null),void 0===n&&(n=null),u.ObservableWrapper.subscribe(this._subject,e,t,n)},e=s([p.Injectable(),a("design:paramtypes",[c.LocationStrategy])],e)}();t.Location=l},function(e,t,n){function r(e){return e.length>0&&"?"!=e.substring(0,1)?"?"+e:e}function i(e,t){if(0==e.length)return t;if(0==t.length)return e;var n=0;return e.endsWith("/")&&n++,t.startsWith("/")&&n++,2==n?e+t.substring(1):1==n?e+t:e+"/"+t}var o=n(5),s=n(2),a=function(){function e(){}return e}();t.LocationStrategy=a,t.APP_BASE_HREF=o.CONST_EXPR(new s.OpaqueToken("appBaseHref")),t.normalizeQueryParams=r,t.joinWithSlash=i},function(e,t,n){function r(e,t){return t instanceof o.Type?e.name in t.prototype:!1}function i(e){for(var t=a.reflector.annotations(e),n=0;no?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(5),s=function(){function e(e){this.name=e}return e=r([o.CONST(),i("design:paramtypes",[String])],e)}();t.RouteLifecycleHook=s;var a=function(){function e(e){this.fn=e}return e=r([o.CONST(),i("design:paramtypes",[Function])],e)}();t.CanActivate=a,t.routerCanReuse=o.CONST_EXPR(new s("routerCanReuse")),t.routerCanDeactivate=o.CONST_EXPR(new s("routerCanDeactivate")),t.routerOnActivate=o.CONST_EXPR(new s("routerOnActivate")),t.routerOnReuse=o.CONST_EXPR(new s("routerOnReuse")),t.routerOnDeactivate=o.CONST_EXPR(new s("routerOnDeactivate"))},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},s=n(60),a=n(12),c=n(5),u=n(14),p=n(2),l=n(225),h=n(229),f=n(242),d=n(239),y=s.PromiseWrapper.resolve(!0),v=function(){function e(e,t,n,r){this._elementRef=e,this._loader=t,this._parentRouter=n,this.name=null,this._componentRef=null,this._currentInstruction=null,c.isPresent(r)?(this.name=r,this._parentRouter.registerAuxOutlet(this)):this._parentRouter.registerPrimaryOutlet(this)}return e.prototype.activate=function(e){var t=this,n=this._currentInstruction;this._currentInstruction=e;var r=e.componentType,i=this._parentRouter.childRouter(r),o=p.Injector.resolve([p.provide(h.RouteData,{useValue:e.routeData}),p.provide(h.RouteParams,{useValue:new h.RouteParams(e.params)}),p.provide(l.Router,{useValue:i})]);return this._loader.loadNextToLocation(r,this._elementRef,o).then(function(i){return t._componentRef=i,d.hasLifecycleHook(f.routerOnActivate,r)?t._componentRef.instance.routerOnActivate(e,n):void 0})},e.prototype.reuse=function(e){var t=this._currentInstruction;if(this._currentInstruction=e,c.isBlank(this._componentRef))throw new u.BaseException("Cannot reuse an outlet that does not contain a component.");return s.PromiseWrapper.resolve(d.hasLifecycleHook(f.routerOnReuse,this._currentInstruction.componentType)?this._componentRef.instance.routerOnReuse(e,t):!0)},e.prototype.deactivate=function(e){var t=this,n=y;return c.isPresent(this._componentRef)&&c.isPresent(this._currentInstruction)&&d.hasLifecycleHook(f.routerOnDeactivate,this._currentInstruction.componentType)&&(n=s.PromiseWrapper.resolve(this._componentRef.instance.routerOnDeactivate(e,this._currentInstruction))),n.then(function(e){c.isPresent(t._componentRef)&&(t._componentRef.dispose(),t._componentRef=null)})},e.prototype.routerCanDeactivate=function(e){return c.isBlank(this._currentInstruction)?y:d.hasLifecycleHook(f.routerCanDeactivate,this._currentInstruction.componentType)?s.PromiseWrapper.resolve(this._componentRef.instance.routerCanDeactivate(e,this._currentInstruction)):y},e.prototype.routerCanReuse=function(e){var t;return t=c.isBlank(this._currentInstruction)||this._currentInstruction.componentType!=e.componentType?!1:d.hasLifecycleHook(f.routerCanReuse,this._currentInstruction.componentType)?this._componentRef.instance.routerCanReuse(e,this._currentInstruction):e==this._currentInstruction||c.isPresent(e.params)&&c.isPresent(this._currentInstruction.params)&&a.StringMapWrapper.equals(e.params,this._currentInstruction.params),s.PromiseWrapper.resolve(t)},e=r([p.Directive({selector:"router-outlet"}),o(3,p.Attribute("name")),i("design:paramtypes",[p.ElementRef,p.DynamicComponentLoader,l.Router,String])],e)}();t.RouterOutlet=v},function(e,t,n){var r=n(9),i=n(240),o=n(240);t.routerCanReuse=o.routerCanReuse,t.routerCanDeactivate=o.routerCanDeactivate,t.routerOnActivate=o.routerOnActivate,t.routerOnReuse=o.routerOnReuse,t.routerOnDeactivate=o.routerOnDeactivate,t.CanActivate=r.makeDecorator(i.CanActivate)},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(2),s=n(5),a=n(225),c=n(237),u=function(){function e(e,t){this._router=e,this._location=t}return Object.defineProperty(e.prototype,"isRouteActive",{get:function(){return this._router.isRouteActive(this._navigationInstruction)},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"routeParams",{set:function(e){this._routeParams=e,this._navigationInstruction=this._router.generate(this._routeParams);var t=this._navigationInstruction.toLinkUrl();this.visibleHref=this._location.prepareExternalUrl(t)},enumerable:!0,configurable:!0}),e.prototype.onClick=function(){return s.isString(this.target)&&"_self"!=this.target?!0:(this._router.navigateByInstruction(this._navigationInstruction),!1)},e=r([o.Directive({selector:"[routerLink]",inputs:["routeParams: routerLink","target: target"],host:{"(click)":"onClick()","[attr.href]":"visibleHref","[class.router-link-active]":"isRouteActive"}}),i("design:paramtypes",[a.Router,c.Location])],e)}();t.RouterLink=u},function(e,t,n){var r=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},i=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},o=n(178),s=n(2),a=function(){function e(){this._init()}return e.prototype._init=function(){this._location=o.DOM.getLocation(),this._history=o.DOM.getHistory()},e.prototype.getBaseHrefFromDOM=function(){return o.DOM.getBaseHref()},e.prototype.onPopState=function(e){o.DOM.getGlobalEventTarget("window").addEventListener("popstate",e,!1)},e.prototype.onHashChange=function(e){o.DOM.getGlobalEventTarget("window").addEventListener("hashchange",e,!1)},Object.defineProperty(e.prototype,"pathname",{get:function(){return this._location.pathname},set:function(e){this._location.pathname=e},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"search",{get:function(){return this._location.search},enumerable:!0,configurable:!0}),Object.defineProperty(e.prototype,"hash",{get:function(){return this._location.hash},enumerable:!0,configurable:!0}),e.prototype.pushState=function(e,t,n){this._history.pushState(e,t,n)},e.prototype.replaceState=function(e,t,n){this._history.replaceState(e,t,n)},e.prototype.forward=function(){this._history.forward()},e.prototype.back=function(){this._history.back()},e=r([s.Injectable(),i("design:paramtypes",[])],e)}();t.PlatformLocation=a},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},a=n(2),c=n(238),u=n(5),p=n(244),l=function(e){function t(t,n){e.call(this),this._platformLocation=t,this._baseHref="",u.isPresent(n)&&(this._baseHref=n)}return r(t,e),t.prototype.onPopState=function(e){this._platformLocation.onPopState(e),this._platformLocation.onHashChange(e)},t.prototype.getBaseHref=function(){return this._baseHref},t.prototype.path=function(){var e=this._platformLocation.hash;return(e.length>0?e.substring(1):e)+c.normalizeQueryParams(this._platformLocation.search)},t.prototype.prepareExternalUrl=function(e){var t=c.joinWithSlash(this._baseHref,e);return t.length>0?"#"+t:t},t.prototype.pushState=function(e,t,n,r){var i=this.prepareExternalUrl(n+c.normalizeQueryParams(r));0==i.length&&(i=this._platformLocation.pathname),this._platformLocation.pushState(e,t,i)},t.prototype.replaceState=function(e,t,n,r){var i=this.prepareExternalUrl(n+c.normalizeQueryParams(r));0==i.length&&(i=this._platformLocation.pathname),this._platformLocation.replaceState(e,t,i)},t.prototype.forward=function(){this._platformLocation.forward()},t.prototype.back=function(){this._platformLocation.back()},t=i([a.Injectable(),s(1,a.Optional()),s(1,a.Inject(c.APP_BASE_HREF)),o("design:paramtypes",[p.PlatformLocation,String])],t)}(c.LocationStrategy);t.HashLocationStrategy=l},function(e,t,n){var r=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},i=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},o=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},s=this&&this.__param||function(e,t){return function(n,r){t(n,r,e)}},a=n(2),c=n(5),u=n(14),p=n(238),l=n(244),h=function(e){function t(t,n){if(e.call(this),this._platformLocation=t,c.isBlank(n)&&(n=this._platformLocation.getBaseHrefFromDOM()),c.isBlank(n))throw new u.BaseException("No base href set. Please provide a value for the APP_BASE_HREF token or add a base element to the document.");this._baseHref=n}return r(t,e),t.prototype.onPopState=function(e){this._platformLocation.onPopState(e),this._platformLocation.onHashChange(e)},t.prototype.getBaseHref=function(){return this._baseHref},t.prototype.prepareExternalUrl=function(e){return p.joinWithSlash(this._baseHref,e)},t.prototype.path=function(){return this._platformLocation.pathname+p.normalizeQueryParams(this._platformLocation.search)},t.prototype.pushState=function(e,t,n,r){var i=this.prepareExternalUrl(n+p.normalizeQueryParams(r));this._platformLocation.pushState(e,t,i)},t.prototype.replaceState=function(e,t,n,r){var i=this.prepareExternalUrl(n+p.normalizeQueryParams(r));this._platformLocation.replaceState(e,t,i)},t.prototype.forward=function(){this._platformLocation.forward()},t.prototype.back=function(){this._platformLocation.back()},t=i([a.Injectable(),s(1,a.Optional()),s(1,a.Inject(p.APP_BASE_HREF)),o("design:paramtypes",[l.PlatformLocation,String])],t)}(p.LocationStrategy);t.PathLocationStrategy=h},function(e,t){},function(e,t,n){var r=n(147),i=n(2),o=n(249),s=n(5),a=n(249);t.RouterLinkTransform=a.RouterLinkTransform,t.ROUTER_LINK_DSL_PROVIDER=s.CONST_EXPR(new i.Provider(r.TEMPLATE_TRANSFORMS,{useClass:o.RouterLinkTransform,multi:!0}))},function(e,t,n){function r(e,t){var n=new v(e,t.trim()).tokenize();return new m(n).generate()}var i=this&&this.__extends||function(e,t){function n(){this.constructor=e}for(var r in t)t.hasOwnProperty(r)&&(e[r]=t[r]);e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)},o=this&&this.__decorate||function(e,t,n,r){var i,o=arguments.length,s=3>o?t:null===r?r=Object.getOwnPropertyDescriptor(t,n):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(e,t,n,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(s=(3>o?i(s):o>3?i(t,n,s):i(t,n))||s);return o>3&&s&&Object.defineProperty(t,n,s),s},s=this&&this.__metadata||function(e,t){return"object"==typeof Reflect&&"function"==typeof Reflect.metadata?Reflect.metadata(e,t):void 0},a=n(147),c=n(30),u=n(14),p=n(2),l=n(32),h=function(){function e(e){this.value=e}return e}(),f=function(){function e(){}return e}(),d=function(){function e(){}return e}(),y=function(){function e(e){this.ast=e}return e}(),v=function(){function e(e,t){this.parser=e,this.exp=t,this.index=0}return e.prototype.tokenize=function(){for(var e=[];this.indexn;n++)t.insertBefore(e[n],this.contentInserctionPoint)},e.prototype.setupOutputs=function(){for(var e=this,t=this.attrs,n=this.info.outputs,r=0;r1)throw new Error("Only support single directive definition for: "+this.name);var n=t[0];n.replace&&this.notSupported("replace"),n.terminal&&this.notSupported("terminal");var r=n.link;return"object"==typeof r&&r.post&&this.notSupported("link.post"),n},e.prototype.notSupported=function(e){throw new Error("Upgraded directive '"+this.name+"' does not support '"+e+"'.")},e.prototype.extractBindings=function(){var e=this.directive.scope;if("object"==typeof e)for(var t in e)if(e.hasOwnProperty(t)){var n=e[t],r=n.charAt(0);n=n.substr(1)||t;var i="output_"+t,o=i+": "+t,s=i+": "+t+"Change",a="input_"+t,c=a+": "+t;switch(r){case"=":this.propertyOutputs.push(i),this.checkProperties.push(n),this.outputs.push(i),this.outputsRename.push(s),this.propertyMap[i]=n;case"@":this.inputs.push(a),this.inputsRename.push(c),this.propertyMap[a]=n;break;case"&":this.outputs.push(i),this.outputsRename.push(o),this.propertyMap[i]=n;break;default:var u=JSON.stringify(e);throw new Error("Unexpected mapping '"+r+"' in '"+u+"' in '"+this.name+"' directive.")}}},e.prototype.compileTemplate=function(e,t,n){function r(t){var n=document.createElement("div");return n.innerHTML=t,e(n.childNodes)}var i=this;if(void 0!==this.directive.template)this.linkFn=r(this.directive.template);else{if(!this.directive.templateUrl)throw new Error("Directive '"+this.name+"' is not a component, it is missing template.");var o=this.directive.templateUrl,s=t.get(o);if(void 0===s)return new Promise(function(e,s){n("GET",o,null,function(n,a){200==n?e(i.linkFn=r(t.put(o,a))):s("GET "+o+" returned "+n+": "+a)})});this.linkFn=r(s)}return null},e.resolve=function(e,t){var n=[],r=t.get(i.NG1_COMPILE),o=t.get(i.NG1_TEMPLATE_CACHE),s=t.get(i.NG1_HTTP_BACKEND),a=t.get(i.NG1_CONTROLLER);for(var c in e)if(e.hasOwnProperty(c)){var u=e[c];u.directive=u.extractDirective(t),u.$controller=a,u.extractBindings();var p=u.compileTemplate(r,o,s);p&&n.push(p)}return Promise.all(n)},e}();t.UpgradeNg1ComponentAdapterBuilder=p;var l=function(){function e(e,t,n,i,a,p,l,h,f,d){this.directive=n,this.inputs=p,this.outputs=l,this.propOuts=h,this.checkProperties=f,this.propertyMap=d,this.destinationObj=null,this.checkLastValues=[];for(var y,v=i.nativeElement,m=[];y=v.firstChild;)v.removeChild(y),m.push(y);var g=t.$new(!!n.scope),_=s.element(v),b=n.controller,C=null;if(b){var P={$scope:g,$element:_};C=a(b,P,null,n.controllerAs),_.data(o.controllerKey(n.name),C)}var w=n.link;if("object"==typeof w&&(w=w.pre),w){var R=u,E=u,O=this.resolveRequired(_,n.require);n.link(g,_,R,O,E)}this.destinationObj=n.bindToController&&C?C:g,e(g,function(e,t){for(var n=0,r=e.length;r>n;n++)v.appendChild(e[n])},{parentBoundTranscludeFn:function(e,t){t(m)}});for(var S=0;S-1;u&&!a&&(i=Promise.resolve());var s=e("es6-promise").Promise;i&&s._setScheduler(function(e){i.then(e)}),s._setAsap(function(e,t){n.zone.scheduleMicrotask(function(){e(t)})}),t.exports={addMicrotaskSupport:o}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"es6-promise":17}],5:[function(e,t,n){(function(n){"use strict";function r(){o.patchSetClearFunction(n,["timeout","interval","immediate"]),o.patchRequestAnimationFrame(n,["requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame"]),o.patchFunction(n,["alert","prompt"]),c.apply(),f.apply(),i.apply(),u.patchClass("MutationObserver"),u.patchClass("WebKitMutationObserver"),a.apply(),s.apply(),p.apply(),l.apply()}var o=e("./functions"),i=e("./promise"),u=e("./mutation-observer"),a=e("./define-property"),s=e("./register-element"),c=(e("./websocket"),e("./event-target")),f=e("./property-descriptor"),p=e("./geolocation"),l=e("./file-reader");t.exports={apply:r}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./define-property":6,"./event-target":7,"./file-reader":8,"./functions":9,"./geolocation":10,"./mutation-observer":11,"./promise":12,"./property-descriptor":13,"./register-element":14,"./websocket":15}],6:[function(e,t,n){"use strict";function r(){Object.defineProperty=function(e,t,n){if(i(e,t))throw new TypeError("Cannot assign to read only property '"+t+"' of "+e);return"prototype"!==t&&(n=u(e,t,n)),s(e,t,n)},Object.defineProperties=function(e,t){return Object.keys(t).forEach(function(n){Object.defineProperty(e,n,t[n])}),e},Object.create=function(e,t){return"object"==typeof t&&Object.keys(t).forEach(function(n){t[n]=u(e,n,t[n])}),f(e,t)},Object.getOwnPropertyDescriptor=function(e,t){var n=c(e,t);return i(e,t)&&(n.configurable=!1),n}}function o(e,t,n){return n=u(e,t,n),s(e,t,n)}function i(e,t){return e&&e[p]&&e[p][t]}function u(e,t,n){return n.configurable=!0,n.configurable||(e[p]||s(e,p,{writable:!0,value:{}}),e[p][t]=!0),n}var a=e("../keys"),s=Object.defineProperty,c=Object.getOwnPropertyDescriptor,f=Object.create,p=a.create("unconfigurables");t.exports={apply:r,_redefineProperty:o}},{"../keys":3}],7:[function(e,t,n){(function(n){"use strict";function r(){if(n.EventTarget)o.patchEventTargetMethods(n.EventTarget.prototype);else{var e=["ApplicationCache","EventSource","FileReader","InputMethodContext","MediaController","MessagePort","Node","Performance","SVGElementInstance","SharedWorker","TextTrack","TextTrackCue","TextTrackList","WebKitNamedFlow","Worker","WorkerGlobalScope","XMLHttpRequest","XMLHttpRequestEventTarget","XMLHttpRequestUpload"];e.forEach(function(e){var t=n[e]&&n[e].prototype;t&&t.addEventListener&&o.patchEventTargetMethods(t)}),"undefined"!=typeof window&&o.patchEventTargetMethods(window)}}var o=e("../utils");t.exports={apply:r}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../utils":16}],8:[function(e,t,n){"use strict";function r(){o.patchClass("FileReader")}var o=e("../utils");t.exports={apply:r}},{"../utils":16}],9:[function(e,t,n){(function(n){"use strict";function r(e,t){t.map(function(e){return e[0].toUpperCase()+e.substr(1)}).forEach(function(t){var r="set"+t,o=e[r];if(o){var i="clear"+t,u={},s="setInterval"===r?a.bindArguments:a.bindArgumentsOnce;n.zone[r]=function(t){var n,r=t;arguments[0]=function(){return delete u[n],r.apply(this,arguments)};var i=s(arguments);return n=o.apply(e,i),u[n]=!0,n},e[r]=function(){return n.zone[r].apply(this,arguments)};var c=e[i];n.zone[i]=function(e){return u[e]&&(delete u[e],n.zone.dequeueTask()),c.apply(this,arguments)},e[i]=function(){return n.zone[i].apply(this,arguments)}}})}function o(e,t){t.forEach(function(t){var r=e[t];r&&(n.zone[t]=function(t){var o=n.zone.isRootZone()?n.zone.fork():n.zone;return t&&(arguments[0]=function(){return o.run(t,this,arguments)}),r.apply(e,arguments)},e[t]=function(){return n.zone[t].apply(this,arguments)})})}function i(e,t){t.forEach(function(t){var r=e[t];r&&(n.zone[t]=function(t){arguments[0]=function(){return t.apply(this,arguments)};var n=a.bindArgumentsOnce(arguments);return r.apply(e,n)},e[t]=function(){return zone[t].apply(this,arguments)})})}function u(e,t){t.forEach(function(t){var r=e[t];n.zone[t]=function(){return r.apply(e,arguments)},e[t]=function(){return n.zone[t].apply(this,arguments)}})}var a=e("../utils");t.exports={patchSetClearFunction:r,patchSetFunction:i,patchRequestAnimationFrame:o,patchFunction:u}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../utils":16}],10:[function(e,t,n){(function(n){"use strict";function r(){n.navigator&&n.navigator.geolocation&&o.patchPrototype(n.navigator.geolocation,["getCurrentPosition","watchPosition"])}var o=e("../utils");t.exports={apply:r}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../utils":16}],11:[function(e,t,n){(function(n){"use strict";function r(e){var t=n[e];if(t){n[e]=function(e){this[i]=new t(n.zone.bind(e,!0)),this[u]=n.zone};var r=new t(function(){});n[e].prototype.disconnect=function(){var e=this[i].disconnect.apply(this[i],arguments);return this[a]&&(this[u].dequeueTask(),this[a]=!1),e},n[e].prototype.observe=function(){return this[a]||(this[u].enqueueTask(),this[a]=!0),this[i].observe.apply(this[i],arguments)};var o;for(o in r)!function(t){"undefined"==typeof n[e].prototype&&("function"==typeof r[t]?n[e].prototype[t]=function(){return this[i][t].apply(this[i],arguments)}:Object.defineProperty(n[e].prototype,t,{set:function(e){"function"==typeof e?this[i][t]=n.zone.bind(e):this[i][t]=e},get:function(){return this[i][t]}}))}(o)}}var o=e("../keys"),i=o.create("originalInstance"),u=o.create("creationZone"),a=o.create("isActive");t.exports={patchClass:r}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../keys":3}],12:[function(e,t,n){(function(n){"use strict";function r(e,t){var r=n,o=e.every(function(e){return r=r[e]});o&&t.forEach(function(e){var t=r[e];t&&(r[e]=u(t))})}function o(e){var t=e.then;e.then=function(){var n=a.bindArguments(arguments),r=t.apply(e,n);return o(r)};var n=e["catch"];return e["catch"]=function(){var t=a.bindArguments(arguments),r=n.apply(e,t);return o(r)},e}function i(){if(n.Promise){a.patchPrototype(Promise.prototype,["then","catch"]);var e=[[[],["fetch"]],[["Response","prototype"],["arrayBuffer","blob","json","text"]]];e.forEach(function(e){r(e[0],e[1])})}}var u,a=e("../utils");u=n.Promise?function(e){return function(){var t=e.apply(this,arguments);return t instanceof Promise?t:new Promise(function(e,n){t.then(e,n)})}}:function(e){return function(){return o(e.apply(this,arguments))}},t.exports={apply:i,bindPromiseFn:u}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../utils":16}],13:[function(e,t,n){(function(n){"use strict";function r(){if(!a.isWebWorker()){var e="undefined"!=typeof WebSocket;if(o()){var t=c.map(function(e){return"on"+e});a.patchProperties(HTMLElement.prototype,t),a.patchProperties(XMLHttpRequest.prototype),e&&a.patchProperties(WebSocket.prototype)}else i(),a.patchClass("XMLHttpRequest"),e&&u.apply()}}function o(){if(!Object.getOwnPropertyDescriptor(HTMLElement.prototype,"onclick")&&"undefined"!=typeof Element){var e=Object.getOwnPropertyDescriptor(Element.prototype,"onclick");if(e&&!e.configurable)return!1}Object.defineProperty(HTMLElement.prototype,"onclick",{get:function(){return!0}});var t=document.createElement("div"),n=!!t.onclick;return Object.defineProperty(HTMLElement.prototype,"onclick",{}),n}function i(){c.forEach(function(e){var t="on"+e;document.addEventListener(e,function(e){for(var r,o=e.target;o;)o[t]&&!o[t][f]&&(r=n.zone.bind(o[t]),r[f]=o[t],o[t]=r),o=o.parentElement},!0)})}var u=e("./websocket"),a=e("../utils"),s=e("../keys"),c="copy cut paste abort blur focus canplay canplaythrough change click contextmenu dblclick drag dragend dragenter dragleave dragover dragstart drop durationchange emptied ended input invalid keydown keypress keyup load loadeddata loadedmetadata loadstart message mousedown mouseenter mouseleave mousemove mouseout mouseover mouseup pause play playing progress ratechange reset scroll seeked seeking select show stalled submit suspend timeupdate volumechange waiting mozfullscreenchange mozfullscreenerror mozpointerlockchange mozpointerlockerror error webglcontextrestored webglcontextlost webglcontextcreationerror".split(" "),f=s.create("unbound");t.exports={apply:r}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../keys":3,"../utils":16,"./websocket":15}],14:[function(e,t,n){(function(n){"use strict";function r(){if(!i.isWebWorker()&&"registerElement"in n.document){var e=document.registerElement,t=["createdCallback","attachedCallback","detachedCallback","attributeChangedCallback"];document.registerElement=function(r,i){return i&&i.prototype&&t.forEach(function(e){if(i.prototype.hasOwnProperty(e)){var t=Object.getOwnPropertyDescriptor(i.prototype,e);t&&t.value?(t.value=n.zone.bind(t.value),o(i.prototype,e,t)):i.prototype[e]=n.zone.bind(i.prototype[e])}else i.prototype[e]&&(i.prototype[e]=n.zone.bind(i.prototype[e]))}),e.apply(document,[r,i])}}}var o=e("./define-property")._redefineProperty,i=e("../utils");t.exports={apply:r}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../utils":16,"./define-property":6}],15:[function(e,t,n){(function(n){"use strict";function r(){var e=n.WebSocket;o.patchEventTargetMethods(e.prototype),n.WebSocket=function(t,n){var r,i=arguments.length>1?new e(t,n):new e(t),u=Object.getOwnPropertyDescriptor(i,"onmessage");return u&&u.configurable===!1?(r=Object.create(i),["addEventListener","removeEventListener","send","close"].forEach(function(e){r[e]=function(){return i[e].apply(i,arguments)}})):r=i,o.patchProperties(r,["onclose","onerror","onmessage","onopen"]),r}}var o=e("../utils");t.exports={apply:r}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"../utils":16}],16:[function(e,t,n){(function(n){"use strict";function r(e){for(var t=e.length-1;t>=0;t--)"function"==typeof e[t]&&(e[t]=n.zone.bind(e[t]));return e}function o(e){for(var t=e.length-1;t>=0;t--)"function"==typeof e[t]&&(e[t]=n.zone.bindOnce(e[t]));return e}function i(e,t){t.forEach(function(t){var n=e[t];n&&(e[t]=function(){return n.apply(this,r(arguments))})})}function u(){return"undefined"==typeof document}function a(e,t){var n=Object.getOwnPropertyDescriptor(e,t)||{enumerable:!0,configurable:!0};delete n.writable,delete n.value;var r=t.substr(2),o="_"+t;n.set=function(e){this[o]&&this.removeEventListener(r,this[o]),"function"==typeof e?(this[o]=e,this.addEventListener(r,e,!1)):this[o]=null},n.get=function(){return this[o]},Object.defineProperty(e,t,n)}function s(e,t){(t||function(){var t=[];for(var n in e)t.push(n);return t}().filter(function(e){return"on"===e.substr(0,2)})).forEach(function(t){a(e,t)})}function c(e){e[p.common.addEventListener]=e.addEventListener,e.addEventListener=function(e,t,r){if(t&&"[object FunctionWrapper]"!==t.toString()){var o,i=e+(r?"$capturing":"$bubbling");o=t.handleEvent?function(e){return function(){e.handleEvent.apply(e,arguments)}}(t):t,t[l]=o,t[d]=t[d]||{},t[d][i]=t[d][i]||zone.bind(o),arguments[1]=t[d][i]}var u=this||n;return n.zone.addEventListener.apply(u,arguments)},e[p.common.removeEventListener]=e.removeEventListener,e.removeEventListener=function(e,t,r){var o=e+(r?"$capturing":"$bubbling");if(t&&t[d]&&t[d][o]){var i=t[d];arguments[1]=i[o],delete i[o],n.zone.dequeueTask(t[l])}var u=this||n,a=n.zone.removeEventListener.apply(u,arguments);return a}}function f(e){var t=n[e];if(t){n[e]=function(){var e=r(arguments);switch(e.length){case 0:this[h]=new t;break;case 1:this[h]=new t(e[0]);break;case 2:this[h]=new t(e[0],e[1]);break;case 3:this[h]=new t(e[0],e[1],e[2]);break;case 4:this[h]=new t(e[0],e[1],e[2],e[3]);break;default:throw new Error("what are you even doing?")}};var o,i=new t;for(o in i)!function(t){"function"==typeof i[t]?n[e].prototype[t]=function(){return this[h][t].apply(this[h],arguments)}:Object.defineProperty(n[e].prototype,t,{set:function(e){"function"==typeof e?this[h][t]=n.zone.bind(e):this[h][t]=e},get:function(){return this[h][t]}})}(o);for(o in t)"prototype"!==o&&t.hasOwnProperty(o)&&(n[e][o]=t[o])}}var p=e("./keys"),l=p.create("originalFn"),d=p.create("boundFns"),h=p.create("originalInstance");t.exports={bindArguments:r,bindArgumentsOnce:o,patchPrototype:i,patchProperty:a,patchProperties:s,patchEventTargetMethods:c,patchClass:f,isWebWorker:u}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"./keys":3}],17:[function(e,t,n){(function(n,r){(function(){"use strict";function o(e){return"function"==typeof e||"object"==typeof e&&null!==e}function i(e){return"function"==typeof e}function u(e){return"object"==typeof e&&null!==e}function a(e){$=e}function s(e){G=e}function c(){return function(){n.nextTick(h)}}function f(){return function(){U(h)}}function p(){var e=0,t=new J(h),n=document.createTextNode("");return t.observe(n,{characterData:!0}),function(){n.data=e=++e%2}}function l(){var e=new MessageChannel;return e.port1.onmessage=h,function(){e.port2.postMessage(0)}}function d(){return function(){setTimeout(h,1)}}function h(){for(var e=0;B>e;e+=2){var t=te[e],n=te[e+1];t(n),te[e]=void 0,te[e+1]=void 0}B=0}function y(){try{var t=e,n=t("vertx");return U=n.runOnLoop||n.runOnContext,f()}catch(r){return d()}}function v(){}function g(){return new TypeError("You cannot resolve a promise with itself")}function m(){return new TypeError("A promises callback cannot return that same promise.")}function w(e){try{return e.then}catch(t){return ie.error=t,ie}}function b(e,t,n,r){try{e.call(t,n,r)}catch(o){return o}}function _(e,t,n){G(function(e){var r=!1,o=b(n,t,function(n){r||(r=!0,t!==n?O(e,n):j(e,n))},function(t){r||(r=!0,P(e,t))},"Settle: "+(e._label||" unknown promise"));!r&&o&&(r=!0,P(e,o))},e)}function k(e,t){t._state===re?j(e,t._result):t._state===oe?P(e,t._result):x(t,void 0,function(t){O(e,t)},function(t){P(e,t)})}function E(e,t){if(t.constructor===e.constructor)k(e,t);else{var n=w(t);n===ie?P(e,ie.error):void 0===n?j(e,t):i(n)?_(e,t,n):j(e,t)}}function O(e,t){e===t?P(e,g()):o(t)?E(e,t):j(e,t)}function T(e){e._onerror&&e._onerror(e._result),z(e)}function j(e,t){e._state===ne&&(e._result=t,e._state=re,0!==e._subscribers.length&&G(z,e))}function P(e,t){e._state===ne&&(e._state=oe,e._result=t,G(T,e))}function x(e,t,n,r){var o=e._subscribers,i=o.length;e._onerror=null,o[i]=t,o[i+re]=n,o[i+oe]=r,0===i&&e._state&&G(z,e)}function z(e){var t=e._subscribers,n=e._state;if(0!==t.length){for(var r,o,i=e._result,u=0;uu;u++)x(r.resolve(e[u]),void 0,t,n);return o}function R(e){var t=this;if(e&&"object"==typeof e&&e.constructor===t)return e;var n=new t(v);return O(n,e),n}function W(e){var t=this,n=new t(v);return P(n,e),n}function D(){throw new TypeError("You must pass a resolver function as the first argument to the promise constructor")}function Z(){throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.")}function H(e){this._id=le++,this._state=void 0,this._result=void 0,this._subscribers=[],v!==e&&(i(e)||D(),this instanceof H||Z(),S(this,e))}function I(){var e;if("undefined"!=typeof r)e=r;else if("undefined"!=typeof self)e=self;else try{e=Function("return this")()}catch(t){throw new Error("polyfill failed because global object is unavailable in this environment")}var n=e.Promise;(!n||"[object Promise]"!==Object.prototype.toString.call(n.resolve())||n.cast)&&(e.Promise=de)}var N;N=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)};var U,$,K,X=N,B=0,G=({}.toString,function(e,t){te[B]=e,te[B+1]=t,B+=2,2===B&&($?$(h):K())}),V="undefined"!=typeof window?window:void 0,Y=V||{},J=Y.MutationObserver||Y.WebKitMutationObserver,Q="undefined"!=typeof n&&"[object process]"==={}.toString.call(n),ee="undefined"!=typeof Uint8ClampedArray&&"undefined"!=typeof importScripts&&"undefined"!=typeof MessageChannel,te=new Array(1e3);K=Q?c():J?p():ee?l():void 0===V&&"function"==typeof e?y():d();var ne=void 0,re=1,oe=2,ie=new A,ue=new A;F.prototype._validateInput=function(e){return X(e)},F.prototype._validationError=function(){return new Error("Array Methods must be provided an Array")},F.prototype._init=function(){this._result=new Array(this.length)};var ae=F;F.prototype._enumerate=function(){for(var e=this,t=e.length,n=e.promise,r=e._input,o=0;n._state===ne&&t>o;o++)e._eachEntry(r[o],o)},F.prototype._eachEntry=function(e,t){var n=this,r=n._instanceConstructor;u(e)?e.constructor===r&&e._state!==ne?(e._onerror=null,n._settledAt(e._state,t,e._result)):n._willSettleAt(r.resolve(e),t):(n._remaining--,n._result[t]=e)},F.prototype._settledAt=function(e,t,n){var r=this,o=r.promise;o._state===ne&&(r._remaining--,e===oe?P(o,n):r._result[t]=n),0===r._remaining&&j(o,r._result)},F.prototype._willSettleAt=function(e,t){var n=this;x(e,void 0,function(e){n._settledAt(re,t,e)},function(e){n._settledAt(oe,t,e)})};var se=C,ce=q,fe=R,pe=W,le=0,de=H;H.all=se,H.race=ce,H.resolve=fe,H.reject=pe,H._setScheduler=a,H._setAsap=s,H._asap=G,H.prototype={constructor:H,then:function(e,t){var n=this,r=n._state;if(r===re&&!e||r===oe&&!t)return this;var o=new this.constructor(v),i=n._result;if(r){var u=arguments[r-1];G(function(){L(r,o,u,i)})}else x(n,o,e,t);return o},"catch":function(e){return this.then(null,e)}};var he=I,ye={Promise:de,polyfill:he};"function"==typeof define&&define.amd?define(function(){return ye}):"undefined"!=typeof t&&t.exports?t.exports=ye:"undefined"!=typeof this&&(this.ES6Promise=ye),he()}).call(this)}).call(this,{},"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}]},{},[1]),function t(e,n,r){function o(u,a){if(!n[u]){if(!e[u]){var s="function"==typeof require&&require;if(!a&&s)return s(u,!0);if(i)return i(u,!0);var c=new Error("Cannot find module '"+u+"'");throw c.code="MODULE_NOT_FOUND",c}var f=n[u]={exports:{}};e[u][0].call(f.exports,function(t){var n=e[u][1][t];return o(n?n:t)},f,f.exports,t,e,n,r)}return n[u].exports}for(var i="function"==typeof require&&require,u=0;u0)return!0;var o=q.get(t);return o["delete"](n),o.size>0?!0:(q["delete"](t),!0)}function p(e,t){for(var n=e.length-1;n>=0;--n){var r=e[n],o=r(t);if(!k(o)){if(!T(o))throw new TypeError;t=o}}return t}function l(e,t,n,r){for(var o=e.length-1;o>=0;--o){var i=e[o],u=i(t,n,r);if(!k(u)){if(!O(u))throw new TypeError;r=u}}return r}function d(e,t,n){for(var r=e.length-1;r>=0;--r){var o=e[r];o(t,n)}}function h(e,t,n){var r=q.get(e);if(!r){if(!n)return void 0;r=new S,q.set(e,r)}var o=r.get(t);if(!o){if(!n)return void 0;o=new S,r.set(t,o)}return o}function y(e,t,n){var r=v(e,t,n);if(r)return!0;var o=x(t);return null!==o?y(e,o,n):!1}function v(e,t,n){var r=h(t,n,!1);return void 0===r?!1:Boolean(r.has(e))}function g(e,t,n){var r=v(e,t,n);if(r)return m(e,t,n);var o=x(t);return null!==o?g(e,o,n):void 0}function m(e,t,n){var r=h(t,n,!1);return void 0===r?void 0:r.get(e)}function w(e,t,n,r){var o=h(n,r,!0);o.set(e,t)}function b(e,t){var n=_(e,t),r=x(e);if(null===r)return n;var o=b(r,t);if(o.length<=0)return n;if(n.length<=0)return o;for(var i=new F,u=[],a=0;a=0?(this._cache=e,!0):!1},get:function(e){var t=this._find(e);return t>=0?(this._cache=e,this._values[t]):void 0},set:function(e,t){return this["delete"](e),this._keys.push(e),this._values.push(t),this._cache=e,this},"delete":function(e){var n=this._find(e);return n>=0?(this._keys.splice(n,1),this._values.splice(n,1),this._cache=t,!0):!1},clear:function(){this._keys.length=0,this._values.length=0,this._cache=t},forEach:function(e,t){for(var n=this.size,r=0;n>r;++r){var o=this._keys[r],i=this._values[r];this._cache=o,e.call(this,i,o,this)}},_find:function(e){for(var t=this._keys,n=t.length,r=0;n>r;++r)if(t[r]===e)return r;return-1}},e}function A(){function e(){this._map=new S}return e.prototype={get size(){return this._map.length},has:function(e){return this._map.has(e)},add:function(e){return this._map.set(e,e),this},"delete":function(e){return this._map["delete"](e)},clear:function(){this._map.clear()},forEach:function(e,t){this._map.forEach(e,t)}},e}function M(){function e(){this._key=o()}function t(e,t){for(var n=0;t>n;++n)e[n]=255*Math.random()|0}function n(e){if(s){var n=s.randomBytes(e);return n}if("function"==typeof Uint8Array){var n=new Uint8Array(e);return"undefined"!=typeof crypto?crypto.getRandomValues(n):"undefined"!=typeof msCrypto?msCrypto.getRandomValues(n):t(n,e),n}var n=new Array(e);return t(n,e),n}function r(){var e=n(u);e[6]=79&e[6]|64,e[8]=191&e[8]|128;for(var t="",r=0;u>r;++r){var o=e[r];(4===r||6===r||8===r)&&(t+="-"),16>o&&(t+="0"),t+=o.toString(16).toLowerCase()}return t}function o(){var e;do e="@@WeakMap@@"+r();while(c.call(f,e));return f[e]=!0,e}function i(e,t){if(!c.call(e,p)){if(!t)return void 0;Object.defineProperty(e,p,{value:Object.create(null)})}return e[p]}var u=16,a="undefined"!=typeof global&&"[object process]"===Object.prototype.toString.call(global.process),s=a&&require("crypto"),c=Object.prototype.hasOwnProperty,f={},p=o();return e.prototype={has:function(e){var t=i(e,!1);return t?this._key in t:!1},get:function(e){var t=i(e,!1);return t?t[this._key]:void 0},set:function(e,t){var n=i(e,!0);return n[this._key]=t,this},"delete":function(e){var t=i(e,!1);return t&&this._key in t?delete t[this._key]:!1},clear:function(){this._key=o()}},e}var L=Object.getPrototypeOf(Function),S="function"==typeof Map?Map:z(),F="function"==typeof Set?Set:A(),C="function"==typeof WeakMap?WeakMap:M(),q=new C;e.decorate=t,e.metadata=n,e.defineMetadata=r,e.hasMetadata=o,e.hasOwnMetadata=i,e.getMetadata=u,e.getOwnMetadata=a,e.getMetadataKeys=s,e.getOwnMetadataKeys=c,e.deleteMetadata=f,function(t){if("undefined"!=typeof t.Reflect){if(t.Reflect!==e)for(var n in e)t.Reflect[n]=e[n]}else t.Reflect=e}("undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope?self:"undefined"!=typeof global?global:Function("return this;")())}(Reflect||(Reflect={})); \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/accessible/libs/es6-shim.min.js b/backend/_pv_1_3_5/static/blockly/accessible/libs/es6-shim.min.js deleted file mode 100755 index 9a11646fc..000000000 --- a/backend/_pv_1_3_5/static/blockly/accessible/libs/es6-shim.min.js +++ /dev/null @@ -1,12 +0,0 @@ -/*! - * https://github.com/paulmillr/es6-shim - * @license es6-shim Copyright 2013-2016 by Paul Miller (http://paulmillr.com) - * and contributors, MIT License - * es6-shim: v0.35.1 - * see https://github.com/paulmillr/es6-shim/blob/0.35.1/LICENSE - * Details and documentation: - * https://github.com/paulmillr/es6-shim/ - */ -(function(e,t){if(typeof define==="function"&&define.amd){define(t)}else if(typeof exports==="object"){module.exports=t()}else{e.returnExports=t()}})(this,function(){"use strict";var e=Function.call.bind(Function.apply);var t=Function.call.bind(Function.call);var r=Array.isArray;var n=Object.keys;var o=function notThunker(t){return function notThunk(){return!e(t,this,arguments)}};var i=function(e){try{e();return false}catch(t){return true}};var a=function valueOrFalseIfThrows(e){try{return e()}catch(t){return false}};var u=o(i);var f=function(){return!i(function(){Object.defineProperty({},"x",{get:function(){}})})};var s=!!Object.defineProperty&&f();var c=function foo(){}.name==="foo";var l=Function.call.bind(Array.prototype.forEach);var p=Function.call.bind(Array.prototype.reduce);var v=Function.call.bind(Array.prototype.filter);var y=Function.call.bind(Array.prototype.some);var h=function(e,t,r,n){if(!n&&t in e){return}if(s){Object.defineProperty(e,t,{configurable:true,enumerable:false,writable:true,value:r})}else{e[t]=r}};var b=function(e,t,r){l(n(t),function(n){var o=t[n];h(e,n,o,!!r)})};var g=Function.call.bind(Object.prototype.toString);var d=typeof/abc/==="function"?function IsCallableSlow(e){return typeof e==="function"&&g(e)==="[object Function]"}:function IsCallableFast(e){return typeof e==="function"};var O={getter:function(e,t,r){if(!s){throw new TypeError("getters require true ES5 support")}Object.defineProperty(e,t,{configurable:true,enumerable:false,get:r})},proxy:function(e,t,r){if(!s){throw new TypeError("getters require true ES5 support")}var n=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,{configurable:n.configurable,enumerable:n.enumerable,get:function getKey(){return e[t]},set:function setKey(r){e[t]=r}})},redefine:function(e,t,r){if(s){var n=Object.getOwnPropertyDescriptor(e,t);n.value=r;Object.defineProperty(e,t,n)}else{e[t]=r}},defineByDescriptor:function(e,t,r){if(s){Object.defineProperty(e,t,r)}else if("value"in r){e[t]=r.value}},preserveToString:function(e,t){if(t&&d(t.toString)){h(e,"toString",t.toString.bind(t),true)}}};var m=Object.create||function(e,t){var r=function Prototype(){};r.prototype=e;var o=new r;if(typeof t!=="undefined"){n(t).forEach(function(e){O.defineByDescriptor(o,e,t[e])})}return o};var w=function(e,t){if(!Object.setPrototypeOf){return false}return a(function(){var r=function Subclass(t){var r=new e(t);Object.setPrototypeOf(r,Subclass.prototype);return r};Object.setPrototypeOf(r,e);r.prototype=m(e.prototype,{constructor:{value:r}});return t(r)})};var j=function(){if(typeof self!=="undefined"){return self}if(typeof window!=="undefined"){return window}if(typeof global!=="undefined"){return global}throw new Error("unable to locate global object")};var S=j();var T=S.isFinite;var I=Function.call.bind(String.prototype.indexOf);var E=Function.apply.bind(Array.prototype.indexOf);var P=Function.call.bind(Array.prototype.concat);var C=Function.call.bind(String.prototype.slice);var M=Function.call.bind(Array.prototype.push);var x=Function.apply.bind(Array.prototype.push);var N=Function.call.bind(Array.prototype.shift);var A=Math.max;var R=Math.min;var _=Math.floor;var k=Math.abs;var F=Math.exp;var L=Math.log;var D=Math.sqrt;var z=Function.call.bind(Object.prototype.hasOwnProperty);var q;var W=function(){};var G=S.Symbol||{};var H=G.species||"@@species";var V=Number.isNaN||function isNaN(e){return e!==e};var B=Number.isFinite||function isFinite(e){return typeof e==="number"&&T(e)};var $=d(Math.sign)?Math.sign:function sign(e){var t=Number(e);if(t===0){return t}if(V(t)){return t}return t<0?-1:1};var U=function isArguments(e){return g(e)==="[object Arguments]"};var J=function isArguments(e){return e!==null&&typeof e==="object"&&typeof e.length==="number"&&e.length>=0&&g(e)!=="[object Array]"&&g(e.callee)==="[object Function]"};var X=U(arguments)?U:J;var K={primitive:function(e){return e===null||typeof e!=="function"&&typeof e!=="object"},string:function(e){return g(e)==="[object String]"},regex:function(e){return g(e)==="[object RegExp]"},symbol:function(e){return typeof S.Symbol==="function"&&typeof e==="symbol"}};var Z=function overrideNative(e,t,r){var n=e[t];h(e,t,r,true);O.preserveToString(e[t],n)};var Y=typeof G==="function"&&typeof G["for"]==="function"&&K.symbol(G());var Q=K.symbol(G.iterator)?G.iterator:"_es6-shim iterator_";if(S.Set&&typeof(new S.Set)["@@iterator"]==="function"){Q="@@iterator"}if(!S.Reflect){h(S,"Reflect",{},true)}var ee=S.Reflect;var te=String;var re={Call:function Call(t,r){var n=arguments.length>2?arguments[2]:[];if(!re.IsCallable(t)){throw new TypeError(t+" is not a function")}return e(t,r,n)},RequireObjectCoercible:function(e,t){if(e==null){throw new TypeError(t||"Cannot call method on "+e)}return e},TypeIsObject:function(e){if(e===void 0||e===null||e===true||e===false){return false}return typeof e==="function"||typeof e==="object"},ToObject:function(e,t){return Object(re.RequireObjectCoercible(e,t))},IsCallable:d,IsConstructor:function(e){return re.IsCallable(e)},ToInt32:function(e){return re.ToNumber(e)>>0},ToUint32:function(e){return re.ToNumber(e)>>>0},ToNumber:function(e){if(g(e)==="[object Symbol]"){throw new TypeError("Cannot convert a Symbol value to a number")}return+e},ToInteger:function(e){var t=re.ToNumber(e);if(V(t)){return 0}if(t===0||!B(t)){return t}return(t>0?1:-1)*_(k(t))},ToLength:function(e){var t=re.ToInteger(e);if(t<=0){return 0}if(t>Number.MAX_SAFE_INTEGER){return Number.MAX_SAFE_INTEGER}return t},SameValue:function(e,t){if(e===t){if(e===0){return 1/e===1/t}return true}return V(e)&&V(t)},SameValueZero:function(e,t){return e===t||V(e)&&V(t)},IsIterable:function(e){return re.TypeIsObject(e)&&(typeof e[Q]!=="undefined"||X(e))},GetIterator:function(e){if(X(e)){return new q(e,"value")}var t=re.GetMethod(e,Q);if(!re.IsCallable(t)){throw new TypeError("value is not an iterable")}var r=re.Call(t,e);if(!re.TypeIsObject(r)){throw new TypeError("bad iterator")}return r},GetMethod:function(e,t){var r=re.ToObject(e)[t];if(r===void 0||r===null){return void 0}if(!re.IsCallable(r)){throw new TypeError("Method not callable: "+t)}return r},IteratorComplete:function(e){return!!e.done},IteratorClose:function(e,t){var r=re.GetMethod(e,"return");if(r===void 0){return}var n,o;try{n=re.Call(r,e)}catch(i){o=i}if(t){return}if(o){throw o}if(!re.TypeIsObject(n)){throw new TypeError("Iterator's return method returned a non-object.")}},IteratorNext:function(e){var t=arguments.length>1?e.next(arguments[1]):e.next();if(!re.TypeIsObject(t)){throw new TypeError("bad iterator")}return t},IteratorStep:function(e){var t=re.IteratorNext(e);var r=re.IteratorComplete(t);return r?false:t},Construct:function(e,t,r,n){var o=typeof r==="undefined"?e:r;if(!n&&ee.construct){return ee.construct(e,t,o)}var i=o.prototype;if(!re.TypeIsObject(i)){i=Object.prototype}var a=m(i);var u=re.Call(e,a,t);return re.TypeIsObject(u)?u:a},SpeciesConstructor:function(e,t){var r=e.constructor;if(r===void 0){return t}if(!re.TypeIsObject(r)){throw new TypeError("Bad constructor")}var n=r[H];if(n===void 0||n===null){return t}if(!re.IsConstructor(n)){throw new TypeError("Bad @@species")}return n},CreateHTML:function(e,t,r,n){var o=re.ToString(e);var i="<"+t;if(r!==""){var a=re.ToString(n);var u=a.replace(/"/g,""");i+=" "+r+'="'+u+'"'}var f=i+">";var s=f+o;return s+""},IsRegExp:function IsRegExp(e){if(!re.TypeIsObject(e)){return false}var t=e[G.match];if(typeof t!=="undefined"){return!!t}return K.regex(e)},ToString:function ToString(e){return te(e)}};if(s&&Y){var ne=function defineWellKnownSymbol(e){if(K.symbol(G[e])){return G[e]}var t=G["for"]("Symbol."+e);Object.defineProperty(G,e,{configurable:false,enumerable:false,writable:false,value:t});return t};if(!K.symbol(G.search)){var oe=ne("search");var ie=String.prototype.search;h(RegExp.prototype,oe,function search(e){return re.Call(ie,e,[this])});var ae=function search(e){var t=re.RequireObjectCoercible(this);if(e!==null&&typeof e!=="undefined"){var r=re.GetMethod(e,oe);if(typeof r!=="undefined"){return re.Call(r,e,[t])}}return re.Call(ie,t,[re.ToString(e)])};Z(String.prototype,"search",ae)}if(!K.symbol(G.replace)){var ue=ne("replace");var fe=String.prototype.replace;h(RegExp.prototype,ue,function replace(e,t){return re.Call(fe,e,[this,t])});var se=function replace(e,t){var r=re.RequireObjectCoercible(this);if(e!==null&&typeof e!=="undefined"){var n=re.GetMethod(e,ue);if(typeof n!=="undefined"){return re.Call(n,e,[r,t])}}return re.Call(fe,r,[re.ToString(e),t])};Z(String.prototype,"replace",se)}if(!K.symbol(G.split)){var ce=ne("split");var le=String.prototype.split;h(RegExp.prototype,ce,function split(e,t){return re.Call(le,e,[this,t])});var pe=function split(e,t){var r=re.RequireObjectCoercible(this);if(e!==null&&typeof e!=="undefined"){var n=re.GetMethod(e,ce);if(typeof n!=="undefined"){return re.Call(n,e,[r,t])}}return re.Call(le,r,[re.ToString(e),t])};Z(String.prototype,"split",pe)}var ve=K.symbol(G.match);var ye=ve&&function(){var e={};e[G.match]=function(){return 42};return"a".match(e)!==42}();if(!ve||ye){var he=ne("match");var be=String.prototype.match;h(RegExp.prototype,he,function match(e){return re.Call(be,e,[this])});var ge=function match(e){var t=re.RequireObjectCoercible(this);if(e!==null&&typeof e!=="undefined"){var r=re.GetMethod(e,he);if(typeof r!=="undefined"){return re.Call(r,e,[t])}}return re.Call(be,t,[re.ToString(e)])};Z(String.prototype,"match",ge)}}var de=function wrapConstructor(e,t,r){O.preserveToString(t,e);if(Object.setPrototypeOf){Object.setPrototypeOf(e,t)}if(s){l(Object.getOwnPropertyNames(e),function(n){if(n in W||r[n]){return}O.proxy(e,n,t)})}else{l(Object.keys(e),function(n){if(n in W||r[n]){return}t[n]=e[n]})}t.prototype=e.prototype;O.redefine(e.prototype,"constructor",t)};var Oe=function(){return this};var me=function(e){if(s&&!z(e,H)){O.getter(e,H,Oe)}};var we=function(e,t){var r=t||function iterator(){return this};h(e,Q,r);if(!e[Q]&&K.symbol(Q)){e[Q]=r}};var je=function createDataProperty(e,t,r){if(s){Object.defineProperty(e,t,{configurable:true,enumerable:true,writable:true,value:r})}else{e[t]=r}};var Se=function createDataPropertyOrThrow(e,t,r){je(e,t,r);if(!re.SameValue(e[t],r)){throw new TypeError("property is nonconfigurable")}};var Te=function(e,t,r,n){if(!re.TypeIsObject(e)){throw new TypeError("Constructor requires `new`: "+t.name)}var o=t.prototype;if(!re.TypeIsObject(o)){o=r}var i=m(o);for(var a in n){if(z(n,a)){var u=n[a];h(i,a,u,true)}}return i};if(String.fromCodePoint&&String.fromCodePoint.length!==1){var Ie=String.fromCodePoint;Z(String,"fromCodePoint",function fromCodePoint(e){return re.Call(Ie,this,arguments)})}var Ee={fromCodePoint:function fromCodePoint(e){var t=[];var r;for(var n=0,o=arguments.length;n1114111){throw new RangeError("Invalid code point "+r)}if(r<65536){M(t,String.fromCharCode(r))}else{r-=65536;M(t,String.fromCharCode((r>>10)+55296));M(t,String.fromCharCode(r%1024+56320))}}return t.join("")},raw:function raw(e){var t=re.ToObject(e,"bad callSite");var r=re.ToObject(t.raw,"bad raw value");var n=r.length;var o=re.ToLength(n);if(o<=0){return""}var i=[];var a=0;var u,f,s,c;while(a=o){break}f=a+1=Ce){throw new RangeError("repeat count must be less than infinity and not overflow maximum string size")}return Pe(t,r)},startsWith:function startsWith(e){var t=re.ToString(re.RequireObjectCoercible(this));if(re.IsRegExp(e)){throw new TypeError('Cannot call method "startsWith" with a regex')}var r=re.ToString(e);var n;if(arguments.length>1){n=arguments[1]}var o=A(re.ToInteger(n),0);return C(t,o,o+r.length)===r},endsWith:function endsWith(e){var t=re.ToString(re.RequireObjectCoercible(this));if(re.IsRegExp(e)){throw new TypeError('Cannot call method "endsWith" with a regex')}var r=re.ToString(e);var n=t.length;var o;if(arguments.length>1){o=arguments[1]}var i=typeof o==="undefined"?n:re.ToInteger(o);var a=R(A(i,0),n);return C(t,a-r.length,a)===r},includes:function includes(e){if(re.IsRegExp(e)){throw new TypeError('"includes" does not accept a RegExp')}var t=re.ToString(e);var r;if(arguments.length>1){r=arguments[1]}return I(this,t,r)!==-1},codePointAt:function codePointAt(e){var t=re.ToString(re.RequireObjectCoercible(this));var r=re.ToInteger(e);var n=t.length;if(r>=0&&r56319||i){return o}var a=t.charCodeAt(r+1);if(a<56320||a>57343){return o}return(o-55296)*1024+(a-56320)+65536}}};if(String.prototype.includes&&"a".includes("a",Infinity)!==false){Z(String.prototype,"includes",Me.includes)}if(String.prototype.startsWith&&String.prototype.endsWith){var xe=i(function(){"/a/".startsWith(/a/)});var Ne=a(function(){return"abc".startsWith("a",Infinity)===false});if(!xe||!Ne){Z(String.prototype,"startsWith",Me.startsWith);Z(String.prototype,"endsWith",Me.endsWith)}}if(Y){var Ae=a(function(){var e=/a/;e[G.match]=false;return"/a/".startsWith(e)});if(!Ae){Z(String.prototype,"startsWith",Me.startsWith)}var Re=a(function(){var e=/a/;e[G.match]=false;return"/a/".endsWith(e)});if(!Re){Z(String.prototype,"endsWith",Me.endsWith)}var _e=a(function(){var e=/a/;e[G.match]=false;return"/a/".includes(e)});if(!_e){Z(String.prototype,"includes",Me.includes)}}b(String.prototype,Me);var ke=[" \n\x0B\f\r \xa0\u1680\u180e\u2000\u2001\u2002\u2003","\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028","\u2029\ufeff"].join("");var Fe=new RegExp("(^["+ke+"]+)|(["+ke+"]+$)","g");var Le=function trim(){return re.ToString(re.RequireObjectCoercible(this)).replace(Fe,"")};var De=["\x85","\u200b","\ufffe"].join("");var ze=new RegExp("["+De+"]","g");var qe=/^[\-+]0x[0-9a-f]+$/i;var We=De.trim().length!==De.length;h(String.prototype,"trim",Le,We);var Ge=function(e){return{value:e,done:arguments.length===0}};var He=function(e){re.RequireObjectCoercible(e);this._s=re.ToString(e);this._i=0};He.prototype.next=function(){var e=this._s;var t=this._i;if(typeof e==="undefined"||t>=e.length){this._s=void 0;return Ge()}var r=e.charCodeAt(t);var n,o;if(r<55296||r>56319||t+1===e.length){o=1}else{n=e.charCodeAt(t+1);o=n<56320||n>57343?1:2}this._i=t+o;return Ge(e.substr(t,o))};we(He.prototype);we(String.prototype,function(){return new He(this)});var Ve={from:function from(e){var r=this;var n;if(arguments.length>1){n=arguments[1]}var o,i;if(typeof n==="undefined"){o=false}else{if(!re.IsCallable(n)){throw new TypeError("Array.from: when provided, the second argument must be a function")}if(arguments.length>2){i=arguments[2]}o=true}var a=typeof(X(e)||re.GetMethod(e,Q))!=="undefined";var u,f,s;if(a){f=re.IsConstructor(r)?Object(new r):[];var c=re.GetIterator(e);var l,p;s=0;while(true){l=re.IteratorStep(c);if(l===false){break}p=l.value;try{if(o){p=typeof i==="undefined"?n(p,s):t(n,i,p,s)}f[s]=p}catch(v){re.IteratorClose(c,true);throw v}s+=1}u=s}else{var y=re.ToObject(e);u=re.ToLength(y.length);f=re.IsConstructor(r)?Object(new r(u)):new Array(u);var h;for(s=0;s2){f=arguments[2]}var s=typeof f==="undefined"?n:re.ToInteger(f);var c=s<0?A(n+s,0):R(s,n);var l=R(c-u,n-a);var p=1;if(u0){if(u in r){r[a]=r[u]}else{delete r[a]}u+=p;a+=p;l-=1}return r},fill:function fill(e){var t;if(arguments.length>1){t=arguments[1]}var r;if(arguments.length>2){r=arguments[2]}var n=re.ToObject(this);var o=re.ToLength(n.length);t=re.ToInteger(typeof t==="undefined"?0:t);r=re.ToInteger(typeof r==="undefined"?o:r);var i=t<0?A(o+t,0):R(t,o);var a=r<0?o+r:r;for(var u=i;u1?arguments[1]:null;for(var i=0,a;i1?arguments[1]:null;for(var i=0;i1&&typeof arguments[1]!=="undefined"){return re.Call(Ze,this,arguments)}else{return t(Ze,this,e)}})}var Ye=-(Math.pow(2,32)-1);var Qe=function(e,r){var n={length:Ye};n[r?(n.length>>>0)-1:0]=true;return a(function(){t(e,n,function(){throw new RangeError("should not reach here")},[]);return true})};if(!Qe(Array.prototype.forEach)){var et=Array.prototype.forEach;Z(Array.prototype,"forEach",function forEach(e){return re.Call(et,this.length>=0?this:[],arguments)},true)}if(!Qe(Array.prototype.map)){var tt=Array.prototype.map;Z(Array.prototype,"map",function map(e){return re.Call(tt,this.length>=0?this:[],arguments)},true)}if(!Qe(Array.prototype.filter)){var rt=Array.prototype.filter;Z(Array.prototype,"filter",function filter(e){return re.Call(rt,this.length>=0?this:[],arguments)},true)}if(!Qe(Array.prototype.some)){var nt=Array.prototype.some;Z(Array.prototype,"some",function some(e){return re.Call(nt,this.length>=0?this:[],arguments)},true)}if(!Qe(Array.prototype.every)){var ot=Array.prototype.every;Z(Array.prototype,"every",function every(e){return re.Call(ot,this.length>=0?this:[],arguments)},true)}if(!Qe(Array.prototype.reduce)){var it=Array.prototype.reduce;Z(Array.prototype,"reduce",function reduce(e){return re.Call(it,this.length>=0?this:[],arguments)},true)}if(!Qe(Array.prototype.reduceRight,true)){var at=Array.prototype.reduceRight;Z(Array.prototype,"reduceRight",function reduceRight(e){return re.Call(at,this.length>=0?this:[],arguments)},true)}var ut=Number("0o10")!==8;var ft=Number("0b10")!==2;var st=y(De,function(e){return Number(e+0+e)===0});if(ut||ft||st){var ct=Number;var lt=/^0b[01]+$/i;var pt=/^0o[0-7]+$/i;var vt=lt.test.bind(lt);var yt=pt.test.bind(pt);var ht=function(e){var t;if(typeof e.valueOf==="function"){t=e.valueOf();if(K.primitive(t)){return t}}if(typeof e.toString==="function"){t=e.toString();if(K.primitive(t)){return t}}throw new TypeError("No default value")};var bt=ze.test.bind(ze);var gt=qe.test.bind(qe);var dt=function(){var e=function Number(t){var r;if(arguments.length>0){r=K.primitive(t)?t:ht(t,"number")}else{r=0}if(typeof r==="string"){r=re.Call(Le,r);if(vt(r)){r=parseInt(C(r,2),2)}else if(yt(r)){r=parseInt(C(r,2),8)}else if(bt(r)||gt(r)){r=NaN}}var n=this;var o=a(function(){ct.prototype.valueOf.call(n);return true});if(n instanceof e&&!o){return new ct(r)}return ct(r)};return e}();de(ct,dt,{});b(dt,{NaN:ct.NaN,MAX_VALUE:ct.MAX_VALUE,MIN_VALUE:ct.MIN_VALUE,NEGATIVE_INFINITY:ct.NEGATIVE_INFINITY,POSITIVE_INFINITY:ct.POSITIVE_INFINITY});Number=dt;O.redefine(S,"Number",dt)}var Ot=Math.pow(2,53)-1;b(Number,{MAX_SAFE_INTEGER:Ot,MIN_SAFE_INTEGER:-Ot,EPSILON:2.220446049250313e-16,parseInt:S.parseInt,parseFloat:S.parseFloat,isFinite:B,isInteger:function isInteger(e){return B(e)&&re.ToInteger(e)===e},isSafeInteger:function isSafeInteger(e){return Number.isInteger(e)&&k(e)<=Number.MAX_SAFE_INTEGER},isNaN:V});h(Number,"parseInt",S.parseInt,Number.parseInt!==S.parseInt);if(![,1].find(function(e,t){return t===0})){Z(Array.prototype,"find",$e.find)}if([,1].findIndex(function(e,t){return t===0})!==0){Z(Array.prototype,"findIndex",$e.findIndex)}var mt=Function.bind.call(Function.bind,Object.prototype.propertyIsEnumerable);var wt=function ensureEnumerable(e,t){if(s&&mt(e,t)){Object.defineProperty(e,t,{enumerable:false})}};var jt=function sliceArgs(){var e=Number(this);var t=arguments.length;var r=t-e;var n=new Array(r<0?0:r);for(var o=e;o1){return NaN}if(t===-1){return-Infinity}if(t===1){return Infinity}if(t===0){return t}return.5*L((1+t)/(1-t))},cbrt:function cbrt(e){var t=Number(e);if(t===0){return t}var r=t<0;var n;if(r){t=-t}if(t===Infinity){n=Infinity}else{n=F(L(t)/3);n=(t/(n*n)+2*n)/3}return r?-n:n},clz32:function clz32(e){var t=Number(e);var r=re.ToUint32(t);if(r===0){return 32}return Or?re.Call(Or,r):31-_(L(r+.5)*gr)},cosh:function cosh(e){var t=Number(e);if(t===0){return 1}if(V(t)){return NaN}if(!T(t)){return Infinity}if(t<0){t=-t}if(t>21){return F(t)/2}return(F(t)+F(-t))/2},expm1:function expm1(e){var t=Number(e);if(t===-Infinity){return-1}if(!T(t)||t===0){return t}if(k(t)>.5){return F(t)-1}var r=t;var n=0;var o=1;while(n+r!==n){n+=r;o+=1;r*=t/o}return n},hypot:function hypot(e,t){var r=0;var n=0;for(var o=0;o0?i/n*(i/n):i}}return n===Infinity?Infinity:n*D(r)},log2:function log2(e){return L(e)*gr},log10:function log10(e){return L(e)*dr},log1p:function log1p(e){var t=Number(e);if(t<-1||V(t)){return NaN}if(t===0||t===Infinity){return t}if(t===-1){return-Infinity}return 1+t-1===0?t:t*(L(1+t)/(1+t-1))},sign:$,sinh:function sinh(e){var t=Number(e);if(!T(t)||t===0){return t}if(k(t)<1){return(Math.expm1(t)-Math.expm1(-t))/2}return(F(t-1)-F(-t-1))*br/2},tanh:function tanh(e){var t=Number(e);if(V(t)||t===0){return t}if(t>=20){return 1}if(t<=-20){return-1}return(Math.expm1(t)-Math.expm1(-t))/(F(t)+F(-t))},trunc:function trunc(e){var t=Number(e);return t<0?-_(-t):_(t)},imul:function imul(e,t){var r=re.ToUint32(e);var n=re.ToUint32(t);var o=r>>>16&65535;var i=r&65535;var a=n>>>16&65535;var u=n&65535;return i*u+(o*u+i*a<<16>>>0)|0},fround:function fround(e){var t=Number(e);if(t===0||t===Infinity||t===-Infinity||V(t)){return t}var r=$(t);var n=k(t);if(nyr||V(i)){return r*Infinity}return r*i}};b(Math,mr);h(Math,"log1p",mr.log1p,Math.log1p(-1e-17)!==-1e-17);h(Math,"asinh",mr.asinh,Math.asinh(-1e7)!==-Math.asinh(1e7));h(Math,"tanh",mr.tanh,Math.tanh(-2e-17)!==-2e-17);h(Math,"acosh",mr.acosh,Math.acosh(Number.MAX_VALUE)===Infinity);h(Math,"cbrt",mr.cbrt,Math.abs(1-Math.cbrt(1e-300)/1e-100)/Number.EPSILON>8);h(Math,"sinh",mr.sinh,Math.sinh(-2e-17)!==-2e-17);var wr=Math.expm1(10);h(Math,"expm1",mr.expm1,wr>22025.465794806718||wr<22025.465794806718);var jr=Math.round;var Sr=Math.round(.5-Number.EPSILON/4)===0&&Math.round(-.5+Number.EPSILON/3.99)===1;var Tr=lr+1;var Ir=2*lr-1;var Er=[Tr,Ir].every(function(e){return Math.round(e)===e});h(Math,"round",function round(e){var t=_(e);var r=t===-1?-0:t+1;return e-t<.5?t:r},!Sr||!Er);O.preserveToString(Math.round,jr);var Pr=Math.imul;if(Math.imul(4294967295,5)!==-5){Math.imul=mr.imul;O.preserveToString(Math.imul,Pr)}if(Math.imul.length!==2){Z(Math,"imul",function imul(e,t){return re.Call(Pr,Math,arguments); -})}var Cr=function(){var e=S.setTimeout;if(typeof e!=="function"&&typeof e!=="object"){return}re.IsPromise=function(e){if(!re.TypeIsObject(e)){return false}if(typeof e._promise==="undefined"){return false}return true};var r=function(e){if(!re.IsConstructor(e)){throw new TypeError("Bad promise constructor")}var t=this;var r=function(e,r){if(t.resolve!==void 0||t.reject!==void 0){throw new TypeError("Bad Promise implementation!")}t.resolve=e;t.reject=r};t.resolve=void 0;t.reject=void 0;t.promise=new e(r);if(!(re.IsCallable(t.resolve)&&re.IsCallable(t.reject))){throw new TypeError("Bad promise constructor")}};var n;if(typeof window!=="undefined"&&re.IsCallable(window.postMessage)){n=function(){var e=[];var t="zero-timeout-message";var r=function(r){M(e,r);window.postMessage(t,"*")};var n=function(r){if(r.source===window&&r.data===t){r.stopPropagation();if(e.length===0){return}var n=N(e);n()}};window.addEventListener("message",n,true);return r}}var o=function(){var e=S.Promise;var t=e&&e.resolve&&e.resolve();return t&&function(e){return t.then(e)}};var i=re.IsCallable(S.setImmediate)?S.setImmediate:typeof process==="object"&&process.nextTick?process.nextTick:o()||(re.IsCallable(n)?n():function(t){e(t,0)});var a=function(e){return e};var u=function(e){throw e};var f=0;var s=1;var c=2;var l=0;var p=1;var v=2;var y={};var h=function(e,t,r){i(function(){g(e,t,r)})};var g=function(e,t,r){var n,o;if(t===y){return e(r)}try{n=e(r);o=t.resolve}catch(i){n=i;o=t.reject}o(n)};var d=function(e,t){var r=e._promise;var n=r.reactionLength;if(n>0){h(r.fulfillReactionHandler0,r.reactionCapability0,t);r.fulfillReactionHandler0=void 0;r.rejectReactions0=void 0;r.reactionCapability0=void 0;if(n>1){for(var o=1,i=0;o0){h(r.rejectReactionHandler0,r.reactionCapability0,t);r.fulfillReactionHandler0=void 0;r.rejectReactions0=void 0;r.reactionCapability0=void 0;if(n>1){for(var o=1,i=0;o2&&arguments[2]===y;if(b&&o===E){i=y}else{i=new r(o)}var g=re.IsCallable(e)?e:a;var d=re.IsCallable(t)?t:u;var O=n._promise;var m;if(O.state===f){if(O.reactionLength===0){O.fulfillReactionHandler0=g;O.rejectReactionHandler0=d;O.reactionCapability0=i}else{var w=3*(O.reactionLength-1);O[w+l]=g;O[w+p]=d;O[w+v]=i}O.reactionLength+=1}else if(O.state===s){m=O.result;h(g,i,m)}else if(O.state===c){m=O.result;h(d,i,m)}else{throw new TypeError("unexpected Promise state")}return i.promise}});y=new r(E);I=T.then;return E}();if(S.Promise){delete S.Promise.accept;delete S.Promise.defer;delete S.Promise.prototype.chain}if(typeof Cr==="function"){b(S,{Promise:Cr});var Mr=w(S.Promise,function(e){return e.resolve(42).then(function(){})instanceof e});var xr=!i(function(){S.Promise.reject(42).then(null,5).then(null,W)});var Nr=i(function(){S.Promise.call(3,W)});var Ar=function(e){var t=e.resolve(5);t.constructor={};var r=e.resolve(t);try{r.then(null,W).then(null,W)}catch(n){return true}return t===r}(S.Promise);var Rr=s&&function(){var e=0;var t=Object.defineProperty({},"then",{get:function(){e+=1}});Promise.resolve(t);return e===1}();var _r=function BadResolverPromise(e){var t=new Promise(e);e(3,function(){});this.then=t.then;this.constructor=BadResolverPromise};_r.prototype=Promise.prototype;_r.all=Promise.all;var kr=a(function(){return!!_r.all([1,2])});if(!Mr||!xr||!Nr||Ar||!Rr||kr){Promise=Cr;Z(S,"Promise",Cr)}if(Promise.all.length!==1){var Fr=Promise.all;Z(Promise,"all",function all(e){return re.Call(Fr,this,arguments)})}if(Promise.race.length!==1){var Lr=Promise.race;Z(Promise,"race",function race(e){return re.Call(Lr,this,arguments)})}if(Promise.resolve.length!==1){var Dr=Promise.resolve;Z(Promise,"resolve",function resolve(e){return re.Call(Dr,this,arguments)})}if(Promise.reject.length!==1){var zr=Promise.reject;Z(Promise,"reject",function reject(e){return re.Call(zr,this,arguments)})}wt(Promise,"all");wt(Promise,"race");wt(Promise,"resolve");wt(Promise,"reject");me(Promise)}var qr=function(e){var t=n(p(e,function(e,t){e[t]=true;return e},{}));return e.join(":")===t.join(":")};var Wr=qr(["z","a","bb"]);var Gr=qr(["z",1,"a","3",2]);if(s){var Hr=function fastkey(e){if(!Wr){return null}if(typeof e==="undefined"||e===null){return"^"+re.ToString(e)}else if(typeof e==="string"){return"$"+e}else if(typeof e==="number"){if(!Gr){return"n"+e}return e}else if(typeof e==="boolean"){return"b"+e}return null};var Vr=function emptyObject(){return Object.create?Object.create(null):{}};var Br=function addIterableToMap(e,n,o){if(r(o)||K.string(o)){l(o,function(e){if(!re.TypeIsObject(e)){throw new TypeError("Iterator value "+e+" is not an entry object")}n.set(e[0],e[1])})}else if(o instanceof e){t(e.prototype.forEach,o,function(e,t){n.set(t,e)})}else{var i,a;if(o!==null&&typeof o!=="undefined"){a=n.set;if(!re.IsCallable(a)){throw new TypeError("bad map")}i=re.GetIterator(o)}if(typeof i!=="undefined"){while(true){var u=re.IteratorStep(i);if(u===false){break}var f=u.value;try{if(!re.TypeIsObject(f)){throw new TypeError("Iterator value "+f+" is not an entry object")}t(a,n,f[0],f[1])}catch(s){re.IteratorClose(i,true);throw s}}}}};var $r=function addIterableToSet(e,n,o){if(r(o)||K.string(o)){l(o,function(e){n.add(e)})}else if(o instanceof e){t(e.prototype.forEach,o,function(e){n.add(e)})}else{var i,a;if(o!==null&&typeof o!=="undefined"){a=n.add;if(!re.IsCallable(a)){throw new TypeError("bad set")}i=re.GetIterator(o)}if(typeof i!=="undefined"){while(true){var u=re.IteratorStep(i);if(u===false){break}var f=u.value;try{t(a,n,f)}catch(s){re.IteratorClose(i,true);throw s}}}}};var Ur={Map:function(){var e={};var r=function MapEntry(e,t){this.key=e;this.value=t;this.next=null;this.prev=null};r.prototype.isRemoved=function isRemoved(){return this.key===e};var n=function isMap(e){return!!e._es6map};var o=function requireMapSlot(e,t){if(!re.TypeIsObject(e)||!n(e)){throw new TypeError("Method Map.prototype."+t+" called on incompatible receiver "+re.ToString(e))}};var i=function MapIterator(e,t){o(e,"[[MapIterator]]");this.head=e._head;this.i=this.head;this.kind=t};i.prototype={next:function next(){var e=this.i;var t=this.kind;var r=this.head;if(typeof this.i==="undefined"){return Ge()}while(e.isRemoved()&&e!==r){e=e.prev}var n;while(e.next!==r){e=e.next;if(!e.isRemoved()){if(t==="key"){n=e.key}else if(t==="value"){n=e.value}else{n=[e.key,e.value]}this.i=e;return Ge(n)}}this.i=void 0;return Ge()}};we(i.prototype);var a;var u=function Map(){if(!(this instanceof Map)){throw new TypeError('Constructor Map requires "new"')}if(this&&this._es6map){throw new TypeError("Bad construction")}var e=Te(this,Map,a,{_es6map:true,_head:null,_storage:Vr(),_size:0});var t=new r(null,null);t.next=t.prev=t;e._head=t;if(arguments.length>0){Br(Map,e,arguments[0])}return e};a=u.prototype;O.getter(a,"size",function(){if(typeof this._size==="undefined"){throw new TypeError("size method called on incompatible Map")}return this._size});b(a,{get:function get(e){o(this,"get");var t=Hr(e);if(t!==null){var r=this._storage[t];if(r){return r.value}else{return}}var n=this._head;var i=n;while((i=i.next)!==n){if(re.SameValueZero(i.key,e)){return i.value}}},has:function has(e){o(this,"has");var t=Hr(e);if(t!==null){return typeof this._storage[t]!=="undefined"}var r=this._head;var n=r;while((n=n.next)!==r){if(re.SameValueZero(n.key,e)){return true}}return false},set:function set(e,t){o(this,"set");var n=this._head;var i=n;var a;var u=Hr(e);if(u!==null){if(typeof this._storage[u]!=="undefined"){this._storage[u].value=t;return this}else{a=this._storage[u]=new r(e,t);i=n.prev}}while((i=i.next)!==n){if(re.SameValueZero(i.key,e)){i.value=t;return this}}a=a||new r(e,t);if(re.SameValue(-0,e)){a.key=+0}a.next=this._head;a.prev=this._head.prev;a.prev.next=a;a.next.prev=a;this._size+=1;return this},"delete":function(t){o(this,"delete");var r=this._head;var n=r;var i=Hr(t);if(i!==null){if(typeof this._storage[i]==="undefined"){return false}n=this._storage[i].prev;delete this._storage[i]}while((n=n.next)!==r){if(re.SameValueZero(n.key,t)){n.key=n.value=e;n.prev.next=n.next;n.next.prev=n.prev;this._size-=1;return true}}return false},clear:function clear(){o(this,"clear");this._size=0;this._storage=Vr();var t=this._head;var r=t;var n=r.next;while((r=n)!==t){r.key=r.value=e;n=r.next;r.next=r.prev=t}t.next=t.prev=t},keys:function keys(){o(this,"keys");return new i(this,"key")},values:function values(){o(this,"values");return new i(this,"value")},entries:function entries(){o(this,"entries");return new i(this,"key+value")},forEach:function forEach(e){o(this,"forEach");var r=arguments.length>1?arguments[1]:null;var n=this.entries();for(var i=n.next();!i.done;i=n.next()){if(r){t(e,r,i.value[1],i.value[0],this)}else{e(i.value[1],i.value[0],this)}}}});we(a,a.entries);return u}(),Set:function(){var e=function isSet(e){return e._es6set&&typeof e._storage!=="undefined"};var r=function requireSetSlot(t,r){if(!re.TypeIsObject(t)||!e(t)){throw new TypeError("Set.prototype."+r+" called on incompatible receiver "+re.ToString(t))}};var o;var i=function Set(){if(!(this instanceof Set)){throw new TypeError('Constructor Set requires "new"')}if(this&&this._es6set){throw new TypeError("Bad construction")}var e=Te(this,Set,o,{_es6set:true,"[[SetData]]":null,_storage:Vr()});if(!e._es6set){throw new TypeError("bad set")}if(arguments.length>0){$r(Set,e,arguments[0])}return e};o=i.prototype;var a=function(e){var t=e;if(t==="^null"){return null}else if(t==="^undefined"){return void 0}else{var r=t.charAt(0);if(r==="$"){return C(t,1)}else if(r==="n"){return+C(t,1)}else if(r==="b"){return t==="btrue"}}return+t};var u=function ensureMap(e){if(!e["[[SetData]]"]){var t=e["[[SetData]]"]=new Ur.Map;l(n(e._storage),function(e){var r=a(e);t.set(r,r)});e["[[SetData]]"]=t}e._storage=null};O.getter(i.prototype,"size",function(){r(this,"size");if(this._storage){return n(this._storage).length}u(this);return this["[[SetData]]"].size});b(i.prototype,{has:function has(e){r(this,"has");var t;if(this._storage&&(t=Hr(e))!==null){return!!this._storage[t]}u(this);return this["[[SetData]]"].has(e)},add:function add(e){r(this,"add");var t;if(this._storage&&(t=Hr(e))!==null){this._storage[t]=true;return this}u(this);this["[[SetData]]"].set(e,e);return this},"delete":function(e){r(this,"delete");var t;if(this._storage&&(t=Hr(e))!==null){var n=z(this._storage,t);return delete this._storage[t]&&n}u(this);return this["[[SetData]]"]["delete"](e)},clear:function clear(){r(this,"clear");if(this._storage){this._storage=Vr()}if(this["[[SetData]]"]){this["[[SetData]]"].clear()}},values:function values(){r(this,"values");u(this);return this["[[SetData]]"].values()},entries:function entries(){r(this,"entries");u(this);return this["[[SetData]]"].entries()},forEach:function forEach(e){r(this,"forEach");var n=arguments.length>1?arguments[1]:null;var o=this;u(o);this["[[SetData]]"].forEach(function(r,i){if(n){t(e,n,i,i,o)}else{e(i,i,o)}})}});h(i.prototype,"keys",i.prototype.values,true);we(i.prototype,i.prototype.values);return i}()};if(S.Map||S.Set){var Jr=a(function(){return new Map([[1,2]]).get(1)===2});if(!Jr){var Xr=S.Map;S.Map=function Map(){if(!(this instanceof Map)){throw new TypeError('Constructor Map requires "new"')}var e=new Xr;if(arguments.length>0){Br(Map,e,arguments[0])}delete e.constructor;Object.setPrototypeOf(e,S.Map.prototype);return e};S.Map.prototype=m(Xr.prototype);h(S.Map.prototype,"constructor",S.Map,true);O.preserveToString(S.Map,Xr)}var Kr=new Map;var Zr=function(){var e=new Map([[1,0],[2,0],[3,0],[4,0]]);e.set(-0,e);return e.get(0)===e&&e.get(-0)===e&&e.has(0)&&e.has(-0)}();var Yr=Kr.set(1,2)===Kr;if(!Zr||!Yr){var Qr=Map.prototype.set;Z(Map.prototype,"set",function set(e,r){t(Qr,this,e===0?0:e,r);return this})}if(!Zr){var en=Map.prototype.get;var tn=Map.prototype.has;b(Map.prototype,{get:function get(e){return t(en,this,e===0?0:e)},has:function has(e){return t(tn,this,e===0?0:e)}},true);O.preserveToString(Map.prototype.get,en);O.preserveToString(Map.prototype.has,tn)}var rn=new Set;var nn=function(e){e["delete"](0);e.add(-0);return!e.has(0)}(rn);var on=rn.add(1)===rn;if(!nn||!on){var an=Set.prototype.add;Set.prototype.add=function add(e){t(an,this,e===0?0:e);return this};O.preserveToString(Set.prototype.add,an)}if(!nn){var un=Set.prototype.has;Set.prototype.has=function has(e){return t(un,this,e===0?0:e)};O.preserveToString(Set.prototype.has,un);var fn=Set.prototype["delete"];Set.prototype["delete"]=function SetDelete(e){return t(fn,this,e===0?0:e)};O.preserveToString(Set.prototype["delete"],fn)}var sn=w(S.Map,function(e){var t=new e([]);t.set(42,42);return t instanceof e});var cn=Object.setPrototypeOf&&!sn;var ln=function(){try{return!(S.Map()instanceof S.Map)}catch(e){return e instanceof TypeError}}();if(S.Map.length!==0||cn||!ln){var pn=S.Map;S.Map=function Map(){if(!(this instanceof Map)){throw new TypeError('Constructor Map requires "new"')}var e=new pn;if(arguments.length>0){Br(Map,e,arguments[0])}delete e.constructor;Object.setPrototypeOf(e,Map.prototype);return e};S.Map.prototype=pn.prototype;h(S.Map.prototype,"constructor",S.Map,true);O.preserveToString(S.Map,pn)}var vn=w(S.Set,function(e){var t=new e([]);t.add(42,42);return t instanceof e});var yn=Object.setPrototypeOf&&!vn;var hn=function(){try{return!(S.Set()instanceof S.Set)}catch(e){return e instanceof TypeError}}();if(S.Set.length!==0||yn||!hn){var bn=S.Set;S.Set=function Set(){if(!(this instanceof Set)){throw new TypeError('Constructor Set requires "new"')}var e=new bn;if(arguments.length>0){$r(Set,e,arguments[0])}delete e.constructor;Object.setPrototypeOf(e,Set.prototype);return e};S.Set.prototype=bn.prototype;h(S.Set.prototype,"constructor",S.Set,true);O.preserveToString(S.Set,bn)}var gn=new S.Map;var dn=!a(function(){return gn.keys().next().done});if(typeof S.Map.prototype.clear!=="function"||(new S.Set).size!==0||gn.size!==0||typeof S.Map.prototype.keys!=="function"||typeof S.Set.prototype.keys!=="function"||typeof S.Map.prototype.forEach!=="function"||typeof S.Set.prototype.forEach!=="function"||u(S.Map)||u(S.Set)||typeof gn.keys().next!=="function"||dn||!sn){b(S,{Map:Ur.Map,Set:Ur.Set},true)}if(S.Set.prototype.keys!==S.Set.prototype.values){h(S.Set.prototype,"keys",S.Set.prototype.values,true)}we(Object.getPrototypeOf((new S.Map).keys()));we(Object.getPrototypeOf((new S.Set).keys()));if(c&&S.Set.prototype.has.name!=="has"){var On=S.Set.prototype.has;Z(S.Set.prototype,"has",function has(e){return t(On,this,e)})}}b(S,Ur);me(S.Map);me(S.Set)}var mn=function throwUnlessTargetIsObject(e){if(!re.TypeIsObject(e)){throw new TypeError("target must be an object")}};var wn={apply:function apply(){return re.Call(re.Call,null,arguments)},construct:function construct(e,t){if(!re.IsConstructor(e)){throw new TypeError("First argument must be a constructor.")}var r=arguments.length>2?arguments[2]:e;if(!re.IsConstructor(r)){throw new TypeError("new.target must be a constructor.")}return re.Construct(e,t,r,"internal")},deleteProperty:function deleteProperty(e,t){mn(e);if(s){var r=Object.getOwnPropertyDescriptor(e,t);if(r&&!r.configurable){return false}}return delete e[t]},has:function has(e,t){mn(e);return t in e}};if(Object.getOwnPropertyNames){Object.assign(wn,{ownKeys:function ownKeys(e){mn(e);var t=Object.getOwnPropertyNames(e);if(re.IsCallable(Object.getOwnPropertySymbols)){x(t,Object.getOwnPropertySymbols(e))}return t}})}var jn=function ConvertExceptionToBoolean(e){return!i(e)};if(Object.preventExtensions){Object.assign(wn,{isExtensible:function isExtensible(e){mn(e);return Object.isExtensible(e)},preventExtensions:function preventExtensions(e){mn(e);return jn(function(){Object.preventExtensions(e)})}})}if(s){var Sn=function get(e,t,r){var n=Object.getOwnPropertyDescriptor(e,t);if(!n){var o=Object.getPrototypeOf(e);if(o===null){return void 0}return Sn(o,t,r)}if("value"in n){return n.value}if(n.get){return re.Call(n.get,r)}return void 0};var Tn=function set(e,r,n,o){var i=Object.getOwnPropertyDescriptor(e,r);if(!i){var a=Object.getPrototypeOf(e);if(a!==null){return Tn(a,r,n,o)}i={value:void 0,writable:true,enumerable:true,configurable:true}}if("value"in i){if(!i.writable){return false}if(!re.TypeIsObject(o)){return false}var u=Object.getOwnPropertyDescriptor(o,r);if(u){return ee.defineProperty(o,r,{value:n})}else{return ee.defineProperty(o,r,{value:n,writable:true,enumerable:true,configurable:true})}}if(i.set){t(i.set,o,n);return true}return false};Object.assign(wn,{defineProperty:function defineProperty(e,t,r){mn(e);return jn(function(){Object.defineProperty(e,t,r)})},getOwnPropertyDescriptor:function getOwnPropertyDescriptor(e,t){mn(e);return Object.getOwnPropertyDescriptor(e,t)},get:function get(e,t){mn(e);var r=arguments.length>2?arguments[2]:e;return Sn(e,t,r)},set:function set(e,t,r){mn(e);var n=arguments.length>3?arguments[3]:e;return Tn(e,t,r,n)}})}if(Object.getPrototypeOf){var In=Object.getPrototypeOf;wn.getPrototypeOf=function getPrototypeOf(e){mn(e);return In(e)}}if(Object.setPrototypeOf&&wn.getPrototypeOf){var En=function(e,t){var r=t;while(r){if(e===r){return true}r=wn.getPrototypeOf(r)}return false};Object.assign(wn,{setPrototypeOf:function setPrototypeOf(e,t){mn(e);if(t!==null&&!re.TypeIsObject(t)){throw new TypeError("proto must be an object or null")}if(t===ee.getPrototypeOf(e)){return true}if(ee.isExtensible&&!ee.isExtensible(e)){return false}if(En(e,t)){return false}Object.setPrototypeOf(e,t);return true}})}var Pn=function(e,t){if(!re.IsCallable(S.Reflect[e])){h(S.Reflect,e,t)}else{var r=a(function(){S.Reflect[e](1);S.Reflect[e](NaN);S.Reflect[e](true);return true});if(r){Z(S.Reflect,e,t)}}};Object.keys(wn).forEach(function(e){Pn(e,wn[e])});var Cn=S.Reflect.getPrototypeOf;if(c&&Cn&&Cn.name!=="getPrototypeOf"){Z(S.Reflect,"getPrototypeOf",function getPrototypeOf(e){return t(Cn,S.Reflect,e)})}if(S.Reflect.setPrototypeOf){if(a(function(){S.Reflect.setPrototypeOf(1,{});return true})){Z(S.Reflect,"setPrototypeOf",wn.setPrototypeOf)}}if(S.Reflect.defineProperty){if(!a(function(){var e=!S.Reflect.defineProperty(1,"test",{value:1});var t=typeof Object.preventExtensions!=="function"||!S.Reflect.defineProperty(Object.preventExtensions({}),"test",{});return e&&t})){Z(S.Reflect,"defineProperty",wn.defineProperty)}}if(S.Reflect.construct){if(!a(function(){var e=function F(){};return S.Reflect.construct(function(){},[],e)instanceof e})){Z(S.Reflect,"construct",wn.construct)}}if(String(new Date(NaN))!=="Invalid Date"){var Mn=Date.prototype.toString;var xn=function toString(){var e=+this;if(e!==e){return"Invalid Date"}return re.Call(Mn,this)};Z(Date.prototype,"toString",xn)}var Nn={anchor:function anchor(e){return re.CreateHTML(this,"a","name",e)},big:function big(){return re.CreateHTML(this,"big","","")},blink:function blink(){return re.CreateHTML(this,"blink","","")},bold:function bold(){return re.CreateHTML(this,"b","","")},fixed:function fixed(){return re.CreateHTML(this,"tt","","")},fontcolor:function fontcolor(e){return re.CreateHTML(this,"font","color",e)},fontsize:function fontsize(e){return re.CreateHTML(this,"font","size",e)},italics:function italics(){return re.CreateHTML(this,"i","","")},link:function link(e){return re.CreateHTML(this,"a","href",e)},small:function small(){return re.CreateHTML(this,"small","","")},strike:function strike(){return re.CreateHTML(this,"strike","","")},sub:function sub(){return re.CreateHTML(this,"sub","","")},sup:function sub(){return re.CreateHTML(this,"sup","","")}};l(Object.keys(Nn),function(e){var r=String.prototype[e];var n=false;if(re.IsCallable(r)){var o=t(r,"",' " ');var i=P([],o.match(/"/g)).length;n=o!==o.toLowerCase()||i>2}else{n=true}if(n){Z(String.prototype,e,Nn[e])}});var An=function(){if(!Y){return false}var e=typeof JSON==="object"&&typeof JSON.stringify==="function"?JSON.stringify:null;if(!e){return false}if(typeof e(G())!=="undefined"){return true}if(e([G()])!=="[null]"){return true}var t={a:G()};t[G()]=true;if(e(t)!=="{}"){return true}return false}();var Rn=a(function(){if(!Y){return true}return JSON.stringify(Object(G()))==="{}"&&JSON.stringify([Object(G())])==="[{}]"});if(An||!Rn){var _n=JSON.stringify;Z(JSON,"stringify",function stringify(e){if(typeof e==="symbol"){return}var n;if(arguments.length>1){n=arguments[1]}var o=[e];if(!r(n)){var i=re.IsCallable(n)?n:null;var a=function(e,r){var n=i?t(i,this,e,r):r;if(typeof n!=="symbol"){if(K.symbol(n)){return St({})(n)}else{return n}}};o.push(a)}else{o.push(n)}if(arguments.length>2){o.push(arguments[2])}return _n.apply(this,o)})}return S}); -//# sourceMappingURL=es6-shim.map diff --git a/backend/_pv_1_3_5/static/blockly/accessible/media/accessible.css b/backend/_pv_1_3_5/static/blockly/accessible/media/accessible.css deleted file mode 100755 index 5a68527ca..000000000 --- a/backend/_pv_1_3_5/static/blockly/accessible/media/accessible.css +++ /dev/null @@ -1,12 +0,0 @@ -.blocklyTable { - vertical-align: top; -} -.blocklyTree .blocklyActiveDescendant > label, -.blocklyTree .blocklyActiveDescendant > div > label, -.blocklyActiveDescendant > button, -.blocklyActiveDescendant > input, -.blocklyActiveDescendant > blockly-field > label, -.blocklyActiveDescendant > blockly-field > input, -.blocklyActiveDescendant > blockly-field > div > label { - outline: 2px dotted #00f; -} diff --git a/backend/_pv_1_3_5/static/blockly/accessible/media/click.mp3 b/backend/_pv_1_3_5/static/blockly/accessible/media/click.mp3 deleted file mode 100755 index 4534b0ddca7424a441a5992f78d7defb7ea01834..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2304 zcmeZtF=l1}0!F_O&k!RZLl%ew@(T(w^U@W3GE)@t(|}Y#QesZ7LU2iDa&}0hYY5S_413-^&w3C0*Djhb23xn^V5J7*a`8)ASWpJ=BH$)Wu~SmB<7_k z6s6{7Rsh*al?v|p`RO^S3Z8k%djEe z|8W7JU6wwMzOKf4mKH^fXJM`pX;9&~;>5tv0CLC9h9lfCiIGA>B1ot=-=`$KfxBg% z!2xvxQN{%u1ZVItq(kKX|Nq&bz`W(yxy6|b2}}%!60c^lW>9qJNYT78cK7X1G`=?E8tc&Ve+j=v1Tvih0*@(UOg z)*t^hr9ta#q~@}-;m&2rD@0cDT)bT*!L`fq5ld(5;h8Pk2Y6UQCK#ON^K*&Q;bhss z9BrK3;2d=3SdT^1nUz-!lTNNk@Mmq?@6Ud%@A{J`(*oW^&e)mc81_B)Si14_drS7G zzq-2c_uuE{Khk^7tTS$rj-Ikr)v)XCym_1Z3znXKSJt+4_U@f=e}9{n-@o_q*!$1_ zEB<}`ef{>-}am~&Ni$6GlPLakVQmBho5g+#P@|YVu44#{>+Kski1s6Sk9!K zfj8soyG^C-EUk(PA#6;{Q6^WIn`c~D`^7+Hh82hGUKz=t+05gThWnaIbh@zJJ~KkT2if{=by{ zTQ@IoW{I(Pu>SSez~uDu?f?G|PglO@n5t)*8uVuWesE08RaG}_le~O;$&!upuPt3# z8=v`Re&nesyE{%Tj?H`UbN#;vFNOjJhOlWaokA)e6P3DTmN+f&5Mr6SvEXOSJm;zB zK{3S7d@XXazRmOo4h9AjU^KF=ZEbV+q!+WU9HsZvvK=+^CR?=u0PulcRlXv+U&QSpI=?S zCH&&rkF9I7s}8nGoo8jOQ&`u;r3EVh^^8^xAfUf1KrvLqe1L&*2{3~xKx1eCLtxZu H^bi05jng?> diff --git a/backend/_pv_1_3_5/static/blockly/accessible/media/click.ogg b/backend/_pv_1_3_5/static/blockly/accessible/media/click.ogg deleted file mode 100755 index e8ae42a6106dadbb6861981a696b7f8b8f64c9ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4865 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 diff --git a/backend/_pv_1_3_5/static/blockly/accessible/media/delete.mp3 b/backend/_pv_1_3_5/static/blockly/accessible/media/delete.mp3 deleted file mode 100755 index 442bd9c1f4c9cee39ca9cc776c7cd594c90f2795..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3123 zcmeHJXH*m07M>&!dX=iEktT2fsh48B1PId6#Ly%{0to>Gg7l^YAtC|_JX+`=MMRMz z%|=4KfCcqIM5>~Qpi&e;ROW`Ku5}mx?vMBDy>G33W`Ad9&EEU$Z_XTRv@Q(b0CEUt zjnm;cq8u|14hsnK_YI^Vf`~!nV4SN3mNU!EF&!;!Z5$eF{&#xRLYqT*Id&|R9OOd` zG(Tc*&tbkC+rlwwSg;q_7~vBd8f1LnKtx1@W)LZa8WukCkYH%o-gs`WQe7$`+4l$5~2qp*kMsj@5D1;@IO7SNntOLC?!LRAvKcf9@ zv<~#9a;ON$-~b@t52$T}<95)t;p%n_ZwI&yoLEM7ruG)Pnns4fkO#lAk)SE^SeXF; zZ7UCz7B9tLH~v?yKN=(v=Ao(A3&8&P?V5oB77DOCAk1_{K7L_V>G{%k=1@Xx3l8dO zEQ;Xh5RJBl0zvil(`Yg2v9WKO`FktsM0UE{FSY4QEWT_XQxf{Lu#@iE>PKaz6z^1S#Kk6E| zG-kc6w!8meF>Y{bCCjCuXMue~ilz2C!X4IBS^mk%roZYV3EJ%*WEKJ4CXdY$UQ4Z)#EROyxblolH`S9mE z2QJKK*G*4-eWTyn(ffXymH0Jo*N+cx#lj%oWXLh=832^!1zpK5Gt?{Zu6~>g=Qj~g z;kv01&+284q4hmg6M7n=LU-_69`#Y6$IHWWue=~!%*zSP3s;u%z(unHZ6oA6>5wpA z0tUusc++ve)J0)^ot6*o<=*A4(6PhKg-GAljOBMKHQ4gC4?a(i7x@ucDN0>VX$46b zs_@PuxW{RY&!YHs-HH!6&(>VsY>jx?(Z1VQ#7!ci>cbIby!@Yaoay>{p&^lq}H#A~FK*Wpum_g(k9vo6T>j89*1Bax3k zbT?{hF?OPO2hY7UaB)<*`XH)mlCdl$c?$Zt#HhLHK)t*(Z)~hqV@I<0$hhCi6GisK zQqs=-E2aO0K*XV4AY z!)OJaCpY7M?urlK8Q0=@t2Y=qzcT^2a?j1DdZgooQGn>Jm3&*B3!-+(yl*41&FJb8 z%B8%lrQDQp^lfz);i~u6+0hrQ!-U4_E0AzUwT{P@C(xp^>g7$30wuI5Qm zHXns9?$9qO{c4Bl;se?U9=>zj5DZg2HdRcIS8=3SR_2nB?){D;FR_fg79G`}9cu4GN#xS_ z*Spjxg7uKy;zd=iJ1eai0tw$HESr@aaK;1VibBOdNH)79IuxFx*KgTjnc=sowdyWO zdL--2d_Pskq{g}N^Uu2^dq0TCWobt zdDo-+Bj7i)?x%kFm6xe+bkX}ZV63vAeH)8yy)9Sn`RKCQbD{H7^;pMaDv&aNv z+Z91w$7vqa(F7jXR5tS9Y%^%s3Iy|29127mmMeD7muocCUcW=X!}xolGP$F6HYPB4VL7_aI(MCd}qs6aUj^1?Gh@W3yLA@0ZwTW z)*=GR(#7yAd~pe<;oqly+u}=$xo>X5oPm`PV=M0;7|ng5ziXP)deG<5Gq{P zV8SlyRFD}Ba3lEn<>S3fCj@-K^~4@gX;D=``xW47B?H~p0+@o}Hz+)QUzwNroMxnk z)lGVO8nn%?1O%Cir7lCA5P6!OmOHWbu%2aEd}63QJr{mofy&9TTS;2wVmyFx{B`Eh m)Y*Qf`iFe0Ly8GZ08$|b00;okqjC1dfB267KmOlbfxiHkb?GSp diff --git a/backend/_pv_1_3_5/static/blockly/accessible/media/delete.ogg b/backend/_pv_1_3_5/static/blockly/accessible/media/delete.ogg deleted file mode 100755 index 67f84ac19a05075a52de49829b3a2bc17af9e29c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5731 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 diff --git a/backend/_pv_1_3_5/static/blockly/accessible/media/delete.wav b/backend/_pv_1_3_5/static/blockly/accessible/media/delete.wav deleted file mode 100755 index 18debcf96d6f76e36f295feb6de2f09dffaec1f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9164 zcmXAu2Yip$_s7qDzDa}-Dr%Jc>{XkXr6@AY+M`sB5G#loTWQP)MXjn$P^v{yVr#9^ z+N<`agpf$`eeU_c_5bRtvcAuK?mg#oKA+Dyw@pN7=+WXL9UFFN(r3`{BDqAw@L%H} zMW%N$;z%xO9?`a4BEOGl8QLnMWy2QlKhr2?#GoMq`$hLHGNi|l$QX%e*ruI7zi&G{ za!6EX zIe74Z?*FaCzkMTzb?-53*x;Dqk-dww7~H#GpMHGPBf58yn8-o>M)Q5o*dk$r2lpKq zStKI5S4DQ#s7+%(-d448l`0~=dkpW9Tuh{>Jk==s!uFI);v+-#qW&OvYgSyeKvfpSiNzigSQ0M7e{Yr*QV;L-YOb2tp95aXHv^Lgknr@%!TS*lw z*QBk~kf}0K{wJSGQPbP`)A4ckn_f;a&l}G`pPQZ!JTuJ;ov7BXaED|jW{mcJ@~P**n7iD4&>l^4i4v4E2rl+2d*CRFKE&wH@8Z-binV_pG<4+t8NL4jQ9DQpp54 zo6Iz+Wwtw)ozNTz2U%T3Qn1dkHtS zq?s*YE9*^ZWq#H{BdMr~uGkYc!8WuN?R`5{HW`o8*IDH>acYo@w7d(Tdn7ADmkH_OaX zGt%sl-V$W0nY8Yr9bfWARQ!Qq@nrFERaK5T4(96GTd}AyCj+%?6kk= z6Md$;^m83AwVjd1N2}Q{^tfD?cbceob*}hJG3}>6Ykx8)a+UXfVID}PmN2!PeUgnc z6_9Z02)=JvuidGiXq5Jpn>tvtkc}{1poOKB+yEJQrJMP{SeU0Uft3kR|m-$TU z6T_ieU2;oR>7?E4HG4pxNupfUe7x(n{I2nuF1<`ka~7QKkqIC#FFPA;3YqJ=&34jo zlW0z`pCOt_L`txuS$f8PrDvo#NZux;rMW)U?J`cfa;ioWDq%882ieV3X*E+@M91)s zmHM{~6xYV+J&88|>O?zC|BwZ;fxo?w2y;YcOI~RpIb}2TAEG<;kk*zeri}cif9ra( z^&7FQDAOf7Yd*J++$y$<+$CdKar(`=G0WazepI47Mz&jO#e zeg)pSPs1}x_(f>e)C(yGeRg~h?OQqRSw^(~S6N%AefLS`K2I;tK0V|4!E8?}oH|pp zd1~98Qp0zK^FQL6!&6u;xy^K-xo>8g+S=AT-u+E-m<;>MK9GabTKC!#`i{6pNqf`P z6ftq2X_F>M4>Q%glBJph45hdS>?~cZr|cR%4wto&6=tDnAiH(Bd?!_;EN7es&&`#7 zri$4BgKX05ve=Y0t#q;twta1V-jH2x>r3;k$8l!rY5OaYnr|cB!aB}uGds1s_F

  • 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 R6c)kuZMgU8%=~+f{2#xTwtoNs diff --git a/backend/_pv_1_3_5/static/blockly/accessible/messages.js b/backend/_pv_1_3_5/static/blockly/accessible/messages.js deleted file mode 100755 index 681b5d535..000000000 --- a/backend/_pv_1_3_5/static/blockly/accessible/messages.js +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Accessible strings. - * @author madeeha@google.com (Madeeha Ghori) - */ -'use strict'; - -// The following are all Accessible Blockly strings. -// None of the alert messages have periods on them. This is because the user -// will have their punctuation setting set to 'all', which will result in any -// punctuation being read out to them. -Blockly.Msg.RUN_CODE = 'Run Code'; -Blockly.Msg.CLEAR_WORKSPACE = 'Clear Workspace'; -Blockly.Msg.BLOCK_ACTION_LIST = 'block action list'; -Blockly.Msg.CUT_BLOCK = 'cut block'; -Blockly.Msg.COPY_BLOCK = 'copy block'; -Blockly.Msg.PASTE_BEFORE = 'paste before'; -Blockly.Msg.PASTE_AFTER = 'paste after'; -Blockly.Msg.MARK_SPOT_BEFORE = 'mark spot before'; -Blockly.Msg.MARK_SPOT_AFTER = 'mark spot after'; -Blockly.Msg.MOVE_TO_MARKED_SPOT = 'move to marked spot'; -Blockly.Msg.DELETE = 'delete'; -Blockly.Msg.MARK_THIS_SPOT = 'mark this spot'; -Blockly.Msg.PASTE = 'paste'; -Blockly.Msg.TOOLBOX_LOAD_MSG = 'Loading Toolbox…'; -Blockly.Msg.WORKSPACE_LOAD_MSG = 'Loading Workspace…'; -Blockly.Msg.BLOCK_SUMMARY = 'block summary'; -Blockly.Msg.OPTION_LIST = 'option list'; -Blockly.Msg.ARGUMENT_OPTIONS_LIST = 'argument options list'; -Blockly.Msg.ARGUMENT_INPUT = 'argument input'; -Blockly.Msg.ARGUMENT_BLOCK_ACTION_LIST = 'argument block action list'; -Blockly.Msg.TEXT = 'text'; -Blockly.Msg.BUTTON = 'button'; -Blockly.Msg.DISABLED = 'disabled'; -Blockly.Msg.CURRENT_ARGUMENT_VALUE = 'current argument value:'; -Blockly.Msg.COPY_TO_WORKSPACE = 'create new group with this block'; -Blockly.Msg.COPY_TO_CLIPBOARD = 'copy to clipboard'; -Blockly.Msg.COPY_TO_MARKED_SPOT = 'copy to marked spot'; -Blockly.Msg.TOOLBOX = 'Toolbox'; -Blockly.Msg.WORKSPACE = 'Workspace'; -Blockly.Msg.ANY = 'any'; -Blockly.Msg.FOR = 'for'; -Blockly.Msg.STATEMENT = 'statement'; -Blockly.Msg.VALUE = 'value'; -Blockly.Msg.CUT_BLOCK_MSG = 'Cut block: '; -Blockly.Msg.COPIED_BLOCK_MSG = 'copied'; -Blockly.Msg.PASTED_BLOCK_FROM_CLIPBOARD_MSG = 'pasted'; -Blockly.Msg.PASTED_BLOCK_TO_MARKED_SPOT_MSG = 'moved to marked spot'; -Blockly.Msg.MARKED_SPOT_MSG = 'Marked spot'; -Blockly.Msg.BLOCK_MOVED_TO_MARKED_SPOT_MSB = 'Block moved to marked spot: '; -Blockly.Msg.TOOLBOX_BLOCK = 'toolbox block'; -Blockly.Msg.WORKSPACE_BLOCK = 'workspace block'; -Blockly.Msg.SUBMENU_INDICATOR = 'move right to view submenu'; -Blockly.Msg.MORE_OPTIONS = 'More options'; diff --git a/backend/_pv_1_3_5/static/blockly/accessible/notifications.service.js b/backend/_pv_1_3_5/static/blockly/accessible/notifications.service.js deleted file mode 100755 index ad5af84ce..000000000 --- a/backend/_pv_1_3_5/static/blockly/accessible/notifications.service.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * AccessibleBlockly - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the 'License'); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an 'AS IS' BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Angular2 Service that notifies the user about actions that - * they have taken, by updating an ARIA live region. - * @author sll@google.com (Sean Lip) - */ - -blocklyApp.NotificationsService = ng.core - .Class({ - constructor: [function() { - this.statusMessage_ = ''; - }], - getStatusMessage: function() { - return this.statusMessage_; - }, - setStatusMessage: function(newMessage) { - // Introduce a temporary status message, so that if, e.g., two "copy" - // operations are done in succession, both messages will be read. - this.statusMessage_ = ''; - - // We need a non-zero timeout here, otherwise NVDA does not read the - // notification messages properly. - var that = this; - setTimeout(function() { - that.statusMessage_ = newMessage; - }, 20); - } - }); diff --git a/backend/_pv_1_3_5/static/blockly/accessible/toolbox-tree.component.js b/backend/_pv_1_3_5/static/blockly/accessible/toolbox-tree.component.js deleted file mode 100755 index e5bbb75be..000000000 --- a/backend/_pv_1_3_5/static/blockly/accessible/toolbox-tree.component.js +++ /dev/null @@ -1,159 +0,0 @@ -/** - * AccessibleBlockly - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the 'License'); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an 'AS IS' BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Angular2 Component that details how blocks are - * rendered in the toolbox in AccessibleBlockly. Also handles any interactions - * with the blocks. - * @author madeeha@google.com (Madeeha Ghori) - */ - -blocklyApp.ToolboxTreeComponent = ng.core - .Component({ - selector: 'blockly-toolbox-tree', - template: ` -
  • - -
      -
    1. - -
    2. -
    3. - -
    4. -
    5. - -
    6. -
    -
  • - - - - `, - directives: [blocklyApp.FieldComponent, ng.core.forwardRef(function() { - return blocklyApp.ToolboxTreeComponent; - })], - inputs: [ - 'block', 'displayBlockMenu', 'level', 'index', 'tree', 'noCategories', 'isTopLevel'], - pipes: [blocklyApp.TranslatePipe] - }) - .Class({ - constructor: [ - blocklyApp.ClipboardService, blocklyApp.NotificationsService, - blocklyApp.TreeService, blocklyApp.UtilsService, - function( - _clipboardService, _notificationsService, - _treeService, _utilsService) { - this.clipboardService = _clipboardService; - this.notificationsService = _notificationsService; - this.treeService = _treeService; - this.utilsService = _utilsService; - }], - ngOnInit: function() { - var elementsNeedingIds = ['blockSummaryLabel']; - if (this.displayBlockMenu) { - elementsNeedingIds = elementsNeedingIds.concat(['blockSummarylabel', - 'workspaceCopy', 'workspaceCopyButton', 'blockCopy', - 'blockCopyButton', 'sendToSelected', 'sendToSelectedButton']); - } - this.idMap = this.utilsService.generateIds(elementsNeedingIds); - if (this.isTopLevel) { - this.idMap['parentList'] = 'blockly-toolbox-tree-node0'; - } else { - this.idMap['parentList'] = this.utilsService.generateUniqueId(); - } - }, - getBlockDescription: function() { - return this.utilsService.getBlockDescription(this.block); - }, - generateAriaLabelledByAttr: function(mainLabel, secondLabel, isDisabled) { - return this.utilsService.generateAriaLabelledByAttr( - mainLabel, secondLabel, isDisabled); - }, - canBeCopiedToMarkedConnection: function() { - return this.clipboardService.canBeCopiedToMarkedConnection(this.block); - }, - copyToWorkspace: function() { - var blockDescription = this.getBlockDescription(); - var xml = Blockly.Xml.blockToDom(this.block); - var newBlockId = Blockly.Xml.domToBlock(blocklyApp.workspace, xml).id; - - var that = this; - setTimeout(function() { - that.treeService.focusOnBlock(newBlockId); - that.notificationsService.setStatusMessage( - blockDescription + ' copied to workspace. ' + - 'Now on copied block in workspace.'); - }); - }, - copyToClipboard: function() { - this.clipboardService.copy(this.block); - this.notificationsService.setStatusMessage( - this.getBlockDescription() + ' ' + Blockly.Msg.COPIED_BLOCK_MSG); - }, - copyToMarkedSpot: function() { - var blockDescription = this.getBlockDescription(); - // Clean up the active desc for the destination tree. - var oldDestinationTreeId = this.treeService.getTreeIdForBlock( - this.clipboardService.getMarkedConnectionBlock().id); - this.treeService.clearActiveDesc(oldDestinationTreeId); - - var newBlockId = this.clipboardService.pasteToMarkedConnection( - this.block); - - // Invoke a digest cycle, so that the DOM settles. - var that = this; - setTimeout(function() { - that.treeService.focusOnBlock(newBlockId); - - var newDestinationTreeId = that.treeService.getTreeIdForBlock( - newBlockId); - if (newDestinationTreeId != oldDestinationTreeId) { - // It is possible for the tree ID for the pasted block to change - // after the paste operation, e.g. when inserting a block between two - // existing blocks that are joined together. In this case, we need to - // also reset the active desc for the old destination tree. - that.treeService.initActiveDesc(oldDestinationTreeId); - } - - that.notificationsService.setStatusMessage( - blockDescription + ' copied to marked spot. ' + - 'Now on copied block in workspace.'); - }); - } - }); diff --git a/backend/_pv_1_3_5/static/blockly/accessible/toolbox.component.js b/backend/_pv_1_3_5/static/blockly/accessible/toolbox.component.js deleted file mode 100755 index a7d5acd93..000000000 --- a/backend/_pv_1_3_5/static/blockly/accessible/toolbox.component.js +++ /dev/null @@ -1,148 +0,0 @@ -/** - * AccessibleBlockly - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the 'License'); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an 'AS IS' BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Angular2 Component that details how a toolbox is rendered - * in AccessibleBlockly. Also handles any interactions with the toolbox. - * @author madeeha@google.com (Madeeha Ghori) - */ - -blocklyApp.ToolboxComponent = ng.core - .Component({ - selector: 'blockly-toolbox', - template: ` -

    Toolbox

    -
      - -
      - - -
      -
    - `, - directives: [blocklyApp.ToolboxTreeComponent] - }) - .Class({ - constructor: [ - blocklyApp.TreeService, blocklyApp.UtilsService, - function(_treeService, _utilsService) { - this.toolboxCategories = []; - this.toolboxWorkspaces = Object.create(null); - this.treeService = _treeService; - this.utilsService = _utilsService; - - this.xmlHasCategories = false; - }], - ngOnInit: function() { - // Note that sometimes the toolbox may not have categories; it may - // display individual blocks directly (which is often the case in, - // e.g., Blockly Games). - var xmlToolboxElt = document.getElementById('blockly-toolbox-xml'); - var xmlCategoryElts = xmlToolboxElt.getElementsByTagName('category'); - if (xmlCategoryElts.length) { - this.xmlHasCategories = true; - this.toolboxCategories = Array.from(xmlCategoryElts); - - var elementsNeedingIds = []; - for (var i = 0; i < this.toolboxCategories.length; i++) { - elementsNeedingIds.push('Parent' + i, 'Label' + i); - } - this.idMap = this.utilsService.generateIds(elementsNeedingIds); - for (var i = 0; i < this.toolboxCategories.length; i++) { - this.idMap['Parent' + i] = 'blockly-toolbox-tree-node' + i; - } - } else { - // Create a single category with all the top-level blocks. - this.xmlHasCategories = false; - this.toolboxCategories = [Array.from(xmlToolboxElt.children)]; - } - }, - ngAfterViewInit: function() { - // If this is a top-level tree in the toolbox, set its active - // descendant after the ids have been computed. - // Note that a timeout is needed here in order to trigger Angular - // change detection. - if (this.xmlHasCategories) { - var that = this; - setTimeout(function() { - that.treeService.setActiveDesc( - 'blockly-toolbox-tree-node0', 'blockly-toolbox-tree'); - }); - } - }, - getActiveDescId: function() { - return this.treeService.getActiveDescId('blockly-toolbox-tree'); - }, - getCategoryAriaLabel: function(category) { - var numBlocks = this.getToolboxWorkspace(category).topBlocks_.length; - return category.attributes.name.value + ' category. ' + - 'Move right to access ' + numBlocks + ' blocks in this category.'; - }, - getToolboxWorkspace: function(categoryNode) { - if (categoryNode.attributes && categoryNode.attributes.name) { - var categoryName = categoryNode.attributes.name.value; - } else { - var categoryName = 'no-category'; - } - if (this.toolboxWorkspaces[categoryName]) { - return this.toolboxWorkspaces[categoryName]; - } else { - var categoryWorkspace = new Blockly.Workspace(); - if (categoryName == 'no-category') { - for (var i = 0; i < categoryNode.length; i++) { - Blockly.Xml.domToBlock(categoryWorkspace, categoryNode[i]); - } - } else { - Blockly.Xml.domToWorkspace(categoryNode, categoryWorkspace); - } - this.toolboxWorkspaces[categoryName] = categoryWorkspace; - return this.toolboxWorkspaces[categoryName]; - } - } - }); diff --git a/backend/_pv_1_3_5/static/blockly/accessible/translate.pipe.js b/backend/_pv_1_3_5/static/blockly/accessible/translate.pipe.js deleted file mode 100755 index c15dec898..000000000 --- a/backend/_pv_1_3_5/static/blockly/accessible/translate.pipe.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * AccessibleBlockly - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the 'License'); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an 'AS IS' BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Angular2 Pipe for internationalizing Blockly message strings. - * @author sll@google.com (Sean Lip) - */ - -blocklyApp.TranslatePipe = ng.core - .Pipe({ - name: 'translate' - }) - .Class({ - constructor: function() {}, - transform: function(messageId) { - return Blockly.Msg[messageId]; - } - }); diff --git a/backend/_pv_1_3_5/static/blockly/accessible/tree.service.js b/backend/_pv_1_3_5/static/blockly/accessible/tree.service.js deleted file mode 100755 index ecf5fd8cc..000000000 --- a/backend/_pv_1_3_5/static/blockly/accessible/tree.service.js +++ /dev/null @@ -1,491 +0,0 @@ -/** - * AccessibleBlockly - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the 'License'); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an 'AS IS' BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Angular2 Service that handles tree keyboard navigation. - * This is a singleton service for the entire application. - * - * @author madeeha@google.com (Madeeha Ghori) - */ - -blocklyApp.TreeService = ng.core - .Class({ - constructor: [ - blocklyApp.NotificationsService, function(_notificationsService) { - // Stores active descendant ids for each tree in the page. - this.activeDescendantIds_ = {}; - this.notificationsService = _notificationsService; - }], - getToolboxTreeNode_: function() { - return document.getElementById('blockly-toolbox-tree'); - }, - getWorkspaceToolbarButtonNodes_: function() { - return Array.from(document.querySelectorAll( - 'button.blocklyWorkspaceToolbarButton')); - }, - // Returns a list of all top-level workspace tree nodes on the page. - getWorkspaceTreeNodes_: function() { - return Array.from(document.querySelectorAll('ol.blocklyWorkspaceTree')); - }, - // Returns a list of all top-level tree nodes on the page. - getAllTreeNodes_: function() { - var treeNodes = [this.getToolboxTreeNode_()]; - treeNodes = treeNodes.concat(this.getWorkspaceToolbarButtonNodes_()); - treeNodes = treeNodes.concat(this.getWorkspaceTreeNodes_()); - return treeNodes; - }, - isTopLevelWorkspaceTree: function(treeId) { - return this.getWorkspaceTreeNodes_().some(function(tree) { - return tree.id == treeId; - }); - }, - getNodeToFocusOnWhenTreeIsDeleted: function(deletedTreeId) { - // This returns the node to focus on after the deletion happens. - // We shift focus to the next tree (if it exists), otherwise we shift - // focus to the previous tree. - var trees = this.getAllTreeNodes_(); - for (var i = 0; i < trees.length; i++) { - if (trees[i].id == deletedTreeId) { - if (i + 1 < trees.length) { - return trees[i + 1]; - } else if (i > 0) { - return trees[i - 1]; - } - } - } - - return this.getToolboxTreeNode_(); - }, - focusOnCurrentTree_: function(treeId) { - var trees = this.getAllTreeNodes_(); - for (var i = 0; i < trees.length; i++) { - if (trees[i].id == treeId) { - trees[i].focus(); - return trees[i].id; - } - } - return null; - }, - getIdOfNextTree_: function(treeId) { - var trees = this.getAllTreeNodes_(); - for (var i = 0; i < trees.length - 1; i++) { - if (trees[i].id == treeId) { - return trees[i + 1].id; - } - } - return null; - }, - getIdOfPreviousTree_: function(treeId) { - var trees = this.getAllTreeNodes_(); - for (var i = trees.length - 1; i > 0; i--) { - if (trees[i].id == treeId) { - return trees[i - 1].id; - } - } - return null; - }, - getActiveDescId: function(treeId) { - return this.activeDescendantIds_[treeId] || ''; - }, - unmarkActiveDesc_: function(activeDescId) { - var activeDesc = document.getElementById(activeDescId); - if (activeDesc) { - activeDesc.classList.remove('blocklyActiveDescendant'); - } - }, - markActiveDesc_: function(activeDescId) { - var newActiveDesc = document.getElementById(activeDescId); - newActiveDesc.classList.add('blocklyActiveDescendant'); - }, - // Runs the given function while preserving the focus and active descendant - // for the given tree. - runWhilePreservingFocus: function(func, treeId, optionalNewActiveDescId) { - var oldDescId = this.getActiveDescId(treeId); - var newDescId = optionalNewActiveDescId || oldDescId; - this.unmarkActiveDesc_(oldDescId); - func(); - - // The timeout is needed in order to give the DOM time to stabilize - // before setting the new active descendant, especially in cases like - // pasteAbove(). - var that = this; - setTimeout(function() { - that.markActiveDesc_(newDescId); - that.activeDescendantIds_[treeId] = newDescId; - document.getElementById(treeId).focus(); - }, 0); - }, - // This clears the active descendant of the given tree. It is used just - // before the tree is deleted. - clearActiveDesc: function(treeId) { - this.unmarkActiveDesc_(this.getActiveDescId(treeId)); - delete this.activeDescendantIds_[treeId]; - }, - // Make a given node the active descendant of a given tree. - setActiveDesc: function(newActiveDescId, treeId) { - this.unmarkActiveDesc_(this.getActiveDescId(treeId)); - this.markActiveDesc_(newActiveDescId); - this.activeDescendantIds_[treeId] = newActiveDescId; - - // Scroll the new active desc into view, if needed. This has no effect - // for blind users, but is helpful for sighted onlookers. - var activeDescNode = document.getElementById(newActiveDescId); - var documentNode = document.body || document.documentElement; - if (activeDescNode.offsetTop < documentNode.scrollTop || - activeDescNode.offsetTop > - documentNode.scrollTop + window.innerHeight) { - window.scrollTo(0, activeDescNode.offsetTop); - } - }, - initActiveDesc: function(treeId) { - // Set the active desc to the first child in this tree. - var tree = document.getElementById(treeId); - this.setActiveDesc(this.getFirstChild(tree).id, treeId); - }, - getTreeIdForBlock: function(blockId) { - // Walk up the DOM until we get to the root node of the tree. - var domNode = document.getElementById(blockId + 'blockRoot'); - while (!domNode.classList.contains('blocklyTree')) { - domNode = domNode.parentNode; - } - return domNode.id; - }, - focusOnBlock: function(blockId) { - // Set focus to the tree containing the given block, and set the active - // desc for this tree to the given block. - var domNode = document.getElementById(blockId + 'blockRoot'); - // Walk up the DOM until we get to the root node of the tree. - while (!domNode.classList.contains('blocklyTree')) { - domNode = domNode.parentNode; - } - domNode.focus(); - - // We need to wait a while to set the active desc, because domNode takes - // a while to be given an ID if a new tree has just been created. - // TODO(sll): Make this more deterministic. - var that = this; - setTimeout(function() { - that.setActiveDesc(blockId + 'blockRoot', domNode.id); - }, 100); - }, - onWorkspaceToolbarKeypress: function(e, treeId) { - if (e.keyCode == 9) { - // Tab key. - var destinationTreeId = - e.shiftKey ? this.getIdOfPreviousTree_(treeId) : - this.getIdOfNextTree_(treeId); - if (destinationTreeId) { - this.notifyUserAboutCurrentTree_(destinationTreeId); - } - } - }, - isButtonOrFieldNode_: function(node) { - return ['BUTTON', 'INPUT'].indexOf(node.tagName) != -1; - }, - getNextActiveDescWhenBlockIsDeleted: function(blockRootNode) { - // Go up a level, if possible. - var nextNode = blockRootNode.parentNode; - while (nextNode && nextNode.tagName != 'LI') { - nextNode = nextNode.parentNode; - } - if (nextNode) { - return nextNode; - } - - // Otherwise, go to the next sibling. - var nextSibling = this.getNextSibling(blockRootNode); - if (nextSibling) { - return nextSibling; - } - - // Otherwise, go to the previous sibling. - var previousSibling = this.getPreviousSibling(blockRootNode); - if (previousSibling) { - return previousSibling; - } - - // Otherwise, this is a top-level isolated block, which means that - // something's gone wrong and this function should not have been called - // in the first place. - console.error('Could not handle deletion of block.' + blockRootNode); - }, - notifyUserAboutCurrentTree_: function(treeId) { - if (this.getToolboxTreeNode_().id == treeId) { - this.notificationsService.setStatusMessage('Now in toolbox.'); - } else { - var workspaceTreeNodes = this.getWorkspaceTreeNodes_(); - for (var i = 0; i < workspaceTreeNodes.length; i++) { - if (workspaceTreeNodes[i].id == treeId) { - this.notificationsService.setStatusMessage( - 'Now in workspace group ' + (i + 1) + ' of ' + - workspaceTreeNodes.length); - } - } - } - }, - onKeypress: function(e, tree) { - var treeId = tree.id; - var activeDesc = document.getElementById(this.getActiveDescId(treeId)); - if (!activeDesc) { - console.error('ERROR: no active descendant for current tree.'); - this.initActiveDesc(treeId); - return; - } - - if (e.altKey || e.ctrlKey) { - // Do not intercept combinations such as Alt+Home. - return; - } else if (document.activeElement.tagName == 'INPUT') { - // For input fields, only Esc and Tab keystrokes are handled specially. - if (e.keyCode == 27 || e.keyCode == 9) { - // For Esc and Tab keys, the focus is removed from the input field. - this.focusOnCurrentTree_(treeId); - - if (e.keyCode == 9) { - var destinationTreeId = - e.shiftKey ? this.getIdOfPreviousTree_(treeId) : - this.getIdOfNextTree_(treeId); - if (destinationTreeId) { - this.notifyUserAboutCurrentTree_(destinationTreeId); - } - } - - // Allow Tab keypresses to go through. - if (e.keyCode == 27) { - e.preventDefault(); - e.stopPropagation(); - } - } - } else { - // Outside an input field, Enter, Tab and navigation keys are all - // recognized. - if (e.keyCode == 13) { - // Enter key. The user wants to interact with a button or an input - // field. - // Algorithm to find the field: do a DFS through the children until - // we find an INPUT or BUTTON element (in which case we use it). - // Truncate the search at child LI elements. - var dfsStack = Array.from(activeDesc.children); - while (dfsStack.length) { - var currentNode = dfsStack.shift(); - if (currentNode.tagName == 'BUTTON') { - this.moveActiveDescToParent(treeId); - currentNode.click(); - break; - } else if (currentNode.tagName == 'INPUT') { - currentNode.focus(); - this.notificationsService.setStatusMessage( - 'Type a value, then press Escape to exit'); - break; - } else if (currentNode.tagName == 'LI') { - continue; - } - - if (currentNode.children) { - var reversedChildren = Array.from(currentNode.children).reverse(); - reversedChildren.forEach(function(childNode) { - dfsStack.unshift(childNode); - }); - } - } - } else if (e.keyCode == 9) { - // Tab key. Note that allowing the event to propagate through is - // intentional. - var destinationTreeId = - e.shiftKey ? this.getIdOfPreviousTree_(treeId) : - this.getIdOfNextTree_(treeId); - if (destinationTreeId) { - this.notifyUserAboutCurrentTree_(destinationTreeId); - } - } else if (e.keyCode >= 35 && e.keyCode <= 40) { - // End, home, and arrow keys. - if (e.keyCode == 35) { - // End key. Go to the last sibling in the subtree. - var finalSibling = this.getFinalSibling(activeDesc); - if (finalSibling) { - this.setActiveDesc(finalSibling.id, treeId); - } - } else if (e.keyCode == 36) { - // Home key. Go to the first sibling in the subtree. - var initialSibling = this.getInitialSibling(activeDesc); - if (initialSibling) { - this.setActiveDesc(initialSibling.id, treeId); - } - } else if (e.keyCode == 37) { - // Left arrow key. Go up a level, if possible. - this.moveActiveDescToParent(treeId); - } else if (e.keyCode == 38) { - // Up arrow key. Go to the previous sibling, if possible. - var prevSibling = this.getPreviousSibling(activeDesc); - if (prevSibling) { - this.setActiveDesc(prevSibling.id, treeId); - } else { - this.notificationsService.setStatusMessage( - 'Reached top of list'); - } - } else if (e.keyCode == 39) { - // Right arrow key. Go down a level, if possible. - var firstChild = this.getFirstChild(activeDesc); - if (firstChild) { - this.setActiveDesc(firstChild.id, treeId); - } - } else if (e.keyCode == 40) { - // Down arrow key. Go to the next sibling, if possible. - var nextSibling = this.getNextSibling(activeDesc); - if (nextSibling) { - this.setActiveDesc(nextSibling.id, treeId); - } else { - this.notificationsService.setStatusMessage( - 'Reached bottom of list'); - } - } - - e.preventDefault(); - e.stopPropagation(); - } - } - }, - moveActiveDescToParent: function(treeId) { - var activeDesc = document.getElementById(this.getActiveDescId(treeId)); - var nextNode = activeDesc.parentNode; - if (this.isButtonOrFieldNode_(activeDesc)) { - nextNode = nextNode.parentNode; - } - while (nextNode && nextNode.tagName != 'LI') { - nextNode = nextNode.parentNode; - } - if (nextNode) { - this.setActiveDesc(nextNode.id, treeId); - } - }, - getFirstChild: function(element) { - if (!element) { - return element; - } else { - var childList = element.children; - for (var i = 0; i < childList.length; i++) { - if (childList[i].tagName == 'LI') { - return childList[i]; - } else { - var potentialElement = this.getFirstChild(childList[i]); - if (potentialElement) { - return potentialElement; - } - } - } - return null; - } - }, - getFinalSibling: function(element) { - while (true) { - var nextSibling = this.getNextSibling(element); - if (nextSibling && nextSibling.id != element.id) { - element = nextSibling; - } else { - return element; - } - } - }, - getInitialSibling: function(element) { - while (true) { - var previousSibling = this.getPreviousSibling(element); - if (previousSibling && previousSibling.id != element.id) { - element = previousSibling; - } else { - return element; - } - } - }, - getNextSibling: function(element) { - if (element.nextElementSibling) { - // If there is a sibling, find the list element child of the sibling. - var node = element.nextElementSibling; - if (node.tagName == 'LI') { - return node; - } else { - // getElementsByTagName returns in DFS order, therefore the first - // element is the first relevant list child. - return node.getElementsByTagName('li')[0]; - } - } else { - var parent = element.parentNode; - while (parent && parent.tagName != 'OL') { - if (parent.nextElementSibling) { - var node = parent.nextElementSibling; - if (node.tagName == 'LI') { - return node; - } else { - return this.getFirstChild(node); - } - } else { - parent = parent.parentNode; - } - } - return null; - } - }, - getPreviousSibling: function(element) { - if (element.previousElementSibling) { - var sibling = element.previousElementSibling; - if (sibling.tagName == 'LI') { - return sibling; - } else { - return this.getLastChild(sibling); - } - } else { - var parent = element.parentNode; - while (parent) { - if (parent.tagName == 'OL') { - break; - } - if (parent.previousElementSibling) { - var node = parent.previousElementSibling; - if (node.tagName == 'LI') { - return node; - } else { - // Find the last list element child of the sibling of the parent. - return this.getLastChild(node); - } - } else { - parent = parent.parentNode; - } - } - return null; - } - }, - getLastChild: function(element) { - if (!element) { - return element; - } else { - var childList = element.children; - for (var i = childList.length - 1; i >= 0; i--) { - // Find the last child that is a list element. - if (childList[i].tagName == 'LI') { - return childList[i]; - } else { - var potentialElement = this.getLastChild(childList[i]); - if (potentialElement) { - return potentialElement; - } - } - } - return null; - } - } -}); diff --git a/backend/_pv_1_3_5/static/blockly/accessible/utils.service.js b/backend/_pv_1_3_5/static/blockly/accessible/utils.service.js deleted file mode 100755 index 3a7eef797..000000000 --- a/backend/_pv_1_3_5/static/blockly/accessible/utils.service.js +++ /dev/null @@ -1,74 +0,0 @@ -/** - * AccessibleBlockly - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the 'License'); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an 'AS IS' BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Angular2 utility service for multiple components. All - * functions in this service should be stateless, since this is a singleton - * service that is used for the entire application. - * - * @author madeeha@google.com (Madeeha Ghori) - */ - -var blocklyApp = {}; - -blocklyApp.UtilsService = ng.core - .Class({ - constructor: function() {}, - generateUniqueId: function() { - return 'blockly-' + Blockly.genUid(); - }, - generateIds: function(elementsList) { - var idMap = {}; - for (var i = 0; i < elementsList.length; i++){ - idMap[elementsList[i]] = this.generateUniqueId(); - } - return idMap; - }, - generateAriaLabelledByAttr: function(mainLabel, secondLabel, isDisabled) { - var attrValue = mainLabel + (secondLabel ? ' ' + secondLabel : ''); - if (isDisabled) { - attrValue += ' blockly-disabled'; - } - return attrValue; - }, - getInputTypeLabel: function(connection) { - // Returns the input type name, or 'any' if any official input type - // qualifies. - if (connection.check_) { - return connection.check_.join(', '); - } else { - return Blockly.Msg.ANY; - } - }, - getBlockTypeLabel: function(inputBlock) { - if (inputBlock.type == Blockly.NEXT_STATEMENT) { - return Blockly.Msg.STATEMENT; - } else { - return Blockly.Msg.VALUE; - } - }, - getBlockDescription: function(block) { - // We use 'BLANK' instead of the default '?' so that the string is read - // out. (By default, screen readers tend to ignore punctuation.) - return block.toString(undefined, 'BLANK'); - }, - isWorkspaceEmpty: function() { - return !blocklyApp.workspace.topBlocks_.length; - } - }); diff --git a/backend/_pv_1_3_5/static/blockly/accessible/workspace-tree.component.js b/backend/_pv_1_3_5/static/blockly/accessible/workspace-tree.component.js deleted file mode 100755 index 04ec09b12..000000000 --- a/backend/_pv_1_3_5/static/blockly/accessible/workspace-tree.component.js +++ /dev/null @@ -1,392 +0,0 @@ -/** - * AccessibleBlockly - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the 'License'); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an 'AS IS' BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Angular2 Component that details how Blockly.Block's are - * rendered in the workspace in AccessibleBlockly. Also handles any - * interactions with the blocks. - * @author madeeha@google.com (Madeeha Ghori) - */ - -blocklyApp.WorkspaceTreeComponent = ng.core - .Component({ - selector: 'blockly-workspace-tree', - template: ` -
  • - - -
      - - -
    1. - -
        -
      1. - -
      2. -
      -
    2. -
    -
  • - - - - `, - directives: [blocklyApp.FieldComponent, ng.core.forwardRef(function() { - return blocklyApp.WorkspaceTreeComponent; - })], - inputs: ['block', 'level', 'tree', 'isTopLevel'], - pipes: [blocklyApp.TranslatePipe] - }) - .Class({ - constructor: [ - blocklyApp.ClipboardService, blocklyApp.NotificationsService, - blocklyApp.TreeService, blocklyApp.UtilsService, - blocklyApp.AudioService, - function( - _clipboardService, _notificationsService, _treeService, - _utilsService, _audioService) { - this.clipboardService = _clipboardService; - this.notificationsService = _notificationsService; - this.treeService = _treeService; - this.utilsService = _utilsService; - this.audioService = _audioService; - }], - getBlockDescription: function() { - return this.utilsService.getBlockDescription(this.block); - }, - isIsolatedTopLevelBlock_: function(block) { - // Returns whether the given block is at the top level, and has no - // siblings. - var blockIsAtTopLevel = !block.getParent(); - var blockHasNoSiblings = ( - (!block.nextConnection || - !block.nextConnection.targetConnection) && - (!block.previousConnection || - !block.previousConnection.targetConnection)); - return blockIsAtTopLevel && blockHasNoSiblings; - }, - removeBlockAndSetFocus_: function(block, deleteBlockFunc) { - // This method runs the given function and then does one of two things: - // - If the block is an isolated top-level block, it shifts the tree - // focus. - // - Otherwise, it sets the correct new active desc for the current tree. - if (this.isIsolatedTopLevelBlock_(block)) { - var nextNodeToFocusOn = - this.treeService.getNodeToFocusOnWhenTreeIsDeleted(this.tree.id); - - this.treeService.clearActiveDesc(this.tree.id); - deleteBlockFunc(); - // Invoke a digest cycle, so that the DOM settles. - setTimeout(function() { - nextNodeToFocusOn.focus(); - }); - } else { - var blockRootNode = document.getElementById(this.idMap['blockRoot']); - var nextActiveDesc = - this.treeService.getNextActiveDescWhenBlockIsDeleted( - blockRootNode); - this.treeService.runWhilePreservingFocus( - deleteBlockFunc, this.tree.id, nextActiveDesc.id); - } - }, - cutBlock_: function() { - var blockDescription = this.getBlockDescription(); - - var that = this; - this.removeBlockAndSetFocus_(this.block, function() { - that.clipboardService.cut(that.block); - }); - - setTimeout(function() { - if (that.utilsService.isWorkspaceEmpty()) { - that.notificationsService.setStatusMessage( - blockDescription + ' cut. Workspace is empty.'); - } else { - that.notificationsService.setStatusMessage( - blockDescription + ' cut. Now on workspace.'); - } - }); - }, - deleteBlock_: function() { - var blockDescription = this.getBlockDescription(); - - var that = this; - this.removeBlockAndSetFocus_(this.block, function() { - that.block.dispose(true); - that.audioService.playDeleteSound(); - }); - - setTimeout(function() { - if (that.utilsService.isWorkspaceEmpty()) { - that.notificationsService.setStatusMessage( - blockDescription + ' deleted. Workspace is empty.'); - } else { - that.notificationsService.setStatusMessage( - blockDescription + ' deleted. Now on workspace.'); - } - }); - }, - pasteToConnection_: function(connection) { - var destinationTreeId = this.treeService.getTreeIdForBlock( - connection.getSourceBlock().id); - this.treeService.clearActiveDesc(destinationTreeId); - - var newBlockId = this.clipboardService.pasteFromClipboard(connection); - - // Invoke a digest cycle, so that the DOM settles. - var that = this; - setTimeout(function() { - that.treeService.focusOnBlock(newBlockId); - }); - }, - moveToMarkedSpot_: function() { - var blockDescription = this.getBlockDescription(); - var oldDestinationTreeId = this.treeService.getTreeIdForBlock( - this.clipboardService.getMarkedConnectionBlock().id); - this.treeService.clearActiveDesc(oldDestinationTreeId); - - var newBlockId = this.clipboardService.pasteToMarkedConnection( - this.block); - - var that = this; - this.removeBlockAndSetFocus_(this.block, function() { - that.block.dispose(true); - }); - - // Invoke a digest cycle, so that the DOM settles. - setTimeout(function() { - that.treeService.focusOnBlock(newBlockId); - - var newDestinationTreeId = that.treeService.getTreeIdForBlock( - newBlockId); - if (newDestinationTreeId != oldDestinationTreeId) { - // It is possible for the tree ID for the pasted block to change - // after the paste operation, e.g. when inserting a block between two - // existing blocks that are joined together. In this case, we need to - // also reset the active desc for the old destination tree. - that.treeService.initActiveDesc(oldDestinationTreeId); - } - - that.notificationsService.setStatusMessage( - blockDescription + ' ' + - Blockly.Msg.PASTED_BLOCK_TO_MARKED_SPOT_MSG + - '. Now on moved block in workspace.'); - }); - }, - copyBlock_: function() { - this.clipboardService.copy(this.block); - this.notificationsService.setStatusMessage( - this.getBlockDescription() + ' ' + Blockly.Msg.COPIED_BLOCK_MSG); - }, - markSpotBefore_: function() { - this.clipboardService.markConnection(this.block.previousConnection); - }, - markSpotAfter_: function() { - this.clipboardService.markConnection(this.block.nextConnection); - }, - pasteToNextConnection_: function() { - this.pasteToConnection_(this.block.nextConnection); - }, - pasteToPreviousConnection_: function() { - this.pasteToConnection_(this.block.previousConnection); - }, - ngOnInit: function() { - var that = this; - - // Generate a list of action buttons. - this.actionButtonsInfo = [{ - baseIdKey: 'cut', - translationIdForText: 'CUT_BLOCK', - action: that.cutBlock_.bind(that), - isDisabled: function() { - return false; - } - }, { - baseIdKey: 'copy', - translationIdForText: 'COPY_BLOCK', - action: that.copyBlock_.bind(that), - isDisabled: function() { - return false; - } - }, { - baseIdKey: 'pasteBefore', - translationIdForText: 'PASTE_BEFORE', - action: that.pasteToPreviousConnection_.bind(that), - isDisabled: function() { - return Boolean( - !that.block.previousConnection || - !that.isCompatibleWithClipboard(that.block.previousConnection)); - } - }, { - baseIdKey: 'pasteAfter', - translationIdForText: 'PASTE_AFTER', - action: that.pasteToNextConnection_.bind(that), - isDisabled: function() { - return Boolean( - !that.block.nextConnection || - !that.isCompatibleWithClipboard(that.block.nextConnection)); - } - }, { - baseIdKey: 'markBefore', - translationIdForText: 'MARK_SPOT_BEFORE', - action: that.markSpotBefore_.bind(that), - isDisabled: function() { - return !that.block.previousConnection; - } - }, { - baseIdKey: 'markAfter', - translationIdForText: 'MARK_SPOT_AFTER', - action: that.markSpotAfter_.bind(that), - isDisabled: function() { - return !that.block.nextConnection; - } - }, { - baseIdKey: 'moveToMarkedSpot', - translationIdForText: 'MOVE_TO_MARKED_SPOT', - action: that.moveToMarkedSpot_.bind(that), - isDisabled: function() { - return !that.clipboardService.isMovableToMarkedConnection( - that.block); - } - }, { - baseIdKey: 'delete', - translationIdForText: 'DELETE', - action: that.deleteBlock_.bind(that), - isDisabled: function() { - return false; - } - }]; - - // Generate a list of action buttons. - this.fieldButtonsInfo = [{ - baseIdKey: 'markSpot', - translationIdForText: 'MARK_THIS_SPOT', - action: function(connection) { - that.clipboardService.markConnection(connection); - }, - isDisabled: function() { - return false; - } - }, { - baseIdKey: 'paste', - translationIdForText: 'PASTE', - action: function(connection) { - that.pasteToConnection_(connection); - }, - isDisabled: function(connection) { - return !that.isCompatibleWithClipboard(connection); - } - }]; - - // Make a list of all the id keys. - this.idKeys = ['blockRoot', 'blockSummary', 'listItem', 'label']; - this.actionButtonsInfo.forEach(function(buttonInfo) { - that.idKeys.push(buttonInfo.baseIdKey, buttonInfo.baseIdKey + 'Button'); - }); - this.fieldButtonsInfo.forEach(function(buttonInfo) { - for (var i = 0; i < that.block.inputList.length; i++) { - that.idKeys.push( - buttonInfo.baseIdKey + i, buttonInfo.baseIdKey + 'Button' + i); - } - }); - for (var i = 0; i < this.block.inputList.length; i++) { - var inputBlock = this.block.inputList[i]; - that.idKeys.push( - 'inputList' + i, 'inputMenuLabel' + i, 'listItem' + i, - 'fieldLabel' + i); - } - }, - ngDoCheck: function() { - // Generate a unique id for each id key. This needs to be done every time - // changes happen, but after the first ng-init, in order to force the - // element ids to change in cases where, e.g., a block is inserted in the - // middle of a sequence of blocks. - this.idMap = {}; - for (var i = 0; i < this.idKeys.length; i++) { - this.idMap[this.idKeys[i]] = this.block.id + this.idKeys[i]; - } - }, - ngAfterViewInit: function() { - // If this is a top-level tree in the workspace, set its id and active - // descendant. (Note that a timeout is needed here in order to trigger - // Angular change detection.) - var that = this; - setTimeout(function() { - if (that.tree && that.isTopLevel && !that.tree.id) { - that.tree.id = that.utilsService.generateUniqueId(); - } - if (that.tree && that.isTopLevel && - !that.treeService.getActiveDescId(that.tree.id)) { - that.treeService.setActiveDesc(that.idMap['blockRoot'], that.tree.id); - } - }); - }, - generateAriaLabelledByAttr: function(mainLabel, secondLabel, isDisabled) { - return this.utilsService.generateAriaLabelledByAttr( - mainLabel, secondLabel, isDisabled); - }, - isCompatibleWithClipboard: function(connection) { - return this.clipboardService.isCompatibleWithClipboard(connection); - } - }); diff --git a/backend/_pv_1_3_5/static/blockly/accessible/workspace.component.js b/backend/_pv_1_3_5/static/blockly/accessible/workspace.component.js deleted file mode 100755 index 255735020..000000000 --- a/backend/_pv_1_3_5/static/blockly/accessible/workspace.component.js +++ /dev/null @@ -1,94 +0,0 @@ -/** - * AccessibleBlockly - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the 'License'); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an 'AS IS' BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Angular2 Component that details how a Blockly.Workspace is - * rendered in AccessibleBlockly. - * @author madeeha@google.com (Madeeha Ghori) - */ - -blocklyApp.WorkspaceComponent = ng.core - .Component({ - selector: 'blockly-workspace', - template: ` - - -
    - - - - -
    - -
    -
      - - -
    -
    - `, - directives: [blocklyApp.WorkspaceTreeComponent], - pipes: [blocklyApp.TranslatePipe] - }) - .Class({ - constructor: [ - blocklyApp.TreeService, blocklyApp.UtilsService, - function(_treeService, _utilsService) { - // ACCESSIBLE_GLOBALS is a global variable defined by the containing - // page. It should contain a key, toolbarButtonConfig, whose - // corresponding value is an Array with two keys: 'text' and 'action'. - // The first is the text to display on the button, and the second is the - // function that gets run when the button is clicked. - this.toolbarButtonConfig = - ACCESSIBLE_GLOBALS && ACCESSIBLE_GLOBALS.toolbarButtonConfig ? - ACCESSIBLE_GLOBALS.toolbarButtonConfig : []; - this.workspace = blocklyApp.workspace; - this.treeService = _treeService; - this.utilsService = _utilsService; - }], - clearWorkspace: function() { - this.workspace.clear(); - }, - getActiveDescId: function(treeId) { - return this.treeService.getActiveDescId(treeId); - }, - onWorkspaceToolbarKeypress: function(e) { - this.treeService.onWorkspaceToolbarKeypress( - e, document.activeElement.id); - }, - onKeypress: function(e, tree) { - this.treeService.onKeypress(e, tree); - }, - isWorkspaceEmpty: function() { - return this.utilsService.isWorkspaceEmpty(); - } - }); diff --git a/backend/_pv_1_3_5/static/blockly/blockly_compressed.js b/backend/_pv_1_3_5/static/blockly/blockly_compressed.js deleted file mode 100755 index f268ea620..000000000 --- a/backend/_pv_1_3_5/static/blockly/blockly_compressed.js +++ /dev/null @@ -1,1457 +0,0 @@ -// Do not edit this file; automatically generated by build.py. -'use strict'; - -var COMPILED=!0,goog=goog||{};goog.global=this;goog.isDef=function(a){return void 0!==a};goog.exportPath_=function(a,b,c){a=a.split(".");c=c||goog.global;a[0]in c||!c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)!a.length&&goog.isDef(b)?c[d]=b:c=c[d]?c[d]:c[d]={}}; -goog.define=function(a,b){var c=b;COMPILED||(goog.global.CLOSURE_UNCOMPILED_DEFINES&&Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_UNCOMPILED_DEFINES,a)?c=goog.global.CLOSURE_UNCOMPILED_DEFINES[a]:goog.global.CLOSURE_DEFINES&&Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_DEFINES,a)&&(c=goog.global.CLOSURE_DEFINES[a]));goog.exportPath_(a,c)};goog.DEBUG=!1;goog.LOCALE="en";goog.TRUSTED_SITE=!0;goog.STRICT_MODE_COMPATIBLE=!1;goog.DISALLOW_TEST_ONLY_CODE=COMPILED&&!goog.DEBUG; -goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING=!1;goog.provide=function(a){if(goog.isInModuleLoader_())throw Error("goog.provide can not be used within a goog.module.");if(!COMPILED&&goog.isProvided_(a))throw Error('Namespace "'+a+'" already declared.');goog.constructNamespace_(a)};goog.constructNamespace_=function(a,b){if(!COMPILED){delete goog.implicitNamespaces_[a];for(var c=a;(c=c.substring(0,c.lastIndexOf(".")))&&!goog.getObjectByName(c);)goog.implicitNamespaces_[c]=!0}goog.exportPath_(a,b)}; -goog.VALID_MODULE_RE_=/^[a-zA-Z_$][a-zA-Z0-9._$]*$/;goog.module=function(a){if(!goog.isString(a)||!a||-1==a.search(goog.VALID_MODULE_RE_))throw Error("Invalid module identifier");if(!goog.isInModuleLoader_())throw Error("Module "+a+" has been loaded incorrectly.");if(goog.moduleLoaderState_.moduleName)throw Error("goog.module may only be called once per module.");goog.moduleLoaderState_.moduleName=a;if(!COMPILED){if(goog.isProvided_(a))throw Error('Namespace "'+a+'" already declared.');delete goog.implicitNamespaces_[a]}}; -goog.module.get=function(a){return goog.module.getInternal_(a)};goog.module.getInternal_=function(a){if(!COMPILED)return goog.isProvided_(a)?a in goog.loadedModules_?goog.loadedModules_[a]:goog.getObjectByName(a):null};goog.moduleLoaderState_=null;goog.isInModuleLoader_=function(){return null!=goog.moduleLoaderState_}; -goog.module.declareLegacyNamespace=function(){if(!COMPILED&&!goog.isInModuleLoader_())throw Error("goog.module.declareLegacyNamespace must be called from within a goog.module");if(!COMPILED&&!goog.moduleLoaderState_.moduleName)throw Error("goog.module must be called prior to goog.module.declareLegacyNamespace.");goog.moduleLoaderState_.declareLegacyNamespace=!0}; -goog.setTestOnly=function(a){if(goog.DISALLOW_TEST_ONLY_CODE)throw a=a||"",Error("Importing test-only code into non-debug environment"+(a?": "+a:"."));};goog.forwardDeclare=function(a){};COMPILED||(goog.isProvided_=function(a){return a in goog.loadedModules_||!goog.implicitNamespaces_[a]&&goog.isDefAndNotNull(goog.getObjectByName(a))},goog.implicitNamespaces_={"goog.module":!0}); -goog.getObjectByName=function(a,b){for(var c=a.split("."),d=b||goog.global,e;e=c.shift();)if(goog.isDefAndNotNull(d[e]))d=d[e];else return null;return d};goog.globalize=function(a,b){var c=b||goog.global,d;for(d in a)c[d]=a[d]}; -goog.addDependency=function(a,b,c,d){if(goog.DEPENDENCIES_ENABLED){var e;a=a.replace(/\\/g,"/");var f=goog.dependencies_;d&&"boolean"!==typeof d||(d=d?{module:"goog"}:{});for(var g=0;e=b[g];g++)f.nameToPath[e]=a,f.loadFlags[a]=d;for(d=0;b=c[d];d++)a in f.requires||(f.requires[a]={}),f.requires[a][b]=!0}};goog.ENABLE_DEBUG_LOADER=!0;goog.logToConsole_=function(a){goog.global.console&&goog.global.console.error(a)}; -goog.require=function(a){if(!COMPILED){goog.ENABLE_DEBUG_LOADER&&goog.IS_OLD_IE_&&goog.maybeProcessDeferredDep_(a);if(goog.isProvided_(a)){if(goog.isInModuleLoader_())return goog.module.getInternal_(a)}else if(goog.ENABLE_DEBUG_LOADER){var b=goog.getPathFromDeps_(a);if(b)goog.writeScripts_(b);else throw a="goog.require could not find: "+a,goog.logToConsole_(a),Error(a);}return null}};goog.basePath="";goog.nullFunction=function(){}; -goog.abstractMethod=function(){throw Error("unimplemented abstract method");};goog.addSingletonGetter=function(a){a.getInstance=function(){if(a.instance_)return a.instance_;goog.DEBUG&&(goog.instantiatedSingletons_[goog.instantiatedSingletons_.length]=a);return a.instance_=new a}};goog.instantiatedSingletons_=[];goog.LOAD_MODULE_USING_EVAL=!0;goog.SEAL_MODULE_EXPORTS=goog.DEBUG;goog.loadedModules_={};goog.DEPENDENCIES_ENABLED=!COMPILED&&goog.ENABLE_DEBUG_LOADER;goog.TRANSPILE="detect"; -goog.TRANSPILER="transpile.js"; -goog.DEPENDENCIES_ENABLED&&(goog.dependencies_={loadFlags:{},nameToPath:{},requires:{},visited:{},written:{},deferred:{}},goog.inHtmlDocument_=function(){var a=goog.global.document;return null!=a&&"write"in a},goog.findBasePath_=function(){if(goog.isDef(goog.global.CLOSURE_BASE_PATH))goog.basePath=goog.global.CLOSURE_BASE_PATH;else if(goog.inHtmlDocument_())for(var a=goog.global.document.getElementsByTagName("SCRIPT"),b=a.length-1;0<=b;--b){var c=a[b].src,d=c.lastIndexOf("?"),d=-1==d?c.length:d;if("base.js"== -c.substr(d-7,7)){goog.basePath=c.substr(0,d-7);break}}},goog.importScript_=function(a,b){(goog.global.CLOSURE_IMPORT_SCRIPT||goog.writeScriptTag_)(a,b)&&(goog.dependencies_.written[a]=!0)},goog.IS_OLD_IE_=!(goog.global.atob||!goog.global.document||!goog.global.document.all),goog.importProcessedScript_=function(a,b,c){goog.importScript_("",'goog.retrieveAndExec_("'+a+'", '+b+", "+c+");")},goog.queuedModules_=[],goog.wrapModule_=function(a,b){return goog.LOAD_MODULE_USING_EVAL&&goog.isDef(goog.global.JSON)? -"goog.loadModule("+goog.global.JSON.stringify(b+"\n//# sourceURL="+a+"\n")+");":'goog.loadModule(function(exports) {"use strict";'+b+"\n;return exports});\n//# sourceURL="+a+"\n"},goog.loadQueuedModules_=function(){var a=goog.queuedModules_.length;if(0\x3c/script>')},goog.appendScriptSrcNode_=function(a){var b=goog.global.document,c=b.createElement("script");c.type="text/javascript";c.src=a;c.defer=!1;c.async=!1;b.head.appendChild(c)},goog.writeScriptTag_=function(a,b){if(goog.inHtmlDocument_()){var c= -goog.global.document;if(!goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING&&"complete"==c.readyState){if(/\bdeps.js$/.test(a))return!1;throw Error('Cannot write "'+a+'" after document load');}if(void 0===b)if(goog.IS_OLD_IE_){var d=" onreadystatechange='goog.onScriptLoad_(this, "+ ++goog.lastNonModuleScriptIndex_+")' ";c.write(''); - // Load fresh Closure Library. - document.write(''); - document.write(''); -} diff --git a/backend/_pv_1_3_5/static/blockly/blocks_compressed.js b/backend/_pv_1_3_5/static/blockly/blocks_compressed.js deleted file mode 100755 index 17b6b121b..000000000 --- a/backend/_pv_1_3_5/static/blockly/blocks_compressed.js +++ /dev/null @@ -1,149 +0,0 @@ -// Do not edit this file; automatically generated by build.py. -'use strict'; - - -// Copyright 2012 Google Inc. Apache License 2.0 -Blockly.Blocks.lists={};Blockly.Blocks.lists.HUE=260;Blockly.Blocks.lists_create_empty={init:function(){this.jsonInit({message0:Blockly.Msg.LISTS_CREATE_EMPTY_TITLE,output:"Array",colour:Blockly.Blocks.lists.HUE,tooltip:Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP,helpUrl:Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL})}}; -Blockly.Blocks.lists_create_with={init:function(){this.setHelpUrl(Blockly.Msg.LISTS_CREATE_WITH_HELPURL);this.setColour(Blockly.Blocks.lists.HUE);this.itemCount_=3;this.updateShape_();this.setOutput(!0,"Array");this.setMutator(new Blockly.Mutator(["lists_create_with_item"]));this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP)},mutationToDom:function(){var a=document.createElement("mutation");a.setAttribute("items",this.itemCount_);return a},domToMutation:function(a){this.itemCount_=parseInt(a.getAttribute("items"), -10);this.updateShape_()},decompose:function(a){var b=a.newBlock("lists_create_with_container");b.initSvg();for(var c=b.getInput("STACK").connection,e=0;e\u200f","GT"],["\u200f\u2265\u200f","GTE"]],b=[["=","EQ"],["\u2260","NEQ"],["<","LT"],["\u2264","LTE"],[">","GT"],["\u2265","GTE"]],a=this.RTL?a:b;this.setHelpUrl(Blockly.Msg.LOGIC_COMPARE_HELPURL);this.setColour(Blockly.Blocks.logic.HUE);this.setOutput(!0,"Boolean");this.appendValueInput("A");this.appendValueInput("B").appendField(new Blockly.FieldDropdown(a), -"OP");this.setInputsInline(!0);var c=this;this.setTooltip(function(){var a=c.getFieldValue("OP");return{EQ:Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ,NEQ:Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ,LT:Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT,LTE:Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE,GT:Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT,GTE:Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE}[a]});this.prevBlocks_=[null,null]},onchange:function(a){var b=this.getInputTargetBlock("A"),c=this.getInputTargetBlock("B");if(b&&c&&!b.outputConnection.checkType_(c.outputConnection)){Blockly.Events.setGroup(a.group); -for(a=0;ad;d++){var f=1==d?b:c;f&&!f.outputConnection.checkType_(e)&&(Blockly.Events.setGroup(a.group),e===this.prevParentConnection_?(this.unplug(),e.getSourceBlock().bumpNeighbours_()):(f.unplug(),f.bumpNeighbours_()),Blockly.Events.setGroup(!1))}this.prevParentConnection_=e}}; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/core/block.js b/backend/_pv_1_3_5/static/blockly/core/block.js deleted file mode 100755 index 2021d3f81..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/block.js +++ /dev/null @@ -1,1364 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2011 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview The class representing one block. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Block'); - -goog.require('Blockly.Blocks'); -goog.require('Blockly.Comment'); -goog.require('Blockly.Connection'); -goog.require('Blockly.Input'); -goog.require('Blockly.Mutator'); -goog.require('Blockly.Warning'); -goog.require('Blockly.Workspace'); -goog.require('Blockly.Xml'); -goog.require('goog.array'); -goog.require('goog.asserts'); -goog.require('goog.math.Coordinate'); -goog.require('goog.string'); - - -/** - * Class for one block. - * Not normally called directly, workspace.newBlock() is preferred. - * @param {!Blockly.Workspace} workspace The block's workspace. - * @param {?string} prototypeName Name of the language object containing - * type-specific functions for this block. - * @param {=string} opt_id Optional ID. Use this ID if provided, otherwise - * create a new id. - * @constructor - */ -Blockly.Block = function(workspace, prototypeName, opt_id) { - /** @type {string} */ - this.id = (opt_id && !workspace.getBlockById(opt_id)) ? - opt_id : Blockly.genUid(); - workspace.blockDB_[this.id] = this; - /** @type {Blockly.Connection} */ - this.outputConnection = null; - /** @type {Blockly.Connection} */ - this.nextConnection = null; - /** @type {Blockly.Connection} */ - this.previousConnection = null; - /** @type {!Array.} */ - this.inputList = []; - /** @type {boolean|undefined} */ - this.inputsInline = undefined; - /** @type {boolean} */ - this.disabled = false; - /** @type {string|!Function} */ - this.tooltip = ''; - /** @type {boolean} */ - this.contextMenu = true; - - /** - * @type {Blockly.Block} - * @private - */ - this.parentBlock_ = null; - - /** - * @type {!Array.} - * @private - */ - this.childBlocks_ = []; - - /** - * @type {boolean} - * @private - */ - this.deletable_ = true; - - /** - * @type {boolean} - * @private - */ - this.movable_ = true; - - /** - * @type {boolean} - * @private - */ - this.editable_ = true; - - /** - * @type {boolean} - * @private - */ - this.isShadow_ = false; - - /** - * @type {boolean} - * @private - */ - this.collapsed_ = false; - - /** @type {string|Blockly.Comment} */ - this.comment = null; - - /** - * @type {!goog.math.Coordinate} - * @private - */ - this.xy_ = new goog.math.Coordinate(0, 0); - - /** @type {!Blockly.Workspace} */ - this.workspace = workspace; - /** @type {boolean} */ - this.isInFlyout = workspace.isFlyout; - /** @type {boolean} */ - this.isInMutator = workspace.isMutator; - - /** @type {boolean} */ - this.RTL = workspace.RTL; - - // Copy the type-specific functions and data from the prototype. - if (prototypeName) { - /** @type {string} */ - this.type = prototypeName; - var prototype = Blockly.Blocks[prototypeName]; - goog.asserts.assertObject(prototype, - 'Error: "%s" is an unknown language block.', prototypeName); - goog.mixin(this, prototype); - } - - workspace.addTopBlock(this); - - // Call an initialization function, if it exists. - if (goog.isFunction(this.init)) { - this.init(); - } - // Record initial inline state. - /** @type {boolean|undefined} */ - this.inputsInlineDefault = this.inputsInline; - if (Blockly.Events.isEnabled()) { - Blockly.Events.fire(new Blockly.Events.Create(this)); - } - // Bind an onchange function, if it exists. - if (goog.isFunction(this.onchange)) { - this.onchangeWrapper_ = this.onchange.bind(this); - this.workspace.addChangeListener(this.onchangeWrapper_); - } -}; - -/** - * Obtain a newly created block. - * @param {!Blockly.Workspace} workspace The block's workspace. - * @param {?string} prototypeName Name of the language object containing - * type-specific functions for this block. - * @return {!Blockly.Block} The created block. - * @deprecated December 2015 - */ -Blockly.Block.obtain = function(workspace, prototypeName) { - console.warn('Deprecated call to Blockly.Block.obtain, ' + - 'use workspace.newBlock instead.'); - return workspace.newBlock(prototypeName); -}; - -/** - * Optional text data that round-trips beween blocks and XML. - * Has no effect. May be used by 3rd parties for meta information. - * @type {?string} - */ -Blockly.Block.prototype.data = null; - -/** - * Colour of the block in '#RRGGBB' format. - * @type {string} - * @private - */ -Blockly.Block.prototype.colour_ = '#000000'; - -/** - * Dispose of this block. - * @param {boolean} healStack If true, then try to heal any gap by connecting - * the next statement with the previous statement. Otherwise, dispose of - * all children of this block. - */ -Blockly.Block.prototype.dispose = function(healStack) { - if (!this.workspace) { - // Already deleted. - return; - } - // Terminate onchange event calls. - if (this.onchangeWrapper_) { - this.workspace.removeChangeListener(this.onchangeWrapper_); - } - this.unplug(healStack); - if (Blockly.Events.isEnabled()) { - Blockly.Events.fire(new Blockly.Events.Delete(this)); - } - Blockly.Events.disable(); - - try { - // This block is now at the top of the workspace. - // Remove this block from the workspace's list of top-most blocks. - if (this.workspace) { - this.workspace.removeTopBlock(this); - // Remove from block database. - delete this.workspace.blockDB_[this.id]; - this.workspace = null; - } - - // Just deleting this block from the DOM would result in a memory leak as - // well as corruption of the connection database. Therefore we must - // methodically step through the blocks and carefully disassemble them. - - // First, dispose of all my children. - for (var i = this.childBlocks_.length - 1; i >= 0; i--) { - this.childBlocks_[i].dispose(false); - } - // Then dispose of myself. - // Dispose of all inputs and their fields. - for (var i = 0, input; input = this.inputList[i]; i++) { - input.dispose(); - } - this.inputList.length = 0; - // Dispose of any remaining connections (next/previous/output). - var connections = this.getConnections_(true); - for (var i = 0; i < connections.length; i++) { - var connection = connections[i]; - if (connection.isConnected()) { - connection.disconnect(); - } - connections[i].dispose(); - } - } finally { - Blockly.Events.enable(); - } -}; - -/** - * Unplug this block from its superior block. If this block is a statement, - * optionally reconnect the block underneath with the block on top. - * @param {boolean} opt_healStack Disconnect child statement and reconnect - * stack. Defaults to false. - */ -Blockly.Block.prototype.unplug = function(opt_healStack) { - if (this.outputConnection) { - if (this.outputConnection.isConnected()) { - // Disconnect from any superior block. - this.outputConnection.disconnect(); - } - } else if (this.previousConnection) { - var previousTarget = null; - if (this.previousConnection.isConnected()) { - // Remember the connection that any next statements need to connect to. - previousTarget = this.previousConnection.targetConnection; - // Detach this block from the parent's tree. - this.previousConnection.disconnect(); - } - var nextBlock = this.getNextBlock(); - if (opt_healStack && nextBlock) { - // Disconnect the next statement. - var nextTarget = this.nextConnection.targetConnection; - nextTarget.disconnect(); - if (previousTarget && previousTarget.checkType_(nextTarget)) { - // Attach the next statement to the previous statement. - previousTarget.connect(nextTarget); - } - } - } -}; - -/** - * Returns all connections originating from this block. - * @return {!Array.} Array of connections. - * @private - */ -Blockly.Block.prototype.getConnections_ = function() { - var myConnections = []; - if (this.outputConnection) { - myConnections.push(this.outputConnection); - } - if (this.previousConnection) { - myConnections.push(this.previousConnection); - } - if (this.nextConnection) { - myConnections.push(this.nextConnection); - } - for (var i = 0, input; input = this.inputList[i]; i++) { - if (input.connection) { - myConnections.push(input.connection); - } - } - return myConnections; -}; - -/** - * Walks down a stack of blocks and finds the last next connection on the stack. - * @return {Blockly.Connection} The last next connection on the stack, or null. - * @private - */ -Blockly.Block.prototype.lastConnectionInStack_ = function() { - var nextConnection = this.nextConnection; - while (nextConnection) { - var nextBlock = nextConnection.targetBlock(); - if (!nextBlock) { - // Found a next connection with nothing on the other side. - return nextConnection; - } - nextConnection = nextBlock.nextConnection; - } - // Ran out of next connections. - return null; -}; - -/** - * Bump unconnected blocks out of alignment. Two blocks which aren't actually - * connected should not coincidentally line up on screen. - * @private - */ -Blockly.Block.prototype.bumpNeighbours_ = function() { - if (!this.workspace) { - return; // Deleted block. - } - if (Blockly.dragMode_ != Blockly.DRAG_NONE) { - return; // Don't bump blocks during a drag. - } - var rootBlock = this.getRootBlock(); - if (rootBlock.isInFlyout) { - return; // Don't move blocks around in a flyout. - } - // Loop though every connection on this block. - var myConnections = this.getConnections_(false); - for (var i = 0, connection; connection = myConnections[i]; i++) { - // Spider down from this block bumping all sub-blocks. - if (connection.isConnected() && connection.isSuperior()) { - connection.targetBlock().bumpNeighbours_(); - } - - var neighbours = connection.neighbours_(Blockly.SNAP_RADIUS); - for (var j = 0, otherConnection; otherConnection = neighbours[j]; j++) { - // If both connections are connected, that's probably fine. But if - // either one of them is unconnected, then there could be confusion. - if (!connection.isConnected() || !otherConnection.isConnected()) { - // Only bump blocks if they are from different tree structures. - if (otherConnection.getSourceBlock().getRootBlock() != rootBlock) { - // Always bump the inferior block. - if (connection.isSuperior()) { - otherConnection.bumpAwayFrom_(connection); - } else { - connection.bumpAwayFrom_(otherConnection); - } - } - } - } - } -}; - -/** - * Return the parent block or null if this block is at the top level. - * @return {Blockly.Block} The block that holds the current block. - */ -Blockly.Block.prototype.getParent = function() { - // Look at the DOM to see if we are nested in another block. - return this.parentBlock_; -}; - -/** - * Return the input that connects to the specified block. - * @param {!Blockly.Block} block A block connected to an input on this block. - * @return {Blockly.Input} The input that connects to the specified block. - */ -Blockly.Block.prototype.getInputWithBlock = function(block) { - for (var i = 0, input; input = this.inputList[i]; i++) { - if (input.connection && input.connection.targetBlock() == block) { - return input; - } - } - return null; -}; - -/** - * Return the parent block that surrounds the current block, or null if this - * block has no surrounding block. A parent block might just be the previous - * statement, whereas the surrounding block is an if statement, while loop, etc. - * @return {Blockly.Block} The block that surrounds the current block. - */ -Blockly.Block.prototype.getSurroundParent = function() { - var block = this; - do { - var prevBlock = block; - block = block.getParent(); - if (!block) { - // Ran off the top. - return null; - } - } while (block.getNextBlock() == prevBlock); - // This block is an enclosing parent, not just a statement in a stack. - return block; -}; - -/** - * Return the next statement block directly connected to this block. - * @return {Blockly.Block} The next statement block or null. - */ -Blockly.Block.prototype.getNextBlock = function() { - return this.nextConnection && this.nextConnection.targetBlock(); -}; - -/** - * Return the top-most block in this block's tree. - * This will return itself if this block is at the top level. - * @return {!Blockly.Block} The root block. - */ -Blockly.Block.prototype.getRootBlock = function() { - var rootBlock; - var block = this; - do { - rootBlock = block; - block = rootBlock.parentBlock_; - } while (block); - return rootBlock; -}; - -/** - * Find all the blocks that are directly nested inside this one. - * Includes value and block inputs, as well as any following statement. - * Excludes any connection on an output tab or any preceding statement. - * @return {!Array.} Array of blocks. - */ -Blockly.Block.prototype.getChildren = function() { - return this.childBlocks_; -}; - -/** - * Set parent of this block to be a new block or null. - * @param {Blockly.Block} newParent New parent block. - */ -Blockly.Block.prototype.setParent = function(newParent) { - if (newParent == this.parentBlock_) { - return; - } - if (this.parentBlock_) { - // Remove this block from the old parent's child list. - var children = this.parentBlock_.childBlocks_; - for (var child, x = 0; child = children[x]; x++) { - if (child == this) { - children.splice(x, 1); - break; - } - } - - // Disconnect from superior blocks. - if (this.previousConnection && this.previousConnection.isConnected()) { - throw 'Still connected to previous block.'; - } - if (this.outputConnection && this.outputConnection.isConnected()) { - throw 'Still connected to parent block.'; - } - this.parentBlock_ = null; - // This block hasn't actually moved on-screen, so there's no need to update - // its connection locations. - } else { - // Remove this block from the workspace's list of top-most blocks. - this.workspace.removeTopBlock(this); - } - - this.parentBlock_ = newParent; - if (newParent) { - // Add this block to the new parent's child list. - newParent.childBlocks_.push(this); - } else { - this.workspace.addTopBlock(this); - } -}; - -/** - * Find all the blocks that are directly or indirectly nested inside this one. - * Includes this block in the list. - * Includes value and block inputs, as well as any following statements. - * Excludes any connection on an output tab or any preceding statements. - * @return {!Array.} Flattened array of blocks. - */ -Blockly.Block.prototype.getDescendants = function() { - var blocks = [this]; - for (var child, x = 0; child = this.childBlocks_[x]; x++) { - blocks.push.apply(blocks, child.getDescendants()); - } - return blocks; -}; - -/** - * Get whether this block is deletable or not. - * @return {boolean} True if deletable. - */ -Blockly.Block.prototype.isDeletable = function() { - return this.deletable_ && !this.isShadow_ && - !(this.workspace && this.workspace.options.readOnly); -}; - -/** - * Set whether this block is deletable or not. - * @param {boolean} deletable True if deletable. - */ -Blockly.Block.prototype.setDeletable = function(deletable) { - this.deletable_ = deletable; -}; - -/** - * Get whether this block is movable or not. - * @return {boolean} True if movable. - */ -Blockly.Block.prototype.isMovable = function() { - return this.movable_ && !this.isShadow_ && - !(this.workspace && this.workspace.options.readOnly); -}; - -/** - * Set whether this block is movable or not. - * @param {boolean} movable True if movable. - */ -Blockly.Block.prototype.setMovable = function(movable) { - this.movable_ = movable; -}; - -/** - * Get whether this block is a shadow block or not. - * @return {boolean} True if a shadow. - */ -Blockly.Block.prototype.isShadow = function() { - return this.isShadow_; -}; - -/** - * Set whether this block is a shadow block or not. - * @param {boolean} shadow True if a shadow. - */ -Blockly.Block.prototype.setShadow = function(shadow) { - this.isShadow_ = shadow; -}; - -/** - * Get whether this block is editable or not. - * @return {boolean} True if editable. - */ -Blockly.Block.prototype.isEditable = function() { - return this.editable_ && !(this.workspace && this.workspace.options.readOnly); -}; - -/** - * Set whether this block is editable or not. - * @param {boolean} editable True if editable. - */ -Blockly.Block.prototype.setEditable = function(editable) { - this.editable_ = editable; - for (var i = 0, input; input = this.inputList[i]; i++) { - for (var j = 0, field; field = input.fieldRow[j]; j++) { - field.updateEditable(); - } - } -}; - -/** - * Set whether the connections are hidden (not tracked in a database) or not. - * Recursively walk down all child blocks (except collapsed blocks). - * @param {boolean} hidden True if connections are hidden. - */ -Blockly.Block.prototype.setConnectionsHidden = function(hidden) { - if (!hidden && this.isCollapsed()) { - if (this.outputConnection) { - this.outputConnection.setHidden(hidden); - } - if (this.previousConnection) { - this.previousConnection.setHidden(hidden); - } - if (this.nextConnection) { - this.nextConnection.setHidden(hidden); - var child = this.nextConnection.targetBlock(); - if (child) { - child.setConnectionsHidden(hidden); - } - } - } else { - var myConnections = this.getConnections_(true); - for (var i = 0, connection; connection = myConnections[i]; i++) { - connection.setHidden(hidden); - if (connection.isSuperior()) { - var child = connection.targetBlock(); - if (child) { - child.setConnectionsHidden(hidden); - } - } - } - } -}; - -/** - * Set the URL of this block's help page. - * @param {string|Function} url URL string for block help, or function that - * returns a URL. Null for no help. - */ -Blockly.Block.prototype.setHelpUrl = function(url) { - this.helpUrl = url; -}; - -/** - * Change the tooltip text for a block. - * @param {string|!Function} newTip Text for tooltip or a parent element to - * link to for its tooltip. May be a function that returns a string. - */ -Blockly.Block.prototype.setTooltip = function(newTip) { - this.tooltip = newTip; -}; - -/** - * Get the colour of a block. - * @return {string} #RRGGBB string. - */ -Blockly.Block.prototype.getColour = function() { - return this.colour_; -}; - -/** - * Change the colour of a block. - * @param {number|string} colour HSV hue value, or #RRGGBB string. - */ -Blockly.Block.prototype.setColour = function(colour) { - var hue = parseFloat(colour); - if (!isNaN(hue)) { - this.colour_ = Blockly.hueToRgb(hue); - } else if (goog.isString(colour) && colour.match(/^#[0-9a-fA-F]{6}$/)) { - this.colour_ = colour; - } else { - throw 'Invalid colour: ' + colour; - } -}; - -/** - * Returns the named field from a block. - * @param {string} name The name of the field. - * @return {Blockly.Field} Named field, or null if field does not exist. - */ -Blockly.Block.prototype.getField = function(name) { - for (var i = 0, input; input = this.inputList[i]; i++) { - for (var j = 0, field; field = input.fieldRow[j]; j++) { - if (field.name === name) { - return field; - } - } - } - return null; -}; - -/** - * Return all variables referenced by this block. - * @return {!Array.} List of variable names. - */ -Blockly.Block.prototype.getVars = function() { - var vars = []; - for (var i = 0, input; input = this.inputList[i]; i++) { - for (var j = 0, field; field = input.fieldRow[j]; j++) { - if (field instanceof Blockly.FieldVariable) { - vars.push(field.getValue()); - } - } - } - return vars; -}; - -/** - * Notification that a variable is renaming. - * If the name matches one of this block's variables, rename it. - * @param {string} oldName Previous name of variable. - * @param {string} newName Renamed variable. - */ -Blockly.Block.prototype.renameVar = function(oldName, newName) { - for (var i = 0, input; input = this.inputList[i]; i++) { - for (var j = 0, field; field = input.fieldRow[j]; j++) { - if (field instanceof Blockly.FieldVariable && - Blockly.Names.equals(oldName, field.getValue())) { - field.setValue(newName); - } - } - } -}; - -/** - * Returns the language-neutral value from the field of a block. - * @param {string} name The name of the field. - * @return {?string} Value from the field or null if field does not exist. - */ -Blockly.Block.prototype.getFieldValue = function(name) { - var field = this.getField(name); - if (field) { - return field.getValue(); - } - return null; -}; - -/** - * Returns the language-neutral value from the field of a block. - * @param {string} name The name of the field. - * @return {?string} Value from the field or null if field does not exist. - * @deprecated December 2013 - */ -Blockly.Block.prototype.getTitleValue = function(name) { - console.warn('Deprecated call to getTitleValue, use getFieldValue instead.'); - return this.getFieldValue(name); -}; - -/** - * Change the field value for a block (e.g. 'CHOOSE' or 'REMOVE'). - * @param {string} newValue Value to be the new field. - * @param {string} name The name of the field. - */ -Blockly.Block.prototype.setFieldValue = function(newValue, name) { - var field = this.getField(name); - goog.asserts.assertObject(field, 'Field "%s" not found.', name); - field.setValue(newValue); -}; - -/** - * Change the field value for a block (e.g. 'CHOOSE' or 'REMOVE'). - * @param {string} newValue Value to be the new field. - * @param {string} name The name of the field. - * @deprecated December 2013 - */ -Blockly.Block.prototype.setTitleValue = function(newValue, name) { - console.warn('Deprecated call to setTitleValue, use setFieldValue instead.'); - this.setFieldValue(newValue, name); -}; - -/** - * Set whether this block can chain onto the bottom of another block. - * @param {boolean} newBoolean True if there can be a previous statement. - * @param {string|Array.|null|undefined} opt_check Statement type or - * list of statement types. Null/undefined if any type could be connected. - */ -Blockly.Block.prototype.setPreviousStatement = function(newBoolean, opt_check) { - if (newBoolean) { - if (opt_check === undefined) { - opt_check = null; - } - if (!this.previousConnection) { - goog.asserts.assert(!this.outputConnection, - 'Remove output connection prior to adding previous connection.'); - this.previousConnection = - this.makeConnection_(Blockly.PREVIOUS_STATEMENT); - } - this.previousConnection.setCheck(opt_check); - } else { - if (this.previousConnection) { - goog.asserts.assert(!this.previousConnection.isConnected(), - 'Must disconnect previous statement before removing connection.'); - this.previousConnection.dispose(); - this.previousConnection = null; - } - } -}; - -/** - * Set whether another block can chain onto the bottom of this block. - * @param {boolean} newBoolean True if there can be a next statement. - * @param {string|Array.|null|undefined} opt_check Statement type or - * list of statement types. Null/undefined if any type could be connected. - */ -Blockly.Block.prototype.setNextStatement = function(newBoolean, opt_check) { - if (newBoolean) { - if (opt_check === undefined) { - opt_check = null; - } - if (!this.nextConnection) { - this.nextConnection = this.makeConnection_(Blockly.NEXT_STATEMENT); - } - this.nextConnection.setCheck(opt_check); - } else { - if (this.nextConnection) { - goog.asserts.assert(!this.nextConnection.isConnected(), - 'Must disconnect next statement before removing connection.'); - this.nextConnection.dispose(); - this.nextConnection = null; - } - } -}; - -/** - * Set whether this block returns a value. - * @param {boolean} newBoolean True if there is an output. - * @param {string|Array.|null|undefined} opt_check Returned type or list - * of returned types. Null or undefined if any type could be returned - * (e.g. variable get). - */ -Blockly.Block.prototype.setOutput = function(newBoolean, opt_check) { - if (newBoolean) { - if (opt_check === undefined) { - opt_check = null; - } - if (!this.outputConnection) { - goog.asserts.assert(!this.previousConnection, - 'Remove previous connection prior to adding output connection.'); - this.outputConnection = this.makeConnection_(Blockly.OUTPUT_VALUE); - } - this.outputConnection.setCheck(opt_check); - } else { - if (this.outputConnection) { - goog.asserts.assert(!this.outputConnection.isConnected(), - 'Must disconnect output value before removing connection.'); - this.outputConnection.dispose(); - this.outputConnection = null; - } - } -}; - -/** - * Set whether value inputs are arranged horizontally or vertically. - * @param {boolean} newBoolean True if inputs are horizontal. - */ -Blockly.Block.prototype.setInputsInline = function(newBoolean) { - if (this.inputsInline != newBoolean) { - Blockly.Events.fire(new Blockly.Events.Change( - this, 'inline', null, this.inputsInline, newBoolean)); - this.inputsInline = newBoolean; - } -}; - -/** - * Get whether value inputs are arranged horizontally or vertically. - * @return {boolean} True if inputs are horizontal. - */ -Blockly.Block.prototype.getInputsInline = function() { - if (this.inputsInline != undefined) { - // Set explicitly. - return this.inputsInline; - } - // Not defined explicitly. Figure out what would look best. - for (var i = 1; i < this.inputList.length; i++) { - if (this.inputList[i - 1].type == Blockly.DUMMY_INPUT && - this.inputList[i].type == Blockly.DUMMY_INPUT) { - // Two dummy inputs in a row. Don't inline them. - return false; - } - } - for (var i = 1; i < this.inputList.length; i++) { - if (this.inputList[i - 1].type == Blockly.INPUT_VALUE && - this.inputList[i].type == Blockly.DUMMY_INPUT) { - // Dummy input after a value input. Inline them. - return true; - } - } - return false; -}; - -/** - * Set whether the block is disabled or not. - * @param {boolean} disabled True if disabled. - */ -Blockly.Block.prototype.setDisabled = function(disabled) { - if (this.disabled != disabled) { - Blockly.Events.fire(new Blockly.Events.Change( - this, 'disabled', null, this.disabled, disabled)); - this.disabled = disabled; - } -}; - -/** - * Get whether the block is disabled or not due to parents. - * The block's own disabled property is not considered. - * @return {boolean} True if disabled. - */ -Blockly.Block.prototype.getInheritedDisabled = function() { - var block = this; - while (true) { - block = block.getSurroundParent(); - if (!block) { - // Ran off the top. - return false; - } else if (block.disabled) { - return true; - } - } -}; - -/** - * Get whether the block is collapsed or not. - * @return {boolean} True if collapsed. - */ -Blockly.Block.prototype.isCollapsed = function() { - return this.collapsed_; -}; - -/** - * Set whether the block is collapsed or not. - * @param {boolean} collapsed True if collapsed. - */ -Blockly.Block.prototype.setCollapsed = function(collapsed) { - if (this.collapsed_ != collapsed) { - Blockly.Events.fire(new Blockly.Events.Change( - this, 'collapsed', null, this.collapsed_, collapsed)); - this.collapsed_ = collapsed; - } -}; - -/** - * Create a human-readable text representation of this block and any children. - * @param {number=} opt_maxLength Truncate the string to this length. - * @param {string=} opt_emptyToken The placeholder string used to denote an - * empty field. If not specified, '?' is used. - * @return {string} Text of block. - */ -Blockly.Block.prototype.toString = function(opt_maxLength, opt_emptyToken) { - var text = []; - var emptyFieldPlaceholder = opt_emptyToken || '?'; - if (this.collapsed_) { - text.push(this.getInput('_TEMP_COLLAPSED_INPUT').fieldRow[0].text_); - } else { - for (var i = 0, input; input = this.inputList[i]; i++) { - for (var j = 0, field; field = input.fieldRow[j]; j++) { - text.push(field.getText()); - } - if (input.connection) { - var child = input.connection.targetBlock(); - if (child) { - text.push(child.toString(undefined, opt_emptyToken)); - } else { - text.push(emptyFieldPlaceholder); - } - } - } - } - text = goog.string.trim(text.join(' ')) || '???'; - if (opt_maxLength) { - // TODO: Improve truncation so that text from this block is given priority. - // E.g. "1+2+3+4+5+6+7+8+9=0" should be "...6+7+8+9=0", not "1+2+3+4+5...". - // E.g. "1+2+3+4+5=6+7+8+9+0" should be "...4+5=6+7...". - text = goog.string.truncate(text, opt_maxLength); - } - return text; -}; - -/** - * Shortcut for appending a value input row. - * @param {string} name Language-neutral identifier which may used to find this - * input again. Should be unique to this block. - * @return {!Blockly.Input} The input object created. - */ -Blockly.Block.prototype.appendValueInput = function(name) { - return this.appendInput_(Blockly.INPUT_VALUE, name); -}; - -/** - * Shortcut for appending a statement input row. - * @param {string} name Language-neutral identifier which may used to find this - * input again. Should be unique to this block. - * @return {!Blockly.Input} The input object created. - */ -Blockly.Block.prototype.appendStatementInput = function(name) { - return this.appendInput_(Blockly.NEXT_STATEMENT, name); -}; - -/** - * Shortcut for appending a dummy input row. - * @param {string=} opt_name Language-neutral identifier which may used to find - * this input again. Should be unique to this block. - * @return {!Blockly.Input} The input object created. - */ -Blockly.Block.prototype.appendDummyInput = function(opt_name) { - return this.appendInput_(Blockly.DUMMY_INPUT, opt_name || ''); -}; - -/** - * Initialize this block using a cross-platform, internationalization-friendly - * JSON description. - * @param {!Object} json Structured data describing the block. - */ -Blockly.Block.prototype.jsonInit = function(json) { - // Validate inputs. - goog.asserts.assert(json['output'] == undefined || - json['previousStatement'] == undefined, - 'Must not have both an output and a previousStatement.'); - - // Set basic properties of block. - if (json['colour'] !== undefined) { - this.setColour(json['colour']); - } - - // Interpolate the message blocks. - var i = 0; - while (json['message' + i] !== undefined) { - this.interpolate_(json['message' + i], json['args' + i] || [], - json['lastDummyAlign' + i]); - i++; - } - - if (json['inputsInline'] !== undefined) { - this.setInputsInline(json['inputsInline']); - } - // Set output and previous/next connections. - if (json['output'] !== undefined) { - this.setOutput(true, json['output']); - } - if (json['previousStatement'] !== undefined) { - this.setPreviousStatement(true, json['previousStatement']); - } - if (json['nextStatement'] !== undefined) { - this.setNextStatement(true, json['nextStatement']); - } - if (json['tooltip'] !== undefined) { - this.setTooltip(json['tooltip']); - } - if (json['helpUrl'] !== undefined) { - this.setHelpUrl(json['helpUrl']); - } -}; - -/** - * Interpolate a message description onto the block. - * @param {string} message Text contains interpolation tokens (%1, %2, ...) - * that match with fields or inputs defined in the args array. - * @param {!Array} args Array of arguments to be interpolated. - * @param {=string} lastDummyAlign If a dummy input is added at the end, - * how should it be aligned? - * @private - */ -Blockly.Block.prototype.interpolate_ = function(message, args, lastDummyAlign) { - var tokens = Blockly.utils.tokenizeInterpolation(message); - // Interpolate the arguments. Build a list of elements. - var indexDup = []; - var indexCount = 0; - var elements = []; - for (var i = 0; i < tokens.length; i++) { - var token = tokens[i]; - if (typeof token == 'number') { - goog.asserts.assert(token > 0 && token <= args.length, - 'Message index "%s" out of range.', token); - goog.asserts.assert(!indexDup[token], - 'Message index "%s" duplicated.', token); - indexDup[token] = true; - indexCount++; - elements.push(args[token - 1]); - } else { - token = token.trim(); - if (token) { - elements.push(token); - } - } - } - goog.asserts.assert(indexCount == args.length, - 'Message does not reference all %s arg(s).', args.length); - // Add last dummy input if needed. - if (elements.length && (typeof elements[elements.length - 1] == 'string' || - elements[elements.length - 1]['type'].indexOf('field_') == 0)) { - var dummyInput = {type: 'input_dummy'}; - if (lastDummyAlign) { - dummyInput['align'] = lastDummyAlign; - } - elements.push(dummyInput); - } - // Lookup of alignment constants. - var alignmentLookup = { - 'LEFT': Blockly.ALIGN_LEFT, - 'RIGHT': Blockly.ALIGN_RIGHT, - 'CENTRE': Blockly.ALIGN_CENTRE - }; - // Populate block with inputs and fields. - var fieldStack = []; - for (var i = 0; i < elements.length; i++) { - var element = elements[i]; - if (typeof element == 'string') { - fieldStack.push([element, undefined]); - } else { - var field = null; - var input = null; - do { - var altRepeat = false; - if (typeof element == 'string') { - field = new Blockly.FieldLabel(element); - } else { - switch (element['type']) { - case 'input_value': - input = this.appendValueInput(element['name']); - break; - case 'input_statement': - input = this.appendStatementInput(element['name']); - break; - case 'input_dummy': - input = this.appendDummyInput(element['name']); - break; - case 'field_label': - field = new Blockly.FieldLabel(element['text'], element['class']); - break; - case 'field_input': - field = new Blockly.FieldTextInput(element['text']); - if (typeof element['spellcheck'] == 'boolean') { - field.setSpellcheck(element['spellcheck']); - } - break; - case 'field_angle': - field = new Blockly.FieldAngle(element['angle']); - break; - case 'field_checkbox': - field = new Blockly.FieldCheckbox( - element['checked'] ? 'TRUE' : 'FALSE'); - break; - case 'field_colour': - field = new Blockly.FieldColour(element['colour']); - break; - case 'field_variable': - field = new Blockly.FieldVariable(element['variable']); - break; - case 'field_dropdown': - field = new Blockly.FieldDropdown(element['options']); - break; - case 'field_image': - field = new Blockly.FieldImage(element['src'], - element['width'], element['height'], element['alt']); - break; - case 'field_number': - field = new Blockly.FieldNumber(element['value'], - element['min'], element['max'], element['precision']); - break; - case 'field_date': - if (Blockly.FieldDate) { - field = new Blockly.FieldDate(element['date']); - break; - } - // Fall through if FieldDate is not compiled in. - default: - // Unknown field. - if (element['alt']) { - element = element['alt']; - altRepeat = true; - } - } - } - } while (altRepeat); - if (field) { - fieldStack.push([field, element['name']]); - } else if (input) { - if (element['check']) { - input.setCheck(element['check']); - } - if (element['align']) { - input.setAlign(alignmentLookup[element['align']]); - } - for (var j = 0; j < fieldStack.length; j++) { - input.appendField(fieldStack[j][0], fieldStack[j][1]); - } - fieldStack.length = 0; - } - } - } -}; - -/** - * Add a value input, statement input or local variable to this block. - * @param {number} type Either Blockly.INPUT_VALUE or Blockly.NEXT_STATEMENT or - * Blockly.DUMMY_INPUT. - * @param {string} name Language-neutral identifier which may used to find this - * input again. Should be unique to this block. - * @return {!Blockly.Input} The input object created. - * @private - */ -Blockly.Block.prototype.appendInput_ = function(type, name) { - var connection = null; - if (type == Blockly.INPUT_VALUE || type == Blockly.NEXT_STATEMENT) { - connection = this.makeConnection_(type); - } - var input = new Blockly.Input(type, name, this, connection); - // Append input to list. - this.inputList.push(input); - return input; -}; - -/** - * Move a named input to a different location on this block. - * @param {string} name The name of the input to move. - * @param {?string} refName Name of input that should be after the moved input, - * or null to be the input at the end. - */ -Blockly.Block.prototype.moveInputBefore = function(name, refName) { - if (name == refName) { - return; - } - // Find both inputs. - var inputIndex = -1; - var refIndex = refName ? -1 : this.inputList.length; - for (var i = 0, input; input = this.inputList[i]; i++) { - if (input.name == name) { - inputIndex = i; - if (refIndex != -1) { - break; - } - } else if (refName && input.name == refName) { - refIndex = i; - if (inputIndex != -1) { - break; - } - } - } - goog.asserts.assert(inputIndex != -1, 'Named input "%s" not found.', name); - goog.asserts.assert(refIndex != -1, 'Reference input "%s" not found.', - refName); - this.moveNumberedInputBefore(inputIndex, refIndex); -}; - -/** - * Move a numbered input to a different location on this block. - * @param {number} inputIndex Index of the input to move. - * @param {number} refIndex Index of input that should be after the moved input. - */ -Blockly.Block.prototype.moveNumberedInputBefore = function( - inputIndex, refIndex) { - // Validate arguments. - goog.asserts.assert(inputIndex != refIndex, 'Can\'t move input to itself.'); - goog.asserts.assert(inputIndex < this.inputList.length, - 'Input index ' + inputIndex + ' out of bounds.'); - goog.asserts.assert(refIndex <= this.inputList.length, - 'Reference input ' + refIndex + ' out of bounds.'); - // Remove input. - var input = this.inputList[inputIndex]; - this.inputList.splice(inputIndex, 1); - if (inputIndex < refIndex) { - refIndex--; - } - // Reinsert input. - this.inputList.splice(refIndex, 0, input); -}; - -/** - * Remove an input from this block. - * @param {string} name The name of the input. - * @param {boolean=} opt_quiet True to prevent error if input is not present. - * @throws {goog.asserts.AssertionError} if the input is not present and - * opt_quiet is not true. - */ -Blockly.Block.prototype.removeInput = function(name, opt_quiet) { - for (var i = 0, input; input = this.inputList[i]; i++) { - if (input.name == name) { - if (input.connection && input.connection.isConnected()) { - input.connection.setShadowDom(null); - var block = input.connection.targetBlock(); - if (block.isShadow()) { - // Destroy any attached shadow block. - block.dispose(); - } else { - // Disconnect any attached normal block. - block.unplug(); - } - } - input.dispose(); - this.inputList.splice(i, 1); - return; - } - } - if (!opt_quiet) { - goog.asserts.fail('Input "%s" not found.', name); - } -}; - -/** - * Fetches the named input object. - * @param {string} name The name of the input. - * @return {Blockly.Input} The input object, or null if input does not exist. - */ -Blockly.Block.prototype.getInput = function(name) { - for (var i = 0, input; input = this.inputList[i]; i++) { - if (input.name == name) { - return input; - } - } - // This input does not exist. - return null; -}; - -/** - * Fetches the block attached to the named input. - * @param {string} name The name of the input. - * @return {Blockly.Block} The attached value block, or null if the input is - * either disconnected or if the input does not exist. - */ -Blockly.Block.prototype.getInputTargetBlock = function(name) { - var input = this.getInput(name); - return input && input.connection && input.connection.targetBlock(); -}; - -/** - * Returns the comment on this block (or '' if none). - * @return {string} Block's comment. - */ -Blockly.Block.prototype.getCommentText = function() { - return this.comment || ''; -}; - -/** - * Set this block's comment text. - * @param {?string} text The text, or null to delete. - */ -Blockly.Block.prototype.setCommentText = function(text) { - if (this.comment != text) { - Blockly.Events.fire(new Blockly.Events.Change( - this, 'comment', null, this.comment, text || '')); - this.comment = text; - } -}; - -/** - * Set this block's warning text. - * @param {?string} text The text, or null to delete. - */ -Blockly.Block.prototype.setWarningText = function(text) { - // NOP. -}; - -/** - * Give this block a mutator dialog. - * @param {Blockly.Mutator} mutator A mutator dialog instance or null to remove. - */ -Blockly.Block.prototype.setMutator = function(mutator) { - // NOP. -}; - -/** - * Return the coordinates of the top-left corner of this block relative to the - * drawing surface's origin (0,0). - * @return {!goog.math.Coordinate} Object with .x and .y properties. - */ -Blockly.Block.prototype.getRelativeToSurfaceXY = function() { - return this.xy_; -}; - -/** - * Move a block by a relative offset. - * @param {number} dx Horizontal offset. - * @param {number} dy Vertical offset. - */ -Blockly.Block.prototype.moveBy = function(dx, dy) { - goog.asserts.assert(!this.parentBlock_, 'Block has parent.'); - var event = new Blockly.Events.Move(this); - this.xy_.translate(dx, dy); - event.recordNew(); - Blockly.Events.fire(event); -}; - -/** - * Create a connection of the specified type. - * @param {number} type The type of the connection to create. - * @return {!Blockly.Connection} A new connection of the specified type. - * @private - */ -Blockly.Block.prototype.makeConnection_ = function(type) { - return new Blockly.Connection(this, type); -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/block_render_svg.js b/backend/_pv_1_3_5/static/blockly/core/block_render_svg.js deleted file mode 100755 index 14c42b0af..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/block_render_svg.js +++ /dev/null @@ -1,969 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Methods for graphically rendering a block as SVG. - * @author fenichel@google.com (Rachel Fenichel) - */ - -'use strict'; - -goog.provide('Blockly.BlockSvg.render'); - -goog.require('Blockly.BlockSvg'); - - -// UI constants for rendering blocks. -/** - * Horizontal space between elements. - * @const - */ -Blockly.BlockSvg.SEP_SPACE_X = 10; -/** - * Vertical space between elements. - * @const - */ -Blockly.BlockSvg.SEP_SPACE_Y = 10; -/** - * Vertical padding around inline elements. - * @const - */ -Blockly.BlockSvg.INLINE_PADDING_Y = 5; -/** - * Minimum height of a block. - * @const - */ -Blockly.BlockSvg.MIN_BLOCK_Y = 25; -/** - * Height of horizontal puzzle tab. - * @const - */ -Blockly.BlockSvg.TAB_HEIGHT = 20; -/** - * Width of horizontal puzzle tab. - * @const - */ -Blockly.BlockSvg.TAB_WIDTH = 8; -/** - * Width of vertical tab (inc left margin). - * @const - */ -Blockly.BlockSvg.NOTCH_WIDTH = 30; -/** - * Rounded corner radius. - * @const - */ -Blockly.BlockSvg.CORNER_RADIUS = 8; -/** - * Do blocks with no previous or output connections have a 'hat' on top? - * @const - */ -Blockly.BlockSvg.START_HAT = false; -/** - * Height of the top hat. - * @const - */ -Blockly.BlockSvg.START_HAT_HEIGHT = 15; -/** - * Path of the top hat's curve. - * @const - */ -Blockly.BlockSvg.START_HAT_PATH = 'c 30,-' + - Blockly.BlockSvg.START_HAT_HEIGHT + ' 70,-' + - Blockly.BlockSvg.START_HAT_HEIGHT + ' 100,0'; -/** - * Path of the top hat's curve's highlight in LTR. - * @const - */ -Blockly.BlockSvg.START_HAT_HIGHLIGHT_LTR = - 'c 17.8,-9.2 45.3,-14.9 75,-8.7 M 100.5,0.5'; -/** - * Path of the top hat's curve's highlight in RTL. - * @const - */ -Blockly.BlockSvg.START_HAT_HIGHLIGHT_RTL = - 'm 25,-8.7 c 29.7,-6.2 57.2,-0.5 75,8.7'; -/** - * Distance from shape edge to intersect with a curved corner at 45 degrees. - * Applies to highlighting on around the inside of a curve. - * @const - */ -Blockly.BlockSvg.DISTANCE_45_INSIDE = (1 - Math.SQRT1_2) * - (Blockly.BlockSvg.CORNER_RADIUS - 0.5) + 0.5; -/** - * Distance from shape edge to intersect with a curved corner at 45 degrees. - * Applies to highlighting on around the outside of a curve. - * @const - */ -Blockly.BlockSvg.DISTANCE_45_OUTSIDE = (1 - Math.SQRT1_2) * - (Blockly.BlockSvg.CORNER_RADIUS + 0.5) - 0.5; -/** - * SVG path for drawing next/previous notch from left to right. - * @const - */ -Blockly.BlockSvg.NOTCH_PATH_LEFT = 'l 6,4 3,0 6,-4'; -/** - * SVG path for drawing next/previous notch from left to right with - * highlighting. - * @const - */ -Blockly.BlockSvg.NOTCH_PATH_LEFT_HIGHLIGHT = 'l 6,4 3,0 6,-4'; -/** - * SVG path for drawing next/previous notch from right to left. - * @const - */ -Blockly.BlockSvg.NOTCH_PATH_RIGHT = 'l -6,4 -3,0 -6,-4'; -/** - * SVG path for drawing jagged teeth at the end of collapsed blocks. - * @const - */ -Blockly.BlockSvg.JAGGED_TEETH = 'l 8,0 0,4 8,4 -16,8 8,4'; -/** - * Height of SVG path for jagged teeth at the end of collapsed blocks. - * @const - */ -Blockly.BlockSvg.JAGGED_TEETH_HEIGHT = 20; -/** - * Width of SVG path for jagged teeth at the end of collapsed blocks. - * @const - */ -Blockly.BlockSvg.JAGGED_TEETH_WIDTH = 15; -/** - * SVG path for drawing a horizontal puzzle tab from top to bottom. - * @const - */ -Blockly.BlockSvg.TAB_PATH_DOWN = 'v 5 c 0,10 -' + Blockly.BlockSvg.TAB_WIDTH + - ',-8 -' + Blockly.BlockSvg.TAB_WIDTH + ',7.5 s ' + - Blockly.BlockSvg.TAB_WIDTH + ',-2.5 ' + Blockly.BlockSvg.TAB_WIDTH + ',7.5'; -/** - * SVG path for drawing a horizontal puzzle tab from top to bottom with - * highlighting from the upper-right. - * @const - */ -Blockly.BlockSvg.TAB_PATH_DOWN_HIGHLIGHT_RTL = 'v 6.5 m -' + - (Blockly.BlockSvg.TAB_WIDTH * 0.97) + ',3 q -' + - (Blockly.BlockSvg.TAB_WIDTH * 0.05) + ',10 ' + - (Blockly.BlockSvg.TAB_WIDTH * 0.3) + ',9.5 m ' + - (Blockly.BlockSvg.TAB_WIDTH * 0.67) + ',-1.9 v 1.4'; - -/** - * SVG start point for drawing the top-left corner. - * @const - */ -Blockly.BlockSvg.TOP_LEFT_CORNER_START = - 'm 0,' + Blockly.BlockSvg.CORNER_RADIUS; -/** - * SVG start point for drawing the top-left corner's highlight in RTL. - * @const - */ -Blockly.BlockSvg.TOP_LEFT_CORNER_START_HIGHLIGHT_RTL = - 'm ' + Blockly.BlockSvg.DISTANCE_45_INSIDE + ',' + - Blockly.BlockSvg.DISTANCE_45_INSIDE; -/** - * SVG start point for drawing the top-left corner's highlight in LTR. - * @const - */ -Blockly.BlockSvg.TOP_LEFT_CORNER_START_HIGHLIGHT_LTR = - 'm 0.5,' + (Blockly.BlockSvg.CORNER_RADIUS - 0.5); -/** - * SVG path for drawing the rounded top-left corner. - * @const - */ -Blockly.BlockSvg.TOP_LEFT_CORNER = - 'A ' + Blockly.BlockSvg.CORNER_RADIUS + ',' + - Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,1 ' + - Blockly.BlockSvg.CORNER_RADIUS + ',0'; -/** - * SVG path for drawing the highlight on the rounded top-left corner. - * @const - */ -Blockly.BlockSvg.TOP_LEFT_CORNER_HIGHLIGHT = - 'A ' + (Blockly.BlockSvg.CORNER_RADIUS - 0.5) + ',' + - (Blockly.BlockSvg.CORNER_RADIUS - 0.5) + ' 0 0,1 ' + - Blockly.BlockSvg.CORNER_RADIUS + ',0.5'; -/** - * SVG path for drawing the top-left corner of a statement input. - * Includes the top notch, a horizontal space, and the rounded inside corner. - * @const - */ -Blockly.BlockSvg.INNER_TOP_LEFT_CORNER = - Blockly.BlockSvg.NOTCH_PATH_RIGHT + ' h -' + - (Blockly.BlockSvg.NOTCH_WIDTH - 15 - Blockly.BlockSvg.CORNER_RADIUS) + - ' a ' + Blockly.BlockSvg.CORNER_RADIUS + ',' + - Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 -' + - Blockly.BlockSvg.CORNER_RADIUS + ',' + - Blockly.BlockSvg.CORNER_RADIUS; -/** - * SVG path for drawing the bottom-left corner of a statement input. - * Includes the rounded inside corner. - * @const - */ -Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER = - 'a ' + Blockly.BlockSvg.CORNER_RADIUS + ',' + - Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 ' + - Blockly.BlockSvg.CORNER_RADIUS + ',' + - Blockly.BlockSvg.CORNER_RADIUS; -/** - * SVG path for drawing highlight on the top-left corner of a statement - * input in RTL. - * @const - */ -Blockly.BlockSvg.INNER_TOP_LEFT_CORNER_HIGHLIGHT_RTL = - 'a ' + Blockly.BlockSvg.CORNER_RADIUS + ',' + - Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,0 ' + - (-Blockly.BlockSvg.DISTANCE_45_OUTSIDE - 0.5) + ',' + - (Blockly.BlockSvg.CORNER_RADIUS - - Blockly.BlockSvg.DISTANCE_45_OUTSIDE); -/** - * SVG path for drawing highlight on the bottom-left corner of a statement - * input in RTL. - * @const - */ -Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER_HIGHLIGHT_RTL = - 'a ' + (Blockly.BlockSvg.CORNER_RADIUS + 0.5) + ',' + - (Blockly.BlockSvg.CORNER_RADIUS + 0.5) + ' 0 0,0 ' + - (Blockly.BlockSvg.CORNER_RADIUS + 0.5) + ',' + - (Blockly.BlockSvg.CORNER_RADIUS + 0.5); -/** - * SVG path for drawing highlight on the bottom-left corner of a statement - * input in LTR. - * @const - */ -Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER_HIGHLIGHT_LTR = - 'a ' + (Blockly.BlockSvg.CORNER_RADIUS + 0.5) + ',' + - (Blockly.BlockSvg.CORNER_RADIUS + 0.5) + ' 0 0,0 ' + - (Blockly.BlockSvg.CORNER_RADIUS - - Blockly.BlockSvg.DISTANCE_45_OUTSIDE) + ',' + - (Blockly.BlockSvg.DISTANCE_45_OUTSIDE + 0.5); - -/** - * Render the block. - * Lays out and reflows a block based on its contents and settings. - * @param {boolean=} opt_bubble If false, just render this block. - * If true, also render block's parent, grandparent, etc. Defaults to true. - */ -Blockly.BlockSvg.prototype.render = function(opt_bubble) { - Blockly.Field.startCache(); - this.rendered = true; - - var cursorX = Blockly.BlockSvg.SEP_SPACE_X; - if (this.RTL) { - cursorX = -cursorX; - } - // Move the icons into position. - var icons = this.getIcons(); - for (var i = 0; i < icons.length; i++) { - cursorX = icons[i].renderIcon(cursorX); - } - cursorX += this.RTL ? - Blockly.BlockSvg.SEP_SPACE_X : -Blockly.BlockSvg.SEP_SPACE_X; - // If there are no icons, cursorX will be 0, otherwise it will be the - // width that the first label needs to move over by. - - var inputRows = this.renderCompute_(cursorX); - this.renderDraw_(cursorX, inputRows); - this.renderMoveConnections_(); - - if (opt_bubble !== false) { - // Render all blocks above this one (propagate a reflow). - var parentBlock = this.getParent(); - if (parentBlock) { - parentBlock.render(true); - } else { - // Top-most block. Fire an event to allow scrollbars to resize. - this.workspace.resizeContents(); - } - } - Blockly.Field.stopCache(); -}; - -/** - * Render a list of fields starting at the specified location. - * @param {!Array.} fieldList List of fields. - * @param {number} cursorX X-coordinate to start the fields. - * @param {number} cursorY Y-coordinate to start the fields. - * @return {number} X-coordinate of the end of the field row (plus a gap). - * @private - */ -Blockly.BlockSvg.prototype.renderFields_ = - function(fieldList, cursorX, cursorY) { - /* eslint-disable indent */ - cursorY += Blockly.BlockSvg.INLINE_PADDING_Y; - if (this.RTL) { - cursorX = -cursorX; - } - for (var t = 0, field; field = fieldList[t]; t++) { - var root = field.getSvgRoot(); - if (!root) { - continue; - } - if (this.RTL) { - cursorX -= field.renderSep + field.renderWidth; - root.setAttribute('transform', - 'translate(' + cursorX + ',' + cursorY + ')'); - if (field.renderWidth) { - cursorX -= Blockly.BlockSvg.SEP_SPACE_X; - } - } else { - root.setAttribute('transform', - 'translate(' + (cursorX + field.renderSep) + ',' + cursorY + ')'); - if (field.renderWidth) { - cursorX += field.renderSep + field.renderWidth + - Blockly.BlockSvg.SEP_SPACE_X; - } - } - } - return this.RTL ? -cursorX : cursorX; -}; /* eslint-enable indent */ - -/** - * Computes the height and widths for each row and field. - * @param {number} iconWidth Offset of first row due to icons. - * @return {!Array.>} 2D array of objects, each containing - * position information. - * @private - */ -Blockly.BlockSvg.prototype.renderCompute_ = function(iconWidth) { - var inputList = this.inputList; - var inputRows = []; - inputRows.rightEdge = iconWidth + Blockly.BlockSvg.SEP_SPACE_X * 2; - if (this.previousConnection || this.nextConnection) { - inputRows.rightEdge = Math.max(inputRows.rightEdge, - Blockly.BlockSvg.NOTCH_WIDTH + Blockly.BlockSvg.SEP_SPACE_X); - } - var fieldValueWidth = 0; // Width of longest external value field. - var fieldStatementWidth = 0; // Width of longest statement field. - var hasValue = false; - var hasStatement = false; - var hasDummy = false; - var lastType = undefined; - var isInline = this.getInputsInline() && !this.isCollapsed(); - for (var i = 0, input; input = inputList[i]; i++) { - if (!input.isVisible()) { - continue; - } - var row; - if (!isInline || !lastType || - lastType == Blockly.NEXT_STATEMENT || - input.type == Blockly.NEXT_STATEMENT) { - // Create new row. - lastType = input.type; - row = []; - if (isInline && input.type != Blockly.NEXT_STATEMENT) { - row.type = Blockly.BlockSvg.INLINE; - } else { - row.type = input.type; - } - row.height = 0; - inputRows.push(row); - } else { - row = inputRows[inputRows.length - 1]; - } - row.push(input); - - // Compute minimum input size. - input.renderHeight = Blockly.BlockSvg.MIN_BLOCK_Y; - // The width is currently only needed for inline value inputs. - if (isInline && input.type == Blockly.INPUT_VALUE) { - input.renderWidth = Blockly.BlockSvg.TAB_WIDTH + - Blockly.BlockSvg.SEP_SPACE_X * 1.25; - } else { - input.renderWidth = 0; - } - // Expand input size if there is a connection. - if (input.connection && input.connection.isConnected()) { - var linkedBlock = input.connection.targetBlock(); - var bBox = linkedBlock.getHeightWidth(); - input.renderHeight = Math.max(input.renderHeight, bBox.height); - input.renderWidth = Math.max(input.renderWidth, bBox.width); - } - // Blocks have a one pixel shadow that should sometimes overhang. - if (!isInline && i == inputList.length - 1) { - // Last value input should overhang. - input.renderHeight--; - } else if (!isInline && input.type == Blockly.INPUT_VALUE && - inputList[i + 1] && inputList[i + 1].type == Blockly.NEXT_STATEMENT) { - // Value input above statement input should overhang. - input.renderHeight--; - } - - row.height = Math.max(row.height, input.renderHeight); - input.fieldWidth = 0; - if (inputRows.length == 1) { - // The first row gets shifted to accommodate any icons. - input.fieldWidth += this.RTL ? -iconWidth : iconWidth; - } - var previousFieldEditable = false; - for (var j = 0, field; field = input.fieldRow[j]; j++) { - if (j != 0) { - input.fieldWidth += Blockly.BlockSvg.SEP_SPACE_X; - } - // Get the dimensions of the field. - var fieldSize = field.getSize(); - field.renderWidth = fieldSize.width; - field.renderSep = (previousFieldEditable && field.EDITABLE) ? - Blockly.BlockSvg.SEP_SPACE_X : 0; - input.fieldWidth += field.renderWidth + field.renderSep; - row.height = Math.max(row.height, fieldSize.height); - previousFieldEditable = field.EDITABLE; - } - - if (row.type != Blockly.BlockSvg.INLINE) { - if (row.type == Blockly.NEXT_STATEMENT) { - hasStatement = true; - fieldStatementWidth = Math.max(fieldStatementWidth, input.fieldWidth); - } else { - if (row.type == Blockly.INPUT_VALUE) { - hasValue = true; - } else if (row.type == Blockly.DUMMY_INPUT) { - hasDummy = true; - } - fieldValueWidth = Math.max(fieldValueWidth, input.fieldWidth); - } - } - } - - // Make inline rows a bit thicker in order to enclose the values. - for (var y = 0, row; row = inputRows[y]; y++) { - row.thicker = false; - if (row.type == Blockly.BlockSvg.INLINE) { - for (var z = 0, input; input = row[z]; z++) { - if (input.type == Blockly.INPUT_VALUE) { - row.height += 2 * Blockly.BlockSvg.INLINE_PADDING_Y; - row.thicker = true; - break; - } - } - } - } - - // Compute the statement edge. - // This is the width of a block where statements are nested. - inputRows.statementEdge = 2 * Blockly.BlockSvg.SEP_SPACE_X + - fieldStatementWidth; - // Compute the preferred right edge. Inline blocks may extend beyond. - // This is the width of the block where external inputs connect. - if (hasStatement) { - inputRows.rightEdge = Math.max(inputRows.rightEdge, - inputRows.statementEdge + Blockly.BlockSvg.NOTCH_WIDTH); - } - if (hasValue) { - inputRows.rightEdge = Math.max(inputRows.rightEdge, fieldValueWidth + - Blockly.BlockSvg.SEP_SPACE_X * 2 + Blockly.BlockSvg.TAB_WIDTH); - } else if (hasDummy) { - inputRows.rightEdge = Math.max(inputRows.rightEdge, fieldValueWidth + - Blockly.BlockSvg.SEP_SPACE_X * 2); - } - - inputRows.hasValue = hasValue; - inputRows.hasStatement = hasStatement; - inputRows.hasDummy = hasDummy; - return inputRows; -}; - - -/** - * Draw the path of the block. - * Move the fields to the correct locations. - * @param {number} iconWidth Offset of first row due to icons. - * @param {!Array.>} inputRows 2D array of objects, each - * containing position information. - * @private - */ -Blockly.BlockSvg.prototype.renderDraw_ = function(iconWidth, inputRows) { - this.startHat_ = false; - // Reset the height to zero and let the rendering process add in - // portions of the block height as it goes. (e.g. hats, inputs, etc.) - this.height = 0; - // Should the top and bottom left corners be rounded or square? - if (this.outputConnection) { - this.squareTopLeftCorner_ = true; - this.squareBottomLeftCorner_ = true; - } else { - this.squareTopLeftCorner_ = false; - this.squareBottomLeftCorner_ = false; - // If this block is in the middle of a stack, square the corners. - if (this.previousConnection) { - var prevBlock = this.previousConnection.targetBlock(); - if (prevBlock && prevBlock.getNextBlock() == this) { - this.squareTopLeftCorner_ = true; - } - } else if (Blockly.BlockSvg.START_HAT) { - // No output or previous connection. - this.squareTopLeftCorner_ = true; - this.startHat_ = true; - this.height += Blockly.BlockSvg.START_HAT_HEIGHT; - inputRows.rightEdge = Math.max(inputRows.rightEdge, 100); - } - var nextBlock = this.getNextBlock(); - if (nextBlock) { - this.squareBottomLeftCorner_ = true; - } - } - - // Assemble the block's path. - var steps = []; - var inlineSteps = []; - // The highlighting applies to edges facing the upper-left corner. - // Since highlighting is a two-pixel wide border, it would normally overhang - // the edge of the block by a pixel. So undersize all measurements by a pixel. - var highlightSteps = []; - var highlightInlineSteps = []; - - this.renderDrawTop_(steps, highlightSteps, inputRows.rightEdge); - var cursorY = this.renderDrawRight_(steps, highlightSteps, inlineSteps, - highlightInlineSteps, inputRows, iconWidth); - this.renderDrawBottom_(steps, highlightSteps, cursorY); - this.renderDrawLeft_(steps, highlightSteps); - - var pathString = steps.join(' ') + '\n' + inlineSteps.join(' '); - this.svgPath_.setAttribute('d', pathString); - this.svgPathDark_.setAttribute('d', pathString); - pathString = highlightSteps.join(' ') + '\n' + highlightInlineSteps.join(' '); - this.svgPathLight_.setAttribute('d', pathString); - if (this.RTL) { - // Mirror the block's path. - this.svgPath_.setAttribute('transform', 'scale(-1 1)'); - this.svgPathLight_.setAttribute('transform', 'scale(-1 1)'); - this.svgPathDark_.setAttribute('transform', 'translate(1,1) scale(-1 1)'); - } -}; - -/** - * Update all of the connections on this block with the new locations calculated - * in renderCompute. Also move all of the connected blocks based on the new - * connection locations. - * @private - */ -Blockly.BlockSvg.prototype.renderMoveConnections_ = function() { - var blockTL = this.getRelativeToSurfaceXY(); - // Don't tighten previous or output connecitons because they are inferior - // connections. - if (this.previousConnection) { - this.previousConnection.moveToOffset(blockTL); - } - if (this.outputConnection) { - this.outputConnection.moveToOffset(blockTL); - } - - for (var i = 0; i < this.inputList.length; i++) { - var conn = this.inputList[i].connection; - if (conn) { - conn.moveToOffset(blockTL); - if (conn.isConnected()) { - conn.tighten_(); - } - } - } - - if (this.nextConnection) { - this.nextConnection.moveToOffset(blockTL); - if (this.nextConnection.isConnected()) { - this.nextConnection.tighten_(); - } - } - -}; - -/** - * Render the top edge of the block. - * @param {!Array.} steps Path of block outline. - * @param {!Array.} highlightSteps Path of block highlights. - * @param {number} rightEdge Minimum width of block. - * @private - */ -Blockly.BlockSvg.prototype.renderDrawTop_ = - function(steps, highlightSteps, rightEdge) { - /* eslint-disable indent */ - // Position the cursor at the top-left starting point. - if (this.squareTopLeftCorner_) { - steps.push('m 0,0'); - highlightSteps.push('m 0.5,0.5'); - if (this.startHat_) { - steps.push(Blockly.BlockSvg.START_HAT_PATH); - highlightSteps.push(this.RTL ? - Blockly.BlockSvg.START_HAT_HIGHLIGHT_RTL : - Blockly.BlockSvg.START_HAT_HIGHLIGHT_LTR); - } - } else { - steps.push(Blockly.BlockSvg.TOP_LEFT_CORNER_START); - highlightSteps.push(this.RTL ? - Blockly.BlockSvg.TOP_LEFT_CORNER_START_HIGHLIGHT_RTL : - Blockly.BlockSvg.TOP_LEFT_CORNER_START_HIGHLIGHT_LTR); - // Top-left rounded corner. - steps.push(Blockly.BlockSvg.TOP_LEFT_CORNER); - highlightSteps.push(Blockly.BlockSvg.TOP_LEFT_CORNER_HIGHLIGHT); - } - - // Top edge. - if (this.previousConnection) { - steps.push('H', Blockly.BlockSvg.NOTCH_WIDTH - 15); - highlightSteps.push('H', Blockly.BlockSvg.NOTCH_WIDTH - 15); - steps.push(Blockly.BlockSvg.NOTCH_PATH_LEFT); - highlightSteps.push(Blockly.BlockSvg.NOTCH_PATH_LEFT_HIGHLIGHT); - - var connectionX = (this.RTL ? - -Blockly.BlockSvg.NOTCH_WIDTH : Blockly.BlockSvg.NOTCH_WIDTH); - this.previousConnection.setOffsetInBlock(connectionX, 0); - } - steps.push('H', rightEdge); - highlightSteps.push('H', rightEdge - 0.5); - this.width = rightEdge; -}; /* eslint-enable indent */ - -/** - * Render the right edge of the block. - * @param {!Array.} steps Path of block outline. - * @param {!Array.} highlightSteps Path of block highlights. - * @param {!Array.} inlineSteps Inline block outlines. - * @param {!Array.} highlightInlineSteps Inline block highlights. - * @param {!Array.>} inputRows 2D array of objects, each - * containing position information. - * @param {number} iconWidth Offset of first row due to icons. - * @return {number} Height of block. - * @private - */ -Blockly.BlockSvg.prototype.renderDrawRight_ = function(steps, highlightSteps, - inlineSteps, highlightInlineSteps, inputRows, iconWidth) { - var cursorX; - var cursorY = 0; - var connectionX, connectionY; - for (var y = 0, row; row = inputRows[y]; y++) { - cursorX = Blockly.BlockSvg.SEP_SPACE_X; - if (y == 0) { - cursorX += this.RTL ? -iconWidth : iconWidth; - } - highlightSteps.push('M', (inputRows.rightEdge - 0.5) + ',' + - (cursorY + 0.5)); - if (this.isCollapsed()) { - // Jagged right edge. - var input = row[0]; - var fieldX = cursorX; - var fieldY = cursorY; - this.renderFields_(input.fieldRow, fieldX, fieldY); - steps.push(Blockly.BlockSvg.JAGGED_TEETH); - highlightSteps.push('h 8'); - var remainder = row.height - Blockly.BlockSvg.JAGGED_TEETH_HEIGHT; - steps.push('v', remainder); - if (this.RTL) { - highlightSteps.push('v 3.9 l 7.2,3.4 m -14.5,8.9 l 7.3,3.5'); - highlightSteps.push('v', remainder - 0.7); - } - this.width += Blockly.BlockSvg.JAGGED_TEETH_WIDTH; - } else if (row.type == Blockly.BlockSvg.INLINE) { - // Inline inputs. - for (var x = 0, input; input = row[x]; x++) { - var fieldX = cursorX; - var fieldY = cursorY; - if (row.thicker) { - // Lower the field slightly. - fieldY += Blockly.BlockSvg.INLINE_PADDING_Y; - } - // TODO: Align inline field rows (left/right/centre). - cursorX = this.renderFields_(input.fieldRow, fieldX, fieldY); - if (input.type != Blockly.DUMMY_INPUT) { - cursorX += input.renderWidth + Blockly.BlockSvg.SEP_SPACE_X; - } - if (input.type == Blockly.INPUT_VALUE) { - inlineSteps.push('M', (cursorX - Blockly.BlockSvg.SEP_SPACE_X) + - ',' + (cursorY + Blockly.BlockSvg.INLINE_PADDING_Y)); - inlineSteps.push('h', Blockly.BlockSvg.TAB_WIDTH - 2 - - input.renderWidth); - inlineSteps.push(Blockly.BlockSvg.TAB_PATH_DOWN); - inlineSteps.push('v', input.renderHeight + 1 - - Blockly.BlockSvg.TAB_HEIGHT); - inlineSteps.push('h', input.renderWidth + 2 - - Blockly.BlockSvg.TAB_WIDTH); - inlineSteps.push('z'); - if (this.RTL) { - // Highlight right edge, around back of tab, and bottom. - highlightInlineSteps.push('M', - (cursorX - Blockly.BlockSvg.SEP_SPACE_X - 2.5 + - Blockly.BlockSvg.TAB_WIDTH - input.renderWidth) + ',' + - (cursorY + Blockly.BlockSvg.INLINE_PADDING_Y + 0.5)); - highlightInlineSteps.push( - Blockly.BlockSvg.TAB_PATH_DOWN_HIGHLIGHT_RTL); - highlightInlineSteps.push('v', - input.renderHeight - Blockly.BlockSvg.TAB_HEIGHT + 2.5); - highlightInlineSteps.push('h', - input.renderWidth - Blockly.BlockSvg.TAB_WIDTH + 2); - } else { - // Highlight right edge, bottom. - highlightInlineSteps.push('M', - (cursorX - Blockly.BlockSvg.SEP_SPACE_X + 0.5) + ',' + - (cursorY + Blockly.BlockSvg.INLINE_PADDING_Y + 0.5)); - highlightInlineSteps.push('v', input.renderHeight + 1); - highlightInlineSteps.push('h', Blockly.BlockSvg.TAB_WIDTH - 2 - - input.renderWidth); - // Short highlight glint at bottom of tab. - highlightInlineSteps.push('M', - (cursorX - input.renderWidth - Blockly.BlockSvg.SEP_SPACE_X + - 0.9) + ',' + (cursorY + Blockly.BlockSvg.INLINE_PADDING_Y + - Blockly.BlockSvg.TAB_HEIGHT - 0.7)); - highlightInlineSteps.push('l', - (Blockly.BlockSvg.TAB_WIDTH * 0.46) + ',-2.1'); - } - // Create inline input connection. - if (this.RTL) { - connectionX = -cursorX - - Blockly.BlockSvg.TAB_WIDTH + Blockly.BlockSvg.SEP_SPACE_X + - input.renderWidth + 1; - } else { - connectionX = cursorX + - Blockly.BlockSvg.TAB_WIDTH - Blockly.BlockSvg.SEP_SPACE_X - - input.renderWidth - 1; - } - connectionY = cursorY + Blockly.BlockSvg.INLINE_PADDING_Y + 1; - input.connection.setOffsetInBlock(connectionX, connectionY); - } - } - - cursorX = Math.max(cursorX, inputRows.rightEdge); - this.width = Math.max(this.width, cursorX); - steps.push('H', cursorX); - highlightSteps.push('H', cursorX - 0.5); - steps.push('v', row.height); - if (this.RTL) { - highlightSteps.push('v', row.height - 1); - } - } else if (row.type == Blockly.INPUT_VALUE) { - // External input. - var input = row[0]; - var fieldX = cursorX; - var fieldY = cursorY; - if (input.align != Blockly.ALIGN_LEFT) { - var fieldRightX = inputRows.rightEdge - input.fieldWidth - - Blockly.BlockSvg.TAB_WIDTH - 2 * Blockly.BlockSvg.SEP_SPACE_X; - if (input.align == Blockly.ALIGN_RIGHT) { - fieldX += fieldRightX; - } else if (input.align == Blockly.ALIGN_CENTRE) { - fieldX += fieldRightX / 2; - } - } - this.renderFields_(input.fieldRow, fieldX, fieldY); - steps.push(Blockly.BlockSvg.TAB_PATH_DOWN); - var v = row.height - Blockly.BlockSvg.TAB_HEIGHT; - steps.push('v', v); - if (this.RTL) { - // Highlight around back of tab. - highlightSteps.push(Blockly.BlockSvg.TAB_PATH_DOWN_HIGHLIGHT_RTL); - highlightSteps.push('v', v + 0.5); - } else { - // Short highlight glint at bottom of tab. - highlightSteps.push('M', (inputRows.rightEdge - 5) + ',' + - (cursorY + Blockly.BlockSvg.TAB_HEIGHT - 0.7)); - highlightSteps.push('l', (Blockly.BlockSvg.TAB_WIDTH * 0.46) + - ',-2.1'); - } - // Create external input connection. - connectionX = this.RTL ? -inputRows.rightEdge - 1 : - inputRows.rightEdge + 1; - input.connection.setOffsetInBlock(connectionX, cursorY); - if (input.connection.isConnected()) { - this.width = Math.max(this.width, inputRows.rightEdge + - input.connection.targetBlock().getHeightWidth().width - - Blockly.BlockSvg.TAB_WIDTH + 1); - } - } else if (row.type == Blockly.DUMMY_INPUT) { - // External naked field. - var input = row[0]; - var fieldX = cursorX; - var fieldY = cursorY; - if (input.align != Blockly.ALIGN_LEFT) { - var fieldRightX = inputRows.rightEdge - input.fieldWidth - - 2 * Blockly.BlockSvg.SEP_SPACE_X; - if (inputRows.hasValue) { - fieldRightX -= Blockly.BlockSvg.TAB_WIDTH; - } - if (input.align == Blockly.ALIGN_RIGHT) { - fieldX += fieldRightX; - } else if (input.align == Blockly.ALIGN_CENTRE) { - fieldX += fieldRightX / 2; - } - } - this.renderFields_(input.fieldRow, fieldX, fieldY); - steps.push('v', row.height); - if (this.RTL) { - highlightSteps.push('v', row.height - 1); - } - } else if (row.type == Blockly.NEXT_STATEMENT) { - // Nested statement. - var input = row[0]; - if (y == 0) { - // If the first input is a statement stack, add a small row on top. - steps.push('v', Blockly.BlockSvg.SEP_SPACE_Y); - if (this.RTL) { - highlightSteps.push('v', Blockly.BlockSvg.SEP_SPACE_Y - 1); - } - cursorY += Blockly.BlockSvg.SEP_SPACE_Y; - } - var fieldX = cursorX; - var fieldY = cursorY; - if (input.align != Blockly.ALIGN_LEFT) { - var fieldRightX = inputRows.statementEdge - input.fieldWidth - - 2 * Blockly.BlockSvg.SEP_SPACE_X; - if (input.align == Blockly.ALIGN_RIGHT) { - fieldX += fieldRightX; - } else if (input.align == Blockly.ALIGN_CENTRE) { - fieldX += fieldRightX / 2; - } - } - this.renderFields_(input.fieldRow, fieldX, fieldY); - cursorX = inputRows.statementEdge + Blockly.BlockSvg.NOTCH_WIDTH; - steps.push('H', cursorX); - steps.push(Blockly.BlockSvg.INNER_TOP_LEFT_CORNER); - steps.push('v', row.height - 2 * Blockly.BlockSvg.CORNER_RADIUS); - steps.push(Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER); - steps.push('H', inputRows.rightEdge); - if (this.RTL) { - highlightSteps.push('M', - (cursorX - Blockly.BlockSvg.NOTCH_WIDTH + - Blockly.BlockSvg.DISTANCE_45_OUTSIDE) + - ',' + (cursorY + Blockly.BlockSvg.DISTANCE_45_OUTSIDE)); - highlightSteps.push( - Blockly.BlockSvg.INNER_TOP_LEFT_CORNER_HIGHLIGHT_RTL); - highlightSteps.push('v', - row.height - 2 * Blockly.BlockSvg.CORNER_RADIUS); - highlightSteps.push( - Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER_HIGHLIGHT_RTL); - highlightSteps.push('H', inputRows.rightEdge - 0.5); - } else { - highlightSteps.push('M', - (cursorX - Blockly.BlockSvg.NOTCH_WIDTH + - Blockly.BlockSvg.DISTANCE_45_OUTSIDE) + ',' + - (cursorY + row.height - Blockly.BlockSvg.DISTANCE_45_OUTSIDE)); - highlightSteps.push( - Blockly.BlockSvg.INNER_BOTTOM_LEFT_CORNER_HIGHLIGHT_LTR); - highlightSteps.push('H', inputRows.rightEdge - 0.5); - } - // Create statement connection. - connectionX = this.RTL ? -cursorX : cursorX + 1; - input.connection.setOffsetInBlock(connectionX, cursorY + 1); - - if (input.connection.isConnected()) { - this.width = Math.max(this.width, inputRows.statementEdge + - input.connection.targetBlock().getHeightWidth().width); - } - if (y == inputRows.length - 1 || - inputRows[y + 1].type == Blockly.NEXT_STATEMENT) { - // If the final input is a statement stack, add a small row underneath. - // Consecutive statement stacks are also separated by a small divider. - steps.push('v', Blockly.BlockSvg.SEP_SPACE_Y); - if (this.RTL) { - highlightSteps.push('v', Blockly.BlockSvg.SEP_SPACE_Y - 1); - } - cursorY += Blockly.BlockSvg.SEP_SPACE_Y; - } - } - cursorY += row.height; - } - if (!inputRows.length) { - cursorY = Blockly.BlockSvg.MIN_BLOCK_Y; - steps.push('V', cursorY); - if (this.RTL) { - highlightSteps.push('V', cursorY - 1); - } - } - return cursorY; -}; - -/** - * Render the bottom edge of the block. - * @param {!Array.} steps Path of block outline. - * @param {!Array.} highlightSteps Path of block highlights. - * @param {number} cursorY Height of block. - * @private - */ -Blockly.BlockSvg.prototype.renderDrawBottom_ = - function(steps, highlightSteps, cursorY) { - /* eslint-disable indent */ - this.height += cursorY + 1; // Add one for the shadow. - if (this.nextConnection) { - steps.push('H', (Blockly.BlockSvg.NOTCH_WIDTH + (this.RTL ? 0.5 : - 0.5)) + - ' ' + Blockly.BlockSvg.NOTCH_PATH_RIGHT); - // Create next block connection. - var connectionX; - if (this.RTL) { - connectionX = -Blockly.BlockSvg.NOTCH_WIDTH; - } else { - connectionX = Blockly.BlockSvg.NOTCH_WIDTH; - } - this.nextConnection.setOffsetInBlock(connectionX, cursorY + 1); - this.height += 4; // Height of tab. - } - - // Should the bottom-left corner be rounded or square? - if (this.squareBottomLeftCorner_) { - steps.push('H 0'); - if (!this.RTL) { - highlightSteps.push('M', '0.5,' + (cursorY - 0.5)); - } - } else { - steps.push('H', Blockly.BlockSvg.CORNER_RADIUS); - steps.push('a', Blockly.BlockSvg.CORNER_RADIUS + ',' + - Blockly.BlockSvg.CORNER_RADIUS + ' 0 0,1 -' + - Blockly.BlockSvg.CORNER_RADIUS + ',-' + - Blockly.BlockSvg.CORNER_RADIUS); - if (!this.RTL) { - highlightSteps.push('M', Blockly.BlockSvg.DISTANCE_45_INSIDE + ',' + - (cursorY - Blockly.BlockSvg.DISTANCE_45_INSIDE)); - highlightSteps.push('A', (Blockly.BlockSvg.CORNER_RADIUS - 0.5) + ',' + - (Blockly.BlockSvg.CORNER_RADIUS - 0.5) + ' 0 0,1 ' + - '0.5,' + (cursorY - Blockly.BlockSvg.CORNER_RADIUS)); - } - } -}; /* eslint-enable indent */ - -/** - * Render the left edge of the block. - * @param {!Array.} steps Path of block outline. - * @param {!Array.} highlightSteps Path of block highlights. - * @private - */ -Blockly.BlockSvg.prototype.renderDrawLeft_ = function(steps, highlightSteps) { - if (this.outputConnection) { - // Create output connection. - this.outputConnection.setOffsetInBlock(0, 0); - steps.push('V', Blockly.BlockSvg.TAB_HEIGHT); - steps.push('c 0,-10 -' + Blockly.BlockSvg.TAB_WIDTH + ',8 -' + - Blockly.BlockSvg.TAB_WIDTH + ',-7.5 s ' + Blockly.BlockSvg.TAB_WIDTH + - ',2.5 ' + Blockly.BlockSvg.TAB_WIDTH + ',-7.5'); - if (this.RTL) { - highlightSteps.push('M', (Blockly.BlockSvg.TAB_WIDTH * -0.25) + ',8.4'); - highlightSteps.push('l', (Blockly.BlockSvg.TAB_WIDTH * -0.45) + ',-2.1'); - } else { - highlightSteps.push('V', Blockly.BlockSvg.TAB_HEIGHT - 1.5); - highlightSteps.push('m', (Blockly.BlockSvg.TAB_WIDTH * -0.92) + - ',-0.5 q ' + (Blockly.BlockSvg.TAB_WIDTH * -0.19) + - ',-5.5 0,-11'); - highlightSteps.push('m', (Blockly.BlockSvg.TAB_WIDTH * 0.92) + - ',1 V 0.5 H 1'); - } - this.width += Blockly.BlockSvg.TAB_WIDTH; - } else if (!this.RTL) { - if (this.squareTopLeftCorner_) { - // Statement block in a stack. - highlightSteps.push('V', 0.5); - } else { - highlightSteps.push('V', Blockly.BlockSvg.CORNER_RADIUS); - } - } - steps.push('z'); -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/block_svg.js b/backend/_pv_1_3_5/static/blockly/core/block_svg.js deleted file mode 100755 index 4d4a7299b..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/block_svg.js +++ /dev/null @@ -1,1629 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Methods for graphically rendering a block as SVG. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.BlockSvg'); - -goog.require('Blockly.Block'); -goog.require('Blockly.ContextMenu'); -goog.require('Blockly.RenderedConnection'); -goog.require('goog.Timer'); -goog.require('goog.asserts'); -goog.require('goog.dom'); -goog.require('goog.math.Coordinate'); -goog.require('goog.userAgent'); - - -/** - * Class for a block's SVG representation. - * Not normally called directly, workspace.newBlock() is preferred. - * @param {!Blockly.Workspace} workspace The block's workspace. - * @param {?string} prototypeName Name of the language object containing - * type-specific functions for this block. - * @param {=string} opt_id Optional ID. Use this ID if provided, otherwise - * create a new id. - * @extends {Blockly.Block} - * @constructor - */ -Blockly.BlockSvg = function(workspace, prototypeName, opt_id) { - // Create core elements for the block. - /** - * @type {SVGElement} - * @private - */ - this.svgGroup_ = Blockly.createSvgElement('g', {}, null); - - /** - * @type {SVGElement} - * @private - */ - this.svgPathDark_ = Blockly.createSvgElement('path', - {'class': 'blocklyPathDark', 'transform': 'translate(1,1)'}, - this.svgGroup_); - - /** - * @type {SVGElement} - * @private - */ - this.svgPath_ = Blockly.createSvgElement('path', {'class': 'blocklyPath'}, - this.svgGroup_); - - /** - * @type {SVGElement} - * @private - */ - this.svgPathLight_ = Blockly.createSvgElement('path', - {'class': 'blocklyPathLight'}, this.svgGroup_); - this.svgPath_.tooltip = this; - - /** @type {boolean} */ - this.rendered = false; - - Blockly.Tooltip.bindMouseEvents(this.svgPath_); - Blockly.BlockSvg.superClass_.constructor.call(this, - workspace, prototypeName, opt_id); -}; -goog.inherits(Blockly.BlockSvg, Blockly.Block); - -/** - * Height of this block, not including any statement blocks above or below. - */ -Blockly.BlockSvg.prototype.height = 0; -/** - * Width of this block, including any connected value blocks. - */ -Blockly.BlockSvg.prototype.width = 0; - -/** - * Original location of block being dragged. - * @type {goog.math.Coordinate} - * @private - */ -Blockly.BlockSvg.prototype.dragStartXY_ = null; - -/** - * Constant for identifying rows that are to be rendered inline. - * Don't collide with Blockly.INPUT_VALUE and friends. - * @const - */ -Blockly.BlockSvg.INLINE = -1; - -/** - * Create and initialize the SVG representation of the block. - * May be called more than once. - */ -Blockly.BlockSvg.prototype.initSvg = function() { - goog.asserts.assert(this.workspace.rendered, 'Workspace is headless.'); - for (var i = 0, input; input = this.inputList[i]; i++) { - input.init(); - } - var icons = this.getIcons(); - for (var i = 0; i < icons.length; i++) { - icons[i].createIcon(); - } - this.updateColour(); - this.updateMovable(); - if (!this.workspace.options.readOnly && !this.eventsInit_) { - Blockly.bindEvent_(this.getSvgRoot(), 'mousedown', this, - this.onMouseDown_); - var thisBlock = this; - Blockly.bindEvent_(this.getSvgRoot(), 'touchstart', null, - function(e) {Blockly.longStart_(e, thisBlock);}); - } - this.eventsInit_ = true; - - if (!this.getSvgRoot().parentNode) { - this.workspace.getCanvas().appendChild(this.getSvgRoot()); - } -}; - -/** - * Select this block. Highlight it visually. - */ -Blockly.BlockSvg.prototype.select = function() { - if (this.isShadow() && this.getParent()) { - // Shadow blocks should not be selected. - this.getParent().select(); - return; - } - if (Blockly.selected == this) { - return; - } - var oldId = null; - if (Blockly.selected) { - oldId = Blockly.selected.id; - // Unselect any previously selected block. - Blockly.Events.disable(); - try { - Blockly.selected.unselect(); - } finally { - Blockly.Events.enable(); - } - } - var event = new Blockly.Events.Ui(null, 'selected', oldId, this.id); - event.workspaceId = this.workspace.id; - Blockly.Events.fire(event); - Blockly.selected = this; - this.addSelect(); -}; - -/** - * Unselect this block. Remove its highlighting. - */ -Blockly.BlockSvg.prototype.unselect = function() { - if (Blockly.selected != this) { - return; - } - var event = new Blockly.Events.Ui(null, 'selected', this.id, null); - event.workspaceId = this.workspace.id; - Blockly.Events.fire(event); - Blockly.selected = null; - this.removeSelect(); -}; - -/** - * Block's mutator icon (if any). - * @type {Blockly.Mutator} - */ -Blockly.BlockSvg.prototype.mutator = null; - -/** - * Block's comment icon (if any). - * @type {Blockly.Comment} - */ -Blockly.BlockSvg.prototype.comment = null; - -/** - * Block's warning icon (if any). - * @type {Blockly.Warning} - */ -Blockly.BlockSvg.prototype.warning = null; - -/** - * Returns a list of mutator, comment, and warning icons. - * @return {!Array} List of icons. - */ -Blockly.BlockSvg.prototype.getIcons = function() { - var icons = []; - if (this.mutator) { - icons.push(this.mutator); - } - if (this.comment) { - icons.push(this.comment); - } - if (this.warning) { - icons.push(this.warning); - } - return icons; -}; - -/** - * Wrapper function called when a mouseUp occurs during a drag operation. - * @type {Array.} - * @private - */ -Blockly.BlockSvg.onMouseUpWrapper_ = null; - -/** - * Wrapper function called when a mouseMove occurs during a drag operation. - * @type {Array.} - * @private - */ -Blockly.BlockSvg.onMouseMoveWrapper_ = null; - -/** - * Stop binding to the global mouseup and mousemove events. - * @package - */ -Blockly.BlockSvg.terminateDrag = function() { - Blockly.BlockSvg.disconnectUiStop_(); - if (Blockly.BlockSvg.onMouseUpWrapper_) { - Blockly.unbindEvent_(Blockly.BlockSvg.onMouseUpWrapper_); - Blockly.BlockSvg.onMouseUpWrapper_ = null; - } - if (Blockly.BlockSvg.onMouseMoveWrapper_) { - Blockly.unbindEvent_(Blockly.BlockSvg.onMouseMoveWrapper_); - Blockly.BlockSvg.onMouseMoveWrapper_ = null; - } - var selected = Blockly.selected; - if (Blockly.dragMode_ == Blockly.DRAG_FREE) { - // Terminate a drag operation. - if (selected) { - // Update the connection locations. - var xy = selected.getRelativeToSurfaceXY(); - var dxy = goog.math.Coordinate.difference(xy, selected.dragStartXY_); - var event = new Blockly.Events.Move(selected); - event.oldCoordinate = selected.dragStartXY_; - event.recordNew(); - Blockly.Events.fire(event); - - selected.moveConnections_(dxy.x, dxy.y); - delete selected.draggedBubbles_; - selected.setDragging_(false); - selected.render(); - // Ensure that any stap and bump are part of this move's event group. - var group = Blockly.Events.getGroup(); - setTimeout(function() { - Blockly.Events.setGroup(group); - selected.snapToGrid(); - Blockly.Events.setGroup(false); - }, Blockly.BUMP_DELAY / 2); - setTimeout(function() { - Blockly.Events.setGroup(group); - selected.bumpNeighbours_(); - Blockly.Events.setGroup(false); - }, Blockly.BUMP_DELAY); - // Fire an event to allow scrollbars to resize. - selected.workspace.resizeContents(); - } - } - Blockly.dragMode_ = Blockly.DRAG_NONE; - Blockly.Css.setCursor(Blockly.Css.Cursor.OPEN); -}; - -/** - * Set parent of this block to be a new block or null. - * @param {Blockly.BlockSvg} newParent New parent block. - */ -Blockly.BlockSvg.prototype.setParent = function(newParent) { - if (newParent == this.parentBlock_) { - return; - } - var svgRoot = this.getSvgRoot(); - if (this.parentBlock_ && svgRoot) { - // Move this block up the DOM. Keep track of x/y translations. - var xy = this.getRelativeToSurfaceXY(); - this.workspace.getCanvas().appendChild(svgRoot); - svgRoot.setAttribute('transform', 'translate(' + xy.x + ',' + xy.y + ')'); - } - - Blockly.Field.startCache(); - Blockly.BlockSvg.superClass_.setParent.call(this, newParent); - Blockly.Field.stopCache(); - - if (newParent) { - var oldXY = this.getRelativeToSurfaceXY(); - newParent.getSvgRoot().appendChild(svgRoot); - var newXY = this.getRelativeToSurfaceXY(); - // Move the connections to match the child's new position. - this.moveConnections_(newXY.x - oldXY.x, newXY.y - oldXY.y); - } -}; - -/** - * Return the coordinates of the top-left corner of this block relative to the - * drawing surface's origin (0,0). - * @return {!goog.math.Coordinate} Object with .x and .y properties. - */ -Blockly.BlockSvg.prototype.getRelativeToSurfaceXY = function() { - var x = 0; - var y = 0; - var element = this.getSvgRoot(); - if (element) { - do { - // Loop through this block and every parent. - var xy = Blockly.getRelativeXY_(element); - x += xy.x; - y += xy.y; - element = element.parentNode; - } while (element && element != this.workspace.getCanvas()); - } - return new goog.math.Coordinate(x, y); -}; - -/** - * Move a block by a relative offset. - * @param {number} dx Horizontal offset. - * @param {number} dy Vertical offset. - */ -Blockly.BlockSvg.prototype.moveBy = function(dx, dy) { - goog.asserts.assert(!this.parentBlock_, 'Block has parent.'); - var event = new Blockly.Events.Move(this); - var xy = this.getRelativeToSurfaceXY(); - this.getSvgRoot().setAttribute('transform', - 'translate(' + (xy.x + dx) + ',' + (xy.y + dy) + ')'); - this.moveConnections_(dx, dy); - event.recordNew(); - this.workspace.resizeContents(); - Blockly.Events.fire(event); -}; - -/** - * Snap this block to the nearest grid point. - */ -Blockly.BlockSvg.prototype.snapToGrid = function() { - if (!this.workspace) { - return; // Deleted block. - } - if (Blockly.dragMode_ != Blockly.DRAG_NONE) { - return; // Don't bump blocks during a drag. - } - if (this.getParent()) { - return; // Only snap top-level blocks. - } - if (this.isInFlyout) { - return; // Don't move blocks around in a flyout. - } - if (!this.workspace.options.gridOptions || - !this.workspace.options.gridOptions['snap']) { - return; // Config says no snapping. - } - var spacing = this.workspace.options.gridOptions['spacing']; - var half = spacing / 2; - var xy = this.getRelativeToSurfaceXY(); - var dx = Math.round((xy.x - half) / spacing) * spacing + half - xy.x; - var dy = Math.round((xy.y - half) / spacing) * spacing + half - xy.y; - dx = Math.round(dx); - dy = Math.round(dy); - if (dx != 0 || dy != 0) { - this.moveBy(dx, dy); - } -}; - -/** - * Returns a bounding box describing the dimensions of this block - * and any blocks stacked below it. - * @return {!{height: number, width: number}} Object with height and width - * properties. - */ -Blockly.BlockSvg.prototype.getHeightWidth = function() { - var height = this.height; - var width = this.width; - // Recursively add size of subsequent blocks. - var nextBlock = this.getNextBlock(); - if (nextBlock) { - var nextHeightWidth = nextBlock.getHeightWidth(); - height += nextHeightWidth.height - 4; // Height of tab. - width = Math.max(width, nextHeightWidth.width); - } else if (!this.nextConnection && !this.outputConnection) { - // Add a bit of margin under blocks with no bottom tab. - height += 2; - } - return {height: height, width: width}; -}; - -/** - * Returns the coordinates of a bounding box describing the dimensions of this - * block and any blocks stacked below it. - * @return {!{topLeft: goog.math.Coordinate, bottomRight: goog.math.Coordinate}} - * Object with top left and bottom right coordinates of the bounding box. - */ -Blockly.BlockSvg.prototype.getBoundingRectangle = function() { - var blockXY = this.getRelativeToSurfaceXY(this); - var tab = this.outputConnection ? Blockly.BlockSvg.TAB_WIDTH : 0; - var blockBounds = this.getHeightWidth(); - var topLeft; - var bottomRight; - if (this.RTL) { - // Width has the tab built into it already so subtract it here. - topLeft = new goog.math.Coordinate(blockXY.x - (blockBounds.width - tab), - blockXY.y); - // Add the width of the tab/puzzle piece knob to the x coordinate - // since X is the corner of the rectangle, not the whole puzzle piece. - bottomRight = new goog.math.Coordinate(blockXY.x + tab, - blockXY.y + blockBounds.height); - } else { - // Subtract the width of the tab/puzzle piece knob to the x coordinate - // since X is the corner of the rectangle, not the whole puzzle piece. - topLeft = new goog.math.Coordinate(blockXY.x - tab, blockXY.y); - // Width has the tab built into it already so subtract it here. - bottomRight = new goog.math.Coordinate(blockXY.x + blockBounds.width - tab, - blockXY.y + blockBounds.height); - } - return {topLeft: topLeft, bottomRight: bottomRight}; -}; - -/** - * Set whether the block is collapsed or not. - * @param {boolean} collapsed True if collapsed. - */ -Blockly.BlockSvg.prototype.setCollapsed = function(collapsed) { - if (this.collapsed_ == collapsed) { - return; - } - var renderList = []; - // Show/hide the inputs. - for (var i = 0, input; input = this.inputList[i]; i++) { - renderList.push.apply(renderList, input.setVisible(!collapsed)); - } - - var COLLAPSED_INPUT_NAME = '_TEMP_COLLAPSED_INPUT'; - if (collapsed) { - var icons = this.getIcons(); - for (var i = 0; i < icons.length; i++) { - icons[i].setVisible(false); - } - var text = this.toString(Blockly.COLLAPSE_CHARS); - this.appendDummyInput(COLLAPSED_INPUT_NAME).appendField(text).init(); - } else { - this.removeInput(COLLAPSED_INPUT_NAME); - // Clear any warnings inherited from enclosed blocks. - this.setWarningText(null); - } - Blockly.BlockSvg.superClass_.setCollapsed.call(this, collapsed); - - if (!renderList.length) { - // No child blocks, just render this block. - renderList[0] = this; - } - if (this.rendered) { - for (var i = 0, block; block = renderList[i]; i++) { - block.render(); - } - // Don't bump neighbours. - // Although bumping neighbours would make sense, users often collapse - // all their functions and store them next to each other. Expanding and - // bumping causes all their definitions to go out of alignment. - } -}; - -/** - * Open the next (or previous) FieldTextInput. - * @param {Blockly.Field|Blockly.Block} start Current location. - * @param {boolean} forward If true go forward, otherwise backward. - */ -Blockly.BlockSvg.prototype.tab = function(start, forward) { - // This function need not be efficient since it runs once on a keypress. - // Create an ordered list of all text fields and connected inputs. - var list = []; - for (var i = 0, input; input = this.inputList[i]; i++) { - for (var j = 0, field; field = input.fieldRow[j]; j++) { - if (field instanceof Blockly.FieldTextInput) { - // TODO: Also support dropdown fields. - list.push(field); - } - } - if (input.connection) { - var block = input.connection.targetBlock(); - if (block) { - list.push(block); - } - } - } - var i = list.indexOf(start); - if (i == -1) { - // No start location, start at the beginning or end. - i = forward ? -1 : list.length; - } - var target = list[forward ? i + 1 : i - 1]; - if (!target) { - // Ran off of list. - var parent = this.getParent(); - if (parent) { - parent.tab(this, forward); - } - } else if (target instanceof Blockly.Field) { - target.showEditor_(); - } else { - target.tab(null, forward); - } -}; - -/** - * Handle a mouse-down on an SVG block. - * @param {!Event} e Mouse down event. - * @private - */ -Blockly.BlockSvg.prototype.onMouseDown_ = function(e) { - if (this.workspace.options.readOnly) { - return; - } - if (this.isInFlyout) { - return; - } - if (this.isInMutator) { - // Mutator's coordinate system could be out of date because the bubble was - // dragged, the block was moved, the parent workspace zoomed, etc. - this.workspace.resize(); - } - - this.workspace.updateScreenCalculationsIfScrolled(); - this.workspace.markFocused(); - Blockly.terminateDrag_(); - this.select(); - Blockly.hideChaff(); - if (Blockly.isRightButton(e)) { - // Right-click. - this.showContextMenu_(e); - } else if (!this.isMovable()) { - // Allow immovable blocks to be selected and context menued, but not - // dragged. Let this event bubble up to document, so the workspace may be - // dragged instead. - return; - } else { - if (!Blockly.Events.getGroup()) { - Blockly.Events.setGroup(true); - } - // Left-click (or middle click) - Blockly.Css.setCursor(Blockly.Css.Cursor.CLOSED); - - this.dragStartXY_ = this.getRelativeToSurfaceXY(); - this.workspace.startDrag(e, this.dragStartXY_); - - Blockly.dragMode_ = Blockly.DRAG_STICKY; - Blockly.BlockSvg.onMouseUpWrapper_ = Blockly.bindEvent_(document, - 'mouseup', this, this.onMouseUp_); - Blockly.BlockSvg.onMouseMoveWrapper_ = Blockly.bindEvent_(document, - 'mousemove', this, this.onMouseMove_); - // Build a list of bubbles that need to be moved and where they started. - this.draggedBubbles_ = []; - var descendants = this.getDescendants(); - for (var i = 0, descendant; descendant = descendants[i]; i++) { - var icons = descendant.getIcons(); - for (var j = 0; j < icons.length; j++) { - var data = icons[j].getIconLocation(); - data.bubble = icons[j]; - this.draggedBubbles_.push(data); - } - } - } - // This event has been handled. No need to bubble up to the document. - e.stopPropagation(); - e.preventDefault(); -}; - -/** - * Handle a mouse-up anywhere in the SVG pane. Is only registered when a - * block is clicked. We can't use mouseUp on the block since a fast-moving - * cursor can briefly escape the block before it catches up. - * @param {!Event} e Mouse up event. - * @private - */ -Blockly.BlockSvg.prototype.onMouseUp_ = function(e) { - if (Blockly.dragMode_ != Blockly.DRAG_FREE && - !Blockly.WidgetDiv.isVisible()) { - Blockly.Events.fire( - new Blockly.Events.Ui(this, 'click', undefined, undefined)); - } - Blockly.terminateDrag_(); - if (Blockly.selected && Blockly.highlightedConnection_) { - // Connect two blocks together. - Blockly.localConnection_.connect(Blockly.highlightedConnection_); - if (this.rendered) { - // Trigger a connection animation. - // Determine which connection is inferior (lower in the source stack). - var inferiorConnection = Blockly.localConnection_.isSuperior() ? - Blockly.highlightedConnection_ : Blockly.localConnection_; - inferiorConnection.getSourceBlock().connectionUiEffect(); - } - if (this.workspace.trashcan) { - // Don't throw an object in the trash can if it just got connected. - this.workspace.trashcan.close(); - } - } else if (!this.getParent() && Blockly.selected.isDeletable() && - this.workspace.isDeleteArea(e)) { - var trashcan = this.workspace.trashcan; - if (trashcan) { - goog.Timer.callOnce(trashcan.close, 100, trashcan); - } - Blockly.selected.dispose(false, true); - } - if (Blockly.highlightedConnection_) { - Blockly.highlightedConnection_.unhighlight(); - Blockly.highlightedConnection_ = null; - } - Blockly.Css.setCursor(Blockly.Css.Cursor.OPEN); - if (!Blockly.WidgetDiv.isVisible()) { - Blockly.Events.setGroup(false); - } -}; - -/** - * Load the block's help page in a new window. - * @private - */ -Blockly.BlockSvg.prototype.showHelp_ = function() { - var url = goog.isFunction(this.helpUrl) ? this.helpUrl() : this.helpUrl; - if (url) { - window.open(url); - } -}; - -/** - * Show the context menu for this block. - * @param {!Event} e Mouse event. - * @private - */ -Blockly.BlockSvg.prototype.showContextMenu_ = function(e) { - if (this.workspace.options.readOnly || !this.contextMenu) { - return; - } - // Save the current block in a variable for use in closures. - var block = this; - var menuOptions = []; - - if (this.isDeletable() && this.isMovable() && !block.isInFlyout) { - // Option to duplicate this block. - var duplicateOption = { - text: Blockly.Msg.DUPLICATE_BLOCK, - enabled: true, - callback: function() { - Blockly.duplicate_(block); - } - }; - if (this.getDescendants().length > this.workspace.remainingCapacity()) { - duplicateOption.enabled = false; - } - menuOptions.push(duplicateOption); - - if (this.isEditable() && !this.collapsed_ && - this.workspace.options.comments) { - // Option to add/remove a comment. - var commentOption = {enabled: !goog.userAgent.IE}; - if (this.comment) { - commentOption.text = Blockly.Msg.REMOVE_COMMENT; - commentOption.callback = function() { - block.setCommentText(null); - }; - } else { - commentOption.text = Blockly.Msg.ADD_COMMENT; - commentOption.callback = function() { - block.setCommentText(''); - }; - } - menuOptions.push(commentOption); - } - - // Option to make block inline. - if (!this.collapsed_) { - for (var i = 1; i < this.inputList.length; i++) { - if (this.inputList[i - 1].type != Blockly.NEXT_STATEMENT && - this.inputList[i].type != Blockly.NEXT_STATEMENT) { - // Only display this option if there are two value or dummy inputs - // next to each other. - var inlineOption = {enabled: true}; - var isInline = this.getInputsInline(); - inlineOption.text = isInline ? - Blockly.Msg.EXTERNAL_INPUTS : Blockly.Msg.INLINE_INPUTS; - inlineOption.callback = function() { - block.setInputsInline(!isInline); - }; - menuOptions.push(inlineOption); - break; - } - } - } - - if (this.workspace.options.collapse) { - // Option to collapse/expand block. - if (this.collapsed_) { - var expandOption = {enabled: true}; - expandOption.text = Blockly.Msg.EXPAND_BLOCK; - expandOption.callback = function() { - block.setCollapsed(false); - }; - menuOptions.push(expandOption); - } else { - var collapseOption = {enabled: true}; - collapseOption.text = Blockly.Msg.COLLAPSE_BLOCK; - collapseOption.callback = function() { - block.setCollapsed(true); - }; - menuOptions.push(collapseOption); - } - } - - if (this.workspace.options.disable) { - // Option to disable/enable block. - var disableOption = { - text: this.disabled ? - Blockly.Msg.ENABLE_BLOCK : Blockly.Msg.DISABLE_BLOCK, - enabled: !this.getInheritedDisabled(), - callback: function() { - block.setDisabled(!block.disabled); - } - }; - menuOptions.push(disableOption); - } - - // Option to delete this block. - // Count the number of blocks that are nested in this block. - var descendantCount = this.getDescendants().length; - var nextBlock = this.getNextBlock(); - if (nextBlock) { - // Blocks in the current stack would survive this block's deletion. - descendantCount -= nextBlock.getDescendants().length; - } - var deleteOption = { - text: descendantCount == 1 ? Blockly.Msg.DELETE_BLOCK : - Blockly.Msg.DELETE_X_BLOCKS.replace('%1', String(descendantCount)), - enabled: true, - callback: function() { - Blockly.Events.setGroup(true); - block.dispose(true, true); - Blockly.Events.setGroup(false); - } - }; - menuOptions.push(deleteOption); - } - - // Option to get help. - var url = goog.isFunction(this.helpUrl) ? this.helpUrl() : this.helpUrl; - var helpOption = {enabled: !!url}; - helpOption.text = Blockly.Msg.HELP; - helpOption.callback = function() { - block.showHelp_(); - }; - menuOptions.push(helpOption); - - // Allow the block to add or modify menuOptions. - if (this.customContextMenu && !block.isInFlyout) { - this.customContextMenu(menuOptions); - } - - Blockly.ContextMenu.show(e, menuOptions, this.RTL); - Blockly.ContextMenu.currentBlock = this; -}; - -/** - * Move the connections for this block and all blocks attached under it. - * Also update any attached bubbles. - * @param {number} dx Horizontal offset from current location. - * @param {number} dy Vertical offset from current location. - * @private - */ -Blockly.BlockSvg.prototype.moveConnections_ = function(dx, dy) { - if (!this.rendered) { - // Rendering is required to lay out the blocks. - // This is probably an invisible block attached to a collapsed block. - return; - } - var myConnections = this.getConnections_(false); - for (var i = 0; i < myConnections.length; i++) { - myConnections[i].moveBy(dx, dy); - } - var icons = this.getIcons(); - for (var i = 0; i < icons.length; i++) { - icons[i].computeIconLocation(); - } - - // Recurse through all blocks attached under this one. - for (var i = 0; i < this.childBlocks_.length; i++) { - this.childBlocks_[i].moveConnections_(dx, dy); - } -}; - -/** - * Recursively adds or removes the dragging class to this node and its children. - * @param {boolean} adding True if adding, false if removing. - * @private - */ -Blockly.BlockSvg.prototype.setDragging_ = function(adding) { - if (adding) { - var group = this.getSvgRoot(); - group.translate_ = ''; - group.skew_ = ''; - this.addDragging(); - Blockly.draggingConnections_ = - Blockly.draggingConnections_.concat(this.getConnections_(true)); - } else { - this.removeDragging(); - Blockly.draggingConnections_ = []; - } - // Recurse through all blocks attached under this one. - for (var i = 0; i < this.childBlocks_.length; i++) { - this.childBlocks_[i].setDragging_(adding); - } -}; - -/** - * Drag this block to follow the mouse. - * @param {!Event} e Mouse move event. - * @private - */ -Blockly.BlockSvg.prototype.onMouseMove_ = function(e) { - if (e.type == 'mousemove' && e.clientX <= 1 && e.clientY == 0 && - e.button == 0) { - /* HACK: - Safari Mobile 6.0 and Chrome for Android 18.0 fire rogue mousemove - events on certain touch actions. Ignore events with these signatures. - This may result in a one-pixel blind spot in other browsers, - but this shouldn't be noticeable. */ - e.stopPropagation(); - return; - } - - var oldXY = this.getRelativeToSurfaceXY(); - var newXY = this.workspace.moveDrag(e); - - if (Blockly.dragMode_ == Blockly.DRAG_STICKY) { - // Still dragging within the sticky DRAG_RADIUS. - var dr = goog.math.Coordinate.distance(oldXY, newXY) * this.workspace.scale; - if (dr > Blockly.DRAG_RADIUS) { - // Switch to unrestricted dragging. - Blockly.dragMode_ = Blockly.DRAG_FREE; - Blockly.longStop_(); - if (this.parentBlock_) { - // Push this block to the very top of the stack. - this.unplug(); - var group = this.getSvgRoot(); - group.translate_ = 'translate(' + newXY.x + ',' + newXY.y + ')'; - this.disconnectUiEffect(); - } - this.setDragging_(true); - } - } - if (Blockly.dragMode_ == Blockly.DRAG_FREE) { - // Unrestricted dragging. - var dxy = goog.math.Coordinate.difference(oldXY, this.dragStartXY_); - var group = this.getSvgRoot(); - group.translate_ = 'translate(' + newXY.x + ',' + newXY.y + ')'; - group.setAttribute('transform', group.translate_ + group.skew_); - // Drag all the nested bubbles. - for (var i = 0; i < this.draggedBubbles_.length; i++) { - var commentData = this.draggedBubbles_[i]; - commentData.bubble.setIconLocation( - goog.math.Coordinate.sum(commentData, dxy)); - } - - // Check to see if any of this block's connections are within range of - // another block's connection. - var myConnections = this.getConnections_(false); - // Also check the last connection on this stack - var lastOnStack = this.lastConnectionInStack_(); - if (lastOnStack && lastOnStack != this.nextConnection) { - myConnections.push(lastOnStack); - } - var closestConnection = null; - var localConnection = null; - var radiusConnection = Blockly.SNAP_RADIUS; - for (var i = 0; i < myConnections.length; i++) { - var myConnection = myConnections[i]; - var neighbour = myConnection.closest(radiusConnection, dxy); - if (neighbour.connection) { - closestConnection = neighbour.connection; - localConnection = myConnection; - radiusConnection = neighbour.radius; - } - } - - // Remove connection highlighting if needed. - if (Blockly.highlightedConnection_ && - Blockly.highlightedConnection_ != closestConnection) { - Blockly.highlightedConnection_.unhighlight(); - Blockly.highlightedConnection_ = null; - Blockly.localConnection_ = null; - } - // Add connection highlighting if needed. - if (closestConnection && - closestConnection != Blockly.highlightedConnection_) { - closestConnection.highlight(); - Blockly.highlightedConnection_ = closestConnection; - Blockly.localConnection_ = localConnection; - } - // Provide visual indication of whether the block will be deleted if - // dropped here. - if (this.isDeletable()) { - this.workspace.isDeleteArea(e); - } - } - // This event has been handled. No need to bubble up to the document. - e.stopPropagation(); - e.preventDefault(); -}; - -/** - * Add or remove the UI indicating if this block is movable or not. - */ -Blockly.BlockSvg.prototype.updateMovable = function() { - if (this.isMovable()) { - Blockly.addClass_(/** @type {!Element} */ (this.svgGroup_), - 'blocklyDraggable'); - } else { - Blockly.removeClass_(/** @type {!Element} */ (this.svgGroup_), - 'blocklyDraggable'); - } -}; - -/** - * Set whether this block is movable or not. - * @param {boolean} movable True if movable. - */ -Blockly.BlockSvg.prototype.setMovable = function(movable) { - Blockly.BlockSvg.superClass_.setMovable.call(this, movable); - this.updateMovable(); -}; - -/** - * Set whether this block is editable or not. - * @param {boolean} editable True if editable. - */ -Blockly.BlockSvg.prototype.setEditable = function(editable) { - Blockly.BlockSvg.superClass_.setEditable.call(this, editable); - var icons = this.getIcons(); - for (var i = 0; i < icons.length; i++) { - icons[i].updateEditable(); - } -}; - -/** - * Set whether this block is a shadow block or not. - * @param {boolean} shadow True if a shadow. - */ -Blockly.BlockSvg.prototype.setShadow = function(shadow) { - Blockly.BlockSvg.superClass_.setShadow.call(this, shadow); - this.updateColour(); -}; - -/** - * Return the root node of the SVG or null if none exists. - * @return {Element} The root SVG node (probably a group). - */ -Blockly.BlockSvg.prototype.getSvgRoot = function() { - return this.svgGroup_; -}; - -/** - * Dispose of this block. - * @param {boolean} healStack If true, then try to heal any gap by connecting - * the next statement with the previous statement. Otherwise, dispose of - * all children of this block. - * @param {boolean} animate If true, show a disposal animation and sound. - */ -Blockly.BlockSvg.prototype.dispose = function(healStack, animate) { - if (!this.workspace) { - // The block has already been deleted. - return; - } - Blockly.Tooltip.hide(); - Blockly.Field.startCache(); - // Save the block's workspace temporarily so we can resize the - // contents once the block is disposed. - var blockWorkspace = this.workspace; - // If this block is being dragged, unlink the mouse events. - if (Blockly.selected == this) { - this.unselect(); - Blockly.terminateDrag_(); - } - // If this block has a context menu open, close it. - if (Blockly.ContextMenu.currentBlock == this) { - Blockly.ContextMenu.hide(); - } - - if (animate && this.rendered) { - this.unplug(healStack); - this.disposeUiEffect(); - } - // Stop rerendering. - this.rendered = false; - - Blockly.Events.disable(); - try { - var icons = this.getIcons(); - for (var i = 0; i < icons.length; i++) { - icons[i].dispose(); - } - } finally { - Blockly.Events.enable(); - } - Blockly.BlockSvg.superClass_.dispose.call(this, healStack); - - goog.dom.removeNode(this.svgGroup_); - blockWorkspace.resizeContents(); - // Sever JavaScript to DOM connections. - this.svgGroup_ = null; - this.svgPath_ = null; - this.svgPathLight_ = null; - this.svgPathDark_ = null; - Blockly.Field.stopCache(); -}; - -/** - * Play some UI effects (sound, animation) when disposing of a block. - */ -Blockly.BlockSvg.prototype.disposeUiEffect = function() { - this.workspace.playAudio('delete'); - - var xy = Blockly.getSvgXY_(/** @type {!Element} */ (this.svgGroup_), - this.workspace); - // Deeply clone the current block. - var clone = this.svgGroup_.cloneNode(true); - clone.translateX_ = xy.x; - clone.translateY_ = xy.y; - clone.setAttribute('transform', - 'translate(' + clone.translateX_ + ',' + clone.translateY_ + ')'); - this.workspace.getParentSvg().appendChild(clone); - clone.bBox_ = clone.getBBox(); - // Start the animation. - Blockly.BlockSvg.disposeUiStep_(clone, this.RTL, new Date, - this.workspace.scale); -}; - -/** - * Animate a cloned block and eventually dispose of it. - * This is a class method, not an instace method since the original block has - * been destroyed and is no longer accessible. - * @param {!Element} clone SVG element to animate and dispose of. - * @param {boolean} rtl True if RTL, false if LTR. - * @param {!Date} start Date of animation's start. - * @param {number} workspaceScale Scale of workspace. - * @private - */ -Blockly.BlockSvg.disposeUiStep_ = function(clone, rtl, start, workspaceScale) { - var ms = new Date - start; - var percent = ms / 150; - if (percent > 1) { - goog.dom.removeNode(clone); - } else { - var x = clone.translateX_ + - (rtl ? -1 : 1) * clone.bBox_.width * workspaceScale / 2 * percent; - var y = clone.translateY_ + clone.bBox_.height * workspaceScale * percent; - var scale = (1 - percent) * workspaceScale; - clone.setAttribute('transform', 'translate(' + x + ',' + y + ')' + - ' scale(' + scale + ')'); - var closure = function() { - Blockly.BlockSvg.disposeUiStep_(clone, rtl, start, workspaceScale); - }; - setTimeout(closure, 10); - } -}; - -/** - * Play some UI effects (sound, ripple) after a connection has been established. - */ -Blockly.BlockSvg.prototype.connectionUiEffect = function() { - this.workspace.playAudio('click'); - if (this.workspace.scale < 1) { - return; // Too small to care about visual effects. - } - // Determine the absolute coordinates of the inferior block. - var xy = Blockly.getSvgXY_(/** @type {!Element} */ (this.svgGroup_), - this.workspace); - // Offset the coordinates based on the two connection types, fix scale. - if (this.outputConnection) { - xy.x += (this.RTL ? 3 : -3) * this.workspace.scale; - xy.y += 13 * this.workspace.scale; - } else if (this.previousConnection) { - xy.x += (this.RTL ? -23 : 23) * this.workspace.scale; - xy.y += 3 * this.workspace.scale; - } - var ripple = Blockly.createSvgElement('circle', - {'cx': xy.x, 'cy': xy.y, 'r': 0, 'fill': 'none', - 'stroke': '#888', 'stroke-width': 10}, - this.workspace.getParentSvg()); - // Start the animation. - Blockly.BlockSvg.connectionUiStep_(ripple, new Date, this.workspace.scale); -}; - -/** - * Expand a ripple around a connection. - * @param {!Element} ripple Element to animate. - * @param {!Date} start Date of animation's start. - * @param {number} workspaceScale Scale of workspace. - * @private - */ -Blockly.BlockSvg.connectionUiStep_ = function(ripple, start, workspaceScale) { - var ms = new Date - start; - var percent = ms / 150; - if (percent > 1) { - goog.dom.removeNode(ripple); - } else { - ripple.setAttribute('r', percent * 25 * workspaceScale); - ripple.style.opacity = 1 - percent; - var closure = function() { - Blockly.BlockSvg.connectionUiStep_(ripple, start, workspaceScale); - }; - Blockly.BlockSvg.disconnectUiStop_.pid_ = setTimeout(closure, 10); - } -}; - -/** - * Play some UI effects (sound, animation) when disconnecting a block. - */ -Blockly.BlockSvg.prototype.disconnectUiEffect = function() { - this.workspace.playAudio('disconnect'); - if (this.workspace.scale < 1) { - return; // Too small to care about visual effects. - } - // Horizontal distance for bottom of block to wiggle. - var DISPLACEMENT = 10; - // Scale magnitude of skew to height of block. - var height = this.getHeightWidth().height; - var magnitude = Math.atan(DISPLACEMENT / height) / Math.PI * 180; - if (!this.RTL) { - magnitude *= -1; - } - // Start the animation. - Blockly.BlockSvg.disconnectUiStep_(this.svgGroup_, magnitude, new Date); -}; - -/** - * Animate a brief wiggle of a disconnected block. - * @param {!Element} group SVG element to animate. - * @param {number} magnitude Maximum degrees skew (reversed for RTL). - * @param {!Date} start Date of animation's start. - * @private - */ -Blockly.BlockSvg.disconnectUiStep_ = function(group, magnitude, start) { - var DURATION = 200; // Milliseconds. - var WIGGLES = 3; // Half oscillations. - - var ms = new Date - start; - var percent = ms / DURATION; - - if (percent > 1) { - group.skew_ = ''; - } else { - var skew = Math.round(Math.sin(percent * Math.PI * WIGGLES) * - (1 - percent) * magnitude); - group.skew_ = 'skewX(' + skew + ')'; - var closure = function() { - Blockly.BlockSvg.disconnectUiStep_(group, magnitude, start); - }; - Blockly.BlockSvg.disconnectUiStop_.group = group; - Blockly.BlockSvg.disconnectUiStop_.pid = setTimeout(closure, 10); - } - group.setAttribute('transform', group.translate_ + group.skew_); -}; - -/** - * Stop the disconnect UI animation immediately. - * @private - */ -Blockly.BlockSvg.disconnectUiStop_ = function() { - if (Blockly.BlockSvg.disconnectUiStop_.group) { - clearTimeout(Blockly.BlockSvg.disconnectUiStop_.pid); - var group = Blockly.BlockSvg.disconnectUiStop_.group; - group.skew_ = ''; - group.setAttribute('transform', group.translate_); - Blockly.BlockSvg.disconnectUiStop_.group = null; - } -}; - -/** - * PID of disconnect UI animation. There can only be one at a time. - * @type {number} - */ -Blockly.BlockSvg.disconnectUiStop_.pid = 0; - -/** - * SVG group of wobbling block. There can only be one at a time. - * @type {Element} - */ -Blockly.BlockSvg.disconnectUiStop_.group = null; - -/** - * Change the colour of a block. - */ -Blockly.BlockSvg.prototype.updateColour = function() { - if (this.disabled) { - // Disabled blocks don't have colour. - return; - } - var hexColour = this.getColour(); - var rgb = goog.color.hexToRgb(hexColour); - if (this.isShadow()) { - rgb = goog.color.lighten(rgb, 0.6); - hexColour = goog.color.rgbArrayToHex(rgb); - this.svgPathLight_.style.display = 'none'; - this.svgPathDark_.setAttribute('fill', hexColour); - } else { - this.svgPathLight_.style.display = ''; - var hexLight = goog.color.rgbArrayToHex(goog.color.lighten(rgb, 0.3)); - var hexDark = goog.color.rgbArrayToHex(goog.color.darken(rgb, 0.2)); - this.svgPathLight_.setAttribute('stroke', hexLight); - this.svgPathDark_.setAttribute('fill', hexDark); - } - this.svgPath_.setAttribute('fill', hexColour); - - var icons = this.getIcons(); - for (var i = 0; i < icons.length; i++) { - icons[i].updateColour(); - } - - // Bump every dropdown to change its colour. - for (var x = 0, input; input = this.inputList[x]; x++) { - for (var y = 0, field; field = input.fieldRow[y]; y++) { - field.setText(null); - } - } -}; - -/** - * Enable or disable a block. - */ -Blockly.BlockSvg.prototype.updateDisabled = function() { - var hasClass = Blockly.hasClass_(/** @type {!Element} */ (this.svgGroup_), - 'blocklyDisabled'); - if (this.disabled || this.getInheritedDisabled()) { - if (!hasClass) { - Blockly.addClass_(/** @type {!Element} */ (this.svgGroup_), - 'blocklyDisabled'); - this.svgPath_.setAttribute('fill', - 'url(#' + this.workspace.options.disabledPatternId + ')'); - } - } else { - if (hasClass) { - Blockly.removeClass_(/** @type {!Element} */ (this.svgGroup_), - 'blocklyDisabled'); - this.updateColour(); - } - } - var children = this.getChildren(); - for (var i = 0, child; child = children[i]; i++) { - child.updateDisabled(); - } -}; - -/** - * Returns the comment on this block (or '' if none). - * @return {string} Block's comment. - */ -Blockly.BlockSvg.prototype.getCommentText = function() { - if (this.comment) { - var comment = this.comment.getText(); - // Trim off trailing whitespace. - return comment.replace(/\s+$/, '').replace(/ +\n/g, '\n'); - } - return ''; -}; - -/** - * Set this block's comment text. - * @param {?string} text The text, or null to delete. - */ -Blockly.BlockSvg.prototype.setCommentText = function(text) { - var changedState = false; - if (goog.isString(text)) { - if (!this.comment) { - this.comment = new Blockly.Comment(this); - changedState = true; - } - this.comment.setText(/** @type {string} */ (text)); - } else { - if (this.comment) { - this.comment.dispose(); - changedState = true; - } - } - if (changedState && this.rendered) { - this.render(); - // Adding or removing a comment icon will cause the block to change shape. - this.bumpNeighbours_(); - } -}; - -/** - * Set this block's warning text. - * @param {?string} text The text, or null to delete. - * @param {string=} opt_id An optional ID for the warning text to be able to - * maintain multiple warnings. - */ -Blockly.BlockSvg.prototype.setWarningText = function(text, opt_id) { - if (!this.setWarningText.pid_) { - // Create a database of warning PIDs. - // Only runs once per block (and only those with warnings). - this.setWarningText.pid_ = Object.create(null); - } - var id = opt_id || ''; - if (!id) { - // Kill all previous pending processes, this edit supercedes them all. - for (var n in this.setWarningText.pid_) { - clearTimeout(this.setWarningText.pid_[n]); - delete this.setWarningText.pid_[n]; - } - } else if (this.setWarningText.pid_[id]) { - // Only queue up the latest change. Kill any earlier pending process. - clearTimeout(this.setWarningText.pid_[id]); - delete this.setWarningText.pid_[id]; - } - if (Blockly.dragMode_ == Blockly.DRAG_FREE) { - // Don't change the warning text during a drag. - // Wait until the drag finishes. - var thisBlock = this; - this.setWarningText.pid_[id] = setTimeout(function() { - if (thisBlock.workspace) { // Check block wasn't deleted. - delete thisBlock.setWarningText.pid_[id]; - thisBlock.setWarningText(text, id); - } - }, 100); - return; - } - if (this.isInFlyout) { - text = null; - } - - // Bubble up to add a warning on top-most collapsed block. - var parent = this.getSurroundParent(); - var collapsedParent = null; - while (parent) { - if (parent.isCollapsed()) { - collapsedParent = parent; - } - parent = parent.getSurroundParent(); - } - if (collapsedParent) { - collapsedParent.setWarningText(text, 'collapsed ' + this.id + ' ' + id); - } - - var changedState = false; - if (goog.isString(text)) { - if (!this.warning) { - this.warning = new Blockly.Warning(this); - changedState = true; - } - this.warning.setText(/** @type {string} */ (text), id); - } else { - // Dispose all warnings if no id is given. - if (this.warning && !id) { - this.warning.dispose(); - changedState = true; - } else if (this.warning) { - var oldText = this.warning.getText(); - this.warning.setText('', id); - var newText = this.warning.getText(); - if (!newText) { - this.warning.dispose(); - } - changedState = oldText == newText; - } - } - if (changedState && this.rendered) { - this.render(); - // Adding or removing a warning icon will cause the block to change shape. - this.bumpNeighbours_(); - } -}; - -/** - * Give this block a mutator dialog. - * @param {Blockly.Mutator} mutator A mutator dialog instance or null to remove. - */ -Blockly.BlockSvg.prototype.setMutator = function(mutator) { - if (this.mutator && this.mutator !== mutator) { - this.mutator.dispose(); - } - if (mutator) { - mutator.block_ = this; - this.mutator = mutator; - mutator.createIcon(); - } -}; - -/** - * Set whether the block is disabled or not. - * @param {boolean} disabled True if disabled. - */ -Blockly.BlockSvg.prototype.setDisabled = function(disabled) { - if (this.disabled != disabled) { - Blockly.BlockSvg.superClass_.setDisabled.call(this, disabled); - if (this.rendered) { - this.updateDisabled(); - } - } -}; - -/** - * Select this block. Highlight it visually. - */ -Blockly.BlockSvg.prototype.addSelect = function() { - Blockly.addClass_(/** @type {!Element} */ (this.svgGroup_), - 'blocklySelected'); - // Move the selected block to the top of the stack. - var block = this; - do { - var root = block.getSvgRoot(); - root.parentNode.appendChild(root); - block = block.getParent(); - } while (block); -}; - -/** - * Unselect this block. Remove its highlighting. - */ -Blockly.BlockSvg.prototype.removeSelect = function() { - Blockly.removeClass_(/** @type {!Element} */ (this.svgGroup_), - 'blocklySelected'); -}; - -/** - * Adds the dragging class to this block. - * Also disables the highlights/shadows to improve performance. - */ -Blockly.BlockSvg.prototype.addDragging = function() { - Blockly.addClass_(/** @type {!Element} */ (this.svgGroup_), - 'blocklyDragging'); -}; - -/** - * Removes the dragging class from this block. - */ -Blockly.BlockSvg.prototype.removeDragging = function() { - Blockly.removeClass_(/** @type {!Element} */ (this.svgGroup_), - 'blocklyDragging'); -}; - -// Overrides of functions on Blockly.Block that take into account whether the -// block has been rendered. - -/** - * Change the colour of a block. - * @param {number|string} colour HSV hue value, or #RRGGBB string. - */ -Blockly.BlockSvg.prototype.setColour = function(colour) { - Blockly.BlockSvg.superClass_.setColour.call(this, colour); - - if (this.rendered) { - this.updateColour(); - } -}; - -/** - * Set whether this block can chain onto the bottom of another block. - * @param {boolean} newBoolean True if there can be a previous statement. - * @param {string|Array.|null|undefined} opt_check Statement type or - * list of statement types. Null/undefined if any type could be connected. - */ -Blockly.BlockSvg.prototype.setPreviousStatement = - function(newBoolean, opt_check) { - /* eslint-disable indent */ - Blockly.BlockSvg.superClass_.setPreviousStatement.call(this, newBoolean, - opt_check); - - if (this.rendered) { - this.render(); - this.bumpNeighbours_(); - } -}; /* eslint-enable indent */ - -/** - * Set whether another block can chain onto the bottom of this block. - * @param {boolean} newBoolean True if there can be a next statement. - * @param {string|Array.|null|undefined} opt_check Statement type or - * list of statement types. Null/undefined if any type could be connected. - */ -Blockly.BlockSvg.prototype.setNextStatement = function(newBoolean, opt_check) { - Blockly.BlockSvg.superClass_.setNextStatement.call(this, newBoolean, - opt_check); - - if (this.rendered) { - this.render(); - this.bumpNeighbours_(); - } -}; - -/** - * Set whether this block returns a value. - * @param {boolean} newBoolean True if there is an output. - * @param {string|Array.|null|undefined} opt_check Returned type or list - * of returned types. Null or undefined if any type could be returned - * (e.g. variable get). - */ -Blockly.BlockSvg.prototype.setOutput = function(newBoolean, opt_check) { - Blockly.BlockSvg.superClass_.setOutput.call(this, newBoolean, opt_check); - - if (this.rendered) { - this.render(); - this.bumpNeighbours_(); - } -}; - -/** - * Set whether value inputs are arranged horizontally or vertically. - * @param {boolean} newBoolean True if inputs are horizontal. - */ -Blockly.BlockSvg.prototype.setInputsInline = function(newBoolean) { - Blockly.BlockSvg.superClass_.setInputsInline.call(this, newBoolean); - - if (this.rendered) { - this.render(); - this.bumpNeighbours_(); - } -}; - -/** - * Remove an input from this block. - * @param {string} name The name of the input. - * @param {boolean=} opt_quiet True to prevent error if input is not present. - * @throws {goog.asserts.AssertionError} if the input is not present and - * opt_quiet is not true. - */ -Blockly.BlockSvg.prototype.removeInput = function(name, opt_quiet) { - Blockly.BlockSvg.superClass_.removeInput.call(this, name, opt_quiet); - - if (this.rendered) { - this.render(); - // Removing an input will cause the block to change shape. - this.bumpNeighbours_(); - } -}; - -/** - * Move a numbered input to a different location on this block. - * @param {number} inputIndex Index of the input to move. - * @param {number} refIndex Index of input that should be after the moved input. - */ -Blockly.BlockSvg.prototype.moveNumberedInputBefore = function( - inputIndex, refIndex) { - Blockly.BlockSvg.superClass_.moveNumberedInputBefore.call(this, inputIndex, - refIndex); - - if (this.rendered) { - this.render(); - // Moving an input will cause the block to change shape. - this.bumpNeighbours_(); - } -}; - -/** - * Add a value input, statement input or local variable to this block. - * @param {number} type Either Blockly.INPUT_VALUE or Blockly.NEXT_STATEMENT or - * Blockly.DUMMY_INPUT. - * @param {string} name Language-neutral identifier which may used to find this - * input again. Should be unique to this block. - * @return {!Blockly.Input} The input object created. - * @private - */ -Blockly.BlockSvg.prototype.appendInput_ = function(type, name) { - var input = Blockly.BlockSvg.superClass_.appendInput_.call(this, type, name); - - if (this.rendered) { - this.render(); - // Adding an input will cause the block to change shape. - this.bumpNeighbours_(); - } - return input; -}; - -/** - * Returns connections originating from this block. - * @param {boolean} all If true, return all connections even hidden ones. - * Otherwise, for a non-rendered block return an empty list, and for a - * collapsed block don't return inputs connections. - * @return {!Array.} Array of connections. - * @private - */ -Blockly.BlockSvg.prototype.getConnections_ = function(all) { - var myConnections = []; - if (all || this.rendered) { - if (this.outputConnection) { - myConnections.push(this.outputConnection); - } - if (this.previousConnection) { - myConnections.push(this.previousConnection); - } - if (this.nextConnection) { - myConnections.push(this.nextConnection); - } - if (all || !this.collapsed_) { - for (var i = 0, input; input = this.inputList[i]; i++) { - if (input.connection) { - myConnections.push(input.connection); - } - } - } - } - return myConnections; -}; - -/** - * Create a connection of the specified type. - * @param {number} type The type of the connection to create. - * @return {!Blockly.RenderedConnection} A new connection of the specified type. - * @private - */ -Blockly.BlockSvg.prototype.makeConnection_ = function(type) { - return new Blockly.RenderedConnection(this, type); -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/blockly.js b/backend/_pv_1_3_5/static/blockly/core/blockly.js deleted file mode 100755 index fb6562ed2..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/blockly.js +++ /dev/null @@ -1,453 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2011 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Core JavaScript library for Blockly. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -// Top level object for Blockly. -goog.provide('Blockly'); - -goog.require('Blockly.BlockSvg.render'); -goog.require('Blockly.Events'); -goog.require('Blockly.FieldAngle'); -goog.require('Blockly.FieldCheckbox'); -goog.require('Blockly.FieldColour'); -// Date picker commented out since it increases footprint by 60%. -// Add it only if you need it. -//goog.require('Blockly.FieldDate'); -goog.require('Blockly.FieldDropdown'); -goog.require('Blockly.FieldImage'); -goog.require('Blockly.FieldTextInput'); -goog.require('Blockly.FieldNumber'); -goog.require('Blockly.FieldVariable'); -goog.require('Blockly.Generator'); -goog.require('Blockly.Msg'); -goog.require('Blockly.Procedures'); -goog.require('Blockly.Toolbox'); -goog.require('Blockly.WidgetDiv'); -goog.require('Blockly.WorkspaceSvg'); -goog.require('Blockly.constants'); -goog.require('Blockly.inject'); -goog.require('Blockly.utils'); -goog.require('goog.color'); -goog.require('goog.userAgent'); - - -// Turn off debugging when compiled. -var CLOSURE_DEFINES = {'goog.DEBUG': false}; - -/** - * The main workspace most recently used. - * Set by Blockly.WorkspaceSvg.prototype.markFocused - * @type {Blockly.Workspace} - */ -Blockly.mainWorkspace = null; - -/** - * Currently selected block. - * @type {Blockly.Block} - */ -Blockly.selected = null; - -/** - * Currently highlighted connection (during a drag). - * @type {Blockly.Connection} - * @private - */ -Blockly.highlightedConnection_ = null; - -/** - * Connection on dragged block that matches the highlighted connection. - * @type {Blockly.Connection} - * @private - */ -Blockly.localConnection_ = null; - -/** - * All of the connections on blocks that are currently being dragged. - * @type {!Array.} - * @private - */ -Blockly.draggingConnections_ = []; - -/** - * Contents of the local clipboard. - * @type {Element} - * @private - */ -Blockly.clipboardXml_ = null; - -/** - * Source of the local clipboard. - * @type {Blockly.WorkspaceSvg} - * @private - */ -Blockly.clipboardSource_ = null; - -/** - * Is the mouse dragging a block? - * DRAG_NONE - No drag operation. - * DRAG_STICKY - Still inside the sticky DRAG_RADIUS. - * DRAG_FREE - Freely draggable. - * @private - */ -Blockly.dragMode_ = Blockly.DRAG_NONE; - -/** - * Wrapper function called when a touch mouseUp occurs during a drag operation. - * @type {Array.} - * @private - */ -Blockly.onTouchUpWrapper_ = null; - -/** - * Convert a hue (HSV model) into an RGB hex triplet. - * @param {number} hue Hue on a colour wheel (0-360). - * @return {string} RGB code, e.g. '#5ba65b'. - */ -Blockly.hueToRgb = function(hue) { - return goog.color.hsvToHex(hue, Blockly.HSV_SATURATION, - Blockly.HSV_VALUE * 255); -}; - -/** - * Returns the dimensions of the specified SVG image. - * @param {!Element} svg SVG image. - * @return {!Object} Contains width and height properties. - */ -Blockly.svgSize = function(svg) { - return {width: svg.cachedWidth_, - height: svg.cachedHeight_}; -}; - -/** - * Size the workspace when the contents change. This also updates - * scrollbars accordingly. - * @param {!Blockly.WorkspaceSvg} workspace The workspace to resize. - */ -Blockly.resizeSvgContents = function(workspace) { - workspace.resizeContents(); -}; - -/** - * Size the SVG image to completely fill its container. Call this when the view - * actually changes sizes (e.g. on a window resize/device orientation change). - * See Blockly.resizeSvgContents to resize the workspace when the contents - * change (e.g. when a block is added or removed). - * Record the height/width of the SVG image. - * @param {!Blockly.WorkspaceSvg} workspace Any workspace in the SVG. - */ -Blockly.svgResize = function(workspace) { - var mainWorkspace = workspace; - while (mainWorkspace.options.parentWorkspace) { - mainWorkspace = mainWorkspace.options.parentWorkspace; - } - var svg = mainWorkspace.getParentSvg(); - var div = svg.parentNode; - if (!div) { - // Workspace deleted, or something. - return; - } - var width = div.offsetWidth; - var height = div.offsetHeight; - if (svg.cachedWidth_ != width) { - svg.setAttribute('width', width + 'px'); - svg.cachedWidth_ = width; - } - if (svg.cachedHeight_ != height) { - svg.setAttribute('height', height + 'px'); - svg.cachedHeight_ = height; - } - mainWorkspace.resize(); -}; - -/** - * Handle a mouse-up anywhere on the page. - * @param {!Event} e Mouse up event. - * @private - */ -Blockly.onMouseUp_ = function(e) { - var workspace = Blockly.getMainWorkspace(); - Blockly.Css.setCursor(Blockly.Css.Cursor.OPEN); - workspace.dragMode_ = Blockly.DRAG_NONE; - // Unbind the touch event if it exists. - if (Blockly.onTouchUpWrapper_) { - Blockly.unbindEvent_(Blockly.onTouchUpWrapper_); - Blockly.onTouchUpWrapper_ = null; - } - if (Blockly.onMouseMoveWrapper_) { - Blockly.unbindEvent_(Blockly.onMouseMoveWrapper_); - Blockly.onMouseMoveWrapper_ = null; - } -}; - -/** - * Handle a mouse-move on SVG drawing surface. - * @param {!Event} e Mouse move event. - * @private - */ -Blockly.onMouseMove_ = function(e) { - if (e.touches && e.touches.length >= 2) { - return; // Multi-touch gestures won't have e.clientX. - } - var workspace = Blockly.getMainWorkspace(); - if (workspace.dragMode_ != Blockly.DRAG_NONE) { - var dx = e.clientX - workspace.startDragMouseX; - var dy = e.clientY - workspace.startDragMouseY; - var metrics = workspace.startDragMetrics; - var x = workspace.startScrollX + dx; - var y = workspace.startScrollY + dy; - x = Math.min(x, -metrics.contentLeft); - y = Math.min(y, -metrics.contentTop); - x = Math.max(x, metrics.viewWidth - metrics.contentLeft - - metrics.contentWidth); - y = Math.max(y, metrics.viewHeight - metrics.contentTop - - metrics.contentHeight); - - // Move the scrollbars and the page will scroll automatically. - workspace.scrollbar.set(-x - metrics.contentLeft, - -y - metrics.contentTop); - // Cancel the long-press if the drag has moved too far. - if (Math.sqrt(dx * dx + dy * dy) > Blockly.DRAG_RADIUS) { - Blockly.longStop_(); - workspace.dragMode_ = Blockly.DRAG_FREE; - } - e.stopPropagation(); - e.preventDefault(); - } -}; - -/** - * Handle a key-down on SVG drawing surface. - * @param {!Event} e Key down event. - * @private - */ -Blockly.onKeyDown_ = function(e) { - if (Blockly.mainWorkspace.options.readOnly || Blockly.isTargetInput_(e)) { - // No key actions on readonly workspaces. - // When focused on an HTML text input widget, don't trap any keys. - return; - } - var deleteBlock = false; - if (e.keyCode == 27) { - // Pressing esc closes the context menu. - Blockly.hideChaff(); - } else if (e.keyCode == 8 || e.keyCode == 46) { - // Delete or backspace. - // Stop the browser from going back to the previous page. - // Do this first to prevent an error in the delete code from resulting in - // data loss. - e.preventDefault(); - if (Blockly.selected && Blockly.selected.isDeletable()) { - deleteBlock = true; - } - } else if (e.altKey || e.ctrlKey || e.metaKey) { - if (Blockly.selected && - Blockly.selected.isDeletable() && Blockly.selected.isMovable()) { - if (e.keyCode == 67) { - // 'c' for copy. - Blockly.hideChaff(); - Blockly.copy_(Blockly.selected); - } else if (e.keyCode == 88) { - // 'x' for cut. - Blockly.copy_(Blockly.selected); - deleteBlock = true; - } - } - if (e.keyCode == 86) { - // 'v' for paste. - if (Blockly.clipboardXml_) { - Blockly.Events.setGroup(true); - Blockly.clipboardSource_.paste(Blockly.clipboardXml_); - Blockly.Events.setGroup(false); - } - } else if (e.keyCode == 90) { - // 'z' for undo 'Z' is for redo. - Blockly.hideChaff(); - Blockly.mainWorkspace.undo(e.shiftKey); - } - } - if (deleteBlock) { - // Common code for delete and cut. - Blockly.Events.setGroup(true); - Blockly.hideChaff(); - var heal = Blockly.dragMode_ != Blockly.DRAG_FREE; - Blockly.selected.dispose(heal, true); - if (Blockly.highlightedConnection_) { - Blockly.highlightedConnection_.unhighlight(); - Blockly.highlightedConnection_ = null; - } - Blockly.Events.setGroup(false); - } -}; - -/** - * Stop binding to the global mouseup and mousemove events. - * @private - */ -Blockly.terminateDrag_ = function() { - Blockly.BlockSvg.terminateDrag(); - Blockly.Flyout.terminateDrag_(); -}; - -/** - * PID of queued long-press task. - * @private - */ -Blockly.longPid_ = 0; - -/** - * Context menus on touch devices are activated using a long-press. - * Unfortunately the contextmenu touch event is currently (2015) only suported - * by Chrome. This function is fired on any touchstart event, queues a task, - * which after about a second opens the context menu. The tasks is killed - * if the touch event terminates early. - * @param {!Event} e Touch start event. - * @param {!Blockly.Block|!Blockly.WorkspaceSvg} uiObject The block or workspace - * under the touchstart event. - * @private - */ -Blockly.longStart_ = function(e, uiObject) { - Blockly.longStop_(); - Blockly.longPid_ = setTimeout(function() { - e.button = 2; // Simulate a right button click. - uiObject.onMouseDown_(e); - }, Blockly.LONGPRESS); -}; - -/** - * Nope, that's not a long-press. Either touchend or touchcancel was fired, - * or a drag hath begun. Kill the queued long-press task. - * @private - */ -Blockly.longStop_ = function() { - if (Blockly.longPid_) { - clearTimeout(Blockly.longPid_); - Blockly.longPid_ = 0; - } -}; - -/** - * Copy a block onto the local clipboard. - * @param {!Blockly.Block} block Block to be copied. - * @private - */ -Blockly.copy_ = function(block) { - var xmlBlock = Blockly.Xml.blockToDom(block); - if (Blockly.dragMode_ != Blockly.DRAG_FREE) { - Blockly.Xml.deleteNext(xmlBlock); - } - // Encode start position in XML. - var xy = block.getRelativeToSurfaceXY(); - xmlBlock.setAttribute('x', block.RTL ? -xy.x : xy.x); - xmlBlock.setAttribute('y', xy.y); - Blockly.clipboardXml_ = xmlBlock; - Blockly.clipboardSource_ = block.workspace; -}; - -/** - * Duplicate this block and its children. - * @param {!Blockly.Block} block Block to be copied. - * @private - */ -Blockly.duplicate_ = function(block) { - // Save the clipboard. - var clipboardXml = Blockly.clipboardXml_; - var clipboardSource = Blockly.clipboardSource_; - - // Create a duplicate via a copy/paste operation. - Blockly.copy_(block); - block.workspace.paste(Blockly.clipboardXml_); - - // Restore the clipboard. - Blockly.clipboardXml_ = clipboardXml; - Blockly.clipboardSource_ = clipboardSource; -}; - -/** - * Cancel the native context menu, unless the focus is on an HTML input widget. - * @param {!Event} e Mouse down event. - * @private - */ -Blockly.onContextMenu_ = function(e) { - if (!Blockly.isTargetInput_(e)) { - // When focused on an HTML text input widget, don't cancel the context menu. - e.preventDefault(); - } -}; - -/** - * Close tooltips, context menus, dropdown selections, etc. - * @param {boolean=} opt_allowToolbox If true, don't close the toolbox. - */ -Blockly.hideChaff = function(opt_allowToolbox) { - Blockly.Tooltip.hide(); - Blockly.WidgetDiv.hide(); - if (!opt_allowToolbox) { - var workspace = Blockly.getMainWorkspace(); - if (workspace.toolbox_ && - workspace.toolbox_.flyout_ && - workspace.toolbox_.flyout_.autoClose) { - workspace.toolbox_.clearSelection(); - } - } -}; - -/** - * When something in Blockly's workspace changes, call a function. - * @param {!Function} func Function to call. - * @return {!Array.} Opaque data that can be passed to - * removeChangeListener. - * @deprecated April 2015 - */ -Blockly.addChangeListener = function(func) { - // Backwards compatability from before there could be multiple workspaces. - console.warn('Deprecated call to Blockly.addChangeListener, ' + - 'use workspace.addChangeListener instead.'); - return Blockly.getMainWorkspace().addChangeListener(func); -}; - -/** - * Returns the main workspace. Returns the last used main workspace (based on - * focus). Try not to use this function, particularly if there are multiple - * Blockly instances on a page. - * @return {!Blockly.Workspace} The main workspace. - */ -Blockly.getMainWorkspace = function() { - return Blockly.mainWorkspace; -}; - -// IE9 does not have a console. Create a stub to stop errors. -if (!goog.global['console']) { - goog.global['console'] = { - 'log': function() {}, - 'warn': function() {} - }; -} - -// Export symbols that would otherwise be renamed by Closure compiler. -if (!goog.global['Blockly']) { - goog.global['Blockly'] = {}; -} -goog.global['Blockly']['getMainWorkspace'] = Blockly.getMainWorkspace; -goog.global['Blockly']['addChangeListener'] = Blockly.addChangeListener; diff --git a/backend/_pv_1_3_5/static/blockly/core/blocks.js b/backend/_pv_1_3_5/static/blockly/core/blocks.js deleted file mode 100755 index d6932ceb9..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/blocks.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2013 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Empty name space for the Blocks singleton. - * @author spertus@google.com (Ellen Spertus) - */ -'use strict'; - -goog.provide('Blockly.Blocks'); - -/** - * Allow for switching between one and zero based indexing for lists and text, - * one based by default. - */ -Blockly.Blocks.ONE_BASED_INDEXING = true; diff --git a/backend/_pv_1_3_5/static/blockly/core/bubble.js b/backend/_pv_1_3_5/static/blockly/core/bubble.js deleted file mode 100755 index d4c1e2719..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/bubble.js +++ /dev/null @@ -1,579 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Object representing a UI bubble. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Bubble'); - -goog.require('Blockly.Workspace'); -goog.require('goog.dom'); -goog.require('goog.math'); -goog.require('goog.math.Coordinate'); -goog.require('goog.userAgent'); - - -/** - * Class for UI bubble. - * @param {!Blockly.WorkspaceSvg} workspace The workspace on which to draw the - * bubble. - * @param {!Element} content SVG content for the bubble. - * @param {Element} shape SVG element to avoid eclipsing. - * @param {!goog.math.Coodinate} anchorXY Absolute position of bubble's anchor - * point. - * @param {?number} bubbleWidth Width of bubble, or null if not resizable. - * @param {?number} bubbleHeight Height of bubble, or null if not resizable. - * @constructor - */ -Blockly.Bubble = function(workspace, content, shape, anchorXY, - bubbleWidth, bubbleHeight) { - this.workspace_ = workspace; - this.content_ = content; - this.shape_ = shape; - - var angle = Blockly.Bubble.ARROW_ANGLE; - if (this.workspace_.RTL) { - angle = -angle; - } - this.arrow_radians_ = goog.math.toRadians(angle); - - var canvas = workspace.getBubbleCanvas(); - canvas.appendChild(this.createDom_(content, !!(bubbleWidth && bubbleHeight))); - - this.setAnchorLocation(anchorXY); - if (!bubbleWidth || !bubbleHeight) { - var bBox = /** @type {SVGLocatable} */ (this.content_).getBBox(); - bubbleWidth = bBox.width + 2 * Blockly.Bubble.BORDER_WIDTH; - bubbleHeight = bBox.height + 2 * Blockly.Bubble.BORDER_WIDTH; - } - this.setBubbleSize(bubbleWidth, bubbleHeight); - - // Render the bubble. - this.positionBubble_(); - this.renderArrow_(); - this.rendered_ = true; - - if (!workspace.options.readOnly) { - Blockly.bindEvent_(this.bubbleBack_, 'mousedown', this, - this.bubbleMouseDown_); - if (this.resizeGroup_) { - Blockly.bindEvent_(this.resizeGroup_, 'mousedown', this, - this.resizeMouseDown_); - } - } -}; - -/** - * Width of the border around the bubble. - */ -Blockly.Bubble.BORDER_WIDTH = 6; - -/** - * Determines the thickness of the base of the arrow in relation to the size - * of the bubble. Higher numbers result in thinner arrows. - */ -Blockly.Bubble.ARROW_THICKNESS = 10; - -/** - * The number of degrees that the arrow bends counter-clockwise. - */ -Blockly.Bubble.ARROW_ANGLE = 20; - -/** - * The sharpness of the arrow's bend. Higher numbers result in smoother arrows. - */ -Blockly.Bubble.ARROW_BEND = 4; - -/** - * Distance between arrow point and anchor point. - */ -Blockly.Bubble.ANCHOR_RADIUS = 8; - -/** - * Wrapper function called when a mouseUp occurs during a drag operation. - * @type {Array.} - * @private - */ -Blockly.Bubble.onMouseUpWrapper_ = null; - -/** - * Wrapper function called when a mouseMove occurs during a drag operation. - * @type {Array.} - * @private - */ -Blockly.Bubble.onMouseMoveWrapper_ = null; - -/** - * Function to call on resize of bubble. - * @type {Function} - */ -Blockly.Bubble.prototype.resizeCallback_ = null; - -/** - * Stop binding to the global mouseup and mousemove events. - * @private - */ -Blockly.Bubble.unbindDragEvents_ = function() { - if (Blockly.Bubble.onMouseUpWrapper_) { - Blockly.unbindEvent_(Blockly.Bubble.onMouseUpWrapper_); - Blockly.Bubble.onMouseUpWrapper_ = null; - } - if (Blockly.Bubble.onMouseMoveWrapper_) { - Blockly.unbindEvent_(Blockly.Bubble.onMouseMoveWrapper_); - Blockly.Bubble.onMouseMoveWrapper_ = null; - } -}; - -/** - * Flag to stop incremental rendering during construction. - * @private - */ -Blockly.Bubble.prototype.rendered_ = false; - -/** - * Absolute coordinate of anchor point. - * @type {goog.math.Coordinate} - * @private - */ -Blockly.Bubble.prototype.anchorXY_ = null; - -/** - * Relative X coordinate of bubble with respect to the anchor's centre. - * In RTL mode the initial value is negated. - * @private - */ -Blockly.Bubble.prototype.relativeLeft_ = 0; - -/** - * Relative Y coordinate of bubble with respect to the anchor's centre. - * @private - */ -Blockly.Bubble.prototype.relativeTop_ = 0; - -/** - * Width of bubble. - * @private - */ -Blockly.Bubble.prototype.width_ = 0; - -/** - * Height of bubble. - * @private - */ -Blockly.Bubble.prototype.height_ = 0; - -/** - * Automatically position and reposition the bubble. - * @private - */ -Blockly.Bubble.prototype.autoLayout_ = true; - -/** - * Create the bubble's DOM. - * @param {!Element} content SVG content for the bubble. - * @param {boolean} hasResize Add diagonal resize gripper if true. - * @return {!Element} The bubble's SVG group. - * @private - */ -Blockly.Bubble.prototype.createDom_ = function(content, hasResize) { - /* Create the bubble. Here's the markup that will be generated: - - - - - - - - - - - [...content goes here...] - - */ - this.bubbleGroup_ = Blockly.createSvgElement('g', {}, null); - var filter = - {'filter': 'url(#' + this.workspace_.options.embossFilterId + ')'}; - if (goog.userAgent.getUserAgentString().indexOf('JavaFX') != -1) { - // Multiple reports that JavaFX can't handle filters. UserAgent: - // Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.44 - // (KHTML, like Gecko) JavaFX/8.0 Safari/537.44 - // https://github.com/google/blockly/issues/99 - filter = {}; - } - var bubbleEmboss = Blockly.createSvgElement('g', - filter, this.bubbleGroup_); - this.bubbleArrow_ = Blockly.createSvgElement('path', {}, bubbleEmboss); - this.bubbleBack_ = Blockly.createSvgElement('rect', - {'class': 'blocklyDraggable', 'x': 0, 'y': 0, - 'rx': Blockly.Bubble.BORDER_WIDTH, 'ry': Blockly.Bubble.BORDER_WIDTH}, - bubbleEmboss); - if (hasResize) { - this.resizeGroup_ = Blockly.createSvgElement('g', - {'class': this.workspace_.RTL ? - 'blocklyResizeSW' : 'blocklyResizeSE'}, - this.bubbleGroup_); - var resizeSize = 2 * Blockly.Bubble.BORDER_WIDTH; - Blockly.createSvgElement('polygon', - {'points': '0,x x,x x,0'.replace(/x/g, resizeSize.toString())}, - this.resizeGroup_); - Blockly.createSvgElement('line', - {'class': 'blocklyResizeLine', - 'x1': resizeSize / 3, 'y1': resizeSize - 1, - 'x2': resizeSize - 1, 'y2': resizeSize / 3}, this.resizeGroup_); - Blockly.createSvgElement('line', - {'class': 'blocklyResizeLine', - 'x1': resizeSize * 2 / 3, 'y1': resizeSize - 1, - 'x2': resizeSize - 1, 'y2': resizeSize * 2 / 3}, this.resizeGroup_); - } else { - this.resizeGroup_ = null; - } - this.bubbleGroup_.appendChild(content); - return this.bubbleGroup_; -}; - -/** - * Handle a mouse-down on bubble's border. - * @param {!Event} e Mouse down event. - * @private - */ -Blockly.Bubble.prototype.bubbleMouseDown_ = function(e) { - this.promote_(); - Blockly.Bubble.unbindDragEvents_(); - if (Blockly.isRightButton(e)) { - // No right-click. - e.stopPropagation(); - return; - } else if (Blockly.isTargetInput_(e)) { - // When focused on an HTML text input widget, don't trap any events. - return; - } - // Left-click (or middle click) - Blockly.Css.setCursor(Blockly.Css.Cursor.CLOSED); - - this.workspace_.startDrag(e, new goog.math.Coordinate( - this.workspace_.RTL ? -this.relativeLeft_ : this.relativeLeft_, - this.relativeTop_)); - - Blockly.Bubble.onMouseUpWrapper_ = Blockly.bindEvent_(document, - 'mouseup', this, Blockly.Bubble.unbindDragEvents_); - Blockly.Bubble.onMouseMoveWrapper_ = Blockly.bindEvent_(document, - 'mousemove', this, this.bubbleMouseMove_); - Blockly.hideChaff(); - // This event has been handled. No need to bubble up to the document. - e.stopPropagation(); -}; - -/** - * Drag this bubble to follow the mouse. - * @param {!Event} e Mouse move event. - * @private - */ -Blockly.Bubble.prototype.bubbleMouseMove_ = function(e) { - this.autoLayout_ = false; - var newXY = this.workspace_.moveDrag(e); - this.relativeLeft_ = this.workspace_.RTL ? -newXY.x : newXY.x; - this.relativeTop_ = newXY.y; - this.positionBubble_(); - this.renderArrow_(); -}; - -/** - * Handle a mouse-down on bubble's resize corner. - * @param {!Event} e Mouse down event. - * @private - */ -Blockly.Bubble.prototype.resizeMouseDown_ = function(e) { - this.promote_(); - Blockly.Bubble.unbindDragEvents_(); - if (Blockly.isRightButton(e)) { - // No right-click. - e.stopPropagation(); - return; - } - // Left-click (or middle click) - Blockly.Css.setCursor(Blockly.Css.Cursor.CLOSED); - - this.workspace_.startDrag(e, new goog.math.Coordinate( - this.workspace_.RTL ? -this.width_ : this.width_, this.height_)); - - Blockly.Bubble.onMouseUpWrapper_ = Blockly.bindEvent_(document, - 'mouseup', this, Blockly.Bubble.unbindDragEvents_); - Blockly.Bubble.onMouseMoveWrapper_ = Blockly.bindEvent_(document, - 'mousemove', this, this.resizeMouseMove_); - Blockly.hideChaff(); - // This event has been handled. No need to bubble up to the document. - e.stopPropagation(); -}; - -/** - * Resize this bubble to follow the mouse. - * @param {!Event} e Mouse move event. - * @private - */ -Blockly.Bubble.prototype.resizeMouseMove_ = function(e) { - this.autoLayout_ = false; - var newXY = this.workspace_.moveDrag(e); - this.setBubbleSize(this.workspace_.RTL ? -newXY.x : newXY.x, newXY.y); - if (this.workspace_.RTL) { - // RTL requires the bubble to move its left edge. - this.positionBubble_(); - } -}; - -/** - * Register a function as a callback event for when the bubble is resized. - * @param {!Function} callback The function to call on resize. - */ -Blockly.Bubble.prototype.registerResizeEvent = function(callback) { - this.resizeCallback_ = callback; -}; - -/** - * Move this bubble to the top of the stack. - * @private - */ -Blockly.Bubble.prototype.promote_ = function() { - var svgGroup = this.bubbleGroup_.parentNode; - svgGroup.appendChild(this.bubbleGroup_); -}; - -/** - * Notification that the anchor has moved. - * Update the arrow and bubble accordingly. - * @param {!goog.math.Coordinate} xy Absolute location. - */ -Blockly.Bubble.prototype.setAnchorLocation = function(xy) { - this.anchorXY_ = xy; - if (this.rendered_) { - this.positionBubble_(); - } -}; - -/** - * Position the bubble so that it does not fall off-screen. - * @private - */ -Blockly.Bubble.prototype.layoutBubble_ = function() { - // Compute the preferred bubble location. - var relativeLeft = -this.width_ / 4; - var relativeTop = -this.height_ - Blockly.BlockSvg.MIN_BLOCK_Y; - // Prevent the bubble from being off-screen. - var metrics = this.workspace_.getMetrics(); - metrics.viewWidth /= this.workspace_.scale; - metrics.viewLeft /= this.workspace_.scale; - var anchorX = this.anchorXY_.x; - if (this.workspace_.RTL) { - if (anchorX - metrics.viewLeft - relativeLeft - this.width_ < - Blockly.Scrollbar.scrollbarThickness) { - // Slide the bubble right until it is onscreen. - relativeLeft = anchorX - metrics.viewLeft - this.width_ - - Blockly.Scrollbar.scrollbarThickness; - } else if (anchorX - metrics.viewLeft - relativeLeft > - metrics.viewWidth) { - // Slide the bubble left until it is onscreen. - relativeLeft = anchorX - metrics.viewLeft - metrics.viewWidth; - } - } else { - if (anchorX + relativeLeft < metrics.viewLeft) { - // Slide the bubble right until it is onscreen. - relativeLeft = metrics.viewLeft - anchorX; - } else if (metrics.viewLeft + metrics.viewWidth < - anchorX + relativeLeft + this.width_ + - Blockly.BlockSvg.SEP_SPACE_X + - Blockly.Scrollbar.scrollbarThickness) { - // Slide the bubble left until it is onscreen. - relativeLeft = metrics.viewLeft + metrics.viewWidth - anchorX - - this.width_ - Blockly.Scrollbar.scrollbarThickness; - } - } - if (this.anchorXY_.y + relativeTop < metrics.viewTop) { - // Slide the bubble below the block. - var bBox = /** @type {SVGLocatable} */ (this.shape_).getBBox(); - relativeTop = bBox.height; - } - this.relativeLeft_ = relativeLeft; - this.relativeTop_ = relativeTop; -}; - -/** - * Move the bubble to a location relative to the anchor's centre. - * @private - */ -Blockly.Bubble.prototype.positionBubble_ = function() { - var left = this.anchorXY_.x; - if (this.workspace_.RTL) { - left -= this.relativeLeft_ + this.width_; - } else { - left += this.relativeLeft_; - } - var top = this.relativeTop_ + this.anchorXY_.y; - this.bubbleGroup_.setAttribute('transform', - 'translate(' + left + ',' + top + ')'); -}; - -/** - * Get the dimensions of this bubble. - * @return {!Object} Object with width and height properties. - */ -Blockly.Bubble.prototype.getBubbleSize = function() { - return {width: this.width_, height: this.height_}; -}; - -/** - * Size this bubble. - * @param {number} width Width of the bubble. - * @param {number} height Height of the bubble. - */ -Blockly.Bubble.prototype.setBubbleSize = function(width, height) { - var doubleBorderWidth = 2 * Blockly.Bubble.BORDER_WIDTH; - // Minimum size of a bubble. - width = Math.max(width, doubleBorderWidth + 45); - height = Math.max(height, doubleBorderWidth + 20); - this.width_ = width; - this.height_ = height; - this.bubbleBack_.setAttribute('width', width); - this.bubbleBack_.setAttribute('height', height); - if (this.resizeGroup_) { - if (this.workspace_.RTL) { - // Mirror the resize group. - var resizeSize = 2 * Blockly.Bubble.BORDER_WIDTH; - this.resizeGroup_.setAttribute('transform', 'translate(' + - resizeSize + ',' + (height - doubleBorderWidth) + ') scale(-1 1)'); - } else { - this.resizeGroup_.setAttribute('transform', 'translate(' + - (width - doubleBorderWidth) + ',' + - (height - doubleBorderWidth) + ')'); - } - } - if (this.rendered_) { - if (this.autoLayout_) { - this.layoutBubble_(); - } - this.positionBubble_(); - this.renderArrow_(); - } - // Allow the contents to resize. - if (this.resizeCallback_) { - this.resizeCallback_(); - } -}; - -/** - * Draw the arrow between the bubble and the origin. - * @private - */ -Blockly.Bubble.prototype.renderArrow_ = function() { - var steps = []; - // Find the relative coordinates of the center of the bubble. - var relBubbleX = this.width_ / 2; - var relBubbleY = this.height_ / 2; - // Find the relative coordinates of the center of the anchor. - var relAnchorX = -this.relativeLeft_; - var relAnchorY = -this.relativeTop_; - if (relBubbleX == relAnchorX && relBubbleY == relAnchorY) { - // Null case. Bubble is directly on top of the anchor. - // Short circuit this rather than wade through divide by zeros. - steps.push('M ' + relBubbleX + ',' + relBubbleY); - } else { - // Compute the angle of the arrow's line. - var rise = relAnchorY - relBubbleY; - var run = relAnchorX - relBubbleX; - if (this.workspace_.RTL) { - run *= -1; - } - var hypotenuse = Math.sqrt(rise * rise + run * run); - var angle = Math.acos(run / hypotenuse); - if (rise < 0) { - angle = 2 * Math.PI - angle; - } - // Compute a line perpendicular to the arrow. - var rightAngle = angle + Math.PI / 2; - if (rightAngle > Math.PI * 2) { - rightAngle -= Math.PI * 2; - } - var rightRise = Math.sin(rightAngle); - var rightRun = Math.cos(rightAngle); - - // Calculate the thickness of the base of the arrow. - var bubbleSize = this.getBubbleSize(); - var thickness = (bubbleSize.width + bubbleSize.height) / - Blockly.Bubble.ARROW_THICKNESS; - thickness = Math.min(thickness, bubbleSize.width, bubbleSize.height) / 2; - - // Back the tip of the arrow off of the anchor. - var backoffRatio = 1 - Blockly.Bubble.ANCHOR_RADIUS / hypotenuse; - relAnchorX = relBubbleX + backoffRatio * run; - relAnchorY = relBubbleY + backoffRatio * rise; - - // Coordinates for the base of the arrow. - var baseX1 = relBubbleX + thickness * rightRun; - var baseY1 = relBubbleY + thickness * rightRise; - var baseX2 = relBubbleX - thickness * rightRun; - var baseY2 = relBubbleY - thickness * rightRise; - - // Distortion to curve the arrow. - var swirlAngle = angle + this.arrow_radians_; - if (swirlAngle > Math.PI * 2) { - swirlAngle -= Math.PI * 2; - } - var swirlRise = Math.sin(swirlAngle) * - hypotenuse / Blockly.Bubble.ARROW_BEND; - var swirlRun = Math.cos(swirlAngle) * - hypotenuse / Blockly.Bubble.ARROW_BEND; - - steps.push('M' + baseX1 + ',' + baseY1); - steps.push('C' + (baseX1 + swirlRun) + ',' + (baseY1 + swirlRise) + - ' ' + relAnchorX + ',' + relAnchorY + - ' ' + relAnchorX + ',' + relAnchorY); - steps.push('C' + relAnchorX + ',' + relAnchorY + - ' ' + (baseX2 + swirlRun) + ',' + (baseY2 + swirlRise) + - ' ' + baseX2 + ',' + baseY2); - } - steps.push('z'); - this.bubbleArrow_.setAttribute('d', steps.join(' ')); -}; - -/** - * Change the colour of a bubble. - * @param {string} hexColour Hex code of colour. - */ -Blockly.Bubble.prototype.setColour = function(hexColour) { - this.bubbleBack_.setAttribute('fill', hexColour); - this.bubbleArrow_.setAttribute('fill', hexColour); -}; - -/** - * Dispose of this bubble. - */ -Blockly.Bubble.prototype.dispose = function() { - Blockly.Bubble.unbindDragEvents_(); - // Dispose of and unlink the bubble. - goog.dom.removeNode(this.bubbleGroup_); - this.bubbleGroup_ = null; - this.bubbleArrow_ = null; - this.bubbleBack_ = null; - this.resizeGroup_ = null; - this.workspace_ = null; - this.content_ = null; - this.shape_ = null; -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/comment.js b/backend/_pv_1_3_5/static/blockly/core/comment.js deleted file mode 100755 index 2121530c0..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/comment.js +++ /dev/null @@ -1,278 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2011 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Object representing a code comment. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Comment'); - -goog.require('Blockly.Bubble'); -goog.require('Blockly.Icon'); -goog.require('goog.userAgent'); - - -/** - * Class for a comment. - * @param {!Blockly.Block} block The block associated with this comment. - * @extends {Blockly.Icon} - * @constructor - */ -Blockly.Comment = function(block) { - Blockly.Comment.superClass_.constructor.call(this, block); - this.createIcon(); -}; -goog.inherits(Blockly.Comment, Blockly.Icon); - -/** - * Comment text (if bubble is not visible). - * @private - */ -Blockly.Comment.prototype.text_ = ''; - -/** - * Width of bubble. - * @private - */ -Blockly.Comment.prototype.width_ = 160; - -/** - * Height of bubble. - * @private - */ -Blockly.Comment.prototype.height_ = 80; - -/** - * Draw the comment icon. - * @param {!Element} group The icon group. - * @private - */ -Blockly.Comment.prototype.drawIcon_ = function(group) { - // Circle. - Blockly.createSvgElement('circle', - {'class': 'blocklyIconShape', 'r': '8', 'cx': '8', 'cy': '8'}, - group); - // Can't use a real '?' text character since different browsers and operating - // systems render it differently. - // Body of question mark. - Blockly.createSvgElement('path', - {'class': 'blocklyIconSymbol', - 'd': 'm6.8,10h2c0.003,-0.617 0.271,-0.962 0.633,-1.266 2.875,-2.405 0.607,-5.534 -3.765,-3.874v1.7c3.12,-1.657 3.698,0.118 2.336,1.25 -1.201,0.998 -1.201,1.528 -1.204,2.19z'}, - group); - // Dot of question point. - Blockly.createSvgElement('rect', - {'class': 'blocklyIconSymbol', - 'x': '6.8', 'y': '10.78', 'height': '2', 'width': '2'}, - group); -}; - -/** - * Create the editor for the comment's bubble. - * @return {!Element} The top-level node of the editor. - * @private - */ -Blockly.Comment.prototype.createEditor_ = function() { - /* Create the editor. Here's the markup that will be generated: - - - - - - */ - this.foreignObject_ = Blockly.createSvgElement('foreignObject', - {'x': Blockly.Bubble.BORDER_WIDTH, 'y': Blockly.Bubble.BORDER_WIDTH}, - null); - var body = document.createElementNS(Blockly.HTML_NS, 'body'); - body.setAttribute('xmlns', Blockly.HTML_NS); - body.className = 'blocklyMinimalBody'; - var textarea = document.createElementNS(Blockly.HTML_NS, 'textarea'); - textarea.className = 'blocklyCommentTextarea'; - textarea.setAttribute('dir', this.block_.RTL ? 'RTL' : 'LTR'); - body.appendChild(textarea); - this.textarea_ = textarea; - this.foreignObject_.appendChild(body); - Blockly.bindEvent_(textarea, 'mouseup', this, this.textareaFocus_); - // Don't zoom with mousewheel. - Blockly.bindEvent_(textarea, 'wheel', this, function(e) { - e.stopPropagation(); - }); - Blockly.bindEvent_(textarea, 'change', this, function(e) { - if (this.text_ != textarea.value) { - Blockly.Events.fire(new Blockly.Events.Change( - this.block_, 'comment', null, this.text_, textarea.value)); - this.text_ = textarea.value; - } - }); - setTimeout(function() { - textarea.focus(); - }, 0); - return this.foreignObject_; -}; - -/** - * Add or remove editability of the comment. - * @override - */ -Blockly.Comment.prototype.updateEditable = function() { - if (this.isVisible()) { - // Toggling visibility will force a rerendering. - this.setVisible(false); - this.setVisible(true); - } - // Allow the icon to update. - Blockly.Icon.prototype.updateEditable.call(this); -}; - -/** - * Callback function triggered when the bubble has resized. - * Resize the text area accordingly. - * @private - */ -Blockly.Comment.prototype.resizeBubble_ = function() { - if (this.isVisible()) { - var size = this.bubble_.getBubbleSize(); - var doubleBorderWidth = 2 * Blockly.Bubble.BORDER_WIDTH; - this.foreignObject_.setAttribute('width', size.width - doubleBorderWidth); - this.foreignObject_.setAttribute('height', size.height - doubleBorderWidth); - this.textarea_.style.width = (size.width - doubleBorderWidth - 4) + 'px'; - this.textarea_.style.height = (size.height - doubleBorderWidth - 4) + 'px'; - } -}; - -/** - * Show or hide the comment bubble. - * @param {boolean} visible True if the bubble should be visible. - */ -Blockly.Comment.prototype.setVisible = function(visible) { - if (visible == this.isVisible()) { - // No change. - return; - } - Blockly.Events.fire( - new Blockly.Events.Ui(this.block_, 'commentOpen', !visible, visible)); - if ((!this.block_.isEditable() && !this.textarea_) || goog.userAgent.IE) { - // Steal the code from warnings to make an uneditable text bubble. - // MSIE does not support foreignobject; textareas are impossible. - // http://msdn.microsoft.com/en-us/library/hh834675%28v=vs.85%29.aspx - // Always treat comments in IE as uneditable. - Blockly.Warning.prototype.setVisible.call(this, visible); - return; - } - // Save the bubble stats before the visibility switch. - var text = this.getText(); - var size = this.getBubbleSize(); - if (visible) { - // Create the bubble. - this.bubble_ = new Blockly.Bubble( - /** @type {!Blockly.WorkspaceSvg} */ (this.block_.workspace), - this.createEditor_(), this.block_.svgPath_, - this.iconXY_, this.width_, this.height_); - this.bubble_.registerResizeEvent(this.resizeBubble_.bind(this)); - this.updateColour(); - } else { - // Dispose of the bubble. - this.bubble_.dispose(); - this.bubble_ = null; - this.textarea_ = null; - this.foreignObject_ = null; - } - // Restore the bubble stats after the visibility switch. - this.setText(text); - this.setBubbleSize(size.width, size.height); -}; - -/** - * Bring the comment to the top of the stack when clicked on. - * @param {!Event} e Mouse up event. - * @private - */ -Blockly.Comment.prototype.textareaFocus_ = function(e) { - // Ideally this would be hooked to the focus event for the comment. - // However doing so in Firefox swallows the cursor for unknown reasons. - // So this is hooked to mouseup instead. No big deal. - this.bubble_.promote_(); - // Since the act of moving this node within the DOM causes a loss of focus, - // we need to reapply the focus. - this.textarea_.focus(); -}; - -/** - * Get the dimensions of this comment's bubble. - * @return {!Object} Object with width and height properties. - */ -Blockly.Comment.prototype.getBubbleSize = function() { - if (this.isVisible()) { - return this.bubble_.getBubbleSize(); - } else { - return {width: this.width_, height: this.height_}; - } -}; - -/** - * Size this comment's bubble. - * @param {number} width Width of the bubble. - * @param {number} height Height of the bubble. - */ -Blockly.Comment.prototype.setBubbleSize = function(width, height) { - if (this.textarea_) { - this.bubble_.setBubbleSize(width, height); - } else { - this.width_ = width; - this.height_ = height; - } -}; - -/** - * Returns this comment's text. - * @return {string} Comment text. - */ -Blockly.Comment.prototype.getText = function() { - return this.textarea_ ? this.textarea_.value : this.text_; -}; - -/** - * Set this comment's text. - * @param {string} text Comment text. - */ -Blockly.Comment.prototype.setText = function(text) { - if (this.text_ != text) { - Blockly.Events.fire(new Blockly.Events.Change( - this.block_, 'comment', null, this.text_, text)); - this.text_ = text; - } - if (this.textarea_) { - this.textarea_.value = text; - } -}; - -/** - * Dispose of this comment. - */ -Blockly.Comment.prototype.dispose = function() { - if (Blockly.Events.isEnabled()) { - this.setText(''); // Fire event to delete comment. - } - this.block_.comment = null; - Blockly.Icon.prototype.dispose.call(this); -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/connection.js b/backend/_pv_1_3_5/static/blockly/core/connection.js deleted file mode 100755 index 3b8c82af8..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/connection.js +++ /dev/null @@ -1,615 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2011 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Components for creating connections between blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Connection'); - -goog.require('goog.asserts'); -goog.require('goog.dom'); - - -/** - * Class for a connection between blocks. - * @param {!Blockly.Block} source The block establishing this connection. - * @param {number} type The type of the connection. - * @constructor - */ -Blockly.Connection = function(source, type) { - /** - * @type {!Blockly.Block} - * @private - */ - this.sourceBlock_ = source; - /** @type {number} */ - this.type = type; - // Shortcut for the databases for this connection's workspace. - if (source.workspace.connectionDBList) { - this.db_ = source.workspace.connectionDBList[type]; - this.dbOpposite_ = - source.workspace.connectionDBList[Blockly.OPPOSITE_TYPE[type]]; - this.hidden_ = !this.db_; - } -}; - -/** - * Constants for checking whether two connections are compatible. - */ -Blockly.Connection.CAN_CONNECT = 0; -Blockly.Connection.REASON_SELF_CONNECTION = 1; -Blockly.Connection.REASON_WRONG_TYPE = 2; -Blockly.Connection.REASON_TARGET_NULL = 3; -Blockly.Connection.REASON_CHECKS_FAILED = 4; -Blockly.Connection.REASON_DIFFERENT_WORKSPACES = 5; -Blockly.Connection.REASON_SHADOW_PARENT = 6; - -/** - * Connection this connection connects to. Null if not connected. - * @type {Blockly.Connection} - */ -Blockly.Connection.prototype.targetConnection = null; - -/** - * List of compatible value types. Null if all types are compatible. - * @type {Array} - * @private - */ -Blockly.Connection.prototype.check_ = null; - -/** - * DOM representation of a shadow block, or null if none. - * @type {Element} - * @private - */ -Blockly.Connection.prototype.shadowDom_ = null; - -/** - * Horizontal location of this connection. - * @type {number} - * @private - */ -Blockly.Connection.prototype.x_ = 0; - -/** - * Vertical location of this connection. - * @type {number} - * @private - */ -Blockly.Connection.prototype.y_ = 0; - -/** - * Has this connection been added to the connection database? - * @type {boolean} - * @private - */ -Blockly.Connection.prototype.inDB_ = false; - -/** - * Connection database for connections of this type on the current workspace. - * @type {Blockly.ConnectionDB} - * @private - */ -Blockly.Connection.prototype.db_ = null; - -/** - * Connection database for connections compatible with this type on the - * current workspace. - * @type {Blockly.ConnectionDB} - * @private - */ -Blockly.Connection.prototype.dbOpposite_ = null; - -/** - * Whether this connections is hidden (not tracked in a database) or not. - * @type {boolean} - * @private - */ -Blockly.Connection.prototype.hidden_ = null; - -/** - * Connect two connections together. This is the connection on the superior - * block. - * @param {!Blockly.Connection} childConnection Connection on inferior block. - * @private - */ -Blockly.Connection.prototype.connect_ = function(childConnection) { - var parentConnection = this; - var parentBlock = parentConnection.getSourceBlock(); - var childBlock = childConnection.getSourceBlock(); - // Disconnect any existing parent on the child connection. - if (childConnection.isConnected()) { - childConnection.disconnect(); - } - if (parentConnection.isConnected()) { - // Other connection is already connected to something. - // Disconnect it and reattach it or bump it as needed. - var orphanBlock = parentConnection.targetBlock(); - var shadowDom = parentConnection.getShadowDom(); - // Temporarily set the shadow DOM to null so it does not respawn. - parentConnection.setShadowDom(null); - // Displaced shadow blocks dissolve rather than reattaching or bumping. - if (orphanBlock.isShadow()) { - // Save the shadow block so that field values are preserved. - shadowDom = Blockly.Xml.blockToDom(orphanBlock); - orphanBlock.dispose(); - orphanBlock = null; - } else if (parentConnection.type == Blockly.INPUT_VALUE) { - // Value connections. - // If female block is already connected, disconnect and bump the male. - if (!orphanBlock.outputConnection) { - throw 'Orphan block does not have an output connection.'; - } - // Attempt to reattach the orphan at the end of the newly inserted - // block. Since this block may be a row, walk down to the end - // or to the first (and only) shadow block. - var connection = Blockly.Connection.lastConnectionInRow_( - childBlock, orphanBlock); - if (connection) { - orphanBlock.outputConnection.connect(connection); - orphanBlock = null; - } - } else if (parentConnection.type == Blockly.NEXT_STATEMENT) { - // Statement connections. - // Statement blocks may be inserted into the middle of a stack. - // Split the stack. - if (!orphanBlock.previousConnection) { - throw 'Orphan block does not have a previous connection.'; - } - // Attempt to reattach the orphan at the bottom of the newly inserted - // block. Since this block may be a stack, walk down to the end. - var newBlock = childBlock; - while (newBlock.nextConnection) { - var nextBlock = newBlock.getNextBlock(); - if (nextBlock && !nextBlock.isShadow()) { - newBlock = nextBlock; - } else { - if (orphanBlock.previousConnection.checkType_( - newBlock.nextConnection)) { - newBlock.nextConnection.connect(orphanBlock.previousConnection); - orphanBlock = null; - } - break; - } - } - } - if (orphanBlock) { - // Unable to reattach orphan. - parentConnection.disconnect(); - if (Blockly.Events.recordUndo) { - // Bump it off to the side after a moment. - var group = Blockly.Events.getGroup(); - setTimeout(function() { - // Verify orphan hasn't been deleted or reconnected (user on meth). - if (orphanBlock.workspace && !orphanBlock.getParent()) { - Blockly.Events.setGroup(group); - if (orphanBlock.outputConnection) { - orphanBlock.outputConnection.bumpAwayFrom_(parentConnection); - } else if (orphanBlock.previousConnection) { - orphanBlock.previousConnection.bumpAwayFrom_(parentConnection); - } - Blockly.Events.setGroup(false); - } - }, Blockly.BUMP_DELAY); - } - } - // Restore the shadow DOM. - parentConnection.setShadowDom(shadowDom); - } - - var event; - if (Blockly.Events.isEnabled()) { - event = new Blockly.Events.Move(childBlock); - } - // Establish the connections. - Blockly.Connection.connectReciprocally_(parentConnection, childConnection); - // Demote the inferior block so that one is a child of the superior one. - childBlock.setParent(parentBlock); - if (event) { - event.recordNew(); - Blockly.Events.fire(event); - } -}; - -/** - * Sever all links to this connection (not including from the source object). - */ -Blockly.Connection.prototype.dispose = function() { - if (this.isConnected()) { - throw 'Disconnect connection before disposing of it.'; - } - if (this.inDB_) { - this.db_.removeConnection_(this); - } - if (Blockly.highlightedConnection_ == this) { - Blockly.highlightedConnection_ = null; - } - if (Blockly.localConnection_ == this) { - Blockly.localConnection_ = null; - } - this.db_ = null; - this.dbOpposite_ = null; -}; - -/** - * Get the source block for this connection. - * @return {Blockly.Block} The source block, or null if there is none. - */ -Blockly.Connection.prototype.getSourceBlock = function() { - return this.sourceBlock_; -}; - -/** - * Does the connection belong to a superior block (higher in the source stack)? - * @return {boolean} True if connection faces down or right. - */ -Blockly.Connection.prototype.isSuperior = function() { - return this.type == Blockly.INPUT_VALUE || - this.type == Blockly.NEXT_STATEMENT; -}; - -/** - * Is the connection connected? - * @return {boolean} True if connection is connected to another connection. - */ -Blockly.Connection.prototype.isConnected = function() { - return !!this.targetConnection; -}; - -/** - * Checks whether the current connection can connect with the target - * connection. - * @param {Blockly.Connection} target Connection to check compatibility with. - * @return {number} Blockly.Connection.CAN_CONNECT if the connection is legal, - * an error code otherwise. - * @private - */ -Blockly.Connection.prototype.canConnectWithReason_ = function(target) { - if (!target) { - return Blockly.Connection.REASON_TARGET_NULL; - } - if (this.isSuperior()) { - var blockA = this.sourceBlock_; - var blockB = target.getSourceBlock(); - } else { - var blockB = this.sourceBlock_; - var blockA = target.getSourceBlock(); - } - if (blockA && blockA == blockB) { - return Blockly.Connection.REASON_SELF_CONNECTION; - } else if (target.type != Blockly.OPPOSITE_TYPE[this.type]) { - return Blockly.Connection.REASON_WRONG_TYPE; - } else if (blockA && blockB && blockA.workspace !== blockB.workspace) { - return Blockly.Connection.REASON_DIFFERENT_WORKSPACES; - } else if (!this.checkType_(target)) { - return Blockly.Connection.REASON_CHECKS_FAILED; - } else if (blockA.isShadow() && !blockB.isShadow()) { - return Blockly.Connection.REASON_SHADOW_PARENT; - } - return Blockly.Connection.CAN_CONNECT; -}; - -/** - * Checks whether the current connection and target connection are compatible - * and throws an exception if they are not. - * @param {Blockly.Connection} target The connection to check compatibility - * with. - * @private - */ -Blockly.Connection.prototype.checkConnection_ = function(target) { - switch (this.canConnectWithReason_(target)) { - case Blockly.Connection.CAN_CONNECT: - break; - case Blockly.Connection.REASON_SELF_CONNECTION: - throw 'Attempted to connect a block to itself.'; - case Blockly.Connection.REASON_DIFFERENT_WORKSPACES: - // Usually this means one block has been deleted. - throw 'Blocks not on same workspace.'; - case Blockly.Connection.REASON_WRONG_TYPE: - throw 'Attempt to connect incompatible types.'; - case Blockly.Connection.REASON_TARGET_NULL: - throw 'Target connection is null.'; - case Blockly.Connection.REASON_CHECKS_FAILED: - throw 'Connection checks failed.'; - case Blockly.Connection.REASON_SHADOW_PARENT: - throw 'Connecting non-shadow to shadow block.'; - default: - throw 'Unknown connection failure: this should never happen!'; - } -}; - -/** - * Check if the two connections can be dragged to connect to each other. - * @param {!Blockly.Connection} candidate A nearby connection to check. - * @return {boolean} True if the connection is allowed, false otherwise. - */ -Blockly.Connection.prototype.isConnectionAllowed = function(candidate) { - // Type checking. - var canConnect = this.canConnectWithReason_(candidate); - if (canConnect != Blockly.Connection.CAN_CONNECT) { - return false; - } - - // Don't offer to connect an already connected left (male) value plug to - // an available right (female) value plug. Don't offer to connect the - // bottom of a statement block to one that's already connected. - if (candidate.type == Blockly.OUTPUT_VALUE || - candidate.type == Blockly.PREVIOUS_STATEMENT) { - if (candidate.isConnected() || this.isConnected()) { - return false; - } - } - - // Offering to connect the left (male) of a value block to an already - // connected value pair is ok, we'll splice it in. - // However, don't offer to splice into an immovable block. - if (candidate.type == Blockly.INPUT_VALUE && candidate.isConnected() && - !candidate.targetBlock().isMovable() && - !candidate.targetBlock().isShadow()) { - return false; - } - - // Don't let a block with no next connection bump other blocks out of the - // stack. But covering up a shadow block or stack of shadow blocks is fine. - // Similarly, replacing a terminal statement with another terminal statement - // is allowed. - if (this.type == Blockly.PREVIOUS_STATEMENT && - candidate.isConnected() && - !this.sourceBlock_.nextConnection && - !candidate.targetBlock().isShadow() && - candidate.targetBlock().nextConnection) { - return false; - } - - // Don't let blocks try to connect to themselves or ones they nest. - if (Blockly.draggingConnections_.indexOf(candidate) != -1) { - return false; - } - - return true; -}; - -/** - * Connect this connection to another connection. - * @param {!Blockly.Connection} otherConnection Connection to connect to. - */ -Blockly.Connection.prototype.connect = function(otherConnection) { - if (this.targetConnection == otherConnection) { - // Already connected together. NOP. - return; - } - this.checkConnection_(otherConnection); - // Determine which block is superior (higher in the source stack). - if (this.isSuperior()) { - // Superior block. - this.connect_(otherConnection); - } else { - // Inferior block. - otherConnection.connect_(this); - } -}; - -/** - * Update two connections to target each other. - * @param {Blockly.Connection} first The first connection to update. - * @param {Blockly.Connection} second The second conneciton to update. - * @private - */ -Blockly.Connection.connectReciprocally_ = function(first, second) { - goog.asserts.assert(first && second, 'Cannot connect null connections.'); - first.targetConnection = second; - second.targetConnection = first; -}; - -/** - * Does the given block have one and only one connection point that will accept - * an orphaned block? - * @param {!Blockly.Block} block The superior block. - * @param {!Blockly.Block} orphanBlock The inferior block. - * @return {Blockly.Connection} The suitable connection point on 'block', - * or null. - * @private - */ -Blockly.Connection.singleConnection_ = function(block, orphanBlock) { - var connection = false; - for (var i = 0; i < block.inputList.length; i++) { - var thisConnection = block.inputList[i].connection; - if (thisConnection && thisConnection.type == Blockly.INPUT_VALUE && - orphanBlock.outputConnection.checkType_(thisConnection)) { - if (connection) { - return null; // More than one connection. - } - connection = thisConnection; - } - } - return connection; -}; - -/** - * Walks down a row a blocks, at each stage checking if there are any - * connections that will accept the orphaned block. If at any point there - * are zero or multiple eligible connections, returns null. Otherwise - * returns the only input on the last block in the chain. - * Terminates early for shadow blocks. - * @param {!Blockly.Block} startBlock The block on which to start the search. - * @param {!Blockly.Block} orphanBlock The block that is looking for a home. - * @return {Blockly.Connection} The suitable connection point on the chain - * of blocks, or null. - * @private - */ -Blockly.Connection.lastConnectionInRow_ = function(startBlock, orphanBlock) { - var newBlock = startBlock; - var connection; - while (connection = Blockly.Connection.singleConnection_( - /** @type {!Blockly.Block} */ (newBlock), orphanBlock)) { - // '=' is intentional in line above. - newBlock = connection.targetBlock(); - if (!newBlock || newBlock.isShadow()) { - return connection; - } - } - return null; -}; - -/** - * Disconnect this connection. - */ -Blockly.Connection.prototype.disconnect = function() { - var otherConnection = this.targetConnection; - goog.asserts.assert(otherConnection, 'Source connection not connected.'); - goog.asserts.assert(otherConnection.targetConnection == this, - 'Target connection not connected to source connection.'); - - var parentBlock, childBlock, parentConnection; - if (this.isSuperior()) { - // Superior block. - parentBlock = this.sourceBlock_; - childBlock = otherConnection.getSourceBlock(); - parentConnection = this; - } else { - // Inferior block. - parentBlock = otherConnection.getSourceBlock(); - childBlock = this.sourceBlock_; - parentConnection = otherConnection; - } - this.disconnectInternal_(parentBlock, childBlock); - parentConnection.respawnShadow_(); -}; - -/** - * Disconnect two blocks that are connected by this connection. - * @param {!Blockly.Block} parentBlock The superior block. - * @param {!Blockly.Block} childBlock The inferior block. - * @private - */ -Blockly.Connection.prototype.disconnectInternal_ = function(parentBlock, - childBlock) { - var event; - if (Blockly.Events.isEnabled()) { - event = new Blockly.Events.Move(childBlock); - } - var otherConnection = this.targetConnection; - otherConnection.targetConnection = null; - this.targetConnection = null; - childBlock.setParent(null); - if (event) { - event.recordNew(); - Blockly.Events.fire(event); - } -}; - -/** - * Respawn the shadow block if there was one connected to the this connection. - * @private - */ -Blockly.Connection.prototype.respawnShadow_ = function() { - var parentBlock = this.getSourceBlock(); - var shadow = this.getShadowDom(); - if (parentBlock.workspace && shadow && Blockly.Events.recordUndo) { - var blockShadow = - Blockly.Xml.domToBlock(shadow, parentBlock.workspace); - if (blockShadow.outputConnection) { - this.connect(blockShadow.outputConnection); - } else if (blockShadow.previousConnection) { - this.connect(blockShadow.previousConnection); - } else { - throw 'Child block does not have output or previous statement.'; - } - } -}; - -/** - * Returns the block that this connection connects to. - * @return {Blockly.Block} The connected block or null if none is connected. - */ -Blockly.Connection.prototype.targetBlock = function() { - if (this.isConnected()) { - return this.targetConnection.getSourceBlock(); - } - return null; -}; - -/** - * Is this connection compatible with another connection with respect to the - * value type system. E.g. square_root("Hello") is not compatible. - * @param {!Blockly.Connection} otherConnection Connection to compare against. - * @return {boolean} True if the connections share a type. - * @private - */ -Blockly.Connection.prototype.checkType_ = function(otherConnection) { - if (!this.check_ || !otherConnection.check_) { - // One or both sides are promiscuous enough that anything will fit. - return true; - } - // Find any intersection in the check lists. - for (var i = 0; i < this.check_.length; i++) { - if (otherConnection.check_.indexOf(this.check_[i]) != -1) { - return true; - } - } - // No intersection. - return false; -}; - -/** - * Change a connection's compatibility. - * @param {*} check Compatible value type or list of value types. - * Null if all types are compatible. - * @return {!Blockly.Connection} The connection being modified - * (to allow chaining). - */ -Blockly.Connection.prototype.setCheck = function(check) { - if (check) { - // Ensure that check is in an array. - if (!goog.isArray(check)) { - check = [check]; - } - this.check_ = check; - // The new value type may not be compatible with the existing connection. - if (this.isConnected() && !this.checkType_(this.targetConnection)) { - var child = this.isSuperior() ? this.targetBlock() : this.sourceBlock_; - child.unplug(); - // Bump away. - this.sourceBlock_.bumpNeighbours_(); - } - } else { - this.check_ = null; - } - return this; -}; - -/** - * Change a connection's shadow block. - * @param {Element} shadow DOM representation of a block or null. - */ -Blockly.Connection.prototype.setShadowDom = function(shadow) { - this.shadowDom_ = shadow; -}; - -/** - * Return a connection's shadow block. - * @return {Element} shadow DOM representation of a block or null. - */ -Blockly.Connection.prototype.getShadowDom = function() { - return this.shadowDom_; -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/connection_db.js b/backend/_pv_1_3_5/static/blockly/core/connection_db.js deleted file mode 100755 index 8b3c3008e..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/connection_db.js +++ /dev/null @@ -1,301 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2011 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Components for managing connections between blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.ConnectionDB'); - -goog.require('Blockly.Connection'); - - -/** - * Database of connections. - * Connections are stored in order of their vertical component. This way - * connections in an area may be looked up quickly using a binary search. - * @constructor - */ -Blockly.ConnectionDB = function() { -}; - -Blockly.ConnectionDB.prototype = new Array(); -/** - * Don't inherit the constructor from Array. - * @type {!Function} - */ -Blockly.ConnectionDB.constructor = Blockly.ConnectionDB; - -/** - * Add a connection to the database. Must not already exist in DB. - * @param {!Blockly.Connection} connection The connection to be added. - */ -Blockly.ConnectionDB.prototype.addConnection = function(connection) { - if (connection.inDB_) { - throw 'Connection already in database.'; - } - if (connection.getSourceBlock().isInFlyout) { - // Don't bother maintaining a database of connections in a flyout. - return; - } - var position = this.findPositionForConnection_(connection); - this.splice(position, 0, connection); - connection.inDB_ = true; -}; - -/** - * Find the given connection. - * Starts by doing a binary search to find the approximate location, then - * linearly searches nearby for the exact connection. - * @param {!Blockly.Connection} conn The connection to find. - * @return {number} The index of the connection, or -1 if the connection was - * not found. - */ -Blockly.ConnectionDB.prototype.findConnection = function(conn) { - if (!this.length) { - return -1; - } - - var bestGuess = this.findPositionForConnection_(conn); - if (bestGuess >= this.length) { - // Not in list - return -1; - } - - var yPos = conn.y_; - // Walk forward and back on the y axis looking for the connection. - var pointerMin = bestGuess; - var pointerMax = bestGuess; - while (pointerMin >= 0 && this[pointerMin].y_ == yPos) { - if (this[pointerMin] == conn) { - return pointerMin; - } - pointerMin--; - } - - while (pointerMax < this.length && this[pointerMax].y_ == yPos) { - if (this[pointerMax] == conn) { - return pointerMax; - } - pointerMax++; - } - return -1; -}; - -/** - * Finds a candidate position for inserting this connection into the list. - * This will be in the correct y order but makes no guarantees about ordering in - * the x axis. - * @param {!Blockly.Connection} connection The connection to insert. - * @return {number} The candidate index. - * @private - */ -Blockly.ConnectionDB.prototype.findPositionForConnection_ = - function(connection) { - /* eslint-disable indent */ - if (!this.length) { - return 0; - } - var pointerMin = 0; - var pointerMax = this.length; - while (pointerMin < pointerMax) { - var pointerMid = Math.floor((pointerMin + pointerMax) / 2); - if (this[pointerMid].y_ < connection.y_) { - pointerMin = pointerMid + 1; - } else if (this[pointerMid].y_ > connection.y_) { - pointerMax = pointerMid; - } else { - pointerMin = pointerMid; - break; - } - } - return pointerMin; -}; /* eslint-enable indent */ - -/** - * Remove a connection from the database. Must already exist in DB. - * @param {!Blockly.Connection} connection The connection to be removed. - * @private - */ -Blockly.ConnectionDB.prototype.removeConnection_ = function(connection) { - if (!connection.inDB_) { - throw 'Connection not in database.'; - } - var removalIndex = this.findConnection(connection); - if (removalIndex == -1) { - throw 'Unable to find connection in connectionDB.'; - } - connection.inDB_ = false; - this.splice(removalIndex, 1); -}; - -/** - * Find all nearby connections to the given connection. - * Type checking does not apply, since this function is used for bumping. - * @param {!Blockly.Connection} connection The connection whose neighbours - * should be returned. - * @param {number} maxRadius The maximum radius to another connection. - * @return {!Array.} List of connections. - */ -Blockly.ConnectionDB.prototype.getNeighbours = function(connection, maxRadius) { - var db = this; - var currentX = connection.x_; - var currentY = connection.y_; - - // Binary search to find the closest y location. - var pointerMin = 0; - var pointerMax = db.length - 2; - var pointerMid = pointerMax; - while (pointerMin < pointerMid) { - if (db[pointerMid].y_ < currentY) { - pointerMin = pointerMid; - } else { - pointerMax = pointerMid; - } - pointerMid = Math.floor((pointerMin + pointerMax) / 2); - } - - var neighbours = []; - /** - * Computes if the current connection is within the allowed radius of another - * connection. - * This function is a closure and has access to outside variables. - * @param {number} yIndex The other connection's index in the database. - * @return {boolean} True if the current connection's vertical distance from - * the other connection is less than the allowed radius. - */ - function checkConnection_(yIndex) { - var dx = currentX - db[yIndex].x_; - var dy = currentY - db[yIndex].y_; - var r = Math.sqrt(dx * dx + dy * dy); - if (r <= maxRadius) { - neighbours.push(db[yIndex]); - } - return dy < maxRadius; - } - - // Walk forward and back on the y axis looking for the closest x,y point. - pointerMin = pointerMid; - pointerMax = pointerMid; - if (db.length) { - while (pointerMin >= 0 && checkConnection_(pointerMin)) { - pointerMin--; - } - do { - pointerMax++; - } while (pointerMax < db.length && checkConnection_(pointerMax)); - } - - return neighbours; -}; - - -/** - * Is the candidate connection close to the reference connection. - * Extremely fast; only looks at Y distance. - * @param {number} index Index in database of candidate connection. - * @param {number} baseY Reference connection's Y value. - * @param {number} maxRadius The maximum radius to another connection. - * @return {boolean} True if connection is in range. - * @private - */ -Blockly.ConnectionDB.prototype.isInYRange_ = function(index, baseY, maxRadius) { - return (Math.abs(this[index].y_ - baseY) <= maxRadius); -}; - -/** - * Find the closest compatible connection to this connection. - * @param {!Blockly.Connection} conn The connection searching for a compatible - * mate. - * @param {number} maxRadius The maximum radius to another connection. - * @param {!goog.math.Coordinate} dxy Offset between this connection's location - * in the database and the current location (as a result of dragging). - * @return {!{connection: ?Blockly.Connection, radius: number}} Contains two - * properties:' connection' which is either another connection or null, - * and 'radius' which is the distance. - */ -Blockly.ConnectionDB.prototype.searchForClosest = function(conn, maxRadius, - dxy) { - // Don't bother. - if (!this.length) { - return {connection: null, radius: maxRadius}; - } - - // Stash the values of x and y from before the drag. - var baseY = conn.y_; - var baseX = conn.x_; - - conn.x_ = baseX + dxy.x; - conn.y_ = baseY + dxy.y; - - // findPositionForConnection finds an index for insertion, which is always - // after any block with the same y index. We want to search both forward - // and back, so search on both sides of the index. - var closestIndex = this.findPositionForConnection_(conn); - - var bestConnection = null; - var bestRadius = maxRadius; - var temp; - - // Walk forward and back on the y axis looking for the closest x,y point. - var pointerMin = closestIndex - 1; - while (pointerMin >= 0 && this.isInYRange_(pointerMin, conn.y_, maxRadius)) { - temp = this[pointerMin]; - if (conn.isConnectionAllowed(temp, bestRadius)) { - bestConnection = temp; - bestRadius = temp.distanceFrom(conn); - } - pointerMin--; - } - - var pointerMax = closestIndex; - while (pointerMax < this.length && this.isInYRange_(pointerMax, conn.y_, - maxRadius)) { - temp = this[pointerMax]; - if (conn.isConnectionAllowed(temp, bestRadius)) { - bestConnection = temp; - bestRadius = temp.distanceFrom(conn); - } - pointerMax++; - } - - // Reset the values of x and y. - conn.x_ = baseX; - conn.y_ = baseY; - - // If there were no valid connections, bestConnection will be null. - return {connection: bestConnection, radius: bestRadius}; -}; - -/** - * Initialize a set of connection DBs for a specified workspace. - * @param {!Blockly.Workspace} workspace The workspace this DB is for. - */ -Blockly.ConnectionDB.init = function(workspace) { - // Create four databases, one for each connection type. - var dbList = []; - dbList[Blockly.INPUT_VALUE] = new Blockly.ConnectionDB(); - dbList[Blockly.OUTPUT_VALUE] = new Blockly.ConnectionDB(); - dbList[Blockly.NEXT_STATEMENT] = new Blockly.ConnectionDB(); - dbList[Blockly.PREVIOUS_STATEMENT] = new Blockly.ConnectionDB(); - workspace.connectionDBList = dbList; -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/constants.js b/backend/_pv_1_3_5/static/blockly/core/constants.js deleted file mode 100755 index 0f327e2d9..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/constants.js +++ /dev/null @@ -1,202 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Blockly constants. - * @author fenichel@google.com (Rachel Fenichel) - */ -'use strict'; - -goog.provide('Blockly.constants'); - - -/** - * Number of pixels the mouse must move before a drag starts. - */ -Blockly.DRAG_RADIUS = 5; - -/** - * Maximum misalignment between connections for them to snap together. - */ -Blockly.SNAP_RADIUS = 20; - -/** - * Delay in ms between trigger and bumping unconnected block out of alignment. - */ -Blockly.BUMP_DELAY = 250; - -/** - * Number of characters to truncate a collapsed block to. - */ -Blockly.COLLAPSE_CHARS = 30; - -/** - * Length in ms for a touch to become a long press. - */ -Blockly.LONGPRESS = 750; - -/** - * Prevent a sound from playing if another sound preceded it within this many - * miliseconds. - */ -Blockly.SOUND_LIMIT = 100; - -/** - * The richness of block colours, regardless of the hue. - * Must be in the range of 0 (inclusive) to 1 (exclusive). - */ -Blockly.HSV_SATURATION = 0.45; - -/** - * The intensity of block colours, regardless of the hue. - * Must be in the range of 0 (inclusive) to 1 (exclusive). - */ -Blockly.HSV_VALUE = 0.65; - -/** - * Sprited icons and images. - */ -Blockly.SPRITE = { - width: 96, - height: 124, - url: 'sprites.png' -}; - -// Constants below this point are not intended to be changed. - -/** - * Required name space for SVG elements. - * @const - */ -Blockly.SVG_NS = 'http://www.w3.org/2000/svg'; - -/** - * Required name space for HTML elements. - * @const - */ -Blockly.HTML_NS = 'http://www.w3.org/1999/xhtml'; - -/** - * ENUM for a right-facing value input. E.g. 'set item to' or 'return'. - * @const - */ -Blockly.INPUT_VALUE = 1; - -/** - * ENUM for a left-facing value output. E.g. 'random fraction'. - * @const - */ -Blockly.OUTPUT_VALUE = 2; - -/** - * ENUM for a down-facing block stack. E.g. 'if-do' or 'else'. - * @const - */ -Blockly.NEXT_STATEMENT = 3; - -/** - * ENUM for an up-facing block stack. E.g. 'break out of loop'. - * @const - */ -Blockly.PREVIOUS_STATEMENT = 4; - -/** - * ENUM for an dummy input. Used to add field(s) with no input. - * @const - */ -Blockly.DUMMY_INPUT = 5; - -/** - * ENUM for left alignment. - * @const - */ -Blockly.ALIGN_LEFT = -1; - -/** - * ENUM for centre alignment. - * @const - */ -Blockly.ALIGN_CENTRE = 0; - -/** - * ENUM for right alignment. - * @const - */ -Blockly.ALIGN_RIGHT = 1; - -/** - * ENUM for no drag operation. - * @const - */ -Blockly.DRAG_NONE = 0; - -/** - * ENUM for inside the sticky DRAG_RADIUS. - * @const - */ -Blockly.DRAG_STICKY = 1; - -/** - * ENUM for inside the non-sticky DRAG_RADIUS, for differentiating between - * clicks and drags. - * @const - */ -Blockly.DRAG_BEGIN = 1; - -/** - * ENUM for freely draggable (outside the DRAG_RADIUS, if one applies). - * @const - */ -Blockly.DRAG_FREE = 2; - -/** - * Lookup table for determining the opposite type of a connection. - * @const - */ -Blockly.OPPOSITE_TYPE = []; -Blockly.OPPOSITE_TYPE[Blockly.INPUT_VALUE] = Blockly.OUTPUT_VALUE; -Blockly.OPPOSITE_TYPE[Blockly.OUTPUT_VALUE] = Blockly.INPUT_VALUE; -Blockly.OPPOSITE_TYPE[Blockly.NEXT_STATEMENT] = Blockly.PREVIOUS_STATEMENT; -Blockly.OPPOSITE_TYPE[Blockly.PREVIOUS_STATEMENT] = Blockly.NEXT_STATEMENT; - - -/** - * ENUM for toolbox and flyout at top of screen. - * @const - */ -Blockly.TOOLBOX_AT_TOP = 0; - -/** - * ENUM for toolbox and flyout at bottom of screen. - * @const - */ -Blockly.TOOLBOX_AT_BOTTOM = 1; - -/** - * ENUM for toolbox and flyout at left of screen. - * @const - */ -Blockly.TOOLBOX_AT_LEFT = 2; - -/** - * ENUM for toolbox and flyout at right of screen. - * @const - */ -Blockly.TOOLBOX_AT_RIGHT = 3; diff --git a/backend/_pv_1_3_5/static/blockly/core/contextmenu.js b/backend/_pv_1_3_5/static/blockly/core/contextmenu.js deleted file mode 100755 index 462ad0b2c..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/contextmenu.js +++ /dev/null @@ -1,148 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2011 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Functionality for the right-click context menus. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.ContextMenu'); - -goog.require('goog.dom'); -goog.require('goog.events'); -goog.require('goog.style'); -goog.require('goog.ui.Menu'); -goog.require('goog.ui.MenuItem'); - - -/** - * Which block is the context menu attached to? - * @type {Blockly.Block} - */ -Blockly.ContextMenu.currentBlock = null; - -/** - * Construct the menu based on the list of options and show the menu. - * @param {!Event} e Mouse event. - * @param {!Array.} options Array of menu options. - * @param {boolean} rtl True if RTL, false if LTR. - */ -Blockly.ContextMenu.show = function(e, options, rtl) { - Blockly.WidgetDiv.show(Blockly.ContextMenu, rtl, null); - if (!options.length) { - Blockly.ContextMenu.hide(); - return; - } - /* Here's what one option object looks like: - {text: 'Make It So', - enabled: true, - callback: Blockly.MakeItSo} - */ - var menu = new goog.ui.Menu(); - menu.setRightToLeft(rtl); - for (var i = 0, option; option = options[i]; i++) { - var menuItem = new goog.ui.MenuItem(option.text); - menuItem.setRightToLeft(rtl); - menu.addChild(menuItem, true); - menuItem.setEnabled(option.enabled); - if (option.enabled) { - goog.events.listen(menuItem, goog.ui.Component.EventType.ACTION, - option.callback); - } - } - goog.events.listen(menu, goog.ui.Component.EventType.ACTION, - Blockly.ContextMenu.hide); - // Record windowSize and scrollOffset before adding menu. - var windowSize = goog.dom.getViewportSize(); - var scrollOffset = goog.style.getViewportPageOffset(document); - var div = Blockly.WidgetDiv.DIV; - menu.render(div); - var menuDom = menu.getElement(); - Blockly.addClass_(menuDom, 'blocklyContextMenu'); - // Prevent system context menu when right-clicking a Blockly context menu. - Blockly.bindEvent_(menuDom, 'contextmenu', null, Blockly.noEvent); - // Record menuSize after adding menu. - var menuSize = goog.style.getSize(menuDom); - - // Position the menu. - var x = e.clientX + scrollOffset.x; - var y = e.clientY + scrollOffset.y; - // Flip menu vertically if off the bottom. - if (e.clientY + menuSize.height >= windowSize.height) { - y -= menuSize.height; - } - // Flip menu horizontally if off the edge. - if (rtl) { - if (menuSize.width >= e.clientX) { - x += menuSize.width; - } - } else { - if (e.clientX + menuSize.width >= windowSize.width) { - x -= menuSize.width; - } - } - Blockly.WidgetDiv.position(x, y, windowSize, scrollOffset, rtl); - - menu.setAllowAutoFocus(true); - // 1ms delay is required for focusing on context menus because some other - // mouse event is still waiting in the queue and clears focus. - setTimeout(function() {menuDom.focus();}, 1); - Blockly.ContextMenu.currentBlock = null; // May be set by Blockly.Block. -}; - -/** - * Hide the context menu. - */ -Blockly.ContextMenu.hide = function() { - Blockly.WidgetDiv.hideIfOwner(Blockly.ContextMenu); - Blockly.ContextMenu.currentBlock = null; -}; - -/** - * Create a callback function that creates and configures a block, - * then places the new block next to the original. - * @param {!Blockly.Block} block Original block. - * @param {!Element} xml XML representation of new block. - * @return {!Function} Function that creates a block. - */ -Blockly.ContextMenu.callbackFactory = function(block, xml) { - return function() { - Blockly.Events.disable(); - try { - var newBlock = Blockly.Xml.domToBlock(xml, block.workspace); - // Move the new block next to the old block. - var xy = block.getRelativeToSurfaceXY(); - if (block.RTL) { - xy.x -= Blockly.SNAP_RADIUS; - } else { - xy.x += Blockly.SNAP_RADIUS; - } - xy.y += Blockly.SNAP_RADIUS * 2; - newBlock.moveBy(xy.x, xy.y); - } finally { - Blockly.Events.enable(); - } - if (Blockly.Events.isEnabled() && !newBlock.isShadow()) { - Blockly.Events.fire(new Blockly.Events.Create(newBlock)); - } - newBlock.select(); - }; -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/css.js b/backend/_pv_1_3_5/static/blockly/core/css.js deleted file mode 100755 index c45ccc907..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/css.js +++ /dev/null @@ -1,782 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2013 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Inject Blockly's CSS synchronously. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Css'); - - -/** - * List of cursors. - * @enum {string} - */ -Blockly.Css.Cursor = { - OPEN: 'handopen', - CLOSED: 'handclosed', - DELETE: 'handdelete' -}; - -/** - * Current cursor (cached value). - * @type {string} - * @private - */ -Blockly.Css.currentCursor_ = ''; - -/** - * Large stylesheet added by Blockly.Css.inject. - * @type {Element} - * @private - */ -Blockly.Css.styleSheet_ = null; - -/** - * Path to media directory, with any trailing slash removed. - * @type {string} - * @private - */ -Blockly.Css.mediaPath_ = ''; - -/** - * Inject the CSS into the DOM. This is preferable over using a regular CSS - * file since: - * a) It loads synchronously and doesn't force a redraw later. - * b) It speeds up loading by not blocking on a separate HTTP transfer. - * c) The CSS content may be made dynamic depending on init options. - * @param {boolean} hasCss If false, don't inject CSS - * (providing CSS becomes the document's responsibility). - * @param {string} pathToMedia Path from page to the Blockly media directory. - */ -Blockly.Css.inject = function(hasCss, pathToMedia) { - // Only inject the CSS once. - if (Blockly.Css.styleSheet_) { - return; - } - // Placeholder for cursor rule. Must be first rule (index 0). - var text = '.blocklyDraggable {}\n'; - if (hasCss) { - text += Blockly.Css.CONTENT.join('\n'); - if (Blockly.FieldDate) { - text += Blockly.FieldDate.CSS.join('\n'); - } - } - // Strip off any trailing slash (either Unix or Windows). - Blockly.Css.mediaPath_ = pathToMedia.replace(/[\\\/]$/, ''); - text = text.replace(/<<>>/g, Blockly.Css.mediaPath_); - // Inject CSS tag. - var cssNode = document.createElement('style'); - document.head.appendChild(cssNode); - var cssTextNode = document.createTextNode(text); - cssNode.appendChild(cssTextNode); - Blockly.Css.styleSheet_ = cssNode.sheet; - Blockly.Css.setCursor(Blockly.Css.Cursor.OPEN); -}; - -/** - * Set the cursor to be displayed when over something draggable. - * @param {Blockly.Css.Cursor} cursor Enum. - */ -Blockly.Css.setCursor = function(cursor) { - if (Blockly.Css.currentCursor_ == cursor) { - return; - } - Blockly.Css.currentCursor_ = cursor; - var url = 'url(' + Blockly.Css.mediaPath_ + '/' + cursor + '.cur), auto'; - // There are potentially hundreds of draggable objects. Changing their style - // properties individually is too slow, so change the CSS rule instead. - var rule = '.blocklyDraggable {\n cursor: ' + url + ';\n}\n'; - Blockly.Css.styleSheet_.deleteRule(0); - Blockly.Css.styleSheet_.insertRule(rule, 0); - // There is probably only one toolbox, so just change its style property. - var toolboxen = document.getElementsByClassName('blocklyToolboxDiv'); - for (var i = 0, toolbox; toolbox = toolboxen[i]; i++) { - if (cursor == Blockly.Css.Cursor.DELETE) { - toolbox.style.cursor = url; - } else { - toolbox.style.cursor = ''; - } - } - // Set cursor on the whole document, so that rapid movements - // don't result in cursor changing to an arrow momentarily. - var html = document.body.parentNode; - if (cursor == Blockly.Css.Cursor.OPEN) { - html.style.cursor = ''; - } else { - html.style.cursor = url; - } -}; - -/** - * Array making up the CSS content for Blockly. - */ -Blockly.Css.CONTENT = [ - '.blocklySvg {', - 'background-color: #fff;', - 'outline: none;', - 'overflow: hidden;', /* IE overflows by default. */ - 'display: block;', - '}', - - '.blocklyWidgetDiv {', - 'display: none;', - 'position: absolute;', - 'z-index: 99999;', /* big value for bootstrap3 compatibility */ - '}', - - '.injectionDiv {', - 'height: 100%;', - 'position: relative;', - '}', - - '.blocklyNonSelectable {', - 'user-select: none;', - '-moz-user-select: none;', - '-webkit-user-select: none;', - '-ms-user-select: none;', - '}', - - '.blocklyTooltipDiv {', - 'background-color: #ffffc7;', - 'border: 1px solid #ddc;', - 'box-shadow: 4px 4px 20px 1px rgba(0,0,0,.15);', - 'color: #000;', - 'display: none;', - 'font-family: sans-serif;', - 'font-size: 9pt;', - 'opacity: 0.9;', - 'padding: 2px;', - 'position: absolute;', - 'z-index: 100000;', /* big value for bootstrap3 compatibility */ - '}', - - '.blocklyResizeSE {', - 'cursor: se-resize;', - 'fill: #aaa;', - '}', - - '.blocklyResizeSW {', - 'cursor: sw-resize;', - 'fill: #aaa;', - '}', - - '.blocklyResizeLine {', - 'stroke: #888;', - 'stroke-width: 1;', - '}', - - '.blocklyHighlightedConnectionPath {', - 'fill: none;', - 'stroke: #fc3;', - 'stroke-width: 4px;', - '}', - - '.blocklyPathLight {', - 'fill: none;', - 'stroke-linecap: round;', - 'stroke-width: 1;', - '}', - - '.blocklySelected>.blocklyPath {', - 'stroke: #fc3;', - 'stroke-width: 3px;', - '}', - - '.blocklySelected>.blocklyPathLight {', - 'display: none;', - '}', - - '.blocklyDragging>.blocklyPath,', - '.blocklyDragging>.blocklyPathLight {', - 'fill-opacity: .8;', - 'stroke-opacity: .8;', - '}', - - '.blocklyDragging>.blocklyPathDark {', - 'display: none;', - '}', - - '.blocklyDisabled>.blocklyPath {', - 'fill-opacity: .5;', - 'stroke-opacity: .5;', - '}', - - '.blocklyDisabled>.blocklyPathLight,', - '.blocklyDisabled>.blocklyPathDark {', - 'display: none;', - '}', - - '.blocklyText {', - 'cursor: default;', - 'fill: #fff;', - 'font-family: sans-serif;', - 'font-size: 11pt;', - '}', - - '.blocklyNonEditableText>text {', - 'pointer-events: none;', - '}', - - '.blocklyNonEditableText>rect,', - '.blocklyEditableText>rect {', - 'fill: #fff;', - 'fill-opacity: .6;', - '}', - - '.blocklyNonEditableText>text,', - '.blocklyEditableText>text {', - 'fill: #000;', - '}', - - '.blocklyEditableText:hover>rect {', - 'stroke: #fff;', - 'stroke-width: 2;', - '}', - - '.blocklyBubbleText {', - 'fill: #000;', - '}', - - '.blocklyFlyoutButton {', - 'fill: #888;', - 'cursor: default', - '}', - - '.blocklyFlyoutButton:hover {', - 'fill: #ccc;', - '}', - - /* - Don't allow users to select text. It gets annoying when trying to - drag a block and selected text moves instead. - */ - '.blocklySvg text {', - 'user-select: none;', - '-moz-user-select: none;', - '-webkit-user-select: none;', - 'cursor: inherit;', - '}', - - '.blocklyHidden {', - 'display: none;', - '}', - - '.blocklyFieldDropdown:not(.blocklyHidden) {', - 'display: block;', - '}', - - '.blocklyIconGroup {', - 'cursor: default;', - '}', - - '.blocklyIconGroup:not(:hover),', - '.blocklyIconGroupReadonly {', - 'opacity: .6;', - '}', - - '.blocklyIconShape {', - 'fill: #00f;', - 'stroke: #fff;', - 'stroke-width: 1px;', - '}', - - '.blocklyIconSymbol {', - 'fill: #fff;', - '}', - - '.blocklyMinimalBody {', - 'margin: 0;', - 'padding: 0;', - '}', - - '.blocklyCommentTextarea {', - 'background-color: #ffc;', - 'border: 0;', - 'margin: 0;', - 'padding: 2px;', - 'resize: none;', - '}', - - '.blocklyHtmlInput {', - 'border: none;', - 'border-radius: 4px;', - 'font-family: sans-serif;', - 'height: 100%;', - 'margin: 0;', - 'outline: none;', - 'padding: 0 1px;', - 'width: 100%', - '}', - - '.blocklyMainBackground {', - 'stroke-width: 1;', - 'stroke: #c6c6c6;', /* Equates to #ddd due to border being off-pixel. */ - '}', - - '.blocklyMutatorBackground {', - 'fill: #fff;', - 'stroke: #ddd;', - 'stroke-width: 1;', - '}', - - '.blocklyFlyoutBackground {', - 'fill: #ddd;', - 'fill-opacity: .8;', - '}', - - '.blocklyScrollbarBackground {', - 'opacity: 0;', - '}', - - '.blocklyScrollbarHandle {', - 'fill: #ccc;', - '}', - - '.blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,', - '.blocklyScrollbarHandle:hover {', - 'fill: #bbb;', - '}', - - '.blocklyZoom>image {', - 'opacity: .4;', - '}', - - '.blocklyZoom>image:hover {', - 'opacity: .6;', - '}', - - '.blocklyZoom>image:active {', - 'opacity: .8;', - '}', - - /* Darken flyout scrollbars due to being on a grey background. */ - /* By contrast, workspace scrollbars are on a white background. */ - '.blocklyFlyout .blocklyScrollbarHandle {', - 'fill: #bbb;', - '}', - - '.blocklyFlyout .blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,', - '.blocklyFlyout .blocklyScrollbarHandle:hover {', - 'fill: #aaa;', - '}', - - '.blocklyInvalidInput {', - 'background: #faa;', - '}', - - '.blocklyAngleCircle {', - 'stroke: #444;', - 'stroke-width: 1;', - 'fill: #ddd;', - 'fill-opacity: .8;', - '}', - - '.blocklyAngleMarks {', - 'stroke: #444;', - 'stroke-width: 1;', - '}', - - '.blocklyAngleGauge {', - 'fill: #f88;', - 'fill-opacity: .8;', - '}', - - '.blocklyAngleLine {', - 'stroke: #f00;', - 'stroke-width: 2;', - 'stroke-linecap: round;', - '}', - - '.blocklyContextMenu {', - 'border-radius: 4px;', - '}', - - '.blocklyDropdownMenu {', - 'padding: 0 !important;', - '}', - - /* Override the default Closure URL. */ - '.blocklyWidgetDiv .goog-option-selected .goog-menuitem-checkbox,', - '.blocklyWidgetDiv .goog-option-selected .goog-menuitem-icon {', - 'background: url(<<>>/sprites.png) no-repeat -48px -16px !important;', - '}', - - /* Category tree in Toolbox. */ - '.blocklyToolboxDiv {', - 'background-color: #ddd;', - 'overflow-x: visible;', - 'overflow-y: auto;', - 'position: absolute;', - '}', - - '.blocklyTreeRoot {', - 'padding: 4px 0;', - '}', - - '.blocklyTreeRoot:focus {', - 'outline: none;', - '}', - - '.blocklyTreeRow {', - 'height: 22px;', - 'line-height: 22px;', - 'margin-bottom: 3px;', - 'padding-right: 8px;', - 'white-space: nowrap;', - '}', - - '.blocklyHorizontalTree {', - 'float: left;', - 'margin: 1px 5px 8px 0;', - '}', - - '.blocklyHorizontalTreeRtl {', - 'float: right;', - 'margin: 1px 0 8px 5px;', - '}', - - '.blocklyToolboxDiv[dir="RTL"] .blocklyTreeRow {', - 'margin-left: 8px;', - '}', - - '.blocklyTreeRow:not(.blocklyTreeSelected):hover {', - 'background-color: #e4e4e4;', - '}', - - '.blocklyTreeSeparator {', - 'border-bottom: solid #e5e5e5 1px;', - 'height: 0;', - 'margin: 5px 0;', - '}', - - '.blocklyTreeSeparatorHorizontal {', - 'border-right: solid #e5e5e5 1px;', - 'width: 0;', - 'padding: 5px 0;', - 'margin: 0 5px;', - '}', - - - '.blocklyTreeIcon {', - 'background-image: url(<<>>/sprites.png);', - 'height: 16px;', - 'vertical-align: middle;', - 'width: 16px;', - '}', - - '.blocklyTreeIconClosedLtr {', - 'background-position: -32px -1px;', - '}', - - '.blocklyTreeIconClosedRtl {', - 'background-position: 0px -1px;', - '}', - - '.blocklyTreeIconOpen {', - 'background-position: -16px -1px;', - '}', - - '.blocklyTreeSelected>.blocklyTreeIconClosedLtr {', - 'background-position: -32px -17px;', - '}', - - '.blocklyTreeSelected>.blocklyTreeIconClosedRtl {', - 'background-position: 0px -17px;', - '}', - - '.blocklyTreeSelected>.blocklyTreeIconOpen {', - 'background-position: -16px -17px;', - '}', - - '.blocklyTreeIconNone,', - '.blocklyTreeSelected>.blocklyTreeIconNone {', - 'background-position: -48px -1px;', - '}', - - '.blocklyTreeLabel {', - 'cursor: default;', - 'font-family: sans-serif;', - 'font-size: 16px;', - 'padding: 0 3px;', - 'vertical-align: middle;', - '}', - - '.blocklyTreeSelected .blocklyTreeLabel {', - 'color: #fff;', - '}', - - /* Copied from: goog/css/colorpicker-simplegrid.css */ - /* - * Copyright 2007 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - - /* Author: pupius@google.com (Daniel Pupius) */ - - /* - Styles to make the colorpicker look like the old gmail color picker - NOTE: without CSS scoping this will override styles defined in palette.css - */ - '.blocklyWidgetDiv .goog-palette {', - 'outline: none;', - 'cursor: default;', - '}', - - '.blocklyWidgetDiv .goog-palette-table {', - 'border: 1px solid #666;', - 'border-collapse: collapse;', - '}', - - '.blocklyWidgetDiv .goog-palette-cell {', - 'height: 13px;', - 'width: 15px;', - 'margin: 0;', - 'border: 0;', - 'text-align: center;', - 'vertical-align: middle;', - 'border-right: 1px solid #666;', - 'font-size: 1px;', - '}', - - '.blocklyWidgetDiv .goog-palette-colorswatch {', - 'position: relative;', - 'height: 13px;', - 'width: 15px;', - 'border: 1px solid #666;', - '}', - - '.blocklyWidgetDiv .goog-palette-cell-hover .goog-palette-colorswatch {', - 'border: 1px solid #FFF;', - '}', - - '.blocklyWidgetDiv .goog-palette-cell-selected .goog-palette-colorswatch {', - 'border: 1px solid #000;', - 'color: #fff;', - '}', - - /* Copied from: goog/css/menu.css */ - /* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - - /** - * Standard styling for menus created by goog.ui.MenuRenderer. - * - * @author attila@google.com (Attila Bodis) - */ - - '.blocklyWidgetDiv .goog-menu {', - 'background: #fff;', - 'border-color: #ccc #666 #666 #ccc;', - 'border-style: solid;', - 'border-width: 1px;', - 'cursor: default;', - 'font: normal 13px Arial, sans-serif;', - 'margin: 0;', - 'outline: none;', - 'padding: 4px 0;', - 'position: absolute;', - 'overflow-y: auto;', - 'overflow-x: hidden;', - 'max-height: 100%;', - 'z-index: 20000;', /* Arbitrary, but some apps depend on it... */ - '}', - - /* Copied from: goog/css/menuitem.css */ - /* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - - /** - * Standard styling for menus created by goog.ui.MenuItemRenderer. - * - * @author attila@google.com (Attila Bodis) - */ - - /** - * State: resting. - * - * NOTE(mleibman,chrishenry): - * The RTL support in Closure is provided via two mechanisms -- "rtl" CSS - * classes and BiDi flipping done by the CSS compiler. Closure supports RTL - * with or without the use of the CSS compiler. In order for them not - * to conflict with each other, the "rtl" CSS classes need to have the #noflip - * annotation. The non-rtl counterparts should ideally have them as well, but, - * since .goog-menuitem existed without .goog-menuitem-rtl for so long before - * being added, there is a risk of people having templates where they are not - * rendering the .goog-menuitem-rtl class when in RTL and instead rely solely - * on the BiDi flipping by the CSS compiler. That's why we're not adding the - * #noflip to .goog-menuitem. - */ - '.blocklyWidgetDiv .goog-menuitem {', - 'color: #000;', - 'font: normal 13px Arial, sans-serif;', - 'list-style: none;', - 'margin: 0;', - /* 28px on the left for icon or checkbox; 7em on the right for shortcut. */ - 'padding: 4px 7em 4px 28px;', - 'white-space: nowrap;', - '}', - - /* BiDi override for the resting state. */ - /* #noflip */ - '.blocklyWidgetDiv .goog-menuitem.goog-menuitem-rtl {', - /* Flip left/right padding for BiDi. */ - 'padding-left: 7em;', - 'padding-right: 28px;', - '}', - - /* If a menu doesn't have checkable items or items with icons, remove padding. */ - '.blocklyWidgetDiv .goog-menu-nocheckbox .goog-menuitem,', - '.blocklyWidgetDiv .goog-menu-noicon .goog-menuitem {', - 'padding-left: 12px;', - '}', - - /* - * If a menu doesn't have items with shortcuts, leave just enough room for - * submenu arrows, if they are rendered. - */ - '.blocklyWidgetDiv .goog-menu-noaccel .goog-menuitem {', - 'padding-right: 20px;', - '}', - - '.blocklyWidgetDiv .goog-menuitem-content {', - 'color: #000;', - 'font: normal 13px Arial, sans-serif;', - '}', - - /* State: disabled. */ - '.blocklyWidgetDiv .goog-menuitem-disabled .goog-menuitem-accel,', - '.blocklyWidgetDiv .goog-menuitem-disabled .goog-menuitem-content {', - 'color: #ccc !important;', - '}', - - '.blocklyWidgetDiv .goog-menuitem-disabled .goog-menuitem-icon {', - 'opacity: 0.3;', - '-moz-opacity: 0.3;', - 'filter: alpha(opacity=30);', - '}', - - /* State: hover. */ - '.blocklyWidgetDiv .goog-menuitem-highlight,', - '.blocklyWidgetDiv .goog-menuitem-hover {', - 'background-color: #d6e9f8;', - /* Use an explicit top and bottom border so that the selection is visible', - * in high contrast mode. */ - 'border-color: #d6e9f8;', - 'border-style: dotted;', - 'border-width: 1px 0;', - 'padding-bottom: 3px;', - 'padding-top: 3px;', - '}', - - /* State: selected/checked. */ - '.blocklyWidgetDiv .goog-menuitem-checkbox,', - '.blocklyWidgetDiv .goog-menuitem-icon {', - 'background-repeat: no-repeat;', - 'height: 16px;', - 'left: 6px;', - 'position: absolute;', - 'right: auto;', - 'vertical-align: middle;', - 'width: 16px;', - '}', - - /* BiDi override for the selected/checked state. */ - /* #noflip */ - '.blocklyWidgetDiv .goog-menuitem-rtl .goog-menuitem-checkbox,', - '.blocklyWidgetDiv .goog-menuitem-rtl .goog-menuitem-icon {', - /* Flip left/right positioning. */ - 'left: auto;', - 'right: 6px;', - '}', - - '.blocklyWidgetDiv .goog-option-selected .goog-menuitem-checkbox,', - '.blocklyWidgetDiv .goog-option-selected .goog-menuitem-icon {', - /* Client apps may override the URL at which they serve the sprite. */ - 'background: url(//ssl.gstatic.com/editor/editortoolbar.png) no-repeat -512px 0;', - '}', - - /* Keyboard shortcut ("accelerator") style. */ - '.blocklyWidgetDiv .goog-menuitem-accel {', - 'color: #999;', - /* Keyboard shortcuts are untranslated; always left-to-right. */ - /* #noflip */ - 'direction: ltr;', - 'left: auto;', - 'padding: 0 6px;', - 'position: absolute;', - 'right: 0;', - 'text-align: right;', - '}', - - /* BiDi override for shortcut style. */ - /* #noflip */ - '.blocklyWidgetDiv .goog-menuitem-rtl .goog-menuitem-accel {', - /* Flip left/right positioning and text alignment. */ - 'left: 0;', - 'right: auto;', - 'text-align: left;', - '}', - - /* Mnemonic styles. */ - '.blocklyWidgetDiv .goog-menuitem-mnemonic-hint {', - 'text-decoration: underline;', - '}', - - '.blocklyWidgetDiv .goog-menuitem-mnemonic-separator {', - 'color: #999;', - 'font-size: 12px;', - 'padding-left: 4px;', - '}', - - /* Copied from: goog/css/menuseparator.css */ - /* - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - - /** - * Standard styling for menus created by goog.ui.MenuSeparatorRenderer. - * - * @author attila@google.com (Attila Bodis) - */ - - '.blocklyWidgetDiv .goog-menuseparator {', - 'border-top: 1px solid #ccc;', - 'margin: 4px 0;', - 'padding: 0;', - '}', - - '' -]; diff --git a/backend/_pv_1_3_5/static/blockly/core/events.js b/backend/_pv_1_3_5/static/blockly/core/events.js deleted file mode 100755 index 1d1e2b70e..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/events.js +++ /dev/null @@ -1,818 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Events fired as a result of actions in Blockly's editor. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Events'); - -goog.require('goog.math.Coordinate'); - - -/** - * Group ID for new events. Grouped events are indivisible. - * @type {string} - * @private - */ -Blockly.Events.group_ = ''; - -/** - * Sets whether events should be added to the undo stack. - * @type {boolean} - */ -Blockly.Events.recordUndo = true; - -/** - * Allow change events to be created and fired. - * @type {number} - * @private - */ -Blockly.Events.disabled_ = 0; - -/** - * Name of event that creates a block. - * @const - */ -Blockly.Events.CREATE = 'create'; - -/** - * Name of event that deletes a block. - * @const - */ -Blockly.Events.DELETE = 'delete'; - -/** - * Name of event that changes a block. - * @const - */ -Blockly.Events.CHANGE = 'change'; - -/** - * Name of event that moves a block. - * @const - */ -Blockly.Events.MOVE = 'move'; - -/** - * Name of event that records a UI change. - * @const - */ -Blockly.Events.UI = 'ui'; - -/** - * List of events queued for firing. - * @private - */ -Blockly.Events.FIRE_QUEUE_ = []; - -/** - * Create a custom event and fire it. - * @param {!Blockly.Events.Abstract} event Custom data for event. - */ -Blockly.Events.fire = function(event) { - if (!Blockly.Events.isEnabled()) { - return; - } - if (!Blockly.Events.FIRE_QUEUE_.length) { - // First event added; schedule a firing of the event queue. - setTimeout(Blockly.Events.fireNow_, 0); - } - Blockly.Events.FIRE_QUEUE_.push(event); -}; - -/** - * Fire all queued events. - * @private - */ -Blockly.Events.fireNow_ = function() { - var queue = Blockly.Events.filter(Blockly.Events.FIRE_QUEUE_, true); - Blockly.Events.FIRE_QUEUE_.length = 0; - for (var i = 0, event; event = queue[i]; i++) { - var workspace = Blockly.Workspace.getById(event.workspaceId); - if (workspace) { - workspace.fireChangeListener(event); - } - } -}; - -/** - * Filter the queued events and merge duplicates. - * @param {!Array.} queueIn Array of events. - * @param {boolean} forward True if forward (redo), false if backward (undo). - * @return {!Array.} Array of filtered events. - */ -Blockly.Events.filter = function(queueIn, forward) { - var queue = goog.array.clone(queueIn); - if (!forward) { - // Undo is merged in reverse order. - queue.reverse(); - } - // Merge duplicates. O(n^2), but n should be very small. - for (var i = 0, event1; event1 = queue[i]; i++) { - for (var j = i + 1, event2; event2 = queue[j]; j++) { - if (event1.type == event2.type && - event1.blockId == event2.blockId && - event1.workspaceId == event2.workspaceId) { - if (event1.type == Blockly.Events.MOVE) { - // Merge move events. - event1.newParentId = event2.newParentId; - event1.newInputName = event2.newInputName; - event1.newCoordinate = event2.newCoordinate; - queue.splice(j, 1); - j--; - } else if (event1.type == Blockly.Events.CHANGE && - event1.element == event2.element && - event1.name == event2.name) { - // Merge change events. - event1.newValue = event2.newValue; - queue.splice(j, 1); - j--; - } else if (event1.type == Blockly.Events.UI && - event2.element == 'click' && - (event1.element == 'commentOpen' || - event1.element == 'mutatorOpen' || - event1.element == 'warningOpen')) { - // Merge change events. - event1.newValue = event2.newValue; - queue.splice(j, 1); - j--; - } - } - } - } - // Remove null events. - for (var i = queue.length - 1; i >= 0; i--) { - if (queue[i].isNull()) { - queue.splice(i, 1); - } - } - if (!forward) { - // Restore undo order. - queue.reverse(); - } - // Move mutation events to the top of the queue. - // Intentionally skip first event. - for (var i = 1, event; event = queue[i]; i++) { - if (event.type == Blockly.Events.CHANGE && - event.element == 'mutation') { - queue.unshift(queue.splice(i, 1)[0]); - } - } - return queue; -}; - -/** - * Modify pending undo events so that when they are fired they don't land - * in the undo stack. Called by Blockly.Workspace.clearUndo. - */ -Blockly.Events.clearPendingUndo = function() { - for (var i = 0, event; event = Blockly.Events.FIRE_QUEUE_[i]; i++) { - event.recordUndo = false; - } -}; - -/** - * Stop sending events. Every call to this function MUST also call enable. - */ -Blockly.Events.disable = function() { - Blockly.Events.disabled_++; -}; - -/** - * Start sending events. Unless events were already disabled when the - * corresponding call to disable was made. - */ -Blockly.Events.enable = function() { - Blockly.Events.disabled_--; -}; - -/** - * Returns whether events may be fired or not. - * @return {boolean} True if enabled. - */ -Blockly.Events.isEnabled = function() { - return Blockly.Events.disabled_ == 0; -}; - -/** - * Current group. - * @return {string} ID string. - */ -Blockly.Events.getGroup = function() { - return Blockly.Events.group_; -}; - -/** - * Start or stop a group. - * @param {boolean|string} state True to start new group, false to end group. - * String to set group explicitly. - */ -Blockly.Events.setGroup = function(state) { - if (typeof state == 'boolean') { - Blockly.Events.group_ = state ? Blockly.genUid() : ''; - } else { - Blockly.Events.group_ = state; - } -}; - -/** - * Compute a list of the IDs of the specified block and all its descendants. - * @param {!Blockly.Block} block The root block. - * @return {!Array.} List of block IDs. - * @private - */ -Blockly.Events.getDescendantIds_ = function(block) { - var ids = []; - var descendants = block.getDescendants(); - for (var i = 0, descendant; descendant = descendants[i]; i++) { - ids[i] = descendant.id; - } - return ids; -}; - -/** - * Decode the JSON into an event. - * @param {!Object} json JSON representation. - * @param {!Blockly.Workspace} workspace Target workspace for event. - * @return {!Blockly.Events.Abstract} The event represented by the JSON. - */ -Blockly.Events.fromJson = function(json, workspace) { - var event; - switch (json.type) { - case Blockly.Events.CREATE: - event = new Blockly.Events.Create(null); - break; - case Blockly.Events.DELETE: - event = new Blockly.Events.Delete(null); - break; - case Blockly.Events.CHANGE: - event = new Blockly.Events.Change(null); - break; - case Blockly.Events.MOVE: - event = new Blockly.Events.Move(null); - break; - case Blockly.Events.UI: - event = new Blockly.Events.Ui(null); - break; - default: - throw 'Unknown event type.'; - } - event.fromJson(json); - event.workspaceId = workspace.id; - return event; -}; - -/** - * Abstract class for an event. - * @param {Blockly.Block} block The block. - * @constructor - */ -Blockly.Events.Abstract = function(block) { - if (block) { - this.blockId = block.id; - this.workspaceId = block.workspace.id; - } - this.group = Blockly.Events.group_; - this.recordUndo = Blockly.Events.recordUndo; -}; - -/** - * Encode the event as JSON. - * @return {!Object} JSON representation. - */ -Blockly.Events.Abstract.prototype.toJson = function() { - var json = { - 'type': this.type, - }; - if (this.blockId) { - json['blockId'] = this.blockId; - } - if (this.group) { - json['group'] = this.group; - } - return json; -}; - -/** - * Decode the JSON event. - * @param {!Object} json JSON representation. - */ -Blockly.Events.Abstract.prototype.fromJson = function(json) { - this.blockId = json['blockId']; - this.group = json['group']; -}; - -/** - * Does this event record any change of state? - * @return {boolean} True if null, false if something changed. - */ -Blockly.Events.Abstract.prototype.isNull = function() { - return false; -}; - -/** - * Run an event. - * @param {boolean} forward True if run forward, false if run backward (undo). - */ -Blockly.Events.Abstract.prototype.run = function(forward) { - // Defined by subclasses. -}; - -/** - * Class for a block creation event. - * @param {Blockly.Block} block The created block. Null for a blank event. - * @extends {Blockly.Events.Abstract} - * @constructor - */ -Blockly.Events.Create = function(block) { - if (!block) { - return; // Blank event to be populated by fromJson. - } - Blockly.Events.Create.superClass_.constructor.call(this, block); - this.xml = Blockly.Xml.blockToDomWithXY(block); - this.ids = Blockly.Events.getDescendantIds_(block); -}; -goog.inherits(Blockly.Events.Create, Blockly.Events.Abstract); - -/** - * Type of this event. - * @type {string} - */ -Blockly.Events.Create.prototype.type = Blockly.Events.CREATE; - -/** - * Encode the event as JSON. - * @return {!Object} JSON representation. - */ -Blockly.Events.Create.prototype.toJson = function() { - var json = Blockly.Events.Create.superClass_.toJson.call(this); - json['xml'] = Blockly.Xml.domToText(this.xml); - json['ids'] = this.ids; - return json; -}; - -/** - * Decode the JSON event. - * @param {!Object} json JSON representation. - */ -Blockly.Events.Create.prototype.fromJson = function(json) { - Blockly.Events.Create.superClass_.fromJson.call(this, json); - this.xml = Blockly.Xml.textToDom('' + json['xml'] + '').firstChild; - this.ids = json['ids']; -}; - -/** - * Run a creation event. - * @param {boolean} forward True if run forward, false if run backward (undo). - */ -Blockly.Events.Create.prototype.run = function(forward) { - var workspace = Blockly.Workspace.getById(this.workspaceId); - if (forward) { - var xml = goog.dom.createDom('xml'); - xml.appendChild(this.xml); - Blockly.Xml.domToWorkspace(xml, workspace); - } else { - for (var i = 0, id; id = this.ids[i]; i++) { - var block = workspace.getBlockById(id); - if (block) { - block.dispose(false, false); - } else if (id == this.blockId) { - // Only complain about root-level block. - console.warn("Can't uncreate non-existant block: " + id); - } - } - } -}; - -/** - * Class for a block deletion event. - * @param {Blockly.Block} block The deleted block. Null for a blank event. - * @extends {Blockly.Events.Abstract} - * @constructor - */ -Blockly.Events.Delete = function(block) { - if (!block) { - return; // Blank event to be populated by fromJson. - } - if (block.getParent()) { - throw 'Connected blocks cannot be deleted.'; - } - Blockly.Events.Delete.superClass_.constructor.call(this, block); - this.oldXml = Blockly.Xml.blockToDomWithXY(block); - this.ids = Blockly.Events.getDescendantIds_(block); -}; -goog.inherits(Blockly.Events.Delete, Blockly.Events.Abstract); - -/** - * Type of this event. - * @type {string} - */ -Blockly.Events.Delete.prototype.type = Blockly.Events.DELETE; - -/** - * Encode the event as JSON. - * @return {!Object} JSON representation. - */ -Blockly.Events.Delete.prototype.toJson = function() { - var json = Blockly.Events.Delete.superClass_.toJson.call(this); - json['ids'] = this.ids; - return json; -}; - -/** - * Decode the JSON event. - * @param {!Object} json JSON representation. - */ -Blockly.Events.Delete.prototype.fromJson = function(json) { - Blockly.Events.Delete.superClass_.fromJson.call(this, json); - this.ids = json['ids']; -}; - -/** - * Run a deletion event. - * @param {boolean} forward True if run forward, false if run backward (undo). - */ -Blockly.Events.Delete.prototype.run = function(forward) { - var workspace = Blockly.Workspace.getById(this.workspaceId); - if (forward) { - for (var i = 0, id; id = this.ids[i]; i++) { - var block = workspace.getBlockById(id); - if (block) { - block.dispose(false, false); - } else if (id == this.blockId) { - // Only complain about root-level block. - console.warn("Can't delete non-existant block: " + id); - } - } - } else { - var xml = goog.dom.createDom('xml'); - xml.appendChild(this.oldXml); - Blockly.Xml.domToWorkspace(xml, workspace); - } -}; - -/** - * Class for a block change event. - * @param {Blockly.Block} block The changed block. Null for a blank event. - * @param {string} element One of 'field', 'comment', 'disabled', etc. - * @param {?string} name Name of input or field affected, or null. - * @param {string} oldValue Previous value of element. - * @param {string} newValue New value of element. - * @extends {Blockly.Events.Abstract} - * @constructor - */ -Blockly.Events.Change = function(block, element, name, oldValue, newValue) { - if (!block) { - return; // Blank event to be populated by fromJson. - } - Blockly.Events.Change.superClass_.constructor.call(this, block); - this.element = element; - this.name = name; - this.oldValue = oldValue; - this.newValue = newValue; -}; -goog.inherits(Blockly.Events.Change, Blockly.Events.Abstract); - -/** - * Type of this event. - * @type {string} - */ -Blockly.Events.Change.prototype.type = Blockly.Events.CHANGE; - -/** - * Encode the event as JSON. - * @return {!Object} JSON representation. - */ -Blockly.Events.Change.prototype.toJson = function() { - var json = Blockly.Events.Change.superClass_.toJson.call(this); - json['element'] = this.element; - if (this.name) { - json['name'] = this.name; - } - json['newValue'] = this.newValue; - return json; -}; - -/** - * Decode the JSON event. - * @param {!Object} json JSON representation. - */ -Blockly.Events.Change.prototype.fromJson = function(json) { - Blockly.Events.Change.superClass_.fromJson.call(this, json); - this.element = json['element']; - this.name = json['name']; - this.newValue = json['newValue']; -}; - -/** - * Does this event record any change of state? - * @return {boolean} True if something changed. - */ -Blockly.Events.Change.prototype.isNull = function() { - return this.oldValue == this.newValue; -}; - -/** - * Run a change event. - * @param {boolean} forward True if run forward, false if run backward (undo). - */ -Blockly.Events.Change.prototype.run = function(forward) { - var workspace = Blockly.Workspace.getById(this.workspaceId); - var block = workspace.getBlockById(this.blockId); - if (!block) { - console.warn("Can't change non-existant block: " + this.blockId); - return; - } - if (block.mutator) { - // Close the mutator (if open) since we don't want to update it. - block.mutator.setVisible(false); - } - var value = forward ? this.newValue : this.oldValue; - switch (this.element) { - case 'field': - var field = block.getField(this.name); - if (field) { - // Run the validator for any side-effects it may have. - // The validator's opinion on validity is ignored. - field.callValidator(value); - field.setValue(value); - } else { - console.warn("Can't set non-existant field: " + this.name); - } - break; - case 'comment': - block.setCommentText(value || null); - break; - case 'collapsed': - block.setCollapsed(value); - break; - case 'disabled': - block.setDisabled(value); - break; - case 'inline': - block.setInputsInline(value); - break; - case 'mutation': - var oldMutation = ''; - if (block.mutationToDom) { - var oldMutationDom = block.mutationToDom(); - oldMutation = oldMutationDom && Blockly.Xml.domToText(oldMutationDom); - } - if (block.domToMutation) { - value = value || ''; - var dom = Blockly.Xml.textToDom('' + value + ''); - block.domToMutation(dom.firstChild); - } - Blockly.Events.fire(new Blockly.Events.Change( - block, 'mutation', null, oldMutation, value)); - break; - default: - console.warn('Unknown change type: ' + this.element); - } -}; - -/** - * Class for a block move event. Created before the move. - * @param {Blockly.Block} block The moved block. Null for a blank event. - * @extends {Blockly.Events.Abstract} - * @constructor - */ -Blockly.Events.Move = function(block) { - if (!block) { - return; // Blank event to be populated by fromJson. - } - Blockly.Events.Move.superClass_.constructor.call(this, block); - var location = this.currentLocation_(); - this.oldParentId = location.parentId; - this.oldInputName = location.inputName; - this.oldCoordinate = location.coordinate; -}; -goog.inherits(Blockly.Events.Move, Blockly.Events.Abstract); - -/** - * Type of this event. - * @type {string} - */ -Blockly.Events.Move.prototype.type = Blockly.Events.MOVE; - -/** - * Encode the event as JSON. - * @return {!Object} JSON representation. - */ -Blockly.Events.Move.prototype.toJson = function() { - var json = Blockly.Events.Move.superClass_.toJson.call(this); - if (this.newParentId) { - json['newParentId'] = this.newParentId; - } - if (this.newInputName) { - json['newInputName'] = this.newInputName; - } - if (this.newCoordinate) { - json['newCoordinate'] = Math.round(this.newCoordinate.x) + ',' + - Math.round(this.newCoordinate.y); - } - return json; -}; - -/** - * Decode the JSON event. - * @param {!Object} json JSON representation. - */ -Blockly.Events.Move.prototype.fromJson = function(json) { - Blockly.Events.Move.superClass_.fromJson.call(this, json); - this.newParentId = json['newParentId']; - this.newInputName = json['newInputName']; - if (json['newCoordinate']) { - var xy = json['newCoordinate'].split(','); - this.newCoordinate = - new goog.math.Coordinate(parseFloat(xy[0]), parseFloat(xy[1])); - } -}; - -/** - * Record the block's new location. Called after the move. - */ -Blockly.Events.Move.prototype.recordNew = function() { - var location = this.currentLocation_(); - this.newParentId = location.parentId; - this.newInputName = location.inputName; - this.newCoordinate = location.coordinate; -}; - -/** - * Returns the parentId and input if the block is connected, - * or the XY location if disconnected. - * @return {!Object} Collection of location info. - * @private - */ -Blockly.Events.Move.prototype.currentLocation_ = function() { - var workspace = Blockly.Workspace.getById(this.workspaceId); - var block = workspace.getBlockById(this.blockId); - var location = {}; - var parent = block.getParent(); - if (parent) { - location.parentId = parent.id; - var input = parent.getInputWithBlock(block); - if (input) { - location.inputName = input.name; - } - } else { - location.coordinate = block.getRelativeToSurfaceXY(); - } - return location; -}; - -/** - * Does this event record any change of state? - * @return {boolean} True if something changed. - */ -Blockly.Events.Move.prototype.isNull = function() { - return this.oldParentId == this.newParentId && - this.oldInputName == this.newInputName && - goog.math.Coordinate.equals(this.oldCoordinate, this.newCoordinate); -}; - -/** - * Run a move event. - * @param {boolean} forward True if run forward, false if run backward (undo). - */ -Blockly.Events.Move.prototype.run = function(forward) { - var workspace = Blockly.Workspace.getById(this.workspaceId); - var block = workspace.getBlockById(this.blockId); - if (!block) { - console.warn("Can't move non-existant block: " + this.blockId); - return; - } - var parentId = forward ? this.newParentId : this.oldParentId; - var inputName = forward ? this.newInputName : this.oldInputName; - var coordinate = forward ? this.newCoordinate : this.oldCoordinate; - var parentBlock = null; - if (parentId) { - parentBlock = workspace.getBlockById(parentId); - if (!parentBlock) { - console.warn("Can't connect to non-existant block: " + parentId); - return; - } - } - if (block.getParent()) { - block.unplug(); - } - if (coordinate) { - var xy = block.getRelativeToSurfaceXY(); - block.moveBy(coordinate.x - xy.x, coordinate.y - xy.y); - } else { - var blockConnection = block.outputConnection || block.previousConnection; - var parentConnection; - if (inputName) { - var input = parentBlock.getInput(inputName); - if (input) { - parentConnection = input.connection; - } - } else if (blockConnection.type == Blockly.PREVIOUS_STATEMENT) { - parentConnection = parentBlock.nextConnection; - } - if (parentConnection) { - blockConnection.connect(parentConnection); - } else { - console.warn("Can't connect to non-existant input: " + inputName); - } - } -}; - -/** - * Class for a UI event. - * @param {Blockly.Block} block The affected block. - * @param {string} element One of 'selected', 'comment', 'mutator', etc. - * @param {string} oldValue Previous value of element. - * @param {string} newValue New value of element. - * @extends {Blockly.Events.Abstract} - * @constructor - */ -Blockly.Events.Ui = function(block, element, oldValue, newValue) { - Blockly.Events.Ui.superClass_.constructor.call(this, block); - this.element = element; - this.oldValue = oldValue; - this.newValue = newValue; - this.recordUndo = false; -}; -goog.inherits(Blockly.Events.Ui, Blockly.Events.Abstract); - -/** - * Type of this event. - * @type {string} - */ -Blockly.Events.Ui.prototype.type = Blockly.Events.UI; - -/** - * Encode the event as JSON. - * @return {!Object} JSON representation. - */ -Blockly.Events.Ui.prototype.toJson = function() { - var json = Blockly.Events.Ui.superClass_.toJson.call(this); - json['element'] = this.element; - if (this.newValue !== undefined) { - json['newValue'] = this.newValue; - } - return json; -}; - -/** - * Decode the JSON event. - * @param {!Object} json JSON representation. - */ -Blockly.Events.Ui.prototype.fromJson = function(json) { - Blockly.Events.Ui.superClass_.fromJson.call(this, json); - this.element = json['element']; - this.newValue = json['newValue']; -}; - -/** - * Enable/disable a block depending on whether it is properly connected. - * Use this on applications where all blocks should be connected to a top block. - * Recommend setting the 'disable' option to 'false' in the config so that - * users don't try to reenable disabled orphan blocks. - * @param {!Blockly.Events.Abstract} event Custom data for event. - */ -Blockly.Events.disableOrphans = function(event) { - if (event.type == Blockly.Events.MOVE || - event.type == Blockly.Events.CREATE) { - Blockly.Events.disable(); - var workspace = Blockly.Workspace.getById(event.workspaceId); - var block = workspace.getBlockById(event.blockId); - if (block) { - if (block.getParent() && !block.getParent().disabled) { - var children = block.getDescendants(); - for (var i = 0, child; child = children[i]; i++) { - child.setDisabled(false); - } - } else if ((block.outputConnection || block.previousConnection) && - Blockly.dragMode_ == Blockly.DRAG_NONE) { - do { - block.setDisabled(true); - block = block.getNextBlock(); - } while (block); - } - } - Blockly.Events.enable(); - } -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/field.js b/backend/_pv_1_3_5/static/blockly/core/field.js deleted file mode 100755 index 131a62679..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/field.js +++ /dev/null @@ -1,495 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Field. Used for editable titles, variables, etc. - * This is an abstract class that defines the UI on the block. Actual - * instances would be Blockly.FieldTextInput, Blockly.FieldDropdown, etc. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Field'); - -goog.require('goog.asserts'); -goog.require('goog.dom'); -goog.require('goog.math.Size'); -goog.require('goog.style'); -goog.require('goog.userAgent'); - - -/** - * Abstract class for an editable field. - * @param {string} text The initial content of the field. - * @param {Function=} opt_validator An optional function that is called - * to validate any constraints on what the user entered. Takes the new - * text as an argument and returns either the accepted text, a replacement - * text, or null to abort the change. - * @constructor - */ -Blockly.Field = function(text, opt_validator) { - this.size_ = new goog.math.Size(0, 25); - this.setValue(text); - this.setValidator(opt_validator); -}; - -/** - * Temporary cache of text widths. - * @type {Object} - * @private - */ -Blockly.Field.cacheWidths_ = null; - -/** - * Number of current references to cache. - * @type {number} - * @private - */ -Blockly.Field.cacheReference_ = 0; - - -/** - * Name of field. Unique within each block. - * Static labels are usually unnamed. - * @type {string=} - */ -Blockly.Field.prototype.name = undefined; - -/** - * Maximum characters of text to display before adding an ellipsis. - * @type {number} - */ -Blockly.Field.prototype.maxDisplayLength = 50; - -/** - * Visible text to display. - * @type {string} - * @private - */ -Blockly.Field.prototype.text_ = ''; - -/** - * Block this field is attached to. Starts as null, then in set in init. - * @type {Blockly.Block} - * @private - */ -Blockly.Field.prototype.sourceBlock_ = null; - -/** - * Is the field visible, or hidden due to the block being collapsed? - * @type {boolean} - * @private - */ -Blockly.Field.prototype.visible_ = true; - -/** - * Validation function called when user edits an editable field. - * @type {Function} - * @private - */ -Blockly.Field.prototype.validator_ = null; - -/** - * Non-breaking space. - * @const - */ -Blockly.Field.NBSP = '\u00A0'; - -/** - * Editable fields are saved by the XML renderer, non-editable fields are not. - */ -Blockly.Field.prototype.EDITABLE = true; - -/** - * Attach this field to a block. - * @param {!Blockly.Block} block The block containing this field. - */ -Blockly.Field.prototype.setSourceBlock = function(block) { - goog.asserts.assert(!this.sourceBlock_, 'Field already bound to a block.'); - this.sourceBlock_ = block; -}; - -/** - * Install this field on a block. - */ -Blockly.Field.prototype.init = function() { - if (this.fieldGroup_) { - // Field has already been initialized once. - return; - } - // Build the DOM. - this.fieldGroup_ = Blockly.createSvgElement('g', {}, null); - if (!this.visible_) { - this.fieldGroup_.style.display = 'none'; - } - this.borderRect_ = Blockly.createSvgElement('rect', - {'rx': 4, - 'ry': 4, - 'x': -Blockly.BlockSvg.SEP_SPACE_X / 2, - 'y': 0, - 'height': 16}, this.fieldGroup_, this.sourceBlock_.workspace); - /** @type {!Element} */ - this.textElement_ = Blockly.createSvgElement('text', - {'class': 'blocklyText', 'y': this.size_.height - 12.5}, - this.fieldGroup_); - - this.updateEditable(); - this.sourceBlock_.getSvgRoot().appendChild(this.fieldGroup_); - this.mouseUpWrapper_ = - Blockly.bindEvent_(this.fieldGroup_, 'mouseup', this, this.onMouseUp_); - // Force a render. - this.updateTextNode_(); -}; - -/** - * Dispose of all DOM objects belonging to this editable field. - */ -Blockly.Field.prototype.dispose = function() { - if (this.mouseUpWrapper_) { - Blockly.unbindEvent_(this.mouseUpWrapper_); - this.mouseUpWrapper_ = null; - } - this.sourceBlock_ = null; - goog.dom.removeNode(this.fieldGroup_); - this.fieldGroup_ = null; - this.textElement_ = null; - this.borderRect_ = null; - this.validator_ = null; -}; - -/** - * Add or remove the UI indicating if this field is editable or not. - */ -Blockly.Field.prototype.updateEditable = function() { - var group = this.fieldGroup_; - if (!this.EDITABLE || !group) { - return; - } - if (this.sourceBlock_.isEditable()) { - Blockly.addClass_(group, 'blocklyEditableText'); - Blockly.removeClass_(group, 'blocklyNonEditableText'); - this.fieldGroup_.style.cursor = this.CURSOR; - } else { - Blockly.addClass_(group, 'blocklyNonEditableText'); - Blockly.removeClass_(group, 'blocklyEditableText'); - this.fieldGroup_.style.cursor = ''; - } -}; - -/** - * Gets whether this editable field is visible or not. - * @return {boolean} True if visible. - */ -Blockly.Field.prototype.isVisible = function() { - return this.visible_; -}; - -/** - * Sets whether this editable field is visible or not. - * @param {boolean} visible True if visible. - */ -Blockly.Field.prototype.setVisible = function(visible) { - if (this.visible_ == visible) { - return; - } - this.visible_ = visible; - var root = this.getSvgRoot(); - if (root) { - root.style.display = visible ? 'block' : 'none'; - this.render_(); - } -}; - -/** - * Sets a new validation function for editable fields. - * @param {Function} handler New validation function, or null. - */ -Blockly.Field.prototype.setValidator = function(handler) { - this.validator_ = handler; -}; - -/** - * Gets the validation function for editable fields. - * @return {Function} Validation function, or null. - */ -Blockly.Field.prototype.getValidator = function() { - return this.validator_; -}; - -/** - * Validates a change. Does nothing. Subclasses may override this. - * @param {string} text The user's text. - * @return {string} No change needed. - */ -Blockly.Field.prototype.classValidator = function(text) { - return text; -}; - -/** - * Calls the validation function for this field, as well as all the validation - * function for the field's class and its parents. - * @param {string} text Proposed text. - * @return {?string} Revised text, or null if invalid. - */ -Blockly.Field.prototype.callValidator = function(text) { - var classResult = this.classValidator(text); - if (classResult === null) { - // Class validator rejects value. Game over. - return null; - } else if (classResult !== undefined) { - text = classResult; - } - var userValidator = this.getValidator(); - if (userValidator) { - var userResult = userValidator.call(this, text); - if (userResult === null) { - // User validator rejects value. Game over. - return null; - } else if (userResult !== undefined) { - text = userResult; - } - } - return text; -}; - -/** - * Gets the group element for this editable field. - * Used for measuring the size and for positioning. - * @return {!Element} The group element. - */ -Blockly.Field.prototype.getSvgRoot = function() { - return /** @type {!Element} */ (this.fieldGroup_); -}; - -/** - * Draws the border with the correct width. - * Saves the computed width in a property. - * @private - */ -Blockly.Field.prototype.render_ = function() { - if (this.visible_ && this.textElement_) { - var key = this.textElement_.textContent + '\n' + - this.textElement_.className.baseVal; - if (Blockly.Field.cacheWidths_ && Blockly.Field.cacheWidths_[key]) { - var width = Blockly.Field.cacheWidths_[key]; - } else { - try { - var width = this.textElement_.getComputedTextLength(); - } catch (e) { - // MSIE 11 is known to throw "Unexpected call to method or property - // access." if Blockly is hidden. - var width = this.textElement_.textContent.length * 8; - } - if (Blockly.Field.cacheWidths_) { - Blockly.Field.cacheWidths_[key] = width; - } - } - if (this.borderRect_) { - this.borderRect_.setAttribute('width', - width + Blockly.BlockSvg.SEP_SPACE_X); - } - } else { - var width = 0; - } - this.size_.width = width; -}; - -/** - * Start caching field widths. Every call to this function MUST also call - * stopCache. Caches must not survive between execution threads. - */ -Blockly.Field.startCache = function() { - Blockly.Field.cacheReference_++; - if (!Blockly.Field.cacheWidths_) { - Blockly.Field.cacheWidths_ = {}; - } -}; - -/** - * Stop caching field widths. Unless caching was already on when the - * corresponding call to startCache was made. - */ -Blockly.Field.stopCache = function() { - Blockly.Field.cacheReference_--; - if (!Blockly.Field.cacheReference_) { - Blockly.Field.cacheWidths_ = null; - } -}; - -/** - * Returns the height and width of the field. - * @return {!goog.math.Size} Height and width. - */ -Blockly.Field.prototype.getSize = function() { - if (!this.size_.width) { - this.render_(); - } - return this.size_; -}; - -/** - * Returns the height and width of the field, - * accounting for the workspace scaling. - * @return {!goog.math.Size} Height and width. - * @private - */ -Blockly.Field.prototype.getScaledBBox_ = function() { - var bBox = this.borderRect_.getBBox(); - // Create new object, as getBBox can return an uneditable SVGRect in IE. - return new goog.math.Size(bBox.width * this.sourceBlock_.workspace.scale, - bBox.height * this.sourceBlock_.workspace.scale); -}; - -/** - * Get the text from this field. - * @return {string} Current text. - */ -Blockly.Field.prototype.getText = function() { - return this.text_; -}; - -/** - * Set the text in this field. Trigger a rerender of the source block. - * @param {*} text New text. - */ -Blockly.Field.prototype.setText = function(text) { - if (text === null) { - // No change if null. - return; - } - text = String(text); - if (text === this.text_) { - // No change. - return; - } - this.text_ = text; - this.updateTextNode_(); - - if (this.sourceBlock_ && this.sourceBlock_.rendered) { - this.sourceBlock_.render(); - this.sourceBlock_.bumpNeighbours_(); - } -}; - -/** - * Update the text node of this field to display the current text. - * @private - */ -Blockly.Field.prototype.updateTextNode_ = function() { - if (!this.textElement_) { - // Not rendered yet. - return; - } - var text = this.text_; - if (text.length > this.maxDisplayLength) { - // Truncate displayed string and add an ellipsis ('...'). - text = text.substring(0, this.maxDisplayLength - 2) + '\u2026'; - } - // Empty the text element. - goog.dom.removeChildren(/** @type {!Element} */ (this.textElement_)); - // Replace whitespace with non-breaking spaces so the text doesn't collapse. - text = text.replace(/\s/g, Blockly.Field.NBSP); - if (this.sourceBlock_.RTL && text) { - // The SVG is LTR, force text to be RTL. - text += '\u200F'; - } - if (!text) { - // Prevent the field from disappearing if empty. - text = Blockly.Field.NBSP; - } - var textNode = document.createTextNode(text); - this.textElement_.appendChild(textNode); - - // Cached width is obsolete. Clear it. - this.size_.width = 0; -}; - -/** - * By default there is no difference between the human-readable text and - * the language-neutral values. Subclasses (such as dropdown) may define this. - * @return {string} Current text. - */ -Blockly.Field.prototype.getValue = function() { - return this.getText(); -}; - -/** - * By default there is no difference between the human-readable text and - * the language-neutral values. Subclasses (such as dropdown) may define this. - * @param {string} newText New text. - */ -Blockly.Field.prototype.setValue = function(newText) { - if (newText === null) { - // No change if null. - return; - } - var oldText = this.getValue(); - if (oldText == newText) { - return; - } - if (this.sourceBlock_ && Blockly.Events.isEnabled()) { - Blockly.Events.fire(new Blockly.Events.Change( - this.sourceBlock_, 'field', this.name, oldText, newText)); - } - this.setText(newText); -}; - -/** - * Handle a mouse up event on an editable field. - * @param {!Event} e Mouse up event. - * @private - */ -Blockly.Field.prototype.onMouseUp_ = function(e) { - if ((goog.userAgent.IPHONE || goog.userAgent.IPAD) && - !goog.userAgent.isVersionOrHigher('537.51.2') && - e.layerX !== 0 && e.layerY !== 0) { - // Old iOS spawns a bogus event on the next touch after a 'prompt()' edit. - // Unlike the real events, these have a layerX and layerY set. - return; - } else if (Blockly.isRightButton(e)) { - // Right-click. - return; - } else if (this.sourceBlock_.workspace.isDragging()) { - // Drag operation is concluding. Don't open the editor. - return; - } else if (this.sourceBlock_.isEditable()) { - // Non-abstract sub-classes must define a showEditor_ method. - this.showEditor_(); - } -}; - -/** - * Change the tooltip text for this field. - * @param {string|!Element} newTip Text for tooltip or a parent element to - * link to for its tooltip. - */ -Blockly.Field.prototype.setTooltip = function(newTip) { - // Non-abstract sub-classes may wish to implement this. See FieldLabel. -}; - -/** - * Return the absolute coordinates of the top-left corner of this field. - * The origin (0,0) is the top-left corner of the page body. - * @return {!goog.math.Coordinate} Object with .x and .y properties. - * @private - */ -Blockly.Field.prototype.getAbsoluteXY_ = function() { - return goog.style.getPageOffset(this.borderRect_); -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/field_angle.js b/backend/_pv_1_3_5/static/blockly/core/field_angle.js deleted file mode 100755 index a294948e9..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/field_angle.js +++ /dev/null @@ -1,294 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2013 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Angle input field. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.FieldAngle'); - -goog.require('Blockly.FieldTextInput'); -goog.require('goog.math'); -goog.require('goog.userAgent'); - - -/** - * Class for an editable angle field. - * @param {string} text The initial content of the field. - * @param {Function=} opt_validator An optional function that is called - * to validate any constraints on what the user entered. Takes the new - * text as an argument and returns the accepted text or null to abort - * the change. - * @extends {Blockly.FieldTextInput} - * @constructor - */ -Blockly.FieldAngle = function(text, opt_validator) { - // Add degree symbol: "360°" (LTR) or "°360" (RTL) - this.symbol_ = Blockly.createSvgElement('tspan', {}, null); - this.symbol_.appendChild(document.createTextNode('\u00B0')); - - Blockly.FieldAngle.superClass_.constructor.call(this, text, opt_validator); -}; -goog.inherits(Blockly.FieldAngle, Blockly.FieldTextInput); - -/** - * Round angles to the nearest 15 degrees when using mouse. - * Set to 0 to disable rounding. - */ -Blockly.FieldAngle.ROUND = 15; - -/** - * Half the width of protractor image. - */ -Blockly.FieldAngle.HALF = 100 / 2; - -/* The following two settings work together to set the behaviour of the angle - * picker. While many combinations are possible, two modes are typical: - * Math mode. - * 0 deg is right, 90 is up. This is the style used by protractors. - * Blockly.FieldAngle.CLOCKWISE = false; - * Blockly.FieldAngle.OFFSET = 0; - * Compass mode. - * 0 deg is up, 90 is right. This is the style used by maps. - * Blockly.FieldAngle.CLOCKWISE = true; - * Blockly.FieldAngle.OFFSET = 90; - */ - -/** - * Angle increases clockwise (true) or counterclockwise (false). - */ -Blockly.FieldAngle.CLOCKWISE = false; - -/** - * Offset the location of 0 degrees (and all angles) by a constant. - * Usually either 0 (0 = right) or 90 (0 = up). - */ -Blockly.FieldAngle.OFFSET = 0; - -/** - * Maximum allowed angle before wrapping. - * Usually either 360 (for 0 to 359.9) or 180 (for -179.9 to 180). - */ -Blockly.FieldAngle.WRAP = 360; - - -/** - * Radius of protractor circle. Slightly smaller than protractor size since - * otherwise SVG crops off half the border at the edges. - */ -Blockly.FieldAngle.RADIUS = Blockly.FieldAngle.HALF - 1; - -/** - * Clean up this FieldAngle, as well as the inherited FieldTextInput. - * @return {!Function} Closure to call on destruction of the WidgetDiv. - * @private - */ -Blockly.FieldAngle.prototype.dispose_ = function() { - var thisField = this; - return function() { - Blockly.FieldAngle.superClass_.dispose_.call(thisField)(); - thisField.gauge_ = null; - if (thisField.clickWrapper_) { - Blockly.unbindEvent_(thisField.clickWrapper_); - } - if (thisField.moveWrapper1_) { - Blockly.unbindEvent_(thisField.moveWrapper1_); - } - if (thisField.moveWrapper2_) { - Blockly.unbindEvent_(thisField.moveWrapper2_); - } - }; -}; - -/** - * Show the inline free-text editor on top of the text. - * @private - */ -Blockly.FieldAngle.prototype.showEditor_ = function() { - var noFocus = - goog.userAgent.MOBILE || goog.userAgent.ANDROID || goog.userAgent.IPAD; - // Mobile browsers have issues with in-line textareas (focus & keyboards). - Blockly.FieldAngle.superClass_.showEditor_.call(this, noFocus); - var div = Blockly.WidgetDiv.DIV; - if (!div.firstChild) { - // Mobile interface uses window.prompt. - return; - } - // Build the SVG DOM. - var svg = Blockly.createSvgElement('svg', { - 'xmlns': 'http://www.w3.org/2000/svg', - 'xmlns:html': 'http://www.w3.org/1999/xhtml', - 'xmlns:xlink': 'http://www.w3.org/1999/xlink', - 'version': '1.1', - 'height': (Blockly.FieldAngle.HALF * 2) + 'px', - 'width': (Blockly.FieldAngle.HALF * 2) + 'px' - }, div); - var circle = Blockly.createSvgElement('circle', { - 'cx': Blockly.FieldAngle.HALF, 'cy': Blockly.FieldAngle.HALF, - 'r': Blockly.FieldAngle.RADIUS, - 'class': 'blocklyAngleCircle' - }, svg); - this.gauge_ = Blockly.createSvgElement('path', - {'class': 'blocklyAngleGauge'}, svg); - this.line_ = Blockly.createSvgElement('line', - {'x1': Blockly.FieldAngle.HALF, - 'y1': Blockly.FieldAngle.HALF, - 'class': 'blocklyAngleLine'}, svg); - // Draw markers around the edge. - for (var angle = 0; angle < 360; angle += 15) { - Blockly.createSvgElement('line', { - 'x1': Blockly.FieldAngle.HALF + Blockly.FieldAngle.RADIUS, - 'y1': Blockly.FieldAngle.HALF, - 'x2': Blockly.FieldAngle.HALF + Blockly.FieldAngle.RADIUS - - (angle % 45 == 0 ? 10 : 5), - 'y2': Blockly.FieldAngle.HALF, - 'class': 'blocklyAngleMarks', - 'transform': 'rotate(' + angle + ',' + - Blockly.FieldAngle.HALF + ',' + Blockly.FieldAngle.HALF + ')' - }, svg); - } - svg.style.marginLeft = (15 - Blockly.FieldAngle.RADIUS) + 'px'; - this.clickWrapper_ = - Blockly.bindEvent_(svg, 'click', this, Blockly.WidgetDiv.hide); - this.moveWrapper1_ = - Blockly.bindEvent_(circle, 'mousemove', this, this.onMouseMove); - this.moveWrapper2_ = - Blockly.bindEvent_(this.gauge_, 'mousemove', this, this.onMouseMove); - this.updateGraph_(); -}; - -/** - * Set the angle to match the mouse's position. - * @param {!Event} e Mouse move event. - */ -Blockly.FieldAngle.prototype.onMouseMove = function(e) { - var bBox = this.gauge_.ownerSVGElement.getBoundingClientRect(); - var dx = e.clientX - bBox.left - Blockly.FieldAngle.HALF; - var dy = e.clientY - bBox.top - Blockly.FieldAngle.HALF; - var angle = Math.atan(-dy / dx); - if (isNaN(angle)) { - // This shouldn't happen, but let's not let this error propogate further. - return; - } - angle = goog.math.toDegrees(angle); - // 0: East, 90: North, 180: West, 270: South. - if (dx < 0) { - angle += 180; - } else if (dy > 0) { - angle += 360; - } - if (Blockly.FieldAngle.CLOCKWISE) { - angle = Blockly.FieldAngle.OFFSET + 360 - angle; - } else { - angle -= Blockly.FieldAngle.OFFSET; - } - if (Blockly.FieldAngle.ROUND) { - angle = Math.round(angle / Blockly.FieldAngle.ROUND) * - Blockly.FieldAngle.ROUND; - } - angle = this.callValidator(angle); - Blockly.FieldTextInput.htmlInput_.value = angle; - this.setValue(angle); - this.validate_(); - this.resizeEditor_(); -}; - -/** - * Insert a degree symbol. - * @param {?string} text New text. - */ -Blockly.FieldAngle.prototype.setText = function(text) { - Blockly.FieldAngle.superClass_.setText.call(this, text); - if (!this.textElement_) { - // Not rendered yet. - return; - } - this.updateGraph_(); - // Insert degree symbol. - if (this.sourceBlock_.RTL) { - this.textElement_.insertBefore(this.symbol_, this.textElement_.firstChild); - } else { - this.textElement_.appendChild(this.symbol_); - } - // Cached width is obsolete. Clear it. - this.size_.width = 0; -}; - -/** - * Redraw the graph with the current angle. - * @private - */ -Blockly.FieldAngle.prototype.updateGraph_ = function() { - if (!this.gauge_) { - return; - } - var angleDegrees = Number(this.getText()) + Blockly.FieldAngle.OFFSET; - var angleRadians = goog.math.toRadians(angleDegrees); - var path = ['M ', Blockly.FieldAngle.HALF, ',', Blockly.FieldAngle.HALF]; - var x2 = Blockly.FieldAngle.HALF; - var y2 = Blockly.FieldAngle.HALF; - if (!isNaN(angleRadians)) { - var angle1 = goog.math.toRadians(Blockly.FieldAngle.OFFSET); - var x1 = Math.cos(angle1) * Blockly.FieldAngle.RADIUS; - var y1 = Math.sin(angle1) * -Blockly.FieldAngle.RADIUS; - if (Blockly.FieldAngle.CLOCKWISE) { - angleRadians = 2 * angle1 - angleRadians; - } - x2 += Math.cos(angleRadians) * Blockly.FieldAngle.RADIUS; - y2 -= Math.sin(angleRadians) * Blockly.FieldAngle.RADIUS; - // Don't ask how the flag calculations work. They just do. - var largeFlag = Math.abs(Math.floor((angleRadians - angle1) / Math.PI) % 2); - if (Blockly.FieldAngle.CLOCKWISE) { - largeFlag = 1 - largeFlag; - } - var sweepFlag = Number(Blockly.FieldAngle.CLOCKWISE); - path.push(' l ', x1, ',', y1, - ' A ', Blockly.FieldAngle.RADIUS, ',', Blockly.FieldAngle.RADIUS, - ' 0 ', largeFlag, ' ', sweepFlag, ' ', x2, ',', y2, ' z'); - } - this.gauge_.setAttribute('d', path.join('')); - this.line_.setAttribute('x2', x2); - this.line_.setAttribute('y2', y2); -}; - -/** - * Ensure that only an angle may be entered. - * @param {string} text The user's text. - * @return {?string} A string representing a valid angle, or null if invalid. - */ -Blockly.FieldAngle.prototype.classValidator = function(text) { - if (text === null) { - return null; - } - var n = parseFloat(text || 0); - if (isNaN(n)) { - return null; - } - n = n % 360; - if (n < 0) { - n += 360; - } - if (n > Blockly.FieldAngle.WRAP) { - n -= 360; - } - return String(n); -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/field_checkbox.js b/backend/_pv_1_3_5/static/blockly/core/field_checkbox.js deleted file mode 100755 index 638aba940..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/field_checkbox.js +++ /dev/null @@ -1,117 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Checkbox field. Checked or not checked. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.FieldCheckbox'); - -goog.require('Blockly.Field'); - - -/** - * Class for a checkbox field. - * @param {string} state The initial state of the field ('TRUE' or 'FALSE'). - * @param {Function=} opt_validator A function that is executed when a new - * option is selected. Its sole argument is the new checkbox state. If - * it returns a value, this becomes the new checkbox state, unless the - * value is null, in which case the change is aborted. - * @extends {Blockly.Field} - * @constructor - */ -Blockly.FieldCheckbox = function(state, opt_validator) { - Blockly.FieldCheckbox.superClass_.constructor.call(this, '', opt_validator); - // Set the initial state. - this.setValue(state); -}; -goog.inherits(Blockly.FieldCheckbox, Blockly.Field); - -/** - * Character for the checkmark. - */ -Blockly.FieldCheckbox.CHECK_CHAR = '\u2713'; - -/** - * Mouse cursor style when over the hotspot that initiates editability. - */ -Blockly.FieldCheckbox.prototype.CURSOR = 'default'; - -/** - * Install this checkbox on a block. - */ -Blockly.FieldCheckbox.prototype.init = function() { - if (this.fieldGroup_) { - // Checkbox has already been initialized once. - return; - } - Blockly.FieldCheckbox.superClass_.init.call(this); - // The checkbox doesn't use the inherited text element. - // Instead it uses a custom checkmark element that is either visible or not. - this.checkElement_ = Blockly.createSvgElement('text', - {'class': 'blocklyText blocklyCheckbox', 'x': -3, 'y': 14}, - this.fieldGroup_); - var textNode = document.createTextNode(Blockly.FieldCheckbox.CHECK_CHAR); - this.checkElement_.appendChild(textNode); - this.checkElement_.style.display = this.state_ ? 'block' : 'none'; -}; - -/** - * Return 'TRUE' if the checkbox is checked, 'FALSE' otherwise. - * @return {string} Current state. - */ -Blockly.FieldCheckbox.prototype.getValue = function() { - return String(this.state_).toUpperCase(); -}; - -/** - * Set the checkbox to be checked if strBool is 'TRUE', unchecks otherwise. - * @param {string} strBool New state. - */ -Blockly.FieldCheckbox.prototype.setValue = function(strBool) { - var newState = (strBool == 'TRUE'); - if (this.state_ !== newState) { - if (this.sourceBlock_ && Blockly.Events.isEnabled()) { - Blockly.Events.fire(new Blockly.Events.Change( - this.sourceBlock_, 'field', this.name, this.state_, newState)); - } - this.state_ = newState; - if (this.checkElement_) { - this.checkElement_.style.display = newState ? 'block' : 'none'; - } - } -}; - -/** - * Toggle the state of the checkbox. - * @private - */ -Blockly.FieldCheckbox.prototype.showEditor_ = function() { - var newState = !this.state_; - if (this.sourceBlock_) { - // Call any validation function, and allow it to override. - newState = this.callValidator(newState); - } - if (newState !== null) { - this.setValue(String(newState).toUpperCase()); - } -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/field_colour.js b/backend/_pv_1_3_5/static/blockly/core/field_colour.js deleted file mode 100755 index 30b7dc5e2..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/field_colour.js +++ /dev/null @@ -1,234 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Colour input field. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.FieldColour'); - -goog.require('Blockly.Field'); -goog.require('goog.dom'); -goog.require('goog.events'); -goog.require('goog.style'); -goog.require('goog.ui.ColorPicker'); - - -/** - * Class for a colour input field. - * @param {string} colour The initial colour in '#rrggbb' format. - * @param {Function=} opt_validator A function that is executed when a new - * colour is selected. Its sole argument is the new colour value. Its - * return value becomes the selected colour, unless it is undefined, in - * which case the new colour stands, or it is null, in which case the change - * is aborted. - * @extends {Blockly.Field} - * @constructor - */ -Blockly.FieldColour = function(colour, opt_validator) { - Blockly.FieldColour.superClass_.constructor.call(this, colour, opt_validator); - this.setText(Blockly.Field.NBSP + Blockly.Field.NBSP + Blockly.Field.NBSP); -}; -goog.inherits(Blockly.FieldColour, Blockly.Field); - -/** - * By default use the global constants for colours. - * @type {Array.} - * @private - */ -Blockly.FieldColour.prototype.colours_ = null; - -/** - * By default use the global constants for columns. - * @type {number} - * @private - */ -Blockly.FieldColour.prototype.columns_ = 0; - -/** - * Install this field on a block. - */ -Blockly.FieldColour.prototype.init = function() { - Blockly.FieldColour.superClass_.init.call(this); - this.borderRect_.style['fillOpacity'] = 1; - this.setValue(this.getValue()); -}; - -/** - * Mouse cursor style when over the hotspot that initiates the editor. - */ -Blockly.FieldColour.prototype.CURSOR = 'default'; - -/** - * Close the colour picker if this input is being deleted. - */ -Blockly.FieldColour.prototype.dispose = function() { - Blockly.WidgetDiv.hideIfOwner(this); - Blockly.FieldColour.superClass_.dispose.call(this); -}; - -/** - * Return the current colour. - * @return {string} Current colour in '#rrggbb' format. - */ -Blockly.FieldColour.prototype.getValue = function() { - return this.colour_; -}; - -/** - * Set the colour. - * @param {string} colour The new colour in '#rrggbb' format. - */ -Blockly.FieldColour.prototype.setValue = function(colour) { - if (this.sourceBlock_ && Blockly.Events.isEnabled() && - this.colour_ != colour) { - Blockly.Events.fire(new Blockly.Events.Change( - this.sourceBlock_, 'field', this.name, this.colour_, colour)); - } - this.colour_ = colour; - if (this.borderRect_) { - this.borderRect_.style.fill = colour; - } -}; - -/** - * Get the text from this field. Used when the block is collapsed. - * @return {string} Current text. - */ -Blockly.FieldColour.prototype.getText = function() { - var colour = this.colour_; - // Try to use #rgb format if possible, rather than #rrggbb. - var m = colour.match(/^#(.)\1(.)\2(.)\3$/); - if (m) { - colour = '#' + m[1] + m[2] + m[3]; - } - return colour; -}; - -/** - * An array of colour strings for the palette. - * See bottom of this page for the default: - * http://docs.closure-library.googlecode.com/git/closure_goog_ui_colorpicker.js.source.html - * @type {!Array.} - */ -Blockly.FieldColour.COLOURS = goog.ui.ColorPicker.SIMPLE_GRID_COLORS; - -/** - * Number of columns in the palette. - */ -Blockly.FieldColour.COLUMNS = 7; - -/** - * Set a custom colour grid for this field. - * @param {Array.} colours Array of colours for this block, - * or null to use default (Blockly.FieldColour.COLOURS). - * @return {!Blockly.FieldColour} Returns itself (for method chaining). - */ -Blockly.FieldColour.prototype.setColours = function(colours) { - this.colours_ = colours; - return this; -}; - -/** - * Set a custom grid size for this field. - * @param {number} columns Number of columns for this block, - * or 0 to use default (Blockly.FieldColour.COLUMNS). - * @return {!Blockly.FieldColour} Returns itself (for method chaining). - */ -Blockly.FieldColour.prototype.setColumns = function(columns) { - this.columns_ = columns; - return this; -}; - -/** - * Create a palette under the colour field. - * @private - */ -Blockly.FieldColour.prototype.showEditor_ = function() { - Blockly.WidgetDiv.show(this, this.sourceBlock_.RTL, - Blockly.FieldColour.widgetDispose_); - // Create the palette using Closure. - var picker = new goog.ui.ColorPicker(); - picker.setSize(this.columns_ || Blockly.FieldColour.COLUMNS); - picker.setColors(this.colours_ || Blockly.FieldColour.COLOURS); - - // Position the palette to line up with the field. - // Record windowSize and scrollOffset before adding the palette. - var windowSize = goog.dom.getViewportSize(); - var scrollOffset = goog.style.getViewportPageOffset(document); - var xy = this.getAbsoluteXY_(); - var borderBBox = this.getScaledBBox_(); - var div = Blockly.WidgetDiv.DIV; - picker.render(div); - picker.setSelectedColor(this.getValue()); - // Record paletteSize after adding the palette. - var paletteSize = goog.style.getSize(picker.getElement()); - - // Flip the palette vertically if off the bottom. - if (xy.y + paletteSize.height + borderBBox.height >= - windowSize.height + scrollOffset.y) { - xy.y -= paletteSize.height - 1; - } else { - xy.y += borderBBox.height - 1; - } - if (this.sourceBlock_.RTL) { - xy.x += borderBBox.width; - xy.x -= paletteSize.width; - // Don't go offscreen left. - if (xy.x < scrollOffset.x) { - xy.x = scrollOffset.x; - } - } else { - // Don't go offscreen right. - if (xy.x > windowSize.width + scrollOffset.x - paletteSize.width) { - xy.x = windowSize.width + scrollOffset.x - paletteSize.width; - } - } - Blockly.WidgetDiv.position(xy.x, xy.y, windowSize, scrollOffset, - this.sourceBlock_.RTL); - - // Configure event handler. - var thisField = this; - Blockly.FieldColour.changeEventKey_ = goog.events.listen(picker, - goog.ui.ColorPicker.EventType.CHANGE, - function(event) { - var colour = event.target.getSelectedColor() || '#000000'; - Blockly.WidgetDiv.hide(); - if (thisField.sourceBlock_) { - // Call any validation function, and allow it to override. - colour = thisField.callValidator(colour); - } - if (colour !== null) { - thisField.setValue(colour); - } - }); -}; - -/** - * Hide the colour palette. - * @private - */ -Blockly.FieldColour.widgetDispose_ = function() { - if (Blockly.FieldColour.changeEventKey_) { - goog.events.unlistenByKey(Blockly.FieldColour.changeEventKey_); - } -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/field_date.js b/backend/_pv_1_3_5/static/blockly/core/field_date.js deleted file mode 100755 index 24f3239e4..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/field_date.js +++ /dev/null @@ -1,346 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2015 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Date input field. - * @author pkendall64@gmail.com (Paul Kendall) - */ -'use strict'; - -goog.provide('Blockly.FieldDate'); - -goog.require('Blockly.Field'); -goog.require('goog.date'); -goog.require('goog.dom'); -goog.require('goog.events'); -goog.require('goog.i18n.DateTimeSymbols'); -goog.require('goog.i18n.DateTimeSymbols_he'); -goog.require('goog.style'); -goog.require('goog.ui.DatePicker'); - - -/** - * Class for a date input field. - * @param {string} date The initial date. - * @param {Function=} opt_validator A function that is executed when a new - * date is selected. Its sole argument is the new date value. Its - * return value becomes the selected date, unless it is undefined, in - * which case the new date stands, or it is null, in which case the change - * is aborted. - * @extends {Blockly.Field} - * @constructor - */ -Blockly.FieldDate = function(date, opt_validator) { - if (!date) { - date = new goog.date.Date().toIsoString(true); - } - Blockly.FieldDate.superClass_.constructor.call(this, date, opt_validator); - this.setValue(date); -}; -goog.inherits(Blockly.FieldDate, Blockly.Field); - -/** - * Mouse cursor style when over the hotspot that initiates the editor. - */ -Blockly.FieldDate.prototype.CURSOR = 'text'; - -/** - * Close the colour picker if this input is being deleted. - */ -Blockly.FieldDate.prototype.dispose = function() { - Blockly.WidgetDiv.hideIfOwner(this); - Blockly.FieldDate.superClass_.dispose.call(this); -}; - -/** - * Return the current date. - * @return {string} Current date. - */ -Blockly.FieldDate.prototype.getValue = function() { - return this.date_; -}; - -/** - * Set the date. - * @param {string} date The new date. - */ -Blockly.FieldDate.prototype.setValue = function(date) { - if (this.sourceBlock_) { - var validated = this.callValidator(date); - // If the new date is invalid, validation returns null. - // In this case we still want to display the illegal result. - if (validated !== null) { - date = validated; - } - } - this.date_ = date; - Blockly.Field.prototype.setText.call(this, date); -}; - -/** - * Create a date picker under the date field. - * @private - */ -Blockly.FieldDate.prototype.showEditor_ = function() { - Blockly.WidgetDiv.show(this, this.sourceBlock_.RTL, - Blockly.FieldDate.widgetDispose_); - // Create the date picker using Closure. - Blockly.FieldDate.loadLanguage_(); - var picker = new goog.ui.DatePicker(); - picker.setAllowNone(false); - picker.setShowWeekNum(false); - - // Position the picker to line up with the field. - // Record windowSize and scrollOffset before adding the picker. - var windowSize = goog.dom.getViewportSize(); - var scrollOffset = goog.style.getViewportPageOffset(document); - var xy = this.getAbsoluteXY_(); - var borderBBox = this.getScaledBBox_(); - var div = Blockly.WidgetDiv.DIV; - picker.render(div); - picker.setDate(goog.date.fromIsoString(this.getValue())); - // Record pickerSize after adding the date picker. - var pickerSize = goog.style.getSize(picker.getElement()); - - // Flip the picker vertically if off the bottom. - if (xy.y + pickerSize.height + borderBBox.height >= - windowSize.height + scrollOffset.y) { - xy.y -= pickerSize.height - 1; - } else { - xy.y += borderBBox.height - 1; - } - if (this.sourceBlock_.RTL) { - xy.x += borderBBox.width; - xy.x -= pickerSize.width; - // Don't go offscreen left. - if (xy.x < scrollOffset.x) { - xy.x = scrollOffset.x; - } - } else { - // Don't go offscreen right. - if (xy.x > windowSize.width + scrollOffset.x - pickerSize.width) { - xy.x = windowSize.width + scrollOffset.x - pickerSize.width; - } - } - Blockly.WidgetDiv.position(xy.x, xy.y, windowSize, scrollOffset, - this.sourceBlock_.RTL); - - // Configure event handler. - var thisField = this; - Blockly.FieldDate.changeEventKey_ = goog.events.listen(picker, - goog.ui.DatePicker.Events.CHANGE, - function(event) { - var date = event.date ? event.date.toIsoString(true) : ''; - Blockly.WidgetDiv.hide(); - if (thisField.sourceBlock_) { - // Call any validation function, and allow it to override. - date = thisField.callValidator(date); - } - thisField.setValue(date); - }); -}; - -/** - * Hide the date picker. - * @private - */ -Blockly.FieldDate.widgetDispose_ = function() { - if (Blockly.FieldDate.changeEventKey_) { - goog.events.unlistenByKey(Blockly.FieldDate.changeEventKey_); - } -}; - -/** - * Load the best language pack by scanning the Blockly.Msg object for a - * language that matches the available languages in Closure. - * @private - */ -Blockly.FieldDate.loadLanguage_ = function() { - var reg = /^DateTimeSymbols_(.+)$/; - for (var prop in goog.i18n) { - var m = prop.match(reg); - if (m) { - var lang = m[1].toLowerCase().replace('_', '.'); // E.g. 'pt.br' - if (goog.getObjectByName(lang, Blockly.Msg)) { - goog.i18n.DateTimeSymbols = goog.i18n[prop]; - } - } - } -}; - -/** - * CSS for date picker. See css.js for use. - */ -Blockly.FieldDate.CSS = [ - /* Copied from: goog/css/datepicker.css */ - /** - * Copyright 2009 The Closure Library Authors. All Rights Reserved. - * - * Use of this source code is governed by the Apache License, Version 2.0. - * See the COPYING file for details. - */ - - /** - * Standard styling for a goog.ui.DatePicker. - * - * @author arv@google.com (Erik Arvidsson) - */ - - '.blocklyWidgetDiv .goog-date-picker,', - '.blocklyWidgetDiv .goog-date-picker th,', - '.blocklyWidgetDiv .goog-date-picker td {', - ' font: 13px Arial, sans-serif;', - '}', - - '.blocklyWidgetDiv .goog-date-picker {', - ' -moz-user-focus: normal;', - ' -moz-user-select: none;', - ' position: relative;', - ' border: 1px solid #000;', - ' float: left;', - ' padding: 2px;', - ' color: #000;', - ' background: #c3d9ff;', - ' cursor: default;', - '}', - - '.blocklyWidgetDiv .goog-date-picker th {', - ' text-align: center;', - '}', - - '.blocklyWidgetDiv .goog-date-picker td {', - ' text-align: center;', - ' vertical-align: middle;', - ' padding: 1px 3px;', - '}', - - '.blocklyWidgetDiv .goog-date-picker-menu {', - ' position: absolute;', - ' background: threedface;', - ' border: 1px solid gray;', - ' -moz-user-focus: normal;', - ' z-index: 1;', - ' outline: none;', - '}', - - '.blocklyWidgetDiv .goog-date-picker-menu ul {', - ' list-style: none;', - ' margin: 0px;', - ' padding: 0px;', - '}', - - '.blocklyWidgetDiv .goog-date-picker-menu ul li {', - ' cursor: default;', - '}', - - '.blocklyWidgetDiv .goog-date-picker-menu-selected {', - ' background: #ccf;', - '}', - - '.blocklyWidgetDiv .goog-date-picker th {', - ' font-size: .9em;', - '}', - - '.blocklyWidgetDiv .goog-date-picker td div {', - ' float: left;', - '}', - - '.blocklyWidgetDiv .goog-date-picker button {', - ' padding: 0px;', - ' margin: 1px 0;', - ' border: 0;', - ' color: #20c;', - ' font-weight: bold;', - ' background: transparent;', - '}', - - '.blocklyWidgetDiv .goog-date-picker-date {', - ' background: #fff;', - '}', - - '.blocklyWidgetDiv .goog-date-picker-week,', - '.blocklyWidgetDiv .goog-date-picker-wday {', - ' padding: 1px 3px;', - ' border: 0;', - ' border-color: #a2bbdd;', - ' border-style: solid;', - '}', - - '.blocklyWidgetDiv .goog-date-picker-week {', - ' border-right-width: 1px;', - '}', - - '.blocklyWidgetDiv .goog-date-picker-wday {', - ' border-bottom-width: 1px;', - '}', - - '.blocklyWidgetDiv .goog-date-picker-head td {', - ' text-align: center;', - '}', - - /** Use td.className instead of !important */ - '.blocklyWidgetDiv td.goog-date-picker-today-cont {', - ' text-align: center;', - '}', - - /** Use td.className instead of !important */ - '.blocklyWidgetDiv td.goog-date-picker-none-cont {', - ' text-align: center;', - '}', - - '.blocklyWidgetDiv .goog-date-picker-month {', - ' min-width: 11ex;', - ' white-space: nowrap;', - '}', - - '.blocklyWidgetDiv .goog-date-picker-year {', - ' min-width: 6ex;', - ' white-space: nowrap;', - '}', - - '.blocklyWidgetDiv .goog-date-picker-monthyear {', - ' white-space: nowrap;', - '}', - - '.blocklyWidgetDiv .goog-date-picker table {', - ' border-collapse: collapse;', - '}', - - '.blocklyWidgetDiv .goog-date-picker-other-month {', - ' color: #888;', - '}', - - '.blocklyWidgetDiv .goog-date-picker-wkend-start,', - '.blocklyWidgetDiv .goog-date-picker-wkend-end {', - ' background: #eee;', - '}', - - /** Use td.className instead of !important */ - '.blocklyWidgetDiv td.goog-date-picker-selected {', - ' background: #c3d9ff;', - '}', - - '.blocklyWidgetDiv .goog-date-picker-today {', - ' background: #9ab;', - ' font-weight: bold !important;', - ' border-color: #246 #9bd #9bd #246;', - ' color: #fff;', - '}' -]; diff --git a/backend/_pv_1_3_5/static/blockly/core/field_dropdown.js b/backend/_pv_1_3_5/static/blockly/core/field_dropdown.js deleted file mode 100755 index ec3dd4f5a..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/field_dropdown.js +++ /dev/null @@ -1,320 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Dropdown input field. Used for editable titles and variables. - * In the interests of a consistent UI, the toolbox shares some functions and - * properties with the context menu. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.FieldDropdown'); - -goog.require('Blockly.Field'); -goog.require('goog.dom'); -goog.require('goog.events'); -goog.require('goog.style'); -goog.require('goog.ui.Menu'); -goog.require('goog.ui.MenuItem'); -goog.require('goog.userAgent'); - - -/** - * Class for an editable dropdown field. - * @param {(!Array.>|!Function)} menuGenerator An array of - * options for a dropdown list, or a function which generates these options. - * @param {Function=} opt_validator A function that is executed when a new - * option is selected, with the newly selected value as its sole argument. - * If it returns a value, that value (which must be one of the options) will - * become selected in place of the newly selected option, unless the return - * value is null, in which case the change is aborted. - * @extends {Blockly.Field} - * @constructor - */ -Blockly.FieldDropdown = function(menuGenerator, opt_validator) { - this.menuGenerator_ = menuGenerator; - this.trimOptions_(); - var firstTuple = this.getOptions_()[0]; - - // Call parent's constructor. - Blockly.FieldDropdown.superClass_.constructor.call(this, firstTuple[1], - opt_validator); -}; -goog.inherits(Blockly.FieldDropdown, Blockly.Field); - -/** - * Horizontal distance that a checkmark ovehangs the dropdown. - */ -Blockly.FieldDropdown.CHECKMARK_OVERHANG = 25; - -/** - * Android can't (in 2014) display "▾", so use "▼" instead. - */ -Blockly.FieldDropdown.ARROW_CHAR = goog.userAgent.ANDROID ? '\u25BC' : '\u25BE'; - -/** - * Mouse cursor style when over the hotspot that initiates the editor. - */ -Blockly.FieldDropdown.prototype.CURSOR = 'default'; - -/** - * Install this dropdown on a block. - */ -Blockly.FieldDropdown.prototype.init = function() { - if (this.fieldGroup_) { - // Dropdown has already been initialized once. - return; - } - // Add dropdown arrow: "option ▾" (LTR) or "▾ אופציה" (RTL) - this.arrow_ = Blockly.createSvgElement('tspan', {}, null); - this.arrow_.appendChild(document.createTextNode( - this.sourceBlock_.RTL ? Blockly.FieldDropdown.ARROW_CHAR + ' ' : - ' ' + Blockly.FieldDropdown.ARROW_CHAR)); - - Blockly.FieldDropdown.superClass_.init.call(this); - // Force a reset of the text to add the arrow. - var text = this.text_; - this.text_ = null; - this.setText(text); -}; - -/** - * Create a dropdown menu under the text. - * @private - */ -Blockly.FieldDropdown.prototype.showEditor_ = function() { - Blockly.WidgetDiv.show(this, this.sourceBlock_.RTL, null); - var thisField = this; - - function callback(e) { - var menuItem = e.target; - if (menuItem) { - var value = menuItem.getValue(); - if (thisField.sourceBlock_) { - // Call any validation function, and allow it to override. - value = thisField.callValidator(value); - } - if (value !== null) { - thisField.setValue(value); - } - } - Blockly.WidgetDiv.hideIfOwner(thisField); - } - - var menu = new goog.ui.Menu(); - menu.setRightToLeft(this.sourceBlock_.RTL); - var options = this.getOptions_(); - for (var i = 0; i < options.length; i++) { - var text = options[i][0]; // Human-readable text. - var value = options[i][1]; // Language-neutral value. - var menuItem = new goog.ui.MenuItem(text); - menuItem.setRightToLeft(this.sourceBlock_.RTL); - menuItem.setValue(value); - menuItem.setCheckable(true); - menu.addChild(menuItem, true); - menuItem.setChecked(value == this.value_); - } - // Listen for mouse/keyboard events. - goog.events.listen(menu, goog.ui.Component.EventType.ACTION, callback); - // Listen for touch events (why doesn't Closure handle this already?). - function callbackTouchStart(e) { - var control = this.getOwnerControl(/** @type {Node} */ (e.target)); - // Highlight the menu item. - control.handleMouseDown(e); - } - function callbackTouchEnd(e) { - var control = this.getOwnerControl(/** @type {Node} */ (e.target)); - // Activate the menu item. - control.performActionInternal(e); - } - menu.getHandler().listen(menu.getElement(), goog.events.EventType.TOUCHSTART, - callbackTouchStart); - menu.getHandler().listen(menu.getElement(), goog.events.EventType.TOUCHEND, - callbackTouchEnd); - - // Record windowSize and scrollOffset before adding menu. - var windowSize = goog.dom.getViewportSize(); - var scrollOffset = goog.style.getViewportPageOffset(document); - var xy = this.getAbsoluteXY_(); - var borderBBox = this.getScaledBBox_(); - var div = Blockly.WidgetDiv.DIV; - menu.render(div); - var menuDom = menu.getElement(); - Blockly.addClass_(menuDom, 'blocklyDropdownMenu'); - // Record menuSize after adding menu. - var menuSize = goog.style.getSize(menuDom); - // Recalculate height for the total content, not only box height. - menuSize.height = menuDom.scrollHeight; - - // Position the menu. - // Flip menu vertically if off the bottom. - if (xy.y + menuSize.height + borderBBox.height >= - windowSize.height + scrollOffset.y) { - xy.y -= menuSize.height + 2; - } else { - xy.y += borderBBox.height; - } - if (this.sourceBlock_.RTL) { - xy.x += borderBBox.width; - xy.x += Blockly.FieldDropdown.CHECKMARK_OVERHANG; - // Don't go offscreen left. - if (xy.x < scrollOffset.x + menuSize.width) { - xy.x = scrollOffset.x + menuSize.width; - } - } else { - xy.x -= Blockly.FieldDropdown.CHECKMARK_OVERHANG; - // Don't go offscreen right. - if (xy.x > windowSize.width + scrollOffset.x - menuSize.width) { - xy.x = windowSize.width + scrollOffset.x - menuSize.width; - } - } - Blockly.WidgetDiv.position(xy.x, xy.y, windowSize, scrollOffset, - this.sourceBlock_.RTL); - menu.setAllowAutoFocus(true); - menuDom.focus(); -}; - -/** - * Factor out common words in statically defined options. - * Create prefix and/or suffix labels. - * @private - */ -Blockly.FieldDropdown.prototype.trimOptions_ = function() { - this.prefixField = null; - this.suffixField = null; - var options = this.menuGenerator_; - if (!goog.isArray(options) || options.length < 2) { - return; - } - var strings = options.map(function(t) {return t[0];}); - var shortest = Blockly.shortestStringLength(strings); - var prefixLength = Blockly.commonWordPrefix(strings, shortest); - var suffixLength = Blockly.commonWordSuffix(strings, shortest); - if (!prefixLength && !suffixLength) { - return; - } - if (shortest <= prefixLength + suffixLength) { - // One or more strings will entirely vanish if we proceed. Abort. - return; - } - if (prefixLength) { - this.prefixField = strings[0].substring(0, prefixLength - 1); - } - if (suffixLength) { - this.suffixField = strings[0].substr(1 - suffixLength); - } - // Remove the prefix and suffix from the options. - var newOptions = []; - for (var i = 0; i < options.length; i++) { - var text = options[i][0]; - var value = options[i][1]; - text = text.substring(prefixLength, text.length - suffixLength); - newOptions[i] = [text, value]; - } - this.menuGenerator_ = newOptions; -}; - -/** - * Return a list of the options for this dropdown. - * @return {!Array.>} Array of option tuples: - * (human-readable text, language-neutral name). - * @private - */ -Blockly.FieldDropdown.prototype.getOptions_ = function() { - if (goog.isFunction(this.menuGenerator_)) { - return this.menuGenerator_.call(this); - } - return /** @type {!Array.>} */ (this.menuGenerator_); -}; - -/** - * Get the language-neutral value from this dropdown menu. - * @return {string} Current text. - */ -Blockly.FieldDropdown.prototype.getValue = function() { - return this.value_; -}; - -/** - * Set the language-neutral value for this dropdown menu. - * @param {string} newValue New value to set. - */ -Blockly.FieldDropdown.prototype.setValue = function(newValue) { - if (newValue === null || newValue === this.value_) { - return; // No change if null. - } - if (this.sourceBlock_ && Blockly.Events.isEnabled()) { - Blockly.Events.fire(new Blockly.Events.Change( - this.sourceBlock_, 'field', this.name, this.value_, newValue)); - } - this.value_ = newValue; - // Look up and display the human-readable text. - var options = this.getOptions_(); - for (var i = 0; i < options.length; i++) { - // Options are tuples of human-readable text and language-neutral values. - if (options[i][1] == newValue) { - this.setText(options[i][0]); - return; - } - } - // Value not found. Add it, maybe it will become valid once set - // (like variable names). - this.setText(newValue); -}; - -/** - * Set the text in this field. Trigger a rerender of the source block. - * @param {?string} text New text. - */ -Blockly.FieldDropdown.prototype.setText = function(text) { - if (this.sourceBlock_ && this.arrow_) { - // Update arrow's colour. - this.arrow_.style.fill = this.sourceBlock_.getColour(); - } - if (text === null || text === this.text_) { - // No change if null. - return; - } - this.text_ = text; - this.updateTextNode_(); - - if (this.textElement_) { - // Insert dropdown arrow. - if (this.sourceBlock_.RTL) { - this.textElement_.insertBefore(this.arrow_, this.textElement_.firstChild); - } else { - this.textElement_.appendChild(this.arrow_); - } - } - - if (this.sourceBlock_ && this.sourceBlock_.rendered) { - this.sourceBlock_.render(); - this.sourceBlock_.bumpNeighbours_(); - } -}; - -/** - * Close the dropdown menu if this input is being deleted. - */ -Blockly.FieldDropdown.prototype.dispose = function() { - Blockly.WidgetDiv.hideIfOwner(this); - Blockly.FieldDropdown.superClass_.dispose.call(this); -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/field_image.js b/backend/_pv_1_3_5/static/blockly/core/field_image.js deleted file mode 100755 index 71d8052f9..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/field_image.js +++ /dev/null @@ -1,171 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Image field. Used for titles, labels, etc. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.FieldImage'); - -goog.require('Blockly.Field'); -goog.require('goog.dom'); -goog.require('goog.math.Size'); -goog.require('goog.userAgent'); - - -/** - * Class for an image. - * @param {string} src The URL of the image. - * @param {number} width Width of the image. - * @param {number} height Height of the image. - * @param {string=} opt_alt Optional alt text for when block is collapsed. - * @extends {Blockly.Field} - * @constructor - */ -Blockly.FieldImage = function(src, width, height, opt_alt) { - this.sourceBlock_ = null; - // Ensure height and width are numbers. Strings are bad at math. - this.height_ = Number(height); - this.width_ = Number(width); - this.size_ = new goog.math.Size(this.width_, - this.height_ + 2 * Blockly.BlockSvg.INLINE_PADDING_Y); - this.text_ = opt_alt || ''; - this.setValue(src); -}; -goog.inherits(Blockly.FieldImage, Blockly.Field); - -/** - * Rectangular mask used by Firefox. - * @type {Element} - * @private - */ -Blockly.FieldImage.prototype.rectElement_ = null; - -/** - * Editable fields are saved by the XML renderer, non-editable fields are not. - */ -Blockly.FieldImage.prototype.EDITABLE = false; - -/** - * Install this image on a block. - */ -Blockly.FieldImage.prototype.init = function() { - if (this.fieldGroup_) { - // Image has already been initialized once. - return; - } - // Build the DOM. - /** @type {SVGElement} */ - this.fieldGroup_ = Blockly.createSvgElement('g', {}, null); - if (!this.visible_) { - this.fieldGroup_.style.display = 'none'; - } - /** @type {SVGElement} */ - this.imageElement_ = Blockly.createSvgElement('image', - {'height': this.height_ + 'px', - 'width': this.width_ + 'px'}, this.fieldGroup_); - this.setValue(this.src_); - if (goog.userAgent.GECKO) { - /** - * Due to a Firefox bug which eats mouse events on image elements, - * a transparent rectangle needs to be placed on top of the image. - * @type {SVGElement} - */ - this.rectElement_ = Blockly.createSvgElement('rect', - {'height': this.height_ + 'px', - 'width': this.width_ + 'px', - 'fill-opacity': 0}, this.fieldGroup_); - } - this.sourceBlock_.getSvgRoot().appendChild(this.fieldGroup_); - - // Configure the field to be transparent with respect to tooltips. - var topElement = this.rectElement_ || this.imageElement_; - topElement.tooltip = this.sourceBlock_; - Blockly.Tooltip.bindMouseEvents(topElement); -}; - -/** - * Dispose of all DOM objects belonging to this text. - */ -Blockly.FieldImage.prototype.dispose = function() { - goog.dom.removeNode(this.fieldGroup_); - this.fieldGroup_ = null; - this.imageElement_ = null; - this.rectElement_ = null; -}; - -/** - * Change the tooltip text for this field. - * @param {string|!Element} newTip Text for tooltip or a parent element to - * link to for its tooltip. - */ -Blockly.FieldImage.prototype.setTooltip = function(newTip) { - var topElement = this.rectElement_ || this.imageElement_; - topElement.tooltip = newTip; -}; - -/** - * Get the source URL of this image. - * @return {string} Current text. - * @override - */ -Blockly.FieldImage.prototype.getValue = function() { - return this.src_; -}; - -/** - * Set the source URL of this image. - * @param {?string} src New source. - * @override - */ -Blockly.FieldImage.prototype.setValue = function(src) { - if (src === null) { - // No change if null. - return; - } - this.src_ = src; - if (this.imageElement_) { - this.imageElement_.setAttributeNS('http://www.w3.org/1999/xlink', - 'xlink:href', goog.isString(src) ? src : ''); - } -}; - -/** - * Set the alt text of this image. - * @param {?string} alt New alt text. - * @override - */ -Blockly.FieldImage.prototype.setText = function(alt) { - if (alt === null) { - // No change if null. - return; - } - this.text_ = alt; -}; - -/** - * Images are fixed width, no need to render. - * @private - */ -Blockly.FieldImage.prototype.render_ = function() { - // NOP -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/field_label.js b/backend/_pv_1_3_5/static/blockly/core/field_label.js deleted file mode 100755 index cb5fa7d39..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/field_label.js +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Non-editable text field. Used for titles, labels, etc. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.FieldLabel'); - -goog.require('Blockly.Field'); -goog.require('Blockly.Tooltip'); -goog.require('goog.dom'); -goog.require('goog.math.Size'); - - -/** - * Class for a non-editable field. - * @param {string} text The initial content of the field. - * @param {string=} opt_class Optional CSS class for the field's text. - * @extends {Blockly.Field} - * @constructor - */ -Blockly.FieldLabel = function(text, opt_class) { - this.size_ = new goog.math.Size(0, 17.5); - this.class_ = opt_class; - this.setValue(text); -}; -goog.inherits(Blockly.FieldLabel, Blockly.Field); - -/** - * Editable fields are saved by the XML renderer, non-editable fields are not. - */ -Blockly.FieldLabel.prototype.EDITABLE = false; - -/** - * Install this text on a block. - */ -Blockly.FieldLabel.prototype.init = function() { - if (this.textElement_) { - // Text has already been initialized once. - return; - } - // Build the DOM. - this.textElement_ = Blockly.createSvgElement('text', - {'class': 'blocklyText', 'y': this.size_.height - 5}, null); - if (this.class_) { - Blockly.addClass_(this.textElement_, this.class_); - } - if (!this.visible_) { - this.textElement_.style.display = 'none'; - } - this.sourceBlock_.getSvgRoot().appendChild(this.textElement_); - - // Configure the field to be transparent with respect to tooltips. - this.textElement_.tooltip = this.sourceBlock_; - Blockly.Tooltip.bindMouseEvents(this.textElement_); - // Force a render. - this.updateTextNode_(); -}; - -/** - * Dispose of all DOM objects belonging to this text. - */ -Blockly.FieldLabel.prototype.dispose = function() { - goog.dom.removeNode(this.textElement_); - this.textElement_ = null; -}; - -/** - * Gets the group element for this field. - * Used for measuring the size and for positioning. - * @return {!Element} The group element. - */ -Blockly.FieldLabel.prototype.getSvgRoot = function() { - return /** @type {!Element} */ (this.textElement_); -}; - -/** - * Change the tooltip text for this field. - * @param {string|!Element} newTip Text for tooltip or a parent element to - * link to for its tooltip. - */ -Blockly.FieldLabel.prototype.setTooltip = function(newTip) { - this.textElement_.tooltip = newTip; -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/field_number.js b/backend/_pv_1_3_5/static/blockly/core/field_number.js deleted file mode 100755 index f72e7f053..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/field_number.js +++ /dev/null @@ -1,101 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Number input field - * @author fenichel@google.com (Rachel Fenichel) - */ -'use strict'; - -goog.provide('Blockly.FieldNumber'); - -goog.require('Blockly.FieldTextInput'); -goog.require('goog.math'); - -/** - * Class for an editable number field. - * @param {number|string} value The initial content of the field. - * @param {number|string|undefined} opt_min Minimum value. - * @param {number|string|undefined} opt_max Maximum value. - * @param {number|string|undefined} opt_precision Precision for value. - * @param {Function=} opt_validator An optional function that is called - * to validate any constraints on what the user entered. Takes the new - * text as an argument and returns either the accepted text, a replacement - * text, or null to abort the change. - * @extends {Blockly.FieldTextInput} - * @constructor - */ -Blockly.FieldNumber = - function(value, opt_min, opt_max, opt_precision, opt_validator) { - value = String(value); - Blockly.FieldNumber.superClass_.constructor.call(this, value, opt_validator); - this.setConstraints(opt_min, opt_max, opt_precision); -}; -goog.inherits(Blockly.FieldNumber, Blockly.FieldTextInput); - -/** - * Set the maximum, minimum and precision constraints on this field. - * Any of these properties may be undefiend or NaN to be disabled. - * Setting precision (usually a power of 10) enforces a minimum step between - * values. That is, the user's value will rounded to the closest multiple of - * precision. The least significant digit place is inferred from the precision. - * Integers values can be enforces by choosing an integer precision. - * @param {number|string|undefined} min Minimum value. - * @param {number|string|undefined} max Maximum value. - * @param {number|string|undefined} precision Precision for value. - */ -Blockly.FieldNumber.prototype.setConstraints = function(min, max, precision) { - precision = parseFloat(precision); - this.precision_ = isNaN(precision) ? 0 : precision; - min = parseFloat(min); - this.min_ = isNaN(min) ? -Infinity : min; - max = parseFloat(max); - this.max_ = isNaN(max) ? Infinity : max; - this.setValue(this.callValidator(this.getValue())); -}; - -/** - * Ensure that only a number in the correct range may be entered. - * @param {string} text The user's text. - * @return {?string} A string representing a valid number, or null if invalid. - */ -Blockly.FieldNumber.prototype.classValidator = function(text) { - if (text === null) { - return null; - } - text = String(text); - // TODO: Handle cases like 'ten', '1.203,14', etc. - // 'O' is sometimes mistaken for '0' by inexperienced users. - text = text.replace(/O/ig, '0'); - // Strip out thousands separators. - text = text.replace(/,/g, ''); - var n = parseFloat(text || 0); - if (isNaN(n)) { - // Invalid number. - return null; - } - // Round to nearest multiple of precision. - if (this.precision_ && isFinite(n)) { - n = Math.round(n / this.precision_) * this.precision_; - } - // Get the value in range. - n = goog.math.clamp(n, this.min_, this.max_); - return String(n); -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/field_textinput.js b/backend/_pv_1_3_5/static/blockly/core/field_textinput.js deleted file mode 100755 index 5af8bf9a7..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/field_textinput.js +++ /dev/null @@ -1,327 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Text input field. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.FieldTextInput'); - -goog.require('Blockly.Field'); -goog.require('Blockly.Msg'); -goog.require('goog.asserts'); -goog.require('goog.dom'); -goog.require('goog.dom.TagName'); -goog.require('goog.userAgent'); - - -/** - * Class for an editable text field. - * @param {string} text The initial content of the field. - * @param {Function=} opt_validator An optional function that is called - * to validate any constraints on what the user entered. Takes the new - * text as an argument and returns either the accepted text, a replacement - * text, or null to abort the change. - * @extends {Blockly.Field} - * @constructor - */ -Blockly.FieldTextInput = function(text, opt_validator) { - Blockly.FieldTextInput.superClass_.constructor.call(this, text, - opt_validator); -}; -goog.inherits(Blockly.FieldTextInput, Blockly.Field); - -/** - * Point size of text. Should match blocklyText's font-size in CSS. - */ -Blockly.FieldTextInput.FONTSIZE = 11; - -/** - * Mouse cursor style when over the hotspot that initiates the editor. - */ -Blockly.FieldTextInput.prototype.CURSOR = 'text'; - -/** - * Allow browser to spellcheck this field. - * @private - */ -Blockly.FieldTextInput.prototype.spellcheck_ = true; - -/** - * Close the input widget if this input is being deleted. - */ -Blockly.FieldTextInput.prototype.dispose = function() { - Blockly.WidgetDiv.hideIfOwner(this); - Blockly.FieldTextInput.superClass_.dispose.call(this); -}; - -/** - * Set the text in this field. - * @param {?string} text New text. - * @override - */ -Blockly.FieldTextInput.prototype.setValue = function(text) { - if (text === null) { - return; // No change if null. - } - if (this.sourceBlock_) { - var validated = this.callValidator(text); - // If the new text is invalid, validation returns null. - // In this case we still want to display the illegal result. - if (validated !== null) { - text = validated; - } - } - Blockly.Field.prototype.setValue.call(this, text); -}; - -/** - * Set whether this field is spellchecked by the browser. - * @param {boolean} check True if checked. - */ -Blockly.FieldTextInput.prototype.setSpellcheck = function(check) { - this.spellcheck_ = check; -}; - -/** - * Show the inline free-text editor on top of the text. - * @param {boolean=} opt_quietInput True if editor should be created without - * focus. Defaults to false. - * @private - */ -Blockly.FieldTextInput.prototype.showEditor_ = function(opt_quietInput) { - this.workspace_ = this.sourceBlock_.workspace; - var quietInput = opt_quietInput || false; - if (!quietInput && (goog.userAgent.MOBILE || goog.userAgent.ANDROID || - goog.userAgent.IPAD)) { - // Mobile browsers have issues with in-line textareas (focus & keyboards). - var newValue = window.prompt(Blockly.Msg.CHANGE_VALUE_TITLE, this.text_); - if (this.sourceBlock_) { - newValue = this.callValidator(newValue); - } - this.setValue(newValue); - return; - } - - Blockly.WidgetDiv.show(this, this.sourceBlock_.RTL, this.widgetDispose_()); - var div = Blockly.WidgetDiv.DIV; - // Create the input. - var htmlInput = - goog.dom.createDom(goog.dom.TagName.INPUT, 'blocklyHtmlInput'); - htmlInput.setAttribute('spellcheck', this.spellcheck_); - var fontSize = - (Blockly.FieldTextInput.FONTSIZE * this.workspace_.scale) + 'pt'; - div.style.fontSize = fontSize; - htmlInput.style.fontSize = fontSize; - /** @type {!HTMLInputElement} */ - Blockly.FieldTextInput.htmlInput_ = htmlInput; - div.appendChild(htmlInput); - - htmlInput.value = htmlInput.defaultValue = this.text_; - htmlInput.oldValue_ = null; - this.validate_(); - this.resizeEditor_(); - if (!quietInput) { - htmlInput.focus(); - htmlInput.select(); - } - - // Bind to keydown -- trap Enter without IME and Esc to hide. - htmlInput.onKeyDownWrapper_ = - Blockly.bindEvent_(htmlInput, 'keydown', this, this.onHtmlInputKeyDown_); - // Bind to keyup -- trap Enter; resize after every keystroke. - htmlInput.onKeyUpWrapper_ = - Blockly.bindEvent_(htmlInput, 'keyup', this, this.onHtmlInputChange_); - // Bind to keyPress -- repeatedly resize when holding down a key. - htmlInput.onKeyPressWrapper_ = - Blockly.bindEvent_(htmlInput, 'keypress', this, this.onHtmlInputChange_); - htmlInput.onWorkspaceChangeWrapper_ = this.resizeEditor_.bind(this); - this.workspace_.addChangeListener(htmlInput.onWorkspaceChangeWrapper_); -}; - -/** - * Handle key down to the editor. - * @param {!Event} e Keyboard event. - * @private - */ -Blockly.FieldTextInput.prototype.onHtmlInputKeyDown_ = function(e) { - var htmlInput = Blockly.FieldTextInput.htmlInput_; - var tabKey = 9, enterKey = 13, escKey = 27; - if (e.keyCode == enterKey) { - Blockly.WidgetDiv.hide(); - } else if (e.keyCode == escKey) { - htmlInput.value = htmlInput.defaultValue; - Blockly.WidgetDiv.hide(); - } else if (e.keyCode == tabKey) { - Blockly.WidgetDiv.hide(); - this.sourceBlock_.tab(this, !e.shiftKey); - e.preventDefault(); - } -}; - -/** - * Handle a change to the editor. - * @param {!Event} e Keyboard event. - * @private - */ -Blockly.FieldTextInput.prototype.onHtmlInputChange_ = function(e) { - var htmlInput = Blockly.FieldTextInput.htmlInput_; - // Update source block. - var text = htmlInput.value; - if (text !== htmlInput.oldValue_) { - htmlInput.oldValue_ = text; - this.setValue(text); - this.validate_(); - } else if (goog.userAgent.WEBKIT) { - // Cursor key. Render the source block to show the caret moving. - // Chrome only (version 26, OS X). - this.sourceBlock_.render(); - } - this.resizeEditor_(); - Blockly.svgResize(this.sourceBlock_.workspace); -}; - -/** - * Check to see if the contents of the editor validates. - * Style the editor accordingly. - * @private - */ -Blockly.FieldTextInput.prototype.validate_ = function() { - var valid = true; - goog.asserts.assertObject(Blockly.FieldTextInput.htmlInput_); - var htmlInput = Blockly.FieldTextInput.htmlInput_; - if (this.sourceBlock_) { - valid = this.callValidator(htmlInput.value); - } - if (valid === null) { - Blockly.addClass_(htmlInput, 'blocklyInvalidInput'); - } else { - Blockly.removeClass_(htmlInput, 'blocklyInvalidInput'); - } -}; - -/** - * Resize the editor and the underlying block to fit the text. - * @private - */ -Blockly.FieldTextInput.prototype.resizeEditor_ = function() { - var div = Blockly.WidgetDiv.DIV; - var bBox = this.fieldGroup_.getBBox(); - div.style.width = bBox.width * this.workspace_.scale + 'px'; - div.style.height = bBox.height * this.workspace_.scale + 'px'; - var xy = this.getAbsoluteXY_(); - // In RTL mode block fields and LTR input fields the left edge moves, - // whereas the right edge is fixed. Reposition the editor. - if (this.sourceBlock_.RTL) { - var borderBBox = this.getScaledBBox_(); - xy.x += borderBBox.width; - xy.x -= div.offsetWidth; - } - // Shift by a few pixels to line up exactly. - xy.y += 1; - if (goog.userAgent.GECKO && Blockly.WidgetDiv.DIV.style.top) { - // Firefox mis-reports the location of the border by a pixel - // once the WidgetDiv is moved into position. - xy.x -= 1; - xy.y -= 1; - } - if (goog.userAgent.WEBKIT) { - xy.y -= 3; - } - div.style.left = xy.x + 'px'; - div.style.top = xy.y + 'px'; -}; - -/** - * Close the editor, save the results, and dispose of the editable - * text field's elements. - * @return {!Function} Closure to call on destruction of the WidgetDiv. - * @private - */ -Blockly.FieldTextInput.prototype.widgetDispose_ = function() { - var thisField = this; - return function() { - var htmlInput = Blockly.FieldTextInput.htmlInput_; - // Save the edit (if it validates). - var text = htmlInput.value; - if (thisField.sourceBlock_) { - var text1 = thisField.callValidator(text); - if (text1 === null) { - // Invalid edit. - text = htmlInput.defaultValue; - } else { - // Validation function has changed the text. - text = text1; - if (thisField.onFinishEditing_) { - thisField.onFinishEditing_(text); - } - } - } - thisField.setValue(text); - thisField.sourceBlock_.rendered && thisField.sourceBlock_.render(); - Blockly.unbindEvent_(htmlInput.onKeyDownWrapper_); - Blockly.unbindEvent_(htmlInput.onKeyUpWrapper_); - Blockly.unbindEvent_(htmlInput.onKeyPressWrapper_); - thisField.workspace_.removeChangeListener( - htmlInput.onWorkspaceChangeWrapper_); - Blockly.FieldTextInput.htmlInput_ = null; - // Delete style properties. - var style = Blockly.WidgetDiv.DIV.style; - style.width = 'auto'; - style.height = 'auto'; - style.fontSize = ''; - }; -}; - -/** - * Ensure that only a number may be entered. - * @param {string} text The user's text. - * @return {?string} A string representing a valid number, or null if invalid. - */ -Blockly.FieldTextInput.numberValidator = function(text) { - console.warn('Blockly.FieldTextInput.numberValidator is deprecated. ' + - 'Use Blockly.FieldNumber instead.'); - if (text === null) { - return null; - } - text = String(text); - // TODO: Handle cases like 'ten', '1.203,14', etc. - // 'O' is sometimes mistaken for '0' by inexperienced users. - text = text.replace(/O/ig, '0'); - // Strip out thousands separators. - text = text.replace(/,/g, ''); - var n = parseFloat(text || 0); - return isNaN(n) ? null : String(n); -}; - -/** - * Ensure that only a nonnegative integer may be entered. - * @param {string} text The user's text. - * @return {?string} A string representing a valid int, or null if invalid. - */ -Blockly.FieldTextInput.nonnegativeIntegerValidator = function(text) { - var n = Blockly.FieldTextInput.numberValidator(text); - if (n) { - n = String(Math.max(0, Math.floor(n))); - } - return n; -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/field_variable.js b/backend/_pv_1_3_5/static/blockly/core/field_variable.js deleted file mode 100755 index f93caa150..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/field_variable.js +++ /dev/null @@ -1,155 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Variable input field. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.FieldVariable'); - -goog.require('Blockly.FieldDropdown'); -goog.require('Blockly.Msg'); -goog.require('Blockly.Variables'); -goog.require('goog.string'); - - -/** - * Class for a variable's dropdown field. - * @param {?string} varname The default name for the variable. If null, - * a unique variable name will be generated. - * @param {Function=} opt_validator A function that is executed when a new - * option is selected. Its sole argument is the new option value. - * @extends {Blockly.FieldDropdown} - * @constructor - */ -Blockly.FieldVariable = function(varname, opt_validator) { - Blockly.FieldVariable.superClass_.constructor.call(this, - Blockly.FieldVariable.dropdownCreate, opt_validator); - this.setValue(varname || ''); -}; -goog.inherits(Blockly.FieldVariable, Blockly.FieldDropdown); - -/** - * Install this dropdown on a block. - */ -Blockly.FieldVariable.prototype.init = function() { - if (this.fieldGroup_) { - // Dropdown has already been initialized once. - return; - } - Blockly.FieldVariable.superClass_.init.call(this); - if (!this.getValue()) { - // Variables without names get uniquely named for this workspace. - var workspace = - this.sourceBlock_.isInFlyout ? - this.sourceBlock_.workspace.targetWorkspace : - this.sourceBlock_.workspace; - this.setValue(Blockly.Variables.generateUniqueName(workspace)); - } - // If the selected variable doesn't exist yet, create it. - // For instance, some blocks in the toolbox have variable dropdowns filled - // in by default. - if (!this.sourceBlock_.isInFlyout) { - this.sourceBlock_.workspace.createVariable(this.getValue()); - } -}; - -/** - * Get the variable's name (use a variableDB to convert into a real name). - * Unline a regular dropdown, variables are literal and have no neutral value. - * @return {string} Current text. - */ -Blockly.FieldVariable.prototype.getValue = function() { - return this.getText(); -}; - -/** - * Set the variable name. - * @param {string} newValue New text. - */ -Blockly.FieldVariable.prototype.setValue = function(newValue) { - if (this.sourceBlock_ && Blockly.Events.isEnabled()) { - Blockly.Events.fire(new Blockly.Events.Change( - this.sourceBlock_, 'field', this.name, this.value_, newValue)); - } - this.value_ = newValue; - this.setText(newValue); -}; - -/** - * Return a sorted list of variable names for variable dropdown menus. - * Include a special option at the end for creating a new variable name. - * @return {!Array.} Array of variable names. - * @this {!Blockly.FieldVariable} - */ -Blockly.FieldVariable.dropdownCreate = function() { - if (this.sourceBlock_ && this.sourceBlock_.workspace) { - // Get a copy of the list, so that adding rename and new variable options - // doesn't modify the workspace's list. - var variableList = this.sourceBlock_.workspace.variableList.slice(0); - } else { - var variableList = []; - } - // Ensure that the currently selected variable is an option. - var name = this.getText(); - if (name && variableList.indexOf(name) == -1) { - variableList.push(name); - } - variableList.sort(goog.string.caseInsensitiveCompare); - variableList.push(Blockly.Msg.RENAME_VARIABLE); - variableList.push(Blockly.Msg.DELETE_VARIABLE.replace('%1', name)); - // Variables are not language-specific, use the name as both the user-facing - // text and the internal representation. - var options = []; - for (var i = 0; i < variableList.length; i++) { - options[i] = [variableList[i], variableList[i]]; - } - return options; -}; - -/** - * Event handler for a change in variable name. - * Special case the 'Rename variable...' and 'Delete variable...' options. - * In the rename case, prompt the user for a new name. - * @param {string} text The selected dropdown menu option. - * @return {null|undefined|string} An acceptable new variable name, or null if - * change is to be either aborted (cancel button) or has been already - * handled (rename), or undefined if an existing variable was chosen. - */ -Blockly.FieldVariable.prototype.classValidator = function(text) { - var workspace = this.sourceBlock_.workspace; - if (text == Blockly.Msg.RENAME_VARIABLE) { - var oldVar = this.getText(); - Blockly.hideChaff(); - text = Blockly.Variables.promptName( - Blockly.Msg.RENAME_VARIABLE_TITLE.replace('%1', oldVar), oldVar); - if (text) { - workspace.renameVariable(oldVar, text); - } - return null; - } else if (text == Blockly.Msg.DELETE_VARIABLE.replace('%1', - this.getText())) { - workspace.deleteVariable(this.getText()); - return null; - } - return undefined; -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/flyout.js b/backend/_pv_1_3_5/static/blockly/core/flyout.js deleted file mode 100755 index 03ea15059..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/flyout.js +++ /dev/null @@ -1,1364 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2011 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Flyout tray containing blocks which may be created. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Flyout'); - -goog.require('Blockly.Block'); -goog.require('Blockly.Comment'); -goog.require('Blockly.Events'); -goog.require('Blockly.FlyoutButton'); -goog.require('Blockly.WorkspaceSvg'); -goog.require('goog.dom'); -goog.require('goog.events'); -goog.require('goog.math.Rect'); -goog.require('goog.userAgent'); - - -/** - * Class for a flyout. - * @param {!Object} workspaceOptions Dictionary of options for the workspace. - * @constructor - */ -Blockly.Flyout = function(workspaceOptions) { - workspaceOptions.getMetrics = this.getMetrics_.bind(this); - workspaceOptions.setMetrics = this.setMetrics_.bind(this); - /** - * @type {!Blockly.Workspace} - * @private - */ - this.workspace_ = new Blockly.WorkspaceSvg(workspaceOptions); - this.workspace_.isFlyout = true; - - /** - * Is RTL vs LTR. - * @type {boolean} - */ - this.RTL = !!workspaceOptions.RTL; - - /** - * Flyout should be laid out horizontally vs vertically. - * @type {boolean} - * @private - */ - this.horizontalLayout_ = workspaceOptions.horizontalLayout; - - /** - * Position of the toolbox and flyout relative to the workspace. - * @type {number} - * @private - */ - this.toolboxPosition_ = workspaceOptions.toolboxPosition; - - /** - * Opaque data that can be passed to Blockly.unbindEvent_. - * @type {!Array.} - * @private - */ - this.eventWrappers_ = []; - - /** - * List of background buttons that lurk behind each block to catch clicks - * landing in the blocks' lakes and bays. - * @type {!Array.} - * @private - */ - this.backgroundButtons_ = []; - - /** - * List of visible buttons. - * @type {!Array.} - * @private - */ - this.buttons_ = []; - - /** - * List of event listeners. - * @type {!Array.} - * @private - */ - this.listeners_ = []; - - /** - * List of blocks that should always be disabled. - * @type {!Array.} - * @private - */ - this.permanentlyDisabled_ = []; - - /** - * y coordinate of mousedown - used to calculate scroll distances. - * @private {number} - */ - this.startDragMouseY_ = 0; - - /** - * x coordinate of mousedown - used to calculate scroll distances. - * @private {number} - */ - this.startDragMouseX_ = 0; -}; - -/** - * When a flyout drag is in progress, this is a reference to the flyout being - * dragged. This is used by Flyout.terminateDrag_ to reset dragMode_. - * @private {Blockly.Flyout} - */ -Blockly.Flyout.startFlyout_ = null; - -/** - * Event that started a drag. Used to determine the drag distance/direction and - * also passed to BlockSvg.onMouseDown_() after creating a new block. - * @private {Event} - */ -Blockly.Flyout.startDownEvent_ = null; - -/** - * Flyout block where the drag/click was initiated. Used to fire click events or - * create a new block. - * @private {Event} - */ -Blockly.Flyout.startBlock_ = null; - -/** - * Wrapper function called when a mouseup occurs during a background or block - * drag operation. - * @private {Array.} - */ -Blockly.Flyout.onMouseUpWrapper_ = null; - -/** - * Wrapper function called when a mousemove occurs during a background drag. - * @private {Array.} - */ -Blockly.Flyout.onMouseMoveWrapper_ = null; - -/** - * Wrapper function called when a mousemove occurs during a block drag. - * @private {Array.} - */ -Blockly.Flyout.onMouseMoveBlockWrapper_ = null; - -/** - * Does the flyout automatically close when a block is created? - * @type {boolean} - */ -Blockly.Flyout.prototype.autoClose = true; - -/** - * Corner radius of the flyout background. - * @type {number} - * @const - */ -Blockly.Flyout.prototype.CORNER_RADIUS = 8; - -/** - * Number of pixels the mouse must move before a drag/scroll starts. Because the - * drag-intention is determined when this is reached, it is larger than - * Blockly.DRAG_RADIUS so that the drag-direction is clearer. - */ -Blockly.Flyout.prototype.DRAG_RADIUS = 10; - -/** - * Margin around the edges of the blocks in the flyout. - * @type {number} - * @const - */ -Blockly.Flyout.prototype.MARGIN = Blockly.Flyout.prototype.CORNER_RADIUS; - -/** - * Gap between items in horizontal flyouts. Can be overridden with the "sep" - * element. - * @const {number} - */ -Blockly.Flyout.prototype.GAP_X = Blockly.Flyout.prototype.MARGIN * 3; - -/** - * Gap between items in vertical flyouts. Can be overridden with the "sep" - * element. - * @const {number} - */ -Blockly.Flyout.prototype.GAP_Y = Blockly.Flyout.prototype.MARGIN * 3; - -/** - * Top/bottom padding between scrollbar and edge of flyout background. - * @type {number} - * @const - */ -Blockly.Flyout.prototype.SCROLLBAR_PADDING = 2; - -/** - * Width of flyout. - * @type {number} - * @private - */ -Blockly.Flyout.prototype.width_ = 0; - -/** - * Height of flyout. - * @type {number} - * @private - */ -Blockly.Flyout.prototype.height_ = 0; - -/** - * Is the flyout dragging (scrolling)? - * DRAG_NONE - no drag is ongoing or state is undetermined. - * DRAG_STICKY - still within the sticky drag radius. - * DRAG_FREE - in scroll mode (never create a new block). - * @private - */ -Blockly.Flyout.prototype.dragMode_ = Blockly.DRAG_NONE; - -/** - * Range of a drag angle from a flyout considered "dragging toward workspace". - * Drags that are within the bounds of this many degrees from the orthogonal - * line to the flyout edge are considered to be "drags toward the workspace". - * Example: - * Flyout Edge Workspace - * [block] / <-within this angle, drags "toward workspace" | - * [block] ---- orthogonal to flyout boundary ---- | - * [block] \ | - * The angle is given in degrees from the orthogonal. - * - * This is used to know when to create a new block and when to scroll the - * flyout. Setting it to 360 means that all drags create a new block. - * @type {number} - * @private -*/ -Blockly.Flyout.prototype.dragAngleRange_ = 70; - -/** - * Creates the flyout's DOM. Only needs to be called once. - * @return {!Element} The flyout's SVG group. - */ -Blockly.Flyout.prototype.createDom = function() { - /* - - - - - */ - this.svgGroup_ = Blockly.createSvgElement('g', - {'class': 'blocklyFlyout'}, null); - this.svgBackground_ = Blockly.createSvgElement('path', - {'class': 'blocklyFlyoutBackground'}, this.svgGroup_); - this.svgGroup_.appendChild(this.workspace_.createDom()); - return this.svgGroup_; -}; - -/** - * Initializes the flyout. - * @param {!Blockly.Workspace} targetWorkspace The workspace in which to create - * new blocks. - */ -Blockly.Flyout.prototype.init = function(targetWorkspace) { - this.targetWorkspace_ = targetWorkspace; - this.workspace_.targetWorkspace = targetWorkspace; - // Add scrollbar. - this.scrollbar_ = new Blockly.Scrollbar(this.workspace_, - this.horizontalLayout_, false); - - this.hide(); - - Array.prototype.push.apply(this.eventWrappers_, - Blockly.bindEvent_(this.svgGroup_, 'wheel', this, this.wheel_)); - if (!this.autoClose) { - this.filterWrapper_ = this.filterForCapacity_.bind(this); - this.targetWorkspace_.addChangeListener(this.filterWrapper_); - } - // Dragging the flyout up and down. - Array.prototype.push.apply(this.eventWrappers_, - Blockly.bindEvent_(this.svgGroup_, 'mousedown', this, this.onMouseDown_)); -}; - -/** - * Dispose of this flyout. - * Unlink from all DOM elements to prevent memory leaks. - */ -Blockly.Flyout.prototype.dispose = function() { - this.hide(); - Blockly.unbindEvent_(this.eventWrappers_); - if (this.filterWrapper_) { - this.targetWorkspace_.removeChangeListener(this.filterWrapper_); - this.filterWrapper_ = null; - } - if (this.scrollbar_) { - this.scrollbar_.dispose(); - this.scrollbar_ = null; - } - if (this.workspace_) { - this.workspace_.targetWorkspace = null; - this.workspace_.dispose(); - this.workspace_ = null; - } - if (this.svgGroup_) { - goog.dom.removeNode(this.svgGroup_); - this.svgGroup_ = null; - } - this.svgBackground_ = null; - this.targetWorkspace_ = null; -}; - -/** - * Get the width of the flyout. - * @return {number} The width of the flyout. - */ -Blockly.Flyout.prototype.getWidth = function() { - return this.width_; -}; - -/** - * Get the height of the flyout. - * @return {number} The width of the flyout. - */ -Blockly.Flyout.prototype.getHeight = function() { - return this.height_; -}; - -/** - * Return an object with all the metrics required to size scrollbars for the - * flyout. The following properties are computed: - * .viewHeight: Height of the visible rectangle, - * .viewWidth: Width of the visible rectangle, - * .contentHeight: Height of the contents, - * .contentWidth: Width of the contents, - * .viewTop: Offset of top edge of visible rectangle from parent, - * .contentTop: Offset of the top-most content from the y=0 coordinate, - * .absoluteTop: Top-edge of view. - * .viewLeft: Offset of the left edge of visible rectangle from parent, - * .contentLeft: Offset of the left-most content from the x=0 coordinate, - * .absoluteLeft: Left-edge of view. - * @return {Object} Contains size and position metrics of the flyout. - * @private - */ -Blockly.Flyout.prototype.getMetrics_ = function() { - if (!this.isVisible()) { - // Flyout is hidden. - return null; - } - - try { - var optionBox = this.workspace_.getCanvas().getBBox(); - } catch (e) { - // Firefox has trouble with hidden elements (Bug 528969). - var optionBox = {height: 0, y: 0, width: 0, x: 0}; - } - - var absoluteTop = this.SCROLLBAR_PADDING; - var absoluteLeft = this.SCROLLBAR_PADDING; - if (this.horizontalLayout_) { - if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_BOTTOM) { - absoluteTop = 0; - } - var viewHeight = this.height_; - if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_TOP) { - viewHeight += this.MARGIN - this.SCROLLBAR_PADDING; - } - var viewWidth = this.width_ - 2 * this.SCROLLBAR_PADDING; - } else { - absoluteLeft = 0; - var viewHeight = this.height_ - 2 * this.SCROLLBAR_PADDING; - var viewWidth = this.width_; - if (!this.RTL) { - viewWidth -= this.SCROLLBAR_PADDING; - } - } - - var metrics = { - viewHeight: viewHeight, - viewWidth: viewWidth, - contentHeight: (optionBox.height + 2 * this.MARGIN) * this.workspace_.scale, - contentWidth: (optionBox.width + 2 * this.MARGIN) * this.workspace_.scale, - viewTop: -this.workspace_.scrollY, - viewLeft: -this.workspace_.scrollX, - contentTop: optionBox.y, - contentLeft: optionBox.x, - absoluteTop: absoluteTop, - absoluteLeft: absoluteLeft - }; - return metrics; -}; - -/** - * Sets the translation of the flyout to match the scrollbars. - * @param {!Object} xyRatio Contains a y property which is a float - * between 0 and 1 specifying the degree of scrolling and a - * similar x property. - * @private - */ -Blockly.Flyout.prototype.setMetrics_ = function(xyRatio) { - var metrics = this.getMetrics_(); - // This is a fix to an apparent race condition. - if (!metrics) { - return; - } - if (!this.horizontalLayout_ && goog.isNumber(xyRatio.y)) { - this.workspace_.scrollY = -metrics.contentHeight * xyRatio.y; - } else if (this.horizontalLayout_ && goog.isNumber(xyRatio.x)) { - this.workspace_.scrollX = -metrics.contentWidth * xyRatio.x; - } - - this.workspace_.translate(this.workspace_.scrollX + metrics.absoluteLeft, - this.workspace_.scrollY + metrics.absoluteTop); -}; - -/** - * Move the flyout to the edge of the workspace. - */ -Blockly.Flyout.prototype.position = function() { - if (!this.isVisible()) { - return; - } - var targetWorkspaceMetrics = this.targetWorkspace_.getMetrics(); - if (!targetWorkspaceMetrics) { - // Hidden components will return null. - return; - } - var edgeWidth = this.horizontalLayout_ ? - targetWorkspaceMetrics.viewWidth : this.width_; - edgeWidth -= this.CORNER_RADIUS; - if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_RIGHT) { - edgeWidth *= -1; - } - - this.setBackgroundPath_(edgeWidth, - this.horizontalLayout_ ? this.height_ : - targetWorkspaceMetrics.viewHeight); - - var x = targetWorkspaceMetrics.absoluteLeft; - if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_RIGHT) { - x += targetWorkspaceMetrics.viewWidth; - x -= this.width_; - } - - var y = targetWorkspaceMetrics.absoluteTop; - if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_BOTTOM) { - y += targetWorkspaceMetrics.viewHeight; - y -= this.height_; - } - - this.svgGroup_.setAttribute('transform', 'translate(' + x + ',' + y + ')'); - - // Record the height for Blockly.Flyout.getMetrics_, or width if the layout is - // horizontal. - if (this.horizontalLayout_) { - this.width_ = targetWorkspaceMetrics.viewWidth; - } else { - this.height_ = targetWorkspaceMetrics.viewHeight; - } - - // Update the scrollbar (if one exists). - if (this.scrollbar_) { - this.scrollbar_.resize(); - } -}; - -/** - * Create and set the path for the visible boundaries of the flyout. - * @param {number} width The width of the flyout, not including the - * rounded corners. - * @param {number} height The height of the flyout, not including - * rounded corners. - * @private - */ -Blockly.Flyout.prototype.setBackgroundPath_ = function(width, height) { - if (this.horizontalLayout_) { - this.setBackgroundPathHorizontal_(width, height); - } else { - this.setBackgroundPathVertical_(width, height); - } -}; - -/** - * Create and set the path for the visible boundaries of the flyout in vertical - * mode. - * @param {number} width The width of the flyout, not including the - * rounded corners. - * @param {number} height The height of the flyout, not including - * rounded corners. - * @private - */ -Blockly.Flyout.prototype.setBackgroundPathVertical_ = function(width, height) { - var atRight = this.toolboxPosition_ == Blockly.TOOLBOX_AT_RIGHT; - // Decide whether to start on the left or right. - var path = ['M ' + (atRight ? this.width_ : 0) + ',0']; - // Top. - path.push('h', width); - // Rounded corner. - path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, - atRight ? 0 : 1, - atRight ? -this.CORNER_RADIUS : this.CORNER_RADIUS, - this.CORNER_RADIUS); - // Side closest to workspace. - path.push('v', Math.max(0, height - this.CORNER_RADIUS * 2)); - // Rounded corner. - path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, - atRight ? 0 : 1, - atRight ? this.CORNER_RADIUS : -this.CORNER_RADIUS, - this.CORNER_RADIUS); - // Bottom. - path.push('h', -width); - path.push('z'); - this.svgBackground_.setAttribute('d', path.join(' ')); -}; - -/** - * Create and set the path for the visible boundaries of the flyout in - * horizontal mode. - * @param {number} width The width of the flyout, not including the - * rounded corners. - * @param {number} height The height of the flyout, not including - * rounded corners. - * @private - */ -Blockly.Flyout.prototype.setBackgroundPathHorizontal_ = function(width, - height) { - var atTop = this.toolboxPosition_ == Blockly.TOOLBOX_AT_TOP; - // Start at top left. - var path = ['M 0,' + (atTop ? 0 : this.CORNER_RADIUS)]; - - if (atTop) { - // Top. - path.push('h', width + this.CORNER_RADIUS); - // Right. - path.push('v', height); - // Bottom. - path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1, - -this.CORNER_RADIUS, this.CORNER_RADIUS); - path.push('h', -1 * (width - this.CORNER_RADIUS)); - // Left. - path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1, - -this.CORNER_RADIUS, -this.CORNER_RADIUS); - path.push('z'); - } else { - // Top. - path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1, - this.CORNER_RADIUS, -this.CORNER_RADIUS); - path.push('h', width - this.CORNER_RADIUS); - // Right. - path.push('a', this.CORNER_RADIUS, this.CORNER_RADIUS, 0, 0, 1, - this.CORNER_RADIUS, this.CORNER_RADIUS); - path.push('v', height - this.CORNER_RADIUS); - // Bottom. - path.push('h', -width - this.CORNER_RADIUS); - // Left. - path.push('z'); - } - this.svgBackground_.setAttribute('d', path.join(' ')); -}; - -/** - * Scroll the flyout to the top. - */ -Blockly.Flyout.prototype.scrollToStart = function() { - this.scrollbar_.set((this.horizontalLayout_ && this.RTL) ? Infinity : 0); -}; - -/** - * Scroll the flyout. - * @param {!Event} e Mouse wheel scroll event. - * @private - */ -Blockly.Flyout.prototype.wheel_ = function(e) { - var delta = this.horizontalLayout_ ? e.deltaX : e.deltaY; - - if (delta) { - if (goog.userAgent.GECKO) { - // Firefox's deltas are a tenth that of Chrome/Safari. - delta *= 10; - } - var metrics = this.getMetrics_(); - var pos = this.horizontalLayout_ ? metrics.viewLeft + delta : - metrics.viewTop + delta; - var limit = this.horizontalLayout_ ? - metrics.contentWidth - metrics.viewWidth : - metrics.contentHeight - metrics.viewHeight; - pos = Math.min(pos, limit); - pos = Math.max(pos, 0); - this.scrollbar_.set(pos); - } - - // Don't scroll the page. - e.preventDefault(); - // Don't propagate mousewheel event (zooming). - e.stopPropagation(); -}; - -/** - * Is the flyout visible? - * @return {boolean} True if visible. - */ -Blockly.Flyout.prototype.isVisible = function() { - return this.svgGroup_ && this.svgGroup_.style.display == 'block'; -}; - -/** - * Hide and empty the flyout. - */ -Blockly.Flyout.prototype.hide = function() { - if (!this.isVisible()) { - return; - } - this.svgGroup_.style.display = 'none'; - // Delete all the event listeners. - for (var x = 0, listen; listen = this.listeners_[x]; x++) { - Blockly.unbindEvent_(listen); - } - this.listeners_.length = 0; - if (this.reflowWrapper_) { - this.workspace_.removeChangeListener(this.reflowWrapper_); - this.reflowWrapper_ = null; - } - // Do NOT delete the blocks here. Wait until Flyout.show. - // https://neil.fraser.name/news/2014/08/09/ -}; - -/** - * Show and populate the flyout. - * @param {!Array|string} xmlList List of blocks to show. - * Variables and procedures have a custom set of blocks. - */ -Blockly.Flyout.prototype.show = function(xmlList) { - this.hide(); - this.clearOldBlocks_(); - - if (xmlList == Blockly.Variables.NAME_TYPE) { - // Special category for variables. - xmlList = - Blockly.Variables.flyoutCategory(this.workspace_.targetWorkspace); - } else if (xmlList == Blockly.Procedures.NAME_TYPE) { - // Special category for procedures. - xmlList = - Blockly.Procedures.flyoutCategory(this.workspace_.targetWorkspace); - } - - this.svgGroup_.style.display = 'block'; - // Create the blocks to be shown in this flyout. - var contents = []; - var gaps = []; - this.permanentlyDisabled_.length = 0; - for (var i = 0, xml; xml = xmlList[i]; i++) { - if (xml.tagName) { - var tagName = xml.tagName.toUpperCase(); - var default_gap = this.horizontalLayout_ ? this.GAP_X : this.GAP_Y; - if (tagName == 'BLOCK') { - var curBlock = Blockly.Xml.domToBlock(xml, this.workspace_); - if (curBlock.disabled) { - // Record blocks that were initially disabled. - // Do not enable these blocks as a result of capacity filtering. - this.permanentlyDisabled_.push(curBlock); - } - contents.push({type: 'block', block: curBlock}); - var gap = parseInt(xml.getAttribute('gap'), 10); - gaps.push(isNaN(gap) ? default_gap : gap); - } else if (xml.tagName.toUpperCase() == 'SEP') { - // Change the gap between two blocks. - // - // The default gap is 24, can be set larger or smaller. - // This overwrites the gap attribute on the previous block. - // Note that a deprecated method is to add a gap to a block. - // - var newGap = parseInt(xml.getAttribute('gap'), 10); - // Ignore gaps before the first block. - if (!isNaN(newGap) && gaps.length > 0) { - gaps[gaps.length - 1] = newGap; - } else { - gaps.push(default_gap); - } - } else if (tagName == 'BUTTON') { - var label = xml.getAttribute('text'); - var curButton = new Blockly.FlyoutButton(this.workspace_, - this.targetWorkspace_, label); - contents.push({type: 'button', button: curButton}); - gaps.push(default_gap); - } - } - } - - this.layout_(contents, gaps); - - // IE 11 is an incompetent browser that fails to fire mouseout events. - // When the mouse is over the background, deselect all blocks. - var deselectAll = function() { - var topBlocks = this.workspace_.getTopBlocks(false); - for (var i = 0, block; block = topBlocks[i]; i++) { - block.removeSelect(); - } - }; - - this.listeners_.push(Blockly.bindEvent_(this.svgBackground_, 'mouseover', - this, deselectAll)); - - if (this.horizontalLayout_) { - this.height_ = 0; - } else { - this.width_ = 0; - } - this.reflow(); - - this.filterForCapacity_(); - - // Correctly position the flyout's scrollbar when it opens. - this.position(); - - this.reflowWrapper_ = this.reflow.bind(this); - this.workspace_.addChangeListener(this.reflowWrapper_); -}; - -/** - * Lay out the blocks in the flyout. - * @param {!Array.} contents The blocks and buttons to lay out. - * @param {!Array.} gaps The visible gaps between blocks. - * @private - */ -Blockly.Flyout.prototype.layout_ = function(contents, gaps) { - this.workspace_.scale = this.targetWorkspace_.scale; - var margin = this.MARGIN; - var cursorX = this.RTL ? margin : margin + Blockly.BlockSvg.TAB_WIDTH; - var cursorY = margin; - if (this.horizontalLayout_ && this.RTL) { - contents = contents.reverse(); - } - - for (var i = 0, item; item = contents[i]; i++) { - if (item.type == 'block') { - var block = item.block; - var allBlocks = block.getDescendants(); - for (var j = 0, child; child = allBlocks[j]; j++) { - // Mark blocks as being inside a flyout. This is used to detect and - // prevent the closure of the flyout if the user right-clicks on such a - // block. - child.isInFlyout = true; - } - block.render(); - var root = block.getSvgRoot(); - var blockHW = block.getHeightWidth(); - var tab = block.outputConnection ? Blockly.BlockSvg.TAB_WIDTH : 0; - if (this.horizontalLayout_) { - cursorX += tab; - } - block.moveBy((this.horizontalLayout_ && this.RTL) ? - cursorX + blockHW.width - tab : cursorX, - cursorY); - if (this.horizontalLayout_) { - cursorX += (blockHW.width + gaps[i] - tab); - } else { - cursorY += blockHW.height + gaps[i]; - } - - // Create an invisible rectangle under the block to act as a button. Just - // using the block as a button is poor, since blocks have holes in them. - var rect = Blockly.createSvgElement('rect', {'fill-opacity': 0}, null); - rect.tooltip = block; - Blockly.Tooltip.bindMouseEvents(rect); - // Add the rectangles under the blocks, so that the blocks' tooltips work. - this.workspace_.getCanvas().insertBefore(rect, block.getSvgRoot()); - block.flyoutRect_ = rect; - this.backgroundButtons_[i] = rect; - - this.addBlockListeners_(root, block, rect); - } else if (item.type == 'button') { - var button = item.button; - var buttonSvg = button.createDom(); - button.moveTo(cursorX, cursorY); - button.show(); - Blockly.bindEvent_(buttonSvg, 'mouseup', button, button.onMouseUp); - - this.buttons_.push(button); - if (this.horizontalLayout_) { - cursorX += (button.width + gaps[i]); - } else { - cursorY += button.height + gaps[i]; - } - } - } -}; - -/** - * Delete blocks and background buttons from a previous showing of the flyout. - * @private - */ -Blockly.Flyout.prototype.clearOldBlocks_ = function() { - // Delete any blocks from a previous showing. - var oldBlocks = this.workspace_.getTopBlocks(false); - for (var i = 0, block; block = oldBlocks[i]; i++) { - if (block.workspace == this.workspace_) { - block.dispose(false, false); - } - } - // Delete any background buttons from a previous showing. - for (var j = 0, rect; rect = this.backgroundButtons_[j]; j++) { - goog.dom.removeNode(rect); - } - this.backgroundButtons_.length = 0; - - for (var i = 0, button; button = this.buttons_[i]; i++) { - button.dispose(); - } - this.buttons_.length = 0; -}; - -/** - * Add listeners to a block that has been added to the flyout. - * @param {!Element} root The root node of the SVG group the block is in. - * @param {!Blockly.Block} block The block to add listeners for. - * @param {!Element} rect The invisible rectangle under the block that acts as - * a button for that block. - * @private - */ -Blockly.Flyout.prototype.addBlockListeners_ = function(root, block, rect) { - this.listeners_.push(Blockly.bindEvent_(root, 'mousedown', null, - this.blockMouseDown_(block))); - this.listeners_.push(Blockly.bindEvent_(rect, 'mousedown', null, - this.blockMouseDown_(block))); - this.listeners_.push(Blockly.bindEvent_(root, 'mouseover', block, - block.addSelect)); - this.listeners_.push(Blockly.bindEvent_(root, 'mouseout', block, - block.removeSelect)); - this.listeners_.push(Blockly.bindEvent_(rect, 'mouseover', block, - block.addSelect)); - this.listeners_.push(Blockly.bindEvent_(rect, 'mouseout', block, - block.removeSelect)); -}; - -/** - * Handle a mouse-down on an SVG block in a non-closing flyout. - * @param {!Blockly.Block} block The flyout block to copy. - * @return {!Function} Function to call when block is clicked. - * @private - */ -Blockly.Flyout.prototype.blockMouseDown_ = function(block) { - var flyout = this; - return function(e) { - Blockly.terminateDrag_(); - Blockly.hideChaff(true); - if (Blockly.isRightButton(e)) { - // Right-click. - block.showContextMenu_(e); - } else { - // Left-click (or middle click) - Blockly.Css.setCursor(Blockly.Css.Cursor.CLOSED); - // Record the current mouse position. - flyout.startDragMouseY_ = e.clientY; - flyout.startDragMouseX_ = e.clientX; - Blockly.Flyout.startDownEvent_ = e; - Blockly.Flyout.startBlock_ = block; - Blockly.Flyout.startFlyout_ = flyout; - Blockly.Flyout.onMouseUpWrapper_ = Blockly.bindEvent_(document, - 'mouseup', flyout, flyout.onMouseUp_); - Blockly.Flyout.onMouseMoveBlockWrapper_ = Blockly.bindEvent_(document, - 'mousemove', flyout, flyout.onMouseMoveBlock_); - } - // This event has been handled. No need to bubble up to the document. - e.stopPropagation(); - e.preventDefault(); - }; -}; - -/** - * Mouse down on the flyout background. Start a vertical scroll drag. - * @param {!Event} e Mouse down event. - * @private - */ -Blockly.Flyout.prototype.onMouseDown_ = function(e) { - if (Blockly.isRightButton(e)) { - return; - } - Blockly.hideChaff(true); - this.dragMode_ = Blockly.DRAG_FREE; - this.startDragMouseY_ = e.clientY; - this.startDragMouseX_ = e.clientX; - Blockly.Flyout.startFlyout_ = this; - Blockly.Flyout.onMouseMoveWrapper_ = Blockly.bindEvent_(document, 'mousemove', - this, this.onMouseMove_); - Blockly.Flyout.onMouseUpWrapper_ = Blockly.bindEvent_(document, 'mouseup', - this, Blockly.Flyout.terminateDrag_); - // This event has been handled. No need to bubble up to the document. - e.preventDefault(); - e.stopPropagation(); -}; - -/** - * Handle a mouse-up anywhere in the SVG pane. Is only registered when a - * block is clicked. We can't use mouseUp on the block since a fast-moving - * cursor can briefly escape the block before it catches up. - * @param {!Event} e Mouse up event. - * @private - */ -Blockly.Flyout.prototype.onMouseUp_ = function(e) { - if (!this.workspace_.isDragging()) { - if (this.autoClose) { - this.createBlockFunc_(Blockly.Flyout.startBlock_)( - Blockly.Flyout.startDownEvent_); - } else if (!Blockly.WidgetDiv.isVisible()) { - Blockly.Events.fire( - new Blockly.Events.Ui(Blockly.Flyout.startBlock_, 'click', - undefined, undefined)); - } - } - Blockly.terminateDrag_(); -}; - -/** - * Handle a mouse-move to vertically drag the flyout. - * @param {!Event} e Mouse move event. - * @private - */ -Blockly.Flyout.prototype.onMouseMove_ = function(e) { - var metrics = this.getMetrics_(); - if (this.horizontalLayout_) { - if (metrics.contentWidth - metrics.viewWidth < 0) { - return; - } - var dx = e.clientX - this.startDragMouseX_; - this.startDragMouseX_ = e.clientX; - var x = metrics.viewLeft - dx; - x = goog.math.clamp(x, 0, metrics.contentWidth - metrics.viewWidth); - this.scrollbar_.set(x); - } else { - if (metrics.contentHeight - metrics.viewHeight < 0) { - return; - } - var dy = e.clientY - this.startDragMouseY_; - this.startDragMouseY_ = e.clientY; - var y = metrics.viewTop - dy; - y = goog.math.clamp(y, 0, metrics.contentHeight - metrics.viewHeight); - this.scrollbar_.set(y); - } -}; - -/** - * Mouse button is down on a block in a non-closing flyout. Create the block - * if the mouse moves beyond a small radius. This allows one to play with - * fields without instantiating blocks that instantly self-destruct. - * @param {!Event} e Mouse move event. - * @private - */ -Blockly.Flyout.prototype.onMouseMoveBlock_ = function(e) { - if (e.type == 'mousemove' && e.clientX <= 1 && e.clientY == 0 && - e.button == 0) { - /* HACK: - Safari Mobile 6.0 and Chrome for Android 18.0 fire rogue mousemove events - on certain touch actions. Ignore events with these signatures. - This may result in a one-pixel blind spot in other browsers, - but this shouldn't be noticeable. */ - e.stopPropagation(); - return; - } - var dx = e.clientX - Blockly.Flyout.startDownEvent_.clientX; - var dy = e.clientY - Blockly.Flyout.startDownEvent_.clientY; - - var createBlock = this.determineDragIntention_(dx, dy); - if (createBlock) { - this.createBlockFunc_(Blockly.Flyout.startBlock_)( - Blockly.Flyout.startDownEvent_); - } else if (this.dragMode_ == Blockly.DRAG_FREE) { - // Do a scroll. - this.onMouseMove_(e); - } - e.stopPropagation(); -}; - -/** - * Determine the intention of a drag. - * Updates dragMode_ based on a drag delta and the current mode, - * and returns true if we should create a new block. - * @param {number} dx X delta of the drag. - * @param {number} dy Y delta of the drag. - * @return {boolean} True if a new block should be created. - * @private - */ -Blockly.Flyout.prototype.determineDragIntention_ = function(dx, dy) { - if (this.dragMode_ == Blockly.DRAG_FREE) { - // Once in free mode, always stay in free mode and never create a block. - return false; - } - var dragDistance = Math.sqrt(dx * dx + dy * dy); - if (dragDistance < this.DRAG_RADIUS) { - // Still within the sticky drag radius. - this.dragMode_ = Blockly.DRAG_STICKY; - return false; - } else { - if (this.isDragTowardWorkspace_(dx, dy) || !this.scrollbar_.isVisible()) { - // Immediately create a block. - return true; - } else { - // Immediately move to free mode - the drag is away from the workspace. - this.dragMode_ = Blockly.DRAG_FREE; - return false; - } - } -}; - -/** - * Determine if a drag delta is toward the workspace, based on the position - * and orientation of the flyout. This is used in determineDragIntention_ to - * determine if a new block should be created or if the flyout should scroll. - * @param {number} dx X delta of the drag. - * @param {number} dy Y delta of the drag. - * @return {boolean} true if the drag is toward the workspace. - * @private - */ -Blockly.Flyout.prototype.isDragTowardWorkspace_ = function(dx, dy) { - // Direction goes from -180 to 180, with 0 toward the right and 90 on top. - var dragDirection = Math.atan2(dy, dx) / Math.PI * 180; - - var draggingTowardWorkspace = false; - var range = this.dragAngleRange_; - if (this.horizontalLayout_) { - if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_TOP) { - // Horizontal at top. - if (dragDirection < 90 + range && dragDirection > 90 - range) { - draggingTowardWorkspace = true; - } - } else { - // Horizontal at bottom. - if (dragDirection > -90 - range && dragDirection < -90 + range) { - draggingTowardWorkspace = true; - } - } - } else { - if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_LEFT) { - // Vertical at left. - if (dragDirection < range && dragDirection > -range) { - draggingTowardWorkspace = true; - } - } else { - // Vertical at right. - if (dragDirection < -180 + range || dragDirection > 180 - range) { - draggingTowardWorkspace = true; - } - } - } - return draggingTowardWorkspace; -}; - -/** - * Create a copy of this block on the workspace. - * @param {!Blockly.Block} originBlock The flyout block to copy. - * @return {!Function} Function to call when block is clicked. - * @private - */ -Blockly.Flyout.prototype.createBlockFunc_ = function(originBlock) { - var flyout = this; - return function(e) { - if (Blockly.isRightButton(e)) { - // Right-click. Don't create a block, let the context menu show. - return; - } - if (originBlock.disabled) { - // Beyond capacity. - return; - } - Blockly.Events.disable(); - try { - var block = flyout.placeNewBlock_(originBlock); - } finally { - Blockly.Events.enable(); - } - if (Blockly.Events.isEnabled()) { - Blockly.Events.setGroup(true); - Blockly.Events.fire(new Blockly.Events.Create(block)); - } - if (flyout.autoClose) { - flyout.hide(); - } else { - flyout.filterForCapacity_(); - } - // Start a dragging operation on the new block. - block.onMouseDown_(e); - Blockly.dragMode_ = Blockly.DRAG_FREE; - block.setDragging_(true); - }; -}; - -/** - * Copy a block from the flyout to the workspace and position it correctly. - * @param {!Blockly.Block} originBlock The flyout block to copy.. - * @return {!Blockly.Block} The new block in the main workspace. - * @private - */ -Blockly.Flyout.prototype.placeNewBlock_ = function(originBlock) { - var targetWorkspace = this.targetWorkspace_; - var svgRootOld = originBlock.getSvgRoot(); - if (!svgRootOld) { - throw 'originBlock is not rendered.'; - } - // Figure out where the original block is on the screen, relative to the upper - // left corner of the main workspace. - var xyOld = Blockly.getSvgXY_(svgRootOld, targetWorkspace); - // Take into account that the flyout might have been scrolled horizontally - // (separately from the main workspace). - // Generally a no-op in vertical mode but likely to happen in horizontal - // mode. - var scrollX = this.workspace_.scrollX; - var scale = this.workspace_.scale; - xyOld.x += scrollX / scale - scrollX; - // If the flyout is on the right side, (0, 0) in the flyout is offset to - // the right of (0, 0) in the main workspace. Add an offset to take that - // into account. - if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_RIGHT) { - scrollX = targetWorkspace.getMetrics().viewWidth - this.width_; - scale = targetWorkspace.scale; - // Scale the scroll (getSvgXY_ did not do this). - xyOld.x += scrollX / scale - scrollX; - } - - // Take into account that the flyout might have been scrolled vertically - // (separately from the main workspace). - // Generally a no-op in horizontal mode but likely to happen in vertical - // mode. - var scrollY = this.workspace_.scrollY; - scale = this.workspace_.scale; - xyOld.y += scrollY / scale - scrollY; - // If the flyout is on the bottom, (0, 0) in the flyout is offset to be below - // (0, 0) in the main workspace. Add an offset to take that into account. - if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_BOTTOM) { - scrollY = targetWorkspace.getMetrics().viewHeight - this.height_; - scale = targetWorkspace.scale; - xyOld.y += scrollY / scale - scrollY; - } - - // Create the new block by cloning the block in the flyout (via XML). - var xml = Blockly.Xml.blockToDom(originBlock); - var block = Blockly.Xml.domToBlock(xml, targetWorkspace); - var svgRootNew = block.getSvgRoot(); - if (!svgRootNew) { - throw 'block is not rendered.'; - } - // Figure out where the new block got placed on the screen, relative to the - // upper left corner of the workspace. This may not be the same as the - // original block because the flyout's origin may not be the same as the - // main workspace's origin. - var xyNew = Blockly.getSvgXY_(svgRootNew, targetWorkspace); - // Scale the scroll (getSvgXY_ did not do this). - xyNew.x += - targetWorkspace.scrollX / targetWorkspace.scale - targetWorkspace.scrollX; - xyNew.y += - targetWorkspace.scrollY / targetWorkspace.scale - targetWorkspace.scrollY; - // If the flyout is collapsible and the workspace can't be scrolled. - if (targetWorkspace.toolbox_ && !targetWorkspace.scrollbar) { - xyNew.x += targetWorkspace.toolbox_.getWidth() / targetWorkspace.scale; - xyNew.y += targetWorkspace.toolbox_.getHeight() / targetWorkspace.scale; - } - - // Move the new block to where the old block is. - block.moveBy(xyOld.x - xyNew.x, xyOld.y - xyNew.y); - return block; -}; - -/** - * Filter the blocks on the flyout to disable the ones that are above the - * capacity limit. - * @private - */ -Blockly.Flyout.prototype.filterForCapacity_ = function() { - var remainingCapacity = this.targetWorkspace_.remainingCapacity(); - var blocks = this.workspace_.getTopBlocks(false); - for (var i = 0, block; block = blocks[i]; i++) { - if (this.permanentlyDisabled_.indexOf(block) == -1) { - var allBlocks = block.getDescendants(); - block.setDisabled(allBlocks.length > remainingCapacity); - } - } -}; - -/** - * Return the deletion rectangle for this flyout. - * @return {goog.math.Rect} Rectangle in which to delete. - */ -Blockly.Flyout.prototype.getClientRect = function() { - if (!this.svgGroup_) { - return null; - } - - var flyoutRect = this.svgGroup_.getBoundingClientRect(); - // BIG_NUM is offscreen padding so that blocks dragged beyond the shown flyout - // area are still deleted. Must be larger than the largest screen size, - // but be smaller than half Number.MAX_SAFE_INTEGER (not available on IE). - var BIG_NUM = 1000000000; - var x = flyoutRect.left; - var y = flyoutRect.top; - var width = flyoutRect.width; - var height = flyoutRect.height; - - if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_TOP) { - return new goog.math.Rect(-BIG_NUM, y - BIG_NUM, BIG_NUM * 2, - BIG_NUM + height); - } else if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_BOTTOM) { - return new goog.math.Rect(-BIG_NUM, y, BIG_NUM * 2, - BIG_NUM + height); - } else if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_LEFT) { - return new goog.math.Rect(x - BIG_NUM, -BIG_NUM, BIG_NUM + width, - BIG_NUM * 2); - } else { // Right - return new goog.math.Rect(x, -BIG_NUM, BIG_NUM + width, BIG_NUM * 2); - } -}; - -/** - * Stop binding to the global mouseup and mousemove events. - * @private - */ -Blockly.Flyout.terminateDrag_ = function() { - if (Blockly.Flyout.startFlyout_) { - Blockly.Flyout.startFlyout_.dragMode_ = Blockly.DRAG_NONE; - } - if (Blockly.Flyout.onMouseUpWrapper_) { - Blockly.unbindEvent_(Blockly.Flyout.onMouseUpWrapper_); - Blockly.Flyout.onMouseUpWrapper_ = null; - } - if (Blockly.Flyout.onMouseMoveBlockWrapper_) { - Blockly.unbindEvent_(Blockly.Flyout.onMouseMoveBlockWrapper_); - Blockly.Flyout.onMouseMoveBlockWrapper_ = null; - } - if (Blockly.Flyout.onMouseMoveWrapper_) { - Blockly.unbindEvent_(Blockly.Flyout.onMouseMoveWrapper_); - Blockly.Flyout.onMouseMoveWrapper_ = null; - } - Blockly.Flyout.startDownEvent_ = null; - Blockly.Flyout.startBlock_ = null; - Blockly.Flyout.startFlyout_ = null; -}; - -/** - * Compute height of flyout. Position button under each block. - * For RTL: Lay out the blocks right-aligned. - * @param {!Array} blocks The blocks to reflow. - */ -Blockly.Flyout.prototype.reflowHorizontal = function(blocks) { - this.workspace_.scale = this.targetWorkspace_.scale; - var flyoutHeight = 0; - for (var i = 0, block; block = blocks[i]; i++) { - flyoutHeight = Math.max(flyoutHeight, block.getHeightWidth().height); - } - flyoutHeight += this.MARGIN * 1.5; - flyoutHeight *= this.workspace_.scale; - flyoutHeight += Blockly.Scrollbar.scrollbarThickness; - if (this.height_ != flyoutHeight) { - for (var i = 0, block; block = blocks[i]; i++) { - var blockHW = block.getHeightWidth(); - if (block.flyoutRect_) { - block.flyoutRect_.setAttribute('width', blockHW.width); - block.flyoutRect_.setAttribute('height', blockHW.height); - // Rectangles behind blocks with output tabs are shifted a bit. - var tab = block.outputConnection ? Blockly.BlockSvg.TAB_WIDTH : 0; - var blockXY = block.getRelativeToSurfaceXY(); - block.flyoutRect_.setAttribute('y', blockXY.y); - block.flyoutRect_.setAttribute('x', - this.RTL ? blockXY.x - blockHW.width + tab : blockXY.x - tab); - // For hat blocks we want to shift them down by the hat height - // since the y coordinate is the corner, not the top of the hat. - var hatOffset = - block.startHat_ ? Blockly.BlockSvg.START_HAT_HEIGHT : 0; - if (hatOffset) { - block.moveBy(0, hatOffset); - } - block.flyoutRect_.setAttribute('y', blockXY.y); - } - } - // Record the height for .getMetrics_ and .position. - this.height_ = flyoutHeight; - // Call this since it is possible the trash and zoom buttons need - // to move. e.g. on a bottom positioned flyout when zoom is clicked. - this.targetWorkspace_.resize(); - } -}; - -/** - * Compute width of flyout. Position button under each block. - * For RTL: Lay out the blocks right-aligned. - * @param {!Array} blocks The blocks to reflow. - */ -Blockly.Flyout.prototype.reflowVertical = function(blocks) { - this.workspace_.scale = this.targetWorkspace_.scale; - var flyoutWidth = 0; - for (var i = 0, block; block = blocks[i]; i++) { - var width = block.getHeightWidth().width; - if (block.outputConnection) { - width -= Blockly.BlockSvg.TAB_WIDTH; - } - flyoutWidth = Math.max(flyoutWidth, width); - } - for (var i = 0, button; button = this.buttons_[i]; i++) { - flyoutWidth = Math.max(flyoutWidth, button.width); - } - flyoutWidth += this.MARGIN * 1.5 + Blockly.BlockSvg.TAB_WIDTH; - flyoutWidth *= this.workspace_.scale; - flyoutWidth += Blockly.Scrollbar.scrollbarThickness; - if (this.width_ != flyoutWidth) { - for (var i = 0, block; block = blocks[i]; i++) { - var blockHW = block.getHeightWidth(); - if (this.RTL) { - // With the flyoutWidth known, right-align the blocks. - var oldX = block.getRelativeToSurfaceXY().x; - var newX = flyoutWidth / this.workspace_.scale - this.MARGIN; - newX -= Blockly.BlockSvg.TAB_WIDTH; - block.moveBy(newX - oldX, 0); - } - if (block.flyoutRect_) { - block.flyoutRect_.setAttribute('width', blockHW.width); - block.flyoutRect_.setAttribute('height', blockHW.height); - // Blocks with output tabs are shifted a bit. - var tab = block.outputConnection ? Blockly.BlockSvg.TAB_WIDTH : 0; - var blockXY = block.getRelativeToSurfaceXY(); - block.flyoutRect_.setAttribute('x', - this.RTL ? blockXY.x - blockHW.width + tab : blockXY.x - tab); - // For hat blocks we want to shift them down by the hat height - // since the y coordinate is the corner, not the top of the hat. - var hatOffset = - block.startHat_ ? Blockly.BlockSvg.START_HAT_HEIGHT : 0; - if (hatOffset) { - block.moveBy(0, hatOffset); - } - block.flyoutRect_.setAttribute('y', blockXY.y); - } - } - // Record the width for .getMetrics_ and .position. - this.width_ = flyoutWidth; - // Call this since it is possible the trash and zoom buttons need - // to move. e.g. on a bottom positioned flyout when zoom is clicked. - this.targetWorkspace_.resize(); - } -}; - -/** - * Reflow blocks and their buttons. - */ -Blockly.Flyout.prototype.reflow = function() { - if (this.reflowWrapper_) { - this.workspace_.removeChangeListener(this.reflowWrapper_); - } - var blocks = this.workspace_.getTopBlocks(false); - if (this.horizontalLayout_) { - this.reflowHorizontal(blocks); - } else { - this.reflowVertical(blocks); - } - if (this.reflowWrapper_) { - this.workspace_.addChangeListener(this.reflowWrapper_); - } -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/flyout_button.js b/backend/_pv_1_3_5/static/blockly/core/flyout_button.js deleted file mode 100755 index 75b7a83c1..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/flyout_button.js +++ /dev/null @@ -1,169 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Class for a button in the flyout. - * @author fenichel@google.com (Rachel Fenichel) - */ -'use strict'; - -goog.provide('Blockly.FlyoutButton'); - -goog.require('goog.dom'); -goog.require('goog.math.Coordinate'); - - -/** - * Class for a button in the flyout. - * @param {!Blockly.Workspace} workspace The workspace in which to place this - * button. - * @param {!Blockly.Workspace} targetWorkspace The flyout's target workspace. - * @param {string} text The text to display on the button. - * @constructor - */ -Blockly.FlyoutButton = function(workspace, targetWorkspace, text) { - /** - * @type {!Blockly.Workspace} - * @private - */ - this.workspace_ = workspace; - - /** - * @type {!Blockly.Workspace} - * @private - */ - this.targetWorkspace_ = targetWorkspace; - - /** - * @type {string} - * @private - */ - this.text_ = text; - - /** - * @type {goog.math.Coordinate} - * @private - */ - this.position_ = new goog.math.Coordinate(0, 0); -}; - -/** - * The margin around the text in the button. - */ -Blockly.FlyoutButton.MARGIN = 5; - -/** - * The width of the button's rect. - * @type {number} - */ -Blockly.FlyoutButton.prototype.width = 0; - -/** - * The height of the button's rect. - * @type {number} - */ -Blockly.FlyoutButton.prototype.height = 0; - -/** - * Create the button elements. - * @return {!Element} The button's SVG group. - */ -Blockly.FlyoutButton.prototype.createDom = function() { - this.svgGroup_ = Blockly.createSvgElement('g', - {'class': 'blocklyFlyoutButton'}, this.workspace_.getCanvas()); - - // Rect with rounded corners. - var rect = Blockly.createSvgElement('rect', - {'rx': 4, 'ry': 4, - 'height': 0, 'width': 0}, - this.svgGroup_); - - var svgText = Blockly.createSvgElement('text', - {'class': 'blocklyText', 'x': 0, 'y': 0, - 'text-anchor': 'middle'}, this.svgGroup_); - svgText.textContent = this.text_; - - this.width = svgText.getComputedTextLength() + - 2 * Blockly.FlyoutButton.MARGIN; - this.height = 20; // Can't compute it :( - - rect.setAttribute('width', this.width); - rect.setAttribute('height', this.height); - - svgText.setAttribute('x', this.width / 2); - svgText.setAttribute('y', this.height - Blockly.FlyoutButton.MARGIN); - - this.updateTransform_(); - return this.svgGroup_; -}; - -/** - * Correctly position the flyout button and make it visible. - */ -Blockly.FlyoutButton.prototype.show = function() { - this.updateTransform_(); - this.svgGroup_.setAttribute('display', 'block'); -}; - -/** - * Update svg attributes to match internal state. - */ -Blockly.FlyoutButton.prototype.updateTransform_ = function() { - this.svgGroup_.setAttribute('transform', 'translate(' + this.position_.x + - ',' + this.position_.y + ')'); -}; - -/** - * Move the button to the given x, y coordinates. - * @param {number} x The new x coordinate. - * @param {number} y The new y coordinate. - */ -Blockly.FlyoutButton.prototype.moveTo = function(x, y) { - this.position_.x = x; - this.position_.y = y; - this.updateTransform_(); -}; - -/** - * Dispose of this button. - */ -Blockly.FlyoutButton.prototype.dispose = function() { - if (this.svgGroup_) { - goog.dom.removeNode(this.svgGroup_); - this.svgGroup_ = null; - } - this.workspace_ = null; - this.targetWorkspace_ = null; -}; - -/** - * Do something when the button is clicked. - * @param {!Event} e Mouse up event. - */ -Blockly.FlyoutButton.prototype.onMouseUp = function(e) { - // Don't scroll the page. - e.preventDefault(); - // Don't propagate mousewheel event (zooming). - e.stopPropagation(); - // Stop binding to mouseup and mousemove events--flyout mouseup would normally - // do this, but we're skipping that. - Blockly.Flyout.terminateDrag_(); - Blockly.Variables.createVariable(this.targetWorkspace_); -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/generator.js b/backend/_pv_1_3_5/static/blockly/core/generator.js deleted file mode 100755 index fecc35531..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/generator.js +++ /dev/null @@ -1,369 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Utility functions for generating executable code from - * Blockly code. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Generator'); - -goog.require('Blockly.Block'); -goog.require('goog.asserts'); - - -/** - * Class for a code generator that translates the blocks into a language. - * @param {string} name Language name of this generator. - * @constructor - */ -Blockly.Generator = function(name) { - this.name_ = name; - this.FUNCTION_NAME_PLACEHOLDER_REGEXP_ = - new RegExp(this.FUNCTION_NAME_PLACEHOLDER_, 'g'); -}; - -/** - * Category to separate generated function names from variables and procedures. - */ -Blockly.Generator.NAME_TYPE = 'generated_function'; - -/** - * Arbitrary code to inject into locations that risk causing infinite loops. - * Any instances of '%1' will be replaced by the block ID that failed. - * E.g. ' checkTimeout(%1);\n' - * @type {?string} - */ -Blockly.Generator.prototype.INFINITE_LOOP_TRAP = null; - -/** - * Arbitrary code to inject before every statement. - * Any instances of '%1' will be replaced by the block ID of the statement. - * E.g. 'highlight(%1);\n' - * @type {?string} - */ -Blockly.Generator.prototype.STATEMENT_PREFIX = null; - -/** - * The method of indenting. Defaults to two spaces, but language generators - * may override this to increase indent or change to tabs. - * @type {string} - */ -Blockly.Generator.prototype.INDENT = ' '; - -/** - * Maximum length for a comment before wrapping. Does not account for - * indenting level. - * @type {number} - */ -Blockly.Generator.prototype.COMMENT_WRAP = 60; - -/** - * List of outer-inner pairings that do NOT require parentheses. - * @type {!Array.>} - */ -Blockly.Generator.prototype.ORDER_OVERRIDES = []; - -/** - * Generate code for all blocks in the workspace to the specified language. - * @param {Blockly.Workspace} workspace Workspace to generate code from. - * @return {string} Generated code. - */ -Blockly.Generator.prototype.workspaceToCode = function(workspace) { - if (!workspace) { - // Backwards compatibility from before there could be multiple workspaces. - console.warn('No workspace specified in workspaceToCode call. Guessing.'); - workspace = Blockly.getMainWorkspace(); - } - var code = []; - this.init(workspace); - var blocks = workspace.getTopBlocks(true); - for (var x = 0, block; block = blocks[x]; x++) { - var line = this.blockToCode(block); - if (goog.isArray(line)) { - // Value blocks return tuples of code and operator order. - // Top-level blocks don't care about operator order. - line = line[0]; - } - if (line) { - if (block.outputConnection && this.scrubNakedValue) { - // This block is a naked value. Ask the language's code generator if - // it wants to append a semicolon, or something. - line = this.scrubNakedValue(line); - } - code.push(line); - } - } - code = code.join('\n'); // Blank line between each section. - code = this.finish(code); - // Final scrubbing of whitespace. - code = code.replace(/^\s+\n/, ''); - code = code.replace(/\n\s+$/, '\n'); - code = code.replace(/[ \t]+\n/g, '\n'); - return code; -}; - -// The following are some helpful functions which can be used by multiple -// languages. - -/** - * Prepend a common prefix onto each line of code. - * @param {string} text The lines of code. - * @param {string} prefix The common prefix. - * @return {string} The prefixed lines of code. - */ -Blockly.Generator.prototype.prefixLines = function(text, prefix) { - return prefix + text.replace(/(?!\n$)\n/g, '\n' + prefix); -}; - -/** - * Recursively spider a tree of blocks, returning all their comments. - * @param {!Blockly.Block} block The block from which to start spidering. - * @return {string} Concatenated list of comments. - */ -Blockly.Generator.prototype.allNestedComments = function(block) { - var comments = []; - var blocks = block.getDescendants(); - for (var i = 0; i < blocks.length; i++) { - var comment = blocks[i].getCommentText(); - if (comment) { - comments.push(comment); - } - } - // Append an empty string to create a trailing line break when joined. - if (comments.length) { - comments.push(''); - } - return comments.join('\n'); -}; - -/** - * Generate code for the specified block (and attached blocks). - * @param {Blockly.Block} block The block to generate code for. - * @return {string|!Array} For statement blocks, the generated code. - * For value blocks, an array containing the generated code and an - * operator order value. Returns '' if block is null. - */ -Blockly.Generator.prototype.blockToCode = function(block) { - if (!block) { - return ''; - } - if (block.disabled) { - // Skip past this block if it is disabled. - return this.blockToCode(block.getNextBlock()); - } - - var func = this[block.type]; - goog.asserts.assertFunction(func, - 'Language "%s" does not know how to generate code for block type "%s".', - this.name_, block.type); - // First argument to func.call is the value of 'this' in the generator. - // Prior to 24 September 2013 'this' was the only way to access the block. - // The current prefered method of accessing the block is through the second - // argument to func.call, which becomes the first parameter to the generator. - var code = func.call(block, block); - if (goog.isArray(code)) { - // Value blocks return tuples of code and operator order. - goog.asserts.assert(block.outputConnection, - 'Expecting string from statement block "%s".', block.type); - return [this.scrub_(block, code[0]), code[1]]; - } else if (goog.isString(code)) { - if (this.STATEMENT_PREFIX) { - code = this.STATEMENT_PREFIX.replace(/%1/g, '\'' + block.id + '\'') + - code; - } - return this.scrub_(block, code); - } else if (code === null) { - // Block has handled code generation itself. - return ''; - } else { - goog.asserts.fail('Invalid code generated: %s', code); - } -}; - -/** - * Generate code representing the specified value input. - * @param {!Blockly.Block} block The block containing the input. - * @param {string} name The name of the input. - * @param {number} outerOrder The maximum binding strength (minimum order value) - * of any operators adjacent to "block". - * @return {string} Generated code or '' if no blocks are connected or the - * specified input does not exist. - */ -Blockly.Generator.prototype.valueToCode = function(block, name, outerOrder) { - if (isNaN(outerOrder)) { - goog.asserts.fail('Expecting valid order from block "%s".', block.type); - } - var targetBlock = block.getInputTargetBlock(name); - if (!targetBlock) { - return ''; - } - var tuple = this.blockToCode(targetBlock); - if (tuple === '') { - // Disabled block. - return ''; - } - // Value blocks must return code and order of operations info. - // Statement blocks must only return code. - goog.asserts.assertArray(tuple, 'Expecting tuple from value block "%s".', - targetBlock.type); - var code = tuple[0]; - var innerOrder = tuple[1]; - if (isNaN(innerOrder)) { - goog.asserts.fail('Expecting valid order from value block "%s".', - targetBlock.type); - } - if (!code) { - return ''; - } - - // Add parentheses if needed. - var parensNeeded = false; - var outerOrderClass = Math.floor(outerOrder); - var innerOrderClass = Math.floor(innerOrder); - if (outerOrderClass <= innerOrderClass) { - if (outerOrderClass == innerOrderClass && - (outerOrderClass == 0 || outerOrderClass == 99)) { - // Don't generate parens around NONE-NONE and ATOMIC-ATOMIC pairs. - // 0 is the atomic order, 99 is the none order. No parentheses needed. - // In all known languages multiple such code blocks are not order - // sensitive. In fact in Python ('a' 'b') 'c' would fail. - } else { - // The operators outside this code are stonger than the operators - // inside this code. To prevent the code from being pulled apart, - // wrap the code in parentheses. - parensNeeded = true; - // Check for special exceptions. - for (var i = 0; i < this.ORDER_OVERRIDES.length; i++) { - if (this.ORDER_OVERRIDES[i][0] == outerOrder && - this.ORDER_OVERRIDES[i][1] == innerOrder) { - parensNeeded = false; - break; - } - } - } - } - if (parensNeeded) { - // Technically, this should be handled on a language-by-language basis. - // However all known (sane) languages use parentheses for grouping. - code = '(' + code + ')'; - } - return code; -}; - -/** - * Generate code representing the statement. Indent the code. - * @param {!Blockly.Block} block The block containing the input. - * @param {string} name The name of the input. - * @return {string} Generated code or '' if no blocks are connected. - */ -Blockly.Generator.prototype.statementToCode = function(block, name) { - var targetBlock = block.getInputTargetBlock(name); - var code = this.blockToCode(targetBlock); - // Value blocks must return code and order of operations info. - // Statement blocks must only return code. - goog.asserts.assertString(code, 'Expecting code from statement block "%s".', - targetBlock && targetBlock.type); - if (code) { - code = this.prefixLines(/** @type {string} */ (code), this.INDENT); - } - return code; -}; - -/** - * Add an infinite loop trap to the contents of a loop. - * If loop is empty, add a statment prefix for the loop block. - * @param {string} branch Code for loop contents. - * @param {string} id ID of enclosing block. - * @return {string} Loop contents, with infinite loop trap added. - */ -Blockly.Generator.prototype.addLoopTrap = function(branch, id) { - if (this.INFINITE_LOOP_TRAP) { - branch = this.INFINITE_LOOP_TRAP.replace(/%1/g, '\'' + id + '\'') + branch; - } - if (this.STATEMENT_PREFIX) { - branch += this.prefixLines(this.STATEMENT_PREFIX.replace(/%1/g, - '\'' + id + '\''), this.INDENT); - } - return branch; -}; - -/** - * Comma-separated list of reserved words. - * @type {string} - * @private - */ -Blockly.Generator.prototype.RESERVED_WORDS_ = ''; - -/** - * Add one or more words to the list of reserved words for this language. - * @param {string} words Comma-separated list of words to add to the list. - * No spaces. Duplicates are ok. - */ -Blockly.Generator.prototype.addReservedWords = function(words) { - this.RESERVED_WORDS_ += words + ','; -}; - -/** - * This is used as a placeholder in functions defined using - * Blockly.Generator.provideFunction_. It must not be legal code that could - * legitimately appear in a function definition (or comment), and it must - * not confuse the regular expression parser. - * @type {string} - * @private - */ -Blockly.Generator.prototype.FUNCTION_NAME_PLACEHOLDER_ = '{leCUI8hutHZI4480Dc}'; - -/** - * Define a function to be included in the generated code. - * The first time this is called with a given desiredName, the code is - * saved and an actual name is generated. Subsequent calls with the - * same desiredName have no effect but have the same return value. - * - * It is up to the caller to make sure the same desiredName is not - * used for different code values. - * - * The code gets output when Blockly.Generator.finish() is called. - * - * @param {string} desiredName The desired name of the function (e.g., isPrime). - * @param {!Array.} code A list of statements. Use ' ' for indents. - * @return {string} The actual name of the new function. This may differ - * from desiredName if the former has already been taken by the user. - * @private - */ -Blockly.Generator.prototype.provideFunction_ = function(desiredName, code) { - if (!this.definitions_[desiredName]) { - var functionName = this.variableDB_.getDistinctName(desiredName, - Blockly.Procedures.NAME_TYPE); - this.functionNames_[desiredName] = functionName; - var codeText = code.join('\n').replace( - this.FUNCTION_NAME_PLACEHOLDER_REGEXP_, functionName); - // Change all ' ' indents into the desired indent. - var oldCodeText; - while (oldCodeText != codeText) { - oldCodeText = codeText; - codeText = codeText.replace(/^(( )*) /gm, '$1' + this.INDENT); - } - this.definitions_[desiredName] = codeText; - } - return this.functionNames_[desiredName]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/icon.js b/backend/_pv_1_3_5/static/blockly/core/icon.js deleted file mode 100755 index b10e18148..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/icon.js +++ /dev/null @@ -1,203 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2013 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Object representing an icon on a block. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Icon'); - -goog.require('goog.dom'); -goog.require('goog.math.Coordinate'); - - -/** - * Class for an icon. - * @param {Blockly.Block} block The block associated with this icon. - * @constructor - */ -Blockly.Icon = function(block) { - this.block_ = block; -}; - -/** - * Does this icon get hidden when the block is collapsed. - */ -Blockly.Icon.prototype.collapseHidden = true; - -/** - * Height and width of icons. - */ -Blockly.Icon.prototype.SIZE = 17; - -/** - * Bubble UI (if visible). - * @type {Blockly.Bubble} - * @private - */ -Blockly.Icon.prototype.bubble_ = null; - -/** - * Absolute coordinate of icon's center. - * @type {goog.math.Coordinate} - * @private - */ -Blockly.Icon.prototype.iconXY_ = null; - -/** - * Create the icon on the block. - */ -Blockly.Icon.prototype.createIcon = function() { - if (this.iconGroup_) { - // Icon already exists. - return; - } - /* Here's the markup that will be generated: - - ... - - */ - this.iconGroup_ = Blockly.createSvgElement('g', - {'class': 'blocklyIconGroup'}, null); - if (this.block_.isInFlyout) { - Blockly.addClass_(/** @type {!Element} */ (this.iconGroup_), - 'blocklyIconGroupReadonly'); - } - this.drawIcon_(this.iconGroup_); - - this.block_.getSvgRoot().appendChild(this.iconGroup_); - Blockly.bindEvent_(this.iconGroup_, 'mouseup', this, this.iconClick_); - this.updateEditable(); -}; - -/** - * Dispose of this icon. - */ -Blockly.Icon.prototype.dispose = function() { - // Dispose of and unlink the icon. - goog.dom.removeNode(this.iconGroup_); - this.iconGroup_ = null; - // Dispose of and unlink the bubble. - this.setVisible(false); - this.block_ = null; -}; - -/** - * Add or remove the UI indicating if this icon may be clicked or not. - */ -Blockly.Icon.prototype.updateEditable = function() { -}; - -/** - * Is the associated bubble visible? - * @return {boolean} True if the bubble is visible. - */ -Blockly.Icon.prototype.isVisible = function() { - return !!this.bubble_; -}; - -/** - * Clicking on the icon toggles if the bubble is visible. - * @param {!Event} e Mouse click event. - * @private - */ -Blockly.Icon.prototype.iconClick_ = function(e) { - if (this.block_.workspace.isDragging()) { - // Drag operation is concluding. Don't open the editor. - return; - } - if (!this.block_.isInFlyout && !Blockly.isRightButton(e)) { - this.setVisible(!this.isVisible()); - } -}; - -/** - * Change the colour of the associated bubble to match its block. - */ -Blockly.Icon.prototype.updateColour = function() { - if (this.isVisible()) { - this.bubble_.setColour(this.block_.getColour()); - } -}; - -/** - * Render the icon. - * @param {number} cursorX Horizontal offset at which to position the icon. - * @return {number} Horizontal offset for next item to draw. - */ -Blockly.Icon.prototype.renderIcon = function(cursorX) { - if (this.collapseHidden && this.block_.isCollapsed()) { - this.iconGroup_.setAttribute('display', 'none'); - return cursorX; - } - this.iconGroup_.setAttribute('display', 'block'); - - var TOP_MARGIN = 5; - var width = this.SIZE; - if (this.block_.RTL) { - cursorX -= width; - } - this.iconGroup_.setAttribute('transform', - 'translate(' + cursorX + ',' + TOP_MARGIN + ')'); - this.computeIconLocation(); - if (this.block_.RTL) { - cursorX -= Blockly.BlockSvg.SEP_SPACE_X; - } else { - cursorX += width + Blockly.BlockSvg.SEP_SPACE_X; - } - return cursorX; -}; - -/** - * Notification that the icon has moved. Update the arrow accordingly. - * @param {!goog.math.Coordinate} xy Absolute location. - */ -Blockly.Icon.prototype.setIconLocation = function(xy) { - this.iconXY_ = xy; - if (this.isVisible()) { - this.bubble_.setAnchorLocation(xy); - } -}; - -/** - * Notification that the icon has moved, but we don't really know where. - * Recompute the icon's location from scratch. - */ -Blockly.Icon.prototype.computeIconLocation = function() { - // Find coordinates for the centre of the icon and update the arrow. - var blockXY = this.block_.getRelativeToSurfaceXY(); - var iconXY = Blockly.getRelativeXY_(this.iconGroup_); - var newXY = new goog.math.Coordinate( - blockXY.x + iconXY.x + this.SIZE / 2, - blockXY.y + iconXY.y + this.SIZE / 2); - if (!goog.math.Coordinate.equals(this.getIconLocation(), newXY)) { - this.setIconLocation(newXY); - } -}; - -/** - * Returns the center of the block's icon relative to the surface. - * @return {!goog.math.Coordinate} Object with x and y properties. - */ -Blockly.Icon.prototype.getIconLocation = function() { - return this.iconXY_; -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/inject.js b/backend/_pv_1_3_5/static/blockly/core/inject.js deleted file mode 100755 index 57e3e51f4..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/inject.js +++ /dev/null @@ -1,378 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2011 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Functions for injecting Blockly into a web page. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.inject'); - -goog.require('Blockly.Css'); -goog.require('Blockly.Options'); -goog.require('Blockly.WorkspaceSvg'); -goog.require('goog.dom'); -goog.require('goog.ui.Component'); -goog.require('goog.userAgent'); - - -/** - * Inject a Blockly editor into the specified container element (usually a div). - * @param {!Element|string} container Containing element, or its ID, - * or a CSS selector. - * @param {Object=} opt_options Optional dictionary of options. - * @return {!Blockly.Workspace} Newly created main workspace. - */ -Blockly.inject = function(container, opt_options) { - if (goog.isString(container)) { - container = document.getElementById(container) || - document.querySelector(container); - } - // Verify that the container is in document. - if (!goog.dom.contains(document, container)) { - throw 'Error: container is not in current document.'; - } - var options = new Blockly.Options(opt_options || {}); - var subContainer = goog.dom.createDom('div', 'injectionDiv'); - container.appendChild(subContainer); - var svg = Blockly.createDom_(subContainer, options); - var workspace = Blockly.createMainWorkspace_(svg, options); - Blockly.init_(workspace); - workspace.markFocused(); - Blockly.bindEvent_(svg, 'focus', workspace, workspace.markFocused); - Blockly.svgResize(workspace); - return workspace; -}; - -/** - * Create the SVG image. - * @param {!Element} container Containing element. - * @param {!Blockly.Options} options Dictionary of options. - * @return {!Element} Newly created SVG image. - * @private - */ -Blockly.createDom_ = function(container, options) { - // Sadly browsers (Chrome vs Firefox) are currently inconsistent in laying - // out content in RTL mode. Therefore Blockly forces the use of LTR, - // then manually positions content in RTL as needed. - container.setAttribute('dir', 'LTR'); - // Closure can be trusted to create HTML widgets with the proper direction. - goog.ui.Component.setDefaultRightToLeft(options.RTL); - - // Load CSS. - Blockly.Css.inject(options.hasCss, options.pathToMedia); - - // Build the SVG DOM. - /* - - ... - - */ - var svg = Blockly.createSvgElement('svg', { - 'xmlns': 'http://www.w3.org/2000/svg', - 'xmlns:html': 'http://www.w3.org/1999/xhtml', - 'xmlns:xlink': 'http://www.w3.org/1999/xlink', - 'version': '1.1', - 'class': 'blocklySvg' - }, container); - /* - - ... filters go here ... - - */ - var defs = Blockly.createSvgElement('defs', {}, svg); - var rnd = String(Math.random()).substring(2); - /* - - - - - - - - - */ - var embossFilter = Blockly.createSvgElement('filter', - {'id': 'blocklyEmbossFilter' + rnd}, defs); - Blockly.createSvgElement('feGaussianBlur', - {'in': 'SourceAlpha', 'stdDeviation': 1, 'result': 'blur'}, embossFilter); - var feSpecularLighting = Blockly.createSvgElement('feSpecularLighting', - {'in': 'blur', 'surfaceScale': 1, 'specularConstant': 0.5, - 'specularExponent': 10, 'lighting-color': 'white', 'result': 'specOut'}, - embossFilter); - Blockly.createSvgElement('fePointLight', - {'x': -5000, 'y': -10000, 'z': 20000}, feSpecularLighting); - Blockly.createSvgElement('feComposite', - {'in': 'specOut', 'in2': 'SourceAlpha', 'operator': 'in', - 'result': 'specOut'}, embossFilter); - Blockly.createSvgElement('feComposite', - {'in': 'SourceGraphic', 'in2': 'specOut', 'operator': 'arithmetic', - 'k1': 0, 'k2': 1, 'k3': 1, 'k4': 0}, embossFilter); - options.embossFilterId = embossFilter.id; - /* - - - - - */ - var disabledPattern = Blockly.createSvgElement('pattern', - {'id': 'blocklyDisabledPattern' + rnd, - 'patternUnits': 'userSpaceOnUse', - 'width': 10, 'height': 10}, defs); - Blockly.createSvgElement('rect', - {'width': 10, 'height': 10, 'fill': '#aaa'}, disabledPattern); - Blockly.createSvgElement('path', - {'d': 'M 0 0 L 10 10 M 10 0 L 0 10', 'stroke': '#cc0'}, disabledPattern); - options.disabledPatternId = disabledPattern.id; - /* - - - - - */ - var gridPattern = Blockly.createSvgElement('pattern', - {'id': 'blocklyGridPattern' + rnd, - 'patternUnits': 'userSpaceOnUse'}, defs); - if (options.gridOptions['length'] > 0 && options.gridOptions['spacing'] > 0) { - Blockly.createSvgElement('line', - {'stroke': options.gridOptions['colour']}, - gridPattern); - if (options.gridOptions['length'] > 1) { - Blockly.createSvgElement('line', - {'stroke': options.gridOptions['colour']}, - gridPattern); - } - // x1, y1, x1, x2 properties will be set later in updateGridPattern_. - } - options.gridPattern = gridPattern; - return svg; -}; - -/** - * Create a main workspace and add it to the SVG. - * @param {!Element} svg SVG element with pattern defined. - * @param {!Blockly.Options} options Dictionary of options. - * @return {!Blockly.Workspace} Newly created main workspace. - * @private - */ -Blockly.createMainWorkspace_ = function(svg, options) { - options.parentWorkspace = null; - var mainWorkspace = new Blockly.WorkspaceSvg(options); - mainWorkspace.scale = options.zoomOptions.startScale; - svg.appendChild(mainWorkspace.createDom('blocklyMainBackground')); - // A null translation will also apply the correct initial scale. - mainWorkspace.translate(0, 0); - mainWorkspace.markFocused(); - - if (!options.readOnly && !options.hasScrollbars) { - var workspaceChanged = function() { - if (Blockly.dragMode_ == Blockly.DRAG_NONE) { - var metrics = mainWorkspace.getMetrics(); - var edgeLeft = metrics.viewLeft + metrics.absoluteLeft; - var edgeTop = metrics.viewTop + metrics.absoluteTop; - if (metrics.contentTop < edgeTop || - metrics.contentTop + metrics.contentHeight > - metrics.viewHeight + edgeTop || - metrics.contentLeft < - (options.RTL ? metrics.viewLeft : edgeLeft) || - metrics.contentLeft + metrics.contentWidth > (options.RTL ? - metrics.viewWidth : metrics.viewWidth + edgeLeft)) { - // One or more blocks may be out of bounds. Bump them back in. - var MARGIN = 25; - var blocks = mainWorkspace.getTopBlocks(false); - for (var b = 0, block; block = blocks[b]; b++) { - var blockXY = block.getRelativeToSurfaceXY(); - var blockHW = block.getHeightWidth(); - // Bump any block that's above the top back inside. - var overflowTop = edgeTop + MARGIN - blockHW.height - blockXY.y; - if (overflowTop > 0) { - block.moveBy(0, overflowTop); - } - // Bump any block that's below the bottom back inside. - var overflowBottom = - edgeTop + metrics.viewHeight - MARGIN - blockXY.y; - if (overflowBottom < 0) { - block.moveBy(0, overflowBottom); - } - // Bump any block that's off the left back inside. - var overflowLeft = MARGIN + edgeLeft - - blockXY.x - (options.RTL ? 0 : blockHW.width); - if (overflowLeft > 0) { - block.moveBy(overflowLeft, 0); - } - // Bump any block that's off the right back inside. - var overflowRight = edgeLeft + metrics.viewWidth - MARGIN - - blockXY.x + (options.RTL ? blockHW.width : 0); - if (overflowRight < 0) { - block.moveBy(overflowRight, 0); - } - } - } - } - }; - mainWorkspace.addChangeListener(workspaceChanged); - } - // The SVG is now fully assembled. - Blockly.svgResize(mainWorkspace); - Blockly.WidgetDiv.createDom(); - Blockly.Tooltip.createDom(); - return mainWorkspace; -}; - -/** - * Initialize Blockly with various handlers. - * @param {!Blockly.Workspace} mainWorkspace Newly created main workspace. - * @private - */ -Blockly.init_ = function(mainWorkspace) { - var options = mainWorkspace.options; - var svg = mainWorkspace.getParentSvg(); - - // Supress the browser's context menu. - Blockly.bindEvent_(svg, 'contextmenu', null, - function(e) { - if (!Blockly.isTargetInput_(e)) { - e.preventDefault(); - } - }); - - var workspaceResizeHandler = Blockly.bindEvent_(window, 'resize', null, - function() { - Blockly.hideChaff(true); - Blockly.svgResize(mainWorkspace); - }); - mainWorkspace.setResizeHandlerWrapper(workspaceResizeHandler); - - Blockly.inject.bindDocumentEvents_(); - - if (options.languageTree) { - if (mainWorkspace.toolbox_) { - mainWorkspace.toolbox_.init(mainWorkspace); - } else if (mainWorkspace.flyout_) { - // Build a fixed flyout with the root blocks. - mainWorkspace.flyout_.init(mainWorkspace); - mainWorkspace.flyout_.show(options.languageTree.childNodes); - mainWorkspace.flyout_.scrollToStart(); - // Translate the workspace sideways to avoid the fixed flyout. - mainWorkspace.scrollX = mainWorkspace.flyout_.width_; - if (options.toolboxPosition == Blockly.TOOLBOX_AT_RIGHT) { - mainWorkspace.scrollX *= -1; - } - mainWorkspace.translate(mainWorkspace.scrollX, 0); - } - } - - if (options.hasScrollbars) { - mainWorkspace.scrollbar = new Blockly.ScrollbarPair(mainWorkspace); - mainWorkspace.scrollbar.resize(); - } - - // Load the sounds. - if (options.hasSounds) { - Blockly.inject.loadSounds_(options.pathToMedia, mainWorkspace); - } -}; - -/** - * Bind document events, but only once. Destroying and reinjecting Blockly - * should not bind again. - * Bind events for scrolling the workspace. - * Most of these events should be bound to the SVG's surface. - * However, 'mouseup' has to be on the whole document so that a block dragged - * out of bounds and released will know that it has been released. - * Also, 'keydown' has to be on the whole document since the browser doesn't - * understand a concept of focus on the SVG image. - * @private - */ -Blockly.inject.bindDocumentEvents_ = function() { - if (!Blockly.documentEventsBound_) { - Blockly.bindEvent_(document, 'keydown', null, Blockly.onKeyDown_); - Blockly.bindEvent_(document, 'touchend', null, Blockly.longStop_); - Blockly.bindEvent_(document, 'touchcancel', null, Blockly.longStop_); - // Don't use bindEvent_ for document's mouseup since that would create a - // corresponding touch handler that would squeltch the ability to interact - // with non-Blockly elements. - document.addEventListener('mouseup', Blockly.onMouseUp_, false); - // Some iPad versions don't fire resize after portrait to landscape change. - if (goog.userAgent.IPAD) { - Blockly.bindEvent_(window, 'orientationchange', document, function() { - // TODO(#397): Fix for multiple blockly workspaces. - Blockly.svgResize(Blockly.getMainWorkspace()); - }); - } - } - Blockly.documentEventsBound_ = true; -}; - -/** - * Load sounds for the given workspace. - * @param {string} pathToMedia The path to the media directory. - * @param {!Blockly.Workspace} workspace The workspace to load sounds for. - * @private - */ -Blockly.inject.loadSounds_ = function(pathToMedia, workspace) { - workspace.loadAudio_( - [pathToMedia + 'click.mp3', - pathToMedia + 'click.wav', - pathToMedia + 'click.ogg'], 'click'); - workspace.loadAudio_( - [pathToMedia + 'disconnect.wav', - pathToMedia + 'disconnect.mp3', - pathToMedia + 'disconnect.ogg'], 'disconnect'); - workspace.loadAudio_( - [pathToMedia + 'delete.mp3', - pathToMedia + 'delete.ogg', - pathToMedia + 'delete.wav'], 'delete'); - - // Bind temporary hooks that preload the sounds. - var soundBinds = []; - var unbindSounds = function() { - while (soundBinds.length) { - Blockly.unbindEvent_(soundBinds.pop()); - } - workspace.preloadAudio_(); - }; - // Android ignores any sound not loaded as a result of a user action. - soundBinds.push( - Blockly.bindEvent_(document, 'mousemove', null, unbindSounds)); - soundBinds.push( - Blockly.bindEvent_(document, 'touchstart', null, unbindSounds)); -}; - -/** - * Modify the block tree on the existing toolbox. - * @param {Node|string} tree DOM tree of blocks, or text representation of same. - */ -Blockly.updateToolbox = function(tree) { - console.warn('Deprecated call to Blockly.updateToolbox, ' + - 'use workspace.updateToolbox instead.'); - Blockly.getMainWorkspace().updateToolbox(tree); -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/input.js b/backend/_pv_1_3_5/static/blockly/core/input.js deleted file mode 100755 index 4b4eb1df9..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/input.js +++ /dev/null @@ -1,241 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Object representing an input (value, statement, or dummy). - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Input'); - -goog.require('Blockly.Connection'); -goog.require('Blockly.FieldLabel'); -goog.require('goog.asserts'); - - -/** - * Class for an input with an optional field. - * @param {number} type The type of the input. - * @param {string} name Language-neutral identifier which may used to find this - * input again. - * @param {!Blockly.Block} block The block containing this input. - * @param {Blockly.Connection} connection Optional connection for this input. - * @constructor - */ -Blockly.Input = function(type, name, block, connection) { - /** @type {number} */ - this.type = type; - /** @type {string} */ - this.name = name; - /** - * @type {!Blockly.Block} - * @private - */ - this.sourceBlock_ = block; - /** @type {Blockly.Connection} */ - this.connection = connection; - /** @type {!Array.} */ - this.fieldRow = []; -}; - -/** - * Alignment of input's fields (left, right or centre). - * @type {number} - */ -Blockly.Input.prototype.align = Blockly.ALIGN_LEFT; - -/** - * Is the input visible? - * @type {boolean} - * @private - */ -Blockly.Input.prototype.visible_ = true; - -/** - * Add an item to the end of the input's field row. - * @param {string|!Blockly.Field} field Something to add as a field. - * @param {string=} opt_name Language-neutral identifier which may used to find - * this field again. Should be unique to the host block. - * @return {!Blockly.Input} The input being append to (to allow chaining). - */ -Blockly.Input.prototype.appendField = function(field, opt_name) { - // Empty string, Null or undefined generates no field, unless field is named. - if (!field && !opt_name) { - return this; - } - // Generate a FieldLabel when given a plain text field. - if (goog.isString(field)) { - field = new Blockly.FieldLabel(/** @type {string} */ (field)); - } - field.setSourceBlock(this.sourceBlock_); - if (this.sourceBlock_.rendered) { - field.init(); - } - field.name = opt_name; - - if (field.prefixField) { - // Add any prefix. - this.appendField(field.prefixField); - } - // Add the field to the field row. - this.fieldRow.push(field); - if (field.suffixField) { - // Add any suffix. - this.appendField(field.suffixField); - } - - if (this.sourceBlock_.rendered) { - this.sourceBlock_.render(); - // Adding a field will cause the block to change shape. - this.sourceBlock_.bumpNeighbours_(); - } - return this; -}; - -/** - * Add an item to the end of the input's field row. - * @param {*} field Something to add as a field. - * @param {string=} opt_name Language-neutral identifier which may used to find - * this field again. Should be unique to the host block. - * @return {!Blockly.Input} The input being append to (to allow chaining). - * @deprecated December 2013 - */ -Blockly.Input.prototype.appendTitle = function(field, opt_name) { - console.warn('Deprecated call to appendTitle, use appendField instead.'); - return this.appendField(field, opt_name); -}; - -/** - * Remove a field from this input. - * @param {string} name The name of the field. - * @throws {goog.asserts.AssertionError} if the field is not present. - */ -Blockly.Input.prototype.removeField = function(name) { - for (var i = 0, field; field = this.fieldRow[i]; i++) { - if (field.name === name) { - field.dispose(); - this.fieldRow.splice(i, 1); - if (this.sourceBlock_.rendered) { - this.sourceBlock_.render(); - // Removing a field will cause the block to change shape. - this.sourceBlock_.bumpNeighbours_(); - } - return; - } - } - goog.asserts.fail('Field "%s" not found.', name); -}; - -/** - * Gets whether this input is visible or not. - * @return {boolean} True if visible. - */ -Blockly.Input.prototype.isVisible = function() { - return this.visible_; -}; - -/** - * Sets whether this input is visible or not. - * Used to collapse/uncollapse a block. - * @param {boolean} visible True if visible. - * @return {!Array.} List of blocks to render. - */ -Blockly.Input.prototype.setVisible = function(visible) { - var renderList = []; - if (this.visible_ == visible) { - return renderList; - } - this.visible_ = visible; - - var display = visible ? 'block' : 'none'; - for (var y = 0, field; field = this.fieldRow[y]; y++) { - field.setVisible(visible); - } - if (this.connection) { - // Has a connection. - if (visible) { - renderList = this.connection.unhideAll(); - } else { - this.connection.hideAll(); - } - var child = this.connection.targetBlock(); - if (child) { - child.getSvgRoot().style.display = display; - if (!visible) { - child.rendered = false; - } - } - } - return renderList; -}; - -/** - * Change a connection's compatibility. - * @param {string|Array.|null} check Compatible value type or - * list of value types. Null if all types are compatible. - * @return {!Blockly.Input} The input being modified (to allow chaining). - */ -Blockly.Input.prototype.setCheck = function(check) { - if (!this.connection) { - throw 'This input does not have a connection.'; - } - this.connection.setCheck(check); - return this; -}; - -/** - * Change the alignment of the connection's field(s). - * @param {number} align One of Blockly.ALIGN_LEFT, ALIGN_CENTRE, ALIGN_RIGHT. - * In RTL mode directions are reversed, and ALIGN_RIGHT aligns to the left. - * @return {!Blockly.Input} The input being modified (to allow chaining). - */ -Blockly.Input.prototype.setAlign = function(align) { - this.align = align; - if (this.sourceBlock_.rendered) { - this.sourceBlock_.render(); - } - return this; -}; - -/** - * Initialize the fields on this input. - */ -Blockly.Input.prototype.init = function() { - if (!this.sourceBlock_.workspace.rendered) { - return; // Headless blocks don't need fields initialized. - } - for (var i = 0; i < this.fieldRow.length; i++) { - this.fieldRow[i].init(); - } -}; - -/** - * Sever all links to this input. - */ -Blockly.Input.prototype.dispose = function() { - for (var i = 0, field; field = this.fieldRow[i]; i++) { - field.dispose(); - } - if (this.connection) { - this.connection.dispose(); - } - this.sourceBlock_ = null; -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/msg.js b/backend/_pv_1_3_5/static/blockly/core/msg.js deleted file mode 100755 index 4ebcad1ab..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/msg.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2013 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Empty name space for the Message singleton. - * @author scr@google.com (Sheridan Rawlins) - */ -'use strict'; - -/** - * Name space for the Msg singleton. - * Msg gets populated in the message files. - */ -goog.provide('Blockly.Msg'); - - -/** - * Back up original getMsg function. - * @type {!Function} - */ -goog.getMsgOrig = goog.getMsg; - -/** - * Gets a localized message. - * Overrides the default Closure function to check for a Blockly.Msg first. - * Used infrequently, only known case is TODAY button in date picker. - * @param {string} str Translatable string, places holders in the form {$foo}. - * @param {Object=} opt_values Maps place holder name to value. - * @return {string} message with placeholders filled. - * @suppress {duplicate} - */ -goog.getMsg = function(str, opt_values) { - var key = goog.getMsg.blocklyMsgMap[str]; - if (key) { - str = Blockly.Msg[key]; - } - return goog.getMsgOrig(str, opt_values); -}; - -/** - * Mapping of Closure messages to Blockly.Msg names. - */ -goog.getMsg.blocklyMsgMap = { - 'Today': 'TODAY' -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/mutator.js b/backend/_pv_1_3_5/static/blockly/core/mutator.js deleted file mode 100755 index 19a0fe86b..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/mutator.js +++ /dev/null @@ -1,389 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Object representing a mutator dialog. A mutator allows the - * user to change the shape of a block using a nested blocks editor. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Mutator'); - -goog.require('Blockly.Bubble'); -goog.require('Blockly.Icon'); -goog.require('Blockly.WorkspaceSvg'); -goog.require('goog.Timer'); -goog.require('goog.dom'); - - -/** - * Class for a mutator dialog. - * @param {!Array.} quarkNames List of names of sub-blocks for flyout. - * @extends {Blockly.Icon} - * @constructor - */ -Blockly.Mutator = function(quarkNames) { - Blockly.Mutator.superClass_.constructor.call(this, null); - this.quarkNames_ = quarkNames; -}; -goog.inherits(Blockly.Mutator, Blockly.Icon); - -/** - * Width of workspace. - * @private - */ -Blockly.Mutator.prototype.workspaceWidth_ = 0; - -/** - * Height of workspace. - * @private - */ -Blockly.Mutator.prototype.workspaceHeight_ = 0; - -/** - * Draw the mutator icon. - * @param {!Element} group The icon group. - * @private - */ -Blockly.Mutator.prototype.drawIcon_ = function(group) { - // Square with rounded corners. - Blockly.createSvgElement('rect', - {'class': 'blocklyIconShape', - 'rx': '4', 'ry': '4', - 'height': '16', 'width': '16'}, - group); - // Gear teeth. - Blockly.createSvgElement('path', - {'class': 'blocklyIconSymbol', - 'd': 'm4.203,7.296 0,1.368 -0.92,0.677 -0.11,0.41 0.9,1.559 0.41,0.11 1.043,-0.457 1.187,0.683 0.127,1.134 0.3,0.3 1.8,0 0.3,-0.299 0.127,-1.138 1.185,-0.682 1.046,0.458 0.409,-0.11 0.9,-1.559 -0.11,-0.41 -0.92,-0.677 0,-1.366 0.92,-0.677 0.11,-0.41 -0.9,-1.559 -0.409,-0.109 -1.046,0.458 -1.185,-0.682 -0.127,-1.138 -0.3,-0.299 -1.8,0 -0.3,0.3 -0.126,1.135 -1.187,0.682 -1.043,-0.457 -0.41,0.11 -0.899,1.559 0.108,0.409z'}, - group); - // Axle hole. - Blockly.createSvgElement('circle', - {'class': 'blocklyIconShape', 'r': '2.7', 'cx': '8', 'cy': '8'}, - group); -}; - -/** - * Clicking on the icon toggles if the mutator bubble is visible. - * Disable if block is uneditable. - * @param {!Event} e Mouse click event. - * @private - * @override - */ -Blockly.Mutator.prototype.iconClick_ = function(e) { - if (this.block_.isEditable()) { - Blockly.Icon.prototype.iconClick_.call(this, e); - } -}; - -/** - * Create the editor for the mutator's bubble. - * @return {!Element} The top-level node of the editor. - * @private - */ -Blockly.Mutator.prototype.createEditor_ = function() { - /* Create the editor. Here's the markup that will be generated: - - [Workspace] - - */ - this.svgDialog_ = Blockly.createSvgElement('svg', - {'x': Blockly.Bubble.BORDER_WIDTH, 'y': Blockly.Bubble.BORDER_WIDTH}, - null); - // Convert the list of names into a list of XML objects for the flyout. - if (this.quarkNames_.length) { - var quarkXml = goog.dom.createDom('xml'); - for (var i = 0, quarkName; quarkName = this.quarkNames_[i]; i++) { - quarkXml.appendChild(goog.dom.createDom('block', {'type': quarkName})); - } - } else { - var quarkXml = null; - } - var workspaceOptions = { - languageTree: quarkXml, - parentWorkspace: this.block_.workspace, - pathToMedia: this.block_.workspace.options.pathToMedia, - RTL: this.block_.RTL, - toolboxPosition: this.block_.RTL ? Blockly.TOOLBOX_AT_RIGHT : - Blockly.TOOLBOX_AT_LEFT, - horizontalLayout: false, - getMetrics: this.getFlyoutMetrics_.bind(this), - setMetrics: null - }; - this.workspace_ = new Blockly.WorkspaceSvg(workspaceOptions); - this.workspace_.isMutator = true; - this.svgDialog_.appendChild( - this.workspace_.createDom('blocklyMutatorBackground')); - return this.svgDialog_; -}; - -/** - * Add or remove the UI indicating if this icon may be clicked or not. - */ -Blockly.Mutator.prototype.updateEditable = function() { - if (!this.block_.isInFlyout) { - if (this.block_.isEditable()) { - if (this.iconGroup_) { - Blockly.removeClass_(/** @type {!Element} */ (this.iconGroup_), - 'blocklyIconGroupReadonly'); - } - } else { - // Close any mutator bubble. Icon is not clickable. - this.setVisible(false); - if (this.iconGroup_) { - Blockly.addClass_(/** @type {!Element} */ (this.iconGroup_), - 'blocklyIconGroupReadonly'); - } - } - } - // Default behaviour for an icon. - Blockly.Icon.prototype.updateEditable.call(this); -}; - -/** - * Callback function triggered when the bubble has resized. - * Resize the workspace accordingly. - * @private - */ -Blockly.Mutator.prototype.resizeBubble_ = function() { - var doubleBorderWidth = 2 * Blockly.Bubble.BORDER_WIDTH; - var workspaceSize = this.workspace_.getCanvas().getBBox(); - var width; - if (this.block_.RTL) { - width = -workspaceSize.x; - } else { - width = workspaceSize.width + workspaceSize.x; - } - var height = workspaceSize.height + doubleBorderWidth * 3; - if (this.workspace_.flyout_) { - var flyoutMetrics = this.workspace_.flyout_.getMetrics_(); - height = Math.max(height, flyoutMetrics.contentHeight + 20); - } - width += doubleBorderWidth * 3; - // Only resize if the size difference is significant. Eliminates shuddering. - if (Math.abs(this.workspaceWidth_ - width) > doubleBorderWidth || - Math.abs(this.workspaceHeight_ - height) > doubleBorderWidth) { - // Record some layout information for getFlyoutMetrics_. - this.workspaceWidth_ = width; - this.workspaceHeight_ = height; - // Resize the bubble. - this.bubble_.setBubbleSize(width + doubleBorderWidth, - height + doubleBorderWidth); - this.svgDialog_.setAttribute('width', this.workspaceWidth_); - this.svgDialog_.setAttribute('height', this.workspaceHeight_); - } - - if (this.block_.RTL) { - // Scroll the workspace to always left-align. - var translation = 'translate(' + this.workspaceWidth_ + ',0)'; - this.workspace_.getCanvas().setAttribute('transform', translation); - } - this.workspace_.resize(); -}; - -/** - * Show or hide the mutator bubble. - * @param {boolean} visible True if the bubble should be visible. - */ -Blockly.Mutator.prototype.setVisible = function(visible) { - if (visible == this.isVisible()) { - // No change. - return; - } - Blockly.Events.fire( - new Blockly.Events.Ui(this.block_, 'mutatorOpen', !visible, visible)); - if (visible) { - // Create the bubble. - this.bubble_ = new Blockly.Bubble( - /** @type {!Blockly.WorkspaceSvg} */ (this.block_.workspace), - this.createEditor_(), this.block_.svgPath_, this.iconXY_, null, null); - var tree = this.workspace_.options.languageTree; - if (tree) { - this.workspace_.flyout_.init(this.workspace_); - this.workspace_.flyout_.show(tree.childNodes); - } - - this.rootBlock_ = this.block_.decompose(this.workspace_); - var blocks = this.rootBlock_.getDescendants(); - for (var i = 0, child; child = blocks[i]; i++) { - child.render(); - } - // The root block should not be dragable or deletable. - this.rootBlock_.setMovable(false); - this.rootBlock_.setDeletable(false); - if (this.workspace_.flyout_) { - var margin = this.workspace_.flyout_.CORNER_RADIUS * 2; - var x = this.workspace_.flyout_.width_ + margin; - } else { - var margin = 16; - var x = margin; - } - if (this.block_.RTL) { - x = -x; - } - this.rootBlock_.moveBy(x, margin); - // Save the initial connections, then listen for further changes. - if (this.block_.saveConnections) { - var thisMutator = this; - this.block_.saveConnections(this.rootBlock_); - this.sourceListener_ = function() { - thisMutator.block_.saveConnections(thisMutator.rootBlock_); - }; - this.block_.workspace.addChangeListener(this.sourceListener_); - } - this.resizeBubble_(); - // When the mutator's workspace changes, update the source block. - this.workspace_.addChangeListener(this.workspaceChanged_.bind(this)); - this.updateColour(); - } else { - // Dispose of the bubble. - this.svgDialog_ = null; - this.workspace_.dispose(); - this.workspace_ = null; - this.rootBlock_ = null; - this.bubble_.dispose(); - this.bubble_ = null; - this.workspaceWidth_ = 0; - this.workspaceHeight_ = 0; - if (this.sourceListener_) { - this.block_.workspace.removeChangeListener(this.sourceListener_); - this.sourceListener_ = null; - } - } -}; - -/** - * Update the source block when the mutator's blocks are changed. - * Bump down any block that's too high. - * Fired whenever a change is made to the mutator's workspace. - * @private - */ -Blockly.Mutator.prototype.workspaceChanged_ = function() { - if (Blockly.dragMode_ == Blockly.DRAG_NONE) { - var blocks = this.workspace_.getTopBlocks(false); - var MARGIN = 20; - for (var b = 0, block; block = blocks[b]; b++) { - var blockXY = block.getRelativeToSurfaceXY(); - var blockHW = block.getHeightWidth(); - if (blockXY.y + blockHW.height < MARGIN) { - // Bump any block that's above the top back inside. - block.moveBy(0, MARGIN - blockHW.height - blockXY.y); - } - } - } - - // When the mutator's workspace changes, update the source block. - if (this.rootBlock_.workspace == this.workspace_) { - Blockly.Events.setGroup(true); - var block = this.block_; - var oldMutationDom = block.mutationToDom(); - var oldMutation = oldMutationDom && Blockly.Xml.domToText(oldMutationDom); - // Switch off rendering while the source block is rebuilt. - var savedRendered = block.rendered; - block.rendered = false; - // Allow the source block to rebuild itself. - block.compose(this.rootBlock_); - // Restore rendering and show the changes. - block.rendered = savedRendered; - // Mutation may have added some elements that need initalizing. - block.initSvg(); - var newMutationDom = block.mutationToDom(); - var newMutation = newMutationDom && Blockly.Xml.domToText(newMutationDom); - if (oldMutation != newMutation) { - Blockly.Events.fire(new Blockly.Events.Change( - block, 'mutation', null, oldMutation, newMutation)); - // Ensure that any bump is part of this mutation's event group. - var group = Blockly.Events.getGroup(); - setTimeout(function() { - Blockly.Events.setGroup(group); - block.bumpNeighbours_(); - Blockly.Events.setGroup(false); - }, Blockly.BUMP_DELAY); - } - if (block.rendered) { - block.render(); - } - this.resizeBubble_(); - Blockly.Events.setGroup(false); - } -}; - -/** - * Return an object with all the metrics required to size scrollbars for the - * mutator flyout. The following properties are computed: - * .viewHeight: Height of the visible rectangle, - * .viewWidth: Width of the visible rectangle, - * .absoluteTop: Top-edge of view. - * .absoluteLeft: Left-edge of view. - * @return {!Object} Contains size and position metrics of mutator dialog's - * workspace. - * @private - */ -Blockly.Mutator.prototype.getFlyoutMetrics_ = function() { - return { - viewHeight: this.workspaceHeight_, - viewWidth: this.workspaceWidth_, - absoluteTop: 0, - absoluteLeft: 0 - }; -}; - -/** - * Dispose of this mutator. - */ -Blockly.Mutator.prototype.dispose = function() { - this.block_.mutator = null; - Blockly.Icon.prototype.dispose.call(this); -}; - -/** - * Reconnect an block to a mutated input. - * @param {Blockly.Connection} connectionChild Connection on child block. - * @param {!Blockly.Block} block Parent block. - * @param {string} inputName Name of input on parent block. - * @return {boolean} True iff a reconnection was made, false otherwise. - */ -Blockly.Mutator.reconnect = function(connectionChild, block, inputName) { - if (!connectionChild || !connectionChild.getSourceBlock().workspace) { - return false; // No connection or block has been deleted. - } - var connectionParent = block.getInput(inputName).connection; - var currentParent = connectionChild.targetBlock(); - if ((!currentParent || currentParent == block) && - connectionParent.targetConnection != connectionChild) { - if (connectionParent.isConnected()) { - // There's already something connected here. Get rid of it. - connectionParent.disconnect(); - } - connectionParent.connect(connectionChild); - return true; - } - return false; -}; - -// Export symbols that would otherwise be renamed by Closure compiler. -if (!goog.global['Blockly']) { - goog.global['Blockly'] = {}; -} -if (!goog.global['Blockly']['Mutator']) { - goog.global['Blockly']['Mutator'] = {}; -} -goog.global['Blockly']['Mutator']['reconnect'] = Blockly.Mutator.reconnect; diff --git a/backend/_pv_1_3_5/static/blockly/core/names.js b/backend/_pv_1_3_5/static/blockly/core/names.js deleted file mode 100755 index bfe942ab9..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/names.js +++ /dev/null @@ -1,143 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Utility functions for handling variables and procedure names. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Names'); - - -/** - * Class for a database of entity names (variables, functions, etc). - * @param {string} reservedWords A comma-separated string of words that are - * illegal for use as names in a language (e.g. 'new,if,this,...'). - * @param {string=} opt_variablePrefix Some languages need a '$' or a namespace - * before all variable names. - * @constructor - */ -Blockly.Names = function(reservedWords, opt_variablePrefix) { - this.variablePrefix_ = opt_variablePrefix || ''; - this.reservedDict_ = Object.create(null); - if (reservedWords) { - var splitWords = reservedWords.split(','); - for (var i = 0; i < splitWords.length; i++) { - this.reservedDict_[splitWords[i]] = true; - } - } - this.reset(); -}; - -/** - * When JavaScript (or most other languages) is generated, variable 'foo' and - * procedure 'foo' would collide. However, Blockly has no such problems since - * variable get 'foo' and procedure call 'foo' are unambiguous. - * Therefore, Blockly keeps a separate type name to disambiguate. - * getName('foo', 'variable') -> 'foo' - * getName('foo', 'procedure') -> 'foo2' - */ - -/** - * Empty the database and start from scratch. The reserved words are kept. - */ -Blockly.Names.prototype.reset = function() { - this.db_ = Object.create(null); - this.dbReverse_ = Object.create(null); -}; - -/** - * Convert a Blockly entity name to a legal exportable entity name. - * @param {string} name The Blockly entity name (no constraints). - * @param {string} type The type of entity in Blockly - * ('VARIABLE', 'PROCEDURE', 'BUILTIN', etc...). - * @return {string} An entity name legal for the exported language. - */ -Blockly.Names.prototype.getName = function(name, type) { - var normalized = name.toLowerCase() + '_' + type; - var prefix = (type == Blockly.Variables.NAME_TYPE) ? - this.variablePrefix_ : ''; - if (normalized in this.db_) { - return prefix + this.db_[normalized]; - } - var safeName = this.getDistinctName(name, type); - this.db_[normalized] = safeName.substr(prefix.length); - return safeName; -}; - -/** - * Convert a Blockly entity name to a legal exportable entity name. - * Ensure that this is a new name not overlapping any previously defined name. - * Also check against list of reserved words for the current language and - * ensure name doesn't collide. - * @param {string} name The Blockly entity name (no constraints). - * @param {string} type The type of entity in Blockly - * ('VARIABLE', 'PROCEDURE', 'BUILTIN', etc...). - * @return {string} An entity name legal for the exported language. - */ -Blockly.Names.prototype.getDistinctName = function(name, type) { - var safeName = this.safeName_(name); - var i = ''; - while (this.dbReverse_[safeName + i] || - (safeName + i) in this.reservedDict_) { - // Collision with existing name. Create a unique name. - i = i ? i + 1 : 2; - } - safeName += i; - this.dbReverse_[safeName] = true; - var prefix = (type == Blockly.Variables.NAME_TYPE) ? - this.variablePrefix_ : ''; - return prefix + safeName; -}; - -/** - * Given a proposed entity name, generate a name that conforms to the - * [_A-Za-z][_A-Za-z0-9]* format that most languages consider legal for - * variables. - * @param {string} name Potentially illegal entity name. - * @return {string} Safe entity name. - * @private - */ -Blockly.Names.prototype.safeName_ = function(name) { - if (!name) { - name = 'unnamed'; - } else { - // Unfortunately names in non-latin characters will look like - // _E9_9F_B3_E4_B9_90 which is pretty meaningless. - name = encodeURI(name.replace(/ /g, '_')).replace(/[^\w]/g, '_'); - // Most languages don't allow names with leading numbers. - if ('0123456789'.indexOf(name[0]) != -1) { - name = 'my_' + name; - } - } - return name; -}; - -/** - * Do the given two entity names refer to the same entity? - * Blockly names are case-insensitive. - * @param {string} name1 First name. - * @param {string} name2 Second name. - * @return {boolean} True if names are the same. - */ -Blockly.Names.equals = function(name1, name2) { - return name1.toLowerCase() == name2.toLowerCase(); -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/options.js b/backend/_pv_1_3_5/static/blockly/core/options.js deleted file mode 100755 index 268affa9b..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/options.js +++ /dev/null @@ -1,231 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Object that controls settings for the workspace. - * @author fenichel@google.com (Rachel Fenichel) - */ -'use strict'; - -goog.provide('Blockly.Options'); - - -/** - * Parse the user-specified options, using reasonable defaults where behaviour - * is unspecified. - * @param {!Object} options Dictionary of options. Specification: - * https://developers.google.com/blockly/guides/get-started/web#configuration - * @constructor - */ -Blockly.Options = function(options) { - var readOnly = !!options['readOnly']; - if (readOnly) { - var languageTree = null; - var hasCategories = false; - var hasTrashcan = false; - var hasCollapse = false; - var hasComments = false; - var hasDisable = false; - var hasSounds = false; - } else { - var languageTree = Blockly.Options.parseToolboxTree(options['toolbox']); - var hasCategories = Boolean(languageTree && - languageTree.getElementsByTagName('category').length); - var hasTrashcan = options['trashcan']; - if (hasTrashcan === undefined) { - hasTrashcan = hasCategories; - } - var hasCollapse = options['collapse']; - if (hasCollapse === undefined) { - hasCollapse = hasCategories; - } - var hasComments = options['comments']; - if (hasComments === undefined) { - hasComments = hasCategories; - } - var hasDisable = options['disable']; - if (hasDisable === undefined) { - hasDisable = hasCategories; - } - var hasSounds = options['sounds']; - if (hasSounds === undefined) { - hasSounds = true; - } - } - var rtl = !!options['rtl']; - var horizontalLayout = options['horizontalLayout']; - if (horizontalLayout === undefined) { - horizontalLayout = false; - } - var toolboxAtStart = options['toolboxPosition']; - if (toolboxAtStart === 'end') { - toolboxAtStart = false; - } else { - toolboxAtStart = true; - } - - if (horizontalLayout) { - var toolboxPosition = toolboxAtStart ? - Blockly.TOOLBOX_AT_TOP : Blockly.TOOLBOX_AT_BOTTOM; - } else { - var toolboxPosition = (toolboxAtStart == rtl) ? - Blockly.TOOLBOX_AT_RIGHT : Blockly.TOOLBOX_AT_LEFT; - } - - var hasScrollbars = options['scrollbars']; - if (hasScrollbars === undefined) { - hasScrollbars = hasCategories; - } - var hasCss = options['css']; - if (hasCss === undefined) { - hasCss = true; - } - var pathToMedia = 'https://blockly-demo.appspot.com/static/media/'; - if (options['media']) { - pathToMedia = options['media']; - } else if (options['path']) { - // 'path' is a deprecated option which has been replaced by 'media'. - pathToMedia = options['path'] + 'media/'; - } - - this.RTL = rtl; - this.collapse = hasCollapse; - this.comments = hasComments; - this.disable = hasDisable; - this.readOnly = readOnly; - this.maxBlocks = options['maxBlocks'] || Infinity; - this.pathToMedia = pathToMedia; - this.hasCategories = hasCategories; - this.hasScrollbars = hasScrollbars; - this.hasTrashcan = hasTrashcan; - this.hasSounds = hasSounds; - this.hasCss = hasCss; - this.horizontalLayout = horizontalLayout; - this.languageTree = languageTree; - this.gridOptions = Blockly.Options.parseGridOptions_(options); - this.zoomOptions = Blockly.Options.parseZoomOptions_(options); - this.toolboxPosition = toolboxPosition; -}; - -/** - * @type {Blockly.Workspace} the parent of the current workspace, or null if - * there is no parent workspace. - **/ -Blockly.Options.prototype.parentWorkspace = null; - -/** - * If set, sets the translation of the workspace to match the scrollbars. - */ -Blockly.Options.prototype.setMetrics = null; - -/** - * Return an object with the metrics required to size the workspace. - * @return {Object} Contains size and position metrics, or null. - */ -Blockly.Options.prototype.getMetrics = null; - -/** - * Parse the user-specified zoom options, using reasonable defaults where - * behaviour is unspecified. See zoom documentation: - * https://developers.google.com/blockly/guides/configure/web/zoom - * @param {!Object} options Dictionary of options. - * @return {!Object} A dictionary of normalized options. - * @private - */ -Blockly.Options.parseZoomOptions_ = function(options) { - var zoom = options['zoom'] || {}; - var zoomOptions = {}; - if (zoom['controls'] === undefined) { - zoomOptions.controls = false; - } else { - zoomOptions.controls = !!zoom['controls']; - } - if (zoom['wheel'] === undefined) { - zoomOptions.wheel = false; - } else { - zoomOptions.wheel = !!zoom['wheel']; - } - if (zoom['startScale'] === undefined) { - zoomOptions.startScale = 1; - } else { - zoomOptions.startScale = parseFloat(zoom['startScale']); - } - if (zoom['maxScale'] === undefined) { - zoomOptions.maxScale = 3; - } else { - zoomOptions.maxScale = parseFloat(zoom['maxScale']); - } - if (zoom['minScale'] === undefined) { - zoomOptions.minScale = 0.3; - } else { - zoomOptions.minScale = parseFloat(zoom['minScale']); - } - if (zoom['scaleSpeed'] === undefined) { - zoomOptions.scaleSpeed = 1.2; - } else { - zoomOptions.scaleSpeed = parseFloat(zoom['scaleSpeed']); - } - return zoomOptions; -}; - -/** - * Parse the user-specified grid options, using reasonable defaults where - * behaviour is unspecified. See grid documentation: - * https://developers.google.com/blockly/guides/configure/web/grid - * @param {!Object} options Dictionary of options. - * @return {!Object} A dictionary of normalized options. - * @private - */ -Blockly.Options.parseGridOptions_ = function(options) { - var grid = options['grid'] || {}; - var gridOptions = {}; - gridOptions.spacing = parseFloat(grid['spacing']) || 0; - gridOptions.colour = grid['colour'] || '#888'; - gridOptions.length = parseFloat(grid['length']) || 1; - gridOptions.snap = gridOptions.spacing > 0 && !!grid['snap']; - return gridOptions; -}; - -/** - * Parse the provided toolbox tree into a consistent DOM format. - * @param {Node|string} tree DOM tree of blocks, or text representation of same. - * @return {Node} DOM tree of blocks, or null. - */ -Blockly.Options.parseToolboxTree = function(tree) { - if (tree) { - if (typeof tree != 'string') { - if (typeof XSLTProcessor == 'undefined' && tree.outerHTML) { - // In this case the tree will not have been properly built by the - // browser. The HTML will be contained in the element, but it will - // not have the proper DOM structure since the browser doesn't support - // XSLTProcessor (XML -> HTML). This is the case in IE 9+. - tree = tree.outerHTML; - } else if (!(tree instanceof Element)) { - tree = null; - } - } - if (typeof tree == 'string') { - tree = Blockly.Xml.textToDom(tree); - } - } else { - tree = null; - } - return tree; -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/procedures.js b/backend/_pv_1_3_5/static/blockly/core/procedures.js deleted file mode 100755 index beb4a17b8..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/procedures.js +++ /dev/null @@ -1,287 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Utility functions for handling procedures. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Procedures'); - -goog.require('Blockly.Blocks'); -goog.require('Blockly.Field'); -goog.require('Blockly.Names'); -goog.require('Blockly.Workspace'); - - -/** - * Category to separate procedure names from variables and generated functions. - */ -Blockly.Procedures.NAME_TYPE = 'PROCEDURE'; - -/** - * Find all user-created procedure definitions in a workspace. - * @param {!Blockly.Workspace} root Root workspace. - * @return {!Array.>} Pair of arrays, the - * first contains procedures without return variables, the second with. - * Each procedure is defined by a three-element list of name, parameter - * list, and return value boolean. - */ -Blockly.Procedures.allProcedures = function(root) { - var blocks = root.getAllBlocks(); - var proceduresReturn = []; - var proceduresNoReturn = []; - for (var i = 0; i < blocks.length; i++) { - if (blocks[i].getProcedureDef) { - var tuple = blocks[i].getProcedureDef(); - if (tuple) { - if (tuple[2]) { - proceduresReturn.push(tuple); - } else { - proceduresNoReturn.push(tuple); - } - } - } - } - proceduresNoReturn.sort(Blockly.Procedures.procTupleComparator_); - proceduresReturn.sort(Blockly.Procedures.procTupleComparator_); - return [proceduresNoReturn, proceduresReturn]; -}; - -/** - * Comparison function for case-insensitive sorting of the first element of - * a tuple. - * @param {!Array} ta First tuple. - * @param {!Array} tb Second tuple. - * @return {number} -1, 0, or 1 to signify greater than, equality, or less than. - * @private - */ -Blockly.Procedures.procTupleComparator_ = function(ta, tb) { - return ta[0].toLowerCase().localeCompare(tb[0].toLowerCase()); -}; - -/** - * Ensure two identically-named procedures don't exist. - * @param {string} name Proposed procedure name. - * @param {!Blockly.Block} block Block to disambiguate. - * @return {string} Non-colliding name. - */ -Blockly.Procedures.findLegalName = function(name, block) { - if (block.isInFlyout) { - // Flyouts can have multiple procedures called 'do something'. - return name; - } - while (!Blockly.Procedures.isLegalName_(name, block.workspace, block)) { - // Collision with another procedure. - var r = name.match(/^(.*?)(\d+)$/); - if (!r) { - name += '2'; - } else { - name = r[1] + (parseInt(r[2], 10) + 1); - } - } - return name; -}; - -/** - * Does this procedure have a legal name? Illegal names include names of - * procedures already defined. - * @param {string} name The questionable name. - * @param {!Blockly.Workspace} workspace The workspace to scan for collisions. - * @param {Blockly.Block=} opt_exclude Optional block to exclude from - * comparisons (one doesn't want to collide with oneself). - * @return {boolean} True if the name is legal. - * @private - */ -Blockly.Procedures.isLegalName_ = function(name, workspace, opt_exclude) { - var blocks = workspace.getAllBlocks(); - // Iterate through every block and check the name. - for (var i = 0; i < blocks.length; i++) { - if (blocks[i] == opt_exclude) { - continue; - } - if (blocks[i].getProcedureDef) { - var procName = blocks[i].getProcedureDef(); - if (Blockly.Names.equals(procName[0], name)) { - return false; - } - } - } - return true; -}; - -/** - * Rename a procedure. Called by the editable field. - * @param {string} name The proposed new name. - * @return {string} The accepted name. - * @this {!Blockly.Field} - */ -Blockly.Procedures.rename = function(name) { - // Strip leading and trailing whitespace. Beyond this, all names are legal. - name = name.replace(/^[\s\xa0]+|[\s\xa0]+$/g, ''); - - // Ensure two identically-named procedures don't exist. - var legalName = Blockly.Procedures.findLegalName(name, this.sourceBlock_); - var oldName = this.text_; - if (oldName != name && oldName != legalName) { - // Rename any callers. - var blocks = this.sourceBlock_.workspace.getAllBlocks(); - for (var i = 0; i < blocks.length; i++) { - if (blocks[i].renameProcedure) { - blocks[i].renameProcedure(oldName, legalName); - } - } - } - return legalName; -}; - -/** - * Construct the blocks required by the flyout for the procedure category. - * @param {!Blockly.Workspace} workspace The workspace contianing procedures. - * @return {!Array.} Array of XML block elements. - */ -Blockly.Procedures.flyoutCategory = function(workspace) { - var xmlList = []; - if (Blockly.Blocks['procedures_defnoreturn']) { - // - var block = goog.dom.createDom('block'); - block.setAttribute('type', 'procedures_defnoreturn'); - block.setAttribute('gap', 16); - xmlList.push(block); - } - if (Blockly.Blocks['procedures_defreturn']) { - // - var block = goog.dom.createDom('block'); - block.setAttribute('type', 'procedures_defreturn'); - block.setAttribute('gap', 16); - xmlList.push(block); - } - if (Blockly.Blocks['procedures_ifreturn']) { - // - var block = goog.dom.createDom('block'); - block.setAttribute('type', 'procedures_ifreturn'); - block.setAttribute('gap', 16); - xmlList.push(block); - } - if (xmlList.length) { - // Add slightly larger gap between system blocks and user calls. - xmlList[xmlList.length - 1].setAttribute('gap', 24); - } - - function populateProcedures(procedureList, templateName) { - for (var i = 0; i < procedureList.length; i++) { - var name = procedureList[i][0]; - var args = procedureList[i][1]; - // - // - // - // - // - var block = goog.dom.createDom('block'); - block.setAttribute('type', templateName); - block.setAttribute('gap', 16); - var mutation = goog.dom.createDom('mutation'); - mutation.setAttribute('name', name); - block.appendChild(mutation); - for (var j = 0; j < args.length; j++) { - var arg = goog.dom.createDom('arg'); - arg.setAttribute('name', args[j]); - mutation.appendChild(arg); - } - xmlList.push(block); - } - } - - var tuple = Blockly.Procedures.allProcedures(workspace); - populateProcedures(tuple[0], 'procedures_callnoreturn'); - populateProcedures(tuple[1], 'procedures_callreturn'); - return xmlList; -}; - -/** - * Find all the callers of a named procedure. - * @param {string} name Name of procedure. - * @param {!Blockly.Workspace} workspace The workspace to find callers in. - * @return {!Array.} Array of caller blocks. - */ -Blockly.Procedures.getCallers = function(name, workspace) { - var callers = []; - var blocks = workspace.getAllBlocks(); - // Iterate through every block and check the name. - for (var i = 0; i < blocks.length; i++) { - if (blocks[i].getProcedureCall) { - var procName = blocks[i].getProcedureCall(); - // Procedure name may be null if the block is only half-built. - if (procName && Blockly.Names.equals(procName, name)) { - callers.push(blocks[i]); - } - } - } - return callers; -}; - -/** - * When a procedure definition changes its parameters, find and edit all its - * callers. - * @param {!Blockly.Block} defBlock Procedure definition block. - */ -Blockly.Procedures.mutateCallers = function(defBlock) { - var oldRecordUndo = Blockly.Events.recordUndo; - var name = defBlock.getProcedureDef()[0]; - var xmlElement = defBlock.mutationToDom(true); - var callers = Blockly.Procedures.getCallers(name, defBlock.workspace); - for (var i = 0, caller; caller = callers[i]; i++) { - var oldMutationDom = caller.mutationToDom(); - var oldMutation = oldMutationDom && Blockly.Xml.domToText(oldMutationDom); - caller.domToMutation(xmlElement); - var newMutationDom = caller.mutationToDom(); - var newMutation = newMutationDom && Blockly.Xml.domToText(newMutationDom); - if (oldMutation != newMutation) { - // Fire a mutation on every caller block. But don't record this as an - // undo action since it is deterministically tied to the procedure's - // definition mutation. - Blockly.Events.recordUndo = false; - Blockly.Events.fire(new Blockly.Events.Change( - caller, 'mutation', null, oldMutation, newMutation)); - Blockly.Events.recordUndo = oldRecordUndo; - } - } -}; - -/** - * Find the definition block for the named procedure. - * @param {string} name Name of procedure. - * @param {!Blockly.Workspace} workspace The workspace to search. - * @return {Blockly.Block} The procedure definition block, or null not found. - */ -Blockly.Procedures.getDefinition = function(name, workspace) { - // Assume that a procedure definition is a top block. - var blocks = workspace.getTopBlocks(false); - for (var i = 0; i < blocks.length; i++) { - if (blocks[i].getProcedureDef) { - var tuple = blocks[i].getProcedureDef(); - if (tuple && Blockly.Names.equals(tuple[0], name)) { - return blocks[i]; - } - } - } - return null; -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/rendered_connection.js b/backend/_pv_1_3_5/static/blockly/core/rendered_connection.js deleted file mode 100755 index dcb90f1b0..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/rendered_connection.js +++ /dev/null @@ -1,395 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Components for creating connections between blocks. - * @author fenichel@google.com (Rachel Fenichel) - */ -'use strict'; - -goog.provide('Blockly.RenderedConnection'); - -goog.require('Blockly.Connection'); - - -/** - * Class for a connection between blocks that may be rendered on screen. - * @param {!Blockly.Block} source The block establishing this connection. - * @param {number} type The type of the connection. - * @extends {Blockly.Connection} - * @constructor - */ -Blockly.RenderedConnection = function(source, type) { - Blockly.RenderedConnection.superClass_.constructor.call(this, source, type); - this.offsetInBlock_ = new goog.math.Coordinate(0, 0); -}; -goog.inherits(Blockly.RenderedConnection, Blockly.Connection); - -/** - * Returns the distance between this connection and another connection. - * @param {!Blockly.Connection} otherConnection The other connection to measure - * the distance to. - * @return {number} The distance between connections. - */ -Blockly.RenderedConnection.prototype.distanceFrom = function(otherConnection) { - var xDiff = this.x_ - otherConnection.x_; - var yDiff = this.y_ - otherConnection.y_; - return Math.sqrt(xDiff * xDiff + yDiff * yDiff); -}; - -/** - * Move the block(s) belonging to the connection to a point where they don't - * visually interfere with the specified connection. - * @param {!Blockly.Connection} staticConnection The connection to move away - * from. - * @private - */ -Blockly.RenderedConnection.prototype.bumpAwayFrom_ = function(staticConnection) { - if (Blockly.dragMode_ != Blockly.DRAG_NONE) { - // Don't move blocks around while the user is doing the same. - return; - } - // Move the root block. - var rootBlock = this.sourceBlock_.getRootBlock(); - if (rootBlock.isInFlyout) { - // Don't move blocks around in a flyout. - return; - } - var reverse = false; - if (!rootBlock.isMovable()) { - // Can't bump an uneditable block away. - // Check to see if the other block is movable. - rootBlock = staticConnection.getSourceBlock().getRootBlock(); - if (!rootBlock.isMovable()) { - return; - } - // Swap the connections and move the 'static' connection instead. - staticConnection = this; - reverse = true; - } - // Raise it to the top for extra visibility. - var selected = Blockly.selected == rootBlock; - selected || rootBlock.addSelect(); - var dx = (staticConnection.x_ + Blockly.SNAP_RADIUS) - this.x_; - var dy = (staticConnection.y_ + Blockly.SNAP_RADIUS) - this.y_; - if (reverse) { - // When reversing a bump due to an uneditable block, bump up. - dy = -dy; - } - if (rootBlock.RTL) { - dx = -dx; - } - rootBlock.moveBy(dx, dy); - selected || rootBlock.removeSelect(); -}; - -/** - * Change the connection's coordinates. - * @param {number} x New absolute x coordinate. - * @param {number} y New absolute y coordinate. - */ -Blockly.RenderedConnection.prototype.moveTo = function(x, y) { - // Remove it from its old location in the database (if already present) - if (this.inDB_) { - this.db_.removeConnection_(this); - } - this.x_ = x; - this.y_ = y; - // Insert it into its new location in the database. - if (!this.hidden_) { - this.db_.addConnection(this); - } -}; - -/** - * Change the connection's coordinates. - * @param {number} dx Change to x coordinate. - * @param {number} dy Change to y coordinate. - */ -Blockly.RenderedConnection.prototype.moveBy = function(dx, dy) { - this.moveTo(this.x_ + dx, this.y_ + dy); -}; - -/** - * Move this connection to the location given by its offset within the block and - * the coordinate of the block's top left corner. - * @param {!goog.math.Coordinate} blockTL The coordinate of the top left corner - * of the block. - */ -Blockly.RenderedConnection.prototype.moveToOffset = function(blockTL) { - this.moveTo(blockTL.x + this.offsetInBlock_.x, - blockTL.y + this.offsetInBlock_.y); -}; - -/** - * Set the offset of this connection relative to the top left of its block. - * @param {number} x The new relative x. - * @param {number} y The new relative y. - */ -Blockly.RenderedConnection.prototype.setOffsetInBlock = function(x, y) { - this.offsetInBlock_.x = x; - this.offsetInBlock_.y = y; -}; - -/** - * Move the blocks on either side of this connection right next to each other. - * @private - */ -Blockly.RenderedConnection.prototype.tighten_ = function() { - var dx = this.targetConnection.x_ - this.x_; - var dy = this.targetConnection.y_ - this.y_; - if (dx != 0 || dy != 0) { - var block = this.targetBlock(); - var svgRoot = block.getSvgRoot(); - if (!svgRoot) { - throw 'block is not rendered.'; - } - var xy = Blockly.getRelativeXY_(svgRoot); - block.getSvgRoot().setAttribute('transform', - 'translate(' + (xy.x - dx) + ',' + (xy.y - dy) + ')'); - block.moveConnections_(-dx, -dy); - } -}; - -/** - * Find the closest compatible connection to this connection. - * @param {number} maxLimit The maximum radius to another connection. - * @param {number} dx Horizontal offset between this connection's location - * in the database and the current location (as a result of dragging). - * @param {number} dy Vertical offset between this connection's location - * in the database and the current location (as a result of dragging). - * @return {!{connection: ?Blockly.Connection, radius: number}} Contains two - * properties: 'connection' which is either another connection or null, - * and 'radius' which is the distance. - */ -Blockly.RenderedConnection.prototype.closest = function(maxLimit, dx, dy) { - return this.dbOpposite_.searchForClosest(this, maxLimit, dx, dy); -}; - -/** - * Add highlighting around this connection. - */ -Blockly.RenderedConnection.prototype.highlight = function() { - var steps; - if (this.type == Blockly.INPUT_VALUE || this.type == Blockly.OUTPUT_VALUE) { - steps = 'm 0,0 ' + Blockly.BlockSvg.TAB_PATH_DOWN + ' v 5'; - } else { - steps = 'm -20,0 h 5 ' + Blockly.BlockSvg.NOTCH_PATH_LEFT + ' h 5'; - } - var xy = this.sourceBlock_.getRelativeToSurfaceXY(); - var x = this.x_ - xy.x; - var y = this.y_ - xy.y; - Blockly.Connection.highlightedPath_ = Blockly.createSvgElement('path', - {'class': 'blocklyHighlightedConnectionPath', - 'd': steps, - transform: 'translate(' + x + ',' + y + ')' + - (this.sourceBlock_.RTL ? ' scale(-1 1)' : '')}, - this.sourceBlock_.getSvgRoot()); -}; - -/** - * Unhide this connection, as well as all down-stream connections on any block - * attached to this connection. This happens when a block is expanded. - * Also unhides down-stream comments. - * @return {!Array.} List of blocks to render. - */ -Blockly.RenderedConnection.prototype.unhideAll = function() { - this.setHidden(false); - // All blocks that need unhiding must be unhidden before any rendering takes - // place, since rendering requires knowing the dimensions of lower blocks. - // Also, since rendering a block renders all its parents, we only need to - // render the leaf nodes. - var renderList = []; - if (this.type != Blockly.INPUT_VALUE && this.type != Blockly.NEXT_STATEMENT) { - // Only spider down. - return renderList; - } - var block = this.targetBlock(); - if (block) { - var connections; - if (block.isCollapsed()) { - // This block should only be partially revealed since it is collapsed. - connections = []; - block.outputConnection && connections.push(block.outputConnection); - block.nextConnection && connections.push(block.nextConnection); - block.previousConnection && connections.push(block.previousConnection); - } else { - // Show all connections of this block. - connections = block.getConnections_(true); - } - for (var i = 0; i < connections.length; i++) { - renderList.push.apply(renderList, connections[i].unhideAll()); - } - if (!renderList.length) { - // Leaf block. - renderList[0] = block; - } - } - return renderList; -}; - -/** - * Remove the highlighting around this connection. - */ -Blockly.RenderedConnection.prototype.unhighlight = function() { - goog.dom.removeNode(Blockly.Connection.highlightedPath_); - delete Blockly.Connection.highlightedPath_; -}; - -/** - * Set whether this connections is hidden (not tracked in a database) or not. - * @param {boolean} hidden True if connection is hidden. - */ -Blockly.RenderedConnection.prototype.setHidden = function(hidden) { - this.hidden_ = hidden; - if (hidden && this.inDB_) { - this.db_.removeConnection_(this); - } else if (!hidden && !this.inDB_) { - this.db_.addConnection(this); - } -}; - -/** - * Hide this connection, as well as all down-stream connections on any block - * attached to this connection. This happens when a block is collapsed. - * Also hides down-stream comments. - */ -Blockly.RenderedConnection.prototype.hideAll = function() { - this.setHidden(true); - if (this.targetConnection) { - var blocks = this.targetBlock().getDescendants(); - for (var i = 0; i < blocks.length; i++) { - var block = blocks[i]; - // Hide all connections of all children. - var connections = block.getConnections_(true); - for (var j = 0; j < connections.length; j++) { - connections[j].setHidden(true); - } - // Close all bubbles of all children. - var icons = block.getIcons(); - for (var j = 0; j < icons.length; j++) { - icons[j].setVisible(false); - } - } - } -}; - -/** - * Check if the two connections can be dragged to connect to each other. - * @param {!Blockly.Connection} candidate A nearby connection to check. - * @param {number} maxRadius The maximum radius allowed for connections. - * @return {boolean} True if the connection is allowed, false otherwise. - */ -Blockly.RenderedConnection.prototype.isConnectionAllowed = function(candidate, - maxRadius) { - if (this.distanceFrom(candidate) > maxRadius) { - return false; - } - - return Blockly.RenderedConnection.superClass_.isConnectionAllowed.call(this, - candidate); -}; - -/** - * Disconnect two blocks that are connected by this connection. - * @param {!Blockly.Block} parentBlock The superior block. - * @param {!Blockly.Block} childBlock The inferior block. - * @private - */ -Blockly.RenderedConnection.prototype.disconnectInternal_ = function(parentBlock, - childBlock) { - Blockly.RenderedConnection.superClass_.disconnectInternal_.call(this, - parentBlock, childBlock); - // Rerender the parent so that it may reflow. - if (parentBlock.rendered) { - parentBlock.render(); - } - if (childBlock.rendered) { - childBlock.updateDisabled(); - childBlock.render(); - } -}; - -/** - * Respawn the shadow block if there was one connected to the this connection. - * Render/rerender blocks as needed. - * @private - */ -Blockly.RenderedConnection.prototype.respawnShadow_ = function() { - var parentBlock = this.getSourceBlock(); - // Respawn the shadow block if there is one. - var shadow = this.getShadowDom(); - if (parentBlock.workspace && shadow && Blockly.Events.recordUndo) { - Blockly.RenderedConnection.superClass_.respawnShadow_.call(this); - var blockShadow = this.targetBlock(); - if (!blockShadow) { - throw 'Couldn\'t respawn the shadow block that should exist here.'; - } - blockShadow.initSvg(); - blockShadow.render(false); - if (parentBlock.rendered) { - parentBlock.render(); - } - } -}; - -/** - * Find all nearby compatible connections to this connection. - * Type checking does not apply, since this function is used for bumping. - * @param {number} maxLimit The maximum radius to another connection. - * @return {!Array.} List of connections. - * @private - */ -Blockly.RenderedConnection.prototype.neighbours_ = function(maxLimit) { - return this.dbOpposite_.getNeighbours(this, maxLimit); -}; - -/** - * Connect two connections together. This is the connection on the superior - * block. Rerender blocks as needed. - * @param {!Blockly.Connection} childConnection Connection on inferior block. - * @private - */ -Blockly.RenderedConnection.prototype.connect_ = function(childConnection) { - Blockly.RenderedConnection.superClass_.connect_.call(this, childConnection); - - var parentConnection = this; - var parentBlock = parentConnection.getSourceBlock(); - var childBlock = childConnection.getSourceBlock(); - - if (parentBlock.rendered) { - parentBlock.updateDisabled(); - } - if (childBlock.rendered) { - childBlock.updateDisabled(); - } - if (parentBlock.rendered && childBlock.rendered) { - if (parentConnection.type == Blockly.NEXT_STATEMENT || - parentConnection.type == Blockly.PREVIOUS_STATEMENT) { - // Child block may need to square off its corners if it is in a stack. - // Rendering a child will render its parent. - childBlock.render(); - } else { - // Child block does not change shape. Rendering the parent node will - // move its connected children into position. - parentBlock.render(); - } - } -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/scrollbar.js b/backend/_pv_1_3_5/static/blockly/core/scrollbar.js deleted file mode 100755 index da2dd942d..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/scrollbar.js +++ /dev/null @@ -1,750 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2011 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Library for creating scrollbars. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Scrollbar'); -goog.provide('Blockly.ScrollbarPair'); - -goog.require('goog.dom'); -goog.require('goog.events'); - - -/** - * Class for a pair of scrollbars. Horizontal and vertical. - * @param {!Blockly.Workspace} workspace Workspace to bind the scrollbars to. - * @constructor - */ -Blockly.ScrollbarPair = function(workspace) { - this.workspace_ = workspace; - this.hScroll = new Blockly.Scrollbar(workspace, true, true); - this.vScroll = new Blockly.Scrollbar(workspace, false, true); - this.corner_ = Blockly.createSvgElement('rect', - {'height': Blockly.Scrollbar.scrollbarThickness, - 'width': Blockly.Scrollbar.scrollbarThickness, - 'class': 'blocklyScrollbarBackground'}, null); - Blockly.Scrollbar.insertAfter_(this.corner_, workspace.getBubbleCanvas()); -}; - -/** - * Previously recorded metrics from the workspace. - * @type {Object} - * @private - */ -Blockly.ScrollbarPair.prototype.oldHostMetrics_ = null; - -/** - * Dispose of this pair of scrollbars. - * Unlink from all DOM elements to prevent memory leaks. - */ -Blockly.ScrollbarPair.prototype.dispose = function() { - goog.dom.removeNode(this.corner_); - this.corner_ = null; - this.workspace_ = null; - this.oldHostMetrics_ = null; - this.hScroll.dispose(); - this.hScroll = null; - this.vScroll.dispose(); - this.vScroll = null; -}; - -/** - * Recalculate both of the scrollbars' locations and lengths. - * Also reposition the corner rectangle. - */ -Blockly.ScrollbarPair.prototype.resize = function() { - // Look up the host metrics once, and use for both scrollbars. - var hostMetrics = this.workspace_.getMetrics(); - if (!hostMetrics) { - // Host element is likely not visible. - return; - } - - // Only change the scrollbars if there has been a change in metrics. - var resizeH = false; - var resizeV = false; - if (!this.oldHostMetrics_ || - this.oldHostMetrics_.viewWidth != hostMetrics.viewWidth || - this.oldHostMetrics_.viewHeight != hostMetrics.viewHeight || - this.oldHostMetrics_.absoluteTop != hostMetrics.absoluteTop || - this.oldHostMetrics_.absoluteLeft != hostMetrics.absoluteLeft) { - // The window has been resized or repositioned. - resizeH = true; - resizeV = true; - } else { - // Has the content been resized or moved? - if (!this.oldHostMetrics_ || - this.oldHostMetrics_.contentWidth != hostMetrics.contentWidth || - this.oldHostMetrics_.viewLeft != hostMetrics.viewLeft || - this.oldHostMetrics_.contentLeft != hostMetrics.contentLeft) { - resizeH = true; - } - if (!this.oldHostMetrics_ || - this.oldHostMetrics_.contentHeight != hostMetrics.contentHeight || - this.oldHostMetrics_.viewTop != hostMetrics.viewTop || - this.oldHostMetrics_.contentTop != hostMetrics.contentTop) { - resizeV = true; - } - } - if (resizeH) { - this.hScroll.resize(hostMetrics); - } - if (resizeV) { - this.vScroll.resize(hostMetrics); - } - - // Reposition the corner square. - if (!this.oldHostMetrics_ || - this.oldHostMetrics_.viewWidth != hostMetrics.viewWidth || - this.oldHostMetrics_.absoluteLeft != hostMetrics.absoluteLeft) { - this.corner_.setAttribute('x', this.vScroll.position_.x); - } - if (!this.oldHostMetrics_ || - this.oldHostMetrics_.viewHeight != hostMetrics.viewHeight || - this.oldHostMetrics_.absoluteTop != hostMetrics.absoluteTop) { - this.corner_.setAttribute('y', this.hScroll.position_.y); - } - - // Cache the current metrics to potentially short-cut the next resize event. - this.oldHostMetrics_ = hostMetrics; -}; - -/** - * Set the sliders of both scrollbars to be at a certain position. - * @param {number} x Horizontal scroll value. - * @param {number} y Vertical scroll value. - */ -Blockly.ScrollbarPair.prototype.set = function(x, y) { - // This function is equivalent to: - // this.hScroll.set(x); - // this.vScroll.set(y); - // However, that calls setMetrics twice which causes a chain of - // getAttribute->setAttribute->getAttribute resulting in an extra layout pass. - // Combining them speeds up rendering. - var xyRatio = {}; - - var hHandlePosition = x * this.hScroll.ratio_; - var vHandlePosition = y * this.vScroll.ratio_; - - var hBarLength = this.hScroll.scrollViewSize_; - var vBarLength = this.vScroll.scrollViewSize_; - - xyRatio.x = this.getRatio_(hHandlePosition, hBarLength); - xyRatio.y = this.getRatio_(vHandlePosition, vBarLength); - this.workspace_.setMetrics(xyRatio); - - this.hScroll.setHandlePosition(hHandlePosition); - this.vScroll.setHandlePosition(vHandlePosition); -}; - -/** - * Helper to calculate the ratio of handle position to scrollbar view size. - * @param {number} handlePosition The value of the handle. - * @param {number} viewSize The total size of the scrollbar's view. - * @return {number} Ratio. - * @private - */ -Blockly.ScrollbarPair.prototype.getRatio_ = function(handlePosition, viewSize) { - var ratio = handlePosition / viewSize; - if (isNaN(ratio)) { - return 0; - } - return ratio; -}; - -// -------------------------------------------------------------------- - -/** - * Class for a pure SVG scrollbar. - * This technique offers a scrollbar that is guaranteed to work, but may not - * look or behave like the system's scrollbars. - * @param {!Blockly.Workspace} workspace Workspace to bind the scrollbar to. - * @param {boolean} horizontal True if horizontal, false if vertical. - * @param {boolean=} opt_pair True if scrollbar is part of a horiz/vert pair. - * @constructor - */ -Blockly.Scrollbar = function(workspace, horizontal, opt_pair) { - this.workspace_ = workspace; - this.pair_ = opt_pair || false; - this.horizontal_ = horizontal; - this.oldHostMetrics_ = null; - - this.createDom_(); - - /** - * The upper left corner of the scrollbar's svg group. - * @type {goog.math.Coordinate} - * @private - */ - this.position_ = new goog.math.Coordinate(0, 0); - - if (horizontal) { - this.svgBackground_.setAttribute('height', - Blockly.Scrollbar.scrollbarThickness); - this.svgHandle_.setAttribute('height', - Blockly.Scrollbar.scrollbarThickness - 5); - this.svgHandle_.setAttribute('y', 2.5); - - this.lengthAttribute_ = 'width'; - this.positionAttribute_ = 'x'; - } else { - this.svgBackground_.setAttribute('width', - Blockly.Scrollbar.scrollbarThickness); - this.svgHandle_.setAttribute('width', - Blockly.Scrollbar.scrollbarThickness - 5); - this.svgHandle_.setAttribute('x', 2.5); - - this.lengthAttribute_ = 'height'; - this.positionAttribute_ = 'y'; - } - var scrollbar = this; - this.onMouseDownBarWrapper_ = Blockly.bindEvent_(this.svgBackground_, - 'mousedown', scrollbar, scrollbar.onMouseDownBar_); - this.onMouseDownHandleWrapper_ = Blockly.bindEvent_(this.svgHandle_, - 'mousedown', scrollbar, scrollbar.onMouseDownHandle_); -}; - -/** - * The size of the area within which the scrollbar handle can move. - * @type {number} - * @private - */ -Blockly.Scrollbar.prototype.scrollViewSize_ = 0; - -/** - * The length of the scrollbar handle. - * @type {number} - * @private - */ -Blockly.Scrollbar.prototype.handleLength_ = 0; - -/** - * The offset of the start of the handle from the start of the scrollbar range. - * @type {number} - * @private - */ -Blockly.Scrollbar.prototype.handlePosition_ = 0; - -/** - * Whether the scrollbar handle is visible. - * @type {boolean} - * @private - */ -Blockly.Scrollbar.prototype.isVisible_ = true; - -/** - * Width of vertical scrollbar or height of horizontal scrollbar. - * Increase the size of scrollbars on touch devices. - * Don't define if there is no document object (e.g. node.js). - */ -Blockly.Scrollbar.scrollbarThickness = 15; -if (goog.events.BrowserFeature.TOUCH_ENABLED) { - Blockly.Scrollbar.scrollbarThickness = 25; -} - -/** - * @param {!Object} first An object containing computed measurements of a - * workspace. - * @param {!Object} second Another object containing computed measurements of a - * workspace. - * @return {boolean} Whether the two sets of metrics are equivalent. - * @private - */ -Blockly.Scrollbar.metricsAreEquivalent_ = function(first, second) { - if (!(first && second)) { - return false; - } - - if (first.viewWidth != second.viewWidth || - first.viewHeight != second.viewHeight || - first.viewLeft != second.viewLeft || - first.viewTop != second.viewTop || - first.absoluteTop != second.absoluteTop || - first.absoluteLeft != second.absoluteLeft || - first.contentWidth != second.contentWidth || - first.contentHeight != second.contentHeight || - first.contentLeft != second.contentLeft || - first.contentTop != second.contentTop) { - return false; - } - - return true; -}; - -/** - * Dispose of this scrollbar. - * Unlink from all DOM elements to prevent memory leaks. - */ -Blockly.Scrollbar.prototype.dispose = function() { - this.onMouseUpHandle_(); - Blockly.unbindEvent_(this.onMouseDownBarWrapper_); - this.onMouseDownBarWrapper_ = null; - Blockly.unbindEvent_(this.onMouseDownHandleWrapper_); - this.onMouseDownHandleWrapper_ = null; - - goog.dom.removeNode(this.svgGroup_); - this.svgGroup_ = null; - this.svgBackground_ = null; - this.svgHandle_ = null; - this.workspace_ = null; -}; - -/** - * Set the length of the scrollbar's handle and change the SVG attribute - * accordingly. - * @param {number} newLength The new scrollbar handle length. - */ -Blockly.Scrollbar.prototype.setHandleLength_ = function(newLength) { - this.handleLength_ = newLength; - this.svgHandle_.setAttribute(this.lengthAttribute_, this.handleLength_); -}; - -/** - * Set the offset of the scrollbar's handle and change the SVG attribute - * accordingly. - * @param {number} newPosition The new scrollbar handle offset. - */ -Blockly.Scrollbar.prototype.setHandlePosition = function(newPosition) { - this.handlePosition_ = newPosition; - this.svgHandle_.setAttribute(this.positionAttribute_, this.handlePosition_); -}; - -/** - * Set the size of the scrollbar's background and change the SVG attribute - * accordingly. - * @param {number} newSize The new scrollbar background length. - * @private - */ -Blockly.Scrollbar.prototype.setScrollViewSize_ = function(newSize) { - this.scrollViewSize_ = newSize; - this.svgBackground_.setAttribute(this.lengthAttribute_, this.scrollViewSize_); -}; - -/** - * Set the position of the scrollbar's svg group. - * @param {number} x The new x coordinate. - * @param {number} y The new y coordinate. - */ -Blockly.Scrollbar.prototype.setPosition = function(x, y) { - this.position_.x = x; - this.position_.y = y; - - this.svgGroup_.setAttribute('transform', - 'translate(' + this.position_.x + ',' + this.position_.y + ')'); -}; - -/** - * Recalculate the scrollbar's location and its length. - * @param {Object=} opt_metrics A data structure of from the describing all the - * required dimensions. If not provided, it will be fetched from the host - * object. - */ -Blockly.Scrollbar.prototype.resize = function(opt_metrics) { - // Determine the location, height and width of the host element. - var hostMetrics = opt_metrics; - if (!hostMetrics) { - hostMetrics = this.workspace_.getMetrics(); - if (!hostMetrics) { - // Host element is likely not visible. - return; - } - } - - if (Blockly.Scrollbar.metricsAreEquivalent_(hostMetrics, - this.oldHostMetrics_)) { - return; - } - this.oldHostMetrics_ = hostMetrics; - - /* hostMetrics is an object with the following properties. - * .viewHeight: Height of the visible rectangle, - * .viewWidth: Width of the visible rectangle, - * .contentHeight: Height of the contents, - * .contentWidth: Width of the content, - * .viewTop: Offset of top edge of visible rectangle from parent, - * .viewLeft: Offset of left edge of visible rectangle from parent, - * .contentTop: Offset of the top-most content from the y=0 coordinate, - * .contentLeft: Offset of the left-most content from the x=0 coordinate, - * .absoluteTop: Top-edge of view. - * .absoluteLeft: Left-edge of view. - */ - if (this.horizontal_) { - this.resizeHorizontal_(hostMetrics); - } else { - this.resizeVertical_(hostMetrics); - } - // Resizing may have caused some scrolling. - this.onScroll_(); -}; - -/** - * Recalculate a horizontal scrollbar's location and length. - * @param {!Object} hostMetrics A data structure describing all the - * required dimensions, possibly fetched from the host object. - * @private - */ -Blockly.Scrollbar.prototype.resizeHorizontal_ = function(hostMetrics) { - // TODO: Inspect metrics to determine if we can get away with just a content - // resize. - this.resizeViewHorizontal(hostMetrics); -}; - -/** - * Recalculate a horizontal scrollbar's location on the screen and path length. - * This should be called when the layout or size of the window has changed. - * @param {!Object} hostMetrics A data structure describing all the - * required dimensions, possibly fetched from the host object. - */ -Blockly.Scrollbar.prototype.resizeViewHorizontal = function(hostMetrics) { - var viewSize = hostMetrics.viewWidth - 1; - if (this.pair_) { - // Shorten the scrollbar to make room for the corner square. - viewSize -= Blockly.Scrollbar.scrollbarThickness; - } - this.setScrollViewSize_(Math.max(0, viewSize)); - - var xCoordinate = hostMetrics.absoluteLeft + 0.5; - if (this.pair_ && this.workspace_.RTL) { - xCoordinate += Blockly.Scrollbar.scrollbarThickness; - } - - // Horizontal toolbar should always be just above the bottom of the workspace. - var yCoordinate = hostMetrics.absoluteTop + hostMetrics.viewHeight - - Blockly.Scrollbar.scrollbarThickness - 0.5; - this.setPosition(xCoordinate, yCoordinate); - - // If the view has been resized, a content resize will also be necessary. The - // reverse is not true. - this.resizeContentHorizontal(hostMetrics); -}; - -/** - * Recalculate a horizontal scrollbar's location within its path and length. - * This should be called when the contents of the workspace have changed. - * @param {!Object} hostMetrics A data structure describing all the - * required dimensions, possibly fetched from the host object. - */ -Blockly.Scrollbar.prototype.resizeContentHorizontal = function(hostMetrics) { - if (!this.pair_) { - // Only show the scrollbar if needed. - // Ideally this would also apply to scrollbar pairs, but that's a bigger - // headache (due to interactions with the corner square). - this.setVisible(this.scrollViewSize_ < hostMetrics.contentWidth); - } - - this.ratio_ = this.scrollViewSize_ / hostMetrics.contentWidth; - if (this.ratio_ == -Infinity || this.ratio_ == Infinity || - isNaN(this.ratio_)) { - this.ratio_ = 0; - } - - var handleLength = hostMetrics.viewWidth * this.ratio_; - this.setHandleLength_(Math.max(0, handleLength)); - - var handlePosition = (hostMetrics.viewLeft - hostMetrics.contentLeft) * - this.ratio_; - this.setHandlePosition(this.constrainHandle_(handlePosition)); -}; - -/** - * Recalculate a vertical scrollbar's location and length. - * @param {!Object} hostMetrics A data structure describing all the - * required dimensions, possibly fetched from the host object. - * @private - */ -Blockly.Scrollbar.prototype.resizeVertical_ = function(hostMetrics) { - // TODO: Inspect metrics to determine if we can get away with just a content - // resize. - this.resizeViewVertical(hostMetrics); -}; - -/** - * Recalculate a vertical scrollbar's location on the screen and path length. - * This should be called when the layout or size of the window has changed. - * @param {!Object} hostMetrics A data structure describing all the - * required dimensions, possibly fetched from the host object. - */ -Blockly.Scrollbar.prototype.resizeViewVertical = function(hostMetrics) { - var viewSize = hostMetrics.viewHeight - 1; - if (this.pair_) { - // Shorten the scrollbar to make room for the corner square. - viewSize -= Blockly.Scrollbar.scrollbarThickness; - } - this.setScrollViewSize_(Math.max(0, viewSize)); - - var xCoordinate = hostMetrics.absoluteLeft + 0.5; - if (!this.workspace_.RTL) { - xCoordinate += hostMetrics.viewWidth - - Blockly.Scrollbar.scrollbarThickness - 1; - } - var yCoordinate = hostMetrics.absoluteTop + 0.5; - this.setPosition(xCoordinate, yCoordinate); - - // If the view has been resized, a content resize will also be necessary. The - // reverse is not true. - this.resizeContentVertical(hostMetrics); -}; - -/** - * Recalculate a vertical scrollbar's location within its path and length. - * This should be called when the contents of the workspace have changed. - * @param {!Object} hostMetrics A data structure describing all the - * required dimensions, possibly fetched from the host object. - */ -Blockly.Scrollbar.prototype.resizeContentVertical = function(hostMetrics) { - if (!this.pair_) { - // Only show the scrollbar if needed. - this.setVisible(this.scrollViewSize_ < hostMetrics.contentHeight); - } - - this.ratio_ = this.scrollViewSize_ / hostMetrics.contentHeight; - if (this.ratio_ == -Infinity || this.ratio_ == Infinity || - isNaN(this.ratio_)) { - this.ratio_ = 0; - } - - var handleLength = hostMetrics.viewHeight * this.ratio_; - this.setHandleLength_(Math.max(0, handleLength)); - - var handlePosition = (hostMetrics.viewTop - hostMetrics.contentTop) * - this.ratio_; - this.setHandlePosition(this.constrainHandle_(handlePosition)); -}; - -/** - * Create all the DOM elements required for a scrollbar. - * The resulting widget is not sized. - * @private - */ -Blockly.Scrollbar.prototype.createDom_ = function() { - /* Create the following DOM: - - - - - */ - var className = 'blocklyScrollbar' + - (this.horizontal_ ? 'Horizontal' : 'Vertical'); - this.svgGroup_ = Blockly.createSvgElement('g', {'class': className}, null); - this.svgBackground_ = Blockly.createSvgElement('rect', - {'class': 'blocklyScrollbarBackground'}, this.svgGroup_); - var radius = Math.floor((Blockly.Scrollbar.scrollbarThickness - 5) / 2); - this.svgHandle_ = Blockly.createSvgElement('rect', - {'class': 'blocklyScrollbarHandle', 'rx': radius, 'ry': radius}, - this.svgGroup_); - Blockly.Scrollbar.insertAfter_(this.svgGroup_, - this.workspace_.getBubbleCanvas()); -}; - -/** - * Is the scrollbar visible. Non-paired scrollbars disappear when they aren't - * needed. - * @return {boolean} True if visible. - */ -Blockly.Scrollbar.prototype.isVisible = function() { - return this.isVisible_; -}; - -/** - * Set whether the scrollbar is visible. - * Only applies to non-paired scrollbars. - * @param {boolean} visible True if visible. - */ -Blockly.Scrollbar.prototype.setVisible = function(visible) { - if (visible == this.isVisible()) { - return; - } - // Ideally this would also apply to scrollbar pairs, but that's a bigger - // headache (due to interactions with the corner square). - if (this.pair_) { - throw 'Unable to toggle visibility of paired scrollbars.'; - } - - this.isVisible_ = visible; - - if (visible) { - this.svgGroup_.setAttribute('display', 'block'); - } else { - // Hide the scrollbar. - this.workspace_.setMetrics({x: 0, y: 0}); - this.svgGroup_.setAttribute('display', 'none'); - } -}; - -/** - * Scroll by one pageful. - * Called when scrollbar background is clicked. - * @param {!Event} e Mouse down event. - * @private - */ -Blockly.Scrollbar.prototype.onMouseDownBar_ = function(e) { - this.onMouseUpHandle_(); - if (Blockly.isRightButton(e)) { - // Right-click. - // Scrollbars have no context menu. - e.stopPropagation(); - return; - } - var mouseXY = Blockly.mouseToSvg(e, this.workspace_.getParentSvg(), - this.workspace_.getInverseScreenCTM()); - var mouseLocation = this.horizontal_ ? mouseXY.x : mouseXY.y; - - var handleXY = Blockly.getSvgXY_(this.svgHandle_, this.workspace_); - var handleStart = this.horizontal_ ? handleXY.x : handleXY.y; - var handlePosition = this.handlePosition_; - - var pageLength = this.handleLength_ * 0.95; - if (mouseLocation <= handleStart) { - // Decrease the scrollbar's value by a page. - handlePosition -= pageLength; - } else if (mouseLocation >= handleStart + this.handleLength_) { - // Increase the scrollbar's value by a page. - handlePosition += pageLength; - } - - this.setHandlePosition(this.constrainHandle_(handlePosition)); - - this.onScroll_(); - e.stopPropagation(); - e.preventDefault(); -}; - -/** - * Start a dragging operation. - * Called when scrollbar handle is clicked. - * @param {!Event} e Mouse down event. - * @private - */ -Blockly.Scrollbar.prototype.onMouseDownHandle_ = function(e) { - this.onMouseUpHandle_(); - if (Blockly.isRightButton(e)) { - // Right-click. - // Scrollbars have no context menu. - e.stopPropagation(); - return; - } - // Look up the current translation and record it. - this.startDragHandle = this.handlePosition_; - // Record the current mouse position. - this.startDragMouse = this.horizontal_ ? e.clientX : e.clientY; - Blockly.Scrollbar.onMouseUpWrapper_ = Blockly.bindEvent_(document, - 'mouseup', this, this.onMouseUpHandle_); - Blockly.Scrollbar.onMouseMoveWrapper_ = Blockly.bindEvent_(document, - 'mousemove', this, this.onMouseMoveHandle_); - e.stopPropagation(); - e.preventDefault(); -}; - -/** - * Drag the scrollbar's handle. - * @param {!Event} e Mouse up event. - * @private - */ -Blockly.Scrollbar.prototype.onMouseMoveHandle_ = function(e) { - var currentMouse = this.horizontal_ ? e.clientX : e.clientY; - var mouseDelta = currentMouse - this.startDragMouse; - var handlePosition = this.startDragHandle + mouseDelta; - // Position the bar. - this.setHandlePosition(this.constrainHandle_(handlePosition)); - this.onScroll_(); -}; - -/** - * Stop binding to the global mouseup and mousemove events. - * @private - */ -Blockly.Scrollbar.prototype.onMouseUpHandle_ = function() { - Blockly.hideChaff(true); - if (Blockly.Scrollbar.onMouseUpWrapper_) { - Blockly.unbindEvent_(Blockly.Scrollbar.onMouseUpWrapper_); - Blockly.Scrollbar.onMouseUpWrapper_ = null; - } - if (Blockly.Scrollbar.onMouseMoveWrapper_) { - Blockly.unbindEvent_(Blockly.Scrollbar.onMouseMoveWrapper_); - Blockly.Scrollbar.onMouseMoveWrapper_ = null; - } -}; - -/** - * Constrain the handle's position within the minimum (0) and maximum - * (length of scrollbar) values allowed for the scrollbar. - * @param {number} value Value that is potentially out of bounds. - * @return {number} Constrained value. - * @private - */ -Blockly.Scrollbar.prototype.constrainHandle_ = function(value) { - if (value <= 0 || isNaN(value) || this.scrollViewSize_ < this.handleLength_) { - value = 0; - } else { - value = Math.min(value, this.scrollViewSize_ - this.handleLength_); - } - return value; -}; - -/** - * Called when scrollbar is moved. - * @private - */ -Blockly.Scrollbar.prototype.onScroll_ = function() { - var ratio = this.handlePosition_ / this.scrollViewSize_; - if (isNaN(ratio)) { - ratio = 0; - } - var xyRatio = {}; - if (this.horizontal_) { - xyRatio.x = ratio; - } else { - xyRatio.y = ratio; - } - this.workspace_.setMetrics(xyRatio); -}; - -/** - * Set the scrollbar slider's position. - * @param {number} value The distance from the top/left end of the bar. - */ -Blockly.Scrollbar.prototype.set = function(value) { - this.setHandlePosition(this.constrainHandle_(value * this.ratio_)); - this.onScroll_(); -}; - -/** - * Insert a node after a reference node. - * Contrast with node.insertBefore function. - * @param {!Element} newNode New element to insert. - * @param {!Element} refNode Existing element to precede new node. - * @private - */ -Blockly.Scrollbar.insertAfter_ = function(newNode, refNode) { - var siblingNode = refNode.nextSibling; - var parentNode = refNode.parentNode; - if (!parentNode) { - throw 'Reference node has no parent.'; - } - if (siblingNode) { - parentNode.insertBefore(newNode, siblingNode); - } else { - parentNode.appendChild(newNode); - } -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/toolbox.js b/backend/_pv_1_3_5/static/blockly/core/toolbox.js deleted file mode 100755 index 5a5096c7a..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/toolbox.js +++ /dev/null @@ -1,650 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2011 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Toolbox from whence to create blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Toolbox'); - -goog.require('Blockly.Flyout'); -goog.require('goog.dom'); -goog.require('goog.dom.TagName'); -goog.require('goog.events'); -goog.require('goog.events.BrowserFeature'); -goog.require('goog.html.SafeHtml'); -goog.require('goog.html.SafeStyle'); -goog.require('goog.math.Rect'); -goog.require('goog.style'); -goog.require('goog.ui.tree.TreeControl'); -goog.require('goog.ui.tree.TreeNode'); - - -/** - * Class for a Toolbox. - * Creates the toolbox's DOM. - * @param {!Blockly.Workspace} workspace The workspace in which to create new - * blocks. - * @constructor - */ -Blockly.Toolbox = function(workspace) { - /** - * @type {!Blockly.Workspace} - * @private - */ - this.workspace_ = workspace; - - /** - * Is RTL vs LTR. - * @type {boolean} - */ - this.RTL = workspace.options.RTL; - - /** - * Whether the toolbox should be laid out horizontally. - * @type {boolean} - * @private - */ - this.horizontalLayout_ = workspace.options.horizontalLayout; - - /** - * Position of the toolbox and flyout relative to the workspace. - * @type {number} - */ - this.toolboxPosition = workspace.options.toolboxPosition; - - /** - * Configuration constants for Closure's tree UI. - * @type {Object.} - * @private - */ - this.config_ = { - indentWidth: 19, - cssRoot: 'blocklyTreeRoot', - cssHideRoot: 'blocklyHidden', - cssItem: '', - cssTreeRow: 'blocklyTreeRow', - cssItemLabel: 'blocklyTreeLabel', - cssTreeIcon: 'blocklyTreeIcon', - cssExpandedFolderIcon: 'blocklyTreeIconOpen', - cssFileIcon: 'blocklyTreeIconNone', - cssSelectedRow: 'blocklyTreeSelected' - }; - - - /** - * Configuration constants for tree separator. - * @type {Object.} - * @private - */ - this.treeSeparatorConfig_ = { - cssTreeRow: 'blocklyTreeSeparator' - }; - - if (this.horizontalLayout_) { - this.config_['cssTreeRow'] = - this.config_['cssTreeRow'] + - (workspace.RTL ? - ' blocklyHorizontalTreeRtl' : ' blocklyHorizontalTree'); - - this.treeSeparatorConfig_['cssTreeRow'] = - 'blocklyTreeSeparatorHorizontal ' + - (workspace.RTL ? - 'blocklyHorizontalTreeRtl' : 'blocklyHorizontalTree'); - this.config_['cssTreeIcon'] = ''; - } -}; - -/** - * Width of the toolbox, which changes only in vertical layout. - * @type {number} - */ -Blockly.Toolbox.prototype.width = 0; - -/** - * Height of the toolbox, which changes only in horizontal layout. - * @type {number} - */ -Blockly.Toolbox.prototype.height = 0; - -/** - * The SVG group currently selected. - * @type {SVGGElement} - * @private - */ -Blockly.Toolbox.prototype.selectedOption_ = null; - -/** - * The tree node most recently selected. - * @type {goog.ui.tree.BaseNode} - * @private - */ -Blockly.Toolbox.prototype.lastCategory_ = null; - -/** - * Initializes the toolbox. - */ -Blockly.Toolbox.prototype.init = function() { - var workspace = this.workspace_; - var svg = this.workspace_.getParentSvg(); - - // Create an HTML container for the Toolbox menu. - this.HtmlDiv = - goog.dom.createDom(goog.dom.TagName.DIV, 'blocklyToolboxDiv'); - this.HtmlDiv.setAttribute('dir', workspace.RTL ? 'RTL' : 'LTR'); - svg.parentNode.insertBefore(this.HtmlDiv, svg); - - // Clicking on toolbox closes popups. - Blockly.bindEvent_(this.HtmlDiv, 'mousedown', this, - function(e) { - if (Blockly.isRightButton(e) || e.target == this.HtmlDiv) { - // Close flyout. - Blockly.hideChaff(false); - } else { - // Just close popups. - Blockly.hideChaff(true); - } - }); - var workspaceOptions = { - disabledPatternId: workspace.options.disabledPatternId, - parentWorkspace: workspace, - RTL: workspace.RTL, - horizontalLayout: workspace.horizontalLayout, - toolboxPosition: workspace.options.toolboxPosition - }; - /** - * @type {!Blockly.Flyout} - * @private - */ - this.flyout_ = new Blockly.Flyout(workspaceOptions); - goog.dom.insertSiblingAfter(this.flyout_.createDom(), workspace.svgGroup_); - this.flyout_.init(workspace); - - this.config_['cleardotPath'] = workspace.options.pathToMedia + '1x1.gif'; - this.config_['cssCollapsedFolderIcon'] = - 'blocklyTreeIconClosed' + (workspace.RTL ? 'Rtl' : 'Ltr'); - var tree = new Blockly.Toolbox.TreeControl(this, this.config_); - this.tree_ = tree; - tree.setShowRootNode(false); - tree.setShowLines(false); - tree.setShowExpandIcons(false); - tree.setSelectedItem(null); - var openNode = this.populate_(workspace.options.languageTree); - tree.render(this.HtmlDiv); - if (openNode) { - tree.setSelectedItem(openNode); - } - this.addColour_(); - this.position(); -}; - -/** - * Dispose of this toolbox. - */ -Blockly.Toolbox.prototype.dispose = function() { - this.flyout_.dispose(); - this.tree_.dispose(); - goog.dom.removeNode(this.HtmlDiv); - this.workspace_ = null; - this.lastCategory_ = null; -}; - -/** - * Get the width of the toolbox. - * @return {number} The width of the toolbox. - */ -Blockly.Toolbox.prototype.getWidth = function() { - return this.width; -}; - -/** - * Get the height of the toolbox. - * @return {number} The width of the toolbox. - */ -Blockly.Toolbox.prototype.getHeight = function() { - return this.height; -}; - -/** - * Move the toolbox to the edge. - */ -Blockly.Toolbox.prototype.position = function() { - var treeDiv = this.HtmlDiv; - if (!treeDiv) { - // Not initialized yet. - return; - } - var svg = this.workspace_.getParentSvg(); - var svgPosition = goog.style.getPageOffset(svg); - var svgSize = Blockly.svgSize(svg); - if (this.horizontalLayout_) { - treeDiv.style.left = '0'; - treeDiv.style.height = 'auto'; - treeDiv.style.width = svgSize.width + 'px'; - this.height = treeDiv.offsetHeight; - if (this.toolboxPosition == Blockly.TOOLBOX_AT_TOP) { // Top - treeDiv.style.top = '0'; - } else { // Bottom - treeDiv.style.bottom = '0'; - } - } else { - if (this.toolboxPosition == Blockly.TOOLBOX_AT_RIGHT) { // Right - treeDiv.style.right = '0'; - } else { // Left - treeDiv.style.left = '0'; - } - treeDiv.style.height = svgSize.height + 'px'; - this.width = treeDiv.offsetWidth; - } - this.flyout_.position(); -}; - -/** - * Fill the toolbox with categories and blocks. - * @param {!Node} newTree DOM tree of blocks. - * @return {Node} Tree node to open at startup (or null). - * @private - */ -Blockly.Toolbox.prototype.populate_ = function(newTree) { - this.tree_.removeChildren(); // Delete any existing content. - this.tree_.blocks = []; - this.hasColours_ = false; - var openNode = - this.syncTrees_(newTree, this.tree_, this.workspace_.options.pathToMedia); - - if (this.tree_.blocks.length) { - throw 'Toolbox cannot have both blocks and categories in the root level.'; - } - - // Fire a resize event since the toolbox may have changed width and height. - this.workspace_.resizeContents(); - return openNode; -}; - -/** - * Sync trees of the toolbox. - * @param {!Node} treeIn DOM tree of blocks. - * @param {!Blockly.Toolbox.TreeControl} treeOut - * @param {string} pathToMedia - * @return {Node} Tree node to open at startup (or null). - * @private - */ -Blockly.Toolbox.prototype.syncTrees_ = function(treeIn, treeOut, pathToMedia) { - var openNode = null; - var lastElement = null; - for (var i = 0, childIn; childIn = treeIn.childNodes[i]; i++) { - if (!childIn.tagName) { - // Skip over text. - continue; - } - switch (childIn.tagName.toUpperCase()) { - case 'CATEGORY': - var childOut = this.tree_.createNode(childIn.getAttribute('name')); - childOut.blocks = []; - treeOut.add(childOut); - var custom = childIn.getAttribute('custom'); - if (custom) { - // Variables and procedures are special dynamic categories. - childOut.blocks = custom; - } else { - var newOpenNode = this.syncTrees_(childIn, childOut, pathToMedia); - if (newOpenNode) { - openNode = newOpenNode; - } - } - var colour = childIn.getAttribute('colour'); - if (goog.isString(colour)) { - if (colour.match(/^#[0-9a-fA-F]{6}$/)) { - childOut.hexColour = colour; - } else { - childOut.hexColour = Blockly.hueToRgb(colour); - } - this.hasColours_ = true; - } else { - childOut.hexColour = ''; - } - if (childIn.getAttribute('expanded') == 'true') { - if (childOut.blocks.length) { - // This is a category that directly contians blocks. - // After the tree is rendered, open this category and show flyout. - openNode = childOut; - } - childOut.setExpanded(true); - } else { - childOut.setExpanded(false); - } - lastElement = childIn; - break; - case 'SEP': - if (lastElement) { - if (lastElement.tagName.toUpperCase() == 'CATEGORY') { - // Separator between two categories. - // - treeOut.add(new Blockly.Toolbox.TreeSeparator( - this.treeSeparatorConfig_)); - } else { - // Change the gap between two blocks. - // - // The default gap is 24, can be set larger or smaller. - // Note that a deprecated method is to add a gap to a block. - // - var newGap = parseFloat(childIn.getAttribute('gap')); - if (!isNaN(newGap) && lastElement) { - lastElement.setAttribute('gap', newGap); - } - } - } - break; - case 'BLOCK': - case 'SHADOW': - treeOut.blocks.push(childIn); - lastElement = childIn; - break; - } - } - return openNode; -}; - -/** - * Recursively add colours to this toolbox. - * @param {Blockly.Toolbox.TreeNode} opt_tree Starting point of tree. - * Defaults to the root node. - * @private - */ -Blockly.Toolbox.prototype.addColour_ = function(opt_tree) { - var tree = opt_tree || this.tree_; - var children = tree.getChildren(); - for (var i = 0, child; child = children[i]; i++) { - var element = child.getRowElement(); - if (element) { - if (this.hasColours_) { - var border = '8px solid ' + (child.hexColour || '#ddd'); - } else { - var border = 'none'; - } - if (this.workspace_.RTL) { - element.style.borderRight = border; - } else { - element.style.borderLeft = border; - } - } - this.addColour_(child); - } -}; - -/** - * Unhighlight any previously specified option. - */ -Blockly.Toolbox.prototype.clearSelection = function() { - this.tree_.setSelectedItem(null); -}; - -/** - * Return the deletion rectangle for this toolbox. - * @return {goog.math.Rect} Rectangle in which to delete. - */ -Blockly.Toolbox.prototype.getClientRect = function() { - if (!this.HtmlDiv) { - return null; - } - - // BIG_NUM is offscreen padding so that blocks dragged beyond the toolbox - // area are still deleted. Must be smaller than Infinity, but larger than - // the largest screen size. - var BIG_NUM = 10000000; - var toolboxRect = this.HtmlDiv.getBoundingClientRect(); - - var x = toolboxRect.left; - var y = toolboxRect.top; - var width = toolboxRect.width; - var height = toolboxRect.height; - - // Assumes that the toolbox is on the SVG edge. If this changes - // (e.g. toolboxes in mutators) then this code will need to be more complex. - if (this.toolboxPosition == Blockly.TOOLBOX_AT_LEFT) { - return new goog.math.Rect(-BIG_NUM, -BIG_NUM, BIG_NUM + x + width, - 2 * BIG_NUM); - } else if (this.toolboxPosition == Blockly.TOOLBOX_AT_RIGHT) { - return new goog.math.Rect(x, -BIG_NUM, BIG_NUM + width, 2 * BIG_NUM); - } else if (this.toolboxPosition == Blockly.TOOLBOX_AT_TOP) { - return new goog.math.Rect(-BIG_NUM, -BIG_NUM, 2 * BIG_NUM, - BIG_NUM + y + height); - } else { // Bottom - return new goog.math.Rect(0, y, 2 * BIG_NUM, BIG_NUM + width); - } -}; - -/** - * Update the flyout's contents without closing it. Should be used in response - * to a change in one of the dynamic categories, such as variables or - * procedures. - */ -Blockly.Toolbox.prototype.refreshSelection = function() { - var selectedItem = this.tree_.getSelectedItem(); - if (selectedItem && selectedItem.blocks) { - this.flyout_.show(selectedItem.blocks); - } -}; - -// Extending Closure's Tree UI. - -/** - * Extention of a TreeControl object that uses a custom tree node. - * @param {Blockly.Toolbox} toolbox The parent toolbox for this tree. - * @param {Object} config The configuration for the tree. See - * goog.ui.tree.TreeControl.DefaultConfig. - * @constructor - * @extends {goog.ui.tree.TreeControl} - */ -Blockly.Toolbox.TreeControl = function(toolbox, config) { - this.toolbox_ = toolbox; - goog.ui.tree.TreeControl.call(this, goog.html.SafeHtml.EMPTY, config); -}; -goog.inherits(Blockly.Toolbox.TreeControl, goog.ui.tree.TreeControl); - -/** - * Adds touch handling to TreeControl. - * @override - */ -Blockly.Toolbox.TreeControl.prototype.enterDocument = function() { - Blockly.Toolbox.TreeControl.superClass_.enterDocument.call(this); - - // Add touch handler. - if (goog.events.BrowserFeature.TOUCH_ENABLED) { - var el = this.getElement(); - Blockly.bindEvent_(el, goog.events.EventType.TOUCHSTART, this, - this.handleTouchEvent_); - } -}; - -/** - * Handles touch events. - * @param {!goog.events.BrowserEvent} e The browser event. - * @private - */ -Blockly.Toolbox.TreeControl.prototype.handleTouchEvent_ = function(e) { - e.preventDefault(); - var node = this.getNodeFromEvent_(e); - if (node && e.type === goog.events.EventType.TOUCHSTART) { - // Fire asynchronously since onMouseDown takes long enough that the browser - // would fire the default mouse event before this method returns. - setTimeout(function() { - node.onMouseDown(e); // Same behaviour for click and touch. - }, 1); - } -}; - -/** - * Creates a new tree node using a custom tree node. - * @param {string=} opt_html The HTML content of the node label. - * @return {!goog.ui.tree.TreeNode} The new item. - * @override - */ -Blockly.Toolbox.TreeControl.prototype.createNode = function(opt_html) { - return new Blockly.Toolbox.TreeNode(this.toolbox_, opt_html ? - goog.html.SafeHtml.htmlEscape(opt_html) : goog.html.SafeHtml.EMPTY, - this.getConfig(), this.getDomHelper()); -}; - -/** - * Display/hide the flyout when an item is selected. - * @param {goog.ui.tree.BaseNode} node The item to select. - * @override - */ -Blockly.Toolbox.TreeControl.prototype.setSelectedItem = function(node) { - var toolbox = this.toolbox_; - if (node == this.selectedItem_ || node == toolbox.tree_) { - return; - } - if (toolbox.lastCategory_) { - toolbox.lastCategory_.getRowElement().style.backgroundColor = ''; - } - if (node) { - var hexColour = node.hexColour || '#57e'; - node.getRowElement().style.backgroundColor = hexColour; - // Add colours to child nodes which may have been collapsed and thus - // not rendered. - toolbox.addColour_(node); - } - var oldNode = this.getSelectedItem(); - goog.ui.tree.TreeControl.prototype.setSelectedItem.call(this, node); - if (node && node.blocks && node.blocks.length) { - toolbox.flyout_.show(node.blocks); - // Scroll the flyout to the top if the category has changed. - if (toolbox.lastCategory_ != node) { - toolbox.flyout_.scrollToStart(); - } - } else { - // Hide the flyout. - toolbox.flyout_.hide(); - } - if (oldNode != node && oldNode != this) { - var event = new Blockly.Events.Ui(null, 'category', - oldNode && oldNode.getHtml(), node && node.getHtml()); - event.workspaceId = toolbox.workspace_.id; - Blockly.Events.fire(event); - } - if (node) { - toolbox.lastCategory_ = node; - } -}; - -/** - * A single node in the tree, customized for Blockly's UI. - * @param {Blockly.Toolbox} toolbox The parent toolbox for this tree. - * @param {!goog.html.SafeHtml} html The HTML content of the node label. - * @param {Object=} opt_config The configuration for the tree. See - * goog.ui.tree.TreeControl.DefaultConfig. If not specified, a default config - * will be used. - * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper. - * @constructor - * @extends {goog.ui.tree.TreeNode} - */ -Blockly.Toolbox.TreeNode = function(toolbox, html, opt_config, opt_domHelper) { - goog.ui.tree.TreeNode.call(this, html, opt_config, opt_domHelper); - if (toolbox) { - this.horizontalLayout_ = toolbox.horizontalLayout_; - var resize = function() { - // Even though the div hasn't changed size, the visible workspace - // surface of the workspace has, so we may need to reposition everything. - Blockly.svgResize(toolbox.workspace_); - }; - // Fire a resize event since the toolbox may have changed width. - goog.events.listen(toolbox.tree_, - goog.ui.tree.BaseNode.EventType.EXPAND, resize); - goog.events.listen(toolbox.tree_, - goog.ui.tree.BaseNode.EventType.COLLAPSE, resize); - } -}; -goog.inherits(Blockly.Toolbox.TreeNode, goog.ui.tree.TreeNode); - -/** - * Supress population of the +/- icon. - * @return {!goog.html.SafeHtml} The source for the icon. - * @override - */ -Blockly.Toolbox.TreeNode.prototype.getExpandIconSafeHtml = function() { - return goog.html.SafeHtml.create('span'); -}; - -/** - * Expand or collapse the node on mouse click. - * @param {!goog.events.BrowserEvent} e The browser event. - * @override - */ -Blockly.Toolbox.TreeNode.prototype.onMouseDown = function(e) { - // Expand icon. - if (this.hasChildren() && this.isUserCollapsible_) { - this.toggle(); - this.select(); - } else if (this.isSelected()) { - this.getTree().setSelectedItem(null); - } else { - this.select(); - } - this.updateRow(); -}; - -/** - * Supress the inherited double-click behaviour. - * @param {!goog.events.BrowserEvent} e The browser event. - * @override - * @private - */ -Blockly.Toolbox.TreeNode.prototype.onDoubleClick_ = function(e) { - // NOP. -}; - -/** - * Remap event.keyCode in horizontalLayout so that arrow - * keys work properly and call original onKeyDown handler. - * @param {!goog.events.BrowserEvent} e The browser event. - * @return {boolean} The handled value. - * @override - * @private - */ -Blockly.Toolbox.TreeNode.prototype.onKeyDown = function(e) { - if (this.horizontalLayout_) { - var map = {}; - map[goog.events.KeyCodes.RIGHT] = goog.events.KeyCodes.DOWN; - map[goog.events.KeyCodes.LEFT] = goog.events.KeyCodes.UP; - map[goog.events.KeyCodes.UP] = goog.events.KeyCodes.LEFT; - map[goog.events.KeyCodes.DOWN] = goog.events.KeyCodes.RIGHT; - - var newKeyCode = map[e.keyCode]; - e.keyCode = newKeyCode || e.keyCode; - } - return Blockly.Toolbox.TreeNode.superClass_.onKeyDown.call(this, e); -}; - -/** - * A blank separator node in the tree. - * @param {Object=} config The configuration for the tree. See - * goog.ui.tree.TreeControl.DefaultConfig. If not specified, a default config - * will be used. - * @constructor - * @extends {Blockly.Toolbox.TreeNode} - */ -Blockly.Toolbox.TreeSeparator = function(config) { - Blockly.Toolbox.TreeNode.call(this, null, '', config); -}; -goog.inherits(Blockly.Toolbox.TreeSeparator, Blockly.Toolbox.TreeNode); diff --git a/backend/_pv_1_3_5/static/blockly/core/tooltip.js b/backend/_pv_1_3_5/static/blockly/core/tooltip.js deleted file mode 100755 index 2ff612b7b..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/tooltip.js +++ /dev/null @@ -1,286 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2011 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Library to create tooltips for Blockly. - * First, call Blockly.Tooltip.init() after onload. - * Second, set the 'tooltip' property on any SVG element that needs a tooltip. - * If the tooltip is a string, then that message will be displayed. - * If the tooltip is an SVG element, then that object's tooltip will be used. - * Third, call Blockly.Tooltip.bindMouseEvents(e) passing the SVG element. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Tooltip'); - -goog.require('goog.dom'); -goog.require('goog.dom.TagName'); - - -/** - * Is a tooltip currently showing? - */ -Blockly.Tooltip.visible = false; - -/** - * Maximum width (in characters) of a tooltip. - */ -Blockly.Tooltip.LIMIT = 50; - -/** - * PID of suspended thread to clear tooltip on mouse out. - * @private - */ -Blockly.Tooltip.mouseOutPid_ = 0; - -/** - * PID of suspended thread to show the tooltip. - * @private - */ -Blockly.Tooltip.showPid_ = 0; - -/** - * Last observed X location of the mouse pointer (freezes when tooltip appears). - * @private - */ -Blockly.Tooltip.lastX_ = 0; - -/** - * Last observed Y location of the mouse pointer (freezes when tooltip appears). - * @private - */ -Blockly.Tooltip.lastY_ = 0; - -/** - * Current element being pointed at. - * @private - */ -Blockly.Tooltip.element_ = null; - -/** - * Once a tooltip has opened for an element, that element is 'poisoned' and - * cannot respawn a tooltip until the pointer moves over a different element. - * @private - */ -Blockly.Tooltip.poisonedElement_ = null; - -/** - * Horizontal offset between mouse cursor and tooltip. - */ -Blockly.Tooltip.OFFSET_X = 0; - -/** - * Vertical offset between mouse cursor and tooltip. - */ -Blockly.Tooltip.OFFSET_Y = 10; - -/** - * Radius mouse can move before killing tooltip. - */ -Blockly.Tooltip.RADIUS_OK = 10; - -/** - * Delay before tooltip appears. - */ -Blockly.Tooltip.HOVER_MS = 750; - -/** - * Horizontal padding between tooltip and screen edge. - */ -Blockly.Tooltip.MARGINS = 5; - -/** - * The HTML container. Set once by Blockly.Tooltip.createDom. - * @type {Element} - */ -Blockly.Tooltip.DIV = null; - -/** - * Create the tooltip div and inject it onto the page. - */ -Blockly.Tooltip.createDom = function() { - if (Blockly.Tooltip.DIV) { - return; // Already created. - } - // Create an HTML container for popup overlays (e.g. editor widgets). - Blockly.Tooltip.DIV = - goog.dom.createDom(goog.dom.TagName.DIV, 'blocklyTooltipDiv'); - document.body.appendChild(Blockly.Tooltip.DIV); -}; - -/** - * Binds the required mouse events onto an SVG element. - * @param {!Element} element SVG element onto which tooltip is to be bound. - */ -Blockly.Tooltip.bindMouseEvents = function(element) { - Blockly.bindEvent_(element, 'mouseover', null, Blockly.Tooltip.onMouseOver_); - Blockly.bindEvent_(element, 'mouseout', null, Blockly.Tooltip.onMouseOut_); - Blockly.bindEvent_(element, 'mousemove', null, Blockly.Tooltip.onMouseMove_); -}; - -/** - * Hide the tooltip if the mouse is over a different object. - * Initialize the tooltip to potentially appear for this object. - * @param {!Event} e Mouse event. - * @private - */ -Blockly.Tooltip.onMouseOver_ = function(e) { - // If the tooltip is an object, treat it as a pointer to the next object in - // the chain to look at. Terminate when a string or function is found. - var element = e.target; - while (!goog.isString(element.tooltip) && !goog.isFunction(element.tooltip)) { - element = element.tooltip; - } - if (Blockly.Tooltip.element_ != element) { - Blockly.Tooltip.hide(); - Blockly.Tooltip.poisonedElement_ = null; - Blockly.Tooltip.element_ = element; - } - // Forget about any immediately preceeding mouseOut event. - clearTimeout(Blockly.Tooltip.mouseOutPid_); -}; - -/** - * Hide the tooltip if the mouse leaves the object and enters the workspace. - * @param {!Event} e Mouse event. - * @private - */ -Blockly.Tooltip.onMouseOut_ = function(e) { - // Moving from one element to another (overlapping or with no gap) generates - // a mouseOut followed instantly by a mouseOver. Fork off the mouseOut - // event and kill it if a mouseOver is received immediately. - // This way the task only fully executes if mousing into the void. - Blockly.Tooltip.mouseOutPid_ = setTimeout(function() { - Blockly.Tooltip.element_ = null; - Blockly.Tooltip.poisonedElement_ = null; - Blockly.Tooltip.hide(); - }, 1); - clearTimeout(Blockly.Tooltip.showPid_); -}; - -/** - * When hovering over an element, schedule a tooltip to be shown. If a tooltip - * is already visible, hide it if the mouse strays out of a certain radius. - * @param {!Event} e Mouse event. - * @private - */ -Blockly.Tooltip.onMouseMove_ = function(e) { - if (!Blockly.Tooltip.element_ || !Blockly.Tooltip.element_.tooltip) { - // No tooltip here to show. - return; - } else if (Blockly.dragMode_ != Blockly.DRAG_NONE) { - // Don't display a tooltip during a drag. - return; - } else if (Blockly.WidgetDiv.isVisible()) { - // Don't display a tooltip if a widget is open (tooltip would be under it). - return; - } - if (Blockly.Tooltip.visible) { - // Compute the distance between the mouse position when the tooltip was - // shown and the current mouse position. Pythagorean theorem. - var dx = Blockly.Tooltip.lastX_ - e.pageX; - var dy = Blockly.Tooltip.lastY_ - e.pageY; - if (Math.sqrt(dx * dx + dy * dy) > Blockly.Tooltip.RADIUS_OK) { - Blockly.Tooltip.hide(); - } - } else if (Blockly.Tooltip.poisonedElement_ != Blockly.Tooltip.element_) { - // The mouse moved, clear any previously scheduled tooltip. - clearTimeout(Blockly.Tooltip.showPid_); - // Maybe this time the mouse will stay put. Schedule showing of tooltip. - Blockly.Tooltip.lastX_ = e.pageX; - Blockly.Tooltip.lastY_ = e.pageY; - Blockly.Tooltip.showPid_ = - setTimeout(Blockly.Tooltip.show_, Blockly.Tooltip.HOVER_MS); - } -}; - -/** - * Hide the tooltip. - */ -Blockly.Tooltip.hide = function() { - if (Blockly.Tooltip.visible) { - Blockly.Tooltip.visible = false; - if (Blockly.Tooltip.DIV) { - Blockly.Tooltip.DIV.style.display = 'none'; - } - } - clearTimeout(Blockly.Tooltip.showPid_); -}; - -/** - * Create the tooltip and show it. - * @private - */ -Blockly.Tooltip.show_ = function() { - Blockly.Tooltip.poisonedElement_ = Blockly.Tooltip.element_; - if (!Blockly.Tooltip.DIV) { - return; - } - // Erase all existing text. - goog.dom.removeChildren(/** @type {!Element} */ (Blockly.Tooltip.DIV)); - // Get the new text. - var tip = Blockly.Tooltip.element_.tooltip; - while (goog.isFunction(tip)) { - tip = tip(); - } - tip = Blockly.utils.wrap(tip, Blockly.Tooltip.LIMIT); - // Create new text, line by line. - var lines = tip.split('\n'); - for (var i = 0; i < lines.length; i++) { - var div = document.createElement('div'); - div.appendChild(document.createTextNode(lines[i])); - Blockly.Tooltip.DIV.appendChild(div); - } - var rtl = Blockly.Tooltip.element_.RTL; - var windowSize = goog.dom.getViewportSize(); - // Display the tooltip. - Blockly.Tooltip.DIV.style.direction = rtl ? 'rtl' : 'ltr'; - Blockly.Tooltip.DIV.style.display = 'block'; - Blockly.Tooltip.visible = true; - // Move the tooltip to just below the cursor. - var anchorX = Blockly.Tooltip.lastX_; - if (rtl) { - anchorX -= Blockly.Tooltip.OFFSET_X + Blockly.Tooltip.DIV.offsetWidth; - } else { - anchorX += Blockly.Tooltip.OFFSET_X; - } - var anchorY = Blockly.Tooltip.lastY_ + Blockly.Tooltip.OFFSET_Y; - - if (anchorY + Blockly.Tooltip.DIV.offsetHeight > - windowSize.height + window.scrollY) { - // Falling off the bottom of the screen; shift the tooltip up. - anchorY -= Blockly.Tooltip.DIV.offsetHeight + 2 * Blockly.Tooltip.OFFSET_Y; - } - if (rtl) { - // Prevent falling off left edge in RTL mode. - anchorX = Math.max(Blockly.Tooltip.MARGINS - window.scrollX, anchorX); - } else { - if (anchorX + Blockly.Tooltip.DIV.offsetWidth > - windowSize.width + window.scrollX - 2 * Blockly.Tooltip.MARGINS) { - // Falling off the right edge of the screen; - // clamp the tooltip on the edge. - anchorX = windowSize.width - Blockly.Tooltip.DIV.offsetWidth - - 2 * Blockly.Tooltip.MARGINS; - } - } - Blockly.Tooltip.DIV.style.top = anchorY + 'px'; - Blockly.Tooltip.DIV.style.left = anchorX + 'px'; -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/trashcan.js b/backend/_pv_1_3_5/static/blockly/core/trashcan.js deleted file mode 100755 index 28baa0f20..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/trashcan.js +++ /dev/null @@ -1,332 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2011 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Object representing a trash can icon. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Trashcan'); - -goog.require('goog.Timer'); -goog.require('goog.dom'); -goog.require('goog.math'); -goog.require('goog.math.Rect'); - - -/** - * Class for a trash can. - * @param {!Blockly.Workspace} workspace The workspace to sit in. - * @constructor - */ -Blockly.Trashcan = function(workspace) { - this.workspace_ = workspace; -}; - -/** - * Width of both the trash can and lid images. - * @type {number} - * @private - */ -Blockly.Trashcan.prototype.WIDTH_ = 47; - -/** - * Height of the trashcan image (minus lid). - * @type {number} - * @private - */ -Blockly.Trashcan.prototype.BODY_HEIGHT_ = 44; - -/** - * Height of the lid image. - * @type {number} - * @private - */ -Blockly.Trashcan.prototype.LID_HEIGHT_ = 16; - -/** - * Distance between trashcan and bottom edge of workspace. - * @type {number} - * @private - */ -Blockly.Trashcan.prototype.MARGIN_BOTTOM_ = 20; - -/** - * Distance between trashcan and right edge of workspace. - * @type {number} - * @private - */ -Blockly.Trashcan.prototype.MARGIN_SIDE_ = 20; - -/** - * Extent of hotspot on all sides beyond the size of the image. - * @type {number} - * @private - */ -Blockly.Trashcan.prototype.MARGIN_HOTSPOT_ = 10; - -/** - * Location of trashcan in sprite image. - * @type {number} - * @private - */ -Blockly.Trashcan.prototype.SPRITE_LEFT_ = 0; - -/** - * Location of trashcan in sprite image. - * @type {number} - * @private - */ -Blockly.Trashcan.prototype.SPRITE_TOP_ = 32; - -/** - * Current open/close state of the lid. - * @type {boolean} - */ -Blockly.Trashcan.prototype.isOpen = false; - -/** - * The SVG group containing the trash can. - * @type {Element} - * @private - */ -Blockly.Trashcan.prototype.svgGroup_ = null; - -/** - * The SVG image element of the trash can lid. - * @type {Element} - * @private - */ -Blockly.Trashcan.prototype.svgLid_ = null; - -/** - * Task ID of opening/closing animation. - * @type {number} - * @private - */ -Blockly.Trashcan.prototype.lidTask_ = 0; - -/** - * Current state of lid opening (0.0 = closed, 1.0 = open). - * @type {number} - * @private - */ -Blockly.Trashcan.prototype.lidOpen_ = 0; - -/** - * Left coordinate of the trash can. - * @type {number} - * @private - */ -Blockly.Trashcan.prototype.left_ = 0; - -/** - * Top coordinate of the trash can. - * @type {number} - * @private - */ -Blockly.Trashcan.prototype.top_ = 0; - -/** - * Create the trash can elements. - * @return {!Element} The trash can's SVG group. - */ -Blockly.Trashcan.prototype.createDom = function() { - /* Here's the markup that will be generated: - - - - - - - - - - - */ - this.svgGroup_ = Blockly.createSvgElement('g', - {'class': 'blocklyTrash'}, null); - var rnd = String(Math.random()).substring(2); - var clip = Blockly.createSvgElement('clipPath', - {'id': 'blocklyTrashBodyClipPath' + rnd}, - this.svgGroup_); - Blockly.createSvgElement('rect', - {'width': this.WIDTH_, 'height': this.BODY_HEIGHT_, - 'y': this.LID_HEIGHT_}, - clip); - var body = Blockly.createSvgElement('image', - {'width': Blockly.SPRITE.width, 'x': -this.SPRITE_LEFT_, - 'height': Blockly.SPRITE.height, 'y': -this.SPRITE_TOP_, - 'clip-path': 'url(#blocklyTrashBodyClipPath' + rnd + ')'}, - this.svgGroup_); - body.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', - this.workspace_.options.pathToMedia + Blockly.SPRITE.url); - - var clip = Blockly.createSvgElement('clipPath', - {'id': 'blocklyTrashLidClipPath' + rnd}, - this.svgGroup_); - Blockly.createSvgElement('rect', - {'width': this.WIDTH_, 'height': this.LID_HEIGHT_}, clip); - this.svgLid_ = Blockly.createSvgElement('image', - {'width': Blockly.SPRITE.width, 'x': -this.SPRITE_LEFT_, - 'height': Blockly.SPRITE.height, 'y': -this.SPRITE_TOP_, - 'clip-path': 'url(#blocklyTrashLidClipPath' + rnd + ')'}, - this.svgGroup_); - this.svgLid_.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', - this.workspace_.options.pathToMedia + Blockly.SPRITE.url); - - Blockly.bindEvent_(this.svgGroup_, 'mouseup', this, this.click); - this.animateLid_(); - return this.svgGroup_; -}; - -/** - * Initialize the trash can. - * @param {number} bottom Distance from workspace bottom to bottom of trashcan. - * @return {number} Distance from workspace bottom to the top of trashcan. - */ -Blockly.Trashcan.prototype.init = function(bottom) { - this.bottom_ = this.MARGIN_BOTTOM_ + bottom; - this.setOpen_(false); - return this.bottom_ + this.BODY_HEIGHT_ + this.LID_HEIGHT_; -}; - -/** - * Dispose of this trash can. - * Unlink from all DOM elements to prevent memory leaks. - */ -Blockly.Trashcan.prototype.dispose = function() { - if (this.svgGroup_) { - goog.dom.removeNode(this.svgGroup_); - this.svgGroup_ = null; - } - this.svgLid_ = null; - this.workspace_ = null; - goog.Timer.clear(this.lidTask_); -}; - -/** - * Move the trash can to the bottom-right corner. - */ -Blockly.Trashcan.prototype.position = function() { - var metrics = this.workspace_.getMetrics(); - if (!metrics) { - // There are no metrics available (workspace is probably not visible). - return; - } - if (this.workspace_.RTL) { - this.left_ = this.MARGIN_SIDE_ + Blockly.Scrollbar.scrollbarThickness; - if (metrics.toolboxPosition == Blockly.TOOLBOX_AT_LEFT) { - this.left_ += metrics.flyoutWidth; - if (this.workspace_.toolbox_) { - this.left_ += metrics.absoluteLeft; - } - } - } else { - this.left_ = metrics.viewWidth + metrics.absoluteLeft - - this.WIDTH_ - this.MARGIN_SIDE_ - Blockly.Scrollbar.scrollbarThickness; - - if (metrics.toolboxPosition == Blockly.TOOLBOX_AT_RIGHT) { - this.left_ -= metrics.flyoutWidth; - } - } - this.top_ = metrics.viewHeight + metrics.absoluteTop - - (this.BODY_HEIGHT_ + this.LID_HEIGHT_) - this.bottom_; - - if (metrics.toolboxPosition == Blockly.TOOLBOX_AT_BOTTOM) { - this.top_ -= metrics.flyoutHeight; - } - this.svgGroup_.setAttribute('transform', - 'translate(' + this.left_ + ',' + this.top_ + ')'); -}; - -/** - * Return the deletion rectangle for this trash can. - * @return {goog.math.Rect} Rectangle in which to delete. - */ -Blockly.Trashcan.prototype.getClientRect = function() { - if (!this.svgGroup_) { - return null; - } - - var trashRect = this.svgGroup_.getBoundingClientRect(); - var left = trashRect.left + this.SPRITE_LEFT_ - this.MARGIN_HOTSPOT_; - var top = trashRect.top + this.SPRITE_TOP_ - this.MARGIN_HOTSPOT_; - var width = this.WIDTH_ + 2 * this.MARGIN_HOTSPOT_; - var height = this.LID_HEIGHT_ + this.BODY_HEIGHT_ + 2 * this.MARGIN_HOTSPOT_; - return new goog.math.Rect(left, top, width, height); - -}; - -/** - * Flip the lid open or shut. - * @param {boolean} state True if open. - * @private - */ -Blockly.Trashcan.prototype.setOpen_ = function(state) { - if (this.isOpen == state) { - return; - } - goog.Timer.clear(this.lidTask_); - this.isOpen = state; - this.animateLid_(); -}; - -/** - * Rotate the lid open or closed by one step. Then wait and recurse. - * @private - */ -Blockly.Trashcan.prototype.animateLid_ = function() { - this.lidOpen_ += this.isOpen ? 0.2 : -0.2; - this.lidOpen_ = goog.math.clamp(this.lidOpen_, 0, 1); - var lidAngle = this.lidOpen_ * 45; - this.svgLid_.setAttribute('transform', 'rotate(' + - (this.workspace_.RTL ? -lidAngle : lidAngle) + ',' + - (this.workspace_.RTL ? 4 : this.WIDTH_ - 4) + ',' + - (this.LID_HEIGHT_ - 2) + ')'); - var opacity = goog.math.lerp(0.4, 0.8, this.lidOpen_); - this.svgGroup_.style.opacity = opacity; - if (this.lidOpen_ > 0 && this.lidOpen_ < 1) { - this.lidTask_ = goog.Timer.callOnce(this.animateLid_, 20, this); - } -}; - -/** - * Flip the lid shut. - * Called externally after a drag. - */ -Blockly.Trashcan.prototype.close = function() { - this.setOpen_(false); -}; - -/** - * Inspect the contents of the trash. - */ -Blockly.Trashcan.prototype.click = function() { - var dx = this.workspace_.startScrollX - this.workspace_.scrollX; - var dy = this.workspace_.startScrollY - this.workspace_.scrollY; - if (Math.sqrt(dx * dx + dy * dy) > Blockly.DRAG_RADIUS) { - return; - } - console.log('TODO: Inspect trash.'); -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/utils.js b/backend/_pv_1_3_5/static/blockly/core/utils.js deleted file mode 100755 index fe13572ac..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/utils.js +++ /dev/null @@ -1,668 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Utility methods. - * These methods are not specific to Blockly, and could be factored out into - * a JavaScript framework such as Closure. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.utils'); - -goog.require('goog.dom'); -goog.require('goog.events.BrowserFeature'); -goog.require('goog.math.Coordinate'); -goog.require('goog.userAgent'); - - -/** - * Add a CSS class to a element. - * Similar to Closure's goog.dom.classes.add, except it handles SVG elements. - * @param {!Element} element DOM element to add class to. - * @param {string} className Name of class to add. - * @private - */ -Blockly.addClass_ = function(element, className) { - var classes = element.getAttribute('class') || ''; - if ((' ' + classes + ' ').indexOf(' ' + className + ' ') == -1) { - if (classes) { - classes += ' '; - } - element.setAttribute('class', classes + className); - } -}; - -/** - * Remove a CSS class from a element. - * Similar to Closure's goog.dom.classes.remove, except it handles SVG elements. - * @param {!Element} element DOM element to remove class from. - * @param {string} className Name of class to remove. - * @private - */ -Blockly.removeClass_ = function(element, className) { - var classes = element.getAttribute('class'); - if ((' ' + classes + ' ').indexOf(' ' + className + ' ') != -1) { - var classList = classes.split(/\s+/); - for (var i = 0; i < classList.length; i++) { - if (!classList[i] || classList[i] == className) { - classList.splice(i, 1); - i--; - } - } - if (classList.length) { - element.setAttribute('class', classList.join(' ')); - } else { - element.removeAttribute('class'); - } - } -}; - -/** - * Checks if an element has the specified CSS class. - * Similar to Closure's goog.dom.classes.has, except it handles SVG elements. - * @param {!Element} element DOM element to check. - * @param {string} className Name of class to check. - * @return {boolean} True if class exists, false otherwise. - * @private - */ -Blockly.hasClass_ = function(element, className) { - var classes = element.getAttribute('class'); - return (' ' + classes + ' ').indexOf(' ' + className + ' ') != -1; -}; - -/** - * Bind an event to a function call. - * @param {!Node} node Node upon which to listen. - * @param {string} name Event name to listen to (e.g. 'mousedown'). - * @param {Object} thisObject The value of 'this' in the function. - * @param {!Function} func Function to call when event is triggered. - * @return {!Array.} Opaque data that can be passed to unbindEvent_. - * @private - */ -Blockly.bindEvent_ = function(node, name, thisObject, func) { - if (thisObject) { - var wrapFunc = function(e) { - func.call(thisObject, e); - }; - } else { - var wrapFunc = func; - } - node.addEventListener(name, wrapFunc, false); - var bindData = [[node, name, wrapFunc]]; - // Add equivalent touch event. - if (name in Blockly.bindEvent_.TOUCH_MAP) { - wrapFunc = function(e) { - // Punt on multitouch events. - if (e.changedTouches.length == 1) { - // Map the touch event's properties to the event. - var touchPoint = e.changedTouches[0]; - e.clientX = touchPoint.clientX; - e.clientY = touchPoint.clientY; - } - func.call(thisObject, e); - // Stop the browser from scrolling/zooming the page. - e.preventDefault(); - }; - for (var i = 0, eventName; - eventName = Blockly.bindEvent_.TOUCH_MAP[name][i]; i++) { - node.addEventListener(eventName, wrapFunc, false); - bindData.push([node, eventName, wrapFunc]); - } - } - return bindData; -}; - -/** - * The TOUCH_MAP lookup dictionary specifies additional touch events to fire, - * in conjunction with mouse events. - * @type {Object} - */ -Blockly.bindEvent_.TOUCH_MAP = {}; -if (goog.events.BrowserFeature.TOUCH_ENABLED) { - Blockly.bindEvent_.TOUCH_MAP = { - 'mousedown': ['touchstart'], - 'mousemove': ['touchmove'], - 'mouseup': ['touchend', 'touchcancel'] - }; -} - -/** - * Unbind one or more events event from a function call. - * @param {!Array.} bindData Opaque data from bindEvent_. This list is - * emptied during the course of calling this function. - * @return {!Function} The function call. - * @private - */ -Blockly.unbindEvent_ = function(bindData) { - while (bindData.length) { - var bindDatum = bindData.pop(); - var node = bindDatum[0]; - var name = bindDatum[1]; - var func = bindDatum[2]; - node.removeEventListener(name, func, false); - } - return func; -}; - -/** - * Don't do anything for this event, just halt propagation. - * @param {!Event} e An event. - */ -Blockly.noEvent = function(e) { - // This event has been handled. No need to bubble up to the document. - e.preventDefault(); - e.stopPropagation(); -}; - -/** - * Is this event targeting a text input widget? - * @param {!Event} e An event. - * @return {boolean} True if text input. - * @private - */ -Blockly.isTargetInput_ = function(e) { - return e.target.type == 'textarea' || e.target.type == 'text' || - e.target.type == 'number' || e.target.type == 'email' || - e.target.type == 'password' || e.target.type == 'search' || - e.target.type == 'tel' || e.target.type == 'url' || - e.target.isContentEditable; -}; - -/** - * Return the coordinates of the top-left corner of this element relative to - * its parent. Only for SVG elements and children (e.g. rect, g, path). - * @param {!Element} element SVG element to find the coordinates of. - * @return {!goog.math.Coordinate} Object with .x and .y properties. - * @private - */ -Blockly.getRelativeXY_ = function(element) { - var xy = new goog.math.Coordinate(0, 0); - // First, check for x and y attributes. - var x = element.getAttribute('x'); - if (x) { - xy.x = parseInt(x, 10); - } - var y = element.getAttribute('y'); - if (y) { - xy.y = parseInt(y, 10); - } - // Second, check for transform="translate(...)" attribute. - var transform = element.getAttribute('transform'); - var r = transform && transform.match(Blockly.getRelativeXY_.XY_REGEXP_); - if (r) { - xy.x += parseFloat(r[1]); - if (r[3]) { - xy.y += parseFloat(r[3]); - } - } - return xy; -}; - -/** - * Static regex to pull the x,y values out of an SVG translate() directive. - * Note that Firefox and IE (9,10) return 'translate(12)' instead of - * 'translate(12, 0)'. - * Note that IE (9,10) returns 'translate(16 8)' instead of 'translate(16, 8)'. - * Note that IE has been reported to return scientific notation (0.123456e-42). - * @type {!RegExp} - * @private - */ -Blockly.getRelativeXY_.XY_REGEXP_ = - /translate\(\s*([-+\d.e]+)([ ,]\s*([-+\d.e]+)\s*\))?/; - -/** - * Return the absolute coordinates of the top-left corner of this element, - * scales that after canvas SVG element, if it's a descendant. - * The origin (0,0) is the top-left corner of the Blockly SVG. - * @param {!Element} element Element to find the coordinates of. - * @param {!Blockly.Workspace} workspace Element must be in this workspace. - * @return {!goog.math.Coordinate} Object with .x and .y properties. - * @private - */ -Blockly.getSvgXY_ = function(element, workspace) { - var x = 0; - var y = 0; - var scale = 1; - if (goog.dom.contains(workspace.getCanvas(), element) || - goog.dom.contains(workspace.getBubbleCanvas(), element)) { - // Before the SVG canvas, scale the coordinates. - scale = workspace.scale; - } - do { - // Loop through this block and every parent. - var xy = Blockly.getRelativeXY_(element); - if (element == workspace.getCanvas() || - element == workspace.getBubbleCanvas()) { - // After the SVG canvas, don't scale the coordinates. - scale = 1; - } - x += xy.x * scale; - y += xy.y * scale; - element = element.parentNode; - } while (element && element != workspace.getParentSvg()); - return new goog.math.Coordinate(x, y); -}; - -/** - * Helper method for creating SVG elements. - * @param {string} name Element's tag name. - * @param {!Object} attrs Dictionary of attribute names and values. - * @param {Element} parent Optional parent on which to append the element. - * @param {Blockly.Workspace=} opt_workspace Optional workspace for access to - * context (scale...). - * @return {!SVGElement} Newly created SVG element. - */ -Blockly.createSvgElement = function(name, attrs, parent, opt_workspace) { - var e = /** @type {!SVGElement} */ ( - document.createElementNS(Blockly.SVG_NS, name)); - for (var key in attrs) { - e.setAttribute(key, attrs[key]); - } - // IE defines a unique attribute "runtimeStyle", it is NOT applied to - // elements created with createElementNS. However, Closure checks for IE - // and assumes the presence of the attribute and crashes. - if (document.body.runtimeStyle) { // Indicates presence of IE-only attr. - e.runtimeStyle = e.currentStyle = e.style; - } - if (parent) { - parent.appendChild(e); - } - return e; -}; - -/** - * Is this event a right-click? - * @param {!Event} e Mouse event. - * @return {boolean} True if right-click. - */ -Blockly.isRightButton = function(e) { - if (e.ctrlKey && goog.userAgent.MAC) { - // Control-clicking on Mac OS X is treated as a right-click. - // WebKit on Mac OS X fails to change button to 2 (but Gecko does). - return true; - } - return e.button == 2; -}; - -/** - * Return the converted coordinates of the given mouse event. - * The origin (0,0) is the top-left corner of the Blockly svg. - * @param {!Event} e Mouse event. - * @param {!Element} svg SVG element. - * @param {SVGMatrix} matrix Inverted screen CTM to use. - * @return {!Object} Object with .x and .y properties. - */ -Blockly.mouseToSvg = function(e, svg, matrix) { - var svgPoint = svg.createSVGPoint(); - svgPoint.x = e.clientX; - svgPoint.y = e.clientY; - - if (!matrix) { - matrix = svg.getScreenCTM().inverse(); - } - return svgPoint.matrixTransform(matrix); -}; - -/** - * Given an array of strings, return the length of the shortest one. - * @param {!Array.} array Array of strings. - * @return {number} Length of shortest string. - */ -Blockly.shortestStringLength = function(array) { - if (!array.length) { - return 0; - } - var len = array[0].length; - for (var i = 1; i < array.length; i++) { - len = Math.min(len, array[i].length); - } - return len; -}; - -/** - * Given an array of strings, return the length of the common prefix. - * Words may not be split. Any space after a word is included in the length. - * @param {!Array.} array Array of strings. - * @param {number=} opt_shortest Length of shortest string. - * @return {number} Length of common prefix. - */ -Blockly.commonWordPrefix = function(array, opt_shortest) { - if (!array.length) { - return 0; - } else if (array.length == 1) { - return array[0].length; - } - var wordPrefix = 0; - var max = opt_shortest || Blockly.shortestStringLength(array); - for (var len = 0; len < max; len++) { - var letter = array[0][len]; - for (var i = 1; i < array.length; i++) { - if (letter != array[i][len]) { - return wordPrefix; - } - } - if (letter == ' ') { - wordPrefix = len + 1; - } - } - for (var i = 1; i < array.length; i++) { - var letter = array[i][len]; - if (letter && letter != ' ') { - return wordPrefix; - } - } - return max; -}; - -/** - * Given an array of strings, return the length of the common suffix. - * Words may not be split. Any space after a word is included in the length. - * @param {!Array.} array Array of strings. - * @param {number=} opt_shortest Length of shortest string. - * @return {number} Length of common suffix. - */ -Blockly.commonWordSuffix = function(array, opt_shortest) { - if (!array.length) { - return 0; - } else if (array.length == 1) { - return array[0].length; - } - var wordPrefix = 0; - var max = opt_shortest || Blockly.shortestStringLength(array); - for (var len = 0; len < max; len++) { - var letter = array[0].substr(-len - 1, 1); - for (var i = 1; i < array.length; i++) { - if (letter != array[i].substr(-len - 1, 1)) { - return wordPrefix; - } - } - if (letter == ' ') { - wordPrefix = len + 1; - } - } - for (var i = 1; i < array.length; i++) { - var letter = array[i].charAt(array[i].length - len - 1); - if (letter && letter != ' ') { - return wordPrefix; - } - } - return max; -}; - -/** - * Is the given string a number (includes negative and decimals). - * @param {string} str Input string. - * @return {boolean} True if number, false otherwise. - */ -Blockly.isNumber = function(str) { - return !!str.match(/^\s*-?\d+(\.\d+)?\s*$/); -}; - -/** - * Parse a string with any number of interpolation tokens (%1, %2, ...). - * '%' characters may be self-escaped (%%). - * @param {string} message Text containing interpolation tokens. - * @return {!Array.} Array of strings and numbers. - */ -Blockly.utils.tokenizeInterpolation = function(message) { - var tokens = []; - var chars = message.split(''); - chars.push(''); // End marker. - // Parse the message with a finite state machine. - // 0 - Base case. - // 1 - % found. - // 2 - Digit found. - var state = 0; - var buffer = []; - var number = null; - for (var i = 0; i < chars.length; i++) { - var c = chars[i]; - if (state == 0) { - if (c == '%') { - state = 1; // Start escape. - } else { - buffer.push(c); // Regular char. - } - } else if (state == 1) { - if (c == '%') { - buffer.push(c); // Escaped %: %% - state = 0; - } else if ('0' <= c && c <= '9') { - state = 2; - number = c; - var text = buffer.join(''); - if (text) { - tokens.push(text); - } - buffer.length = 0; - } else { - buffer.push('%', c); // Not an escape: %a - state = 0; - } - } else if (state == 2) { - if ('0' <= c && c <= '9') { - number += c; // Multi-digit number. - } else { - tokens.push(parseInt(number, 10)); - i--; // Parse this char again. - state = 0; - } - } - } - var text = buffer.join(''); - if (text) { - tokens.push(text); - } - return tokens; -}; - -/** - * Generate a unique ID. This should be globally unique. - * 87 characters ^ 20 length > 128 bits (better than a UUID). - * @return {string} A globally unique ID string. - */ -Blockly.genUid = function() { - var length = 20; - var soupLength = Blockly.genUid.soup_.length; - var id = []; - for (var i = 0; i < length; i++) { - id[i] = Blockly.genUid.soup_.charAt(Math.random() * soupLength); - } - return id.join(''); -}; - -/** - * Legal characters for the unique ID. - * Should be all on a US keyboard. No XML special characters or control codes. - * Removed $ due to issue 251. - * @private - */ -Blockly.genUid.soup_ = '!#%()*+,-./:;=?@[]^_`{|}~' + - 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - -/** - * Wrap text to the specified width. - * @param {string} text Text to wrap. - * @param {number} limit Width to wrap each line. - * @return {string} Wrapped text. - */ -Blockly.utils.wrap = function(text, limit) { - var lines = text.split('\n'); - for (var i = 0; i < lines.length; i++) { - lines[i] = Blockly.utils.wrap_line_(lines[i], limit); - } - return lines.join('\n'); -}; - -/** - * Wrap single line of text to the specified width. - * @param {string} text Text to wrap. - * @param {number} limit Width to wrap each line. - * @return {string} Wrapped text. - * @private - */ -Blockly.utils.wrap_line_ = function(text, limit) { - if (text.length <= limit) { - // Short text, no need to wrap. - return text; - } - // Split the text into words. - var words = text.trim().split(/\s+/); - // Set limit to be the length of the largest word. - for (var i = 0; i < words.length; i++) { - if (words[i].length > limit) { - limit = words[i].length; - } - } - - var lastScore; - var score = -Infinity; - var lastText; - var lineCount = 1; - do { - lastScore = score; - lastText = text; - // Create a list of booleans representing if a space (false) or - // a break (true) appears after each word. - var wordBreaks = []; - // Seed the list with evenly spaced linebreaks. - var steps = words.length / lineCount; - var insertedBreaks = 1; - for (var i = 0; i < words.length - 1; i++) { - if (insertedBreaks < (i + 1.5) / steps) { - insertedBreaks++; - wordBreaks[i] = true; - } else { - wordBreaks[i] = false; - } - } - wordBreaks = Blockly.utils.wrapMutate_(words, wordBreaks, limit); - score = Blockly.utils.wrapScore_(words, wordBreaks, limit); - text = Blockly.utils.wrapToText_(words, wordBreaks); - lineCount++; - } while (score > lastScore); - return lastText; -}; - -/** - * Compute a score for how good the wrapping is. - * @param {!Array.} words Array of each word. - * @param {!Array.} wordBreaks Array of line breaks. - * @param {number} limit Width to wrap each line. - * @return {number} Larger the better. - * @private - */ -Blockly.utils.wrapScore_ = function(words, wordBreaks, limit) { - // If this function becomes a performance liability, add caching. - // Compute the length of each line. - var lineLengths = [0]; - var linePunctuation = []; - for (var i = 0; i < words.length; i++) { - lineLengths[lineLengths.length - 1] += words[i].length; - if (wordBreaks[i] === true) { - lineLengths.push(0); - linePunctuation.push(words[i].charAt(words[i].length - 1)); - } else if (wordBreaks[i] === false) { - lineLengths[lineLengths.length - 1]++; - } - } - var maxLength = Math.max.apply(Math, lineLengths); - - var score = 0; - for (var i = 0; i < lineLengths.length; i++) { - // Optimize for width. - // -2 points per char over limit (scaled to the power of 1.5). - score -= Math.pow(Math.abs(limit - lineLengths[i]), 1.5) * 2; - // Optimize for even lines. - // -1 point per char smaller than max (scaled to the power of 1.5). - score -= Math.pow(maxLength - lineLengths[i], 1.5); - // Optimize for structure. - // Add score to line endings after punctuation. - if ('.?!'.indexOf(linePunctuation[i]) != -1) { - score += limit / 3; - } else if (',;)]}'.indexOf(linePunctuation[i]) != -1) { - score += limit / 4; - } - } - // All else being equal, the last line should not be longer than the - // previous line. For example, this looks wrong: - // aaa bbb - // ccc ddd eee - if (lineLengths.length > 1 && lineLengths[lineLengths.length - 1] <= - lineLengths[lineLengths.length - 2]) { - score += 0.5; - } - return score; -}; - -/** - * Mutate the array of line break locations until an optimal solution is found. - * No line breaks are added or deleted, they are simply moved around. - * @param {!Array.} words Array of each word. - * @param {!Array.} wordBreaks Array of line breaks. - * @param {number} limit Width to wrap each line. - * @return {!Array.} New array of optimal line breaks. - * @private - */ -Blockly.utils.wrapMutate_ = function(words, wordBreaks, limit) { - var bestScore = Blockly.utils.wrapScore_(words, wordBreaks, limit); - var bestBreaks; - // Try shifting every line break forward or backward. - for (var i = 0; i < wordBreaks.length - 1; i++) { - if (wordBreaks[i] == wordBreaks[i + 1]) { - continue; - } - var mutatedWordBreaks = [].concat(wordBreaks); - mutatedWordBreaks[i] = !mutatedWordBreaks[i]; - mutatedWordBreaks[i + 1] = !mutatedWordBreaks[i + 1]; - var mutatedScore = - Blockly.utils.wrapScore_(words, mutatedWordBreaks, limit); - if (mutatedScore > bestScore) { - bestScore = mutatedScore; - bestBreaks = mutatedWordBreaks; - } - } - if (bestBreaks) { - // Found an improvement. See if it may be improved further. - return Blockly.utils.wrapMutate_(words, bestBreaks, limit); - } - // No improvements found. Done. - return wordBreaks; -}; - -/** - * Reassemble the array of words into text, with the specified line breaks. - * @param {!Array.} words Array of each word. - * @param {!Array.} wordBreaks Array of line breaks. - * @return {string} Plain text. - * @private - */ -Blockly.utils.wrapToText_ = function(words, wordBreaks) { - var text = []; - for (var i = 0; i < words.length; i++) { - text.push(words[i]); - if (wordBreaks[i] !== undefined) { - text.push(wordBreaks[i] ? '\n' : ' '); - } - } - return text.join(''); -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/variables.js b/backend/_pv_1_3_5/static/blockly/core/variables.js deleted file mode 100755 index 00c38ad21..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/variables.js +++ /dev/null @@ -1,273 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Utility functions for handling variables. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Variables'); - -goog.require('Blockly.Blocks'); -goog.require('Blockly.Workspace'); -goog.require('goog.string'); - - -/** - * Category to separate variable names from procedures and generated functions. - */ -Blockly.Variables.NAME_TYPE = 'VARIABLE'; - -/** - * Find all user-created variables that are in use in the workspace. - * For use by generators. - * @param {!Blockly.Block|!Blockly.Workspace} root Root block or workspace. - * @return {!Array.} Array of variable names. - */ -Blockly.Variables.allUsedVariables = function(root) { - var blocks; - if (root instanceof Blockly.Block) { - // Root is Block. - blocks = root.getDescendants(); - } else if (root.getAllBlocks) { - // Root is Workspace. - blocks = root.getAllBlocks(); - } else { - throw 'Not Block or Workspace: ' + root; - } - var variableHash = Object.create(null); - // Iterate through every block and add each variable to the hash. - for (var x = 0; x < blocks.length; x++) { - var blockVariables = blocks[x].getVars(); - if (blockVariables) { - for (var y = 0; y < blockVariables.length; y++) { - var varName = blockVariables[y]; - // Variable name may be null if the block is only half-built. - if (varName) { - variableHash[varName.toLowerCase()] = varName; - } - } - } - } - // Flatten the hash into a list. - var variableList = []; - for (var name in variableHash) { - variableList.push(variableHash[name]); - } - return variableList; -}; - -/** - * Find all variables that the user has created through the workspace or - * toolbox. For use by generators. - * @param {!Blockly.Workspace} root The workspace to inspect. - * @return {!Array.} Array of variable names. - */ -Blockly.Variables.allVariables = function(root) { - if (root instanceof Blockly.Block) { - // Root is Block. - console.warn('Deprecated call to Blockly.Variables.allVariables ' + - 'with a block instead of a workspace. You may want ' + - 'Blockly.Variables.allUsedVariables'); - } - return root.variableList; -}; - -/** - * Construct the blocks required by the flyout for the variable category. - * @param {!Blockly.Workspace} workspace The workspace contianing variables. - * @return {!Array.} Array of XML block elements. - */ -Blockly.Variables.flyoutCategory = function(workspace) { - var variableList = workspace.variableList; - variableList.sort(goog.string.caseInsensitiveCompare); - - var xmlList = []; - var button = goog.dom.createDom('button'); - button.setAttribute('text', Blockly.Msg.NEW_VARIABLE); - xmlList.push(button); - - if (variableList.length > 0) { - if (Blockly.Blocks['variables_set']) { - // - // item - // - var block = goog.dom.createDom('block'); - block.setAttribute('type', 'variables_set'); - if (Blockly.Blocks['math_change']) { - block.setAttribute('gap', 8); - } else { - block.setAttribute('gap', 24); - } - var field = goog.dom.createDom('field', null, variableList[0]); - field.setAttribute('name', 'VAR'); - block.appendChild(field); - xmlList.push(block); - } - if (Blockly.Blocks['math_change']) { - // - // - // - // 1 - // - // - // - var block = goog.dom.createDom('block'); - block.setAttribute('type', 'math_change'); - if (Blockly.Blocks['variables_get']) { - block.setAttribute('gap', 20); - } - var value = goog.dom.createDom('value'); - value.setAttribute('name', 'DELTA'); - block.appendChild(value); - - var field = goog.dom.createDom('field', null, variableList[0]); - field.setAttribute('name', 'VAR'); - block.appendChild(field); - - var shadowBlock = goog.dom.createDom('shadow'); - shadowBlock.setAttribute('type', 'math_number'); - value.appendChild(shadowBlock); - - var numberField = goog.dom.createDom('field', null, '1'); - numberField.setAttribute('name', 'NUM'); - shadowBlock.appendChild(numberField); - - xmlList.push(block); - } - - for (var i = 0; i < variableList.length; i++) { - if (Blockly.Blocks['variables_get']) { - // - // item - // - var block = goog.dom.createDom('block'); - block.setAttribute('type', 'variables_get'); - if (Blockly.Blocks['variables_set']) { - block.setAttribute('gap', 8); - } - var field = goog.dom.createDom('field', null, variableList[i]); - field.setAttribute('name', 'VAR'); - block.appendChild(field); - xmlList.push(block); - } - } - } - return xmlList; -}; - -/** -* Return a new variable name that is not yet being used. This will try to -* generate single letter variable names in the range 'i' to 'z' to start with. -* If no unique name is located it will try 'i' to 'z', 'a' to 'h', -* then 'i2' to 'z2' etc. Skip 'l'. - * @param {!Blockly.Workspace} workspace The workspace to be unique in. -* @return {string} New variable name. -*/ -Blockly.Variables.generateUniqueName = function(workspace) { - var variableList = workspace.variableList; - var newName = ''; - if (variableList.length) { - var nameSuffix = 1; - var letters = 'ijkmnopqrstuvwxyzabcdefgh'; // No 'l'. - var letterIndex = 0; - var potName = letters.charAt(letterIndex); - while (!newName) { - var inUse = false; - for (var i = 0; i < variableList.length; i++) { - if (variableList[i].toLowerCase() == potName) { - // This potential name is already used. - inUse = true; - break; - } - } - if (inUse) { - // Try the next potential name. - letterIndex++; - if (letterIndex == letters.length) { - // Reached the end of the character sequence so back to 'i'. - // a new suffix. - letterIndex = 0; - nameSuffix++; - } - potName = letters.charAt(letterIndex); - if (nameSuffix > 1) { - potName += nameSuffix; - } - } else { - // We can use the current potential name. - newName = potName; - } - } - } else { - newName = 'i'; - } - return newName; -}; - -/** - * Create a new variable on the given workspace. - * @param {!Blockly.Workspace} workspace The workspace on which to create the - * variable. - * @return {null|undefined|string} An acceptable new variable name, or null if - * change is to be aborted (cancel button), or undefined if an existing - * variable was chosen. - */ -Blockly.Variables.createVariable = function(workspace) { - while (true) { - var text = Blockly.Variables.promptName(Blockly.Msg.NEW_VARIABLE_TITLE, ''); - if (text) { - if (workspace.variableIndexOf(text) != -1) { - window.alert(Blockly.Msg.VARIABLE_ALREADY_EXISTS.replace('%1', - text.toLowerCase())); - } else { - workspace.createVariable(text); - break; - } - } else { - text = null; - break; - } - } - return text; -}; - -/** - * Prompt the user for a new variable name. - * @param {string} promptText The string of the prompt. - * @param {string} defaultText The default value to show in the prompt's field. - * @return {?string} The new variable name, or null if the user picked - * something illegal. - */ -Blockly.Variables.promptName = function(promptText, defaultText) { - var newVar = window.prompt(promptText, defaultText); - // Merge runs of whitespace. Strip leading and trailing whitespace. - // Beyond this, all names are legal. - if (newVar) { - newVar = newVar.replace(/[\s\xa0]+/g, ' ').replace(/^ | $/g, ''); - if (newVar == Blockly.Msg.RENAME_VARIABLE || - newVar == Blockly.Msg.NEW_VARIABLE) { - // Ok, not ALL names are legal... - newVar = null; - } - } - return newVar; -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/warning.js b/backend/_pv_1_3_5/static/blockly/core/warning.js deleted file mode 100755 index bffbf06df..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/warning.js +++ /dev/null @@ -1,185 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Object representing a warning. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Warning'); - -goog.require('Blockly.Bubble'); -goog.require('Blockly.Icon'); - - -/** - * Class for a warning. - * @param {!Blockly.Block} block The block associated with this warning. - * @extends {Blockly.Icon} - * @constructor - */ -Blockly.Warning = function(block) { - Blockly.Warning.superClass_.constructor.call(this, block); - this.createIcon(); - // The text_ object can contain multiple warnings. - this.text_ = {}; -}; -goog.inherits(Blockly.Warning, Blockly.Icon); - -/** - * Does this icon get hidden when the block is collapsed. - */ -Blockly.Warning.prototype.collapseHidden = false; - -/** - * Draw the warning icon. - * @param {!Element} group The icon group. - * @private - */ -Blockly.Warning.prototype.drawIcon_ = function(group) { - // Triangle with rounded corners. - Blockly.createSvgElement('path', - {'class': 'blocklyIconShape', - 'd': 'M2,15Q-1,15 0.5,12L6.5,1.7Q8,-1 9.5,1.7L15.5,12Q17,15 14,15z'}, - group); - // Can't use a real '!' text character since different browsers and operating - // systems render it differently. - // Body of exclamation point. - Blockly.createSvgElement('path', - {'class': 'blocklyIconSymbol', - 'd': 'm7,4.8v3.16l0.27,2.27h1.46l0.27,-2.27v-3.16z'}, - group); - // Dot of exclamation point. - Blockly.createSvgElement('rect', - {'class': 'blocklyIconSymbol', - 'x': '7', 'y': '11', 'height': '2', 'width': '2'}, - group); -}; - -/** - * Create the text for the warning's bubble. - * @param {string} text The text to display. - * @return {!SVGTextElement} The top-level node of the text. - * @private - */ -Blockly.Warning.textToDom_ = function(text) { - var paragraph = /** @type {!SVGTextElement} */ ( - Blockly.createSvgElement('text', - {'class': 'blocklyText blocklyBubbleText', - 'y': Blockly.Bubble.BORDER_WIDTH}, - null)); - var lines = text.split('\n'); - for (var i = 0; i < lines.length; i++) { - var tspanElement = Blockly.createSvgElement('tspan', - {'dy': '1em', 'x': Blockly.Bubble.BORDER_WIDTH}, paragraph); - var textNode = document.createTextNode(lines[i]); - tspanElement.appendChild(textNode); - } - return paragraph; -}; - -/** - * Show or hide the warning bubble. - * @param {boolean} visible True if the bubble should be visible. - */ -Blockly.Warning.prototype.setVisible = function(visible) { - if (visible == this.isVisible()) { - // No change. - return; - } - Blockly.Events.fire( - new Blockly.Events.Ui(this.block_, 'warningOpen', !visible, visible)); - if (visible) { - // Create the bubble to display all warnings. - var paragraph = Blockly.Warning.textToDom_(this.getText()); - this.bubble_ = new Blockly.Bubble( - /** @type {!Blockly.WorkspaceSvg} */ (this.block_.workspace), - paragraph, this.block_.svgPath_, this.iconXY_, null, null); - if (this.block_.RTL) { - // Right-align the paragraph. - // This cannot be done until the bubble is rendered on screen. - var maxWidth = paragraph.getBBox().width; - for (var i = 0, textElement; textElement = paragraph.childNodes[i]; i++) { - textElement.setAttribute('text-anchor', 'end'); - textElement.setAttribute('x', maxWidth + Blockly.Bubble.BORDER_WIDTH); - } - } - this.updateColour(); - // Bump the warning into the right location. - var size = this.bubble_.getBubbleSize(); - this.bubble_.setBubbleSize(size.width, size.height); - } else { - // Dispose of the bubble. - this.bubble_.dispose(); - this.bubble_ = null; - this.body_ = null; - } -}; - -/** - * Bring the warning to the top of the stack when clicked on. - * @param {!Event} e Mouse up event. - * @private - */ -Blockly.Warning.prototype.bodyFocus_ = function(e) { - this.bubble_.promote_(); -}; - -/** - * Set this warning's text. - * @param {string} text Warning text (or '' to delete). - * @param {string} id An ID for this text entry to be able to maintain - * multiple warnings. - */ -Blockly.Warning.prototype.setText = function(text, id) { - if (this.text_[id] == text) { - return; - } - if (text) { - this.text_[id] = text; - } else { - delete this.text_[id]; - } - if (this.isVisible()) { - this.setVisible(false); - this.setVisible(true); - } -}; - -/** - * Get this warning's texts. - * @return {string} All texts concatenated into one string. - */ -Blockly.Warning.prototype.getText = function() { - var allWarnings = []; - for (var id in this.text_) { - allWarnings.push(this.text_[id]); - } - return allWarnings.join('\n'); -}; - -/** - * Dispose of this warning. - */ -Blockly.Warning.prototype.dispose = function() { - this.block_.warning = null; - Blockly.Icon.prototype.dispose.call(this); -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/widgetdiv.js b/backend/_pv_1_3_5/static/blockly/core/widgetdiv.js deleted file mode 100755 index a811339b3..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/widgetdiv.js +++ /dev/null @@ -1,152 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2013 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview A div that floats on top of Blockly. This singleton contains - * temporary HTML UI widgets that the user is currently interacting with. - * E.g. text input areas, colour pickers, context menus. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.WidgetDiv'); - -goog.require('Blockly.Css'); -goog.require('goog.dom'); -goog.require('goog.dom.TagName'); -goog.require('goog.style'); - - -/** - * The HTML container. Set once by Blockly.WidgetDiv.createDom. - * @type {Element} - */ -Blockly.WidgetDiv.DIV = null; - -/** - * The object currently using this container. - * @type {Object} - * @private - */ -Blockly.WidgetDiv.owner_ = null; - -/** - * Optional cleanup function set by whichever object uses the widget. - * @type {Function} - * @private - */ -Blockly.WidgetDiv.dispose_ = null; - -/** - * Create the widget div and inject it onto the page. - */ -Blockly.WidgetDiv.createDom = function() { - if (Blockly.WidgetDiv.DIV) { - return; // Already created. - } - // Create an HTML container for popup overlays (e.g. editor widgets). - Blockly.WidgetDiv.DIV = - goog.dom.createDom(goog.dom.TagName.DIV, 'blocklyWidgetDiv'); - document.body.appendChild(Blockly.WidgetDiv.DIV); -}; - -/** - * Initialize and display the widget div. Close the old one if needed. - * @param {!Object} newOwner The object that will be using this container. - * @param {boolean} rtl Right-to-left (true) or left-to-right (false). - * @param {Function} dispose Optional cleanup function to be run when the widget - * is closed. - */ -Blockly.WidgetDiv.show = function(newOwner, rtl, dispose) { - Blockly.WidgetDiv.hide(); - Blockly.WidgetDiv.owner_ = newOwner; - Blockly.WidgetDiv.dispose_ = dispose; - // Temporarily move the widget to the top of the screen so that it does not - // cause a scrollbar jump in Firefox when displayed. - var xy = goog.style.getViewportPageOffset(document); - Blockly.WidgetDiv.DIV.style.top = xy.y + 'px'; - Blockly.WidgetDiv.DIV.style.direction = rtl ? 'rtl' : 'ltr'; - Blockly.WidgetDiv.DIV.style.display = 'block'; -}; - -/** - * Destroy the widget and hide the div. - */ -Blockly.WidgetDiv.hide = function() { - if (Blockly.WidgetDiv.owner_) { - Blockly.WidgetDiv.owner_ = null; - Blockly.WidgetDiv.DIV.style.display = 'none'; - Blockly.WidgetDiv.DIV.style.left = ''; - Blockly.WidgetDiv.DIV.style.top = ''; - Blockly.WidgetDiv.dispose_ && Blockly.WidgetDiv.dispose_(); - Blockly.WidgetDiv.dispose_ = null; - goog.dom.removeChildren(Blockly.WidgetDiv.DIV); - } -}; - -/** - * Is the container visible? - * @return {boolean} True if visible. - */ -Blockly.WidgetDiv.isVisible = function() { - return !!Blockly.WidgetDiv.owner_; -}; - -/** - * Destroy the widget and hide the div if it is being used by the specified - * object. - * @param {!Object} oldOwner The object that was using this container. - */ -Blockly.WidgetDiv.hideIfOwner = function(oldOwner) { - if (Blockly.WidgetDiv.owner_ == oldOwner) { - Blockly.WidgetDiv.hide(); - } -}; - -/** - * Position the widget at a given location. Prevent the widget from going - * offscreen top or left (right in RTL). - * @param {number} anchorX Horizontal location (window coorditates, not body). - * @param {number} anchorY Vertical location (window coorditates, not body). - * @param {!goog.math.Size} windowSize Height/width of window. - * @param {!goog.math.Coordinate} scrollOffset X/y of window scrollbars. - * @param {boolean} rtl True if RTL, false if LTR. - */ -Blockly.WidgetDiv.position = function(anchorX, anchorY, windowSize, - scrollOffset, rtl) { - // Don't let the widget go above the top edge of the window. - if (anchorY < scrollOffset.y) { - anchorY = scrollOffset.y; - } - if (rtl) { - // Don't let the widget go right of the right edge of the window. - if (anchorX > windowSize.width + scrollOffset.x) { - anchorX = windowSize.width + scrollOffset.x; - } - } else { - // Don't let the widget go left of the left edge of the window. - if (anchorX < scrollOffset.x) { - anchorX = scrollOffset.x; - } - } - Blockly.WidgetDiv.DIV.style.left = anchorX + 'px'; - Blockly.WidgetDiv.DIV.style.top = anchorY + 'px'; - Blockly.WidgetDiv.DIV.style.height = windowSize.height + 'px'; -}; diff --git a/backend/_pv_1_3_5/static/blockly/core/workspace.js b/backend/_pv_1_3_5/static/blockly/core/workspace.js deleted file mode 100755 index a8e97c04b..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/workspace.js +++ /dev/null @@ -1,501 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Object representing a workspace. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Workspace'); - -goog.require('goog.math'); - - -/** - * Class for a workspace. This is a data structure that contains blocks. - * There is no UI, and can be created headlessly. - * @param {Blockly.Options} opt_options Dictionary of options. - * @constructor - */ -Blockly.Workspace = function(opt_options) { - /** @type {string} */ - this.id = Blockly.genUid(); - Blockly.Workspace.WorkspaceDB_[this.id] = this; - /** @type {!Blockly.Options} */ - this.options = opt_options || {}; - /** @type {boolean} */ - this.RTL = !!this.options.RTL; - /** @type {boolean} */ - this.horizontalLayout = !!this.options.horizontalLayout; - /** @type {number} */ - this.toolboxPosition = this.options.toolboxPosition; - - /** - * @type {!Array.} - * @private - */ - this.topBlocks_ = []; - /** - * @type {!Array.} - * @private - */ - this.listeners_ = []; - /** - * @type {!Array.} - * @private - */ - this.undoStack_ = []; - /** - * @type {!Array.} - * @private - */ - this.redoStack_ = []; - /** - * @type {!Object} - * @private - */ - this.blockDB_ = Object.create(null); - /* - * @type {!Array.} - * A list of all of the named variables in the workspace, including variables - * that are not currently in use. - */ - this.variableList = []; -}; - -/** - * Workspaces may be headless. - * @type {boolean} True if visible. False if headless. - */ -Blockly.Workspace.prototype.rendered = false; - -/** - * Maximum number of undo events in stack. - * @type {number} 0 to turn off undo, Infinity for unlimited. - */ -Blockly.Workspace.prototype.MAX_UNDO = 1024; - -/** - * Dispose of this workspace. - * Unlink from all DOM elements to prevent memory leaks. - */ -Blockly.Workspace.prototype.dispose = function() { - this.listeners_.length = 0; - this.clear(); - // Remove from workspace database. - delete Blockly.Workspace.WorkspaceDB_[this.id]; -}; - -/** - * Angle away from the horizontal to sweep for blocks. Order of execution is - * generally top to bottom, but a small angle changes the scan to give a bit of - * a left to right bias (reversed in RTL). Units are in degrees. - * See: http://tvtropes.org/pmwiki/pmwiki.php/Main/DiagonalBilling. - */ -Blockly.Workspace.SCAN_ANGLE = 3; - -/** - * Add a block to the list of top blocks. - * @param {!Blockly.Block} block Block to remove. - */ -Blockly.Workspace.prototype.addTopBlock = function(block) { - this.topBlocks_.push(block); - if (this.isFlyout) { - // This is for the (unlikely) case where you have a variable in a block in - // an always-open flyout. It needs to be possible to edit the block in the - // flyout, so the contents of the dropdown need to be correct. - var variables = Blockly.Variables.allUsedVariables(block); - for (var i = 0; i < variables.length; i++) { - if (this.variableList.indexOf(variables[i]) == -1) { - this.variableList.push(variables[i]); - } - } - } -}; - -/** - * Remove a block from the list of top blocks. - * @param {!Blockly.Block} block Block to remove. - */ -Blockly.Workspace.prototype.removeTopBlock = function(block) { - var found = false; - for (var child, i = 0; child = this.topBlocks_[i]; i++) { - if (child == block) { - this.topBlocks_.splice(i, 1); - found = true; - break; - } - } - if (!found) { - throw 'Block not present in workspace\'s list of top-most blocks.'; - } -}; - -/** - * Finds the top-level blocks and returns them. Blocks are optionally sorted - * by position; top to bottom (with slight LTR or RTL bias). - * @param {boolean} ordered Sort the list if true. - * @return {!Array.} The top-level block objects. - */ -Blockly.Workspace.prototype.getTopBlocks = function(ordered) { - // Copy the topBlocks_ list. - var blocks = [].concat(this.topBlocks_); - if (ordered && blocks.length > 1) { - var offset = Math.sin(goog.math.toRadians(Blockly.Workspace.SCAN_ANGLE)); - if (this.RTL) { - offset *= -1; - } - blocks.sort(function(a, b) { - var aXY = a.getRelativeToSurfaceXY(); - var bXY = b.getRelativeToSurfaceXY(); - return (aXY.y + offset * aXY.x) - (bXY.y + offset * bXY.x); - }); - } - return blocks; -}; - -/** - * Find all blocks in workspace. No particular order. - * @return {!Array.} Array of blocks. - */ -Blockly.Workspace.prototype.getAllBlocks = function() { - var blocks = this.getTopBlocks(false); - for (var i = 0; i < blocks.length; i++) { - blocks.push.apply(blocks, blocks[i].getChildren()); - } - return blocks; -}; - -/** - * Dispose of all blocks in workspace. - */ -Blockly.Workspace.prototype.clear = function() { - var existingGroup = Blockly.Events.getGroup(); - if (!existingGroup) { - Blockly.Events.setGroup(true); - } - while (this.topBlocks_.length) { - this.topBlocks_[0].dispose(); - } - if (!existingGroup) { - Blockly.Events.setGroup(false); - } - - this.variableList.length = 0; -}; - -/** - * Walk the workspace and update the list of variables to only contain ones in - * use on the workspace. Use when loading new workspaces from disk. - * @param {boolean} clearList True if the old variable list should be cleared. - */ -Blockly.Workspace.prototype.updateVariableList = function(clearList) { - // TODO: Sort - if (!this.isFlyout) { - // Update the list in place so that the flyout's references stay correct. - if (clearList) { - this.variableList.length = 0; - } - var allVariables = Blockly.Variables.allUsedVariables(this); - for (var i = 0; i < allVariables.length; i++) { - this.createVariable(allVariables[i]); - } - } -}; - -/** - * Rename a variable by updating its name in the variable list. - * TODO: #468 - * @param {string} oldName Variable to rename. - * @param {string} newName New variable name. - */ -Blockly.Workspace.prototype.renameVariable = function(oldName, newName) { - // Find the old name in the list. - var variableIndex = this.variableIndexOf(oldName); - var newVariableIndex = this.variableIndexOf(newName); - - // We might be renaming to an existing name but with different case. If so, - // we will also update all of the blocks using the new name to have the - // correct case. - if (newVariableIndex != -1 && - this.variableList[newVariableIndex] != newName) { - var oldCase = this.variableList[newVariableIndex]; - } - - Blockly.Events.setGroup(true); - var blocks = this.getAllBlocks(); - // Iterate through every block. - for (var i = 0; i < blocks.length; i++) { - blocks[i].renameVar(oldName, newName); - if (oldCase) { - blocks[i].renameVar(oldCase, newName); - } - } - Blockly.Events.setGroup(false); - - - if (variableIndex == newVariableIndex || - variableIndex != -1 && newVariableIndex == -1) { - // Only changing case, or renaming to a completely novel name. - this.variableList[variableIndex] = newName; - } else if (variableIndex != -1 && newVariableIndex != -1) { - // Renaming one existing variable to another existing variable. - this.variableList.splice(variableIndex, 1); - // The case might have changed. - this.variableList[newVariableIndex] = newName; - } else { - this.variableList.push(newName); - console.log('Tried to rename an non-existent variable.'); - } -}; - -/** - * Create a variable with the given name. - * TODO: #468 - * @param {string} name The new variable's name. - */ -Blockly.Workspace.prototype.createVariable = function(name) { - var index = this.variableIndexOf(name); - if (index == -1) { - this.variableList.push(name); - } -}; - -/** - * Find all the uses of a named variable. - * @param {string} name Name of variable. - * @return {!Array.} Array of block usages. - */ -Blockly.Workspace.prototype.getVariableUses = function(name) { - var uses = []; - var blocks = this.getAllBlocks(); - // Iterate through every block and check the name. - for (var i = 0; i < blocks.length; i++) { - var blockVariables = blocks[i].getVars(); - if (blockVariables) { - for (var j = 0; j < blockVariables.length; j++) { - var varName = blockVariables[j]; - // Variable name may be null if the block is only half-built. - if (varName && Blockly.Names.equals(varName, name)) { - uses.push(blocks[i]); - } - } - } - } - return uses; -}; - -/** - * Delete a variables and all of its uses from this workspace. - * @param {string} name Name of variable to delete. - */ -Blockly.Workspace.prototype.deleteVariable = function(name) { - var variableIndex = this.variableIndexOf(name); - if (variableIndex != -1) { - var uses = this.getVariableUses(name); - if (uses.length > 1) { - for (var i = 0, block; block = uses[i]; i++) { - if (block.type == 'procedures_defnoreturn' || - block.type == 'procedures_defreturn') { - var procedureName = block.getFieldValue('NAME'); - window.alert( - Blockly.Msg.CANNOT_DELETE_VARIABLE_PROCEDURE.replace('%1', name). - replace('%2', procedureName)); - return; - } - } - var ok = window.confirm( - Blockly.Msg.DELETE_VARIABLE_CONFIRMATION.replace('%1', uses.length). - replace('%2', name)); - if (!ok) { - return; - } - } - - Blockly.Events.setGroup(true); - for (var i = 0; i < uses.length; i++) { - uses[i].dispose(true, false); - } - Blockly.Events.setGroup(false); - this.variableList.splice(variableIndex, 1); - } -}; - -/** - * Check whether a variable exists with the given name. The check is - * case-insensitive. - * @param {string} name The name to check for. - * @return {number} The index of the name in the variable list, or -1 if it is - * not present. - */ -Blockly.Workspace.prototype.variableIndexOf = function(name) { - for (var i = 0, varname; varname = this.variableList[i]; i++) { - if (Blockly.Names.equals(varname, name)) { - return i; - } - } - return -1; -}; - -/** - * Returns the horizontal offset of the workspace. - * Intended for LTR/RTL compatibility in XML. - * Not relevant for a headless workspace. - * @return {number} Width. - */ -Blockly.Workspace.prototype.getWidth = function() { - return 0; -}; - -/** - * Obtain a newly created block. - * @param {?string} prototypeName Name of the language object containing - * type-specific functions for this block. - * @param {=string} opt_id Optional ID. Use this ID if provided, otherwise - * create a new id. - * @return {!Blockly.Block} The created block. - */ -Blockly.Workspace.prototype.newBlock = function(prototypeName, opt_id) { - return new Blockly.Block(this, prototypeName, opt_id); -}; - -/** - * The number of blocks that may be added to the workspace before reaching - * the maxBlocks. - * @return {number} Number of blocks left. - */ -Blockly.Workspace.prototype.remainingCapacity = function() { - if (isNaN(this.options.maxBlocks)) { - return Infinity; - } - return this.options.maxBlocks - this.getAllBlocks().length; -}; - -/** - * Undo or redo the previous action. - * @param {boolean} redo False if undo, true if redo. - */ -Blockly.Workspace.prototype.undo = function(redo) { - var inputStack = redo ? this.redoStack_ : this.undoStack_; - var outputStack = redo ? this.undoStack_ : this.redoStack_; - var inputEvent = inputStack.pop(); - if (!inputEvent) { - return; - } - var events = [inputEvent]; - // Do another undo/redo if the next one is of the same group. - while (inputStack.length && inputEvent.group && - inputEvent.group == inputStack[inputStack.length - 1].group) { - events.push(inputStack.pop()); - } - // Push these popped events on the opposite stack. - for (var i = 0, event; event = events[i]; i++) { - outputStack.push(event); - } - events = Blockly.Events.filter(events, redo); - Blockly.Events.recordUndo = false; - for (var i = 0, event; event = events[i]; i++) { - event.run(redo); - } - Blockly.Events.recordUndo = true; -}; - -/** - * Clear the undo/redo stacks. - */ -Blockly.Workspace.prototype.clearUndo = function() { - this.undoStack_.length = 0; - this.redoStack_.length = 0; - // Stop any events already in the firing queue from being undoable. - Blockly.Events.clearPendingUndo(); -}; - -/** - * When something in this workspace changes, call a function. - * @param {!Function} func Function to call. - * @return {!Function} Function that can be passed to - * removeChangeListener. - */ -Blockly.Workspace.prototype.addChangeListener = function(func) { - this.listeners_.push(func); - return func; -}; - -/** - * Stop listening for this workspace's changes. - * @param {Function} func Function to stop calling. - */ -Blockly.Workspace.prototype.removeChangeListener = function(func) { - var i = this.listeners_.indexOf(func); - if (i != -1) { - this.listeners_.splice(i, 1); - } -}; - -/** - * Fire a change event. - * @param {!Blockly.Events.Abstract} event Event to fire. - */ -Blockly.Workspace.prototype.fireChangeListener = function(event) { - if (event.recordUndo) { - this.undoStack_.push(event); - this.redoStack_.length = 0; - if (this.undoStack_.length > this.MAX_UNDO) { - this.undoStack_.unshift(); - } - } - for (var i = 0, func; func = this.listeners_[i]; i++) { - func(event); - } -}; - -/** - * Find the block on this workspace with the specified ID. - * @param {string} id ID of block to find. - * @return {Blockly.Block} The sought after block or null if not found. - */ -Blockly.Workspace.prototype.getBlockById = function(id) { - return this.blockDB_[id] || null; -}; - -/** - * Database of all workspaces. - * @private - */ -Blockly.Workspace.WorkspaceDB_ = Object.create(null); - -/** - * Find the workspace with the specified ID. - * @param {string} id ID of workspace to find. - * @return {Blockly.Workspace} The sought after workspace or null if not found. - */ -Blockly.Workspace.getById = function(id) { - return Blockly.Workspace.WorkspaceDB_[id] || null; -}; - -// Export symbols that would otherwise be renamed by Closure compiler. -Blockly.Workspace.prototype['clear'] = Blockly.Workspace.prototype.clear; -Blockly.Workspace.prototype['clearUndo'] = - Blockly.Workspace.prototype.clearUndo; -Blockly.Workspace.prototype['addChangeListener'] = - Blockly.Workspace.prototype.addChangeListener; -Blockly.Workspace.prototype['removeChangeListener'] = - Blockly.Workspace.prototype.removeChangeListener; diff --git a/backend/_pv_1_3_5/static/blockly/core/workspace_svg.js b/backend/_pv_1_3_5/static/blockly/core/workspace_svg.js deleted file mode 100755 index a3c0b5344..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/workspace_svg.js +++ /dev/null @@ -1,1401 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2014 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Object representing a workspace rendered as SVG. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.WorkspaceSvg'); - -// TODO(scr): Fix circular dependencies -//goog.require('Blockly.BlockSvg'); -goog.require('Blockly.ConnectionDB'); -goog.require('Blockly.constants'); -goog.require('Blockly.Options'); -goog.require('Blockly.ScrollbarPair'); -goog.require('Blockly.Trashcan'); -goog.require('Blockly.Workspace'); -goog.require('Blockly.Xml'); -goog.require('Blockly.ZoomControls'); - -goog.require('goog.dom'); -goog.require('goog.math.Coordinate'); -goog.require('goog.userAgent'); - - -/** - * Class for a workspace. This is an onscreen area with optional trashcan, - * scrollbars, bubbles, and dragging. - * @param {!Blockly.Options} options Dictionary of options. - * @extends {Blockly.Workspace} - * @constructor - */ -Blockly.WorkspaceSvg = function(options) { - Blockly.WorkspaceSvg.superClass_.constructor.call(this, options); - this.getMetrics = - options.getMetrics || Blockly.WorkspaceSvg.getTopLevelWorkspaceMetrics_; - this.setMetrics = - options.setMetrics || Blockly.WorkspaceSvg.setTopLevelWorkspaceMetrics_; - - Blockly.ConnectionDB.init(this); - - /** - * Database of pre-loaded sounds. - * @private - * @const - */ - this.SOUNDS_ = Object.create(null); -}; -goog.inherits(Blockly.WorkspaceSvg, Blockly.Workspace); - -/** - * Wrapper function called when a resize event occurs. - * @type {Array.} Data that can be passed to unbindEvent_ - */ -Blockly.WorkspaceSvg.prototype.resizeHandlerWrapper_ = null; - -/** - * Svg workspaces are user-visible (as opposed to a headless workspace). - * @type {boolean} True if visible. False if headless. - */ -Blockly.WorkspaceSvg.prototype.rendered = true; - -/** - * Is this workspace the surface for a flyout? - * @type {boolean} - */ -Blockly.WorkspaceSvg.prototype.isFlyout = false; - -/** - * Is this workspace the surface for a mutator? - * @type {boolean} - * @package - */ -Blockly.WorkspaceSvg.prototype.isMutator = false; - -/** - * Is this workspace currently being dragged around? - * DRAG_NONE - No drag operation. - * DRAG_BEGIN - Still inside the initial DRAG_RADIUS. - * DRAG_FREE - Workspace has been dragged further than DRAG_RADIUS. - * @private - */ -Blockly.WorkspaceSvg.prototype.dragMode_ = Blockly.DRAG_NONE; - -/** - * Current horizontal scrolling offset. - * @type {number} - */ -Blockly.WorkspaceSvg.prototype.scrollX = 0; - -/** - * Current vertical scrolling offset. - * @type {number} - */ -Blockly.WorkspaceSvg.prototype.scrollY = 0; - -/** - * Horizontal scroll value when scrolling started. - * @type {number} - */ -Blockly.WorkspaceSvg.prototype.startScrollX = 0; - -/** - * Vertical scroll value when scrolling started. - * @type {number} - */ -Blockly.WorkspaceSvg.prototype.startScrollY = 0; - -/** - * Distance from mouse to object being dragged. - * @type {goog.math.Coordinate} - * @private - */ -Blockly.WorkspaceSvg.prototype.dragDeltaXY_ = null; - -/** - * Current scale. - * @type {number} - */ -Blockly.WorkspaceSvg.prototype.scale = 1; - -/** - * The workspace's trashcan (if any). - * @type {Blockly.Trashcan} - */ -Blockly.WorkspaceSvg.prototype.trashcan = null; - -/** - * This workspace's scrollbars, if they exist. - * @type {Blockly.ScrollbarPair} - */ -Blockly.WorkspaceSvg.prototype.scrollbar = null; - -/** - * Time that the last sound was played. - * @type {Date} - * @private - */ -Blockly.WorkspaceSvg.prototype.lastSound_ = null; - -/** - * Last known position of the page scroll. - * This is used to determine whether we have recalculated screen coordinate - * stuff since the page scrolled. - * @type {!goog.math.Coordinate} - * @private - */ -Blockly.WorkspaceSvg.prototype.lastRecordedPageScroll_ = null; - -/** - * Inverted screen CTM, for use in mouseToSvg. - * @type {SVGMatrix} - * @private - */ -Blockly.WorkspaceSvg.prototype.inverseScreenCTM_ = null; - -/** - * Getter for the inverted screen CTM. - * @return {SVGMatrix} The matrix to use in mouseToSvg - */ -Blockly.WorkspaceSvg.prototype.getInverseScreenCTM = function() { - return this.inverseScreenCTM_; -}; - -/** - * Update the inverted screen CTM. - */ -Blockly.WorkspaceSvg.prototype.updateInverseScreenCTM = function() { - this.inverseScreenCTM_ = this.getParentSvg().getScreenCTM().inverse(); -}; - -/** - * Save resize handler data so we can delete it later in dispose. - * @param {!Array.} handler Data that can be passed to unbindEvent_. - */ -Blockly.WorkspaceSvg.prototype.setResizeHandlerWrapper = function(handler) { - this.resizeHandlerWrapper_ = handler; -}; - -/** - * Create the workspace DOM elements. - * @param {string=} opt_backgroundClass Either 'blocklyMainBackground' or - * 'blocklyMutatorBackground'. - * @return {!Element} The workspace's SVG group. - */ -Blockly.WorkspaceSvg.prototype.createDom = function(opt_backgroundClass) { - /** - * - * - * [Trashcan and/or flyout may go here] - * - * - * [Scrollbars may go here] - * - * @type {SVGElement} - */ - this.svgGroup_ = Blockly.createSvgElement('g', - {'class': 'blocklyWorkspace'}, null); - if (opt_backgroundClass) { - /** @type {SVGElement} */ - this.svgBackground_ = Blockly.createSvgElement('rect', - {'height': '100%', 'width': '100%', 'class': opt_backgroundClass}, - this.svgGroup_); - if (opt_backgroundClass == 'blocklyMainBackground') { - this.svgBackground_.style.fill = - 'url(#' + this.options.gridPattern.id + ')'; - } - } - /** @type {SVGElement} */ - this.svgBlockCanvas_ = Blockly.createSvgElement('g', - {'class': 'blocklyBlockCanvas'}, this.svgGroup_, this); - /** @type {SVGElement} */ - this.svgBubbleCanvas_ = Blockly.createSvgElement('g', - {'class': 'blocklyBubbleCanvas'}, this.svgGroup_, this); - var bottom = Blockly.Scrollbar.scrollbarThickness; - if (this.options.hasTrashcan) { - bottom = this.addTrashcan_(bottom); - } - if (this.options.zoomOptions && this.options.zoomOptions.controls) { - bottom = this.addZoomControls_(bottom); - } - - if (!this.isFlyout) { - Blockly.bindEvent_(this.svgGroup_, 'mousedown', this, this.onMouseDown_); - var thisWorkspace = this; - Blockly.bindEvent_(this.svgGroup_, 'touchstart', null, - function(e) {Blockly.longStart_(e, thisWorkspace);}); - if (this.options.zoomOptions && this.options.zoomOptions.wheel) { - // Mouse-wheel. - Blockly.bindEvent_(this.svgGroup_, 'wheel', this, this.onMouseWheel_); - } - } - - // Determine if there needs to be a category tree, or a simple list of - // blocks. This cannot be changed later, since the UI is very different. - if (this.options.hasCategories) { - this.toolbox_ = new Blockly.Toolbox(this); - } else if (this.options.languageTree) { - this.addFlyout_(); - } - this.updateGridPattern_(); - this.recordDeleteAreas(); - return this.svgGroup_; -}; - -/** - * Dispose of this workspace. - * Unlink from all DOM elements to prevent memory leaks. - */ -Blockly.WorkspaceSvg.prototype.dispose = function() { - // Stop rerendering. - this.rendered = false; - Blockly.WorkspaceSvg.superClass_.dispose.call(this); - if (this.svgGroup_) { - goog.dom.removeNode(this.svgGroup_); - this.svgGroup_ = null; - } - this.svgBlockCanvas_ = null; - this.svgBubbleCanvas_ = null; - if (this.toolbox_) { - this.toolbox_.dispose(); - this.toolbox_ = null; - } - if (this.flyout_) { - this.flyout_.dispose(); - this.flyout_ = null; - } - if (this.trashcan) { - this.trashcan.dispose(); - this.trashcan = null; - } - if (this.scrollbar) { - this.scrollbar.dispose(); - this.scrollbar = null; - } - if (this.zoomControls_) { - this.zoomControls_.dispose(); - this.zoomControls_ = null; - } - if (!this.options.parentWorkspace) { - // Top-most workspace. Dispose of the div that the - // svg is injected into (i.e. injectionDiv). - goog.dom.removeNode(this.getParentSvg().parentNode); - } - if (this.resizeHandlerWrapper_) { - Blockly.unbindEvent_(this.resizeHandlerWrapper_); - this.resizeHandlerWrapper_ = null; - } -}; - -/** - * Obtain a newly created block. - * @param {?string} prototypeName Name of the language object containing - * type-specific functions for this block. - * @param {=string} opt_id Optional ID. Use this ID if provided, otherwise - * create a new id. - * @return {!Blockly.BlockSvg} The created block. - */ -Blockly.WorkspaceSvg.prototype.newBlock = function(prototypeName, opt_id) { - return new Blockly.BlockSvg(this, prototypeName, opt_id); -}; - -/** - * Add a trashcan. - * @param {number} bottom Distance from workspace bottom to bottom of trashcan. - * @return {number} Distance from workspace bottom to the top of trashcan. - * @private - */ -Blockly.WorkspaceSvg.prototype.addTrashcan_ = function(bottom) { - /** @type {Blockly.Trashcan} */ - this.trashcan = new Blockly.Trashcan(this); - var svgTrashcan = this.trashcan.createDom(); - this.svgGroup_.insertBefore(svgTrashcan, this.svgBlockCanvas_); - return this.trashcan.init(bottom); -}; - -/** - * Add zoom controls. - * @param {number} bottom Distance from workspace bottom to bottom of controls. - * @return {number} Distance from workspace bottom to the top of controls. - * @private - */ -Blockly.WorkspaceSvg.prototype.addZoomControls_ = function(bottom) { - /** @type {Blockly.ZoomControls} */ - this.zoomControls_ = new Blockly.ZoomControls(this); - var svgZoomControls = this.zoomControls_.createDom(); - this.svgGroup_.appendChild(svgZoomControls); - return this.zoomControls_.init(bottom); -}; - -/** - * Add a flyout. - * @private - */ -Blockly.WorkspaceSvg.prototype.addFlyout_ = function() { - var workspaceOptions = { - disabledPatternId: this.options.disabledPatternId, - parentWorkspace: this, - RTL: this.RTL, - horizontalLayout: this.horizontalLayout, - toolboxPosition: this.options.toolboxPosition - }; - /** @type {Blockly.Flyout} */ - this.flyout_ = new Blockly.Flyout(workspaceOptions); - this.flyout_.autoClose = false; - var svgFlyout = this.flyout_.createDom(); - this.svgGroup_.insertBefore(svgFlyout, this.svgBlockCanvas_); -}; - -/** - * Update items that use screen coordinate calculations - * because something has changed (e.g. scroll position, window size). - * @private - */ -Blockly.WorkspaceSvg.prototype.updateScreenCalculations_ = function() { - this.updateInverseScreenCTM(); - this.recordDeleteAreas(); -}; - -/** - * Resize the parts of the workspace that change when the workspace - * contents (e.g. block positions) change. This will also scroll the - * workspace contents if needed. - * @package - */ -Blockly.WorkspaceSvg.prototype.resizeContents = function() { - if (this.scrollbar) { - // TODO(picklesrus): Once rachel-fenichel's scrollbar refactoring - // is complete, call the method that only resizes scrollbar - // based on contents. - this.scrollbar.resize(); - } - this.updateInverseScreenCTM(); -}; - -/** - * Resize and reposition all of the workspace chrome (toolbox, - * trash, scrollbars etc.) - * This should be called when something changes that - * requires recalculating dimensions and positions of the - * trash, zoom, toolbox, etc. (e.g. window resize). - */ -Blockly.WorkspaceSvg.prototype.resize = function() { - if (this.toolbox_) { - this.toolbox_.position(); - } - if (this.flyout_) { - this.flyout_.position(); - } - if (this.trashcan) { - this.trashcan.position(); - } - if (this.zoomControls_) { - this.zoomControls_.position(); - } - if (this.scrollbar) { - this.scrollbar.resize(); - } - this.updateScreenCalculations_(); -}; - -/** - * Resizes and repositions workspace chrome if the page has a new - * scroll position. - * @package - */ -Blockly.WorkspaceSvg.prototype.updateScreenCalculationsIfScrolled - = function() { - /* eslint-disable indent */ - var currScroll = goog.dom.getDocumentScroll(); - if (!goog.math.Coordinate.equals(this.lastRecordedPageScroll_, - currScroll)) { - this.lastRecordedPageScroll_ = currScroll; - this.updateScreenCalculations_(); - } -}; /* eslint-enable indent */ - -/** - * Get the SVG element that forms the drawing surface. - * @return {!Element} SVG element. - */ -Blockly.WorkspaceSvg.prototype.getCanvas = function() { - return this.svgBlockCanvas_; -}; - -/** - * Get the SVG element that forms the bubble surface. - * @return {!SVGGElement} SVG element. - */ -Blockly.WorkspaceSvg.prototype.getBubbleCanvas = function() { - return this.svgBubbleCanvas_; -}; - -/** - * Get the SVG element that contains this workspace. - * @return {!Element} SVG element. - */ -Blockly.WorkspaceSvg.prototype.getParentSvg = function() { - if (this.cachedParentSvg_) { - return this.cachedParentSvg_; - } - var element = this.svgGroup_; - while (element) { - if (element.tagName == 'svg') { - this.cachedParentSvg_ = element; - return element; - } - element = element.parentNode; - } - return null; -}; - -/** - * Translate this workspace to new coordinates. - * @param {number} x Horizontal translation. - * @param {number} y Vertical translation. - */ -Blockly.WorkspaceSvg.prototype.translate = function(x, y) { - var translation = 'translate(' + x + ',' + y + ') ' + - 'scale(' + this.scale + ')'; - this.svgBlockCanvas_.setAttribute('transform', translation); - this.svgBubbleCanvas_.setAttribute('transform', translation); -}; - -/** - * Returns the horizontal offset of the workspace. - * Intended for LTR/RTL compatibility in XML. - * @return {number} Width. - */ -Blockly.WorkspaceSvg.prototype.getWidth = function() { - var metrics = this.getMetrics(); - return metrics ? metrics.viewWidth / this.scale : 0; -}; - -/** - * Toggles the visibility of the workspace. - * Currently only intended for main workspace. - * @param {boolean} isVisible True if workspace should be visible. - */ -Blockly.WorkspaceSvg.prototype.setVisible = function(isVisible) { - this.getParentSvg().style.display = isVisible ? 'block' : 'none'; - if (this.toolbox_) { - // Currently does not support toolboxes in mutators. - this.toolbox_.HtmlDiv.style.display = isVisible ? 'block' : 'none'; - } - if (isVisible) { - this.render(); - if (this.toolbox_) { - this.toolbox_.position(); - } - } else { - Blockly.hideChaff(true); - } -}; - -/** - * Render all blocks in workspace. - */ -Blockly.WorkspaceSvg.prototype.render = function() { - // Generate list of all blocks. - var blocks = this.getAllBlocks(); - // Render each block. - for (var i = blocks.length - 1; i >= 0; i--) { - blocks[i].render(false); - } -}; - -/** - * Turn the visual trace functionality on or off. - * @param {boolean} armed True if the trace should be on. - */ -Blockly.WorkspaceSvg.prototype.traceOn = function(armed) { - this.traceOn_ = armed; - if (this.traceWrapper_) { - Blockly.unbindEvent_(this.traceWrapper_); - this.traceWrapper_ = null; - } - if (armed) { - this.traceWrapper_ = Blockly.bindEvent_(this.svgBlockCanvas_, - 'blocklySelectChange', this, function() {this.traceOn_ = false;}); - } -}; - -/** - * Highlight a block in the workspace. - * @param {?string} id ID of block to find. - */ -Blockly.WorkspaceSvg.prototype.highlightBlock = function(id) { - if (this.traceOn_ && Blockly.dragMode_ != Blockly.DRAG_NONE) { - // The blocklySelectChange event normally prevents this, but sometimes - // there is a race condition on fast-executing apps. - this.traceOn(false); - } - if (!this.traceOn_) { - return; - } - var block = null; - if (id) { - block = this.getBlockById(id); - if (!block) { - return; - } - } - // Temporary turn off the listener for selection changes, so that we don't - // trip the monitor for detecting user activity. - this.traceOn(false); - // Select the current block. - if (block) { - block.select(); - } else if (Blockly.selected) { - Blockly.selected.unselect(); - } - // Restore the monitor for user activity after the selection event has fired. - var thisWorkspace = this; - setTimeout(function() {thisWorkspace.traceOn(true);}, 1); -}; - -/** - * Paste the provided block onto the workspace. - * @param {!Element} xmlBlock XML block element. - */ -Blockly.WorkspaceSvg.prototype.paste = function(xmlBlock) { - if (!this.rendered || xmlBlock.getElementsByTagName('block').length >= - this.remainingCapacity()) { - return; - } - Blockly.terminateDrag_(); // Dragging while pasting? No. - Blockly.Events.disable(); - try { - var block = Blockly.Xml.domToBlock(xmlBlock, this); - // Move the duplicate to original position. - var blockX = parseInt(xmlBlock.getAttribute('x'), 10); - var blockY = parseInt(xmlBlock.getAttribute('y'), 10); - if (!isNaN(blockX) && !isNaN(blockY)) { - if (this.RTL) { - blockX = -blockX; - } - // Offset block until not clobbering another block and not in connection - // distance with neighbouring blocks. - do { - var collide = false; - var allBlocks = this.getAllBlocks(); - for (var i = 0, otherBlock; otherBlock = allBlocks[i]; i++) { - var otherXY = otherBlock.getRelativeToSurfaceXY(); - if (Math.abs(blockX - otherXY.x) <= 1 && - Math.abs(blockY - otherXY.y) <= 1) { - collide = true; - break; - } - } - if (!collide) { - // Check for blocks in snap range to any of its connections. - var connections = block.getConnections_(false); - for (var i = 0, connection; connection = connections[i]; i++) { - var neighbour = connection.closest(Blockly.SNAP_RADIUS, - new goog.math.Coordinate(blockX, blockY)); - if (neighbour.connection) { - collide = true; - break; - } - } - } - if (collide) { - if (this.RTL) { - blockX -= Blockly.SNAP_RADIUS; - } else { - blockX += Blockly.SNAP_RADIUS; - } - blockY += Blockly.SNAP_RADIUS * 2; - } - } while (collide); - block.moveBy(blockX, blockY); - } - } finally { - Blockly.Events.enable(); - } - if (Blockly.Events.isEnabled() && !block.isShadow()) { - Blockly.Events.fire(new Blockly.Events.Create(block)); - } - block.select(); -}; - -/** - * Create a new variable with the given name. Update the flyout to show the new - * variable immediately. - * TODO: #468 - * @param {string} name The new variable's name. - */ -Blockly.WorkspaceSvg.prototype.createVariable = function(name) { - Blockly.WorkspaceSvg.superClass_.createVariable.call(this, name); - if (this.toolbox_ && this.toolbox_.flyout_) { - this.toolbox_.refreshSelection(); - } -}; - -/** - * Make a list of all the delete areas for this workspace. - */ -Blockly.WorkspaceSvg.prototype.recordDeleteAreas = function() { - if (this.trashcan) { - this.deleteAreaTrash_ = this.trashcan.getClientRect(); - } else { - this.deleteAreaTrash_ = null; - } - if (this.flyout_) { - this.deleteAreaToolbox_ = this.flyout_.getClientRect(); - } else if (this.toolbox_) { - this.deleteAreaToolbox_ = this.toolbox_.getClientRect(); - } else { - this.deleteAreaToolbox_ = null; - } -}; - -/** - * Is the mouse event over a delete area (toolbox or non-closing flyout)? - * Opens or closes the trashcan and sets the cursor as a side effect. - * @param {!Event} e Mouse move event. - * @return {boolean} True if event is in a delete area. - */ -Blockly.WorkspaceSvg.prototype.isDeleteArea = function(e) { - var xy = new goog.math.Coordinate(e.clientX, e.clientY); - if (this.deleteAreaTrash_) { - if (this.deleteAreaTrash_.contains(xy)) { - this.trashcan.setOpen_(true); - Blockly.Css.setCursor(Blockly.Css.Cursor.DELETE); - return true; - } - this.trashcan.setOpen_(false); - } - if (this.deleteAreaToolbox_) { - if (this.deleteAreaToolbox_.contains(xy)) { - Blockly.Css.setCursor(Blockly.Css.Cursor.DELETE); - return true; - } - } - Blockly.Css.setCursor(Blockly.Css.Cursor.CLOSED); - return false; -}; - -/** - * Handle a mouse-down on SVG drawing surface. - * @param {!Event} e Mouse down event. - * @private - */ -Blockly.WorkspaceSvg.prototype.onMouseDown_ = function(e) { - this.markFocused(); - if (Blockly.isTargetInput_(e)) { - return; - } - Blockly.terminateDrag_(); // In case mouse-up event was lost. - Blockly.hideChaff(); - var isTargetWorkspace = e.target && e.target.nodeName && - (e.target.nodeName.toLowerCase() == 'svg' || - e.target == this.svgBackground_); - if (isTargetWorkspace && Blockly.selected && !this.options.readOnly) { - // Clicking on the document clears the selection. - Blockly.selected.unselect(); - } - if (Blockly.isRightButton(e)) { - // Right-click. - this.showContextMenu_(e); - } else if (this.scrollbar) { - this.dragMode_ = Blockly.DRAG_BEGIN; - // Record the current mouse position. - this.startDragMouseX = e.clientX; - this.startDragMouseY = e.clientY; - this.startDragMetrics = this.getMetrics(); - this.startScrollX = this.scrollX; - this.startScrollY = this.scrollY; - - // If this is a touch event then bind to the mouseup so workspace drag mode - // is turned off and double move events are not performed on a block. - // See comment in inject.js Blockly.init_ as to why mouseup events are - // bound to the document instead of the SVG's surface. - if ('mouseup' in Blockly.bindEvent_.TOUCH_MAP) { - Blockly.onTouchUpWrapper_ = Blockly.onTouchUpWrapper_ || []; - Blockly.onTouchUpWrapper_ = Blockly.onTouchUpWrapper_.concat( - Blockly.bindEvent_(document, 'mouseup', null, Blockly.onMouseUp_)); - } - Blockly.onMouseMoveWrapper_ = Blockly.onMouseMoveWrapper_ || []; - Blockly.onMouseMoveWrapper_ = Blockly.onMouseMoveWrapper_.concat( - Blockly.bindEvent_(document, 'mousemove', null, Blockly.onMouseMove_)); - } - // This event has been handled. No need to bubble up to the document. - e.stopPropagation(); - e.preventDefault(); -}; - -/** - * Start tracking a drag of an object on this workspace. - * @param {!Event} e Mouse down event. - * @param {!goog.math.Coordinate} xy Starting location of object. - */ -Blockly.WorkspaceSvg.prototype.startDrag = function(e, xy) { - // Record the starting offset between the bubble's location and the mouse. - var point = Blockly.mouseToSvg(e, this.getParentSvg(), - this.getInverseScreenCTM()); - // Fix scale of mouse event. - point.x /= this.scale; - point.y /= this.scale; - this.dragDeltaXY_ = goog.math.Coordinate.difference(xy, point); -}; - -/** - * Track a drag of an object on this workspace. - * @param {!Event} e Mouse move event. - * @return {!goog.math.Coordinate} New location of object. - */ -Blockly.WorkspaceSvg.prototype.moveDrag = function(e) { - var point = Blockly.mouseToSvg(e, this.getParentSvg(), - this.getInverseScreenCTM()); - // Fix scale of mouse event. - point.x /= this.scale; - point.y /= this.scale; - return goog.math.Coordinate.sum(this.dragDeltaXY_, point); -}; - -/** - * Is the user currently dragging a block or scrolling the flyout/workspace? - * @return {boolean} True if currently dragging or scrolling. - */ -Blockly.WorkspaceSvg.prototype.isDragging = function() { - return Blockly.dragMode_ == Blockly.DRAG_FREE || - (Blockly.Flyout.startFlyout_ && - Blockly.Flyout.startFlyout_.dragMode_ == Blockly.DRAG_FREE) || - this.dragMode_ == Blockly.DRAG_FREE; -}; - -/** - * Handle a mouse-wheel on SVG drawing surface. - * @param {!Event} e Mouse wheel event. - * @private - */ -Blockly.WorkspaceSvg.prototype.onMouseWheel_ = function(e) { - // TODO: Remove terminateDrag and compensate for coordinate skew during zoom. - Blockly.terminateDrag_(); - var delta = e.deltaY > 0 ? -1 : 1; - var position = Blockly.mouseToSvg(e, this.getParentSvg(), - this.getInverseScreenCTM()); - this.zoom(position.x, position.y, delta); - e.preventDefault(); -}; - -/** - * Calculate the bounding box for the blocks on the workspace. - * - * @return {Object} Contains the position and size of the bounding box - * containing the blocks on the workspace. - */ -Blockly.WorkspaceSvg.prototype.getBlocksBoundingBox = function() { - var topBlocks = this.getTopBlocks(false); - // There are no blocks, return empty rectangle. - if (!topBlocks.length) { - return {x: 0, y: 0, width: 0, height: 0}; - } - - // Initialize boundary using the first block. - var boundary = topBlocks[0].getBoundingRectangle(); - - // Start at 1 since the 0th block was used for initialization - for (var i = 1; i < topBlocks.length; i++) { - var blockBoundary = topBlocks[i].getBoundingRectangle(); - if (blockBoundary.topLeft.x < boundary.topLeft.x) { - boundary.topLeft.x = blockBoundary.topLeft.x; - } - if (blockBoundary.bottomRight.x > boundary.bottomRight.x) { - boundary.bottomRight.x = blockBoundary.bottomRight.x; - } - if (blockBoundary.topLeft.y < boundary.topLeft.y) { - boundary.topLeft.y = blockBoundary.topLeft.y; - } - if (blockBoundary.bottomRight.y > boundary.bottomRight.y) { - boundary.bottomRight.y = blockBoundary.bottomRight.y; - } - } - return { - x: boundary.topLeft.x, - y: boundary.topLeft.y, - width: boundary.bottomRight.x - boundary.topLeft.x, - height: boundary.bottomRight.y - boundary.topLeft.y - }; -}; - -/** - * Clean up the workspace by ordering all the blocks in a column. - */ -Blockly.WorkspaceSvg.prototype.cleanUp = function() { - Blockly.Events.setGroup(true); - var topBlocks = this.getTopBlocks(true); - var cursorY = 0; - for (var i = 0, block; block = topBlocks[i]; i++) { - var xy = block.getRelativeToSurfaceXY(); - block.moveBy(-xy.x, cursorY - xy.y); - block.snapToGrid(); - cursorY = block.getRelativeToSurfaceXY().y + - block.getHeightWidth().height + Blockly.BlockSvg.MIN_BLOCK_Y; - } - Blockly.Events.setGroup(false); - // Fire an event to allow scrollbars to resize. - this.resizeContents(); -}; - -/** - * Show the context menu for the workspace. - * @param {!Event} e Mouse event. - * @private - */ -Blockly.WorkspaceSvg.prototype.showContextMenu_ = function(e) { - if (this.options.readOnly || this.isFlyout) { - return; - } - var menuOptions = []; - var topBlocks = this.getTopBlocks(true); - var eventGroup = Blockly.genUid(); - - // Options to undo/redo previous action. - var undoOption = {}; - undoOption.text = Blockly.Msg.UNDO; - undoOption.enabled = this.undoStack_.length > 0; - undoOption.callback = this.undo.bind(this, false); - menuOptions.push(undoOption); - var redoOption = {}; - redoOption.text = Blockly.Msg.REDO; - redoOption.enabled = this.redoStack_.length > 0; - redoOption.callback = this.undo.bind(this, true); - menuOptions.push(redoOption); - - // Option to clean up blocks. - if (this.scrollbar) { - var cleanOption = {}; - cleanOption.text = Blockly.Msg.CLEAN_UP; - cleanOption.enabled = topBlocks.length > 1; - cleanOption.callback = this.cleanUp.bind(this); - menuOptions.push(cleanOption); - } - - // Add a little animation to collapsing and expanding. - var DELAY = 10; - if (this.options.collapse) { - var hasCollapsedBlocks = false; - var hasExpandedBlocks = false; - for (var i = 0; i < topBlocks.length; i++) { - var block = topBlocks[i]; - while (block) { - if (block.isCollapsed()) { - hasCollapsedBlocks = true; - } else { - hasExpandedBlocks = true; - } - block = block.getNextBlock(); - } - } - - /** - * Option to collapse or expand top blocks. - * @param {boolean} shouldCollapse Whether a block should collapse. - * @private - */ - var toggleOption = function(shouldCollapse) { - var ms = 0; - for (var i = 0; i < topBlocks.length; i++) { - var block = topBlocks[i]; - while (block) { - setTimeout(block.setCollapsed.bind(block, shouldCollapse), ms); - block = block.getNextBlock(); - ms += DELAY; - } - } - }; - - // Option to collapse top blocks. - var collapseOption = {enabled: hasExpandedBlocks}; - collapseOption.text = Blockly.Msg.COLLAPSE_ALL; - collapseOption.callback = function() { - toggleOption(true); - }; - menuOptions.push(collapseOption); - - // Option to expand top blocks. - var expandOption = {enabled: hasCollapsedBlocks}; - expandOption.text = Blockly.Msg.EXPAND_ALL; - expandOption.callback = function() { - toggleOption(false); - }; - menuOptions.push(expandOption); - } - - // Option to delete all blocks. - // Count the number of blocks that are deletable. - var deleteList = []; - function addDeletableBlocks(block) { - if (block.isDeletable()) { - deleteList = deleteList.concat(block.getDescendants()); - } else { - var children = block.getChildren(); - for (var i = 0; i < children.length; i++) { - addDeletableBlocks(children[i]); - } - } - } - for (var i = 0; i < topBlocks.length; i++) { - addDeletableBlocks(topBlocks[i]); - } - - function deleteNext() { - Blockly.Events.setGroup(eventGroup); - var block = deleteList.shift(); - if (block) { - if (block.workspace) { - block.dispose(false, true); - setTimeout(deleteNext, DELAY); - } else { - deleteNext(); - } - } - Blockly.Events.setGroup(false); - } - - var deleteOption = { - text: deleteList.length == 1 ? Blockly.Msg.DELETE_BLOCK : - Blockly.Msg.DELETE_X_BLOCKS.replace('%1', String(deleteList.length)), - enabled: deleteList.length > 0, - callback: function() { - if (deleteList.length < 2 || - window.confirm(Blockly.Msg.DELETE_ALL_BLOCKS.replace('%1', - String(deleteList.length)))) { - deleteNext(); - } - } - }; - menuOptions.push(deleteOption); - - Blockly.ContextMenu.show(e, menuOptions, this.RTL); -}; - -/** - * Load an audio file. Cache it, ready for instantaneous playing. - * @param {!Array.} filenames List of file types in decreasing order of - * preference (i.e. increasing size). E.g. ['media/go.mp3', 'media/go.wav'] - * Filenames include path from Blockly's root. File extensions matter. - * @param {string} name Name of sound. - * @private - */ -Blockly.WorkspaceSvg.prototype.loadAudio_ = function(filenames, name) { - if (!filenames.length) { - return; - } - try { - var audioTest = new window['Audio'](); - } catch (e) { - // No browser support for Audio. - // IE can throw an error even if the Audio object exists. - return; - } - var sound; - for (var i = 0; i < filenames.length; i++) { - var filename = filenames[i]; - var ext = filename.match(/\.(\w+)$/); - if (ext && audioTest.canPlayType('audio/' + ext[1])) { - // Found an audio format we can play. - sound = new window['Audio'](filename); - break; - } - } - if (sound && sound.play) { - this.SOUNDS_[name] = sound; - } -}; - -/** - * Preload all the audio files so that they play quickly when asked for. - * @private - */ -Blockly.WorkspaceSvg.prototype.preloadAudio_ = function() { - for (var name in this.SOUNDS_) { - var sound = this.SOUNDS_[name]; - sound.volume = .01; - sound.play(); - sound.pause(); - // iOS can only process one sound at a time. Trying to load more than one - // corrupts the earlier ones. Just load one and leave the others uncached. - if (goog.userAgent.IPAD || goog.userAgent.IPHONE) { - break; - } - } -}; - -/** - * Play a named sound at specified volume. If volume is not specified, - * use full volume (1). - * @param {string} name Name of sound. - * @param {number=} opt_volume Volume of sound (0-1). - */ -Blockly.WorkspaceSvg.prototype.playAudio = function(name, opt_volume) { - var sound = this.SOUNDS_[name]; - if (sound) { - // Don't play one sound on top of another. - var now = new Date; - if (now - this.lastSound_ < Blockly.SOUND_LIMIT) { - return; - } - this.lastSound_ = now; - var mySound; - var ie9 = goog.userAgent.DOCUMENT_MODE && - goog.userAgent.DOCUMENT_MODE === 9; - if (ie9 || goog.userAgent.IPAD || goog.userAgent.ANDROID) { - // Creating a new audio node causes lag in IE9, Android and iPad. Android - // and IE9 refetch the file from the server, iPad uses a singleton audio - // node which must be deleted and recreated for each new audio tag. - mySound = sound; - } else { - mySound = sound.cloneNode(); - } - mySound.volume = (opt_volume === undefined ? 1 : opt_volume); - mySound.play(); - } else if (this.options.parentWorkspace) { - // Maybe a workspace on a lower level knows about this sound. - this.options.parentWorkspace.playAudio(name, opt_volume); - } -}; - -/** - * Modify the block tree on the existing toolbox. - * @param {Node|string} tree DOM tree of blocks, or text representation of same. - */ -Blockly.WorkspaceSvg.prototype.updateToolbox = function(tree) { - tree = Blockly.Options.parseToolboxTree(tree); - if (!tree) { - if (this.options.languageTree) { - throw 'Can\'t nullify an existing toolbox.'; - } - return; // No change (null to null). - } - if (!this.options.languageTree) { - throw 'Existing toolbox is null. Can\'t create new toolbox.'; - } - if (tree.getElementsByTagName('category').length) { - if (!this.toolbox_) { - throw 'Existing toolbox has no categories. Can\'t change mode.'; - } - this.options.languageTree = tree; - this.toolbox_.populate_(tree); - this.toolbox_.addColour_(); - } else { - if (!this.flyout_) { - throw 'Existing toolbox has categories. Can\'t change mode.'; - } - this.options.languageTree = tree; - this.flyout_.show(tree.childNodes); - } -}; - -/** - * Mark this workspace as the currently focused main workspace. - */ -Blockly.WorkspaceSvg.prototype.markFocused = function() { - if (this.options.parentWorkspace) { - this.options.parentWorkspace.markFocused(); - } else { - Blockly.mainWorkspace = this; - } -}; - -/** - * Zooming the blocks centered in (x, y) coordinate with zooming in or out. - * @param {number} x X coordinate of center. - * @param {number} y Y coordinate of center. - * @param {number} type Type of zooming (-1 zooming out and 1 zooming in). - */ -Blockly.WorkspaceSvg.prototype.zoom = function(x, y, type) { - var speed = this.options.zoomOptions.scaleSpeed; - var metrics = this.getMetrics(); - var center = this.getParentSvg().createSVGPoint(); - center.x = x; - center.y = y; - center = center.matrixTransform(this.getCanvas().getCTM().inverse()); - x = center.x; - y = center.y; - var canvas = this.getCanvas(); - // Scale factor. - var scaleChange = (type == 1) ? speed : 1 / speed; - // Clamp scale within valid range. - var newScale = this.scale * scaleChange; - if (newScale > this.options.zoomOptions.maxScale) { - scaleChange = this.options.zoomOptions.maxScale / this.scale; - } else if (newScale < this.options.zoomOptions.minScale) { - scaleChange = this.options.zoomOptions.minScale / this.scale; - } - if (this.scale == newScale) { - return; // No change in zoom. - } - if (this.scrollbar) { - var matrix = canvas.getCTM() - .translate(x * (1 - scaleChange), y * (1 - scaleChange)) - .scale(scaleChange); - // newScale and matrix.a should be identical (within a rounding error). - this.scrollX = matrix.e - metrics.absoluteLeft; - this.scrollY = matrix.f - metrics.absoluteTop; - } - this.setScale(newScale); -}; - -/** - * Zooming the blocks centered in the center of view with zooming in or out. - * @param {number} type Type of zooming (-1 zooming out and 1 zooming in). - */ -Blockly.WorkspaceSvg.prototype.zoomCenter = function(type) { - var metrics = this.getMetrics(); - var x = metrics.viewWidth / 2; - var y = metrics.viewHeight / 2; - this.zoom(x, y, type); -}; - -/** - * Zoom the blocks to fit in the workspace if possible. - */ -Blockly.WorkspaceSvg.prototype.zoomToFit = function() { - var metrics = this.getMetrics(); - var blocksBox = this.getBlocksBoundingBox(); - var blocksWidth = blocksBox.width; - var blocksHeight = blocksBox.height; - if (!blocksWidth) { - return; // Prevents zooming to infinity. - } - var workspaceWidth = metrics.viewWidth; - var workspaceHeight = metrics.viewHeight; - if (this.flyout_) { - workspaceWidth -= this.flyout_.width_; - } - if (!this.scrollbar) { - // Orgin point of 0,0 is fixed, blocks will not scroll to center. - blocksWidth += metrics.contentLeft; - blocksHeight += metrics.contentTop; - } - var ratioX = workspaceWidth / blocksWidth; - var ratioY = workspaceHeight / blocksHeight; - this.setScale(Math.min(ratioX, ratioY)); - this.scrollCenter(); -}; - -/** - * Center the workspace. - */ -Blockly.WorkspaceSvg.prototype.scrollCenter = function() { - if (!this.scrollbar) { - // Can't center a non-scrolling workspace. - return; - } - var metrics = this.getMetrics(); - var x = (metrics.contentWidth - metrics.viewWidth) / 2; - if (this.flyout_) { - x -= this.flyout_.width_ / 2; - } - var y = (metrics.contentHeight - metrics.viewHeight) / 2; - this.scrollbar.set(x, y); -}; - -/** - * Set the workspace's zoom factor. - * @param {number} newScale Zoom factor. - */ -Blockly.WorkspaceSvg.prototype.setScale = function(newScale) { - if (this.options.zoomOptions.maxScale && - newScale > this.options.zoomOptions.maxScale) { - newScale = this.options.zoomOptions.maxScale; - } else if (this.options.zoomOptions.minScale && - newScale < this.options.zoomOptions.minScale) { - newScale = this.options.zoomOptions.minScale; - } - this.scale = newScale; - this.updateGridPattern_(); - if (this.scrollbar) { - this.scrollbar.resize(); - } else { - this.translate(this.scrollX, this.scrollY); - } - Blockly.hideChaff(false); - if (this.flyout_) { - // No toolbox, resize flyout. - this.flyout_.reflow(); - } -}; - -/** - * Updates the grid pattern. - * @private - */ -Blockly.WorkspaceSvg.prototype.updateGridPattern_ = function() { - if (!this.options.gridPattern) { - return; // No grid. - } - // MSIE freaks if it sees a 0x0 pattern, so set empty patterns to 100x100. - var safeSpacing = (this.options.gridOptions['spacing'] * this.scale) || 100; - this.options.gridPattern.setAttribute('width', safeSpacing); - this.options.gridPattern.setAttribute('height', safeSpacing); - var half = Math.floor(this.options.gridOptions['spacing'] / 2) + 0.5; - var start = half - this.options.gridOptions['length'] / 2; - var end = half + this.options.gridOptions['length'] / 2; - var line1 = this.options.gridPattern.firstChild; - var line2 = line1 && line1.nextSibling; - half *= this.scale; - start *= this.scale; - end *= this.scale; - if (line1) { - line1.setAttribute('stroke-width', this.scale); - line1.setAttribute('x1', start); - line1.setAttribute('y1', half); - line1.setAttribute('x2', end); - line1.setAttribute('y2', half); - } - if (line2) { - line2.setAttribute('stroke-width', this.scale); - line2.setAttribute('x1', half); - line2.setAttribute('y1', start); - line2.setAttribute('x2', half); - line2.setAttribute('y2', end); - } -}; - - -/** - * Return an object with all the metrics required to size scrollbars for a - * top level workspace. The following properties are computed: - * .viewHeight: Height of the visible rectangle, - * .viewWidth: Width of the visible rectangle, - * .contentHeight: Height of the contents, - * .contentWidth: Width of the content, - * .viewTop: Offset of top edge of visible rectangle from parent, - * .viewLeft: Offset of left edge of visible rectangle from parent, - * .contentTop: Offset of the top-most content from the y=0 coordinate, - * .contentLeft: Offset of the left-most content from the x=0 coordinate. - * .absoluteTop: Top-edge of view. - * .absoluteLeft: Left-edge of view. - * .toolboxWidth: Width of toolbox, if it exists. Otherwise zero. - * .toolboxHeight: Height of toolbox, if it exists. Otherwise zero. - * .flyoutWidth: Width of the flyout if it is always open. Otherwise zero. - * .flyoutHeight: Height of flyout if it is always open. Otherwise zero. - * .toolboxPosition: Top, bottom, left or right. - * @return {Object} Contains size and position metrics of a top level workspace. - * @private - */ -Blockly.WorkspaceSvg.getTopLevelWorkspaceMetrics_ = function() { - var svgSize = Blockly.svgSize(this.getParentSvg()); - if (this.toolbox_) { - if (this.toolboxPosition == Blockly.TOOLBOX_AT_TOP || - this.toolboxPosition == Blockly.TOOLBOX_AT_BOTTOM) { - svgSize.height -= this.toolbox_.getHeight(); - } else if (this.toolboxPosition == Blockly.TOOLBOX_AT_LEFT || - this.toolboxPosition == Blockly.TOOLBOX_AT_RIGHT) { - svgSize.width -= this.toolbox_.getWidth(); - } - } - // Set the margin to match the flyout's margin so that the workspace does - // not jump as blocks are added. - var MARGIN = Blockly.Flyout.prototype.CORNER_RADIUS - 1; - var viewWidth = svgSize.width - MARGIN; - var viewHeight = svgSize.height - MARGIN; - var blockBox = this.getBlocksBoundingBox(); - - // Fix scale. - var contentWidth = blockBox.width * this.scale; - var contentHeight = blockBox.height * this.scale; - var contentX = blockBox.x * this.scale; - var contentY = blockBox.y * this.scale; - if (this.scrollbar) { - // Add a border around the content that is at least half a screenful wide. - // Ensure border is wide enough that blocks can scroll over entire screen. - var leftEdge = Math.min(contentX - viewWidth / 2, - contentX + contentWidth - viewWidth); - var rightEdge = Math.max(contentX + contentWidth + viewWidth / 2, - contentX + viewWidth); - var topEdge = Math.min(contentY - viewHeight / 2, - contentY + contentHeight - viewHeight); - var bottomEdge = Math.max(contentY + contentHeight + viewHeight / 2, - contentY + viewHeight); - } else { - var leftEdge = blockBox.x; - var rightEdge = leftEdge + blockBox.width; - var topEdge = blockBox.y; - var bottomEdge = topEdge + blockBox.height; - } - var absoluteLeft = 0; - if (this.toolbox_ && this.toolboxPosition == Blockly.TOOLBOX_AT_LEFT) { - absoluteLeft = this.toolbox_.getWidth(); - } - var absoluteTop = 0; - if (this.toolbox_ && this.toolboxPosition == Blockly.TOOLBOX_AT_TOP) { - absoluteTop = this.toolbox_.getHeight(); - } - - var metrics = { - viewHeight: svgSize.height, - viewWidth: svgSize.width, - contentHeight: bottomEdge - topEdge, - contentWidth: rightEdge - leftEdge, - viewTop: -this.scrollY, - viewLeft: -this.scrollX, - contentTop: topEdge, - contentLeft: leftEdge, - absoluteTop: absoluteTop, - absoluteLeft: absoluteLeft, - toolboxWidth: this.toolbox_ ? this.toolbox_.getWidth() : 0, - toolboxHeight: this.toolbox_ ? this.toolbox_.getHeight() : 0, - flyoutWidth: this.flyout_ ? this.flyout_.getWidth() : 0, - flyoutHeight: this.flyout_ ? this.flyout_.getHeight() : 0, - toolboxPosition: this.toolboxPosition - }; - return metrics; -}; - -/** - * Sets the X/Y translations of a top level workspace to match the scrollbars. - * @param {!Object} xyRatio Contains an x and/or y property which is a float - * between 0 and 1 specifying the degree of scrolling. - * @private - */ -Blockly.WorkspaceSvg.setTopLevelWorkspaceMetrics_ = function(xyRatio) { - if (!this.scrollbar) { - throw 'Attempt to set top level workspace scroll without scrollbars.'; - } - var metrics = this.getMetrics(); - if (goog.isNumber(xyRatio.x)) { - this.scrollX = -metrics.contentWidth * xyRatio.x - metrics.contentLeft; - } - if (goog.isNumber(xyRatio.y)) { - this.scrollY = -metrics.contentHeight * xyRatio.y - metrics.contentTop; - } - var x = this.scrollX + metrics.absoluteLeft; - var y = this.scrollY + metrics.absoluteTop; - this.translate(x, y); - if (this.options.gridPattern) { - this.options.gridPattern.setAttribute('x', x); - this.options.gridPattern.setAttribute('y', y); - if (goog.userAgent.IE) { - // IE doesn't notice that the x/y offsets have changed. Force an update. - this.updateGridPattern_(); - } - } -}; -// Export symbols that would otherwise be renamed by Closure compiler. -Blockly.WorkspaceSvg.prototype['setVisible'] = - Blockly.WorkspaceSvg.prototype.setVisible; diff --git a/backend/_pv_1_3_5/static/blockly/core/xml.js b/backend/_pv_1_3_5/static/blockly/core/xml.js deleted file mode 100755 index 2567560cd..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/xml.js +++ /dev/null @@ -1,566 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview XML reader and writer. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Xml'); - -goog.require('goog.asserts'); -goog.require('goog.dom'); - - -/** - * Encode a block tree as XML. - * @param {!Blockly.Workspace} workspace The workspace containing blocks. - * @return {!Element} XML document. - */ -Blockly.Xml.workspaceToDom = function(workspace) { - var xml = goog.dom.createDom('xml'); - var blocks = workspace.getTopBlocks(true); - for (var i = 0, block; block = blocks[i]; i++) { - xml.appendChild(Blockly.Xml.blockToDomWithXY(block)); - } - return xml; -}; - -/** - * Encode a block subtree as XML with XY coordinates. - * @param {!Blockly.Block} block The root block to encode. - * @return {!Element} Tree of XML elements. - */ -Blockly.Xml.blockToDomWithXY = function(block) { - var width; // Not used in LTR. - if (block.workspace.RTL) { - width = block.workspace.getWidth(); - } - var element = Blockly.Xml.blockToDom(block); - var xy = block.getRelativeToSurfaceXY(); - element.setAttribute('x', - Math.round(block.workspace.RTL ? width - xy.x : xy.x)); - element.setAttribute('y', Math.round(xy.y)); - return element; -}; - -/** - * Encode a block subtree as XML. - * @param {!Blockly.Block} block The root block to encode. - * @return {!Element} Tree of XML elements. - */ -Blockly.Xml.blockToDom = function(block) { - var element = goog.dom.createDom(block.isShadow() ? 'shadow' : 'block'); - element.setAttribute('type', block.type); - element.setAttribute('id', block.id); - if (block.mutationToDom) { - // Custom data for an advanced block. - var mutation = block.mutationToDom(); - if (mutation && (mutation.hasChildNodes() || mutation.hasAttributes())) { - element.appendChild(mutation); - } - } - function fieldToDom(field) { - if (field.name && field.EDITABLE) { - var container = goog.dom.createDom('field', null, field.getValue()); - container.setAttribute('name', field.name); - element.appendChild(container); - } - } - for (var i = 0, input; input = block.inputList[i]; i++) { - for (var j = 0, field; field = input.fieldRow[j]; j++) { - fieldToDom(field); - } - } - - var commentText = block.getCommentText(); - if (commentText) { - var commentElement = goog.dom.createDom('comment', null, commentText); - if (typeof block.comment == 'object') { - commentElement.setAttribute('pinned', block.comment.isVisible()); - var hw = block.comment.getBubbleSize(); - commentElement.setAttribute('h', hw.height); - commentElement.setAttribute('w', hw.width); - } - element.appendChild(commentElement); - } - - if (block.data) { - var dataElement = goog.dom.createDom('data', null, block.data); - element.appendChild(dataElement); - } - - for (var i = 0, input; input = block.inputList[i]; i++) { - var container; - var empty = true; - if (input.type == Blockly.DUMMY_INPUT) { - continue; - } else { - var childBlock = input.connection.targetBlock(); - if (input.type == Blockly.INPUT_VALUE) { - container = goog.dom.createDom('value'); - } else if (input.type == Blockly.NEXT_STATEMENT) { - container = goog.dom.createDom('statement'); - } - var shadow = input.connection.getShadowDom(); - if (shadow && (!childBlock || !childBlock.isShadow())) { - container.appendChild(Blockly.Xml.cloneShadow_(shadow)); - } - if (childBlock) { - container.appendChild(Blockly.Xml.blockToDom(childBlock)); - empty = false; - } - } - container.setAttribute('name', input.name); - if (!empty) { - element.appendChild(container); - } - } - if (block.inputsInlineDefault != block.inputsInline) { - element.setAttribute('inline', block.inputsInline); - } - if (block.isCollapsed()) { - element.setAttribute('collapsed', true); - } - if (block.disabled) { - element.setAttribute('disabled', true); - } - if (!block.isDeletable() && !block.isShadow()) { - element.setAttribute('deletable', false); - } - if (!block.isMovable() && !block.isShadow()) { - element.setAttribute('movable', false); - } - if (!block.isEditable()) { - element.setAttribute('editable', false); - } - - var nextBlock = block.getNextBlock(); - if (nextBlock) { - var container = goog.dom.createDom('next', null, - Blockly.Xml.blockToDom(nextBlock)); - element.appendChild(container); - } - var shadow = block.nextConnection && block.nextConnection.getShadowDom(); - if (shadow && (!nextBlock || !nextBlock.isShadow())) { - container.appendChild(Blockly.Xml.cloneShadow_(shadow)); - } - - return element; -}; - -/** - * Deeply clone the shadow's DOM so that changes don't back-wash to the block. - * @param {!Element} shadow A tree of XML elements. - * @return {!Element} A tree of XML elements. - * @private - */ -Blockly.Xml.cloneShadow_ = function(shadow) { - shadow = shadow.cloneNode(true); - // Walk the tree looking for whitespace. Don't prune whitespace in a tag. - var node = shadow; - var textNode; - while (node) { - if (node.firstChild) { - node = node.firstChild; - } else { - while (node && !node.nextSibling) { - textNode = node; - node = node.parentNode; - if (textNode.nodeType == 3 && textNode.data.trim() == '' && - node.firstChild != textNode) { - // Prune whitespace after a tag. - goog.dom.removeNode(textNode); - } - } - if (node) { - textNode = node; - node = node.nextSibling; - if (textNode.nodeType == 3 && textNode.data.trim() == '') { - // Prune whitespace before a tag. - goog.dom.removeNode(textNode); - } - } - } - } - return shadow; -}; - -/** - * Converts a DOM structure into plain text. - * Currently the text format is fairly ugly: all one line with no whitespace. - * @param {!Element} dom A tree of XML elements. - * @return {string} Text representation. - */ -Blockly.Xml.domToText = function(dom) { - var oSerializer = new XMLSerializer(); - return oSerializer.serializeToString(dom); -}; - -/** - * Converts a DOM structure into properly indented text. - * @param {!Element} dom A tree of XML elements. - * @return {string} Text representation. - */ -Blockly.Xml.domToPrettyText = function(dom) { - // This function is not guaranteed to be correct for all XML. - // But it handles the XML that Blockly generates. - var blob = Blockly.Xml.domToText(dom); - // Place every open and close tag on its own line. - var lines = blob.split('<'); - // Indent every line. - var indent = ''; - for (var i = 1; i < lines.length; i++) { - var line = lines[i]; - if (line[0] == '/') { - indent = indent.substring(2); - } - lines[i] = indent + '<' + line; - if (line[0] != '/' && line.slice(-2) != '/>') { - indent += ' '; - } - } - // Pull simple tags back together. - // E.g. - var text = lines.join('\n'); - text = text.replace(/(<(\w+)\b[^>]*>[^\n]*)\n *<\/\2>/g, '$1'); - // Trim leading blank line. - return text.replace(/^\n/, ''); -}; - -/** - * Converts plain text into a DOM structure. - * Throws an error if XML doesn't parse. - * @param {string} text Text representation. - * @return {!Element} A tree of XML elements. - */ -Blockly.Xml.textToDom = function(text) { - var oParser = new DOMParser(); - var dom = oParser.parseFromString(text, 'text/xml'); - // The DOM should have one and only one top-level node, an XML tag. - if (!dom || !dom.firstChild || - dom.firstChild.nodeName.toLowerCase() != 'xml' || - dom.firstChild !== dom.lastChild) { - // Whatever we got back from the parser is not XML. - goog.asserts.fail('Blockly.Xml.textToDom did not obtain a valid XML tree.'); - } - return dom.firstChild; -}; - -/** - * Decode an XML DOM and create blocks on the workspace. - * @param {!Element} xml XML DOM. - * @param {!Blockly.Workspace} workspace The workspace. - */ -Blockly.Xml.domToWorkspace = function(xml, workspace) { - if (xml instanceof Blockly.Workspace) { - var swap = xml; - xml = workspace; - workspace = swap; - console.warn('Deprecated call to Blockly.Xml.domToWorkspace, ' + - 'swap the arguments.'); - } - var width; // Not used in LTR. - if (workspace.RTL) { - width = workspace.getWidth(); - } - Blockly.Field.startCache(); - // Safari 7.1.3 is known to provide node lists with extra references to - // children beyond the lists' length. Trust the length, do not use the - // looping pattern of checking the index for an object. - var childCount = xml.childNodes.length; - var existingGroup = Blockly.Events.getGroup(); - if (!existingGroup) { - Blockly.Events.setGroup(true); - } - for (var i = 0; i < childCount; i++) { - var xmlChild = xml.childNodes[i]; - var name = xmlChild.nodeName.toLowerCase(); - if (name == 'block' || - (name == 'shadow' && !Blockly.Events.recordUndo)) { - // Allow top-level shadow blocks if recordUndo is disabled since - // that means an undo is in progress. Such a block is expected - // to be moved to a nested destination in the next operation. - var block = Blockly.Xml.domToBlock(xmlChild, workspace); - var blockX = parseInt(xmlChild.getAttribute('x'), 10); - var blockY = parseInt(xmlChild.getAttribute('y'), 10); - if (!isNaN(blockX) && !isNaN(blockY)) { - block.moveBy(workspace.RTL ? width - blockX : blockX, blockY); - } - } else if (name == 'shadow') { - goog.asserts.fail('Shadow block cannot be a top-level block.'); - } - } - if (!existingGroup) { - Blockly.Events.setGroup(false); - } - Blockly.Field.stopCache(); - - workspace.updateVariableList(false); -}; - -/** - * Decode an XML block tag and create a block (and possibly sub blocks) on the - * workspace. - * @param {!Element} xmlBlock XML block element. - * @param {!Blockly.Workspace} workspace The workspace. - * @return {!Blockly.Block} The root block created. - */ -Blockly.Xml.domToBlock = function(xmlBlock, workspace) { - if (xmlBlock instanceof Blockly.Workspace) { - var swap = xmlBlock; - xmlBlock = workspace; - workspace = swap; - console.warn('Deprecated call to Blockly.Xml.domToBlock, ' + - 'swap the arguments.'); - } - // Create top-level block. - Blockly.Events.disable(); - try { - var topBlock = Blockly.Xml.domToBlockHeadless_(xmlBlock, workspace); - if (workspace.rendered) { - // Hide connections to speed up assembly. - topBlock.setConnectionsHidden(true); - // Generate list of all blocks. - var blocks = topBlock.getDescendants(); - // Render each block. - for (var i = blocks.length - 1; i >= 0; i--) { - blocks[i].initSvg(); - } - for (var i = blocks.length - 1; i >= 0; i--) { - blocks[i].render(false); - } - // Populating the connection database may be defered until after the - // blocks have rendered. - setTimeout(function() { - if (topBlock.workspace) { // Check that the block hasn't been deleted. - topBlock.setConnectionsHidden(false); - } - }, 1); - topBlock.updateDisabled(); - // Allow the scrollbars to resize and move based on the new contents. - // TODO(@picklesrus): #387. Remove when domToBlock avoids resizing. - workspace.resizeContents(); - } - } finally { - Blockly.Events.enable(); - } - if (Blockly.Events.isEnabled()) { - Blockly.Events.fire(new Blockly.Events.Create(topBlock)); - } - return topBlock; -}; - -/** - * Decode an XML block tag and create a block (and possibly sub blocks) on the - * workspace. - * @param {!Element} xmlBlock XML block element. - * @param {!Blockly.Workspace} workspace The workspace. - * @return {!Blockly.Block} The root block created. - * @private - */ -Blockly.Xml.domToBlockHeadless_ = function(xmlBlock, workspace) { - var block = null; - var prototypeName = xmlBlock.getAttribute('type'); - goog.asserts.assert(prototypeName, 'Block type unspecified: %s', - xmlBlock.outerHTML); - var id = xmlBlock.getAttribute('id'); - block = workspace.newBlock(prototypeName, id); - - var blockChild = null; - for (var i = 0, xmlChild; xmlChild = xmlBlock.childNodes[i]; i++) { - if (xmlChild.nodeType == 3) { - // Ignore any text at the level. It's all whitespace anyway. - continue; - } - var input; - - // Find any enclosed blocks or shadows in this tag. - var childBlockNode = null; - var childShadowNode = null; - for (var j = 0, grandchildNode; grandchildNode = xmlChild.childNodes[j]; - j++) { - if (grandchildNode.nodeType == 1) { - if (grandchildNode.nodeName.toLowerCase() == 'block') { - childBlockNode = grandchildNode; - } else if (grandchildNode.nodeName.toLowerCase() == 'shadow') { - childShadowNode = grandchildNode; - } - } - } - // Use the shadow block if there is no child block. - if (!childBlockNode && childShadowNode) { - childBlockNode = childShadowNode; - } - - var name = xmlChild.getAttribute('name'); - switch (xmlChild.nodeName.toLowerCase()) { - case 'mutation': - // Custom data for an advanced block. - if (block.domToMutation) { - block.domToMutation(xmlChild); - if (block.initSvg) { - // Mutation may have added some elements that need initalizing. - block.initSvg(); - } - } - break; - case 'comment': - block.setCommentText(xmlChild.textContent); - var visible = xmlChild.getAttribute('pinned'); - if (visible && !block.isInFlyout) { - // Give the renderer a millisecond to render and position the block - // before positioning the comment bubble. - setTimeout(function() { - if (block.comment && block.comment.setVisible) { - block.comment.setVisible(visible == 'true'); - } - }, 1); - } - var bubbleW = parseInt(xmlChild.getAttribute('w'), 10); - var bubbleH = parseInt(xmlChild.getAttribute('h'), 10); - if (!isNaN(bubbleW) && !isNaN(bubbleH) && - block.comment && block.comment.setVisible) { - block.comment.setBubbleSize(bubbleW, bubbleH); - } - break; - case 'data': - block.data = xmlChild.textContent; - break; - case 'title': - // Titles were renamed to field in December 2013. - // Fall through. - case 'field': - var field = block.getField(name); - if (!field) { - console.warn('Ignoring non-existent field ' + name + ' in block ' + - prototypeName); - break; - } - field.setValue(xmlChild.textContent); - break; - case 'value': - case 'statement': - input = block.getInput(name); - if (!input) { - console.warn('Ignoring non-existent input ' + name + ' in block ' + - prototypeName); - break; - } - if (childShadowNode) { - input.connection.setShadowDom(childShadowNode); - } - if (childBlockNode) { - blockChild = Blockly.Xml.domToBlockHeadless_(childBlockNode, - workspace); - if (blockChild.outputConnection) { - input.connection.connect(blockChild.outputConnection); - } else if (blockChild.previousConnection) { - input.connection.connect(blockChild.previousConnection); - } else { - goog.asserts.fail( - 'Child block does not have output or previous statement.'); - } - } - break; - case 'next': - if (childShadowNode && block.nextConnection) { - block.nextConnection.setShadowDom(childShadowNode); - } - if (childBlockNode) { - goog.asserts.assert(block.nextConnection, - 'Next statement does not exist.'); - // If there is more than one XML 'next' tag. - goog.asserts.assert(!block.nextConnection.isConnected(), - 'Next statement is already connected.'); - blockChild = Blockly.Xml.domToBlockHeadless_(childBlockNode, - workspace); - goog.asserts.assert(blockChild.previousConnection, - 'Next block does not have previous statement.'); - block.nextConnection.connect(blockChild.previousConnection); - } - break; - default: - // Unknown tag; ignore. Same principle as HTML parsers. - console.warn('Ignoring unknown tag: ' + xmlChild.nodeName); - } - } - - var inline = xmlBlock.getAttribute('inline'); - if (inline) { - block.setInputsInline(inline == 'true'); - } - var disabled = xmlBlock.getAttribute('disabled'); - if (disabled) { - block.setDisabled(disabled == 'true'); - } - var deletable = xmlBlock.getAttribute('deletable'); - if (deletable) { - block.setDeletable(deletable == 'true'); - } - var movable = xmlBlock.getAttribute('movable'); - if (movable) { - block.setMovable(movable == 'true'); - } - var editable = xmlBlock.getAttribute('editable'); - if (editable) { - block.setEditable(editable == 'true'); - } - var collapsed = xmlBlock.getAttribute('collapsed'); - if (collapsed) { - block.setCollapsed(collapsed == 'true'); - } - if (xmlBlock.nodeName.toLowerCase() == 'shadow') { - // Ensure all children are also shadows. - var children = block.getChildren(); - for (var i = 0, child; child = children[i]; i++) { - goog.asserts.assert(child.isShadow(), - 'Shadow block not allowed non-shadow child.'); - } - block.setShadow(true); - } - return block; -}; - -/** - * Remove any 'next' block (statements in a stack). - * @param {!Element} xmlBlock XML block element. - */ -Blockly.Xml.deleteNext = function(xmlBlock) { - for (var i = 0, child; child = xmlBlock.childNodes[i]; i++) { - if (child.nodeName.toLowerCase() == 'next') { - xmlBlock.removeChild(child); - break; - } - } -}; - -// Export symbols that would otherwise be renamed by Closure compiler. -if (!goog.global['Blockly']) { - goog.global['Blockly'] = {}; -} -if (!goog.global['Blockly']['Xml']) { - goog.global['Blockly']['Xml'] = {}; -} -goog.global['Blockly']['Xml']['domToText'] = Blockly.Xml.domToText; -goog.global['Blockly']['Xml']['domToWorkspace'] = Blockly.Xml.domToWorkspace; -goog.global['Blockly']['Xml']['textToDom'] = Blockly.Xml.textToDom; -goog.global['Blockly']['Xml']['workspaceToDom'] = Blockly.Xml.workspaceToDom; diff --git a/backend/_pv_1_3_5/static/blockly/core/zoom_controls.js b/backend/_pv_1_3_5/static/blockly/core/zoom_controls.js deleted file mode 100755 index 48d8ce571..000000000 --- a/backend/_pv_1_3_5/static/blockly/core/zoom_controls.js +++ /dev/null @@ -1,239 +0,0 @@ -/** - * @license - * Visual Blocks Editor - * - * Copyright 2015 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Object representing a zoom icons. - * @author carloslfu@gmail.com (Carlos Galarza) - */ -'use strict'; - -goog.provide('Blockly.ZoomControls'); - -goog.require('goog.dom'); - - -/** - * Class for a zoom controls. - * @param {!Blockly.Workspace} workspace The workspace to sit in. - * @constructor - */ -Blockly.ZoomControls = function(workspace) { - this.workspace_ = workspace; -}; - -/** - * Width of the zoom controls. - * @type {number} - * @private - */ -Blockly.ZoomControls.prototype.WIDTH_ = 32; - -/** - * Height of the zoom controls. - * @type {number} - * @private - */ -Blockly.ZoomControls.prototype.HEIGHT_ = 110; - -/** - * Distance between zoom controls and bottom edge of workspace. - * @type {number} - * @private - */ -Blockly.ZoomControls.prototype.MARGIN_BOTTOM_ = 20; - -/** - * Distance between zoom controls and right edge of workspace. - * @type {number} - * @private - */ -Blockly.ZoomControls.prototype.MARGIN_SIDE_ = 20; - -/** - * The SVG group containing the zoom controls. - * @type {Element} - * @private - */ -Blockly.ZoomControls.prototype.svgGroup_ = null; - -/** - * Left coordinate of the zoom controls. - * @type {number} - * @private - */ -Blockly.ZoomControls.prototype.left_ = 0; - -/** - * Top coordinate of the zoom controls. - * @type {number} - * @private - */ -Blockly.ZoomControls.prototype.top_ = 0; - -/** - * Create the zoom controls. - * @return {!Element} The zoom controls SVG group. - */ -Blockly.ZoomControls.prototype.createDom = function() { - var workspace = this.workspace_; - /* Here's the markup that will be generated: - - - - - - - - - - - - - - - */ - this.svgGroup_ = Blockly.createSvgElement('g', - {'class': 'blocklyZoom'}, null); - var rnd = String(Math.random()).substring(2); - - var clip = Blockly.createSvgElement('clipPath', - {'id': 'blocklyZoomoutClipPath' + rnd}, - this.svgGroup_); - Blockly.createSvgElement('rect', - {'width': 32, 'height': 32, 'y': 77}, - clip); - var zoomoutSvg = Blockly.createSvgElement('image', - {'width': Blockly.SPRITE.width, - 'height': Blockly.SPRITE.height, 'x': -64, - 'y': -15, - 'clip-path': 'url(#blocklyZoomoutClipPath' + rnd + ')'}, - this.svgGroup_); - zoomoutSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', - workspace.options.pathToMedia + Blockly.SPRITE.url); - - var clip = Blockly.createSvgElement('clipPath', - {'id': 'blocklyZoominClipPath' + rnd}, - this.svgGroup_); - Blockly.createSvgElement('rect', - {'width': 32, 'height': 32, 'y': 43}, - clip); - var zoominSvg = Blockly.createSvgElement('image', - {'width': Blockly.SPRITE.width, - 'height': Blockly.SPRITE.height, - 'x': -32, - 'y': -49, - 'clip-path': 'url(#blocklyZoominClipPath' + rnd + ')'}, - this.svgGroup_); - zoominSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', - workspace.options.pathToMedia + Blockly.SPRITE.url); - - var clip = Blockly.createSvgElement('clipPath', - {'id': 'blocklyZoomresetClipPath' + rnd}, - this.svgGroup_); - Blockly.createSvgElement('rect', - {'width': 32, 'height': 32}, - clip); - var zoomresetSvg = Blockly.createSvgElement('image', - {'width': Blockly.SPRITE.width, - 'height': Blockly.SPRITE.height, 'y': -92, - 'clip-path': 'url(#blocklyZoomresetClipPath' + rnd + ')'}, - this.svgGroup_); - zoomresetSvg.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', - workspace.options.pathToMedia + Blockly.SPRITE.url); - - // Attach event listeners. - Blockly.bindEvent_(zoomresetSvg, 'mousedown', null, function(e) { - workspace.setScale(1); - workspace.scrollCenter(); - e.stopPropagation(); // Don't start a workspace scroll. - e.preventDefault(); // Stop double-clicking from selecting text. - }); - Blockly.bindEvent_(zoominSvg, 'mousedown', null, function(e) { - workspace.zoomCenter(1); - e.stopPropagation(); // Don't start a workspace scroll. - e.preventDefault(); // Stop double-clicking from selecting text. - }); - Blockly.bindEvent_(zoomoutSvg, 'mousedown', null, function(e) { - workspace.zoomCenter(-1); - e.stopPropagation(); // Don't start a workspace scroll. - e.preventDefault(); // Stop double-clicking from selecting text. - }); - - return this.svgGroup_; -}; - -/** - * Initialize the zoom controls. - * @param {number} bottom Distance from workspace bottom to bottom of controls. - * @return {number} Distance from workspace bottom to the top of controls. - */ -Blockly.ZoomControls.prototype.init = function(bottom) { - this.bottom_ = this.MARGIN_BOTTOM_ + bottom; - return this.bottom_ + this.HEIGHT_; -}; - -/** - * Dispose of this zoom controls. - * Unlink from all DOM elements to prevent memory leaks. - */ -Blockly.ZoomControls.prototype.dispose = function() { - if (this.svgGroup_) { - goog.dom.removeNode(this.svgGroup_); - this.svgGroup_ = null; - } - this.workspace_ = null; -}; - -/** - * Move the zoom controls to the bottom-right corner. - */ -Blockly.ZoomControls.prototype.position = function() { - var metrics = this.workspace_.getMetrics(); - if (!metrics) { - // There are no metrics available (workspace is probably not visible). - return; - } - if (this.workspace_.RTL) { - this.left_ = this.MARGIN_SIDE_ + Blockly.Scrollbar.scrollbarThickness; - if (metrics.toolboxPosition == Blockly.TOOLBOX_AT_LEFT) { - this.left_ += metrics.flyoutWidth; - if (this.workspace_.toolbox_) { - this.left_ += metrics.absoluteLeft; - } - } - } else { - this.left_ = metrics.viewWidth + metrics.absoluteLeft - - this.WIDTH_ - this.MARGIN_SIDE_ - Blockly.Scrollbar.scrollbarThickness; - - if (metrics.toolboxPosition == Blockly.TOOLBOX_AT_RIGHT) { - this.left_ -= metrics.flyoutWidth; - } - } - this.top_ = metrics.viewHeight + metrics.absoluteTop - - this.HEIGHT_ - this.bottom_; - if (metrics.toolboxPosition == Blockly.TOOLBOX_AT_BOTTOM) { - this.top_ -= metrics.flyoutHeight; - } - this.svgGroup_.setAttribute('transform', - 'translate(' + this.left_ + ',' + this.top_ + ')'); -}; diff --git a/backend/_pv_1_3_5/static/blockly/dart_compressed.js b/backend/_pv_1_3_5/static/blockly/dart_compressed.js deleted file mode 100755 index 4e9fbe701..000000000 --- a/backend/_pv_1_3_5/static/blockly/dart_compressed.js +++ /dev/null @@ -1,92 +0,0 @@ -// Do not edit this file; automatically generated by build.py. -'use strict'; - - -// Copyright 2014 Google Inc. Apache License 2.0 -Blockly.Dart=new Blockly.Generator("Dart");Blockly.Dart.addReservedWords("assert,break,case,catch,class,const,continue,default,do,else,enum,extends,false,final,finally,for,if,in,is,new,null,rethrow,return,super,switch,this,throw,true,try,var,void,while,with,print,identityHashCode,identical,BidirectionalIterator,Comparable,double,Function,int,Invocation,Iterable,Iterator,List,Map,Match,num,Pattern,RegExp,Set,StackTrace,String,StringSink,Type,bool,DateTime,Deprecated,Duration,Expando,Null,Object,RuneIterator,Runes,Stopwatch,StringBuffer,Symbol,Uri,Comparator,AbstractClassInstantiationError,ArgumentError,AssertionError,CastError,ConcurrentModificationError,CyclicInitializationError,Error,Exception,FallThroughError,FormatException,IntegerDivisionByZeroException,NoSuchMethodError,NullThrownError,OutOfMemoryError,RangeError,StackOverflowError,StateError,TypeError,UnimplementedError,UnsupportedError"); -Blockly.Dart.ORDER_ATOMIC=0;Blockly.Dart.ORDER_UNARY_POSTFIX=1;Blockly.Dart.ORDER_UNARY_PREFIX=2;Blockly.Dart.ORDER_MULTIPLICATIVE=3;Blockly.Dart.ORDER_ADDITIVE=4;Blockly.Dart.ORDER_SHIFT=5;Blockly.Dart.ORDER_BITWISE_AND=6;Blockly.Dart.ORDER_BITWISE_XOR=7;Blockly.Dart.ORDER_BITWISE_OR=8;Blockly.Dart.ORDER_RELATIONAL=9;Blockly.Dart.ORDER_EQUALITY=10;Blockly.Dart.ORDER_LOGICAL_AND=11;Blockly.Dart.ORDER_LOGICAL_OR=12;Blockly.Dart.ORDER_IF_NULL=13;Blockly.Dart.ORDER_CONDITIONAL=14; -Blockly.Dart.ORDER_CASCADE=15;Blockly.Dart.ORDER_ASSIGNMENT=16;Blockly.Dart.ORDER_NONE=99;Blockly.Dart.ONE_BASED_INDEXING=!0; -Blockly.Dart.init=function(a){Blockly.Dart.definitions_=Object.create(null);Blockly.Dart.functionNames_=Object.create(null);Blockly.Dart.variableDB_?Blockly.Dart.variableDB_.reset():Blockly.Dart.variableDB_=new Blockly.Names(Blockly.Dart.RESERVED_WORDS_);var b=[];a=a.variableList;if(a.length){for(var c=0;cc&&(a=a+" - "+-c,g=Blockly.Dart.ORDER_ADDITIVE);d&&(a= -c?"-("+a+")":"-"+a,g=Blockly.Dart.ORDER_UNARY_PREFIX);g=Math.floor(g);e=Math.floor(e);g&&e>=g&&(a="("+a+")")}return a};Blockly.Dart.lists={};Blockly.Dart.addReservedWords("Math");Blockly.Dart.lists_create_empty=function(a){return["[]",Blockly.Dart.ORDER_ATOMIC]};Blockly.Dart.lists_create_with=function(a){for(var b=Array(a.itemCount_),c=0;c direction * a.compareTo(b),',' "TEXT": (a, b) => direction * a.toString().compareTo(b.toString()),',' "IGNORE_CASE": '," (a, b) => direction * ", -" a.toString().toLowerCase().compareTo(b.toString().toLowerCase())"," };"," list = new List.from(list);"," var compare = compareFuncs[type];"," list.sort(compare);"," return list;","}"])+"("+b+', "'+a+'", '+c+")",Blockly.Dart.ORDER_UNARY_POSTFIX]}; -Blockly.Dart.lists_split=function(a){var b=Blockly.Dart.valueToCode(a,"INPUT",Blockly.Dart.ORDER_UNARY_POSTFIX),c=Blockly.Dart.valueToCode(a,"DELIM",Blockly.Dart.ORDER_NONE)||"''";a=a.getFieldValue("MODE");if("SPLIT"==a)b||(b="''"),a="split";else if("JOIN"==a)b||(b="[]"),a="join";else throw"Unknown mode: "+a;return[b+"."+a+"("+c+")",Blockly.Dart.ORDER_UNARY_POSTFIX]};Blockly.Dart.math={};Blockly.Dart.addReservedWords("Math");Blockly.Dart.math_number=function(a){a=parseFloat(a.getFieldValue("NUM"));var b;Infinity==a?(a="double.INFINITY",b=Blockly.Dart.ORDER_UNARY_POSTFIX):-Infinity==a?(a="-double.INFINITY",b=Blockly.Dart.ORDER_UNARY_PREFIX):b=0>a?Blockly.Dart.ORDER_UNARY_PREFIX:Blockly.Dart.ORDER_ATOMIC;return[a,b]}; -Blockly.Dart.math_arithmetic=function(a){var b={ADD:[" + ",Blockly.Dart.ORDER_ADDITIVE],MINUS:[" - ",Blockly.Dart.ORDER_ADDITIVE],MULTIPLY:[" * ",Blockly.Dart.ORDER_MULTIPLICATIVE],DIVIDE:[" / ",Blockly.Dart.ORDER_MULTIPLICATIVE],POWER:[null,Blockly.Dart.ORDER_NONE]}[a.getFieldValue("OP")],c=b[0],b=b[1],d=Blockly.Dart.valueToCode(a,"A",b)||"0";a=Blockly.Dart.valueToCode(a,"B",b)||"0";return c?[d+c+a,b]:(Blockly.Dart.definitions_.import_dart_math="import 'dart:math' as Math;",["Math.pow("+d+", "+a+ -")",Blockly.Dart.ORDER_UNARY_POSTFIX])}; -Blockly.Dart.math_single=function(a){var b=a.getFieldValue("OP"),c;if("NEG"==b)return a=Blockly.Dart.valueToCode(a,"NUM",Blockly.Dart.ORDER_UNARY_PREFIX)||"0","-"==a[0]&&(a=" "+a),["-"+a,Blockly.Dart.ORDER_UNARY_PREFIX];Blockly.Dart.definitions_.import_dart_math="import 'dart:math' as Math;";a="ABS"==b||"ROUND"==b.substring(0,5)?Blockly.Dart.valueToCode(a,"NUM",Blockly.Dart.ORDER_UNARY_POSTFIX)||"0":"SIN"==b||"COS"==b||"TAN"==b?Blockly.Dart.valueToCode(a,"NUM",Blockly.Dart.ORDER_MULTIPLICATIVE)|| -"0":Blockly.Dart.valueToCode(a,"NUM",Blockly.Dart.ORDER_NONE)||"0";switch(b){case "ABS":c=a+".abs()";break;case "ROOT":c="Math.sqrt("+a+")";break;case "LN":c="Math.log("+a+")";break;case "EXP":c="Math.exp("+a+")";break;case "POW10":c="Math.pow(10,"+a+")";break;case "ROUND":c=a+".round()";break;case "ROUNDUP":c=a+".ceil()";break;case "ROUNDDOWN":c=a+".floor()";break;case "SIN":c="Math.sin("+a+" / 180 * Math.PI)";break;case "COS":c="Math.cos("+a+" / 180 * Math.PI)";break;case "TAN":c="Math.tan("+a+ -" / 180 * Math.PI)"}if(c)return[c,Blockly.Dart.ORDER_UNARY_POSTFIX];switch(b){case "LOG10":c="Math.log("+a+") / Math.log(10)";break;case "ASIN":c="Math.asin("+a+") / Math.PI * 180";break;case "ACOS":c="Math.acos("+a+") / Math.PI * 180";break;case "ATAN":c="Math.atan("+a+") / Math.PI * 180";break;default:throw"Unknown math operator: "+b;}return[c,Blockly.Dart.ORDER_MULTIPLICATIVE]}; -Blockly.Dart.math_constant=function(a){var b={PI:["Math.PI",Blockly.Dart.ORDER_UNARY_POSTFIX],E:["Math.E",Blockly.Dart.ORDER_UNARY_POSTFIX],GOLDEN_RATIO:["(1 + Math.sqrt(5)) / 2",Blockly.Dart.ORDER_MULTIPLICATIVE],SQRT2:["Math.SQRT2",Blockly.Dart.ORDER_UNARY_POSTFIX],SQRT1_2:["Math.SQRT1_2",Blockly.Dart.ORDER_UNARY_POSTFIX],INFINITY:["double.INFINITY",Blockly.Dart.ORDER_ATOMIC]};a=a.getFieldValue("CONSTANT");"INFINITY"!=a&&(Blockly.Dart.definitions_.import_dart_math="import 'dart:math' as Math;"); -return b[a]}; -Blockly.Dart.math_number_property=function(a){var b=Blockly.Dart.valueToCode(a,"NUMBER_TO_CHECK",Blockly.Dart.ORDER_MULTIPLICATIVE);if(!b)return["false",Blockly.Python.ORDER_ATOMIC];var c=a.getFieldValue("PROPERTY"),d;if("PRIME"==c)return Blockly.Dart.definitions_.import_dart_math="import 'dart:math' as Math;",[Blockly.Dart.provideFunction_("math_isPrime",["bool "+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+"(n) {"," // https://en.wikipedia.org/wiki/Primality_test#Naive_methods"," if (n == 2 || n == 3) {"," return true;", -" }"," // False if n is null, negative, is 1, or not whole."," // And false if n is divisible by 2 or 3."," if (n == null || n <= 1 || n % 1 != 0 || n % 2 == 0 || n % 3 == 0) {"," return false;"," }"," // Check all the numbers of form 6k +/- 1, up to sqrt(n)."," for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {"," if (n % (x - 1) == 0 || n % (x + 1) == 0) {"," return false;"," }"," }"," return true;","}"])+"("+b+")",Blockly.Dart.ORDER_UNARY_POSTFIX];switch(c){case "EVEN":d=b+ -" % 2 == 0";break;case "ODD":d=b+" % 2 == 1";break;case "WHOLE":d=b+" % 1 == 0";break;case "POSITIVE":d=b+" > 0";break;case "NEGATIVE":d=b+" < 0";break;case "DIVISIBLE_BY":a=Blockly.Dart.valueToCode(a,"DIVISOR",Blockly.Dart.ORDER_MULTIPLICATIVE);if(!a)return["false",Blockly.Python.ORDER_ATOMIC];d=b+" % "+a+" == 0"}return[d,Blockly.Dart.ORDER_EQUALITY]}; -Blockly.Dart.math_change=function(a){var b=Blockly.Dart.valueToCode(a,"DELTA",Blockly.Dart.ORDER_ADDITIVE)||"0";a=Blockly.Dart.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE);return a+" = ("+a+" is num ? "+a+" : 0) + "+b+";\n"};Blockly.Dart.math_round=Blockly.Dart.math_single;Blockly.Dart.math_trig=Blockly.Dart.math_single; -Blockly.Dart.math_on_list=function(a){var b=a.getFieldValue("OP");a=Blockly.Dart.valueToCode(a,"LIST",Blockly.Dart.ORDER_NONE)||"[]";switch(b){case "SUM":b=Blockly.Dart.provideFunction_("math_sum",["num "+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+"(List myList) {"," num sumVal = 0;"," myList.forEach((num entry) {sumVal += entry;});"," return sumVal;","}"]);b=b+"("+a+")";break;case "MIN":Blockly.Dart.definitions_.import_dart_math="import 'dart:math' as Math;";b=Blockly.Dart.provideFunction_("math_min", -["num "+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+"(List myList) {"," if (myList.isEmpty) return null;"," num minVal = myList[0];"," myList.forEach((num entry) {minVal = Math.min(minVal, entry);});"," return minVal;","}"]);b=b+"("+a+")";break;case "MAX":Blockly.Dart.definitions_.import_dart_math="import 'dart:math' as Math;";b=Blockly.Dart.provideFunction_("math_max",["num "+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+"(List myList) {"," if (myList.isEmpty) return null;"," num maxVal = myList[0];", -" myList.forEach((num entry) {maxVal = Math.max(maxVal, entry);});"," return maxVal;","}"]);b=b+"("+a+")";break;case "AVERAGE":b=Blockly.Dart.provideFunction_("math_mean",["num "+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+"(List myList) {"," // First filter list for numbers only."," List localList = new List.from(myList);"," localList.removeWhere((a) => a is! num);"," if (localList.isEmpty) return null;"," num sumVal = 0;"," localList.forEach((num entry) {sumVal += entry;});"," return sumVal / localList.length;", -"}"]);b=b+"("+a+")";break;case "MEDIAN":b=Blockly.Dart.provideFunction_("math_median",["num "+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+"(List myList) {"," // First filter list for numbers only, then sort, then return middle value"," // or the average of two middle values if list has an even number of elements."," List localList = new List.from(myList);"," localList.removeWhere((a) => a is! num);"," if (localList.isEmpty) return null;"," localList.sort((a, b) => (a - b));"," int index = localList.length ~/ 2;", -" if (localList.length % 2 == 1) {"," return localList[index];"," } else {"," return (localList[index - 1] + localList[index]) / 2;"," }","}"]);b=b+"("+a+")";break;case "MODE":Blockly.Dart.definitions_.import_dart_math="import 'dart:math' as Math;";b=Blockly.Dart.provideFunction_("math_modes",["List "+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+"(List values) {"," List modes = [];"," List counts = [];"," int maxCount = 0;"," for (int i = 0; i < values.length; i++) {"," var value = values[i];", -" bool found = false;"," int thisCount;"," for (int j = 0; j < counts.length; j++) {"," if (counts[j][0] == value) {"," thisCount = ++counts[j][1];"," found = true;"," break;"," }"," }"," if (!found) {"," counts.add([value, 1]);"," thisCount = 1;"," }"," maxCount = Math.max(thisCount, maxCount);"," }"," for (int j = 0; j < counts.length; j++) {"," if (counts[j][1] == maxCount) {"," modes.add(counts[j][0]);"," }"," }"," return modes;", -"}"]);b=b+"("+a+")";break;case "STD_DEV":Blockly.Dart.definitions_.import_dart_math="import 'dart:math' as Math;";b=Blockly.Dart.provideFunction_("math_standard_deviation",["num "+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+"(List myList) {"," // First filter list for numbers only."," List numbers = new List.from(myList);"," numbers.removeWhere((a) => a is! num);"," if (numbers.isEmpty) return null;"," num n = numbers.length;"," num sum = 0;"," numbers.forEach((x) => sum += x);"," num mean = sum / n;", -" num sumSquare = 0;"," numbers.forEach((x) => sumSquare += Math.pow(x - mean, 2));"," return Math.sqrt(sumSquare / n);","}"]);b=b+"("+a+")";break;case "RANDOM":Blockly.Dart.definitions_.import_dart_math="import 'dart:math' as Math;";b=Blockly.Dart.provideFunction_("math_random_item",["dynamic "+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+"(List myList) {"," int x = new Math.Random().nextInt(myList.length);"," return myList[x];","}"]);b=b+"("+a+")";break;default:throw"Unknown operator: "+b;}return[b, -Blockly.Dart.ORDER_UNARY_POSTFIX]};Blockly.Dart.math_modulo=function(a){var b=Blockly.Dart.valueToCode(a,"DIVIDEND",Blockly.Dart.ORDER_MULTIPLICATIVE)||"0";a=Blockly.Dart.valueToCode(a,"DIVISOR",Blockly.Dart.ORDER_MULTIPLICATIVE)||"0";return[b+" % "+a,Blockly.Dart.ORDER_MULTIPLICATIVE]}; -Blockly.Dart.math_constrain=function(a){Blockly.Dart.definitions_.import_dart_math="import 'dart:math' as Math;";var b=Blockly.Dart.valueToCode(a,"VALUE",Blockly.Dart.ORDER_NONE)||"0",c=Blockly.Dart.valueToCode(a,"LOW",Blockly.Dart.ORDER_NONE)||"0";a=Blockly.Dart.valueToCode(a,"HIGH",Blockly.Dart.ORDER_NONE)||"double.INFINITY";return["Math.min(Math.max("+b+", "+c+"), "+a+")",Blockly.Dart.ORDER_UNARY_POSTFIX]}; -Blockly.Dart.math_random_int=function(a){Blockly.Dart.definitions_.import_dart_math="import 'dart:math' as Math;";var b=Blockly.Dart.valueToCode(a,"FROM",Blockly.Dart.ORDER_NONE)||"0";a=Blockly.Dart.valueToCode(a,"TO",Blockly.Dart.ORDER_NONE)||"0";return[Blockly.Dart.provideFunction_("math_random_int",["int "+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+"(num a, num b) {"," if (a > b) {"," // Swap a and b to ensure a is smaller."," num c = a;"," a = b;"," b = c;"," }"," return new Math.Random().nextInt(b - a + 1) + a;", -"}"])+"("+b+", "+a+")",Blockly.Dart.ORDER_UNARY_POSTFIX]};Blockly.Dart.math_random_float=function(a){Blockly.Dart.definitions_.import_dart_math="import 'dart:math' as Math;";return["new Math.Random().nextDouble()",Blockly.Dart.ORDER_UNARY_POSTFIX]};Blockly.Dart.variables={};Blockly.Dart.variables_get=function(a){return[Blockly.Dart.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE),Blockly.Dart.ORDER_ATOMIC]};Blockly.Dart.variables_set=function(a){var b=Blockly.Dart.valueToCode(a,"VALUE",Blockly.Dart.ORDER_ASSIGNMENT)||"0";return Blockly.Dart.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE)+" = "+b+";\n"};Blockly.Dart.colour={};Blockly.Dart.addReservedWords("Math");Blockly.Dart.colour_picker=function(a){return["'"+a.getFieldValue("COLOUR")+"'",Blockly.Dart.ORDER_ATOMIC]}; -Blockly.Dart.colour_random=function(a){Blockly.Dart.definitions_.import_dart_math="import 'dart:math' as Math;";return[Blockly.Dart.provideFunction_("colour_random",["String "+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+"() {"," String hex = '0123456789abcdef';"," var rnd = new Math.Random();"," return '#${hex[rnd.nextInt(16)]}${hex[rnd.nextInt(16)]}'"," '${hex[rnd.nextInt(16)]}${hex[rnd.nextInt(16)]}'"," '${hex[rnd.nextInt(16)]}${hex[rnd.nextInt(16)]}';","}"])+"()",Blockly.Dart.ORDER_UNARY_POSTFIX]}; -Blockly.Dart.colour_rgb=function(a){var b=Blockly.Dart.valueToCode(a,"RED",Blockly.Dart.ORDER_NONE)||0,c=Blockly.Dart.valueToCode(a,"GREEN",Blockly.Dart.ORDER_NONE)||0;a=Blockly.Dart.valueToCode(a,"BLUE",Blockly.Dart.ORDER_NONE)||0;Blockly.Dart.definitions_.import_dart_math="import 'dart:math' as Math;";return[Blockly.Dart.provideFunction_("colour_rgb",["String "+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+"(num r, num g, num b) {"," num rn = (Math.max(Math.min(r, 1), 0) * 255).round();"," String rs = rn.toInt().toRadixString(16);", -" rs = '0$rs';"," rs = rs.substring(rs.length - 2);"," num gn = (Math.max(Math.min(g, 1), 0) * 255).round();"," String gs = gn.toInt().toRadixString(16);"," gs = '0$gs';"," gs = gs.substring(gs.length - 2);"," num bn = (Math.max(Math.min(b, 1), 0) * 255).round();"," String bs = bn.toInt().toRadixString(16);"," bs = '0$bs';"," bs = bs.substring(bs.length - 2);"," return '#$rs$gs$bs';","}"])+"("+b+", "+c+", "+a+")",Blockly.Dart.ORDER_UNARY_POSTFIX]}; -Blockly.Dart.colour_blend=function(a){var b=Blockly.Dart.valueToCode(a,"COLOUR1",Blockly.Dart.ORDER_NONE)||"'#000000'",c=Blockly.Dart.valueToCode(a,"COLOUR2",Blockly.Dart.ORDER_NONE)||"'#000000'";a=Blockly.Dart.valueToCode(a,"RATIO",Blockly.Dart.ORDER_NONE)||.5;Blockly.Dart.definitions_.import_dart_math="import 'dart:math' as Math;";return[Blockly.Dart.provideFunction_("colour_blend",["String "+Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_+"(String c1, String c2, num ratio) {"," ratio = Math.max(Math.min(ratio, 1), 0);", -" int r1 = int.parse('0x${c1.substring(1, 3)}');"," int g1 = int.parse('0x${c1.substring(3, 5)}');"," int b1 = int.parse('0x${c1.substring(5, 7)}');"," int r2 = int.parse('0x${c2.substring(1, 3)}');"," int g2 = int.parse('0x${c2.substring(3, 5)}');"," int b2 = int.parse('0x${c2.substring(5, 7)}');"," num rn = (r1 * (1 - ratio) + r2 * ratio).round();"," String rs = rn.toInt().toRadixString(16);"," num gn = (g1 * (1 - ratio) + g2 * ratio).round();"," String gs = gn.toInt().toRadixString(16);", -" num bn = (b1 * (1 - ratio) + b2 * ratio).round();"," String bs = bn.toInt().toRadixString(16);"," rs = '0$rs';"," rs = rs.substring(rs.length - 2);"," gs = '0$gs';"," gs = gs.substring(gs.length - 2);"," bs = '0$bs';"," bs = bs.substring(bs.length - 2);"," return '#$rs$gs$bs';","}"])+"("+b+", "+c+", "+a+")",Blockly.Dart.ORDER_UNARY_POSTFIX]};Blockly.Dart.procedures={}; -Blockly.Dart.procedures_defreturn=function(a){var b=Blockly.Dart.variableDB_.getName(a.getFieldValue("NAME"),Blockly.Procedures.NAME_TYPE),c=Blockly.Dart.statementToCode(a,"STACK");Blockly.Dart.STATEMENT_PREFIX&&(c=Blockly.Dart.prefixLines(Blockly.Dart.STATEMENT_PREFIX.replace(/%1/g,"'"+a.id+"'"),Blockly.Dart.INDENT)+c);Blockly.Dart.INFINITE_LOOP_TRAP&&(c=Blockly.Dart.INFINITE_LOOP_TRAP.replace(/%1/g,"'"+a.id+"'")+c);var d=Blockly.Dart.valueToCode(a,"RETURN",Blockly.Dart.ORDER_NONE)||"";d&&(d=" return "+ -d+";\n");for(var e=d?"dynamic":"void",f=[],g=0;g list = str.split(exp);"," final title = new StringBuffer();"," for (String part in list) {", -" if (part.length > 0) {"," title.write(part[0].toUpperCase());"," if (part.length > 0) {"," title.write(part.substring(1).toLowerCase());"," }"," }"," }"," return title.toString();","}"])+"("+a+")",Blockly.Dart.ORDER_UNARY_POSTFIX]}; -Blockly.Dart.text_trim=function(a){var b={LEFT:".replaceFirst(new RegExp(r'^\\s+'), '')",RIGHT:".replaceFirst(new RegExp(r'\\s+$'), '')",BOTH:".trim()"}[a.getFieldValue("MODE")];return[(Blockly.Dart.valueToCode(a,"TEXT",Blockly.Dart.ORDER_UNARY_POSTFIX)||"''")+b,Blockly.Dart.ORDER_UNARY_POSTFIX]};Blockly.Dart.text_print=function(a){return"print("+(Blockly.Dart.valueToCode(a,"TEXT",Blockly.Dart.ORDER_NONE)||"''")+");\n"}; -Blockly.Dart.text_prompt_ext=function(a){Blockly.Dart.definitions_.import_dart_html="import 'dart:html' as Html;";var b="Html.window.prompt("+(a.getField("TEXT")?Blockly.Dart.quote_(a.getFieldValue("TEXT")):Blockly.Dart.valueToCode(a,"TEXT",Blockly.Dart.ORDER_NONE)||"''")+", '')";"NUMBER"==a.getFieldValue("TYPE")&&(Blockly.Dart.definitions_.import_dart_math="import 'dart:math' as Math;",b="Math.parseDouble("+b+")");return[b,Blockly.Dart.ORDER_UNARY_POSTFIX]};Blockly.Dart.text_prompt=Blockly.Dart.text_prompt_ext;Blockly.Dart.loops={}; -Blockly.Dart.controls_repeat_ext=function(a){var b=a.getField("TIMES")?String(Number(a.getFieldValue("TIMES"))):Blockly.Dart.valueToCode(a,"TIMES",Blockly.Dart.ORDER_ASSIGNMENT)||"0",c=Blockly.Dart.statementToCode(a,"DO"),c=Blockly.Dart.addLoopTrap(c,a.id);a="";var d=Blockly.Dart.variableDB_.getDistinctName("count",Blockly.Variables.NAME_TYPE),e=b;b.match(/^\w+$/)||Blockly.isNumber(b)||(e=Blockly.Dart.variableDB_.getDistinctName("repeat_end",Blockly.Variables.NAME_TYPE),a+="var "+e+" = "+b+";\n"); -return a+("for (int "+d+" = 0; "+d+" < "+e+"; "+d+"++) {\n"+c+"}\n")};Blockly.Dart.controls_repeat=Blockly.Dart.controls_repeat_ext;Blockly.Dart.controls_whileUntil=function(a){var b="UNTIL"==a.getFieldValue("MODE"),c=Blockly.Dart.valueToCode(a,"BOOL",b?Blockly.Dart.ORDER_UNARY_PREFIX:Blockly.Dart.ORDER_NONE)||"false",d=Blockly.Dart.statementToCode(a,"DO"),d=Blockly.Dart.addLoopTrap(d,a.id);b&&(c="!"+c);return"while ("+c+") {\n"+d+"}\n"}; -Blockly.Dart.controls_for=function(a){var b=Blockly.Dart.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE),c=Blockly.Dart.valueToCode(a,"FROM",Blockly.Dart.ORDER_ASSIGNMENT)||"0",d=Blockly.Dart.valueToCode(a,"TO",Blockly.Dart.ORDER_ASSIGNMENT)||"0",e=Blockly.Dart.valueToCode(a,"BY",Blockly.Dart.ORDER_ASSIGNMENT)||"1",f=Blockly.Dart.statementToCode(a,"DO"),f=Blockly.Dart.addLoopTrap(f,a.id);if(Blockly.isNumber(c)&&Blockly.isNumber(d)&&Blockly.isNumber(e)){var g=parseFloat(c)<= -parseFloat(d);a="for ("+b+" = "+c+"; "+b+(g?" <= ":" >= ")+d+"; "+b;b=Math.abs(parseFloat(e));a=(1==b?a+(g?"++":"--"):a+((g?" += ":" -= ")+b))+(") {\n"+f+"}\n")}else a="",g=c,c.match(/^\w+$/)||Blockly.isNumber(c)||(g=Blockly.Dart.variableDB_.getDistinctName(b+"_start",Blockly.Variables.NAME_TYPE),a+="var "+g+" = "+c+";\n"),c=d,d.match(/^\w+$/)||Blockly.isNumber(d)||(c=Blockly.Dart.variableDB_.getDistinctName(b+"_end",Blockly.Variables.NAME_TYPE),a+="var "+c+" = "+d+";\n"),d=Blockly.Dart.variableDB_.getDistinctName(b+ -"_inc",Blockly.Variables.NAME_TYPE),a+="num "+d+" = ",a=Blockly.isNumber(e)?a+(Math.abs(e)+";\n"):a+("("+e+").abs();\n"),a=a+("if ("+g+" > "+c+") {\n")+(Blockly.Dart.INDENT+d+" = -"+d+";\n"),a+="}\n",a+="for ("+b+" = "+g+"; "+d+" >= 0 ? "+b+" <= "+c+" : "+b+" >= "+c+"; "+b+" += "+d+") {\n"+f+"}\n";return a}; -Blockly.Dart.controls_forEach=function(a){var b=Blockly.Dart.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE),c=Blockly.Dart.valueToCode(a,"LIST",Blockly.Dart.ORDER_ASSIGNMENT)||"[]",d=Blockly.Dart.statementToCode(a,"DO"),d=Blockly.Dart.addLoopTrap(d,a.id);return"for (var "+b+" in "+c+") {\n"+d+"}\n"}; -Blockly.Dart.controls_flow_statements=function(a){switch(a.getFieldValue("FLOW")){case "BREAK":return"break;\n";case "CONTINUE":return"continue;\n"}throw"Unknown flow statement.";};Blockly.Dart.logic={};Blockly.Dart.controls_if=function(a){for(var b=0,c=Blockly.Dart.valueToCode(a,"IF"+b,Blockly.Dart.ORDER_NONE)||"false",d=Blockly.Dart.statementToCode(a,"DO"+b),e="if ("+c+") {\n"+d+"}",b=1;b<=a.elseifCount_;b++)c=Blockly.Dart.valueToCode(a,"IF"+b,Blockly.Dart.ORDER_NONE)||"false",d=Blockly.Dart.statementToCode(a,"DO"+b),e+=" else if ("+c+") {\n"+d+"}";a.elseCount_&&(d=Blockly.Dart.statementToCode(a,"ELSE"),e+=" else {\n"+d+"}");return e+"\n"}; -Blockly.Dart.logic_compare=function(a){var b={EQ:"==",NEQ:"!=",LT:"<",LTE:"<=",GT:">",GTE:">="}[a.getFieldValue("OP")],c="=="==b||"!="==b?Blockly.Dart.ORDER_EQUALITY:Blockly.Dart.ORDER_RELATIONAL,d=Blockly.Dart.valueToCode(a,"A",c)||"0";a=Blockly.Dart.valueToCode(a,"B",c)||"0";return[d+" "+b+" "+a,c]}; -Blockly.Dart.logic_operation=function(a){var b="AND"==a.getFieldValue("OP")?"&&":"||",c="&&"==b?Blockly.Dart.ORDER_LOGICAL_AND:Blockly.Dart.ORDER_LOGICAL_OR,d=Blockly.Dart.valueToCode(a,"A",c);a=Blockly.Dart.valueToCode(a,"B",c);if(d||a){var e="&&"==b?"true":"false";d||(d=e);a||(a=e)}else a=d="false";return[d+" "+b+" "+a,c]};Blockly.Dart.logic_negate=function(a){var b=Blockly.Dart.ORDER_UNARY_PREFIX;return["!"+(Blockly.Dart.valueToCode(a,"BOOL",b)||"true"),b]}; -Blockly.Dart.logic_boolean=function(a){return["TRUE"==a.getFieldValue("BOOL")?"true":"false",Blockly.Dart.ORDER_ATOMIC]};Blockly.Dart.logic_null=function(a){return["null",Blockly.Dart.ORDER_ATOMIC]};Blockly.Dart.logic_ternary=function(a){var b=Blockly.Dart.valueToCode(a,"IF",Blockly.Dart.ORDER_CONDITIONAL)||"false",c=Blockly.Dart.valueToCode(a,"THEN",Blockly.Dart.ORDER_CONDITIONAL)||"null";a=Blockly.Dart.valueToCode(a,"ELSE",Blockly.Dart.ORDER_CONDITIONAL)||"null";return[b+" ? "+c+" : "+a,Blockly.Dart.ORDER_CONDITIONAL]}; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/demos/code/style.css b/backend/_pv_1_3_5/static/blockly/demos/code/style.css deleted file mode 100755 index e05664f24..000000000 --- a/backend/_pv_1_3_5/static/blockly/demos/code/style.css +++ /dev/null @@ -1,163 +0,0 @@ -html, body { - height: 100%; -} - -body { - background-color: #fff; - font-family: sans-serif; - margin: 0; - overflow: hidden; -} - -.farSide { - text-align: right; -} - -html[dir="RTL"] .farSide { - text-align: left; -} - -/* Buttons */ -button { - margin: 5px; - padding: 10px; - border-radius: 4px; - border: 1px solid #ddd; - font-size: large; - background-color: #eee; - color: #000; -} -button.primary { - border: 1px solid #dd4b39; - background-color: #dd4b39; - color: #fff; -} -button.primary>img { - opacity: 1; -} -button>img { - opacity: 0.6; - vertical-align: text-bottom; -} -button:hover>img { - opacity: 1; -} -button:active { - border: 1px solid #888 !important; -} -button:hover { - box-shadow: 2px 2px 5px #888; -} -button.disabled:hover>img { - opacity: 0.6; -} -button.disabled { - display: none; -} -button.notext { - font-size: 10%; -} - -h1 { - font-weight: normal; - font-size: 140%; - margin-left: 5px; - margin-right: 5px; -} - -/* Tabs */ -#tabRow>td { - border: 1px solid #ccc; - border-bottom: none; -} -td.tabon { - border-bottom-color: #ddd !important; - background-color: #ddd; - padding: 5px 19px; -} -td.taboff { - cursor: pointer; - padding: 5px 19px; -} -td.taboff:hover { - background-color: #eee; -} -td.tabmin { - border-top-style: none !important; - border-left-style: none !important; - border-right-style: none !important; -} -td.tabmax { - border-top-style: none !important; - border-left-style: none !important; - border-right-style: none !important; - width: 99%; - padding-left: 10px; - padding-right: 10px; - text-align: right; -} -html[dir=rtl] td.tabmax { - text-align: left; -} - -table { - border-collapse: collapse; - margin: 0; - padding: 0; - border: none; -} -td { - padding: 0; - vertical-align: top; -} -.content { - visibility: hidden; - margin: 0; - padding: 1ex; - position: absolute; - direction: ltr; -} -pre.content { - border: 1px solid #ccc; - overflow: scroll; -} -#content_blocks { - padding: 0; -} -.blocklySvg { - border-top: none !important; -} -#content_xml { - resize: none; - outline: none; - border: 1px solid #ccc; - font-family: monospace; - overflow: scroll; -} -#languageMenu { - vertical-align: top; - margin-top: 15px; - margin-right: 15px; -} - -/* Buttons */ -button { - padding: 1px 10px; - margin: 1px 5px; -} - -/* Sprited icons. */ -.icon21 { - height: 21px; - width: 21px; - background-image: url(icons.png); -} -.trash { - background-position: 0px 0px; -} -.link { - background-position: -21px 0px; -} -.run { - background-position: -42px 0px; -} diff --git a/backend/_pv_1_3_5/static/blockly/generators/dart.js b/backend/_pv_1_3_5/static/blockly/generators/dart.js deleted file mode 100755 index 72c828ce5..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/dart.js +++ /dev/null @@ -1,280 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2014 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Helper functions for generating Dart for blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Dart'); - -goog.require('Blockly.Generator'); - - -/** - * Dart code generator. - * @type {!Blockly.Generator} - */ -Blockly.Dart = new Blockly.Generator('Dart'); - -/** - * List of illegal variable names. - * This is not intended to be a security feature. Blockly is 100% client-side, - * so bypassing this list is trivial. This is intended to prevent users from - * accidentally clobbering a built-in object or function. - * @private - */ -Blockly.Dart.addReservedWords( - // https://www.dartlang.org/docs/spec/latest/dart-language-specification.pdf - // Section 16.1.1 - 'assert,break,case,catch,class,const,continue,default,do,else,enum,' + - 'extends,false,final,finally,for,if,in,is,new,null,rethrow,return,super,' + - 'switch,this,throw,true,try,var,void,while,with,' + - // https://api.dartlang.org/dart_core.html - 'print,identityHashCode,identical,BidirectionalIterator,Comparable,' + - 'double,Function,int,Invocation,Iterable,Iterator,List,Map,Match,num,' + - 'Pattern,RegExp,Set,StackTrace,String,StringSink,Type,bool,DateTime,' + - 'Deprecated,Duration,Expando,Null,Object,RuneIterator,Runes,Stopwatch,' + - 'StringBuffer,Symbol,Uri,Comparator,AbstractClassInstantiationError,' + - 'ArgumentError,AssertionError,CastError,ConcurrentModificationError,' + - 'CyclicInitializationError,Error,Exception,FallThroughError,' + - 'FormatException,IntegerDivisionByZeroException,NoSuchMethodError,' + - 'NullThrownError,OutOfMemoryError,RangeError,StackOverflowError,' + - 'StateError,TypeError,UnimplementedError,UnsupportedError' -); - -/** - * Order of operation ENUMs. - * https://www.dartlang.org/docs/dart-up-and-running/ch02.html#operator_table - */ -Blockly.Dart.ORDER_ATOMIC = 0; // 0 "" ... -Blockly.Dart.ORDER_UNARY_POSTFIX = 1; // expr++ expr-- () [] . ?. -Blockly.Dart.ORDER_UNARY_PREFIX = 2; // -expr !expr ~expr ++expr --expr -Blockly.Dart.ORDER_MULTIPLICATIVE = 3; // * / % ~/ -Blockly.Dart.ORDER_ADDITIVE = 4; // + - -Blockly.Dart.ORDER_SHIFT = 5; // << >> -Blockly.Dart.ORDER_BITWISE_AND = 6; // & -Blockly.Dart.ORDER_BITWISE_XOR = 7; // ^ -Blockly.Dart.ORDER_BITWISE_OR = 8; // | -Blockly.Dart.ORDER_RELATIONAL = 9; // >= > <= < as is is! -Blockly.Dart.ORDER_EQUALITY = 10; // == != -Blockly.Dart.ORDER_LOGICAL_AND = 11; // && -Blockly.Dart.ORDER_LOGICAL_OR = 12; // || -Blockly.Dart.ORDER_IF_NULL = 13; // ?? -Blockly.Dart.ORDER_CONDITIONAL = 14; // expr ? expr : expr -Blockly.Dart.ORDER_CASCADE = 15; // .. -Blockly.Dart.ORDER_ASSIGNMENT = 16; // = *= /= ~/= %= += -= <<= >>= &= ^= |= -Blockly.Dart.ORDER_NONE = 99; // (...) - -/** - * Allow for switching between one and zero based indexing for lists and text, - * one based by default. - */ -Blockly.Dart.ONE_BASED_INDEXING = true; - -/** - * Initialise the database of variable names. - * @param {!Blockly.Workspace} workspace Workspace to generate code from. - */ -Blockly.Dart.init = function(workspace) { - // Create a dictionary of definitions to be printed before the code. - Blockly.Dart.definitions_ = Object.create(null); - // Create a dictionary mapping desired function names in definitions_ - // to actual function names (to avoid collisions with user functions). - Blockly.Dart.functionNames_ = Object.create(null); - - if (!Blockly.Dart.variableDB_) { - Blockly.Dart.variableDB_ = - new Blockly.Names(Blockly.Dart.RESERVED_WORDS_); - } else { - Blockly.Dart.variableDB_.reset(); - } - - var defvars = []; - var variables = workspace.variableList; - if (variables.length) { - for (var i = 0; i < variables.length; i++) { - defvars[i] = Blockly.Dart.variableDB_.getName(variables[i], - Blockly.Variables.NAME_TYPE); - } - Blockly.Dart.definitions_['variables'] = - 'var ' + defvars.join(', ') + ';'; - } -}; - -/** - * Prepend the generated code with the variable definitions. - * @param {string} code Generated code. - * @return {string} Completed code. - */ -Blockly.Dart.finish = function(code) { - // Indent every line. - if (code) { - code = Blockly.Dart.prefixLines(code, Blockly.Dart.INDENT); - } - code = 'main() {\n' + code + '}'; - - // Convert the definitions dictionary into a list. - var imports = []; - var definitions = []; - for (var name in Blockly.Dart.definitions_) { - var def = Blockly.Dart.definitions_[name]; - if (def.match(/^import\s/)) { - imports.push(def); - } else { - definitions.push(def); - } - } - // Clean up temporary data. - delete Blockly.Dart.definitions_; - delete Blockly.Dart.functionNames_; - Blockly.Dart.variableDB_.reset(); - var allDefs = imports.join('\n') + '\n\n' + definitions.join('\n\n'); - return allDefs.replace(/\n\n+/g, '\n\n').replace(/\n*$/, '\n\n\n') + code; -}; - -/** - * Naked values are top-level blocks with outputs that aren't plugged into - * anything. A trailing semicolon is needed to make this legal. - * @param {string} line Line of generated code. - * @return {string} Legal line of code. - */ -Blockly.Dart.scrubNakedValue = function(line) { - return line + ';\n'; -}; - -/** - * Encode a string as a properly escaped Dart string, complete with quotes. - * @param {string} string Text to encode. - * @return {string} Dart string. - * @private - */ -Blockly.Dart.quote_ = function(string) { - // Can't use goog.string.quote since $ must also be escaped. - string = string.replace(/\\/g, '\\\\') - .replace(/\n/g, '\\\n') - .replace(/\$/g, '\\$') - .replace(/'/g, '\\\''); - return '\'' + string + '\''; -}; - -/** - * Common tasks for generating Dart from blocks. - * Handles comments for the specified block and any connected value blocks. - * Calls any statements following this block. - * @param {!Blockly.Block} block The current block. - * @param {string} code The Dart code created for this block. - * @return {string} Dart code with comments and subsequent blocks added. - * @private - */ -Blockly.Dart.scrub_ = function(block, code) { - var commentCode = ''; - // Only collect comments for blocks that aren't inline. - if (!block.outputConnection || !block.outputConnection.targetConnection) { - // Collect comment for this block. - var comment = block.getCommentText(); - comment = Blockly.utils.wrap(comment, Blockly.Dart.COMMENT_WRAP - 3); - if (comment) { - if (block.getProcedureDef) { - // Use documentation comment for function comments. - commentCode += Blockly.Dart.prefixLines(comment + '\n', '/// '); - } else { - commentCode += Blockly.Dart.prefixLines(comment + '\n', '// '); - } - } - // Collect comments for all value arguments. - // Don't collect comments for nested statements. - for (var i = 0; i < block.inputList.length; i++) { - if (block.inputList[i].type == Blockly.INPUT_VALUE) { - var childBlock = block.inputList[i].connection.targetBlock(); - if (childBlock) { - var comment = Blockly.Dart.allNestedComments(childBlock); - if (comment) { - commentCode += Blockly.Dart.prefixLines(comment, '// '); - } - } - } - } - } - var nextBlock = block.nextConnection && block.nextConnection.targetBlock(); - var nextCode = Blockly.Dart.blockToCode(nextBlock); - return commentCode + code + nextCode; -}; - -/** - * Gets a property and adjusts the value while taking into account indexing. - * @param {!Blockly.Block} block The block. - * @param {string} atId The property ID of the element to get. - * @param {number=} opt_delta Value to add. - * @param {boolean=} opt_negate Whether to negate the value. - * @param {number=} opt_order The highest order acting on this value. - * @return {string|number} - */ -Blockly.Dart.getAdjusted = function(block, atId, opt_delta, opt_negate, - opt_order) { - var delta = opt_delta || 0; - var order = opt_order || Blockly.Dart.ORDER_NONE; - if (Blockly.Dart.ONE_BASED_INDEXING) { - delta--; - } - var defaultAtIndex = Blockly.Dart.ONE_BASED_INDEXING ? '1' : '0'; - if (delta) { - var at = Blockly.Dart.valueToCode(block, atId, - Blockly.Dart.ORDER_ADDITIVE) || defaultAtIndex; - } else if (opt_negate) { - var at = Blockly.Dart.valueToCode(block, atId, - Blockly.Dart.ORDER_UNARY_PREFIX) || defaultAtIndex; - } else { - var at = Blockly.Dart.valueToCode(block, atId, order) || - defaultAtIndex; - } - - if (Blockly.isNumber(at)) { - // If the index is a naked number, adjust it right now. - at = parseInt(at, 10) + delta; - if (opt_negate) { - at = -at; - } - } else { - // If the index is dynamic, adjust it in code. - if (delta > 0) { - at = at + ' + ' + delta; - var innerOrder = Blockly.Dart.ORDER_ADDITIVE; - } else if (delta < 0) { - at = at + ' - ' + -delta; - var innerOrder = Blockly.Dart.ORDER_ADDITIVE; - } - if (opt_negate) { - if (delta) { - at = '-(' + at + ')'; - } else { - at = '-' + at; - } - var innerOrder = Blockly.Dart.ORDER_UNARY_PREFIX; - } - innerOrder = Math.floor(innerOrder); - order = Math.floor(order); - if (innerOrder && order >= innerOrder) { - at = '(' + at + ')'; - } - } - return at; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/dart/colour.js b/backend/_pv_1_3_5/static/blockly/generators/dart/colour.js deleted file mode 100755 index 7ded91419..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/dart/colour.js +++ /dev/null @@ -1,128 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2014 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Dart for colour blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Dart.colour'); - -goog.require('Blockly.Dart'); - - -Blockly.Dart.addReservedWords('Math'); - -Blockly.Dart['colour_picker'] = function(block) { - // Colour picker. - var code = '\'' + block.getFieldValue('COLOUR') + '\''; - return [code, Blockly.Dart.ORDER_ATOMIC]; -}; - -Blockly.Dart['colour_random'] = function(block) { - // Generate a random colour. - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - var functionName = Blockly.Dart.provideFunction_( - 'colour_random', - ['String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + '() {', - ' String hex = \'0123456789abcdef\';', - ' var rnd = new Math.Random();', - ' return \'#${hex[rnd.nextInt(16)]}${hex[rnd.nextInt(16)]}\'', - ' \'${hex[rnd.nextInt(16)]}${hex[rnd.nextInt(16)]}\'', - ' \'${hex[rnd.nextInt(16)]}${hex[rnd.nextInt(16)]}\';', - '}']); - var code = functionName + '()'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; - -Blockly.Dart['colour_rgb'] = function(block) { - // Compose a colour from RGB components expressed as percentages. - var red = Blockly.Dart.valueToCode(block, 'RED', - Blockly.Dart.ORDER_NONE) || 0; - var green = Blockly.Dart.valueToCode(block, 'GREEN', - Blockly.Dart.ORDER_NONE) || 0; - var blue = Blockly.Dart.valueToCode(block, 'BLUE', - Blockly.Dart.ORDER_NONE) || 0; - - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - var functionName = Blockly.Dart.provideFunction_( - 'colour_rgb', - ['String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(num r, num g, num b) {', - ' num rn = (Math.max(Math.min(r, 1), 0) * 255).round();', - ' String rs = rn.toInt().toRadixString(16);', - ' rs = \'0$rs\';', - ' rs = rs.substring(rs.length - 2);', - ' num gn = (Math.max(Math.min(g, 1), 0) * 255).round();', - ' String gs = gn.toInt().toRadixString(16);', - ' gs = \'0$gs\';', - ' gs = gs.substring(gs.length - 2);', - ' num bn = (Math.max(Math.min(b, 1), 0) * 255).round();', - ' String bs = bn.toInt().toRadixString(16);', - ' bs = \'0$bs\';', - ' bs = bs.substring(bs.length - 2);', - ' return \'#$rs$gs$bs\';', - '}']); - var code = functionName + '(' + red + ', ' + green + ', ' + blue + ')'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; - -Blockly.Dart['colour_blend'] = function(block) { - // Blend two colours together. - var c1 = Blockly.Dart.valueToCode(block, 'COLOUR1', - Blockly.Dart.ORDER_NONE) || '\'#000000\''; - var c2 = Blockly.Dart.valueToCode(block, 'COLOUR2', - Blockly.Dart.ORDER_NONE) || '\'#000000\''; - var ratio = Blockly.Dart.valueToCode(block, 'RATIO', - Blockly.Dart.ORDER_NONE) || 0.5; - - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - var functionName = Blockly.Dart.provideFunction_( - 'colour_blend', - ['String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(String c1, String c2, num ratio) {', - ' ratio = Math.max(Math.min(ratio, 1), 0);', - ' int r1 = int.parse(\'0x${c1.substring(1, 3)}\');', - ' int g1 = int.parse(\'0x${c1.substring(3, 5)}\');', - ' int b1 = int.parse(\'0x${c1.substring(5, 7)}\');', - ' int r2 = int.parse(\'0x${c2.substring(1, 3)}\');', - ' int g2 = int.parse(\'0x${c2.substring(3, 5)}\');', - ' int b2 = int.parse(\'0x${c2.substring(5, 7)}\');', - ' num rn = (r1 * (1 - ratio) + r2 * ratio).round();', - ' String rs = rn.toInt().toRadixString(16);', - ' num gn = (g1 * (1 - ratio) + g2 * ratio).round();', - ' String gs = gn.toInt().toRadixString(16);', - ' num bn = (b1 * (1 - ratio) + b2 * ratio).round();', - ' String bs = bn.toInt().toRadixString(16);', - ' rs = \'0$rs\';', - ' rs = rs.substring(rs.length - 2);', - ' gs = \'0$gs\';', - ' gs = gs.substring(gs.length - 2);', - ' bs = \'0$bs\';', - ' bs = bs.substring(bs.length - 2);', - ' return \'#$rs$gs$bs\';', - '}']); - var code = functionName + '(' + c1 + ', ' + c2 + ', ' + ratio + ')'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/dart/lists.js b/backend/_pv_1_3_5/static/blockly/generators/dart/lists.js deleted file mode 100755 index ae5ecc20e..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/dart/lists.js +++ /dev/null @@ -1,452 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2014 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Dart for list blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Dart.lists'); - -goog.require('Blockly.Dart'); - - -Blockly.Dart.addReservedWords('Math'); - -Blockly.Dart['lists_create_empty'] = function(block) { - // Create an empty list. - return ['[]', Blockly.Dart.ORDER_ATOMIC]; -}; - -Blockly.Dart['lists_create_with'] = function(block) { - // Create a list with any number of elements of any type. - var elements = new Array(block.itemCount_); - for (var i = 0; i < block.itemCount_; i++) { - elements[i] = Blockly.Dart.valueToCode(block, 'ADD' + i, - Blockly.Dart.ORDER_NONE) || 'null'; - } - var code = '[' + elements.join(', ') + ']'; - return [code, Blockly.Dart.ORDER_ATOMIC]; -}; - -Blockly.Dart['lists_repeat'] = function(block) { - // Create a list with one element repeated. - var element = Blockly.Dart.valueToCode(block, 'ITEM', - Blockly.Dart.ORDER_NONE) || 'null'; - var repeatCount = Blockly.Dart.valueToCode(block, 'NUM', - Blockly.Dart.ORDER_NONE) || '0'; - var code = 'new List.filled(' + repeatCount + ', ' + element + ')'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; - -Blockly.Dart['lists_length'] = function(block) { - // String or array length. - var list = Blockly.Dart.valueToCode(block, 'VALUE', - Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]'; - return [list + '.length', Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; - -Blockly.Dart['lists_isEmpty'] = function(block) { - // Is the string null or array empty? - var list = Blockly.Dart.valueToCode(block, 'VALUE', - Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]'; - return [list + '.isEmpty', Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; - -Blockly.Dart['lists_indexOf'] = function(block) { - // Find an item in the list. - var operator = block.getFieldValue('END') == 'FIRST' ? - 'indexOf' : 'lastIndexOf'; - var item = Blockly.Dart.valueToCode(block, 'FIND', - Blockly.Dart.ORDER_NONE) || '\'\''; - var list = Blockly.Dart.valueToCode(block, 'VALUE', - Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]'; - var code = list + '.' + operator + '(' + item + ')'; - if (Blockly.Dart.ONE_BASED_INDEXING) { - return [code + ' + 1', Blockly.Dart.ORDER_ADDITIVE]; - } - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; - -Blockly.Dart['lists_getIndex'] = function(block) { - // Get element at index. - // Note: Until January 2013 this block did not have MODE or WHERE inputs. - var mode = block.getFieldValue('MODE') || 'GET'; - var where = block.getFieldValue('WHERE') || 'FROM_START'; - var listOrder = (where == 'RANDOM' || where == 'FROM_END') ? - Blockly.Dart.ORDER_NONE : Blockly.Dart.ORDER_UNARY_POSTFIX; - var list = Blockly.Dart.valueToCode(block, 'VALUE', listOrder) || '[]'; - // Cache non-trivial values to variables to prevent repeated look-ups. - // Closure, which accesses and modifies 'list'. - function cacheList() { - var listVar = Blockly.Dart.variableDB_.getDistinctName( - 'tmp_list', Blockly.Variables.NAME_TYPE); - var code = 'List ' + listVar + ' = ' + list + ';\n'; - list = listVar; - return code; - } - // If `list` would be evaluated more than once (which is the case for - // RANDOM REMOVE and FROM_END) and is non-trivial, make sure to access it - // only once. - if (((where == 'RANDOM' && mode == 'REMOVE') || where == 'FROM_END') && - !list.match(/^\w+$/)) { - // `list` is an expression, so we may not evaluate it more than once. - if (where == 'RANDOM') { - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - // We can use multiple statements. - var code = cacheList(); - var xVar = Blockly.Dart.variableDB_.getDistinctName( - 'tmp_x', Blockly.Variables.NAME_TYPE); - code += 'int ' + xVar + ' = new Math.Random().nextInt(' + list + - '.length);\n'; - code += list + '.removeAt(' + xVar + ');\n'; - return code; - } else { // where == 'FROM_END' - if (mode == 'REMOVE') { - // We can use multiple statements. - var at = Blockly.Dart.getAdjusted(block, 'AT', 1, false, - Blockly.Dart.ORDER_ADDITIVE); - var code = cacheList(); - code += list + '.removeAt(' + list + '.length' + ' - ' + at + ');\n'; - return code; - - } else if (mode == 'GET') { - var at = Blockly.Dart.getAdjusted(block, 'AT', 1); - // We need to create a procedure to avoid reevaluating values. - var functionName = Blockly.Dart.provideFunction_( - 'lists_get_from_end', - ['dynamic ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(List my_list, num x) {', - ' x = my_list.length - x;', - ' return my_list[x];', - '}']); - var code = functionName + '(' + list + ', ' + at + ')'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - } else if (mode == 'GET_REMOVE') { - var at = Blockly.Dart.getAdjusted(block, 'AT', 1); - // We need to create a procedure to avoid reevaluating values. - var functionName = Blockly.Dart.provideFunction_( - 'lists_remove_from_end', - ['dynamic ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(List my_list, num x) {', - ' x = my_list.length - x;', - ' return my_list.removeAt(x);', - '}']); - var code = functionName + '(' + list + ', ' + at + ')'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - } - } - } else { - // Either `list` is a simple variable, or we only need to refer to `list` - // once. - switch (where) { - case 'FIRST': - if (mode == 'GET') { - var code = list + '.first'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - } else if (mode == 'GET_REMOVE') { - var code = list + '.removeAt(0)'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - } else if (mode == 'REMOVE') { - return list + '.removeAt(0);\n'; - } - break; - case 'LAST': - if (mode == 'GET') { - var code = list + '.last'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - } else if (mode == 'GET_REMOVE') { - var code = list + '.removeLast()'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - } else if (mode == 'REMOVE') { - return list + '.removeLast();\n'; - } - break; - case 'FROM_START': - var at = Blockly.Dart.getAdjusted(block, 'AT'); - if (mode == 'GET') { - var code = list + '[' + at + ']'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - } else if (mode == 'GET_REMOVE') { - var code = list + '.removeAt(' + at + ')'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - } else if (mode == 'REMOVE') { - return list + '.removeAt(' + at + ');\n'; - } - break; - case 'FROM_END': - var at = Blockly.Dart.getAdjusted(block, 'AT', 1, false, - Blockly.Dart.ORDER_ADDITIVE); - if (mode == 'GET') { - var code = list + '[' + list + '.length - ' + at + ']'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - } else if (mode == 'GET_REMOVE' || mode == 'REMOVE') { - var code = list + '.removeAt(' + list + '.length - ' + at + ')'; - if (mode == 'GET_REMOVE') { - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - } else if (mode == 'REMOVE') { - return code + ';\n'; - } - } - break; - case 'RANDOM': - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - if (mode == 'REMOVE') { - // We can use multiple statements. - var xVar = Blockly.Dart.variableDB_.getDistinctName( - 'tmp_x', Blockly.Variables.NAME_TYPE); - var code = 'int ' + xVar + ' = new Math.Random().nextInt(' + list + - '.length);\n'; - code += list + '.removeAt(' + xVar + ');\n'; - return code; - } else if (mode == 'GET') { - var functionName = Blockly.Dart.provideFunction_( - 'lists_get_random_item', - ['dynamic ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(List my_list) {', - ' int x = new Math.Random().nextInt(my_list.length);', - ' return my_list[x];', - '}']); - var code = functionName + '(' + list + ')'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - } else if (mode == 'GET_REMOVE') { - var functionName = Blockly.Dart.provideFunction_( - 'lists_remove_random_item', - ['dynamic ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(List my_list) {', - ' int x = new Math.Random().nextInt(my_list.length);', - ' return my_list.removeAt(x);', - '}']); - var code = functionName + '(' + list + ')'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - } - break; - } - } - throw 'Unhandled combination (lists_getIndex).'; -}; - -Blockly.Dart['lists_setIndex'] = function(block) { - // Set element at index. - // Note: Until February 2013 this block did not have MODE or WHERE inputs. - var mode = block.getFieldValue('MODE') || 'GET'; - var where = block.getFieldValue('WHERE') || 'FROM_START'; - var list = Blockly.Dart.valueToCode(block, 'LIST', - Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]'; - var value = Blockly.Dart.valueToCode(block, 'TO', - Blockly.Dart.ORDER_ASSIGNMENT) || 'null'; - // Cache non-trivial values to variables to prevent repeated look-ups. - // Closure, which accesses and modifies 'list'. - function cacheList() { - if (list.match(/^\w+$/)) { - return ''; - } - var listVar = Blockly.Dart.variableDB_.getDistinctName( - 'tmp_list', Blockly.Variables.NAME_TYPE); - var code = 'List ' + listVar + ' = ' + list + ';\n'; - list = listVar; - return code; - } - switch (where) { - case 'FIRST': - if (mode == 'SET') { - return list + '[0] = ' + value + ';\n'; - } else if (mode == 'INSERT') { - return list + '.insert(0, ' + value + ');\n'; - } - break; - case 'LAST': - if (mode == 'SET') { - var code = cacheList(); - code += list + '[' + list + '.length - 1] = ' + value + ';\n'; - return code; - } else if (mode == 'INSERT') { - return list + '.add(' + value + ');\n'; - } - break; - case 'FROM_START': - var at = Blockly.Dart.getAdjusted(block, 'AT'); - if (mode == 'SET') { - return list + '[' + at + '] = ' + value + ';\n'; - } else if (mode == 'INSERT') { - return list + '.insert(' + at + ', ' + value + ');\n'; - } - break; - case 'FROM_END': - var at = Blockly.Dart.getAdjusted(block, 'AT', 1, false, - Blockly.Dart.ORDER_ADDITIVE); - var code = cacheList(); - if (mode == 'SET') { - code += list + '[' + list + '.length - ' + at + '] = ' + value + - ';\n'; - return code; - } else if (mode == 'INSERT') { - code += list + '.insert(' + list + '.length - ' + at + ', ' + - value + ');\n'; - return code; - } - break; - case 'RANDOM': - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - var code = cacheList(); - var xVar = Blockly.Dart.variableDB_.getDistinctName( - 'tmp_x', Blockly.Variables.NAME_TYPE); - code += 'int ' + xVar + - ' = new Math.Random().nextInt(' + list + '.length);\n'; - if (mode == 'SET') { - code += list + '[' + xVar + '] = ' + value + ';\n'; - return code; - } else if (mode == 'INSERT') { - code += list + '.insert(' + xVar + ', ' + value + ');\n'; - return code; - } - break; - } - throw 'Unhandled combination (lists_setIndex).'; -}; - -Blockly.Dart['lists_getSublist'] = function(block) { - // Get sublist. - var list = Blockly.Dart.valueToCode(block, 'LIST', - Blockly.Dart.ORDER_UNARY_POSTFIX) || '[]'; - var where1 = block.getFieldValue('WHERE1'); - var where2 = block.getFieldValue('WHERE2'); - if (list.match(/^\w+$/) || (where1 != 'FROM_END' && where2 == 'FROM_START')) { - // If the list is a is a variable or doesn't require a call for length, - // don't generate a helper function. - switch (where1) { - case 'FROM_START': - var at1 = Blockly.Dart.getAdjusted(block, 'AT1'); - break; - case 'FROM_END': - var at1 = Blockly.Dart.getAdjusted(block, 'AT1', 1, false, - Blockly.Dart.ORDER_ADDITIVE); - at1 = list + '.length - ' + at1; - break; - case 'FIRST': - var at1 = '0'; - break; - default: - throw 'Unhandled option (lists_getSublist).'; - } - switch (where2) { - case 'FROM_START': - var at2 = Blockly.Dart.getAdjusted(block, 'AT2', 1); - break; - case 'FROM_END': - var at2 = Blockly.Dart.getAdjusted(block, 'AT2', 0, false, - Blockly.Dart.ORDER_ADDITIVE); - at2 = list + '.length - ' + at2; - break; - case 'LAST': - // There is no second index if LAST option is chosen. - break; - default: - throw 'Unhandled option (lists_getSublist).'; - } - if (where2 == 'LAST') { - var code = list + '.sublist(' + at1 + ')'; - } else { - var code = list + '.sublist(' + at1 + ', ' + at2 + ')'; - } - } else { - var at1 = Blockly.Dart.getAdjusted(block, 'AT1'); - var at2 = Blockly.Dart.getAdjusted(block, 'AT2'); - var functionName = Blockly.Dart.provideFunction_( - 'lists_get_sublist', - ['List ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(list, where1, at1, where2, at2) {', - ' int getAt(where, at) {', - ' if (where == \'FROM_END\') {', - ' at = list.length - 1 - at;', - ' } else if (where == \'FIRST\') {', - ' at = 0;', - ' } else if (where == \'LAST\') {', - ' at = list.length - 1;', - ' } else if (where != \'FROM_START\') {', - ' throw \'Unhandled option (lists_getSublist).\';', - ' }', - ' return at;', - ' }', - ' at1 = getAt(where1, at1);', - ' at2 = getAt(where2, at2) + 1;', - ' return list.sublist(at1, at2);', - '}']); - var code = functionName + '(' + list + ', \'' + - where1 + '\', ' + at1 + ', \'' + where2 + '\', ' + at2 + ')'; - } - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; - -Blockly.Dart['lists_sort'] = function(block) { - // Block for sorting a list. - var list = Blockly.Dart.valueToCode(block, 'LIST', - Blockly.Dart.ORDER_NONE) || '[]'; - var direction = block.getFieldValue('DIRECTION') === '1' ? 1 : -1; - var type = block.getFieldValue('TYPE'); - var sortFunctionName = Blockly.Dart.provideFunction_( - 'lists_sort', - ['List ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(list, type, direction) {', - ' var compareFuncs = {', - ' "NUMERIC": (a, b) => direction * a.compareTo(b),', - ' "TEXT": (a, b) => direction * ' + - 'a.toString().compareTo(b.toString()),', - ' "IGNORE_CASE": ', - ' (a, b) => direction * ', - ' a.toString().toLowerCase().compareTo(b.toString().toLowerCase())', - ' };', - ' list = new List.from(list);', // Clone the list. - ' var compare = compareFuncs[type];', - ' list.sort(compare);', - ' return list;', - '}']); - return [sortFunctionName + '(' + list + ', ' + - '"' + type + '", ' + direction + ')', - Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; - -Blockly.Dart['lists_split'] = function(block) { - // Block for splitting text into a list, or joining a list into text. - var input = Blockly.Dart.valueToCode(block, 'INPUT', - Blockly.Dart.ORDER_UNARY_POSTFIX); - var delimiter = Blockly.Dart.valueToCode(block, 'DELIM', - Blockly.Dart.ORDER_NONE) || '\'\''; - var mode = block.getFieldValue('MODE'); - if (mode == 'SPLIT') { - if (!input) { - input = '\'\''; - } - var functionName = 'split'; - } else if (mode == 'JOIN') { - if (!input) { - input = '[]'; - } - var functionName = 'join'; - } else { - throw 'Unknown mode: ' + mode; - } - var code = input + '.' + functionName + '(' + delimiter + ')'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/dart/logic.js b/backend/_pv_1_3_5/static/blockly/generators/dart/logic.js deleted file mode 100755 index 13f4e0a36..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/dart/logic.js +++ /dev/null @@ -1,125 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2014 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Dart for logic blocks. - * @author q.neutron@gmail.com (Quynh Neutron) - */ -'use strict'; - -goog.provide('Blockly.Dart.logic'); - -goog.require('Blockly.Dart'); - - -Blockly.Dart['controls_if'] = function(block) { - // If/elseif/else condition. - var n = 0; - var argument = Blockly.Dart.valueToCode(block, 'IF' + n, - Blockly.Dart.ORDER_NONE) || 'false'; - var branch = Blockly.Dart.statementToCode(block, 'DO' + n); - var code = 'if (' + argument + ') {\n' + branch + '}'; - for (n = 1; n <= block.elseifCount_; n++) { - argument = Blockly.Dart.valueToCode(block, 'IF' + n, - Blockly.Dart.ORDER_NONE) || 'false'; - branch = Blockly.Dart.statementToCode(block, 'DO' + n); - code += ' else if (' + argument + ') {\n' + branch + '}'; - } - if (block.elseCount_) { - branch = Blockly.Dart.statementToCode(block, 'ELSE'); - code += ' else {\n' + branch + '}'; - } - return code + '\n'; -}; - -Blockly.Dart['logic_compare'] = function(block) { - // Comparison operator. - var OPERATORS = { - 'EQ': '==', - 'NEQ': '!=', - 'LT': '<', - 'LTE': '<=', - 'GT': '>', - 'GTE': '>=' - }; - var operator = OPERATORS[block.getFieldValue('OP')]; - var order = (operator == '==' || operator == '!=') ? - Blockly.Dart.ORDER_EQUALITY : Blockly.Dart.ORDER_RELATIONAL; - var argument0 = Blockly.Dart.valueToCode(block, 'A', order) || '0'; - var argument1 = Blockly.Dart.valueToCode(block, 'B', order) || '0'; - var code = argument0 + ' ' + operator + ' ' + argument1; - return [code, order]; -}; - -Blockly.Dart['logic_operation'] = function(block) { - // Operations 'and', 'or'. - var operator = (block.getFieldValue('OP') == 'AND') ? '&&' : '||'; - var order = (operator == '&&') ? Blockly.Dart.ORDER_LOGICAL_AND : - Blockly.Dart.ORDER_LOGICAL_OR; - var argument0 = Blockly.Dart.valueToCode(block, 'A', order); - var argument1 = Blockly.Dart.valueToCode(block, 'B', order); - if (!argument0 && !argument1) { - // If there are no arguments, then the return value is false. - argument0 = 'false'; - argument1 = 'false'; - } else { - // Single missing arguments have no effect on the return value. - var defaultArgument = (operator == '&&') ? 'true' : 'false'; - if (!argument0) { - argument0 = defaultArgument; - } - if (!argument1) { - argument1 = defaultArgument; - } - } - var code = argument0 + ' ' + operator + ' ' + argument1; - return [code, order]; -}; - -Blockly.Dart['logic_negate'] = function(block) { - // Negation. - var order = Blockly.Dart.ORDER_UNARY_PREFIX; - var argument0 = Blockly.Dart.valueToCode(block, 'BOOL', order) || 'true'; - var code = '!' + argument0; - return [code, order]; -}; - -Blockly.Dart['logic_boolean'] = function(block) { - // Boolean values true and false. - var code = (block.getFieldValue('BOOL') == 'TRUE') ? 'true' : 'false'; - return [code, Blockly.Dart.ORDER_ATOMIC]; -}; - -Blockly.Dart['logic_null'] = function(block) { - // Null data type. - return ['null', Blockly.Dart.ORDER_ATOMIC]; -}; - -Blockly.Dart['logic_ternary'] = function(block) { - // Ternary operator. - var value_if = Blockly.Dart.valueToCode(block, 'IF', - Blockly.Dart.ORDER_CONDITIONAL) || 'false'; - var value_then = Blockly.Dart.valueToCode(block, 'THEN', - Blockly.Dart.ORDER_CONDITIONAL) || 'null'; - var value_else = Blockly.Dart.valueToCode(block, 'ELSE', - Blockly.Dart.ORDER_CONDITIONAL) || 'null'; - var code = value_if + ' ? ' + value_then + ' : ' + value_else; - return [code, Blockly.Dart.ORDER_CONDITIONAL]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/dart/loops.js b/backend/_pv_1_3_5/static/blockly/generators/dart/loops.js deleted file mode 100755 index 0dd7c0ce5..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/dart/loops.js +++ /dev/null @@ -1,163 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2014 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Dart for loop blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Dart.loops'); - -goog.require('Blockly.Dart'); - - -Blockly.Dart['controls_repeat_ext'] = function(block) { - // Repeat n times. - if (block.getField('TIMES')) { - // Internal number. - var repeats = String(Number(block.getFieldValue('TIMES'))); - } else { - // External number. - var repeats = Blockly.Dart.valueToCode(block, 'TIMES', - Blockly.Dart.ORDER_ASSIGNMENT) || '0'; - } - var branch = Blockly.Dart.statementToCode(block, 'DO'); - branch = Blockly.Dart.addLoopTrap(branch, block.id); - var code = ''; - var loopVar = Blockly.Dart.variableDB_.getDistinctName( - 'count', Blockly.Variables.NAME_TYPE); - var endVar = repeats; - if (!repeats.match(/^\w+$/) && !Blockly.isNumber(repeats)) { - var endVar = Blockly.Dart.variableDB_.getDistinctName( - 'repeat_end', Blockly.Variables.NAME_TYPE); - code += 'var ' + endVar + ' = ' + repeats + ';\n'; - } - code += 'for (int ' + loopVar + ' = 0; ' + - loopVar + ' < ' + endVar + '; ' + - loopVar + '++) {\n' + - branch + '}\n'; - return code; -}; - -Blockly.Dart['controls_repeat'] = Blockly.Dart['controls_repeat_ext']; - -Blockly.Dart['controls_whileUntil'] = function(block) { - // Do while/until loop. - var until = block.getFieldValue('MODE') == 'UNTIL'; - var argument0 = Blockly.Dart.valueToCode(block, 'BOOL', - until ? Blockly.Dart.ORDER_UNARY_PREFIX : - Blockly.Dart.ORDER_NONE) || 'false'; - var branch = Blockly.Dart.statementToCode(block, 'DO'); - branch = Blockly.Dart.addLoopTrap(branch, block.id); - if (until) { - argument0 = '!' + argument0; - } - return 'while (' + argument0 + ') {\n' + branch + '}\n'; -}; - -Blockly.Dart['controls_for'] = function(block) { - // For loop. - var variable0 = Blockly.Dart.variableDB_.getName( - block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); - var argument0 = Blockly.Dart.valueToCode(block, 'FROM', - Blockly.Dart.ORDER_ASSIGNMENT) || '0'; - var argument1 = Blockly.Dart.valueToCode(block, 'TO', - Blockly.Dart.ORDER_ASSIGNMENT) || '0'; - var increment = Blockly.Dart.valueToCode(block, 'BY', - Blockly.Dart.ORDER_ASSIGNMENT) || '1'; - var branch = Blockly.Dart.statementToCode(block, 'DO'); - branch = Blockly.Dart.addLoopTrap(branch, block.id); - var code; - if (Blockly.isNumber(argument0) && Blockly.isNumber(argument1) && - Blockly.isNumber(increment)) { - // All arguments are simple numbers. - var up = parseFloat(argument0) <= parseFloat(argument1); - code = 'for (' + variable0 + ' = ' + argument0 + '; ' + - variable0 + (up ? ' <= ' : ' >= ') + argument1 + '; ' + - variable0; - var step = Math.abs(parseFloat(increment)); - if (step == 1) { - code += up ? '++' : '--'; - } else { - code += (up ? ' += ' : ' -= ') + step; - } - code += ') {\n' + branch + '}\n'; - } else { - code = ''; - // Cache non-trivial values to variables to prevent repeated look-ups. - var startVar = argument0; - if (!argument0.match(/^\w+$/) && !Blockly.isNumber(argument0)) { - var startVar = Blockly.Dart.variableDB_.getDistinctName( - variable0 + '_start', Blockly.Variables.NAME_TYPE); - code += 'var ' + startVar + ' = ' + argument0 + ';\n'; - } - var endVar = argument1; - if (!argument1.match(/^\w+$/) && !Blockly.isNumber(argument1)) { - var endVar = Blockly.Dart.variableDB_.getDistinctName( - variable0 + '_end', Blockly.Variables.NAME_TYPE); - code += 'var ' + endVar + ' = ' + argument1 + ';\n'; - } - // Determine loop direction at start, in case one of the bounds - // changes during loop execution. - var incVar = Blockly.Dart.variableDB_.getDistinctName( - variable0 + '_inc', Blockly.Variables.NAME_TYPE); - code += 'num ' + incVar + ' = '; - if (Blockly.isNumber(increment)) { - code += Math.abs(increment) + ';\n'; - } else { - code += '(' + increment + ').abs();\n'; - } - code += 'if (' + startVar + ' > ' + endVar + ') {\n'; - code += Blockly.Dart.INDENT + incVar + ' = -' + incVar + ';\n'; - code += '}\n'; - code += 'for (' + variable0 + ' = ' + startVar + '; ' + - incVar + ' >= 0 ? ' + - variable0 + ' <= ' + endVar + ' : ' + - variable0 + ' >= ' + endVar + '; ' + - variable0 + ' += ' + incVar + ') {\n' + - branch + '}\n'; - } - return code; -}; - -Blockly.Dart['controls_forEach'] = function(block) { - // For each loop. - var variable0 = Blockly.Dart.variableDB_.getName( - block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); - var argument0 = Blockly.Dart.valueToCode(block, 'LIST', - Blockly.Dart.ORDER_ASSIGNMENT) || '[]'; - var branch = Blockly.Dart.statementToCode(block, 'DO'); - branch = Blockly.Dart.addLoopTrap(branch, block.id); - var code = 'for (var ' + variable0 + ' in ' + argument0 + ') {\n' + - branch + '}\n'; - return code; -}; - -Blockly.Dart['controls_flow_statements'] = function(block) { - // Flow statements: continue, break. - switch (block.getFieldValue('FLOW')) { - case 'BREAK': - return 'break;\n'; - case 'CONTINUE': - return 'continue;\n'; - } - throw 'Unknown flow statement.'; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/dart/math.js b/backend/_pv_1_3_5/static/blockly/generators/dart/math.js deleted file mode 100755 index 867822beb..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/dart/math.js +++ /dev/null @@ -1,487 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2014 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Dart for math blocks. - * @author q.neutron@gmail.com (Quynh Neutron) - */ -'use strict'; - -goog.provide('Blockly.Dart.math'); - -goog.require('Blockly.Dart'); - - -Blockly.Dart.addReservedWords('Math'); - -Blockly.Dart['math_number'] = function(block) { - // Numeric value. - var code = parseFloat(block.getFieldValue('NUM')); - var order; - if (code == Infinity) { - code = 'double.INFINITY'; - order = Blockly.Dart.ORDER_UNARY_POSTFIX; - } else if (code == -Infinity) { - code = '-double.INFINITY'; - order = Blockly.Dart.ORDER_UNARY_PREFIX; - } else { - // -4.abs() returns -4 in Dart due to strange order of operation choices. - // -4 is actually an operator and a number. Reflect this in the order. - order = code < 0 ? - Blockly.Dart.ORDER_UNARY_PREFIX : Blockly.Dart.ORDER_ATOMIC; - } - return [code, order]; -}; - -Blockly.Dart['math_arithmetic'] = function(block) { - // Basic arithmetic operators, and power. - var OPERATORS = { - 'ADD': [' + ', Blockly.Dart.ORDER_ADDITIVE], - 'MINUS': [' - ', Blockly.Dart.ORDER_ADDITIVE], - 'MULTIPLY': [' * ', Blockly.Dart.ORDER_MULTIPLICATIVE], - 'DIVIDE': [' / ', Blockly.Dart.ORDER_MULTIPLICATIVE], - 'POWER': [null, Blockly.Dart.ORDER_NONE] // Handle power separately. - }; - var tuple = OPERATORS[block.getFieldValue('OP')]; - var operator = tuple[0]; - var order = tuple[1]; - var argument0 = Blockly.Dart.valueToCode(block, 'A', order) || '0'; - var argument1 = Blockly.Dart.valueToCode(block, 'B', order) || '0'; - var code; - // Power in Dart requires a special case since it has no operator. - if (!operator) { - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - code = 'Math.pow(' + argument0 + ', ' + argument1 + ')'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - } - code = argument0 + operator + argument1; - return [code, order]; -}; - -Blockly.Dart['math_single'] = function(block) { - // Math operators with single operand. - var operator = block.getFieldValue('OP'); - var code; - var arg; - if (operator == 'NEG') { - // Negation is a special case given its different operator precedence. - arg = Blockly.Dart.valueToCode(block, 'NUM', - Blockly.Dart.ORDER_UNARY_PREFIX) || '0'; - if (arg[0] == '-') { - // --3 is not legal in Dart. - arg = ' ' + arg; - } - code = '-' + arg; - return [code, Blockly.Dart.ORDER_UNARY_PREFIX]; - } - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - if (operator == 'ABS' || operator.substring(0, 5) == 'ROUND') { - arg = Blockly.Dart.valueToCode(block, 'NUM', - Blockly.Dart.ORDER_UNARY_POSTFIX) || '0'; - } else if (operator == 'SIN' || operator == 'COS' || operator == 'TAN') { - arg = Blockly.Dart.valueToCode(block, 'NUM', - Blockly.Dart.ORDER_MULTIPLICATIVE) || '0'; - } else { - arg = Blockly.Dart.valueToCode(block, 'NUM', - Blockly.Dart.ORDER_NONE) || '0'; - } - // First, handle cases which generate values that don't need parentheses - // wrapping the code. - switch (operator) { - case 'ABS': - code = arg + '.abs()'; - break; - case 'ROOT': - code = 'Math.sqrt(' + arg + ')'; - break; - case 'LN': - code = 'Math.log(' + arg + ')'; - break; - case 'EXP': - code = 'Math.exp(' + arg + ')'; - break; - case 'POW10': - code = 'Math.pow(10,' + arg + ')'; - break; - case 'ROUND': - code = arg + '.round()'; - break; - case 'ROUNDUP': - code = arg + '.ceil()'; - break; - case 'ROUNDDOWN': - code = arg + '.floor()'; - break; - case 'SIN': - code = 'Math.sin(' + arg + ' / 180 * Math.PI)'; - break; - case 'COS': - code = 'Math.cos(' + arg + ' / 180 * Math.PI)'; - break; - case 'TAN': - code = 'Math.tan(' + arg + ' / 180 * Math.PI)'; - break; - } - if (code) { - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - } - // Second, handle cases which generate values that may need parentheses - // wrapping the code. - switch (operator) { - case 'LOG10': - code = 'Math.log(' + arg + ') / Math.log(10)'; - break; - case 'ASIN': - code = 'Math.asin(' + arg + ') / Math.PI * 180'; - break; - case 'ACOS': - code = 'Math.acos(' + arg + ') / Math.PI * 180'; - break; - case 'ATAN': - code = 'Math.atan(' + arg + ') / Math.PI * 180'; - break; - default: - throw 'Unknown math operator: ' + operator; - } - return [code, Blockly.Dart.ORDER_MULTIPLICATIVE]; -}; - -Blockly.Dart['math_constant'] = function(block) { - // Constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY. - var CONSTANTS = { - 'PI': ['Math.PI', Blockly.Dart.ORDER_UNARY_POSTFIX], - 'E': ['Math.E', Blockly.Dart.ORDER_UNARY_POSTFIX], - 'GOLDEN_RATIO': - ['(1 + Math.sqrt(5)) / 2', Blockly.Dart.ORDER_MULTIPLICATIVE], - 'SQRT2': ['Math.SQRT2', Blockly.Dart.ORDER_UNARY_POSTFIX], - 'SQRT1_2': ['Math.SQRT1_2', Blockly.Dart.ORDER_UNARY_POSTFIX], - 'INFINITY': ['double.INFINITY', Blockly.Dart.ORDER_ATOMIC] - }; - var constant = block.getFieldValue('CONSTANT'); - if (constant != 'INFINITY') { - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - } - return CONSTANTS[constant]; -}; - -Blockly.Dart['math_number_property'] = function(block) { - // Check if a number is even, odd, prime, whole, positive, or negative - // or if it is divisible by certain number. Returns true or false. - var number_to_check = Blockly.Dart.valueToCode(block, 'NUMBER_TO_CHECK', - Blockly.Dart.ORDER_MULTIPLICATIVE); - if (!number_to_check) { - return ['false', Blockly.Python.ORDER_ATOMIC]; - } - var dropdown_property = block.getFieldValue('PROPERTY'); - var code; - if (dropdown_property == 'PRIME') { - // Prime is a special case as it is not a one-liner test. - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - var functionName = Blockly.Dart.provideFunction_( - 'math_isPrime', - ['bool ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + '(n) {', - ' // https://en.wikipedia.org/wiki/Primality_test#Naive_methods', - ' if (n == 2 || n == 3) {', - ' return true;', - ' }', - ' // False if n is null, negative, is 1, or not whole.', - ' // And false if n is divisible by 2 or 3.', - ' if (n == null || n <= 1 || n % 1 != 0 || n % 2 == 0 ||' + - ' n % 3 == 0) {', - ' return false;', - ' }', - ' // Check all the numbers of form 6k +/- 1, up to sqrt(n).', - ' for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {', - ' if (n % (x - 1) == 0 || n % (x + 1) == 0) {', - ' return false;', - ' }', - ' }', - ' return true;', - '}']); - code = functionName + '(' + number_to_check + ')'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - } - switch (dropdown_property) { - case 'EVEN': - code = number_to_check + ' % 2 == 0'; - break; - case 'ODD': - code = number_to_check + ' % 2 == 1'; - break; - case 'WHOLE': - code = number_to_check + ' % 1 == 0'; - break; - case 'POSITIVE': - code = number_to_check + ' > 0'; - break; - case 'NEGATIVE': - code = number_to_check + ' < 0'; - break; - case 'DIVISIBLE_BY': - var divisor = Blockly.Dart.valueToCode(block, 'DIVISOR', - Blockly.Dart.ORDER_MULTIPLICATIVE); - if (!divisor) { - return ['false', Blockly.Python.ORDER_ATOMIC]; - } - code = number_to_check + ' % ' + divisor + ' == 0'; - break; - } - return [code, Blockly.Dart.ORDER_EQUALITY]; -}; - -Blockly.Dart['math_change'] = function(block) { - // Add to a variable in place. - var argument0 = Blockly.Dart.valueToCode(block, 'DELTA', - Blockly.Dart.ORDER_ADDITIVE) || '0'; - var varName = Blockly.Dart.variableDB_.getName(block.getFieldValue('VAR'), - Blockly.Variables.NAME_TYPE); - return varName + ' = (' + varName + ' is num ? ' + varName + ' : 0) + ' + - argument0 + ';\n'; -}; - -// Rounding functions have a single operand. -Blockly.Dart['math_round'] = Blockly.Dart['math_single']; -// Trigonometry functions have a single operand. -Blockly.Dart['math_trig'] = Blockly.Dart['math_single']; - -Blockly.Dart['math_on_list'] = function(block) { - // Math functions for lists. - var func = block.getFieldValue('OP'); - var list = Blockly.Dart.valueToCode(block, 'LIST', - Blockly.Dart.ORDER_NONE) || '[]'; - var code; - switch (func) { - case 'SUM': - var functionName = Blockly.Dart.provideFunction_( - 'math_sum', - ['num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(List myList) {', - ' num sumVal = 0;', - ' myList.forEach((num entry) {sumVal += entry;});', - ' return sumVal;', - '}']); - code = functionName + '(' + list + ')'; - break; - case 'MIN': - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - var functionName = Blockly.Dart.provideFunction_( - 'math_min', - ['num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(List myList) {', - ' if (myList.isEmpty) return null;', - ' num minVal = myList[0];', - ' myList.forEach((num entry) ' + - '{minVal = Math.min(minVal, entry);});', - ' return minVal;', - '}']); - code = functionName + '(' + list + ')'; - break; - case 'MAX': - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - var functionName = Blockly.Dart.provideFunction_( - 'math_max', - ['num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(List myList) {', - ' if (myList.isEmpty) return null;', - ' num maxVal = myList[0];', - ' myList.forEach((num entry) ' + - '{maxVal = Math.max(maxVal, entry);});', - ' return maxVal;', - '}']); - code = functionName + '(' + list + ')'; - break; - case 'AVERAGE': - // This operation exclude null and values that are not int or float: - // math_mean([null,null,"aString",1,9]) == 5.0. - var functionName = Blockly.Dart.provideFunction_( - 'math_mean', - ['num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(List myList) {', - ' // First filter list for numbers only.', - ' List localList = new List.from(myList);', - ' localList.removeWhere((a) => a is! num);', - ' if (localList.isEmpty) return null;', - ' num sumVal = 0;', - ' localList.forEach((num entry) {sumVal += entry;});', - ' return sumVal / localList.length;', - '}']); - code = functionName + '(' + list + ')'; - break; - case 'MEDIAN': - var functionName = Blockly.Dart.provideFunction_( - 'math_median', - ['num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(List myList) {', - ' // First filter list for numbers only, then sort, ' + - 'then return middle value', - ' // or the average of two middle values if list has an ' + - 'even number of elements.', - ' List localList = new List.from(myList);', - ' localList.removeWhere((a) => a is! num);', - ' if (localList.isEmpty) return null;', - ' localList.sort((a, b) => (a - b));', - ' int index = localList.length ~/ 2;', - ' if (localList.length % 2 == 1) {', - ' return localList[index];', - ' } else {', - ' return (localList[index - 1] + localList[index]) / 2;', - ' }', - '}']); - code = functionName + '(' + list + ')'; - break; - case 'MODE': - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - // As a list of numbers can contain more than one mode, - // the returned result is provided as an array. - // Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1]. - var functionName = Blockly.Dart.provideFunction_( - 'math_modes', - ['List ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(List values) {', - ' List modes = [];', - ' List counts = [];', - ' int maxCount = 0;', - ' for (int i = 0; i < values.length; i++) {', - ' var value = values[i];', - ' bool found = false;', - ' int thisCount;', - ' for (int j = 0; j < counts.length; j++) {', - ' if (counts[j][0] == value) {', - ' thisCount = ++counts[j][1];', - ' found = true;', - ' break;', - ' }', - ' }', - ' if (!found) {', - ' counts.add([value, 1]);', - ' thisCount = 1;', - ' }', - ' maxCount = Math.max(thisCount, maxCount);', - ' }', - ' for (int j = 0; j < counts.length; j++) {', - ' if (counts[j][1] == maxCount) {', - ' modes.add(counts[j][0]);', - ' }', - ' }', - ' return modes;', - '}']); - code = functionName + '(' + list + ')'; - break; - case 'STD_DEV': - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - var functionName = Blockly.Dart.provideFunction_( - 'math_standard_deviation', - ['num ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(List myList) {', - ' // First filter list for numbers only.', - ' List numbers = new List.from(myList);', - ' numbers.removeWhere((a) => a is! num);', - ' if (numbers.isEmpty) return null;', - ' num n = numbers.length;', - ' num sum = 0;', - ' numbers.forEach((x) => sum += x);', - ' num mean = sum / n;', - ' num sumSquare = 0;', - ' numbers.forEach((x) => sumSquare += ' + - 'Math.pow(x - mean, 2));', - ' return Math.sqrt(sumSquare / n);', - '}']); - code = functionName + '(' + list + ')'; - break; - case 'RANDOM': - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - var functionName = Blockly.Dart.provideFunction_( - 'math_random_item', - ['dynamic ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(List myList) {', - ' int x = new Math.Random().nextInt(myList.length);', - ' return myList[x];', - '}']); - code = functionName + '(' + list + ')'; - break; - default: - throw 'Unknown operator: ' + func; - } - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; - -Blockly.Dart['math_modulo'] = function(block) { - // Remainder computation. - var argument0 = Blockly.Dart.valueToCode(block, 'DIVIDEND', - Blockly.Dart.ORDER_MULTIPLICATIVE) || '0'; - var argument1 = Blockly.Dart.valueToCode(block, 'DIVISOR', - Blockly.Dart.ORDER_MULTIPLICATIVE) || '0'; - var code = argument0 + ' % ' + argument1; - return [code, Blockly.Dart.ORDER_MULTIPLICATIVE]; -}; - -Blockly.Dart['math_constrain'] = function(block) { - // Constrain a number between two limits. - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - var argument0 = Blockly.Dart.valueToCode(block, 'VALUE', - Blockly.Dart.ORDER_NONE) || '0'; - var argument1 = Blockly.Dart.valueToCode(block, 'LOW', - Blockly.Dart.ORDER_NONE) || '0'; - var argument2 = Blockly.Dart.valueToCode(block, 'HIGH', - Blockly.Dart.ORDER_NONE) || 'double.INFINITY'; - var code = 'Math.min(Math.max(' + argument0 + ', ' + argument1 + '), ' + - argument2 + ')'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; - -Blockly.Dart['math_random_int'] = function(block) { - // Random integer between [X] and [Y]. - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - var argument0 = Blockly.Dart.valueToCode(block, 'FROM', - Blockly.Dart.ORDER_NONE) || '0'; - var argument1 = Blockly.Dart.valueToCode(block, 'TO', - Blockly.Dart.ORDER_NONE) || '0'; - var functionName = Blockly.Dart.provideFunction_( - 'math_random_int', - ['int ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + '(num a, num b) {', - ' if (a > b) {', - ' // Swap a and b to ensure a is smaller.', - ' num c = a;', - ' a = b;', - ' b = c;', - ' }', - ' return new Math.Random().nextInt(b - a + 1) + a;', - '}']); - var code = functionName + '(' + argument0 + ', ' + argument1 + ')'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; - -Blockly.Dart['math_random_float'] = function(block) { - // Random fraction between 0 and 1. - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - return ['new Math.Random().nextDouble()', Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/dart/procedures.js b/backend/_pv_1_3_5/static/blockly/generators/dart/procedures.js deleted file mode 100755 index ad2550cc7..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/dart/procedures.js +++ /dev/null @@ -1,109 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2014 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Dart for procedure blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Dart.procedures'); - -goog.require('Blockly.Dart'); - - -Blockly.Dart['procedures_defreturn'] = function(block) { - // Define a procedure with a return value. - var funcName = Blockly.Dart.variableDB_.getName(block.getFieldValue('NAME'), - Blockly.Procedures.NAME_TYPE); - var branch = Blockly.Dart.statementToCode(block, 'STACK'); - if (Blockly.Dart.STATEMENT_PREFIX) { - branch = Blockly.Dart.prefixLines( - Blockly.Dart.STATEMENT_PREFIX.replace(/%1/g, - '\'' + block.id + '\''), Blockly.Dart.INDENT) + branch; - } - if (Blockly.Dart.INFINITE_LOOP_TRAP) { - branch = Blockly.Dart.INFINITE_LOOP_TRAP.replace(/%1/g, - '\'' + block.id + '\'') + branch; - } - var returnValue = Blockly.Dart.valueToCode(block, 'RETURN', - Blockly.Dart.ORDER_NONE) || ''; - if (returnValue) { - returnValue = ' return ' + returnValue + ';\n'; - } - var returnType = returnValue ? 'dynamic' : 'void'; - var args = []; - for (var i = 0; i < block.arguments_.length; i++) { - args[i] = Blockly.Dart.variableDB_.getName(block.arguments_[i], - Blockly.Variables.NAME_TYPE); - } - var code = returnType + ' ' + funcName + '(' + args.join(', ') + ') {\n' + - branch + returnValue + '}'; - code = Blockly.Dart.scrub_(block, code); - // Add % so as not to collide with helper functions in definitions list. - Blockly.Dart.definitions_['%' + funcName] = code; - return null; -}; - -// Defining a procedure without a return value uses the same generator as -// a procedure with a return value. -Blockly.Dart['procedures_defnoreturn'] = Blockly.Dart['procedures_defreturn']; - -Blockly.Dart['procedures_callreturn'] = function(block) { - // Call a procedure with a return value. - var funcName = Blockly.Dart.variableDB_.getName(block.getFieldValue('NAME'), - Blockly.Procedures.NAME_TYPE); - var args = []; - for (var i = 0; i < block.arguments_.length; i++) { - args[i] = Blockly.Dart.valueToCode(block, 'ARG' + i, - Blockly.Dart.ORDER_NONE) || 'null'; - } - var code = funcName + '(' + args.join(', ') + ')'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; - -Blockly.Dart['procedures_callnoreturn'] = function(block) { - // Call a procedure with no return value. - var funcName = Blockly.Dart.variableDB_.getName(block.getFieldValue('NAME'), - Blockly.Procedures.NAME_TYPE); - var args = []; - for (var i = 0; i < block.arguments_.length; i++) { - args[i] = Blockly.Dart.valueToCode(block, 'ARG' + i, - Blockly.Dart.ORDER_NONE) || 'null'; - } - var code = funcName + '(' + args.join(', ') + ');\n'; - return code; -}; - -Blockly.Dart['procedures_ifreturn'] = function(block) { - // Conditionally return value from a procedure. - var condition = Blockly.Dart.valueToCode(block, 'CONDITION', - Blockly.Dart.ORDER_NONE) || 'false'; - var code = 'if (' + condition + ') {\n'; - if (block.hasReturnValue_) { - var value = Blockly.Dart.valueToCode(block, 'VALUE', - Blockly.Dart.ORDER_NONE) || 'null'; - code += ' return ' + value + ';\n'; - } else { - code += ' return;\n'; - } - code += '}\n'; - return code; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/dart/text.js b/backend/_pv_1_3_5/static/blockly/generators/dart/text.js deleted file mode 100755 index 5cdbb03ec..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/dart/text.js +++ /dev/null @@ -1,297 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2014 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Dart for text blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Dart.texts'); - -goog.require('Blockly.Dart'); - - -Blockly.Dart.addReservedWords('Html,Math'); - -Blockly.Dart['text'] = function(block) { - // Text value. - var code = Blockly.Dart.quote_(block.getFieldValue('TEXT')); - return [code, Blockly.Dart.ORDER_ATOMIC]; -}; - -Blockly.Dart['text_join'] = function(block) { - // Create a string made up of any number of elements of any type. - switch (block.itemCount_) { - case 0: - return ['\'\'', Blockly.Dart.ORDER_ATOMIC]; - case 1: - var element = Blockly.Dart.valueToCode(block, 'ADD0', - Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\''; - var code = element + '.toString()'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - default: - var elements = new Array(block.itemCount_); - for (var i = 0; i < block.itemCount_; i++) { - elements[i] = Blockly.Dart.valueToCode(block, 'ADD' + i, - Blockly.Dart.ORDER_NONE) || '\'\''; - } - var code = '[' + elements.join(',') + '].join()'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - } -}; - -Blockly.Dart['text_append'] = function(block) { - // Append to a variable in place. - var varName = Blockly.Dart.variableDB_.getName(block.getFieldValue('VAR'), - Blockly.Variables.NAME_TYPE); - var value = Blockly.Dart.valueToCode(block, 'TEXT', - Blockly.Dart.ORDER_NONE) || '\'\''; - return varName + ' = [' + varName + ', ' + value + '].join();\n'; -}; - -Blockly.Dart['text_length'] = function(block) { - // String or array length. - var text = Blockly.Dart.valueToCode(block, 'VALUE', - Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\''; - return [text + '.length', Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; - -Blockly.Dart['text_isEmpty'] = function(block) { - // Is the string null or array empty? - var text = Blockly.Dart.valueToCode(block, 'VALUE', - Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\''; - return [text + '.isEmpty', Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; - -Blockly.Dart['text_indexOf'] = function(block) { - // Search the text for a substring. - var operator = block.getFieldValue('END') == 'FIRST' ? - 'indexOf' : 'lastIndexOf'; - var substring = Blockly.Dart.valueToCode(block, 'FIND', - Blockly.Dart.ORDER_NONE) || '\'\''; - var text = Blockly.Dart.valueToCode(block, 'VALUE', - Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\''; - var code = text + '.' + operator + '(' + substring + ')'; - if (Blockly.Dart.ONE_BASED_INDEXING) { - return [code + ' + 1', Blockly.Dart.ORDER_ADDITIVE]; - } - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; - -Blockly.Dart['text_charAt'] = function(block) { - // Get letter at index. - // Note: Until January 2013 this block did not have the WHERE input. - var where = block.getFieldValue('WHERE') || 'FROM_START'; - var text = Blockly.Dart.valueToCode(block, 'VALUE', - Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\''; - switch (where) { - case 'FIRST': - var code = text + '[0]'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - case 'FROM_START': - var at = Blockly.Dart.getAdjusted(block, 'AT'); - var code = text + '[' + at + ']'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - case 'LAST': - at = 1; - // Fall through. - case 'FROM_END': - var at = Blockly.Dart.getAdjusted(block, 'AT', 1); - var functionName = Blockly.Dart.provideFunction_( - 'text_get_from_end', - ['String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(String text, num x) {', - ' return text[text.length - x];', - '}']); - code = functionName + '(' + text + ', ' + at + ')'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - case 'RANDOM': - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - var functionName = Blockly.Dart.provideFunction_( - 'text_random_letter', - ['String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(String text) {', - ' int x = new Math.Random().nextInt(text.length);', - ' return text[x];', - '}']); - code = functionName + '(' + text + ')'; - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; - } - throw 'Unhandled option (text_charAt).'; -}; - -Blockly.Dart['text_getSubstring'] = function(block) { - // Get substring. - var text = Blockly.Dart.valueToCode(block, 'STRING', - Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\''; - var where1 = block.getFieldValue('WHERE1'); - var where2 = block.getFieldValue('WHERE2'); - if (where1 == 'FIRST' && where2 == 'LAST') { - var code = text; - } else if (text.match(/^'?\w+'?$/) || - (where1 != 'FROM_END' && where2 == 'FROM_START')) { - // If the text is a variable or literal or doesn't require a call for - // length, don't generate a helper function. - switch (where1) { - case 'FROM_START': - var at1 = Blockly.Dart.getAdjusted(block, 'AT1'); - break; - case 'FROM_END': - var at1 = Blockly.Dart.getAdjusted(block, 'AT1', 1, false, - Blockly.Dart.ORDER_ADDITIVE); - at1 = text + '.length - ' + at1; - break; - case 'FIRST': - var at1 = '0'; - break; - default: - throw 'Unhandled option (text_getSubstring).'; - } - switch (where2) { - case 'FROM_START': - var at2 = Blockly.Dart.getAdjusted(block, 'AT2', 1); - break; - case 'FROM_END': - var at2 = Blockly.Dart.getAdjusted(block, 'AT2', 0, false, - Blockly.Dart.ORDER_ADDITIVE); - at2 = text + '.length - ' + at2; - break; - case 'LAST': - break; - default: - throw 'Unhandled option (text_getSubstring).'; - } - if (where2 == 'LAST') { - var code = text + '.substring(' + at1 + ')'; - } else { - var code = text + '.substring(' + at1 + ', ' + at2 + ')'; - } - } else { - var at1 = Blockly.Dart.getAdjusted(block, 'AT1'); - var at2 = Blockly.Dart.getAdjusted(block, 'AT2'); - var functionName = Blockly.Dart.provideFunction_( - 'text_get_substring', - ['List ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(text, where1, at1, where2, at2) {', - ' int getAt(where, at) {', - ' if (where == \'FROM_END\') {', - ' at = text.length - 1 - at;', - ' } else if (where == \'FIRST\') {', - ' at = 0;', - ' } else if (where == \'LAST\') {', - ' at = text.length - 1;', - ' } else if (where != \'FROM_START\') {', - ' throw \'Unhandled option (text_getSubstring).\';', - ' }', - ' return at;', - ' }', - ' at1 = getAt(where1, at1);', - ' at2 = getAt(where2, at2) + 1;', - ' return text.substring(at1, at2);', - '}']); - var code = functionName + '(' + text + ', \'' + - where1 + '\', ' + at1 + ', \'' + where2 + '\', ' + at2 + ')'; - } - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; - -Blockly.Dart['text_changeCase'] = function(block) { - // Change capitalization. - var OPERATORS = { - 'UPPERCASE': '.toUpperCase()', - 'LOWERCASE': '.toLowerCase()', - 'TITLECASE': null - }; - var operator = OPERATORS[block.getFieldValue('CASE')]; - var textOrder = operator ? Blockly.Dart.ORDER_UNARY_POSTFIX : - Blockly.Dart.ORDER_NONE; - var text = Blockly.Dart.valueToCode(block, 'TEXT', textOrder) || '\'\''; - if (operator) { - // Upper and lower case are functions built into Dart. - var code = text + operator; - } else { - // Title case is not a native Dart function. Define one. - var functionName = Blockly.Dart.provideFunction_( - 'text_toTitleCase', - ['String ' + Blockly.Dart.FUNCTION_NAME_PLACEHOLDER_ + - '(String str) {', - ' RegExp exp = new RegExp(r\'\\b\');', - ' List list = str.split(exp);', - ' final title = new StringBuffer();', - ' for (String part in list) {', - ' if (part.length > 0) {', - ' title.write(part[0].toUpperCase());', - ' if (part.length > 0) {', - ' title.write(part.substring(1).toLowerCase());', - ' }', - ' }', - ' }', - ' return title.toString();', - '}']); - var code = functionName + '(' + text + ')'; - } - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; - -Blockly.Dart['text_trim'] = function(block) { - // Trim spaces. - var OPERATORS = { - 'LEFT': '.replaceFirst(new RegExp(r\'^\\s+\'), \'\')', - 'RIGHT': '.replaceFirst(new RegExp(r\'\\s+$\'), \'\')', - 'BOTH': '.trim()' - }; - var operator = OPERATORS[block.getFieldValue('MODE')]; - var text = Blockly.Dart.valueToCode(block, 'TEXT', - Blockly.Dart.ORDER_UNARY_POSTFIX) || '\'\''; - return [text + operator, Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; - -Blockly.Dart['text_print'] = function(block) { - // Print statement. - var msg = Blockly.Dart.valueToCode(block, 'TEXT', - Blockly.Dart.ORDER_NONE) || '\'\''; - return 'print(' + msg + ');\n'; -}; - -Blockly.Dart['text_prompt_ext'] = function(block) { - // Prompt function. - Blockly.Dart.definitions_['import_dart_html'] = - 'import \'dart:html\' as Html;'; - if (block.getField('TEXT')) { - // Internal message. - var msg = Blockly.Dart.quote_(block.getFieldValue('TEXT')); - } else { - // External message. - var msg = Blockly.Dart.valueToCode(block, 'TEXT', - Blockly.Dart.ORDER_NONE) || '\'\''; - } - var code = 'Html.window.prompt(' + msg + ', \'\')'; - var toNumber = block.getFieldValue('TYPE') == 'NUMBER'; - if (toNumber) { - Blockly.Dart.definitions_['import_dart_math'] = - 'import \'dart:math\' as Math;'; - code = 'Math.parseDouble(' + code + ')'; - } - return [code, Blockly.Dart.ORDER_UNARY_POSTFIX]; -}; - -Blockly.Dart['text_prompt'] = Blockly.Dart['text_prompt_ext']; diff --git a/backend/_pv_1_3_5/static/blockly/generators/dart/variables.js b/backend/_pv_1_3_5/static/blockly/generators/dart/variables.js deleted file mode 100755 index 446f7aa15..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/dart/variables.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2014 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Dart for variable blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Dart.variables'); - -goog.require('Blockly.Dart'); - - -Blockly.Dart['variables_get'] = function(block) { - // Variable getter. - var code = Blockly.Dart.variableDB_.getName(block.getFieldValue('VAR'), - Blockly.Variables.NAME_TYPE); - return [code, Blockly.Dart.ORDER_ATOMIC]; -}; - -Blockly.Dart['variables_set'] = function(block) { - // Variable setter. - var argument0 = Blockly.Dart.valueToCode(block, 'VALUE', - Blockly.Dart.ORDER_ASSIGNMENT) || '0'; - var varName = Blockly.Dart.variableDB_.getName(block.getFieldValue('VAR'), - Blockly.Variables.NAME_TYPE); - return varName + ' = ' + argument0 + ';\n'; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/javascript.js b/backend/_pv_1_3_5/static/blockly/generators/javascript.js deleted file mode 100755 index a1043abe8..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/javascript.js +++ /dev/null @@ -1,323 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Helper functions for generating JavaScript for blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.JavaScript'); - -goog.require('Blockly.Generator'); - - -/** - * JavaScript code generator. - * @type {!Blockly.Generator} - */ -Blockly.JavaScript = new Blockly.Generator('JavaScript'); - -/** - * List of illegal variable names. - * This is not intended to be a security feature. Blockly is 100% client-side, - * so bypassing this list is trivial. This is intended to prevent users from - * accidentally clobbering a built-in object or function. - * @private - */ -Blockly.JavaScript.addReservedWords( - 'Blockly,' + // In case JS is evaled in the current window. - // https://developer.mozilla.org/en/JavaScript/Reference/Reserved_Words - 'break,case,catch,continue,debugger,default,delete,do,else,finally,for,function,if,in,instanceof,new,return,switch,this,throw,try,typeof,var,void,while,with,' + - 'class,enum,export,extends,import,super,implements,interface,let,package,private,protected,public,static,yield,' + - 'const,null,true,false,' + - // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects - 'Array,ArrayBuffer,Boolean,Date,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Error,eval,EvalError,Float32Array,Float64Array,Function,Infinity,Int16Array,Int32Array,Int8Array,isFinite,isNaN,Iterator,JSON,Math,NaN,Number,Object,parseFloat,parseInt,RangeError,ReferenceError,RegExp,StopIteration,String,SyntaxError,TypeError,Uint16Array,Uint32Array,Uint8Array,Uint8ClampedArray,undefined,uneval,URIError,' + - // https://developer.mozilla.org/en/DOM/window - 'applicationCache,closed,Components,content,_content,controllers,crypto,defaultStatus,dialogArguments,directories,document,frameElement,frames,fullScreen,globalStorage,history,innerHeight,innerWidth,length,location,locationbar,localStorage,menubar,messageManager,mozAnimationStartTime,mozInnerScreenX,mozInnerScreenY,mozPaintCount,name,navigator,opener,outerHeight,outerWidth,pageXOffset,pageYOffset,parent,performance,personalbar,pkcs11,returnValue,screen,screenX,screenY,scrollbars,scrollMaxX,scrollMaxY,scrollX,scrollY,self,sessionStorage,sidebar,status,statusbar,toolbar,top,URL,window,' + - 'addEventListener,alert,atob,back,blur,btoa,captureEvents,clearImmediate,clearInterval,clearTimeout,close,confirm,disableExternalCapture,dispatchEvent,dump,enableExternalCapture,escape,find,focus,forward,GeckoActiveXObject,getAttention,getAttentionWithCycleCount,getComputedStyle,getSelection,home,matchMedia,maximize,minimize,moveBy,moveTo,mozRequestAnimationFrame,open,openDialog,postMessage,print,prompt,QueryInterface,releaseEvents,removeEventListener,resizeBy,resizeTo,restore,routeEvent,scroll,scrollBy,scrollByLines,scrollByPages,scrollTo,setCursor,setImmediate,setInterval,setResizable,setTimeout,showModalDialog,sizeToContent,stop,unescape,updateCommands,XPCNativeWrapper,XPCSafeJSObjectWrapper,' + - 'onabort,onbeforeunload,onblur,onchange,onclick,onclose,oncontextmenu,ondevicemotion,ondeviceorientation,ondragdrop,onerror,onfocus,onhashchange,onkeydown,onkeypress,onkeyup,onload,onmousedown,onmousemove,onmouseout,onmouseover,onmouseup,onmozbeforepaint,onpaint,onpopstate,onreset,onresize,onscroll,onselect,onsubmit,onunload,onpageshow,onpagehide,' + - 'Image,Option,Worker,' + - // https://developer.mozilla.org/en/Gecko_DOM_Reference - 'Event,Range,File,FileReader,Blob,BlobBuilder,' + - 'Attr,CDATASection,CharacterData,Comment,console,DocumentFragment,DocumentType,DomConfiguration,DOMError,DOMErrorHandler,DOMException,DOMImplementation,DOMImplementationList,DOMImplementationRegistry,DOMImplementationSource,DOMLocator,DOMObject,DOMString,DOMStringList,DOMTimeStamp,DOMUserData,Entity,EntityReference,MediaQueryList,MediaQueryListListener,NameList,NamedNodeMap,Node,NodeFilter,NodeIterator,NodeList,Notation,Plugin,PluginArray,ProcessingInstruction,SharedWorker,Text,TimeRanges,Treewalker,TypeInfo,UserDataHandler,Worker,WorkerGlobalScope,' + - 'HTMLDocument,HTMLElement,HTMLAnchorElement,HTMLAppletElement,HTMLAudioElement,HTMLAreaElement,HTMLBaseElement,HTMLBaseFontElement,HTMLBodyElement,HTMLBRElement,HTMLButtonElement,HTMLCanvasElement,HTMLDirectoryElement,HTMLDivElement,HTMLDListElement,HTMLEmbedElement,HTMLFieldSetElement,HTMLFontElement,HTMLFormElement,HTMLFrameElement,HTMLFrameSetElement,HTMLHeadElement,HTMLHeadingElement,HTMLHtmlElement,HTMLHRElement,HTMLIFrameElement,HTMLImageElement,HTMLInputElement,HTMLKeygenElement,HTMLLabelElement,HTMLLIElement,HTMLLinkElement,HTMLMapElement,HTMLMenuElement,HTMLMetaElement,HTMLModElement,HTMLObjectElement,HTMLOListElement,HTMLOptGroupElement,HTMLOptionElement,HTMLOutputElement,HTMLParagraphElement,HTMLParamElement,HTMLPreElement,HTMLQuoteElement,HTMLScriptElement,HTMLSelectElement,HTMLSourceElement,HTMLSpanElement,HTMLStyleElement,HTMLTableElement,HTMLTableCaptionElement,HTMLTableCellElement,HTMLTableDataCellElement,HTMLTableHeaderCellElement,HTMLTableColElement,HTMLTableRowElement,HTMLTableSectionElement,HTMLTextAreaElement,HTMLTimeElement,HTMLTitleElement,HTMLTrackElement,HTMLUListElement,HTMLUnknownElement,HTMLVideoElement,' + - 'HTMLCanvasElement,CanvasRenderingContext2D,CanvasGradient,CanvasPattern,TextMetrics,ImageData,CanvasPixelArray,HTMLAudioElement,HTMLVideoElement,NotifyAudioAvailableEvent,HTMLCollection,HTMLAllCollection,HTMLFormControlsCollection,HTMLOptionsCollection,HTMLPropertiesCollection,DOMTokenList,DOMSettableTokenList,DOMStringMap,RadioNodeList,' + - 'SVGDocument,SVGElement,SVGAElement,SVGAltGlyphElement,SVGAltGlyphDefElement,SVGAltGlyphItemElement,SVGAnimationElement,SVGAnimateElement,SVGAnimateColorElement,SVGAnimateMotionElement,SVGAnimateTransformElement,SVGSetElement,SVGCircleElement,SVGClipPathElement,SVGColorProfileElement,SVGCursorElement,SVGDefsElement,SVGDescElement,SVGEllipseElement,SVGFilterElement,SVGFilterPrimitiveStandardAttributes,SVGFEBlendElement,SVGFEColorMatrixElement,SVGFEComponentTransferElement,SVGFECompositeElement,SVGFEConvolveMatrixElement,SVGFEDiffuseLightingElement,SVGFEDisplacementMapElement,SVGFEDistantLightElement,SVGFEFloodElement,SVGFEGaussianBlurElement,SVGFEImageElement,SVGFEMergeElement,SVGFEMergeNodeElement,SVGFEMorphologyElement,SVGFEOffsetElement,SVGFEPointLightElement,SVGFESpecularLightingElement,SVGFESpotLightElement,SVGFETileElement,SVGFETurbulenceElement,SVGComponentTransferFunctionElement,SVGFEFuncRElement,SVGFEFuncGElement,SVGFEFuncBElement,SVGFEFuncAElement,SVGFontElement,SVGFontFaceElement,SVGFontFaceFormatElement,SVGFontFaceNameElement,SVGFontFaceSrcElement,SVGFontFaceUriElement,SVGForeignObjectElement,SVGGElement,SVGGlyphElement,SVGGlyphRefElement,SVGGradientElement,SVGLinearGradientElement,SVGRadialGradientElement,SVGHKernElement,SVGImageElement,SVGLineElement,SVGMarkerElement,SVGMaskElement,SVGMetadataElement,SVGMissingGlyphElement,SVGMPathElement,SVGPathElement,SVGPatternElement,SVGPolylineElement,SVGPolygonElement,SVGRectElement,SVGScriptElement,SVGStopElement,SVGStyleElement,SVGSVGElement,SVGSwitchElement,SVGSymbolElement,SVGTextElement,SVGTextPathElement,SVGTitleElement,SVGTRefElement,SVGTSpanElement,SVGUseElement,SVGViewElement,SVGVKernElement,' + - 'SVGAngle,SVGColor,SVGICCColor,SVGElementInstance,SVGElementInstanceList,SVGLength,SVGLengthList,SVGMatrix,SVGNumber,SVGNumberList,SVGPaint,SVGPoint,SVGPointList,SVGPreserveAspectRatio,SVGRect,SVGStringList,SVGTransform,SVGTransformList,' + - 'SVGAnimatedAngle,SVGAnimatedBoolean,SVGAnimatedEnumeration,SVGAnimatedInteger,SVGAnimatedLength,SVGAnimatedLengthList,SVGAnimatedNumber,SVGAnimatedNumberList,SVGAnimatedPreserveAspectRatio,SVGAnimatedRect,SVGAnimatedString,SVGAnimatedTransformList,' + - 'SVGPathSegList,SVGPathSeg,SVGPathSegArcAbs,SVGPathSegArcRel,SVGPathSegClosePath,SVGPathSegCurvetoCubicAbs,SVGPathSegCurvetoCubicRel,SVGPathSegCurvetoCubicSmoothAbs,SVGPathSegCurvetoCubicSmoothRel,SVGPathSegCurvetoQuadraticAbs,SVGPathSegCurvetoQuadraticRel,SVGPathSegCurvetoQuadraticSmoothAbs,SVGPathSegCurvetoQuadraticSmoothRel,SVGPathSegLinetoAbs,SVGPathSegLinetoHorizontalAbs,SVGPathSegLinetoHorizontalRel,SVGPathSegLinetoRel,SVGPathSegLinetoVerticalAbs,SVGPathSegLinetoVerticalRel,SVGPathSegMovetoAbs,SVGPathSegMovetoRel,ElementTimeControl,TimeEvent,SVGAnimatedPathData,' + - 'SVGAnimatedPoints,SVGColorProfileRule,SVGCSSRule,SVGExternalResourcesRequired,SVGFitToViewBox,SVGLangSpace,SVGLocatable,SVGRenderingIntent,SVGStylable,SVGTests,SVGTextContentElement,SVGTextPositioningElement,SVGTransformable,SVGUnitTypes,SVGURIReference,SVGViewSpec,SVGZoomAndPan'); - -/** - * Order of operation ENUMs. - * https://developer.mozilla.org/en/JavaScript/Reference/Operators/Operator_Precedence - */ -Blockly.JavaScript.ORDER_ATOMIC = 0; // 0 "" ... -Blockly.JavaScript.ORDER_NEW = 1.1; // new -Blockly.JavaScript.ORDER_MEMBER = 1.2; // . [] -Blockly.JavaScript.ORDER_FUNCTION_CALL = 2; // () -Blockly.JavaScript.ORDER_INCREMENT = 3; // ++ -Blockly.JavaScript.ORDER_DECREMENT = 3; // -- -Blockly.JavaScript.ORDER_BITWISE_NOT = 4.1; // ~ -Blockly.JavaScript.ORDER_UNARY_PLUS = 4.2; // + -Blockly.JavaScript.ORDER_UNARY_NEGATION = 4.3; // - -Blockly.JavaScript.ORDER_LOGICAL_NOT = 4.4; // ! -Blockly.JavaScript.ORDER_TYPEOF = 4.5; // typeof -Blockly.JavaScript.ORDER_VOID = 4.6; // void -Blockly.JavaScript.ORDER_DELETE = 4.7; // delete -Blockly.JavaScript.ORDER_DIVISION = 5.1; // / -Blockly.JavaScript.ORDER_MULTIPLICATION = 5.2; // * -Blockly.JavaScript.ORDER_MODULUS = 5.3; // % -Blockly.JavaScript.ORDER_SUBTRACTION = 6.1; // - -Blockly.JavaScript.ORDER_ADDITION = 6.2; // + -Blockly.JavaScript.ORDER_BITWISE_SHIFT = 7; // << >> >>> -Blockly.JavaScript.ORDER_RELATIONAL = 8; // < <= > >= -Blockly.JavaScript.ORDER_IN = 8; // in -Blockly.JavaScript.ORDER_INSTANCEOF = 8; // instanceof -Blockly.JavaScript.ORDER_EQUALITY = 9; // == != === !== -Blockly.JavaScript.ORDER_BITWISE_AND = 10; // & -Blockly.JavaScript.ORDER_BITWISE_XOR = 11; // ^ -Blockly.JavaScript.ORDER_BITWISE_OR = 12; // | -Blockly.JavaScript.ORDER_LOGICAL_AND = 13; // && -Blockly.JavaScript.ORDER_LOGICAL_OR = 14; // || -Blockly.JavaScript.ORDER_CONDITIONAL = 15; // ?: -Blockly.JavaScript.ORDER_ASSIGNMENT = 16; // = += -= *= /= %= <<= >>= ... -Blockly.JavaScript.ORDER_COMMA = 17; // , -Blockly.JavaScript.ORDER_NONE = 99; // (...) - -/** - * List of outer-inner pairings that do NOT require parentheses. - * @type {!Array.>} - */ -Blockly.JavaScript.ORDER_OVERRIDES = [ - // (foo()).bar -> foo().bar - // (foo())[0] -> foo()[0] - [Blockly.JavaScript.ORDER_FUNCTION_CALL, Blockly.JavaScript.ORDER_MEMBER], - // (foo())() -> foo()() - [Blockly.JavaScript.ORDER_FUNCTION_CALL, Blockly.JavaScript.ORDER_FUNCTION_CALL], - // (foo.bar).baz -> foo.bar.baz - // (foo.bar)[0] -> foo.bar[0] - // (foo[0]).bar -> foo[0].bar - // (foo[0])[1] -> foo[0][1] - [Blockly.JavaScript.ORDER_MEMBER, Blockly.JavaScript.ORDER_MEMBER], - // (foo.bar)() -> foo.bar() - // (foo[0])() -> foo[0]() - [Blockly.JavaScript.ORDER_MEMBER, Blockly.JavaScript.ORDER_FUNCTION_CALL], - - // !(!foo) -> !!foo - [Blockly.JavaScript.ORDER_LOGICAL_NOT, Blockly.JavaScript.ORDER_LOGICAL_NOT], - // a * (b * c) -> a * b * c - [Blockly.JavaScript.ORDER_MULTIPLICATION, Blockly.JavaScript.ORDER_MULTIPLICATION], - // a + (b + c) -> a + b + c - [Blockly.JavaScript.ORDER_ADDITION, Blockly.JavaScript.ORDER_ADDITION], - // a && (b && c) -> a && b && c - [Blockly.JavaScript.ORDER_LOGICAL_AND, Blockly.JavaScript.ORDER_LOGICAL_AND], - // a || (b || c) -> a || b || c - [Blockly.JavaScript.ORDER_LOGICAL_OR, Blockly.JavaScript.ORDER_LOGICAL_OR] -]; - -/** - * Allow for switching between one and zero based indexing for lists and text, - * one based by default. - */ -Blockly.JavaScript.ONE_BASED_INDEXING = true; - -/** - * Initialise the database of variable names. - * @param {!Blockly.Workspace} workspace Workspace to generate code from. - */ -Blockly.JavaScript.init = function(workspace) { - // Create a dictionary of definitions to be printed before the code. - Blockly.JavaScript.definitions_ = Object.create(null); - // Create a dictionary mapping desired function names in definitions_ - // to actual function names (to avoid collisions with user functions). - Blockly.JavaScript.functionNames_ = Object.create(null); - - if (!Blockly.JavaScript.variableDB_) { - Blockly.JavaScript.variableDB_ = - new Blockly.Names(Blockly.JavaScript.RESERVED_WORDS_); - } else { - Blockly.JavaScript.variableDB_.reset(); - } - - var defvars = []; - var variables = workspace.variableList; - if (variables.length) { - for (var i = 0; i < variables.length; i++) { - defvars[i] = Blockly.JavaScript.variableDB_.getName(variables[i], - Blockly.Variables.NAME_TYPE); - } - Blockly.JavaScript.definitions_['variables'] = - 'var ' + defvars.join(', ') + ';'; - } -}; - -/** - * Prepend the generated code with the variable definitions. - * @param {string} code Generated code. - * @return {string} Completed code. - */ -Blockly.JavaScript.finish = function(code) { - // Convert the definitions dictionary into a list. - var definitions = []; - for (var name in Blockly.JavaScript.definitions_) { - definitions.push(Blockly.JavaScript.definitions_[name]); - } - // Clean up temporary data. - delete Blockly.JavaScript.definitions_; - delete Blockly.JavaScript.functionNames_; - Blockly.JavaScript.variableDB_.reset(); - return definitions.join('\n\n') + '\n\n\n' + code; -}; - -/** - * Naked values are top-level blocks with outputs that aren't plugged into - * anything. A trailing semicolon is needed to make this legal. - * @param {string} line Line of generated code. - * @return {string} Legal line of code. - */ -Blockly.JavaScript.scrubNakedValue = function(line) { - return line + ';\n'; -}; - -/** - * Encode a string as a properly escaped JavaScript string, complete with - * quotes. - * @param {string} string Text to encode. - * @return {string} JavaScript string. - * @private - */ -Blockly.JavaScript.quote_ = function(string) { - // Can't use goog.string.quote since Google's style guide recommends - // JS string literals use single quotes. - string = string.replace(/\\/g, '\\\\') - .replace(/\n/g, '\\\n') - .replace(/'/g, '\\\''); - return '\'' + string + '\''; -}; - -/** - * Common tasks for generating JavaScript from blocks. - * Handles comments for the specified block and any connected value blocks. - * Calls any statements following this block. - * @param {!Blockly.Block} block The current block. - * @param {string} code The JavaScript code created for this block. - * @return {string} JavaScript code with comments and subsequent blocks added. - * @private - */ -Blockly.JavaScript.scrub_ = function(block, code) { - var commentCode = ''; - // Only collect comments for blocks that aren't inline. - if (!block.outputConnection || !block.outputConnection.targetConnection) { - // Collect comment for this block. - var comment = block.getCommentText(); - comment = Blockly.utils.wrap(comment, Blockly.JavaScript.COMMENT_WRAP - 3); - if (comment) { - if (block.getProcedureDef) { - // Use a comment block for function comments. - commentCode += '/**\n' + - Blockly.JavaScript.prefixLines(comment + '\n', ' * ') + - ' */\n'; - } else { - commentCode += Blockly.JavaScript.prefixLines(comment + '\n', '// '); - } - } - // Collect comments for all value arguments. - // Don't collect comments for nested statements. - for (var i = 0; i < block.inputList.length; i++) { - if (block.inputList[i].type == Blockly.INPUT_VALUE) { - var childBlock = block.inputList[i].connection.targetBlock(); - if (childBlock) { - var comment = Blockly.JavaScript.allNestedComments(childBlock); - if (comment) { - commentCode += Blockly.JavaScript.prefixLines(comment, '// '); - } - } - } - } - } - var nextBlock = block.nextConnection && block.nextConnection.targetBlock(); - var nextCode = Blockly.JavaScript.blockToCode(nextBlock); - return commentCode + code + nextCode; -}; - -/** - * Gets a property and adjusts the value while taking into account indexing. - * @param {!Blockly.Block} block The block. - * @param {string} atId The property ID of the element to get. - * @param {number=} opt_delta Value to add. - * @param {boolean=} opt_negate Whether to negate the value. - * @param {number=} opt_order The highest order acting on this value. - * @return {string|number} - */ -Blockly.JavaScript.getAdjusted = function(block, atId, opt_delta, opt_negate, - opt_order) { - var delta = opt_delta || 0; - var order = opt_order || Blockly.JavaScript.ORDER_NONE; - if (Blockly.JavaScript.ONE_BASED_INDEXING) { - delta--; - } - var defaultAtIndex = Blockly.JavaScript.ONE_BASED_INDEXING ? '1' : '0'; - if (delta > 0) { - var at = Blockly.JavaScript.valueToCode(block, atId, - Blockly.JavaScript.ORDER_ADDITION) || defaultAtIndex; - } else if (delta < 0) { - var at = Blockly.JavaScript.valueToCode(block, atId, - Blockly.JavaScript.ORDER_SUBTRACTION) || defaultAtIndex; - } else if (opt_negate) { - var at = Blockly.JavaScript.valueToCode(block, atId, - Blockly.JavaScript.ORDER_UNARY_NEGATION) || defaultAtIndex; - } else { - var at = Blockly.JavaScript.valueToCode(block, atId, order) || - defaultAtIndex; - } - - if (Blockly.isNumber(at)) { - // If the index is a naked number, adjust it right now. - at = parseFloat(at) + delta; - if (opt_negate) { - at = -at; - } - } else { - // If the index is dynamic, adjust it in code. - if (delta > 0) { - at = at + ' + ' + delta; - var innerOrder = Blockly.JavaScript.ORDER_ADDITION; - } else if (delta < 0) { - at = at + ' - ' + -delta; - var innerOrder = Blockly.JavaScript.ORDER_SUBTRACTION; - } - if (opt_negate) { - if (delta) { - at = '-(' + at + ')'; - } else { - at = '-' + at; - } - var innerOrder = Blockly.JavaScript.ORDER_UNARY_NEGATION; - } - innerOrder = Math.floor(innerOrder); - order = Math.floor(order); - if (innerOrder && order >= innerOrder) { - at = '(' + at + ')'; - } - } - return at; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/javascript/colour.js b/backend/_pv_1_3_5/static/blockly/generators/javascript/colour.js deleted file mode 100755 index 21b372e9c..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/javascript/colour.js +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating JavaScript for colour blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.JavaScript.colour'); - -goog.require('Blockly.JavaScript'); - - -Blockly.JavaScript['colour_picker'] = function(block) { - // Colour picker. - var code = '\'' + block.getFieldValue('COLOUR') + '\''; - return [code, Blockly.JavaScript.ORDER_ATOMIC]; -}; - -Blockly.JavaScript['colour_random'] = function(block) { - // Generate a random colour. - var functionName = Blockly.JavaScript.provideFunction_( - 'colourRandom', - ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + '() {', - ' var num = Math.floor(Math.random() * Math.pow(2, 24));', - ' return \'#\' + (\'00000\' + num.toString(16)).substr(-6);', - '}']); - var code = functionName + '()'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; -}; - -Blockly.JavaScript['colour_rgb'] = function(block) { - // Compose a colour from RGB components expressed as percentages. - var red = Blockly.JavaScript.valueToCode(block, 'RED', - Blockly.JavaScript.ORDER_COMMA) || 0; - var green = Blockly.JavaScript.valueToCode(block, 'GREEN', - Blockly.JavaScript.ORDER_COMMA) || 0; - var blue = Blockly.JavaScript.valueToCode(block, 'BLUE', - Blockly.JavaScript.ORDER_COMMA) || 0; - var functionName = Blockly.JavaScript.provideFunction_( - 'colourRgb', - ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + - '(r, g, b) {', - ' r = Math.max(Math.min(Number(r), 100), 0) * 2.55;', - ' g = Math.max(Math.min(Number(g), 100), 0) * 2.55;', - ' b = Math.max(Math.min(Number(b), 100), 0) * 2.55;', - ' r = (\'0\' + (Math.round(r) || 0).toString(16)).slice(-2);', - ' g = (\'0\' + (Math.round(g) || 0).toString(16)).slice(-2);', - ' b = (\'0\' + (Math.round(b) || 0).toString(16)).slice(-2);', - ' return \'#\' + r + g + b;', - '}']); - var code = functionName + '(' + red + ', ' + green + ', ' + blue + ')'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; -}; - -Blockly.JavaScript['colour_blend'] = function(block) { - // Blend two colours together. - var c1 = Blockly.JavaScript.valueToCode(block, 'COLOUR1', - Blockly.JavaScript.ORDER_COMMA) || '\'#000000\''; - var c2 = Blockly.JavaScript.valueToCode(block, 'COLOUR2', - Blockly.JavaScript.ORDER_COMMA) || '\'#000000\''; - var ratio = Blockly.JavaScript.valueToCode(block, 'RATIO', - Blockly.JavaScript.ORDER_COMMA) || 0.5; - var functionName = Blockly.JavaScript.provideFunction_( - 'colourBlend', - ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + - '(c1, c2, ratio) {', - ' ratio = Math.max(Math.min(Number(ratio), 1), 0);', - ' var r1 = parseInt(c1.substring(1, 3), 16);', - ' var g1 = parseInt(c1.substring(3, 5), 16);', - ' var b1 = parseInt(c1.substring(5, 7), 16);', - ' var r2 = parseInt(c2.substring(1, 3), 16);', - ' var g2 = parseInt(c2.substring(3, 5), 16);', - ' var b2 = parseInt(c2.substring(5, 7), 16);', - ' var r = Math.round(r1 * (1 - ratio) + r2 * ratio);', - ' var g = Math.round(g1 * (1 - ratio) + g2 * ratio);', - ' var b = Math.round(b1 * (1 - ratio) + b2 * ratio);', - ' r = (\'0\' + (r || 0).toString(16)).slice(-2);', - ' g = (\'0\' + (g || 0).toString(16)).slice(-2);', - ' b = (\'0\' + (b || 0).toString(16)).slice(-2);', - ' return \'#\' + r + g + b;', - '}']); - var code = functionName + '(' + c1 + ', ' + c2 + ', ' + ratio + ')'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/javascript/lists.js b/backend/_pv_1_3_5/static/blockly/generators/javascript/lists.js deleted file mode 100755 index d1e66a0ed..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/javascript/lists.js +++ /dev/null @@ -1,394 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating JavaScript for list blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.JavaScript.lists'); - -goog.require('Blockly.JavaScript'); - - -Blockly.JavaScript['lists_create_empty'] = function(block) { - // Create an empty list. - return ['[]', Blockly.JavaScript.ORDER_ATOMIC]; -}; - -Blockly.JavaScript['lists_create_with'] = function(block) { - // Create a list with any number of elements of any type. - var elements = new Array(block.itemCount_); - for (var i = 0; i < block.itemCount_; i++) { - elements[i] = Blockly.JavaScript.valueToCode(block, 'ADD' + i, - Blockly.JavaScript.ORDER_COMMA) || 'null'; - } - var code = '[' + elements.join(', ') + ']'; - return [code, Blockly.JavaScript.ORDER_ATOMIC]; -}; - -Blockly.JavaScript['lists_repeat'] = function(block) { - // Create a list with one element repeated. - var functionName = Blockly.JavaScript.provideFunction_( - 'listsRepeat', - ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + - '(value, n) {', - ' var array = [];', - ' for (var i = 0; i < n; i++) {', - ' array[i] = value;', - ' }', - ' return array;', - '}']); - var element = Blockly.JavaScript.valueToCode(block, 'ITEM', - Blockly.JavaScript.ORDER_COMMA) || 'null'; - var repeatCount = Blockly.JavaScript.valueToCode(block, 'NUM', - Blockly.JavaScript.ORDER_COMMA) || '0'; - var code = functionName + '(' + element + ', ' + repeatCount + ')'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; -}; - -Blockly.JavaScript['lists_length'] = function(block) { - // String or array length. - var list = Blockly.JavaScript.valueToCode(block, 'VALUE', - Blockly.JavaScript.ORDER_MEMBER) || '[]'; - return [list + '.length', Blockly.JavaScript.ORDER_MEMBER]; -}; - -Blockly.JavaScript['lists_isEmpty'] = function(block) { - // Is the string null or array empty? - var list = Blockly.JavaScript.valueToCode(block, 'VALUE', - Blockly.JavaScript.ORDER_MEMBER) || '[]'; - return ['!' + list + '.length', Blockly.JavaScript.ORDER_LOGICAL_NOT]; -}; - -Blockly.JavaScript['lists_indexOf'] = function(block) { - // Find an item in the list. - var operator = block.getFieldValue('END') == 'FIRST' ? - 'indexOf' : 'lastIndexOf'; - var item = Blockly.JavaScript.valueToCode(block, 'FIND', - Blockly.JavaScript.ORDER_NONE) || '\'\''; - var list = Blockly.JavaScript.valueToCode(block, 'VALUE', - Blockly.JavaScript.ORDER_MEMBER) || '[]'; - var code = list + '.' + operator + '(' + item + ')'; - if (Blockly.JavaScript.ONE_BASED_INDEXING) { - return [code + ' + 1', Blockly.JavaScript.ORDER_ADDITION]; - } - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; -}; - -Blockly.JavaScript['lists_getIndex'] = function(block) { - // Get element at index. - // Note: Until January 2013 this block did not have MODE or WHERE inputs. - var mode = block.getFieldValue('MODE') || 'GET'; - var where = block.getFieldValue('WHERE') || 'FROM_START'; - var listOrder = (where == 'RANDOM') ? Blockly.JavaScript.ORDER_COMMA : - Blockly.JavaScript.ORDER_MEMBER; - var list = Blockly.JavaScript.valueToCode(block, 'VALUE', listOrder) || '[]'; - - switch (where) { - case ('FIRST'): - if (mode == 'GET') { - var code = list + '[0]'; - return [code, Blockly.JavaScript.ORDER_MEMBER]; - } else if (mode == 'GET_REMOVE') { - var code = list + '.shift()'; - return [code, Blockly.JavaScript.ORDER_MEMBER]; - } else if (mode == 'REMOVE') { - return list + '.shift();\n'; - } - break; - case ('LAST'): - if (mode == 'GET') { - var code = list + '.slice(-1)[0]'; - return [code, Blockly.JavaScript.ORDER_MEMBER]; - } else if (mode == 'GET_REMOVE') { - var code = list + '.pop()'; - return [code, Blockly.JavaScript.ORDER_MEMBER]; - } else if (mode == 'REMOVE') { - return list + '.pop();\n'; - } - break; - case ('FROM_START'): - var at = Blockly.JavaScript.getAdjusted(block, 'AT'); - if (mode == 'GET') { - var code = list + '[' + at + ']'; - return [code, Blockly.JavaScript.ORDER_MEMBER]; - } else if (mode == 'GET_REMOVE') { - var code = list + '.splice(' + at + ', 1)[0]'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; - } else if (mode == 'REMOVE') { - return list + '.splice(' + at + ', 1);\n'; - } - break; - case ('FROM_END'): - var at = Blockly.JavaScript.getAdjusted(block, 'AT', 1, true); - if (mode == 'GET') { - var code = list + '.slice(' + at + ')[0]'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; - } else if (mode == 'GET_REMOVE') { - var code = list + '.splice(' + at + ', 1)[0]'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; - } else if (mode == 'REMOVE') { - return list + '.splice(' + at + ', 1);'; - } - break; - case ('RANDOM'): - var functionName = Blockly.JavaScript.provideFunction_( - 'listsGetRandomItem', - ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + - '(list, remove) {', - ' var x = Math.floor(Math.random() * list.length);', - ' if (remove) {', - ' return list.splice(x, 1)[0];', - ' } else {', - ' return list[x];', - ' }', - '}']); - code = functionName + '(' + list + ', ' + (mode != 'GET') + ')'; - if (mode == 'GET' || mode == 'GET_REMOVE') { - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; - } else if (mode == 'REMOVE') { - return code + ';\n'; - } - break; - } - throw 'Unhandled combination (lists_getIndex).'; -}; - -Blockly.JavaScript['lists_setIndex'] = function(block) { - // Set element at index. - // Note: Until February 2013 this block did not have MODE or WHERE inputs. - var list = Blockly.JavaScript.valueToCode(block, 'LIST', - Blockly.JavaScript.ORDER_MEMBER) || '[]'; - var mode = block.getFieldValue('MODE') || 'GET'; - var where = block.getFieldValue('WHERE') || 'FROM_START'; - var value = Blockly.JavaScript.valueToCode(block, 'TO', - Blockly.JavaScript.ORDER_ASSIGNMENT) || 'null'; - // Cache non-trivial values to variables to prevent repeated look-ups. - // Closure, which accesses and modifies 'list'. - function cacheList() { - if (list.match(/^\w+$/)) { - return ''; - } - var listVar = Blockly.JavaScript.variableDB_.getDistinctName( - 'tmpList', Blockly.Variables.NAME_TYPE); - var code = 'var ' + listVar + ' = ' + list + ';\n'; - list = listVar; - return code; - } - switch (where) { - case ('FIRST'): - if (mode == 'SET') { - return list + '[0] = ' + value + ';\n'; - } else if (mode == 'INSERT') { - return list + '.unshift(' + value + ');\n'; - } - break; - case ('LAST'): - if (mode == 'SET') { - var code = cacheList(); - code += list + '[' + list + '.length - 1] = ' + value + ';\n'; - return code; - } else if (mode == 'INSERT') { - return list + '.push(' + value + ');\n'; - } - break; - case ('FROM_START'): - var at = Blockly.JavaScript.getAdjusted(block, 'AT'); - if (mode == 'SET') { - return list + '[' + at + '] = ' + value + ';\n'; - } else if (mode == 'INSERT') { - return list + '.splice(' + at + ', 0, ' + value + ');\n'; - } - break; - case ('FROM_END'): - var at = Blockly.JavaScript.getAdjusted(block, 'AT', 1, false, - Blockly.JavaScript.ORDER_SUBTRACTION); - var code = cacheList(); - if (mode == 'SET') { - code += list + '[' + list + '.length - ' + at + '] = ' + value + ';\n'; - return code; - } else if (mode == 'INSERT') { - code += list + '.splice(' + list + '.length - ' + at + ', 0, ' + value + - ');\n'; - return code; - } - break; - case ('RANDOM'): - var code = cacheList(); - var xVar = Blockly.JavaScript.variableDB_.getDistinctName( - 'tmpX', Blockly.Variables.NAME_TYPE); - code += 'var ' + xVar + ' = Math.floor(Math.random() * ' + list + - '.length);\n'; - if (mode == 'SET') { - code += list + '[' + xVar + '] = ' + value + ';\n'; - return code; - } else if (mode == 'INSERT') { - code += list + '.splice(' + xVar + ', 0, ' + value + ');\n'; - return code; - } - break; - } - throw 'Unhandled combination (lists_setIndex).'; -}; - -/** - * Returns an expression calculating the index into a list. - * @private - * @param {string} listName Name of the list, used to calculate length. - * @param {string} where The method of indexing, selected by dropdown in Blockly - * @param {string=} opt_at The optional offset when indexing from start/end. - * @return {string} Index expression. - */ -Blockly.JavaScript.lists.getIndex_ = function(listName, where, opt_at) { - if (where == 'FIRST') { - return '0'; - } else if (where == 'FROM_END') { - return listName + '.length - 1 - ' + opt_at; - } else if (where == 'LAST') { - return listName + '.length - 1'; - } else { - return opt_at; - } -}; - -Blockly.JavaScript['lists_getSublist'] = function(block) { - // Get sublist. - var list = Blockly.JavaScript.valueToCode(block, 'LIST', - Blockly.JavaScript.ORDER_MEMBER) || '[]'; - var where1 = block.getFieldValue('WHERE1'); - var where2 = block.getFieldValue('WHERE2'); - if (where1 == 'FIRST' && where2 == 'LAST') { - var code = list + '.slice(0)'; - } else if (list.match(/^\w+$/) || - (where1 != 'FROM_END' && where2 == 'FROM_START')) { - // If the list is a variable or doesn't require a call for length, don't - // generate a helper function. - switch (where1) { - case 'FROM_START': - var at1 = Blockly.JavaScript.getAdjusted(block, 'AT1'); - break; - case 'FROM_END': - var at1 = Blockly.JavaScript.getAdjusted(block, 'AT1', 1, false, - Blockly.JavaScript.ORDER_SUBTRACTION); - at1 = list + '.length - ' + at1; - break; - case 'FIRST': - var at1 = '0'; - break; - default: - throw 'Unhandled option (lists_getSublist).'; - } - switch (where2) { - case 'FROM_START': - var at2 = Blockly.JavaScript.getAdjusted(block, 'AT2', 1); - break; - case 'FROM_END': - var at2 = Blockly.JavaScript.getAdjusted(block, 'AT2', 0, false, - Blockly.JavaScript.ORDER_SUBTRACTION); - at2 = list + '.length - ' + at2; - break; - case 'LAST': - var at2 = list + '.length'; - break; - default: - throw 'Unhandled option (lists_getSublist).'; - } - code = list + '.slice(' + at1 + ', ' + at2 + ')'; - } else { - var at1 = Blockly.JavaScript.getAdjusted(block, 'AT1'); - var at2 = Blockly.JavaScript.getAdjusted(block, 'AT2'); - var getIndex_ = Blockly.JavaScript.lists.getIndex_; - var wherePascalCase = {'FIRST': 'First', 'LAST': 'Last', - 'FROM_START': 'FromStart', 'FROM_END': 'FromEnd'}; - var functionName = Blockly.JavaScript.provideFunction_( - 'subsequence' + wherePascalCase[where1] + wherePascalCase[where2], - ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + - '(sequence' + - // The value for 'FROM_END' and'FROM_START' depends on `at` so - // we add it as a parameter. - ((where1 == 'FROM_END' || where1 == 'FROM_START') ? ', at1' : '') + - ((where2 == 'FROM_END' || where2 == 'FROM_START') ? ', at2' : '') + - ') {', - ' var start = ' + getIndex_('sequence', where1, 'at1') + ';', - ' var end = ' + getIndex_('sequence', where2, 'at2') + ' + 1;', - ' return sequence.slice(start, end);', - '}']); - var code = functionName + '(' + list + - // The value for 'FROM_END' and 'FROM_START' depends on `at` so we - // pass it. - ((where1 == 'FROM_END' || where1 == 'FROM_START') ? ', ' + at1 : '') + - ((where2 == 'FROM_END' || where2 == 'FROM_START') ? ', ' + at2 : '') + - ')'; - } - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; -}; - -Blockly.JavaScript['lists_sort'] = function(block) { - // Block for sorting a list. - var list = Blockly.JavaScript.valueToCode(block, 'LIST', - Blockly.JavaScript.ORDER_FUNCTION_CALL) || '[]'; - var direction = block.getFieldValue('DIRECTION') === '1' ? 1 : -1; - var type = block.getFieldValue('TYPE'); - var getCompareFunctionName = Blockly.JavaScript.provideFunction_( - 'listsGetSortCompare', - ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + - '(type, direction) {', - ' var compareFuncs = {', - ' "NUMERIC": function(a, b) {', - ' return parseFloat(a) - parseFloat(b); },', - ' "TEXT": function(a, b) {', - ' return a.toString() > b.toString() ? 1 : -1; },', - ' "IGNORE_CASE": function(a, b) {', - ' return a.toString().toLowerCase() > ' + - 'b.toString().toLowerCase() ? 1 : -1; },', - ' };', - ' var compare = compareFuncs[type];', - ' return function(a, b) { return compare(a, b) * direction; }', - '}']); - return [list + '.slice().sort(' + - getCompareFunctionName + '("' + type + '", ' + direction + '))', - Blockly.JavaScript.ORDER_FUNCTION_CALL]; -}; - -Blockly.JavaScript['lists_split'] = function(block) { - // Block for splitting text into a list, or joining a list into text. - var input = Blockly.JavaScript.valueToCode(block, 'INPUT', - Blockly.JavaScript.ORDER_MEMBER); - var delimiter = Blockly.JavaScript.valueToCode(block, 'DELIM', - Blockly.JavaScript.ORDER_NONE) || '\'\''; - var mode = block.getFieldValue('MODE'); - if (mode == 'SPLIT') { - if (!input) { - input = '\'\''; - } - var functionName = 'split'; - } else if (mode == 'JOIN') { - if (!input) { - input = '[]'; - } - var functionName = 'join'; - } else { - throw 'Unknown mode: ' + mode; - } - var code = input + '.' + functionName + '(' + delimiter + ')'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/javascript/logic.js b/backend/_pv_1_3_5/static/blockly/generators/javascript/logic.js deleted file mode 100755 index 07ee35b6c..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/javascript/logic.js +++ /dev/null @@ -1,126 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating JavaScript for logic blocks. - * @author q.neutron@gmail.com (Quynh Neutron) - */ -'use strict'; - -goog.provide('Blockly.JavaScript.logic'); - -goog.require('Blockly.JavaScript'); - - -Blockly.JavaScript['controls_if'] = function(block) { - // If/elseif/else condition. - var n = 0; - var argument = Blockly.JavaScript.valueToCode(block, 'IF' + n, - Blockly.JavaScript.ORDER_NONE) || 'false'; - var branch = Blockly.JavaScript.statementToCode(block, 'DO' + n); - var code = 'if (' + argument + ') {\n' + branch + '}'; - for (n = 1; n <= block.elseifCount_; n++) { - argument = Blockly.JavaScript.valueToCode(block, 'IF' + n, - Blockly.JavaScript.ORDER_NONE) || 'false'; - branch = Blockly.JavaScript.statementToCode(block, 'DO' + n); - code += ' else if (' + argument + ') {\n' + branch + '}'; - } - if (block.elseCount_) { - branch = Blockly.JavaScript.statementToCode(block, 'ELSE'); - code += ' else {\n' + branch + '}'; - } - return code + '\n'; -}; - -Blockly.JavaScript['logic_compare'] = function(block) { - // Comparison operator. - var OPERATORS = { - 'EQ': '==', - 'NEQ': '!=', - 'LT': '<', - 'LTE': '<=', - 'GT': '>', - 'GTE': '>=' - }; - var operator = OPERATORS[block.getFieldValue('OP')]; - var order = (operator == '==' || operator == '!=') ? - Blockly.JavaScript.ORDER_EQUALITY : Blockly.JavaScript.ORDER_RELATIONAL; - var argument0 = Blockly.JavaScript.valueToCode(block, 'A', order) || '0'; - var argument1 = Blockly.JavaScript.valueToCode(block, 'B', order) || '0'; - var code = argument0 + ' ' + operator + ' ' + argument1; - return [code, order]; -}; - -Blockly.JavaScript['logic_operation'] = function(block) { - // Operations 'and', 'or'. - var operator = (block.getFieldValue('OP') == 'AND') ? '&&' : '||'; - var order = (operator == '&&') ? Blockly.JavaScript.ORDER_LOGICAL_AND : - Blockly.JavaScript.ORDER_LOGICAL_OR; - var argument0 = Blockly.JavaScript.valueToCode(block, 'A', order); - var argument1 = Blockly.JavaScript.valueToCode(block, 'B', order); - if (!argument0 && !argument1) { - // If there are no arguments, then the return value is false. - argument0 = 'false'; - argument1 = 'false'; - } else { - // Single missing arguments have no effect on the return value. - var defaultArgument = (operator == '&&') ? 'true' : 'false'; - if (!argument0) { - argument0 = defaultArgument; - } - if (!argument1) { - argument1 = defaultArgument; - } - } - var code = argument0 + ' ' + operator + ' ' + argument1; - return [code, order]; -}; - -Blockly.JavaScript['logic_negate'] = function(block) { - // Negation. - var order = Blockly.JavaScript.ORDER_LOGICAL_NOT; - var argument0 = Blockly.JavaScript.valueToCode(block, 'BOOL', order) || - 'true'; - var code = '!' + argument0; - return [code, order]; -}; - -Blockly.JavaScript['logic_boolean'] = function(block) { - // Boolean values true and false. - var code = (block.getFieldValue('BOOL') == 'TRUE') ? 'true' : 'false'; - return [code, Blockly.JavaScript.ORDER_ATOMIC]; -}; - -Blockly.JavaScript['logic_null'] = function(block) { - // Null data type. - return ['null', Blockly.JavaScript.ORDER_ATOMIC]; -}; - -Blockly.JavaScript['logic_ternary'] = function(block) { - // Ternary operator. - var value_if = Blockly.JavaScript.valueToCode(block, 'IF', - Blockly.JavaScript.ORDER_CONDITIONAL) || 'false'; - var value_then = Blockly.JavaScript.valueToCode(block, 'THEN', - Blockly.JavaScript.ORDER_CONDITIONAL) || 'null'; - var value_else = Blockly.JavaScript.valueToCode(block, 'ELSE', - Blockly.JavaScript.ORDER_CONDITIONAL) || 'null'; - var code = value_if + ' ? ' + value_then + ' : ' + value_else; - return [code, Blockly.JavaScript.ORDER_CONDITIONAL]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/javascript/loops.js b/backend/_pv_1_3_5/static/blockly/generators/javascript/loops.js deleted file mode 100755 index 1a2ade593..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/javascript/loops.js +++ /dev/null @@ -1,175 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating JavaScript for loop blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.JavaScript.loops'); - -goog.require('Blockly.JavaScript'); - - -Blockly.JavaScript['controls_repeat_ext'] = function(block) { - // Repeat n times. - if (block.getField('TIMES')) { - // Internal number. - var repeats = String(Number(block.getFieldValue('TIMES'))); - } else { - // External number. - var repeats = Blockly.JavaScript.valueToCode(block, 'TIMES', - Blockly.JavaScript.ORDER_ASSIGNMENT) || '0'; - } - var branch = Blockly.JavaScript.statementToCode(block, 'DO'); - branch = Blockly.JavaScript.addLoopTrap(branch, block.id); - var code = ''; - var loopVar = Blockly.JavaScript.variableDB_.getDistinctName( - 'count', Blockly.Variables.NAME_TYPE); - var endVar = repeats; - if (!repeats.match(/^\w+$/) && !Blockly.isNumber(repeats)) { - var endVar = Blockly.JavaScript.variableDB_.getDistinctName( - 'repeat_end', Blockly.Variables.NAME_TYPE); - code += 'var ' + endVar + ' = ' + repeats + ';\n'; - } - code += 'for (var ' + loopVar + ' = 0; ' + - loopVar + ' < ' + endVar + '; ' + - loopVar + '++) {\n' + - branch + '}\n'; - return code; -}; - -Blockly.JavaScript['controls_repeat'] = - Blockly.JavaScript['controls_repeat_ext']; - -Blockly.JavaScript['controls_whileUntil'] = function(block) { - // Do while/until loop. - var until = block.getFieldValue('MODE') == 'UNTIL'; - var argument0 = Blockly.JavaScript.valueToCode(block, 'BOOL', - until ? Blockly.JavaScript.ORDER_LOGICAL_NOT : - Blockly.JavaScript.ORDER_NONE) || 'false'; - var branch = Blockly.JavaScript.statementToCode(block, 'DO'); - branch = Blockly.JavaScript.addLoopTrap(branch, block.id); - if (until) { - argument0 = '!' + argument0; - } - return 'while (' + argument0 + ') {\n' + branch + '}\n'; -}; - -Blockly.JavaScript['controls_for'] = function(block) { - // For loop. - var variable0 = Blockly.JavaScript.variableDB_.getName( - block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); - var argument0 = Blockly.JavaScript.valueToCode(block, 'FROM', - Blockly.JavaScript.ORDER_ASSIGNMENT) || '0'; - var argument1 = Blockly.JavaScript.valueToCode(block, 'TO', - Blockly.JavaScript.ORDER_ASSIGNMENT) || '0'; - var increment = Blockly.JavaScript.valueToCode(block, 'BY', - Blockly.JavaScript.ORDER_ASSIGNMENT) || '1'; - var branch = Blockly.JavaScript.statementToCode(block, 'DO'); - branch = Blockly.JavaScript.addLoopTrap(branch, block.id); - var code; - if (Blockly.isNumber(argument0) && Blockly.isNumber(argument1) && - Blockly.isNumber(increment)) { - // All arguments are simple numbers. - var up = parseFloat(argument0) <= parseFloat(argument1); - code = 'for (' + variable0 + ' = ' + argument0 + '; ' + - variable0 + (up ? ' <= ' : ' >= ') + argument1 + '; ' + - variable0; - var step = Math.abs(parseFloat(increment)); - if (step == 1) { - code += up ? '++' : '--'; - } else { - code += (up ? ' += ' : ' -= ') + step; - } - code += ') {\n' + branch + '}\n'; - } else { - code = ''; - // Cache non-trivial values to variables to prevent repeated look-ups. - var startVar = argument0; - if (!argument0.match(/^\w+$/) && !Blockly.isNumber(argument0)) { - startVar = Blockly.JavaScript.variableDB_.getDistinctName( - variable0 + '_start', Blockly.Variables.NAME_TYPE); - code += 'var ' + startVar + ' = ' + argument0 + ';\n'; - } - var endVar = argument1; - if (!argument1.match(/^\w+$/) && !Blockly.isNumber(argument1)) { - var endVar = Blockly.JavaScript.variableDB_.getDistinctName( - variable0 + '_end', Blockly.Variables.NAME_TYPE); - code += 'var ' + endVar + ' = ' + argument1 + ';\n'; - } - // Determine loop direction at start, in case one of the bounds - // changes during loop execution. - var incVar = Blockly.JavaScript.variableDB_.getDistinctName( - variable0 + '_inc', Blockly.Variables.NAME_TYPE); - code += 'var ' + incVar + ' = '; - if (Blockly.isNumber(increment)) { - code += Math.abs(increment) + ';\n'; - } else { - code += 'Math.abs(' + increment + ');\n'; - } - code += 'if (' + startVar + ' > ' + endVar + ') {\n'; - code += Blockly.JavaScript.INDENT + incVar + ' = -' + incVar + ';\n'; - code += '}\n'; - code += 'for (' + variable0 + ' = ' + startVar + '; ' + - incVar + ' >= 0 ? ' + - variable0 + ' <= ' + endVar + ' : ' + - variable0 + ' >= ' + endVar + '; ' + - variable0 + ' += ' + incVar + ') {\n' + - branch + '}\n'; - } - return code; -}; - -Blockly.JavaScript['controls_forEach'] = function(block) { - // For each loop. - var variable0 = Blockly.JavaScript.variableDB_.getName( - block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); - var argument0 = Blockly.JavaScript.valueToCode(block, 'LIST', - Blockly.JavaScript.ORDER_ASSIGNMENT) || '[]'; - var branch = Blockly.JavaScript.statementToCode(block, 'DO'); - branch = Blockly.JavaScript.addLoopTrap(branch, block.id); - var code = ''; - // Cache non-trivial values to variables to prevent repeated look-ups. - var listVar = argument0; - if (!argument0.match(/^\w+$/)) { - listVar = Blockly.JavaScript.variableDB_.getDistinctName( - variable0 + '_list', Blockly.Variables.NAME_TYPE); - code += 'var ' + listVar + ' = ' + argument0 + ';\n'; - } - var indexVar = Blockly.JavaScript.variableDB_.getDistinctName( - variable0 + '_index', Blockly.Variables.NAME_TYPE); - branch = Blockly.JavaScript.INDENT + variable0 + ' = ' + - listVar + '[' + indexVar + '];\n' + branch; - code += 'for (var ' + indexVar + ' in ' + listVar + ') {\n' + branch + '}\n'; - return code; -}; - -Blockly.JavaScript['controls_flow_statements'] = function(block) { - // Flow statements: continue, break. - switch (block.getFieldValue('FLOW')) { - case 'BREAK': - return 'break;\n'; - case 'CONTINUE': - return 'continue;\n'; - } - throw 'Unknown flow statement.'; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/javascript/math.js b/backend/_pv_1_3_5/static/blockly/generators/javascript/math.js deleted file mode 100755 index a31b94392..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/javascript/math.js +++ /dev/null @@ -1,411 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating JavaScript for math blocks. - * @author q.neutron@gmail.com (Quynh Neutron) - */ -'use strict'; - -goog.provide('Blockly.JavaScript.math'); - -goog.require('Blockly.JavaScript'); - - -Blockly.JavaScript['math_number'] = function(block) { - // Numeric value. - var code = parseFloat(block.getFieldValue('NUM')); - return [code, Blockly.JavaScript.ORDER_ATOMIC]; -}; - -Blockly.JavaScript['math_arithmetic'] = function(block) { - // Basic arithmetic operators, and power. - var OPERATORS = { - 'ADD': [' + ', Blockly.JavaScript.ORDER_ADDITION], - 'MINUS': [' - ', Blockly.JavaScript.ORDER_SUBTRACTION], - 'MULTIPLY': [' * ', Blockly.JavaScript.ORDER_MULTIPLICATION], - 'DIVIDE': [' / ', Blockly.JavaScript.ORDER_DIVISION], - 'POWER': [null, Blockly.JavaScript.ORDER_COMMA] // Handle power separately. - }; - var tuple = OPERATORS[block.getFieldValue('OP')]; - var operator = tuple[0]; - var order = tuple[1]; - var argument0 = Blockly.JavaScript.valueToCode(block, 'A', order) || '0'; - var argument1 = Blockly.JavaScript.valueToCode(block, 'B', order) || '0'; - var code; - // Power in JavaScript requires a special case since it has no operator. - if (!operator) { - code = 'Math.pow(' + argument0 + ', ' + argument1 + ')'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; - } - code = argument0 + operator + argument1; - return [code, order]; -}; - -Blockly.JavaScript['math_single'] = function(block) { - // Math operators with single operand. - var operator = block.getFieldValue('OP'); - var code; - var arg; - if (operator == 'NEG') { - // Negation is a special case given its different operator precedence. - arg = Blockly.JavaScript.valueToCode(block, 'NUM', - Blockly.JavaScript.ORDER_UNARY_NEGATION) || '0'; - if (arg[0] == '-') { - // --3 is not legal in JS. - arg = ' ' + arg; - } - code = '-' + arg; - return [code, Blockly.JavaScript.ORDER_UNARY_NEGATION]; - } - if (operator == 'SIN' || operator == 'COS' || operator == 'TAN') { - arg = Blockly.JavaScript.valueToCode(block, 'NUM', - Blockly.JavaScript.ORDER_DIVISION) || '0'; - } else { - arg = Blockly.JavaScript.valueToCode(block, 'NUM', - Blockly.JavaScript.ORDER_NONE) || '0'; - } - // First, handle cases which generate values that don't need parentheses - // wrapping the code. - switch (operator) { - case 'ABS': - code = 'Math.abs(' + arg + ')'; - break; - case 'ROOT': - code = 'Math.sqrt(' + arg + ')'; - break; - case 'LN': - code = 'Math.log(' + arg + ')'; - break; - case 'EXP': - code = 'Math.exp(' + arg + ')'; - break; - case 'POW10': - code = 'Math.pow(10,' + arg + ')'; - break; - case 'ROUND': - code = 'Math.round(' + arg + ')'; - break; - case 'ROUNDUP': - code = 'Math.ceil(' + arg + ')'; - break; - case 'ROUNDDOWN': - code = 'Math.floor(' + arg + ')'; - break; - case 'SIN': - code = 'Math.sin(' + arg + ' / 180 * Math.PI)'; - break; - case 'COS': - code = 'Math.cos(' + arg + ' / 180 * Math.PI)'; - break; - case 'TAN': - code = 'Math.tan(' + arg + ' / 180 * Math.PI)'; - break; - } - if (code) { - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; - } - // Second, handle cases which generate values that may need parentheses - // wrapping the code. - switch (operator) { - case 'LOG10': - code = 'Math.log(' + arg + ') / Math.log(10)'; - break; - case 'ASIN': - code = 'Math.asin(' + arg + ') / Math.PI * 180'; - break; - case 'ACOS': - code = 'Math.acos(' + arg + ') / Math.PI * 180'; - break; - case 'ATAN': - code = 'Math.atan(' + arg + ') / Math.PI * 180'; - break; - default: - throw 'Unknown math operator: ' + operator; - } - return [code, Blockly.JavaScript.ORDER_DIVISION]; -}; - -Blockly.JavaScript['math_constant'] = function(block) { - // Constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY. - var CONSTANTS = { - 'PI': ['Math.PI', Blockly.JavaScript.ORDER_MEMBER], - 'E': ['Math.E', Blockly.JavaScript.ORDER_MEMBER], - 'GOLDEN_RATIO': - ['(1 + Math.sqrt(5)) / 2', Blockly.JavaScript.ORDER_DIVISION], - 'SQRT2': ['Math.SQRT2', Blockly.JavaScript.ORDER_MEMBER], - 'SQRT1_2': ['Math.SQRT1_2', Blockly.JavaScript.ORDER_MEMBER], - 'INFINITY': ['Infinity', Blockly.JavaScript.ORDER_ATOMIC] - }; - return CONSTANTS[block.getFieldValue('CONSTANT')]; -}; - -Blockly.JavaScript['math_number_property'] = function(block) { - // Check if a number is even, odd, prime, whole, positive, or negative - // or if it is divisible by certain number. Returns true or false. - var number_to_check = Blockly.JavaScript.valueToCode(block, 'NUMBER_TO_CHECK', - Blockly.JavaScript.ORDER_MODULUS) || '0'; - var dropdown_property = block.getFieldValue('PROPERTY'); - var code; - if (dropdown_property == 'PRIME') { - // Prime is a special case as it is not a one-liner test. - var functionName = Blockly.JavaScript.provideFunction_( - 'mathIsPrime', - ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + '(n) {', - ' // https://en.wikipedia.org/wiki/Primality_test#Naive_methods', - ' if (n == 2 || n == 3) {', - ' return true;', - ' }', - ' // False if n is NaN, negative, is 1, or not whole.', - ' // And false if n is divisible by 2 or 3.', - ' if (isNaN(n) || n <= 1 || n % 1 != 0 || n % 2 == 0 ||' + - ' n % 3 == 0) {', - ' return false;', - ' }', - ' // Check all the numbers of form 6k +/- 1, up to sqrt(n).', - ' for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {', - ' if (n % (x - 1) == 0 || n % (x + 1) == 0) {', - ' return false;', - ' }', - ' }', - ' return true;', - '}']); - code = functionName + '(' + number_to_check + ')'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; - } - switch (dropdown_property) { - case 'EVEN': - code = number_to_check + ' % 2 == 0'; - break; - case 'ODD': - code = number_to_check + ' % 2 == 1'; - break; - case 'WHOLE': - code = number_to_check + ' % 1 == 0'; - break; - case 'POSITIVE': - code = number_to_check + ' > 0'; - break; - case 'NEGATIVE': - code = number_to_check + ' < 0'; - break; - case 'DIVISIBLE_BY': - var divisor = Blockly.JavaScript.valueToCode(block, 'DIVISOR', - Blockly.JavaScript.ORDER_MODULUS) || '0'; - code = number_to_check + ' % ' + divisor + ' == 0'; - break; - } - return [code, Blockly.JavaScript.ORDER_EQUALITY]; -}; - -Blockly.JavaScript['math_change'] = function(block) { - // Add to a variable in place. - var argument0 = Blockly.JavaScript.valueToCode(block, 'DELTA', - Blockly.JavaScript.ORDER_ADDITION) || '0'; - var varName = Blockly.JavaScript.variableDB_.getName( - block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); - return varName + ' = (typeof ' + varName + ' == \'number\' ? ' + varName + - ' : 0) + ' + argument0 + ';\n'; -}; - -// Rounding functions have a single operand. -Blockly.JavaScript['math_round'] = Blockly.JavaScript['math_single']; -// Trigonometry functions have a single operand. -Blockly.JavaScript['math_trig'] = Blockly.JavaScript['math_single']; - -Blockly.JavaScript['math_on_list'] = function(block) { - // Math functions for lists. - var func = block.getFieldValue('OP'); - var list, code; - switch (func) { - case 'SUM': - list = Blockly.JavaScript.valueToCode(block, 'LIST', - Blockly.JavaScript.ORDER_MEMBER) || '[]'; - code = list + '.reduce(function(x, y) {return x + y;})'; - break; - case 'MIN': - list = Blockly.JavaScript.valueToCode(block, 'LIST', - Blockly.JavaScript.ORDER_COMMA) || '[]'; - code = 'Math.min.apply(null, ' + list + ')'; - break; - case 'MAX': - list = Blockly.JavaScript.valueToCode(block, 'LIST', - Blockly.JavaScript.ORDER_COMMA) || '[]'; - code = 'Math.max.apply(null, ' + list + ')'; - break; - case 'AVERAGE': - // mathMean([null,null,1,3]) == 2.0. - var functionName = Blockly.JavaScript.provideFunction_( - 'mathMean', - ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + - '(myList) {', - ' return myList.reduce(function(x, y) {return x + y;}) / ' + - 'myList.length;', - '}']); - list = Blockly.JavaScript.valueToCode(block, 'LIST', - Blockly.JavaScript.ORDER_NONE) || '[]'; - code = functionName + '(' + list + ')'; - break; - case 'MEDIAN': - // mathMedian([null,null,1,3]) == 2.0. - var functionName = Blockly.JavaScript.provideFunction_( - 'mathMedian', - ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + - '(myList) {', - ' var localList = myList.filter(function (x) ' + - '{return typeof x == \'number\';});', - ' if (!localList.length) return null;', - ' localList.sort(function(a, b) {return b - a;});', - ' if (localList.length % 2 == 0) {', - ' return (localList[localList.length / 2 - 1] + ' + - 'localList[localList.length / 2]) / 2;', - ' } else {', - ' return localList[(localList.length - 1) / 2];', - ' }', - '}']); - list = Blockly.JavaScript.valueToCode(block, 'LIST', - Blockly.JavaScript.ORDER_NONE) || '[]'; - code = functionName + '(' + list + ')'; - break; - case 'MODE': - // As a list of numbers can contain more than one mode, - // the returned result is provided as an array. - // Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1]. - var functionName = Blockly.JavaScript.provideFunction_( - 'mathModes', - ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + - '(values) {', - ' var modes = [];', - ' var counts = [];', - ' var maxCount = 0;', - ' for (var i = 0; i < values.length; i++) {', - ' var value = values[i];', - ' var found = false;', - ' var thisCount;', - ' for (var j = 0; j < counts.length; j++) {', - ' if (counts[j][0] === value) {', - ' thisCount = ++counts[j][1];', - ' found = true;', - ' break;', - ' }', - ' }', - ' if (!found) {', - ' counts.push([value, 1]);', - ' thisCount = 1;', - ' }', - ' maxCount = Math.max(thisCount, maxCount);', - ' }', - ' for (var j = 0; j < counts.length; j++) {', - ' if (counts[j][1] == maxCount) {', - ' modes.push(counts[j][0]);', - ' }', - ' }', - ' return modes;', - '}']); - list = Blockly.JavaScript.valueToCode(block, 'LIST', - Blockly.JavaScript.ORDER_NONE) || '[]'; - code = functionName + '(' + list + ')'; - break; - case 'STD_DEV': - var functionName = Blockly.JavaScript.provideFunction_( - 'mathStandardDeviation', - ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + - '(numbers) {', - ' var n = numbers.length;', - ' if (!n) return null;', - ' var mean = numbers.reduce(function(x, y) {return x + y;}) / n;', - ' var variance = 0;', - ' for (var j = 0; j < n; j++) {', - ' variance += Math.pow(numbers[j] - mean, 2);', - ' }', - ' variance = variance / n;', - ' return Math.sqrt(variance);', - '}']); - list = Blockly.JavaScript.valueToCode(block, 'LIST', - Blockly.JavaScript.ORDER_NONE) || '[]'; - code = functionName + '(' + list + ')'; - break; - case 'RANDOM': - var functionName = Blockly.JavaScript.provideFunction_( - 'mathRandomList', - ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + - '(list) {', - ' var x = Math.floor(Math.random() * list.length);', - ' return list[x];', - '}']); - list = Blockly.JavaScript.valueToCode(block, 'LIST', - Blockly.JavaScript.ORDER_NONE) || '[]'; - code = functionName + '(' + list + ')'; - break; - default: - throw 'Unknown operator: ' + func; - } - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; -}; - -Blockly.JavaScript['math_modulo'] = function(block) { - // Remainder computation. - var argument0 = Blockly.JavaScript.valueToCode(block, 'DIVIDEND', - Blockly.JavaScript.ORDER_MODULUS) || '0'; - var argument1 = Blockly.JavaScript.valueToCode(block, 'DIVISOR', - Blockly.JavaScript.ORDER_MODULUS) || '0'; - var code = argument0 + ' % ' + argument1; - return [code, Blockly.JavaScript.ORDER_MODULUS]; -}; - -Blockly.JavaScript['math_constrain'] = function(block) { - // Constrain a number between two limits. - var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE', - Blockly.JavaScript.ORDER_COMMA) || '0'; - var argument1 = Blockly.JavaScript.valueToCode(block, 'LOW', - Blockly.JavaScript.ORDER_COMMA) || '0'; - var argument2 = Blockly.JavaScript.valueToCode(block, 'HIGH', - Blockly.JavaScript.ORDER_COMMA) || 'Infinity'; - var code = 'Math.min(Math.max(' + argument0 + ', ' + argument1 + '), ' + - argument2 + ')'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; -}; - -Blockly.JavaScript['math_random_int'] = function(block) { - // Random integer between [X] and [Y]. - var argument0 = Blockly.JavaScript.valueToCode(block, 'FROM', - Blockly.JavaScript.ORDER_COMMA) || '0'; - var argument1 = Blockly.JavaScript.valueToCode(block, 'TO', - Blockly.JavaScript.ORDER_COMMA) || '0'; - var functionName = Blockly.JavaScript.provideFunction_( - 'mathRandomInt', - ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + - '(a, b) {', - ' if (a > b) {', - ' // Swap a and b to ensure a is smaller.', - ' var c = a;', - ' a = b;', - ' b = c;', - ' }', - ' return Math.floor(Math.random() * (b - a + 1) + a);', - '}']); - var code = functionName + '(' + argument0 + ', ' + argument1 + ')'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; -}; - -Blockly.JavaScript['math_random_float'] = function(block) { - // Random fraction between 0 and 1. - return ['Math.random()', Blockly.JavaScript.ORDER_FUNCTION_CALL]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/javascript/procedures.js b/backend/_pv_1_3_5/static/blockly/generators/javascript/procedures.js deleted file mode 100755 index 04845f9bd..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/javascript/procedures.js +++ /dev/null @@ -1,109 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating JavaScript for procedure blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.JavaScript.procedures'); - -goog.require('Blockly.JavaScript'); - - -Blockly.JavaScript['procedures_defreturn'] = function(block) { - // Define a procedure with a return value. - var funcName = Blockly.JavaScript.variableDB_.getName( - block.getFieldValue('NAME'), Blockly.Procedures.NAME_TYPE); - var branch = Blockly.JavaScript.statementToCode(block, 'STACK'); - if (Blockly.JavaScript.STATEMENT_PREFIX) { - branch = Blockly.JavaScript.prefixLines( - Blockly.JavaScript.STATEMENT_PREFIX.replace(/%1/g, - '\'' + block.id + '\''), Blockly.JavaScript.INDENT) + branch; - } - if (Blockly.JavaScript.INFINITE_LOOP_TRAP) { - branch = Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g, - '\'' + block.id + '\'') + branch; - } - var returnValue = Blockly.JavaScript.valueToCode(block, 'RETURN', - Blockly.JavaScript.ORDER_NONE) || ''; - if (returnValue) { - returnValue = ' return ' + returnValue + ';\n'; - } - var args = []; - for (var i = 0; i < block.arguments_.length; i++) { - args[i] = Blockly.JavaScript.variableDB_.getName(block.arguments_[i], - Blockly.Variables.NAME_TYPE); - } - var code = 'function ' + funcName + '(' + args.join(', ') + ') {\n' + - branch + returnValue + '}'; - code = Blockly.JavaScript.scrub_(block, code); - // Add % so as not to collide with helper functions in definitions list. - Blockly.JavaScript.definitions_['%' + funcName] = code; - return null; -}; - -// Defining a procedure without a return value uses the same generator as -// a procedure with a return value. -Blockly.JavaScript['procedures_defnoreturn'] = - Blockly.JavaScript['procedures_defreturn']; - -Blockly.JavaScript['procedures_callreturn'] = function(block) { - // Call a procedure with a return value. - var funcName = Blockly.JavaScript.variableDB_.getName( - block.getFieldValue('NAME'), Blockly.Procedures.NAME_TYPE); - var args = []; - for (var i = 0; i < block.arguments_.length; i++) { - args[i] = Blockly.JavaScript.valueToCode(block, 'ARG' + i, - Blockly.JavaScript.ORDER_COMMA) || 'null'; - } - var code = funcName + '(' + args.join(', ') + ')'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; -}; - -Blockly.JavaScript['procedures_callnoreturn'] = function(block) { - // Call a procedure with no return value. - var funcName = Blockly.JavaScript.variableDB_.getName( - block.getFieldValue('NAME'), Blockly.Procedures.NAME_TYPE); - var args = []; - for (var i = 0; i < block.arguments_.length; i++) { - args[i] = Blockly.JavaScript.valueToCode(block, 'ARG' + i, - Blockly.JavaScript.ORDER_COMMA) || 'null'; - } - var code = funcName + '(' + args.join(', ') + ');\n'; - return code; -}; - -Blockly.JavaScript['procedures_ifreturn'] = function(block) { - // Conditionally return value from a procedure. - var condition = Blockly.JavaScript.valueToCode(block, 'CONDITION', - Blockly.JavaScript.ORDER_NONE) || 'false'; - var code = 'if (' + condition + ') {\n'; - if (block.hasReturnValue_) { - var value = Blockly.JavaScript.valueToCode(block, 'VALUE', - Blockly.JavaScript.ORDER_NONE) || 'null'; - code += ' return ' + value + ';\n'; - } else { - code += ' return;\n'; - } - code += '}\n'; - return code; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/javascript/text.js b/backend/_pv_1_3_5/static/blockly/generators/javascript/text.js deleted file mode 100755 index 9ecfdc387..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/javascript/text.js +++ /dev/null @@ -1,304 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating JavaScript for text blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.JavaScript.texts'); - -goog.require('Blockly.JavaScript'); - - -Blockly.JavaScript['text'] = function(block) { - // Text value. - var code = Blockly.JavaScript.quote_(block.getFieldValue('TEXT')); - return [code, Blockly.JavaScript.ORDER_ATOMIC]; -}; - -Blockly.JavaScript['text_join'] = function(block) { - // Create a string made up of any number of elements of any type. - switch (block.itemCount_) { - case 0: - return ['\'\'', Blockly.JavaScript.ORDER_ATOMIC]; - case 1: - var element = Blockly.JavaScript.valueToCode(block, 'ADD0', - Blockly.JavaScript.ORDER_NONE) || '\'\''; - var code = 'String(' + element + ')'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; - case 2: - var element0 = Blockly.JavaScript.valueToCode(block, 'ADD0', - Blockly.JavaScript.ORDER_NONE) || '\'\''; - var element1 = Blockly.JavaScript.valueToCode(block, 'ADD1', - Blockly.JavaScript.ORDER_NONE) || '\'\''; - var code = 'String(' + element0 + ') + String(' + element1 + ')'; - return [code, Blockly.JavaScript.ORDER_ADDITION]; - default: - var elements = new Array(block.itemCount_); - for (var i = 0; i < block.itemCount_; i++) { - elements[i] = Blockly.JavaScript.valueToCode(block, 'ADD' + i, - Blockly.JavaScript.ORDER_COMMA) || '\'\''; - } - var code = '[' + elements.join(',') + '].join(\'\')'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; - } -}; - -Blockly.JavaScript['text_append'] = function(block) { - // Append to a variable in place. - var varName = Blockly.JavaScript.variableDB_.getName( - block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); - var value = Blockly.JavaScript.valueToCode(block, 'TEXT', - Blockly.JavaScript.ORDER_NONE) || '\'\''; - return varName + ' = String(' + varName + ') + String(' + value + ');\n'; -}; - -Blockly.JavaScript['text_length'] = function(block) { - // String or array length. - var text = Blockly.JavaScript.valueToCode(block, 'VALUE', - Blockly.JavaScript.ORDER_FUNCTION_CALL) || '\'\''; - return [text + '.length', Blockly.JavaScript.ORDER_MEMBER]; -}; - -Blockly.JavaScript['text_isEmpty'] = function(block) { - // Is the string null or array empty? - var text = Blockly.JavaScript.valueToCode(block, 'VALUE', - Blockly.JavaScript.ORDER_MEMBER) || '\'\''; - return ['!' + text + '.length', Blockly.JavaScript.ORDER_LOGICAL_NOT]; -}; - -Blockly.JavaScript['text_indexOf'] = function(block) { - // Search the text for a substring. - var operator = block.getFieldValue('END') == 'FIRST' ? - 'indexOf' : 'lastIndexOf'; - var substring = Blockly.JavaScript.valueToCode(block, 'FIND', - Blockly.JavaScript.ORDER_NONE) || '\'\''; - var text = Blockly.JavaScript.valueToCode(block, 'VALUE', - Blockly.JavaScript.ORDER_MEMBER) || '\'\''; - var code = text + '.' + operator + '(' + substring + ')'; - // Adjust index if using one-based indices. - if (Blockly.JavaScript.ONE_BASED_INDEXING) { - return [code + ' + 1', Blockly.JavaScript.ORDER_ADDITION]; - } - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; -}; - -Blockly.JavaScript['text_charAt'] = function(block) { - // Get letter at index. - // Note: Until January 2013 this block did not have the WHERE input. - var where = block.getFieldValue('WHERE') || 'FROM_START'; - var textOrder = (where == 'RANDOM') ? Blockly.JavaScript.ORDER_NONE : - Blockly.JavaScript.ORDER_MEMBER; - var text = Blockly.JavaScript.valueToCode(block, 'VALUE', - textOrder) || '\'\''; - switch (where) { - case 'FIRST': - var code = text + '.charAt(0)'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; - case 'LAST': - var code = text + '.slice(-1)'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; - case 'FROM_START': - var at = Blockly.JavaScript.getAdjusted(block, 'AT'); - // Adjust index if using one-based indices. - var code = text + '.charAt(' + at + ')'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; - case 'FROM_END': - var at = Blockly.JavaScript.getAdjusted(block, 'AT', 1, true); - var code = text + '.slice(' + at + ').charAt(0)'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; - case 'RANDOM': - var functionName = Blockly.JavaScript.provideFunction_( - 'textRandomLetter', - ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + - '(text) {', - ' var x = Math.floor(Math.random() * text.length);', - ' return text[x];', - '}']); - var code = functionName + '(' + text + ')'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; - } - throw 'Unhandled option (text_charAt).'; -}; - -/** - * Returns an expression calculating the index into a string. - * @private - * @param {string} stringName Name of the string, used to calculate length. - * @param {string} where The method of indexing, selected by dropdown in Blockly - * @param {string=} opt_at The optional offset when indexing from start/end. - * @return {string} Index expression. - */ -Blockly.JavaScript.text.getIndex_ = function(stringName, where, opt_at) { - if (where == 'FIRST') { - return '0'; - } else if (where == 'FROM_END') { - return stringName + '.length - 1 - ' + opt_at; - } else if (where == 'LAST') { - return stringName + '.length - 1'; - } else { - return opt_at; - } -}; - -Blockly.JavaScript['text_getSubstring'] = function(block) { - // Get substring. - var text = Blockly.JavaScript.valueToCode(block, 'STRING', - Blockly.JavaScript.ORDER_FUNCTION_CALL) || '\'\''; - var where1 = block.getFieldValue('WHERE1'); - var where2 = block.getFieldValue('WHERE2'); - if (where1 == 'FIRST' && where2 == 'LAST') { - var code = text; - } else if (text.match(/^'?\w+'?$/) || - (where1 != 'FROM_END' && where1 != 'LAST' && - where2 != 'FROM_END' && where2 != 'LAST')) { - // If the text is a variable or literal or doesn't require a call for - // length, don't generate a helper function. - switch (where1) { - case 'FROM_START': - var at1 = Blockly.JavaScript.getAdjusted(block, 'AT1'); - break; - case 'FROM_END': - var at1 = Blockly.JavaScript.getAdjusted(block, 'AT1', 1, false, - Blockly.JavaScript.ORDER_SUBTRACTION); - at1 = text + '.length - ' + at1; - break; - case 'FIRST': - var at1 = '0'; - break; - default: - throw 'Unhandled option (text_getSubstring).'; - } - switch (where2) { - case 'FROM_START': - var at2 = Blockly.JavaScript.getAdjusted(block, 'AT2', 1); - break; - case 'FROM_END': - var at2 = Blockly.JavaScript.getAdjusted(block, 'AT2', 0, false, - Blockly.JavaScript.ORDER_SUBTRACTION); - at2 = text + '.length - ' + at2; - break; - case 'LAST': - var at2 = text + '.length'; - break; - default: - throw 'Unhandled option (text_getSubstring).'; - } - code = text + '.slice(' + at1 + ', ' + at2 + ')'; - } else { - var at1 = Blockly.JavaScript.getAdjusted(block, 'AT1'); - var at2 = Blockly.JavaScript.getAdjusted(block, 'AT2'); - var getIndex_ = Blockly.JavaScript.text.getIndex_; - var wherePascalCase = {'FIRST': 'First', 'LAST': 'Last', - 'FROM_START': 'FromStart', 'FROM_END': 'FromEnd'}; - var functionName = Blockly.JavaScript.provideFunction_( - 'subsequence' + wherePascalCase[where1] + wherePascalCase[where2], - ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + - '(sequence' + - // The value for 'FROM_END' and'FROM_START' depends on `at` so - // we add it as a parameter. - ((where1 == 'FROM_END' || where1 == 'FROM_START') ? ', at1' : '') + - ((where2 == 'FROM_END' || where2 == 'FROM_START') ? ', at2' : '') + - ') {', - ' var start = ' + getIndex_('sequence', where1, 'at1') + ';', - ' var end = ' + getIndex_('sequence', where2, 'at2') + ' + 1;', - ' return sequence.slice(start, end);', - '}']); - var code = functionName + '(' + text + - // The value for 'FROM_END' and 'FROM_START' depends on `at` so we - // pass it. - ((where1 == 'FROM_END' || where1 == 'FROM_START') ? ', ' + at1 : '') + - ((where2 == 'FROM_END' || where2 == 'FROM_START') ? ', ' + at2 : '') + - ')'; - } - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; -}; - -Blockly.JavaScript['text_changeCase'] = function(block) { - // Change capitalization. - var OPERATORS = { - 'UPPERCASE': '.toUpperCase()', - 'LOWERCASE': '.toLowerCase()', - 'TITLECASE': null - }; - var operator = OPERATORS[block.getFieldValue('CASE')]; - var textOrder = operator ? Blockly.JavaScript.ORDER_MEMBER : - Blockly.JavaScript.ORDER_NONE; - var text = Blockly.JavaScript.valueToCode(block, 'TEXT', - textOrder) || '\'\''; - if (operator) { - // Upper and lower case are functions built into JavaScript. - var code = text + operator; - } else { - // Title case is not a native JavaScript function. Define one. - var functionName = Blockly.JavaScript.provideFunction_( - 'textToTitleCase', - ['function ' + Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_ + - '(str) {', - ' return str.replace(/\\S+/g,', - ' function(txt) {return txt[0].toUpperCase() + ' + - 'txt.substring(1).toLowerCase();});', - '}']); - var code = functionName + '(' + text + ')'; - } - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; -}; - -Blockly.JavaScript['text_trim'] = function(block) { - // Trim spaces. - var OPERATORS = { - 'LEFT': ".replace(/^[\\s\\xa0]+/, '')", - 'RIGHT': ".replace(/[\\s\\xa0]+$/, '')", - 'BOTH': '.trim()' - }; - var operator = OPERATORS[block.getFieldValue('MODE')]; - var text = Blockly.JavaScript.valueToCode(block, 'TEXT', - Blockly.JavaScript.ORDER_MEMBER) || '\'\''; - return [text + operator, Blockly.JavaScript.ORDER_FUNCTION_CALL]; -}; - -Blockly.JavaScript['text_print'] = function(block) { - // Print statement. - var msg = Blockly.JavaScript.valueToCode(block, 'TEXT', - Blockly.JavaScript.ORDER_NONE) || '\'\''; - return 'window.alert(' + msg + ');\n'; -}; - -Blockly.JavaScript['text_prompt_ext'] = function(block) { - // Prompt function. - if (block.getField('TEXT')) { - // Internal message. - var msg = Blockly.JavaScript.quote_(block.getFieldValue('TEXT')); - } else { - // External message. - var msg = Blockly.JavaScript.valueToCode(block, 'TEXT', - Blockly.JavaScript.ORDER_NONE) || '\'\''; - } - var code = 'window.prompt(' + msg + ')'; - var toNumber = block.getFieldValue('TYPE') == 'NUMBER'; - if (toNumber) { - code = 'parseFloat(' + code + ')'; - } - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; -}; - -Blockly.JavaScript['text_prompt'] = Blockly.JavaScript['text_prompt_ext']; diff --git a/backend/_pv_1_3_5/static/blockly/generators/javascript/variables.js b/backend/_pv_1_3_5/static/blockly/generators/javascript/variables.js deleted file mode 100755 index fe0135b12..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/javascript/variables.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating JavaScript for variable blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.JavaScript.variables'); - -goog.require('Blockly.JavaScript'); - - -Blockly.JavaScript['variables_get'] = function(block) { - // Variable getter. - var code = Blockly.JavaScript.variableDB_.getName(block.getFieldValue('VAR'), - Blockly.Variables.NAME_TYPE); - return [code, Blockly.JavaScript.ORDER_ATOMIC]; -}; - -Blockly.JavaScript['variables_set'] = function(block) { - // Variable setter. - var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE', - Blockly.JavaScript.ORDER_ASSIGNMENT) || '0'; - var varName = Blockly.JavaScript.variableDB_.getName( - block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); - return varName + ' = ' + argument0 + ';\n'; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/lua.js b/backend/_pv_1_3_5/static/blockly/generators/lua.js deleted file mode 100755 index 225489641..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/lua.js +++ /dev/null @@ -1,194 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Helper functions for generating Lua for blocks. - * @author rodrigoq@google.com (Rodrigo Queiro) - * Based on Ellen Spertus's blocky-lua project. - */ -'use strict'; - -goog.provide('Blockly.Lua'); - -goog.require('Blockly.Generator'); - - -/** - * Lua code generator. - * @type {!Blockly.Generator} - */ -Blockly.Lua = new Blockly.Generator('Lua'); - -/** - * List of illegal variable names. - * This is not intended to be a security feature. Blockly is 100% client-side, - * so bypassing this list is trivial. This is intended to prevent users from - * accidentally clobbering a built-in object or function. - * @private - */ -Blockly.Lua.addReservedWords( - // Special character - '_,' + - // From theoriginalbit's script: - // https://github.com/espertus/blockly-lua/issues/6 - '__inext,assert,bit,colors,colours,coroutine,disk,dofile,error,fs,' + - 'fetfenv,getmetatable,gps,help,io,ipairs,keys,loadfile,loadstring,math,' + - 'native,next,os,paintutils,pairs,parallel,pcall,peripheral,print,' + - 'printError,rawequal,rawget,rawset,read,rednet,redstone,rs,select,' + - 'setfenv,setmetatable,sleep,string,table,term,textutils,tonumber,' + - 'tostring,turtle,type,unpack,vector,write,xpcall,_VERSION,__indext,' + - // Not included in the script, probably because it wasn't enabled: - 'HTTP,' + - // Keywords (http://www.lua.org/pil/1.3.html). - 'and,break,do,else,elseif,end,false,for,function,if,in,local,nil,not,or,' + - 'repeat,return,then,true,until,while,' + - // Metamethods (http://www.lua.org/manual/5.2/manual.html). - 'add,sub,mul,div,mod,pow,unm,concat,len,eq,lt,le,index,newindex,call,' + - // Basic functions (http://www.lua.org/manual/5.2/manual.html, section 6.1). - 'assert,collectgarbage,dofile,error,_G,getmetatable,inpairs,load,' + - 'loadfile,next,pairs,pcall,print,rawequal,rawget,rawlen,rawset,select,' + - 'setmetatable,tonumber,tostring,type,_VERSION,xpcall,' + - // Modules (http://www.lua.org/manual/5.2/manual.html, section 6.3). - 'require,package,string,table,math,bit32,io,file,os,debug' -); - -/** - * Order of operation ENUMs. - * http://www.lua.org/manual/5.3/manual.html#3.4.8 - */ -Blockly.Lua.ORDER_ATOMIC = 0; // literals -// The next level was not explicit in documentation and inferred by Ellen. -Blockly.Lua.ORDER_HIGH = 1; // Function calls, tables[] -Blockly.Lua.ORDER_EXPONENTIATION = 2; // ^ -Blockly.Lua.ORDER_UNARY = 3; // not # - ~ -Blockly.Lua.ORDER_MULTIPLICATIVE = 4; // * / % -Blockly.Lua.ORDER_ADDITIVE = 5; // + - -Blockly.Lua.ORDER_CONCATENATION = 6; // .. -Blockly.Lua.ORDER_RELATIONAL = 7; // < > <= >= ~= == -Blockly.Lua.ORDER_AND = 8; // and -Blockly.Lua.ORDER_OR = 9; // or -Blockly.Lua.ORDER_NONE = 99; - -/** - * Lua is not supporting zero-indexing since the language itself is one-indexed, - * so there is not flag for ONE_BASED_INDEXING to indicate which indexing is - * used for lists and text. - */ - -/** - * Initialise the database of variable names. - * @param {!Blockly.Workspace} workspace Workspace to generate code from. - */ -Blockly.Lua.init = function(workspace) { - // Create a dictionary of definitions to be printed before the code. - Blockly.Lua.definitions_ = Object.create(null); - // Create a dictionary mapping desired function names in definitions_ - // to actual function names (to avoid collisions with user functions). - Blockly.Lua.functionNames_ = Object.create(null); - - if (!Blockly.Lua.variableDB_) { - Blockly.Lua.variableDB_ = - new Blockly.Names(Blockly.Lua.RESERVED_WORDS_); - } else { - Blockly.Lua.variableDB_.reset(); - } -}; - -/** - * Prepend the generated code with the variable definitions. - * @param {string} code Generated code. - * @return {string} Completed code. - */ -Blockly.Lua.finish = function(code) { - // Convert the definitions dictionary into a list. - var definitions = []; - for (var name in Blockly.Lua.definitions_) { - definitions.push(Blockly.Lua.definitions_[name]); - } - // Clean up temporary data. - delete Blockly.Lua.definitions_; - delete Blockly.Lua.functionNames_; - Blockly.Lua.variableDB_.reset(); - return definitions.join('\n\n') + '\n\n\n' + code; -}; - -/** - * Naked values are top-level blocks with outputs that aren't plugged into - * anything. In Lua, an expression is not a legal statement, so we must assign - * the value to the (conventionally ignored) _. - * http://lua-users.org/wiki/ExpressionsAsStatements - * @param {string} line Line of generated code. - * @return {string} Legal line of code. - */ -Blockly.Lua.scrubNakedValue = function(line) { - return 'local _ = ' + line + '\n'; -}; - -/** - * Encode a string as a properly escaped Lua string, complete with - * quotes. - * @param {string} string Text to encode. - * @return {string} Lua string. - * @private - */ -Blockly.Lua.quote_ = function(string) { - string = string.replace(/\\/g, '\\\\') - .replace(/\n/g, '\\\n') - .replace(/'/g, '\\\''); - return '\'' + string + '\''; -}; - -/** - * Common tasks for generating Lua from blocks. - * Handles comments for the specified block and any connected value blocks. - * Calls any statements following this block. - * @param {!Blockly.Block} block The current block. - * @param {string} code The Lua code created for this block. - * @return {string} Lua code with comments and subsequent blocks added. - * @private - */ -Blockly.Lua.scrub_ = function(block, code) { - var commentCode = ''; - // Only collect comments for blocks that aren't inline. - if (!block.outputConnection || !block.outputConnection.targetConnection) { - // Collect comment for this block. - var comment = block.getCommentText(); - comment = Blockly.utils.wrap(comment, Blockly.Lua.COMMENT_WRAP - 3); - if (comment) { - commentCode += Blockly.Lua.prefixLines(comment, '-- ') + '\n'; - } - // Collect comments for all value arguments. - // Don't collect comments for nested statements. - for (var i = 0; i < block.inputList.length; i++) { - if (block.inputList[i].type == Blockly.INPUT_VALUE) { - var childBlock = block.inputList[i].connection.targetBlock(); - if (childBlock) { - comment = Blockly.Lua.allNestedComments(childBlock); - if (comment) { - commentCode += Blockly.Lua.prefixLines(comment, '-- '); - } - } - } - } - } - var nextBlock = block.nextConnection && block.nextConnection.targetBlock(); - var nextCode = Blockly.Lua.blockToCode(nextBlock); - return commentCode + code + nextCode; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/lua/colour.js b/backend/_pv_1_3_5/static/blockly/generators/lua/colour.js deleted file mode 100755 index 9175a9de9..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/lua/colour.js +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Lua for colour blocks. - * @author rodrigoq@google.com (Rodrigo Queiro) - */ -'use strict'; - -goog.provide('Blockly.Lua.colour'); - -goog.require('Blockly.Lua'); - - -Blockly.Lua['colour_picker'] = function(block) { - // Colour picker. - var code = '\'' + block.getFieldValue('COLOUR') + '\''; - return [code, Blockly.Lua.ORDER_ATOMIC]; -}; - -Blockly.Lua['colour_random'] = function(block) { - // Generate a random colour. - var code = 'string.format("#%06x", math.random(0, 2^24 - 1))'; - return [code, Blockly.Lua.ORDER_HIGH]; -}; - -Blockly.Lua['colour_rgb'] = function(block) { - // Compose a colour from RGB components expressed as percentages. - var functionName = Blockly.Lua.provideFunction_( - 'colour_rgb', - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(r, g, b)', - ' r = math.floor(math.min(100, math.max(0, r)) * 2.55 + .5)', - ' g = math.floor(math.min(100, math.max(0, g)) * 2.55 + .5)', - ' b = math.floor(math.min(100, math.max(0, b)) * 2.55 + .5)', - ' return string.format("#%02x%02x%02x", r, g, b)', - 'end']); - var r = Blockly.Lua.valueToCode(block, 'RED', - Blockly.Lua.ORDER_NONE) || 0; - var g = Blockly.Lua.valueToCode(block, 'GREEN', - Blockly.Lua.ORDER_NONE) || 0; - var b = Blockly.Lua.valueToCode(block, 'BLUE', - Blockly.Lua.ORDER_NONE) || 0; - var code = functionName + '(' + r + ', ' + g + ', ' + b + ')'; - return [code, Blockly.Lua.ORDER_HIGH]; -}; - -Blockly.Lua['colour_blend'] = function(block) { - // Blend two colours together. - var functionName = Blockly.Lua.provideFunction_( - 'colour_blend', - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + - '(colour1, colour2, ratio)', - ' local r1 = tonumber(string.sub(colour1, 2, 3), 16)', - ' local r2 = tonumber(string.sub(colour2, 2, 3), 16)', - ' local g1 = tonumber(string.sub(colour1, 4, 5), 16)', - ' local g2 = tonumber(string.sub(colour2, 4, 5), 16)', - ' local b1 = tonumber(string.sub(colour1, 6, 7), 16)', - ' local b2 = tonumber(string.sub(colour2, 6, 7), 16)', - ' local ratio = math.min(1, math.max(0, ratio))', - ' local r = math.floor(r1 * (1 - ratio) + r2 * ratio + .5)', - ' local g = math.floor(g1 * (1 - ratio) + g2 * ratio + .5)', - ' local b = math.floor(b1 * (1 - ratio) + b2 * ratio + .5)', - ' return string.format("#%02x%02x%02x", r, g, b)', - 'end']); - var colour1 = Blockly.Lua.valueToCode(block, 'COLOUR1', - Blockly.Lua.ORDER_NONE) || '\'#000000\''; - var colour2 = Blockly.Lua.valueToCode(block, 'COLOUR2', - Blockly.Lua.ORDER_NONE) || '\'#000000\''; - var ratio = Blockly.Lua.valueToCode(block, 'RATIO', - Blockly.Lua.ORDER_NONE) || 0; - var code = functionName + '(' + colour1 + ', ' + colour2 + ', ' + ratio + ')'; - return [code, Blockly.Lua.ORDER_HIGH]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/lua/lists.js b/backend/_pv_1_3_5/static/blockly/generators/lua/lists.js deleted file mode 100755 index 5b7711dbb..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/lua/lists.js +++ /dev/null @@ -1,365 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Lua for list blocks. - * @author rodrigoq@google.com (Rodrigo Queiro) - */ -'use strict'; - -goog.provide('Blockly.Lua.lists'); - -goog.require('Blockly.Lua'); - - -Blockly.Lua['lists_create_empty'] = function(block) { - // Create an empty list. - return ['{}', Blockly.Lua.ORDER_ATOMIC]; -}; - -Blockly.Lua['lists_create_with'] = function(block) { - // Create a list with any number of elements of any type. - var elements = new Array(block.itemCount_); - for (var i = 0; i < block.itemCount_; i++) { - elements[i] = Blockly.Lua.valueToCode(block, 'ADD' + i, - Blockly.Lua.ORDER_NONE) || 'None'; - } - var code = '{' + elements.join(', ') + '}'; - return [code, Blockly.Lua.ORDER_ATOMIC]; -}; - -Blockly.Lua['lists_repeat'] = function(block) { - // Create a list with one element repeated. - var functionName = Blockly.Lua.provideFunction_( - 'create_list_repeated', - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(item, count)', - ' local t = {}', - ' for i = 1, count do', - ' table.insert(t, item)', - ' end', - ' return t', - 'end']); - var element = Blockly.Lua.valueToCode(block, 'ITEM', - Blockly.Lua.ORDER_NONE) || 'None'; - var repeatCount = Blockly.Lua.valueToCode(block, 'NUM', - Blockly.Lua.ORDER_NONE) || '0'; - var code = functionName + '(' + element + ', ' + repeatCount + ')'; - return [code, Blockly.Lua.ORDER_HIGH]; -}; - -Blockly.Lua['lists_length'] = function(block) { - // String or array length. - var list = Blockly.Lua.valueToCode(block, 'VALUE', - Blockly.Lua.ORDER_UNARY) || '{}'; - return ['#' + list, Blockly.Lua.ORDER_UNARY]; -}; - -Blockly.Lua['lists_isEmpty'] = function(block) { - // Is the string null or array empty? - var list = Blockly.Lua.valueToCode(block, 'VALUE', - Blockly.Lua.ORDER_UNARY) || '{}'; - var code = '#' + list + ' == 0'; - return [code, Blockly.Lua.ORDER_RELATIONAL]; -}; - -Blockly.Lua['lists_indexOf'] = function(block) { - // Find an item in the list. - var item = Blockly.Lua.valueToCode(block, 'FIND', - Blockly.Lua.ORDER_NONE) || '\'\''; - var list = Blockly.Lua.valueToCode(block, 'VALUE', - Blockly.Lua.ORDER_NONE) || '{}'; - if (block.getFieldValue('END') == 'FIRST') { - var functionName = Blockly.Lua.provideFunction_( - 'first_index', - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t, elem)', - ' for k, v in ipairs(t) do', - ' if v == elem then', - ' return k', - ' end', - ' end', - ' return 0', - 'end']); - } else { - var functionName = Blockly.Lua.provideFunction_( - 'last_index', - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t, elem)', - ' for i = #t, 1, -1 do', - ' if t[i] == elem then', - ' return i', - ' end', - ' end', - ' return 0', - 'end']); - } - var code = functionName + '(' + list + ', ' + item + ')'; - return [code, Blockly.Lua.ORDER_HIGH]; -}; - -/** - * Returns an expression calculating the index into a list. - * @private - * @param {string} listName Name of the list, used to calculate length. - * @param {string} where The method of indexing, selected by dropdown in Blockly - * @param {string=} opt_at The optional offset when indexing from start/end. - * @return {string} Index expression. - */ -Blockly.Lua.lists.getIndex_ = function(listName, where, opt_at) { - if (where == 'FIRST') { - return '1'; - } else if (where == 'FROM_END') { - return '#' + listName + ' + 1 - ' + opt_at; - } else if (where == 'LAST') { - return '#' + listName; - } else if (where == 'RANDOM') { - return 'math.random(#' + listName + ')'; - } else { - return opt_at; - } -}; - -Blockly.Lua['lists_getIndex'] = function(block) { - // Get element at index. - // Note: Until January 2013 this block did not have MODE or WHERE inputs. - var mode = block.getFieldValue('MODE') || 'GET'; - var where = block.getFieldValue('WHERE') || 'FROM_START'; - var list = Blockly.Lua.valueToCode(block, 'VALUE', Blockly.Lua.ORDER_HIGH) || - '{}'; - var getIndex_ = Blockly.Lua.lists.getIndex_; - - // If `list` would be evaluated more than once (which is the case for LAST, - // FROM_END, and RANDOM) and is non-trivial, make sure to access it only once. - if ((where == 'LAST' || where == 'FROM_END' || where == 'RANDOM') && - !list.match(/^\w+$/)) { - // `list` is an expression, so we may not evaluate it more than once. - if (mode == 'REMOVE') { - // We can use multiple statements. - var atOrder = (where == 'FROM_END') ? Blockly.Lua.ORDER_ADDITIVE : - Blockly.Lua.ORDER_NONE; - var at = Blockly.Lua.valueToCode(block, 'AT', atOrder) || '1'; - var listVar = Blockly.Lua.variableDB_.getDistinctName( - 'tmp_list', Blockly.Variables.NAME_TYPE); - at = getIndex_(listVar, where, at); - var code = listVar + ' = ' + list + '\n' + - 'table.remove(' + listVar + ', ' + at + ')\n'; - return code; - } else { - // We need to create a procedure to avoid reevaluating values. - var at = Blockly.Lua.valueToCode(block, 'AT', Blockly.Lua.ORDER_NONE) || - '1'; - if (mode == 'GET') { - var functionName = Blockly.Lua.provideFunction_( - 'list_get_' + where.toLowerCase(), - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t' + - // The value for 'FROM_END' and'FROM_START' depends on `at` so - // we add it as a parameter. - ((where == 'FROM_END' || where == 'FROM_START') ? - ', at)' : ')'), - ' return t[' + getIndex_('t', where, 'at') + ']', - 'end']); - } else { // mode == 'GET_REMOVE' - var functionName = Blockly.Lua.provideFunction_( - 'list_remove_' + where.toLowerCase(), - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t' + - // The value for 'FROM_END' and'FROM_START' depends on `at` so - // we add it as a parameter. - ((where == 'FROM_END' || where == 'FROM_START') ? - ', at)' : ')'), - ' return table.remove(t, ' + getIndex_('t', where, 'at') + ')', - 'end']); - } - var code = functionName + '(' + list + - // The value for 'FROM_END' and 'FROM_START' depends on `at` so we - // pass it. - ((where == 'FROM_END' || where == 'FROM_START') ? ', ' + at : '') + - ')'; - return [code, Blockly.Lua.ORDER_HIGH]; - } - } else { - // Either `list` is a simple variable, or we only need to refer to `list` - // once. - var atOrder = (mode == 'GET' && where == 'FROM_END') ? - Blockly.Lua.ORDER_ADDITIVE : Blockly.Lua.ORDER_NONE; - var at = Blockly.Lua.valueToCode(block, 'AT', atOrder) || '1'; - at = getIndex_(list, where, at); - if (mode == 'GET') { - var code = list + '[' + at + ']'; - return [code, Blockly.Lua.ORDER_HIGH]; - } else { - var code = 'table.remove(' + list + ', ' + at + ')'; - if (mode == 'GET_REMOVE') { - return [code, Blockly.Lua.ORDER_HIGH]; - } else { // `mode` == 'REMOVE' - return code + '\n'; - } - } - } -}; - -Blockly.Lua['lists_setIndex'] = function(block) { - // Set element at index. - // Note: Until February 2013 this block did not have MODE or WHERE inputs. - var list = Blockly.Lua.valueToCode(block, 'LIST', - Blockly.Lua.ORDER_HIGH) || '{}'; - var mode = block.getFieldValue('MODE') || 'SET'; - var where = block.getFieldValue('WHERE') || 'FROM_START'; - var at = Blockly.Lua.valueToCode(block, 'AT', - Blockly.Lua.ORDER_ADDITIVE) || '1'; - var value = Blockly.Lua.valueToCode(block, 'TO', - Blockly.Lua.ORDER_NONE) || 'None'; - var getIndex_ = Blockly.Lua.lists.getIndex_; - - var code = ''; - // If `list` would be evaluated more than once (which is the case for LAST, - // FROM_END, and RANDOM) and is non-trivial, make sure to access it only once. - if ((where == 'LAST' || where == 'FROM_END' || where == 'RANDOM') && - !list.match(/^\w+$/)) { - // `list` is an expression, so we may not evaluate it more than once. - // We can use multiple statements. - var listVar = Blockly.Lua.variableDB_.getDistinctName( - 'tmp_list', Blockly.Variables.NAME_TYPE); - code = listVar + ' = ' + list + '\n'; - list = listVar; - } - if (mode == 'SET') { - code += list + '[' + getIndex_(list, where, at) + '] = ' + value; - } else { // `mode` == 'INSERT' - // LAST is a special case, because we want to insert - // *after* not *before*, the existing last element. - code += 'table.insert(' + list + ', ' + - (getIndex_(list, where, at) + (where == 'LAST' ? ' + 1' : '')) + - ', ' + value + ')'; - } - return code + '\n'; -}; - -Blockly.Lua['lists_getSublist'] = function(block) { - // Get sublist. - var list = Blockly.Lua.valueToCode(block, 'LIST', - Blockly.Lua.ORDER_NONE) || '{}'; - var where1 = block.getFieldValue('WHERE1'); - var where2 = block.getFieldValue('WHERE2'); - var at1 = Blockly.Lua.valueToCode(block, 'AT1', - Blockly.Lua.ORDER_NONE) || '1'; - var at2 = Blockly.Lua.valueToCode(block, 'AT2', - Blockly.Lua.ORDER_NONE) || '1'; - var getIndex_ = Blockly.Lua.lists.getIndex_; - - var functionName = Blockly.Lua.provideFunction_( - 'list_sublist_' + where1.toLowerCase() + '_' + where2.toLowerCase(), - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(source' + - // The value for 'FROM_END' and'FROM_START' depends on `at` so - // we add it as a parameter. - ((where1 == 'FROM_END' || where1 == 'FROM_START') ? ', at1' : '') + - ((where2 == 'FROM_END' || where2 == 'FROM_START') ? ', at2' : '') + - ')', - ' local t = {}', - ' local start = ' + getIndex_('source', where1, 'at1'), - ' local finish = ' + getIndex_('source', where2, 'at2'), - ' for i = start, finish do', - ' table.insert(t, source[i])', - ' end', - ' return t', - 'end']); - var code = functionName + '(' + list + - // The value for 'FROM_END' and 'FROM_START' depends on `at` so we - // pass it. - ((where1 == 'FROM_END' || where1 == 'FROM_START') ? ', ' + at1 : '') + - ((where2 == 'FROM_END' || where2 == 'FROM_START') ? ', ' + at2 : '') + - ')'; - return [code, Blockly.Lua.ORDER_HIGH]; -}; - -Blockly.Lua['lists_sort'] = function(block) { - // Block for sorting a list. - var list = Blockly.Lua.valueToCode( - block, 'LIST', Blockly.Lua.ORDER_NONE) || '{}'; - var direction = block.getFieldValue('DIRECTION') === '1' ? 1 : -1; - var type = block.getFieldValue('TYPE'); - - var functionName = Blockly.Lua.provideFunction_( - 'list_sort', - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + - '(list, typev, direction)', - ' local t = {}', - ' for n,v in pairs(list) do table.insert(t, v) end', // Shallow-copy. - ' local compareFuncs = {', - ' NUMERIC = function(a, b)', - ' return (tonumber(tostring(a)) or 0)', - ' < (tonumber(tostring(b)) or 0) end,', - ' TEXT = function(a, b)', - ' return tostring(a) < tostring(b) end,', - ' IGNORE_CASE = function(a, b)', - ' return string.lower(tostring(a)) < string.lower(tostring(b)) end', - ' }', - ' local compareTemp = compareFuncs[typev]', - ' local compare = compareTemp', - ' if direction == -1', - ' then compare = function(a, b) return compareTemp(b, a) end', - ' end', - ' table.sort(t, compare)', - ' return t', - 'end']); - - var code = functionName + - '(' + list + ',"' + type + '", ' + direction + ')'; - return [code, Blockly.Lua.ORDER_HIGH]; -}; - -Blockly.Lua['lists_split'] = function(block) { - // Block for splitting text into a list, or joining a list into text. - var input = Blockly.Lua.valueToCode(block, 'INPUT', - Blockly.Lua.ORDER_NONE); - var delimiter = Blockly.Lua.valueToCode(block, 'DELIM', - Blockly.Lua.ORDER_NONE) || '\'\''; - var mode = block.getFieldValue('MODE'); - var functionName; - if (mode == 'SPLIT') { - if (!input) { - input = '\'\''; - } - functionName = Blockly.Lua.provideFunction_( - 'list_string_split', - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + - '(input, delim)', - ' local t = {}', - ' local pos = 1', - ' while true do', - ' next_delim = string.find(input, delim, pos)', - ' if next_delim == nil then', - ' table.insert(t, string.sub(input, pos))', - ' break', - ' else', - ' table.insert(t, string.sub(input, pos, next_delim-1))', - ' pos = next_delim + #delim', - ' end', - ' end', - ' return t', - 'end']); - } else if (mode == 'JOIN') { - if (!input) { - input = '{}'; - } - functionName = 'table.concat'; - } else { - throw 'Unknown mode: ' + mode; - } - var code = functionName + '(' + input + ', ' + delimiter + ')'; - return [code, Blockly.Lua.ORDER_HIGH]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/lua/logic.js b/backend/_pv_1_3_5/static/blockly/generators/lua/logic.js deleted file mode 100755 index cc3c5a95c..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/lua/logic.js +++ /dev/null @@ -1,125 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Lua for logic blocks. - * @author rodrigoq@google.com (Rodrigo Queiro) - */ -'use strict'; - -goog.provide('Blockly.Lua.logic'); - -goog.require('Blockly.Lua'); - - -Blockly.Lua['controls_if'] = function(block) { - // If/elseif/else condition. - var n = 0; - var argument = Blockly.Lua.valueToCode(block, 'IF' + n, - Blockly.Lua.ORDER_NONE) || 'false'; - var branch = Blockly.Lua.statementToCode(block, 'DO' + n); - var code = 'if ' + argument + ' then\n' + branch; - for (n = 1; n <= block.elseifCount_; n++) { - argument = Blockly.Lua.valueToCode(block, 'IF' + n, - Blockly.Lua.ORDER_NONE) || 'false'; - branch = Blockly.Lua.statementToCode(block, 'DO' + n); - code += ' elseif ' + argument + ' then\n' + branch; - } - if (block.elseCount_) { - branch = Blockly.Lua.statementToCode(block, 'ELSE'); - code += ' else\n' + branch; - } - return code + 'end\n'; -}; - -Blockly.Lua['logic_compare'] = function(block) { - // Comparison operator. - var OPERATORS = { - 'EQ': '==', - 'NEQ': '~=', - 'LT': '<', - 'LTE': '<=', - 'GT': '>', - 'GTE': '>=' - }; - var operator = OPERATORS[block.getFieldValue('OP')]; - var argument0 = Blockly.Lua.valueToCode(block, 'A', - Blockly.Lua.ORDER_RELATIONAL) || '0'; - var argument1 = Blockly.Lua.valueToCode(block, 'B', - Blockly.Lua.ORDER_RELATIONAL) || '0'; - var code = argument0 + ' ' + operator + ' ' + argument1; - return [code, Blockly.Lua.ORDER_RELATIONAL]; -}; - -Blockly.Lua['logic_operation'] = function(block) { - // Operations 'and', 'or'. - var operator = (block.getFieldValue('OP') == 'AND') ? 'and' : 'or'; - var order = (operator == 'and') ? Blockly.Lua.ORDER_AND : - Blockly.Lua.ORDER_OR; - var argument0 = Blockly.Lua.valueToCode(block, 'A', order); - var argument1 = Blockly.Lua.valueToCode(block, 'B', order); - if (!argument0 && !argument1) { - // If there are no arguments, then the return value is false. - argument0 = 'false'; - argument1 = 'false'; - } else { - // Single missing arguments have no effect on the return value. - var defaultArgument = (operator == 'and') ? 'true' : 'false'; - if (!argument0) { - argument0 = defaultArgument; - } - if (!argument1) { - argument1 = defaultArgument; - } - } - var code = argument0 + ' ' + operator + ' ' + argument1; - return [code, order]; -}; - -Blockly.Lua['logic_negate'] = function(block) { - // Negation. - var argument0 = Blockly.Lua.valueToCode(block, 'BOOL', - Blockly.Lua.ORDER_UNARY) || 'true'; - var code = 'not ' + argument0; - return [code, Blockly.Lua.ORDER_UNARY]; -}; - -Blockly.Lua['logic_boolean'] = function(block) { - // Boolean values true and false. - var code = (block.getFieldValue('BOOL') == 'TRUE') ? 'true' : 'false'; - return [code, Blockly.Lua.ORDER_ATOMIC]; -}; - -Blockly.Lua['logic_null'] = function(block) { - // Null data type. - return ['nil', Blockly.Lua.ORDER_ATOMIC]; -}; - -Blockly.Lua['logic_ternary'] = function(block) { - // Ternary operator. - var value_if = Blockly.Lua.valueToCode(block, 'IF', - Blockly.Lua.ORDER_AND) || 'false'; - var value_then = Blockly.Lua.valueToCode(block, 'THEN', - Blockly.Lua.ORDER_AND) || 'nil'; - var value_else = Blockly.Lua.valueToCode(block, 'ELSE', - Blockly.Lua.ORDER_OR) || 'nil'; - var code = value_if + ' and ' + value_then + ' or ' + value_else; - return [code, Blockly.Lua.ORDER_OR]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/lua/loops.js b/backend/_pv_1_3_5/static/blockly/generators/lua/loops.js deleted file mode 100755 index 785398ff7..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/lua/loops.js +++ /dev/null @@ -1,166 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Lua for loop blocks. - * @author rodrigoq@google.com (Rodrigo Queiro) - */ -'use strict'; - -goog.provide('Blockly.Lua.loops'); - -goog.require('Blockly.Lua'); - - -/** - * This is the text used to implement a
    continue
    . - * It is also used to recognise
    continue
    s in generated code so that - * the appropriate label can be put at the end of the loop body. - * @const {string} - */ -Blockly.Lua.CONTINUE_STATEMENT = 'goto continue\n'; - -/** - * If the loop body contains a "goto continue" statement, add a continue label - * to the loop body. Slightly inefficient, as continue labels will be generated - * in all outer loops, but this is safer than duplicating the logic of - * blockToCode. - * - * @param {string} branch Generated code of the loop body - * @return {string} Generated label or '' if unnecessary - */ -Blockly.Lua.addContinueLabel = function(branch) { - if (branch.indexOf(Blockly.Lua.CONTINUE_STATEMENT) > -1) { - return branch + Blockly.Lua.INDENT + '::continue::\n'; - } else { - return branch; - } -}; - -Blockly.Lua['controls_repeat'] = function(block) { - // Repeat n times (internal number). - var repeats = parseInt(block.getFieldValue('TIMES'), 10); - var branch = Blockly.Lua.statementToCode(block, 'DO') || ''; - branch = Blockly.Lua.addContinueLabel(branch); - var loopVar = Blockly.Lua.variableDB_.getDistinctName( - 'count', Blockly.Variables.NAME_TYPE); - var code = 'for ' + loopVar + ' = 1, ' + repeats + ' do\n' + branch + 'end\n'; - return code; -}; - -Blockly.Lua['controls_repeat_ext'] = function(block) { - // Repeat n times (external number). - var repeats = Blockly.Lua.valueToCode(block, 'TIMES', - Blockly.Lua.ORDER_NONE) || '0'; - if (Blockly.isNumber(repeats)) { - repeats = parseInt(repeats, 10); - } else { - repeats = 'math.floor(' + repeats + ')'; - } - var branch = Blockly.Lua.statementToCode(block, 'DO') || '\n'; - branch = Blockly.Lua.addContinueLabel(branch); - var loopVar = Blockly.Lua.variableDB_.getDistinctName( - 'count', Blockly.Variables.NAME_TYPE); - var code = 'for ' + loopVar + ' = 1, ' + repeats + ' do\n' + - branch + 'end\n'; - return code; -}; - -Blockly.Lua['controls_whileUntil'] = function(block) { - // Do while/until loop. - var until = block.getFieldValue('MODE') == 'UNTIL'; - var argument0 = Blockly.Lua.valueToCode(block, 'BOOL', - until ? Blockly.Lua.ORDER_UNARY : - Blockly.Lua.ORDER_NONE) || 'false'; - var branch = Blockly.Lua.statementToCode(block, 'DO') || '\n'; - branch = Blockly.Lua.addLoopTrap(branch, block.id); - branch = Blockly.Lua.addContinueLabel(branch); - if (until) { - argument0 = 'not ' + argument0; - } - return 'while ' + argument0 + ' do\n' + branch + 'end\n'; -}; - -Blockly.Lua['controls_for'] = function(block) { - // For loop. - var variable0 = Blockly.Lua.variableDB_.getName( - block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); - var startVar = Blockly.Lua.valueToCode(block, 'FROM', - Blockly.Lua.ORDER_NONE) || '0'; - var endVar = Blockly.Lua.valueToCode(block, 'TO', - Blockly.Lua.ORDER_NONE) || '0'; - var increment = Blockly.Lua.valueToCode(block, 'BY', - Blockly.Lua.ORDER_NONE) || '1'; - var branch = Blockly.Lua.statementToCode(block, 'DO') || '\n'; - branch = Blockly.Lua.addLoopTrap(branch, block.id); - branch = Blockly.Lua.addContinueLabel(branch); - var code = ''; - var incValue; - if (Blockly.isNumber(startVar) && Blockly.isNumber(endVar) && - Blockly.isNumber(increment)) { - // All arguments are simple numbers. - var up = parseFloat(startVar) <= parseFloat(endVar); - var step = Math.abs(parseFloat(increment)); - incValue = (up ? '' : '-') + step; - } else { - code = ''; - // Determine loop direction at start, in case one of the bounds - // changes during loop execution. - incValue = Blockly.Lua.variableDB_.getDistinctName( - variable0 + '_inc', Blockly.Variables.NAME_TYPE); - code += incValue + ' = '; - if (Blockly.isNumber(increment)) { - code += Math.abs(increment) + '\n'; - } else { - code += 'math.abs(' + increment + ')\n'; - } - code += 'if (' + startVar + ') > (' + endVar + ') then\n'; - code += Blockly.Lua.INDENT + incValue + ' = -' + incValue + '\n'; - code += 'end\n'; - } - code += 'for ' + variable0 + ' = ' + startVar + ', ' + endVar + - ', ' + incValue; - code += ' do\n' + branch + 'end\n'; - return code; -}; - -Blockly.Lua['controls_forEach'] = function(block) { - // For each loop. - var variable0 = Blockly.Lua.variableDB_.getName( - block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); - var argument0 = Blockly.Lua.valueToCode(block, 'LIST', - Blockly.Lua.ORDER_NONE) || '{}'; - var branch = Blockly.Lua.statementToCode(block, 'DO') || '\n'; - branch = Blockly.Lua.addContinueLabel(branch); - var code = 'for _, ' + variable0 + ' in ipairs(' + argument0 + ') do \n' + - branch + 'end\n'; - return code; -}; - -Blockly.Lua['controls_flow_statements'] = function(block) { - // Flow statements: continue, break. - switch (block.getFieldValue('FLOW')) { - case 'BREAK': - return 'break\n'; - case 'CONTINUE': - return Blockly.Lua.CONTINUE_STATEMENT; - } - throw 'Unknown flow statement.'; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/lua/math.js b/backend/_pv_1_3_5/static/blockly/generators/lua/math.js deleted file mode 100755 index c104bfc16..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/lua/math.js +++ /dev/null @@ -1,425 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Lua for math blocks. - * @author rodrigoq@google.com (Rodrigo Queiro) - */ -'use strict'; - -goog.provide('Blockly.Lua.math'); - -goog.require('Blockly.Lua'); - - -Blockly.Lua['math_number'] = function(block) { - // Numeric value. - var code = parseFloat(block.getFieldValue('NUM')); - var order = code < 0 ? Blockly.Lua.ORDER_UNARY : - Blockly.Lua.ORDER_ATOMIC; - return [code, order]; -}; - -Blockly.Lua['math_arithmetic'] = function(block) { - // Basic arithmetic operators, and power. - var OPERATORS = { - ADD: [' + ', Blockly.Lua.ORDER_ADDITIVE], - MINUS: [' - ', Blockly.Lua.ORDER_ADDITIVE], - MULTIPLY: [' * ', Blockly.Lua.ORDER_MULTIPLICATIVE], - DIVIDE: [' / ', Blockly.Lua.ORDER_MULTIPLICATIVE], - POWER: [' ^ ', Blockly.Lua.ORDER_EXPONENTIATION] - }; - var tuple = OPERATORS[block.getFieldValue('OP')]; - var operator = tuple[0]; - var order = tuple[1]; - var argument0 = Blockly.Lua.valueToCode(block, 'A', order) || '0'; - var argument1 = Blockly.Lua.valueToCode(block, 'B', order) || '0'; - var code = argument0 + operator + argument1; - return [code, order]; -}; - -Blockly.Lua['math_single'] = function(block) { - // Math operators with single operand. - var operator = block.getFieldValue('OP'); - var code; - var arg; - if (operator == 'NEG') { - // Negation is a special case given its different operator precedence. - arg = Blockly.Lua.valueToCode(block, 'NUM', - Blockly.Lua.ORDER_UNARY) || '0'; - return ['-' + arg, Blockly.Lua.ORDER_UNARY]; - } - if (operator == 'SIN' || operator == 'COS' || operator == 'TAN') { - arg = Blockly.Lua.valueToCode(block, 'NUM', - Blockly.Lua.ORDER_MULTIPLICATIVE) || '0'; - } else { - arg = Blockly.Lua.valueToCode(block, 'NUM', - Blockly.Lua.ORDER_NONE) || '0'; - } - switch (operator) { - case 'ABS': - code = 'math.abs(' + arg + ')'; - break; - case 'ROOT': - code = 'math.sqrt(' + arg + ')'; - break; - case 'LN': - code = 'math.log(' + arg + ')'; - break; - case 'LOG10': - code = 'math.log10(' + arg + ')'; - break; - case 'EXP': - code = 'math.exp(' + arg + ')'; - break; - case 'POW10': - code = 'math.pow(10,' + arg + ')'; - break; - case 'ROUND': - // This rounds up. Blockly does not specify rounding direction. - code = 'math.floor(' + arg + ' + .5)'; - break; - case 'ROUNDUP': - code = 'math.ceil(' + arg + ')'; - break; - case 'ROUNDDOWN': - code = 'math.floor(' + arg + ')'; - break; - case 'SIN': - code = 'math.sin(math.rad(' + arg + '))'; - break; - case 'COS': - code = 'math.cos(math.rad(' + arg + '))'; - break; - case 'TAN': - code = 'math.tan(math.rad(' + arg + '))'; - break; - case 'ASIN': - code = 'math.deg(math.asin(' + arg + '))'; - break; - case 'ACOS': - code = 'math.deg(math.acos(' + arg + '))'; - break; - case 'ATAN': - code = 'math.deg(math.atan(' + arg + '))'; - break; - default: - throw 'Unknown math operator: ' + operator; - } - return [code, Blockly.Lua.ORDER_HIGH]; -}; - -Blockly.Lua['math_constant'] = function(block) { - // Constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY. - var CONSTANTS = { - PI: ['math.pi', Blockly.Lua.ORDER_HIGH], - E: ['math.exp(1)', Blockly.Lua.ORDER_HIGH], - GOLDEN_RATIO: ['(1 + math.sqrt(5)) / 2', Blockly.Lua.ORDER_MULTIPLICATIVE], - SQRT2: ['math.sqrt(2)', Blockly.Lua.ORDER_HIGH], - SQRT1_2: ['math.sqrt(1 / 2)', Blockly.Lua.ORDER_HIGH], - INFINITY: ['math.huge', Blockly.Lua.ORDER_HIGH] - }; - return CONSTANTS[block.getFieldValue('CONSTANT')]; -}; - -Blockly.Lua['math_number_property'] = function(block) { - // Check if a number is even, odd, prime, whole, positive, or negative - // or if it is divisible by certain number. Returns true or false. - var number_to_check = Blockly.Lua.valueToCode(block, 'NUMBER_TO_CHECK', - Blockly.Lua.ORDER_MULTIPLICATIVE) || '0'; - var dropdown_property = block.getFieldValue('PROPERTY'); - var code; - if (dropdown_property == 'PRIME') { - // Prime is a special case as it is not a one-liner test. - var functionName = Blockly.Lua.provideFunction_( - 'math_isPrime', - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(n)', - ' -- https://en.wikipedia.org/wiki/Primality_test#Naive_methods', - ' if n == 2 or n == 3 then', - ' return true', - ' end', - ' -- False if n is NaN, negative, is 1, or not whole.', - ' -- And false if n is divisible by 2 or 3.', - ' if not(n > 1) or n % 1 ~= 0 or n % 2 == 0 or n % 3 == 0 then', - ' return false', - ' end', - ' -- Check all the numbers of form 6k +/- 1, up to sqrt(n).', - ' for x = 6, math.sqrt(n) + 1.5, 6 do', - ' if n % (x - 1) == 0 or n % (x + 1) == 0 then', - ' return false', - ' end', - ' end', - ' return true', - 'end']); - code = functionName + '(' + number_to_check + ')'; - return [code, Blockly.Lua.ORDER_HIGH]; - } - switch (dropdown_property) { - case 'EVEN': - code = number_to_check + ' % 2 == 0'; - break; - case 'ODD': - code = number_to_check + ' % 2 == 1'; - break; - case 'WHOLE': - code = number_to_check + ' % 1 == 0'; - break; - case 'POSITIVE': - code = number_to_check + ' > 0'; - break; - case 'NEGATIVE': - code = number_to_check + ' < 0'; - break; - case 'DIVISIBLE_BY': - var divisor = Blockly.Lua.valueToCode(block, 'DIVISOR', - Blockly.Lua.ORDER_MULTIPLICATIVE); - // If 'divisor' is some code that evals to 0, Lua will produce a nan. - // Let's produce nil if we can determine this at compile-time. - if (!divisor || divisor == '0') { - return ['nil', Blockly.Lua.ORDER_ATOMIC]; - } - // The normal trick to implement ?: with and/or doesn't work here: - // divisor == 0 and nil or number_to_check % divisor == 0 - // because nil is false, so allow a runtime failure. :-( - code = number_to_check + ' % ' + divisor + ' == 0'; - break; - } - return [code, Blockly.Lua.ORDER_RELATIONAL]; -}; - -Blockly.Lua['math_change'] = function(block) { - // Add to a variable in place. - var argument0 = Blockly.Lua.valueToCode(block, 'DELTA', - Blockly.Lua.ORDER_ADDITIVE) || '0'; - var varName = Blockly.Lua.variableDB_.getName( - block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); - return varName + ' = ' + varName + ' + ' + argument0 + '\n'; -}; - -// Rounding functions have a single operand. -Blockly.Lua['math_round'] = Blockly.Lua['math_single']; -// Trigonometry functions have a single operand. -Blockly.Lua['math_trig'] = Blockly.Lua['math_single']; - -Blockly.Lua['math_on_list'] = function(block) { - // Math functions for lists. - var func = block.getFieldValue('OP'); - var list = Blockly.Lua.valueToCode(block, 'LIST', - Blockly.Lua.ORDER_NONE) || '{}'; - var functionName; - - // Functions needed in more than one case. - function provideSum() { - return Blockly.Lua.provideFunction_( - 'math_sum', - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t)', - ' local result = 0', - ' for _, v in ipairs(t) do', - ' result = result + v', - ' end', - ' return result', - 'end']); - } - - switch (func) { - case 'SUM': - functionName = provideSum(); - break; - - case 'MIN': - // Returns 0 for the empty list. - functionName = Blockly.Lua.provideFunction_( - 'math_min', - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t)', - ' if #t == 0 then', - ' return 0', - ' end', - ' local result = math.huge', - ' for _, v in ipairs(t) do', - ' if v < result then', - ' result = v', - ' end', - ' end', - ' return result', - 'end']); - break; - - case 'AVERAGE': - // Returns 0 for the empty list. - functionName = Blockly.Lua.provideFunction_( - 'math_average', - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t)', - ' if #t == 0 then', - ' return 0', - ' end', - ' return ' + provideSum() + '(t) / #t', - 'end']); - break; - - case 'MAX': - // Returns 0 for the empty list. - functionName = Blockly.Lua.provideFunction_( - 'math_max', - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t)', - ' if #t == 0 then', - ' return 0', - ' end', - ' local result = -math.huge', - ' for _, v in ipairs(t) do', - ' if v > result then', - ' result = v', - ' end', - ' end', - ' return result', - 'end']); - break; - - case 'MEDIAN': - functionName = Blockly.Lua.provideFunction_( - 'math_median', - // This operation excludes non-numbers. - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t)', - ' -- Source: http://lua-users.org/wiki/SimpleStats', - ' if #t == 0 then', - ' return 0', - ' end', - ' local temp={}', - ' for _, v in ipairs(t) do', - ' if type(v) == "number" then', - ' table.insert(temp, v)', - ' end', - ' end', - ' table.sort(temp)', - ' if #temp % 2 == 0 then', - ' return (temp[#temp/2] + temp[(#temp/2)+1]) / 2', - ' else', - ' return temp[math.ceil(#temp/2)]', - ' end', - 'end']); - break; - - case 'MODE': - functionName = Blockly.Lua.provideFunction_( - 'math_modes', - // As a list of numbers can contain more than one mode, - // the returned result is provided as an array. - // The Lua version includes non-numbers. - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t)', - ' -- Source: http://lua-users.org/wiki/SimpleStats', - ' local counts={}', - ' for _, v in ipairs(t) do', - ' if counts[v] == nil then', - ' counts[v] = 1', - ' else', - ' counts[v] = counts[v] + 1', - ' end', - ' end', - ' local biggestCount = 0', - ' for _, v in pairs(counts) do', - ' if v > biggestCount then', - ' biggestCount = v', - ' end', - ' end', - ' local temp={}', - ' for k, v in pairs(counts) do', - ' if v == biggestCount then', - ' table.insert(temp, k)', - ' end', - ' end', - ' return temp', - 'end']); - break; - - case 'STD_DEV': - functionName = Blockly.Lua.provideFunction_( - 'math_standard_deviation', - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t)', - ' local m', - ' local vm', - ' local total = 0', - ' local count = 0', - ' local result', - ' m = #t == 0 and 0 or ' + provideSum() + '(t) / #t', - ' for _, v in ipairs(t) do', - " if type(v) == 'number' then", - ' vm = v - m', - ' total = total + (vm * vm)', - ' count = count + 1', - ' end', - ' end', - ' result = math.sqrt(total / (count-1))', - ' return result', - 'end']); - break; - - case 'RANDOM': - functionName = Blockly.Lua.provideFunction_( - 'math_random_list', - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(t)', - ' if #t == 0 then', - ' return nil', - ' end', - ' return t[math.random(#t)]', - 'end']); - break; - - default: - throw 'Unknown operator: ' + func; - } - return [functionName + '(' + list + ')', Blockly.Lua.ORDER_HIGH]; -}; - -Blockly.Lua['math_modulo'] = function(block) { - // Remainder computation. - var argument0 = Blockly.Lua.valueToCode(block, 'DIVIDEND', - Blockly.Lua.ORDER_MULTIPLICATIVE) || '0'; - var argument1 = Blockly.Lua.valueToCode(block, 'DIVISOR', - Blockly.Lua.ORDER_MULTIPLICATIVE) || '0'; - var code = argument0 + ' % ' + argument1; - return [code, Blockly.Lua.ORDER_MULTIPLICATIVE]; -}; - -Blockly.Lua['math_constrain'] = function(block) { - // Constrain a number between two limits. - var argument0 = Blockly.Lua.valueToCode(block, 'VALUE', - Blockly.Lua.ORDER_NONE) || '0'; - var argument1 = Blockly.Lua.valueToCode(block, 'LOW', - Blockly.Lua.ORDER_NONE) || '-math.huge'; - var argument2 = Blockly.Lua.valueToCode(block, 'HIGH', - Blockly.Lua.ORDER_NONE) || 'math.huge'; - var code = 'math.min(math.max(' + argument0 + ', ' + argument1 + '), ' + - argument2 + ')'; - return [code, Blockly.Lua.ORDER_HIGH]; -}; - -Blockly.Lua['math_random_int'] = function(block) { - // Random integer between [X] and [Y]. - var argument0 = Blockly.Lua.valueToCode(block, 'FROM', - Blockly.Lua.ORDER_NONE) || '0'; - var argument1 = Blockly.Lua.valueToCode(block, 'TO', - Blockly.Lua.ORDER_NONE) || '0'; - var code = 'math.random(' + argument0 + ', ' + argument1 + ')'; - return [code, Blockly.Lua.ORDER_HIGH]; -}; - -Blockly.Lua['math_random_float'] = function(block) { - // Random fraction between 0 and 1. - return ['math.random()', Blockly.Lua.ORDER_HIGH]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/lua/procedures.js b/backend/_pv_1_3_5/static/blockly/generators/lua/procedures.js deleted file mode 100755 index b6d6cdda1..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/lua/procedures.js +++ /dev/null @@ -1,111 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Lua for procedure blocks. - * @author rodrigoq@google.com (Rodrigo Queiro) - */ -'use strict'; - -goog.provide('Blockly.Lua.procedures'); - -goog.require('Blockly.Lua'); - - -Blockly.Lua['procedures_defreturn'] = function(block) { - // Define a procedure with a return value. - var funcName = Blockly.Lua.variableDB_.getName( - block.getFieldValue('NAME'), Blockly.Procedures.NAME_TYPE); - var branch = Blockly.Lua.statementToCode(block, 'STACK'); - if (Blockly.Lua.STATEMENT_PREFIX) { - branch = Blockly.Lua.prefixLines( - Blockly.Lua.STATEMENT_PREFIX.replace(/%1/g, - '\'' + block.id + '\''), Blockly.Lua.INDENT) + branch; - } - if (Blockly.Lua.INFINITE_LOOP_TRAP) { - branch = Blockly.Lua.INFINITE_LOOP_TRAP.replace(/%1/g, - '\'' + block.id + '\'') + branch; - } - var returnValue = Blockly.Lua.valueToCode(block, 'RETURN', - Blockly.Lua.ORDER_NONE) || ''; - if (returnValue) { - returnValue = ' return ' + returnValue + '\n'; - } else if (!branch) { - branch = ''; - } - var args = []; - for (var i = 0; i < block.arguments_.length; i++) { - args[i] = Blockly.Lua.variableDB_.getName(block.arguments_[i], - Blockly.Variables.NAME_TYPE); - } - var code = 'function ' + funcName + '(' + args.join(', ') + ')\n' + - branch + returnValue + 'end\n'; - code = Blockly.Lua.scrub_(block, code); - // Add % so as not to collide with helper functions in definitions list. - Blockly.Lua.definitions_['%' + funcName] = code; - return null; -}; - -// Defining a procedure without a return value uses the same generator as -// a procedure with a return value. -Blockly.Lua['procedures_defnoreturn'] = - Blockly.Lua['procedures_defreturn']; - -Blockly.Lua['procedures_callreturn'] = function(block) { - // Call a procedure with a return value. - var funcName = Blockly.Lua.variableDB_.getName( - block.getFieldValue('NAME'), Blockly.Procedures.NAME_TYPE); - var args = []; - for (var i = 0; i < block.arguments_.length; i++) { - args[i] = Blockly.Lua.valueToCode(block, 'ARG' + i, - Blockly.Lua.ORDER_NONE) || 'nil'; - } - var code = funcName + '(' + args.join(', ') + ')'; - return [code, Blockly.Lua.ORDER_HIGH]; -}; - -Blockly.Lua['procedures_callnoreturn'] = function(block) { - // Call a procedure with no return value. - var funcName = Blockly.Lua.variableDB_.getName( - block.getFieldValue('NAME'), Blockly.Procedures.NAME_TYPE); - var args = []; - for (var i = 0; i < block.arguments_.length; i++) { - args[i] = Blockly.Lua.valueToCode(block, 'ARG' + i, - Blockly.Lua.ORDER_NONE) || 'nil'; - } - var code = funcName + '(' + args.join(', ') + ')\n'; - return code; -}; - -Blockly.Lua['procedures_ifreturn'] = function(block) { - // Conditionally return value from a procedure. - var condition = Blockly.Lua.valueToCode(block, 'CONDITION', - Blockly.Lua.ORDER_NONE) || 'false'; - var code = 'if ' + condition + ' then\n'; - if (block.hasReturnValue_) { - var value = Blockly.Lua.valueToCode(block, 'VALUE', - Blockly.Lua.ORDER_NONE) || 'nil'; - code += ' return ' + value + '\n'; - } else { - code += ' return\n'; - } - code += 'end\n'; - return code; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/lua/text.js b/backend/_pv_1_3_5/static/blockly/generators/lua/text.js deleted file mode 100755 index 74efba4a2..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/lua/text.js +++ /dev/null @@ -1,294 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Lua for text blocks. - * @author rodrigoq@google.com (Rodrigo Queiro) - */ -'use strict'; - -goog.provide('Blockly.Lua.texts'); - -goog.require('Blockly.Lua'); - - -Blockly.Lua['text'] = function(block) { - // Text value. - var code = Blockly.Lua.quote_(block.getFieldValue('TEXT')); - return [code, Blockly.Lua.ORDER_ATOMIC]; -}; - -Blockly.Lua['text_join'] = function(block) { - // Create a string made up of any number of elements of any type. - if (block.itemCount_ == 0) { - return ['\'\'', Blockly.Lua.ORDER_ATOMIC]; - } else if (block.itemCount_ == 1) { - var element = Blockly.Lua.valueToCode(block, 'ADD0', - Blockly.Lua.ORDER_NONE) || '\'\''; - var code = 'tostring(' + element + ')'; - return [code, Blockly.Lua.ORDER_HIGH]; - } else if (block.itemCount_ == 2) { - var element0 = Blockly.Lua.valueToCode(block, 'ADD0', - Blockly.Lua.ORDER_CONCATENATION) || '\'\''; - var element1 = Blockly.Lua.valueToCode(block, 'ADD1', - Blockly.Lua.ORDER_CONCATENATION) || '\'\''; - var code = element0 + ' .. ' + element1; - return [code, Blockly.Lua.ORDER_CONCATENATION]; - } else { - var elements = []; - for (var i = 0; i < block.itemCount_; i++) { - elements[i] = Blockly.Lua.valueToCode(block, 'ADD' + i, - Blockly.Lua.ORDER_NONE) || '\'\''; - } - var code = 'table.concat({' + elements.join(', ') + '})'; - return [code, Blockly.Lua.ORDER_HIGH]; - } -}; - -Blockly.Lua['text_append'] = function(block) { - // Append to a variable in place. - var varName = Blockly.Lua.variableDB_.getName( - block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); - var value = Blockly.Lua.valueToCode(block, 'TEXT', - Blockly.Lua.ORDER_CONCATENATION) || '\'\''; - return varName + ' = ' + varName + ' .. ' + value + '\n'; -}; - -Blockly.Lua['text_length'] = function(block) { - // String or array length. - var text = Blockly.Lua.valueToCode(block, 'VALUE', - Blockly.Lua.ORDER_UNARY) || '\'\''; - return ['#' + text, Blockly.Lua.ORDER_UNARY]; -}; - -Blockly.Lua['text_isEmpty'] = function(block) { - // Is the string null or array empty? - var text = Blockly.Lua.valueToCode(block, 'VALUE', - Blockly.Lua.ORDER_UNARY) || '\'\''; - return ['#' + text + ' == 0', Blockly.Lua.ORDER_RELATIONAL]; -}; - -Blockly.Lua['text_indexOf'] = function(block) { - // Search the text for a substring. - var substring = Blockly.Lua.valueToCode(block, 'FIND', - Blockly.Lua.ORDER_NONE) || '\'\''; - var text = Blockly.Lua.valueToCode(block, 'VALUE', - Blockly.Lua.ORDER_NONE) || '\'\''; - if (block.getFieldValue('END') == 'FIRST') { - var functionName = Blockly.Lua.provideFunction_( - 'firstIndexOf', - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + - '(str, substr) ', - ' local i = string.find(str, substr, 1, true)', - ' if i == nil then', - ' return 0', - ' else', - ' return i', - ' end', - 'end']); - } else { - var functionName = Blockly.Lua.provideFunction_( - 'lastIndexOf', - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + - '(str, substr)', - ' local i = string.find(string.reverse(str), ' + - 'string.reverse(substr), 1, true)', - ' if i then', - ' return #str + 2 - i - #substr', - ' end', - ' return 0', - 'end']); - } - var code = functionName + '(' + text + ', ' + substring + ')'; - return [code, Blockly.Lua.ORDER_HIGH]; -}; - -Blockly.Lua['text_charAt'] = function(block) { - // Get letter at index. - // Note: Until January 2013 this block did not have the WHERE input. - var where = block.getFieldValue('WHERE') || 'FROM_START'; - var atOrder = (where == 'FROM_END') ? Blockly.Lua.ORDER_UNARY : - Blockly.Lua.ORDER_NONE; - var at = Blockly.Lua.valueToCode(block, 'AT', atOrder) || '1'; - var text = Blockly.Lua.valueToCode(block, 'VALUE', - Blockly.Lua.ORDER_NONE) || '\'\''; - var code; - if (where == 'RANDOM') { - var functionName = Blockly.Lua.provideFunction_( - 'text_random_letter', - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(str)', - ' local index = math.random(string.len(str))', - ' return string.sub(str, index, index)', - 'end']); - code = functionName + '(' + text + ')'; - } else { - if (where == 'FIRST') { - var start = '1'; - } else if (where == 'LAST') { - var start = '-1'; - } else { - if (where == 'FROM_START') { - var start = at; - } else if (where == 'FROM_END') { - var start = '-' + at; - } else { - throw 'Unhandled option (text_charAt).'; - } - } - if (start.match(/^-?\w*$/)) { - code = 'string.sub(' + text + ', ' + start + ', ' + start + ')'; - } else { - // use function to avoid reevaluation - var functionName = Blockly.Lua.provideFunction_( - 'text_char_at', - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + - '(str, index)', - ' return string.sub(str, index, index)', - 'end']); - code = functionName + '(' + text + ', ' + start + ')'; - } - } - return [code, Blockly.Lua.ORDER_HIGH]; -}; - -Blockly.Lua['text_getSubstring'] = function(block) { - // Get substring. - var text = Blockly.Lua.valueToCode(block, 'STRING', - Blockly.Lua.ORDER_NONE) || '\'\''; - - // Get start index. - var where1 = block.getFieldValue('WHERE1'); - var at1Order = (where1 == 'FROM_END') ? Blockly.Lua.ORDER_UNARY : - Blockly.Lua.ORDER_NONE; - var at1 = Blockly.Lua.valueToCode(block, 'AT1', at1Order) || '1'; - if (where1 == 'FIRST') { - var start = 1; - } else if (where1 == 'FROM_START') { - var start = at1; - } else if (where1 == 'FROM_END') { - var start = '-' + at1; - } else { - throw 'Unhandled option (text_getSubstring)'; - } - - // Get end index. - var where2 = block.getFieldValue('WHERE2'); - var at2Order = (where2 == 'FROM_END') ? Blockly.Lua.ORDER_UNARY : - Blockly.Lua.ORDER_NONE; - var at2 = Blockly.Lua.valueToCode(block, 'AT2', at2Order) || '1'; - if (where2 == 'LAST') { - var end = -1; - } else if (where2 == 'FROM_START') { - var end = at2; - } else if (where2 == 'FROM_END') { - var end = '-' + at2; - } else { - throw 'Unhandled option (text_getSubstring)'; - } - var code = 'string.sub(' + text + ', ' + start + ', ' + end + ')'; - return [code, Blockly.Lua.ORDER_HIGH]; -}; - -Blockly.Lua['text_changeCase'] = function(block) { - // Change capitalization. - var operator = block.getFieldValue('CASE'); - var text = Blockly.Lua.valueToCode(block, 'TEXT', - Blockly.Lua.ORDER_NONE) || '\'\''; - if (operator == 'UPPERCASE') { - var functionName = 'string.upper'; - } else if (operator == 'LOWERCASE') { - var functionName = 'string.lower'; - } else if (operator == 'TITLECASE') { - var functionName = Blockly.Lua.provideFunction_( - 'text_titlecase', - // There are shorter versions at - // http://lua-users.org/wiki/SciteTitleCase - // that do not preserve whitespace. - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(str)', - ' local buf = {}', - ' local inWord = false', - ' for i = 1, #str do', - ' local c = string.sub(str, i, i)', - ' if inWord then', - ' table.insert(buf, string.lower(c))', - ' if string.find(c, "%s") then', - ' inWord = false', - ' end', - ' else', - ' table.insert(buf, string.upper(c))', - ' inWord = true', - ' end', - ' end', - ' return table.concat(buf)', - 'end']); - } - var code = functionName + '(' + text + ')'; - return [code, Blockly.Lua.ORDER_HIGH]; -}; - -Blockly.Lua['text_trim'] = function(block) { - // Trim spaces. - var OPERATORS = { - LEFT: '^%s*(,-)', - RIGHT: '(.-)%s*$', - BOTH: '^%s*(.-)%s*$' - }; - var operator = OPERATORS[block.getFieldValue('MODE')]; - var text = Blockly.Lua.valueToCode(block, 'TEXT', - Blockly.Lua.ORDER_NONE) || '\'\''; - var code = 'string.gsub(' + text + ', "' + operator + '", "%1")'; - return [code, Blockly.Lua.ORDER_HIGH]; -}; - -Blockly.Lua['text_print'] = function(block) { - // Print statement. - var msg = Blockly.Lua.valueToCode(block, 'TEXT', - Blockly.Lua.ORDER_NONE) || '\'\''; - return 'print(' + msg + ')\n'; -}; - -Blockly.Lua['text_prompt_ext'] = function(block) { - // Prompt function. - if (block.getField('TEXT')) { - // Internal message. - var msg = Blockly.Lua.quote_(block.getFieldValue('TEXT')); - } else { - // External message. - var msg = Blockly.Lua.valueToCode(block, 'TEXT', - Blockly.Lua.ORDER_NONE) || '\'\''; - } - - var functionName = Blockly.Lua.provideFunction_( - 'text_prompt', - ['function ' + Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_ + '(msg)', - ' io.write(msg)', - ' io.flush()', - ' return io.read()', - 'end']); - var code = functionName + '(' + msg + ')'; - - var toNumber = block.getFieldValue('TYPE') == 'NUMBER'; - if (toNumber) { - code = 'tonumber(' + code + ', 10)'; - } - return [code, Blockly.Lua.ORDER_HIGH]; -}; - -Blockly.Lua['text_prompt'] = Blockly.Lua['text_prompt_ext']; diff --git a/backend/_pv_1_3_5/static/blockly/generators/lua/variables.js b/backend/_pv_1_3_5/static/blockly/generators/lua/variables.js deleted file mode 100755 index 10b53d1de..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/lua/variables.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2016 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Lua for variable blocks. - * @author rodrigoq@google.com (Rodrigo Queiro) - */ -'use strict'; - -goog.provide('Blockly.Lua.variables'); - -goog.require('Blockly.Lua'); - - -Blockly.Lua['variables_get'] = function(block) { - // Variable getter. - var code = Blockly.Lua.variableDB_.getName(block.getFieldValue('VAR'), - Blockly.Variables.NAME_TYPE); - return [code, Blockly.Lua.ORDER_ATOMIC]; -}; - -Blockly.Lua['variables_set'] = function(block) { - // Variable setter. - var argument0 = Blockly.Lua.valueToCode(block, 'VALUE', - Blockly.Lua.ORDER_NONE) || '0'; - var varName = Blockly.Lua.variableDB_.getName( - block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); - return varName + ' = ' + argument0 + '\n'; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/php.js b/backend/_pv_1_3_5/static/blockly/generators/php.js deleted file mode 100755 index 0543a439a..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/php.js +++ /dev/null @@ -1,308 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2015 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Helper functions for generating PHP for blocks. - * @author daarond@gmail.com (Daaron Dwyer) - */ -'use strict'; - -goog.provide('Blockly.PHP'); - -goog.require('Blockly.Generator'); - - -/** - * PHP code generator. - * @type {!Blockly.Generator} - */ -Blockly.PHP = new Blockly.Generator('PHP'); - -/** - * List of illegal variable names. - * This is not intended to be a security feature. Blockly is 100% client-side, - * so bypassing this list is trivial. This is intended to prevent users from - * accidentally clobbering a built-in object or function. - * @private - */ -Blockly.PHP.addReservedWords( - // http://php.net/manual/en/reserved.keywords.php - '__halt_compiler,abstract,and,array,as,break,callable,case,catch,class,' + - 'clone,const,continue,declare,default,die,do,echo,else,elseif,empty,' + - 'enddeclare,endfor,endforeach,endif,endswitch,endwhile,eval,exit,extends,' + - 'final,for,foreach,function,global,goto,if,implements,include,' + - 'include_once,instanceof,insteadof,interface,isset,list,namespace,new,or,' + - 'print,private,protected,public,require,require_once,return,static,' + - 'switch,throw,trait,try,unset,use,var,while,xor,' + - // http://php.net/manual/en/reserved.constants.php - 'PHP_VERSION,PHP_MAJOR_VERSION,PHP_MINOR_VERSION,PHP_RELEASE_VERSION,' + - 'PHP_VERSION_ID,PHP_EXTRA_VERSION,PHP_ZTS,PHP_DEBUG,PHP_MAXPATHLEN,' + - 'PHP_OS,PHP_SAPI,PHP_EOL,PHP_INT_MAX,PHP_INT_SIZE,DEFAULT_INCLUDE_PATH,' + - 'PEAR_INSTALL_DIR,PEAR_EXTENSION_DIR,PHP_EXTENSION_DIR,PHP_PREFIX,' + - 'PHP_BINDIR,PHP_BINARY,PHP_MANDIR,PHP_LIBDIR,PHP_DATADIR,PHP_SYSCONFDIR,' + - 'PHP_LOCALSTATEDIR,PHP_CONFIG_FILE_PATH,PHP_CONFIG_FILE_SCAN_DIR,' + - 'PHP_SHLIB_SUFFIX,E_ERROR,E_WARNING,E_PARSE,E_NOTICE,E_CORE_ERROR,' + - 'E_CORE_WARNING,E_COMPILE_ERROR,E_COMPILE_WARNING,E_USER_ERROR,' + - 'E_USER_WARNING,E_USER_NOTICE,E_DEPRECATED,E_USER_DEPRECATED,E_ALL,' + - 'E_STRICT,__COMPILER_HALT_OFFSET__,TRUE,FALSE,NULL,__CLASS__,__DIR__,' + - '__FILE__,__FUNCTION__,__LINE__,__METHOD__,__NAMESPACE__,__TRAIT__' -); - -/** - * Order of operation ENUMs. - * http://php.net/manual/en/language.operators.precedence.php - */ -Blockly.PHP.ORDER_ATOMIC = 0; // 0 "" ... -Blockly.PHP.ORDER_CLONE = 1; // clone -Blockly.PHP.ORDER_NEW = 1; // new -Blockly.PHP.ORDER_MEMBER = 2.1; // [] -Blockly.PHP.ORDER_FUNCTION_CALL = 2.2; // () -Blockly.PHP.ORDER_POWER = 3; // ** -Blockly.PHP.ORDER_INCREMENT = 4; // ++ -Blockly.PHP.ORDER_DECREMENT = 4; // -- -Blockly.PHP.ORDER_BITWISE_NOT = 4; // ~ -Blockly.PHP.ORDER_CAST = 4; // (int) (float) (string) (array) ... -Blockly.PHP.ORDER_SUPPRESS_ERROR = 4; // @ -Blockly.PHP.ORDER_INSTANCEOF = 5; // instanceof -Blockly.PHP.ORDER_LOGICAL_NOT = 6; // ! -Blockly.PHP.ORDER_UNARY_PLUS = 7.1; // + -Blockly.PHP.ORDER_UNARY_NEGATION = 7.2; // - -Blockly.PHP.ORDER_MULTIPLICATION = 8.1; // * -Blockly.PHP.ORDER_DIVISION = 8.2; // / -Blockly.PHP.ORDER_MODULUS = 8.3; // % -Blockly.PHP.ORDER_ADDITION = 9.1; // + -Blockly.PHP.ORDER_SUBTRACTION = 9.2; // - -Blockly.PHP.ORDER_STRING_CONCAT = 9.3; // . -Blockly.PHP.ORDER_BITWISE_SHIFT = 10; // << >> -Blockly.PHP.ORDER_RELATIONAL = 11; // < <= > >= -Blockly.PHP.ORDER_EQUALITY = 12; // == != === !== <> <=> -Blockly.PHP.ORDER_REFERENCE = 13; // & -Blockly.PHP.ORDER_BITWISE_AND = 13; // & -Blockly.PHP.ORDER_BITWISE_XOR = 14; // ^ -Blockly.PHP.ORDER_BITWISE_OR = 15; // | -Blockly.PHP.ORDER_LOGICAL_AND = 16; // && -Blockly.PHP.ORDER_LOGICAL_OR = 17; // || -Blockly.PHP.ORDER_IF_NULL = 18; // ?? -Blockly.PHP.ORDER_CONDITIONAL = 19; // ?: -Blockly.PHP.ORDER_ASSIGNMENT = 20; // = += -= *= /= %= <<= >>= ... -Blockly.PHP.ORDER_LOGICAL_AND_WEAK = 21; // and -Blockly.PHP.ORDER_LOGICAL_XOR = 22; // xor -Blockly.PHP.ORDER_LOGICAL_OR_WEAK = 23; // or -Blockly.PHP.ORDER_COMMA = 24; // , -Blockly.PHP.ORDER_NONE = 99; // (...) - -/** - * List of outer-inner pairings that do NOT require parentheses. - * @type {!Array.>} - */ -Blockly.PHP.ORDER_OVERRIDES = [ - // (foo()).bar() -> foo().bar() - // (foo())[0] -> foo()[0] - [Blockly.PHP.ORDER_MEMBER, Blockly.PHP.ORDER_FUNCTION_CALL], - // (foo[0])[1] -> foo[0][1] - // (foo.bar).baz -> foo.bar.baz - [Blockly.PHP.ORDER_MEMBER, Blockly.PHP.ORDER_MEMBER], - // !(!foo) -> !!foo - [Blockly.PHP.ORDER_LOGICAL_NOT, Blockly.PHP.ORDER_LOGICAL_NOT], - // a * (b * c) -> a * b * c - [Blockly.PHP.ORDER_MULTIPLICATION, Blockly.PHP.ORDER_MULTIPLICATION], - // a + (b + c) -> a + b + c - [Blockly.PHP.ORDER_ADDITION, Blockly.PHP.ORDER_ADDITION], - // a && (b && c) -> a && b && c - [Blockly.PHP.ORDER_LOGICAL_AND, Blockly.PHP.ORDER_LOGICAL_AND], - // a || (b || c) -> a || b || c - [Blockly.PHP.ORDER_LOGICAL_OR, Blockly.PHP.ORDER_LOGICAL_OR] -]; - -/** - * Allow for switching between one and zero based indexing for lists and text, - * one based by default. - */ -Blockly.PHP.ONE_BASED_INDEXING = true; - -/** - * Initialise the database of variable names. - * @param {!Blockly.Workspace} workspace Workspace to generate code from. - */ -Blockly.PHP.init = function(workspace) { - // Create a dictionary of definitions to be printed before the code. - Blockly.PHP.definitions_ = Object.create(null); - // Create a dictionary mapping desired function names in definitions_ - // to actual function names (to avoid collisions with user functions). - Blockly.PHP.functionNames_ = Object.create(null); - - if (!Blockly.PHP.variableDB_) { - Blockly.PHP.variableDB_ = - new Blockly.Names(Blockly.PHP.RESERVED_WORDS_, '$'); - } else { - Blockly.PHP.variableDB_.reset(); - } - - var defvars = []; - var variables = Blockly.Variables.allVariables(workspace); - for (var i = 0; i < variables.length; i++) { - defvars[i] = Blockly.PHP.variableDB_.getName(variables[i], - Blockly.Variables.NAME_TYPE) + ';'; - } - Blockly.PHP.definitions_['variables'] = defvars.join('\n'); -}; - -/** - * Prepend the generated code with the variable definitions. - * @param {string} code Generated code. - * @return {string} Completed code. - */ -Blockly.PHP.finish = function(code) { - // Convert the definitions dictionary into a list. - var definitions = []; - for (var name in Blockly.PHP.definitions_) { - definitions.push(Blockly.PHP.definitions_[name]); - } - // Clean up temporary data. - delete Blockly.PHP.definitions_; - delete Blockly.PHP.functionNames_; - Blockly.PHP.variableDB_.reset(); - return definitions.join('\n\n') + '\n\n\n' + code; -}; - -/** - * Naked values are top-level blocks with outputs that aren't plugged into - * anything. A trailing semicolon is needed to make this legal. - * @param {string} line Line of generated code. - * @return {string} Legal line of code. - */ -Blockly.PHP.scrubNakedValue = function(line) { - return line + ';\n'; -}; - -/** - * Encode a string as a properly escaped PHP string, complete with - * quotes. - * @param {string} string Text to encode. - * @return {string} PHP string. - * @private - */ -Blockly.PHP.quote_ = function(string) { - string = string.replace(/\\/g, '\\\\') - .replace(/\n/g, '\\\n') - .replace(/'/g, '\\\''); - return '\'' + string + '\''; -}; - -/** - * Common tasks for generating PHP from blocks. - * Handles comments for the specified block and any connected value blocks. - * Calls any statements following this block. - * @param {!Blockly.Block} block The current block. - * @param {string} code The PHP code created for this block. - * @return {string} PHP code with comments and subsequent blocks added. - * @private - */ -Blockly.PHP.scrub_ = function(block, code) { - var commentCode = ''; - // Only collect comments for blocks that aren't inline. - if (!block.outputConnection || !block.outputConnection.targetConnection) { - // Collect comment for this block. - var comment = block.getCommentText(); - comment = Blockly.utils.wrap(comment, Blockly.PHP.COMMENT_WRAP - 3); - if (comment) { - commentCode += Blockly.PHP.prefixLines(comment, '// ') + '\n'; - } - // Collect comments for all value arguments. - // Don't collect comments for nested statements. - for (var i = 0; i < block.inputList.length; i++) { - if (block.inputList[i].type == Blockly.INPUT_VALUE) { - var childBlock = block.inputList[i].connection.targetBlock(); - if (childBlock) { - var comment = Blockly.PHP.allNestedComments(childBlock); - if (comment) { - commentCode += Blockly.PHP.prefixLines(comment, '// '); - } - } - } - } - } - var nextBlock = block.nextConnection && block.nextConnection.targetBlock(); - var nextCode = Blockly.PHP.blockToCode(nextBlock); - return commentCode + code + nextCode; -}; - -/** - * Gets a property and adjusts the value while taking into account indexing. - * @param {!Blockly.Block} block The block. - * @param {string} atId The property ID of the element to get. - * @param {number=} opt_delta Value to add. - * @param {boolean=} opt_negate Whether to negate the value. - * @param {number=} opt_order The highest order acting on this value. - * @return {string|number} - */ -Blockly.PHP.getAdjusted = function(block, atId, opt_delta, opt_negate, - opt_order) { - var delta = opt_delta || 0; - var order = opt_order || Blockly.PHP.ORDER_NONE; - if (Blockly.PHP.ONE_BASED_INDEXING) { - delta--; - } - var defaultAtIndex = Blockly.PHP.ONE_BASED_INDEXING ? '1' : '0'; - if (delta > 0) { - var at = Blockly.PHP.valueToCode(block, atId, - Blockly.PHP.ORDER_ADDITION) || defaultAtIndex; - } else if (delta < 0) { - var at = Blockly.PHP.valueToCode(block, atId, - Blockly.PHP.ORDER_SUBTRACTION) || defaultAtIndex; - } else if (opt_negate) { - var at = Blockly.PHP.valueToCode(block, atId, - Blockly.PHP.ORDER_UNARY_NEGATION) || defaultAtIndex; - } else { - var at = Blockly.PHP.valueToCode(block, atId, order) || - defaultAtIndex; - } - - if (Blockly.isNumber(at)) { - // If the index is a naked number, adjust it right now. - at = parseFloat(at) + delta; - if (opt_negate) { - at = -at; - } - } else { - // If the index is dynamic, adjust it in code. - if (delta > 0) { - at = at + ' + ' + delta; - var innerOrder = Blockly.PHP.ORDER_ADDITION; - } else if (delta < 0) { - at = at + ' - ' + -delta; - var innerOrder = Blockly.PHP.ORDER_SUBTRACTION; - } - if (opt_negate) { - if (delta) { - at = '-(' + at + ')'; - } else { - at = '-' + at; - } - var innerOrder = Blockly.PHP.ORDER_UNARY_NEGATION; - } - innerOrder = Math.floor(innerOrder); - order = Math.floor(order); - if (innerOrder && order >= innerOrder) { - at = '(' + at + ')'; - } - } - return at; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/php/colour.js b/backend/_pv_1_3_5/static/blockly/generators/php/colour.js deleted file mode 100755 index e73c17a95..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/php/colour.js +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2015 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating PHP for colour blocks. - * @author daarond@gmail.com (Daaron Dwyer) - */ -'use strict'; - -goog.provide('Blockly.PHP.colour'); - -goog.require('Blockly.PHP'); - - -Blockly.PHP['colour_picker'] = function(block) { - // Colour picker. - var code = '\'' + block.getFieldValue('COLOUR') + '\''; - return [code, Blockly.PHP.ORDER_ATOMIC]; -}; - -Blockly.PHP['colour_random'] = function(block) { - // Generate a random colour. - var functionName = Blockly.PHP.provideFunction_( - 'colour_random', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + '() {', - ' return \'#\' . str_pad(dechex(mt_rand(0, 0xFFFFFF)), ' + - '6, \'0\', STR_PAD_LEFT);', - '}']); - var code = functionName + '()'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['colour_rgb'] = function(block) { - // Compose a colour from RGB components expressed as percentages. - var red = Blockly.PHP.valueToCode(block, 'RED', - Blockly.PHP.ORDER_COMMA) || 0; - var green = Blockly.PHP.valueToCode(block, 'GREEN', - Blockly.PHP.ORDER_COMMA) || 0; - var blue = Blockly.PHP.valueToCode(block, 'BLUE', - Blockly.PHP.ORDER_COMMA) || 0; - var functionName = Blockly.PHP.provideFunction_( - 'colour_rgb', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '($r, $g, $b) {', - ' $r = round(max(min($r, 100), 0) * 2.55);', - ' $g = round(max(min($g, 100), 0) * 2.55);', - ' $b = round(max(min($b, 100), 0) * 2.55);', - ' $hex = \'#\';', - ' $hex .= str_pad(dechex($r), 2, \'0\', STR_PAD_LEFT);', - ' $hex .= str_pad(dechex($g), 2, \'0\', STR_PAD_LEFT);', - ' $hex .= str_pad(dechex($b), 2, \'0\', STR_PAD_LEFT);', - ' return $hex;', - '}']); - var code = functionName + '(' + red + ', ' + green + ', ' + blue + ')'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['colour_blend'] = function(block) { - // Blend two colours together. - var c1 = Blockly.PHP.valueToCode(block, 'COLOUR1', - Blockly.PHP.ORDER_COMMA) || '\'#000000\''; - var c2 = Blockly.PHP.valueToCode(block, 'COLOUR2', - Blockly.PHP.ORDER_COMMA) || '\'#000000\''; - var ratio = Blockly.PHP.valueToCode(block, 'RATIO', - Blockly.PHP.ORDER_COMMA) || 0.5; - var functionName = Blockly.PHP.provideFunction_( - 'colour_blend', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '($c1, $c2, $ratio) {', - ' $ratio = max(min($ratio, 1), 0);', - ' $r1 = hexdec(substr($c1, 1, 2));', - ' $g1 = hexdec(substr($c1, 3, 2));', - ' $b1 = hexdec(substr($c1, 5, 2));', - ' $r2 = hexdec(substr($c2, 1, 2));', - ' $g2 = hexdec(substr($c2, 3, 2));', - ' $b2 = hexdec(substr($c2, 5, 2));', - ' $r = round($r1 * (1 - $ratio) + $r2 * $ratio);', - ' $g = round($g1 * (1 - $ratio) + $g2 * $ratio);', - ' $b = round($b1 * (1 - $ratio) + $b2 * $ratio);', - ' $hex = \'#\';', - ' $hex .= str_pad(dechex($r), 2, \'0\', STR_PAD_LEFT);', - ' $hex .= str_pad(dechex($g), 2, \'0\', STR_PAD_LEFT);', - ' $hex .= str_pad(dechex($b), 2, \'0\', STR_PAD_LEFT);', - ' return $hex;', - '}']); - var code = functionName + '(' + c1 + ', ' + c2 + ', ' + ratio + ')'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/php/lists.js b/backend/_pv_1_3_5/static/blockly/generators/php/lists.js deleted file mode 100755 index 449c31a5e..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/php/lists.js +++ /dev/null @@ -1,504 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2015 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating PHP for list blocks. - * @author daarond@gmail.com (Daaron Dwyer) - */ - -/* - * Lists in PHP are known to break when non-variables are passed into blocks - * that require a list. PHP, unlike other languages, passes arrays as reference - * value instead of value so we are unable to support it to the extent we can - * for the other languages. - * For example, a ternary operator with two arrays will return the array by - * value and that cannot be passed into any of the built-in array functions for - * PHP (because only variables can be passed by reference). - * ex: end(true ? list1 : list2) - */ -'use strict'; - -goog.provide('Blockly.PHP.lists'); - -goog.require('Blockly.PHP'); - - -Blockly.PHP['lists_create_empty'] = function(block) { - // Create an empty list. - return ['array()', Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['lists_create_with'] = function(block) { - // Create a list with any number of elements of any type. - var code = new Array(block.itemCount_); - for (var i = 0; i < block.itemCount_; i++) { - code[i] = Blockly.PHP.valueToCode(block, 'ADD' + i, - Blockly.PHP.ORDER_COMMA) || 'null'; - } - code = 'array(' + code.join(', ') + ')'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['lists_repeat'] = function(block) { - // Create a list with one element repeated. - var functionName = Blockly.PHP.provideFunction_( - 'lists_repeat', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '($value, $count) {', - ' $array = array();', - ' for ($index = 0; $index < $count; $index++) {', - ' $array[] = $value;', - ' }', - ' return $array;', - '}']); - var element = Blockly.PHP.valueToCode(block, 'ITEM', - Blockly.PHP.ORDER_COMMA) || 'null'; - var repeatCount = Blockly.PHP.valueToCode(block, 'NUM', - Blockly.PHP.ORDER_COMMA) || '0'; - var code = functionName + '(' + element + ', ' + repeatCount + ')'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['lists_length'] = function(block) { - // String or array length. - var functionName = Blockly.PHP.provideFunction_( - 'length', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + '($value) {', - ' if (is_string($value)) {', - ' return strlen($value);', - ' } else {', - ' return count($value);', - ' }', - '}']); - var list = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_NONE) || '\'\''; - return [functionName + '(' + list + ')', Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['lists_isEmpty'] = function(block) { - // Is the string null or array empty? - var argument0 = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_FUNCTION_CALL) || 'array()'; - return ['empty(' + argument0 + ')', Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['lists_indexOf'] = function(block) { - // Find an item in the list. - var argument0 = Blockly.PHP.valueToCode(block, 'FIND', - Blockly.PHP.ORDER_NONE) || '\'\''; - var argument1 = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_MEMBER) || '[]'; - if (Blockly.PHP.ONE_BASED_INDEXING) { - var errorIndex = ' 0'; - var indexAdjustment = ' + 1'; - } else { - var errorIndex = ' -1'; - var indexAdjustment = ''; - } - if (block.getFieldValue('END') == 'FIRST') { - // indexOf - var functionName = Blockly.PHP.provideFunction_( - 'indexOf', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '($haystack, $needle) {', - ' for ($index = 0; $index < count($haystack); $index++) {', - ' if ($haystack[$index] == $needle) return $index' + - indexAdjustment + ';', - ' }', - ' return ' + errorIndex + ';', - '}']); - } else { - // lastIndexOf - var functionName = Blockly.PHP.provideFunction_( - 'lastIndexOf', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '($haystack, $needle) {', - ' $last = ' + errorIndex + ';', - ' for ($index = 0; $index < count($haystack); $index++) {', - ' if ($haystack[$index] == $needle) $last = $index' + - indexAdjustment + ';', - ' }', - ' return $last;', - '}']); - } - - var code = functionName + '(' + argument1 + ', ' + argument0 + ')'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['lists_getIndex'] = function(block) { - // Get element at index. - var mode = block.getFieldValue('MODE') || 'GET'; - var where = block.getFieldValue('WHERE') || 'FROM_START'; - switch (where) { - case 'FIRST': - if (mode == 'GET') { - var list = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_MEMBER) || 'array()'; - var code = list + '[0]'; - return [code, Blockly.PHP.ORDER_MEMBER]; - } else if (mode == 'GET_REMOVE') { - var list = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_NONE) || 'array()'; - var code = 'array_shift(' + list + ')'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; - } else if (mode == 'REMOVE') { - var list = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_NONE) || 'array()'; - return 'array_shift(' + list + ');\n'; - } - break; - case 'LAST': - if (mode == 'GET') { - var list = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_NONE) || 'array()'; - var code = 'end(' + list + ')'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; - } else if (mode == 'GET_REMOVE') { - var list = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_NONE) || 'array()'; - var code = 'array_pop(' + list + ')'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; - } else if (mode == 'REMOVE') { - var list = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_NONE) || 'array()'; - return 'array_pop(' + list + ');\n'; - } - break; - case 'FROM_START': - var at = Blockly.PHP.getAdjusted(block, 'AT'); - if (mode == 'GET') { - var list = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_MEMBER) || 'array()'; - var code = list + '[' + at + ']'; - return [code, Blockly.PHP.ORDER_MEMBER]; - } else if (mode == 'GET_REMOVE') { - var list = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_COMMA) || 'array()'; - var code = 'array_splice(' + list + ', ' + at + ', 1)[0]'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; - } else if (mode == 'REMOVE') { - var list = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_COMMA) || 'array()'; - return 'array_splice(' + list + ', ' + at + ', 1);\n'; - } - break; - case 'FROM_END': - if (mode == 'GET') { - var list = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_COMMA) || 'array()'; - var at = Blockly.PHP.getAdjusted(block, 'AT', 1, true); - var code = 'array_slice(' + list + ', ' + at + ', 1)[0]'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; - } else if (mode == 'GET_REMOVE' || mode == 'REMOVE') { - var list = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_NONE) || 'array()'; - var at = Blockly.PHP.getAdjusted(block, 'AT', 1, false, - Blockly.PHP.ORDER_SUBTRACTION); - code = 'array_splice(' + list + - ', count(' + list + ') - ' + at + ', 1)[0]'; - if (mode == 'GET_REMOVE') { - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; - } else if (mode == 'REMOVE') { - return code + ';\n'; - } - } - break; - case 'RANDOM': - var list = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_NONE) || 'array()'; - if (mode == 'GET') { - var functionName = Blockly.PHP.provideFunction_( - 'lists_get_random_item', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '($list) {', - ' return $list[rand(0,count($list)-1)];', - '}']); - code = functionName + '(' + list + ')'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; - } else if (mode == 'GET_REMOVE') { - var functionName = Blockly.PHP.provideFunction_( - 'lists_get_remove_random_item', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '(&$list) {', - ' $x = rand(0,count($list)-1);', - ' unset($list[$x]);', - ' return array_values($list);', - '}']); - code = functionName + '(' + list + ')'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; - } else if (mode == 'REMOVE') { - var functionName = Blockly.PHP.provideFunction_( - 'lists_remove_random_item', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '(&$list) {', - ' unset($list[rand(0,count($list)-1)]);', - '}']); - return functionName + '(' + list + ');\n'; - } - break; - } - throw 'Unhandled combination (lists_getIndex).'; -}; - -Blockly.PHP['lists_setIndex'] = function(block) { - // Set element at index. - // Note: Until February 2013 this block did not have MODE or WHERE inputs. - var mode = block.getFieldValue('MODE') || 'GET'; - var where = block.getFieldValue('WHERE') || 'FROM_START'; - var value = Blockly.PHP.valueToCode(block, 'TO', - Blockly.PHP.ORDER_ASSIGNMENT) || 'null'; - // Cache non-trivial values to variables to prevent repeated look-ups. - // Closure, which accesses and modifies 'list'. - function cacheList() { - if (list.match(/^\$\w+$/)) { - return ''; - } - var listVar = Blockly.PHP.variableDB_.getDistinctName( - 'tmp_list', Blockly.Variables.NAME_TYPE); - var code = listVar + ' = &' + list + ';\n'; - list = listVar; - return code; - } - switch (where) { - case 'FIRST': - if (mode == 'SET') { - var list = Blockly.PHP.valueToCode(block, 'LIST', - Blockly.PHP.ORDER_MEMBER) || 'array()'; - return list + '[0] = ' + value + ';\n'; - } else if (mode == 'INSERT') { - var list = Blockly.PHP.valueToCode(block, 'LIST', - Blockly.PHP.ORDER_COMMA) || 'array()'; - return 'array_unshift(' + list + ', ' + value + ');\n'; - } - break; - case 'LAST': - var list = Blockly.PHP.valueToCode(block, 'LIST', - Blockly.PHP.ORDER_COMMA) || 'array()'; - if (mode == 'SET') { - var functionName = Blockly.PHP.provideFunction_( - 'lists_set_last_item', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '(&$list, $value) {', - ' $list[count($list) - 1] = $value;', - '}']); - return functionName + '(' + list + ', ' + value + ');\n'; - } else if (mode == 'INSERT') { - return 'array_push(' + list + ', ' + value + ');\n'; - } - break; - case 'FROM_START': - var at = Blockly.PHP.getAdjusted(block, 'AT'); - if (mode == 'SET') { - var list = Blockly.PHP.valueToCode(block, 'LIST', - Blockly.PHP.ORDER_MEMBER) || 'array()'; - return list + '[' + at + '] = ' + value + ';\n'; - } else if (mode == 'INSERT') { - var list = Blockly.PHP.valueToCode(block, 'LIST', - Blockly.PHP.ORDER_COMMA) || 'array()'; - return 'array_splice(' + list + ', ' + at + ', 0, ' + value + ');\n'; - } - break; - case 'FROM_END': - var list = Blockly.PHP.valueToCode(block, 'LIST', - Blockly.PHP.ORDER_COMMA) || 'array()'; - var at = Blockly.PHP.getAdjusted(block, 'AT', 1); - if (mode == 'SET') { - var functionName = Blockly.PHP.provideFunction_( - 'lists_set_from_end', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '(&$list, $at, $value) {', - ' $list[count($list) - $at] = $value;', - '}']); - return functionName + '(' + list + ', ' + at + ', ' + value + ');\n'; - } else if (mode == 'INSERT') { - var functionName = Blockly.PHP.provideFunction_( - 'lists_insert_from_end', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '(&$list, $at, $value) {', - ' return array_splice($list, count($list) - $at, 0, $value);', - '}']); - return functionName + '(' + list + ', ' + at + ', ' + value + ');\n'; - } - break; - case 'RANDOM': - var list = Blockly.PHP.valueToCode(block, 'LIST', - Blockly.PHP.ORDER_REFERENCE) || 'array()'; - var code = cacheList(); - var xVar = Blockly.PHP.variableDB_.getDistinctName( - 'tmp_x', Blockly.Variables.NAME_TYPE); - code += xVar + ' = rand(0, count(' + list + ')-1);\n'; - if (mode == 'SET') { - code += list + '[' + xVar + '] = ' + value + ';\n'; - return code; - } else if (mode == 'INSERT') { - code += 'array_splice(' + list + ', ' + xVar + ', 0, ' + value + - ');\n'; - return code; - } - break; - } - throw 'Unhandled combination (lists_setIndex).'; -}; - -Blockly.PHP['lists_getSublist'] = function(block) { - // Get sublist. - var list = Blockly.PHP.valueToCode(block, 'LIST', - Blockly.PHP.ORDER_COMMA) || 'array()'; - var where1 = block.getFieldValue('WHERE1'); - var where2 = block.getFieldValue('WHERE2'); - if (where1 == 'FIRST' && where2 == 'LAST') { - var code = list; - } else if (list.match(/^\$\w+$/) || - (where1 != 'FROM_END' && where2 == 'FROM_START')) { - // If the list is a simple value or doesn't require a call for length, don't - // generate a helper function. - switch (where1) { - case 'FROM_START': - var at1 = Blockly.PHP.getAdjusted(block, 'AT1'); - break; - case 'FROM_END': - var at1 = Blockly.PHP.getAdjusted(block, 'AT1', 1, false, - Blockly.PHP.ORDER_SUBTRACTION); - at1 = 'count(' + list + ') - ' + at1; - break; - case 'FIRST': - var at1 = '0'; - break; - default: - throw 'Unhandled option (lists_getSublist).'; - } - switch (where2) { - case 'FROM_START': - var at2 = Blockly.PHP.getAdjusted(block, 'AT2', 0, false, - Blockly.PHP.ORDER_SUBTRACTION); - var length = at2 + ' - '; - if (Blockly.isNumber(String(at1)) || String(at1).match(/^\(.+\)$/)) { - length += at1; - } else { - length += '(' + at1 + ')'; - } - length += ' + 1'; - break; - case 'FROM_END': - var at2 = Blockly.PHP.getAdjusted(block, 'AT2', 0, false, - Blockly.PHP.ORDER_SUBTRACTION); - var length = 'count(' + list + ') - ' + at2 + ' - '; - if (Blockly.isNumber(String(at1)) || String(at1).match(/^\(.+\)$/)) { - length += at1; - } else { - length += '(' + at1 + ')'; - } - break; - case 'LAST': - var length = 'count(' + list + ') - '; - if (Blockly.isNumber(String(at1)) || String(at1).match(/^\(.+\)$/)) { - length += at1; - } else { - length += '(' + at1 + ')'; - } - break; - default: - throw 'Unhandled option (lists_getSublist).'; - } - code = 'array_slice(' + list + ', ' + at1 + ', ' + length + ')'; - } else { - var at1 = Blockly.PHP.getAdjusted(block, 'AT1'); - var at2 = Blockly.PHP.getAdjusted(block, 'AT2'); - var functionName = Blockly.PHP.provideFunction_( - 'lists_get_sublist', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '($list, $where1, $at1, $where2, $at2) {', - ' if ($where1 == \'FROM_END\') {', - ' $at1 = count($list) - 1 - $at1;', - ' } else if ($where1 == \'FIRST\') {', - ' $at1 = 0;', - ' } else if ($where1 != \'FROM_START\'){', - ' throw new Exception(\'Unhandled option (lists_get_sublist).\');', - ' }', - ' $length = 0;', - ' if ($where2 == \'FROM_START\') {', - ' $length = $at2 - $at1 + 1;', - ' } else if ($where2 == \'FROM_END\') {', - ' $length = count($list) - $at1 - $at2;', - ' } else if ($where2 == \'LAST\') {', - ' $length = count($list) - $at1;', - ' } else {', - ' throw new Exception(\'Unhandled option (lists_get_sublist).\');', - ' }', - ' return array_slice($list, $at1, $length);', - '}']); - var code = functionName + '(' + list + ', \'' + - where1 + '\', ' + at1 + ', \'' + where2 + '\', ' + at2 + ')'; - } - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['lists_sort'] = function(block) { - // Block for sorting a list. - var listCode = Blockly.PHP.valueToCode(block, 'LIST', - Blockly.PHP.ORDER_COMMA) || 'array()'; - var direction = block.getFieldValue('DIRECTION') === '1' ? 1 : -1; - var type = block.getFieldValue('TYPE'); - var functionName = Blockly.PHP.provideFunction_( - 'lists_sort', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '($list, $type, $direction) {', - ' $sortCmpFuncs = array(', - ' "NUMERIC" => "strnatcasecmp",', - ' "TEXT" => "strcmp",', - ' "IGNORE_CASE" => "strcasecmp"', - ' );', - ' $sortCmp = $sortCmpFuncs[$type];', - ' $list2 = $list;', // Clone list. - ' usort($list2, $sortCmp);', - ' if ($direction == -1) {', - ' $list2 = array_reverse($list2);', - ' }', - ' return $list2;', - '}']); - var sortCode = functionName + - '(' + listCode + ', "' + type + '", ' + direction + ')'; - return [sortCode, Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['lists_split'] = function(block) { - // Block for splitting text into a list, or joining a list into text. - var value_input = Blockly.PHP.valueToCode(block, 'INPUT', - Blockly.PHP.ORDER_COMMA); - var value_delim = Blockly.PHP.valueToCode(block, 'DELIM', - Blockly.PHP.ORDER_COMMA) || '\'\''; - var mode = block.getFieldValue('MODE'); - if (mode == 'SPLIT') { - if (!value_input) { - value_input = '\'\''; - } - var functionName = 'explode'; - } else if (mode == 'JOIN') { - if (!value_input) { - value_input = 'array()'; - } - var functionName = 'implode'; - } else { - throw 'Unknown mode: ' + mode; - } - var code = functionName + '(' + value_delim + ', ' + value_input + ')'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/php/logic.js b/backend/_pv_1_3_5/static/blockly/generators/php/logic.js deleted file mode 100755 index 59389239f..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/php/logic.js +++ /dev/null @@ -1,126 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2015 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating PHP for logic blocks. - * @author daarond@gmail.com (Daaron Dwyer) - */ -'use strict'; - -goog.provide('Blockly.PHP.logic'); - -goog.require('Blockly.PHP'); - - -Blockly.PHP['controls_if'] = function(block) { - // If/elseif/else condition. - var n = 0; - var argument = Blockly.PHP.valueToCode(block, 'IF' + n, - Blockly.PHP.ORDER_NONE) || 'false'; - var branch = Blockly.PHP.statementToCode(block, 'DO' + n); - var code = 'if (' + argument + ') {\n' + branch + '}'; - for (n = 1; n <= block.elseifCount_; n++) { - argument = Blockly.PHP.valueToCode(block, 'IF' + n, - Blockly.PHP.ORDER_NONE) || 'false'; - branch = Blockly.PHP.statementToCode(block, 'DO' + n); - code += ' else if (' + argument + ') {\n' + branch + '}'; - } - if (block.elseCount_) { - branch = Blockly.PHP.statementToCode(block, 'ELSE'); - code += ' else {\n' + branch + '}'; - } - return code + '\n'; -}; - -Blockly.PHP['logic_compare'] = function(block) { - // Comparison operator. - var OPERATORS = { - 'EQ': '==', - 'NEQ': '!=', - 'LT': '<', - 'LTE': '<=', - 'GT': '>', - 'GTE': '>=' - }; - var operator = OPERATORS[block.getFieldValue('OP')]; - var order = (operator == '==' || operator == '!=') ? - Blockly.PHP.ORDER_EQUALITY : Blockly.PHP.ORDER_RELATIONAL; - var argument0 = Blockly.PHP.valueToCode(block, 'A', order) || '0'; - var argument1 = Blockly.PHP.valueToCode(block, 'B', order) || '0'; - var code = argument0 + ' ' + operator + ' ' + argument1; - return [code, order]; -}; - -Blockly.PHP['logic_operation'] = function(block) { - // Operations 'and', 'or'. - var operator = (block.getFieldValue('OP') == 'AND') ? '&&' : '||'; - var order = (operator == '&&') ? Blockly.PHP.ORDER_LOGICAL_AND : - Blockly.PHP.ORDER_LOGICAL_OR; - var argument0 = Blockly.PHP.valueToCode(block, 'A', order); - var argument1 = Blockly.PHP.valueToCode(block, 'B', order); - if (!argument0 && !argument1) { - // If there are no arguments, then the return value is false. - argument0 = 'false'; - argument1 = 'false'; - } else { - // Single missing arguments have no effect on the return value. - var defaultArgument = (operator == '&&') ? 'true' : 'false'; - if (!argument0) { - argument0 = defaultArgument; - } - if (!argument1) { - argument1 = defaultArgument; - } - } - var code = argument0 + ' ' + operator + ' ' + argument1; - return [code, order]; -}; - -Blockly.PHP['logic_negate'] = function(block) { - // Negation. - var order = Blockly.PHP.ORDER_LOGICAL_NOT; - var argument0 = Blockly.PHP.valueToCode(block, 'BOOL', order) || - 'true'; - var code = '!' + argument0; - return [code, order]; -}; - -Blockly.PHP['logic_boolean'] = function(block) { - // Boolean values true and false. - var code = (block.getFieldValue('BOOL') == 'TRUE') ? 'true' : 'false'; - return [code, Blockly.PHP.ORDER_ATOMIC]; -}; - -Blockly.PHP['logic_null'] = function(block) { - // Null data type. - return ['null', Blockly.PHP.ORDER_ATOMIC]; -}; - -Blockly.PHP['logic_ternary'] = function(block) { - // Ternary operator. - var value_if = Blockly.PHP.valueToCode(block, 'IF', - Blockly.PHP.ORDER_CONDITIONAL) || 'false'; - var value_then = Blockly.PHP.valueToCode(block, 'THEN', - Blockly.PHP.ORDER_CONDITIONAL) || 'null'; - var value_else = Blockly.PHP.valueToCode(block, 'ELSE', - Blockly.PHP.ORDER_CONDITIONAL) || 'null'; - var code = value_if + ' ? ' + value_then + ' : ' + value_else; - return [code, Blockly.PHP.ORDER_CONDITIONAL]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/php/loops.js b/backend/_pv_1_3_5/static/blockly/generators/php/loops.js deleted file mode 100755 index f306b1053..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/php/loops.js +++ /dev/null @@ -1,164 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2015 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating PHP for loop blocks. - * @author daarond@gmail.com (Daaron Dwyer) - */ -'use strict'; - -goog.provide('Blockly.PHP.loops'); - -goog.require('Blockly.PHP'); - - -Blockly.PHP['controls_repeat_ext'] = function(block) { - // Repeat n times. - if (block.getField('TIMES')) { - // Internal number. - var repeats = String(Number(block.getFieldValue('TIMES'))); - } else { - // External number. - var repeats = Blockly.PHP.valueToCode(block, 'TIMES', - Blockly.PHP.ORDER_ASSIGNMENT) || '0'; - } - var branch = Blockly.PHP.statementToCode(block, 'DO'); - branch = Blockly.PHP.addLoopTrap(branch, block.id); - var code = ''; - var loopVar = Blockly.PHP.variableDB_.getDistinctName( - 'count', Blockly.Variables.NAME_TYPE); - var endVar = repeats; - if (!repeats.match(/^\w+$/) && !Blockly.isNumber(repeats)) { - var endVar = Blockly.PHP.variableDB_.getDistinctName( - 'repeat_end', Blockly.Variables.NAME_TYPE); - code += endVar + ' = ' + repeats + ';\n'; - } - code += 'for (' + loopVar + ' = 0; ' + - loopVar + ' < ' + endVar + '; ' + - loopVar + '++) {\n' + - branch + '}\n'; - return code; -}; - -Blockly.PHP['controls_repeat'] = Blockly.PHP['controls_repeat_ext']; - -Blockly.PHP['controls_whileUntil'] = function(block) { - // Do while/until loop. - var until = block.getFieldValue('MODE') == 'UNTIL'; - var argument0 = Blockly.PHP.valueToCode(block, 'BOOL', - until ? Blockly.PHP.ORDER_LOGICAL_NOT : - Blockly.PHP.ORDER_NONE) || 'false'; - var branch = Blockly.PHP.statementToCode(block, 'DO'); - branch = Blockly.PHP.addLoopTrap(branch, block.id); - if (until) { - argument0 = '!' + argument0; - } - return 'while (' + argument0 + ') {\n' + branch + '}\n'; -}; - -Blockly.PHP['controls_for'] = function(block) { - // For loop. - var variable0 = Blockly.PHP.variableDB_.getName( - block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); - var argument0 = Blockly.PHP.valueToCode(block, 'FROM', - Blockly.PHP.ORDER_ASSIGNMENT) || '0'; - var argument1 = Blockly.PHP.valueToCode(block, 'TO', - Blockly.PHP.ORDER_ASSIGNMENT) || '0'; - var increment = Blockly.PHP.valueToCode(block, 'BY', - Blockly.PHP.ORDER_ASSIGNMENT) || '1'; - var branch = Blockly.PHP.statementToCode(block, 'DO'); - branch = Blockly.PHP.addLoopTrap(branch, block.id); - var code; - if (Blockly.isNumber(argument0) && Blockly.isNumber(argument1) && - Blockly.isNumber(increment)) { - // All arguments are simple numbers. - var up = parseFloat(argument0) <= parseFloat(argument1); - code = 'for (' + variable0 + ' = ' + argument0 + '; ' + - variable0 + (up ? ' <= ' : ' >= ') + argument1 + '; ' + - variable0; - var step = Math.abs(parseFloat(increment)); - if (step == 1) { - code += up ? '++' : '--'; - } else { - code += (up ? ' += ' : ' -= ') + step; - } - code += ') {\n' + branch + '}\n'; - } else { - code = ''; - // Cache non-trivial values to variables to prevent repeated look-ups. - var startVar = argument0; - if (!argument0.match(/^\w+$/) && !Blockly.isNumber(argument0)) { - startVar = Blockly.PHP.variableDB_.getDistinctName( - variable0 + '_start', Blockly.Variables.NAME_TYPE); - code += startVar + ' = ' + argument0 + ';\n'; - } - var endVar = argument1; - if (!argument1.match(/^\w+$/) && !Blockly.isNumber(argument1)) { - var endVar = Blockly.PHP.variableDB_.getDistinctName( - variable0 + '_end', Blockly.Variables.NAME_TYPE); - code += endVar + ' = ' + argument1 + ';\n'; - } - // Determine loop direction at start, in case one of the bounds - // changes during loop execution. - var incVar = Blockly.PHP.variableDB_.getDistinctName( - variable0 + '_inc', Blockly.Variables.NAME_TYPE); - code += incVar + ' = '; - if (Blockly.isNumber(increment)) { - code += Math.abs(increment) + ';\n'; - } else { - code += 'abs(' + increment + ');\n'; - } - code += 'if (' + startVar + ' > ' + endVar + ') {\n'; - code += Blockly.PHP.INDENT + incVar + ' = -' + incVar + ';\n'; - code += '}\n'; - code += 'for (' + variable0 + ' = ' + startVar + '; ' + - incVar + ' >= 0 ? ' + - variable0 + ' <= ' + endVar + ' : ' + - variable0 + ' >= ' + endVar + '; ' + - variable0 + ' += ' + incVar + ') {\n' + - branch + '}\n'; - } - return code; -}; - -Blockly.PHP['controls_forEach'] = function(block) { - // For each loop. - var variable0 = Blockly.PHP.variableDB_.getName( - block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); - var argument0 = Blockly.PHP.valueToCode(block, 'LIST', - Blockly.PHP.ORDER_ASSIGNMENT) || '[]'; - var branch = Blockly.PHP.statementToCode(block, 'DO'); - branch = Blockly.PHP.addLoopTrap(branch, block.id); - var code = ''; - code += 'foreach (' + argument0 + ' as ' + variable0 + - ') {\n' + branch + '}\n'; - return code; -}; - -Blockly.PHP['controls_flow_statements'] = function(block) { - // Flow statements: continue, break. - switch (block.getFieldValue('FLOW')) { - case 'BREAK': - return 'break;\n'; - case 'CONTINUE': - return 'continue;\n'; - } - throw 'Unknown flow statement.'; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/php/math.js b/backend/_pv_1_3_5/static/blockly/generators/php/math.js deleted file mode 100755 index 7789ba8fe..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/php/math.js +++ /dev/null @@ -1,372 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2015 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating PHP for math blocks. - * @author daarond@gmail.com (Daaron Dwyer) - */ -'use strict'; - -goog.provide('Blockly.PHP.math'); - -goog.require('Blockly.PHP'); - - -Blockly.PHP['math_number'] = function(block) { - // Numeric value. - var code = parseFloat(block.getFieldValue('NUM')); - if (code == Infinity) { - code = 'INF'; - } else if (code == -Infinity) { - code = '-INF'; - } - return [code, Blockly.PHP.ORDER_ATOMIC]; -}; - -Blockly.PHP['math_arithmetic'] = function(block) { - // Basic arithmetic operators, and power. - var OPERATORS = { - 'ADD': [' + ', Blockly.PHP.ORDER_ADDITION], - 'MINUS': [' - ', Blockly.PHP.ORDER_SUBTRACTION], - 'MULTIPLY': [' * ', Blockly.PHP.ORDER_MULTIPLICATION], - 'DIVIDE': [' / ', Blockly.PHP.ORDER_DIVISION], - 'POWER': [' ** ', Blockly.PHP.ORDER_POWER] - }; - var tuple = OPERATORS[block.getFieldValue('OP')]; - var operator = tuple[0]; - var order = tuple[1]; - var argument0 = Blockly.PHP.valueToCode(block, 'A', order) || '0'; - var argument1 = Blockly.PHP.valueToCode(block, 'B', order) || '0'; - var code = argument0 + operator + argument1; - return [code, order]; -}; - -Blockly.PHP['math_single'] = function(block) { - // Math operators with single operand. - var operator = block.getFieldValue('OP'); - var code; - var arg; - if (operator == 'NEG') { - // Negation is a special case given its different operator precedence. - arg = Blockly.PHP.valueToCode(block, 'NUM', - Blockly.PHP.ORDER_UNARY_NEGATION) || '0'; - if (arg[0] == '-') { - // --3 is not legal in JS. - arg = ' ' + arg; - } - code = '-' + arg; - return [code, Blockly.PHP.ORDER_UNARY_NEGATION]; - } - if (operator == 'SIN' || operator == 'COS' || operator == 'TAN') { - arg = Blockly.PHP.valueToCode(block, 'NUM', - Blockly.PHP.ORDER_DIVISION) || '0'; - } else { - arg = Blockly.PHP.valueToCode(block, 'NUM', - Blockly.PHP.ORDER_NONE) || '0'; - } - // First, handle cases which generate values that don't need parentheses - // wrapping the code. - switch (operator) { - case 'ABS': - code = 'abs(' + arg + ')'; - break; - case 'ROOT': - code = 'sqrt(' + arg + ')'; - break; - case 'LN': - code = 'log(' + arg + ')'; - break; - case 'EXP': - code = 'exp(' + arg + ')'; - break; - case 'POW10': - code = 'pow(10,' + arg + ')'; - break; - case 'ROUND': - code = 'round(' + arg + ')'; - break; - case 'ROUNDUP': - code = 'ceil(' + arg + ')'; - break; - case 'ROUNDDOWN': - code = 'floor(' + arg + ')'; - break; - case 'SIN': - code = 'sin(' + arg + ' / 180 * pi())'; - break; - case 'COS': - code = 'cos(' + arg + ' / 180 * pi())'; - break; - case 'TAN': - code = 'tan(' + arg + ' / 180 * pi())'; - break; - } - if (code) { - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; - } - // Second, handle cases which generate values that may need parentheses - // wrapping the code. - switch (operator) { - case 'LOG10': - code = 'log(' + arg + ') / log(10)'; - break; - case 'ASIN': - code = 'asin(' + arg + ') / pi() * 180'; - break; - case 'ACOS': - code = 'acos(' + arg + ') / pi() * 180'; - break; - case 'ATAN': - code = 'atan(' + arg + ') / pi() * 180'; - break; - default: - throw 'Unknown math operator: ' + operator; - } - return [code, Blockly.PHP.ORDER_DIVISION]; -}; - -Blockly.PHP['math_constant'] = function(block) { - // Constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY. - var CONSTANTS = { - 'PI': ['M_PI', Blockly.PHP.ORDER_ATOMIC], - 'E': ['M_E', Blockly.PHP.ORDER_ATOMIC], - 'GOLDEN_RATIO': ['(1 + sqrt(5)) / 2', Blockly.PHP.ORDER_DIVISION], - 'SQRT2': ['M_SQRT2', Blockly.PHP.ORDER_ATOMIC], - 'SQRT1_2': ['M_SQRT1_2', Blockly.PHP.ORDER_ATOMIC], - 'INFINITY': ['INF', Blockly.PHP.ORDER_ATOMIC] - }; - return CONSTANTS[block.getFieldValue('CONSTANT')]; -}; - -Blockly.PHP['math_number_property'] = function(block) { - // Check if a number is even, odd, prime, whole, positive, or negative - // or if it is divisible by certain number. Returns true or false. - var number_to_check = Blockly.PHP.valueToCode(block, 'NUMBER_TO_CHECK', - Blockly.PHP.ORDER_MODULUS) || '0'; - var dropdown_property = block.getFieldValue('PROPERTY'); - var code; - if (dropdown_property == 'PRIME') { - // Prime is a special case as it is not a one-liner test. - var functionName = Blockly.PHP.provideFunction_( - 'math_isPrime', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + '($n) {', - ' // https://en.wikipedia.org/wiki/Primality_test#Naive_methods', - ' if ($n == 2 || $n == 3) {', - ' return true;', - ' }', - ' // False if n is NaN, negative, is 1, or not whole.', - ' // And false if n is divisible by 2 or 3.', - ' if (!is_numeric($n) || $n <= 1 || $n % 1 != 0 || $n % 2 == 0 ||' + - ' $n % 3 == 0) {', - ' return false;', - ' }', - ' // Check all the numbers of form 6k +/- 1, up to sqrt(n).', - ' for ($x = 6; $x <= sqrt($n) + 1; $x += 6) {', - ' if ($n % ($x - 1) == 0 || $n % ($x + 1) == 0) {', - ' return false;', - ' }', - ' }', - ' return true;', - '}']); - code = functionName + '(' + number_to_check + ')'; - return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL]; - } - switch (dropdown_property) { - case 'EVEN': - code = number_to_check + ' % 2 == 0'; - break; - case 'ODD': - code = number_to_check + ' % 2 == 1'; - break; - case 'WHOLE': - code = 'is_int(' + number_to_check + ')'; - break; - case 'POSITIVE': - code = number_to_check + ' > 0'; - break; - case 'NEGATIVE': - code = number_to_check + ' < 0'; - break; - case 'DIVISIBLE_BY': - var divisor = Blockly.PHP.valueToCode(block, 'DIVISOR', - Blockly.PHP.ORDER_MODULUS) || '0'; - code = number_to_check + ' % ' + divisor + ' == 0'; - break; - } - return [code, Blockly.PHP.ORDER_EQUALITY]; -}; - -Blockly.PHP['math_change'] = function(block) { - // Add to a variable in place. - var argument0 = Blockly.PHP.valueToCode(block, 'DELTA', - Blockly.PHP.ORDER_ADDITION) || '0'; - var varName = Blockly.PHP.variableDB_.getName( - block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); - return varName + ' += ' + argument0 + ';\n'; -}; - -// Rounding functions have a single operand. -Blockly.PHP['math_round'] = Blockly.PHP['math_single']; -// Trigonometry functions have a single operand. -Blockly.PHP['math_trig'] = Blockly.PHP['math_single']; - -Blockly.PHP['math_on_list'] = function(block) { - // Math functions for lists. - var func = block.getFieldValue('OP'); - var list, code; - switch (func) { - case 'SUM': - list = Blockly.PHP.valueToCode(block, 'LIST', - Blockly.PHP.ORDER_FUNCTION_CALL) || 'array()'; - code = 'array_sum(' + list + ')'; - break; - case 'MIN': - list = Blockly.PHP.valueToCode(block, 'LIST', - Blockly.PHP.ORDER_FUNCTION_CALL) || 'array()'; - code = 'min(' + list + ')'; - break; - case 'MAX': - list = Blockly.PHP.valueToCode(block, 'LIST', - Blockly.PHP.ORDER_FUNCTION_CALL) || 'array()'; - code = 'max(' + list + ')'; - break; - case 'AVERAGE': - var functionName = Blockly.PHP.provideFunction_( - 'math_mean', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '($myList) {', - ' return array_sum($myList) / count($myList);', - '}']); - list = Blockly.PHP.valueToCode(block, 'LIST', - Blockly.PHP.ORDER_NONE) || 'array()'; - code = functionName + '(' + list + ')'; - break; - case 'MEDIAN': - var functionName = Blockly.PHP.provideFunction_( - 'math_median', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '($arr) {', - ' sort($arr,SORT_NUMERIC);', - ' return (count($arr) % 2) ? $arr[floor(count($arr)/2)] : ', - ' ($arr[floor(count($arr)/2)] + $arr[floor(count($arr)/2)' + - ' - 1]) / 2;', - '}']); - list = Blockly.PHP.valueToCode(block, 'LIST', - Blockly.PHP.ORDER_NONE) || '[]'; - code = functionName + '(' + list + ')'; - break; - case 'MODE': - // As a list of numbers can contain more than one mode, - // the returned result is provided as an array. - // Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1]. - var functionName = Blockly.PHP.provideFunction_( - 'math_modes', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '($values) {', - ' if (empty($values)) return array();', - ' $counts = array_count_values($values);', - ' arsort($counts); // Sort counts in descending order', - ' $modes = array_keys($counts, current($counts), true);', - ' return $modes;', - '}']); - list = Blockly.PHP.valueToCode(block, 'LIST', - Blockly.PHP.ORDER_NONE) || '[]'; - code = functionName + '(' + list + ')'; - break; - case 'STD_DEV': - var functionName = Blockly.PHP.provideFunction_( - 'math_standard_deviation', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '($numbers) {', - ' $n = count($numbers);', - ' if (!$n) return null;', - ' $mean = array_sum($numbers) / count($numbers);', - ' foreach($numbers as $key => $num) $devs[$key] = ' + - 'pow($num - $mean, 2);', - ' return sqrt(array_sum($devs) / (count($devs) - 1));', - '}']); - list = Blockly.PHP.valueToCode(block, 'LIST', - Blockly.PHP.ORDER_NONE) || '[]'; - code = functionName + '(' + list + ')'; - break; - case 'RANDOM': - var functionName = Blockly.PHP.provideFunction_( - 'math_random_list', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '($list) {', - ' $x = rand(0, count($list)-1);', - ' return $list[$x];', - '}']); - list = Blockly.PHP.valueToCode(block, 'LIST', - Blockly.PHP.ORDER_NONE) || '[]'; - code = functionName + '(' + list + ')'; - break; - default: - throw 'Unknown operator: ' + func; - } - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['math_modulo'] = function(block) { - // Remainder computation. - var argument0 = Blockly.PHP.valueToCode(block, 'DIVIDEND', - Blockly.PHP.ORDER_MODULUS) || '0'; - var argument1 = Blockly.PHP.valueToCode(block, 'DIVISOR', - Blockly.PHP.ORDER_MODULUS) || '0'; - var code = argument0 + ' % ' + argument1; - return [code, Blockly.PHP.ORDER_MODULUS]; -}; - -Blockly.PHP['math_constrain'] = function(block) { - // Constrain a number between two limits. - var argument0 = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_COMMA) || '0'; - var argument1 = Blockly.PHP.valueToCode(block, 'LOW', - Blockly.PHP.ORDER_COMMA) || '0'; - var argument2 = Blockly.PHP.valueToCode(block, 'HIGH', - Blockly.PHP.ORDER_COMMA) || 'Infinity'; - var code = 'min(max(' + argument0 + ', ' + argument1 + '), ' + - argument2 + ')'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['math_random_int'] = function(block) { - // Random integer between [X] and [Y]. - var argument0 = Blockly.PHP.valueToCode(block, 'FROM', - Blockly.PHP.ORDER_COMMA) || '0'; - var argument1 = Blockly.PHP.valueToCode(block, 'TO', - Blockly.PHP.ORDER_COMMA) || '0'; - var functionName = Blockly.PHP.provideFunction_( - 'math_random_int', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '($a, $b) {', - ' if ($a > $b) {', - ' return rand($b, $a);', - ' }', - ' return rand($a, $b);', - '}']); - var code = functionName + '(' + argument0 + ', ' + argument1 + ')'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['math_random_float'] = function(block) { - // Random fraction between 0 and 1. - return ['(float)rand()/(float)getrandmax()', Blockly.PHP.ORDER_FUNCTION_CALL]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/php/procedures.js b/backend/_pv_1_3_5/static/blockly/generators/php/procedures.js deleted file mode 100755 index 2131bebde..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/php/procedures.js +++ /dev/null @@ -1,123 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2015 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating PHP for procedure blocks. - * @author daarond@gmail.com (Daaron Dwyer) - */ -'use strict'; - -goog.provide('Blockly.PHP.procedures'); - -goog.require('Blockly.PHP'); - -Blockly.PHP['procedures_defreturn'] = function(block) { - // Define a procedure with a return value. - // First, add a 'global' statement for every variable that is assigned. - var globals = block.workspace.variableList; - for (var i = globals.length - 1; i >= 0; i--) { - var varName = globals[i]; - if (block.arguments_.indexOf(varName) == -1) { - globals[i] = Blockly.PHP.variableDB_.getName(varName, - Blockly.Variables.NAME_TYPE); - } else { - // This variable is actually a parameter name. Do not include it in - // the list of globals, thus allowing it be of local scope. - globals.splice(i, 1); - } - } - globals = globals.length ? ' global ' + globals.join(', ') + ';\n' : ''; - - var funcName = Blockly.PHP.variableDB_.getName( - block.getFieldValue('NAME'), Blockly.Procedures.NAME_TYPE); - var branch = Blockly.PHP.statementToCode(block, 'STACK'); - if (Blockly.PHP.STATEMENT_PREFIX) { - branch = Blockly.PHP.prefixLines( - Blockly.PHP.STATEMENT_PREFIX.replace(/%1/g, - '\'' + block.id + '\''), Blockly.PHP.INDENT) + branch; - } - if (Blockly.PHP.INFINITE_LOOP_TRAP) { - branch = Blockly.PHP.INFINITE_LOOP_TRAP.replace(/%1/g, - '\'' + block.id + '\'') + branch; - } - var returnValue = Blockly.PHP.valueToCode(block, 'RETURN', - Blockly.PHP.ORDER_NONE) || ''; - if (returnValue) { - returnValue = ' return ' + returnValue + ';\n'; - } - var args = []; - for (var i = 0; i < block.arguments_.length; i++) { - args[i] = Blockly.PHP.variableDB_.getName(block.arguments_[i], - Blockly.Variables.NAME_TYPE); - } - var code = 'function ' + funcName + '(' + args.join(', ') + ') {\n' + - globals + branch + returnValue + '}'; - code = Blockly.PHP.scrub_(block, code); - // Add % so as not to collide with helper functions in definitions list. - Blockly.PHP.definitions_['%' + funcName] = code; - return null; -}; - -// Defining a procedure without a return value uses the same generator as -// a procedure with a return value. -Blockly.PHP['procedures_defnoreturn'] = - Blockly.PHP['procedures_defreturn']; - -Blockly.PHP['procedures_callreturn'] = function(block) { - // Call a procedure with a return value. - var funcName = Blockly.PHP.variableDB_.getName( - block.getFieldValue('NAME'), Blockly.Procedures.NAME_TYPE); - var args = []; - for (var i = 0; i < block.arguments_.length; i++) { - args[i] = Blockly.PHP.valueToCode(block, 'ARG' + i, - Blockly.PHP.ORDER_COMMA) || 'null'; - } - var code = funcName + '(' + args.join(', ') + ')'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['procedures_callnoreturn'] = function(block) { - // Call a procedure with no return value. - var funcName = Blockly.PHP.variableDB_.getName( - block.getFieldValue('NAME'), Blockly.Procedures.NAME_TYPE); - var args = []; - for (var i = 0; i < block.arguments_.length; i++) { - args[i] = Blockly.PHP.valueToCode(block, 'ARG' + i, - Blockly.PHP.ORDER_COMMA) || 'null'; - } - var code = funcName + '(' + args.join(', ') + ');\n'; - return code; -}; - -Blockly.PHP['procedures_ifreturn'] = function(block) { - // Conditionally return value from a procedure. - var condition = Blockly.PHP.valueToCode(block, 'CONDITION', - Blockly.PHP.ORDER_NONE) || 'false'; - var code = 'if (' + condition + ') {\n'; - if (block.hasReturnValue_) { - var value = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_NONE) || 'null'; - code += ' return ' + value + ';\n'; - } else { - code += ' return;\n'; - } - code += '}\n'; - return code; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/php/text.js b/backend/_pv_1_3_5/static/blockly/generators/php/text.js deleted file mode 100755 index efc0f2de3..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/php/text.js +++ /dev/null @@ -1,250 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2015 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating PHP for text blocks. - * @author daarond@gmail.com (Daaron Dwyer) - */ -'use strict'; - -goog.provide('Blockly.PHP.texts'); - -goog.require('Blockly.PHP'); - - -Blockly.PHP['text'] = function(block) { - // Text value. - var code = Blockly.PHP.quote_(block.getFieldValue('TEXT')); - return [code, Blockly.PHP.ORDER_ATOMIC]; -}; - -Blockly.PHP['text_join'] = function(block) { - // Create a string made up of any number of elements of any type. - if (block.itemCount_ == 0) { - return ['\'\'', Blockly.PHP.ORDER_ATOMIC]; - } else if (block.itemCount_ == 1) { - var element = Blockly.PHP.valueToCode(block, 'ADD0', - Blockly.PHP.ORDER_NONE) || '\'\''; - var code = element; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; - } else if (block.itemCount_ == 2) { - var element0 = Blockly.PHP.valueToCode(block, 'ADD0', - Blockly.PHP.ORDER_NONE) || '\'\''; - var element1 = Blockly.PHP.valueToCode(block, 'ADD1', - Blockly.PHP.ORDER_NONE) || '\'\''; - var code = element0 + ' . ' + element1; - return [code, Blockly.PHP.ORDER_ADDITION]; - } else { - var elements = new Array(block.itemCount_); - for (var i = 0; i < block.itemCount_; i++) { - elements[i] = Blockly.PHP.valueToCode(block, 'ADD' + i, - Blockly.PHP.ORDER_COMMA) || '\'\''; - } - var code = 'implode(\'\', array(' + elements.join(',') + '))'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; - } -}; - -Blockly.PHP['text_append'] = function(block) { - // Append to a variable in place. - var varName = Blockly.PHP.variableDB_.getName( - block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); - var value = Blockly.PHP.valueToCode(block, 'TEXT', - Blockly.PHP.ORDER_ASSIGNMENT) || '\'\''; - return varName + ' .= ' + value + ';\n'; -}; - -Blockly.PHP['text_length'] = function(block) { - // String or array length. - var functionName = Blockly.PHP.provideFunction_( - 'length', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + '($value) {', - ' if (is_string($value)) {', - ' return strlen($value);', - ' } else {', - ' return count($value);', - ' }', - '}']); - var text = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_NONE) || '\'\''; - return [functionName + '(' + text + ')', Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['text_isEmpty'] = function(block) { - // Is the string null or array empty? - var text = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_NONE) || '\'\''; - return ['empty(' + text + ')', Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['text_indexOf'] = function(block) { - // Search the text for a substring. - var operator = block.getFieldValue('END') == 'FIRST' ? - 'strpos' : 'strrpos'; - var substring = Blockly.PHP.valueToCode(block, 'FIND', - Blockly.PHP.ORDER_NONE) || '\'\''; - var text = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_NONE) || '\'\''; - if (Blockly.PHP.ONE_BASED_INDEXING) { - var errorIndex = ' 0'; - var indexAdjustment = ' + 1'; - } else { - var errorIndex = ' -1'; - var indexAdjustment = ''; - } - var functionName = Blockly.PHP.provideFunction_( - block.getFieldValue('END') == 'FIRST' ? - 'text_indexOf' : 'text_lastIndexOf', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '($text, $search) {', - ' $pos = ' + operator + '($text, $search);', - ' return $pos === false ? ' + errorIndex + ' : $pos' + - indexAdjustment + ';', - '}']); - var code = functionName + '(' + text + ', ' + substring + ')'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['text_charAt'] = function(block) { - // Get letter at index. - var where = block.getFieldValue('WHERE') || 'FROM_START'; - var textOrder = (where == 'RANDOM') ? Blockly.PHP.ORDER_NONE : - Blockly.PHP.ORDER_COMMA; - var text = Blockly.PHP.valueToCode(block, 'VALUE', textOrder) || '\'\''; - switch (where) { - case 'FIRST': - var code = 'substr(' + text + ', 0, 1)'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; - case 'LAST': - var code = 'substr(' + text + ', -1)'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; - case 'FROM_START': - var at = Blockly.PHP.getAdjusted(block, 'AT'); - var code = 'substr(' + text + ', ' + at + ', 1)'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; - case 'FROM_END': - var at = Blockly.PHP.getAdjusted(block, 'AT', 1, true); - var code = 'substr(' + text + ', ' + at + ', 1)'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; - case 'RANDOM': - var functionName = Blockly.PHP.provideFunction_( - 'text_random_letter', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + '($text) {', - ' return $text[rand(0, strlen($text) - 1)];', - '}']); - code = functionName + '(' + text + ')'; - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; - } - throw 'Unhandled option (text_charAt).'; -}; - -Blockly.PHP['text_getSubstring'] = function(block) { - // Get substring. - var text = Blockly.PHP.valueToCode(block, 'STRING', - Blockly.PHP.ORDER_FUNCTION_CALL) || '\'\''; - var where1 = block.getFieldValue('WHERE1'); - var where2 = block.getFieldValue('WHERE2'); - if (where1 == 'FIRST' && where2 == 'LAST') { - var code = text; - } else { - var at1 = Blockly.PHP.getAdjusted(block, 'AT1'); - var at2 = Blockly.PHP.getAdjusted(block, 'AT2'); - var functionName = Blockly.PHP.provideFunction_( - 'text_get_substring', - ['function ' + Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_ + - '($text, $where1, $at1, $where2, $at2) {', - ' if ($where1 == \'FROM_END\') {', - ' $at1 = strlen($text) - 1 - $at1;', - ' } else if ($where1 == \'FIRST\') {', - ' $at1 = 0;', - ' } else if ($where1 != \'FROM_START\'){', - ' throw new Exception(\'Unhandled option (text_get_substring).\');', - ' }', - ' $length = 0;', - ' if ($where2 == \'FROM_START\') {', - ' $length = $at2 - $at1 + 1;', - ' } else if ($where2 == \'FROM_END\') {', - ' $length = strlen($text) - $at1 - $at2;', - ' } else if ($where2 == \'LAST\') {', - ' $length = strlen($text) - $at1;', - ' } else {', - ' throw new Exception(\'Unhandled option (text_get_substring).\');', - ' }', - ' return substr($text, $at1, $length);', - '}']); - var code = functionName + '(' + text + ', \'' + - where1 + '\', ' + at1 + ', \'' + where2 + '\', ' + at2 + ')'; - } - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['text_changeCase'] = function(block) { - // Change capitalization. - var text = Blockly.PHP.valueToCode(block, 'TEXT', - Blockly.PHP.ORDER_NONE) || '\'\''; - if (block.getFieldValue('CASE') == 'UPPERCASE') { - var code = 'strtoupper(' + text + ')'; - } else if (block.getFieldValue('CASE') == 'LOWERCASE') { - var code = 'strtolower(' + text + ')'; - } else if (block.getFieldValue('CASE') == 'TITLECASE') { - var code = 'ucwords(strtolower(' + text + '))'; - } - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['text_trim'] = function(block) { - // Trim spaces. - var OPERATORS = { - 'LEFT': 'ltrim', - 'RIGHT': 'rtrim', - 'BOTH': 'trim' - }; - var operator = OPERATORS[block.getFieldValue('MODE')]; - var text = Blockly.PHP.valueToCode(block, 'TEXT', - Blockly.PHP.ORDER_NONE) || '\'\''; - return [operator + '(' + text + ')', Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['text_print'] = function(block) { - // Print statement. - var msg = Blockly.PHP.valueToCode(block, 'TEXT', - Blockly.PHP.ORDER_NONE) || '\'\''; - return 'print(' + msg + ');\n'; -}; - -Blockly.PHP['text_prompt_ext'] = function(block) { - // Prompt function. - if (block.getField('TEXT')) { - // Internal message. - var msg = Blockly.PHP.quote_(block.getFieldValue('TEXT')); - } else { - // External message. - var msg = Blockly.PHP.valueToCode(block, 'TEXT', - Blockly.PHP.ORDER_NONE) || '\'\''; - } - var code = 'readline(' + msg + ')'; - var toNumber = block.getFieldValue('TYPE') == 'NUMBER'; - if (toNumber) { - code = 'floatval(' + code + ')'; - } - return [code, Blockly.PHP.ORDER_FUNCTION_CALL]; -}; - -Blockly.PHP['text_prompt'] = Blockly.PHP['text_prompt_ext']; diff --git a/backend/_pv_1_3_5/static/blockly/generators/php/variables.js b/backend/_pv_1_3_5/static/blockly/generators/php/variables.js deleted file mode 100755 index 466774b3f..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/php/variables.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2015 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating PHP for variable blocks. - * @author daarond@gmail.com (Daaron Dwyer) - */ -'use strict'; - -goog.provide('Blockly.PHP.variables'); - -goog.require('Blockly.PHP'); - - -Blockly.PHP['variables_get'] = function(block) { - // Variable getter. - var code = Blockly.PHP.variableDB_.getName(block.getFieldValue('VAR'), - Blockly.Variables.NAME_TYPE); - return [code, Blockly.PHP.ORDER_ATOMIC]; -}; - -Blockly.PHP['variables_set'] = function(block) { - // Variable setter. - var argument0 = Blockly.PHP.valueToCode(block, 'VALUE', - Blockly.PHP.ORDER_ASSIGNMENT) || '0'; - var varName = Blockly.PHP.variableDB_.getName( - block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); - return varName + ' = ' + argument0 + ';\n'; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/python.js b/backend/_pv_1_3_5/static/blockly/generators/python.js deleted file mode 100755 index aad958251..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/python.js +++ /dev/null @@ -1,290 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Helper functions for generating Python for blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Python'); - -goog.require('Blockly.Generator'); - - -/** - * Python code generator. - * @type {!Blockly.Generator} - */ -Blockly.Python = new Blockly.Generator('Python'); - -/** - * List of illegal variable names. - * This is not intended to be a security feature. Blockly is 100% client-side, - * so bypassing this list is trivial. This is intended to prevent users from - * accidentally clobbering a built-in object or function. - * @private - */ -Blockly.Python.addReservedWords( - // import keyword - // print ','.join(keyword.kwlist) - // http://docs.python.org/reference/lexical_analysis.html#keywords - 'and,as,assert,break,class,continue,def,del,elif,else,except,exec,' + - 'finally,for,from,global,if,import,in,is,lambda,not,or,pass,print,raise,' + - 'return,try,while,with,yield,' + - //http://docs.python.org/library/constants.html - 'True,False,None,NotImplemented,Ellipsis,__debug__,quit,exit,copyright,' + - 'license,credits,' + - // http://docs.python.org/library/functions.html - 'abs,divmod,input,open,staticmethod,all,enumerate,int,ord,str,any,eval,' + - 'isinstance,pow,sum,basestring,execfile,issubclass,print,super,bin,file,' + - 'iter,property,tuple,bool,filter,len,range,type,bytearray,float,list,' + - 'raw_input,unichr,callable,format,locals,reduce,unicode,chr,frozenset,' + - 'long,reload,vars,classmethod,getattr,map,repr,xrange,cmp,globals,max,' + - 'reversed,zip,compile,hasattr,memoryview,round,__import__,complex,hash,' + - 'min,set,apply,delattr,help,next,setattr,buffer,dict,hex,object,slice,' + - 'coerce,dir,id,oct,sorted,intern' -); - -/** - * Order of operation ENUMs. - * http://docs.python.org/reference/expressions.html#summary - */ -Blockly.Python.ORDER_ATOMIC = 0; // 0 "" ... -Blockly.Python.ORDER_COLLECTION = 1; // tuples, lists, dictionaries -Blockly.Python.ORDER_STRING_CONVERSION = 1; // `expression...` -Blockly.Python.ORDER_MEMBER = 2.1; // . [] -Blockly.Python.ORDER_FUNCTION_CALL = 2.2; // () -Blockly.Python.ORDER_EXPONENTIATION = 3; // ** -Blockly.Python.ORDER_UNARY_SIGN = 4; // + - -Blockly.Python.ORDER_BITWISE_NOT = 4; // ~ -Blockly.Python.ORDER_MULTIPLICATIVE = 5; // * / // % -Blockly.Python.ORDER_ADDITIVE = 6; // + - -Blockly.Python.ORDER_BITWISE_SHIFT = 7; // << >> -Blockly.Python.ORDER_BITWISE_AND = 8; // & -Blockly.Python.ORDER_BITWISE_XOR = 9; // ^ -Blockly.Python.ORDER_BITWISE_OR = 10; // | -Blockly.Python.ORDER_RELATIONAL = 11; // in, not in, is, is not, - // <, <=, >, >=, <>, !=, == -Blockly.Python.ORDER_LOGICAL_NOT = 12; // not -Blockly.Python.ORDER_LOGICAL_AND = 13; // and -Blockly.Python.ORDER_LOGICAL_OR = 14; // or -Blockly.Python.ORDER_CONDITIONAL = 15; // if else -Blockly.Python.ORDER_LAMBDA = 16; // lambda -Blockly.Python.ORDER_NONE = 99; // (...) - -/** - * Allow for switching between one and zero based indexing for lists and text, - * one based by default. - */ -Blockly.Python.ONE_BASED_INDEXING = true; - -/** - * List of outer-inner pairings that do NOT require parentheses. - * @type {!Array.>} - */ -Blockly.Python.ORDER_OVERRIDES = [ - // (foo()).bar -> foo().bar - // (foo())[0] -> foo()[0] - [Blockly.Python.ORDER_FUNCTION_CALL, Blockly.Python.ORDER_MEMBER], - // (foo())() -> foo()() - [Blockly.Python.ORDER_FUNCTION_CALL, Blockly.Python.ORDER_FUNCTION_CALL], - // (foo.bar).baz -> foo.bar.baz - // (foo.bar)[0] -> foo.bar[0] - // (foo[0]).bar -> foo[0].bar - // (foo[0])[1] -> foo[0][1] - [Blockly.Python.ORDER_MEMBER, Blockly.Python.ORDER_MEMBER], - // (foo.bar)() -> foo.bar() - // (foo[0])() -> foo[0]() - [Blockly.Python.ORDER_MEMBER, Blockly.Python.ORDER_FUNCTION_CALL], - - // not (not foo) -> not not foo - [Blockly.Python.ORDER_LOGICAL_NOT, Blockly.Python.ORDER_LOGICAL_NOT], - // a and (b and c) -> a and b and c - [Blockly.Python.ORDER_LOGICAL_AND, Blockly.Python.ORDER_LOGICAL_AND], - // a or (b or c) -> a or b or c - [Blockly.Python.ORDER_LOGICAL_OR, Blockly.Python.ORDER_LOGICAL_OR] -]; - -/** - * Initialise the database of variable names. - * @param {!Blockly.Workspace} workspace Workspace to generate code from. - */ -Blockly.Python.init = function(workspace) { - /** - * Empty loops or conditionals are not allowed in Python. - */ - Blockly.Python.PASS = this.INDENT + 'pass\n'; - // Create a dictionary of definitions to be printed before the code. - Blockly.Python.definitions_ = Object.create(null); - // Create a dictionary mapping desired function names in definitions_ - // to actual function names (to avoid collisions with user functions). - Blockly.Python.functionNames_ = Object.create(null); - - if (!Blockly.Python.variableDB_) { - Blockly.Python.variableDB_ = - new Blockly.Names(Blockly.Python.RESERVED_WORDS_); - } else { - Blockly.Python.variableDB_.reset(); - } - - var defvars = []; - var variables = workspace.variableList; - for (var i = 0; i < variables.length; i++) { - defvars[i] = Blockly.Python.variableDB_.getName(variables[i], - Blockly.Variables.NAME_TYPE) + ' = None'; - } - Blockly.Python.definitions_['variables'] = defvars.join('\n'); -}; - -/** - * Prepend the generated code with the variable definitions. - * @param {string} code Generated code. - * @return {string} Completed code. - */ -Blockly.Python.finish = function(code) { - // Convert the definitions dictionary into a list. - var imports = []; - var definitions = []; - for (var name in Blockly.Python.definitions_) { - var def = Blockly.Python.definitions_[name]; - if (def.match(/^(from\s+\S+\s+)?import\s+\S+/)) { - imports.push(def); - } else { - definitions.push(def); - } - } - // Clean up temporary data. - delete Blockly.Python.definitions_; - delete Blockly.Python.functionNames_; - Blockly.Python.variableDB_.reset(); - var allDefs = imports.join('\n') + '\n\n' + definitions.join('\n\n'); - return allDefs.replace(/\n\n+/g, '\n\n').replace(/\n*$/, '\n\n\n') + code; -}; - -/** - * Naked values are top-level blocks with outputs that aren't plugged into - * anything. - * @param {string} line Line of generated code. - * @return {string} Legal line of code. - */ -Blockly.Python.scrubNakedValue = function(line) { - return line + '\n'; -}; - -/** - * Encode a string as a properly escaped Python string, complete with quotes. - * @param {string} string Text to encode. - * @return {string} Python string. - * @private - */ -Blockly.Python.quote_ = function(string) { - // Can't use goog.string.quote since % must also be escaped. - string = string.replace(/\\/g, '\\\\') - .replace(/\n/g, '\\\n') - .replace(/\%/g, '\\%') - .replace(/'/g, '\\\''); - return '\'' + string + '\''; -}; - -/** - * Common tasks for generating Python from blocks. - * Handles comments for the specified block and any connected value blocks. - * Calls any statements following this block. - * @param {!Blockly.Block} block The current block. - * @param {string} code The Python code created for this block. - * @return {string} Python code with comments and subsequent blocks added. - * @private - */ -Blockly.Python.scrub_ = function(block, code) { - var commentCode = ''; - // Only collect comments for blocks that aren't inline. - if (!block.outputConnection || !block.outputConnection.targetConnection) { - // Collect comment for this block. - var comment = block.getCommentText(); - comment = Blockly.utils.wrap(comment, Blockly.Python.COMMENT_WRAP - 3); - if (comment) { - if (block.getProcedureDef) { - // Use a comment block for function comments. - commentCode += '"""' + comment + '\n"""\n'; - } else { - commentCode += Blockly.Python.prefixLines(comment + '\n', '# '); - } - } - // Collect comments for all value arguments. - // Don't collect comments for nested statements. - for (var i = 0; i < block.inputList.length; i++) { - if (block.inputList[i].type == Blockly.INPUT_VALUE) { - var childBlock = block.inputList[i].connection.targetBlock(); - if (childBlock) { - var comment = Blockly.Python.allNestedComments(childBlock); - if (comment) { - commentCode += Blockly.Python.prefixLines(comment, '# '); - } - } - } - } - } - var nextBlock = block.nextConnection && block.nextConnection.targetBlock(); - var nextCode = Blockly.Python.blockToCode(nextBlock); - return commentCode + code + nextCode; -}; - -/** - * Gets a property and adjusts the value, taking into account indexing, and - * casts to an integer. - * @param {!Blockly.Block} block The block. - * @param {string} atId The property ID of the element to get. - * @param {number=} opt_delta Value to add. - * @param {boolean=} opt_negate Whether to negate the value. - * @return {string|number} - */ -Blockly.Python.getAdjustedInt = function(block, atId, opt_delta, opt_negate) { - var delta = opt_delta || 0; - if (Blockly.Python.ONE_BASED_INDEXING) { - delta--; - } - var defaultAtIndex = Blockly.Python.ONE_BASED_INDEXING ? '1' : '0'; - var atOrder = delta ? Blockly.Python.ORDER_ADDITIVE : - Blockly.Python.ORDER_NONE; - var at = Blockly.Python.valueToCode(block, atId, atOrder) || defaultAtIndex; - - if (Blockly.isNumber(at)) { - // If the index is a naked number, adjust it right now. - at = parseInt(at, 10) + delta; - if (opt_negate) { - at = -at; - } - } else { - // If the index is dynamic, adjust it in code. - if (delta > 0) { - at = 'int(' + at + ' + ' + delta + ')'; - } else if (delta < 0) { - at = 'int(' + at + ' - ' + -delta + ')'; - } else { - at = 'int(' + at + ')'; - } - if (opt_negate) { - at = '-' + at; - } - } - return at; -}; - diff --git a/backend/_pv_1_3_5/static/blockly/generators/python/colour.js b/backend/_pv_1_3_5/static/blockly/generators/python/colour.js deleted file mode 100755 index 68666a89b..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/python/colour.js +++ /dev/null @@ -1,86 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Python for colour blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Python.colour'); - -goog.require('Blockly.Python'); - - -Blockly.Python['colour_picker'] = function(block) { - // Colour picker. - var code = '\'' + block.getFieldValue('COLOUR') + '\''; - return [code, Blockly.Python.ORDER_ATOMIC]; -}; - -Blockly.Python['colour_random'] = function(block) { - // Generate a random colour. - Blockly.Python.definitions_['import_random'] = 'import random'; - var code = '\'#%06x\' % random.randint(0, 2**24 - 1)'; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; -}; - -Blockly.Python['colour_rgb'] = function(block) { - // Compose a colour from RGB components expressed as percentages. - var functionName = Blockly.Python.provideFunction_( - 'colour_rgb', - ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(r, g, b):', - ' r = round(min(100, max(0, r)) * 2.55)', - ' g = round(min(100, max(0, g)) * 2.55)', - ' b = round(min(100, max(0, b)) * 2.55)', - ' return \'#%02x%02x%02x\' % (r, g, b)']); - var r = Blockly.Python.valueToCode(block, 'RED', - Blockly.Python.ORDER_NONE) || 0; - var g = Blockly.Python.valueToCode(block, 'GREEN', - Blockly.Python.ORDER_NONE) || 0; - var b = Blockly.Python.valueToCode(block, 'BLUE', - Blockly.Python.ORDER_NONE) || 0; - var code = functionName + '(' + r + ', ' + g + ', ' + b + ')'; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; -}; - -Blockly.Python['colour_blend'] = function(block) { - // Blend two colours together. - var functionName = Blockly.Python.provideFunction_( - 'colour_blend', - ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + - '(colour1, colour2, ratio):', - ' r1, r2 = int(colour1[1:3], 16), int(colour2[1:3], 16)', - ' g1, g2 = int(colour1[3:5], 16), int(colour2[3:5], 16)', - ' b1, b2 = int(colour1[5:7], 16), int(colour2[5:7], 16)', - ' ratio = min(1, max(0, ratio))', - ' r = round(r1 * (1 - ratio) + r2 * ratio)', - ' g = round(g1 * (1 - ratio) + g2 * ratio)', - ' b = round(b1 * (1 - ratio) + b2 * ratio)', - ' return \'#%02x%02x%02x\' % (r, g, b)']); - var colour1 = Blockly.Python.valueToCode(block, 'COLOUR1', - Blockly.Python.ORDER_NONE) || '\'#000000\''; - var colour2 = Blockly.Python.valueToCode(block, 'COLOUR2', - Blockly.Python.ORDER_NONE) || '\'#000000\''; - var ratio = Blockly.Python.valueToCode(block, 'RATIO', - Blockly.Python.ORDER_NONE) || 0; - var code = functionName + '(' + colour1 + ', ' + colour2 + ', ' + ratio + ')'; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/python/lists.js b/backend/_pv_1_3_5/static/blockly/generators/python/lists.js deleted file mode 100755 index b831d4d2f..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/python/lists.js +++ /dev/null @@ -1,355 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Python for list blocks. - * @author q.neutron@gmail.com (Quynh Neutron) - */ -'use strict'; - -goog.provide('Blockly.Python.lists'); - -goog.require('Blockly.Python'); - - -Blockly.Python['lists_create_empty'] = function(block) { - // Create an empty list. - return ['[]', Blockly.Python.ORDER_ATOMIC]; -}; - -Blockly.Python['lists_create_with'] = function(block) { - // Create a list with any number of elements of any type. - var elements = new Array(block.itemCount_); - for (var i = 0; i < block.itemCount_; i++) { - elements[i] = Blockly.Python.valueToCode(block, 'ADD' + i, - Blockly.Python.ORDER_NONE) || 'None'; - } - var code = '[' + elements.join(', ') + ']'; - return [code, Blockly.Python.ORDER_ATOMIC]; -}; - -Blockly.Python['lists_repeat'] = function(block) { - // Create a list with one element repeated. - var item = Blockly.Python.valueToCode(block, 'ITEM', - Blockly.Python.ORDER_NONE) || 'None'; - var times = Blockly.Python.valueToCode(block, 'NUM', - Blockly.Python.ORDER_MULTIPLICATIVE) || '0'; - var code = '[' + item + '] * ' + times; - return [code, Blockly.Python.ORDER_MULTIPLICATIVE]; -}; - -Blockly.Python['lists_length'] = function(block) { - // String or array length. - var list = Blockly.Python.valueToCode(block, 'VALUE', - Blockly.Python.ORDER_NONE) || '[]'; - return ['len(' + list + ')', Blockly.Python.ORDER_FUNCTION_CALL]; -}; - -Blockly.Python['lists_isEmpty'] = function(block) { - // Is the string null or array empty? - var list = Blockly.Python.valueToCode(block, 'VALUE', - Blockly.Python.ORDER_NONE) || '[]'; - var code = 'not len(' + list + ')'; - return [code, Blockly.Python.ORDER_LOGICAL_NOT]; -}; - -Blockly.Python['lists_indexOf'] = function(block) { - // Find an item in the list. - var item = Blockly.Python.valueToCode(block, 'FIND', - Blockly.Python.ORDER_NONE) || '[]'; - var list = Blockly.Python.valueToCode(block, 'VALUE', - Blockly.Python.ORDER_NONE) || '\'\''; - if (Blockly.Python.ONE_BASED_INDEXING) { - var errorIndex = ' 0'; - var firstIndexAdjustment = ' + 1'; - var lastIndexAdjustment = ''; - } else { - var errorIndex = ' -1'; - var firstIndexAdjustment = ''; - var lastIndexAdjustment = ' - 1'; - } - if (block.getFieldValue('END') == 'FIRST') { - var functionName = Blockly.Python.provideFunction_( - 'first_index', - ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + - '(my_list, elem):', - ' try: index = my_list.index(elem)' + firstIndexAdjustment, - ' except: index =' + errorIndex, - ' return index']); - var code = functionName + '(' + list + ', ' + item + ')'; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; - } - var functionName = Blockly.Python.provideFunction_( - 'last_index', - ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(my_list, elem):', - ' try: index = len(my_list) - my_list[::-1].index(elem)' + - lastIndexAdjustment, - ' except: index =' + errorIndex, - ' return index']); - var code = functionName + '(' + list + ', ' + item + ')'; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; -}; - -Blockly.Python['lists_getIndex'] = function(block) { - // Get element at index. - // Note: Until January 2013 this block did not have MODE or WHERE inputs. - var mode = block.getFieldValue('MODE') || 'GET'; - var where = block.getFieldValue('WHERE') || 'FROM_START'; - var listOrder = (where == 'RANDOM') ? Blockly.Python.ORDER_NONE : - Blockly.Python.ORDER_MEMBER; - var list = Blockly.Python.valueToCode(block, 'VALUE', listOrder) || '[]'; - - switch (where) { - case 'FIRST': - if (mode == 'GET') { - var code = list + '[0]'; - return [code, Blockly.Python.ORDER_MEMBER]; - } else if (mode == 'GET_REMOVE') { - var code = list + '.pop(0)'; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; - } else if (mode == 'REMOVE') { - return list + '.pop(0)\n'; - } - break; - case 'LAST': - if (mode == 'GET') { - var code = list + '[-1]'; - return [code, Blockly.Python.ORDER_MEMBER]; - } else if (mode == 'GET_REMOVE') { - var code = list + '.pop()'; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; - } else if (mode == 'REMOVE') { - return list + '.pop()\n'; - } - break; - case 'FROM_START': - var at = Blockly.Python.getAdjustedInt(block, 'AT'); - if (mode == 'GET') { - var code = list + '[' + at + ']'; - return [code, Blockly.Python.ORDER_MEMBER]; - } else if (mode == 'GET_REMOVE') { - var code = list + '.pop(' + at + ')'; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; - } else if (mode == 'REMOVE') { - return list + '.pop(' + at + ')\n'; - } - break; - case'FROM_END': - var at = Blockly.Python.getAdjustedInt(block, 'AT', 1, true); - if (mode == 'GET') { - var code = list + '[' + at + ']'; - return [code, Blockly.Python.ORDER_MEMBER]; - } else if (mode == 'GET_REMOVE') { - var code = list + '.pop(' + at + ')'; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; - } else if (mode == 'REMOVE') { - return list + '.pop(' + at + ')\n'; - } - break; - case 'RANDOM': - Blockly.Python.definitions_['import_random'] = 'import random'; - if (mode == 'GET') { - code = 'random.choice(' + list + ')'; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; - } else { - var functionName = Blockly.Python.provideFunction_( - 'lists_remove_random_item', - ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList):', - ' x = int(random.random() * len(myList))', - ' return myList.pop(x)']); - code = functionName + '(' + list + ')'; - if (mode == 'GET_REMOVE') { - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; - } else if (mode == 'REMOVE') { - return code + '\n'; - } - } - break; - } - throw 'Unhandled combination (lists_getIndex).'; -}; - -Blockly.Python['lists_setIndex'] = function(block) { - // Set element at index. - // Note: Until February 2013 this block did not have MODE or WHERE inputs. - var list = Blockly.Python.valueToCode(block, 'LIST', - Blockly.Python.ORDER_MEMBER) || '[]'; - var mode = block.getFieldValue('MODE') || 'GET'; - var where = block.getFieldValue('WHERE') || 'FROM_START'; - var value = Blockly.Python.valueToCode(block, 'TO', - Blockly.Python.ORDER_NONE) || 'None'; - // Cache non-trivial values to variables to prevent repeated look-ups. - // Closure, which accesses and modifies 'list'. - function cacheList() { - if (list.match(/^\w+$/)) { - return ''; - } - var listVar = Blockly.Python.variableDB_.getDistinctName( - 'tmp_list', Blockly.Variables.NAME_TYPE); - var code = listVar + ' = ' + list + '\n'; - list = listVar; - return code; - } - - switch (where) { - case 'FIRST': - if (mode == 'SET') { - return list + '[0] = ' + value + '\n'; - } else if (mode == 'INSERT') { - return list + '.insert(0, ' + value + ')\n'; - } - break; - case 'LAST': - if (mode == 'SET') { - return list + '[-1] = ' + value + '\n'; - } else if (mode == 'INSERT') { - return list + '.append(' + value + ')\n'; - } - break; - case 'FROM_START': - var at = Blockly.Python.getAdjustedInt(block, 'AT'); - if (mode == 'SET') { - return list + '[' + at + '] = ' + value + '\n'; - } else if (mode == 'INSERT') { - return list + '.insert(' + at + ', ' + value + ')\n'; - } - break; - case 'FROM_END': - var at = Blockly.Python.getAdjustedInt(block, 'AT', 1, true); - if (mode == 'SET') { - return list + '[' + at + '] = ' + value + '\n'; - } else if (mode == 'INSERT') { - return list + '.insert(' + at + ', ' + value + ')\n'; - } - break; - case 'RANDOM': - Blockly.Python.definitions_['import_random'] = 'import random'; - var code = cacheList(); - var xVar = Blockly.Python.variableDB_.getDistinctName( - 'tmp_x', Blockly.Variables.NAME_TYPE); - code += xVar + ' = int(random.random() * len(' + list + '))\n'; - if (mode == 'SET') { - code += list + '[' + xVar + '] = ' + value + '\n'; - return code; - } else if (mode == 'INSERT') { - code += list + '.insert(' + xVar + ', ' + value + ')\n'; - return code; - } - break; - } - throw 'Unhandled combination (lists_setIndex).'; -}; - -Blockly.Python['lists_getSublist'] = function(block) { - // Get sublist. - var list = Blockly.Python.valueToCode(block, 'LIST', - Blockly.Python.ORDER_MEMBER) || '[]'; - var where1 = block.getFieldValue('WHERE1'); - var where2 = block.getFieldValue('WHERE2'); - switch (where1) { - case 'FROM_START': - var at1 = Blockly.Python.getAdjustedInt(block, 'AT1'); - if (at1 == '0') { - at1 = ''; - } - break; - case 'FROM_END': - var at1 = Blockly.Python.getAdjustedInt(block, 'AT1', 1, true); - break; - case 'FIRST': - var at1 = ''; - break; - default: - throw 'Unhandled option (lists_getSublist)'; - } - switch (where2) { - case 'FROM_START': - var at2 = Blockly.Python.getAdjustedInt(block, 'AT2', 1); - break; - case 'FROM_END': - var at2 = Blockly.Python.getAdjustedInt(block, 'AT2', 0, true); - // Ensure that if the result calculated is 0 that sub-sequence will - // include all elements as expected. - if (!Blockly.isNumber(String(at2))) { - Blockly.Python.definitions_['import_sys'] = 'import sys'; - at2 += ' or sys.maxsize'; - } else if (at2 == '0') { - at2 = ''; - } - break; - case 'LAST': - var at2 = ''; - break; - default: - throw 'Unhandled option (lists_getSublist)'; - } - var code = list + '[' + at1 + ' : ' + at2 + ']'; - return [code, Blockly.Python.ORDER_MEMBER]; -}; - -Blockly.Python['lists_sort'] = function(block) { - // Block for sorting a list. - var list = (Blockly.Python.valueToCode(block, 'LIST', - Blockly.Python.ORDER_NONE) || '[]'); - var type = block.getFieldValue('TYPE'); - var reverse = block.getFieldValue('DIRECTION') === '1' ? 'False' : 'True'; - var sortFunctionName = Blockly.Python.provideFunction_('lists_sort', - ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + - '(my_list, type, reverse):', - ' def try_float(s):', - ' try:', - ' return float(s)', - ' except:', - ' return 0', - ' key_funcs = {', - ' "NUMERIC": try_float,', - ' "TEXT": str,', - ' "IGNORE_CASE": lambda s: str(s).lower()', - ' }', - ' key_func = key_funcs[type]', - ' list_cpy = list(my_list)', // Clone the list. - ' return sorted(list_cpy, key=key_func, reverse=reverse)' - ]); - - var code = sortFunctionName + - '(' + list + ', "' + type + '", ' + reverse + ')'; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; -}; - -Blockly.Python['lists_split'] = function(block) { - // Block for splitting text into a list, or joining a list into text. - var mode = block.getFieldValue('MODE'); - if (mode == 'SPLIT') { - var value_input = Blockly.Python.valueToCode(block, 'INPUT', - Blockly.Python.ORDER_MEMBER) || '\'\''; - var value_delim = Blockly.Python.valueToCode(block, 'DELIM', - Blockly.Python.ORDER_NONE); - var code = value_input + '.split(' + value_delim + ')'; - } else if (mode == 'JOIN') { - var value_input = Blockly.Python.valueToCode(block, 'INPUT', - Blockly.Python.ORDER_NONE) || '[]'; - var value_delim = Blockly.Python.valueToCode(block, 'DELIM', - Blockly.Python.ORDER_MEMBER) || '\'\''; - var code = value_delim + '.join(' + value_input + ')'; - } else { - throw 'Unknown mode: ' + mode; - } - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/python/logic.js b/backend/_pv_1_3_5/static/blockly/generators/python/logic.js deleted file mode 100755 index a485e5c9e..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/python/logic.js +++ /dev/null @@ -1,127 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Python for logic blocks. - * @author q.neutron@gmail.com (Quynh Neutron) - */ -'use strict'; - -goog.provide('Blockly.Python.logic'); - -goog.require('Blockly.Python'); - - -Blockly.Python['controls_if'] = function(block) { - // If/elseif/else condition. - var n = 0; - var argument = Blockly.Python.valueToCode(block, 'IF' + n, - Blockly.Python.ORDER_NONE) || 'False'; - var branch = Blockly.Python.statementToCode(block, 'DO' + n) || - Blockly.Python.PASS; - var code = 'if ' + argument + ':\n' + branch; - for (n = 1; n <= block.elseifCount_; n++) { - argument = Blockly.Python.valueToCode(block, 'IF' + n, - Blockly.Python.ORDER_NONE) || 'False'; - branch = Blockly.Python.statementToCode(block, 'DO' + n) || - Blockly.Python.PASS; - code += 'elif ' + argument + ':\n' + branch; - } - if (block.elseCount_) { - branch = Blockly.Python.statementToCode(block, 'ELSE') || - Blockly.Python.PASS; - code += 'else:\n' + branch; - } - return code; -}; - -Blockly.Python['logic_compare'] = function(block) { - // Comparison operator. - var OPERATORS = { - 'EQ': '==', - 'NEQ': '!=', - 'LT': '<', - 'LTE': '<=', - 'GT': '>', - 'GTE': '>=' - }; - var operator = OPERATORS[block.getFieldValue('OP')]; - var order = Blockly.Python.ORDER_RELATIONAL; - var argument0 = Blockly.Python.valueToCode(block, 'A', order) || '0'; - var argument1 = Blockly.Python.valueToCode(block, 'B', order) || '0'; - var code = argument0 + ' ' + operator + ' ' + argument1; - return [code, order]; -}; - -Blockly.Python['logic_operation'] = function(block) { - // Operations 'and', 'or'. - var operator = (block.getFieldValue('OP') == 'AND') ? 'and' : 'or'; - var order = (operator == 'and') ? Blockly.Python.ORDER_LOGICAL_AND : - Blockly.Python.ORDER_LOGICAL_OR; - var argument0 = Blockly.Python.valueToCode(block, 'A', order); - var argument1 = Blockly.Python.valueToCode(block, 'B', order); - if (!argument0 && !argument1) { - // If there are no arguments, then the return value is false. - argument0 = 'False'; - argument1 = 'False'; - } else { - // Single missing arguments have no effect on the return value. - var defaultArgument = (operator == 'and') ? 'True' : 'False'; - if (!argument0) { - argument0 = defaultArgument; - } - if (!argument1) { - argument1 = defaultArgument; - } - } - var code = argument0 + ' ' + operator + ' ' + argument1; - return [code, order]; -}; - -Blockly.Python['logic_negate'] = function(block) { - // Negation. - var argument0 = Blockly.Python.valueToCode(block, 'BOOL', - Blockly.Python.ORDER_LOGICAL_NOT) || 'True'; - var code = 'not ' + argument0; - return [code, Blockly.Python.ORDER_LOGICAL_NOT]; -}; - -Blockly.Python['logic_boolean'] = function(block) { - // Boolean values true and false. - var code = (block.getFieldValue('BOOL') == 'TRUE') ? 'True' : 'False'; - return [code, Blockly.Python.ORDER_ATOMIC]; -}; - -Blockly.Python['logic_null'] = function(block) { - // Null data type. - return ['None', Blockly.Python.ORDER_ATOMIC]; -}; - -Blockly.Python['logic_ternary'] = function(block) { - // Ternary operator. - var value_if = Blockly.Python.valueToCode(block, 'IF', - Blockly.Python.ORDER_CONDITIONAL) || 'False'; - var value_then = Blockly.Python.valueToCode(block, 'THEN', - Blockly.Python.ORDER_CONDITIONAL) || 'None'; - var value_else = Blockly.Python.valueToCode(block, 'ELSE', - Blockly.Python.ORDER_CONDITIONAL) || 'None'; - var code = value_then + ' if ' + value_if + ' else ' + value_else; - return [code, Blockly.Python.ORDER_CONDITIONAL]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/python/loops.js b/backend/_pv_1_3_5/static/blockly/generators/python/loops.js deleted file mode 100755 index 3cb1ab900..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/python/loops.js +++ /dev/null @@ -1,211 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Python for loop blocks. - * @author q.neutron@gmail.com (Quynh Neutron) - */ -'use strict'; - -goog.provide('Blockly.Python.loops'); - -goog.require('Blockly.Python'); - - -Blockly.Python['controls_repeat_ext'] = function(block) { - // Repeat n times. - if (block.getField('TIMES')) { - // Internal number. - var repeats = String(parseInt(block.getFieldValue('TIMES'), 10)); - } else { - // External number. - var repeats = Blockly.Python.valueToCode(block, 'TIMES', - Blockly.Python.ORDER_NONE) || '0'; - } - if (Blockly.isNumber(repeats)) { - repeats = parseInt(repeats, 10); - } else { - repeats = 'int(' + repeats + ')'; - } - var branch = Blockly.Python.statementToCode(block, 'DO'); - branch = Blockly.Python.addLoopTrap(branch, block.id) || - Blockly.Python.PASS; - var loopVar = Blockly.Python.variableDB_.getDistinctName( - 'count', Blockly.Variables.NAME_TYPE); - var code = 'for ' + loopVar + ' in range(' + repeats + '):\n' + branch; - return code; -}; - -Blockly.Python['controls_repeat'] = Blockly.Python['controls_repeat_ext']; - -Blockly.Python['controls_whileUntil'] = function(block) { - // Do while/until loop. - var until = block.getFieldValue('MODE') == 'UNTIL'; - var argument0 = Blockly.Python.valueToCode(block, 'BOOL', - until ? Blockly.Python.ORDER_LOGICAL_NOT : - Blockly.Python.ORDER_NONE) || 'False'; - var branch = Blockly.Python.statementToCode(block, 'DO'); - branch = Blockly.Python.addLoopTrap(branch, block.id) || - Blockly.Python.PASS; - if (until) { - argument0 = 'not ' + argument0; - } - return 'while ' + argument0 + ':\n' + branch; -}; - -Blockly.Python['controls_for'] = function(block) { - // For loop. - var variable0 = Blockly.Python.variableDB_.getName( - block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); - var argument0 = Blockly.Python.valueToCode(block, 'FROM', - Blockly.Python.ORDER_NONE) || '0'; - var argument1 = Blockly.Python.valueToCode(block, 'TO', - Blockly.Python.ORDER_NONE) || '0'; - var increment = Blockly.Python.valueToCode(block, 'BY', - Blockly.Python.ORDER_NONE) || '1'; - var branch = Blockly.Python.statementToCode(block, 'DO'); - branch = Blockly.Python.addLoopTrap(branch, block.id) || - Blockly.Python.PASS; - - var code = ''; - var range; - - // Helper functions. - var defineUpRange = function() { - return Blockly.Python.provideFunction_( - 'upRange', - ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + - '(start, stop, step):', - ' while start <= stop:', - ' yield start', - ' start += abs(step)']); - }; - var defineDownRange = function() { - return Blockly.Python.provideFunction_( - 'downRange', - ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + - '(start, stop, step):', - ' while start >= stop:', - ' yield start', - ' start -= abs(step)']); - }; - // Arguments are legal Python code (numbers or strings returned by scrub()). - var generateUpDownRange = function(start, end, inc) { - return '(' + start + ' <= ' + end + ') and ' + - defineUpRange() + '(' + start + ', ' + end + ', ' + inc + ') or ' + - defineDownRange() + '(' + start + ', ' + end + ', ' + inc + ')'; - }; - - if (Blockly.isNumber(argument0) && Blockly.isNumber(argument1) && - Blockly.isNumber(increment)) { - // All parameters are simple numbers. - argument0 = parseFloat(argument0); - argument1 = parseFloat(argument1); - increment = Math.abs(parseFloat(increment)); - if (argument0 % 1 === 0 && argument1 % 1 === 0 && increment % 1 === 0) { - // All parameters are integers. - if (argument0 <= argument1) { - // Count up. - argument1++; - if (argument0 == 0 && increment == 1) { - // If starting index is 0, omit it. - range = argument1; - } else { - range = argument0 + ', ' + argument1; - } - // If increment isn't 1, it must be explicit. - if (increment != 1) { - range += ', ' + increment; - } - } else { - // Count down. - argument1--; - range = argument0 + ', ' + argument1 + ', -' + increment; - } - range = 'range(' + range + ')'; - } else { - // At least one of the parameters is not an integer. - if (argument0 < argument1) { - range = defineUpRange(); - } else { - range = defineDownRange(); - } - range += '(' + argument0 + ', ' + argument1 + ', ' + increment + ')'; - } - } else { - // Cache non-trivial values to variables to prevent repeated look-ups. - var scrub = function(arg, suffix) { - if (Blockly.isNumber(arg)) { - // Simple number. - arg = parseFloat(arg); - } else if (arg.match(/^\w+$/)) { - // Variable. - arg = 'float(' + arg + ')'; - } else { - // It's complicated. - var varName = Blockly.Python.variableDB_.getDistinctName( - variable0 + suffix, Blockly.Variables.NAME_TYPE); - code += varName + ' = float(' + arg + ')\n'; - arg = varName; - } - return arg; - }; - var startVar = scrub(argument0, '_start'); - var endVar = scrub(argument1, '_end'); - var incVar = scrub(increment, '_inc'); - - if (typeof startVar == 'number' && typeof endVar == 'number') { - if (startVar < endVar) { - range = defineUpRange(startVar, endVar, increment); - } else { - range = defineDownRange(startVar, endVar, increment); - } - } else { - // We cannot determine direction statically. - range = generateUpDownRange(startVar, endVar, increment); - } - } - code += 'for ' + variable0 + ' in ' + range + ':\n' + branch; - return code; -}; - -Blockly.Python['controls_forEach'] = function(block) { - // For each loop. - var variable0 = Blockly.Python.variableDB_.getName( - block.getFieldValue('VAR'), Blockly.Variables.NAME_TYPE); - var argument0 = Blockly.Python.valueToCode(block, 'LIST', - Blockly.Python.ORDER_RELATIONAL) || '[]'; - var branch = Blockly.Python.statementToCode(block, 'DO'); - branch = Blockly.Python.addLoopTrap(branch, block.id) || - Blockly.Python.PASS; - var code = 'for ' + variable0 + ' in ' + argument0 + ':\n' + branch; - return code; -}; - -Blockly.Python['controls_flow_statements'] = function(block) { - // Flow statements: continue, break. - switch (block.getFieldValue('FLOW')) { - case 'BREAK': - return 'break\n'; - case 'CONTINUE': - return 'continue\n'; - } - throw 'Unknown flow statement.'; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/python/math.js b/backend/_pv_1_3_5/static/blockly/generators/python/math.js deleted file mode 100755 index a2595e00c..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/python/math.js +++ /dev/null @@ -1,388 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Python for math blocks. - * @author q.neutron@gmail.com (Quynh Neutron) - */ -'use strict'; - -goog.provide('Blockly.Python.math'); - -goog.require('Blockly.Python'); - - -// If any new block imports any library, add that library name here. -Blockly.Python.addReservedWords('math,random,Number'); - -Blockly.Python['math_number'] = function(block) { - // Numeric value. - var code = parseFloat(block.getFieldValue('NUM')); - var order; - if (code == Infinity) { - code = 'float("inf")'; - order = Blockly.Python.ORDER_FUNCTION_CALL; - } else if (code == -Infinity) { - code = '-float("inf")'; - order = Blockly.Python.ORDER_UNARY_SIGN; - } else { - order = code < 0 ? Blockly.Python.ORDER_UNARY_SIGN : - Blockly.Python.ORDER_ATOMIC; - } - return [code, order]; -}; - -Blockly.Python['math_arithmetic'] = function(block) { - // Basic arithmetic operators, and power. - var OPERATORS = { - 'ADD': [' + ', Blockly.Python.ORDER_ADDITIVE], - 'MINUS': [' - ', Blockly.Python.ORDER_ADDITIVE], - 'MULTIPLY': [' * ', Blockly.Python.ORDER_MULTIPLICATIVE], - 'DIVIDE': [' / ', Blockly.Python.ORDER_MULTIPLICATIVE], - 'POWER': [' ** ', Blockly.Python.ORDER_EXPONENTIATION] - }; - var tuple = OPERATORS[block.getFieldValue('OP')]; - var operator = tuple[0]; - var order = tuple[1]; - var argument0 = Blockly.Python.valueToCode(block, 'A', order) || '0'; - var argument1 = Blockly.Python.valueToCode(block, 'B', order) || '0'; - var code = argument0 + operator + argument1; - return [code, order]; - // In case of 'DIVIDE', division between integers returns different results - // in Python 2 and 3. However, is not an issue since Blockly does not - // guarantee identical results in all languages. To do otherwise would - // require every operator to be wrapped in a function call. This would kill - // legibility of the generated code. -}; - -Blockly.Python['math_single'] = function(block) { - // Math operators with single operand. - var operator = block.getFieldValue('OP'); - var code; - var arg; - if (operator == 'NEG') { - // Negation is a special case given its different operator precedence. - var code = Blockly.Python.valueToCode(block, 'NUM', - Blockly.Python.ORDER_UNARY_SIGN) || '0'; - return ['-' + code, Blockly.Python.ORDER_UNARY_SIGN]; - } - Blockly.Python.definitions_['import_math'] = 'import math'; - if (operator == 'SIN' || operator == 'COS' || operator == 'TAN') { - arg = Blockly.Python.valueToCode(block, 'NUM', - Blockly.Python.ORDER_MULTIPLICATIVE) || '0'; - } else { - arg = Blockly.Python.valueToCode(block, 'NUM', - Blockly.Python.ORDER_NONE) || '0'; - } - // First, handle cases which generate values that don't need parentheses - // wrapping the code. - switch (operator) { - case 'ABS': - code = 'math.fabs(' + arg + ')'; - break; - case 'ROOT': - code = 'math.sqrt(' + arg + ')'; - break; - case 'LN': - code = 'math.log(' + arg + ')'; - break; - case 'LOG10': - code = 'math.log10(' + arg + ')'; - break; - case 'EXP': - code = 'math.exp(' + arg + ')'; - break; - case 'POW10': - code = 'math.pow(10,' + arg + ')'; - break; - case 'ROUND': - code = 'round(' + arg + ')'; - break; - case 'ROUNDUP': - code = 'math.ceil(' + arg + ')'; - break; - case 'ROUNDDOWN': - code = 'math.floor(' + arg + ')'; - break; - case 'SIN': - code = 'math.sin(' + arg + ' / 180.0 * math.pi)'; - break; - case 'COS': - code = 'math.cos(' + arg + ' / 180.0 * math.pi)'; - break; - case 'TAN': - code = 'math.tan(' + arg + ' / 180.0 * math.pi)'; - break; - } - if (code) { - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; - } - // Second, handle cases which generate values that may need parentheses - // wrapping the code. - switch (operator) { - case 'ASIN': - code = 'math.asin(' + arg + ') / math.pi * 180'; - break; - case 'ACOS': - code = 'math.acos(' + arg + ') / math.pi * 180'; - break; - case 'ATAN': - code = 'math.atan(' + arg + ') / math.pi * 180'; - break; - default: - throw 'Unknown math operator: ' + operator; - } - return [code, Blockly.Python.ORDER_MULTIPLICATIVE]; -}; - -Blockly.Python['math_constant'] = function(block) { - // Constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY. - var CONSTANTS = { - 'PI': ['math.pi', Blockly.Python.ORDER_MEMBER], - 'E': ['math.e', Blockly.Python.ORDER_MEMBER], - 'GOLDEN_RATIO': ['(1 + math.sqrt(5)) / 2', - Blockly.Python.ORDER_MULTIPLICATIVE], - 'SQRT2': ['math.sqrt(2)', Blockly.Python.ORDER_MEMBER], - 'SQRT1_2': ['math.sqrt(1.0 / 2)', Blockly.Python.ORDER_MEMBER], - 'INFINITY': ['float(\'inf\')', Blockly.Python.ORDER_ATOMIC] - }; - var constant = block.getFieldValue('CONSTANT'); - if (constant != 'INFINITY') { - Blockly.Python.definitions_['import_math'] = 'import math'; - } - return CONSTANTS[constant]; -}; - -Blockly.Python['math_number_property'] = function(block) { - // Check if a number is even, odd, prime, whole, positive, or negative - // or if it is divisible by certain number. Returns true or false. - var number_to_check = Blockly.Python.valueToCode(block, 'NUMBER_TO_CHECK', - Blockly.Python.ORDER_MULTIPLICATIVE) || '0'; - var dropdown_property = block.getFieldValue('PROPERTY'); - var code; - if (dropdown_property == 'PRIME') { - Blockly.Python.definitions_['import_math'] = 'import math'; - Blockly.Python.definitions_['from_numbers_import_Number'] = - 'from numbers import Number'; - var functionName = Blockly.Python.provideFunction_( - 'math_isPrime', - ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(n):', - ' # https://en.wikipedia.org/wiki/Primality_test#Naive_methods', - ' # If n is not a number but a string, try parsing it.', - ' if not isinstance(n, Number):', - ' try:', - ' n = float(n)', - ' except:', - ' return False', - ' if n == 2 or n == 3:', - ' return True', - ' # False if n is negative, is 1, or not whole,' + - ' or if n is divisible by 2 or 3.', - ' if n <= 1 or n % 1 != 0 or n % 2 == 0 or n % 3 == 0:', - ' return False', - ' # Check all the numbers of form 6k +/- 1, up to sqrt(n).', - ' for x in range(6, int(math.sqrt(n)) + 2, 6):', - ' if n % (x - 1) == 0 or n % (x + 1) == 0:', - ' return False', - ' return True']); - code = functionName + '(' + number_to_check + ')'; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; - } - switch (dropdown_property) { - case 'EVEN': - code = number_to_check + ' % 2 == 0'; - break; - case 'ODD': - code = number_to_check + ' % 2 == 1'; - break; - case 'WHOLE': - code = number_to_check + ' % 1 == 0'; - break; - case 'POSITIVE': - code = number_to_check + ' > 0'; - break; - case 'NEGATIVE': - code = number_to_check + ' < 0'; - break; - case 'DIVISIBLE_BY': - var divisor = Blockly.Python.valueToCode(block, 'DIVISOR', - Blockly.Python.ORDER_MULTIPLICATIVE); - // If 'divisor' is some code that evals to 0, Python will raise an error. - if (!divisor || divisor == '0') { - return ['False', Blockly.Python.ORDER_ATOMIC]; - } - code = number_to_check + ' % ' + divisor + ' == 0'; - break; - } - return [code, Blockly.Python.ORDER_RELATIONAL]; -}; - -Blockly.Python['math_change'] = function(block) { - // Add to a variable in place. - Blockly.Python.definitions_['from_numbers_import_Number'] = - 'from numbers import Number'; - var argument0 = Blockly.Python.valueToCode(block, 'DELTA', - Blockly.Python.ORDER_ADDITIVE) || '0'; - var varName = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'), - Blockly.Variables.NAME_TYPE); - return varName + ' = (' + varName + ' if isinstance(' + varName + - ', Number) else 0) + ' + argument0 + '\n'; -}; - -// Rounding functions have a single operand. -Blockly.Python['math_round'] = Blockly.Python['math_single']; -// Trigonometry functions have a single operand. -Blockly.Python['math_trig'] = Blockly.Python['math_single']; - -Blockly.Python['math_on_list'] = function(block) { - // Math functions for lists. - var func = block.getFieldValue('OP'); - var list = Blockly.Python.valueToCode(block, 'LIST', - Blockly.Python.ORDER_NONE) || '[]'; - var code; - switch (func) { - case 'SUM': - code = 'sum(' + list + ')'; - break; - case 'MIN': - code = 'min(' + list + ')'; - break; - case 'MAX': - code = 'max(' + list + ')'; - break; - case 'AVERAGE': - Blockly.Python.definitions_['from_numbers_import_Number'] = - 'from numbers import Number'; - var functionName = Blockly.Python.provideFunction_( - 'math_mean', - // This operation excludes null and values that aren't int or float:', - // math_mean([null, null, "aString", 1, 9]) == 5.0.', - ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList):', - ' localList = [e for e in myList if isinstance(e, Number)]', - ' if not localList: return', - ' return float(sum(localList)) / len(localList)']); - code = functionName + '(' + list + ')'; - break; - case 'MEDIAN': - Blockly.Python.definitions_['from_numbers_import_Number'] = - 'from numbers import Number'; - var functionName = Blockly.Python.provideFunction_( - 'math_median', - // This operation excludes null values: - // math_median([null, null, 1, 3]) == 2.0. - ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(myList):', - ' localList = sorted([e for e in myList if isinstance(e, Number)])', - ' if not localList: return', - ' if len(localList) % 2 == 0:', - ' return (localList[len(localList) // 2 - 1] + ' + - 'localList[len(localList) // 2]) / 2.0', - ' else:', - ' return localList[(len(localList) - 1) // 2]']); - code = functionName + '(' + list + ')'; - break; - case 'MODE': - var functionName = Blockly.Python.provideFunction_( - 'math_modes', - // As a list of numbers can contain more than one mode, - // the returned result is provided as an array. - // Mode of [3, 'x', 'x', 1, 1, 2, '3'] -> ['x', 1]. - ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(some_list):', - ' modes = []', - ' # Using a lists of [item, count] to keep count rather than dict', - ' # to avoid "unhashable" errors when the counted item is ' + - 'itself a list or dict.', - ' counts = []', - ' maxCount = 1', - ' for item in some_list:', - ' found = False', - ' for count in counts:', - ' if count[0] == item:', - ' count[1] += 1', - ' maxCount = max(maxCount, count[1])', - ' found = True', - ' if not found:', - ' counts.append([item, 1])', - ' for counted_item, item_count in counts:', - ' if item_count == maxCount:', - ' modes.append(counted_item)', - ' return modes']); - code = functionName + '(' + list + ')'; - break; - case 'STD_DEV': - Blockly.Python.definitions_['import_math'] = 'import math'; - var functionName = Blockly.Python.provideFunction_( - 'math_standard_deviation', - ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(numbers):', - ' n = len(numbers)', - ' if n == 0: return', - ' mean = float(sum(numbers)) / n', - ' variance = sum((x - mean) ** 2 for x in numbers) / n', - ' return math.sqrt(variance)']); - code = functionName + '(' + list + ')'; - break; - case 'RANDOM': - Blockly.Python.definitions_['import_random'] = 'import random'; - code = 'random.choice(' + list + ')'; - break; - default: - throw 'Unknown operator: ' + func; - } - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; -}; - -Blockly.Python['math_modulo'] = function(block) { - // Remainder computation. - var argument0 = Blockly.Python.valueToCode(block, 'DIVIDEND', - Blockly.Python.ORDER_MULTIPLICATIVE) || '0'; - var argument1 = Blockly.Python.valueToCode(block, 'DIVISOR', - Blockly.Python.ORDER_MULTIPLICATIVE) || '0'; - var code = argument0 + ' % ' + argument1; - return [code, Blockly.Python.ORDER_MULTIPLICATIVE]; -}; - -Blockly.Python['math_constrain'] = function(block) { - // Constrain a number between two limits. - var argument0 = Blockly.Python.valueToCode(block, 'VALUE', - Blockly.Python.ORDER_NONE) || '0'; - var argument1 = Blockly.Python.valueToCode(block, 'LOW', - Blockly.Python.ORDER_NONE) || '0'; - var argument2 = Blockly.Python.valueToCode(block, 'HIGH', - Blockly.Python.ORDER_NONE) || 'float(\'inf\')'; - var code = 'min(max(' + argument0 + ', ' + argument1 + '), ' + - argument2 + ')'; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; -}; - -Blockly.Python['math_random_int'] = function(block) { - // Random integer between [X] and [Y]. - Blockly.Python.definitions_['import_random'] = 'import random'; - var argument0 = Blockly.Python.valueToCode(block, 'FROM', - Blockly.Python.ORDER_NONE) || '0'; - var argument1 = Blockly.Python.valueToCode(block, 'TO', - Blockly.Python.ORDER_NONE) || '0'; - var code = 'random.randint(' + argument0 + ', ' + argument1 + ')'; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; -}; - -Blockly.Python['math_random_float'] = function(block) { - // Random fraction between 0 and 1. - Blockly.Python.definitions_['import_random'] = 'import random'; - return ['random.random()', Blockly.Python.ORDER_FUNCTION_CALL]; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/python/procedures.js b/backend/_pv_1_3_5/static/blockly/generators/python/procedures.js deleted file mode 100755 index fa938ef0f..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/python/procedures.js +++ /dev/null @@ -1,124 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Python for procedure blocks. - * @author fraser@google.com (Neil Fraser) - */ -'use strict'; - -goog.provide('Blockly.Python.procedures'); - -goog.require('Blockly.Python'); - - -Blockly.Python['procedures_defreturn'] = function(block) { - // Define a procedure with a return value. - // First, add a 'global' statement for every variable that is assigned. - var globals = block.workspace.variableList; - for (var i = globals.length - 1; i >= 0; i--) { - var varName = globals[i]; - if (block.arguments_.indexOf(varName) == -1) { - globals[i] = Blockly.Python.variableDB_.getName(varName, - Blockly.Variables.NAME_TYPE); - } else { - // This variable is actually a parameter name. Do not include it in - // the list of globals, thus allowing it be of local scope. - globals.splice(i, 1); - } - } - globals = globals.length ? ' global ' + globals.join(', ') + '\n' : ''; - var funcName = Blockly.Python.variableDB_.getName(block.getFieldValue('NAME'), - Blockly.Procedures.NAME_TYPE); - var branch = Blockly.Python.statementToCode(block, 'STACK'); - if (Blockly.Python.STATEMENT_PREFIX) { - branch = Blockly.Python.prefixLines( - Blockly.Python.STATEMENT_PREFIX.replace(/%1/g, - '\'' + block.id + '\''), Blockly.Python.INDENT) + branch; - } - if (Blockly.Python.INFINITE_LOOP_TRAP) { - branch = Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g, - '"' + block.id + '"') + branch; - } - var returnValue = Blockly.Python.valueToCode(block, 'RETURN', - Blockly.Python.ORDER_NONE) || ''; - if (returnValue) { - returnValue = ' return ' + returnValue + '\n'; - } else if (!branch) { - branch = Blockly.Python.PASS; - } - var args = []; - for (var i = 0; i < block.arguments_.length; i++) { - args[i] = Blockly.Python.variableDB_.getName(block.arguments_[i], - Blockly.Variables.NAME_TYPE); - } - var code = 'def ' + funcName + '(' + args.join(', ') + '):\n' + - globals + branch + returnValue; - code = Blockly.Python.scrub_(block, code); - // Add % so as not to collide with helper functions in definitions list. - Blockly.Python.definitions_['%' + funcName] = code; - return null; -}; - -// Defining a procedure without a return value uses the same generator as -// a procedure with a return value. -Blockly.Python['procedures_defnoreturn'] = - Blockly.Python['procedures_defreturn']; - -Blockly.Python['procedures_callreturn'] = function(block) { - // Call a procedure with a return value. - var funcName = Blockly.Python.variableDB_.getName(block.getFieldValue('NAME'), - Blockly.Procedures.NAME_TYPE); - var args = []; - for (var i = 0; i < block.arguments_.length; i++) { - args[i] = Blockly.Python.valueToCode(block, 'ARG' + i, - Blockly.Python.ORDER_NONE) || 'None'; - } - var code = funcName + '(' + args.join(', ') + ')'; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; -}; - -Blockly.Python['procedures_callnoreturn'] = function(block) { - // Call a procedure with no return value. - var funcName = Blockly.Python.variableDB_.getName(block.getFieldValue('NAME'), - Blockly.Procedures.NAME_TYPE); - var args = []; - for (var i = 0; i < block.arguments_.length; i++) { - args[i] = Blockly.Python.valueToCode(block, 'ARG' + i, - Blockly.Python.ORDER_NONE) || 'None'; - } - var code = funcName + '(' + args.join(', ') + ')\n'; - return code; -}; - -Blockly.Python['procedures_ifreturn'] = function(block) { - // Conditionally return value from a procedure. - var condition = Blockly.Python.valueToCode(block, 'CONDITION', - Blockly.Python.ORDER_NONE) || 'False'; - var code = 'if ' + condition + ':\n'; - if (block.hasReturnValue_) { - var value = Blockly.Python.valueToCode(block, 'VALUE', - Blockly.Python.ORDER_NONE) || 'None'; - code += ' return ' + value + '\n'; - } else { - code += ' return\n'; - } - return code; -}; diff --git a/backend/_pv_1_3_5/static/blockly/generators/python/text.js b/backend/_pv_1_3_5/static/blockly/generators/python/text.js deleted file mode 100755 index 84e19872a..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/python/text.js +++ /dev/null @@ -1,253 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Python for text blocks. - * @author q.neutron@gmail.com (Quynh Neutron) - */ -'use strict'; - -goog.provide('Blockly.Python.texts'); - -goog.require('Blockly.Python'); - - -Blockly.Python['text'] = function(block) { - // Text value. - var code = Blockly.Python.quote_(block.getFieldValue('TEXT')); - return [code, Blockly.Python.ORDER_ATOMIC]; -}; - -Blockly.Python['text_join'] = function(block) { - // Create a string made up of any number of elements of any type. - //Should we allow joining by '-' or ',' or any other characters? - switch (block.itemCount_) { - case 0: - return ['\'\'', Blockly.Python.ORDER_ATOMIC]; - break; - case 1: - var element = Blockly.Python.valueToCode(block, 'ADD0', - Blockly.Python.ORDER_NONE) || '\'\''; - var code = 'str(' + element + ')'; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; - break; - case 2: - var element0 = Blockly.Python.valueToCode(block, 'ADD0', - Blockly.Python.ORDER_NONE) || '\'\''; - var element1 = Blockly.Python.valueToCode(block, 'ADD1', - Blockly.Python.ORDER_NONE) || '\'\''; - var code = 'str(' + element0 + ') + str(' + element1 + ')'; - return [code, Blockly.Python.ORDER_ADDITIVE]; - break; - default: - var elements = []; - for (var i = 0; i < block.itemCount_; i++) { - elements[i] = Blockly.Python.valueToCode(block, 'ADD' + i, - Blockly.Python.ORDER_NONE) || '\'\''; - } - var tempVar = Blockly.Python.variableDB_.getDistinctName('x', - Blockly.Variables.NAME_TYPE); - var code = '\'\'.join([str(' + tempVar + ') for ' + tempVar + ' in [' + - elements.join(', ') + ']])'; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; - } -}; - -Blockly.Python['text_append'] = function(block) { - // Append to a variable in place. - var varName = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'), - Blockly.Variables.NAME_TYPE); - var value = Blockly.Python.valueToCode(block, 'TEXT', - Blockly.Python.ORDER_NONE) || '\'\''; - return varName + ' = str(' + varName + ') + str(' + value + ')\n'; -}; - -Blockly.Python['text_length'] = function(block) { - // Is the string null or array empty? - var text = Blockly.Python.valueToCode(block, 'VALUE', - Blockly.Python.ORDER_NONE) || '\'\''; - return ['len(' + text + ')', Blockly.Python.ORDER_FUNCTION_CALL]; -}; - -Blockly.Python['text_isEmpty'] = function(block) { - // Is the string null or array empty? - var text = Blockly.Python.valueToCode(block, 'VALUE', - Blockly.Python.ORDER_NONE) || '\'\''; - var code = 'not len(' + text + ')'; - return [code, Blockly.Python.ORDER_LOGICAL_NOT]; -}; - -Blockly.Python['text_indexOf'] = function(block) { - // Search the text for a substring. - // Should we allow for non-case sensitive??? - var operator = block.getFieldValue('END') == 'FIRST' ? 'find' : 'rfind'; - var substring = Blockly.Python.valueToCode(block, 'FIND', - Blockly.Python.ORDER_NONE) || '\'\''; - var text = Blockly.Python.valueToCode(block, 'VALUE', - Blockly.Python.ORDER_MEMBER) || '\'\''; - var code = text + '.' + operator + '(' + substring + ')'; - if (Blockly.Python.ONE_BASED_INDEXING) { - return [code + ' + 1', Blockly.Python.ORDER_ADDITIVE]; - } - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; -}; - -Blockly.Python['text_charAt'] = function(block) { - // Get letter at index. - // Note: Until January 2013 this block did not have the WHERE input. - var where = block.getFieldValue('WHERE') || 'FROM_START'; - var text = Blockly.Python.valueToCode(block, 'VALUE', - Blockly.Python.ORDER_MEMBER) || '\'\''; - switch (where) { - case 'FIRST': - var code = text + '[0]'; - return [code, Blockly.Python.ORDER_MEMBER]; - case 'LAST': - var code = text + '[-1]'; - return [code, Blockly.Python.ORDER_MEMBER]; - case 'FROM_START': - var at = Blockly.Python.getAdjustedInt(block, 'AT'); - var code = text + '[' + at + ']'; - return [code, Blockly.Python.ORDER_MEMBER]; - case 'FROM_END': - var at = Blockly.Python.getAdjustedInt(block, 'AT', 1, true); - var code = text + '[' + at + ']'; - return [code, Blockly.Python.ORDER_MEMBER]; - case 'RANDOM': - Blockly.Python.definitions_['import_random'] = 'import random'; - var functionName = Blockly.Python.provideFunction_( - 'text_random_letter', - ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(text):', - ' x = int(random.random() * len(text))', - ' return text[x];']); - code = functionName + '(' + text + ')'; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; - } - throw 'Unhandled option (text_charAt).'; -}; - -Blockly.Python['text_getSubstring'] = function(block) { - // Get substring. - var where1 = block.getFieldValue('WHERE1'); - var where2 = block.getFieldValue('WHERE2'); - var text = Blockly.Python.valueToCode(block, 'STRING', - Blockly.Python.ORDER_MEMBER) || '\'\''; - switch (where1) { - case 'FROM_START': - var at1 = Blockly.Python.getAdjustedInt(block, 'AT1'); - if (at1 == '0') { - at1 = ''; - } - break; - case 'FROM_END': - var at1 = Blockly.Python.getAdjustedInt(block, 'AT1', 1, true); - break; - case 'FIRST': - var at1 = ''; - break; - default: - throw 'Unhandled option (text_getSubstring)'; - } - switch (where2) { - case 'FROM_START': - var at2 = Blockly.Python.getAdjustedInt(block, 'AT2', 1); - break; - case 'FROM_END': - var at2 = Blockly.Python.getAdjustedInt(block, 'AT2', 0, true); - // Ensure that if the result calculated is 0 that sub-sequence will - // include all elements as expected. - if (!Blockly.isNumber(String(at2))) { - Blockly.Python.definitions_['import_sys'] = 'import sys'; - at2 += ' or sys.maxsize'; - } else if (at2 == '0') { - at2 = ''; - } - break; - case 'LAST': - var at2 = ''; - break; - default: - throw 'Unhandled option (text_getSubstring)'; - } - var code = text + '[' + at1 + ' : ' + at2 + ']'; - return [code, Blockly.Python.ORDER_MEMBER]; -}; - -Blockly.Python['text_changeCase'] = function(block) { - // Change capitalization. - var OPERATORS = { - 'UPPERCASE': '.upper()', - 'LOWERCASE': '.lower()', - 'TITLECASE': '.title()' - }; - var operator = OPERATORS[block.getFieldValue('CASE')]; - var text = Blockly.Python.valueToCode(block, 'TEXT', - Blockly.Python.ORDER_MEMBER) || '\'\''; - var code = text + operator; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; -}; - -Blockly.Python['text_trim'] = function(block) { - // Trim spaces. - var OPERATORS = { - 'LEFT': '.lstrip()', - 'RIGHT': '.rstrip()', - 'BOTH': '.strip()' - }; - var operator = OPERATORS[block.getFieldValue('MODE')]; - var text = Blockly.Python.valueToCode(block, 'TEXT', - Blockly.Python.ORDER_MEMBER) || '\'\''; - var code = text + operator; - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; -}; - -Blockly.Python['text_print'] = function(block) { - // Print statement. - var msg = Blockly.Python.valueToCode(block, 'TEXT', - Blockly.Python.ORDER_NONE) || '\'\''; - return 'print(' + msg + ')\n'; -}; - -Blockly.Python['text_prompt_ext'] = function(block) { - // Prompt function. - var functionName = Blockly.Python.provideFunction_( - 'text_prompt', - ['def ' + Blockly.Python.FUNCTION_NAME_PLACEHOLDER_ + '(msg):', - ' try:', - ' return raw_input(msg)', - ' except NameError:', - ' return input(msg)']); - if (block.getField('TEXT')) { - // Internal message. - var msg = Blockly.Python.quote_(block.getFieldValue('TEXT')); - } else { - // External message. - var msg = Blockly.Python.valueToCode(block, 'TEXT', - Blockly.Python.ORDER_NONE) || '\'\''; - } - var code = functionName + '(' + msg + ')'; - var toNumber = block.getFieldValue('TYPE') == 'NUMBER'; - if (toNumber) { - code = 'float(' + code + ')'; - } - return [code, Blockly.Python.ORDER_FUNCTION_CALL]; -}; - -Blockly.Python['text_prompt'] = Blockly.Python['text_prompt_ext']; diff --git a/backend/_pv_1_3_5/static/blockly/generators/python/variables.js b/backend/_pv_1_3_5/static/blockly/generators/python/variables.js deleted file mode 100755 index 00d9971af..000000000 --- a/backend/_pv_1_3_5/static/blockly/generators/python/variables.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview Generating Python for variable blocks. - * @author q.neutron@gmail.com (Quynh Neutron) - */ -'use strict'; - -goog.provide('Blockly.Python.variables'); - -goog.require('Blockly.Python'); - - -Blockly.Python['variables_get'] = function(block) { - // Variable getter. - var code = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'), - Blockly.Variables.NAME_TYPE); - return [code, Blockly.Python.ORDER_ATOMIC]; -}; - -Blockly.Python['variables_set'] = function(block) { - // Variable setter. - var argument0 = Blockly.Python.valueToCode(block, 'VALUE', - Blockly.Python.ORDER_NONE) || '0'; - var varName = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'), - Blockly.Variables.NAME_TYPE); - return varName + ' = ' + argument0 + '\n'; -}; diff --git a/backend/_pv_1_3_5/static/blockly/i18n/common.py b/backend/_pv_1_3_5/static/blockly/i18n/common.py deleted file mode 100755 index 90e584e16..000000000 --- a/backend/_pv_1_3_5/static/blockly/i18n/common.py +++ /dev/null @@ -1,234 +0,0 @@ -#!/usr/bin/python - -# Code shared by translation conversion scripts. -# -# Copyright 2013 Google Inc. -# https://developers.google.com/blockly/ -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import codecs -import json -import os -from datetime import datetime - -class InputError(Exception): - """Exception raised for errors in the input. - - Attributes: - location -- where error occurred - msg -- explanation of the error - - """ - - def __init__(self, location, msg): - Exception.__init__(self, '{0}: {1}'.format(location, msg)) - self.location = location - self.msg = msg - - -def read_json_file(filename): - """Read a JSON file as UTF-8 into a dictionary, discarding @metadata. - - Args: - filename: The filename, which must end ".json". - - Returns: - The dictionary. - - Raises: - InputError: The filename did not end with ".json" or an error occurred - while opening or reading the file. - """ - if not filename.endswith('.json'): - raise InputError(filename, 'filenames must end with ".json"') - try: - # Read in file. - with codecs.open(filename, 'r', 'utf-8') as infile: - defs = json.load(infile) - if '@metadata' in defs: - del defs['@metadata'] - return defs - except ValueError, e: - print('Error reading ' + filename) - raise InputError(filename, str(e)) - - -def _create_qqq_file(output_dir): - """Creates a qqq.json file with message documentation for translatewiki.net. - - The file consists of key-value pairs, where the keys are message ids and - the values are descriptions for the translators of the messages. - What documentation exists for the format can be found at: - http://translatewiki.net/wiki/Translating:Localisation_for_developers#Message_documentation - - The file should be closed by _close_qqq_file(). - - Parameters: - output_dir: The output directory. - - Returns: - A pointer to a file to which a left brace and newline have been written. - - Raises: - IOError: An error occurred while opening or writing the file. - """ - qqq_file_name = os.path.join(os.curdir, output_dir, 'qqq.json') - qqq_file = codecs.open(qqq_file_name, 'w', 'utf-8') - print 'Created file: ' + qqq_file_name - qqq_file.write('{\n') - return qqq_file - - -def _close_qqq_file(qqq_file): - """Closes a qqq.json file created and opened by _create_qqq_file(). - - This writes the final newlines and right brace. - - Args: - qqq_file: A file created by _create_qqq_file(). - - Raises: - IOError: An error occurred while writing to or closing the file. - """ - qqq_file.write('\n}\n') - qqq_file.close() - - -def _create_lang_file(author, lang, output_dir): - """Creates a .json file for translatewiki.net. - - The file consists of metadata, followed by key-value pairs, where the keys - are message ids and the values are the messages in the language specified - by the corresponding command-line argument. The file should be closed by - _close_lang_file(). - - Args: - author: Name and email address of contact for translators. - lang: ISO 639-1 source language code. - output_dir: Relative directory for output files. - - Returns: - A pointer to a file to which the metadata has been written. - - Raises: - IOError: An error occurred while opening or writing the file. - """ - lang_file_name = os.path.join(os.curdir, output_dir, lang + '.json') - lang_file = codecs.open(lang_file_name, 'w', 'utf-8') - print 'Created file: ' + lang_file_name - # string.format doesn't like printing braces, so break up our writes. - lang_file.write('{\n\t"@metadata": {') - lang_file.write(""" -\t\t"author": "{0}", -\t\t"lastupdated": "{1}", -\t\t"locale": "{2}", -\t\t"messagedocumentation" : "qqq" -""".format(author, str(datetime.now()), lang)) - lang_file.write('\t},\n') - return lang_file - - -def _close_lang_file(lang_file): - """Closes a .json file created with _create_lang_file(). - - This also writes the terminating left brace and newline. - - Args: - lang_file: A file opened with _create_lang_file(). - - Raises: - IOError: An error occurred while writing to or closing the file. - """ - lang_file.write('\n}\n') - lang_file.close() - - -def _create_key_file(output_dir): - """Creates a keys.json file mapping Closure keys to Blockly keys. - - Args: - output_dir: Relative directory for output files. - - Raises: - IOError: An error occurred while creating the file. - """ - key_file_name = os.path.join(os.curdir, output_dir, 'keys.json') - key_file = open(key_file_name, 'w') - key_file.write('{\n') - print 'Created file: ' + key_file_name - return key_file - - -def _close_key_file(key_file): - """Closes a key file created and opened with _create_key_file(). - - Args: - key_file: A file created by _create_key_file(). - - Raises: - IOError: An error occurred while writing to or closing the file. - """ - key_file.write('\n}\n') - key_file.close() - - -def write_files(author, lang, output_dir, units, write_key_file): - """Writes the output files for the given units. - - There are three possible output files: - * lang_file: JSON file mapping meanings (e.g., Maze.turnLeft) to the - English text. The base name of the language file is specified by the - "lang" command-line argument. - * key_file: JSON file mapping meanings to Soy-generated keys (long hash - codes). This is only output if the parameter write_key_file is True. - * qqq_file: JSON file mapping meanings to descriptions. - - Args: - author: Name and email address of contact for translators. - lang: ISO 639-1 source language code. - output_dir: Relative directory for output files. - units: A list of dictionaries with entries for 'meaning', 'source', - 'description', and 'keys' (the last only if write_key_file is true), - in the order desired in the output files. - write_key_file: Whether to output a keys.json file. - - Raises: - IOError: An error occurs opening, writing to, or closing a file. - KeyError: An expected key is missing from units. - """ - lang_file = _create_lang_file(author, lang, output_dir) - qqq_file = _create_qqq_file(output_dir) - if write_key_file: - key_file = _create_key_file(output_dir) - first_entry = True - for unit in units: - if not first_entry: - lang_file.write(',\n') - if write_key_file: - key_file.write(',\n') - qqq_file.write(',\n') - lang_file.write(u'\t"{0}": "{1}"'.format( - unit['meaning'], - unit['source'].replace('"', "'"))) - if write_key_file: - key_file.write('"{0}": "{1}"'.format(unit['meaning'], unit['key'])) - qqq_file.write(u'\t"{0}": "{1}"'.format( - unit['meaning'], - unit['description'].replace('"', "'").replace( - '{lb}', '{').replace('{rb}', '}'))) - first_entry = False - _close_lang_file(lang_file) - if write_key_file: - _close_key_file(key_file) - _close_qqq_file(qqq_file) diff --git a/backend/_pv_1_3_5/static/blockly/i18n/create_messages.py b/backend/_pv_1_3_5/static/blockly/i18n/create_messages.py deleted file mode 100755 index d32814f4a..000000000 --- a/backend/_pv_1_3_5/static/blockly/i18n/create_messages.py +++ /dev/null @@ -1,149 +0,0 @@ -#!/usr/bin/python - -# Generate .js files defining Blockly core and language messages. -# -# Copyright 2013 Google Inc. -# https://developers.google.com/blockly/ -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import argparse -import codecs -import os -import re -import sys -from common import read_json_file - - -_NEWLINE_PATTERN = re.compile('[\n\r]') - - -def string_is_ascii(s): - try: - s.decode('ascii') - return True - except UnicodeEncodeError: - return False - - -def main(): - """Generate .js files defining Blockly core and language messages.""" - - # Process command-line arguments. - parser = argparse.ArgumentParser(description='Convert JSON files to JS.') - parser.add_argument('--source_lang', default='en', - help='ISO 639-1 source language code') - parser.add_argument('--source_lang_file', - default=os.path.join('json', 'en.json'), - help='Path to .json file for source language') - parser.add_argument('--source_synonym_file', - default=os.path.join('json', 'synonyms.json'), - help='Path to .json file with synonym definitions') - parser.add_argument('--output_dir', default='js/', - help='relative directory for output files') - parser.add_argument('--key_file', default='keys.json', - help='relative path to input keys file') - parser.add_argument('--quiet', action='store_true', default=False, - help='do not write anything to standard output') - parser.add_argument('files', nargs='+', help='input files') - args = parser.parse_args() - if not args.output_dir.endswith(os.path.sep): - args.output_dir += os.path.sep - - # Read in source language .json file, which provides any values missing - # in target languages' .json files. - source_defs = read_json_file(os.path.join(os.curdir, args.source_lang_file)) - # Make sure the source file doesn't contain a newline or carriage return. - for key, value in source_defs.items(): - if _NEWLINE_PATTERN.search(value): - print('ERROR: definition of {0} in {1} contained a newline character.'. - format(key, args.source_lang_file)) - sys.exit(1) - sorted_keys = source_defs.keys() - sorted_keys.sort() - - # Read in synonyms file, which must be output in every language. - synonym_defs = read_json_file(os.path.join( - os.curdir, args.source_synonym_file)) - synonym_text = '\n'.join(['Blockly.Msg.{0} = Blockly.Msg.{1};'.format( - key, synonym_defs[key]) for key in synonym_defs]) - - # Create each output file. - for arg_file in args.files: - (_, filename) = os.path.split(arg_file) - target_lang = filename[:filename.index('.')] - if target_lang not in ('qqq', 'keys', 'synonyms'): - target_defs = read_json_file(os.path.join(os.curdir, arg_file)) - - # Verify that keys are 'ascii' - bad_keys = [key for key in target_defs if not string_is_ascii(key)] - if bad_keys: - print(u'These keys in {0} contain non ascii characters: {1}'.format( - filename, ', '.join(bad_keys))) - - # If there's a '\n' or '\r', remove it and print a warning. - for key, value in target_defs.items(): - if _NEWLINE_PATTERN.search(value): - print(u'WARNING: definition of {0} in {1} contained ' - 'a newline character.'. - format(key, arg_file)) - target_defs[key] = _NEWLINE_PATTERN.sub(' ', value) - - # Output file. - outname = os.path.join(os.curdir, args.output_dir, target_lang + '.js') - with codecs.open(outname, 'w', 'utf-8') as outfile: - outfile.write( - """// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.{0}'); - -goog.require('Blockly.Msg'); - -""".format(target_lang.replace('-', '.'))) - # For each key in the source language file, output the target value - # if present; otherwise, output the source language value with a - # warning comment. - for key in sorted_keys: - if key in target_defs: - value = target_defs[key] - comment = '' - del target_defs[key] - else: - value = source_defs[key] - comment = ' // untranslated' - value = value.replace('"', '\\"') - outfile.write(u'Blockly.Msg.{0} = "{1}";{2}\n'.format( - key, value, comment)) - - # Announce any keys defined only for target language. - if target_defs: - extra_keys = [key for key in target_defs if key not in synonym_defs] - synonym_keys = [key for key in target_defs if key in synonym_defs] - if not args.quiet: - if extra_keys: - print(u'These extra keys appeared in {0}: {1}'.format( - filename, ', '.join(extra_keys))) - if synonym_keys: - print(u'These synonym keys appeared in {0}: {1}'.format( - filename, ', '.join(synonym_keys))) - - outfile.write(synonym_text) - - if not args.quiet: - print('Created {0}.'.format(outname)) - - -if __name__ == '__main__': - main() diff --git a/backend/_pv_1_3_5/static/blockly/i18n/dedup_json.py b/backend/_pv_1_3_5/static/blockly/i18n/dedup_json.py deleted file mode 100755 index 30e572dde..000000000 --- a/backend/_pv_1_3_5/static/blockly/i18n/dedup_json.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/python - -# Consolidates duplicate key-value pairs in a JSON file. -# If the same key is used with different values, no warning is given, -# and there is no guarantee about which key-value pair will be output. -# There is also no guarantee as to the order of the key-value pairs -# output. -# -# Copyright 2013 Google Inc. -# https://developers.google.com/blockly/ -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import argparse -import codecs -import json -from common import InputError - - -def main(): - """Parses arguments and iterates over files. - - Raises: - IOError: An I/O error occurred with an input or output file. - InputError: Input JSON could not be parsed. - """ - - # Set up argument parser. - parser = argparse.ArgumentParser( - description='Removes duplicate key-value pairs from JSON files.') - parser.add_argument('--suffix', default='', - help='optional suffix for output files; ' - 'if empty, files will be changed in place') - parser.add_argument('files', nargs='+', help='input files') - args = parser.parse_args() - - # Iterate over files. - for filename in args.files: - # Read in json using Python libraries. This eliminates duplicates. - print('Processing ' + filename + '...') - try: - with codecs.open(filename, 'r', 'utf-8') as infile: - j = json.load(infile) - except ValueError, e: - print('Error reading ' + filename) - raise InputError(file, str(e)) - - # Built up output strings as an array to make output of delimiters easier. - output = [] - for key in j: - if key != '@metadata': - output.append('\t"' + key + '": "' + - j[key].replace('\n', '\\n') + '"') - - # Output results. - with codecs.open(filename + args.suffix, 'w', 'utf-8') as outfile: - outfile.write('{\n') - outfile.write(',\n'.join(output)) - outfile.write('\n}\n') - - -if __name__ == '__main__': - main() diff --git a/backend/_pv_1_3_5/static/blockly/i18n/js_to_json.py b/backend/_pv_1_3_5/static/blockly/i18n/js_to_json.py deleted file mode 100755 index 197dc4357..000000000 --- a/backend/_pv_1_3_5/static/blockly/i18n/js_to_json.py +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/python - -# Gives the translation status of the specified apps and languages. -# -# Copyright 2013 Google Inc. -# https://developers.google.com/blockly/ -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Extracts messages from .js files into .json files for translation. - -Specifically, lines with the following formats are extracted: - - /// Here is a description of the following message. - Blockly.SOME_KEY = 'Some value'; - -Adjacent "///" lines are concatenated. - -There are two output files, each of which is proper JSON. For each key, the -file en.json would get an entry of the form: - - "Blockly.SOME_KEY", "Some value", - -The file qqq.json would get: - - "Blockly.SOME_KEY", "Here is a description of the following message.", - -Commas would of course be omitted for the final entry of each value. - -@author Ellen Spertus (ellen.spertus@gmail.com) -""" - -import argparse -import codecs -import json -import os -import re -from common import write_files - - -_INPUT_DEF_PATTERN = re.compile("""Blockly.Msg.(\w*)\s*=\s*'([^']*)';?$""") - -_INPUT_SYN_PATTERN = re.compile( - """Blockly.Msg.(\w*)\s*=\s*Blockly.Msg.(\w*);""") - -def main(): - # Set up argument parser. - parser = argparse.ArgumentParser(description='Create translation files.') - parser.add_argument( - '--author', - default='Ellen Spertus ', - help='name and email address of contact for translators') - parser.add_argument('--lang', default='en', - help='ISO 639-1 source language code') - parser.add_argument('--output_dir', default='json', - help='relative directory for output files') - parser.add_argument('--input_file', default='messages.js', - help='input file') - parser.add_argument('--quiet', action='store_true', default=False, - help='only display warnings, not routine info') - args = parser.parse_args() - if (not args.output_dir.endswith(os.path.sep)): - args.output_dir += os.path.sep - - # Read and parse input file. - results = [] - synonyms = {} - description = '' - infile = codecs.open(args.input_file, 'r', 'utf-8') - for line in infile: - if line.startswith('///'): - if description: - description = description + ' ' + line[3:].strip() - else: - description = line[3:].strip() - else: - match = _INPUT_DEF_PATTERN.match(line) - if match: - result = {} - result['meaning'] = match.group(1) - result['source'] = match.group(2) - if not description: - print('Warning: No description for ' + result['meaning']) - result['description'] = description - description = '' - results.append(result) - else: - match = _INPUT_SYN_PATTERN.match(line) - if match: - if description: - print('Warning: Description preceding definition of synonym {0}.'. - format(match.group(1))) - description = '' - synonyms[match.group(1)] = match.group(2) - infile.close() - - # Create .json, keys.json, and qqq.json. - write_files(args.author, args.lang, args.output_dir, results, False) - - # Create synonyms.json. - synonym_file_name = os.path.join(os.curdir, args.output_dir, 'synonyms.json') - with open(synonym_file_name, 'w') as outfile: - json.dump(synonyms, outfile) - if not args.quiet: - print("Wrote {0} synonym pairs to {1}.".format( - len(synonyms), synonym_file_name)) - - -if __name__ == '__main__': - main() diff --git a/backend/_pv_1_3_5/static/blockly/i18n/json_to_js.py b/backend/_pv_1_3_5/static/blockly/i18n/json_to_js.py deleted file mode 100755 index f8c20f6af..000000000 --- a/backend/_pv_1_3_5/static/blockly/i18n/json_to_js.py +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/python - -# Converts .json files into .js files for use within Blockly apps. -# -# Copyright 2013 Google Inc. -# https://developers.google.com/blockly/ -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import argparse -import codecs # for codecs.open(..., 'utf-8') -import glob -import json # for json.load() -import os # for os.path() -import subprocess # for subprocess.check_call() -from common import InputError -from common import read_json_file - - -# Store parsed command-line arguments in global variable. -args = None - - -def _create_xlf(target_lang): - """Creates a .xlf file for Soy. - - Args: - target_lang: The ISO 639 language code for the target language. - This is used in the name of the file and in the metadata. - - Returns: - A pointer to a file to which the metadata has been written. - - Raises: - IOError: An error occurred while opening or writing the file. - """ - filename = os.path.join(os.curdir, args.output_dir, target_lang + '.xlf') - out_file = codecs.open(filename, 'w', 'utf-8') - out_file.write(""" - - - """.format(args.source_lang, target_lang)) - return out_file - - -def _close_xlf(xlf_file): - """Closes a .xlf file created with create_xlf(). - - This includes writing the terminating XML. - - Args: - xlf_file: A pointer to a file created by _create_xlf(). - - Raises: - IOError: An error occurred while writing to or closing the file. - """ - xlf_file.write(""" - - - -""") - xlf_file.close() - - -def _process_file(path_to_json, target_lang, key_dict): - """Creates an .xlf file corresponding to the specified .json input file. - - The name of the input file must be target_lang followed by '.json'. - The name of the output file will be target_lang followed by '.js'. - - Args: - path_to_json: Path to the directory of xx.json files. - target_lang: A IETF language code (RFC 4646), such as 'es' or 'pt-br'. - key_dict: Dictionary mapping Blockly keys (e.g., Maze.turnLeft) to - Closure keys (hash numbers). - - Raises: - IOError: An I/O error occurred with an input or output file. - InputError: Input JSON could not be parsed. - KeyError: Key found in input file but not in key file. - """ - keyfile = os.path.join(path_to_json, target_lang + '.json') - j = read_json_file(keyfile) - out_file = _create_xlf(target_lang) - for key in j: - if key != '@metadata': - try: - identifier = key_dict[key] - except KeyError, e: - print('Key "%s" is in %s but not in %s' % - (key, keyfile, args.key_file)) - raise e - target = j.get(key) - out_file.write(u""" - - {1} - """.format(identifier, target)) - _close_xlf(out_file) - - -def main(): - """Parses arguments and iterates over files.""" - - # Set up argument parser. - parser = argparse.ArgumentParser(description='Convert JSON files to JS.') - parser.add_argument('--source_lang', default='en', - help='ISO 639-1 source language code') - parser.add_argument('--output_dir', default='generated', - help='relative directory for output files') - parser.add_argument('--key_file', default='json' + os.path.sep + 'keys.json', - help='relative path to input keys file') - parser.add_argument('--template', default='template.soy') - parser.add_argument('--path_to_jar', - default='..' + os.path.sep + 'apps' + os.path.sep - + '_soy', - help='relative path from working directory to ' - 'SoyToJsSrcCompiler.jar') - parser.add_argument('files', nargs='+', help='input files') - - # Initialize global variables. - global args - args = parser.parse_args() - - # Make sure output_dir ends with slash. - if (not args.output_dir.endswith(os.path.sep)): - args.output_dir += os.path.sep - - # Read in keys.json, mapping descriptions (e.g., Maze.turnLeft) to - # Closure keys (long hash numbers). - key_file = open(args.key_file) - key_dict = json.load(key_file) - key_file.close() - - # Process each input file. - print('Creating .xlf files...') - processed_langs = [] - if len(args.files) == 1: - # Windows does not expand globs automatically. - args.files = glob.glob(args.files[0]) - for arg_file in args.files: - (path_to_json, filename) = os.path.split(arg_file) - if not filename.endswith('.json'): - raise InputError(filename, 'filenames must end with ".json"') - target_lang = filename[:filename.index('.')] - if not target_lang in ('qqq', 'keys'): - processed_langs.append(target_lang) - _process_file(path_to_json, target_lang, key_dict) - - # Output command line for Closure compiler. - if processed_langs: - print('Creating .js files...') - processed_lang_list = ','.join(processed_langs) - subprocess.check_call([ - 'java', - '-jar', os.path.join(args.path_to_jar, 'SoyToJsSrcCompiler.jar'), - '--locales', processed_lang_list, - '--messageFilePathFormat', args.output_dir + '{LOCALE}.xlf', - '--outputPathFormat', args.output_dir + '{LOCALE}.js', - '--srcs', args.template]) - if len(processed_langs) == 1: - print('Created ' + processed_lang_list + '.js in ' + args.output_dir) - else: - print('Created {' + processed_lang_list + '}.js in ' + args.output_dir) - - for lang in processed_langs: - os.remove(args.output_dir + lang + '.xlf') - print('Removed .xlf files.') - - -if __name__ == '__main__': - main() diff --git a/backend/_pv_1_3_5/static/blockly/i18n/tests.py b/backend/_pv_1_3_5/static/blockly/i18n/tests.py deleted file mode 100755 index 7e4fc49aa..000000000 --- a/backend/_pv_1_3_5/static/blockly/i18n/tests.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# Tests of i18n scripts. -# -# Copyright 2013 Google Inc. -# https://developers.google.com/blockly/ -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import common -import re -import unittest - -class TestSequenceFunctions(unittest.TestCase): - def test_insert_breaks(self): - spaces = re.compile(r'\s+|\\n') - def contains_all_chars(orig, result): - return re.sub(spaces, '', orig) == re.sub(spaces, '', result) - - sentences = [u'Quay Pegman qua bên trái hoặc bên phải 90 độ.', - u'Foo bar baz this is english that is okay bye.', - u'If there is a path in the specified direction, \nthen ' + - u'do some actions.', - u'If there is a path in the specified direction, then do ' + - u'the first block of actions. Otherwise, do the second ' + - u'block of actions.'] - for sentence in sentences: - output = common.insert_breaks(sentence, 30, 50) - self.assert_(contains_all_chars(sentence, output), - u'Mismatch between:\n{0}\n{1}'.format( - re.sub(spaces, '', sentence), - re.sub(spaces, '', output))) - - -if __name__ == '__main__': - unittest.main() diff --git a/backend/_pv_1_3_5/static/blockly/i18n/xliff_to_json.py b/backend/_pv_1_3_5/static/blockly/i18n/xliff_to_json.py deleted file mode 100755 index b38b4d6ec..000000000 --- a/backend/_pv_1_3_5/static/blockly/i18n/xliff_to_json.py +++ /dev/null @@ -1,232 +0,0 @@ -#!/usr/bin/python - -# Converts .xlf files into .json files for use at http://translatewiki.net. -# -# Copyright 2013 Google Inc. -# https://developers.google.com/blockly/ -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import argparse -import os -import re -import subprocess -import sys -from xml.dom import minidom -from common import InputError -from common import write_files - -# Global variables -args = None # Parsed command-line arguments. - - -def _parse_trans_unit(trans_unit): - """Converts a trans-unit XML node into a more convenient dictionary format. - - Args: - trans_unit: An XML representation of a .xlf translation unit. - - Returns: - A dictionary with useful information about the translation unit. - The returned dictionary is guaranteed to have an entry for 'key' and - may have entries for 'source', 'target', 'description', and 'meaning' - if present in the argument. - - Raises: - InputError: A required field was not present. - """ - - def get_value(tag_name): - elts = trans_unit.getElementsByTagName(tag_name) - if not elts: - return None - elif len(elts) == 1: - return ''.join([child.toxml() for child in elts[0].childNodes]) - else: - raise InputError('', 'Unable to extract ' + tag_name) - - result = {} - key = trans_unit.getAttribute('id') - if not key: - raise InputError('', 'id attribute not found') - result['key'] = key - - # Get source and target, if present. - try: - result['source'] = get_value('source') - result['target'] = get_value('target') - except InputError, e: - raise InputError(key, e.msg) - - # Get notes, using the from value as key and the data as value. - notes = trans_unit.getElementsByTagName('note') - for note in notes: - from_value = note.getAttribute('from') - if from_value and len(note.childNodes) == 1: - result[from_value] = note.childNodes[0].data - else: - raise InputError(key, 'Unable to extract ' + from_value) - - return result - - -def _process_file(filename): - """Builds list of translation units from input file. - - Each translation unit in the input file includes: - - an id (opaquely generated by Soy) - - the Blockly name for the message - - the text in the source language (generally English) - - a description for the translator - - The Soy and Blockly ids are joined with a hyphen and serve as the - keys in both output files. The value is the corresponding text (in the - .json file) or the description (in the qqq.json file). - - Args: - filename: The name of an .xlf file produced by Closure. - - Raises: - IOError: An I/O error occurred with an input or output file. - InputError: The input file could not be parsed or lacked required - fields. - - Returns: - A list of dictionaries produced by parse_trans_unit(). - """ - try: - results = [] # list of dictionaries (return value) - names = [] # list of names of encountered keys (local variable) - try: - parsed_xml = minidom.parse(filename) - except IOError: - # Don't get caught by below handler - raise - except Exception, e: - print - raise InputError(filename, str(e)) - - # Make sure needed fields are present and non-empty. - for trans_unit in parsed_xml.getElementsByTagName('trans-unit'): - unit = _parse_trans_unit(trans_unit) - for key in ['description', 'meaning', 'source']: - if not key in unit or not unit[key]: - raise InputError(filename + ':' + unit['key'], - key + ' not found') - if unit['description'].lower() == 'ibid': - if unit['meaning'] not in names: - # If the term has not already been described, the use of 'ibid' - # is an error. - raise InputError( - filename, - 'First encountered definition of: ' + unit['meaning'] - + ' has definition: ' + unit['description'] - + '. This error can occur if the definition was not' - + ' provided on the first appearance of the message' - + ' or if the source (English-language) messages differ.') - else: - # If term has already been described, 'ibid' was used correctly, - # and we output nothing. - pass - else: - if unit['meaning'] in names: - raise InputError(filename, - 'Second definition of: ' + unit['meaning']) - names.append(unit['meaning']) - results.append(unit) - - return results - except IOError, e: - print 'Error with file {0}: {1}'.format(filename, e.strerror) - sys.exit(1) - - -def sort_units(units, templates): - """Sorts the translation units by their definition order in the template. - - Args: - units: A list of dictionaries produced by parse_trans_unit() - that have a non-empty value for the key 'meaning'. - templates: A string containing the Soy templates in which each of - the units' meanings is defined. - - Returns: - A new list of translation units, sorted by the order in which - their meaning is defined in the templates. - - Raises: - InputError: If a meaning definition cannot be found in the - templates. - """ - def key_function(unit): - match = re.search( - '\\smeaning\\s*=\\s*"{0}"\\s'.format(unit['meaning']), - templates) - if match: - return match.start() - else: - raise InputError(args.templates, - 'msg definition for meaning not found: ' + - unit['meaning']) - return sorted(units, key=key_function) - - -def main(): - """Parses arguments and processes the specified file. - - Raises: - IOError: An I/O error occurred with an input or output file. - InputError: Input files lacked required fields. - """ - # Set up argument parser. - parser = argparse.ArgumentParser(description='Create translation files.') - parser.add_argument( - '--author', - default='Ellen Spertus ', - help='name and email address of contact for translators') - parser.add_argument('--lang', default='en', - help='ISO 639-1 source language code') - parser.add_argument('--output_dir', default='json', - help='relative directory for output files') - parser.add_argument('--xlf', help='file containing xlf definitions') - parser.add_argument('--templates', default=['template.soy'], nargs='+', - help='relative path to Soy templates, comma or space ' - 'separated (used for ordering messages)') - global args - args = parser.parse_args() - - # Make sure output_dir ends with slash. - if (not args.output_dir.endswith(os.path.sep)): - args.output_dir += os.path.sep - - # Process the input file, and sort the entries. - units = _process_file(args.xlf) - files = [] - for arg in args.templates: - for filename in arg.split(','): - filename = filename.strip(); - if filename: - with open(filename) as myfile: - files.append(' '.join(line.strip() for line in myfile)) - sorted_units = sort_units(units, ' '.join(files)) - - # Write the output files. - write_files(args.author, args.lang, args.output_dir, sorted_units, True) - - # Delete the input .xlf file. - os.remove(args.xlf) - print('Removed ' + args.xlf) - - -if __name__ == '__main__': - main() diff --git a/backend/_pv_1_3_5/static/blockly/javascript_compressed.js b/backend/_pv_1_3_5/static/blockly/javascript_compressed.js deleted file mode 100755 index c39f206ab..000000000 --- a/backend/_pv_1_3_5/static/blockly/javascript_compressed.js +++ /dev/null @@ -1,91 +0,0 @@ -// Do not edit this file; automatically generated by build.py. -'use strict'; - - -// Copyright 2012 Google Inc. Apache License 2.0 -Blockly.JavaScript=new Blockly.Generator("JavaScript");Blockly.JavaScript.addReservedWords("Blockly,break,case,catch,continue,debugger,default,delete,do,else,finally,for,function,if,in,instanceof,new,return,switch,this,throw,try,typeof,var,void,while,with,class,enum,export,extends,import,super,implements,interface,let,package,private,protected,public,static,yield,const,null,true,false,Array,ArrayBuffer,Boolean,Date,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Error,eval,EvalError,Float32Array,Float64Array,Function,Infinity,Int16Array,Int32Array,Int8Array,isFinite,isNaN,Iterator,JSON,Math,NaN,Number,Object,parseFloat,parseInt,RangeError,ReferenceError,RegExp,StopIteration,String,SyntaxError,TypeError,Uint16Array,Uint32Array,Uint8Array,Uint8ClampedArray,undefined,uneval,URIError,applicationCache,closed,Components,content,_content,controllers,crypto,defaultStatus,dialogArguments,directories,document,frameElement,frames,fullScreen,globalStorage,history,innerHeight,innerWidth,length,location,locationbar,localStorage,menubar,messageManager,mozAnimationStartTime,mozInnerScreenX,mozInnerScreenY,mozPaintCount,name,navigator,opener,outerHeight,outerWidth,pageXOffset,pageYOffset,parent,performance,personalbar,pkcs11,returnValue,screen,screenX,screenY,scrollbars,scrollMaxX,scrollMaxY,scrollX,scrollY,self,sessionStorage,sidebar,status,statusbar,toolbar,top,URL,window,addEventListener,alert,atob,back,blur,btoa,captureEvents,clearImmediate,clearInterval,clearTimeout,close,confirm,disableExternalCapture,dispatchEvent,dump,enableExternalCapture,escape,find,focus,forward,GeckoActiveXObject,getAttention,getAttentionWithCycleCount,getComputedStyle,getSelection,home,matchMedia,maximize,minimize,moveBy,moveTo,mozRequestAnimationFrame,open,openDialog,postMessage,print,prompt,QueryInterface,releaseEvents,removeEventListener,resizeBy,resizeTo,restore,routeEvent,scroll,scrollBy,scrollByLines,scrollByPages,scrollTo,setCursor,setImmediate,setInterval,setResizable,setTimeout,showModalDialog,sizeToContent,stop,unescape,updateCommands,XPCNativeWrapper,XPCSafeJSObjectWrapper,onabort,onbeforeunload,onblur,onchange,onclick,onclose,oncontextmenu,ondevicemotion,ondeviceorientation,ondragdrop,onerror,onfocus,onhashchange,onkeydown,onkeypress,onkeyup,onload,onmousedown,onmousemove,onmouseout,onmouseover,onmouseup,onmozbeforepaint,onpaint,onpopstate,onreset,onresize,onscroll,onselect,onsubmit,onunload,onpageshow,onpagehide,Image,Option,Worker,Event,Range,File,FileReader,Blob,BlobBuilder,Attr,CDATASection,CharacterData,Comment,console,DocumentFragment,DocumentType,DomConfiguration,DOMError,DOMErrorHandler,DOMException,DOMImplementation,DOMImplementationList,DOMImplementationRegistry,DOMImplementationSource,DOMLocator,DOMObject,DOMString,DOMStringList,DOMTimeStamp,DOMUserData,Entity,EntityReference,MediaQueryList,MediaQueryListListener,NameList,NamedNodeMap,Node,NodeFilter,NodeIterator,NodeList,Notation,Plugin,PluginArray,ProcessingInstruction,SharedWorker,Text,TimeRanges,Treewalker,TypeInfo,UserDataHandler,Worker,WorkerGlobalScope,HTMLDocument,HTMLElement,HTMLAnchorElement,HTMLAppletElement,HTMLAudioElement,HTMLAreaElement,HTMLBaseElement,HTMLBaseFontElement,HTMLBodyElement,HTMLBRElement,HTMLButtonElement,HTMLCanvasElement,HTMLDirectoryElement,HTMLDivElement,HTMLDListElement,HTMLEmbedElement,HTMLFieldSetElement,HTMLFontElement,HTMLFormElement,HTMLFrameElement,HTMLFrameSetElement,HTMLHeadElement,HTMLHeadingElement,HTMLHtmlElement,HTMLHRElement,HTMLIFrameElement,HTMLImageElement,HTMLInputElement,HTMLKeygenElement,HTMLLabelElement,HTMLLIElement,HTMLLinkElement,HTMLMapElement,HTMLMenuElement,HTMLMetaElement,HTMLModElement,HTMLObjectElement,HTMLOListElement,HTMLOptGroupElement,HTMLOptionElement,HTMLOutputElement,HTMLParagraphElement,HTMLParamElement,HTMLPreElement,HTMLQuoteElement,HTMLScriptElement,HTMLSelectElement,HTMLSourceElement,HTMLSpanElement,HTMLStyleElement,HTMLTableElement,HTMLTableCaptionElement,HTMLTableCellElement,HTMLTableDataCellElement,HTMLTableHeaderCellElement,HTMLTableColElement,HTMLTableRowElement,HTMLTableSectionElement,HTMLTextAreaElement,HTMLTimeElement,HTMLTitleElement,HTMLTrackElement,HTMLUListElement,HTMLUnknownElement,HTMLVideoElement,HTMLCanvasElement,CanvasRenderingContext2D,CanvasGradient,CanvasPattern,TextMetrics,ImageData,CanvasPixelArray,HTMLAudioElement,HTMLVideoElement,NotifyAudioAvailableEvent,HTMLCollection,HTMLAllCollection,HTMLFormControlsCollection,HTMLOptionsCollection,HTMLPropertiesCollection,DOMTokenList,DOMSettableTokenList,DOMStringMap,RadioNodeList,SVGDocument,SVGElement,SVGAElement,SVGAltGlyphElement,SVGAltGlyphDefElement,SVGAltGlyphItemElement,SVGAnimationElement,SVGAnimateElement,SVGAnimateColorElement,SVGAnimateMotionElement,SVGAnimateTransformElement,SVGSetElement,SVGCircleElement,SVGClipPathElement,SVGColorProfileElement,SVGCursorElement,SVGDefsElement,SVGDescElement,SVGEllipseElement,SVGFilterElement,SVGFilterPrimitiveStandardAttributes,SVGFEBlendElement,SVGFEColorMatrixElement,SVGFEComponentTransferElement,SVGFECompositeElement,SVGFEConvolveMatrixElement,SVGFEDiffuseLightingElement,SVGFEDisplacementMapElement,SVGFEDistantLightElement,SVGFEFloodElement,SVGFEGaussianBlurElement,SVGFEImageElement,SVGFEMergeElement,SVGFEMergeNodeElement,SVGFEMorphologyElement,SVGFEOffsetElement,SVGFEPointLightElement,SVGFESpecularLightingElement,SVGFESpotLightElement,SVGFETileElement,SVGFETurbulenceElement,SVGComponentTransferFunctionElement,SVGFEFuncRElement,SVGFEFuncGElement,SVGFEFuncBElement,SVGFEFuncAElement,SVGFontElement,SVGFontFaceElement,SVGFontFaceFormatElement,SVGFontFaceNameElement,SVGFontFaceSrcElement,SVGFontFaceUriElement,SVGForeignObjectElement,SVGGElement,SVGGlyphElement,SVGGlyphRefElement,SVGGradientElement,SVGLinearGradientElement,SVGRadialGradientElement,SVGHKernElement,SVGImageElement,SVGLineElement,SVGMarkerElement,SVGMaskElement,SVGMetadataElement,SVGMissingGlyphElement,SVGMPathElement,SVGPathElement,SVGPatternElement,SVGPolylineElement,SVGPolygonElement,SVGRectElement,SVGScriptElement,SVGStopElement,SVGStyleElement,SVGSVGElement,SVGSwitchElement,SVGSymbolElement,SVGTextElement,SVGTextPathElement,SVGTitleElement,SVGTRefElement,SVGTSpanElement,SVGUseElement,SVGViewElement,SVGVKernElement,SVGAngle,SVGColor,SVGICCColor,SVGElementInstance,SVGElementInstanceList,SVGLength,SVGLengthList,SVGMatrix,SVGNumber,SVGNumberList,SVGPaint,SVGPoint,SVGPointList,SVGPreserveAspectRatio,SVGRect,SVGStringList,SVGTransform,SVGTransformList,SVGAnimatedAngle,SVGAnimatedBoolean,SVGAnimatedEnumeration,SVGAnimatedInteger,SVGAnimatedLength,SVGAnimatedLengthList,SVGAnimatedNumber,SVGAnimatedNumberList,SVGAnimatedPreserveAspectRatio,SVGAnimatedRect,SVGAnimatedString,SVGAnimatedTransformList,SVGPathSegList,SVGPathSeg,SVGPathSegArcAbs,SVGPathSegArcRel,SVGPathSegClosePath,SVGPathSegCurvetoCubicAbs,SVGPathSegCurvetoCubicRel,SVGPathSegCurvetoCubicSmoothAbs,SVGPathSegCurvetoCubicSmoothRel,SVGPathSegCurvetoQuadraticAbs,SVGPathSegCurvetoQuadraticRel,SVGPathSegCurvetoQuadraticSmoothAbs,SVGPathSegCurvetoQuadraticSmoothRel,SVGPathSegLinetoAbs,SVGPathSegLinetoHorizontalAbs,SVGPathSegLinetoHorizontalRel,SVGPathSegLinetoRel,SVGPathSegLinetoVerticalAbs,SVGPathSegLinetoVerticalRel,SVGPathSegMovetoAbs,SVGPathSegMovetoRel,ElementTimeControl,TimeEvent,SVGAnimatedPathData,SVGAnimatedPoints,SVGColorProfileRule,SVGCSSRule,SVGExternalResourcesRequired,SVGFitToViewBox,SVGLangSpace,SVGLocatable,SVGRenderingIntent,SVGStylable,SVGTests,SVGTextContentElement,SVGTextPositioningElement,SVGTransformable,SVGUnitTypes,SVGURIReference,SVGViewSpec,SVGZoomAndPan"); -Blockly.JavaScript.ORDER_ATOMIC=0;Blockly.JavaScript.ORDER_NEW=1.1;Blockly.JavaScript.ORDER_MEMBER=1.2;Blockly.JavaScript.ORDER_FUNCTION_CALL=2;Blockly.JavaScript.ORDER_INCREMENT=3;Blockly.JavaScript.ORDER_DECREMENT=3;Blockly.JavaScript.ORDER_BITWISE_NOT=4.1;Blockly.JavaScript.ORDER_UNARY_PLUS=4.2;Blockly.JavaScript.ORDER_UNARY_NEGATION=4.3;Blockly.JavaScript.ORDER_LOGICAL_NOT=4.4;Blockly.JavaScript.ORDER_TYPEOF=4.5;Blockly.JavaScript.ORDER_VOID=4.6;Blockly.JavaScript.ORDER_DELETE=4.7; -Blockly.JavaScript.ORDER_DIVISION=5.1;Blockly.JavaScript.ORDER_MULTIPLICATION=5.2;Blockly.JavaScript.ORDER_MODULUS=5.3;Blockly.JavaScript.ORDER_SUBTRACTION=6.1;Blockly.JavaScript.ORDER_ADDITION=6.2;Blockly.JavaScript.ORDER_BITWISE_SHIFT=7;Blockly.JavaScript.ORDER_RELATIONAL=8;Blockly.JavaScript.ORDER_IN=8;Blockly.JavaScript.ORDER_INSTANCEOF=8;Blockly.JavaScript.ORDER_EQUALITY=9;Blockly.JavaScript.ORDER_BITWISE_AND=10;Blockly.JavaScript.ORDER_BITWISE_XOR=11;Blockly.JavaScript.ORDER_BITWISE_OR=12; -Blockly.JavaScript.ORDER_LOGICAL_AND=13;Blockly.JavaScript.ORDER_LOGICAL_OR=14;Blockly.JavaScript.ORDER_CONDITIONAL=15;Blockly.JavaScript.ORDER_ASSIGNMENT=16;Blockly.JavaScript.ORDER_COMMA=17;Blockly.JavaScript.ORDER_NONE=99; -Blockly.JavaScript.ORDER_OVERRIDES=[[Blockly.JavaScript.ORDER_FUNCTION_CALL,Blockly.JavaScript.ORDER_MEMBER],[Blockly.JavaScript.ORDER_FUNCTION_CALL,Blockly.JavaScript.ORDER_FUNCTION_CALL],[Blockly.JavaScript.ORDER_MEMBER,Blockly.JavaScript.ORDER_MEMBER],[Blockly.JavaScript.ORDER_MEMBER,Blockly.JavaScript.ORDER_FUNCTION_CALL],[Blockly.JavaScript.ORDER_LOGICAL_NOT,Blockly.JavaScript.ORDER_LOGICAL_NOT],[Blockly.JavaScript.ORDER_MULTIPLICATION,Blockly.JavaScript.ORDER_MULTIPLICATION],[Blockly.JavaScript.ORDER_ADDITION, -Blockly.JavaScript.ORDER_ADDITION],[Blockly.JavaScript.ORDER_LOGICAL_AND,Blockly.JavaScript.ORDER_LOGICAL_AND],[Blockly.JavaScript.ORDER_LOGICAL_OR,Blockly.JavaScript.ORDER_LOGICAL_OR]];Blockly.JavaScript.ONE_BASED_INDEXING=!0; -Blockly.JavaScript.init=function(a){Blockly.JavaScript.definitions_=Object.create(null);Blockly.JavaScript.functionNames_=Object.create(null);Blockly.JavaScript.variableDB_?Blockly.JavaScript.variableDB_.reset():Blockly.JavaScript.variableDB_=new Blockly.Names(Blockly.JavaScript.RESERVED_WORDS_);var b=[];a=a.variableList;if(a.length){for(var c=0;cc?Blockly.JavaScript.valueToCode(a,b,Blockly.JavaScript.ORDER_SUBTRACTION)||f:d?Blockly.JavaScript.valueToCode(a,b,Blockly.JavaScript.ORDER_UNARY_NEGATION)||f:Blockly.JavaScript.valueToCode(a,b,e)||f;if(Blockly.isNumber(a))a=parseFloat(a)+ -c,d&&(a=-a);else{if(0c&&(a=a+" - "+-c,g=Blockly.JavaScript.ORDER_SUBTRACTION);d&&(a=c?"-("+a+")":"-"+a,g=Blockly.JavaScript.ORDER_UNARY_NEGATION);g=Math.floor(g);e=Math.floor(e);g&&e>=g&&(a="("+a+")")}return a};Blockly.JavaScript.lists={};Blockly.JavaScript.lists_create_empty=function(a){return["[]",Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.lists_create_with=function(a){for(var b=Array(a.itemCount_),c=0;c b.toString() ? 1 : -1; },", -' "IGNORE_CASE": function(a, b) {'," return a.toString().toLowerCase() > b.toString().toLowerCase() ? 1 : -1; },"," };"," var compare = compareFuncs[type];"," return function(a, b) { return compare(a, b) * direction; }","}"]);return[b+".slice().sort("+d+'("'+a+'", '+c+"))",Blockly.JavaScript.ORDER_FUNCTION_CALL]}; -Blockly.JavaScript.lists_split=function(a){var b=Blockly.JavaScript.valueToCode(a,"INPUT",Blockly.JavaScript.ORDER_MEMBER),c=Blockly.JavaScript.valueToCode(a,"DELIM",Blockly.JavaScript.ORDER_NONE)||"''";a=a.getFieldValue("MODE");if("SPLIT"==a)b||(b="''"),a="split";else if("JOIN"==a)b||(b="[]"),a="join";else throw"Unknown mode: "+a;return[b+"."+a+"("+c+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.math={};Blockly.JavaScript.math_number=function(a){return[parseFloat(a.getFieldValue("NUM")),Blockly.JavaScript.ORDER_ATOMIC]}; -Blockly.JavaScript.math_arithmetic=function(a){var b={ADD:[" + ",Blockly.JavaScript.ORDER_ADDITION],MINUS:[" - ",Blockly.JavaScript.ORDER_SUBTRACTION],MULTIPLY:[" * ",Blockly.JavaScript.ORDER_MULTIPLICATION],DIVIDE:[" / ",Blockly.JavaScript.ORDER_DIVISION],POWER:[null,Blockly.JavaScript.ORDER_COMMA]}[a.getFieldValue("OP")],c=b[0],b=b[1],d=Blockly.JavaScript.valueToCode(a,"A",b)||"0";a=Blockly.JavaScript.valueToCode(a,"B",b)||"0";return c?[d+c+a,b]:["Math.pow("+d+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]}; -Blockly.JavaScript.math_single=function(a){var b=a.getFieldValue("OP"),c;if("NEG"==b)return a=Blockly.JavaScript.valueToCode(a,"NUM",Blockly.JavaScript.ORDER_UNARY_NEGATION)||"0","-"==a[0]&&(a=" "+a),["-"+a,Blockly.JavaScript.ORDER_UNARY_NEGATION];a="SIN"==b||"COS"==b||"TAN"==b?Blockly.JavaScript.valueToCode(a,"NUM",Blockly.JavaScript.ORDER_DIVISION)||"0":Blockly.JavaScript.valueToCode(a,"NUM",Blockly.JavaScript.ORDER_NONE)||"0";switch(b){case "ABS":c="Math.abs("+a+")";break;case "ROOT":c="Math.sqrt("+ -a+")";break;case "LN":c="Math.log("+a+")";break;case "EXP":c="Math.exp("+a+")";break;case "POW10":c="Math.pow(10,"+a+")";break;case "ROUND":c="Math.round("+a+")";break;case "ROUNDUP":c="Math.ceil("+a+")";break;case "ROUNDDOWN":c="Math.floor("+a+")";break;case "SIN":c="Math.sin("+a+" / 180 * Math.PI)";break;case "COS":c="Math.cos("+a+" / 180 * Math.PI)";break;case "TAN":c="Math.tan("+a+" / 180 * Math.PI)"}if(c)return[c,Blockly.JavaScript.ORDER_FUNCTION_CALL];switch(b){case "LOG10":c="Math.log("+a+ -") / Math.log(10)";break;case "ASIN":c="Math.asin("+a+") / Math.PI * 180";break;case "ACOS":c="Math.acos("+a+") / Math.PI * 180";break;case "ATAN":c="Math.atan("+a+") / Math.PI * 180";break;default:throw"Unknown math operator: "+b;}return[c,Blockly.JavaScript.ORDER_DIVISION]}; -Blockly.JavaScript.math_constant=function(a){return{PI:["Math.PI",Blockly.JavaScript.ORDER_MEMBER],E:["Math.E",Blockly.JavaScript.ORDER_MEMBER],GOLDEN_RATIO:["(1 + Math.sqrt(5)) / 2",Blockly.JavaScript.ORDER_DIVISION],SQRT2:["Math.SQRT2",Blockly.JavaScript.ORDER_MEMBER],SQRT1_2:["Math.SQRT1_2",Blockly.JavaScript.ORDER_MEMBER],INFINITY:["Infinity",Blockly.JavaScript.ORDER_ATOMIC]}[a.getFieldValue("CONSTANT")]}; -Blockly.JavaScript.math_number_property=function(a){var b=Blockly.JavaScript.valueToCode(a,"NUMBER_TO_CHECK",Blockly.JavaScript.ORDER_MODULUS)||"0",c=a.getFieldValue("PROPERTY"),d;if("PRIME"==c)return[Blockly.JavaScript.provideFunction_("mathIsPrime",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(n) {"," // https://en.wikipedia.org/wiki/Primality_test#Naive_methods"," if (n == 2 || n == 3) {"," return true;"," }"," // False if n is NaN, negative, is 1, or not whole."," // And false if n is divisible by 2 or 3.", -" if (isNaN(n) || n <= 1 || n % 1 != 0 || n % 2 == 0 || n % 3 == 0) {"," return false;"," }"," // Check all the numbers of form 6k +/- 1, up to sqrt(n)."," for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {"," if (n % (x - 1) == 0 || n % (x + 1) == 0) {"," return false;"," }"," }"," return true;","}"])+"("+b+")",Blockly.JavaScript.ORDER_FUNCTION_CALL];switch(c){case "EVEN":d=b+" % 2 == 0";break;case "ODD":d=b+" % 2 == 1";break;case "WHOLE":d=b+" % 1 == 0";break;case "POSITIVE":d= -b+" > 0";break;case "NEGATIVE":d=b+" < 0";break;case "DIVISIBLE_BY":a=Blockly.JavaScript.valueToCode(a,"DIVISOR",Blockly.JavaScript.ORDER_MODULUS)||"0",d=b+" % "+a+" == 0"}return[d,Blockly.JavaScript.ORDER_EQUALITY]};Blockly.JavaScript.math_change=function(a){var b=Blockly.JavaScript.valueToCode(a,"DELTA",Blockly.JavaScript.ORDER_ADDITION)||"0";a=Blockly.JavaScript.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE);return a+" = (typeof "+a+" == 'number' ? "+a+" : 0) + "+b+";\n"}; -Blockly.JavaScript.math_round=Blockly.JavaScript.math_single;Blockly.JavaScript.math_trig=Blockly.JavaScript.math_single; -Blockly.JavaScript.math_on_list=function(a){var b=a.getFieldValue("OP");switch(b){case "SUM":a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_MEMBER)||"[]";a+=".reduce(function(x, y) {return x + y;})";break;case "MIN":a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_COMMA)||"[]";a="Math.min.apply(null, "+a+")";break;case "MAX":a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_COMMA)||"[]";a="Math.max.apply(null, "+a+")";break;case "AVERAGE":b=Blockly.JavaScript.provideFunction_("mathMean", -["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(myList) {"," return myList.reduce(function(x, y) {return x + y;}) / myList.length;","}"]);a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=b+"("+a+")";break;case "MEDIAN":b=Blockly.JavaScript.provideFunction_("mathMedian",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(myList) {"," var localList = myList.filter(function (x) {return typeof x == 'number';});"," if (!localList.length) return null;", -" localList.sort(function(a, b) {return b - a;});"," if (localList.length % 2 == 0) {"," return (localList[localList.length / 2 - 1] + localList[localList.length / 2]) / 2;"," } else {"," return localList[(localList.length - 1) / 2];"," }","}"]);a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=b+"("+a+")";break;case "MODE":b=Blockly.JavaScript.provideFunction_("mathModes",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(values) {"," var modes = [];", -" var counts = [];"," var maxCount = 0;"," for (var i = 0; i < values.length; i++) {"," var value = values[i];"," var found = false;"," var thisCount;"," for (var j = 0; j < counts.length; j++) {"," if (counts[j][0] === value) {"," thisCount = ++counts[j][1];"," found = true;"," break;"," }"," }"," if (!found) {"," counts.push([value, 1]);"," thisCount = 1;"," }"," maxCount = Math.max(thisCount, maxCount);"," }"," for (var j = 0; j < counts.length; j++) {", -" if (counts[j][1] == maxCount) {"," modes.push(counts[j][0]);"," }"," }"," return modes;","}"]);a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=b+"("+a+")";break;case "STD_DEV":b=Blockly.JavaScript.provideFunction_("mathStandardDeviation",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(numbers) {"," var n = numbers.length;"," if (!n) return null;"," var mean = numbers.reduce(function(x, y) {return x + y;}) / n;"," var variance = 0;", -" for (var j = 0; j < n; j++) {"," variance += Math.pow(numbers[j] - mean, 2);"," }"," variance = variance / n;"," return Math.sqrt(variance);","}"]);a=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=b+"("+a+")";break;case "RANDOM":b=Blockly.JavaScript.provideFunction_("mathRandomList",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(list) {"," var x = Math.floor(Math.random() * list.length);"," return list[x];","}"]);a=Blockly.JavaScript.valueToCode(a, -"LIST",Blockly.JavaScript.ORDER_NONE)||"[]";a=b+"("+a+")";break;default:throw"Unknown operator: "+b;}return[a,Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.math_modulo=function(a){var b=Blockly.JavaScript.valueToCode(a,"DIVIDEND",Blockly.JavaScript.ORDER_MODULUS)||"0";a=Blockly.JavaScript.valueToCode(a,"DIVISOR",Blockly.JavaScript.ORDER_MODULUS)||"0";return[b+" % "+a,Blockly.JavaScript.ORDER_MODULUS]}; -Blockly.JavaScript.math_constrain=function(a){var b=Blockly.JavaScript.valueToCode(a,"VALUE",Blockly.JavaScript.ORDER_COMMA)||"0",c=Blockly.JavaScript.valueToCode(a,"LOW",Blockly.JavaScript.ORDER_COMMA)||"0";a=Blockly.JavaScript.valueToCode(a,"HIGH",Blockly.JavaScript.ORDER_COMMA)||"Infinity";return["Math.min(Math.max("+b+", "+c+"), "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]}; -Blockly.JavaScript.math_random_int=function(a){var b=Blockly.JavaScript.valueToCode(a,"FROM",Blockly.JavaScript.ORDER_COMMA)||"0";a=Blockly.JavaScript.valueToCode(a,"TO",Blockly.JavaScript.ORDER_COMMA)||"0";return[Blockly.JavaScript.provideFunction_("mathRandomInt",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(a, b) {"," if (a > b) {"," // Swap a and b to ensure a is smaller."," var c = a;"," a = b;"," b = c;"," }"," return Math.floor(Math.random() * (b - a + 1) + a);", -"}"])+"("+b+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.math_random_float=function(a){return["Math.random()",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.variables={};Blockly.JavaScript.variables_get=function(a){return[Blockly.JavaScript.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE),Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.variables_set=function(a){var b=Blockly.JavaScript.valueToCode(a,"VALUE",Blockly.JavaScript.ORDER_ASSIGNMENT)||"0";return Blockly.JavaScript.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE)+" = "+b+";\n"};Blockly.JavaScript.colour={};Blockly.JavaScript.colour_picker=function(a){return["'"+a.getFieldValue("COLOUR")+"'",Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.colour_random=function(a){return[Blockly.JavaScript.provideFunction_("colourRandom",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"() {"," var num = Math.floor(Math.random() * Math.pow(2, 24));"," return '#' + ('00000' + num.toString(16)).substr(-6);","}"])+"()",Blockly.JavaScript.ORDER_FUNCTION_CALL]}; -Blockly.JavaScript.colour_rgb=function(a){var b=Blockly.JavaScript.valueToCode(a,"RED",Blockly.JavaScript.ORDER_COMMA)||0,c=Blockly.JavaScript.valueToCode(a,"GREEN",Blockly.JavaScript.ORDER_COMMA)||0;a=Blockly.JavaScript.valueToCode(a,"BLUE",Blockly.JavaScript.ORDER_COMMA)||0;return[Blockly.JavaScript.provideFunction_("colourRgb",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(r, g, b) {"," r = Math.max(Math.min(Number(r), 100), 0) * 2.55;"," g = Math.max(Math.min(Number(g), 100), 0) * 2.55;", -" b = Math.max(Math.min(Number(b), 100), 0) * 2.55;"," r = ('0' + (Math.round(r) || 0).toString(16)).slice(-2);"," g = ('0' + (Math.round(g) || 0).toString(16)).slice(-2);"," b = ('0' + (Math.round(b) || 0).toString(16)).slice(-2);"," return '#' + r + g + b;","}"])+"("+b+", "+c+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]}; -Blockly.JavaScript.colour_blend=function(a){var b=Blockly.JavaScript.valueToCode(a,"COLOUR1",Blockly.JavaScript.ORDER_COMMA)||"'#000000'",c=Blockly.JavaScript.valueToCode(a,"COLOUR2",Blockly.JavaScript.ORDER_COMMA)||"'#000000'";a=Blockly.JavaScript.valueToCode(a,"RATIO",Blockly.JavaScript.ORDER_COMMA)||.5;return[Blockly.JavaScript.provideFunction_("colourBlend",["function "+Blockly.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(c1, c2, ratio) {"," ratio = Math.max(Math.min(Number(ratio), 1), 0);"," var r1 = parseInt(c1.substring(1, 3), 16);", -" var g1 = parseInt(c1.substring(3, 5), 16);"," var b1 = parseInt(c1.substring(5, 7), 16);"," var r2 = parseInt(c2.substring(1, 3), 16);"," var g2 = parseInt(c2.substring(3, 5), 16);"," var b2 = parseInt(c2.substring(5, 7), 16);"," var r = Math.round(r1 * (1 - ratio) + r2 * ratio);"," var g = Math.round(g1 * (1 - ratio) + g2 * ratio);"," var b = Math.round(b1 * (1 - ratio) + b2 * ratio);"," r = ('0' + (r || 0).toString(16)).slice(-2);"," g = ('0' + (g || 0).toString(16)).slice(-2);"," b = ('0' + (b || 0).toString(16)).slice(-2);", -" return '#' + r + g + b;","}"])+"("+b+", "+c+", "+a+")",Blockly.JavaScript.ORDER_FUNCTION_CALL]};Blockly.JavaScript.procedures={}; -Blockly.JavaScript.procedures_defreturn=function(a){var b=Blockly.JavaScript.variableDB_.getName(a.getFieldValue("NAME"),Blockly.Procedures.NAME_TYPE),c=Blockly.JavaScript.statementToCode(a,"STACK");Blockly.JavaScript.STATEMENT_PREFIX&&(c=Blockly.JavaScript.prefixLines(Blockly.JavaScript.STATEMENT_PREFIX.replace(/%1/g,"'"+a.id+"'"),Blockly.JavaScript.INDENT)+c);Blockly.JavaScript.INFINITE_LOOP_TRAP&&(c=Blockly.JavaScript.INFINITE_LOOP_TRAP.replace(/%1/g,"'"+a.id+"'")+c);var d=Blockly.JavaScript.valueToCode(a, -"RETURN",Blockly.JavaScript.ORDER_NONE)||"";d&&(d=" return "+d+";\n");for(var e=[],f=0;f= ")+d+"; "+b;b=Math.abs(parseFloat(e));a=(1==b?a+(g?"++":"--"):a+((g?" += ":" -= ")+b))+(") {\n"+f+"}\n")}else a="",g=c,c.match(/^\w+$/)||Blockly.isNumber(c)||(g=Blockly.JavaScript.variableDB_.getDistinctName(b+"_start",Blockly.Variables.NAME_TYPE),a+="var "+g+" = "+c+";\n"),c=d,d.match(/^\w+$/)||Blockly.isNumber(d)||(c=Blockly.JavaScript.variableDB_.getDistinctName(b+"_end",Blockly.Variables.NAME_TYPE), -a+="var "+c+" = "+d+";\n"),d=Blockly.JavaScript.variableDB_.getDistinctName(b+"_inc",Blockly.Variables.NAME_TYPE),a+="var "+d+" = ",a=Blockly.isNumber(e)?a+(Math.abs(e)+";\n"):a+("Math.abs("+e+");\n"),a=a+("if ("+g+" > "+c+") {\n")+(Blockly.JavaScript.INDENT+d+" = -"+d+";\n"),a+="}\n",a+="for ("+b+" = "+g+"; "+d+" >= 0 ? "+b+" <= "+c+" : "+b+" >= "+c+"; "+b+" += "+d+") {\n"+f+"}\n";return a}; -Blockly.JavaScript.controls_forEach=function(a){var b=Blockly.JavaScript.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE),c=Blockly.JavaScript.valueToCode(a,"LIST",Blockly.JavaScript.ORDER_ASSIGNMENT)||"[]",d=Blockly.JavaScript.statementToCode(a,"DO"),d=Blockly.JavaScript.addLoopTrap(d,a.id);a="";var e=c;c.match(/^\w+$/)||(e=Blockly.JavaScript.variableDB_.getDistinctName(b+"_list",Blockly.Variables.NAME_TYPE),a+="var "+e+" = "+c+";\n");c=Blockly.JavaScript.variableDB_.getDistinctName(b+ -"_index",Blockly.Variables.NAME_TYPE);d=Blockly.JavaScript.INDENT+b+" = "+e+"["+c+"];\n"+d;return a+("for (var "+c+" in "+e+") {\n"+d+"}\n")};Blockly.JavaScript.controls_flow_statements=function(a){switch(a.getFieldValue("FLOW")){case "BREAK":return"break;\n";case "CONTINUE":return"continue;\n"}throw"Unknown flow statement.";};Blockly.JavaScript.logic={}; -Blockly.JavaScript.controls_if=function(a){for(var b=0,c=Blockly.JavaScript.valueToCode(a,"IF"+b,Blockly.JavaScript.ORDER_NONE)||"false",d=Blockly.JavaScript.statementToCode(a,"DO"+b),e="if ("+c+") {\n"+d+"}",b=1;b<=a.elseifCount_;b++)c=Blockly.JavaScript.valueToCode(a,"IF"+b,Blockly.JavaScript.ORDER_NONE)||"false",d=Blockly.JavaScript.statementToCode(a,"DO"+b),e+=" else if ("+c+") {\n"+d+"}";a.elseCount_&&(d=Blockly.JavaScript.statementToCode(a,"ELSE"),e+=" else {\n"+d+"}");return e+"\n"}; -Blockly.JavaScript.logic_compare=function(a){var b={EQ:"==",NEQ:"!=",LT:"<",LTE:"<=",GT:">",GTE:">="}[a.getFieldValue("OP")],c="=="==b||"!="==b?Blockly.JavaScript.ORDER_EQUALITY:Blockly.JavaScript.ORDER_RELATIONAL,d=Blockly.JavaScript.valueToCode(a,"A",c)||"0";a=Blockly.JavaScript.valueToCode(a,"B",c)||"0";return[d+" "+b+" "+a,c]}; -Blockly.JavaScript.logic_operation=function(a){var b="AND"==a.getFieldValue("OP")?"&&":"||",c="&&"==b?Blockly.JavaScript.ORDER_LOGICAL_AND:Blockly.JavaScript.ORDER_LOGICAL_OR,d=Blockly.JavaScript.valueToCode(a,"A",c);a=Blockly.JavaScript.valueToCode(a,"B",c);if(d||a){var e="&&"==b?"true":"false";d||(d=e);a||(a=e)}else a=d="false";return[d+" "+b+" "+a,c]}; -Blockly.JavaScript.logic_negate=function(a){var b=Blockly.JavaScript.ORDER_LOGICAL_NOT;return["!"+(Blockly.JavaScript.valueToCode(a,"BOOL",b)||"true"),b]};Blockly.JavaScript.logic_boolean=function(a){return["TRUE"==a.getFieldValue("BOOL")?"true":"false",Blockly.JavaScript.ORDER_ATOMIC]};Blockly.JavaScript.logic_null=function(a){return["null",Blockly.JavaScript.ORDER_ATOMIC]}; -Blockly.JavaScript.logic_ternary=function(a){var b=Blockly.JavaScript.valueToCode(a,"IF",Blockly.JavaScript.ORDER_CONDITIONAL)||"false",c=Blockly.JavaScript.valueToCode(a,"THEN",Blockly.JavaScript.ORDER_CONDITIONAL)||"null";a=Blockly.JavaScript.valueToCode(a,"ELSE",Blockly.JavaScript.ORDER_CONDITIONAL)||"null";return[b+" ? "+c+" : "+a,Blockly.JavaScript.ORDER_CONDITIONAL]}; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/lua_compressed.js b/backend/_pv_1_3_5/static/blockly/lua_compressed.js deleted file mode 100755 index b9c47fcec..000000000 --- a/backend/_pv_1_3_5/static/blockly/lua_compressed.js +++ /dev/null @@ -1,74 +0,0 @@ -// Do not edit this file; automatically generated by build.py. -'use strict'; - - -// Copyright 2016 Google Inc. Apache License 2.0 -Blockly.Lua=new Blockly.Generator("Lua");Blockly.Lua.addReservedWords("_,__inext,assert,bit,colors,colours,coroutine,disk,dofile,error,fs,fetfenv,getmetatable,gps,help,io,ipairs,keys,loadfile,loadstring,math,native,next,os,paintutils,pairs,parallel,pcall,peripheral,print,printError,rawequal,rawget,rawset,read,rednet,redstone,rs,select,setfenv,setmetatable,sleep,string,table,term,textutils,tonumber,tostring,turtle,type,unpack,vector,write,xpcall,_VERSION,__indext,HTTP,and,break,do,else,elseif,end,false,for,function,if,in,local,nil,not,or,repeat,return,then,true,until,while,add,sub,mul,div,mod,pow,unm,concat,len,eq,lt,le,index,newindex,call,assert,collectgarbage,dofile,error,_G,getmetatable,inpairs,load,loadfile,next,pairs,pcall,print,rawequal,rawget,rawlen,rawset,select,setmetatable,tonumber,tostring,type,_VERSION,xpcall,require,package,string,table,math,bit32,io,file,os,debug"); -Blockly.Lua.ORDER_ATOMIC=0;Blockly.Lua.ORDER_HIGH=1;Blockly.Lua.ORDER_EXPONENTIATION=2;Blockly.Lua.ORDER_UNARY=3;Blockly.Lua.ORDER_MULTIPLICATIVE=4;Blockly.Lua.ORDER_ADDITIVE=5;Blockly.Lua.ORDER_CONCATENATION=6;Blockly.Lua.ORDER_RELATIONAL=7;Blockly.Lua.ORDER_AND=8;Blockly.Lua.ORDER_OR=9;Blockly.Lua.ORDER_NONE=99; -Blockly.Lua.init=function(a){Blockly.Lua.definitions_=Object.create(null);Blockly.Lua.functionNames_=Object.create(null);Blockly.Lua.variableDB_?Blockly.Lua.variableDB_.reset():Blockly.Lua.variableDB_=new Blockly.Names(Blockly.Lua.RESERVED_WORDS_)};Blockly.Lua.finish=function(a){var b=[],c;for(c in Blockly.Lua.definitions_)b.push(Blockly.Lua.definitions_[c]);delete Blockly.Lua.definitions_;delete Blockly.Lua.functionNames_;Blockly.Lua.variableDB_.reset();return b.join("\n\n")+"\n\n\n"+a}; -Blockly.Lua.scrubNakedValue=function(a){return"local _ = "+a+"\n"};Blockly.Lua.quote_=function(a){a=a.replace(/\\/g,"\\\\").replace(/\n/g,"\\\n").replace(/'/g,"\\'");return"'"+a+"'"}; -Blockly.Lua.scrub_=function(a,b){var c="";if(!a.outputConnection||!a.outputConnection.targetConnection){var d=a.getCommentText();(d=Blockly.utils.wrap(d,Blockly.Lua.COMMENT_WRAP-3))&&(c+=Blockly.Lua.prefixLines(d,"-- ")+"\n");for(var e=0;ea?Blockly.Lua.ORDER_UNARY:Blockly.Lua.ORDER_ATOMIC]}; -Blockly.Lua.math_arithmetic=function(a){var b={ADD:[" + ",Blockly.Lua.ORDER_ADDITIVE],MINUS:[" - ",Blockly.Lua.ORDER_ADDITIVE],MULTIPLY:[" * ",Blockly.Lua.ORDER_MULTIPLICATIVE],DIVIDE:[" / ",Blockly.Lua.ORDER_MULTIPLICATIVE],POWER:[" ^ ",Blockly.Lua.ORDER_EXPONENTIATION]}[a.getFieldValue("OP")],c=b[0],b=b[1],d=Blockly.Lua.valueToCode(a,"A",b)||"0";a=Blockly.Lua.valueToCode(a,"B",b)||"0";return[d+c+a,b]}; -Blockly.Lua.math_single=function(a){var b=a.getFieldValue("OP");if("NEG"==b)return a=Blockly.Lua.valueToCode(a,"NUM",Blockly.Lua.ORDER_UNARY)||"0",["-"+a,Blockly.Lua.ORDER_UNARY];a="SIN"==b||"COS"==b||"TAN"==b?Blockly.Lua.valueToCode(a,"NUM",Blockly.Lua.ORDER_MULTIPLICATIVE)||"0":Blockly.Lua.valueToCode(a,"NUM",Blockly.Lua.ORDER_NONE)||"0";switch(b){case "ABS":b="math.abs("+a+")";break;case "ROOT":b="math.sqrt("+a+")";break;case "LN":b="math.log("+a+")";break;case "LOG10":b="math.log10("+a+")";break; -case "EXP":b="math.exp("+a+")";break;case "POW10":b="math.pow(10,"+a+")";break;case "ROUND":b="math.floor("+a+" + .5)";break;case "ROUNDUP":b="math.ceil("+a+")";break;case "ROUNDDOWN":b="math.floor("+a+")";break;case "SIN":b="math.sin(math.rad("+a+"))";break;case "COS":b="math.cos(math.rad("+a+"))";break;case "TAN":b="math.tan(math.rad("+a+"))";break;case "ASIN":b="math.deg(math.asin("+a+"))";break;case "ACOS":b="math.deg(math.acos("+a+"))";break;case "ATAN":b="math.deg(math.atan("+a+"))";break;default:throw"Unknown math operator: "+ -b;}return[b,Blockly.Lua.ORDER_HIGH]};Blockly.Lua.math_constant=function(a){return{PI:["math.pi",Blockly.Lua.ORDER_HIGH],E:["math.exp(1)",Blockly.Lua.ORDER_HIGH],GOLDEN_RATIO:["(1 + math.sqrt(5)) / 2",Blockly.Lua.ORDER_MULTIPLICATIVE],SQRT2:["math.sqrt(2)",Blockly.Lua.ORDER_HIGH],SQRT1_2:["math.sqrt(1 / 2)",Blockly.Lua.ORDER_HIGH],INFINITY:["math.huge",Blockly.Lua.ORDER_HIGH]}[a.getFieldValue("CONSTANT")]}; -Blockly.Lua.math_number_property=function(a){var b=Blockly.Lua.valueToCode(a,"NUMBER_TO_CHECK",Blockly.Lua.ORDER_MULTIPLICATIVE)||"0",c=a.getFieldValue("PROPERTY"),d;if("PRIME"==c)return[Blockly.Lua.provideFunction_("math_isPrime",["function "+Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_+"(n)"," -- https://en.wikipedia.org/wiki/Primality_test#Naive_methods"," if n == 2 or n == 3 then"," return true"," end"," -- False if n is NaN, negative, is 1, or not whole."," -- And false if n is divisible by 2 or 3.", -" if not(n > 1) or n % 1 ~= 0 or n % 2 == 0 or n % 3 == 0 then"," return false"," end"," -- Check all the numbers of form 6k +/- 1, up to sqrt(n)."," for x = 6, math.sqrt(n) + 1.5, 6 do"," if n % (x - 1) == 0 or n % (x + 1) == 0 then"," return false"," end"," end"," return true","end"])+"("+b+")",Blockly.Lua.ORDER_HIGH];switch(c){case "EVEN":d=b+" % 2 == 0";break;case "ODD":d=b+" % 2 == 1";break;case "WHOLE":d=b+" % 1 == 0";break;case "POSITIVE":d=b+" > 0";break;case "NEGATIVE":d= -b+" < 0";break;case "DIVISIBLE_BY":a=Blockly.Lua.valueToCode(a,"DIVISOR",Blockly.Lua.ORDER_MULTIPLICATIVE);if(!a||"0"==a)return["nil",Blockly.Lua.ORDER_ATOMIC];d=b+" % "+a+" == 0"}return[d,Blockly.Lua.ORDER_RELATIONAL]};Blockly.Lua.math_change=function(a){var b=Blockly.Lua.valueToCode(a,"DELTA",Blockly.Lua.ORDER_ADDITIVE)||"0";a=Blockly.Lua.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE);return a+" = "+a+" + "+b+"\n"};Blockly.Lua.math_round=Blockly.Lua.math_single; -Blockly.Lua.math_trig=Blockly.Lua.math_single; -Blockly.Lua.math_on_list=function(a){function b(){return Blockly.Lua.provideFunction_("math_sum",["function "+Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_+"(t)"," local result = 0"," for _, v in ipairs(t) do"," result = result + v"," end"," return result","end"])}var c=a.getFieldValue("OP");a=Blockly.Lua.valueToCode(a,"LIST",Blockly.Lua.ORDER_NONE)||"{}";switch(c){case "SUM":c=b();break;case "MIN":c=Blockly.Lua.provideFunction_("math_min",["function "+Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_+"(t)", -" if #t == 0 then"," return 0"," end"," local result = math.huge"," for _, v in ipairs(t) do"," if v < result then"," result = v"," end"," end"," return result","end"]);break;case "AVERAGE":c=Blockly.Lua.provideFunction_("math_average",["function "+Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_+"(t)"," if #t == 0 then"," return 0"," end"," return "+b()+"(t) / #t","end"]);break;case "MAX":c=Blockly.Lua.provideFunction_("math_max",["function "+Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_+ -"(t)"," if #t == 0 then"," return 0"," end"," local result = -math.huge"," for _, v in ipairs(t) do"," if v > result then"," result = v"," end"," end"," return result","end"]);break;case "MEDIAN":c=Blockly.Lua.provideFunction_("math_median",["function "+Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_+"(t)"," -- Source: http://lua-users.org/wiki/SimpleStats"," if #t == 0 then"," return 0"," end"," local temp={}"," for _, v in ipairs(t) do",' if type(v) == "number" then'," table.insert(temp, v)", -" end"," end"," table.sort(temp)"," if #temp % 2 == 0 then"," return (temp[#temp/2] + temp[(#temp/2)+1]) / 2"," else"," return temp[math.ceil(#temp/2)]"," end","end"]);break;case "MODE":c=Blockly.Lua.provideFunction_("math_modes",["function "+Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_+"(t)"," -- Source: http://lua-users.org/wiki/SimpleStats"," local counts={}"," for _, v in ipairs(t) do"," if counts[v] == nil then"," counts[v] = 1"," else"," counts[v] = counts[v] + 1", -" end"," end"," local biggestCount = 0"," for _, v in pairs(counts) do"," if v > biggestCount then"," biggestCount = v"," end"," end"," local temp={}"," for k, v in pairs(counts) do"," if v == biggestCount then"," table.insert(temp, k)"," end"," end"," return temp","end"]);break;case "STD_DEV":c=Blockly.Lua.provideFunction_("math_standard_deviation",["function "+Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_+"(t)"," local m"," local vm"," local total = 0"," local count = 0", -" local result"," m = #t == 0 and 0 or "+b()+"(t) / #t"," for _, v in ipairs(t) do"," if type(v) == 'number' then"," vm = v - m"," total = total + (vm * vm)"," count = count + 1"," end"," end"," result = math.sqrt(total / (count-1))"," return result","end"]);break;case "RANDOM":c=Blockly.Lua.provideFunction_("math_random_list",["function "+Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_+"(t)"," if #t == 0 then"," return nil"," end"," return t[math.random(#t)]","end"]);break; -default:throw"Unknown operator: "+c;}return[c+"("+a+")",Blockly.Lua.ORDER_HIGH]};Blockly.Lua.math_modulo=function(a){var b=Blockly.Lua.valueToCode(a,"DIVIDEND",Blockly.Lua.ORDER_MULTIPLICATIVE)||"0";a=Blockly.Lua.valueToCode(a,"DIVISOR",Blockly.Lua.ORDER_MULTIPLICATIVE)||"0";return[b+" % "+a,Blockly.Lua.ORDER_MULTIPLICATIVE]}; -Blockly.Lua.math_constrain=function(a){var b=Blockly.Lua.valueToCode(a,"VALUE",Blockly.Lua.ORDER_NONE)||"0",c=Blockly.Lua.valueToCode(a,"LOW",Blockly.Lua.ORDER_NONE)||"-math.huge";a=Blockly.Lua.valueToCode(a,"HIGH",Blockly.Lua.ORDER_NONE)||"math.huge";return["math.min(math.max("+b+", "+c+"), "+a+")",Blockly.Lua.ORDER_HIGH]}; -Blockly.Lua.math_random_int=function(a){var b=Blockly.Lua.valueToCode(a,"FROM",Blockly.Lua.ORDER_NONE)||"0";a=Blockly.Lua.valueToCode(a,"TO",Blockly.Lua.ORDER_NONE)||"0";return["math.random("+b+", "+a+")",Blockly.Lua.ORDER_HIGH]};Blockly.Lua.math_random_float=function(a){return["math.random()",Blockly.Lua.ORDER_HIGH]};Blockly.Lua.variables={};Blockly.Lua.variables_get=function(a){return[Blockly.Lua.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE),Blockly.Lua.ORDER_ATOMIC]};Blockly.Lua.variables_set=function(a){var b=Blockly.Lua.valueToCode(a,"VALUE",Blockly.Lua.ORDER_NONE)||"0";return Blockly.Lua.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE)+" = "+b+"\n"};Blockly.Lua.colour={};Blockly.Lua.colour_picker=function(a){return["'"+a.getFieldValue("COLOUR")+"'",Blockly.Lua.ORDER_ATOMIC]};Blockly.Lua.colour_random=function(a){return['string.format("#%06x", math.random(0, 2^24 - 1))',Blockly.Lua.ORDER_HIGH]}; -Blockly.Lua.colour_rgb=function(a){var b=Blockly.Lua.provideFunction_("colour_rgb",["function "+Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_+"(r, g, b)"," r = math.floor(math.min(100, math.max(0, r)) * 2.55 + .5)"," g = math.floor(math.min(100, math.max(0, g)) * 2.55 + .5)"," b = math.floor(math.min(100, math.max(0, b)) * 2.55 + .5)",' return string.format("#%02x%02x%02x", r, g, b)',"end"]),c=Blockly.Lua.valueToCode(a,"RED",Blockly.Lua.ORDER_NONE)||0,d=Blockly.Lua.valueToCode(a,"GREEN",Blockly.Lua.ORDER_NONE)|| -0;a=Blockly.Lua.valueToCode(a,"BLUE",Blockly.Lua.ORDER_NONE)||0;return[b+"("+c+", "+d+", "+a+")",Blockly.Lua.ORDER_HIGH]}; -Blockly.Lua.colour_blend=function(a){var b=Blockly.Lua.provideFunction_("colour_blend",["function "+Blockly.Lua.FUNCTION_NAME_PLACEHOLDER_+"(colour1, colour2, ratio)"," local r1 = tonumber(string.sub(colour1, 2, 3), 16)"," local r2 = tonumber(string.sub(colour2, 2, 3), 16)"," local g1 = tonumber(string.sub(colour1, 4, 5), 16)"," local g2 = tonumber(string.sub(colour2, 4, 5), 16)"," local b1 = tonumber(string.sub(colour1, 6, 7), 16)"," local b2 = tonumber(string.sub(colour2, 6, 7), 16)"," local ratio = math.min(1, math.max(0, ratio))", -" local r = math.floor(r1 * (1 - ratio) + r2 * ratio + .5)"," local g = math.floor(g1 * (1 - ratio) + g2 * ratio + .5)"," local b = math.floor(b1 * (1 - ratio) + b2 * ratio + .5)",' return string.format("#%02x%02x%02x", r, g, b)',"end"]),c=Blockly.Lua.valueToCode(a,"COLOUR1",Blockly.Lua.ORDER_NONE)||"'#000000'",d=Blockly.Lua.valueToCode(a,"COLOUR2",Blockly.Lua.ORDER_NONE)||"'#000000'";a=Blockly.Lua.valueToCode(a,"RATIO",Blockly.Lua.ORDER_NONE)||0;return[b+"("+c+", "+d+", "+a+")",Blockly.Lua.ORDER_HIGH]};Blockly.Lua.procedures={}; -Blockly.Lua.procedures_defreturn=function(a){var b=Blockly.Lua.variableDB_.getName(a.getFieldValue("NAME"),Blockly.Procedures.NAME_TYPE),c=Blockly.Lua.statementToCode(a,"STACK");Blockly.Lua.STATEMENT_PREFIX&&(c=Blockly.Lua.prefixLines(Blockly.Lua.STATEMENT_PREFIX.replace(/%1/g,"'"+a.id+"'"),Blockly.Lua.INDENT)+c);Blockly.Lua.INFINITE_LOOP_TRAP&&(c=Blockly.Lua.INFINITE_LOOP_TRAP.replace(/%1/g,"'"+a.id+"'")+c);var d=Blockly.Lua.valueToCode(a,"RETURN",Blockly.Lua.ORDER_NONE)||"";d?d=" return "+d+"\n": -c||(c="");for(var e=[],f=0;f ("+d+") then\n")+(Blockly.Lua.INDENT+g+" = -"+g+"\n"),a+="end\n");return a+("for "+b+" = "+c+", "+d+", "+g)+(" do\n"+f+"end\n")}; -Blockly.Lua.controls_forEach=function(a){var b=Blockly.Lua.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE),c=Blockly.Lua.valueToCode(a,"LIST",Blockly.Lua.ORDER_NONE)||"{}";a=Blockly.Lua.statementToCode(a,"DO")||"\n";a=Blockly.Lua.addContinueLabel(a);return"for _, "+b+" in ipairs("+c+") do \n"+a+"end\n"}; -Blockly.Lua.controls_flow_statements=function(a){switch(a.getFieldValue("FLOW")){case "BREAK":return"break\n";case "CONTINUE":return Blockly.Lua.CONTINUE_STATEMENT}throw"Unknown flow statement.";};Blockly.Lua.logic={};Blockly.Lua.controls_if=function(a){for(var b=0,c=Blockly.Lua.valueToCode(a,"IF"+b,Blockly.Lua.ORDER_NONE)||"false",d=Blockly.Lua.statementToCode(a,"DO"+b),e="if "+c+" then\n"+d,b=1;b<=a.elseifCount_;b++)c=Blockly.Lua.valueToCode(a,"IF"+b,Blockly.Lua.ORDER_NONE)||"false",d=Blockly.Lua.statementToCode(a,"DO"+b),e+=" elseif "+c+" then\n"+d;a.elseCount_&&(d=Blockly.Lua.statementToCode(a,"ELSE"),e+=" else\n"+d);return e+"end\n"}; -Blockly.Lua.logic_compare=function(a){var b={EQ:"==",NEQ:"~=",LT:"<",LTE:"<=",GT:">",GTE:">="}[a.getFieldValue("OP")],c=Blockly.Lua.valueToCode(a,"A",Blockly.Lua.ORDER_RELATIONAL)||"0";a=Blockly.Lua.valueToCode(a,"B",Blockly.Lua.ORDER_RELATIONAL)||"0";return[c+" "+b+" "+a,Blockly.Lua.ORDER_RELATIONAL]}; -Blockly.Lua.logic_operation=function(a){var b="AND"==a.getFieldValue("OP")?"and":"or",c="and"==b?Blockly.Lua.ORDER_AND:Blockly.Lua.ORDER_OR,d=Blockly.Lua.valueToCode(a,"A",c);a=Blockly.Lua.valueToCode(a,"B",c);if(d||a){var e="and"==b?"true":"false";d||(d=e);a||(a=e)}else a=d="false";return[d+" "+b+" "+a,c]};Blockly.Lua.logic_negate=function(a){return["not "+(Blockly.Lua.valueToCode(a,"BOOL",Blockly.Lua.ORDER_UNARY)||"true"),Blockly.Lua.ORDER_UNARY]}; -Blockly.Lua.logic_boolean=function(a){return["TRUE"==a.getFieldValue("BOOL")?"true":"false",Blockly.Lua.ORDER_ATOMIC]};Blockly.Lua.logic_null=function(a){return["nil",Blockly.Lua.ORDER_ATOMIC]};Blockly.Lua.logic_ternary=function(a){var b=Blockly.Lua.valueToCode(a,"IF",Blockly.Lua.ORDER_AND)||"false",c=Blockly.Lua.valueToCode(a,"THEN",Blockly.Lua.ORDER_AND)||"nil";a=Blockly.Lua.valueToCode(a,"ELSE",Blockly.Lua.ORDER_OR)||"nil";return[b+" and "+c+" or "+a,Blockly.Lua.ORDER_OR]}; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/media/1x1.gif b/backend/_pv_1_3_5/static/blockly/media/1x1.gif deleted file mode 100755 index 3085511236caea65b69ad30a68979c9b95f4a425..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43 qcmZ?wbhEHbWMp7uXkY+=|Ns9h{$$}~01D`U_#hbuCMF+725SJojRy(< diff --git a/backend/_pv_1_3_5/static/blockly/media/click.mp3 b/backend/_pv_1_3_5/static/blockly/media/click.mp3 deleted file mode 100755 index 4534b0ddca7424a441a5992f78d7defb7ea01834..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2304 zcmeZtF=l1}0!F_O&k!RZLl%ew@(T(w^U@W3GE)@t(|}Y#QesZ7LU2iDa&}0hYY5S_413-^&w3C0*Djhb23xn^V5J7*a`8)ASWpJ=BH$)Wu~SmB<7_k z6s6{7Rsh*al?v|p`RO^S3Z8k%djEe z|8W7JU6wwMzOKf4mKH^fXJM`pX;9&~;>5tv0CLC9h9lfCiIGA>B1ot=-=`$KfxBg% z!2xvxQN{%u1ZVItq(kKX|Nq&bz`W(yxy6|b2}}%!60c^lW>9qJNYT78cK7X1G`=?E8tc&Ve+j=v1Tvih0*@(UOg z)*t^hr9ta#q~@}-;m&2rD@0cDT)bT*!L`fq5ld(5;h8Pk2Y6UQCK#ON^K*&Q;bhss z9BrK3;2d=3SdT^1nUz-!lTNNk@Mmq?@6Ud%@A{J`(*oW^&e)mc81_B)Si14_drS7G zzq-2c_uuE{Khk^7tTS$rj-Ikr)v)XCym_1Z3znXKSJt+4_U@f=e}9{n-@o_q*!$1_ zEB<}`ef{>-}am~&Ni$6GlPLakVQmBho5g+#P@|YVu44#{>+Kski1s6Sk9!K zfj8soyG^C-EUk(PA#6;{Q6^WIn`c~D`^7+Hh82hGUKz=t+05gThWnaIbh@zJJ~KkT2if{=by{ zTQ@IoW{I(Pu>SSez~uDu?f?G|PglO@n5t)*8uVuWesE08RaG}_le~O;$&!upuPt3# z8=v`Re&nesyE{%Tj?H`UbN#;vFNOjJhOlWaokA)e6P3DTmN+f&5Mr6SvEXOSJm;zB zK{3S7d@XXazRmOo4h9AjU^KF=ZEbV+q!+WU9HsZvvK=+^CR?=u0PulcRlXv+U&QSpI=?S zCH&&rkF9I7s}8nGoo8jOQ&`u;r3EVh^^8^xAfUf1KrvLqe1L&*2{3~xKx1eCLtxZu H^bi05jng?> diff --git a/backend/_pv_1_3_5/static/blockly/media/click.ogg b/backend/_pv_1_3_5/static/blockly/media/click.ogg deleted file mode 100755 index e8ae42a6106dadbb6861981a696b7f8b8f64c9ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4865 zcmai13s_S}7QRu01OrA07;JQJkQ8nJB?w5^vgIL#1X3gS4T_I;7qX~&LkdY!roq9>%9EDy)D25XYk`Pxlv((8**}U z#o1|alvoJoq=LU(L2_mm9Gfpr$-seG>w~#rfncfM67Ukt;WA^nfwB3?l1y>FC>IQc zMzh&r?{Z@UV{>GZ6j1=YH9tQ$V9lCs+qSLF6-skt*+S{+97)<5Gr1<$tZ#FsShzVS z75tg>ZI+_?V0MmBoGKOx;pA)~ED>di-v_i{I~<;qla?uhnb|3;F^kM*A|au17zhh? zK#zj;MPt=G2qHkx78k^}HkFB}70qtj8x#>JrS~dtP?YOQDV21?uN~|obbufWsK^ah z)jGpWA7P}CT&pBa4Dq}E$6>3An0pM|UUfK=9WdBSh^3Q|5Q0U;mm%#95+KTK77P^uGokQ9MCKXd&>8ZzahK@t zJYwv9$Jd6%a@joa$dcjqkyK}B2>85OY zs&IPhz~*J8e+1TVnFE2Ok(+W-A*iJHtBT(Z!I=a6Yv$w;`wx+?9&(B7a$!$+T>H)^ z`l-*jeOQbSJJum-+(CBTQ55T!blq2UohOR|R`d6)D*0?0pyt%zTtz4-&eDsl~#rhAKv$f)QL&fp3irKO%xAJ;% zxl((fC3CQIzW4vO-!dm$;sP4ToG^*YYngM2P7Vdx)aAi`YPKoAo5T93;sexmRj|$F_D#%({#bDASwJxmR74-3 zUm;0Gm{*(DkI->P6ax%bb?pQb@vJAUMX2p|DGyYw6U?h^3Q}ankv6-OavfL%S%Kf; z=CNuAOb`)*1bB`$Qlj9DAT!mRLHa{7hs8LqiXCBKSI7tHmPd*Sh?*Qbg7lN+!@&<# z#bd#45CmVsfM1B4k1z}(xI*`GT}EqtB8k*U`>;`>Xv&^FRp)cf$2W${8?xt3a(QH3F_|s=jcu zF)OLzl_)mRB+8FB)#DqJ&x_%S61cpC0#U+qUc9j|5^!VLw;Xu99^S2IS-kqf`}w@2 zc+suryadNxiBl!_e<-|9LM2a4$^bXnC`vvjn|2c`#px|4v`ROvR-^67(st?+TjsPa z+QF_gZD+?|*Qt}8ne%|#c|zOeq1Aev?CN--^_cHDq3zWTcAakQJUQR<&Eh_f`QBV@ zXXnYTCn&d9H*d(B@AcZ*jtsS*eB7()?aiL=%^U8?BDZQEe@Yv=e0s3!oB7@~XJwQa zp6sq7=|McOBWv@vqlwQ;y0ZTIneN3P5HRsC#%K=t0$BD@_8VZ#@YMb7WdAC4niA|( zt83JrobSqZ@9UTkiQyF{)rqFpB_%A&o?cg#ICY>!`?!}j^eIq8|H6<%{@9D0bjJ@c zj&$i37p4q6$Bky(G331nc<_U)^%Nf0e-K~;gJQ#eFsPa0zM#k-16fjLiLnHl9?mCl z9>Z;1x+O*WE=x~VY+$8R6gOxFm|MjhP}SP8wjzoNj#aaI11qChVdP|-X}=-(2i)e! z5_>8p_~{zM4Swa)6oU6`n{b4QQ=df{K-6qgn{5b7-A0ULdBzO`Ah%8gM`+sYVwsw5 zAWGfl7|Ejd5EHZMMlx8@W|zoB48+(hPlIxm0S2P3qRLG=9yTa|sKdoIES9dWhBK_H zMMV`?v6x6t4J!)lip4rp!r^DqjVey2FW40jRl~~kH1HFnx@83ZV$-g4-EkS|Is;Hn zRg)rFXSy9TvgtF+Sz;ZkT%&hPtOCkoGkn{P=_n&HE6}KvvUJ89oCAQ7l67%Xx#OE( zEf=JF8jJ!Rs+@MFt_CQdxy`R+C?*6zR1K#RtVqnf&|aSo7)s9m?wQ-tOy3`F@HCpG*v^l>Od!G8h+ zXk_{p5CE(U{7{xozcHheqBaUTe5U}2yJwUcEWpUPb^(IESY!pAUie0spDPJR^AVbi zD1w0-E9s>~K?QwQ6^cdl4WPzpC!wVW_{gI5M`bpInXiiU2J`D{HT&ASP=X);J|LqNeAZzpheM;P>(Qg* z2A|~#WLr_yMov1=5`a~oy@9H_861JAjr{$dAmv!#RZ!_$$^ldKHw7K^wh0c%Pf|(; zNFaU&*m{O1(rpw}b_4%|6T&Fi?`z~QhVEtOLPZg$^GfU5KDs=9&lGD4D7HgP-bOD5 z91x2p6fKnXEPyH$BNRCZgLzC|{o5EJVAc#R0H|5>JjI3(6ST0+U<_FSK;~wmsDQ$m z3pf)P<#wQyQvk{4F@+t_VJhzw92AkjH7LUbRTG7ypzbnFrkK~FwIG1#Li7|~HRsYg z=$z?u|MJ2OTL)NB5gvl_Zl=#8#sOHblGjJdt0e@%>ZP0tM)(;~gp-~$si3Qgv7C%K zm7p>v`bY|k-q)dsW4RsLJ0a=lE*J*4Ulye}(Z z|4`ZVZ%wcniLe7ykR&P;Xa?3ye`rmfS;o8fNIphV@Yd>1J*zERk$4~57Gpga z<=6cB);VnYXJ`C7J-0We)Xha7T8y`ysj?3xx%%H^I3gFj%U+UniJ@KJCqCS5y>rni zlFjm)`(_I{MUkWvtD~$=xYzDuC9nF6h4|+M%XODn%|A6R!(={t4+r&aqtvTDTR6wt z(E0g6;iC!CUn5Q=F;lNCeU$BW|GOmSroE}z?jKvqe=MMt#x1$K^JVRVO9UB`AAH+?lzm%p z1{*OoyDC~2yvA{|wBY%m$HfoEr(eFDn~YrWN#O44%&c#(*VYUW8=}3SZR50+b&>qM zxcCR>eP4+5OETUHu=zUuse4@FjUC3L8u14ODJ0uU>gIE|zX`wiY2M#!by-+9-^KoO zeJ}QBQO_Ma+Ub;B>A9{pn|5Hj_BxTTyL(j`e$?g0&p8<2ox_Kd!;juM{mwD$hBLOe zpWo-*oe_@yVnOE*4^^(d)lrW|-?kAh+P0$SyGn*^ho|&;Rtx^% p7k4FIZ@TV#xbK&J-v%`HU5P#@S^9X{;VrAfeySU))r708{sTaExM%T7p^9ndf_EzHQ$3of#W9Y}f@)fC>4I3RdDtcslIgiiG%1X;f4SFXnB`9;I9I~b- zrOyo-my?z}N3M(>n_!iz#^ofOdL$jp?qnQ1dpf|4>)g67Yd zo3=>Kr!NkQ&CEjjXKl#}$p10a$V5G(8wK{$@Ms5jfg zCMe65Y!=5R8M|9{nFh1f@H+X0fT(NEuDtzh(?&i5>(uCyEx*a`2A+3pL=ew zJ;KpB)FYwl-`5+95B~h*a_z&Jrol5SE z-;;|EuE1x(hOgb1e_IE^OgtylbCY zHRnb2i_FR}+fJr>1^K76a(Sj2^0oKv2kc&&AKhjx@rw0f?kicf>yL)OnlGz^8~eG2 zQcp{r+coQU!8lQOvE6HY^eW1E5Br+j-A}tOu*9=pwSzXlrnKh2oXHq(EVX{` zcEdcJUE&>G>m1WvLjRr&R92fzrWfo4&eEMm1o@yqaN){Q6##71+Ch)r6M;odo>7B(Sh^KSdF7}Ad zC2b)MCt@-N;5Na;dwi+x(!SMKidoQuzF^tP0OM^X(ojRjpk3dr4bn=qX?!3ag9&6a z`HGAow_yN0!3G=wV<8;Ma2<9*1J;Ws@mTmtyBB#z+R~rNDDnXeMn$yZEA(W2vp$il zq7$j3UmH|qq;Z7eqE;Bj!?Z{>MV+OodNMAj;YzOYnsSUaLO=0X>#Ca7f%*;ngT7

    ~Kv18<{tYx#Fqpj22d0W|!J;axGqUq#0ju4-7Dk3onMvxkUB#{h-^Wq$Law|@T zTjT~s$)xQh1`32P|6H%s-{y2? z_zgDUY5W{1L_!tr!|j-cFGYb^B7T)S4#5+$lYUEIkaO@co)BZjFmXa;;#?R{@<|!k z(I2OaFmY7WVH%l7f1?Ewy@#=zn8%m$5HVJs*ll`@g|nrkBYN_y+6HZr?khsTm-b+N z*<17=grh|aF{vBq}uRHE|4vv3C@q1S-IW zz(q7lE@gZ=Cb}_ivVOk6sB0&$=iZvUr zfOK}x;4sv%U1YD&w0yNptx*O+O++NDtP^aEmRb@jykc?xh#&UBn$6MB?Z+%IF1{jzh&xewMElNAM{;Cb@Ja zEh4Ao+3&`AScG9P3;MuKoPb@i6~2v+Fb^JsfwUuCNqbTXn_(hkLjlZ%1{{jdM3tC= ze_{x%g6pscJfJH^i4s0Zyos&gZ@5Sn(oMAdpWP6KE5t&HxVu;igdUalOJp`wix>Pj zZ!J7A7p(Lxmd9RWA=E^CAqH2AY2u=oj5o0Z^acwY#HkpI^YNHO=R`OG=OG?;V7SaQ z0XJedh#)QKWLifCla=s`#6^in!fo(18A6xQN%RcaC)L5hyYpz?z@1_cY#|HiT56;n zNEdihYSS9whR<;`G(j1hg++i86#=M=R=5z$a0nDbAF_d5AU}~j(vo~6kytEOjF;s>G4Z4zHB$AZF3aG{5cv2*Z@#2m+j76}YMADvgCpiU6aiB=%akA#s_&S+J|EBxt zJ#ts}KTq7}ErdUwgIL;zxv|;wJ<=cIFkd3MS(M0H9MD}>w+-SkSS;lmc@L2&QJh4- zV1KbT>L_(u27`{*l-j0l8I!zL`qj!jRP^c36+(IVK>r?eQJwlY>C*&l3joqSuO5a^DRfLOl;fn$#^QEG!CUx+Z zRJ@xaTTBtXL{BkND%pGJC(%VncX^|PlJ})r4#knU8Vj)sBVj9?gY^>WQJ5r(`A%NV zFNj(UBtbO4X?WAt=1SWwJGURPZ?&Ja?{Q30?c!af$}P?N8y`RKjUL%FY+jdf>6iFU-b(BWZMZ8II+)C%5-x*G>roK}NdiRF$dR#`+p!ce|n z>#eEUSG>Dq9-;9p$?&#PqI{-g84~GAJf`?QN+xa9Gse_&oB3VU_Wg@wn2J z-NPsPZZ*o4=z6J+=SSc-!&LJR)&*{Zt-a*?KLFFT66az^f@81q4J}zT5sOk`++zwf zX@;{TR9sS{oZTGZjv!}ywO(%vomif7z<5r+WzMo}vI2cYF2BN0i&6|GGwE1%i*060 zs0TTXlSHFlqlIZ)&DYlGcX% diff --git a/backend/_pv_1_3_5/static/blockly/media/delete.mp3 b/backend/_pv_1_3_5/static/blockly/media/delete.mp3 deleted file mode 100755 index 442bd9c1f4c9cee39ca9cc776c7cd594c90f2795..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3123 zcmeHJXH*m07M>&!dX=iEktT2fsh48B1PId6#Ly%{0to>Gg7l^YAtC|_JX+`=MMRMz z%|=4KfCcqIM5>~Qpi&e;ROW`Ku5}mx?vMBDy>G33W`Ad9&EEU$Z_XTRv@Q(b0CEUt zjnm;cq8u|14hsnK_YI^Vf`~!nV4SN3mNU!EF&!;!Z5$eF{&#xRLYqT*Id&|R9OOd` zG(Tc*&tbkC+rlwwSg;q_7~vBd8f1LnKtx1@W)LZa8WukCkYH%o-gs`WQe7$`+4l$5~2qp*kMsj@5D1;@IO7SNntOLC?!LRAvKcf9@ zv<~#9a;ON$-~b@t52$T}<95)t;p%n_ZwI&yoLEM7ruG)Pnns4fkO#lAk)SE^SeXF; zZ7UCz7B9tLH~v?yKN=(v=Ao(A3&8&P?V5oB77DOCAk1_{K7L_V>G{%k=1@Xx3l8dO zEQ;Xh5RJBl0zvil(`Yg2v9WKO`FktsM0UE{FSY4QEWT_XQxf{Lu#@iE>PKaz6z^1S#Kk6E| zG-kc6w!8meF>Y{bCCjCuXMue~ilz2C!X4IBS^mk%roZYV3EJ%*WEKJ4CXdY$UQ4Z)#EROyxblolH`S9mE z2QJKK*G*4-eWTyn(ffXymH0Jo*N+cx#lj%oWXLh=832^!1zpK5Gt?{Zu6~>g=Qj~g z;kv01&+284q4hmg6M7n=LU-_69`#Y6$IHWWue=~!%*zSP3s;u%z(unHZ6oA6>5wpA z0tUusc++ve)J0)^ot6*o<=*A4(6PhKg-GAljOBMKHQ4gC4?a(i7x@ucDN0>VX$46b zs_@PuxW{RY&!YHs-HH!6&(>VsY>jx?(Z1VQ#7!ci>cbIby!@Yaoay>{p&^lq}H#A~FK*Wpum_g(k9vo6T>j89*1Bax3k zbT?{hF?OPO2hY7UaB)<*`XH)mlCdl$c?$Zt#HhLHK)t*(Z)~hqV@I<0$hhCi6GisK zQqs=-E2aO0K*XV4AY z!)OJaCpY7M?urlK8Q0=@t2Y=qzcT^2a?j1DdZgooQGn>Jm3&*B3!-+(yl*41&FJb8 z%B8%lrQDQp^lfz);i~u6+0hrQ!-U4_E0AzUwT{P@C(xp^>g7$30wuI5Qm zHXns9?$9qO{c4Bl;se?U9=>zj5DZg2HdRcIS8=3SR_2nB?){D;FR_fg79G`}9cu4GN#xS_ z*Spjxg7uKy;zd=iJ1eai0tw$HESr@aaK;1VibBOdNH)79IuxFx*KgTjnc=sowdyWO zdL--2d_Pskq{g}N^Uu2^dq0TCWobt zdDo-+Bj7i)?x%kFm6xe+bkX}ZV63vAeH)8yy)9Sn`RKCQbD{H7^;pMaDv&aNv z+Z91w$7vqa(F7jXR5tS9Y%^%s3Iy|29127mmMeD7muocCUcW=X!}xolGP$F6HYPB4VL7_aI(MCd}qs6aUj^1?Gh@W3yLA@0ZwTW z)*=GR(#7yAd~pe<;oqly+u}=$xo>X5oPm`PV=M0;7|ng5ziXP)deG<5Gq{P zV8SlyRFD}Ba3lEn<>S3fCj@-K^~4@gX;D=``xW47B?H~p0+@o}Hz+)QUzwNroMxnk z)lGVO8nn%?1O%Cir7lCA5P6!OmOHWbu%2aEd}63QJr{mofy&9TTS;2wVmyFx{B`Eh m)Y*Qf`iFe0Ly8GZ08$|b00;okqjC1dfB267KmOlbfxiHkb?GSp diff --git a/backend/_pv_1_3_5/static/blockly/media/delete.ogg b/backend/_pv_1_3_5/static/blockly/media/delete.ogg deleted file mode 100755 index 67f84ac19a05075a52de49829b3a2bc17af9e29c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5731 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 diff --git a/backend/_pv_1_3_5/static/blockly/media/delete.wav b/backend/_pv_1_3_5/static/blockly/media/delete.wav deleted file mode 100755 index 18debcf96d6f76e36f295feb6de2f09dffaec1f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9164 zcmXAu2Yip$_s7qDzDa}-Dr%Jc>{XkXr6@AY+M`sB5G#loTWQP)MXjn$P^v{yVr#9^ z+N<`agpf$`eeU_c_5bRtvcAuK?mg#oKA+Dyw@pN7=+WXL9UFFN(r3`{BDqAw@L%H} zMW%N$;z%xO9?`a4BEOGl8QLnMWy2QlKhr2?#GoMq`$hLHGNi|l$QX%e*ruI7zi&G{ za!6EX zIe74Z?*FaCzkMTzb?-53*x;Dqk-dww7~H#GpMHGPBf58yn8-o>M)Q5o*dk$r2lpKq zStKI5S4DQ#s7+%(-d448l`0~=dkpW9Tuh{>Jk==s!uFI);v+-#qW&OvYgSyeKvfpSiNzigSQ0M7e{Yr*QV;L-YOb2tp95aXHv^Lgknr@%!TS*lw z*QBk~kf}0K{wJSGQPbP`)A4ckn_f;a&l}G`pPQZ!JTuJ;ov7BXaED|jW{mcJ@~P**n7iD4&>l^4i4v4E2rl+2d*CRFKE&wH@8Z-binV_pG<4+t8NL4jQ9DQpp54 zo6Iz+Wwtw)ozNTz2U%T3Qn1dkHtS zq?s*YE9*^ZWq#H{BdMr~uGkYc!8WuN?R`5{HW`o8*IDH>acYo@w7d(Tdn7ADmkH_OaX zGt%sl-V$W0nY8Yr9bfWARQ!Qq@nrFERaK5T4(96GTd}AyCj+%?6kk= z6Md$;^m83AwVjd1N2}Q{^tfD?cbceob*}hJG3}>6Ykx8)a+UXfVID}PmN2!PeUgnc z6_9Z02)=JvuidGiXq5Jpn>tvtkc}{1poOKB+yEJQrJMP{SeU0Uft3kR|m-$TU z6T_ieU2;oR>7?E4HG4pxNupfUe7x(n{I2nuF1<`ka~7QKkqIC#FFPA;3YqJ=&34jo zlW0z`pCOt_L`txuS$f8PrDvo#NZux;rMW)U?J`cfa;ioWDq%882ieV3X*E+@M91)s zmHM{~6xYV+J&88|>O?zC|BwZ;fxo?w2y;YcOI~RpIb}2TAEG<;kk*zeri}cif9ra( z^&7FQDAOf7Yd*J++$y$<+$CdKar(`=G0WazepI47Mz&jO#e zeg)pSPs1}x_(f>e)C(yGeRg~h?OQqRSw^(~S6N%AefLS`K2I;tK0V|4!E8?}oH|pp zd1~98Qp0zK^FQL6!&6u;xy^K-xo>8g+S=AT-u+E-m<;>MK9GabTKC!#`i{6pNqf`P z6ftq2X_F>M4>Q%glBJph45hdS>?~cZr|cR%4wto&6=tDnAiH(Bd?!_;EN7es&&`#7 zri$4BgKX05ve=Y0t#q;twta1V-jH2x>r3;k$8l!rY5OaYnr|cB!aB}uGds1s_F

  • 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 R6c)kuZMgU8%=~+f{2#xTwtoNs diff --git a/backend/_pv_1_3_5/static/blockly/media/disconnect.mp3 b/backend/_pv_1_3_5/static/blockly/media/disconnect.mp3 deleted file mode 100755 index 8cfaff6c06253a8b9bbe50dc0d5d05c4a25b6fb5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1586 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 diff --git a/backend/_pv_1_3_5/static/blockly/media/disconnect.wav b/backend/_pv_1_3_5/static/blockly/media/disconnect.wav deleted file mode 100755 index af5c25447cad1a7ebd705e0f28ffbc4ebec01f49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1492 zcmcgse@v8R9Djbiciaz^Ls1l@Ugwr2@*^}OGz~%I%0mZ-QkeuC2WQ9K0Y~UYx-47F z)a7)e;WE=P*TBL;@<+^7&eSBAzbaP~Jp?=m9rug(eV^y)IZjqvTYvVv`@Y}L_vh#P zJbT`^z?hr+qY8laS?g9>tKFgj008-u(+0r%#SkE10G3jBX{^8l;|l`D!a0onTPVYT zjz`0Yj0@sb5eq%430ME^iCE#-BZ5a!g$cYvq&iah&z=$Xi8(0Go0ux%n|SX7C&5lI z1!S^vdX^j{_sLm0#1i2gv|}`Hbic39e>I>4+5-Cmoq=NAm z757*5CG~X=Y#yd*dUkOB!04bbG7y*ptMvU-d*g)o z!*Q2mzS1Uuxxu#{T=!<*Upp*}PL;ag*HIUB8G1$YxZt2Kj_vVx_!yUOFg$qe#jha@$x#a7rNLuL`C~edGzGQDJ zRU_KN(#R1xLssM#vWV>l80F&%Ay;)rwO>^ul%Ym;TuGPC1qb|zeybk^)zT&6ga?G} z>K=86Y5~5=?kESO7sfV>d8I<~1^7;|YT9($^qIP)QOogcW|eP;wgiiUheJv7Myfz2 zJXE(tiBV(18JJAZNlQb?!SrBaXpS_j#DjTwi>h6HQr)HM#t!%{GtdTdo}8k+Y(6YU zX554K;?2kaJK3xBfif(o$g=mx9@%UCg$$znP}Z?ij~6^7tvkbrhpLYI>LN{doRHqqlu1AVXr?L-a~hdzSS z;Z}aT%h)j*P0x{5a)s2;Z4AR^^d(mC+c*Q|gH&o)n&ci?Anmjn%tLwjV?2ts!y(p5 zLqtn2(W@*LO0X66pbtfY)IQ>;>Iy84W0v%08u@{7HWWJJIJ@E1bYyKDmz_ zrFY3`VxX7lT}Hqle2=pip__04KZ|~5;S9O-8tEoU)K9->UEmm8Z7ejO;vcRtKX;8W zKg;wO$7`J~m(5WruC`f3rArgZy5QX7CK}5#YAc(B&4cephDBOgraFhrH5{cWsZDtreZ06gynH32{0;NO} z9j^cn;3-8u5_G)Ae{U_GW-~k8u8*mL%Q9^6c6*bRZdjrJa+LmXTW#6QRhg67=(=WB LR`K-RGPP%aOVoiS diff --git a/backend/_pv_1_3_5/static/blockly/media/handdelete.cur b/backend/_pv_1_3_5/static/blockly/media/handdelete.cur deleted file mode 100755 index 170320fc281ab02ded109f0310aa180b77e465f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 766 zcmeHFF%AMD5F9v?Yp*cIl58w|z?Bw6?qT>6zj9Bx!ot!YtV7NVgxDBcCk(s8u)7HX zurTm`K#vX&3+w@$NKXdRz;P$&Z5XzMF{K1mWu^!r$3MP#feGL$h{26T0d9<;Xe$zH zyVWAc`hK=AyHX$`lT`DlMSN-BYBYYUZ7#3struI#()e@6fAbs8EI*J})n~VIF{(3v TWO5|WGG}sm$GKO%-`24&Q~QG0 diff --git a/backend/_pv_1_3_5/static/blockly/media/handopen.cur b/backend/_pv_1_3_5/static/blockly/media/handopen.cur deleted file mode 100755 index da44588b2fa68ee115deb843e1ce6802e58b3e30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 198 zcmaLQu?>Sj429wUKWFU8GbZ8()Nlj27Z*CxAAWdOomE>Pr0007eNkl3__@j4bYHCE1~!w_VN8vPIvx-hJST0~G5wg{n(i=dS&7X?8-)S@6-v^1h1 zD56b}B*FwX3xxv9D6pUg4HBZVKjCdLbMKsU=ANGxy{mi9eR%oK_nq&Y16afqukkW{ zIEhO*#QUtXgZns3lHBQJ+rep)SGXn)T+incR$#j!1sNrXDR#z#8_RVKb&|FJ zV0)fRQ&?+`M%>?I3hK2B3?iXzS$QxWZLAHZkKSz>O( zx=JpPu&!}?$=G*5qlht&87sZAWcCyz%Dn a|MeGMMynZGn?~jU0000_G{ diff --git a/backend/_pv_1_3_5/static/blockly/media/quote1.png b/backend/_pv_1_3_5/static/blockly/media/quote1.png deleted file mode 100755 index 826583e0ad72dd1424a2ffe9e21a8b653b596058..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 738 zcmV<80v-K{P)hppyUq0&_`3K~zY` zwU*CIR8bVizi%)dr%W2FnSNk}mX$CPQd80l=@=9tO1LP9gf>Aze?W_ZAd3nT+6Pk9 zB8q4gJZRIxeo$192pP3d(M`3B=|$fbGxNOndG9^1MQ3#neBSq+d(J)QUf@5Or#j4F zE9wy-zzpWS-|kPDMh6-ZAix6Vys`~za&kJm|imv7ub-TtLCa_4e4I5=UIc=oR zMZp~HHelG>w3R-sf=NDc2!CO_CY#_mUAB7>EzoVZHQ_FSe#`~{NC3zSC#Rbm6>q&j z@5Sbta9Kce=vKUpKxc5ECM?@Y)`jaPksjiTxWXwc3)c%Gy#>t`;U6*3bhw@s=`#LQ zgx|zK7hC@;CdDkb013dG#HfHafZ=eN#h56ZuI2a!d?)%Hf#Ti4gV;lk^&D{=`uAKH z>As_!bMQrNY%+xcO4tP87l0Fr(gz&zW+I^^kw+i4SLqVeU+?i=+xKuriC~HwgdGn= z_h&iBtV2O@KjE8@OLZ0puFhMItm66JPiMSI>{r}(jwa$xtr%TGBJ>G;*cI`RvVMxs zLL&On7Or35l|6!X?J)HV@n-o}p+{V2`o01_tPF04@MVR5#+7#Pn08lp2(l%u8a;OK zp!ISz(Yv&yU9p3`nyiop<}_K~ng$MQvd`J#lr2W)iTQcM6h}31f?4O#I;+uB+-3%Q z`0*cPJNYsaZJP;O!<&(@=W~@+w3!zp^n`Il@%WNyddXfg_AZ&jjk(TlN%G=_dLieUI)}5eKVv-52W;%U3({kc=kzi09cD^L9+|y1X;sFF|f& UTm9BGZ2$lO07*qoM6N<$g0UG+&Hw-a diff --git a/backend/_pv_1_3_5/static/blockly/media/sprites.png b/backend/_pv_1_3_5/static/blockly/media/sprites.png deleted file mode 100755 index 7f704a5f1ff6b99c6877e40d4d87729bd58bf42f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4146 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 diff --git a/backend/_pv_1_3_5/static/blockly/media/sprites.svg b/backend/_pv_1_3_5/static/blockly/media/sprites.svg deleted file mode 100755 index 3f09ef3a4..000000000 --- a/backend/_pv_1_3_5/static/blockly/media/sprites.svg +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/ar.js b/backend/_pv_1_3_5/static/blockly/msg/js/ar.js deleted file mode 100755 index 5284faf3e..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/ar.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.ar'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "اضافة تعليق"; -Blockly.Msg.CHANGE_VALUE_TITLE = "تغيير قيمة:"; -Blockly.Msg.CLEAN_UP = "Clean up Blocks"; // untranslated -Blockly.Msg.COLLAPSE_ALL = "إخفاء القطع"; -Blockly.Msg.COLLAPSE_BLOCK = "إخفاء القطعة"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "اللون 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "اللون 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "نسبة"; -Blockly.Msg.COLOUR_BLEND_TITLE = "دمج"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "دمج لونين ببعضهما البعض بنسبة (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://ar.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "اختر لون من اللوحة."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "لون عشوائي"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "اختر لون بشكل عشوائي."; -Blockly.Msg.COLOUR_RGB_BLUE = "أزرق"; -Blockly.Msg.COLOUR_RGB_GREEN = "أخضر"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "أحمر"; -Blockly.Msg.COLOUR_RGB_TITLE = "لون مع"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "إنشئ لون بالكمية المحددة من الأحمر, الأخضر والأزرق. بحيث يجب تكون كافة القيم بين 0 و 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "اخرج من الحلقة"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "استمر ابتداءا من التكرار التالي من الحلقة"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "اخرج من الحلقة الحالية."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "تخط ما تبقى من هذه الحلقة، واستمر ابتداءا من التكرار التالي."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "تحذير: يمكن استخدام هذه القطعة فقط داخل حلقة."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "لكل عنصر %1 في قائمة %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "لكل عنصر في قائمة ما، عين المتغير '%1' لهذا الغنصر، ومن ثم نفذ بعض الأوامر."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "عد بـ %1 من %2 إلى %3 بمعدل %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "اجعل المتغير %1 يأخذ القيم من رقم البداية الى رقم النهاية، قم بالعد داخل المجال المحدد، وطبق أوامر القطع المحددة."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "إضف شرطا إلى القطعة الشرطية \"إذا\"."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "أضف شرط \"نهاية، إجمع\" إلى القطعة الشرطية \"إذا\"."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "أضف, إزل, أو أعد ترتيب المقاطع لإعادة تكوين القطعة الشرطية \"إذا\"."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "والا"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "وإﻻ إذا"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "إذا"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "إذا كانت قيمة ما تساوي صحيح, إذن قم بتنفيذ أمر ما."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "إذا كانت قيمة ما تساوي \"صحيح\"، إذن قم بتنفيذ أول قطعة من الأوامر. والا ،قم بتنفيذ القطعة الثانية من الأوامر."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "إذا كانت القيمة الأولى تساوي \"صحيح\", إذن قم بتنفيذ القطعة الأولى من الأوامر. والا, إذا كانت القيمة الثانية تساوي \"صحيح\", قم بتنفيذ القطعة الثانية من الأوامر."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "إذا كانت القيمة الأولى تساوي \"صحيح\", إذن قم بتنفيذ القطعة الأولى من الأوامر. والا , إذا كانت القيمة الثانية تساوي \"صحيح\", قم بتنفيذ القطعة الثانية من الأوامر. إذا لم تكن هناك أي قيمة تساوي صحيح, قم بتنفيذ آخر قطعة من الأوامر."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "نفّذ"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "كرر %1 مرات"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "نفّذ بعض الأوامر عدة مرات."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "اكرّر حتى"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "اكرّر طالما"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "بما ان القيمة خاطئة, نفّذ بعض الأوامر."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "بما ان القيمة صحيحة, نفّذ بعض الأوامر."; -Blockly.Msg.DELETE_ALL_BLOCKS = "حذف كل مناعات %1؟"; -Blockly.Msg.DELETE_BLOCK = "إحذف القطعة"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "إحذف قطع %1"; -Blockly.Msg.DISABLE_BLOCK = "عطّل القطعة"; -Blockly.Msg.DUPLICATE_BLOCK = "ادمج"; -Blockly.Msg.ENABLE_BLOCK = "أعد تفعيل القطعة"; -Blockly.Msg.EXPAND_ALL = "وسٌّع القطع"; -Blockly.Msg.EXPAND_BLOCK = "وسٌّع القطعة"; -Blockly.Msg.EXTERNAL_INPUTS = "ادخال خارجي"; -Blockly.Msg.HELP = "مساعدة"; -Blockly.Msg.INLINE_INPUTS = "ادخال خطي"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "إنشئ قائمة فارغة"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "تقوم بإرجاع قائمة، طولها 0, لا تحتوي على أية سجلات البيانات"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "قائمة"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "أضف, إزل, أو أعد ترتيب المقاطع لإعادة تكوين القطعة قائمة القطع التالية."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "أتشئ قائمة مع"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "أضف عنصرا إلى القائمة."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "أنشيء قائمة من أي عدد من العناصر."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "أول"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# من نهاية"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "احصل على"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "احصل على و ازل"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "أخير"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "عشوائي"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "ازل"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "يرجع العنصر الأول في قائمة ما."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "يقوم بإرجاع العنصر في الموضع المحدد في قائمة ما."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "يرجع العنصر الأخير في قائمة ما."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "يرجع عنصرا عشوائيا في قائمة."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "يزيل ويرجع العنصر الأول في قائمة."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "يزيل ويقوم بإرجاع العنصر في الموضع المحدد في قائمة ما."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "يزيل ويرجع العنصر الأخير في قائمة ما."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "يزيل و يرجع عنصرا عشوائيا في قائمة ما."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "يزيل العنصر الأول في قائمة ما."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "يزيل العنصر الموجود في الموضع المحدد في قائمة ما."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "يزيل العنصر الأخير في قائمة ما."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "يزيل عنصرا عشوائيا في قائمة ما."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "إلى # من نهاية"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "إلى #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "إلى الأخير"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "احصل على قائمة فرعية من الأول"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "احصل على قائمة فرعية من # من نهاية"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "احصل على قائمة فرعية من #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "يقوم بإنشاء نسخة من الجزء المحدد من قائمة ما."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 هو العنصر الأخير."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 هو العنصر الأول."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "ابحث على على التواجد الأول للعنصر"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "ابحث على التواجد الأخير للعنصر"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "تقوم بإرجاع مؤشر التواجد الأول/الأخير في القائمة. تقوم بإرجاع %1 إذا لم يتم العثور على النص."; -Blockly.Msg.LISTS_INLIST = "في قائمة"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 فارغ"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "يرجع \"صحيح\" إذا كانت القائمة فارغة."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "الطول من %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "تقوم بإرجاع طول قائمة."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "إنشئ قائمة مع العنصر %1 %2 مرات"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "انشئ قائمة تتألف من القيمة المعطاة متكررة لعدد محدد من المرات."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "مثل"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "أدخل في"; -Blockly.Msg.LISTS_SET_INDEX_SET = "تعيين"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "يقوم بإدراج هذا العنصر في بداية قائمة."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "يقوم بإدخال العنصر في الموضع المحدد في قائمة ما."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "ألصق هذا العنصر بنهاية قائمة."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "ادخل العنصر عشوائياً في القائمة."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "يحدد العنصر الأول في قائمة."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "يحدد العنصر في الموضع المحدد في قائمة ما."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "يحدد العنصر الأخير في قائمة."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "يحدد عنصرا عشوائيا في قائمة."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "إعداد قائمة من النصوص"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "إعداد نص من القائمة"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "خاطئ"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "يرجع صحيح أو خاطئ."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "صحيح"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "يرجع صحيح إذا كان كلا المدخلات مساوية بعضها البعض."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "يرجع صحيح إذا كان الإدخال الأول أكبر من الإدخال الثاني."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "يرجع صحيح إذا كان الإدخال الأول أكبر من أو يساوي الإدخال الثاني."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "يرجع صحيح إذا كان الإدخال الأول أصغر من الإدخال الثاني."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "يرجع صحيح إذا كان الإدخال الأول أصغر من أو يساوي الإدخال الثاني."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "يرجع صحيح إذا كانت كلا المدخلات غير مساوية لبعضها البعض."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "ليس من %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "يرجع صحيح إذا كان الإدخال خاطئ . يرجع خاطئ إذا كان الإدخال صحيح."; -Blockly.Msg.LOGIC_NULL = "ملغى"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "ترجع ملغى."; -Blockly.Msg.LOGIC_OPERATION_AND = "و"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "أو"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "ترجع صحيح إذا كان كلا المٌدخلات صحيح."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "ترجع صحيح إذا كان واحد على الأقل من المدخلات صحيح."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "اختبار"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "إذا كانت العبارة خاطئة"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "إذا كانت العبارة صحيحة"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "تحقق الشرط في 'الاختبار'. إذا كان الشرط صحيح، يقوم بإرجاع قيمة 'اذا كانت العبارة صحيحة'؛ خلاف ذلك يرجع قيمة 'اذا كانت العبارة خاطئة'."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Arithmetic"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "يرجع مجموع الرقمين."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "يرجع حاصل قسمة الرقمين."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "يرجع الفرق بين الرقمين."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "يرجع حاصل ضرب الرقمين."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "يرجع الرقم الأول مرفوع إلى تربيع الرقم الثاني."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "غير %1 بـ %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "إضف رقم إلى متغير '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "ير جع واحد من الثوابت الشائعة : π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "تقيد %1 منخفض %2 مرتفع %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "تقييد العددليكون بين الحدود المحددة (ضمناً)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "قابل للقسمة"; -Blockly.Msg.MATH_IS_EVEN = "هو زوجي"; -Blockly.Msg.MATH_IS_NEGATIVE = "هو سالب"; -Blockly.Msg.MATH_IS_ODD = "هو فرذي"; -Blockly.Msg.MATH_IS_POSITIVE = "هو موجب"; -Blockly.Msg.MATH_IS_PRIME = "هو أولي"; -Blockly.Msg.MATH_IS_TOOLTIP = "تحقق إذا كان عدد ما زوجيا، فرذيا, أوليا، صحيحا،موجبا أو سالبا، أو إذا كان قابلا للقسمة على عدد معين. يرجع صحيح أو خاطئ."; -Blockly.Msg.MATH_IS_WHOLE = "هو صحيح"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "باقي %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "يرجع الباقي من قسمة الرقمين."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "عدد ما."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "متوسط القائمة"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "الحد الأقصى لقائمة"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "متوسط القائمة"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "الحد الأدنى من قائمة"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "منوال القائمة"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "عنصر عشوائي من القائمة"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "الانحراف المعياري للقائمة"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "مجموع القائمة"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "يرجع المعدل (الوسط الحسابي) للقيم الرقمية في القائمة."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "يرجع أكبر عدد في القائمة."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "يرجع وسيط العدد في القائمة."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "يرجع أصغر رقم في القائمة."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "يرجع قائمة من العنصر أو العناصر الأكثر شيوعاً في القائمة."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "يرجع عنصر عشوائي من القائمة."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "يرجع الانحراف المعياري للقائمة."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "يرجع مجموع كافة الأرقام الموجودة في القائمة."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "كسر عشوائي"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "يرجع جزء عشوائي بين 0.0 (ضمنياً) و 1.0 (خارجيا)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = " عدد صحيح عشوائي من %1 إلى %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "يرجع عدد صحيح عشوائي بين حدين محددين, ضمنيا."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "تقريب"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "تقريب إلى اصغر عدد صحيح"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "تقريب الى اكبر عدد صحيح"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "تقريب الى اكبر عدد صحيح أو الى اصغر عدد صحيح."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "مطلق"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "الجذر التربيعي"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "يرجع القيمة المطلقة لرقم."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "يرجع e الذي هو الاس المرفوع للرقم."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "يرجع اللوغاريتم الطبيعي لرقم."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "يرجع لوغاريتم عدد معين للاساس 10."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "يرجع عدد سالب."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "يرجع مضروب الرقم 10 في نفسه ."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "يرجع الجذر التربيعي للرقم."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "acos"; -Blockly.Msg.MATH_TRIG_ASIN = "asin"; -Blockly.Msg.MATH_TRIG_ATAN = "atan"; -Blockly.Msg.MATH_TRIG_COS = "جيب تمام"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "جيب"; -Blockly.Msg.MATH_TRIG_TAN = "ظل"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "يرجع قوس جيب التمام لرقم."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "يرجع قوس الجيب للرقم."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "يرجع قوس الظل للرقم."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "يرجع جيب التمام لدرجة (لا زواية نصف قطرية)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "يرجع جيب التمام لدرجة (لا زواية نصف قطرية)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "يرجع الظل لدرجة (لا دائرة نصف قطرية)."; -Blockly.Msg.NEW_VARIABLE = "متغير جديد..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "اسم المتغير الجديد:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "allow statements"; // untranslated -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "مع:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "تشغيل الدالة المعرفة من قبل المستخدم '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "تشغيل الدالة المعرفة من قبل المستخدم %1 واستخدام مخرجاتها."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "مع:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "إنشئ '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "القيام بشيء ما"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "إلى"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "انشئ دالة بدون مخرجات ."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "يرجع"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "انشئ دالة مع المخرجات."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "تحذير: هذه الدالة تحتوي على معلمات مكررة."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "تسليط الضوء على تعريف الدالة"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "إذا كانت القيمة صحيحة ، اذان قم بارجاع القيمة الثانية."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "تحذير:هذه القطعة تستخدم فقط داخل تعريف دالة."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "اسم الإدخال:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Add an input to the function."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "المدخلات"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Add, remove, or reorder inputs to this function."; // untranslated -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "ازل التعليق"; -Blockly.Msg.RENAME_VARIABLE = "إعادة تسمية المتغير..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "إعادة تسمية كافة المتغيرات '%1' إلى:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "إلصق نص"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "إلى"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "إلصق جزءا من النص إلى متغير '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "الى حروف صغيرة"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "الى حروف العنوان"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "الى حروف كبيرة"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "يرجع نسخة من النص في حالة مختلفة."; -Blockly.Msg.TEXT_CHARAT_FIRST = "احصل على الحرف الأول"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "الحصول على الحرف # من نهاية"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "الحصول على الحرف #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "في النص"; -Blockly.Msg.TEXT_CHARAT_LAST = "احصل على آخر حرف"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "الحصول على حرف عشوائي"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "يرجع حرف ما في الموضع المحدد."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "إضف عنصر إلى النص."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "الانضمام إلى"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "أضف, إحذف, أو أعد ترتيب المقاطع لإعادة تكوين النص من القطع التالية."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "إلى حرف # من نهاية"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "إلى حرف #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "إلى آخر حرف"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "في النص"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "الحصول على سلسلة فرعية من الحرف الأول"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "الحصول على سلسلة حروف فرعية من الحرف # من نهاية"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "الحصول على سلسلة حروف فرعية من الحرف #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "يرجع جزء معين من النص."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "في النص"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "ابحث عن التواجد الأول للنص"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "ابحث عن التواجد الأخير للنص"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "تقوم بإرجاع مؤشر التواجد الأول/الأخير للنص الأول في النص الثاني. تقوم بإرجاع %1 إذا لم يتم العثور على النص."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 فارغ"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "يرجع \"صحيح\" إذا كان النص المقدم فارغ."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "انشئ نص مع"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "أنشئ جزء من النص بالصاق أي عدد من العناصر ببعضها البعض."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "طول %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "تقوم بإرجاع عدد الاحرف (بما في ذلك الفراغات) في النص المقدم."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "اطبع %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "اطبع النص المحدد أو العدد أو قيمة أخرى."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "انتظر ادخال المستخذم لرقم ما."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "انتظر ادخال المستخدم لنص ما."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "انتظر ادخال المستخدم لرقم ما مع اظهار رسالة"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "انتظر ادخال المستخدم لنص ما مع اظهار رسالة"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "حرف أو كلمة أو سطر من النص."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "إزالة الفراغات من كلا الجانبين"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "إزالة الفراغات من الجانب الأيسر من"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "إزالة الفراغات من الجانب الأيمن من"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "يرجع نسخة من النص مع حذف من أحد أو كلا الفراغات من أطرافه."; -Blockly.Msg.TODAY = "اليوم"; -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "البند"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "انشئ 'التعيين %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "يرجع قيمة هذا المتغير."; -Blockly.Msg.VARIABLES_SET = "تعيين %1 إلى %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "انشئ 'احصل على %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "تعيين هذا المتغير لتكون مساوية للقيمة المدخلة."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "المتغير '%1' موجود بالفعل"; -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/az.js b/backend/_pv_1_3_5/static/blockly/msg/js/az.js deleted file mode 100755 index 243e7e676..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/az.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.az'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Şərh əlavə et"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Qiyməti dəyiş:"; -Blockly.Msg.CLEAN_UP = "Blokları təmizlə"; -Blockly.Msg.COLLAPSE_ALL = "Blokları yığ"; -Blockly.Msg.COLLAPSE_BLOCK = "Bloku yığ"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "rəng 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "rəng 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "nisbət"; -Blockly.Msg.COLOUR_BLEND_TITLE = "qarışdır"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "İki rəngi verilmiş nisbətdə (0,0 - 1,0) qarışdırır."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://az.wikipedia.org/wiki/Rəng"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Palitradan bir rəng seçin."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "təsadüfi rəng"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Təsadüfi bir rəng seçin."; -Blockly.Msg.COLOUR_RGB_BLUE = "mavi"; -Blockly.Msg.COLOUR_RGB_GREEN = "yaşıl"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "qırmızı"; -Blockly.Msg.COLOUR_RGB_TITLE = "rənglə"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Qırmızı, yaşıl və mavinin göstərilən miqdarı ilə bir rəng düzəlt. Bütün qiymətlər 0 ilə 100 arasında olmalıdır."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "dövrdən çıx"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "dövrün növbəti addımından davam et"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Cari dövrdən çıx."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Bu dövrün qalanını ötür və növbəti addımla davam et."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Xəbərdarlıq: Bu blok ancaq dövr daxilində istifadə oluna bilər."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "hər element üçün %1 siyahıda %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Siyahıdakı hər element üçün \"%1\" dəyişənini elementə mənimsət və bundan sonra bəzi əmrləri yerinə yetir."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "say: %1 %2 ilə başlayıb, %3 qiymətinə kimi %4 qədər dəyiş"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "\"%1\" dəyişəni başlanğıc ədəddən son ədədə qədər göstərilən aralıqla qiymətlər aldıqca göstərilən blokları yerinə yetir."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "\"Əgər\" blokuna bir şərt əlavə et."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "\"Əgər\" blokuna qalan bütün halları əhatə edəb son bir şərt əlavə et."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Bu \"əgər\" blokunu dəyişdirmək üçün bölümlərin yenisini əlavə et, sil və ya yerini dəyiş."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "əks halda"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "əks halda əgər"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "əgər"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Əgər qiymət doğrudursa, onda bəzi əmrləri yerinə yetir."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Əgər qiymət doğrudursa, onda birinci əmrlər blokunu yerinə yetir. Əks halda isə ikinci əmrlər blokunu yerinə yetir."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Əgər birinci qiymət doğrudursa, onda birinci əmrlər blokunu yerinə yetir. Əks halda əgər ikinci qiymət doğrudursa, onda ikinci əmrlər blokunu yerinə yetir."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Əgər birinci qiymət doğrudursa, onda birinci əmrlər blokunu yerinə yetir. Əks halda əgər ikinci qiymət doğrudursa, onda ikinci əmrlər blokunu yerinə yetir. Əgər qiymətlərdən heç biri doğru deyilsə, onda axırıncı əmrlər blokunu yerinə yetir."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://az.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "icra et"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "%1 dəfə təkrar et"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Bəzi əmrləri bir neçə dəfə yerinə yetir."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "təkrar et, ta ki"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "təkrar et, hələ ki"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Hələ ki, qiymət \"yalan\"dır, bəzi əmrləri yerinə yetir."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Hələ ki, qiymət \"doğru\"dur, bəzi əmrləri yerinə yetir."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Bütün %1 blok silinsin?"; -Blockly.Msg.DELETE_BLOCK = "Bloku sil"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "%1 bloku sil"; -Blockly.Msg.DISABLE_BLOCK = "Bloku söndür"; -Blockly.Msg.DUPLICATE_BLOCK = "Dublikat"; -Blockly.Msg.ENABLE_BLOCK = "Bloku aktivləşdir"; -Blockly.Msg.EXPAND_ALL = "Blokları aç"; -Blockly.Msg.EXPAND_BLOCK = "Bloku aç"; -Blockly.Msg.EXTERNAL_INPUTS = "Xarici girişlər"; -Blockly.Msg.HELP = "Kömək"; -Blockly.Msg.INLINE_INPUTS = "Sətiriçi girişlər"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "boş siyahı düzəlt"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Heç bir verilən qeyd olunmamış, uzunluğu 0 olan bir siyahı verir"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "siyahı"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Bu siyahı blokunu yenidən konfigurasiya etmək üçün bölmələri əlavə edin, silin və ya yerlərini dəyişin."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "bunlardan siyahı düzəlt"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Siyahıya element əlavə edin."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "İstənilən ölçülü siyahı yaradın."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "birinci"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "axırdan # nömrəli"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "götür"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "götür və sil"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "axırıncı"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "təsadüfi"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "yığışdır"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Siyahının ilk elementini qaytarır."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Siyahıdan təyin olunmuş indeksli elementi qaytarır."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Siyahının son elementini qaytarır."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Siyahıdan hər hansı təsadüfi elementi qaytarır."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Siyahıdan ilk elementi silir və qaytarır."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Siyahıdan təyin olunmuş indeksli elementi silir və qaytarır."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Siyahıdan son elementi silir və qaytarır."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Siyahıdan təsadufi elementi silir və qaytarır."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Siyahıdan ilk elementi silir."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Siyahıdan təyin olunmuş indeksli elementi silir."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Siyahıdan son elementi silir."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Siyahıdan təsadüfi bir elementi silir."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "sondan # nömrəliyə"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "# nömrəliyə"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "Sonuncuya"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "Birincidən alt-siyahını alın"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "# sonuncudan alt-siyahını alın"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "# - dən alt-siyahını alın"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Siyahının təyin olunmuş hissəsinin surətini yaradın."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 son elementdir."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 ilk elementdir."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "Element ilə ilk rastlaşma indeksini müəyyən edin"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "Element ilə son rastlaşma indeksini müəyyən edin"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Siyahıda element ilə ilk/son rastlaşma indeksini qaytarır. Əgər tekst siyahıda tapılmazsa, %1 qaytarılır."; -Blockly.Msg.LISTS_INLIST = "siyahıda"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 boşdur"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Siyahı boşdursa \"doğru\" cavabını qaytarır."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "%1 siyahısının uzunluğu"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Siyahının uzunluğunu verir."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "%1 elementinin %2 dəfə təkrarlandığı siyahı düzəlt"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Təyin olunmuş elementin/qiymətin təyin olunmuş sayda təkrarlandığı siyahını yaradır."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "Kimi"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "daxil et"; -Blockly.Msg.LISTS_SET_INDEX_SET = "təyin et"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Elementi siyahının əvvəlinə daxil edir."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Elementi siyahıda göstərilən yerə daxil edir."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Elementi siyahının sonuna artırır."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Elementi siyahıda təsadüfi seçilmiş bir yerə atır."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Siyahıda birinci elementi təyin edir."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Siyahının göstərilən yerdəki elementini təyin edir."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Siyahının sonuncu elementini təyin edir."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Siyahının təsadüfi seçilmiş bir elementini təyin edir."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "make list from text"; // untranslated -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "make text from list"; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "səhf"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "\"doğru\" və ya \"səhf\" cavanını qaytarır."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "doğru"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://az.wikipedia.org/wiki/bərabərsizlik_(riyazi)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Girişlər bir birinə bərabərdirsə \"doğru\" cavabını qaytarır."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Birinci giriş ikincidən böyükdürsə \"doğru\" cavabını qaytarır."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Birinci giriş ikincidən böyük və ya bərarbərdirsə \"doğru\" cavabını qaytarır."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Birinci giriş ikincidən kiçikdirsə \"doğru\" cavabını qaytarır."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Birinci giriş ikincidən kiçik və ya bərarbərdirsə \"doğru\" cavabını qaytarır."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Girişlər bərabər deyillərsə \"doğru\" cavabını qaytarır."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "%1 deyil"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Giriş \"yalan\"-dursa \"doğru\" cavabını qaytarır. Giriş \"doğru\"-dursa \"səhf\" cavabını qaytarır."; -Blockly.Msg.LOGIC_NULL = "boş"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Boş cavab qaytarır."; -Blockly.Msg.LOGIC_OPERATION_AND = "və"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "və ya"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Hər iki giriş \"doğru\"-dursa \"doğru\" cavabını qaytarır."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Girişlərdən heç olmasa biri \"doğru\"-dursa \"doğru\" cavabını qaytarır."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "əgər səhfdirsə"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "əgər doğrudursa"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "'Yoxla' əmrindəki şərtə nəzər yetirin. Əgər şərt \"doğru\"-dursa \"əgər doğru\", əks halda isə \"əgər yalan\" cavabını qaytarır."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://az.wikipedia.org/wiki/Hesab"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "İki ədədin cəmini qaytarır."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "İki ədədin nisbətini qaytarır."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "İki ədədin fərqini qaytarır."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "İki ədədin hasilini verir."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Birinci ədədin ikinci ədəd dərəcəsindən qüvvətini qaytarır."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; // untranslated -Blockly.Msg.MATH_CHANGE_TITLE = "dəyiş: %1 buna: %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "'%1' dəyişəninin üzərinə bir ədəd artır."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://az.wikipedia.org/wiki/Riyazi_sabitlər"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Ümumi sabitlərdən birini qaytarır π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), və ya ∞ (sonsuzluq)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "%1 üçün ən aşağı %2, ən yuxarı %3 olmağı tələb et"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Bir ədədin verilmiş iki ədəd arasında olmasını tələb edir (sərhədlər də daxil olmaqla)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "bölünür"; -Blockly.Msg.MATH_IS_EVEN = "cütdür"; -Blockly.Msg.MATH_IS_NEGATIVE = "mənfidir"; -Blockly.Msg.MATH_IS_ODD = "təkdir"; -Blockly.Msg.MATH_IS_POSITIVE = "müsətdir"; -Blockly.Msg.MATH_IS_PRIME = "sadədir"; -Blockly.Msg.MATH_IS_TOOLTIP = "Bir ədədin cüt, tək, sadə, tam, müsbət, mənfi olmasını və ya müəyyən bir ədədə bölünməsini yoxlayır. \"Doğru\" və ya \"yalan\" qiymətini qaytarır."; -Blockly.Msg.MATH_IS_WHOLE = "tamdır"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; // untranslated -Blockly.Msg.MATH_MODULO_TITLE = "%1 ÷ %2 bölməsinin qalığı"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "İki ədədin nisbətindən alınan qalığı qaytarır."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://az.wikipedia.org/wiki/Ədəd"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Ədəd."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "siyahının ədədi ortası"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "siyahının maksimumu"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "siyahının medianı"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "siyahının minimumu"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "Siyahı modları( Ən çox rastlaşılan elementləri)"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "siyahıdan təsadüfi seçilmiş bir element"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "Siyahının standart deviasiyası"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "Siyahının cəmi"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Siyahıdaki ədədlərin ədədi ortasını qaytarır."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Siyahıdaki ən böyük elementi qaytarır."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Siyahının median elementini qaytarır."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Siyahıdaki ən kiçik ədədi qaytarır."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Siyahıdaki ən çox rastlanan element(lər)dən ibarət siyahı qaytarır."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Siyahıdan təsadüfi bir element qaytarır."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Siyahının standart deviasiyasını qaytarır."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Siyahıdakı bütün ədədlərin cəmini qaytarır."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "təsadüfi kəsr"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "0.0 (daxil olmaqla) və 1.0 (daxil olmamaqla) ədədlərinin arasından təsadüfi bir kəsr ədəd qaytarır."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TITLE = "%1 ilə %2 arasından təsadüfi tam ədəd"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Verilmiş iki ədəd arasından (ədədrlər də daxil olmaqla) təsadüfi bir tam ədəd qaytarır."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; // untranslated -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "yuvarlaqlaşdır"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "aşağı yuvarlaqlaşdır"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "yuxarı yuvarlaqlaşdır"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Ədədi aşağı və ya yuxari yuvarlaqşdır."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://az.wikipedia.org/wiki/Kvadrat_kökləri"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "modul"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "kvadrat kök"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Ədədin modulunu qaytarır."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "e sabitinin verilmiş ədədə qüvvətini qaytarır."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Ədədin natural loqarifmini tapır."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Ədədin 10-cu dərəcədən loqarifmini tapır."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Ədədin əksini qaytarır."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "10-un verilmiş ədədə qüvvətini qaytarır."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Ədədin kvadrat kökünü qaytarır."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "arccos"; -Blockly.Msg.MATH_TRIG_ASIN = "arcsin"; -Blockly.Msg.MATH_TRIG_ATAN = "arctan"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://az.wikipedia.org/wiki/Triqonometrik_funksiyalar"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tg"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Ədədin arccosinusunu qaytarır."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Ədədin arcsinusunu qaytarır."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Ədədin arctanqensini qaytarır."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Dərəcənin kosinusunu qaytarır (radianın yox)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Dərəcənin sinusunu qaytar (radianın yox)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Dərəcənin tangensini qaytar (radianın yox)."; -Blockly.Msg.NEW_VARIABLE = "Yeni dəyişən..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Yeni dəyişənin adı:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "allow statements"; // untranslated -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "ilə:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Yaradılmış '%1' funksiyasını çalışdır."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Yaradılmış '%1' funksiyasını çalışdır və nəticəni istifadə et."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "ilə:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "'%1' yarat"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "hansısa əməliyyat"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "icra et:"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Nəticəsi olmayan funksiya yaradır."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "qaytar"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Nəticəsi olan funksiya yaradır."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Xəbərdarlıq: Bu funksiyanın təkrar olunmuş parametrləri var."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Funksiyanın təyinatını vurğula"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Əgər bir dəyər \"doğru\"-dursa onda ikinci dəyəri qaytar."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Xəbərdarlıq: Bu blok ancaq bir funksiyanın təyinatı daxilində işlədilə bilər."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "Giriş adı:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Add an input to the function."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "girişlər"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Add, remove, or reorder inputs to this function."; // untranslated -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "Şərhi sil"; -Blockly.Msg.RENAME_VARIABLE = "Dəyişənin adını dəyiş..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Bütün '%1' dəyişənlərinin adını buna dəyiş:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "bu mətni əlavə et:"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "bu mətnin sonuna:"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "'%1' dəyişəninin sonuna nəsə əlavə et."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "kiçik hərflərlə"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "Baş Hərflərlə"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "BÖYÜK HƏRFLƏRLƏ"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Mətndə hərflərin böyük-kiçikliyini dəyiş."; -Blockly.Msg.TEXT_CHARAT_FIRST = "birinci hərfi götür"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "axırdan bu nömrəli hərfi götür"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "bu nömrəli hərfi götür"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "növbəti mətndə"; -Blockly.Msg.TEXT_CHARAT_LAST = "axırıncı hərfi götür"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "təsadüfi hərf götür"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Göstərilən mövqedəki hərfi qaytarır."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Mətnə bir element əlavə et."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "birləşdir"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Bu mətn blokunu yenidən konfigurasiya etmək üçün bölmələri əlavə edin, silin və ya yerlərini dəyişin."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "axırdan bu nömrəli hərfə qədər"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "bu nömrəli hərfə qədər"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "son hərfə qədər"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "mətndə"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "Mətnin surətini ilk hərfdən"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "Mətnin surətini sondan bu nömrəli # hərfdən"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "Mətnin surətini bu nömrəli hərfdən"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Mətnin təyin olunmuş hissəsini qaytarır."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "mətndə"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "Bu mətn ilə ilk rastlaşmanı tap:"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "Bu mətn ilə son rastlaşmanı tap:"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Birinci mətnin ikinci mətndə ilk/son rastlaşma indeksini qaytarır. Əgər rastlaşma baş verməzsə, %1 qaytarır."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 boşdur"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Verilmiş mətn boşdursa, doğru qiymətini qaytarır."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "Verilmişlərlə mətn yarat"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "İxtiyari sayda elementlərinin birləşməsi ilə mətn parçası yarat."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "%1 - ın uzunluğu"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Verilmiş mətndəki hərflərin(sözlər arası boşluqlar sayılmaqla) sayını qaytarır."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "%1 - i çap elə"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Təyin olunmuş mətn, ədəd və ya hər hansı bir başqa elementi çap elə."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "İstifadəçiyə ədəd daxil etməsi üçün sorğu/tələb göndərin."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "İstifadəçiyə mətn daxil etməsi üçün sorğu/tələb göndərin."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "İstifadəçiyə ədəd daxil etməsi üçün sorğunu/tələbi ismarıc kimi göndərin"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "İstifadəçiyə mətn daxil etməsi üçün sorğunu/tələbi ismarıc ilə göndərin"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; // untranslated -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Mətndəki hərf, söz və ya sətir."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "Boşluqları hər iki tərəfdən pozun"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "Boşluqlari yalnız sol tərəfdən pozun"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "Boşluqları yalnız sağ tərəfdən pozun"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Mətnin hər iki və ya yalnız bir tərəfdən olan boşluqları pozulmuş surətini qaytarın."; -Blockly.Msg.TODAY = "Bugün"; -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "element"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "'%1 - i təyin et' - i yarat"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Bu dəyişənin qiymətini qaytarır."; -Blockly.Msg.VARIABLES_SET = "%1 - i bu qiymət ilə təyin et: %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "'%1 - i götür' - ü yarat"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Bu dəyişəni daxil edilmiş qiymətə bərabər edir."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/ba.js b/backend/_pv_1_3_5/static/blockly/msg/js/ba.js deleted file mode 100755 index 734e00c7e..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/ba.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.ba'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Фекер өҫтәргә"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Мәғәнәне үҙгәртегеҙ:"; -Blockly.Msg.CLEAN_UP = "Блоктарҙы таҙартырға"; -Blockly.Msg.COLLAPSE_ALL = "Блоктарҙы төрөргә"; -Blockly.Msg.COLLAPSE_BLOCK = "Блокты төрөргә"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "1-се төҫ"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "2-се төҫ"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "1-се төҫтөң өлөшө"; -Blockly.Msg.COLOUR_BLEND_TITLE = "ҡатнаштырырға"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Ике төҫтө бирелгән нисбәттә болғата (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Төҫ"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Палитранан төҫ һайлағыҙ."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "осраҡлы төҫ"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Төҫтө осраҡлылыҡ буйынса һайлай."; -Blockly.Msg.COLOUR_RGB_BLUE = "зәңгәр"; -Blockly.Msg.COLOUR_RGB_GREEN = "йәшелдән"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "ҡыҙылдан"; -Blockly.Msg.COLOUR_RGB_TITLE = "ошонан төҫ"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Бирелгән нисбәттәрҙә ҡыҙылдан, йәшелдән һәм зәңгәрҙән төҫ барлыҡҡа килә. Бөтә мәғәнәләр 0 менән 100 араһында булырға тейеш."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "циклдан сығырға"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "циклдың киләһе аҙымына күсергә"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Был циклды өҙә."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Циклдың ҡалдығын төшөрөп ҡалдыра һәм киләһе аҙымға күсә."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Иҫкәртеү: был блок цикл эсендә генә ҡулланыла ала."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "һәр элемент өсөн %1 исемлектә %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Исемлектәге һәр элемент өсөн үҙгәреүсәнгә элементтың '%1' мәғәнәһен бирә һәм күрһәтелгән командаларҙы үтәй."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "count with %1 from %2 to %3 by %4"; // untranslated -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Үҙгәреүсәнгә башынан аҙағына тиклем тәғәйен аҙым менән %1 мәғәнәне бирә һәм күрһәтелгән командаларҙы үтәй."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "\"Әгәр\" блогына шарт өҫтәй"; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Бер шарт та дөрөҫ булмаған осраҡҡа йомғаҡлау ярҙамсы блогын өҫтәргә."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "\"Әгәр\" блогын ҡабаттан төҙөү өсөн киҫәктәрҙе өҫтәгеҙ, юйҙырығыҙ, урындарын алмаштырығыҙ."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "юғиһә"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "юғиһә, әгәр"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "әгәр"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Мәғәнә дөрөҫ булғанда, командаларҙы үтәй."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Шарт дөрөҫ булғанда, командаларҙың беренсе блогын үтәй. Улай булмаһа, командаларҙың икенсе блогы үтәлә."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Беренсе шарт дөрөҫ булһа, командаларҙың беренсе блогын үтәй. Икенсе шарт дөрөҫ булһа, командаларҙың икенсе блогын үтәй."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Беренсе шарт дөрөҫ булһа, командаларҙың беренсе блогын үтәй. Әгәр икенсе шарт дөрөҫ булһа, командаларҙың икенсе блогын үтәй. Бер шарт та дөрөҫ булмаһа, команда блоктарының һуңғыһын үтәй."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/Цикл_(программалау)"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "үтәргә"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = " %1 тапҡыр ҡабатларға"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Командаларҙы бер нисә тапҡыр үтәй."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "ҡабатларға, әлегә юҡ"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "ҡабатларға, әлегә"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Мәғәнә ялған булғанда, командаларҙы ҡабатлай."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Мәғәнә дөрөҫ булғанда, командаларҙы ҡабатлай."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Бөтә %1 блоктарҙы юйырғамы?"; -Blockly.Msg.DELETE_BLOCK = "Блокты юйҙырырға"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = " %1 блокты юйҙырырға"; -Blockly.Msg.DISABLE_BLOCK = "Блокты һүндерергә"; -Blockly.Msg.DUPLICATE_BLOCK = "Күсереп алырға"; -Blockly.Msg.ENABLE_BLOCK = "Блокты тоҡандырырға"; -Blockly.Msg.EXPAND_ALL = "Блоктарҙы йәйергә"; -Blockly.Msg.EXPAND_BLOCK = "Блокты йәйергә"; -Blockly.Msg.EXTERNAL_INPUTS = "Тышҡы өҫтәлмә"; -Blockly.Msg.HELP = "Ярҙам"; -Blockly.Msg.INLINE_INPUTS = "Эске өҫтәлмә"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "create empty list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Returns a list, of length 0, containing no data records"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "исемлек"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Add, remove, or reorder sections to reconfigure this list block."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "менән исемлек төҙөргә"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Add an item to the list."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Create a list with any number of items."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_FIRST = "беренсе"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# аҙағынан"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "алырға"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "алырға һәм юйырға"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "аҙаҡҡы"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "осраҡлы"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "юйырға"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Removes and returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Removes and returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Removes and returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Removes and returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Removes the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Removes the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Removes the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Removes a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "to # from end"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "to #"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "to last"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "get sub-list from first"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "get sub-list from # from end"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "get sub-list from #"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Creates a copy of the specified portion of a list."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 is the last item."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 is the first item."; // untranslated -Blockly.Msg.LISTS_INDEX_OF_FIRST = "find first occurrence of item"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "find last occurrence of item"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Returns the index of the first/last occurrence of the item in the list. Returns %1 if item is not found."; // untranslated -Blockly.Msg.LISTS_INLIST = "исемлеккә"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 буш"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Returns true if the list is empty."; // untranslated -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "оҙонлоғо %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Returns the length of a list."; // untranslated -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "create list with item %1 repeated %2 times"; // untranslated -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Creates a list consisting of the given value repeated the specified number of times."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "кеүек"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "өҫтәп ҡуйырға"; -Blockly.Msg.LISTS_SET_INDEX_SET = "йыйылма"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserts the item at the start of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Inserts the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Append the item to the end of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Inserts the item randomly in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Sets the first item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Sets the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Sets the last item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Sets a random item in a list."; // untranslated -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "make list from text"; // untranslated -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "make text from list"; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "ялған"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Дөрөҫ йәки ялғанды ҡайтара."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "дөрөҫ"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(математика)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Өҫтәмәләр тигеҙ булһа, дөрөҫ мәғәнәһен кире ҡайтара."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Беренсе өҫтәмә икенсеһенән ҙурыраҡ булһа, дөрөҫ мәғәнәһен кире ҡайтара."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Беренсе өҫтәмә икенсеһенән бәләкәйерәк йә уға тиң булһа, дөрөҫ мәғәнәһен кире ҡайтара."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Беренсе өҫтәмә икенсеһенән бәләкәйерәк булһа, дөрөҫ мәғәнәһен кире ҡайтара."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Беренсе өҫтәмә икенсеһенән бәләкәйерәк йә уға тиң булһа, дөрөҫ мәғәнәһен кире ҡайтара."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Өҫтәмәләр тигеҙ булмаһа, дөрөҫ мәғәнәһен кире ҡайтара."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "%1 түгел"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Өҫтәлмә ялған булһа, дөрөҫ аңлатманы ҡайтара. Өҫтәлмә дөрөҫ булһа, ялған аңлатманы ҡайтара."; -Blockly.Msg.LOGIC_NULL = "нуль"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Нулде ҡайтара."; -Blockly.Msg.LOGIC_OPERATION_AND = "һәм"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "йәки"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Әгәр ҙә ике өҫтәлмә лә тап килһә, дөрөҫ аңлатманы кире ҡайтара."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Өҫтәлмәләрҙең береһе генә дөрөҫ булһа, дөрөҫ аңлатманы ҡайтара."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "тест"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "әгәр ялған булһа"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "әгәр дөрөҫ булһа"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Һайлау шартын тикшерә. Әгәр ул дөрөҫ булһа, беренсе мәғәнәне, хата булһа, икенсе мәғәнәне ҡайтара."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://ba.wikipedia.org/wiki/Арифметика"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Ике һандың суммаһын ҡайтара."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Ике һандың бүлендеген ҡайтара."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Ике һандың айырмаһын ҡайтара."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Ике һандың ҡабатландығын ҡайтара."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Дәрәжәгә күтәрелгән икенсе һандан тәүгеһенә ҡайтара."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://ba.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "%1 тан %2 ҡа арттырырға"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Үҙгәреүсән һанға өҫтәй '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://ba.wikipedia.org/wiki/Математик_константа"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Таралған константаның береһен күрһәтә: π (3.141...), e (2.718...), φ (1.618...), sqrt(2) (1.414...), sqrt(½) (0.707...) йәки ∞ (сикһеҙлек)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "сикләргә %1 аҫтан %2 өҫтән %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Һанды аҫтан һәм өҫтән сикләй (сиктәгеләрен индереп)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "бүленә"; -Blockly.Msg.MATH_IS_EVEN = "тағы"; -Blockly.Msg.MATH_IS_NEGATIVE = "тиҫкәре"; -Blockly.Msg.MATH_IS_ODD = "сәйер"; -Blockly.Msg.MATH_IS_POSITIVE = "ыңғай"; -Blockly.Msg.MATH_IS_PRIME = "ябай"; -Blockly.Msg.MATH_IS_TOOLTIP = "Һандың йоп, таҡ, ябай, бөтөн, ыңғай, кире йәки билдәле һанға ҡарата ниндәй булыуын тикшерә. Дөрөҫ йә ялған мәғәнәһен күрһәтә."; -Blockly.Msg.MATH_IS_WHOLE = "бөтөн"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://ba.wikipedia.org/wiki/Ҡалдыҡ_менән_бүлеү"; -Blockly.Msg.MATH_MODULO_TITLE = "ҡалдыҡ %1 : %2 араһында"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Ике һанды бүлеү ҡалдығын күрһәтә."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://ba.wikipedia.org/wiki/Һан"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Рәт."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "исемлектең уртаса арифметик дәүмәле"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "исемлектәге иң ҙуры"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "исемлек медианаһы"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "Исемлектәге иң бәләкәйе"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "исемлек модалары"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "исемлектең осраҡлы элементы"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "исемлекте стандарт кире ҡағыу"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "исемлек суммаһы"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Исемлектең уртаса арифметик дәүмәле күрһәтә."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Исемлектең иң ҙур һанын күрһәтә."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Исемлек медианаһын күрһәтә."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Исемлектәге иң бәләкәй һанды күрһәтә."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Исемлектең иң күп осраған элементтарын күрһәтә."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Исемлектең осраҡлы элементын күрһәтә."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Исемлекте стандарт кире ҡағыуҙы күрһәтә."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Исемлектәрҙәге һандар суммаһын күрһәтә."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://ba.wikipedia.org/wiki/Ялған осраҡлы_һандар_генераторы"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "0 (үҙен дә индереп) һәм 1 араһындағы осраҡлы һан"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive)."; // untranslated -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://ba.wikipedia.org/wiki/Ялған осраҡлы_һандар_генераторы"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "%1-ҙән %2-гә тиклем осраҡлы бөтөн һан"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Ике бирелгән һан араһындағы (үҙҙәрен дә индереп) осраҡлы һанды күрһәтә."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://ba.wikipedia.org/wiki/Т=Түңәрәкләү"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "түңәрәк"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "бәләкәйгә тиклем түңәрәкләргә"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "ҙурына тиклем түңәрәкләргә"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Һанды ҙурына йә бәләкәйенә тиклем түңәрәкләргә."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://ba.wikipedia.org/wiki/Квадрат_тамыр"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "абсолют"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "квадрат тамыр"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Һандың модулен ҡайтара."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Күрһәтелгән дәрәжәлә ҡайтара."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Һандың натураль логаритмын ҡайтара."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Һандың унынсы логаритмын ҡайтара."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Кире һанды ҡайтара."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Күрһәтелгән 10-сы дәрәжәлә ҡайтара."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Һандың квадрат тамырын ҡайтара."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://ba..wikipedia.org/wiki/Тригонометрик_функциялар"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Арккосинусты градустарҙа күрһәтә."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Арксинусты градустарҙа күрһәтә."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Арктангенсты градустарҙа күрһәтә."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Мөйөштөң косинусын градустарҙа ҡайтара."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Мөйөштөң синусын градустарҙа ҡайтара."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Мөйөштөң тангенсын градустарҙа күрһәтә."; -Blockly.Msg.NEW_VARIABLE = "Яңы үҙгәреүсән..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Яңы үҙгәреүсәндең исеме:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "allow statements"; // untranslated -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "with:"; // untranslated -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Run the user-defined function '%1'."; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Run the user-defined function '%1' and use its output."; // untranslated -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "with:"; // untranslated -Blockly.Msg.PROCEDURES_CREATE_DO = "'%1' төҙөргә"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "do something"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "to"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Creates a function with no output."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "кире ҡайтарыу"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Creates a function with an output."; // untranslated -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Warning: This function has duplicate parameters."; // untranslated -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Highlight function definition"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "If a value is true, then return a second value."; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Warning: This block may be used only within a function definition."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "инеү исеме:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Add an input to the function."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "инеү"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Add, remove, or reorder inputs to this function."; // untranslated -Blockly.Msg.REDO = "документтарҙы үҙгәртергә"; -Blockly.Msg.REMOVE_COMMENT = "Аңлатмаларҙы юйырға"; -Blockly.Msg.RENAME_VARIABLE = "Үҙгәреүсәндең исемен алмаштырырға..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Бөтә '%1' үҙгәреүсәндәрҙең исемен ошолай алмаштырырға:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "текст өҫтәргә"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "to"; // untranslated -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Үҙгәреүсән «%1»-гә текст өҫтәргә."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "to lower case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "to Title Case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "to UPPER CASE"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; // untranslated -Blockly.Msg.TEXT_CHARAT_FIRST = "тәүге хәрефте алырға"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "№ хәрефен аҙаҡтан алырға"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "хат алырға #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "текста"; -Blockly.Msg.TEXT_CHARAT_LAST = "һуңғы хәрефте алырға"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "осраҡлы хәрефте алырға"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Returns the letter at the specified position."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Текстҡа элемент өҫтәү."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "ҡушылығыҙ"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Add, remove, or reorder sections to reconfigure this text block."; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "to letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "# хатҡа"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "һуңғы хәрефкә тиклем"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "текста"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "get substring from first letter"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "get substring from letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "get substring from letter #"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returns a specified portion of the text."; // untranslated -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "текстҡа"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "текстың тәүге инеүен табырға"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "Текстың һуңғы инеүен табырға"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found."; // untranslated -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 буш"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returns true if the provided text is empty."; // untranslated -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "текст төҙөргә"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Элементтарҙың теләһә күпме һанын берләштереп текст фрагментын булдыра."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "оҙонлоғо %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Бирелгән текстағы символдар һанын (буш урындар менән бергә) кире ҡайтара."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "%1 баҫтырырға"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Print the specified text, number or other value."; // untranslated -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Prompt for user for a number."; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Prompt for user for some text."; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "prompt for number with message"; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "prompt for text with message"; // untranslated -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; // untranslated -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Текстың хәрефе, һүҙе йәки юлы."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "trim spaces from both sides of"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "trim spaces from left side of"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "trim spaces from right side of"; // untranslated -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Return a copy of the text with spaces removed from one or both ends."; // untranslated -Blockly.Msg.TODAY = "Бөгөн"; -Blockly.Msg.UNDO = "Кире алырға"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "элемент"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Create 'set %1'"; // untranslated -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returns the value of this variable."; // untranslated -Blockly.Msg.VARIABLES_SET = "set %1 to %2"; // untranslated -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Create 'get %1'"; // untranslated -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Sets this variable to be equal to the input."; // untranslated -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/bcc.js b/backend/_pv_1_3_5/static/blockly/msg/js/bcc.js deleted file mode 100755 index d4ff7cbe3..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/bcc.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.bcc'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "افزودن نظر"; -Blockly.Msg.CHANGE_VALUE_TITLE = "تغییر مقدار:"; -Blockly.Msg.CLEAN_UP = "Clean up Blocks"; // untranslated -Blockly.Msg.COLLAPSE_ALL = "فروپاشی بلوک‌ها"; -Blockly.Msg.COLLAPSE_BLOCK = "فروپاشی بلوک"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "رنگ ۱"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "رنگ ۲"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "نسبت"; -Blockly.Msg.COLOUR_BLEND_TITLE = "مخلوط"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "دو رنگ را با نسبت مشخص‌شده مخلوط می‌کند (۰٫۰ - ۱٫۰)"; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://fa.wikipedia.org/wiki/%D8%B1%D9%86%DA%AF"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "انتخاب یک رنگ از تخته‌رنگ."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "رنگ تصادفی"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "انتخاب یک رنگ به شکل تصادفی."; -Blockly.Msg.COLOUR_RGB_BLUE = "آبی"; -Blockly.Msg.COLOUR_RGB_GREEN = "سبز"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "قرمز"; -Blockly.Msg.COLOUR_RGB_TITLE = "رنگ با"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "ساخت یک رنگ با مقدار مشخص‌شده‌ای از قرمز، سبز و آبی. همهٔ مقادیر باید بین ۰ تا ۱۰۰ باشند."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "شکستن حلقه"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "ادامه با تکرار بعدی حلقه"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "شکستن حلقهٔ شامل."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "پریدن از بقیهٔ حلقه و ادامه با تکرار بعدی."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "اخطار: این بلوک ممکن است فقط داخل یک حلقه استفاده شود."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "برای هر مورد %1 در فهرست %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "برای هر مورد در این فهرست، تنظیم متغیر «%1» به مورد و انجام تعدادی عبارت."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "با تعداد %1 از %2 به %3 با گام‌های %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "متغیر %1 را در مقادیر شروع‌شده از عدد انتهای به عدد انتهایی را دارد، با فواصل مشخص‌شده می‌شمارد و این بلوک مشخص‌شده را انجام می‌دهد."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "افزودن یک شرط به بلوک اگر."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "اضافه‌کردن نهایی، گرفتن همهٔ شرایط به بلوک اگر."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "اضافه، حذف یا ترتیب‌سازی قسمت‌ها برای تنظیم مجدد این بلوک اگر مسدود است."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "آنگاه"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "اگر آنگاه"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "اگر"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "اگر یک مقدار صحیح است، سپس چند عبارت را انجام بده."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "اگر یک مقدار صحیح است، اول بلوک اول عبارات را انجام بده. در غیر این صورت بلوک دوم عبارات انجام بده."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "اگر مقدار اول صحیح بود، از آن بلوک اول عبارات را انجام بده. در غیر این صورت، اگر مقدار دوم صحیح است، بلوک دوم عبارات را انجام بده."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "اگر مقدار اول درست است، بلوک اول عبارات را انجام بده. در غیر این صورت، اگر مقدار دوم درست باشد بلوک دوم عبارات را انجام بده. اگر هیچ از مقادیر درست نبود، آخرین بلوک عبارات را انجام بده."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://fa.wikipedia.org/wiki/%D8%AD%D9%84%D9%82%D9%87_%D9%81%D9%88%D8%B1"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "انجام"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "%1 بار تکرار"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "انجام چند عبارت چندین بار."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "تکرار تا"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "تکرار در حالی که"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "تا زمانی که یک مقدار ناصحیح است، چند عبارت را انجام بده."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "تا زمانی که یک مقدار صحیح است، چند عبارت را انجام بده."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Delete all %1 blocks?"; // untranslated -Blockly.Msg.DELETE_BLOCK = "حذف بلوک"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "حذف بلوک‌های %1"; -Blockly.Msg.DISABLE_BLOCK = "غیرفعال‌سازی بلوک"; -Blockly.Msg.DUPLICATE_BLOCK = "تکراری"; -Blockly.Msg.ENABLE_BLOCK = "فعال‌سازی بلوک"; -Blockly.Msg.EXPAND_ALL = "گسترش بلوک‌ها"; -Blockly.Msg.EXPAND_BLOCK = "گسترش بلوک"; -Blockly.Msg.EXTERNAL_INPUTS = "ورودی‌های خارجی"; -Blockly.Msg.HELP = "کومک"; -Blockly.Msg.INLINE_INPUTS = "ورودی‌های درون خطی"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "ایجاد فهرست خالی"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "فهرستی با طول صفر شامل هیچ رکورد داده‌ای بر می‌گرداند."; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "فهرست"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "اضافه‌کردن، حذف‌کردن یا ترتیب‌سازی مجدد بخش‌ها این بلوک فهرستی."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "ایجاد فهرست با"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "اضافه‌کردن یک مورد به فهرست."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "فهرستی از هر عددی از موارد می‌سازد."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "اولین"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# از انتها"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "گرفتن"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "گرفتن و حذف‌کردن"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "اهرین"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "تصادفی"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "حذف‌کردن"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "اولین مورد یک فهرست را بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "موردی در محل مشخص‌شده بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "آخرین مورد در یک فهرست را بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "یک مورد تصادفی در یک فهرست بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "اولین مورد مشخص‌شده در فهرست را حذف و بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "مورد در محل مشخص‌شده در فهرست را حذف و بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "آخرین مورد مشخص‌شده در فهرست را حذف و بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "مورد تصادفی‌ای را در فهرست حذف و بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "اولین مورد را در یک فهرست حذف می‌کند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "مورد مشخص‌شده در موقعیت مشخص در یک فهرست را حذف و بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "آخرین مورد را در یک فهرست حذف می‌کند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "یک مورد تصادفی را یک فهرست حذف می‌کند."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "به # از انتها"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "به #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "به آخرین"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "گرفتن زیرمجموعه‌ای از ابتدا"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "گرفتن زیرمجموعه‌ای از # از انتها"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "گرفتن زیرمجموعه‌ای از #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "کپی از قسمت مشخص‌شدهٔ لیست درست می‌کند."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 آخرین مورد است."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 اولین مورد است."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "آخرین رخداد متن را بیاب"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "یافتن آخرین رخ‌داد مورد"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "شاخصی از اولین/آخرین رخ‌داد مورد در فهرست را بر می‌گرداند. %1 بر می‌گرداند اگر متن موجود نبود."; -Blockly.Msg.LISTS_INLIST = "در فهرست"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 خالی است"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "اگر فهرست خالی است مقدار صجیج بر می‌گرداند."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "طول %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "طول یک فهرست را برمی‌گرداند."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "فهرستی با %1 تکرارشده به اندازهٔ %2 می‌سازد"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "فهرستی شامل مقادیر داده‌شدهٔ تکرار شده عدد مشخص‌شده می‌سازد."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "به‌عنوان"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "درج در"; -Blockly.Msg.LISTS_SET_INDEX_SET = "مجموعه"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "موردی به ته فهرست اضافه می‌کند."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "موردی در موقعیت مشخص‌شده در یک فهرست اضافه می‌کند."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "موردی به ته فهرست الحاق می‌کند."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "مورد را به صورت تصادفی در یک فهرست می‌افزاید."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "اولین مورد در یک فهرست را تعیین می‌کند."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "مورد مشخص‌شده در یک فهرست را قرار می‌دهد."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "آخرین مورد در یک فهرست را تعیین می‌کند."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "یک مورد تصادفی در یک فهرست را تعیین می‌کند."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "make list from text"; // untranslated -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "make text from list"; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "ناصحیح"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "بازگرداندن یکی از صحیح یا ناصحیح."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "صحیح"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://fa.wikipedia.org/wiki/%D9%86%D8%A7%D8%A8%D8%B1%D8%A7%D8%A8%D8%B1%DB%8C"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "بازگشت صحیح اگر هر دو ورودی با یکدیگر برابر باشد."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "بازگرداندن صحیح اگر ورودی اول بزرگتر از ورودی دوم باشد."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "بازگرداندن صحیح اگر ورودی اول بزرگتر یا مساوی یا ورودی دوم باشد."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "بازگرداندن صحیح اگر ورودی اول کوچکتر از ورودی دوم باشد."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "بازگرداندن صحیح اگر ورودی اول کوچکتر یا مساوی با ورودی دوم باشد."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "برگرداندن صحیح اگر هر دو ورودی با یکدیگر برابر نباشند."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "نه %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "صجیج باز می‌گرداند اگر ورودی نا صحیح باشند. ناصحیح بازمی‌گرداند اگر ورودی صحیح باشد."; -Blockly.Msg.LOGIC_NULL = "تهی"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "تهی بازمی‌گرداند."; -Blockly.Msg.LOGIC_OPERATION_AND = "و"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "یا"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "بازگرداندن صحیح اگر هر دو ورودی صحیح باشد."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "بازگرداندن صحیح اگر یکی از دو ورودی صحیح باشد."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "آزمایش"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "اگر ناصحیح"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "اگر صحیح"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "بررسی وضعیت در «آزمایش». اگر وضعیت صحیح باشد، مقدار «اگر صحیح» را بر می‌گرداند در غیر اینصورت مقدار «اگر ناصحیح» را."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://fa.wikipedia.org/wiki/%D8%AD%D8%B3%D8%A7%D8%A8"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "بازگرداندن مقدار جمع دو عدد."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "بازگرداندن باقی‌ماندهٔ دو عدد."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "بازگرداندن تفاوت دو عدد."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "بازگرداندن حاصلضرب دو عدد."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "بازگرداندن اولین عددی که از توان عدد دوم حاصل شده باشد."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://fa.wikipedia.org/wiki/%D8%A7%D8%B5%D8%B7%D9%84%D8%A7%D8%AD_%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87%E2%80%8C%D9%86%D9%88%DB%8C%D8%B3%DB%8C#.D8.A7.D9.81.D8.B2.D8.A7.DB.8C.D8.B4_.D8.B4.D9.85.D8.A7.D8.B1.D9.86.D8.AF.D9.87"; -Blockly.Msg.MATH_CHANGE_TITLE = "تغییر %1 با %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "افزودن یک عدد به متغیر '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://fa.wikipedia.org/wiki/%D8%AB%D8%A7%D8%A8%D8%AA_%D8%B1%DB%8C%D8%A7%D8%B6%DB%8C"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "یکی از مقادیر مشترک را برمی‌گرداند: π (۳٫۱۴۱…)، e (۲٫۷۱۸...)، φ (۱٫۶۱۸)، sqrt(۲) (۱٫۴۱۴)، sqrt(۱/۲) (۰٫۷۰۷...) و یا ∞ (بی‌نهایت)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "محدودکردن %1 پایین %2 بالا %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "محدودکردن یک عدد بین محدودیت‌های مشخص‌شده (بسته)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "تقسیم شده بر"; -Blockly.Msg.MATH_IS_EVEN = "زوج است"; -Blockly.Msg.MATH_IS_NEGATIVE = "منفی است"; -Blockly.Msg.MATH_IS_ODD = "فرد است"; -Blockly.Msg.MATH_IS_POSITIVE = "مثبت است"; -Blockly.Msg.MATH_IS_PRIME = "عدد اول است"; -Blockly.Msg.MATH_IS_TOOLTIP = "بررسی می‌کند که آیا یک عدد زوج، فرد، اول، کامل، مثبت، منفی یا بخش‌پذیر عدد خاصی باشد را بررسی می‌کند. درست یا نادرست باز می‌گرداند."; -Blockly.Msg.MATH_IS_WHOLE = "کامل است"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://fa.wikipedia.org/wiki/%D8%B9%D9%85%D9%84%DB%8C%D8%A7%D8%AA_%D9%BE%DB%8C%D9%85%D8%A7%D9%86%D9%87"; -Blockly.Msg.MATH_MODULO_TITLE = "باقی‌ماندهٔ %1 + %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "باقی‌ماندهٔ تقسیم دو عدد را بر می‌گرداند."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://fa.wikipedia.org/wiki/%D8%B9%D8%AF%D8%AF"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "یک عدد."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "میانگین فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "بزرگ‌ترین فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "میانهٔ فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "کوچکترین فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "مد فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "مورد تصادفی از فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "انحراف معیار فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "جمع فهرست"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "میانگین (میانگین ریاضی) مقادیر عددی فهرست را بر می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "بزرگ‌ترین عدد در فهرست را باز می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "میانهٔ عدد در فهرست را بر می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "کوچک‌ترین عدد در فهرست را باز می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "شایع‌ترین قلم(های) در فهرست را بر می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "موردی تصادفی از فهرست را بر می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "انحراف معیار فهرست را بر می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "جمع همهٔ عددهای فهرست را باز می‌گرداند."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://fa.wikipedia.org/wiki/%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D8%A7%D8%B9%D8%AF%D8%A7%D8%AF_%D8%AA%D8%B5%D8%A7%D8%AF%D9%81%DB%8C"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "کسر تصادفی"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "بازگرداندن کسری تصادفی بین ۰٫۰ (بسته) تا ۱٫۰ (باز)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://fa.wikipedia.org/wiki/%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D8%A7%D8%B9%D8%AF%D8%A7%D8%AF_%D8%AA%D8%B5%D8%A7%D8%AF%D9%81%DB%8C"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "عدد صحیح تصادفی بین %1 تا %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "یک عدد تصادفی بین دو مقدار مشخص‌شده به صورت بسته باز می‌گرداند."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "گردکردن"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "گرد به پایین"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "گرد به بالا"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "گردکردن یک عدد به بالا یا پایین."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://fa.wikipedia.org/wiki/%D8%B1%DB%8C%D8%B4%D9%87_%D8%AF%D9%88%D9%85"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "مطلق"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "ریشهٔ دوم"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "قدر مطلق یک عدد را بازمی‌گرداند."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "بازگرداندن توان e یک عدد."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "لوگاریتم طبیعی یک عدد را باز می‌گرداند."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "بازگرداندن لگاریتم بر پایهٔ ۱۰ یک عدد."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "منفی‌شدهٔ یک عدد را باز می‌گرداند."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "بازگرداندن توان ۱۰ یک عدد."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "ریشهٔ دوم یک عدد را باز می‌گرداند."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://fa.wikipedia.org/wiki/%D8%AA%D8%A7%D8%A8%D8%B9%E2%80%8C%D9%87%D8%A7%DB%8C_%D9%85%D8%AB%D9%84%D8%AB%D8%A7%D8%AA%DB%8C"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "بازگرداندن آرک‌کسینوس درجه (نه رادیان)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "بازگرداندن آرک‌سینوس درجه (نه رادیان)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "بازگرداندن آرک‌تانژانت درجه (نه رادیان)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "بازگرداندن کسینوس درجه (نه رادیان)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "بازگرداندن سینوس درجه (نه رادیان)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "بازگرداندن تانژانت یک درجه (نه رادیان)."; -Blockly.Msg.NEW_VARIABLE = "متغیر تازه..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "نام متغیر تازه:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "اجازه اظهارات"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "با:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "اجرای تابع تعریف‌شده توسط کاربر «%1»."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "اجرای تابع تعریف‌شده توسط کاربر «%1» و استفاده از خروجی آن."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "با:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "ساختن «%1»"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "انجام چیزی"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "به"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "تابعی می‌سازد بدون هیچ خروجی."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "بازگشت"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "تابعی با یک خروجی می‌سازد."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "اخطار: این تابعی پارامتر تکراری دارد."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "برجسته‌سازی تعریف تابع"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "اگر یک مقدار صحیح است، مقدار دوم را برگردان."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "اخطار: این بلوک احتمالاً فقط داخل یک تابع استفاده می‌شود."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "نام ورودی:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "اضافه کردن ورودی به تابع."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "ورودی‌ها"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "افزودن، حذف یا دوباره مرتب‌کردن ورودی این تابع."; -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "حذف نظر"; -Blockly.Msg.RENAME_VARIABLE = "تغییر نام متغیر..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "تغییر نام همهٔ متغیرهای «%1» به:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "الحاق متن"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "به"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "الحاق متنی به متغیر «%1»."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "به حروف کوچک"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "به حروف بزرگ عنوان"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "به حروف بزرگ"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "بازگرداندن کپی متن در حالتی متفاوت."; -Blockly.Msg.TEXT_CHARAT_FIRST = "گرفتن اولین حرف"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "گرفتن حرف # از آخر"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "گرفتن حرف #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "در متن"; -Blockly.Msg.TEXT_CHARAT_LAST = "گرفتن آخرین حرف"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "گرفتن حرف تصادفی"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "حرفی در موقعیت مشخص‌شده بر می‌گرداند."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "افزودن یک مورد به متن."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "عضویت"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "اضافه، حذف یا ترتیب‌سازی قسمت‌ها برای تنظیم مجدد این بلوک اگر مسدود است."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "به حرف # از انتها"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "به حرف #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "گرفتن آخرین حرف"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "در متن"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "گرفتن زیرمتن از اولین حرف"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "گرفتن زیرمتن از حرف # به انتها"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "گرفتن زیرمتن از حرف #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "قسمت مشخصی‌شده‌ای از متن را بر می‌گرداند."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "در متن"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "اولین رخداد متن را بیاب"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "آخرین رخداد متن را بیاب"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "شاخصی از اولین آخرین رخ‌داد متن اول در متن دوم بر می‌گرداند. اگر متن یافت نشد %1 باز می‌گرداند."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 خالی است"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "اضافه‌کردن صحیح اگر متن فراهم‌شده خالی است."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "ایجاد متن با"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "یک تکه‌ای از متن را با چسپاندن همهٔ تعداد از موارد ایجاد می‌کند."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "طول %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "بازگرداندن عددی از حروف (شامل فاصله‌ها) در متن فراهم‌شده."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "چاپ %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "چاپ متن، عدد یا هر مقدار دیگر مشخص‌شده."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "اعلان برای کاربر با یک عدد."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "اعلان برای کاربر برای یک متن."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "اعلان برای عدد با پیام"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "اعلان برای متن با پیام"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://fa.wikipedia.org/wiki/%D8%B1%D8%B4%D8%AA%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "یک حرف، کلمه یا خطی از متن."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "تراشیدن فاصله‌ها از هر دو طرف"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "تراشیدن فاصله‌ها از طرف چپ"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "تراشیدن فاصله‌ها از طرف چپ"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "کپی از متن با فاصله‌های حذف‌شده از یک یا هر دو پایان باز می‌گرداند."; -Blockly.Msg.TODAY = "Today"; // untranslated -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "مورد"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "درست‌کردن «تنظیم %1»"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "مقدار این متغیر را بر می‌گرداند."; -Blockly.Msg.VARIABLES_SET = "مجموعه %1 به %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "درست‌کردن «تنظیم %1»"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "متغیر برابر با خروجی را مشخص می‌کند."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/be-tarask.js b/backend/_pv_1_3_5/static/blockly/msg/js/be-tarask.js deleted file mode 100755 index 6b1752b6b..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/be-tarask.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.be.tarask'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Дадаць камэнтар"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Зьмяніць значэньне:"; -Blockly.Msg.CLEAN_UP = "Ачысьціць блёкі"; -Blockly.Msg.COLLAPSE_ALL = "Згарнуць блёкі"; -Blockly.Msg.COLLAPSE_BLOCK = "Згарнуць блёк"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "колер 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "колер 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "дзеля"; -Blockly.Msg.COLOUR_BLEND_TITLE = "зьмяшаць"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Зьмешвае два колеры ў дадзенай прапорцыі (0.0 — 1.0)"; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://be-x-old.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BB%D0%B5%D1%80"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Абярыце колер з палітры."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "выпадковы колер"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Абраць выпадковы колер."; -Blockly.Msg.COLOUR_RGB_BLUE = "сіняга"; -Blockly.Msg.COLOUR_RGB_GREEN = "зялёнага"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "чырвонага"; -Blockly.Msg.COLOUR_RGB_TITLE = "колер з"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Стварыць колер з абранымі прапорцыямі чырвонага, зялёнага і сіняга. Усе значэньні павінны быць ад 0 да 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "перарваць цыкль"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "працягнуць з наступнага кроку цыклю"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Спыніць гэты цыкль."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Прапусьціць рэшту цыклю і перайсьці да наступнага кроку."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Увага: гэты блёк можа быць выкарыстаны толькі ў цыклі."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "для кожнага элемэнта %1 у сьпісе %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Для кожнага элемэнту сьпісу прысвойвае зьменнай '%1' ягонае значэньне і выконвае пэўныя апэрацыі."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "лічыць з %1 ад %2 да %3 па %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Прысвойвае зьменнай \"%1\" значэньні ад пачатковага да канчатковага значэньня, улічваючы зададзены крок, і выконвае абраныя блёкі."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Дадаць умову да блёку «калі»."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Дадаць заключную ўмову для ўсіх астатніх варыянтаў блёку «калі»."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Дадаць, выдаліць ці пераставіць сэкцыі для пераканфігураваньня гэтага блёку «калі»."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "інакш"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "інакш, калі"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "калі"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Калі значэньне ісьціна, выканаць пэўныя апэрацыі."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Калі значэньне ісьціна, выканаць першы блёк апэрацыяў, інакш выканаць другі блёк."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Калі першае значэньне ісьціна, выканаць першы блёк апэрацыяў. Інакш, калі другое значэньне ісьціна, выканаць другі блёк апэрацыяў."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Калі першае значэньне ісьціна, выканаць першы блёк апэрацыяў. Інакш, калі другое значэньне ісьціна, выканаць другі блёк апэрацыяў. Калі ніводнае з значэньняў не сапраўднае, выканаць апошні блёк апэрацыяў."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "выканаць"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "паўтарыць %1 раз(ы)"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Выконвае апэрацыі некалькі разоў."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "паўтараць, пакуль не"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "паўтараць, пакуль"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Пакуль значэньне хлусьня, выконваць пэўныя апэрацыі."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Пакуль значэньне ісьціна, выконваць пэўныя апэрацыі."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Выдаліць усе блёкі %1?"; -Blockly.Msg.DELETE_BLOCK = "Выдаліць блёк"; -Blockly.Msg.DELETE_VARIABLE = "Выдаліць зьменную «%1»"; -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Выдаліць %1 выкарыстаньняў зьменнай «%2»?"; -Blockly.Msg.DELETE_X_BLOCKS = "Выдаліць %1 блёкі"; -Blockly.Msg.DISABLE_BLOCK = "Адключыць блёк"; -Blockly.Msg.DUPLICATE_BLOCK = "Капіяваць"; -Blockly.Msg.ENABLE_BLOCK = "Уключыць блёк"; -Blockly.Msg.EXPAND_ALL = "Разгарнуць блёкі"; -Blockly.Msg.EXPAND_BLOCK = "Разгарнуць блёк"; -Blockly.Msg.EXTERNAL_INPUTS = "Зьнешнія ўваходы"; -Blockly.Msg.HELP = "Дапамога"; -Blockly.Msg.INLINE_INPUTS = "Унутраныя ўваходы"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "стварыць пусты сьпіс"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Вяртае сьпіс даўжынёй 0, які ня ўтрымлівае запісаў зьвестак"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "сьпіс"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Дадаць, выдаліць ці пераставіць сэкцыі для пераканфігураваньня гэтага блёку."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "стварыць сьпіс з"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Дадаць элемэнт да сьпісу."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Ставарае сьпіс зь любой колькасьцю элемэнтаў."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "першы"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "№ з канца"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "атрымаць"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "атрымаць і выдаліць"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "апошні"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "выпадковы"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "выдаліць"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Вяртае першы элемэнт у сьпісе."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Вяртае элемэнт у пазначанай пазыцыі ў сьпісе."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Вяртае апошні элемэнт у сьпісе."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Вяртае выпадковы элемэнт у сьпісе."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Выдаляе і вяртае першы элемэнт у сьпісе."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Выдаляе і вяртае элемэнт у пазначанай пазыцыі ў сьпісе."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Выдаляе і вяртае апошні элемэнт у сьпісе."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Выдаляе і вяртае выпадковы элемэнт у сьпісе."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Выдаляе першы элемэнт у сьпісе."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Выдаляе элемэнт у пазначанай пазыцыі ў сьпісе."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Выдаляе апошні элемэнт у сьпісе."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Выдаляе выпадковы элемэнт у сьпісе."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "па № з канца"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "да #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "да апошняга"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "атрымаць падсьпіс зь першага"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "атрымаць падсьпіс з № з канца"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "атрымаць падсьпіс з №"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Стварае копію пазначанай часткі сьпісу."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "№%1 — апошні элемэнт."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "№%1 — першы элемэнт."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "знайсьці першае ўваходжаньне элемэнту"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "знайсьці апошняе ўваходжаньне элемэнту"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Вяртае індэкс першага/апошняга ўваходжаньня элемэнту ў сьпіс. Вяртае %1, калі элемэнт ня знойдзены."; -Blockly.Msg.LISTS_INLIST = "у сьпісе"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 пусты"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Вяртае значэньне ісьціна, калі сьпіс пусты."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "даўжыня %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Вяртае даўжыню сьпісу."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "стварыць сьпіс з элемэнту %1, які паўтараецца %2 разоў"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Стварае сьпіс, які ўтрымлівае пададзеную колькасьць копіяў элемэнту."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "як"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "уставіць у"; -Blockly.Msg.LISTS_SET_INDEX_SET = "усталяваць"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Устаўляе элемэнт у пачатак сьпісу."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Устаўляе элемэнт у пазначанай пазыцыі ў сьпісе."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Дадае элемэнт у канец сьпісу."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Выпадковым чынам устаўляе элемэнт у сьпіс."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Задае першы элемэнт у сьпісе."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Задае элемэнт у пазначанай пазыцыі ў сьпісе."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Задае апошні элемэнт у сьпісе."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Задае выпадковы элемэнт у сьпісе."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "па павелічэньні"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "па зьмяншэньні"; -Blockly.Msg.LISTS_SORT_TITLE = "сартаваць %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Сартаваць копію сьпісу."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "паводле альфабэту, ігнараваць рэгістар"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "як лікі"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "паводле альфабэту"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "стварыць сьпіс з тэксту"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "стварыць тэкст са сьпісу"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Аб’ядноўвае сьпіс тэкстаў у адзін тэкст па падзяляльніках."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Падзяліць тэкст у сьпіс тэкстаў, па падзяляльніках."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "з падзяляльнікам"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "хлусьня"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Вяртае «ісьціна» ці «хлусьня»."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "ісьціна"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://be-x-old.wikipedia.org/wiki/%D0%9D%D1%8F%D1%80%D0%BE%D1%9E%D0%BD%D0%B0%D1%81%D1%8C%D1%86%D1%8C"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Вяртае «ісьціна», калі абодва ўводы роўныя."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Вяртае «ісьціна», калі першы ўвод большы за другі."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Вяртае «ісьціна», калі першы ўвод большы ці роўны другому."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Вяртае «ісьціна», калі першы ўвод меншы за другі."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Вяртае «ісьціна», калі першы ўвод меншы ці роўны другому."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Вяртае «ісьціна», калі абодва ўводы ня роўныя."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "не %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Вяртае «ісьціна», калі ўвод непраўдзівы. Вяртае «хлусьня», калі ўвод праўдзівы."; -Blockly.Msg.LOGIC_NULL = "нічога"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Вяртае нічога."; -Blockly.Msg.LOGIC_OPERATION_AND = "і"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "ці"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Вяртае «ісьціна», калі абодва ўводы праўдзівыя."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Вяртае «ісьціна», калі прынамсі адзін з уводаў праўдзівы."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "тэст"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "калі хлусьня"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "калі ісьціна"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Праверыць умову ў 'тэст'. Калі ўмова праўдзівая, будзе вернутае значэньне «калі ісьціна»; інакш будзе вернутае «калі хлусьня»."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://be-x-old.wikipedia.org/wiki/%D0%90%D1%80%D1%8B%D1%82%D0%BC%D1%8D%D1%82%D1%8B%D0%BA%D0%B0"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Вяртае суму двух лікаў."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Вяртае дзель двух лікаў."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Вяртае рознасьць двух лікаў."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Вяртае здабытак двух лікаў."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Вяртае першы лік у ступені другога ліку."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "зьмяніць %1 на %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Дадае лічбу да зьменнай '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://be-x-old.wikipedia.org/wiki/%D0%9C%D0%B0%D1%82%D1%8D%D0%BC%D0%B0%D1%82%D1%8B%D1%87%D0%BD%D0%B0%D1%8F_%D0%BA%D0%B0%D0%BD%D1%81%D1%82%D0%B0%D0%BD%D1%82%D0%B0"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Вяртае адну з агульных канстантаў: π (3.141...), e (2.718...), φ (1.618...), sqrt(2) (1.414...), sqrt(½) (0,707...) або ∞ (бясконцасьць)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "абмежаваць %1 зьнізу %2 зьверху %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Абмяжоўвае колькасьць ніжняй і верхняй межамі (уключна)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "дзяліць на"; -Blockly.Msg.MATH_IS_EVEN = "парная"; -Blockly.Msg.MATH_IS_NEGATIVE = "адмоўная"; -Blockly.Msg.MATH_IS_ODD = "няпарная"; -Blockly.Msg.MATH_IS_POSITIVE = "станоўчая"; -Blockly.Msg.MATH_IS_PRIME = "простая"; -Blockly.Msg.MATH_IS_TOOLTIP = "Правярае, ці зьяўляецца лік парным, няпарным, простым, станоўчым, адмоўным, ці ён дзеліцца на пэўны лік без астатку. Вяртае значэньне ісьціна або няпраўда."; -Blockly.Msg.MATH_IS_WHOLE = "цэлая"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "рэшта дзяленьня %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Вяртае рэшту дзяленьня двух лікаў."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://be-x-old.wikipedia.org/wiki/%D0%9B%D1%96%D0%BA"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Лік."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "сярэдняя ў сьпісе"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "мінімальная ў сьпісе"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "мэдыяна сьпісу"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "мінімальная ў сьпісе"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "рэжымы сьпісу"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "выпадковы элемэнт сьпісу"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "стандартнае адхіленьне сьпісу"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "Сума сьпісу"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Вяртае сярэднеарытмэтычнае значэньне лікавых значэньняў у сьпісе."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Вяртае найменшы лік у сьпісе."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Вяртае мэдыяну сьпісу."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Вяртае найменшы лік у сьпісе."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Вяртае сьпіс самых распаўсюджаных элемэнтаў у сьпісе."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Вяртае выпадковы элемэнт сьпісу."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Вяртае стандартнае адхіленьне сьпісу."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Вяртае суму ўсіх лікаў у сьпісе."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "выпадковая дроб"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Вяртае выпадковую дроб у дыяпазоне ад 0,0 (уключна) да 1,0."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "выпадковая цэлая з %1 для %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Вяртае выпадковы цэлы лік паміж двума зададзенымі абмежаваньнямі ўключна."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "акругліць"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "акругліць да меншага"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "акругліць да большага"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Акругленьне ліку да большага ці меншага."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://be-x-old.wikipedia.org/wiki/%D0%9A%D0%B2%D0%B0%D0%B4%D1%80%D0%B0%D1%82%D0%BD%D1%8B_%D0%BA%D0%BE%D1%80%D0%B0%D0%BD%D1%8C"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "модуль"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "квадратны корань"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Вяртае модуль ліку."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Вяртае e ў ступені ліку."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Вяртае натуральны лягарытм ліку."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Вяртае дзесятковы лягарытм ліку."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Вяртае супрацьлеглы лік."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Вяртае 10 у ступені ліку."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Вяртае квадратны корань ліку."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://be-x-old.wikipedia.org/wiki/%D0%A2%D1%80%D1%8B%D0%B3%D0%B0%D0%BD%D0%B0%D0%BC%D1%8D%D1%82%D1%80%D1%8B%D1%8F#.D0.A2.D1.80.D1.8B.D0.B3.D0.B0.D0.BD.D0.B0.D0.BC.D1.8D.D1.82.D1.80.D1.8B.D1.87.D0.BD.D1.8B.D1.8F_.D1.84.D1.83.D0.BD.D0.BA.D1.86.D1.8B.D1.96"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Вяртае арккосынус ліку."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Вяртае арксынус ліку."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Вяртае арктангэнс ліку."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Вяртае косынус кута ў градусах."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Вяртае сынус кута ў градусах."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Вяртае тангэнс кута ў градусах."; -Blockly.Msg.NEW_VARIABLE = "Стварыць зьменную…"; -Blockly.Msg.NEW_VARIABLE_TITLE = "Імя новай зьменнай:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "дазволіць зацьвярджэньне"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "з:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Запусьціць функцыю вызначаную карыстальнікам '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Запусьціць функцыю вызначаную карыстальнікам '%1' і выкарыстаць яе вынік."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "з:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Стварыць '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Апішыце гэтую функцыю…"; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "зрабіць што-небудзь"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "да"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Стварае функцыю бяз выніку."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "вярнуць"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Стварае функцыю з вынікам."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Увага: гэтая функцыя мае парамэтры-дублікаты."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Падсьвяціць вызначэньне функцыі"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Калі значэньне ісьціна, вярнуць другое значэньне."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Папярэджаньне: гэты блёк можа выкарыстоўвацца толькі ў вызначанай функцыі."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "назва парамэтру:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Дадаць уваходныя парамэтры ў функцыю."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "парамэтры"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Дадаць, выдаліць ці запісаць чаргу ўваходных парамэтраў для гэтай функцыі."; -Blockly.Msg.REDO = "Паўтарыць"; -Blockly.Msg.REMOVE_COMMENT = "Выдаліць камэнтар"; -Blockly.Msg.RENAME_VARIABLE = "Перайменаваць зьменную…"; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Перайменаваць усе назвы зьменных '%1' на:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "дадаць тэкст"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "да"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Дадаць які-небудзь тэкст да зьменнай '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "да ніжняга рэгістру"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "Вялікія Першыя Літары"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "да ВЕРХНЯГА РЭГІСТРУ"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Вярнуць копію тэксту зь іншай велічынёй літар."; -Blockly.Msg.TEXT_CHARAT_FIRST = "узяць першую літару"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "узяць літару № з канца"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "узяць літару №"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "у тэксьце"; -Blockly.Msg.TEXT_CHARAT_LAST = "узяць апошнюю літару"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "узяць выпадковую літару"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Вяртае літару ў пазначанай пазыцыі."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Дадаць элемэнт да тэксту."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "далучыць"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Дадайце, выдаліце ці зьмяніце парадак разьдзелаў для перадачы тэкставага блёку."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "да літары № з канца"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "да літары №"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "да апошняй літары"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "у тэксьце"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "атрымаць падрадок зь першай літары"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "узяць падрадок зь літары № з канца"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "узяць падрадок зь літары №"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Вяртае пазначаную частку тэксту."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "у тэксьце"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "знайсьці першае ўваходжаньне тэксту"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "знайсьці апошняе ўваходжаньне тэксту"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Вяртае індэкс першага/апошняга ўваходжаньня першага тэксту ў другі тэкст. Вяртае %1, калі тэкст ня знойдзены."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 пусты"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Вяртае значэньне ісьціна, калі тэкст пусты."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "стварыць тэкст з"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Стварае фрагмэнт тэксту аб’яднаньнем любой колькасьці элемэнтаў."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "даўжыня %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Вяртае колькасьць літараў (у тым ліку прабелы) у пададзеным тэксьце."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "друкаваць %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Надрукаваць пазначаны тэкст, лічбу ці іншыя сымбалі."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Запытаць у карыстальніка лічбу."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Запытаць у карыстальніка тэкст."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "запытаць лічбу з падказкай"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "запытаць тэкст з падказкай"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Літара, слова ці радок тэксту."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "абрэзаць прабелы з абодвух бакоў"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "абрэзаць прабелы зь левага боку"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "абрэзаць прабелы з правага боку"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Вяртае копію тэксту з прабеламі, выдаленымі ад аднаго ці абодвух бакоў."; -Blockly.Msg.TODAY = "Сёньня"; -Blockly.Msg.UNDO = "Скасаваць"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "аб’ект"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Стварыць блёк «усталяваць %1»"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Вяртае значэньне гэтай зьменнай."; -Blockly.Msg.VARIABLES_SET = "усталяваць %1 да %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Стварыць блёк «атрымаць %1»"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Надаць гэтай зьменнай значэньне ўстаўкі."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "Зьменная з назвай «%1» ужо існуе."; -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/bg.js b/backend/_pv_1_3_5/static/blockly/msg/js/bg.js deleted file mode 100755 index 1681e1f80..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/bg.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.bg'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Добави коментар"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Промени стойността:"; -Blockly.Msg.CLEAN_UP = "Премахни блокове"; -Blockly.Msg.COLLAPSE_ALL = "Скрий блокове"; -Blockly.Msg.COLLAPSE_BLOCK = "Скрий блок"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "цвят 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "цвят 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "съотношение"; -Blockly.Msg.COLOUR_BLEND_TITLE = "смеси"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Смесва два цвят в дадено съотношение (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://bg.wikipedia.org/wiki/Цвят_(оптика)"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Избери цвят от палитрата."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "случаен цвят"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Избери цвят на случаен принцип."; -Blockly.Msg.COLOUR_RGB_BLUE = "син"; -Blockly.Msg.COLOUR_RGB_GREEN = "зелен"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "червен"; -Blockly.Msg.COLOUR_RGB_TITLE = "оцвети с"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Създай цвят с избраните пропорции, червено, зелено и синьо. Всички стойности трябва да бъдат от 0 до 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "прекъсни цикъла"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "премини към следващата стъпка от цикъла"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Прекъсни цикъла, в койте се съдержа тази команда."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Премини към следващата стъпка от цикъла"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Предупреждение: Този блок може да се използва само в цикъл."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "за всеки елемент %1 в списъка %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "За всеки елемент в списък присвои елемента на променливата '%1' и след това изпълни командите."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "преброй чрез %1 от %2 до %3 през %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Нека променлива \"%1\" премине през стойностите от началното до крайното число през зададената стъпка и изпълни избраните блокове."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Добави условие към \"ако\" блока."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Добави окончателено, прихващащо всичко останали случаи условие към \"ако\" блока."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Добави, премахни или пренареди частите, за да промениш този \"ако\" блок."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "иначе"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "иначе ако"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "ако"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Ако стойността е вярна, изпълни операциите."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Ако стойността е вярна, изпълни първия блок. Иначе, изпълни втория блок."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Ако първата стойност е вярна, изпълни първия блок. Иначе, ако втората стойност е вярна, изпълни втория блок."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Ако първата стойност е вярна, изпълни първия блок. В противен случай, ако втората стойност е вярна, изпълни втория блок. Ако нито една от стойностите не е вярна, изпълни последния блок."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://bg.wikipedia.org/wiki/Цикъл_(програмиране)#For_.D1.86.D0.B8.D0.BA.D1.8A.D0.BB.D1.8A.D1.82"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "изпълни"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "Повтори %1 пъти"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Изпълнява команди няколко пъти."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "повтаряй докато"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "повтаряй докато е вярно, че"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Докато стойността е лъжа, изпълнявай командите."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Докато стойността е истина, изпълнявай командите."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Изтриване на всички 1% блокове?"; -Blockly.Msg.DELETE_BLOCK = "Изтрий блок"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Изтрий %1 блока"; -Blockly.Msg.DISABLE_BLOCK = "Деактивирай блок"; -Blockly.Msg.DUPLICATE_BLOCK = "Копирай"; -Blockly.Msg.ENABLE_BLOCK = "Активирай блок"; -Blockly.Msg.EXPAND_ALL = "Покажи блокове"; -Blockly.Msg.EXPAND_BLOCK = "Покажи блок"; -Blockly.Msg.EXTERNAL_INPUTS = "Външни входове"; -Blockly.Msg.HELP = "Помощ"; -Blockly.Msg.INLINE_INPUTS = "Вътрешни входове"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "създай празен списък"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Връща списък с дължина 0, не съдържащ данни"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "списък"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Добави, премахни или пренареди частите, за да промениш този списъчен блок."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "създай списък с"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Добави елемент към текста."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Създай списък с произволен брой елементи."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "първия"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "№ от края"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "вземи"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "вземи и премахни"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "последния"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "произволен"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "премахни"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Връща първия елемент в списък."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Връща елемента на определената позиция в списък."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Връща последния елемент в списък."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Връща случаен елемент от списъка."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Премахва и връща първия елемент в списък."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Премахва и връща елемента на определена позиция в списък."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Премахва и връща последния елемент в списък."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Премахва и връща случаен елемент в списък."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Премахва първия елемент в списък."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Премахва елемент на определена позиция в списък."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Премахва последния елемент в списък."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Премахва случаен елемент от списък."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "до № открая"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "до #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "до края"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "вземи подсписък от първия"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "вземи подсписък от № от края"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "вземи подсписък от №"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Копира част от списък."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 е последният елемент."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 е първият елемент."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "намери първата поява на елемента"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "намери последната поява на елемента"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Връща индекса на първото/последното появяване на елемента в списъка. Връща %1 ако елементът не е намерен."; -Blockly.Msg.LISTS_INLIST = "в списъка"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 е празен"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Връща стойност вярно, ако списъкът е празен."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "дължината на %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Връща дължината на списък."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "създай списък от %1 повторен %2 пъти"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Създава списък, състоящ се от определен брой копия на елемента."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "следното"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "вмъкни на позиция"; -Blockly.Msg.LISTS_SET_INDEX_SET = "промени"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Вмъква елемент в началото на списъка."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Вмъква елемент на определена позиция в списък."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Добави елемент в края на списък."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Вмъква елемент на произволно място в списък."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Променя първия елемент в списък."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Променя елемента на определена позиция в списък."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Променя последния елемент в списък."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Променя случаен елемент от списък."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "възходящо"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "низходящо"; -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Подреди копие на списъка."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "по азбучен ред, без отчитане на малки и главни букви"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "в числов ред"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "по азбучен ред"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "Направи списък от текст"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "направи текст от списък"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Събира списък от текстове в един текст, раделени с разделител."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Разделя текст в списък на текстове, по всеки разделител."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "с разделител"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "невярно"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Връща вярно или невярно."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "вярно"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Върни вярно, ако двата параметъра са еднакви."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Върни истина, ако първия параметър е по-голям от втория."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Върни истина, ако първия параметър е по-голям или равен на втория."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Върни вярно, ако първия параметър е по-малък от втория."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Върни истина, ако първия параметър е по-малък или равен на втория."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Върни вярно, ако двата параметъра са различни."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "не %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Върни вярно, ако параметърът е неверен. Върни невярно, ако параметърът е верен."; -Blockly.Msg.LOGIC_NULL = "нула"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Връща нула."; -Blockly.Msg.LOGIC_OPERATION_AND = "и"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "или"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Върни вярно, ако и двата параметъра са верни."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Върни \"вярно\", ако поне един от входовете е верен."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "тест"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "Ако е невярно"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "Ако е вярно"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Провери исловието в \"тест\". Ако условието е истина, върни \"ако е истина\" стойността, иначе върни \"ако е лъжа\" стойността."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://bg.wikipedia.org/wiki/Аритметика"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Върни сумата на двете числа."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Върни частното на двете числа."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Върни разликата на двете числа."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Върни произведението на двете числа."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Върни първото число, повдигнато на степен на второто число."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://bg.wikipedia.org/wiki/Събиране"; -Blockly.Msg.MATH_CHANGE_TITLE = "промени %1 на %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Добави число към променлива '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "http://bg.wikipedia.org/wiki/Константа"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Връща една от често срещаните константи: π (3.141...), e (2.718...), φ (1.618...), sqrt(2) (1.414...), sqrt(½) (0.707...) или ∞ (безкрайност)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "ограничи %1 между %2 и %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Ограничи число да бъде в определените граници (включително)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "се дели на"; -Blockly.Msg.MATH_IS_EVEN = "е четно"; -Blockly.Msg.MATH_IS_NEGATIVE = "е отрицателно"; -Blockly.Msg.MATH_IS_ODD = "е нечетно"; -Blockly.Msg.MATH_IS_POSITIVE = "е положително"; -Blockly.Msg.MATH_IS_PRIME = "е просто"; -Blockly.Msg.MATH_IS_TOOLTIP = "Проверете дали дадено число е четно, нечетно, просто, цяло, положително, отрицателно или дали се дели на друго число. Връща истина или лъжа."; -Blockly.Msg.MATH_IS_WHOLE = "е цяло"; -Blockly.Msg.MATH_MODULO_HELPURL = "http://bg.wikipedia.org/wiki/Остатък"; -Blockly.Msg.MATH_MODULO_TITLE = "остатъка от делението на %1 на %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Върни остатъка от деление на две числа."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://bg.wikipedia.org/wiki/Число"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Число."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "средната стойност на числата в списъка"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "най-голямата стойност в списъка"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "медианата на списък"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "най-малката стойност в списъка"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "мода на списъка"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "случаен елемент от списъка"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "стандартно отклонение на списък"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "сумирай списъка"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Върни средната стойност (аритметичното средно) на числата в списъка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Върни най-голямото число в списъка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Върни медианата в списъка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Върни най-малкото число в списъка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Върни списък на най-често срещаните елементи в списъка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Върни случаен елемент от списъка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Връща стандартното отклонение на списъка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Върни сумата на всички числа в списъка."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://bg.wikipedia.org/wiki/Генератор_на_случайни_числа"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "случайно дробно число"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Върни случайно дробно число между 0.0 (включително) и 1.0 (без да го включва)"; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://bg.wikipedia.org/wiki/Генератор_на_случайни_числа"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "случайно цяло число между %1 и %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Върни случайно число в определените граници (включително)."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "закръгли"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "закръгли надолу"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "закръгли нагоре"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Закръгли число нагоре или надолу."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "абсолютна"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "корен квадратен"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Връща абсолютната стойност на число."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Върни е (неперовото число) на степен зададеното число."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Върни натуралния логаритъм от число."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Върни десетичния логаритъм на число."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Върни числото с обърнат знак."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Върни 10 на степен зададеното число."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Връща корен квадратен от число."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://bg.wikipedia.org/wiki/Тригонометрична_функция"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Върни аркускосинус от число."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Върни аркуссинус от число."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Върни аркустангенс от число."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Върни косинус от ъгъл в градуси (не в радиани)"; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Върни синус от ъгъл в градуси (не в радиани)"; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Върни тангенс от ъгъл в градуси (не в радиани)"; -Blockly.Msg.NEW_VARIABLE = "Нова променлива..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Ново име на променливата:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "позволи операциите"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "със:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://bg.wikipedia.org/wiki/Подпрограма"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Изпълни дефинирана от потребителя функция \"%1\"."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://bg.wikipedia.org/wiki/Подпрограма"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Изпълни дефинирана от потребителя функция \"%1\" и използвай резултата."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "със:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Създай '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Опишете тази функция..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "направиш"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "за да"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Създава функция, която не връща резултат."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "върни"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Създава функция, която връща резултат."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Предупреждение: Тази функция има дублиращи се параметри."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Покажи дефиницията на функцията"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Ако стойността е истина, върни втората стойност."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Предупреждение: Този блок може да се използва само във функция."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "име на параметър"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Добавяне на параметър към функцията."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "вход"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Добави, премахни или пренареди входните параметри за тази функция."; -Blockly.Msg.REDO = "Повторение"; -Blockly.Msg.REMOVE_COMMENT = "Премахни коментар"; -Blockly.Msg.RENAME_VARIABLE = "Преименувай променливата..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Преименувай всички '%1' променливи на:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "добави текста"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "към"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Добави текста към променливата \"%1\"."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "с малки букви"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "с Главна Буква На Всяка Дума"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "с ГЛАВНИ БУКВИ"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Връща копие на текста със сменени малки и главни букви."; -Blockly.Msg.TEXT_CHARAT_FIRST = "вземи първата буква"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "вземи поредна буква от края"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "вземи поредна буква"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "от текста"; -Blockly.Msg.TEXT_CHARAT_LAST = "вземи последната буква"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "вземи произволна буква"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Връща буквата в определена позиция."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Добави елемент към текста."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "свържи"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Добави, премахни или пренареди частите, за да промениш този текстов блок."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "со буква № (броено отзад-напред)"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "до буква №"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "со последната буква."; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "В текста"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "вземи текста от първата буква"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "вземи текста от буква № (броено отзад-напред)"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "вземи текста от буква №"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Връща определена част от текста."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "в текста"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "намери първата поява на текста"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "намери последната поява на текста"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Връща индекса на първото/последното срещане на първия текст във втория текст. Връща %1, ако текстът не е намерен."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 е празен"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Връща истина, ако текста е празен."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "създай текст с"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Създай текст като съчетаеш няколко елемента."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "дължината на %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Връща броя на символите (включително и интервалите) в текста."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "отпечатай %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Отпечатай текста, числото или друга стойност."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Питай потребителя за число."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Питай потребителя за текст."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "питай за число със съобщение"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "питай за текст със съобщение"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://bg.wikipedia.org/wiki/Низ"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Буква, дума или ред"; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "премахни интервалите от двете страни"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "премахни интервалите отляво"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "премахни интервалите отдясно"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Върни копие на текста с пемахнати интервали от диния или двата края."; -Blockly.Msg.TODAY = "Днес"; -Blockly.Msg.UNDO = "Отмяна"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "елемент"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Създай \"промени стойността на %1\""; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Връща стойността на тази променлива."; -Blockly.Msg.VARIABLES_SET = "нека %1 бъде %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Създай \"вземи стойността на %1\""; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Задава тази променлива да бъде равен на входа."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/bn.js b/backend/_pv_1_3_5/static/blockly/msg/js/bn.js deleted file mode 100755 index 739407ddd..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/bn.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.bn'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "মন্তব্য যোগ করুন"; -Blockly.Msg.CHANGE_VALUE_TITLE = "মান পরিবর্তন করুন:"; -Blockly.Msg.CLEAN_UP = "Clean up Blocks"; // untranslated -Blockly.Msg.COLLAPSE_ALL = "Collapse Blocks"; // untranslated -Blockly.Msg.COLLAPSE_BLOCK = "Collapse Block"; // untranslated -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "রং ১"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "রং ২"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "অনুপাত"; -Blockly.Msg.COLOUR_BLEND_TITLE = "মিশ্রণ"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "প্রদত্ত অনুপাত(০.০ - ১.০) অনুসারে দুটি রং একসাথে মিশ্রিত করুন।"; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Color"; // untranslated -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "প্যালেট থেকে একটি রং পছন্দ করুন"; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "এলোমেলো রং"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "এলোমেলোভাবে একটি রং পছন্দ করুন।"; -Blockly.Msg.COLOUR_RGB_BLUE = "নীল"; -Blockly.Msg.COLOUR_RGB_GREEN = "সবুজ"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "লাল"; -Blockly.Msg.COLOUR_RGB_TITLE = "রং সহ"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "একটি রং তৈরি করুন নির্দিষ্ট পরিমাণে লাল, সবুজ এবং নীল রং মিশ্রিত করে। প্রত্যেকটির মান অবশ্যই ০ থেকে ১০০ এর মধ্যে হতে হবে।"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "break out of loop"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "continue with next iteration of loop"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Break out of the containing loop."; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Skip the rest of this loop, and continue with the next iteration."; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "সর্তকীবার্তা: এই ব্লকটি শুধুমাত্র লুপের মধ্যে ব্যবহার করা যাবে।"; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "প্রত্যেকটি পদের জন্য %1 তালিকার মধ্যে %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "For each item in a list, set the variable '%1' to the item, and then do some statements."; // untranslated -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "গণনা কর %1 %4 দিয়ে %2 থেকে %3"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Have the variable '%1' take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks."; // untranslated -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "যদি নামক ব্লক এ একটি শর্ত যোগ করুন।"; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Add a final, catch-all condition to the if block."; // untranslated -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Add, remove, or reorder sections to reconfigure this if block."; // untranslated -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "নতুবা"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "নতুবা যদি"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "যদি"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "If a value is true, then do some statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "If a value is true, then do the first block of statements. Otherwise, do the second block of statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements."; // untranslated -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; // untranslated -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "করুন"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "%1 বার পুনরাবৃত্তি করো"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Do some statements several times."; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "repeat until"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "repeat while"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "While a value is false, then do some statements."; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "While a value is true, then do some statements."; // untranslated -Blockly.Msg.DELETE_ALL_BLOCKS = "Delete all %1 blocks?"; // untranslated -Blockly.Msg.DELETE_BLOCK = "ব্লকটি মুছে ফেল"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "%1 ব্লক অপসারণ কর"; -Blockly.Msg.DISABLE_BLOCK = "ব্লকটি বিকল কর"; -Blockly.Msg.DUPLICATE_BLOCK = "প্রতিলিপি"; -Blockly.Msg.ENABLE_BLOCK = "ব্লকটি সচল কর"; -Blockly.Msg.EXPAND_ALL = "ব্লকগুলো সম্প্রসারিত কর"; -Blockly.Msg.EXPAND_BLOCK = "ব্লকটি সম্প্রসারিত কর"; -Blockly.Msg.EXTERNAL_INPUTS = "বহি:স্থ ইনপুট"; -Blockly.Msg.HELP = "সাহায্য"; -Blockly.Msg.INLINE_INPUTS = "সারি ইনপুট"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "খালি তালিকা তৈরি করুন"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "পাঠাবে একটি তালিকা, দের্ঘ্য হবে ০, কোন উপাত্ত থাকবে না"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "তালিকা"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Add, remove, or reorder sections to reconfigure this list block."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "create list with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "তালিকায় একটি পদ যোগ করুন।"; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "যেকোন সংখ্যক পদ নিয়ে একটি তালিকা তৈরি করুন।"; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "প্রথম"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# শেষ থেকে"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "নিন"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "নিন ও সরান"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "শেষ"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "এলোমেলো"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "অপসারণ"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "তালিকার প্রথম পদটি পাঠাবে।"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "তালিকার শেষ পদটি পাঠাবে।"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "এলোমেলোভাবে তালিকার যেকোন একটি পদ পাঠাবে।"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "অপসারণ করুন এবং তালিকার প্রথম পদটি পাঠান।"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Removes and returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "অপসারণ করুন এবং তালিকার শেষ পদটি পাঠান।"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "অপসারণ করুন এবং তালিকার এলোমেলো একটি পদ পাঠান।"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "তালিকার প্রথম পদটি অপসারণ করা হয়েছে।"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Removes the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "তালিকার শেষ পদটি অপসারণ করা হয়েছে।"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "তালিকা থেকে এলোমেলো একটি পদ অপসারণ করা হয়েছে।"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "to # from end"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "to #"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "to last"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "get sub-list from first"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "get sub-list from # from end"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "get sub-list from #"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Creates a copy of the specified portion of a list."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 is the last item."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 is the first item."; // untranslated -Blockly.Msg.LISTS_INDEX_OF_FIRST = "আইটেমের প্রথম সংঘটন খুঁজুন"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "আইটেমের শেষ সংঘটন খুঁজুন"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Returns the index of the first/last occurrence of the item in the list. Returns %1 if item is not found."; // untranslated -Blockly.Msg.LISTS_INLIST = "তালিকার মধ্যে"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 খালি"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "পাঠাবে সত্য যদি তালিকাটি খালি হয়।"; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "%1-এর দৈর্ঘ্য"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "একটি তালিকার দৈর্ঘ্য পাঠাবে।"; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "create list with item %1 repeated %2 times"; // untranslated -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Creates a list consisting of the given value repeated the specified number of times."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "as"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INSERT = "insert at"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_SET = "set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserts the item at the start of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Inserts the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Append the item to the end of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Inserts the item randomly in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Sets the first item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Sets the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Sets the last item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Sets a random item in a list."; // untranslated -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "লিখা থেকে তালিকা তৈরি করুন"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "তালিকা থেকে লিখা তৈরি করুন"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "মিথ্যা"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "পাঠাবে হয় সত্য অথবা মিথ্যা।"; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "সত্য"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "পাঠাবে সত্য যদি উভয় ইনপুটই সমান হয়।"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "পাঠাবে সত্য যদি প্রথম ইনপুট দ্বিতীয় ইনপুট থেকে বড় হয়।"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "পাঠাবে সত্য যদি প্রথম ইনপুট দ্বিতীয় ইনপুট থেকে বড় অথবা সমান হয়।"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "পাঠাবে সত্য যদি প্রথম ইনপুট দ্বিতীয় ইনপুট থেকে ছোট হয়।"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "পাঠাবে সত্য যদি প্রথম ইনপুট দ্বিতীয় ইনপুট থেকে ছোট অথবা সমান হয়।"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "পাঠাবে সত্য যদি উভয় ইনপুটই সমান না হয়।"; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "%1 নয়"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "পাঠাবে সত্য যদি ইনপুট মিথ্যা হয়। পাঠাবে মিথ্যা যদি ইনপুট সত্য হয়।"; -Blockly.Msg.LOGIC_NULL = "কিছু না"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "কিছু ফেরত দিবে না।"; -Blockly.Msg.LOGIC_OPERATION_AND = "এবং"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "অথবা"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "পাঠাবে সত্য যদি উভয় ইনপুটই সত্য হয়।"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "পাঠাবে সত্য যদি অন্ততপক্ষে যেকোন একটি ইনপুট সত্য হয়।"; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "পরীক্ষা"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "যদি মিথ্যা হয়"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "যদি সত্য হয়"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value."; // untranslated -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Arithmetic"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "পাঠাবে দুটি সংখ্যার যোগফল।"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "পাঠাবে দুটি সংখ্যার ভাগফল।"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "পাঠাবে দুটি সংখ্যার বিয়োগফল।"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "পাঠাবে দুটি সংখ্যার গুণফল।"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Return the first number raised to the power of the second number."; // untranslated -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; // untranslated -Blockly.Msg.MATH_CHANGE_TITLE = "%2 দ্বারা %1 পরিবর্তন"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Add a number to variable '%1'."; // untranslated -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; // untranslated -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; // untranslated -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "constrain %1 low %2 high %3"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Constrain a number to be between the specified limits (inclusive)."; // untranslated -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "দ্বারা বিভাজ্য"; -Blockly.Msg.MATH_IS_EVEN = "জোড় সংখ্যা"; -Blockly.Msg.MATH_IS_NEGATIVE = "নেতিবাচক"; -Blockly.Msg.MATH_IS_ODD = "বিজোড় সংখ্যা"; -Blockly.Msg.MATH_IS_POSITIVE = "ইতিবাচক"; -Blockly.Msg.MATH_IS_PRIME = "মৌলিক সংখ্যা"; -Blockly.Msg.MATH_IS_TOOLTIP = "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false."; // untranslated -Blockly.Msg.MATH_IS_WHOLE = "is whole"; // untranslated -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; // untranslated -Blockly.Msg.MATH_MODULO_TITLE = "%1 ÷ %2 এর ভাগশেষ"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Return the remainder from dividing the two numbers."; // untranslated -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://bn.wikipedia.org/wiki/সংখ্যা"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "একটি সংখ্যা।"; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "তালিকার গড়"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "তালিকার মধ্যে সর্বোচ্চ"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "তালিকার মধ্যমা"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "তালিকার মধ্যে সর্বনিম্ন"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "modes of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "তালিকার এলোমেলো পদ"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "standard deviation of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "তালিকার যোগফল"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "পাঠাবে তালিকার সব সংখ্যার গড়।"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "তালিকার মধ্যে সর্বোচ্চ সংখ্যাটি পাঠাও"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "তালিকার মধ্যমা সংখ্যাটি পাঠাবে।"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "তালিকার মধ্যে সর্বনিম্ন সংখ্যাটি পাঠাও"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Return a list of the most common item(s) in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "তালিকা থেকে এলোমেলোভাবে একটি পদ পাঠাবে।"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Return the standard deviation of the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "পাঠাবে তালিকার সব সংখ্যার যোগফল।"; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "এলোমেলো ভগ্নাংশ"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive)."; // untranslated -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TITLE = "random integer from %1 to %2"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Return a random integer between the two specified limits, inclusive."; // untranslated -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; // untranslated -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "round"; // untranslated -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "round down"; // untranslated -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "round up"; // untranslated -Blockly.Msg.MATH_ROUND_TOOLTIP = "Round a number up or down."; // untranslated -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; // untranslated -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "পরম"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "বর্গমূল"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "পাঠাবে সংখ্যার পরমমান।"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Return e to the power of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Return the natural logarithm of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Return the base 10 logarithm of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Return the negation of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Return 10 to the power of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "পাঠাবে একটি সংখ্যার বর্গমূল।"; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; // untranslated -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Return the arccosine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Return the arcsine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Return the arctangent of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Return the cosine of a degree (not radian)."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Return the sine of a degree (not radian)."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Return the tangent of a degree (not radian)."; // untranslated -Blockly.Msg.NEW_VARIABLE = "নতুন চলক..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "নতুন চলকের নাম:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "allow statements"; // untranslated -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "with:"; // untranslated -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Run the user-defined function '%1'."; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Run the user-defined function '%1' and use its output."; // untranslated -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "with:"; // untranslated -Blockly.Msg.PROCEDURES_CREATE_DO = "Create '%1'"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "do something"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "এতে"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "আউটপুট ছাড়া একটি ক্রিয়া তৈরি করুন।"; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "পাঠাবে"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "আউটপুট সহ একটি ক্রিয়া তৈরি করুন।"; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Warning: This function has duplicate parameters."; // untranslated -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "ক্রিয়ার সংজ্ঞা উজ্জল করুন"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "যদি মান সত্য হয় তাহলে দ্বিতীয় মান পাঠাবে।"; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Warning: This block may be used only within a function definition."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "ইনপুটের নাম:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "ক্রিয়াতে একটি ইনপুট যোগ করুন।"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "inputs"; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Add, remove, or reorder inputs to this function."; // untranslated -Blockly.Msg.REDO = "পুনরায় করুন"; -Blockly.Msg.REMOVE_COMMENT = "মন্তব্য সরাও"; -Blockly.Msg.RENAME_VARIABLE = "চলকের নাম পরিবর্তন..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Rename all '%1' variables to:"; // untranslated -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "append text"; // untranslated -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "এতে"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Append some text to variable '%1'."; // untranslated -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "ছোটহাতের অক্ষরে"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "to Title Case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "বড়হাতের অক্ষরে"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; // untranslated -Blockly.Msg.TEXT_CHARAT_FIRST = "get first letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_FROM_END = "get letter # from end"; // untranslated -Blockly.Msg.TEXT_CHARAT_FROM_START = "get letter #"; // untranslated -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "in text"; // untranslated -Blockly.Msg.TEXT_CHARAT_LAST = "get last letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_RANDOM = "get random letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Returns the letter at the specified position."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "লেখাটিতে একটি পদ যোগ করুন।"; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "যোগ"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Add, remove, or reorder sections to reconfigure this text block."; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "to letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "to letter #"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "to last letter"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "in text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "get substring from first letter"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "get substring from letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "get substring from letter #"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returns a specified portion of the text."; // untranslated -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "in text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "find first occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "find last occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found."; // untranslated -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 খালি"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "পাঠাবে সত্য যদি সরবরাহকৃত লেখাটি খালি হয়।"; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "create text with"; // untranslated -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Create a piece of text by joining together any number of items."; // untranslated -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "%1-এর দৈর্ঘ্য"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Returns the number of letters (including spaces) in the provided text."; // untranslated -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "%1 মুদ্রণ করুন"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Print the specified text, number or other value."; // untranslated -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Prompt for user for a number."; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Prompt for user for some text."; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "prompt for number with message"; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "prompt for text with message"; // untranslated -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; // untranslated -Blockly.Msg.TEXT_TEXT_TOOLTIP = "একটি অক্ষর, শব্দ অথবা বাক্য।"; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "উভয় পাশ থেকে খালি অংশ ছাটাই"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "বামপাশ থেকে খালি অংশ ছাটাই"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "ডানপাশ থেকে খালি অংশ ছাটাই"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Return a copy of the text with spaces removed from one or both ends."; // untranslated -Blockly.Msg.TODAY = "আজ"; -Blockly.Msg.UNDO = "পূর্বাবস্থা"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "পদ"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Create 'set %1'"; // untranslated -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returns the value of this variable."; // untranslated -Blockly.Msg.VARIABLES_SET = "set %1 to %2"; // untranslated -Blockly.Msg.VARIABLES_SET_CREATE_GET = "'%1 নিন' তৈরি করুন"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Sets this variable to be equal to the input."; // untranslated -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/br.js b/backend/_pv_1_3_5/static/blockly/msg/js/br.js deleted file mode 100755 index 00a952a17..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/br.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.br'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Ouzhpennañ un evezhiadenn"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Kemmañ an dalvoudenn :"; -Blockly.Msg.CLEAN_UP = "Naetaat ar bloc'hoù"; -Blockly.Msg.COLLAPSE_ALL = "Bihanaat ar bloc'hoù"; -Blockly.Msg.COLLAPSE_BLOCK = "Bihanaat ar bloc'h"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "liv 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "liv 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "feur"; -Blockly.Msg.COLOUR_BLEND_TITLE = "meskañ"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "a gemmesk daou liv gant ur feur roet(0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "http://br.wikipedia.org/wiki/Liv"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Dibab ul liv diwar al livaoueg."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "liv dargouezhek"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Tennañ ul liv d'ar sord"; -Blockly.Msg.COLOUR_RGB_BLUE = "glas"; -Blockly.Msg.COLOUR_RGB_GREEN = "gwer"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "ruz"; -Blockly.Msg.COLOUR_RGB_TITLE = "liv gant"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Krouiñ ul liv gant ar c'hementad spisaet a ruz, a wer hag a c'hlas. Etre 0 ha 100 e tle bezañ an holl dalvoudoù."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "Mont e-maez an adlañsañ"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "Kenderc'hel gant iteradur nevez ar rodell"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Mont e-maez ar boukl engronnus."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Lammat ar rest eus ar rodell, ha kenderc'hel gant an iteradur war-lerc'h."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Diwallit : ne c'hall ar bloc'h-mañ bezañ implijet nemet e-barzh ur boukl."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "evit pep elfenn %1 er roll %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Evit pep elfenn en ur roll, reiñ talvoud an elfenn d'an argemmenn '%1', ha seveniñ urzhioù zo da c'houde."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "kontañ gant %1 eus %2 da %3 dre %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Ober e doare ma kemero an argemmenn \"%1\" an talvoudennoù adalek niverenn an deroù betek niverenn an dibenn, en ur inkremantiñ an esaouenn, ha seveniñ an urzhioù spisaet."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Ouzhpennañ un amplegad d'ar bloc'h ma."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Ouzhpennañ un amplegad dibenn lak-pep-tra d'ar bloc'h ma."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Ouzhpennañ, lemel pe adurzhiañ ar rannoù evit kefluniañ ar bloc'h ma."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "a-hend-all"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "mod all ma"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "ma"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Ma vez gwir un dalvoudenn, seveniñ urzhioù zo neuze."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Ma vez gwir un dalvoudenn, seveniñ ar c'henañ bloc'had urzhioù neuze. Anez seveniñ an eil bloc'had urzhioù."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Ma vez gwir an dalvoudenn gentañ, seveniñ ar c'hentañ bloc'had urzhioù neuze. Anez ma vez gwir an eil talvoudenn, seveniñ an eil bloc'had urzhioù."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Ma vez gwir an dalvoudenn gentañ, seveniñ ar c'hentañ bloc'had. Anez, ma vez gwir an eil talvoudenn, seveniñ an eil bloc'had urzhioù. Ma ne vez gwir talvoudenn ebet, seveniñ ar bloc'had diwezhañ a urzhioù."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "ober"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "adober %1 gwech"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Seveniñ urzhioù zo meur a wech"; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "adober betek"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "adober keit ha ma"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Keit ha ma vez faos un dalvoudenn,seveniñ urzhioù zo neuze."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Keit ha ma vez gwir un dalvoudenn, seveniñ urzhioù zo neuze."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Diverkañ an holl vloc'hoù %1 ?"; -Blockly.Msg.DELETE_BLOCK = "Dilemel ar bloc'h"; -Blockly.Msg.DELETE_VARIABLE = "Lemel an argemm '%1'"; -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Lemel %1 implij eus an argemm '%2' ?"; -Blockly.Msg.DELETE_X_BLOCKS = "Dilemel %1 bloc'h"; -Blockly.Msg.DISABLE_BLOCK = "Diweredekaat ar bloc'h"; -Blockly.Msg.DUPLICATE_BLOCK = "Eiladuriñ"; -Blockly.Msg.ENABLE_BLOCK = "Gweredekaat ar bloc'h"; -Blockly.Msg.EXPAND_ALL = "Astenn ar bloc'hoù"; -Blockly.Msg.EXPAND_BLOCK = "Astenn ar bloc'h"; -Blockly.Msg.EXTERNAL_INPUTS = "Monedoù diavaez"; -Blockly.Msg.HELP = "Skoazell"; -Blockly.Msg.INLINE_INPUTS = "Monedoù enlinenn"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "krouiñ ur roll goullo"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Distreiñ ul listenn, 0 a hirder, n'eus enrolladenn ebet enni"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "roll"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Ouzhpennañ, lemel pe adurzhiañ ar rannoù evit kefluniañ ar bloc'h listenn-mañ."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "krouiñ ur roll gant"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Ouzhpennañ un elfenn d'ar roll"; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Krouiñ ur roll gant un niver bennak a elfennoù."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "kentañ"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# adalek ar fin"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "tapout"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "tapout ha lemel"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "diwezhañ"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "dre zegouezh"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "lemel"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Distreiñ an elfenn gentañ en ul listenn."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Distreiñ an elfenn el lec'h meneget en ul listenn."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Distreiñ un elfenn diwezhañ en ul listenn."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Distreiñ un elfenn dre zegouezh en ul listenn."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Lemel ha distreiñ a ra an elfenn gentañ en ul listenn."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Lemel ha distreiñ a ra an elfenn el lec'h meneget en ul listenn."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Lemel ha distreiñ a ra an elfenn diwezhañ en ul listenn."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Lemel ha distreiñ a ra an elfenn dre zegouezh en ul listenn."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Lemel a ra an elfenn gentañ en ul listenn."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Lemel a ra an elfenn el lec'h meneget en ul listenn."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Distreiñ a ra an elfenn diwezhañ en ul listenn."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Lemel a ra un elfenn dre zegouezh en ul listenn."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "betek # adalek an dibenn"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "da #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "betek ar fin"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "Kaout an islistenn adalek an deroù"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "Kaout an islistenn adalek # adalek an dibenn"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "Kaout an islistenn adalek #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Krouiñ un eilad eus lodenn spisaet ul listenn."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 eo an elfenn gentañ."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 eo an elfenn gentañ."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "kavout reveziadenn gentañ un elfenn"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "kavout reveziadenn diwezhañ un elfenn"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Distreiñ meneger ar c'hentañ/an eil reveziadenn eus an elfenn en ul listenn. Distreiñ %1 ma n'eo ket kavet an destenn."; -Blockly.Msg.LISTS_INLIST = "el listenn"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 zo goullo"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Distreiñ gwir m'eo goullo al listenn."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "hirder %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Distreiñ hirder ul listenn."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "Krouiñ ul listenn gant an elfenn %1 arreet div wech"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Krouiñ ul listenn a c'hoarvez eus an dalvoudenn roet arreet an niver a wech meneget"; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "evel"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "ensoc'hañ evel"; -Blockly.Msg.LISTS_SET_INDEX_SET = "termenañ"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Ensoc'hañ a ra an elfenn e deroù ul listenn."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Ensoc'hañ a ra an elfenn el lec'h meneget en ul listenn."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Ouzhpennañ a ra an elfenn e fin al listenn."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Ensoc'hañ a ra an elfenn dre zegouezh en ul listenn."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Termenañ a ra an elfenn gentañ en ul listenn."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Termenañ a ra an elfenn el lec'h meneget en ul listenn."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Termenañ a ra an elfenn diwezhañ en ul listenn."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Termenañ a ra un elfenn dre zegouezh en ul listenn."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "war gresk"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "war zigresk"; -Blockly.Msg.LISTS_SORT_TITLE = "Rummañ%1,%2,%3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Rummañ un eilenn eus ar roll"; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "Dre urzh al lizherenneg, hep derc'hel kont eus an direnneg"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "niverel"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "Dre urzh al lizherenneg"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "Krouiñ ul listenn diwar an destenn"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "Krouiñ un destenn diwar al listenn"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Bodañ ul listennad testennoù en ul listenn hepken, o tispartiañ anezho gant un dispartier."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Troc'hañ un destenn en ul listennad testennoù, o troc'hañ e pep dispartier."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "gant an dispartier"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "gaou"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Distreiñ pe gwir pe faos"; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "gwir"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Distreiñ gwir m'eo par an daou voned."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Distreiñ gwir m'eo brasoc'h ar moned kentañ eget an eil."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Distreiñ gwir m'eo brasoc'h ar moned kentañ eget an eil pe par dezhañ."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Distreiñ gwir m'eo bihanoc'h ar moned kentañ eget an eil."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Distreiñ gwir m'eo bihanoc'h ar moned kentañ eget an eil pe m'eo par dezhañ."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Distreiñ gwir ma n'eo ket par an daou voned."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "nann %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Distreiñ gwir m'eo faos ar moned. Distreiñ faos m'eo gwir ar moned."; -Blockly.Msg.LOGIC_NULL = "Null"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Distreiñ null."; -Blockly.Msg.LOGIC_OPERATION_AND = "ha(g)"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "pe"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Distreiñ gwir m'eo gwir an da daou voned."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Distreiñ gwir m'eo gwir unan eus an daou voned da nebeutañ."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "amprouad"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "m'eo gaou"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "m'eo gwir"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Gwiriañ an amplegad e 'prouad'. M'eo gwir an amplegad, distreiñ an dalvoudenn 'm'eo gwir'; anez distreiñ ar moned 'm'eo faos'."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://br.wikipedia.org/wiki/Aritmetik"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Distreiñ sammad daou niver."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Distreiñ rannad daou niver."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Distreiñ diforc'h daou niver"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Distreiñ liesad daou niver."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Distreiñ an niver kentañ lakaet dindan gallouter an eil niver."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "kemmañ %1 gant %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Ouzhpennañ un niver d'an argemm '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Distreiñ unan eus digemmennoù red : π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (anvevenn)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "destrizhañ %1 etre %2 ha %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Destrizhañ un niver da vezañ etre ar bevennoù spisaet (enlakaet)"; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "a zo rannadus dre"; -Blockly.Msg.MATH_IS_EVEN = "zo par"; -Blockly.Msg.MATH_IS_NEGATIVE = "a zo negativel"; -Blockly.Msg.MATH_IS_ODD = "zo ampar"; -Blockly.Msg.MATH_IS_POSITIVE = "a zo pozitivel"; -Blockly.Msg.MATH_IS_PRIME = "zo kentañ"; -Blockly.Msg.MATH_IS_TOOLTIP = "Gwiriañ m'eo par, anpar, kentañ, muiel, leiel un niverenn pe ma c'haller rannañ anezhi dre un niver roet zo. Distreiñ gwir pe faos."; -Blockly.Msg.MATH_IS_WHOLE = "zo anterin"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "rest eus %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Distreiñ dilerc'h rannadur an div niver"; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://br.wikipedia.org/wiki/Niver"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Un niver."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "Keitat al listenn"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "Uc'hegenn al listenn"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "Kreizad al listenn"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "Izegenn al listenn"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "modoù stankañ el listenn"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "Elfennn eus al listenn tennet d'ar sord"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "forc'had standart eus al listenn"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "Sammad al listenn"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Distreiñ keitad (niveroniel) an talvoudennoù niverel el listenn."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Distreiñ an niver brasañ el listenn."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Distreiñ an niver kreiz el listenn"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Distreiñ an niver bihanañ el listenn"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Distreiñ ul listennad elfennoù stankoc'h el listenn."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Distreiñ un elfenn zargouezhek el listenn"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Distreiñ forc'had standart al listenn."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Distreiñ sammad an holl niveroù zo el listenn."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "Rann dargouezhek"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Distreiñ ur rann dargouezhek etre 0.0 (enkaelat) hag 1.0 (ezkaelat)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "anterin dargouezhek etre %1 ha %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Distreiñ un anterin dargouezhek etre an div vevenn spisaet, endalc'het."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "Rontaat"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "Rontaat dindan"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "Rontaat a-us"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Rontaat un niver dindan pe a-us"; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://br.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "dizave"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "gwrizienn garrez"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Distreiñ talvoud dizave un niver."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Distreiñ galloudad un niver."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Distreiñ logaritm naturel un niver"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Distreiñ logaritm diazez 10 un niver"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Distreiñ enebad un niver"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Distreiñ 10 da c'halloudad un niver."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Distreiñ gwrizienn garrez un niver"; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://br.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Distreiñ ark kosinuz un niver"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Distreiñ ark sinuz un niver"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Distreiñ ark tangent un niver"; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Distreiñ kosinuz ur c'horn (ket e radianoù)"; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Distreiñ sinuz ur c'horn (ket e radianoù)"; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Distreiñ tangent ur c'horn (ket e radianoù)."; -Blockly.Msg.NEW_VARIABLE = "Krouiñ un argemm nevez..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Anv an argemmenn nevez :"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "aotren an disklêriadurioù"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "gant :"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Seveniñ an arc'hwel '%1' termenet gant an implijer."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Seveniñ an arc'hwel '%1' termenet gant an implijer hag implijout e zisoc'h."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "gant :"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Krouiñ '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Deskrivañ an arc'hwel-mañ..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "ober un dra bennak"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "da"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Krouiñ un arc'hwel hep mont er-maez."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "distreiñ"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Kouiñ un arc'hwel gant ur mont er-maez"; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Diwallit : an arc'hwel-mañ en deus arventennoù eiladet."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Dreislinennañ termenadur an arc'hwel"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Ma'z eo gwir un dalvoudenn, distreiñ un eil talvoudenn neuze."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Diwallit : Gallout a rafe ar bloc'h bezañ implijet e termenadur un arc'hwel hepken."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "Anv ar moned"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Ouzhpennañ ur moned d'an arc'hwel."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "Monedoù"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Ouzhpennañ, lemel, pe adkempenn monedoù an arc'hwel-mañ."; -Blockly.Msg.REDO = "Adober"; -Blockly.Msg.REMOVE_COMMENT = "Lemel an evezhiadenn kuit"; -Blockly.Msg.RENAME_VARIABLE = "Adenvel an argemmenn..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Adenvel an holl argemmennoù '%1' e :"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "ouzhpennañ an destenn"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "da"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Ouzhpennañ testenn d'an argemmenn'%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "e lizherennoù bihan"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "Gant Ur Bennlizherenn E Deroù Pep Ger"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "e PENNLIZHERENNOÙ"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Distreiñ un eilenn eus an eilenn en un direnneg all"; -Blockly.Msg.TEXT_CHARAT_FIRST = "tapout al lizherenn gentañ"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "Kaout al lizherenn # adalek an dibenn."; -Blockly.Msg.TEXT_CHARAT_FROM_START = "Kaout al lizherenn #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "en destenn"; -Blockly.Msg.TEXT_CHARAT_LAST = "tapout al lizherenn ziwezhañ"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "Kaout ul lizherenn dre zegouezh"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Distreiñ al lizherenn d'al lec'h spisaet."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Ouzhpennañ un elfenn d'an destenn."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "stagañ"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Ouzhpennañ, lemel pe adurzhiañ ar rannoù evit kefluniañ ar bloc'h testenn-mañ."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "Betek al lizherenn # adalek an dibenn."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "betek al lizherenn #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "d'al lizherenn diwezhañ"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "en destenn"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "Kaout an ischadenn adalek al lizherenn gentañ"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "Kaout an ischadenn adalek al lizherenn # betek an dibenn"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "Kaout an ischadenn adalek al lizherenn #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Distreiñ un tamm spisaet eus an destenn."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "en destenn"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "kavout reveziadenn gentañ an destenn"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "kavout reveziadenn diwezhañ an destenn"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Distreiñ meneger ar c'hentañ/an eil reveziadenn eus ar chadenn gentañ en eil chadenn. Distreiñ %1 ma n'eo ket kavet ar chadenn."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 zo goullo"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Adkas gwir m'eo goullo an destenn roet."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "krouiñ un destenn gant"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Krouit un tamm testenn en ur gevelstrollañ un niver bennak a elfennoù"; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "hirder %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Distreiñ an niver a lizherennoù(en ur gontañ an esaouennoù e-barzh) en destenn roet."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "moullañ %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Moullañ an destenn, an niverenn pe un dalvoudenn spisaet all"; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Goulenn un niver gant an implijer."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Goulenn un destenn gant an implijer."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "pedadenn evit un niver gant ur c'hemennad"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "pedadenn evit un destenn gant ur c'hemennad"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Ul lizherenn, ur ger pe ul linennad testenn."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "Lemel an esaouennoù en daou du"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "Lemel an esaouennoù eus an tu kleiz"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "Lemel an esaouennoù eus an tu dehou"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Distreiñ un eilenn eus an destenn gant an esaouennoù lamet eus un tu pe eus an daou du"; -Blockly.Msg.TODAY = "Hiziv"; -Blockly.Msg.UNDO = "Dizober"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "elfenn"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Krouiñ 'termenañ %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Distreiñ talvoud an argemm-mañ."; -Blockly.Msg.VARIABLES_SET = "termenañ %1 da %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Krouiñ 'kaout %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Termenañ a ra argemm-mañ evit ma vo par da dalvoudenn ar moned."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "Un argemm anvet '%1' zo anezhañ dija."; -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/ca.js b/backend/_pv_1_3_5/static/blockly/msg/js/ca.js deleted file mode 100755 index 7bd6ef6c0..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/ca.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.ca'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Afegeix un comentari"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Canvia valor:"; -Blockly.Msg.CLEAN_UP = "Clean up Blocks"; // untranslated -Blockly.Msg.COLLAPSE_ALL = "Contraure blocs"; -Blockly.Msg.COLLAPSE_BLOCK = "Contraure bloc"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "color 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "color 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "proporció"; -Blockly.Msg.COLOUR_BLEND_TITLE = "barreja"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Barreja dos colors amb una proporció donada (0,0 - 1,0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://ca.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Escolliu un color de la paleta."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "color aleatori"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Escolliu un color a l'atzar."; -Blockly.Msg.COLOUR_RGB_BLUE = "blau"; -Blockly.Msg.COLOUR_RGB_GREEN = "verd"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "vermell"; -Blockly.Msg.COLOUR_RGB_TITLE = "color amb"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Crear un color amb les quantitats especificades de vermell, verd i blau. Tots els valors han de ser entre 0 i 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "sortir del bucle"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "continuar amb la següent iteració del bucle"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Sortir del bucle interior."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Ometre la resta d'aquest bucle, i continuar amb la següent iteració."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Advertència: Aquest bloc només es pot utilitzar dins d'un bucle."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "per a cada element %1 en la llista %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Per a cada element en la llista, desar l'element dins la variable '%1', i llavors executar unes sentències."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "comptar amb %1 des de %2 fins a %3 en increments de %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Fer que la variable \"%1\" prengui els valors des del nombre inicial fins al nombre final, incrementant a cada pas l'interval indicat, i executar els blocs especificats."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Afegeix una condició al bloc 'si'."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Afegeix una condició final, que recull qualsevol altra possibilitat, al bloc 'si'."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Afegeix, esborra o reordena seccions per reconfigurar aquest bloc 'si'."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "si no"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "si no, si"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "si"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Si un valor és cert, llavors executar unes sentències."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Si un valor és cert, llavors executar el primer bloc de sentències. En cas contrari, executar el segon bloc de sentències."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Si el primer valor és cert, llavors executar el primer bloc de sentències. En cas contrari, si el segon valor és cert, executar el segon bloc de sentències."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Si el primer valor és cert, llavors executar el primer bloc de sentències. En cas contrari, si el segon valor és cert, executar el segon bloc de sentències. Si cap dels valors és cert, executar l'últim bloc de sentències."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://ca.wikipedia.org/wiki/Bucle_For"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "fer"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "repetir %1 vegades"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Executar unes sentències diverses vegades."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "repetir fins que"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "repetir mentre"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Mentre un valor sigui fals, llavors executar unes sentències."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Mentre un valor sigui cert, llavors executar unes sentències."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Esborrar els %1 blocs?"; -Blockly.Msg.DELETE_BLOCK = "Esborra bloc"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Esborra %1 blocs"; -Blockly.Msg.DISABLE_BLOCK = "Desactiva bloc"; -Blockly.Msg.DUPLICATE_BLOCK = "Duplica"; -Blockly.Msg.ENABLE_BLOCK = "Activa bloc"; -Blockly.Msg.EXPAND_ALL = "Expandir blocs"; -Blockly.Msg.EXPAND_BLOCK = "Expandir bloc"; -Blockly.Msg.EXTERNAL_INPUTS = "Entrades externes"; -Blockly.Msg.HELP = "Ajuda"; -Blockly.Msg.INLINE_INPUTS = "Entrades en línia"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "crear llista buida"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Retorna una llista, de longitud 0, que no conté cap dada."; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "llista"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Afegeix, esborra o reordena seccions per reconfigurar aquest bloc de llista."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "crear llista amb"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Afegeix un element a la llista."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Crea una llista amb qualsevol nombre d'elements."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "primer"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "núm.# des del final"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "recupera"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "recupera i esborra"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "últim"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "a l'atzar"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "esborra"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Retorna el primer element d'una llista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Retorna l'element de la posició especificada a la llista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Retorna l'últim element d'una llista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Retorna un element a l'atzar d'una llista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Esborra i retorna el primer element d'una llista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Esborra i retorna l'element de la posició especificada de la llista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Esborra i retorna l'últim element d'una llista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Esborra i retorna un element a l'atzar d'una llista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Esborra el primer element d'una llista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Esborra l'element de la posició especificada de la llista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Esborra l'últim element d'una llista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Esborra un element a l'atzar d'una llista."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "fins # des del final"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "fins #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "fins l'últim"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "recupera sub-llista des del principi"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "recupera sub-llista des de # des del final"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "recupera sub-llista des de #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Crea una còpia de la part especificada d'una llista."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 és l'últim element."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 és el primer element."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "buscar primera aparició d'un element"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "buscar última aparició d'un element"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Retorna l'índex de la primera/última aparició d'un element a la llista. Retorna %1 si no s'hi troba el text."; -Blockly.Msg.LISTS_INLIST = "en la llista"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 és buida"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Retorna cert si la llista és buida."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "longitud de %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Retorna la longitud d'una llista."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "crea llista amb element %1 repetit %2 vegades"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Crea una llista formada pel valor donat, repetit tantes vegades com s'indiqui."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "com"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "insereix a"; -Blockly.Msg.LISTS_SET_INDEX_SET = "modifica"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Insereix l'element al principi d'una llista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Insereix l'element a la posició especificada d'una llista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Afegeix l'element al final d'una llista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Insereix l'element en una posició a l'atzar d'una llista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Modifica el primer element d'una llista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Modifica l'element de la posició especificada d'una llista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Modifica l'últim element d'una llista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Modifica un element a l'atzar d'una llista."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "make list from text"; // untranslated -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "make text from list"; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "fals"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Retorna o bé cert o bé fals."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "cert"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://ca.wikipedia.org/wiki/Inequaci%C3%B3"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Retorna cert si totes dues entrades són iguals."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Retorna cert si la primera entrada és més gran que la segona entrada."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Retorna cert si la primera entrada és més gran o igual a la segona entrada."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Retorna cert si la primera entrada és més petita que la segona entrada."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Retorna cert si la primera entra és més petita o igual a la segona entrada."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Retorna cert si totes dues entrades són diferents."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "no %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Retorna cert si l'entrada és falsa. Retorna fals si l'entrada és certa."; -Blockly.Msg.LOGIC_NULL = "nul"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Retorna nul."; -Blockly.Msg.LOGIC_OPERATION_AND = "i"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "o"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Retorna cer si totes dues entrades són certes."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Retorna cert si almenys una de les entrades és certa."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "condició"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "si és fals"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "si és cert"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Comprova la condició de 'condició'. Si la condició és certa, retorna el valor 'si és cert'; en cas contrari, retorna el valor 'si és fals'."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://ca.wikipedia.org/wiki/Aritm%C3%A8tica"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Retorna la suma dels dos nombres."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Retorna el quocient dels dos nombres."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Retorna la diferència entre els dos nombres."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Retorna el producte del dos nombres."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Retorna el primer nombre elevat a la potència indicada pel segon nombre."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://ca.wikipedia.org/wiki/Suma"; -Blockly.Msg.MATH_CHANGE_TITLE = "canvia %1 per %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Afegeix un nombre a la variable '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://ca.wikipedia.org/wiki/Constant_matem%C3%A0tica"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Retorna una de les constants més habituals: π (3,141…), e (2,718…), φ (1,618…), sqrt(2) (1,414…), sqrt(½) (0,707…), o ∞ (infinit)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "limitar %1 entre %2 i %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Limita un nombre perquè estigui entre els límits especificats (inclosos)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "és divisible per"; -Blockly.Msg.MATH_IS_EVEN = "és parell"; -Blockly.Msg.MATH_IS_NEGATIVE = "és negatiu"; -Blockly.Msg.MATH_IS_ODD = "és senar"; -Blockly.Msg.MATH_IS_POSITIVE = "és positiu"; -Blockly.Msg.MATH_IS_PRIME = "és primer"; -Blockly.Msg.MATH_IS_TOOLTIP = "Comprova si un nombre és parell, senar, enter, positium negatiu, o si és divisible per un cert nombre. Retorna cert o fals."; -Blockly.Msg.MATH_IS_WHOLE = "és enter"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://ca.wikipedia.org/wiki/Residu_%28aritm%C3%A8tica%29"; -Blockly.Msg.MATH_MODULO_TITLE = "residu de %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Retorna el residu de dividir els dos nombres."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://ca.wikipedia.org/wiki/Nombre"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Un nombre."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "mitjana de llista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "màxim de llista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "mediana de llista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "mínim de llista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "moda de llista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "element aleatori de llista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "desviació estàndard de llista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "suma de llista"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Retorna la mitjana (mitjana aritmètica) dels valors numèrics de la llista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Retorna el nombre més gran de la llista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Retorna la mediana de la llista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Retorna el nombre més petit de la llista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Retorna una llista dels elements que apareixen més vegades a la llista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Retorna un element aleatori de la lllista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Retorna la desviació estàndard de la llista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Retorna la suma de tots els nombres de la llista."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://ca.wikipedia.org/wiki/Generaci%C3%B3_de_nombres_aleatoris"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "fracció aleatòria"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Retorna una fracció aleatòria entre 0,0 (inclòs) i 1,0 (exclòs)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://ca.wikipedia.org/wiki/Generaci%C3%B3_de_nombres_aleatoris"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "nombre aleatori entre %1 i %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Retorna un nombre aleatori entre els dos límits especificats, inclosos."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://ca.wikipedia.org/wiki/Arrodoniment"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "arrodonir"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "arrodonir cap avall"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "arrodonir cap amunt"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Arrodonir un nombre cap amunt o cap avall."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://ca.wikipedia.org/wiki/Arrel_quadrada"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absolut"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "arrel quadrada"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Retorna el valor absolut d'un nombre."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Retorna ''e'' elevat a la potència del nombre indicat."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Retorna el logaritme natural d'un nombre."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Retorna el logaritme en base 10 d'un nombre."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Retorna l'oposat d'un nombre."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Retorna 10 elevat a la potència del nombre indicat."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Retorna l'arrel quadrada d'un nombre."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://ca.wikipedia.org/wiki/Funci%C3%B3_trigonom%C3%A8trica"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Retorna l'arccosinus d'un nombre."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Retorna l'arcsinus d'un nombre."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Retorna l'arctangent d'un nombre."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Retorna el cosinus d'un grau (no radiant)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Retorna el sinus d'un grau (no radiant)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Retorna la tangent d'un grau (no radiant)."; -Blockly.Msg.NEW_VARIABLE = "Nova variable..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Nou nom de variable:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "permetre declaracions"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "amb:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://ca.wikipedia.org/wiki/Procediment_%28Programació%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Executa la funció definida per usuari '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://ca.wikipedia.org/wiki/Procediment_%28Programació%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Executa la funció definida per l'usuari '%1' i utilitza la seva sortida."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "amb:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Crear '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "fes alguna cosa"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "a"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Crea una funció sense sortida."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "retorna"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Crea una funció amb una sortida."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Advertència: Aquesta funció té paràmetres duplicats."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Iluminar la definició de la funció"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Si el valor és cert, llavors retorna un segon valor."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Advertència: Aquest bloc només es pot utilitzar dins de la definició d'una funció."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "nom d'entrada:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Afegir una entrada per la funció."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "entrades"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Afegir, eliminar o canviar l'ordre de les entrades per aquesta funció."; -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "Elimina el comentari"; -Blockly.Msg.RENAME_VARIABLE = "Reanomena variable..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Reanomena totes les variables '%1' a:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "afegir text"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "a"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Afegir un text a la variable '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "a minúscules"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "a Text De Títol"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "a MAJÚSCULES"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Retorna una còpia del text amb diferents majúscules/minúscules."; -Blockly.Msg.TEXT_CHARAT_FIRST = "recupera la primera lletra"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "recupera la lletra núm.# des del final"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "recupera la lletra núm.#"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "en el text"; -Blockly.Msg.TEXT_CHARAT_LAST = "recupera l'última lletra"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "recupera una lletra a l'atzar"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Recupera la lletra de la posició especificada."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Afegeix un element al text."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "unir"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Afegeix, esborrar o reordenar seccions per reconfigurar aquest bloc de text."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "fins a la lletra núm.# des del final"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "fins a la lletra núm.#"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "fins a l'última lletra"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "en el text"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "recupera subcadena des de la primera lletra"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "recupera subcadena des de la lletra núm.# des del final"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "recupera subcadena des de la lletra núm.#"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Recupera una part especificada del text."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "en el text"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "trobar la primera aparició del text"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "trobar l'última aparició del text"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Retorna l'índex de la primera/última aparició del primer text dins el segon. Retorna %1 si no es troba el text."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 està buit"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Retorna cert si el text proporcionat està buit."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "crear text amb"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Crea un tros de text per unió de qualsevol nombre d'elements."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "llargària de %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Retorna el nombre de lletres (espais inclosos) en el text proporcionat."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "imprimir %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Imprimir el text, el nombre o altre valor especificat."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Demana que l'usuari introdueixi un nombre."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Demana que l'usuari introdueixi un text."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "demanar un nombre amb el missatge"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "demanar text amb el missatge"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://ca.wikipedia.org/wiki/Cadena_%28inform%C3%A0tica%29"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Una lletra, paraula o línia de text."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "retalla espais de tots dos extrems de"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "retalla espais de l'esquerra de"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "retalla espais de la dreta de"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Retorna una còpia del text on s'han esborrat els espais d'un o dels dos extrems."; -Blockly.Msg.TODAY = "Today"; // untranslated -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "element"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Crea 'modifica %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Retorna el valor d'aquesta variable."; -Blockly.Msg.VARIABLES_SET = "modifica %1 a %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Crear 'recupera %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Modifica aquesta variable al valor introduït."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/cs.js b/backend/_pv_1_3_5/static/blockly/msg/js/cs.js deleted file mode 100755 index 1ca8da116..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/cs.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.cs'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Přidat komentář"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Změnit hodnotu:"; -Blockly.Msg.CLEAN_UP = "Uspořádat bloky"; -Blockly.Msg.COLLAPSE_ALL = "Sbalit bloky"; -Blockly.Msg.COLLAPSE_BLOCK = "Sbalit blok"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "barva 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "barva 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "poměr"; -Blockly.Msg.COLOUR_BLEND_TITLE = "smíchat"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Smíchá dvě barvy v daném poměru (0.0–1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://cs.wikipedia.org/wiki/Barva"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Vyberte barvu z palety."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "náhodná barva"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Zvolte barvu náhodně."; -Blockly.Msg.COLOUR_RGB_BLUE = "modrá"; -Blockly.Msg.COLOUR_RGB_GREEN = "zelená"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "červená"; -Blockly.Msg.COLOUR_RGB_TITLE = "obarvěte barvou"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Vytvoř barvu se zadaným množstvím červené, zelené a modré. Všechny hodnoty musí být mezi 0 a 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "vyskočit ze smyčky"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "pokračuj dalším opakováním smyčky"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Vyskoč z vnitřní smyčky."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Přeskoč zbytek této smyčky a pokračuj dalším opakováním."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Upozornění: Tento blok může být použit pouze uvnitř smyčky."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "pro každou položku %1 v seznamu %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Pro každou položku v seznamu nastavte do proměnné '%1' danou položku a proveďte nějaké operace."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "počítat s %1 od %2 do %3 po %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Nechá proměnnou '%1' nabývat hodnot od počátečního do koncového čísla po daném přírůstku a provádí s ní příslušné bloky."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Přidat podmínku do \"pokud\" bloku."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Přidej konečnou podmínku zahrnující ostatní případy do bloku \"pokud\"."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Přidej, odstraň či uspořádej sekce k přenastavení tohoto bloku \"pokud\"."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "jinak"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "nebo pokud"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "pokud"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Je-li hodnota pravda, proveď určité příkazy."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Je-li hodnota pravda, proveď první blok příkazů. V opačném případě proveď druhý blok příkazů."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Je-li první hodnota pravdivá, proveď první blok příkazů. V opačném případě, je-li pravdivá druhá hodnota, proveď druhý blok příkazů."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Je-li první hodnota pravda, proveď první blok příkazů. Je-li druhá hodnota pravda, proveď druhý blok příkazů. Pokud žádná hodnota není pravda, proveď poslední blok příkazů."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://cs.wikipedia.org/wiki/Cyklus_pro"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "dělej"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "opakuj %1 krát"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Proveď určité příkazy několikrát."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "opakovat dokud"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "opakovat když"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Dokud je hodnota nepravdivá, prováděj určité příkazy."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Dokud je hodnota pravdivá, prováděj určité příkazy."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Smazat všech %1 bloků?"; -Blockly.Msg.DELETE_BLOCK = "Smazat blok"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Smazat %1 bloků"; -Blockly.Msg.DISABLE_BLOCK = "Deaktivovat blok"; -Blockly.Msg.DUPLICATE_BLOCK = "Duplikovat"; -Blockly.Msg.ENABLE_BLOCK = "Povolit blok"; -Blockly.Msg.EXPAND_ALL = "Rozbalit bloky"; -Blockly.Msg.EXPAND_BLOCK = "Rozbalit blok"; -Blockly.Msg.EXTERNAL_INPUTS = "vnější vstupy"; -Blockly.Msg.HELP = "Nápověda"; -Blockly.Msg.INLINE_INPUTS = "Vložené vstupy"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "vytvořit prázdný seznam"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Vrátí seznam nulové délky, který neobsahuje žádné datové záznamy"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "seznam"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Přidat, odebrat nebo změnit pořadí oddílů tohoto seznamu bloku."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "vytvořit seznam s"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Přidat položku do seznamu."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Vytvoř seznam s libovolným počtem položek."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "první"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# od konce"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "získat"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "získat a odstranit"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "poslední"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "náhodné"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "odstranit"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Vrátí první položku v seznamu."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Získá položku z určené pozice v seznamu."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Vrátí poslední položku v seznamu."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Vrátí náhodnou položku ze seznamu."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Odstraní a vrátí první položku v seznamu."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Odstraní a získá položku z určené pozice v seznamu."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Odstraní a vrátí poslední položku v seznamu."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Odstraní a vrátí náhodnou položku v seznamu."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Odstraní první položku v seznamu."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Odebere položku na konkrétním místě v seznamu."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Odstraní poslední položku v seznamu."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Odstraní náhodou položku v seznamu."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "do # od konce"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "do #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "jako poslední"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "získat podseznam od první položky"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "získat podseznam od # od konce"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "získat podseznam od #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Vytvoří kopii určené části seznamu."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 je poslední položka."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 je první položka."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "najít první výskyt položky"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "najít poslední výskyt položky"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Vrací index prvního/posledního výskytu položky v seznamu. Vrací %1, pokud položka nebyla nalezena."; -Blockly.Msg.LISTS_INLIST = "v seznamu"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 je prázdné"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Vrátí hodnotu pravda, pokud je seznam prázdný."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "délka %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Vrací počet položek v seznamu."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "vytvoř seznam s položkou %1 opakovanou %1 krát"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Vytváří seznam obsahující danou hodnotu n-krát."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "jako"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "vložit na"; -Blockly.Msg.LISTS_SET_INDEX_SET = "nastavit"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Vložit položku na začátek seznamu."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Vloží položku na určenou pozici v seznamu."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Připojí položku na konec seznamu."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Připojí položku náhodně do seznamu."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Nastaví první položku v seznamu."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Nastaví položku na konkrétní místo v seznamu."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Nastaví poslední položku v seznamu."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Nastaví náhodnou položku v seznamu."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "vzestupně"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "sestupně"; -Blockly.Msg.LISTS_SORT_TITLE = "seřadit %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Seřadit kopii seznamu."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "abecedně, na velikosti písmen nezáleží"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "číselné"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "abecedně"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "udělat z textu seznam"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "udělat ze seznamu text"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Spojit seznam textů do jednoho textu, rozdělaného oddělovači."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Rozdělit text do seznamu textů, lámání na oddělovačích."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "s oddělovačem"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "nepravda"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Vrací pravda nebo nepravda."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "pravda"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://cs.wikipedia.org/wiki/Nerovnost_(matematika)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Vrátí hodnotu pravda, pokud se oba vstupy rovnají jeden druhému."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Navrátí hodnotu pravda, pokud první vstup je větší než druhý vstup."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Navrátí hodnotu pravda, pokud je první vstup větší a nebo rovný druhému vstupu."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Navrátí hodnotu pravda, pokud je první vstup menší než druhý vstup."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Navrátí hodnotu pravda, pokud je první vstup menší a nebo rovný druhému vstupu."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Vrátí hodnotu pravda, pokud se oba vstupy nerovnají sobě navzájem."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "ne %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Navrátí hodnotu pravda, pokud je vstup nepravda. Navrátí hodnotu nepravda, pokud je vstup pravda."; -Blockly.Msg.LOGIC_NULL = "prázdný"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Vrátí prázdnou hodnotu"; -Blockly.Msg.LOGIC_OPERATION_AND = "a"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "nebo"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Vrátí hodnotu pravda, pokud oba dva vstupy jsou pravdivé."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Vrátí hodnotu pravda, pokud alespoň jeden ze vstupů má hodnotu pravda."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://cs.wikipedia.org/wiki/Ternární operátor (programování)"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "pokud nepravda"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "pokud pravda"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Zkontroluje podmínku v \"testu\". Když je podmínka pravda, vrátí hodnotu \"pokud pravda\"; v opačném případě vrátí hodnotu \"pokud nepravda\"."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://cs.wikipedia.org/wiki/Aritmetika"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Vrátí součet dvou čísel."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Vrátí podíl dvou čísel."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Vrátí rozdíl dvou čísel."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Vrátí součin dvou čísel."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Vrátí první číslo umocněné na druhé číslo."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "zaměň %1 za %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Přičti číslo k proměnné '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Vraťte jednu z následujících konstant: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (nekonečno)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "omez %1 na rozmezí od %2 do %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Omezí číslo tak, aby bylo ve stanovených mezích (včetně)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "je dělitelné číslem"; -Blockly.Msg.MATH_IS_EVEN = "je sudé"; -Blockly.Msg.MATH_IS_NEGATIVE = "je záporné"; -Blockly.Msg.MATH_IS_ODD = "je liché"; -Blockly.Msg.MATH_IS_POSITIVE = "je kladné"; -Blockly.Msg.MATH_IS_PRIME = "je prvočíslo"; -Blockly.Msg.MATH_IS_TOOLTIP = "Kontrola, zda je číslo sudé, liché, prvočíslo, celé, kladné, záporné nebo zda je dělitelné daným číslem. Vrací pravdu nebo nepravdu."; -Blockly.Msg.MATH_IS_WHOLE = "je celé"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://cs.wikipedia.org/wiki/Modul%C3%A1rn%C3%AD_aritmetika"; -Blockly.Msg.MATH_MODULO_TITLE = "zbytek po dělení %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Vrátí zbytek po dělení dvou čísel."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://cs.wikipedia.org/wiki/Číslo"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Číslo."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "průměr v seznamu"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "největší v seznamu"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "medián v seznamu"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "nejmenší v seznamu"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "nejčastější ze seznamu"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "náhodná položka seznamu"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "směrodatná odchylka ze seznamu"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "suma seznamu"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Vrátí průměr (aritmetický průměr) číselných hodnot v seznamu."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Vrátí největší číslo v seznamu."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Vrátí medián seznamu."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Vrátí nejmenší číslo v seznamu."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Vrátí seznam nejčastějších položek seznamu."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Vrátí náhodnou položku ze seznamu."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Vrátí směrodatnou odchylku seznamu."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Vrátí součet všech čísel v seznamu."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://cs.wikipedia.org/wiki/Gener%C3%A1tor_n%C3%A1hodn%C3%BDch_%C4%8D%C3%ADsel"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "náhodné číslo mezi 0 (včetně) do 1"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Vrátí náhodné číslo mezi 0,0 (včetně) až 1,0"; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://cs.wikipedia.org/wiki/Gener%C3%A1tor_n%C3%A1hodn%C3%BDch_%C4%8D%C3%ADsel"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "náhodné celé číslo od %1 do %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Vrací náhodné celé číslo mezi dvěma určenými mezemi, včetně mezních hodnot."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "zaokrouhlit"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "zaokrouhlit dolů"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "zaokrouhlit nahoru"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Zaokrouhlit číslo nahoru nebo dolů."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://cs.wikipedia.org/wiki/Druhá_odmocnina"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absolutní hodnota"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "druhá odmocnina"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Vrátí absolutní hodnotu čísla."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Vrátí mocninu čísla e."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Vrátí přirozený logaritmus čísla."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Vrátí desítkový logaritmus čísla."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Vrátí zápornou hodnotu čísla."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Vrátí mocninu čísla 10."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Vrátí druhou odmocninu čísla."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "acos"; -Blockly.Msg.MATH_TRIG_ASIN = "arcsin"; -Blockly.Msg.MATH_TRIG_ATAN = "arctan"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tan"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Vrátí arkus kosinus čísla."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Vrátí arkus sinus čísla."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Vrátí arkus tangens čísla."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Vrátí kosinus úhlu ve stupních."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Vrátí sinus úhlu ve stupních."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Vrátí tangens úhlu ve stupních."; -Blockly.Msg.NEW_VARIABLE = "Nová proměnná..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Nový název proměnné:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "povolit příkazy"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "s:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://cs.wikipedia.org/wiki/Funkce_(programov%C3%A1n%C3%AD)"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Spustí uživatelem definovanou funkci '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://cs.wikipedia.org/wiki/Funkce_(programov%C3%A1n%C3%AD)"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Spustí uživatelem definovanou funkci '%1' a použije její výstup."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "s:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Vytvořit '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Popište tuto funkci..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://cs.wikipedia.org/w/index.php?title=Funkce_(programování)"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "proveď něco"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "k provedení"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Vytvořit funkci bez výstupu."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://cs.wikipedia.org/w/index.php?title=Funkce_(programování)"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "navrátit"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Vytvořit funkci s výstupem."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Upozornění: Tato funkce má duplicitní parametry."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Zvýraznit definici funkce"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Je-li hodnota pravda, pak vrátí druhou hodnotu."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Varování: Tento blok může být použit pouze uvnitř definici funkce."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "vstupní jméno:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Přidat vstupy do funkce."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "vstupy"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Přidat, odebrat nebo změnit pořadí vstupů této funkce."; -Blockly.Msg.REDO = "Znovu"; -Blockly.Msg.REMOVE_COMMENT = "Odstranit komentář"; -Blockly.Msg.RENAME_VARIABLE = "Přejmenovat proměnnou..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Přejmenuj všech '%1' proměnných na:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "přidat text"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "do"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Přidá určitý text k proměnné '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "na malá písmena"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "na Počáteční Velká Písmena"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "na VELKÁ PÍSMENA"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Vrátí kopii textu s jinou velikostí písmen."; -Blockly.Msg.TEXT_CHARAT_FIRST = "získat první písmeno"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "získat # písmeno od konce"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "získat písmeno #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "v textu"; -Blockly.Msg.TEXT_CHARAT_LAST = "získat poslední písmeno"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "získat náhodné písmeno"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Získat písmeno na konkrétní pozici."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Přidat položku do textu."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "spojit"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Přidat, odebrat nebo změnit pořadí oddílů tohoto textového bloku."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "do # písmene od konce"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "do písmene #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "do posledního písmene"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "v textu"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "získat podřetězec od prvního písmene"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "získat podřetězec od písmene # od konce"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "získat podřetězec od písmene #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Získat zadanou část textu."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "v textu"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "najít první výskyt textu"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "najít poslední výskyt textu"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Vrátí index prvního/posledního výskytu prvního textu v druhém textu. Pokud text není nalezen, vypíše %1."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 je prázdný"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Vrátí pravda pokud je zadaný text prázdný."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "vytvořit text s"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Vytvoří kousek textu spojením libovolného počtu položek."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "délka %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Vrátí počet písmen (včetně mezer) v zadaném textu."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "tisk %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Tisk zadaného textu, čísla nebo jiné hodnoty."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Výzva pro uživatele k zadání čísla."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Výzva pro uživatele k zadání nějakého textu."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "výzva k zadání čísla se zprávou"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "výzva k zadání textu se zprávou"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://cs.wikipedia.org/wiki/Textov%C3%BD_%C5%99et%C4%9Bzec"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Písmeno, slovo nebo řádek textu."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "odstranit mezery z obou stran"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "odstranit mezery z levé strany"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "odstranit mezery z pravé strany"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Vrátí kopii textu s odstraněnými mezerami z jednoho nebo obou konců."; -Blockly.Msg.TODAY = "Dnes"; -Blockly.Msg.UNDO = "Zpět"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "položka"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Vytvořit \"nastavit %1\""; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Vrátí hodnotu této proměnné."; -Blockly.Msg.VARIABLES_SET = "nastavit %1 na %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Vytvořit \"získat %1\""; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Nastaví tuto proměnnou, aby se rovnala vstupu."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/da.js b/backend/_pv_1_3_5/static/blockly/msg/js/da.js deleted file mode 100755 index 21e3e3e31..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/da.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.da'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Tilføj kommentar"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Skift værdi:"; -Blockly.Msg.CLEAN_UP = "Ryd op i blokke"; -Blockly.Msg.COLLAPSE_ALL = "Fold blokkene sammen"; -Blockly.Msg.COLLAPSE_BLOCK = "Fold blokken sammen"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "farve 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "farve 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "i forholdet"; -Blockly.Msg.COLOUR_BLEND_TITLE = "bland"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Blander to farver sammen i et bestemt forhold (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://da.wikipedia.org/wiki/Farve"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Vælg en farve fra paletten."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "tilfældig farve"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Vælg en tilfældig farve."; -Blockly.Msg.COLOUR_RGB_BLUE = "blå"; -Blockly.Msg.COLOUR_RGB_GREEN = "grøn"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "rød"; -Blockly.Msg.COLOUR_RGB_TITLE = "farve med"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Lav en farve med den angivne mængde af rød, grøn og blå. Alle værdier skal være mellem 0 og 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "bryd ud af løkken"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "fortsæt med den næste gentagelse i løkken"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Bryd ud af den omgivende løkke."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Spring resten af denne løkke over, og fortsæt med den næste gentagelse."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Advarsel: Denne blok kan kun bruges i en løkke."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "for hvert element %1 i listen %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "For hvert element i en liste, sæt variablen '%1' til elementet, og udfør derefter nogle kommandoer."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "tæl med %1 fra %2 til %3 med %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Få variablen \"%1\" til at have værdierne fra startværdien til slutværdien, mens der tælles med det angivne interval, og udfør de angivne blokke."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Tilføj en betingelse til denne \"hvis\" blok."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Tilføj en sidste fang-alt betingelse, til denne \"hvis\" blok."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Tilføj, fjern eller byt om på rækkefølgen af delene for at konfigurere denne \"hvis\" blok."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "ellers"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "ellers hvis"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "hvis"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Hvis en værdi er sand, så udfør nogle kommandoer."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Hvis en værdi er sand, så udfør den første blok af kommandoer. Ellers udfør den anden blok af kommandoer."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Hvis den første værdi er sand, så udfør den første blok af kommandoer. Ellers, hvis den anden værdi er sand, så udfør den anden blok af kommandoer."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Hvis den første værdi er sand, så udfør den første blok af kommandoer. Ellers, hvis den anden værdi er sand, så udfør den anden blok af kommandoer. Hvis ingen af værdierne er sande, så udfør den sidste blok af kommandoer."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://da.wikipedia.org/wiki/For-l%C3%B8kke"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "udfør"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "gentag %1 gange"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Udfør nogle kommandoer flere gange."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "gentag indtil"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "gentag sålænge"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Udfør nogle kommandoer, sålænge en værdi er falsk."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Udfør nogle kommandoer, sålænge en værdi er sand."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Slet alle %1 blokke?"; -Blockly.Msg.DELETE_BLOCK = "Slet blok"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Slet %1 blokke"; -Blockly.Msg.DISABLE_BLOCK = "Deaktivér blok"; -Blockly.Msg.DUPLICATE_BLOCK = "Duplikér"; -Blockly.Msg.ENABLE_BLOCK = "Aktivér blok"; -Blockly.Msg.EXPAND_ALL = "Fold blokkene ud"; -Blockly.Msg.EXPAND_BLOCK = "Fold blokken ud"; -Blockly.Msg.EXTERNAL_INPUTS = "Udvendige inputs"; -Blockly.Msg.HELP = "Hjælp"; -Blockly.Msg.INLINE_INPUTS = "Indlejrede inputs"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "opret en tom liste"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Returnerer en liste af længde 0, som ikke indeholder nogen data"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "liste"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Tilføj, fjern eller byt om på rækkefølgen af delene for at konfigurere denne blok."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "opret liste med"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Føj et element til listen."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Opret en liste med et vilkårligt antal elementer."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "første"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# fra slutningen"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "hent"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "hent og fjern"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "sidste"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "tilfældig"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "fjern"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Returnerer det første element i en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Returnerer elementet på den angivne position på en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Returnerer den sidste element i en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Returnerer et tilfældigt element i en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Fjerner og returnerer det første element i en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Fjerner og returnerer elementet på den angivne position på en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Fjerner og returnerer det sidste element i en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Fjerner og returnerer et tilfældigt element i en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Fjerner det første element i en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Fjerner elementet på den angivne position på en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Fjerner sidste element i en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Fjerner et tilfældigt element i en liste."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "til # fra slutningen"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "til #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "til sidste"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "hent underliste fra første"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "hent underliste fra # fra slutningen"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "hent underliste fra #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Opretter en kopi af den angivne del af en liste."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 er det sidste element."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 er det første element."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "find første forekomst af elementet"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "find sidste forekomst af elementet"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Returnerer indeks for første/sidste forekomst af elementet i listen. Returnerer %1, hvis elementet ikke kan findes."; -Blockly.Msg.LISTS_INLIST = "i listen"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 er tom"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Returnerer sand, hvis listen er tom."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "længden af %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Returnerer længden af en liste."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "opret liste med elementet %1 gentaget %2 gange"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Opretter en liste bestående af den givne værdi gentaget et bestemt antal gange."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "som"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "indsæt ved"; -Blockly.Msg.LISTS_SET_INDEX_SET = "sæt"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Indsætter elementet i starten af en liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Indsætter elementet på den angivne position i en liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Føj elementet til slutningen af en liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Indsætter elementet tilfældigt i en liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Sætter det første element i en liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Sætter elementet på den angivne position i en liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Sætter det sidste element i en liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Sætter et tilfældigt element i en liste."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "lav tekst til liste"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "lav liste til tekst"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Saml en liste af tekster til én tekst, der er adskilt af et skilletegn."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Bryd tekst op i en liste af tekster med brud ved hvert skilletegn."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "med skilletegn"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "falsk"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Returnerer enten sand eller falsk."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "sand"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://da.wikipedia.org/wiki/Ulighed_(matematik)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Returnere sand, hvis begge inputs er lig med hinanden."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Returnere sand, hvis det første input er større end det andet input."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Returnere sand, hvis det første input er større end eller lig med det andet input."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Returnere sand, hvis det første input er mindre end det andet input."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Returnere sand, hvis det første input er mindre end eller lig med det andet input."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Returnere sand, hvis begge inputs ikke er lig med hinanden."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "ikke %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Returnerer sand, hvis input er falsk. Returnerer falsk, hvis input er sandt."; -Blockly.Msg.LOGIC_NULL = "null"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Returnerer null."; -Blockly.Msg.LOGIC_OPERATION_AND = "og"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "eller"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Returnere sand, hvis begge inputs er sande."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Returnere sand, hvis mindst et af inputtene er sande."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "hvis falsk"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "hvis sand"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Kontrollér betingelsen i 'test'. Hvis betingelsen er sand, returnér \"hvis sand\" værdien; ellers returnér \"hvis falsk\" værdien."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://da.wikipedia.org/wiki/Aritmetik"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Returnere summen af de to tal."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Returnere kvotienten af de to tal."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Returnere forskellen mellem de to tal."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Returnere produktet af de to tal."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Returnere det første tal opløftet til potensen af det andet tal."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "skift %1 med %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Læg et tal til variablen '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://da.wikipedia.org/wiki/Matematisk_konstant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Returnere en af de ofte brugte konstanter: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(2) (1.414…), sqrt(½) (0.707…) eller ∞ (uendeligt)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "begræns %1 til mellem %2 og %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Begræns et tal til at være mellem de angivne grænser (inklusiv)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = ":"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "er deleligt med"; -Blockly.Msg.MATH_IS_EVEN = "er lige"; -Blockly.Msg.MATH_IS_NEGATIVE = "er negativt"; -Blockly.Msg.MATH_IS_ODD = "er ulige"; -Blockly.Msg.MATH_IS_POSITIVE = "er positivt"; -Blockly.Msg.MATH_IS_PRIME = "er et primtal"; -Blockly.Msg.MATH_IS_TOOLTIP = "Kontrollere, om et tal er lige, ulige, primtal, helt, positivt, negativt, eller om det er deleligt med bestemt tal. Returnere sandt eller falskt."; -Blockly.Msg.MATH_IS_WHOLE = "er helt"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://da.wikipedia.org/wiki/Modulo"; -Blockly.Msg.MATH_MODULO_TITLE = "resten af %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Returner resten fra at dividere de to tal."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://da.wikipedia.org/wiki/Tal"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Et tal."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "gennemsnit af listen"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "største tal i listen"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "listens median"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "mindste tal i listen"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "listens typetal"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "tilfældigt element fra listen"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "standardafvigelsen for listen"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "summen af listen"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Returner gennemsnittet (middelværdien) af de numeriske værdier i listen."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Returner det største tal i listen."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Returner listens median."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Returner det mindste tal i listen."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Returner en liste over de mest almindelige elementer på listen."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Returner et tilfældigt element fra listen."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Returner standardafvigelsen for listen."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Returner summen af alle tal i listen."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://da.wikipedia.org/wiki/Tilfældighedsgenerator"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "tilfældigt decimaltal (mellem 0 og 1)"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Returner et tilfældigt decimaltal mellem 0,0 (inklusiv) og 1,0 (eksklusiv)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://da.wikipedia.org/wiki/Tilfældighedsgenerator"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "tilfældigt heltal mellem %1 og %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Returner et tilfældigt heltal mellem de to angivne grænser (inklusiv)."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://da.wikipedia.org/wiki/Afrunding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "afrund"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "rund ned"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "rund op"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Runde et tal op eller ned."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://da.wikipedia.org/wiki/Kvadratrod"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absolut"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "kvadratrod"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Returnere den absolutte værdi af et tal."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Returnere e til potensen af et tal."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Returnere den naturlige logaritme af et tal."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Returnere 10-talslogaritmen af et tal."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Returnere negationen af et tal."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Returnere 10 til potensen af et tal."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Returnere kvadratroden af et tal."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://da.wikipedia.org/wiki/Trigonometrisk_funktion"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Returnere arcus cosinus af et tal."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Returnere arcus sinus af et tal."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Returnere arcus tangens af et tal."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Returnere cosinus af en vinkel (i grader)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Returnere sinus af en vinkel (i grader)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Returnere tangens af en vinkel (i grader)."; -Blockly.Msg.NEW_VARIABLE = "Ny variabel..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Navn til den nye variabel:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "tillad erklæringer"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "med:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://da.wikipedia.org/wiki/Funktion_%28programmering%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Kør den brugerdefinerede funktion '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://da.wikipedia.org/wiki/Funktion_%28programmering%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Kør den brugerdefinerede funktion '%1' og brug dens returværdi."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "med:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Opret '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Beskriv denne funktion..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "gøre noget"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "for at"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Opretter en funktion der ikke har nogen returværdi."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "returnér"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Opretter en funktion der har en returværdi."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Advarsel: Denne funktion har dublerede parametre."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Markér funktionsdefinitionen"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Hvis en værdi er sand, så returnér en anden værdi."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Advarsel: Denne blok kan kun anvendes inden for en funktionsdefinition."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "parameternavn:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Tilføj en parameter til funktionen."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "parametre"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Tilføje, fjerne eller ændre rækkefølgen af parametre til denne funktion."; -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "Fjern kommentar"; -Blockly.Msg.RENAME_VARIABLE = "Omdøb variabel..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Omdøb alle '%1' variabler til:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "tilføj tekst"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "til"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Tilføj noget tekst til variablen '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "til små bogstaver"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "til Stort Begyndelsesbogstav"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "til STORE BOGSTAVER"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Returner en kopi af teksten hvor bogstaverne enten er udelukkende store eller små, eller hvor første bogstav i hvert ord er stort."; -Blockly.Msg.TEXT_CHARAT_FIRST = "hent første bogstav"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "hent bogstav # fra slutningen"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "hent bogstav #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "i teksten"; -Blockly.Msg.TEXT_CHARAT_LAST = "hent sidste bogstav"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "hent tilfældigt bogstav"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Returnerer bogstavet på den angivne placering."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Føj et element til teksten."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "sammenføj"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Tilføj, fjern eller byt om på rækkefølgen af delene for at konfigurere denne tekstblok."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "til bogstav # fra slutningen"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "til bogstav #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "til sidste bogstav"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "i teksten"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "hent delstreng fra første bogstav"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "hent delstreng fra bogstav # fra slutningen"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "hent delstreng fra bogstav #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returnerer den angivne del af teksten."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "i teksten"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "find første forekomst af teksten"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "find sidste forekomst af teksten"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returnerer indeks for første/sidste forekomst af første tekst i den anden tekst. Returnerer %1, hvis teksten ikke kan findes."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 er tom"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returnerer sand, hvis den angivne tekst er tom."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "lav en tekst med"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Lav et stykke tekst ved at sætte et antal elementer sammen."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "længden af %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Returnerer antallet af bogstaver (herunder mellemrum) i den angivne tekst."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "skriv %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Skriv den angivne tekst, tal eller anden værdi."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Spørg brugeren efter et tal"; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Spørg brugeren efter en tekst"; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "spørg efter et tal med meddelelsen"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "spørg efter tekst med meddelelsen"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://da.wikipedia.org/wiki/Tekststreng"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "En bogstav, et ord eller en linje med tekst."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "fjern mellemrum fra begge sider af"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "fjern mellemrum fra venstre side af"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "fjern mellemrum fra højre side af"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Returner en kopi af teksten med mellemrum fjernet fra den ene eller begge sider."; -Blockly.Msg.TODAY = "I dag"; -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "element"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Opret 'sæt %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returnerer værdien af denne variabel."; -Blockly.Msg.VARIABLES_SET = "sæt %1 til %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Opret 'hent %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Sætter denne variabel til at være lig med input."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/de.js b/backend/_pv_1_3_5/static/blockly/msg/js/de.js deleted file mode 100755 index 39bb1e34d..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/de.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.de'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Kommentar hinzufügen"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Wert ändern:"; -Blockly.Msg.CLEAN_UP = "Bausteine aufräumen"; -Blockly.Msg.COLLAPSE_ALL = "Alle Bausteine zusammenfalten"; -Blockly.Msg.COLLAPSE_BLOCK = "Baustein zusammenfalten"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "Farbe 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "und Farbe 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "im Verhältnis"; -Blockly.Msg.COLOUR_BLEND_TITLE = "mische"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Vermischt 2 Farben mit konfigurierbarem Farbverhältnis (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://de.wikipedia.org/wiki/Farbe"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Erzeugt eine Farbe aus der Palette."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "zufällige Farbe"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Erzeugt eine Farbe nach dem Zufallsprinzip."; -Blockly.Msg.COLOUR_RGB_BLUE = "blau"; -Blockly.Msg.COLOUR_RGB_GREEN = "grün"; -Blockly.Msg.COLOUR_RGB_HELPURL = "https://de.wikipedia.org/wiki/RGB-Farbraum"; -Blockly.Msg.COLOUR_RGB_RED = "rot"; -Blockly.Msg.COLOUR_RGB_TITLE = "Farbe aus"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Erzeugt eine Farbe mit selbst definierten Rot-, Grün- und Blauwerten. Alle Werte müssen zwischen 0 und 100 liegen."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://de.wikipedia.org/wiki/Kontrollstruktur"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "die Schleife abbrechen"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "sofort mit nächstem Schleifendurchlauf fortfahren"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Die umgebende Schleife beenden."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Diese Anweisung abbrechen und mit dem nächsten Schleifendurchlauf fortfahren."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Warnung: Dieser Baustein kann nur in einer Schleife verwendet werden."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://de.wikipedia.org/wiki/For-Schleife"; -Blockly.Msg.CONTROLS_FOREACH_TITLE = "für jeden Wert %1 aus der Liste %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Führt eine Anweisung für jeden Wert in der Liste aus und setzt dabei die Variable \"%1\" auf den aktuellen Listenwert."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://de.wikipedia.org/wiki/For-Schleife"; -Blockly.Msg.CONTROLS_FOR_TITLE = "zähle %1 von %2 bis %3 in Schritten von %4:"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Zählt die Variable \"%1\" von einem Startwert bis zu einem Endwert und führt für jeden Wert eine Anweisung aus."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Eine weitere Bedingung hinzufügen."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Eine sonst-Bedingung hinzufügen. Führt eine Anweisung aus, falls keine Bedingung zutrifft."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Hinzufügen, entfernen oder sortieren von Sektionen"; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "sonst"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "sonst falls"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "falls"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Führt eine Anweisung aus, falls eine Bedingung wahr ist."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Führt die erste Anweisung aus, falls eine Bedingung wahr ist. Führt ansonsten die zweite Anweisung aus."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Führt die erste Anweisung aus, falls die erste Bedingung wahr ist. Führt ansonsten die zweite Anweisung aus, falls die zweite Bedingung wahr ist."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Führe die erste Anweisung aus, falls die erste Bedingung wahr ist. Führt ansonsten die zweite Anweisung aus, falls die zweite Bedingung wahr ist. Führt die dritte Anweisung aus, falls keine der beiden Bedingungen wahr ist"; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://de.wikipedia.org/wiki/For-Schleife"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "mache"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "wiederhole %1 mal:"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Eine Anweisung mehrfach ausführen."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://de.wikipedia.org/wiki/Schleife_%28Programmierung%29"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "wiederhole bis"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "wiederhole solange"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Führt Anweisungen aus solange die Bedingung unwahr ist."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Führt Anweisungen aus solange die Bedingung wahr ist."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Alle %1 Bausteine löschen?"; -Blockly.Msg.DELETE_BLOCK = "Baustein löschen"; -Blockly.Msg.DELETE_VARIABLE = "Die Variable „%1“ löschen"; -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "%1 Verwendungen der Variable „%2“ löschen?"; -Blockly.Msg.DELETE_X_BLOCKS = "Baustein %1 löschen"; -Blockly.Msg.DISABLE_BLOCK = "Baustein deaktivieren"; -Blockly.Msg.DUPLICATE_BLOCK = "Kopieren"; -Blockly.Msg.ENABLE_BLOCK = "Baustein aktivieren"; -Blockly.Msg.EXPAND_ALL = "Alle Bausteine entfalten"; -Blockly.Msg.EXPAND_BLOCK = "Baustein entfalten"; -Blockly.Msg.EXTERNAL_INPUTS = "externe Eingänge"; -Blockly.Msg.HELP = "Hilfe"; -Blockly.Msg.INLINE_INPUTS = "interne Eingänge"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "erzeuge eine leere Liste"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Erzeugt eine leere Liste ohne Inhalt."; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "Liste"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Hinzufügen, entfernen und sortieren von Elementen."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "erzeuge Liste mit"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Ein Element zur Liste hinzufügen."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Erzeugt eine Liste aus den angegebenen Elementen."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "erstes"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "#tes von hinten"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#tes"; -Blockly.Msg.LISTS_GET_INDEX_GET = "nimm"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "nimm und entferne"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "letztes"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "zufälliges"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "entferne"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Extrahiert das erste Element aus der Liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Extrahiert das Element an der angegebenen Position in der Liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Extrahiert das letzte Element aus der Liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Extrahiert ein zufälliges Element aus der Liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Extrahiert und entfernt das erste Element aus der Liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Extrahiert und entfernt das Element an der angegebenen Position aus der Liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Extrahiert und entfernt das letzte Element aus der Liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Extrahiert und entfernt ein zufälliges Element aus der Liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Entfernt das erste Element aus der Liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Entfernt das Element an der angegebenen Position aus der Liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Entfernt das letzte Element aus der Liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Entfernt ein zufälliges Element aus der Liste."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "bis zu # von hinten"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "bis zu #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "bis zum Ende"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "erhalte Unterliste vom Anfang"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "erhalte Unterliste von # von hinten"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "erhalte Unterliste von #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Erstellt eine Kopie mit dem angegebenen Abschnitt der Liste."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 ist das letzte Element."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 ist das erste Element."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "suche erstes Auftreten von"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm"; -Blockly.Msg.LISTS_INDEX_OF_LAST = "suche letztes Auftreten von"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Sucht die Position (Index) eines Elementes in der Liste. Gibt %1 zurück, falls kein Element gefunden wurde."; -Blockly.Msg.LISTS_INLIST = "in der Liste"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 ist leer"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Ist wahr, falls die Liste leer ist."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "Länge von %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Die Anzahl von Elementen in der Liste."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm"; -Blockly.Msg.LISTS_REPEAT_TITLE = "erzeuge Liste mit %2 mal dem Element %1​"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Erzeugt eine Liste mit einer variablen Anzahl von Elementen"; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm"; -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "ein"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "füge als"; -Blockly.Msg.LISTS_SET_INDEX_SET = "setze für"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Fügt das Element an den Anfang der Liste an."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Fügt das Element an der angegebenen Position in die Liste ein."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Fügt das Element ans Ende der Liste an."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Fügt das Element zufällig in die Liste ein."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Setzt das erste Element in der Liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Setzt das Element an der angegebenen Position in der Liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Setzt das letzte Element in die Liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Setzt ein zufälliges Element in der Liste."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "aufsteigend"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "absteigend"; -Blockly.Msg.LISTS_SORT_TITLE = "%1 %2 %3 sortieren"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Eine Kopie einer Liste sortieren."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetisch, Großschreibung ignorieren"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numerisch"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetisch"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "Liste aus Text erstellen"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "Text aus Liste erstellen"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Liste mit Texten in einen Text vereinen, getrennt durch ein Trennzeichen."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Text in eine Liste mit Texten aufteilen, unterbrochen bei jedem Trennzeichen."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "mit Trennzeichen"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "unwahr"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Ist entweder wahr oder unwahr"; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "wahr"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://de.wikipedia.org/wiki/Vergleich_%28Zahlen%29"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Ist wahr, falls beide Werte gleich sind."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Ist wahr, falls der erste Wert größer als der zweite Wert ist."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Ist wahr, falls der erste Wert größer als oder gleich groß wie der zweite Wert ist."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Ist wahr, falls der erste Wert kleiner als der zweite Wert ist."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Ist wahr, falls der erste Wert kleiner als oder gleich groß wie der zweite Wert ist."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Ist wahr, falls beide Werte unterschiedlich sind."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "nicht %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Ist wahr, falls der Eingabewert unwahr ist. Ist unwahr, falls der Eingabewert wahr ist."; -Blockly.Msg.LOGIC_NULL = "null"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://de.wikipedia.org/wiki/Nullwert"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Ist \"null\"."; -Blockly.Msg.LOGIC_OPERATION_AND = "und"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "oder"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Ist wahr, falls beide Werte wahr sind."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Ist wahr, falls einer der beiden Werte wahr ist."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "prüfe"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://de.wikipedia.org/wiki/%3F:#Auswahloperator"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "falls unwahr"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "falls wahr"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Überprüft eine Bedingung \"prüfe\". Falls die Bedingung wahr ist, wird der \"falls wahr\" Wert zurückgegeben, andernfalls der \"falls unwahr\" Wert"; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://de.wikipedia.org/wiki/Grundrechenart"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Ist die Summe zweier Zahlen."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Ist der Quotient zweier Zahlen."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Ist die Differenz zweier Zahlen."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Ist das Produkt zweier Zahlen."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Ist die erste Zahl potenziert mit der zweiten Zahl."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://de.wikipedia.org/wiki/Inkrement_und_Dekrement"; -Blockly.Msg.MATH_CHANGE_TITLE = "erhöhe %1 um %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Addiert eine Zahl zu \"%1\"."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://de.wikipedia.org/wiki/Mathematische_Konstante"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Mathematische Konstanten wie: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…) oder ∞ (unendlich)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "begrenze %1 zwischen %2 und %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Begrenzt eine Zahl auf den Wertebereich zwischen zwei anderen Zahlen (inklusiv)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "ist teilbar durch"; -Blockly.Msg.MATH_IS_EVEN = "ist gerade"; -Blockly.Msg.MATH_IS_NEGATIVE = "ist negativ"; -Blockly.Msg.MATH_IS_ODD = "ist ungerade"; -Blockly.Msg.MATH_IS_POSITIVE = "ist positiv"; -Blockly.Msg.MATH_IS_PRIME = "ist eine Primzahl"; -Blockly.Msg.MATH_IS_TOOLTIP = "Überprüft ob eine Zahl gerade, ungerade, eine Primzahl, ganzzahlig, positiv, negativ oder durch eine zweite Zahl teilbar ist. Gibt wahr oder unwahr zurück."; -Blockly.Msg.MATH_IS_WHOLE = "ist eine ganze Zahl"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://de.wikipedia.org/wiki/Modulo"; -Blockly.Msg.MATH_MODULO_TITLE = "Rest von %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Der Rest nach einer Division."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://de.wikipedia.org/wiki/Zahl"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Eine Zahl."; -Blockly.Msg.MATH_ONLIST_HELPURL = "http://www.sysplus.ch/einstieg.php?links=menu&seite=4125&grad=Crash&prog=Excel"; -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "Mittelwert der Liste"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "Maximalwert der Liste"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "Median der Liste"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "Minimalwert der Liste"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "am häufigsten in der Liste"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "Zufallswert aus der Liste"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "Standardabweichung der Liste"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "Summe über die Liste"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Ist der Durchschnittswert aller Zahlen in einer Liste."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Ist die größte Zahl in einer Liste."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Ist der Median aller Zahlen in einer Liste."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Ist die kleinste Zahl in einer Liste."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Findet die Werte mit dem häufigstem Vorkommen in der Liste."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Gibt einen zufälligen Wert aus der Liste zurück."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Ist die Standardabweichung aller Werte in der Liste."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Ist die Summe aller Zahlen in einer Liste."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://de.wikipedia.org/wiki/Zufallszahlen"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "Zufallszahl (0.0 - 1.0)"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Erzeugt eine Zufallszahl zwischen 0.0 (inklusiv) und 1.0 (exklusiv)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://de.wikipedia.org/wiki/Zufallszahlen"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "ganzzahlige Zufallszahl zwischen %1 und %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Erzeugt eine ganzzahlige Zufallszahl zwischen zwei Zahlen (inklusiv)."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://de.wikipedia.org/wiki/Runden"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "runde"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "runde ab"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "runde auf"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Eine Zahl auf- oder abrunden."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://de.wikipedia.org/wiki/Quadratwurzel"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "Betrag"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "Quadratwurzel"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Ist der Betrag einer Zahl."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Ist Wert der Exponentialfunktion einer Zahl."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Ist der natürliche Logarithmus einer Zahl."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Ist der dekadische Logarithmus einer Zahl."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Negiert eine Zahl."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Rechnet 10 hoch eine Zahl."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Ist die Quadratwurzel einer Zahl."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://de.wikipedia.org/wiki/Trigonometrie"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Ist der Arkuskosinus des Eingabewertes."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Ist der Arkussinus des Eingabewertes."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Ist der Arkustangens des Eingabewertes."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Ist der Kosinus des Winkels."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Ist der Sinus des Winkels."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Ist der Tangens des Winkels."; -Blockly.Msg.NEW_VARIABLE = "Variable erstellen …"; -Blockly.Msg.NEW_VARIABLE_TITLE = "Name der neuen Variable:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "Aussagen erlauben"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "mit:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Rufe einen Funktionsblock ohne Rückgabewert auf."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Rufe einen Funktionsblock mit Rückgabewert auf."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "mit:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Erzeuge \"Aufruf %1\""; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Beschreibe diese Funktion …"; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "etwas tun"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = ""; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Ein Funktionsblock ohne Rückgabewert."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "gebe zurück"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Ein Funktionsblock mit Rückgabewert."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Warnung: dieser Funktionsblock hat zwei gleich benannte Parameter."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Markiere Funktionsblock"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Gibt den zweiten Wert zurück und verlässt die Funktion, falls der erste Wert wahr ist."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Warnung: Dieser Block darf nur innerhalb eines Funktionsblocks genutzt werden."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "Variable:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Eine Eingabe zur Funktion hinzufügen."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "Parameter"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Die Eingaben zu dieser Funktion hinzufügen, entfernen oder neu anordnen."; -Blockly.Msg.REDO = "Wiederholen"; -Blockly.Msg.REMOVE_COMMENT = "Kommentar entfernen"; -Blockly.Msg.RENAME_VARIABLE = "Variable umbenennen …"; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Alle \"%1\" Variablen umbenennen in:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "Text anhängen"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "an"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Text an die Variable \"%1\" anhängen."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "wandel um in kleinbuchstaben"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "wandel um in Substantive"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "wandel um in GROSSBUCHSTABEN"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Wandelt Schreibweise von Texten um, in Großbuchstaben, Kleinbuchstaben oder den ersten Buchstaben jedes Wortes groß und die anderen klein."; -Blockly.Msg.TEXT_CHARAT_FIRST = "nehme ersten Buchstaben"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "nehme #ten Buchstaben von hinten"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "nehme #ten Buchstaben"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm"; -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "vom Text"; -Blockly.Msg.TEXT_CHARAT_LAST = "nehme letzten Buchstaben"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "nehme zufälligen Buchstaben"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Extrahiert einen Buchstaben von einer bestimmten Position."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Ein Element zum Text hinzufügen."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "verbinden"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Hinzufügen, entfernen und sortieren von Elementen."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "bis zum #ten Buchstaben von hinten"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "bis zum #ten Buchstaben"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "bis zum letzten Buchstaben"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm"; -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "im Text"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "nehme Teil ab erstem Buchstaben"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "nehme Teil ab #tem Buchstaben von hinten"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "nehme Teil ab #tem Buchstaben"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Gibt den angegebenen Textabschnitt zurück."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm"; -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "im Text"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "suche erstes Auftreten des Begriffs"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "suche letztes Auftreten des Begriffs"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Findet das erste / letzte Auftreten eines Suchbegriffs in einem Text. Gibt die Position des Begriffs zurück oder %1 falls der Suchbegriff nicht gefunden wurde."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 ist leer"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Ist wahr, falls der Text keine Zeichen enthält ist."; -Blockly.Msg.TEXT_JOIN_HELPURL = ""; -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "erstelle Text aus"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Erstellt einen Text durch das Verbinden von mehreren Textelementen."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "Länge von %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Die Anzahl von Zeichen in einem Text (inkl. Leerzeichen)."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "gib aus %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Gibt den Text aus."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Fragt den Benutzer nach einer Zahl."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Fragt den Benutzer nach einem Text."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "frage nach Zahl mit Hinweis"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "frage nach Text mit Hinweis"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://de.wikipedia.org/wiki/Zeichenkette"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Ein Buchstabe, Text oder Satz."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "entferne Leerzeichen vom Anfang und vom Ende (links und rechts)"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "entferne Leerzeichen vom Anfang (links)"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "entferne Leerzeichen vom Ende (rechts)"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Entfernt Leerzeichen vom Anfang und / oder Ende eines Textes."; -Blockly.Msg.TODAY = "Heute"; -Blockly.Msg.UNDO = "Rückgängig"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "etwas"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Erzeuge \"Schreibe %1\""; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://de.wikipedia.org/wiki/Variable_%28Programmierung%29"; -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Gibt den Wert der Variable zurück."; -Blockly.Msg.VARIABLES_SET = "setze %1 auf %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Erzeuge \"Lese %1\""; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://de.wikipedia.org/wiki/Variable_%28Programmierung%29"; -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Setzt den Wert einer Variable."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "Eine Variable namens „%1“ ist bereits vorhanden."; -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/diq.js b/backend/_pv_1_3_5/static/blockly/msg/js/diq.js deleted file mode 100755 index 7d9f5638d..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/diq.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.diq'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Tefsir cı ke"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Erci bıvurne:"; -Blockly.Msg.CLEAN_UP = "Blokan pak ke"; -Blockly.Msg.COLLAPSE_ALL = "Blokan teng ke"; -Blockly.Msg.COLLAPSE_BLOCK = "Bloki teng ke"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "reng 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "reng 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "nısbet"; -Blockly.Msg.COLOUR_BLEND_TITLE = "tewde"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Blends two colours together with a given ratio (0.0 - 1.0)."; // untranslated -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://diq.wikipedia.org/wiki/Reng"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Choose a colour from the palette."; // untranslated -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "rengo rastameye"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Tesadufi yu ren bıweçin"; -Blockly.Msg.COLOUR_RGB_BLUE = "kewe"; -Blockly.Msg.COLOUR_RGB_GREEN = "kıho"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "sur"; -Blockly.Msg.COLOUR_RGB_TITLE = "komponentên rengan"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Create a colour with the specified amount of red, green, and blue. All values must be between 0 and 100."; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "Çerxen ra vec"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "Gama bin da çerxeni ra dewam ke"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Öujtewada çerxeni ra bıvıci"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Skip the rest of this loop, and continue with the next iteration."; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Warning: This block may only be used within a loop."; // untranslated -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "for each item %1 in list %2"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "For each item in a list, set the variable '%1' to the item, and then do some statements."; // untranslated -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "count with %1 from %2 to %3 by %4"; // untranslated -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Have the variable '%1' take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks."; // untranslated -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Bloq da if'i rê yu şert dekerê de."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Add a final, catch-all condition to the if block."; // untranslated -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Add, remove, or reorder sections to reconfigure this if block."; // untranslated -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "çıniyose"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "niyose"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "se"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "If a value is true, then do some statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "If a value is true, then do the first block of statements. Otherwise, do the second block of statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements."; // untranslated -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "bıke"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "%1 fıni tekrar ke"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Do some statements several times."; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "hend tekrar ke"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "Tekrar kerdış de"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Yew erc xırabo se tay beyanati bıd"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Yew erc raşto se yu beyanat bıd."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Pêro %1 bloki besteriyê?"; -Blockly.Msg.DELETE_BLOCK = "Bloki bestere"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "%1 blokan bestere"; -Blockly.Msg.DISABLE_BLOCK = "Çengi devre ra vec"; -Blockly.Msg.DUPLICATE_BLOCK = "Zewnc"; -Blockly.Msg.ENABLE_BLOCK = "Bloki feal ke"; -Blockly.Msg.EXPAND_ALL = "Blokan hera ke"; -Blockly.Msg.EXPAND_BLOCK = "Bloki hera ke"; -Blockly.Msg.EXTERNAL_INPUTS = "Cıkewtışê xarıciy"; -Blockly.Msg.HELP = "Peşti"; -Blockly.Msg.INLINE_INPUTS = "Cıkerdışê xomiyani"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "lista venge vıraze"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Returns a list, of length 0, containing no data records"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "liste"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Add, remove, or reorder sections to reconfigure this list block."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "create list with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Yew nesne dekerê lista miyan"; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Create a list with any number of items."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_FIRST = "verên"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# peyniye ra"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "bıgê"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "Bıgi u wedarne"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "peyên"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "raştameye"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "wedare"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Removes and returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Removes and returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Removes and returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Removes and returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Removes the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Removes the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Removes the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Removes a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "Peyni # ra hetana"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "#'ya"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "Hetana pey"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "get sub-list from first"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "get sub-list from # from end"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "get sub-list from #"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Creates a copy of the specified portion of a list."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 objeyo peyên o"; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 objeyo sıfteyên o"; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "Sıfte bıyayena cay obcey bıvin"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "find last occurrence of item"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Returns the index of the first/last occurrence of the item in the list. Returns %1 if item is not found."; // untranslated -Blockly.Msg.LISTS_INLIST = "lista de"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 vengo"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Eger kı lista venga se raşt keno çerğ"; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "length of %1"; // untranslated -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Derganiya yu lister dano."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "create list with item %1 repeated %2 times"; // untranslated -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Creates a list consisting of the given value repeated the specified number of times."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "zey"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "De fi"; -Blockly.Msg.LISTS_SET_INDEX_SET = "ca ke"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserts the item at the start of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Inserts the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Append the item to the end of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Inserts the item randomly in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Sets the first item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Sets the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Sets the last item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Sets a random item in a list."; // untranslated -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "zeydıyen"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "Kemeyen"; -Blockly.Msg.LISTS_SORT_TITLE = "Kılm %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "Amoriyal"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "Alfabetik"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "make list from text"; // untranslated -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "make text from list"; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "Hududoxi ya"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "ğelet"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Raşt yana çep erc dano"; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "raşt"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Return true if both inputs equal each other."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Return true if the first input is greater than the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Return true if the first input is greater than or equal to the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Return true if the first input is smaller than the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Return true if the first input is smaller than or equal to the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Return true if both inputs are not equal to each other."; // untranslated -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "%1 niyo"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Returns true if the input is false. Returns false if the input is true."; // untranslated -Blockly.Msg.LOGIC_NULL = "veng"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Veng çarneno ra."; -Blockly.Msg.LOGIC_OPERATION_AND = "û"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "ya zi"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Return true if both inputs are true."; // untranslated -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Return true if at least one of the inputs is true."; // untranslated -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "eke ğeleto"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "eke raşto"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Şerta'test'i test keno. Eger ke şert raşta se erca 'raşt'i çarneno, çepo se erca 'çep' çarneno."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Aritmetik"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Return the sum of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Return the quotient of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Return the difference of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Return the product of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Return the first number raised to the power of the second number."; // untranslated -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "%2, keno %1 vurneno"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Add a number to variable '%1'."; // untranslated -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Heryen sabitan ra yewi çerx ke:π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (bêsonp)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "constrain %1 low %2 high %3"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Constrain a number to be between the specified limits (inclusive)."; // untranslated -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "Leteyêno"; -Blockly.Msg.MATH_IS_EVEN = "zewnco"; -Blockly.Msg.MATH_IS_NEGATIVE = "negatifo"; -Blockly.Msg.MATH_IS_ODD = "kıto"; -Blockly.Msg.MATH_IS_POSITIVE = "pozitifo"; -Blockly.Msg.MATH_IS_PRIME = "bıngehên"; -Blockly.Msg.MATH_IS_TOOLTIP = "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false."; // untranslated -Blockly.Msg.MATH_IS_WHOLE = "tamo"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "%1 ÷ %2 ra menden"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Dı amoran ra amora menden çerx ke"; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://diq.wikipedia.org/wiki/Numre"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Yew numre."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "Averacê lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "Tewr gırdê lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "Wertey lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "Tewr qıcê lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "listey modi"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "Raştamaye objeya lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "standard deviation of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "koma liste"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Return the average (arithmetic mean) of the numeric values in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Return the largest number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Return the median number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Return the smallest number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Return a list of the most common item(s) in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Liste ra raştamaye yew elementi çerx ke"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Return the standard deviation of the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Return the sum of all the numbers in the list."; // untranslated -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "Raştamaye nimande amor"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive)."; // untranslated -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "random integer from %1 to %2"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Return a random integer between the two specified limits, inclusive."; // untranslated -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "gılor ke"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "Loğê cêri ke"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "Loğê cori ke"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Yu amorer loğê cêri yana cori ke"; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "mutlaq"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "karekok"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Return the absolute value of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Return e to the power of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Return the natural logarithm of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Return the base 10 logarithm of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Ena amorer nêravêrde deyne çerx ke."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Return 10 to the power of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Return the square root of a number."; // untranslated -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; // untranslated -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Return the arccosine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Return the arcsine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Return the arctangent of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Return the cosine of a degree (not radian)."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Return the sine of a degree (not radian)."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Return the tangent of a degree (not radian)."; // untranslated -Blockly.Msg.NEW_VARIABLE = "Vuriyayeyo bıvıraz..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Namey vuriyayeyê newi:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "Çıyan rê mısafe bıd"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "ebe:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Run the user-defined function '%1'."; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Run the user-defined function '%1' and use its output."; // untranslated -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "ebe:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "'%1' vıraze"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Nê fonksiyoni beyan ke..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "Çıyê bık"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "rê"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Yew fonksiyono çap nêdate vırazeno"; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "peyser biya"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Yew fonksiyono çap daye vırazeno"; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Warning: This function has duplicate parameters."; // untranslated -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Highlight function definition"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "If a value is true, then return a second value."; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Warning: This block may be used only within a function definition."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "nameyê cıkewtışi:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Add an input to the function."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "cıkewtışi"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Add, remove, or reorder inputs to this function."; // untranslated -Blockly.Msg.REDO = "Newe ke"; -Blockly.Msg.REMOVE_COMMENT = "Tefsiri Wedare"; -Blockly.Msg.RENAME_VARIABLE = "Vuriyayey fına name ke..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Rename all '%1' variables to:"; // untranslated -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "Metin dek"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "rê"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Append some text to variable '%1'."; // untranslated -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "Herfanê werdiyana"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "Ser herf gırd"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "HERFANÊ GIRDANA"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; // untranslated -Blockly.Msg.TEXT_CHARAT_FIRST = "Herfa sıfti bıgi"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "# ra tepya herfan bıgi"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "Herfa # bıgi"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "metın de"; -Blockly.Msg.TEXT_CHARAT_LAST = "Herfa peyên bıgi"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "Raştamaye yu herf bıgi"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Şınasnaye pozisyon de yu herfer çerğ keno"; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Add an item to the text."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "gıre de"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Add, remove, or reorder sections to reconfigure this text block."; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "to letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "to letter #"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "to last letter"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "metın de"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "get substring from first letter"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "get substring from letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "# ra substring gêno"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Tay letey metini çerğ keno"; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "metın de"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "find first occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "find last occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found."; // untranslated -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 vengo"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returns true if the provided text is empty."; // untranslated -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "ya metin vıraz"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Create a piece of text by joining together any number of items."; // untranslated -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "length of %1"; // untranslated -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Returns the number of letters (including spaces) in the provided text."; // untranslated -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "print %1"; // untranslated -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Print the specified text, number or other value."; // untranslated -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Prompt for user for a number."; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Prompt for user for some text."; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "prompt for number with message"; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "prompt for text with message"; // untranslated -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Yu herfa, satır yana çekuya metini"; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "trim spaces from both sides of"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "trim spaces from left side of"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "trim spaces from right side of"; // untranslated -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Return a copy of the text with spaces removed from one or both ends."; // untranslated -Blockly.Msg.TODAY = "Ewro"; -Blockly.Msg.UNDO = "Peyser biya"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "unsur"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Create 'set %1'"; // untranslated -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returns the value of this variable."; // untranslated -Blockly.Msg.VARIABLES_SET = "set %1 to %2"; // untranslated -Blockly.Msg.VARIABLES_SET_CREATE_GET = "'get %1' vıraz"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Sets this variable to be equal to the input."; // untranslated -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/el.js b/backend/_pv_1_3_5/static/blockly/msg/js/el.js deleted file mode 100755 index 0445c9bf4..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/el.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.el'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Πρόσθεσε Το Σχόλιο"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Άλλαξε την τιμή:"; -Blockly.Msg.CLEAN_UP = "Clean up Blocks"; // untranslated -Blockly.Msg.COLLAPSE_ALL = "Σύμπτυξτε Όλα Τα Μπλοκ"; -Blockly.Msg.COLLAPSE_BLOCK = "Σύμπτυξε Το Μπλοκ"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "χρώμα 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "χρώμα 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "αναλογία"; -Blockly.Msg.COLOUR_BLEND_TITLE = "μείγμα"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Συνδυάζει δύο χρώματα μαζί με μια δεδομένη αναλογία (0.0 - 1,0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://el.wikipedia.org/wiki/%CE%A7%CF%81%CF%8E%CE%BC%CE%B1"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Επιτρέπει επιλογή χρώματος από την παλέτα."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "τυχαίο χρώμα"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Επιλέγει χρώμα τυχαία."; -Blockly.Msg.COLOUR_RGB_BLUE = "μπλε"; -Blockly.Msg.COLOUR_RGB_GREEN = "πράσινο"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "κόκκινο"; -Blockly.Msg.COLOUR_RGB_TITLE = "χρώμα με"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Δημιουργεί χρώμα με το συγκεκριμένο ποσό του κόκκινου, πράσινου και μπλε που ορίζεις. Όλες οι τιμές πρέπει να είναι μεταξύ 0 και 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "φεύγει από το μπλοκ επαναλήψεως"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "συνέχισε με την επόμενη επανάληψη του μπλοκ επαναλήψεως"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Ξεφεύγει (βγαίνει έξω) από την επανάληψη."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Παραλείπει το υπόλοιπο τμήμα αυτού του μπλοκ επαναλήψεως, και συνεχίζει με την επόμενη επανάληψη."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Προειδοποίηση: Αυτό το μπλοκ μπορεί να χρησιμοποιηθεί μόνο μέσα σε μια επανάληψη."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "για κάθε στοιχείο %1 στη λίστα %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Για κάθε στοιχείο σε μια λίστα, ορίζει τη μεταβλητή «%1» στο στοιχείο και, στη συνέχεια, εκτελεί κάποιες εντολές."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "Blockly"; -Blockly.Msg.CONTROLS_FOR_TITLE = "μέτρησε με %1 από το %2 έως το %3 ανά %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Η μεταβλητή «%1» παίρνει τιμές ξεκινώντας από τον αριθμό έναρξης μέχρι τον αριθμό τέλους αυξάνοντας κάθε φορά με το καθορισμένο βήμα και εκτελώντας το καθορισμένο μπλοκ."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Πρόσθετει μια κατάσταση/συνθήκη στο μπλοκ «εάν»."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Προσθέτει μια τελική κατάσταση/συνθήκη, που πιάνει όλες τις άλλες περιπτώσεις, στο μπλοκ «εάν»."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Προσθέτει, αφαιρεί ή αναδιατάσσει τα τμήματα για να αναδιαμορφώσει αυτό το μπλοκ «εάν»."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "αλλιώς"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "εναλλακτικά εάν"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "εάν"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Αν μια τιμή είναι αληθής, τότε εκτελεί κάποιες εντολές."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Αν μια τιμή είναι αληθής, τότε εκτελεί το πρώτο τμήμα εντολών. Διαφορετικά, εκτελεί το δεύτερο τμήμα εντολών."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Αν η πρώτη τιμή είναι αληθής, τότε εκτελεί το πρώτο τμήμα εντολών. Διαφορετικά, αν η δεύτερη τιμή είναι αληθής, εκτελεί το δεύτερο μπλοκ εντολών."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Αν η πρώτη τιμή είναι αληθής, τότε εκτελεί το πρώτο τμήμα εντολών. Διαφορετικά, αν η δεύτερη τιμή είναι αληθής, εκτελεί το δεύτερο τμήμα εντολών. Αν καμία από τις τιμές δεν είναι αληθής, εκτελεί το τελευταίο τμήμα εντολών."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "κάνε"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "επανάλαβε %1 φορές"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Εκτελεί κάποιες εντολές αρκετές φορές."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "επανάλαβε μέχρι"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "επανάλαβε ενώ"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Ενόσω μια τιμή είναι ψευδής, τότε εκτελεί κάποιες εντολές."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Ενόσω μια τιμή είναι αληθής, τότε εκτελεί κάποιες εντολές."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Να διαγραφούν και τα %1 μπλοκ?"; -Blockly.Msg.DELETE_BLOCK = "Διέγραψε Το Μπλοκ"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Διέγραψε %1 Μπλοκ"; -Blockly.Msg.DISABLE_BLOCK = "Απενεργοποίησε Το Μπλοκ"; -Blockly.Msg.DUPLICATE_BLOCK = "Διπλότυπο"; -Blockly.Msg.ENABLE_BLOCK = "Ενεργοποίησε Το Μπλοκ"; -Blockly.Msg.EXPAND_ALL = "Επέκτεινε Όλα Τα Μπλοκ"; -Blockly.Msg.EXPAND_BLOCK = "Επέκτεινε Το Μπλοκ"; -Blockly.Msg.EXTERNAL_INPUTS = "Εξωτερικές Είσοδοι"; -Blockly.Msg.HELP = "Βοήθεια"; -Blockly.Msg.INLINE_INPUTS = "Εσωτερικές Είσοδοι"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "δημιούργησε κενή λίστα"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Επιστρέφει μια λίστα, με μήκος 0, η οποία δεν περιέχει εγγραφές δεδομένων"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "λίστα"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Προσθέτει, αφαιρεί ή αναδιατάσσει τα τμήματα για να αναδιαμορφώσει αυτό το μπλοκ λίστας."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "δημιούργησε λίστα με"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Προσθέτει αντικείμενο στη λίστα."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Δημιουργεί λίστα με οποιονδήποτε αριθμό αντικειμένων."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "πρώτο"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# από το τέλος"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "πάρε"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "πάρε και αφαίρεσε"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "τελευταίο"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "τυχαίο"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "αφαίρεσε"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Επιστρέφει το πρώτο στοιχείο σε μια λίστα."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Επιστρέφει το στοιχείο στην καθορισμένη θέση σε μια λίστα."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Επιστρέφει το τελευταίο στοιχείο σε μια λίστα."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Επιστρέφει ένα τυχαίο στοιχείο σε μια λίστα."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Καταργεί και επιστρέφει το πρώτο στοιχείο σε μια λίστα."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Καταργεί και επιστρέφει το στοιχείο στην καθορισμένη θέση σε μια λίστα."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Καταργεί και επιστρέφει το τελευταίο στοιχείο σε μια λίστα."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Καταργεί και επιστρέφει ένα τυχαίο στοιχείο σε μια λίστα."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Καταργεί το πρώτο στοιχείο σε μια λίστα."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Καταργεί το στοιχείο στην καθορισμένη θέση σε μια λίστα."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Καταργεί το τελευταίο στοιχείο σε μια λίστα."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Καταργεί ένα τυχαίο στοιχείο σε μια λίστα."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "έως # από το τέλος"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "έως #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "έως το τελευταίο"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "Blockly"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "πάρε υπολίστα από την αρχή"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "πάρε υπολίστα από # από το τέλος"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "πάρε υπολίστα από #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Δημιουργεί ένα αντίγραφο του καθορισμένου τμήματος μιας λίστας."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "Το %1 είναι το τελευταίο στοιχείο."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "Το %1 είναι το πρώτο στοιχείο."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "βρες την πρώτη εμφάνιση του στοιχείου"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "Blockly"; -Blockly.Msg.LISTS_INDEX_OF_LAST = "βρες την τελευταία εμφάνιση του στοιχείου"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Επιστρέφει τον δείκτη της πρώτης/τελευταίας εμφάνισης του στοιχείου στη λίστα. Επιστρέφει τιμή %1, αν το στοιχείο δεν βρεθεί."; -Blockly.Msg.LISTS_INLIST = "στη λίστα"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "το %1 είναι κενό"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Επιστρέφει αληθής αν η λίστα είναι κενή."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "Blockly"; -Blockly.Msg.LISTS_LENGTH_TITLE = "το μήκος του %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Επιστρέφει το μήκος μιας λίστας."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "Blockly"; -Blockly.Msg.LISTS_REPEAT_TITLE = "δημιούργησε λίστα με το στοιχείο %1 να επαναλαμβάνεται %2 φορές"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Δημιουργεί μια λίστα που αποτελείται από την δεδομένη τιμή που επαναλαμβάνεται για συγκεκριμένο αριθμό επαναλήψεων."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "σε"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "είσαγε στο"; -Blockly.Msg.LISTS_SET_INDEX_SET = "όρισε"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Εισάγει το στοιχείο στην αρχή μιας λίστας."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Εισάγει το στοιχείο στην καθορισμένη θέση σε μια λίστα."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Αναθέτει το στοιχείο στο τέλος μιας λίστας."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Εισάγει το στοιχείο τυχαία σε μια λίστα."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Ορίζει το πρώτο στοιχείο σε μια λίστα."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Ορίζει το στοιχείο στην καθορισμένη θέση σε μια λίστα."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Ορίζει το τελευταίο στοιχείο σε μια λίστα."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Ορίζει ένα τυχαίο στοιχείο σε μια λίστα."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "Αύξουσα"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "Φθίνουσα"; -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "αριθμητικό"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "Αλφαβητικά"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "κάνετε λίστα από το κείμενο"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "κάνετε κείμενο από τη λίστα"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Ενώστε μια λίστα κειμένων σε ένα κείμενο, που χωρίζονται από ένα διαχωριστικό."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Διαίρεση του κειμένου σε μια λίστα κειμένων, με σπάσιμο σε κάθε διαχωριστικό."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "με διαχωριστικό"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "ψευδής"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Επιστρέφει είτε αληθής είτε ψευδής."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "αληθής"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Επιστρέφει αληθής αν και οι δύο είσοδοι είναι ίσες μεταξύ τους."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Επιστρέφει αληθής αν η πρώτη είσοδος είναι μεγαλύτερη από τη δεύτερη είσοδο."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Επιστρέφει αληθής αν η πρώτη είσοδος είναι μικρότερη ή ίση με τη δεύτερη είσοδο."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Επιστρέφει αληθής αν η πρώτη είσοδος είναι μικρότερη από τη δεύτερη είσοδο."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Επιστρέφει αληθής αν η πρώτη είσοδος είναι μικρότερη από ή ίση με τη δεύτερη είσοδο."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Επιστρέφει αληθής αν και οι δύο είσοδοι δεν είναι ίσες μεταξύ τους."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "όχι %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Επιστρέφει αληθής αν η είσοδος είναι ψευδής. Επιστρέφει ψευδής αν η είσοδος είναι αληθής."; -Blockly.Msg.LOGIC_NULL = "κενό"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Επιστρέφει κενό."; -Blockly.Msg.LOGIC_OPERATION_AND = "και"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "ή"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Επιστρέφει αληθής αν και οι δύο είσοδοι είναι αληθής."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Επιστρέφει αληθής αν τουλάχιστον μια από τις εισόδους είναι αληθής."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "έλεγχος"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "εάν είναι ψευδής"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "εάν είναι αληθής"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Ελέγχει την κατάσταση/συνθήκη στον «έλεγχο». Αν η κατάσταση/συνθήκη είναι αληθής, επιστρέφει την τιμή «εάν αληθής», διαφορετικά επιστρέφει την τιμή «εάν ψευδής»."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://el.wikipedia.org/wiki/%CE%91%CF%81%CE%B9%CE%B8%CE%BC%CE%B7%CF%84%CE%B9%CE%BA%CE%AE"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Επιστρέφει το άθροισμα των δύο αριθμών."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Επιστρέφει το πηλίκο των δύο αριθμών."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Επιστρέφει τη διαφορά των δύο αριθμών."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Επιστρέφει το γινόμενο των δύο αριθμών."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Επιστρέφει τον πρώτο αριθμό υψωμένο στη δύναμη του δεύτερου αριθμού."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://el.wikipedia.org/wiki/%CE%A0%CF%81%CF%8C%CF%83%CE%B8%CE%B5%CF%83%CE%B7"; -Blockly.Msg.MATH_CHANGE_TITLE = "άλλαξε %1 από %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Προσθέτει έναν αριθμό στη μεταβλητή «%1»."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Επιστρέφει μία από τις κοινές σταθερές: π (3.141...), e (2.718...), φ (1.618...), sqrt(2) (1.414...), sqrt(½) (0.707...), ή ∞ (άπειρο)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "περιόρισε %1 χαμηλή %2 υψηλή %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Περιορίζει έναν αριθμό μεταξύ των προβλεπόμενων ορίων (χωρίς αποκλεισμούς)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "είναι διαιρετός από το"; -Blockly.Msg.MATH_IS_EVEN = "είναι άρτιος"; -Blockly.Msg.MATH_IS_NEGATIVE = "είναι αρνητικός"; -Blockly.Msg.MATH_IS_ODD = "είναι περιττός"; -Blockly.Msg.MATH_IS_POSITIVE = "είναι θετικός"; -Blockly.Msg.MATH_IS_PRIME = "είναι πρώτος"; -Blockly.Msg.MATH_IS_TOOLTIP = "Ελέγχει αν ένας αριθμός είναι άρτιος, περιττός, πρώτος, ακέραιος, θετικός, αρνητικός, ή αν είναι διαιρετός από έναν ορισμένο αριθμό. Επιστρέφει αληθής ή ψευδής."; -Blockly.Msg.MATH_IS_WHOLE = "είναι ακέραιος"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "υπόλοιπο της %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Επιστρέφει το υπόλοιπο της διαίρεσης των δύο αριθμών."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://el.wikipedia.org/wiki/%CE%91%CF%81%CE%B9%CE%B8%CE%BC%CF%8C%CF%82"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Ένας αριθμός."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "μέσος όρος λίστας"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "μεγαλύτερος λίστας"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "διάμεσος λίστας"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "μικρότερος λίστας"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "μορφές λίστας"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "τυχαίο στοιχείο λίστας"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "τυπική απόκλιση λίστας"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "άθροισμα λίστας"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Επιστρέφει τον αριθμητικό μέσο όρο από τις αριθμητικές τιμές στη λίστα."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Επιστρέφει τον μεγαλύτερο αριθμό στη λίστα."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Επιστρέφει τον διάμεσο της λίστας."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Επιστρέφει τον μικρότερο αριθμό στη λίστα."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Επιστρέφει μια λίστα με τα πιο κοινά στοιχεία στη λίστα."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Επιστρέφει ένα τυχαίο στοιχείο από τη λίστα."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Επιστρέφει την τυπική απόκλιση της λίστας."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Επιστρέφει το άθροισμα όλων των αριθμών στη λίστα."; -Blockly.Msg.MATH_POWER_SYMBOL = "^ ύψωση σε δύναμη"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://el.wikipedia.org/wiki/%CE%93%CE%B5%CE%BD%CE%BD%CE%AE%CF%84%CF%81%CE%B9%CE%B1_%CE%A4%CF%85%CF%87%CE%B1%CE%AF%CF%89%CE%BD_%CE%91%CF%81%CE%B9%CE%B8%CE%BC%CF%8E%CE%BD"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "τυχαίο κλάσμα"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Επιστρέψει ένα τυχαία κλάσμα μεταξύ 0,0 (κλειστό) και 1,0 (ανοικτό)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "τυχαίος ακέραιος από το %1 έως το %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Επιστρέφει έναν τυχαίο ακέραιο αριθμό μεταξύ δύο συγκεκριμένων ορίων (εντός - συμπεριλαμβανομένων και των ακραίων τιμών)."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "στρογγυλοποίησε"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "στρογγυλοποίησε προς τα κάτω"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "στρογγυλοποίησε προς τα πάνω"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Στρογγυλοποιεί έναν αριθμό προς τα πάνω ή προς τα κάτω."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://el.wikipedia.org/wiki/%CE%A4%CE%B5%CF%84%CF%81%CE%B1%CE%B3%CF%89%CE%BD%CE%B9%CE%BA%CE%AE_%CF%81%CE%AF%CE%B6%CE%B1"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "απόλυτη"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "τετραγωνική ρίζα"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Επιστρέφει την απόλυτη τιμή ενός αριθμού."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Επιστρέφει το e υψωμένο στη δύναμη ενός αριθμού."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Επιστρέφει τον νεπέρειο λογάριθμο ενός αριθμού."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Επιστρέφει τον λογάριθμο με βάση το 10 ενός αριθμού."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Επιστρέφει την αρνητική ενός αριθμού."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Επιστρέφει το 10 υψωμένο στη δύναμη ενός αριθμού."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Επιστρέφει την τετραγωνική ρίζα ενός αριθμού."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "acos"; -Blockly.Msg.MATH_TRIG_ASIN = "asin"; -Blockly.Msg.MATH_TRIG_ATAN = "atan"; -Blockly.Msg.MATH_TRIG_COS = "συν"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://el.wikipedia.org/wiki/%CE%A4%CF%81%CE%B9%CE%B3%CF%89%CE%BD%CE%BF%CE%BC%CE%B5%CF%84%CF%81%CE%B9%CE%BA%CE%AE_%CF%83%CF%85%CE%BD%CE%AC%CF%81%CF%84%CE%B7%CF%83%CE%B7"; -Blockly.Msg.MATH_TRIG_SIN = "ημ"; -Blockly.Msg.MATH_TRIG_TAN = "εφ"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Επιστρέφει το τόξο συνημίτονου ενός αριθμού."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Επιστρέφει το τόξο ημίτονου ενός αριθμού."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Επιστρέφει το τόξο εφαπτομένης ενός αριθμού."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Επιστρέφει το συνημίτονο ενός βαθμού (όχι ακτινίου)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Επιστρέφει το ημίτονο ενός βαθμού (όχι ακτινίου)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Επιστρέφει την εφαπτομένη ενός βαθμού (όχι ακτινίου)."; -Blockly.Msg.NEW_VARIABLE = "Νέα μεταβλητή..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Νέο όνομα μεταβλητής:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "να επιτρέπονται οι δηλώσεις"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "με:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://el.wikipedia.org/wiki/%CE%94%CE%B9%CE%B1%CE%B4%CE%B9%CE%BA%CE%B1%CF%83%CE%AF%CE%B1_%28%CF%85%CF%80%CE%BF%CE%BB%CE%BF%CE%B3%CE%B9%CF%83%CF%84%CE%AD%CF%82%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Εκτελεί την ορισμένη από τον χρήστη συνάρτηση «%1»."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://el.wikipedia.org/wiki/%CE%94%CE%B9%CE%B1%CE%B4%CE%B9%CE%BA%CE%B1%CF%83%CE%AF%CE%B1_%28%CF%85%CF%80%CE%BF%CE%BB%CE%BF%CE%B3%CE%B9%CF%83%CF%84%CE%AD%CF%82%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Εκτελεί την ορισμένη από τον χρήστη συνάρτηση «%1» και χρησιμοποίησε την έξοδό της."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "με:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Δημιούργησε «%1»"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "κάνε κάτι"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "στο"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Δημιουργεί μια συνάρτηση χωρίς έξοδο."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "επέστρεψε"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Δημιουργεί μια συνάρτηση με μια έξοδο."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Προειδοποίηση: Αυτή η συνάρτηση έχει διπλότυπες παραμέτρους."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Επισημάνετε τον ορισμό συνάρτησης"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Αν μια τιμή είναι αληθής, τότε επιστρέφει τη δεύτερη τιμή."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Προειδοποίηση: Αυτό το μπλοκ μπορεί να χρησιμοποιηθεί μόνο στον ορισμό μιας συνάρτησης."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "όνομα εισόδου:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Πρόσθεσε μια είσοδος στη συνάρτηση"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "είσοδοι"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Προσθέτει, αφαιρεί ή αναδιατάσσει εισόδους σε αυτήν τη λειτουργία"; -Blockly.Msg.REDO = "Ακύρωση αναίρεσης"; -Blockly.Msg.REMOVE_COMMENT = "Αφαίρεσε Το Σχόλιο"; -Blockly.Msg.RENAME_VARIABLE = "Μετονόμασε τη μεταβλητή..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Μετονόμασε όλες τις μεταβλητές «%1» σε:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "ανάθεσε κείμενο"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "έως"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Αναθέτει κείμενο στη μεταβλητή «%1»."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "σε πεζά"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "σε Λέξεις Με Πρώτα Κεφαλαία"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "σε ΚΕΦΑΛΑΙΑ"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Επιστρέφει ένα αντίγραφο του κειμένου σε διαφορετική μορφή γραμμάτων."; -Blockly.Msg.TEXT_CHARAT_FIRST = "πάρε το πρώτο γράμμα"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "πάρε το γράμμα # από το τέλος"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "πάρε το γράμμα #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "στο κείμενο"; -Blockly.Msg.TEXT_CHARAT_LAST = "πάρε το τελευταίο γράμμα"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "πάρε τυχαίο γράμμα"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Επιστρέφει το γράμμα στην καθορισμένη θέση."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Προσθέτει ένα στοιχείο στο κείμενο."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "ένωσε"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Προσθέτει, αφαιρεί ή αναδιατάσσει τους τομείς για να αναδιαμορφώσει αυτό το μπλοκ κειμένου."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "μέχρι το # γράμμα από το τέλος"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "μέχρι το # γράμμα"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "μέχρι το τελευταίο γράμμα"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "στο κείμενο"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "πάρε τη δευτερεύουσα συμβολοσειρά από το πρώτο γράμμα"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "πάρε τη δευτερεύουσα συμβολοσειρά από το # γράμμα από το τέλος"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "πάρε τη δευτερεύουσα συμβολοσειρά από το # γράμμα"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Επιστρέφει ένα συγκεκριμένο τμήμα του κειμένου."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "στο κείμενο"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "βρες την πρώτη εμφάνιση του κειμένου"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "βρες την τελευταία εμφάνιση του κειμένου"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Επιστρέφει τον δείκτη της πρώτης/τελευταίας εμφάνισης του πρώτου κειμένου στο δεύτερο κείμενο. Επιστρέφει τιμή %1, αν δε βρει το κείμενο."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "το %1 είναι κενό"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Επιστρέφει αληθής αν το παρεχόμενο κείμενο είναι κενό."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "δημιούργησε κείμενο με"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Δημιουργεί ένα κομμάτι κειμένου ενώνοντας έναν απεριόριστο αριθμό αντικειμένων."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "το μήκος του %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Επιστρέφει το πλήθος των γραμμάτων (συμπεριλαμβανομένων και των κενών διαστημάτων) στο παρεχόμενο κείμενο."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "εκτύπωσε %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Εκτυπώνει το καθορισμένο κείμενο, αριθμό ή άλλη τιμή."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Δημιουργεί προτροπή για τον χρήστη για να δώσει ένα αριθμό."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Δημιουργεί προτροπή για το χρήστη για να δώσει κάποιο κείμενο."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "πρότρεψε με μήνυμα για να δοθεί αριθμός"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "πρότρεψε με μήνυμα για να δοθεί κείμενο"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://el.wikipedia.org/wiki/%CE%A3%CF%85%CE%BC%CE%B2%CE%BF%CE%BB%CE%BF%CF%83%CE%B5%CE%B9%CF%81%CE%AC"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Ένα γράμμα, μια λέξη ή μια γραμμή κειμένου."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "περίκοψε τα κενά και από τις δυο πλευρές του"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "περίκοψε τα κενά από την αριστερή πλευρά του"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "περίκοψε τα κενά από την δεξιά πλευρά του"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Επιστρέφει ένα αντίγραφο του κειμένου με αφαιρεμένα τα κενά από το ένα ή και τα δύο άκρα."; -Blockly.Msg.TODAY = "Σήμερα"; -Blockly.Msg.UNDO = "Αναίρεση"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "αντικείμενο"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Δημιούργησε «όρισε %1»"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Επιστρέφει την τιμή αυτής της μεταβλητής."; -Blockly.Msg.VARIABLES_SET = "όρισε %1 μέχρι το %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Δημιούργησε «πάρε %1»"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Ορίζει αυτή τη μεταβλητή να είναι ίση με την είσοδο."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/en-gb.js b/backend/_pv_1_3_5/static/blockly/msg/js/en-gb.js deleted file mode 100755 index 7690dfd2e..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/en-gb.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.en.gb'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Add Comment"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Change value:"; -Blockly.Msg.CLEAN_UP = "Clean up Blocks"; -Blockly.Msg.COLLAPSE_ALL = "Collapse Blocks"; -Blockly.Msg.COLLAPSE_BLOCK = "Collapse Block"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "colour 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "colour 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "ratio"; -Blockly.Msg.COLOUR_BLEND_TITLE = "blend"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Blends two colours together with a given ratio (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Colour"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Choose a colour from the palette."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "random colour"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Choose a colour at random."; -Blockly.Msg.COLOUR_RGB_BLUE = "blue"; -Blockly.Msg.COLOUR_RGB_GREEN = "green"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "red"; -Blockly.Msg.COLOUR_RGB_TITLE = "colour with"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Create a colour with the specified amount of red, green, and blue. All values must be between 0 and 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "break out of loop"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "continue with next iteration of loop"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Break out of the containing loop."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Skip the rest of this loop, and continue with the next iteration."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Warning: This block may only be used within a loop."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "for each item %1 in list %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "For each item in a list, set the variable '%1' to the item, and then do some statements."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "count with %1 from %2 to %3 by %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Have the variable '%1' take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Add a condition to the if block."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Add a final, catch-all condition to the if block."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Add, remove, or reorder sections to reconfigure this if block."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "else"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "else if"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "if"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "If a value is true, then do some statements."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "If a value is true, then do the first block of statements. Otherwise, do the second block of statements."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "do"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "repeat %1 times"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Do some statements several times."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "repeat until"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "repeat while"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "While a value is false, then do some statements."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "While a value is true, then do some statements."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Delete all %1 blocks?"; -Blockly.Msg.DELETE_BLOCK = "Delete Block"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Delete %1 Blocks"; -Blockly.Msg.DISABLE_BLOCK = "Disable Block"; -Blockly.Msg.DUPLICATE_BLOCK = "Duplicate"; -Blockly.Msg.ENABLE_BLOCK = "Enable Block"; -Blockly.Msg.EXPAND_ALL = "Expand Blocks"; -Blockly.Msg.EXPAND_BLOCK = "Expand Block"; -Blockly.Msg.EXTERNAL_INPUTS = "External Inputs"; -Blockly.Msg.HELP = "Help"; -Blockly.Msg.INLINE_INPUTS = "Inline Inputs"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "create empty list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Returns a list, of length 0, containing no data records"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "list"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Add, remove, or reorder sections to reconfigure this list block."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "create list with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Add an item to the list."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Create a list with any number of items."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_FIRST = "first"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# from end"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "get"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "get and remove"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_LAST = "last"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "random"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "remove"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Removes and returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Removes and returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Removes and returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Removes and returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Removes the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Removes the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Removes the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Removes a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "to # from end"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "to #"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "to last"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "get sub-list from first"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "get sub-list from # from end"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "get sub-list from #"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Creates a copy of the specified portion of a list."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 is the last item."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 is the first item."; // untranslated -Blockly.Msg.LISTS_INDEX_OF_FIRST = "find first occurrence of item"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "find last occurrence of item"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Returns the index of the first/last occurrence of the item in the list. Returns %1 if item is not found."; // untranslated -Blockly.Msg.LISTS_INLIST = "in list"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 is empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Returns true if the list is empty."; // untranslated -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "length of %1"; // untranslated -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Returns the length of a list."; // untranslated -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "create list with item %1 repeated %2 times"; // untranslated -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Creates a list consisting of the given value repeated the specified number of times."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "as"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INSERT = "insert at"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_SET = "set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserts the item at the start of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Inserts the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Append the item to the end of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Inserts the item randomly in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Sets the first item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Sets the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Sets the last item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Sets a random item in a list."; // untranslated -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descendente"; -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "make list from text"; // untranslated -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "make text from list"; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "false"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Returns either true or false."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "true"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Return true if both inputs equal each other."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Return true if the first input is greater than the second input."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Return true if the first input is greater than or equal to the second input."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Return true if the first input is smaller than the second input."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Return true if the first input is smaller than or equal to the second input."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Return true if both inputs are not equal to each other."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "not %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Returns true if the input is false. Returns false if the input is true."; -Blockly.Msg.LOGIC_NULL = "null"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Returns null."; -Blockly.Msg.LOGIC_OPERATION_AND = "and"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "or"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Return true if both inputs are true."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Return true if at least one of the inputs is true."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "if false"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "if true"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Arithmetic"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Return the sum of the two numbers."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Return the quotient of the two numbers."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Return the difference of the two numbers."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Return the product of the two numbers."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Return the first number raised to the power of the second number."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "change %1 by %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Add a number to variable '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "constrain %1 low %2 high %3"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Constrain a number to be between the specified limits (inclusive)."; // untranslated -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "is divisible by"; -Blockly.Msg.MATH_IS_EVEN = "is even"; -Blockly.Msg.MATH_IS_NEGATIVE = "is negative"; -Blockly.Msg.MATH_IS_ODD = "is odd"; -Blockly.Msg.MATH_IS_POSITIVE = "is positive"; -Blockly.Msg.MATH_IS_PRIME = "is prime"; -Blockly.Msg.MATH_IS_TOOLTIP = "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false."; -Blockly.Msg.MATH_IS_WHOLE = "is whole"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; // untranslated -Blockly.Msg.MATH_MODULO_TITLE = "remainder of %1 ÷ %2"; // untranslated -Blockly.Msg.MATH_MODULO_TOOLTIP = "Return the remainder from dividing the two numbers."; // untranslated -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "A number."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "average of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "max of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "median of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "min of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "modes of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "random item of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "standard deviation of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "sum of list"; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Return the average (arithmetic mean) of the numeric values in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Return the largest number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Return the median number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Return the smallest number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Return a list of the most common item(s) in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Return a random element from the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Return the standard deviation of the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Return the sum of all the numbers in the list."; // untranslated -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "random fraction"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive)."; // untranslated -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TITLE = "random integer from %1 to %2"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Return a random integer between the two specified limits, inclusive."; // untranslated -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "round"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "round down"; // untranslated -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "round up"; // untranslated -Blockly.Msg.MATH_ROUND_TOOLTIP = "Round a number up or down."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absolute"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "square root"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Return the absolute value of a number."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Return e to the power of a number."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Return the natural logarithm of a number."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Return the base 10 logarithm of a number."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Return the negation of a number."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Return 10 to the power of a number."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Return the square root of a number."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Return the arccosine of a number."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Return the arcsine of a number."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Return the arctangent of a number."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Return the cosine of a degree (not radian)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Return the sine of a degree (not radian)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Return the tangent of a degree (not radian)."; -Blockly.Msg.NEW_VARIABLE = "New variable..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "New variable name:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "allow statements"; // untranslated -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "with:"; // untranslated -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Run the user-defined function '%1'."; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Run the user-defined function '%1' and use its output."; // untranslated -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "with:"; // untranslated -Blockly.Msg.PROCEDURES_CREATE_DO = "Create '%1'"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "do something"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "to"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Creates a function with no output."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "return"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Creates a function with an output."; // untranslated -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Warning: This function has duplicate parameters."; // untranslated -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Highlight function definition"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "If a value is true, then return a second value."; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Warning: This block may be used only within a function definition."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "input name:"; // untranslated -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Add an input to the function."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "inputs"; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Add, remove, or reorder inputs to this function."; // untranslated -Blockly.Msg.REDO = "Redo"; -Blockly.Msg.REMOVE_COMMENT = "Remove Comment"; -Blockly.Msg.RENAME_VARIABLE = "Rename variable..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Rename all '%1' variables to:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "append text"; // untranslated -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "to"; // untranslated -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Append some text to variable '%1'."; // untranslated -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "to lower case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "to Title Case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "to UPPER CASE"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; // untranslated -Blockly.Msg.TEXT_CHARAT_FIRST = "get first letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_FROM_END = "get letter # from end"; // untranslated -Blockly.Msg.TEXT_CHARAT_FROM_START = "get letter #"; // untranslated -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "in text"; // untranslated -Blockly.Msg.TEXT_CHARAT_LAST = "get last letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_RANDOM = "get random letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Returns the letter at the specified position."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Add an item to the text."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "join"; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Add, remove, or reorder sections to reconfigure this text block."; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "to letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "to letter #"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "to last letter"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "in text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "get substring from first letter"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "get substring from letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "get substring from letter #"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returns a specified portion of the text."; // untranslated -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "in text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "find first occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "find last occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found."; // untranslated -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 is empty"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returns true if the provided text is empty."; // untranslated -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "create text with"; // untranslated -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Create a piece of text by joining together any number of items."; // untranslated -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "length of %1"; // untranslated -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Returns the number of letters (including spaces) in the provided text."; // untranslated -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "print %1"; // untranslated -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Print the specified text, number or other value."; // untranslated -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Prompt for user for a number."; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Prompt for user for some text."; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "prompt for number with message"; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "prompt for text with message"; // untranslated -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; // untranslated -Blockly.Msg.TEXT_TEXT_TOOLTIP = "A letter, word, or line of text."; // untranslated -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "trim spaces from both sides of"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "trim spaces from left side of"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "trim spaces from right side of"; // untranslated -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Return a copy of the text with spaces removed from one or both ends."; // untranslated -Blockly.Msg.TODAY = "Today"; -Blockly.Msg.UNDO = "Undo"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "item"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Create 'set %1'"; // untranslated -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returns the value of this variable."; // untranslated -Blockly.Msg.VARIABLES_SET = "set %1 to %2"; // untranslated -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Create 'get %1'"; // untranslated -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Sets this variable to be equal to the input."; // untranslated -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/en.js b/backend/_pv_1_3_5/static/blockly/msg/js/en.js deleted file mode 100755 index 1020c64dd..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/en.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.en'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Add Comment"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Change value:"; -Blockly.Msg.CLEAN_UP = "Clean up Blocks"; -Blockly.Msg.COLLAPSE_ALL = "Collapse Blocks"; -Blockly.Msg.COLLAPSE_BLOCK = "Collapse Block"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "colour 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "colour 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "ratio"; -Blockly.Msg.COLOUR_BLEND_TITLE = "blend"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Blends two colours together with a given ratio (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Choose a colour from the palette."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; -Blockly.Msg.COLOUR_RANDOM_TITLE = "random colour"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Choose a colour at random."; -Blockly.Msg.COLOUR_RGB_BLUE = "blue"; -Blockly.Msg.COLOUR_RGB_GREEN = "green"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "red"; -Blockly.Msg.COLOUR_RGB_TITLE = "colour with"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Create a colour with the specified amount of red, green, and blue. All values must be between 0 and 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "break out of loop"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "continue with next iteration of loop"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Break out of the containing loop."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Skip the rest of this loop, and continue with the next iteration."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Warning: This block may only be used within a loop."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; -Blockly.Msg.CONTROLS_FOREACH_TITLE = "for each item %1 in list %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "For each item in a list, set the variable '%1' to the item, and then do some statements."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; -Blockly.Msg.CONTROLS_FOR_TITLE = "count with %1 from %2 to %3 by %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Have the variable '%1' take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Add a condition to the if block."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Add a final, catch-all condition to the if block."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Add, remove, or reorder sections to reconfigure this if block."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "else"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "else if"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "if"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "If a value is true, then do some statements."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "If a value is true, then do the first block of statements. Otherwise, do the second block of statements."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "do"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "repeat %1 times"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Do some statements several times."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "repeat until"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "repeat while"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "While a value is false, then do some statements."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "While a value is true, then do some statements."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Delete all %1 blocks?"; -Blockly.Msg.DELETE_BLOCK = "Delete Block"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; -Blockly.Msg.DELETE_X_BLOCKS = "Delete %1 Blocks"; -Blockly.Msg.DISABLE_BLOCK = "Disable Block"; -Blockly.Msg.DUPLICATE_BLOCK = "Duplicate"; -Blockly.Msg.ENABLE_BLOCK = "Enable Block"; -Blockly.Msg.EXPAND_ALL = "Expand Blocks"; -Blockly.Msg.EXPAND_BLOCK = "Expand Block"; -Blockly.Msg.EXTERNAL_INPUTS = "External Inputs"; -Blockly.Msg.HELP = "Help"; -Blockly.Msg.INLINE_INPUTS = "Inline Inputs"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "create empty list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Returns a list, of length 0, containing no data records"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "list"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Add, remove, or reorder sections to reconfigure this list block."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "create list with"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Add an item to the list."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Create a list with any number of items."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "first"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# from end"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "get"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "get and remove"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "last"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "random"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "remove"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Returns the first item in a list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Returns the item at the specified position in a list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Returns the last item in a list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Returns a random item in a list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Removes and returns the first item in a list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Removes and returns the item at the specified position in a list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Removes and returns the last item in a list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Removes and returns a random item in a list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Removes the first item in a list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Removes the item at the specified position in a list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Removes the last item in a list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Removes a random item in a list."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "to # from end"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "to #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "to last"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "get sub-list from first"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "get sub-list from # from end"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "get sub-list from #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Creates a copy of the specified portion of a list."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 is the last item."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 is the first item."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "find first occurrence of item"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; -Blockly.Msg.LISTS_INDEX_OF_LAST = "find last occurrence of item"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Returns the index of the first/last occurrence of the item in the list. Returns %1 if item is not found."; -Blockly.Msg.LISTS_INLIST = "in list"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 is empty"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Returns true if the list is empty."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; -Blockly.Msg.LISTS_LENGTH_TITLE = "length of %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Returns the length of a list."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg.LISTS_REPEAT_TITLE = "create list with item %1 repeated %2 times"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Creates a list consisting of the given value repeated the specified number of times."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "as"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "insert at"; -Blockly.Msg.LISTS_SET_INDEX_SET = "set"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserts the item at the start of a list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Inserts the item at the specified position in a list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Append the item to the end of a list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Inserts the item randomly in a list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Sets the first item in a list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Sets the item at the specified position in a list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Sets the last item in a list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Sets a random item in a list."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "make list from text"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "make text from list"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "false"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Returns either true or false."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "true"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Return true if both inputs equal each other."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Return true if the first input is greater than the second input."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Return true if the first input is greater than or equal to the second input."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Return true if the first input is smaller than the second input."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Return true if the first input is smaller than or equal to the second input."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Return true if both inputs are not equal to each other."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; -Blockly.Msg.LOGIC_NEGATE_TITLE = "not %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Returns true if the input is false. Returns false if the input is true."; -Blockly.Msg.LOGIC_NULL = "null"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Returns null."; -Blockly.Msg.LOGIC_OPERATION_AND = "and"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; -Blockly.Msg.LOGIC_OPERATION_OR = "or"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Return true if both inputs are true."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Return true if at least one of the inputs is true."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "if false"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "if true"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Arithmetic"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Return the sum of the two numbers."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Return the quotient of the two numbers."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Return the difference of the two numbers."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Return the product of the two numbers."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Return the first number raised to the power of the second number."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "change %1 by %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Add a number to variable '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; -Blockly.Msg.MATH_CONSTRAIN_TITLE = "constrain %1 low %2 high %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Constrain a number to be between the specified limits (inclusive)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "is divisible by"; -Blockly.Msg.MATH_IS_EVEN = "is even"; -Blockly.Msg.MATH_IS_NEGATIVE = "is negative"; -Blockly.Msg.MATH_IS_ODD = "is odd"; -Blockly.Msg.MATH_IS_POSITIVE = "is positive"; -Blockly.Msg.MATH_IS_PRIME = "is prime"; -Blockly.Msg.MATH_IS_TOOLTIP = "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false."; -Blockly.Msg.MATH_IS_WHOLE = "is whole"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "remainder of %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Return the remainder from dividing the two numbers."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "A number."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "average of list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "max of list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "median of list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "min of list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "modes of list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "random item of list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "standard deviation of list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "sum of list"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Return the average (arithmetic mean) of the numeric values in the list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Return the largest number in the list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Return the median number in the list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Return the smallest number in the list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Return a list of the most common item(s) in the list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Return a random element from the list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Return the standard deviation of the list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Return the sum of all the numbers in the list."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "random fraction"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "random integer from %1 to %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Return a random integer between the two specified limits, inclusive."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "round"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "round down"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "round up"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Round a number up or down."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absolute"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "square root"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Return the absolute value of a number."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Return e to the power of a number."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Return the natural logarithm of a number."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Return the base 10 logarithm of a number."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Return the negation of a number."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Return 10 to the power of a number."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Return the square root of a number."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "acos"; -Blockly.Msg.MATH_TRIG_ASIN = "asin"; -Blockly.Msg.MATH_TRIG_ATAN = "atan"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tan"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Return the arccosine of a number."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Return the arcsine of a number."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Return the arctangent of a number."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Return the cosine of a degree (not radian)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Return the sine of a degree (not radian)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Return the tangent of a degree (not radian)."; -Blockly.Msg.NEW_VARIABLE = "Create variable..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "New variable name:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "allow statements"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "with:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Run the user-defined function '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Run the user-defined function '%1' and use its output."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "with:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Create '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "do something"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "to"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Creates a function with no output."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "return"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Creates a function with an output."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Warning: This function has duplicate parameters."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Highlight function definition"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "If a value is true, then return a second value."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Warning: This block may be used only within a function definition."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "input name:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Add an input to the function."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "inputs"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Add, remove, or reorder inputs to this function."; -Blockly.Msg.REDO = "Redo"; -Blockly.Msg.REMOVE_COMMENT = "Remove Comment"; -Blockly.Msg.RENAME_VARIABLE = "Rename variable..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Rename all '%1' variables to:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "append text"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; -Blockly.Msg.TEXT_APPEND_TO = "to"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Append some text to variable '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "to lower case"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "to Title Case"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "to UPPER CASE"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; -Blockly.Msg.TEXT_CHARAT_FIRST = "get first letter"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "get letter # from end"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "get letter #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "in text"; -Blockly.Msg.TEXT_CHARAT_LAST = "get last letter"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "get random letter"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Returns the letter at the specified position."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Add an item to the text."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "join"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Add, remove, or reorder sections to reconfigure this text block."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "to letter # from end"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "to letter #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "to last letter"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "in text"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "get substring from first letter"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "get substring from letter # from end"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "get substring from letter #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returns a specified portion of the text."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "in text"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "find first occurrence of text"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "find last occurrence of text"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 is empty"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returns true if the provided text is empty."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "create text with"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Create a piece of text by joining together any number of items."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; -Blockly.Msg.TEXT_LENGTH_TITLE = "length of %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Returns the number of letters (including spaces) in the provided text."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; -Blockly.Msg.TEXT_PRINT_TITLE = "print %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Print the specified text, number or other value."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Prompt for user for a number."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Prompt for user for some text."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "prompt for number with message"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "prompt for text with message"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "A letter, word, or line of text."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "trim spaces from both sides of"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "trim spaces from left side of"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "trim spaces from right side of"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Return a copy of the text with spaces removed from one or both ends."; -Blockly.Msg.TODAY = "Today"; -Blockly.Msg.UNDO = "Undo"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "item"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Create 'set %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returns the value of this variable."; -Blockly.Msg.VARIABLES_SET = "set %1 to %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Create 'get %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Sets this variable to be equal to the input."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/es.js b/backend/_pv_1_3_5/static/blockly/msg/js/es.js deleted file mode 100755 index 399f4fd7e..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/es.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.es'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Añadir comentario"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Cambiar el valor:"; -Blockly.Msg.CLEAN_UP = "Limpiar los bloques"; -Blockly.Msg.COLLAPSE_ALL = "Contraer bloques"; -Blockly.Msg.COLLAPSE_BLOCK = "Contraer bloque"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "color 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "color 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "proporción"; -Blockly.Msg.COLOUR_BLEND_TITLE = "combinar"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Combina dos colores con una proporción determinada (0,0–1,0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://es.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Elige un color de la paleta."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "color aleatorio"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Elige un color al azar."; -Blockly.Msg.COLOUR_RGB_BLUE = "azul"; -Blockly.Msg.COLOUR_RGB_GREEN = "verde"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "rojo"; -Blockly.Msg.COLOUR_RGB_TITLE = "colorear con"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Crea un color con cantidades específicas de rojo, verde y azul. Todos los valores deben encontrarse entre 0 y 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "romper el bucle"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "continuar con la siguiente iteración del bucle"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Romper el bucle que lo contiene."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Saltar el resto de este bucle, y continuar con la siguiente iteración."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "ADVERTENCIA: Este bloque puede usarse sólo dentro de un bucle."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://es.wikipedia.org/wiki/Foreach"; -Blockly.Msg.CONTROLS_FOREACH_TITLE = "para cada elemento %1 en la lista %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Para cada elemento en una lista, establecer la variable '%1' al elemento y luego hacer algunas declaraciones."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "contar con %1 desde %2 hasta %3 de a %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Hacer que la variable \"%1\" tome los valores desde el número de inicio hasta el número final, contando con el intervalo especificado, y hacer los bloques especificados."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Agregar una condición a este bloque."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Agregar una condición general final a este bloque."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Agregar, eliminar o reordenar las secciones para reconfigurar este bloque."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "sino"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "sino si"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "si"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Si un valor es verdadero, entonces hacer algunas declaraciones."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Si un valor es verdadero, entonces hacer el primer bloque de declaraciones. De lo contrario, hacer el segundo bloque de declaraciones."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Si el primer valor es verdadero, entonces hacer el primer bloque de declaraciones. De lo contrario, si el segundo valor es verdadero, hacer el segundo bloque de declaraciones."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Si el primer valor es verdadero, entonces hacer el primer bloque de declaraciones. De lo contrario, si el segundo valor es verdadero, hacer el segundo bloque de declaraciones. Si ninguno de los valores son verdaderos, hacer el último bloque de declaraciones."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://es.wikipedia.org/wiki/Bucle_for"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "hacer"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "repetir %1 veces"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Hacer algunas declaraciones varias veces."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "repetir hasta"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "repetir mientras"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Mientras un valor sea falso, entonces hacer algunas declaraciones."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Mientras un valor sea verdadero, entonces hacer algunas declaraciones."; -Blockly.Msg.DELETE_ALL_BLOCKS = "¿Eliminar todos los %1 bloques?"; -Blockly.Msg.DELETE_BLOCK = "Eliminar bloque"; -Blockly.Msg.DELETE_VARIABLE = "Borrar la variable \"%1\""; -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "¿Borrar %1 usos de la variable \"%2\"?"; -Blockly.Msg.DELETE_X_BLOCKS = "Eliminar %1 bloques"; -Blockly.Msg.DISABLE_BLOCK = "Desactivar bloque"; -Blockly.Msg.DUPLICATE_BLOCK = "Duplicar"; -Blockly.Msg.ENABLE_BLOCK = "Activar bloque"; -Blockly.Msg.EXPAND_ALL = "Expandir bloques"; -Blockly.Msg.EXPAND_BLOCK = "Expandir bloque"; -Blockly.Msg.EXTERNAL_INPUTS = "Entradas externas"; -Blockly.Msg.HELP = "Ayuda"; -Blockly.Msg.INLINE_INPUTS = "Entradas en línea"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "crear lista vacía"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Devuelve una lista, de longitud 0, sin ningún dato"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "lista"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Agregar, eliminar o reorganizar las secciones para reconfigurar este bloque de lista."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "crear lista con"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Agregar un elemento a la lista."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Crear una lista con cualquier número de elementos."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "primero"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# del final"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "obtener"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "obtener y eliminar"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "último"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "aleatorio"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "eliminar"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Devuelve el primer elemento de una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Devuelve el elemento en la posición especificada en una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Devuelve el último elemento de una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Devuelve un elemento aleatorio en una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Elimina y devuelve el primer elemento de una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Elimina y devuelve el elemento en la posición especificada en una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Elimina y devuelve el último elemento de una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Elimina y devuelve un elemento aleatorio en una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Elimina el primer elemento de una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Elimina el elemento en la posición especificada en una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Elimina el último elemento de una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Elimina un elemento aleatorio en una lista."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "hasta # del final"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "hasta #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "hasta el último"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "obtener sublista desde el primero"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "obtener sublista desde # del final"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "obtener sublista desde #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Crea una copia de la parte especificada de una lista."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 es el último elemento."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 es el primer elemento."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "encontrar la primera aparición del elemento"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "encontrar la última aparición del elemento"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Devuelve el índice de la primera/última aparición del elemento en la lista. Devuelve %1 si el elemento no se encuentra."; -Blockly.Msg.LISTS_INLIST = "en la lista"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 está vacía"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Devuelve verdadero si la lista está vacía."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "longitud de %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Devuelve la longitud de una lista."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "crear lista con el elemento %1 repetido %2 veces"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Crea una lista que consta de un valor dado repetido el número de veces especificado."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "como"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "insertar en"; -Blockly.Msg.LISTS_SET_INDEX_SET = "establecer"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserta el elemento al inicio de una lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Inserta el elemento en la posición especificada en una lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Añade el elemento al final de una lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Inserta el elemento aleatoriamente en una lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Establece el primer elemento de una lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Establece el elemento en la posición especificada en una lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Establece el último elemento de una lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Establece un elemento aleatorio en una lista."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascendente"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descendente"; -Blockly.Msg.LISTS_SORT_TITLE = "orden %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Ordenar una copia de una lista."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alfabético, ignorar mayúscula/minúscula"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numérico"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alfabético"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "hacer lista a partir de texto"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "hacer texto a partir de lista"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Unir una lista de textos en un solo texto, separado por un delimitador."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Dividir el texto en una lista de textos, separando en cada delimitador."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "con delimitador"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "falso"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Devuelve verdadero o falso."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "verdadero"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://es.wikipedia.org/wiki/Desigualdad_matemática"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Devuelve verdadero si ambas entradas son iguales."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Devuelve verdadero si la primera entrada es mayor que la segunda entrada."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Devuelve verdadero si la primera entrada es mayor o igual a la segunda entrada."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Devuelve verdadero si la primera entrada es menor que la segunda entrada."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Devuelve verdadero si la primera entrada es menor que o igual a la segunda entrada."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Devuelve verdadero si ambas entradas son distintas."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "no %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Devuelve verdadero si la entrada es falsa. Devuelve falso si la entrada es verdadera."; -Blockly.Msg.LOGIC_NULL = "nulo"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Devuelve nulo."; -Blockly.Msg.LOGIC_OPERATION_AND = "y"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "o"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Devuelve verdadero si ambas entradas son verdaderas."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Devuelve verdadero si al menos una de las entradas es verdadera."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "prueba"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "si es falso"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "si es verdadero"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Comprueba la condición en \"prueba\". Si la condición es verdadera, devuelve el valor \"si es verdadero\"; de lo contrario, devuelve el valor \"si es falso\"."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://es.wikipedia.org/wiki/Aritmética"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Devuelve la suma de ambos números."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Devuelve el cociente de ambos números."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Devuelve la diferencia de ambos números."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Devuelve el producto de ambos números."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Devuelve el primer número elevado a la potencia del segundo."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "añadir %2 a %1"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Añadir un número a la variable «%1»."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://es.wikipedia.org/wiki/Anexo:Constantes_matemáticas"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Devuelve una de las constantes comunes: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…) o ∞ (infinito)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "limitar %1 entre %2 y %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Limitar un número entre los límites especificados (inclusive)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "es divisible por"; -Blockly.Msg.MATH_IS_EVEN = "es par"; -Blockly.Msg.MATH_IS_NEGATIVE = "es negativo"; -Blockly.Msg.MATH_IS_ODD = "es impar"; -Blockly.Msg.MATH_IS_POSITIVE = "es positivo"; -Blockly.Msg.MATH_IS_PRIME = "es primo"; -Blockly.Msg.MATH_IS_TOOLTIP = "Comprueba si un número es par, impar, primo, entero, positivo, negativo, o si es divisible por un número determinado. Devuelve verdadero o falso."; -Blockly.Msg.MATH_IS_WHOLE = "es entero"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "resto de %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Devuelve el resto al dividir los dos números."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://es.wikipedia.org/wiki/Número"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Un número."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "promedio de la lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "máximo de la lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "mediana de la lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "mínimo de la lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "modas de la lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "elemento aleatorio de la lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "desviación estándar de la lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "suma de la lista"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Devuelve el promedio (media aritmética) de los valores numéricos en la lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Devuelve el número más grande en la lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Devuelve la mediana en la lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Devuelve el número más pequeño en la lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Devuelve una lista de los elementos más comunes en la lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Devuelve un elemento aleatorio de la lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Devuelve la desviación estándar de la lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Devuelve la suma de todos los números en la lista."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://es.wikipedia.org/wiki/Generador_de_números_aleatorios"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "fracción aleatoria"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Devuelve una fracción aleatoria entre 0,0 (ambos inclusive) y 1.0 (exclusivo)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://es.wikipedia.org/wiki/Generador_de_números_aleatorios"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "entero aleatorio de %1 a %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Devuelve un entero aleatorio entre los dos límites especificados, inclusive."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://es.wikipedia.org/wiki/Redondeo"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "redondear"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "redondear hacia abajo"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "redondear hacia arriba"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Redondear un número hacia arriba o hacia abajo."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://es.wikipedia.org/wiki/Ra%C3%ADz_cuadrada"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absoluto"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "raíz cuadrada"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Devuelve el valor absoluto de un número."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Devuelve e a la potencia de un número."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Devuelve el logaritmo natural de un número."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Devuelve el logaritmo base 10 de un número."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Devuelve la negación de un número."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Devuelve 10 a la potencia de un número."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Devuelve la raíz cuadrada de un número."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://es.wikipedia.org/wiki/Función_trigonométrica"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Devuelve el arcocoseno de un número."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Devuelve el arcoseno de un número."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Devuelve el arcotangente de un número."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Devuelve el coseno de un grado (no radián)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Devuelve el seno de un grado (no radián)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Devuelve la tangente de un grado (no radián)."; -Blockly.Msg.NEW_VARIABLE = "Crear variable…"; -Blockly.Msg.NEW_VARIABLE_TITLE = "Nombre de variable nueva:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "permitir declaraciones"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "con:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://es.wikipedia.org/wiki/Subrutina"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Ejecuta la función definida por el usuario '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://es.wikipedia.org/wiki/Subrutina"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Ejecuta la función definida por el usuario '%1' y usa su salida."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "con:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Crear '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe esta función..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "hacer algo"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "para"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Crea una función sin salida."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "devuelve"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Crea una función con una salida."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Advertencia: Esta función tiene parámetros duplicados."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Destacar definición de la función"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Si un valor es verdadero, entonces devuelve un segundo valor."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Advertencia: Este bloque solo puede ser utilizado dentro de la definición de una función."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "nombre de entrada:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Añadir una entrada a la función."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "entradas"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Añadir, eliminar o reordenar entradas para esta función."; -Blockly.Msg.REDO = "Rehacer"; -Blockly.Msg.REMOVE_COMMENT = "Eliminar comentario"; -Blockly.Msg.RENAME_VARIABLE = "Renombrar la variable…"; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Renombrar todas las variables «%1» a:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "añadir texto"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "a"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Añadir texto a la variable '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "a minúsculas"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "a Mayúsculas Cada Palabra"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "a MAYÚSCULAS"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Devuelve una copia del texto en un caso diferente."; -Blockly.Msg.TEXT_CHARAT_FIRST = "obtener la primera letra"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "obtener la letra # del final"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "obtener la letra #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "en el texto"; -Blockly.Msg.TEXT_CHARAT_LAST = "obtener la última letra"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "obtener letra aleatoria"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Devuelve la letra en la posición especificada."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Agregar un elemento al texto."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "unir"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Agregar, eliminar o reordenar las secciones para reconfigurar este bloque de texto."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "hasta la letra # del final"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "hasta la letra #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "hasta la última letra"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "en el texto"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "obtener subcadena desde la primera letra"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "obtener subcadena desde la letra # del final"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "obtener subcadena desde la letra #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Devuelve una porción determinada del texto."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "en el texto"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "encontrar la primera aparición del texto"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "encontrar la última aparición del texto"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Devuelve el índice de la primera/última aparición del primer texto en el segundo texto. Devuelve %1 si el texto no se encuentra."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 está vacío"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Devuelve verdadero si el texto proporcionado está vacío."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "crear texto con"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Crear un fragmento de texto al unir cualquier número de elementos."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "longitud de %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Devuelve el número de letras (incluyendo espacios) en el texto proporcionado."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "imprimir %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Imprimir el texto, número u otro valor especificado."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Solicitar al usuario un número."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Solicitar al usuario un texto."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "solicitar número con el mensaje"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "solicitar texto con el mensaje"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://es.wikipedia.org/wiki/Cadena_de_caracteres"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Una letra, palabra o línea de texto."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "quitar espacios de ambos lados de"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "quitar espacios iniciales de"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "quitar espacios finales de"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Devuelve una copia del texto sin los espacios de uno o ambos extremos."; -Blockly.Msg.TODAY = "Hoy"; -Blockly.Msg.UNDO = "Deshacer"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "elemento"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Crear 'establecer %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Devuelve el valor de esta variable."; -Blockly.Msg.VARIABLES_SET = "establecer %1 a %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Crear 'obtener %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Establece esta variable para que sea igual a la entrada."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "Ya existe una variable llamada \"%1\"."; -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/et.js b/backend/_pv_1_3_5/static/blockly/msg/js/et.js deleted file mode 100755 index d5e8f3e62..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/et.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.et'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Lisa kommentaar"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Muuda väärtust:"; -Blockly.Msg.CLEAN_UP = "Korista plokid kokku"; -Blockly.Msg.COLLAPSE_ALL = "Tõmba plokid kokku"; -Blockly.Msg.COLLAPSE_BLOCK = "Tõmba plokk kokku"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "1. värvist"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "2. värvist"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "suhtega"; -Blockly.Msg.COLOUR_BLEND_TITLE = "segu"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Segab kaks värvi määratud suhtega (0.0 - 1.0) kokku."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Valitud värv paletist."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "juhuslik värv"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Juhuslikult valitud värv."; -Blockly.Msg.COLOUR_RGB_BLUE = "sinisest"; -Blockly.Msg.COLOUR_RGB_GREEN = "rohelisest"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "punasest"; -Blockly.Msg.COLOUR_RGB_TITLE = "segu"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Tekitab värvi määratud hulgast punasest, rohelisest ja sinisest. Kõik väärtused peavad olema 0 ja 100 vahel."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "katkesta kordus"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "liigu järgmisele kordusele"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Katkestab korduse ja liigub edasi korduse järel oleva koodi käivitamisele."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Katkestab korduse sees oleva koodi käivitamise ja käivitab järgmise korduse."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Hoiatus: Seda plokki saab kasutada ainult korduse sees."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "iga elemendiga %1 loendis %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Iga elemendiga loendis anna muutujale '%1' elemendi väärtus ja kõivita plokis olevad käsud."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "loenda muutujaga %1 alates %2 kuni %3 %4 kaupa"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Annab muutujale '%1' väärtused ühest numbrist teiseni, muutes seda intervalli kaupa ja käivitab igal muudatusel ploki sees oleva koodi."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Lisab „kui“ plokile tingimuse."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Lisab „kui“ plokile lõpliku tingimuseta koodiploki."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Selle „kui“ ploki muutmine sektsioonide lisamise, eemaldamise ja järjestamisega."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "vastasel juhul"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "vastasel juhul, kui"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "kui"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Kui avaldis on tõene, käivita ploki sees olevad käsud."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Kui avaldis on tõene, käivita käsud esimesest plokist. Vastasel juhul käivita käsud teisest plokist."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Kui esimene avaldis on tõene, käivita käsud esimesest plokist. Vastasel juhul, kui teine avaldis on tõene, käivita käsud teisest plokist."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Kui esimene avaldis on tõene, käivita käsud esimesest plokist. Vastasel juhul, kui teine avaldis on tõene, käivita käsud teisest plokist. Kui ükski avaldistest pole tõene, käivita käsud viimasest plokist."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "käivita"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "kordus %1 korda"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Plokis olevate käskude käivitamine mitu korda."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "kordus kuni pole"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "kordus kuni on"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Kuni avaldis pole tõene, korda plokis olevaid käske."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Kuni avaldis on tõene, korda plokis olevaid käske."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Kas kustutada kõik %1 plokki?"; -Blockly.Msg.DELETE_BLOCK = "Kustuta plokk"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Kustuta %1 plokki"; -Blockly.Msg.DISABLE_BLOCK = "Keela ploki kasutamine"; -Blockly.Msg.DUPLICATE_BLOCK = "Tekita duplikaat"; -Blockly.Msg.ENABLE_BLOCK = "Luba ploki kasutamine"; -Blockly.Msg.EXPAND_ALL = "Laota plokid laiali"; -Blockly.Msg.EXPAND_BLOCK = "Laota plokk laiali"; -Blockly.Msg.EXTERNAL_INPUTS = "Sisendid ploki taga"; -Blockly.Msg.HELP = "Abi"; -Blockly.Msg.INLINE_INPUTS = "Sisendid ploki sees"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "tühi loend"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Tagastab loendi, mille pikkus on 0 ja milles pole ühtegi elementi."; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "loend"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Loendiploki elementide lisamine, eemaldamine või järjestuse muutmine."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "loend elementidest"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Elemendi lisamine loendisse."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Tekitab mistahes arvust elementidest loendi."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "esimene element"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# lõpust"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "võta"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "võta ja eemalda"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "viimane element"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "juhuslik element"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "eemalda"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Tagastab loendi esimese elemendi."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Tagastab loendis määratud asukohal oleva elemendi."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Tagastab loendi viimase elemendi."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Tagastab loendi juhusliku elemendi."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Tagastab ja eemaldab loendist esimese elemendi."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Tagastab ja eemaldab loendist määratud asukohal oleva elemendi."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Tagastab ja eemaldab loendist viimase elemendi."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Tagastab ja eemaldab loendist juhusliku elemendi."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Eemaldab loendist esimese elemendi."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Eemaldab loendist määratud asukohal oleva elemendi."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Eemaldab loendist viimase elemendi."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Eemaldab loendist juhusliku elemendi."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "elemendini # (lõpust)"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "elemendini #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "lõpuni"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "alamloend algusest"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "alamloend elemendist # (lõpust)"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "alamloend elemendist #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Tekitab loendi määratud osast koopia."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "Viimane element on %1."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "Esimene element on %1."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "esimene leitud element"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "viimane leitud element"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Tagastab esimese/viimase loendist leitud elemendi asukoha (järjekorranumbri). Kui elementi ei leita, tagastab %1."; -Blockly.Msg.LISTS_INLIST = "loendis"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 on tühi"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Tagastab „tõene“ kui loend on tühi."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "%1 pikkus"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Tagastab loendi pikkuse."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "loend pikkusega %2 elemendist %1"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Tekitab uue loendi, millesse lisatakse ühte elementi pikkusega määratud arv kordi."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "väärtus:"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "lisa asukohale"; -Blockly.Msg.LISTS_SET_INDEX_SET = "asenda"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Lisab loendi algusesse uue elemendi."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Lisab määratud asukohale loendis uue elemendi."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Lisab loendi lõppu uue elemendi."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Lisab juhuslikule kohale loendis uue elemendi."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Asendab loendis esimese elemendi."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Asendab loendis määratud kohal oleva elemendi."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Asendab loendis viimase elemendi."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Asendab loendis juhusliku elemendi."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "kasvavalt"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "kahanevalt"; -Blockly.Msg.LISTS_SORT_TITLE = "%1 %2 sorteeritud %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Loendi koopia sorteerimine."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "tähestiku järgi (tähesuurust eirates)"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "arvväärtuste järgi"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "tähestiku järgi"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "loend, tekitatud tekstist"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "tekst, tekitatud loendist"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Ühendab tekstide loendis olevad tükid üheks tekstiks, asetades tükkide vahele eraldaja."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Tükeldab teksti eraldajade kohalt ja asetab tükid tekstide loendisse."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "eraldajaga"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "väär"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Tagastab tõeväärtuse – kas „tõene“ või „väär“."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "tõene"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Tagastab „tõene“, kui avaldiste väärtused on võrdsed."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Tagastab „tõene“, kui esimese avaldise väärtus on suurem kui teise väärtus."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Tagastab „tõene“, kui esimese avaldise väärtus on suurem või võrdne teise väärtusega."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Tagastab „tõene“, kui esimese avaldise väärtus on väiksem kui teise väärtus."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Tagastab „tõene“, kui esimese avaldise väärtus on väiksem või võrdne teise väärtusega."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Tagastab „tõene“, kui avaldiste väärtused pole võrdsed."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "pole %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Tagastab „tõene“, kui avaldis on väär. Tagastab „väär“, kui avaldis on tõene."; -Blockly.Msg.LOGIC_NULL = "null"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Tagastab nulli."; -Blockly.Msg.LOGIC_OPERATION_AND = "ja"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "või"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Tagastab „tõene“, kui mõlemad avaldised on tõesed."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Tagastab „tõene“, kui vähemalt üks avaldistest on tõene."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "tingimus"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "kui väär"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "kui tõene"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Kui tingimuse väärtus on tõene, tagastab „kui tõene“ väärtuse, vastasel juhul „kui väär“ väärtuse."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://et.wikipedia.org/wiki/Aritmeetika"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Tagastab kahe arvu summa."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Tagastab kahe arvu jagatise."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Tagastab kahe arvu vahe."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Tagastab kahe arvu korrutise."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Tagastab esimese arvu teise arvu astmes."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "muuda %1 %2 võrra"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Lisab arvu muutujale '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Tagastab ühe konstantidest: π (3,141…), e (2,718…), φ (1.618…), √2) (1,414…), √½ (0,707…), või ∞ (infinity)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "%1 piirang %2 ja %3 vahele"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Piirab arvu väärtuse toodud piiridesse (piirarvud kaasa arvatud)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "jagub arvuga"; -Blockly.Msg.MATH_IS_EVEN = "on paarisarv"; -Blockly.Msg.MATH_IS_NEGATIVE = "on negatiivne arv"; -Blockly.Msg.MATH_IS_ODD = "on paaritu arv"; -Blockly.Msg.MATH_IS_POSITIVE = "on positiivne arv"; -Blockly.Msg.MATH_IS_PRIME = "on algarv"; -Blockly.Msg.MATH_IS_TOOLTIP = "Kontrollib kas arv on paarisarv, paaritu arv, algarv, täisarv, positiivne, negatiivne või jagub kindla arvuga. Tagastab „tõene“ või „väär“."; -Blockly.Msg.MATH_IS_WHOLE = "on täisarv"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "%1 ÷ %2 jääk"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Tagastab esimese numbri teisega jagamisel tekkiva jäägi."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://et.wikipedia.org/wiki/Arv"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Arv."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "loendi keskmine"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "loendi maksimum"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "loendi mediaan"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "loendi miinimum"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "loendi moodid"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "juhuslik element loendist"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "loendi standardhälve"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "loendi summa"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Tagastab loendis olevate arvväärtuste aritmeetilise keskmise."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Tagastab suurima loendis oleva arvu."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Return the median number in the list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Tagastab väikseima loendis oleva arvu."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Tagastab loendi kõige sagedamini esinevate loendi liikmetega."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Tagastab juhusliku elemendi loendist."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Tagastab loendi standardhälbe."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Tagastab kõigi loendis olevate arvude summa."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "juhuslik murdosa"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Tagastab juhusliku murdosa 0.0 (kaasa arvatud) and 1.0 (välja arvatud) vahel."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "juhuslik täisarv %1 ja %2 vahel"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Tagastab juhusliku täisarvu toodud piiride vahel (piirarvud kaasa arvatud)."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "ümarda"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "ümarda alla"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "ümarda üles"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Ümardab arvu üles või alla."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://et.wikipedia.org/wiki/Ruutjuur"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absoluutväärtus"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "ruutjuur"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Tagastab arvu absoluutväärtuse."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Tagasta e arvu astmes."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Tagastab arvu naturaallogaritmi."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Tagastab arvu kümnendlogaritm."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Tagastab arvu vastandväärtuse."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Tagastab 10 arvu astmes."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Tagastab arvu ruutjuure."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://et.wikipedia.org/wiki/Trigonomeetrilised_funktsioonid"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Tagastab arvu arkuskoosiinuse."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Tagastab arvu arkussiinuse."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Tagastab arvu arkustangensi."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Tagastab arvu (kraadid) kosiinuse."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Tagastab arvu (kraadid) siinuse."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Tagastab arvu (kraadid) tangensi."; -Blockly.Msg.NEW_VARIABLE = "Uus muutuja ..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Uue muutuja nimi:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "kood plokis"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "sisenditega:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Käivitab kasutaja defineeritud funktsiooni '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Run the user-defined function '%1' and use its output."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "sisenditega:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Tekita '%1' plokk"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Funktsiooni kirjeldus ..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "teeme midagi"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "funktsioon"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Tekitab funktsiooni, mis ei tagasta midagi."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "tagasta"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Tekitab funktsiooni, mis tagastab midagi."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Hoiatus: Sel funktsioonil on mitu sama nimega sisendit."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Tõsta funktsiooni definitsioon esile"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Kui väärtus on tõene, tagastatakse teine väärtus."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Hoiatus: Seda plokki saab kasutada ainult funktsiooni definitsioonis."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "sisend nimega:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Lisab funktsioonile sisendi."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "sisendid"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Funktsiooni sisendite lisamine, eemaldamine või järjestuse muutmine."; -Blockly.Msg.REDO = "Tee uuesti"; -Blockly.Msg.REMOVE_COMMENT = "Eemalda kommentaar"; -Blockly.Msg.RENAME_VARIABLE = "Nimeta muutuja ümber ..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Muutuja „%1“ uus nimi:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "lõppu tekst"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "lisa muutuja"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Lisab teksti muutuja „%1“ väärtuse lõppu."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "väikeste tähtedega"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "Suurte Esitähtedega"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "SUURTE TÄHTEDEGA"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Tagastab muudetud tähesuurusega teksti koopia."; -Blockly.Msg.TEXT_CHARAT_FIRST = "esimene sümbol"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "lõpust sümbol #"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "sümbol #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "tekstist"; -Blockly.Msg.TEXT_CHARAT_LAST = "viimane sümbol"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "juhuslik sümbol"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Tagastab tekstis määratud asukohal oleva sümboli."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Objekti lisamine tekstile."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "ühenda"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Tekstiploki muutmine sektsioonide lisamise, eemaldamise või järjestuse muutmisega."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "kuni (lõpust) sümbolini #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "kuni sümbolini #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "kuni viimase sümbolini"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "tekstist"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "alates esimesest sümbolist"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "alates (lõpust) sümbolist #"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "alates sümbolist #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Tagastab määratud tüki tekstist."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "tekstist"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "esimese leitud tekstitüki"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "viimase leitud tekstitüki"; -Blockly.Msg.TEXT_INDEXOF_TAIL = "asukoht"; -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Tagastab esimesest tekstist esimese/viimase leitud teise teksti asukoha (indeksi). Kui teksti ei leita, tagastab %1."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 on tühi"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Tagastab „tõene“, kui tekstis pole ühtegi sümbolit."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "tekita tekst"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Tekitab teksti ühendades mistahes arvu elemente."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "%1 pikkus"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Tagastab sümbolite aru (ka tühikud) toodud tekstis."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "trüki %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Trükib määratud teksti, numbri või mõne muu objekti väärtuse."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Küsib kasutajalt teadet näidates mingit arvu."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Küsib kasutajalt teadet näidates mingit teksti."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "kasutajalt küsitud arv teatega"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "kasutajalt küsitud tekst teatega"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Täht, sõna või rida teksti."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "mõlemalt poolt eemaldatud tühikutega"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "algusest eemaldatud tühikutega"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "lõpust eemaldatud tühikutega"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Tagastab koopia tekstist, millel on tühikud ühelt või mõlemalt poolt eemaldatud."; -Blockly.Msg.TODAY = "Täna"; -Blockly.Msg.UNDO = "Võta tagasi"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "objekt"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Tekita 'määra „%1“ väärtuseks' plokk"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Tagastab selle muutuja väärtuse."; -Blockly.Msg.VARIABLES_SET = "\"määra %1 väärtuseks %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Tekita '„%1“ väärtus' plokk"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Määrab selle muutuja väärtuse võrdseks sisendi väärtusega."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/fa.js b/backend/_pv_1_3_5/static/blockly/msg/js/fa.js deleted file mode 100755 index 399e043eb..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/fa.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.fa'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "افزودن نظر"; -Blockly.Msg.CHANGE_VALUE_TITLE = "تغییر مقدار:"; -Blockly.Msg.CLEAN_UP = "تمیز کردن بلوک‌ها"; -Blockly.Msg.COLLAPSE_ALL = "فروپاشی بلوک‌ها"; -Blockly.Msg.COLLAPSE_BLOCK = "فروپاشی بلوک"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "رنگ ۱"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "رنگ ۲"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "نسبت"; -Blockly.Msg.COLOUR_BLEND_TITLE = "مخلوط"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "دو رنگ را با نسبت مشخص‌شده مخلوط می‌کند (۰٫۰ - ۱٫۰)"; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://fa.wikipedia.org/wiki/%D8%B1%D9%86%DA%AF"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "انتخاب یک رنگ از تخته‌رنگ."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "رنگ تصادفی"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "انتخاب یک رنگ به شکل تصادفی."; -Blockly.Msg.COLOUR_RGB_BLUE = "آبی"; -Blockly.Msg.COLOUR_RGB_GREEN = "سبز"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "قرمز"; -Blockly.Msg.COLOUR_RGB_TITLE = "رنگ با"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "ساخت یک رنگ با مقدار مشخص‌شده‌ای از قرمز، سبز و آبی. همهٔ مقادیر باید بین ۰ تا ۱۰۰ باشند."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "شکستن حلقه"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "ادامه با تکرار بعدی حلقه"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "شکستن حلقهٔ شامل."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "پریدن از بقیهٔ حلقه و ادامه با تکرار بعدی."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "اخطار: این بلوک ممکن است فقط داخل یک حلقه استفاده شود."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "برای هر مورد %1 در فهرست %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "برای هر مورد در این فهرست، تنظیم متغیر «%1» به مورد و انجام تعدادی عبارت."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "با تعداد %1 از %2 به %3 با گام‌های %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "متغیر %1 را در مقادیر شروع‌شده از عدد انتهای به عدد انتهایی را دارد، با فواصل مشخص‌شده می‌شمارد و این بلوک مشخص‌شده را انجام می‌دهد."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "افزودن یک شرط به بلوک اگر."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "اضافه کردن نهایی، گرفتن همهٔ شرایط به بلوک اگر."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "افزودن، حذف یا بازمرتب‌سازی قسمت‌ها برای پیکربندی دوبارهٔ این بلوک اگر."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "آنگاه"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "اگر آنگاه"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "اگر"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "اگر یک مقدار صحیح است، سپس چند عبارت را انجام بده."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "اگر یک مقدار صحیح است، اول بلوک اول عبارات را انجام بده. در غیر این صورت بلوک دوم عبارات انجام بده."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "اگر مقدار اول صحیح بود، از آن بلوک اول عبارات را انجام بده. در غیر این صورت، اگر مقدار دوم صحیح است، بلوک دوم عبارات را انجام بده."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "اگر مقدار اول درست است، بلوک اول عبارات را انجام بده. در غیر این صورت، اگر مقدار دوم درست باشد بلوک دوم عبارات را انجام بده. اگر هیچ از مقادیر درست نبود، آخرین بلوک عبارات را انجام بده."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://fa.wikipedia.org/wiki/%D8%AD%D9%84%D9%82%D9%87_%D9%81%D9%88%D8%B1"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "انحام"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "%1 بار تکرار"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "انجام چند عبارت چندین بار."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "تکرار تا زمانی که"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "تکرار در حالی که"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "تا زمانی که یک مقدار ناصحیح است، چند عبارت را انجام بده."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "تا زمانی که یک مقدار صحیح است، چند عبارت را انجام بده."; -Blockly.Msg.DELETE_ALL_BLOCKS = "حذف همهٔ بلاک‌های %1؟"; -Blockly.Msg.DELETE_BLOCK = "حذف بلوک"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "حذف بلوک‌های %1"; -Blockly.Msg.DISABLE_BLOCK = "غیرفعال‌سازی بلوک"; -Blockly.Msg.DUPLICATE_BLOCK = "تکراری"; -Blockly.Msg.ENABLE_BLOCK = "فعال‌سازی بلوک"; -Blockly.Msg.EXPAND_ALL = "گسترش بلوک‌ها"; -Blockly.Msg.EXPAND_BLOCK = "گسترش بلوک"; -Blockly.Msg.EXTERNAL_INPUTS = "ورودی‌های خارجی"; -Blockly.Msg.HELP = "راهنما"; -Blockly.Msg.INLINE_INPUTS = "ورودی‌های درون خطی"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "ایجاد فهرست خالی"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "فهرستی با طول صفر شامل هیچ رکورد داده‌ای بر می‌گرداند."; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "فهرست"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "اضافه کردن، حذف کردن یا ترتیب‌سازی مجدد بخش‌ها این بلوک فهرستی."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "ایجاد فهرست با"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "اضافه کردن یک مورد به فهرست."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "فهرستی از هر عددی از موارد می‌سازد."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "اولین"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# از انتها"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "گرفتن"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "گرفتن و حذف‌کردن"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "آخرین"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "تصادفی"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "حذف‌کردن"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "اولین مورد یک فهرست را بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "موردی در محل مشخص‌شده بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "آخرین مورد در یک فهرست را بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "یک مورد تصادفی در یک فهرست بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "اولین مورد مشخص‌شده در فهرست را حذف و بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "مورد در محل مشخص‌شده در فهرست را حذف و بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "آخرین مورد مشخص‌شده در فهرست را حذف و بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "مورد تصادفی‌ای را در فهرست حذف و بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "اولین مورد را در یک فهرست حذف می‌کند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "مورد مشخص‌شده در موقعیت مشخص در یک فهرست را حذف و بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "آخرین مورد را در یک فهرست حذف می‌کند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "یک مورد تصادفی را یک فهرست حذف می‌کند."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "به # از انتها"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "به #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "به آخرین"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "گرفتن زیرمجموعه‌ای از ابتدا"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "گرفتن زیرمجموعه‌ای از # از انتها"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "گرفتن زیرمجموعه‌ای از #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "کپی از قسمت مشخص‌شدهٔ لیست درست می‌کند."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 آخرین مورد است."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 اولین مورد است."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "یافتن اولین رخ‌داد مورد"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "یافتن آخرین رخ‌داد مورد"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "شاخصی از اولین/آخرین رخ‌داد مورد در فهرست را بر می‌گرداند. %1 بر می‌گرداند اگر آیتم موجود نبود."; -Blockly.Msg.LISTS_INLIST = "در فهرست"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 خالی است"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "اگر فهرست خالی است مقدار صجیج بر می‌گرداند."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "طول %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "طول یک فهرست را برمی‌گرداند."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "فهرستی با %1 تکرارشده به اندازهٔ %2 می‌سازد"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "فهرستی شامل مقادیر داده‌شدهٔ تکرار شده عدد مشخص‌شده می‌سازد."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "به عنوان"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "درج در"; -Blockly.Msg.LISTS_SET_INDEX_SET = "مجموعه"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "موردی به ته فهرست اضافه می‌کند."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "موردی در موقعیت مشخص‌شده در یک فهرست اضافه می‌کند."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "موردی به ته فهرست الحاق می‌کند."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "مورد را به صورت تصادفی در یک فهرست می‌افزاید."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "اولین مورد در یک فهرست را تعیین می‌کند."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "مورد مشخص‌شده در یک فهرست را قرار می‌دهد."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "آخرین مورد در یک فهرست را تعیین می‌کند."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "یک مورد تصادفی در یک فهرست را تعیین می‌کند."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "صعودی"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "نزولی"; -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "حروفی ، رد کردن مورد"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "عددی"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "حروفی ، الفبایی"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "ایجاد فهرست از متن"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "ایجاد متن از فهرست"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "همراه جداساز"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "ناصحیح"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "بازگرداندن یکی از صحیح یا ناصحیح."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "صحیح"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://fa.wikipedia.org/wiki/%D9%86%D8%A7%D8%A8%D8%B1%D8%A7%D8%A8%D8%B1%DB%8C"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "بازگشت صحیح اگر هر دو ورودی با یکدیگر برابر باشد."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "بازگرداندن صحیح اگر ورودی اول بزرگتر از ورودی دوم باشد."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "بازگرداندن صحیح اگر ورودی اول بزرگتر یا مساوی یا ورودی دوم باشد."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "بازگرداندن صحیح اگر ورودی اول کوچکتر از ورودی دوم باشد."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "بازگرداندن صحیح اگر ورودی اول کوچکتر یا مساوی با ورودی دوم باشد."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "برگرداندن صحیح اگر هر دو ورودی با یکدیگر برابر نباشند."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "نه %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "صجیج باز می‌گرداند اگر ورودی نا صحیح باشند. ناصحیح بازمی‌گرداند اگر ورودی صحیح باشد."; -Blockly.Msg.LOGIC_NULL = "تهی"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "تهی بازمی‌گرداند."; -Blockly.Msg.LOGIC_OPERATION_AND = "و"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "یا"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "بازگرداندن صحیح اگر هر دو ورودی صحیح باشد."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "بازگرداندن صحیح اگر یکی از دو ورودی صحیح باشد."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "آزمایش"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "اگر ناصحیح"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "اگر صحیح"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "بررسی وضعیت در «آزمایش». اگر وضعیت صحیح باشد، مقدار «اگر صحیح» را بر می‌گرداند در غیر اینصورت مقدار «اگر ناصحیح» را."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://fa.wikipedia.org/wiki/%D8%AD%D8%B3%D8%A7%D8%A8"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "بازگرداندن مقدار جمع دو عدد."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "بازگرداندن باقی‌ماندهٔ دو عدد."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "بازگرداندن تفاوت دو عدد."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "بازگرداندن حاصلضرب دو عدد."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "بازگرداندن اولین عددی که از توان عدد دوم حاصل شده باشد."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://fa.wikipedia.org/wiki/%D8%A7%D8%B5%D8%B7%D9%84%D8%A7%D8%AD_%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87%E2%80%8C%D9%86%D9%88%DB%8C%D8%B3%DB%8C#.D8.A7.D9.81.D8.B2.D8.A7.DB.8C.D8.B4_.D8.B4.D9.85.D8.A7.D8.B1.D9.86.D8.AF.D9.87"; -Blockly.Msg.MATH_CHANGE_TITLE = "تغییر %1 با %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "افزودن یک عدد به متغیر '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://fa.wikipedia.org/wiki/%D8%AB%D8%A7%D8%A8%D8%AA_%D8%B1%DB%8C%D8%A7%D8%B6%DB%8C"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "یکی از مقادیر مشترک را برمی‌گرداند: π (۳٫۱۴۱…)، e (۲٫۷۱۸...)، φ (۱٫۶۱۸)، sqrt(۲) (۱٫۴۱۴)، sqrt(۱/۲) (۰٫۷۰۷...) و یا ∞ (بی‌نهایت)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "محدودکردن %1 پایین %2 بالا %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "محدودکردن یک عدد بین محدودیت‌های مشخص‌شده (بسته)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "تقسیم شده بر"; -Blockly.Msg.MATH_IS_EVEN = "زوج است"; -Blockly.Msg.MATH_IS_NEGATIVE = "منفی است"; -Blockly.Msg.MATH_IS_ODD = "فرد است"; -Blockly.Msg.MATH_IS_POSITIVE = "مثبت است"; -Blockly.Msg.MATH_IS_PRIME = "عدد اول است"; -Blockly.Msg.MATH_IS_TOOLTIP = "بررسی می‌کند که آیا یک عدد زوج، فرد، اول، کامل، مثبت، منفی یا بخش‌پذیر عدد خاصی باشد را بررسی می‌کند. درست یا نادرست باز می‌گرداند."; -Blockly.Msg.MATH_IS_WHOLE = "کامل است"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://fa.wikipedia.org/wiki/%D8%B9%D9%85%D9%84%DB%8C%D8%A7%D8%AA_%D9%BE%DB%8C%D9%85%D8%A7%D9%86%D9%87"; -Blockly.Msg.MATH_MODULO_TITLE = "باقی‌ماندهٔ %1 + %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "باقی‌ماندهٔ تقسیم دو عدد را بر می‌گرداند."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://fa.wikipedia.org/wiki/%D8%B9%D8%AF%D8%AF"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "یک عدد."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "میانگین فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "بزرگ‌ترین فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "میانهٔ فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "کوچکترین فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "مد فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "مورد تصادفی از فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "انحراف معیار فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "جمع فهرست"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "میانگین (میانگین ریاضی) مقادیر عددی فهرست را بر می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "بزرگ‌ترین عدد در فهرست را باز می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "میانهٔ عدد در فهرست را بر می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "کوچک‌ترین عدد در فهرست را باز می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "شایع‌ترین قلم(های) در فهرست را بر می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "موردی تصادفی از فهرست را بر می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "انحراف معیار فهرست را بر می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "جمع همهٔ عددهای فهرست را باز می‌گرداند."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://fa.wikipedia.org/wiki/%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D8%A7%D8%B9%D8%AF%D8%A7%D8%AF_%D8%AA%D8%B5%D8%A7%D8%AF%D9%81%DB%8C"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "کسر تصادفی"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "بازگرداندن کسری تصادفی بین ۰٫۰ (بسته) تا ۱٫۰ (باز)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://fa.wikipedia.org/wiki/%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D8%A7%D8%B9%D8%AF%D8%A7%D8%AF_%D8%AA%D8%B5%D8%A7%D8%AF%D9%81%DB%8C"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "عدد صحیح تصادفی بین %1 تا %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "یک عدد تصادفی بین دو مقدار مشخص‌شده به صورت بسته باز می‌گرداند."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "گردکردن"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "گرد به پایین"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "گرد به بالا"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "گردکردن یک عدد به بالا یا پایین."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://fa.wikipedia.org/wiki/%D8%B1%DB%8C%D8%B4%D9%87_%D8%AF%D9%88%D9%85"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "مطلق"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "ریشهٔ دوم"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "قدر مطلق یک عدد را بازمی‌گرداند."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "بازگرداندن توان e یک عدد."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "لوگاریتم طبیعی یک عدد را باز می‌گرداند."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "بازگرداندن لگاریتم بر پایهٔ ۱۰ یک عدد."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "منفی‌شدهٔ یک عدد را باز می‌گرداند."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "بازگرداندن توان ۱۰ یک عدد."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "ریشهٔ دوم یک عدد را باز می‌گرداند."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://fa.wikipedia.org/wiki/%D8%AA%D8%A7%D8%A8%D8%B9%E2%80%8C%D9%87%D8%A7%DB%8C_%D9%85%D8%AB%D9%84%D8%AB%D8%A7%D8%AA%DB%8C"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "بازگرداندن آرک‌کسینوس درجه (نه رادیان)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "بازگرداندن آرک‌سینوس درجه (نه رادیان)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "بازگرداندن آرک‌تانژانت درجه (نه رادیان)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "بازگرداندن کسینوس درجه (نه رادیان)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "بازگرداندن سینوس درجه (نه رادیان)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "بازگرداندن تانژانت یک درجه (نه رادیان)."; -Blockly.Msg.NEW_VARIABLE = "متغیر تازه..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "نام متغیر تازه:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "اجازه اظهارات"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "با:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "اجرای تابع تعریف‌شده توسط کاربر «%1»."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "اجرای تابع تعریف‌شده توسط کاربر «%1» و استفاده از خروجی آن."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "با:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "ساختن «%1»"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "توصیف این عملکرد..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "انجام چیزی"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "به"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "تابعی می‌سازد بدون هیچ خروجی."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "بازگشت"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "تابعی با یک خروجی می‌سازد."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "اخطار: این تابعی پارامتر تکراری دارد."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "برجسته‌سازی تعریف تابع"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "اگر یک مقدار صحیح است، مقدار دوم را برگردان."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "اخطار: این بلوک احتمالاً فقط داخل یک تابع استفاده می‌شود."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "نام ورودی:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "اضافه کردن ورودی به تابع."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "ورودی‌ها"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "افزودن، حذف یا دوباره مرتب‌کردن ورودی این تابع."; -Blockly.Msg.REDO = "واگردانی"; -Blockly.Msg.REMOVE_COMMENT = "حذف نظر"; -Blockly.Msg.RENAME_VARIABLE = "تغییر نام متغیر..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "تغییر نام همهٔ متغیرهای «%1» به:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "الحاق متن"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "به"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "الحاق متنی به متغیر «%1»."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "به حروف کوچک"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "به حروف بزرگ عنوان"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "به حروف بزرگ"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "بازگرداندن کپی متن در حالتی متفاوت."; -Blockly.Msg.TEXT_CHARAT_FIRST = "گرفتن اولین حرف"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "گرفتن حرف # از آخر"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "گرفتن حرف #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "در متن"; -Blockly.Msg.TEXT_CHARAT_LAST = "گرفتن آخرین حرف"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "گرفتن حرف تصادفی"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "حرفی در موقعیت مشخص‌شده بر می‌گرداند."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "افزودن یک مورد به متن."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "عضویت"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "اضافه کردن، حذف یا مرتب‌سازی بحش‌ها برای تنظیم مجدد این بلوک متنی."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "به حرف # از انتها"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "به حرف #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "به آخرین حرف"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "در متن"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "گرفتن زیرمتن از اولین حرف"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "گرفتن زیرمتن از حرف # به انتها"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "گرفتن زیرمتن از حرف #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "قسمت مشخصی‌شده‌ای از متن را بر می‌گرداند."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "در متن"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "اولین رخداد متن را بیاب"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "آخرین رخداد متن را بیاب"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "شاخصی از اولین آخرین رخ‌داد متن اول در متن دوم بر می‌گرداند. اگر متن یافت نشد %1 باز می‌گرداند."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 خالی است"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "اضافه کردن صحیح اگر متن فراهم‌شده خالی است."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "ایجاد متن با"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "یک تکه‌ای از متن را با چسپاندن همهٔ تعداد از موارد ایجاد می‌کند."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "طول %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "بازگرداندن عددی از حروف (شامل فاصله‌ها) در متن فراهم‌شده."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "چاپ %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "چاپ متن، عدد یا هر مقدار دیگر مشخص‌شده."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "اعلان برای کاربر با یک عدد."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "اعلان برای کاربر برای یک متن."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "اعلان برای عدد با پیام"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "اعلان برای متن با پیام"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://fa.wikipedia.org/wiki/%D8%B1%D8%B4%D8%AA%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "یک حرف، کلمه یا خطی از متن."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "تراشیدن فاصله‌ها از هر دو طرف"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "تراشیدن فاصله‌ها از طرف چپ"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "تراشیدن فاصله‌ها از طرف چپ"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "کپی از متن با فاصله‌های حذف‌شده از یک یا هر دو پایان باز می‌گرداند."; -Blockly.Msg.TODAY = "امروز"; -Blockly.Msg.UNDO = "واگردانی"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "مورد"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "درست‌کردن «تنظیم %1»"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "مقدار این متغیر را بر می‌گرداند."; -Blockly.Msg.VARIABLES_SET = "مجموعه %1 به %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "درست‌کردن «گرفتن %1»"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "متغیر برابر با خروجی را مشخص می‌کند."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/fi.js b/backend/_pv_1_3_5/static/blockly/msg/js/fi.js deleted file mode 100755 index bd3bf389a..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/fi.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.fi'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Lisää kommentti"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Muuta arvoa:"; -Blockly.Msg.CLEAN_UP = "Siivoa lohkot"; -Blockly.Msg.COLLAPSE_ALL = "Sulje lohkot"; -Blockly.Msg.COLLAPSE_BLOCK = "Sulje lohko"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "väri 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "väri 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "suhde"; -Blockly.Msg.COLOUR_BLEND_TITLE = "sekoitus"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Sekoittaa kaksi väriä keskenään annetussa suhteessa (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://fi.wikipedia.org/wiki/V%C3%A4ri"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Valitse väri paletista."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "satunnainen väri"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Valitse väri sattumanvaraisesti."; -Blockly.Msg.COLOUR_RGB_BLUE = "sininen"; -Blockly.Msg.COLOUR_RGB_GREEN = "vihreä"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "punainen"; -Blockly.Msg.COLOUR_RGB_TITLE = "väri, jossa on"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Luo väri, jossa on tietty määrä punaista, vihreää ja sinistä. Kaikkien arvojen tulee olla välillä 0 - 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "poistu silmukasta"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "jatka silmukan seuraavaan toistoon"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Poistu sisemmästä silmukasta."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Ohita loput tästä silmukasta ja siirry seuraavaan toistoon."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Varoitus: Tätä lohkoa voi käyttää vain silmukan sisällä."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "kullekin kohteelle %1 listassa %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Aseta muuttujan %1 arvoksi kukin listan kohde vuorollaan ja suorita joukko lausekkeita."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "laske %1 Väli %2-%3 %4:n välein"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Aseta muuttujaan \"%1\" arvot alkuarvosta loppuarvoon annetun askeleen välein ja suorita joka askeleella annettu koodilohko."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Lisää ehto \"jos\" lohkoon."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Lisää lopullinen \"muuten\" lohko \"jos\" lohkoon."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Lisää, poista tai järjestele osioita tässä \"jos\" lohkossa."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "muuten"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "muuten jos"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "jos"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Jos arvo on tosi, suorita lauseke."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Jos arvo on tosi, suorita ensimmäinen lohko lausekkeita. Muuten suorita toinen lohko lausekkeita."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Jos ensimmäinen arvo on tosi, suorita ensimmäinen lohko lausekkeita. Muuten, jos toinen arvo on tosi, suorita toinen lohko lausekkeita."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Jos ensimmäinen arvo on tosi, suorita ensimmäinen lohko lausekkeita. Muuten, jos toinen arvo on tosi, suorita toinen lohko lausekkeita. Jos mikään arvoista ei ole tosi, suorita viimeinen lohko lausekkeita."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "tee"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "toista %1 kertaa"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Suorita joukko lausekkeita useampi kertaa."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "toista kunnes"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "toista niin kauan kuin"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Niin kauan kuin arvo on epätosi, suorita joukko lausekkeita."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Niin kauan kuin arvo on tosi, suorita joukko lausekkeita."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Poistetaanko kaikki %1 lohkoa?"; -Blockly.Msg.DELETE_BLOCK = "Poista lohko"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Poista %1 lohkoa"; -Blockly.Msg.DISABLE_BLOCK = "Passivoi lohko"; -Blockly.Msg.DUPLICATE_BLOCK = "Kopioi"; -Blockly.Msg.ENABLE_BLOCK = "Aktivoi lohko"; -Blockly.Msg.EXPAND_ALL = "Laajenna lohkot"; -Blockly.Msg.EXPAND_BLOCK = "Laajenna lohko"; -Blockly.Msg.EXTERNAL_INPUTS = "Ulkoiset syötteet"; -Blockly.Msg.HELP = "Apua"; -Blockly.Msg.INLINE_INPUTS = "Tuo syötteet"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "Luo tyhjä lista"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Palauta tyhjä lista, pituus 0"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "lista"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Listää, poista tai järjestele uudestaan osioita tässä lohkossa."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "luo lista"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Lisää kohde listaan."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Luo lista, jossa on mikä tahansa määrä kohteita."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "ensimmäinen"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "nro (lopusta laskien)"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "nro"; -Blockly.Msg.LISTS_GET_INDEX_GET = "hae"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "hae ja poista"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "viimeinen"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "satunnainen"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "poista"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Palauta ensimmäinen kohde listalta."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Palauta kohde annetusta kohdasta listaa."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Palauttaa listan viimeisen kohteen."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Palauttaa satunnaisen kohteen listalta."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Poistaa ja palauttaa ensimmäisen kohteen listalta."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Poistaa ja palauttaa kohteen listan annetusta kohdasta."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Poistaa ja palauttaa viimeisen kohteen listalta."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Poistaa ja palauttaa satunnaisen kohteen listalta."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Poistaa ensimmäisen kohteen listalta."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Poistaa kohteen listalta annetusta kohtaa."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Poistaa viimeisen kohteen listalta."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Poistaa satunnaisen kohteen listalta."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "päättyen kohtaan (lopusta laskien)"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "päättyen kohtaan"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "viimeinen"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "hae osalista alkaen alusta"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "hae osalista alkaen kohdasta (lopusta laskien)"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "hae osalista alkaen kohdasta"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Luo kopio määrätystä kohden listaa."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "Numero %1 tarkoittaa listan viimeistä kohdetta."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "Numero %1 tarkoittaa listan ensimmäistä kohdetta."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "etsi ensimmäinen esiintymä kohteelle"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "etsi viimeinen esiintymä kohteelle"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Palauttaa kohteen ensimmäisen/viimeisen esiintymän kohdan listassa. Palauttaa %1 jos kohdetta ei löydy."; -Blockly.Msg.LISTS_INLIST = "listassa"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 on tyhjä"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Palauttaa tosi, jos lista on tyhjä."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "%1:n pituus"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Palauttaa listan pituuden."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "luo lista, jossa kohde %1 toistuu %2 kertaa"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Luo listan, jossa annettu arvo toistuu määrätyn monta kertaa."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "kohteeksi"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "lisää kohtaan"; -Blockly.Msg.LISTS_SET_INDEX_SET = "aseta"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Lisää kohteen listan kärkeen."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Lisää kohteen annettuun kohtaan listassa."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Lisää kohteen listan loppuun."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Lisää kohteen satunnaiseen kohtaan listassa."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Asettaa listan ensimmäisen kohteen."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Asettaa kohteen annettuun kohtaan listassa."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Asettaa listan viimeisen kohteen."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Asettaa satunnaisen kohteen listassa."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "nouseva"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "laskeva"; -Blockly.Msg.LISTS_SORT_TITLE = "lajittele %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Lajittele kopio luettelosta."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "aakkosjärjestyksessä, ohita kapitaalit"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeerinen"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "aakkosjärjestys"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "tee lista tekstistä"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "tee listasta teksti"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Yhdistä luettelon tekstit yhdeksi tekstiksi, erotettuina välimerkillä."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Jaa teksti osiin erotinmerkin perusteella ja järjestä osat listaksi."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "erottimen kanssa"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "epätosi"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Palauttaa joko tosi tai epätosi."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "tosi"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://fi.wikipedia.org/wiki/Ep%C3%A4yht%C3%A4l%C3%B6"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Palauta tosi, jos syötteet ovat keskenään samat."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Palauttaa tosi, jos ensimmäinen syöte on suurempi, kuin toinen."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Palauttaa tosi, jos ensimmäinen syöte on suurempi tai yhtä suuri, kuin toinen."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Palauttaa tosi, jos ensimmäinen syöte on pienempi, kuin toinen."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Palauttaa tosi, jos ensimmäinen syöte on pienempi tai yhtä suuri, kuin toinen."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Palauttaa tosi, jos syötteet eivät ole keskenään samoja."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "ei %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Palauttaa tosi, jos syöte on epätosi. Palauttaa epätosi, jos syöte on tosi."; -Blockly.Msg.LOGIC_NULL = "ei mitään"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Palauttaa \"ei mitään\"-arvon."; -Blockly.Msg.LOGIC_OPERATION_AND = "ja"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "tai"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Palauttaa tosi, jos kummatkin syötteet ovat tosia."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Palauttaa tosi, jos ainakin yksi syötteistä on tosi."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "testi"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "jos epätosi"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "jos tosi"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Tarkistaa testin ehdon. Jos ehto on tosi, palauttaa \"jos tosi\" arvon, muuten palauttaa \"jos epätosi\" arvon."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "http://fi.wikipedia.org/wiki/Aritmetiikka"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Palauttaa kahden luvun summan."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Palauttaa jakolaskun osamäärän."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Palauttaa kahden luvun erotuksen."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Palauttaa kertolaskun tulon."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Palauttaa ensimmäisen luvun korotettuna toisen luvun potenssiin."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://fi.wikipedia.org/wiki/Yhteenlasku"; -Blockly.Msg.MATH_CHANGE_TITLE = "muuta %1 arvolla %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Lisää arvo muuttujaan '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Palauttaa jonkin seuraavista vakioista: π (3.141…), e (2.718…), φ (1.618…), neliöjuuri(2) (1.414…), neliöjuuri(½) (0.707…), or ∞ (ääretön)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "rajoita %1 vähintään %2 enintään %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Rajoittaa arvon annetulle suljetulle välille."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "on jaollinen luvulla"; -Blockly.Msg.MATH_IS_EVEN = "on parillinen"; -Blockly.Msg.MATH_IS_NEGATIVE = "on negatiivinen"; -Blockly.Msg.MATH_IS_ODD = "on pariton"; -Blockly.Msg.MATH_IS_POSITIVE = "on positiivinen"; -Blockly.Msg.MATH_IS_PRIME = "on alkuluku"; -Blockly.Msg.MATH_IS_TOOLTIP = "Tarkistaa onko numero parillinen, pariton, alkuluku, kokonaisluku, positiivinen, negatiivinen, tai jos se on jaollinen toisella luvulla. Palauttaa tosi tai epätosi."; -Blockly.Msg.MATH_IS_WHOLE = "on kokonaisluku"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "%1 ÷ %2 jakojäännös"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Palauttaa jakolaskun jakojäännöksen."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "⋅"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://fi.wikipedia.org/wiki/Luku"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Luku."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "keskiarvo luvuista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "suurin luvuista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "keskiluku luvuista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "pienin luvuista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "tyyppiarvo luvuista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "satunnainen valinta luvuista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "keskihajonta luvuista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "summa luvuista"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Palauttaa aritmeettisen keskiarvon annetuista luvuista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Palauttaa suurimman annetuista luvuista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Palauttaa annettujen lukujen keskiluvun."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Palauttaa pienimmän annetuista luvuista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Palauttaa luettelon yleisimmistä luvuista annetussa listassa."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Palauttaa satunnaisesti valitun luvun annetuista luvuista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Palauttaa annettujen lukujen keskihajonnan."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Palauttaa kaikkien annettujen lukujen summan."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://fi.wikipedia.org/wiki/Satunnaisluku"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "satunnainen murtoluku"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Palauttaa satunnaisen luvun oikealta puoliavoimesta välistä [0.0, 1.0)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://fi.wikipedia.org/wiki/Satunnaisluku"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "Palauttaa satunnaisen kokonaisluvun väliltä %1-%2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Palauttaa satunnaisen kokonaisluvun kahden annetun arvon suljetulta väliltä."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://fi.wikipedia.org/wiki/Py%C3%B6rist%C3%A4minen"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "pyöristä"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "pyöristä alaspäin"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "pyöristä ylöspäin"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Pyöristää luvun ylös- tai alaspäin."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://fi.wikipedia.org/wiki/Neli%C3%B6juuri"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "itseisarvo"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "neliöjuuri"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Palauttaa luvun itseisarvon."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Palauttaa e potenssiin luku."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Palauttaa luvun luonnollisen logaritmin."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Palauttaa luvun kymmenkantaisen logaritmin."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Palauttaa numeron vastaluvun."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Palauttaa 10 potenssiin luku."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Palauttaa luvun neliöjuuren."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "acos"; -Blockly.Msg.MATH_TRIG_ASIN = "asin"; -Blockly.Msg.MATH_TRIG_ATAN = "atan"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://fi.wikipedia.org/wiki/Trigonometrinen_funktio"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tan"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Palauttaa luvun arkuskosinin."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Palauttaa luvun arkussinin."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Palauttaa luvun arkustangentin."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Palauttaa asteluvun (ei radiaanin) kosinin."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Palauttaa asteluvun (ei radiaanin) sinin."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Palauttaa asteluvun (ei radiaanin) tangentin."; -Blockly.Msg.NEW_VARIABLE = "Uusi muuttuja..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Uuden muuttujan nimi:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "salli kommentit"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "parametrit:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://fi.wikipedia.org/wiki/Aliohjelma"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Suorittaa käyttäjän määrittelemä funktio '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://fi.wikipedia.org/wiki/Aliohjelma"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Suorittaa käyttäjän määrittelemän funktion '%1' ja käyttää sen tuotosta."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "parametrit:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Luo '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Kuvaile tämä funktio..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "tee jotain"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "tehdäksesi"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Luo funktio, jolla ei ole tuotosta."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "palauta"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Luo funktio, jolla ei ole tuotosta."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Varoitus: tällä funktiolla on sama parametri useamman kerran."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Korosta funktion määritelmä"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Jos arvo on tosi, palauta toinen arvo."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Varoitus: tätä lohkoa voi käyttää vain funktion määrityksessä."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "syötteen nimi:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Lisää sisääntulon funktioon."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "syötteet"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Lisää, poista tai järjestele uudelleen tämän toiminnon tulot."; -Blockly.Msg.REDO = "Tee uudelleen"; -Blockly.Msg.REMOVE_COMMENT = "Poista kommentti"; -Blockly.Msg.RENAME_VARIABLE = "Nimeä uudelleen muuttuja..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Nimeä uudelleen kaikki '%1' muuttujaa:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "lisää teksti"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "muuttujaan"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Lisää tekstiä muuttujaan '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "pienet kirjaimet"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "isot alkukirjaimet"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "isot kirjaimet"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Palauttaa kopion tekstistä eri kirjainkoossa."; -Blockly.Msg.TEXT_CHARAT_FIRST = "hae ensimmäinen kirjain"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "Hae kirjain nro (lopusta laskien)"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "Hae kirjain nro"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "tekstistä"; -Blockly.Msg.TEXT_CHARAT_LAST = "hae viimeinen kirjain"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "hae satunnainen kirjain"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Palauttaa annetussa kohdassa olevan kirjaimen."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Lisää kohteen tekstiin."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "liitä"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Lisää, poista tai uudelleen järjestä osioita tässä lohkossa."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "kirjaimeen nro (lopusta laskien)"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "kirjaimeen nro"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "viimeiseen kirjaimeen"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "merkkijonosta"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "hae osa alkaen ensimmäisestä kirjaimesta"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "hae osa alkaen kirjaimesta nro (lopusta laskien)"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "hae osa alkaen kirjaimesta nro"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Palauttaa määrätyn osan tekstistä."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "tekstistä"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "etsi ensimmäinen esiintymä merkkijonolle"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "etsi viimeinen esiintymä merkkijonolle"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Palauttaa ensin annetun tekstin ensimmäisen/viimeisen esiintymän osoitteen toisessa tekstissä. Palauttaa osoitteen %1 jos tekstiä ei löytynyt."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 on tyhjä"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Palauttaa tosi, jos annettu teksti on tyhjä."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "luo teksti"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Luo merkkijonon liittämällä yhteen minkä tahansa määrän kohteita."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "%1:n pituus"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Palauttaa annetussa tekstissä olevien merkkien määrän (välilyönnit mukaan lukien)."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "tulosta %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Tulostaa annetun tekstin, numeron tai muun arvon."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Kehottaa käyttäjää syöttämään numeron."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Kehottaa käyttäjää syöttämään tekstiä."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "käyttäen annettua viestiä, kehottaa syöttämään numeron"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "käyttäen annettua viestiä, kehottaa syöttämään tekstiä"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://fi.wikipedia.org/wiki/Merkkijono"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Kirjain, sana tai rivi tekstiä."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "poistaa välilyönnit kummaltakin puolelta"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "poistaa välilyönnit vasemmalta puolelta"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "poistaa välilyönnit oikealta puolelta"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Palauttaa kopion tekstistä siten, että välilyönnit on poistettu yhdestä tai molemmista päistä."; -Blockly.Msg.TODAY = "Tänään"; -Blockly.Msg.UNDO = "Kumoa"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "kohde"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Luo 'aseta %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Palauttaa muuttujan arvon."; -Blockly.Msg.VARIABLES_SET = "aseta %1 arvoksi %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Luo 'hae %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Asettaa muutujan arvoksi annetun syötteen."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/fr.js b/backend/_pv_1_3_5/static/blockly/msg/js/fr.js deleted file mode 100755 index b26eb85af..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/fr.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.fr'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Ajouter un commentaire"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Modifier la valeur :"; -Blockly.Msg.CLEAN_UP = "Nettoyer les blocs"; -Blockly.Msg.COLLAPSE_ALL = "Réduire les blocs"; -Blockly.Msg.COLLAPSE_BLOCK = "Réduire le bloc"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "couleur 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "couleur 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "taux"; -Blockly.Msg.COLOUR_BLEND_TITLE = "mélanger"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Mélange deux couleurs dans une proportion donnée (de 0.0 à 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://fr.wikipedia.org/wiki/Couleur"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Choisir une couleur dans la palette."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "couleur aléatoire"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Choisir une couleur au hasard."; -Blockly.Msg.COLOUR_RGB_BLUE = "bleu"; -Blockly.Msg.COLOUR_RGB_GREEN = "vert"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "rouge"; -Blockly.Msg.COLOUR_RGB_TITLE = "colorier avec"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Créer une couleur avec la quantité spécifiée de rouge, vert et bleu. Les valeurs doivent être comprises entre 0 et 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "quitter la boucle"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "passer à l’itération de boucle suivante"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Sortir de la boucle englobante."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Sauter le reste de cette boucle, et poursuivre avec l’itération suivante."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Attention : Ce bloc ne devrait être utilisé que dans une boucle."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "pour chaque élément %1 dans la liste %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Pour chaque élément d’une liste, assigner la valeur de l’élément à la variable '%1', puis exécuter des instructions."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "compter avec %1 de %2 à %3 par %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Faire prendre à la variable « %1 » les valeurs depuis le nombre de début jusqu’au nombre de fin, en s’incrémentant du pas spécifié, et exécuter les instructions spécifiées."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Ajouter une condition au bloc si."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Ajouter une condition finale fourre-tout au bloc si."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Ajouter, supprimer ou réordonner les sections pour reconfigurer ce bloc si."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "sinon"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "sinon si"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "si"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Si une valeur est vraie, alors exécuter certains ordres."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Si une valeur est vraie, alors exécuter le premier bloc d’ordres. Sinon, exécuter le second bloc d’ordres."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Si la première valeur est vraie, alors exécuter le premier bloc d’ordres. Sinon, si la seconde valeur est vraie, exécuter le second bloc d’ordres."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Si la première valeur est vraie, alors exécuter le premier bloc d’ordres. Sinon, si la seconde valeur est vraie, exécuter le second bloc d’ordres. Si aucune des valeurs n’est vraie, exécuter le dernier bloc d’ordres."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "http://fr.wikipedia.org/wiki/Boucle_for"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "faire"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "répéter %1 fois"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Exécuter des instructions plusieurs fois."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "répéter jusqu’à"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "répéter tant que"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Tant qu’une valeur est fausse, alors exécuter des instructions."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Tant qu’une valeur est vraie, alors exécuter des instructions."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Supprimer ces %1 blocs ?"; -Blockly.Msg.DELETE_BLOCK = "Supprimer le bloc"; -Blockly.Msg.DELETE_VARIABLE = "Supprimer la variable '%1'"; -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Supprimer %1 utilisations de la variable '%2' ?"; -Blockly.Msg.DELETE_X_BLOCKS = "Supprimer %1 blocs"; -Blockly.Msg.DISABLE_BLOCK = "Désactiver le bloc"; -Blockly.Msg.DUPLICATE_BLOCK = "Dupliquer"; -Blockly.Msg.ENABLE_BLOCK = "Activer le bloc"; -Blockly.Msg.EXPAND_ALL = "Développer les blocs"; -Blockly.Msg.EXPAND_BLOCK = "Développer le bloc"; -Blockly.Msg.EXTERNAL_INPUTS = "Entrées externes"; -Blockly.Msg.HELP = "Aide"; -Blockly.Msg.INLINE_INPUTS = "Entrées en ligne"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "créer une liste vide"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Renvoyer une liste, de longueur 0, ne contenant aucun enregistrement"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "liste"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Ajouter, supprimer, ou réordonner les sections pour reconfigurer ce bloc de liste."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "créer une liste avec"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Ajouter un élément à la liste."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Créer une liste avec un nombre quelconque d’éléments."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "premier"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# depuis la fin"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "obtenir"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "obtenir et supprimer"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "dernier"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "aléatoire"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "supprimer"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Renvoie le premier élément dans une liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Renvoie l’élément à la position indiquée dans une liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Renvoie le dernier élément dans une liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Renvoie un élément au hasard dans une liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Supprime et renvoie le premier élément dans une liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Supprime et renvoie l’élément à la position indiquée dans une liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Supprime et renvoie le dernier élément dans une liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Supprime et renvoie un élément au hasard dans une liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Supprime le premier élément dans une liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Supprime l’élément à la position indiquée dans une liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Supprime le dernier élément dans une liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Supprime un élément au hasard dans une liste."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "jusqu’à # depuis la fin"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "jusqu’à #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "jusqu’à la fin"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "obtenir la sous-liste depuis le début"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "obtenir la sous-liste depuis # depuis la fin"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "obtenir la sous-liste depuis #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Crée une copie de la partie spécifiée d’une liste."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 est le dernier élément."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 est le premier élément."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "trouver la première occurrence de l’élément"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "trouver la dernière occurrence de l’élément"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Renvoie l’index de la première/dernière occurrence de l’élément dans la liste. Renvoie %1 si l'élément n'est pas trouvé."; -Blockly.Msg.LISTS_INLIST = "dans la liste"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 est vide"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Renvoie vrai si la liste est vide."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "longueur de %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Renvoie la longueur d’une liste."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "créer une liste avec l’élément %1 répété %2 fois"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Crée une liste consistant en la valeur fournie répétée le nombre de fois indiqué."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "comme"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "insérer en"; -Blockly.Msg.LISTS_SET_INDEX_SET = "mettre"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Insère l’élément au début d’une liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Insère l’élément à la position indiquée dans une liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Ajouter l’élément à la fin d’une liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Insère l’élément au hasard dans une liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Fixe le premier élément dans une liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Met à jour l’élément à la position indiquée dans une liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Fixe le dernier élément dans une liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Fixe un élément au hasard dans une liste."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "croissant"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "décroissant"; -Blockly.Msg.LISTS_SORT_TITLE = "trier %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Trier une copie d’une liste."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabétique, en ignorant la casse"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numérique"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabétique"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "créer une liste depuis le texte"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "créer un texte depuis la liste"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Réunir une liste de textes en un seul, en les séparant par un séparateur."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Couper un texte en une liste de textes, en coupant à chaque séparateur."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "avec le séparateur"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "faux"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Renvoie soit vrai soit faux."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "vrai"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://fr.wikipedia.org/wiki/Inegalite_(mathematiques)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Renvoyer vrai si les deux entrées sont égales."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Renvoyer vrai si la première entrée est plus grande que la seconde."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Renvoyer vrai si la première entrée est plus grande ou égale à la seconde."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Renvoyer vrai si la première entrée est plus petite que la seconde."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Renvoyer vrai si la première entrée est plus petite ou égale à la seconde."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Renvoyer vrai si les deux entrées sont différentes."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "pas %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Renvoie vrai si l’entrée est fausse. Renvoie faux si l’entrée est vraie."; -Blockly.Msg.LOGIC_NULL = "nul"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Renvoie nul."; -Blockly.Msg.LOGIC_OPERATION_AND = "et"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "ou"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Renvoyer vrai si les deux entrées sont vraies."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Renvoyer vrai si au moins une des entrées est vraie."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "si faux"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "si vrai"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Vérifier la condition dans 'test'. Si elle est vraie, renvoie la valeur 'si vrai' ; sinon renvoie la valeur 'si faux'."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://fr.wikipedia.org/wiki/Arithmetique"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Renvoie la somme des deux nombres."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Renvoie le quotient des deux nombres."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Renvoie la différence des deux nombres."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Renvoie le produit des deux nombres."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Renvoie le premier nombre élevé à la puissance du second."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "incrémenter %1 de %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Ajouter un nombre à la variable '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Renvoie une des constantes courantes : π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), ou ∞ (infini)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "contraindre %1 entre %2 et %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Contraindre un nombre à être entre les limites spécifiées (incluses)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "est divisible par"; -Blockly.Msg.MATH_IS_EVEN = "est pair"; -Blockly.Msg.MATH_IS_NEGATIVE = "est négatif"; -Blockly.Msg.MATH_IS_ODD = "est impair"; -Blockly.Msg.MATH_IS_POSITIVE = "est positif"; -Blockly.Msg.MATH_IS_PRIME = "est premier"; -Blockly.Msg.MATH_IS_TOOLTIP = "Vérifier si un nombre est pair, impair, premier, entier, positif, négatif, ou s’il est divisible par un certain nombre. Renvoie vrai ou faux."; -Blockly.Msg.MATH_IS_WHOLE = "est entier"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "reste de %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Renvoyer le reste de la division euclidienne des deux nombres."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://fr.wikipedia.org/wiki/Nombre"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Un nombre."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "moyenne de la liste"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "maximum de la liste"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "médiane de la liste"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "minimum de la liste"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "majoritaires de la liste"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "élément aléatoire de la liste"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "écart-type de la liste"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "somme de la liste"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Renvoyer la moyenne (arithmétique) des valeurs numériques dans la liste."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Renvoyer le plus grand nombre dans la liste."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Renvoyer le nombre médian de la liste."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Renvoyer le plus petit nombre dans la liste."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Renvoyer une liste des élément(s) le(s) plus courant(s) dans la liste."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Renvoyer un élément dans la liste au hasard."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Renvoyer l’écart-type de la liste."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Renvoyer la somme de tous les nombres dans la liste."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "fraction aléatoire"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Renvoyer une fraction aléatoire entre 0.0 (inclus) et 1.0 (exclus)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "entier aléatoire entre %1 et %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Renvoyer un entier aléatoire entre les deux limites spécifiées, incluses."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "arrondir"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "arrondir par défaut"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "arrondir par excès"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Arrondir un nombre au-dessus ou au-dessous."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://fr.wikipedia.org/wiki/Racine_carree"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "valeur absolue"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "racine carrée"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Renvoie la valeur absolue d’un nombre."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Renvoie e à la puissance d’un nombre."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Renvoie le logarithme naturel d’un nombre."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Renvoie le logarithme base 10 d’un nombre."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Renvoie l’opposé d’un nombre"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Renvoie 10 à la puissance d’un nombre."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Renvoie la racine carrée d’un nombre."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Renvoie l’arccosinus d’un nombre."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Renvoie l’arcsinus d’un nombre."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Renvoie l’arctangente d’un nombre."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Renvoie le cosinus d’un angle en degrés (pas en radians)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Renvoie le sinus d’un angle en degrés (pas en radians)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Renvoie la tangente d’un angle en degrés (pas en radians)."; -Blockly.Msg.NEW_VARIABLE = "Créer une variable..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Nouveau nom de la variable :"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "autoriser les ordres"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "avec :"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "http://fr.wikipedia.org/wiki/Proc%C3%A9dure_%28informatique%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Exécuter la fonction '%1' définie par l’utilisateur."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Exécuter la fonction '%1' définie par l’utilisateur et utiliser son résultat."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "avec :"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Créer '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Décrire cette fonction…"; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "faire quelque chose"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "pour"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Crée une fonction sans sortie."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "retour"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Crée une fonction avec une sortie."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Attention : Cette fonction a des paramètres en double."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Surligner la définition de la fonction"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Si une valeur est vraie, alors renvoyer une seconde valeur."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Attention : Ce bloc pourrait n’être utilisé que dans une définition de fonction."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "nom de l’entrée :"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Ajouter une entrée à la fonction."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "entrées"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Ajouter, supprimer, ou réarranger les entrées de cette fonction."; -Blockly.Msg.REDO = "Refaire"; -Blockly.Msg.REMOVE_COMMENT = "Supprimer un commentaire"; -Blockly.Msg.RENAME_VARIABLE = "Renommer la variable…"; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Renommer toutes les variables « %1 » en :"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "ajouter le texte"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "à"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Ajouter du texte à la variable '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "en minuscules"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "en Majuscule Au Début De Chaque Mot"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "en MAJUSCULES"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Renvoyer une copie du texte dans une autre casse."; -Blockly.Msg.TEXT_CHARAT_FIRST = "obtenir la première lettre"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "obtenir la lettre # depuis la fin"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "obtenir la lettre #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "dans le texte"; -Blockly.Msg.TEXT_CHARAT_LAST = "obtenir la dernière lettre"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "obtenir une lettre au hasard"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Renvoie la lettre à la position indiquée."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Ajouter un élément au texte."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "joindre"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Ajouter, supprimer, ou réordonner des sections pour reconfigurer ce bloc de texte."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "jusqu’à la lettre # depuis la fin"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "jusqu’à la lettre #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "jusqu’à la dernière lettre"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "dans le texte"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "obtenir la sous-chaîne depuis la première lettre"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "obtenir la sous-chaîne depuis la lettre # depuis la fin"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "obtenir la sous-chaîne depuis la lettre #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Renvoie une partie indiquée du texte."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "dans le texte"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "trouver la première occurrence de la chaîne"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "trouver la dernière occurrence de la chaîne"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Renvoie l’index de la première/dernière occurrence de la première chaîne dans la seconde. Renvoie %1 si la chaîne n’est pas trouvée."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 est vide"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Renvoie vrai si le texte fourni est vide."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "créer un texte avec"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Créer un morceau de texte en agrégeant un nombre quelconque d’éléments."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "longueur de %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Renvoie le nombre de lettres (espaces compris) dans le texte fourni."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "afficher %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Afficher le texte, le nombre ou une autre valeur spécifié."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Demander un nombre à l’utilisateur."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Demander un texte à l’utilisateur."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "invite pour un nombre avec un message"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "invite pour un texte avec un message"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Une lettre, un mot ou une ligne de texte."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "supprimer les espaces des deux côtés"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "supprimer les espaces du côté gauche"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "supprimer les espaces du côté droit"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Renvoyer une copie du texte avec les espaces supprimés d’un bout ou des deux."; -Blockly.Msg.TODAY = "Aujourd'hui"; -Blockly.Msg.UNDO = "Annuler"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "élément"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Créer 'fixer %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Renvoie la valeur de cette variable."; -Blockly.Msg.VARIABLES_SET = "fixer %1 à %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Créer 'obtenir %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Fixe cette variable pour qu’elle soit égale à la valeur de l’entrée."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "Une variable appelée '%1' existe déjà."; -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/he.js b/backend/_pv_1_3_5/static/blockly/msg/js/he.js deleted file mode 100755 index 4bbd18b23..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/he.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.he'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "הוסף תגובה"; -Blockly.Msg.CHANGE_VALUE_TITLE = "שנה ערך:"; -Blockly.Msg.CLEAN_UP = "סידור בלוקים"; -Blockly.Msg.COLLAPSE_ALL = "צמצם קטעי קוד"; -Blockly.Msg.COLLAPSE_BLOCK = "צמצם קטע קוד"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "צבע 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "צבע 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "יחס"; -Blockly.Msg.COLOUR_BLEND_TITLE = "ערבב"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "מערבב שני צבעים יחד עם יחס נתון(0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "http://he.wikipedia.org/wiki/%D7%A6%D7%91%D7%A2"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "בחר צבע מן הצבעים."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "צבע אקראי"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "בחר צבא אקראי."; -Blockly.Msg.COLOUR_RGB_BLUE = "כחול"; -Blockly.Msg.COLOUR_RGB_GREEN = "ירוק"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "אדום"; -Blockly.Msg.COLOUR_RGB_TITLE = "צבע עם"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "צור צבע עם הסכום המצוין של אדום, ירוק וכחול. כל הערכים חייבים להיות בין 0 ל100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "צא מהלולאה"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "המשך עם האיטרציה הבאה של הלולאה"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "צא אל מחוץ ללולאה הכוללת."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "דלג על שאר הלולאה והמשך עם האיטרציה הבאה."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "אזהרה: בלוק זה עשוי לשמש רק בתוך לולאה."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "לכל פריט %1 ברשימה %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "לכל פריט ברשימה, להגדיר את המשתנה '%1' לפריט הזה, ולאחר מכן לעשות כמה פעולות."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "תספור עם %1 מ- %2 ל- %3 עד- %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Have the variable '%1' take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks."; // untranslated -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "תוסיף תנאי לבלוק If."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "לסיום, כל התנאים תקפים לגבי בלוק If."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "תוסיף, תמחק, או תסדר מחדש כדי להגדיר מחדש את הבלוק If."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "אחרת"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "אחרת אם"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "אם"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "אם ערך נכון, לבצע כמה פעולות."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "אם הערך הוא אמת, לבצע את הבלוק הראשון של הפעולות. אחרת, לבצע את הבלוק השני של הפעולות."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "אם הערך הראשון הוא אמת, לבצע את הבלוק הראשון של הפעולות. אחרת, אם הערך השני הוא אמת, לבצע את הבלוק השני של הפעולות."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "אם הערך הראשון הוא אמת, לבצע את הבלוק הראשון של הפעולות. אחרת, אם הערך השני הוא אמת, לבצע את הבלוק השני של הפעולות. אם אף אחד מהם אינו נכון, לבצע את הבלוק האחרון של הפעולות."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "http://he.wikipedia.org/wiki/בקרת_זרימה"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "תעשה"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "חזור על הפעולה %1 פעמים"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "לעשות כמה פעולות מספר פעמים."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "חזור עד ש..."; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "חזור כל עוד"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "בזמן שהערך שווה לשגוי, תעשה מספר חישובים."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "כל עוד הערך הוא אמת, לעשות כמה פעולות."; -Blockly.Msg.DELETE_ALL_BLOCKS = "האם למחוק את כל %1 קטעי הקוד?"; -Blockly.Msg.DELETE_BLOCK = "מחק קטע קוד"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "מחק %1 קטעי קוד"; -Blockly.Msg.DISABLE_BLOCK = "נטרל קטע קוד"; -Blockly.Msg.DUPLICATE_BLOCK = "שכפל"; -Blockly.Msg.ENABLE_BLOCK = "הפעל קטע קוד"; -Blockly.Msg.EXPAND_ALL = "הרחב קטעי קוד"; -Blockly.Msg.EXPAND_BLOCK = "הרחב קטע קוד"; -Blockly.Msg.EXTERNAL_INPUTS = "קלטים חיצוניים"; -Blockly.Msg.HELP = "עזרה"; -Blockly.Msg.INLINE_INPUTS = "קלטים פנימיים"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "צור רשימה ריקה"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "החזר רשימה,באורך 0, המכילה רשומות נתונים"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "רשימה"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "תוסיף, תמחק, או תסדר מחדש כדי להגדיר מחדש את הבלוק If."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "צור רשימה עם"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "הוסף פריט לרשימה."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "צור רשימה עם כל מספר של פריטים."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "ראשון"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# מהסוף"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "לקבל"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "קבל ומחק"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "אחרון"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "אקראי"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "הסרה"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "מחזיר את הפריט הראשון ברשימה."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "מחזיר פריט במיקום שצוין ברשימה."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "מחזיר את הפריט האחרון ברשימה."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "מחזיר פריט אקראי מהרשימה."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "מסיר ומחזיר את הפריט הראשון ברשימה."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "מסיר ומחזיר את הפריט במיקום שצוין ברשימה."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "מסיר ומחזיר את הפריט האחרון ברשימה."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "מחק והחזר פריט אקראי מהרשימה."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "הסר את הפריט הראשון ברשימה."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "מחזיר פריט במיקום שצוין ברשימה."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "הסר את הפריט הראשון ברשימה."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "הסר פריט אקראי ברשימה."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "ל # מהסוף"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "ל #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "לאחרון"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "לקבל חלק מהרשימה החל מהתחלה"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "לקבל חלק מהרשימה החל מ-# עד הסוף"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "לקבל חלק מהרשימה החל מ-#"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "יוצרת עותק של חלק מסוים מהרשימה."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 הוא הפריט האחרון."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 הוא הפריט הראשון."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "מחזירה את המיקום הראשון של פריט ברשימה"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "מחזירה את המיקום האחרון של פריט ברשימה"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "מחזירה את האינדקס של המופע הראשון/האחרון של הפריט ברשימה. מחזירה %1 אם הפריט אינו נמצא."; -Blockly.Msg.LISTS_INLIST = "ברשימה"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 הוא ריק"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "מחזיר אמת אם הרשימה ריקה."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "אורכו של %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "מחזירה את האורך של רשימה."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "ליצור רשימה עם הפריט %1 %2 פעמים"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "יוצר רשימה המורכבת מהערך נתון חוזר מספר פעמים שצוין."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "כמו"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "הכנס ב"; -Blockly.Msg.LISTS_SET_INDEX_SET = "הגדר"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "מכניס את הפריט בתחילת רשימה."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "מכניס את הפריט במיקום שצוין ברשימה."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "מוסיף את הפריט בסוף רשימה."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "הוסף פריט באופן אקראי ברשימה."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "מגדיר את הפריט הראשון ברשימה."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "מגדיר את הפריט במיקום שצוין ברשימה."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "מגדיר את הפריט האחרון ברשימה."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "מגדיר פריט אקראי ברשימה."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "סדר עולה"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "סדר יורד"; -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "סדר אלפביתי, לא תלוי רישיות"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "סדר אלפביתי"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "יצירת רשימה מטקסט"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "יצירת טקסט מרשימה"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "שגוי"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "תחזיר אם נכון או אם שגוי."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "נכון"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "תחזיר נכון אם שני הקלטים שווים אחד לשני."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "תחזיר נכון אם הקלט הראשון גדול יותר מהקלט השני."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "תחזיר נכון אם הקלט הראשון גדול יותר או שווה לכניסה השנייה."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "תחזיר אמת (true) אם הקלט הראשון הוא קטן יותר מאשר הקלט השני."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "תחזיר אמת אם הקלט הראשון הוא קטן יותר או שווה לקלט השני."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "תחזיר אמת אם שני הקלטים אינם שווים זה לזה."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "לא %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "החזר אמת אם הקלט הוא שקר. החזר שקר אם הקלט אמת."; -Blockly.Msg.LOGIC_NULL = "null"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "תחזיר ריק."; -Blockly.Msg.LOGIC_OPERATION_AND = "ו"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "או"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "תחזיר נכון אם שני הקלטים נכונים."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "תחזיר נכון אם מתקיים לפחות אחד מהקלטים נכונים."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "בדיקה"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "אם שגוי"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "אם נכון"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "בדוק את התנאי ב'מבחן'. אם התנאי נכון, תחזיר את הערך 'אם נכון'; אחרת תחזיר את הערך 'אם שגוי'."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://he.wikipedia.org/wiki/ארבע_פעולות_החשבון"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "תחזיר את סכום שני המספרים."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "החזרת המנה של שני המספרים."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "החזרת ההפרש בין שני מספרים."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "החזרת תוצאת הכפל בין שני מספרים."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "החזרת המספר הראשון בחזקת המספר השני."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; // untranslated -Blockly.Msg.MATH_CHANGE_TITLE = "שינוי %1 על־ידי %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "הוסף מספר למשתנה '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; // untranslated -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; // untranslated -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "constrain %1 low %2 high %3"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Constrain a number to be between the specified limits (inclusive)."; // untranslated -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "מתחלק ב"; -Blockly.Msg.MATH_IS_EVEN = "זוגי"; -Blockly.Msg.MATH_IS_NEGATIVE = "שלילי"; -Blockly.Msg.MATH_IS_ODD = "אי-זוגי"; -Blockly.Msg.MATH_IS_POSITIVE = "חיובי"; -Blockly.Msg.MATH_IS_PRIME = "ראשוני"; -Blockly.Msg.MATH_IS_TOOLTIP = "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false."; // untranslated -Blockly.Msg.MATH_IS_WHOLE = "שלם"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; // untranslated -Blockly.Msg.MATH_MODULO_TITLE = "שארית החילוק %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "החזרת השארית מחלוקת שני המספרים."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://he.wikipedia.org/wiki/מספר_ממשי"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "מספר."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "ממוצע של רשימה"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "מקסימום של רשימה"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "חציון של רשימה"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "מינימום של רשימה"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "שכיחי הרשימה"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "פריט אקראי מרשימה"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "standard deviation of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "סכום של רשימה"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Return the average (arithmetic mean) of the numeric values in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "תחזיר את המספר הגדול ביותר ברשימה."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "תחזיר את המספר החיצוני ביותר ברשימה."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "תחזיר את המספר הקטן ביותר ברשימה."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "החזרת רשימה של הפריטים הנפוצים ביותר ברשימה"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "תחזיר רכיב אקראי מרשימה."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Return the standard deviation of the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "החזרת הסכום של המספרים ברשימה."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "שבר אקראי"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive)."; // untranslated -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TITLE = "random integer from %1 to %2"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Return a random integer between the two specified limits, inclusive."; // untranslated -Blockly.Msg.MATH_ROUND_HELPURL = "https://he.wikipedia.org/wiki/עיגול_(אריתמטיקה)"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "עיגול"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "עיגול למטה"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "עיגול למעלה"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "עיגול מספר למעלה או למטה."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://he.wikipedia.org/wiki/שורש_ריבועי"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "ערך מוחלט"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "שורש ריבועי"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "החזרת הערך המוחלט של מספר."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "החזרת e בחזקת מספר."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "החזרת הלוגריתם הטבעי של מספר."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "החזרת הלוגריתם לפי בסיס עשר של מספר."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "החזרת הערך הנגדי של מספר."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "החזרת 10 בחזקת מספר."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "החזרת השורש הריבועי של מספר."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "acos"; -Blockly.Msg.MATH_TRIG_ASIN = "asin"; -Blockly.Msg.MATH_TRIG_ATAN = "atan"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://he.wikipedia.org/wiki/פונקציות_טריגונומטריות"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tan"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Return the arccosine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Return the arcsine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Return the arctangent of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "החזרת הקוסינוס של מעלה (לא רדיאן)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "החזרת הסינוס של מעלה (לא רדיאן)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "החזרת הטנגס של מעלה (לא רדיאן)."; -Blockly.Msg.NEW_VARIABLE = "משתנה חדש..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "שם המשתנה החדש:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "לאפשר פעולות"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "עם:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://he.wikipedia.org/wiki/שגרה_(תכנות)"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "להפעיל את הפונקציה המוגדרת על-ידי המשתמש '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://he.wikipedia.org/wiki/שגרה_(תכנות)"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "להפעיל את הפונקציה המוגדרת על-ידי המשתמש '%1' ולהשתמש הפלט שלה."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "עם:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "ליצור '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "לעשות משהו"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "לביצוע:"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "יצירת פונקציה ללא פלט."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "להחזיר"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "יצירת פונקציה עם פלט."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "אזהרה: לפונקציה זו יש פרמטרים כפולים."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "הדגש הגדרה של פונקציה"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "אם ערך נכון, אז להחזיר ערך שני."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "אזהרה: בלוק זה עשוי לשמש רק בתוך הגדרה של פונקציה."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "שם הקלט:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "הוסף קלט לפונקציה"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "מקורות קלט"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "הוסף, הסר או סדר מחדש קלטים לפונקציה זו"; -Blockly.Msg.REDO = "ביצוע חוזר"; -Blockly.Msg.REMOVE_COMMENT = "הסר תגובה"; -Blockly.Msg.RENAME_VARIABLE = "שנה את שם המשתנה..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "שנה את שם כל '%1' המשתנים ל:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "הוספת טקסט"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "אל"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Append some text to variable '%1'."; // untranslated -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "לאותיות קטנות (עבור טקסט באנגלית)"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "לאותיות גדולות בתחילת כל מילה (עבור טקסט באנגלית)"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "לאותיות גדולות (עבור טקסט באנגלית)"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; // untranslated -Blockly.Msg.TEXT_CHARAT_FIRST = "get first letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_FROM_END = "get letter # from end"; // untranslated -Blockly.Msg.TEXT_CHARAT_FROM_START = "get letter #"; // untranslated -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "in text"; // untranslated -Blockly.Msg.TEXT_CHARAT_LAST = "get last letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_RANDOM = "get random letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Returns the letter at the specified position."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Add an item to the text."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "צירוף"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Add, remove, or reorder sections to reconfigure this text block."; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "לאות # מהסוף"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "לאות #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "to last letter"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "in text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "get substring from first letter"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "get substring from letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "get substring from letter #"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returns a specified portion of the text."; // untranslated -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "in text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "find first occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "find last occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "מחזירה את האינדקס של המופע הראשון/האחרון בטקסט הראשון לתוך הטקסט השני. מחזירה %1 אם הטקסט אינו נמצא."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 is empty"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returns true if the provided text is empty."; // untranslated -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "יצירת טקסט עם"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Create a piece of text by joining together any number of items."; // untranslated -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "length of %1"; // untranslated -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Returns the number of letters (including spaces) in the provided text."; // untranslated -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "הדפס %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "להדפיס טקסט, מספר או ערך אחר שצוין"; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "בקש מהמשתמש מספר."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "בקשה למשתמש להזין טקסט כלשהו."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "בקשה למספר עם הודעה"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "בקשה להזנת טקסט עם הודעה"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; // untranslated -Blockly.Msg.TEXT_TEXT_TOOLTIP = "אות, מילה, או שורת טקסט."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "למחוק רווחים משני הקצוות"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "למחוק רווחים מימין"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "למחוק רווחים משמאל"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "להחזיר עותק של הטקסט לאחר מחיקת רווחים מאחד או משני הקצוות."; -Blockly.Msg.TODAY = "היום"; -Blockly.Msg.UNDO = "ביטול"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "פריט"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "ליצור 'הגדר %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "להחזיר את הערך של משתנה זה."; -Blockly.Msg.VARIABLES_SET = "הגדר %1 ל- %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "ליצור 'קרא %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "מגדיר משתנה זה להיות שווה לקלט."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/hi.js b/backend/_pv_1_3_5/static/blockly/msg/js/hi.js deleted file mode 100755 index 261a69cf2..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/hi.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.hi'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "टिप्पणी छोड़ें"; -Blockly.Msg.CHANGE_VALUE_TITLE = "मान परिवर्तित करें:"; -Blockly.Msg.CLEAN_UP = "Clean up Blocks"; // untranslated -Blockly.Msg.COLLAPSE_ALL = "ब्लॉक संक्षिप्त करें"; -Blockly.Msg.COLLAPSE_BLOCK = "ब्लॉक को संक्षिप्त करें"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "रंग 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "रंग 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "अनुपात"; -Blockly.Msg.COLOUR_BLEND_TITLE = "मिश्रण करें"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "दिए गए अनुपात (0.0 - 1.0) के साथ दो रंगों का मिश्रण करता है।"; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "पैलेट से एक रंग चुनें।"; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "रैन्डम रंग"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "रैन्डम्ली एक रंग चयन करें।"; -Blockly.Msg.COLOUR_RGB_BLUE = "नीला"; -Blockly.Msg.COLOUR_RGB_GREEN = "हरा"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "लाल"; -Blockly.Msg.COLOUR_RGB_TITLE = "इसके साथ रंग करें"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "लाल, हरा और नीले की निर्दिष्ट मात्रा के साथ एक रंग बनायें। सभी मान ० से १०० के बीच होने चाहिए।"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "लूप से बाहर निकलें"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "लूप का अगला आईटरेशन जारी रखें"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "भीतरी लूप से बाहर निकलें।"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "बाकी बचे लूप को छोड़ें, और अगला आईटरेशन जारी रखें।"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "सावधान: ये ब्लॉक केवल लूप के अंदर इस्तेमाल किया जा सकता है।"; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "प्रत्येक आइटम के लिए %1 सूची में %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "सूची के प्रत्येक आयटम के लिए, आयटम में चर का मान '%1' रखें और बाद में कुछ कथन लिखें।"; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "काउंट करें"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Have the variable '%1' take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks."; // untranslated -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "यदि ब्लॉक मे एक शर्त जोड़ें।"; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Add a final, catch-all condition to the if block."; // untranslated -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Add, remove, or reorder sections to reconfigure this if block."; // untranslated -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "एल्स"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "एल्स इफ"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "इफ"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "यदी मान ट्रू है, तो कुछ स्टेट्मेंट्स चलाएँ।"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "यदि एक मान सत्य है तो कथनों का प्रथम खण्ड बनायें। अन्यथा कथनों का दूसरा भाग निर्मित करें।"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements."; // untranslated -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "डू"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "%1 बार दोहराएँ"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "कुछ स्टेट्मन्ट कई बार चलाएँ।"; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "दोहराएँ जब तक"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "दोहराएँ जब कि"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "जब तक मान फॉल्स है, तब तक कुछ स्टेट्मेंट्स चलाएँ।"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "जब तक मान ट्रू है, तब तक कुछ स्टेट्मेंट्स चलाएँ।"; -Blockly.Msg.DELETE_ALL_BLOCKS = "Delete all %1 blocks?"; // untranslated -Blockly.Msg.DELETE_BLOCK = "ब्लॉक हटाएँ"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "%1 ब्लॉक हटाएँ"; -Blockly.Msg.DISABLE_BLOCK = "ब्लॉक को अक्षम करें"; -Blockly.Msg.DUPLICATE_BLOCK = "कॉपी करें"; -Blockly.Msg.ENABLE_BLOCK = "ब्लॉक को सक्षम करें"; -Blockly.Msg.EXPAND_ALL = "ब्लॉक विस्तार करें"; -Blockly.Msg.EXPAND_BLOCK = "ब्लॉक का विस्तार करें"; -Blockly.Msg.EXTERNAL_INPUTS = "बाहरी इनपुट"; -Blockly.Msg.HELP = "सहायता"; -Blockly.Msg.INLINE_INPUTS = "इनलाइन इनपुट"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "खाली सूची बनाएँ"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Returns a list, of length 0, containing no data records"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "सूची"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Add, remove, or reorder sections to reconfigure this list block."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "इसके सूची बनाएँ"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "सूची मे एक आइटम जोड़ें।"; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "कितने भी आइटम वाली एक सूची बनाएँ।"; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "%1 पहला आइटम है।"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "अंत से #"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "प्राप्त"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "प्राप्त करे और हटाए"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "%1 आखरी आइटम है।"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "रैन्डम"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "निकालें"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "सूची का पहला आइटम रिटर्न करता है।"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "सूची का आखरी आइटम रिटर्न करता है।"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "सूची से रैन्डम आइटम रिटर्न करता है।"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "सूची का पहला आइटम निकालता है और रिटर्न करता है।"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Removes and returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "सूची का आखरी आइटम निकालता है और रिटर्न करता है।"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "सूची से रैन्डम आइटम निकालता है और रिटर्न करता है।"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "सूची का पहला आइटम निकालता है।"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Removes the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "सूची का आखरी आइटम निकालता है।"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "सूची से रैन्डम आइटम निकालता है।"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "to # from end"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "to #"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "to last"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "get sub-list from first"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "get sub-list from # from end"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "get sub-list from #"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "सूची के बताए गये भाग की कॉपी बनता है।"; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 is the last item."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 is the first item."; // untranslated -Blockly.Msg.LISTS_INDEX_OF_FIRST = "आइटम पहली बार जहाँ आया है उसे ढूढ़े"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "आइटम आखरी बार जहाँ आया है उसे ढूढ़े"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Returns the index of the first/last occurrence of the item in the list. Returns %1 if item is not found."; // untranslated -Blockly.Msg.LISTS_INLIST = "सूची में"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 खाली है"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "यदि सूची खाली है तो ट्रू रिटर्न करता है।"; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "%1 की लंबाई"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "सूची की लंबाई रिटर्न करता है।"; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "create list with item %1 repeated %2 times"; // untranslated -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Creates a list consisting of the given value repeated the specified number of times."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "as"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INSERT = "insert at"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_SET = "सैट करें"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "आइटम को सूची के शुरू में इनसर्ट करता है।"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "सूची मे बताए गये स्थान में आइटम इनसर्ट करता है।"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "आइटम को सूची के अंत में जोड़ता है।"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "आइटम को सूची में रैन्डम्ली इनसर्ट करता है।"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "सूची में पहला आइटम सैट करता है।"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "सूची मे बताए गये स्थान में आइटम सैट करता है।"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "सूची में आखरी आइटम सैट करता है।"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "सूची में रैन्डम आइटम सैट करता है।"; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "अंकीय"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "make list from text"; // untranslated -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "make text from list"; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "फॉल्स"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "ट्रू या फॉल्स रिटर्न करता है।"; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "ट्रू"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "ट्रू रिटर्न करें यदि दोनो इनपुट इक दूसरे के बराबर हों।"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "ट्रू रिटर्न करें यदि पहला इनपुट दूसरे इनपुट से बड़ा हो।"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "ट्रू रिटर्न करें यदि पहला इनपुट दूसरे इनपुट से बड़ा हो या बराबर हो।"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "ट्रू रिटर्न करें यदि पहला इनपुट दूसरे इनपुट से छोटा हो।"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "ट्रू रिटर्न करें यदि पहला इनपुट दूसरे इनपुट से छोटा हो या बराबर हो।"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "ट्रू रिटर्न करें यदि दोनो इनपुट इक दूसरे के बराबर नहीं हों।"; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "NOT (पूरक) %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "ट्रू रिटर्न करता है यदि इनपुट फॉल्स है। फॉल्स रिटर्न करता है यदि इनपुट ट्रू है।"; -Blockly.Msg.LOGIC_NULL = "NULL (अमान्य)"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "null (अमान्य) रिटर्न करता है।"; -Blockly.Msg.LOGIC_OPERATION_AND = "AND (तथा)"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "OR (अथवा)"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "ट्रू रिटर्न करें यदि दोनो इनपुट ट्रू हों।"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "ट्रू रिटर्न करें यदि दोनो मे से इक इनपुट ट्रू हो।"; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "टेस्ट"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "यदि फॉल्स है"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "यदि ट्रू है"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value."; // untranslated -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Arithmetic"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "दो संख्याओं का योग रिटर्न करें।"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "दो संख्याओं का भागफल रिटर्न करें।"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "दो संख्याओं का अंतर रिटर्न करें।"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "दो संख्याओं का गुणन रिटर्न करें।"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Return the first number raised to the power of the second number."; // untranslated -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "change %1 by %2"; // untranslated -Blockly.Msg.MATH_CHANGE_TOOLTIP = "संख्या को चर '%1' से जोड़ें।"; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; // untranslated -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "constrain %1 low %2 high %3"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Constrain a number to be between the specified limits (inclusive)."; // untranslated -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "इसके द्वारा विभाज्य है"; -Blockly.Msg.MATH_IS_EVEN = "सम है"; -Blockly.Msg.MATH_IS_NEGATIVE = "ऋणात्मक है"; -Blockly.Msg.MATH_IS_ODD = "विषम है"; -Blockly.Msg.MATH_IS_POSITIVE = "धनात्मक है"; -Blockly.Msg.MATH_IS_PRIME = "अभाज्य है"; -Blockly.Msg.MATH_IS_TOOLTIP = "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false."; // untranslated -Blockly.Msg.MATH_IS_WHOLE = "पूर्णांक है"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "%1 ÷ %2 का शेषफल"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "दो संख्याओं के भाग का शेषफल रिटर्न करें।"; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "एक संख्या।"; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "सूची का औसत मान"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "सूची मे अधिकतम"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "सूची की माध्यिका"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "सूची मे न्यूनतम"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "सूची का मोड"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "सूची का रैन्डम आइटम"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "सूची का मानक विचलन"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "सूची का योग"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Return the average (arithmetic mean) of the numeric values in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "सूची मे सबसे बड़ी संख्या रिटर्न करें।"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "सूची की माध्यिका संख्या रिटर्न करें।"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "सूची मे सबसे छोटी संख्या रिटर्न करें।"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "सूची मे सबसे आम आइटम(s) की सूची रिटर्न करें।"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "सूची से एक रैन्डम आइटम रिटर्न करें।"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "सूची का मानक विचलन रिटर्न करें।"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "सूची की सभी संख्याओं का योग रिटर्न करें।"; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "रैन्डम अंश"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive)."; // untranslated -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "%1 से %2 तक रैन्डम पूर्णांक"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Return a random integer between the two specified limits, inclusive."; // untranslated -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "पूर्णांक बनाएँ"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "घटा के पूर्णांक बनाएँ"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "बड़ा के पूर्णांक बनाएँ"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "संख्या को बड़ा या घटा के पूर्णांक बनाएँ।"; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "परम"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "वर्गमूल"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "संख्या का परम मान रिटर्न करें।"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Return e to the power of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "संख्या का प्राकृतिक लघुगणक रिटर्न करें।"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "संख्या का मूल 10 लघुगणक रिटर्न करें।"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "संख्या का निषेध मान रिटर्न करें।"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Return 10 to the power of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "संख्या का वर्गमूल रिटर्न करें।"; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "संख्या का आर्ककोसाइन रिटर्न करें।"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "संख्या का आर्कसाइन रिटर्न करें।"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "संख्या का आर्कटैन्जन्ट रिटर्न करें।"; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "डिग्री का कोसाइन रिटर्न करें (रेडियन नही)"; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "डिग्री का साइन रिटर्न करें (रेडियन नही)"; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "डिग्री का टैन्जन्ट रिटर्न करें (रेडियन नही)"; -Blockly.Msg.NEW_VARIABLE = "नया चर..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "नए चर का नाम:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "allow statements"; // untranslated -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = ": के साथ"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "यूज़र द्वारा वर्णन किया गया फ़ंक्शन '%1' चलाएँ।"; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "यूज़र द्वारा वर्णन किया गया फ़ंक्शन '%1' चलाएँ और उसका आउटपुट इस्तेमाल करें।"; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = ": के साथ"; -Blockly.Msg.PROCEDURES_CREATE_DO = "'%1' बनाएँ"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "कुछ करें"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "to"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "बिना आउटपुट वाला एक फ़ंक्शन बनाता है।"; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "रिटर्न"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "आउटपुट वाला एक फ़ंक्शन बनाता है।"; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "सावधान: इस फ़ंक्शन मे डुप्लिकेट पैरामीटर हैं।"; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "फ़ंक्शन परिभाषा को हाइलाइट करें"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "यदि एक मान ट्रू है तो, दूसरा मान रिटर्न करें।"; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "सावधान: ये ब्लॉक फ़ंक्शन परिभाषा के अंदर ही इस्तेमाल किया जा सकता।"; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "इनपुट का नाम:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "फंगक्शन को इनपुट प्रदान करें।"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "इनपुट"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Add, remove, or reorder inputs to this function."; // untranslated -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "टिप्पणी हटायें"; -Blockly.Msg.RENAME_VARIABLE = "चर का नाम बदलें..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "सभी '%1' चरों के नाम बदलें:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "से जोड़ें ये टेक्स्ट"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "इस"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "कुछ टेक्स्ट इस चर '%1' से जोड़ें।"; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "छोटे अक्षर मे"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "टाइटल केस मे"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "बड़े अक्षर मे"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "टेक्स्ट की कॉपी भिन्न केस (अक्षर से संबंधित) मे रिटर्न करें।"; -Blockly.Msg.TEXT_CHARAT_FIRST = "पहला अक्षर पाएँ"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "आखिर से अक्षर # पाएँ"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "अक्षर # पाएँ"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "इस टेक्स्ट मे"; -Blockly.Msg.TEXT_CHARAT_LAST = "आखरी अक्षर पाएँ"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "रैन्डम अक्षर पाएँ"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "बताई गयी जगह से अक्षर रिटर्न करता है"; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "सूची मे एक आइटम जोड़ें।"; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "जोड़"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Add, remove, or reorder sections to reconfigure this text block."; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "आखिर से यहाँ तक अक्षर #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "यहाँ तक अक्षर #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "यहाँ तक आखरी अक्षर"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "इस टेक्स्ट मे"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "पहले अक्षर से सबस्ट्रिंग पाएँ"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "आखरी अक्षर # से सबस्ट्रिंग पाएँ"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "अक्षर # से सबस्ट्रिंग पाएँ"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "टेक्स्ट का बताया गया अंश रिटर्न करता है"; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "इस टेक्स्ट मे"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "टेक्स्ट पहली बार जहाँ आया है उसे ढूढ़े"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "टेक्स्ट आखरी बार जहाँ आया है उसे ढूढ़े"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found."; // untranslated -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 खाली है"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "ट्रू रिटर्न करता है यदि दिया गया टेक्स्ट खाली है।"; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "इसके साथ टेक्स्ट बनाएँ"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Create a piece of text by joining together any number of items."; // untranslated -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "%1 की लंबाई"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "दिए गये टेक्स्ट मे अक्षरों की संख्या रिटर्न करता है (खाली स्थान मिला के)।"; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "प्रिंट करें %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "दिया गया टेक्स्ट प्रिंट करें, संख्या या अन्य मान।"; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "यूज़र से संख्या के लिए प्रॉम्प्ट करें।"; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "यूज़र से कुछ टेक्स्ट के लिए प्रॉम्प्ट करें।"; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "सूचना के साथ संख्या के लिए प्रॉम्प्ट करें"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "सूचना के साथ टेक्स्ट के लिए प्रॉम्प्ट करें"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "एक अक्षर, शब्द, या टेक्स्ट की पंक्ति।"; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "रिक्त स्थान को इस टेक्स्ट के दोनों तरफ से निकालें"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "रिक्त स्थान को इस टेक्स्ट के बायें तरफ से निकालें"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "रिक्त स्थान को इस टेक्स्ट के दाईं तरफ से निकालें"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Return a copy of the text with spaces removed from one or both ends."; // untranslated -Blockly.Msg.TODAY = "आज"; -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "आइटम"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "सेट '%1' बनाएँ"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "इस चर का मान रिटर्न करता है।"; -Blockly.Msg.VARIABLES_SET = "सेट करें %1 को %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Create 'get %1'"; // untranslated -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "इस चर को इनपुट के बराबर सेट करता है।"; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/hrx.js b/backend/_pv_1_3_5/static/blockly/msg/js/hrx.js deleted file mode 100755 index d2518399a..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/hrx.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.hrx'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Kommentar hinzufüche"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Neie Variable..."; -Blockly.Msg.CLEAN_UP = "Clean up Blocks"; // untranslated -Blockly.Msg.COLLAPSE_ALL = "Blocke zusammerfalte"; -Blockly.Msg.COLLAPSE_BLOCK = "Block zusammerfalte"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "Farreb 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "mit Farreb 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "im Verhältniss"; -Blockly.Msg.COLOUR_BLEND_TITLE = "misch"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Vermischt 2 Farwe mit konfigurierbare Farrebverhältniss (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://hrx.wikipedia.org/wiki/Farreb"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Wähl en Farreb von der Palett."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "zufälliche Farwe"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Wähl en Farreb noh dem Zufallsprinzip."; -Blockly.Msg.COLOUR_RGB_BLUE = "blau"; -Blockly.Msg.COLOUR_RGB_GREEN = "grün"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "rot"; -Blockly.Msg.COLOUR_RGB_TITLE = "Färreb mit"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Kreiere ene Farreb mit sellrbst definierte rot, grün und blau Wearte. All Wearte müsse zwischich 0 und 100 liehe."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "ausbreche aus der Schleif"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "mit der nächste Iteration fortfoohre aus der Schleifa"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Die umgebne Schleif beenne."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Die Oonweisung abbreche und mit der nächste Schleifiteration fortfoohre."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Warnung: Die block sollt nuar in en Schleif verwennet sin."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "Für Weart %1 aus der List %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Füahr en Oonweisung für jede Weart in der List aus und setzt dabei die Variable \"%1\" uff den aktuelle List Weart."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "Zähl %1 von %2 bis %3 mit %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Zähl die Variable \"%1\" von enem Startweart bis zu enem Zielweart und füahrefür jede Weart en Oonweisung aus."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "En weitre Bedingung hinzufüche."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "En orrer Bedingung hinzufüche, füahrt en Oonweisung aus falls ken Bedingung zutrifft."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Hinzufüche, entferne orrer sortiere von Sektione"; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "orrer"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "orrer wenn"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "wenn"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Wenn en Bedingung woahr (true) ist, dann füahr en Oonweisung aus."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Wenn en Bedingung woahr (true) ist, dann füahr die earscht Oonweisung aus. Ansonscht füahr die zwooite Oonweisung aus."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Wenn der erschte Bedingung woahr (true) ist, dann füahr die erschte Oonweisung aus. Orrer wenn die zwooite Bedingung woahr (true) ist, dann füahr die zwooite Oonweisung aus."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Wenn der erscht Bedingung woahr (true) ist, dann füahr die erschte Oonweisung aus. Orrer wenn die zwooite Bedingung woahr (true) ist, dann füahr die zwooite Oonweisung aus. Falls ken der beide Bedingungen woahr (true) ist, dann füahr die dritte Oonweisung aus."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://hrx.wikipedia.org/wiki/For-Schleif"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "mach"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "wiederhol %1 mol"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "En Oonweisung meahrfach ausführe."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "Repetiere bis"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "Repetier solang"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Füahr die Oonweisung solang aus wie die Bedingung falsch (false) ist."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Füahr die Oonweisung solang aus wie die Bedingung woahr (true) ist."; -Blockly.Msg.DELETE_ALL_BLOCKS = "All %1 Bausten lösche?"; -Blockly.Msg.DELETE_BLOCK = "Block lösche"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Block %1 lösche"; -Blockly.Msg.DISABLE_BLOCK = "Block deaktivieren"; -Blockly.Msg.DUPLICATE_BLOCK = "Kopieren"; -Blockly.Msg.ENABLE_BLOCK = "Block aktivieren"; -Blockly.Msg.EXPAND_ALL = "Blocke expandiere"; -Blockly.Msg.EXPAND_BLOCK = "Block entfalte"; -Blockly.Msg.EXTERNAL_INPUTS = "External Inputsexterne Ingänge"; -Blockly.Msg.HELP = "Hellef"; -Blockly.Msg.INLINE_INPUTS = "interne Ingänge"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "Generier/erzeich en leear List"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Generier/erzeich en leear List ohne Inhalt."; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "List"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Hinzufüche, entferne und sortiere von Elemente."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "Erzeich List mit"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "En Element zur List hinzufüche."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Generier/erzeich en List mit konfigurierte Elemente."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "earste"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "#te von hinne"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "Nehm"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "Nehm und entfern"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "letzte"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "zufälliches"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "Entfern"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Extrahiert das earste Element von der List."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Extrahiert das Element zu en definierte Stell von der List."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Extrahiert das letzte Element von der List."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Extrahiert en zufälliches Element von der List."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Extrahiert und entfernt das earste Element von der List."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Extrahiert und entfernt das Element zu en definierte Stell von der List."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Extrahiert und entfernt das letzte Element von der List."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Extrahiert und entfernt en zufälliches Element von der List."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Entfernt das earste Element von der List."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Entfernt das Element zu en definierte Stell von der List."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Entfernt das letzte Element von der List."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Entfernt en zufälliches Element von der List."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "zu # vom End"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "zu #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "zum Letzte"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "hol Unnerliste vom Earste"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "hol Unnerliste von # vom End"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "hol Unnerlist von #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Generiert en Kopie von en definierte Tel von en List."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 ist das letzte Element."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 ist das earschte Element."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "Such earstes Voarkommniss"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "Such letztes Voarkommniss"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Sucht die Position (index) von en Element in der List Gebt %1 zurück wenn nixs gefunn woard."; -Blockly.Msg.LISTS_INLIST = "in der List"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 ist leear?"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Ist woahr (true), wenn die List leear ist."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "länge %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Die Oonzoohl von Elemente in der List."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "Erzich List mit Element %1 wiederhol das %2 mol"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Erzeicht en List mit en variable Oonzoohl von Elemente"; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "uff"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "tue ren setz an"; -Blockly.Msg.LISTS_SET_INDEX_SET = "setz"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Tut das Element an en Oonfang von en List ren setze."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Tut das Element ren setze an en definierte Stell an en List."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Oonhängt das Element zu en List sei End."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Tut das Element zufällich an en List ren setze."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Sets the first item in a list.Setzt das earschte Element an en list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Setzt das Element zu en definierte Stell in en List."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Setzt das letzte Element an en List."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Setzt en zufälliches Element an en List."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "make list from text"; // untranslated -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "make text from list"; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "falsch"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Ist entweder woahr (true) orrer falsch (false)"; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "woahr"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://hrx.wikipedia.org/wiki/Vergleich_%28Zahlen%29"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Ist woahr (true) wenn beide Wearte identisch sind."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Ist woahr (true) wenn der erschte Weart grösser als der zwooite Weart ist."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Ist woahr (true) wenn der erschte Weart grösser als orrer gleich gross wie zwooite Weart ist."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Ist woahr (true) wenn der earschte Weart klener als der zwooite Weart ist."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Ist woahr (true) wenn der earscht Weart klener als orrer gleich gross wie zwooite Weart ist."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Ist woahr (true) wenn beide Wearte unnerschiedlich sind."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "net %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Ist woahr (true) wenn der Ingäweweart falsch (false) ist. Ist falsch (false) wenn der Ingäweweart woahr (true) ist."; -Blockly.Msg.LOGIC_NULL = "null"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Is NULL."; -Blockly.Msg.LOGIC_OPERATION_AND = "und"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "orrer"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Ist woahr (true) wenn beide Wearte woahr (true) sind."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Ist woahr (true) wenn en von der beide Wearte woahr (true) ist."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "wenn falsch"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "wenn woahr"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Üwerprüft en Bedingung \"test\". Wenn die Bedingung woahr ist weerd der \"wenn woahr\" Weart zurückgeb, annerfalls der \"wenn falsch\" Weart"; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://hrx.wikipedia.org/wiki/Grundrechenoort"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Ist die Summe zwooier Wearte."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Ist der Quotient zwooier Wearte."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Ist die Differenz zwooier Wearte."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Ist das Produkt zwooier Wearte."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Ist der earschte Weart potenziert mit dem zoiten Weart."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://hrx.wikipedia.org/wiki/Inkrement_und_Dekrement"; -Blockly.Msg.MATH_CHANGE_TITLE = "mach höcher / erhöhe %1 um %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Addiert en Weart zur Variable \"%1\" hinzu."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://hrx.wikipedia.org/wiki/Mathematische_Konstante"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Mathematische Konstante wie: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…) oder ∞ (unendlich)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "begrenze %1 von %2 bis %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Begrenzt den Weartebereich mittels von / bis Wearte. (inklusiv)"; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "ist telbar/kann getelt sin doorrich"; -Blockly.Msg.MATH_IS_EVEN = "ist grood"; -Blockly.Msg.MATH_IS_NEGATIVE = "ist negativ"; -Blockly.Msg.MATH_IS_ODD = "ist ungrood"; -Blockly.Msg.MATH_IS_POSITIVE = "ist positiv"; -Blockly.Msg.MATH_IS_PRIME = "ist en Primenzoohl"; -Blockly.Msg.MATH_IS_TOOLTIP = "Üwerprüft ob en Zoohl grood, ungrood, en Primenzoohl, ganzzoohlich, positiv, negativ orrer doorrich en zwooite Zoohl telbar ist. Gebt woahr (true) orrer falsch (false) zurück."; -Blockly.Msg.MATH_IS_WHOLE = "ganze Zoohl"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://hrx.wikipedia.org/wiki/Modulo"; -Blockly.Msg.MATH_MODULO_TITLE = "Rest von %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Der Rest noh en Division."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://hrx.wikipedia.org/wiki/Zoohl"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "En Zoohl."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "Mittelweart en List"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "Maximalweart en List"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "Median von en List"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "Minimalweart von en List"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "Restweart von en List"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "Zufallsweart von en List"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "Standart/Padrong Abweichung von en List"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "Summe von en List"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Ist der Doorrichschnittsweart von aller Wearte in en List."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Ist der grösste Weart in en List."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Ist der Zentralweart von aller Wearte in en List."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Ist der klenste Weart in en List."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Findt den am häifichste voarkommend Weart in en List. Falls ken Weart öftersch voarkomme als all annre, weard die originale List zurückgeche"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Geb en Zufallsweart aus der List zurück."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Ist die standartiesierte/padronisierte Standartabweichung/Padrongabweichung von aller Wearte in der List"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Ist die Summ aller Wearte in en List."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://hex.wikipedia.org/wiki/Zufallszoohle"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "Zufallszoohl (0.0 -1.0)"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Generier/erzeich en Zufallszoohl zwischich 0.0 (inklusiv) und 1.0 (exklusiv)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://hrx.wikipedia.org/wiki/Zufallszahlen"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "ganzoohlicher Zufallswearte zwischich %1 bis %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Generier/erzeich en ganzähliche Zufallsweart zwischich zwooi Wearte (inklusiv)."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://hrx.wikipedia.org/wiki/Runden"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "runde"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "ab runde"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "uff runde"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "En Zoohl uff orrer ab runde."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://hrx.wikipedia.org/wiki/Quadratwoorzel"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "Absolutweart"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "Quadratwoorzel"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Ist der Absolutweart von en Weart."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Ist Weart von der Exponentialfunktion von en Weart."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Ist der natüarliche Logarithmus von en Weart."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Ist der dekoodische Logarithmus von en Weart."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Negiert en Weart."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Rechnet 10 hoch Ingäbweart."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Ist die Qudratwoorzel von en Weart."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://hrx.wikipedia.org/wiki/Trigonometrie"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Ist der Arcuscosinus von en Ingabweart."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Ist der Arcussinus von en Ingäbweart."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Ist der Arcustangens von en Ingäbweart."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Ist der Cosinus von en Winkel."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Ist der Sinus von en Winkel."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Ist der Tangens von en Winkel."; -Blockly.Msg.NEW_VARIABLE = "Neie Variable..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Die neie Variable sei Noome:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "allow statements"; // untranslated -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "mit:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://hrx.wikipedia.org/wiki/Prozedur_%28Programmierung%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Ruf en Funktionsblock ohne Rückgäweart uff."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://hrx.wikipedia.org/wiki/Prozedur_%28Programmierung%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Ruf en Funktionsblock mit Rückgäbweart uff."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "mit:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Generier/erzeich \"Uffruf %1\""; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "Funktionsblock"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "zu"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "En Funktionsblock ohne Rückgäbweart."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "geb zurück"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "En Funktionsblock mit Rückgäbweart."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Warnung: die Funktionsblock hot doppelt Parameter."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Markiear Funktionsblock"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Wenn der earste Weart woahr (true) ist, Geb den zwooite Weart zurück."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Warnung: Der Block därref nuar innich en Funktionsblock genutzt sin."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "Markiear Funktionsblock"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Generier/erzeich \"Uffruf %1\""; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "Parameter"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Variable:"; -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "Kommentar entferne"; -Blockly.Msg.RENAME_VARIABLE = "Die neie Variable sei Noome:"; -Blockly.Msg.RENAME_VARIABLE_TITLE = "All \"%1\" Variable umbenenne in:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "Text oonhänge"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "An"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Text an die Variable \"%1\" oonhänge."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "umwandle in klenbuchstoobe"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "umwandle in Wörter"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "umwandle in GROSSBUCHSTOOBE"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Wandelt Schreibweise von Texte um, in Grossbuchstoobe, Klenbuchstoobe orrer den earste Buchstoob von jedes Wort gross und die annre klen."; -Blockly.Msg.TEXT_CHARAT_FIRST = "hol earschte Buchstoob"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "hol Buchstoob # von End"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "hol Buchstoob #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "in Text"; -Blockly.Msg.TEXT_CHARAT_LAST = "hol letztes Wort"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "hol zufälliches Buchstoob"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Extrahiear en Buchstoob von en spezifizierte Position."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "En Element zum Text hinzufüche."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "verbinne"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Hinzufüche, entfernne und sortiere von Elemente."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "bis #te Buchstoob von hinne"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "bis Buchstoob #te"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "bis letzte Buchstoob"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "in Text"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "earschte Buchstoob"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "hol #te Buchstoob von hinne"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "hol substring Buchstoob #te"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Schickt en bestimmstes Tel von dem Text retuar."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "im Text"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "Such der Begriff sein earstes Voarkommniss"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "Suche der Begriff sein letztes Vorkommniss."; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Findt das earste / letzte Voarkommniss von en Suchbegriffes in enem Text. Gebt die Position von dem Begriff orrer %1 zurück."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 ist leer?"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Ist woahr (true), wenn der Text leer ist."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "Erstell Text aus"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Erstellt en Text doorrich das verbinne von mehre Textelemente."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "läng %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Die Oonzoohl von Zeiche in enem Text. (inkl. Leerzeiche)"; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "Ausgäb %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Geb den Inhalt von en Variable aus."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Frocht den Benutzer noh en Zoohl."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Frocht den Benutzer noh enem Text."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "Frächt noh Zoohl mit Hinweis"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "Frocht noh Text mit Hinweis"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)https://hrx.wikipedia.org/wiki/Zeichenkette"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "En Buchstoob, Text orrer Satz."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "entfern Leerzeiche von Oonfang und End Seite"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "entferne Leerzeiche von Oonfang Seite"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "entferne Leerzeiche von End Seite von"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Entfernt Leerzeiche vom Oonfang und / orrer End von en Text."; -Blockly.Msg.TODAY = "Today"; // untranslated -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "Element"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Generier/erzeiche \"Schreibe %1\""; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Gebt der Variable sein Weart zurück."; -Blockly.Msg.VARIABLES_SET = "Schreib %1 zu %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Generier/erzeich \"Lese %1\""; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Setzt en Variable sei Weart."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/hu.js b/backend/_pv_1_3_5/static/blockly/msg/js/hu.js deleted file mode 100755 index 90fa37e4b..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/hu.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.hu'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Megjegyzés hozzáadása"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Érték módosítása:"; -Blockly.Msg.CLEAN_UP = "Blokkok kiürítése"; -Blockly.Msg.COLLAPSE_ALL = "Blokkok összecsukása"; -Blockly.Msg.COLLAPSE_BLOCK = "Blokk összecsukása"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "szín 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "szín 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "arány"; -Blockly.Msg.COLOUR_BLEND_TITLE = "színkeverés"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Két színt kever össze a megadott arányban (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://hu.wikipedia.org/wiki/Szín"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Válassz színt a palettáról."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "véletlen szín"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Véletlenszerűen kiválasztott szín."; -Blockly.Msg.COLOUR_RGB_BLUE = "kék"; -Blockly.Msg.COLOUR_RGB_GREEN = "zöld"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "vörös"; -Blockly.Msg.COLOUR_RGB_TITLE = "Szín"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Szín előállítása a megadott vörös, zöld, és kék értékekkel. Minden értéknek 0 és 100 közé kell esnie."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "befejezi az ismétlést"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "folytatja a következővel"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Megszakítja az utasítást tartalmazó ciklust."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Kihagyja a ciklus további részét, és elölről kezdi a következő elemmel."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Figyelem: Ez a blokk csak cikluson belül használható."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "minden %1 elemre a %2 listában"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "A '%1' változó minden lépésben megkapja a lista adott elemének értékét, és végrehajt vele néhány utasítást."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "számolj %1 értékével %2 és %3 között %4 lépésközzel"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "A(z) '%1' változó felveszi a kezdőérték és a végérték közötti értékeket a meghatározott lépésközzel. Eközben a meghatározott blokkokat hajtja végre."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Feltétel hozzáadása a ha blokkhoz."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Végső feltétel hozzáadása a ha blokkhoz."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "A ha blokk testreszabásához bővítsd, töröld vagy rendezd át a részeit."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "különben"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "különben ha"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "ha"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Ha a kifejezés igaz, akkor végrehajtja az utasításokat."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Ha a kifejezés igaz, akkor végrehajtja az első utasításblokkot. Különben a második utasításblokk kerül végrehajtásra."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Ha az első kifejezés igaz, akkor végrehajtja az első utasításblokkot. Különben, ha a második kifejezés igaz, akkor végrehajtja a második utasítás blokkot."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Ha az első kifejezés igaz, akkor végrehajtjuk az első utasítás blokkot. Ha a második kifejezés igaz, akkor végrehajtjuk a második utasítás blokkot. Amennyiben egyik kifejezés sem igaz, akkor az utolsó utasítás blokk kerül végrehajtásra."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://hu.wikipedia.org/wiki/Ciklus_(programoz%C3%A1s)#Sz.C3.A1ml.C3.A1l.C3.B3s_.28FOR.29_ciklus"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = ""; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "ismételd %1 alkalommal"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Megadott kódrészlet ismételt végrehajtása."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "ismételd amíg nem"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "ismételd amíg"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Amíg a feltétel hamis, végrehajtja az utasításokat."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Amíg a feltétel igaz, végrehajtja az utasításokat."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Az összes %1 blokk törlése?"; -Blockly.Msg.DELETE_BLOCK = "Blokk törlése"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "%1 blokk törlése"; -Blockly.Msg.DISABLE_BLOCK = "Blokk letiltása"; -Blockly.Msg.DUPLICATE_BLOCK = "Másolat"; -Blockly.Msg.ENABLE_BLOCK = "Blokk engedélyezése"; -Blockly.Msg.EXPAND_ALL = "Blokkok kibontása"; -Blockly.Msg.EXPAND_BLOCK = "Blokk kibontása"; -Blockly.Msg.EXTERNAL_INPUTS = "Külső kapcsolatok"; -Blockly.Msg.HELP = "Súgó"; -Blockly.Msg.INLINE_INPUTS = "Belső kapcsolatok"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "üres lista"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Elemeket nem tartalmazó üres listát ad eredményül"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "lista"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Add, remove, or reorder sections to reconfigure this list block."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "Lista készítés, elemek:"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Elem hozzáadása listához."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Listát készít a megadott elemekből."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "az első"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "a végétől számított"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "az elejétől számított"; -Blockly.Msg.LISTS_GET_INDEX_GET = "listából értéke"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "listából kivétele"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "az utolsó"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "bármely"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "listából törlése"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = "elemnek"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "A lista első elemét adja eredményül."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "A lista megadott sorszámú elemét adja eredményül."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "A lista utolsó elemét adja eredményül."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "A lista véletlenszerűen választott elemét adja eredményül."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Az első elem kivétele a listából."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "A megadott sorszámú elem kivétele a listából."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Az utolsó elem kivétele a listából."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Véletlenszerűen választott elem kivétele a listából."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Az első elem törlése a listából."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "A megadott sorszámú elem törlése a listából."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Az utolsó elem törlése a listából."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Véletlenszerűen választott elem törlése a listából."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "és a végétől számított"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "és az elejétől számított"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "és az utolsó"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "részlistája az első"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "részlistája a végétől számított"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "részlistája az elejétől számított"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = "elem között"; -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "A lista adott részéről másolat."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 az utolsó elemet jelenti."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 az első elemet jelenti."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "listában első előfordulásaː"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "listában utolsó előfordulásaː"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "A megadott elem első vagy utolsó előfordulásával tér vissza. Ha nem talál ilyen elemet, akkor %1 a visszatérési érték."; -Blockly.Msg.LISTS_INLIST = "A(z)"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 üres lista?"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Az eredmény igaz, ha a lista nem tartalmaz elemeket."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "%1 lista hossza"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "A lista elemszámát adja eredményül."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "Lista készítése %1 elemet %2 alkalommal hozzáadva"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "A megadtott elem felhasználásával n elemű listát készít"; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "elemkéntː"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "listába szúrd be"; -Blockly.Msg.LISTS_SET_INDEX_SET = "listába állítsd be"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Beszúrás a lista elejére."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Beszúrás a megadott sorszámú elem elé a listában."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Beszúrás a lista végére."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Beszúrás véletlenszerűen választott elem elé a listában."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Az első elem cseréje a listában."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "A megadott sorszámú elem cseréje a listában."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Az utolsó elem cseréje a listában."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Véletlenszerűen választott elem cseréje a listában."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "növekvő"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "csökkenő"; -Blockly.Msg.LISTS_SORT_TITLE = "%1 %2 %3 rendezés"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Egy lista egy másolatának rendezése."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "betűrendben nagybetű figyelmen kívül hagyásával"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numerikus"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "betűrendben"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "lista készítése szövegből"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "sztring készítése listából"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "A lista elemeit összefűzi szöveggé a határoló karaktereket is felhasználva."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Listát készít a határoló karaktereknél törve a szöveget."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "határoló karakter"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "hamis"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Igaz, vagy hamis érték"; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "igaz"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://hu.wikipedia.org/wiki/Egyenl%C5%91tlens%C3%A9g"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Igaz, ha a kifejezés két oldala egyenlő."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Igaz, ha a bal oldali kifejezés nagyobb, mint a jobb oldali."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Igaz, ha a bal oldali kifejezés nagyobb vagy egyenlő, mint a jobb oldali."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Igaz, ha a bal oldali kifejezés kisebb, mint a jobb oldali."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Igaz, ha a bal oldali kifejezés kisebb vagy egyenlő, mint a jobb oldali."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Igaz, ha a kifejezés két oldala nem egyenlő.."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "nem %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Igaz, ha a kifejezés hamis. Hamis, ha a kifejezés igaz."; -Blockly.Msg.LOGIC_NULL = "null"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "null érték."; -Blockly.Msg.LOGIC_OPERATION_AND = "és"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "vagy"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Igaz, ha mindkét kifejezés igaz."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Igaz, ha legalább az egyik kifejezés igaz."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "vizsgáld meg:"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "érték, ha hamis:"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "érték, ha igaz:"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Kiértékeli a megvizsgálandó kifejezést. Ha a kifejezés igaz, visszatér az \"érték, ha igaz\" értékkel, különben az \"érték, ha hamis\" értékkel."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://hu.wikipedia.org/wiki/Matematikai_m%C5%B1velet"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Két szám összege."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Két szám hányadosa."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Két szám különbsége."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Két szám szorzata."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Az első számnak a második számmal megegyező hatványa."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://hu.wikipedia.org/wiki/JavaScript#Aritmetikai_oper.C3.A1torok"; -Blockly.Msg.MATH_CHANGE_TITLE = "növeld %1 értékét %2 -vel"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "A \"%1\" változó értékének növelése egy számmal."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://hu.wikipedia.org/wiki/Matematikai_konstans"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Ismert matematikai konstans: π (3.141…), e (2.718…), φ (1.618…), gyök(2) (1.414…), gyök(½) (0.707…), vagy ∞ (végtelen)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "korlátozd %1-t %2 és %3 közé"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Egy változó értékének korlátozása a megadott zárt intervallumra."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "-nek osztója"; -Blockly.Msg.MATH_IS_EVEN = "páros"; -Blockly.Msg.MATH_IS_NEGATIVE = "negatív"; -Blockly.Msg.MATH_IS_ODD = "páratlan"; -Blockly.Msg.MATH_IS_POSITIVE = "pozitív"; -Blockly.Msg.MATH_IS_PRIME = "prím"; -Blockly.Msg.MATH_IS_TOOLTIP = "Ellenőrzi, hogy a szám páros, páratlan, prím, egész, pozitív vagy negatív-e, illetve osztható-e a másodikkal. Igaz, vagy hamis értéket ad eredményül."; -Blockly.Msg.MATH_IS_WHOLE = "egész"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://hu.wikipedia.org/wiki/Eg%C3%A9szr%C3%A9sz#Als.C3.B3_eg.C3.A9szr.C3.A9sz"; -Blockly.Msg.MATH_MODULO_TITLE = "%1 ÷ %2 maradéka"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Az egész osztás maradékát adja eredméynül."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://hu.wikipedia.org/wiki/Sz%C3%A1m"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Egy szám."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "lista elemeinek átlaga"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "lista legnagyobb eleme"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "lista mediánja"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "lista legkisebb eleme"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "lista módusza"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "lista véletlen eleme"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "lista elemeinek szórása"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "lista elemeinek összege"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "A lista elemeinek átlagát adja eredményül."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "A lista legnagyobb elemét adja vissza."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "A lista elemeinek mediánját adja eredményül."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "A lista legkisebb elemét adja vissza."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "A lista elemeinek móduszát adja eredményül."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "A lista egy véletlen elemét adja eredményül."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "A lista elemeinek szórását adja eredményül."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "A lista elemeinek összegét adja eredményül."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://hu.wikipedia.org/wiki/V%C3%A9letlen"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "véletlen tört"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Véletlen tört érték 0.0 és 1.0 között."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://hu.wikipedia.org/wiki/V%C3%A9letlen"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "véletlen egész szám %1 között %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Véletlen egész szám a megadott zárt intervallumon belül."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://hu.wikipedia.org/wiki/Eg%C3%A9szr%C3%A9sz#Kerek.C3.ADt.C3.A9s"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "kerekítsd"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "kerekítsd lefelé"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "kerekítsd felfelé"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Egy szám kerekítése felfelé vagy lefelé."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://hu.wikipedia.org/wiki/Gy%C3%B6kvon%C3%A1s"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "abszolútérték"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "négyzetgyök"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "A szám abszolútértéke."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Az e megadott számú hatványa."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "A szám természetes alapú logaritmusa."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "A szám 10-es alapú logaritmusa."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "A szám -1 szerese."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "A 10 megadott számú hatványa."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "A szám négyzetgyöke."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://hu.wikipedia.org/wiki/Sz%C3%B6gf%C3%BCggv%C3%A9nyek"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "A fokban megadott szög arkusz koszinusz értéke."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "A fokban megadott szög arkusz szinusz értéke."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "A fokban megadott szög arkusz tangens értéke."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "A fokban megadott szög koszinusz értéke."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "A fokban megadott szög szinusz értéke."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "A fokban megadott szög tangens értéke."; -Blockly.Msg.NEW_VARIABLE = "Új változó..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Az új változó neve:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = "."; -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "utasítások engedélyezése"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "paraméterlistaː"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://hu.wikipedia.org/wiki/F%C3%BCggv%C3%A9ny_(programoz%C3%A1s)"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Végrehajtja az eljárást."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://hu.wikipedia.org/wiki/F%C3%BCggv%C3%A9ny_(programoz%C3%A1s)"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Meghívja a függvényt."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "paraméterlistaː"; -Blockly.Msg.PROCEDURES_CREATE_DO = "„%1” létrehozása"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Írj erről a funkcióról..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "név"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "Eljárás"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Eljárás (nem ad vissza eredményt)."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "eredménye"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Függvény eredménnyel."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Figyelem: Az eljárásban azonos elnevezésű paramétert adtál meg."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Függvénydefiníció kiemelése"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Ha az érték igaz, akkor visszatér a függvény értékével."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Figyelem: Ez a blokk csak függvénydefiníción belül használható."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "változó:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Bemenet hozzáadása a függvényhez."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "paraméterek"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Bemenetek hozzáadása, eltávolítása vagy átrendezése ehhez a függvényhez."; -Blockly.Msg.REDO = "Újra"; -Blockly.Msg.REMOVE_COMMENT = "Megjegyzés törlése"; -Blockly.Msg.RENAME_VARIABLE = "Változó átnevezése..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Minden \"%1\" változó átnevezése erre:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "szövegéhez fűzd hozzá"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "A"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Szöveget fűz a \"%1\" változó értékéhez."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "kisbetűs"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "Címként Formázott"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "NAGYBETŰS"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; -Blockly.Msg.TEXT_CHARAT_FIRST = "első"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "hátulról"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "elölről"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "A"; -Blockly.Msg.TEXT_CHARAT_LAST = "utolsó"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "véletlen"; -Blockly.Msg.TEXT_CHARAT_TAIL = "karaktere"; -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "A szöveg egy megadott karakterét adja eredményül."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Elem hozzáfűzése a szöveghez."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "fűzd össze"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Összefűzéssel, törléssel vagy rendezéssel kapcsolato sblokkok szöveg szerkesztéséhez."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "betűtől a hátulról számított"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "betűtől a(z)"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "betűtől az utolsó"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "a"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "szövegben válaszd ki az első"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "szövegben válaszd ki a hátulról a(z)"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "szövegben válaszd ki a(z)"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = "betűig tartó betűsort"; -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "A megadott szövegrészletet adja eredményül."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "A(z)"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "szövegben az első előfordulásának helye"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "szövegben az utolsó előfordulásának helye"; -Blockly.Msg.TEXT_INDEXOF_TAIL = "szövegnek"; -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "A keresett szöveg első vagy utolsó előfordulásával tér vissza. %1 esetén a szövegrészlet nem található."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 üres"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Igaz, ha a vizsgált szöveg hossza 0."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "fűzd össze"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Tetszőleges számú szövegrészletet fűz össze egybefüggő szöveggé."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "%1 hossza"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "A megadott szöveg karaktereinek számát adja eredményül (beleértve a szóközöket)."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "Üzenet %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Megejelníti a megadott kaakterláncot üzenetként a képernyőn."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Számot kér be a felhasználótól."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Szöveget kér be a felhasználótól."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "Kérj be számot"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "Kérj be szöveget"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://hu.wikipedia.org/wiki/String"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Egy betű, szó vagy szöveg egy sora."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "szóközök levágása mindkét végéről"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "szóközök levágása az elejéről"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "szóközök levágása a végéről"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Levágja a megadott szöveg végeiről a szóközöket."; -Blockly.Msg.TODAY = "Ma"; -Blockly.Msg.UNDO = "Visszavonás"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "változó"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Készíts \"%1=\""; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "A változó értékét adja eredményül."; -Blockly.Msg.VARIABLES_SET = "%1 %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Készíts \"%1\""; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "A változónak adhatunk értéket."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/ia.js b/backend/_pv_1_3_5/static/blockly/msg/js/ia.js deleted file mode 100755 index 107664020..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/ia.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.ia'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Adder commento"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Cambiar valor:"; -Blockly.Msg.CLEAN_UP = "Clarar le blocos"; -Blockly.Msg.COLLAPSE_ALL = "Plicar blocos"; -Blockly.Msg.COLLAPSE_BLOCK = "Plicar bloco"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "color 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "color 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "ration"; -Blockly.Msg.COLOUR_BLEND_TITLE = "miscer"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Misce duo colores con un ration specificate (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://ia.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Elige un color del paletta."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "color aleatori"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Eliger un color al hasardo."; -Blockly.Msg.COLOUR_RGB_BLUE = "blau"; -Blockly.Msg.COLOUR_RGB_GREEN = "verde"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "rubie"; -Blockly.Msg.COLOUR_RGB_TITLE = "colorar con"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Crear un color con le quantitate specificate de rubie, verde e blau. Tote le valores debe esser inter 0 e 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "escappar del bucla"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "continuar con le proxime iteration del bucla"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Escappar del bucla continente."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Saltar le resto de iste bucla e continuar con le proxime iteration."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Attention: Iste bloco pote solmente esser usate in un bucla."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "pro cata elemento %1 in lista %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Pro cata elemento in un lista, mitter lo in le variabile '%1' e exequer certe instructiones."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "contar con %1 de %2 a %3 per %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Mitter in le variabile '%1' le valores ab le numero initial usque al numero final, con passos secundo le intervallo specificate, e exequer le blocos specificate."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Adder un condition al bloco \"si\"."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Adder un condition final de reserva al bloco \"si\"."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Adde, remove o reordina sectiones pro reconfigurar iste bloco \"si\"."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "si non"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "si non si"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "si"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Si un valor es ver, exequer certe instructiones."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Si un valor es ver, exequer le prime bloco de instructiones. Si non, exequer le secunde bloco de instructiones."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Si le prime valor es ver, exequer le prime bloco de instructiones. Si non, si le secunde valor es ver, exequer le secunde bloco de instructiones."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Si le prime valor es ver, exequer le prime bloco de instructiones. Si non, si le secunde valor es ver, exequer le secunde bloco de instructiones. Si necun del valores es ver, exequer le ultime bloco de instructiones."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "face"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "repeter %1 vices"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Exequer certe instructiones plure vices."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "repeter usque a"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "repeter durante que"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Durante que un valor es false, exequer certe instructiones."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Durante que un valor es ver, exequer certe instructiones."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Deler tote le %1 blocos?"; -Blockly.Msg.DELETE_BLOCK = "Deler bloco"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Deler %1 blocos"; -Blockly.Msg.DISABLE_BLOCK = "Disactivar bloco"; -Blockly.Msg.DUPLICATE_BLOCK = "Duplicar"; -Blockly.Msg.ENABLE_BLOCK = "Activar bloco"; -Blockly.Msg.EXPAND_ALL = "Displicar blocos"; -Blockly.Msg.EXPAND_BLOCK = "Displicar bloco"; -Blockly.Msg.EXTERNAL_INPUTS = "Entrata externe"; -Blockly.Msg.HELP = "Adjuta"; -Blockly.Msg.INLINE_INPUTS = "Entrata interne"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "crear un lista vacue"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Retorna un lista, de longitude 0, sin datos."; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "lista"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Adde, remove o reordina sectiones pro reconfigurar iste bloco de listas."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "crear lista con"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Adder un elemento al lista."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Crear un lista con un numero qualcunque de elementos."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "prime"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "№ ab fin"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "prender"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "prender e remover"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "ultime"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "aleatori"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "remover"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Retorna le prime elemento in un lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Retorna le elemento presente al position specificate in un lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Retorna le ultime elemento in un lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Retorna un elemento aleatori in un lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Remove e retorna le prime elemento in un lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Remove e retorna le elemento presente al position specificate in un lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Remove e retorna le ultime elemento in un lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Remove e retorna un elemento aleatori in un lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Remove le prime elemento in un lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Remove le elemento presente al position specificate in un lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Remove le ultime elemento in un lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Remove un elemento aleatori in un lista."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "usque al № ab fin"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "usque al №"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "usque al ultime"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "prender sublista ab initio"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "prender sublista ab le fin ab №"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "prender sublista ab №"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Crea un copia del parte specificate de un lista."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "№ %1 es le ultime elemento."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "№ %1 es le prime elemento."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "cercar le prime occurrentia del elemento"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "cercar le ultime occurrentia del elemento"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Retorna le indice del prime/ultime occurrentia del elemento in le lista. Retorna %1 si le elemento non es trovate."; -Blockly.Msg.LISTS_INLIST = "in lista"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 es vacue"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Retorna ver si le lista es vacue."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "longitude de %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Retorna le longitude de un lista."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "crear lista con elemento %1 repetite %2 vices"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Crea un lista que contine le valor fornite, repetite le numero specificate de vices."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "a"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "inserer in"; -Blockly.Msg.LISTS_SET_INDEX_SET = "mitter"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Insere le elemento al initio de un lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Insere le elemento al position specificate in un lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Adjunge le elemento al fin de un lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Insere le elemento a un position aleatori in un lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Defini le valor del prime elemento in un lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Defini le valor del elemento al position specificate in un lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Defini le valor del ultime elemento in un lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Defini le valor de un elemento aleatori in un lista."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascendente"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descendente"; -Blockly.Msg.LISTS_SORT_TITLE = "ordinamento %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Ordinar un copia de un lista."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignorar majuscula/minuscula"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "Crear un lista per un texto"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "crear un texto per un lista"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Unir un lista de textos, separate per un delimitator, in un sol texto."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Divider texto in un lista de textos, separante lo a cata delimitator."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "con delimitator"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "false"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Retorna o ver o false."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "ver"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Retornar ver si le duo entratas es equal."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Retornar ver si le prime entrata es major que le secunde."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Retornar ver si le prime entrata es major que o equal al secunde."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Retornar ver si le prime entrata es minor que le secunde."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Retornar ver si le prime entrata es minor que o equal al secunde."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Retornar ver si le duo entratas non es equal."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "non %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Retornar ver si le entrata es false. Retornar false si le entrata es ver."; -Blockly.Msg.LOGIC_NULL = "nulle"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Retorna nulle."; -Blockly.Msg.LOGIC_OPERATION_AND = "e"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "o"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Retornar ver si ambe entratas es ver."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Retornar ver si al minus un del entratas es ver."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "si false"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "si ver"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Verificar le condition in 'test'. Si le condition es ver, retorna le valor de 'si ver'; si non, retorna le valor de 'si false'."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://ia.wikipedia.org/wiki/Arithmetica"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Retornar le summa del duo numeros."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Retornar le quotiente del duo numeros."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Retornar le differentia del duo numeros."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Retornar le producto del duo numeros."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Retornar le prime numero elevate al potentia del secunde numero."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; // untranslated -Blockly.Msg.MATH_CHANGE_TITLE = "cambiar %1 per %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Adder un numero al variabile '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; // untranslated -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Retornar un del constantes commun: π (3,141…), e (2,718…), φ (1,618…), sqrt(2) (1,414…), sqrt(½) (0,707…) o ∞ (infinite)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "limitar %1 inter %2 e %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Limitar un numero a esser inter le limites specificate (incluse)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "es divisibile per"; -Blockly.Msg.MATH_IS_EVEN = "es par"; -Blockly.Msg.MATH_IS_NEGATIVE = "es negative"; -Blockly.Msg.MATH_IS_ODD = "es impare"; -Blockly.Msg.MATH_IS_POSITIVE = "es positive"; -Blockly.Msg.MATH_IS_PRIME = "es prime"; -Blockly.Msg.MATH_IS_TOOLTIP = "Verificar si un numero es par, impare, prime, integre, positive, negative, o divisibile per un certe numero. Retorna ver o false."; -Blockly.Msg.MATH_IS_WHOLE = "es integre"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; // untranslated -Blockly.Msg.MATH_MODULO_TITLE = "resto de %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Retornar le resto del division del duo numeros."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://ia.wikipedia.org/wiki/Numero"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Un numero."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "media del lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "maximo del lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "mediana del lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "minimo del lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "modas del lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "elemento aleatori del lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "deviation standard del lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "summa del lista"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Retornar le media arithmetic del valores numeric in le lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Retornar le numero le plus grande in le lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Retornar le numero median del lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Retornar le numero le plus parve in le lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Retornar un lista del elemento(s) le plus commun in le lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Retornar un elemento aleatori del lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Retornar le deviation standard del lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Retornar le summa de tote le numeros in le lista."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "fraction aleatori"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Retornar un fraction aleatori inter 0.0 (incluse) e 1.0 (excluse)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TITLE = "numero integre aleatori inter %1 e %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Retornar un numero integre aleatori inter le duo limites specificate, incluse."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://ia.wikipedia.org/wiki/Rotundamento"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "arrotundar"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "arrotundar a infra"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "arrotundar a supra"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Arrotundar un numero a supra o a infra."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://ia.wikipedia.org/wiki/Radice_quadrate"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absolute"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "radice quadrate"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Retornar le valor absolute de un numero."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Retornar e elevate al potentia del numero."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Retornar le logarithmo natural de un numero."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Retornar le logarithmo in base 10 del numero."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Retornar le negation de un numero."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Retornar 10 elevate al potentia de un numero."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Retornar le radice quadrate de un numero."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; // untranslated -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Retornar le arcocosino de un numero."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Retornar le arcosino de un numero."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Retornar le arcotangente de un numero."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Retornar le cosino de un grado (non radiano)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Retornar le sino de un grado (non radiano)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Retornar le tangente de un grado (non radiano)."; -Blockly.Msg.NEW_VARIABLE = "Nove variabile..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Nomine del nove variabile:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "permitter declarationes"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "con:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Executar le function '%1' definite per le usator."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Executar le function '%1' definite per le usator e usar su resultato."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "con:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Crear '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe iste function..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "facer qualcosa"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "pro"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Crea un function que non retorna un valor."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "retornar"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Crea un function que retorna un valor."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Attention: Iste function ha parametros duplicate."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Accentuar le definition del function"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Si un valor es ver, alora retornar un secunde valor."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Attention: Iste bloco pote solmente esser usate in le definition de un function."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "nomine del entrata:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Adder un entrata al function."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "entratas"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Adder, remover o reordinar le entratas pro iste function."; -Blockly.Msg.REDO = "Refacer"; -Blockly.Msg.REMOVE_COMMENT = "Remover commento"; -Blockly.Msg.RENAME_VARIABLE = "Renominar variabile..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Renominar tote le variabiles '%1' a:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "adjunger texto"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "a"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Adjunger un texto al variabile '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "in minusculas"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "con Initiales Majuscule"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "in MAJUSCULAS"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Retornar un copia del texto con differente majusculas/minusculas."; -Blockly.Msg.TEXT_CHARAT_FIRST = "prender le prime littera"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "prender ab le fin le littera №"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "prender le littera №"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "in le texto"; -Blockly.Msg.TEXT_CHARAT_LAST = "prender le ultime littera"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "prender un littera aleatori"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Retorna le littera presente al position specificate."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Adder un elemento al texto."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "unir"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Adde, remove o reordina sectiones pro reconfigurar iste bloco de texto."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "ab le fin usque al littera №"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "usque al littera №"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "usque al ultime littera"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "in le texto"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "prender subcatena ab le prime littera"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "prender subcatena ab le fin ab le littera №"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "prender subcatena ab le littera №"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Retorna le parte specificate del texto."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "in le texto"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "cercar le prime occurrentia del texto"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "cercar le ultime occurrentia del texto"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Retorna le indice del prime/ultime occurrentia del prime texto in le secunde texto. Retorna %1 si le texto non es trovate."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 es vacue"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Retorna ver si le texto fornite es vacue."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "crear texto con"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Crear un pecia de texto uniente un certe numero de elementos."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "longitude de %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Retorna le numero de litteras (incluse spatios) in le texto fornite."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "scriber %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Scriber le texto, numero o altere valor specificate."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Peter un numero al usator."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Peter un texto al usator."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "peter un numero con le message"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "peter un texto con le message"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; // untranslated -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Un littera, parola o linea de texto."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "remover spatios de ambe lateres de"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "remover spatios del sinistre latere de"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "remover spatios del dextre latere de"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Retornar un copia del texto con spatios eliminate de un extremitate o ambes."; -Blockly.Msg.TODAY = "Hodie"; -Blockly.Msg.UNDO = "Disfacer"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "cosa"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Crea 'mitter %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Retorna le valor de iste variabile."; -Blockly.Msg.VARIABLES_SET = "mitter %1 a %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Crear 'prender %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Mitte iste variabile al valor del entrata."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/id.js b/backend/_pv_1_3_5/static/blockly/msg/js/id.js deleted file mode 100755 index bfc163d80..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/id.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.id'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Tambahkan Komentar"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Ubah nilai:"; -Blockly.Msg.CLEAN_UP = "Bersihkan Blok"; -Blockly.Msg.COLLAPSE_ALL = "Ciutkan Blok"; -Blockly.Msg.COLLAPSE_BLOCK = "Ciutkan Blok"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "warna 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "warna 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "rasio"; -Blockly.Msg.COLOUR_BLEND_TITLE = "campur"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Campur dua warna secara bersamaan dengan perbandingan (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Pilih warna dari daftar warna."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "Warna acak"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Pilih warna secara acak."; -Blockly.Msg.COLOUR_RGB_BLUE = "biru"; -Blockly.Msg.COLOUR_RGB_GREEN = "hijau"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "merah"; -Blockly.Msg.COLOUR_RGB_TITLE = "Dengan warna"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Buatlah warna dengan jumlah yang ditentukan dari merah, hijau dan biru. Semua nilai harus antarai 0 sampai 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "keluar dari perulangan"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "lanjutkan dengan langkah perulangan berikutnya"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Keluar dari perulangan."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Abaikan sisa dari perulangan ini, dan lanjutkan dengan langkah berikutnya."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Peringatan: Blok ini hanya dapat digunakan dalam perulangan."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "untuk setiap item %1 di dalam list %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Untuk tiap-tiap item di dalam list, tetapkan variabel '%1' ke dalam item, selanjutnya kerjakan beberapa statement."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "Cacah dengan %1 dari %2 ke %3 dengan step / penambahan %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Menggunakan variabel \"%1\" dengan mengambil nilai dari batas awal hingga ke batas akhir, dengan interval tertentu, dan mengerjakan block tertentu."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Tambahkan prasyarat ke dalam blok IF."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Terakhir, tambahkan kondisi tangkap-semua kedalam blok IF."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Tambahkan, hapus, atau susun kembali bagian untuk mengkonfigurasi blok IF ini."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "lainnya"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "atau jika"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "jika"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Jika nilainya benar, maka lakukan beberapa perintah."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Jika nilainya benar, maka kerjakan perintah blok pertama. Jika tidak, kerjakan perintah blok kedua."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Jika nilai pertama benar, maka kerjakan perintah blok pertama. Sebaliknya, jika nilai kedua benar, kerjakan perintah blok kedua."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Jika nilai pertama benar, maka kerjakan perintah blok pertama. Sebaliknya, jika nilai kedua benar, kerjakan perintah blok kedua. Jika dua-duanya tidak benar, kerjakan perintah blok terakhir."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "kerjakan"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "ulangi %1 kali"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Lakukan beberapa perintah beberapa kali."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "ulangi sampai"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "ulangi jika"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Selagi nilainya salah, maka lakukan beberapa perintah."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Selagi nilainya benar, maka lakukan beberapa perintah."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Hapus semua %1 blok?"; -Blockly.Msg.DELETE_BLOCK = "Hapus Blok"; -Blockly.Msg.DELETE_VARIABLE = "Hapus variabel '%1'"; -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Hapus %1 yang digunakan pada variabel '%2'?"; -Blockly.Msg.DELETE_X_BLOCKS = "Hapus %1 Blok"; -Blockly.Msg.DISABLE_BLOCK = "Nonaktifkan Blok"; -Blockly.Msg.DUPLICATE_BLOCK = "Duplikat"; -Blockly.Msg.ENABLE_BLOCK = "Aktifkan Blok"; -Blockly.Msg.EXPAND_ALL = "Kembangkan Blok"; -Blockly.Msg.EXPAND_BLOCK = "Kembangkan Blok"; -Blockly.Msg.EXTERNAL_INPUTS = "Input Eksternal"; -Blockly.Msg.HELP = "Bantuan"; -Blockly.Msg.INLINE_INPUTS = "Input Inline"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "buat list kosong"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Kembalikan list, dengan panjang 0, tidak berisi data"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "list"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Tambahkan, hapus, atau susun ulang bagian untuk mengkonfigurasi blok list ini."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "buat list dengan"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Tambahkan sebuah item ke list."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Buat sebuah list dengan sejumlah item."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "pertama"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# dari akhir"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "dapatkan"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "dapatkan dan hapus"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "terakhir"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "acak"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "Hapus"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Kembalikan item pertama dalam list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Kembalikan item di posisi tertentu dalam list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Kembalikan item terakhir dalam list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Kembalikan item acak dalam list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Hapus dan kembalikan item pertama dalam list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Hapus dan kembalikan item di posisi tertentu dalam list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Hapus dan kembalikan item terakhir dalam list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Hapus dan kembalikan item acak dalam list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Hapus item pertama dalam list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Hapus item di posisi tertentu dalam list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Hapus item terakhir dalam list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Hapus sebuah item acak dalam list."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "ke # dari akhir"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "ke #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "ke yang paling akhir"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "dapatkan sub-list dari pertama"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "dapatkan sub-list dari nomor # dari akhir"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "dapatkan sub-list dari #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Buat salinan bagian tertentu dari list."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 adalah item terakhir."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 adalah item pertama."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "cari kejadian pertama item"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "cari kejadian terakhir item"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Kembalikan indeks dari item pertama/terakhir kali muncul dalam list. Kembalikan %1 jika item tidak ditemukan."; -Blockly.Msg.LISTS_INLIST = "dalam list"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 kosong"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Kembalikan benar jika list kosong."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "panjang dari %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Kembalikan panjang list."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "buat list dengan item %1 diulang %2 kali"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Buat sebuah list yang terdiri dari nilai yang diberikan diulang sebanyak jumlah yang ditentukan."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "sebagai"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "sisipkan di"; -Blockly.Msg.LISTS_SET_INDEX_SET = "tetapkan"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Sisipkan item di bagian awal dari list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Sisipkan item ke dalam posisi yang telah ditentukan di dalam list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Tambahkan item ke bagian akhir list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Sisipkan item secara acak ke dalam list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Tetapkan item pertama di dalam list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Tetapkan item ke dalam posisi yang telah ditentukan di dalam list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Menetapkan item terakhir dalam list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Tetapkan secara acak sebuah item dalam list."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "menaik"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "menurun"; -Blockly.Msg.LISTS_SORT_TITLE = "urutkan %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Urutkan salinan dari daftar"; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "sesuai abjad, abaikan kasus"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "sesuai nomor"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "sesuai abjad"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "buat list dari teks"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "buat teks dari list"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Gabung daftar teks menjadi satu teks, yang dipisahkan oleh pembatas."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Membagi teks ke dalam daftar teks, pisahkan pada setiap pembatas."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "dengan pembatas"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "salah"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Kembalikan benar atau salah."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "benar"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Kembalikan benar jika kedua input sama satu dengan lainnya."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Kembalikan benar jika input pertama lebih besar dari input kedua."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Kembalikan benar jika input pertama lebih besar dari atau sama dengan input kedua."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Kembalikan benar jika input pertama lebih kecil dari input kedua."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Kembalikan benar jika input pertama lebih kecil atau sama dengan input kedua ."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Kembalikan benar jika kedua input tidak sama satu dengan lainnya."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "bukan (not) %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Kembalikan benar jika input salah. Kembalikan salah jika input benar."; -Blockly.Msg.LOGIC_NULL = "null"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Kembalikan null."; -Blockly.Msg.LOGIC_OPERATION_AND = "dan"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "atau"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Kembalikan benar jika kedua input adalah benar."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Kembalikan benar jika minimal satu input nilainya benar."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "jika salah"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "jika benar"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Periksa kondisi di 'test'. Jika kondisi benar, kembalikan nilai 'if true'; jika sebaliknya kembalikan nilai 'if false'."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://id.wikipedia.org/wiki/Aritmetika"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Kembalikan jumlah dari kedua angka."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Kembalikan hasil bagi dari kedua angka."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Kembalikan selisih dari kedua angka."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Kembalikan perkalian dari kedua angka."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Kembalikan angka pertama pangkat angka kedua."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "ubah %1 oleh %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Tambahkan angka kedalam variabel '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Kembalikan salah satu konstanta: π (3,141…), e (2,718…), φ (1,618…), akar(2) (1,414…), akar(½) (0.707…), atau ∞ (tak terhingga)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "Batasi %1 rendah %2 tinggi %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Batasi angka antara batas yang ditentukan (inklusif)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "dapat dibagi oleh"; -Blockly.Msg.MATH_IS_EVEN = "adalah bilangan genap"; -Blockly.Msg.MATH_IS_NEGATIVE = "adalah bilangan negatif"; -Blockly.Msg.MATH_IS_ODD = "adalah bilangan ganjil"; -Blockly.Msg.MATH_IS_POSITIVE = "adalah bilangan positif"; -Blockly.Msg.MATH_IS_PRIME = "adalah bilangan pokok"; -Blockly.Msg.MATH_IS_TOOLTIP = "Periksa apakah angka adalah bilangan genap, bilangan ganjil, bilangan pokok, bilangan bulat, bilangan positif, bilangan negatif, atau apakan bisa dibagi oleh angka tertentu. Kembalikan benar atau salah."; -Blockly.Msg.MATH_IS_WHOLE = "adalah bilangan bulat"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "sisa dari %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Kembalikan sisa dari pembagian ke dua angka."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Suatu angka."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "rata-rata dari list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "maksimum dari list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "median dari list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "minimum dari list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "mode-mode dari list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "item acak dari list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "deviasi standar dari list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "jumlah dari list"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Kembalikan rata-rata (mean aritmetik) dari nilai numerik dari list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Kembalikan angka terbesar dari list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Kembalikan median dari list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Kembalikan angka terkecil dari list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Kembalikan list berisi item yang paling umum dari dalam list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Kembalikan elemen acak dari list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Kembalikan standard deviasi dari list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Kembalikan jumlah dari seluruh bilangan dari list."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "nilai pecahan acak"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Kembalikan nilai pecahan acak antara 0.0 (inklusif) dan 1.0 (eksklusif)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "acak bulat dari %1 sampai %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Kembalikan bilangan acak antara dua batas yang ditentukan, inklusif."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "membulatkan"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "membulatkan kebawah"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "membulatkan keatas"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Bulatkan suatu bilangan naik atau turun."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "mutlak"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "akar"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Kembalikan nilai absolut angka."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Kembalikan 10 pangkat angka."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Kembalikan logaritma natural dari angka."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Kembalikan dasar logaritma 10 dari angka."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Kembalikan penyangkalan terhadap angka."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Kembalikan 10 pangkat angka."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Kembalikan akar dari angka."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "acos"; -Blockly.Msg.MATH_TRIG_ASIN = "asin"; -Blockly.Msg.MATH_TRIG_ATAN = "atan"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tan"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Kembalikan acosine dari angka."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Kembalikan asin dari angka."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Kembalikan atan dari angka."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Kembalikan cosinus dari derajat (bukan radian)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Kembalikan sinus dari derajat (bukan radian)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Kembalikan tangen dari derajat (bukan radian)."; -Blockly.Msg.NEW_VARIABLE = "Buat variabel..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Nama variabel baru:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "memungkinkan pernyataan"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "dengan:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Menjalankan fungsi '%1' yang ditetapkan pengguna."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Menjalankan fungsi '%1' yang ditetapkan pengguna dan menggunakan outputnya."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "dengan:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Buat '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Jelaskan fungsi ini..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "buat sesuatu"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "untuk"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Buat sebuah fungsi tanpa output."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "kembali"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Buat sebuah fungsi dengan satu output."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Peringatan: Fungsi ini memiliki parameter duplikat."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Sorot definisi fungsi"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Jika nilai yang benar, kemudian kembalikan nilai kedua."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Peringatan: Blok ini dapat digunakan hanya dalam definisi fungsi."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "masukan Nama:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Tambahkan masukan ke fungsi."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "input"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Menambah, menghapus, atau menyusun ulang masukan untuk fungsi ini."; -Blockly.Msg.REDO = "Lakukan ulang"; -Blockly.Msg.REMOVE_COMMENT = "Hapus Komentar"; -Blockly.Msg.RENAME_VARIABLE = "Ubah nama variabel..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Ubah nama semua variabel '%1' menjadi:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "tambahkan teks"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "untuk"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Tambahkan beberapa teks ke variabel '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "menjadi huruf kecil"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "menjadi huruf pertama kapital"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "menjadi huruf kapital"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Kembalikan kopi dari text dengan kapitalisasi yang berbeda."; -Blockly.Msg.TEXT_CHARAT_FIRST = "ambil huruf pertama"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "ambil huruf nomor # dari belakang"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "ambil huruf ke #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "dalam teks"; -Blockly.Msg.TEXT_CHARAT_LAST = "ambil huruf terakhir"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "ambil huruf secara acak"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Kembalikan karakter dari posisi tertentu."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Tambahkan suatu item ke dalam teks."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "join"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Tambah, ambil, atau susun ulang teks blok."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "pada huruf nomer # dari terakhir"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "pada huruf #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "pada huruf terakhir"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "in teks"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "ambil bagian teks (substring) dari huruf pertama"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "ambil bagian teks (substring) dari huruf ke # dari terakhir"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "ambil bagian teks (substring) dari huruf no #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Kembalikan spesifik bagian dari teks."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "dalam teks"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "temukan kejadian pertama dalam teks"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "temukan kejadian terakhir dalam teks"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Kembalikan indeks pertama dan terakhir dari kejadian pertama/terakhir dari teks pertama dalam teks kedua. Kembalikan %1 jika teks tidak ditemukan."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 kosong"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Kembalikan benar jika teks yang disediakan kosong."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "buat teks dengan"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Buat teks dengan cara gabungkan sejumlah item."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "panjang dari %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Kembalikan sejumlah huruf (termasuk spasi) dari teks yang disediakan."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "cetak %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Cetak teks yant ditentukan, angka atau ninlai lainnya."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Meminta pengguna untuk memberi sebuah angka."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Meminta pengguna untuk memberi beberapa teks."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "Meminta angka dengan pesan"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "meminta teks dengan pesan"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Huruf, kata atau baris teks."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "pangkas ruang dari kedua belah sisi"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "pangkas ruang dari sisi kiri"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "pangkas ruang dari sisi kanan"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Kembali salinan teks dengan spasi dihapus dari satu atau kedua ujungnya."; -Blockly.Msg.TODAY = "Hari ini"; -Blockly.Msg.UNDO = "Urungkan"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "item"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Buat 'set %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Kembalikan nilai variabel ini."; -Blockly.Msg.VARIABLES_SET = "tetapkan %1 untuk %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Buat 'get %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "tetapkan variabel ini dengan input yang sama."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "Sebuah variabel dengan nama '%1' sudah ada."; -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/is.js b/backend/_pv_1_3_5/static/blockly/msg/js/is.js deleted file mode 100755 index 8b7eed1af..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/is.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.is'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Skrifa skýringu"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Breyta gildi:"; -Blockly.Msg.CLEAN_UP = "Hreinsa kubba"; -Blockly.Msg.COLLAPSE_ALL = "Loka kubbum"; -Blockly.Msg.COLLAPSE_BLOCK = "Loka kubbi"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "litur 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "litur 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "hlutfall"; -Blockly.Msg.COLOUR_BLEND_TITLE = "blöndun"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Blandar tveimur litum í gefnu hlutfalli (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Velja lit úr litakorti."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "einhver litur"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Velja einhvern lit af handahófi."; -Blockly.Msg.COLOUR_RGB_BLUE = "blátt"; -Blockly.Msg.COLOUR_RGB_GREEN = "grænt"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "rauður"; -Blockly.Msg.COLOUR_RGB_TITLE = "litur"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Búa til lit úr tilteknu magni af rauðu, grænu og bláu. Allar tölurnar verða að vera á bilinu 0 til 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "fara út úr lykkju"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "fara beint í næstu umferð lykkjunnar"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Fara út úr umlykjandi lykkju."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Sleppa afganginum af lykkjunni og fara beint í næstu umferð hennar."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Aðvörun: Þennan kubb má aðeins nota innan lykkju."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "fyrir hvert %1 í lista %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Fyrir hvert atriði í lista er breyta '%1' stillt á atriðið og skipanir gerðar."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; -Blockly.Msg.CONTROLS_FOR_TITLE = "telja með %1 frá %2 til %3 um %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Láta breytuna '%1' taka inn gildi frá fyrstu tölu til síðustu tölu, hlaupandi á tiltekna bilinu og gera tilteknu kubbana."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Bæta skilyrði við EF kubbinn."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Bæta við hluta EF kubbs sem grípur öll tilfelli sem uppfylla ekki hin skilyrðin."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Bæta við, fjarlægja eða umraða til að breyta skipan þessa EF kubbs."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "annars"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "annars ef"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "ef"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Ef gildi er satt skal gera einhverjar skipanir."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Ef gildi er satt skal gera skipanir í fyrri kubbnum. Annars skal gera skipanir í seinni kubbnum."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Ef fyrra gildið er satt skal gera skipanir í fyrri kubbnum. Annars, ef seinna gildið er satt, þá skal gera skipanir í seinni kubbnum."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Ef fyrra gildið er satt skal gera skipanir í fyrri kubbnum. Annars, ef seinna gildið er satt, skal gera skipanir í seinni kubbnum. Ef hvorugt gildið er satt, skal gera skipanir í síðasta kubbnum."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "gera"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "endurtaka %1 sinnum"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Gera eitthvað aftur og aftur."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "endurtaka þar til"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "endurtaka á meðan"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Endurtaka eitthvað á meðan gildi er ósatt."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Endurtaka eitthvað á meðan gildi er satt."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Eyða öllum %1 kubbunum?"; -Blockly.Msg.DELETE_BLOCK = "Eyða kubbi"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Eyða %1 kubbum"; -Blockly.Msg.DISABLE_BLOCK = "Óvirkja kubb"; -Blockly.Msg.DUPLICATE_BLOCK = "Afrita"; -Blockly.Msg.ENABLE_BLOCK = "Virkja kubb"; -Blockly.Msg.EXPAND_ALL = "Opna kubba"; -Blockly.Msg.EXPAND_BLOCK = "Opna kubb"; -Blockly.Msg.EXTERNAL_INPUTS = "Ytri inntök"; -Blockly.Msg.HELP = "Hjálp"; -Blockly.Msg.INLINE_INPUTS = "Innri inntök"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "búa til tóman lista"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Skilar lista með lengdina 0 án gagna"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "listi"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Bæta við, fjarlægja eða umraða hlutum til að breyta skipan þessa listakubbs."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "búa til lista með"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Bæta atriði við listann."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Búa til lista með einhverjum fjölda atriða."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "fyrsta"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# frá enda"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "sækja"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "sækja og fjarlægja"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "síðasta"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "eitthvert"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "fjarlægja"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Skilar fyrsta atriði í lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Skilar atriðinu í hinum tiltekna stað í lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Skilar síðasta atriði í lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Skilar einhverju atriði úr lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Fjarlægir og skilar fyrsta atriðinu í lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Fjarlægir og skilar atriðinu á hinum tiltekna stað í lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Fjarlægir og skilar síðasta atriðinu í lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Fjarlægir og skilar einhverju atriði úr lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Fjarlægir fyrsta atriðið í lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Fjarlægir atriðið á hinum tiltekna stað í lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Fjarlægir síðasta atriðið í lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Fjarlægir eitthvert atriði úr lista."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "til # frá enda"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "til #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "til síðasta"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "sækja undirlista frá fyrsta"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "sækja undirlista frá # frá enda"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "sækja undirlista frá #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Býr til afrit af tilteknum hluta lista."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 er síðasta atriðið."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 er fyrsta atriðið."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "finna fyrsta tilfelli atriðis"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; -Blockly.Msg.LISTS_INDEX_OF_LAST = "finna síðasta tilfelli atriðis"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Finnur hvar atriðið kemur fyrir fyrst/síðast í listanum og skilar sæti þess. Skilar %1 ef atriðið finnst ekki."; -Blockly.Msg.LISTS_INLIST = "í lista"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 er tómur"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Skilar sönnu ef listinn er tómur."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; -Blockly.Msg.LISTS_LENGTH_TITLE = "lengd %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Skilar lengd lista."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg.LISTS_REPEAT_TITLE = "búa til lista með atriði %1 endurtekið %2 sinnum"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Býr til lista sem inniheldur tiltekna gildið endurtekið tiltekið oft."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "sem"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "bæta við"; -Blockly.Msg.LISTS_SET_INDEX_SET = "setja í"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Bætir atriðinu fremst í listann."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Bætir atriðinu í listann á tilteknum stað."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Bætir atriðinu aftan við listann."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Bætir atriðinu einhversstaðar við listann."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Setur atriðið í fyrsta sæti lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Setur atriðið í tiltekna sætið í listanum."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Setur atriðið í síðasta sæti lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Setur atriðið í eitthvert sæti lista."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "hækkandi"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "lækkandi"; -Blockly.Msg.LISTS_SORT_TITLE = "raða %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Raða afriti lista."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "í stafrófsröð án tillits til stafstöðu"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "í númeraröð"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "í stafrófsröð"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "gera lista úr texta"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "gera texta úr lista"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Sameinar lista af textum í einn texta, með skiltákn á milli."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Skiptir texta í lista af textum, með skil við hvert skiltákn."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "með skiltákni"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "ósatt"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Skilar annað hvort sönnu eða ósönnu."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "satt"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Skila sönnu ef inntökin eru jöfn."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Skila sönnu ef fyrra inntakið er stærra en seinna inntakið."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Skila sönnu ef fyrra inntakið er stærra en eða jafnt og seinna inntakið."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Skila sönnu ef fyrra inntakið er minna en seinna inntakið."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Skila sönnu ef fyrra inntakið er minna en eða jafnt og seinna inntakið."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Skila sönnu ef inntökin eru ekki jöfn."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; -Blockly.Msg.LOGIC_NEGATE_TITLE = "ekki %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Skilar sönnu ef inntakið er ósatt. Skilar ósönnu ef inntakið er satt."; -Blockly.Msg.LOGIC_NULL = "tómagildi"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Skilar tómagildi."; -Blockly.Msg.LOGIC_OPERATION_AND = "og"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; -Blockly.Msg.LOGIC_OPERATION_OR = "eða"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Skila sönnu ef bæði inntökin eru sönn."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Skila sönnu ef að minnsta kosti eitt inntak er satt."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "prófun"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "ef ósatt"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "ef satt"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Kanna skilyrðið í 'prófun'. Skilar 'ef satt' gildinu ef skilyrðið er satt, en skilar annars 'ef ósatt' gildinu."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Arithmetic"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Skila summu talnanna tveggja."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Skila deilingu talnanna."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Skila mismun talnanna."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Skila margfeldi talnanna."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Skila fyrri tölunni í veldinu seinni talan."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "breyta %1 um %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Bæta tölu við breytu '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Skila algengum fasta: π (3.141…), e (2.718…), φ (1.618…), kvrót(2) (1.414…), kvrót(½) (0.707…) eða ∞ (óendanleika)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "þröngva %1 lægst %2 hæst %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Þröngva tölu til að vera innan hinna tilgreindu marka (að báðum meðtöldum)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "er\u00A0deilanleg með"; -Blockly.Msg.MATH_IS_EVEN = "er\u00A0jöfn tala"; -Blockly.Msg.MATH_IS_NEGATIVE = "er neikvæð"; -Blockly.Msg.MATH_IS_ODD = "er oddatala"; -Blockly.Msg.MATH_IS_POSITIVE = "er jákvæð"; -Blockly.Msg.MATH_IS_PRIME = "er prímtala"; -Blockly.Msg.MATH_IS_TOOLTIP = "Kanna hvort tala sé jöfn tala, oddatala, jákvæð, neikvæð eða deilanleg með tiltekinni tölu. Skilar sönnu eða ósönnu."; -Blockly.Msg.MATH_IS_WHOLE = "er heiltala"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "afgangur af %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Skila afgangi deilingar með tölunum."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Tala."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "meðaltal lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "stærst í lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "miðgildi lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "minnst í lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "tíðast í lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "eitthvað úr lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "staðalfrávik lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "summa lista"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Skila meðaltali talna í listanum."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Skila stærstu tölu í listanum."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Skila miðgildi listans."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Skila minnstu tölu í listanum."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Skila lista yfir tíðustu gildin í listanum."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Skila einhverju atriði úr listanum."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Skila staðalfráviki lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Skila summu allra talna í listanum."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "slembibrot"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Skila broti sem er valið af handahófi úr tölum á bilinu frá og með 0.0 til (en ekki með) 1.0."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "slembitala frá %1 til %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Skila heiltölu sem valin er af handahófi og er innan tilgreindra marka, að báðum meðtöldum."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "námunda"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "námunda niður"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "námunda upp"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Námunda tölu upp eða niður."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "algildi"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "kvaðratrót"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Skila algildi tölu."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Skila e í veldi tölu."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Skila náttúrlegum lógaritma tölu."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Skila tugalógaritma tölu."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Skila neitun tölu (tölunni með öfugu formerki)."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Skila 10 í veldi tölu."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Skila kvaðratrót tölu."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "acos"; -Blockly.Msg.MATH_TRIG_ASIN = "asin"; -Blockly.Msg.MATH_TRIG_ATAN = "atan"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tan"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Skila arkarkósínusi tölu."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Skila arkarsínusi tölu."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Skila arkartangensi tölu."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Skila kósínusi horns gefnu í gráðum."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Skila sínusi horns gefnu í gráðum."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Skila tangensi horns gefnu í gráðum."; -Blockly.Msg.NEW_VARIABLE = "Ný breyta..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Heiti nýrrar breytu:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "leyfa setningar"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "með:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Keyra heimatilbúna fallið '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Keyra heimatilbúna fallið '%1' og nota úttak þess."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "með:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Búa til '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Lýstu þessari aðgerð/falli..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "gera eitthvað"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "til að"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Býr til fall sem skilar engu."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "skila"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Býr til fall sem skilar úttaki."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Aðvörun: Þetta fall er með tvítekna stika."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Sýna skilgreiningu falls"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Ef gildi er satt, skal skila öðru gildi."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Aðvörun: Þennan kubb má aðeins nota í skilgreiningu falls."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "heiti inntaks:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Bæta inntaki við fallið."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "inntök"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Bæta við, fjarlægja eða umraða inntökum fyrir þetta fall."; -Blockly.Msg.REDO = "Endurtaka"; -Blockly.Msg.REMOVE_COMMENT = "Fjarlægja skýringu"; -Blockly.Msg.RENAME_VARIABLE = "Endurnefna breytu..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Endurnefna allar '%1' breyturnar:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "bæta texta"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; -Blockly.Msg.TEXT_APPEND_TO = "við"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Bæta texta við breytuna '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "í lágstafi"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "í Upphafstafi"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "í HÁSTAFI"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Skila afriti af textanum með annarri stafastöðu."; -Blockly.Msg.TEXT_CHARAT_FIRST = "sækja fyrsta staf"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "sækja staf # frá enda"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "sækja staf #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "í texta"; -Blockly.Msg.TEXT_CHARAT_LAST = "sækja síðasta staf"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "sækja einhvern staf"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Skila staf á tilteknum stað."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Bæta atriði við textann."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "tengja"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Bæta við, fjarlægja eða umraða hlutum til að breyta skipan þessa textakubbs."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "að staf # frá enda"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "að staf #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "að síðasta staf"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "í texta"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "sækja textabút frá fyrsta staf"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "sækja textabút frá staf # frá enda"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "sækja textabút frá staf #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Skilar tilteknum hluta textans."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "í texta"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "finna fyrsta tilfelli texta"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "finna síðasta tilfelli texta"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Finnur fyrsta/síðasta tilfelli fyrri textans í seinni textanum og skilar sæti hans. Skilar %1 ef textinn finnst ekki."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 er tómur"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Skilar sönnu ef gefni textinn er tómur."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "búa til texta með"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Búa til texta með því að tengja saman einhvern fjölda atriða."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; -Blockly.Msg.TEXT_LENGTH_TITLE = "lengd %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Skilar fjölda stafa (með bilum) í gefna textanum."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; -Blockly.Msg.TEXT_PRINT_TITLE = "prenta %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Prenta tiltekinn texta, tölu eða annað gildi."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Biðja notandann um tölu."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Biðja notandann um texta."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "biðja um tölu með skilaboðum"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "biðja um texta með skilaboðum"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Stafur, orð eða textalína."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "eyða bilum báðum megin við"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "eyða bilum vinstra megin við"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "eyða bilum hægra megin við"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Skila afriti af textanum þar sem möguleg bil við báða enda hafa verið fjarlægð."; -Blockly.Msg.TODAY = "Í dag"; -Blockly.Msg.UNDO = "Afturkalla"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "atriði"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Búa til 'stilla %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Skilar gildi þessarar breytu."; -Blockly.Msg.VARIABLES_SET = "stilla %1 á %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Búa til 'sækja %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Stillir þessa breytu á innihald inntaksins."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/it.js b/backend/_pv_1_3_5/static/blockly/msg/js/it.js deleted file mode 100755 index 238a87e75..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/it.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.it'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Aggiungi commento"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Modifica valore:"; -Blockly.Msg.CLEAN_UP = "Pulisci i blocchi"; -Blockly.Msg.COLLAPSE_ALL = "Comprimi blocchi"; -Blockly.Msg.COLLAPSE_BLOCK = "Comprimi blocco"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "colore 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "colore 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "rapporto"; -Blockly.Msg.COLOUR_BLEND_TITLE = "miscela"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Mescola due colori insieme con un determinato rapporto (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://it.wikipedia.org/wiki/Colore"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Scegli un colore dalla tavolozza."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "colore casuale"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Scegli un colore a caso."; -Blockly.Msg.COLOUR_RGB_BLUE = "blu"; -Blockly.Msg.COLOUR_RGB_GREEN = "verde"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "rosso"; -Blockly.Msg.COLOUR_RGB_TITLE = "colora con"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Crea un colore con la quantità specificata di rosso, verde e blu. Tutti i valori devono essere compresi tra 0 e 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "esce dal ciclo"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "prosegui con la successiva iterazione del ciclo"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Esce dal ciclo."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Salta il resto di questo ciclo e prosegue con la successiva iterazione."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Attenzioneː Questo blocco può essere usato solo in un ciclo."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "per ogni elemento %1 nella lista %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Per ogni elemento in una lista, imposta la variabile '%1' pari all'elemento e quindi esegue alcune istruzioni."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "conta con %1 da %2 a %3 per %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Fa sì che la variabile '%1' prenda tutti i valori a partire dal numero di partenza fino a quello di arrivo, con passo pari all'intervallo specificato, ed esegue il blocco indicato."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Aggiungi una condizione al blocco se."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Aggiungi una condizione finale pigliatutto al blocco se."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Aggiungi, elimina o riordina le sezioni per riconfigurare questo blocco se."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "altrimenti"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "altrimenti se"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "se"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Se un valore è vero allora esegue alcune istruzioni."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Se un valore è vero allora esegue il primo blocco di istruzioni. Altrimenti esegue il secondo blocco di istruzioni."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Se il primo valore è vero allora esegue un primo blocco di istruzioni. Altrimenti, se il secondo valore è vero, esegue un secondo blocco di istruzioni."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Se il primo valore è vero allora esegue un primo blocco di istruzioni. Altrimenti, se il secondo valore è vero, esegue un secondo blocco di istruzioni. Se nessuno dei valori è vero esegue l'ultimo blocco di istruzioni."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://it.wikipedia.org/wiki/Ciclo_for"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "fai"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "ripeti %1 volte"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Esegue alcune istruzione diverse volte."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "ripeti fino a che"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "ripeti mentre"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Finché un valore è falso, esegue alcune istruzioni."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Finché un valore è vero, esegue alcune istruzioni."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Cancellare tutti i %1 blocchi?"; -Blockly.Msg.DELETE_BLOCK = "Cancella blocco"; -Blockly.Msg.DELETE_VARIABLE = "Cancella la variabile '%1'"; -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Cancella %1 usi della variabile '%2'?"; -Blockly.Msg.DELETE_X_BLOCKS = "Cancella %1 blocchi"; -Blockly.Msg.DISABLE_BLOCK = "Disattiva blocco"; -Blockly.Msg.DUPLICATE_BLOCK = "Duplica"; -Blockly.Msg.ENABLE_BLOCK = "Attiva blocco"; -Blockly.Msg.EXPAND_ALL = "Espandi blocchi"; -Blockly.Msg.EXPAND_BLOCK = "Espandi blocco"; -Blockly.Msg.EXTERNAL_INPUTS = "Ingressi esterni"; -Blockly.Msg.HELP = "Aiuto"; -Blockly.Msg.INLINE_INPUTS = "Ingressi in linea"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "crea lista vuota"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Restituisce una lista, di lunghezza 0, contenente nessun record di dati"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "lista"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Aggiungi, rimuovi o riordina le sezioni per riconfigurare il blocco lista."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "crea lista con"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Aggiunge un elemento alla lista."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Crea una lista con un certo numero di elementi."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "primo"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# dalla fine"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "prendi"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "prendi e rimuovi"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "ultimo"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "casuale"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "rimuovi"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Restituisce il primo elemento in una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Restituisce l'elemento nella posizione indicata della lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Restituisce l'ultimo elemento in una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Restituisce un elemento casuale in una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Rimuove e restituisce il primo elemento in una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Rimuove e restituisce l'elemento nella posizione indicata in una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Restituisce e rimuove l'ultimo elemento in una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Restituisce e rimuove un elemento casuale in una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Rimuove il primo elemento in una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Rimuove l'elemento nella posizione indicata in una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Rimuove l'ultimo elemento in una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Rimuove un elemento casuale in una lista."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "da # dalla fine"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "fino a #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "dagli ultimi"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "prendi sotto-lista dall'inizio"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "prendi sotto-lista da # dalla fine"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "prendi sotto-lista da #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Crea una copia della porzione specificata di una lista."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 corrisponde all'ultimo elemento."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 corrisponde al primo elemento."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "trova la prima occorrenza dell'elemento"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "trova l'ultima occorrenza dell'elemento"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Restituisce l'indice della prima/ultima occorrenza dell'elemento nella lista. Restituisce %1 se l'elemento non viene trovato."; -Blockly.Msg.LISTS_INLIST = "nella lista"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 è vuota"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Restituisce vero se la lista è vuota."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "lunghezza di %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Restituisce la lunghezza della lista"; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "crea una lista con l'elemento %1 ripetuto %2 volte"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Crea una lista costituita dal valore indicato ripetuto per il numero di volte specificato."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "come"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "inserisci in"; -Blockly.Msg.LISTS_SET_INDEX_SET = "imposta"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserisci l'elemento all'inizio della lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Inserisci un elemento nella posizione indicata in una lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Aggiungi un elemento alla fine di una lista"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Inserisce l'elemento casualmente in una lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Imposta il primo elemento in una lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Imposta l'elemento nella posizione indicata di una lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Imposta l'ultimo elemento in una lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Imposta un elemento casuale in una lista."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "crescente"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "decrescente"; -Blockly.Msg.LISTS_SORT_TITLE = "ordinamento %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Ordina una copia di un elenco."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alfabetico, ignorare differenze maiuscole e minuscole"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numerico"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alfabetico"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "crea lista da testo"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "crea testo da lista"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Unisci una lista di testi in un unico testo, separato da un delimitatore."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Dividi il testo in un elenco di testi, interrompendo ad ogni delimitatore."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "con delimitatore"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "falso"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Restituisce vero o falso."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "vero"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://it.wikipedia.org/wiki/Disuguaglianza"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Restituisce vero se gli input sono uno uguale all'altro."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Restituisce vero se il primo input è maggiore o uguale al secondo."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Restituisce uguale se il primo input è maggiore o uguale al secondo input."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Restituisce vero se il primo input è minore del secondo."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Restituisce vero se il primo input è minore o uguale al secondo."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Restituisce vero se gli input non sono uno uguale all'altro."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "non %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Restituisce vero se l'input è falso. Restituisce falso se l'input è vero."; -Blockly.Msg.LOGIC_NULL = "nullo"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Restituisce valore nullo."; -Blockly.Msg.LOGIC_OPERATION_AND = "e"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "o"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Restituisce vero se entrambi gli input sono veri."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Restituisce vero se almeno uno degli input è vero."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "se falso"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "se vero"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Verifica la condizione in 'test'. Se questa è vera restituisce il valore 'se vero' altrimenti restituisce il valore 'se falso'."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://it.wikipedia.org/wiki/Aritmetica"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Restituisce la somma dei due numeri."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Restituisce il quoziente dei due numeri."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Restituisce la differenza dei due numeri."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Restituisce il prodotto dei due numeri."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Restituisce il primo numero elevato alla potenza del secondo numero."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://it.wikipedia.org/wiki/Addizione"; -Blockly.Msg.MATH_CHANGE_TITLE = "cambia %1 di %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Aggiunge un numero alla variabile '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://it.wikipedia.org/wiki/Costante_matematica"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Restituisce una delle costanti comuniː π (3.141…), e (2.718…), φ (1.618…), radq(2) (1.414…), radq(½) (0.707…) o ∞ (infinito)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "costringi %1 da %2 a %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Costringe un numero all'interno dei limiti indicati (compresi)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "è divisibile per"; -Blockly.Msg.MATH_IS_EVEN = "è pari"; -Blockly.Msg.MATH_IS_NEGATIVE = "è negativo"; -Blockly.Msg.MATH_IS_ODD = "è dispari"; -Blockly.Msg.MATH_IS_POSITIVE = "è positivo"; -Blockly.Msg.MATH_IS_PRIME = "è primo"; -Blockly.Msg.MATH_IS_TOOLTIP = "Verifica se un numero è pari, dispari, primo, intero, positivo, negativo o se è divisibile per un certo numero. Restituisce vero o falso."; -Blockly.Msg.MATH_IS_WHOLE = "è intero"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://it.wikipedia.org/wiki/Resto"; -Blockly.Msg.MATH_MODULO_TITLE = "resto di %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Restituisce il resto della divisione di due numeri."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://it.wikipedia.org/wiki/Numero"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Un numero."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "media della lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "massimo della lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "mediana della lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "minimo della lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "mode della lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "elemento casuale della lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "deviazione standard della lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "somma la lista"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Restituisce la media (media aritmetica) dei valori numerici nella lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Restituisce il più grande numero della lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Restituisce il valore mediano della lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Restituisce il più piccolo numero della lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Restituisce una lista degli elementi più frequenti nella lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Restituisce un elemento casuale della lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Restituisce la deviazione standard della lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Restituisce la somma si tutti i numeri nella lista."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://it.wikipedia.org/wiki/Numeri_pseudo-casuali"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "frazione casuale"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Restituisce una frazione compresa fra 0.0 (incluso) e 1.0 (escluso)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://it.wikipedia.org/wiki/Numeri_pseudo-casuali"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "intero casuale da %1 a %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Restituisce un numero intero casuale compreso tra i due limiti indicati (inclusi)."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://it.wikipedia.org/wiki/Arrotondamento"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "arrotonda"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "arrotonda verso il basso"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "arrotonda verso l'alto"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Arrotonda un numero verso l'alto o verso il basso."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://it.wikipedia.org/wiki/Radice_quadrata"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "assoluto"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "radice quadrata"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Restituisce il valore assoluto del numero."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Restituisce e elevato alla potenza del numero."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Restituisce il logaritmo naturale del numero."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Restituisce il logaritmo in base 10 del numero."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Restituisce l'opposto del numero."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Restituisce 10 elevato alla potenza del numero."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Restituisce la radice quadrata del numero."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://it.wikipedia.org/wiki/Funzione_trigonometrica"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Restituisce l'arco-coseno di un numero."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Restituisce l'arco-seno di un numero."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Restituisce l'arco-tangente di un numero."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Restituisce il coseno di un angolo espresso in gradi (non radianti)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Restituisce il seno di un angolo espresso in gradi (non radianti)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Restituisce la tangente di un angolo espresso in gradi (non radianti)."; -Blockly.Msg.NEW_VARIABLE = "Crea variabile..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Nome della nuova variabile:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "consenti dichiarazioni"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "conː"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://it.wikipedia.org/wiki/Funzione_(informatica)"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Esegue la funzione definita dall'utente '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://it.wikipedia.org/wiki/Funzione_(informatica)"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Esegue la funzione definita dall'utente '%1' ed usa il suo output."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "conː"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Crea '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Descrivi questa funzione..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "fai qualcosa"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "per"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Crea una funzione senza output."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "ritorna"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Crea una funzione con un output."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Attenzioneː Questa funzione ha parametri duplicati."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Evidenzia definizione di funzione"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Se un valore è vero allora restituisce un secondo valore."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Attenzioneː Questo blocco può essere usato solo all'interno di una definizione di funzione."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "nome inputː"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Aggiungi un input alla funzione."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "input"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Aggiungi, rimuovi o riordina input alla funzione."; -Blockly.Msg.REDO = "Ripeti"; -Blockly.Msg.REMOVE_COMMENT = "Rimuovi commento"; -Blockly.Msg.RENAME_VARIABLE = "Rinomina variabile..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Rinomina tutte le variabili '%1' in:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "aggiungi il testo"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "a"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Aggiunge del testo alla variabile '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "in minuscolo"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "con Iniziali Maiuscole"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "in MAIUSCOLO"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Restituisce una copia del testo in un diverso formato maiuscole/minuscole."; -Blockly.Msg.TEXT_CHARAT_FIRST = "prendi la prima lettera"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "prendi la lettera # dalla fine"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "prendi la lettera #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "nel testo"; -Blockly.Msg.TEXT_CHARAT_LAST = "prendi l'ultima lettera"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "prendi lettera casuale"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Restituisce la lettera nella posizione indicata."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Aggiungi un elemento al testo."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "unisci"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Aggiungi, rimuovi o riordina le sezioni per riconfigurare questo blocco testo."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "alla lettera # dalla fine"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "alla lettera #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "all'ultima lettera"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "nel testo"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "prendi sotto-stringa dalla prima lettera"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "prendi sotto-stringa dalla lettera # dalla fine"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "prendi sotto-stringa dalla lettera #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Restituisce la porzione di testo indicata."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "nel testo"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "trova la prima occorrenza del testo"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "trova l'ultima occorrenza del testo"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Restituisce l'indice della prima occorrenza del primo testo all'interno del secondo testo. Restituisce %1 se il testo non viene trovato."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 è vuoto"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Restituisce vero se il testo fornito è vuoto."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "crea testo con"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Crea un blocco di testo unendo un certo numero di elementi."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "lunghezza di %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Restituisce il numero di lettere (inclusi gli spazi) nel testo fornito."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "scrivi %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Scrive il testo, numero o altro valore indicato."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Richiedi un numero all'utente."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Richiede del testo da parte dell'utente."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "richiedi numero con messaggio"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "richiedi testo con messaggio"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://it.wikipedia.org/wiki/Stringa_(informatica)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Una lettera, una parola o una linea di testo."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "rimuovi spazi da entrambi gli estremi"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "rimuovi spazi a sinistra"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "rimuovi spazi a destra"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Restituisce una copia del testo con gli spazi rimossi ad uno o entrambe le estremità."; -Blockly.Msg.TODAY = "Oggi"; -Blockly.Msg.UNDO = "Annulla"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "elemento"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Crea 'imposta %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Restituisce il valore di una variabile."; -Blockly.Msg.VARIABLES_SET = "imposta %1 a %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Crea 'prendi %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Imposta questa variabile ad essere pari all'input."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "Una variabile denominata '%1' esiste già."; -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/ja.js b/backend/_pv_1_3_5/static/blockly/msg/js/ja.js deleted file mode 100755 index ad00d3f3b..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/ja.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.ja'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "コメントを追加"; -Blockly.Msg.CHANGE_VALUE_TITLE = "値を変更します。"; -Blockly.Msg.CLEAN_UP = "ブロックの整理"; -Blockly.Msg.COLLAPSE_ALL = "ブロックを折りたたむ"; -Blockly.Msg.COLLAPSE_BLOCK = "ブロックを折りたたむ"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "色 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "色 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "割合"; -Blockly.Msg.COLOUR_BLEND_TITLE = "ブレンド"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "ブレンド2 つの色を指定された比率に混ぜる」 (0.0 ~ 1.0)。"; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://ja.wikipedia.org/wiki/色"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "パレットから色を選んでください。"; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "ランダムな色"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "ランダムな色を選択します。"; -Blockly.Msg.COLOUR_RGB_BLUE = "青"; -Blockly.Msg.COLOUR_RGB_GREEN = "緑"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "赤"; -Blockly.Msg.COLOUR_RGB_TITLE = "カラーと"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "赤、緑、および青の指定された量で色を作成します。すべての値は 0 ~ 100 の間でなければなりません。"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "ループから抜け出す"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "ループの次の反復処理を続行します。"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "含むループから抜け出します。"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "このループの残りの部分をスキップし、次のイテレーションに進みます。"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "注意: このブロックは、ループ内でのみ使用します。"; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "各項目の %1 リストで %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "リストの各項目に対して変数 '%1' のアイテムに設定し、いくつかのステートメントをしてください。"; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "で、カウントします。 %1 %2 から%3、 %4 で"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "変数 \"%1\"は、指定した間隔ごとのカウントを開始番号から 終了番号まで、値をとり、指定したブロックを行う必要があります。"; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "場合に条件にブロック追加。"; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Ifブロックに、すべてをキャッチする条件を追加。"; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "追加、削除、またはセクションを順序変更して、ブロックをこれを再構成します。"; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "他"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "他でもし"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "もし"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "値が true の場合はその後ステートメントを行をいくつかします。"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "値が true 場合は、ステートメントの最初のブロックを行います。それ以外の場合は、ステートメントの 2 番目のブロックを行います。"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "最初の値が true 場合は、ステートメントの最初のブロックを行います。それ以外の場合は、2 番目の値が true の場合、ステートメントの 2 番目のブロックをします。"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "最初の値が true 場合は、ステートメントの最初のブロックを行います。2 番目の値が true の場合は、ステートメントの 2 番目のブロックを行います。それ以外の場合は最後のブロックのステートメントを行います。"; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://ja.wikipedia.org/wiki/for文"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "してください"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "%1 回、繰り返します"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "いくつかのステートメントを数回行います。"; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "までを繰り返します"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "つつその間、繰り返す4"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "値は false のあいだ、いくつかのステートメントを行います。"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "値は true のあいだ、いくつかのステートメントを行います。"; -Blockly.Msg.DELETE_ALL_BLOCKS = "%1件のすべてのブロックを消しますか?"; -Blockly.Msg.DELETE_BLOCK = "ブロックを消す"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "%1 個のブロックを消す"; -Blockly.Msg.DISABLE_BLOCK = "ブロックを無効にします。"; -Blockly.Msg.DUPLICATE_BLOCK = "複製"; -Blockly.Msg.ENABLE_BLOCK = "ブロックを有効にします。"; -Blockly.Msg.EXPAND_ALL = "ブロックを展開します。"; -Blockly.Msg.EXPAND_BLOCK = "ブロックを展開します。"; -Blockly.Msg.EXTERNAL_INPUTS = "外部入力"; -Blockly.Msg.HELP = "ヘルプ"; -Blockly.Msg.INLINE_INPUTS = "インライン入力"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "空のリストを作成します。"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "長さゼロ、データ レコード空のリストを返します"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "リスト"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "追加、削除、またはセクションを順序変更して、ブロックを再構成します。"; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "これを使ってリストを作成します。"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "リストにアイテムを追加します。"; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "アイテム数かぎりないのリストを作成します。"; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "最初"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "終しまいから #"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "取得"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "取得と削除"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "最後"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "ランダム"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "削除"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "リストの最初の項目を返信します。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "リスト内の指定位置にある項目を返します。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "リストの最後の項目を返します。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "ランダム アイテム リストを返します。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "リスト内の最初の項目を削除したあと返します。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "リスト内の指定位置にある項目を削除し、返します。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "リスト内の最後の項目を削除したあと返します。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "リストのランダムなアイテムを削除し、返します。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "リスト内の最初の項目を削除します。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "リスト内の指定位置にある項目を返します。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "リスト内の最後の項目を削除します。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "リスト内にある任意のアイテムを削除します。"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "最後から#へ"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "#へ"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "最後へ"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "最初からサブリストを取得する。"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "端から #のサブリストを取得します。"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "# からサブディレクトリのリストを取得します。"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "リストの指定された部分のコピーを作成してくださ。"; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 は、最後の項目です。"; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 は、最初の項目です。"; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "最初に見つかった項目を検索します。"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "最後に見つかったアイテムを見つける"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "リスト項目の最初/最後に出現するインデックス位置を返します。項目が見つからない場合は %1 を返します。"; -Blockly.Msg.LISTS_INLIST = "リストで"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 が空"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "リストが空の場合は、true を返します。"; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = " %1の長さ"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "リストの長さを返します。"; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "アイテム %1 と一緒にリストを作成し %2 回繰り"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "指定された値をなんどか繰り返してリストを作ります。"; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "として"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "挿入します。"; -Blockly.Msg.LISTS_SET_INDEX_SET = "セット"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "リストの先頭に項目を挿入します。"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "リスト内の指定位置に項目を挿入します。"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "リストの末尾に項目を追加します。"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "リストに項目をランダムに挿入します。"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "リスト内に最初の項目を設定します。"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "リスト内の指定された位置に項目を設定します。"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "リスト内の最後の項目を設定します。"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "リスト内にランダムなアイテムを設定します。"; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "昇順"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "降順"; -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "テキストからリストを作る"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "リストからテキストを作る"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "false"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "True または false を返します。"; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "true"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://ja.wikipedia.org/wiki/不等式"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "もし両方がお互いに等しく入力した場合は true を返します。"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "最初の入力が 2 番目の入力よりも大きい場合は true を返します。"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "もし入力がふたつめの入よりも大きかったらtrueをり返します。"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "最初の入力が 2 番目の入力よりも小さいい場合は true を返します。"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "もし、最初の入力が二つ目入力より少ないか、おなじであったらTRUEをかえしてください"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "両方の入力が互いに等しくない場合に true を返します。"; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://ja.wikipedia.org/wiki/否定"; -Blockly.Msg.LOGIC_NEGATE_TITLE = "%1 ではないです。"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "入力が false の場合は、true を返します。入力が true の場合は false を返します。"; -Blockly.Msg.LOGIC_NULL = "null"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Null を返します。"; -Blockly.Msg.LOGIC_OPERATION_AND = "そして"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "または"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "両方の入力がおんなじ場わいわtrue を返します。"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "最低少なくとも 1 つの入力が true の場合は true を返します。"; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "テスト"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://ja.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "false の場合"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "true の場合"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "'テスト' の条件をチェックします。条件が true の場合、'true' の値を返します。それ以外の場合 'false' のを返します。"; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://ja.wikipedia.org/wiki/算術"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "2 つの数の合計を返します。"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "2 つの数の商を返します。"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "2 つの数の差を返します。"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "2 つの数の積を返します。"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "最初の数を2 番目の値で累乗した結果を返します。"; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://ja.wikipedia.org/wiki/加法"; -Blockly.Msg.MATH_CHANGE_TITLE = "変更 %1 に %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "'%1' をたします。"; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://ja.wikipedia.org/wiki/数学定数"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "いずれかの共通の定数のを返す: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (無限)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "制限%1下リミット%2上限リミット%3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "値を、上限 x と下限 y のあいだに制限んする(上限と下限が、x と y とに同じ場合わ、上限の値は x, 下限の値はy)。"; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "割り切れる"; -Blockly.Msg.MATH_IS_EVEN = "わ偶数"; -Blockly.Msg.MATH_IS_NEGATIVE = "負の値"; -Blockly.Msg.MATH_IS_ODD = "奇数です。"; -Blockly.Msg.MATH_IS_POSITIVE = "正の値"; -Blockly.Msg.MATH_IS_PRIME = "素数です"; -Blockly.Msg.MATH_IS_TOOLTIP = "数字が、偶数、奇数、素数、整数、正数、負数、またはそれが特定の数で割り切れる場合かどうかを確認してください。どの制限が一つでも本当でしたら true をかえしてください、そうでない場合わ falseを返してください。"; -Blockly.Msg.MATH_IS_WHOLE = "は整数"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "残りの %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "2つの数値を除算した余りを返します。"; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://ja.wikipedia.org/wiki/数"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "数です。"; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "リストの平均"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "リストの最大値"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "リストの中央値"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "リストの最小の数"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "一覧モード"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "リストのランダム アイテム"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "リストの標準偏差"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "リストの合計"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "リストの数値の平均 (算術平均) を返します。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "リストの最大数を返します。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "リストの中央値の数を返します。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "リストの最小数を返します。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "リストで最も一般的な項目のリストを返します。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "リストからランダムに要素を返します。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "リウトの標準偏差をかえす"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "全部リストの数をたして返す"; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "ランダムな分数"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "ランダムな分数を返すー0.0 (包括) の間のと 1.0 (排他的な)。"; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "%1 から %2 への無作為の整数"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "指定した下限の間、無作為なランダムな整数を返します。"; -Blockly.Msg.MATH_ROUND_HELPURL = "https://ja.wikipedia.org/wiki/端数処理"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "概数"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "端数を切り捨てる"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "数値を切り上げ"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "数値を切り上げるか切り捨てる"; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://ja.wikipedia.org/wiki/平方根"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "絶対値"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "平方根"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "絶対値を返す"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "数値の e 粂を返す"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "数値の自然対数をかえしてください"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "log 10 を返す。"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "負の数を返す"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "10の x 乗"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "平方根を返す"; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "acos"; -Blockly.Msg.MATH_TRIG_ASIN = "asin"; -Blockly.Msg.MATH_TRIG_ATAN = "atan"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://ja.wikipedia.org/wiki/三角関数"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tan"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "arccosine の値を返す"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "番号のarcsine を返すます"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "番号のarctangent を返すます"; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "番号のcosineの次数を返す"; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "番号のsineの次数を返す"; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "番号のtangentの次数を返す"; -Blockly.Msg.NEW_VARIABLE = "新しい変数"; -Blockly.Msg.NEW_VARIABLE_TITLE = "新しい変数の、名前"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "allow statements"; // untranslated -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "で。"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://ja.wikipedia.org/wiki/サブルーチン"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "ユーザー定義関数 '%1' を実行します。"; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://ja.wikipedia.org/wiki/サブルーチン"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "ユーザー定義関数 '%1' を実行し、その出力を使用します。"; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "で。"; -Blockly.Msg.PROCEDURES_CREATE_DO = "%1をつくる"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://ja.wikipedia.org/wiki/サブルーチン"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "何かしてください"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "宛先"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "出力なしで関数を作成します。"; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://ja.wikipedia.org/wiki/サブルーチン"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "返す"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "出力を持つ関数を作成します。"; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "警告: この関数は、重複するパラメーターがあります。"; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "関数の内容を強調表示します。"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "1番目値が true の場合、2 番目の値を返します。"; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "警告: このブロックは、関数定義内でのみ使用できます。"; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "入力名:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Add an input to the function."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "入力"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Add, remove, or reorder inputs to this function."; // untranslated -Blockly.Msg.REDO = "やり直し"; -Blockly.Msg.REMOVE_COMMENT = "コメントを削除"; -Blockly.Msg.RENAME_VARIABLE = "変数の名前を変更."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "%1の変数すべてを名前変更します。"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "テキストを追加します。"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "宛先"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "変数 '%1' にいくつかのテキストを追加します。"; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "小文字に"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "タイトル ケースに"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "大文字に変換する"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "別のケースに、テキストのコピーを返します。"; -Blockly.Msg.TEXT_CHARAT_FIRST = "最初の文字を得る"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "一番最後の言葉、キャラクターを所得"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "文字# を取得"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "テキストで"; -Blockly.Msg.TEXT_CHARAT_LAST = "最後の文字を得る"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "ランダムな文字を得る"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "指定された位置に文字を返します。"; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "テキスト をアイテム追加します。"; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "結合"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "追加、削除、またはセクションを順序変更して、ブロックを再構成します。"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "文字列の# 終わりからの#"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "# の文字"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "最後のの文字"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "テキストで"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "部分文字列を取得する。"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "部分文字列を取得する #端から得る"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "文字列からの部分文字列を取得 #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "テキストの指定部分を返します。"; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "テキストで"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "テキストの最初の出現箇所を検索します。"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "テキストの最後に見つかったを検索します。"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "最初のテキストの二番目のてきすとの、最初と最後の、出現したインデックスをかえします。テキストが見つからない場合は %1 を返します。"; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 が空"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "指定されたテキストが空の場合は、true を返します。"; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "テキストを作成します。"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "任意の数の項目一部を一緒に接合してテキストの作成します。"; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "%1 の長さ"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "指定されたテキストの文字 (スペースを含む) の数を返します。"; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "%1 を印刷します。"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "指定したテキスト、番号または他の値を印刷します。"; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "ユーザーにプロンプトして数字のインプットを求めます"; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "いくつかのテキストを、ユーザーに入力するようにプロンプト。"; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "メッセージを送って番号の入力を求める"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "メッセージをプロンプトしてにテキストを求める"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://ja.wikipedia.org/wiki/文字列"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "文字、単語、または行のテキスト。"; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "両端のスペースを取り除く"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "左端のスペースを取り除く"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "右端のスペースを取り除く"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "スペースを 1 つまたは両方の端から削除したのち、テキストのコピーを返します。"; -Blockly.Msg.TODAY = "今日"; -Blockly.Msg.UNDO = "取り消し"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "項目"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "'セット%1を作成します。"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "この変数の値を返します。"; -Blockly.Msg.VARIABLES_SET = "セット %1 宛先 %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "'%1 を取得' を作成します。"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "この入力を変数と等しくなるように設定します。"; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/ko.js b/backend/_pv_1_3_5/static/blockly/msg/js/ko.js deleted file mode 100755 index 2e601b823..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/ko.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.ko'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "댓글 추가"; -Blockly.Msg.CHANGE_VALUE_TITLE = "값 바꾸기:"; -Blockly.Msg.CLEAN_UP = "블록 정리"; -Blockly.Msg.COLLAPSE_ALL = "블록 축소"; -Blockly.Msg.COLLAPSE_BLOCK = "블록 축소"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "색 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "색 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "비율"; -Blockly.Msg.COLOUR_BLEND_TITLE = "혼합"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "두 색을 주어진 비율로 혼합 (0.0 - 1.0)"; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://ko.wikipedia.org/wiki/색"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "팔레트에서 색을 고릅니다"; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "임의 색상"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "무작위로 색을 고릅니다."; -Blockly.Msg.COLOUR_RGB_BLUE = "파랑"; -Blockly.Msg.COLOUR_RGB_GREEN = "초록"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "빨강"; -Blockly.Msg.COLOUR_RGB_TITLE = "색"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "빨강,파랑,초록의 값을 이용하여 색을 만드십시오. 모든 값은 0과 100 사이에 있어야 합니다."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://ko.wikipedia.org/wiki/%EC%A0%9C%EC%96%B4_%ED%9D%90%EB%A6%84"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "반복 중단"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "다음 반복"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "현재 반복 실행 블럭을 빠져나갑니다."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "나머지 반복 부분을 더 이상 실행하지 않고, 다음 반복을 수행합니다."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "경고 : 이 블록은 반복 실행 블럭 안에서만 사용됩니다."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://ko.wikipedia.org/wiki/For_%EB%A3%A8%ED%94%84#.EC.9E.84.EC.9D.98.EC.9D.98_.EC.A7.91.ED.95.A9"; -Blockly.Msg.CONTROLS_FOREACH_TITLE = "각 항목에 대해 %1 목록으로 %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "리스트 안에 들어있는 각 아이템들을, 순서대로 변수 '%1' 에 한 번씩 저장시키고, 그 때 마다 명령을 실행합니다."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://ko.wikipedia.org/wiki/For_%EB%A3%A8%ED%94%84"; -Blockly.Msg.CONTROLS_FOR_TITLE = "으로 계산 %1 %2에서 %4을 이용하여 %3로"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "변수 \"%1\"은 지정된 간격으로 시작 수에서 끝 수까지를 세어 지정된 블록을 수행해야 합니다."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "\"만약\" 블럭에 조건 검사를 추가합니다."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "\"만약\" 블럭의 마지막에, 모든 검사 결과가 거짓인 경우 실행할 부분을 추가합니다."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://ko.wikipedia.org/wiki/%EC%A1%B0%EA%B1%B4%EB%AC%B8"; -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "섹션을 추가, 제거하거나 순서를 변경하여 이 if 블럭을 재구성합니다."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "아니라면"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "다른 경우"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "만약"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "조건식의 계산 결과가 참이면, 명령을 실행합니다."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "조건식의 계산 결과가 참이면, 첫 번째 블럭의 명령을 실행하고, 그렇지 않으면 두 번째 블럭의 명령을 실행합니다."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "첫 번째 조건식의 계산 결과가 참이면, 첫 번째 블럭의 명령을 실행하고, 두 번째 조건식의 계산 결과가 참이면, 두 번째 블럭의 명령을 실행합니다."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "첫 번째 조건식의 계산 결과가 참이면, 첫 번째 블럭의 명령을 실행하고, 두 번째 조건식의 계산 결과가 참이면, 두 번째 블럭의 명령을 실행하고, ... , 어떤 조건식의 계산 결과도 참이 아니면, 마지막 블럭의 명령을 실행합니다."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://ko.wikipedia.org/wiki/For_루프"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "하기"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "%1회 반복"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "여러 번 반복해 명령들을 실행합니다."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://ko.wikipedia.org/wiki/While_%EB%A3%A8%ED%94%84"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "다음까지 반복"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "동안 반복"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "값이 거짓일 때, 몇 가지 선언을 합니다."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "값이 참일 때, 몇 가지 선언을 합니다."; -Blockly.Msg.DELETE_ALL_BLOCKS = "모든 블록 %1개를 삭제하겠습니까?"; -Blockly.Msg.DELETE_BLOCK = "블록 삭제"; -Blockly.Msg.DELETE_VARIABLE = "'%1' 변수를 삭제합니다"; -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "블록 %1개 삭제"; -Blockly.Msg.DISABLE_BLOCK = "블록 비활성화"; -Blockly.Msg.DUPLICATE_BLOCK = "중복됨"; -Blockly.Msg.ENABLE_BLOCK = "블록 활성화"; -Blockly.Msg.EXPAND_ALL = "블록 확장"; -Blockly.Msg.EXPAND_BLOCK = "블록 확장"; -Blockly.Msg.EXTERNAL_INPUTS = "외부 입력"; -Blockly.Msg.HELP = "도움말"; -Blockly.Msg.INLINE_INPUTS = "내부 입력"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "빈 리스트 생성"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "데이터 레코드가 없는, 길이가 0인 목록을 반환합니다."; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "리스트"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "섹션을 추가, 제거하거나 순서를 변경하여 이 리스트 블럭을 재구성합니다."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "리스트 만들기"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "아이템을 리스트에 추가합니다."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "원하는 수의 항목들로 목록을 생성합니다."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "첫 번째"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "마지막 번째 위치부터, # 번째"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "가져오기"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "잘라 내기"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "마지막"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "임의로"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "삭제"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "첫 번째 아이템을 찾아 돌려줍니다."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "목록에서 특정 위치의 항목을 반환합니다."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "마지막 아이템을 찾아 돌려줍니다."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "리스트의 아이템들 중, 랜덤으로 선택해 돌려줍니다."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "첫 번째 아이템을 찾아내 돌려주고, 그 아이템을 리스트에서 삭제합니다."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "목록의 특정 위치에 있는 항목을 제거하고 반환합니다."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "마지막 아이템을 찾아내 돌려주고, 그 아이템을 리스트에서 삭제합니다."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "목록에서 임의 위치의 아이템을 찾아내 삭제하고 돌려줍니다."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "리스트에서 첫 번째 아이템을 삭제합니다."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "목록에서 특정 위치의 항목을 삭제합니다."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "리스트에서 마지막 아이템을 찾아 삭제합니다."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "리스트에서 랜덤하게 아이템을 삭제합니다."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "끝에서부터 # 번째로"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "앞에서부터 # 번째로"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "마지막으로"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "첫 번째 위치부터, 서브 리스트 추출"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "마지막부터 # 번째 위치부터, 서브 리스트 추출"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "처음 # 번째 위치부터, 서브 리스트 추출"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "목록의 특정 부분에 대한 복사본을 만듭니다."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1은(는) 마지막 항목입니다."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1은 첫 번째 항목입니다."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "처음으로 나타난 위치"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; -Blockly.Msg.LISTS_INDEX_OF_LAST = "마지막으로 나타난 위치"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "목록에서 항목이 처음 또는 마지막으로 발생한 색인 위치를 반환합니다. 항목이 없으면 %1을 반환합니다."; -Blockly.Msg.LISTS_INLIST = "리스트"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1이 비어 있습니다"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "목록이 비었을 때 참을 반환합니다."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; -Blockly.Msg.LISTS_LENGTH_TITLE = "%1의 길이"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "목록의 길이를 반환합니다."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg.LISTS_REPEAT_TITLE = "%1을 %2번 넣어, 리스트 생성"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "원하는 값을, 원하는 갯수 만큼 넣어, 목록을 생성합니다."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "에"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "에서 원하는 위치에 삽입"; -Blockly.Msg.LISTS_SET_INDEX_SET = "에서 설정"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "항목을 목록의 처음 위치에 삽입합니다."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "목록의 특정 위치에 항목을 삽입합니다."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "리스트의 마지막에 아이템을 추가합니다."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "목록에서 임의 위치에 아이템을 삽입합니다."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "첫 번째 위치의 아이템으로 설정합니다."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "목록의 특정 위치에 있는 항목으로 설정합니다."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "마지막 아이템으로 설정합니다."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "목록에서 임의 위치의 아이템을 설정합니다."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "오름차순"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "내림차순"; -Blockly.Msg.LISTS_SORT_TITLE = "정렬 %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "목록의 사본을 정렬합니다."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "알파벳순 (대소문자 구분 안 함)"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "숫자순"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "알파벳순"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "텍스트에서 목록 만들기"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "목록에서 텍스트 만들기"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "구분 기호로 구분하여 텍스트 목록을 하나의 텍스트에 병합합니다."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "각 속보, 텍스트의 목록들에서 텍스트를 분할합니다."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "분리와"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "거짓"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://ko.wikipedia.org/wiki/%EC%A7%84%EB%A6%BF%EA%B0%92"; -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "참 혹은 거짓 모두 반환합니다."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "참"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "두 값이 같으면, 참(true) 값을 돌려줍니다."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "첫 번째 값이 두 번째 값보다 크면, 참(true) 값을 돌려줍니다."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "첫 번째 값이 두 번째 값보다 크거나 같으면, 참(true) 값을 돌려줍니다."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "첫 번째 값이 두 번째 값보다 작으면, 참(true) 값을 돌려줍니다."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "첫 번째 값이 두 번째 값보다 작거나 같으면, 참(true) 값을 돌려줍니다."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "두 값이 서로 다르면, 참(true) 값을 돌려줍니다."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://ko.wikipedia.org/wiki/%EB%B6%80%EC%A0%95"; -Blockly.Msg.LOGIC_NEGATE_TITLE = "%1가 아닙니다"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "입력값이 거짓이라면 참을 반환합니다. 참이라면 거짓을 반환합니다."; -Blockly.Msg.LOGIC_NULL = "빈 값"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "빈 값을 반환합니다."; -Blockly.Msg.LOGIC_OPERATION_AND = "그리고"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://ko.wikipedia.org/wiki/%EB%B6%88_%EB%85%BC%EB%A6%AC"; -Blockly.Msg.LOGIC_OPERATION_OR = "또는"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "두 값이 모두 참(true) 값이면, 참 값을 돌려줍니다."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "적어도 하나의 값이 참일 경우 참을 반환합니다."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "테스트"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "만약 거짓이라면"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "만약 참이라면"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "'test'의 조건을 검사합니다. 조건이 참이면 'if true' 값을 반환합니다. 거짓이면 'if false' 값을 반환합니다."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Arithmetic"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "두 수의 합을 반환합니다."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "두 수의 나눈 결과를 반환합니다."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "두 수간의 차이를 반환합니다."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "두 수의 곱을 반환합니다."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "첫 번째 수를 두 번째 수 만큼, 거듭제곱 한 결과값을 돌려줍니다."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "바꾸기 %1 만큼 %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "변수 '%1' 에 저장되어있는 값에, 어떤 수를 더해, 변수에 다시 저장합니다."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "일반적인 상수 값들 중 하나를 돌려줍니다. : π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://ko.wikipedia.org/wiki/%ED%81%B4%EB%9E%A8%ED%95%91_(%EA%B7%B8%EB%9E%98%ED%94%BD)"; -Blockly.Msg.MATH_CONSTRAIN_TITLE = "%1의 값을, 최소 %2 최대 %3으로 조정"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "어떤 수를, 특정 범위의 값이 되도록 강제로 조정합니다."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "가 다음 수로 나누어 떨어지면 :"; -Blockly.Msg.MATH_IS_EVEN = "가 짝수(even) 이면"; -Blockly.Msg.MATH_IS_NEGATIVE = "가 음(-)수 이면"; -Blockly.Msg.MATH_IS_ODD = "가 홀수(odd) 이면"; -Blockly.Msg.MATH_IS_POSITIVE = "가 양(+)수 이면"; -Blockly.Msg.MATH_IS_PRIME = "가 소수(prime) 이면"; -Blockly.Msg.MATH_IS_TOOLTIP = "어떤 수가 짝 수, 홀 수, 소 수, 정 수, 양 수, 음 수, 나누어 떨어지는 수 인지 검사해 결과값을 돌려줍니다. 참(true) 또는 거짓(false) 값을 돌려줌."; -Blockly.Msg.MATH_IS_WHOLE = "가 정수이면"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "%1 ÷ %2의 나머지"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "첫 번째 수를 두 번째 수로 나눈, 나머지 값을 돌려줍니다."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "x"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "수"; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "평균값"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "최대값"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "중간값"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "최소값"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "가장 여러 개 있는 값"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "목록의 임의 항목"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "표준 편차"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "합"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "리스트에 들어있는 수(값)들에 대해, 산술 평균(arithmetic mean) 한 값을 돌려줍니다."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "리스트에 들어있는 수(값) 들 중, 가장 큰(max) 수(값)를 돌려줍니다."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "리스트에 들어있는 수(값) 들 중, 중간(median) 수(값)를 돌려줍니다."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "리스트에 들어있는 수(값) 들 중, 가장 작은(min) 수(값)를 돌려줍니다."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "리스트에 들어있는 아이템들 중에서, 가장 여러 번 들어있는 아이템들을 리스트로 만들어 돌려줍니다. (최빈값, modes)"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "목록에서 임의의 아이템을 돌려줍니다."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "이 리스트의 표준 편차를 반환합니다."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "리스트에 들어있는 수(값)들을, 모두 합(sum) 한, 총합(sum)을 돌려줍니다."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "임의 분수"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "0.0 (포함)과 1.0 (배타적) 사이의 임의 분수 값을 돌려줍니다."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "랜덤정수(%1<= n <=%2)"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "두 주어진 제한된 범위 사이의 임의 정수값을 돌려줍니다."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "반올림"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "버림"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "올림"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "어떤 수를 반올림/올림/버림한 결과를, 정수값으로 돌려줍니다."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "절대값"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "제곱근"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "어떤 수의 절대값(absolute)을 계산한 결과를, 정수값으로 돌려줍니다."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "e의 거듭제곱 값을 반환합니다."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "어떤 수의, 자연로그(natural logarithm) 값을 돌려줍니다.(밑 e, 예시 log e x)"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "어떤 수의, 기본로그(logarithm) 값을 돌려줍니다.(밑 10, 예시 log 10 x)"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "음(-)/양(+), 부호를 반대로 하여 값을 돌려줍니다."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "10의 거듭제곱 값을 반환합니다."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "숫자의 제곱근을 반환합니다."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "acos"; -Blockly.Msg.MATH_TRIG_ASIN = "asin"; -Blockly.Msg.MATH_TRIG_ATAN = "atan"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tan"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "어떤 수에 대한, acos(arccosine) 값을 돌려줍니다."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "어떤 수에 대한, asin(arcsine) 값을 돌려줍니다."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "어떤 수에 대한, atan(arctangent) 값을 돌려줍니다."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "각도의 코사인을 반환합니다. (라디안 아님)"; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "각도의 사인을 반환합니다. (라디안 아님)"; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "각도의 탄젠트를 반환합니다. (라디안 아님)"; -Blockly.Msg.NEW_VARIABLE = "변수 만들기..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "새 변수 이름:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "서술 허가"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "사용:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "미리 정의해 둔 '%1' 함수를 실행합니다."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "미리 정의해 둔 '%1' 함수를 실행하고, 함수를 실행한 결과 값을 돌려줍니다."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "사용:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "'%1' 생성"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "이 함수를 설명하세요..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://ko.wikipedia.org/wiki/%ED%95%A8%EC%88%98_%28%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%29"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "함수 이름"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "함수"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "실행 후, 결과 값을 돌려주지 않는 함수를 만듭니다."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://ko.wikipedia.org/wiki/%ED%95%A8%EC%88%98_%28%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%29"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "다음을 돌려줌"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "실행 후, 결과 값을 돌려주는 함수를 만듭니다."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "경고: 이 함수에는, 같은 이름을 사용하는 매개 변수들이 있습니다."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "함수 정의 찾기"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "값이 참이라면, 두 번째 값을 반환합니다."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "경고: 이 블럭은, 함수 정의 블럭 안에서만 사용할 수 있습니다."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "매개 변수:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "함수에 값을 더합니다."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "매개 변수들"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "이 함수를 추가, 삭제, 혹은 재정렬합니다."; -Blockly.Msg.REDO = "다시 실행"; -Blockly.Msg.REMOVE_COMMENT = "내용 제거"; -Blockly.Msg.RENAME_VARIABLE = "변수 이름 바꾸기:"; -Blockly.Msg.RENAME_VARIABLE_TITLE = "'%1' 변수 이름을 바꾸기:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "내용 덧붙이기"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; -Blockly.Msg.TEXT_APPEND_TO = "다음"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "'%1' 변수의 끝에 일부 텍스트를 덧붙입니다."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "소문자로"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "첫 문자만 대문자로"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "대문자로"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "영문 대소문자 형태를 변경해 돌려줍니다."; -Blockly.Msg.TEXT_CHARAT_FIRST = "에서, 첫 번째 문자 얻기"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "에서, 마지막부터 # 번째 위치의 문자 얻기"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "에서, 앞에서부터 # 번째 위치의 문자 얻기"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "문장"; -Blockly.Msg.TEXT_CHARAT_LAST = "에서, 마지막 문자 얻기"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "에서, 랜덤하게 한 문자 얻기"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "특정 번째 위치에서, 문자를 얻어내 돌려줍니다."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "텍스트에 항목을 추가합니다."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "가입"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "섹션을 추가, 제거하거나 순서를 변경하여 이 텍스트 블럭을 재구성합니다."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "끝에서부터 # 번째 문자까지"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "# 번째 문자까지"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "마지막 문자까지"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "문장"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "에서, 처음부터 얻어냄"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "에서, 마지막에서 # 번째부터 얻어냄"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "에서, 처음부터 # 번째 문자부터 얻어냄"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "문장 중 일부를 얻어내 돌려줍니다."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "문장"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "에서 다음 문장이 처음으로 나타난 위치 찾기 :"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "에서 다음 문장이 마지막으로 나타난 위치 찾기 :"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "두 번째 텍스트에서 첫 번째 텍스트가 처음 또는 마지막으로 발생한 색인 위치를 반환합니다. 텍스트가 없으면 %1을 반환합니다."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1이 비어 있습니다"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "입력된 문장이, 빈 문장(\"\")이면 참(true) 값을 돌려줍니다."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "텍스트 만들기"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "여러 개의 아이템들을 연결해(묶어), 새로운 문장을 만듭니다."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; -Blockly.Msg.TEXT_LENGTH_TITLE = "다음 문장의 문자 개수 %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "입력된 문장의, 문자 개수를 돌려줍니다.(공백문자 포함)"; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; -Blockly.Msg.TEXT_PRINT_TITLE = "다음 내용 출력 %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "원하는 문장, 수, 값 등을 출력합니다."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "수에 대해 사용자의 입력을 받습니다."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "문장에 대해 사용자의 입력을 받습니다."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "메시지를 활용해 수 입력"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "메시지를 활용해 문장 입력"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "문자, 단어, 문장."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "양쪽의 공백 문자 제거"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "왼쪽의 공백 문자 제거"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "오른쪽의 공백 문자 제거"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "문장의 왼쪽/오른쪽/양쪽에서 스페이스 문자를 제거해 돌려줍니다."; -Blockly.Msg.TODAY = "오늘"; -Blockly.Msg.UNDO = "실행 취소"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "항목"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "'집합 %1' 생성"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://ko.wikipedia.org/wiki/%EB%B3%80%EC%88%98_(%EC%BB%B4%ED%93%A8%ED%84%B0_%EA%B3%BC%ED%95%99)"; -Blockly.Msg.VARIABLES_GET_TOOLTIP = "변수에 저장 되어있는 값을 돌려줍니다."; -Blockly.Msg.VARIABLES_SET = "%1를 %2로 설정"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "'%1 값 읽기' 블럭 생성"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://ko.wikipedia.org/wiki/%EB%B3%80%EC%88%98_(%EC%BB%B4%ED%93%A8%ED%84%B0_%EA%B3%BC%ED%95%99)"; -Blockly.Msg.VARIABLES_SET_TOOLTIP = "변수의 값을 입력한 값으로 변경해 줍니다."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "'%1' 변수는 이미 존재합니다."; -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/lb.js b/backend/_pv_1_3_5/static/blockly/msg/js/lb.js deleted file mode 100755 index 57ad27307..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/lb.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.lb'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Bemierkung derbäisetzen"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Wäert änneren:"; -Blockly.Msg.CLEAN_UP = "Bléck opraumen"; -Blockly.Msg.COLLAPSE_ALL = "Bléck zesummeklappen"; -Blockly.Msg.COLLAPSE_BLOCK = "Block zesummeklappen"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "Faarf 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "Faarf 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "ratio"; -Blockly.Msg.COLOUR_BLEND_TITLE = "mëschen"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Blends two colours together with a given ratio (0.0 - 1.0)."; // untranslated -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Color"; // untranslated -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Sicht eng Faarf an der Palette eraus."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "zoufälleg Faarf"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Eng zoufälleg Faarf eraussichen."; -Blockly.Msg.COLOUR_RGB_BLUE = "blo"; -Blockly.Msg.COLOUR_RGB_GREEN = "gréng"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "rout"; -Blockly.Msg.COLOUR_RGB_TITLE = "fierwe mat"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Create a colour with the specified amount of red, green, and blue. All values must be between 0 and 100."; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "break out of loop"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "continue with next iteration of loop"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Break out of the containing loop."; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Skip the rest of this loop, and continue with the next iteration."; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Warning: This block may only be used within a loop."; // untranslated -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "fir all Element %1 an der Lëscht %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "For each item in a list, set the variable '%1' to the item, and then do some statements."; // untranslated -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "zielt mat %1 vun %2 bis %3 mat %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Have the variable '%1' take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks."; // untranslated -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Add a condition to the if block."; // untranslated -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Add a final, catch-all condition to the if block."; // untranslated -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Add, remove, or reorder sections to reconfigure this if block."; // untranslated -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "soss"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "else if"; // untranslated -Blockly.Msg.CONTROLS_IF_MSG_IF = "wann"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "If a value is true, then do some statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "If a value is true, then do the first block of statements. Otherwise, do the second block of statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements."; // untranslated -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; // untranslated -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "maach"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "%1-mol widderhuelen"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Do some statements several times."; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "widderhuele bis"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "Widderhuel soulaang"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Féiert d'Uweisungen aus, soulaang wéi de Wäert falsch ass."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Féiert d'Uweisungen aus, soulaang wéi de Wäert richteg ass"; -Blockly.Msg.DELETE_ALL_BLOCKS = "Delete all %1 blocks?"; // untranslated -Blockly.Msg.DELETE_BLOCK = "Block läschen"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "%1 Bléck läschen"; -Blockly.Msg.DISABLE_BLOCK = "Block desaktivéieren"; -Blockly.Msg.DUPLICATE_BLOCK = "Eng Kopie maachen"; -Blockly.Msg.ENABLE_BLOCK = "Block aktivéieren"; -Blockly.Msg.EXPAND_ALL = "Bléck opklappen"; -Blockly.Msg.EXPAND_BLOCK = "Block opklappen"; -Blockly.Msg.EXTERNAL_INPUTS = "External Inputs"; // untranslated -Blockly.Msg.HELP = "Hëllef"; -Blockly.Msg.INLINE_INPUTS = "Inline Inputs"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "create empty list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Returns a list, of length 0, containing no data records"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "Lëscht"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Add, remove, or reorder sections to reconfigure this list block."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "create list with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "En Element op d'Lëscht derbäisetzen."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Create a list with any number of items."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_FIRST = "éischt"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# vun hannen"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "get"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "get and remove"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_LAST = "lescht"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "Zoufall"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "ewechhuelen"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Schéckt en zoufällegt Element aus enger Lëscht zréck."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Removes and returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Removes and returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Removes and returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Removes and returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Removes the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Removes the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Hëlt dat lescht Element aus enger Lëscht eraus."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Hëlt en zoufällegt Element aus enger Lëscht eraus."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "to # from end"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "to #"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "to last"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "get sub-list from first"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "get sub-list from # from end"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "get sub-list from #"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Creates a copy of the specified portion of a list."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 ass dat éischt Element."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 ass dat éischt Element."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "find first occurrence of item"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "find last occurrence of item"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Returns the index of the first/last occurrence of the item in the list. Returns %1 if item is not found."; // untranslated -Blockly.Msg.LISTS_INLIST = "an der Lëscht"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 ass eidel"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Returns true if the list is empty."; // untranslated -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "Längt vu(n) %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Returns the length of a list."; // untranslated -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "create list with item %1 repeated %2 times"; // untranslated -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Creates a list consisting of the given value repeated the specified number of times."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "als"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "asetzen op"; -Blockly.Msg.LISTS_SET_INDEX_SET = "set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserts the item at the start of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Inserts the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Setzt d'Element um Enn vun enger Lëscht derbäi."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Setzt d'Element op eng zoufälleg Plaz an d'Lëscht derbäi."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Sets the first item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Sets the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Sets the last item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Setzt en zoufällegt Element an eng Lëscht."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeresch"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetesch"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "make list from text"; // untranslated -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "make text from list"; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "falsch"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Schéckt entweder richteg oder falsch zréck."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "wouer"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Return true if both inputs equal each other."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Return true if the first input is greater than the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Return true if the first input is greater than or equal to the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Return true if the first input is smaller than the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Return true if the first input is smaller than or equal to the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Return true if both inputs are not equal to each other."; // untranslated -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "net %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Returns true if the input is false. Returns false if the input is true."; // untranslated -Blockly.Msg.LOGIC_NULL = "null"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Returns null."; // untranslated -Blockly.Msg.LOGIC_OPERATION_AND = "an"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "oder"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Return true if both inputs are true."; // untranslated -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Return true if at least one of the inputs is true."; // untranslated -Blockly.Msg.LOGIC_TERNARY_CONDITION = "Test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "wa falsch"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "wa wouer"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value."; // untranslated -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Arithmetic"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Den Total vun den zwou Zuelen zréckginn."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Return the quotient of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Return the difference of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "D'Produkt vun den zwou Zuelen zréckginn."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Return the first number raised to the power of the second number."; // untranslated -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; // untranslated -Blockly.Msg.MATH_CHANGE_TITLE = "änneren %1 ëm %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Add a number to variable '%1'."; // untranslated -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; // untranslated -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; // untranslated -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "constrain %1 low %2 high %3"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Constrain a number to be between the specified limits (inclusive)."; // untranslated -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "is divisible by"; // untranslated -Blockly.Msg.MATH_IS_EVEN = "ass gerued"; -Blockly.Msg.MATH_IS_NEGATIVE = "ass negativ"; -Blockly.Msg.MATH_IS_ODD = "ass ongerued"; -Blockly.Msg.MATH_IS_POSITIVE = "ass positiv"; -Blockly.Msg.MATH_IS_PRIME = "ass eng Primzuel"; -Blockly.Msg.MATH_IS_TOOLTIP = "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false."; // untranslated -Blockly.Msg.MATH_IS_WHOLE = "ass eng ganz Zuel"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; // untranslated -Blockly.Msg.MATH_MODULO_TITLE = "Rescht vu(n) %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Return the remainder from dividing the two numbers."; // untranslated -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; // untranslated -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Eng Zuel."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "Moyenne vun der Lëscht"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "Maximum aus der Lëscht"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "median of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "min of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "modes of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "zoufällegt Element vun enger Lëscht"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "standard deviation of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "sum of list"; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Return the average (arithmetic mean) of the numeric values in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Schéckt de gréisste Wäert aus enger Lëscht zréck."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Return the median number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Return the smallest number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Return a list of the most common item(s) in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Return a random element from the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Return the standard deviation of the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Return the sum of all the numbers in the list."; // untranslated -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "random fraction"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive)."; // untranslated -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TITLE = "zoufälleg ganz Zuel tëscht %1 a(n) %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Return a random integer between the two specified limits, inclusive."; // untranslated -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; // untranslated -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "opronnen"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "ofrënnen"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "oprënnen"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Eng Zuel op- oder ofrënnen."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://lb.wikipedia.org/wiki/Racine carrée"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absolut"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "Quadratwuerzel"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Return the absolute value of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Return e to the power of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Return the natural logarithm of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Return the base 10 logarithm of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Return the negation of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Return 10 to the power of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Return the square root of a number."; // untranslated -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; // untranslated -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Return the arccosine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Return the arcsine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Return the arctangent of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Return the cosine of a degree (not radian)."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Return the sine of a degree (not radian)."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Return the tangent of a degree (not radian)."; // untranslated -Blockly.Msg.NEW_VARIABLE = "Variabel uleeën..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Neie variabelen Numm:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "allow statements"; // untranslated -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "mat:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Run the user-defined function '%1'."; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Run the user-defined function '%1' and use its output."; // untranslated -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "mat:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Create '%1'"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Dës Funktioun beschreiwen..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "eppes maachen"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "to"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Creates a function with no output."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "zréck"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Creates a function with an output."; // untranslated -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Warning: This function has duplicate parameters."; // untranslated -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Highlight function definition"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "If a value is true, then return a second value."; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Warning: This block may be used only within a function definition."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "input name:"; // untranslated -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Add an input to the function."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "inputs"; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Add, remove, or reorder inputs to this function."; // untranslated -Blockly.Msg.REDO = "Widderhuelen"; -Blockly.Msg.REMOVE_COMMENT = "Bemierkung ewechhuelen"; -Blockly.Msg.RENAME_VARIABLE = "Variabel ëmbenennen..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "All '%1' Variabelen ëmbenennen op:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "Text drunhänken"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "to"; // untranslated -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Append some text to variable '%1'."; // untranslated -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "to lower case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "to Title Case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "to UPPER CASE"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; // untranslated -Blockly.Msg.TEXT_CHARAT_FIRST = "get first letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_FROM_END = "get letter # from end"; // untranslated -Blockly.Msg.TEXT_CHARAT_FROM_START = "get letter #"; // untranslated -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "am Text"; -Blockly.Msg.TEXT_CHARAT_LAST = "get last letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_RANDOM = "get random letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Returns the letter at the specified position."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "En Element bei den Text derbäisetzen."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "join"; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Add, remove, or reorder sections to reconfigure this text block."; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "to letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "bis bei de Buschtaf #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "bis bei de leschte Buschtaw"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "am Text"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "get substring from first letter"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "get substring from letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "get substring from letter #"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returns a specified portion of the text."; // untranslated -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "am Text"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "find first occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "find last occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found."; // untranslated -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 ass eidel"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returns true if the provided text is empty."; // untranslated -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "create text with"; // untranslated -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Create a piece of text by joining together any number of items."; // untranslated -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "Längt vu(n) %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Returns the number of letters (including spaces) in the provided text."; // untranslated -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "%1 drécken"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Print the specified text, number or other value."; // untranslated -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Prompt for user for a number."; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Frot de Benotzer no engem Text."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "prompt for number with message"; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "prompt for text with message"; // untranslated -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; // untranslated -Blockly.Msg.TEXT_TEXT_TOOLTIP = "E Buschtaf, e Wuert oder eng Textzeil."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "trim spaces from both sides of"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "trim spaces from left side of"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "trim spaces from right side of"; // untranslated -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Return a copy of the text with spaces removed from one or both ends."; // untranslated -Blockly.Msg.TODAY = "Haut"; -Blockly.Msg.UNDO = "Réckgängeg maachen"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "Element"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Create 'set %1'"; // untranslated -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returns the value of this variable."; // untranslated -Blockly.Msg.VARIABLES_SET = "set %1 to %2"; // untranslated -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Create 'get %1'"; // untranslated -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Sets this variable to be equal to the input."; // untranslated -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/lki.js b/backend/_pv_1_3_5/static/blockly/msg/js/lki.js deleted file mode 100755 index 0c4469e93..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/lki.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.lki'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "گةپ دائن"; -Blockly.Msg.CHANGE_VALUE_TITLE = "تةغییر مقدار:"; -Blockly.Msg.CLEAN_UP = "تمیزکردن بلاکةل"; -Blockly.Msg.COLLAPSE_ALL = "چؤیچانن/پشکانن بلاکةل"; -Blockly.Msg.COLLAPSE_BLOCK = "چؤیچانن/پشکانن بلاک"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "رةنگ 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "رةنگ 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "نسبت"; -Blockly.Msg.COLOUR_BLEND_TITLE = "قاتی پاتی"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "دو رنگ را با نسبت مشخص‌شده مخلوط می‌کند (۰٫۰ - ۱٫۰)"; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/رةنگ"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "رةنگێ إژ تةختة رةنگ انتخاب کةن"; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "رةنگ بةختةکی"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = ".رةنگئ بةختةکی انتخاب کةن"; -Blockly.Msg.COLOUR_RGB_BLUE = "کاوو"; -Blockly.Msg.COLOUR_RGB_GREEN = "سؤز"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "سۆر"; -Blockly.Msg.COLOUR_RGB_TITLE = "رةنگ وة"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "ساخت یک رنگ با مقدار مشخص‌شده‌ای از سۆر، سؤز و کاوو. همهٔ مقادیر باید بین ۰ تا ۱۰۰ باشند."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "شکانِن حلقه"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "ادامه با تکرار بعدی حلقه"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "شکستن حلقهٔ شامل."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "پریدن از بقیهٔ حلقه و ادامه با تکرار بعدی."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "اخطار: این بلوک ممکن است فقط داخل یک حلقه استفاده شود."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "ئةرا هر مورد %1 وۀ نام لیست%2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "برای هر مورد در این فهرست، تنظیم متغیر «%1» به مورد و انجام تعدادی عبارت."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "با تعداد %1 از %2 به %3 با گام‌های %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "متغیر %1 را در مقادیر شروع‌شده از عدد انتهای به عدد انتهایی را دارد، با فواصل مشخص‌شده می‌شمارد و این بلوک مشخص‌شده را انجام می‌دهد."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "افزودن یک شرط به بلوک اگر."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "اضافه‌کردن نهایی، گرفتن همهٔ شرایط به بلوک اگر."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "افزودن، حذف یا بازمرتب‌سازی قسمت‌ها برای پیکربندی دوبارهٔ این بلوک اگر."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "آنگاه"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "اگر آنگاه"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "اگر"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "اگر یک مقدار صحیح است، سپس چند عبارت را انجام بده."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "اگر یک مقدار صحیح است، اول بلوک اول عبارات را انجام بده. در غیر این صورت بلوک دوم عبارات انجام بده."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "اگر مقدار اول صحیح بود، از آن بلوک اول عبارات را انجام بده. در غیر این صورت، اگر مقدار دوم صحیح است، بلوک دوم عبارات را انجام بده."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "اگر مقدار اول درست است، بلوک اول عبارات را انجام بده. در غیر این صورت، اگر مقدار دوم درست باشد بلوک دوم عبارات را انجام بده. اگر هیچ از مقادیر درست نبود، آخرین بلوک عبارات را انجام بده."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://lki.wikipedia.org/wiki/حلقه_فور"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "انجوم بی"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "%بار تکرار 1"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "انجام چةن عبارت چندین گِل."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "تکرار تا وةختێ گإ"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "تکرار در حالی که"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "تا زمانی که یک مقدار ناصحیح است، چند عبارت را انجام بده."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "تا زمانی که یک مقدار صحیح است، چند عبارت را انجام بده."; -Blockly.Msg.DELETE_ALL_BLOCKS = "حةذف کؤل %1 بلاکةل?"; -Blockly.Msg.DELETE_BLOCK = "پاک کردن بلاک"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "حةذف %1 بلاکةل"; -Blockly.Msg.DISABLE_BLOCK = "إ کار کةتن(غیرفعال‌سازی) بلاک"; -Blockly.Msg.DUPLICATE_BLOCK = "کؤپی کردن"; -Blockly.Msg.ENABLE_BLOCK = "إ کارآشتن(فعال)بلاک"; -Blockly.Msg.EXPAND_ALL = "کةلنگآ کردِن بلاکةل"; -Blockly.Msg.EXPAND_BLOCK = "کةلنگآ کردِن بلاک"; -Blockly.Msg.EXTERNAL_INPUTS = "ورودیةل خروجی"; -Blockly.Msg.HELP = "کؤمةک"; -Blockly.Msg.INLINE_INPUTS = "ورودیةل نوم جا"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "ایجاد فهرست خالی"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "فهرستی با طول صفر شامل هیچ رکورد داده‌ای بر می‌گرداند."; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "لیست"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "اضافه‌کردن، حذف‌کردن یا ترتیب‌سازی مجدد بخش‌ها این بلوک فهرستی."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "ایجاد فهرست با"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "اضافه‌کردن یک مورد به فهرست."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "فهرستی از هر عددی از موارد می‌سازد."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "إژ أؤةل"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# إژ دؤما آخر"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "گِرتِن"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "گِرتِن و حةذف کردن"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "دؤمائن/آخرین"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "بةختةکی"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "حةذف کردن"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "اولین مورد یک فهرست را بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "موردی در محل مشخص‌شده بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "آخرین مورد در یک فهرست را بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "یک مورد تصادفی در یک فهرست بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "اولین مورد مشخص‌شده در فهرست را حذف و بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "مورد در محل مشخص‌شده در فهرست را حذف و بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "آخرین مورد مشخص‌شده در فهرست را حذف و بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "مورد تصادفی‌ای را در فهرست حذف و بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "اولین مورد را در یک فهرست حذف می‌کند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "مورد مشخص‌شده در موقعیت مشخص در یک فهرست را حذف و بر می‌گرداند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "آخرین مورد را در یک فهرست حذف می‌کند."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "یک مورد تصادفی را یک فهرست حذف می‌کند."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "به # از انتها"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "به #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "به آخرین"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "گرفتن زیرمجموعه‌ای از ابتدا"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "گرفتن زیرمجموعه‌ای از # از انتها"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "گرفتن زیرمجموعه‌ای از #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "کپی از قسمت مشخص‌شدهٔ لیست درست می‌کند."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 آخرین مورد است."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 اولین مورد است."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "یافتن اولین رخ‌داد مورد"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "یافتن آخرین رخ‌داد مورد"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "شاخصی از اولین/آخرین رخ‌داد مورد در فهرست را بر می‌گرداند. %1 بر می‌گرداند اگر آیتم موجود نبود."; -Blockly.Msg.LISTS_INLIST = "در فهرست"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 خالی است"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "اگر فهرست خالی است مقدار صجیج بر می‌گرداند."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "طول %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "طول یک فهرست را برمی‌گرداند."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "فهرستی با %1 تکرارشده به اندازهٔ %2 می‌سازد"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "فهرستی شامل مقادیر داده‌شدهٔ تکرار شده عدد مشخص‌شده می‌سازد."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "به عنوان"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "درج در"; -Blockly.Msg.LISTS_SET_INDEX_SET = "مجموعه"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "موردی به ته فهرست اضافه می‌کند."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "موردی در موقعیت مشخص‌شده در یک فهرست اضافه می‌کند."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "موردی به ته فهرست الحاق می‌کند."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "مورد را به صورت تصادفی در یک فهرست می‌افزاید."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "اولین مورد در یک فهرست را تعیین می‌کند."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "مورد مشخص‌شده در یک فهرست را قرار می‌دهد."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "آخرین مورد در یک فهرست را تعیین می‌کند."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "یک مورد تصادفی در یک فهرست را تعیین می‌کند."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "ساخت لیست إژ متن"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "ساخت متن إژ لیست"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "همراه جداساز"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "نادرست"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "بازگرداندن یکی از صحیح یا ناصحیح."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "درست"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "بازگشت صحیح اگر هر دو ورودی با یکدیگر برابر باشد."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "بازگرداندن صحیح اگر ورودی اول بزرگتر از ورودی دوم باشد."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "بازگرداندن صحیح اگر ورودی اول بزرگتر یا مساوی یا ورودی دوم باشد."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "بازگرداندن صحیح اگر ورودی اول کوچکتر از ورودی دوم باشد."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "بازگرداندن صحیح اگر ورودی اول کوچکتر یا مساوی با ورودی دوم باشد."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "برگرداندن صحیح اگر هر دو ورودی با یکدیگر برابر نباشند."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "نه %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "صجیج باز می‌گرداند اگر ورودی نا صحیح باشند. ناصحیح بازمی‌گرداند اگر ورودی صحیح باشد."; -Blockly.Msg.LOGIC_NULL = "پةتی/خالی"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "تهی باز می گرداند"; -Blockly.Msg.LOGIC_OPERATION_AND = "و"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "یا"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "بازگرداندن صحیح اگر هر دو ورودی صحیح باشد."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "بازگرداندن صحیح اگر یکی از دو ورودی صحیح باشد."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "آزمائشت"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "اگر نادرست"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "اگر درست"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "بررسی وضعیت در «آزمایش». اگر وضعیت صحیح باشد، مقدار «اگر صحیح» را بر می‌گرداند در غیر اینصورت مقدار «اگر ناصحیح» را."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Arithmetic"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "بازگرداندن مقدار جمع دو عدد."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "بازگرداندن باقی‌ماندهٔ دو عدد."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "بازگرداندن تفاوت دو عدد."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "بازگرداندن حاصلضرب دو عدد."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "بازگرداندن اولین عددی که از توان عدد دوم حاصل شده باشد."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "تغییر %1 با %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "افزودن یک عدد به متغیر '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "یکی از مقادیر مشترک را برمی‌گرداند: π (۳٫۱۴۱…)، e (۲٫۷۱۸...)، φ (۱٫۶۱۸)، sqrt(۲) (۱٫۴۱۴)، sqrt(۱/۲) (۰٫۷۰۷...) و یا ∞ (بی‌نهایت)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "محدودکردن %1 پایین %2 بالا %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "محدودکردن یک عدد بین محدودیت‌های مشخص‌شده (بسته)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "تقسیم شده بر"; -Blockly.Msg.MATH_IS_EVEN = "زوج است"; -Blockly.Msg.MATH_IS_NEGATIVE = "منفی است"; -Blockly.Msg.MATH_IS_ODD = "فرد است"; -Blockly.Msg.MATH_IS_POSITIVE = "مثبت است"; -Blockly.Msg.MATH_IS_PRIME = "عدد اول است"; -Blockly.Msg.MATH_IS_TOOLTIP = "بررسی می‌کند که آیا یک عدد زوج، فرد، اول، کامل، مثبت، منفی یا بخش‌پذیر عدد خاصی باشد را بررسی می‌کند. درست یا نادرست باز می‌گرداند."; -Blockly.Msg.MATH_IS_WHOLE = "کامل است"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "باقی‌ماندهٔ %1 + %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "باقی‌ماندهٔ تقسیم دو عدد را بر می‌گرداند."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "شؤمارە یەک"; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "میانگین فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "بزرگ‌ترین فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "میانهٔ فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "گوجةرتةرین لیست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "مد فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "مورد تصادفی از فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "انحراف معیار فهرست"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "جمع لیست"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "میانگین (میانگین ریاضی) مقادیر عددی فهرست را بر می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "بزرگ‌ترین عدد در فهرست را باز می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "میانهٔ عدد در فهرست را بر می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "کوچک‌ترین عدد در فهرست را باز می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "شایع‌ترین قلم(های) در فهرست را بر می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "موردی تصادفی از فهرست را بر می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "انحراف معیار فهرست را بر می‌گرداند."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "جمع همهٔ عددهای فهرست را باز می‌گرداند."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "کسر تصادفی"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "بازگرداندن کسری تصادفی بین ۰٫۰ (بسته) تا ۱٫۰ (باز)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "عدد صحیح تصادفی بین %1 تا %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "یک عدد تصادفی بین دو مقدار مشخص‌شده به صورت بسته باز می‌گرداند."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "گردکردن"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "گرد به پایین"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "گرد به بالا"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "گردکردن یک عدد به بالا یا پایین."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "مطلق"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "ریشهٔ دوم"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "قدر مطلق یک عدد را بازمی‌گرداند."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "بازگرداندن توان e یک عدد."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "لوگاریتم طبیعی یک عدد را باز می‌گرداند."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "بازگرداندن لگاریتم بر پایهٔ ۱۰ یک عدد."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "منفی‌شدهٔ یک عدد را باز می‌گرداند."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "بازگرداندن توان ۱۰ یک عدد."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "ریشهٔ دوم یک عدد را باز می‌گرداند."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "بازگرداندن آرک‌کسینوس درجه (نه رادیان)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = ".(بازگرداندن آرک‌سینوس درجه (نه رادیان"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "بازگرداندن آرک‌تانژانت درجه (نه رادیان)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "بازگرداندن کسینوس درجه (نه رادیان)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "بازگرداندن سینوس درجه (نه رادیان)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "بازگرداندن تانژانت یک درجه (نه رادیان)."; -Blockly.Msg.NEW_VARIABLE = "متغیر تازه..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "نام متغیر تازه:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "اجازه اظهارات"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "با:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "اجرای تابع تعریف‌شده توسط کاربر «%1»."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "اجرای تابع تعریف‌شده توسط کاربر «%1» و استفاده از خروجی آن."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "با:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "ساختن «%1»"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "انجام چیزی"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "به"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "تابعی می‌سازد بدون هیچ خروجی."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "بازگشت"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "تابعی با یک خروجی می‌سازد."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "اخطار: این تابعی پارامتر تکراری دارد."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "برجسته‌سازی تعریف تابع"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "اگر یک مقدار صحیح است، مقدار دوم را برگردان."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "اخطار: این بلوک احتمالاً فقط داخل یک تابع استفاده می‌شود."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "نام ورودی:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "اضافه کردن ورودی به تابع."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "ورودی‌ها"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "افزودن، حذف یا دوباره مرتب‌کردن ورودی این تابع."; -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "پاک کردن گةپةل/قِسةل"; -Blockly.Msg.RENAME_VARIABLE = "تغییر نام متغیر..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "تغییر نام همهٔ متغیرهای «%1» به:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "چسباندن متن"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "به"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "الحاق متنی به متغیر «%1»."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "به حروف کوچک"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "به حروف بزرگ عنوان"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "به حروف بزرگ"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "بازگرداندن کپی متن در حالتی متفاوت."; -Blockly.Msg.TEXT_CHARAT_FIRST = "گرفتن اولین حرف"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "گرفتن حرف # از آخر"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "گرفتن حرف #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "در متن"; -Blockly.Msg.TEXT_CHARAT_LAST = "گرفتن آخرین حرف"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "گرفتن حرف تصادفی"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "حرفی در موقعیت مشخص‌شده بر می‌گرداند."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "افزودن یک مورد به متن."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "نام نؤیسی"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "اضافه‌کردن، حذف یا مرتب‌سازی بحش‌ها برای تنظیم مجدد این بلوک متنی."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "به حرف # از انتها"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "به حرف #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "به آخرین حرف"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "در متن"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "گرفتن زیرمتن از اولین حرف"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "گرفتن زیرمتن از حرف # به انتها"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "گرفتن زیرمتن از حرف #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "قسمت مشخصی‌شده‌ای از متن را بر می‌گرداند."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "در متن"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "اولین رخداد متن را بیاب"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "آخرین رخداد متن را بیاب"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "شاخصی از اولین آخرین رخ‌داد متن اول در متن دوم بر می‌گرداند. اگر متن یافت نشد %1 باز می‌گرداند."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 خالی است"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "اضافه‌کردن صحیح اگر متن فراهم‌شده خالی است."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "ایجاد متن با"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "یک تکه‌ای از متن را با چسپاندن همهٔ تعداد از موارد ایجاد می‌کند."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "طول %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "بازگرداندن عددی از حروف (شامل فاصله‌ها) در متن فراهم‌شده."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "چاپ %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "چاپ متن، عدد یا هر مقدار دیگر مشخص‌شده."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "اعلان برای کاربر با یک عدد."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "اعلان برای کاربر برای یک متن."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "اعلان برای عدد با پیام"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "اعلان برای متن با پیام"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "یک حرف، کلمه یا خطی از متن."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "تراشیدن فاصله‌ها از هر دو طرف"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "تراشیدن فاصله‌ها از طرف چپ"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "تراشیدن فاصله‌ها از طرف چپ"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "کپی از متن با فاصله‌های حذف‌شده از یک یا هر دو پایان باز می‌گرداند."; -Blockly.Msg.TODAY = "ایمڕۆ"; -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "آیتم"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "درست‌کردن «تنظیم %1»"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "مقدار این متغیر را بر می‌گرداند."; -Blockly.Msg.VARIABLES_SET = "مجموعه %1 به %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "درست‌کردن «گرفتن %1»"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "متغیر برابر با خروجی را مشخص می‌کند."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/lrc.js b/backend/_pv_1_3_5/static/blockly/msg/js/lrc.js deleted file mode 100755 index 2731ca98c..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/lrc.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.lrc'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "نظرتونه اضاف بکید"; -Blockly.Msg.CHANGE_VALUE_TITLE = "ارزشت آلشت کو:"; -Blockly.Msg.CLEAN_UP = "Clean up Blocks"; // untranslated -Blockly.Msg.COLLAPSE_ALL = "کوچک کردن برشتیا"; -Blockly.Msg.COLLAPSE_BLOCK = "کوچک کردن برشت"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "رن 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "رن 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "نسوت"; -Blockly.Msg.COLOUR_BLEND_TITLE = "شیوسته"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "هر کوم د رنگیانه وا نسوت دائه بیه به شیون(0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "یه رن د رنگ دو انتخاو بکید"; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "رن بختکی"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "یه رنگ بختکی انتخاو بکید"; -Blockly.Msg.COLOUR_RGB_BLUE = "آوی"; -Blockly.Msg.COLOUR_RGB_GREEN = "سوز"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "سور"; -Blockly.Msg.COLOUR_RGB_TITLE = "رن وا"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Create a colour with the specified amount of red, green, and blue. All values must be between 0 and 100."; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "حلقه نه خراو کو"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "continue with next iteration of loop"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "حلقه شومل بیه نه خراو کو"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Skip the rest of this loop, and continue with the next iteration."; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Warning: This block may only be used within a loop."; // untranslated -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "سی هر قلم %1 د نوم گه %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "For each item in a list, set the variable '%1' to the item, and then do some statements."; // untranslated -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "اشماردن وا %1 د %2 سی %3 وا %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Have the variable '%1' take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks."; // untranslated -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Add a condition to the if block."; // untranslated -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Add a final, catch-all condition to the if block."; // untranslated -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Add, remove, or reorder sections to reconfigure this if block."; // untranslated -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "هنی"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "هنی ار"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "ار"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "If a value is true, then do some statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "If a value is true, then do the first block of statements. Otherwise, do the second block of statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements."; // untranslated -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "انجوم بئه"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "%1 تکرار کو چن بار"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Do some statements several times."; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "تا تکرار کو"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "تا تکرار کو"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "While a value is false, then do some statements."; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "While a value is true, then do some statements."; // untranslated -Blockly.Msg.DELETE_ALL_BLOCKS = "Delete all %1 blocks?"; // untranslated -Blockly.Msg.DELETE_BLOCK = "پاکسا کردن برشت"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "پاکسا کردن%1 د برشتیا"; -Blockly.Msg.DISABLE_BLOCK = "ناکشتگر کردن برشت"; -Blockly.Msg.DUPLICATE_BLOCK = "کپی کردن"; -Blockly.Msg.ENABLE_BLOCK = "کنشتگر کردن برشت"; -Blockly.Msg.EXPAND_ALL = "گپ کردن برشتیا"; -Blockly.Msg.EXPAND_BLOCK = "گپ کردن برشت"; -Blockly.Msg.EXTERNAL_INPUTS = "داده یا وه دری"; -Blockly.Msg.HELP = "هومياری"; -Blockly.Msg.INLINE_INPUTS = "داده یا مئنجا"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "یه گل نوم گه حالی راس بکیت"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Returns a list, of length 0, containing no data records"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "نوم گه"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Add, remove, or reorder sections to reconfigure this list block."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "create list with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Add an item to the list."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Create a list with any number of items."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_FIRST = "اولی"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# تا آخر"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "گرتن"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "گرتن و جاوه جا بیئن"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "آخر"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "بختكی"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "ؤرداشتن"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Removes and returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Removes and returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Removes and returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Removes and returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Removes the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Removes the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Removes the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Removes a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "to # from end"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "سی#"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "سی آخر"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "get sub-list from first"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "get sub-list from # from end"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "get sub-list from #"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Creates a copy of the specified portion of a list."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 is the last item."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 is the first item."; // untranslated -Blockly.Msg.LISTS_INDEX_OF_FIRST = "find first occurrence of item"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "find last occurrence of item"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Returns the index of the first/last occurrence of the item in the list. Returns %1 if item is not found."; // untranslated -Blockly.Msg.LISTS_INLIST = "د نوم گه"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 حالیه"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Returns true if the list is empty."; // untranslated -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "length of %1"; // untranslated -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Returns the length of a list."; // untranslated -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "create list with item %1 repeated %2 times"; // untranslated -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Creates a list consisting of the given value repeated the specified number of times."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "چی"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "بنه د"; -Blockly.Msg.LISTS_SET_INDEX_SET = "set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserts the item at the start of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Inserts the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Append the item to the end of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Inserts the item randomly in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Sets the first item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Sets the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Sets the last item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Sets a random item in a list."; // untranslated -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "make list from text"; // untranslated -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "make text from list"; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "غلط"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "هم غلط و هم راس ورگن"; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "راست و دوروست"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Return true if both inputs equal each other."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Return true if the first input is greater than the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Return true if the first input is greater than or equal to the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Return true if the first input is smaller than the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Return true if the first input is smaller than or equal to the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Return true if both inputs are not equal to each other."; // untranslated -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "نه %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Returns true if the input is false. Returns false if the input is true."; // untranslated -Blockly.Msg.LOGIC_NULL = "خمثی"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Returns null."; // untranslated -Blockly.Msg.LOGIC_OPERATION_AND = "و"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "یا"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Return true if both inputs are true."; // untranslated -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Return true if at least one of the inputs is true."; // untranslated -Blockly.Msg.LOGIC_TERNARY_CONDITION = "آزماشت کردن"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "ار غلط بی"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "ار درس بی"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value."; // untranslated -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Arithmetic"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "وه انازه دو گل شماره ورگن."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Return the quotient of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Return the difference of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Return the product of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Return the first number raised to the power of the second number."; // untranslated -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "آلشت بكيد %1 وا %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Add a number to variable '%1'."; // untranslated -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; // untranslated -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "constrain %1 low %2 high %3"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Constrain a number to be between the specified limits (inclusive)."; // untranslated -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "یه وا بهر بیه"; -Blockly.Msg.MATH_IS_EVEN = "همیشه هیئش"; -Blockly.Msg.MATH_IS_NEGATIVE = "منفیه"; -Blockly.Msg.MATH_IS_ODD = "تهنائه"; -Blockly.Msg.MATH_IS_POSITIVE = "مثبته"; -Blockly.Msg.MATH_IS_PRIME = "وه اوله"; -Blockly.Msg.MATH_IS_TOOLTIP = "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false."; // untranslated -Blockly.Msg.MATH_IS_WHOLE = "همشه"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "remainder of %1 ÷ %2"; // untranslated -Blockly.Msg.MATH_MODULO_TOOLTIP = "Return the remainder from dividing the two numbers."; // untranslated -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "یه شماره."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "مینجاگه نوم گه"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "بیشترونه د نومگه"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "مینجا نوم گه"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "کمترونه د نومگه"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "بیشری د نومگه"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "random item of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "standard deviation of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "جم کردن نومگه"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Return the average (arithmetic mean) of the numeric values in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Return the largest number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Return the median number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Return the smallest number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Return a list of the most common item(s) in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Return a random element from the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Return the standard deviation of the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Return the sum of all the numbers in the list."; // untranslated -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "random fraction"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive)."; // untranslated -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "random integer from %1 to %2"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Return a random integer between the two specified limits, inclusive."; // untranslated -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "گرد کردن"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "وه هار گرد کردن"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "وه رو گرد کردن"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Round a number up or down."; // untranslated -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "تموم و کمال"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "چارسوک ریشه"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Return the absolute value of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Return e to the power of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Return the natural logarithm of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Return the base 10 logarithm of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Return the negation of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Return 10 to the power of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Return the square root of a number."; // untranslated -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Return the arccosine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Return the arcsine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Return the arctangent of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Return the cosine of a degree (not radian)."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Return the sine of a degree (not radian)."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Return the tangent of a degree (not radian)."; // untranslated -Blockly.Msg.NEW_VARIABLE = "آلشتگر تازه..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "نوم آلشتگر تازه:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "allow statements"; // untranslated -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "وا:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Run the user-defined function '%1'."; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Run the user-defined function '%1' and use its output."; // untranslated -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "وا:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "راس کردن%1"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "یه کار انجوم بیئت"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "سی"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Creates a function with no output."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "ورگنیئن"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Creates a function with an output."; // untranslated -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Warning: This function has duplicate parameters."; // untranslated -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Highlight function definition"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "If a value is true, then return a second value."; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Warning: This block may be used only within a function definition."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "نوم داده:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Add an input to the function."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "داده یا"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Add, remove, or reorder inputs to this function."; // untranslated -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "نظر جا وه جا کو"; -Blockly.Msg.RENAME_VARIABLE = "د نو نوم نیائن آلشتگر..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "د نو نوم نیائن %1 د تموم آلشتگریا د:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "append text"; // untranslated -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "سی"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Append some text to variable '%1'."; // untranslated -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "سی واج کؤچک"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "to Title Case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "سی حرف گپ"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; // untranslated -Blockly.Msg.TEXT_CHARAT_FIRST = "get first letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_FROM_END = "get letter # from end"; // untranslated -Blockly.Msg.TEXT_CHARAT_FROM_START = "get letter #"; // untranslated -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "د متن"; -Blockly.Msg.TEXT_CHARAT_LAST = "get last letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_RANDOM = "get random letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Returns the letter at the specified position."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Add an item to the text."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "پیوسن"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Add, remove, or reorder sections to reconfigure this text block."; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "سی واج# تا آخر"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "سی واج#"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "سی آخرین واج"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "د متن"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "get substring from first letter"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "get substring from letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "get substring from letter #"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returns a specified portion of the text."; // untranslated -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "د متن"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "find first occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "find last occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found."; // untranslated -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 حالیه"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returns true if the provided text is empty."; // untranslated -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "راس کردن متن وا"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Create a piece of text by joining together any number of items."; // untranslated -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "length of %1"; // untranslated -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Returns the number of letters (including spaces) in the provided text."; // untranslated -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "print %1"; // untranslated -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Print the specified text, number or other value."; // untranslated -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Prompt for user for a number."; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Prompt for user for some text."; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "prompt for number with message"; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "prompt for text with message"; // untranslated -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "A letter, word, or line of text."; // untranslated -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "trim spaces from both sides of"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "trim spaces from left side of"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "trim spaces from right side of"; // untranslated -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Return a copy of the text with spaces removed from one or both ends."; // untranslated -Blockly.Msg.TODAY = "ئمروٙ"; -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "قلم"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Create 'set %1'"; // untranslated -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returns the value of this variable."; // untranslated -Blockly.Msg.VARIABLES_SET = "میزوکاری %1 سی %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Create 'get %1'"; // untranslated -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Sets this variable to be equal to the input."; // untranslated -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/lt.js b/backend/_pv_1_3_5/static/blockly/msg/js/lt.js deleted file mode 100755 index bc06f1e90..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/lt.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.lt'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Palikti komentarą"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Keisti reikšmę:"; -Blockly.Msg.CLEAN_UP = "Išvalyti blokus"; -Blockly.Msg.COLLAPSE_ALL = "Suskleisti blokus"; -Blockly.Msg.COLLAPSE_BLOCK = "Suskleisti bloką"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "1 spalva"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "2 spalva"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "santykis"; -Blockly.Msg.COLOUR_BLEND_TITLE = "sumaišyk"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Sumaišo dvi spalvas su pateiktu santykiu (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://lt.wikipedia.org/wiki/Spalva"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Pasirinkti spalvą iš paletės."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "atsitiktinė spalva"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Pasirinkti spalvą atsitiktinai."; -Blockly.Msg.COLOUR_RGB_BLUE = "mėlyna"; -Blockly.Msg.COLOUR_RGB_GREEN = "žalia"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "raudona"; -Blockly.Msg.COLOUR_RGB_TITLE = "spalva su"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Spalvą galima sudaryti iš raudonos, žalios ir mėlynos dedamųjų. Kiekvienos intensyvumas nuo 0 iki 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "nutraukti kartojimą"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "šį kartą praleisti likusius veiksmus ir tęsti kartojimą"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Nutraukia (artimiausią) vykstantį kartojimą."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Praleidžia žemiau išvardintus kartojimo veiksmus (ir tęsia darbą nuo kartojimo pradinio veiksmo)."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Atsargiai: šis blokas gali būt naudojamas tik kartojimo bloko viduje."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "kartok su kiekvienu %1 iš sąrašo %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Kartok veiksmus, kol kintamasis \"%1\" paeiliui gauna kiekvieną sąrašo reikšmę."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "kartok, kai %1 kinta nuo %2 iki %3 po %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Kartoti veiksmus su kiekvienu sąrašo elementu, priskirtu kintamajam \"%1\"."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Pridėti sąlygą „jei“ blokui."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Pridėti veiksmų vykdymo variantą/\"šaką\", kai netenkinama nė viena sąlyga."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Galite pridėt/pašalinti/pertvarkyti sąlygų \"šakas\"."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "kitu atveju"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "arba jei"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "jei"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Jeigu sąlyga tenkinama, tai atlik veiksmus."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Jei sąlyga tenkinama, atlikti jai priklausančius veiksmus, o jei ne -- atlikti kitus nurodytus veiksmus."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Jei pirma sąlyga tenkinama, atlikti jai priklausančius veiksmus, O jei ne, tikrinti antrą sąlygą -- ir jei ši tenkinama, atlikti jos veiksmus."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Jei pirma sąlyga tenkinama, atlikti jai priklausančius veiksmus, O jei ne, tikrinti antrą sąlygą -- ir jei ši tenkinama, atlikti jos veiksmus. Kitais atvejais -- atlikti paskutinio bloko veiksmus."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "daryti"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "pakartokite %1 kartus"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Leidžia atlikti išvardintus veiksmus kelis kartus."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "kartok, kol pasieksi"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "kartok kol"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Kartoja veiksmus, kol bus pasiekta nurodyta sąlyga."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Kartoja veiksmus, kol sąlyga tenkinama."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Ištrinti visus %1 blokus?"; -Blockly.Msg.DELETE_BLOCK = "Ištrinti bloką"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Ištrinti %1 blokus"; -Blockly.Msg.DISABLE_BLOCK = "Išjungti bloką"; -Blockly.Msg.DUPLICATE_BLOCK = "Kopijuoti"; -Blockly.Msg.ENABLE_BLOCK = "Įjungti bloką"; -Blockly.Msg.EXPAND_ALL = "Išskleisti blokus"; -Blockly.Msg.EXPAND_BLOCK = "Išskleisti bloką"; -Blockly.Msg.EXTERNAL_INPUTS = "Išdėstyti stulpeliu, kai daug parametrų"; -Blockly.Msg.HELP = "Pagalba"; -Blockly.Msg.INLINE_INPUTS = "Išdėstyti vienoje eilutėje"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "tuščias sąrašas"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Grąžina sąrašą, ilgio 0, neturintį duomenų"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "sąrašas"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Add, remove, or reorder sections to reconfigure this list block."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "sukurti sąrašą su"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Pridėti elementą į sąrašą."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Sukurti sąrašą iš bet kokio skaičiaus elementų."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "pirmas"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# nuo galo"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "paimk"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "paimk ir ištrink"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "paskutinis"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "atsitiktinis"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "pašalinti"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Grąžina pirmąjį sąrašo elementą."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Gražina objektą į nurodyta poziciją sąraše."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Grąžina paskutinį elementą iš sąrašo."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Grąžina atsitiktinį elementą iš sąrašo."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Removes and returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Removes and returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Removes and returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Removes and returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Removes the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Removes the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Removes the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Removes a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "iki # nuo galo"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "iki #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "iki galo"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "sąrašo dalis nuo pradžios"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "sąrašo dalis nuo # nuo galo"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "sąrašo dalis nuo #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Creates a copy of the specified portion of a list."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 yra paskutinis objektas."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 yra pirmasis objektas."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "rask pirmą reikšmę"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "rask paskutinę reikšmę"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Grąžina pirmos/paskutinės reikšmės eilės nr. sąraše. Grąžina %1, jei reikšmės neranda."; -Blockly.Msg.LISTS_INLIST = "sąraše"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 yra tuščias"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Grąžina „true“, jeigu sąrašas tuščias."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "ilgis %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Grąžina sąrašo ilgį."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "sukurk sąrašą, kuriame %1 bus %2 kartus"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Creates a list consisting of the given value repeated the specified number of times."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "kaip"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "įterpk į vietą"; -Blockly.Msg.LISTS_SET_INDEX_SET = "priskirk elementui"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserts the item at the start of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Įterpią objektą į nurodytą poziciją sąraše."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Append the item to the end of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Inserts the item randomly in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Sets the first item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Sets the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Sets the last item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Sets a random item in a list."; // untranslated -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "didėjančia tvarka"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "mažėjančia tvarka"; -Blockly.Msg.LISTS_SORT_TITLE = "rūšiuoti %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Rūšiuoti sąrašo kopiją."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "abecėlės, ignoruoti raidžių dydį"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "skaitmeninis"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "abėcėlės"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "make list from text"; // untranslated -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "make text from list"; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "klaidinga"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Reikšmė gali būti \"teisinga\"/\"Taip\" arba \"klaidinga\"/\"Ne\"."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "tiesa"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Tenkinama, jei abu reiškiniai lygūs."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Return true if the first input is greater than the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Return true if the first input is greater than or equal to the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Return true if the first input is smaller than the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Return true if the first input is smaller than or equal to the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Return true if both inputs are not equal to each other."; // untranslated -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "ne %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Returns true if the input is false. Returns false if the input is true."; // untranslated -Blockly.Msg.LOGIC_NULL = "nieko"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Reikšmė nebuvo nurodyta..."; -Blockly.Msg.LOGIC_OPERATION_AND = "ir"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "arba"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Bus teisinga, kai abi sąlygos bus tenkinamos."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Return true if at least one of the inputs is true."; // untranslated -Blockly.Msg.LOGIC_TERNARY_CONDITION = "sąlyga"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "jei ne"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "jei taip"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Jeigu sąlygą tenkinama, grąžina pirmą reikšmę, o jei ne - antrąją."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Arithmetic"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Grąžina dviejų skaičių sumą."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Grąžina dviejų skaičių dalmenį."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Grąžina dviejų skaičių skirtumą."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Grąžina dviejų skaičių sandaugą."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Grąžina pirmą skaičių pakeltą laipsniu pagal antrą skaičių."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "padidink %1 (emptypage) %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Prideda skaičių prie kintamojo '%1'. Kai skaičius neigiamas - gaunasi atimtis."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; // untranslated -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "apribok %1 tarp %2 ir %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Constrain a number to be between the specified limits (inclusive)."; // untranslated -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "yra dalus iš"; -Blockly.Msg.MATH_IS_EVEN = "yra lyginis"; -Blockly.Msg.MATH_IS_NEGATIVE = "yra neigiamas"; -Blockly.Msg.MATH_IS_ODD = "yra nelyginis"; -Blockly.Msg.MATH_IS_POSITIVE = "yra teigiamas"; -Blockly.Msg.MATH_IS_PRIME = "yra pirminis"; -Blockly.Msg.MATH_IS_TOOLTIP = "Patikrina skaičiaus savybę: (ne)lyginis/pirminis/sveikasis/teigiamas/neigiamas/dalus iš x."; -Blockly.Msg.MATH_IS_WHOLE = "yra sveikasis"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "dalybos liekana %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Return the remainder from dividing the two numbers."; // untranslated -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://lt.wikipedia.org/wiki/Skaičius"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Skaičius."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "vidurkis"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "didžiausia reikšmė sąraše"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "mediana sąrašui"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "mažiausia reikšmė sąraše"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "statistinė moda sąrašui"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "atsitiktinis elementas iš sąrašo"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "standartinis nuokrypis sąraše"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "suma"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Return the average (arithmetic mean) of the numeric values in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Return the largest number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Grąžinti sąrašo medianą."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Return the smallest number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Grąžinti sąrašą dažniausių elementų sąraše."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Grąžinti atsitiktinį elementą iš sąrašo."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Return the standard deviation of the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "didžiausia reikšmė"; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "atsitiktinė trupmena"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Atsitiktinė trupmena nuo 0 (imtinai) iki 1 (neimtinai)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "atsitiktinis sveikas sk. nuo %1 iki %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Return a random integer between the two specified limits, inclusive."; // untranslated -Blockly.Msg.MATH_ROUND_HELPURL = "https://lt.wikipedia.org/wiki/Apvalinimas"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "apvalink"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "apvalink žemyn"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "apvalink aukštyn"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Suapvalinti skaičių į žemesnę ar aukštesnę reikšmę."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "modulis"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "kvadratinė šaknis"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Skaičiaus modulis - reikšmė be ženklo (panaikina minusą)."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Grąžinti skaičių laipsniu e."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Grąžinti skaičiaus natūrinį logaritmą."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Return the base 10 logarithm of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Grąžina skaičiui priešingą skaičių."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Grąžinti skaičių laipsniu 10."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Return the square root of a number."; // untranslated -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://lt.wikipedia.org/wiki/Trigonometrinės_funkcijos"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Grąžinti skaičiaus arkkosinusą."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Grąžinti skaičiaus arksinusą."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Grąžinti skaičiaus arktangentą."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Grąžinti laipsnio kosinusą (ne radiano)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Grąžinti laipsnio sinusą (ne radiano)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Grąžinti laipsnio tangentą (ne radiano)."; -Blockly.Msg.NEW_VARIABLE = "Naujas kintamasis..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Naujo kintamojo pavadinimas:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "leisti vidinius veiksmus"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "pagal:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Vykdyti sukurtą komandą \"%1\"."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Įvykdyti komandą \"%1\" ir naudoti jos suskaičiuotą (atiduotą) reikšmę."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "su:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Sukurti \"%1\""; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "daryk kažką"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "komanda:"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Sukuria procedūrą - komandą, kuri nepateikia jokio rezultato (tik atlieka veiksmus)."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "duok"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Sukuria funkciją - komandą, kuri ne tik atlieka veiksmus bet ir pateikia (grąžina/duoda) rezultatą."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Ši komanda turi du vienodus gaunamų duomenų pavadinimus."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Highlight function definition"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Jeigu pirma reikšmė yra teisinga (sąlyga tenkinama), grąžina antrą reikšmę."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Perspėjimas: šis blokas gali būti naudojamas tik aprašant funkciją."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "parametro pavadinimas:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Pridėti funkcijos parametrą (gaunamų duomenų pavadinimą)."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "gaunami duomenys (parametrai)"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Tvarkyti komandos gaunamus duomenis (parametrus)."; -Blockly.Msg.REDO = "Atkurti"; -Blockly.Msg.REMOVE_COMMENT = "Pašalinti komentarą"; -Blockly.Msg.RENAME_VARIABLE = "Pervardyti kintamajį..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Pervadinti visus '%1' kintamuosius į:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "pridėk tekstą"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "prie"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Append some text to variable '%1'."; // untranslated -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = " mažosiom raidėm"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = " Pavadinimo Raidėmis"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = " DIDŽIOSIOM RAIDĖM"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; // untranslated -Blockly.Msg.TEXT_CHARAT_FIRST = "gauti pirmą raidę"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "raidė nuo galo #"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "gauti raidę #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "tekste"; -Blockly.Msg.TEXT_CHARAT_LAST = "gauti paskutinę raidę"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "gauti atsitiktinę raidę"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Returns the letter at the specified position."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Pridėti teksto elementą."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "sujunk"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Add, remove, or reorder sections to reconfigure this text block."; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "iki raidės nuo galo #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "iki raidės #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "iki pabaigos"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "tekste"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "dalis nuo pradžios"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "dalis nuo raidės #"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "dalis nuo raidės #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returns a specified portion of the text."; // untranslated -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "tekste"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "rask,kur pirmą kartą paminėta"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "rask,kur paskutinį kartą paminėta"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found."; // untranslated -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 yra tuščias"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returns true if the provided text is empty."; // untranslated -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "sukurti tekstą su"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Create a piece of text by joining together any number of items."; // untranslated -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "teksto %1 ilgis"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Suranda teksto simbolių kiekį (įskaitant ir tarpus)"; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "spausdinti %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Print the specified text, number or other value."; // untranslated -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Prašyti vartotoją įvesti skaičių."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Prašyti vartotoją įvesti tekstą."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "paprašyk įvesti skaičių :"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "paprašyk įvesti tekstą :"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; // untranslated -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Tekstas (arba žodis, ar raidė)"; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "išvalyk tarpus šonuose"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "išvalyk tarpus pradžioje"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "išvalyk tarpus pabaigoje"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Return a copy of the text with spaces removed from one or both ends."; // untranslated -Blockly.Msg.TODAY = "Šiandien"; -Blockly.Msg.UNDO = "Anuliuoti"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "elementas"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Sukurk \"priskirk %1\""; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returns the value of this variable."; // untranslated -Blockly.Msg.VARIABLES_SET = "priskirk %1 = %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Sukurti 'kintamasis %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Sets this variable to be equal to the input."; // untranslated -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/mk.js b/backend/_pv_1_3_5/static/blockly/msg/js/mk.js deleted file mode 100755 index 8a9b2b322..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/mk.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.mk'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Додај коментар:"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Смена на вредност:"; -Blockly.Msg.CLEAN_UP = "Clean up Blocks"; // untranslated -Blockly.Msg.COLLAPSE_ALL = "Собери блокови"; -Blockly.Msg.COLLAPSE_BLOCK = "Собери блок"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "боја 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "боја 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "сооднос"; -Blockly.Msg.COLOUR_BLEND_TITLE = "смешај"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Меша две бои во даден сооднос (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://mk.wikipedia.org/wiki/Боја"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Изберете боја од палетата."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "случајна боја"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Избери боја на тепка."; -Blockly.Msg.COLOUR_RGB_BLUE = "сина"; -Blockly.Msg.COLOUR_RGB_GREEN = "зелена"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "црвена"; -Blockly.Msg.COLOUR_RGB_TITLE = "боја со"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Создајте боја со укажаните износи на црвена, зелена и сина. Сите вредности мора да бидат помеѓу 0 и 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "излези од јамката"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "продолжи со следното повторување на јамката"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Излези од содржечката јамка."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Skip the rest of this loop, and continue with the next iteration."; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Warning: This block may only be used within a loop."; // untranslated -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "за секој елемент %1 на списокот %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Му ја задава променливата „%1“ на секој елемент на списокот, а потоа исполнува наредби."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "број со %1 од %2 до %3 со %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Променливата \"%1\" да ги земе вредностите од почетниот до завршниот број, броејќи според укажаниот интервал и ги исполнува укажаните блокови."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Add a condition to the if block."; // untranslated -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Add a final, catch-all condition to the if block."; // untranslated -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Додава, отстранува или прередува делови за прераспоредување на овој блок „ако“."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "инаку"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "инаку ако"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "ако"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "If a value is true, then do some statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "If a value is true, then do the first block of statements. Otherwise, do the second block of statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements."; // untranslated -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://mk.wikipedia.org/wiki/For-јамка"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "исполни"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "повтори %1 пати"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Исполнува наредби неколку пати."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "повторувај сè до"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "повторувај додека"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Додека вредноста е невистинита, исполнува наредби."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Додека вредноста е вистинита, исполнува наредби."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Да ги избришам сите %1 блокчиња?"; -Blockly.Msg.DELETE_BLOCK = "Избриши блок"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Избриши %1 блока"; -Blockly.Msg.DISABLE_BLOCK = "Исклучи блок"; -Blockly.Msg.DUPLICATE_BLOCK = "Ископирај"; -Blockly.Msg.ENABLE_BLOCK = "Вклучи блок"; -Blockly.Msg.EXPAND_ALL = "Рашири блокови"; -Blockly.Msg.EXPAND_BLOCK = "Рашири го блокови"; -Blockly.Msg.EXTERNAL_INPUTS = "Надворешен внос"; -Blockly.Msg.HELP = "Помош"; -Blockly.Msg.INLINE_INPUTS = "Внатрешен внос"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "create empty list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Returns a list, of length 0, containing no data records"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "list"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Add, remove, or reorder sections to reconfigure this list block."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "create list with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Add an item to the list."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Create a list with any number of items."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_FIRST = "first"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# from end"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "get"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "get and remove"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_LAST = "last"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "random"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "remove"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Removes and returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Removes and returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Removes and returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Removes and returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Removes the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Removes the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Removes the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Removes a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "to # from end"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "to #"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "to last"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "get sub-list from first"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "get sub-list from # from end"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "get sub-list from #"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Creates a copy of the specified portion of a list."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 is the last item."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 is the first item."; // untranslated -Blockly.Msg.LISTS_INDEX_OF_FIRST = "find first occurrence of item"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "find last occurrence of item"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Returns the index of the first/last occurrence of the item in the list. Returns %1 if item is not found."; // untranslated -Blockly.Msg.LISTS_INLIST = "in list"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 is empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Returns true if the list is empty."; // untranslated -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "length of %1"; // untranslated -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Returns the length of a list."; // untranslated -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "create list with item %1 repeated %2 times"; // untranslated -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Creates a list consisting of the given value repeated the specified number of times."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "as"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INSERT = "insert at"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_SET = "set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserts the item at the start of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Inserts the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Append the item to the end of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Inserts the item randomly in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Sets the first item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Sets the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Sets the last item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Sets a random item in a list."; // untranslated -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "make list from text"; // untranslated -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "make text from list"; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "невистина"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Дава или вистина или невистина."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "вистина"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://mk.wikipedia.org/wiki/Неравенство"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Дава вистина ако обата вноса се еднакви."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Дава вистина ако првиот внос е поголем од вториот."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Дава вистина ако првиот внос е поголем или еднаков на вториот."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Дава вистина ако првиот внос е помал од вториот."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Дава вистина ако првиот внос е помал или еднаков на вториот."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Дава вистина ако обата вноса не се еднакви."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "не %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Дава вистина ако вносот е невистинит. Дава невистина ако вносот е вистинит."; -Blockly.Msg.LOGIC_NULL = "ништо"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Дава ништо."; -Blockly.Msg.LOGIC_OPERATION_AND = "и"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "или"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Дава вистина ако обата вноса се вистинити."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Дава вистина ако барем еден од вносовите е вистинит."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "испробај"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "ако е невистинито"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "ако е вистинито"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value."; // untranslated -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Arithmetic"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Return the sum of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Return the quotient of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Return the difference of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Return the product of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Return the first number raised to the power of the second number."; // untranslated -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter?uselang=mk"; -Blockly.Msg.MATH_CHANGE_TITLE = "повиши %1 за %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Ѝ додава број на променливата „%1“."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://mk.wikipedia.org/wiki/Математичка_константа"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Дава една од вообичаените константи: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), или ∞ (бесконечност)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "constrain %1 low %2 high %3"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Constrain a number to be between the specified limits (inclusive)."; // untranslated -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "е делив со"; -Blockly.Msg.MATH_IS_EVEN = "е парен"; -Blockly.Msg.MATH_IS_NEGATIVE = "е негативен"; -Blockly.Msg.MATH_IS_ODD = "е непарен"; -Blockly.Msg.MATH_IS_POSITIVE = "е позитивен"; -Blockly.Msg.MATH_IS_PRIME = "е прост"; -Blockly.Msg.MATH_IS_TOOLTIP = "Проверува дали бројот е парен, непарен, прост, цел, позитивен, негативен или делив со некој број. Дава вистина или невистина."; -Blockly.Msg.MATH_IS_WHOLE = "е цел"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; // untranslated -Blockly.Msg.MATH_MODULO_TITLE = "remainder of %1 ÷ %2"; // untranslated -Blockly.Msg.MATH_MODULO_TOOLTIP = "Return the remainder from dividing the two numbers."; // untranslated -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; // untranslated -Blockly.Msg.MATH_NUMBER_TOOLTIP = "A number."; // untranslated -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "просек на списокот"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "најголем на списокот"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "медијана на списокот"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "најмал на списокот"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "модул на списокот"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "random item of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "standard deviation of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "збир од списокот"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Дава просек (аритметичка средина) од броевите на списокот."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Го дава најголемиот број на списокот."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Дава медијана од броевите на списокот."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Го дава најмалиот број на списокот."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Дава список на најзастапен(и) елемент(и) на списокот."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Return a random element from the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Return the standard deviation of the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Дава збир од сите броеви на списокот."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "random fraction"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive)."; // untranslated -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TITLE = "random integer from %1 to %2"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Return a random integer between the two specified limits, inclusive."; // untranslated -Blockly.Msg.MATH_ROUND_HELPURL = "https://mk.wikipedia.org/wiki/Заокружување"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "заокружи"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "заокружи на помало"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "заокружи на поголемо"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Го заокружува бројот на поголем или помал."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; // untranslated -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absolute"; // untranslated -Blockly.Msg.MATH_SINGLE_OP_ROOT = "square root"; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Return the absolute value of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Return e to the power of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Return the natural logarithm of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Return the base 10 logarithm of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Return the negation of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Return 10 to the power of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Return the square root of a number."; // untranslated -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; // untranslated -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Return the arccosine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Return the arcsine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Return the arctangent of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Return the cosine of a degree (not radian)."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Return the sine of a degree (not radian)."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Return the tangent of a degree (not radian)."; // untranslated -Blockly.Msg.NEW_VARIABLE = "Нова променлива..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Назив на новата променлива:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "allow statements"; // untranslated -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "with:"; // untranslated -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Run the user-defined function '%1'."; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Run the user-defined function '%1' and use its output."; // untranslated -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "with:"; // untranslated -Blockly.Msg.PROCEDURES_CREATE_DO = "Create '%1'"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "do something"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "to"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Creates a function with no output."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "return"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Creates a function with an output."; // untranslated -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Warning: This function has duplicate parameters."; // untranslated -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Highlight function definition"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "If a value is true, then return a second value."; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Warning: This block may be used only within a function definition."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "input name:"; // untranslated -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Add an input to the function."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "inputs"; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Add, remove, or reorder inputs to this function."; // untranslated -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "Отстрани коментар"; -Blockly.Msg.RENAME_VARIABLE = "Преименувај променлива..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Преименувај ги сите променливи „%1“ во:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "append text"; // untranslated -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "to"; // untranslated -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Append some text to variable '%1'."; // untranslated -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "to lower case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "to Title Case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "to UPPER CASE"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; // untranslated -Blockly.Msg.TEXT_CHARAT_FIRST = "get first letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_FROM_END = "get letter # from end"; // untranslated -Blockly.Msg.TEXT_CHARAT_FROM_START = "get letter #"; // untranslated -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "in text"; // untranslated -Blockly.Msg.TEXT_CHARAT_LAST = "get last letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_RANDOM = "get random letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Returns the letter at the specified position."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Add an item to the text."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "join"; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Add, remove, or reorder sections to reconfigure this text block."; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "to letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "to letter #"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "to last letter"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "in text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "get substring from first letter"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "get substring from letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "get substring from letter #"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returns a specified portion of the text."; // untranslated -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "in text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "find first occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "find last occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found."; // untranslated -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 is empty"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returns true if the provided text is empty."; // untranslated -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "create text with"; // untranslated -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Create a piece of text by joining together any number of items."; // untranslated -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "length of %1"; // untranslated -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Returns the number of letters (including spaces) in the provided text."; // untranslated -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "print %1"; // untranslated -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Print the specified text, number or other value."; // untranslated -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Prompt for user for a number."; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Prompt for user for some text."; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "prompt for number with message"; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "prompt for text with message"; // untranslated -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; // untranslated -Blockly.Msg.TEXT_TEXT_TOOLTIP = "A letter, word, or line of text."; // untranslated -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "trim spaces from both sides of"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "trim spaces from left side of"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "trim spaces from right side of"; // untranslated -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Return a copy of the text with spaces removed from one or both ends."; // untranslated -Blockly.Msg.TODAY = "Today"; // untranslated -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "елемент"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Create 'set %1'"; // untranslated -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returns the value of this variable."; // untranslated -Blockly.Msg.VARIABLES_SET = "set %1 to %2"; // untranslated -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Create 'get %1'"; // untranslated -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Sets this variable to be equal to the input."; // untranslated -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/ms.js b/backend/_pv_1_3_5/static/blockly/msg/js/ms.js deleted file mode 100755 index 65c1c638c..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/ms.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.ms'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Berikan Komen"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Ubah nilai:"; -Blockly.Msg.CLEAN_UP = "Kemaskan Blok"; -Blockly.Msg.COLLAPSE_ALL = "Lipat Blok²"; -Blockly.Msg.COLLAPSE_BLOCK = "Lipat Blok"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "warna 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "warna 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "nisbah"; -Blockly.Msg.COLOUR_BLEND_TITLE = "adun"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Campurkan dua warna sekali pada nisbah yang ditentukan (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://ms.wikipedia.org/wiki/Warna"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Pilih satu warna daripada palet."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "warna rawak"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Pilih satu warna secara rawak."; -Blockly.Msg.COLOUR_RGB_BLUE = "biru"; -Blockly.Msg.COLOUR_RGB_GREEN = "hijau"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "merah"; -Blockly.Msg.COLOUR_RGB_TITLE = "warnakan"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Peroleh satu warna dengan menentukan amaun campuran merah, hijau dan biru. Kesemua nilai haruslah antara 0 hingga 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "hentikan gelung"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "teruskan dengan lelaran gelung seterusnya"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Keluar dari gelung pengandung."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Langkau seluruh gelung yang tinggal dan bersambung dengan lelaran seterusnya."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Amaran: Blok ini hanya boleh digunakan dalam satu gelung."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "untuk setiap perkara %1 dalam senarai %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Untuk setiap perkara dalam senarai, tetapkan pembolehubah '%1' pada perkara, kemudian lakukan beberapa perintah."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "kira dengan %1 dari %2 hingga %3 selang %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Gunakan pembolehubah '%1' pada nilai-nilai dari nombor pangkal hingga nombor hujung, mengira mengikut selang yang ditentukan, dan lakukan blok-blok yang tertentu."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Tambah satu syarat kepada blok jika."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Tambah yang terakhir, alihkan semua keadaan ke blok jika."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Tambah, alih keluar, atau susun semula bahagian-bahagian untuk menyusun semula blok jika."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "lain"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "lain jika"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "jika"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Jika nilai yang benar, lakukan beberapa penyata."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Jika suatu nilai benar, lakukan penyata blok pertama. Jika tidak, bina penyata blok kedua."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Jika nilai yang pertama adalah benar, lakukan penyata pertama blok. Sebaliknya, jika nilai kedua adalah benar, lakukan penyata blok kedua."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Jika nilai yang pertama adalah benar, lakukan penyata blok pertama. Sebaliknya, jika nilai kedua adalah benar, lakukan penyata blok kedua. Jika tiada nilai adalah benar, lakukan penyata blok terakhir."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "lakukan"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "ulang %1 kali"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Lakukan perintah berulang kali."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "ulangi sehingga"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "ulangi apabila"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Lakukan beberapa perintah apabila nilainya palsu (false)."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Lakukan beberapa perintah apabila nilainya benar (true)."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Hapuskan kesemua %1 blok?"; -Blockly.Msg.DELETE_BLOCK = "Hapuskan Blok"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Hapuskan %1 Blok"; -Blockly.Msg.DISABLE_BLOCK = "Matikan Blok"; -Blockly.Msg.DUPLICATE_BLOCK = "Pendua"; -Blockly.Msg.ENABLE_BLOCK = "Hidupkan Blok"; -Blockly.Msg.EXPAND_ALL = "Buka Blok²"; -Blockly.Msg.EXPAND_BLOCK = "Buka Blok"; -Blockly.Msg.EXTERNAL_INPUTS = "Input Luaran"; -Blockly.Msg.HELP = "Bantuan"; -Blockly.Msg.INLINE_INPUTS = "Input Sebaris"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "Wujudkan senarai kosong"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Kembalikan senarai panjang 0, yang tidak mengandungi rekod data"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "senarai"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Tambah, alih keluar, atau susun semula bahagian-bahagian untuk menyusun semula senarai blok."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "wujudkan senarai dengan"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Tambah item ke dalam senarai."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Wujudkan senarai dengan apa jua nombor item."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "pertama"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# dari akhir"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "dapatkan"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "dapat dan alihkan"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "terakhir"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "rawak"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "alihkan"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Kembalikan item pertama dalam senarai."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Kembalikan item dalam kedudukan yang ditetapkan dalam senarai."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Kembalikan item pertama dalam senarai."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Kembalikan item rawak dalam senarai."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Alihkan dan kembalikan item pertama dalam senarai."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Alihkan dan kembalikan item mengikut spesifikasi posisi dalam senarai."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Alihkan dan kembalikan item terakhir dalam senarai."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Alihkan dan kembalikan item rawak dalam senarai."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Alihkan item pertama dalam senarai."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Alihkan item pada posisi mengikut spesifikasi dalam senarai."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Alihkan item terakhir dalam senarai."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Alihkan item rawak dalam senarai."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "ke # dari akhir"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "ke #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "ke akhir"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "dapatkan sub-senarai daripada pertama"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "dapatkan sub-senarai daripada # daripada terakhir"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "dapatkan sub-senarai daripada #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Wujudkan salinan bahagian yang ditentukan dari senarai."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 ialah item terakhir."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 ialah item pertama."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "cari pertama item kejadian"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "cari kejadian akhir item"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Menyatakan indeks kejadian pertama/terakhir item berkenaan dalam senarai. Menyatakan %1 jika item berkenaan tidak ditemui."; -Blockly.Msg.LISTS_INLIST = "dalam senarai"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 adalah kosong"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Kembalikan benar jika senarai kosong."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "panjang %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Kembalikan panjang senarai"; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "wujudkan senarai dengan item %1 diulangi %2 kali"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Wujudkan senarai yang terdiri daripada nilai berulang mengikut nombor yang ditentukan."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "sebagai"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "masukkan pada"; -Blockly.Msg.LISTS_SET_INDEX_SET = "set"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Selit item pada permulaan senarai."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Masukkan item pada posisi yand ditentukan dalam senarai."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Tambahkan item dalam senarai akhir."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Selit item secara rawak di dalam senarai."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Set item pertama dalam senarai."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Masukkan item pada posisi yang ditentukan dalam senarai."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Set item terakhir dalam senarai."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Set item rawak dalam senarai."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "buat senarai dgn teks"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "buat teks drpd senarai"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Cantumkan senarai teks menjadi satu teks, dipecahkan oleh delimiter."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Pecahkan teks kepada senarai teks, berpecah di setiap delimiter."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "dengan delimiter"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "palsu"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Kembalikan samada benar atau palsu."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "benar"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://id.wikipedia.org/wiki/Pertidaksamaan"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Kembali benar jika kedua-dua input benar antara satu sama lain."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Kembali benar jika input pertama adalah lebih besar daripada input kedua."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Kembali benar jika input pertama adalah lebih besar daripada atau sama dengan input kedua."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Kembali benar jika input pertama adalah lebih kecil daripada input kedua."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Kembali benar jika input pertama adalah lebih kecil daripada atau sama dengan input kedua."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Taip balik benar jika kedua-dua input tidak sama."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "bukan %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "'Benar' akan dibalas jika inputnya salah. 'Salah' akan dibalas jika inputnya benar."; -Blockly.Msg.LOGIC_NULL = "null"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Returns null."; -Blockly.Msg.LOGIC_OPERATION_AND = "dan"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "atau"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Return true if both inputs are true."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Return true if at least one of the inputs is true."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "Jika palsu"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "Jika benar"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://ms.wikipedia.org/wiki/Aritmetik"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Kembalikan jumlah kedua-dua bilangan."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Taip balik hasil bahagi dua nombor tersebut."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Taip balik hasil tolak dua nombor tersebut."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Taip balik hasil darab dua nombor tersebut."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Return the first number raised to the power of the second number."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://id.wikipedia.org/wiki/Perjumlahan"; -Blockly.Msg.MATH_CHANGE_TITLE = "perubahan %1 oleh %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Tambah nombor kepada pembolehubah '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://ms.wikipedia.org/wiki/Pemalar_matematik"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "constrain %1 low %2 high %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Constrain a number to be between the specified limits (inclusive)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "Boleh dibahagikan dengan"; -Blockly.Msg.MATH_IS_EVEN = "Adalah genap"; -Blockly.Msg.MATH_IS_NEGATIVE = "negatif"; -Blockly.Msg.MATH_IS_ODD = "aneh"; -Blockly.Msg.MATH_IS_POSITIVE = "adalah positif"; -Blockly.Msg.MATH_IS_PRIME = "is prime"; -Blockly.Msg.MATH_IS_TOOLTIP = "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false."; -Blockly.Msg.MATH_IS_WHOLE = "is whole"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://id.wikipedia.org/wiki/Operasi_modulus"; -Blockly.Msg.MATH_MODULO_TITLE = "remainder of %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Taip balik baki yang didapat daripada pembahagian dua nombor tersebut."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://ms.wikipedia.org/wiki/Nombor"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Suatu nombor."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "purata daripada senarai"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "Max senarai"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "Median senarai"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "min dalam senarai"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "jenis senarai"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "Item rawak daripada senarai"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "sisihan piawai bagi senarai"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "Jumlah senarai"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Kembalikan purata (min aritmetik) nilai-nilai angka di dalam senarai."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Pulangkan jumlah terbesar dalam senarai."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Kembalikan nombor median dalam senarai."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Kembalikan nombor terkecil dalam senarai."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Kembali senarai item yang paling biasa dalam senarai."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Kembalikan elemen rawak daripada senarai."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Kembali dengan sisihan piawai daripada senarai."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Kembalikan jumlah semua nombor dalam senarai."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "pecahan rawak"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Kembali sebahagian kecil rawak antara 0.0 (inklusif) dan 1.0 (eksklusif)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "integer rawak dari %1ke %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Kembalikan integer rawak diantara dua had yang ditentukan, inklusif."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "pusingan"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "Pusingan ke bawah"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "pusingan ke atas"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Bulat nombor yang naik atau turun."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://ms.wikipedia.org/wiki/Punca_kuasa_dua"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "mutlak"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "Punca kuasa dua"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Kembalikan nilai mutlak suatu nombor."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Kembalikan e kepada kuasa nombor."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Kembali dalam logaritma nombor asli."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Kembali logarithm 10 asas nombor."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Kembalikan nombor yang songsang."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Kembalikan 10 kepada kuasa nombor."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Kembalikan punca kuasa nombor."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "acos"; -Blockly.Msg.MATH_TRIG_ASIN = "asin"; -Blockly.Msg.MATH_TRIG_ATAN = "atan"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://ms.wikipedia.org/wiki/Fungsi_trigonometri"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tan"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Kembali arccosine beberapa nombor."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Kembalikan arcsince beberapa nombor."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Kembalikan beberapa nombor arctangent."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Kembalikan darjah kosinus (bukan radian)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Kembalikan darjah sine (bukan radian)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Kembalikan darjah tangen (bukan radian)."; -Blockly.Msg.NEW_VARIABLE = "Pembolehubah baru..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Nama pembolehubah baru:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "bolehkan kenyataan"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "dengan:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://ms.wikipedia.org/wiki/Fungsi"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Run the user-defined function '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://ms.wikipedia.org/wiki/Fungsi"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Run the user-defined function '%1' and use its output."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "dengan:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Hasilkan '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Terangkan fungsi ini..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "Buat sesuatu"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "Untuk"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Menghasilkan suatu fungsi tanpa output."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "kembali"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Mencipta satu fungsi dengan pengeluaran."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Amaran: Fungsi ini mempunyai parameter yang berganda."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Serlahkan definisi fungsi"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "If a value is true, then return a second value."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Amaran: Blok ini hanya boleh digunakan dalam fungsi definisi."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "Nama input:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Tambah satu input pada fungsi."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "Input-input"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Tambah, alih keluar atau susun semula input pada fungsi ini."; -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "Padamkan Komen"; -Blockly.Msg.RENAME_VARIABLE = "Tukar nama pembolehubah..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Tukar nama semua pembolehubah '%1' kepada:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "append text"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "Untuk"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Append some text to variable '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "Kepada huruf kecil"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "to Title Case"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "Kepada HURUF BESAR"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; -Blockly.Msg.TEXT_CHARAT_FIRST = "get first letter"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "get letter # from end"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "get letter #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "Dalam teks"; -Blockly.Msg.TEXT_CHARAT_LAST = "Dapatkan abjad terakhir"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "Dapatkan abjad rawak"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Returns the letter at the specified position."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Add an item to the text."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "Sertai"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Add, remove, or reorder sections to reconfigure this text block."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "to letter # from end"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "to letter #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "untuk huruf terakhir"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "dalam teks"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "get substring from first letter"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "get substring from letter # from end"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "get substring from letter #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returns a specified portion of the text."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "dalam teks"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "mencari kejadian pertama teks"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "mencari kejadian terakhir teks"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Kembalikan Indeks kejadian pertama/terakhir dari teks pertama ke dalam teks kedua. Kembalikan %1 Jika teks tidak ditemui."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 adalah kosong"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Kembalikan benar jika teks yang disediakan adalah kosong."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "hasilkan teks dengan"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Hasilkan sebahagian teks dengan menghubungkan apa jua nombor item."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "panjang %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Kembalikan jumlah huruf (termasuk ruang) dalam teks yang disediakan."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "cetak %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Cetak teks yang ditentukan, nombor atau nilai lain."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Peringatan kepada pengguna untuk nombor."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Peringatkan pengguna untuk sebahagian teks."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "Prom untuk nombor dengan mesej"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "Prom untuk teks dengan mesej"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://ms.wikipedia.org/wiki/Rentetan"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Huruf, perkataan, atau baris teks."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "mengurangkan kawasan dari kedua-dua belah"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "mengurangkan ruang dari sebelah kiri"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "mengurangkan kawasan dari sisi kanan"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Kembali salinan teks dengan ruang yang dikeluarkan daripada satu atau hujung kedua belah."; -Blockly.Msg.TODAY = "Hari ini"; -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "Perkara"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Hasilkan 'set %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Kembalikan nilai pemboleh ubah ini."; -Blockly.Msg.VARIABLES_SET = "set %1 ke %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Hasilkan 'set %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Set pembolehubah ini supaya sama dengan input."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/nb.js b/backend/_pv_1_3_5/static/blockly/msg/js/nb.js deleted file mode 100755 index a6e1c5562..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/nb.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.nb'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Legg til kommentar"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Bytt verdi:"; -Blockly.Msg.CLEAN_UP = "Rydd opp Blocks"; -Blockly.Msg.COLLAPSE_ALL = "Skjul blokker"; -Blockly.Msg.COLLAPSE_BLOCK = "Skjul blokk"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "farge 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "farge 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "forhold"; -Blockly.Msg.COLOUR_BLEND_TITLE = "blande"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Blander to farger sammen med et gitt forhold (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Velg en farge fra paletten."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "tilfeldig farge"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Velg en tilfeldig farge."; -Blockly.Msg.COLOUR_RGB_BLUE = "blå"; -Blockly.Msg.COLOUR_RGB_GREEN = "grønn"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "rød"; -Blockly.Msg.COLOUR_RGB_TITLE = "farge med"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Lag en farge med angitt verdi av rød, grønn og blå. Alle verdier må være mellom 0 og 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "bryt ut av løkken"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "fortsett med neste gjentakelse av løkken"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Bryt ut av den gjeldende løkken."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Hopp over resten av denne løkken og fortsett med neste gjentakelse."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Advarsel: Denne blokken kan kun brukes innenfor en løkke."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "for hvert element %1 i listen %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "For hvert element i en liste, angi variabelen '%1' til elementet, og deretter lag noen setninger."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "tell med %1 fra %2 til %3 med %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Ha variabel \"%1\" ta verdiene fra start nummer til slutt nummer, telle med spesifisert intervall og lag de spesifiserte blokkene."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Legg til en betingelse til hvis blokken."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Legg til hva som skal skje hvis de andre ikke slår til."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Legg til, fjern eller flytt seksjoner i denne hvis-blokken."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "ellers"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "ellers hvis"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "hvis"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Hvis dette er sant, så gjør følgende."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Hvis dette er sant, så utfør den første blokken av instruksjoner. Hvis ikke, utfør den andre blokken."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Hvis det første stemmer, så utfør den første blokken av instruksjoner. Ellers, hvis det andre stemmer, utfør den andre blokken av instruksjoner."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Hvis den første verdien er sann, så utfør den første blokken med setninger. Ellers, hvis den andre verdien er sann, så utfør den andre blokken med setninger. Hvis ingen av verdiene er sanne, så utfør den siste blokken med setninger."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "gjør"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "gjenta %1 ganger"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Gjenta noen instruksjoner flere ganger."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "gjenta til"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "gjenta mens"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Så lenge et utsagn ikke stemmer, gjør noen instruksjoner."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Så lenge et utsagn stemmer, utfør noen instruksjoner."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Slett alle %1 blokker?"; -Blockly.Msg.DELETE_BLOCK = "Slett blokk"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Slett %1 blokker"; -Blockly.Msg.DISABLE_BLOCK = "Deaktiver blokk"; -Blockly.Msg.DUPLICATE_BLOCK = "duplikat"; -Blockly.Msg.ENABLE_BLOCK = "Aktiver blokk"; -Blockly.Msg.EXPAND_ALL = "Utvid blokker"; -Blockly.Msg.EXPAND_BLOCK = "Utvid blokk"; -Blockly.Msg.EXTERNAL_INPUTS = "Eksterne kilder"; -Blockly.Msg.HELP = "Hjelp"; -Blockly.Msg.INLINE_INPUTS = "Interne kilder"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "opprett en tom liste"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Returnerer en tom liste, altså med lengde 0"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "liste"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Legg til, fjern eller endre rekkefølgen for å endre på denne delen av listen."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "lag en liste med"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Tilføy et element til listen."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Lag en liste med et vilkårlig antall elementer."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "først"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# fra slutten"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "hent"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "hent og fjern"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "siste"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "tilfeldig"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "fjern"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Returnerer det første elementet i en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Returner elementet på den angitte posisjonen i en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Returnerer det siste elementet i en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Returnerer et tilfeldig element i en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Fjerner og returnerer det første elementet i en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Fjerner og returnerer elementet ved en gitt posisjon i en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Fjerner og returnerer det siste elementet i en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Fjerner og returnerer et tilfeldig element i en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Fjerner det første elementet i en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Fjerner et element ved en gitt posisjon i en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Fjerner det siste elementet i en liste."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Fjerner et tilfeldig element i en liste."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "til # fra slutten"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "til #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "til siste"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "Hent en del av listen"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "Hent de siste # elementene"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "Hent del-listen fra #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Kopiérer en ønsket del av en liste."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 er det siste elementet."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 er det første elementet."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "finn første forekomst av elementet"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "finn siste forekomst av elementet"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Returnerer indeksen av den første/siste forekomsten av elementet i lista. Returnerer %1 hvis ikke funnet."; -Blockly.Msg.LISTS_INLIST = "i listen"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 er tom"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Returnerer sann hvis listen er tom."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "lengden på %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Returnerer lengden til en liste."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "Lag en liste hvor elementet %1 forekommer %2 ganger"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Lager en liste hvor den gitte verdien gjentas et antall ganger."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "som"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "sett inn ved"; -Blockly.Msg.LISTS_SET_INDEX_SET = "sett"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Setter inn elementet i starten av en liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Setter inn elementet ved den angitte posisjonen i en liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Tilføy elementet til slutten av en liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Setter inn elementet ved en tilfeldig posisjon i en liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Angir det første elementet i en liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Setter inn elementet ved den angitte posisjonen i en liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Angir det siste elementet i en liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Angir et tilfeldig element i en liste."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "lag liste av tekst"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "lag tekst av liste"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "usann"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Returnerer enten sann eller usann."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "sann"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Returnerer sann hvis begge inputene er like hverandre."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Returnerer sant hvis det første argumentet er større enn den andre argumentet."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Returnerer sant hvis det første argumentet er større enn eller likt det andre argumentet."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Returnerer sant hvis det første argumentet er mindre enn det andre argumentet."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Returnerer sant hvis det første argumentet er mindre enn eller likt det andre argumentet."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Returnerer sant hvis begge argumentene er ulike hverandre."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "ikke %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Returnerer sant hvis argumentet er usant. Returnerer usant hvis argumentet er sant."; -Blockly.Msg.LOGIC_NULL = "null"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Returnerer null."; -Blockly.Msg.LOGIC_OPERATION_AND = "og"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "eller"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Returnerer sant hvis begge argumentene er sanne."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Returnerer sant hvis minst ett av argumentene er sant."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "hvis usant"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "hvis sant"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Sjekk betingelsen i 'test'. Hvis betingelsen er sann, da returneres 'hvis sant' verdien. Hvis ikke returneres 'hvis usant' verdien."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://no.wikipedia.org/wiki/Aritmetikk"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Returnerer summen av to tall."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Returner kvotienten av to tall."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Returner differansen mellom to tall."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Returner produktet av to tall."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Returner det første tallet opphøyd i den andre tallet."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "endre %1 ved %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Addere et tall til variabelen '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Returner en av felleskonstantene π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), eller ∞ (uendelig)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "begrense %1 lav %2 høy %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Begrens et tall til å være mellom de angitte grenseverdiene (inklusiv)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "er delelig med"; -Blockly.Msg.MATH_IS_EVEN = "er et partall"; -Blockly.Msg.MATH_IS_NEGATIVE = "er negativer negativt"; -Blockly.Msg.MATH_IS_ODD = "er et oddetall"; -Blockly.Msg.MATH_IS_POSITIVE = "er positivt"; -Blockly.Msg.MATH_IS_PRIME = "er et primtall"; -Blockly.Msg.MATH_IS_TOOLTIP = "Sjekk om et tall er et partall, oddetall, primtall, heltall, positivt, negativt, eller om det er delelig med et annet tall. Returnerer sant eller usant."; -Blockly.Msg.MATH_IS_WHOLE = "er et heltall"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "resten av %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Returner resten fra delingen av to tall."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "x"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Et tall."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "gjennomsnittet av listen"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "maksimum av liste"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "medianen til listen"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "minimum av listen"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "Listens typetall"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "tilfeldig element i listen"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "standardavviket til listen"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "summen av listen"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Returner det aritmetiske gjennomsnittet av tallene i listen."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Returner det største tallet i listen."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Returner listens median."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Returner det minste tallet i listen."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Returner en liste av de vanligste elementene i listen."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Returner et tilfeldig element fra listen."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Returner listens standardavvik."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Returner summen av alle tallene i listen."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "tilfeldig flyttall"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Returner et tilfeldig flyttall mellom 0.0 (inkludert) og 1.0 (ikke inkludert)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "Et tilfeldig heltall mellom %1 og %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Returner et tilfeldig tall mellom de to spesifiserte grensene, inkludert de to."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "avrunding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "rund ned"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "rund opp"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Avrund et tall ned eller opp."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absoluttverdi"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "kvadratrot"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Returner absoluttverdien av et tall."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Returner e opphøyd i et tall."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Returner den naturlige logaritmen til et tall."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Returner base-10 logaritmen til et tall."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Returner det negative tallet."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Returner 10 opphøyd i et tall."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Returner kvadratroten av et tall."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "acos"; -Blockly.Msg.MATH_TRIG_ASIN = "asin"; -Blockly.Msg.MATH_TRIG_ATAN = "atan"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tan"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Returner arccosinus til et tall."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Returner arcsinus til et tall."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Returner arctangens til et tall."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Returner cosinus av en vinkel (ikke radian)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Returner sinus av en vinkel (ikke radian)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Returner tangenten av en vinkel (ikke radian)."; -Blockly.Msg.NEW_VARIABLE = "Ny variabel..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Nytt variabelnavn:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "tillat uttalelser"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "med:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Kjør den brukerdefinerte funksjonen '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Kjør den brukerdefinerte funksjonen'%1' og bruk resultatet av den."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "med:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Opprett '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "gjør noe"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "til"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Opprett en funksjon som ikke har noe resultat."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "returner"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Oppretter en funksjon som har et resultat."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Advarsel: Denne funksjonen har duplikate parametere."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Marker funksjonsdefinisjonen"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Hvis en verdi er sann, returner da en annen verdi."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Advarsel: Denne blokken kan bare benyttes innenfor en funksjonsdefinisjon."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "Navn på parameter:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Legg til en input til funksjonen."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "parametere"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Legg til, fjern eller endre rekkefølgen på input til denne funksjonen."; -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "Fjern kommentar"; -Blockly.Msg.RENAME_VARIABLE = "Gi nytt navn til variabel..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Endre navnet til alle '%1' variabler til:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "tilføy tekst"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "til"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Tilføy tekst til variabelen '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "til små bokstaver"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "til store forbokstaver"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "til STORE BOKSTAVER"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Returnerer en kopi av teksten der store og små bokstaver er byttet om."; -Blockly.Msg.TEXT_CHARAT_FIRST = "hent første bokstav"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "hent bokstav # fra slutten"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "hent bokstav #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "i tekst"; -Blockly.Msg.TEXT_CHARAT_LAST = "hent den siste bokstaven"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "hent en tilfeldig bokstav"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Returnerer bokstaven på angitt plassering."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Legg til et element til teksten."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "føy sammen"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Legg til, fjern eller forandre rekkefølgen for å forandre på denne tekstblokken."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "til bokstav # fra slutten"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "til bokstav #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "til siste bokstav"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "i tekst"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "hent delstreng fra første bokstav"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "hent delstreng fra bokstav # fra slutten"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "hent delstreng fra bokstav #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returnerer den angitte delen av teksten."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "i tekst"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "finn første forekomst av tekst"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "finn siste forekomst av tekst"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returnerer posisjonen for første/siste forekomsten av den første tekst i den andre teksten. Returnerer %1 hvis teksten ikke blir funnet."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 er tom"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returnerer sann hvis den angitte teksten er tom."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "lage tekst med"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Opprett en tekst ved å sette sammen et antall elementer."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "lengden av %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Returnerer antall bokstaver (inkludert mellomrom) i den angitte teksten."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "skriv ut %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Skriv ut angitt tekst, tall eller annet innhold."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Be brukeren om et tall."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Spør brukeren om tekst."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "spør om et tall med en melding"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "spør om tekst med en melding"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "En bokstav, ett ord eller en linje med tekst."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "fjern mellomrom fra begge sider av"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "fjern mellomrom fra venstre side av"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "fjern mellomrom fra høyre side av"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Returner en kopi av teksten med mellomrom fjernet fra en eller begge sidene."; -Blockly.Msg.TODAY = "I dag"; -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "element"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Opprett 'sett %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returnerer verdien av denne variabelen."; -Blockly.Msg.VARIABLES_SET = "sett %1 til %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Opprett 'hent %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Setter verdien av denne variablen lik parameteren."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/nl.js b/backend/_pv_1_3_5/static/blockly/msg/js/nl.js deleted file mode 100755 index 6574d34d6..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/nl.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.nl'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Reactie toevoegen"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Waarde wijzigen:"; -Blockly.Msg.CLEAN_UP = "Blokken opschonen"; -Blockly.Msg.COLLAPSE_ALL = "Blokken samenvouwen"; -Blockly.Msg.COLLAPSE_BLOCK = "Blok samenvouwen"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "kleur 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "kleur 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "verhouding"; -Blockly.Msg.COLOUR_BLEND_TITLE = "mengen"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Mengt twee kleuren samen met een bepaalde verhouding (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://nl.wikipedia.org/wiki/Kleur"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Kies een kleur in het palet."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "willekeurige kleur"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Kies een willekeurige kleur."; -Blockly.Msg.COLOUR_RGB_BLUE = "blauw"; -Blockly.Msg.COLOUR_RGB_GREEN = "groen"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "rood"; -Blockly.Msg.COLOUR_RGB_TITLE = "kleuren met"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Maak een kleur met de opgegeven hoeveelheid rood, groen en blauw. Alle waarden moeten tussen 0 en 100 liggen."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "uit lus breken"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "doorgaan met de volgende iteratie van de lus"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "uit de bovenliggende lus breken"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "De rest van deze lus overslaan en doorgaan met de volgende herhaling."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Waarschuwing: dit blok mag alleen gebruikt worden in een lus."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "voor ieder item %1 in lijst %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Voor ieder item in een lijst, stel de variabele \"%1\" in op het item en voer daarna opdrachten uit."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; -Blockly.Msg.CONTROLS_FOR_TITLE = "rekenen met %1 van %2 tot %3 in stappen van %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Laat de variabele \"%1\" de waarden aannemen van het beginnummer tot het laatste nummer, tellende met het opgegeven interval, en met uitvoering van de opgegeven blokken."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Voeg een voorwaarde toe aan het als-blok."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Voeg een laatste, vang-alles conditie toe aan het als-statement."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Voeg stukken toe, verwijder of wijzig de volgorde om dit \"als\"-blok te wijzigen."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "anders"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "anders als"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "als"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Als een waarde waar is, voer dan opdrachten uit."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Als een waarde waar is, voert dan het eerste blok met opdrachten uit. Voer andere het tweede blok met opdrachten uit."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Als de eerste waarde waar is, voer dan het eerste blok met opdrachten uit. Voer anders, als de tweede waarde waar is, het tweede blok met opdrachten uit."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Als de eerste waarde \"waar\" is, voer dan het eerste blok uit. Voer anders wanneer de tweede waarde \"waar\" is, het tweede blok uit. Als geen van beide waarden waar zijn, voer dan het laatste blok uit."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://nl.wikipedia.org/wiki/Repetitie_(informatica)#For_en_Foreach"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "voer uit"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "%1 keer herhalen"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Voer een aantal opdrachten meerdere keren uit."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "herhalen totdat"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "herhalen zolang"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Terwijl een waarde onwaar is de volgende opdrachten uitvoeren."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Terwijl een waarde waar is de volgende opdrachten uitvoeren."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Alle %1 blokken verwijderen?"; -Blockly.Msg.DELETE_BLOCK = "Blok verwijderen"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "%1 blokken verwijderen"; -Blockly.Msg.DISABLE_BLOCK = "Blok uitschakelen"; -Blockly.Msg.DUPLICATE_BLOCK = "Duplicaat"; -Blockly.Msg.ENABLE_BLOCK = "Blok inschakelen"; -Blockly.Msg.EXPAND_ALL = "Blokken uitvouwen"; -Blockly.Msg.EXPAND_BLOCK = "Blok uitvouwen"; -Blockly.Msg.EXTERNAL_INPUTS = "Externe invoer"; -Blockly.Msg.HELP = "Hulp"; -Blockly.Msg.INLINE_INPUTS = "Inline invoer"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "maak een lege lijst"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Geeft een lijst terug met lengte 0, zonder items"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "lijst"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Voeg stukken toe, verwijder ze of wijzig de volgorde om dit lijstblok aan te passen."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "maak een lijst met"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Voeg iets toe aan de lijst."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Maak een lijst met een willekeurig aantal items."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "eerste"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# van einde"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "haal op"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "haal op en verwijder"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "laatste"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "willekeurig"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "verwijder"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Geeft het eerste item in een lijst terug."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Geeft het item op de opgegeven positie in een lijst."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Geeft het laatste item in een lijst terug."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Geeft een willekeurig item uit een lijst."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Geeft het laatste item in een lijst terug en verwijdert het."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Geeft het item op de opgegeven positie in een lijst terug en verwijdert het."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Geeft het laatste item uit een lijst terug en verwijdert het."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Geeft een willekeurig item in een lijst terug en verwijdert het."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Verwijdert het eerste item in een lijst."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Verwijdert het item op de opgegeven positie in een lijst."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Verwijdert het laatste item uit een lijst."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Verwijdert een willekeurig item uit een lijst."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "naar # vanaf einde"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "naar item"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "naar laatste"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "haal sublijst op vanaf eerste"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "haal sublijst op van positie vanaf einde"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "haal sublijst op vanaf positie"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Maakt een kopie van het opgegeven deel van de lijst."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "Item %1 is het laatste item."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "Item %1 is het eerste item."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "zoek eerste voorkomen van item"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; -Blockly.Msg.LISTS_INDEX_OF_LAST = "zoek laatste voorkomen van item"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Geeft de index terug van het eerste of laatste voorkomen van een item in de lijst. Geeft %1 terug als het item niet is gevonden."; -Blockly.Msg.LISTS_INLIST = "in lijst"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 is leeg"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Geeft waar terug als de lijst leeg is."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; -Blockly.Msg.LISTS_LENGTH_TITLE = "lengte van %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Geeft de lengte van een lijst terug."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg.LISTS_REPEAT_TITLE = "Maak lijst met item %1, %2 keer herhaald"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Maakt een lijst die bestaat uit de opgegeven waarde, het opgegeven aantal keer herhaald."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "als"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "tussenvoegen op"; -Blockly.Msg.LISTS_SET_INDEX_SET = "stel in"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Voegt het item toe aan het begin van de lijst."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Voegt het item op een opgegeven positie in een lijst in."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Voeg het item aan het einde van een lijst toe."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Voegt het item op een willekeurige positie in de lijst in."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Stelt het eerste item in een lijst in."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Stelt het item op de opgegeven positie in de lijst in."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Stelt het laatste item van een lijst in."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Stelt een willekeurig item uit de lijst in."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "oplopend"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "aflopend"; -Blockly.Msg.LISTS_SORT_TITLE = "sorteer %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sorteer een kopie van een lijst."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alfabetisch, negeer hoofd-/kleine letters"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numerieke"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "in alfabetische volgorde"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "lijst maken van tekst"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "tekst maken van lijst"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Lijst van tekstdelen samenvoegen in één stuk tekst, waarbij de tekstdelen gescheiden zijn door een scheidingsteken."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Tekst splitsen in een lijst van teksten op basis van een scheidingsteken."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "met scheidingsteken"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "onwaar"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Geeft \"waar\" of \"onwaar\" terug."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "waar"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://nl.wikipedia.org/wiki/Ongelijkheid_(wiskunde)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Geeft \"waar\", als beide waarden gelijk aan elkaar zijn."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Geeft \"waar\" terug als de eerste invoer meer is dan de tweede invoer."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Geeft \"waar\" terug als de eerste invoer groter is of gelijk aan de tweede invoer."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Geeft \"waar\" als de eerste invoer kleiner is dan de tweede invoer."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Geeft \"waar\" terug als de eerste invoer kleiner of gelijk is aan de tweede invoer."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Geeft \"waar\" terug als de waarden niet gelijk zijn aan elkaar."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; -Blockly.Msg.LOGIC_NEGATE_TITLE = "niet %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Geeft \"waar\" terug als de invoer \"onwaar\" is. Geeft \"onwaar\" als de invoer \"waar\" is."; -Blockly.Msg.LOGIC_NULL = "niets"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Geeft niets terug."; -Blockly.Msg.LOGIC_OPERATION_AND = "en"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; -Blockly.Msg.LOGIC_OPERATION_OR = "of"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Geeft waar als beide waarden waar zijn."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Geeft \"waar\" terug als in ieder geval één van de waarden waar is."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "als onwaar"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "als waar"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Test de voorwaarde in \"test\". Als de voorwaarde \"waar\" is, geef de waarde van \"als waar\" terug; geef anders de waarde van \"als onwaar\" terug."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://nl.wikipedia.org/wiki/Rekenen"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Geeft de som van 2 getallen."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Geeft de gedeelde waarde van twee getallen."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Geeft het verschil van de twee getallen."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Geeft het product terug van de twee getallen."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Geeft het eerste getal tot de macht van het tweede getal."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "%1 wijzigen met %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Voegt een getal toe aan variabele \"%1\"."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://nl.wikipedia.org/wiki/Wiskundige_constante"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Geeft een van de vaak voorkomende constante waardes: π (3.141…), e (2.718…), φ (1.618…), √2 (1.414…), √½ (0.707…), of ∞ (oneindig)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "beperk %1 van minimaal %2 tot maximaal %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Beperk een getal tussen de twee opgegeven limieten (inclusief)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "is deelbaar door"; -Blockly.Msg.MATH_IS_EVEN = "is even"; -Blockly.Msg.MATH_IS_NEGATIVE = "is negatief"; -Blockly.Msg.MATH_IS_ODD = "is oneven"; -Blockly.Msg.MATH_IS_POSITIVE = "is positief"; -Blockly.Msg.MATH_IS_PRIME = "is priemgetal"; -Blockly.Msg.MATH_IS_TOOLTIP = "Test of een getal even, oneven, een priemgetal, geheel, positief of negatief is, of deelbaar is door een bepaald getal. Geeft \"waar\" of \"onwaar\"."; -Blockly.Msg.MATH_IS_WHOLE = "is geheel getal"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://nl.wikipedia.org/wiki/Modulair_rekenen"; -Blockly.Msg.MATH_MODULO_TITLE = "restgetal van %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Geeft het restgetal van het resultaat van de deling van de twee getallen."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://nl.wikipedia.org/wiki/Getal_%28wiskunde%29"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Een getal."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "gemiddelde van lijst"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "hoogste uit lijst"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "mediaan van lijst"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "laagste uit lijst"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "modi van lijst"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "willekeurige item van lijst"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "standaarddeviatie van lijst"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "som van lijst"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Geeft het gemiddelde terug van de numerieke waardes in een lijst."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Geeft het grootste getal in een lijst."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Geeft de mediaan in de lijst."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Geeft het kleinste getal uit een lijst."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Geeft een lijst van de meest voorkomende onderdelen in de lijst."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Geeft een willekeurig item uit de lijst terug."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Geeft de standaardafwijking van de lijst."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Geeft de som van alle getallen in de lijst."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://nl.wikipedia.org/wiki/Toevalsgenerator"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "willekeurige fractie"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Geeft een willekeurige fractie tussen 0.0 (inclusief) en 1.0 (exclusief)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://nl.wikipedia.org/wiki/Toevalsgenerator"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "willekeurig geheel getal van %1 tot %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Geeft een willekeurig getal tussen de 2 opgegeven limieten in, inclusief."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://nl.wikipedia.org/wiki/Afronden"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "afronden"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "naar beneden afronden"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "omhoog afronden"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Rondt een getal af omhoog of naar beneden."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://nl.wikipedia.org/wiki/Vierkantswortel"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absoluut"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "wortel"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Geeft de absolute waarde van een getal."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Geeft e tot de macht van een getal."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Geeft het natuurlijk logaritme van een getal."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Geeft het logaritme basis 10 van een getal."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Geeft de negatief van een getal."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Geeft 10 tot de macht van een getal."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Geeft de wortel van een getal."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "acos"; -Blockly.Msg.MATH_TRIG_ASIN = "asin"; -Blockly.Msg.MATH_TRIG_ATAN = "arctan"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://nl.wikipedia.org/wiki/Goniometrische_functie"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tan"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Geeft de arccosinus van een getal."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Geeft de arcsinus van een getal."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Geeft de arctangens van een getal."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Geeft de cosinus van een graad (geen radialen)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Geeft de sinus van een graad (geen radialen)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Geeft de tangens van een graad (geen radialen)."; -Blockly.Msg.NEW_VARIABLE = "Nieuwe variabele..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Nieuwe variabelenaam:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "statements toestaan"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "met:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://nl.wikipedia.org/wiki/Subprogramma"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Voer de door de gebruiker gedefinieerde functie \"%1\" uit."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://nl.wikipedia.org/wiki/Subprogramma"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Voer de door de gebruiker gedefinieerde functie \"%1\" uit en gebruik de uitvoer."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "met:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Maak \"%1\""; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Deze functie beschrijven..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://nl.wikipedia.org/wiki/Subprogramma"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "doe iets"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "om"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Maakt een functie zonder uitvoer."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://nl.wikipedia.org/wiki/Subprogramma"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "uitvoeren"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Maakt een functie met een uitvoer."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Waarschuwing: deze functie heeft parameters met dezelfde naam."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Accentueer functiedefinitie"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Als de eerste waarde \"waar\" is, geef dan de tweede waarde terug."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Waarschuwing: dit blok mag alleen gebruikt worden binnen de definitie van een functie."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "invoernaam:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Een invoer aan de functie toevoegen."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "ingangen"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Invoer van deze functie toevoegen, verwijderen of herordenen."; -Blockly.Msg.REDO = "Opnieuw"; -Blockly.Msg.REMOVE_COMMENT = "Opmerking verwijderen"; -Blockly.Msg.RENAME_VARIABLE = "Variabele hernoemen..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Alle variabelen \"%1\" hernoemen naar:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "tekst"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; -Blockly.Msg.TEXT_APPEND_TO = "voeg toe aan"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Voeg tekst toe aan de variabele \"%1\"."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "naar kleine letters"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "naar Hoofdletter Per Woord"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "naar HOOFDLETTERS"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Geef een kopie van de tekst met veranderde hoofdletters terug."; -Blockly.Msg.TEXT_CHARAT_FIRST = "haal eerste letter op"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "haal letter # op vanaf einde"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "haal letter # op"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "in tekst"; -Blockly.Msg.TEXT_CHARAT_LAST = "haal laatste letter op"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "haal willekeurige letter op"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Geeft de letter op de opgegeven positie terug."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Voegt een item aan de tekst toe."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "samenvoegen"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Toevoegen, verwijderen of volgorde wijzigen van secties om dit tekstblok opnieuw in te stellen."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "van letter # tot einde"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "naar letter #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "naar laatste letter"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "in tekst"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "haal subtekst op van eerste letter"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "haal subtekst op vanaf letter # vanaf einde"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "haal subtekst op vanaf letter #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Geeft het opgegeven onderdeel van de tekst terug."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "in tekst"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "zoek eerste voorkomen van tekst"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "zoek het laatste voorkomen van tekst"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Geeft de index terug van de eerste/laatste aanwezigheid van de eerste tekst in de tweede tekst. Geeft %1 terug als de tekst niet gevonden is."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 is leeg"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Geeft \"waar\" terug, als de opgegeven tekst leeg is."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "maak tekst met"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Maakt een stuk tekst door één of meer items samen te voegen."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; -Blockly.Msg.TEXT_LENGTH_TITLE = "lengte van %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Geeft het aantal tekens terug (inclusief spaties) in de opgegeven tekst."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; -Blockly.Msg.TEXT_PRINT_TITLE = "tekst weergeven: %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Drukt de opgegeven tekst, getal of een andere waarde af."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Vraagt de gebruiker om een getal in te voeren."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Vraagt de gebruiker om invoer."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "vraagt de gebruiker om een getal met de tekst"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "vraagt om invoer met bericht"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://nl.wikipedia.org/wiki/String_%28informatica%29"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Een letter, woord of een regel tekst."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "spaties van beide kanten afhalen van"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "spaties van de linkerkant verwijderen van"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "spaties van de rechterkant verwijderen van"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Geeft een kopie van de tekst met verwijderde spaties van één of beide kanten."; -Blockly.Msg.TODAY = "Vandaag"; -Blockly.Msg.UNDO = "Ongedaan maken"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "item"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Maak \"verander %1\""; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Geeft de waarde van deze variabele."; -Blockly.Msg.VARIABLES_SET = "stel %1 in op %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Maak 'opvragen van %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Verandert de waarde van de variabele naar de waarde van de invoer."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/oc.js b/backend/_pv_1_3_5/static/blockly/msg/js/oc.js deleted file mode 100755 index 5e682d070..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/oc.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.oc'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Apondre un comentari"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Modificar la valor :"; -Blockly.Msg.CLEAN_UP = "Clean up Blocks"; // untranslated -Blockly.Msg.COLLAPSE_ALL = "Redusir los blòts"; -Blockly.Msg.COLLAPSE_BLOCK = "Redusir lo blòt"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "color 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "color 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "ratio"; -Blockly.Msg.COLOUR_BLEND_TITLE = "mesclar"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Blends two colours together with a given ratio (0.0 - 1.0)."; // untranslated -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://oc.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Choose a colour from the palette."; // untranslated -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "color aleatòria"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Causir una color a l'azard."; -Blockly.Msg.COLOUR_RGB_BLUE = "blau"; -Blockly.Msg.COLOUR_RGB_GREEN = "verd"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "roge"; -Blockly.Msg.COLOUR_RGB_TITLE = "colorar amb"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Create a colour with the specified amount of red, green, and blue. All values must be between 0 and 100."; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "break out of loop"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "continue with next iteration of loop"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Break out of the containing loop."; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Skip the rest of this loop, and continue with the next iteration."; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Warning: This block may only be used within a loop."; // untranslated -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "per cada element %1 dins la lista %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "For each item in a list, set the variable '%1' to the item, and then do some statements."; // untranslated -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "comptar amb %1 de %2 a %3 per %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Have the variable '%1' take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks."; // untranslated -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Add a condition to the if block."; // untranslated -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Add a final, catch-all condition to the if block."; // untranslated -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Add, remove, or reorder sections to reconfigure this if block."; // untranslated -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "siquenon"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "siquenon se"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "se"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "If a value is true, then do some statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "If a value is true, then do the first block of statements. Otherwise, do the second block of statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements."; // untranslated -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://oc.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "far"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "repetir %1 còps"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Do some statements several times."; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "repetir fins a"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "repetir tant que"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "While a value is false, then do some statements."; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "While a value is true, then do some statements."; // untranslated -Blockly.Msg.DELETE_ALL_BLOCKS = "Suprimir totes los %1 blòts ?"; -Blockly.Msg.DELETE_BLOCK = "Suprimir lo blòt"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Suprimir %1 blòts"; -Blockly.Msg.DISABLE_BLOCK = "Desactivar lo blòt"; -Blockly.Msg.DUPLICATE_BLOCK = "Duplicar"; -Blockly.Msg.ENABLE_BLOCK = "Activar lo blòt"; -Blockly.Msg.EXPAND_ALL = "Desvolopar los blòts"; -Blockly.Msg.EXPAND_BLOCK = "Desvolopar lo blòt"; -Blockly.Msg.EXTERNAL_INPUTS = "Entradas extèrnas"; -Blockly.Msg.HELP = "Ajuda"; -Blockly.Msg.INLINE_INPUTS = "Entradas en linha"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "create empty list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Returns a list, of length 0, containing no data records"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "lista"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Add, remove, or reorder sections to reconfigure this list block."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "crear una lista amb"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Add an item to the list."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Create a list with any number of items."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_FIRST = "primièr"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# dempuèi la fin"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "obténer"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "obténer e suprimir"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "darrièr"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "aleatòri"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "suprimit"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Removes and returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Removes and returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Removes and returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Removes and returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Removes the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Removes the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Removes the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Removes a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "fins a # dempuèi la fin"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "fins a #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "fins a la fin"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "get sub-list from first"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "get sub-list from # from end"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "get sub-list from #"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Creates a copy of the specified portion of a list."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 is the last item."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 is the first item."; // untranslated -Blockly.Msg.LISTS_INDEX_OF_FIRST = "find first occurrence of item"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "find last occurrence of item"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Returns the index of the first/last occurrence of the item in the list. Returns %1 if item is not found."; // untranslated -Blockly.Msg.LISTS_INLIST = "dins la lista"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 is empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Returns true if the list is empty."; // untranslated -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "length of %1"; // untranslated -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Returns the length of a list."; // untranslated -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "create list with item %1 repeated %2 times"; // untranslated -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Creates a list consisting of the given value repeated the specified number of times."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "coma"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "inserir en"; -Blockly.Msg.LISTS_SET_INDEX_SET = "metre"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserts the item at the start of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Inserts the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Append the item to the end of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Inserts the item randomly in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Sets the first item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Sets the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Sets the last item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Sets a random item in a list."; // untranslated -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "make list from text"; // untranslated -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "make text from list"; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "fals"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Returns either true or false."; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "verai"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Return true if both inputs equal each other."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Return true if the first input is greater than the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Return true if the first input is greater than or equal to the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Return true if the first input is smaller than the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Return true if the first input is smaller than or equal to the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Return true if both inputs are not equal to each other."; // untranslated -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "pas %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Returns true if the input is false. Returns false if the input is true."; // untranslated -Blockly.Msg.LOGIC_NULL = "nul"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Renvia nul."; -Blockly.Msg.LOGIC_OPERATION_AND = "e"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "o"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Return true if both inputs are true."; // untranslated -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Return true if at least one of the inputs is true."; // untranslated -Blockly.Msg.LOGIC_TERNARY_CONDITION = "tèst"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "se fals"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "se verai"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value."; // untranslated -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://oc.wikipedia.org/wiki/Aritmetica"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Return the sum of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Return the quotient of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Return the difference of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Return the product of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Return the first number raised to the power of the second number."; // untranslated -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; // untranslated -Blockly.Msg.MATH_CHANGE_TITLE = "incrementar %1 per %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Add a number to variable '%1'."; // untranslated -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; // untranslated -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; // untranslated -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "constrain %1 low %2 high %3"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Constrain a number to be between the specified limits (inclusive)."; // untranslated -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "es devesible per"; -Blockly.Msg.MATH_IS_EVEN = "es par"; -Blockly.Msg.MATH_IS_NEGATIVE = "es negatiu"; -Blockly.Msg.MATH_IS_ODD = "es impar"; -Blockly.Msg.MATH_IS_POSITIVE = "es positiu"; -Blockly.Msg.MATH_IS_PRIME = "es primièr"; -Blockly.Msg.MATH_IS_TOOLTIP = "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false."; // untranslated -Blockly.Msg.MATH_IS_WHOLE = "es entièr"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; // untranslated -Blockly.Msg.MATH_MODULO_TITLE = "remainder of %1 ÷ %2"; // untranslated -Blockly.Msg.MATH_MODULO_TOOLTIP = "Return the remainder from dividing the two numbers."; // untranslated -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://oc.wikipedia.org/wiki/Nombre"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Un nombre."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "mejana de la lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "maximum de la lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "mediana de la lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "minimum de la lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "modes of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "random item of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "standard deviation of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "soma de la lista"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Return the average (arithmetic mean) of the numeric values in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Return the largest number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Return the median number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Return the smallest number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Return a list of the most common item(s) in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Return a random element from the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Return the standard deviation of the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Return the sum of all the numbers in the list."; // untranslated -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "random fraction"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive)."; // untranslated -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TITLE = "random integer from %1 to %2"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Return a random integer between the two specified limits, inclusive."; // untranslated -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; // untranslated -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "arredondir"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "arredondir a l’inferior"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "arredondir al superior"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Round a number up or down."; // untranslated -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; // untranslated -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absolut"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "raiç carrada"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Return the absolute value of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Return e to the power of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Return the natural logarithm of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Return the base 10 logarithm of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Return the negation of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Return 10 to the power of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Return the square root of a number."; // untranslated -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; // untranslated -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Return the arccosine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Return the arcsine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Return the arctangent of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Return the cosine of a degree (not radian)."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Return the sine of a degree (not radian)."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Return the tangent of a degree (not radian)."; // untranslated -Blockly.Msg.NEW_VARIABLE = "Variabla novèla…"; -Blockly.Msg.NEW_VARIABLE_TITLE = "Nom de la novèla variabla :"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "allow statements"; // untranslated -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "amb :"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Run the user-defined function '%1'."; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Run the user-defined function '%1' and use its output."; // untranslated -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "amb :"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Crear '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "far quicòm"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "a"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Creates a function with no output."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "retorn"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Creates a function with an output."; // untranslated -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Warning: This function has duplicate parameters."; // untranslated -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Highlight function definition"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "If a value is true, then return a second value."; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Warning: This block may be used only within a function definition."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "nom de l’entrada :"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Add an input to the function."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "entradas"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Add, remove, or reorder inputs to this function."; // untranslated -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "Suprimir un comentari"; -Blockly.Msg.RENAME_VARIABLE = "Renomenar la variabla…"; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Rename all '%1' variables to:"; // untranslated -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "apondre lo tèxte"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "a"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Append some text to variable '%1'."; // untranslated -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "en minusculas"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "to Title Case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "en MAJUSCULAS"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; // untranslated -Blockly.Msg.TEXT_CHARAT_FIRST = "obténer la primièra letra"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "obténer la letra # dempuèi la fin"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "obténer la letra #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "dins lo tèxte"; -Blockly.Msg.TEXT_CHARAT_LAST = "obténer la darrièra letra"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "obténer una letra a l'azard"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Renvia la letra a la posicion indicada."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Add an item to the text."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "join"; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Add, remove, or reorder sections to reconfigure this text block."; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "to letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "fins a la letra #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "to last letter"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "dins lo tèxte"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "get substring from first letter"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "get substring from letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "get substring from letter #"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returns a specified portion of the text."; // untranslated -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "dins lo tèxte"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "find first occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "find last occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found."; // untranslated -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 es void"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returns true if the provided text is empty."; // untranslated -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "create text with"; // untranslated -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Create a piece of text by joining together any number of items."; // untranslated -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "longor de %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Returns the number of letters (including spaces) in the provided text."; // untranslated -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "afichar %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Print the specified text, number or other value."; // untranslated -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Prompt for user for a number."; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Prompt for user for some text."; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "prompt for number with message"; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "prompt for text with message"; // untranslated -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; // untranslated -Blockly.Msg.TEXT_TEXT_TOOLTIP = "A letter, word, or line of text."; // untranslated -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "trim spaces from both sides of"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "trim spaces from left side of"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "trim spaces from right side of"; // untranslated -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Return a copy of the text with spaces removed from one or both ends."; // untranslated -Blockly.Msg.TODAY = "Today"; // untranslated -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "element"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Crear 'fixar %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returns the value of this variable."; // untranslated -Blockly.Msg.VARIABLES_SET = "fixar %1 a %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Create 'get %1'"; // untranslated -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Sets this variable to be equal to the input."; // untranslated -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/pl.js b/backend/_pv_1_3_5/static/blockly/msg/js/pl.js deleted file mode 100755 index 44da10c70..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/pl.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.pl'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Dodaj komentarz"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Zmień wartość:"; -Blockly.Msg.CLEAN_UP = "Uporządkuj bloki"; -Blockly.Msg.COLLAPSE_ALL = "Zwiń bloki"; -Blockly.Msg.COLLAPSE_BLOCK = "Zwiń blok"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "kolor 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "kolor 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "proporcja"; -Blockly.Msg.COLOUR_BLEND_TITLE = "wymieszaj"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Miesza dwa kolory w danej proporcji (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Wybierz kolor z palety."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "losowy kolor"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Wybierz kolor w sposób losowy."; -Blockly.Msg.COLOUR_RGB_BLUE = "niebieski"; -Blockly.Msg.COLOUR_RGB_GREEN = "zielony"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "czerwony"; -Blockly.Msg.COLOUR_RGB_TITLE = "kolor z"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Połącz czerwony, zielony i niebieski w odpowiednich proporcjach, tak aby powstał nowy kolor. Zawartość każdego z nich określa liczba z przedziału od 0 do 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "wyjdź z pętli"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "przejdź do kolejnej iteracji pętli"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Wyjdź z zawierającej pętli."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Pomiń resztę pętli i kontynuuj w kolejnej iteracji."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Uwaga: Ten blok może być użyty tylko w pętli."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "dla każdego elementu %1 na liście %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Dla każdego elementu listy ustaw zmienną %1 na ten element, a następnie wykonaj kilka instrukcji."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "licz z %1 od %2 do %3 co %4 (wartość kroku)"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Przypisuje zmiennej %1 wartości od numeru startowego do numeru końcowego, licząc co określony interwał, wykonując określone bloki."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Dodaj warunek do bloku „jeśli”."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Dodaj ostatni warunek do bloku „jeśli”, gdy żaden wcześniejszy nie był spełniony."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Dodaj, usuń lub zmień kolejność bloków, żeby zmodyfikować ten blok „jeśli”."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "w przeciwnym razie"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "w przeciwnym razie, jeśli"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "jeśli"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Jeśli wartość jest prawdziwa, to wykonaj kilka instrukcji."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Jeśli wartość jest prawdziwa, to wykonaj pierwszy blok instrukcji. W przeciwnym razie, wykonaj drugi blok instrukcji."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Jeśli pierwsza wartość jest prawdziwa, to wykonaj pierwszy blok instrukcji. W przeciwnym razie, jeśli druga wartość jest prawdziwa, to wykonaj drugi blok instrukcji."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Jeśli pierwsza wartość jest prawdziwa, wykonaj pierwszy blok instrukcji. W przeciwnym razie jeśli druga wartość jest prawdziwa, wykonaj drugi blok instrukcji. Jeżeli żadna z wartości nie jest prawdziwa, wykonaj ostatni blok instrukcji."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "wykonaj"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "powtórz %1 razy"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Wykonaj niektóre instrukcje kilka razy."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "powtarzaj aż"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "powtarzaj dopóki"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Gdy wartość jest nieprawdziwa, wykonaj kilka instrukcji."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Gdy wartość jest prawdziwa, wykonaj kilka instrukcji."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Usunąć wszystkie %1 bloki(ów)?"; -Blockly.Msg.DELETE_BLOCK = "Usuń blok"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Usuń %1 bloki(ów)"; -Blockly.Msg.DISABLE_BLOCK = "Wyłącz blok"; -Blockly.Msg.DUPLICATE_BLOCK = "Duplikuj"; -Blockly.Msg.ENABLE_BLOCK = "Włącz blok"; -Blockly.Msg.EXPAND_ALL = "Rozwiń bloki"; -Blockly.Msg.EXPAND_BLOCK = "Rozwiń blok"; -Blockly.Msg.EXTERNAL_INPUTS = "Zewnętrzne wejścia"; -Blockly.Msg.HELP = "Pomoc"; -Blockly.Msg.INLINE_INPUTS = "Wbudowane wejścia"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "utwórz pustą listę"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Zwraca listę, o długości 0, nie zawierającą rekordów z danymi"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "lista"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Dodaj, usuń lub zmień kolejność sekcji żeby skonfigurować ten blok listy."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "Tworzenie listy z"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Dodaj element do listy."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Utwórz listę z dowolną ilością elementów."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "pierwszy"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# od końca"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "pobierz"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "Pobierz i usuń"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "ostatni"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "losowy"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "usuń"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Zwraca pierwszy element z listy."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Zwraca element z konkretnej pozycji na liście."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Zwraca ostatni element z listy."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Zwraca losowy element z listy."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Usuwa i zwraca pierwszy element z listy."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Usuwa i zwraca element z określonej pozycji na liście."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Usuwa i zwraca ostatni element z listy."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Usuwa i zwraca losowy element z listy."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Usuwa pierwszy element z listy."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Usuwa element z określonej pozycji na liście."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Usuwa ostatni element z listy."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Usuwa losowy element z listy."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "do # od końca"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "do #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "do ostatniego"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "Pobierz listę podrzędną z pierwszego"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "Pobierz listę podrzędną z # od końca"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "Pobierz listę podrzędną z #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Tworzy kopię z określoną część listy."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 to ostatni element."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 to pierwszy element."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "znaleźć pierwsze wystąpienie elementu"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "znajduje ostatanie wystąpienie elementu"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Zwraca indeks pierwszego/ostatniego wystąpienia elementu na liście. Zwraca wartość %1, jeśli tekst nie zostanie znaleziony."; -Blockly.Msg.LISTS_INLIST = "na liście"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 jest pusty"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Zwraca \"prawda\" jeśli lista jest pusta."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "długość %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Zwraca długość listy."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "stwórz listę, powtarzając element %1 %2 razy"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Tworzy listę składającą się z podanej wartości powtórzonej odpowiednią liczbę razy."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "jako"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "wstaw w"; -Blockly.Msg.LISTS_SET_INDEX_SET = "ustaw"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Wstawia element na początku listy."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Wstawia element w odpowiednim miejscu na liście."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Dodaj element na koniec listy."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Wstawia element w losowym miejscu na liście."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Ustawia pierwszy element na liście."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Ustawia element w określonym miejscu na liście."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Ustawia ostatni element na liście."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Ustawia losowy element na liście."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "rosnąco"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "malejąco"; -Blockly.Msg.LISTS_SORT_TITLE = "sortuj %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sortuj kopię listy."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alfabetycznie, bez uwzględniania wielkości liter"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numerycznie"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alfabetycznie"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "stwórz listę z tekstu"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "stwórz tekst z listy"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Łączy listę tekstów w jeden tekst, rozdzielany separatorem."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Rozdziela tekst na listę mniejszych tekstów, dzieląc na każdym separatorze."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "z separatorem"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "fałsz"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Zwraca 'prawda' lub 'fałsz'."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "prawda"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://pl.wikipedia.org/wiki/Nierówność"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Zwróć \"prawda\", jeśli oba wejścia są sobie równe."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Zwróć \"prawda\" jeśli pierwsze wejście jest większe od drugiego."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Zwróć \"prawda\", jeśli pierwsze wejście jest większe lub równe drugiemu."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Zwróć \"prawda\" jeśli pierwsze wejście jest większe od drugiego."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Zwróć \"prawda\", jeśli pierwsze wejście jest większe lub równe drugiemu."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Zwróć \"prawda\", jeśli oba wejścia są sobie nierówne."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "nie %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Zwraca \"prawda\", jeśli dane wejściowe są fałszywe. Zwraca \"fałsz\", jeśli dana wejściowa jest prawdziwa."; -Blockly.Msg.LOGIC_NULL = "nic"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Zwraca nic."; -Blockly.Msg.LOGIC_OPERATION_AND = "i"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "lub"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Zwróć \"prawda\" jeśli oba dane elementy mają wartość \"prawda\"."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Zwróć \"prawda\" jeśli co najmniej jeden dany element ma wartość \"prawda\"."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "jeśli fałsz"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "jeśli prawda"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Sprawdź warunek w „test”. Jeśli warunek jest prawdziwy, to zwróci „jeśli prawda”; jeśli nie jest prawdziwy to zwróci „jeśli fałsz”."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://pl.wikipedia.org/wiki/Arytmetyka"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Zwróć sumę dwóch liczb."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Zwróć iloraz dwóch liczb."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Zwróć różnicę dwóch liczb."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Zwróć iloczyn dwóch liczb."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Zwróć pierwszą liczbę podniesioną do potęgi o wykładniku drugiej liczby."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "zmień %1 o %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Dodaj liczbę do zmiennej '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://pl.wikipedia.org/wiki/Stała_(matematyka)"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Zwróć jedną wspólną stałą: π (3.141), e (2.718...), φ (1.618...), sqrt(2) (1.414...), sqrt(½) (0.707...) lub ∞ (nieskończoność)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "ogranicz %1 z dołu %2 z góry %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Ogranicz liczbę, aby była w określonych granicach (włącznie)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "/"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "jest podzielna przez"; -Blockly.Msg.MATH_IS_EVEN = "jest parzysta"; -Blockly.Msg.MATH_IS_NEGATIVE = "jest ujemna"; -Blockly.Msg.MATH_IS_ODD = "jest nieparzysta"; -Blockly.Msg.MATH_IS_POSITIVE = "jest dodatnia"; -Blockly.Msg.MATH_IS_PRIME = "jest liczbą pierwszą"; -Blockly.Msg.MATH_IS_TOOLTIP = "Sprawdź, czy liczba jest parzysta, nieparzysta, pierwsza, całkowita, dodatnia, ujemna, lub czy jest podzielna przez podaną liczbę. Zwraca wartość \"prawda\" lub \"fałsz\"."; -Blockly.Msg.MATH_IS_WHOLE = "jest liczbą całkowitą"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://pl.wikipedia.org/wiki/Modulo"; -Blockly.Msg.MATH_MODULO_TITLE = "reszta z dzielenia %1 przez %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Zwróć resztę z dzielenia dwóch liczb przez siebie."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Liczba."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "średnia elementów listy"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "maksymalna wartość z listy"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "mediana listy"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "minimalna wartość z listy"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "dominanty listy"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "losowy element z listy"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "odchylenie standardowe listy"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "suma elementów listy"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Zwróć średnią (średnią arytmetyczną) wartości liczbowych z listy."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Zwróć największą liczbę w liście."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Zwróć medianę listy."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Zwróć najmniejszą liczbę w liście."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Zwróć listę najczęściej występujących elementów w liście."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Zwróć losowy element z listy."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Zwróć odchylenie standardowe listy."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Zwróć sumę wszystkich liczb z listy."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "losowy ułamek"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Zwróć losowy ułamek między 0.0 (włącznie), a 1.0 (wyłącznie)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "losowa liczba całkowita od %1 do %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Zwróć losową liczbę całkowitą w ramach dwóch wyznaczonych granic, włącznie."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://pl.wikipedia.org/wiki/Zaokrąglanie"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "zaokrąglij"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "zaokrąglij w dół"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "zaokrąglij w górę"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Zaokrąglij w górę lub w dół."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://pl.wikipedia.org/wiki/Pierwiastek_kwadratowy"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "wartość bezwzględna"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "pierwiastek kwadratowy"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Zwróć wartość bezwzględną danej liczby."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Zwróć e do potęgi danej liczby."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Zwróć logarytm naturalny danej liczby."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Zwraca logarytm dziesiętny danej liczby."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Zwróć negację danej liczby."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Zwróć 10 do potęgi danej liczby."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Zwróć pierwiastek kwadratowy danej liczby."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "arccos"; -Blockly.Msg.MATH_TRIG_ASIN = "arcsin"; -Blockly.Msg.MATH_TRIG_ATAN = "arctg"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://pl.wikipedia.org/wiki/Funkcje_trygonometryczne"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tg"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Zwróć arcus cosinus danej liczby."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Zwróć arcus sinus danej liczby."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Zwróć arcus tangens danej liczby."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Zwróć wartość cosinusa o stopniu (nie w radianach)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Zwróć wartość sinusa o stopniu (nie w radianach)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Zwróć tangens o stopniu (nie w radianach)."; -Blockly.Msg.NEW_VARIABLE = "Nowa zmienna..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Nowa nazwa zmiennej:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "zezwól na instrukcje"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "z:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://pl.wikipedia.org/wiki/Podprogram"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Uruchom funkcję zdefiniowaną przez użytkownika '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://pl.wikipedia.org/wiki/Podprogram"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Uruchom funkcję zdefiniowaną przez użytkownika '%1' i skorzystaj z jej wyniku."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "z:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Stwórz '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Opisz tę funkcję..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "zrób coś"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "do"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Tworzy funkcję bez wyniku."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "zwróć"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Tworzy funkcję z wynikiem."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Uwaga: Ta funkcja ma powtórzone parametry."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Podświetl definicję funkcji"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Jeśli wartość jest prawdziwa, zwróć drugą wartość."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Uwaga: Ten blok może być używany tylko w definicji funkcji."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "nazwa wejścia:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Dodaj dane wejściowe do funkcji."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "wejścia"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Dodaj, usuń lub zmień kolejność danych wejściowych dla tej funkcji."; -Blockly.Msg.REDO = "Ponów"; -Blockly.Msg.REMOVE_COMMENT = "Usuń komentarz"; -Blockly.Msg.RENAME_VARIABLE = "Zmień nazwę zmiennej..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Zmień nazwy wszystkich '%1' zmiennych na:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "dołącz tekst"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "do"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Dołącz tekst do zmiennej '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "zmień na małe litery"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "zmień na od Wielkich Liter"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "zmień na WIELKIE LITERY"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Zwraca kopię tekstu z inną wielkością liter."; -Blockly.Msg.TEXT_CHARAT_FIRST = "pobierz pierwszą literę"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "pobierz literę # od końca"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "pobierz literę #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "z tekstu"; -Blockly.Msg.TEXT_CHARAT_LAST = "pobierz ostatnią literę"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "pobierz losową literę"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Zwraca literę z określonej pozycji."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Dodaj element do tekstu."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "połącz"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Dodaj, usuń lub zmień kolejność sekcji, aby zmodyfikować blok tekstowy."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "do # litery od końca"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "do # litery"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "do ostatniej litery"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "w tekście"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "pobierz podciąg od pierwszej litery"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "pobierz podciąg od # litery od końca"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "pobierz podciąg od # litery"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Zwraca określoną część tekstu."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "w tekście"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "znajdź pierwsze wystąpienie tekstu"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "znajdź ostatnie wystąpienie tekstu"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Zwraca indeks pierwszego/ostatniego wystąpienia pierwszego tekstu w drugim tekście. Zwraca wartość %1, jeśli tekst nie został znaleziony."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 jest pusty"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Zwraca prawda (true), jeśli podany tekst jest pusty."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "utwórz tekst z"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Tworzy fragment tekstu, łącząc ze sobą dowolną liczbę tekstów."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "długość %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Zwraca liczbę liter (łącznie ze spacjami) w podanym tekście."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "wydrukuj %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Drukuj określony tekst, liczbę lub inną wartość."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Zapytaj użytkownika o liczbę."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Zapytaj użytkownika o jakiś tekst."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "poproś o liczbę z tą wiadomością"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "poproś o tekst z tą wiadomością"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://pl.wikipedia.org/wiki/Tekstowy_typ_danych"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Litera, wyraz lub linia tekstu."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "usuń spacje po obu stronach"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "usuń spacje z lewej strony"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "usuń spacje z prawej strony"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Zwraca kopię tekstu z usuniętymi spacjami z jednego lub z obu końców tekstu."; -Blockly.Msg.TODAY = "Dzisiaj"; -Blockly.Msg.UNDO = "Cofnij"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "element"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Utwórz blok 'ustaw %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Zwraca wartość tej zmiennej."; -Blockly.Msg.VARIABLES_SET = "przypisz %1 wartość %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Utwórz blok 'pobierz %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Nadaj tej zmiennej wartość."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/pms.js b/backend/_pv_1_3_5/static/blockly/msg/js/pms.js deleted file mode 100755 index a1cf30f92..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/pms.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.pms'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Gionté un coment"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Modifiché ël valor:"; -Blockly.Msg.CLEAN_UP = "Dëscancelé ij blòch"; -Blockly.Msg.COLLAPSE_ALL = "Arduve ij blòch"; -Blockly.Msg.COLLAPSE_BLOCK = "Arduve ël blòch"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "color 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "color 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "rapòrt"; -Blockly.Msg.COLOUR_BLEND_TITLE = "mës-cé"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "A mës-cia doi color ansema con un rapòrt dàit (0,0 - 1,0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Serne un color ant la taulòssa."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "color a asar"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Serne un color a asar."; -Blockly.Msg.COLOUR_RGB_BLUE = "bleu"; -Blockly.Msg.COLOUR_RGB_GREEN = "verd"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "ross"; -Blockly.Msg.COLOUR_RGB_TITLE = "coloré con"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Creé un color con la quantità spessificà ëd ross, verd e bleu. Tuti ij valor a devo esse antra 0 e 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "seurte da la liassa"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "continué con l'iterassion sucessiva dla liassa"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Seurte da la liassa anglobanta."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Sauté ël rest ëd sa liassa, e continué con l'iterassion apress."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Atension: Ës blòch a peul mach esse dovrà andrinta a na liassa."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "për minca n'element %1 ant la lista %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Për minca element an na lista, dé ël valor ëd l'element a la variàbil '%1', peui eseguì chèiche anstrussion."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "conté con %1 da %2 a %3 për %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Fé an manera che la variàbil \"%1\" a pija ij valor dal nùmer inissial fin-a al nùmer final, an contand për l'antërval ëspessificà, e eseguì ij bloch ëspessificà."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Gionté na condission al blòch si."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Gionté na condission final ch'a cheuj tut al blòch si."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Gionté, gavé o riordiné le session për cinfiguré torna ës blòch si."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "dësnò"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "dësnò si"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "si"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Si un valor a l'é ver, antlora eseguì chèiche anstrussion."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Si un valor a l'é ver, antlora eseguì ël prim blòch d'anstrussion. Dësnò, eseguì ël second blòch d'anstrussion."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Si ël prim valor a l'é ver, antlora fé andé ël prim blòch d'anstrussion. Dësnò, si ël second valor a l'é ver, fé andé ël second blòch d'anstrussion."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Si ël prim valor a l'é ver, antlora fé andé ël prim blòch d'anstrussion. Dësnò, si ël second valor a l'é ver, fé andé ël second blòcj d'anstrussion. Si gnun dij valor a l'é ver, fé andé l'ùltim blòch d'anstrussion."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "fé"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "arpete %1 vire"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Eseguì chèiche anstrussion vàire vire."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "arpete fin-a a"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "arpete antramentre che"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Cand un valor a l'é fàuss, eseguì chèiche anstrussion."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Cand un valor a l'é ver, eseguì chèiche anstrussion."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Scancelé tuti ij %1 blòch?"; -Blockly.Msg.DELETE_BLOCK = "Scancelé ël blòch"; -Blockly.Msg.DELETE_VARIABLE = "Eliminé la variàbil '%1'"; -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Eliminé %1 utilisassion ëd la variàbil '%2'?"; -Blockly.Msg.DELETE_X_BLOCKS = "Scancelé %1 blòch"; -Blockly.Msg.DISABLE_BLOCK = "Disativé ël blòch"; -Blockly.Msg.DUPLICATE_BLOCK = "Dupliché"; -Blockly.Msg.ENABLE_BLOCK = "Ativé ël blòch"; -Blockly.Msg.EXPAND_ALL = "Dësvlupé ij blòch"; -Blockly.Msg.EXPAND_BLOCK = "Dësvlupé ël blòch"; -Blockly.Msg.EXTERNAL_INPUTS = "Imission esterne"; -Blockly.Msg.HELP = "Agiut"; -Blockly.Msg.INLINE_INPUTS = "Imission an linia"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "creé na lista veuida"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Smon-e na lista, ëd longheur 0, ch'a conten gnun-a argistrassion"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "lista"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Gionté, gavé o riordiné le session për configuré torna cost blòch ëd lista."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "creé na lista con"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Gionté n'element a la lista."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Creé na lista con un nùmer qualsëssìa d'element."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "prim"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# da la fin"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "oten-e"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "oten-e e eliminé"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "ùltim"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "a l'ancàpit"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "eliminé"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "A smon ël prim element an na lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "A smon l'element a la posission ëspessificà an na lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "A smon l'ùltim element an na lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "A smon n'element a l'ancàpit an na lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "A gava e a smon ël prim element an na lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "A gava e a smon l'element a la posission ëspessificà an na lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "A gava e a smon l'ùltim element an na lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "A gava e a smon n'element a l'ancàpit an na lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "A gava ël prim element an na lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "A gava l'element a la posission ëspessificà an na lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "A gava l'ùltim element an na lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "A gava n'element a l'ancàpit da na lista."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "fin-a a # da la fin"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "fin-a a #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "fin-a a l'ùltim"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "oten-e la sot-lista dal prim"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "oten-e la sot-lista da # da la fin"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "oten-e la sot-lista da #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "A crea na còpia dël tòch ëspessificà ëd na lista."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 a l'é l'ùltim element."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 a l'é ël prim element."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "trové la prima ocorensa dl'element"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "trové l'ùltima ocorensa dl'element"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "A smon l'ìndes ëd la prima/ùltima ocorensa dl'element ant la lista. A smon %1 se l'element a l'é nen trovà."; -Blockly.Msg.LISTS_INLIST = "ant la lista"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 a l'é veuid"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "A smon ver se la lista a l'é veuida."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "longheur ëd %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "A smon la longheur ¨d na lista."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "creé na lista con l'element %1 arpetù %2 vire"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "A crea na lista ch'a consist dël valor dàit arpetù ël nùmer ëspessificà ëd vire."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "tanme"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "anserì an"; -Blockly.Msg.LISTS_SET_INDEX_SET = "buté"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "A anseriss l'element al prinsipi ëd na lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "A anseriss l'element a la posission ëspessificà an na lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Gionté l'element a la fin ëd na lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "A anseriss l'element a l'ancàpit an na lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "A fissa ël prim element an na lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "A fissa l'element a la posission ëspessificà an na lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "A fissa l'ùltim element an na lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "A fissa n'element a l'ancàpit an na lista."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "chërsent"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "calant"; -Blockly.Msg.LISTS_SORT_TITLE = "ordiné %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Ordiné na còpia ëd na lista."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alfabétich, ignorand ël caràter minùscol o majùscol"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numérich"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alfabétich"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "fé na lista da 'n test"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "fé 'n test da na lista"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Gionze na lista ëd test ant un test sol, separandje con un separator."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Divide un test an na lista ëd test, tajand a minca 'n separator."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "con ël separator"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "fàuss"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "A rëspond ver o fàuss."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "ver"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Rësponde ver si le doe imission a son uguaj."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Rësponde ver si la prima imission a l'é pi granda che la sconda."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Rësponde ver si la prima imission a l'é pi granda o ugual a la sconda."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Rësponde ver si la prima imission a l'é pi cita dla sconda."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Rësponde ver si la prima imission a l'é pi cita o ugual a la sconda."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Rësponde ver si le doe imission a son nen uguaj."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "nen %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "A rëspond ver se l'imission a l'é fàussa. A rëspond fàuss se l'imission a l'é vera."; -Blockly.Msg.LOGIC_NULL = "gnente"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "A rëspond gnente."; -Blockly.Msg.LOGIC_OPERATION_AND = "e"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "o"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Rësponde ver se tute doe j'imission a son vere."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Rësponde ver se almanch un-a d'imission a l'é vera."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "preuva"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "se fàuss"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "se ver"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Controlé la condission an 'preuva'. Se la condission a l'é vera, a rëspond con ël valor 'se ver'; dësnò a rëspond con ël valor 'se fàuss'."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Arithmetic"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "A smon la soma ëd doi nùmer."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "A smon ël cossient dij doi nùmer."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "A smon la diferensa dij doi nùmer."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "A smon ël prodot dij doi nùmer."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "A smon ël prim nùmer alvà a la potensa dël second."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "ancrementé %1 për %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Gionté un nùmer a la variàbil '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "A smon un-a dle costante comun-e π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…) o ∞ (infinì)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "limité %1 antra %2 e %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Limité un nùmer a esse antra le limitassion ëspessificà (comprèise)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "a l'é divisìbil për"; -Blockly.Msg.MATH_IS_EVEN = "a l'é cobi"; -Blockly.Msg.MATH_IS_NEGATIVE = "a l'é negativ"; -Blockly.Msg.MATH_IS_ODD = "a l'é dëscobi"; -Blockly.Msg.MATH_IS_POSITIVE = "a l'é positiv"; -Blockly.Msg.MATH_IS_PRIME = "a l'é prim"; -Blockly.Msg.MATH_IS_TOOLTIP = "A contròla si un nùmer a l'é cobi, dëscobi, prim, antreghm positiv, negativ, o s'a l'é divisìbil për un nùmer dàit. A rëspond ver o fàuss."; -Blockly.Msg.MATH_IS_WHOLE = "a l'é antregh"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "resta ëd %1:%2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "A smon la resta ëd la division dij doi nùmer."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Un nùmer."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "media dla lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "màssim ëd la lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "mesan-a dla lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "mìnim ëd la lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "mòde dla lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "element a l'ancàpit ëd la lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "deviassion ëstàndard ëd la lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "soma dla lista"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "A smon la media (aritmética) dij valor numérich ant la lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "A smon ël pi gròss nùmer ëd la lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "A smon ël nùmer mesan ëd la lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "A smon ël pi cit nùmer ëd la lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "A smon na lista dj'element pi frequent ëd la lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "A smon n'element a l'ancàpit da la lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "A smon la deviassion ëstàndard ëd la lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "A smon la soma ëd tuti ij nùmer ant la lista."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "frassion aleatòria"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "A smon na frassion aleatòria antra 0,0 (comprèis) e 1,0 (esclus)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "antregh aleatòri antra %1 e %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "A smon n'antregh aleatòri antra ij doi lìmit ëspessificà, comprèis."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "ariondé"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "ariondé për difet"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "ariondé për ecess"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "A arionda un nùmer për difet o ecess."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "assolù"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "rèis quadra"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "A smon ël valor assolù d'un nùmer."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "A smon e a la potensa d'un nùmer."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "A smon ël logaritm natural d'un nùmer."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "A smon ël logaritm an base 10 d'un nùmer."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "A smon l'opòst d'un nùmer."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "A smon 10 a la potensa d'un nùmer."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "A smon la rèis quadra d'un nùmer."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "A smon l'arch-cosen d'un nùmer."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "A smon l'arch-sen d'un nùmer."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "A smon l'arch-tangenta d'un nùmer."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "A smon ël cosen ëd n'àngol an gré (pa an radiant)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "A smon ël sen ëd n'àngol an gré (pa an radiant)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "A smon la tangenta ëd n'àngol an gré (pa an radiant)."; -Blockly.Msg.NEW_VARIABLE = "Creé na variàbil..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Nòm ëd la neuva variàbil:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "përmëtte le diciairassion"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "con:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Eseguì la fonsion '%1' definìa da l'utent."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Eseguì la fonsion '%1' definìa da l'utent e dovré sò arzultà."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "con:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Creé '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Descrive sa fonsion..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "fé cheicòs"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "a"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "A crea na fonsion sensa surtìa."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "artorn"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "A crea na fonsion con na surtìa."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Atension: Costa fonsion a l'ha dij paràmeter duplicà."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Sot-ligné la definission dla fonsion"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Se un valor a l'é ver, antlora smon-e un second valor."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Atension: Ës blòch a podria esse dovrà mach an na definission ëd fonsion."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "nòm ëd l'imission:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Gionté n'imission a la fonsion."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "imission"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Gionté, gavé o riordiné j'imission ëd sa fonsion."; -Blockly.Msg.REDO = "Fé torna"; -Blockly.Msg.REMOVE_COMMENT = "Scancelé un coment"; -Blockly.Msg.RENAME_VARIABLE = "Arnomé la variàbil..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Arnomé tute le variàbij '%1' 'me:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "taché ël test"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "a"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Taché dël test a la variàbil '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "an minùscul"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "an Majùscol A L'Ancamin Ëd Minca Paròla"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "an MAJÙSCOL"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "A smon na còpia dël test ant un caràter diferent."; -Blockly.Msg.TEXT_CHARAT_FIRST = "oten-e la prima litra"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "oten-e la litra # da la fin"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "oten-e la litra #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "ant ël test"; -Blockly.Msg.TEXT_CHARAT_LAST = "oten-e l'ùltima litra"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "oten-e na litra a l'ancàpit"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "A smon la litra ant la posission ëspessificà."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Gionté n'element al test."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "gionze"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Gionté, gavé o riordiné le session për configuré torna ës blòch ëd test."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "fin-a a la litra # da la fin"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "fin-a a la litra #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "fin-a a l'ùltima litra"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "ant ël test"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "oten-e la sota-stringa da la prima litra"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "oten-e la sota-stringa da la litra # da la fin"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "oten-e la sota-stringa da la litra #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "A smon un tòch ëspessificà dël test."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "ant ël test"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "trové la prima ocorensa dël test"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "trové l'ùltima ocorensa dël test"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "A smon l'ìndes dla prima/ùltima ocorensa dël prim test ant ël second test. A smon %1 se ël test a l'é nen trovà."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 a l'é veuid"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "A smon ver se ël test fornì a l'é veuid."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "creé ël test con"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Creé un tòch ëd test an gionzend un nùmer qualsëssìa d'element."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "longheur ëd %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "A smon ël nùmer ëd litre (spassi comprèis) ant ël test fornì."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "smon-e %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Smon-e ël test, ël nùmer o n'àutr valor ëspessificà."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Ciamé un nùmer a l'utent."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Ciamé un test a l'utent."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "anvit për un nùmer con un mëssagi"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "anvit për un test con un mëssagi"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Na litra, na paròla o na linia ëd test."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "gavé jë spassi da le doe bande ëd"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "gavé jë spassi da la banda snistra ëd"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "gavé jë spassi da la banda drita ëd"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "A smon na còpia dël test con jë spassi gavà da n'estremità o da tute doe."; -Blockly.Msg.TODAY = "Ancheuj"; -Blockly.Msg.UNDO = "Anulé"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "element"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Creé 'fissé %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "A smon ël valor ëd sa variàbil."; -Blockly.Msg.VARIABLES_SET = "fissé %1 a %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Creé 'oten-e %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Fissé costa variàbil ugual al valor d'imission."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "Na variàbil con ël nòm '%1' a esist già."; -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/pt-br.js b/backend/_pv_1_3_5/static/blockly/msg/js/pt-br.js deleted file mode 100755 index ba41b5ef9..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/pt-br.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.pt.br'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Adicionar comentário"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Mudar valor:"; -Blockly.Msg.CLEAN_UP = "Limpar blocos"; -Blockly.Msg.COLLAPSE_ALL = "Recolher blocos"; -Blockly.Msg.COLLAPSE_BLOCK = "Recolher bloco"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "cor 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "cor 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "proporção"; -Blockly.Msg.COLOUR_BLEND_TITLE = "misturar"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Mistura duas cores em uma dada proporção (0,0 - 1,0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://pt.wikipedia.org/wiki/Cor"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Escolher uma cor da palheta de cores."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "cor aleatória"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Escolher cor de forma aleatória."; -Blockly.Msg.COLOUR_RGB_BLUE = "azul"; -Blockly.Msg.COLOUR_RGB_GREEN = "verde"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "vermelho"; -Blockly.Msg.COLOUR_RGB_TITLE = "colorir com"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Cria uma cor de acordo com a quantidade especificada de vermelho, verde e azul. Todos os valores devem estar entre 0 e 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "encerra o laço"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "continua com a próxima iteração do laço"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Encerra o laço."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Ignora o resto deste laço, e continua com a próxima iteração."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Atenção: Este bloco só pode ser usado dentro de um laço."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "para cada item %1 na lista %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Para cada item em uma lista, atribuir o item à variável '%1' e então realiza algumas instruções."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "contar com %1 de %2 até %3 por %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Faz com que a variável '%1' assuma os valores do número inicial ao número final, contando de acordo com o intervalo especificado e executa os blocos especificados."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Acrescente uma condição para o bloco se."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Acrescente uma condição final para o bloco se."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Acrescente, remova ou reordene seções para reconfigurar este bloco."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "senão"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "senão se"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "se"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Se um valor for verdadeiro, então realize algumas instruções."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Se um valor for verdadeiro, então realize o primeiro bloco de instruções. Senão, realize o segundo bloco de instruções."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Se o primeiro valor é verdadeiro, então realize o primeiro bloco de instruções. Senão, se o segundo valor é verdadeiro, realize o segundo bloco de instruções."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Se o primeiro valor for verdadeiro, então realize o primeiro bloco de instruções. Senão, se o segundo valor é verdadeiro, realize o segundo bloco de instruções. Se nenhum dos blocos for verdadeiro, realize o último bloco de instruções."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://pt.wikipedia.org/wiki/Estrutura_de_repeti%C3%A7%C3%A3o#Repeti.C3.A7.C3.A3o_com_vari.C3.A1vel_de_controle"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "faça"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "repita %1 vezes"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Faça algumas instruções várias vezes."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "repita até"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "repita enquanto"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Enquanto um valor for falso, então faça algumas instruções."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Enquanto um valor for verdadeiro, então faça algumas instruções."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Apagar todos os %1 blocos?"; -Blockly.Msg.DELETE_BLOCK = "Remover bloco"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Remover %1 blocos"; -Blockly.Msg.DISABLE_BLOCK = "Desabilitar bloco"; -Blockly.Msg.DUPLICATE_BLOCK = "Duplicar"; -Blockly.Msg.ENABLE_BLOCK = "Habilitar bloco"; -Blockly.Msg.EXPAND_ALL = "Expandir blocos"; -Blockly.Msg.EXPAND_BLOCK = "Expandir bloco"; -Blockly.Msg.EXTERNAL_INPUTS = "Entradas externas"; -Blockly.Msg.HELP = "Ajuda"; -Blockly.Msg.INLINE_INPUTS = "Entradas incorporadas"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "criar lista vazia"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Retorna uma lista, de tamanho 0, contendo nenhum registro"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "lista"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Acrescenta, remove ou reordena seções para reconfigurar este bloco de lista."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "criar lista com"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Acrescenta um item à lista."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Cria uma lista com a quantidade de itens informada."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "primeiro"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "nº a partir do final"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "nº"; -Blockly.Msg.LISTS_GET_INDEX_GET = "obter"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "obter e remover"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "último"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "aleatório"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "remover"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Retorna o primeiro item em uma lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Retorna o item da lista na posição especificada."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Retorna o último item em uma lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Retorna um item aleatório de uma lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Remove e retorna o primeiro item de uma lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Remove e retorna o item na posição especificada em uma lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Remove e retorna o último item de uma lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Remove e retorna um item aleatório de uma lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Remove o primeiro item de uma lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Remove o item na posição especificada em uma lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Remove o último item de uma lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Remove um item aleatório de uma lista."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "até nº a partir do final"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "até nº"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "até último"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "obtém sublista a partir do primeiro"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "obtém sublista de nº a partir do final"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "obtém sublista de nº"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Cria uma cópia da porção especificada de uma lista."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 é o último item."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 é o primeiro item."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "encontre a primeira ocorrência do item"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "encontre a última ocorrência do item"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Retorna o índice da primeira/última ocorrência do item na lista. Retorna %1 se o item não for encontrado."; -Blockly.Msg.LISTS_INLIST = "na lista"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 é vazia"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Retorna ao verdadeiro se a lista estiver vazia."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "tamanho de %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Retorna o tamanho de uma lista."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "criar lista com item %1 repetido %2 vezes"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Cria uma lista consistindo no valor informado repetido o número de vezes especificado."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "como"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "inserir em"; -Blockly.Msg.LISTS_SET_INDEX_SET = "definir"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Insere o item no início de uma lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Insere o item na posição especificada em uma lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Insere o item no final de uma lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Insere o item em uma posição qualquer de uma lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Define o primeiro item de uma lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Define o item da posição especificada de uma lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Define o último item de uma lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Define um item aleatório de uma lista."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascendente"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descendente"; -Blockly.Msg.LISTS_SORT_TITLE = "ordenar %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Ordenar uma cópia de uma lista."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alfabético, ignorar maiúscula/minúscula"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numérico"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alfabético"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "Fazer uma lista a partir do texto"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "fazer um texto a partir da lista"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Juntar uma lista de textos em um único texto, separado por um delimitador."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Dividir o texto em uma lista de textos, separando-o em cada delimitador."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "com delimitador"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "falso"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Retorna verdadeiro ou falso."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "verdadeiro"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://pt.wikipedia.org/wiki/Inequa%C3%A7%C3%A3o"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Retorna verdadeiro se ambas as entradas forem iguais."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Retorna verdadeiro se a primeira entrada for maior que a segunda entrada."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Retorna verdadeiro se a primeira entrada for maior ou igual à segunda entrada."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Retorna verdadeiro se a primeira entrada for menor que a segunda entrada."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Retorna verdadeiro se a primeira entrada for menor ou igual à segunda entrada."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Retorna verdadeiro se ambas as entradas forem diferentes."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "não %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Retorna verdadeiro se a entrada for falsa. Retorna falsa se a entrada for verdadeira."; -Blockly.Msg.LOGIC_NULL = "nulo"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Retorna nulo."; -Blockly.Msg.LOGIC_OPERATION_AND = "e"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "ou"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Retorna verdadeiro se ambas as entradas forem verdadeiras."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Retorna verdadeiro se uma das estradas for verdadeira."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "teste"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "se falso"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "se verdadeiro"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Avalia a condição em \"teste\". Se a condição for verdadeira retorna o valor \"se verdadeiro\", senão retorna o valor \"se falso\"."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://pt.wikipedia.org/wiki/Aritm%C3%A9tica"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Retorna a soma dos dois números."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Retorna o quociente da divisão dos dois números."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Retorna a diferença entre os dois números."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Retorna o produto dos dois números."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Retorna o primeiro número elevado à potência do segundo número."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://pt.wikipedia.org/wiki/Adi%C3%A7%C3%A3o"; -Blockly.Msg.MATH_CHANGE_TITLE = "alterar %1 por %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Soma um número à variável \"%1\"."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://pt.wikipedia.org/wiki/Anexo:Lista_de_constantes_matem%C3%A1ticas"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Retorna uma das constantes comuns: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), ou ∞ (infinito)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "restringe %1 inferior %2 superior %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Restringe um número entre os limites especificados (inclusivo)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "é divisível por"; -Blockly.Msg.MATH_IS_EVEN = "é par"; -Blockly.Msg.MATH_IS_NEGATIVE = "é negativo"; -Blockly.Msg.MATH_IS_ODD = "é ímpar"; -Blockly.Msg.MATH_IS_POSITIVE = "é positivo"; -Blockly.Msg.MATH_IS_PRIME = "é primo"; -Blockly.Msg.MATH_IS_TOOLTIP = "Verifica se um número é par, ímpar, inteiro, positivo, negativo, ou se é divisível por outro número. Retorna verdadeiro ou falso."; -Blockly.Msg.MATH_IS_WHOLE = "é inteiro"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://pt.wikipedia.org/wiki/Opera%C3%A7%C3%A3o_m%C3%B3dulo"; -Blockly.Msg.MATH_MODULO_TITLE = "resto da divisão de %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Retorna o resto da divisão de dois números."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://pt.wikipedia.org/wiki/N%C3%BAmero"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Um número."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "média da lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "maior da lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "mediana da lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "menor da lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "moda da lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "item aleatório da lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "desvio padrão da lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "soma de uma lista"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Retorna a média aritmética dos números da lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Retorna o maior número da lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Retorna a mediana dos números da lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Retorna o menor número da lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Retorna uma lista do(s) item(ns) mais comum(ns) da lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Retorna um elemento aleatório da lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Retorna o desvio padrão dos números da lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Retorna a soma de todos os números na lista."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://pt.wikipedia.org/wiki/Gerador_de_n%C3%BAmeros_pseudoaleat%C3%B3rios"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "fração aleatória"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Retorna uma fração aleatória entre 0.0 (inclusivo) e 1.0 (exclusivo)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://pt.wikipedia.org/wiki/Gerador_de_n%C3%BAmeros_pseudoaleat%C3%B3rios"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "inteiro aleatório entre %1 e %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Retorna um número inteiro entre os dois limites informados, inclusivo."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://pt.wikipedia.org/wiki/Arredondamento"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "arredonda"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "arredonda para baixo"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "arredonda para cima"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Arredonda um número para cima ou para baixo."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://pt.wikipedia.org/wiki/Raiz_quadrada"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absoluto"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "raiz quadrada"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Retorna o valor absoluto de um número."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Retorna o número e elevado à potência de um número."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Retorna o logaritmo natural de um número."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Retorna o logaritmo em base 10 de um número."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Retorna o oposto de um número."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Retorna 10 elevado à potência de um número."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Retorna a raiz quadrada de um número."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://pt.wikipedia.org/wiki/Fun%C3%A7%C3%A3o_trigonom%C3%A9trica"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Retorna o arco cosseno de um número."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Retorna o arco seno de um número."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Retorna o arco tangente de um número."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Retorna o cosseno de um grau (não radiano)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Retorna o seno de um grau (não radiano)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Retorna a tangente de um grau (não radiano)."; -Blockly.Msg.NEW_VARIABLE = "Nova variável..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Nome da nova variável:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "permitir declarações"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "com:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://pt.wikipedia.org/wiki/Sub-rotina"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Executa a função definida pelo usuário \"%1\"."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://pt.wikipedia.org/wiki/Sub-rotina"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Executa a função definida pelo usuário \"%1\" e usa seu retorno."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "com:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Criar \"%1\""; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Descreva esta função..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "faça algo"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "para"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Cria uma função que não tem retorno."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "retorna"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Cria uma função que possui um valor de retorno."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Atenção: Esta função tem parâmetros duplicados."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Destacar definição da função"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Se um valor é verdadeiro, então retorna um valor."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Atenção: Este bloco só pode ser utilizado dentro da definição de uma função."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "nome da entrada:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Adiciona uma entrada para esta função"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "entradas"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Adiciona, remove, ou reordena as entradas para esta função."; -Blockly.Msg.REDO = "Refazer"; -Blockly.Msg.REMOVE_COMMENT = "Remover comentário"; -Blockly.Msg.RENAME_VARIABLE = "Renomear variável..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Renomear todas as variáveis '%1' para:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "acrescentar texto"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "para"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Acrescentar um pedaço de texto à variável \"%1\"."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "para minúsculas"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "para Nomes Próprios"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "para MAIÚSCULAS"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Retorna uma cópia do texto em um formato diferente."; -Blockly.Msg.TEXT_CHARAT_FIRST = "obter primeira letra"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "obter letra # a partir do final"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "obter letra nº"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "no texto"; -Blockly.Msg.TEXT_CHARAT_LAST = "obter última letra"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "obter letra aleatória"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Retorna a letra na posição especificada."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Acrescentar um item ao texto."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "unir"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Acrescenta, remove ou reordena seções para reconfigurar este bloco de texto."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "até letra nº a partir do final"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "até letra nº"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "até última letra"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "no texto"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "obter trecho de primeira letra"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "obter trecho de letra nº a partir do final"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "obter trecho de letra nº"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Retorna o trecho de texto especificado."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "no texto"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "encontre a primeira ocorrência do item"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "encontre a última ocorrência do texto"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Retorna a posição da primeira/última ocorrência do primeiro texto no segundo texto. Retorna %1 se o texto não for encontrado."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 é vazio"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Retorna verdadeiro se o texto fornecido for vazio."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "criar texto com"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Criar um pedaço de texto juntando qualquer número de itens."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "tamanho de %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Retorna o número de letras (incluindo espaços) no texto fornecido."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "imprime %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Imprime o texto, número ou valor especificado."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Pede ao usuário um número."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Pede ao usuário um texto."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "Pede um número com uma mensagem"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "Pede um texto com uma mensagem"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://pt.wikipedia.org/wiki/Cadeia_de_caracteres"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Uma letra, palavra ou linha de texto."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "remover espaços de ambos os lados de"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "remover espaços à esquerda de"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "remover espaços à direita de"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Retorna uma cópia do texto com os espaços removidos de uma ou ambas extremidades."; -Blockly.Msg.TODAY = "Hoje"; -Blockly.Msg.UNDO = "Desfazer"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "item"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Criar \"definir %1\""; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Retorna o valor desta variável."; -Blockly.Msg.VARIABLES_SET = "definir %1 para %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Criar \"obter %1\""; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Define esta variável para o valor da entrada."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/pt.js b/backend/_pv_1_3_5/static/blockly/msg/js/pt.js deleted file mode 100755 index 3242d851b..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/pt.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.pt'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Adicionar Comentário"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Alterar valor:"; -Blockly.Msg.CLEAN_UP = "Limpar os blocos"; -Blockly.Msg.COLLAPSE_ALL = "Recolher Blocos"; -Blockly.Msg.COLLAPSE_BLOCK = "Colapsar Bloco"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "cor 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "cor 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "proporção"; -Blockly.Msg.COLOUR_BLEND_TITLE = "misturar"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Mistura duas cores dada uma proporção (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "http://pt.wikipedia.org/wiki/Cor"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Escolhe uma cor da paleta de cores."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "cor aleatória"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Escolher cor de forma aleatória."; -Blockly.Msg.COLOUR_RGB_BLUE = "azul"; -Blockly.Msg.COLOUR_RGB_GREEN = "verde"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "vermelho"; -Blockly.Msg.COLOUR_RGB_TITLE = "pinte com"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Cria uma cor de acordo com a quantidade especificada de vermelho, verde e azul. Todos os valores devem estar entre 0 e 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "sair do ciclo"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "continuar com a próxima iteração do ciclo"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Sair do ciclo que está contido."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Ignora o resto deste ciclo e continua na próxima iteração."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Atenção: Este bloco só pode ser usado dentro de um ciclo."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "para cada item %1 na lista %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Para cada item numa lista, define a variável \"%1\" para o item e então faz algumas instruções."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "contar com %1 de %2 até %3 de %3 em %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Faz com que a variável \"%1\" assuma os valores desde o número inicial até ao número final, contando de acordo com o intervalo especificado e executa os blocos especificados."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Acrescente uma condição ao bloco se."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Acrescente uma condição de excepação final para o bloco se."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Acrescente, remova ou reordene secções para reconfigurar este bloco se."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "senão"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "senão se"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "se"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Se um valor é verdadeiro, então realize alguns passos."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Se um valor é verdadeiro, então realize o primeiro bloco de instruções. Senão, realize o segundo bloco de instruções"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Se o primeiro valor é verdadeiro, então realize o primeiro bloco de instruções. Senão, se o segundo valor é verdadeiro, realize o segundo bloco de instruções."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Se o primeiro valor é verdadeiro, então realize o primeiro bloco de instruções. Senão, se o segundo valor é verdadeiro, realize o segundo bloco de instruções. Se nenhum dos blocos for verdadeiro, realize o último bloco de instruções."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "http://pt.wikipedia.org/wiki/Estrutura_de_repeti%C3%A7%C3%A3o#Repeti.C3.A7.C3.A3o_com_vari.C3.A1vel_de_controle"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "faça"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "repita %1 vez"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Faça algumas instruções várias vezes."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "repita até"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "repita enquanto"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Enquanto um valor for falso, então faça algumas instruções."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Enquanto um valor for verdadeiro, então faça algumas instruções."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Apagar todos os %1 blocos?"; -Blockly.Msg.DELETE_BLOCK = "Remover Bloco"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Remover %1 Blocos"; -Blockly.Msg.DISABLE_BLOCK = "Desabilitar Bloco"; -Blockly.Msg.DUPLICATE_BLOCK = "Duplicar"; -Blockly.Msg.ENABLE_BLOCK = "Habilitar Bloco"; -Blockly.Msg.EXPAND_ALL = "Expandir Blocos"; -Blockly.Msg.EXPAND_BLOCK = "Expandir Bloco"; -Blockly.Msg.EXTERNAL_INPUTS = "Entradas externas"; -Blockly.Msg.HELP = "Ajuda"; -Blockly.Msg.INLINE_INPUTS = "Entradas Internas"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "criar lista vazia"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Retorna uma lista, de tamanho 0, contendo nenhum registo"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "lista"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Acrescente, remova ou reordene as seções para reconfigurar este bloco lista."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "criar lista com"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Acrescenta um item à lista."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Cria uma lista com qualquer número de itens."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "primeiro"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# a partir do final"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "obter"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "obter e remover"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "último"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "aleatório"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "remover"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Retorna o primeiro item de uma lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Retorna o item na posição especificada da lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Retorna o último item de uma lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Retorna um item aleatório de uma lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Remove e retorna o primeiro item de uma lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Remove e retorna o item na posição especificada de uma lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Remove e retorna o último item de uma lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Remove e retorna um item aleatório de uma lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Remove o primeiro item de uma lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Remove o item de uma posição especifica da lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Remove o último item de uma lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Remove um item aleatório de uma lista."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "até #, a partir do final"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "até #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "para o último"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "obtem sublista da primeira lista"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "obtem sublista de # a partir do final"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "obtem sublista de #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Cria uma cópia da porção especificada de uma lista."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 é o último item."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 é o primeiro item."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "encontre a primeira ocorrência do item"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "encontre a última ocorrência do item"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Retorna a posição da primeira/última ocorrência do item na lista. Retorna %1 se o item não for encontrado."; -Blockly.Msg.LISTS_INLIST = "na lista"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 está vazia"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Retona verdadeiro se a lista estiver vazia."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "tamanho de %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Retorna o tamanho de uma lista."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "criar lista com o item %1 repetido %2 vezes"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Cria uma lista constituída por um dado valor repetido o número de vezes especificado."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "como"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "inserir em"; -Blockly.Msg.LISTS_SET_INDEX_SET = "definir"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Insere o item no início da lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Insere o item numa posição especificada numa lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Insere o item no final da lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Insere o item numa posição aleatória de uma lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Define o primeiro item de uma lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Define o item na posição especificada de uma lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Define o último item de uma lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Define um item aleatório de uma lista."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "fazer lista a partir de texto"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "fazer texto a partir da lista"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Juntar uma lista de textos num único texto, separado por um delimitador."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Dividir o texto numa lista de textos, separando-o em cada delimitador."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "com delimitador"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "falso"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Retorna verdadeiro ou falso."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "verdadeiro"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "http://pt.wikipedia.org/wiki/Inequa%C3%A7%C3%A3o"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Retorna verdadeiro se ambas as entradas forem iguais entre si."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Retorna verdadeiro se a primeira entrada for maior que a segunda entrada."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Retorna verdadeiro se a primeira entrada for maior ou igual à segunda entrada."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Retorna verdadeiro se a primeira entrada for menor que a segunda entrada."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Retorna verdadeiro se a primeira entrada for menor ou igual à segunda entrada."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Retorna verdadeiro se ambas as entradas forem diferentes entre si."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "não %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Retorna verdadeiro se a entrada for falsa. Retorna falso se a entrada for verdadeira."; -Blockly.Msg.LOGIC_NULL = "nulo"; -Blockly.Msg.LOGIC_NULL_HELPURL = "http://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Retorna nulo."; -Blockly.Msg.LOGIC_OPERATION_AND = "e"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "ou"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Retorna verdadeiro se ambas as entradas forem verdadeiras."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Retorna verdadeiro se pelo menos uma das estradas for verdadeira."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "teste"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "http://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "se falso"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "se verdadeiro"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Avalia a condição em \"teste\". Se a condição for verdadeira retorna o valor \"se verdadeiro\", senão retorna o valor \"se falso\"."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "http://pt.wikipedia.org/wiki/Aritm%C3%A9tica"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Retorna a soma de dois números."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Retorna o quociente da divisão de dois números."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Retorna a diferença de dois números."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Retorna o produto de dois números."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Retorna o primeiro número elevado à potência do segundo número."; -Blockly.Msg.MATH_CHANGE_HELPURL = "http://pt.wikipedia.org/wiki/Adi%C3%A7%C3%A3o"; -Blockly.Msg.MATH_CHANGE_TITLE = "alterar %1 por %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Soma um número à variável \"%1\"."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "http://pt.wikipedia.org/wiki/Anexo:Lista_de_constantes_matem%C3%A1ticas"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Retorna uma das constantes comuns: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), ou ∞ (infinito)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "restringe %1 inferior %2 superior %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Restringe um número entre os limites especificados (inclusive)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "é divisível por"; -Blockly.Msg.MATH_IS_EVEN = "é par"; -Blockly.Msg.MATH_IS_NEGATIVE = "é negativo"; -Blockly.Msg.MATH_IS_ODD = "é impar"; -Blockly.Msg.MATH_IS_POSITIVE = "é positivo"; -Blockly.Msg.MATH_IS_PRIME = "é primo"; -Blockly.Msg.MATH_IS_TOOLTIP = "Verifica se um número é par, impar, primo, inteiro, positivo, negativo, ou se é divisível por outro número. Retorna verdadeiro ou falso."; -Blockly.Msg.MATH_IS_WHOLE = "é inteiro"; -Blockly.Msg.MATH_MODULO_HELPURL = "http://pt.wikipedia.org/wiki/Opera%C3%A7%C3%A3o_m%C3%B3dulo"; -Blockly.Msg.MATH_MODULO_TITLE = "resto da divisão de %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Retorna o resto da divisão de dois números."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; -Blockly.Msg.MATH_NUMBER_HELPURL = "http://pt.wikipedia.org/wiki/N%C3%BAmero"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Um número."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "média de uma lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "maior de uma lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "mediana de uma lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "menor de uma lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "moda de uma lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "item aleatório de uma lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "desvio padrão de uma lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "soma da lista"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Retorna a média aritmética dos valores números da lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Retorna o maior número da lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Retorna a mediana da lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Retorna o menor número da lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Retorna a lista de item(ns) mais comum(ns) da lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Retorna um elemento aleatório da lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Retorna o desvio padrão dos números da lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Retorna a soma de todos os números da lista."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "http://pt.wikipedia.org/wiki/N%C3%BAmero_aleat%C3%B3rio"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "fração aleatória"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Insere uma fração aleatória entre 0.0 (inclusive) e 1.0 (exclusive)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "http://pt.wikipedia.org/wiki/N%C3%BAmero_aleat%C3%B3rio"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "inteiro aleatório entre %1 e %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Retorna um número inteiro entre os dois limites especificados, inclusive."; -Blockly.Msg.MATH_ROUND_HELPURL = "http://pt.wikipedia.org/wiki/Arredondamento"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "arredonda"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "arredonda para baixo"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "arredonda para cima"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Arredonda um número para cima ou para baixo."; -Blockly.Msg.MATH_SINGLE_HELPURL = "http://pt.wikipedia.org/wiki/Raiz_quadrada"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absoluto"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "raíz quadrada"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Retorna o valor absoluto de um número."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Retorna o número e elevado à potência de um número."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Retorna o logarítmo natural de um número."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Retorna o logarítmo em base 10 de um número."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Retorna o oposto de um número."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Retorna 10 elevado à potência de um número."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Retorna a raiz quadrada de um número."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "acos"; -Blockly.Msg.MATH_TRIG_ASIN = "asin"; -Blockly.Msg.MATH_TRIG_ATAN = "atan"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "http://pt.wikipedia.org/wiki/Fun%C3%A7%C3%A3o_trigonom%C3%A9trica"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tan"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Retorna o arco cosseno de um número."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Retorna o arco seno de um número."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Retorna o arco tangente de um número."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Retorna o cosseno de um grau (não radiano)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Retorna o seno de um grau (não radiano)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Retorna a tangente de um grau (não radiano)."; -Blockly.Msg.NEW_VARIABLE = "Nova variável..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Nome da nova variável:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "permitir declarações"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "com:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "http://pt.wikipedia.org/wiki/Sub-rotina"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Executa a função \"%1\"."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "http://pt.wikipedia.org/wiki/Sub-rotina"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Executa a função \"%1\" e usa o seu retorno."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "com:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Criar \"%1\""; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Descreva esta função..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "faz algo"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "para"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Cria uma função que não tem retorno."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "retorna"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Cria uma função que possui um valor de retorno."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Atenção: Esta função tem parâmetros duplicados."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Destacar definição da função"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "se o valor é verdadeiro, então retorna um segundo valor."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Atenção: Este bloco só pode ser utilizado dentro da definição de uma função."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "nome da entrada:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Adicionar uma entrada para a função."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "entradas"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Adicionar, remover ou reordenar as entradas para esta função."; -Blockly.Msg.REDO = "Refazer"; -Blockly.Msg.REMOVE_COMMENT = "Remover Comentário"; -Blockly.Msg.RENAME_VARIABLE = "Renomear variável..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Renomear todas as variáveis '%1' para:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "acrescentar texto"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "para"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Acrescentar um pedaço de texto à variável \"%1\"."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "para minúsculas"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "para Iniciais Maiúsculas"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "para MAIÚSCULAS"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Retorna uma cópia do texto em formato diferente."; -Blockly.Msg.TEXT_CHARAT_FIRST = "obter primeira letra"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "obter letra nº a partir do final"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "obter letra nº"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "no texto"; -Blockly.Msg.TEXT_CHARAT_LAST = "obter última letra"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "obter letra aleatória"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Retorna a letra na posição especificada."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Acrescentar um item ao texto."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "unir"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Acrescenta, remove ou reordena seções para reconfigurar este bloco de texto."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "até letra nº a partir do final"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "até letra nº"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "até última letra"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "no texto"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "obter subsequência a partir da primeira letra"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "obter subsequência de tamanho # a partir do final"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "obter subsequência de tamanho #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Retorna a parte especificada do texto."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "no texto"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "primeira ocorrência do texto"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "última ocorrência do texto"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Retorna a posição da primeira/última ocorrência do primeiro texto no segundo texto. Retorna %1 se o texto não for encontrado."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 está vazio"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Retorna verdadeiro se o texto fornecido estiver vazio."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "criar texto com"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Criar um pedaço de texto juntando qualquer número de itens."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "tamanho de %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Devolve o número de letras (incluindo espaços) do texto fornecido."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "imprime %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Imprime o texto, número ou outro valor especificado."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Pede ao utilizador um número."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Pede ao utilizador um texto."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "pede um número com a mensagem"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "Pede um texto com a mensagem"; -Blockly.Msg.TEXT_TEXT_HELPURL = "http://pt.wikipedia.org/wiki/Cadeia_de_caracteres"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Uma letra, palavra ou linha de texto."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "remover espaços de ambos os lados"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "remover espaços à esquerda de"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "remover espaços à direita"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Retorna uma cópia do texto com os espaços removidos de uma ou ambas as extremidades."; -Blockly.Msg.TODAY = "Hoje"; -Blockly.Msg.UNDO = "Desfazer"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "item"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Criar \"definir %1\""; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Retorna o valor desta variável."; -Blockly.Msg.VARIABLES_SET = "definir %1 para %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Criar \"obter %1\""; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Define esta variável para o valor inserido."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/ro.js b/backend/_pv_1_3_5/static/blockly/msg/js/ro.js deleted file mode 100755 index 3626c8c87..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/ro.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.ro'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Adaugă un comentariu"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Schimbaţi valoarea:"; -Blockly.Msg.CLEAN_UP = "Clean up Blocks"; // untranslated -Blockly.Msg.COLLAPSE_ALL = "Restrange blocurile"; -Blockly.Msg.COLLAPSE_BLOCK = "Restrange blocul"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "culoare 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "culoare 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "Raport"; -Blockly.Msg.COLOUR_BLEND_TITLE = "amestec"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Amestecă două culori cu un raport dat (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://ro.wikipedia.org/wiki/Culoare"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Alege o culoare din paleta de culori."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "culoare aleatorie"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Alege o culoare la întâmplare."; -Blockly.Msg.COLOUR_RGB_BLUE = "albastru"; -Blockly.Msg.COLOUR_RGB_GREEN = "verde"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "roşu"; -Blockly.Msg.COLOUR_RGB_TITLE = "colorează cu"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Creează o culoare cu suma specificată de roşu, verde şi albastru. Toate valorile trebuie să fie între 0 şi 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "ieşi din bucla"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "continuă cu următoarea iterație a buclei"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Ieși din bucla care conţine."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Sari peste restul aceastei bucle, şi continuă cu urmatoarea iteratie."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Avertisment: Acest bloc pote fi utilizat numai în interiorul unei bucle."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "pentru fiecare element %1 în listă %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Pentru fiecare element din listă, setaţi variabila '%1' ca valoarea elementului, şi apoi faceţi unele declaraţii."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "numără cu %1 de la %2 la %3 prin %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Cu variablia \"%1\" ia o valoare din numărul început la numărul final, numara in intervalul specificat, apoi face blocurile specificate."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Adăugaţi o condiţie in blocul if."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Adauga o stare finala, cuprinde toata conditia din blocul if."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Adaugă, elimină sau reordonează secţiuni pentru a reconfigura acest bloc if."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "altfel"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "altfel dacă"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "dacă"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Dacă o valoare este adevărată, atunci fa unele declaraţii."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Dacă o valoare este adevărat, atunci face primul bloc de declaraţii. Altfel, face al doilea bloc de declaraţii."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Dacă prima valoare este adevărat, atunci face primul bloc de declaraţii. Altfel, dacă a doua valoare este adevărat, face al doilea bloc de declaraţii."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Dacă prima valoare este adevărat, atunci face primul bloc de declaraţii. Altfel, dacă a doua valoare este adevărat, face al doilea bloc de declaraţii. În cazul în care niciuna din valorilor nu este adevărat, face ultimul bloc de declaraţii."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "fă"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "repetă de %1 ori"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Face unele afirmaţii de mai multe ori."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "Repetaţi până când"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "repetă în timp ce"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "În timp ce o valoare este adevărat, atunci face unele declaraţii."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "În timp ce o valoare este adevărat, atunci face unele declaraţii."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Ștergi toate cele %1 (de) blocuri?"; -Blockly.Msg.DELETE_BLOCK = "Șterge Bloc"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Ștergeți %1 Blocuri"; -Blockly.Msg.DISABLE_BLOCK = "Dezactivaţi bloc"; -Blockly.Msg.DUPLICATE_BLOCK = "Duplicati"; -Blockly.Msg.ENABLE_BLOCK = "Permite bloc"; -Blockly.Msg.EXPAND_ALL = "Extinde blocuri"; -Blockly.Msg.EXPAND_BLOCK = "Extinde bloc"; -Blockly.Msg.EXTERNAL_INPUTS = "Intrări externe"; -Blockly.Msg.HELP = "Ajutor"; -Blockly.Msg.INLINE_INPUTS = "Intrări în linie"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "creează listă goală"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Returnează o listă, de lungime 0, care nu conţine înregistrări de date"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "listă"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Adaugă, elimină sau reordonează secţiuni ca să reconfiguraţi aceste blocuri de listă."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "creează listă cu"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Adăugaţi un element la listă."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Creaţi o listă cu orice număr de elemente."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "primul"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# de la sfârșit"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "obţine"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "obţine şi elimină"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "ultimul"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "aleator"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "elimină"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Returnează primul element dintr-o listă."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Returneaza elementul la poziţia specificată într-o listă."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Returnează ultimul element într-o listă."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Returneaza un element aleatoriu într-o listă."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Elimină şi returnează primul element într-o listă."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Elimină şi returneaza elementul la poziţia specificată într-o listă."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Elimină şi returnează ultimul element într-o listă."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Elimină şi returnează un element aleatoriu într-o listă."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Elimină primul element într-o listă."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Elimină elementul la poziţia specificată într-o listă."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Elimină ultimul element într-o listă."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Elimină un element aleatoriu într-o listă."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "la # de la sfarsit"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "la #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "la ultima"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "obţine sub-lista de la primul"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "obţine sub-lista de la # de la sfârşitul"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "obţine sub-lista de la #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Creează o copie a porţiunii specificate dintr-o listă."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 este ultimul element."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 este primul element."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "Găseşte prima apariţie a elementului"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "găseşte ultima apariţie a elementului"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Revine la indexul de la prima/ultima apariție a elementului din listă. Returnează %1 dacă elementul nu este găsit."; -Blockly.Msg.LISTS_INLIST = "în listă"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 este gol"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Returnează adevărat dacă lista este goală."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "lungime de %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Returnează lungimea unei liste."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "creaza lista cu %1 elemente repetate de %2 ori"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Creează o listă alcătuită dintr-o anumită valoare repetată de numărul specificat de ori."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "ca"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "introduceţi la"; -Blockly.Msg.LISTS_SET_INDEX_SET = "seteaza"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserează elementul la începutul unei liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Inserează elementul la poziţia specificată într-o listă."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Adăugă elementul la sfârşitul unei liste."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Inserează elementul aleatoriu într-o listă."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Setează primul element într-o listă."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Setează elementul la poziţia specificată într-o listă."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Setează ultimul element într-o listă."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Setează un element aleator într-o listă."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "convertește textul în listă"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "convertește lista în text"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Concatenează o listă de texte (alternate cu separatorul) într-un text unic"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Împarte textul într-o listă de texte, despărțite prin fiecare separator"; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "cu separatorul"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "fals"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Returnează adevărat sau fals."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "adevărat"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Returnează adevărat dacă ambele intrări sunt egale."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Returnează adevărat dacă prima intrare este mai mare decât a doua intrare."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Returnează adevărat dacă prima intrare este mai mare sau egală cu a doua intrare."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Returnează adevărat dacă prima intrare este mai mică decât a doua intrare."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Returnează adevărat dacă prima intrare este mai mică sau egală cu a doua intrare."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Returnează adevărat daca cele două intrări nu sunt egale."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "non %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Returnează adevărat dacă intrarea este falsă. Returnează fals dacă intrarea este adevărată."; -Blockly.Msg.LOGIC_NULL = "nul"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "returnează nul."; -Blockly.Msg.LOGIC_OPERATION_AND = "şi"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "sau"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Returnează adevărat daca ambele intrări sunt adevărate."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Returnează adevărat dacă cel puţin una din intrări este adevărată."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "dacă este fals"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "dacă este adevărat"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Verifică condiţia din \"test\". Dacă condiţia este adevărată, returnează valoarea \"în cazul în care adevărat\"; în caz contrar întoarce valoarea \"în cazul în care e fals\"."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://ro.wikipedia.org/wiki/Aritmetic%C4%83"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Returnează suma a două numere."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Returnează câtul celor două numere."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Returneaza diferenţa dintre cele două numere."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Returnează produsul celor două numere."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Returneaza numărul rezultat prin ridicarea primului număr la puterea celui de-al doilea."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "schimbă %1 de %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Adaugă un număr variabilei '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://ro.wikipedia.org/wiki/Constant%C4%83_matematic%C4%83"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Întoarcă una din constantele comune: π (3.141...), e (2.718...), φ (1,618...), sqrt(2) (1.414...), sqrt(½) (0.707...) sau ∞ (infinitate)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "constrânge %1 redus %2 ridicat %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Constrânge un număr să fie între limitele specificate (inclusiv)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "este divizibil cu"; -Blockly.Msg.MATH_IS_EVEN = "este par"; -Blockly.Msg.MATH_IS_NEGATIVE = "este negativ"; -Blockly.Msg.MATH_IS_ODD = "este impar"; -Blockly.Msg.MATH_IS_POSITIVE = "este pozitiv"; -Blockly.Msg.MATH_IS_PRIME = "este prim"; -Blockly.Msg.MATH_IS_TOOLTIP = "Verifică dacă un număr este un par, impar, prim, întreg, pozitiv, negativ, sau dacă este divizibil cu un anumit număr. Returnează true sau false."; -Blockly.Msg.MATH_IS_WHOLE = "este întreg"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "restul la %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Întoarce restul din împărţirea celor două numere."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Un număr."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "media listei"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "maximul listei"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "media listei"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "minimul listei"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "moduri de listă"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "element aleatoriu din lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "deviația standard a listei"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "suma listei"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Întoarce media (aritmetică) a valorilor numerice în listă."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Întoarce cel mai mare număr din listă."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Întoarce numărul median în listă."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Returnează cel mai mic număr din listă."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Returnează o listă cu cel(e) mai frecvent(e) element(e) din listă."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Returnează un element aleatoriu din listă."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Întoarce deviația standard a listei."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Returnează suma tuturor numerelor din lista."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "fracții aleatorii"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Returnează o fracţie aleatoare între 0.0 (inclusiv) si 1.0 (exclusiv)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "un număr întreg aleator de la %1 la %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Returnează un număr întreg aleator aflat între cele două limite specificate, inclusiv."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "rotund"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "rotunjit"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "rotunjește în sus"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Rotunjirea unui număr în sus sau în jos."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absolută"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "rădăcina pătrată"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Returnează valoarea absolută a unui număr."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Returnează e la puterea unui număr."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Întoarce logaritmul natural al unui număr."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Returnează logaritmul în baza 10 a unui număr."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Returnează negaţia unui număr."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Returnează 10 la puterea unui număr."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Returnează rădăcina pătrată a unui număr."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "arccos"; -Blockly.Msg.MATH_TRIG_ASIN = "arcsin"; -Blockly.Msg.MATH_TRIG_ATAN = "arctg"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tg"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Returnează arccosinusul unui număr."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Returnează arcsinusul unui număr."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Returnează arctangenta unui număr."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Întoarce cosinusul unui grad (nu radianul)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Întoarce cosinusul unui grad (nu radianul)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Întoarce tangenta unui grad (nu radianul)."; -Blockly.Msg.NEW_VARIABLE = "Variabilă nouă..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Noul nume de variabilă:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "permite declarațiile"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "cu:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Executați funcția '%1 'definită de utilizator."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Executați funcția '%1 'definită de utilizator şi folosiţi producţia sa."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "cu:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Creaţi '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "fă ceva"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "la"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Crează o funcţie cu nici o ieşire."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "returnează"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Creează o funcţie cu o ieşire."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Atenţie: Această funcţie are parametri duplicaţi."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Evidenţiază definiţia funcţiei"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Dacă o valoare este adevărată, atunci returnează valoarea a doua."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Avertisment: Acest bloc poate fi utilizat numai în definiţia unei funcţii."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "nume de intrare:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Adaugă un parametru de intrare pentru funcție."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "intrări"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Adăugă, șterge sau reordonează parametrii de intrare ai acestei funcții."; -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "Elimină comentariu"; -Blockly.Msg.RENAME_VARIABLE = "Redenumirea variabilei..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Redenumeşte toate variabilele '%1' în:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "Adăugaţi text"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "la"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Adăugaţi text la variabila '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "la litere mici"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "către Titlul de caz"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "la MAJUSCULE"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Întoarce o copie a textului într-un caz diferit."; -Blockly.Msg.TEXT_CHARAT_FIRST = "obţine prima litera"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "obţine litera # de la sfârșit"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "obtine litera #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "în text"; -Blockly.Msg.TEXT_CHARAT_LAST = "obţine o litera oarecare"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "obtine o litera oarecare"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Returnează litera la poziția specificată."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Adaugă un element în text."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "alăturaţi-vă"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Adaugă, elimină sau reordonează secțiuni ca să reconfigureze blocul text."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "la litera # de la sfarsit"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "la litera #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "la ultima literă"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "în text"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "obţine un subșir de la prima literă"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "obține un subșir de la litera # de la sfârșit"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "obține subșir de la litera #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returnează o anumită parte din text."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "în text"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "găseşte prima apariţie a textului"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "găseşte ultima apariţie a textului"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returnează indicele primei/ultimei apariţii din primul text în al doilea text. Returnează %1 dacă textul nu este găsit."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 este gol"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returnează adevărat dacă textul furnizat este gol."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "crează text cu"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Creaţi o bucată de text prin unirea oricărui număr de elemente."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "lungime de %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Returnează numărul de litere (inclusiv spaţiile) în textul furnizat."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "imprimare %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Afișează textul specificat, numărul sau altă valoare."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Solicită utilizatorul pentru un număr."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Solicită utilizatorul pentru text."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "solicită pentru număr cu mesaj"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "solicită pentru text cu mesaj"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "O literă, cuvânt sau linie de text."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "taie spațiile de pe ambele părți ale"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "tăiaţi spațiile din partea stângă a"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "taie spațiile din partea dreaptă a"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Returnează o copie a textului fără spațiile de la unul sau ambele capete."; -Blockly.Msg.TODAY = "Astăzi"; -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "element"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Crează 'set %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returnează valoarea acestei variabile."; -Blockly.Msg.VARIABLES_SET = "seteaza %1 la %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Crează 'get %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Setează această variabilă sa fie egală la intrare."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/ru.js b/backend/_pv_1_3_5/static/blockly/msg/js/ru.js deleted file mode 100755 index 2a73ad453..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/ru.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.ru'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Добавить комментарий"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Измените значение:"; -Blockly.Msg.CLEAN_UP = "Убрать блоки"; -Blockly.Msg.COLLAPSE_ALL = "Свернуть блоки"; -Blockly.Msg.COLLAPSE_BLOCK = "Свернуть блок"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "цвет 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "цвет 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "доля цвета 1"; -Blockly.Msg.COLOUR_BLEND_TITLE = "смешать"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Смешивает два цвета в заданном соотношении (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://ru.wikipedia.org/wiki/Цвет"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Выберите цвет из палитры."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "случайный цвет"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Выбирает цвет случайным образом."; -Blockly.Msg.COLOUR_RGB_BLUE = "синего"; -Blockly.Msg.COLOUR_RGB_GREEN = "зелёного"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "красного"; -Blockly.Msg.COLOUR_RGB_TITLE = "цвет из"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Создаёт цвет с указанной пропорцией красного, зеленого и синего. Все значения должны быть между 0 и 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "выйти из цикла"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "перейти к следующему шагу цикла"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Прерывает этот цикл."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Пропускает остаток цикла и переходит к следующему шагу."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Предупреждение: этот блок может использоваться только внутри цикла."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "для каждого элемента %1 в списке %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Для каждого элемента в списке, присваивает переменной '%1' значение элемента и выполняет указанные команды."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "цикл по %1 от %2 до %3 с шагом %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Присваивает переменной '%1' значения от начального до конечного с заданным шагом и выполняет указанные команды."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Добавляет условие к блоку \"если\""; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Добавить заключительный подблок для случая, когда все условия ложны."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Добавьте, удалите, переставьте фрагменты для переделки блока \"если\"."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "иначе"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "иначе если"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "если"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Если условие истинно, выполняет команды."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Если условие истинно, выполняет первый блок команд. Иначе выполняется второй блок команд."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Если первое условие истинно, то выполняет первый блок команд. Иначе, если второе условие истинно, выполняет второй блок команд."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Если первое условие истинно, то выполняет первый блок команд. В противном случае, если второе условие истинно, выполняет второй блок команд. Если ни одно из условий не истинно, выполняет последний блок команд."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://ru.wikipedia.org/wiki/Цикл_(программирование)"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "выполнить"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "повторить %1 раз"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Выполняет некоторые команды несколько раз."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "повторять, пока не"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "повторять, пока"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Пока значение ложно, выполняет команды"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Пока значение истинно, выполняет команды."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Удалить все блоки (%1)?"; -Blockly.Msg.DELETE_BLOCK = "Удалить блок"; -Blockly.Msg.DELETE_VARIABLE = "Удалить переменную '%1'"; -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Удалить %1 использований переменной '%2'?"; -Blockly.Msg.DELETE_X_BLOCKS = "Удалить %1 блоков"; -Blockly.Msg.DISABLE_BLOCK = "Отключить блок"; -Blockly.Msg.DUPLICATE_BLOCK = "Скопировать"; -Blockly.Msg.ENABLE_BLOCK = "Включить блок"; -Blockly.Msg.EXPAND_ALL = "Развернуть блоки"; -Blockly.Msg.EXPAND_BLOCK = "Развернуть блок"; -Blockly.Msg.EXTERNAL_INPUTS = "Вставки снаружи"; -Blockly.Msg.HELP = "Справка"; -Blockly.Msg.INLINE_INPUTS = "Вставки внутри"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "создать пустой список"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Возвращает список длины 0, не содержащий данных"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "список"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Добавьте, удалите, переставьте элементы для переделки блока списка."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "создать список из"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Добавляет элемент к списку."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Создаёт список с любым числом элементов."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "первый"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "№ с конца"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "взять"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "взять и удалить"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "последний"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "произвольный"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "удалить"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Возвращает первый элемент списка."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Возвращает элемент в указанной позиции списка."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Возвращает последний элемент списка."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Возвращает случайный элемент списка."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Удаляет и возвращает первый элемент списка."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Удаляет и возвращает элемент в указанной позиции списка."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Удаляет и возвращает последний элемент списка."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Удаляет и возвращает случайный элемент списка."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Удаляет первый элемент списка."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Удаляет элемент в указанной позиции списка."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Удаляет последний элемент списка."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Удаляет случайный элемент списка."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "по № с конца"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "по №"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "по последний"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "взять подсписок с первого"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "взять подсписок с № с конца"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "взять подсписок с №"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Создаёт копию указанной части списка."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 - последний элемент."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 - первый элемент."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "найти первое вхождение элемента"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "найти последнее вхождение элемента"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Возвращает номер позиции первого/последнего вхождения элемента в списке. Возвращает %1, если элемент не найден."; -Blockly.Msg.LISTS_INLIST = "в списке"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 пуст"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Возвращает значение истина, если список пуст."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "длина %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Возвращает длину списка."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "создать список из элемента %1, повторяющегося %2 раз"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Создаёт список, состоящий из заданного числа копий элемента."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "="; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "вставить в"; -Blockly.Msg.LISTS_SET_INDEX_SET = "присвоить"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Вставляет элемент в начало списка."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Вставляет элемент в указанной позиции списка."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Добавляет элемент в конец списка."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Вставляет элемент в случайное место в списке."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Присваивает значение первому элементу списка."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Присваивает значение элементу в указанной позиции списка."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Присваивает значение последнему элементу списка."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Присваивает значение случайному элементу списка."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "по возрастанию"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "по убыванию"; -Blockly.Msg.LISTS_SORT_TITLE = "сортировать %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Сортировать копию списка."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "по алфавиту, без учёта регистра"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "числовая"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "по алфавиту"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "сделать список из текста"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "собрать текст из списка"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Соединяет сптсок текстов в один текст с разделителями."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Разбивает текст в список текстов, по разделителям."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "с разделителем"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "ложь"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Возвращает значение истина или ложь."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "истина"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://ru.wikipedia.org/wiki/Неравенство"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Возвращает положительное значение, если вводы равны."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Возвращает значение истина, если первая вставка больше второй."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Возвращает значение истина, если первая вставка больше или равна второй."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Возвращает положительное значение, если первый ввод меньше второго."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Возвращает значение истина, если первая вставка меньше или равна второй."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Возвращает положительное значение, если вводы не равны."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "не %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Возвращает значение истина, если вставка ложна. Возвращает значение ложь, если вставка истинна."; -Blockly.Msg.LOGIC_NULL = "ничто"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Возвращает ничто."; -Blockly.Msg.LOGIC_OPERATION_AND = "и"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "или"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Возвращает значение истина, если обе вставки истинны."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Возвращает значение истина, если хотя бы одна из вставок истинна."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "выбрать по"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://ru.wikipedia.org/wiki/Тернарная_условная_операция"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "если ложь"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "если истина"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Проверяет условие выбора. Если условие истинно, возвращает первое значение, в противном случае возвращает второе значение."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://ru.wikipedia.org/wiki/Арифметика"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Возвращает сумму двух чисел."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Возвращает частное от деления первого числа на второе."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Возвращает разность двух чисел."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Возвращает произведение двух чисел."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Возвращает первое число, возведённое в степень второго числа."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://ru.wikipedia.org/wiki/%D0%98%D0%B4%D0%B8%D0%BE%D0%BC%D0%B0_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%29#.D0.98.D0.BD.D0.BA.D1.80.D0.B5.D0.BC.D0.B5.D0.BD.D1.82"; -Blockly.Msg.MATH_CHANGE_TITLE = "увеличить %1 на %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Добавляет число к переменной '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://ru.wikipedia.org/wiki/Математическая_константа"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Возвращает одну из распространённых констант: π (3.141...), e (2.718...), φ (1.618...), sqrt(2) (1.414...), sqrt(½) (0.707...) или ∞ (бесконечность)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "ограничить %1 снизу %2 сверху %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Ограничивает число нижней и верхней границами (включительно)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "делится на"; -Blockly.Msg.MATH_IS_EVEN = "чётное"; -Blockly.Msg.MATH_IS_NEGATIVE = "отрицательное"; -Blockly.Msg.MATH_IS_ODD = "нечётное"; -Blockly.Msg.MATH_IS_POSITIVE = "положительное"; -Blockly.Msg.MATH_IS_PRIME = "простое"; -Blockly.Msg.MATH_IS_TOOLTIP = "Проверяет, является ли число чётным, нечётным, простым, целым, положительным, отрицательным или оно кратно определённому числу. Возвращает значение истина или ложь."; -Blockly.Msg.MATH_IS_WHOLE = "целое"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://ru.wikipedia.org/wiki/Деление_с_остатком"; -Blockly.Msg.MATH_MODULO_TITLE = "остаток от %1 : %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Возвращает остаток от деления двух чисел."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://ru.wikipedia.org/wiki/Число"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Число."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "среднее арифметическое списка"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "наибольшее в списке"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "медиана списка"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "наименьшее в списке"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "моды списка"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "случайный элемент списка"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "стандартное отклонение списка"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "сумма списка"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Возвращает среднее арифметическое списка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Возвращает наибольшее число списка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Возвращает медиану списка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Возвращает наименьшее число списка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Возвращает список наиболее часто встречающихся элементов списка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Возвращает случайный элемент списка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Возвращает стандартное отклонение списка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Возвращает сумму всех чисел в списке."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://ru.wikipedia.org/wiki/Генератор_псевдослучайных_чисел"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "случайное число от 0 (включительно) до 1"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Возвращает случайное число от 0.0 (включительно) до 1.0."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://ru.wikipedia.org/wiki/Генератор_псевдослучайных_чисел"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "случайное целое число от %1 для %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Возвращает случайное число между двумя заданными пределами (включая и их)."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://ru.wikipedia.org/wiki/Округление"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "округлить"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "округлить к меньшему"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "округлить к большему"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Округляет число до большего или меньшего."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://ru.wikipedia.org/wiki/Квадратный_корень"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "модуль"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "квадратный корень"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Возвращает модуль числа"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Возвращает е в указанной степени."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Возвращает натуральный логарифм числа."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Возвращает десятичный логарифм числа."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Возвращает противоположное число."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Возвращает 10 в указанной степени."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Возвращает квадратный корень числа."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://ru.wikipedia.org/wiki/Тригонометрические_функции"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Возвращает арккосинус (в градусах)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Возвращает арксинус (в градусах)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Возвращает арктангенс (в градусах)"; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Возвращает косинус угла в градусах."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Возвращает синус угла в градусах."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Возвращает тангенс угла в градусах."; -Blockly.Msg.NEW_VARIABLE = "Создать переменную…"; -Blockly.Msg.NEW_VARIABLE_TITLE = "Имя новой переменной:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "разрешить операторы"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "с:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://ru.wikipedia.org/wiki/Функция_%28программирование%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Исполняет определённую пользователем процедуру '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://ru.wikipedia.org/wiki/Функция_%28программирование%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Исполняет определённую пользователем процедуру '%1' и возвращает вычисленное значение."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "с:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Создать вызов '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Опишите эту функцию…"; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "выполнить что-то"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "чтобы"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Создаёт процедуру, не возвращающую значение."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "вернуть"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Создаёт процедуру, возвращающую значение."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Предупреждение: эта функция имеет повторяющиеся параметры."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Выделить определение процедуры"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Если первое значение истинно, возвращает второе значение."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Предупреждение: Этот блок может использоваться только внутри определения функции."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "имя параметра:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Добавить входной параметр в функцию."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "параметры"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Добавить, удалить или изменить порядок входных параметров для этой функции."; -Blockly.Msg.REDO = "Повторить"; -Blockly.Msg.REMOVE_COMMENT = "Удалить комментарий"; -Blockly.Msg.RENAME_VARIABLE = "Переименовать переменную…"; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Переименовать все переменные '%1' в:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "добавить текст"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "к"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Добавить текст к переменной «%1»."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "в строчные буквы"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "в Заглавные Начальные Буквы"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "в ЗАГЛАВНЫЕ БУКВЫ"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Возвращает копию текста с ЗАГЛАВНЫМИ или строчными буквами."; -Blockly.Msg.TEXT_CHARAT_FIRST = "взять первую букву"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "взять букву № с конца"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "взять букву №"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "в тексте"; -Blockly.Msg.TEXT_CHARAT_LAST = "взять последнюю букву"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "взять случайную букву"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Возвращает букву в указанной позиции."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Добавить элемент к тексту."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "соединить"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Добавьте, удалите, переставьте фрагменты для переделки текстового блока."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "по букву № с конца"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "по букву №"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "по последнюю букву"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "в тексте"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "взять подстроку с первой буквы"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "взять подстроку с буквы № с конца"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "взять подстроку с буквы №"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Возвращает указанную часть текста."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "в тексте"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "найти первое вхождение текста"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "найти последнее вхождение текста"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Возвращает номер позиции первого/последнего вхождения первого текста во втором. Возвращает %1, если текст не найден."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 пуст"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Возвращает значение истина, если предоставленный текст пуст."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "создать текст из"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Создаёт фрагмент текста, объединяя любое число элементов"; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "длина %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Возвращает число символов (включая пробелы) в заданном тексте."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "напечатать %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Печатает текст, число или другой объект."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Запросить у пользователя число."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Запросить у пользователя текст."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "запросить число с подсказкой"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "запросить текст с подсказкой"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://ru.wikipedia.org/wiki/Строковый_тип"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Буква, слово или строка текста."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "обрезать пробелы с двух сторон"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "обрезать пробелы слева"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "обрезать пробелы справа"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Возвращает копию текста с пробелами, удалеными с одного или обоих концов."; -Blockly.Msg.TODAY = "Сегодня"; -Blockly.Msg.UNDO = "Отменить"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "элемент"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Создать блок \"присвоить\" для %1"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Возвращает значение этой переменной."; -Blockly.Msg.VARIABLES_SET = "присвоить %1 = %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Создать вставку %1"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Присваивает переменной значение вставки."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "Переменная с именем '%1' уже существует."; -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/sc.js b/backend/_pv_1_3_5/static/blockly/msg/js/sc.js deleted file mode 100755 index bb4b2ff6f..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/sc.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.sc'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Agiunghe unu cumentu"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Muda valori:"; -Blockly.Msg.CLEAN_UP = "Lìmpia is brocus"; -Blockly.Msg.COLLAPSE_ALL = "Serra e stringi Brocus"; -Blockly.Msg.COLLAPSE_BLOCK = "Serra e stringi Brocu"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "colori 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "colori 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "raportu"; -Blockly.Msg.COLOUR_BLEND_TITLE = "mestura"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Amestura duus coloris cun unu raportu (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Scebera unu colori de sa tauledda."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "Unu colori a brítiu"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Scebera unu colori a brítiu."; -Blockly.Msg.COLOUR_RGB_BLUE = "blue"; -Blockly.Msg.COLOUR_RGB_GREEN = "birdi"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "arrùbiu"; -Blockly.Msg.COLOUR_RGB_TITLE = "colora cun"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Cuncorda unu colori cun su tanti de arrubiu, birdi, e blue. Totu is valoris depint essi intra 0 e 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "sàrtiat a foras de sa lòriga"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "sighit cun su repicu afatànti"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Bessit de sa lòriga."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Sartiat su chi abarrat de sa loriga, e sighit cun su repicu afatànti."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Amonestu: Custu brocu ddu podis ponni sceti aintru de una lòriga."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "po dònnia item %1 in lista %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Po dònnia item in sa lista, ponit sa variàbili '%1' pari a s'item, e tandu fait pariga de cumandus."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "po %1 de %2 fintzas %3 a passus de %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Fait pigai a sa variàbili \"%1\" i valoris de su primu numeru a s'urtimu, a su passu impostau e fait su brocu."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Aciungi una cunditzioni a su brocu si."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Aciungi una urtima cunditzioni piga-totu a su brocu si."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Aciungi, fùlia, o assenta is partis po torrai a sètiu custu brocu si."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "sinuncas"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "sinuncas si"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "si"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Si su valori est berus, tandu fait pariga de cumandus."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Si su valori est berus, tandu fai su primu brocu de is cumandus. Sinuncas, fai su segundu brocu de is cumandus."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Si su primu valori est beridadi, tandu fai su primu brocu de is cumandus. Sinuncas, si su segundu valori est beridadi, fai su segundu brocu de is cumandus."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Si su primu valori est berus, tandu fai su primu brocu de is cumandus. Sinuncas, si su segundu valori est berus, fai su segundu brocu de is cumandus. Si mancu unu valori est berus, tandu fai s'urtimu brocu de is cumandus."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "fai"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "repiti %1 bortas"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Fait pariga de cumandus prus bortas."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "repiti fintzas"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "repiti interis"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Interis su valori est frassu, tandu fai pariga de cumandus."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Interis su valori est berus, tandu fai pariga de cumandus."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Scancellu su %1 de is brocus?"; -Blockly.Msg.DELETE_BLOCK = "Fùlia Blocu"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Fulia %1 Blocus"; -Blockly.Msg.DISABLE_BLOCK = "Disabìlita Blocu"; -Blockly.Msg.DUPLICATE_BLOCK = "Dùplica"; -Blockly.Msg.ENABLE_BLOCK = "Abìlita Blocu"; -Blockly.Msg.EXPAND_ALL = "Aberi Brocus"; -Blockly.Msg.EXPAND_BLOCK = "Aberi Brocu"; -Blockly.Msg.EXTERNAL_INPUTS = "Intradas esternas"; -Blockly.Msg.HELP = "Agiudu"; -Blockly.Msg.INLINE_INPUTS = "Intradas in lìnia"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "fait una lista buida"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Torrat una lista, de longària 0, chena records de datus."; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "lista"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Aciungi, fùlia, o assenta is partis po torrai a sètiu custu brocu lista."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "fait una lista cun"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Acciungi unu item a sa lista."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Fait una lista cun calisiollat numeru de items."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "primu"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# de sa fini"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "piga"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "piga e fùlia"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "urtimu"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "a brìtiu (random)"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "fùlia"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Torrat su primu elementu de una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Torrat s'elementu de su postu inditau de una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Torrat s'urtimu elementu de una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Torrat un'elementu a brìtiu de una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Fùliat e torrat su primu elementu de una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Fùliat e torrat s'elementu de su postu inditau de una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Fùliat e torrat s'urtimu elementu de una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Fùliat e torrat un'elementu a brìtiu de una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Fùliat su primu elementu de una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Fùliat s'elementu de su postu inditau de una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Fùliat s'urtimu elementu de una lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Fùliat unu elementu a brìtiu de una lista."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "a # de sa fini"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "fintzas a #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "a s'urtimu"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "bogandi suta-lista de su primu"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "bogandi suta-lista de # de sa fini."; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "bogandi suta-lista de #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Fait una copia de sa parti inditada de sa lista."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 est po s'urtimu elementu."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 est po su primu elementu."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "circa prima ocasioni de s'item"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "circa urtima ocasioni de s'item"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Torrat s'indixi de sa primu/urtima ocasioni de s'item in sa lista. Torrat %1 si s'item non s'agatat."; -Blockly.Msg.LISTS_INLIST = "in lista"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 est buidu"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Torrat berus si sa lista est buida."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "longària de %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Torrat sa longària de una lista."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "fait una lista cun item %1 repitiu %2 bortas"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Fait una lista cun unu numeru giau repitiu su tanti de is bortas inditadas."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "a"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "inserta a"; -Blockly.Msg.LISTS_SET_INDEX_SET = "imposta"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Insertat s'elementu a su cumintzu de sa lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Insertat s'elementu in su postu inditau in una lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Aciungit s'elementu a sa fini de sa lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Aciungit s'elementu a brítiu in sa lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Impostat su primu elementu in una lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Impostat s'elementu in su postu inditau de una lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Impostat s'urtimu elementu in una lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Impostat unu elementu random in una lista."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "fai una lista de unu testu"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "fai unu testu de una lista"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Auni una lista de testus in d-unu sceti, ponendi separadoris."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Dividi su testu in un'elencu de testus, firmendi po dònnia separadori."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "cun separadori"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "frassu"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Torrat berus o frassu."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "berus"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Torrat berus si is inputs funt unu uguali a s'àteru."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Torrat berus si su primu input est prus mannu de s'àteru."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Torrat berus si su primu input est prus mannu o uguali a s'àteru."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Torrat berus si su primu input est prus piticu de s'àteru."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Torrat berus si su primu input est prus piticu o uguali a s'àteru."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Torrat berus si is inputs non funt unu uguali a s'àteru."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "non %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Torrat berus si s'input est frassu. Torrat frassu si s'input est berus."; -Blockly.Msg.LOGIC_NULL = "null"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Torrat null."; -Blockly.Msg.LOGIC_OPERATION_AND = "and"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "or"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Torrat berus si ambos is inputs funt berus."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Torrat berus si assumancu unu de is inputs est berus."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "cumpròa"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "si frassu"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "si berus"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "‎Cumproa sa cunditzioni in 'cumproa'. Si sa cunditzioni est berus, torrat su valori 'si berus'; sinuncas torrat su valori 'si frassu'."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Arithmetic"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Torrat sa summa de is duus nùmerus."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Torrat su cuotzienti de is duus nùmerus."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Torrat sa diferèntzia de is duus nùmerus."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Torrat su produtu de is duus nùmerus."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Torrat su primu numeru artziau a sa potenza de su segundu nùmeru."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "muda %1 de %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Aciungi unu numeru a sa variabili '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Torrat una de is costantis comunas: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), o ∞ (infiniu)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "custringi %1 de %2 a %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Custringi unu numeru aintru de is liminaxus giaus (cumprendius)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "fait a ddu dividi po"; -Blockly.Msg.MATH_IS_EVEN = "est paris"; -Blockly.Msg.MATH_IS_NEGATIVE = "est negativu"; -Blockly.Msg.MATH_IS_ODD = "est dísparu"; -Blockly.Msg.MATH_IS_POSITIVE = "est positivu"; -Blockly.Msg.MATH_IS_PRIME = "est primu"; -Blockly.Msg.MATH_IS_TOOLTIP = "Cumprova si unu numeru est paris, dìsparis, primu, intreu, positivu, negativu o si fait a ddu dividi po unu numeru giau. Torrat berus o frassu."; -Blockly.Msg.MATH_IS_WHOLE = "est intreu"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "arrestu de %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Torrat s'arrestu de sa divisioni de duus numerus."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Unu numeru"; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "mèdia de sa lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "massimu de sa lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "medianu de sa lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "minimu de sa lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "modas de sa lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "unu item a brìtiu de sa lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "deviadura standard de sa lista"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "suma sa lista"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Torrat sa mèdia (aritimètica) de is valoris de sa lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Torrat su numeru prus mannu de sa lista"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Torrat su numeru medianu de sa lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Torrat su numeru prus piticu de sa lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Torrat una lista de is itams prus frecuentis de sa lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Torrat unu item a brìtiu de sa lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Torrat sa deviadura standard de sa lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Torrat sa suma de totu is numerus de sa lista."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "una fratzioni a brìtiu"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Torrat una fratzioni a brìtiu intra 0.0 (cumpresu) e 1.0 (bogau)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "numeru intreu a brítiu de %1 a %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Torrat unu numeru intreu a brìtiu intra duus nùmerus giaus (cumpresus)."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "arretunda"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "arretunda faci a bàsciu."; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "Arretunda faci a susu"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Arretunda unu numeru faci a susu o faci a bàsciu."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "assolutu"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "arraxina cuadra"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Torrat su valori assolútu de unu numeru."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Torrat (e) a sa potèntzia de unu numeru."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Torrat su logaritmu naturali de unu numeru."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Torrat su logaritmu a basi 10 de unu numeru."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Torrat su valori negau de unu numeru."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Torrat (10) a sa potèntzia de unu numeru."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Torrat s'arraxina cuadra de unu numeru."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Torrat su arccosinu de unu numeru."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Torrat su arcsinu de unu numeru."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Torrat su arctangenti de unu numeru."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Torrat su cosinu de unu gradu (no radianti)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Torrat su sinu de unu gradu (no radianti)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Torrat sa tangenti de unu gradu (no radianti)."; -Blockly.Msg.NEW_VARIABLE = "Variabili noa..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Nòmini de sa variabili noa:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "permiti decraratzionis"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "con:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Arròllia sa funtzione '%1' cuncordada dae s'impitadore."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Arròllia sa funtzione '%1' cuncordada dae s'impitadore e imprea s'output suu."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "cun"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Ingenerau'%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "fait calincuna cosa"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "po"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Fait una funtzioni chena output."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "torrat"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Fait una funtzioni cun output."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Amonestu: Custa funtzioni tenit parametrus duplicaus."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Marca sa definitzioni de funtzioni."; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Si unu valori est berus, tandu torrat unu segundu valori."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Amonestu: Custu brocu ddu podis ponni sceti aintru de una funtzioni."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "nomini input:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Aciungi un input a sa funtzioni."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "inputs"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Aciungi, fùlia, o assenta is inputs a custa funtzioni."; -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "Fùlia unu cumentu"; -Blockly.Msg.RENAME_VARIABLE = "Muda nòmini a variabili..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "A is variabilis '%1' muda nòmini a:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "acciungi su testu"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "a"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Aciungit testu a sa variàbili '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "a minúdu"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "cun Primu lìtera a Mauschínu"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "a mauschínu"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Torrat una copia de su testu inditau mudendi mauschínu/minúdu."; -Blockly.Msg.TEXT_CHARAT_FIRST = "piga sa prima lìtera"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "piga sa lìtera # de sa fini"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "piga sa lìtera #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "in su testu"; -Blockly.Msg.TEXT_CHARAT_LAST = "piga s'urtima lìtera"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "piga una lìtera a brìtiu"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Torrat sa lìtera de su postu giau."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Acciungi unu item a su testu."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "auni a pari"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Aciungi, fùlia, o assenta is partis po torrai a sètiu custu brocu de testu."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "a sa lìtera # de sa fini"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "a sa lìtera #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "a s'urtima lìtera"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "in su testu"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "piga suta-stringa de sa primu lìtera"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "piga suta-stringa de sa lìtera # fintzas a fini"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "piga suta-stringa de sa lìtera #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Torrat su testu inditau."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "in su testu"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "circa prima ocasioni de su testu"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "circa urtima ocasioni de su testu"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Torrat s'indixi de sa primu/urtima ocasioni de su primu testu in su segundu testu. Torrat %1 si su testu no ddu agatat."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 est buidu"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Torrat berus si su testu giau est buidu."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "scri testu cun"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Fait unu testu ponendi a pari parigas de items."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "longària de %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Torrat su numeru de lìteras (cun is spàtzius) in su testu giau."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "scri %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Scri su testu, numeru o àteru valori."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Pregonta unu nùmeru a s'impitadore."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Pregonta testu a s'impitadore."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "pregonta po unu numeru"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "pregonta po su testu"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Una lìtera, paràula, o linia de testu."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "bogat spàtzius de ambus càbudus de"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "bogat spàtzius de su càbudu de manca de"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "bogat spàtzius de su càbudu de dereta de"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Torrat una copia de su testu bogaus is spàtzius de unu o de ambus is càbudus."; -Blockly.Msg.TODAY = "Oe"; -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "item"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Fait 'imposta %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Torrat su valori de custa variabili."; -Blockly.Msg.VARIABLES_SET = "imposta %1 a %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Fait 'piga %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Imposta custa variabili uguali a s'input."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/sd.js b/backend/_pv_1_3_5/static/blockly/msg/js/sd.js deleted file mode 100755 index 7127dda34..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/sd.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.sd'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "تاثرات ڏيو"; -Blockly.Msg.CHANGE_VALUE_TITLE = "قدر بدلايو"; -Blockly.Msg.CLEAN_UP = "بندشون هٽايو"; -Blockly.Msg.COLLAPSE_ALL = "بلاڪَ ڍڪيو"; -Blockly.Msg.COLLAPSE_BLOCK = "بلاڪ ڍڪيو"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "رنگ 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "رنگ 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "تناسب"; -Blockly.Msg.COLOUR_BLEND_TITLE = "blend"; // untranslated -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "ڄاڻايل تناسب سان ٻہ رنگ پاڻ ۾ ملايو (0.0-1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "رنگ دٻيءَ مان رنگ چونڊيو."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "بلا ترتيب رنگ"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "ڪو بہ ‌ڃڳ چونڊيو."; -Blockly.Msg.COLOUR_RGB_BLUE = "نيرو"; -Blockly.Msg.COLOUR_RGB_GREEN = "سائو"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "ڳاڙهو"; -Blockly.Msg.COLOUR_RGB_TITLE = "سان رڱيو"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "ڳاڙهي، سائي، ۽ نيري جو مقدار ڄاڻائي گھربل رنگ ٺاهيو. سمورا قدر 0 ۽ 100 جي وچ ۾ هجن."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "چڪر مان ٻاهر نڪرو"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "چڪر جاري رکندر نئين ڦيري پايو"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Break out of the containing loop."; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Skip the rest of this loop, and continue with the next iteration."; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Warning: This block may only be used within a loop."; // untranslated -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "for each item %1 in list %2"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "For each item in a list, set the variable '%1' to the item, and then do some statements."; // untranslated -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "count with %1 from %2 to %3 by %4"; // untranslated -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Have the variable '%1' take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks."; // untranslated -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Add a condition to the if block."; // untranslated -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Add a final, catch-all condition to the if block."; // untranslated -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Add, remove, or reorder sections to reconfigure this if block."; // untranslated -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "نہ تہ"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "نہ تہ جي"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "جيڪڏهن"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "If a value is true, then do some statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "If a value is true, then do the first block of statements. Otherwise, do the second block of statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements."; // untranslated -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "ڪريو"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "1٪ ڀيرا ورجايو"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Do some statements several times."; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "ورجايو جيستائين"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "ورجايو جڏهن"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "While a value is false, then do some statements."; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "While a value is true, then do some statements."; // untranslated -Blockly.Msg.DELETE_ALL_BLOCKS = "Delete all %1 blocks?"; // untranslated -Blockly.Msg.DELETE_BLOCK = "بلاڪ ڊاهيو"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "1٪ بلاڪ ڊاهيو"; -Blockly.Msg.DISABLE_BLOCK = "بلاڪ کي غيرفعال بڻايو"; -Blockly.Msg.DUPLICATE_BLOCK = "نقل"; -Blockly.Msg.ENABLE_BLOCK = "بلاڪ کي فعال بڻايو"; -Blockly.Msg.EXPAND_ALL = "بلاڪَ نمايو"; -Blockly.Msg.EXPAND_BLOCK = "بلاڪ نمايو"; -Blockly.Msg.EXTERNAL_INPUTS = "خارجي ڄاڻ"; -Blockly.Msg.HELP = "مدد"; -Blockly.Msg.INLINE_INPUTS = "Inline Inputs"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "خالي فهرست تخليق ڪريو"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Returns a list, of length 0, containing no data records"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "لسٽ"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Add, remove, or reorder sections to reconfigure this list block."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "create list with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "فهرست ۾ ڪا شي شامل ڪريو."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Create a list with any number of items."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_FIRST = "پهريون"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# آخر کان"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "get"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "get and remove"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_LAST = "آخري"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "بي ترتيب"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "هٽايو"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Removes and returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Removes and returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Removes and returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Removes and returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Removes the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Removes the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Removes the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Removes a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "ڏانهن # آخر کان"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "ڏانهن #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "آخري ڏانهن"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "get sub-list from first"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "get sub-list from # from end"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "get sub-list from #"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Creates a copy of the specified portion of a list."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 is the last item."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 is the first item."; // untranslated -Blockly.Msg.LISTS_INDEX_OF_FIRST = "find first occurrence of item"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "find last occurrence of item"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Returns the index of the first/last occurrence of the item in the list. Returns %1 if item is not found."; // untranslated -Blockly.Msg.LISTS_INLIST = "فهرست ۾"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 is empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Returns true if the list is empty."; // untranslated -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "length of %1"; // untranslated -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Returns the length of a list."; // untranslated -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "create list with item %1 repeated %2 times"; // untranslated -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Creates a list consisting of the given value repeated the specified number of times."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "جيان"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "تي داخل ڪريو"; -Blockly.Msg.LISTS_SET_INDEX_SET = "ميڙ"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserts the item at the start of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Inserts the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Append the item to the end of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Inserts the item randomly in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Sets the first item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Sets the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Sets the last item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Sets a random item in a list."; // untranslated -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "make list from text"; // untranslated -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "make text from list"; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "ڪُوڙ"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "درست يا غير درست وراڻي ٿو."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "سچ"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "جيڪڏهن ٻئي ان پُٽس برابر آهن تہ درست وراڻيو"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "جيڪڏهن پهريون ان پُٽ ٻين ان پُٽ کان وڏو آهي تہ درست وراڻيو."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "جيڪڏهن پهريون ان پُٽ ٻين ان پُٽ کان وڏو آهي يا ٻئي برابر آهن تہ درست وراڻيو."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "جيڪڏهن پهريون ان پُٽ ٻين ان پُٽ کان ننڍو آهي تہ درست وراڻيو"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "جيڪڏهن پهريون ان پُٽ ٻين ان پُٽ کان ننڍو آهي يا ٻئي برابر آهن تہ درست وراڻيو"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "جيڪڏهن ٻئي ان پُٽس اڻ برابر آهن تہ درست وراڻيو"; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "نڪي %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "ان پُٽ غير درست آهي تہ درست وراڻيو. ان پُٽ درست آهي تہ غير درست وراڻيو."; -Blockly.Msg.LOGIC_NULL = "null"; // untranslated -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Returns null."; // untranslated -Blockly.Msg.LOGIC_OPERATION_AND = "۽"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "يا"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "جيڪڏهن ٻئي ان پُٽ درست آهن تہ درست وراڻيو."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "جيڪڏهن ٻنهي ان پُٽس مان ڪو هڪ بہ درست آهي تہ درست وراڻيو."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; // untranslated -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "جيڪڏهن ڪوڙو"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "جيڪڏهن سچو"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value."; // untranslated -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Arithmetic"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "ٻن انگن جي جوڙ اپت ڏيو."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "ٻنهي انگن جي ونڊ ڏيو."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "ٻنهي انگن جو تفاوت ڏيو."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "ٻنهي انگن جي ضرب اُپت ڏيو."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Return the first number raised to the power of the second number."; // untranslated -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; // untranslated -Blockly.Msg.MATH_CHANGE_TITLE = "%1 کي %2 سان مَٽايو"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Add a number to variable '%1'."; // untranslated -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/رياضياتي استقلال"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; // untranslated -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "constrain %1 low %2 high %3"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Constrain a number to be between the specified limits (inclusive)."; // untranslated -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "سان ونڊجندڙ آهي"; -Blockly.Msg.MATH_IS_EVEN = "ٻڌي آهي"; -Blockly.Msg.MATH_IS_NEGATIVE = "ڪاٽو آهي"; -Blockly.Msg.MATH_IS_ODD = "اِڪي آهي"; -Blockly.Msg.MATH_IS_POSITIVE = "واڌو آهي"; -Blockly.Msg.MATH_IS_PRIME = "مفرد آهي"; -Blockly.Msg.MATH_IS_TOOLTIP = "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false."; // untranslated -Blockly.Msg.MATH_IS_WHOLE = "سڄو آهي"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; // untranslated -Blockly.Msg.MATH_MODULO_TITLE = "remainder of %1 ÷ %2"; // untranslated -Blockly.Msg.MATH_MODULO_TOOLTIP = "Return the remainder from dividing the two numbers."; // untranslated -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; // untranslated -Blockly.Msg.MATH_NUMBER_TOOLTIP = "ڪو انگ."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "لسٽ جي سراسري"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "لسٽ جو وڏي ۾ وڏو قدر"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "لسٽ جو مڌيان"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "لسٽ جو ننڍي ۾ ننڍو قدر"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "modes of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "random item of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "standard deviation of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "sum of list"; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Return the average (arithmetic mean) of the numeric values in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "لسٽ ۾ وڏي کان وڏو قدر ڄاڻايو."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "لسٽ جو مڌيان انگ ڄاڻايو."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "لسٽ ۾ ننڍي کان ننڍو قدر ڄاڻايو."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Return a list of the most common item(s) in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Return a random element from the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Return the standard deviation of the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Return the sum of all the numbers in the list."; // untranslated -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "random fraction"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive)."; // untranslated -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TITLE = "random integer from %1 to %2"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Return a random integer between the two specified limits, inclusive."; // untranslated -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; // untranslated -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "round"; // untranslated -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "round down"; // untranslated -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "round up"; // untranslated -Blockly.Msg.MATH_ROUND_TOOLTIP = "Round a number up or down."; // untranslated -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/ٻيون مول"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "ٺپ"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "ٻيون مول"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Return the absolute value of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Return e to the power of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "ڪنهن انگ جو قدرتي لاگ ڄاڻايو."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "ڪنهن انگ جو 10 بنيادي لاگ ڄاڻايو."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "ڪنهن انگ جو ڪاٽو ڄاڻايو."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Return 10 to the power of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "ڪنهن انگ جو ٻيون مول ڄاڻايو."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/ٽڪنڊور ڪاڄ"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Return the arccosine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Return the arcsine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Return the arctangent of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Return the cosine of a degree (not radian)."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Return the sine of a degree (not radian)."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Return the tangent of a degree (not radian)."; // untranslated -Blockly.Msg.NEW_VARIABLE = "نئون ڦرڻو..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "ڦرڻي جو نئون نالو:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "allow statements"; // untranslated -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "سان:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Run the user-defined function '%1'."; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Run the user-defined function '%1' and use its output."; // untranslated -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "سان:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "تخليق ڪريو '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "ڪجھ ڪريو"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "ڏانهن"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Creates a function with no output."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "واپس ورو"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Creates a function with an output."; // untranslated -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Warning: This function has duplicate parameters."; // untranslated -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Highlight function definition"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "If a value is true, then return a second value."; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Warning: This block may be used only within a function definition."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "input name:"; // untranslated -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Add an input to the function."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "ان پُٽس"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Add, remove, or reorder inputs to this function."; // untranslated -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "تاثرات مِٽايو"; -Blockly.Msg.RENAME_VARIABLE = "ڦرڻي کي نئون نالو ڏيو..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Rename all '%1' variables to:"; // untranslated -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "append text"; // untranslated -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "to"; // untranslated -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Append some text to variable '%1'."; // untranslated -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "ننڍن اکر ڏانهن"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "to Title Case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "وڏن اکرن ڏانهن"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; // untranslated -Blockly.Msg.TEXT_CHARAT_FIRST = "get first letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_FROM_END = "get letter # from end"; // untranslated -Blockly.Msg.TEXT_CHARAT_FROM_START = "get letter #"; // untranslated -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "in text"; // untranslated -Blockly.Msg.TEXT_CHARAT_LAST = "get last letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_RANDOM = "get random letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Returns the letter at the specified position."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Add an item to the text."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "شامل ٿيو"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Add, remove, or reorder sections to reconfigure this text block."; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "to letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "to letter #"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "to last letter"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "in text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "get substring from first letter"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "get substring from letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "get substring from letter #"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returns a specified portion of the text."; // untranslated -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "in text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "find first occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "find last occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found."; // untranslated -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 is empty"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returns true if the provided text is empty."; // untranslated -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "create text with"; // untranslated -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Create a piece of text by joining together any number of items."; // untranslated -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "length of %1"; // untranslated -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Returns the number of letters (including spaces) in the provided text."; // untranslated -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "ڇاپيو %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "ڄاڻايل تحرير، انگ يا ڪو ٻيو قدر ڇاپيو."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Prompt for user for a number."; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Prompt for user for some text."; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "prompt for number with message"; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "prompt for text with message"; // untranslated -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; // untranslated -Blockly.Msg.TEXT_TEXT_TOOLTIP = "A letter, word, or line of text."; // untranslated -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "trim spaces from both sides of"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "trim spaces from left side of"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "trim spaces from right side of"; // untranslated -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Return a copy of the text with spaces removed from one or both ends."; // untranslated -Blockly.Msg.TODAY = "اڄ"; -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "اسم"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Create 'set %1'"; // untranslated -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returns the value of this variable."; // untranslated -Blockly.Msg.VARIABLES_SET = "set %1 to %2"; // untranslated -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Create 'get %1'"; // untranslated -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Sets this variable to be equal to the input."; // untranslated -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/shn.js b/backend/_pv_1_3_5/static/blockly/msg/js/shn.js deleted file mode 100755 index 630a99ba9..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/shn.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.shn'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "သႂ်ႇၶေႃႈၵႂၢမ်း"; -Blockly.Msg.CHANGE_VALUE_TITLE = "လႅၵ်ႈလၢႆႈၼမ်ႉၵတ်ႉ"; -Blockly.Msg.CLEAN_UP = "Clean up Blocks"; // untranslated -Blockly.Msg.COLLAPSE_ALL = "ပလွၵ်ႉတင်းၼမ် လႅဝ်"; -Blockly.Msg.COLLAPSE_BLOCK = "ပလွၵ်ႉလႅဝ်"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "သီ 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "သီ 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "သႅၼ်း"; -Blockly.Msg.COLOUR_BLEND_TITLE = "လေႃးလႄး"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "ဢဝ်သီသွင်ဢၼ်လေႃးၵၼ် ၸွမ်းၼမ် သႅၼ်းဢၼ်ပၼ်ဝႆႉ (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Color သီ"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "လိူၵ်ႈသီ တမ်ႈတီႈ ၽႃးလႅတ်ႉ"; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "သီလၢမ်းလိမ်း"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "လိူၵ်ႈသီတမ်ႈတီႈလွၵ်းလၢမ်းလိမ်း"; -Blockly.Msg.COLOUR_RGB_BLUE = "သွမ်ႇ"; -Blockly.Msg.COLOUR_RGB_GREEN = "ၶဵဝ်"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "လီင်"; -Blockly.Msg.COLOUR_RGB_TITLE = "ႁူမ်ႈၵိုၵ်းသီ"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "ႁဵတ်းတူၺ်း သီဢၼ်ၼိုင်ႈ ၸွမ်းၼင်ႇမၵ်းမၼ်ႈဝႆႉ ၼႂ်းၶႂၢင်ႇ သီလႅင်, ၶဵဝ် လႄႈ သွမ်ႇ။ ၼမ်ႉၼၵ်းသီ တေလႆႈမီးၼႂ်းဝူင်ႈၵၢင် 0 တေႃႇ 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "ဢွၵ်ႇတီႈၶွပ်ႇမူၼ်း"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "သိုပ်ႇပၼ်ႇထႅင်ႈ ၶွပ်ႇမူၼ်းတၢင်ႇဢၼ်"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "ၵိုတ်းပႅတ်ႈ ၶွပ်ႇမူၼ်း ဢၼ်မီးဝႆႉ"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "ဝဵၼ်ႉဝႆႉ ၶွပ်ႇမူၼ်း ဢၼ်ၵိုတ်းၸိူဝ်ႈဝႆႉ, သေ သိုပ်ႇထႅင်ႈတၢင်ႇဢၼ်"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "ၾၢင်ႉ: ပလွၵ်ႉဢၼ်ၼႆႉ ၵူၺ်းၸႂ်ႉလူၺ်ႈတႃႇ ၶွပ်ႇမူၼ်းၵူၺ်း"; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "တႃႇၵူႈဢၼ်ဢၼ် ၼႂ်း %1 သဵၼ်ႈမၢႆ %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "For each item in a list, set the variable '%1' to the item, and then do some statements."; // untranslated -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "တႄႇဢၢၼ်ႇၵိုၵ်း %1 တေႃႇ %2 တေႃႇ %3 လူၺ်ႈ %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Have the variable '%1' take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks."; // untranslated -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "သင်ဝႃႈ ပလွၵ်ႉၸိုင် သႂ်ႇပၼ်လွင်ႈတၢင်းမၼ်း တမ်ႈ"; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "သႂ်ႇၵမ်းလိုၼ်း, သင်ဝႃႈ ပလွၵ်ႉၸိုင် ဢဝ်လွင်ႈတၢင်းမၼ်းတင်းသဵင်ႈ တမ်ႈ"; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Add, remove, or reorder sections to reconfigure this if block."; // untranslated -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "လိူဝ်သေၼၼ်ႉ"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "သင်ဝႃႈ လိူဝ်သေၼၼ်ႉ"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "သင်ဝႃႈ"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "ပေႃးဝႃႈ ၵႃႈၶၼ် (ၼမ်ႉၵတ်ႉ) မၢၼ်ႇမႅၼ်ႈယဝ်ႉၸိုင် ႁဵတ်းၶေႃႈၵဵပ်းထွၼ်ၵမ်ႈၽွင်ႈ"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "သင်ဝႃႈ ၵႃႈၶၼ်(ၼမ်ႉၵတ်ႉ)မၢၼ်ႇမႅၼ်ႈၸိုင် ႁဵတ်းပလွၵ်ႉဢွၼ်တၢင်းသုတ်း တီႈၼႂ်းၶေႃႈၵဵပ်းထွၼ်တ။ လိူဝ်သေၼၼ်ႉ ႁဵတ်းပႅတ်ႈ ပလွၵ်ႉသွင် တီႈၼႂ်းၶေႃႈၵဵပ်းထွၼ်"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "သင်ဝႃႈ ၵႃႈၶၼ်(ၼမ်ႉၵတ်ႉ)မၢႉၼိုင်ႈ မၢၼ်ႇမႅၼ်ႈၸိုင် ႁဵတ်းပလွၵ်ႉဢွၼ်တၢင်းသုတ်း တီႈၼႂ်းၶေႃႈၵဵပ်းထွၼ်တ။ သင်ဝႃႈ ၵႃႈၶၼ်(ၼမ်ႉၵတ်ႉ)မၢႆသွင်မၢၼ်ႇမႅၼ်ႈၸိုင် ႁဵတ်းပႅတ်ႈ ပလွၵ်ႉသွင် တီႈၼႂ်းၶေႃႈၵဵပ်းထွၼ်"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "သင်ဝႃႈ ၵႃႈၶၼ်(ၼမ်ႉၵတ်ႉ)မၢႆၼိုင်ႈ မၢၼ်ႇမႅၼ်ႈၸိုင် ႁဵတ်းပလွၵ်ႉဢွၼ်တၢင်းသုတ်း တီႈၼႂ်းၶေႃႈၵဵပ်းထွၼ်တ။ လိူဝ်သေၼၼ်ႉ, သင်ဝႃႈ ၵႃႈၶၼ် (ၼမ်ႉၵတ်ႉ) မၢႆသွင် မၢၼ်ႇမႅၼ်ႈၸိုင် ႁဵတ်းပႅတ်ႈ ပလွၵ်ႉသွင် တီႈၼႂ်းၶေႃႈၵဵပ်းထွၼ်တ။ သင်ဝႃႈ ၵႃႈၶၼ်(ၼမ်ႉၵတ်ႉ) ဢမ်ႇမီးလွင်ႈမၢၼ်ႇမႅၼ်ႈ သင်ၸိုင် ႁဵတ်းပႅတ်ႈပလွၵ်ႉ ၵမ်းလိုမ်း တီႈၼႂ်းၶေႃႈၵဵပ်းထွၼ်တ။"; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop တႃႇတူင်ႇမူၼ်း"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "ႁဵတ်း"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "ပၼ်ႇၶိုၼ်း %1 ၵမ်း"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "ႁဵတ်းၶေႃႈၵဵပ်းထွၼ်ၵမ်ႈၽွင်ႈ တင်းၼမ်"; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "တိုၵ်ႉလိုမ်ႉထိုင်"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "ၶၢဝ်းတိုၵ်ႉလိုမ်ႉ"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "ပေႃးဝႃႈ ၵႃႈၶၼ် (ၼမ်ႉၵတ်ႉ) ဢမ်ႇမၢၼ်ႇမႅၼ်ႈၸိုင် ႁဵတ်းၶေႃႈၵဵပ်းထွၼ် ၵမ်ႈၽွင်ႈ"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "ပေႃးဝႃႈ ၵႃႈၶၼ် (ၼမ်ႉၵတ်ႉ) မၢၼ်ႇမႅၼ်ႈယဝ်ႉၸိုင် ႁဵတ်းၶေႃႈၵဵပ်းထွၼ်ၵမ်ႈၽွင်ႈ"; -Blockly.Msg.DELETE_ALL_BLOCKS = "Delete all %1 blocks?"; // untranslated -Blockly.Msg.DELETE_BLOCK = "မွတ်ႇပလွၵ်ႉ"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "မွတ်ႇပလွၵ်ႉ %1"; -Blockly.Msg.DISABLE_BLOCK = "ဢမ်ႇၸၢင်ႈပလွၵ်ႉ"; -Blockly.Msg.DUPLICATE_BLOCK = "ထုတ်ႇ"; -Blockly.Msg.ENABLE_BLOCK = "ၵမ်ႉထႅမ်ပၼ် ပလွၵ်ႉ"; -Blockly.Msg.EXPAND_ALL = "ၶႂၢၵ်ႈပလွၵ်ႉတင်းၼမ်"; -Blockly.Msg.EXPAND_BLOCK = "ၶႂၢၵ်ႈပလွၵ်ႉ"; -Blockly.Msg.EXTERNAL_INPUTS = "ၶိူင်ႈဢၼ်လုၵ်ႉတၢင်းၼွၵ်ႈၶဝ်ႈမႃး"; -Blockly.Msg.HELP = "ၸွႆႈထႅမ်"; -Blockly.Msg.INLINE_INPUTS = "ၶိူင်ႈဢၼ်ၶဝ်ႈမႃးၸွမ်းလႅင်း"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "create empty list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Returns a list, of length 0, containing no data records"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "list"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Add, remove, or reorder sections to reconfigure this list block."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "create list with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Add an item to the list."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Create a list with any number of items."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_FIRST = "first"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# from end"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "get"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "get and remove"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_LAST = "last"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "random"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "remove"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Removes and returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Removes and returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Removes and returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Removes and returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Removes the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Removes the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Removes the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Removes a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "to # from end"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "to #"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "to last"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "get sub-list from first"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "get sub-list from # from end"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "get sub-list from #"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Creates a copy of the specified portion of a list."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 is the last item."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 is the first item."; // untranslated -Blockly.Msg.LISTS_INDEX_OF_FIRST = "find first occurrence of item"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "find last occurrence of item"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Returns the index of the first/last occurrence of the item in the list. Returns %1 if item is not found."; // untranslated -Blockly.Msg.LISTS_INLIST = "in list"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 is empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Returns true if the list is empty."; // untranslated -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "length of %1"; // untranslated -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Returns the length of a list."; // untranslated -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "create list with item %1 repeated %2 times"; // untranslated -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Creates a list consisting of the given value repeated the specified number of times."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "as"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INSERT = "insert at"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_SET = "set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserts the item at the start of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Inserts the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Append the item to the end of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Inserts the item randomly in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Sets the first item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Sets the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Sets the last item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Sets a random item in a list."; // untranslated -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "make list from text"; // untranslated -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "make text from list"; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "ဢမ်ႇၼႅၼ်ႈၼႃ"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "မၢၼ်ႇမႅၼ်ႈလႄႈသင် ဢမ်ႇၼႅၼ်ႈၼႃလႄႈသင် ႁူၼ်ၶိုၼ်း"; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "မၢၼ်ႇမႅၼ်ႈ"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(ပၢႆးၼပ်ႉ)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ တင်းသွင် မိူၼ်တၢင်ႇဢၼ်ၸိုင် မႄးၶိုၼ်း ႁႂ်ႈမၢၼ်ႇမႅၼ်ႈ"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ ဢွၼ်တၢင်း ယႂ်ႇလိူဝ် ဢၼ်ၽိူမ်ႉသႂ်ႇ မၢႆသွင်ၸိုင် မႄးၶိုၼ်း ႁႂ်ႈမၢၼ်ႇမႅၼ်ႈ"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ ဢွၼ်တၢင်း ယႂ်ႇလိူဝ် ဢမ်ႇၼၼ် ၽဵင်ႇပဵင်း ဢၼ်ၽိူမ်ႉသႂ်ႇ မၢႆသွင်ၸိုင် မႄးၶိုၼ်း ႁႂ်ႈမၢၼ်ႇမႅၼ်ႈ"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ ဢွၼ်တၢင်း မိူၼ် ဢၼ်ၽိူမ်ႉသႂ်ႇ မၢႆသွင်ၸိုင် မႄးၶိုၼ်း ႁႂ်ႈမၢၼ်ႇမႅၼ်ႈ"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ ဢွၼ်တၢင်း မိူၼ် ဢမ်ႇၼၼ် ၽဵင်ႇပဵင်း ဢၼ်ၽိူမ်ႉသႂ်ႇ မၢႆသွင်ၸိုင် မႄးၶိုၼ်း ႁႂ်ႈမၢၼ်ႇမႅၼ်ႈ"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ တင်းသွင် ဢမ်ႇမိူၼ်တၢင်ႇဢၼ်ၸိုင် မႄးၶိုၼ်း ႁႂ်ႈမၢၼ်ႇမႅၼ်ႈ"; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "ဢမ်ႇၸႂ်ႈ %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ ဢမ်ႇၼႅၼ်ႈၼႃၸိုင် မႄးၶိုၼ်း ႁႂ်ႈမၢၼ်ႇမႅၼ်ႈ။ သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ မၢၼ်ႇမႅၼ်ႈၸိုင် ၶိုၼ်းမူၼ်ႉမႄး ႁႂ်ႈၼႅၼ်ႈၼႃ"; -Blockly.Msg.LOGIC_NULL = "ဢမ်ႇၶဝ်ႈၶႂၢင်ႇ"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "လဵဝ်ၶိုၼ်း ဢမ်ႇၶဝ်ႈၶႂၢင်ႇ"; -Blockly.Msg.LOGIC_OPERATION_AND = "လႄႈ"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "ဢမ်ႇၼၼ်"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ တင်းသွင်ဢၼ် မၢၼ်ႇမႅၼ်ႈၸိုင်ၸိုင် မႄးၶိုၼ်း ႁႂ်ႈမၢၼ်ႇမႅၼ်ႈ"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ ၵမ်းလိုၼ်းသုတ်း မၢၼ်ႇမႅၼ်ႈၸိုင် မႄးၶိုၼ်း ႁႂ်ႈမၢၼ်ႇမႅၼ်ႈ"; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "ၸၢမ်း"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "သင်ဝႃႈ ဢမ်ႇၼႅၼ်ႈၼႃ"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "သင်ဝႃႈ မၢၼ်ႇမႅၼ်ႈ"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "ၸၢမ်းၵူတ်ႇတူၺ်း သၢႆငၢႆ။ သင်ဝႃႈ သၢႆငၢႆမၢၼ်ႇမႅၼ်ႈ, လဵဝ်ၶိုၼ်း ၵႃႈၶၼ် (ၼမ်ႉၵတ်ႉ) 'သင်မၢၼ်ႇမႅၼ်ႈ'; လိူဝ်ၼၼ်ႉ လဵဝ်ၶိုၼ်း ၵႃႈၶၼ် (ၼမ်ႉၵတ်ႉ) 'သင်ဢမ်ႇၼႅၼ်ႈၼႃ'။"; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/ပၢႆးၼပ်ႉ"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "လဵဝ်ၶိုၼ်း တၢင်းၼမ် ၼႂ်းမၢႆၼပ်ႉ သွင်"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "လဵဝ်ၶိုၼ်း ပမႃႇၼ ၼႂ်းမၢႆၼပ်ႉ သွင်"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "လဵဝ်ၶိုၼ်း ဢၼ်ပႅၵ်ႇပိူင်ႈ ၼႂ်းမၢႆၼပ်ႉ သွင်"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "လဵဝ်ၶိုၼ်း ဢၼ်ဢဝ်ဢွၵ်ႇ ၼႂ်းမၢႆၼပ်ႉ သွင်"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "လဵဝ်ၶိုၼ်း တူဝ်ၼပ်ႉမၢႆၼိုင်ႈၼႆႉ ၸွႆႈႁႅင်းပၼ် တူဝ်ၼပ်ႉမၢႆသွင်"; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; // untranslated -Blockly.Msg.MATH_CHANGE_TITLE = "change %1 by %2"; // untranslated -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Add a number to variable '%1'."; // untranslated -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; // untranslated -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; // untranslated -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "constrain %1 low %2 high %3"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Constrain a number to be between the specified limits (inclusive)."; // untranslated -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "is divisible by"; // untranslated -Blockly.Msg.MATH_IS_EVEN = "ပဵၼ်ၵူပ်ႉ"; -Blockly.Msg.MATH_IS_NEGATIVE = "is negative"; // untranslated -Blockly.Msg.MATH_IS_ODD = "ပဵၼ်ၵိၵ်ႈ"; -Blockly.Msg.MATH_IS_POSITIVE = "is positive"; // untranslated -Blockly.Msg.MATH_IS_PRIME = "is prime"; // untranslated -Blockly.Msg.MATH_IS_TOOLTIP = "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false."; // untranslated -Blockly.Msg.MATH_IS_WHOLE = "is whole"; // untranslated -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; // untranslated -Blockly.Msg.MATH_MODULO_TITLE = "remainder of %1 ÷ %2"; // untranslated -Blockly.Msg.MATH_MODULO_TOOLTIP = "Return the remainder from dividing the two numbers."; // untranslated -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/မၢႆၼပ်ႉ"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "မၢႆၼပ်ႉ ၼိုင်ႈဢၼ်"; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "average of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "max of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "median of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "min of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "modes of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "random item of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "standard deviation of list"; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "sum of list"; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Return the average (arithmetic mean) of the numeric values in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Return the largest number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Return the median number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Return the smallest number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Return a list of the most common item(s) in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Return a random element from the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Return the standard deviation of the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Return the sum of all the numbers in the list."; // untranslated -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "random fraction"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive)."; // untranslated -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TITLE = "random integer from %1 to %2"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Return a random integer between the two specified limits, inclusive."; // untranslated -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; // untranslated -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "round"; // untranslated -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "round down"; // untranslated -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "round up"; // untranslated -Blockly.Msg.MATH_ROUND_TOOLTIP = "Round a number up or down."; // untranslated -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root (မၢႆတူပ်ႉမိူၼ်)"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "ပၵတိ"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "မၢႆတူပ်ႉမိူၼ်"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "လဵဝ်ၶိုၼ်း ၵႃႈၶၼ် (ၼမ်ႉၵတ်ႉ) ပၵတိ ၼႂ်းမၢႆၼပ်ႉ"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "လဵဝ်ၶိုၼ်း e ၵႂႃႇတီႈ ပႃႇဝႃႇ ၼႂ်းမၢႆၼပ်ႉ"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "လဵဝ်ၶိုၼ်း လွၵ်းလၢႆးၼပ်ႉ ၼႂ်းမၢႆၼပ်ႉ"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "လဵဝ်ၶိုၼ်း ပိုၼ်ႉထၢၼ် 10 လွၵ်းလၢႆးၼပ်ႉ ၼႂ်းမၢႆၼပ်ႉ"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "လဵဝ်ၶိုၼ်း ဢၼ်သၢၼ်ၶတ်း ၼႂ်း မၢႆၼပ်ႉ"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "လဵဝ်ၶိုၼ်း 10 ၵႂႃႇတီႈ ပႃႇဝႃႇ ၼႂ်းမၢႆၼပ်ႉ"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "လဵဝ်ၶိုၼ်း မၢႆတူပ်ႉမိူၼ် ၼႂ်းမၢႆၼပ်ႉ"; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; // untranslated -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Return the arccosine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Return the arcsine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Return the arctangent of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Return the cosine of a degree (not radian)."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Return the sine of a degree (not radian)."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Return the tangent of a degree (not radian)."; // untranslated -Blockly.Msg.NEW_VARIABLE = "လၢႆႈဢၼ်မႂ်ႇ"; -Blockly.Msg.NEW_VARIABLE_TITLE = "ၸိုဝ်ႈဢၼ်လၢႆႈမႂ်ႇ"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "allow statements"; // untranslated -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "with:"; // untranslated -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Run the user-defined function '%1'."; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Run the user-defined function '%1' and use its output."; // untranslated -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "with:"; // untranslated -Blockly.Msg.PROCEDURES_CREATE_DO = "Create '%1'"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "do something"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "to"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Creates a function with no output."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "return"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Creates a function with an output."; // untranslated -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Warning: This function has duplicate parameters."; // untranslated -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Highlight function definition"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "If a value is true, then return a second value."; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Warning: This block may be used only within a function definition."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "input name:"; // untranslated -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Add an input to the function."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "inputs"; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Add, remove, or reorder inputs to this function."; // untranslated -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "ဢဝ်ဢွၵ်ႇ ၶေႃႈၵႂၢမ်း"; -Blockly.Msg.RENAME_VARIABLE = "လိုမ်ႉၶိုၼ်း ဢၼ်လၢႆႈမႂ်ႇ"; -Blockly.Msg.RENAME_VARIABLE_TITLE = "လိုမ်ႉၶိုၼ်း ဢၼ်လၢႆႈမႂ်ႇၸိူဝ်းၼၼ်ႉ '%1' ထိုင်"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "append text"; // untranslated -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "to"; // untranslated -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Append some text to variable '%1'."; // untranslated -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "to lower case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "to Title Case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "to UPPER CASE"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; // untranslated -Blockly.Msg.TEXT_CHARAT_FIRST = "get first letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_FROM_END = "get letter # from end"; // untranslated -Blockly.Msg.TEXT_CHARAT_FROM_START = "get letter #"; // untranslated -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "in text"; // untranslated -Blockly.Msg.TEXT_CHARAT_LAST = "get last letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_RANDOM = "get random letter"; // untranslated -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Returns the letter at the specified position."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Add an item to the text."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "join"; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Add, remove, or reorder sections to reconfigure this text block."; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "to letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "to letter #"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "to last letter"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "in text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "get substring from first letter"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "get substring from letter # from end"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "get substring from letter #"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returns a specified portion of the text."; // untranslated -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "in text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "find first occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "find last occurrence of text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found."; // untranslated -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 is empty"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returns true if the provided text is empty."; // untranslated -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "create text with"; // untranslated -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Create a piece of text by joining together any number of items."; // untranslated -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "length of %1"; // untranslated -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Returns the number of letters (including spaces) in the provided text."; // untranslated -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "print %1"; // untranslated -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Print the specified text, number or other value."; // untranslated -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Prompt for user for a number."; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Prompt for user for some text."; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "prompt for number with message"; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "prompt for text with message"; // untranslated -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; // untranslated -Blockly.Msg.TEXT_TEXT_TOOLTIP = "A letter, word, or line of text."; // untranslated -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "trim spaces from both sides of"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "trim spaces from left side of"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "trim spaces from right side of"; // untranslated -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Return a copy of the text with spaces removed from one or both ends."; // untranslated -Blockly.Msg.TODAY = "မိူဝ်ႈၼႆႉ"; -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "ဢၼ်"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Create 'set %1'"; // untranslated -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returns the value of this variable."; // untranslated -Blockly.Msg.VARIABLES_SET = "set %1 to %2"; // untranslated -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Create 'get %1'"; // untranslated -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Sets this variable to be equal to the input."; // untranslated -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/sk.js b/backend/_pv_1_3_5/static/blockly/msg/js/sk.js deleted file mode 100755 index d929eef20..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/sk.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.sk'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Pridať komentár"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Zmeniť hodnotu:"; -Blockly.Msg.CLEAN_UP = "Narovnať bloky"; -Blockly.Msg.COLLAPSE_ALL = "Zvinúť bloky"; -Blockly.Msg.COLLAPSE_BLOCK = "Zvinúť blok"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "farba 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "farba 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "pomer"; -Blockly.Msg.COLOUR_BLEND_TITLE = "zmiešať"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Zmieša dve farby v danom pomere (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Zvoľte farbu z palety."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "náhodná farba"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Zvoliť farbu náhodne."; -Blockly.Msg.COLOUR_RGB_BLUE = "modrá"; -Blockly.Msg.COLOUR_RGB_GREEN = "zelená"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "červená"; -Blockly.Msg.COLOUR_RGB_TITLE = "ofarbiť s"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Vytvoriť farbu pomocou zadaného množstva červenej, zelenej a modrej. Množstvo musí byť medzi 0 a 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "opustiť slučku"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "prejdi na nasledujúce opakovanie slučky"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Opustiť túto slučku."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Vynechať zvyšok tejto slučky a pokračovať ďalším opakovaním."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Upozornenie: Tento blok sa môže používať len v rámci slučky."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "pre každý prvok %1 v zozname %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Pre každý prvok v zozname priraď jeho hodnotu do premenej '%1' a vykonaj príkazy."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "počítať s %1 od %2 do %3 o %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Nechá premennú '%1' nadobúdať hodnoty od začiatočného čísla po konečné s daným medzikrokom a vykoná zadané bloky."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Pridať podmienku k \"ak\" bloku."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Pridať poslednú záchytnú podmienku k \"ak\" bloku."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Pridať, odstrániť alebo zmeniť poradie oddielov tohto \"ak\" bloku."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "inak"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "inak ak"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "ak"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Ak je hodnota pravda, vykonaj príkazy."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Ak je hodnota pravda, vykonaj príkazy v prvom bloku. Inak vykonaj príkazy v druhom bloku."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Ak je prvá hodnota pravda, vykonaj príkazy v prvom bloku. Inak, ak je druhá hodnota pravda, vykonaj príkazy v druhom bloku."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Ak je prvá hodnota pravda, vykonaj príkazy v prvom bloku. Inak, ak je druhá hodnota pravda, vykonaj príkazy v druhom bloku. Ak ani jedna hodnota nie je pravda, vykonaj príkazy v poslednom bloku."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "rob"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "opakuj %1 krát"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Opakuj určité príkazy viackrát."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "opakuj kým nebude"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "opakuj kým"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Kým je hodnota nepravdivá, vykonávaj príkazy."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Kým je hodnota pravdivá, vykonávaj príkazy."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Zmazať všetkých %1 dielcov?"; -Blockly.Msg.DELETE_BLOCK = "Odstrániť blok"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Odstrániť %1 blokov"; -Blockly.Msg.DISABLE_BLOCK = "Vypnúť blok"; -Blockly.Msg.DUPLICATE_BLOCK = "Duplikovať"; -Blockly.Msg.ENABLE_BLOCK = "Povoliť blok"; -Blockly.Msg.EXPAND_ALL = "Rozvinúť bloky"; -Blockly.Msg.EXPAND_BLOCK = "Rozvinúť blok"; -Blockly.Msg.EXTERNAL_INPUTS = "Vonkajšie vstupy"; -Blockly.Msg.HELP = "Pomoc"; -Blockly.Msg.INLINE_INPUTS = "Riadkové vstupy"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "prázdny zoznam"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Vráti zoznam nulovej dĺžky, ktorý neobsahuje žiadne prvky."; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "zoznam"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Pridaj, odstráň alebo zmeň poradie v tomto zoznamovom bloku."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "vytvor zoznam s"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Pridaj prvok do zoznamu."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Vytvor zoznam s ľubovoľným počtom prvkov."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "prvý"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# od konca"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "zisti"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "zisti a odstráň"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "posledný"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "náhodný"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "odstráň"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Vráti počiatočný prvok zoznamu."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Vráti prvok na určenej pozícii v zozname."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Vráti posledný prvok zoznamu."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Vráti náhodný prvok zoznamu."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Odstráni a vráti prvý prvok v zozname."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Odstráni a vráti prvok z určenej pozície v zozname."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Odstráni a vráti posledný prvok v zozname."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Odstráni a vráti náhodný prvok v zozname."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Odstráni prvý prvok v zozname."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Odstráni prvok na určenej pozícii v zozname."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Odstráni posledný prvok v zozname."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Odstráni náhodný prvok v zozname."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "po # od konca"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "po #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "po koniec"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "Získať podzoznam od začiatku"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "Získať podzoznam od # od konca"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "získať podzoznam od #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Skopíruje určený úsek zoznamu."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 je posledný prvok."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 je počiatočný prvok."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "nájdi prvý výskyt prvku"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "nájdi posledný výskyt prvku"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Vráti index prvého/posledného výskytu prvku v zozname. Ak sa nič nenašlo, vráti %1."; -Blockly.Msg.LISTS_INLIST = "v zozname"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 je prázdny"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Vráti pravda, ak je zoznam prázdny."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "dĺžka %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Vráti dĺžku zoznamu"; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "vytvor zoznam s prvkom %1 opakovaným %2 krát"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Vytvorí zoznam s niekoľkými rovnakými prvkami s danou hodnotou."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "ako"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "vložiť na"; -Blockly.Msg.LISTS_SET_INDEX_SET = "nastaviť"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Vsunie prvok na začiatok zoznamu."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Vsunie prvok na určenú pozíciu v zozname."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Pripojí prvok na koniec zoznamu."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Vsunie prvok na náhodné miesto v zozname."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Nastaví prvý prvok v zozname."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Nastaví prvok na určenej pozícii v zozname."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Nastaví posledný prvok v zozname."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Nastaví posledný prvok v zozname."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "vytvoriť zoznam z textu"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "vytvoriť text zo zoznamu"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Spojiť zoznam textov do jedného textu s oddeľovačmi."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Rozdelenie textu do zoznamu textov, lámanie na oddeľovačoch."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "s oddeľovačom"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "nepravda"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Vráť buď hodnotu pravda alebo nepravda."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "pravda"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Vráť hodnotu pravda, ak sú vstupy rovnaké."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Vráť hodnotu pravda ak prvý vstup je väčší než druhý."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Vráť hodnotu pravda ak prvý vstup je väčší alebo rovný druhému."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Vráť hodnotu pravda, ak prvý vstup je menší než druhý."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Vráť hodnotu pravda ak prvý vstup je menší alebo rovný druhému."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Vráť hodnotu pravda, ak vstupy nie sú rovnaké."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "nie je %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Vráti hodnotu pravda, ak je vstup nepravda. Vráti hodnotu nepravda ak je vstup pravda."; -Blockly.Msg.LOGIC_NULL = "nič"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Vráti hodnotu nula."; -Blockly.Msg.LOGIC_OPERATION_AND = "a"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "alebo"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Vráť hodnotu pravda, ak sú vstupy pravdivé."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Vráť hodnotu pravda, ak je aspoň jeden vstup pravda."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "ak nepravda"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "ak pravda"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Skontroluj podmienku testom. Ak je podmienka pravda, vráť hodnotu \"ak pravda\", inak vráť hodnotu \"ak nepravda\"."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Arithmetic"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Vráť súčet dvoch čísel."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Vráť podiel dvoch čísel."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Vráť rozdiel dvoch čísel."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Vráť súčin dvoch čísel."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Vráť prvé číslo umocnené druhým."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "zmeniť %1 o %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Pridaj číslo do premennej \"%1\"."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant‎"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Vráť jednu zo zvyčajných konštánt: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), alebo ∞ (nekonečno)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "obmedz %1 od %2 do %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Obmedzí číslo do zadaných hraníc (vrátane)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "je deliteľné"; -Blockly.Msg.MATH_IS_EVEN = "je párne"; -Blockly.Msg.MATH_IS_NEGATIVE = "je záporné"; -Blockly.Msg.MATH_IS_ODD = "je nepárne"; -Blockly.Msg.MATH_IS_POSITIVE = "je kladné"; -Blockly.Msg.MATH_IS_PRIME = "je prvočíslo"; -Blockly.Msg.MATH_IS_TOOLTIP = "Skontroluj či je číslo párne, nepárne, celé, kladné, záporné alebo deliteľné určitým číslom. Vráť hodnotu pravda alebo nepravda."; -Blockly.Msg.MATH_IS_WHOLE = "je celé číslo"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "zvyšok po delení %1 + %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Vráť zvyšok po delení jedného čísla druhým."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Číslo."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "priemer zoznamu"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "najväčšie v zozname"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "medián zoznamu"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "najmenšie v zozname"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "najčastejšie v zozname"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "náhodný prvok zoznamu"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "smerodajná odchýlka zoznamu"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "súčet zoznamu"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Vráť aritmetický priemer čísel v zozname."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Vrátiť najväčšie číslo v zozname."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Vráť medián čísel v zozname."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Vrátiť najmenšie číslo v zozname."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Vrátiť najčastejší prvok v zozname."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Vráť náhodne zvolený prvok zoznamu."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Vráť smeroddajnú odchýlku zoznamu."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Vráť súčet všetkých čísel v zozname."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "náhodné číslo od 0 do 1"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Vráť náhodné číslo z intervalu 0.0 (vrátane) až 1.0."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "náhodné celé číslo od %1 do %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Vráť náhodné celé číslo z určeného intervalu (vrátane)."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "zaokrúhli"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "zaokrúhli nadol"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "zaokrúhli nahor"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Zaokrúhli číslo nahor alebo nadol."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absolútna hodnota"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "druhá odmocnina"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Vráť absolútnu hodnotu čísla."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Vráť e umocnené číslom."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Vráť prirodzený logaritmus čísla."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Vráť logaritmus čísla so základom 10."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Vráť opačné číslo."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Vráť 10 umocnené číslom."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Vráť druhú odmocninu čísla."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "arccos"; -Blockly.Msg.MATH_TRIG_ASIN = "arcsin"; -Blockly.Msg.MATH_TRIG_ATAN = "arctan"; -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Vráť arkus kosínus čísla."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Vráť arkus sínus čísla."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Vráť arkus tangens čísla."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Vráť kosínus uhla (v stupňoch)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Vráť sínus uhla (v stupňoch)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Vráť tangens uhla (v stupňoch)."; -Blockly.Msg.NEW_VARIABLE = "Nová premenná..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Názov novej premennej:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "povoliť príkazy"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "s:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Spustí používateľom definovanú funkciu '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Spustí používateľom definovanú funkciu '%1' a použije jej výstup."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "s:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Vytvoriť '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Doplň, čo robí táto funkcia..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "urob niečo"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "na"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Vytvorí funciu bez výstupu."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "vrátiť"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Vytvorí funkciu s výstupom."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Upozornenie: Táto funkcia má duplicitné parametre."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Zvýrazniť definíciu funkcie"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Ak je hodnota pravda, tak vráti druhú hodnotu."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Upozornenie: Tento blok môže byť len vo vnútri funkcie."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "názov vstupu:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Pridať vstup do funkcie."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "vstupy"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Pridať, odstrániť alebo zmeniť poradie vstupov tejto funkcie."; -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "Odstrániť komentár"; -Blockly.Msg.RENAME_VARIABLE = "Premenovať premennú..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Premenovať všetky premenné '%1' na:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "pridaj text"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "do"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Pridaj určitý text do premennej '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "na malé písmená"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "na Veľké Začiatočné Písmená"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "na VEĽKÉ PÍSMENÁ"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Vráť kópiu textu s inou veľkosťou písmen."; -Blockly.Msg.TEXT_CHARAT_FIRST = "zisti prvé písmeno"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "zisti # písmeno od konca"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "zisti písmeno #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "v texte"; -Blockly.Msg.TEXT_CHARAT_LAST = "zisti posledné písmeno"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "vyber náhodné písmeno"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Vráti písmeno na určenej pozícii."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Pridaj prvok do textu."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "spoj"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Pridaj, odstráň alebo zmeň poradie oddielov v tomto textovom bloku."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "po # písmeno od konca"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "po písmeno #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "po koniec"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "v texte"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "vyber podreťazec od začiatku"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "vyber podreťazec od # písmena od konca"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "vyber podreťazec od písmena #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Vráti určenú časť textu."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "v texte"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "nájdi prvý výskyt textu"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "nájdi posledný výskyt textu"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Vráti index prvého/posledného výskytu prvého textu v druhom texte. Ak nenájde, vráti %1."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 je prázdny"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Vráti hodnotu pravda, ak zadaný text je prázdny."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "vytvor text z"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Vytvor text spojením určitého počtu prvkov."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "dĺžka %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Vráti počet písmen (s medzerami) v zadanom texte."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "píš %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Napíš zadaný text, číslo alebo hodnotu."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Výzva pre používateľa na zadanie čísla."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Výzva pre používateľa na zadanie textu."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "výzva na zadanie čísla so správou"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "výzva za zadanie textu so správou"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Písmeno, slovo alebo riadok textu."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "odstráň medzery z oboch strán"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "odstráň medzery z ľavej strany"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "odstráň medzery z pravej strany"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Vráť kópiu textu bez medzier na jednom alebo oboch koncoch."; -Blockly.Msg.TODAY = "Dnes"; -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "prvok"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Vytvoriť \"nastaviť %1\""; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Vráti hodnotu tejto premennej."; -Blockly.Msg.VARIABLES_SET = "nastaviť %1 na %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Vytvoriť \"získať %1\""; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Nastaví túto premennú, aby sa rovnala vstupu."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/sl.js b/backend/_pv_1_3_5/static/blockly/msg/js/sl.js deleted file mode 100755 index adf537dad..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/sl.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.sl'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Dodaj komentar"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Spremeni vrednost:"; -Blockly.Msg.CLEAN_UP = "Ponastavi kocke"; -Blockly.Msg.COLLAPSE_ALL = "Skrči kocke"; -Blockly.Msg.COLLAPSE_BLOCK = "Skrči kocko"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "barva 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "barva 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "razmerje"; -Blockly.Msg.COLOUR_BLEND_TITLE = "mešanica"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Zmeša dve barvi v danem razmerju (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Izberi barvo s palete."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "naključna barva"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Izbere naključno barvo."; -Blockly.Msg.COLOUR_RGB_BLUE = "modra"; -Blockly.Msg.COLOUR_RGB_GREEN = "zelena"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "rdeča"; -Blockly.Msg.COLOUR_RGB_TITLE = "določena barva"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Ustvari barvo z določeno količino rdeče, zelene in modre. Vse vrednosti morajo biti med 0 in 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "izstopi iz zanke"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "nadaljuj z naslednjo ponovitvijo zanke"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Izstopi iz trenutne zanke."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Preskoči preostanek te zanke in nadaljuje z naslednjo ponovitvijo."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Pozor: To kocko lahko uporabiš samo znotraj zanke."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; -Blockly.Msg.CONTROLS_FOREACH_TITLE = "za vsak element %1 v seznamu %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Za vsak element v seznamu, nastavi spremenljivko '%1' na ta element. Pri tem se izvedejo določene kocke."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; -Blockly.Msg.CONTROLS_FOR_TITLE = "štej s/z %1 od %2 do %3 s korakom %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Vrednost spremenljivke '%1' se spreminja od začetnega števila do končnega števila, z določenim korakom. Pri tem se izvedejo določene kocke."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Dodaj pogoj »če« kocki."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Dodaj končni pogoj »če« kocki."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Dodaj, odstrani ali spremeni vrstni red odsekov za ponovno nastavitev »če« kocke."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "sicer"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "sicer če"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "če"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Če je vrednost resnična, izvedi določene kocke."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Če je vrednost resnična, izvedi prvo skupino kock. Sicer izvedi drugo skupino kock."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Če je prva vrednost resnična, izvedi prvo skupino kock. Sicer, če je resnična druga vrednost, izvedi drugo skupino kock."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Če je prva vrednost resnična, izvedi prvo skupino kock. Sicer, če je resnična druga vrednost, izvedi drugo skupino kock. Če nobena izmed vrednosti ni resnična, izvedi zadnjo skupino kock."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "izvedi"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "ponavljaj %1 krat"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Kocke se izvedejo večkrat."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "ponavljaj dokler"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "ponavljaj"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Kocke se izvajajo dokler je vrednost neresnična."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Kocke se izvajajo dokler je vrednost resnična."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Izbrišem vseh %1 kock?"; -Blockly.Msg.DELETE_BLOCK = "Izbriši kocko"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Izbriši kocke"; -Blockly.Msg.DISABLE_BLOCK = "Onemogoči kocko"; -Blockly.Msg.DUPLICATE_BLOCK = "Podvoji"; -Blockly.Msg.ENABLE_BLOCK = "Omogoči kocko"; -Blockly.Msg.EXPAND_ALL = "Razširi kocke"; -Blockly.Msg.EXPAND_BLOCK = "Razširi kocko"; -Blockly.Msg.EXTERNAL_INPUTS = "Vnosi zunaj"; -Blockly.Msg.HELP = "Pomoč"; -Blockly.Msg.INLINE_INPUTS = "Vnosi v vrsti"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "ustvari prazen seznam"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Vrne seznam, dolžine 0, ki ne vsebuje nobenih podatkov."; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "seznam"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Doda, odstrani ali spremeni vrstni red elementov tega seznama."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "ustvari seznam s/z"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Doda element seznamu."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Ustvari seznam s poljubnim številom elementov."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "prvo mesto"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "mesto št. od konca"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "št."; -Blockly.Msg.LISTS_GET_INDEX_GET = "vrni"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "odstrani in vrni"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "zadnje mesto"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "naključno mesto"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "odstrani"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Vrne prvi element seznama."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Vrne element na določenem mestu v seznamu."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Vrne zadnji element seznama."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Vrne naključni element seznama."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Odstrani in vrne prvi element seznama."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Odstrani in vrne element na določenem mestu v seznamu."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Odstrani in vrne zadnji element seznama."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Odstrani in vrne naključni element seznama."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Odstrani prvi element seznama."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Odstrani element na določenem mestu v seznamu."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Odstrani zadnji element seznama."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Odstrani naključni element seznama."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "do mesta št. od konca"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "do mesta št."; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "do zadnjega mesta"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "ustvari podseznam od prvega mesta"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "ustvari podseznam od mesta št. od konca"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "ustvari podseznam od mesta št."; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Ustvari nov seznam, kot kopijo določenega dela seznama."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "Zadnji element je št. %1."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "Prvi element je št. %1."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "najdi prvo pojavitev elementa"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; -Blockly.Msg.LISTS_INDEX_OF_LAST = "najdi zadnjo pojavitev elementa"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Vrne mesto (indeks) prve/zadnje pojavitve elementa v seznamu. Če elementa ne najde, vrne %1."; -Blockly.Msg.LISTS_INLIST = "v seznamu"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 je prazen"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Vrne resnično, če je seznam prazen."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; -Blockly.Msg.LISTS_LENGTH_TITLE = "dolžina %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Vrne dolžino seznama."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg.LISTS_REPEAT_TITLE = "ustvari seznam z elementom %1, ki se ponovi %2 krat"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Ustvari seznam z danim elementom, ki se poljubno mnogo krat ponovi."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "element"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "vstavi na"; -Blockly.Msg.LISTS_SET_INDEX_SET = "nastavi na"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Vstavi element na začetek seznama."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Vstavi element na določeno mesto v seznamu."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Doda element na konec seznama."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Vstavi element na naključno mesto v seznamu."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Nastavi prvi element seznama."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Nastavi element na določenem mestu v seznamu."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Nastavi zadnji element seznama."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Nastavi naključni element seznama."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "naraščajoče"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "padajoče"; -Blockly.Msg.LISTS_SORT_TITLE = "uredi %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Uredi kopijo seznama."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "abecedno, brez velikosti črk"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "številčno"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "abecedno"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "ustvari seznam iz besedila"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "ustvari besedilo iz seznama"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Združi seznam besedil v eno besedilo, ločeno z ločilom."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Razdruži besedilo v seznam besedil. Za razdruževanje besedila uporabi ločilo."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "z ločilom"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "neresnično"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Vrne resnično ali neresnično."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "resnično"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Vrne resnično, če sta vnosa enaka."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Vrne resnično, če je prvi vnos večji od drugega."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Vrne resnično, če je prvi vnos večji ali enak drugemu."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Vrne resnično, če je prvi vnos manjši od drugega."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Vrne resnično, če je prvi vnos manjši ali enak drugemu."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Vrne resnično, če vnosa nista enaka."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; -Blockly.Msg.LOGIC_NEGATE_TITLE = "ne %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Vrne resnično, če je vnos neresničen. Vrne neresnično, če je vnos resničen."; -Blockly.Msg.LOGIC_NULL = "prazno"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Vrne prazno."; -Blockly.Msg.LOGIC_OPERATION_AND = "in"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; -Blockly.Msg.LOGIC_OPERATION_OR = "ali"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Vrne resnično, če sta oba vnosa resnična."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Vrne resnično, če je vsaj eden od vnosov resničen."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "če neresnično"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "če resnično"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Preveri pogoj v »testu«. Če je pogoj resničen, potem vrne vrednost »če resnično«; sicer vrne vrednost »če neresnično«."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Arithmetic"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Vrne vsoto dveh števil."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Vrne kvocient dveh števil."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Vrne razliko dveh števil."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Vrne zmnožek dveh števil."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Vrne prvo število na potenco drugega števila."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "spremeni %1 za %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Prišteje število k spremenljivki '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Vrne eno izmed običajnih konstant: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), ali ∞ (neskončno)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; -Blockly.Msg.MATH_CONSTRAIN_TITLE = "omeji %1 na najmanj %2 in največ %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Omeji število, da bo med določenima (vključenima) mejama."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "je deljivo s/z"; -Blockly.Msg.MATH_IS_EVEN = "je sodo"; -Blockly.Msg.MATH_IS_NEGATIVE = "je negativno"; -Blockly.Msg.MATH_IS_ODD = "je liho"; -Blockly.Msg.MATH_IS_POSITIVE = "je pozitivno"; -Blockly.Msg.MATH_IS_PRIME = "je praštevilo"; -Blockly.Msg.MATH_IS_TOOLTIP = "Preveri, če je število sodo, liho, praštevilo, celo, pozitivno, negativno ali, če je deljivo z določenim številom. Vrne resnično ali neresnično."; -Blockly.Msg.MATH_IS_WHOLE = "je celo"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "ostanek pri %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Vrne ostanek pri deljenju dveh števil."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Število."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "povprečje seznama"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "maksimum seznama"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "mediana seznama"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "minimum seznama"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "modus seznama"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "naključni element seznama"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "standardni odklon seznama"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "vsota seznama"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Vrne povprečje (aritmetično sredino) števil na seznamu."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Vrne največje število na seznamu."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Vrne mediano števil na seznamu."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Vrne najmanjše število na seznamu."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Vrne seznam najpogostejšega elementa(-ov) na seznamu."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Vrne naključno število izmed števil na seznamu."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Vrne standardni odklon seznama."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Vrne vsoto vseh števil na seznamu."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "naključni ulomek"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Vrne naključni ulomek med (vključno) 0.0 in 1.0 (izključno)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "naključno število med %1 in %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Vrne naključno število med dvema določenima mejama, vključno z mejama."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "zaokroži"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "zaokroži navzdol"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "zaokroži navzgor"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Zaokroži število navzgor ali navzdol."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absolutno"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "kvadratni koren"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Vrne absolutno vrednost števila."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Vrne e na potenco števila."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Vrne naravni logaritem števila."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Vrne desetiški logaritem števila."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Vrne negacijo števila."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Vrne 10 na potenco števila."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Vrne kvadratni koren števila."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "acos"; -Blockly.Msg.MATH_TRIG_ASIN = "asin"; -Blockly.Msg.MATH_TRIG_ATAN = "atan"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tan"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Vrne arkus kosinus števila."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Vrne arkus sinus števila."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Vrne arkus tangens števila."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Vrne kosinus kota v stopinjah (ne radianih)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Vrne sinus kota v stopinjah (ne radianih)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Vrne tangens kota v stopinjah (ne radianih)."; -Blockly.Msg.NEW_VARIABLE = "Nova spremenljivka..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Ime nove spremenljivke:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "dovoli korake"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "s/z:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Subroutine"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Izvede uporabniško funkcijo '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Subroutine"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Izvede uporabniško funkcijo '%1' in uporabi njen izhod."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "s/z:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Ustvari '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Opišite funkcijo ..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "nekaj"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "izvedi"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Ustvari funkcijo brez izhoda."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "vrni"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Ustvari funkcijo z izhodom."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Pozor: Ta funkcija ima podvojene parametre."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Označi definicijo funkcije"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Če je vrednost resnična, vrne drugo vrednost."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Pozor: To kocko lahko uporabiš samo znotraj definicije funkcije."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "ime vnosa:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Funkciji doda vnos."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "vnosi"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Doda, odstrani ali spremeni vrstni red vnosov te funkcije."; -Blockly.Msg.REDO = "Ponovi"; -Blockly.Msg.REMOVE_COMMENT = "Odstrani komentar"; -Blockly.Msg.RENAME_VARIABLE = "Preimenuj spremenljivko..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Preimenuj vse spremenljivke '%1' v:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "dodaj besedilo"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; -Blockly.Msg.TEXT_APPEND_TO = "k"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Doda besedilo k spremenljivki '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "v male črke"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "v Velike Začetnice"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "v VELIKE ČRKE"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Vrne kopijo besedila v drugi obliki."; -Blockly.Msg.TEXT_CHARAT_FIRST = "vrni prvo črko"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "vrni črko št. od konca"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "vrni črko št."; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "iz besedila"; -Blockly.Msg.TEXT_CHARAT_LAST = "vrni zadnjo črko"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "vrni naključno črko"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Vrne črko na določenem mestu v besedilu."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Doda element k besedilu."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "združi"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Doda, odstrani ali spremeni vrstni red elementov tega besedila."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "do črke št. od konca"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "do črke št."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "do zadnje črke"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "iz besedila"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "vrni del od prve črke"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "vrni del od črke št. od konca"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "vrni del od črke št."; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Vrne določen del besedila."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "v besedilu"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "najdi prvo pojavitev besedila"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "najdi zadnjo pojavitev besedila"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Vrne mesto (indeks) prve/zadnje pojavitve drugega besedila v prvem besedilu. Če besedila ne najde, vrne %1."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 je prazno"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Vrne resnično, če je določeno besedilo prazno."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "ustvari besedilo iz"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Ustvari besedilo tako, da združi poljubno število elementov."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; -Blockly.Msg.TEXT_LENGTH_TITLE = "dolžina %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Vrne število črk oz. znakov (vključno s presledki) v določenem besedilu."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; -Blockly.Msg.TEXT_PRINT_TITLE = "izpiši %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Izpiše določeno besedilo, število ali drugo vrednost."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Vpraša uporabnika za vnos števila."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Vpraša uporabnika za vnos besedila."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "vprašaj za število s sporočilom"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "vprašaj za besedilo s sporočilom"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Črka, beseda ali vrstica besedila."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "odstrani presledke z obeh strani"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "odstrani presledke z leve strani"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "odstrani presledke z desne strani"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Vrne kopijo besedila z odstranjenimi presledki z ene ali obeh strani."; -Blockly.Msg.TODAY = "Danes"; -Blockly.Msg.UNDO = "Razveljavi"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "element"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Ustvari 'nastavi %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Vrne vrednost spremenljivke."; -Blockly.Msg.VARIABLES_SET = "nastavi %1 na %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Ustvari 'vrni %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Nastavi, da je vrednost spremenljivke enaka vnosu."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/sq.js b/backend/_pv_1_3_5/static/blockly/msg/js/sq.js deleted file mode 100755 index c0c6e65a4..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/sq.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.sq'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Vendos nje Koment"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Ndrysho Vlerat:"; -Blockly.Msg.CLEAN_UP = "Clean up Blocks"; // untranslated -Blockly.Msg.COLLAPSE_ALL = "Mbyll blloqet"; -Blockly.Msg.COLLAPSE_BLOCK = "Mbyll bllokun"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "Ngjyra 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "Ngjyra 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "Perpjesetim"; -Blockly.Msg.COLOUR_BLEND_TITLE = "Përzierje"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Perzien dy ngjyra së bashku me një raport të dhënë (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "http://en.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Zgjidh nje ngjyre nga nje game ngjyrash."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "ngjyre e rastesishme"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Zgjidhni një ngjyrë në mënyrë të rastësishme."; -Blockly.Msg.COLOUR_RGB_BLUE = "blu"; -Blockly.Msg.COLOUR_RGB_GREEN = "jeshile"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "e kuqe"; -Blockly.Msg.COLOUR_RGB_TITLE = "ngjyre me"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Krijo një ngjyrë me shumën e specifikuar te te kuqes, te gjelbëres, dhe bluse. Te gjitha vlerat duhet te jene mes 0 dhe 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "dil nga nje faze perseritese"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "vazhdo me elementin tjeter te nje faze perseritese"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Ndahu nga unaza."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Kapërce pjesën e mbetur të unazës, dhe vazhdo me ripërsëritjen tjetër."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Paralajmërim: Ky bllok mund të përdoret vetëm brenda unazës."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "per cdo produkt %1 ne liste %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Per cdo produkt ne nje \"liste\" \"vendos\" ndryshoren '%1' produktit, dhe pastaj bej disa deklarata."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "numero me %1 nga %2 ne %3 me nga %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Bëje identifikuesin \"%1\" që ta ketë vlerat prej numrit të fillimit deri tek numri i fundit, duke numëruar nga intervali i specifikuar, dhe ti bëj blloqet e specifikuara."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "\"Vendos\" \"kushtein\"tek \"pjesa\" \"if\""; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Shto një përfundues, që i mbërrin të gjitha kushtet në bllokun nëse."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Shto, fshij, ose rirregullo sektoret për ta rikonfiguruar këte bllok nëse."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "përndryshe"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "përndryshe nëse"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "nëse"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Nëse një vlerë është e saktë, atëherë ekzekuto disa fjali."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Nëse një vlerë është e saktë, atëherë ekzekuto bllokun e parë të fjalive. Përndryshe, ekzekuto bllokun e dytë të fjalive."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Nëse vlera e parë është e saktë, atëherë ekzekuto bllokun e parë të fjalive. Përndryshe, nëse vlera e dytë është e saktë, ekzekuto bllokun e dytë të fjalive."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Nëse vlera e parë është e saktë, atëherë ekzekuto bllokun e parë të fjalive. Përndryshe, nëse vlera e dytë është e saktë, ekzekuto bllokun e dytë të fjalive. Nëse asnjëra nga vlerat nuk është e saktë, ekzekuto bllokun e fundit të fjalive."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "http://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "ekzekuto"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "përsërit %1 herë"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Ekzekuto disa fjali disa herë."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "përsërit derisa"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "përsërit përderisa"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Përderisa një vlerë është e pasaktë, atëherë ekzekuto disa fjali."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Përderisa një vlerë është e saktë, atëherë ekzekuto disa fjali."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Delete all %1 blocks?"; // untranslated -Blockly.Msg.DELETE_BLOCK = "Fshij bllokun"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Fshij %1 blloqe"; -Blockly.Msg.DISABLE_BLOCK = "Çaktivizo bllokun"; -Blockly.Msg.DUPLICATE_BLOCK = "Kopjo"; -Blockly.Msg.ENABLE_BLOCK = "Aktivizo bllokun"; -Blockly.Msg.EXPAND_ALL = "Zmadho blloqet"; -Blockly.Msg.EXPAND_BLOCK = "Zmadho bllokun"; -Blockly.Msg.EXTERNAL_INPUTS = "Hyrjet e jashtme"; -Blockly.Msg.HELP = "Ndihmë"; -Blockly.Msg.INLINE_INPUTS = "Hyrjet e brendshme"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "krijo një listë të zbrazët"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Kthen një listë, te gjatësisë 0, duke mos përmbajtur asnjë regjistrim të të dhënave"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "listë"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Shto, fshij, ose rirregullo sektoret për ta rikonfiguruar këtë bllok të listës."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "krijo listë me"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Shto një send në listë."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Krijo një listë me ndonjë numbër të sendeve."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "i parë"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# nga fundi"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "merr"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "merr dhe fshij"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "i fundit"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "i rastësishëm"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "largo"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Rikthen tek artikulli i par në list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Kthen një send në pozicionin e specifikuar në listë."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Kthen artikullin e fundit në list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Kthen një send të rastësishëm në listë."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Fshin dhe kthen sendin e parë në listë."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Fshin dhe kthen sendin në pozicionin e specifikuar në listë."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Fshin dhe kthen sendin e fundit në listë."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Fshin dhe kthen një send të rastësishëm në listë."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Fshin sendin e parë në listë."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Fshin sendin në pozicionin e specifikuar në listë."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Fshin sendin e fundit në listë."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Kthen një send të rastësishëm në listë."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "tek # nga fundi"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "tek #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "tek i fundit"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "merr nën-listën nga i pari"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "merr nën listën nga # nga fundi"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "merr nën-listën nga #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Krijon në kopje të pjesës së specifikuar të listës."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 është sendi i fundit."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 është sendi i parë."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "gjen ndodhjen e parë të sendit"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "gjen ndodhjen e fundit të sendit"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Kthen indeksin e ndodhjes së parë/fudit të sendit në listë. Kthen %1 nëse teksti nuk është gjetur."; -Blockly.Msg.LISTS_INLIST = "në listë"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 është e zbraztë"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Kthehet i saktë nëse lista është e zbraztë."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "gjatësia e %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Kthen gjatësinë e listës."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "krijo listën me sendin %1 të përsëritur %2 herë"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Krijon në listë qe përmban vlerën e dhënë të përsëritur aq herë sa numri i specifikuar."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "sikurse"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "fut në"; -Blockly.Msg.LISTS_SET_INDEX_SET = "vendos"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Fut sendin në fillim të listës."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Fut sendin në pozicionin e specifikuar të listës."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Bashkangjit sendin në fund të listës."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Fut sendin rastësisht në listë."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Vendos sendin e parë në listë."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Vendos sendin në pozicionin e specifikuar në listë."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Vendos sendin e fundit në listë."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Vendos një send të rastësishëm në listë."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "make list from text"; // untranslated -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "make text from list"; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "e pasaktë"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Kthehet ose të saktë ose të pasaktë."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "e saktë"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "http://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Ktheje të saktë nëse të dy hyrjet janë të barabarta me njëra-tjetrën."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Ktheje të saktë nëse hyrja e parë është më e madhe se hyrja e dytë."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Ktheje të saktë nëse hyrja e parë është më e madhe ose e barabartë me hyrjen e dytë."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Ktheje të saktë nëse hyrja e parë është më e vogël se hyrja e dytë."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Ktheje të saktë nëse hyrja e parë është më e vogël ose e barabartë me hyrjen e dytë."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Ktheje të saktë nëse të dy hyrjet nuk janë të barabarta me njëra-tjetrën."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "jo %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Kthehet e saktë nëse hyrja është e pasaktë. Kthehet e pasaktë nëse hyrja është e saktë."; -Blockly.Msg.LOGIC_NULL = "pavlerë"; -Blockly.Msg.LOGIC_NULL_HELPURL = "http://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Kthehet e pavlerë."; -Blockly.Msg.LOGIC_OPERATION_AND = "dhe"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "ose"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Kthehet të saktë nëse të dy hyrjet janë të sakta."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Kthehet e saktë nëse së paku njëra nga hyrjet është e saktë."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "http://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "nëse e pasaktë"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "nëse e saktë"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Kontrollo kushtin në 'test'. Nëse kushti është i saktë, kthen vlerën 'nëse e saktë'; përndryshe kthen vlerën 'nëse e pasaktë'."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "http://sq.wikipedia.org/wiki/Aritmetika"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Kthen shumën e dy numrave."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Kthen herësin e dy numrave."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Kthen ndryshimin e dy numrave."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Kthen produktin e dy numrave."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Kthen numrin e parë të ngritur në fuqinë e numrit të dytë."; -Blockly.Msg.MATH_CHANGE_HELPURL = "http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "ndrysho %1 nga %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Shto një numër në ndryshoren '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "http://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Kthen një nga konstantet e përbashkëta: : π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infiniti)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "detyro %1 e ulët %2 e lartë %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Vëni një numër që të jetë në mes të kufive të specifikuara(përfshirëse)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "është i pjestueshme me"; -Blockly.Msg.MATH_IS_EVEN = "është çift"; -Blockly.Msg.MATH_IS_NEGATIVE = "është negativ"; -Blockly.Msg.MATH_IS_ODD = "është tek"; -Blockly.Msg.MATH_IS_POSITIVE = "është pozitiv"; -Blockly.Msg.MATH_IS_PRIME = "është prim"; -Blockly.Msg.MATH_IS_TOOLTIP = "Kontrollo nëse një numër është çift, tek, prim, i plotë, pozitiv, negativ, ose nëse është i pjestueshëm me një numër të caktuar. Kthehet e saktë ose e pasaktë."; -Blockly.Msg.MATH_IS_WHOLE = "është i plotë"; -Blockly.Msg.MATH_MODULO_HELPURL = "http://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "mbetësi i %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Kthen mbetësin nga pjestimi i dy numrave."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "x"; -Blockly.Msg.MATH_NUMBER_HELPURL = "http://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Një numër."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "mesatarja e listës"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "numri më i madh i listës"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "mediana e listës"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "numri më i ulët i listës"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "modat e listës"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "send i rastësishëm i listës"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "devijimi standard i listës"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "mbledhja e listës"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Kthen mesatarën (kuptimi aritmetik) i vlerave numerike të listës."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Kthe numrin më të madh të listës."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Kthe numrin median të listës."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Kthe numrin me të vogël të listës."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Kthe listën e sendit(eve) më të zakonshme të listës."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Kthe një element të rastësishëm nga lista."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Kthe devijimin standard të listës."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Kthe shumën e të gjithë numrave të listës."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "http://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "fraksioni i rastësishëm"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Kthe fraksionin e rastësishëm në mes të 0.0 (përfshirëse) dhe 1.0 (jopërfshirëse)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "http://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "numër i plotë i rastësishëm nga %1 deri në %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Kthe një numër të plotë të rastësishëm të dy kufijve të specifikuar, të përfshirë."; -Blockly.Msg.MATH_ROUND_HELPURL = "http://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "rrumbullakësimi"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "rrumbullakësimi i ulët"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "rrumbullakësimi i lartë"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Rrumbullakësimi i numrit të lartë ose të ulët."; -Blockly.Msg.MATH_SINGLE_HELPURL = "http://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absolut"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "rrënja katrore"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Kthen vlerën absolute të një numri."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Kthen e në fuqinë e një numri."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Kthen logaritmën natyrale të një numri."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Kthen 10 logaritmet bazë të një numri."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Kthe negacionin e një numri."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Kthen 10 në fuqinë e një numri."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Kthen rrënjën katrore të një numri."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "acosinus"; -Blockly.Msg.MATH_TRIG_ASIN = "asinus"; -Blockly.Msg.MATH_TRIG_ATAN = "atangjentë"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "http://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tan"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Rikthe cos-1 e nje numeri."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Rikthe sin-1 e nje numeri."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Kthe tg-1 e nje numeri."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Kthe kosinusin e nje grade (jo ne radiant)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Kthe kosinusin e nje kendi (jo ne radiant)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Kthe tangentin e nje kendi (jo radiant)."; -Blockly.Msg.NEW_VARIABLE = "Identifikatorë i ri..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Emri i identifikatorit të ri:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "allow statements"; // untranslated -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "me:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Lësho funksionin e definuar nga përdoruesi '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Lëho funksionin e definuar nga përdoruesi '%1' dhe përdor daljen e tij."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "me:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Krijo '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "bëj diqka"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "te"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Krijon një funksion pa dalje."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "rikthe"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Krijon një funksion me një dalje."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Paralajmërim: Ky funksion ka parametra të dyfishuar."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Thekso definicionin e funksionit"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Nëse një vlerë është e saktë, atëherë kthe një vlerë të dytë."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Paralajmërim: Ky bllok mund të përdoret vetëm brenda definicionit të funksionit."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "Fut emrin:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Add an input to the function."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "Informacioni i futur"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Add, remove, or reorder inputs to this function."; // untranslated -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "Fshij komentin"; -Blockly.Msg.RENAME_VARIABLE = "Ndrysho emrin variables..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Ndrysho emrin e te gjitha '%1' variablave ne :"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "shto tekst"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "ne"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "shto tekst tek varibla '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "me shkronja te vogla shtypi"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "Fillimi me shkronje te madhe shtypi"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "me shkronja te medha shtypi"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Kthe nje kopje te tekstit ne nje rast te ndryshem."; -Blockly.Msg.TEXT_CHARAT_FIRST = "merr shkronjen e pare"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "merr shkronjen # nga fundi"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "merr shkronjen #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "ne tekst"; -Blockly.Msg.TEXT_CHARAT_LAST = "merr shkronjen e fundit"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "merr nje shkronje te rastesishme"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Kthe nje shkronje nga nje pozicion i caktuar."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Shto nje gje ne tekst"; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "bashkangjit"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Shto, fshij, ose rirregullo sektoret për ta rikonfiguruar këtë bllok teksti."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "ne shkronjen # nga fundi"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "ne shkronjen #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "tek shkronja e fundit"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "ne tekst"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "merr vlerat qe vazhdojne me shkronjen e pare"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "merr nenvargun nga shkronja # nga fundi"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "Merr nenvargun nga shkronja #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Pergjigjet me nje pjese te caktuar teksti."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "ne tekst"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "gjej rastisjen e pare te tekstit"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "gjej rastisjen e fundit te tekstit"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Pergjigjet me indeksin e pare/fundit te rastisjes se tekstit te pare ne tekstin e dyte. Pergjigjet me %1 ne qofte se teksti nuk u gjet."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 eshte bosh"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Kthehet e vertete neqoftese teksti i dhene eshte bosh."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "krijo tekst me"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Krijo nje pjese te tekstit duke bashkuar se bashku disa sende"; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "gjatesi %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Pergjigjet me nje numer shkronjash (duke perfshire hapesire) ne tekstin e dhene."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "printo %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Printo tekstin e caktuar, numer ose vlere tjeter."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Kerkoji perdoruesit nje numer."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Kerkoji perdoruesit ca tekst."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "kerko nje numer me njoftim"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "kerko tekst me njoftim"; -Blockly.Msg.TEXT_TEXT_HELPURL = "http://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Nje shkronje, fjale, ose rresht teksti."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "prit hapesirat nga te dyja anet"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "prit hapesirat nga ana e majte"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "prit hapesirat nga ana e djathte"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Pergjigju me nje kopje te tekstit me hapesira te fshira nga njera ane ose te dyja anet."; -Blockly.Msg.TODAY = "Today"; // untranslated -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "send"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Krijo 'vendos %1"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Pergjigjet me nje vlere te kesaj variable."; -Blockly.Msg.VARIABLES_SET = "vendos %1 ne %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Krijo 'merr %1"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Vendos kete variable te jete e barabarte me te dhenat ne hyrje."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/sr.js b/backend/_pv_1_3_5/static/blockly/msg/js/sr.js deleted file mode 100755 index e53417c34..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/sr.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.sr'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Додај коментар"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Промените вредност:"; -Blockly.Msg.CLEAN_UP = "Уклоните блокова"; -Blockly.Msg.COLLAPSE_ALL = "Скупи блокове"; -Blockly.Msg.COLLAPSE_BLOCK = "Скупи блок"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "боја 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "боја 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "однос"; -Blockly.Msg.COLOUR_BLEND_TITLE = "помешај"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Помешати две боје заједно са датим односом (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://sr.wikipedia.org/wiki/Боја"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Изаберите боју са палете."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "случајна боја"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Изаберите боју насумице."; -Blockly.Msg.COLOUR_RGB_BLUE = "плава"; -Blockly.Msg.COLOUR_RGB_GREEN = "зелена"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "црвена"; -Blockly.Msg.COLOUR_RGB_TITLE = "боја са"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Креирај боју са одређеном количином црвене,зелене, и плаве. Све вредности морају бити између 0 и 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "Изађите из петље"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "настави са следећом итерацијом петље"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Напусти садржај петље."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Прескочи остатак ове петље, и настави са следећом итерацијом(понављанјем)."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Упозорење: Овај блок може да се употреби само унутар петље."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "за сваку ставку %1 на списку %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "За сваку ставку унутар листе, подеси промењиву '%1' по ставци, и онда начини неке изјаве-наредбе."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "преброј са %1 од %2 до %3 од %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Имај промењиву \"%1\" узми вредности од почетног броја до задњег броја, бројећи по одређеном интервалу, и изврши одређене блокове."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Додајте услов блоку „ако“."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Додај коначни, catch-all (ухвати све) услове иф блока."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Додај, уклони, или преуреди делове како бих реконфигурисали овај иф блок."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "иначе"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "иначе-ако"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "ако"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "ако је вредност тачна, онда изврши неке наредбе-изјаве."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "ако је вредност тачна, онда изврши први блок наредби, У супротном, изврши други блок наредби."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Ако је прва вредност тачна, онда изврши први блок наредби, у супротном, ако је друга вредност тачна , изврши други блок наредби."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Ако је прва вредност тачна, онда изврши први блок наредби, у супротном, ако је друга вредност тачна , изврши други блок наредби. Ако ни једна од вредности није тачна, изврши последнји блок наредби."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://sr.wikipedia.org/wiki/For_петља"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "изврши"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "понови %1 пута"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Одрадити неке наредбе неколико пута."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "понављати до"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "понављати док"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Док вредност није тачна, онда извршити неке наредбе."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Док је вредност тачна, онда извршите неке наредбе."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Обрисати %1 блокова?"; -Blockly.Msg.DELETE_BLOCK = "Обриши блок"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Обриши %1 блокова"; -Blockly.Msg.DISABLE_BLOCK = "Онемогући блок"; -Blockly.Msg.DUPLICATE_BLOCK = "Дуплирај"; -Blockly.Msg.ENABLE_BLOCK = "Омогући блок"; -Blockly.Msg.EXPAND_ALL = "Прошири блокове"; -Blockly.Msg.EXPAND_BLOCK = "Прошири блок"; -Blockly.Msg.EXTERNAL_INPUTS = "Спољни улази"; -Blockly.Msg.HELP = "Помоћ"; -Blockly.Msg.INLINE_INPUTS = "Унутрашњи улази"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "направи празан списак"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "враћа листу, дужине 0, не садржавајући евиденцију података"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "списак"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Додајте, избришите, или преуредите делове како би се реорганизовали овај блок листе."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "направи списак са"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Додајте ставку на списак."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Креирај листу са било којим бројем ставки."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "прва"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# са краја"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "преузми"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "преузми и уклони"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "последња"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "случајна"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "уклони"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Враћа прву ставку на списку."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Враћа ставку на одређену позицију на листи."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Враћа последњу ставку на списку."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Враћа случајну ставку са списка."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Уклања и враћа прву ставку са списка."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Уклања и враћа ставку са одређеног положаја на списку."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Уклања и враћа последњу ставку са списка."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Уклања и враћа случајну ставку са списка."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Уклања прву ставку са списка."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Уклања ставку са одређеног положаја на списку."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Уклања последњу ставку са списка."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Уклања случајну ставку са списка."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "до # од краја"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "до #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "до последње"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "преузми подсписак од прве"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "преузми подсписак из # са краја"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "преузми подсписак од #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Прави копију одређеног дела листе."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 је последња ставка."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 је прва ставка."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "пронађи прво појављивање ставке"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "пронађи последње појављивање ставке"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Враћа број првог и/последњег уласка елемента у листу. Враћа %1 Ако елемент није пронађен."; -Blockly.Msg.LISTS_INLIST = "на списку"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 је празан"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Враћа вредност тачно ако је листа празна."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "дужина списка %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Враћа дужину списка."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "Направити листу са ставком %1 која се понавлја %2 пута"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Прави листу која се састоји од задане вредности коју понавлјамо одређени број шута."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "као"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "убаци на"; -Blockly.Msg.LISTS_SET_INDEX_SET = "постави"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Убацује ставку на почетак списка."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Убацује ставку на одређени положај на списку."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Додајте ставку на крај списка."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Убацује ставку на случајно место на списку."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Поставља прву ставку на списку."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Поставља ставку на одређени положај на списку."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Поставља последњу ставку на списку."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Поставља случајну ставку на списку."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "сортирај %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Сортирајте копију списка."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "направите листу са текста"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "да текст из листе"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Да се придружи листу текстова у један текст, подељених за раздвајање."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Поделити текст у листу текстова, разбијање на сваком граничник."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "са раздвајање"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "нетачно"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "враћа вредност или тачно или нетачно."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "тачно"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://sr.wikipedia.org/wiki/Неједнакост"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Враћа вредност „тачно“ ако су оба улаза једнака."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Враћа вредност „тачно“ ако је први улаз већи од другог."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Враћа вредност „тачно“ ако је први улаз већи или једнак другом."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Враћа вредност „тачно“ ако је први улаз мањи од другог."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Враћа вредност „тачно“ ако је први улаз мањи или једнак другом."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Враћа вредност „тачно“ ако су оба улаза неједнака."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "није %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Враћа вредност „тачно“ ако је улаз нетачан. Враћа вредност „нетачно“ ако је улаз тачан."; -Blockly.Msg.LOGIC_NULL = "без вредности"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Враћа „без вредности“."; -Blockly.Msg.LOGIC_OPERATION_AND = "и"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "или"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Враћа вредност „тачно“ ако су оба улаза тачна."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Враћа вредност „тачно“ ако је бар један од улаза тачан."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "тест"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "ако је нетачно"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "ако је тачно"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Провери услов у 'test'. Ако је услов тачан, тада враћа 'if true' вредност; у другом случају враћа 'if false' вредност."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Arithmetic"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Вратите збир два броја."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Враћа количник два броја."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Враћа разлику два броја."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Враћа производ два броја."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Враћа први број степенован другим."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "промени %1 за %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Додајте број променљивој „%1“."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://sr.wikipedia.org/wiki/Математичка_константа"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "врати једну од заједничких константи: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), или ∞ (infinity)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "ограничи %1 ниско %2 високо %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Ограничава број на доње и горње границе (укључиво)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "је дељив са"; -Blockly.Msg.MATH_IS_EVEN = "је паран"; -Blockly.Msg.MATH_IS_NEGATIVE = "је негативан"; -Blockly.Msg.MATH_IS_ODD = "је непаран"; -Blockly.Msg.MATH_IS_POSITIVE = "је позитиван"; -Blockly.Msg.MATH_IS_PRIME = "је прост"; -Blockly.Msg.MATH_IS_TOOLTIP = "Провјерава да ли је број паран, непаран, прост, цио, позитиван, негативан, или да ли је делјив са одређеним бројем. Враћа тачно или нетачно."; -Blockly.Msg.MATH_IS_WHOLE = "је цео"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://sr.wikipedia.org/wiki/Конгруенција"; -Blockly.Msg.MATH_MODULO_TITLE = "подсетник од %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Враћа подсетник од дељења два броја."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Неки број."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "просек списка"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "макс. списка"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "медијана списка"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "мин. списка"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "модус списка"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "случајна ставка списка"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "стандардна девијација списка"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "збир списка"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Враћа просек нумеричких вредности са списка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Враћа највећи број са списка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Враћа медијану са списка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Враћа најмањи број са списка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Враћа најчешће ставке са списка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Враћа случајни елемент са списка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Враћа стандардну девијацију списка."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Враћа збир свих бројева са списка."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://sr.wikipedia.org/wiki/Генератор_случајних_бројева"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "случајни разломак"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Враћа случајни разломак између 0.0 (укључиво) и 1.0 (искључиво)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://sr.wikipedia.org/wiki/Генератор_случајних_бројева"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "сличајно одабрани цијели број од %1 до %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Враћа случајно одабрани цели број између две одређене границе, уклјучиво."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://sr.wikipedia.org/wiki/Заокруживање"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "заокружи"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "заокружи наниже"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "заокружи навише"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Заокружите број на већу или мању вредност."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://sr.wikipedia.org/wiki/Квадратни_корен"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "апсолутан"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "квадратни корен"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Враћа апсолутну вредност броја."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "вратити е на власти броја."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Враћа природни логаритам броја."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Враћа логаритам броја са основом 10."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Враћа негацију броја."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Враћа 10-ти степен броја."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Враћа квадратни корен броја."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "арц цос"; -Blockly.Msg.MATH_TRIG_ASIN = "арц син"; -Blockly.Msg.MATH_TRIG_ATAN = "арц тан"; -Blockly.Msg.MATH_TRIG_COS = "цос"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://sr.wikipedia.org/wiki/Тригонометријске_функције"; -Blockly.Msg.MATH_TRIG_SIN = "син"; -Blockly.Msg.MATH_TRIG_TAN = "тан"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Враћа аркус косинус броја."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Враћа аркус броја."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Враћа аркус тангенс броја."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Враћа косинус степена (не радијан)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Враћа синус степена (не радијан)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Враћа тангенс степена (не радијан)."; -Blockly.Msg.NEW_VARIABLE = "Нова променљива…"; -Blockly.Msg.NEW_VARIABLE_TITLE = "Име нове променљиве:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "дозволити изреке"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "са:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://sr.wikipedia.org/wiki/Функција_(програмирање)"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Покрените прилагођену функцију „%1“."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://sr.wikipedia.org/wiki/Функција_(програмирање)"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Покрените прилагођену функцију „%1“ и користи њен излаз."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "са:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Направи „%1“"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Описати ову функцију..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "урадите нешто"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "да"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Прави функцију без излаза."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "врати"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Прави функцију са излазом."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Упозорење: Ова функција има дупликате параметара."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Истакни дефиницију функције"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Уколико је вредност тачна, врати другу вредност."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Упозорење: Овај блок се може користити једино у дефиницији функције."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "назив улаза:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Додајте улазна функција."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "улази"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Да додате, уклоните или переупорядочить улаза за ову функцију."; -Blockly.Msg.REDO = "Понови"; -Blockly.Msg.REMOVE_COMMENT = "Уклони коментар"; -Blockly.Msg.RENAME_VARIABLE = "Преименуј променљиву…"; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Преименујте све „%1“ променљиве у:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "додај текст"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "на"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Додајте текст на променљиву „%1“."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "малим словима"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "свака реч великим словом"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "великим словима"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Враћа примерак текста са другачијом величином слова."; -Blockly.Msg.TEXT_CHARAT_FIRST = "преузми прво слово"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "преузми слово # са краја"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "преузми слово #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "у тексту"; -Blockly.Msg.TEXT_CHARAT_LAST = "преузми последње слово"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "преузми случајно слово"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Враћа слово на одређени положај."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Додајте ставку у текст."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "спајањем"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Додај, уклони, или другачије поредај одјелке како би изнова поставили овај текст блок."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "слову # са краја"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "слову #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "последњем слову"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "у тексту"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "преузми подниску из првог слова"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "преузми подниску из слова # са краја"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "преузми подниску из слова #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Враћа одређени део текста."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "у тексту"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "пронађи прво појављивање текста"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "пронађи последње појављивање текста"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Враћа однос првог/заднјег појавлјиванја текста у другом тексту. Врађа %1 ако текст није пронађен."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 је празан"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Враћа тачно ако је доставлјени текст празан."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "напиши текст са"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Направити дио текста спајајући различите ставке."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "дужина текста %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Враћа број слова (уклјучујући размаке) у датом тексту."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "прикажи %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Прикажите одређени текст, број или другу вредност на екрану."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Питајте корисника за број."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Питајте корисника за унос текста."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "питај за број са поруком"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "питај за текст са поруком"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://sr.wikipedia.org/wiki/Ниска"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Слово, реч или ред текста."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "трим празнине са обе стране"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "скратити простор са леве стране"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "скратити простор са десне стране"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Враћа копију текста са уклонјеним простором са једног од два краја."; -Blockly.Msg.TODAY = "Данас"; -Blockly.Msg.UNDO = "Опозови"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "ставка"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Направи „постави %1“"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Враћа вредност ове променљиве."; -Blockly.Msg.VARIABLES_SET = "постави %1 у %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Направи „преузми %1“"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Поставља променљиву тако да буде једнака улазу."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/sv.js b/backend/_pv_1_3_5/static/blockly/msg/js/sv.js deleted file mode 100755 index 1cb95f9cd..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/sv.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.sv'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Lägg till kommentar"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Ändra värde:"; -Blockly.Msg.CLEAN_UP = "Rada upp block"; -Blockly.Msg.COLLAPSE_ALL = "Fäll ihop block"; -Blockly.Msg.COLLAPSE_BLOCK = "Fäll ihop block"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "färg 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "färg 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "förhållande"; -Blockly.Msg.COLOUR_BLEND_TITLE = "blanda"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Blandar ihop två färger med ett bestämt förhållande (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://sv.wikipedia.org/wiki/Färg"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Välj en färg från paletten."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "slumpfärg"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Slumpa fram en färg."; -Blockly.Msg.COLOUR_RGB_BLUE = "blå"; -Blockly.Msg.COLOUR_RGB_GREEN = "grön"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "röd"; -Blockly.Msg.COLOUR_RGB_TITLE = "färg med"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Skapa en färg med det angivna mängden röd, grön och blå. Alla värden måste vara mellan 0 och 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "bryt ut ur loop"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "fortsätta med nästa upprepning av loop"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Bryt ut ur den innehållande upprepningen."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Hoppa över resten av denna loop och fortsätt med nästa loop."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Varning: Detta block kan endast användas i en loop."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "för varje föremål %1 i listan %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "För varje objekt i en lista, ange variabeln '%1' till objektet, och utför sedan några kommandon."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "räkna med %1 från %2 till %3 med %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Låt variabeln \"%1\" ta värden från starttalet till sluttalet, beräknat med det angivna intervallet, och utför de angivna blocken."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Lägg till ett villkor blocket \"om\"."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Lägg till ett sista villkor som täcker alla alternativ som är kvar för \"if\"-blocket."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Lägg till, ta bort eller ändra ordningen för sektioner för att omkonfigurera blocket \"om\"."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "annars"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "annars om"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "om"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Om ett värde är sant, utför några kommandon."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Om värdet är sant, utför det första kommandoblocket. Annars utför det andra kommandoblocket."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Om det första värdet är sant, utför det första kommandoblocket. Annars, om det andra värdet är sant, utför det andra kommandoblocket."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Om det första värdet är sant, utför det första kommandoblocket. Annars, om det andra värdet är sant, utför det andra kommandoblocket. Om ingen av värdena är sanna, utför det sista kommandoblocket."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "utför"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "upprepa %1 gånger"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Utför några kommandon flera gånger."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "upprepa tills"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "upprepa medan"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Medan ett värde är falskt, utför några kommandon."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Medan ett värde är sant, utför några kommandon."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Radera alla %1 block?"; -Blockly.Msg.DELETE_BLOCK = "Radera block"; -Blockly.Msg.DELETE_VARIABLE = "Radera variabeln \"%1\""; -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Radera %1 användningar av variabeln \"%2\"?"; -Blockly.Msg.DELETE_X_BLOCKS = "Radera %1 block"; -Blockly.Msg.DISABLE_BLOCK = "Inaktivera block"; -Blockly.Msg.DUPLICATE_BLOCK = "Duplicera"; -Blockly.Msg.ENABLE_BLOCK = "Aktivera block"; -Blockly.Msg.EXPAND_ALL = "Fäll ut block"; -Blockly.Msg.EXPAND_BLOCK = "Fäll ut block"; -Blockly.Msg.EXTERNAL_INPUTS = "Externa inmatningar"; -Blockly.Msg.HELP = "Hjälp"; -Blockly.Msg.INLINE_INPUTS = "Radinmatning"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "skapa tom lista"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Ger tillbaka en lista utan någon data, alltså med längden 0"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "lista"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Lägg till, ta bort eller ändra ordningen på objekten för att göra om det här \"list\"-blocket."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "skapa lista med"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Lägg till ett föremål till listan."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Skapa en lista med valfritt antal föremål."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "första"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# från slutet"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "hämta"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "hämta och ta bort"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "sista"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "slumpad"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "ta bort"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Returnerar det första objektet i en lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Ger tillbaka objektet på den efterfrågade positionen i en lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Returnerar det sista objektet i en lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Returnerar ett slumpmässigt objekt i en lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Tar bort och återställer det första objektet i en lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Tar bort och återställer objektet på den specificerade positionen i en lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Tar bort och återställer det sista objektet i en lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Tar bort och återställer ett slumpmässigt objekt i en lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Tar bort det första objektet i en lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Tar bort objektet på den specificerade positionen i en lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Tar bort det sista objektet i en lista."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Tar bort en slumpmässig post i en lista."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "till # från slutet"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "till #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "till sista"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "få underlista från första"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "få underlista från # från slutet"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "få underlista från #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Skapar en kopia av den specificerade delen av en lista."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 är det sista objektet."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 är det första objektet."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "hitta första förekomsten av objektet"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "hitta sista förekomsten av objektet"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Ger tillbaka den första/sista förekomsten av objektet i listan. Returnerar %1 om objektet inte hittas."; -Blockly.Msg.LISTS_INLIST = "i listan"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 är tom"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Returnerar sant om listan är tom."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "längden på %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Returnerar längden på en lista."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "skapa lista med föremålet %1 upprepat %2 gånger"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Skapar en lista som innehåller ett valt värde upprepat ett bestämt antalet gånger."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "som"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "Sätt in vid"; -Blockly.Msg.LISTS_SET_INDEX_SET = "ange"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "sätter in objektet i början av en lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Sätter in objektet vid en specificerad position i en lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Lägg till objektet i slutet av en lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "sätter in objektet på en slumpad position i en lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Anger det första objektet i en lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Sätter in objektet vid en specificerad position i en lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Anger det sista elementet i en lista."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Sätter in ett slumpat objekt i en lista."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "stigande"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "fallande"; -Blockly.Msg.LISTS_SORT_TITLE = "sortera %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sortera en kopia av en lista."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alfabetiskt, ignorera skiftläge"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeriskt"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alfabetiskt"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "skapa lista från text"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "skapa text från lista"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Sammanfoga en textlista till en text, som separeras av en avgränsare."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Dela upp text till en textlista och bryt vid varje avgränsare."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "med avgränsare"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "falskt"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Returnerar antingen sant eller falskt."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "sant"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://sv.wikipedia.org/wiki/Olikhet"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Ger tillbaka sant om båda värdena är lika med varandra."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Ger tillbaka sant om det första värdet är större än det andra."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Ger tillbaka sant om det första värdet är större än eller lika med det andra."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Ger tillbaka sant om det första värdet är mindre än det andra."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Ger tillbaka sant om det första värdet är mindre än eller lika med det andra."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Ger tillbaka sant om båda värdena inte är lika med varandra."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "inte %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Ger tillbaka sant om inmatningen är falsk. Ger tillbaka falskt och inmatningen är sann."; -Blockly.Msg.LOGIC_NULL = "null"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://sv.wikipedia.org/wiki/Null"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Returnerar null."; -Blockly.Msg.LOGIC_OPERATION_AND = "och"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "eller"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Ger tillbaka sant om båda värdena är sanna."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Ger tillbaka sant om minst ett av värdena är sant."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "om falskt"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "om sant"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Kontrollera villkoret i \"test\". Om villkoret är sant, ge tillbaka \"om sant\"-värdet; annars ge tillbaka \"om falskt\"-värdet."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://sv.wikipedia.org/wiki/Aritmetik"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Returnerar summan av de två talen."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Returnerar kvoten av de två talen."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Returnerar differensen mellan de två talen."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Returnerar produkten av de två talen."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Ger tillbaka det första talet upphöjt till det andra talet."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "ändra %1 med %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Lägg till ett tal till variabeln '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://sv.wikipedia.org/wiki/Matematisk_konstant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Returnerar en av de vanliga konstanterna: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…) eller ∞ (oändligt)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "begränsa %1 till mellan %2 och %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Begränsa ett tal till att mellan de angivna gränsvärden (inkluderande)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "är delbart med"; -Blockly.Msg.MATH_IS_EVEN = "är jämnt"; -Blockly.Msg.MATH_IS_NEGATIVE = "är negativt"; -Blockly.Msg.MATH_IS_ODD = "är ojämnt"; -Blockly.Msg.MATH_IS_POSITIVE = "är positivt"; -Blockly.Msg.MATH_IS_PRIME = "är ett primtal"; -Blockly.Msg.MATH_IS_TOOLTIP = "Kontrollera om ett tal är jämnt, ojämnt, helt, positivt, negativt eller det är delbart med ett bestämt tal. Returnerar med sant eller falskt."; -Blockly.Msg.MATH_IS_WHOLE = "är helt"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "resten av %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Returnerar kvoten från divisionen av de två talen."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://sv.wikipedia.org/wiki/Tal"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Ett tal."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "medelvärdet av listan"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "högsta talet i listan"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "medianen av listan"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "minsta talet i listan"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "typvärdet i listan"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "slumpmässigt objekt i listan"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "standardavvikelsen i listan"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "summan av listan"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Ger tillbaka medelvärdet (aritmetiskt) av de numeriska värdena i listan."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Ger tillbaka det största talet i listan."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Returnerar medianen av talen i listan."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Ger tillbaka det minsta talet i listan."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Ger tillbaka en lista med de(t) vanligaste objekte(t/n) i listan."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Returnerar ett slumpmässigt element från listan."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Ger tillbaka standardavvikelsen i listan."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Ger tillbaka summan av alla talen i listan."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://sv.wikipedia.org/wiki/Slumptalsgenerator"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "slumpat decimaltal"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Ger tillbaka ett slumpat decimaltal mellan 0.0 (inkluderat) och 1.0 (exkluderat)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://sv.wikipedia.org/wiki/Slumptalsgenerator"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "slumpartat heltal från %1 till %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Ger tillbaka ett slumpat heltal mellan två värden, inkluderande."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://sv.wikipedia.org/wiki/Avrundning"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "avrunda"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "avrunda nedåt"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "avrunda uppåt"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Avrunda ett tal uppåt eller nedåt."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://sv.wikipedia.org/wiki/Kvadratrot"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absolut"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "kvadratrot"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Returnerar absolutvärdet av ett tal."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Ger tillbaka e upphöjt i ett tal."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Returnera den naturliga logaritmen av ett tal."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Returnerar logaritmen för bas 10 av ett tal."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Returnerar negationen av ett tal."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Ger tillbaka 10 upphöjt i ett tal."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Returnerar kvadratroten av ett tal."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "arccos"; -Blockly.Msg.MATH_TRIG_ASIN = "arcsin"; -Blockly.Msg.MATH_TRIG_ATAN = "arctan"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://sv.wikipedia.org/wiki/Trigonometrisk_funktion"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tan"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Ger tillbaka arcus cosinus (arccos) för ett tal."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Ger tillbaka arcus sinus (arcsin) för ett tal."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Ger tillbaka arcus tangens (arctan) av ett tal."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Ger tillbaka cosinus för en grad (inte radian)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Ger tillbaka sinus för en grad (inte radian)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Ger tillbaka tangens för en grad (inte radian)."; -Blockly.Msg.NEW_VARIABLE = "Skapa variabel..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Nytt variabelnamn:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "tillåta uttalanden"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "med:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://sv.wikipedia.org/wiki/Funktion_%28programmering%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Kör den användardefinierade funktionen \"%1\"."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://sv.wikipedia.org/wiki/Funktion_%28programmering%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Kör den användardefinierade funktionen \"%1\" och använd resultatet av den."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "med:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Skapa '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Beskriv denna funktion..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://sv.wikipedia.org/wiki/Funktion_%28programmering%29"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "göra något"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "för att"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Skapar en funktion utan output."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://sv.wikipedia.org/wiki/Funktion_%28programmering%29"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "returnera"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Skapar en funktion med output."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Varning: Denna funktion har dubbla parametrar."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Markera funktionsdefinition"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Om ett värde är sant returneras ett andra värde."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Varning: Detta block får användas endast i en funktionsdefinition."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "inmatningsnamn:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Lägg till en inmatning till funktionen."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "inmatningar"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Lägg till, ta bort och ändra ordningen för inmatningar till denna funktion."; -Blockly.Msg.REDO = "Gör om"; -Blockly.Msg.REMOVE_COMMENT = "Radera kommentar"; -Blockly.Msg.RENAME_VARIABLE = "Byt namn på variabel..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Byt namn på alla'%1'-variabler till:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "lägg till text"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "till"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Lägg till lite text till variabeln '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "till gemener"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "till Versala Initialer"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "till VERSALER"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Returnerar en kopia av texten i ett annat skiftläge."; -Blockly.Msg.TEXT_CHARAT_FIRST = "hämta första bokstaven"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "hämta bokstaven # från slutet"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "hämta bokstaven #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "i texten"; -Blockly.Msg.TEXT_CHARAT_LAST = "hämta sista bokstaven"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "hämta slumpad bokstav"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Ger tillbaka bokstaven på den specificerade positionen."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Lägg till ett föremål till texten."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "sammanfoga"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Lägg till, ta bort eller ändra ordningen för sektioner för att omkonfigurera detta textblock."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "till bokstav # från slutet"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "till bokstav #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "till sista bokstaven"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "i texten"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "få textdel från första bokstaven"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "få textdel från bokstav # från slutet"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "få textdel från bokstav #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Ger tillbaka en viss del av texten."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "i texten"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "hitta första förekomsten av texten"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "hitta sista förekomsten av texten"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Ger tillbaka indexet för den första/sista förekomsten av första texten i den andra texten. Ger tillbaka %1 om texten inte hittas."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 är tom"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returnerar sant om den angivna texten är tom."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "skapa text med"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Skapa en textbit genom att sammanfoga ett valfritt antal föremål."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "längden på %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Ger tillbaka antalet bokstäver (inklusive mellanslag) i den angivna texten."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "skriv %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Skriv den angivna texten, talet eller annat värde."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Fråga användaren efter ett tal."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Fråga användaren efter lite text."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "fråga efter ett tal med meddelande"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "fråga efter text med meddelande"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://sv.wikipedia.org/wiki/Str%C3%A4ng_%28data%29"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "En bokstav, ord eller textrad."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "ta bort mellanrum från båda sidorna av"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "ta bort mellanrum från vänstra sidan av"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "ta bort mellanrum från högra sidan av"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Returnerar en kopia av texten med borttagna mellanrum från en eller båda ändar."; -Blockly.Msg.TODAY = "Idag"; -Blockly.Msg.UNDO = "Ångra"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "föremål"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Skapa \"välj %1\""; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returnerar värdet av denna variabel."; -Blockly.Msg.VARIABLES_SET = "ange %1 till %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Skapa 'hämta %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Gör så att den här variabeln blir lika med inputen."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "En variabel som heter \"%1\" finns redan."; -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/ta.js b/backend/_pv_1_3_5/static/blockly/msg/js/ta.js deleted file mode 100755 index 669bc0da0..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/ta.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.ta'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "கருத்தை சேர்"; -Blockly.Msg.CHANGE_VALUE_TITLE = "மதிப்பை மாற்றவும்:"; -Blockly.Msg.CLEAN_UP = "Clean up Blocks"; // untranslated -Blockly.Msg.COLLAPSE_ALL = "உறுப்புகளை மரை"; -Blockly.Msg.COLLAPSE_BLOCK = "உறுப்பை மரை"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "நிறம் 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "நிறம் 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "விகிதம்"; -Blockly.Msg.COLOUR_BLEND_TITLE = "கலப்பு (வண்ணம்)"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "கொடுக்கப்பட்ட விகதத்தில் (0.0 - 1.0) இரு நிறங்களை கலக்குக."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "வண்ண தட்டிலிருந்து ஒரு நிறத்தைத் தேர்ந்தெடுக்கவும்."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "தற்போக்கு நிறம்"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "தற்போக்கில் ஒரு நிறத்தை தேர்ந்தெடுக்கவும்."; -Blockly.Msg.COLOUR_RGB_BLUE = "நீலம்"; -Blockly.Msg.COLOUR_RGB_GREEN = "பச்சை"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "சிகப்பு"; -Blockly.Msg.COLOUR_RGB_TITLE = "நிறத்துடன்"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "குறிப்பிட்ட அளவு சிவப்பு,பச்சை மற்றும் நீலம் சேர்த்து புது நிறம் உருவாக்கு. மதிப்புகள் 0 முதல் 100 வரை மட்டுமே இருக்க வேண்டும்."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "மடக்கு கட்டளையை நிறுத்து."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "மடக்கு கட்டளையின் அடுத்த இயக்கநிலைக்கு செல்"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "மடக்கு கட்டளையின் இயக்கத்தில் இருந்து நிறுத்து."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "மடக்கு கட்டளையின் மீதியை விட்டுவிட்டு அடுத்த இயக்கநிலைக்கு செல்"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "எச்சரிக்கை : மடக்கு கூற்றில் இந்த தொகுதி ஒரு முறை மட்டுமே செயல்படுத்தப் படலாம்."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "உருப்படி ஒவ்வொன்றாக %1 பட்டியலில் உள்ள %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "பட்டியலில் உள்ள உருப்படியில் ஒவ்வொன்றாக, மாறியின் பொருள் '%1' ஆக வைக்க."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "மாறியை வைத்து எண்ண %1 %2 இல் இருந்து %3 வரை %4-இன் படியாக"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "முதல் எண்ணில் இருந்து கடை எண் வரை எடுத்துக்கொள்ள ஒரு மாறியை வைத்துக்கொள், குறித்த இடைவெளியை சேர்த்தவறே தொகுதிகளை செயலாக்கு."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "ஆனால் தொகுப்பிற்கு நிபந்தனை சேர்க்க"; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "ஆனால் தொகுப்பிற்கு விதிவிலக்கு காப்பை சேர்க்க"; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "கட்டளைகளை தொகுப்பு திருத்துதம் செய்"; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "இல்லையெனில்"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "இல்லைஆனால்"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "எனில்"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "மாறி உண்மை ஆக உள்ள வரை, கட்டளைகளை இயக்கு"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "மாறி உண்மை ஆக உள்ள வரை, கட்டளைகளை இயக்கு. அல்லது மற்ற (அடுத்த) கட்டளைகளை இயக்கு."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "மாறி உண்மை ஆக உள்ள வரை, கட்டளைகளை தொகுப்பு இயக்கு. அல்லது மற்ற (அடுத்த) கட்டளைகளை தொகுப்பு இயக்கு."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "மாறி உண்மை ஆக உள்ள வரை, கட்டளைகளை தொகுப்பு இயக்கு. அல்லது மற்ற (அடுத்த) கட்டளைகளை தொகுப்பு இயக்கு. இரண்டும் இல்லை என்றால் கடைசி தொகுப்பு இயக்கு."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "செய்க"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "'%1' முரை திரும்ப செய்"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "கட்டளைகளை பல முரை செய்ய"; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "பலமுரை திரும்ப செய் (முடயேனில்)"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "பலமுரை திரும்ப செய் (வரை)"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "மாறி பொய் ஆக உள்ள வரை, கட்டளைகளை இயக்கு"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "மாறி உண்மை ஆக உள்ள வரை, கட்டளைகளை இயக்கு"; -Blockly.Msg.DELETE_ALL_BLOCKS = "அனைத்து %1 நிரல் துண்டுகளையும் அழிக்கவா??"; -Blockly.Msg.DELETE_BLOCK = "உறுப்பை நீக்கு"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "%1 உறுப்பை நீக்கு"; -Blockly.Msg.DISABLE_BLOCK = "உறுப்பை இயங்காது செய்"; -Blockly.Msg.DUPLICATE_BLOCK = "மறுநகல்"; -Blockly.Msg.ENABLE_BLOCK = "உறுப்பை இயங்குமாரு செய்"; -Blockly.Msg.EXPAND_ALL = "உறுப்புகளை காட்டு"; -Blockly.Msg.EXPAND_BLOCK = "உறுப்பை காட்டு"; -Blockly.Msg.EXTERNAL_INPUTS = "வெளி கருவிகளுடன் உள்ளீடு"; -Blockly.Msg.HELP = "உதவி"; -Blockly.Msg.INLINE_INPUTS = "சூழமைவில் உள்ளீடு"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "காலி பட்டியல் உருவாக்க"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "காலி பட்டியல் பின்கொடு."; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "பட்டியல்"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "கட்டளைகளை தொகுப்பு திருத்துதம் செய்"; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "வைத்து பட்டியல் உருவாக்க"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "பட்டியலில் ஒரு பொருளை சேர்க்க."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "இவ்வளவு உருப்படிகளை கொண்டு வேண்டுமாலும் ஒரு பட்டியலை உருவாக்கு."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "முதல்"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "கடைசியில் இருந்து #"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "எடு"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "பெற்று நீக்குக"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "கடைசி"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "ஏதோ ஒன்று"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "நீக்குக"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "பட்டியல் முதல் உருப்படியை பின்கொடு,"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "பட்டியலில் இடத்தில் உருப்படி பின்கொடு."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "பட்டியல் கடைசி உருப்படியை பின்கொடு,"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "பட்டியல் சீரற்ற உருப்படியை பின்கொடு,"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "பட்டியல் முதல் உருப்படியை நீக்கியபின் பின்கொடு,"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "பட்டியலில் கேட்ட இடத்தின் உருப்படி நீக்கி பின்கொடு."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "பட்டியல் இறுதி உருப்படியை நீக்கியபின் பின்கொடு,"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "பட்டியல் சீரற்ற உருப்படியை நீக்கியபின் பின்கொடு,"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "பட்டியலில் முதல் உருப்படியை நீக்கு"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "பட்டியலில் கேட்ட இடத்தின் உருப்படி நீக்கு."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "பட்டியலில் கடைசி உருப்படியை நீக்கு"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "பட்டியல் சீரற்ற உருப்படியை நீக்கு,"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "முடிவில் இருந்து # வரை"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "# வரை"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "முடிவு வரை"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "# முதலில் இருந்து பகுதி பட்டியலை கொடு"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "# கடைசியில் இருந்து பகுதி பட்டியலை கொடு"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "பகுதி பட்டியலை # இடத்தில் இருந்து கொடு"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "குறிப்பட்ட பகுதி பட்டியலின் நகலை கொடு"; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 கடைசி உருப்படி.ி"; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 முதல் உருப்படி."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "உரையில் முதல் தோற்ற இடத்தை காட்டு"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "உரையில் கடைசி தோற்ற இடத்தை காட்டு"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "பட்டியலில் மதிப்பின் முதல், கடைசி தோற்ற இடத்தை பின்கொடு. காணாவிட்டால் %1 பின்கொடு."; -Blockly.Msg.LISTS_INLIST = "பட்டியலில் உள்ள"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 காலியானது"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "பட்டியல் காலியானது மெய் பின்கொடு,"; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "%1 இன் நீளம்"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "பட்டியல் நீளம் பின்கொடு"; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "உருப்படி %1-யை, %2 தடவைகள் உள்ளவாறு ஒரு பட்டியலை உருவாக்கு"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "கொடுக்க பட்ட மதிப்பை, கூறியுள்ள தடவைகள் உள்ளவாறு ஒரு பட்டியலை உருவாக்கு"; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "இதுபொல"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "அவ்விடத்தில் நுழை"; -Blockly.Msg.LISTS_SET_INDEX_SET = "நியமி"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "மதிப்பை பட்டியலின் முதலில் நுழை"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "பட்டியலில் கேட்ட இடத்தில் உருப்படியை நுழை."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "மதிப்பை பட்டியலின் முடிவில் நுழை"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "மதிப்பை பட்டியலின் சீற்ற இடத்தில் நுழை"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "மதிப்பை பட்டியலில் முதல் உருப்படியில் வை"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "பட்டியலில் கேட்ட இடத்தில் உருப்படியை வை."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "மதிப்பை பட்டியலில் கடைசி உருப்படியில் வை"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "மதிப்பை பட்டியலில் சீரற்ற உருப்படியில் வை"; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "உரையில் இருந்து பட்டியல் உருவாக்கு"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "பட்டியலில் இருந்து உரை உருவாக்கு"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "வரம்புச் சுட்டியை இடையில் இட்டு, உரைதுண்டுகளை ஒன்று சேர்"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "உரையை வரம்புச் சுட்டி கொண்டு துண்டாக்கு."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "தடை எழுத்து"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "பொய்"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "மெய், அல்லது பொய் பின்கொடு."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "மெய்"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "இரண்டு மாறியும் ஈடானால், மெய் பின்கொடு."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "முதல் உள்ளீடு இரண்டாவதைவிட அதிகமாக இருந்தால், மெய் பின்கொடு."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "முதல் உள்ளீடு இரண்டாவதைவிட அதிகமாக அல்ல சமமாக இருந்தால், மெய் பின்கொடு."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "முதல் உள்ளீடு இரண்டாவதைவிட குறைவாக இருந்தால், மெய் பின்கொடு."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "முதல் உள்ளீடு இரண்டாவதைவிட குறைவாக அல்ல சமமாக இருந்தால், மெய் பின்கொடு"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "இரண்டு மாறியும் ஈடாகாவிட்டால், மெய் பின்கொடு."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "%1 இல்லை"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "மெய் ஆனால், பொய் பின்கொடு. பொய் ஆனால், மெய் பின்கொடு."; -Blockly.Msg.LOGIC_NULL = "பூஜியம்"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "பூஜியம் பின்கொடு"; -Blockly.Msg.LOGIC_OPERATION_AND = "மற்றும்"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "அல்லது"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "இரண்டு மாறியும் மெய் ஆனால், மெய் பின்கொடு."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "ஏதேனும் ஒரு மதிப்பு மெய் ஆனால், மெய் பின்கொடு"; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "சோதனை"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "பொய்யெனில்"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "மெய்யெனில்"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "'test' உள்ள நிபந்தனையை சரிபார்க்கவும், நிபந்தனை மெய்யானால்,'if true'வை பின்கொடுக்கும் இல்லையெனில் 'if false'வை பின்கொடுக்கும்."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://ta.wikipedia.org/wiki/%E0%AE%8E%E0%AE%A3%E0%AF%8D%E0%AE%95%E0%AE%A3%E0%AE%BF%E0%AE%A4%E0%AE%AE%E0%AF%8D"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "இரு எண்களின் கூட்டை பின்கொடு"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "இரு எண்களின் வகுத்தல் பின்கொடு"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "இரு எண்களின் கழிப்பை பின்கொடு"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "இரு எண்களின் பெருக்கலை பின்கொடு"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "முதல் உள்ளீடு இரண்டாவது எண் அளவான அடுக்கு பெருக்கை கணித்து பின்கொடு."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "மாற்று %1 மூலம் %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "எண்னை '%1' மதிப்பால் கூட்டு,"; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://ta.wikipedia.org/wiki/%E0%AE%95%E0%AE%A3%E0%AE%BF%E0%AE%A4_%E0%AE%AE%E0%AE%BE%E0%AE%B1%E0%AE%BF%E0%AE%B2%E0%AE%BF"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "ஒரு மாறிலியை பின்கொடு π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (முடிவிலி)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "%1 மாறியை %2 மேலும் %3 கீழும் வற்புறுத்து"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "எண் மாறி வீசுகளம் உள்ளடங்கிய வாறு வற்புறுத்து"; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "ஆல் வகுபடக் கூடியது"; -Blockly.Msg.MATH_IS_EVEN = "2-ஆல் பகும்"; -Blockly.Msg.MATH_IS_NEGATIVE = "எண் குறைவானதா ?"; -Blockly.Msg.MATH_IS_ODD = "2-ஆல் பகாத"; -Blockly.Msg.MATH_IS_POSITIVE = "எண் நேர்ம முழுதானதா ?"; -Blockly.Msg.MATH_IS_PRIME = "எண் பகாத்தனிதானதா?"; -Blockly.Msg.MATH_IS_TOOLTIP = "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false."; // untranslated -Blockly.Msg.MATH_IS_WHOLE = "எண் முழுதானதா?"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "%1 ÷ %2ன் மீதி"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "இரண்டு எண்கள் மூலம் பிரிவில் இருந்து எஞ்சியதை பின்கொடு."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://ta.wikipedia.org/wiki/%E0%AE%8E%E0%AE%A3%E0%AF%8D"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "ஒரு எண்."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "பட்டியலின் எண் சராசரி"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "பட்டியலின் மிகுதி"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "பட்டியலின் நடுக்கோடு"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "பட்டியலின் கறைவு"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "பட்டியலின் பொதுவகைகள்"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "ஒரு பட்டியலில் இருந்து சீரற்ற உருப்படி"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "பட்டியலின் நியமவிலகல்"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "பட்டியலின் கூட்டு"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "முழு பட்டியலின் எண் சராசரி பின்கொடு"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "பட்டியலின் அதிகமான எண் பின்கொடு"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "பட்டியலின் நடுக்கோடு பின்கொடு"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "பட்டியலின் குறைவான எண் பின்கொடு"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "பட்டியலின் பொதுவகைகள் பின்கொடு"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "ஒரு பட்டியலில் இருந்து சீரற்ற உருப்படி பின்கொடு"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "பட்டியலின் நியமவிலகலை பின்கொடு."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "முழு பட்டியலின் எண் சமம் பின்கொடு,"; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "சீரற்ற எண் பின்னம்"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "சீரற்ற எண் பின்னம், 0.0 இல் இருந்து 1.0 உட்பட, பின்கொடு."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "வீசுகளம் %1 இல் இருந்து %2 உள்ளடங்கிய வாறு சீரற்ற எண்"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "வீசுகளம் இல் இருந்த (உள்ளடங்கிய) வாறு சீரற்ற எண் பின்கொடு."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "முழுமையாக்கு"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "கீழ்வழி முழுமையாக்கு"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "மேல்வழி முழுமையாக்கு"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "மேல்/கீழ் வழி முழு எண் ஆக மாற்று."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://ta.wikipedia.org/wiki/%E0%AE%B5%E0%AE%B0%E0%AF%8D%E0%AE%95%E0%AF%8D%E0%AE%95%E0%AE%AE%E0%AF%82%E0%AE%B2%E0%AE%AE%E0%AF%8D"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "தனித்த"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "வர்க்கமூலம்"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "ஒரு எண்ணின் தனித்த மதிப்பை பின்கொடு"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "e-இன் எண் அடுக்கு பெருக்கை பின்கொடு."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "ஒரு எண்ணின் (இயற்கை) மடக்கை மதிப்பை பின்கொடு."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "ஒரு எண்ணின் (10) மடக்கை மதிப்பை பின்கொடு."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "ஒரு எண்ணின் எதிர்மறை மதிப்பை பின்கொடு"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "10-இன் எண் அடுக்கு பெருக்கை பின்கொடு."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "ஒரு எண்ணின் வர்க்கமூலத்தைத் தரும்."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://ta.wikipedia.org/wiki/%E0%AE%AE%E0%AF%81%E0%AE%95%E0%AF%8D%E0%AE%95%E0%AF%8B%E0%AE%A3%E0%AE%B5%E0%AE%BF%E0%AE%AF%E0%AE%B2%E0%AF%8D_%E0%AE%9A%E0%AE%BE%E0%AE%B0%E0%AF%8D%E0%AE%AA%E0%AF%81%E0%AE%95%E0%AE%B3%E0%AF%8D"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "மதிப்பின் நேர்மாறு கோசைன் பின்கொடு"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "மதிப்பின் நேர்மாறு சைன் பின்கொடு"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "மதிப்பின் நேர்மாறு டேஞ்சன்டு பின்கொடு"; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "டிகிரீ கோசைன் மதிப்பை பின்கொடு"; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "டிகிரீ சைன் மதிப்பை பின்கொடு."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "டிகிரீ டேஞ்சன்டு மதிப்பை பின்கொடு"; -Blockly.Msg.NEW_VARIABLE = "புதிய மாறிலி..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "புதிய மாறிலியின் பெயர்:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "வாக்குமூலங்களை அனுமதிக்கவும்"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "இத்துடன்"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "பயனரின் '%1' செயற்கூற்றை ஓட்டு."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "பயனரின் '%1' செயற்கூற்றை ஓட்டி வரும் வெளியீட்டை பயன்படுத்து."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "இத்துடன்:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "'%1' உருவாக்குக"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "கட்டளைகள் செய்ய (இடம்காட்டி)"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "இந்த மாறியிற்கு"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "வெளியீடு இல்லாத ஒரு செயல்பாடு உருவாக்குகிறது"; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "பின்கொடு"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "வெளியீடு உள்ள ஒரு செயல்பாடு உருவாக்குகிறது"; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "எச்சரிக்கை: இந்த செயற்கூறில் போலியான அளபுருக்கள் உண்டு."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "நிரல்பாகத்தை விளக்கமாக காட்டு"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "மதிப்பு உண்மையானால், இரண்டாவது மதிப்பை பின்கொடு."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Warning: This block may be used only within a function definition."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "பெயரை உள்ளிடுக:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "செயல்கூறுக்கு ஒரு உள்ளீட்டை சேர்."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "உள்ளீடுகள்"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "செயல்கூறுகளின் உள்ளீட்டை சேர், நீக்கு, or மீண்டும் வரிசை செய்."; -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "கருத்தை நீக்கு"; -Blockly.Msg.RENAME_VARIABLE = "மாறிலியை மறுபெயரிடுக..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "அனைத்து '%1' மாறிலிகளையும் பின்வருமாறு மறுபெயரிடுக:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "உரை சேர்க்க"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "இந்த மாறியிற்கு"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "'%1' மாறியில் உரையை சேர்"; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "சின்ன எழுத்துக்கு மாற்று"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "தலைப்பு எழுத்துக்கு மாற்று"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "பொரிய எழுத்துக்கு மாற்று"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "உரை நகல் எடுத்து பொரிய/சின்ன எழுத்து மாற்றி பின்கொடு."; -Blockly.Msg.TEXT_CHARAT_FIRST = "முதல் எழுத்தைப் பெறுக"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "முடிவில் இருந்து # எழுத்தை எடு"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "# எழுத்தை எடு"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "உரையில்"; -Blockly.Msg.TEXT_CHARAT_LAST = "இறுதி எழுத்தைப் பெறுக"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "சமவாய்ப்புள்ள எழுத்தை எடு"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "கூறிய இடத்தில் உள்ள எழுத்தை எடு"; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "உருபடியை உரையில் சேர்க்க."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "சேர்க்க"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "தொகுப்பு உரை திருத்துதம் செய்"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "எழுத்து கடைசியில் இருந்து # வரை"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "எழுத்து # வரை"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "கடைசி எழுத்து வரை"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "உரையில்"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "-இல் உட்கணம் முதல் எழுத்திலிருந்து"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "-இல் உட்கணம் கடைசி # எழுத்திலிருந்து"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "-இல் உட்கணம் # எழுத்திலிருந்து"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "உரையின் குறியிடப்பட்ட சரம் பின்கொடு"; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "உரையில்"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "உரையில் முதல் தோற்ற இடத்தை பின்கொடு"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "உரையில் கடைசி தோற்ற இடத்தை பின்கொடு"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "இரண்டாவது உரையில் முதல் உரையின் முதல்/கடை இருக்கை குறிஎண்ணை பின்கொடு."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 காலியானது"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "காலியானது என்றால் மெய் மதிப்பை பின்கொடு"; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "வைத்து உரை உருவாக்க"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "பல பொருட்களை ஒன்றாக சேர்வதன் மூலம் உரை உருவாக்க."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "%1ன் நீளம்"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "தொடரில் உள்ள எழுத்துக்களின் (இடைவெளிகளையும் சேர்த்து) எண்ணிகையை பின்கொடு."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "%1 அச்சிடுக"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "மதிப்பை அச்சிடு"; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "எண்-உள்ளீடு தூண்டுதலை காட்டு"; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "உரை-உள்ளீடு தூண்டுதலை காட்டு"; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "உரை கொண்டு எண்-உள்ளீடு தூண்டுதலை காட்டு"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "உரை கொண்டு உரை-உள்ளீடு தூண்டுதலை காட்டு"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://ta.wikipedia.org/wiki/%E0%AE%9A%E0%AE%B0%E0%AE%AE%E0%AF%8D_%28%E0%AE%95%E0%AE%A3%E0%AE%BF%E0%AE%A9%E0%AE%BF%E0%AE%AF%E0%AE%BF%E0%AE%AF%E0%AE%B2%E0%AF%8D%29"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "எழுத்து, சரம், சொல், அல்லது உரை சொற்தொடர்."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "இரு பக்கத்திலும் இடைவெளி எழுத்து நேர்த்தி செய்."; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "இடது பக்கத்தில் இடைவெளி எழுத்து நேர்த்தி செய்."; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "வலது பக்கத்தில் இடைவெளி எழுத்து நேர்த்தி செய்."; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "உரை நகல் எடுத்து இடைவெளி எழுத்து நீக்கி பின்கொடு."; -Blockly.Msg.TODAY = "இன்று"; -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "உருப்படி"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "'%1 நியமி' உருவாக்கு"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "இந்த மாறி மதிப்பை பின்கொடு"; -Blockly.Msg.VARIABLES_SET = "நியமி %1 இந்த மாறியிற்கு %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "'எடு %1' உருவாக்கு"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "மாறியின் மதிப்பாய் உள்ளீட்டு மதிப்பை வை."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/tcy.js b/backend/_pv_1_3_5/static/blockly/msg/js/tcy.js deleted file mode 100755 index 47fbb0cbc..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/tcy.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.tcy'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "ಟಿಪ್ಪಣಿ ಸೇರ್ಸಲೆ"; -Blockly.Msg.CHANGE_VALUE_TITLE = "ಮೌಲ್ಯೊದ ಬದಲಾವಣೆ"; -Blockly.Msg.CLEAN_UP = "ನಿರ್ಬಂದೊಲೆನ್ ಸ್ವೊಚ್ಚೊ ಮಲ್ಪುಲೆ"; -Blockly.Msg.COLLAPSE_ALL = "ಕುಗ್ಗಿಸಾದ್ ನಿರ್ಬಂಧಿಸಾಪುನೆ"; -Blockly.Msg.COLLAPSE_BLOCK = "ಕುಗ್ಗಿಸಾದ್ ತಡೆಪತ್ತುನೆ"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "ಬಣ್ಣೊ ೧(ಒಂಜಿ)"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "ಬಣ್ಣೊ ೨(ರಡ್ಡ್)"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "ಅನುಪಾತೊ"; -Blockly.Msg.COLOUR_BLEND_TITLE = "ಮಿಸ್ರನೊ"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "ಕೊರ್‍ನ ಅನುಪಾತೊದ ಒಟ್ಟುಗೆ (0.0- 1.0 ) ರಡ್ಡ್ ಬಣ್ಣೊಲೆನ್ ಜೊತೆಟ್ ಒಂಜಿ ಮಲ್ಪುಂಡು."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/ಬಣ್ಣೊ"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "ವರ್ಣಫಲಕೊದ ಒಂಜಿ ಬಣ್ಣೊದ ಆಯ್ಕೆ."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "ಯಾದೃಚ್ಛಿಕೊ ಬಣ್ಣೊ"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "ಯಾದೃಚ್ಛಿಕವಾಯಿನ ಬಣ್ಣೊದ ಆಯ್ಕೆ."; -Blockly.Msg.COLOUR_RGB_BLUE = "ನೀಲಿ"; -Blockly.Msg.COLOUR_RGB_GREEN = "ಪಚ್ಚೆ"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "ಕೆಂಪು ಬಣ್ಣೊ"; -Blockly.Msg.COLOUR_RGB_TITLE = "ಬಣ್ಣೊದೊಟ್ಟುಗೆ"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "ತೋಜಿಪಾಯಿನ ಕೆಂಪು, ಪಚ್ಚೆ ಬುಕ್ಕೊ ನೀಲಿ ಬಣ್ಣೊದ ಪ್ರಮಾಣೊನು ರಚಿಸಲೆ. ಮಾಂತ ಮೌಲ್ಯೊಲು 0 ಬುಕ್ಕೊ 100 ನಡುಟೆ ಇಪ್ಪೊಡು."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "ಕುಣಿಕೆದ ಪಿದಯಿ ತುಂಡಾಪುಂಡು"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "ದುಂಬುದ ಆದೇಸೊಡೆ ಪುನರಾವರ್ತನೆ ದುಂಬರಿಪ್ಪುಂಡು"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "ಬಳಕೆಡುಪ್ಪುನ ಕೊಲಿಕೆಡ್ದ್ ಪಿದಯಿ ಪಾಡ್‍ಲೆ"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "ದುಂಬುದ ಆವೃತಿಡ್ ಉಪ್ಪುನಂಚನೆ ಮಾಂತ ಕೊಲಿಕೆಲೆನ್ ದೆತ್ಪುಲೆ ಬುಕ್ಕೊ ದುಂಬರಿಲೆ"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "ಎಚ್ಚರೊ: ಈ ನಿರ್ಬಂದೊನು ಕೇವಲ ಒಂಜಿ ಕೊಲಿಕೆದಾಕಾರೊದ ಮುಕ್ತಮಾರ್ಗೊದ ಪರಿಮಿತಿದುಲಯಿಡ್ ಬಳಸೊಲಿ"; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "ಅತ್ತಂದೆ ಪ್ರತೀ ಅಂಸೊ %1ದ ಉಲಯಿ %2ದ ಪಟ್ಟಿ"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "ಒಂಜಿ ಪಟ್ಟಿಡ್ ಪ್ರತಿ ವಸ್ತುಗು, ಜೋಡಾಯಿನ ವಸ್ತು ಬದಲಾಪುನಂಚ '% 1', ಬುಕ್ಕೊ ಒಂತೆ ಹೇಳಿಕೆಲೆನ್ ಮಲ್ಲಪುಲೆ."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "%1ಡ್ದ್ %2ಗ್ ಮುಟ್ಟ %3 ಬುಕ್ಕೊ %4ನ್ ಒಟ್ಟೂಗು ಗೆನ್ಪಿ"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "ಸುರೂತ ನಂಬ್ರೊಡ್ದು ಅಕೇರಿದ ನಂಬ್ರೊಗು ಬಿಲೆಟ್ ಮಸ್ತ್ ಹೆಚ್ಚ್‌ಕಮ್ಮಿ ಇತ್ತ್ಂಡಲಾ %1 ದೆತೊಂದ್, ನಿರ್ದಿಸ್ಟೊ ಮಧ್ಯಂತರೊದ ಮೂಲಕೊ ಲೆಕ್ಕೊದೆತೊಂದು ಬುಕ್ಕೊ ನಿಗಂಟ್ ಮಲ್ತ್‌ನ ಬ್ಲಾಕ್‍ಲೆನ್ ಲೆಕ್ಕೊ ಮಲ್ಪುಲ."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "ಒಂಜಿ ವೇಲೆ ಒಂಜಿ ತಡೆಕ್ ಈ ಪರಿಸ್ಥಿತಿನ್ ಸೇರಲೆ"; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "ಒಂಜಿ ವೇಲೆ ಮಾಂತೆನ್ಲಾ ದೀಡೊಂದು ಅಕೇರಿದ ಪರಿಸ್ಥಿಡ್ ಸೇರಲೆ"; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "ಸೇರಲ, ದೆತ್ತ್‌ ಪಾಡ್‌ಲ, ಅತ್ತಂಡ ಒಂಜಿ ವೇಲೆ ಈ ರಚನೆನ್ ತಡೆದ್, ಇಂದೆತ ಇಬಾಗೊಲೆನ್ ಬೇತೆ ಕ್ರಮೊಟು ಮಲ್ಪುಲೆ"; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "ಬೇತೆ"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "ಬೇತೆ ಸಮಯೊ"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "ಒಂಜಿ ವೇಲೆ"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "ಇಂದೆತ ಮೌಲ್ಯೊ ನಿಜವಾದಿತ್ತ್‌ಂಡ, ಬುಕ್ಕೊ ಒಂತೆ ನಿರೂಪಣೆಲೆನ್ ಮಲ್ಪುಲೆ"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "ಇಂದೆತ ಮೌಲ್ಯೊ ನಿಜವಾದಿತ್ತ್‌ಂಡ, ಬುಕ್ಕೊದ ನಿರೂಪಣೆಲೆನ್ ಸುರೂಕು ಮಲ್ಪುಲೆ. ಅತ್ತಂಡ ರಡ್ಡನೆದ ನಿರೂಪಣೆನ್ ತಡೆ ಪತ್ತುನಂಚನೆ ಮಲ್ಲಪುಲೆ"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "ಸುರೂತ ಮೌಲ್ಯೊ ನಿಜವಾದಿತ್ತ್‌ಂಡ, ಬುಕ್ಕೊದ ನಿರೂಪಣೆಲೆನ್ ಸುರೂಕು ತಡೆ ಮಲ್ಪುಲೆ. ಅತ್ತಂಡ ರಡ್ಡನೆದ ನಿರೂಪಣೆನ್ ನಿಜವಾದಿತ್ತ್‌ಂಡ ಬುಕ್ಕೊ ಒಂತೆ ನಿರೂಪಣೆಲೆನ್ ಮಲ್ಪುಲೆ"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "ಸುರೂತ ಮೌಲ್ಯೊ ನಿಜವಾದಿತ್ತ್‌ಂಡ, ಸುರೂತ ನಿರೂಪಣೆನ್ ತಡೆ ಮಲ್ಪುಲೆ. ರಡ್ಡನೆದ ನಿರೂಪಣೆ ನಿಜವಾದಿತ್ತ್ಂಡ, ರಡ್ಡನೆದ ನಿರೂಪಣೆನ್ ತಡೆ ಮಲ್ಪುಲೆ. ಉಂದು ಒವ್ವೇ ಮೌಲ್ಯೊ ನಿಜವಾದಿದ್ಯಂಡ, ಅಕೇರಿದ ನಿರೂಪಣೆನ್ ತಡೆ ಮಲ್ಪುಲೆ."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "ಮಲ್ಪು / ಅಂಚನೆ"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "ನಾನೊರೊ %1 ಸಮಯೊಗು"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "ಕೆಲವು ಹೇಳಿಕೆಲೆನ್ ಮಸ್ತ್ ಸಮಯೊ ಮಲ್ಪೊಡು"; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "ಬುಕ್ಕೊ ಮುಟ್ಟೊ"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "ಬುಕ್ಕೊ ಅಂಚನೇ"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "ಈ ತಿರ್ತ್‍ದ ತಪ್ಪಾದುಂಡು, ಬುಕ್ಕೊದ ಕೆಲವು ಹೇಳಿಕೆಲೆನ್ ಮಲ್ಪಪುಲ"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "ಈ ತಿರ್ತ್‌ದ ಸರಿ ಇತ್ತ್ಂಡಲಾ, ಬುಕ್ಕೊದ ಕೆಲವು ಹೇಳಿಕೆಲೆನ್ ಮಲ್ಪುಲ"; -Blockly.Msg.DELETE_ALL_BLOCKS = "ಮಾತ %1 ನಿರ್ಬಂದೊಲೆನ್ ದೆತ್ತ್ ಪಾಡ್ಲೆ ?"; -Blockly.Msg.DELETE_BLOCK = "ಮಾಜಯರ ತಡೆಯಾತ್ಂಡ್"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "ಮಾಜಯರ ಶೇಕಡಾ ೧ ತಡೆಯಾತ್ಂಡ್"; -Blockly.Msg.DISABLE_BLOCK = "ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಾದ್ ತಡೆಪತ್ತುನೆ"; -Blockly.Msg.DUPLICATE_BLOCK = "ನಕಲ್"; -Blockly.Msg.ENABLE_BLOCK = "ಸಕ್ರಿಯಗೊಳಿಸಾದ್ ತಡೆಪತ್ತುನೆ"; -Blockly.Msg.EXPAND_ALL = "ವಿಸ್ತರಿಸಾದ್ ನಿರ್ಬಂದಿಸಾಪುನೆ"; -Blockly.Msg.EXPAND_BLOCK = "ವಿಸ್ತರಿಸಾದ್ ತಡೆಪತ್ತುನೆ"; -Blockly.Msg.EXTERNAL_INPUTS = "ಬಾಹ್ಯೊ ಪರಿಕರೊ"; -Blockly.Msg.HELP = "ಸಹಾಯೊ"; -Blockly.Msg.INLINE_INPUTS = "ಉಳಸಾಲ್‍ದ ಉಳಪರಿಪು"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "ಕಾಲಿ ಪಟ್ಟಿನ್ ಸ್ರಿಸ್ಟಿಸಲೆ"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "ಒಂಜಿ ಪಟ್ಟಿ, ೦ದ ಉದ್ದೊ, ಒವ್ವೇ ಅಂಕಿಅಂಸೊ ಇದ್ಯಾಂತಿನ ದಾಖಲೆ ಪಿರಕೊರು."; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "ಪಟ್ಟಿ"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "ಸೇರಯರ, ದೆತ್ತ್‌ ಪಾಡೆರೆ ಅತ್ತಂಡ ಈ ಪಟ್ಯೊಲೆನ್ ತಡೆದ್ ಪತ್ತ್‌ದ್ ಇಬಾಗೊ ಮಲ್ಪುಲೆ."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "ಜತೆ ಪಟ್ಟಿನ್ ರಚಿಸಲೆ"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "ಪಟ್ಟಿಡ್ ಕೆಲವು ಅಂಸೊಲೆನ್ ಸೇರಲೆ."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "ಒವ್ವೇ ಸಂಖ್ಯೆದ ಪಟ್ಟಿಲೆ ಅಂಸೊದೊಟ್ಟುಗೆ ರಚಿಸಲೆ"; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "ಸುರುತ"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# ಅಕೇರಿಡ್ದ್"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "ದೆತೊನು"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "ದೆತೊನಿಯರ ಬುಕ್ಕೊ ದೆಪ್ಪೆರೆ"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "ಕಡೆತ"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "ಗೊತ್ತು ಗುರಿದಾಂತಿನ"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "ದೆಪ್ಪುಲೆ"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "ಸುರುತ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ಪಿರಕೊರು."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "ನಿರ್ದಸ್ಟೊ ಜಾಗೆಡುಪ್ಪುನ ಅಂಸೊಲೆ ಪಟ್ಟಿನ್ ಪಿರಕೊರು"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "ಅಕೇರಿದ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ಪಿರಕೊರು."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "ಗೊತ್ತುಗುರಿದಾಂತಿನ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ಪಿರಕೊರು."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "ಸುರುತ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ದೆಪ್ಪು ಅತ್ತಂಡ ಪಿರಕೊರು."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "ನಿರ್ದಿಸ್ಟೊ ಜಾಗೆಡುಪ್ಪುನ ಅಂಸೊಲೆ ಪಟ್ಟಿನ್ ದೆಪ್ಪು ಅತ್ತಂಡ ಪಿರಕೊರು"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "ಅಕೇರಿದ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ದೆಪ್ಪು ಅತ್ತಂಡ ಪಿರಕೊರು."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "ಗೊತ್ತುಗುರಿದಾಂತಿನ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ದೆಪ್ಪು ಅತ್ತಂಡ ಪಿರಕೊರು."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "ಸುರುತ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ದೆಪ್ಪು."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "ನಿರ್ದಿಸ್ಟೊ ಜಾಗೆಡುಪ್ಪುನ ಅಂಸೊಲೆ ಪಟ್ಟಿನ್ ದೆಪ್ಪುಲೆ"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "ಅಕೇರಿದ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ದೆಪ್ಪು."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "ಗೊತ್ತುಗುರಿದಾಂತಿನ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ದೆಪ್ಪು."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "ಡ್ದ್ # ಅಕೇರಿಗ್"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "ಡ್ದ್"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "ಅಕೇರಿಡ್ದ್"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "ಉಪ-ಪಟ್ಯೊನು ಸುರುಡ್ದು ದೆತೊನು"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "ಉಪ-ಪಟ್ಯೊನು ದೆತೊನು#ಅಕೇರಿಡ್ದ್"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "ಉಪ-ಪಟ್ಯೊನು ದೆತೊನು#"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "ಪಟ್ಯೊದ ನಿರ್ದಿಷ್ಟ ಬಾಗೊದ ಪ್ರತಿನ್ ಸ್ರಸ್ಟಿಸವುಂಡು."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 ಅಕೇರಿತ ಅಂಸೊ"; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 ಸುರುತ ಅಂಸೊ"; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "ದುಂಬು ಕರಿನ ಪಟ್ಯೊನು ನಾಡ್‍ಲೆ"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "ಅಕೆರಿಗ್ ಕರಿನ ಪಟ್ಯೊನು ನಾಡ್‍ಲೆ"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "ಸುರುತ ಪಟ್ಯೊದ ಸೂಚ್ಯಿ/ಅಕೇರಿಟ್ ಸಂಭವಿಸವುನ ಸುರುತ ಪಟ್ಟಯೊದುಲಯಿದ ರಡ್ಡನೆ ಪಟ್ಯೊನು ಪಿರಕೊರು. %1 ಪಟ್ಯೊ ತಿಕಂದಿತ್ತ್‌ಂಡ ಪಿರಕೊರು."; -Blockly.Msg.LISTS_INLIST = "ಪಟ್ಟಿಡ್"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 ಕಾಲಿ"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "ಪಟ್ಯೊ ಕಾಲಿ ಪನ್ಪುನವು ಸತ್ಯೊ ಆಂಡ ಪಿರಕೊರು."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "೧% ಉದ್ದೊ"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "ಪಟ್ಟಿದ ಉದ್ದೊನು ಪಿರಕೊರು."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "%1 ಪಿರೊರ %2 ಕಾಲೊಡು ಪಟ್ಟಿಲೆನ ಅಂಸೊನು ರಚಿಸಲೆ."; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "ಕೊರ್‍ನ ಮೌಲ್ಯಡು ನಿರ್ದಿಷ್ಟ ಕಾಲೊಡು ಪಿರೊತ ಪಟ್ಟಿನ್ ರಚಿಸಲೆ."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "ಅಂಚ"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "ಸೇರಲ"; -Blockly.Msg.LISTS_SET_INDEX_SET = "ಮಾಲ್ಪು"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "ಸುರುತ ಅಂಸೊಲೆ ಪಟ್ಟಿನ್ ಸೇರಲ."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "ನಿರ್ದಿಸ್ಟೊ ಜಾಗೆಡುಪ್ಪುನ ಅಂಸೊಲೆ ಪಟ್ಟಿನ್ ಸೇರಲ"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "ಪಟ್ಟಿದ ಅಕೇರಿಗ್ ಈ ಅಂಸೊಲೆನ್ ಸೇರಲ."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "ಪಟ್ಟಿಗ್ ಗೊತ್ತುಗುರಿದಾಂತೆ ಅಂಸೊಲೆನ್ ಸೇರಲ."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "ಸುರುತ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ಮಾಲ್ಪು."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "ನಿರ್ದಿಸ್ಟೊ ಜಾಗೆಡುಪ್ಪುನ ಅಂಸೊಲೆ ಪಟ್ಟಿನ್ ಮಾಲ್ಪು"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "ಅಕೇರಿದ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ಮಾಲ್ಪು."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "ಗೊತ್ತುಗುರಿದಾಂತಿನ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ಮಾಲ್ಪು."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ಮಿತ್ತ್ ಪೋಪುನೆ"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "ತಿರ್ತ್ ಪೋಪುನೆ"; -Blockly.Msg.LISTS_SORT_TITLE = "%1 %2 %3 ಇಂಗಡಿಪು"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "ಪಟ್ಟಿಲೆ ಪ್ರತಿನ್ ಇಂಗಡಿಪುಲೆ"; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "ಅಕ್ಷರೊಲು, ಸಂದರ್ಭೊಡು ನಿರ್ಲಕ್ಷಿಸಲೆ"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "ಸಂಕೇತೊ"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "ಅಕ್ಷರೊಲು"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "ಪಟ್ಯೊಲೆ ಪಟ್ಟಿನ್ ತಯಾರ್ ಮಲ್ಪುಲೆ"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "ಪಟ್ಟಿದ ಪಟ್ಯೊನು ತಯಾರ್ ಮಲ್ಪುಲೆ"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "ಒಂಜಿ ಗ್ರಂತೊಡ್ದು ಒಂಜಿ ಪಟ್ಯೊದ ಪಟ್ಟಿಗ್ ಸೇರಾದ್, ಮಿತಿಸೂಚಕೊದ ಮೂಲಕೊ ಬೇತೆ ಮಲ್ಪುಲೆ."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "ಗ್ರಂತೊಲೆನ ಪಟ್ಟಿಡ್ದ್ ಪಟ್ಯೊಲೆನ್ ಬೇತೆ ಮಾಲ್ತ್‌ಂಡ,ಪ್ರತಿ ಮಿತಿಸೂಚಕೊಡು ಬೇತೆ ಆಪುಂಡು."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "ಮಿತಿಸೂಚಕೊದ ಒಟ್ಟುಗು"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "ಸುಲ್ಲು"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "ಪೂರ ಸತ್ಯೊ ಅತ್ತಂಡ ಸುಲ್ಲು ಆಂಡ ಪಿರಕೊರು"; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "ಸತ್ಯೊ"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "ರಡ್ಡ್ ಅತ್ತಂದೆ ಬೇತೆ ಸೂಚನೆಲು ನಿಜೊಕ್ಕುಲಾ ಸಮೊ ಇತ್ತ್ಂಡ ಪಿರ ಕೊರ್ಲೆ."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "ಸುರುತ ಅತ್ತಂದೆ ರಡ್ಡನೆದ ಸೂಚನೆಡ್ದ್ ನಿಜೊಕ್ಕುಲಾ ಮಲ್ಲೆ ಆದಿತ್ತ್ಂಡ ಪಿರ ಕೊರ್ಲೆ"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "ಸುರುತ ಅತ್ತಂದೆ ರಡ್ಡನೆದ ಸೂಚನೆ ನಿಜೊಕ್ಕುಲಾ ದಿಂಜ ಮಲ್ಲೆ ಅತ್ತಂಡ ಸಮೊ ಆದಿತ್ತ್ಂಡ ಪಿರ ಕೊರ್ಲೆ"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "ಸುರುತ ಅತ್ತಂದೆ ರಡ್ಡನೆದ ಸೂಚನೆ ನಿಜೊಕ್ಕುಲಾ ಒಂಜಿ ವೇಲೆ ಎಲ್ಯೆ ಆದಿತ್ತ್ಂಡ ಪಿರ ಕೊರ್ಲೆ"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "ಸುರುತ ಅತ್ತಂದೆ ರಡ್ಡನೆದ ಸೂಚನೆ ನಿಜೊಕ್ಕುಲಾ ದಿಂಜ ಎಲ್ಯೆ ಅತ್ತಂಡ ಸಮೊ ಆದಿತ್ತ್ಂಡ ಪಿರ ಕೊರ್ಲೆ"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "ರಡ್ಡ್ ಅತ್ತಂದೆ ಬೇತೆ ಸೂಚನೆಲು ನಿಜೊಕ್ಕುಲಾ ಸಮೊ ಆತಿಜಂಡ ಪಿರ ಕೊರ್ಲೆ"; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "%1 ಇದ್ದಿ"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "ನಿಜವಾದ್‍ ಇನ್‍ಪುಟ್ ಸುಲ್ಲಾದಿತ್ತ್‌ಂಡ ಪಿರಕೊರು. ನಿಜವಾದ್ ಸುಲ್ಲು ಇನ್‍ಪುಟ್ ಇತ್ತ್‌ಂಡ ಪಿರಕೊರು"; -Blockly.Msg.LOGIC_NULL = "ಸೊನ್ನೆ"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "ಸೊನ್ನೆನ್ ಪರಿಕೊರ್ಪುಂಡು"; -Blockly.Msg.LOGIC_OPERATION_AND = "ಬುಕ್ಕೊ"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "ಅತ್ತಂಡ"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "ರಡ್ಡ್ ಸೂಚನೆಲಾ ನಿಜೊ ಆದಿತ್ತ್ಂಡ ನಿಜವಾತ್ ಪಿರಕೊರ್ಲೆ"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "ನಿಜವಾದ್‍ಲ ಒಂಜಿವೇಳೆ ಇನ್‍ಪುಟ್ ಒಂತೆ ನಿಜವಾದಿತ್ತ್ಂಡ ಪಿರಕೊರು"; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "ಪರೀಕ್ಷೆ"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "ಒಂಜಿ ವೇಲೆ ಸುಳ್ಳು"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "ಒಂಜಿ ವೇಲೆ ಸತ್ಯೊ"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "ಪರೀಕ್ಷೆದ ಸ್ಥಿತಿನ್ ಪರಿಶೀಲನೆ ಮಲ್ಲಪುಲೆ. ಪರಿಸ್ಥಿತಿ ನಿಜವಾದಿತ್ತ್ಂಡ, ನಿಜವಾಯಿನ ಮೌಲ್ಯೊನು ಪಿರಕೊರ್ಲೆ; ಅತ್ತಂಡ ತಪ್ಪು ಮೌಲ್ಯೊನೇ ಪಿರ ಕೊರ್ಲೆ."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/ಅಂಕಗಣಿತ"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "ಸಂಖ್ಯೆದ ಮೊತ್ತನ್ ಪಿರ ಕೊರು."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "ಸಂಖ್ಯೆದ ಭಾಗಲಬ್ದೊನು ಪಿರ ಕೊರು."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "ಸಂಖ್ಯೆದ ವ್ಯತ್ಯಾಸೊನು ಪರಕೊರು."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "ಸಂಖ್ಯೆದ ಉತ್ಪನ್ನೊನು ಪಿರ ಕೊರು."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "ಒಂಜನೆ ಸಂಖ್ಯೆದ ಶಕ್ತಿನ್ ರಡ್ಡನೆ ಸಂಖ್ಯೆಡ್ದ್ ಪಿರ ಹೆಚ್ಚಿಗೆ ಮಲ್ಪುಲೆ."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; // untranslated -Blockly.Msg.MATH_CHANGE_TITLE = "%1 ಡ್ದ್ %2 ಬದಲಾಯಿಸವೊಲಿ"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "'%1' ಬದಲ್ ಮಲ್ಪುನಂಚಿನ ಒಂಜಿ ನಂಬರ್‍ನ್ ಸೇರಾವು"; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/ಗಣಿತ_ನಿರಂತರ"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "ಸಾಮಾನ್ಯವಾದ್ ಒಂಜಿ ಸ್ಥಿರವಾದಿತ್ತ್‌ಂಡ ಪಿರಕೊರು: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = " %1 ಕಮ್ಮಿ %2 ಜಾಸ್ತಿ %3 ಕಡ್ಡಾಯ ಮಲ್ಪು"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "ನಿಗದಿತ ನಿಯಮೊಗು ನಡುಟು ದಿಂಜ ನಿರ್ಬಂದೊ(ಸೇರ್‍ನಂಚ)"; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "ಭಾಗಿಸವೊಲಿಯ"; -Blockly.Msg.MATH_IS_EVEN = "ಸಮೊ ಆತ್ಂಡ್"; -Blockly.Msg.MATH_IS_NEGATIVE = "ರುನೊ ಆತ್ಂಡ್"; -Blockly.Msg.MATH_IS_ODD = "ಬೆಸೊ ಆತ್ಂಡ್"; -Blockly.Msg.MATH_IS_POSITIVE = "ಗುನೊ ಆತ್ಂಡ್"; -Blockly.Msg.MATH_IS_PRIME = "ಎಡ್ಡೆ ಆತ್ಂಡ್"; -Blockly.Msg.MATH_IS_TOOLTIP = "ಒಂಜಿ ವೇಲ್ಯೊ ಸಂಖ್ಯೆ ಸರಿ, ಬೆಸ, ಅವಿಭಾಜ್ಯ, ಇಡೀ, ಕೂಡಬುನ, ಕಲೆವುನ, ಅತ್ತಂಡ ನಿರ್ದಿಷ್ಟ ಸಂಖ್ಯೆಡ್ದ್ ಭಾಗಿಸವುಂಡಂದ್ ಪರಿಶೀಲಿಸ. ಸರಿ ಅತ್ತಂಡ ತಪ್ಪುನು ಪಿರಕೊರು."; -Blockly.Msg.MATH_IS_WHOLE = "ಮಾಂತ ಆತ್ಂಡ್"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/ಮೋಡ್ಯುಲೊ_ಒಪರೇಶನ್"; -Blockly.Msg.MATH_MODULO_TITLE = " %1 ÷ %2 ಒರಿನ ಬಾಗೊ"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "ರಡ್ಡ್ ಸಂಖ್ಯೆದ ಇಬಾಗೊಡ್ದು ಒರಿನ ಬಾಗೊನು ಪಿರಕೊರು"; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/ಸಂಖ್ಯೆ"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "ಅ ನಂಬ್ರೊ"; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "ಸರಾಸರಿ ಪಟ್ಟಿ"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "ಪಟ್ಟಿನ್ ಮಿಸ್ರೊ ಮಲ್ಪು"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "ನಡುತ ಪಟ್ಟಿ"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "ಕಿನ್ಯ ಪಟ್ಟಿ"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "ಪಟ್ಟಿದ ಇದಾನೊಲು"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "ಗೊತ್ತುಗುರಿ ದಾಂತಿನ ಅಂಸೊದ ಪಟ್ಟಿ"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "ಕಬರ್ ಪಟ್ಟಿದ ಪ್ರಮಾನೊ"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "ಒಟ್ಟು ಕೂಡಯಿನಾ ಪಟ್ಟಿ"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "ಪಟ್ಟಿಡುಪ್ಪುನ ಸರ್ವಸಾಧಾರಣ ಬಿಲೆನ್ ಪಿರಕೋರ್ಲೆ"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "ಪಟ್ಟಿದಾ ಮಲ್ಲ ಸಂಕ್ಯೆನ್ ಪಿರಕೊರು"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "ಪಟ್ಟಿದಾ ನಡುತ ಸಂಕ್ಯೆನ್ ಪಿರಕೊರು"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "ಪಟ್ಟಿದಾ ಕಿನ್ಯ ಸಂಕ್ಯೆನ್ ಪಿರಕೊರು"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "ಪಟ್ಟಿದ ಸಾಮಾನ್ಯೊ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ಪಿರಕೊರು"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "ಪಟ್ಟಿದ ಗೊತ್ತು ಗುರಿದಾಂತಿನ ಅಂಸೊಲೆನ್ ಪಿರಕೊರು"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "ಪಟ್ಟಿದ ಗುಣಮಟ್ಟೊದ ವರ್ಗೀಕರಣೊನು ಪಿರಕೊರು"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "ಪಟ್ಟಿದಾ ಮಾಂತ ಸಂಕ್ಯೆಲೆನ್ ಪಿರಕೊರ್ಲೆ"; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/ರಾಂಡಮ್_ನಂಬರ್_ಜನರೇಶನ್"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "ಗೊತ್ತುಗುರಿ ದಾಂತಿನ ಬಾಗೊ"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "0.0 (ಸೇರ್ನಂಚಿನ) and 1.0 (ಸೇರಂದಿನಂಚಿನ) ನಡುತ ಗೊತ್ತು ಗುರಿದಾಂತಿನ ಬಾಗೊನು ಪಿರಕೊರು."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/ರಾಂಡಮ್_ನಂಬರ್_ಜನರೇಶನ್"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = " %1 ಡ್ದ್ %2 ಯಾದೃಚ್ಛಿಕ ಪೂರ್ಣಾಂಕೊ"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "ರಡ್ಡ್ ನಿಗದಿತ ನಿಯಮೊದ ನಡುತ ಯಾದೃಚ್ಛಿಕ ಪೂರ್ಣಾಂಕೊನು ಪಿರಕೊರು"; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/ಪೂರ್ಣಾಂಕೊ"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "ಸುತ್ತು"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "ಸುತ್ತು ಕಡಮೆ"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "ಮುಗಿಪುನ ಸಮಯೊ"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "ಸಂಖ್ಯೆನ್ ಮಿತ್ತ್ ಅತ್ತಂಡ ತಿರ್ತ್ ರೌಂಡ್ ಮಲ್ಪು"; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/ವರ್ಗೊಮೂಲೊ"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "ಸಂಪೂರ್ನೊ"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "ವರ್ಗಮೂಲೊ"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "ಸಂಖ್ಯೆದ ಸರಿಯಾಯಿನ ಮೌಲ್ಯೊನು ಕೊರು"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "ಸಂಖ್ಯೆದ ಇ ಗ್ ಅಧಿಕಾರೊನು ಪಿರಕೊರು"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "ಸಂಖ್ಯೆದ ನಿಜವಾಯಿನ ಕ್ರಮಾವಳಿನ್ ಪಿರಕೊರು"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "ಸಂಖ್ಯೆದ ೧೦ ಮೂಲೊ ಕ್ರಮಾವಳಿನ್ ಪಿರಕೊರು"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "ಸಂಖ್ಯೆದ ನಿರಾಕರಣೆನ್ ಪಿರಕೊರು"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "ಸಂಖ್ಯೆದ ೧೦ಗ್ ಅಧಿಕಾರೊನು ಪಿರಕೊರು"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "ಸಂಖ್ಯೆದ ವರ್ಗಮೂಲೊನು ಪಿರ ಕೊರು."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/ತ್ರಿಕೋನಮಿತಿದ_ಕಾರ್ಯೊಲು"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "ಸಂಖ್ಯೆದ ಆರ್ಕ್ಕೊಸಿನ್ ಪಿರಕೊರು"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "ಪದವಿದ ಆರ್ಕ್ಸೈನ್ ಪಿರಕೊರು"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "ಸಂಖ್ಯೆದ ಆರ್ಕ್ಟ್ಯಾಂಜೆಂಟ್ ಪಿರಕೊರು"; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "ಪದವಿದ ಸಹ ಚಿಹ್ನೆನ್ ಪಿರಕೊರು"; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "ಪದವಿದ ಚಿಹ್ನೆನ್ ಪಿರಕೊರು"; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "ಪದವಿದ ಸ್ಪರ್ಶಕೊನು ಪಿರಕೊರು"; -Blockly.Msg.NEW_VARIABLE = "ಪೊಸ ಬದಲಾವಣೆ"; -Blockly.Msg.NEW_VARIABLE_TITLE = "ಪುದರ್‍ದ ಪೊಸ ಬದಲಾವಣೆ:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "ಹೇಳಿಕೆಗ್ ಅವಕಾಸೊ"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "ಜೊತೆ:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/ಪ್ರೊಸಿಜರ್_%28ಕಂಪ್ಯೂಟರ್_ಸೈನ್ಸ್%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "'%1' ಬಳಕೆದಾರೆರೆ ಕಾರ್ಯೊನು ನಡಪಾಲೆ."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/ಪ್ರೊಸಿಜರ್_%28ಕಂಪ್ಯೂಟರ್_ಸೈನ್ಸ್%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = " '%1' ಬಳಕೆದಾರೆರೆ ಕಾರ್ಯೊನು ನಡಪಾಲೆ ಬುಕ್ಕೊ ಅಯಿತ ಉತ್ಪಾದನೆನ್ ಉಪಯೋಗಿಸಲೆ."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "ಜೊತೆ:"; -Blockly.Msg.PROCEDURES_CREATE_DO = " '%1'ನ್ ರಚಿಸಲೆ"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "ಈ ಕಾರ್ಯೊನು ಇವರಿಸಲೆ..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "ಎಂಚಿನಾಂಡಲ ಮಲ್ಪು"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "ಇಂದೆಕ್"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "ಉತ್ಪಾದನೆ ದಾಂತಿನ ಕಾರ್ಯೊನು ಸ್ರಿಸ್ಟಿಸಲೆ."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "ಪಿರಪೋ"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "ಉತ್ಪಾದನೆ ದಾಂತಿನ ಕಾರ್ಯೊನು ಸ್ರಿಸ್ಟಿಸಲೆ."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "ಎಚ್ಚರಿಕೆ: ಈ ಕಾರ್ಯೊ ನಕಲಿ ಮಾನದಂಡೊನು ಹೊಂದ್‍ದ್ಂಡ್."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "ದೇರ್ತ್ ತೋಜುನ ಕಾರ್ಯೊದ ವ್ಯಾಕ್ಯಾನೊ"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "ಮೌಲ್ಯೊ ಸತ್ಯೊ ಆಯಿನೆಡ್ದ್ ಬುಕ್ಕೊನೆ ರಡ್ಡನೆ ಮೌಲ್ಯೊನು ಪಿರಕೊರು."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "ಎಚ್ಚರಿಕೆ:ವ್ಯಾಕ್ಯಾನೊದ ಕಾರ್ಯೊನು ತಡೆ ಮಲ್ಪೆರೆ ಮಾತ್ರೊ ಇಂದೆತ ಉಪಯೊಗ."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "ಉಲಪರಿಪುದ ಪುದರ್:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "ಕಾರ್ಯೊದ ಉಲಪರಿಪುನು ಸೇರಲೆ."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "ಉಲಪರಿಪು"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "ಸೇರಯರ, ದೆತ್ತ್‌ ಪಾಡೆರೆ ಅತ್ತಂಡ ಪಿರಕೋರಿಕೆದ ಉಲಪರಿಪುದ ಕಾರ್ಯೊನು ಮಲ್ಪುಲೆ."; -Blockly.Msg.REDO = "ಪಿರವುದಂಚ"; -Blockly.Msg.REMOVE_COMMENT = "ಟಿಪ್ಪಣಿನ್ ದೆತ್ತ್‌ಪಾಡ್ಲೆ"; -Blockly.Msg.RENAME_VARIABLE = "ಬದಲಾವಣೆ ಆಯಿನ ಪುದರ್‍ನ್ ನಾನೊರೊ ಪನ್ಲೆ"; -Blockly.Msg.RENAME_VARIABLE_TITLE = "ನಾನೊರೊ ಪುದರ್ ಬದಲಾವಣೆ ಆಯಿನ ಮಾಂತ '% 1':"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "ಪಟ್ಯೊನು ಸೇರವೆ"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "ಇಂದೆಕ್"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "%1 ಬದಲಾಪುನ ಕೆಲವು ಪಟ್ಯೊಲೆನ್ ಸೇರಾವೊಂಡು."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "ಎಲ್ಯ ಅಕ್ಷರೊಗು"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "ತರೆಬರವುಗು"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "ಮಲ್ಲ ಅಕ್ಷರೊಗು"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "ಪಟ್ಯೊದ ಒಂಜಿ ನಕಲ್‍ನ್ ಬೇತೆ ಸಮಯೊಡು ಪಿರಕೊರು"; -Blockly.Msg.TEXT_CHARAT_FIRST = "ಸುರುಡ್ದ್ ಅಕ್ಷರೊನು ನಟೊನ್ಲ"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "ಅಕ್ಷರೊ ನಟೊನ್#ಅಕೇರಿಡ್ದ್"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "ಅಕ್ಸರೊನು ದೆತೊನುಲೆ#"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "ಪಟ್ಯೊಡು"; -Blockly.Msg.TEXT_CHARAT_LAST = "ಅಕೇರಿದ ಅಕ್ಷರೊನು ನಟೊನ್ಲ"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "ಗೊತ್ತುಗುರಿದಾಂತಿ ಅಕ್ಷರೊನು ನಟೊನ್ಲ"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "ಅಕ್ಷರೊನು ನಿರ್ದಿಷ್ಟ ಜಾಗೆಡ್ ಪಿರಕೊರು."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "ಪಟ್ಯೊಡು ಅಂಸೊಲೆನ್ ಸೇರಲೆ"; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "ಸೇರೊಲಿ"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "ಸೇರಯರ, ದೆತ್ತ್‌ ಪಾಡೆರೆ ಅತ್ತಂಡ ಈ ಪಟ್ಯೊಲೆನ್ ತಡೆದ್ ಪತ್ತ್‌ದ್ ಪಿರ ರಚಿಸಯರ ಇಬಾಗೊ ಮಲ್ಪುಲೆ."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "ಅಕ್ಷರೊಗು#ಅಕೇರಿಡ್ದ್"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "ಅಕ್ಷರೊಗು#"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "ಅಕೇರಿದ ಅಕ್ಷರೊಗು"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "ಪಟ್ಯೊಡು"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "ಉಪ ವಾಕ್ಯೊಡ್ದು ಸುರುತ ಅಕ್ಷರೊನು ನಟೊನ್ಲ"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "ಉಪ ವಾಕ್ಯೊಡ್ದು ಅಕ್ಷರೊನು ನಟೊನ್ಲ#ಅಕೇರಿಡ್ದ್"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "ಉಪ ವಾಕ್ಯೊಡ್ದು ಅಕ್ಷರೊನು ನಟೊನ್ಲ"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "ಪಟ್ಯೊನು ನಿರ್ದಿಷ್ಟ ಬಾಗೊಡು ಪಿರಕೊರು"; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "ಪಟ್ಯೊಡು"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "ಸುರುಟು ಸಂಭವಿಸಯಿನ ಪಟ್ಯೊನು ನಾಡ್‍ಲ"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "ದುಂಬು ಕರಿನ ಪಟ್ಯೊನು ನಾಡ್‍ಲೆ"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "ಸುರುತ ಪಟ್ಯೊದ ಸೂಚ್ಯಿ/ಅಕೇರಿಟ್ ಸಂಭವಿಸವುನ ಸುರುತ ಪಟ್ಟಯೊದುಲಯಿದ ರಡ್ಡನೆ ಪಟ್ಯೊನು ಪಿರಕೊರು. %1 ಪಟ್ಯೊ ತಿಕಂದಿತ್ತ್‌ಂಡ ಪಿರಕೊರು."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 ಕಾಲಿ"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "ಕೊರ್‌ನ ಪಟ್ಯೊ ಕಾಲಿಂದ್ ಸತ್ಯೊ ಆಂಡ ಪಿರಕೊರು"; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "ಪಟ್ಯೊನು ರಚನೆ ಮಲ್ಪು"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "ಒವ್ವೇ ಸಂಖ್ಯೆದ ಪಟ್ಯೊದ ತುಂಡುಲೆನ್ ಒಟ್ಟೂಗೆ ಸೇರಯರ ರಚಿಸಲೆ"; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "೧% ಉದ್ದೊ"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "ಕೊರ್‌ನ ಪಟ್ಯೊದ ಅಕ್ಷರೊಲೆನ(ಅಂತರೊಲು ಸೇರ್‌ನಂಚ) ಸಂಖ್ಯೆನ್ ಪಿರಕೊರು."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "%1 ಮುದ್ರಿತ"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "ನಿರ್ದಿಷ್ಟ ಪಟ್ಯೊ, ಸಂಖ್ಯೆ ಅತ್ತಂಡ ಬೇತೆ ಮೌಲ್ಯೊನು ಮುದ್ರಿಸಲೆ."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "ದಿಂಜ ಬಳಕೆದಾರೆರೆನ್ ಕೇನುಂಡು."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "ಕೆಲವು ಪಟ್ಯೊದ ಬಳಕೆದಾರೆರೆನ್ ಕೇನುಂಡು."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "ಸಂಖ್ಯೆದೊಟ್ಟುಗೆ ಸಂದೇಸೊನು ಕೇನುಂಡು"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "ಪಟ್ಯೊದೊಟ್ಟುಗೆ ಸಂದೇಸೊನು ಕೇನುಂಡು."; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/ಸ್ಟ್ರಿಂಗ್_(ಕಂಪ್ಯೂಟರ್_ಸೈನ್ಸ್)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "ಒಂಜಿ ಅಕ್ಷರೊ, ಪದೊ ಅತ್ತಂಡ ಪಾಟೊದ ಒಂಜಿ ಸಾಲ್"; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "ರಡ್ಡ್ ಬರಿತ ಜಾಗೆನ್ಲ ಕತ್ತೆರಿಪುಲೆ."; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "ಎಡತ ಬರಿತ ಜಾಗೆನ್ ಕತ್ತೆರಿಪುಲೆ."; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "ಬಲತ ಬರಿತ ಜಾಗೆನ್ ಕತ್ತೆರಿಪುಲೆ."; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "ಒಂಜಿ ಅತ್ತಂಡ ರಡ್ಡ್ ಕೊಡಿಡ್ದ್ ದೆತ್ತ್‌ನ ಕಅಲಿ ಪಟ್ಯೊದ ಪ್ರತಿನ್ ಪಿರಕೊರು."; -Blockly.Msg.TODAY = "ಇನಿ"; -Blockly.Msg.UNDO = "ದುಂಬುದಲೆಕೊ"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "ವಸ್ತು"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "'%1' ರಚನೆ ಮಲ್ಪುಲೆ"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "ಈ ವ್ಯತ್ಯಯೊದ ಮೌಲ್ಯೊನು ಪಿರಕೊರು."; -Blockly.Msg.VARIABLES_SET = "%1 ಡ್ದು %2 ಮಲ್ಪುಲೆ"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "'%1' ರಚನೆ ಮಲ್ಪುಲೆ"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "ಉಲಯಿ ಬರ್ಪುನವು ಸಮಪಾಲ್ ಇಪ್ಪುನಂಚ ವ್ಯತ್ಯಾಸೊ ಮಾಲ್ಪು"; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/th.js b/backend/_pv_1_3_5/static/blockly/msg/js/th.js deleted file mode 100755 index 339b1cd26..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/th.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.th'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "ใส่คำอธิบาย"; -Blockly.Msg.CHANGE_VALUE_TITLE = "เปลี่ยนค่า:"; -Blockly.Msg.CLEAN_UP = "จัดเรียงบล็อกให้เป็นแถว"; -Blockly.Msg.COLLAPSE_ALL = "ย่อบล็อก"; -Blockly.Msg.COLLAPSE_BLOCK = "ย่อบล็อก"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "สีที่ 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "สีที่ 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "อัตราส่วน"; -Blockly.Msg.COLOUR_BLEND_TITLE = "ผสม"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "ผสมสองสีเข้าด้วยกันด้วยอัตราส่วน (0.0 - 1.0)"; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://th.wikipedia.org/wiki/สี"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "เลือกสีจากจานสี"; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "สุ่มสี"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "เลือกสีแบบสุ่ม"; -Blockly.Msg.COLOUR_RGB_BLUE = "ค่าสีน้ำเงิน"; -Blockly.Msg.COLOUR_RGB_GREEN = "ค่าสีเขียว"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "ค่าสีแดง"; -Blockly.Msg.COLOUR_RGB_TITLE = "สีที่ประกอบด้วย"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "สร้างสีด้วยการกำหนดค่าสีแดง เขียว และน้ำเงิน ค่าทั้งหมดต้องอยู่ระหว่าง 0 ถึง 100"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "ออกจากการวนซ้ำ"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "เริ่มการวนซ้ำรอบต่อไป"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "ออกจากการวนซ้ำที่อยู่"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "ข้ามคำสั่งที่เหลืออยู่ และเริ่มต้นวนซ้ำรอบต่อไป"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "คำเตือน: บล็อกนี้ใช้งานได้ภายในการวนซ้ำเท่านั้น"; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "จากทุกรายการ %1 ในรายชื่อ %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "จากทุกรายการในรายชื่อ ตั้งค่าตัวแปร \"%1\" เป็นรายการ และทำตามคำสั่งที่กำหนดไว้"; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "นับด้วย %1 จาก %2 จนถึง %3 เปลี่ยนค่าทีละ %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "ตัวแปร '%1' จะเริ่มจากจำนวนเริ่มต้น ไปจนถึงจำนวนสุดท้าย ตามระยะที่กำหนด และ ทำบล็อกที่กำหนดไว้"; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "กำหนดเงื่อนไขของบล็อก \"ถ้า\""; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "เพิ่มสิ่งสุดท้าย ที่จะตรวจจับความเป็นไปได้ทั้งหมดของบล็อก \"ถ้า\""; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "เพิ่ม ลบ หรือจัดเรียงบล็อก \"ถ้า\" นี้ใหม่"; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "นอกเหนือจากนี้"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "นอกเหนือจากนี้ ถ้า"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "ถ้า"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "ว่าเงื่อนไขเป็นจริง ก็จะ \"ทำ\" ตามที่กำหนด"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "ถ้าเงื่อนไขเป็นจริง ก็จะ \"ทำ\" ตามที่กำหนด แต่ถ้าเงื่อนไขเป็นเท็จก็จะทำ \"นอกเหนือจากนี้\""; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "ถ้าเงื่อนไขแรกเป็นจริง ก็จะทำตามคำสั่งในบล็อกแรก แต่ถ้าไม่ก็จะไปตรวจเงื่อนไขที่สอง ถ้าเงื่อนไขที่สองเป็นจริง ก็จะทำตามเงื่อนไขในบล็อกที่สองนี้"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "ถ้าเงื่อนไขแรกเป็นจริง ก็จะทำคำสั่งในบล็อกแรก จากนั้นจะข้ามคำสั่งในบล็อกที่เหลือ แต่ถ้าเงื่อนไขแรกเป็นเท็จ ก็จะทำการตรวจเงื่อนไขที่สอง ถ้าเงื่อนไขที่สองเป็นจริง ก็จะทำตามคำสั่งในบล็อกที่สอง จากนั้นจะข้ามคำสั่งในบล็อกที่เหลือ แต่ถ้าทั้งเงื่อนไขแรกและเงื่อนไขที่สองเป็นเท็จทั้งหมด ก็จะมาทำบล็อกที่สาม"; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "ทำ:"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "ทำซ้ำ %1 ครั้ง"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "ทำซ้ำบางคำสั่งหลายครั้ง"; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "ทำซ้ำจนกระทั่ง"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "ทำซ้ำขณะที่"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "ขณะที่ค่าเป็นเท็จ ก็จะทำบางคำสั่ง"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "ขณะที่ค่าเป็นจริง ก็จะทำบางคำสั่ง"; -Blockly.Msg.DELETE_ALL_BLOCKS = "ลบ %1 บล็อกทั้งหมด?"; -Blockly.Msg.DELETE_BLOCK = "ลบบล็อก"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "ลบ %1 บล็อก"; -Blockly.Msg.DISABLE_BLOCK = "ปิดใช้งานบล็อก"; -Blockly.Msg.DUPLICATE_BLOCK = "ทำสำเนา"; -Blockly.Msg.ENABLE_BLOCK = "เปิดใช้งานบล็อก"; -Blockly.Msg.EXPAND_ALL = "ขยายบล็อก"; -Blockly.Msg.EXPAND_BLOCK = "ขยายบล็อก"; -Blockly.Msg.EXTERNAL_INPUTS = "อินพุตภายนอก"; -Blockly.Msg.HELP = "ช่วยเหลือ"; -Blockly.Msg.INLINE_INPUTS = "อินพุตในบรรทัด"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "สร้างรายการเปล่า"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "สร้างรายการเปล่า (ความยาวเป็น 0) ยังไม่มีข้อมูลใดๆ อยู่"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "รายการ"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "เพิ่ม ลบ หรือจัดเรียงบล็อกรายการนี้ใหม่"; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "สร้างข้อความด้วย"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "เพิ่มไอเท็มเข้าไปในรายการ"; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "สร้างรายการพร้อมด้วยไอเท็ม"; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "แรกสุด"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# จากท้าย"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "เรียกดู"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "เรียกดูและเอาออก"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "ท้ายสุด"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "สุ่ม"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "เอาออก"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "คืนค่าไอเท็มอันแรกในรายการ"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "คืนค่าเป็นไอเท็มตามตำแหน่งที่ระบุ"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "คืนค่าไอเท็มอันสุดท้ายในรายการ"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "คืนค่าไอเท็มแบบสุ่มจากรายการ"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "เอาออก และคืนค่าไอเท็มอันแรกในรายการ"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "เอาออก และคืนค่าไอเท็มในตำแหน่งที่ระบุจากรายการ"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "เอาออก และคืนค่าไอเท็มอันสุดท้ายในรายการ"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "เอาออก และคืนค่าไอเท็มแบบสุ่มจากรายการ"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "เอาไอเท็มแรกสุดในรายการออก"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "คืนค่าเป็นไอเท็มตามตำแหน่งที่ระบุ"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "เอาไอเท็มอันท้ายสุดในรายการออก"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "เอาไอเท็มแบบสุ่มจากรายการออก"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "ถึง # จากท้ายสุด"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "จนถึง #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "ถึง ท้ายสุด"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "ดึงรายการย่อยทั้งแต่แรกสุด"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "ดึงรายการย่อยจาก # จากท้ายสุด"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "ดึงรายการย่อยจาก #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "สร้างสำเนารายการในช่วงที่กำหนด"; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 คือไอเท็มอันท้ายสุด"; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 คือไอเท็มอันแรกสุด"; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "หาอันแรกที่พบ"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "หาอันสุดท้ายที่พบ"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "คืนค่าตำแหน่งของไอเท็มอันแรก/สุดท้ายที่พบในรายการ คืนค่า %1 ถ้าหาไม่พบ"; -Blockly.Msg.LISTS_INLIST = "ในรายการ"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 ว่างเปล่า"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "คืนค่าเป็นจริง ถ้ารายการยังว่างเปล่า"; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "ความยาวของ %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "ส่งคืนค่าความยาวของรายการ"; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "สร้างรายการที่มีไอเท็ม %1 จำนวน %2"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "สร้างรายการที่ประกอบด้วยค่าตามที่ระบุในจำนวนตามที่ต้องการ"; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "เป็น"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "แทรกที่"; -Blockly.Msg.LISTS_SET_INDEX_SET = "กำหนด"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "แทรกไอเท็มเข้าไปเป็นอันแรกสุดของรายการ"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "แทรกไอเท็มเข้าไปในตำแหน่งที่กำหนด"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "เพิ่มไอเท็มเข้าไปท้ายสุดของรายการ"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "เพิ่มไอเท็มเข้าไปในรายการแบบสุ่ม"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "กำหนดไอเท็มอันแรกในรายการ"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "กำหนดไอเท็มในตำแหน่งที่ระบุในรายการ"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "กำหนดไอเท็มอันสุดท้ายในรายการ"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "กำหนดไอเท็มแบบสุ่มในรายการ"; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "น้อยไปหามาก"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "มากไปหาน้อย"; -Blockly.Msg.LISTS_SORT_TITLE = "เรียงลำดับ %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "เรียงลำดับสำเนาของรายชื่อ"; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "ตัวอักษร"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "ตัวเลข"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "ตัวอักษร"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "สร้างรายการจากข้อความ"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "สร้างข้อความจากรายการ"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "รวมรายการข้อความเป็นข้อความเดียว แบ่งด้วยตัวคั่น"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "แบ่งข้อความเป็นรายการข้อความ แยกแต่ละรายการด้วยตัวคั่น"; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "ด้วยตัวคั่น"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "เท็จ"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "คืนค่าเป็นจริงหรือเท็จ"; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "จริง"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://th.wikipedia.org/wiki/อสมการ"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "คืนค่าเป็น \"จริง\" ถ้าค่าที่ใส่ทั้งสองค่านั้นเท่ากัน"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "คืนค่าเป็น \"จริง\" ถ้าค่าแรกมากกว่าค่าที่สอง"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "คืนค่าเป็น \"จริง\" ถ้าค่าแรกมากกว่าหรือเท่ากับค่าที่สอง"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "คืนค่าเป็น \"จริง\" ถ้าค่าแรกน้อยกว่าค่าที่สอง"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "คืนค่าเป็น \"จริง\" ถ้าค่าแรกน้อยกว่าหรือเท่ากับค่าที่สอง"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "คืนค่าเป็น \"จริง\" ถ้าค่าที่ใส่ทั้งสองค่านั้นไม่เท่ากัน"; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "ไม่ %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "คืนค่าเป็น \"จริง\" ถ้าค่าที่ใส่เป็นเท็จ คืนค่าเป็น \"เท็จ\" ถ้าค่าที่ใส่เป็นจริง"; -Blockly.Msg.LOGIC_NULL = "ไม่กำหนด"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "คืนค่า \"ไม่กำหนด\""; -Blockly.Msg.LOGIC_OPERATION_AND = "และ"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "หรือ"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "คืนค่าเป็น \"จริง\" ถ้าค่าทั้งสองค่าเป็นจริง"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "คืนค่าเป็น \"จริง\" ถ้ามีอย่างน้อยหนึ่งค่าที่เป็นจริง"; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "ทดสอบ"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "ถ้า เป็นเท็จ"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "ถ้า เป็นจริง"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "ตรวจสอบเงื่อนไขใน \"ทดสอบ\" ถ้าเงื่อนไขเป็นจริง จะคืนค่า \"ถ้า เป็นจริง\" ถ้าเงื่อนไขเป็นเท็จ จะคืนค่า \"ถ้า เป็นเท็จ\""; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://th.wikipedia.org/wiki/เลขคณิต"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "คืนค่าผลรวมของตัวเลขทั้งสองจำนวน"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "คืนค่าผลหารของตัวเลขทั้งสองจำนวน"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "คืนค่าผลต่างของตัวเลขทั้งสองจำนวน"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "คืนค่าผลคูณของตัวเลขทั้งสองจำนวน"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "คืนค่าผลการยกกำลัง โดยตัวเลขแรกเป็นฐาน และตัวเลขที่สองเป็นเลขชี้กำลัง"; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "เปลี่ยนค่า %1 เป็น %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "เพิ่มค่าของตัวแปร \"%1\""; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://th.wikipedia.org/wiki/ค่าคงตัวทางคณิตศาสตร์"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "คืนค่าคงตัวทางคณิตศาสตร์ที่พบบ่อยๆ เช่น π (3.141…), e (2.718…), φ (1.618…), รากที่สอง (1.414…), รากที่ ½ (0.707…), ∞ (อนันต์)"; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "จำกัดค่า %1 ต่ำสุด %2 สูงสุด %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "จำกัดค่าของตัวเลขให้อยู่ในช่วงที่กำหนด"; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "หารลงตัว"; -Blockly.Msg.MATH_IS_EVEN = "เป็นจำนวนคู่"; -Blockly.Msg.MATH_IS_NEGATIVE = "เป็นเลขติดลบ"; -Blockly.Msg.MATH_IS_ODD = "เป็นจำนวนคี่"; -Blockly.Msg.MATH_IS_POSITIVE = "เป็นเลขบวก"; -Blockly.Msg.MATH_IS_PRIME = "เป็นจำนวนเฉพาะ"; -Blockly.Msg.MATH_IS_TOOLTIP = "ตรวจว่าตัวเลขเป็นจำนวนคู่ จำนวนคี่ จำนวนเฉพาะ จำนวนเต็ม เลขบวก เลขติดลบ หรือหารด้วยเลขที่กำหนดลงตัวหรือไม่ คืนค่าเป็นจริงหรือเท็จ"; -Blockly.Msg.MATH_IS_WHOLE = "เป็นเลขจำนวนเต็ม"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "เศษของ %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "คืนค่าเศษที่ได้จากการหารของตัวเลขทั้งสองจำนวน"; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://th.wikipedia.org/wiki/จำนวน"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "จำนวน"; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "ค่าเฉลี่ยของรายการ"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "มากที่สุดในรายการ"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "ค่ามัธยฐานของรายการ"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "น้อยที่สุดในรายการ"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "ฐานนิยมของรายการ"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "สุ่มรายการ"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "ส่วนเบี่ยงเบนมาตรฐานของรายการ"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "ผลรวมของรายการ"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "คืนค่าเฉลี่ยของรายการ"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "คืนค่าตัวเลขที่มากที่สุดในรายการ"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "คืนค่ามัธยฐานของรายการ"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "คืนค่าตัวเลขที่น้อยที่สุดในรายการ"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "คืนค่าฐานนิยมของรายการ"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "สุ่มคืนค่าสิ่งที่อยู่ในรายการ"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "คืนค่าส่วนเบี่ยงเบนมาตรฐานของรายการ"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "คืนค่าผลรวมของตัวเลขทั้งหมดในรายการ"; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "สุ่มเลขเศษส่วน"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "สุ่มเลขเศษส่วน ตั้งแต่ 0.0 แต่ไม่เกิน 1.0"; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "สุ่มเลขจำนวนเต็มตั้งแต่ %1 จนถึง %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "สุ่มเลขจำนวนเต็มจากช่วงที่กำหนด"; -Blockly.Msg.MATH_ROUND_HELPURL = "https://th.wikipedia.org/wiki/การปัดเศษ"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "ปัดเศษ"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "ปัดเศษลง"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "ปัดเศษขึ้น"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "ปัดเศษของตัวเลขขึ้นหรือลง"; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "ค่าสัมบูรณ์"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "รากที่สอง"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "คืนค่าค่าสัมบูรณ์ของตัวเลข"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "คืนค่า e ยกกำลังด้วยตัวเลข"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "คืนค่าลอการิทึมธรรมชาติของตัวเลข"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "คืนค่าลอการิทึมฐานสิบของตัวเลข"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "คืนค่าติดลบของตัวเลข"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "คืนค่า 10 ยกกำลังด้วยตัวเลข"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "คืนค่ารากที่สองของตัวเลข"; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://th.wikipedia.org/wiki/ฟังก์ชันตรีโกณมิติ"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "คืนค่า arccosine ของตัวเลข"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "คืนค่า arcsine ของตัวเลข"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "คืนค่า arctangent ของตัวเลข"; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "คืนค่า cosine ขององศา (ไม่ใช่เรเดียน)"; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "คืนค่า sine ขององศา (ไม่ใช่เรเดียน)"; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "คืนค่า tangent ขององศา (ไม่ใช่เรเดียน)"; -Blockly.Msg.NEW_VARIABLE = "สร้างตัวแปร..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "ชื่อตัวแปรใหม่:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "ข้อความที่ใช้ได้"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "ด้วย:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_(computer_science)"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "เรียกใช้ฟังก์ชันที่สร้างโดยผู้ใช้ \"%1\""; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_(computer_science)"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "เรียกใช้ฟังก์ชันที่สร้างโดยผู้ใช้ \"%1\" และใช้ผลลัพธ์ของมัน"; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "ด้วย:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "สร้าง \"%1\""; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "อธิบายฟังก์ชันนี้"; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "ทำอะไรบางอย่าง"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "ถึง"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "สร้างฟังก์ชันที่ไม่มีผลลัพธ์"; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "คืนค่า"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "สร้างฟังก์ชันที่มีผลลัพธ์"; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "ระวัง: ฟังก์ชันนี้มีพารามิเตอร์ที่มีชื่อซ้ำกัน"; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "เน้นฟังก์ชันนิยาม"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "ถ้ามีค่าเป็นจริง ให้คืนค่าที่สอง"; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "ระวัง: บล็อกนี้ใช้เฉพาะในการสร้างฟังก์ชันเท่านั้น"; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "ชื่อนำเข้า:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "เพิ่มค่าป้อนเข้าฟังก์ชัน"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "นำเข้า"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "เพิ่ม, ลบ, หรือจัดเรียง ข้อมูลที่ป้อนเข้าฟังก์ชันนี้"; -Blockly.Msg.REDO = "ทำซ้ำ"; -Blockly.Msg.REMOVE_COMMENT = "เอาคำอธิบายออก"; -Blockly.Msg.RENAME_VARIABLE = "เปลี่ยนชื่อตัวแปร..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "เปลี่ยนชื่อตัวแปร '%1' ทั้งหมดเป็น:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "ต่อด้วยข้อความ"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "นำเอา"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "ต่อข้อความให้ตัวแปร \"%1\""; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "เปลี่ยนเป็น ตัวพิมพ์เล็ก"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "เปลี่ยนเป็น ตัวอักษรแรกเป็นตัวพิมพ์ใหญ่"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "เปลี่ยนเป็น ตัวพิมพ์ใหญ่"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "คืนค่าสำเนาของข้อความในกรณีต่างๆ"; -Blockly.Msg.TEXT_CHARAT_FIRST = "ดึง ตัวอักษรตัวแรก"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "ดึง ตัวอักษรตัวที่ # จากท้าย"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "ดึง ตัวอักษรตัวที่"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "ในข้อความ"; -Blockly.Msg.TEXT_CHARAT_LAST = "ดึง ตัวอักษรตัวสุดท้าย"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "ถึงตัวอักษรแบบสุ่ม"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "คืนค่าตัวอักษรจากตำแหน่งที่ระบุ"; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "เพิ่มรายการเข้าไปในข้อความ"; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "รวม"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "เพิ่ม ลบ หรือจัดเรียงบล็อกข้อความนี้ใหม่"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "จนถึง ตัวอักษรที่ # จากท้าย"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "จนถึง ตัวอักษรที่"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "จนถึง ตัวอักษรสุดท้าย"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "ในข้อความ"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "แยกข้อความย่อยตั้งแต่ ตัวอักษรแรก"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "แยกข้อความย่อยตั้งแต่ ตัวอักษรที่ # จากท้าย"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "แยกข้อความย่อยตั้งแต่ ตัวอักษรที่"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "คืนค่าบางส่วนของข้อความ"; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "ในข้อความ"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "หาข้อความแรกที่พบ"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "หาข้อความสุดท้ายที่พบ"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "คืนค่าตำแหน่งที่พบข้อความแรกอยู่ในข้อความที่สอง คืนค่า %1 ถ้าหาไม่พบ"; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 ว่าง"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "คืนค่าจริง ถ้าข้อความยังว่าง"; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "สร้างข้อความด้วย"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "สร้างข้อความด้วยการรวมจำนวนของรายการเข้าด้วยกัน"; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "ความยาวของ %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "คืนค่าความยาวของข้อความ (รวมช่องว่าง)"; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "พิมพ์ %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "พิมพ์ข้อความ ตัวเลข หรือค่าอื่นๆ"; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "แสดงหน้าต่างให้ผู้ใช้ใส่ตัวเลข"; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "แสดงหน้าต่างให้ผู้ใช้ใส่ข้อความ"; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "แสดงหน้าต่างตัวเลข"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "แสดงหน้าต่างข้อความ"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://th.wikipedia.org/wiki/สายอักขระ"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "ตัวหนังสือ คำ หรือข้อความ"; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "ลบช่องว่างทั้งสองข้างของ"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "ลบช่องว่างด้านหน้าของ"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "ลบช่องว่างข้างท้ายของ"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "คืนค่าสำเนาของข้อความที่ลบเอาช่องว่างหน้าและหลังข้อความออกแล้ว"; -Blockly.Msg.TODAY = "วันนี้"; -Blockly.Msg.UNDO = "ย้อนกลับ"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "รายการ"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "สร้าง \"กำหนด %1\""; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "คืนค่าของตัวแปรนี้"; -Blockly.Msg.VARIABLES_SET = "กำหนด %1 จนถึง %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "สร้าง \"get %1\""; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "กำหนดให้ตัวแปรนี้เท่ากับการป้อนข้อมูล"; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/tl.js b/backend/_pv_1_3_5/static/blockly/msg/js/tl.js deleted file mode 100755 index 0151c9264..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/tl.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.tl'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Dagdag komento"; -Blockly.Msg.CHANGE_VALUE_TITLE = "pagbago ng value:"; -Blockly.Msg.CLEAN_UP = "Clean up Blocks"; // untranslated -Blockly.Msg.COLLAPSE_ALL = "bloke"; -Blockly.Msg.COLLAPSE_BLOCK = "bloke"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "kulay 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "kulay 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "proporsyon"; -Blockly.Msg.COLOUR_BLEND_TITLE = "halo"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Paghalo ng dalawang kulay kasama ng ibinigay na proporsyon (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "http://en.wikipedia.org/wiki/Color"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "pagpili ng kulay sa paleta."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "iba ibang kulay"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "pagpili ng iba't ibang kulay."; -Blockly.Msg.COLOUR_RGB_BLUE = "asul"; -Blockly.Msg.COLOUR_RGB_GREEN = "berde"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "pula"; -Blockly.Msg.COLOUR_RGB_TITLE = "kulayan ng"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "gumawa ng kulay ng may espisipikong dami ng kulay pula, berde, at asul. lahat ng halaga ay dapat sa pagitan ng 0 at 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "putulin ang paulit ulit"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "Magpatuloy sa susunod na pag-ulit ng loop"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Hatiin ang nilalaman ng loop."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Laktawan ang natitirang bahagi ng loop, at magpatuloy sa susunod na pag-ulit."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Babala: Ang block ito ay maaari lamang magamit sa loob ng loop."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "sa bawat bagay %1 sa listahan %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Para sa bawat item sa isang list, i-set ang variable ng '%1' sa mga item, at pagkatapos ay gumawa ng ilang mga statements."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "bilangin %1 mula %2 hanggang %3 ng %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Magkaroon ng mga variable na \"%1\" na tanggalin ng mga halaga mula sa simulang numero hanggang sa dulong numero, at bilangin sa pamamagitan ng tinukoy na agwat, at gawin ang mga tinukoy na mga blocks."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Mag dagdag ng condition sa if block."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Mag Add ng final, kunin lahat ng condition sa if block."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Mag Add, remove o kaya mag reorder ng sections para maayos ang if block."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "else"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "else if"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "kung"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "kung ang value ay true, gagawin ang do statements."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Kung ang value ay true, gagawin ang unang block ng do statements. Kung hindi, gagawin ang pangalawang block ng statement."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Kung ang unang value ay true, gagawin ang first block ng statement. Kung hindi, kung ang second value ay true, gagawin ang second block ng statement."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Kung ang first value ay true, gagawin ang first block ng statement. Kung hindi true ang second value, gagawin ang second block ng statement. Kung wala sa mga values ay true, gagawin ang last block ng statements."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "http://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "gawin"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "ulitin %1 beses"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "gumawa ng ilang pangungusap ng ilang ulit."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "ulitin hanggang"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "ulitin habang"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Habang ang value ay false, gagawin ang ibang statements."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Habang ang value ay true, gagawin ang ibang statements."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Delete all %1 blocks?"; // untranslated -Blockly.Msg.DELETE_BLOCK = "burahin ang bloke"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "burahin %1 ng bloke"; -Blockly.Msg.DISABLE_BLOCK = "Ipangwalang bisa ang Block"; -Blockly.Msg.DUPLICATE_BLOCK = "Kaparehas"; -Blockly.Msg.ENABLE_BLOCK = "Bigyan ng bisa ang Block"; -Blockly.Msg.EXPAND_ALL = "Palawakin ang Blocks"; -Blockly.Msg.EXPAND_BLOCK = "Palawakin ang Block"; -Blockly.Msg.EXTERNAL_INPUTS = "Panlabas na Inputs"; -Blockly.Msg.HELP = "Tulong"; -Blockly.Msg.INLINE_INPUTS = "Inline na Inputs"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "Gumawa ng walang laman na list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Ibabalik ang list, na may haba na 0, nag lalaman ng walang data records"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "list"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Magdagdag, mag tanggal or mag ayos ng sections para muling maayos ang listahan ng block."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "gumawa ng list kasama"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Mag dagdag ng item sa list."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Gumawa ng list na may kahit anong number ng items."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "Una"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# mula katapusan"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "kunin"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "kunin at tanggalin"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "huli"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "nang hindi pinipili"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "tanggalin"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Ibalik ang unang item sa list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Ibalik ang item sa itinakdang posisyon sa list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Ibalik ang huling item sa list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Nag babalik ng hindi pinipiling item sa list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Nag tatanggal at nag babalik ng mga unang item sa list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Nag tatanggal at nag babalik ng mga items sa tinukoy na posisyon sa list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Nag tatanggal at nag babalik ng huling item sa list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Nag tatanggal at nag babalik ng mga hindi pinipiling item sa list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Nag tatanggal ng unang item sa list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Nag tatanggal ng item sa tinukoy na posisyon sa list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Nag tatanggal ng huling item sa list."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Nag tatanggal ng item mula sa walang pinipiling list."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "mula # hanggang huli"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "mula #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "hanggang huli"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "pag kuha ng sub-list mula sa una"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "pag kuha ng sub-list mula sa # mula huli"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "pag kuha ng sub-list mula #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Gumagawa ng kopya ng tinukoy na bahagi ng list."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 ay ang huling item."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 ay ang unang item."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "Hanapin ang unang pangyayari ng item"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "hanapin ang huling pangyayari ng item"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Pagbalik ng index ng una/huli pangyayari ng item sa list. Pagbalik ng %1 kung ang item ay hindi makita."; -Blockly.Msg.LISTS_INLIST = "sa list"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 ay walang laman"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Nagbabalik ng true kung ang list ay walang laman."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "haba ng %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Pag balik ng haba ng list."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "pag gawa ng list kasama ng item %1 inuulit %2 beses"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Pag gawa ng list na binubuo ng binigay na value at inulit na tinuloy na bilang ng beses."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "gaya ng"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "isingit sa"; -Blockly.Msg.LISTS_SET_INDEX_SET = "set"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Nag singit ng item sa simula ng list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Nag singit ng item sa tinukoy na posistion sa list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Idagdag ang item sa huli ng isang list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Isingit ang item ng walang pinipili sa isang list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Pag set ng unang item sa isang list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Pag set ng item sa tinukoy na position sa isang list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Pag set sa huling item sa isang list."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Pag set ng walang pinipiling item sa isang list."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "make list from text"; // untranslated -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "make text from list"; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "mali"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Nag babalik ng true or false."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "tama"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "http://en.wikipedia.org/wiki/Inequality_(mathematics)"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Nag babalik ng true kung ang pinasok ay parehong magkatumbas."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Nagbabalik ng true kung ang unang pinasok ay mas malaki kaysa pangalawang pinasok."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Nag babalik ng true kung ang unang pinasok ay mas malaki or katumbas ng pangalawang pinasok."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Nag babalik ng true kung ang unang pinasok ay maliit kaysa sa pangalawang pinasok."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Nag babalik ng true kung ang unang pinasok ay maliit sa o katumbas sa pangalawang pinasok."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Return true if both inputs are not equal to each other."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "not %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Returns true if the input is false. Returns false if the input is true."; -Blockly.Msg.LOGIC_NULL = "blangko"; -Blockly.Msg.LOGIC_NULL_HELPURL = "http://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Returns null."; -Blockly.Msg.LOGIC_OPERATION_AND = "at"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "o"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Return true if both inputs are true."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Return true if at least one of the inputs is true."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "http://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "kung mali"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "kung tama"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "http://en.wikipedia.org/wiki/Arithmetic"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Return the sum of the two numbers."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Return the quotient of the two numbers."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Return the difference of the two numbers."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Return the product of the two numbers."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Return the first number raised to the power of the second number."; -Blockly.Msg.MATH_CHANGE_HELPURL = "http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "baguhin %1 by %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Add a number to variable '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "http://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "constrain %1 low %2 high %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Constrain a number to be between the specified limits (inclusive)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "is divisible by"; -Blockly.Msg.MATH_IS_EVEN = "is even"; -Blockly.Msg.MATH_IS_NEGATIVE = "ay negatibo"; -Blockly.Msg.MATH_IS_ODD = "is odd"; -Blockly.Msg.MATH_IS_POSITIVE = "ay positibo"; -Blockly.Msg.MATH_IS_PRIME = "is prime"; -Blockly.Msg.MATH_IS_TOOLTIP = "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false."; -Blockly.Msg.MATH_IS_WHOLE = "is whole"; -Blockly.Msg.MATH_MODULO_HELPURL = "http://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "remainder of %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Return the remainder from dividing the two numbers."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; -Blockly.Msg.MATH_NUMBER_HELPURL = "http://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "A number."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "average of list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "max of list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "median of list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "min of list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "modes of list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "random item of list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "standard deviation of list"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "sum of list"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Return the average (arithmetic mean) of the numeric values in the list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Return the largest number in the list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Return the median number in the list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Return the smallest number in the list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Return a list of the most common item(s) in the list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Return a random element from the list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Return the standard deviation of the list."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Return the sum of all the numbers in the list."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "http://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "random fraction"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "http://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "random integer from %1 to %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Return a random integer between the two specified limits, inclusive."; -Blockly.Msg.MATH_ROUND_HELPURL = "http://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "round"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "round down"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "round up"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Round a number up or down."; -Blockly.Msg.MATH_SINGLE_HELPURL = "http://en.wikipedia.org/wiki/Square_root"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "absolute"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "square root"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Return the absolute value of a number."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Return e to the power of a number."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Return the natural logarithm of a number."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Return the base 10 logarithm of a number."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Return the negation of a number."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Return 10 to the power of a number."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Return the square root of a number."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "acos"; -Blockly.Msg.MATH_TRIG_ASIN = "asin"; -Blockly.Msg.MATH_TRIG_ATAN = "atan"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "http://en.wikipedia.org/wiki/Trigonometric_functions"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tan"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Return the arccosine of a number."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Return the arcsine of a number."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Return the arctangent of a number."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Return the cosine of a degree (not radian)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Return the sine of a degree (not radian)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Return the tangent of a degree (not radian)."; -Blockly.Msg.NEW_VARIABLE = "New variable..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "New variable name:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "allow statements"; // untranslated -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "with:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Run the user-defined function '%1'."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Run the user-defined function '%1' and use its output."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "with:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Create '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "do something"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "to"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Creates a function with no output."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "return"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Creates a function with an output."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Warning: This function has duplicate parameters."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Highlight function definition"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "If a value is true, then return a second value."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Warning: This block may be used only within a function definition."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "input name:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Add an input to the function."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "inputs"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Add, remove, or reorder inputs to this function."; // untranslated -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "Remove Comment"; -Blockly.Msg.RENAME_VARIABLE = "Rename variable..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Rename all '%1' variables to:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "append text"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "to"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Append some text to variable '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "to lower case"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "to Title Case"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "to UPPER CASE"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; -Blockly.Msg.TEXT_CHARAT_FIRST = "get first letter"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "get letter # from end"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "get letter #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "in text"; -Blockly.Msg.TEXT_CHARAT_LAST = "get last letter"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "get random letter"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; // untranslated -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Returns the letter at the specified position."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Add an item to the text."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "join"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Add, remove, or reorder sections to reconfigure this text block."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "to letter # from end"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "to letter #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "to last letter"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "in text"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "get substring from first letter"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "get substring from letter # from end"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "get substring from letter #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returns a specified portion of the text."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "in text"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "find first occurrence of text"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "find last occurrence of text"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returns the index of the first/last occurrence of first text in the second text. Returns %1 if text is not found."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 is empty"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returns true if the provided text is empty."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "create text with"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Create a piece of text by joining together any number of items."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "length of %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Returns the number of letters (including spaces) in the provided text."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "print %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Print the specified text, number or other value."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Prompt for user for a number."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Prompt for user for some text."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "prompt for number with message"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "prompt for text with message"; -Blockly.Msg.TEXT_TEXT_HELPURL = "http://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "A letter, word, or line of text."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "trim spaces from both sides"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "trim spaces from left side"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "trim spaces from right side"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Return a copy of the text with spaces removed from one or both ends."; -Blockly.Msg.TODAY = "Today"; // untranslated -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "item"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Create 'set %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returns the value of this variable."; -Blockly.Msg.VARIABLES_SET = "set %1 to %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Create 'get %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Sets this variable to be equal to the input."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/tlh.js b/backend/_pv_1_3_5/static/blockly/msg/js/tlh.js deleted file mode 100755 index fee40f3e1..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/tlh.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.tlh'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "QInHom chel"; -Blockly.Msg.CHANGE_VALUE_TITLE = "choH:"; -Blockly.Msg.CLEAN_UP = "ngoghmeyvaD tlhegh rurmoH"; -Blockly.Msg.COLLAPSE_ALL = "ngoghmey DejmoH"; -Blockly.Msg.COLLAPSE_BLOCK = "ngogh DejmoH"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "rItlh wa'"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "rItlh cha'"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "'ar"; -Blockly.Msg.COLOUR_BLEND_TITLE = "DuD"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Blends two colours together with a given ratio (0.0 - 1.0)."; // untranslated -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://en.wikipedia.org/wiki/Color"; // untranslated -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Choose a colour from the palette."; // untranslated -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "rItlh vISaHbe'"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Choose a colour at random."; // untranslated -Blockly.Msg.COLOUR_RGB_BLUE = "chal rItlh"; -Blockly.Msg.COLOUR_RGB_GREEN = "tI rItlh"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "'Iw rItlh"; -Blockly.Msg.COLOUR_RGB_TITLE = "rItlh wIv"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Create a colour with the specified amount of red, green, and blue. All values must be between 0 and 100."; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "gho Haw'"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "gho taHqa'"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Break out of the containing loop."; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Skip the rest of this loop, and continue with the next iteration."; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "yIqIm! ghoDaq neH ngoghvam lo'laH vay'."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "ngIq Doch %1 ngaSbogh tetlh %2 nuDDI'"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "For each item in a list, set the variable '%1' to the item, and then do some statements."; // untranslated -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "togh %1 mung %2 ghoch %3 Do %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Have the variable '%1' take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks."; // untranslated -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Add a condition to the if block."; // untranslated -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Add a final, catch-all condition to the if block."; // untranslated -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Add, remove, or reorder sections to reconfigure this if block."; // untranslated -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "pagh"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "pagh teHchugh"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "teHchugh"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "If a value is true, then do some statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "If a value is true, then do the first block of statements. Otherwise, do the second block of statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements."; // untranslated -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements."; // untranslated -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; // untranslated -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "ruch"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "%1-logh qaSmoH"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Do some statements several times."; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "teHpa' qaSmoH"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "teHtaHvIS qaSmoH"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "While a value is false, then do some statements."; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "While a value is true, then do some statements."; // untranslated -Blockly.Msg.DELETE_ALL_BLOCKS = "Hoch %1 ngoghmey Qaw'?"; -Blockly.Msg.DELETE_BLOCK = "ngogh Qaw'"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "%1 ngoghmey Qaw'"; -Blockly.Msg.DISABLE_BLOCK = "ngogh Qotlh"; -Blockly.Msg.DUPLICATE_BLOCK = "velqa' chenmoH"; -Blockly.Msg.ENABLE_BLOCK = "ngogh QotlhHa'"; -Blockly.Msg.EXPAND_ALL = "ngoghmey DejHa'moH"; -Blockly.Msg.EXPAND_BLOCK = "ngogh DejHa'moH"; -Blockly.Msg.EXTERNAL_INPUTS = "Hur rar"; -Blockly.Msg.HELP = "QaH"; -Blockly.Msg.INLINE_INPUTS = "qoD rar"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "tetlh chIm"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Returns a list, of length 0, containing no data records"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "tetlh"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Add, remove, or reorder sections to reconfigure this list block."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "tetlh ghom"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Add an item to the list."; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Create a list with any number of items."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_FIRST = "wa'DIch"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# Qav"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "Suq"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "Suq vaj pej"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "Qav"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "Sahbe'"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "pej"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Removes and returns the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Removes and returns the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Removes and returns the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Removes and returns a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Removes the first item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Removes the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Removes the last item in a list."; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Removes a random item in a list."; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "mojaQ # Qav"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "mojaQ #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "mojaQ Qav"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "tetlhHom moHaq wa'DIch"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "tetlhHom moHaq # Qav"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "tetlhHom moHaq #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = "Suq"; -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Creates a copy of the specified portion of a list."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 is the last item."; // untranslated -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 is the first item."; // untranslated -Blockly.Msg.LISTS_INDEX_OF_FIRST = "Doch sam wa'DIch"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "Doch sam Qav"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Returns the index of the first/last occurrence of the item in the list. Returns %1 if item is not found."; // untranslated -Blockly.Msg.LISTS_INLIST = "tetlhDaq"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 chIm'a'"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Returns true if the list is empty."; // untranslated -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "chuq %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Returns the length of a list."; // untranslated -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "tetlh ghom %2 Dochmey %1 pus"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Creates a list consisting of the given value repeated the specified number of times."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "Dos"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "lIH"; -Blockly.Msg.LISTS_SET_INDEX_SET = "choH"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Inserts the item at the start of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Inserts the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Append the item to the end of a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Inserts the item randomly in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Sets the first item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Sets the item at the specified position in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Sets the last item in a list."; // untranslated -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Sets a random item in a list."; // untranslated -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "tetlh ghermeH ghItlh wav"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "ghItlh chenmoHmeH tetlh gherHa'"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "rarwI'Hom lo'"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "teHbe'"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Returns either true or false."; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "teH"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://en.wikipedia.org/wiki/Inequality_(mathematics)"; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Return true if both inputs equal each other."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Return true if the first input is greater than the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Return true if the first input is greater than or equal to the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Return true if the first input is smaller than the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Return true if the first input is smaller than or equal to the second input."; // untranslated -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Return true if both inputs are not equal to each other."; // untranslated -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "yoymoH %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Returns true if the input is false. Returns false if the input is true."; // untranslated -Blockly.Msg.LOGIC_NULL = "paghna'"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Returns null."; // untranslated -Blockly.Msg.LOGIC_OPERATION_AND = "'ej"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "qoj"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Return true if both inputs are true."; // untranslated -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Return true if at least one of the inputs is true."; // untranslated -Blockly.Msg.LOGIC_TERNARY_CONDITION = "chov"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "teHbe'chugh"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "teHchugh"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value."; // untranslated -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://en.wikipedia.org/wiki/Arithmetic"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Return the sum of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Return the quotient of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Return the difference of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Return the product of the two numbers."; // untranslated -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Return the first number raised to the power of the second number."; // untranslated -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; // untranslated -Blockly.Msg.MATH_CHANGE_TITLE = "choH %1 chel %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Add a number to variable '%1'."; // untranslated -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; // untranslated -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity)."; // untranslated -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "jon %1 bIng %2 Dung %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Constrain a number to be between the specified limits (inclusive)."; // untranslated -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "wav'a'"; -Blockly.Msg.MATH_IS_EVEN = "lang'a' mI'"; -Blockly.Msg.MATH_IS_NEGATIVE = "bIng pagh"; -Blockly.Msg.MATH_IS_ODD = "ror'a' mI'"; -Blockly.Msg.MATH_IS_POSITIVE = "Dung pagh"; -Blockly.Msg.MATH_IS_PRIME = "potlh'a' mI'"; -Blockly.Msg.MATH_IS_TOOLTIP = "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false."; // untranslated -Blockly.Msg.MATH_IS_WHOLE = "ngoHlaHbe''a'"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; // untranslated -Blockly.Msg.MATH_MODULO_TITLE = "ratlwI' SIm %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Return the remainder from dividing the two numbers."; // untranslated -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; // untranslated -Blockly.Msg.MATH_NUMBER_TOOLTIP = "A number."; // untranslated -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "beQwI' SIm tetlh"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "tInwI''a' SIm tetlh"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "beQwI'botlh SIm tetlh"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "machwI''a' SIm tetlh"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "beQwI' motlh SIm tetlh"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "SaHbe' SIm tetlh"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "motlhbe'wI' SIm tetlh"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "chelwI' SIm tetlh"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Return the average (arithmetic mean) of the numeric values in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Return the largest number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Return the median number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Return the smallest number in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Return a list of the most common item(s) in the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Return a random element from the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Return the standard deviation of the list."; // untranslated -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Return the sum of all the numbers in the list."; // untranslated -Blockly.Msg.MATH_POWER_SYMBOL = "^"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "mI'HomSaHbe'"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive)."; // untranslated -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; // untranslated -Blockly.Msg.MATH_RANDOM_INT_TITLE = "ngoH mI'SaHbe' bIng %1 Dung %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Return a random integer between the two specified limits, inclusive."; // untranslated -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; // untranslated -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "ngoH"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "bIng ngoH"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "Dung ngoH"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Round a number up or down."; // untranslated -Blockly.Msg.MATH_SINGLE_HELPURL = "https://en.wikipedia.org/wiki/Square_root"; // untranslated -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "Dung pagh choH"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "cha'DIch wav"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Return the absolute value of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Return e to the power of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Return the natural logarithm of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Return the base 10 logarithm of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Return the negation of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Return 10 to the power of a number."; // untranslated -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Return the square root of a number."; // untranslated -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; -Blockly.Msg.MATH_TRIG_ACOS = "acos"; -Blockly.Msg.MATH_TRIG_ASIN = "asin"; -Blockly.Msg.MATH_TRIG_ATAN = "atan"; -Blockly.Msg.MATH_TRIG_COS = "cos"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://en.wikipedia.org/wiki/Trigonometric_functions"; // untranslated -Blockly.Msg.MATH_TRIG_SIN = "sin"; -Blockly.Msg.MATH_TRIG_TAN = "tan"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Return the arccosine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Return the arcsine of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Return the arctangent of a number."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Return the cosine of a degree (not radian)."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Return the sine of a degree (not radian)."; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Return the tangent of a degree (not radian)."; // untranslated -Blockly.Msg.NEW_VARIABLE = "lIw chu'..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "lIw chu' pong:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "mu'tlhegh chaw'"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "qel:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Run the user-defined function '%1'."; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Run the user-defined function '%1' and use its output."; // untranslated -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "qel:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "chel '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "mIw yIDel..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "mIw"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "ruch"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Creates a function with no output."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "chegh"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Creates a function with an output."; // untranslated -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "ghuHmoHna': qelwI' cha'logh chen."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "mIwna' wew"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "If a value is true, then return a second value."; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "ghoHmoHna': ngoghvam ngaSbe' mIwDaq."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "pong:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Add an input to the function."; // untranslated -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "qelwI'mey"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Add, remove, or reorder inputs to this function."; // untranslated -Blockly.Msg.REDO = "vangqa'"; -Blockly.Msg.REMOVE_COMMENT = "QInHom chelHa'"; -Blockly.Msg.RENAME_VARIABLE = "lIw pong choH..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Hoch \"%1\" lIwmey pongmey choH:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "ghItlh"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "chel"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Append some text to variable '%1'."; // untranslated -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "machchoH"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "DojchoH"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "tInchoH"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Return a copy of the text in a different case."; // untranslated -Blockly.Msg.TEXT_CHARAT_FIRST = "mu'Hom wa'DIch"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "mu'Hom # Qav"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "mu'Hom #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "ghItlhDaq"; -Blockly.Msg.TEXT_CHARAT_LAST = "mu'Hom Qav"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "mu'Hom SaHbe'"; -Blockly.Msg.TEXT_CHARAT_TAIL = "Suq"; -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Returns the letter at the specified position."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Add an item to the text."; // untranslated -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "ghom"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Add, remove, or reorder sections to reconfigure this text block."; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "mojaq mu'Hom # Qav"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "mojaq mu'Hom #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "mojaq mu'Hom Qav"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "ghItlhDaq"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "ghItlhHom moHaq mu'Hom wa'DIch"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "ghItlhHom moHaq mu'Hom # Qav"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "ghItlhHom moHaq mu'Hom #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = "Suq"; -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Returns a specified portion of the text."; // untranslated -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "ghItlhDaq"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "ghItlh wa'DIch Sam"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "ghItlh Qav Sam"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found."; // untranslated -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 chIm'a'"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Returns true if the provided text is empty."; // untranslated -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "ghItlh ghom"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Create a piece of text by joining together any number of items."; // untranslated -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "chuq %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Returns the number of letters (including spaces) in the provided text."; // untranslated -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "maq %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Print the specified text, number or other value."; // untranslated -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Prompt for user for a number."; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Prompt for user for some text."; // untranslated -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "mI' tlhob 'ej maq"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "ghItln tlhob 'ej maq"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; // untranslated -Blockly.Msg.TEXT_TEXT_TOOLTIP = "A letter, word, or line of text."; // untranslated -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "poSnIHlogh pei"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "poSlogh pei"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "nIHlogh pei"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Return a copy of the text with spaces removed from one or both ends."; // untranslated -Blockly.Msg.TODAY = "DaHjaj"; -Blockly.Msg.UNDO = "vangHa'"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "Doch"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "chel 'choH %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Returns the value of this variable."; // untranslated -Blockly.Msg.VARIABLES_SET = "choH %1 %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "chel 'Suq %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Sets this variable to be equal to the input."; // untranslated -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/tr.js b/backend/_pv_1_3_5/static/blockly/msg/js/tr.js deleted file mode 100755 index e613af951..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/tr.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.tr'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Yorum Ekle"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Değeri değiştir:"; -Blockly.Msg.CLEAN_UP = "Blokları temizle"; -Blockly.Msg.COLLAPSE_ALL = "Blokları Daralt"; -Blockly.Msg.COLLAPSE_BLOCK = "Blok'u Daralt"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "renk 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "renk 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "oran"; -Blockly.Msg.COLOUR_BLEND_TITLE = "karıştır"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Verilen bir orana bağlı olarak iki rengi karıştırır. (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://tr.wikipedia.org/wiki/Renk"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Paletten bir renk seçin."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "rastgele renk"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Rastgele bir renk seçin."; -Blockly.Msg.COLOUR_RGB_BLUE = "mavi"; -Blockly.Msg.COLOUR_RGB_GREEN = "yeşil"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "kırmızı"; -Blockly.Msg.COLOUR_RGB_TITLE = "renk değerleri"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Kırmızı, yeşil ve mavinin belirtilen miktarıyla bir renk oluşturun. Tüm değerler 0 ile 100 arasında olmalıdır."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "döngüden çık"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "döngünün sonraki adımından devam et"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "İçeren döngüden çık."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Bu döngünün geri kalanını atlayın ve sonraki adım ile devam edin."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Uyarı: Bu blok sadece bir döngü içinde kullanılabilir."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "her öğe için %1 listede %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Bir listedeki her öğe için '%1' değişkenini maddeye atayın ve bundan sonra bazı açıklamalar yapın."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "ile sayılır %1 %2 den %3 ye, her adımda %4 değişim"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Başlangıç sayısından bitiş sayısına kadar belirtilen aralık ve belirtilen engeller ile devam eden değerler alan '%1' değişkeni oluştur."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "If bloğuna bir koşul ekleyin."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "If bloğuna kalan durumları \"yakalayan\" bir son ekle."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "If bloğuna ekle, kaldır veya yeniden düzenleme yap."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "değilse"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "değilse eğer"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "eğer"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Eğer değişken true , yani gerçekleşmiş ise , ardından gelen işlemi yerine getir ."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Eğer değişken true, yani gerçekleşiyor ise ilk blok'taki işlemleri yerine getir, Aksi halde ikinci blok'taki işlemleri yerine getir."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Eğer ilk değişken true, yani koşul gerçekleşmiş ise ilk blok içerisindeki işlem(ler)i gerçekleştir. Eğer ikinci değişken true ise, ikinci bloktaki işlem(ler)i gerçekleştir ."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Eğer ilk değer true, yani olumlu ise, ilk blok'taki işlem(ler)i gerçekleştir. İlk değer true değil ama ikinci değer true ise, ikinci bloktaki işlem(ler)i gerçekleştir. Eğer değerlerin hiçbiri true değil ise son blok'taki işlem(ler)i gerçekleştir."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://tr.wikipedia.org/wiki/For_d%C3%B6ng%C3%BCs%C3%BC"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "yap"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "%1 kez tekrarla"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Bazı işlemleri birkaç kez yap."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "kadar tekrarla"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "tekrar ederken"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Bir değer yanlış olduğunda bazı beyanlarda bulun."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Bir değer doğru olduğunda bazı beyanlarda bulun."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Tüm %1 blok silinsin mi?"; -Blockly.Msg.DELETE_BLOCK = "Bloğu Sil"; -Blockly.Msg.DELETE_VARIABLE = "'%1' değişkenini silmek istiyor musunuz?"; -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "'%2' değişkeninin %1 kullanımını silmek istiyor musunuz?"; -Blockly.Msg.DELETE_X_BLOCKS = "%1 Blokları Sil"; -Blockly.Msg.DISABLE_BLOCK = "Bloğu Devre Dışı Bırak"; -Blockly.Msg.DUPLICATE_BLOCK = "Çoğalt"; -Blockly.Msg.ENABLE_BLOCK = "Bloğu Etkinleştir"; -Blockly.Msg.EXPAND_ALL = "Blokları Genişlet"; -Blockly.Msg.EXPAND_BLOCK = "Bloğu Genişlet"; -Blockly.Msg.EXTERNAL_INPUTS = "Harici Girişler"; -Blockly.Msg.HELP = "Yardım"; -Blockly.Msg.INLINE_INPUTS = "Satır içi girdiler"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "Boş liste oluştur"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Veri kaydı içermeyen uzunluğu 0 olan bir listeyi verir"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "liste"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Bu liste bloğunu yeniden yapılandırmak için bölüm ekle,kaldır veya yeniden çağır."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "İle liste oluşturma"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Listeye bir nesne ekle."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Herhangi sayıda nesne içeren bir liste oluştur."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "ilk"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# sonundan"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "# Kare"; -Blockly.Msg.LISTS_GET_INDEX_GET = "Al"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "al ve kaldır"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "son"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "rastgele"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "kaldır"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Listedeki ilk öğeyi verir."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Listede belirli pozisyondaki bir öğeyi verir."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Listedeki son öğeyi verir."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Listedeki rastgele bir öğeyi verir."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Kaldırır ve listedeki ilk öğeyi döndürür."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Kaldırır ve listede belirtilen konumdaki bir öğeyi döndürür."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Kaldırır ve listedeki son öğeyi döndürür."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Kaldırır ve listedeki rastgele bir öğeyi verir."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Listedeki ilk nesneyi kaldırır."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Bir liste içerisinde , tanımlanan pozisyonda ki öğeyi kaldırır."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Listedeki son nesneyi kaldırır."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Listedeki rastgele bir nesneyi kaldırır."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "Sondan #'a kadar"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "#'a"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "Sona kadar"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "ilk öğeden alt liste al"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "# işaretinden sonra gelen ifadeye göre alt liste al , # sondan"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "# dan alt liste al"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Listenin belirli bir kısmının kopyasını yaratır."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 son öğedir."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 ilk öğedir."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "Öğenin ilk varolduğu yeri bul"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "Öğenin son varolduğu yeri bul"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Listedeki öğenin ilk/son oluşumunun indeksini döndürür. Eğer öğe bulunamaz ise %1 döndürür."; -Blockly.Msg.LISTS_INLIST = "Listede"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 boş"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Eğer liste boş ise true döndürür ."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "%1'in uzunluğu"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Bir listenin uzunluğunu verir."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "%1 nesnenin %2 kez tekrarlandığı bir liste yarat"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Verilen bir değerin , belirli bir sayıda tekrarlanmasından oluşan bir liste yaratır ."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "olarak"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "e yerleştir"; -Blockly.Msg.LISTS_SET_INDEX_SET = "yerleştir"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Nesneyi listenin başlangıcına ekler."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Bir öğeyi belirtilen pozisyona göre listeye yerleştirir ."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Öğeyi listenin sonuna ekle ."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Bir öğeyi listeye rast gele ekler ."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Bir listenin ilk öğesini yerleştirir ."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Bir öğeyi belirtilen yere göre listeye yerleştirir ."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Bir listedeki son öğeyi yerleştirir ."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Listeye rast gele bir öğe yerleştirir ."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "artan"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "azalan"; -Blockly.Msg.LISTS_SORT_TITLE = "kısa %1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Listenin kısa bir kopyası."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alfabetik, gözardı et"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "sayısal"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alfabetik"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "metinden liste yap"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "listeden metin yap"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Bir sınırlayıcı tarafından kesilen metinlerin listesini bir metine ekle."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Her sınırlayıcıda kesen metinleri bir metin listesine ayır."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "sınırlayıcı ile"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "false = Olumsuz"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Ya 'True' yada 'False' değerini verir."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "Olumlu"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://tr.wikipedia.org/wiki/E%C5%9Fitsizlikler"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Girilen iki değer birbirine eşitse \"True\" değerini verir."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Girilen ilk değer ikinci değerden daha büyükse \"True\" değerini verir."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Girilen ilk değer ikinci değerden büyük veya eşitse \"True\" değerini verir."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Girilen ilk değer ikinci değerden küçükse \"True\" değerini verir."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Girilen ilk değer ikinci değerden küçük veya eşitse \"True\" değerini verir."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Girilen iki değerde birbirine eşit değilse \"True\" değerini verir."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "%1 değil"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Girilen değer yanlışsa \"True\" değerini verir.Girilen değer doğruysa \"False\" değerini verir."; -Blockly.Msg.LOGIC_NULL = "sıfır"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "sıfır verir."; -Blockly.Msg.LOGIC_OPERATION_AND = "ve"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "veya"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Girilen iki değerde doğruysa \"True\" değerini verir."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Girilen iki değerden en az biri doğruysa \"True\" değerini verir."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "test"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "yanlış ise"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "doğru ise"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "'test'deki şartı test eder. Eğer şart doğru ise 'doğru' değeri döndürür, aksi halde 'yanlış' değeri döndürür."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://tr.wikipedia.org/wiki/Aritmetik"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "İki rakamın toplamını döndür."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "İki sayının bölümünü döndür."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "İki sayını farkını döndür."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "İki sayının çarpımını döndür."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "İlk sayinin ikincinin kuvvetine yükseltilmişini döndür."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "%1'i %2 kadar değiştir"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "'%1' değişkenine bir sayı ekle."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Yaygın sabitlerden birini döndür:π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (sonsuz)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "%1 i en düşük %2 en yüksek %3 ile sınırla"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Bir sayıyı belirli iki sayı arasında sınırlandır(dahil)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "bölünebilir"; -Blockly.Msg.MATH_IS_EVEN = "çift"; -Blockly.Msg.MATH_IS_NEGATIVE = "negatif"; -Blockly.Msg.MATH_IS_ODD = "tek"; -Blockly.Msg.MATH_IS_POSITIVE = "pozitif"; -Blockly.Msg.MATH_IS_PRIME = "asal"; -Blockly.Msg.MATH_IS_TOOLTIP = "Bir sayinin çift mi tek mi , tam mı, asal mı , pozitif mi, negatif mi, veya tam bir sayıyla bölünebilirliğini kontrol et.'True' veya 'False' değerini döndür."; -Blockly.Msg.MATH_IS_WHOLE = "Bütün olduğunu"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "%1 ÷ %2 nin kalanı"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "İki sayının bölümünden kalanı döndür."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "x"; -Blockly.Msg.MATH_NUMBER_HELPURL = "https://en.wikipedia.org/wiki/Number"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Bir sayı."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "listenin ortalaması"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "en büyük sayı"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "Listenin medyanı"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "Listenin en küçüğü"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "Listenin modları"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "Listenin rastgele öğesi"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "Listenin standart sapması"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "Listenin toplamı"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Listedeki sayısal değerlerin ortalamasını (aritmetik anlamda) döndür."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Listenin en büyüğünü döndür."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Listenin medyanını döndür."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Listenin en küçüğünü döndür."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Listede ki en yaygın öğe veya öğelerinin listesini döndür."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Listeden rastgele bir element döndür."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Listenin standart sapmasını döndür."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Listede ki tüm sayıların toplamını döndür."; -Blockly.Msg.MATH_POWER_SYMBOL = "üst alma"; -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://tr.wikipedia.org/wiki/Rastgele_say%C4%B1_%C3%BCretimi"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "Rast gele kesirli sayı , yada parça"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "0.0(dahil) ve 1.0 (hariç) sayıları arasında bir sayı döndür ."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://tr.wikipedia.org/wiki/Rastgele_say%C4%B1_%C3%BCretimi"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "%1 ile %2 arasında rastgele tam sayı üret"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Herhangi iki sayı arasında , sayılar dahil olmak üzere , rastgele bir tam sayı döndür."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding Yuvarlama fonksiyonu için araştırma yapınız, sayfanın Türkçe çevirisi henüz mevcut değil."; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "Yuvarla"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "aşağı yuvarla"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "yukarı yuvarla"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Bir sayı yı yukarı yada aşağı yuvarla ."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://tr.wikipedia.org/wiki/Karek%C3%B6k"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "Kesin"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "Kare kök"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Bir sayının tam değerini döndür ."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Bir sayının e ' inci kuvvetini döndür ."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Bir sayının doğal logaritmasını döndür ."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Bir sayının 10 temelinde logaritmasını döndür ."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Bir sayıyı geçersiz olarak döndür ."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Bir sayının 10. kuvvetini döndür ."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Bir sayının karekökü nü döndür ."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "tire"; -Blockly.Msg.MATH_TRIG_ACOS = "akosünüs"; -Blockly.Msg.MATH_TRIG_ASIN = "asinüs"; -Blockly.Msg.MATH_TRIG_ATAN = "atanjant"; -Blockly.Msg.MATH_TRIG_COS = "kosünüs"; -Blockly.Msg.MATH_TRIG_HELPURL = "https://tr.wikipedia.org/wiki/Trigonometrik_fonksiyonlar"; -Blockly.Msg.MATH_TRIG_SIN = "Sinüs"; -Blockly.Msg.MATH_TRIG_TAN = "tanjant"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Bir sayının ters kosunusunu döndür ."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Bir sayının ters sinüsünü döndür ."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Bir sayının ters tanjantını döndür ."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Bir açının kosinüsünü döndür(radyan olarak değil)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Bir açının sinüsünü döndür(radyan olarak değil)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Bir açının tanjantını döndür(radyan olarak değil)."; -Blockly.Msg.NEW_VARIABLE = "Değişken oluştur..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Yeni değişken ismi :"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "Eğer ifadelerine izin ver"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "ile :"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Kullanıcı tanımlı fonksiyonu çalıştır '%1' ."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Kullanıcı tanımlı fonksiyonu çalıştır '%1' ve çıktısını kullan ."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "ile :"; -Blockly.Msg.PROCEDURES_CREATE_DO = "'%1' oluştur"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Bu işlevi açıkla..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "birşey yap"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "e"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Çıktı vermeyen bir fonksiyon yaratır ."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "Geri dön"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Çıktı veren bir fonksiyon oluşturur."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Uyarı: Bu fonksiyon yinelenen parametreler vardır."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Fonksiyon tanımı vurgulamak"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Eğer değer doğruysa, ikinci değere geri dön."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Uyarı: Bu blok yalnızca bir fonksiyon tanımı içinde kullanılır."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "girdi adı:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "İşleve bir girdi ekleyin."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "girdiler"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Bu işlevin girdilerini ekleyin, çıkarın, ya da yeniden sıralayın."; -Blockly.Msg.REDO = "Yinele"; -Blockly.Msg.REMOVE_COMMENT = "Yorumu Sil"; -Blockly.Msg.RENAME_VARIABLE = "Değişkeni yeniden adlandır..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Tüm '%1' değişkenlerini yeniden isimlendir:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "Metin Ekle"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "e"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Değişken '%1' e bazı metinler ekleyin."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "küçük harf"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "Baş Harfler Büyük"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "büyük harf"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Metnin bir kopyasını farklı bir harf durumunda (HEPSİ BÜYÜK - hepsi küçük) getirir."; -Blockly.Msg.TEXT_CHARAT_FIRST = "İlk harfini al"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "# dan sona harfleri al"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "# harfini al"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "metinde"; -Blockly.Msg.TEXT_CHARAT_LAST = "son harfi al"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "Rastgele bir harf al"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Belirli pozisyonda ki bir harfi döndürür."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Metine bir öğe ekle."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "Katıl"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Bu metin bloğunu düzenlemek için bölüm ekle,sil veya yeniden görevlendir."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "Sondan # harfe"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "# harfe"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "son harfe"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "metinde"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "ilk harften başlayarak alt-string alma"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "n inci harften sona kadar alt-string alma"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "n inci harften alt-string alma"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Metinin belirli bir kısmını döndürür."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "metinde"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "Metnin ilk varolduğu yeri bul"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "Metnin son varolduğu yeri bul"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "İlk metnin ikinci metnin içindeki ilk ve son varoluşlarının indeksini döndürür.Metin bulunamadıysa %1 döndürür."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 boş"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Verilen metin boşsa true(doğru) değerini verir."; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "ile metin oluştur"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Herhangi bir sayıda ki öğeleri bir araya getirerek metnin bir parçasını oluştur."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "%1 in uzunluğu"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Yazı içerisinde verilen harflerin ( harf arasındaki boşluklar dahil) sayısını verir ."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "%1 ' i Yaz"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Belirli bir metni,sayıyı veya başka bir değeri yaz."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Kullanıcıdan sayı al ."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Kullanıcıdan Yazım al ."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "Kullanıcıdan sayı al , istek mesajı göstererek"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "Kullanıcıdan yazım al , istek mesajıyla"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/String_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Metnin bir harfi,kelimesi veya satırı."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "iki tarafından da boşlukları temizle"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "solundan boşlukları temizle"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "sağından boşlukları temizle"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Metnin bir veya her iki sondan da boşlukları silinmiş şekilde kopyasını verir."; -Blockly.Msg.TODAY = "Bugün"; -Blockly.Msg.UNDO = "Geri al"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "öge"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "'set %1' oluştur"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Bu değişkenin değerini verir."; -Blockly.Msg.VARIABLES_SET = "Atamak %1 e %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "'get %1' oluştur"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Bu değişkeni girilen değere eşitler."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "'%1' isimli değişken adı zaten var."; -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/uk.js b/backend/_pv_1_3_5/static/blockly/msg/js/uk.js deleted file mode 100755 index 832d6af68..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/uk.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.uk'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Додати коментар"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Змінити значення:"; -Blockly.Msg.CLEAN_UP = "Вирівняти блоки"; -Blockly.Msg.COLLAPSE_ALL = "Згорнути блоки"; -Blockly.Msg.COLLAPSE_BLOCK = "Згорнути блок"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "колір 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "колір 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; -Blockly.Msg.COLOUR_BLEND_RATIO = "співвідношення"; -Blockly.Msg.COLOUR_BLEND_TITLE = "змішати"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Змішує два кольори разом у вказаному співвідношені (0.0 - 1.0)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://uk.wikipedia.org/wiki/Колір"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Вибрати колір з палітри."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "випадковий колір"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "Вибрати колір навмання."; -Blockly.Msg.COLOUR_RGB_BLUE = "синій"; -Blockly.Msg.COLOUR_RGB_GREEN = "зелений"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; -Blockly.Msg.COLOUR_RGB_RED = "червоний"; -Blockly.Msg.COLOUR_RGB_TITLE = "колір з"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Створити колір зі вказаними рівнями червоного, зеленого та синього. Усі значення мають бути від 0 до 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "перервати цикл"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "продовжити з наступної ітерації циклу"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Перервати виконання циклу."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Пропустити залишок цього циклу і перейти до виконання наступної ітерації."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Попередження: цей блок може бути використаний тільки в межах циклу."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "для кожного елемента %1 у списку %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Для кожного елемента в списку змінна '%1' отримує значення елемента, а потім виконуються певні дії."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "рахувати з %1 від %2 до %3 через %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Наявна змінна \"%1\" набуває значень від початкового до кінцевого, враховуючи заданий інтервал, і виконуються вказані блоки."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Додайте умову до блока 'якщо'."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Додати остаточну, всеосяжну умову до блоку 'якщо'."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Додайте, вилучіть або змініть порядок секцій, щоб переналаштувати цей блок 'якщо'."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "інакше"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "інакше якщо"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "якщо"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Якщо значення істинне, то виконати певні дії."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Якщо значення істинне, то виконується перший блок операторів. В іншому випадку виконується другий блок операторів."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Якщо перше значення істинне, то виконується перший блок операторів. В іншому випадку, якщо друге значення істина, то виконується другий блок операторів."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Якщо перше значення істинне, то виконується перший блок операторів. В іншому випадку, якщо друге значення істинне, то виконується другий блок операторів. Якщо жодне із значень не є істинним, то виконується останній блок операторів."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://uk.wikipedia.org/wiki/Цикл_(програмування)#.D0.A6.D0.B8.D0.BA.D0.BB_.D0.B7_.D0.BB.D1.96.D1.87.D0.B8.D0.BB.D1.8C.D0.BD.D0.B8.D0.BA.D0.BE.D0.BC"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "виконати"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "повторити %1 разів"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Виконати певні дії декілька разів."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "повторювати, доки не"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "повторювати поки"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Поки значення хибне, виконувати певні дії."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Поки значення істинне, виконувати певні дії."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Вилучити всі блоки %1?"; -Blockly.Msg.DELETE_BLOCK = "Видалити блок"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Видалити %1 блоків"; -Blockly.Msg.DISABLE_BLOCK = "Вимкнути блок"; -Blockly.Msg.DUPLICATE_BLOCK = "Дублювати"; -Blockly.Msg.ENABLE_BLOCK = "Увімкнути блок"; -Blockly.Msg.EXPAND_ALL = "Розгорнути блоки"; -Blockly.Msg.EXPAND_BLOCK = "Розгорнути блок"; -Blockly.Msg.EXTERNAL_INPUTS = "Зовнішні входи"; -Blockly.Msg.HELP = "Довідка"; -Blockly.Msg.INLINE_INPUTS = "Вбудовані входи"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "створити порожній список"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Повертає список, довжиною 0, що не містить записів даних"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "список"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Додайте, вилучіть або змініть порядок секцій для переналаштування блока списку."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "створити список з"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Додати елемент до списку."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Створює список з будь-якою кількістю елементів."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "перший"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "# з кінця"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "отримати"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "отримати і вилучити"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "останній"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "випадковий"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "вилучити"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = "-ий."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Повертає перший елемент списку."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Повертає елемент у заданій позиції у списку."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Повертає останній елемент списку."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Повертає випадковий елемент списку."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Видаляє і повертає перший елемент списку."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Видаляє і повертає елемент у заданій позиції у списку."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Видаляє і повертає останній елемент списку."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Видаляє і повертає випадковий елемент списоку."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Вилучає перший елемент списку."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Вилучає зі списку елемент у вказаній позиції."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Вилучає останній елемент списку."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Вилучає випадковий елемент списку."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "до # з кінця"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "до #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "до останнього"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "отримати вкладений список з першого"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "отримати вкладений список від # з кінця"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "отримати вкладений список з #"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = "символу."; -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Створює копію вказаної частини списку."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 - це останній елемент."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 - це перший елемент."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "знайти перше входження елемента"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "знайти останнє входження елемента"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Повертає індекс першого/останнього входження елемента у списку. Повертає %1, якщо елемент не знайдено."; -Blockly.Msg.LISTS_INLIST = "у списку"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 є порожнім"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Повертає істину, якщо список порожній."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "довжина %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Повертає довжину списку."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "створити список з елемента %1 повтореного %2 разів"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Створює список, що складається з заданого значення повтореного задану кількість разів."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "як"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "вставити в"; -Blockly.Msg.LISTS_SET_INDEX_SET = "встановити"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Вставляє елемент на початок списку."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Вставка елемента у вказану позицію списку."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Додає елемент у кінці списку."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Випадковим чином вставляє елемент у список."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Задає перший елемент списку."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Задає елемент списку у вказаній позиції."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Задає останній елемент списку."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Задає випадковий елемент у списку."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "за зростанням"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "за спаданням"; -Blockly.Msg.LISTS_SORT_TITLE = "сортувати %3 %1 %2"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "Сортувати копію списку."; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "за абеткою, ігноруючи регістр"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "як числа"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "за абеткою"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "зробити з тексту список"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "зробити зі списку текст"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Злити список текстів у єдиний текст, відокремивши розділювачами."; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Поділити текст на список текстів, розриваючи на кожному розділювачі."; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "з розділювачем"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "хибність"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Повертає значення істина або хибність."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "істина"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://uk.wikipedia.org/wiki/Нерівність"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Повертає істину, якщо обидва входи рівні один одному."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Повертає істину, якщо перше вхідне значення більше, ніж друге."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Повертає істину, якщо перше вхідне значення більше або дорівнює другому."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Повертає істину, якщо перше вхідне значення менше, ніж друге."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Повертає істину, якщо перше вхідне значення менше або дорівнює другому."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Повертає істину, якщо обидва входи не дорівнюють один одному."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "не %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Повертає істину, якщо вхідне значення хибне. Повертає хибність, якщо вхідне значення істинне."; -Blockly.Msg.LOGIC_NULL = "ніщо"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Повертає ніщо."; -Blockly.Msg.LOGIC_OPERATION_AND = "та"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "або"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Повертає істину, якщо обидва входи істинні."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Повертає істину, якщо принаймні один з входів істинний."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "тест"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "якщо хибність"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "якщо істина"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Перевіряє умову в 'тест'. Якщо умова істинна, то повертає значення 'якщо істина'; в іншому випадку повертає значення 'якщо хибність'."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://uk.wikipedia.org/wiki/Арифметика"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Повертає суму двох чисел."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Повертає частку двох чисел."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Повертає різницю двох чисел."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Повертає добуток двох чисел."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Повертає перше число, піднесене до степеня, вираженого другим числом."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter"; -Blockly.Msg.MATH_CHANGE_TITLE = "змінити %1 на %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Додати число до змінної '%1'."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://uk.wikipedia.org/wiki/Математична_константа"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Повертає одну з поширених констант: π (3.141...), e (2.718...), φ (1,618...), sqrt(2) (1.414...), sqrt(½) (0.707...) або ∞ (нескінченність)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "обмежити %1 від %2 до %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Обмежує число вказаними межами (включно)."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "ділиться на"; -Blockly.Msg.MATH_IS_EVEN = "парне"; -Blockly.Msg.MATH_IS_NEGATIVE = "від'ємне"; -Blockly.Msg.MATH_IS_ODD = "непарне"; -Blockly.Msg.MATH_IS_POSITIVE = "додатне"; -Blockly.Msg.MATH_IS_PRIME = "просте"; -Blockly.Msg.MATH_IS_TOOLTIP = "Перевіряє, чи число парне, непарне, просте, ціле, додатне, від'ємне або чи воно ділиться на певне число без остачі. Повертає істину або хибність."; -Blockly.Msg.MATH_IS_WHOLE = "ціле"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://uk.wikipedia.org/wiki/Ділення_з_остачею"; -Blockly.Msg.MATH_MODULO_TITLE = "остача від %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Повертає остачу від ділення двох чисел."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://uk.wikipedia.org/wiki/Число"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Число."; -Blockly.Msg.MATH_ONLIST_HELPURL = "http://www.mapleprimes.com/questions/100441-Applying-Function-To-List-Of-Numbers"; -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "середнє списку"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "максимум списку"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "медіана списку"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "мінімум списку"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "моди списку"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "випадковий елемент списку"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "стандартне відхилення списку"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "сума списку"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Повертає середнє (арифметичне) числових значень у списку."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Повертає найбільше число у списку."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Повертає медіану списку."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Повертає найменше число у списку."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Повертає перелік найпоширеніших елементів у списку."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Повертає випадковий елемент зі списку."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Повертає стандартне відхилення списку."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Повертає суму всіх чисел у списку."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://uk.wikipedia.org/wiki/Генерація_випадкових_чисел"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "випадковий дріб"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Повертає випадковий дріб від 0,0 (включно) та 1.0 (не включно)."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://uk.wikipedia.org/wiki/Генерація_випадкових_чисел"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "випадкове ціле число від %1 до %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Повертає випадкове ціле число між двома заданими межами включно."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://uk.wikipedia.org/wiki/Округлення"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "округлити"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "округлити до меншого"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "округлити до більшого"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Округлення числа до більшого або до меншого."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://uk.wikipedia.org/wiki/Квадратний_корінь"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "модуль"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "квадратний корінь"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Повертає модуль числа."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Повертає e у степені."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Повертає натуральний логарифм числа."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Повертає десятковий логарифм числа."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Повертає протилежне число."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Повертає 10 у степені."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Повертає квадратний корінь з числа."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://uk.wikipedia.org/wiki/Тригонометричні_функції"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Повертає арккосинус числа."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Повертає арксинус числа."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Повертає арктангенс числа."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Повертає косинус кута в градусах (не в радіанах)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Повертає синус кута в градусах (не в радіанах)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Повертає тангенс кута в градусах (не в радіанах)."; -Blockly.Msg.NEW_VARIABLE = "Нова змінна..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Нова назва змінної:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = "-ий."; -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "дозволити дії"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "з:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://uk.wikipedia.org/wiki/Підпрограма"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Запустити користувацьку функцію \"%1\"."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://uk.wikipedia.org/wiki/Підпрограма"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Запустити користувацьку функцію \"%1\" і використати її вивід."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "з:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Створити \"%1\""; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Опишіть цю функцію..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = "блок тексту"; -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://uk.wikipedia.org/wiki/Підпрограма"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "щось зробити"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "до"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Створює функцію без виводу."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://uk.wikipedia.org/wiki/Підпрограма"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "повернути"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Створює функцію з виводом."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Увага: ця функція має дубльовані параметри."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Підсвітити визначення функції"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Якщо значення істинне, то повернути друге значення."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Попередження: цей блок може використовуватися лише в межах визначення функції."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "назва входу:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Додати до функції вхідні параметри."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "входи"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Додайте, вилучіть або змініть порядок вхідних параметрів для цієї функції."; -Blockly.Msg.REDO = "Повторити"; -Blockly.Msg.REMOVE_COMMENT = "Видалити коментар"; -Blockly.Msg.RENAME_VARIABLE = "Перейменувати змінну..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Перейменувати усі змінні \"%1\" до:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "додати текст"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "до"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Додати деякий текст до змінної '%1'."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "до нижнього регістру"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "Великі Перші Букви"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "до ВЕРХНЬОГО регістру"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "В іншому випадку повертає копію тексту."; -Blockly.Msg.TEXT_CHARAT_FIRST = "отримати перший символ"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "отримати символ # з кінця"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "отримати символ #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm"; -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "у тексті"; -Blockly.Msg.TEXT_CHARAT_LAST = "отримати останній символ"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "отримати випадковий символ"; -Blockly.Msg.TEXT_CHARAT_TAIL = "-ий."; -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Повертає символ у зазначеній позиції."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "Додати елемент до тексту."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "приєднати"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Додайте, вилучіть або змініть порядок секцій для переналаштування текстового блоку."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "до символу # з кінця"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "до символу #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "до останнього символу"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "у тексті"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "отримати підрядок від першого символу"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "отримати підрядок від символу # з кінця"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "отримати підрядок від символу #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = "-ого."; -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Повертає заданий фрагмент тексту."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "у тексті"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "знайти перше входження тексту"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "знайти останнє входження тексту"; -Blockly.Msg.TEXT_INDEXOF_TAIL = "."; -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Повертає індекс першого/останнього входження першого тексту в другий. Повертає %1, якщо текст не знайдено."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 є порожнім"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Повертає істину, якщо вказаний текст порожній."; -Blockly.Msg.TEXT_JOIN_HELPURL = "http://www.chemie.fu-berlin.de/chemnet/use/info/make/make_8.html"; -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "створити текст з"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Створити фрагмент тексту шляхом з'єднування будь-якого числа елементів."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "довжина %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Повертає число символів (включно з пропусками) у даному тексті."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "друк %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "Надрукувати заданий текст, числа або інші значення."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Запитати у користувача число."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Запитати у користувача деякий текст."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "запит числа з повідомленням"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "запит тексту з повідомленням"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://uk.wikipedia.org/wiki/Рядок_(програмування)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Символ, слово або рядок тексту."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "вилучити крайні пропуски з обох кінців"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "вилучити пропуски з лівого боку"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "вилучити пропуски з правого боку"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Повертає копію тексту з вилученими пропусками з одного або обох кінців."; -Blockly.Msg.TODAY = "Сьогодні"; -Blockly.Msg.UNDO = "Скасувати"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "елемент"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Створити 'встановити %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Повертає значення цієї змінної."; -Blockly.Msg.VARIABLES_SET = "встановити %1 до %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Створити 'отримати %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Задає цю змінну рівною входу."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/vi.js b/backend/_pv_1_3_5/static/blockly/msg/js/vi.js deleted file mode 100755 index 6bd63860e..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/vi.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.vi'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "Thêm Chú Giải"; -Blockly.Msg.CHANGE_VALUE_TITLE = "Thay giá trị thành:"; -Blockly.Msg.CLEAN_UP = "Clean up Blocks"; // untranslated -Blockly.Msg.COLLAPSE_ALL = "Thu Nhỏ Mọi Mảnh"; -Blockly.Msg.COLLAPSE_BLOCK = "Thu Nhỏ Mảnh"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "màu 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "màu 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "tỉ lệ"; -Blockly.Msg.COLOUR_BLEND_TITLE = "pha"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "Pha hai màu với nhau theo tỉ lệ (0 - 100)."; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://vi.wikipedia.org/wiki/M%C3%A0u_s%E1%BA%AFc"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "Chọn một màu từ bảng màu."; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "màu bất kỳ"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "chọn một màu bất kỳ."; -Blockly.Msg.COLOUR_RGB_BLUE = "màu xanh dương"; -Blockly.Msg.COLOUR_RGB_GREEN = "màu xanh lá cây"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "màu đỏ"; -Blockly.Msg.COLOUR_RGB_TITLE = "Tạo màu từ"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "Tạo màu từ ba màu: đỏ, xanh lá cây, xanh dương với số lượng cụ thể. Mỗi số phải có giá trị từ 0 đến 100."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "thoát"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "sang lần lặp tiếp theo"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "Thoát khỏi vòng lặp hiện tại."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "Bỏ qua phần còn lại trong vòng lặp này, và sang lần lặp tiếp theo."; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "Chú ý: Mảnh này chỉ có thế dùng trong các vòng lặp."; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "với mỗi thành phần %1 trong danh sách %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "Trong một danh sách, lấy từng thành phần, gán vào biến \"%1\", rồi thực hiện một số lệnh."; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "đếm theo %1 từ %2 đến %3 mỗi lần thêm %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "Đếm từ số đầu đến số cuối. Khi đến mỗi số, gán số vào biến \"%1\" rồi thực hiện các lệnh."; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "Thêm một điều kiện vào mảnh nếu."; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "Cuối cùng, khi không điều kiện nào đúng."; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "Thêm, bỏ, hoặc đổi thứ tự các mảnh con để tạo cấu trúc mới cho mảnh nếu."; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "nếu không"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "nếu không nếu"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "nếu"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "Nếu điều kiện đúng, thực hiện các lệnh."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "Nếu điều kiện đúng, thực hiện các lệnh đầu. Nếu sai, thực hiện các lệnh sau."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "Nếu điều kiện đúng, thực hiện các lệnh đầu. Nếu không, nếu điều kiện thứ hai đúng, thực hiện các lệnh thứ hai."; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "Nếu điều kiện đúng, thực hiện các lệnh đầu. Nếu không, nếu điều kiện thứ hai đúng, thực hiện các lệnh thứ hai. Nếu không điều kiện nào đúng, thực hiện các lệnh cuối cùng."; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://en.wikipedia.org/wiki/For_loop"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "thực hiện"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "lặp lại %1 lần"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "Thực hiện các lệnh vài lần."; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "lặp lại cho đến khi"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "lặp lại trong khi"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "Miễn là điều kiện còn sai, thì thực hiện các lệnh. Khi điều kiện đúng thì ngưng."; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "Miễn là điều kiện còn đúng, thì thực hiện các lệnh."; -Blockly.Msg.DELETE_ALL_BLOCKS = "Xóa hết %1 mảnh?"; -Blockly.Msg.DELETE_BLOCK = "Xóa Mảnh Này"; -Blockly.Msg.DELETE_VARIABLE = "Delete the '%1' variable"; // untranslated -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "Delete %1 uses of the '%2' variable?"; // untranslated -Blockly.Msg.DELETE_X_BLOCKS = "Xóa %1 Mảnh"; -Blockly.Msg.DISABLE_BLOCK = "Ngưng Tác Dụng"; -Blockly.Msg.DUPLICATE_BLOCK = "Tạo Bản Sao"; -Blockly.Msg.ENABLE_BLOCK = "Phục Hồi Tác Dụng"; -Blockly.Msg.EXPAND_ALL = "Mở Lớn Mọi Mảnh"; -Blockly.Msg.EXPAND_BLOCK = "Mở Lớn Mảnh"; -Blockly.Msg.EXTERNAL_INPUTS = "Chỗ Gắn Bên Ngoài"; -Blockly.Msg.HELP = "Trợ Giúp"; -Blockly.Msg.INLINE_INPUTS = "Chỗ Gắn Cùng Dòng"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "tạo danh sách trống"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "Hoàn trả một danh sách, với độ dài 0, không có thành tố nào cả"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "danh sách"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "Thêm, bỏ, hoặc sắp xếp lại các thành phần để tạo dựng mảnh danh sách này."; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "tạo danh sách gồm"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "Thêm vật vào danh sách."; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "Tạo một danh sách bao gồm nhiều vậts, với một số lượng bất kỳ."; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "đầu tiên"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "(đếm từ cuối) thứ"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "thứ"; -Blockly.Msg.LISTS_GET_INDEX_GET = "lấy thành tố"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "lấy và xóa thành tố"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "cuối cùng"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "bất kỳ"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "xóa thành tố"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "Hoàn trả thành tố đầu tiên trong danh sách."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "Hoàn trả thành tố trong danh sách ở vị trí ấn định."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "Hoàn trả thành tố cuối cùng trong danh sách."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "Hoàn trả một thành tố bất kỳ trong danh sách."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "Hoàn trả và xóa thành tố đầu tiên trong danh sách."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "Hoàn trả và xóa thành tố trong danh sách ở vị trí ấn định."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "Hoàn trả và xóa thành tố cuối cùng trong danh sách."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "Hoàn trả và xóa mộtthành tố bất kỳ trong danh sách."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "Xóa thành tố đầu tiên trong danh sách."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "Xóa thành tố trong danh sách ở vị trí ấn định."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "Xóa thành tố cuối cùng trong danh sách."; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "Xóa thành tố bất kỳ trong danh sách."; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "đến (đếm từ cuối) thứ"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "đến thứ"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "đến cuối cùng"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "lấy một danh sách con từ đầu tiên"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "lấy một danh sách con từ (đếm từ cuối) thứ"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "lấy một danh sách con từ thứ"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "Lấy một mảng của danh sách này để tạo danh sách con."; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 là thành tố cuối cùng."; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 là thành tố đầu tiên."; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "tìm sự có mặt đầu tiên của vật"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "tìm sự có mặt cuối cùng của vật"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "Hoàn trả vị trí xuất hiện đầu/cuối của vật trong danh sách. Nếu không tìm thấy thì hoàn trả số %1."; -Blockly.Msg.LISTS_INLIST = "trong dánh sách"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 trống rỗng"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "Hoàn trả “đúng\" nếu danh sách không có thành tử nào."; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "độ dài của %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "Hoàn trả độ dài của một danh sách."; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "tạo danh sách gồm một vật %1 lặp lại %2 lần"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "Tạo danh sách gồm một số lượng vật nhất định với mỗi vật đều giống nhau."; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "giá trị"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "gắn chèn vào vị trí"; -Blockly.Msg.LISTS_SET_INDEX_SET = "đặt thành tố"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "Gắn chèn vật vào đầu danh sách."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "Gắn chèn vật vào danh sách theo vị trí ấn định."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "Gắn thêm vật vào cuối danh sách."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "Gắn chèn vật vào danh sách ở vị trí ngẫu nhiên."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "Đặt giá trị của thành tố đầu tiên trong danh sách."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "Đặt giá trị của thành tố ở vị trí ấn định trong một danh sách."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "Đặt giá trị của thành tố cuối cùng trong danh sách."; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "Đặt giá trị của thành tố ngẫu nhiên trong danh sách."; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "ascending"; // untranslated -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "descending"; // untranslated -Blockly.Msg.LISTS_SORT_TITLE = "sort %1 %2 %3"; // untranslated -Blockly.Msg.LISTS_SORT_TOOLTIP = "Sort a copy of a list."; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "alphabetic, ignore case"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "numeric"; // untranslated -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "alphabetic"; // untranslated -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "make list from text"; // untranslated -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "make text from list"; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "Join a list of texts into one text, separated by a delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "Split text into a list of texts, breaking at each delimiter."; // untranslated -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "with delimiter"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "sai"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "Hoàn trả \"đúng\" hoặc \"sai\"."; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "đúng"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://vi.wikipedia.org/wiki/B%E1%BA%A5t_%C4%91%E1%BA%B3ng_th%E1%BB%A9c"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "Hoàn trả giá trị \"đúng\" (true) nếu giá trị hai đầu vào bằng nhau."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "Hoàn trả giá trị \"đúng\" (true) nếu đầu vào thứ nhất lớn hơn đầu vào thứ hai."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "Hoàn trả giá trị \"đúng\" (true) nếu đầu vào thứ nhất lớn hơn hoặc bằng đầu vào thứ hai."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "Hoàn trả giá trị \"đúng\" (true) nếu đầu vào thứ nhất nhỏ hơn đầu vào thứ hai."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "Hoàn trả giá trị \"đúng\" (true) nếu đầu vào thứ nhất nhỏ hơn hoặc bằng đầu vào thứ hai."; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "Hoàn trả giá trị \"đúng\" (true) nếu giá trị hai đầu vào không bằng nhau."; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "không %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "Hoàn trả \"đúng\" (true) nếu đầu vào sai. Hoàn trả \"sai\" (false) nếu đầu vào đúng."; -Blockly.Msg.LOGIC_NULL = "trống không"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "Hoàn trả trống không."; -Blockly.Msg.LOGIC_OPERATION_AND = "và"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "hoặc"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "Hoàn trả \"đúng\" (true) nếu cả hai đầu vào đều đúng."; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "Hoàn trả \"đúng\" (true) nếu ít nhất một trong hai đầu vào đúng."; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "kiểm tra"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://en.wikipedia.org/wiki/%3F:"; // untranslated -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "nếu sai"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "nếu đúng"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "Kiểm tra điều kiện. Nếu điều kiện đúng, hoàn trả giá trị từ mệnh đề \"nếu đúng\" nếu không đúng, hoàn trả giá trị từ mệnh đề \"nếu sai\"."; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://vi.wikipedia.org/wiki/S%E1%BB%91_h%E1%BB%8Dc"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "Hoàn trả tổng của hai con số."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "Hoàn trả thương của hai con số."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "Hoàn trả hiệu của hai con số."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "Hoàn trả tích của hai con số."; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "Hoàn trả số lũy thừa với số thứ nhất là cơ số và số thứ hai là số mũ."; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://vi.wikipedia.org/wiki/Ph%C3%A9p_c%E1%BB%99ng"; -Blockly.Msg.MATH_CHANGE_TITLE = "cộng vào %1 giá trị %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "Cộng số đầu vào vào biến \"%1\"."; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://en.wikipedia.org/wiki/Mathematical_constant"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "Hoàn trả các đẳng số thường gặp: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (vô cực)."; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "giới hạn %1 không dưới %2 không hơn %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "Giới hạn số đầu vào để không dưới số thứ nhất và không hơn số thứ hai."; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "chia hết cho"; -Blockly.Msg.MATH_IS_EVEN = "chẵn"; -Blockly.Msg.MATH_IS_NEGATIVE = "là số âm"; -Blockly.Msg.MATH_IS_ODD = "lẻ"; -Blockly.Msg.MATH_IS_POSITIVE = "là số dương"; -Blockly.Msg.MATH_IS_PRIME = "là số nguyên tố"; -Blockly.Msg.MATH_IS_TOOLTIP = "Kiểm tra con số xem nó có phải là số chẵn, lẻ, nguyên tố, nguyên, dương, âm, hay xem nó có chia hết cho số đầu vào hay không. Hoàn trả đúng hay sai."; -Blockly.Msg.MATH_IS_WHOLE = "là số nguyên"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://en.wikipedia.org/wiki/Modulo_operation"; -Blockly.Msg.MATH_MODULO_TITLE = "số dư của %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "Chia số thứ nhất cho số thứ hai rồi hoàn trả số dư từ."; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://vi.wikipedia.org/wiki/S%E1%BB%91"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "Một con số."; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "giá trị trung bình của một danh sách"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "số lớn nhât của một danh sách"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "số trung vị của một danh sách"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "số nhỏ nhất của một danh sách"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "các mode của một danh sách"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "một số bất kỳ của một danh sách"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "độ lệch chuẩn của một danh sách"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "tổng của một danh sách"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "Hoàn trả giá trị trung bình từ của danh sách số."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "Hoàn trả số lớn nhất trong tất cả các số trong danh sách."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "Hoàn trả số trung vị của danh sách số."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "Hoàn trả số nhỏ nhất trong tất cả các số trong danh sách."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "Hoàn trả các số có mặt nhiều nhất trong danh sách."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "Hoàn trả một số bất kỳ từ các số trong danh sách."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "Hoàn trả độ lệch chuẩn của danh sách số."; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "Hoàn trả tổng số của tất cả các số trong danh sách."; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "phân số bất kỳ"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "Hoàn trả một phân số bất kỳ không nhỏ hơn 0.0 và không lớn hơn 1.0."; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://en.wikipedia.org/wiki/Random_number_generation"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "Một số nguyên bất kỳ từ %1 đến %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "Hoàn trả một số nguyên bất kỳ lớn hơn hoặc bằng số đầu và nhỏ hơn hoặc bằng số sau."; -Blockly.Msg.MATH_ROUND_HELPURL = "https://en.wikipedia.org/wiki/Rounding"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "làm tròn"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "làm tròn xuống"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "làm tròn lên"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "Làm tròn lên hoặc tròn xuống số đầu vào."; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://vi.wikipedia.org/wiki/C%C4%83n_b%E1%BA%ADc_hai"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "giá trị tuyệt đối"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "căn bật hai"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "Hoàn trả giá trị tuyệt đối của số đầu vào."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "Hoàn trả lũy thừa của số e với số mũ đầu vào."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "Hoàn trả lôgarit tự nhiên của số đầu vào."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "Hoàn trả lôgarit cơ số 10 của số đầu vào."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "Đổi dấu của số đầu vào: âm thành dương và dương thành âm, và hoàn trả số mới."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "Hoàn trả lũy thừa của số 10 với số mũ đầu vào."; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "Hoàn trả căn bật hai của số đầu vào."; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://vi.wikipedia.org/wiki/H%C3%A0m_l%C6%B0%E1%BB%A3ng_gi%C3%A1c"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "Hoàn trả Arccos của một góc (theo độ)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "Hoàn trả Arcsin của một góc (theo độ)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "Hoàn trả Arctang của một góc (theo độ)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "Hoàn trả Cos của một góc (theo độ)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "Hoàn trả Sin của một góc (theo độ)."; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "Hoàn trả Tang của một góc (theo độ)."; -Blockly.Msg.NEW_VARIABLE = "Biến mới..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "Tên của biến mới:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "cho phép báo cáo"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "với:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "Chạy một thủ tục không có giá trị hoàn trả."; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "Chạy một thủ tục có giá trị hoàn trả."; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "với:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "Tạo mảnh \"thực hiện %1\""; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "Describe this function..."; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "thủ tục"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = ""; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "Một thủ tục không có giá trị hoàn trả."; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "hoàn trả"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "Một thủ tục có giá trị hoàn trả."; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "Chú ý: Thủ tục này có lặp lại tên các tham số."; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "Làm nổi bật thủ tục"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "Khi điều kiện đúng thì hoàn trả một giá trị."; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "Chú ý: Mảnh này chỉ có thể dùng trong một thủ tục."; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "biến:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "Thêm một đầu vào cho hàm."; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "các tham số"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "Thêm, xóa hoặc sắp xếp lại các đầu vào cho hàm này."; -Blockly.Msg.REDO = "Redo"; // untranslated -Blockly.Msg.REMOVE_COMMENT = "Xóa Chú Giải"; -Blockly.Msg.RENAME_VARIABLE = "Thay tên biến..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "Thay tên tất cả \"%1\" biến này thành:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "thêm văn bản"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "ở cuối"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "Thêm một mảng văn bản vào biến \"%1\"."; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "thành chữ thường"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "thành Chữ In Đầu Mỗi Từ"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "thành CHỮ IN HOA"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "Hoàn trả văn bản sau khi chuyển đổi chữ in hoa hay thường."; -Blockly.Msg.TEXT_CHARAT_FIRST = "lấy ký tự đầu tiên"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "lấy từ phía cuối, ký tự thứ"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "lấy ký tự thứ"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "trong văn bản"; -Blockly.Msg.TEXT_CHARAT_LAST = "lấy ký tự cuối cùng"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "lấy ký tự bất kỳ"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "Hoàn trả ký tự ở vị trí đặt ra."; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "thêm vật mới vào văn bản."; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "kết nối"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "Thêm, bỏ, hoặc sắp xếp lại các thành phần để tạo dựng mảnh văn bản này."; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "đến từ phía cuối, ký tự thứ"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "đến ký tự thứ"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "đến ký tự cuối cùng"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "trong văn bản"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "lấy từ ký tự đầu tiên"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "lấy từ phía cuối, ký tự thứ"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "lấy từ ký tự thứ"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "Hoàn trả một mảng ký tự ấn định từ trong văn bản."; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "trong văn bản"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "tìm sự có mặt đầu tiên của"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "tìm sự có mặt cuối cùng của"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "Hoàn trả vị trí xuất hiện đầu/cuối của văn bản thứ nhất trong văn bản thứ hai. Nếu không tìm thấy thì hoàn trả số %1."; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 trống không"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "Hoàn trả “đúng nếu văn bản không có ký tự nào."; -Blockly.Msg.TEXT_JOIN_HELPURL = ""; -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "tạo văn bản từ"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "Tạo một văn bản từ các thành phần."; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "độ dài của %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "Hoàn trả số lượng ký tự (kể cả khoảng trắng) trong văn bản đầu vào."; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "in lên màng hình %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "In ra màng hình một văn bản, con số, hay một giá trị đầu vào khác."; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "Xin người dùng nhập vào một con số."; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "Xin người dùng nhập vào một văn bản."; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "Xin người dùng nhập vào con số với dòng hướng dẫn"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "Xin người dùng nhập vào văn bản với dòng hướng dẫn"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://en.wikipedia.org/wiki/string_(computer_science)"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "Một ký tự, một từ, hay một dòng."; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "cắt các không gian từ cả hai mặt của"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "cắt các không gian từ bên trái của"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "cắt các không gian từ bên phải của"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "Hoàn trả bản sao của văn bản sau khi xóa khoảng trắng từ một hoặc hai bên."; -Blockly.Msg.TODAY = "Today"; // untranslated -Blockly.Msg.UNDO = "Undo"; // untranslated -Blockly.Msg.VARIABLES_DEFAULT_NAME = "vật"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "Tạo mảnh \"đặt vào %1\""; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "Hoàn trả giá trị của."; -Blockly.Msg.VARIABLES_SET = "cho %1 bằng %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "Tạo mảnh \"lấy %1\""; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "Đặt giá trị của biến này thành..."; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "A variable named '%1' already exists."; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/zh-hans.js b/backend/_pv_1_3_5/static/blockly/msg/js/zh-hans.js deleted file mode 100755 index 66b7ec800..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/zh-hans.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.zh.hans'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "添加注释"; -Blockly.Msg.CHANGE_VALUE_TITLE = "更改值:"; -Blockly.Msg.CLEAN_UP = "整理块"; -Blockly.Msg.COLLAPSE_ALL = "折叠块"; -Blockly.Msg.COLLAPSE_BLOCK = "折叠块"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "颜色1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "颜色2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "比例"; -Blockly.Msg.COLOUR_BLEND_TITLE = "混合"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "用一个给定的比率(0.0-1.0)混合两种颜色。"; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://zh.wikipedia.org/wiki/颜色"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "从调色板中选择一种颜色。"; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "随机颜色"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "随机选择一种颜色。"; -Blockly.Msg.COLOUR_RGB_BLUE = "蓝色"; -Blockly.Msg.COLOUR_RGB_GREEN = "绿色"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "红色"; -Blockly.Msg.COLOUR_RGB_TITLE = "颜色"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "通过指定红色、绿色和蓝色的量创建一种颜色。所有的值必须介于0和100之间。"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "中断循环"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "继续下一次循环"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "中断包含它的循环。"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "跳过这个循环的剩余部分,并继续下一次迭代。"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "警告:此块仅可用于在一个循环内。"; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "为每个项目 %1 在列表中 %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "遍历每个列表中的项目,将变量“%1”设定到该项中,然后执行某些语句。"; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "使用 %1 从范围 %2 到 %3 每隔 %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "从起始数到结尾数中取出变量“%1”的值,按指定的时间间隔,执行指定的块。"; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "在if语句块中增加一个条件。"; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "添加一个最终的,包括所有情况的节到if块中。"; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "增加、删除或重新排列各节来重新配置“if”块。"; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "否则"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "否则如果"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "如果"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "如果值为真,执行一些语句。"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "如果值为真,则执行第一块语句。否则,则执行第二块语句。"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "如果第一个值为真,则执行第一块的语句。否则,如果第二个值为真,则执行第二块的语句。"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "如果第一个值为真,则执行第一块对语句。否则,如果第二个值为真,则执行语句的第二块。如果没有值为真,则执行最后一块的语句。"; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://zh.wikipedia.org/wiki/For循环"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "执行"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "重复 %1 次"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "多次执行一些语句。"; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "重复直到"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "重复当"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "只要值为假,执行一些语句。"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "只要值为真,执行一些语句。"; -Blockly.Msg.DELETE_ALL_BLOCKS = "删除所有%1块吗?"; -Blockly.Msg.DELETE_BLOCK = "删除块"; -Blockly.Msg.DELETE_VARIABLE = "删除“%1”变量"; -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "删除“%2”变量的%1种用途么?"; -Blockly.Msg.DELETE_X_BLOCKS = "删除 %1 块"; -Blockly.Msg.DISABLE_BLOCK = "禁用块"; -Blockly.Msg.DUPLICATE_BLOCK = "复制"; -Blockly.Msg.ENABLE_BLOCK = "启用块"; -Blockly.Msg.EXPAND_ALL = "展开块"; -Blockly.Msg.EXPAND_BLOCK = "展开块"; -Blockly.Msg.EXTERNAL_INPUTS = "外部输入"; -Blockly.Msg.HELP = "帮助"; -Blockly.Msg.INLINE_INPUTS = "单行输入"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "创建空列表"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "返回一个列表,长度为 0,不包含任何数据记录"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "列表"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "增加、删除或重新排列各部分以此重新配置这个列表块。"; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "建立字串使用"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "将一个项添加到列表中。"; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "建立一个具有任意数量项目的列表。"; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "第一"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "倒数第#"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; -Blockly.Msg.LISTS_GET_INDEX_GET = "获得"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "取出并移除"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "最后"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "随机"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "移除"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = "空白"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "返回列表中的第一个项目。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "返回在列表中的指定位置的项。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "返回列表中的最后一项。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "随机返回列表中的一个项目。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "移除并返回列表中的第一个项目。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "移除并返回列表中的指定位置的项。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "移除并返回列表中的最后一个项目。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "移除并返回列表中的一个随机项目中。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "移除列表中的第一项"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "移除在列表中的指定位置的项。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "移除列表中的最后一项"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "删除列表中的一个随机的项。"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "到倒数第#"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "到#"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "到最后"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "从头获得子列表"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "从倒数#取得子列表"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "从#取得子列表"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = "空白"; -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "复制列表中指定的部分。"; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1是最后一项。"; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1是第一个项目。"; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "找出第一个项出现"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "找出最后一个项出现"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "返回在列表中的第一/最后一个匹配项的索引值。如果找不到项目则返回%1。"; -Blockly.Msg.LISTS_INLIST = "在列表中"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1是空的"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "如果改列表为空,则返回真。"; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "%1的长度"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "返回列表的长度。"; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "建立列表使用项 %1 重复 %2 次"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "建立包含指定重复次数的值的列表。"; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "为"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "插入在"; -Blockly.Msg.LISTS_SET_INDEX_SET = "设置"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "在列表的起始处添加该项。"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "插入在列表中指定位置的项。"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "将该项追加到列表的末尾。"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "在列表中随机插入项。"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "设置列表中的第一个项目。"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "设置在列表中指定位置的项。"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "设置列表中的最后一项。"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "设置列表中一个随机的项目。"; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "升序"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "降序"; -Blockly.Msg.LISTS_SORT_TITLE = "排序%1 %2 %3"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "排序一个列表的拷贝。"; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "按字母排序,忽略大小写"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "按数字排序"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "按字母排序"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "从文本制作列表"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "从列表拆出文本"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "加入文本列表至一个文本,由分隔符分隔。"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "拆分文本到文本列表,按每个分隔符拆分。"; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "用分隔符"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "假"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "返回真或假。"; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "真"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://zh.wikipedia.org/wiki/不等"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "如果两个输入结果相等,则返回真。"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "如果第一个输入结果比第二个大,则返回真。"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "如果第一个输入结果大于或等于第二个输入结果,则返回真。"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "如果第一个输入结果比第二个小,则返回真。"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "如果第一个输入结果小于或等于第二个输入结果,则返回真。"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "如果两个输入结果不相等,则返回真。"; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; -Blockly.Msg.LOGIC_NEGATE_TITLE = "非%1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "如果输入结果为假,则返回真;如果输入结果为真,则返回假。"; -Blockly.Msg.LOGIC_NULL = "空"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "返回空值。"; -Blockly.Msg.LOGIC_OPERATION_AND = "和"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "或"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "如果两个输入结果都为真,则返回真。"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "如果至少有一个输入结果为真,则返回真。"; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "测试"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://zh.wikipedia.org/wiki/条件运算符"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "如果为假"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "如果为真"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "检查“test”中的条件。如果条件为真,则返回“if true”的值,否则,则返回“if false”的值。"; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://zh.wikipedia.org/wiki/算术"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "返回两个数字的和。"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "返回两个数字的商。"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "返回两个数字的区别。"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "返回两个数字的乘积。"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "返回第一个数的第二个数次幂。"; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://zh.wikipedia.org/wiki/%E5%8A%A0%E6%B3%95"; -Blockly.Msg.MATH_CHANGE_TITLE = "更改 %1 由 %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "将一个数添加到变量“%1”。"; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://zh.wikipedia.org/wiki/数学常数"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "返回一个常见常量:π (3.141......),e (2.718...)、φ (1.618...)、 sqrt(2) (1.414......)、sqrt(½) (0.707......)或 ∞(无穷大)。"; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "限制数字 %1 介于 (低) %2 到 (高) %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "限制数字介于两个指定的数字之间"; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "可被整除"; -Blockly.Msg.MATH_IS_EVEN = "是偶数"; -Blockly.Msg.MATH_IS_NEGATIVE = "为负"; -Blockly.Msg.MATH_IS_ODD = "是奇数"; -Blockly.Msg.MATH_IS_POSITIVE = "为正"; -Blockly.Msg.MATH_IS_PRIME = "是质数"; -Blockly.Msg.MATH_IS_TOOLTIP = "如果数字是偶数、奇数、非负整数、正数、负数或如果它可被某数字整除,则返回真或假。"; -Blockly.Msg.MATH_IS_WHOLE = "为整数"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://zh.wikipedia.org/wiki/模除"; -Blockly.Msg.MATH_MODULO_TITLE = "取余数自 %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "返回这两个数字相除后的余数。"; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://zh.wikipedia.org/wiki/数"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "一个数字。"; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "列表中的平均数"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "列表中的最大值"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "列表中位数"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "列表中的最小值"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "列表模式"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "列表的随机项"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "列表中的标准差"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "列表中的数的总和"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "返回列表中的数值的平均值。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "返回列表中最大数。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "返回列表中的中位数。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "返回列表中最小数。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "返回列表中的最常见的项的列表。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "从列表中返回一个随机的元素。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "返回列表的标准偏差。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "返回列表中的所有数字的和。"; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://zh.wikipedia.org/wiki/随机数生成器"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "随机分数"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "返回介于(包含)0.0到1.0之间的随机数。"; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://zh.wikipedia.org/wiki/随机数生成器"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "从 %1 到 %2 之间的随机整数"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "返回两个指定的范围(含)之间的随机整数。"; -Blockly.Msg.MATH_ROUND_HELPURL = "https://zh.wikipedia.org/wiki/数值修约"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "向下舍入"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "向下舍入"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "向上舍入"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "数字向上或向下舍入。"; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://zh.wikipedia.org/wiki/平方根"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "绝对"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "平方根"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "返回一个数的绝对值。"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "返回数的e次幂。"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "返回一个数的自然对数。"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "返回数字的对数。"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "返回数的逻辑非。"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "返回数的10次幂。"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "返回数的平方根。"; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://zh.wikipedia.org/wiki/三角函数"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "返回一个数的反余弦值。"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "返回一个数的反正弦值。"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "返回指定角度的反正切值。"; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "返回指定角度的余弦值(非弧度)。"; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "返回指定角度的正弦值(非弧度)。"; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "返回指定角度的正切值(非弧度)。"; -Blockly.Msg.NEW_VARIABLE = "创建变量..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "新变量的名称:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = "空白"; -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "允许声明"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "与:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://zh.wikipedia.org/wiki/子程序"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "运行用户定义的函数“%1”。"; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://zh.wikipedia.org/wiki/子程序"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "运行用户定义的函数“%1”,并使用它的输出值。"; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "与:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "创建“%1”"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "描述该功能..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = "空白"; -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://zh.wikipedia.org/wiki/子程序"; -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "做点什么"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "至"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "创建一个不带输出值的函数。"; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://zh.wikipedia.org/wiki/子程序"; -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "返回"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "创建一个有输出值的函数。"; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "警告: 此函数具有重复参数。"; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "突出显示函数定义"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "如果值为真,则返回第二个值。"; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "警告: 仅在定义函数内可使用此块。"; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "输入名称:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "添加函数输入。"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "输入"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "添加、删除或重新排此函数的输入。"; -Blockly.Msg.REDO = "重做"; -Blockly.Msg.REMOVE_COMMENT = "删除注释"; -Blockly.Msg.RENAME_VARIABLE = "重命名变量..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "将所有“%1”变量重命名为:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "追加文本"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "在"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "将一些文本追加到变量“%1”。"; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "为小写"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "为首字母大写"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "为大写"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "使用不同的大小写复制这段文字。"; -Blockly.Msg.TEXT_CHARAT_FIRST = "获得第一个字符"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "获得倒数第#个字符"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "获得字符#"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "于文本中"; -Blockly.Msg.TEXT_CHARAT_LAST = "获得最后一个字符"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "获取随机的字母"; -Blockly.Msg.TEXT_CHARAT_TAIL = "空白"; -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "返回位于指定位置的字母。"; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "将一个项添加到文本中。"; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "加入"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "添加、移除或重新排列各节来重新配置这个文本块。"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "到倒数第#个字符"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "到字符#"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "到最后一个字符"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "自文本"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "取得一段字串自第一个字符"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "取得一段字串自倒数第#个字符"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "取得一段字串自#"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = "空白"; -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "返回指定的部分文本。"; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "自文本"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "寻找第一个出现的文本"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "寻找最后一个出现的文本"; -Blockly.Msg.TEXT_INDEXOF_TAIL = "空白"; -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "返回在第二个字串中的第一/最后一个匹配项的索引值。如果未找到则返回%1。"; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1是空的"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "如果提供的文本为空,则返回真。"; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "建立字串使用"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "通过串起任意数量的项以建立一段文字。"; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "%1的长度"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "返回提供文本的字母数(包括空格)。"; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "打印%1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "打印指定的文字、数字或其他值。"; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "提示用户输入数字。"; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "提示用户输入一些文本。"; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "输入数字并显示提示消息"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "输入数字并显示提示消息"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://zh.wikipedia.org/wiki/字符串"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "一个字母、单词或一行文本。"; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "消除两侧空格"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "消除左侧空格"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "消除右侧空格"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "复制这段文字的同时删除两端多余的空格。"; -Blockly.Msg.TODAY = "今天"; -Blockly.Msg.UNDO = "撤销"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "项目"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "创建“设定%1”"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "返回此变量的值。"; -Blockly.Msg.VARIABLES_SET = "赋值 %1 到 %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "创建“获得%1”"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "设置此变量,以使它和输入值相等。"; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "已存在名为“%1”的变量。"; -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/js/zh-hant.js b/backend/_pv_1_3_5/static/blockly/msg/js/zh-hant.js deleted file mode 100755 index 5b92bd2fc..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/js/zh-hant.js +++ /dev/null @@ -1,391 +0,0 @@ -// This file was automatically generated. Do not modify. - -'use strict'; - -goog.provide('Blockly.Msg.zh.hant'); - -goog.require('Blockly.Msg'); - -Blockly.Msg.ADD_COMMENT = "加入註解"; -Blockly.Msg.CHANGE_VALUE_TITLE = "修改值:"; -Blockly.Msg.CLEAN_UP = "清理積木"; -Blockly.Msg.COLLAPSE_ALL = "收合積木"; -Blockly.Msg.COLLAPSE_BLOCK = "收合積木"; -Blockly.Msg.COLOUR_BLEND_COLOUR1 = "顏色 1"; -Blockly.Msg.COLOUR_BLEND_COLOUR2 = "顏色 2"; -Blockly.Msg.COLOUR_BLEND_HELPURL = "http://meyerweb.com/eric/tools/color-blend/"; // untranslated -Blockly.Msg.COLOUR_BLEND_RATIO = "比例"; -Blockly.Msg.COLOUR_BLEND_TITLE = "混合"; -Blockly.Msg.COLOUR_BLEND_TOOLTIP = "透過一個比率 (0.0-1.0)來混合兩種顏色。"; -Blockly.Msg.COLOUR_PICKER_HELPURL = "https://zh.wikipedia.org/wiki/顏色"; -Blockly.Msg.COLOUR_PICKER_TOOLTIP = "從調色板中選擇一種顏色。"; -Blockly.Msg.COLOUR_RANDOM_HELPURL = "http://randomcolour.com"; // untranslated -Blockly.Msg.COLOUR_RANDOM_TITLE = "隨機顏色"; -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = "隨機選擇一種顏色。"; -Blockly.Msg.COLOUR_RGB_BLUE = "藍"; -Blockly.Msg.COLOUR_RGB_GREEN = "綠"; -Blockly.Msg.COLOUR_RGB_HELPURL = "http://www.december.com/html/spec/colorper.html"; // untranslated -Blockly.Msg.COLOUR_RGB_RED = "紅"; -Blockly.Msg.COLOUR_RGB_TITLE = "顏色"; -Blockly.Msg.COLOUR_RGB_TOOLTIP = "透過指定紅、綠、 藍色的值來建立一種顏色。所有的值必須介於 0 和 100 之間。"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks"; // untranslated -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = "停止 迴圈"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = "繼續下一個 迴圈"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = "離開當前的 迴圈"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = "跳過這個迴圈的其餘步驟,並繼續下一次的迴圈運算。"; -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = "警告: 此積木僅可用於迴圈內。"; -Blockly.Msg.CONTROLS_FOREACH_HELPURL = "https://github.com/google/blockly/wiki/Loops#for-each"; // untranslated -Blockly.Msg.CONTROLS_FOREACH_TITLE = "取出每個 %1 自列表 %2"; -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = "遍歷每個列表中的項目,將變數 '%1' 設定到該項目中,然後執行某些語句"; -Blockly.Msg.CONTROLS_FOR_HELPURL = "https://github.com/google/blockly/wiki/Loops#count-with"; // untranslated -Blockly.Msg.CONTROLS_FOR_TITLE = "使用 %1 從範圍 %2 到 %3 每隔 %4"; -Blockly.Msg.CONTROLS_FOR_TOOLTIP = "從起始數到結尾數中取出變數 \"%1\" 的值,按指定的時間間隔,執行指定的積木。"; -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = "將條件添加到'如果'積木。"; -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = "加入一個最終,所有條件下都都執行的區塊到'如果'積木中"; -Blockly.Msg.CONTROLS_IF_HELPURL = "https://github.com/google/blockly/wiki/IfElse"; // untranslated -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = "添加、 刪除或重新排列各區塊來此重新配置這個'如果'積木。"; -Blockly.Msg.CONTROLS_IF_MSG_ELSE = "否則"; -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = "否則如果"; -Blockly.Msg.CONTROLS_IF_MSG_IF = "如果"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = "當值為真時,執行一些語句"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = "當值為真時,執行第一個語句,否則則執行第二個語句"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = "如果第一個值為真,則執行第一個語句。否則當第二個值為真時,則執行第二個語句"; -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = "如果第一個值為真,則執行第一個語句。否則當第二個值為真時,則執行第二個語句。如果前幾個敘述都不為真,則執行最後一個語句"; -Blockly.Msg.CONTROLS_REPEAT_HELPURL = "https://zh.wikipedia.org/wiki/For迴圈"; -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = "執行"; -Blockly.Msg.CONTROLS_REPEAT_TITLE = "重複 %1 次"; -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = "多次執行一些語句"; -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = "https://github.com/google/blockly/wiki/Loops#repeat"; // untranslated -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = "重複 直到"; -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = "重複 當"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = "當值為否時,執行一些語句"; -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = "當值為真時,執行一些語句"; -Blockly.Msg.DELETE_ALL_BLOCKS = "刪除共 %1 塊積木?"; -Blockly.Msg.DELETE_BLOCK = "刪除積木"; -Blockly.Msg.DELETE_VARIABLE = "刪除%1變數"; -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = "刪除%1使用的%2變數?"; -Blockly.Msg.DELETE_X_BLOCKS = "刪除 %1 塊積木"; -Blockly.Msg.DISABLE_BLOCK = "停用積木"; -Blockly.Msg.DUPLICATE_BLOCK = "複製"; -Blockly.Msg.ENABLE_BLOCK = "啟用積木"; -Blockly.Msg.EXPAND_ALL = "展開積木"; -Blockly.Msg.EXPAND_BLOCK = "展開積木"; -Blockly.Msg.EXTERNAL_INPUTS = "多行輸入"; -Blockly.Msg.HELP = "說明"; -Blockly.Msg.INLINE_INPUTS = "單行輸入"; -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-empty-list"; // untranslated -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = "建立空列表"; -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = "返回一個長度為 0 的列表,不包含任何資料記錄"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = "列表"; -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = "添加、 刪除或重新排列各區塊來此重新配置這個 列表 積木。"; -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = "使用這些值建立列表"; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = "將一個項目加入到列表中。"; -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = "建立一個具備任意數量項目的列表。"; -Blockly.Msg.LISTS_GET_INDEX_FIRST = "第一筆"; -Blockly.Msg.LISTS_GET_INDEX_FROM_END = "倒數第#筆"; -Blockly.Msg.LISTS_GET_INDEX_FROM_START = "#"; // untranslated -Blockly.Msg.LISTS_GET_INDEX_GET = "取值"; -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = "取出並移除"; -Blockly.Msg.LISTS_GET_INDEX_LAST = "最後一筆"; -Blockly.Msg.LISTS_GET_INDEX_RANDOM = "隨機"; -Blockly.Msg.LISTS_GET_INDEX_REMOVE = "移除"; -Blockly.Msg.LISTS_GET_INDEX_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = "返回列表中的第一個項目"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = "返回在列表中的指定位置的項目。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = "返回列表中的最後一個項目"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = "返回列表中隨機的一個項目"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = "移除並返回列表中的第一個項目"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = "移除並返回列表中的指定位置的項目。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = "移除並返回列表中的最後一個項目"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = "移除並返回列表中的隨機一個項目"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = "移除列表中的第一個項目"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = "移除在列表中的指定位置的項目。"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = "移除列表中的最後一個項目"; -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = "移除列表中隨機的一個項目"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = "到 倒數 # 位"; -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = "到 #"; -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = "到 最後"; -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-a-sublist"; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = "從 頭 取得子列表"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = "從倒數 # 取得子列表"; -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = "從 # 取得子列表"; -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ""; // untranslated -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = "複製列表中指定的部分。"; -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = "%1 是最後一個項目。"; -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = "%1 是第一個項目。"; -Blockly.Msg.LISTS_INDEX_OF_FIRST = "找出 第一個 項目出現"; -Blockly.Msg.LISTS_INDEX_OF_HELPURL = "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list"; // untranslated -Blockly.Msg.LISTS_INDEX_OF_LAST = "找出 最後一個 項目出現"; -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = "返回在列表中的第一個/最後一個匹配項目的索引值。如果未找到則返回 %1。"; -Blockly.Msg.LISTS_INLIST = "自列表"; -Blockly.Msg.LISTS_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Lists#is-empty"; // untranslated -Blockly.Msg.LISTS_ISEMPTY_TITLE = "%1 值為空"; -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = "如果該列表為空,則返回 真。"; -Blockly.Msg.LISTS_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Lists#length-of"; // untranslated -Blockly.Msg.LISTS_LENGTH_TITLE = "長度 %1"; -Blockly.Msg.LISTS_LENGTH_TOOLTIP = "返回列表的長度。"; -Blockly.Msg.LISTS_REPEAT_HELPURL = "https://github.com/google/blockly/wiki/Lists#create-list-with"; // untranslated -Blockly.Msg.LISTS_REPEAT_TITLE = "建立列表使用項目 %1 重複 %2 次數"; -Blockly.Msg.LISTS_REPEAT_TOOLTIP = "建立包含指定重複次數的 值 的列表。"; -Blockly.Msg.LISTS_SET_INDEX_HELPURL = "https://github.com/google/blockly/wiki/Lists#in-list--set"; // untranslated -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = "為"; -Blockly.Msg.LISTS_SET_INDEX_INSERT = "插入在"; -Blockly.Msg.LISTS_SET_INDEX_SET = "設定"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = "在列表的起始處添加一個項目"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = "插入在列表中的指定位置的項目。"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = "在列表的尾端加入一個項目"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = "在列表中隨機插入項目"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = "設定列表中的第一個項目"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = "設定在列表中的指定位置的項目。"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = "設定列表中的最後一個項目"; -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = "設定列表中隨機的一個項目"; -Blockly.Msg.LISTS_SORT_HELPURL = "https://github.com/google/blockly/wiki/Lists#sorting-a-list"; -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = "升冪排序"; -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = "降冪排序"; -Blockly.Msg.LISTS_SORT_TITLE = "依%1%2%3排序"; -Blockly.Msg.LISTS_SORT_TOOLTIP = "排序清單的複製內容"; -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = "依字母排序並忽略大小寫"; -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = "依數字排序"; -Blockly.Msg.LISTS_SORT_TYPE_TEXT = "依字母排序"; -Blockly.Msg.LISTS_SPLIT_HELPURL = "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists"; // untranslated -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = "從文本製作列表"; -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = "從列表拆出文本"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = "串起文本列表成一個文本,由分隔符分隔。"; -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = "拆分文本到文本列表,按每個分隔符拆分。"; -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = "用分隔符"; -Blockly.Msg.LOGIC_BOOLEAN_FALSE = "否"; -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = "https://github.com/google/blockly/wiki/Logic#values"; // untranslated -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = "返回 真 或 否。"; -Blockly.Msg.LOGIC_BOOLEAN_TRUE = "真"; -Blockly.Msg.LOGIC_COMPARE_HELPURL = "https://zh.wikipedia.org/wiki/不等"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = "如果這兩個輸入區塊內容相等,返回 真。"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = "如果第一個輸入大於第二個輸入,返回 真。"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = "如果第一個輸入大於或等於第二個輸入,返回 真。"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = "如果第一個輸入小於第二個輸入,返回 真。"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = "如果第一個輸入是小於或等於第二個輸入,返回 真。"; -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = "如果這兩個輸入區塊內容不相等,返回 真。"; -Blockly.Msg.LOGIC_NEGATE_HELPURL = "https://github.com/google/blockly/wiki/Logic#not"; // untranslated -Blockly.Msg.LOGIC_NEGATE_TITLE = "非 %1"; -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = "如果輸入的值是 否,則返回 真。如果輸入的值是 真 返回 否。"; -Blockly.Msg.LOGIC_NULL = "空"; -Blockly.Msg.LOGIC_NULL_HELPURL = "https://en.wikipedia.org/wiki/Nullable_type"; // untranslated -Blockly.Msg.LOGIC_NULL_TOOLTIP = "返回 空。"; -Blockly.Msg.LOGIC_OPERATION_AND = "且"; -Blockly.Msg.LOGIC_OPERATION_HELPURL = "https://github.com/google/blockly/wiki/Logic#logical-operations"; // untranslated -Blockly.Msg.LOGIC_OPERATION_OR = "或"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = "如果這兩個輸入值都為 真,則返回 真。"; -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = "如果至少一個輸入的值為 真,返回 真。"; -Blockly.Msg.LOGIC_TERNARY_CONDITION = "測試"; -Blockly.Msg.LOGIC_TERNARY_HELPURL = "https://zh.wikipedia.org/wiki/條件運算符"; -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = "如果為非"; -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = "如果為真"; -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = "檢查 'test' 中的條件。如果條件為 真,將返回 '如果為 真' 值 ;否則,返回 '如果為 否' 的值。"; -Blockly.Msg.MATH_ADDITION_SYMBOL = "+"; // untranslated -Blockly.Msg.MATH_ARITHMETIC_HELPURL = "https://zh.wikipedia.org/wiki/算術"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = "返回兩個數字的總和。"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = "返回兩個數字的商。"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = "返回兩個數字的差。"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = "返回兩個數字的乘積。"; -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = "返回第二個數字的指數的第一個數字。"; -Blockly.Msg.MATH_CHANGE_HELPURL = "https://zh.wikipedia.org/wiki/加法"; -Blockly.Msg.MATH_CHANGE_TITLE = "修改 %1 自 %2"; -Blockly.Msg.MATH_CHANGE_TOOLTIP = "將數字添加到變數 '%1'。"; -Blockly.Msg.MATH_CONSTANT_HELPURL = "https://zh.wikipedia.org/wiki/數學常數"; -Blockly.Msg.MATH_CONSTANT_TOOLTIP = "返回一個的常見常量: π (3.141......),e (2.718...)、 φ (1.618...)、 開方(2) (1.414......)、 開方(½) (0.707......) 或 ∞ (無窮大)。"; -Blockly.Msg.MATH_CONSTRAIN_HELPURL = "https://en.wikipedia.org/wiki/Clamping_%28graphics%29"; // untranslated -Blockly.Msg.MATH_CONSTRAIN_TITLE = "限制數字 %1 介於 (低) %2 到 (高) %3"; -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = "限制數字介於兩個指定的數字之間"; -Blockly.Msg.MATH_DIVISION_SYMBOL = "÷"; // untranslated -Blockly.Msg.MATH_IS_DIVISIBLE_BY = "可被整除"; -Blockly.Msg.MATH_IS_EVEN = "是偶數"; -Blockly.Msg.MATH_IS_NEGATIVE = "是負值"; -Blockly.Msg.MATH_IS_ODD = "是奇數"; -Blockly.Msg.MATH_IS_POSITIVE = "是正值"; -Blockly.Msg.MATH_IS_PRIME = "是質數"; -Blockly.Msg.MATH_IS_TOOLTIP = "如果數字是偶數,奇數,非負整數,正數、 負數或如果它是可被某數字整除,則返回 真 或 否。"; -Blockly.Msg.MATH_IS_WHOLE = "是非負整數"; -Blockly.Msg.MATH_MODULO_HELPURL = "https://zh.wikipedia.org/wiki/模除"; -Blockly.Msg.MATH_MODULO_TITLE = "取餘數自 %1 ÷ %2"; -Blockly.Msg.MATH_MODULO_TOOLTIP = "回傳兩個數字相除的餘數"; -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = "×"; // untranslated -Blockly.Msg.MATH_NUMBER_HELPURL = "https://zh.wikipedia.org/wiki/數"; -Blockly.Msg.MATH_NUMBER_TOOLTIP = "一個數字。"; -Blockly.Msg.MATH_ONLIST_HELPURL = ""; // untranslated -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = "平均值 自列表"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = "最大值 自列表"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = "中位數 自列表"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = "最小值 自列表"; -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = "比較眾數 自列表"; -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = "隨機抽取 自列表"; -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = "標準差 自列表"; -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = "總和 自列表"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = "返回列表中數值的平均值 (算術平均值)。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = "返回列表中的最大數字。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = "返回列表中數值的中位數。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = "返回列表中的最小數字。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = "返回一個列表中的最常見項目的列表。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = "從列表中返回一個隨機的項目。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = "返回列表中數字的標準差。"; -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = "返回列表中的所有數字的總和。"; -Blockly.Msg.MATH_POWER_SYMBOL = "^"; // untranslated -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = "https://zh.wikipedia.org/wiki/隨機數生成器"; -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = "取隨機分數"; -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = "返回介於 (包含) 0.0 到 1.0 之間的隨機數。"; -Blockly.Msg.MATH_RANDOM_INT_HELPURL = "https://zh.wikipedia.org/wiki/隨機數生成器"; -Blockly.Msg.MATH_RANDOM_INT_TITLE = "取隨機整數介於 (低) %1 到 %2"; -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = "回傳限制的數字區間內的隨機數字"; -Blockly.Msg.MATH_ROUND_HELPURL = "https://zh.wikipedia.org/wiki/數值簡化"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = "四捨五入"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = "無條件捨去"; -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = "無條件進位"; -Blockly.Msg.MATH_ROUND_TOOLTIP = "將數字向上或向下舍入。"; -Blockly.Msg.MATH_SINGLE_HELPURL = "https://zh.wikipedia.org/wiki/平方根"; -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = "絕對值"; -Blockly.Msg.MATH_SINGLE_OP_ROOT = "開根號"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = "返回指定數字的絕對值。"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = "返回指定數字指數的 e"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = "返回指定數字的自然對數。"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = "返回指定數字的對數。"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = "返回指定數字的 negation。"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = "返回指定數字指數的10的冪次。"; -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = "返回指定數字的平方根。"; -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = "-"; // untranslated -Blockly.Msg.MATH_TRIG_ACOS = "acos"; // untranslated -Blockly.Msg.MATH_TRIG_ASIN = "asin"; // untranslated -Blockly.Msg.MATH_TRIG_ATAN = "atan"; // untranslated -Blockly.Msg.MATH_TRIG_COS = "cos"; // untranslated -Blockly.Msg.MATH_TRIG_HELPURL = "https://zh.wikipedia.org/wiki/三角函數"; -Blockly.Msg.MATH_TRIG_SIN = "sin"; // untranslated -Blockly.Msg.MATH_TRIG_TAN = "tan"; // untranslated -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = "返回指定角度的反餘弦值(非弧度)。"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = "返回指定角度的反正弦值(非弧度)。"; -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = "返回指定角度的反正切值。"; -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = "返回指定角度的餘弦值(非弧度)。"; -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = "返回指定角度的正弦值(非弧度)。"; -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = "返回指定角度的正切值(非弧度)。"; -Blockly.Msg.NEW_VARIABLE = "建立變數..."; -Blockly.Msg.NEW_VARIABLE_TITLE = "新變數名稱:"; -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ""; // untranslated -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = "允許語句"; -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = "與:"; -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = "https://zh.wikipedia.org/wiki/子程式"; -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = "執行使用者定義的函數 '%1'。"; -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = "https://zh.wikipedia.org/wiki/子程式"; -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = "執行使用者定義的函數 '%1' 並使用它的回傳值"; -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = "與:"; -Blockly.Msg.PROCEDURES_CREATE_DO = "建立 '%1'"; -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = "描述此函數..."; -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ""; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = "流程"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = "到"; -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = "創建一個無回傳值的函數。"; -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29"; // untranslated -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = "回傳"; -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = "創建一個有回傳值的函數。"; -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = "警告: 此函數中有重複的參數。"; -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = "反白顯示函式定義"; -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = "http://c2.com/cgi/wiki?GuardClause"; // untranslated -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = "如果值為 真,則返回第二個值。"; -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = "警告: 此積木僅可在定義函式時使用。"; -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = "變數:"; -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = "添加函數輸入。"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = "參數"; -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = "添加、刪除或重新排列此函數的輸入。"; -Blockly.Msg.REDO = "重試"; -Blockly.Msg.REMOVE_COMMENT = "移除註解"; -Blockly.Msg.RENAME_VARIABLE = "重新命名變數..."; -Blockly.Msg.RENAME_VARIABLE_TITLE = "將所有 \"%1\" 變數重新命名為:"; -Blockly.Msg.TEXT_APPEND_APPENDTEXT = "後加入文字"; -Blockly.Msg.TEXT_APPEND_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_APPEND_TO = "在"; -Blockly.Msg.TEXT_APPEND_TOOLTIP = "將一些文字追加到變數 '%1'。"; -Blockly.Msg.TEXT_CHANGECASE_HELPURL = "https://github.com/google/blockly/wiki/Text#adjusting-text-case"; // untranslated -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = "轉成 小寫"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = "轉成 首字母大寫"; -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = "轉成 大寫"; -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = "使用不同的大小寫複製這段文字。"; -Blockly.Msg.TEXT_CHARAT_FIRST = "取第一個字元"; -Blockly.Msg.TEXT_CHARAT_FROM_END = "取得 倒數第 # 個字元"; -Blockly.Msg.TEXT_CHARAT_FROM_START = "取得 字元 #"; -Blockly.Msg.TEXT_CHARAT_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-text"; // untranslated -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = "的字元在字串"; -Blockly.Msg.TEXT_CHARAT_LAST = "取最後一個字元"; -Blockly.Msg.TEXT_CHARAT_RANDOM = "取隨機一個字元"; -Blockly.Msg.TEXT_CHARAT_TAIL = ""; -Blockly.Msg.TEXT_CHARAT_TOOLTIP = "返回位於指定位置的字元。"; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = "將一個項目加入到字串中。"; -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = "加入"; -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = "添加、 刪除或重新排列各區塊來此重新配置這個文字積木。"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = "到 倒數第 # 個字元"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = "到 字元 #"; -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = "到 最後一個字元"; -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text"; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = "自字串"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = "取得一段字串 自 第一個字元"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = "取得一段字串自 #"; -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = "取得一段字串自 #"; -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ""; // untranslated -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = "返回指定的部分文字。"; -Blockly.Msg.TEXT_INDEXOF_HELPURL = "https://github.com/google/blockly/wiki/Text#finding-text"; // untranslated -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = "在字串"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = "尋找 第一個 出現的字串"; -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = "尋找 最後一個 出現的字串"; -Blockly.Msg.TEXT_INDEXOF_TAIL = ""; // untranslated -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = "返回在第二個字串中的第一個/最後一個匹配項目的索引值。如果未找到則返回 %1。"; -Blockly.Msg.TEXT_ISEMPTY_HELPURL = "https://github.com/google/blockly/wiki/Text#checking-for-empty-text"; // untranslated -Blockly.Msg.TEXT_ISEMPTY_TITLE = "%1 為空"; -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = "如果提供的字串為空,則返回 真。"; -Blockly.Msg.TEXT_JOIN_HELPURL = "https://github.com/google/blockly/wiki/Text#text-creation"; // untranslated -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = "建立字串使用"; -Blockly.Msg.TEXT_JOIN_TOOLTIP = "通過串起任意數量的項目來建立一段文字。"; -Blockly.Msg.TEXT_LENGTH_HELPURL = "https://github.com/google/blockly/wiki/Text#text-modification"; // untranslated -Blockly.Msg.TEXT_LENGTH_TITLE = "長度 %1"; -Blockly.Msg.TEXT_LENGTH_TOOLTIP = "返回這串文字的字元數(含空格) 。"; -Blockly.Msg.TEXT_PRINT_HELPURL = "https://github.com/google/blockly/wiki/Text#printing-text"; // untranslated -Blockly.Msg.TEXT_PRINT_TITLE = "印出 %1"; -Blockly.Msg.TEXT_PRINT_TOOLTIP = "印出指定的文字、 數字或其他值。"; -Blockly.Msg.TEXT_PROMPT_HELPURL = "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user"; // untranslated -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = "輸入數字"; -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = "輸入文字"; -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = "輸入 數字 並顯示提示訊息"; -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = "輸入 文字 並顯示提示訊息"; -Blockly.Msg.TEXT_TEXT_HELPURL = "https://zh.wikipedia.org/wiki/字串"; -Blockly.Msg.TEXT_TEXT_TOOLTIP = "字元、 單詞或一行文字。"; -Blockly.Msg.TEXT_TRIM_HELPURL = "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces"; // untranslated -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = "消除兩側空格"; -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = "消除左側空格"; -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = "消除右側空格"; -Blockly.Msg.TEXT_TRIM_TOOLTIP = "複製這段文字的同時刪除兩端多餘的空格。"; -Blockly.Msg.TODAY = "今天"; -Blockly.Msg.UNDO = "還原"; -Blockly.Msg.VARIABLES_DEFAULT_NAME = "變數"; -Blockly.Msg.VARIABLES_GET_CREATE_SET = "建立 '設定 %1'"; -Blockly.Msg.VARIABLES_GET_HELPURL = "https://github.com/google/blockly/wiki/Variables#get"; // untranslated -Blockly.Msg.VARIABLES_GET_TOOLTIP = "返回此變數的值。"; -Blockly.Msg.VARIABLES_SET = "賦值 %1 到 %2"; -Blockly.Msg.VARIABLES_SET_CREATE_GET = "建立 '取得 %1'"; -Blockly.Msg.VARIABLES_SET_HELPURL = "https://github.com/google/blockly/wiki/Variables#set"; // untranslated -Blockly.Msg.VARIABLES_SET_TOOLTIP = "設定此變數,好和輸入值相等。"; -Blockly.Msg.VARIABLE_ALREADY_EXISTS = "一個名為%1的變數已存在。"; -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/ar.json b/backend/_pv_1_3_5/static/blockly/msg/json/ar.json deleted file mode 100755 index 0c2b413e3..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/ar.json +++ /dev/null @@ -1,316 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Meno25", - "Test Create account", - "아라", - "Diyariq", - "محمد أحمد عبد الفتاح", - "Moud hosny" - ] - }, - "VARIABLES_DEFAULT_NAME": "البند", - "TODAY": "اليوم", - "DUPLICATE_BLOCK": "ادمج", - "ADD_COMMENT": "اضافة تعليق", - "REMOVE_COMMENT": "ازل التعليق", - "EXTERNAL_INPUTS": "ادخال خارجي", - "INLINE_INPUTS": "ادخال خطي", - "DELETE_BLOCK": "إحذف القطعة", - "DELETE_X_BLOCKS": "إحذف قطع %1", - "DELETE_ALL_BLOCKS": "حذف كل مناعات %1؟", - "COLLAPSE_BLOCK": "إخفاء القطعة", - "COLLAPSE_ALL": "إخفاء القطع", - "EXPAND_BLOCK": "وسٌّع القطعة", - "EXPAND_ALL": "وسٌّع القطع", - "DISABLE_BLOCK": "عطّل القطعة", - "ENABLE_BLOCK": "أعد تفعيل القطعة", - "HELP": "مساعدة", - "UNDO": "رجوع", - "CHANGE_VALUE_TITLE": "تغيير قيمة:", - "RENAME_VARIABLE": "إعادة تسمية المتغير...", - "RENAME_VARIABLE_TITLE": "إعادة تسمية كافة المتغيرات '%1' إلى:", - "NEW_VARIABLE": "متغير جديد...", - "NEW_VARIABLE_TITLE": "اسم المتغير الجديد:", - "VARIABLE_ALREADY_EXISTS": "المتغير '%1' موجود بالفعل", - "COLOUR_PICKER_HELPURL": "https://ar.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "اختر لون من اللوحة.", - "COLOUR_RANDOM_TITLE": "لون عشوائي", - "COLOUR_RANDOM_TOOLTIP": "اختر لون بشكل عشوائي.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "لون مع", - "COLOUR_RGB_RED": "أحمر", - "COLOUR_RGB_GREEN": "أخضر", - "COLOUR_RGB_BLUE": "أزرق", - "COLOUR_RGB_TOOLTIP": "إنشئ لون بالكمية المحددة من الأحمر, الأخضر والأزرق. بحيث يجب تكون كافة القيم بين 0 و 100.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "دمج", - "COLOUR_BLEND_COLOUR1": "اللون 1", - "COLOUR_BLEND_COLOUR2": "اللون 2", - "COLOUR_BLEND_RATIO": "نسبة", - "COLOUR_BLEND_TOOLTIP": "دمج لونين ببعضهما البعض بنسبة (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "كرر %1 مرات", - "CONTROLS_REPEAT_INPUT_DO": "نفّذ", - "CONTROLS_REPEAT_TOOLTIP": "نفّذ بعض الأوامر عدة مرات.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "اكرّر طالما", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "اكرّر حتى", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "بما ان القيمة صحيحة, نفّذ بعض الأوامر.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "بما ان القيمة خاطئة, نفّذ بعض الأوامر.", - "CONTROLS_FOR_TOOLTIP": "اجعل المتغير %1 يأخذ القيم من رقم البداية الى رقم النهاية، قم بالعد داخل المجال المحدد، وطبق أوامر القطع المحددة.", - "CONTROLS_FOR_TITLE": "عد بـ %1 من %2 إلى %3 بمعدل %4", - "CONTROLS_FOREACH_TITLE": "لكل عنصر %1 في قائمة %2", - "CONTROLS_FOREACH_TOOLTIP": "لكل عنصر في قائمة ما، عين المتغير '%1' لهذا الغنصر، ومن ثم نفذ بعض الأوامر.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "اخرج من الحلقة", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "استمر ابتداءا من التكرار التالي من الحلقة", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "اخرج من الحلقة الحالية.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "تخط ما تبقى من هذه الحلقة، واستمر ابتداءا من التكرار التالي.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "تحذير: يمكن استخدام هذه القطعة فقط داخل حلقة.", - "CONTROLS_IF_TOOLTIP_1": "إذا كانت قيمة ما تساوي صحيح, إذن قم بتنفيذ أمر ما.", - "CONTROLS_IF_TOOLTIP_2": "إذا كانت قيمة ما تساوي \"صحيح\"، إذن قم بتنفيذ أول قطعة من الأوامر. والا ،قم بتنفيذ القطعة الثانية من الأوامر.", - "CONTROLS_IF_TOOLTIP_3": "إذا كانت القيمة الأولى تساوي \"صحيح\", إذن قم بتنفيذ القطعة الأولى من الأوامر. والا, إذا كانت القيمة الثانية تساوي \"صحيح\", قم بتنفيذ القطعة الثانية من الأوامر.", - "CONTROLS_IF_TOOLTIP_4": "إذا كانت القيمة الأولى تساوي \"صحيح\", إذن قم بتنفيذ القطعة الأولى من الأوامر. والا , إذا كانت القيمة الثانية تساوي \"صحيح\", قم بتنفيذ القطعة الثانية من الأوامر. إذا لم تكن هناك أي قيمة تساوي صحيح, قم بتنفيذ آخر قطعة من الأوامر.", - "CONTROLS_IF_MSG_IF": "إذا", - "CONTROLS_IF_MSG_ELSEIF": "وإﻻ إذا", - "CONTROLS_IF_MSG_ELSE": "والا", - "CONTROLS_IF_IF_TOOLTIP": "أضف, إزل, أو أعد ترتيب المقاطع لإعادة تكوين القطعة الشرطية \"إذا\".", - "CONTROLS_IF_ELSEIF_TOOLTIP": "إضف شرطا إلى القطعة الشرطية \"إذا\".", - "CONTROLS_IF_ELSE_TOOLTIP": "أضف شرط \"نهاية، إجمع\" إلى القطعة الشرطية \"إذا\".", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "يرجع صحيح إذا كان كلا المدخلات مساوية بعضها البعض.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "يرجع صحيح إذا كانت كلا المدخلات غير مساوية لبعضها البعض.", - "LOGIC_COMPARE_TOOLTIP_LT": "يرجع صحيح إذا كان الإدخال الأول أصغر من الإدخال الثاني.", - "LOGIC_COMPARE_TOOLTIP_LTE": "يرجع صحيح إذا كان الإدخال الأول أصغر من أو يساوي الإدخال الثاني.", - "LOGIC_COMPARE_TOOLTIP_GT": "يرجع صحيح إذا كان الإدخال الأول أكبر من الإدخال الثاني.", - "LOGIC_COMPARE_TOOLTIP_GTE": "يرجع صحيح إذا كان الإدخال الأول أكبر من أو يساوي الإدخال الثاني.", - "LOGIC_OPERATION_TOOLTIP_AND": "ترجع صحيح إذا كان كلا المٌدخلات صحيح.", - "LOGIC_OPERATION_AND": "و", - "LOGIC_OPERATION_TOOLTIP_OR": "ترجع صحيح إذا كان واحد على الأقل من المدخلات صحيح.", - "LOGIC_OPERATION_OR": "أو", - "LOGIC_NEGATE_TITLE": "ليس من %1", - "LOGIC_NEGATE_TOOLTIP": "يرجع صحيح إذا كان الإدخال خاطئ . يرجع خاطئ إذا كان الإدخال صحيح.", - "LOGIC_BOOLEAN_TRUE": "صحيح", - "LOGIC_BOOLEAN_FALSE": "خاطئ", - "LOGIC_BOOLEAN_TOOLTIP": "يرجع صحيح أو خاطئ.", - "LOGIC_NULL_HELPURL": "https://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "ملغى", - "LOGIC_NULL_TOOLTIP": "ترجع ملغى.", - "LOGIC_TERNARY_HELPURL": "https://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "اختبار", - "LOGIC_TERNARY_IF_TRUE": "إذا كانت العبارة صحيحة", - "LOGIC_TERNARY_IF_FALSE": "إذا كانت العبارة خاطئة", - "LOGIC_TERNARY_TOOLTIP": "تحقق الشرط في 'الاختبار'. إذا كان الشرط صحيح، يقوم بإرجاع قيمة 'اذا كانت العبارة صحيحة'؛ خلاف ذلك يرجع قيمة 'اذا كانت العبارة خاطئة'.", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "عدد ما.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "جيب", - "MATH_TRIG_COS": "جيب تمام", - "MATH_TRIG_TAN": "ظل", - "MATH_TRIG_ASIN": "asin", - "MATH_TRIG_ACOS": "acos", - "MATH_TRIG_ATAN": "atan", - "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/Arithmetic", - "MATH_ARITHMETIC_TOOLTIP_ADD": "يرجع مجموع الرقمين.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "يرجع الفرق بين الرقمين.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "يرجع حاصل ضرب الرقمين.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "يرجع حاصل قسمة الرقمين.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "يرجع الرقم الأول مرفوع إلى تربيع الرقم الثاني.", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "الجذر التربيعي", - "MATH_SINGLE_TOOLTIP_ROOT": "يرجع الجذر التربيعي للرقم.", - "MATH_SINGLE_OP_ABSOLUTE": "مطلق", - "MATH_SINGLE_TOOLTIP_ABS": "يرجع القيمة المطلقة لرقم.", - "MATH_SINGLE_TOOLTIP_NEG": "يرجع عدد سالب.", - "MATH_SINGLE_TOOLTIP_LN": "يرجع اللوغاريتم الطبيعي لرقم.", - "MATH_SINGLE_TOOLTIP_LOG10": "يرجع لوغاريتم عدد معين للاساس 10.", - "MATH_SINGLE_TOOLTIP_EXP": "يرجع e الذي هو الاس المرفوع للرقم.", - "MATH_SINGLE_TOOLTIP_POW10": "يرجع مضروب الرقم 10 في نفسه .", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "يرجع جيب التمام لدرجة (لا زواية نصف قطرية).", - "MATH_TRIG_TOOLTIP_COS": "يرجع جيب التمام لدرجة (لا زواية نصف قطرية).", - "MATH_TRIG_TOOLTIP_TAN": "يرجع الظل لدرجة (لا دائرة نصف قطرية).", - "MATH_TRIG_TOOLTIP_ASIN": "يرجع قوس الجيب للرقم.", - "MATH_TRIG_TOOLTIP_ACOS": "يرجع قوس جيب التمام لرقم.", - "MATH_TRIG_TOOLTIP_ATAN": "يرجع قوس الظل للرقم.", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "ير جع واحد من الثوابت الشائعة : π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).", - "MATH_IS_EVEN": "هو زوجي", - "MATH_IS_ODD": "هو فرذي", - "MATH_IS_PRIME": "هو أولي", - "MATH_IS_WHOLE": "هو صحيح", - "MATH_IS_POSITIVE": "هو موجب", - "MATH_IS_NEGATIVE": "هو سالب", - "MATH_IS_DIVISIBLE_BY": "قابل للقسمة", - "MATH_IS_TOOLTIP": "تحقق إذا كان عدد ما زوجيا، فرذيا, أوليا، صحيحا،موجبا أو سالبا، أو إذا كان قابلا للقسمة على عدد معين. يرجع صحيح أو خاطئ.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "غير %1 بـ %2", - "MATH_CHANGE_TOOLTIP": "إضف رقم إلى متغير '%1'.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "تقريب الى اكبر عدد صحيح أو الى اصغر عدد صحيح.", - "MATH_ROUND_OPERATOR_ROUND": "تقريب", - "MATH_ROUND_OPERATOR_ROUNDUP": "تقريب الى اكبر عدد صحيح", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "تقريب إلى اصغر عدد صحيح", - "MATH_ONLIST_OPERATOR_SUM": "مجموع القائمة", - "MATH_ONLIST_TOOLTIP_SUM": "يرجع مجموع كافة الأرقام الموجودة في القائمة.", - "MATH_ONLIST_OPERATOR_MIN": "الحد الأدنى من قائمة", - "MATH_ONLIST_TOOLTIP_MIN": "يرجع أصغر رقم في القائمة.", - "MATH_ONLIST_OPERATOR_MAX": "الحد الأقصى لقائمة", - "MATH_ONLIST_TOOLTIP_MAX": "يرجع أكبر عدد في القائمة.", - "MATH_ONLIST_OPERATOR_AVERAGE": "متوسط القائمة", - "MATH_ONLIST_TOOLTIP_AVERAGE": "يرجع المعدل (الوسط الحسابي) للقيم الرقمية في القائمة.", - "MATH_ONLIST_OPERATOR_MEDIAN": "متوسط القائمة", - "MATH_ONLIST_TOOLTIP_MEDIAN": "يرجع وسيط العدد في القائمة.", - "MATH_ONLIST_OPERATOR_MODE": "منوال القائمة", - "MATH_ONLIST_TOOLTIP_MODE": "يرجع قائمة من العنصر أو العناصر الأكثر شيوعاً في القائمة.", - "MATH_ONLIST_OPERATOR_STD_DEV": "الانحراف المعياري للقائمة", - "MATH_ONLIST_TOOLTIP_STD_DEV": "يرجع الانحراف المعياري للقائمة.", - "MATH_ONLIST_OPERATOR_RANDOM": "عنصر عشوائي من القائمة", - "MATH_ONLIST_TOOLTIP_RANDOM": "يرجع عنصر عشوائي من القائمة.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "باقي %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "يرجع الباقي من قسمة الرقمين.", - "MATH_CONSTRAIN_TITLE": "تقيد %1 منخفض %2 مرتفع %3", - "MATH_CONSTRAIN_TOOLTIP": "تقييد العددليكون بين الحدود المحددة (ضمناً).", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": " عدد صحيح عشوائي من %1 إلى %2", - "MATH_RANDOM_INT_TOOLTIP": "يرجع عدد صحيح عشوائي بين حدين محددين, ضمنيا.", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "كسر عشوائي", - "MATH_RANDOM_FLOAT_TOOLTIP": "يرجع جزء عشوائي بين 0.0 (ضمنياً) و 1.0 (خارجيا).", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "حرف أو كلمة أو سطر من النص.", - "TEXT_JOIN_TITLE_CREATEWITH": "انشئ نص مع", - "TEXT_JOIN_TOOLTIP": "أنشئ جزء من النص بالصاق أي عدد من العناصر ببعضها البعض.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "الانضمام إلى", - "TEXT_CREATE_JOIN_TOOLTIP": "أضف, إحذف, أو أعد ترتيب المقاطع لإعادة تكوين النص من القطع التالية.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "إضف عنصر إلى النص.", - "TEXT_APPEND_TO": "إلى", - "TEXT_APPEND_APPENDTEXT": "إلصق نص", - "TEXT_APPEND_TOOLTIP": "إلصق جزءا من النص إلى متغير '%1'.", - "TEXT_LENGTH_TITLE": "طول %1", - "TEXT_LENGTH_TOOLTIP": "تقوم بإرجاع عدد الاحرف (بما في ذلك الفراغات) في النص المقدم.", - "TEXT_ISEMPTY_TITLE": "%1 فارغ", - "TEXT_ISEMPTY_TOOLTIP": "يرجع \"صحيح\" إذا كان النص المقدم فارغ.", - "TEXT_INDEXOF_TOOLTIP": "تقوم بإرجاع مؤشر التواجد الأول/الأخير للنص الأول في النص الثاني. تقوم بإرجاع %1 إذا لم يتم العثور على النص.", - "TEXT_INDEXOF_INPUT_INTEXT": "في النص", - "TEXT_INDEXOF_OPERATOR_FIRST": "ابحث عن التواجد الأول للنص", - "TEXT_INDEXOF_OPERATOR_LAST": "ابحث عن التواجد الأخير للنص", - "TEXT_CHARAT_INPUT_INTEXT": "في النص", - "TEXT_CHARAT_FROM_START": "الحصول على الحرف #", - "TEXT_CHARAT_FROM_END": "الحصول على الحرف # من نهاية", - "TEXT_CHARAT_FIRST": "احصل على الحرف الأول", - "TEXT_CHARAT_LAST": "احصل على آخر حرف", - "TEXT_CHARAT_RANDOM": "الحصول على حرف عشوائي", - "TEXT_CHARAT_TOOLTIP": "يرجع حرف ما في الموضع المحدد.", - "TEXT_GET_SUBSTRING_TOOLTIP": "يرجع جزء معين من النص.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "في النص", - "TEXT_GET_SUBSTRING_START_FROM_START": "الحصول على سلسلة حروف فرعية من الحرف #", - "TEXT_GET_SUBSTRING_START_FROM_END": "الحصول على سلسلة حروف فرعية من الحرف # من نهاية", - "TEXT_GET_SUBSTRING_START_FIRST": "الحصول على سلسلة فرعية من الحرف الأول", - "TEXT_GET_SUBSTRING_END_FROM_START": "إلى حرف #", - "TEXT_GET_SUBSTRING_END_FROM_END": "إلى حرف # من نهاية", - "TEXT_GET_SUBSTRING_END_LAST": "إلى آخر حرف", - "TEXT_CHANGECASE_TOOLTIP": "يرجع نسخة من النص في حالة مختلفة.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "الى حروف كبيرة", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "الى حروف صغيرة", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "الى حروف العنوان", - "TEXT_TRIM_TOOLTIP": "يرجع نسخة من النص مع حذف من أحد أو كلا الفراغات من أطرافه.", - "TEXT_TRIM_OPERATOR_BOTH": "إزالة الفراغات من كلا الجانبين", - "TEXT_TRIM_OPERATOR_LEFT": "إزالة الفراغات من الجانب الأيسر من", - "TEXT_TRIM_OPERATOR_RIGHT": "إزالة الفراغات من الجانب الأيمن من", - "TEXT_PRINT_TITLE": "اطبع %1", - "TEXT_PRINT_TOOLTIP": "اطبع النص المحدد أو العدد أو قيمة أخرى.", - "TEXT_PROMPT_TYPE_TEXT": "انتظر ادخال المستخدم لنص ما مع اظهار رسالة", - "TEXT_PROMPT_TYPE_NUMBER": "انتظر ادخال المستخدم لرقم ما مع اظهار رسالة", - "TEXT_PROMPT_TOOLTIP_NUMBER": "انتظر ادخال المستخذم لرقم ما.", - "TEXT_PROMPT_TOOLTIP_TEXT": "انتظر ادخال المستخدم لنص ما.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "إنشئ قائمة فارغة", - "LISTS_CREATE_EMPTY_TOOLTIP": "تقوم بإرجاع قائمة، طولها 0, لا تحتوي على أية سجلات البيانات", - "LISTS_CREATE_WITH_TOOLTIP": "أنشيء قائمة من أي عدد من العناصر.", - "LISTS_CREATE_WITH_INPUT_WITH": "أتشئ قائمة مع", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "قائمة", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "أضف, إزل, أو أعد ترتيب المقاطع لإعادة تكوين القطعة قائمة القطع التالية.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "أضف عنصرا إلى القائمة.", - "LISTS_REPEAT_TOOLTIP": "انشئ قائمة تتألف من القيمة المعطاة متكررة لعدد محدد من المرات.", - "LISTS_REPEAT_TITLE": "إنشئ قائمة مع العنصر %1 %2 مرات", - "LISTS_LENGTH_TITLE": "الطول من %1", - "LISTS_LENGTH_TOOLTIP": "تقوم بإرجاع طول قائمة.", - "LISTS_ISEMPTY_TITLE": "%1 فارغ", - "LISTS_ISEMPTY_TOOLTIP": "يرجع \"صحيح\" إذا كانت القائمة فارغة.", - "LISTS_INLIST": "في قائمة", - "LISTS_INDEX_OF_FIRST": "ابحث على على التواجد الأول للعنصر", - "LISTS_INDEX_OF_LAST": "ابحث على التواجد الأخير للعنصر", - "LISTS_INDEX_OF_TOOLTIP": "تقوم بإرجاع مؤشر التواجد الأول/الأخير في القائمة. تقوم بإرجاع %1 إذا لم يتم العثور على النص.", - "LISTS_GET_INDEX_GET": "احصل على", - "LISTS_GET_INDEX_GET_REMOVE": "احصل على و ازل", - "LISTS_GET_INDEX_REMOVE": "ازل", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# من نهاية", - "LISTS_GET_INDEX_FIRST": "أول", - "LISTS_GET_INDEX_LAST": "أخير", - "LISTS_GET_INDEX_RANDOM": "عشوائي", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 هو العنصر الأول.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 هو العنصر الأخير.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "يقوم بإرجاع العنصر في الموضع المحدد في قائمة ما.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "يرجع العنصر الأول في قائمة ما.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "يرجع العنصر الأخير في قائمة ما.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "يرجع عنصرا عشوائيا في قائمة.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "يزيل ويقوم بإرجاع العنصر في الموضع المحدد في قائمة ما.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "يزيل ويرجع العنصر الأول في قائمة.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "يزيل ويرجع العنصر الأخير في قائمة ما.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "يزيل و يرجع عنصرا عشوائيا في قائمة ما.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "يزيل العنصر الموجود في الموضع المحدد في قائمة ما.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "يزيل العنصر الأول في قائمة ما.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "يزيل العنصر الأخير في قائمة ما.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "يزيل عنصرا عشوائيا في قائمة ما.", - "LISTS_SET_INDEX_SET": "تعيين", - "LISTS_SET_INDEX_INSERT": "أدخل في", - "LISTS_SET_INDEX_INPUT_TO": "مثل", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "يحدد العنصر في الموضع المحدد في قائمة ما.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "يحدد العنصر الأول في قائمة.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "يحدد العنصر الأخير في قائمة.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "يحدد عنصرا عشوائيا في قائمة.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "يقوم بإدخال العنصر في الموضع المحدد في قائمة ما.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "يقوم بإدراج هذا العنصر في بداية قائمة.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "ألصق هذا العنصر بنهاية قائمة.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "ادخل العنصر عشوائياً في القائمة.", - "LISTS_GET_SUBLIST_START_FROM_START": "احصل على قائمة فرعية من #", - "LISTS_GET_SUBLIST_START_FROM_END": "احصل على قائمة فرعية من # من نهاية", - "LISTS_GET_SUBLIST_START_FIRST": "احصل على قائمة فرعية من الأول", - "LISTS_GET_SUBLIST_END_FROM_START": "إلى #", - "LISTS_GET_SUBLIST_END_FROM_END": "إلى # من نهاية", - "LISTS_GET_SUBLIST_END_LAST": "إلى الأخير", - "LISTS_GET_SUBLIST_TOOLTIP": "يقوم بإنشاء نسخة من الجزء المحدد من قائمة ما.", - "LISTS_SPLIT_LIST_FROM_TEXT": "إعداد قائمة من النصوص", - "LISTS_SPLIT_TEXT_FROM_LIST": "إعداد نص من القائمة", - "VARIABLES_GET_TOOLTIP": "يرجع قيمة هذا المتغير.", - "VARIABLES_GET_CREATE_SET": "انشئ 'التعيين %1'", - "VARIABLES_SET": "تعيين %1 إلى %2", - "VARIABLES_SET_TOOLTIP": "تعيين هذا المتغير لتكون مساوية للقيمة المدخلة.", - "VARIABLES_SET_CREATE_GET": "انشئ 'احصل على %1'", - "PROCEDURES_DEFNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFNORETURN_TITLE": "إلى", - "PROCEDURES_DEFNORETURN_PROCEDURE": "القيام بشيء ما", - "PROCEDURES_BEFORE_PARAMS": "مع:", - "PROCEDURES_CALL_BEFORE_PARAMS": "مع:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "انشئ دالة بدون مخرجات .", - "PROCEDURES_DEFRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFRETURN_RETURN": "يرجع", - "PROCEDURES_DEFRETURN_TOOLTIP": "انشئ دالة مع المخرجات.", - "PROCEDURES_DEF_DUPLICATE_WARNING": "تحذير: هذه الدالة تحتوي على معلمات مكررة.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "تشغيل الدالة المعرفة من قبل المستخدم '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "تشغيل الدالة المعرفة من قبل المستخدم %1 واستخدام مخرجاتها.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "المدخلات", - "PROCEDURES_MUTATORARG_TITLE": "اسم الإدخال:", - "PROCEDURES_HIGHLIGHT_DEF": "تسليط الضوء على تعريف الدالة", - "PROCEDURES_CREATE_DO": "إنشئ '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "إذا كانت القيمة صحيحة ، اذان قم بارجاع القيمة الثانية.", - "PROCEDURES_IFRETURN_WARNING": "تحذير:هذه القطعة تستخدم فقط داخل تعريف دالة." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/az.json b/backend/_pv_1_3_5/static/blockly/msg/json/az.json deleted file mode 100755 index 14636929e..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/az.json +++ /dev/null @@ -1,296 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Cekli829", - "AZISS" - ] - }, - "VARIABLES_DEFAULT_NAME": "element", - "TODAY": "Bugün", - "DUPLICATE_BLOCK": "Dublikat", - "ADD_COMMENT": "Şərh əlavə et", - "REMOVE_COMMENT": "Şərhi sil", - "EXTERNAL_INPUTS": "Xarici girişlər", - "INLINE_INPUTS": "Sətiriçi girişlər", - "DELETE_BLOCK": "Bloku sil", - "DELETE_X_BLOCKS": "%1 bloku sil", - "DELETE_ALL_BLOCKS": "Bütün %1 blok silinsin?", - "CLEAN_UP": "Blokları təmizlə", - "COLLAPSE_BLOCK": "Bloku yığ", - "COLLAPSE_ALL": "Blokları yığ", - "EXPAND_BLOCK": "Bloku aç", - "EXPAND_ALL": "Blokları aç", - "DISABLE_BLOCK": "Bloku söndür", - "ENABLE_BLOCK": "Bloku aktivləşdir", - "HELP": "Kömək", - "CHANGE_VALUE_TITLE": "Qiyməti dəyiş:", - "RENAME_VARIABLE": "Dəyişənin adını dəyiş...", - "RENAME_VARIABLE_TITLE": "Bütün '%1' dəyişənlərinin adını buna dəyiş:", - "NEW_VARIABLE": "Yeni dəyişən...", - "NEW_VARIABLE_TITLE": "Yeni dəyişənin adı:", - "COLOUR_PICKER_HELPURL": "https://az.wikipedia.org/wiki/Rəng", - "COLOUR_PICKER_TOOLTIP": "Palitradan bir rəng seçin.", - "COLOUR_RANDOM_TITLE": "təsadüfi rəng", - "COLOUR_RANDOM_TOOLTIP": "Təsadüfi bir rəng seçin.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "rənglə", - "COLOUR_RGB_RED": "qırmızı", - "COLOUR_RGB_GREEN": "yaşıl", - "COLOUR_RGB_BLUE": "mavi", - "COLOUR_RGB_TOOLTIP": "Qırmızı, yaşıl və mavinin göstərilən miqdarı ilə bir rəng düzəlt. Bütün qiymətlər 0 ilə 100 arasında olmalıdır.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "qarışdır", - "COLOUR_BLEND_COLOUR1": "rəng 1", - "COLOUR_BLEND_COLOUR2": "rəng 2", - "COLOUR_BLEND_RATIO": "nisbət", - "COLOUR_BLEND_TOOLTIP": "İki rəngi verilmiş nisbətdə (0,0 - 1,0) qarışdırır.", - "CONTROLS_REPEAT_HELPURL": "https://az.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "%1 dəfə təkrar et", - "CONTROLS_REPEAT_INPUT_DO": "icra et", - "CONTROLS_REPEAT_TOOLTIP": "Bəzi əmrləri bir neçə dəfə yerinə yetir.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "təkrar et, hələ ki", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "təkrar et, ta ki", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Hələ ki, qiymət \"doğru\"dur, bəzi əmrləri yerinə yetir.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Hələ ki, qiymət \"yalan\"dır, bəzi əmrləri yerinə yetir.", - "CONTROLS_FOR_TOOLTIP": "\"%1\" dəyişəni başlanğıc ədəddən son ədədə qədər göstərilən aralıqla qiymətlər aldıqca göstərilən blokları yerinə yetir.", - "CONTROLS_FOR_TITLE": "say: %1 %2 ilə başlayıb, %3 qiymətinə kimi %4 qədər dəyiş", - "CONTROLS_FOREACH_TITLE": "hər element üçün %1 siyahıda %2", - "CONTROLS_FOREACH_TOOLTIP": "Siyahıdakı hər element üçün \"%1\" dəyişənini elementə mənimsət və bundan sonra bəzi əmrləri yerinə yetir.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "dövrdən çıx", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "dövrün növbəti addımından davam et", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Cari dövrdən çıx.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Bu dövrün qalanını ötür və növbəti addımla davam et.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Xəbərdarlıq: Bu blok ancaq dövr daxilində istifadə oluna bilər.", - "CONTROLS_IF_TOOLTIP_1": "Əgər qiymət doğrudursa, onda bəzi əmrləri yerinə yetir.", - "CONTROLS_IF_TOOLTIP_2": "Əgər qiymət doğrudursa, onda birinci əmrlər blokunu yerinə yetir. Əks halda isə ikinci əmrlər blokunu yerinə yetir.", - "CONTROLS_IF_TOOLTIP_3": "Əgər birinci qiymət doğrudursa, onda birinci əmrlər blokunu yerinə yetir. Əks halda əgər ikinci qiymət doğrudursa, onda ikinci əmrlər blokunu yerinə yetir.", - "CONTROLS_IF_TOOLTIP_4": "Əgər birinci qiymət doğrudursa, onda birinci əmrlər blokunu yerinə yetir. Əks halda əgər ikinci qiymət doğrudursa, onda ikinci əmrlər blokunu yerinə yetir. Əgər qiymətlərdən heç biri doğru deyilsə, onda axırıncı əmrlər blokunu yerinə yetir.", - "CONTROLS_IF_MSG_IF": "əgər", - "CONTROLS_IF_MSG_ELSEIF": "əks halda əgər", - "CONTROLS_IF_MSG_ELSE": "əks halda", - "CONTROLS_IF_IF_TOOLTIP": "Bu \"əgər\" blokunu dəyişdirmək üçün bölümlərin yenisini əlavə et, sil və ya yerini dəyiş.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "\"Əgər\" blokuna bir şərt əlavə et.", - "CONTROLS_IF_ELSE_TOOLTIP": "\"Əgər\" blokuna qalan bütün halları əhatə edəb son bir şərt əlavə et.", - "LOGIC_COMPARE_HELPURL": "https://az.wikipedia.org/wiki/bərabərsizlik_(riyazi)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Girişlər bir birinə bərabərdirsə \"doğru\" cavabını qaytarır.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Girişlər bərabər deyillərsə \"doğru\" cavabını qaytarır.", - "LOGIC_COMPARE_TOOLTIP_LT": "Birinci giriş ikincidən kiçikdirsə \"doğru\" cavabını qaytarır.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Birinci giriş ikincidən kiçik və ya bərarbərdirsə \"doğru\" cavabını qaytarır.", - "LOGIC_COMPARE_TOOLTIP_GT": "Birinci giriş ikincidən böyükdürsə \"doğru\" cavabını qaytarır.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Birinci giriş ikincidən böyük və ya bərarbərdirsə \"doğru\" cavabını qaytarır.", - "LOGIC_OPERATION_TOOLTIP_AND": "Hər iki giriş \"doğru\"-dursa \"doğru\" cavabını qaytarır.", - "LOGIC_OPERATION_AND": "və", - "LOGIC_OPERATION_TOOLTIP_OR": "Girişlərdən heç olmasa biri \"doğru\"-dursa \"doğru\" cavabını qaytarır.", - "LOGIC_OPERATION_OR": "və ya", - "LOGIC_NEGATE_TITLE": "%1 deyil", - "LOGIC_NEGATE_TOOLTIP": "Giriş \"yalan\"-dursa \"doğru\" cavabını qaytarır. Giriş \"doğru\"-dursa \"səhf\" cavabını qaytarır.", - "LOGIC_BOOLEAN_TRUE": "doğru", - "LOGIC_BOOLEAN_FALSE": "səhf", - "LOGIC_BOOLEAN_TOOLTIP": "\"doğru\" və ya \"səhf\" cavanını qaytarır.", - "LOGIC_NULL": "boş", - "LOGIC_NULL_TOOLTIP": "Boş cavab qaytarır.", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "əgər doğrudursa", - "LOGIC_TERNARY_IF_FALSE": "əgər səhfdirsə", - "LOGIC_TERNARY_TOOLTIP": "'Yoxla' əmrindəki şərtə nəzər yetirin. Əgər şərt \"doğru\"-dursa \"əgər doğru\", əks halda isə \"əgər yalan\" cavabını qaytarır.", - "MATH_NUMBER_HELPURL": "https://az.wikipedia.org/wiki/Ədəd", - "MATH_NUMBER_TOOLTIP": "Ədəd.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tg", - "MATH_TRIG_ASIN": "arcsin", - "MATH_TRIG_ACOS": "arccos", - "MATH_TRIG_ATAN": "arctan", - "MATH_ARITHMETIC_HELPURL": "https://az.wikipedia.org/wiki/Hesab", - "MATH_ARITHMETIC_TOOLTIP_ADD": "İki ədədin cəmini qaytarır.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "İki ədədin fərqini qaytarır.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "İki ədədin hasilini verir.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "İki ədədin nisbətini qaytarır.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Birinci ədədin ikinci ədəd dərəcəsindən qüvvətini qaytarır.", - "MATH_SINGLE_HELPURL": "https://az.wikipedia.org/wiki/Kvadrat_kökləri", - "MATH_SINGLE_OP_ROOT": "kvadrat kök", - "MATH_SINGLE_TOOLTIP_ROOT": "Ədədin kvadrat kökünü qaytarır.", - "MATH_SINGLE_OP_ABSOLUTE": "modul", - "MATH_SINGLE_TOOLTIP_ABS": "Ədədin modulunu qaytarır.", - "MATH_SINGLE_TOOLTIP_NEG": "Ədədin əksini qaytarır.", - "MATH_SINGLE_TOOLTIP_LN": "Ədədin natural loqarifmini tapır.", - "MATH_SINGLE_TOOLTIP_LOG10": "Ədədin 10-cu dərəcədən loqarifmini tapır.", - "MATH_SINGLE_TOOLTIP_EXP": "e sabitinin verilmiş ədədə qüvvətini qaytarır.", - "MATH_SINGLE_TOOLTIP_POW10": "10-un verilmiş ədədə qüvvətini qaytarır.", - "MATH_TRIG_HELPURL": "https://az.wikipedia.org/wiki/Triqonometrik_funksiyalar", - "MATH_TRIG_TOOLTIP_SIN": "Dərəcənin sinusunu qaytar (radianın yox).", - "MATH_TRIG_TOOLTIP_COS": "Dərəcənin kosinusunu qaytarır (radianın yox).", - "MATH_TRIG_TOOLTIP_TAN": "Dərəcənin tangensini qaytar (radianın yox).", - "MATH_TRIG_TOOLTIP_ASIN": "Ədədin arcsinusunu qaytarır.", - "MATH_TRIG_TOOLTIP_ACOS": "Ədədin arccosinusunu qaytarır.", - "MATH_TRIG_TOOLTIP_ATAN": "Ədədin arctanqensini qaytarır.", - "MATH_CONSTANT_HELPURL": "https://az.wikipedia.org/wiki/Riyazi_sabitlər", - "MATH_CONSTANT_TOOLTIP": "Ümumi sabitlərdən birini qaytarır π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), və ya ∞ (sonsuzluq).", - "MATH_IS_EVEN": "cütdür", - "MATH_IS_ODD": "təkdir", - "MATH_IS_PRIME": "sadədir", - "MATH_IS_WHOLE": "tamdır", - "MATH_IS_POSITIVE": "müsətdir", - "MATH_IS_NEGATIVE": "mənfidir", - "MATH_IS_DIVISIBLE_BY": "bölünür", - "MATH_IS_TOOLTIP": "Bir ədədin cüt, tək, sadə, tam, müsbət, mənfi olmasını və ya müəyyən bir ədədə bölünməsini yoxlayır. \"Doğru\" və ya \"yalan\" qiymətini qaytarır.", - "MATH_CHANGE_TITLE": "dəyiş: %1 buna: %2", - "MATH_CHANGE_TOOLTIP": "'%1' dəyişəninin üzərinə bir ədəd artır.", - "MATH_ROUND_TOOLTIP": "Ədədi aşağı və ya yuxari yuvarlaqşdır.", - "MATH_ROUND_OPERATOR_ROUND": "yuvarlaqlaşdır", - "MATH_ROUND_OPERATOR_ROUNDUP": "yuxarı yuvarlaqlaşdır", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "aşağı yuvarlaqlaşdır", - "MATH_ONLIST_OPERATOR_SUM": "Siyahının cəmi", - "MATH_ONLIST_TOOLTIP_SUM": "Siyahıdakı bütün ədədlərin cəmini qaytarır.", - "MATH_ONLIST_OPERATOR_MIN": "siyahının minimumu", - "MATH_ONLIST_TOOLTIP_MIN": "Siyahıdaki ən kiçik ədədi qaytarır.", - "MATH_ONLIST_OPERATOR_MAX": "siyahının maksimumu", - "MATH_ONLIST_TOOLTIP_MAX": "Siyahıdaki ən böyük elementi qaytarır.", - "MATH_ONLIST_OPERATOR_AVERAGE": "siyahının ədədi ortası", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Siyahıdaki ədədlərin ədədi ortasını qaytarır.", - "MATH_ONLIST_OPERATOR_MEDIAN": "siyahının medianı", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Siyahının median elementini qaytarır.", - "MATH_ONLIST_OPERATOR_MODE": "Siyahı modları( Ən çox rastlaşılan elementləri)", - "MATH_ONLIST_TOOLTIP_MODE": "Siyahıdaki ən çox rastlanan element(lər)dən ibarət siyahı qaytarır.", - "MATH_ONLIST_OPERATOR_STD_DEV": "Siyahının standart deviasiyası", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Siyahının standart deviasiyasını qaytarır.", - "MATH_ONLIST_OPERATOR_RANDOM": "siyahıdan təsadüfi seçilmiş bir element", - "MATH_ONLIST_TOOLTIP_RANDOM": "Siyahıdan təsadüfi bir element qaytarır.", - "MATH_MODULO_TITLE": "%1 ÷ %2 bölməsinin qalığı", - "MATH_MODULO_TOOLTIP": "İki ədədin nisbətindən alınan qalığı qaytarır.", - "MATH_CONSTRAIN_TITLE": "%1 üçün ən aşağı %2, ən yuxarı %3 olmağı tələb et", - "MATH_CONSTRAIN_TOOLTIP": "Bir ədədin verilmiş iki ədəd arasında olmasını tələb edir (sərhədlər də daxil olmaqla).", - "MATH_RANDOM_INT_TITLE": "%1 ilə %2 arasından təsadüfi tam ədəd", - "MATH_RANDOM_INT_TOOLTIP": "Verilmiş iki ədəd arasından (ədədrlər də daxil olmaqla) təsadüfi bir tam ədəd qaytarır.", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "təsadüfi kəsr", - "MATH_RANDOM_FLOAT_TOOLTIP": "0.0 (daxil olmaqla) və 1.0 (daxil olmamaqla) ədədlərinin arasından təsadüfi bir kəsr ədəd qaytarır.", - "TEXT_TEXT_TOOLTIP": "Mətndəki hərf, söz və ya sətir.", - "TEXT_JOIN_TITLE_CREATEWITH": "Verilmişlərlə mətn yarat", - "TEXT_JOIN_TOOLTIP": "İxtiyari sayda elementlərinin birləşməsi ilə mətn parçası yarat.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "birləşdir", - "TEXT_CREATE_JOIN_TOOLTIP": "Bu mətn blokunu yenidən konfigurasiya etmək üçün bölmələri əlavə edin, silin və ya yerlərini dəyişin.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Mətnə bir element əlavə et.", - "TEXT_APPEND_TO": "bu mətnin sonuna:", - "TEXT_APPEND_APPENDTEXT": "bu mətni əlavə et:", - "TEXT_APPEND_TOOLTIP": "'%1' dəyişəninin sonuna nəsə əlavə et.", - "TEXT_LENGTH_TITLE": "%1 - ın uzunluğu", - "TEXT_LENGTH_TOOLTIP": "Verilmiş mətndəki hərflərin(sözlər arası boşluqlar sayılmaqla) sayını qaytarır.", - "TEXT_ISEMPTY_TITLE": "%1 boşdur", - "TEXT_ISEMPTY_TOOLTIP": "Verilmiş mətn boşdursa, doğru qiymətini qaytarır.", - "TEXT_INDEXOF_TOOLTIP": "Birinci mətnin ikinci mətndə ilk/son rastlaşma indeksini qaytarır. Əgər rastlaşma baş verməzsə, %1 qaytarır.", - "TEXT_INDEXOF_INPUT_INTEXT": "mətndə", - "TEXT_INDEXOF_OPERATOR_FIRST": "Bu mətn ilə ilk rastlaşmanı tap:", - "TEXT_INDEXOF_OPERATOR_LAST": "Bu mətn ilə son rastlaşmanı tap:", - "TEXT_CHARAT_INPUT_INTEXT": "növbəti mətndə", - "TEXT_CHARAT_FROM_START": "bu nömrəli hərfi götür", - "TEXT_CHARAT_FROM_END": "axırdan bu nömrəli hərfi götür", - "TEXT_CHARAT_FIRST": "birinci hərfi götür", - "TEXT_CHARAT_LAST": "axırıncı hərfi götür", - "TEXT_CHARAT_RANDOM": "təsadüfi hərf götür", - "TEXT_CHARAT_TOOLTIP": "Göstərilən mövqedəki hərfi qaytarır.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Mətnin təyin olunmuş hissəsini qaytarır.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "mətndə", - "TEXT_GET_SUBSTRING_START_FROM_START": "Mətnin surətini bu nömrəli hərfdən", - "TEXT_GET_SUBSTRING_START_FROM_END": "Mətnin surətini sondan bu nömrəli # hərfdən", - "TEXT_GET_SUBSTRING_START_FIRST": "Mətnin surətini ilk hərfdən", - "TEXT_GET_SUBSTRING_END_FROM_START": "bu nömrəli hərfə qədər", - "TEXT_GET_SUBSTRING_END_FROM_END": "axırdan bu nömrəli hərfə qədər", - "TEXT_GET_SUBSTRING_END_LAST": "son hərfə qədər", - "TEXT_CHANGECASE_TOOLTIP": "Mətndə hərflərin böyük-kiçikliyini dəyiş.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "BÖYÜK HƏRFLƏRLƏ", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "kiçik hərflərlə", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "Baş Hərflərlə", - "TEXT_TRIM_TOOLTIP": "Mətnin hər iki və ya yalnız bir tərəfdən olan boşluqları pozulmuş surətini qaytarın.", - "TEXT_TRIM_OPERATOR_BOTH": "Boşluqları hər iki tərəfdən pozun", - "TEXT_TRIM_OPERATOR_LEFT": "Boşluqlari yalnız sol tərəfdən pozun", - "TEXT_TRIM_OPERATOR_RIGHT": "Boşluqları yalnız sağ tərəfdən pozun", - "TEXT_PRINT_TITLE": "%1 - i çap elə", - "TEXT_PRINT_TOOLTIP": "Təyin olunmuş mətn, ədəd və ya hər hansı bir başqa elementi çap elə.", - "TEXT_PROMPT_TYPE_TEXT": "İstifadəçiyə mətn daxil etməsi üçün sorğunu/tələbi ismarıc ilə göndərin", - "TEXT_PROMPT_TYPE_NUMBER": "İstifadəçiyə ədəd daxil etməsi üçün sorğunu/tələbi ismarıc kimi göndərin", - "TEXT_PROMPT_TOOLTIP_NUMBER": "İstifadəçiyə ədəd daxil etməsi üçün sorğu/tələb göndərin.", - "TEXT_PROMPT_TOOLTIP_TEXT": "İstifadəçiyə mətn daxil etməsi üçün sorğu/tələb göndərin.", - "LISTS_CREATE_EMPTY_TITLE": "boş siyahı düzəlt", - "LISTS_CREATE_EMPTY_TOOLTIP": "Heç bir verilən qeyd olunmamış, uzunluğu 0 olan bir siyahı verir", - "LISTS_CREATE_WITH_TOOLTIP": "İstənilən ölçülü siyahı yaradın.", - "LISTS_CREATE_WITH_INPUT_WITH": "bunlardan siyahı düzəlt", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "siyahı", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Bu siyahı blokunu yenidən konfigurasiya etmək üçün bölmələri əlavə edin, silin və ya yerlərini dəyişin.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Siyahıya element əlavə edin.", - "LISTS_REPEAT_TOOLTIP": "Təyin olunmuş elementin/qiymətin təyin olunmuş sayda təkrarlandığı siyahını yaradır.", - "LISTS_REPEAT_TITLE": "%1 elementinin %2 dəfə təkrarlandığı siyahı düzəlt", - "LISTS_LENGTH_TITLE": "%1 siyahısının uzunluğu", - "LISTS_LENGTH_TOOLTIP": "Siyahının uzunluğunu verir.", - "LISTS_ISEMPTY_TITLE": "%1 boşdur", - "LISTS_ISEMPTY_TOOLTIP": "Siyahı boşdursa \"doğru\" cavabını qaytarır.", - "LISTS_INLIST": "siyahıda", - "LISTS_INDEX_OF_FIRST": "Element ilə ilk rastlaşma indeksini müəyyən edin", - "LISTS_INDEX_OF_LAST": "Element ilə son rastlaşma indeksini müəyyən edin", - "LISTS_INDEX_OF_TOOLTIP": "Siyahıda element ilə ilk/son rastlaşma indeksini qaytarır. Əgər tekst siyahıda tapılmazsa, %1 qaytarılır.", - "LISTS_GET_INDEX_GET": "götür", - "LISTS_GET_INDEX_GET_REMOVE": "götür və sil", - "LISTS_GET_INDEX_REMOVE": "yığışdır", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "axırdan # nömrəli", - "LISTS_GET_INDEX_FIRST": "birinci", - "LISTS_GET_INDEX_LAST": "axırıncı", - "LISTS_GET_INDEX_RANDOM": "təsadüfi", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 ilk elementdir.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 son elementdir.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Siyahıdan təyin olunmuş indeksli elementi qaytarır.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Siyahının ilk elementini qaytarır.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Siyahının son elementini qaytarır.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Siyahıdan hər hansı təsadüfi elementi qaytarır.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Siyahıdan təyin olunmuş indeksli elementi silir və qaytarır.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Siyahıdan ilk elementi silir və qaytarır.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Siyahıdan son elementi silir və qaytarır.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Siyahıdan təsadufi elementi silir və qaytarır.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Siyahıdan təyin olunmuş indeksli elementi silir.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Siyahıdan ilk elementi silir.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Siyahıdan son elementi silir.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Siyahıdan təsadüfi bir elementi silir.", - "LISTS_SET_INDEX_SET": "təyin et", - "LISTS_SET_INDEX_INSERT": "daxil et", - "LISTS_SET_INDEX_INPUT_TO": "Kimi", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Siyahının göstərilən yerdəki elementini təyin edir.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Siyahıda birinci elementi təyin edir.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Siyahının sonuncu elementini təyin edir.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Siyahının təsadüfi seçilmiş bir elementini təyin edir.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Elementi siyahıda göstərilən yerə daxil edir.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Elementi siyahının əvvəlinə daxil edir.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Elementi siyahının sonuna artırır.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Elementi siyahıda təsadüfi seçilmiş bir yerə atır.", - "LISTS_GET_SUBLIST_START_FROM_START": "# - dən alt-siyahını alın", - "LISTS_GET_SUBLIST_START_FROM_END": "# sonuncudan alt-siyahını alın", - "LISTS_GET_SUBLIST_START_FIRST": "Birincidən alt-siyahını alın", - "LISTS_GET_SUBLIST_END_FROM_START": "# nömrəliyə", - "LISTS_GET_SUBLIST_END_FROM_END": "sondan # nömrəliyə", - "LISTS_GET_SUBLIST_END_LAST": "Sonuncuya", - "LISTS_GET_SUBLIST_TOOLTIP": "Siyahının təyin olunmuş hissəsinin surətini yaradın.", - "VARIABLES_GET_TOOLTIP": "Bu dəyişənin qiymətini qaytarır.", - "VARIABLES_GET_CREATE_SET": "'%1 - i təyin et' - i yarat", - "VARIABLES_SET": "%1 - i bu qiymət ilə təyin et: %2", - "VARIABLES_SET_TOOLTIP": "Bu dəyişəni daxil edilmiş qiymətə bərabər edir.", - "VARIABLES_SET_CREATE_GET": "'%1 - i götür' - ü yarat", - "PROCEDURES_DEFNORETURN_TITLE": "icra et:", - "PROCEDURES_DEFNORETURN_PROCEDURE": "hansısa əməliyyat", - "PROCEDURES_BEFORE_PARAMS": "ilə:", - "PROCEDURES_CALL_BEFORE_PARAMS": "ilə:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Nəticəsi olmayan funksiya yaradır.", - "PROCEDURES_DEFRETURN_RETURN": "qaytar", - "PROCEDURES_DEFRETURN_TOOLTIP": "Nəticəsi olan funksiya yaradır.", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Xəbərdarlıq: Bu funksiyanın təkrar olunmuş parametrləri var.", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Yaradılmış '%1' funksiyasını çalışdır.", - "PROCEDURES_CALLRETURN_TOOLTIP": "Yaradılmış '%1' funksiyasını çalışdır və nəticəni istifadə et.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "girişlər", - "PROCEDURES_MUTATORARG_TITLE": "Giriş adı:", - "PROCEDURES_HIGHLIGHT_DEF": "Funksiyanın təyinatını vurğula", - "PROCEDURES_CREATE_DO": "'%1' yarat", - "PROCEDURES_IFRETURN_TOOLTIP": "Əgər bir dəyər \"doğru\"-dursa onda ikinci dəyəri qaytar.", - "PROCEDURES_IFRETURN_WARNING": "Xəbərdarlıq: Bu blok ancaq bir funksiyanın təyinatı daxilində işlədilə bilər." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/ba.json b/backend/_pv_1_3_5/static/blockly/msg/json/ba.json deleted file mode 100755 index e1cc00c85..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/ba.json +++ /dev/null @@ -1,210 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Alfiya55", - "Ләйсән", - "Айсар", - "Кутлубаева Кунсулу Закиевна", - "Азат Хәлилов", - "Танзиля Кутлугильдина" - ] - }, - "VARIABLES_DEFAULT_NAME": "элемент", - "TODAY": "Бөгөн", - "DUPLICATE_BLOCK": "Күсереп алырға", - "ADD_COMMENT": "Фекер өҫтәргә", - "REMOVE_COMMENT": "Аңлатмаларҙы юйырға", - "EXTERNAL_INPUTS": "Тышҡы өҫтәлмә", - "INLINE_INPUTS": "Эске өҫтәлмә", - "DELETE_BLOCK": "Блокты юйҙырырға", - "DELETE_X_BLOCKS": " %1 блокты юйҙырырға", - "DELETE_ALL_BLOCKS": "Бөтә %1 блоктарҙы юйырғамы?", - "CLEAN_UP": "Блоктарҙы таҙартырға", - "COLLAPSE_BLOCK": "Блокты төрөргә", - "COLLAPSE_ALL": "Блоктарҙы төрөргә", - "EXPAND_BLOCK": "Блокты йәйергә", - "EXPAND_ALL": "Блоктарҙы йәйергә", - "DISABLE_BLOCK": "Блокты һүндерергә", - "ENABLE_BLOCK": "Блокты тоҡандырырға", - "HELP": "Ярҙам", - "UNDO": "Кире алырға", - "REDO": "документтарҙы үҙгәртергә", - "CHANGE_VALUE_TITLE": "Мәғәнәне үҙгәртегеҙ:", - "RENAME_VARIABLE": "Үҙгәреүсәндең исемен алмаштырырға...", - "RENAME_VARIABLE_TITLE": "Бөтә '%1' үҙгәреүсәндәрҙең исемен ошолай алмаштырырға:", - "NEW_VARIABLE": "Яңы үҙгәреүсән...", - "NEW_VARIABLE_TITLE": "Яңы үҙгәреүсәндең исеме:", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Төҫ", - "COLOUR_PICKER_TOOLTIP": "Палитранан төҫ һайлағыҙ.", - "COLOUR_RANDOM_TITLE": "осраҡлы төҫ", - "COLOUR_RANDOM_TOOLTIP": "Төҫтө осраҡлылыҡ буйынса һайлай.", - "COLOUR_RGB_TITLE": "ошонан төҫ", - "COLOUR_RGB_RED": "ҡыҙылдан", - "COLOUR_RGB_GREEN": "йәшелдән", - "COLOUR_RGB_BLUE": "зәңгәр", - "COLOUR_RGB_TOOLTIP": "Бирелгән нисбәттәрҙә ҡыҙылдан, йәшелдән һәм зәңгәрҙән төҫ барлыҡҡа килә. Бөтә мәғәнәләр 0 менән 100 араһында булырға тейеш.", - "COLOUR_BLEND_TITLE": "ҡатнаштырырға", - "COLOUR_BLEND_COLOUR1": "1-се төҫ", - "COLOUR_BLEND_COLOUR2": "2-се төҫ", - "COLOUR_BLEND_RATIO": "1-се төҫтөң өлөшө", - "COLOUR_BLEND_TOOLTIP": "Ике төҫтө бирелгән нисбәттә болғата (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/Цикл_(программалау)", - "CONTROLS_REPEAT_TITLE": " %1 тапҡыр ҡабатларға", - "CONTROLS_REPEAT_INPUT_DO": "үтәргә", - "CONTROLS_REPEAT_TOOLTIP": "Командаларҙы бер нисә тапҡыр үтәй.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "ҡабатларға, әлегә", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "ҡабатларға, әлегә юҡ", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Мәғәнә дөрөҫ булғанда, командаларҙы ҡабатлай.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Мәғәнә ялған булғанда, командаларҙы ҡабатлай.", - "CONTROLS_FOR_TOOLTIP": "Үҙгәреүсәнгә башынан аҙағына тиклем тәғәйен аҙым менән %1 мәғәнәне бирә һәм күрһәтелгән командаларҙы үтәй.", - "CONTROLS_FOREACH_TITLE": "һәр элемент өсөн %1 исемлектә %2", - "CONTROLS_FOREACH_TOOLTIP": "Исемлектәге һәр элемент өсөн үҙгәреүсәнгә элементтың '%1' мәғәнәһен бирә һәм күрһәтелгән командаларҙы үтәй.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "циклдан сығырға", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "циклдың киләһе аҙымына күсергә", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Был циклды өҙә.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Циклдың ҡалдығын төшөрөп ҡалдыра һәм киләһе аҙымға күсә.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Иҫкәртеү: был блок цикл эсендә генә ҡулланыла ала.", - "CONTROLS_IF_TOOLTIP_1": "Мәғәнә дөрөҫ булғанда, командаларҙы үтәй.", - "CONTROLS_IF_TOOLTIP_2": "Шарт дөрөҫ булғанда, командаларҙың беренсе блогын үтәй. Улай булмаһа, командаларҙың икенсе блогы үтәлә.", - "CONTROLS_IF_TOOLTIP_3": "Беренсе шарт дөрөҫ булһа, командаларҙың беренсе блогын үтәй. Икенсе шарт дөрөҫ булһа, командаларҙың икенсе блогын үтәй.", - "CONTROLS_IF_TOOLTIP_4": "Беренсе шарт дөрөҫ булһа, командаларҙың беренсе блогын үтәй. Әгәр икенсе шарт дөрөҫ булһа, командаларҙың икенсе блогын үтәй. Бер шарт та дөрөҫ булмаһа, команда блоктарының һуңғыһын үтәй.", - "CONTROLS_IF_MSG_IF": "әгәр", - "CONTROLS_IF_MSG_ELSEIF": "юғиһә, әгәр", - "CONTROLS_IF_MSG_ELSE": "юғиһә", - "CONTROLS_IF_IF_TOOLTIP": "\"Әгәр\" блогын ҡабаттан төҙөү өсөн киҫәктәрҙе өҫтәгеҙ, юйҙырығыҙ, урындарын алмаштырығыҙ.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "\"Әгәр\" блогына шарт өҫтәй", - "CONTROLS_IF_ELSE_TOOLTIP": "Бер шарт та дөрөҫ булмаған осраҡҡа йомғаҡлау ярҙамсы блогын өҫтәргә.", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(математика)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Өҫтәмәләр тигеҙ булһа, дөрөҫ мәғәнәһен кире ҡайтара.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Өҫтәмәләр тигеҙ булмаһа, дөрөҫ мәғәнәһен кире ҡайтара.", - "LOGIC_COMPARE_TOOLTIP_LT": "Беренсе өҫтәмә икенсеһенән бәләкәйерәк булһа, дөрөҫ мәғәнәһен кире ҡайтара.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Беренсе өҫтәмә икенсеһенән бәләкәйерәк йә уға тиң булһа, дөрөҫ мәғәнәһен кире ҡайтара.", - "LOGIC_COMPARE_TOOLTIP_GT": "Беренсе өҫтәмә икенсеһенән ҙурыраҡ булһа, дөрөҫ мәғәнәһен кире ҡайтара.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Беренсе өҫтәмә икенсеһенән бәләкәйерәк йә уға тиң булһа, дөрөҫ мәғәнәһен кире ҡайтара.", - "LOGIC_OPERATION_TOOLTIP_AND": "Әгәр ҙә ике өҫтәлмә лә тап килһә, дөрөҫ аңлатманы кире ҡайтара.", - "LOGIC_OPERATION_AND": "һәм", - "LOGIC_OPERATION_TOOLTIP_OR": "Өҫтәлмәләрҙең береһе генә дөрөҫ булһа, дөрөҫ аңлатманы ҡайтара.", - "LOGIC_OPERATION_OR": "йәки", - "LOGIC_NEGATE_TITLE": "%1 түгел", - "LOGIC_NEGATE_TOOLTIP": "Өҫтәлмә ялған булһа, дөрөҫ аңлатманы ҡайтара. Өҫтәлмә дөрөҫ булһа, ялған аңлатманы ҡайтара.", - "LOGIC_BOOLEAN_TRUE": "дөрөҫ", - "LOGIC_BOOLEAN_FALSE": "ялған", - "LOGIC_BOOLEAN_TOOLTIP": "Дөрөҫ йәки ялғанды ҡайтара.", - "LOGIC_NULL": "нуль", - "LOGIC_NULL_TOOLTIP": "Нулде ҡайтара.", - "LOGIC_TERNARY_CONDITION": "тест", - "LOGIC_TERNARY_IF_TRUE": "әгәр дөрөҫ булһа", - "LOGIC_TERNARY_IF_FALSE": "әгәр ялған булһа", - "LOGIC_TERNARY_TOOLTIP": "Һайлау шартын тикшерә. Әгәр ул дөрөҫ булһа, беренсе мәғәнәне, хата булһа, икенсе мәғәнәне ҡайтара.", - "MATH_NUMBER_HELPURL": "https://ba.wikipedia.org/wiki/Һан", - "MATH_NUMBER_TOOLTIP": "Рәт.", - "MATH_ARITHMETIC_HELPURL": "https://ba.wikipedia.org/wiki/Арифметика", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Ике һандың суммаһын ҡайтара.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Ике һандың айырмаһын ҡайтара.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Ике һандың ҡабатландығын ҡайтара.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Ике һандың бүлендеген ҡайтара.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Дәрәжәгә күтәрелгән икенсе һандан тәүгеһенә ҡайтара.", - "MATH_SINGLE_HELPURL": "https://ba.wikipedia.org/wiki/Квадрат_тамыр", - "MATH_SINGLE_OP_ROOT": "квадрат тамыр", - "MATH_SINGLE_TOOLTIP_ROOT": "Һандың квадрат тамырын ҡайтара.", - "MATH_SINGLE_OP_ABSOLUTE": "абсолют", - "MATH_SINGLE_TOOLTIP_ABS": "Һандың модулен ҡайтара.", - "MATH_SINGLE_TOOLTIP_NEG": "Кире һанды ҡайтара.", - "MATH_SINGLE_TOOLTIP_LN": "Һандың натураль логаритмын ҡайтара.", - "MATH_SINGLE_TOOLTIP_LOG10": "Һандың унынсы логаритмын ҡайтара.", - "MATH_SINGLE_TOOLTIP_EXP": "Күрһәтелгән дәрәжәлә ҡайтара.", - "MATH_SINGLE_TOOLTIP_POW10": "Күрһәтелгән 10-сы дәрәжәлә ҡайтара.", - "MATH_TRIG_HELPURL": "https://ba..wikipedia.org/wiki/Тригонометрик_функциялар", - "MATH_TRIG_TOOLTIP_SIN": "Мөйөштөң синусын градустарҙа ҡайтара.", - "MATH_TRIG_TOOLTIP_COS": "Мөйөштөң косинусын градустарҙа ҡайтара.", - "MATH_TRIG_TOOLTIP_TAN": "Мөйөштөң тангенсын градустарҙа күрһәтә.", - "MATH_TRIG_TOOLTIP_ASIN": "Арксинусты градустарҙа күрһәтә.", - "MATH_TRIG_TOOLTIP_ACOS": "Арккосинусты градустарҙа күрһәтә.", - "MATH_TRIG_TOOLTIP_ATAN": "Арктангенсты градустарҙа күрһәтә.", - "MATH_CONSTANT_HELPURL": "https://ba.wikipedia.org/wiki/Математик_константа", - "MATH_CONSTANT_TOOLTIP": "Таралған константаның береһен күрһәтә: π (3.141...), e (2.718...), φ (1.618...), sqrt(2) (1.414...), sqrt(½) (0.707...) йәки ∞ (сикһеҙлек).", - "MATH_IS_EVEN": "тағы", - "MATH_IS_ODD": "сәйер", - "MATH_IS_PRIME": "ябай", - "MATH_IS_WHOLE": "бөтөн", - "MATH_IS_POSITIVE": "ыңғай", - "MATH_IS_NEGATIVE": "тиҫкәре", - "MATH_IS_DIVISIBLE_BY": "бүленә", - "MATH_IS_TOOLTIP": "Һандың йоп, таҡ, ябай, бөтөн, ыңғай, кире йәки билдәле һанға ҡарата ниндәй булыуын тикшерә. Дөрөҫ йә ялған мәғәнәһен күрһәтә.", - "MATH_CHANGE_HELPURL": "https://ba.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "%1 тан %2 ҡа арттырырға", - "MATH_CHANGE_TOOLTIP": "Үҙгәреүсән һанға өҫтәй '%1'.", - "MATH_ROUND_HELPURL": "https://ba.wikipedia.org/wiki/Т=Түңәрәкләү", - "MATH_ROUND_TOOLTIP": "Һанды ҙурына йә бәләкәйенә тиклем түңәрәкләргә.", - "MATH_ROUND_OPERATOR_ROUND": "түңәрәк", - "MATH_ROUND_OPERATOR_ROUNDUP": "ҙурына тиклем түңәрәкләргә", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "бәләкәйгә тиклем түңәрәкләргә", - "MATH_ONLIST_OPERATOR_SUM": "исемлек суммаһы", - "MATH_ONLIST_TOOLTIP_SUM": "Исемлектәрҙәге һандар суммаһын күрһәтә.", - "MATH_ONLIST_OPERATOR_MIN": "Исемлектәге иң бәләкәйе", - "MATH_ONLIST_TOOLTIP_MIN": "Исемлектәге иң бәләкәй һанды күрһәтә.", - "MATH_ONLIST_OPERATOR_MAX": "исемлектәге иң ҙуры", - "MATH_ONLIST_TOOLTIP_MAX": "Исемлектең иң ҙур һанын күрһәтә.", - "MATH_ONLIST_OPERATOR_AVERAGE": "исемлектең уртаса арифметик дәүмәле", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Исемлектең уртаса арифметик дәүмәле күрһәтә.", - "MATH_ONLIST_OPERATOR_MEDIAN": "исемлек медианаһы", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Исемлек медианаһын күрһәтә.", - "MATH_ONLIST_OPERATOR_MODE": "исемлек модалары", - "MATH_ONLIST_TOOLTIP_MODE": "Исемлектең иң күп осраған элементтарын күрһәтә.", - "MATH_ONLIST_OPERATOR_STD_DEV": "исемлекте стандарт кире ҡағыу", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Исемлекте стандарт кире ҡағыуҙы күрһәтә.", - "MATH_ONLIST_OPERATOR_RANDOM": "исемлектең осраҡлы элементы", - "MATH_ONLIST_TOOLTIP_RANDOM": "Исемлектең осраҡлы элементын күрһәтә.", - "MATH_MODULO_HELPURL": "https://ba.wikipedia.org/wiki/Ҡалдыҡ_менән_бүлеү", - "MATH_MODULO_TITLE": "ҡалдыҡ %1 : %2 араһында", - "MATH_MODULO_TOOLTIP": "Ике һанды бүлеү ҡалдығын күрһәтә.", - "MATH_CONSTRAIN_TITLE": "сикләргә %1 аҫтан %2 өҫтән %3", - "MATH_CONSTRAIN_TOOLTIP": "Һанды аҫтан һәм өҫтән сикләй (сиктәгеләрен индереп).", - "MATH_RANDOM_INT_HELPURL": "https://ba.wikipedia.org/wiki/Ялған осраҡлы_һандар_генераторы", - "MATH_RANDOM_INT_TITLE": "%1-ҙән %2-гә тиклем осраҡлы бөтөн һан", - "MATH_RANDOM_INT_TOOLTIP": "Ике бирелгән һан араһындағы (үҙҙәрен дә индереп) осраҡлы һанды күрһәтә.", - "MATH_RANDOM_FLOAT_HELPURL": "https://ba.wikipedia.org/wiki/Ялған осраҡлы_һандар_генераторы", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "0 (үҙен дә индереп) һәм 1 араһындағы осраҡлы һан", - "TEXT_TEXT_TOOLTIP": "Текстың хәрефе, һүҙе йәки юлы.", - "TEXT_JOIN_TITLE_CREATEWITH": "текст төҙөргә", - "TEXT_JOIN_TOOLTIP": "Элементтарҙың теләһә күпме һанын берләштереп текст фрагментын булдыра.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "ҡушылығыҙ", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Текстҡа элемент өҫтәү.", - "TEXT_APPEND_APPENDTEXT": "текст өҫтәргә", - "TEXT_APPEND_TOOLTIP": "Үҙгәреүсән «%1»-гә текст өҫтәргә.", - "TEXT_LENGTH_TITLE": "оҙонлоғо %1", - "TEXT_LENGTH_TOOLTIP": "Бирелгән текстағы символдар һанын (буш урындар менән бергә) кире ҡайтара.", - "TEXT_ISEMPTY_TITLE": "%1 буш", - "TEXT_INDEXOF_INPUT_INTEXT": "текстҡа", - "TEXT_INDEXOF_OPERATOR_FIRST": "текстың тәүге инеүен табырға", - "TEXT_INDEXOF_OPERATOR_LAST": "Текстың һуңғы инеүен табырға", - "TEXT_CHARAT_INPUT_INTEXT": "текста", - "TEXT_CHARAT_FROM_START": "хат алырға #", - "TEXT_CHARAT_FROM_END": "№ хәрефен аҙаҡтан алырға", - "TEXT_CHARAT_FIRST": "тәүге хәрефте алырға", - "TEXT_CHARAT_LAST": "һуңғы хәрефте алырға", - "TEXT_CHARAT_RANDOM": "осраҡлы хәрефте алырға", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "текста", - "TEXT_GET_SUBSTRING_END_FROM_START": "# хатҡа", - "TEXT_GET_SUBSTRING_END_LAST": "һуңғы хәрефкә тиклем", - "TEXT_PRINT_TITLE": "%1 баҫтырырға", - "LISTS_CREATE_WITH_INPUT_WITH": "менән исемлек төҙөргә", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "исемлек", - "LISTS_LENGTH_TITLE": "оҙонлоғо %1", - "LISTS_ISEMPTY_TITLE": "%1 буш", - "LISTS_INLIST": "исемлеккә", - "LISTS_GET_INDEX_GET": "алырға", - "LISTS_GET_INDEX_GET_REMOVE": "алырға һәм юйырға", - "LISTS_GET_INDEX_REMOVE": "юйырға", - "LISTS_GET_INDEX_FROM_END": "# аҙағынан", - "LISTS_GET_INDEX_FIRST": "беренсе", - "LISTS_GET_INDEX_LAST": "аҙаҡҡы", - "LISTS_GET_INDEX_RANDOM": "осраҡлы", - "LISTS_SET_INDEX_SET": "йыйылма", - "LISTS_SET_INDEX_INSERT": "өҫтәп ҡуйырға", - "LISTS_SET_INDEX_INPUT_TO": "кеүек", - "PROCEDURES_DEFRETURN_RETURN": "кире ҡайтарыу", - "PROCEDURES_MUTATORCONTAINER_TITLE": "инеү", - "PROCEDURES_MUTATORARG_TITLE": "инеү исеме:", - "PROCEDURES_CREATE_DO": "'%1' төҙөргә" -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/bcc.json b/backend/_pv_1_3_5/static/blockly/msg/json/bcc.json deleted file mode 100755 index 88fd16716..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/bcc.json +++ /dev/null @@ -1,289 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Baloch Afghanistan" - ] - }, - "VARIABLES_DEFAULT_NAME": "مورد", - "DUPLICATE_BLOCK": "تکراری", - "ADD_COMMENT": "افزودن نظر", - "REMOVE_COMMENT": "حذف نظر", - "EXTERNAL_INPUTS": "ورودی‌های خارجی", - "INLINE_INPUTS": "ورودی‌های درون خطی", - "DELETE_BLOCK": "حذف بلوک", - "DELETE_X_BLOCKS": "حذف بلوک‌های %1", - "COLLAPSE_BLOCK": "فروپاشی بلوک", - "COLLAPSE_ALL": "فروپاشی بلوک‌ها", - "EXPAND_BLOCK": "گسترش بلوک", - "EXPAND_ALL": "گسترش بلوک‌ها", - "DISABLE_BLOCK": "غیرفعال‌سازی بلوک", - "ENABLE_BLOCK": "فعال‌سازی بلوک", - "HELP": "کومک", - "CHANGE_VALUE_TITLE": "تغییر مقدار:", - "RENAME_VARIABLE": "تغییر نام متغیر...", - "RENAME_VARIABLE_TITLE": "تغییر نام همهٔ متغیرهای «%1» به:", - "NEW_VARIABLE": "متغیر تازه...", - "NEW_VARIABLE_TITLE": "نام متغیر تازه:", - "COLOUR_PICKER_HELPURL": "https://fa.wikipedia.org/wiki/%D8%B1%D9%86%DA%AF", - "COLOUR_PICKER_TOOLTIP": "انتخاب یک رنگ از تخته‌رنگ.", - "COLOUR_RANDOM_TITLE": "رنگ تصادفی", - "COLOUR_RANDOM_TOOLTIP": "انتخاب یک رنگ به شکل تصادفی.", - "COLOUR_RGB_TITLE": "رنگ با", - "COLOUR_RGB_RED": "قرمز", - "COLOUR_RGB_GREEN": "سبز", - "COLOUR_RGB_BLUE": "آبی", - "COLOUR_RGB_TOOLTIP": "ساخت یک رنگ با مقدار مشخص‌شده‌ای از قرمز، سبز و آبی. همهٔ مقادیر باید بین ۰ تا ۱۰۰ باشند.", - "COLOUR_BLEND_TITLE": "مخلوط", - "COLOUR_BLEND_COLOUR1": "رنگ ۱", - "COLOUR_BLEND_COLOUR2": "رنگ ۲", - "COLOUR_BLEND_RATIO": "نسبت", - "COLOUR_BLEND_TOOLTIP": "دو رنگ را با نسبت مشخص‌شده مخلوط می‌کند (۰٫۰ - ۱٫۰)", - "CONTROLS_REPEAT_HELPURL": "https://fa.wikipedia.org/wiki/%D8%AD%D9%84%D9%82%D9%87_%D9%81%D9%88%D8%B1", - "CONTROLS_REPEAT_TITLE": "%1 بار تکرار", - "CONTROLS_REPEAT_INPUT_DO": "انجام", - "CONTROLS_REPEAT_TOOLTIP": "انجام چند عبارت چندین بار.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "تکرار در حالی که", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "تکرار تا", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "تا زمانی که یک مقدار صحیح است، چند عبارت را انجام بده.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "تا زمانی که یک مقدار ناصحیح است، چند عبارت را انجام بده.", - "CONTROLS_FOR_TOOLTIP": "متغیر %1 را در مقادیر شروع‌شده از عدد انتهای به عدد انتهایی را دارد، با فواصل مشخص‌شده می‌شمارد و این بلوک مشخص‌شده را انجام می‌دهد.", - "CONTROLS_FOR_TITLE": "با تعداد %1 از %2 به %3 با گام‌های %4", - "CONTROLS_FOREACH_TITLE": "برای هر مورد %1 در فهرست %2", - "CONTROLS_FOREACH_TOOLTIP": "برای هر مورد در این فهرست، تنظیم متغیر «%1» به مورد و انجام تعدادی عبارت.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "شکستن حلقه", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "ادامه با تکرار بعدی حلقه", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "شکستن حلقهٔ شامل.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "پریدن از بقیهٔ حلقه و ادامه با تکرار بعدی.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "اخطار: این بلوک ممکن است فقط داخل یک حلقه استفاده شود.", - "CONTROLS_IF_TOOLTIP_1": "اگر یک مقدار صحیح است، سپس چند عبارت را انجام بده.", - "CONTROLS_IF_TOOLTIP_2": "اگر یک مقدار صحیح است، اول بلوک اول عبارات را انجام بده. در غیر این صورت بلوک دوم عبارات انجام بده.", - "CONTROLS_IF_TOOLTIP_3": "اگر مقدار اول صحیح بود، از آن بلوک اول عبارات را انجام بده. در غیر این صورت، اگر مقدار دوم صحیح است، بلوک دوم عبارات را انجام بده.", - "CONTROLS_IF_TOOLTIP_4": "اگر مقدار اول درست است، بلوک اول عبارات را انجام بده. در غیر این صورت، اگر مقدار دوم درست باشد بلوک دوم عبارات را انجام بده. اگر هیچ از مقادیر درست نبود، آخرین بلوک عبارات را انجام بده.", - "CONTROLS_IF_MSG_IF": "اگر", - "CONTROLS_IF_MSG_ELSEIF": "اگر آنگاه", - "CONTROLS_IF_MSG_ELSE": "آنگاه", - "CONTROLS_IF_IF_TOOLTIP": "اضافه، حذف یا ترتیب‌سازی قسمت‌ها برای تنظیم مجدد این بلوک اگر مسدود است.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "افزودن یک شرط به بلوک اگر.", - "CONTROLS_IF_ELSE_TOOLTIP": "اضافه‌کردن نهایی، گرفتن همهٔ شرایط به بلوک اگر.", - "LOGIC_COMPARE_HELPURL": "https://fa.wikipedia.org/wiki/%D9%86%D8%A7%D8%A8%D8%B1%D8%A7%D8%A8%D8%B1%DB%8C", - "LOGIC_COMPARE_TOOLTIP_EQ": "بازگشت صحیح اگر هر دو ورودی با یکدیگر برابر باشد.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "برگرداندن صحیح اگر هر دو ورودی با یکدیگر برابر نباشند.", - "LOGIC_COMPARE_TOOLTIP_LT": "بازگرداندن صحیح اگر ورودی اول کوچکتر از ورودی دوم باشد.", - "LOGIC_COMPARE_TOOLTIP_LTE": "بازگرداندن صحیح اگر ورودی اول کوچکتر یا مساوی با ورودی دوم باشد.", - "LOGIC_COMPARE_TOOLTIP_GT": "بازگرداندن صحیح اگر ورودی اول بزرگتر از ورودی دوم باشد.", - "LOGIC_COMPARE_TOOLTIP_GTE": "بازگرداندن صحیح اگر ورودی اول بزرگتر یا مساوی یا ورودی دوم باشد.", - "LOGIC_OPERATION_TOOLTIP_AND": "بازگرداندن صحیح اگر هر دو ورودی صحیح باشد.", - "LOGIC_OPERATION_AND": "و", - "LOGIC_OPERATION_TOOLTIP_OR": "بازگرداندن صحیح اگر یکی از دو ورودی صحیح باشد.", - "LOGIC_OPERATION_OR": "یا", - "LOGIC_NEGATE_TITLE": "نه %1", - "LOGIC_NEGATE_TOOLTIP": "صجیج باز می‌گرداند اگر ورودی نا صحیح باشند. ناصحیح بازمی‌گرداند اگر ورودی صحیح باشد.", - "LOGIC_BOOLEAN_TRUE": "صحیح", - "LOGIC_BOOLEAN_FALSE": "ناصحیح", - "LOGIC_BOOLEAN_TOOLTIP": "بازگرداندن یکی از صحیح یا ناصحیح.", - "LOGIC_NULL": "تهی", - "LOGIC_NULL_TOOLTIP": "تهی بازمی‌گرداند.", - "LOGIC_TERNARY_CONDITION": "آزمایش", - "LOGIC_TERNARY_IF_TRUE": "اگر صحیح", - "LOGIC_TERNARY_IF_FALSE": "اگر ناصحیح", - "LOGIC_TERNARY_TOOLTIP": "بررسی وضعیت در «آزمایش». اگر وضعیت صحیح باشد، مقدار «اگر صحیح» را بر می‌گرداند در غیر اینصورت مقدار «اگر ناصحیح» را.", - "MATH_NUMBER_HELPURL": "https://fa.wikipedia.org/wiki/%D8%B9%D8%AF%D8%AF", - "MATH_NUMBER_TOOLTIP": "یک عدد.", - "MATH_ARITHMETIC_HELPURL": "https://fa.wikipedia.org/wiki/%D8%AD%D8%B3%D8%A7%D8%A8", - "MATH_ARITHMETIC_TOOLTIP_ADD": "بازگرداندن مقدار جمع دو عدد.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "بازگرداندن تفاوت دو عدد.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "بازگرداندن حاصلضرب دو عدد.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "بازگرداندن باقی‌ماندهٔ دو عدد.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "بازگرداندن اولین عددی که از توان عدد دوم حاصل شده باشد.", - "MATH_SINGLE_HELPURL": "https://fa.wikipedia.org/wiki/%D8%B1%DB%8C%D8%B4%D9%87_%D8%AF%D9%88%D9%85", - "MATH_SINGLE_OP_ROOT": "ریشهٔ دوم", - "MATH_SINGLE_TOOLTIP_ROOT": "ریشهٔ دوم یک عدد را باز می‌گرداند.", - "MATH_SINGLE_OP_ABSOLUTE": "مطلق", - "MATH_SINGLE_TOOLTIP_ABS": "قدر مطلق یک عدد را بازمی‌گرداند.", - "MATH_SINGLE_TOOLTIP_NEG": "منفی‌شدهٔ یک عدد را باز می‌گرداند.", - "MATH_SINGLE_TOOLTIP_LN": "لوگاریتم طبیعی یک عدد را باز می‌گرداند.", - "MATH_SINGLE_TOOLTIP_LOG10": "بازگرداندن لگاریتم بر پایهٔ ۱۰ یک عدد.", - "MATH_SINGLE_TOOLTIP_EXP": "بازگرداندن توان e یک عدد.", - "MATH_SINGLE_TOOLTIP_POW10": "بازگرداندن توان ۱۰ یک عدد.", - "MATH_TRIG_HELPURL": "https://fa.wikipedia.org/wiki/%D8%AA%D8%A7%D8%A8%D8%B9%E2%80%8C%D9%87%D8%A7%DB%8C_%D9%85%D8%AB%D9%84%D8%AB%D8%A7%D8%AA%DB%8C", - "MATH_TRIG_TOOLTIP_SIN": "بازگرداندن سینوس درجه (نه رادیان).", - "MATH_TRIG_TOOLTIP_COS": "بازگرداندن کسینوس درجه (نه رادیان).", - "MATH_TRIG_TOOLTIP_TAN": "بازگرداندن تانژانت یک درجه (نه رادیان).", - "MATH_TRIG_TOOLTIP_ASIN": "بازگرداندن آرک‌سینوس درجه (نه رادیان).", - "MATH_TRIG_TOOLTIP_ACOS": "بازگرداندن آرک‌کسینوس درجه (نه رادیان).", - "MATH_TRIG_TOOLTIP_ATAN": "بازگرداندن آرک‌تانژانت درجه (نه رادیان).", - "MATH_CONSTANT_HELPURL": "https://fa.wikipedia.org/wiki/%D8%AB%D8%A7%D8%A8%D8%AA_%D8%B1%DB%8C%D8%A7%D8%B6%DB%8C", - "MATH_CONSTANT_TOOLTIP": "یکی از مقادیر مشترک را برمی‌گرداند: π (۳٫۱۴۱…)، e (۲٫۷۱۸...)، φ (۱٫۶۱۸)، sqrt(۲) (۱٫۴۱۴)، sqrt(۱/۲) (۰٫۷۰۷...) و یا ∞ (بی‌نهایت).", - "MATH_IS_EVEN": "زوج است", - "MATH_IS_ODD": "فرد است", - "MATH_IS_PRIME": "عدد اول است", - "MATH_IS_WHOLE": "کامل است", - "MATH_IS_POSITIVE": "مثبت است", - "MATH_IS_NEGATIVE": "منفی است", - "MATH_IS_DIVISIBLE_BY": "تقسیم شده بر", - "MATH_IS_TOOLTIP": "بررسی می‌کند که آیا یک عدد زوج، فرد، اول، کامل، مثبت، منفی یا بخش‌پذیر عدد خاصی باشد را بررسی می‌کند. درست یا نادرست باز می‌گرداند.", - "MATH_CHANGE_HELPURL": "https://fa.wikipedia.org/wiki/%D8%A7%D8%B5%D8%B7%D9%84%D8%A7%D8%AD_%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87%E2%80%8C%D9%86%D9%88%DB%8C%D8%B3%DB%8C#.D8.A7.D9.81.D8.B2.D8.A7.DB.8C.D8.B4_.D8.B4.D9.85.D8.A7.D8.B1.D9.86.D8.AF.D9.87", - "MATH_CHANGE_TITLE": "تغییر %1 با %2", - "MATH_CHANGE_TOOLTIP": "افزودن یک عدد به متغیر '%1'.", - "MATH_ROUND_HELPURL": "https://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29", - "MATH_ROUND_TOOLTIP": "گردکردن یک عدد به بالا یا پایین.", - "MATH_ROUND_OPERATOR_ROUND": "گردکردن", - "MATH_ROUND_OPERATOR_ROUNDUP": "گرد به بالا", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "گرد به پایین", - "MATH_ONLIST_OPERATOR_SUM": "جمع فهرست", - "MATH_ONLIST_TOOLTIP_SUM": "جمع همهٔ عددهای فهرست را باز می‌گرداند.", - "MATH_ONLIST_OPERATOR_MIN": "کوچکترین فهرست", - "MATH_ONLIST_TOOLTIP_MIN": "کوچک‌ترین عدد در فهرست را باز می‌گرداند.", - "MATH_ONLIST_OPERATOR_MAX": "بزرگ‌ترین فهرست", - "MATH_ONLIST_TOOLTIP_MAX": "بزرگ‌ترین عدد در فهرست را باز می‌گرداند.", - "MATH_ONLIST_OPERATOR_AVERAGE": "میانگین فهرست", - "MATH_ONLIST_TOOLTIP_AVERAGE": "میانگین (میانگین ریاضی) مقادیر عددی فهرست را بر می‌گرداند.", - "MATH_ONLIST_OPERATOR_MEDIAN": "میانهٔ فهرست", - "MATH_ONLIST_TOOLTIP_MEDIAN": "میانهٔ عدد در فهرست را بر می‌گرداند.", - "MATH_ONLIST_OPERATOR_MODE": "مد فهرست", - "MATH_ONLIST_TOOLTIP_MODE": "شایع‌ترین قلم(های) در فهرست را بر می‌گرداند.", - "MATH_ONLIST_OPERATOR_STD_DEV": "انحراف معیار فهرست", - "MATH_ONLIST_TOOLTIP_STD_DEV": "انحراف معیار فهرست را بر می‌گرداند.", - "MATH_ONLIST_OPERATOR_RANDOM": "مورد تصادفی از فهرست", - "MATH_ONLIST_TOOLTIP_RANDOM": "موردی تصادفی از فهرست را بر می‌گرداند.", - "MATH_MODULO_HELPURL": "https://fa.wikipedia.org/wiki/%D8%B9%D9%85%D9%84%DB%8C%D8%A7%D8%AA_%D9%BE%DB%8C%D9%85%D8%A7%D9%86%D9%87", - "MATH_MODULO_TITLE": "باقی‌ماندهٔ %1 + %2", - "MATH_MODULO_TOOLTIP": "باقی‌ماندهٔ تقسیم دو عدد را بر می‌گرداند.", - "MATH_CONSTRAIN_TITLE": "محدودکردن %1 پایین %2 بالا %3", - "MATH_CONSTRAIN_TOOLTIP": "محدودکردن یک عدد بین محدودیت‌های مشخص‌شده (بسته).", - "MATH_RANDOM_INT_HELPURL": "https://fa.wikipedia.org/wiki/%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D8%A7%D8%B9%D8%AF%D8%A7%D8%AF_%D8%AA%D8%B5%D8%A7%D8%AF%D9%81%DB%8C", - "MATH_RANDOM_INT_TITLE": "عدد صحیح تصادفی بین %1 تا %2", - "MATH_RANDOM_INT_TOOLTIP": "یک عدد تصادفی بین دو مقدار مشخص‌شده به صورت بسته باز می‌گرداند.", - "MATH_RANDOM_FLOAT_HELPURL": "https://fa.wikipedia.org/wiki/%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D8%A7%D8%B9%D8%AF%D8%A7%D8%AF_%D8%AA%D8%B5%D8%A7%D8%AF%D9%81%DB%8C", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "کسر تصادفی", - "MATH_RANDOM_FLOAT_TOOLTIP": "بازگرداندن کسری تصادفی بین ۰٫۰ (بسته) تا ۱٫۰ (باز).", - "TEXT_TEXT_HELPURL": "https://fa.wikipedia.org/wiki/%D8%B1%D8%B4%D8%AA%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29", - "TEXT_TEXT_TOOLTIP": "یک حرف، کلمه یا خطی از متن.", - "TEXT_JOIN_TITLE_CREATEWITH": "ایجاد متن با", - "TEXT_JOIN_TOOLTIP": "یک تکه‌ای از متن را با چسپاندن همهٔ تعداد از موارد ایجاد می‌کند.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "عضویت", - "TEXT_CREATE_JOIN_TOOLTIP": "اضافه، حذف یا ترتیب‌سازی قسمت‌ها برای تنظیم مجدد این بلوک اگر مسدود است.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "افزودن یک مورد به متن.", - "TEXT_APPEND_TO": "به", - "TEXT_APPEND_APPENDTEXT": "الحاق متن", - "TEXT_APPEND_TOOLTIP": "الحاق متنی به متغیر «%1».", - "TEXT_LENGTH_TITLE": "طول %1", - "TEXT_LENGTH_TOOLTIP": "بازگرداندن عددی از حروف (شامل فاصله‌ها) در متن فراهم‌شده.", - "TEXT_ISEMPTY_TITLE": "%1 خالی است", - "TEXT_ISEMPTY_TOOLTIP": "اضافه‌کردن صحیح اگر متن فراهم‌شده خالی است.", - "TEXT_INDEXOF_TOOLTIP": "شاخصی از اولین آخرین رخ‌داد متن اول در متن دوم بر می‌گرداند. اگر متن یافت نشد %1 باز می‌گرداند.", - "TEXT_INDEXOF_INPUT_INTEXT": "در متن", - "TEXT_INDEXOF_OPERATOR_FIRST": "اولین رخداد متن را بیاب", - "TEXT_INDEXOF_OPERATOR_LAST": "آخرین رخداد متن را بیاب", - "TEXT_CHARAT_INPUT_INTEXT": "در متن", - "TEXT_CHARAT_FROM_START": "گرفتن حرف #", - "TEXT_CHARAT_FROM_END": "گرفتن حرف # از آخر", - "TEXT_CHARAT_FIRST": "گرفتن اولین حرف", - "TEXT_CHARAT_LAST": "گرفتن آخرین حرف", - "TEXT_CHARAT_RANDOM": "گرفتن حرف تصادفی", - "TEXT_CHARAT_TOOLTIP": "حرفی در موقعیت مشخص‌شده بر می‌گرداند.", - "TEXT_GET_SUBSTRING_TOOLTIP": "قسمت مشخصی‌شده‌ای از متن را بر می‌گرداند.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "در متن", - "TEXT_GET_SUBSTRING_START_FROM_START": "گرفتن زیرمتن از حرف #", - "TEXT_GET_SUBSTRING_START_FROM_END": "گرفتن زیرمتن از حرف # به انتها", - "TEXT_GET_SUBSTRING_START_FIRST": "گرفتن زیرمتن از اولین حرف", - "TEXT_GET_SUBSTRING_END_FROM_START": "به حرف #", - "TEXT_GET_SUBSTRING_END_FROM_END": "به حرف # از انتها", - "TEXT_GET_SUBSTRING_END_LAST": "گرفتن آخرین حرف", - "TEXT_CHANGECASE_TOOLTIP": "بازگرداندن کپی متن در حالتی متفاوت.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "به حروف بزرگ", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "به حروف کوچک", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "به حروف بزرگ عنوان", - "TEXT_TRIM_TOOLTIP": "کپی از متن با فاصله‌های حذف‌شده از یک یا هر دو پایان باز می‌گرداند.", - "TEXT_TRIM_OPERATOR_BOTH": "تراشیدن فاصله‌ها از هر دو طرف", - "TEXT_TRIM_OPERATOR_LEFT": "تراشیدن فاصله‌ها از طرف چپ", - "TEXT_TRIM_OPERATOR_RIGHT": "تراشیدن فاصله‌ها از طرف چپ", - "TEXT_PRINT_TITLE": "چاپ %1", - "TEXT_PRINT_TOOLTIP": "چاپ متن، عدد یا هر مقدار دیگر مشخص‌شده.", - "TEXT_PROMPT_TYPE_TEXT": "اعلان برای متن با پیام", - "TEXT_PROMPT_TYPE_NUMBER": "اعلان برای عدد با پیام", - "TEXT_PROMPT_TOOLTIP_NUMBER": "اعلان برای کاربر با یک عدد.", - "TEXT_PROMPT_TOOLTIP_TEXT": "اعلان برای کاربر برای یک متن.", - "LISTS_CREATE_EMPTY_TITLE": "ایجاد فهرست خالی", - "LISTS_CREATE_EMPTY_TOOLTIP": "فهرستی با طول صفر شامل هیچ رکورد داده‌ای بر می‌گرداند.", - "LISTS_CREATE_WITH_TOOLTIP": "فهرستی از هر عددی از موارد می‌سازد.", - "LISTS_CREATE_WITH_INPUT_WITH": "ایجاد فهرست با", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "فهرست", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "اضافه‌کردن، حذف‌کردن یا ترتیب‌سازی مجدد بخش‌ها این بلوک فهرستی.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "اضافه‌کردن یک مورد به فهرست.", - "LISTS_REPEAT_TOOLTIP": "فهرستی شامل مقادیر داده‌شدهٔ تکرار شده عدد مشخص‌شده می‌سازد.", - "LISTS_REPEAT_TITLE": "فهرستی با %1 تکرارشده به اندازهٔ %2 می‌سازد", - "LISTS_LENGTH_TITLE": "طول %1", - "LISTS_LENGTH_TOOLTIP": "طول یک فهرست را برمی‌گرداند.", - "LISTS_ISEMPTY_TITLE": "%1 خالی است", - "LISTS_ISEMPTY_TOOLTIP": "اگر فهرست خالی است مقدار صجیج بر می‌گرداند.", - "LISTS_INLIST": "در فهرست", - "LISTS_INDEX_OF_FIRST": "آخرین رخداد متن را بیاب", - "LISTS_INDEX_OF_LAST": "یافتن آخرین رخ‌داد مورد", - "LISTS_INDEX_OF_TOOLTIP": "شاخصی از اولین/آخرین رخ‌داد مورد در فهرست را بر می‌گرداند. %1 بر می‌گرداند اگر متن موجود نبود.", - "LISTS_GET_INDEX_GET": "گرفتن", - "LISTS_GET_INDEX_GET_REMOVE": "گرفتن و حذف‌کردن", - "LISTS_GET_INDEX_REMOVE": "حذف‌کردن", - "LISTS_GET_INDEX_FROM_END": "# از انتها", - "LISTS_GET_INDEX_FIRST": "اولین", - "LISTS_GET_INDEX_LAST": "اهرین", - "LISTS_GET_INDEX_RANDOM": "تصادفی", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 اولین مورد است.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 آخرین مورد است.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "موردی در محل مشخص‌شده بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "اولین مورد یک فهرست را بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "آخرین مورد در یک فهرست را بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "یک مورد تصادفی در یک فهرست بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "مورد در محل مشخص‌شده در فهرست را حذف و بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "اولین مورد مشخص‌شده در فهرست را حذف و بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "آخرین مورد مشخص‌شده در فهرست را حذف و بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "مورد تصادفی‌ای را در فهرست حذف و بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "مورد مشخص‌شده در موقعیت مشخص در یک فهرست را حذف و بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "اولین مورد را در یک فهرست حذف می‌کند.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "آخرین مورد را در یک فهرست حذف می‌کند.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "یک مورد تصادفی را یک فهرست حذف می‌کند.", - "LISTS_SET_INDEX_SET": "مجموعه", - "LISTS_SET_INDEX_INSERT": "درج در", - "LISTS_SET_INDEX_INPUT_TO": "به‌عنوان", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "مورد مشخص‌شده در یک فهرست را قرار می‌دهد.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "اولین مورد در یک فهرست را تعیین می‌کند.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "آخرین مورد در یک فهرست را تعیین می‌کند.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "یک مورد تصادفی در یک فهرست را تعیین می‌کند.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "موردی در موقعیت مشخص‌شده در یک فهرست اضافه می‌کند.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "موردی به ته فهرست اضافه می‌کند.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "موردی به ته فهرست الحاق می‌کند.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "مورد را به صورت تصادفی در یک فهرست می‌افزاید.", - "LISTS_GET_SUBLIST_START_FROM_START": "گرفتن زیرمجموعه‌ای از #", - "LISTS_GET_SUBLIST_START_FROM_END": "گرفتن زیرمجموعه‌ای از # از انتها", - "LISTS_GET_SUBLIST_START_FIRST": "گرفتن زیرمجموعه‌ای از ابتدا", - "LISTS_GET_SUBLIST_END_FROM_START": "به #", - "LISTS_GET_SUBLIST_END_FROM_END": "به # از انتها", - "LISTS_GET_SUBLIST_END_LAST": "به آخرین", - "LISTS_GET_SUBLIST_TOOLTIP": "کپی از قسمت مشخص‌شدهٔ لیست درست می‌کند.", - "VARIABLES_GET_TOOLTIP": "مقدار این متغیر را بر می‌گرداند.", - "VARIABLES_GET_CREATE_SET": "درست‌کردن «تنظیم %1»", - "VARIABLES_SET": "مجموعه %1 به %2", - "VARIABLES_SET_TOOLTIP": "متغیر برابر با خروجی را مشخص می‌کند.", - "VARIABLES_SET_CREATE_GET": "درست‌کردن «تنظیم %1»", - "PROCEDURES_DEFNORETURN_TITLE": "به", - "PROCEDURES_DEFNORETURN_PROCEDURE": "انجام چیزی", - "PROCEDURES_BEFORE_PARAMS": "با:", - "PROCEDURES_CALL_BEFORE_PARAMS": "با:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "تابعی می‌سازد بدون هیچ خروجی.", - "PROCEDURES_DEFRETURN_RETURN": "بازگشت", - "PROCEDURES_DEFRETURN_TOOLTIP": "تابعی با یک خروجی می‌سازد.", - "PROCEDURES_ALLOW_STATEMENTS": "اجازه اظهارات", - "PROCEDURES_DEF_DUPLICATE_WARNING": "اخطار: این تابعی پارامتر تکراری دارد.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "اجرای تابع تعریف‌شده توسط کاربر «%1».", - "PROCEDURES_CALLRETURN_HELPURL": "https://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "اجرای تابع تعریف‌شده توسط کاربر «%1» و استفاده از خروجی آن.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "ورودی‌ها", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "افزودن، حذف یا دوباره مرتب‌کردن ورودی این تابع.", - "PROCEDURES_MUTATORARG_TITLE": "نام ورودی:", - "PROCEDURES_MUTATORARG_TOOLTIP": "اضافه کردن ورودی به تابع.", - "PROCEDURES_HIGHLIGHT_DEF": "برجسته‌سازی تعریف تابع", - "PROCEDURES_CREATE_DO": "ساختن «%1»", - "PROCEDURES_IFRETURN_TOOLTIP": "اگر یک مقدار صحیح است، مقدار دوم را برگردان.", - "PROCEDURES_IFRETURN_WARNING": "اخطار: این بلوک احتمالاً فقط داخل یک تابع استفاده می‌شود." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/be-tarask.json b/backend/_pv_1_3_5/static/blockly/msg/json/be-tarask.json deleted file mode 100755 index 353ea3260..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/be-tarask.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Renessaince", - "Jim-by", - "Red Winged Duck" - ] - }, - "VARIABLES_DEFAULT_NAME": "аб’ект", - "TODAY": "Сёньня", - "DUPLICATE_BLOCK": "Капіяваць", - "ADD_COMMENT": "Дадаць камэнтар", - "REMOVE_COMMENT": "Выдаліць камэнтар", - "EXTERNAL_INPUTS": "Зьнешнія ўваходы", - "INLINE_INPUTS": "Унутраныя ўваходы", - "DELETE_BLOCK": "Выдаліць блёк", - "DELETE_X_BLOCKS": "Выдаліць %1 блёкі", - "DELETE_ALL_BLOCKS": "Выдаліць усе блёкі %1?", - "CLEAN_UP": "Ачысьціць блёкі", - "COLLAPSE_BLOCK": "Згарнуць блёк", - "COLLAPSE_ALL": "Згарнуць блёкі", - "EXPAND_BLOCK": "Разгарнуць блёк", - "EXPAND_ALL": "Разгарнуць блёкі", - "DISABLE_BLOCK": "Адключыць блёк", - "ENABLE_BLOCK": "Уключыць блёк", - "HELP": "Дапамога", - "UNDO": "Скасаваць", - "REDO": "Паўтарыць", - "CHANGE_VALUE_TITLE": "Зьмяніць значэньне:", - "RENAME_VARIABLE": "Перайменаваць зьменную…", - "RENAME_VARIABLE_TITLE": "Перайменаваць усе назвы зьменных '%1' на:", - "NEW_VARIABLE": "Стварыць зьменную…", - "NEW_VARIABLE_TITLE": "Імя новай зьменнай:", - "VARIABLE_ALREADY_EXISTS": "Зьменная з назвай «%1» ужо існуе.", - "DELETE_VARIABLE_CONFIRMATION": "Выдаліць %1 выкарыстаньняў зьменнай «%2»?", - "DELETE_VARIABLE": "Выдаліць зьменную «%1»", - "COLOUR_PICKER_HELPURL": "https://be-x-old.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BB%D0%B5%D1%80", - "COLOUR_PICKER_TOOLTIP": "Абярыце колер з палітры.", - "COLOUR_RANDOM_TITLE": "выпадковы колер", - "COLOUR_RANDOM_TOOLTIP": "Абраць выпадковы колер.", - "COLOUR_RGB_TITLE": "колер з", - "COLOUR_RGB_RED": "чырвонага", - "COLOUR_RGB_GREEN": "зялёнага", - "COLOUR_RGB_BLUE": "сіняга", - "COLOUR_RGB_TOOLTIP": "Стварыць колер з абранымі прапорцыямі чырвонага, зялёнага і сіняга. Усе значэньні павінны быць ад 0 да 100.", - "COLOUR_BLEND_TITLE": "зьмяшаць", - "COLOUR_BLEND_COLOUR1": "колер 1", - "COLOUR_BLEND_COLOUR2": "колер 2", - "COLOUR_BLEND_RATIO": "дзеля", - "COLOUR_BLEND_TOOLTIP": "Зьмешвае два колеры ў дадзенай прапорцыі (0.0 — 1.0)", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "паўтарыць %1 раз(ы)", - "CONTROLS_REPEAT_INPUT_DO": "выканаць", - "CONTROLS_REPEAT_TOOLTIP": "Выконвае апэрацыі некалькі разоў.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "паўтараць, пакуль", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "паўтараць, пакуль не", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Пакуль значэньне ісьціна, выконваць пэўныя апэрацыі.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Пакуль значэньне хлусьня, выконваць пэўныя апэрацыі.", - "CONTROLS_FOR_TOOLTIP": "Прысвойвае зьменнай \"%1\" значэньні ад пачатковага да канчатковага значэньня, улічваючы зададзены крок, і выконвае абраныя блёкі.", - "CONTROLS_FOR_TITLE": "лічыць з %1 ад %2 да %3 па %4", - "CONTROLS_FOREACH_TITLE": "для кожнага элемэнта %1 у сьпісе %2", - "CONTROLS_FOREACH_TOOLTIP": "Для кожнага элемэнту сьпісу прысвойвае зьменнай '%1' ягонае значэньне і выконвае пэўныя апэрацыі.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "перарваць цыкль", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "працягнуць з наступнага кроку цыклю", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Спыніць гэты цыкль.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Прапусьціць рэшту цыклю і перайсьці да наступнага кроку.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Увага: гэты блёк можа быць выкарыстаны толькі ў цыклі.", - "CONTROLS_IF_TOOLTIP_1": "Калі значэньне ісьціна, выканаць пэўныя апэрацыі.", - "CONTROLS_IF_TOOLTIP_2": "Калі значэньне ісьціна, выканаць першы блёк апэрацыяў, інакш выканаць другі блёк.", - "CONTROLS_IF_TOOLTIP_3": "Калі першае значэньне ісьціна, выканаць першы блёк апэрацыяў. Інакш, калі другое значэньне ісьціна, выканаць другі блёк апэрацыяў.", - "CONTROLS_IF_TOOLTIP_4": "Калі першае значэньне ісьціна, выканаць першы блёк апэрацыяў. Інакш, калі другое значэньне ісьціна, выканаць другі блёк апэрацыяў. Калі ніводнае з значэньняў не сапраўднае, выканаць апошні блёк апэрацыяў.", - "CONTROLS_IF_MSG_IF": "калі", - "CONTROLS_IF_MSG_ELSEIF": "інакш, калі", - "CONTROLS_IF_MSG_ELSE": "інакш", - "CONTROLS_IF_IF_TOOLTIP": "Дадаць, выдаліць ці пераставіць сэкцыі для пераканфігураваньня гэтага блёку «калі».", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Дадаць умову да блёку «калі».", - "CONTROLS_IF_ELSE_TOOLTIP": "Дадаць заключную ўмову для ўсіх астатніх варыянтаў блёку «калі».", - "LOGIC_COMPARE_HELPURL": "https://be-x-old.wikipedia.org/wiki/%D0%9D%D1%8F%D1%80%D0%BE%D1%9E%D0%BD%D0%B0%D1%81%D1%8C%D1%86%D1%8C", - "LOGIC_COMPARE_TOOLTIP_EQ": "Вяртае «ісьціна», калі абодва ўводы роўныя.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Вяртае «ісьціна», калі абодва ўводы ня роўныя.", - "LOGIC_COMPARE_TOOLTIP_LT": "Вяртае «ісьціна», калі першы ўвод меншы за другі.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Вяртае «ісьціна», калі першы ўвод меншы ці роўны другому.", - "LOGIC_COMPARE_TOOLTIP_GT": "Вяртае «ісьціна», калі першы ўвод большы за другі.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Вяртае «ісьціна», калі першы ўвод большы ці роўны другому.", - "LOGIC_OPERATION_TOOLTIP_AND": "Вяртае «ісьціна», калі абодва ўводы праўдзівыя.", - "LOGIC_OPERATION_AND": "і", - "LOGIC_OPERATION_TOOLTIP_OR": "Вяртае «ісьціна», калі прынамсі адзін з уводаў праўдзівы.", - "LOGIC_OPERATION_OR": "ці", - "LOGIC_NEGATE_TITLE": "не %1", - "LOGIC_NEGATE_TOOLTIP": "Вяртае «ісьціна», калі ўвод непраўдзівы. Вяртае «хлусьня», калі ўвод праўдзівы.", - "LOGIC_BOOLEAN_TRUE": "ісьціна", - "LOGIC_BOOLEAN_FALSE": "хлусьня", - "LOGIC_BOOLEAN_TOOLTIP": "Вяртае «ісьціна» ці «хлусьня».", - "LOGIC_NULL": "нічога", - "LOGIC_NULL_TOOLTIP": "Вяртае нічога.", - "LOGIC_TERNARY_CONDITION": "тэст", - "LOGIC_TERNARY_IF_TRUE": "калі ісьціна", - "LOGIC_TERNARY_IF_FALSE": "калі хлусьня", - "LOGIC_TERNARY_TOOLTIP": "Праверыць умову ў 'тэст'. Калі ўмова праўдзівая, будзе вернутае значэньне «калі ісьціна»; інакш будзе вернутае «калі хлусьня».", - "MATH_NUMBER_HELPURL": "https://be-x-old.wikipedia.org/wiki/%D0%9B%D1%96%D0%BA", - "MATH_NUMBER_TOOLTIP": "Лік.", - "MATH_ARITHMETIC_HELPURL": "https://be-x-old.wikipedia.org/wiki/%D0%90%D1%80%D1%8B%D1%82%D0%BC%D1%8D%D1%82%D1%8B%D0%BA%D0%B0", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Вяртае суму двух лікаў.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Вяртае рознасьць двух лікаў.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Вяртае здабытак двух лікаў.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Вяртае дзель двух лікаў.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Вяртае першы лік у ступені другога ліку.", - "MATH_SINGLE_HELPURL": "https://be-x-old.wikipedia.org/wiki/%D0%9A%D0%B2%D0%B0%D0%B4%D1%80%D0%B0%D1%82%D0%BD%D1%8B_%D0%BA%D0%BE%D1%80%D0%B0%D0%BD%D1%8C", - "MATH_SINGLE_OP_ROOT": "квадратны корань", - "MATH_SINGLE_TOOLTIP_ROOT": "Вяртае квадратны корань ліку.", - "MATH_SINGLE_OP_ABSOLUTE": "модуль", - "MATH_SINGLE_TOOLTIP_ABS": "Вяртае модуль ліку.", - "MATH_SINGLE_TOOLTIP_NEG": "Вяртае супрацьлеглы лік.", - "MATH_SINGLE_TOOLTIP_LN": "Вяртае натуральны лягарытм ліку.", - "MATH_SINGLE_TOOLTIP_LOG10": "Вяртае дзесятковы лягарытм ліку.", - "MATH_SINGLE_TOOLTIP_EXP": "Вяртае e ў ступені ліку.", - "MATH_SINGLE_TOOLTIP_POW10": "Вяртае 10 у ступені ліку.", - "MATH_TRIG_HELPURL": "https://be-x-old.wikipedia.org/wiki/%D0%A2%D1%80%D1%8B%D0%B3%D0%B0%D0%BD%D0%B0%D0%BC%D1%8D%D1%82%D1%80%D1%8B%D1%8F#.D0.A2.D1.80.D1.8B.D0.B3.D0.B0.D0.BD.D0.B0.D0.BC.D1.8D.D1.82.D1.80.D1.8B.D1.87.D0.BD.D1.8B.D1.8F_.D1.84.D1.83.D0.BD.D0.BA.D1.86.D1.8B.D1.96", - "MATH_TRIG_TOOLTIP_SIN": "Вяртае сынус кута ў градусах.", - "MATH_TRIG_TOOLTIP_COS": "Вяртае косынус кута ў градусах.", - "MATH_TRIG_TOOLTIP_TAN": "Вяртае тангэнс кута ў градусах.", - "MATH_TRIG_TOOLTIP_ASIN": "Вяртае арксынус ліку.", - "MATH_TRIG_TOOLTIP_ACOS": "Вяртае арккосынус ліку.", - "MATH_TRIG_TOOLTIP_ATAN": "Вяртае арктангэнс ліку.", - "MATH_CONSTANT_HELPURL": "https://be-x-old.wikipedia.org/wiki/%D0%9C%D0%B0%D1%82%D1%8D%D0%BC%D0%B0%D1%82%D1%8B%D1%87%D0%BD%D0%B0%D1%8F_%D0%BA%D0%B0%D0%BD%D1%81%D1%82%D0%B0%D0%BD%D1%82%D0%B0", - "MATH_CONSTANT_TOOLTIP": "Вяртае адну з агульных канстантаў: π (3.141...), e (2.718...), φ (1.618...), sqrt(2) (1.414...), sqrt(½) (0,707...) або ∞ (бясконцасьць).", - "MATH_IS_EVEN": "парная", - "MATH_IS_ODD": "няпарная", - "MATH_IS_PRIME": "простая", - "MATH_IS_WHOLE": "цэлая", - "MATH_IS_POSITIVE": "станоўчая", - "MATH_IS_NEGATIVE": "адмоўная", - "MATH_IS_DIVISIBLE_BY": "дзяліць на", - "MATH_IS_TOOLTIP": "Правярае, ці зьяўляецца лік парным, няпарным, простым, станоўчым, адмоўным, ці ён дзеліцца на пэўны лік без астатку. Вяртае значэньне ісьціна або няпраўда.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "зьмяніць %1 на %2", - "MATH_CHANGE_TOOLTIP": "Дадае лічбу да зьменнай '%1'.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Акругленьне ліку да большага ці меншага.", - "MATH_ROUND_OPERATOR_ROUND": "акругліць", - "MATH_ROUND_OPERATOR_ROUNDUP": "акругліць да большага", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "акругліць да меншага", - "MATH_ONLIST_OPERATOR_SUM": "Сума сьпісу", - "MATH_ONLIST_TOOLTIP_SUM": "Вяртае суму ўсіх лікаў у сьпісе.", - "MATH_ONLIST_OPERATOR_MIN": "мінімальная ў сьпісе", - "MATH_ONLIST_TOOLTIP_MIN": "Вяртае найменшы лік у сьпісе.", - "MATH_ONLIST_OPERATOR_MAX": "мінімальная ў сьпісе", - "MATH_ONLIST_TOOLTIP_MAX": "Вяртае найменшы лік у сьпісе.", - "MATH_ONLIST_OPERATOR_AVERAGE": "сярэдняя ў сьпісе", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Вяртае сярэднеарытмэтычнае значэньне лікавых значэньняў у сьпісе.", - "MATH_ONLIST_OPERATOR_MEDIAN": "мэдыяна сьпісу", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Вяртае мэдыяну сьпісу.", - "MATH_ONLIST_OPERATOR_MODE": "рэжымы сьпісу", - "MATH_ONLIST_TOOLTIP_MODE": "Вяртае сьпіс самых распаўсюджаных элемэнтаў у сьпісе.", - "MATH_ONLIST_OPERATOR_STD_DEV": "стандартнае адхіленьне сьпісу", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Вяртае стандартнае адхіленьне сьпісу.", - "MATH_ONLIST_OPERATOR_RANDOM": "выпадковы элемэнт сьпісу", - "MATH_ONLIST_TOOLTIP_RANDOM": "Вяртае выпадковы элемэнт сьпісу.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "рэшта дзяленьня %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Вяртае рэшту дзяленьня двух лікаў.", - "MATH_CONSTRAIN_TITLE": "абмежаваць %1 зьнізу %2 зьверху %3", - "MATH_CONSTRAIN_TOOLTIP": "Абмяжоўвае колькасьць ніжняй і верхняй межамі (уключна).", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "выпадковая цэлая з %1 для %2", - "MATH_RANDOM_INT_TOOLTIP": "Вяртае выпадковы цэлы лік паміж двума зададзенымі абмежаваньнямі ўключна.", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "выпадковая дроб", - "MATH_RANDOM_FLOAT_TOOLTIP": "Вяртае выпадковую дроб у дыяпазоне ад 0,0 (уключна) да 1,0.", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "Літара, слова ці радок тэксту.", - "TEXT_JOIN_TITLE_CREATEWITH": "стварыць тэкст з", - "TEXT_JOIN_TOOLTIP": "Стварае фрагмэнт тэксту аб’яднаньнем любой колькасьці элемэнтаў.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "далучыць", - "TEXT_CREATE_JOIN_TOOLTIP": "Дадайце, выдаліце ці зьмяніце парадак разьдзелаў для перадачы тэкставага блёку.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Дадаць элемэнт да тэксту.", - "TEXT_APPEND_TO": "да", - "TEXT_APPEND_APPENDTEXT": "дадаць тэкст", - "TEXT_APPEND_TOOLTIP": "Дадаць які-небудзь тэкст да зьменнай '%1'.", - "TEXT_LENGTH_TITLE": "даўжыня %1", - "TEXT_LENGTH_TOOLTIP": "Вяртае колькасьць літараў (у тым ліку прабелы) у пададзеным тэксьце.", - "TEXT_ISEMPTY_TITLE": "%1 пусты", - "TEXT_ISEMPTY_TOOLTIP": "Вяртае значэньне ісьціна, калі тэкст пусты.", - "TEXT_INDEXOF_TOOLTIP": "Вяртае індэкс першага/апошняга ўваходжаньня першага тэксту ў другі тэкст. Вяртае %1, калі тэкст ня знойдзены.", - "TEXT_INDEXOF_INPUT_INTEXT": "у тэксьце", - "TEXT_INDEXOF_OPERATOR_FIRST": "знайсьці першае ўваходжаньне тэксту", - "TEXT_INDEXOF_OPERATOR_LAST": "знайсьці апошняе ўваходжаньне тэксту", - "TEXT_CHARAT_INPUT_INTEXT": "у тэксьце", - "TEXT_CHARAT_FROM_START": "узяць літару №", - "TEXT_CHARAT_FROM_END": "узяць літару № з канца", - "TEXT_CHARAT_FIRST": "узяць першую літару", - "TEXT_CHARAT_LAST": "узяць апошнюю літару", - "TEXT_CHARAT_RANDOM": "узяць выпадковую літару", - "TEXT_CHARAT_TOOLTIP": "Вяртае літару ў пазначанай пазыцыі.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Вяртае пазначаную частку тэксту.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "у тэксьце", - "TEXT_GET_SUBSTRING_START_FROM_START": "узяць падрадок зь літары №", - "TEXT_GET_SUBSTRING_START_FROM_END": "узяць падрадок зь літары № з канца", - "TEXT_GET_SUBSTRING_START_FIRST": "атрымаць падрадок зь першай літары", - "TEXT_GET_SUBSTRING_END_FROM_START": "да літары №", - "TEXT_GET_SUBSTRING_END_FROM_END": "да літары № з канца", - "TEXT_GET_SUBSTRING_END_LAST": "да апошняй літары", - "TEXT_CHANGECASE_TOOLTIP": "Вярнуць копію тэксту зь іншай велічынёй літар.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "да ВЕРХНЯГА РЭГІСТРУ", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "да ніжняга рэгістру", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "Вялікія Першыя Літары", - "TEXT_TRIM_TOOLTIP": "Вяртае копію тэксту з прабеламі, выдаленымі ад аднаго ці абодвух бакоў.", - "TEXT_TRIM_OPERATOR_BOTH": "абрэзаць прабелы з абодвух бакоў", - "TEXT_TRIM_OPERATOR_LEFT": "абрэзаць прабелы зь левага боку", - "TEXT_TRIM_OPERATOR_RIGHT": "абрэзаць прабелы з правага боку", - "TEXT_PRINT_TITLE": "друкаваць %1", - "TEXT_PRINT_TOOLTIP": "Надрукаваць пазначаны тэкст, лічбу ці іншыя сымбалі.", - "TEXT_PROMPT_TYPE_TEXT": "запытаць тэкст з падказкай", - "TEXT_PROMPT_TYPE_NUMBER": "запытаць лічбу з падказкай", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Запытаць у карыстальніка лічбу.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Запытаць у карыстальніка тэкст.", - "LISTS_CREATE_EMPTY_TITLE": "стварыць пусты сьпіс", - "LISTS_CREATE_EMPTY_TOOLTIP": "Вяртае сьпіс даўжынёй 0, які ня ўтрымлівае запісаў зьвестак", - "LISTS_CREATE_WITH_TOOLTIP": "Ставарае сьпіс зь любой колькасьцю элемэнтаў.", - "LISTS_CREATE_WITH_INPUT_WITH": "стварыць сьпіс з", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "сьпіс", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Дадаць, выдаліць ці пераставіць сэкцыі для пераканфігураваньня гэтага блёку.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Дадаць элемэнт да сьпісу.", - "LISTS_REPEAT_TOOLTIP": "Стварае сьпіс, які ўтрымлівае пададзеную колькасьць копіяў элемэнту.", - "LISTS_REPEAT_TITLE": "стварыць сьпіс з элемэнту %1, які паўтараецца %2 разоў", - "LISTS_LENGTH_TITLE": "даўжыня %1", - "LISTS_LENGTH_TOOLTIP": "Вяртае даўжыню сьпісу.", - "LISTS_ISEMPTY_TITLE": "%1 пусты", - "LISTS_ISEMPTY_TOOLTIP": "Вяртае значэньне ісьціна, калі сьпіс пусты.", - "LISTS_INLIST": "у сьпісе", - "LISTS_INDEX_OF_FIRST": "знайсьці першае ўваходжаньне элемэнту", - "LISTS_INDEX_OF_LAST": "знайсьці апошняе ўваходжаньне элемэнту", - "LISTS_INDEX_OF_TOOLTIP": "Вяртае індэкс першага/апошняга ўваходжаньня элемэнту ў сьпіс. Вяртае %1, калі элемэнт ня знойдзены.", - "LISTS_GET_INDEX_GET": "атрымаць", - "LISTS_GET_INDEX_GET_REMOVE": "атрымаць і выдаліць", - "LISTS_GET_INDEX_REMOVE": "выдаліць", - "LISTS_GET_INDEX_FROM_END": "№ з канца", - "LISTS_GET_INDEX_FIRST": "першы", - "LISTS_GET_INDEX_LAST": "апошні", - "LISTS_GET_INDEX_RANDOM": "выпадковы", - "LISTS_INDEX_FROM_START_TOOLTIP": "№%1 — першы элемэнт.", - "LISTS_INDEX_FROM_END_TOOLTIP": "№%1 — апошні элемэнт.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Вяртае элемэнт у пазначанай пазыцыі ў сьпісе.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Вяртае першы элемэнт у сьпісе.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Вяртае апошні элемэнт у сьпісе.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Вяртае выпадковы элемэнт у сьпісе.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Выдаляе і вяртае элемэнт у пазначанай пазыцыі ў сьпісе.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Выдаляе і вяртае першы элемэнт у сьпісе.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Выдаляе і вяртае апошні элемэнт у сьпісе.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Выдаляе і вяртае выпадковы элемэнт у сьпісе.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Выдаляе элемэнт у пазначанай пазыцыі ў сьпісе.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Выдаляе першы элемэнт у сьпісе.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Выдаляе апошні элемэнт у сьпісе.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Выдаляе выпадковы элемэнт у сьпісе.", - "LISTS_SET_INDEX_SET": "усталяваць", - "LISTS_SET_INDEX_INSERT": "уставіць у", - "LISTS_SET_INDEX_INPUT_TO": "як", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Задае элемэнт у пазначанай пазыцыі ў сьпісе.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Задае першы элемэнт у сьпісе.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Задае апошні элемэнт у сьпісе.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Задае выпадковы элемэнт у сьпісе.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Устаўляе элемэнт у пазначанай пазыцыі ў сьпісе.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Устаўляе элемэнт у пачатак сьпісу.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Дадае элемэнт у канец сьпісу.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Выпадковым чынам устаўляе элемэнт у сьпіс.", - "LISTS_GET_SUBLIST_START_FROM_START": "атрымаць падсьпіс з №", - "LISTS_GET_SUBLIST_START_FROM_END": "атрымаць падсьпіс з № з канца", - "LISTS_GET_SUBLIST_START_FIRST": "атрымаць падсьпіс зь першага", - "LISTS_GET_SUBLIST_END_FROM_START": "да #", - "LISTS_GET_SUBLIST_END_FROM_END": "па № з канца", - "LISTS_GET_SUBLIST_END_LAST": "да апошняга", - "LISTS_GET_SUBLIST_TOOLTIP": "Стварае копію пазначанай часткі сьпісу.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "сартаваць %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Сартаваць копію сьпісу.", - "LISTS_SORT_ORDER_ASCENDING": "па павелічэньні", - "LISTS_SORT_ORDER_DESCENDING": "па зьмяншэньні", - "LISTS_SORT_TYPE_NUMERIC": "як лікі", - "LISTS_SORT_TYPE_TEXT": "паводле альфабэту", - "LISTS_SORT_TYPE_IGNORECASE": "паводле альфабэту, ігнараваць рэгістар", - "LISTS_SPLIT_LIST_FROM_TEXT": "стварыць сьпіс з тэксту", - "LISTS_SPLIT_TEXT_FROM_LIST": "стварыць тэкст са сьпісу", - "LISTS_SPLIT_WITH_DELIMITER": "з падзяляльнікам", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Падзяліць тэкст у сьпіс тэкстаў, па падзяляльніках.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Аб’ядноўвае сьпіс тэкстаў у адзін тэкст па падзяляльніках.", - "VARIABLES_GET_TOOLTIP": "Вяртае значэньне гэтай зьменнай.", - "VARIABLES_GET_CREATE_SET": "Стварыць блёк «усталяваць %1»", - "VARIABLES_SET": "усталяваць %1 да %2", - "VARIABLES_SET_TOOLTIP": "Надаць гэтай зьменнай значэньне ўстаўкі.", - "VARIABLES_SET_CREATE_GET": "Стварыць блёк «атрымаць %1»", - "PROCEDURES_DEFNORETURN_TITLE": "да", - "PROCEDURES_DEFNORETURN_PROCEDURE": "зрабіць што-небудзь", - "PROCEDURES_BEFORE_PARAMS": "з:", - "PROCEDURES_CALL_BEFORE_PARAMS": "з:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Стварае функцыю бяз выніку.", - "PROCEDURES_DEFNORETURN_COMMENT": "Апішыце гэтую функцыю…", - "PROCEDURES_DEFRETURN_RETURN": "вярнуць", - "PROCEDURES_DEFRETURN_TOOLTIP": "Стварае функцыю з вынікам.", - "PROCEDURES_ALLOW_STATEMENTS": "дазволіць зацьвярджэньне", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Увага: гэтая функцыя мае парамэтры-дублікаты.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Запусьціць функцыю вызначаную карыстальнікам '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Запусьціць функцыю вызначаную карыстальнікам '%1' і выкарыстаць яе вынік.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "парамэтры", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Дадаць, выдаліць ці запісаць чаргу ўваходных парамэтраў для гэтай функцыі.", - "PROCEDURES_MUTATORARG_TITLE": "назва парамэтру:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Дадаць уваходныя парамэтры ў функцыю.", - "PROCEDURES_HIGHLIGHT_DEF": "Падсьвяціць вызначэньне функцыі", - "PROCEDURES_CREATE_DO": "Стварыць '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Калі значэньне ісьціна, вярнуць другое значэньне.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Папярэджаньне: гэты блёк можа выкарыстоўвацца толькі ў вызначанай функцыі." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/bg.json b/backend/_pv_1_3_5/static/blockly/msg/json/bg.json deleted file mode 100755 index 336c2af7a..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/bg.json +++ /dev/null @@ -1,312 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Gkostov", - "Vodnokon4e", - "Alpinistbg", - "Miroslav35232", - "StanProg" - ] - }, - "VARIABLES_DEFAULT_NAME": "елемент", - "TODAY": "Днес", - "DUPLICATE_BLOCK": "Копирай", - "ADD_COMMENT": "Добави коментар", - "REMOVE_COMMENT": "Премахни коментар", - "EXTERNAL_INPUTS": "Външни входове", - "INLINE_INPUTS": "Вътрешни входове", - "DELETE_BLOCK": "Изтрий блок", - "DELETE_X_BLOCKS": "Изтрий %1 блока", - "DELETE_ALL_BLOCKS": "Изтриване на всички 1% блокове?", - "CLEAN_UP": "Премахни блокове", - "COLLAPSE_BLOCK": "Скрий блок", - "COLLAPSE_ALL": "Скрий блокове", - "EXPAND_BLOCK": "Покажи блок", - "EXPAND_ALL": "Покажи блокове", - "DISABLE_BLOCK": "Деактивирай блок", - "ENABLE_BLOCK": "Активирай блок", - "HELP": "Помощ", - "UNDO": "Отмяна", - "REDO": "Повторение", - "CHANGE_VALUE_TITLE": "Промени стойността:", - "RENAME_VARIABLE": "Преименувай променливата...", - "RENAME_VARIABLE_TITLE": "Преименувай всички '%1' променливи на:", - "NEW_VARIABLE": "Нова променлива...", - "NEW_VARIABLE_TITLE": "Ново име на променливата:", - "COLOUR_PICKER_HELPURL": "https://bg.wikipedia.org/wiki/Цвят_(оптика)", - "COLOUR_PICKER_TOOLTIP": "Избери цвят от палитрата.", - "COLOUR_RANDOM_TITLE": "случаен цвят", - "COLOUR_RANDOM_TOOLTIP": "Избери цвят на случаен принцип.", - "COLOUR_RGB_TITLE": "оцвети с", - "COLOUR_RGB_RED": "червен", - "COLOUR_RGB_GREEN": "зелен", - "COLOUR_RGB_BLUE": "син", - "COLOUR_RGB_TOOLTIP": "Създай цвят с избраните пропорции, червено, зелено и синьо. Всички стойности трябва да бъдат от 0 до 100.", - "COLOUR_BLEND_TITLE": "смеси", - "COLOUR_BLEND_COLOUR1": "цвят 1", - "COLOUR_BLEND_COLOUR2": "цвят 2", - "COLOUR_BLEND_RATIO": "съотношение", - "COLOUR_BLEND_TOOLTIP": "Смесва два цвят в дадено съотношение (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://bg.wikipedia.org/wiki/Цикъл_(програмиране)#For_.D1.86.D0.B8.D0.BA.D1.8A.D0.BB.D1.8A.D1.82", - "CONTROLS_REPEAT_TITLE": "Повтори %1 пъти", - "CONTROLS_REPEAT_INPUT_DO": "изпълни", - "CONTROLS_REPEAT_TOOLTIP": "Изпълнява команди няколко пъти.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "повтаряй докато е вярно, че", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "повтаряй докато", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Докато стойността е истина, изпълнявай командите.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Докато стойността е лъжа, изпълнявай командите.", - "CONTROLS_FOR_TOOLTIP": "Нека променлива \"%1\" премине през стойностите от началното до крайното число през зададената стъпка и изпълни избраните блокове.", - "CONTROLS_FOR_TITLE": "преброй чрез %1 от %2 до %3 през %4", - "CONTROLS_FOREACH_TITLE": "за всеки елемент %1 в списъка %2", - "CONTROLS_FOREACH_TOOLTIP": "За всеки елемент в списък присвои елемента на променливата '%1' и след това изпълни командите.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "прекъсни цикъла", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "премини към следващата стъпка от цикъла", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Прекъсни цикъла, в койте се съдержа тази команда.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Премини към следващата стъпка от цикъла", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Предупреждение: Този блок може да се използва само в цикъл.", - "CONTROLS_IF_TOOLTIP_1": "Ако стойността е вярна, изпълни операциите.", - "CONTROLS_IF_TOOLTIP_2": "Ако стойността е вярна, изпълни първия блок. Иначе, изпълни втория блок.", - "CONTROLS_IF_TOOLTIP_3": "Ако първата стойност е вярна, изпълни първия блок. Иначе, ако втората стойност е вярна, изпълни втория блок.", - "CONTROLS_IF_TOOLTIP_4": "Ако първата стойност е вярна, изпълни първия блок. В противен случай, ако втората стойност е вярна, изпълни втория блок. Ако нито една от стойностите не е вярна, изпълни последния блок.", - "CONTROLS_IF_MSG_IF": "ако", - "CONTROLS_IF_MSG_ELSEIF": "иначе ако", - "CONTROLS_IF_MSG_ELSE": "иначе", - "CONTROLS_IF_IF_TOOLTIP": "Добави, премахни или пренареди частите, за да промениш този \"ако\" блок.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Добави условие към \"ако\" блока.", - "CONTROLS_IF_ELSE_TOOLTIP": "Добави окончателено, прихващащо всичко останали случаи условие към \"ако\" блока.", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Върни вярно, ако двата параметъра са еднакви.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Върни вярно, ако двата параметъра са различни.", - "LOGIC_COMPARE_TOOLTIP_LT": "Върни вярно, ако първия параметър е по-малък от втория.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Върни истина, ако първия параметър е по-малък или равен на втория.", - "LOGIC_COMPARE_TOOLTIP_GT": "Върни истина, ако първия параметър е по-голям от втория.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Върни истина, ако първия параметър е по-голям или равен на втория.", - "LOGIC_OPERATION_TOOLTIP_AND": "Върни вярно, ако и двата параметъра са верни.", - "LOGIC_OPERATION_AND": "и", - "LOGIC_OPERATION_TOOLTIP_OR": "Върни \"вярно\", ако поне един от входовете е верен.", - "LOGIC_OPERATION_OR": "или", - "LOGIC_NEGATE_TITLE": "не %1", - "LOGIC_NEGATE_TOOLTIP": "Върни вярно, ако параметърът е неверен. Върни невярно, ако параметърът е верен.", - "LOGIC_BOOLEAN_TRUE": "вярно", - "LOGIC_BOOLEAN_FALSE": "невярно", - "LOGIC_BOOLEAN_TOOLTIP": "Връща вярно или невярно.", - "LOGIC_NULL": "нула", - "LOGIC_NULL_TOOLTIP": "Връща нула.", - "LOGIC_TERNARY_CONDITION": "тест", - "LOGIC_TERNARY_IF_TRUE": "Ако е вярно", - "LOGIC_TERNARY_IF_FALSE": "Ако е невярно", - "LOGIC_TERNARY_TOOLTIP": "Провери исловието в \"тест\". Ако условието е истина, върни \"ако е истина\" стойността, иначе върни \"ако е лъжа\" стойността.", - "MATH_NUMBER_HELPURL": "https://bg.wikipedia.org/wiki/Число", - "MATH_NUMBER_TOOLTIP": "Число.", - "MATH_ARITHMETIC_HELPURL": "https://bg.wikipedia.org/wiki/Аритметика", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Върни сумата на двете числа.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Върни разликата на двете числа.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Върни произведението на двете числа.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Върни частното на двете числа.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Върни първото число, повдигнато на степен на второто число.", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "корен квадратен", - "MATH_SINGLE_TOOLTIP_ROOT": "Връща корен квадратен от число.", - "MATH_SINGLE_OP_ABSOLUTE": "абсолютна", - "MATH_SINGLE_TOOLTIP_ABS": "Връща абсолютната стойност на число.", - "MATH_SINGLE_TOOLTIP_NEG": "Върни числото с обърнат знак.", - "MATH_SINGLE_TOOLTIP_LN": "Върни натуралния логаритъм от число.", - "MATH_SINGLE_TOOLTIP_LOG10": "Върни десетичния логаритъм на число.", - "MATH_SINGLE_TOOLTIP_EXP": "Върни е (неперовото число) на степен зададеното число.", - "MATH_SINGLE_TOOLTIP_POW10": "Върни 10 на степен зададеното число.", - "MATH_TRIG_HELPURL": "https://bg.wikipedia.org/wiki/Тригонометрична_функция", - "MATH_TRIG_TOOLTIP_SIN": "Върни синус от ъгъл в градуси (не в радиани)", - "MATH_TRIG_TOOLTIP_COS": "Върни косинус от ъгъл в градуси (не в радиани)", - "MATH_TRIG_TOOLTIP_TAN": "Върни тангенс от ъгъл в градуси (не в радиани)", - "MATH_TRIG_TOOLTIP_ASIN": "Върни аркуссинус от число.", - "MATH_TRIG_TOOLTIP_ACOS": "Върни аркускосинус от число.", - "MATH_TRIG_TOOLTIP_ATAN": "Върни аркустангенс от число.", - "MATH_CONSTANT_HELPURL": "http://bg.wikipedia.org/wiki/Константа", - "MATH_CONSTANT_TOOLTIP": "Връща една от често срещаните константи: π (3.141...), e (2.718...), φ (1.618...), sqrt(2) (1.414...), sqrt(½) (0.707...) или ∞ (безкрайност).", - "MATH_IS_EVEN": "е четно", - "MATH_IS_ODD": "е нечетно", - "MATH_IS_PRIME": "е просто", - "MATH_IS_WHOLE": "е цяло", - "MATH_IS_POSITIVE": "е положително", - "MATH_IS_NEGATIVE": "е отрицателно", - "MATH_IS_DIVISIBLE_BY": "се дели на", - "MATH_IS_TOOLTIP": "Проверете дали дадено число е четно, нечетно, просто, цяло, положително, отрицателно или дали се дели на друго число. Връща истина или лъжа.", - "MATH_CHANGE_HELPURL": "https://bg.wikipedia.org/wiki/Събиране", - "MATH_CHANGE_TITLE": "промени %1 на %2", - "MATH_CHANGE_TOOLTIP": "Добави число към променлива '%1'.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Закръгли число нагоре или надолу.", - "MATH_ROUND_OPERATOR_ROUND": "закръгли", - "MATH_ROUND_OPERATOR_ROUNDUP": "закръгли нагоре", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "закръгли надолу", - "MATH_ONLIST_OPERATOR_SUM": "сумирай списъка", - "MATH_ONLIST_TOOLTIP_SUM": "Върни сумата на всички числа в списъка.", - "MATH_ONLIST_OPERATOR_MIN": "най-малката стойност в списъка", - "MATH_ONLIST_TOOLTIP_MIN": "Върни най-малкото число в списъка.", - "MATH_ONLIST_OPERATOR_MAX": "най-голямата стойност в списъка", - "MATH_ONLIST_TOOLTIP_MAX": "Върни най-голямото число в списъка.", - "MATH_ONLIST_OPERATOR_AVERAGE": "средната стойност на числата в списъка", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Върни средната стойност (аритметичното средно) на числата в списъка.", - "MATH_ONLIST_OPERATOR_MEDIAN": "медианата на списък", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Върни медианата в списъка.", - "MATH_ONLIST_OPERATOR_MODE": "мода на списъка", - "MATH_ONLIST_TOOLTIP_MODE": "Върни списък на най-често срещаните елементи в списъка.", - "MATH_ONLIST_OPERATOR_STD_DEV": "стандартно отклонение на списък", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Връща стандартното отклонение на списъка.", - "MATH_ONLIST_OPERATOR_RANDOM": "случаен елемент от списъка", - "MATH_ONLIST_TOOLTIP_RANDOM": "Върни случаен елемент от списъка.", - "MATH_MODULO_HELPURL": "http://bg.wikipedia.org/wiki/Остатък", - "MATH_MODULO_TITLE": "остатъка от делението на %1 на %2", - "MATH_MODULO_TOOLTIP": "Върни остатъка от деление на две числа.", - "MATH_CONSTRAIN_TITLE": "ограничи %1 между %2 и %3", - "MATH_CONSTRAIN_TOOLTIP": "Ограничи число да бъде в определените граници (включително).", - "MATH_RANDOM_INT_HELPURL": "https://bg.wikipedia.org/wiki/Генератор_на_случайни_числа", - "MATH_RANDOM_INT_TITLE": "случайно цяло число между %1 и %2", - "MATH_RANDOM_INT_TOOLTIP": "Върни случайно число в определените граници (включително).", - "MATH_RANDOM_FLOAT_HELPURL": "https://bg.wikipedia.org/wiki/Генератор_на_случайни_числа", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "случайно дробно число", - "MATH_RANDOM_FLOAT_TOOLTIP": "Върни случайно дробно число между 0.0 (включително) и 1.0 (без да го включва)", - "TEXT_TEXT_HELPURL": "https://bg.wikipedia.org/wiki/Низ", - "TEXT_TEXT_TOOLTIP": "Буква, дума или ред", - "TEXT_JOIN_TITLE_CREATEWITH": "създай текст с", - "TEXT_JOIN_TOOLTIP": "Създай текст като съчетаеш няколко елемента.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "свържи", - "TEXT_CREATE_JOIN_TOOLTIP": "Добави, премахни или пренареди частите, за да промениш този текстов блок.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Добави елемент към текста.", - "TEXT_APPEND_TO": "към", - "TEXT_APPEND_APPENDTEXT": "добави текста", - "TEXT_APPEND_TOOLTIP": "Добави текста към променливата \"%1\".", - "TEXT_LENGTH_TITLE": "дължината на %1", - "TEXT_LENGTH_TOOLTIP": "Връща броя на символите (включително и интервалите) в текста.", - "TEXT_ISEMPTY_TITLE": "%1 е празен", - "TEXT_ISEMPTY_TOOLTIP": "Връща истина, ако текста е празен.", - "TEXT_INDEXOF_TOOLTIP": "Връща индекса на първото/последното срещане на първия текст във втория текст. Връща %1, ако текстът не е намерен.", - "TEXT_INDEXOF_INPUT_INTEXT": "в текста", - "TEXT_INDEXOF_OPERATOR_FIRST": "намери първата поява на текста", - "TEXT_INDEXOF_OPERATOR_LAST": "намери последната поява на текста", - "TEXT_CHARAT_INPUT_INTEXT": "от текста", - "TEXT_CHARAT_FROM_START": "вземи поредна буква", - "TEXT_CHARAT_FROM_END": "вземи поредна буква от края", - "TEXT_CHARAT_FIRST": "вземи първата буква", - "TEXT_CHARAT_LAST": "вземи последната буква", - "TEXT_CHARAT_RANDOM": "вземи произволна буква", - "TEXT_CHARAT_TOOLTIP": "Връща буквата в определена позиция.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Връща определена част от текста.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "В текста", - "TEXT_GET_SUBSTRING_START_FROM_START": "вземи текста от буква №", - "TEXT_GET_SUBSTRING_START_FROM_END": "вземи текста от буква № (броено отзад-напред)", - "TEXT_GET_SUBSTRING_START_FIRST": "вземи текста от първата буква", - "TEXT_GET_SUBSTRING_END_FROM_START": "до буква №", - "TEXT_GET_SUBSTRING_END_FROM_END": "со буква № (броено отзад-напред)", - "TEXT_GET_SUBSTRING_END_LAST": "со последната буква.", - "TEXT_CHANGECASE_TOOLTIP": "Връща копие на текста със сменени малки и главни букви.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "с ГЛАВНИ БУКВИ", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "с малки букви", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "с Главна Буква На Всяка Дума", - "TEXT_TRIM_TOOLTIP": "Върни копие на текста с пемахнати интервали от диния или двата края.", - "TEXT_TRIM_OPERATOR_BOTH": "премахни интервалите от двете страни", - "TEXT_TRIM_OPERATOR_LEFT": "премахни интервалите отляво", - "TEXT_TRIM_OPERATOR_RIGHT": "премахни интервалите отдясно", - "TEXT_PRINT_TITLE": "отпечатай %1", - "TEXT_PRINT_TOOLTIP": "Отпечатай текста, числото или друга стойност.", - "TEXT_PROMPT_TYPE_TEXT": "питай за текст със съобщение", - "TEXT_PROMPT_TYPE_NUMBER": "питай за число със съобщение", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Питай потребителя за число.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Питай потребителя за текст.", - "LISTS_CREATE_EMPTY_TITLE": "създай празен списък", - "LISTS_CREATE_EMPTY_TOOLTIP": "Връща списък с дължина 0, не съдържащ данни", - "LISTS_CREATE_WITH_TOOLTIP": "Създай списък с произволен брой елементи.", - "LISTS_CREATE_WITH_INPUT_WITH": "създай списък с", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "списък", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Добави, премахни или пренареди частите, за да промениш този списъчен блок.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Добави елемент към текста.", - "LISTS_REPEAT_TOOLTIP": "Създава списък, състоящ се от определен брой копия на елемента.", - "LISTS_REPEAT_TITLE": "създай списък от %1 повторен %2 пъти", - "LISTS_LENGTH_TITLE": "дължината на %1", - "LISTS_LENGTH_TOOLTIP": "Връща дължината на списък.", - "LISTS_ISEMPTY_TITLE": "%1 е празен", - "LISTS_ISEMPTY_TOOLTIP": "Връща стойност вярно, ако списъкът е празен.", - "LISTS_INLIST": "в списъка", - "LISTS_INDEX_OF_FIRST": "намери първата поява на елемента", - "LISTS_INDEX_OF_LAST": "намери последната поява на елемента", - "LISTS_INDEX_OF_TOOLTIP": "Връща индекса на първото/последното появяване на елемента в списъка. Връща %1 ако елементът не е намерен.", - "LISTS_GET_INDEX_GET": "вземи", - "LISTS_GET_INDEX_GET_REMOVE": "вземи и премахни", - "LISTS_GET_INDEX_REMOVE": "премахни", - "LISTS_GET_INDEX_FROM_END": "№ от края", - "LISTS_GET_INDEX_FIRST": "първия", - "LISTS_GET_INDEX_LAST": "последния", - "LISTS_GET_INDEX_RANDOM": "произволен", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 е първият елемент.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 е последният елемент.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Връща елемента на определената позиция в списък.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Връща първия елемент в списък.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Връща последния елемент в списък.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Връща случаен елемент от списъка.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Премахва и връща елемента на определена позиция в списък.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Премахва и връща първия елемент в списък.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Премахва и връща последния елемент в списък.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Премахва и връща случаен елемент в списък.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Премахва елемент на определена позиция в списък.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Премахва първия елемент в списък.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Премахва последния елемент в списък.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Премахва случаен елемент от списък.", - "LISTS_SET_INDEX_SET": "промени", - "LISTS_SET_INDEX_INSERT": "вмъкни на позиция", - "LISTS_SET_INDEX_INPUT_TO": "следното", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Променя елемента на определена позиция в списък.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Променя първия елемент в списък.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Променя последния елемент в списък.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Променя случаен елемент от списък.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Вмъква елемент на определена позиция в списък.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Вмъква елемент в началото на списъка.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Добави елемент в края на списък.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Вмъква елемент на произволно място в списък.", - "LISTS_GET_SUBLIST_START_FROM_START": "вземи подсписък от №", - "LISTS_GET_SUBLIST_START_FROM_END": "вземи подсписък от № от края", - "LISTS_GET_SUBLIST_START_FIRST": "вземи подсписък от първия", - "LISTS_GET_SUBLIST_END_FROM_START": "до #", - "LISTS_GET_SUBLIST_END_FROM_END": "до № открая", - "LISTS_GET_SUBLIST_END_LAST": "до края", - "LISTS_GET_SUBLIST_TOOLTIP": "Копира част от списък.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TOOLTIP": "Подреди копие на списъка.", - "LISTS_SORT_ORDER_ASCENDING": "възходящо", - "LISTS_SORT_ORDER_DESCENDING": "низходящо", - "LISTS_SORT_TYPE_NUMERIC": "в числов ред", - "LISTS_SORT_TYPE_TEXT": "по азбучен ред", - "LISTS_SORT_TYPE_IGNORECASE": "по азбучен ред, без отчитане на малки и главни букви", - "LISTS_SPLIT_LIST_FROM_TEXT": "Направи списък от текст", - "LISTS_SPLIT_TEXT_FROM_LIST": "направи текст от списък", - "LISTS_SPLIT_WITH_DELIMITER": "с разделител", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Разделя текст в списък на текстове, по всеки разделител.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Събира списък от текстове в един текст, раделени с разделител.", - "VARIABLES_GET_TOOLTIP": "Връща стойността на тази променлива.", - "VARIABLES_GET_CREATE_SET": "Създай \"промени стойността на %1\"", - "VARIABLES_SET": "нека %1 бъде %2", - "VARIABLES_SET_TOOLTIP": "Задава тази променлива да бъде равен на входа.", - "VARIABLES_SET_CREATE_GET": "Създай \"вземи стойността на %1\"", - "PROCEDURES_DEFNORETURN_TITLE": "за да", - "PROCEDURES_DEFNORETURN_PROCEDURE": "направиш", - "PROCEDURES_BEFORE_PARAMS": "със:", - "PROCEDURES_CALL_BEFORE_PARAMS": "със:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Създава функция, която не връща резултат.", - "PROCEDURES_DEFNORETURN_COMMENT": "Опишете тази функция...", - "PROCEDURES_DEFRETURN_RETURN": "върни", - "PROCEDURES_DEFRETURN_TOOLTIP": "Създава функция, която връща резултат.", - "PROCEDURES_ALLOW_STATEMENTS": "позволи операциите", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Предупреждение: Тази функция има дублиращи се параметри.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://bg.wikipedia.org/wiki/Подпрограма", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Изпълни дефинирана от потребителя функция \"%1\".", - "PROCEDURES_CALLRETURN_HELPURL": "https://bg.wikipedia.org/wiki/Подпрограма", - "PROCEDURES_CALLRETURN_TOOLTIP": "Изпълни дефинирана от потребителя функция \"%1\" и използвай резултата.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "вход", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Добави, премахни или пренареди входните параметри за тази функция.", - "PROCEDURES_MUTATORARG_TITLE": "име на параметър", - "PROCEDURES_MUTATORARG_TOOLTIP": "Добавяне на параметър към функцията.", - "PROCEDURES_HIGHLIGHT_DEF": "Покажи дефиницията на функцията", - "PROCEDURES_CREATE_DO": "Създай '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Ако стойността е истина, върни втората стойност.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Предупреждение: Този блок може да се използва само във функция." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/bn.json b/backend/_pv_1_3_5/static/blockly/msg/json/bn.json deleted file mode 100755 index 1a4e1aaef..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/bn.json +++ /dev/null @@ -1,156 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Aftabuzzaman", - "Rakibul", - "Tauhid16", - "MasterMinhaz", - "এম আবু সাঈদ" - ] - }, - "VARIABLES_DEFAULT_NAME": "পদ", - "TODAY": "আজ", - "DUPLICATE_BLOCK": "প্রতিলিপি", - "ADD_COMMENT": "মন্তব্য যোগ করুন", - "REMOVE_COMMENT": "মন্তব্য সরাও", - "EXTERNAL_INPUTS": "বহি:স্থ ইনপুট", - "INLINE_INPUTS": "সারি ইনপুট", - "DELETE_BLOCK": "ব্লকটি মুছে ফেল", - "DELETE_X_BLOCKS": "%1 ব্লক অপসারণ কর", - "EXPAND_BLOCK": "ব্লকটি সম্প্রসারিত কর", - "EXPAND_ALL": "ব্লকগুলো সম্প্রসারিত কর", - "DISABLE_BLOCK": "ব্লকটি বিকল কর", - "ENABLE_BLOCK": "ব্লকটি সচল কর", - "HELP": "সাহায্য", - "UNDO": "পূর্বাবস্থা", - "REDO": "পুনরায় করুন", - "CHANGE_VALUE_TITLE": "মান পরিবর্তন করুন:", - "RENAME_VARIABLE": "চলকের নাম পরিবর্তন...", - "NEW_VARIABLE": "নতুন চলক...", - "NEW_VARIABLE_TITLE": "নতুন চলকের নাম:", - "COLOUR_PICKER_TOOLTIP": "প্যালেট থেকে একটি রং পছন্দ করুন", - "COLOUR_RANDOM_TITLE": "এলোমেলো রং", - "COLOUR_RANDOM_TOOLTIP": "এলোমেলোভাবে একটি রং পছন্দ করুন।", - "COLOUR_RGB_TITLE": "রং সহ", - "COLOUR_RGB_RED": "লাল", - "COLOUR_RGB_GREEN": "সবুজ", - "COLOUR_RGB_BLUE": "নীল", - "COLOUR_RGB_TOOLTIP": "একটি রং তৈরি করুন নির্দিষ্ট পরিমাণে লাল, সবুজ এবং নীল রং মিশ্রিত করে। প্রত্যেকটির মান অবশ্যই ০ থেকে ১০০ এর মধ্যে হতে হবে।", - "COLOUR_BLEND_TITLE": "মিশ্রণ", - "COLOUR_BLEND_COLOUR1": "রং ১", - "COLOUR_BLEND_COLOUR2": "রং ২", - "COLOUR_BLEND_RATIO": "অনুপাত", - "COLOUR_BLEND_TOOLTIP": "প্রদত্ত অনুপাত(০.০ - ১.০) অনুসারে দুটি রং একসাথে মিশ্রিত করুন।", - "CONTROLS_REPEAT_TITLE": "%1 বার পুনরাবৃত্তি করো", - "CONTROLS_REPEAT_INPUT_DO": "করুন", - "CONTROLS_FOR_TITLE": "গণনা কর %1 %4 দিয়ে %2 থেকে %3", - "CONTROLS_FOREACH_TITLE": "প্রত্যেকটি পদের জন্য %1 তালিকার মধ্যে %2", - "CONTROLS_FLOW_STATEMENTS_WARNING": "সর্তকীবার্তা: এই ব্লকটি শুধুমাত্র লুপের মধ্যে ব্যবহার করা যাবে।", - "CONTROLS_IF_MSG_IF": "যদি", - "CONTROLS_IF_MSG_ELSEIF": "নতুবা যদি", - "CONTROLS_IF_MSG_ELSE": "নতুবা", - "CONTROLS_IF_ELSEIF_TOOLTIP": "যদি নামক ব্লক এ একটি শর্ত যোগ করুন।", - "LOGIC_COMPARE_TOOLTIP_EQ": "পাঠাবে সত্য যদি উভয় ইনপুটই সমান হয়।", - "LOGIC_COMPARE_TOOLTIP_NEQ": "পাঠাবে সত্য যদি উভয় ইনপুটই সমান না হয়।", - "LOGIC_COMPARE_TOOLTIP_LT": "পাঠাবে সত্য যদি প্রথম ইনপুট দ্বিতীয় ইনপুট থেকে ছোট হয়।", - "LOGIC_COMPARE_TOOLTIP_LTE": "পাঠাবে সত্য যদি প্রথম ইনপুট দ্বিতীয় ইনপুট থেকে ছোট অথবা সমান হয়।", - "LOGIC_COMPARE_TOOLTIP_GT": "পাঠাবে সত্য যদি প্রথম ইনপুট দ্বিতীয় ইনপুট থেকে বড় হয়।", - "LOGIC_COMPARE_TOOLTIP_GTE": "পাঠাবে সত্য যদি প্রথম ইনপুট দ্বিতীয় ইনপুট থেকে বড় অথবা সমান হয়।", - "LOGIC_OPERATION_TOOLTIP_AND": "পাঠাবে সত্য যদি উভয় ইনপুটই সত্য হয়।", - "LOGIC_OPERATION_AND": "এবং", - "LOGIC_OPERATION_TOOLTIP_OR": "পাঠাবে সত্য যদি অন্ততপক্ষে যেকোন একটি ইনপুট সত্য হয়।", - "LOGIC_OPERATION_OR": "অথবা", - "LOGIC_NEGATE_TITLE": "%1 নয়", - "LOGIC_NEGATE_TOOLTIP": "পাঠাবে সত্য যদি ইনপুট মিথ্যা হয়। পাঠাবে মিথ্যা যদি ইনপুট সত্য হয়।", - "LOGIC_BOOLEAN_TRUE": "সত্য", - "LOGIC_BOOLEAN_FALSE": "মিথ্যা", - "LOGIC_BOOLEAN_TOOLTIP": "পাঠাবে হয় সত্য অথবা মিথ্যা।", - "LOGIC_NULL": "কিছু না", - "LOGIC_NULL_TOOLTIP": "কিছু ফেরত দিবে না।", - "LOGIC_TERNARY_CONDITION": "পরীক্ষা", - "LOGIC_TERNARY_IF_TRUE": "যদি সত্য হয়", - "LOGIC_TERNARY_IF_FALSE": "যদি মিথ্যা হয়", - "MATH_NUMBER_HELPURL": "https://bn.wikipedia.org/wiki/সংখ্যা", - "MATH_NUMBER_TOOLTIP": "একটি সংখ্যা।", - "MATH_ARITHMETIC_TOOLTIP_ADD": "পাঠাবে দুটি সংখ্যার যোগফল।", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "পাঠাবে দুটি সংখ্যার বিয়োগফল।", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "পাঠাবে দুটি সংখ্যার গুণফল।", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "পাঠাবে দুটি সংখ্যার ভাগফল।", - "MATH_SINGLE_OP_ROOT": "বর্গমূল", - "MATH_SINGLE_TOOLTIP_ROOT": "পাঠাবে একটি সংখ্যার বর্গমূল।", - "MATH_SINGLE_OP_ABSOLUTE": "পরম", - "MATH_SINGLE_TOOLTIP_ABS": "পাঠাবে সংখ্যার পরমমান।", - "MATH_IS_EVEN": "জোড় সংখ্যা", - "MATH_IS_ODD": "বিজোড় সংখ্যা", - "MATH_IS_PRIME": "মৌলিক সংখ্যা", - "MATH_IS_POSITIVE": "ইতিবাচক", - "MATH_IS_NEGATIVE": "নেতিবাচক", - "MATH_IS_DIVISIBLE_BY": "দ্বারা বিভাজ্য", - "MATH_CHANGE_TITLE": "%2 দ্বারা %1 পরিবর্তন", - "MATH_ONLIST_OPERATOR_SUM": "তালিকার যোগফল", - "MATH_ONLIST_TOOLTIP_SUM": "পাঠাবে তালিকার সব সংখ্যার যোগফল।", - "MATH_ONLIST_OPERATOR_MIN": "তালিকার মধ্যে সর্বনিম্ন", - "MATH_ONLIST_TOOLTIP_MIN": "তালিকার মধ্যে সর্বনিম্ন সংখ্যাটি পাঠাও", - "MATH_ONLIST_OPERATOR_MAX": "তালিকার মধ্যে সর্বোচ্চ", - "MATH_ONLIST_TOOLTIP_MAX": "তালিকার মধ্যে সর্বোচ্চ সংখ্যাটি পাঠাও", - "MATH_ONLIST_OPERATOR_AVERAGE": "তালিকার গড়", - "MATH_ONLIST_TOOLTIP_AVERAGE": "পাঠাবে তালিকার সব সংখ্যার গড়।", - "MATH_ONLIST_OPERATOR_MEDIAN": "তালিকার মধ্যমা", - "MATH_ONLIST_TOOLTIP_MEDIAN": "তালিকার মধ্যমা সংখ্যাটি পাঠাবে।", - "MATH_ONLIST_OPERATOR_RANDOM": "তালিকার এলোমেলো পদ", - "MATH_ONLIST_TOOLTIP_RANDOM": "তালিকা থেকে এলোমেলোভাবে একটি পদ পাঠাবে।", - "MATH_MODULO_TITLE": "%1 ÷ %2 এর ভাগশেষ", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "এলোমেলো ভগ্নাংশ", - "TEXT_TEXT_TOOLTIP": "একটি অক্ষর, শব্দ অথবা বাক্য।", - "TEXT_CREATE_JOIN_TITLE_JOIN": "যোগ", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "লেখাটিতে একটি পদ যোগ করুন।", - "TEXT_APPEND_TO": "এতে", - "TEXT_LENGTH_TITLE": "%1-এর দৈর্ঘ্য", - "TEXT_ISEMPTY_TITLE": "%1 খালি", - "TEXT_ISEMPTY_TOOLTIP": "পাঠাবে সত্য যদি সরবরাহকৃত লেখাটি খালি হয়।", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "বড়হাতের অক্ষরে", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "ছোটহাতের অক্ষরে", - "TEXT_TRIM_OPERATOR_BOTH": "উভয় পাশ থেকে খালি অংশ ছাটাই", - "TEXT_TRIM_OPERATOR_LEFT": "বামপাশ থেকে খালি অংশ ছাটাই", - "TEXT_TRIM_OPERATOR_RIGHT": "ডানপাশ থেকে খালি অংশ ছাটাই", - "TEXT_PRINT_TITLE": "%1 মুদ্রণ করুন", - "LISTS_CREATE_EMPTY_TITLE": "খালি তালিকা তৈরি করুন", - "LISTS_CREATE_EMPTY_TOOLTIP": "পাঠাবে একটি তালিকা, দের্ঘ্য হবে ০, কোন উপাত্ত থাকবে না", - "LISTS_CREATE_WITH_TOOLTIP": "যেকোন সংখ্যক পদ নিয়ে একটি তালিকা তৈরি করুন।", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "তালিকা", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "তালিকায় একটি পদ যোগ করুন।", - "LISTS_LENGTH_TITLE": "%1-এর দৈর্ঘ্য", - "LISTS_LENGTH_TOOLTIP": "একটি তালিকার দৈর্ঘ্য পাঠাবে।", - "LISTS_ISEMPTY_TITLE": "%1 খালি", - "LISTS_ISEMPTY_TOOLTIP": "পাঠাবে সত্য যদি তালিকাটি খালি হয়।", - "LISTS_INLIST": "তালিকার মধ্যে", - "LISTS_INDEX_OF_FIRST": "আইটেমের প্রথম সংঘটন খুঁজুন", - "LISTS_INDEX_OF_LAST": "আইটেমের শেষ সংঘটন খুঁজুন", - "LISTS_GET_INDEX_GET": "নিন", - "LISTS_GET_INDEX_GET_REMOVE": "নিন ও সরান", - "LISTS_GET_INDEX_REMOVE": "অপসারণ", - "LISTS_GET_INDEX_FROM_END": "# শেষ থেকে", - "LISTS_GET_INDEX_FIRST": "প্রথম", - "LISTS_GET_INDEX_LAST": "শেষ", - "LISTS_GET_INDEX_RANDOM": "এলোমেলো", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "তালিকার প্রথম পদটি পাঠাবে।", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "তালিকার শেষ পদটি পাঠাবে।", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "এলোমেলোভাবে তালিকার যেকোন একটি পদ পাঠাবে।", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "অপসারণ করুন এবং তালিকার প্রথম পদটি পাঠান।", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "অপসারণ করুন এবং তালিকার শেষ পদটি পাঠান।", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "অপসারণ করুন এবং তালিকার এলোমেলো একটি পদ পাঠান।", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "তালিকার প্রথম পদটি অপসারণ করা হয়েছে।", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "তালিকার শেষ পদটি অপসারণ করা হয়েছে।", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "তালিকা থেকে এলোমেলো একটি পদ অপসারণ করা হয়েছে।", - "LISTS_SPLIT_LIST_FROM_TEXT": "লিখা থেকে তালিকা তৈরি করুন", - "LISTS_SPLIT_TEXT_FROM_LIST": "তালিকা থেকে লিখা তৈরি করুন", - "VARIABLES_SET_CREATE_GET": "'%1 নিন' তৈরি করুন", - "PROCEDURES_DEFNORETURN_TITLE": "এতে", - "PROCEDURES_DEFNORETURN_TOOLTIP": "আউটপুট ছাড়া একটি ক্রিয়া তৈরি করুন।", - "PROCEDURES_DEFRETURN_RETURN": "পাঠাবে", - "PROCEDURES_DEFRETURN_TOOLTIP": "আউটপুট সহ একটি ক্রিয়া তৈরি করুন।", - "PROCEDURES_MUTATORARG_TITLE": "ইনপুটের নাম:", - "PROCEDURES_MUTATORARG_TOOLTIP": "ক্রিয়াতে একটি ইনপুট যোগ করুন।", - "PROCEDURES_HIGHLIGHT_DEF": "ক্রিয়ার সংজ্ঞা উজ্জল করুন", - "PROCEDURES_IFRETURN_TOOLTIP": "যদি মান সত্য হয় তাহলে দ্বিতীয় মান পাঠাবে।" -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/br.json b/backend/_pv_1_3_5/static/blockly/msg/json/br.json deleted file mode 100755 index 8b6277490..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/br.json +++ /dev/null @@ -1,315 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Fohanno", - "Y-M D", - "Gwenn-Ael" - ] - }, - "VARIABLES_DEFAULT_NAME": "elfenn", - "TODAY": "Hiziv", - "DUPLICATE_BLOCK": "Eiladuriñ", - "ADD_COMMENT": "Ouzhpennañ un evezhiadenn", - "REMOVE_COMMENT": "Lemel an evezhiadenn kuit", - "EXTERNAL_INPUTS": "Monedoù diavaez", - "INLINE_INPUTS": "Monedoù enlinenn", - "DELETE_BLOCK": "Dilemel ar bloc'h", - "DELETE_X_BLOCKS": "Dilemel %1 bloc'h", - "DELETE_ALL_BLOCKS": "Diverkañ an holl vloc'hoù %1 ?", - "CLEAN_UP": "Naetaat ar bloc'hoù", - "COLLAPSE_BLOCK": "Bihanaat ar bloc'h", - "COLLAPSE_ALL": "Bihanaat ar bloc'hoù", - "EXPAND_BLOCK": "Astenn ar bloc'h", - "EXPAND_ALL": "Astenn ar bloc'hoù", - "DISABLE_BLOCK": "Diweredekaat ar bloc'h", - "ENABLE_BLOCK": "Gweredekaat ar bloc'h", - "HELP": "Skoazell", - "UNDO": "Dizober", - "REDO": "Adober", - "CHANGE_VALUE_TITLE": "Kemmañ an dalvoudenn :", - "RENAME_VARIABLE": "Adenvel an argemmenn...", - "RENAME_VARIABLE_TITLE": "Adenvel an holl argemmennoù '%1' e :", - "NEW_VARIABLE": "Krouiñ un argemm nevez...", - "NEW_VARIABLE_TITLE": "Anv an argemmenn nevez :", - "VARIABLE_ALREADY_EXISTS": "Un argemm anvet '%1' zo anezhañ dija.", - "DELETE_VARIABLE_CONFIRMATION": "Lemel %1 implij eus an argemm '%2' ?", - "DELETE_VARIABLE": "Lemel an argemm '%1'", - "COLOUR_PICKER_HELPURL": "http://br.wikipedia.org/wiki/Liv", - "COLOUR_PICKER_TOOLTIP": "Dibab ul liv diwar al livaoueg.", - "COLOUR_RANDOM_TITLE": "liv dargouezhek", - "COLOUR_RANDOM_TOOLTIP": "Tennañ ul liv d'ar sord", - "COLOUR_RGB_TITLE": "liv gant", - "COLOUR_RGB_RED": "ruz", - "COLOUR_RGB_GREEN": "gwer", - "COLOUR_RGB_BLUE": "glas", - "COLOUR_RGB_TOOLTIP": "Krouiñ ul liv gant ar c'hementad spisaet a ruz, a wer hag a c'hlas. Etre 0 ha 100 e tle bezañ an holl dalvoudoù.", - "COLOUR_BLEND_TITLE": "meskañ", - "COLOUR_BLEND_COLOUR1": "liv 1", - "COLOUR_BLEND_COLOUR2": "liv 2", - "COLOUR_BLEND_RATIO": "feur", - "COLOUR_BLEND_TOOLTIP": "a gemmesk daou liv gant ur feur roet(0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "adober %1 gwech", - "CONTROLS_REPEAT_INPUT_DO": "ober", - "CONTROLS_REPEAT_TOOLTIP": "Seveniñ urzhioù zo meur a wech", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "adober keit ha ma", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "adober betek", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Keit ha ma vez gwir un dalvoudenn, seveniñ urzhioù zo neuze.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Keit ha ma vez faos un dalvoudenn,seveniñ urzhioù zo neuze.", - "CONTROLS_FOR_TOOLTIP": "Ober e doare ma kemero an argemmenn \"%1\" an talvoudennoù adalek niverenn an deroù betek niverenn an dibenn, en ur inkremantiñ an esaouenn, ha seveniñ an urzhioù spisaet.", - "CONTROLS_FOR_TITLE": "kontañ gant %1 eus %2 da %3 dre %4", - "CONTROLS_FOREACH_TITLE": "evit pep elfenn %1 er roll %2", - "CONTROLS_FOREACH_TOOLTIP": "Evit pep elfenn en ur roll, reiñ talvoud an elfenn d'an argemmenn '%1', ha seveniñ urzhioù zo da c'houde.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "Mont e-maez an adlañsañ", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "Kenderc'hel gant iteradur nevez ar rodell", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Mont e-maez ar boukl engronnus.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Lammat ar rest eus ar rodell, ha kenderc'hel gant an iteradur war-lerc'h.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Diwallit : ne c'hall ar bloc'h-mañ bezañ implijet nemet e-barzh ur boukl.", - "CONTROLS_IF_TOOLTIP_1": "Ma vez gwir un dalvoudenn, seveniñ urzhioù zo neuze.", - "CONTROLS_IF_TOOLTIP_2": "Ma vez gwir un dalvoudenn, seveniñ ar c'henañ bloc'had urzhioù neuze. Anez seveniñ an eil bloc'had urzhioù.", - "CONTROLS_IF_TOOLTIP_3": "Ma vez gwir an dalvoudenn gentañ, seveniñ ar c'hentañ bloc'had urzhioù neuze. Anez ma vez gwir an eil talvoudenn, seveniñ an eil bloc'had urzhioù.", - "CONTROLS_IF_TOOLTIP_4": "Ma vez gwir an dalvoudenn gentañ, seveniñ ar c'hentañ bloc'had. Anez, ma vez gwir an eil talvoudenn, seveniñ an eil bloc'had urzhioù. Ma ne vez gwir talvoudenn ebet, seveniñ ar bloc'had diwezhañ a urzhioù.", - "CONTROLS_IF_MSG_IF": "ma", - "CONTROLS_IF_MSG_ELSEIF": "mod all ma", - "CONTROLS_IF_MSG_ELSE": "a-hend-all", - "CONTROLS_IF_IF_TOOLTIP": "Ouzhpennañ, lemel pe adurzhiañ ar rannoù evit kefluniañ ar bloc'h ma.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Ouzhpennañ un amplegad d'ar bloc'h ma.", - "CONTROLS_IF_ELSE_TOOLTIP": "Ouzhpennañ un amplegad dibenn lak-pep-tra d'ar bloc'h ma.", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Distreiñ gwir m'eo par an daou voned.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Distreiñ gwir ma n'eo ket par an daou voned.", - "LOGIC_COMPARE_TOOLTIP_LT": "Distreiñ gwir m'eo bihanoc'h ar moned kentañ eget an eil.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Distreiñ gwir m'eo bihanoc'h ar moned kentañ eget an eil pe m'eo par dezhañ.", - "LOGIC_COMPARE_TOOLTIP_GT": "Distreiñ gwir m'eo brasoc'h ar moned kentañ eget an eil.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Distreiñ gwir m'eo brasoc'h ar moned kentañ eget an eil pe par dezhañ.", - "LOGIC_OPERATION_TOOLTIP_AND": "Distreiñ gwir m'eo gwir an da daou voned.", - "LOGIC_OPERATION_AND": "ha(g)", - "LOGIC_OPERATION_TOOLTIP_OR": "Distreiñ gwir m'eo gwir unan eus an daou voned da nebeutañ.", - "LOGIC_OPERATION_OR": "pe", - "LOGIC_NEGATE_TITLE": "nann %1", - "LOGIC_NEGATE_TOOLTIP": "Distreiñ gwir m'eo faos ar moned. Distreiñ faos m'eo gwir ar moned.", - "LOGIC_BOOLEAN_TRUE": "gwir", - "LOGIC_BOOLEAN_FALSE": "gaou", - "LOGIC_BOOLEAN_TOOLTIP": "Distreiñ pe gwir pe faos", - "LOGIC_NULL": "Null", - "LOGIC_NULL_TOOLTIP": "Distreiñ null.", - "LOGIC_TERNARY_CONDITION": "amprouad", - "LOGIC_TERNARY_IF_TRUE": "m'eo gwir", - "LOGIC_TERNARY_IF_FALSE": "m'eo gaou", - "LOGIC_TERNARY_TOOLTIP": "Gwiriañ an amplegad e 'prouad'. M'eo gwir an amplegad, distreiñ an dalvoudenn 'm'eo gwir'; anez distreiñ ar moned 'm'eo faos'.", - "MATH_NUMBER_HELPURL": "https://br.wikipedia.org/wiki/Niver", - "MATH_NUMBER_TOOLTIP": "Un niver.", - "MATH_ARITHMETIC_HELPURL": "https://br.wikipedia.org/wiki/Aritmetik", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Distreiñ sammad daou niver.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Distreiñ diforc'h daou niver", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Distreiñ liesad daou niver.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Distreiñ rannad daou niver.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Distreiñ an niver kentañ lakaet dindan gallouter an eil niver.", - "MATH_SINGLE_HELPURL": "https://br.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "gwrizienn garrez", - "MATH_SINGLE_TOOLTIP_ROOT": "Distreiñ gwrizienn garrez un niver", - "MATH_SINGLE_OP_ABSOLUTE": "dizave", - "MATH_SINGLE_TOOLTIP_ABS": "Distreiñ talvoud dizave un niver.", - "MATH_SINGLE_TOOLTIP_NEG": "Distreiñ enebad un niver", - "MATH_SINGLE_TOOLTIP_LN": "Distreiñ logaritm naturel un niver", - "MATH_SINGLE_TOOLTIP_LOG10": "Distreiñ logaritm diazez 10 un niver", - "MATH_SINGLE_TOOLTIP_EXP": "Distreiñ galloudad un niver.", - "MATH_SINGLE_TOOLTIP_POW10": "Distreiñ 10 da c'halloudad un niver.", - "MATH_TRIG_HELPURL": "https://br.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "Distreiñ sinuz ur c'horn (ket e radianoù)", - "MATH_TRIG_TOOLTIP_COS": "Distreiñ kosinuz ur c'horn (ket e radianoù)", - "MATH_TRIG_TOOLTIP_TAN": "Distreiñ tangent ur c'horn (ket e radianoù).", - "MATH_TRIG_TOOLTIP_ASIN": "Distreiñ ark sinuz un niver", - "MATH_TRIG_TOOLTIP_ACOS": "Distreiñ ark kosinuz un niver", - "MATH_TRIG_TOOLTIP_ATAN": "Distreiñ ark tangent un niver", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "Distreiñ unan eus digemmennoù red : π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (anvevenn).", - "MATH_IS_EVEN": "zo par", - "MATH_IS_ODD": "zo ampar", - "MATH_IS_PRIME": "zo kentañ", - "MATH_IS_WHOLE": "zo anterin", - "MATH_IS_POSITIVE": "a zo pozitivel", - "MATH_IS_NEGATIVE": "a zo negativel", - "MATH_IS_DIVISIBLE_BY": "a zo rannadus dre", - "MATH_IS_TOOLTIP": "Gwiriañ m'eo par, anpar, kentañ, muiel, leiel un niverenn pe ma c'haller rannañ anezhi dre un niver roet zo. Distreiñ gwir pe faos.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "kemmañ %1 gant %2", - "MATH_CHANGE_TOOLTIP": "Ouzhpennañ un niver d'an argemm '%1'.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Rontaat un niver dindan pe a-us", - "MATH_ROUND_OPERATOR_ROUND": "Rontaat", - "MATH_ROUND_OPERATOR_ROUNDUP": "Rontaat a-us", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "Rontaat dindan", - "MATH_ONLIST_OPERATOR_SUM": "Sammad al listenn", - "MATH_ONLIST_TOOLTIP_SUM": "Distreiñ sammad an holl niveroù zo el listenn.", - "MATH_ONLIST_OPERATOR_MIN": "Izegenn al listenn", - "MATH_ONLIST_TOOLTIP_MIN": "Distreiñ an niver bihanañ el listenn", - "MATH_ONLIST_OPERATOR_MAX": "Uc'hegenn al listenn", - "MATH_ONLIST_TOOLTIP_MAX": "Distreiñ an niver brasañ el listenn.", - "MATH_ONLIST_OPERATOR_AVERAGE": "Keitat al listenn", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Distreiñ keitad (niveroniel) an talvoudennoù niverel el listenn.", - "MATH_ONLIST_OPERATOR_MEDIAN": "Kreizad al listenn", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Distreiñ an niver kreiz el listenn", - "MATH_ONLIST_OPERATOR_MODE": "modoù stankañ el listenn", - "MATH_ONLIST_TOOLTIP_MODE": "Distreiñ ul listennad elfennoù stankoc'h el listenn.", - "MATH_ONLIST_OPERATOR_STD_DEV": "forc'had standart eus al listenn", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Distreiñ forc'had standart al listenn.", - "MATH_ONLIST_OPERATOR_RANDOM": "Elfennn eus al listenn tennet d'ar sord", - "MATH_ONLIST_TOOLTIP_RANDOM": "Distreiñ un elfenn zargouezhek el listenn", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "rest eus %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Distreiñ dilerc'h rannadur an div niver", - "MATH_CONSTRAIN_TITLE": "destrizhañ %1 etre %2 ha %3", - "MATH_CONSTRAIN_TOOLTIP": "Destrizhañ un niver da vezañ etre ar bevennoù spisaet (enlakaet)", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "anterin dargouezhek etre %1 ha %2", - "MATH_RANDOM_INT_TOOLTIP": "Distreiñ un anterin dargouezhek etre an div vevenn spisaet, endalc'het.", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "Rann dargouezhek", - "MATH_RANDOM_FLOAT_TOOLTIP": "Distreiñ ur rann dargouezhek etre 0.0 (enkaelat) hag 1.0 (ezkaelat).", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "Ul lizherenn, ur ger pe ul linennad testenn.", - "TEXT_JOIN_TITLE_CREATEWITH": "krouiñ un destenn gant", - "TEXT_JOIN_TOOLTIP": "Krouit un tamm testenn en ur gevelstrollañ un niver bennak a elfennoù", - "TEXT_CREATE_JOIN_TITLE_JOIN": "stagañ", - "TEXT_CREATE_JOIN_TOOLTIP": "Ouzhpennañ, lemel pe adurzhiañ ar rannoù evit kefluniañ ar bloc'h testenn-mañ.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Ouzhpennañ un elfenn d'an destenn.", - "TEXT_APPEND_TO": "da", - "TEXT_APPEND_APPENDTEXT": "ouzhpennañ an destenn", - "TEXT_APPEND_TOOLTIP": "Ouzhpennañ testenn d'an argemmenn'%1'.", - "TEXT_LENGTH_TITLE": "hirder %1", - "TEXT_LENGTH_TOOLTIP": "Distreiñ an niver a lizherennoù(en ur gontañ an esaouennoù e-barzh) en destenn roet.", - "TEXT_ISEMPTY_TITLE": "%1 zo goullo", - "TEXT_ISEMPTY_TOOLTIP": "Adkas gwir m'eo goullo an destenn roet.", - "TEXT_INDEXOF_TOOLTIP": "Distreiñ meneger ar c'hentañ/an eil reveziadenn eus ar chadenn gentañ en eil chadenn. Distreiñ %1 ma n'eo ket kavet ar chadenn.", - "TEXT_INDEXOF_INPUT_INTEXT": "en destenn", - "TEXT_INDEXOF_OPERATOR_FIRST": "kavout reveziadenn gentañ an destenn", - "TEXT_INDEXOF_OPERATOR_LAST": "kavout reveziadenn diwezhañ an destenn", - "TEXT_CHARAT_INPUT_INTEXT": "en destenn", - "TEXT_CHARAT_FROM_START": "Kaout al lizherenn #", - "TEXT_CHARAT_FROM_END": "Kaout al lizherenn # adalek an dibenn.", - "TEXT_CHARAT_FIRST": "tapout al lizherenn gentañ", - "TEXT_CHARAT_LAST": "tapout al lizherenn ziwezhañ", - "TEXT_CHARAT_RANDOM": "Kaout ul lizherenn dre zegouezh", - "TEXT_CHARAT_TOOLTIP": "Distreiñ al lizherenn d'al lec'h spisaet.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Distreiñ un tamm spisaet eus an destenn.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "en destenn", - "TEXT_GET_SUBSTRING_START_FROM_START": "Kaout an ischadenn adalek al lizherenn #", - "TEXT_GET_SUBSTRING_START_FROM_END": "Kaout an ischadenn adalek al lizherenn # betek an dibenn", - "TEXT_GET_SUBSTRING_START_FIRST": "Kaout an ischadenn adalek al lizherenn gentañ", - "TEXT_GET_SUBSTRING_END_FROM_START": "betek al lizherenn #", - "TEXT_GET_SUBSTRING_END_FROM_END": "Betek al lizherenn # adalek an dibenn.", - "TEXT_GET_SUBSTRING_END_LAST": "d'al lizherenn diwezhañ", - "TEXT_CHANGECASE_TOOLTIP": "Distreiñ un eilenn eus an eilenn en un direnneg all", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "e PENNLIZHERENNOÙ", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "e lizherennoù bihan", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "Gant Ur Bennlizherenn E Deroù Pep Ger", - "TEXT_TRIM_TOOLTIP": "Distreiñ un eilenn eus an destenn gant an esaouennoù lamet eus un tu pe eus an daou du", - "TEXT_TRIM_OPERATOR_BOTH": "Lemel an esaouennoù en daou du", - "TEXT_TRIM_OPERATOR_LEFT": "Lemel an esaouennoù eus an tu kleiz", - "TEXT_TRIM_OPERATOR_RIGHT": "Lemel an esaouennoù eus an tu dehou", - "TEXT_PRINT_TITLE": "moullañ %1", - "TEXT_PRINT_TOOLTIP": "Moullañ an destenn, an niverenn pe un dalvoudenn spisaet all", - "TEXT_PROMPT_TYPE_TEXT": "pedadenn evit un destenn gant ur c'hemennad", - "TEXT_PROMPT_TYPE_NUMBER": "pedadenn evit un niver gant ur c'hemennad", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Goulenn un niver gant an implijer.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Goulenn un destenn gant an implijer.", - "LISTS_CREATE_EMPTY_TITLE": "krouiñ ur roll goullo", - "LISTS_CREATE_EMPTY_TOOLTIP": "Distreiñ ul listenn, 0 a hirder, n'eus enrolladenn ebet enni", - "LISTS_CREATE_WITH_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_CREATE_WITH_TOOLTIP": "Krouiñ ur roll gant un niver bennak a elfennoù.", - "LISTS_CREATE_WITH_INPUT_WITH": "krouiñ ur roll gant", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "roll", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Ouzhpennañ, lemel pe adurzhiañ ar rannoù evit kefluniañ ar bloc'h listenn-mañ.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Ouzhpennañ un elfenn d'ar roll", - "LISTS_REPEAT_TOOLTIP": "Krouiñ ul listenn a c'hoarvez eus an dalvoudenn roet arreet an niver a wech meneget", - "LISTS_REPEAT_TITLE": "Krouiñ ul listenn gant an elfenn %1 arreet div wech", - "LISTS_LENGTH_TITLE": "hirder %1", - "LISTS_LENGTH_TOOLTIP": "Distreiñ hirder ul listenn.", - "LISTS_ISEMPTY_TITLE": "%1 zo goullo", - "LISTS_ISEMPTY_TOOLTIP": "Distreiñ gwir m'eo goullo al listenn.", - "LISTS_INLIST": "el listenn", - "LISTS_INDEX_OF_FIRST": "kavout reveziadenn gentañ un elfenn", - "LISTS_INDEX_OF_LAST": "kavout reveziadenn diwezhañ un elfenn", - "LISTS_INDEX_OF_TOOLTIP": "Distreiñ meneger ar c'hentañ/an eil reveziadenn eus an elfenn en ul listenn. Distreiñ %1 ma n'eo ket kavet an destenn.", - "LISTS_GET_INDEX_GET": "tapout", - "LISTS_GET_INDEX_GET_REMOVE": "tapout ha lemel", - "LISTS_GET_INDEX_REMOVE": "lemel", - "LISTS_GET_INDEX_FROM_END": "# adalek ar fin", - "LISTS_GET_INDEX_FIRST": "kentañ", - "LISTS_GET_INDEX_LAST": "diwezhañ", - "LISTS_GET_INDEX_RANDOM": "dre zegouezh", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 eo an elfenn gentañ.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 eo an elfenn gentañ.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Distreiñ an elfenn el lec'h meneget en ul listenn.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Distreiñ an elfenn gentañ en ul listenn.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Distreiñ un elfenn diwezhañ en ul listenn.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Distreiñ un elfenn dre zegouezh en ul listenn.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Lemel ha distreiñ a ra an elfenn el lec'h meneget en ul listenn.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Lemel ha distreiñ a ra an elfenn gentañ en ul listenn.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Lemel ha distreiñ a ra an elfenn diwezhañ en ul listenn.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Lemel ha distreiñ a ra an elfenn dre zegouezh en ul listenn.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Lemel a ra an elfenn el lec'h meneget en ul listenn.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Lemel a ra an elfenn gentañ en ul listenn.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Distreiñ a ra an elfenn diwezhañ en ul listenn.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Lemel a ra un elfenn dre zegouezh en ul listenn.", - "LISTS_SET_INDEX_SET": "termenañ", - "LISTS_SET_INDEX_INSERT": "ensoc'hañ evel", - "LISTS_SET_INDEX_INPUT_TO": "evel", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Termenañ a ra an elfenn el lec'h meneget en ul listenn.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Termenañ a ra an elfenn gentañ en ul listenn.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Termenañ a ra an elfenn diwezhañ en ul listenn.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Termenañ a ra un elfenn dre zegouezh en ul listenn.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Ensoc'hañ a ra an elfenn el lec'h meneget en ul listenn.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Ensoc'hañ a ra an elfenn e deroù ul listenn.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Ouzhpennañ a ra an elfenn e fin al listenn.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Ensoc'hañ a ra an elfenn dre zegouezh en ul listenn.", - "LISTS_GET_SUBLIST_START_FROM_START": "Kaout an islistenn adalek #", - "LISTS_GET_SUBLIST_START_FROM_END": "Kaout an islistenn adalek # adalek an dibenn", - "LISTS_GET_SUBLIST_START_FIRST": "Kaout an islistenn adalek an deroù", - "LISTS_GET_SUBLIST_END_FROM_START": "da #", - "LISTS_GET_SUBLIST_END_FROM_END": "betek # adalek an dibenn", - "LISTS_GET_SUBLIST_END_LAST": "betek ar fin", - "LISTS_GET_SUBLIST_TOOLTIP": "Krouiñ un eilad eus lodenn spisaet ul listenn.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_SORT_TITLE": "Rummañ%1,%2,%3", - "LISTS_SORT_TOOLTIP": "Rummañ un eilenn eus ar roll", - "LISTS_SORT_ORDER_ASCENDING": "war gresk", - "LISTS_SORT_ORDER_DESCENDING": "war zigresk", - "LISTS_SORT_TYPE_NUMERIC": "niverel", - "LISTS_SORT_TYPE_TEXT": "Dre urzh al lizherenneg", - "LISTS_SORT_TYPE_IGNORECASE": "Dre urzh al lizherenneg, hep derc'hel kont eus an direnneg", - "LISTS_SPLIT_HELPURL": "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists", - "LISTS_SPLIT_LIST_FROM_TEXT": "Krouiñ ul listenn diwar an destenn", - "LISTS_SPLIT_TEXT_FROM_LIST": "Krouiñ un destenn diwar al listenn", - "LISTS_SPLIT_WITH_DELIMITER": "gant an dispartier", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Troc'hañ un destenn en ul listennad testennoù, o troc'hañ e pep dispartier.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Bodañ ul listennad testennoù en ul listenn hepken, o tispartiañ anezho gant un dispartier.", - "VARIABLES_GET_TOOLTIP": "Distreiñ talvoud an argemm-mañ.", - "VARIABLES_GET_CREATE_SET": "Krouiñ 'termenañ %1'", - "VARIABLES_SET": "termenañ %1 da %2", - "VARIABLES_SET_TOOLTIP": "Termenañ a ra argemm-mañ evit ma vo par da dalvoudenn ar moned.", - "VARIABLES_SET_CREATE_GET": "Krouiñ 'kaout %1'", - "PROCEDURES_DEFNORETURN_TITLE": "da", - "PROCEDURES_DEFNORETURN_PROCEDURE": "ober un dra bennak", - "PROCEDURES_BEFORE_PARAMS": "gant :", - "PROCEDURES_CALL_BEFORE_PARAMS": "gant :", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Krouiñ un arc'hwel hep mont er-maez.", - "PROCEDURES_DEFNORETURN_COMMENT": "Deskrivañ an arc'hwel-mañ...", - "PROCEDURES_DEFRETURN_RETURN": "distreiñ", - "PROCEDURES_DEFRETURN_TOOLTIP": "Kouiñ un arc'hwel gant ur mont er-maez", - "PROCEDURES_ALLOW_STATEMENTS": "aotren an disklêriadurioù", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Diwallit : an arc'hwel-mañ en deus arventennoù eiladet.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Seveniñ an arc'hwel '%1' termenet gant an implijer.", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Seveniñ an arc'hwel '%1' termenet gant an implijer hag implijout e zisoc'h.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "Monedoù", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Ouzhpennañ, lemel, pe adkempenn monedoù an arc'hwel-mañ.", - "PROCEDURES_MUTATORARG_TITLE": "Anv ar moned", - "PROCEDURES_MUTATORARG_TOOLTIP": "Ouzhpennañ ur moned d'an arc'hwel.", - "PROCEDURES_HIGHLIGHT_DEF": "Dreislinennañ termenadur an arc'hwel", - "PROCEDURES_CREATE_DO": "Krouiñ '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Ma'z eo gwir un dalvoudenn, distreiñ un eil talvoudenn neuze.", - "PROCEDURES_IFRETURN_WARNING": "Diwallit : Gallout a rafe ar bloc'h bezañ implijet e termenadur un arc'hwel hepken." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/ca.json b/backend/_pv_1_3_5/static/blockly/msg/json/ca.json deleted file mode 100755 index fc13a69b2..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/ca.json +++ /dev/null @@ -1,293 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Alvaro Vidal-Abarca", - "Espertus", - "Hiperpobla", - "Jaumeortola" - ] - }, - "VARIABLES_DEFAULT_NAME": "element", - "DUPLICATE_BLOCK": "Duplica", - "ADD_COMMENT": "Afegeix un comentari", - "REMOVE_COMMENT": "Elimina el comentari", - "EXTERNAL_INPUTS": "Entrades externes", - "INLINE_INPUTS": "Entrades en línia", - "DELETE_BLOCK": "Esborra bloc", - "DELETE_X_BLOCKS": "Esborra %1 blocs", - "DELETE_ALL_BLOCKS": "Esborrar els %1 blocs?", - "COLLAPSE_BLOCK": "Contraure bloc", - "COLLAPSE_ALL": "Contraure blocs", - "EXPAND_BLOCK": "Expandir bloc", - "EXPAND_ALL": "Expandir blocs", - "DISABLE_BLOCK": "Desactiva bloc", - "ENABLE_BLOCK": "Activa bloc", - "HELP": "Ajuda", - "CHANGE_VALUE_TITLE": "Canvia valor:", - "RENAME_VARIABLE": "Reanomena variable...", - "RENAME_VARIABLE_TITLE": "Reanomena totes les variables '%1' a:", - "NEW_VARIABLE": "Nova variable...", - "NEW_VARIABLE_TITLE": "Nou nom de variable:", - "COLOUR_PICKER_HELPURL": "https://ca.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "Escolliu un color de la paleta.", - "COLOUR_RANDOM_TITLE": "color aleatori", - "COLOUR_RANDOM_TOOLTIP": "Escolliu un color a l'atzar.", - "COLOUR_RGB_TITLE": "color amb", - "COLOUR_RGB_RED": "vermell", - "COLOUR_RGB_GREEN": "verd", - "COLOUR_RGB_BLUE": "blau", - "COLOUR_RGB_TOOLTIP": "Crear un color amb les quantitats especificades de vermell, verd i blau. Tots els valors han de ser entre 0 i 100.", - "COLOUR_BLEND_TITLE": "barreja", - "COLOUR_BLEND_COLOUR1": "color 1", - "COLOUR_BLEND_COLOUR2": "color 2", - "COLOUR_BLEND_RATIO": "proporció", - "COLOUR_BLEND_TOOLTIP": "Barreja dos colors amb una proporció donada (0,0 - 1,0).", - "CONTROLS_REPEAT_HELPURL": "https://ca.wikipedia.org/wiki/Bucle_For", - "CONTROLS_REPEAT_TITLE": "repetir %1 vegades", - "CONTROLS_REPEAT_INPUT_DO": "fer", - "CONTROLS_REPEAT_TOOLTIP": "Executar unes sentències diverses vegades.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "repetir mentre", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "repetir fins que", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Mentre un valor sigui cert, llavors executar unes sentències.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Mentre un valor sigui fals, llavors executar unes sentències.", - "CONTROLS_FOR_TOOLTIP": "Fer que la variable \"%1\" prengui els valors des del nombre inicial fins al nombre final, incrementant a cada pas l'interval indicat, i executar els blocs especificats.", - "CONTROLS_FOR_TITLE": "comptar amb %1 des de %2 fins a %3 en increments de %4", - "CONTROLS_FOREACH_TITLE": "per a cada element %1 en la llista %2", - "CONTROLS_FOREACH_TOOLTIP": "Per a cada element en la llista, desar l'element dins la variable '%1', i llavors executar unes sentències.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "sortir del bucle", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "continuar amb la següent iteració del bucle", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Sortir del bucle interior.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Ometre la resta d'aquest bucle, i continuar amb la següent iteració.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Advertència: Aquest bloc només es pot utilitzar dins d'un bucle.", - "CONTROLS_IF_TOOLTIP_1": "Si un valor és cert, llavors executar unes sentències.", - "CONTROLS_IF_TOOLTIP_2": "Si un valor és cert, llavors executar el primer bloc de sentències. En cas contrari, executar el segon bloc de sentències.", - "CONTROLS_IF_TOOLTIP_3": "Si el primer valor és cert, llavors executar el primer bloc de sentències. En cas contrari, si el segon valor és cert, executar el segon bloc de sentències.", - "CONTROLS_IF_TOOLTIP_4": "Si el primer valor és cert, llavors executar el primer bloc de sentències. En cas contrari, si el segon valor és cert, executar el segon bloc de sentències. Si cap dels valors és cert, executar l'últim bloc de sentències.", - "CONTROLS_IF_MSG_IF": "si", - "CONTROLS_IF_MSG_ELSEIF": "si no, si", - "CONTROLS_IF_MSG_ELSE": "si no", - "CONTROLS_IF_IF_TOOLTIP": "Afegeix, esborra o reordena seccions per reconfigurar aquest bloc 'si'.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Afegeix una condició al bloc 'si'.", - "CONTROLS_IF_ELSE_TOOLTIP": "Afegeix una condició final, que recull qualsevol altra possibilitat, al bloc 'si'.", - "LOGIC_COMPARE_HELPURL": "https://ca.wikipedia.org/wiki/Inequaci%C3%B3", - "LOGIC_COMPARE_TOOLTIP_EQ": "Retorna cert si totes dues entrades són iguals.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Retorna cert si totes dues entrades són diferents.", - "LOGIC_COMPARE_TOOLTIP_LT": "Retorna cert si la primera entrada és més petita que la segona entrada.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Retorna cert si la primera entra és més petita o igual a la segona entrada.", - "LOGIC_COMPARE_TOOLTIP_GT": "Retorna cert si la primera entrada és més gran que la segona entrada.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Retorna cert si la primera entrada és més gran o igual a la segona entrada.", - "LOGIC_OPERATION_TOOLTIP_AND": "Retorna cer si totes dues entrades són certes.", - "LOGIC_OPERATION_AND": "i", - "LOGIC_OPERATION_TOOLTIP_OR": "Retorna cert si almenys una de les entrades és certa.", - "LOGIC_OPERATION_OR": "o", - "LOGIC_NEGATE_TITLE": "no %1", - "LOGIC_NEGATE_TOOLTIP": "Retorna cert si l'entrada és falsa. Retorna fals si l'entrada és certa.", - "LOGIC_BOOLEAN_TRUE": "cert", - "LOGIC_BOOLEAN_FALSE": "fals", - "LOGIC_BOOLEAN_TOOLTIP": "Retorna o bé cert o bé fals.", - "LOGIC_NULL": "nul", - "LOGIC_NULL_TOOLTIP": "Retorna nul.", - "LOGIC_TERNARY_CONDITION": "condició", - "LOGIC_TERNARY_IF_TRUE": "si és cert", - "LOGIC_TERNARY_IF_FALSE": "si és fals", - "LOGIC_TERNARY_TOOLTIP": "Comprova la condició de 'condició'. Si la condició és certa, retorna el valor 'si és cert'; en cas contrari, retorna el valor 'si és fals'.", - "MATH_NUMBER_HELPURL": "https://ca.wikipedia.org/wiki/Nombre", - "MATH_NUMBER_TOOLTIP": "Un nombre.", - "MATH_ARITHMETIC_HELPURL": "https://ca.wikipedia.org/wiki/Aritm%C3%A8tica", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Retorna la suma dels dos nombres.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Retorna la diferència entre els dos nombres.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Retorna el producte del dos nombres.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Retorna el quocient dels dos nombres.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Retorna el primer nombre elevat a la potència indicada pel segon nombre.", - "MATH_SINGLE_HELPURL": "https://ca.wikipedia.org/wiki/Arrel_quadrada", - "MATH_SINGLE_OP_ROOT": "arrel quadrada", - "MATH_SINGLE_TOOLTIP_ROOT": "Retorna l'arrel quadrada d'un nombre.", - "MATH_SINGLE_OP_ABSOLUTE": "absolut", - "MATH_SINGLE_TOOLTIP_ABS": "Retorna el valor absolut d'un nombre.", - "MATH_SINGLE_TOOLTIP_NEG": "Retorna l'oposat d'un nombre.", - "MATH_SINGLE_TOOLTIP_LN": "Retorna el logaritme natural d'un nombre.", - "MATH_SINGLE_TOOLTIP_LOG10": "Retorna el logaritme en base 10 d'un nombre.", - "MATH_SINGLE_TOOLTIP_EXP": "Retorna ''e'' elevat a la potència del nombre indicat.", - "MATH_SINGLE_TOOLTIP_POW10": "Retorna 10 elevat a la potència del nombre indicat.", - "MATH_TRIG_HELPURL": "https://ca.wikipedia.org/wiki/Funci%C3%B3_trigonom%C3%A8trica", - "MATH_TRIG_TOOLTIP_SIN": "Retorna el sinus d'un grau (no radiant).", - "MATH_TRIG_TOOLTIP_COS": "Retorna el cosinus d'un grau (no radiant).", - "MATH_TRIG_TOOLTIP_TAN": "Retorna la tangent d'un grau (no radiant).", - "MATH_TRIG_TOOLTIP_ASIN": "Retorna l'arcsinus d'un nombre.", - "MATH_TRIG_TOOLTIP_ACOS": "Retorna l'arccosinus d'un nombre.", - "MATH_TRIG_TOOLTIP_ATAN": "Retorna l'arctangent d'un nombre.", - "MATH_CONSTANT_HELPURL": "https://ca.wikipedia.org/wiki/Constant_matem%C3%A0tica", - "MATH_CONSTANT_TOOLTIP": "Retorna una de les constants més habituals: π (3,141…), e (2,718…), φ (1,618…), sqrt(2) (1,414…), sqrt(½) (0,707…), o ∞ (infinit).", - "MATH_IS_EVEN": "és parell", - "MATH_IS_ODD": "és senar", - "MATH_IS_PRIME": "és primer", - "MATH_IS_WHOLE": "és enter", - "MATH_IS_POSITIVE": "és positiu", - "MATH_IS_NEGATIVE": "és negatiu", - "MATH_IS_DIVISIBLE_BY": "és divisible per", - "MATH_IS_TOOLTIP": "Comprova si un nombre és parell, senar, enter, positium negatiu, o si és divisible per un cert nombre. Retorna cert o fals.", - "MATH_CHANGE_HELPURL": "https://ca.wikipedia.org/wiki/Suma", - "MATH_CHANGE_TITLE": "canvia %1 per %2", - "MATH_CHANGE_TOOLTIP": "Afegeix un nombre a la variable '%1'.", - "MATH_ROUND_HELPURL": "https://ca.wikipedia.org/wiki/Arrodoniment", - "MATH_ROUND_TOOLTIP": "Arrodonir un nombre cap amunt o cap avall.", - "MATH_ROUND_OPERATOR_ROUND": "arrodonir", - "MATH_ROUND_OPERATOR_ROUNDUP": "arrodonir cap amunt", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "arrodonir cap avall", - "MATH_ONLIST_OPERATOR_SUM": "suma de llista", - "MATH_ONLIST_TOOLTIP_SUM": "Retorna la suma de tots els nombres de la llista.", - "MATH_ONLIST_OPERATOR_MIN": "mínim de llista", - "MATH_ONLIST_TOOLTIP_MIN": "Retorna el nombre més petit de la llista.", - "MATH_ONLIST_OPERATOR_MAX": "màxim de llista", - "MATH_ONLIST_TOOLTIP_MAX": "Retorna el nombre més gran de la llista.", - "MATH_ONLIST_OPERATOR_AVERAGE": "mitjana de llista", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Retorna la mitjana (mitjana aritmètica) dels valors numèrics de la llista.", - "MATH_ONLIST_OPERATOR_MEDIAN": "mediana de llista", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Retorna la mediana de la llista.", - "MATH_ONLIST_OPERATOR_MODE": "moda de llista", - "MATH_ONLIST_TOOLTIP_MODE": "Retorna una llista dels elements que apareixen més vegades a la llista.", - "MATH_ONLIST_OPERATOR_STD_DEV": "desviació estàndard de llista", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Retorna la desviació estàndard de la llista.", - "MATH_ONLIST_OPERATOR_RANDOM": "element aleatori de llista", - "MATH_ONLIST_TOOLTIP_RANDOM": "Retorna un element aleatori de la lllista.", - "MATH_MODULO_HELPURL": "https://ca.wikipedia.org/wiki/Residu_%28aritm%C3%A8tica%29", - "MATH_MODULO_TITLE": "residu de %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Retorna el residu de dividir els dos nombres.", - "MATH_CONSTRAIN_TITLE": "limitar %1 entre %2 i %3", - "MATH_CONSTRAIN_TOOLTIP": "Limita un nombre perquè estigui entre els límits especificats (inclosos).", - "MATH_RANDOM_INT_HELPURL": "https://ca.wikipedia.org/wiki/Generaci%C3%B3_de_nombres_aleatoris", - "MATH_RANDOM_INT_TITLE": "nombre aleatori entre %1 i %2", - "MATH_RANDOM_INT_TOOLTIP": "Retorna un nombre aleatori entre els dos límits especificats, inclosos.", - "MATH_RANDOM_FLOAT_HELPURL": "https://ca.wikipedia.org/wiki/Generaci%C3%B3_de_nombres_aleatoris", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "fracció aleatòria", - "MATH_RANDOM_FLOAT_TOOLTIP": "Retorna una fracció aleatòria entre 0,0 (inclòs) i 1,0 (exclòs).", - "TEXT_TEXT_HELPURL": "https://ca.wikipedia.org/wiki/Cadena_%28inform%C3%A0tica%29", - "TEXT_TEXT_TOOLTIP": "Una lletra, paraula o línia de text.", - "TEXT_JOIN_TITLE_CREATEWITH": "crear text amb", - "TEXT_JOIN_TOOLTIP": "Crea un tros de text per unió de qualsevol nombre d'elements.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "unir", - "TEXT_CREATE_JOIN_TOOLTIP": "Afegeix, esborrar o reordenar seccions per reconfigurar aquest bloc de text.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Afegeix un element al text.", - "TEXT_APPEND_TO": "a", - "TEXT_APPEND_APPENDTEXT": "afegir text", - "TEXT_APPEND_TOOLTIP": "Afegir un text a la variable '%1'.", - "TEXT_LENGTH_TITLE": "llargària de %1", - "TEXT_LENGTH_TOOLTIP": "Retorna el nombre de lletres (espais inclosos) en el text proporcionat.", - "TEXT_ISEMPTY_TITLE": "%1 està buit", - "TEXT_ISEMPTY_TOOLTIP": "Retorna cert si el text proporcionat està buit.", - "TEXT_INDEXOF_TOOLTIP": "Retorna l'índex de la primera/última aparició del primer text dins el segon. Retorna %1 si no es troba el text.", - "TEXT_INDEXOF_INPUT_INTEXT": "en el text", - "TEXT_INDEXOF_OPERATOR_FIRST": "trobar la primera aparició del text", - "TEXT_INDEXOF_OPERATOR_LAST": "trobar l'última aparició del text", - "TEXT_CHARAT_INPUT_INTEXT": "en el text", - "TEXT_CHARAT_FROM_START": "recupera la lletra núm.#", - "TEXT_CHARAT_FROM_END": "recupera la lletra núm.# des del final", - "TEXT_CHARAT_FIRST": "recupera la primera lletra", - "TEXT_CHARAT_LAST": "recupera l'última lletra", - "TEXT_CHARAT_RANDOM": "recupera una lletra a l'atzar", - "TEXT_CHARAT_TOOLTIP": "Recupera la lletra de la posició especificada.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Recupera una part especificada del text.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "en el text", - "TEXT_GET_SUBSTRING_START_FROM_START": "recupera subcadena des de la lletra núm.#", - "TEXT_GET_SUBSTRING_START_FROM_END": "recupera subcadena des de la lletra núm.# des del final", - "TEXT_GET_SUBSTRING_START_FIRST": "recupera subcadena des de la primera lletra", - "TEXT_GET_SUBSTRING_END_FROM_START": "fins a la lletra núm.#", - "TEXT_GET_SUBSTRING_END_FROM_END": "fins a la lletra núm.# des del final", - "TEXT_GET_SUBSTRING_END_LAST": "fins a l'última lletra", - "TEXT_CHANGECASE_TOOLTIP": "Retorna una còpia del text amb diferents majúscules/minúscules.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "a MAJÚSCULES", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "a minúscules", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "a Text De Títol", - "TEXT_TRIM_TOOLTIP": "Retorna una còpia del text on s'han esborrat els espais d'un o dels dos extrems.", - "TEXT_TRIM_OPERATOR_BOTH": "retalla espais de tots dos extrems de", - "TEXT_TRIM_OPERATOR_LEFT": "retalla espais de l'esquerra de", - "TEXT_TRIM_OPERATOR_RIGHT": "retalla espais de la dreta de", - "TEXT_PRINT_TITLE": "imprimir %1", - "TEXT_PRINT_TOOLTIP": "Imprimir el text, el nombre o altre valor especificat.", - "TEXT_PROMPT_TYPE_TEXT": "demanar text amb el missatge", - "TEXT_PROMPT_TYPE_NUMBER": "demanar un nombre amb el missatge", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Demana que l'usuari introdueixi un nombre.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Demana que l'usuari introdueixi un text.", - "LISTS_CREATE_EMPTY_TITLE": "crear llista buida", - "LISTS_CREATE_EMPTY_TOOLTIP": "Retorna una llista, de longitud 0, que no conté cap dada.", - "LISTS_CREATE_WITH_TOOLTIP": "Crea una llista amb qualsevol nombre d'elements.", - "LISTS_CREATE_WITH_INPUT_WITH": "crear llista amb", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "llista", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Afegeix, esborra o reordena seccions per reconfigurar aquest bloc de llista.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Afegeix un element a la llista.", - "LISTS_REPEAT_TOOLTIP": "Crea una llista formada pel valor donat, repetit tantes vegades com s'indiqui.", - "LISTS_REPEAT_TITLE": "crea llista amb element %1 repetit %2 vegades", - "LISTS_LENGTH_TITLE": "longitud de %1", - "LISTS_LENGTH_TOOLTIP": "Retorna la longitud d'una llista.", - "LISTS_ISEMPTY_TITLE": "%1 és buida", - "LISTS_ISEMPTY_TOOLTIP": "Retorna cert si la llista és buida.", - "LISTS_INLIST": "en la llista", - "LISTS_INDEX_OF_FIRST": "buscar primera aparició d'un element", - "LISTS_INDEX_OF_LAST": "buscar última aparició d'un element", - "LISTS_INDEX_OF_TOOLTIP": "Retorna l'índex de la primera/última aparició d'un element a la llista. Retorna %1 si no s'hi troba el text.", - "LISTS_GET_INDEX_GET": "recupera", - "LISTS_GET_INDEX_GET_REMOVE": "recupera i esborra", - "LISTS_GET_INDEX_REMOVE": "esborra", - "LISTS_GET_INDEX_FROM_END": "núm.# des del final", - "LISTS_GET_INDEX_FIRST": "primer", - "LISTS_GET_INDEX_LAST": "últim", - "LISTS_GET_INDEX_RANDOM": "a l'atzar", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 és el primer element.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 és l'últim element.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Retorna l'element de la posició especificada a la llista.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Retorna el primer element d'una llista.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Retorna l'últim element d'una llista.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Retorna un element a l'atzar d'una llista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Esborra i retorna l'element de la posició especificada de la llista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Esborra i retorna el primer element d'una llista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Esborra i retorna l'últim element d'una llista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Esborra i retorna un element a l'atzar d'una llista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Esborra l'element de la posició especificada de la llista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Esborra el primer element d'una llista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Esborra l'últim element d'una llista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Esborra un element a l'atzar d'una llista.", - "LISTS_SET_INDEX_SET": "modifica", - "LISTS_SET_INDEX_INSERT": "insereix a", - "LISTS_SET_INDEX_INPUT_TO": "com", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Modifica l'element de la posició especificada d'una llista.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Modifica el primer element d'una llista.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Modifica l'últim element d'una llista.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Modifica un element a l'atzar d'una llista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Insereix l'element a la posició especificada d'una llista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Insereix l'element al principi d'una llista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Afegeix l'element al final d'una llista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Insereix l'element en una posició a l'atzar d'una llista.", - "LISTS_GET_SUBLIST_START_FROM_START": "recupera sub-llista des de #", - "LISTS_GET_SUBLIST_START_FROM_END": "recupera sub-llista des de # des del final", - "LISTS_GET_SUBLIST_START_FIRST": "recupera sub-llista des del principi", - "LISTS_GET_SUBLIST_END_FROM_START": "fins #", - "LISTS_GET_SUBLIST_END_FROM_END": "fins # des del final", - "LISTS_GET_SUBLIST_END_LAST": "fins l'últim", - "LISTS_GET_SUBLIST_TOOLTIP": "Crea una còpia de la part especificada d'una llista.", - "VARIABLES_GET_TOOLTIP": "Retorna el valor d'aquesta variable.", - "VARIABLES_GET_CREATE_SET": "Crea 'modifica %1'", - "VARIABLES_SET": "modifica %1 a %2", - "VARIABLES_SET_TOOLTIP": "Modifica aquesta variable al valor introduït.", - "VARIABLES_SET_CREATE_GET": "Crear 'recupera %1'", - "PROCEDURES_DEFNORETURN_TITLE": "a", - "PROCEDURES_DEFNORETURN_PROCEDURE": "fes alguna cosa", - "PROCEDURES_BEFORE_PARAMS": "amb:", - "PROCEDURES_CALL_BEFORE_PARAMS": "amb:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Crea una funció sense sortida.", - "PROCEDURES_DEFRETURN_RETURN": "retorna", - "PROCEDURES_DEFRETURN_TOOLTIP": "Crea una funció amb una sortida.", - "PROCEDURES_ALLOW_STATEMENTS": "permetre declaracions", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Advertència: Aquesta funció té paràmetres duplicats.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://ca.wikipedia.org/wiki/Procediment_%28Programació%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Executa la funció definida per usuari '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "https://ca.wikipedia.org/wiki/Procediment_%28Programació%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Executa la funció definida per l'usuari '%1' i utilitza la seva sortida.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "entrades", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Afegir, eliminar o canviar l'ordre de les entrades per aquesta funció.", - "PROCEDURES_MUTATORARG_TITLE": "nom d'entrada:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Afegir una entrada per la funció.", - "PROCEDURES_HIGHLIGHT_DEF": "Iluminar la definició de la funció", - "PROCEDURES_CREATE_DO": "Crear '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Si el valor és cert, llavors retorna un segon valor.", - "PROCEDURES_IFRETURN_WARNING": "Advertència: Aquest bloc només es pot utilitzar dins de la definició d'una funció." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/cs.json b/backend/_pv_1_3_5/static/blockly/msg/json/cs.json deleted file mode 100755 index cff838b65..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/cs.json +++ /dev/null @@ -1,331 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Chmee2", - "Rosnicka.kacka", - "Matěj Grabovský", - "Espertus", - "Utar", - "Clon", - "Koo6", - "Vtmarvin", - "Dvorapa" - ] - }, - "VARIABLES_DEFAULT_NAME": "položka", - "TODAY": "Dnes", - "DUPLICATE_BLOCK": "Duplikovat", - "ADD_COMMENT": "Přidat komentář", - "REMOVE_COMMENT": "Odstranit komentář", - "EXTERNAL_INPUTS": "vnější vstupy", - "INLINE_INPUTS": "Vložené vstupy", - "DELETE_BLOCK": "Smazat blok", - "DELETE_X_BLOCKS": "Smazat %1 bloků", - "DELETE_ALL_BLOCKS": "Smazat všech %1 bloků?", - "CLEAN_UP": "Uspořádat bloky", - "COLLAPSE_BLOCK": "Sbalit blok", - "COLLAPSE_ALL": "Sbalit bloky", - "EXPAND_BLOCK": "Rozbalit blok", - "EXPAND_ALL": "Rozbalit bloky", - "DISABLE_BLOCK": "Deaktivovat blok", - "ENABLE_BLOCK": "Povolit blok", - "HELP": "Nápověda", - "UNDO": "Zpět", - "REDO": "Znovu", - "CHANGE_VALUE_TITLE": "Změnit hodnotu:", - "RENAME_VARIABLE": "Přejmenovat proměnnou...", - "RENAME_VARIABLE_TITLE": "Přejmenuj všech '%1' proměnných na:", - "NEW_VARIABLE": "Nová proměnná...", - "NEW_VARIABLE_TITLE": "Nový název proměnné:", - "COLOUR_PICKER_HELPURL": "https://cs.wikipedia.org/wiki/Barva", - "COLOUR_PICKER_TOOLTIP": "Vyberte barvu z palety.", - "COLOUR_RANDOM_TITLE": "náhodná barva", - "COLOUR_RANDOM_TOOLTIP": "Zvolte barvu náhodně.", - "COLOUR_RGB_TITLE": "obarvěte barvou", - "COLOUR_RGB_RED": "červená", - "COLOUR_RGB_GREEN": "zelená", - "COLOUR_RGB_BLUE": "modrá", - "COLOUR_RGB_TOOLTIP": "Vytvoř barvu se zadaným množstvím červené, zelené a modré. Všechny hodnoty musí být mezi 0 a 100.", - "COLOUR_BLEND_TITLE": "smíchat", - "COLOUR_BLEND_COLOUR1": "barva 1", - "COLOUR_BLEND_COLOUR2": "barva 2", - "COLOUR_BLEND_RATIO": "poměr", - "COLOUR_BLEND_TOOLTIP": "Smíchá dvě barvy v daném poměru (0.0–1.0).", - "CONTROLS_REPEAT_HELPURL": "https://cs.wikipedia.org/wiki/Cyklus_pro", - "CONTROLS_REPEAT_TITLE": "opakuj %1 krát", - "CONTROLS_REPEAT_INPUT_DO": "dělej", - "CONTROLS_REPEAT_TOOLTIP": "Proveď určité příkazy několikrát.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "opakovat když", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "opakovat dokud", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Dokud je hodnota pravdivá, prováděj určité příkazy.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Dokud je hodnota nepravdivá, prováděj určité příkazy.", - "CONTROLS_FOR_TOOLTIP": "Nechá proměnnou '%1' nabývat hodnot od počátečního do koncového čísla po daném přírůstku a provádí s ní příslušné bloky.", - "CONTROLS_FOR_TITLE": "počítat s %1 od %2 do %3 po %4", - "CONTROLS_FOREACH_TITLE": "pro každou položku %1 v seznamu %2", - "CONTROLS_FOREACH_TOOLTIP": "Pro každou položku v seznamu nastavte do proměnné '%1' danou položku a proveďte nějaké operace.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "vyskočit ze smyčky", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "pokračuj dalším opakováním smyčky", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Vyskoč z vnitřní smyčky.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Přeskoč zbytek této smyčky a pokračuj dalším opakováním.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Upozornění: Tento blok může být použit pouze uvnitř smyčky.", - "CONTROLS_IF_TOOLTIP_1": "Je-li hodnota pravda, proveď určité příkazy.", - "CONTROLS_IF_TOOLTIP_2": "Je-li hodnota pravda, proveď první blok příkazů. V opačném případě proveď druhý blok příkazů.", - "CONTROLS_IF_TOOLTIP_3": "Je-li první hodnota pravdivá, proveď první blok příkazů. V opačném případě, je-li pravdivá druhá hodnota, proveď druhý blok příkazů.", - "CONTROLS_IF_TOOLTIP_4": "Je-li první hodnota pravda, proveď první blok příkazů. Je-li druhá hodnota pravda, proveď druhý blok příkazů. Pokud žádná hodnota není pravda, proveď poslední blok příkazů.", - "CONTROLS_IF_MSG_IF": "pokud", - "CONTROLS_IF_MSG_ELSEIF": "nebo pokud", - "CONTROLS_IF_MSG_ELSE": "jinak", - "CONTROLS_IF_IF_TOOLTIP": "Přidej, odstraň či uspořádej sekce k přenastavení tohoto bloku \"pokud\".", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Přidat podmínku do \"pokud\" bloku.", - "CONTROLS_IF_ELSE_TOOLTIP": "Přidej konečnou podmínku zahrnující ostatní případy do bloku \"pokud\".", - "LOGIC_COMPARE_HELPURL": "https://cs.wikipedia.org/wiki/Nerovnost_(matematika)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Vrátí hodnotu pravda, pokud se oba vstupy rovnají jeden druhému.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Vrátí hodnotu pravda, pokud se oba vstupy nerovnají sobě navzájem.", - "LOGIC_COMPARE_TOOLTIP_LT": "Navrátí hodnotu pravda, pokud je první vstup menší než druhý vstup.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Navrátí hodnotu pravda, pokud je první vstup menší a nebo rovný druhému vstupu.", - "LOGIC_COMPARE_TOOLTIP_GT": "Navrátí hodnotu pravda, pokud první vstup je větší než druhý vstup.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Navrátí hodnotu pravda, pokud je první vstup větší a nebo rovný druhému vstupu.", - "LOGIC_OPERATION_TOOLTIP_AND": "Vrátí hodnotu pravda, pokud oba dva vstupy jsou pravdivé.", - "LOGIC_OPERATION_AND": "a", - "LOGIC_OPERATION_TOOLTIP_OR": "Vrátí hodnotu pravda, pokud alespoň jeden ze vstupů má hodnotu pravda.", - "LOGIC_OPERATION_OR": "nebo", - "LOGIC_NEGATE_TITLE": "ne %1", - "LOGIC_NEGATE_TOOLTIP": "Navrátí hodnotu pravda, pokud je vstup nepravda. Navrátí hodnotu nepravda, pokud je vstup pravda.", - "LOGIC_BOOLEAN_TRUE": "pravda", - "LOGIC_BOOLEAN_FALSE": "nepravda", - "LOGIC_BOOLEAN_TOOLTIP": "Vrací pravda nebo nepravda.", - "LOGIC_NULL": "prázdný", - "LOGIC_NULL_TOOLTIP": "Vrátí prázdnou hodnotu", - "LOGIC_TERNARY_HELPURL": "https://cs.wikipedia.org/wiki/Ternární operátor (programování)", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "pokud pravda", - "LOGIC_TERNARY_IF_FALSE": "pokud nepravda", - "LOGIC_TERNARY_TOOLTIP": "Zkontroluje podmínku v \"testu\". Když je podmínka pravda, vrátí hodnotu \"pokud pravda\"; v opačném případě vrátí hodnotu \"pokud nepravda\".", - "MATH_NUMBER_HELPURL": "https://cs.wikipedia.org/wiki/Číslo", - "MATH_NUMBER_TOOLTIP": "Číslo.", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tan", - "MATH_TRIG_ASIN": "arcsin", - "MATH_TRIG_ACOS": "acos", - "MATH_TRIG_ATAN": "arctan", - "MATH_ARITHMETIC_HELPURL": "https://cs.wikipedia.org/wiki/Aritmetika", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Vrátí součet dvou čísel.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Vrátí rozdíl dvou čísel.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Vrátí součin dvou čísel.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Vrátí podíl dvou čísel.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Vrátí první číslo umocněné na druhé číslo.", - "MATH_SINGLE_HELPURL": "https://cs.wikipedia.org/wiki/Druhá_odmocnina", - "MATH_SINGLE_OP_ROOT": "druhá odmocnina", - "MATH_SINGLE_TOOLTIP_ROOT": "Vrátí druhou odmocninu čísla.", - "MATH_SINGLE_OP_ABSOLUTE": "absolutní hodnota", - "MATH_SINGLE_TOOLTIP_ABS": "Vrátí absolutní hodnotu čísla.", - "MATH_SINGLE_TOOLTIP_NEG": "Vrátí zápornou hodnotu čísla.", - "MATH_SINGLE_TOOLTIP_LN": "Vrátí přirozený logaritmus čísla.", - "MATH_SINGLE_TOOLTIP_LOG10": "Vrátí desítkový logaritmus čísla.", - "MATH_SINGLE_TOOLTIP_EXP": "Vrátí mocninu čísla e.", - "MATH_SINGLE_TOOLTIP_POW10": "Vrátí mocninu čísla 10.", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "Vrátí sinus úhlu ve stupních.", - "MATH_TRIG_TOOLTIP_COS": "Vrátí kosinus úhlu ve stupních.", - "MATH_TRIG_TOOLTIP_TAN": "Vrátí tangens úhlu ve stupních.", - "MATH_TRIG_TOOLTIP_ASIN": "Vrátí arkus sinus čísla.", - "MATH_TRIG_TOOLTIP_ACOS": "Vrátí arkus kosinus čísla.", - "MATH_TRIG_TOOLTIP_ATAN": "Vrátí arkus tangens čísla.", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "Vraťte jednu z následujících konstant: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (nekonečno).", - "MATH_IS_EVEN": "je sudé", - "MATH_IS_ODD": "je liché", - "MATH_IS_PRIME": "je prvočíslo", - "MATH_IS_WHOLE": "je celé", - "MATH_IS_POSITIVE": "je kladné", - "MATH_IS_NEGATIVE": "je záporné", - "MATH_IS_DIVISIBLE_BY": "je dělitelné číslem", - "MATH_IS_TOOLTIP": "Kontrola, zda je číslo sudé, liché, prvočíslo, celé, kladné, záporné nebo zda je dělitelné daným číslem. Vrací pravdu nebo nepravdu.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "zaměň %1 za %2", - "MATH_CHANGE_TOOLTIP": "Přičti číslo k proměnné '%1'.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Zaokrouhlit číslo nahoru nebo dolů.", - "MATH_ROUND_OPERATOR_ROUND": "zaokrouhlit", - "MATH_ROUND_OPERATOR_ROUNDUP": "zaokrouhlit nahoru", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "zaokrouhlit dolů", - "MATH_ONLIST_OPERATOR_SUM": "suma seznamu", - "MATH_ONLIST_TOOLTIP_SUM": "Vrátí součet všech čísel v seznamu.", - "MATH_ONLIST_OPERATOR_MIN": "nejmenší v seznamu", - "MATH_ONLIST_TOOLTIP_MIN": "Vrátí nejmenší číslo v seznamu.", - "MATH_ONLIST_OPERATOR_MAX": "největší v seznamu", - "MATH_ONLIST_TOOLTIP_MAX": "Vrátí největší číslo v seznamu.", - "MATH_ONLIST_OPERATOR_AVERAGE": "průměr v seznamu", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Vrátí průměr (aritmetický průměr) číselných hodnot v seznamu.", - "MATH_ONLIST_OPERATOR_MEDIAN": "medián v seznamu", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Vrátí medián seznamu.", - "MATH_ONLIST_OPERATOR_MODE": "nejčastější ze seznamu", - "MATH_ONLIST_TOOLTIP_MODE": "Vrátí seznam nejčastějších položek seznamu.", - "MATH_ONLIST_OPERATOR_STD_DEV": "směrodatná odchylka ze seznamu", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Vrátí směrodatnou odchylku seznamu.", - "MATH_ONLIST_OPERATOR_RANDOM": "náhodná položka seznamu", - "MATH_ONLIST_TOOLTIP_RANDOM": "Vrátí náhodnou položku ze seznamu.", - "MATH_MODULO_HELPURL": "https://cs.wikipedia.org/wiki/Modul%C3%A1rn%C3%AD_aritmetika", - "MATH_MODULO_TITLE": "zbytek po dělení %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Vrátí zbytek po dělení dvou čísel.", - "MATH_CONSTRAIN_TITLE": "omez %1 na rozmezí od %2 do %3", - "MATH_CONSTRAIN_TOOLTIP": "Omezí číslo tak, aby bylo ve stanovených mezích (včetně).", - "MATH_RANDOM_INT_HELPURL": "https://cs.wikipedia.org/wiki/Gener%C3%A1tor_n%C3%A1hodn%C3%BDch_%C4%8D%C3%ADsel", - "MATH_RANDOM_INT_TITLE": "náhodné celé číslo od %1 do %2", - "MATH_RANDOM_INT_TOOLTIP": "Vrací náhodné celé číslo mezi dvěma určenými mezemi, včetně mezních hodnot.", - "MATH_RANDOM_FLOAT_HELPURL": "https://cs.wikipedia.org/wiki/Gener%C3%A1tor_n%C3%A1hodn%C3%BDch_%C4%8D%C3%ADsel", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "náhodné číslo mezi 0 (včetně) do 1", - "MATH_RANDOM_FLOAT_TOOLTIP": "Vrátí náhodné číslo mezi 0,0 (včetně) až 1,0", - "TEXT_TEXT_HELPURL": "https://cs.wikipedia.org/wiki/Textov%C3%BD_%C5%99et%C4%9Bzec", - "TEXT_TEXT_TOOLTIP": "Písmeno, slovo nebo řádek textu.", - "TEXT_JOIN_TITLE_CREATEWITH": "vytvořit text s", - "TEXT_JOIN_TOOLTIP": "Vytvoří kousek textu spojením libovolného počtu položek.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "spojit", - "TEXT_CREATE_JOIN_TOOLTIP": "Přidat, odebrat nebo změnit pořadí oddílů tohoto textového bloku.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Přidat položku do textu.", - "TEXT_APPEND_TO": "do", - "TEXT_APPEND_APPENDTEXT": "přidat text", - "TEXT_APPEND_TOOLTIP": "Přidá určitý text k proměnné '%1'.", - "TEXT_LENGTH_TITLE": "délka %1", - "TEXT_LENGTH_TOOLTIP": "Vrátí počet písmen (včetně mezer) v zadaném textu.", - "TEXT_ISEMPTY_TITLE": "%1 je prázdný", - "TEXT_ISEMPTY_TOOLTIP": "Vrátí pravda pokud je zadaný text prázdný.", - "TEXT_INDEXOF_TOOLTIP": "Vrátí index prvního/posledního výskytu prvního textu v druhém textu. Pokud text není nalezen, vypíše %1.", - "TEXT_INDEXOF_INPUT_INTEXT": "v textu", - "TEXT_INDEXOF_OPERATOR_FIRST": "najít první výskyt textu", - "TEXT_INDEXOF_OPERATOR_LAST": "najít poslední výskyt textu", - "TEXT_CHARAT_INPUT_INTEXT": "v textu", - "TEXT_CHARAT_FROM_START": "získat písmeno #", - "TEXT_CHARAT_FROM_END": "získat # písmeno od konce", - "TEXT_CHARAT_FIRST": "získat první písmeno", - "TEXT_CHARAT_LAST": "získat poslední písmeno", - "TEXT_CHARAT_RANDOM": "získat náhodné písmeno", - "TEXT_CHARAT_TOOLTIP": "Získat písmeno na konkrétní pozici.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Získat zadanou část textu.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "v textu", - "TEXT_GET_SUBSTRING_START_FROM_START": "získat podřetězec od písmene #", - "TEXT_GET_SUBSTRING_START_FROM_END": "získat podřetězec od písmene # od konce", - "TEXT_GET_SUBSTRING_START_FIRST": "získat podřetězec od prvního písmene", - "TEXT_GET_SUBSTRING_END_FROM_START": "do písmene #", - "TEXT_GET_SUBSTRING_END_FROM_END": "do # písmene od konce", - "TEXT_GET_SUBSTRING_END_LAST": "do posledního písmene", - "TEXT_CHANGECASE_TOOLTIP": "Vrátí kopii textu s jinou velikostí písmen.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "na VELKÁ PÍSMENA", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "na malá písmena", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "na Počáteční Velká Písmena", - "TEXT_TRIM_TOOLTIP": "Vrátí kopii textu s odstraněnými mezerami z jednoho nebo obou konců.", - "TEXT_TRIM_OPERATOR_BOTH": "odstranit mezery z obou stran", - "TEXT_TRIM_OPERATOR_LEFT": "odstranit mezery z levé strany", - "TEXT_TRIM_OPERATOR_RIGHT": "odstranit mezery z pravé strany", - "TEXT_PRINT_TITLE": "tisk %1", - "TEXT_PRINT_TOOLTIP": "Tisk zadaného textu, čísla nebo jiné hodnoty.", - "TEXT_PROMPT_TYPE_TEXT": "výzva k zadání textu se zprávou", - "TEXT_PROMPT_TYPE_NUMBER": "výzva k zadání čísla se zprávou", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Výzva pro uživatele k zadání čísla.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Výzva pro uživatele k zadání nějakého textu.", - "LISTS_CREATE_EMPTY_TITLE": "vytvořit prázdný seznam", - "LISTS_CREATE_EMPTY_TOOLTIP": "Vrátí seznam nulové délky, který neobsahuje žádné datové záznamy", - "LISTS_CREATE_WITH_TOOLTIP": "Vytvoř seznam s libovolným počtem položek.", - "LISTS_CREATE_WITH_INPUT_WITH": "vytvořit seznam s", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "seznam", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Přidat, odebrat nebo změnit pořadí oddílů tohoto seznamu bloku.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Přidat položku do seznamu.", - "LISTS_REPEAT_TOOLTIP": "Vytváří seznam obsahující danou hodnotu n-krát.", - "LISTS_REPEAT_TITLE": "vytvoř seznam s položkou %1 opakovanou %1 krát", - "LISTS_LENGTH_TITLE": "délka %1", - "LISTS_LENGTH_TOOLTIP": "Vrací počet položek v seznamu.", - "LISTS_ISEMPTY_TITLE": "%1 je prázdné", - "LISTS_ISEMPTY_TOOLTIP": "Vrátí hodnotu pravda, pokud je seznam prázdný.", - "LISTS_INLIST": "v seznamu", - "LISTS_INDEX_OF_FIRST": "najít první výskyt položky", - "LISTS_INDEX_OF_LAST": "najít poslední výskyt položky", - "LISTS_INDEX_OF_TOOLTIP": "Vrací index prvního/posledního výskytu položky v seznamu. Vrací %1, pokud položka nebyla nalezena.", - "LISTS_GET_INDEX_GET": "získat", - "LISTS_GET_INDEX_GET_REMOVE": "získat a odstranit", - "LISTS_GET_INDEX_REMOVE": "odstranit", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# od konce", - "LISTS_GET_INDEX_FIRST": "první", - "LISTS_GET_INDEX_LAST": "poslední", - "LISTS_GET_INDEX_RANDOM": "náhodné", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 je první položka.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 je poslední položka.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Získá položku z určené pozice v seznamu.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Vrátí první položku v seznamu.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Vrátí poslední položku v seznamu.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Vrátí náhodnou položku ze seznamu.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Odstraní a získá položku z určené pozice v seznamu.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Odstraní a vrátí první položku v seznamu.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Odstraní a vrátí poslední položku v seznamu.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Odstraní a vrátí náhodnou položku v seznamu.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Odebere položku na konkrétním místě v seznamu.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Odstraní první položku v seznamu.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Odstraní poslední položku v seznamu.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Odstraní náhodou položku v seznamu.", - "LISTS_SET_INDEX_SET": "nastavit", - "LISTS_SET_INDEX_INSERT": "vložit na", - "LISTS_SET_INDEX_INPUT_TO": "jako", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Nastaví položku na konkrétní místo v seznamu.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Nastaví první položku v seznamu.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Nastaví poslední položku v seznamu.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Nastaví náhodnou položku v seznamu.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Vloží položku na určenou pozici v seznamu.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Vložit položku na začátek seznamu.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Připojí položku na konec seznamu.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Připojí položku náhodně do seznamu.", - "LISTS_GET_SUBLIST_START_FROM_START": "získat podseznam od #", - "LISTS_GET_SUBLIST_START_FROM_END": "získat podseznam od # od konce", - "LISTS_GET_SUBLIST_START_FIRST": "získat podseznam od první položky", - "LISTS_GET_SUBLIST_END_FROM_START": "do #", - "LISTS_GET_SUBLIST_END_FROM_END": "do # od konce", - "LISTS_GET_SUBLIST_END_LAST": "jako poslední", - "LISTS_GET_SUBLIST_TOOLTIP": "Vytvoří kopii určené části seznamu.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "seřadit %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Seřadit kopii seznamu.", - "LISTS_SORT_ORDER_ASCENDING": "vzestupně", - "LISTS_SORT_ORDER_DESCENDING": "sestupně", - "LISTS_SORT_TYPE_NUMERIC": "číselné", - "LISTS_SORT_TYPE_TEXT": "abecedně", - "LISTS_SORT_TYPE_IGNORECASE": "abecedně, na velikosti písmen nezáleží", - "LISTS_SPLIT_LIST_FROM_TEXT": "udělat z textu seznam", - "LISTS_SPLIT_TEXT_FROM_LIST": "udělat ze seznamu text", - "LISTS_SPLIT_WITH_DELIMITER": "s oddělovačem", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Rozdělit text do seznamu textů, lámání na oddělovačích.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Spojit seznam textů do jednoho textu, rozdělaného oddělovači.", - "VARIABLES_GET_TOOLTIP": "Vrátí hodnotu této proměnné.", - "VARIABLES_GET_CREATE_SET": "Vytvořit \"nastavit %1\"", - "VARIABLES_SET": "nastavit %1 na %2", - "VARIABLES_SET_TOOLTIP": "Nastaví tuto proměnnou, aby se rovnala vstupu.", - "VARIABLES_SET_CREATE_GET": "Vytvořit \"získat %1\"", - "PROCEDURES_DEFNORETURN_HELPURL": "https://cs.wikipedia.org/w/index.php?title=Funkce_(programování)", - "PROCEDURES_DEFNORETURN_TITLE": "k provedení", - "PROCEDURES_DEFNORETURN_PROCEDURE": "proveď něco", - "PROCEDURES_BEFORE_PARAMS": "s:", - "PROCEDURES_CALL_BEFORE_PARAMS": "s:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Vytvořit funkci bez výstupu.", - "PROCEDURES_DEFNORETURN_COMMENT": "Popište tuto funkci...", - "PROCEDURES_DEFRETURN_HELPURL": "https://cs.wikipedia.org/w/index.php?title=Funkce_(programování)", - "PROCEDURES_DEFRETURN_RETURN": "navrátit", - "PROCEDURES_DEFRETURN_TOOLTIP": "Vytvořit funkci s výstupem.", - "PROCEDURES_ALLOW_STATEMENTS": "povolit příkazy", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Upozornění: Tato funkce má duplicitní parametry.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://cs.wikipedia.org/wiki/Funkce_(programov%C3%A1n%C3%AD)", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Spustí uživatelem definovanou funkci '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "https://cs.wikipedia.org/wiki/Funkce_(programov%C3%A1n%C3%AD)", - "PROCEDURES_CALLRETURN_TOOLTIP": "Spustí uživatelem definovanou funkci '%1' a použije její výstup.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "vstupy", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Přidat, odebrat nebo změnit pořadí vstupů této funkce.", - "PROCEDURES_MUTATORARG_TITLE": "vstupní jméno:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Přidat vstupy do funkce.", - "PROCEDURES_HIGHLIGHT_DEF": "Zvýraznit definici funkce", - "PROCEDURES_CREATE_DO": "Vytvořit '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Je-li hodnota pravda, pak vrátí druhou hodnotu.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Varování: Tento blok může být použit pouze uvnitř definici funkce." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/da.json b/backend/_pv_1_3_5/static/blockly/msg/json/da.json deleted file mode 100755 index 636bd7cd1..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/da.json +++ /dev/null @@ -1,303 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Christian List", - "RickiRunge", - "MGA73", - "Mads Haupt" - ] - }, - "VARIABLES_DEFAULT_NAME": "element", - "TODAY": "I dag", - "DUPLICATE_BLOCK": "Duplikér", - "ADD_COMMENT": "Tilføj kommentar", - "REMOVE_COMMENT": "Fjern kommentar", - "EXTERNAL_INPUTS": "Udvendige inputs", - "INLINE_INPUTS": "Indlejrede inputs", - "DELETE_BLOCK": "Slet blok", - "DELETE_X_BLOCKS": "Slet %1 blokke", - "DELETE_ALL_BLOCKS": "Slet alle %1 blokke?", - "CLEAN_UP": "Ryd op i blokke", - "COLLAPSE_BLOCK": "Fold blokken sammen", - "COLLAPSE_ALL": "Fold blokkene sammen", - "EXPAND_BLOCK": "Fold blokken ud", - "EXPAND_ALL": "Fold blokkene ud", - "DISABLE_BLOCK": "Deaktivér blok", - "ENABLE_BLOCK": "Aktivér blok", - "HELP": "Hjælp", - "CHANGE_VALUE_TITLE": "Skift værdi:", - "RENAME_VARIABLE": "Omdøb variabel...", - "RENAME_VARIABLE_TITLE": "Omdøb alle '%1' variabler til:", - "NEW_VARIABLE": "Ny variabel...", - "NEW_VARIABLE_TITLE": "Navn til den nye variabel:", - "COLOUR_PICKER_HELPURL": "https://da.wikipedia.org/wiki/Farve", - "COLOUR_PICKER_TOOLTIP": "Vælg en farve fra paletten.", - "COLOUR_RANDOM_TITLE": "tilfældig farve", - "COLOUR_RANDOM_TOOLTIP": "Vælg en tilfældig farve.", - "COLOUR_RGB_TITLE": "farve med", - "COLOUR_RGB_RED": "rød", - "COLOUR_RGB_GREEN": "grøn", - "COLOUR_RGB_BLUE": "blå", - "COLOUR_RGB_TOOLTIP": "Lav en farve med den angivne mængde af rød, grøn og blå. Alle værdier skal være mellem 0 og 100.", - "COLOUR_BLEND_TITLE": "bland", - "COLOUR_BLEND_COLOUR1": "farve 1", - "COLOUR_BLEND_COLOUR2": "farve 2", - "COLOUR_BLEND_RATIO": "i forholdet", - "COLOUR_BLEND_TOOLTIP": "Blander to farver sammen i et bestemt forhold (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://da.wikipedia.org/wiki/For-l%C3%B8kke", - "CONTROLS_REPEAT_TITLE": "gentag %1 gange", - "CONTROLS_REPEAT_INPUT_DO": "udfør", - "CONTROLS_REPEAT_TOOLTIP": "Udfør nogle kommandoer flere gange.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "gentag sålænge", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "gentag indtil", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Udfør nogle kommandoer, sålænge en værdi er sand.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Udfør nogle kommandoer, sålænge en værdi er falsk.", - "CONTROLS_FOR_TOOLTIP": "Få variablen \"%1\" til at have værdierne fra startværdien til slutværdien, mens der tælles med det angivne interval, og udfør de angivne blokke.", - "CONTROLS_FOR_TITLE": "tæl med %1 fra %2 til %3 med %4", - "CONTROLS_FOREACH_TITLE": "for hvert element %1 i listen %2", - "CONTROLS_FOREACH_TOOLTIP": "For hvert element i en liste, sæt variablen '%1' til elementet, og udfør derefter nogle kommandoer.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "bryd ud af løkken", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "fortsæt med den næste gentagelse i løkken", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Bryd ud af den omgivende løkke.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Spring resten af denne løkke over, og fortsæt med den næste gentagelse.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Advarsel: Denne blok kan kun bruges i en løkke.", - "CONTROLS_IF_TOOLTIP_1": "Hvis en værdi er sand, så udfør nogle kommandoer.", - "CONTROLS_IF_TOOLTIP_2": "Hvis en værdi er sand, så udfør den første blok af kommandoer. Ellers udfør den anden blok af kommandoer.", - "CONTROLS_IF_TOOLTIP_3": "Hvis den første værdi er sand, så udfør den første blok af kommandoer. Ellers, hvis den anden værdi er sand, så udfør den anden blok af kommandoer.", - "CONTROLS_IF_TOOLTIP_4": "Hvis den første værdi er sand, så udfør den første blok af kommandoer. Ellers, hvis den anden værdi er sand, så udfør den anden blok af kommandoer. Hvis ingen af værdierne er sande, så udfør den sidste blok af kommandoer.", - "CONTROLS_IF_MSG_IF": "hvis", - "CONTROLS_IF_MSG_ELSEIF": "ellers hvis", - "CONTROLS_IF_MSG_ELSE": "ellers", - "CONTROLS_IF_IF_TOOLTIP": "Tilføj, fjern eller byt om på rækkefølgen af delene for at konfigurere denne \"hvis\" blok.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Tilføj en betingelse til denne \"hvis\" blok.", - "CONTROLS_IF_ELSE_TOOLTIP": "Tilføj en sidste fang-alt betingelse, til denne \"hvis\" blok.", - "LOGIC_COMPARE_HELPURL": "https://da.wikipedia.org/wiki/Ulighed_(matematik)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Returnere sand, hvis begge inputs er lig med hinanden.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Returnere sand, hvis begge inputs ikke er lig med hinanden.", - "LOGIC_COMPARE_TOOLTIP_LT": "Returnere sand, hvis det første input er mindre end det andet input.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Returnere sand, hvis det første input er mindre end eller lig med det andet input.", - "LOGIC_COMPARE_TOOLTIP_GT": "Returnere sand, hvis det første input er større end det andet input.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Returnere sand, hvis det første input er større end eller lig med det andet input.", - "LOGIC_OPERATION_TOOLTIP_AND": "Returnere sand, hvis begge inputs er sande.", - "LOGIC_OPERATION_AND": "og", - "LOGIC_OPERATION_TOOLTIP_OR": "Returnere sand, hvis mindst et af inputtene er sande.", - "LOGIC_OPERATION_OR": "eller", - "LOGIC_NEGATE_TITLE": "ikke %1", - "LOGIC_NEGATE_TOOLTIP": "Returnerer sand, hvis input er falsk. Returnerer falsk, hvis input er sandt.", - "LOGIC_BOOLEAN_TRUE": "sand", - "LOGIC_BOOLEAN_FALSE": "falsk", - "LOGIC_BOOLEAN_TOOLTIP": "Returnerer enten sand eller falsk.", - "LOGIC_NULL": "null", - "LOGIC_NULL_TOOLTIP": "Returnerer null.", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "hvis sand", - "LOGIC_TERNARY_IF_FALSE": "hvis falsk", - "LOGIC_TERNARY_TOOLTIP": "Kontrollér betingelsen i 'test'. Hvis betingelsen er sand, returnér \"hvis sand\" værdien; ellers returnér \"hvis falsk\" værdien.", - "MATH_NUMBER_HELPURL": "https://da.wikipedia.org/wiki/Tal", - "MATH_NUMBER_TOOLTIP": "Et tal.", - "MATH_DIVISION_SYMBOL": ":", - "MATH_ARITHMETIC_HELPURL": "https://da.wikipedia.org/wiki/Aritmetik", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Returnere summen af de to tal.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Returnere forskellen mellem de to tal.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Returnere produktet af de to tal.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Returnere kvotienten af de to tal.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Returnere det første tal opløftet til potensen af det andet tal.", - "MATH_SINGLE_HELPURL": "https://da.wikipedia.org/wiki/Kvadratrod", - "MATH_SINGLE_OP_ROOT": "kvadratrod", - "MATH_SINGLE_TOOLTIP_ROOT": "Returnere kvadratroden af et tal.", - "MATH_SINGLE_OP_ABSOLUTE": "absolut", - "MATH_SINGLE_TOOLTIP_ABS": "Returnere den absolutte værdi af et tal.", - "MATH_SINGLE_TOOLTIP_NEG": "Returnere negationen af et tal.", - "MATH_SINGLE_TOOLTIP_LN": "Returnere den naturlige logaritme af et tal.", - "MATH_SINGLE_TOOLTIP_LOG10": "Returnere 10-talslogaritmen af et tal.", - "MATH_SINGLE_TOOLTIP_EXP": "Returnere e til potensen af et tal.", - "MATH_SINGLE_TOOLTIP_POW10": "Returnere 10 til potensen af et tal.", - "MATH_TRIG_HELPURL": "https://da.wikipedia.org/wiki/Trigonometrisk_funktion", - "MATH_TRIG_TOOLTIP_SIN": "Returnere sinus af en vinkel (i grader).", - "MATH_TRIG_TOOLTIP_COS": "Returnere cosinus af en vinkel (i grader).", - "MATH_TRIG_TOOLTIP_TAN": "Returnere tangens af en vinkel (i grader).", - "MATH_TRIG_TOOLTIP_ASIN": "Returnere arcus sinus af et tal.", - "MATH_TRIG_TOOLTIP_ACOS": "Returnere arcus cosinus af et tal.", - "MATH_TRIG_TOOLTIP_ATAN": "Returnere arcus tangens af et tal.", - "MATH_CONSTANT_HELPURL": "https://da.wikipedia.org/wiki/Matematisk_konstant", - "MATH_CONSTANT_TOOLTIP": "Returnere en af de ofte brugte konstanter: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(2) (1.414…), sqrt(½) (0.707…) eller ∞ (uendeligt).", - "MATH_IS_EVEN": "er lige", - "MATH_IS_ODD": "er ulige", - "MATH_IS_PRIME": "er et primtal", - "MATH_IS_WHOLE": "er helt", - "MATH_IS_POSITIVE": "er positivt", - "MATH_IS_NEGATIVE": "er negativt", - "MATH_IS_DIVISIBLE_BY": "er deleligt med", - "MATH_IS_TOOLTIP": "Kontrollere, om et tal er lige, ulige, primtal, helt, positivt, negativt, eller om det er deleligt med bestemt tal. Returnere sandt eller falskt.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "skift %1 med %2", - "MATH_CHANGE_TOOLTIP": "Læg et tal til variablen '%1'.", - "MATH_ROUND_HELPURL": "https://da.wikipedia.org/wiki/Afrunding", - "MATH_ROUND_TOOLTIP": "Runde et tal op eller ned.", - "MATH_ROUND_OPERATOR_ROUND": "afrund", - "MATH_ROUND_OPERATOR_ROUNDUP": "rund op", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "rund ned", - "MATH_ONLIST_OPERATOR_SUM": "summen af listen", - "MATH_ONLIST_TOOLTIP_SUM": "Returner summen af alle tal i listen.", - "MATH_ONLIST_OPERATOR_MIN": "mindste tal i listen", - "MATH_ONLIST_TOOLTIP_MIN": "Returner det mindste tal i listen.", - "MATH_ONLIST_OPERATOR_MAX": "største tal i listen", - "MATH_ONLIST_TOOLTIP_MAX": "Returner det største tal i listen.", - "MATH_ONLIST_OPERATOR_AVERAGE": "gennemsnit af listen", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Returner gennemsnittet (middelværdien) af de numeriske værdier i listen.", - "MATH_ONLIST_OPERATOR_MEDIAN": "listens median", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Returner listens median.", - "MATH_ONLIST_OPERATOR_MODE": "listens typetal", - "MATH_ONLIST_TOOLTIP_MODE": "Returner en liste over de mest almindelige elementer på listen.", - "MATH_ONLIST_OPERATOR_STD_DEV": "standardafvigelsen for listen", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Returner standardafvigelsen for listen.", - "MATH_ONLIST_OPERATOR_RANDOM": "tilfældigt element fra listen", - "MATH_ONLIST_TOOLTIP_RANDOM": "Returner et tilfældigt element fra listen.", - "MATH_MODULO_HELPURL": "https://da.wikipedia.org/wiki/Modulo", - "MATH_MODULO_TITLE": "resten af %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Returner resten fra at dividere de to tal.", - "MATH_CONSTRAIN_TITLE": "begræns %1 til mellem %2 og %3", - "MATH_CONSTRAIN_TOOLTIP": "Begræns et tal til at være mellem de angivne grænser (inklusiv).", - "MATH_RANDOM_INT_HELPURL": "https://da.wikipedia.org/wiki/Tilfældighedsgenerator", - "MATH_RANDOM_INT_TITLE": "tilfældigt heltal mellem %1 og %2", - "MATH_RANDOM_INT_TOOLTIP": "Returner et tilfældigt heltal mellem de to angivne grænser (inklusiv).", - "MATH_RANDOM_FLOAT_HELPURL": "https://da.wikipedia.org/wiki/Tilfældighedsgenerator", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "tilfældigt decimaltal (mellem 0 og 1)", - "MATH_RANDOM_FLOAT_TOOLTIP": "Returner et tilfældigt decimaltal mellem 0,0 (inklusiv) og 1,0 (eksklusiv).", - "TEXT_TEXT_HELPURL": "https://da.wikipedia.org/wiki/Tekststreng", - "TEXT_TEXT_TOOLTIP": "En bogstav, et ord eller en linje med tekst.", - "TEXT_JOIN_TITLE_CREATEWITH": "lav en tekst med", - "TEXT_JOIN_TOOLTIP": "Lav et stykke tekst ved at sætte et antal elementer sammen.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "sammenføj", - "TEXT_CREATE_JOIN_TOOLTIP": "Tilføj, fjern eller byt om på rækkefølgen af delene for at konfigurere denne tekstblok.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Føj et element til teksten.", - "TEXT_APPEND_TO": "til", - "TEXT_APPEND_APPENDTEXT": "tilføj tekst", - "TEXT_APPEND_TOOLTIP": "Tilføj noget tekst til variablen '%1'.", - "TEXT_LENGTH_TITLE": "længden af %1", - "TEXT_LENGTH_TOOLTIP": "Returnerer antallet af bogstaver (herunder mellemrum) i den angivne tekst.", - "TEXT_ISEMPTY_TITLE": "%1 er tom", - "TEXT_ISEMPTY_TOOLTIP": "Returnerer sand, hvis den angivne tekst er tom.", - "TEXT_INDEXOF_TOOLTIP": "Returnerer indeks for første/sidste forekomst af første tekst i den anden tekst. Returnerer %1, hvis teksten ikke kan findes.", - "TEXT_INDEXOF_INPUT_INTEXT": "i teksten", - "TEXT_INDEXOF_OPERATOR_FIRST": "find første forekomst af teksten", - "TEXT_INDEXOF_OPERATOR_LAST": "find sidste forekomst af teksten", - "TEXT_CHARAT_INPUT_INTEXT": "i teksten", - "TEXT_CHARAT_FROM_START": "hent bogstav #", - "TEXT_CHARAT_FROM_END": "hent bogstav # fra slutningen", - "TEXT_CHARAT_FIRST": "hent første bogstav", - "TEXT_CHARAT_LAST": "hent sidste bogstav", - "TEXT_CHARAT_RANDOM": "hent tilfældigt bogstav", - "TEXT_CHARAT_TOOLTIP": "Returnerer bogstavet på den angivne placering.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Returnerer den angivne del af teksten.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "i teksten", - "TEXT_GET_SUBSTRING_START_FROM_START": "hent delstreng fra bogstav #", - "TEXT_GET_SUBSTRING_START_FROM_END": "hent delstreng fra bogstav # fra slutningen", - "TEXT_GET_SUBSTRING_START_FIRST": "hent delstreng fra første bogstav", - "TEXT_GET_SUBSTRING_END_FROM_START": "til bogstav #", - "TEXT_GET_SUBSTRING_END_FROM_END": "til bogstav # fra slutningen", - "TEXT_GET_SUBSTRING_END_LAST": "til sidste bogstav", - "TEXT_CHANGECASE_TOOLTIP": "Returner en kopi af teksten hvor bogstaverne enten er udelukkende store eller små, eller hvor første bogstav i hvert ord er stort.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "til STORE BOGSTAVER", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "til små bogstaver", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "til Stort Begyndelsesbogstav", - "TEXT_TRIM_TOOLTIP": "Returner en kopi af teksten med mellemrum fjernet fra den ene eller begge sider.", - "TEXT_TRIM_OPERATOR_BOTH": "fjern mellemrum fra begge sider af", - "TEXT_TRIM_OPERATOR_LEFT": "fjern mellemrum fra venstre side af", - "TEXT_TRIM_OPERATOR_RIGHT": "fjern mellemrum fra højre side af", - "TEXT_PRINT_TITLE": "skriv %1", - "TEXT_PRINT_TOOLTIP": "Skriv den angivne tekst, tal eller anden værdi.", - "TEXT_PROMPT_TYPE_TEXT": "spørg efter tekst med meddelelsen", - "TEXT_PROMPT_TYPE_NUMBER": "spørg efter et tal med meddelelsen", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Spørg brugeren efter et tal", - "TEXT_PROMPT_TOOLTIP_TEXT": "Spørg brugeren efter en tekst", - "LISTS_CREATE_EMPTY_TITLE": "opret en tom liste", - "LISTS_CREATE_EMPTY_TOOLTIP": "Returnerer en liste af længde 0, som ikke indeholder nogen data", - "LISTS_CREATE_WITH_TOOLTIP": "Opret en liste med et vilkårligt antal elementer.", - "LISTS_CREATE_WITH_INPUT_WITH": "opret liste med", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "liste", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Tilføj, fjern eller byt om på rækkefølgen af delene for at konfigurere denne blok.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Føj et element til listen.", - "LISTS_REPEAT_TOOLTIP": "Opretter en liste bestående af den givne værdi gentaget et bestemt antal gange.", - "LISTS_REPEAT_TITLE": "opret liste med elementet %1 gentaget %2 gange", - "LISTS_LENGTH_TITLE": "længden af %1", - "LISTS_LENGTH_TOOLTIP": "Returnerer længden af en liste.", - "LISTS_ISEMPTY_TITLE": "%1 er tom", - "LISTS_ISEMPTY_TOOLTIP": "Returnerer sand, hvis listen er tom.", - "LISTS_INLIST": "i listen", - "LISTS_INDEX_OF_FIRST": "find første forekomst af elementet", - "LISTS_INDEX_OF_LAST": "find sidste forekomst af elementet", - "LISTS_INDEX_OF_TOOLTIP": "Returnerer indeks for første/sidste forekomst af elementet i listen. Returnerer %1, hvis elementet ikke kan findes.", - "LISTS_GET_INDEX_GET": "hent", - "LISTS_GET_INDEX_GET_REMOVE": "hent og fjern", - "LISTS_GET_INDEX_REMOVE": "fjern", - "LISTS_GET_INDEX_FROM_END": "# fra slutningen", - "LISTS_GET_INDEX_FIRST": "første", - "LISTS_GET_INDEX_LAST": "sidste", - "LISTS_GET_INDEX_RANDOM": "tilfældig", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 er det første element.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 er det sidste element.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Returnerer elementet på den angivne position på en liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Returnerer det første element i en liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Returnerer den sidste element i en liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Returnerer et tilfældigt element i en liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Fjerner og returnerer elementet på den angivne position på en liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Fjerner og returnerer det første element i en liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Fjerner og returnerer det sidste element i en liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Fjerner og returnerer et tilfældigt element i en liste.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Fjerner elementet på den angivne position på en liste.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Fjerner det første element i en liste.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Fjerner sidste element i en liste.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Fjerner et tilfældigt element i en liste.", - "LISTS_SET_INDEX_SET": "sæt", - "LISTS_SET_INDEX_INSERT": "indsæt ved", - "LISTS_SET_INDEX_INPUT_TO": "som", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Sætter elementet på den angivne position i en liste.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Sætter det første element i en liste.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Sætter det sidste element i en liste.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Sætter et tilfældigt element i en liste.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Indsætter elementet på den angivne position i en liste.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Indsætter elementet i starten af en liste.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Føj elementet til slutningen af en liste.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Indsætter elementet tilfældigt i en liste.", - "LISTS_GET_SUBLIST_START_FROM_START": "hent underliste fra #", - "LISTS_GET_SUBLIST_START_FROM_END": "hent underliste fra # fra slutningen", - "LISTS_GET_SUBLIST_START_FIRST": "hent underliste fra første", - "LISTS_GET_SUBLIST_END_FROM_START": "til #", - "LISTS_GET_SUBLIST_END_FROM_END": "til # fra slutningen", - "LISTS_GET_SUBLIST_END_LAST": "til sidste", - "LISTS_GET_SUBLIST_TOOLTIP": "Opretter en kopi af den angivne del af en liste.", - "LISTS_SPLIT_LIST_FROM_TEXT": "lav tekst til liste", - "LISTS_SPLIT_TEXT_FROM_LIST": "lav liste til tekst", - "LISTS_SPLIT_WITH_DELIMITER": "med skilletegn", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Bryd tekst op i en liste af tekster med brud ved hvert skilletegn.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Saml en liste af tekster til én tekst, der er adskilt af et skilletegn.", - "VARIABLES_GET_TOOLTIP": "Returnerer værdien af denne variabel.", - "VARIABLES_GET_CREATE_SET": "Opret 'sæt %1'", - "VARIABLES_SET": "sæt %1 til %2", - "VARIABLES_SET_TOOLTIP": "Sætter denne variabel til at være lig med input.", - "VARIABLES_SET_CREATE_GET": "Opret 'hent %1'", - "PROCEDURES_DEFNORETURN_TITLE": "for at", - "PROCEDURES_DEFNORETURN_PROCEDURE": "gøre noget", - "PROCEDURES_BEFORE_PARAMS": "med:", - "PROCEDURES_CALL_BEFORE_PARAMS": "med:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Opretter en funktion der ikke har nogen returværdi.", - "PROCEDURES_DEFNORETURN_COMMENT": "Beskriv denne funktion...", - "PROCEDURES_DEFRETURN_RETURN": "returnér", - "PROCEDURES_DEFRETURN_TOOLTIP": "Opretter en funktion der har en returværdi.", - "PROCEDURES_ALLOW_STATEMENTS": "tillad erklæringer", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Advarsel: Denne funktion har dublerede parametre.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://da.wikipedia.org/wiki/Funktion_%28programmering%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Kør den brugerdefinerede funktion '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "https://da.wikipedia.org/wiki/Funktion_%28programmering%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Kør den brugerdefinerede funktion '%1' og brug dens returværdi.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "parametre", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Tilføje, fjerne eller ændre rækkefølgen af parametre til denne funktion.", - "PROCEDURES_MUTATORARG_TITLE": "parameternavn:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Tilføj en parameter til funktionen.", - "PROCEDURES_HIGHLIGHT_DEF": "Markér funktionsdefinitionen", - "PROCEDURES_CREATE_DO": "Opret '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Hvis en værdi er sand, så returnér en anden værdi.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Advarsel: Denne blok kan kun anvendes inden for en funktionsdefinition." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/de.json b/backend/_pv_1_3_5/static/blockly/msg/json/de.json deleted file mode 100755 index b227813f5..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/de.json +++ /dev/null @@ -1,350 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Metalhead64", - "M165437", - "Dan-yell", - "아라", - "Octycs", - "Cvanca", - "THINK" - ] - }, - "VARIABLES_DEFAULT_NAME": "etwas", - "TODAY": "Heute", - "DUPLICATE_BLOCK": "Kopieren", - "ADD_COMMENT": "Kommentar hinzufügen", - "REMOVE_COMMENT": "Kommentar entfernen", - "EXTERNAL_INPUTS": "externe Eingänge", - "INLINE_INPUTS": "interne Eingänge", - "DELETE_BLOCK": "Baustein löschen", - "DELETE_X_BLOCKS": "Baustein %1 löschen", - "DELETE_ALL_BLOCKS": "Alle %1 Bausteine löschen?", - "CLEAN_UP": "Bausteine aufräumen", - "COLLAPSE_BLOCK": "Baustein zusammenfalten", - "COLLAPSE_ALL": "Alle Bausteine zusammenfalten", - "EXPAND_BLOCK": "Baustein entfalten", - "EXPAND_ALL": "Alle Bausteine entfalten", - "DISABLE_BLOCK": "Baustein deaktivieren", - "ENABLE_BLOCK": "Baustein aktivieren", - "HELP": "Hilfe", - "UNDO": "Rückgängig", - "REDO": "Wiederholen", - "CHANGE_VALUE_TITLE": "Wert ändern:", - "RENAME_VARIABLE": "Variable umbenennen …", - "RENAME_VARIABLE_TITLE": "Alle \"%1\" Variablen umbenennen in:", - "NEW_VARIABLE": "Variable erstellen …", - "NEW_VARIABLE_TITLE": "Name der neuen Variable:", - "VARIABLE_ALREADY_EXISTS": "Eine Variable namens „%1“ ist bereits vorhanden.", - "DELETE_VARIABLE_CONFIRMATION": "%1 Verwendungen der Variable „%2“ löschen?", - "DELETE_VARIABLE": "Die Variable „%1“ löschen", - "COLOUR_PICKER_HELPURL": "https://de.wikipedia.org/wiki/Farbe", - "COLOUR_PICKER_TOOLTIP": "Erzeugt eine Farbe aus der Palette.", - "COLOUR_RANDOM_TITLE": "zufällige Farbe", - "COLOUR_RANDOM_TOOLTIP": "Erzeugt eine Farbe nach dem Zufallsprinzip.", - "COLOUR_RGB_HELPURL": "https://de.wikipedia.org/wiki/RGB-Farbraum", - "COLOUR_RGB_TITLE": "Farbe aus", - "COLOUR_RGB_RED": "rot", - "COLOUR_RGB_GREEN": "grün", - "COLOUR_RGB_BLUE": "blau", - "COLOUR_RGB_TOOLTIP": "Erzeugt eine Farbe mit selbst definierten Rot-, Grün- und Blauwerten. Alle Werte müssen zwischen 0 und 100 liegen.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "mische", - "COLOUR_BLEND_COLOUR1": "Farbe 1", - "COLOUR_BLEND_COLOUR2": "und Farbe 2", - "COLOUR_BLEND_RATIO": "im Verhältnis", - "COLOUR_BLEND_TOOLTIP": "Vermischt 2 Farben mit konfigurierbarem Farbverhältnis (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://de.wikipedia.org/wiki/For-Schleife", - "CONTROLS_REPEAT_TITLE": "wiederhole %1 mal:", - "CONTROLS_REPEAT_INPUT_DO": "mache", - "CONTROLS_REPEAT_TOOLTIP": "Eine Anweisung mehrfach ausführen.", - "CONTROLS_WHILEUNTIL_HELPURL": "https://de.wikipedia.org/wiki/Schleife_%28Programmierung%29", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "wiederhole solange", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "wiederhole bis", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Führt Anweisungen aus solange die Bedingung wahr ist.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Führt Anweisungen aus solange die Bedingung unwahr ist.", - "CONTROLS_FOR_HELPURL": "https://de.wikipedia.org/wiki/For-Schleife", - "CONTROLS_FOR_TOOLTIP": "Zählt die Variable \"%1\" von einem Startwert bis zu einem Endwert und führt für jeden Wert eine Anweisung aus.", - "CONTROLS_FOR_TITLE": "zähle %1 von %2 bis %3 in Schritten von %4:", - "CONTROLS_FOREACH_HELPURL": "https://de.wikipedia.org/wiki/For-Schleife", - "CONTROLS_FOREACH_TITLE": "für jeden Wert %1 aus der Liste %2", - "CONTROLS_FOREACH_TOOLTIP": "Führt eine Anweisung für jeden Wert in der Liste aus und setzt dabei die Variable \"%1\" auf den aktuellen Listenwert.", - "CONTROLS_FLOW_STATEMENTS_HELPURL": "https://de.wikipedia.org/wiki/Kontrollstruktur", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "die Schleife abbrechen", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "sofort mit nächstem Schleifendurchlauf fortfahren", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Die umgebende Schleife beenden.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Diese Anweisung abbrechen und mit dem nächsten Schleifendurchlauf fortfahren.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Warnung: Dieser Baustein kann nur in einer Schleife verwendet werden.", - "CONTROLS_IF_TOOLTIP_1": "Führt eine Anweisung aus, falls eine Bedingung wahr ist.", - "CONTROLS_IF_TOOLTIP_2": "Führt die erste Anweisung aus, falls eine Bedingung wahr ist. Führt ansonsten die zweite Anweisung aus.", - "CONTROLS_IF_TOOLTIP_3": "Führt die erste Anweisung aus, falls die erste Bedingung wahr ist. Führt ansonsten die zweite Anweisung aus, falls die zweite Bedingung wahr ist.", - "CONTROLS_IF_TOOLTIP_4": "Führe die erste Anweisung aus, falls die erste Bedingung wahr ist. Führt ansonsten die zweite Anweisung aus, falls die zweite Bedingung wahr ist. Führt die dritte Anweisung aus, falls keine der beiden Bedingungen wahr ist", - "CONTROLS_IF_MSG_IF": "falls", - "CONTROLS_IF_MSG_ELSEIF": "sonst falls", - "CONTROLS_IF_MSG_ELSE": "sonst", - "CONTROLS_IF_IF_TOOLTIP": "Hinzufügen, entfernen oder sortieren von Sektionen", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Eine weitere Bedingung hinzufügen.", - "CONTROLS_IF_ELSE_TOOLTIP": "Eine sonst-Bedingung hinzufügen. Führt eine Anweisung aus, falls keine Bedingung zutrifft.", - "LOGIC_COMPARE_HELPURL": "https://de.wikipedia.org/wiki/Vergleich_%28Zahlen%29", - "LOGIC_COMPARE_TOOLTIP_EQ": "Ist wahr, falls beide Werte gleich sind.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Ist wahr, falls beide Werte unterschiedlich sind.", - "LOGIC_COMPARE_TOOLTIP_LT": "Ist wahr, falls der erste Wert kleiner als der zweite Wert ist.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Ist wahr, falls der erste Wert kleiner als oder gleich groß wie der zweite Wert ist.", - "LOGIC_COMPARE_TOOLTIP_GT": "Ist wahr, falls der erste Wert größer als der zweite Wert ist.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Ist wahr, falls der erste Wert größer als oder gleich groß wie der zweite Wert ist.", - "LOGIC_OPERATION_TOOLTIP_AND": "Ist wahr, falls beide Werte wahr sind.", - "LOGIC_OPERATION_AND": "und", - "LOGIC_OPERATION_TOOLTIP_OR": "Ist wahr, falls einer der beiden Werte wahr ist.", - "LOGIC_OPERATION_OR": "oder", - "LOGIC_NEGATE_TITLE": "nicht %1", - "LOGIC_NEGATE_TOOLTIP": "Ist wahr, falls der Eingabewert unwahr ist. Ist unwahr, falls der Eingabewert wahr ist.", - "LOGIC_BOOLEAN_TRUE": "wahr", - "LOGIC_BOOLEAN_FALSE": "unwahr", - "LOGIC_BOOLEAN_TOOLTIP": "Ist entweder wahr oder unwahr", - "LOGIC_NULL_HELPURL": "https://de.wikipedia.org/wiki/Nullwert", - "LOGIC_NULL": "null", - "LOGIC_NULL_TOOLTIP": "Ist \"null\".", - "LOGIC_TERNARY_HELPURL": "https://de.wikipedia.org/wiki/%3F:#Auswahloperator", - "LOGIC_TERNARY_CONDITION": "prüfe", - "LOGIC_TERNARY_IF_TRUE": "falls wahr", - "LOGIC_TERNARY_IF_FALSE": "falls unwahr", - "LOGIC_TERNARY_TOOLTIP": "Überprüft eine Bedingung \"prüfe\". Falls die Bedingung wahr ist, wird der \"falls wahr\" Wert zurückgegeben, andernfalls der \"falls unwahr\" Wert", - "MATH_NUMBER_HELPURL": "https://de.wikipedia.org/wiki/Zahl", - "MATH_NUMBER_TOOLTIP": "Eine Zahl.", - "MATH_ARITHMETIC_HELPURL": "https://de.wikipedia.org/wiki/Grundrechenart", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Ist die Summe zweier Zahlen.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Ist die Differenz zweier Zahlen.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Ist das Produkt zweier Zahlen.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Ist der Quotient zweier Zahlen.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Ist die erste Zahl potenziert mit der zweiten Zahl.", - "MATH_SINGLE_HELPURL": "https://de.wikipedia.org/wiki/Quadratwurzel", - "MATH_SINGLE_OP_ROOT": "Quadratwurzel", - "MATH_SINGLE_TOOLTIP_ROOT": "Ist die Quadratwurzel einer Zahl.", - "MATH_SINGLE_OP_ABSOLUTE": "Betrag", - "MATH_SINGLE_TOOLTIP_ABS": "Ist der Betrag einer Zahl.", - "MATH_SINGLE_TOOLTIP_NEG": "Negiert eine Zahl.", - "MATH_SINGLE_TOOLTIP_LN": "Ist der natürliche Logarithmus einer Zahl.", - "MATH_SINGLE_TOOLTIP_LOG10": "Ist der dekadische Logarithmus einer Zahl.", - "MATH_SINGLE_TOOLTIP_EXP": "Ist Wert der Exponentialfunktion einer Zahl.", - "MATH_SINGLE_TOOLTIP_POW10": "Rechnet 10 hoch eine Zahl.", - "MATH_TRIG_HELPURL": "https://de.wikipedia.org/wiki/Trigonometrie", - "MATH_TRIG_TOOLTIP_SIN": "Ist der Sinus des Winkels.", - "MATH_TRIG_TOOLTIP_COS": "Ist der Kosinus des Winkels.", - "MATH_TRIG_TOOLTIP_TAN": "Ist der Tangens des Winkels.", - "MATH_TRIG_TOOLTIP_ASIN": "Ist der Arkussinus des Eingabewertes.", - "MATH_TRIG_TOOLTIP_ACOS": "Ist der Arkuskosinus des Eingabewertes.", - "MATH_TRIG_TOOLTIP_ATAN": "Ist der Arkustangens des Eingabewertes.", - "MATH_CONSTANT_HELPURL": "https://de.wikipedia.org/wiki/Mathematische_Konstante", - "MATH_CONSTANT_TOOLTIP": "Mathematische Konstanten wie: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…) oder ∞ (unendlich).", - "MATH_IS_EVEN": "ist gerade", - "MATH_IS_ODD": "ist ungerade", - "MATH_IS_PRIME": "ist eine Primzahl", - "MATH_IS_WHOLE": "ist eine ganze Zahl", - "MATH_IS_POSITIVE": "ist positiv", - "MATH_IS_NEGATIVE": "ist negativ", - "MATH_IS_DIVISIBLE_BY": "ist teilbar durch", - "MATH_IS_TOOLTIP": "Überprüft ob eine Zahl gerade, ungerade, eine Primzahl, ganzzahlig, positiv, negativ oder durch eine zweite Zahl teilbar ist. Gibt wahr oder unwahr zurück.", - "MATH_CHANGE_HELPURL": "https://de.wikipedia.org/wiki/Inkrement_und_Dekrement", - "MATH_CHANGE_TITLE": "erhöhe %1 um %2", - "MATH_CHANGE_TOOLTIP": "Addiert eine Zahl zu \"%1\".", - "MATH_ROUND_HELPURL": "https://de.wikipedia.org/wiki/Runden", - "MATH_ROUND_TOOLTIP": "Eine Zahl auf- oder abrunden.", - "MATH_ROUND_OPERATOR_ROUND": "runde", - "MATH_ROUND_OPERATOR_ROUNDUP": "runde auf", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "runde ab", - "MATH_ONLIST_HELPURL": "http://www.sysplus.ch/einstieg.php?links=menu&seite=4125&grad=Crash&prog=Excel", - "MATH_ONLIST_OPERATOR_SUM": "Summe über die Liste", - "MATH_ONLIST_TOOLTIP_SUM": "Ist die Summe aller Zahlen in einer Liste.", - "MATH_ONLIST_OPERATOR_MIN": "Minimalwert der Liste", - "MATH_ONLIST_TOOLTIP_MIN": "Ist die kleinste Zahl in einer Liste.", - "MATH_ONLIST_OPERATOR_MAX": "Maximalwert der Liste", - "MATH_ONLIST_TOOLTIP_MAX": "Ist die größte Zahl in einer Liste.", - "MATH_ONLIST_OPERATOR_AVERAGE": "Mittelwert der Liste", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Ist der Durchschnittswert aller Zahlen in einer Liste.", - "MATH_ONLIST_OPERATOR_MEDIAN": "Median der Liste", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Ist der Median aller Zahlen in einer Liste.", - "MATH_ONLIST_OPERATOR_MODE": "am häufigsten in der Liste", - "MATH_ONLIST_TOOLTIP_MODE": "Findet die Werte mit dem häufigstem Vorkommen in der Liste.", - "MATH_ONLIST_OPERATOR_STD_DEV": "Standardabweichung der Liste", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Ist die Standardabweichung aller Werte in der Liste.", - "MATH_ONLIST_OPERATOR_RANDOM": "Zufallswert aus der Liste", - "MATH_ONLIST_TOOLTIP_RANDOM": "Gibt einen zufälligen Wert aus der Liste zurück.", - "MATH_MODULO_HELPURL": "https://de.wikipedia.org/wiki/Modulo", - "MATH_MODULO_TITLE": "Rest von %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Der Rest nach einer Division.", - "MATH_CONSTRAIN_TITLE": "begrenze %1 zwischen %2 und %3", - "MATH_CONSTRAIN_TOOLTIP": "Begrenzt eine Zahl auf den Wertebereich zwischen zwei anderen Zahlen (inklusiv).", - "MATH_RANDOM_INT_HELPURL": "https://de.wikipedia.org/wiki/Zufallszahlen", - "MATH_RANDOM_INT_TITLE": "ganzzahlige Zufallszahl zwischen %1 und %2", - "MATH_RANDOM_INT_TOOLTIP": "Erzeugt eine ganzzahlige Zufallszahl zwischen zwei Zahlen (inklusiv).", - "MATH_RANDOM_FLOAT_HELPURL": "https://de.wikipedia.org/wiki/Zufallszahlen", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "Zufallszahl (0.0 - 1.0)", - "MATH_RANDOM_FLOAT_TOOLTIP": "Erzeugt eine Zufallszahl zwischen 0.0 (inklusiv) und 1.0 (exklusiv).", - "TEXT_TEXT_HELPURL": "https://de.wikipedia.org/wiki/Zeichenkette", - "TEXT_TEXT_TOOLTIP": "Ein Buchstabe, Text oder Satz.", - "TEXT_JOIN_HELPURL": "", - "TEXT_JOIN_TITLE_CREATEWITH": "erstelle Text aus", - "TEXT_JOIN_TOOLTIP": "Erstellt einen Text durch das Verbinden von mehreren Textelementen.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "verbinden", - "TEXT_CREATE_JOIN_TOOLTIP": "Hinzufügen, entfernen und sortieren von Elementen.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Ein Element zum Text hinzufügen.", - "TEXT_APPEND_TO": "an", - "TEXT_APPEND_APPENDTEXT": "Text anhängen", - "TEXT_APPEND_TOOLTIP": "Text an die Variable \"%1\" anhängen.", - "TEXT_LENGTH_TITLE": "Länge von %1", - "TEXT_LENGTH_TOOLTIP": "Die Anzahl von Zeichen in einem Text (inkl. Leerzeichen).", - "TEXT_ISEMPTY_TITLE": "%1 ist leer", - "TEXT_ISEMPTY_TOOLTIP": "Ist wahr, falls der Text keine Zeichen enthält ist.", - "TEXT_INDEXOF_HELPURL": "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm", - "TEXT_INDEXOF_TOOLTIP": "Findet das erste / letzte Auftreten eines Suchbegriffs in einem Text. Gibt die Position des Begriffs zurück oder %1 falls der Suchbegriff nicht gefunden wurde.", - "TEXT_INDEXOF_INPUT_INTEXT": "im Text", - "TEXT_INDEXOF_OPERATOR_FIRST": "suche erstes Auftreten des Begriffs", - "TEXT_INDEXOF_OPERATOR_LAST": "suche letztes Auftreten des Begriffs", - "TEXT_INDEXOF_TAIL": "", - "TEXT_CHARAT_HELPURL": "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm", - "TEXT_CHARAT_INPUT_INTEXT": "vom Text", - "TEXT_CHARAT_FROM_START": "nehme #ten Buchstaben", - "TEXT_CHARAT_FROM_END": "nehme #ten Buchstaben von hinten", - "TEXT_CHARAT_FIRST": "nehme ersten Buchstaben", - "TEXT_CHARAT_LAST": "nehme letzten Buchstaben", - "TEXT_CHARAT_RANDOM": "nehme zufälligen Buchstaben", - "TEXT_CHARAT_TAIL": "", - "TEXT_CHARAT_TOOLTIP": "Extrahiert einen Buchstaben von einer bestimmten Position.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Gibt den angegebenen Textabschnitt zurück.", - "TEXT_GET_SUBSTRING_HELPURL": "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "im Text", - "TEXT_GET_SUBSTRING_START_FROM_START": "nehme Teil ab #tem Buchstaben", - "TEXT_GET_SUBSTRING_START_FROM_END": "nehme Teil ab #tem Buchstaben von hinten", - "TEXT_GET_SUBSTRING_START_FIRST": "nehme Teil ab erstem Buchstaben", - "TEXT_GET_SUBSTRING_END_FROM_START": "bis zum #ten Buchstaben", - "TEXT_GET_SUBSTRING_END_FROM_END": "bis zum #ten Buchstaben von hinten", - "TEXT_GET_SUBSTRING_END_LAST": "bis zum letzten Buchstaben", - "TEXT_GET_SUBSTRING_TAIL": "", - "TEXT_CHANGECASE_TOOLTIP": "Wandelt Schreibweise von Texten um, in Großbuchstaben, Kleinbuchstaben oder den ersten Buchstaben jedes Wortes groß und die anderen klein.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "wandel um in GROSSBUCHSTABEN", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "wandel um in kleinbuchstaben", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "wandel um in Substantive", - "TEXT_TRIM_TOOLTIP": "Entfernt Leerzeichen vom Anfang und / oder Ende eines Textes.", - "TEXT_TRIM_OPERATOR_BOTH": "entferne Leerzeichen vom Anfang und vom Ende (links und rechts)", - "TEXT_TRIM_OPERATOR_LEFT": "entferne Leerzeichen vom Anfang (links)", - "TEXT_TRIM_OPERATOR_RIGHT": "entferne Leerzeichen vom Ende (rechts)", - "TEXT_PRINT_TITLE": "gib aus %1", - "TEXT_PRINT_TOOLTIP": "Gibt den Text aus.", - "TEXT_PROMPT_TYPE_TEXT": "frage nach Text mit Hinweis", - "TEXT_PROMPT_TYPE_NUMBER": "frage nach Zahl mit Hinweis", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Fragt den Benutzer nach einer Zahl.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Fragt den Benutzer nach einem Text.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "erzeuge eine leere Liste", - "LISTS_CREATE_EMPTY_TOOLTIP": "Erzeugt eine leere Liste ohne Inhalt.", - "LISTS_CREATE_WITH_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_CREATE_WITH_TOOLTIP": "Erzeugt eine Liste aus den angegebenen Elementen.", - "LISTS_CREATE_WITH_INPUT_WITH": "erzeuge Liste mit", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "Liste", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Hinzufügen, entfernen und sortieren von Elementen.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Ein Element zur Liste hinzufügen.", - "LISTS_REPEAT_HELPURL": "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm", - "LISTS_REPEAT_TOOLTIP": "Erzeugt eine Liste mit einer variablen Anzahl von Elementen", - "LISTS_REPEAT_TITLE": "erzeuge Liste mit %2 mal dem Element %1​", - "LISTS_LENGTH_TITLE": "Länge von %1", - "LISTS_LENGTH_TOOLTIP": "Die Anzahl von Elementen in der Liste.", - "LISTS_ISEMPTY_TITLE": "%1 ist leer", - "LISTS_ISEMPTY_TOOLTIP": "Ist wahr, falls die Liste leer ist.", - "LISTS_INLIST": "in der Liste", - "LISTS_INDEX_OF_HELPURL": "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm", - "LISTS_INDEX_OF_FIRST": "suche erstes Auftreten von", - "LISTS_INDEX_OF_LAST": "suche letztes Auftreten von", - "LISTS_INDEX_OF_TOOLTIP": "Sucht die Position (Index) eines Elementes in der Liste. Gibt %1 zurück, falls kein Element gefunden wurde.", - "LISTS_GET_INDEX_GET": "nimm", - "LISTS_GET_INDEX_GET_REMOVE": "nimm und entferne", - "LISTS_GET_INDEX_REMOVE": "entferne", - "LISTS_GET_INDEX_FROM_START": "#tes", - "LISTS_GET_INDEX_FROM_END": "#tes von hinten", - "LISTS_GET_INDEX_FIRST": "erstes", - "LISTS_GET_INDEX_LAST": "letztes", - "LISTS_GET_INDEX_RANDOM": "zufälliges", - "LISTS_GET_INDEX_TAIL": "", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 ist das erste Element.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 ist das letzte Element.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Extrahiert das Element an der angegebenen Position in der Liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Extrahiert das erste Element aus der Liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Extrahiert das letzte Element aus der Liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Extrahiert ein zufälliges Element aus der Liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Extrahiert und entfernt das Element an der angegebenen Position aus der Liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Extrahiert und entfernt das erste Element aus der Liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Extrahiert und entfernt das letzte Element aus der Liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Extrahiert und entfernt ein zufälliges Element aus der Liste.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Entfernt das Element an der angegebenen Position aus der Liste.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Entfernt das erste Element aus der Liste.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Entfernt das letzte Element aus der Liste.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Entfernt ein zufälliges Element aus der Liste.", - "LISTS_SET_INDEX_HELPURL": "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm", - "LISTS_SET_INDEX_SET": "setze für", - "LISTS_SET_INDEX_INSERT": "füge als", - "LISTS_SET_INDEX_INPUT_TO": "ein", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Setzt das Element an der angegebenen Position in der Liste.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Setzt das erste Element in der Liste.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Setzt das letzte Element in die Liste.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Setzt ein zufälliges Element in der Liste.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Fügt das Element an der angegebenen Position in die Liste ein.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Fügt das Element an den Anfang der Liste an.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Fügt das Element ans Ende der Liste an.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Fügt das Element zufällig in die Liste ein.", - "LISTS_GET_SUBLIST_HELPURL": "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm", - "LISTS_GET_SUBLIST_START_FROM_START": "erhalte Unterliste von #", - "LISTS_GET_SUBLIST_START_FROM_END": "erhalte Unterliste von # von hinten", - "LISTS_GET_SUBLIST_START_FIRST": "erhalte Unterliste vom Anfang", - "LISTS_GET_SUBLIST_END_FROM_START": "bis zu #", - "LISTS_GET_SUBLIST_END_FROM_END": "bis zu # von hinten", - "LISTS_GET_SUBLIST_END_LAST": "bis zum Ende", - "LISTS_GET_SUBLIST_TAIL": "", - "LISTS_GET_SUBLIST_TOOLTIP": "Erstellt eine Kopie mit dem angegebenen Abschnitt der Liste.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "%1 %2 %3 sortieren", - "LISTS_SORT_TOOLTIP": "Eine Kopie einer Liste sortieren.", - "LISTS_SORT_ORDER_ASCENDING": "aufsteigend", - "LISTS_SORT_ORDER_DESCENDING": "absteigend", - "LISTS_SORT_TYPE_NUMERIC": "numerisch", - "LISTS_SORT_TYPE_TEXT": "alphabetisch", - "LISTS_SORT_TYPE_IGNORECASE": "alphabetisch, Großschreibung ignorieren", - "LISTS_SPLIT_HELPURL": "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists", - "LISTS_SPLIT_LIST_FROM_TEXT": "Liste aus Text erstellen", - "LISTS_SPLIT_TEXT_FROM_LIST": "Text aus Liste erstellen", - "LISTS_SPLIT_WITH_DELIMITER": "mit Trennzeichen", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Text in eine Liste mit Texten aufteilen, unterbrochen bei jedem Trennzeichen.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Liste mit Texten in einen Text vereinen, getrennt durch ein Trennzeichen.", - "ORDINAL_NUMBER_SUFFIX": "", - "VARIABLES_GET_HELPURL": "https://de.wikipedia.org/wiki/Variable_%28Programmierung%29", - "VARIABLES_GET_TOOLTIP": "Gibt den Wert der Variable zurück.", - "VARIABLES_GET_CREATE_SET": "Erzeuge \"Schreibe %1\"", - "VARIABLES_SET_HELPURL": "https://de.wikipedia.org/wiki/Variable_%28Programmierung%29", - "VARIABLES_SET": "setze %1 auf %2", - "VARIABLES_SET_TOOLTIP": "Setzt den Wert einer Variable.", - "VARIABLES_SET_CREATE_GET": "Erzeuge \"Lese %1\"", - "PROCEDURES_DEFNORETURN_HELPURL": "https://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29", - "PROCEDURES_DEFNORETURN_TITLE": "", - "PROCEDURES_DEFNORETURN_PROCEDURE": "etwas tun", - "PROCEDURES_BEFORE_PARAMS": "mit:", - "PROCEDURES_CALL_BEFORE_PARAMS": "mit:", - "PROCEDURES_DEFNORETURN_DO": "", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Ein Funktionsblock ohne Rückgabewert.", - "PROCEDURES_DEFNORETURN_COMMENT": "Beschreibe diese Funktion …", - "PROCEDURES_DEFRETURN_HELPURL": "https://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29", - "PROCEDURES_DEFRETURN_RETURN": "gebe zurück", - "PROCEDURES_DEFRETURN_TOOLTIP": "Ein Funktionsblock mit Rückgabewert.", - "PROCEDURES_ALLOW_STATEMENTS": "Aussagen erlauben", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Warnung: dieser Funktionsblock hat zwei gleich benannte Parameter.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Rufe einen Funktionsblock ohne Rückgabewert auf.", - "PROCEDURES_CALLRETURN_HELPURL": "https://de.wikipedia.org/wiki/Prozedur_%28Programmierung%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Rufe einen Funktionsblock mit Rückgabewert auf.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "Parameter", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Die Eingaben zu dieser Funktion hinzufügen, entfernen oder neu anordnen.", - "PROCEDURES_MUTATORARG_TITLE": "Variable:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Eine Eingabe zur Funktion hinzufügen.", - "PROCEDURES_HIGHLIGHT_DEF": "Markiere Funktionsblock", - "PROCEDURES_CREATE_DO": "Erzeuge \"Aufruf %1\"", - "PROCEDURES_IFRETURN_TOOLTIP": "Gibt den zweiten Wert zurück und verlässt die Funktion, falls der erste Wert wahr ist.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Warnung: Dieser Block darf nur innerhalb eines Funktionsblocks genutzt werden." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/diq.json b/backend/_pv_1_3_5/static/blockly/msg/json/diq.json deleted file mode 100755 index 23f250d96..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/diq.json +++ /dev/null @@ -1,171 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Kumkumuk", - "Marmase", - "Mirzali" - ] - }, - "VARIABLES_DEFAULT_NAME": "unsur", - "TODAY": "Ewro", - "DUPLICATE_BLOCK": "Zewnc", - "ADD_COMMENT": "Tefsir cı ke", - "REMOVE_COMMENT": "Tefsiri Wedare", - "EXTERNAL_INPUTS": "Cıkewtışê xarıciy", - "INLINE_INPUTS": "Cıkerdışê xomiyani", - "DELETE_BLOCK": "Bloki bestere", - "DELETE_X_BLOCKS": "%1 blokan bestere", - "DELETE_ALL_BLOCKS": "Pêro %1 bloki besteriyê?", - "CLEAN_UP": "Blokan pak ke", - "COLLAPSE_BLOCK": "Bloki teng ke", - "COLLAPSE_ALL": "Blokan teng ke", - "EXPAND_BLOCK": "Bloki hera ke", - "EXPAND_ALL": "Blokan hera ke", - "DISABLE_BLOCK": "Çengi devre ra vec", - "ENABLE_BLOCK": "Bloki feal ke", - "HELP": "Peşti", - "UNDO": "Peyser biya", - "REDO": "Newe ke", - "CHANGE_VALUE_TITLE": "Erci bıvurne:", - "RENAME_VARIABLE": "Vuriyayey fına name ke...", - "NEW_VARIABLE": "Vuriyayeyo bıvıraz...", - "NEW_VARIABLE_TITLE": "Namey vuriyayeyê newi:", - "COLOUR_PICKER_HELPURL": "https://diq.wikipedia.org/wiki/Reng", - "COLOUR_RANDOM_TITLE": "rengo rastameye", - "COLOUR_RANDOM_TOOLTIP": "Tesadufi yu ren bıweçin", - "COLOUR_RGB_TITLE": "komponentên rengan", - "COLOUR_RGB_RED": "sur", - "COLOUR_RGB_GREEN": "kıho", - "COLOUR_RGB_BLUE": "kewe", - "COLOUR_BLEND_TITLE": "tewde", - "COLOUR_BLEND_COLOUR1": "reng 1", - "COLOUR_BLEND_COLOUR2": "reng 2", - "COLOUR_BLEND_RATIO": "nısbet", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "%1 fıni tekrar ke", - "CONTROLS_REPEAT_INPUT_DO": "bıke", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "Tekrar kerdış de", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "hend tekrar ke", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Yew erc raşto se yu beyanat bıd.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Yew erc xırabo se tay beyanati bıd", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "Çerxen ra vec", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "Gama bin da çerxeni ra dewam ke", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Öujtewada çerxeni ra bıvıci", - "CONTROLS_IF_MSG_IF": "se", - "CONTROLS_IF_MSG_ELSEIF": "niyose", - "CONTROLS_IF_MSG_ELSE": "çıniyose", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Bloq da if'i rê yu şert dekerê de.", - "LOGIC_OPERATION_AND": "û", - "LOGIC_OPERATION_OR": "ya zi", - "LOGIC_NEGATE_TITLE": "%1 niyo", - "LOGIC_BOOLEAN_TRUE": "raşt", - "LOGIC_BOOLEAN_FALSE": "ğelet", - "LOGIC_BOOLEAN_TOOLTIP": "Raşt yana çep erc dano", - "LOGIC_NULL": "veng", - "LOGIC_NULL_TOOLTIP": "Veng çarneno ra.", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "eke raşto", - "LOGIC_TERNARY_IF_FALSE": "eke ğeleto", - "LOGIC_TERNARY_TOOLTIP": "Şerta'test'i test keno. Eger ke şert raşta se erca 'raşt'i çarneno, çepo se erca 'çep' çarneno.", - "MATH_NUMBER_HELPURL": "https://diq.wikipedia.org/wiki/Numre", - "MATH_NUMBER_TOOLTIP": "Yew numre.", - "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/Aritmetik", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "karekok", - "MATH_SINGLE_OP_ABSOLUTE": "mutlaq", - "MATH_SINGLE_TOOLTIP_NEG": "Ena amorer nêravêrde deyne çerx ke.", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "Heryen sabitan ra yewi çerx ke:π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (bêsonp).", - "MATH_IS_EVEN": "zewnco", - "MATH_IS_ODD": "kıto", - "MATH_IS_PRIME": "bıngehên", - "MATH_IS_WHOLE": "tamo", - "MATH_IS_POSITIVE": "pozitifo", - "MATH_IS_NEGATIVE": "negatifo", - "MATH_IS_DIVISIBLE_BY": "Leteyêno", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "%2, keno %1 vurneno", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Yu amorer loğê cêri yana cori ke", - "MATH_ROUND_OPERATOR_ROUND": "gılor ke", - "MATH_ROUND_OPERATOR_ROUNDUP": "Loğê cori ke", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "Loğê cêri ke", - "MATH_ONLIST_OPERATOR_SUM": "koma liste", - "MATH_ONLIST_OPERATOR_MIN": "Tewr qıcê lista", - "MATH_ONLIST_OPERATOR_MAX": "Tewr gırdê lista", - "MATH_ONLIST_OPERATOR_AVERAGE": "Averacê lista", - "MATH_ONLIST_OPERATOR_MEDIAN": "Wertey lista", - "MATH_ONLIST_OPERATOR_MODE": "listey modi", - "MATH_ONLIST_OPERATOR_RANDOM": "Raştamaye objeya lista", - "MATH_ONLIST_TOOLTIP_RANDOM": "Liste ra raştamaye yew elementi çerx ke", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "%1 ÷ %2 ra menden", - "MATH_MODULO_TOOLTIP": "Dı amoran ra amora menden çerx ke", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "Raştamaye nimande amor", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "Yu herfa, satır yana çekuya metini", - "TEXT_JOIN_TITLE_CREATEWITH": "ya metin vıraz", - "TEXT_CREATE_JOIN_TITLE_JOIN": "gıre de", - "TEXT_APPEND_TO": "rê", - "TEXT_APPEND_APPENDTEXT": "Metin dek", - "TEXT_ISEMPTY_TITLE": "%1 vengo", - "TEXT_INDEXOF_INPUT_INTEXT": "metın de", - "TEXT_CHARAT_INPUT_INTEXT": "metın de", - "TEXT_CHARAT_FROM_START": "Herfa # bıgi", - "TEXT_CHARAT_FROM_END": "# ra tepya herfan bıgi", - "TEXT_CHARAT_FIRST": "Herfa sıfti bıgi", - "TEXT_CHARAT_LAST": "Herfa peyên bıgi", - "TEXT_CHARAT_RANDOM": "Raştamaye yu herf bıgi", - "TEXT_CHARAT_TOOLTIP": "Şınasnaye pozisyon de yu herfer çerğ keno", - "TEXT_GET_SUBSTRING_TOOLTIP": "Tay letey metini çerğ keno", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "metın de", - "TEXT_GET_SUBSTRING_START_FROM_START": "# ra substring gêno", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "HERFANÊ GIRDANA", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "Herfanê werdiyana", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "Ser herf gırd", - "LISTS_CREATE_EMPTY_TITLE": "lista venge vıraze", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "liste", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Yew nesne dekerê lista miyan", - "LISTS_LENGTH_TOOLTIP": "Derganiya yu lister dano.", - "LISTS_ISEMPTY_TITLE": "%1 vengo", - "LISTS_ISEMPTY_TOOLTIP": "Eger kı lista venga se raşt keno çerğ", - "LISTS_INLIST": "lista de", - "LISTS_INDEX_OF_FIRST": "Sıfte bıyayena cay obcey bıvin", - "LISTS_GET_INDEX_GET": "bıgê", - "LISTS_GET_INDEX_GET_REMOVE": "Bıgi u wedarne", - "LISTS_GET_INDEX_REMOVE": "wedare", - "LISTS_GET_INDEX_FROM_END": "# peyniye ra", - "LISTS_GET_INDEX_FIRST": "verên", - "LISTS_GET_INDEX_LAST": "peyên", - "LISTS_GET_INDEX_RANDOM": "raştameye", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 objeyo sıfteyên o", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 objeyo peyên o", - "LISTS_SET_INDEX_SET": "ca ke", - "LISTS_SET_INDEX_INSERT": "De fi", - "LISTS_SET_INDEX_INPUT_TO": "zey", - "LISTS_GET_SUBLIST_END_FROM_START": "#'ya", - "LISTS_GET_SUBLIST_END_FROM_END": "Peyni # ra hetana", - "LISTS_GET_SUBLIST_END_LAST": "Hetana pey", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "Kılm %1 %2 %3", - "LISTS_SORT_ORDER_ASCENDING": "zeydıyen", - "LISTS_SORT_ORDER_DESCENDING": "Kemeyen", - "LISTS_SORT_TYPE_NUMERIC": "Amoriyal", - "LISTS_SORT_TYPE_TEXT": "Alfabetik", - "LISTS_SPLIT_WITH_DELIMITER": "Hududoxi ya", - "VARIABLES_SET_CREATE_GET": "'get %1' vıraz", - "PROCEDURES_DEFNORETURN_TITLE": "rê", - "PROCEDURES_DEFNORETURN_PROCEDURE": "Çıyê bık", - "PROCEDURES_BEFORE_PARAMS": "ebe:", - "PROCEDURES_CALL_BEFORE_PARAMS": "ebe:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Yew fonksiyono çap nêdate vırazeno", - "PROCEDURES_DEFNORETURN_COMMENT": "Nê fonksiyoni beyan ke...", - "PROCEDURES_DEFRETURN_RETURN": "peyser biya", - "PROCEDURES_DEFRETURN_TOOLTIP": "Yew fonksiyono çap daye vırazeno", - "PROCEDURES_ALLOW_STATEMENTS": "Çıyan rê mısafe bıd", - "PROCEDURES_MUTATORCONTAINER_TITLE": "cıkewtışi", - "PROCEDURES_MUTATORARG_TITLE": "nameyê cıkewtışi:", - "PROCEDURES_CREATE_DO": "'%1' vıraze" -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/el.json b/backend/_pv_1_3_5/static/blockly/msg/json/el.json deleted file mode 100755 index 5e6f1a0f3..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/el.json +++ /dev/null @@ -1,336 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Azountas", - "Espertus", - "Evropi", - "Namatreasure", - "Sfyrakis", - "Glavkos", - "Gchr", - "아라", - "Geraki", - "Ανώνυμος Βικιπαιδιστής" - ] - }, - "VARIABLES_DEFAULT_NAME": "αντικείμενο", - "TODAY": "Σήμερα", - "DUPLICATE_BLOCK": "Διπλότυπο", - "ADD_COMMENT": "Πρόσθεσε Το Σχόλιο", - "REMOVE_COMMENT": "Αφαίρεσε Το Σχόλιο", - "EXTERNAL_INPUTS": "Εξωτερικές Είσοδοι", - "INLINE_INPUTS": "Εσωτερικές Είσοδοι", - "DELETE_BLOCK": "Διέγραψε Το Μπλοκ", - "DELETE_X_BLOCKS": "Διέγραψε %1 Μπλοκ", - "DELETE_ALL_BLOCKS": "Να διαγραφούν και τα %1 μπλοκ?", - "COLLAPSE_BLOCK": "Σύμπτυξε Το Μπλοκ", - "COLLAPSE_ALL": "Σύμπτυξτε Όλα Τα Μπλοκ", - "EXPAND_BLOCK": "Επέκτεινε Το Μπλοκ", - "EXPAND_ALL": "Επέκτεινε Όλα Τα Μπλοκ", - "DISABLE_BLOCK": "Απενεργοποίησε Το Μπλοκ", - "ENABLE_BLOCK": "Ενεργοποίησε Το Μπλοκ", - "HELP": "Βοήθεια", - "UNDO": "Αναίρεση", - "REDO": "Ακύρωση αναίρεσης", - "CHANGE_VALUE_TITLE": "Άλλαξε την τιμή:", - "RENAME_VARIABLE": "Μετονόμασε τη μεταβλητή...", - "RENAME_VARIABLE_TITLE": "Μετονόμασε όλες τις μεταβλητές «%1» σε:", - "NEW_VARIABLE": "Νέα μεταβλητή...", - "NEW_VARIABLE_TITLE": "Νέο όνομα μεταβλητής:", - "COLOUR_PICKER_HELPURL": "https://el.wikipedia.org/wiki/%CE%A7%CF%81%CF%8E%CE%BC%CE%B1", - "COLOUR_PICKER_TOOLTIP": "Επιτρέπει επιλογή χρώματος από την παλέτα.", - "COLOUR_RANDOM_TITLE": "τυχαίο χρώμα", - "COLOUR_RANDOM_TOOLTIP": "Επιλέγει χρώμα τυχαία.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "χρώμα με", - "COLOUR_RGB_RED": "κόκκινο", - "COLOUR_RGB_GREEN": "πράσινο", - "COLOUR_RGB_BLUE": "μπλε", - "COLOUR_RGB_TOOLTIP": "Δημιουργεί χρώμα με το συγκεκριμένο ποσό του κόκκινου, πράσινου και μπλε που ορίζεις. Όλες οι τιμές πρέπει να είναι μεταξύ 0 και 100.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "μείγμα", - "COLOUR_BLEND_COLOUR1": "χρώμα 1", - "COLOUR_BLEND_COLOUR2": "χρώμα 2", - "COLOUR_BLEND_RATIO": "αναλογία", - "COLOUR_BLEND_TOOLTIP": "Συνδυάζει δύο χρώματα μαζί με μια δεδομένη αναλογία (0.0 - 1,0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "επανάλαβε %1 φορές", - "CONTROLS_REPEAT_INPUT_DO": "κάνε", - "CONTROLS_REPEAT_TOOLTIP": "Εκτελεί κάποιες εντολές αρκετές φορές.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "επανάλαβε ενώ", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "επανάλαβε μέχρι", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Ενόσω μια τιμή είναι αληθής, τότε εκτελεί κάποιες εντολές.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Ενόσω μια τιμή είναι ψευδής, τότε εκτελεί κάποιες εντολές.", - "CONTROLS_FOR_HELPURL": "Blockly", - "CONTROLS_FOR_TOOLTIP": "Η μεταβλητή «%1» παίρνει τιμές ξεκινώντας από τον αριθμό έναρξης μέχρι τον αριθμό τέλους αυξάνοντας κάθε φορά με το καθορισμένο βήμα και εκτελώντας το καθορισμένο μπλοκ.", - "CONTROLS_FOR_TITLE": "μέτρησε με %1 από το %2 έως το %3 ανά %4", - "CONTROLS_FOREACH_TITLE": "για κάθε στοιχείο %1 στη λίστα %2", - "CONTROLS_FOREACH_TOOLTIP": "Για κάθε στοιχείο σε μια λίστα, ορίζει τη μεταβλητή «%1» στο στοιχείο και, στη συνέχεια, εκτελεί κάποιες εντολές.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "φεύγει από το μπλοκ επαναλήψεως", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "συνέχισε με την επόμενη επανάληψη του μπλοκ επαναλήψεως", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Ξεφεύγει (βγαίνει έξω) από την επανάληψη.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Παραλείπει το υπόλοιπο τμήμα αυτού του μπλοκ επαναλήψεως, και συνεχίζει με την επόμενη επανάληψη.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Προειδοποίηση: Αυτό το μπλοκ μπορεί να χρησιμοποιηθεί μόνο μέσα σε μια επανάληψη.", - "CONTROLS_IF_TOOLTIP_1": "Αν μια τιμή είναι αληθής, τότε εκτελεί κάποιες εντολές.", - "CONTROLS_IF_TOOLTIP_2": "Αν μια τιμή είναι αληθής, τότε εκτελεί το πρώτο τμήμα εντολών. Διαφορετικά, εκτελεί το δεύτερο τμήμα εντολών.", - "CONTROLS_IF_TOOLTIP_3": "Αν η πρώτη τιμή είναι αληθής, τότε εκτελεί το πρώτο τμήμα εντολών. Διαφορετικά, αν η δεύτερη τιμή είναι αληθής, εκτελεί το δεύτερο μπλοκ εντολών.", - "CONTROLS_IF_TOOLTIP_4": "Αν η πρώτη τιμή είναι αληθής, τότε εκτελεί το πρώτο τμήμα εντολών. Διαφορετικά, αν η δεύτερη τιμή είναι αληθής, εκτελεί το δεύτερο τμήμα εντολών. Αν καμία από τις τιμές δεν είναι αληθής, εκτελεί το τελευταίο τμήμα εντολών.", - "CONTROLS_IF_MSG_IF": "εάν", - "CONTROLS_IF_MSG_ELSEIF": "εναλλακτικά εάν", - "CONTROLS_IF_MSG_ELSE": "αλλιώς", - "CONTROLS_IF_IF_TOOLTIP": "Προσθέτει, αφαιρεί ή αναδιατάσσει τα τμήματα για να αναδιαμορφώσει αυτό το μπλοκ «εάν».", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Πρόσθετει μια κατάσταση/συνθήκη στο μπλοκ «εάν».", - "CONTROLS_IF_ELSE_TOOLTIP": "Προσθέτει μια τελική κατάσταση/συνθήκη, που πιάνει όλες τις άλλες περιπτώσεις, στο μπλοκ «εάν».", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Επιστρέφει αληθής αν και οι δύο είσοδοι είναι ίσες μεταξύ τους.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Επιστρέφει αληθής αν και οι δύο είσοδοι δεν είναι ίσες μεταξύ τους.", - "LOGIC_COMPARE_TOOLTIP_LT": "Επιστρέφει αληθής αν η πρώτη είσοδος είναι μικρότερη από τη δεύτερη είσοδο.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Επιστρέφει αληθής αν η πρώτη είσοδος είναι μικρότερη από ή ίση με τη δεύτερη είσοδο.", - "LOGIC_COMPARE_TOOLTIP_GT": "Επιστρέφει αληθής αν η πρώτη είσοδος είναι μεγαλύτερη από τη δεύτερη είσοδο.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Επιστρέφει αληθής αν η πρώτη είσοδος είναι μικρότερη ή ίση με τη δεύτερη είσοδο.", - "LOGIC_OPERATION_TOOLTIP_AND": "Επιστρέφει αληθής αν και οι δύο είσοδοι είναι αληθής.", - "LOGIC_OPERATION_AND": "και", - "LOGIC_OPERATION_TOOLTIP_OR": "Επιστρέφει αληθής αν τουλάχιστον μια από τις εισόδους είναι αληθής.", - "LOGIC_OPERATION_OR": "ή", - "LOGIC_NEGATE_TITLE": "όχι %1", - "LOGIC_NEGATE_TOOLTIP": "Επιστρέφει αληθής αν η είσοδος είναι ψευδής. Επιστρέφει ψευδής αν η είσοδος είναι αληθής.", - "LOGIC_BOOLEAN_TRUE": "αληθής", - "LOGIC_BOOLEAN_FALSE": "ψευδής", - "LOGIC_BOOLEAN_TOOLTIP": "Επιστρέφει είτε αληθής είτε ψευδής.", - "LOGIC_NULL_HELPURL": "https://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "κενό", - "LOGIC_NULL_TOOLTIP": "Επιστρέφει κενό.", - "LOGIC_TERNARY_HELPURL": "https://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "έλεγχος", - "LOGIC_TERNARY_IF_TRUE": "εάν είναι αληθής", - "LOGIC_TERNARY_IF_FALSE": "εάν είναι ψευδής", - "LOGIC_TERNARY_TOOLTIP": "Ελέγχει την κατάσταση/συνθήκη στον «έλεγχο». Αν η κατάσταση/συνθήκη είναι αληθής, επιστρέφει την τιμή «εάν αληθής», διαφορετικά επιστρέφει την τιμή «εάν ψευδής».", - "MATH_NUMBER_HELPURL": "https://el.wikipedia.org/wiki/%CE%91%CF%81%CE%B9%CE%B8%CE%BC%CF%8C%CF%82", - "MATH_NUMBER_TOOLTIP": "Ένας αριθμός.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^ ύψωση σε δύναμη", - "MATH_TRIG_SIN": "ημ", - "MATH_TRIG_COS": "συν", - "MATH_TRIG_TAN": "εφ", - "MATH_TRIG_ASIN": "asin", - "MATH_TRIG_ACOS": "acos", - "MATH_TRIG_ATAN": "atan", - "MATH_ARITHMETIC_HELPURL": "https://el.wikipedia.org/wiki/%CE%91%CF%81%CE%B9%CE%B8%CE%BC%CE%B7%CF%84%CE%B9%CE%BA%CE%AE", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Επιστρέφει το άθροισμα των δύο αριθμών.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Επιστρέφει τη διαφορά των δύο αριθμών.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Επιστρέφει το γινόμενο των δύο αριθμών.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Επιστρέφει το πηλίκο των δύο αριθμών.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Επιστρέφει τον πρώτο αριθμό υψωμένο στη δύναμη του δεύτερου αριθμού.", - "MATH_SINGLE_HELPURL": "https://el.wikipedia.org/wiki/%CE%A4%CE%B5%CF%84%CF%81%CE%B1%CE%B3%CF%89%CE%BD%CE%B9%CE%BA%CE%AE_%CF%81%CE%AF%CE%B6%CE%B1", - "MATH_SINGLE_OP_ROOT": "τετραγωνική ρίζα", - "MATH_SINGLE_TOOLTIP_ROOT": "Επιστρέφει την τετραγωνική ρίζα ενός αριθμού.", - "MATH_SINGLE_OP_ABSOLUTE": "απόλυτη", - "MATH_SINGLE_TOOLTIP_ABS": "Επιστρέφει την απόλυτη τιμή ενός αριθμού.", - "MATH_SINGLE_TOOLTIP_NEG": "Επιστρέφει την αρνητική ενός αριθμού.", - "MATH_SINGLE_TOOLTIP_LN": "Επιστρέφει τον νεπέρειο λογάριθμο ενός αριθμού.", - "MATH_SINGLE_TOOLTIP_LOG10": "Επιστρέφει τον λογάριθμο με βάση το 10 ενός αριθμού.", - "MATH_SINGLE_TOOLTIP_EXP": "Επιστρέφει το e υψωμένο στη δύναμη ενός αριθμού.", - "MATH_SINGLE_TOOLTIP_POW10": "Επιστρέφει το 10 υψωμένο στη δύναμη ενός αριθμού.", - "MATH_TRIG_HELPURL": "https://el.wikipedia.org/wiki/%CE%A4%CF%81%CE%B9%CE%B3%CF%89%CE%BD%CE%BF%CE%BC%CE%B5%CF%84%CF%81%CE%B9%CE%BA%CE%AE_%CF%83%CF%85%CE%BD%CE%AC%CF%81%CF%84%CE%B7%CF%83%CE%B7", - "MATH_TRIG_TOOLTIP_SIN": "Επιστρέφει το ημίτονο ενός βαθμού (όχι ακτινίου).", - "MATH_TRIG_TOOLTIP_COS": "Επιστρέφει το συνημίτονο ενός βαθμού (όχι ακτινίου).", - "MATH_TRIG_TOOLTIP_TAN": "Επιστρέφει την εφαπτομένη ενός βαθμού (όχι ακτινίου).", - "MATH_TRIG_TOOLTIP_ASIN": "Επιστρέφει το τόξο ημίτονου ενός αριθμού.", - "MATH_TRIG_TOOLTIP_ACOS": "Επιστρέφει το τόξο συνημίτονου ενός αριθμού.", - "MATH_TRIG_TOOLTIP_ATAN": "Επιστρέφει το τόξο εφαπτομένης ενός αριθμού.", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "Επιστρέφει μία από τις κοινές σταθερές: π (3.141...), e (2.718...), φ (1.618...), sqrt(2) (1.414...), sqrt(½) (0.707...), ή ∞ (άπειρο).", - "MATH_IS_EVEN": "είναι άρτιος", - "MATH_IS_ODD": "είναι περιττός", - "MATH_IS_PRIME": "είναι πρώτος", - "MATH_IS_WHOLE": "είναι ακέραιος", - "MATH_IS_POSITIVE": "είναι θετικός", - "MATH_IS_NEGATIVE": "είναι αρνητικός", - "MATH_IS_DIVISIBLE_BY": "είναι διαιρετός από το", - "MATH_IS_TOOLTIP": "Ελέγχει αν ένας αριθμός είναι άρτιος, περιττός, πρώτος, ακέραιος, θετικός, αρνητικός, ή αν είναι διαιρετός από έναν ορισμένο αριθμό. Επιστρέφει αληθής ή ψευδής.", - "MATH_CHANGE_HELPURL": "https://el.wikipedia.org/wiki/%CE%A0%CF%81%CF%8C%CF%83%CE%B8%CE%B5%CF%83%CE%B7", - "MATH_CHANGE_TITLE": "άλλαξε %1 από %2", - "MATH_CHANGE_TOOLTIP": "Προσθέτει έναν αριθμό στη μεταβλητή «%1».", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Στρογγυλοποιεί έναν αριθμό προς τα πάνω ή προς τα κάτω.", - "MATH_ROUND_OPERATOR_ROUND": "στρογγυλοποίησε", - "MATH_ROUND_OPERATOR_ROUNDUP": "στρογγυλοποίησε προς τα πάνω", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "στρογγυλοποίησε προς τα κάτω", - "MATH_ONLIST_OPERATOR_SUM": "άθροισμα λίστας", - "MATH_ONLIST_TOOLTIP_SUM": "Επιστρέφει το άθροισμα όλων των αριθμών στη λίστα.", - "MATH_ONLIST_OPERATOR_MIN": "μικρότερος λίστας", - "MATH_ONLIST_TOOLTIP_MIN": "Επιστρέφει τον μικρότερο αριθμό στη λίστα.", - "MATH_ONLIST_OPERATOR_MAX": "μεγαλύτερος λίστας", - "MATH_ONLIST_TOOLTIP_MAX": "Επιστρέφει τον μεγαλύτερο αριθμό στη λίστα.", - "MATH_ONLIST_OPERATOR_AVERAGE": "μέσος όρος λίστας", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Επιστρέφει τον αριθμητικό μέσο όρο από τις αριθμητικές τιμές στη λίστα.", - "MATH_ONLIST_OPERATOR_MEDIAN": "διάμεσος λίστας", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Επιστρέφει τον διάμεσο της λίστας.", - "MATH_ONLIST_OPERATOR_MODE": "μορφές λίστας", - "MATH_ONLIST_TOOLTIP_MODE": "Επιστρέφει μια λίστα με τα πιο κοινά στοιχεία στη λίστα.", - "MATH_ONLIST_OPERATOR_STD_DEV": "τυπική απόκλιση λίστας", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Επιστρέφει την τυπική απόκλιση της λίστας.", - "MATH_ONLIST_OPERATOR_RANDOM": "τυχαίο στοιχείο λίστας", - "MATH_ONLIST_TOOLTIP_RANDOM": "Επιστρέφει ένα τυχαίο στοιχείο από τη λίστα.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "υπόλοιπο της %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Επιστρέφει το υπόλοιπο της διαίρεσης των δύο αριθμών.", - "MATH_CONSTRAIN_TITLE": "περιόρισε %1 χαμηλή %2 υψηλή %3", - "MATH_CONSTRAIN_TOOLTIP": "Περιορίζει έναν αριθμό μεταξύ των προβλεπόμενων ορίων (χωρίς αποκλεισμούς).", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "τυχαίος ακέραιος από το %1 έως το %2", - "MATH_RANDOM_INT_TOOLTIP": "Επιστρέφει έναν τυχαίο ακέραιο αριθμό μεταξύ δύο συγκεκριμένων ορίων (εντός - συμπεριλαμβανομένων και των ακραίων τιμών).", - "MATH_RANDOM_FLOAT_HELPURL": "https://el.wikipedia.org/wiki/%CE%93%CE%B5%CE%BD%CE%BD%CE%AE%CF%84%CF%81%CE%B9%CE%B1_%CE%A4%CF%85%CF%87%CE%B1%CE%AF%CF%89%CE%BD_%CE%91%CF%81%CE%B9%CE%B8%CE%BC%CF%8E%CE%BD", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "τυχαίο κλάσμα", - "MATH_RANDOM_FLOAT_TOOLTIP": "Επιστρέψει ένα τυχαία κλάσμα μεταξύ 0,0 (κλειστό) και 1,0 (ανοικτό).", - "TEXT_TEXT_HELPURL": "https://el.wikipedia.org/wiki/%CE%A3%CF%85%CE%BC%CE%B2%CE%BF%CE%BB%CE%BF%CF%83%CE%B5%CE%B9%CF%81%CE%AC", - "TEXT_TEXT_TOOLTIP": "Ένα γράμμα, μια λέξη ή μια γραμμή κειμένου.", - "TEXT_JOIN_TITLE_CREATEWITH": "δημιούργησε κείμενο με", - "TEXT_JOIN_TOOLTIP": "Δημιουργεί ένα κομμάτι κειμένου ενώνοντας έναν απεριόριστο αριθμό αντικειμένων.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "ένωσε", - "TEXT_CREATE_JOIN_TOOLTIP": "Προσθέτει, αφαιρεί ή αναδιατάσσει τους τομείς για να αναδιαμορφώσει αυτό το μπλοκ κειμένου.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Προσθέτει ένα στοιχείο στο κείμενο.", - "TEXT_APPEND_TO": "έως", - "TEXT_APPEND_APPENDTEXT": "ανάθεσε κείμενο", - "TEXT_APPEND_TOOLTIP": "Αναθέτει κείμενο στη μεταβλητή «%1».", - "TEXT_LENGTH_TITLE": "το μήκος του %1", - "TEXT_LENGTH_TOOLTIP": "Επιστρέφει το πλήθος των γραμμάτων (συμπεριλαμβανομένων και των κενών διαστημάτων) στο παρεχόμενο κείμενο.", - "TEXT_ISEMPTY_TITLE": "το %1 είναι κενό", - "TEXT_ISEMPTY_TOOLTIP": "Επιστρέφει αληθής αν το παρεχόμενο κείμενο είναι κενό.", - "TEXT_INDEXOF_TOOLTIP": "Επιστρέφει τον δείκτη της πρώτης/τελευταίας εμφάνισης του πρώτου κειμένου στο δεύτερο κείμενο. Επιστρέφει τιμή %1, αν δε βρει το κείμενο.", - "TEXT_INDEXOF_INPUT_INTEXT": "στο κείμενο", - "TEXT_INDEXOF_OPERATOR_FIRST": "βρες την πρώτη εμφάνιση του κειμένου", - "TEXT_INDEXOF_OPERATOR_LAST": "βρες την τελευταία εμφάνιση του κειμένου", - "TEXT_CHARAT_INPUT_INTEXT": "στο κείμενο", - "TEXT_CHARAT_FROM_START": "πάρε το γράμμα #", - "TEXT_CHARAT_FROM_END": "πάρε το γράμμα # από το τέλος", - "TEXT_CHARAT_FIRST": "πάρε το πρώτο γράμμα", - "TEXT_CHARAT_LAST": "πάρε το τελευταίο γράμμα", - "TEXT_CHARAT_RANDOM": "πάρε τυχαίο γράμμα", - "TEXT_CHARAT_TOOLTIP": "Επιστρέφει το γράμμα στην καθορισμένη θέση.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Επιστρέφει ένα συγκεκριμένο τμήμα του κειμένου.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "στο κείμενο", - "TEXT_GET_SUBSTRING_START_FROM_START": "πάρε τη δευτερεύουσα συμβολοσειρά από το # γράμμα", - "TEXT_GET_SUBSTRING_START_FROM_END": "πάρε τη δευτερεύουσα συμβολοσειρά από το # γράμμα από το τέλος", - "TEXT_GET_SUBSTRING_START_FIRST": "πάρε τη δευτερεύουσα συμβολοσειρά από το πρώτο γράμμα", - "TEXT_GET_SUBSTRING_END_FROM_START": "μέχρι το # γράμμα", - "TEXT_GET_SUBSTRING_END_FROM_END": "μέχρι το # γράμμα από το τέλος", - "TEXT_GET_SUBSTRING_END_LAST": "μέχρι το τελευταίο γράμμα", - "TEXT_CHANGECASE_TOOLTIP": "Επιστρέφει ένα αντίγραφο του κειμένου σε διαφορετική μορφή γραμμάτων.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "σε ΚΕΦΑΛΑΙΑ", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "σε πεζά", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "σε Λέξεις Με Πρώτα Κεφαλαία", - "TEXT_TRIM_TOOLTIP": "Επιστρέφει ένα αντίγραφο του κειμένου με αφαιρεμένα τα κενά από το ένα ή και τα δύο άκρα.", - "TEXT_TRIM_OPERATOR_BOTH": "περίκοψε τα κενά και από τις δυο πλευρές του", - "TEXT_TRIM_OPERATOR_LEFT": "περίκοψε τα κενά από την αριστερή πλευρά του", - "TEXT_TRIM_OPERATOR_RIGHT": "περίκοψε τα κενά από την δεξιά πλευρά του", - "TEXT_PRINT_TITLE": "εκτύπωσε %1", - "TEXT_PRINT_TOOLTIP": "Εκτυπώνει το καθορισμένο κείμενο, αριθμό ή άλλη τιμή.", - "TEXT_PROMPT_TYPE_TEXT": "πρότρεψε με μήνυμα για να δοθεί κείμενο", - "TEXT_PROMPT_TYPE_NUMBER": "πρότρεψε με μήνυμα για να δοθεί αριθμός", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Δημιουργεί προτροπή για τον χρήστη για να δώσει ένα αριθμό.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Δημιουργεί προτροπή για το χρήστη για να δώσει κάποιο κείμενο.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "δημιούργησε κενή λίστα", - "LISTS_CREATE_EMPTY_TOOLTIP": "Επιστρέφει μια λίστα, με μήκος 0, η οποία δεν περιέχει εγγραφές δεδομένων", - "LISTS_CREATE_WITH_TOOLTIP": "Δημιουργεί λίστα με οποιονδήποτε αριθμό αντικειμένων.", - "LISTS_CREATE_WITH_INPUT_WITH": "δημιούργησε λίστα με", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "λίστα", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Προσθέτει, αφαιρεί ή αναδιατάσσει τα τμήματα για να αναδιαμορφώσει αυτό το μπλοκ λίστας.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Προσθέτει αντικείμενο στη λίστα.", - "LISTS_REPEAT_HELPURL": "Blockly", - "LISTS_REPEAT_TOOLTIP": "Δημιουργεί μια λίστα που αποτελείται από την δεδομένη τιμή που επαναλαμβάνεται για συγκεκριμένο αριθμό επαναλήψεων.", - "LISTS_REPEAT_TITLE": "δημιούργησε λίστα με το στοιχείο %1 να επαναλαμβάνεται %2 φορές", - "LISTS_LENGTH_HELPURL": "Blockly", - "LISTS_LENGTH_TITLE": "το μήκος του %1", - "LISTS_LENGTH_TOOLTIP": "Επιστρέφει το μήκος μιας λίστας.", - "LISTS_ISEMPTY_TITLE": "το %1 είναι κενό", - "LISTS_ISEMPTY_TOOLTIP": "Επιστρέφει αληθής αν η λίστα είναι κενή.", - "LISTS_INLIST": "στη λίστα", - "LISTS_INDEX_OF_HELPURL": "Blockly", - "LISTS_INDEX_OF_FIRST": "βρες την πρώτη εμφάνιση του στοιχείου", - "LISTS_INDEX_OF_LAST": "βρες την τελευταία εμφάνιση του στοιχείου", - "LISTS_INDEX_OF_TOOLTIP": "Επιστρέφει τον δείκτη της πρώτης/τελευταίας εμφάνισης του στοιχείου στη λίστα. Επιστρέφει τιμή %1, αν το στοιχείο δεν βρεθεί.", - "LISTS_GET_INDEX_GET": "πάρε", - "LISTS_GET_INDEX_GET_REMOVE": "πάρε και αφαίρεσε", - "LISTS_GET_INDEX_REMOVE": "αφαίρεσε", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# από το τέλος", - "LISTS_GET_INDEX_FIRST": "πρώτο", - "LISTS_GET_INDEX_LAST": "τελευταίο", - "LISTS_GET_INDEX_RANDOM": "τυχαίο", - "LISTS_INDEX_FROM_START_TOOLTIP": "Το %1 είναι το πρώτο στοιχείο.", - "LISTS_INDEX_FROM_END_TOOLTIP": "Το %1 είναι το τελευταίο στοιχείο.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Επιστρέφει το στοιχείο στην καθορισμένη θέση σε μια λίστα.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Επιστρέφει το πρώτο στοιχείο σε μια λίστα.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Επιστρέφει το τελευταίο στοιχείο σε μια λίστα.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Επιστρέφει ένα τυχαίο στοιχείο σε μια λίστα.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Καταργεί και επιστρέφει το στοιχείο στην καθορισμένη θέση σε μια λίστα.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Καταργεί και επιστρέφει το πρώτο στοιχείο σε μια λίστα.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Καταργεί και επιστρέφει το τελευταίο στοιχείο σε μια λίστα.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Καταργεί και επιστρέφει ένα τυχαίο στοιχείο σε μια λίστα.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Καταργεί το στοιχείο στην καθορισμένη θέση σε μια λίστα.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Καταργεί το πρώτο στοιχείο σε μια λίστα.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Καταργεί το τελευταίο στοιχείο σε μια λίστα.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Καταργεί ένα τυχαίο στοιχείο σε μια λίστα.", - "LISTS_SET_INDEX_SET": "όρισε", - "LISTS_SET_INDEX_INSERT": "είσαγε στο", - "LISTS_SET_INDEX_INPUT_TO": "σε", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Ορίζει το στοιχείο στην καθορισμένη θέση σε μια λίστα.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Ορίζει το πρώτο στοιχείο σε μια λίστα.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Ορίζει το τελευταίο στοιχείο σε μια λίστα.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Ορίζει ένα τυχαίο στοιχείο σε μια λίστα.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Εισάγει το στοιχείο στην καθορισμένη θέση σε μια λίστα.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Εισάγει το στοιχείο στην αρχή μιας λίστας.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Αναθέτει το στοιχείο στο τέλος μιας λίστας.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Εισάγει το στοιχείο τυχαία σε μια λίστα.", - "LISTS_GET_SUBLIST_HELPURL": "Blockly", - "LISTS_GET_SUBLIST_START_FROM_START": "πάρε υπολίστα από #", - "LISTS_GET_SUBLIST_START_FROM_END": "πάρε υπολίστα από # από το τέλος", - "LISTS_GET_SUBLIST_START_FIRST": "πάρε υπολίστα από την αρχή", - "LISTS_GET_SUBLIST_END_FROM_START": "έως #", - "LISTS_GET_SUBLIST_END_FROM_END": "έως # από το τέλος", - "LISTS_GET_SUBLIST_END_LAST": "έως το τελευταίο", - "LISTS_GET_SUBLIST_TOOLTIP": "Δημιουργεί ένα αντίγραφο του καθορισμένου τμήματος μιας λίστας.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_ORDER_ASCENDING": "Αύξουσα", - "LISTS_SORT_ORDER_DESCENDING": "Φθίνουσα", - "LISTS_SORT_TYPE_NUMERIC": "αριθμητικό", - "LISTS_SORT_TYPE_TEXT": "Αλφαβητικά", - "LISTS_SPLIT_LIST_FROM_TEXT": "κάνετε λίστα από το κείμενο", - "LISTS_SPLIT_TEXT_FROM_LIST": "κάνετε κείμενο από τη λίστα", - "LISTS_SPLIT_WITH_DELIMITER": "με διαχωριστικό", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Διαίρεση του κειμένου σε μια λίστα κειμένων, με σπάσιμο σε κάθε διαχωριστικό.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Ενώστε μια λίστα κειμένων σε ένα κείμενο, που χωρίζονται από ένα διαχωριστικό.", - "VARIABLES_GET_TOOLTIP": "Επιστρέφει την τιμή αυτής της μεταβλητής.", - "VARIABLES_GET_CREATE_SET": "Δημιούργησε «όρισε %1»", - "VARIABLES_SET": "όρισε %1 μέχρι το %2", - "VARIABLES_SET_TOOLTIP": "Ορίζει αυτή τη μεταβλητή να είναι ίση με την είσοδο.", - "VARIABLES_SET_CREATE_GET": "Δημιούργησε «πάρε %1»", - "PROCEDURES_DEFNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFNORETURN_TITLE": "στο", - "PROCEDURES_DEFNORETURN_PROCEDURE": "κάνε κάτι", - "PROCEDURES_BEFORE_PARAMS": "με:", - "PROCEDURES_CALL_BEFORE_PARAMS": "με:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Δημιουργεί μια συνάρτηση χωρίς έξοδο.", - "PROCEDURES_DEFRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFRETURN_RETURN": "επέστρεψε", - "PROCEDURES_DEFRETURN_TOOLTIP": "Δημιουργεί μια συνάρτηση με μια έξοδο.", - "PROCEDURES_ALLOW_STATEMENTS": "να επιτρέπονται οι δηλώσεις", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Προειδοποίηση: Αυτή η συνάρτηση έχει διπλότυπες παραμέτρους.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://el.wikipedia.org/wiki/%CE%94%CE%B9%CE%B1%CE%B4%CE%B9%CE%BA%CE%B1%CF%83%CE%AF%CE%B1_%28%CF%85%CF%80%CE%BF%CE%BB%CE%BF%CE%B3%CE%B9%CF%83%CF%84%CE%AD%CF%82%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Εκτελεί την ορισμένη από τον χρήστη συνάρτηση «%1».", - "PROCEDURES_CALLRETURN_HELPURL": "https://el.wikipedia.org/wiki/%CE%94%CE%B9%CE%B1%CE%B4%CE%B9%CE%BA%CE%B1%CF%83%CE%AF%CE%B1_%28%CF%85%CF%80%CE%BF%CE%BB%CE%BF%CE%B3%CE%B9%CF%83%CF%84%CE%AD%CF%82%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Εκτελεί την ορισμένη από τον χρήστη συνάρτηση «%1» και χρησιμοποίησε την έξοδό της.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "είσοδοι", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Προσθέτει, αφαιρεί ή αναδιατάσσει εισόδους σε αυτήν τη λειτουργία", - "PROCEDURES_MUTATORARG_TITLE": "όνομα εισόδου:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Πρόσθεσε μια είσοδος στη συνάρτηση", - "PROCEDURES_HIGHLIGHT_DEF": "Επισημάνετε τον ορισμό συνάρτησης", - "PROCEDURES_CREATE_DO": "Δημιούργησε «%1»", - "PROCEDURES_IFRETURN_TOOLTIP": "Αν μια τιμή είναι αληθής, τότε επιστρέφει τη δεύτερη τιμή.", - "PROCEDURES_IFRETURN_WARNING": "Προειδοποίηση: Αυτό το μπλοκ μπορεί να χρησιμοποιηθεί μόνο στον ορισμό μιας συνάρτησης." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/en-gb.json b/backend/_pv_1_3_5/static/blockly/msg/json/en-gb.json deleted file mode 100755 index a6a662173..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/en-gb.json +++ /dev/null @@ -1,139 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Andibing", - "Codynguyen1116", - "Shirayuki" - ] - }, - "VARIABLES_DEFAULT_NAME": "item", - "TODAY": "Today", - "DUPLICATE_BLOCK": "Duplicate", - "ADD_COMMENT": "Add Comment", - "REMOVE_COMMENT": "Remove Comment", - "EXTERNAL_INPUTS": "External Inputs", - "INLINE_INPUTS": "Inline Inputs", - "DELETE_BLOCK": "Delete Block", - "DELETE_X_BLOCKS": "Delete %1 Blocks", - "DELETE_ALL_BLOCKS": "Delete all %1 blocks?", - "CLEAN_UP": "Clean up Blocks", - "COLLAPSE_BLOCK": "Collapse Block", - "COLLAPSE_ALL": "Collapse Blocks", - "EXPAND_BLOCK": "Expand Block", - "EXPAND_ALL": "Expand Blocks", - "DISABLE_BLOCK": "Disable Block", - "ENABLE_BLOCK": "Enable Block", - "HELP": "Help", - "UNDO": "Undo", - "REDO": "Redo", - "CHANGE_VALUE_TITLE": "Change value:", - "RENAME_VARIABLE": "Rename variable...", - "RENAME_VARIABLE_TITLE": "Rename all '%1' variables to:", - "NEW_VARIABLE": "New variable...", - "NEW_VARIABLE_TITLE": "New variable name:", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Colour", - "COLOUR_PICKER_TOOLTIP": "Choose a colour from the palette.", - "COLOUR_RANDOM_TITLE": "random colour", - "COLOUR_RANDOM_TOOLTIP": "Choose a colour at random.", - "COLOUR_RGB_TITLE": "colour with", - "COLOUR_RGB_RED": "red", - "COLOUR_RGB_GREEN": "green", - "COLOUR_RGB_BLUE": "blue", - "COLOUR_RGB_TOOLTIP": "Create a colour with the specified amount of red, green, and blue. All values must be between 0 and 100.", - "COLOUR_BLEND_TITLE": "blend", - "COLOUR_BLEND_COLOUR1": "colour 1", - "COLOUR_BLEND_COLOUR2": "colour 2", - "COLOUR_BLEND_RATIO": "ratio", - "COLOUR_BLEND_TOOLTIP": "Blends two colours together with a given ratio (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "repeat %1 times", - "CONTROLS_REPEAT_INPUT_DO": "do", - "CONTROLS_REPEAT_TOOLTIP": "Do some statements several times.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "repeat while", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "repeat until", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "While a value is true, then do some statements.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "While a value is false, then do some statements.", - "CONTROLS_FOR_TOOLTIP": "Have the variable '%1' take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks.", - "CONTROLS_FOR_TITLE": "count with %1 from %2 to %3 by %4", - "CONTROLS_FOREACH_TITLE": "for each item %1 in list %2", - "CONTROLS_FOREACH_TOOLTIP": "For each item in a list, set the variable '%1' to the item, and then do some statements.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "break out of loop", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "continue with next iteration of loop", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Break out of the containing loop.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Skip the rest of this loop, and continue with the next iteration.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Warning: This block may only be used within a loop.", - "CONTROLS_IF_TOOLTIP_1": "If a value is true, then do some statements.", - "CONTROLS_IF_TOOLTIP_2": "If a value is true, then do the first block of statements. Otherwise, do the second block of statements.", - "CONTROLS_IF_TOOLTIP_3": "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements.", - "CONTROLS_IF_TOOLTIP_4": "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements.", - "CONTROLS_IF_MSG_IF": "if", - "CONTROLS_IF_MSG_ELSEIF": "else if", - "CONTROLS_IF_MSG_ELSE": "else", - "CONTROLS_IF_IF_TOOLTIP": "Add, remove, or reorder sections to reconfigure this if block.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Add a condition to the if block.", - "CONTROLS_IF_ELSE_TOOLTIP": "Add a final, catch-all condition to the if block.", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Return true if both inputs equal each other.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Return true if both inputs are not equal to each other.", - "LOGIC_COMPARE_TOOLTIP_LT": "Return true if the first input is smaller than the second input.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Return true if the first input is smaller than or equal to the second input.", - "LOGIC_COMPARE_TOOLTIP_GT": "Return true if the first input is greater than the second input.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Return true if the first input is greater than or equal to the second input.", - "LOGIC_OPERATION_TOOLTIP_AND": "Return true if both inputs are true.", - "LOGIC_OPERATION_AND": "and", - "LOGIC_OPERATION_TOOLTIP_OR": "Return true if at least one of the inputs is true.", - "LOGIC_OPERATION_OR": "or", - "LOGIC_NEGATE_TITLE": "not %1", - "LOGIC_NEGATE_TOOLTIP": "Returns true if the input is false. Returns false if the input is true.", - "LOGIC_BOOLEAN_TRUE": "true", - "LOGIC_BOOLEAN_FALSE": "false", - "LOGIC_BOOLEAN_TOOLTIP": "Returns either true or false.", - "LOGIC_NULL": "null", - "LOGIC_NULL_TOOLTIP": "Returns null.", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "if true", - "LOGIC_TERNARY_IF_FALSE": "if false", - "LOGIC_TERNARY_TOOLTIP": "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value.", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "A number.", - "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/Arithmetic", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Return the sum of the two numbers.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Return the difference of the two numbers.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Return the product of the two numbers.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Return the quotient of the two numbers.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Return the first number raised to the power of the second number.", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "square root", - "MATH_SINGLE_TOOLTIP_ROOT": "Return the square root of a number.", - "MATH_SINGLE_OP_ABSOLUTE": "absolute", - "MATH_SINGLE_TOOLTIP_ABS": "Return the absolute value of a number.", - "MATH_SINGLE_TOOLTIP_NEG": "Return the negation of a number.", - "MATH_SINGLE_TOOLTIP_LN": "Return the natural logarithm of a number.", - "MATH_SINGLE_TOOLTIP_LOG10": "Return the base 10 logarithm of a number.", - "MATH_SINGLE_TOOLTIP_EXP": "Return e to the power of a number.", - "MATH_SINGLE_TOOLTIP_POW10": "Return 10 to the power of a number.", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "Return the sine of a degree (not radian).", - "MATH_TRIG_TOOLTIP_COS": "Return the cosine of a degree (not radian).", - "MATH_TRIG_TOOLTIP_TAN": "Return the tangent of a degree (not radian).", - "MATH_TRIG_TOOLTIP_ASIN": "Return the arcsine of a number.", - "MATH_TRIG_TOOLTIP_ACOS": "Return the arccosine of a number.", - "MATH_TRIG_TOOLTIP_ATAN": "Return the arctangent of a number.", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).", - "MATH_IS_EVEN": "is even", - "MATH_IS_ODD": "is odd", - "MATH_IS_PRIME": "is prime", - "MATH_IS_WHOLE": "is whole", - "MATH_IS_POSITIVE": "is positive", - "MATH_IS_NEGATIVE": "is negative", - "MATH_IS_DIVISIBLE_BY": "is divisible by", - "MATH_IS_TOOLTIP": "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "change %1 by %2", - "MATH_CHANGE_TOOLTIP": "Add a number to variable '%1'.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Round a number up or down.", - "MATH_ROUND_OPERATOR_ROUND": "round", - "LISTS_SORT_ORDER_DESCENDING": "descendente" -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/en.json b/backend/_pv_1_3_5/static/blockly/msg/json/en.json deleted file mode 100755 index d2c052a6b..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/en.json +++ /dev/null @@ -1,371 +0,0 @@ -{ - "@metadata": { - "author": "Ellen Spertus ", - "lastupdated": "2016-08-17 16:08:04.888607", - "locale": "en", - "messagedocumentation" : "qqq" - }, - "VARIABLES_DEFAULT_NAME": "item", - "TODAY": "Today", - "DUPLICATE_BLOCK": "Duplicate", - "ADD_COMMENT": "Add Comment", - "REMOVE_COMMENT": "Remove Comment", - "EXTERNAL_INPUTS": "External Inputs", - "INLINE_INPUTS": "Inline Inputs", - "DELETE_BLOCK": "Delete Block", - "DELETE_X_BLOCKS": "Delete %1 Blocks", - "DELETE_ALL_BLOCKS": "Delete all %1 blocks?", - "CLEAN_UP": "Clean up Blocks", - "COLLAPSE_BLOCK": "Collapse Block", - "COLLAPSE_ALL": "Collapse Blocks", - "EXPAND_BLOCK": "Expand Block", - "EXPAND_ALL": "Expand Blocks", - "DISABLE_BLOCK": "Disable Block", - "ENABLE_BLOCK": "Enable Block", - "HELP": "Help", - "UNDO": "Undo", - "REDO": "Redo", - "CHANGE_VALUE_TITLE": "Change value:", - "RENAME_VARIABLE": "Rename variable...", - "RENAME_VARIABLE_TITLE": "Rename all '%1' variables to:", - "NEW_VARIABLE": "Create variable...", - "NEW_VARIABLE_TITLE": "New variable name:", - "VARIABLE_ALREADY_EXISTS": "A variable named '%1' already exists.", - "DELETE_VARIABLE_CONFIRMATION": "Delete %1 uses of the '%2' variable?", - "DELETE_VARIABLE": "Delete the '%1' variable", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "Choose a colour from the palette.", - "COLOUR_RANDOM_HELPURL": "http://randomcolour.com", - "COLOUR_RANDOM_TITLE": "random colour", - "COLOUR_RANDOM_TOOLTIP": "Choose a colour at random.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "colour with", - "COLOUR_RGB_RED": "red", - "COLOUR_RGB_GREEN": "green", - "COLOUR_RGB_BLUE": "blue", - "COLOUR_RGB_TOOLTIP": "Create a colour with the specified amount of red, green, and blue. All values must be between 0 and 100.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "blend", - "COLOUR_BLEND_COLOUR1": "colour 1", - "COLOUR_BLEND_COLOUR2": "colour 2", - "COLOUR_BLEND_RATIO": "ratio", - "COLOUR_BLEND_TOOLTIP": "Blends two colours together with a given ratio (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "repeat %1 times", - "CONTROLS_REPEAT_INPUT_DO": "do", - "CONTROLS_REPEAT_TOOLTIP": "Do some statements several times.", - "CONTROLS_WHILEUNTIL_HELPURL": "https://github.com/google/blockly/wiki/Loops#repeat", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "repeat while", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "repeat until", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "While a value is true, then do some statements.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "While a value is false, then do some statements.", - "CONTROLS_FOR_HELPURL": "https://github.com/google/blockly/wiki/Loops#count-with", - "CONTROLS_FOR_TOOLTIP": "Have the variable '%1' take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks.", - "CONTROLS_FOR_TITLE": "count with %1 from %2 to %3 by %4", - "CONTROLS_FOREACH_HELPURL": "https://github.com/google/blockly/wiki/Loops#for-each", - "CONTROLS_FOREACH_TITLE": "for each item %1 in list %2", - "CONTROLS_FOREACH_TOOLTIP": "For each item in a list, set the variable '%1' to the item, and then do some statements.", - "CONTROLS_FLOW_STATEMENTS_HELPURL": "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "break out of loop", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "continue with next iteration of loop", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Break out of the containing loop.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Skip the rest of this loop, and continue with the next iteration.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Warning: This block may only be used within a loop.", - "CONTROLS_IF_HELPURL": "https://github.com/google/blockly/wiki/IfElse", - "CONTROLS_IF_TOOLTIP_1": "If a value is true, then do some statements.", - "CONTROLS_IF_TOOLTIP_2": "If a value is true, then do the first block of statements. Otherwise, do the second block of statements.", - "CONTROLS_IF_TOOLTIP_3": "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements.", - "CONTROLS_IF_TOOLTIP_4": "If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements.", - "CONTROLS_IF_MSG_IF": "if", - "CONTROLS_IF_MSG_ELSEIF": "else if", - "CONTROLS_IF_MSG_ELSE": "else", - "CONTROLS_IF_IF_TOOLTIP": "Add, remove, or reorder sections to reconfigure this if block.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Add a condition to the if block.", - "CONTROLS_IF_ELSE_TOOLTIP": "Add a final, catch-all condition to the if block.", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Return true if both inputs equal each other.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Return true if both inputs are not equal to each other.", - "LOGIC_COMPARE_TOOLTIP_LT": "Return true if the first input is smaller than the second input.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Return true if the first input is smaller than or equal to the second input.", - "LOGIC_COMPARE_TOOLTIP_GT": "Return true if the first input is greater than the second input.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Return true if the first input is greater than or equal to the second input.", - "LOGIC_OPERATION_HELPURL": "https://github.com/google/blockly/wiki/Logic#logical-operations", - "LOGIC_OPERATION_TOOLTIP_AND": "Return true if both inputs are true.", - "LOGIC_OPERATION_AND": "and", - "LOGIC_OPERATION_TOOLTIP_OR": "Return true if at least one of the inputs is true.", - "LOGIC_OPERATION_OR": "or", - "LOGIC_NEGATE_HELPURL": "https://github.com/google/blockly/wiki/Logic#not", - "LOGIC_NEGATE_TITLE": "not %1", - "LOGIC_NEGATE_TOOLTIP": "Returns true if the input is false. Returns false if the input is true.", - "LOGIC_BOOLEAN_HELPURL": "https://github.com/google/blockly/wiki/Logic#values", - "LOGIC_BOOLEAN_TRUE": "true", - "LOGIC_BOOLEAN_FALSE": "false", - "LOGIC_BOOLEAN_TOOLTIP": "Returns either true or false.", - "LOGIC_NULL_HELPURL": "https://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "null", - "LOGIC_NULL_TOOLTIP": "Returns null.", - "LOGIC_TERNARY_HELPURL": "https://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "if true", - "LOGIC_TERNARY_IF_FALSE": "if false", - "LOGIC_TERNARY_TOOLTIP": "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value.", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "A number.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tan", - "MATH_TRIG_ASIN": "asin", - "MATH_TRIG_ACOS": "acos", - "MATH_TRIG_ATAN": "atan", - "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/Arithmetic", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Return the sum of the two numbers.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Return the difference of the two numbers.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Return the product of the two numbers.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Return the quotient of the two numbers.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Return the first number raised to the power of the second number.", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "square root", - "MATH_SINGLE_TOOLTIP_ROOT": "Return the square root of a number.", - "MATH_SINGLE_OP_ABSOLUTE": "absolute", - "MATH_SINGLE_TOOLTIP_ABS": "Return the absolute value of a number.", - "MATH_SINGLE_TOOLTIP_NEG": "Return the negation of a number.", - "MATH_SINGLE_TOOLTIP_LN": "Return the natural logarithm of a number.", - "MATH_SINGLE_TOOLTIP_LOG10": "Return the base 10 logarithm of a number.", - "MATH_SINGLE_TOOLTIP_EXP": "Return e to the power of a number.", - "MATH_SINGLE_TOOLTIP_POW10": "Return 10 to the power of a number.", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "Return the sine of a degree (not radian).", - "MATH_TRIG_TOOLTIP_COS": "Return the cosine of a degree (not radian).", - "MATH_TRIG_TOOLTIP_TAN": "Return the tangent of a degree (not radian).", - "MATH_TRIG_TOOLTIP_ASIN": "Return the arcsine of a number.", - "MATH_TRIG_TOOLTIP_ACOS": "Return the arccosine of a number.", - "MATH_TRIG_TOOLTIP_ATAN": "Return the arctangent of a number.", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).", - "MATH_IS_EVEN": "is even", - "MATH_IS_ODD": "is odd", - "MATH_IS_PRIME": "is prime", - "MATH_IS_WHOLE": "is whole", - "MATH_IS_POSITIVE": "is positive", - "MATH_IS_NEGATIVE": "is negative", - "MATH_IS_DIVISIBLE_BY": "is divisible by", - "MATH_IS_TOOLTIP": "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "change %1 by %2", - "MATH_CHANGE_TOOLTIP": "Add a number to variable '%1'.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Round a number up or down.", - "MATH_ROUND_OPERATOR_ROUND": "round", - "MATH_ROUND_OPERATOR_ROUNDUP": "round up", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "round down", - "MATH_ONLIST_HELPURL": "", - "MATH_ONLIST_OPERATOR_SUM": "sum of list", - "MATH_ONLIST_TOOLTIP_SUM": "Return the sum of all the numbers in the list.", - "MATH_ONLIST_OPERATOR_MIN": "min of list", - "MATH_ONLIST_TOOLTIP_MIN": "Return the smallest number in the list.", - "MATH_ONLIST_OPERATOR_MAX": "max of list", - "MATH_ONLIST_TOOLTIP_MAX": "Return the largest number in the list.", - "MATH_ONLIST_OPERATOR_AVERAGE": "average of list", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Return the average (arithmetic mean) of the numeric values in the list.", - "MATH_ONLIST_OPERATOR_MEDIAN": "median of list", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Return the median number in the list.", - "MATH_ONLIST_OPERATOR_MODE": "modes of list", - "MATH_ONLIST_TOOLTIP_MODE": "Return a list of the most common item(s) in the list.", - "MATH_ONLIST_OPERATOR_STD_DEV": "standard deviation of list", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Return the standard deviation of the list.", - "MATH_ONLIST_OPERATOR_RANDOM": "random item of list", - "MATH_ONLIST_TOOLTIP_RANDOM": "Return a random element from the list.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "remainder of %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Return the remainder from dividing the two numbers.", - "MATH_CONSTRAIN_HELPURL": "https://en.wikipedia.org/wiki/Clamping_%28graphics%29", - "MATH_CONSTRAIN_TITLE": "constrain %1 low %2 high %3", - "MATH_CONSTRAIN_TOOLTIP": "Constrain a number to be between the specified limits (inclusive).", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "random integer from %1 to %2", - "MATH_RANDOM_INT_TOOLTIP": "Return a random integer between the two specified limits, inclusive.", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "random fraction", - "MATH_RANDOM_FLOAT_TOOLTIP": "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "A letter, word, or line of text.", - "TEXT_JOIN_HELPURL": "https://github.com/google/blockly/wiki/Text#text-creation", - "TEXT_JOIN_TITLE_CREATEWITH": "create text with", - "TEXT_JOIN_TOOLTIP": "Create a piece of text by joining together any number of items.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "join", - "TEXT_CREATE_JOIN_TOOLTIP": "Add, remove, or reorder sections to reconfigure this text block.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Add an item to the text.", - "TEXT_APPEND_HELPURL": "https://github.com/google/blockly/wiki/Text#text-modification", - "TEXT_APPEND_TO": "to", - "TEXT_APPEND_APPENDTEXT": "append text", - "TEXT_APPEND_TOOLTIP": "Append some text to variable '%1'.", - "TEXT_LENGTH_HELPURL": "https://github.com/google/blockly/wiki/Text#text-modification", - "TEXT_LENGTH_TITLE": "length of %1", - "TEXT_LENGTH_TOOLTIP": "Returns the number of letters (including spaces) in the provided text.", - "TEXT_ISEMPTY_HELPURL": "https://github.com/google/blockly/wiki/Text#checking-for-empty-text", - "TEXT_ISEMPTY_TITLE": "%1 is empty", - "TEXT_ISEMPTY_TOOLTIP": "Returns true if the provided text is empty.", - "TEXT_INDEXOF_HELPURL": "https://github.com/google/blockly/wiki/Text#finding-text", - "TEXT_INDEXOF_TOOLTIP": "Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found.", - "TEXT_INDEXOF_INPUT_INTEXT": "in text", - "TEXT_INDEXOF_OPERATOR_FIRST": "find first occurrence of text", - "TEXT_INDEXOF_OPERATOR_LAST": "find last occurrence of text", - "TEXT_INDEXOF_TAIL": "", - "TEXT_CHARAT_HELPURL": "https://github.com/google/blockly/wiki/Text#extracting-text", - "TEXT_CHARAT_INPUT_INTEXT": "in text", - "TEXT_CHARAT_FROM_START": "get letter #", - "TEXT_CHARAT_FROM_END": "get letter # from end", - "TEXT_CHARAT_FIRST": "get first letter", - "TEXT_CHARAT_LAST": "get last letter", - "TEXT_CHARAT_RANDOM": "get random letter", - "TEXT_CHARAT_TAIL": "", - "TEXT_CHARAT_TOOLTIP": "Returns the letter at the specified position.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Returns a specified portion of the text.", - "TEXT_GET_SUBSTRING_HELPURL": "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "in text", - "TEXT_GET_SUBSTRING_START_FROM_START": "get substring from letter #", - "TEXT_GET_SUBSTRING_START_FROM_END": "get substring from letter # from end", - "TEXT_GET_SUBSTRING_START_FIRST": "get substring from first letter", - "TEXT_GET_SUBSTRING_END_FROM_START": "to letter #", - "TEXT_GET_SUBSTRING_END_FROM_END": "to letter # from end", - "TEXT_GET_SUBSTRING_END_LAST": "to last letter", - "TEXT_GET_SUBSTRING_TAIL": "", - "TEXT_CHANGECASE_HELPURL": "https://github.com/google/blockly/wiki/Text#adjusting-text-case", - "TEXT_CHANGECASE_TOOLTIP": "Return a copy of the text in a different case.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "to UPPER CASE", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "to lower case", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "to Title Case", - "TEXT_TRIM_HELPURL": "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces", - "TEXT_TRIM_TOOLTIP": "Return a copy of the text with spaces removed from one or both ends.", - "TEXT_TRIM_OPERATOR_BOTH": "trim spaces from both sides of", - "TEXT_TRIM_OPERATOR_LEFT": "trim spaces from left side of", - "TEXT_TRIM_OPERATOR_RIGHT": "trim spaces from right side of", - "TEXT_PRINT_HELPURL": "https://github.com/google/blockly/wiki/Text#printing-text", - "TEXT_PRINT_TITLE": "print %1", - "TEXT_PRINT_TOOLTIP": "Print the specified text, number or other value.", - "TEXT_PROMPT_HELPURL": "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user", - "TEXT_PROMPT_TYPE_TEXT": "prompt for text with message", - "TEXT_PROMPT_TYPE_NUMBER": "prompt for number with message", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Prompt for user for a number.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Prompt for user for some text.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "create empty list", - "LISTS_CREATE_EMPTY_TOOLTIP": "Returns a list, of length 0, containing no data records", - "LISTS_CREATE_WITH_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_CREATE_WITH_TOOLTIP": "Create a list with any number of items.", - "LISTS_CREATE_WITH_INPUT_WITH": "create list with", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "list", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Add, remove, or reorder sections to reconfigure this list block.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Add an item to the list.", - "LISTS_REPEAT_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_REPEAT_TOOLTIP": "Creates a list consisting of the given value repeated the specified number of times.", - "LISTS_REPEAT_TITLE": "create list with item %1 repeated %2 times", - "LISTS_LENGTH_HELPURL": "https://github.com/google/blockly/wiki/Lists#length-of", - "LISTS_LENGTH_TITLE": "length of %1", - "LISTS_LENGTH_TOOLTIP": "Returns the length of a list.", - "LISTS_ISEMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#is-empty", - "LISTS_ISEMPTY_TITLE": "%1 is empty", - "LISTS_ISEMPTY_TOOLTIP": "Returns true if the list is empty.", - "LISTS_INLIST": "in list", - "LISTS_INDEX_OF_HELPURL": "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list", - "LISTS_INDEX_OF_FIRST": "find first occurrence of item", - "LISTS_INDEX_OF_LAST": "find last occurrence of item", - "LISTS_INDEX_OF_TOOLTIP": "Returns the index of the first/last occurrence of the item in the list. Returns %1 if item is not found.", - "LISTS_GET_INDEX_GET": "get", - "LISTS_GET_INDEX_GET_REMOVE": "get and remove", - "LISTS_GET_INDEX_REMOVE": "remove", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# from end", - "LISTS_GET_INDEX_FIRST": "first", - "LISTS_GET_INDEX_LAST": "last", - "LISTS_GET_INDEX_RANDOM": "random", - "LISTS_GET_INDEX_TAIL": "", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 is the first item.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 is the last item.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Returns the item at the specified position in a list.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Returns the first item in a list.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Returns the last item in a list.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Returns a random item in a list.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Removes and returns the item at the specified position in a list.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Removes and returns the first item in a list.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Removes and returns the last item in a list.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Removes and returns a random item in a list.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Removes the item at the specified position in a list.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Removes the first item in a list.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Removes the last item in a list.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Removes a random item in a list.", - "LISTS_SET_INDEX_HELPURL": "https://github.com/google/blockly/wiki/Lists#in-list--set", - "LISTS_SET_INDEX_SET": "set", - "LISTS_SET_INDEX_INSERT": "insert at", - "LISTS_SET_INDEX_INPUT_TO": "as", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Sets the item at the specified position in a list.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Sets the first item in a list.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Sets the last item in a list.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Sets a random item in a list.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Inserts the item at the specified position in a list.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Inserts the item at the start of a list.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Append the item to the end of a list.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Inserts the item randomly in a list.", - "LISTS_GET_SUBLIST_HELPURL": "https://github.com/google/blockly/wiki/Lists#getting-a-sublist", - "LISTS_GET_SUBLIST_START_FROM_START": "get sub-list from #", - "LISTS_GET_SUBLIST_START_FROM_END": "get sub-list from # from end", - "LISTS_GET_SUBLIST_START_FIRST": "get sub-list from first", - "LISTS_GET_SUBLIST_END_FROM_START": "to #", - "LISTS_GET_SUBLIST_END_FROM_END": "to # from end", - "LISTS_GET_SUBLIST_END_LAST": "to last", - "LISTS_GET_SUBLIST_TAIL": "", - "LISTS_GET_SUBLIST_TOOLTIP": "Creates a copy of the specified portion of a list.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "sort %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Sort a copy of a list.", - "LISTS_SORT_ORDER_ASCENDING": "ascending", - "LISTS_SORT_ORDER_DESCENDING": "descending", - "LISTS_SORT_TYPE_NUMERIC": "numeric", - "LISTS_SORT_TYPE_TEXT": "alphabetic", - "LISTS_SORT_TYPE_IGNORECASE": "alphabetic, ignore case", - "LISTS_SPLIT_HELPURL": "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists", - "LISTS_SPLIT_LIST_FROM_TEXT": "make list from text", - "LISTS_SPLIT_TEXT_FROM_LIST": "make text from list", - "LISTS_SPLIT_WITH_DELIMITER": "with delimiter", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Split text into a list of texts, breaking at each delimiter.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Join a list of texts into one text, separated by a delimiter.", - "ORDINAL_NUMBER_SUFFIX": "", - "VARIABLES_GET_HELPURL": "https://github.com/google/blockly/wiki/Variables#get", - "VARIABLES_GET_TOOLTIP": "Returns the value of this variable.", - "VARIABLES_GET_CREATE_SET": "Create 'set %1'", - "VARIABLES_SET_HELPURL": "https://github.com/google/blockly/wiki/Variables#set", - "VARIABLES_SET": "set %1 to %2", - "VARIABLES_SET_TOOLTIP": "Sets this variable to be equal to the input.", - "VARIABLES_SET_CREATE_GET": "Create 'get %1'", - "PROCEDURES_DEFNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFNORETURN_TITLE": "to", - "PROCEDURES_DEFNORETURN_PROCEDURE": "do something", - "PROCEDURES_BEFORE_PARAMS": "with:", - "PROCEDURES_CALL_BEFORE_PARAMS": "with:", - "PROCEDURES_DEFNORETURN_DO": "", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Creates a function with no output.", - "PROCEDURES_DEFNORETURN_COMMENT": "Describe this function...", - "PROCEDURES_DEFRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFRETURN_RETURN": "return", - "PROCEDURES_DEFRETURN_TOOLTIP": "Creates a function with an output.", - "PROCEDURES_ALLOW_STATEMENTS": "allow statements", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Warning: This function has duplicate parameters.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Run the user-defined function '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Run the user-defined function '%1' and use its output.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "inputs", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Add, remove, or reorder inputs to this function.", - "PROCEDURES_MUTATORARG_TITLE": "input name:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Add an input to the function.", - "PROCEDURES_HIGHLIGHT_DEF": "Highlight function definition", - "PROCEDURES_CREATE_DO": "Create '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "If a value is true, then return a second value.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Warning: This block may be used only within a function definition." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/es.json b/backend/_pv_1_3_5/static/blockly/msg/json/es.json deleted file mode 100755 index d5879b64e..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/es.json +++ /dev/null @@ -1,321 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Fitoschido", - "VegaDark", - "WeSiToS", - "Macofe", - "Codynguyen1116", - "Indiralena", - "Rubentl134", - "Martineduardo" - ] - }, - "VARIABLES_DEFAULT_NAME": "elemento", - "TODAY": "Hoy", - "DUPLICATE_BLOCK": "Duplicar", - "ADD_COMMENT": "Añadir comentario", - "REMOVE_COMMENT": "Eliminar comentario", - "EXTERNAL_INPUTS": "Entradas externas", - "INLINE_INPUTS": "Entradas en línea", - "DELETE_BLOCK": "Eliminar bloque", - "DELETE_X_BLOCKS": "Eliminar %1 bloques", - "DELETE_ALL_BLOCKS": "¿Eliminar todos los %1 bloques?", - "CLEAN_UP": "Limpiar los bloques", - "COLLAPSE_BLOCK": "Contraer bloque", - "COLLAPSE_ALL": "Contraer bloques", - "EXPAND_BLOCK": "Expandir bloque", - "EXPAND_ALL": "Expandir bloques", - "DISABLE_BLOCK": "Desactivar bloque", - "ENABLE_BLOCK": "Activar bloque", - "HELP": "Ayuda", - "UNDO": "Deshacer", - "REDO": "Rehacer", - "CHANGE_VALUE_TITLE": "Cambiar el valor:", - "RENAME_VARIABLE": "Renombrar la variable…", - "RENAME_VARIABLE_TITLE": "Renombrar todas las variables «%1» a:", - "NEW_VARIABLE": "Crear variable…", - "NEW_VARIABLE_TITLE": "Nombre de variable nueva:", - "VARIABLE_ALREADY_EXISTS": "Ya existe una variable llamada \"%1\".", - "DELETE_VARIABLE_CONFIRMATION": "¿Borrar %1 usos de la variable \"%2\"?", - "DELETE_VARIABLE": "Borrar la variable \"%1\"", - "COLOUR_PICKER_HELPURL": "https://es.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "Elige un color de la paleta.", - "COLOUR_RANDOM_TITLE": "color aleatorio", - "COLOUR_RANDOM_TOOLTIP": "Elige un color al azar.", - "COLOUR_RGB_TITLE": "colorear con", - "COLOUR_RGB_RED": "rojo", - "COLOUR_RGB_GREEN": "verde", - "COLOUR_RGB_BLUE": "azul", - "COLOUR_RGB_TOOLTIP": "Crea un color con cantidades específicas de rojo, verde y azul. Todos los valores deben encontrarse entre 0 y 100.", - "COLOUR_BLEND_TITLE": "combinar", - "COLOUR_BLEND_COLOUR1": "color 1", - "COLOUR_BLEND_COLOUR2": "color 2", - "COLOUR_BLEND_RATIO": "proporción", - "COLOUR_BLEND_TOOLTIP": "Combina dos colores con una proporción determinada (0,0–1,0).", - "CONTROLS_REPEAT_HELPURL": "https://es.wikipedia.org/wiki/Bucle_for", - "CONTROLS_REPEAT_TITLE": "repetir %1 veces", - "CONTROLS_REPEAT_INPUT_DO": "hacer", - "CONTROLS_REPEAT_TOOLTIP": "Hacer algunas declaraciones varias veces.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "repetir mientras", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "repetir hasta", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Mientras un valor sea verdadero, entonces hacer algunas declaraciones.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Mientras un valor sea falso, entonces hacer algunas declaraciones.", - "CONTROLS_FOR_TOOLTIP": "Hacer que la variable \"%1\" tome los valores desde el número de inicio hasta el número final, contando con el intervalo especificado, y hacer los bloques especificados.", - "CONTROLS_FOR_TITLE": "contar con %1 desde %2 hasta %3 de a %4", - "CONTROLS_FOREACH_HELPURL": "https://es.wikipedia.org/wiki/Foreach", - "CONTROLS_FOREACH_TITLE": "para cada elemento %1 en la lista %2", - "CONTROLS_FOREACH_TOOLTIP": "Para cada elemento en una lista, establecer la variable '%1' al elemento y luego hacer algunas declaraciones.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "romper el bucle", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "continuar con la siguiente iteración del bucle", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Romper el bucle que lo contiene.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Saltar el resto de este bucle, y continuar con la siguiente iteración.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "ADVERTENCIA: Este bloque puede usarse sólo dentro de un bucle.", - "CONTROLS_IF_TOOLTIP_1": "Si un valor es verdadero, entonces hacer algunas declaraciones.", - "CONTROLS_IF_TOOLTIP_2": "Si un valor es verdadero, entonces hacer el primer bloque de declaraciones. De lo contrario, hacer el segundo bloque de declaraciones.", - "CONTROLS_IF_TOOLTIP_3": "Si el primer valor es verdadero, entonces hacer el primer bloque de declaraciones. De lo contrario, si el segundo valor es verdadero, hacer el segundo bloque de declaraciones.", - "CONTROLS_IF_TOOLTIP_4": "Si el primer valor es verdadero, entonces hacer el primer bloque de declaraciones. De lo contrario, si el segundo valor es verdadero, hacer el segundo bloque de declaraciones. Si ninguno de los valores son verdaderos, hacer el último bloque de declaraciones.", - "CONTROLS_IF_MSG_IF": "si", - "CONTROLS_IF_MSG_ELSEIF": "sino si", - "CONTROLS_IF_MSG_ELSE": "sino", - "CONTROLS_IF_IF_TOOLTIP": "Agregar, eliminar o reordenar las secciones para reconfigurar este bloque.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Agregar una condición a este bloque.", - "CONTROLS_IF_ELSE_TOOLTIP": "Agregar una condición general final a este bloque.", - "LOGIC_COMPARE_HELPURL": "https://es.wikipedia.org/wiki/Desigualdad_matemática", - "LOGIC_COMPARE_TOOLTIP_EQ": "Devuelve verdadero si ambas entradas son iguales.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Devuelve verdadero si ambas entradas son distintas.", - "LOGIC_COMPARE_TOOLTIP_LT": "Devuelve verdadero si la primera entrada es menor que la segunda entrada.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Devuelve verdadero si la primera entrada es menor que o igual a la segunda entrada.", - "LOGIC_COMPARE_TOOLTIP_GT": "Devuelve verdadero si la primera entrada es mayor que la segunda entrada.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Devuelve verdadero si la primera entrada es mayor o igual a la segunda entrada.", - "LOGIC_OPERATION_TOOLTIP_AND": "Devuelve verdadero si ambas entradas son verdaderas.", - "LOGIC_OPERATION_AND": "y", - "LOGIC_OPERATION_TOOLTIP_OR": "Devuelve verdadero si al menos una de las entradas es verdadera.", - "LOGIC_OPERATION_OR": "o", - "LOGIC_NEGATE_TITLE": "no %1", - "LOGIC_NEGATE_TOOLTIP": "Devuelve verdadero si la entrada es falsa. Devuelve falso si la entrada es verdadera.", - "LOGIC_BOOLEAN_TRUE": "verdadero", - "LOGIC_BOOLEAN_FALSE": "falso", - "LOGIC_BOOLEAN_TOOLTIP": "Devuelve verdadero o falso.", - "LOGIC_NULL": "nulo", - "LOGIC_NULL_TOOLTIP": "Devuelve nulo.", - "LOGIC_TERNARY_CONDITION": "prueba", - "LOGIC_TERNARY_IF_TRUE": "si es verdadero", - "LOGIC_TERNARY_IF_FALSE": "si es falso", - "LOGIC_TERNARY_TOOLTIP": "Comprueba la condición en \"prueba\". Si la condición es verdadera, devuelve el valor \"si es verdadero\"; de lo contrario, devuelve el valor \"si es falso\".", - "MATH_NUMBER_HELPURL": "https://es.wikipedia.org/wiki/Número", - "MATH_NUMBER_TOOLTIP": "Un número.", - "MATH_ARITHMETIC_HELPURL": "https://es.wikipedia.org/wiki/Aritmética", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Devuelve la suma de ambos números.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Devuelve la diferencia de ambos números.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Devuelve el producto de ambos números.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Devuelve el cociente de ambos números.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Devuelve el primer número elevado a la potencia del segundo.", - "MATH_SINGLE_HELPURL": "https://es.wikipedia.org/wiki/Ra%C3%ADz_cuadrada", - "MATH_SINGLE_OP_ROOT": "raíz cuadrada", - "MATH_SINGLE_TOOLTIP_ROOT": "Devuelve la raíz cuadrada de un número.", - "MATH_SINGLE_OP_ABSOLUTE": "absoluto", - "MATH_SINGLE_TOOLTIP_ABS": "Devuelve el valor absoluto de un número.", - "MATH_SINGLE_TOOLTIP_NEG": "Devuelve la negación de un número.", - "MATH_SINGLE_TOOLTIP_LN": "Devuelve el logaritmo natural de un número.", - "MATH_SINGLE_TOOLTIP_LOG10": "Devuelve el logaritmo base 10 de un número.", - "MATH_SINGLE_TOOLTIP_EXP": "Devuelve e a la potencia de un número.", - "MATH_SINGLE_TOOLTIP_POW10": "Devuelve 10 a la potencia de un número.", - "MATH_TRIG_HELPURL": "https://es.wikipedia.org/wiki/Función_trigonométrica", - "MATH_TRIG_TOOLTIP_SIN": "Devuelve el seno de un grado (no radián).", - "MATH_TRIG_TOOLTIP_COS": "Devuelve el coseno de un grado (no radián).", - "MATH_TRIG_TOOLTIP_TAN": "Devuelve la tangente de un grado (no radián).", - "MATH_TRIG_TOOLTIP_ASIN": "Devuelve el arcoseno de un número.", - "MATH_TRIG_TOOLTIP_ACOS": "Devuelve el arcocoseno de un número.", - "MATH_TRIG_TOOLTIP_ATAN": "Devuelve el arcotangente de un número.", - "MATH_CONSTANT_HELPURL": "https://es.wikipedia.org/wiki/Anexo:Constantes_matemáticas", - "MATH_CONSTANT_TOOLTIP": "Devuelve una de las constantes comunes: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…) o ∞ (infinito).", - "MATH_IS_EVEN": "es par", - "MATH_IS_ODD": "es impar", - "MATH_IS_PRIME": "es primo", - "MATH_IS_WHOLE": "es entero", - "MATH_IS_POSITIVE": "es positivo", - "MATH_IS_NEGATIVE": "es negativo", - "MATH_IS_DIVISIBLE_BY": "es divisible por", - "MATH_IS_TOOLTIP": "Comprueba si un número es par, impar, primo, entero, positivo, negativo, o si es divisible por un número determinado. Devuelve verdadero o falso.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "añadir %2 a %1", - "MATH_CHANGE_TOOLTIP": "Añadir un número a la variable «%1».", - "MATH_ROUND_HELPURL": "https://es.wikipedia.org/wiki/Redondeo", - "MATH_ROUND_TOOLTIP": "Redondear un número hacia arriba o hacia abajo.", - "MATH_ROUND_OPERATOR_ROUND": "redondear", - "MATH_ROUND_OPERATOR_ROUNDUP": "redondear hacia arriba", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "redondear hacia abajo", - "MATH_ONLIST_OPERATOR_SUM": "suma de la lista", - "MATH_ONLIST_TOOLTIP_SUM": "Devuelve la suma de todos los números en la lista.", - "MATH_ONLIST_OPERATOR_MIN": "mínimo de la lista", - "MATH_ONLIST_TOOLTIP_MIN": "Devuelve el número más pequeño en la lista.", - "MATH_ONLIST_OPERATOR_MAX": "máximo de la lista", - "MATH_ONLIST_TOOLTIP_MAX": "Devuelve el número más grande en la lista.", - "MATH_ONLIST_OPERATOR_AVERAGE": "promedio de la lista", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Devuelve el promedio (media aritmética) de los valores numéricos en la lista.", - "MATH_ONLIST_OPERATOR_MEDIAN": "mediana de la lista", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Devuelve la mediana en la lista.", - "MATH_ONLIST_OPERATOR_MODE": "modas de la lista", - "MATH_ONLIST_TOOLTIP_MODE": "Devuelve una lista de los elementos más comunes en la lista.", - "MATH_ONLIST_OPERATOR_STD_DEV": "desviación estándar de la lista", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Devuelve la desviación estándar de la lista.", - "MATH_ONLIST_OPERATOR_RANDOM": "elemento aleatorio de la lista", - "MATH_ONLIST_TOOLTIP_RANDOM": "Devuelve un elemento aleatorio de la lista.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "resto de %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Devuelve el resto al dividir los dos números.", - "MATH_CONSTRAIN_TITLE": "limitar %1 entre %2 y %3", - "MATH_CONSTRAIN_TOOLTIP": "Limitar un número entre los límites especificados (inclusive).", - "MATH_RANDOM_INT_HELPURL": "https://es.wikipedia.org/wiki/Generador_de_números_aleatorios", - "MATH_RANDOM_INT_TITLE": "entero aleatorio de %1 a %2", - "MATH_RANDOM_INT_TOOLTIP": "Devuelve un entero aleatorio entre los dos límites especificados, inclusive.", - "MATH_RANDOM_FLOAT_HELPURL": "https://es.wikipedia.org/wiki/Generador_de_números_aleatorios", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "fracción aleatoria", - "MATH_RANDOM_FLOAT_TOOLTIP": "Devuelve una fracción aleatoria entre 0,0 (ambos inclusive) y 1.0 (exclusivo).", - "TEXT_TEXT_HELPURL": "https://es.wikipedia.org/wiki/Cadena_de_caracteres", - "TEXT_TEXT_TOOLTIP": "Una letra, palabra o línea de texto.", - "TEXT_JOIN_TITLE_CREATEWITH": "crear texto con", - "TEXT_JOIN_TOOLTIP": "Crear un fragmento de texto al unir cualquier número de elementos.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "unir", - "TEXT_CREATE_JOIN_TOOLTIP": "Agregar, eliminar o reordenar las secciones para reconfigurar este bloque de texto.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Agregar un elemento al texto.", - "TEXT_APPEND_TO": "a", - "TEXT_APPEND_APPENDTEXT": "añadir texto", - "TEXT_APPEND_TOOLTIP": "Añadir texto a la variable '%1'.", - "TEXT_LENGTH_TITLE": "longitud de %1", - "TEXT_LENGTH_TOOLTIP": "Devuelve el número de letras (incluyendo espacios) en el texto proporcionado.", - "TEXT_ISEMPTY_TITLE": "%1 está vacío", - "TEXT_ISEMPTY_TOOLTIP": "Devuelve verdadero si el texto proporcionado está vacío.", - "TEXT_INDEXOF_TOOLTIP": "Devuelve el índice de la primera/última aparición del primer texto en el segundo texto. Devuelve %1 si el texto no se encuentra.", - "TEXT_INDEXOF_INPUT_INTEXT": "en el texto", - "TEXT_INDEXOF_OPERATOR_FIRST": "encontrar la primera aparición del texto", - "TEXT_INDEXOF_OPERATOR_LAST": "encontrar la última aparición del texto", - "TEXT_CHARAT_INPUT_INTEXT": "en el texto", - "TEXT_CHARAT_FROM_START": "obtener la letra #", - "TEXT_CHARAT_FROM_END": "obtener la letra # del final", - "TEXT_CHARAT_FIRST": "obtener la primera letra", - "TEXT_CHARAT_LAST": "obtener la última letra", - "TEXT_CHARAT_RANDOM": "obtener letra aleatoria", - "TEXT_CHARAT_TOOLTIP": "Devuelve la letra en la posición especificada.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Devuelve una porción determinada del texto.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "en el texto", - "TEXT_GET_SUBSTRING_START_FROM_START": "obtener subcadena desde la letra #", - "TEXT_GET_SUBSTRING_START_FROM_END": "obtener subcadena desde la letra # del final", - "TEXT_GET_SUBSTRING_START_FIRST": "obtener subcadena desde la primera letra", - "TEXT_GET_SUBSTRING_END_FROM_START": "hasta la letra #", - "TEXT_GET_SUBSTRING_END_FROM_END": "hasta la letra # del final", - "TEXT_GET_SUBSTRING_END_LAST": "hasta la última letra", - "TEXT_CHANGECASE_TOOLTIP": "Devuelve una copia del texto en un caso diferente.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "a MAYÚSCULAS", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "a minúsculas", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "a Mayúsculas Cada Palabra", - "TEXT_TRIM_TOOLTIP": "Devuelve una copia del texto sin los espacios de uno o ambos extremos.", - "TEXT_TRIM_OPERATOR_BOTH": "quitar espacios de ambos lados de", - "TEXT_TRIM_OPERATOR_LEFT": "quitar espacios iniciales de", - "TEXT_TRIM_OPERATOR_RIGHT": "quitar espacios finales de", - "TEXT_PRINT_TITLE": "imprimir %1", - "TEXT_PRINT_TOOLTIP": "Imprimir el texto, número u otro valor especificado.", - "TEXT_PROMPT_TYPE_TEXT": "solicitar texto con el mensaje", - "TEXT_PROMPT_TYPE_NUMBER": "solicitar número con el mensaje", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Solicitar al usuario un número.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Solicitar al usuario un texto.", - "LISTS_CREATE_EMPTY_TITLE": "crear lista vacía", - "LISTS_CREATE_EMPTY_TOOLTIP": "Devuelve una lista, de longitud 0, sin ningún dato", - "LISTS_CREATE_WITH_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_CREATE_WITH_TOOLTIP": "Crear una lista con cualquier número de elementos.", - "LISTS_CREATE_WITH_INPUT_WITH": "crear lista con", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "lista", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Agregar, eliminar o reorganizar las secciones para reconfigurar este bloque de lista.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Agregar un elemento a la lista.", - "LISTS_REPEAT_TOOLTIP": "Crea una lista que consta de un valor dado repetido el número de veces especificado.", - "LISTS_REPEAT_TITLE": "crear lista con el elemento %1 repetido %2 veces", - "LISTS_LENGTH_TITLE": "longitud de %1", - "LISTS_LENGTH_TOOLTIP": "Devuelve la longitud de una lista.", - "LISTS_ISEMPTY_TITLE": "%1 está vacía", - "LISTS_ISEMPTY_TOOLTIP": "Devuelve verdadero si la lista está vacía.", - "LISTS_INLIST": "en la lista", - "LISTS_INDEX_OF_FIRST": "encontrar la primera aparición del elemento", - "LISTS_INDEX_OF_LAST": "encontrar la última aparición del elemento", - "LISTS_INDEX_OF_TOOLTIP": "Devuelve el índice de la primera/última aparición del elemento en la lista. Devuelve %1 si el elemento no se encuentra.", - "LISTS_GET_INDEX_GET": "obtener", - "LISTS_GET_INDEX_GET_REMOVE": "obtener y eliminar", - "LISTS_GET_INDEX_REMOVE": "eliminar", - "LISTS_GET_INDEX_FROM_END": "# del final", - "LISTS_GET_INDEX_FIRST": "primero", - "LISTS_GET_INDEX_LAST": "último", - "LISTS_GET_INDEX_RANDOM": "aleatorio", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 es el primer elemento.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 es el último elemento.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Devuelve el elemento en la posición especificada en una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Devuelve el primer elemento de una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Devuelve el último elemento de una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Devuelve un elemento aleatorio en una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Elimina y devuelve el elemento en la posición especificada en una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Elimina y devuelve el primer elemento de una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Elimina y devuelve el último elemento de una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Elimina y devuelve un elemento aleatorio en una lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Elimina el elemento en la posición especificada en una lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Elimina el primer elemento de una lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Elimina el último elemento de una lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Elimina un elemento aleatorio en una lista.", - "LISTS_SET_INDEX_SET": "establecer", - "LISTS_SET_INDEX_INSERT": "insertar en", - "LISTS_SET_INDEX_INPUT_TO": "como", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Establece el elemento en la posición especificada en una lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Establece el primer elemento de una lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Establece el último elemento de una lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Establece un elemento aleatorio en una lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Inserta el elemento en la posición especificada en una lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Inserta el elemento al inicio de una lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Añade el elemento al final de una lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Inserta el elemento aleatoriamente en una lista.", - "LISTS_GET_SUBLIST_START_FROM_START": "obtener sublista desde #", - "LISTS_GET_SUBLIST_START_FROM_END": "obtener sublista desde # del final", - "LISTS_GET_SUBLIST_START_FIRST": "obtener sublista desde el primero", - "LISTS_GET_SUBLIST_END_FROM_START": "hasta #", - "LISTS_GET_SUBLIST_END_FROM_END": "hasta # del final", - "LISTS_GET_SUBLIST_END_LAST": "hasta el último", - "LISTS_GET_SUBLIST_TOOLTIP": "Crea una copia de la parte especificada de una lista.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "orden %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Ordenar una copia de una lista.", - "LISTS_SORT_ORDER_ASCENDING": "ascendente", - "LISTS_SORT_ORDER_DESCENDING": "descendente", - "LISTS_SORT_TYPE_NUMERIC": "numérico", - "LISTS_SORT_TYPE_TEXT": "alfabético", - "LISTS_SORT_TYPE_IGNORECASE": "alfabético, ignorar mayúscula/minúscula", - "LISTS_SPLIT_HELPURL": "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists", - "LISTS_SPLIT_LIST_FROM_TEXT": "hacer lista a partir de texto", - "LISTS_SPLIT_TEXT_FROM_LIST": "hacer texto a partir de lista", - "LISTS_SPLIT_WITH_DELIMITER": "con delimitador", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Dividir el texto en una lista de textos, separando en cada delimitador.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Unir una lista de textos en un solo texto, separado por un delimitador.", - "VARIABLES_GET_TOOLTIP": "Devuelve el valor de esta variable.", - "VARIABLES_GET_CREATE_SET": "Crear 'establecer %1'", - "VARIABLES_SET": "establecer %1 a %2", - "VARIABLES_SET_TOOLTIP": "Establece esta variable para que sea igual a la entrada.", - "VARIABLES_SET_CREATE_GET": "Crear 'obtener %1'", - "PROCEDURES_DEFNORETURN_TITLE": "para", - "PROCEDURES_DEFNORETURN_PROCEDURE": "hacer algo", - "PROCEDURES_BEFORE_PARAMS": "con:", - "PROCEDURES_CALL_BEFORE_PARAMS": "con:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Crea una función sin salida.", - "PROCEDURES_DEFNORETURN_COMMENT": "Describe esta función...", - "PROCEDURES_DEFRETURN_RETURN": "devuelve", - "PROCEDURES_DEFRETURN_TOOLTIP": "Crea una función con una salida.", - "PROCEDURES_ALLOW_STATEMENTS": "permitir declaraciones", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Advertencia: Esta función tiene parámetros duplicados.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://es.wikipedia.org/wiki/Subrutina", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Ejecuta la función definida por el usuario '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "https://es.wikipedia.org/wiki/Subrutina", - "PROCEDURES_CALLRETURN_TOOLTIP": "Ejecuta la función definida por el usuario '%1' y usa su salida.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "entradas", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Añadir, eliminar o reordenar entradas para esta función.", - "PROCEDURES_MUTATORARG_TITLE": "nombre de entrada:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Añadir una entrada a la función.", - "PROCEDURES_HIGHLIGHT_DEF": "Destacar definición de la función", - "PROCEDURES_CREATE_DO": "Crear '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Si un valor es verdadero, entonces devuelve un segundo valor.", - "PROCEDURES_IFRETURN_WARNING": "Advertencia: Este bloque solo puede ser utilizado dentro de la definición de una función." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/et.json b/backend/_pv_1_3_5/static/blockly/msg/json/et.json deleted file mode 100755 index 95663b95c..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/et.json +++ /dev/null @@ -1,310 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Aivarannamaa", - "Hasso" - ] - }, - "VARIABLES_DEFAULT_NAME": "objekt", - "TODAY": "Täna", - "DUPLICATE_BLOCK": "Tekita duplikaat", - "ADD_COMMENT": "Lisa kommentaar", - "REMOVE_COMMENT": "Eemalda kommentaar", - "EXTERNAL_INPUTS": "Sisendid ploki taga", - "INLINE_INPUTS": "Sisendid ploki sees", - "DELETE_BLOCK": "Kustuta plokk", - "DELETE_X_BLOCKS": "Kustuta %1 plokki", - "DELETE_ALL_BLOCKS": "Kas kustutada kõik %1 plokki?", - "CLEAN_UP": "Korista plokid kokku", - "COLLAPSE_BLOCK": "Tõmba plokk kokku", - "COLLAPSE_ALL": "Tõmba plokid kokku", - "EXPAND_BLOCK": "Laota plokk laiali", - "EXPAND_ALL": "Laota plokid laiali", - "DISABLE_BLOCK": "Keela ploki kasutamine", - "ENABLE_BLOCK": "Luba ploki kasutamine", - "HELP": "Abi", - "UNDO": "Võta tagasi", - "REDO": "Tee uuesti", - "CHANGE_VALUE_TITLE": "Muuda väärtust:", - "RENAME_VARIABLE": "Nimeta muutuja ümber ...", - "RENAME_VARIABLE_TITLE": "Muutuja „%1“ uus nimi:", - "NEW_VARIABLE": "Uus muutuja ...", - "NEW_VARIABLE_TITLE": "Uue muutuja nimi:", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "Valitud värv paletist.", - "COLOUR_RANDOM_TITLE": "juhuslik värv", - "COLOUR_RANDOM_TOOLTIP": "Juhuslikult valitud värv.", - "COLOUR_RGB_TITLE": "segu", - "COLOUR_RGB_RED": "punasest", - "COLOUR_RGB_GREEN": "rohelisest", - "COLOUR_RGB_BLUE": "sinisest", - "COLOUR_RGB_TOOLTIP": "Tekitab värvi määratud hulgast punasest, rohelisest ja sinisest. Kõik väärtused peavad olema 0 ja 100 vahel.", - "COLOUR_BLEND_TITLE": "segu", - "COLOUR_BLEND_COLOUR1": "1. värvist", - "COLOUR_BLEND_COLOUR2": "2. värvist", - "COLOUR_BLEND_RATIO": "suhtega", - "COLOUR_BLEND_TOOLTIP": "Segab kaks värvi määratud suhtega (0.0 - 1.0) kokku.", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "kordus %1 korda", - "CONTROLS_REPEAT_INPUT_DO": "käivita", - "CONTROLS_REPEAT_TOOLTIP": "Plokis olevate käskude käivitamine mitu korda.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "kordus kuni on", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "kordus kuni pole", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Kuni avaldis on tõene, korda plokis olevaid käske.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Kuni avaldis pole tõene, korda plokis olevaid käske.", - "CONTROLS_FOR_TOOLTIP": "Annab muutujale '%1' väärtused ühest numbrist teiseni, muutes seda intervalli kaupa ja käivitab igal muudatusel ploki sees oleva koodi.", - "CONTROLS_FOR_TITLE": "loenda muutujaga %1 alates %2 kuni %3 %4 kaupa", - "CONTROLS_FOREACH_TITLE": "iga elemendiga %1 loendis %2", - "CONTROLS_FOREACH_TOOLTIP": "Iga elemendiga loendis anna muutujale '%1' elemendi väärtus ja kõivita plokis olevad käsud.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "katkesta kordus", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "liigu järgmisele kordusele", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Katkestab korduse ja liigub edasi korduse järel oleva koodi käivitamisele.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Katkestab korduse sees oleva koodi käivitamise ja käivitab järgmise korduse.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Hoiatus: Seda plokki saab kasutada ainult korduse sees.", - "CONTROLS_IF_TOOLTIP_1": "Kui avaldis on tõene, käivita ploki sees olevad käsud.", - "CONTROLS_IF_TOOLTIP_2": "Kui avaldis on tõene, käivita käsud esimesest plokist. Vastasel juhul käivita käsud teisest plokist.", - "CONTROLS_IF_TOOLTIP_3": "Kui esimene avaldis on tõene, käivita käsud esimesest plokist. Vastasel juhul, kui teine avaldis on tõene, käivita käsud teisest plokist.", - "CONTROLS_IF_TOOLTIP_4": "Kui esimene avaldis on tõene, käivita käsud esimesest plokist. Vastasel juhul, kui teine avaldis on tõene, käivita käsud teisest plokist. Kui ükski avaldistest pole tõene, käivita käsud viimasest plokist.", - "CONTROLS_IF_MSG_IF": "kui", - "CONTROLS_IF_MSG_ELSEIF": "vastasel juhul, kui", - "CONTROLS_IF_MSG_ELSE": "vastasel juhul", - "CONTROLS_IF_IF_TOOLTIP": "Selle „kui“ ploki muutmine sektsioonide lisamise, eemaldamise ja järjestamisega.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Lisab „kui“ plokile tingimuse.", - "CONTROLS_IF_ELSE_TOOLTIP": "Lisab „kui“ plokile lõpliku tingimuseta koodiploki.", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Tagastab „tõene“, kui avaldiste väärtused on võrdsed.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Tagastab „tõene“, kui avaldiste väärtused pole võrdsed.", - "LOGIC_COMPARE_TOOLTIP_LT": "Tagastab „tõene“, kui esimese avaldise väärtus on väiksem kui teise väärtus.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Tagastab „tõene“, kui esimese avaldise väärtus on väiksem või võrdne teise väärtusega.", - "LOGIC_COMPARE_TOOLTIP_GT": "Tagastab „tõene“, kui esimese avaldise väärtus on suurem kui teise väärtus.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Tagastab „tõene“, kui esimese avaldise väärtus on suurem või võrdne teise väärtusega.", - "LOGIC_OPERATION_TOOLTIP_AND": "Tagastab „tõene“, kui mõlemad avaldised on tõesed.", - "LOGIC_OPERATION_AND": "ja", - "LOGIC_OPERATION_TOOLTIP_OR": "Tagastab „tõene“, kui vähemalt üks avaldistest on tõene.", - "LOGIC_OPERATION_OR": "või", - "LOGIC_NEGATE_TITLE": "pole %1", - "LOGIC_NEGATE_TOOLTIP": "Tagastab „tõene“, kui avaldis on väär. Tagastab „väär“, kui avaldis on tõene.", - "LOGIC_BOOLEAN_TRUE": "tõene", - "LOGIC_BOOLEAN_FALSE": "väär", - "LOGIC_BOOLEAN_TOOLTIP": "Tagastab tõeväärtuse – kas „tõene“ või „väär“.", - "LOGIC_NULL": "null", - "LOGIC_NULL_TOOLTIP": "Tagastab nulli.", - "LOGIC_TERNARY_CONDITION": "tingimus", - "LOGIC_TERNARY_IF_TRUE": "kui tõene", - "LOGIC_TERNARY_IF_FALSE": "kui väär", - "LOGIC_TERNARY_TOOLTIP": "Kui tingimuse väärtus on tõene, tagastab „kui tõene“ väärtuse, vastasel juhul „kui väär“ väärtuse.", - "MATH_NUMBER_HELPURL": "https://et.wikipedia.org/wiki/Arv", - "MATH_NUMBER_TOOLTIP": "Arv.", - "MATH_ARITHMETIC_HELPURL": "https://et.wikipedia.org/wiki/Aritmeetika", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Tagastab kahe arvu summa.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Tagastab kahe arvu vahe.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Tagastab kahe arvu korrutise.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Tagastab kahe arvu jagatise.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Tagastab esimese arvu teise arvu astmes.", - "MATH_SINGLE_HELPURL": "https://et.wikipedia.org/wiki/Ruutjuur", - "MATH_SINGLE_OP_ROOT": "ruutjuur", - "MATH_SINGLE_TOOLTIP_ROOT": "Tagastab arvu ruutjuure.", - "MATH_SINGLE_OP_ABSOLUTE": "absoluutväärtus", - "MATH_SINGLE_TOOLTIP_ABS": "Tagastab arvu absoluutväärtuse.", - "MATH_SINGLE_TOOLTIP_NEG": "Tagastab arvu vastandväärtuse.", - "MATH_SINGLE_TOOLTIP_LN": "Tagastab arvu naturaallogaritmi.", - "MATH_SINGLE_TOOLTIP_LOG10": "Tagastab arvu kümnendlogaritm.", - "MATH_SINGLE_TOOLTIP_EXP": "Tagasta e arvu astmes.", - "MATH_SINGLE_TOOLTIP_POW10": "Tagastab 10 arvu astmes.", - "MATH_TRIG_HELPURL": "https://et.wikipedia.org/wiki/Trigonomeetrilised_funktsioonid", - "MATH_TRIG_TOOLTIP_SIN": "Tagastab arvu (kraadid) siinuse.", - "MATH_TRIG_TOOLTIP_COS": "Tagastab arvu (kraadid) kosiinuse.", - "MATH_TRIG_TOOLTIP_TAN": "Tagastab arvu (kraadid) tangensi.", - "MATH_TRIG_TOOLTIP_ASIN": "Tagastab arvu arkussiinuse.", - "MATH_TRIG_TOOLTIP_ACOS": "Tagastab arvu arkuskoosiinuse.", - "MATH_TRIG_TOOLTIP_ATAN": "Tagastab arvu arkustangensi.", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "Tagastab ühe konstantidest: π (3,141…), e (2,718…), φ (1.618…), √2) (1,414…), √½ (0,707…), või ∞ (infinity).", - "MATH_IS_EVEN": "on paarisarv", - "MATH_IS_ODD": "on paaritu arv", - "MATH_IS_PRIME": "on algarv", - "MATH_IS_WHOLE": "on täisarv", - "MATH_IS_POSITIVE": "on positiivne arv", - "MATH_IS_NEGATIVE": "on negatiivne arv", - "MATH_IS_DIVISIBLE_BY": "jagub arvuga", - "MATH_IS_TOOLTIP": "Kontrollib kas arv on paarisarv, paaritu arv, algarv, täisarv, positiivne, negatiivne või jagub kindla arvuga. Tagastab „tõene“ või „väär“.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "muuda %1 %2 võrra", - "MATH_CHANGE_TOOLTIP": "Lisab arvu muutujale '%1'.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Ümardab arvu üles või alla.", - "MATH_ROUND_OPERATOR_ROUND": "ümarda", - "MATH_ROUND_OPERATOR_ROUNDUP": "ümarda üles", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "ümarda alla", - "MATH_ONLIST_OPERATOR_SUM": "loendi summa", - "MATH_ONLIST_TOOLTIP_SUM": "Tagastab kõigi loendis olevate arvude summa.", - "MATH_ONLIST_OPERATOR_MIN": "loendi miinimum", - "MATH_ONLIST_TOOLTIP_MIN": "Tagastab väikseima loendis oleva arvu.", - "MATH_ONLIST_OPERATOR_MAX": "loendi maksimum", - "MATH_ONLIST_TOOLTIP_MAX": "Tagastab suurima loendis oleva arvu.", - "MATH_ONLIST_OPERATOR_AVERAGE": "loendi keskmine", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Tagastab loendis olevate arvväärtuste aritmeetilise keskmise.", - "MATH_ONLIST_OPERATOR_MEDIAN": "loendi mediaan", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Return the median number in the list.", - "MATH_ONLIST_OPERATOR_MODE": "loendi moodid", - "MATH_ONLIST_TOOLTIP_MODE": "Tagastab loendi kõige sagedamini esinevate loendi liikmetega.", - "MATH_ONLIST_OPERATOR_STD_DEV": "loendi standardhälve", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Tagastab loendi standardhälbe.", - "MATH_ONLIST_OPERATOR_RANDOM": "juhuslik element loendist", - "MATH_ONLIST_TOOLTIP_RANDOM": "Tagastab juhusliku elemendi loendist.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "%1 ÷ %2 jääk", - "MATH_MODULO_TOOLTIP": "Tagastab esimese numbri teisega jagamisel tekkiva jäägi.", - "MATH_CONSTRAIN_TITLE": "%1 piirang %2 ja %3 vahele", - "MATH_CONSTRAIN_TOOLTIP": "Piirab arvu väärtuse toodud piiridesse (piirarvud kaasa arvatud).", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "juhuslik täisarv %1 ja %2 vahel", - "MATH_RANDOM_INT_TOOLTIP": "Tagastab juhusliku täisarvu toodud piiride vahel (piirarvud kaasa arvatud).", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "juhuslik murdosa", - "MATH_RANDOM_FLOAT_TOOLTIP": "Tagastab juhusliku murdosa 0.0 (kaasa arvatud) and 1.0 (välja arvatud) vahel.", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "Täht, sõna või rida teksti.", - "TEXT_JOIN_TITLE_CREATEWITH": "tekita tekst", - "TEXT_JOIN_TOOLTIP": "Tekitab teksti ühendades mistahes arvu elemente.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "ühenda", - "TEXT_CREATE_JOIN_TOOLTIP": "Tekstiploki muutmine sektsioonide lisamise, eemaldamise või järjestuse muutmisega.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Objekti lisamine tekstile.", - "TEXT_APPEND_TO": "lisa muutuja", - "TEXT_APPEND_APPENDTEXT": "lõppu tekst", - "TEXT_APPEND_TOOLTIP": "Lisab teksti muutuja „%1“ väärtuse lõppu.", - "TEXT_LENGTH_TITLE": "%1 pikkus", - "TEXT_LENGTH_TOOLTIP": "Tagastab sümbolite aru (ka tühikud) toodud tekstis.", - "TEXT_ISEMPTY_TITLE": "%1 on tühi", - "TEXT_ISEMPTY_TOOLTIP": "Tagastab „tõene“, kui tekstis pole ühtegi sümbolit.", - "TEXT_INDEXOF_TOOLTIP": "Tagastab esimesest tekstist esimese/viimase leitud teise teksti asukoha (indeksi). Kui teksti ei leita, tagastab %1.", - "TEXT_INDEXOF_INPUT_INTEXT": "tekstist", - "TEXT_INDEXOF_OPERATOR_FIRST": "esimese leitud tekstitüki", - "TEXT_INDEXOF_OPERATOR_LAST": "viimase leitud tekstitüki", - "TEXT_INDEXOF_TAIL": "asukoht", - "TEXT_CHARAT_INPUT_INTEXT": "tekstist", - "TEXT_CHARAT_FROM_START": "sümbol #", - "TEXT_CHARAT_FROM_END": "lõpust sümbol #", - "TEXT_CHARAT_FIRST": "esimene sümbol", - "TEXT_CHARAT_LAST": "viimane sümbol", - "TEXT_CHARAT_RANDOM": "juhuslik sümbol", - "TEXT_CHARAT_TOOLTIP": "Tagastab tekstis määratud asukohal oleva sümboli.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Tagastab määratud tüki tekstist.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "tekstist", - "TEXT_GET_SUBSTRING_START_FROM_START": "alates sümbolist #", - "TEXT_GET_SUBSTRING_START_FROM_END": "alates (lõpust) sümbolist #", - "TEXT_GET_SUBSTRING_START_FIRST": "alates esimesest sümbolist", - "TEXT_GET_SUBSTRING_END_FROM_START": "kuni sümbolini #", - "TEXT_GET_SUBSTRING_END_FROM_END": "kuni (lõpust) sümbolini #", - "TEXT_GET_SUBSTRING_END_LAST": "kuni viimase sümbolini", - "TEXT_CHANGECASE_TOOLTIP": "Tagastab muudetud tähesuurusega teksti koopia.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "SUURTE TÄHTEDEGA", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "väikeste tähtedega", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "Suurte Esitähtedega", - "TEXT_TRIM_TOOLTIP": "Tagastab koopia tekstist, millel on tühikud ühelt või mõlemalt poolt eemaldatud.", - "TEXT_TRIM_OPERATOR_BOTH": "mõlemalt poolt eemaldatud tühikutega", - "TEXT_TRIM_OPERATOR_LEFT": "algusest eemaldatud tühikutega", - "TEXT_TRIM_OPERATOR_RIGHT": "lõpust eemaldatud tühikutega", - "TEXT_PRINT_TITLE": "trüki %1", - "TEXT_PRINT_TOOLTIP": "Trükib määratud teksti, numbri või mõne muu objekti väärtuse.", - "TEXT_PROMPT_TYPE_TEXT": "kasutajalt küsitud tekst teatega", - "TEXT_PROMPT_TYPE_NUMBER": "kasutajalt küsitud arv teatega", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Küsib kasutajalt teadet näidates mingit arvu.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Küsib kasutajalt teadet näidates mingit teksti.", - "LISTS_CREATE_EMPTY_TITLE": "tühi loend", - "LISTS_CREATE_EMPTY_TOOLTIP": "Tagastab loendi, mille pikkus on 0 ja milles pole ühtegi elementi.", - "LISTS_CREATE_WITH_TOOLTIP": "Tekitab mistahes arvust elementidest loendi.", - "LISTS_CREATE_WITH_INPUT_WITH": "loend elementidest", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "loend", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Loendiploki elementide lisamine, eemaldamine või järjestuse muutmine.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Elemendi lisamine loendisse.", - "LISTS_REPEAT_TOOLTIP": "Tekitab uue loendi, millesse lisatakse ühte elementi pikkusega määratud arv kordi.", - "LISTS_REPEAT_TITLE": "loend pikkusega %2 elemendist %1", - "LISTS_LENGTH_TITLE": "%1 pikkus", - "LISTS_LENGTH_TOOLTIP": "Tagastab loendi pikkuse.", - "LISTS_ISEMPTY_TITLE": "%1 on tühi", - "LISTS_ISEMPTY_TOOLTIP": "Tagastab „tõene“ kui loend on tühi.", - "LISTS_INLIST": "loendis", - "LISTS_INDEX_OF_FIRST": "esimene leitud element", - "LISTS_INDEX_OF_LAST": "viimane leitud element", - "LISTS_INDEX_OF_TOOLTIP": "Tagastab esimese/viimase loendist leitud elemendi asukoha (järjekorranumbri). Kui elementi ei leita, tagastab %1.", - "LISTS_GET_INDEX_GET": "võta", - "LISTS_GET_INDEX_GET_REMOVE": "võta ja eemalda", - "LISTS_GET_INDEX_REMOVE": "eemalda", - "LISTS_GET_INDEX_FROM_END": "# lõpust", - "LISTS_GET_INDEX_FIRST": "esimene element", - "LISTS_GET_INDEX_LAST": "viimane element", - "LISTS_GET_INDEX_RANDOM": "juhuslik element", - "LISTS_INDEX_FROM_START_TOOLTIP": "Esimene element on %1.", - "LISTS_INDEX_FROM_END_TOOLTIP": "Viimane element on %1.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Tagastab loendis määratud asukohal oleva elemendi.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Tagastab loendi esimese elemendi.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Tagastab loendi viimase elemendi.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Tagastab loendi juhusliku elemendi.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Tagastab ja eemaldab loendist määratud asukohal oleva elemendi.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Tagastab ja eemaldab loendist esimese elemendi.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Tagastab ja eemaldab loendist viimase elemendi.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Tagastab ja eemaldab loendist juhusliku elemendi.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Eemaldab loendist määratud asukohal oleva elemendi.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Eemaldab loendist esimese elemendi.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Eemaldab loendist viimase elemendi.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Eemaldab loendist juhusliku elemendi.", - "LISTS_SET_INDEX_SET": "asenda", - "LISTS_SET_INDEX_INSERT": "lisa asukohale", - "LISTS_SET_INDEX_INPUT_TO": "väärtus:", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Asendab loendis määratud kohal oleva elemendi.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Asendab loendis esimese elemendi.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Asendab loendis viimase elemendi.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Asendab loendis juhusliku elemendi.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Lisab määratud asukohale loendis uue elemendi.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Lisab loendi algusesse uue elemendi.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Lisab loendi lõppu uue elemendi.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Lisab juhuslikule kohale loendis uue elemendi.", - "LISTS_GET_SUBLIST_START_FROM_START": "alamloend elemendist #", - "LISTS_GET_SUBLIST_START_FROM_END": "alamloend elemendist # (lõpust)", - "LISTS_GET_SUBLIST_START_FIRST": "alamloend algusest", - "LISTS_GET_SUBLIST_END_FROM_START": "elemendini #", - "LISTS_GET_SUBLIST_END_FROM_END": "elemendini # (lõpust)", - "LISTS_GET_SUBLIST_END_LAST": "lõpuni", - "LISTS_GET_SUBLIST_TOOLTIP": "Tekitab loendi määratud osast koopia.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "%1 %2 sorteeritud %3", - "LISTS_SORT_TOOLTIP": "Loendi koopia sorteerimine.", - "LISTS_SORT_ORDER_ASCENDING": "kasvavalt", - "LISTS_SORT_ORDER_DESCENDING": "kahanevalt", - "LISTS_SORT_TYPE_NUMERIC": "arvväärtuste järgi", - "LISTS_SORT_TYPE_TEXT": "tähestiku järgi", - "LISTS_SORT_TYPE_IGNORECASE": "tähestiku järgi (tähesuurust eirates)", - "LISTS_SPLIT_LIST_FROM_TEXT": "loend, tekitatud tekstist", - "LISTS_SPLIT_TEXT_FROM_LIST": "tekst, tekitatud loendist", - "LISTS_SPLIT_WITH_DELIMITER": "eraldajaga", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Tükeldab teksti eraldajade kohalt ja asetab tükid tekstide loendisse.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Ühendab tekstide loendis olevad tükid üheks tekstiks, asetades tükkide vahele eraldaja.", - "VARIABLES_GET_TOOLTIP": "Tagastab selle muutuja väärtuse.", - "VARIABLES_GET_CREATE_SET": "Tekita 'määra „%1“ väärtuseks' plokk", - "VARIABLES_SET": "\"määra %1 väärtuseks %2", - "VARIABLES_SET_TOOLTIP": "Määrab selle muutuja väärtuse võrdseks sisendi väärtusega.", - "VARIABLES_SET_CREATE_GET": "Tekita '„%1“ väärtus' plokk", - "PROCEDURES_DEFNORETURN_TITLE": "funktsioon", - "PROCEDURES_DEFNORETURN_PROCEDURE": "teeme midagi", - "PROCEDURES_BEFORE_PARAMS": "sisenditega:", - "PROCEDURES_CALL_BEFORE_PARAMS": "sisenditega:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Tekitab funktsiooni, mis ei tagasta midagi.", - "PROCEDURES_DEFNORETURN_COMMENT": "Funktsiooni kirjeldus ...", - "PROCEDURES_DEFRETURN_RETURN": "tagasta", - "PROCEDURES_DEFRETURN_TOOLTIP": "Tekitab funktsiooni, mis tagastab midagi.", - "PROCEDURES_ALLOW_STATEMENTS": "kood plokis", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Hoiatus: Sel funktsioonil on mitu sama nimega sisendit.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Käivitab kasutaja defineeritud funktsiooni '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Run the user-defined function '%1' and use its output.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "sisendid", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Funktsiooni sisendite lisamine, eemaldamine või järjestuse muutmine.", - "PROCEDURES_MUTATORARG_TITLE": "sisend nimega:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Lisab funktsioonile sisendi.", - "PROCEDURES_HIGHLIGHT_DEF": "Tõsta funktsiooni definitsioon esile", - "PROCEDURES_CREATE_DO": "Tekita '%1' plokk", - "PROCEDURES_IFRETURN_TOOLTIP": "Kui väärtus on tõene, tagastatakse teine väärtus.", - "PROCEDURES_IFRETURN_WARNING": "Hoiatus: Seda plokki saab kasutada ainult funktsiooni definitsioonis." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/fa.json b/backend/_pv_1_3_5/static/blockly/msg/json/fa.json deleted file mode 100755 index 80c55a81b..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/fa.json +++ /dev/null @@ -1,309 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Ebraminio", - "Reza1615", - "Alirezaaa", - "Mehran", - "MohandesWiki", - "Dalba", - "Hamisun" - ] - }, - "VARIABLES_DEFAULT_NAME": "مورد", - "TODAY": "امروز", - "DUPLICATE_BLOCK": "تکراری", - "ADD_COMMENT": "افزودن نظر", - "REMOVE_COMMENT": "حذف نظر", - "EXTERNAL_INPUTS": "ورودی‌های خارجی", - "INLINE_INPUTS": "ورودی‌های درون خطی", - "DELETE_BLOCK": "حذف بلوک", - "DELETE_X_BLOCKS": "حذف بلوک‌های %1", - "DELETE_ALL_BLOCKS": "حذف همهٔ بلاک‌های %1؟", - "CLEAN_UP": "تمیز کردن بلوک‌ها", - "COLLAPSE_BLOCK": "فروپاشی بلوک", - "COLLAPSE_ALL": "فروپاشی بلوک‌ها", - "EXPAND_BLOCK": "گسترش بلوک", - "EXPAND_ALL": "گسترش بلوک‌ها", - "DISABLE_BLOCK": "غیرفعال‌سازی بلوک", - "ENABLE_BLOCK": "فعال‌سازی بلوک", - "HELP": "راهنما", - "UNDO": "واگردانی", - "REDO": "واگردانی", - "CHANGE_VALUE_TITLE": "تغییر مقدار:", - "RENAME_VARIABLE": "تغییر نام متغیر...", - "RENAME_VARIABLE_TITLE": "تغییر نام همهٔ متغیرهای «%1» به:", - "NEW_VARIABLE": "متغیر تازه...", - "NEW_VARIABLE_TITLE": "نام متغیر تازه:", - "COLOUR_PICKER_HELPURL": "https://fa.wikipedia.org/wiki/%D8%B1%D9%86%DA%AF", - "COLOUR_PICKER_TOOLTIP": "انتخاب یک رنگ از تخته‌رنگ.", - "COLOUR_RANDOM_TITLE": "رنگ تصادفی", - "COLOUR_RANDOM_TOOLTIP": "انتخاب یک رنگ به شکل تصادفی.", - "COLOUR_RGB_TITLE": "رنگ با", - "COLOUR_RGB_RED": "قرمز", - "COLOUR_RGB_GREEN": "سبز", - "COLOUR_RGB_BLUE": "آبی", - "COLOUR_RGB_TOOLTIP": "ساخت یک رنگ با مقدار مشخص‌شده‌ای از قرمز، سبز و آبی. همهٔ مقادیر باید بین ۰ تا ۱۰۰ باشند.", - "COLOUR_BLEND_TITLE": "مخلوط", - "COLOUR_BLEND_COLOUR1": "رنگ ۱", - "COLOUR_BLEND_COLOUR2": "رنگ ۲", - "COLOUR_BLEND_RATIO": "نسبت", - "COLOUR_BLEND_TOOLTIP": "دو رنگ را با نسبت مشخص‌شده مخلوط می‌کند (۰٫۰ - ۱٫۰)", - "CONTROLS_REPEAT_HELPURL": "https://fa.wikipedia.org/wiki/%D8%AD%D9%84%D9%82%D9%87_%D9%81%D9%88%D8%B1", - "CONTROLS_REPEAT_TITLE": "%1 بار تکرار", - "CONTROLS_REPEAT_INPUT_DO": "انحام", - "CONTROLS_REPEAT_TOOLTIP": "انجام چند عبارت چندین بار.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "تکرار در حالی که", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "تکرار تا زمانی که", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "تا زمانی که یک مقدار صحیح است، چند عبارت را انجام بده.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "تا زمانی که یک مقدار ناصحیح است، چند عبارت را انجام بده.", - "CONTROLS_FOR_TOOLTIP": "متغیر %1 را در مقادیر شروع‌شده از عدد انتهای به عدد انتهایی را دارد، با فواصل مشخص‌شده می‌شمارد و این بلوک مشخص‌شده را انجام می‌دهد.", - "CONTROLS_FOR_TITLE": "با تعداد %1 از %2 به %3 با گام‌های %4", - "CONTROLS_FOREACH_TITLE": "برای هر مورد %1 در فهرست %2", - "CONTROLS_FOREACH_TOOLTIP": "برای هر مورد در این فهرست، تنظیم متغیر «%1» به مورد و انجام تعدادی عبارت.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "شکستن حلقه", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "ادامه با تکرار بعدی حلقه", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "شکستن حلقهٔ شامل.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "پریدن از بقیهٔ حلقه و ادامه با تکرار بعدی.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "اخطار: این بلوک ممکن است فقط داخل یک حلقه استفاده شود.", - "CONTROLS_IF_TOOLTIP_1": "اگر یک مقدار صحیح است، سپس چند عبارت را انجام بده.", - "CONTROLS_IF_TOOLTIP_2": "اگر یک مقدار صحیح است، اول بلوک اول عبارات را انجام بده. در غیر این صورت بلوک دوم عبارات انجام بده.", - "CONTROLS_IF_TOOLTIP_3": "اگر مقدار اول صحیح بود، از آن بلوک اول عبارات را انجام بده. در غیر این صورت، اگر مقدار دوم صحیح است، بلوک دوم عبارات را انجام بده.", - "CONTROLS_IF_TOOLTIP_4": "اگر مقدار اول درست است، بلوک اول عبارات را انجام بده. در غیر این صورت، اگر مقدار دوم درست باشد بلوک دوم عبارات را انجام بده. اگر هیچ از مقادیر درست نبود، آخرین بلوک عبارات را انجام بده.", - "CONTROLS_IF_MSG_IF": "اگر", - "CONTROLS_IF_MSG_ELSEIF": "اگر آنگاه", - "CONTROLS_IF_MSG_ELSE": "آنگاه", - "CONTROLS_IF_IF_TOOLTIP": "افزودن، حذف یا بازمرتب‌سازی قسمت‌ها برای پیکربندی دوبارهٔ این بلوک اگر.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "افزودن یک شرط به بلوک اگر.", - "CONTROLS_IF_ELSE_TOOLTIP": "اضافه کردن نهایی، گرفتن همهٔ شرایط به بلوک اگر.", - "LOGIC_COMPARE_HELPURL": "https://fa.wikipedia.org/wiki/%D9%86%D8%A7%D8%A8%D8%B1%D8%A7%D8%A8%D8%B1%DB%8C", - "LOGIC_COMPARE_TOOLTIP_EQ": "بازگشت صحیح اگر هر دو ورودی با یکدیگر برابر باشد.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "برگرداندن صحیح اگر هر دو ورودی با یکدیگر برابر نباشند.", - "LOGIC_COMPARE_TOOLTIP_LT": "بازگرداندن صحیح اگر ورودی اول کوچکتر از ورودی دوم باشد.", - "LOGIC_COMPARE_TOOLTIP_LTE": "بازگرداندن صحیح اگر ورودی اول کوچکتر یا مساوی با ورودی دوم باشد.", - "LOGIC_COMPARE_TOOLTIP_GT": "بازگرداندن صحیح اگر ورودی اول بزرگتر از ورودی دوم باشد.", - "LOGIC_COMPARE_TOOLTIP_GTE": "بازگرداندن صحیح اگر ورودی اول بزرگتر یا مساوی یا ورودی دوم باشد.", - "LOGIC_OPERATION_TOOLTIP_AND": "بازگرداندن صحیح اگر هر دو ورودی صحیح باشد.", - "LOGIC_OPERATION_AND": "و", - "LOGIC_OPERATION_TOOLTIP_OR": "بازگرداندن صحیح اگر یکی از دو ورودی صحیح باشد.", - "LOGIC_OPERATION_OR": "یا", - "LOGIC_NEGATE_TITLE": "نه %1", - "LOGIC_NEGATE_TOOLTIP": "صجیج باز می‌گرداند اگر ورودی نا صحیح باشند. ناصحیح بازمی‌گرداند اگر ورودی صحیح باشد.", - "LOGIC_BOOLEAN_TRUE": "صحیح", - "LOGIC_BOOLEAN_FALSE": "ناصحیح", - "LOGIC_BOOLEAN_TOOLTIP": "بازگرداندن یکی از صحیح یا ناصحیح.", - "LOGIC_NULL": "تهی", - "LOGIC_NULL_TOOLTIP": "تهی بازمی‌گرداند.", - "LOGIC_TERNARY_CONDITION": "آزمایش", - "LOGIC_TERNARY_IF_TRUE": "اگر صحیح", - "LOGIC_TERNARY_IF_FALSE": "اگر ناصحیح", - "LOGIC_TERNARY_TOOLTIP": "بررسی وضعیت در «آزمایش». اگر وضعیت صحیح باشد، مقدار «اگر صحیح» را بر می‌گرداند در غیر اینصورت مقدار «اگر ناصحیح» را.", - "MATH_NUMBER_HELPURL": "https://fa.wikipedia.org/wiki/%D8%B9%D8%AF%D8%AF", - "MATH_NUMBER_TOOLTIP": "یک عدد.", - "MATH_ARITHMETIC_HELPURL": "https://fa.wikipedia.org/wiki/%D8%AD%D8%B3%D8%A7%D8%A8", - "MATH_ARITHMETIC_TOOLTIP_ADD": "بازگرداندن مقدار جمع دو عدد.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "بازگرداندن تفاوت دو عدد.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "بازگرداندن حاصلضرب دو عدد.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "بازگرداندن باقی‌ماندهٔ دو عدد.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "بازگرداندن اولین عددی که از توان عدد دوم حاصل شده باشد.", - "MATH_SINGLE_HELPURL": "https://fa.wikipedia.org/wiki/%D8%B1%DB%8C%D8%B4%D9%87_%D8%AF%D9%88%D9%85", - "MATH_SINGLE_OP_ROOT": "ریشهٔ دوم", - "MATH_SINGLE_TOOLTIP_ROOT": "ریشهٔ دوم یک عدد را باز می‌گرداند.", - "MATH_SINGLE_OP_ABSOLUTE": "مطلق", - "MATH_SINGLE_TOOLTIP_ABS": "قدر مطلق یک عدد را بازمی‌گرداند.", - "MATH_SINGLE_TOOLTIP_NEG": "منفی‌شدهٔ یک عدد را باز می‌گرداند.", - "MATH_SINGLE_TOOLTIP_LN": "لوگاریتم طبیعی یک عدد را باز می‌گرداند.", - "MATH_SINGLE_TOOLTIP_LOG10": "بازگرداندن لگاریتم بر پایهٔ ۱۰ یک عدد.", - "MATH_SINGLE_TOOLTIP_EXP": "بازگرداندن توان e یک عدد.", - "MATH_SINGLE_TOOLTIP_POW10": "بازگرداندن توان ۱۰ یک عدد.", - "MATH_TRIG_HELPURL": "https://fa.wikipedia.org/wiki/%D8%AA%D8%A7%D8%A8%D8%B9%E2%80%8C%D9%87%D8%A7%DB%8C_%D9%85%D8%AB%D9%84%D8%AB%D8%A7%D8%AA%DB%8C", - "MATH_TRIG_TOOLTIP_SIN": "بازگرداندن سینوس درجه (نه رادیان).", - "MATH_TRIG_TOOLTIP_COS": "بازگرداندن کسینوس درجه (نه رادیان).", - "MATH_TRIG_TOOLTIP_TAN": "بازگرداندن تانژانت یک درجه (نه رادیان).", - "MATH_TRIG_TOOLTIP_ASIN": "بازگرداندن آرک‌سینوس درجه (نه رادیان).", - "MATH_TRIG_TOOLTIP_ACOS": "بازگرداندن آرک‌کسینوس درجه (نه رادیان).", - "MATH_TRIG_TOOLTIP_ATAN": "بازگرداندن آرک‌تانژانت درجه (نه رادیان).", - "MATH_CONSTANT_HELPURL": "https://fa.wikipedia.org/wiki/%D8%AB%D8%A7%D8%A8%D8%AA_%D8%B1%DB%8C%D8%A7%D8%B6%DB%8C", - "MATH_CONSTANT_TOOLTIP": "یکی از مقادیر مشترک را برمی‌گرداند: π (۳٫۱۴۱…)، e (۲٫۷۱۸...)، φ (۱٫۶۱۸)، sqrt(۲) (۱٫۴۱۴)، sqrt(۱/۲) (۰٫۷۰۷...) و یا ∞ (بی‌نهایت).", - "MATH_IS_EVEN": "زوج است", - "MATH_IS_ODD": "فرد است", - "MATH_IS_PRIME": "عدد اول است", - "MATH_IS_WHOLE": "کامل است", - "MATH_IS_POSITIVE": "مثبت است", - "MATH_IS_NEGATIVE": "منفی است", - "MATH_IS_DIVISIBLE_BY": "تقسیم شده بر", - "MATH_IS_TOOLTIP": "بررسی می‌کند که آیا یک عدد زوج، فرد، اول، کامل، مثبت، منفی یا بخش‌پذیر عدد خاصی باشد را بررسی می‌کند. درست یا نادرست باز می‌گرداند.", - "MATH_CHANGE_HELPURL": "https://fa.wikipedia.org/wiki/%D8%A7%D8%B5%D8%B7%D9%84%D8%A7%D8%AD_%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87%E2%80%8C%D9%86%D9%88%DB%8C%D8%B3%DB%8C#.D8.A7.D9.81.D8.B2.D8.A7.DB.8C.D8.B4_.D8.B4.D9.85.D8.A7.D8.B1.D9.86.D8.AF.D9.87", - "MATH_CHANGE_TITLE": "تغییر %1 با %2", - "MATH_CHANGE_TOOLTIP": "افزودن یک عدد به متغیر '%1'.", - "MATH_ROUND_HELPURL": "https://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29", - "MATH_ROUND_TOOLTIP": "گردکردن یک عدد به بالا یا پایین.", - "MATH_ROUND_OPERATOR_ROUND": "گردکردن", - "MATH_ROUND_OPERATOR_ROUNDUP": "گرد به بالا", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "گرد به پایین", - "MATH_ONLIST_OPERATOR_SUM": "جمع فهرست", - "MATH_ONLIST_TOOLTIP_SUM": "جمع همهٔ عددهای فهرست را باز می‌گرداند.", - "MATH_ONLIST_OPERATOR_MIN": "کوچکترین فهرست", - "MATH_ONLIST_TOOLTIP_MIN": "کوچک‌ترین عدد در فهرست را باز می‌گرداند.", - "MATH_ONLIST_OPERATOR_MAX": "بزرگ‌ترین فهرست", - "MATH_ONLIST_TOOLTIP_MAX": "بزرگ‌ترین عدد در فهرست را باز می‌گرداند.", - "MATH_ONLIST_OPERATOR_AVERAGE": "میانگین فهرست", - "MATH_ONLIST_TOOLTIP_AVERAGE": "میانگین (میانگین ریاضی) مقادیر عددی فهرست را بر می‌گرداند.", - "MATH_ONLIST_OPERATOR_MEDIAN": "میانهٔ فهرست", - "MATH_ONLIST_TOOLTIP_MEDIAN": "میانهٔ عدد در فهرست را بر می‌گرداند.", - "MATH_ONLIST_OPERATOR_MODE": "مد فهرست", - "MATH_ONLIST_TOOLTIP_MODE": "شایع‌ترین قلم(های) در فهرست را بر می‌گرداند.", - "MATH_ONLIST_OPERATOR_STD_DEV": "انحراف معیار فهرست", - "MATH_ONLIST_TOOLTIP_STD_DEV": "انحراف معیار فهرست را بر می‌گرداند.", - "MATH_ONLIST_OPERATOR_RANDOM": "مورد تصادفی از فهرست", - "MATH_ONLIST_TOOLTIP_RANDOM": "موردی تصادفی از فهرست را بر می‌گرداند.", - "MATH_MODULO_HELPURL": "https://fa.wikipedia.org/wiki/%D8%B9%D9%85%D9%84%DB%8C%D8%A7%D8%AA_%D9%BE%DB%8C%D9%85%D8%A7%D9%86%D9%87", - "MATH_MODULO_TITLE": "باقی‌ماندهٔ %1 + %2", - "MATH_MODULO_TOOLTIP": "باقی‌ماندهٔ تقسیم دو عدد را بر می‌گرداند.", - "MATH_CONSTRAIN_TITLE": "محدودکردن %1 پایین %2 بالا %3", - "MATH_CONSTRAIN_TOOLTIP": "محدودکردن یک عدد بین محدودیت‌های مشخص‌شده (بسته).", - "MATH_RANDOM_INT_HELPURL": "https://fa.wikipedia.org/wiki/%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D8%A7%D8%B9%D8%AF%D8%A7%D8%AF_%D8%AA%D8%B5%D8%A7%D8%AF%D9%81%DB%8C", - "MATH_RANDOM_INT_TITLE": "عدد صحیح تصادفی بین %1 تا %2", - "MATH_RANDOM_INT_TOOLTIP": "یک عدد تصادفی بین دو مقدار مشخص‌شده به صورت بسته باز می‌گرداند.", - "MATH_RANDOM_FLOAT_HELPURL": "https://fa.wikipedia.org/wiki/%D8%AA%D9%88%D9%84%DB%8C%D8%AF_%D8%A7%D8%B9%D8%AF%D8%A7%D8%AF_%D8%AA%D8%B5%D8%A7%D8%AF%D9%81%DB%8C", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "کسر تصادفی", - "MATH_RANDOM_FLOAT_TOOLTIP": "بازگرداندن کسری تصادفی بین ۰٫۰ (بسته) تا ۱٫۰ (باز).", - "TEXT_TEXT_HELPURL": "https://fa.wikipedia.org/wiki/%D8%B1%D8%B4%D8%AA%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29", - "TEXT_TEXT_TOOLTIP": "یک حرف، کلمه یا خطی از متن.", - "TEXT_JOIN_TITLE_CREATEWITH": "ایجاد متن با", - "TEXT_JOIN_TOOLTIP": "یک تکه‌ای از متن را با چسپاندن همهٔ تعداد از موارد ایجاد می‌کند.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "عضویت", - "TEXT_CREATE_JOIN_TOOLTIP": "اضافه کردن، حذف یا مرتب‌سازی بحش‌ها برای تنظیم مجدد این بلوک متنی.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "افزودن یک مورد به متن.", - "TEXT_APPEND_TO": "به", - "TEXT_APPEND_APPENDTEXT": "الحاق متن", - "TEXT_APPEND_TOOLTIP": "الحاق متنی به متغیر «%1».", - "TEXT_LENGTH_TITLE": "طول %1", - "TEXT_LENGTH_TOOLTIP": "بازگرداندن عددی از حروف (شامل فاصله‌ها) در متن فراهم‌شده.", - "TEXT_ISEMPTY_TITLE": "%1 خالی است", - "TEXT_ISEMPTY_TOOLTIP": "اضافه کردن صحیح اگر متن فراهم‌شده خالی است.", - "TEXT_INDEXOF_TOOLTIP": "شاخصی از اولین آخرین رخ‌داد متن اول در متن دوم بر می‌گرداند. اگر متن یافت نشد %1 باز می‌گرداند.", - "TEXT_INDEXOF_INPUT_INTEXT": "در متن", - "TEXT_INDEXOF_OPERATOR_FIRST": "اولین رخداد متن را بیاب", - "TEXT_INDEXOF_OPERATOR_LAST": "آخرین رخداد متن را بیاب", - "TEXT_CHARAT_INPUT_INTEXT": "در متن", - "TEXT_CHARAT_FROM_START": "گرفتن حرف #", - "TEXT_CHARAT_FROM_END": "گرفتن حرف # از آخر", - "TEXT_CHARAT_FIRST": "گرفتن اولین حرف", - "TEXT_CHARAT_LAST": "گرفتن آخرین حرف", - "TEXT_CHARAT_RANDOM": "گرفتن حرف تصادفی", - "TEXT_CHARAT_TOOLTIP": "حرفی در موقعیت مشخص‌شده بر می‌گرداند.", - "TEXT_GET_SUBSTRING_TOOLTIP": "قسمت مشخصی‌شده‌ای از متن را بر می‌گرداند.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "در متن", - "TEXT_GET_SUBSTRING_START_FROM_START": "گرفتن زیرمتن از حرف #", - "TEXT_GET_SUBSTRING_START_FROM_END": "گرفتن زیرمتن از حرف # به انتها", - "TEXT_GET_SUBSTRING_START_FIRST": "گرفتن زیرمتن از اولین حرف", - "TEXT_GET_SUBSTRING_END_FROM_START": "به حرف #", - "TEXT_GET_SUBSTRING_END_FROM_END": "به حرف # از انتها", - "TEXT_GET_SUBSTRING_END_LAST": "به آخرین حرف", - "TEXT_CHANGECASE_TOOLTIP": "بازگرداندن کپی متن در حالتی متفاوت.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "به حروف بزرگ", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "به حروف کوچک", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "به حروف بزرگ عنوان", - "TEXT_TRIM_TOOLTIP": "کپی از متن با فاصله‌های حذف‌شده از یک یا هر دو پایان باز می‌گرداند.", - "TEXT_TRIM_OPERATOR_BOTH": "تراشیدن فاصله‌ها از هر دو طرف", - "TEXT_TRIM_OPERATOR_LEFT": "تراشیدن فاصله‌ها از طرف چپ", - "TEXT_TRIM_OPERATOR_RIGHT": "تراشیدن فاصله‌ها از طرف چپ", - "TEXT_PRINT_TITLE": "چاپ %1", - "TEXT_PRINT_TOOLTIP": "چاپ متن، عدد یا هر مقدار دیگر مشخص‌شده.", - "TEXT_PROMPT_TYPE_TEXT": "اعلان برای متن با پیام", - "TEXT_PROMPT_TYPE_NUMBER": "اعلان برای عدد با پیام", - "TEXT_PROMPT_TOOLTIP_NUMBER": "اعلان برای کاربر با یک عدد.", - "TEXT_PROMPT_TOOLTIP_TEXT": "اعلان برای کاربر برای یک متن.", - "LISTS_CREATE_EMPTY_TITLE": "ایجاد فهرست خالی", - "LISTS_CREATE_EMPTY_TOOLTIP": "فهرستی با طول صفر شامل هیچ رکورد داده‌ای بر می‌گرداند.", - "LISTS_CREATE_WITH_TOOLTIP": "فهرستی از هر عددی از موارد می‌سازد.", - "LISTS_CREATE_WITH_INPUT_WITH": "ایجاد فهرست با", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "فهرست", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "اضافه کردن، حذف کردن یا ترتیب‌سازی مجدد بخش‌ها این بلوک فهرستی.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "اضافه کردن یک مورد به فهرست.", - "LISTS_REPEAT_TOOLTIP": "فهرستی شامل مقادیر داده‌شدهٔ تکرار شده عدد مشخص‌شده می‌سازد.", - "LISTS_REPEAT_TITLE": "فهرستی با %1 تکرارشده به اندازهٔ %2 می‌سازد", - "LISTS_LENGTH_TITLE": "طول %1", - "LISTS_LENGTH_TOOLTIP": "طول یک فهرست را برمی‌گرداند.", - "LISTS_ISEMPTY_TITLE": "%1 خالی است", - "LISTS_ISEMPTY_TOOLTIP": "اگر فهرست خالی است مقدار صجیج بر می‌گرداند.", - "LISTS_INLIST": "در فهرست", - "LISTS_INDEX_OF_FIRST": "یافتن اولین رخ‌داد مورد", - "LISTS_INDEX_OF_LAST": "یافتن آخرین رخ‌داد مورد", - "LISTS_INDEX_OF_TOOLTIP": "شاخصی از اولین/آخرین رخ‌داد مورد در فهرست را بر می‌گرداند. %1 بر می‌گرداند اگر آیتم موجود نبود.", - "LISTS_GET_INDEX_GET": "گرفتن", - "LISTS_GET_INDEX_GET_REMOVE": "گرفتن و حذف‌کردن", - "LISTS_GET_INDEX_REMOVE": "حذف‌کردن", - "LISTS_GET_INDEX_FROM_END": "# از انتها", - "LISTS_GET_INDEX_FIRST": "اولین", - "LISTS_GET_INDEX_LAST": "آخرین", - "LISTS_GET_INDEX_RANDOM": "تصادفی", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 اولین مورد است.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 آخرین مورد است.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "موردی در محل مشخص‌شده بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "اولین مورد یک فهرست را بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "آخرین مورد در یک فهرست را بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "یک مورد تصادفی در یک فهرست بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "مورد در محل مشخص‌شده در فهرست را حذف و بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "اولین مورد مشخص‌شده در فهرست را حذف و بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "آخرین مورد مشخص‌شده در فهرست را حذف و بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "مورد تصادفی‌ای را در فهرست حذف و بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "مورد مشخص‌شده در موقعیت مشخص در یک فهرست را حذف و بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "اولین مورد را در یک فهرست حذف می‌کند.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "آخرین مورد را در یک فهرست حذف می‌کند.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "یک مورد تصادفی را یک فهرست حذف می‌کند.", - "LISTS_SET_INDEX_SET": "مجموعه", - "LISTS_SET_INDEX_INSERT": "درج در", - "LISTS_SET_INDEX_INPUT_TO": "به عنوان", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "مورد مشخص‌شده در یک فهرست را قرار می‌دهد.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "اولین مورد در یک فهرست را تعیین می‌کند.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "آخرین مورد در یک فهرست را تعیین می‌کند.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "یک مورد تصادفی در یک فهرست را تعیین می‌کند.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "موردی در موقعیت مشخص‌شده در یک فهرست اضافه می‌کند.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "موردی به ته فهرست اضافه می‌کند.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "موردی به ته فهرست الحاق می‌کند.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "مورد را به صورت تصادفی در یک فهرست می‌افزاید.", - "LISTS_GET_SUBLIST_START_FROM_START": "گرفتن زیرمجموعه‌ای از #", - "LISTS_GET_SUBLIST_START_FROM_END": "گرفتن زیرمجموعه‌ای از # از انتها", - "LISTS_GET_SUBLIST_START_FIRST": "گرفتن زیرمجموعه‌ای از ابتدا", - "LISTS_GET_SUBLIST_END_FROM_START": "به #", - "LISTS_GET_SUBLIST_END_FROM_END": "به # از انتها", - "LISTS_GET_SUBLIST_END_LAST": "به آخرین", - "LISTS_GET_SUBLIST_TOOLTIP": "کپی از قسمت مشخص‌شدهٔ لیست درست می‌کند.", - "LISTS_SORT_ORDER_ASCENDING": "صعودی", - "LISTS_SORT_ORDER_DESCENDING": "نزولی", - "LISTS_SORT_TYPE_NUMERIC": "عددی", - "LISTS_SORT_TYPE_TEXT": "حروفی ، الفبایی", - "LISTS_SORT_TYPE_IGNORECASE": "حروفی ، رد کردن مورد", - "LISTS_SPLIT_LIST_FROM_TEXT": "ایجاد فهرست از متن", - "LISTS_SPLIT_TEXT_FROM_LIST": "ایجاد متن از فهرست", - "LISTS_SPLIT_WITH_DELIMITER": "همراه جداساز", - "VARIABLES_GET_TOOLTIP": "مقدار این متغیر را بر می‌گرداند.", - "VARIABLES_GET_CREATE_SET": "درست‌کردن «تنظیم %1»", - "VARIABLES_SET": "مجموعه %1 به %2", - "VARIABLES_SET_TOOLTIP": "متغیر برابر با خروجی را مشخص می‌کند.", - "VARIABLES_SET_CREATE_GET": "درست‌کردن «گرفتن %1»", - "PROCEDURES_DEFNORETURN_TITLE": "به", - "PROCEDURES_DEFNORETURN_PROCEDURE": "انجام چیزی", - "PROCEDURES_BEFORE_PARAMS": "با:", - "PROCEDURES_CALL_BEFORE_PARAMS": "با:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "تابعی می‌سازد بدون هیچ خروجی.", - "PROCEDURES_DEFNORETURN_COMMENT": "توصیف این عملکرد...", - "PROCEDURES_DEFRETURN_RETURN": "بازگشت", - "PROCEDURES_DEFRETURN_TOOLTIP": "تابعی با یک خروجی می‌سازد.", - "PROCEDURES_ALLOW_STATEMENTS": "اجازه اظهارات", - "PROCEDURES_DEF_DUPLICATE_WARNING": "اخطار: این تابعی پارامتر تکراری دارد.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "اجرای تابع تعریف‌شده توسط کاربر «%1».", - "PROCEDURES_CALLRETURN_HELPURL": "https://fa.wikipedia.org/wiki/%D8%B1%D9%88%DB%8C%D9%87_%28%D8%B9%D9%84%D9%88%D9%85_%D8%B1%D8%A7%DB%8C%D8%A7%D9%86%D9%87%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "اجرای تابع تعریف‌شده توسط کاربر «%1» و استفاده از خروجی آن.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "ورودی‌ها", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "افزودن، حذف یا دوباره مرتب‌کردن ورودی این تابع.", - "PROCEDURES_MUTATORARG_TITLE": "نام ورودی:", - "PROCEDURES_MUTATORARG_TOOLTIP": "اضافه کردن ورودی به تابع.", - "PROCEDURES_HIGHLIGHT_DEF": "برجسته‌سازی تعریف تابع", - "PROCEDURES_CREATE_DO": "ساختن «%1»", - "PROCEDURES_IFRETURN_TOOLTIP": "اگر یک مقدار صحیح است، مقدار دوم را برگردان.", - "PROCEDURES_IFRETURN_WARNING": "اخطار: این بلوک احتمالاً فقط داخل یک تابع استفاده می‌شود." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/fi.json b/backend/_pv_1_3_5/static/blockly/msg/json/fi.json deleted file mode 100755 index b8b196981..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/fi.json +++ /dev/null @@ -1,330 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Nike", - "Silvonen", - "Espertus", - "Pettevi", - "McSalama", - "Espeox", - "SNuutti", - "PStudios", - "Mikahama" - ] - }, - "VARIABLES_DEFAULT_NAME": "kohde", - "TODAY": "Tänään", - "DUPLICATE_BLOCK": "Kopioi", - "ADD_COMMENT": "Lisää kommentti", - "REMOVE_COMMENT": "Poista kommentti", - "EXTERNAL_INPUTS": "Ulkoiset syötteet", - "INLINE_INPUTS": "Tuo syötteet", - "DELETE_BLOCK": "Poista lohko", - "DELETE_X_BLOCKS": "Poista %1 lohkoa", - "DELETE_ALL_BLOCKS": "Poistetaanko kaikki %1 lohkoa?", - "CLEAN_UP": "Siivoa lohkot", - "COLLAPSE_BLOCK": "Sulje lohko", - "COLLAPSE_ALL": "Sulje lohkot", - "EXPAND_BLOCK": "Laajenna lohko", - "EXPAND_ALL": "Laajenna lohkot", - "DISABLE_BLOCK": "Passivoi lohko", - "ENABLE_BLOCK": "Aktivoi lohko", - "HELP": "Apua", - "UNDO": "Kumoa", - "REDO": "Tee uudelleen", - "CHANGE_VALUE_TITLE": "Muuta arvoa:", - "RENAME_VARIABLE": "Nimeä uudelleen muuttuja...", - "RENAME_VARIABLE_TITLE": "Nimeä uudelleen kaikki '%1' muuttujaa:", - "NEW_VARIABLE": "Uusi muuttuja...", - "NEW_VARIABLE_TITLE": "Uuden muuttujan nimi:", - "COLOUR_PICKER_HELPURL": "https://fi.wikipedia.org/wiki/V%C3%A4ri", - "COLOUR_PICKER_TOOLTIP": "Valitse väri paletista.", - "COLOUR_RANDOM_TITLE": "satunnainen väri", - "COLOUR_RANDOM_TOOLTIP": "Valitse väri sattumanvaraisesti.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "väri, jossa on", - "COLOUR_RGB_RED": "punainen", - "COLOUR_RGB_GREEN": "vihreä", - "COLOUR_RGB_BLUE": "sininen", - "COLOUR_RGB_TOOLTIP": "Luo väri, jossa on tietty määrä punaista, vihreää ja sinistä. Kaikkien arvojen tulee olla välillä 0 - 100.", - "COLOUR_BLEND_TITLE": "sekoitus", - "COLOUR_BLEND_COLOUR1": "väri 1", - "COLOUR_BLEND_COLOUR2": "väri 2", - "COLOUR_BLEND_RATIO": "suhde", - "COLOUR_BLEND_TOOLTIP": "Sekoittaa kaksi väriä keskenään annetussa suhteessa (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "toista %1 kertaa", - "CONTROLS_REPEAT_INPUT_DO": "tee", - "CONTROLS_REPEAT_TOOLTIP": "Suorita joukko lausekkeita useampi kertaa.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "toista niin kauan kuin", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "toista kunnes", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Niin kauan kuin arvo on tosi, suorita joukko lausekkeita.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Niin kauan kuin arvo on epätosi, suorita joukko lausekkeita.", - "CONTROLS_FOR_TOOLTIP": "Aseta muuttujaan \"%1\" arvot alkuarvosta loppuarvoon annetun askeleen välein ja suorita joka askeleella annettu koodilohko.", - "CONTROLS_FOR_TITLE": "laske %1 Väli %2-%3 %4:n välein", - "CONTROLS_FOREACH_TITLE": "kullekin kohteelle %1 listassa %2", - "CONTROLS_FOREACH_TOOLTIP": "Aseta muuttujan %1 arvoksi kukin listan kohde vuorollaan ja suorita joukko lausekkeita.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "poistu silmukasta", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "jatka silmukan seuraavaan toistoon", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Poistu sisemmästä silmukasta.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Ohita loput tästä silmukasta ja siirry seuraavaan toistoon.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Varoitus: Tätä lohkoa voi käyttää vain silmukan sisällä.", - "CONTROLS_IF_TOOLTIP_1": "Jos arvo on tosi, suorita lauseke.", - "CONTROLS_IF_TOOLTIP_2": "Jos arvo on tosi, suorita ensimmäinen lohko lausekkeita. Muuten suorita toinen lohko lausekkeita.", - "CONTROLS_IF_TOOLTIP_3": "Jos ensimmäinen arvo on tosi, suorita ensimmäinen lohko lausekkeita. Muuten, jos toinen arvo on tosi, suorita toinen lohko lausekkeita.", - "CONTROLS_IF_TOOLTIP_4": "Jos ensimmäinen arvo on tosi, suorita ensimmäinen lohko lausekkeita. Muuten, jos toinen arvo on tosi, suorita toinen lohko lausekkeita. Jos mikään arvoista ei ole tosi, suorita viimeinen lohko lausekkeita.", - "CONTROLS_IF_MSG_IF": "jos", - "CONTROLS_IF_MSG_ELSEIF": "muuten jos", - "CONTROLS_IF_MSG_ELSE": "muuten", - "CONTROLS_IF_IF_TOOLTIP": "Lisää, poista tai järjestele osioita tässä \"jos\" lohkossa.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Lisää ehto \"jos\" lohkoon.", - "CONTROLS_IF_ELSE_TOOLTIP": "Lisää lopullinen \"muuten\" lohko \"jos\" lohkoon.", - "LOGIC_COMPARE_HELPURL": "https://fi.wikipedia.org/wiki/Ep%C3%A4yht%C3%A4l%C3%B6", - "LOGIC_COMPARE_TOOLTIP_EQ": "Palauta tosi, jos syötteet ovat keskenään samat.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Palauttaa tosi, jos syötteet eivät ole keskenään samoja.", - "LOGIC_COMPARE_TOOLTIP_LT": "Palauttaa tosi, jos ensimmäinen syöte on pienempi, kuin toinen.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Palauttaa tosi, jos ensimmäinen syöte on pienempi tai yhtä suuri, kuin toinen.", - "LOGIC_COMPARE_TOOLTIP_GT": "Palauttaa tosi, jos ensimmäinen syöte on suurempi, kuin toinen.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Palauttaa tosi, jos ensimmäinen syöte on suurempi tai yhtä suuri, kuin toinen.", - "LOGIC_OPERATION_TOOLTIP_AND": "Palauttaa tosi, jos kummatkin syötteet ovat tosia.", - "LOGIC_OPERATION_AND": "ja", - "LOGIC_OPERATION_TOOLTIP_OR": "Palauttaa tosi, jos ainakin yksi syötteistä on tosi.", - "LOGIC_OPERATION_OR": "tai", - "LOGIC_NEGATE_TITLE": "ei %1", - "LOGIC_NEGATE_TOOLTIP": "Palauttaa tosi, jos syöte on epätosi. Palauttaa epätosi, jos syöte on tosi.", - "LOGIC_BOOLEAN_TRUE": "tosi", - "LOGIC_BOOLEAN_FALSE": "epätosi", - "LOGIC_BOOLEAN_TOOLTIP": "Palauttaa joko tosi tai epätosi.", - "LOGIC_NULL": "ei mitään", - "LOGIC_NULL_TOOLTIP": "Palauttaa \"ei mitään\"-arvon.", - "LOGIC_TERNARY_CONDITION": "testi", - "LOGIC_TERNARY_IF_TRUE": "jos tosi", - "LOGIC_TERNARY_IF_FALSE": "jos epätosi", - "LOGIC_TERNARY_TOOLTIP": "Tarkistaa testin ehdon. Jos ehto on tosi, palauttaa \"jos tosi\" arvon, muuten palauttaa \"jos epätosi\" arvon.", - "MATH_NUMBER_HELPURL": "https://fi.wikipedia.org/wiki/Luku", - "MATH_NUMBER_TOOLTIP": "Luku.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "⋅", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tan", - "MATH_TRIG_ASIN": "asin", - "MATH_TRIG_ACOS": "acos", - "MATH_TRIG_ATAN": "atan", - "MATH_ARITHMETIC_HELPURL": "http://fi.wikipedia.org/wiki/Aritmetiikka", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Palauttaa kahden luvun summan.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Palauttaa kahden luvun erotuksen.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Palauttaa kertolaskun tulon.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Palauttaa jakolaskun osamäärän.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Palauttaa ensimmäisen luvun korotettuna toisen luvun potenssiin.", - "MATH_SINGLE_HELPURL": "https://fi.wikipedia.org/wiki/Neli%C3%B6juuri", - "MATH_SINGLE_OP_ROOT": "neliöjuuri", - "MATH_SINGLE_TOOLTIP_ROOT": "Palauttaa luvun neliöjuuren.", - "MATH_SINGLE_OP_ABSOLUTE": "itseisarvo", - "MATH_SINGLE_TOOLTIP_ABS": "Palauttaa luvun itseisarvon.", - "MATH_SINGLE_TOOLTIP_NEG": "Palauttaa numeron vastaluvun.", - "MATH_SINGLE_TOOLTIP_LN": "Palauttaa luvun luonnollisen logaritmin.", - "MATH_SINGLE_TOOLTIP_LOG10": "Palauttaa luvun kymmenkantaisen logaritmin.", - "MATH_SINGLE_TOOLTIP_EXP": "Palauttaa e potenssiin luku.", - "MATH_SINGLE_TOOLTIP_POW10": "Palauttaa 10 potenssiin luku.", - "MATH_TRIG_HELPURL": "https://fi.wikipedia.org/wiki/Trigonometrinen_funktio", - "MATH_TRIG_TOOLTIP_SIN": "Palauttaa asteluvun (ei radiaanin) sinin.", - "MATH_TRIG_TOOLTIP_COS": "Palauttaa asteluvun (ei radiaanin) kosinin.", - "MATH_TRIG_TOOLTIP_TAN": "Palauttaa asteluvun (ei radiaanin) tangentin.", - "MATH_TRIG_TOOLTIP_ASIN": "Palauttaa luvun arkussinin.", - "MATH_TRIG_TOOLTIP_ACOS": "Palauttaa luvun arkuskosinin.", - "MATH_TRIG_TOOLTIP_ATAN": "Palauttaa luvun arkustangentin.", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "Palauttaa jonkin seuraavista vakioista: π (3.141…), e (2.718…), φ (1.618…), neliöjuuri(2) (1.414…), neliöjuuri(½) (0.707…), or ∞ (ääretön).", - "MATH_IS_EVEN": "on parillinen", - "MATH_IS_ODD": "on pariton", - "MATH_IS_PRIME": "on alkuluku", - "MATH_IS_WHOLE": "on kokonaisluku", - "MATH_IS_POSITIVE": "on positiivinen", - "MATH_IS_NEGATIVE": "on negatiivinen", - "MATH_IS_DIVISIBLE_BY": "on jaollinen luvulla", - "MATH_IS_TOOLTIP": "Tarkistaa onko numero parillinen, pariton, alkuluku, kokonaisluku, positiivinen, negatiivinen, tai jos se on jaollinen toisella luvulla. Palauttaa tosi tai epätosi.", - "MATH_CHANGE_HELPURL": "https://fi.wikipedia.org/wiki/Yhteenlasku", - "MATH_CHANGE_TITLE": "muuta %1 arvolla %2", - "MATH_CHANGE_TOOLTIP": "Lisää arvo muuttujaan '%1'.", - "MATH_ROUND_HELPURL": "https://fi.wikipedia.org/wiki/Py%C3%B6rist%C3%A4minen", - "MATH_ROUND_TOOLTIP": "Pyöristää luvun ylös- tai alaspäin.", - "MATH_ROUND_OPERATOR_ROUND": "pyöristä", - "MATH_ROUND_OPERATOR_ROUNDUP": "pyöristä ylöspäin", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "pyöristä alaspäin", - "MATH_ONLIST_OPERATOR_SUM": "summa luvuista", - "MATH_ONLIST_TOOLTIP_SUM": "Palauttaa kaikkien annettujen lukujen summan.", - "MATH_ONLIST_OPERATOR_MIN": "pienin luvuista", - "MATH_ONLIST_TOOLTIP_MIN": "Palauttaa pienimmän annetuista luvuista.", - "MATH_ONLIST_OPERATOR_MAX": "suurin luvuista", - "MATH_ONLIST_TOOLTIP_MAX": "Palauttaa suurimman annetuista luvuista.", - "MATH_ONLIST_OPERATOR_AVERAGE": "keskiarvo luvuista", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Palauttaa aritmeettisen keskiarvon annetuista luvuista.", - "MATH_ONLIST_OPERATOR_MEDIAN": "keskiluku luvuista", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Palauttaa annettujen lukujen keskiluvun.", - "MATH_ONLIST_OPERATOR_MODE": "tyyppiarvo luvuista", - "MATH_ONLIST_TOOLTIP_MODE": "Palauttaa luettelon yleisimmistä luvuista annetussa listassa.", - "MATH_ONLIST_OPERATOR_STD_DEV": "keskihajonta luvuista", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Palauttaa annettujen lukujen keskihajonnan.", - "MATH_ONLIST_OPERATOR_RANDOM": "satunnainen valinta luvuista", - "MATH_ONLIST_TOOLTIP_RANDOM": "Palauttaa satunnaisesti valitun luvun annetuista luvuista.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "%1 ÷ %2 jakojäännös", - "MATH_MODULO_TOOLTIP": "Palauttaa jakolaskun jakojäännöksen.", - "MATH_CONSTRAIN_TITLE": "rajoita %1 vähintään %2 enintään %3", - "MATH_CONSTRAIN_TOOLTIP": "Rajoittaa arvon annetulle suljetulle välille.", - "MATH_RANDOM_INT_HELPURL": "https://fi.wikipedia.org/wiki/Satunnaisluku", - "MATH_RANDOM_INT_TITLE": "Palauttaa satunnaisen kokonaisluvun väliltä %1-%2", - "MATH_RANDOM_INT_TOOLTIP": "Palauttaa satunnaisen kokonaisluvun kahden annetun arvon suljetulta väliltä.", - "MATH_RANDOM_FLOAT_HELPURL": "https://fi.wikipedia.org/wiki/Satunnaisluku", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "satunnainen murtoluku", - "MATH_RANDOM_FLOAT_TOOLTIP": "Palauttaa satunnaisen luvun oikealta puoliavoimesta välistä [0.0, 1.0).", - "TEXT_TEXT_HELPURL": "https://fi.wikipedia.org/wiki/Merkkijono", - "TEXT_TEXT_TOOLTIP": "Kirjain, sana tai rivi tekstiä.", - "TEXT_JOIN_TITLE_CREATEWITH": "luo teksti", - "TEXT_JOIN_TOOLTIP": "Luo merkkijonon liittämällä yhteen minkä tahansa määrän kohteita.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "liitä", - "TEXT_CREATE_JOIN_TOOLTIP": "Lisää, poista tai uudelleen järjestä osioita tässä lohkossa.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Lisää kohteen tekstiin.", - "TEXT_APPEND_TO": "muuttujaan", - "TEXT_APPEND_APPENDTEXT": "lisää teksti", - "TEXT_APPEND_TOOLTIP": "Lisää tekstiä muuttujaan '%1'.", - "TEXT_LENGTH_TITLE": "%1:n pituus", - "TEXT_LENGTH_TOOLTIP": "Palauttaa annetussa tekstissä olevien merkkien määrän (välilyönnit mukaan lukien).", - "TEXT_ISEMPTY_TITLE": "%1 on tyhjä", - "TEXT_ISEMPTY_TOOLTIP": "Palauttaa tosi, jos annettu teksti on tyhjä.", - "TEXT_INDEXOF_TOOLTIP": "Palauttaa ensin annetun tekstin ensimmäisen/viimeisen esiintymän osoitteen toisessa tekstissä. Palauttaa osoitteen %1 jos tekstiä ei löytynyt.", - "TEXT_INDEXOF_INPUT_INTEXT": "tekstistä", - "TEXT_INDEXOF_OPERATOR_FIRST": "etsi ensimmäinen esiintymä merkkijonolle", - "TEXT_INDEXOF_OPERATOR_LAST": "etsi viimeinen esiintymä merkkijonolle", - "TEXT_CHARAT_INPUT_INTEXT": "tekstistä", - "TEXT_CHARAT_FROM_START": "Hae kirjain nro", - "TEXT_CHARAT_FROM_END": "Hae kirjain nro (lopusta laskien)", - "TEXT_CHARAT_FIRST": "hae ensimmäinen kirjain", - "TEXT_CHARAT_LAST": "hae viimeinen kirjain", - "TEXT_CHARAT_RANDOM": "hae satunnainen kirjain", - "TEXT_CHARAT_TOOLTIP": "Palauttaa annetussa kohdassa olevan kirjaimen.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Palauttaa määrätyn osan tekstistä.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "merkkijonosta", - "TEXT_GET_SUBSTRING_START_FROM_START": "hae osa alkaen kirjaimesta nro", - "TEXT_GET_SUBSTRING_START_FROM_END": "hae osa alkaen kirjaimesta nro (lopusta laskien)", - "TEXT_GET_SUBSTRING_START_FIRST": "hae osa alkaen ensimmäisestä kirjaimesta", - "TEXT_GET_SUBSTRING_END_FROM_START": "kirjaimeen nro", - "TEXT_GET_SUBSTRING_END_FROM_END": "kirjaimeen nro (lopusta laskien)", - "TEXT_GET_SUBSTRING_END_LAST": "viimeiseen kirjaimeen", - "TEXT_CHANGECASE_TOOLTIP": "Palauttaa kopion tekstistä eri kirjainkoossa.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "isot kirjaimet", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "pienet kirjaimet", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "isot alkukirjaimet", - "TEXT_TRIM_TOOLTIP": "Palauttaa kopion tekstistä siten, että välilyönnit on poistettu yhdestä tai molemmista päistä.", - "TEXT_TRIM_OPERATOR_BOTH": "poistaa välilyönnit kummaltakin puolelta", - "TEXT_TRIM_OPERATOR_LEFT": "poistaa välilyönnit vasemmalta puolelta", - "TEXT_TRIM_OPERATOR_RIGHT": "poistaa välilyönnit oikealta puolelta", - "TEXT_PRINT_TITLE": "tulosta %1", - "TEXT_PRINT_TOOLTIP": "Tulostaa annetun tekstin, numeron tai muun arvon.", - "TEXT_PROMPT_TYPE_TEXT": "käyttäen annettua viestiä, kehottaa syöttämään tekstiä", - "TEXT_PROMPT_TYPE_NUMBER": "käyttäen annettua viestiä, kehottaa syöttämään numeron", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Kehottaa käyttäjää syöttämään numeron.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Kehottaa käyttäjää syöttämään tekstiä.", - "LISTS_CREATE_EMPTY_TITLE": "Luo tyhjä lista", - "LISTS_CREATE_EMPTY_TOOLTIP": "Palauta tyhjä lista, pituus 0", - "LISTS_CREATE_WITH_TOOLTIP": "Luo lista, jossa on mikä tahansa määrä kohteita.", - "LISTS_CREATE_WITH_INPUT_WITH": "luo lista", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "lista", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Listää, poista tai järjestele uudestaan osioita tässä lohkossa.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Lisää kohde listaan.", - "LISTS_REPEAT_TOOLTIP": "Luo listan, jossa annettu arvo toistuu määrätyn monta kertaa.", - "LISTS_REPEAT_TITLE": "luo lista, jossa kohde %1 toistuu %2 kertaa", - "LISTS_LENGTH_TITLE": "%1:n pituus", - "LISTS_LENGTH_TOOLTIP": "Palauttaa listan pituuden.", - "LISTS_ISEMPTY_TITLE": "%1 on tyhjä", - "LISTS_ISEMPTY_TOOLTIP": "Palauttaa tosi, jos lista on tyhjä.", - "LISTS_INLIST": "listassa", - "LISTS_INDEX_OF_FIRST": "etsi ensimmäinen esiintymä kohteelle", - "LISTS_INDEX_OF_LAST": "etsi viimeinen esiintymä kohteelle", - "LISTS_INDEX_OF_TOOLTIP": "Palauttaa kohteen ensimmäisen/viimeisen esiintymän kohdan listassa. Palauttaa %1 jos kohdetta ei löydy.", - "LISTS_GET_INDEX_GET": "hae", - "LISTS_GET_INDEX_GET_REMOVE": "hae ja poista", - "LISTS_GET_INDEX_REMOVE": "poista", - "LISTS_GET_INDEX_FROM_START": "nro", - "LISTS_GET_INDEX_FROM_END": "nro (lopusta laskien)", - "LISTS_GET_INDEX_FIRST": "ensimmäinen", - "LISTS_GET_INDEX_LAST": "viimeinen", - "LISTS_GET_INDEX_RANDOM": "satunnainen", - "LISTS_INDEX_FROM_START_TOOLTIP": "Numero %1 tarkoittaa listan ensimmäistä kohdetta.", - "LISTS_INDEX_FROM_END_TOOLTIP": "Numero %1 tarkoittaa listan viimeistä kohdetta.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Palauta kohde annetusta kohdasta listaa.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Palauta ensimmäinen kohde listalta.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Palauttaa listan viimeisen kohteen.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Palauttaa satunnaisen kohteen listalta.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Poistaa ja palauttaa kohteen listan annetusta kohdasta.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Poistaa ja palauttaa ensimmäisen kohteen listalta.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Poistaa ja palauttaa viimeisen kohteen listalta.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Poistaa ja palauttaa satunnaisen kohteen listalta.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Poistaa kohteen listalta annetusta kohtaa.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Poistaa ensimmäisen kohteen listalta.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Poistaa viimeisen kohteen listalta.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Poistaa satunnaisen kohteen listalta.", - "LISTS_SET_INDEX_SET": "aseta", - "LISTS_SET_INDEX_INSERT": "lisää kohtaan", - "LISTS_SET_INDEX_INPUT_TO": "kohteeksi", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Asettaa kohteen annettuun kohtaan listassa.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Asettaa listan ensimmäisen kohteen.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Asettaa listan viimeisen kohteen.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Asettaa satunnaisen kohteen listassa.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Lisää kohteen annettuun kohtaan listassa.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Lisää kohteen listan kärkeen.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Lisää kohteen listan loppuun.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Lisää kohteen satunnaiseen kohtaan listassa.", - "LISTS_GET_SUBLIST_START_FROM_START": "hae osalista alkaen kohdasta", - "LISTS_GET_SUBLIST_START_FROM_END": "hae osalista alkaen kohdasta (lopusta laskien)", - "LISTS_GET_SUBLIST_START_FIRST": "hae osalista alkaen alusta", - "LISTS_GET_SUBLIST_END_FROM_START": "päättyen kohtaan", - "LISTS_GET_SUBLIST_END_FROM_END": "päättyen kohtaan (lopusta laskien)", - "LISTS_GET_SUBLIST_END_LAST": "viimeinen", - "LISTS_GET_SUBLIST_TOOLTIP": "Luo kopio määrätystä kohden listaa.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "lajittele %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Lajittele kopio luettelosta.", - "LISTS_SORT_ORDER_ASCENDING": "nouseva", - "LISTS_SORT_ORDER_DESCENDING": "laskeva", - "LISTS_SORT_TYPE_NUMERIC": "numeerinen", - "LISTS_SORT_TYPE_TEXT": "aakkosjärjestys", - "LISTS_SORT_TYPE_IGNORECASE": "aakkosjärjestyksessä, ohita kapitaalit", - "LISTS_SPLIT_LIST_FROM_TEXT": "tee lista tekstistä", - "LISTS_SPLIT_TEXT_FROM_LIST": "tee listasta teksti", - "LISTS_SPLIT_WITH_DELIMITER": "erottimen kanssa", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Jaa teksti osiin erotinmerkin perusteella ja järjestä osat listaksi.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Yhdistä luettelon tekstit yhdeksi tekstiksi, erotettuina välimerkillä.", - "VARIABLES_GET_TOOLTIP": "Palauttaa muuttujan arvon.", - "VARIABLES_GET_CREATE_SET": "Luo 'aseta %1'", - "VARIABLES_SET": "aseta %1 arvoksi %2", - "VARIABLES_SET_TOOLTIP": "Asettaa muutujan arvoksi annetun syötteen.", - "VARIABLES_SET_CREATE_GET": "Luo 'hae %1'", - "PROCEDURES_DEFNORETURN_TITLE": "tehdäksesi", - "PROCEDURES_DEFNORETURN_PROCEDURE": "tee jotain", - "PROCEDURES_BEFORE_PARAMS": "parametrit:", - "PROCEDURES_CALL_BEFORE_PARAMS": "parametrit:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Luo funktio, jolla ei ole tuotosta.", - "PROCEDURES_DEFNORETURN_COMMENT": "Kuvaile tämä funktio...", - "PROCEDURES_DEFRETURN_RETURN": "palauta", - "PROCEDURES_DEFRETURN_TOOLTIP": "Luo funktio, jolla ei ole tuotosta.", - "PROCEDURES_ALLOW_STATEMENTS": "salli kommentit", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Varoitus: tällä funktiolla on sama parametri useamman kerran.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://fi.wikipedia.org/wiki/Aliohjelma", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Suorittaa käyttäjän määrittelemä funktio '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "https://fi.wikipedia.org/wiki/Aliohjelma", - "PROCEDURES_CALLRETURN_TOOLTIP": "Suorittaa käyttäjän määrittelemän funktion '%1' ja käyttää sen tuotosta.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "syötteet", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Lisää, poista tai järjestele uudelleen tämän toiminnon tulot.", - "PROCEDURES_MUTATORARG_TITLE": "syötteen nimi:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Lisää sisääntulon funktioon.", - "PROCEDURES_HIGHLIGHT_DEF": "Korosta funktion määritelmä", - "PROCEDURES_CREATE_DO": "Luo '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Jos arvo on tosi, palauta toinen arvo.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Varoitus: tätä lohkoa voi käyttää vain funktion määrityksessä." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/fr.json b/backend/_pv_1_3_5/static/blockly/msg/json/fr.json deleted file mode 100755 index c5903f503..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/fr.json +++ /dev/null @@ -1,325 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Espertus", - "Gomoko", - "ProfGra", - "Wladek92", - "Fredlefred", - "Grimault", - "Rixed", - "Frigory" - ] - }, - "VARIABLES_DEFAULT_NAME": "élément", - "TODAY": "Aujourd'hui", - "DUPLICATE_BLOCK": "Dupliquer", - "ADD_COMMENT": "Ajouter un commentaire", - "REMOVE_COMMENT": "Supprimer un commentaire", - "EXTERNAL_INPUTS": "Entrées externes", - "INLINE_INPUTS": "Entrées en ligne", - "DELETE_BLOCK": "Supprimer le bloc", - "DELETE_X_BLOCKS": "Supprimer %1 blocs", - "DELETE_ALL_BLOCKS": "Supprimer ces %1 blocs ?", - "CLEAN_UP": "Nettoyer les blocs", - "COLLAPSE_BLOCK": "Réduire le bloc", - "COLLAPSE_ALL": "Réduire les blocs", - "EXPAND_BLOCK": "Développer le bloc", - "EXPAND_ALL": "Développer les blocs", - "DISABLE_BLOCK": "Désactiver le bloc", - "ENABLE_BLOCK": "Activer le bloc", - "HELP": "Aide", - "UNDO": "Annuler", - "REDO": "Refaire", - "CHANGE_VALUE_TITLE": "Modifier la valeur :", - "RENAME_VARIABLE": "Renommer la variable…", - "RENAME_VARIABLE_TITLE": "Renommer toutes les variables « %1 » en :", - "NEW_VARIABLE": "Créer une variable...", - "NEW_VARIABLE_TITLE": "Nouveau nom de la variable :", - "VARIABLE_ALREADY_EXISTS": "Une variable appelée '%1' existe déjà.", - "DELETE_VARIABLE_CONFIRMATION": "Supprimer %1 utilisations de la variable '%2' ?", - "DELETE_VARIABLE": "Supprimer la variable '%1'", - "COLOUR_PICKER_HELPURL": "https://fr.wikipedia.org/wiki/Couleur", - "COLOUR_PICKER_TOOLTIP": "Choisir une couleur dans la palette.", - "COLOUR_RANDOM_TITLE": "couleur aléatoire", - "COLOUR_RANDOM_TOOLTIP": "Choisir une couleur au hasard.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "colorier avec", - "COLOUR_RGB_RED": "rouge", - "COLOUR_RGB_GREEN": "vert", - "COLOUR_RGB_BLUE": "bleu", - "COLOUR_RGB_TOOLTIP": "Créer une couleur avec la quantité spécifiée de rouge, vert et bleu. Les valeurs doivent être comprises entre 0 et 100.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "mélanger", - "COLOUR_BLEND_COLOUR1": "couleur 1", - "COLOUR_BLEND_COLOUR2": "couleur 2", - "COLOUR_BLEND_RATIO": "taux", - "COLOUR_BLEND_TOOLTIP": "Mélange deux couleurs dans une proportion donnée (de 0.0 à 1.0).", - "CONTROLS_REPEAT_HELPURL": "http://fr.wikipedia.org/wiki/Boucle_for", - "CONTROLS_REPEAT_TITLE": "répéter %1 fois", - "CONTROLS_REPEAT_INPUT_DO": "faire", - "CONTROLS_REPEAT_TOOLTIP": "Exécuter des instructions plusieurs fois.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "répéter tant que", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "répéter jusqu’à", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Tant qu’une valeur est vraie, alors exécuter des instructions.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Tant qu’une valeur est fausse, alors exécuter des instructions.", - "CONTROLS_FOR_TOOLTIP": "Faire prendre à la variable « %1 » les valeurs depuis le nombre de début jusqu’au nombre de fin, en s’incrémentant du pas spécifié, et exécuter les instructions spécifiées.", - "CONTROLS_FOR_TITLE": "compter avec %1 de %2 à %3 par %4", - "CONTROLS_FOREACH_TITLE": "pour chaque élément %1 dans la liste %2", - "CONTROLS_FOREACH_TOOLTIP": "Pour chaque élément d’une liste, assigner la valeur de l’élément à la variable '%1', puis exécuter des instructions.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "quitter la boucle", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "passer à l’itération de boucle suivante", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Sortir de la boucle englobante.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Sauter le reste de cette boucle, et poursuivre avec l’itération suivante.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Attention : Ce bloc ne devrait être utilisé que dans une boucle.", - "CONTROLS_IF_TOOLTIP_1": "Si une valeur est vraie, alors exécuter certains ordres.", - "CONTROLS_IF_TOOLTIP_2": "Si une valeur est vraie, alors exécuter le premier bloc d’ordres. Sinon, exécuter le second bloc d’ordres.", - "CONTROLS_IF_TOOLTIP_3": "Si la première valeur est vraie, alors exécuter le premier bloc d’ordres. Sinon, si la seconde valeur est vraie, exécuter le second bloc d’ordres.", - "CONTROLS_IF_TOOLTIP_4": "Si la première valeur est vraie, alors exécuter le premier bloc d’ordres. Sinon, si la seconde valeur est vraie, exécuter le second bloc d’ordres. Si aucune des valeurs n’est vraie, exécuter le dernier bloc d’ordres.", - "CONTROLS_IF_MSG_IF": "si", - "CONTROLS_IF_MSG_ELSEIF": "sinon si", - "CONTROLS_IF_MSG_ELSE": "sinon", - "CONTROLS_IF_IF_TOOLTIP": "Ajouter, supprimer ou réordonner les sections pour reconfigurer ce bloc si.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Ajouter une condition au bloc si.", - "CONTROLS_IF_ELSE_TOOLTIP": "Ajouter une condition finale fourre-tout au bloc si.", - "LOGIC_COMPARE_HELPURL": "https://fr.wikipedia.org/wiki/Inegalite_(mathematiques)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Renvoyer vrai si les deux entrées sont égales.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Renvoyer vrai si les deux entrées sont différentes.", - "LOGIC_COMPARE_TOOLTIP_LT": "Renvoyer vrai si la première entrée est plus petite que la seconde.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Renvoyer vrai si la première entrée est plus petite ou égale à la seconde.", - "LOGIC_COMPARE_TOOLTIP_GT": "Renvoyer vrai si la première entrée est plus grande que la seconde.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Renvoyer vrai si la première entrée est plus grande ou égale à la seconde.", - "LOGIC_OPERATION_TOOLTIP_AND": "Renvoyer vrai si les deux entrées sont vraies.", - "LOGIC_OPERATION_AND": "et", - "LOGIC_OPERATION_TOOLTIP_OR": "Renvoyer vrai si au moins une des entrées est vraie.", - "LOGIC_OPERATION_OR": "ou", - "LOGIC_NEGATE_TITLE": "pas %1", - "LOGIC_NEGATE_TOOLTIP": "Renvoie vrai si l’entrée est fausse. Renvoie faux si l’entrée est vraie.", - "LOGIC_BOOLEAN_TRUE": "vrai", - "LOGIC_BOOLEAN_FALSE": "faux", - "LOGIC_BOOLEAN_TOOLTIP": "Renvoie soit vrai soit faux.", - "LOGIC_NULL_HELPURL": "https://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "nul", - "LOGIC_NULL_TOOLTIP": "Renvoie nul.", - "LOGIC_TERNARY_HELPURL": "https://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "si vrai", - "LOGIC_TERNARY_IF_FALSE": "si faux", - "LOGIC_TERNARY_TOOLTIP": "Vérifier la condition dans 'test'. Si elle est vraie, renvoie la valeur 'si vrai' ; sinon renvoie la valeur 'si faux'.", - "MATH_NUMBER_HELPURL": "https://fr.wikipedia.org/wiki/Nombre", - "MATH_NUMBER_TOOLTIP": "Un nombre.", - "MATH_ARITHMETIC_HELPURL": "https://fr.wikipedia.org/wiki/Arithmetique", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Renvoie la somme des deux nombres.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Renvoie la différence des deux nombres.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Renvoie le produit des deux nombres.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Renvoie le quotient des deux nombres.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Renvoie le premier nombre élevé à la puissance du second.", - "MATH_SINGLE_HELPURL": "https://fr.wikipedia.org/wiki/Racine_carree", - "MATH_SINGLE_OP_ROOT": "racine carrée", - "MATH_SINGLE_TOOLTIP_ROOT": "Renvoie la racine carrée d’un nombre.", - "MATH_SINGLE_OP_ABSOLUTE": "valeur absolue", - "MATH_SINGLE_TOOLTIP_ABS": "Renvoie la valeur absolue d’un nombre.", - "MATH_SINGLE_TOOLTIP_NEG": "Renvoie l’opposé d’un nombre", - "MATH_SINGLE_TOOLTIP_LN": "Renvoie le logarithme naturel d’un nombre.", - "MATH_SINGLE_TOOLTIP_LOG10": "Renvoie le logarithme base 10 d’un nombre.", - "MATH_SINGLE_TOOLTIP_EXP": "Renvoie e à la puissance d’un nombre.", - "MATH_SINGLE_TOOLTIP_POW10": "Renvoie 10 à la puissance d’un nombre.", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "Renvoie le sinus d’un angle en degrés (pas en radians).", - "MATH_TRIG_TOOLTIP_COS": "Renvoie le cosinus d’un angle en degrés (pas en radians).", - "MATH_TRIG_TOOLTIP_TAN": "Renvoie la tangente d’un angle en degrés (pas en radians).", - "MATH_TRIG_TOOLTIP_ASIN": "Renvoie l’arcsinus d’un nombre.", - "MATH_TRIG_TOOLTIP_ACOS": "Renvoie l’arccosinus d’un nombre.", - "MATH_TRIG_TOOLTIP_ATAN": "Renvoie l’arctangente d’un nombre.", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "Renvoie une des constantes courantes : π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), ou ∞ (infini).", - "MATH_IS_EVEN": "est pair", - "MATH_IS_ODD": "est impair", - "MATH_IS_PRIME": "est premier", - "MATH_IS_WHOLE": "est entier", - "MATH_IS_POSITIVE": "est positif", - "MATH_IS_NEGATIVE": "est négatif", - "MATH_IS_DIVISIBLE_BY": "est divisible par", - "MATH_IS_TOOLTIP": "Vérifier si un nombre est pair, impair, premier, entier, positif, négatif, ou s’il est divisible par un certain nombre. Renvoie vrai ou faux.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "incrémenter %1 de %2", - "MATH_CHANGE_TOOLTIP": "Ajouter un nombre à la variable '%1'.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Arrondir un nombre au-dessus ou au-dessous.", - "MATH_ROUND_OPERATOR_ROUND": "arrondir", - "MATH_ROUND_OPERATOR_ROUNDUP": "arrondir par excès", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "arrondir par défaut", - "MATH_ONLIST_OPERATOR_SUM": "somme de la liste", - "MATH_ONLIST_TOOLTIP_SUM": "Renvoyer la somme de tous les nombres dans la liste.", - "MATH_ONLIST_OPERATOR_MIN": "minimum de la liste", - "MATH_ONLIST_TOOLTIP_MIN": "Renvoyer le plus petit nombre dans la liste.", - "MATH_ONLIST_OPERATOR_MAX": "maximum de la liste", - "MATH_ONLIST_TOOLTIP_MAX": "Renvoyer le plus grand nombre dans la liste.", - "MATH_ONLIST_OPERATOR_AVERAGE": "moyenne de la liste", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Renvoyer la moyenne (arithmétique) des valeurs numériques dans la liste.", - "MATH_ONLIST_OPERATOR_MEDIAN": "médiane de la liste", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Renvoyer le nombre médian de la liste.", - "MATH_ONLIST_OPERATOR_MODE": "majoritaires de la liste", - "MATH_ONLIST_TOOLTIP_MODE": "Renvoyer une liste des élément(s) le(s) plus courant(s) dans la liste.", - "MATH_ONLIST_OPERATOR_STD_DEV": "écart-type de la liste", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Renvoyer l’écart-type de la liste.", - "MATH_ONLIST_OPERATOR_RANDOM": "élément aléatoire de la liste", - "MATH_ONLIST_TOOLTIP_RANDOM": "Renvoyer un élément dans la liste au hasard.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "reste de %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Renvoyer le reste de la division euclidienne des deux nombres.", - "MATH_CONSTRAIN_TITLE": "contraindre %1 entre %2 et %3", - "MATH_CONSTRAIN_TOOLTIP": "Contraindre un nombre à être entre les limites spécifiées (incluses).", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "entier aléatoire entre %1 et %2", - "MATH_RANDOM_INT_TOOLTIP": "Renvoyer un entier aléatoire entre les deux limites spécifiées, incluses.", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "fraction aléatoire", - "MATH_RANDOM_FLOAT_TOOLTIP": "Renvoyer une fraction aléatoire entre 0.0 (inclus) et 1.0 (exclus).", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "Une lettre, un mot ou une ligne de texte.", - "TEXT_JOIN_TITLE_CREATEWITH": "créer un texte avec", - "TEXT_JOIN_TOOLTIP": "Créer un morceau de texte en agrégeant un nombre quelconque d’éléments.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "joindre", - "TEXT_CREATE_JOIN_TOOLTIP": "Ajouter, supprimer, ou réordonner des sections pour reconfigurer ce bloc de texte.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Ajouter un élément au texte.", - "TEXT_APPEND_TO": "à", - "TEXT_APPEND_APPENDTEXT": "ajouter le texte", - "TEXT_APPEND_TOOLTIP": "Ajouter du texte à la variable '%1'.", - "TEXT_LENGTH_TITLE": "longueur de %1", - "TEXT_LENGTH_TOOLTIP": "Renvoie le nombre de lettres (espaces compris) dans le texte fourni.", - "TEXT_ISEMPTY_TITLE": "%1 est vide", - "TEXT_ISEMPTY_TOOLTIP": "Renvoie vrai si le texte fourni est vide.", - "TEXT_INDEXOF_TOOLTIP": "Renvoie l’index de la première/dernière occurrence de la première chaîne dans la seconde. Renvoie %1 si la chaîne n’est pas trouvée.", - "TEXT_INDEXOF_INPUT_INTEXT": "dans le texte", - "TEXT_INDEXOF_OPERATOR_FIRST": "trouver la première occurrence de la chaîne", - "TEXT_INDEXOF_OPERATOR_LAST": "trouver la dernière occurrence de la chaîne", - "TEXT_CHARAT_INPUT_INTEXT": "dans le texte", - "TEXT_CHARAT_FROM_START": "obtenir la lettre #", - "TEXT_CHARAT_FROM_END": "obtenir la lettre # depuis la fin", - "TEXT_CHARAT_FIRST": "obtenir la première lettre", - "TEXT_CHARAT_LAST": "obtenir la dernière lettre", - "TEXT_CHARAT_RANDOM": "obtenir une lettre au hasard", - "TEXT_CHARAT_TOOLTIP": "Renvoie la lettre à la position indiquée.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Renvoie une partie indiquée du texte.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "dans le texte", - "TEXT_GET_SUBSTRING_START_FROM_START": "obtenir la sous-chaîne depuis la lettre #", - "TEXT_GET_SUBSTRING_START_FROM_END": "obtenir la sous-chaîne depuis la lettre # depuis la fin", - "TEXT_GET_SUBSTRING_START_FIRST": "obtenir la sous-chaîne depuis la première lettre", - "TEXT_GET_SUBSTRING_END_FROM_START": "jusqu’à la lettre #", - "TEXT_GET_SUBSTRING_END_FROM_END": "jusqu’à la lettre # depuis la fin", - "TEXT_GET_SUBSTRING_END_LAST": "jusqu’à la dernière lettre", - "TEXT_CHANGECASE_TOOLTIP": "Renvoyer une copie du texte dans une autre casse.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "en MAJUSCULES", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "en minuscules", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "en Majuscule Au Début De Chaque Mot", - "TEXT_TRIM_TOOLTIP": "Renvoyer une copie du texte avec les espaces supprimés d’un bout ou des deux.", - "TEXT_TRIM_OPERATOR_BOTH": "supprimer les espaces des deux côtés", - "TEXT_TRIM_OPERATOR_LEFT": "supprimer les espaces du côté gauche", - "TEXT_TRIM_OPERATOR_RIGHT": "supprimer les espaces du côté droit", - "TEXT_PRINT_TITLE": "afficher %1", - "TEXT_PRINT_TOOLTIP": "Afficher le texte, le nombre ou une autre valeur spécifié.", - "TEXT_PROMPT_TYPE_TEXT": "invite pour un texte avec un message", - "TEXT_PROMPT_TYPE_NUMBER": "invite pour un nombre avec un message", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Demander un nombre à l’utilisateur.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Demander un texte à l’utilisateur.", - "LISTS_CREATE_EMPTY_TITLE": "créer une liste vide", - "LISTS_CREATE_EMPTY_TOOLTIP": "Renvoyer une liste, de longueur 0, ne contenant aucun enregistrement", - "LISTS_CREATE_WITH_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_CREATE_WITH_TOOLTIP": "Créer une liste avec un nombre quelconque d’éléments.", - "LISTS_CREATE_WITH_INPUT_WITH": "créer une liste avec", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "liste", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Ajouter, supprimer, ou réordonner les sections pour reconfigurer ce bloc de liste.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Ajouter un élément à la liste.", - "LISTS_REPEAT_TOOLTIP": "Crée une liste consistant en la valeur fournie répétée le nombre de fois indiqué.", - "LISTS_REPEAT_TITLE": "créer une liste avec l’élément %1 répété %2 fois", - "LISTS_LENGTH_TITLE": "longueur de %1", - "LISTS_LENGTH_TOOLTIP": "Renvoie la longueur d’une liste.", - "LISTS_ISEMPTY_TITLE": "%1 est vide", - "LISTS_ISEMPTY_TOOLTIP": "Renvoie vrai si la liste est vide.", - "LISTS_INLIST": "dans la liste", - "LISTS_INDEX_OF_FIRST": "trouver la première occurrence de l’élément", - "LISTS_INDEX_OF_LAST": "trouver la dernière occurrence de l’élément", - "LISTS_INDEX_OF_TOOLTIP": "Renvoie l’index de la première/dernière occurrence de l’élément dans la liste. Renvoie %1 si l'élément n'est pas trouvé.", - "LISTS_GET_INDEX_GET": "obtenir", - "LISTS_GET_INDEX_GET_REMOVE": "obtenir et supprimer", - "LISTS_GET_INDEX_REMOVE": "supprimer", - "LISTS_GET_INDEX_FROM_END": "# depuis la fin", - "LISTS_GET_INDEX_FIRST": "premier", - "LISTS_GET_INDEX_LAST": "dernier", - "LISTS_GET_INDEX_RANDOM": "aléatoire", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 est le premier élément.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 est le dernier élément.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Renvoie l’élément à la position indiquée dans une liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Renvoie le premier élément dans une liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Renvoie le dernier élément dans une liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Renvoie un élément au hasard dans une liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Supprime et renvoie l’élément à la position indiquée dans une liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Supprime et renvoie le premier élément dans une liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Supprime et renvoie le dernier élément dans une liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Supprime et renvoie un élément au hasard dans une liste.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Supprime l’élément à la position indiquée dans une liste.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Supprime le premier élément dans une liste.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Supprime le dernier élément dans une liste.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Supprime un élément au hasard dans une liste.", - "LISTS_SET_INDEX_SET": "mettre", - "LISTS_SET_INDEX_INSERT": "insérer en", - "LISTS_SET_INDEX_INPUT_TO": "comme", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Met à jour l’élément à la position indiquée dans une liste.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Fixe le premier élément dans une liste.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Fixe le dernier élément dans une liste.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Fixe un élément au hasard dans une liste.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Insère l’élément à la position indiquée dans une liste.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Insère l’élément au début d’une liste.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Ajouter l’élément à la fin d’une liste.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Insère l’élément au hasard dans une liste.", - "LISTS_GET_SUBLIST_START_FROM_START": "obtenir la sous-liste depuis #", - "LISTS_GET_SUBLIST_START_FROM_END": "obtenir la sous-liste depuis # depuis la fin", - "LISTS_GET_SUBLIST_START_FIRST": "obtenir la sous-liste depuis le début", - "LISTS_GET_SUBLIST_END_FROM_START": "jusqu’à #", - "LISTS_GET_SUBLIST_END_FROM_END": "jusqu’à # depuis la fin", - "LISTS_GET_SUBLIST_END_LAST": "jusqu’à la fin", - "LISTS_GET_SUBLIST_TOOLTIP": "Crée une copie de la partie spécifiée d’une liste.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "trier %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Trier une copie d’une liste.", - "LISTS_SORT_ORDER_ASCENDING": "croissant", - "LISTS_SORT_ORDER_DESCENDING": "décroissant", - "LISTS_SORT_TYPE_NUMERIC": "numérique", - "LISTS_SORT_TYPE_TEXT": "alphabétique", - "LISTS_SORT_TYPE_IGNORECASE": "alphabétique, en ignorant la casse", - "LISTS_SPLIT_HELPURL": "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists", - "LISTS_SPLIT_LIST_FROM_TEXT": "créer une liste depuis le texte", - "LISTS_SPLIT_TEXT_FROM_LIST": "créer un texte depuis la liste", - "LISTS_SPLIT_WITH_DELIMITER": "avec le séparateur", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Couper un texte en une liste de textes, en coupant à chaque séparateur.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Réunir une liste de textes en un seul, en les séparant par un séparateur.", - "VARIABLES_GET_TOOLTIP": "Renvoie la valeur de cette variable.", - "VARIABLES_GET_CREATE_SET": "Créer 'fixer %1'", - "VARIABLES_SET": "fixer %1 à %2", - "VARIABLES_SET_TOOLTIP": "Fixe cette variable pour qu’elle soit égale à la valeur de l’entrée.", - "VARIABLES_SET_CREATE_GET": "Créer 'obtenir %1'", - "PROCEDURES_DEFNORETURN_TITLE": "pour", - "PROCEDURES_DEFNORETURN_PROCEDURE": "faire quelque chose", - "PROCEDURES_BEFORE_PARAMS": "avec :", - "PROCEDURES_CALL_BEFORE_PARAMS": "avec :", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Crée une fonction sans sortie.", - "PROCEDURES_DEFNORETURN_COMMENT": "Décrire cette fonction…", - "PROCEDURES_DEFRETURN_RETURN": "retour", - "PROCEDURES_DEFRETURN_TOOLTIP": "Crée une fonction avec une sortie.", - "PROCEDURES_ALLOW_STATEMENTS": "autoriser les ordres", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Attention : Cette fonction a des paramètres en double.", - "PROCEDURES_CALLNORETURN_HELPURL": "http://fr.wikipedia.org/wiki/Proc%C3%A9dure_%28informatique%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Exécuter la fonction '%1' définie par l’utilisateur.", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Exécuter la fonction '%1' définie par l’utilisateur et utiliser son résultat.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "entrées", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Ajouter, supprimer, ou réarranger les entrées de cette fonction.", - "PROCEDURES_MUTATORARG_TITLE": "nom de l’entrée :", - "PROCEDURES_MUTATORARG_TOOLTIP": "Ajouter une entrée à la fonction.", - "PROCEDURES_HIGHLIGHT_DEF": "Surligner la définition de la fonction", - "PROCEDURES_CREATE_DO": "Créer '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Si une valeur est vraie, alors renvoyer une seconde valeur.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Attention : Ce bloc pourrait n’être utilisé que dans une définition de fonction." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/he.json b/backend/_pv_1_3_5/static/blockly/msg/json/he.json deleted file mode 100755 index 69deb4793..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/he.json +++ /dev/null @@ -1,277 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Dorongol", - "YaronSh", - "Amire80", - "Inkbug", - "Yona b", - "Noamrotem", - "Dvb", - "LaG roiL", - "아라", - "Elyashiv", - "Guycn2" - ] - }, - "VARIABLES_DEFAULT_NAME": "פריט", - "TODAY": "היום", - "DUPLICATE_BLOCK": "שכפל", - "ADD_COMMENT": "הוסף תגובה", - "REMOVE_COMMENT": "הסר תגובה", - "EXTERNAL_INPUTS": "קלטים חיצוניים", - "INLINE_INPUTS": "קלטים פנימיים", - "DELETE_BLOCK": "מחק קטע קוד", - "DELETE_X_BLOCKS": "מחק %1 קטעי קוד", - "DELETE_ALL_BLOCKS": "האם למחוק את כל %1 קטעי הקוד?", - "CLEAN_UP": "סידור בלוקים", - "COLLAPSE_BLOCK": "צמצם קטע קוד", - "COLLAPSE_ALL": "צמצם קטעי קוד", - "EXPAND_BLOCK": "הרחב קטע קוד", - "EXPAND_ALL": "הרחב קטעי קוד", - "DISABLE_BLOCK": "נטרל קטע קוד", - "ENABLE_BLOCK": "הפעל קטע קוד", - "HELP": "עזרה", - "UNDO": "ביטול", - "REDO": "ביצוע חוזר", - "CHANGE_VALUE_TITLE": "שנה ערך:", - "RENAME_VARIABLE": "שנה את שם המשתנה...", - "RENAME_VARIABLE_TITLE": "שנה את שם כל '%1' המשתנים ל:", - "NEW_VARIABLE": "משתנה חדש...", - "NEW_VARIABLE_TITLE": "שם המשתנה החדש:", - "COLOUR_PICKER_HELPURL": "http://he.wikipedia.org/wiki/%D7%A6%D7%91%D7%A2", - "COLOUR_PICKER_TOOLTIP": "בחר צבע מן הצבעים.", - "COLOUR_RANDOM_TITLE": "צבע אקראי", - "COLOUR_RANDOM_TOOLTIP": "בחר צבא אקראי.", - "COLOUR_RGB_TITLE": "צבע עם", - "COLOUR_RGB_RED": "אדום", - "COLOUR_RGB_GREEN": "ירוק", - "COLOUR_RGB_BLUE": "כחול", - "COLOUR_RGB_TOOLTIP": "צור צבע עם הסכום המצוין של אדום, ירוק וכחול. כל הערכים חייבים להיות בין 0 ל100.", - "COLOUR_BLEND_TITLE": "ערבב", - "COLOUR_BLEND_COLOUR1": "צבע 1", - "COLOUR_BLEND_COLOUR2": "צבע 2", - "COLOUR_BLEND_RATIO": "יחס", - "COLOUR_BLEND_TOOLTIP": "מערבב שני צבעים יחד עם יחס נתון(0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "http://he.wikipedia.org/wiki/בקרת_זרימה", - "CONTROLS_REPEAT_TITLE": "חזור על הפעולה %1 פעמים", - "CONTROLS_REPEAT_INPUT_DO": "תעשה", - "CONTROLS_REPEAT_TOOLTIP": "לעשות כמה פעולות מספר פעמים.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "חזור כל עוד", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "חזור עד ש...", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "כל עוד הערך הוא אמת, לעשות כמה פעולות.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "בזמן שהערך שווה לשגוי, תעשה מספר חישובים.", - "CONTROLS_FOR_TITLE": "תספור עם %1 מ- %2 ל- %3 עד- %4", - "CONTROLS_FOREACH_TITLE": "לכל פריט %1 ברשימה %2", - "CONTROLS_FOREACH_TOOLTIP": "לכל פריט ברשימה, להגדיר את המשתנה '%1' לפריט הזה, ולאחר מכן לעשות כמה פעולות.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "צא מהלולאה", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "המשך עם האיטרציה הבאה של הלולאה", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "צא אל מחוץ ללולאה הכוללת.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "דלג על שאר הלולאה והמשך עם האיטרציה הבאה.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "אזהרה: בלוק זה עשוי לשמש רק בתוך לולאה.", - "CONTROLS_IF_TOOLTIP_1": "אם ערך נכון, לבצע כמה פעולות.", - "CONTROLS_IF_TOOLTIP_2": "אם הערך הוא אמת, לבצע את הבלוק הראשון של הפעולות. אחרת, לבצע את הבלוק השני של הפעולות.", - "CONTROLS_IF_TOOLTIP_3": "אם הערך הראשון הוא אמת, לבצע את הבלוק הראשון של הפעולות. אחרת, אם הערך השני הוא אמת, לבצע את הבלוק השני של הפעולות.", - "CONTROLS_IF_TOOLTIP_4": "אם הערך הראשון הוא אמת, לבצע את הבלוק הראשון של הפעולות. אחרת, אם הערך השני הוא אמת, לבצע את הבלוק השני של הפעולות. אם אף אחד מהם אינו נכון, לבצע את הבלוק האחרון של הפעולות.", - "CONTROLS_IF_MSG_IF": "אם", - "CONTROLS_IF_MSG_ELSEIF": "אחרת אם", - "CONTROLS_IF_MSG_ELSE": "אחרת", - "CONTROLS_IF_IF_TOOLTIP": "תוסיף, תמחק, או תסדר מחדש כדי להגדיר מחדש את הבלוק If.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "תוסיף תנאי לבלוק If.", - "CONTROLS_IF_ELSE_TOOLTIP": "לסיום, כל התנאים תקפים לגבי בלוק If.", - "LOGIC_COMPARE_TOOLTIP_EQ": "תחזיר נכון אם שני הקלטים שווים אחד לשני.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "תחזיר אמת אם שני הקלטים אינם שווים זה לזה.", - "LOGIC_COMPARE_TOOLTIP_LT": "תחזיר אמת (true) אם הקלט הראשון הוא קטן יותר מאשר הקלט השני.", - "LOGIC_COMPARE_TOOLTIP_LTE": "תחזיר אמת אם הקלט הראשון הוא קטן יותר או שווה לקלט השני.", - "LOGIC_COMPARE_TOOLTIP_GT": "תחזיר נכון אם הקלט הראשון גדול יותר מהקלט השני.", - "LOGIC_COMPARE_TOOLTIP_GTE": "תחזיר נכון אם הקלט הראשון גדול יותר או שווה לכניסה השנייה.", - "LOGIC_OPERATION_TOOLTIP_AND": "תחזיר נכון אם שני הקלטים נכונים.", - "LOGIC_OPERATION_AND": "ו", - "LOGIC_OPERATION_TOOLTIP_OR": "תחזיר נכון אם מתקיים לפחות אחד מהקלטים נכונים.", - "LOGIC_OPERATION_OR": "או", - "LOGIC_NEGATE_TITLE": "לא %1", - "LOGIC_NEGATE_TOOLTIP": "החזר אמת אם הקלט הוא שקר. החזר שקר אם הקלט אמת.", - "LOGIC_BOOLEAN_TRUE": "נכון", - "LOGIC_BOOLEAN_FALSE": "שגוי", - "LOGIC_BOOLEAN_TOOLTIP": "תחזיר אם נכון או אם שגוי.", - "LOGIC_NULL": "null", - "LOGIC_NULL_TOOLTIP": "תחזיר ריק.", - "LOGIC_TERNARY_CONDITION": "בדיקה", - "LOGIC_TERNARY_IF_TRUE": "אם נכון", - "LOGIC_TERNARY_IF_FALSE": "אם שגוי", - "LOGIC_TERNARY_TOOLTIP": "בדוק את התנאי ב'מבחן'. אם התנאי נכון, תחזיר את הערך 'אם נכון'; אחרת תחזיר את הערך 'אם שגוי'.", - "MATH_NUMBER_HELPURL": "https://he.wikipedia.org/wiki/מספר_ממשי", - "MATH_NUMBER_TOOLTIP": "מספר.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tan", - "MATH_TRIG_ASIN": "asin", - "MATH_TRIG_ACOS": "acos", - "MATH_TRIG_ATAN": "atan", - "MATH_ARITHMETIC_HELPURL": "https://he.wikipedia.org/wiki/ארבע_פעולות_החשבון", - "MATH_ARITHMETIC_TOOLTIP_ADD": "תחזיר את סכום שני המספרים.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "החזרת ההפרש בין שני מספרים.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "החזרת תוצאת הכפל בין שני מספרים.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "החזרת המנה של שני המספרים.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "החזרת המספר הראשון בחזקת המספר השני.", - "MATH_SINGLE_HELPURL": "https://he.wikipedia.org/wiki/שורש_ריבועי", - "MATH_SINGLE_OP_ROOT": "שורש ריבועי", - "MATH_SINGLE_TOOLTIP_ROOT": "החזרת השורש הריבועי של מספר.", - "MATH_SINGLE_OP_ABSOLUTE": "ערך מוחלט", - "MATH_SINGLE_TOOLTIP_ABS": "החזרת הערך המוחלט של מספר.", - "MATH_SINGLE_TOOLTIP_NEG": "החזרת הערך הנגדי של מספר.", - "MATH_SINGLE_TOOLTIP_LN": "החזרת הלוגריתם הטבעי של מספר.", - "MATH_SINGLE_TOOLTIP_LOG10": "החזרת הלוגריתם לפי בסיס עשר של מספר.", - "MATH_SINGLE_TOOLTIP_EXP": "החזרת e בחזקת מספר.", - "MATH_SINGLE_TOOLTIP_POW10": "החזרת 10 בחזקת מספר.", - "MATH_TRIG_HELPURL": "https://he.wikipedia.org/wiki/פונקציות_טריגונומטריות", - "MATH_TRIG_TOOLTIP_SIN": "החזרת הסינוס של מעלה (לא רדיאן).", - "MATH_TRIG_TOOLTIP_COS": "החזרת הקוסינוס של מעלה (לא רדיאן).", - "MATH_TRIG_TOOLTIP_TAN": "החזרת הטנגס של מעלה (לא רדיאן).", - "MATH_IS_EVEN": "זוגי", - "MATH_IS_ODD": "אי-זוגי", - "MATH_IS_PRIME": "ראשוני", - "MATH_IS_WHOLE": "שלם", - "MATH_IS_POSITIVE": "חיובי", - "MATH_IS_NEGATIVE": "שלילי", - "MATH_IS_DIVISIBLE_BY": "מתחלק ב", - "MATH_CHANGE_TITLE": "שינוי %1 על־ידי %2", - "MATH_CHANGE_TOOLTIP": "הוסף מספר למשתנה '%1'.", - "MATH_ROUND_HELPURL": "https://he.wikipedia.org/wiki/עיגול_(אריתמטיקה)", - "MATH_ROUND_TOOLTIP": "עיגול מספר למעלה או למטה.", - "MATH_ROUND_OPERATOR_ROUND": "עיגול", - "MATH_ROUND_OPERATOR_ROUNDUP": "עיגול למעלה", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "עיגול למטה", - "MATH_ONLIST_OPERATOR_SUM": "סכום של רשימה", - "MATH_ONLIST_TOOLTIP_SUM": "החזרת הסכום של המספרים ברשימה.", - "MATH_ONLIST_OPERATOR_MIN": "מינימום של רשימה", - "MATH_ONLIST_TOOLTIP_MIN": "תחזיר את המספר הקטן ביותר ברשימה.", - "MATH_ONLIST_OPERATOR_MAX": "מקסימום של רשימה", - "MATH_ONLIST_TOOLTIP_MAX": "תחזיר את המספר הגדול ביותר ברשימה.", - "MATH_ONLIST_OPERATOR_AVERAGE": "ממוצע של רשימה", - "MATH_ONLIST_OPERATOR_MEDIAN": "חציון של רשימה", - "MATH_ONLIST_TOOLTIP_MEDIAN": "תחזיר את המספר החיצוני ביותר ברשימה.", - "MATH_ONLIST_OPERATOR_MODE": "שכיחי הרשימה", - "MATH_ONLIST_TOOLTIP_MODE": "החזרת רשימה של הפריטים הנפוצים ביותר ברשימה", - "MATH_ONLIST_OPERATOR_RANDOM": "פריט אקראי מרשימה", - "MATH_ONLIST_TOOLTIP_RANDOM": "תחזיר רכיב אקראי מרשימה.", - "MATH_MODULO_TITLE": "שארית החילוק %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "החזרת השארית מחלוקת שני המספרים.", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "שבר אקראי", - "TEXT_TEXT_TOOLTIP": "אות, מילה, או שורת טקסט.", - "TEXT_JOIN_TITLE_CREATEWITH": "יצירת טקסט עם", - "TEXT_CREATE_JOIN_TITLE_JOIN": "צירוף", - "TEXT_APPEND_TO": "אל", - "TEXT_APPEND_APPENDTEXT": "הוספת טקסט", - "TEXT_INDEXOF_TOOLTIP": "מחזירה את האינדקס של המופע הראשון/האחרון בטקסט הראשון לתוך הטקסט השני. מחזירה %1 אם הטקסט אינו נמצא.", - "TEXT_GET_SUBSTRING_END_FROM_START": "לאות #", - "TEXT_GET_SUBSTRING_END_FROM_END": "לאות # מהסוף", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "לאותיות גדולות (עבור טקסט באנגלית)", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "לאותיות קטנות (עבור טקסט באנגלית)", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "לאותיות גדולות בתחילת כל מילה (עבור טקסט באנגלית)", - "TEXT_TRIM_TOOLTIP": "להחזיר עותק של הטקסט לאחר מחיקת רווחים מאחד או משני הקצוות.", - "TEXT_TRIM_OPERATOR_BOTH": "למחוק רווחים משני הקצוות", - "TEXT_TRIM_OPERATOR_LEFT": "למחוק רווחים מימין", - "TEXT_TRIM_OPERATOR_RIGHT": "למחוק רווחים משמאל", - "TEXT_PRINT_TITLE": "הדפס %1", - "TEXT_PRINT_TOOLTIP": "להדפיס טקסט, מספר או ערך אחר שצוין", - "TEXT_PROMPT_TYPE_TEXT": "בקשה להזנת טקסט עם הודעה", - "TEXT_PROMPT_TYPE_NUMBER": "בקשה למספר עם הודעה", - "TEXT_PROMPT_TOOLTIP_NUMBER": "בקש מהמשתמש מספר.", - "TEXT_PROMPT_TOOLTIP_TEXT": "בקשה למשתמש להזין טקסט כלשהו.", - "LISTS_CREATE_EMPTY_TITLE": "צור רשימה ריקה", - "LISTS_CREATE_EMPTY_TOOLTIP": "החזר רשימה,באורך 0, המכילה רשומות נתונים", - "LISTS_CREATE_WITH_TOOLTIP": "צור רשימה עם כל מספר של פריטים.", - "LISTS_CREATE_WITH_INPUT_WITH": "צור רשימה עם", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "רשימה", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "תוסיף, תמחק, או תסדר מחדש כדי להגדיר מחדש את הבלוק If.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "הוסף פריט לרשימה.", - "LISTS_REPEAT_TOOLTIP": "יוצר רשימה המורכבת מהערך נתון חוזר מספר פעמים שצוין.", - "LISTS_REPEAT_TITLE": "ליצור רשימה עם הפריט %1 %2 פעמים", - "LISTS_LENGTH_TITLE": "אורכו של %1", - "LISTS_LENGTH_TOOLTIP": "מחזירה את האורך של רשימה.", - "LISTS_ISEMPTY_TITLE": "%1 הוא ריק", - "LISTS_ISEMPTY_TOOLTIP": "מחזיר אמת אם הרשימה ריקה.", - "LISTS_INLIST": "ברשימה", - "LISTS_INDEX_OF_FIRST": "מחזירה את המיקום הראשון של פריט ברשימה", - "LISTS_INDEX_OF_LAST": "מחזירה את המיקום האחרון של פריט ברשימה", - "LISTS_INDEX_OF_TOOLTIP": "מחזירה את האינדקס של המופע הראשון/האחרון של הפריט ברשימה. מחזירה %1 אם הפריט אינו נמצא.", - "LISTS_GET_INDEX_GET": "לקבל", - "LISTS_GET_INDEX_GET_REMOVE": "קבל ומחק", - "LISTS_GET_INDEX_REMOVE": "הסרה", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# מהסוף", - "LISTS_GET_INDEX_FIRST": "ראשון", - "LISTS_GET_INDEX_LAST": "אחרון", - "LISTS_GET_INDEX_RANDOM": "אקראי", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 הוא הפריט הראשון.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 הוא הפריט האחרון.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "מחזיר פריט במיקום שצוין ברשימה.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "מחזיר את הפריט הראשון ברשימה.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "מחזיר את הפריט האחרון ברשימה.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "מחזיר פריט אקראי מהרשימה.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "מסיר ומחזיר את הפריט במיקום שצוין ברשימה.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "מסיר ומחזיר את הפריט הראשון ברשימה.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "מסיר ומחזיר את הפריט האחרון ברשימה.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "מחק והחזר פריט אקראי מהרשימה.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "מחזיר פריט במיקום שצוין ברשימה.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "הסר את הפריט הראשון ברשימה.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "הסר את הפריט הראשון ברשימה.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "הסר פריט אקראי ברשימה.", - "LISTS_SET_INDEX_SET": "הגדר", - "LISTS_SET_INDEX_INSERT": "הכנס ב", - "LISTS_SET_INDEX_INPUT_TO": "כמו", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "מגדיר את הפריט במיקום שצוין ברשימה.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "מגדיר את הפריט הראשון ברשימה.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "מגדיר את הפריט האחרון ברשימה.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "מגדיר פריט אקראי ברשימה.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "מכניס את הפריט במיקום שצוין ברשימה.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "מכניס את הפריט בתחילת רשימה.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "מוסיף את הפריט בסוף רשימה.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "הוסף פריט באופן אקראי ברשימה.", - "LISTS_GET_SUBLIST_START_FROM_START": "לקבל חלק מהרשימה החל מ-#", - "LISTS_GET_SUBLIST_START_FROM_END": "לקבל חלק מהרשימה החל מ-# עד הסוף", - "LISTS_GET_SUBLIST_START_FIRST": "לקבל חלק מהרשימה החל מהתחלה", - "LISTS_GET_SUBLIST_END_FROM_START": "ל #", - "LISTS_GET_SUBLIST_END_FROM_END": "ל # מהסוף", - "LISTS_GET_SUBLIST_END_LAST": "לאחרון", - "LISTS_GET_SUBLIST_TOOLTIP": "יוצרת עותק של חלק מסוים מהרשימה.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_ORDER_ASCENDING": "סדר עולה", - "LISTS_SORT_ORDER_DESCENDING": "סדר יורד", - "LISTS_SORT_TYPE_TEXT": "סדר אלפביתי", - "LISTS_SORT_TYPE_IGNORECASE": "סדר אלפביתי, לא תלוי רישיות", - "LISTS_SPLIT_LIST_FROM_TEXT": "יצירת רשימה מטקסט", - "LISTS_SPLIT_TEXT_FROM_LIST": "יצירת טקסט מרשימה", - "VARIABLES_GET_TOOLTIP": "להחזיר את הערך של משתנה זה.", - "VARIABLES_GET_CREATE_SET": "ליצור 'הגדר %1'", - "VARIABLES_SET": "הגדר %1 ל- %2", - "VARIABLES_SET_TOOLTIP": "מגדיר משתנה זה להיות שווה לקלט.", - "VARIABLES_SET_CREATE_GET": "ליצור 'קרא %1'", - "PROCEDURES_DEFNORETURN_TITLE": "לביצוע:", - "PROCEDURES_DEFNORETURN_PROCEDURE": "לעשות משהו", - "PROCEDURES_BEFORE_PARAMS": "עם:", - "PROCEDURES_CALL_BEFORE_PARAMS": "עם:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "יצירת פונקציה ללא פלט.", - "PROCEDURES_DEFRETURN_RETURN": "להחזיר", - "PROCEDURES_DEFRETURN_TOOLTIP": "יצירת פונקציה עם פלט.", - "PROCEDURES_ALLOW_STATEMENTS": "לאפשר פעולות", - "PROCEDURES_DEF_DUPLICATE_WARNING": "אזהרה: לפונקציה זו יש פרמטרים כפולים.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://he.wikipedia.org/wiki/שגרה_(תכנות)", - "PROCEDURES_CALLNORETURN_TOOLTIP": "להפעיל את הפונקציה המוגדרת על-ידי המשתמש '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "https://he.wikipedia.org/wiki/שגרה_(תכנות)", - "PROCEDURES_CALLRETURN_TOOLTIP": "להפעיל את הפונקציה המוגדרת על-ידי המשתמש '%1' ולהשתמש הפלט שלה.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "מקורות קלט", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "הוסף, הסר או סדר מחדש קלטים לפונקציה זו", - "PROCEDURES_MUTATORARG_TITLE": "שם הקלט:", - "PROCEDURES_MUTATORARG_TOOLTIP": "הוסף קלט לפונקציה", - "PROCEDURES_HIGHLIGHT_DEF": "הדגש הגדרה של פונקציה", - "PROCEDURES_CREATE_DO": "ליצור '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "אם ערך נכון, אז להחזיר ערך שני.", - "PROCEDURES_IFRETURN_WARNING": "אזהרה: בלוק זה עשוי לשמש רק בתוך הגדרה של פונקציה." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/hi.json b/backend/_pv_1_3_5/static/blockly/msg/json/hi.json deleted file mode 100755 index c90cd1c00..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/hi.json +++ /dev/null @@ -1,251 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Bl707", - "संजीव कुमार", - "Phoenix303", - "Sfic" - ] - }, - "VARIABLES_DEFAULT_NAME": "आइटम", - "TODAY": "आज", - "DUPLICATE_BLOCK": "कॉपी करें", - "ADD_COMMENT": "टिप्पणी छोड़ें", - "REMOVE_COMMENT": "टिप्पणी हटायें", - "EXTERNAL_INPUTS": "बाहरी इनपुट", - "INLINE_INPUTS": "इनलाइन इनपुट", - "DELETE_BLOCK": "ब्लॉक हटाएँ", - "DELETE_X_BLOCKS": "%1 ब्लॉक हटाएँ", - "COLLAPSE_BLOCK": "ब्लॉक को संक्षिप्त करें", - "COLLAPSE_ALL": "ब्लॉक संक्षिप्त करें", - "EXPAND_BLOCK": "ब्लॉक का विस्तार करें", - "EXPAND_ALL": "ब्लॉक विस्तार करें", - "DISABLE_BLOCK": "ब्लॉक को अक्षम करें", - "ENABLE_BLOCK": "ब्लॉक को सक्षम करें", - "HELP": "सहायता", - "CHANGE_VALUE_TITLE": "मान परिवर्तित करें:", - "RENAME_VARIABLE": "चर का नाम बदलें...", - "RENAME_VARIABLE_TITLE": "सभी '%1' चरों के नाम बदलें:", - "NEW_VARIABLE": "नया चर...", - "NEW_VARIABLE_TITLE": "नए चर का नाम:", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "पैलेट से एक रंग चुनें।", - "COLOUR_RANDOM_TITLE": "रैन्डम रंग", - "COLOUR_RANDOM_TOOLTIP": "रैन्डम्ली एक रंग चयन करें।", - "COLOUR_RGB_TITLE": "इसके साथ रंग करें", - "COLOUR_RGB_RED": "लाल", - "COLOUR_RGB_GREEN": "हरा", - "COLOUR_RGB_BLUE": "नीला", - "COLOUR_RGB_TOOLTIP": "लाल, हरा और नीले की निर्दिष्ट मात्रा के साथ एक रंग बनायें। सभी मान ० से १०० के बीच होने चाहिए।", - "COLOUR_BLEND_TITLE": "मिश्रण करें", - "COLOUR_BLEND_COLOUR1": "रंग 1", - "COLOUR_BLEND_COLOUR2": "रंग 2", - "COLOUR_BLEND_RATIO": "अनुपात", - "COLOUR_BLEND_TOOLTIP": "दिए गए अनुपात (0.0 - 1.0) के साथ दो रंगों का मिश्रण करता है।", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "%1 बार दोहराएँ", - "CONTROLS_REPEAT_INPUT_DO": "डू", - "CONTROLS_REPEAT_TOOLTIP": "कुछ स्टेट्मन्ट कई बार चलाएँ।", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "दोहराएँ जब कि", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "दोहराएँ जब तक", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "जब तक मान ट्रू है, तब तक कुछ स्टेट्मेंट्स चलाएँ।", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "जब तक मान फॉल्स है, तब तक कुछ स्टेट्मेंट्स चलाएँ।", - "CONTROLS_FOR_TITLE": "काउंट करें", - "CONTROLS_FOREACH_TITLE": "प्रत्येक आइटम के लिए %1 सूची में %2", - "CONTROLS_FOREACH_TOOLTIP": "सूची के प्रत्येक आयटम के लिए, आयटम में चर का मान '%1' रखें और बाद में कुछ कथन लिखें।", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "लूप से बाहर निकलें", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "लूप का अगला आईटरेशन जारी रखें", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "भीतरी लूप से बाहर निकलें।", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "बाकी बचे लूप को छोड़ें, और अगला आईटरेशन जारी रखें।", - "CONTROLS_FLOW_STATEMENTS_WARNING": "सावधान: ये ब्लॉक केवल लूप के अंदर इस्तेमाल किया जा सकता है।", - "CONTROLS_IF_TOOLTIP_1": "यदी मान ट्रू है, तो कुछ स्टेट्मेंट्स चलाएँ।", - "CONTROLS_IF_TOOLTIP_2": "यदि एक मान सत्य है तो कथनों का प्रथम खण्ड बनायें। अन्यथा कथनों का दूसरा भाग निर्मित करें।", - "CONTROLS_IF_MSG_IF": "इफ", - "CONTROLS_IF_MSG_ELSEIF": "एल्स इफ", - "CONTROLS_IF_MSG_ELSE": "एल्स", - "CONTROLS_IF_ELSEIF_TOOLTIP": "यदि ब्लॉक मे एक शर्त जोड़ें।", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "ट्रू रिटर्न करें यदि दोनो इनपुट इक दूसरे के बराबर हों।", - "LOGIC_COMPARE_TOOLTIP_NEQ": "ट्रू रिटर्न करें यदि दोनो इनपुट इक दूसरे के बराबर नहीं हों।", - "LOGIC_COMPARE_TOOLTIP_LT": "ट्रू रिटर्न करें यदि पहला इनपुट दूसरे इनपुट से छोटा हो।", - "LOGIC_COMPARE_TOOLTIP_LTE": "ट्रू रिटर्न करें यदि पहला इनपुट दूसरे इनपुट से छोटा हो या बराबर हो।", - "LOGIC_COMPARE_TOOLTIP_GT": "ट्रू रिटर्न करें यदि पहला इनपुट दूसरे इनपुट से बड़ा हो।", - "LOGIC_COMPARE_TOOLTIP_GTE": "ट्रू रिटर्न करें यदि पहला इनपुट दूसरे इनपुट से बड़ा हो या बराबर हो।", - "LOGIC_OPERATION_TOOLTIP_AND": "ट्रू रिटर्न करें यदि दोनो इनपुट ट्रू हों।", - "LOGIC_OPERATION_AND": "AND (तथा)", - "LOGIC_OPERATION_TOOLTIP_OR": "ट्रू रिटर्न करें यदि दोनो मे से इक इनपुट ट्रू हो।", - "LOGIC_OPERATION_OR": "OR (अथवा)", - "LOGIC_NEGATE_TITLE": "NOT (पूरक) %1", - "LOGIC_NEGATE_TOOLTIP": "ट्रू रिटर्न करता है यदि इनपुट फॉल्स है। फॉल्स रिटर्न करता है यदि इनपुट ट्रू है।", - "LOGIC_BOOLEAN_TRUE": "ट्रू", - "LOGIC_BOOLEAN_FALSE": "फॉल्स", - "LOGIC_BOOLEAN_TOOLTIP": "ट्रू या फॉल्स रिटर्न करता है।", - "LOGIC_NULL": "NULL (अमान्य)", - "LOGIC_NULL_TOOLTIP": "null (अमान्य) रिटर्न करता है।", - "LOGIC_TERNARY_CONDITION": "टेस्ट", - "LOGIC_TERNARY_IF_TRUE": "यदि ट्रू है", - "LOGIC_TERNARY_IF_FALSE": "यदि फॉल्स है", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "एक संख्या।", - "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/Arithmetic", - "MATH_ARITHMETIC_TOOLTIP_ADD": "दो संख्याओं का योग रिटर्न करें।", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "दो संख्याओं का अंतर रिटर्न करें।", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "दो संख्याओं का गुणन रिटर्न करें।", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "दो संख्याओं का भागफल रिटर्न करें।", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "वर्गमूल", - "MATH_SINGLE_TOOLTIP_ROOT": "संख्या का वर्गमूल रिटर्न करें।", - "MATH_SINGLE_OP_ABSOLUTE": "परम", - "MATH_SINGLE_TOOLTIP_ABS": "संख्या का परम मान रिटर्न करें।", - "MATH_SINGLE_TOOLTIP_NEG": "संख्या का निषेध मान रिटर्न करें।", - "MATH_SINGLE_TOOLTIP_LN": "संख्या का प्राकृतिक लघुगणक रिटर्न करें।", - "MATH_SINGLE_TOOLTIP_LOG10": "संख्या का मूल 10 लघुगणक रिटर्न करें।", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "डिग्री का साइन रिटर्न करें (रेडियन नही)", - "MATH_TRIG_TOOLTIP_COS": "डिग्री का कोसाइन रिटर्न करें (रेडियन नही)", - "MATH_TRIG_TOOLTIP_TAN": "डिग्री का टैन्जन्ट रिटर्न करें (रेडियन नही)", - "MATH_TRIG_TOOLTIP_ASIN": "संख्या का आर्कसाइन रिटर्न करें।", - "MATH_TRIG_TOOLTIP_ACOS": "संख्या का आर्ककोसाइन रिटर्न करें।", - "MATH_TRIG_TOOLTIP_ATAN": "संख्या का आर्कटैन्जन्ट रिटर्न करें।", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_IS_EVEN": "सम है", - "MATH_IS_ODD": "विषम है", - "MATH_IS_PRIME": "अभाज्य है", - "MATH_IS_WHOLE": "पूर्णांक है", - "MATH_IS_POSITIVE": "धनात्मक है", - "MATH_IS_NEGATIVE": "ऋणात्मक है", - "MATH_IS_DIVISIBLE_BY": "इसके द्वारा विभाज्य है", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TOOLTIP": "संख्या को चर '%1' से जोड़ें।", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "संख्या को बड़ा या घटा के पूर्णांक बनाएँ।", - "MATH_ROUND_OPERATOR_ROUND": "पूर्णांक बनाएँ", - "MATH_ROUND_OPERATOR_ROUNDUP": "बड़ा के पूर्णांक बनाएँ", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "घटा के पूर्णांक बनाएँ", - "MATH_ONLIST_OPERATOR_SUM": "सूची का योग", - "MATH_ONLIST_TOOLTIP_SUM": "सूची की सभी संख्याओं का योग रिटर्न करें।", - "MATH_ONLIST_OPERATOR_MIN": "सूची मे न्यूनतम", - "MATH_ONLIST_TOOLTIP_MIN": "सूची मे सबसे छोटी संख्या रिटर्न करें।", - "MATH_ONLIST_OPERATOR_MAX": "सूची मे अधिकतम", - "MATH_ONLIST_TOOLTIP_MAX": "सूची मे सबसे बड़ी संख्या रिटर्न करें।", - "MATH_ONLIST_OPERATOR_AVERAGE": "सूची का औसत मान", - "MATH_ONLIST_OPERATOR_MEDIAN": "सूची की माध्यिका", - "MATH_ONLIST_TOOLTIP_MEDIAN": "सूची की माध्यिका संख्या रिटर्न करें।", - "MATH_ONLIST_OPERATOR_MODE": "सूची का मोड", - "MATH_ONLIST_TOOLTIP_MODE": "सूची मे सबसे आम आइटम(s) की सूची रिटर्न करें।", - "MATH_ONLIST_OPERATOR_STD_DEV": "सूची का मानक विचलन", - "MATH_ONLIST_TOOLTIP_STD_DEV": "सूची का मानक विचलन रिटर्न करें।", - "MATH_ONLIST_OPERATOR_RANDOM": "सूची का रैन्डम आइटम", - "MATH_ONLIST_TOOLTIP_RANDOM": "सूची से एक रैन्डम आइटम रिटर्न करें।", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "%1 ÷ %2 का शेषफल", - "MATH_MODULO_TOOLTIP": "दो संख्याओं के भाग का शेषफल रिटर्न करें।", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "%1 से %2 तक रैन्डम पूर्णांक", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "रैन्डम अंश", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "एक अक्षर, शब्द, या टेक्स्ट की पंक्ति।", - "TEXT_JOIN_TITLE_CREATEWITH": "इसके साथ टेक्स्ट बनाएँ", - "TEXT_CREATE_JOIN_TITLE_JOIN": "जोड़", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "सूची मे एक आइटम जोड़ें।", - "TEXT_APPEND_TO": "इस", - "TEXT_APPEND_APPENDTEXT": "से जोड़ें ये टेक्स्ट", - "TEXT_APPEND_TOOLTIP": "कुछ टेक्स्ट इस चर '%1' से जोड़ें।", - "TEXT_LENGTH_TITLE": "%1 की लंबाई", - "TEXT_LENGTH_TOOLTIP": "दिए गये टेक्स्ट मे अक्षरों की संख्या रिटर्न करता है (खाली स्थान मिला के)।", - "TEXT_ISEMPTY_TITLE": "%1 खाली है", - "TEXT_ISEMPTY_TOOLTIP": "ट्रू रिटर्न करता है यदि दिया गया टेक्स्ट खाली है।", - "TEXT_INDEXOF_INPUT_INTEXT": "इस टेक्स्ट मे", - "TEXT_INDEXOF_OPERATOR_FIRST": "टेक्स्ट पहली बार जहाँ आया है उसे ढूढ़े", - "TEXT_INDEXOF_OPERATOR_LAST": "टेक्स्ट आखरी बार जहाँ आया है उसे ढूढ़े", - "TEXT_CHARAT_INPUT_INTEXT": "इस टेक्स्ट मे", - "TEXT_CHARAT_FROM_START": "अक्षर # पाएँ", - "TEXT_CHARAT_FROM_END": "आखिर से अक्षर # पाएँ", - "TEXT_CHARAT_FIRST": "पहला अक्षर पाएँ", - "TEXT_CHARAT_LAST": "आखरी अक्षर पाएँ", - "TEXT_CHARAT_RANDOM": "रैन्डम अक्षर पाएँ", - "TEXT_CHARAT_TOOLTIP": "बताई गयी जगह से अक्षर रिटर्न करता है", - "TEXT_GET_SUBSTRING_TOOLTIP": "टेक्स्ट का बताया गया अंश रिटर्न करता है", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "इस टेक्स्ट मे", - "TEXT_GET_SUBSTRING_START_FROM_START": "अक्षर # से सबस्ट्रिंग पाएँ", - "TEXT_GET_SUBSTRING_START_FROM_END": "आखरी अक्षर # से सबस्ट्रिंग पाएँ", - "TEXT_GET_SUBSTRING_START_FIRST": "पहले अक्षर से सबस्ट्रिंग पाएँ", - "TEXT_GET_SUBSTRING_END_FROM_START": "यहाँ तक अक्षर #", - "TEXT_GET_SUBSTRING_END_FROM_END": "आखिर से यहाँ तक अक्षर #", - "TEXT_GET_SUBSTRING_END_LAST": "यहाँ तक आखरी अक्षर", - "TEXT_CHANGECASE_TOOLTIP": "टेक्स्ट की कॉपी भिन्न केस (अक्षर से संबंधित) मे रिटर्न करें।", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "बड़े अक्षर मे", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "छोटे अक्षर मे", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "टाइटल केस मे", - "TEXT_TRIM_OPERATOR_BOTH": "रिक्त स्थान को इस टेक्स्ट के दोनों तरफ से निकालें", - "TEXT_TRIM_OPERATOR_LEFT": "रिक्त स्थान को इस टेक्स्ट के बायें तरफ से निकालें", - "TEXT_TRIM_OPERATOR_RIGHT": "रिक्त स्थान को इस टेक्स्ट के दाईं तरफ से निकालें", - "TEXT_PRINT_TITLE": "प्रिंट करें %1", - "TEXT_PRINT_TOOLTIP": "दिया गया टेक्स्ट प्रिंट करें, संख्या या अन्य मान।", - "TEXT_PROMPT_TYPE_TEXT": "सूचना के साथ टेक्स्ट के लिए प्रॉम्प्ट करें", - "TEXT_PROMPT_TYPE_NUMBER": "सूचना के साथ संख्या के लिए प्रॉम्प्ट करें", - "TEXT_PROMPT_TOOLTIP_NUMBER": "यूज़र से संख्या के लिए प्रॉम्प्ट करें।", - "TEXT_PROMPT_TOOLTIP_TEXT": "यूज़र से कुछ टेक्स्ट के लिए प्रॉम्प्ट करें।", - "LISTS_CREATE_EMPTY_TITLE": "खाली सूची बनाएँ", - "LISTS_CREATE_WITH_TOOLTIP": "कितने भी आइटम वाली एक सूची बनाएँ।", - "LISTS_CREATE_WITH_INPUT_WITH": "इसके सूची बनाएँ", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "सूची", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "सूची मे एक आइटम जोड़ें।", - "LISTS_LENGTH_TITLE": "%1 की लंबाई", - "LISTS_LENGTH_TOOLTIP": "सूची की लंबाई रिटर्न करता है।", - "LISTS_ISEMPTY_TITLE": "%1 खाली है", - "LISTS_ISEMPTY_TOOLTIP": "यदि सूची खाली है तो ट्रू रिटर्न करता है।", - "LISTS_INLIST": "सूची में", - "LISTS_INDEX_OF_FIRST": "आइटम पहली बार जहाँ आया है उसे ढूढ़े", - "LISTS_INDEX_OF_LAST": "आइटम आखरी बार जहाँ आया है उसे ढूढ़े", - "LISTS_GET_INDEX_GET": "प्राप्त", - "LISTS_GET_INDEX_GET_REMOVE": "प्राप्त करे और हटाए", - "LISTS_GET_INDEX_REMOVE": "निकालें", - "LISTS_GET_INDEX_FROM_END": "अंत से #", - "LISTS_GET_INDEX_FIRST": "%1 पहला आइटम है।", - "LISTS_GET_INDEX_LAST": "%1 आखरी आइटम है।", - "LISTS_GET_INDEX_RANDOM": "रैन्डम", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "सूची का पहला आइटम रिटर्न करता है।", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "सूची का आखरी आइटम रिटर्न करता है।", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "सूची से रैन्डम आइटम रिटर्न करता है।", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "सूची का पहला आइटम निकालता है और रिटर्न करता है।", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "सूची का आखरी आइटम निकालता है और रिटर्न करता है।", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "सूची से रैन्डम आइटम निकालता है और रिटर्न करता है।", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "सूची का पहला आइटम निकालता है।", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "सूची का आखरी आइटम निकालता है।", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "सूची से रैन्डम आइटम निकालता है।", - "LISTS_SET_INDEX_SET": "सैट करें", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "सूची मे बताए गये स्थान में आइटम सैट करता है।", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "सूची में पहला आइटम सैट करता है।", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "सूची में आखरी आइटम सैट करता है।", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "सूची में रैन्डम आइटम सैट करता है।", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "सूची मे बताए गये स्थान में आइटम इनसर्ट करता है।", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "आइटम को सूची के शुरू में इनसर्ट करता है।", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "आइटम को सूची के अंत में जोड़ता है।", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "आइटम को सूची में रैन्डम्ली इनसर्ट करता है।", - "LISTS_GET_SUBLIST_TOOLTIP": "सूची के बताए गये भाग की कॉपी बनता है।", - "LISTS_SORT_TYPE_NUMERIC": "अंकीय", - "VARIABLES_GET_TOOLTIP": "इस चर का मान रिटर्न करता है।", - "VARIABLES_GET_CREATE_SET": "सेट '%1' बनाएँ", - "VARIABLES_SET": "सेट करें %1 को %2", - "VARIABLES_SET_TOOLTIP": "इस चर को इनपुट के बराबर सेट करता है।", - "PROCEDURES_DEFNORETURN_PROCEDURE": "कुछ करें", - "PROCEDURES_BEFORE_PARAMS": ": के साथ", - "PROCEDURES_CALL_BEFORE_PARAMS": ": के साथ", - "PROCEDURES_DEFNORETURN_TOOLTIP": "बिना आउटपुट वाला एक फ़ंक्शन बनाता है।", - "PROCEDURES_DEFRETURN_RETURN": "रिटर्न", - "PROCEDURES_DEFRETURN_TOOLTIP": "आउटपुट वाला एक फ़ंक्शन बनाता है।", - "PROCEDURES_DEF_DUPLICATE_WARNING": "सावधान: इस फ़ंक्शन मे डुप्लिकेट पैरामीटर हैं।", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "यूज़र द्वारा वर्णन किया गया फ़ंक्शन '%1' चलाएँ।", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "यूज़र द्वारा वर्णन किया गया फ़ंक्शन '%1' चलाएँ और उसका आउटपुट इस्तेमाल करें।", - "PROCEDURES_MUTATORCONTAINER_TITLE": "इनपुट", - "PROCEDURES_MUTATORARG_TITLE": "इनपुट का नाम:", - "PROCEDURES_MUTATORARG_TOOLTIP": "फंगक्शन को इनपुट प्रदान करें।", - "PROCEDURES_HIGHLIGHT_DEF": "फ़ंक्शन परिभाषा को हाइलाइट करें", - "PROCEDURES_CREATE_DO": "'%1' बनाएँ", - "PROCEDURES_IFRETURN_TOOLTIP": "यदि एक मान ट्रू है तो, दूसरा मान रिटर्न करें।", - "PROCEDURES_IFRETURN_WARNING": "सावधान: ये ब्लॉक फ़ंक्शन परिभाषा के अंदर ही इस्तेमाल किया जा सकता।" -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/hrx.json b/backend/_pv_1_3_5/static/blockly/msg/json/hrx.json deleted file mode 100755 index 8f9e8c72c..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/hrx.json +++ /dev/null @@ -1,289 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Paul Beppler" - ] - }, - "VARIABLES_DEFAULT_NAME": "Element", - "DUPLICATE_BLOCK": "Kopieren", - "ADD_COMMENT": "Kommentar hinzufüche", - "REMOVE_COMMENT": "Kommentar entferne", - "EXTERNAL_INPUTS": "External Inputsexterne Ingänge", - "INLINE_INPUTS": "interne Ingänge", - "DELETE_BLOCK": "Block lösche", - "DELETE_X_BLOCKS": "Block %1 lösche", - "DELETE_ALL_BLOCKS": "All %1 Bausten lösche?", - "COLLAPSE_BLOCK": "Block zusammerfalte", - "COLLAPSE_ALL": "Blocke zusammerfalte", - "EXPAND_BLOCK": "Block entfalte", - "EXPAND_ALL": "Blocke expandiere", - "DISABLE_BLOCK": "Block deaktivieren", - "ENABLE_BLOCK": "Block aktivieren", - "HELP": "Hellef", - "CHANGE_VALUE_TITLE": "Neie Variable...", - "RENAME_VARIABLE": "Die neie Variable sei Noome:", - "RENAME_VARIABLE_TITLE": "All \"%1\" Variable umbenenne in:", - "NEW_VARIABLE": "Neie Variable...", - "NEW_VARIABLE_TITLE": "Die neie Variable sei Noome:", - "COLOUR_PICKER_HELPURL": "https://hrx.wikipedia.org/wiki/Farreb", - "COLOUR_PICKER_TOOLTIP": "Wähl en Farreb von der Palett.", - "COLOUR_RANDOM_TITLE": "zufälliche Farwe", - "COLOUR_RANDOM_TOOLTIP": "Wähl en Farreb noh dem Zufallsprinzip.", - "COLOUR_RGB_TITLE": "Färreb mit", - "COLOUR_RGB_RED": "rot", - "COLOUR_RGB_GREEN": "grün", - "COLOUR_RGB_BLUE": "blau", - "COLOUR_RGB_TOOLTIP": "Kreiere ene Farreb mit sellrbst definierte rot, grün und blau Wearte. All Wearte müsse zwischich 0 und 100 liehe.", - "COLOUR_BLEND_TITLE": "misch", - "COLOUR_BLEND_COLOUR1": "Farreb 1", - "COLOUR_BLEND_COLOUR2": "mit Farreb 2", - "COLOUR_BLEND_RATIO": "im Verhältniss", - "COLOUR_BLEND_TOOLTIP": "Vermischt 2 Farwe mit konfigurierbare Farrebverhältniss (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://hrx.wikipedia.org/wiki/For-Schleif", - "CONTROLS_REPEAT_TITLE": "wiederhol %1 mol", - "CONTROLS_REPEAT_INPUT_DO": "mach", - "CONTROLS_REPEAT_TOOLTIP": "En Oonweisung meahrfach ausführe.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "Repetier solang", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "Repetiere bis", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Füahr die Oonweisung solang aus wie die Bedingung woahr (true) ist.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Füahr die Oonweisung solang aus wie die Bedingung falsch (false) ist.", - "CONTROLS_FOR_TOOLTIP": "Zähl die Variable \"%1\" von enem Startweart bis zu enem Zielweart und füahrefür jede Weart en Oonweisung aus.", - "CONTROLS_FOR_TITLE": "Zähl %1 von %2 bis %3 mit %4", - "CONTROLS_FOREACH_TITLE": "Für Weart %1 aus der List %2", - "CONTROLS_FOREACH_TOOLTIP": "Füahr en Oonweisung für jede Weart in der List aus und setzt dabei die Variable \"%1\" uff den aktuelle List Weart.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "ausbreche aus der Schleif", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "mit der nächste Iteration fortfoohre aus der Schleifa", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Die umgebne Schleif beenne.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Die Oonweisung abbreche und mit der nächste Schleifiteration fortfoohre.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Warnung: Die block sollt nuar in en Schleif verwennet sin.", - "CONTROLS_IF_TOOLTIP_1": "Wenn en Bedingung woahr (true) ist, dann füahr en Oonweisung aus.", - "CONTROLS_IF_TOOLTIP_2": "Wenn en Bedingung woahr (true) ist, dann füahr die earscht Oonweisung aus. Ansonscht füahr die zwooite Oonweisung aus.", - "CONTROLS_IF_TOOLTIP_3": "Wenn der erschte Bedingung woahr (true) ist, dann füahr die erschte Oonweisung aus. Orrer wenn die zwooite Bedingung woahr (true) ist, dann füahr die zwooite Oonweisung aus.", - "CONTROLS_IF_TOOLTIP_4": "Wenn der erscht Bedingung woahr (true) ist, dann füahr die erschte Oonweisung aus. Orrer wenn die zwooite Bedingung woahr (true) ist, dann füahr die zwooite Oonweisung aus. Falls ken der beide Bedingungen woahr (true) ist, dann füahr die dritte Oonweisung aus.", - "CONTROLS_IF_MSG_IF": "wenn", - "CONTROLS_IF_MSG_ELSEIF": "orrer wenn", - "CONTROLS_IF_MSG_ELSE": "orrer", - "CONTROLS_IF_IF_TOOLTIP": "Hinzufüche, entferne orrer sortiere von Sektione", - "CONTROLS_IF_ELSEIF_TOOLTIP": "En weitre Bedingung hinzufüche.", - "CONTROLS_IF_ELSE_TOOLTIP": "En orrer Bedingung hinzufüche, füahrt en Oonweisung aus falls ken Bedingung zutrifft.", - "LOGIC_COMPARE_HELPURL": "https://hrx.wikipedia.org/wiki/Vergleich_%28Zahlen%29", - "LOGIC_COMPARE_TOOLTIP_EQ": "Ist woahr (true) wenn beide Wearte identisch sind.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Ist woahr (true) wenn beide Wearte unnerschiedlich sind.", - "LOGIC_COMPARE_TOOLTIP_LT": "Ist woahr (true) wenn der earschte Weart klener als der zwooite Weart ist.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Ist woahr (true) wenn der earscht Weart klener als orrer gleich gross wie zwooite Weart ist.", - "LOGIC_COMPARE_TOOLTIP_GT": "Ist woahr (true) wenn der erschte Weart grösser als der zwooite Weart ist.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Ist woahr (true) wenn der erschte Weart grösser als orrer gleich gross wie zwooite Weart ist.", - "LOGIC_OPERATION_TOOLTIP_AND": "Ist woahr (true) wenn beide Wearte woahr (true) sind.", - "LOGIC_OPERATION_AND": "und", - "LOGIC_OPERATION_TOOLTIP_OR": "Ist woahr (true) wenn en von der beide Wearte woahr (true) ist.", - "LOGIC_OPERATION_OR": "orrer", - "LOGIC_NEGATE_TITLE": "net %1", - "LOGIC_NEGATE_TOOLTIP": "Ist woahr (true) wenn der Ingäweweart falsch (false) ist. Ist falsch (false) wenn der Ingäweweart woahr (true) ist.", - "LOGIC_BOOLEAN_TRUE": "woahr", - "LOGIC_BOOLEAN_FALSE": "falsch", - "LOGIC_BOOLEAN_TOOLTIP": "Ist entweder woahr (true) orrer falsch (false)", - "LOGIC_NULL": "null", - "LOGIC_NULL_TOOLTIP": "Is NULL.", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "wenn woahr", - "LOGIC_TERNARY_IF_FALSE": "wenn falsch", - "LOGIC_TERNARY_TOOLTIP": "Üwerprüft en Bedingung \"test\". Wenn die Bedingung woahr ist weerd der \"wenn woahr\" Weart zurückgeb, annerfalls der \"wenn falsch\" Weart", - "MATH_NUMBER_HELPURL": "https://hrx.wikipedia.org/wiki/Zoohl", - "MATH_NUMBER_TOOLTIP": "En Zoohl.", - "MATH_ARITHMETIC_HELPURL": "https://hrx.wikipedia.org/wiki/Grundrechenoort", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Ist die Summe zwooier Wearte.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Ist die Differenz zwooier Wearte.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Ist das Produkt zwooier Wearte.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Ist der Quotient zwooier Wearte.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Ist der earschte Weart potenziert mit dem zoiten Weart.", - "MATH_SINGLE_HELPURL": "https://hrx.wikipedia.org/wiki/Quadratwoorzel", - "MATH_SINGLE_OP_ROOT": "Quadratwoorzel", - "MATH_SINGLE_TOOLTIP_ROOT": "Ist die Qudratwoorzel von en Weart.", - "MATH_SINGLE_OP_ABSOLUTE": "Absolutweart", - "MATH_SINGLE_TOOLTIP_ABS": "Ist der Absolutweart von en Weart.", - "MATH_SINGLE_TOOLTIP_NEG": "Negiert en Weart.", - "MATH_SINGLE_TOOLTIP_LN": "Ist der natüarliche Logarithmus von en Weart.", - "MATH_SINGLE_TOOLTIP_LOG10": "Ist der dekoodische Logarithmus von en Weart.", - "MATH_SINGLE_TOOLTIP_EXP": "Ist Weart von der Exponentialfunktion von en Weart.", - "MATH_SINGLE_TOOLTIP_POW10": "Rechnet 10 hoch Ingäbweart.", - "MATH_TRIG_HELPURL": "https://hrx.wikipedia.org/wiki/Trigonometrie", - "MATH_TRIG_TOOLTIP_SIN": "Ist der Sinus von en Winkel.", - "MATH_TRIG_TOOLTIP_COS": "Ist der Cosinus von en Winkel.", - "MATH_TRIG_TOOLTIP_TAN": "Ist der Tangens von en Winkel.", - "MATH_TRIG_TOOLTIP_ASIN": "Ist der Arcussinus von en Ingäbweart.", - "MATH_TRIG_TOOLTIP_ACOS": "Ist der Arcuscosinus von en Ingabweart.", - "MATH_TRIG_TOOLTIP_ATAN": "Ist der Arcustangens von en Ingäbweart.", - "MATH_CONSTANT_HELPURL": "https://hrx.wikipedia.org/wiki/Mathematische_Konstante", - "MATH_CONSTANT_TOOLTIP": "Mathematische Konstante wie: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…) oder ∞ (unendlich).", - "MATH_IS_EVEN": "ist grood", - "MATH_IS_ODD": "ist ungrood", - "MATH_IS_PRIME": "ist en Primenzoohl", - "MATH_IS_WHOLE": "ganze Zoohl", - "MATH_IS_POSITIVE": "ist positiv", - "MATH_IS_NEGATIVE": "ist negativ", - "MATH_IS_DIVISIBLE_BY": "ist telbar/kann getelt sin doorrich", - "MATH_IS_TOOLTIP": "Üwerprüft ob en Zoohl grood, ungrood, en Primenzoohl, ganzzoohlich, positiv, negativ orrer doorrich en zwooite Zoohl telbar ist. Gebt woahr (true) orrer falsch (false) zurück.", - "MATH_CHANGE_HELPURL": "https://hrx.wikipedia.org/wiki/Inkrement_und_Dekrement", - "MATH_CHANGE_TITLE": "mach höcher / erhöhe %1 um %2", - "MATH_CHANGE_TOOLTIP": "Addiert en Weart zur Variable \"%1\" hinzu.", - "MATH_ROUND_HELPURL": "https://hrx.wikipedia.org/wiki/Runden", - "MATH_ROUND_TOOLTIP": "En Zoohl uff orrer ab runde.", - "MATH_ROUND_OPERATOR_ROUND": "runde", - "MATH_ROUND_OPERATOR_ROUNDUP": "uff runde", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "ab runde", - "MATH_ONLIST_OPERATOR_SUM": "Summe von en List", - "MATH_ONLIST_TOOLTIP_SUM": "Ist die Summ aller Wearte in en List.", - "MATH_ONLIST_OPERATOR_MIN": "Minimalweart von en List", - "MATH_ONLIST_TOOLTIP_MIN": "Ist der klenste Weart in en List.", - "MATH_ONLIST_OPERATOR_MAX": "Maximalweart en List", - "MATH_ONLIST_TOOLTIP_MAX": "Ist der grösste Weart in en List.", - "MATH_ONLIST_OPERATOR_AVERAGE": "Mittelweart en List", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Ist der Doorrichschnittsweart von aller Wearte in en List.", - "MATH_ONLIST_OPERATOR_MEDIAN": "Median von en List", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Ist der Zentralweart von aller Wearte in en List.", - "MATH_ONLIST_OPERATOR_MODE": "Restweart von en List", - "MATH_ONLIST_TOOLTIP_MODE": "Findt den am häifichste voarkommend Weart in en List. Falls ken Weart öftersch voarkomme als all annre, weard die originale List zurückgeche", - "MATH_ONLIST_OPERATOR_STD_DEV": "Standart/Padrong Abweichung von en List", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Ist die standartiesierte/padronisierte Standartabweichung/Padrongabweichung von aller Wearte in der List", - "MATH_ONLIST_OPERATOR_RANDOM": "Zufallsweart von en List", - "MATH_ONLIST_TOOLTIP_RANDOM": "Geb en Zufallsweart aus der List zurück.", - "MATH_MODULO_HELPURL": "https://hrx.wikipedia.org/wiki/Modulo", - "MATH_MODULO_TITLE": "Rest von %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Der Rest noh en Division.", - "MATH_CONSTRAIN_TITLE": "begrenze %1 von %2 bis %3", - "MATH_CONSTRAIN_TOOLTIP": "Begrenzt den Weartebereich mittels von / bis Wearte. (inklusiv)", - "MATH_RANDOM_INT_HELPURL": "https://hrx.wikipedia.org/wiki/Zufallszahlen", - "MATH_RANDOM_INT_TITLE": "ganzoohlicher Zufallswearte zwischich %1 bis %2", - "MATH_RANDOM_INT_TOOLTIP": "Generier/erzeich en ganzähliche Zufallsweart zwischich zwooi Wearte (inklusiv).", - "MATH_RANDOM_FLOAT_HELPURL": "https://hex.wikipedia.org/wiki/Zufallszoohle", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "Zufallszoohl (0.0 -1.0)", - "MATH_RANDOM_FLOAT_TOOLTIP": "Generier/erzeich en Zufallszoohl zwischich 0.0 (inklusiv) und 1.0 (exklusiv).", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)https://hrx.wikipedia.org/wiki/Zeichenkette", - "TEXT_TEXT_TOOLTIP": "En Buchstoob, Text orrer Satz.", - "TEXT_JOIN_TITLE_CREATEWITH": "Erstell Text aus", - "TEXT_JOIN_TOOLTIP": "Erstellt en Text doorrich das verbinne von mehre Textelemente.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "verbinne", - "TEXT_CREATE_JOIN_TOOLTIP": "Hinzufüche, entfernne und sortiere von Elemente.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "En Element zum Text hinzufüche.", - "TEXT_APPEND_TO": "An", - "TEXT_APPEND_APPENDTEXT": "Text oonhänge", - "TEXT_APPEND_TOOLTIP": "Text an die Variable \"%1\" oonhänge.", - "TEXT_LENGTH_TITLE": "läng %1", - "TEXT_LENGTH_TOOLTIP": "Die Oonzoohl von Zeiche in enem Text. (inkl. Leerzeiche)", - "TEXT_ISEMPTY_TITLE": "%1 ist leer?", - "TEXT_ISEMPTY_TOOLTIP": "Ist woahr (true), wenn der Text leer ist.", - "TEXT_INDEXOF_TOOLTIP": "Findt das earste / letzte Voarkommniss von en Suchbegriffes in enem Text. Gebt die Position von dem Begriff orrer %1 zurück.", - "TEXT_INDEXOF_INPUT_INTEXT": "im Text", - "TEXT_INDEXOF_OPERATOR_FIRST": "Such der Begriff sein earstes Voarkommniss", - "TEXT_INDEXOF_OPERATOR_LAST": "Suche der Begriff sein letztes Vorkommniss.", - "TEXT_CHARAT_INPUT_INTEXT": "in Text", - "TEXT_CHARAT_FROM_START": "hol Buchstoob #", - "TEXT_CHARAT_FROM_END": "hol Buchstoob # von End", - "TEXT_CHARAT_FIRST": "hol earschte Buchstoob", - "TEXT_CHARAT_LAST": "hol letztes Wort", - "TEXT_CHARAT_RANDOM": "hol zufälliches Buchstoob", - "TEXT_CHARAT_TOOLTIP": "Extrahiear en Buchstoob von en spezifizierte Position.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Schickt en bestimmstes Tel von dem Text retuar.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "in Text", - "TEXT_GET_SUBSTRING_START_FROM_START": "hol substring Buchstoob #te", - "TEXT_GET_SUBSTRING_START_FROM_END": "hol #te Buchstoob von hinne", - "TEXT_GET_SUBSTRING_START_FIRST": "earschte Buchstoob", - "TEXT_GET_SUBSTRING_END_FROM_START": "bis Buchstoob #te", - "TEXT_GET_SUBSTRING_END_FROM_END": "bis #te Buchstoob von hinne", - "TEXT_GET_SUBSTRING_END_LAST": "bis letzte Buchstoob", - "TEXT_CHANGECASE_TOOLTIP": "Wandelt Schreibweise von Texte um, in Grossbuchstoobe, Klenbuchstoobe orrer den earste Buchstoob von jedes Wort gross und die annre klen.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "umwandle in GROSSBUCHSTOOBE", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "umwandle in klenbuchstoobe", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "umwandle in Wörter", - "TEXT_TRIM_TOOLTIP": "Entfernt Leerzeiche vom Oonfang und / orrer End von en Text.", - "TEXT_TRIM_OPERATOR_BOTH": "entfern Leerzeiche von Oonfang und End Seite", - "TEXT_TRIM_OPERATOR_LEFT": "entferne Leerzeiche von Oonfang Seite", - "TEXT_TRIM_OPERATOR_RIGHT": "entferne Leerzeiche von End Seite von", - "TEXT_PRINT_TITLE": "Ausgäb %1", - "TEXT_PRINT_TOOLTIP": "Geb den Inhalt von en Variable aus.", - "TEXT_PROMPT_TYPE_TEXT": "Frocht noh Text mit Hinweis", - "TEXT_PROMPT_TYPE_NUMBER": "Frächt noh Zoohl mit Hinweis", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Frocht den Benutzer noh en Zoohl.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Frocht den Benutzer noh enem Text.", - "LISTS_CREATE_EMPTY_TITLE": "Generier/erzeich en leear List", - "LISTS_CREATE_EMPTY_TOOLTIP": "Generier/erzeich en leear List ohne Inhalt.", - "LISTS_CREATE_WITH_TOOLTIP": "Generier/erzeich en List mit konfigurierte Elemente.", - "LISTS_CREATE_WITH_INPUT_WITH": "Erzeich List mit", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "List", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Hinzufüche, entferne und sortiere von Elemente.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "En Element zur List hinzufüche.", - "LISTS_REPEAT_TOOLTIP": "Erzeicht en List mit en variable Oonzoohl von Elemente", - "LISTS_REPEAT_TITLE": "Erzich List mit Element %1 wiederhol das %2 mol", - "LISTS_LENGTH_TITLE": "länge %1", - "LISTS_LENGTH_TOOLTIP": "Die Oonzoohl von Elemente in der List.", - "LISTS_ISEMPTY_TITLE": "%1 ist leear?", - "LISTS_ISEMPTY_TOOLTIP": "Ist woahr (true), wenn die List leear ist.", - "LISTS_INLIST": "in der List", - "LISTS_INDEX_OF_FIRST": "Such earstes Voarkommniss", - "LISTS_INDEX_OF_LAST": "Such letztes Voarkommniss", - "LISTS_INDEX_OF_TOOLTIP": "Sucht die Position (index) von en Element in der List Gebt %1 zurück wenn nixs gefunn woard.", - "LISTS_GET_INDEX_GET": "Nehm", - "LISTS_GET_INDEX_GET_REMOVE": "Nehm und entfern", - "LISTS_GET_INDEX_REMOVE": "Entfern", - "LISTS_GET_INDEX_FROM_END": "#te von hinne", - "LISTS_GET_INDEX_FIRST": "earste", - "LISTS_GET_INDEX_LAST": "letzte", - "LISTS_GET_INDEX_RANDOM": "zufälliches", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 ist das earschte Element.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 ist das letzte Element.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Extrahiert das Element zu en definierte Stell von der List.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Extrahiert das earste Element von der List.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Extrahiert das letzte Element von der List.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Extrahiert en zufälliches Element von der List.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Extrahiert und entfernt das Element zu en definierte Stell von der List.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Extrahiert und entfernt das earste Element von der List.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Extrahiert und entfernt das letzte Element von der List.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Extrahiert und entfernt en zufälliches Element von der List.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Entfernt das Element zu en definierte Stell von der List.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Entfernt das earste Element von der List.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Entfernt das letzte Element von der List.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Entfernt en zufälliches Element von der List.", - "LISTS_SET_INDEX_SET": "setz", - "LISTS_SET_INDEX_INSERT": "tue ren setz an", - "LISTS_SET_INDEX_INPUT_TO": "uff", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Setzt das Element zu en definierte Stell in en List.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Sets the first item in a list.Setzt das earschte Element an en list.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Setzt das letzte Element an en List.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Setzt en zufälliches Element an en List.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Tut das Element ren setze an en definierte Stell an en List.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Tut das Element an en Oonfang von en List ren setze.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Oonhängt das Element zu en List sei End.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Tut das Element zufällich an en List ren setze.", - "LISTS_GET_SUBLIST_START_FROM_START": "hol Unnerlist von #", - "LISTS_GET_SUBLIST_START_FROM_END": "hol Unnerliste von # vom End", - "LISTS_GET_SUBLIST_START_FIRST": "hol Unnerliste vom Earste", - "LISTS_GET_SUBLIST_END_FROM_START": "zu #", - "LISTS_GET_SUBLIST_END_FROM_END": "zu # vom End", - "LISTS_GET_SUBLIST_END_LAST": "zum Letzte", - "LISTS_GET_SUBLIST_TOOLTIP": "Generiert en Kopie von en definierte Tel von en List.", - "VARIABLES_GET_TOOLTIP": "Gebt der Variable sein Weart zurück.", - "VARIABLES_GET_CREATE_SET": "Generier/erzeiche \"Schreibe %1\"", - "VARIABLES_SET": "Schreib %1 zu %2", - "VARIABLES_SET_TOOLTIP": "Setzt en Variable sei Weart.", - "VARIABLES_SET_CREATE_GET": "Generier/erzeich \"Lese %1\"", - "PROCEDURES_DEFNORETURN_TITLE": "zu", - "PROCEDURES_DEFNORETURN_PROCEDURE": "Funktionsblock", - "PROCEDURES_BEFORE_PARAMS": "mit:", - "PROCEDURES_CALL_BEFORE_PARAMS": "mit:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "En Funktionsblock ohne Rückgäbweart.", - "PROCEDURES_DEFRETURN_RETURN": "geb zurück", - "PROCEDURES_DEFRETURN_TOOLTIP": "En Funktionsblock mit Rückgäbweart.", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Warnung: die Funktionsblock hot doppelt Parameter.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://hrx.wikipedia.org/wiki/Prozedur_%28Programmierung%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Ruf en Funktionsblock ohne Rückgäweart uff.", - "PROCEDURES_CALLRETURN_HELPURL": "https://hrx.wikipedia.org/wiki/Prozedur_%28Programmierung%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Ruf en Funktionsblock mit Rückgäbweart uff.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "Parameter", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Variable:", - "PROCEDURES_MUTATORARG_TITLE": "Markiear Funktionsblock", - "PROCEDURES_MUTATORARG_TOOLTIP": "Generier/erzeich \"Uffruf %1\"", - "PROCEDURES_HIGHLIGHT_DEF": "Markiear Funktionsblock", - "PROCEDURES_CREATE_DO": "Generier/erzeich \"Uffruf %1\"", - "PROCEDURES_IFRETURN_TOOLTIP": "Wenn der earste Weart woahr (true) ist, Geb den zwooite Weart zurück.", - "PROCEDURES_IFRETURN_WARNING": "Warnung: Der Block därref nuar innich en Funktionsblock genutzt sin." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/hu.json b/backend/_pv_1_3_5/static/blockly/msg/json/hu.json deleted file mode 100755 index eef1456f4..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/hu.json +++ /dev/null @@ -1,327 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Espertus", - "Takács Viktor László", - "Dj", - "Grin", - "ViDam", - "Csega", - "Fitoschido", - "Lajthabalazs", - "Tacsipacsi", - "Rodrigo", - "Máté" - ] - }, - "VARIABLES_DEFAULT_NAME": "változó", - "TODAY": "Ma", - "DUPLICATE_BLOCK": "Másolat", - "ADD_COMMENT": "Megjegyzés hozzáadása", - "REMOVE_COMMENT": "Megjegyzés törlése", - "EXTERNAL_INPUTS": "Külső kapcsolatok", - "INLINE_INPUTS": "Belső kapcsolatok", - "DELETE_BLOCK": "Blokk törlése", - "DELETE_X_BLOCKS": "%1 blokk törlése", - "DELETE_ALL_BLOCKS": "Az összes %1 blokk törlése?", - "CLEAN_UP": "Blokkok kiürítése", - "COLLAPSE_BLOCK": "Blokk összecsukása", - "COLLAPSE_ALL": "Blokkok összecsukása", - "EXPAND_BLOCK": "Blokk kibontása", - "EXPAND_ALL": "Blokkok kibontása", - "DISABLE_BLOCK": "Blokk letiltása", - "ENABLE_BLOCK": "Blokk engedélyezése", - "HELP": "Súgó", - "UNDO": "Visszavonás", - "REDO": "Újra", - "CHANGE_VALUE_TITLE": "Érték módosítása:", - "RENAME_VARIABLE": "Változó átnevezése...", - "RENAME_VARIABLE_TITLE": "Minden \"%1\" változó átnevezése erre:", - "NEW_VARIABLE": "Új változó...", - "NEW_VARIABLE_TITLE": "Az új változó neve:", - "COLOUR_PICKER_HELPURL": "https://hu.wikipedia.org/wiki/Szín", - "COLOUR_PICKER_TOOLTIP": "Válassz színt a palettáról.", - "COLOUR_RANDOM_TITLE": "véletlen szín", - "COLOUR_RANDOM_TOOLTIP": "Véletlenszerűen kiválasztott szín.", - "COLOUR_RGB_TITLE": "Szín", - "COLOUR_RGB_RED": "vörös", - "COLOUR_RGB_GREEN": "zöld", - "COLOUR_RGB_BLUE": "kék", - "COLOUR_RGB_TOOLTIP": "Szín előállítása a megadott vörös, zöld, és kék értékekkel. Minden értéknek 0 és 100 közé kell esnie.", - "COLOUR_BLEND_TITLE": "színkeverés", - "COLOUR_BLEND_COLOUR1": "szín 1", - "COLOUR_BLEND_COLOUR2": "szín 2", - "COLOUR_BLEND_RATIO": "arány", - "COLOUR_BLEND_TOOLTIP": "Két színt kever össze a megadott arányban (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://hu.wikipedia.org/wiki/Ciklus_(programoz%C3%A1s)#Sz.C3.A1ml.C3.A1l.C3.B3s_.28FOR.29_ciklus", - "CONTROLS_REPEAT_TITLE": "ismételd %1 alkalommal", - "CONTROLS_REPEAT_INPUT_DO": "", - "CONTROLS_REPEAT_TOOLTIP": "Megadott kódrészlet ismételt végrehajtása.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "ismételd amíg", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "ismételd amíg nem", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Amíg a feltétel igaz, végrehajtja az utasításokat.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Amíg a feltétel hamis, végrehajtja az utasításokat.", - "CONTROLS_FOR_TOOLTIP": "A(z) '%1' változó felveszi a kezdőérték és a végérték közötti értékeket a meghatározott lépésközzel. Eközben a meghatározott blokkokat hajtja végre.", - "CONTROLS_FOR_TITLE": "számolj %1 értékével %2 és %3 között %4 lépésközzel", - "CONTROLS_FOREACH_TITLE": "minden %1 elemre a %2 listában", - "CONTROLS_FOREACH_TOOLTIP": "A '%1' változó minden lépésben megkapja a lista adott elemének értékét, és végrehajt vele néhány utasítást.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "befejezi az ismétlést", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "folytatja a következővel", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Megszakítja az utasítást tartalmazó ciklust.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Kihagyja a ciklus további részét, és elölről kezdi a következő elemmel.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Figyelem: Ez a blokk csak cikluson belül használható.", - "CONTROLS_IF_TOOLTIP_1": "Ha a kifejezés igaz, akkor végrehajtja az utasításokat.", - "CONTROLS_IF_TOOLTIP_2": "Ha a kifejezés igaz, akkor végrehajtja az első utasításblokkot. Különben a második utasításblokk kerül végrehajtásra.", - "CONTROLS_IF_TOOLTIP_3": "Ha az első kifejezés igaz, akkor végrehajtja az első utasításblokkot. Különben, ha a második kifejezés igaz, akkor végrehajtja a második utasítás blokkot.", - "CONTROLS_IF_TOOLTIP_4": "Ha az első kifejezés igaz, akkor végrehajtjuk az első utasítás blokkot. Ha a második kifejezés igaz, akkor végrehajtjuk a második utasítás blokkot. Amennyiben egyik kifejezés sem igaz, akkor az utolsó utasítás blokk kerül végrehajtásra.", - "CONTROLS_IF_MSG_IF": "ha", - "CONTROLS_IF_MSG_ELSEIF": "különben ha", - "CONTROLS_IF_MSG_ELSE": "különben", - "CONTROLS_IF_IF_TOOLTIP": "A ha blokk testreszabásához bővítsd, töröld vagy rendezd át a részeit.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Feltétel hozzáadása a ha blokkhoz.", - "CONTROLS_IF_ELSE_TOOLTIP": "Végső feltétel hozzáadása a ha blokkhoz.", - "LOGIC_COMPARE_HELPURL": "https://hu.wikipedia.org/wiki/Egyenl%C5%91tlens%C3%A9g", - "LOGIC_COMPARE_TOOLTIP_EQ": "Igaz, ha a kifejezés két oldala egyenlő.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Igaz, ha a kifejezés két oldala nem egyenlő..", - "LOGIC_COMPARE_TOOLTIP_LT": "Igaz, ha a bal oldali kifejezés kisebb, mint a jobb oldali.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Igaz, ha a bal oldali kifejezés kisebb vagy egyenlő, mint a jobb oldali.", - "LOGIC_COMPARE_TOOLTIP_GT": "Igaz, ha a bal oldali kifejezés nagyobb, mint a jobb oldali.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Igaz, ha a bal oldali kifejezés nagyobb vagy egyenlő, mint a jobb oldali.", - "LOGIC_OPERATION_TOOLTIP_AND": "Igaz, ha mindkét kifejezés igaz.", - "LOGIC_OPERATION_AND": "és", - "LOGIC_OPERATION_TOOLTIP_OR": "Igaz, ha legalább az egyik kifejezés igaz.", - "LOGIC_OPERATION_OR": "vagy", - "LOGIC_NEGATE_TITLE": "nem %1", - "LOGIC_NEGATE_TOOLTIP": "Igaz, ha a kifejezés hamis. Hamis, ha a kifejezés igaz.", - "LOGIC_BOOLEAN_TRUE": "igaz", - "LOGIC_BOOLEAN_FALSE": "hamis", - "LOGIC_BOOLEAN_TOOLTIP": "Igaz, vagy hamis érték", - "LOGIC_NULL": "null", - "LOGIC_NULL_TOOLTIP": "null érték.", - "LOGIC_TERNARY_CONDITION": "vizsgáld meg:", - "LOGIC_TERNARY_IF_TRUE": "érték, ha igaz:", - "LOGIC_TERNARY_IF_FALSE": "érték, ha hamis:", - "LOGIC_TERNARY_TOOLTIP": "Kiértékeli a megvizsgálandó kifejezést. Ha a kifejezés igaz, visszatér az \"érték, ha igaz\" értékkel, különben az \"érték, ha hamis\" értékkel.", - "MATH_NUMBER_HELPURL": "https://hu.wikipedia.org/wiki/Sz%C3%A1m", - "MATH_NUMBER_TOOLTIP": "Egy szám.", - "MATH_ARITHMETIC_HELPURL": "https://hu.wikipedia.org/wiki/Matematikai_m%C5%B1velet", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Két szám összege.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Két szám különbsége.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Két szám szorzata.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Két szám hányadosa.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Az első számnak a második számmal megegyező hatványa.", - "MATH_SINGLE_HELPURL": "https://hu.wikipedia.org/wiki/Gy%C3%B6kvon%C3%A1s", - "MATH_SINGLE_OP_ROOT": "négyzetgyök", - "MATH_SINGLE_TOOLTIP_ROOT": "A szám négyzetgyöke.", - "MATH_SINGLE_OP_ABSOLUTE": "abszolútérték", - "MATH_SINGLE_TOOLTIP_ABS": "A szám abszolútértéke.", - "MATH_SINGLE_TOOLTIP_NEG": "A szám -1 szerese.", - "MATH_SINGLE_TOOLTIP_LN": "A szám természetes alapú logaritmusa.", - "MATH_SINGLE_TOOLTIP_LOG10": "A szám 10-es alapú logaritmusa.", - "MATH_SINGLE_TOOLTIP_EXP": "Az e megadott számú hatványa.", - "MATH_SINGLE_TOOLTIP_POW10": "A 10 megadott számú hatványa.", - "MATH_TRIG_HELPURL": "https://hu.wikipedia.org/wiki/Sz%C3%B6gf%C3%BCggv%C3%A9nyek", - "MATH_TRIG_TOOLTIP_SIN": "A fokban megadott szög szinusz értéke.", - "MATH_TRIG_TOOLTIP_COS": "A fokban megadott szög koszinusz értéke.", - "MATH_TRIG_TOOLTIP_TAN": "A fokban megadott szög tangens értéke.", - "MATH_TRIG_TOOLTIP_ASIN": "A fokban megadott szög arkusz szinusz értéke.", - "MATH_TRIG_TOOLTIP_ACOS": "A fokban megadott szög arkusz koszinusz értéke.", - "MATH_TRIG_TOOLTIP_ATAN": "A fokban megadott szög arkusz tangens értéke.", - "MATH_CONSTANT_HELPURL": "https://hu.wikipedia.org/wiki/Matematikai_konstans", - "MATH_CONSTANT_TOOLTIP": "Ismert matematikai konstans: π (3.141…), e (2.718…), φ (1.618…), gyök(2) (1.414…), gyök(½) (0.707…), vagy ∞ (végtelen).", - "MATH_IS_EVEN": "páros", - "MATH_IS_ODD": "páratlan", - "MATH_IS_PRIME": "prím", - "MATH_IS_WHOLE": "egész", - "MATH_IS_POSITIVE": "pozitív", - "MATH_IS_NEGATIVE": "negatív", - "MATH_IS_DIVISIBLE_BY": "-nek osztója", - "MATH_IS_TOOLTIP": "Ellenőrzi, hogy a szám páros, páratlan, prím, egész, pozitív vagy negatív-e, illetve osztható-e a másodikkal. Igaz, vagy hamis értéket ad eredményül.", - "MATH_CHANGE_HELPURL": "https://hu.wikipedia.org/wiki/JavaScript#Aritmetikai_oper.C3.A1torok", - "MATH_CHANGE_TITLE": "növeld %1 értékét %2 -vel", - "MATH_CHANGE_TOOLTIP": "A \"%1\" változó értékének növelése egy számmal.", - "MATH_ROUND_HELPURL": "https://hu.wikipedia.org/wiki/Eg%C3%A9szr%C3%A9sz#Kerek.C3.ADt.C3.A9s", - "MATH_ROUND_TOOLTIP": "Egy szám kerekítése felfelé vagy lefelé.", - "MATH_ROUND_OPERATOR_ROUND": "kerekítsd", - "MATH_ROUND_OPERATOR_ROUNDUP": "kerekítsd felfelé", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "kerekítsd lefelé", - "MATH_ONLIST_OPERATOR_SUM": "lista elemeinek összege", - "MATH_ONLIST_TOOLTIP_SUM": "A lista elemeinek összegét adja eredményül.", - "MATH_ONLIST_OPERATOR_MIN": "lista legkisebb eleme", - "MATH_ONLIST_TOOLTIP_MIN": "A lista legkisebb elemét adja vissza.", - "MATH_ONLIST_OPERATOR_MAX": "lista legnagyobb eleme", - "MATH_ONLIST_TOOLTIP_MAX": "A lista legnagyobb elemét adja vissza.", - "MATH_ONLIST_OPERATOR_AVERAGE": "lista elemeinek átlaga", - "MATH_ONLIST_TOOLTIP_AVERAGE": "A lista elemeinek átlagát adja eredményül.", - "MATH_ONLIST_OPERATOR_MEDIAN": "lista mediánja", - "MATH_ONLIST_TOOLTIP_MEDIAN": "A lista elemeinek mediánját adja eredményül.", - "MATH_ONLIST_OPERATOR_MODE": "lista módusza", - "MATH_ONLIST_TOOLTIP_MODE": "A lista elemeinek móduszát adja eredményül.", - "MATH_ONLIST_OPERATOR_STD_DEV": "lista elemeinek szórása", - "MATH_ONLIST_TOOLTIP_STD_DEV": "A lista elemeinek szórását adja eredményül.", - "MATH_ONLIST_OPERATOR_RANDOM": "lista véletlen eleme", - "MATH_ONLIST_TOOLTIP_RANDOM": "A lista egy véletlen elemét adja eredményül.", - "MATH_MODULO_HELPURL": "https://hu.wikipedia.org/wiki/Eg%C3%A9szr%C3%A9sz#Als.C3.B3_eg.C3.A9szr.C3.A9sz", - "MATH_MODULO_TITLE": "%1 ÷ %2 maradéka", - "MATH_MODULO_TOOLTIP": "Az egész osztás maradékát adja eredméynül.", - "MATH_CONSTRAIN_TITLE": "korlátozd %1-t %2 és %3 közé", - "MATH_CONSTRAIN_TOOLTIP": "Egy változó értékének korlátozása a megadott zárt intervallumra.", - "MATH_RANDOM_INT_HELPURL": "https://hu.wikipedia.org/wiki/V%C3%A9letlen", - "MATH_RANDOM_INT_TITLE": "véletlen egész szám %1 között %2", - "MATH_RANDOM_INT_TOOLTIP": "Véletlen egész szám a megadott zárt intervallumon belül.", - "MATH_RANDOM_FLOAT_HELPURL": "https://hu.wikipedia.org/wiki/V%C3%A9letlen", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "véletlen tört", - "MATH_RANDOM_FLOAT_TOOLTIP": "Véletlen tört érték 0.0 és 1.0 között.", - "TEXT_TEXT_HELPURL": "https://hu.wikipedia.org/wiki/String", - "TEXT_TEXT_TOOLTIP": "Egy betű, szó vagy szöveg egy sora.", - "TEXT_JOIN_TITLE_CREATEWITH": "fűzd össze", - "TEXT_JOIN_TOOLTIP": "Tetszőleges számú szövegrészletet fűz össze egybefüggő szöveggé.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "fűzd össze", - "TEXT_CREATE_JOIN_TOOLTIP": "Összefűzéssel, törléssel vagy rendezéssel kapcsolato sblokkok szöveg szerkesztéséhez.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Elem hozzáfűzése a szöveghez.", - "TEXT_APPEND_TO": "A", - "TEXT_APPEND_APPENDTEXT": "szövegéhez fűzd hozzá", - "TEXT_APPEND_TOOLTIP": "Szöveget fűz a \"%1\" változó értékéhez.", - "TEXT_LENGTH_TITLE": "%1 hossza", - "TEXT_LENGTH_TOOLTIP": "A megadott szöveg karaktereinek számát adja eredményül (beleértve a szóközöket).", - "TEXT_ISEMPTY_TITLE": "%1 üres", - "TEXT_ISEMPTY_TOOLTIP": "Igaz, ha a vizsgált szöveg hossza 0.", - "TEXT_INDEXOF_TOOLTIP": "A keresett szöveg első vagy utolsó előfordulásával tér vissza. %1 esetén a szövegrészlet nem található.", - "TEXT_INDEXOF_INPUT_INTEXT": "A(z)", - "TEXT_INDEXOF_OPERATOR_FIRST": "szövegben az első előfordulásának helye", - "TEXT_INDEXOF_OPERATOR_LAST": "szövegben az utolsó előfordulásának helye", - "TEXT_INDEXOF_TAIL": "szövegnek", - "TEXT_CHARAT_INPUT_INTEXT": "A", - "TEXT_CHARAT_FROM_START": "elölről", - "TEXT_CHARAT_FROM_END": "hátulról", - "TEXT_CHARAT_FIRST": "első", - "TEXT_CHARAT_LAST": "utolsó", - "TEXT_CHARAT_RANDOM": "véletlen", - "TEXT_CHARAT_TAIL": "karaktere", - "TEXT_CHARAT_TOOLTIP": "A szöveg egy megadott karakterét adja eredményül.", - "TEXT_GET_SUBSTRING_TOOLTIP": "A megadott szövegrészletet adja eredményül.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "a", - "TEXT_GET_SUBSTRING_START_FROM_START": "szövegben válaszd ki a(z)", - "TEXT_GET_SUBSTRING_START_FROM_END": "szövegben válaszd ki a hátulról a(z)", - "TEXT_GET_SUBSTRING_START_FIRST": "szövegben válaszd ki az első", - "TEXT_GET_SUBSTRING_END_FROM_START": "betűtől a(z)", - "TEXT_GET_SUBSTRING_END_FROM_END": "betűtől a hátulról számított", - "TEXT_GET_SUBSTRING_END_LAST": "betűtől az utolsó", - "TEXT_GET_SUBSTRING_TAIL": "betűig tartó betűsort", - "TEXT_CHANGECASE_TOOLTIP": "Return a copy of the text in a different case.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "NAGYBETŰS", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "kisbetűs", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "Címként Formázott", - "TEXT_TRIM_TOOLTIP": "Levágja a megadott szöveg végeiről a szóközöket.", - "TEXT_TRIM_OPERATOR_BOTH": "szóközök levágása mindkét végéről", - "TEXT_TRIM_OPERATOR_LEFT": "szóközök levágása az elejéről", - "TEXT_TRIM_OPERATOR_RIGHT": "szóközök levágása a végéről", - "TEXT_PRINT_TITLE": "Üzenet %1", - "TEXT_PRINT_TOOLTIP": "Megejelníti a megadott kaakterláncot üzenetként a képernyőn.", - "TEXT_PROMPT_TYPE_TEXT": "Kérj be szöveget", - "TEXT_PROMPT_TYPE_NUMBER": "Kérj be számot", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Számot kér be a felhasználótól.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Szöveget kér be a felhasználótól.", - "LISTS_CREATE_EMPTY_TITLE": "üres lista", - "LISTS_CREATE_EMPTY_TOOLTIP": "Elemeket nem tartalmazó üres listát ad eredményül", - "LISTS_CREATE_WITH_TOOLTIP": "Listát készít a megadott elemekből.", - "LISTS_CREATE_WITH_INPUT_WITH": "Lista készítés, elemek:", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "lista", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Add, remove, or reorder sections to reconfigure this list block.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Elem hozzáadása listához.", - "LISTS_REPEAT_TOOLTIP": "A megadtott elem felhasználásával n elemű listát készít", - "LISTS_REPEAT_TITLE": "Lista készítése %1 elemet %2 alkalommal hozzáadva", - "LISTS_LENGTH_TITLE": "%1 lista hossza", - "LISTS_LENGTH_TOOLTIP": "A lista elemszámát adja eredményül.", - "LISTS_ISEMPTY_TITLE": "%1 üres lista?", - "LISTS_ISEMPTY_TOOLTIP": "Az eredmény igaz, ha a lista nem tartalmaz elemeket.", - "LISTS_INLIST": "A(z)", - "LISTS_INDEX_OF_FIRST": "listában első előfordulásaː", - "LISTS_INDEX_OF_LAST": "listában utolsó előfordulásaː", - "LISTS_INDEX_OF_TOOLTIP": "A megadott elem első vagy utolsó előfordulásával tér vissza. Ha nem talál ilyen elemet, akkor %1 a visszatérési érték.", - "LISTS_GET_INDEX_GET": "listából értéke", - "LISTS_GET_INDEX_GET_REMOVE": "listából kivétele", - "LISTS_GET_INDEX_REMOVE": "listából törlése", - "LISTS_GET_INDEX_FROM_START": "az elejétől számított", - "LISTS_GET_INDEX_FROM_END": "a végétől számított", - "LISTS_GET_INDEX_FIRST": "az első", - "LISTS_GET_INDEX_LAST": "az utolsó", - "LISTS_GET_INDEX_RANDOM": "bármely", - "LISTS_GET_INDEX_TAIL": "elemnek", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 az első elemet jelenti.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 az utolsó elemet jelenti.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "A lista megadott sorszámú elemét adja eredményül.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "A lista első elemét adja eredményül.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "A lista utolsó elemét adja eredményül.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "A lista véletlenszerűen választott elemét adja eredményül.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "A megadott sorszámú elem kivétele a listából.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Az első elem kivétele a listából.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Az utolsó elem kivétele a listából.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Véletlenszerűen választott elem kivétele a listából.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "A megadott sorszámú elem törlése a listából.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Az első elem törlése a listából.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Az utolsó elem törlése a listából.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Véletlenszerűen választott elem törlése a listából.", - "LISTS_SET_INDEX_SET": "listába állítsd be", - "LISTS_SET_INDEX_INSERT": "listába szúrd be", - "LISTS_SET_INDEX_INPUT_TO": "elemkéntː", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "A megadott sorszámú elem cseréje a listában.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Az első elem cseréje a listában.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Az utolsó elem cseréje a listában.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Véletlenszerűen választott elem cseréje a listában.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Beszúrás a megadott sorszámú elem elé a listában.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Beszúrás a lista elejére.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Beszúrás a lista végére.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Beszúrás véletlenszerűen választott elem elé a listában.", - "LISTS_GET_SUBLIST_START_FROM_START": "részlistája az elejétől számított", - "LISTS_GET_SUBLIST_START_FROM_END": "részlistája a végétől számított", - "LISTS_GET_SUBLIST_START_FIRST": "részlistája az első", - "LISTS_GET_SUBLIST_END_FROM_START": "és az elejétől számított", - "LISTS_GET_SUBLIST_END_FROM_END": "és a végétől számított", - "LISTS_GET_SUBLIST_END_LAST": "és az utolsó", - "LISTS_GET_SUBLIST_TAIL": "elem között", - "LISTS_GET_SUBLIST_TOOLTIP": "A lista adott részéről másolat.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "%1 %2 %3 rendezés", - "LISTS_SORT_TOOLTIP": "Egy lista egy másolatának rendezése.", - "LISTS_SORT_ORDER_ASCENDING": "növekvő", - "LISTS_SORT_ORDER_DESCENDING": "csökkenő", - "LISTS_SORT_TYPE_NUMERIC": "numerikus", - "LISTS_SORT_TYPE_TEXT": "betűrendben", - "LISTS_SORT_TYPE_IGNORECASE": "betűrendben nagybetű figyelmen kívül hagyásával", - "LISTS_SPLIT_LIST_FROM_TEXT": "lista készítése szövegből", - "LISTS_SPLIT_TEXT_FROM_LIST": "sztring készítése listából", - "LISTS_SPLIT_WITH_DELIMITER": "határoló karakter", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Listát készít a határoló karaktereknél törve a szöveget.", - "LISTS_SPLIT_TOOLTIP_JOIN": "A lista elemeit összefűzi szöveggé a határoló karaktereket is felhasználva.", - "ORDINAL_NUMBER_SUFFIX": ".", - "VARIABLES_GET_TOOLTIP": "A változó értékét adja eredményül.", - "VARIABLES_GET_CREATE_SET": "Készíts \"%1=\"", - "VARIABLES_SET": "%1 %2", - "VARIABLES_SET_TOOLTIP": "A változónak adhatunk értéket.", - "VARIABLES_SET_CREATE_GET": "Készíts \"%1\"", - "PROCEDURES_DEFNORETURN_TITLE": "Eljárás", - "PROCEDURES_DEFNORETURN_PROCEDURE": "név", - "PROCEDURES_BEFORE_PARAMS": "paraméterlistaː", - "PROCEDURES_CALL_BEFORE_PARAMS": "paraméterlistaː", - "PROCEDURES_DEFNORETURN_DO": "", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Eljárás (nem ad vissza eredményt).", - "PROCEDURES_DEFNORETURN_COMMENT": "Írj erről a funkcióról...", - "PROCEDURES_DEFRETURN_RETURN": "eredménye", - "PROCEDURES_DEFRETURN_TOOLTIP": "Függvény eredménnyel.", - "PROCEDURES_ALLOW_STATEMENTS": "utasítások engedélyezése", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Figyelem: Az eljárásban azonos elnevezésű paramétert adtál meg.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://hu.wikipedia.org/wiki/F%C3%BCggv%C3%A9ny_(programoz%C3%A1s)", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Végrehajtja az eljárást.", - "PROCEDURES_CALLRETURN_HELPURL": "https://hu.wikipedia.org/wiki/F%C3%BCggv%C3%A9ny_(programoz%C3%A1s)", - "PROCEDURES_CALLRETURN_TOOLTIP": "Meghívja a függvényt.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "paraméterek", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Bemenetek hozzáadása, eltávolítása vagy átrendezése ehhez a függvényhez.", - "PROCEDURES_MUTATORARG_TITLE": "változó:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Bemenet hozzáadása a függvényhez.", - "PROCEDURES_HIGHLIGHT_DEF": "Függvénydefiníció kiemelése", - "PROCEDURES_CREATE_DO": "„%1” létrehozása", - "PROCEDURES_IFRETURN_TOOLTIP": "Ha az érték igaz, akkor visszatér a függvény értékével.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Figyelem: Ez a blokk csak függvénydefiníción belül használható." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/ia.json b/backend/_pv_1_3_5/static/blockly/msg/json/ia.json deleted file mode 100755 index 258090004..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/ia.json +++ /dev/null @@ -1,298 +0,0 @@ -{ - "@metadata": { - "authors": [ - "McDutchie", - "Karmwiki" - ] - }, - "VARIABLES_DEFAULT_NAME": "cosa", - "TODAY": "Hodie", - "DUPLICATE_BLOCK": "Duplicar", - "ADD_COMMENT": "Adder commento", - "REMOVE_COMMENT": "Remover commento", - "EXTERNAL_INPUTS": "Entrata externe", - "INLINE_INPUTS": "Entrata interne", - "DELETE_BLOCK": "Deler bloco", - "DELETE_X_BLOCKS": "Deler %1 blocos", - "DELETE_ALL_BLOCKS": "Deler tote le %1 blocos?", - "CLEAN_UP": "Clarar le blocos", - "COLLAPSE_BLOCK": "Plicar bloco", - "COLLAPSE_ALL": "Plicar blocos", - "EXPAND_BLOCK": "Displicar bloco", - "EXPAND_ALL": "Displicar blocos", - "DISABLE_BLOCK": "Disactivar bloco", - "ENABLE_BLOCK": "Activar bloco", - "HELP": "Adjuta", - "UNDO": "Disfacer", - "REDO": "Refacer", - "CHANGE_VALUE_TITLE": "Cambiar valor:", - "RENAME_VARIABLE": "Renominar variabile...", - "RENAME_VARIABLE_TITLE": "Renominar tote le variabiles '%1' a:", - "NEW_VARIABLE": "Nove variabile...", - "NEW_VARIABLE_TITLE": "Nomine del nove variabile:", - "COLOUR_PICKER_HELPURL": "https://ia.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "Elige un color del paletta.", - "COLOUR_RANDOM_TITLE": "color aleatori", - "COLOUR_RANDOM_TOOLTIP": "Eliger un color al hasardo.", - "COLOUR_RGB_TITLE": "colorar con", - "COLOUR_RGB_RED": "rubie", - "COLOUR_RGB_GREEN": "verde", - "COLOUR_RGB_BLUE": "blau", - "COLOUR_RGB_TOOLTIP": "Crear un color con le quantitate specificate de rubie, verde e blau. Tote le valores debe esser inter 0 e 100.", - "COLOUR_BLEND_TITLE": "miscer", - "COLOUR_BLEND_COLOUR1": "color 1", - "COLOUR_BLEND_COLOUR2": "color 2", - "COLOUR_BLEND_RATIO": "ration", - "COLOUR_BLEND_TOOLTIP": "Misce duo colores con un ration specificate (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "repeter %1 vices", - "CONTROLS_REPEAT_INPUT_DO": "face", - "CONTROLS_REPEAT_TOOLTIP": "Exequer certe instructiones plure vices.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "repeter durante que", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "repeter usque a", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Durante que un valor es ver, exequer certe instructiones.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Durante que un valor es false, exequer certe instructiones.", - "CONTROLS_FOR_TOOLTIP": "Mitter in le variabile '%1' le valores ab le numero initial usque al numero final, con passos secundo le intervallo specificate, e exequer le blocos specificate.", - "CONTROLS_FOR_TITLE": "contar con %1 de %2 a %3 per %4", - "CONTROLS_FOREACH_TITLE": "pro cata elemento %1 in lista %2", - "CONTROLS_FOREACH_TOOLTIP": "Pro cata elemento in un lista, mitter lo in le variabile '%1' e exequer certe instructiones.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "escappar del bucla", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "continuar con le proxime iteration del bucla", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Escappar del bucla continente.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Saltar le resto de iste bucla e continuar con le proxime iteration.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Attention: Iste bloco pote solmente esser usate in un bucla.", - "CONTROLS_IF_TOOLTIP_1": "Si un valor es ver, exequer certe instructiones.", - "CONTROLS_IF_TOOLTIP_2": "Si un valor es ver, exequer le prime bloco de instructiones. Si non, exequer le secunde bloco de instructiones.", - "CONTROLS_IF_TOOLTIP_3": "Si le prime valor es ver, exequer le prime bloco de instructiones. Si non, si le secunde valor es ver, exequer le secunde bloco de instructiones.", - "CONTROLS_IF_TOOLTIP_4": "Si le prime valor es ver, exequer le prime bloco de instructiones. Si non, si le secunde valor es ver, exequer le secunde bloco de instructiones. Si necun del valores es ver, exequer le ultime bloco de instructiones.", - "CONTROLS_IF_MSG_IF": "si", - "CONTROLS_IF_MSG_ELSEIF": "si non si", - "CONTROLS_IF_MSG_ELSE": "si non", - "CONTROLS_IF_IF_TOOLTIP": "Adde, remove o reordina sectiones pro reconfigurar iste bloco \"si\".", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Adder un condition al bloco \"si\".", - "CONTROLS_IF_ELSE_TOOLTIP": "Adder un condition final de reserva al bloco \"si\".", - "LOGIC_COMPARE_TOOLTIP_EQ": "Retornar ver si le duo entratas es equal.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Retornar ver si le duo entratas non es equal.", - "LOGIC_COMPARE_TOOLTIP_LT": "Retornar ver si le prime entrata es minor que le secunde.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Retornar ver si le prime entrata es minor que o equal al secunde.", - "LOGIC_COMPARE_TOOLTIP_GT": "Retornar ver si le prime entrata es major que le secunde.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Retornar ver si le prime entrata es major que o equal al secunde.", - "LOGIC_OPERATION_TOOLTIP_AND": "Retornar ver si ambe entratas es ver.", - "LOGIC_OPERATION_AND": "e", - "LOGIC_OPERATION_TOOLTIP_OR": "Retornar ver si al minus un del entratas es ver.", - "LOGIC_OPERATION_OR": "o", - "LOGIC_NEGATE_TITLE": "non %1", - "LOGIC_NEGATE_TOOLTIP": "Retornar ver si le entrata es false. Retornar false si le entrata es ver.", - "LOGIC_BOOLEAN_TRUE": "ver", - "LOGIC_BOOLEAN_FALSE": "false", - "LOGIC_BOOLEAN_TOOLTIP": "Retorna o ver o false.", - "LOGIC_NULL": "nulle", - "LOGIC_NULL_TOOLTIP": "Retorna nulle.", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "si ver", - "LOGIC_TERNARY_IF_FALSE": "si false", - "LOGIC_TERNARY_TOOLTIP": "Verificar le condition in 'test'. Si le condition es ver, retorna le valor de 'si ver'; si non, retorna le valor de 'si false'.", - "MATH_NUMBER_HELPURL": "https://ia.wikipedia.org/wiki/Numero", - "MATH_NUMBER_TOOLTIP": "Un numero.", - "MATH_ARITHMETIC_HELPURL": "https://ia.wikipedia.org/wiki/Arithmetica", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Retornar le summa del duo numeros.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Retornar le differentia del duo numeros.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Retornar le producto del duo numeros.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Retornar le quotiente del duo numeros.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Retornar le prime numero elevate al potentia del secunde numero.", - "MATH_SINGLE_HELPURL": "https://ia.wikipedia.org/wiki/Radice_quadrate", - "MATH_SINGLE_OP_ROOT": "radice quadrate", - "MATH_SINGLE_TOOLTIP_ROOT": "Retornar le radice quadrate de un numero.", - "MATH_SINGLE_OP_ABSOLUTE": "absolute", - "MATH_SINGLE_TOOLTIP_ABS": "Retornar le valor absolute de un numero.", - "MATH_SINGLE_TOOLTIP_NEG": "Retornar le negation de un numero.", - "MATH_SINGLE_TOOLTIP_LN": "Retornar le logarithmo natural de un numero.", - "MATH_SINGLE_TOOLTIP_LOG10": "Retornar le logarithmo in base 10 del numero.", - "MATH_SINGLE_TOOLTIP_EXP": "Retornar e elevate al potentia del numero.", - "MATH_SINGLE_TOOLTIP_POW10": "Retornar 10 elevate al potentia de un numero.", - "MATH_TRIG_TOOLTIP_SIN": "Retornar le sino de un grado (non radiano).", - "MATH_TRIG_TOOLTIP_COS": "Retornar le cosino de un grado (non radiano).", - "MATH_TRIG_TOOLTIP_TAN": "Retornar le tangente de un grado (non radiano).", - "MATH_TRIG_TOOLTIP_ASIN": "Retornar le arcosino de un numero.", - "MATH_TRIG_TOOLTIP_ACOS": "Retornar le arcocosino de un numero.", - "MATH_TRIG_TOOLTIP_ATAN": "Retornar le arcotangente de un numero.", - "MATH_CONSTANT_TOOLTIP": "Retornar un del constantes commun: π (3,141…), e (2,718…), φ (1,618…), sqrt(2) (1,414…), sqrt(½) (0,707…) o ∞ (infinite).", - "MATH_IS_EVEN": "es par", - "MATH_IS_ODD": "es impare", - "MATH_IS_PRIME": "es prime", - "MATH_IS_WHOLE": "es integre", - "MATH_IS_POSITIVE": "es positive", - "MATH_IS_NEGATIVE": "es negative", - "MATH_IS_DIVISIBLE_BY": "es divisibile per", - "MATH_IS_TOOLTIP": "Verificar si un numero es par, impare, prime, integre, positive, negative, o divisibile per un certe numero. Retorna ver o false.", - "MATH_CHANGE_TITLE": "cambiar %1 per %2", - "MATH_CHANGE_TOOLTIP": "Adder un numero al variabile '%1'.", - "MATH_ROUND_HELPURL": "https://ia.wikipedia.org/wiki/Rotundamento", - "MATH_ROUND_TOOLTIP": "Arrotundar un numero a supra o a infra.", - "MATH_ROUND_OPERATOR_ROUND": "arrotundar", - "MATH_ROUND_OPERATOR_ROUNDUP": "arrotundar a supra", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "arrotundar a infra", - "MATH_ONLIST_OPERATOR_SUM": "summa del lista", - "MATH_ONLIST_TOOLTIP_SUM": "Retornar le summa de tote le numeros in le lista.", - "MATH_ONLIST_OPERATOR_MIN": "minimo del lista", - "MATH_ONLIST_TOOLTIP_MIN": "Retornar le numero le plus parve in le lista.", - "MATH_ONLIST_OPERATOR_MAX": "maximo del lista", - "MATH_ONLIST_TOOLTIP_MAX": "Retornar le numero le plus grande in le lista.", - "MATH_ONLIST_OPERATOR_AVERAGE": "media del lista", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Retornar le media arithmetic del valores numeric in le lista.", - "MATH_ONLIST_OPERATOR_MEDIAN": "mediana del lista", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Retornar le numero median del lista.", - "MATH_ONLIST_OPERATOR_MODE": "modas del lista", - "MATH_ONLIST_TOOLTIP_MODE": "Retornar un lista del elemento(s) le plus commun in le lista.", - "MATH_ONLIST_OPERATOR_STD_DEV": "deviation standard del lista", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Retornar le deviation standard del lista.", - "MATH_ONLIST_OPERATOR_RANDOM": "elemento aleatori del lista", - "MATH_ONLIST_TOOLTIP_RANDOM": "Retornar un elemento aleatori del lista.", - "MATH_MODULO_TITLE": "resto de %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Retornar le resto del division del duo numeros.", - "MATH_CONSTRAIN_TITLE": "limitar %1 inter %2 e %3", - "MATH_CONSTRAIN_TOOLTIP": "Limitar un numero a esser inter le limites specificate (incluse).", - "MATH_RANDOM_INT_TITLE": "numero integre aleatori inter %1 e %2", - "MATH_RANDOM_INT_TOOLTIP": "Retornar un numero integre aleatori inter le duo limites specificate, incluse.", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "fraction aleatori", - "MATH_RANDOM_FLOAT_TOOLTIP": "Retornar un fraction aleatori inter 0.0 (incluse) e 1.0 (excluse).", - "TEXT_TEXT_TOOLTIP": "Un littera, parola o linea de texto.", - "TEXT_JOIN_TITLE_CREATEWITH": "crear texto con", - "TEXT_JOIN_TOOLTIP": "Crear un pecia de texto uniente un certe numero de elementos.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "unir", - "TEXT_CREATE_JOIN_TOOLTIP": "Adde, remove o reordina sectiones pro reconfigurar iste bloco de texto.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Adder un elemento al texto.", - "TEXT_APPEND_TO": "a", - "TEXT_APPEND_APPENDTEXT": "adjunger texto", - "TEXT_APPEND_TOOLTIP": "Adjunger un texto al variabile '%1'.", - "TEXT_LENGTH_TITLE": "longitude de %1", - "TEXT_LENGTH_TOOLTIP": "Retorna le numero de litteras (incluse spatios) in le texto fornite.", - "TEXT_ISEMPTY_TITLE": "%1 es vacue", - "TEXT_ISEMPTY_TOOLTIP": "Retorna ver si le texto fornite es vacue.", - "TEXT_INDEXOF_TOOLTIP": "Retorna le indice del prime/ultime occurrentia del prime texto in le secunde texto. Retorna %1 si le texto non es trovate.", - "TEXT_INDEXOF_INPUT_INTEXT": "in le texto", - "TEXT_INDEXOF_OPERATOR_FIRST": "cercar le prime occurrentia del texto", - "TEXT_INDEXOF_OPERATOR_LAST": "cercar le ultime occurrentia del texto", - "TEXT_CHARAT_INPUT_INTEXT": "in le texto", - "TEXT_CHARAT_FROM_START": "prender le littera №", - "TEXT_CHARAT_FROM_END": "prender ab le fin le littera №", - "TEXT_CHARAT_FIRST": "prender le prime littera", - "TEXT_CHARAT_LAST": "prender le ultime littera", - "TEXT_CHARAT_RANDOM": "prender un littera aleatori", - "TEXT_CHARAT_TOOLTIP": "Retorna le littera presente al position specificate.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Retorna le parte specificate del texto.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "in le texto", - "TEXT_GET_SUBSTRING_START_FROM_START": "prender subcatena ab le littera №", - "TEXT_GET_SUBSTRING_START_FROM_END": "prender subcatena ab le fin ab le littera №", - "TEXT_GET_SUBSTRING_START_FIRST": "prender subcatena ab le prime littera", - "TEXT_GET_SUBSTRING_END_FROM_START": "usque al littera №", - "TEXT_GET_SUBSTRING_END_FROM_END": "ab le fin usque al littera №", - "TEXT_GET_SUBSTRING_END_LAST": "usque al ultime littera", - "TEXT_CHANGECASE_TOOLTIP": "Retornar un copia del texto con differente majusculas/minusculas.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "in MAJUSCULAS", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "in minusculas", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "con Initiales Majuscule", - "TEXT_TRIM_TOOLTIP": "Retornar un copia del texto con spatios eliminate de un extremitate o ambes.", - "TEXT_TRIM_OPERATOR_BOTH": "remover spatios de ambe lateres de", - "TEXT_TRIM_OPERATOR_LEFT": "remover spatios del sinistre latere de", - "TEXT_TRIM_OPERATOR_RIGHT": "remover spatios del dextre latere de", - "TEXT_PRINT_TITLE": "scriber %1", - "TEXT_PRINT_TOOLTIP": "Scriber le texto, numero o altere valor specificate.", - "TEXT_PROMPT_TYPE_TEXT": "peter un texto con le message", - "TEXT_PROMPT_TYPE_NUMBER": "peter un numero con le message", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Peter un numero al usator.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Peter un texto al usator.", - "LISTS_CREATE_EMPTY_TITLE": "crear un lista vacue", - "LISTS_CREATE_EMPTY_TOOLTIP": "Retorna un lista, de longitude 0, sin datos.", - "LISTS_CREATE_WITH_TOOLTIP": "Crear un lista con un numero qualcunque de elementos.", - "LISTS_CREATE_WITH_INPUT_WITH": "crear lista con", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "lista", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Adde, remove o reordina sectiones pro reconfigurar iste bloco de listas.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Adder un elemento al lista.", - "LISTS_REPEAT_TOOLTIP": "Crea un lista que contine le valor fornite, repetite le numero specificate de vices.", - "LISTS_REPEAT_TITLE": "crear lista con elemento %1 repetite %2 vices", - "LISTS_LENGTH_TITLE": "longitude de %1", - "LISTS_LENGTH_TOOLTIP": "Retorna le longitude de un lista.", - "LISTS_ISEMPTY_TITLE": "%1 es vacue", - "LISTS_ISEMPTY_TOOLTIP": "Retorna ver si le lista es vacue.", - "LISTS_INLIST": "in lista", - "LISTS_INDEX_OF_FIRST": "cercar le prime occurrentia del elemento", - "LISTS_INDEX_OF_LAST": "cercar le ultime occurrentia del elemento", - "LISTS_INDEX_OF_TOOLTIP": "Retorna le indice del prime/ultime occurrentia del elemento in le lista. Retorna %1 si le elemento non es trovate.", - "LISTS_GET_INDEX_GET": "prender", - "LISTS_GET_INDEX_GET_REMOVE": "prender e remover", - "LISTS_GET_INDEX_REMOVE": "remover", - "LISTS_GET_INDEX_FROM_END": "№ ab fin", - "LISTS_GET_INDEX_FIRST": "prime", - "LISTS_GET_INDEX_LAST": "ultime", - "LISTS_GET_INDEX_RANDOM": "aleatori", - "LISTS_INDEX_FROM_START_TOOLTIP": "№ %1 es le prime elemento.", - "LISTS_INDEX_FROM_END_TOOLTIP": "№ %1 es le ultime elemento.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Retorna le elemento presente al position specificate in un lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Retorna le prime elemento in un lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Retorna le ultime elemento in un lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Retorna un elemento aleatori in un lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Remove e retorna le elemento presente al position specificate in un lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Remove e retorna le prime elemento in un lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Remove e retorna le ultime elemento in un lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Remove e retorna un elemento aleatori in un lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Remove le elemento presente al position specificate in un lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Remove le prime elemento in un lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Remove le ultime elemento in un lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Remove un elemento aleatori in un lista.", - "LISTS_SET_INDEX_SET": "mitter", - "LISTS_SET_INDEX_INSERT": "inserer in", - "LISTS_SET_INDEX_INPUT_TO": "a", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Defini le valor del elemento al position specificate in un lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Defini le valor del prime elemento in un lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Defini le valor del ultime elemento in un lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Defini le valor de un elemento aleatori in un lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Insere le elemento al position specificate in un lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Insere le elemento al initio de un lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Adjunge le elemento al fin de un lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Insere le elemento a un position aleatori in un lista.", - "LISTS_GET_SUBLIST_START_FROM_START": "prender sublista ab №", - "LISTS_GET_SUBLIST_START_FROM_END": "prender sublista ab le fin ab №", - "LISTS_GET_SUBLIST_START_FIRST": "prender sublista ab initio", - "LISTS_GET_SUBLIST_END_FROM_START": "usque al №", - "LISTS_GET_SUBLIST_END_FROM_END": "usque al № ab fin", - "LISTS_GET_SUBLIST_END_LAST": "usque al ultime", - "LISTS_GET_SUBLIST_TOOLTIP": "Crea un copia del parte specificate de un lista.", - "LISTS_SORT_TITLE": "ordinamento %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Ordinar un copia de un lista.", - "LISTS_SORT_ORDER_ASCENDING": "ascendente", - "LISTS_SORT_ORDER_DESCENDING": "descendente", - "LISTS_SORT_TYPE_NUMERIC": "numeric", - "LISTS_SORT_TYPE_TEXT": "alphabetic", - "LISTS_SORT_TYPE_IGNORECASE": "alphabetic, ignorar majuscula/minuscula", - "LISTS_SPLIT_LIST_FROM_TEXT": "Crear un lista per un texto", - "LISTS_SPLIT_TEXT_FROM_LIST": "crear un texto per un lista", - "LISTS_SPLIT_WITH_DELIMITER": "con delimitator", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Divider texto in un lista de textos, separante lo a cata delimitator.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Unir un lista de textos, separate per un delimitator, in un sol texto.", - "VARIABLES_GET_TOOLTIP": "Retorna le valor de iste variabile.", - "VARIABLES_GET_CREATE_SET": "Crea 'mitter %1'", - "VARIABLES_SET": "mitter %1 a %2", - "VARIABLES_SET_TOOLTIP": "Mitte iste variabile al valor del entrata.", - "VARIABLES_SET_CREATE_GET": "Crear 'prender %1'", - "PROCEDURES_DEFNORETURN_TITLE": "pro", - "PROCEDURES_DEFNORETURN_PROCEDURE": "facer qualcosa", - "PROCEDURES_BEFORE_PARAMS": "con:", - "PROCEDURES_CALL_BEFORE_PARAMS": "con:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Crea un function que non retorna un valor.", - "PROCEDURES_DEFNORETURN_COMMENT": "Describe iste function...", - "PROCEDURES_DEFRETURN_RETURN": "retornar", - "PROCEDURES_DEFRETURN_TOOLTIP": "Crea un function que retorna un valor.", - "PROCEDURES_ALLOW_STATEMENTS": "permitter declarationes", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Attention: Iste function ha parametros duplicate.", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Executar le function '%1' definite per le usator.", - "PROCEDURES_CALLRETURN_TOOLTIP": "Executar le function '%1' definite per le usator e usar su resultato.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "entratas", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Adder, remover o reordinar le entratas pro iste function.", - "PROCEDURES_MUTATORARG_TITLE": "nomine del entrata:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Adder un entrata al function.", - "PROCEDURES_HIGHLIGHT_DEF": "Accentuar le definition del function", - "PROCEDURES_CREATE_DO": "Crear '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Si un valor es ver, alora retornar un secunde valor.", - "PROCEDURES_IFRETURN_WARNING": "Attention: Iste bloco pote solmente esser usate in le definition de un function." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/id.json b/backend/_pv_1_3_5/static/blockly/msg/json/id.json deleted file mode 100755 index 3f61ade87..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/id.json +++ /dev/null @@ -1,335 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Kenrick95", - "아라", - "Mirws", - "Marwan Mohamad", - "Kasimtan", - "Arifin.wijaya" - ] - }, - "VARIABLES_DEFAULT_NAME": "item", - "TODAY": "Hari ini", - "DUPLICATE_BLOCK": "Duplikat", - "ADD_COMMENT": "Tambahkan Komentar", - "REMOVE_COMMENT": "Hapus Komentar", - "EXTERNAL_INPUTS": "Input Eksternal", - "INLINE_INPUTS": "Input Inline", - "DELETE_BLOCK": "Hapus Blok", - "DELETE_X_BLOCKS": "Hapus %1 Blok", - "DELETE_ALL_BLOCKS": "Hapus semua %1 blok?", - "CLEAN_UP": "Bersihkan Blok", - "COLLAPSE_BLOCK": "Ciutkan Blok", - "COLLAPSE_ALL": "Ciutkan Blok", - "EXPAND_BLOCK": "Kembangkan Blok", - "EXPAND_ALL": "Kembangkan Blok", - "DISABLE_BLOCK": "Nonaktifkan Blok", - "ENABLE_BLOCK": "Aktifkan Blok", - "HELP": "Bantuan", - "UNDO": "Urungkan", - "REDO": "Lakukan ulang", - "CHANGE_VALUE_TITLE": "Ubah nilai:", - "RENAME_VARIABLE": "Ubah nama variabel...", - "RENAME_VARIABLE_TITLE": "Ubah nama semua variabel '%1' menjadi:", - "NEW_VARIABLE": "Buat variabel...", - "NEW_VARIABLE_TITLE": "Nama variabel baru:", - "VARIABLE_ALREADY_EXISTS": "Sebuah variabel dengan nama '%1' sudah ada.", - "DELETE_VARIABLE_CONFIRMATION": "Hapus %1 yang digunakan pada variabel '%2'?", - "DELETE_VARIABLE": "Hapus variabel '%1'", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "Pilih warna dari daftar warna.", - "COLOUR_RANDOM_TITLE": "Warna acak", - "COLOUR_RANDOM_TOOLTIP": "Pilih warna secara acak.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "Dengan warna", - "COLOUR_RGB_RED": "merah", - "COLOUR_RGB_GREEN": "hijau", - "COLOUR_RGB_BLUE": "biru", - "COLOUR_RGB_TOOLTIP": "Buatlah warna dengan jumlah yang ditentukan dari merah, hijau dan biru. Semua nilai harus antarai 0 sampai 100.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "campur", - "COLOUR_BLEND_COLOUR1": "warna 1", - "COLOUR_BLEND_COLOUR2": "warna 2", - "COLOUR_BLEND_RATIO": "rasio", - "COLOUR_BLEND_TOOLTIP": "Campur dua warna secara bersamaan dengan perbandingan (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "ulangi %1 kali", - "CONTROLS_REPEAT_INPUT_DO": "kerjakan", - "CONTROLS_REPEAT_TOOLTIP": "Lakukan beberapa perintah beberapa kali.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "ulangi jika", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "ulangi sampai", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Selagi nilainya benar, maka lakukan beberapa perintah.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Selagi nilainya salah, maka lakukan beberapa perintah.", - "CONTROLS_FOR_TOOLTIP": "Menggunakan variabel \"%1\" dengan mengambil nilai dari batas awal hingga ke batas akhir, dengan interval tertentu, dan mengerjakan block tertentu.", - "CONTROLS_FOR_TITLE": "Cacah dengan %1 dari %2 ke %3 dengan step / penambahan %4", - "CONTROLS_FOREACH_TITLE": "untuk setiap item %1 di dalam list %2", - "CONTROLS_FOREACH_TOOLTIP": "Untuk tiap-tiap item di dalam list, tetapkan variabel '%1' ke dalam item, selanjutnya kerjakan beberapa statement.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "keluar dari perulangan", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "lanjutkan dengan langkah perulangan berikutnya", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Keluar dari perulangan.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Abaikan sisa dari perulangan ini, dan lanjutkan dengan langkah berikutnya.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Peringatan: Blok ini hanya dapat digunakan dalam perulangan.", - "CONTROLS_IF_TOOLTIP_1": "Jika nilainya benar, maka lakukan beberapa perintah.", - "CONTROLS_IF_TOOLTIP_2": "Jika nilainya benar, maka kerjakan perintah blok pertama. Jika tidak, kerjakan perintah blok kedua.", - "CONTROLS_IF_TOOLTIP_3": "Jika nilai pertama benar, maka kerjakan perintah blok pertama. Sebaliknya, jika nilai kedua benar, kerjakan perintah blok kedua.", - "CONTROLS_IF_TOOLTIP_4": "Jika nilai pertama benar, maka kerjakan perintah blok pertama. Sebaliknya, jika nilai kedua benar, kerjakan perintah blok kedua. Jika dua-duanya tidak benar, kerjakan perintah blok terakhir.", - "CONTROLS_IF_MSG_IF": "jika", - "CONTROLS_IF_MSG_ELSEIF": "atau jika", - "CONTROLS_IF_MSG_ELSE": "lainnya", - "CONTROLS_IF_IF_TOOLTIP": "Tambahkan, hapus, atau susun kembali bagian untuk mengkonfigurasi blok IF ini.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Tambahkan prasyarat ke dalam blok IF.", - "CONTROLS_IF_ELSE_TOOLTIP": "Terakhir, tambahkan kondisi tangkap-semua kedalam blok IF.", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Kembalikan benar jika kedua input sama satu dengan lainnya.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Kembalikan benar jika kedua input tidak sama satu dengan lainnya.", - "LOGIC_COMPARE_TOOLTIP_LT": "Kembalikan benar jika input pertama lebih kecil dari input kedua.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Kembalikan benar jika input pertama lebih kecil atau sama dengan input kedua .", - "LOGIC_COMPARE_TOOLTIP_GT": "Kembalikan benar jika input pertama lebih besar dari input kedua.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Kembalikan benar jika input pertama lebih besar dari atau sama dengan input kedua.", - "LOGIC_OPERATION_TOOLTIP_AND": "Kembalikan benar jika kedua input adalah benar.", - "LOGIC_OPERATION_AND": "dan", - "LOGIC_OPERATION_TOOLTIP_OR": "Kembalikan benar jika minimal satu input nilainya benar.", - "LOGIC_OPERATION_OR": "atau", - "LOGIC_NEGATE_TITLE": "bukan (not) %1", - "LOGIC_NEGATE_TOOLTIP": "Kembalikan benar jika input salah. Kembalikan salah jika input benar.", - "LOGIC_BOOLEAN_TRUE": "benar", - "LOGIC_BOOLEAN_FALSE": "salah", - "LOGIC_BOOLEAN_TOOLTIP": "Kembalikan benar atau salah.", - "LOGIC_NULL_HELPURL": "https://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "null", - "LOGIC_NULL_TOOLTIP": "Kembalikan null.", - "LOGIC_TERNARY_HELPURL": "https://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "jika benar", - "LOGIC_TERNARY_IF_FALSE": "jika salah", - "LOGIC_TERNARY_TOOLTIP": "Periksa kondisi di 'test'. Jika kondisi benar, kembalikan nilai 'if true'; jika sebaliknya kembalikan nilai 'if false'.", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "Suatu angka.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tan", - "MATH_TRIG_ASIN": "asin", - "MATH_TRIG_ACOS": "acos", - "MATH_TRIG_ATAN": "atan", - "MATH_ARITHMETIC_HELPURL": "https://id.wikipedia.org/wiki/Aritmetika", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Kembalikan jumlah dari kedua angka.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Kembalikan selisih dari kedua angka.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Kembalikan perkalian dari kedua angka.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Kembalikan hasil bagi dari kedua angka.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Kembalikan angka pertama pangkat angka kedua.", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "akar", - "MATH_SINGLE_TOOLTIP_ROOT": "Kembalikan akar dari angka.", - "MATH_SINGLE_OP_ABSOLUTE": "mutlak", - "MATH_SINGLE_TOOLTIP_ABS": "Kembalikan nilai absolut angka.", - "MATH_SINGLE_TOOLTIP_NEG": "Kembalikan penyangkalan terhadap angka.", - "MATH_SINGLE_TOOLTIP_LN": "Kembalikan logaritma natural dari angka.", - "MATH_SINGLE_TOOLTIP_LOG10": "Kembalikan dasar logaritma 10 dari angka.", - "MATH_SINGLE_TOOLTIP_EXP": "Kembalikan 10 pangkat angka.", - "MATH_SINGLE_TOOLTIP_POW10": "Kembalikan 10 pangkat angka.", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "Kembalikan sinus dari derajat (bukan radian).", - "MATH_TRIG_TOOLTIP_COS": "Kembalikan cosinus dari derajat (bukan radian).", - "MATH_TRIG_TOOLTIP_TAN": "Kembalikan tangen dari derajat (bukan radian).", - "MATH_TRIG_TOOLTIP_ASIN": "Kembalikan asin dari angka.", - "MATH_TRIG_TOOLTIP_ACOS": "Kembalikan acosine dari angka.", - "MATH_TRIG_TOOLTIP_ATAN": "Kembalikan atan dari angka.", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "Kembalikan salah satu konstanta: π (3,141…), e (2,718…), φ (1,618…), akar(2) (1,414…), akar(½) (0.707…), atau ∞ (tak terhingga).", - "MATH_IS_EVEN": "adalah bilangan genap", - "MATH_IS_ODD": "adalah bilangan ganjil", - "MATH_IS_PRIME": "adalah bilangan pokok", - "MATH_IS_WHOLE": "adalah bilangan bulat", - "MATH_IS_POSITIVE": "adalah bilangan positif", - "MATH_IS_NEGATIVE": "adalah bilangan negatif", - "MATH_IS_DIVISIBLE_BY": "dapat dibagi oleh", - "MATH_IS_TOOLTIP": "Periksa apakah angka adalah bilangan genap, bilangan ganjil, bilangan pokok, bilangan bulat, bilangan positif, bilangan negatif, atau apakan bisa dibagi oleh angka tertentu. Kembalikan benar atau salah.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "ubah %1 oleh %2", - "MATH_CHANGE_TOOLTIP": "Tambahkan angka kedalam variabel '%1'.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Bulatkan suatu bilangan naik atau turun.", - "MATH_ROUND_OPERATOR_ROUND": "membulatkan", - "MATH_ROUND_OPERATOR_ROUNDUP": "membulatkan keatas", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "membulatkan kebawah", - "MATH_ONLIST_OPERATOR_SUM": "jumlah dari list", - "MATH_ONLIST_TOOLTIP_SUM": "Kembalikan jumlah dari seluruh bilangan dari list.", - "MATH_ONLIST_OPERATOR_MIN": "minimum dari list", - "MATH_ONLIST_TOOLTIP_MIN": "Kembalikan angka terkecil dari list.", - "MATH_ONLIST_OPERATOR_MAX": "maksimum dari list", - "MATH_ONLIST_TOOLTIP_MAX": "Kembalikan angka terbesar dari list.", - "MATH_ONLIST_OPERATOR_AVERAGE": "rata-rata dari list", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Kembalikan rata-rata (mean aritmetik) dari nilai numerik dari list.", - "MATH_ONLIST_OPERATOR_MEDIAN": "median dari list", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Kembalikan median dari list.", - "MATH_ONLIST_OPERATOR_MODE": "mode-mode dari list", - "MATH_ONLIST_TOOLTIP_MODE": "Kembalikan list berisi item yang paling umum dari dalam list.", - "MATH_ONLIST_OPERATOR_STD_DEV": "deviasi standar dari list", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Kembalikan standard deviasi dari list.", - "MATH_ONLIST_OPERATOR_RANDOM": "item acak dari list", - "MATH_ONLIST_TOOLTIP_RANDOM": "Kembalikan elemen acak dari list.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "sisa dari %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Kembalikan sisa dari pembagian ke dua angka.", - "MATH_CONSTRAIN_TITLE": "Batasi %1 rendah %2 tinggi %3", - "MATH_CONSTRAIN_TOOLTIP": "Batasi angka antara batas yang ditentukan (inklusif).", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "acak bulat dari %1 sampai %2", - "MATH_RANDOM_INT_TOOLTIP": "Kembalikan bilangan acak antara dua batas yang ditentukan, inklusif.", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "nilai pecahan acak", - "MATH_RANDOM_FLOAT_TOOLTIP": "Kembalikan nilai pecahan acak antara 0.0 (inklusif) dan 1.0 (eksklusif).", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "Huruf, kata atau baris teks.", - "TEXT_JOIN_TITLE_CREATEWITH": "buat teks dengan", - "TEXT_JOIN_TOOLTIP": "Buat teks dengan cara gabungkan sejumlah item.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "join", - "TEXT_CREATE_JOIN_TOOLTIP": "Tambah, ambil, atau susun ulang teks blok.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Tambahkan suatu item ke dalam teks.", - "TEXT_APPEND_TO": "untuk", - "TEXT_APPEND_APPENDTEXT": "tambahkan teks", - "TEXT_APPEND_TOOLTIP": "Tambahkan beberapa teks ke variabel '%1'.", - "TEXT_LENGTH_TITLE": "panjang dari %1", - "TEXT_LENGTH_TOOLTIP": "Kembalikan sejumlah huruf (termasuk spasi) dari teks yang disediakan.", - "TEXT_ISEMPTY_TITLE": "%1 kosong", - "TEXT_ISEMPTY_TOOLTIP": "Kembalikan benar jika teks yang disediakan kosong.", - "TEXT_INDEXOF_TOOLTIP": "Kembalikan indeks pertama dan terakhir dari kejadian pertama/terakhir dari teks pertama dalam teks kedua. Kembalikan %1 jika teks tidak ditemukan.", - "TEXT_INDEXOF_INPUT_INTEXT": "dalam teks", - "TEXT_INDEXOF_OPERATOR_FIRST": "temukan kejadian pertama dalam teks", - "TEXT_INDEXOF_OPERATOR_LAST": "temukan kejadian terakhir dalam teks", - "TEXT_CHARAT_INPUT_INTEXT": "dalam teks", - "TEXT_CHARAT_FROM_START": "ambil huruf ke #", - "TEXT_CHARAT_FROM_END": "ambil huruf nomor # dari belakang", - "TEXT_CHARAT_FIRST": "ambil huruf pertama", - "TEXT_CHARAT_LAST": "ambil huruf terakhir", - "TEXT_CHARAT_RANDOM": "ambil huruf secara acak", - "TEXT_CHARAT_TOOLTIP": "Kembalikan karakter dari posisi tertentu.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Kembalikan spesifik bagian dari teks.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "in teks", - "TEXT_GET_SUBSTRING_START_FROM_START": "ambil bagian teks (substring) dari huruf no #", - "TEXT_GET_SUBSTRING_START_FROM_END": "ambil bagian teks (substring) dari huruf ke # dari terakhir", - "TEXT_GET_SUBSTRING_START_FIRST": "ambil bagian teks (substring) dari huruf pertama", - "TEXT_GET_SUBSTRING_END_FROM_START": "pada huruf #", - "TEXT_GET_SUBSTRING_END_FROM_END": "pada huruf nomer # dari terakhir", - "TEXT_GET_SUBSTRING_END_LAST": "pada huruf terakhir", - "TEXT_CHANGECASE_TOOLTIP": "Kembalikan kopi dari text dengan kapitalisasi yang berbeda.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "menjadi huruf kapital", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "menjadi huruf kecil", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "menjadi huruf pertama kapital", - "TEXT_TRIM_TOOLTIP": "Kembali salinan teks dengan spasi dihapus dari satu atau kedua ujungnya.", - "TEXT_TRIM_OPERATOR_BOTH": "pangkas ruang dari kedua belah sisi", - "TEXT_TRIM_OPERATOR_LEFT": "pangkas ruang dari sisi kiri", - "TEXT_TRIM_OPERATOR_RIGHT": "pangkas ruang dari sisi kanan", - "TEXT_PRINT_TITLE": "cetak %1", - "TEXT_PRINT_TOOLTIP": "Cetak teks yant ditentukan, angka atau ninlai lainnya.", - "TEXT_PROMPT_TYPE_TEXT": "meminta teks dengan pesan", - "TEXT_PROMPT_TYPE_NUMBER": "Meminta angka dengan pesan", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Meminta pengguna untuk memberi sebuah angka.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Meminta pengguna untuk memberi beberapa teks.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "buat list kosong", - "LISTS_CREATE_EMPTY_TOOLTIP": "Kembalikan list, dengan panjang 0, tidak berisi data", - "LISTS_CREATE_WITH_TOOLTIP": "Buat sebuah list dengan sejumlah item.", - "LISTS_CREATE_WITH_INPUT_WITH": "buat list dengan", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "list", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Tambahkan, hapus, atau susun ulang bagian untuk mengkonfigurasi blok list ini.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Tambahkan sebuah item ke list.", - "LISTS_REPEAT_TOOLTIP": "Buat sebuah list yang terdiri dari nilai yang diberikan diulang sebanyak jumlah yang ditentukan.", - "LISTS_REPEAT_TITLE": "buat list dengan item %1 diulang %2 kali", - "LISTS_LENGTH_TITLE": "panjang dari %1", - "LISTS_LENGTH_TOOLTIP": "Kembalikan panjang list.", - "LISTS_ISEMPTY_TITLE": "%1 kosong", - "LISTS_ISEMPTY_TOOLTIP": "Kembalikan benar jika list kosong.", - "LISTS_INLIST": "dalam list", - "LISTS_INDEX_OF_FIRST": "cari kejadian pertama item", - "LISTS_INDEX_OF_LAST": "cari kejadian terakhir item", - "LISTS_INDEX_OF_TOOLTIP": "Kembalikan indeks dari item pertama/terakhir kali muncul dalam list. Kembalikan %1 jika item tidak ditemukan.", - "LISTS_GET_INDEX_GET": "dapatkan", - "LISTS_GET_INDEX_GET_REMOVE": "dapatkan dan hapus", - "LISTS_GET_INDEX_REMOVE": "Hapus", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# dari akhir", - "LISTS_GET_INDEX_FIRST": "pertama", - "LISTS_GET_INDEX_LAST": "terakhir", - "LISTS_GET_INDEX_RANDOM": "acak", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 adalah item pertama.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 adalah item terakhir.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Kembalikan item di posisi tertentu dalam list.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Kembalikan item pertama dalam list.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Kembalikan item terakhir dalam list.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Kembalikan item acak dalam list.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Hapus dan kembalikan item di posisi tertentu dalam list.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Hapus dan kembalikan item pertama dalam list.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Hapus dan kembalikan item terakhir dalam list.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Hapus dan kembalikan item acak dalam list.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Hapus item di posisi tertentu dalam list.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Hapus item pertama dalam list.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Hapus item terakhir dalam list.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Hapus sebuah item acak dalam list.", - "LISTS_SET_INDEX_SET": "tetapkan", - "LISTS_SET_INDEX_INSERT": "sisipkan di", - "LISTS_SET_INDEX_INPUT_TO": "sebagai", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Tetapkan item ke dalam posisi yang telah ditentukan di dalam list.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Tetapkan item pertama di dalam list.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Menetapkan item terakhir dalam list.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Tetapkan secara acak sebuah item dalam list.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Sisipkan item ke dalam posisi yang telah ditentukan di dalam list.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Sisipkan item di bagian awal dari list.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Tambahkan item ke bagian akhir list.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Sisipkan item secara acak ke dalam list.", - "LISTS_GET_SUBLIST_START_FROM_START": "dapatkan sub-list dari #", - "LISTS_GET_SUBLIST_START_FROM_END": "dapatkan sub-list dari nomor # dari akhir", - "LISTS_GET_SUBLIST_START_FIRST": "dapatkan sub-list dari pertama", - "LISTS_GET_SUBLIST_END_FROM_START": "ke #", - "LISTS_GET_SUBLIST_END_FROM_END": "ke # dari akhir", - "LISTS_GET_SUBLIST_END_LAST": "ke yang paling akhir", - "LISTS_GET_SUBLIST_TOOLTIP": "Buat salinan bagian tertentu dari list.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "urutkan %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Urutkan salinan dari daftar", - "LISTS_SORT_ORDER_ASCENDING": "menaik", - "LISTS_SORT_ORDER_DESCENDING": "menurun", - "LISTS_SORT_TYPE_NUMERIC": "sesuai nomor", - "LISTS_SORT_TYPE_TEXT": "sesuai abjad", - "LISTS_SORT_TYPE_IGNORECASE": "sesuai abjad, abaikan kasus", - "LISTS_SPLIT_LIST_FROM_TEXT": "buat list dari teks", - "LISTS_SPLIT_TEXT_FROM_LIST": "buat teks dari list", - "LISTS_SPLIT_WITH_DELIMITER": "dengan pembatas", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Membagi teks ke dalam daftar teks, pisahkan pada setiap pembatas.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Gabung daftar teks menjadi satu teks, yang dipisahkan oleh pembatas.", - "VARIABLES_GET_TOOLTIP": "Kembalikan nilai variabel ini.", - "VARIABLES_GET_CREATE_SET": "Buat 'set %1'", - "VARIABLES_SET": "tetapkan %1 untuk %2", - "VARIABLES_SET_TOOLTIP": "tetapkan variabel ini dengan input yang sama.", - "VARIABLES_SET_CREATE_GET": "Buat 'get %1'", - "PROCEDURES_DEFNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFNORETURN_TITLE": "untuk", - "PROCEDURES_DEFNORETURN_PROCEDURE": "buat sesuatu", - "PROCEDURES_BEFORE_PARAMS": "dengan:", - "PROCEDURES_CALL_BEFORE_PARAMS": "dengan:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Buat sebuah fungsi tanpa output.", - "PROCEDURES_DEFNORETURN_COMMENT": "Jelaskan fungsi ini...", - "PROCEDURES_DEFRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFRETURN_RETURN": "kembali", - "PROCEDURES_DEFRETURN_TOOLTIP": "Buat sebuah fungsi dengan satu output.", - "PROCEDURES_ALLOW_STATEMENTS": "memungkinkan pernyataan", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Peringatan: Fungsi ini memiliki parameter duplikat.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Menjalankan fungsi '%1' yang ditetapkan pengguna.", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Menjalankan fungsi '%1' yang ditetapkan pengguna dan menggunakan outputnya.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "input", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Menambah, menghapus, atau menyusun ulang masukan untuk fungsi ini.", - "PROCEDURES_MUTATORARG_TITLE": "masukan Nama:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Tambahkan masukan ke fungsi.", - "PROCEDURES_HIGHLIGHT_DEF": "Sorot definisi fungsi", - "PROCEDURES_CREATE_DO": "Buat '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Jika nilai yang benar, kemudian kembalikan nilai kedua.", - "PROCEDURES_IFRETURN_WARNING": "Peringatan: Blok ini dapat digunakan hanya dalam definisi fungsi." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/is.json b/backend/_pv_1_3_5/static/blockly/msg/json/is.json deleted file mode 100755 index 8bf3dc2e4..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/is.json +++ /dev/null @@ -1,357 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Jonbg", - "아라", - "Gaddi00", - "Sveinki", - "Sveinn í Felli" - ] - }, - "VARIABLES_DEFAULT_NAME": "atriði", - "TODAY": "Í dag", - "DUPLICATE_BLOCK": "Afrita", - "ADD_COMMENT": "Skrifa skýringu", - "REMOVE_COMMENT": "Fjarlægja skýringu", - "EXTERNAL_INPUTS": "Ytri inntök", - "INLINE_INPUTS": "Innri inntök", - "DELETE_BLOCK": "Eyða kubbi", - "DELETE_X_BLOCKS": "Eyða %1 kubbum", - "DELETE_ALL_BLOCKS": "Eyða öllum %1 kubbunum?", - "CLEAN_UP": "Hreinsa kubba", - "COLLAPSE_BLOCK": "Loka kubbi", - "COLLAPSE_ALL": "Loka kubbum", - "EXPAND_BLOCK": "Opna kubb", - "EXPAND_ALL": "Opna kubba", - "DISABLE_BLOCK": "Óvirkja kubb", - "ENABLE_BLOCK": "Virkja kubb", - "HELP": "Hjálp", - "UNDO": "Afturkalla", - "REDO": "Endurtaka", - "CHANGE_VALUE_TITLE": "Breyta gildi:", - "RENAME_VARIABLE": "Endurnefna breytu...", - "RENAME_VARIABLE_TITLE": "Endurnefna allar '%1' breyturnar:", - "NEW_VARIABLE": "Ný breyta...", - "NEW_VARIABLE_TITLE": "Heiti nýrrar breytu:", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "Velja lit úr litakorti.", - "COLOUR_RANDOM_TITLE": "einhver litur", - "COLOUR_RANDOM_TOOLTIP": "Velja einhvern lit af handahófi.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "litur", - "COLOUR_RGB_RED": "rauður", - "COLOUR_RGB_GREEN": "grænt", - "COLOUR_RGB_BLUE": "blátt", - "COLOUR_RGB_TOOLTIP": "Búa til lit úr tilteknu magni af rauðu, grænu og bláu. Allar tölurnar verða að vera á bilinu 0 til 100.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "blöndun", - "COLOUR_BLEND_COLOUR1": "litur 1", - "COLOUR_BLEND_COLOUR2": "litur 2", - "COLOUR_BLEND_RATIO": "hlutfall", - "COLOUR_BLEND_TOOLTIP": "Blandar tveimur litum í gefnu hlutfalli (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "endurtaka %1 sinnum", - "CONTROLS_REPEAT_INPUT_DO": "gera", - "CONTROLS_REPEAT_TOOLTIP": "Gera eitthvað aftur og aftur.", - "CONTROLS_WHILEUNTIL_HELPURL": "https://github.com/google/blockly/wiki/Loops#repeat", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "endurtaka á meðan", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "endurtaka þar til", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Endurtaka eitthvað á meðan gildi er satt.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Endurtaka eitthvað á meðan gildi er ósatt.", - "CONTROLS_FOR_HELPURL": "https://github.com/google/blockly/wiki/Loops#count-with", - "CONTROLS_FOR_TOOLTIP": "Láta breytuna '%1' taka inn gildi frá fyrstu tölu til síðustu tölu, hlaupandi á tiltekna bilinu og gera tilteknu kubbana.", - "CONTROLS_FOR_TITLE": "telja með %1 frá %2 til %3 um %4", - "CONTROLS_FOREACH_TITLE": "fyrir hvert %1 í lista %2", - "CONTROLS_FOREACH_TOOLTIP": "Fyrir hvert atriði í lista er breyta '%1' stillt á atriðið og skipanir gerðar.", - "CONTROLS_FLOW_STATEMENTS_HELPURL": "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "fara út úr lykkju", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "fara beint í næstu umferð lykkjunnar", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Fara út úr umlykjandi lykkju.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Sleppa afganginum af lykkjunni og fara beint í næstu umferð hennar.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Aðvörun: Þennan kubb má aðeins nota innan lykkju.", - "CONTROLS_IF_HELPURL": "https://github.com/google/blockly/wiki/IfElse", - "CONTROLS_IF_TOOLTIP_1": "Ef gildi er satt skal gera einhverjar skipanir.", - "CONTROLS_IF_TOOLTIP_2": "Ef gildi er satt skal gera skipanir í fyrri kubbnum. Annars skal gera skipanir í seinni kubbnum.", - "CONTROLS_IF_TOOLTIP_3": "Ef fyrra gildið er satt skal gera skipanir í fyrri kubbnum. Annars, ef seinna gildið er satt, þá skal gera skipanir í seinni kubbnum.", - "CONTROLS_IF_TOOLTIP_4": "Ef fyrra gildið er satt skal gera skipanir í fyrri kubbnum. Annars, ef seinna gildið er satt, skal gera skipanir í seinni kubbnum. Ef hvorugt gildið er satt, skal gera skipanir í síðasta kubbnum.", - "CONTROLS_IF_MSG_IF": "ef", - "CONTROLS_IF_MSG_ELSEIF": "annars ef", - "CONTROLS_IF_MSG_ELSE": "annars", - "CONTROLS_IF_IF_TOOLTIP": "Bæta við, fjarlægja eða umraða til að breyta skipan þessa EF kubbs.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Bæta skilyrði við EF kubbinn.", - "CONTROLS_IF_ELSE_TOOLTIP": "Bæta við hluta EF kubbs sem grípur öll tilfelli sem uppfylla ekki hin skilyrðin.", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Skila sönnu ef inntökin eru jöfn.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Skila sönnu ef inntökin eru ekki jöfn.", - "LOGIC_COMPARE_TOOLTIP_LT": "Skila sönnu ef fyrra inntakið er minna en seinna inntakið.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Skila sönnu ef fyrra inntakið er minna en eða jafnt og seinna inntakið.", - "LOGIC_COMPARE_TOOLTIP_GT": "Skila sönnu ef fyrra inntakið er stærra en seinna inntakið.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Skila sönnu ef fyrra inntakið er stærra en eða jafnt og seinna inntakið.", - "LOGIC_OPERATION_HELPURL": "https://github.com/google/blockly/wiki/Logic#logical-operations", - "LOGIC_OPERATION_TOOLTIP_AND": "Skila sönnu ef bæði inntökin eru sönn.", - "LOGIC_OPERATION_AND": "og", - "LOGIC_OPERATION_TOOLTIP_OR": "Skila sönnu ef að minnsta kosti eitt inntak er satt.", - "LOGIC_OPERATION_OR": "eða", - "LOGIC_NEGATE_HELPURL": "https://github.com/google/blockly/wiki/Logic#not", - "LOGIC_NEGATE_TITLE": "ekki %1", - "LOGIC_NEGATE_TOOLTIP": "Skilar sönnu ef inntakið er ósatt. Skilar ósönnu ef inntakið er satt.", - "LOGIC_BOOLEAN_HELPURL": "https://github.com/google/blockly/wiki/Logic#values", - "LOGIC_BOOLEAN_TRUE": "satt", - "LOGIC_BOOLEAN_FALSE": "ósatt", - "LOGIC_BOOLEAN_TOOLTIP": "Skilar annað hvort sönnu eða ósönnu.", - "LOGIC_NULL_HELPURL": "https://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "tómagildi", - "LOGIC_NULL_TOOLTIP": "Skilar tómagildi.", - "LOGIC_TERNARY_HELPURL": "https://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "prófun", - "LOGIC_TERNARY_IF_TRUE": "ef satt", - "LOGIC_TERNARY_IF_FALSE": "ef ósatt", - "LOGIC_TERNARY_TOOLTIP": "Kanna skilyrðið í 'prófun'. Skilar 'ef satt' gildinu ef skilyrðið er satt, en skilar annars 'ef ósatt' gildinu.", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "Tala.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tan", - "MATH_TRIG_ASIN": "asin", - "MATH_TRIG_ACOS": "acos", - "MATH_TRIG_ATAN": "atan", - "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/Arithmetic", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Skila summu talnanna tveggja.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Skila mismun talnanna.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Skila margfeldi talnanna.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Skila deilingu talnanna.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Skila fyrri tölunni í veldinu seinni talan.", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "kvaðratrót", - "MATH_SINGLE_TOOLTIP_ROOT": "Skila kvaðratrót tölu.", - "MATH_SINGLE_OP_ABSOLUTE": "algildi", - "MATH_SINGLE_TOOLTIP_ABS": "Skila algildi tölu.", - "MATH_SINGLE_TOOLTIP_NEG": "Skila neitun tölu (tölunni með öfugu formerki).", - "MATH_SINGLE_TOOLTIP_LN": "Skila náttúrlegum lógaritma tölu.", - "MATH_SINGLE_TOOLTIP_LOG10": "Skila tugalógaritma tölu.", - "MATH_SINGLE_TOOLTIP_EXP": "Skila e í veldi tölu.", - "MATH_SINGLE_TOOLTIP_POW10": "Skila 10 í veldi tölu.", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "Skila sínusi horns gefnu í gráðum.", - "MATH_TRIG_TOOLTIP_COS": "Skila kósínusi horns gefnu í gráðum.", - "MATH_TRIG_TOOLTIP_TAN": "Skila tangensi horns gefnu í gráðum.", - "MATH_TRIG_TOOLTIP_ASIN": "Skila arkarsínusi tölu.", - "MATH_TRIG_TOOLTIP_ACOS": "Skila arkarkósínusi tölu.", - "MATH_TRIG_TOOLTIP_ATAN": "Skila arkartangensi tölu.", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "Skila algengum fasta: π (3.141…), e (2.718…), φ (1.618…), kvrót(2) (1.414…), kvrót(½) (0.707…) eða ∞ (óendanleika).", - "MATH_IS_EVEN": "er\\u00A0jöfn tala", - "MATH_IS_ODD": "er oddatala", - "MATH_IS_PRIME": "er prímtala", - "MATH_IS_WHOLE": "er heiltala", - "MATH_IS_POSITIVE": "er jákvæð", - "MATH_IS_NEGATIVE": "er neikvæð", - "MATH_IS_DIVISIBLE_BY": "er\\u00A0deilanleg með", - "MATH_IS_TOOLTIP": "Kanna hvort tala sé jöfn tala, oddatala, jákvæð, neikvæð eða deilanleg með tiltekinni tölu. Skilar sönnu eða ósönnu.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "breyta %1 um %2", - "MATH_CHANGE_TOOLTIP": "Bæta tölu við breytu '%1'.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Námunda tölu upp eða niður.", - "MATH_ROUND_OPERATOR_ROUND": "námunda", - "MATH_ROUND_OPERATOR_ROUNDUP": "námunda upp", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "námunda niður", - "MATH_ONLIST_OPERATOR_SUM": "summa lista", - "MATH_ONLIST_TOOLTIP_SUM": "Skila summu allra talna í listanum.", - "MATH_ONLIST_OPERATOR_MIN": "minnst í lista", - "MATH_ONLIST_TOOLTIP_MIN": "Skila minnstu tölu í listanum.", - "MATH_ONLIST_OPERATOR_MAX": "stærst í lista", - "MATH_ONLIST_TOOLTIP_MAX": "Skila stærstu tölu í listanum.", - "MATH_ONLIST_OPERATOR_AVERAGE": "meðaltal lista", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Skila meðaltali talna í listanum.", - "MATH_ONLIST_OPERATOR_MEDIAN": "miðgildi lista", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Skila miðgildi listans.", - "MATH_ONLIST_OPERATOR_MODE": "tíðast í lista", - "MATH_ONLIST_TOOLTIP_MODE": "Skila lista yfir tíðustu gildin í listanum.", - "MATH_ONLIST_OPERATOR_STD_DEV": "staðalfrávik lista", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Skila staðalfráviki lista.", - "MATH_ONLIST_OPERATOR_RANDOM": "eitthvað úr lista", - "MATH_ONLIST_TOOLTIP_RANDOM": "Skila einhverju atriði úr listanum.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "afgangur af %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Skila afgangi deilingar með tölunum.", - "MATH_CONSTRAIN_TITLE": "þröngva %1 lægst %2 hæst %3", - "MATH_CONSTRAIN_TOOLTIP": "Þröngva tölu til að vera innan hinna tilgreindu marka (að báðum meðtöldum).", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "slembitala frá %1 til %2", - "MATH_RANDOM_INT_TOOLTIP": "Skila heiltölu sem valin er af handahófi og er innan tilgreindra marka, að báðum meðtöldum.", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "slembibrot", - "MATH_RANDOM_FLOAT_TOOLTIP": "Skila broti sem er valið af handahófi úr tölum á bilinu frá og með 0.0 til (en ekki með) 1.0.", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "Stafur, orð eða textalína.", - "TEXT_JOIN_HELPURL": "https://github.com/google/blockly/wiki/Text#text-creation", - "TEXT_JOIN_TITLE_CREATEWITH": "búa til texta með", - "TEXT_JOIN_TOOLTIP": "Búa til texta með því að tengja saman einhvern fjölda atriða.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "tengja", - "TEXT_CREATE_JOIN_TOOLTIP": "Bæta við, fjarlægja eða umraða hlutum til að breyta skipan þessa textakubbs.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Bæta atriði við textann.", - "TEXT_APPEND_HELPURL": "https://github.com/google/blockly/wiki/Text#text-modification", - "TEXT_APPEND_TO": "við", - "TEXT_APPEND_APPENDTEXT": "bæta texta", - "TEXT_APPEND_TOOLTIP": "Bæta texta við breytuna '%1'.", - "TEXT_LENGTH_HELPURL": "https://github.com/google/blockly/wiki/Text#text-modification", - "TEXT_LENGTH_TITLE": "lengd %1", - "TEXT_LENGTH_TOOLTIP": "Skilar fjölda stafa (með bilum) í gefna textanum.", - "TEXT_ISEMPTY_HELPURL": "https://github.com/google/blockly/wiki/Text#checking-for-empty-text", - "TEXT_ISEMPTY_TITLE": "%1 er tómur", - "TEXT_ISEMPTY_TOOLTIP": "Skilar sönnu ef gefni textinn er tómur.", - "TEXT_INDEXOF_HELPURL": "https://github.com/google/blockly/wiki/Text#finding-text", - "TEXT_INDEXOF_TOOLTIP": "Finnur fyrsta/síðasta tilfelli fyrri textans í seinni textanum og skilar sæti hans. Skilar %1 ef textinn finnst ekki.", - "TEXT_INDEXOF_INPUT_INTEXT": "í texta", - "TEXT_INDEXOF_OPERATOR_FIRST": "finna fyrsta tilfelli texta", - "TEXT_INDEXOF_OPERATOR_LAST": "finna síðasta tilfelli texta", - "TEXT_CHARAT_HELPURL": "https://github.com/google/blockly/wiki/Text#extracting-text", - "TEXT_CHARAT_INPUT_INTEXT": "í texta", - "TEXT_CHARAT_FROM_START": "sækja staf #", - "TEXT_CHARAT_FROM_END": "sækja staf # frá enda", - "TEXT_CHARAT_FIRST": "sækja fyrsta staf", - "TEXT_CHARAT_LAST": "sækja síðasta staf", - "TEXT_CHARAT_RANDOM": "sækja einhvern staf", - "TEXT_CHARAT_TOOLTIP": "Skila staf á tilteknum stað.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Skilar tilteknum hluta textans.", - "TEXT_GET_SUBSTRING_HELPURL": "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "í texta", - "TEXT_GET_SUBSTRING_START_FROM_START": "sækja textabút frá staf #", - "TEXT_GET_SUBSTRING_START_FROM_END": "sækja textabút frá staf # frá enda", - "TEXT_GET_SUBSTRING_START_FIRST": "sækja textabút frá fyrsta staf", - "TEXT_GET_SUBSTRING_END_FROM_START": "að staf #", - "TEXT_GET_SUBSTRING_END_FROM_END": "að staf # frá enda", - "TEXT_GET_SUBSTRING_END_LAST": "að síðasta staf", - "TEXT_CHANGECASE_HELPURL": "https://github.com/google/blockly/wiki/Text#adjusting-text-case", - "TEXT_CHANGECASE_TOOLTIP": "Skila afriti af textanum með annarri stafastöðu.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "í HÁSTAFI", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "í lágstafi", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "í Upphafstafi", - "TEXT_TRIM_HELPURL": "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces", - "TEXT_TRIM_TOOLTIP": "Skila afriti af textanum þar sem möguleg bil við báða enda hafa verið fjarlægð.", - "TEXT_TRIM_OPERATOR_BOTH": "eyða bilum báðum megin við", - "TEXT_TRIM_OPERATOR_LEFT": "eyða bilum vinstra megin við", - "TEXT_TRIM_OPERATOR_RIGHT": "eyða bilum hægra megin við", - "TEXT_PRINT_HELPURL": "https://github.com/google/blockly/wiki/Text#printing-text", - "TEXT_PRINT_TITLE": "prenta %1", - "TEXT_PRINT_TOOLTIP": "Prenta tiltekinn texta, tölu eða annað gildi.", - "TEXT_PROMPT_HELPURL": "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user", - "TEXT_PROMPT_TYPE_TEXT": "biðja um texta með skilaboðum", - "TEXT_PROMPT_TYPE_NUMBER": "biðja um tölu með skilaboðum", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Biðja notandann um tölu.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Biðja notandann um texta.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "búa til tóman lista", - "LISTS_CREATE_EMPTY_TOOLTIP": "Skilar lista með lengdina 0 án gagna", - "LISTS_CREATE_WITH_TOOLTIP": "Búa til lista með einhverjum fjölda atriða.", - "LISTS_CREATE_WITH_INPUT_WITH": "búa til lista með", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "listi", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Bæta við, fjarlægja eða umraða hlutum til að breyta skipan þessa listakubbs.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Bæta atriði við listann.", - "LISTS_REPEAT_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_REPEAT_TOOLTIP": "Býr til lista sem inniheldur tiltekna gildið endurtekið tiltekið oft.", - "LISTS_REPEAT_TITLE": "búa til lista með atriði %1 endurtekið %2 sinnum", - "LISTS_LENGTH_HELPURL": "https://github.com/google/blockly/wiki/Lists#length-of", - "LISTS_LENGTH_TITLE": "lengd %1", - "LISTS_LENGTH_TOOLTIP": "Skilar lengd lista.", - "LISTS_ISEMPTY_TITLE": "%1 er tómur", - "LISTS_ISEMPTY_TOOLTIP": "Skilar sönnu ef listinn er tómur.", - "LISTS_INLIST": "í lista", - "LISTS_INDEX_OF_HELPURL": "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list", - "LISTS_INDEX_OF_FIRST": "finna fyrsta tilfelli atriðis", - "LISTS_INDEX_OF_LAST": "finna síðasta tilfelli atriðis", - "LISTS_INDEX_OF_TOOLTIP": "Finnur hvar atriðið kemur fyrir fyrst/síðast í listanum og skilar sæti þess. Skilar %1 ef atriðið finnst ekki.", - "LISTS_GET_INDEX_GET": "sækja", - "LISTS_GET_INDEX_GET_REMOVE": "sækja og fjarlægja", - "LISTS_GET_INDEX_REMOVE": "fjarlægja", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# frá enda", - "LISTS_GET_INDEX_FIRST": "fyrsta", - "LISTS_GET_INDEX_LAST": "síðasta", - "LISTS_GET_INDEX_RANDOM": "eitthvert", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 er fyrsta atriðið.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 er síðasta atriðið.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Skilar atriðinu í hinum tiltekna stað í lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Skilar fyrsta atriði í lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Skilar síðasta atriði í lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Skilar einhverju atriði úr lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Fjarlægir og skilar atriðinu á hinum tiltekna stað í lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Fjarlægir og skilar fyrsta atriðinu í lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Fjarlægir og skilar síðasta atriðinu í lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Fjarlægir og skilar einhverju atriði úr lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Fjarlægir atriðið á hinum tiltekna stað í lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Fjarlægir fyrsta atriðið í lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Fjarlægir síðasta atriðið í lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Fjarlægir eitthvert atriði úr lista.", - "LISTS_SET_INDEX_HELPURL": "https://github.com/google/blockly/wiki/Lists#in-list--set", - "LISTS_SET_INDEX_SET": "setja í", - "LISTS_SET_INDEX_INSERT": "bæta við", - "LISTS_SET_INDEX_INPUT_TO": "sem", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Setur atriðið í tiltekna sætið í listanum.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Setur atriðið í fyrsta sæti lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Setur atriðið í síðasta sæti lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Setur atriðið í eitthvert sæti lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Bætir atriðinu í listann á tilteknum stað.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Bætir atriðinu fremst í listann.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Bætir atriðinu aftan við listann.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Bætir atriðinu einhversstaðar við listann.", - "LISTS_GET_SUBLIST_HELPURL": "https://github.com/google/blockly/wiki/Lists#getting-a-sublist", - "LISTS_GET_SUBLIST_START_FROM_START": "sækja undirlista frá #", - "LISTS_GET_SUBLIST_START_FROM_END": "sækja undirlista frá # frá enda", - "LISTS_GET_SUBLIST_START_FIRST": "sækja undirlista frá fyrsta", - "LISTS_GET_SUBLIST_END_FROM_START": "til #", - "LISTS_GET_SUBLIST_END_FROM_END": "til # frá enda", - "LISTS_GET_SUBLIST_END_LAST": "til síðasta", - "LISTS_GET_SUBLIST_TOOLTIP": "Býr til afrit af tilteknum hluta lista.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "raða %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Raða afriti lista.", - "LISTS_SORT_ORDER_ASCENDING": "hækkandi", - "LISTS_SORT_ORDER_DESCENDING": "lækkandi", - "LISTS_SORT_TYPE_NUMERIC": "í númeraröð", - "LISTS_SORT_TYPE_TEXT": "í stafrófsröð", - "LISTS_SORT_TYPE_IGNORECASE": "í stafrófsröð án tillits til stafstöðu", - "LISTS_SPLIT_LIST_FROM_TEXT": "gera lista úr texta", - "LISTS_SPLIT_TEXT_FROM_LIST": "gera texta úr lista", - "LISTS_SPLIT_WITH_DELIMITER": "með skiltákni", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Skiptir texta í lista af textum, með skil við hvert skiltákn.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Sameinar lista af textum í einn texta, með skiltákn á milli.", - "VARIABLES_GET_HELPURL": "https://github.com/google/blockly/wiki/Variables#get", - "VARIABLES_GET_TOOLTIP": "Skilar gildi þessarar breytu.", - "VARIABLES_GET_CREATE_SET": "Búa til 'stilla %1'", - "VARIABLES_SET_HELPURL": "https://github.com/google/blockly/wiki/Variables#set", - "VARIABLES_SET": "stilla %1 á %2", - "VARIABLES_SET_TOOLTIP": "Stillir þessa breytu á innihald inntaksins.", - "VARIABLES_SET_CREATE_GET": "Búa til 'sækja %1'", - "PROCEDURES_DEFNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFNORETURN_TITLE": "til að", - "PROCEDURES_DEFNORETURN_PROCEDURE": "gera eitthvað", - "PROCEDURES_BEFORE_PARAMS": "með:", - "PROCEDURES_CALL_BEFORE_PARAMS": "með:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Býr til fall sem skilar engu.", - "PROCEDURES_DEFNORETURN_COMMENT": "Lýstu þessari aðgerð/falli...", - "PROCEDURES_DEFRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFRETURN_RETURN": "skila", - "PROCEDURES_DEFRETURN_TOOLTIP": "Býr til fall sem skilar úttaki.", - "PROCEDURES_ALLOW_STATEMENTS": "leyfa setningar", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Aðvörun: Þetta fall er með tvítekna stika.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Keyra heimatilbúna fallið '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Keyra heimatilbúna fallið '%1' og nota úttak þess.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "inntök", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Bæta við, fjarlægja eða umraða inntökum fyrir þetta fall.", - "PROCEDURES_MUTATORARG_TITLE": "heiti inntaks:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Bæta inntaki við fallið.", - "PROCEDURES_HIGHLIGHT_DEF": "Sýna skilgreiningu falls", - "PROCEDURES_CREATE_DO": "Búa til '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Ef gildi er satt, skal skila öðru gildi.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Aðvörun: Þennan kubb má aðeins nota í skilgreiningu falls." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/it.json b/backend/_pv_1_3_5/static/blockly/msg/json/it.json deleted file mode 100755 index 5991e26b8..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/it.json +++ /dev/null @@ -1,317 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Beta16", - "Espertus", - "Nerimic", - "Gbonanome", - "Gianfranco", - "Federico Mugnaini", - "JackLantern" - ] - }, - "VARIABLES_DEFAULT_NAME": "elemento", - "TODAY": "Oggi", - "DUPLICATE_BLOCK": "Duplica", - "ADD_COMMENT": "Aggiungi commento", - "REMOVE_COMMENT": "Rimuovi commento", - "EXTERNAL_INPUTS": "Ingressi esterni", - "INLINE_INPUTS": "Ingressi in linea", - "DELETE_BLOCK": "Cancella blocco", - "DELETE_X_BLOCKS": "Cancella %1 blocchi", - "DELETE_ALL_BLOCKS": "Cancellare tutti i %1 blocchi?", - "CLEAN_UP": "Pulisci i blocchi", - "COLLAPSE_BLOCK": "Comprimi blocco", - "COLLAPSE_ALL": "Comprimi blocchi", - "EXPAND_BLOCK": "Espandi blocco", - "EXPAND_ALL": "Espandi blocchi", - "DISABLE_BLOCK": "Disattiva blocco", - "ENABLE_BLOCK": "Attiva blocco", - "HELP": "Aiuto", - "UNDO": "Annulla", - "REDO": "Ripeti", - "CHANGE_VALUE_TITLE": "Modifica valore:", - "RENAME_VARIABLE": "Rinomina variabile...", - "RENAME_VARIABLE_TITLE": "Rinomina tutte le variabili '%1' in:", - "NEW_VARIABLE": "Crea variabile...", - "NEW_VARIABLE_TITLE": "Nome della nuova variabile:", - "VARIABLE_ALREADY_EXISTS": "Una variabile denominata '%1' esiste già.", - "DELETE_VARIABLE_CONFIRMATION": "Cancella %1 usi della variabile '%2'?", - "DELETE_VARIABLE": "Cancella la variabile '%1'", - "COLOUR_PICKER_HELPURL": "https://it.wikipedia.org/wiki/Colore", - "COLOUR_PICKER_TOOLTIP": "Scegli un colore dalla tavolozza.", - "COLOUR_RANDOM_TITLE": "colore casuale", - "COLOUR_RANDOM_TOOLTIP": "Scegli un colore a caso.", - "COLOUR_RGB_TITLE": "colora con", - "COLOUR_RGB_RED": "rosso", - "COLOUR_RGB_GREEN": "verde", - "COLOUR_RGB_BLUE": "blu", - "COLOUR_RGB_TOOLTIP": "Crea un colore con la quantità specificata di rosso, verde e blu. Tutti i valori devono essere compresi tra 0 e 100.", - "COLOUR_BLEND_TITLE": "miscela", - "COLOUR_BLEND_COLOUR1": "colore 1", - "COLOUR_BLEND_COLOUR2": "colore 2", - "COLOUR_BLEND_RATIO": "rapporto", - "COLOUR_BLEND_TOOLTIP": "Mescola due colori insieme con un determinato rapporto (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://it.wikipedia.org/wiki/Ciclo_for", - "CONTROLS_REPEAT_TITLE": "ripeti %1 volte", - "CONTROLS_REPEAT_INPUT_DO": "fai", - "CONTROLS_REPEAT_TOOLTIP": "Esegue alcune istruzione diverse volte.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "ripeti mentre", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "ripeti fino a che", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Finché un valore è vero, esegue alcune istruzioni.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Finché un valore è falso, esegue alcune istruzioni.", - "CONTROLS_FOR_TOOLTIP": "Fa sì che la variabile '%1' prenda tutti i valori a partire dal numero di partenza fino a quello di arrivo, con passo pari all'intervallo specificato, ed esegue il blocco indicato.", - "CONTROLS_FOR_TITLE": "conta con %1 da %2 a %3 per %4", - "CONTROLS_FOREACH_TITLE": "per ogni elemento %1 nella lista %2", - "CONTROLS_FOREACH_TOOLTIP": "Per ogni elemento in una lista, imposta la variabile '%1' pari all'elemento e quindi esegue alcune istruzioni.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "esce dal ciclo", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "prosegui con la successiva iterazione del ciclo", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Esce dal ciclo.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Salta il resto di questo ciclo e prosegue con la successiva iterazione.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Attenzioneː Questo blocco può essere usato solo in un ciclo.", - "CONTROLS_IF_TOOLTIP_1": "Se un valore è vero allora esegue alcune istruzioni.", - "CONTROLS_IF_TOOLTIP_2": "Se un valore è vero allora esegue il primo blocco di istruzioni. Altrimenti esegue il secondo blocco di istruzioni.", - "CONTROLS_IF_TOOLTIP_3": "Se il primo valore è vero allora esegue un primo blocco di istruzioni. Altrimenti, se il secondo valore è vero, esegue un secondo blocco di istruzioni.", - "CONTROLS_IF_TOOLTIP_4": "Se il primo valore è vero allora esegue un primo blocco di istruzioni. Altrimenti, se il secondo valore è vero, esegue un secondo blocco di istruzioni. Se nessuno dei valori è vero esegue l'ultimo blocco di istruzioni.", - "CONTROLS_IF_MSG_IF": "se", - "CONTROLS_IF_MSG_ELSEIF": "altrimenti se", - "CONTROLS_IF_MSG_ELSE": "altrimenti", - "CONTROLS_IF_IF_TOOLTIP": "Aggiungi, elimina o riordina le sezioni per riconfigurare questo blocco se.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Aggiungi una condizione al blocco se.", - "CONTROLS_IF_ELSE_TOOLTIP": "Aggiungi una condizione finale pigliatutto al blocco se.", - "LOGIC_COMPARE_HELPURL": "https://it.wikipedia.org/wiki/Disuguaglianza", - "LOGIC_COMPARE_TOOLTIP_EQ": "Restituisce vero se gli input sono uno uguale all'altro.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Restituisce vero se gli input non sono uno uguale all'altro.", - "LOGIC_COMPARE_TOOLTIP_LT": "Restituisce vero se il primo input è minore del secondo.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Restituisce vero se il primo input è minore o uguale al secondo.", - "LOGIC_COMPARE_TOOLTIP_GT": "Restituisce vero se il primo input è maggiore o uguale al secondo.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Restituisce uguale se il primo input è maggiore o uguale al secondo input.", - "LOGIC_OPERATION_TOOLTIP_AND": "Restituisce vero se entrambi gli input sono veri.", - "LOGIC_OPERATION_AND": "e", - "LOGIC_OPERATION_TOOLTIP_OR": "Restituisce vero se almeno uno degli input è vero.", - "LOGIC_OPERATION_OR": "o", - "LOGIC_NEGATE_TITLE": "non %1", - "LOGIC_NEGATE_TOOLTIP": "Restituisce vero se l'input è falso. Restituisce falso se l'input è vero.", - "LOGIC_BOOLEAN_TRUE": "vero", - "LOGIC_BOOLEAN_FALSE": "falso", - "LOGIC_BOOLEAN_TOOLTIP": "Restituisce vero o falso.", - "LOGIC_NULL": "nullo", - "LOGIC_NULL_TOOLTIP": "Restituisce valore nullo.", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "se vero", - "LOGIC_TERNARY_IF_FALSE": "se falso", - "LOGIC_TERNARY_TOOLTIP": "Verifica la condizione in 'test'. Se questa è vera restituisce il valore 'se vero' altrimenti restituisce il valore 'se falso'.", - "MATH_NUMBER_HELPURL": "https://it.wikipedia.org/wiki/Numero", - "MATH_NUMBER_TOOLTIP": "Un numero.", - "MATH_ARITHMETIC_HELPURL": "https://it.wikipedia.org/wiki/Aritmetica", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Restituisce la somma dei due numeri.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Restituisce la differenza dei due numeri.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Restituisce il prodotto dei due numeri.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Restituisce il quoziente dei due numeri.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Restituisce il primo numero elevato alla potenza del secondo numero.", - "MATH_SINGLE_HELPURL": "https://it.wikipedia.org/wiki/Radice_quadrata", - "MATH_SINGLE_OP_ROOT": "radice quadrata", - "MATH_SINGLE_TOOLTIP_ROOT": "Restituisce la radice quadrata del numero.", - "MATH_SINGLE_OP_ABSOLUTE": "assoluto", - "MATH_SINGLE_TOOLTIP_ABS": "Restituisce il valore assoluto del numero.", - "MATH_SINGLE_TOOLTIP_NEG": "Restituisce l'opposto del numero.", - "MATH_SINGLE_TOOLTIP_LN": "Restituisce il logaritmo naturale del numero.", - "MATH_SINGLE_TOOLTIP_LOG10": "Restituisce il logaritmo in base 10 del numero.", - "MATH_SINGLE_TOOLTIP_EXP": "Restituisce e elevato alla potenza del numero.", - "MATH_SINGLE_TOOLTIP_POW10": "Restituisce 10 elevato alla potenza del numero.", - "MATH_TRIG_HELPURL": "https://it.wikipedia.org/wiki/Funzione_trigonometrica", - "MATH_TRIG_TOOLTIP_SIN": "Restituisce il seno di un angolo espresso in gradi (non radianti).", - "MATH_TRIG_TOOLTIP_COS": "Restituisce il coseno di un angolo espresso in gradi (non radianti).", - "MATH_TRIG_TOOLTIP_TAN": "Restituisce la tangente di un angolo espresso in gradi (non radianti).", - "MATH_TRIG_TOOLTIP_ASIN": "Restituisce l'arco-seno di un numero.", - "MATH_TRIG_TOOLTIP_ACOS": "Restituisce l'arco-coseno di un numero.", - "MATH_TRIG_TOOLTIP_ATAN": "Restituisce l'arco-tangente di un numero.", - "MATH_CONSTANT_HELPURL": "https://it.wikipedia.org/wiki/Costante_matematica", - "MATH_CONSTANT_TOOLTIP": "Restituisce una delle costanti comuniː π (3.141…), e (2.718…), φ (1.618…), radq(2) (1.414…), radq(½) (0.707…) o ∞ (infinito).", - "MATH_IS_EVEN": "è pari", - "MATH_IS_ODD": "è dispari", - "MATH_IS_PRIME": "è primo", - "MATH_IS_WHOLE": "è intero", - "MATH_IS_POSITIVE": "è positivo", - "MATH_IS_NEGATIVE": "è negativo", - "MATH_IS_DIVISIBLE_BY": "è divisibile per", - "MATH_IS_TOOLTIP": "Verifica se un numero è pari, dispari, primo, intero, positivo, negativo o se è divisibile per un certo numero. Restituisce vero o falso.", - "MATH_CHANGE_HELPURL": "https://it.wikipedia.org/wiki/Addizione", - "MATH_CHANGE_TITLE": "cambia %1 di %2", - "MATH_CHANGE_TOOLTIP": "Aggiunge un numero alla variabile '%1'.", - "MATH_ROUND_HELPURL": "https://it.wikipedia.org/wiki/Arrotondamento", - "MATH_ROUND_TOOLTIP": "Arrotonda un numero verso l'alto o verso il basso.", - "MATH_ROUND_OPERATOR_ROUND": "arrotonda", - "MATH_ROUND_OPERATOR_ROUNDUP": "arrotonda verso l'alto", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "arrotonda verso il basso", - "MATH_ONLIST_OPERATOR_SUM": "somma la lista", - "MATH_ONLIST_TOOLTIP_SUM": "Restituisce la somma si tutti i numeri nella lista.", - "MATH_ONLIST_OPERATOR_MIN": "minimo della lista", - "MATH_ONLIST_TOOLTIP_MIN": "Restituisce il più piccolo numero della lista.", - "MATH_ONLIST_OPERATOR_MAX": "massimo della lista", - "MATH_ONLIST_TOOLTIP_MAX": "Restituisce il più grande numero della lista.", - "MATH_ONLIST_OPERATOR_AVERAGE": "media della lista", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Restituisce la media (media aritmetica) dei valori numerici nella lista.", - "MATH_ONLIST_OPERATOR_MEDIAN": "mediana della lista", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Restituisce il valore mediano della lista.", - "MATH_ONLIST_OPERATOR_MODE": "mode della lista", - "MATH_ONLIST_TOOLTIP_MODE": "Restituisce una lista degli elementi più frequenti nella lista.", - "MATH_ONLIST_OPERATOR_STD_DEV": "deviazione standard della lista", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Restituisce la deviazione standard della lista.", - "MATH_ONLIST_OPERATOR_RANDOM": "elemento casuale della lista", - "MATH_ONLIST_TOOLTIP_RANDOM": "Restituisce un elemento casuale della lista.", - "MATH_MODULO_HELPURL": "https://it.wikipedia.org/wiki/Resto", - "MATH_MODULO_TITLE": "resto di %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Restituisce il resto della divisione di due numeri.", - "MATH_CONSTRAIN_TITLE": "costringi %1 da %2 a %3", - "MATH_CONSTRAIN_TOOLTIP": "Costringe un numero all'interno dei limiti indicati (compresi).", - "MATH_RANDOM_INT_HELPURL": "https://it.wikipedia.org/wiki/Numeri_pseudo-casuali", - "MATH_RANDOM_INT_TITLE": "intero casuale da %1 a %2", - "MATH_RANDOM_INT_TOOLTIP": "Restituisce un numero intero casuale compreso tra i due limiti indicati (inclusi).", - "MATH_RANDOM_FLOAT_HELPURL": "https://it.wikipedia.org/wiki/Numeri_pseudo-casuali", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "frazione casuale", - "MATH_RANDOM_FLOAT_TOOLTIP": "Restituisce una frazione compresa fra 0.0 (incluso) e 1.0 (escluso).", - "TEXT_TEXT_HELPURL": "https://it.wikipedia.org/wiki/Stringa_(informatica)", - "TEXT_TEXT_TOOLTIP": "Una lettera, una parola o una linea di testo.", - "TEXT_JOIN_TITLE_CREATEWITH": "crea testo con", - "TEXT_JOIN_TOOLTIP": "Crea un blocco di testo unendo un certo numero di elementi.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "unisci", - "TEXT_CREATE_JOIN_TOOLTIP": "Aggiungi, rimuovi o riordina le sezioni per riconfigurare questo blocco testo.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Aggiungi un elemento al testo.", - "TEXT_APPEND_TO": "a", - "TEXT_APPEND_APPENDTEXT": "aggiungi il testo", - "TEXT_APPEND_TOOLTIP": "Aggiunge del testo alla variabile '%1'.", - "TEXT_LENGTH_TITLE": "lunghezza di %1", - "TEXT_LENGTH_TOOLTIP": "Restituisce il numero di lettere (inclusi gli spazi) nel testo fornito.", - "TEXT_ISEMPTY_TITLE": "%1 è vuoto", - "TEXT_ISEMPTY_TOOLTIP": "Restituisce vero se il testo fornito è vuoto.", - "TEXT_INDEXOF_TOOLTIP": "Restituisce l'indice della prima occorrenza del primo testo all'interno del secondo testo. Restituisce %1 se il testo non viene trovato.", - "TEXT_INDEXOF_INPUT_INTEXT": "nel testo", - "TEXT_INDEXOF_OPERATOR_FIRST": "trova la prima occorrenza del testo", - "TEXT_INDEXOF_OPERATOR_LAST": "trova l'ultima occorrenza del testo", - "TEXT_CHARAT_INPUT_INTEXT": "nel testo", - "TEXT_CHARAT_FROM_START": "prendi la lettera #", - "TEXT_CHARAT_FROM_END": "prendi la lettera # dalla fine", - "TEXT_CHARAT_FIRST": "prendi la prima lettera", - "TEXT_CHARAT_LAST": "prendi l'ultima lettera", - "TEXT_CHARAT_RANDOM": "prendi lettera casuale", - "TEXT_CHARAT_TOOLTIP": "Restituisce la lettera nella posizione indicata.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Restituisce la porzione di testo indicata.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "nel testo", - "TEXT_GET_SUBSTRING_START_FROM_START": "prendi sotto-stringa dalla lettera #", - "TEXT_GET_SUBSTRING_START_FROM_END": "prendi sotto-stringa dalla lettera # dalla fine", - "TEXT_GET_SUBSTRING_START_FIRST": "prendi sotto-stringa dalla prima lettera", - "TEXT_GET_SUBSTRING_END_FROM_START": "alla lettera #", - "TEXT_GET_SUBSTRING_END_FROM_END": "alla lettera # dalla fine", - "TEXT_GET_SUBSTRING_END_LAST": "all'ultima lettera", - "TEXT_CHANGECASE_TOOLTIP": "Restituisce una copia del testo in un diverso formato maiuscole/minuscole.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "in MAIUSCOLO", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "in minuscolo", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "con Iniziali Maiuscole", - "TEXT_TRIM_TOOLTIP": "Restituisce una copia del testo con gli spazi rimossi ad uno o entrambe le estremità.", - "TEXT_TRIM_OPERATOR_BOTH": "rimuovi spazi da entrambi gli estremi", - "TEXT_TRIM_OPERATOR_LEFT": "rimuovi spazi a sinistra", - "TEXT_TRIM_OPERATOR_RIGHT": "rimuovi spazi a destra", - "TEXT_PRINT_TITLE": "scrivi %1", - "TEXT_PRINT_TOOLTIP": "Scrive il testo, numero o altro valore indicato.", - "TEXT_PROMPT_TYPE_TEXT": "richiedi testo con messaggio", - "TEXT_PROMPT_TYPE_NUMBER": "richiedi numero con messaggio", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Richiedi un numero all'utente.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Richiede del testo da parte dell'utente.", - "LISTS_CREATE_EMPTY_TITLE": "crea lista vuota", - "LISTS_CREATE_EMPTY_TOOLTIP": "Restituisce una lista, di lunghezza 0, contenente nessun record di dati", - "LISTS_CREATE_WITH_TOOLTIP": "Crea una lista con un certo numero di elementi.", - "LISTS_CREATE_WITH_INPUT_WITH": "crea lista con", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "lista", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Aggiungi, rimuovi o riordina le sezioni per riconfigurare il blocco lista.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Aggiunge un elemento alla lista.", - "LISTS_REPEAT_TOOLTIP": "Crea una lista costituita dal valore indicato ripetuto per il numero di volte specificato.", - "LISTS_REPEAT_TITLE": "crea una lista con l'elemento %1 ripetuto %2 volte", - "LISTS_LENGTH_TITLE": "lunghezza di %1", - "LISTS_LENGTH_TOOLTIP": "Restituisce la lunghezza della lista", - "LISTS_ISEMPTY_TITLE": "%1 è vuota", - "LISTS_ISEMPTY_TOOLTIP": "Restituisce vero se la lista è vuota.", - "LISTS_INLIST": "nella lista", - "LISTS_INDEX_OF_FIRST": "trova la prima occorrenza dell'elemento", - "LISTS_INDEX_OF_LAST": "trova l'ultima occorrenza dell'elemento", - "LISTS_INDEX_OF_TOOLTIP": "Restituisce l'indice della prima/ultima occorrenza dell'elemento nella lista. Restituisce %1 se l'elemento non viene trovato.", - "LISTS_GET_INDEX_GET": "prendi", - "LISTS_GET_INDEX_GET_REMOVE": "prendi e rimuovi", - "LISTS_GET_INDEX_REMOVE": "rimuovi", - "LISTS_GET_INDEX_FROM_END": "# dalla fine", - "LISTS_GET_INDEX_FIRST": "primo", - "LISTS_GET_INDEX_LAST": "ultimo", - "LISTS_GET_INDEX_RANDOM": "casuale", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 corrisponde al primo elemento.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 corrisponde all'ultimo elemento.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Restituisce l'elemento nella posizione indicata della lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Restituisce il primo elemento in una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Restituisce l'ultimo elemento in una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Restituisce un elemento casuale in una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Rimuove e restituisce l'elemento nella posizione indicata in una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Rimuove e restituisce il primo elemento in una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Restituisce e rimuove l'ultimo elemento in una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Restituisce e rimuove un elemento casuale in una lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Rimuove l'elemento nella posizione indicata in una lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Rimuove il primo elemento in una lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Rimuove l'ultimo elemento in una lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Rimuove un elemento casuale in una lista.", - "LISTS_SET_INDEX_SET": "imposta", - "LISTS_SET_INDEX_INSERT": "inserisci in", - "LISTS_SET_INDEX_INPUT_TO": "come", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Imposta l'elemento nella posizione indicata di una lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Imposta il primo elemento in una lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Imposta l'ultimo elemento in una lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Imposta un elemento casuale in una lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Inserisci un elemento nella posizione indicata in una lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Inserisci l'elemento all'inizio della lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Aggiungi un elemento alla fine di una lista", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Inserisce l'elemento casualmente in una lista.", - "LISTS_GET_SUBLIST_START_FROM_START": "prendi sotto-lista da #", - "LISTS_GET_SUBLIST_START_FROM_END": "prendi sotto-lista da # dalla fine", - "LISTS_GET_SUBLIST_START_FIRST": "prendi sotto-lista dall'inizio", - "LISTS_GET_SUBLIST_END_FROM_START": "fino a #", - "LISTS_GET_SUBLIST_END_FROM_END": "da # dalla fine", - "LISTS_GET_SUBLIST_END_LAST": "dagli ultimi", - "LISTS_GET_SUBLIST_TOOLTIP": "Crea una copia della porzione specificata di una lista.", - "LISTS_SORT_TITLE": "ordinamento %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Ordina una copia di un elenco.", - "LISTS_SORT_ORDER_ASCENDING": "crescente", - "LISTS_SORT_ORDER_DESCENDING": "decrescente", - "LISTS_SORT_TYPE_NUMERIC": "numerico", - "LISTS_SORT_TYPE_TEXT": "alfabetico", - "LISTS_SORT_TYPE_IGNORECASE": "alfabetico, ignorare differenze maiuscole e minuscole", - "LISTS_SPLIT_LIST_FROM_TEXT": "crea lista da testo", - "LISTS_SPLIT_TEXT_FROM_LIST": "crea testo da lista", - "LISTS_SPLIT_WITH_DELIMITER": "con delimitatore", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Dividi il testo in un elenco di testi, interrompendo ad ogni delimitatore.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Unisci una lista di testi in un unico testo, separato da un delimitatore.", - "VARIABLES_GET_TOOLTIP": "Restituisce il valore di una variabile.", - "VARIABLES_GET_CREATE_SET": "Crea 'imposta %1'", - "VARIABLES_SET": "imposta %1 a %2", - "VARIABLES_SET_TOOLTIP": "Imposta questa variabile ad essere pari all'input.", - "VARIABLES_SET_CREATE_GET": "Crea 'prendi %1'", - "PROCEDURES_DEFNORETURN_TITLE": "per", - "PROCEDURES_DEFNORETURN_PROCEDURE": "fai qualcosa", - "PROCEDURES_BEFORE_PARAMS": "conː", - "PROCEDURES_CALL_BEFORE_PARAMS": "conː", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Crea una funzione senza output.", - "PROCEDURES_DEFNORETURN_COMMENT": "Descrivi questa funzione...", - "PROCEDURES_DEFRETURN_RETURN": "ritorna", - "PROCEDURES_DEFRETURN_TOOLTIP": "Crea una funzione con un output.", - "PROCEDURES_ALLOW_STATEMENTS": "consenti dichiarazioni", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Attenzioneː Questa funzione ha parametri duplicati.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://it.wikipedia.org/wiki/Funzione_(informatica)", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Esegue la funzione definita dall'utente '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "https://it.wikipedia.org/wiki/Funzione_(informatica)", - "PROCEDURES_CALLRETURN_TOOLTIP": "Esegue la funzione definita dall'utente '%1' ed usa il suo output.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "input", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Aggiungi, rimuovi o riordina input alla funzione.", - "PROCEDURES_MUTATORARG_TITLE": "nome inputː", - "PROCEDURES_MUTATORARG_TOOLTIP": "Aggiungi un input alla funzione.", - "PROCEDURES_HIGHLIGHT_DEF": "Evidenzia definizione di funzione", - "PROCEDURES_CREATE_DO": "Crea '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Se un valore è vero allora restituisce un secondo valore.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Attenzioneː Questo blocco può essere usato solo all'interno di una definizione di funzione." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/ja.json b/backend/_pv_1_3_5/static/blockly/msg/json/ja.json deleted file mode 100755 index 3e52b2b39..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/ja.json +++ /dev/null @@ -1,328 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Shirayuki", - "Oda", - "아라", - "Otokoume", - "Sujiniku", - "Sgk" - ] - }, - "VARIABLES_DEFAULT_NAME": "項目", - "TODAY": "今日", - "DUPLICATE_BLOCK": "複製", - "ADD_COMMENT": "コメントを追加", - "REMOVE_COMMENT": "コメントを削除", - "EXTERNAL_INPUTS": "外部入力", - "INLINE_INPUTS": "インライン入力", - "DELETE_BLOCK": "ブロックを消す", - "DELETE_X_BLOCKS": "%1 個のブロックを消す", - "DELETE_ALL_BLOCKS": "%1件のすべてのブロックを消しますか?", - "CLEAN_UP": "ブロックの整理", - "COLLAPSE_BLOCK": "ブロックを折りたたむ", - "COLLAPSE_ALL": "ブロックを折りたたむ", - "EXPAND_BLOCK": "ブロックを展開します。", - "EXPAND_ALL": "ブロックを展開します。", - "DISABLE_BLOCK": "ブロックを無効にします。", - "ENABLE_BLOCK": "ブロックを有効にします。", - "HELP": "ヘルプ", - "UNDO": "取り消し", - "REDO": "やり直し", - "CHANGE_VALUE_TITLE": "値を変更します。", - "RENAME_VARIABLE": "変数の名前を変更.", - "RENAME_VARIABLE_TITLE": "%1の変数すべてを名前変更します。", - "NEW_VARIABLE": "新しい変数", - "NEW_VARIABLE_TITLE": "新しい変数の、名前", - "COLOUR_PICKER_HELPURL": "https://ja.wikipedia.org/wiki/色", - "COLOUR_PICKER_TOOLTIP": "パレットから色を選んでください。", - "COLOUR_RANDOM_TITLE": "ランダムな色", - "COLOUR_RANDOM_TOOLTIP": "ランダムな色を選択します。", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "カラーと", - "COLOUR_RGB_RED": "赤", - "COLOUR_RGB_GREEN": "緑", - "COLOUR_RGB_BLUE": "青", - "COLOUR_RGB_TOOLTIP": "赤、緑、および青の指定された量で色を作成します。すべての値は 0 ~ 100 の間でなければなりません。", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "ブレンド", - "COLOUR_BLEND_COLOUR1": "色 1", - "COLOUR_BLEND_COLOUR2": "色 2", - "COLOUR_BLEND_RATIO": "割合", - "COLOUR_BLEND_TOOLTIP": "ブレンド2 つの色を指定された比率に混ぜる」 (0.0 ~ 1.0)。", - "CONTROLS_REPEAT_HELPURL": "https://ja.wikipedia.org/wiki/for文", - "CONTROLS_REPEAT_TITLE": "%1 回、繰り返します", - "CONTROLS_REPEAT_INPUT_DO": "してください", - "CONTROLS_REPEAT_TOOLTIP": "いくつかのステートメントを数回行います。", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "つつその間、繰り返す4", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "までを繰り返します", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "値は true のあいだ、いくつかのステートメントを行います。", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "値は false のあいだ、いくつかのステートメントを行います。", - "CONTROLS_FOR_TOOLTIP": "変数 \"%1\"は、指定した間隔ごとのカウントを開始番号から 終了番号まで、値をとり、指定したブロックを行う必要があります。", - "CONTROLS_FOR_TITLE": "で、カウントします。 %1 %2 から%3、 %4 で", - "CONTROLS_FOREACH_TITLE": "各項目の %1 リストで %2", - "CONTROLS_FOREACH_TOOLTIP": "リストの各項目に対して変数 '%1' のアイテムに設定し、いくつかのステートメントをしてください。", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "ループから抜け出す", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "ループの次の反復処理を続行します。", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "含むループから抜け出します。", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "このループの残りの部分をスキップし、次のイテレーションに進みます。", - "CONTROLS_FLOW_STATEMENTS_WARNING": "注意: このブロックは、ループ内でのみ使用します。", - "CONTROLS_IF_TOOLTIP_1": "値が true の場合はその後ステートメントを行をいくつかします。", - "CONTROLS_IF_TOOLTIP_2": "値が true 場合は、ステートメントの最初のブロックを行います。それ以外の場合は、ステートメントの 2 番目のブロックを行います。", - "CONTROLS_IF_TOOLTIP_3": "最初の値が true 場合は、ステートメントの最初のブロックを行います。それ以外の場合は、2 番目の値が true の場合、ステートメントの 2 番目のブロックをします。", - "CONTROLS_IF_TOOLTIP_4": "最初の値が true 場合は、ステートメントの最初のブロックを行います。2 番目の値が true の場合は、ステートメントの 2 番目のブロックを行います。それ以外の場合は最後のブロックのステートメントを行います。", - "CONTROLS_IF_MSG_IF": "もし", - "CONTROLS_IF_MSG_ELSEIF": "他でもし", - "CONTROLS_IF_MSG_ELSE": "他", - "CONTROLS_IF_IF_TOOLTIP": "追加、削除、またはセクションを順序変更して、ブロックをこれを再構成します。", - "CONTROLS_IF_ELSEIF_TOOLTIP": "場合に条件にブロック追加。", - "CONTROLS_IF_ELSE_TOOLTIP": "Ifブロックに、すべてをキャッチする条件を追加。", - "LOGIC_COMPARE_HELPURL": "https://ja.wikipedia.org/wiki/不等式", - "LOGIC_COMPARE_TOOLTIP_EQ": "もし両方がお互いに等しく入力した場合は true を返します。", - "LOGIC_COMPARE_TOOLTIP_NEQ": "両方の入力が互いに等しくない場合に true を返します。", - "LOGIC_COMPARE_TOOLTIP_LT": "最初の入力が 2 番目の入力よりも小さいい場合は true を返します。", - "LOGIC_COMPARE_TOOLTIP_LTE": "もし、最初の入力が二つ目入力より少ないか、おなじであったらTRUEをかえしてください", - "LOGIC_COMPARE_TOOLTIP_GT": "最初の入力が 2 番目の入力よりも大きい場合は true を返します。", - "LOGIC_COMPARE_TOOLTIP_GTE": "もし入力がふたつめの入よりも大きかったらtrueをり返します。", - "LOGIC_OPERATION_TOOLTIP_AND": "両方の入力がおんなじ場わいわtrue を返します。", - "LOGIC_OPERATION_AND": "そして", - "LOGIC_OPERATION_TOOLTIP_OR": "最低少なくとも 1 つの入力が true の場合は true を返します。", - "LOGIC_OPERATION_OR": "または", - "LOGIC_NEGATE_HELPURL": "https://ja.wikipedia.org/wiki/否定", - "LOGIC_NEGATE_TITLE": "%1 ではないです。", - "LOGIC_NEGATE_TOOLTIP": "入力が false の場合は、true を返します。入力が true の場合は false を返します。", - "LOGIC_BOOLEAN_TRUE": "true", - "LOGIC_BOOLEAN_FALSE": "false", - "LOGIC_BOOLEAN_TOOLTIP": "True または false を返します。", - "LOGIC_NULL_HELPURL": "https://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "null", - "LOGIC_NULL_TOOLTIP": "Null を返します。", - "LOGIC_TERNARY_HELPURL": "https://ja.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "テスト", - "LOGIC_TERNARY_IF_TRUE": "true の場合", - "LOGIC_TERNARY_IF_FALSE": "false の場合", - "LOGIC_TERNARY_TOOLTIP": "'テスト' の条件をチェックします。条件が true の場合、'true' の値を返します。それ以外の場合 'false' のを返します。", - "MATH_NUMBER_HELPURL": "https://ja.wikipedia.org/wiki/数", - "MATH_NUMBER_TOOLTIP": "数です。", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tan", - "MATH_TRIG_ASIN": "asin", - "MATH_TRIG_ACOS": "acos", - "MATH_TRIG_ATAN": "atan", - "MATH_ARITHMETIC_HELPURL": "https://ja.wikipedia.org/wiki/算術", - "MATH_ARITHMETIC_TOOLTIP_ADD": "2 つの数の合計を返します。", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "2 つの数の差を返します。", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "2 つの数の積を返します。", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "2 つの数の商を返します。", - "MATH_ARITHMETIC_TOOLTIP_POWER": "最初の数を2 番目の値で累乗した結果を返します。", - "MATH_SINGLE_HELPURL": "https://ja.wikipedia.org/wiki/平方根", - "MATH_SINGLE_OP_ROOT": "平方根", - "MATH_SINGLE_TOOLTIP_ROOT": "平方根を返す", - "MATH_SINGLE_OP_ABSOLUTE": "絶対値", - "MATH_SINGLE_TOOLTIP_ABS": "絶対値を返す", - "MATH_SINGLE_TOOLTIP_NEG": "負の数を返す", - "MATH_SINGLE_TOOLTIP_LN": "数値の自然対数をかえしてください", - "MATH_SINGLE_TOOLTIP_LOG10": "log 10 を返す。", - "MATH_SINGLE_TOOLTIP_EXP": "数値の e 粂を返す", - "MATH_SINGLE_TOOLTIP_POW10": "10の x 乗", - "MATH_TRIG_HELPURL": "https://ja.wikipedia.org/wiki/三角関数", - "MATH_TRIG_TOOLTIP_SIN": "番号のsineの次数を返す", - "MATH_TRIG_TOOLTIP_COS": "番号のcosineの次数を返す", - "MATH_TRIG_TOOLTIP_TAN": "番号のtangentの次数を返す", - "MATH_TRIG_TOOLTIP_ASIN": "番号のarcsine を返すます", - "MATH_TRIG_TOOLTIP_ACOS": "arccosine の値を返す", - "MATH_TRIG_TOOLTIP_ATAN": "番号のarctangent を返すます", - "MATH_CONSTANT_HELPURL": "https://ja.wikipedia.org/wiki/数学定数", - "MATH_CONSTANT_TOOLTIP": "いずれかの共通の定数のを返す: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (無限).", - "MATH_IS_EVEN": "わ偶数", - "MATH_IS_ODD": "奇数です。", - "MATH_IS_PRIME": "素数です", - "MATH_IS_WHOLE": "は整数", - "MATH_IS_POSITIVE": "正の値", - "MATH_IS_NEGATIVE": "負の値", - "MATH_IS_DIVISIBLE_BY": "割り切れる", - "MATH_IS_TOOLTIP": "数字が、偶数、奇数、素数、整数、正数、負数、またはそれが特定の数で割り切れる場合かどうかを確認してください。どの制限が一つでも本当でしたら true をかえしてください、そうでない場合わ falseを返してください。", - "MATH_CHANGE_HELPURL": "https://ja.wikipedia.org/wiki/加法", - "MATH_CHANGE_TITLE": "変更 %1 に %2", - "MATH_CHANGE_TOOLTIP": "'%1' をたします。", - "MATH_ROUND_HELPURL": "https://ja.wikipedia.org/wiki/端数処理", - "MATH_ROUND_TOOLTIP": "数値を切り上げるか切り捨てる", - "MATH_ROUND_OPERATOR_ROUND": "概数", - "MATH_ROUND_OPERATOR_ROUNDUP": "数値を切り上げ", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "端数を切り捨てる", - "MATH_ONLIST_HELPURL": "", - "MATH_ONLIST_OPERATOR_SUM": "リストの合計", - "MATH_ONLIST_TOOLTIP_SUM": "全部リストの数をたして返す", - "MATH_ONLIST_OPERATOR_MIN": "リストの最小の数", - "MATH_ONLIST_TOOLTIP_MIN": "リストの最小数を返します。", - "MATH_ONLIST_OPERATOR_MAX": "リストの最大値", - "MATH_ONLIST_TOOLTIP_MAX": "リストの最大数を返します。", - "MATH_ONLIST_OPERATOR_AVERAGE": "リストの平均", - "MATH_ONLIST_TOOLTIP_AVERAGE": "リストの数値の平均 (算術平均) を返します。", - "MATH_ONLIST_OPERATOR_MEDIAN": "リストの中央値", - "MATH_ONLIST_TOOLTIP_MEDIAN": "リストの中央値の数を返します。", - "MATH_ONLIST_OPERATOR_MODE": "一覧モード", - "MATH_ONLIST_TOOLTIP_MODE": "リストで最も一般的な項目のリストを返します。", - "MATH_ONLIST_OPERATOR_STD_DEV": "リストの標準偏差", - "MATH_ONLIST_TOOLTIP_STD_DEV": "リウトの標準偏差をかえす", - "MATH_ONLIST_OPERATOR_RANDOM": "リストのランダム アイテム", - "MATH_ONLIST_TOOLTIP_RANDOM": "リストからランダムに要素を返します。", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "残りの %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "2つの数値を除算した余りを返します。", - "MATH_CONSTRAIN_TITLE": "制限%1下リミット%2上限リミット%3", - "MATH_CONSTRAIN_TOOLTIP": "値を、上限 x と下限 y のあいだに制限んする(上限と下限が、x と y とに同じ場合わ、上限の値は x, 下限の値はy)。", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "%1 から %2 への無作為の整数", - "MATH_RANDOM_INT_TOOLTIP": "指定した下限の間、無作為なランダムな整数を返します。", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "ランダムな分数", - "MATH_RANDOM_FLOAT_TOOLTIP": "ランダムな分数を返すー0.0 (包括) の間のと 1.0 (排他的な)。", - "TEXT_TEXT_HELPURL": "https://ja.wikipedia.org/wiki/文字列", - "TEXT_TEXT_TOOLTIP": "文字、単語、または行のテキスト。", - "TEXT_JOIN_TITLE_CREATEWITH": "テキストを作成します。", - "TEXT_JOIN_TOOLTIP": "任意の数の項目一部を一緒に接合してテキストの作成します。", - "TEXT_CREATE_JOIN_TITLE_JOIN": "結合", - "TEXT_CREATE_JOIN_TOOLTIP": "追加、削除、またはセクションを順序変更して、ブロックを再構成します。", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "テキスト をアイテム追加します。", - "TEXT_APPEND_TO": "宛先", - "TEXT_APPEND_APPENDTEXT": "テキストを追加します。", - "TEXT_APPEND_TOOLTIP": "変数 '%1' にいくつかのテキストを追加します。", - "TEXT_LENGTH_TITLE": "%1 の長さ", - "TEXT_LENGTH_TOOLTIP": "指定されたテキストの文字 (スペースを含む) の数を返します。", - "TEXT_ISEMPTY_TITLE": "%1 が空", - "TEXT_ISEMPTY_TOOLTIP": "指定されたテキストが空の場合は、true を返します。", - "TEXT_INDEXOF_TOOLTIP": "最初のテキストの二番目のてきすとの、最初と最後の、出現したインデックスをかえします。テキストが見つからない場合は %1 を返します。", - "TEXT_INDEXOF_INPUT_INTEXT": "テキストで", - "TEXT_INDEXOF_OPERATOR_FIRST": "テキストの最初の出現箇所を検索します。", - "TEXT_INDEXOF_OPERATOR_LAST": "テキストの最後に見つかったを検索します。", - "TEXT_INDEXOF_TAIL": "", - "TEXT_CHARAT_INPUT_INTEXT": "テキストで", - "TEXT_CHARAT_FROM_START": "文字# を取得", - "TEXT_CHARAT_FROM_END": "一番最後の言葉、キャラクターを所得", - "TEXT_CHARAT_FIRST": "最初の文字を得る", - "TEXT_CHARAT_LAST": "最後の文字を得る", - "TEXT_CHARAT_RANDOM": "ランダムな文字を得る", - "TEXT_CHARAT_TAIL": "", - "TEXT_CHARAT_TOOLTIP": "指定された位置に文字を返します。", - "TEXT_GET_SUBSTRING_TOOLTIP": "テキストの指定部分を返します。", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "テキストで", - "TEXT_GET_SUBSTRING_START_FROM_START": "文字列からの部分文字列を取得 #", - "TEXT_GET_SUBSTRING_START_FROM_END": "部分文字列を取得する #端から得る", - "TEXT_GET_SUBSTRING_START_FIRST": "部分文字列を取得する。", - "TEXT_GET_SUBSTRING_END_FROM_START": "# の文字", - "TEXT_GET_SUBSTRING_END_FROM_END": "文字列の# 終わりからの#", - "TEXT_GET_SUBSTRING_END_LAST": "最後のの文字", - "TEXT_GET_SUBSTRING_TAIL": "", - "TEXT_CHANGECASE_TOOLTIP": "別のケースに、テキストのコピーを返します。", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "大文字に変換する", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "小文字に", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "タイトル ケースに", - "TEXT_TRIM_TOOLTIP": "スペースを 1 つまたは両方の端から削除したのち、テキストのコピーを返します。", - "TEXT_TRIM_OPERATOR_BOTH": "両端のスペースを取り除く", - "TEXT_TRIM_OPERATOR_LEFT": "左端のスペースを取り除く", - "TEXT_TRIM_OPERATOR_RIGHT": "右端のスペースを取り除く", - "TEXT_PRINT_TITLE": "%1 を印刷します。", - "TEXT_PRINT_TOOLTIP": "指定したテキスト、番号または他の値を印刷します。", - "TEXT_PROMPT_TYPE_TEXT": "メッセージをプロンプトしてにテキストを求める", - "TEXT_PROMPT_TYPE_NUMBER": "メッセージを送って番号の入力を求める", - "TEXT_PROMPT_TOOLTIP_NUMBER": "ユーザーにプロンプトして数字のインプットを求めます", - "TEXT_PROMPT_TOOLTIP_TEXT": "いくつかのテキストを、ユーザーに入力するようにプロンプト。", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "空のリストを作成します。", - "LISTS_CREATE_EMPTY_TOOLTIP": "長さゼロ、データ レコード空のリストを返します", - "LISTS_CREATE_WITH_TOOLTIP": "アイテム数かぎりないのリストを作成します。", - "LISTS_CREATE_WITH_INPUT_WITH": "これを使ってリストを作成します。", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "リスト", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "追加、削除、またはセクションを順序変更して、ブロックを再構成します。", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "リストにアイテムを追加します。", - "LISTS_REPEAT_TOOLTIP": "指定された値をなんどか繰り返してリストを作ります。", - "LISTS_REPEAT_TITLE": "アイテム %1 と一緒にリストを作成し %2 回繰り", - "LISTS_LENGTH_TITLE": " %1の長さ", - "LISTS_LENGTH_TOOLTIP": "リストの長さを返します。", - "LISTS_ISEMPTY_TITLE": "%1 が空", - "LISTS_ISEMPTY_TOOLTIP": "リストが空の場合は、true を返します。", - "LISTS_INLIST": "リストで", - "LISTS_INDEX_OF_FIRST": "最初に見つかった項目を検索します。", - "LISTS_INDEX_OF_LAST": "最後に見つかったアイテムを見つける", - "LISTS_INDEX_OF_TOOLTIP": "リスト項目の最初/最後に出現するインデックス位置を返します。項目が見つからない場合は %1 を返します。", - "LISTS_GET_INDEX_GET": "取得", - "LISTS_GET_INDEX_GET_REMOVE": "取得と削除", - "LISTS_GET_INDEX_REMOVE": "削除", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "終しまいから #", - "LISTS_GET_INDEX_FIRST": "最初", - "LISTS_GET_INDEX_LAST": "最後", - "LISTS_GET_INDEX_RANDOM": "ランダム", - "LISTS_GET_INDEX_TAIL": "", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 は、最初の項目です。", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 は、最後の項目です。", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "リスト内の指定位置にある項目を返します。", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "リストの最初の項目を返信します。", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "リストの最後の項目を返します。", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "ランダム アイテム リストを返します。", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "リスト内の指定位置にある項目を削除し、返します。", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "リスト内の最初の項目を削除したあと返します。", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "リスト内の最後の項目を削除したあと返します。", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "リストのランダムなアイテムを削除し、返します。", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "リスト内の指定位置にある項目を返します。", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "リスト内の最初の項目を削除します。", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "リスト内の最後の項目を削除します。", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "リスト内にある任意のアイテムを削除します。", - "LISTS_SET_INDEX_SET": "セット", - "LISTS_SET_INDEX_INSERT": "挿入します。", - "LISTS_SET_INDEX_INPUT_TO": "として", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "リスト内の指定された位置に項目を設定します。", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "リスト内に最初の項目を設定します。", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "リスト内の最後の項目を設定します。", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "リスト内にランダムなアイテムを設定します。", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "リスト内の指定位置に項目を挿入します。", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "リストの先頭に項目を挿入します。", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "リストの末尾に項目を追加します。", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "リストに項目をランダムに挿入します。", - "LISTS_GET_SUBLIST_START_FROM_START": "# からサブディレクトリのリストを取得します。", - "LISTS_GET_SUBLIST_START_FROM_END": "端から #のサブリストを取得します。", - "LISTS_GET_SUBLIST_START_FIRST": "最初からサブリストを取得する。", - "LISTS_GET_SUBLIST_END_FROM_START": "#へ", - "LISTS_GET_SUBLIST_END_FROM_END": "最後から#へ", - "LISTS_GET_SUBLIST_END_LAST": "最後へ", - "LISTS_GET_SUBLIST_TAIL": "", - "LISTS_GET_SUBLIST_TOOLTIP": "リストの指定された部分のコピーを作成してくださ。", - "LISTS_SORT_ORDER_ASCENDING": "昇順", - "LISTS_SORT_ORDER_DESCENDING": "降順", - "LISTS_SPLIT_LIST_FROM_TEXT": "テキストからリストを作る", - "LISTS_SPLIT_TEXT_FROM_LIST": "リストからテキストを作る", - "ORDINAL_NUMBER_SUFFIX": "", - "VARIABLES_GET_TOOLTIP": "この変数の値を返します。", - "VARIABLES_GET_CREATE_SET": "'セット%1を作成します。", - "VARIABLES_SET": "セット %1 宛先 %2", - "VARIABLES_SET_TOOLTIP": "この入力を変数と等しくなるように設定します。", - "VARIABLES_SET_CREATE_GET": "'%1 を取得' を作成します。", - "PROCEDURES_DEFNORETURN_HELPURL": "https://ja.wikipedia.org/wiki/サブルーチン", - "PROCEDURES_DEFNORETURN_TITLE": "宛先", - "PROCEDURES_DEFNORETURN_PROCEDURE": "何かしてください", - "PROCEDURES_BEFORE_PARAMS": "で。", - "PROCEDURES_CALL_BEFORE_PARAMS": "で。", - "PROCEDURES_DEFNORETURN_DO": "", - "PROCEDURES_DEFNORETURN_TOOLTIP": "出力なしで関数を作成します。", - "PROCEDURES_DEFRETURN_HELPURL": "https://ja.wikipedia.org/wiki/サブルーチン", - "PROCEDURES_DEFRETURN_RETURN": "返す", - "PROCEDURES_DEFRETURN_TOOLTIP": "出力を持つ関数を作成します。", - "PROCEDURES_DEF_DUPLICATE_WARNING": "警告: この関数は、重複するパラメーターがあります。", - "PROCEDURES_CALLNORETURN_HELPURL": "https://ja.wikipedia.org/wiki/サブルーチン", - "PROCEDURES_CALLNORETURN_TOOLTIP": "ユーザー定義関数 '%1' を実行します。", - "PROCEDURES_CALLRETURN_HELPURL": "https://ja.wikipedia.org/wiki/サブルーチン", - "PROCEDURES_CALLRETURN_TOOLTIP": "ユーザー定義関数 '%1' を実行し、その出力を使用します。", - "PROCEDURES_MUTATORCONTAINER_TITLE": "入力", - "PROCEDURES_MUTATORARG_TITLE": "入力名:", - "PROCEDURES_HIGHLIGHT_DEF": "関数の内容を強調表示します。", - "PROCEDURES_CREATE_DO": "%1をつくる", - "PROCEDURES_IFRETURN_TOOLTIP": "1番目値が true の場合、2 番目の値を返します。", - "PROCEDURES_IFRETURN_WARNING": "警告: このブロックは、関数定義内でのみ使用できます。" -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/ko.json b/backend/_pv_1_3_5/static/blockly/msg/json/ko.json deleted file mode 100755 index a393394c8..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/ko.json +++ /dev/null @@ -1,376 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Hym411", - "아라", - "Priviet", - "Revi", - "SeoJeongHo", - "Alex00728", - "Kurousagi", - "Lemondoge", - "Ykhwong" - ] - }, - "VARIABLES_DEFAULT_NAME": "항목", - "TODAY": "오늘", - "DUPLICATE_BLOCK": "중복됨", - "ADD_COMMENT": "댓글 추가", - "REMOVE_COMMENT": "내용 제거", - "EXTERNAL_INPUTS": "외부 입력", - "INLINE_INPUTS": "내부 입력", - "DELETE_BLOCK": "블록 삭제", - "DELETE_X_BLOCKS": "블록 %1개 삭제", - "DELETE_ALL_BLOCKS": "모든 블록 %1개를 삭제하겠습니까?", - "CLEAN_UP": "블록 정리", - "COLLAPSE_BLOCK": "블록 축소", - "COLLAPSE_ALL": "블록 축소", - "EXPAND_BLOCK": "블록 확장", - "EXPAND_ALL": "블록 확장", - "DISABLE_BLOCK": "블록 비활성화", - "ENABLE_BLOCK": "블록 활성화", - "HELP": "도움말", - "UNDO": "실행 취소", - "REDO": "다시 실행", - "CHANGE_VALUE_TITLE": "값 바꾸기:", - "RENAME_VARIABLE": "변수 이름 바꾸기:", - "RENAME_VARIABLE_TITLE": "'%1' 변수 이름을 바꾸기:", - "NEW_VARIABLE": "변수 만들기...", - "NEW_VARIABLE_TITLE": "새 변수 이름:", - "VARIABLE_ALREADY_EXISTS": "'%1' 변수는 이미 존재합니다.", - "DELETE_VARIABLE": "'%1' 변수를 삭제합니다", - "COLOUR_PICKER_HELPURL": "https://ko.wikipedia.org/wiki/색", - "COLOUR_PICKER_TOOLTIP": "팔레트에서 색을 고릅니다", - "COLOUR_RANDOM_TITLE": "임의 색상", - "COLOUR_RANDOM_TOOLTIP": "무작위로 색을 고릅니다.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "색", - "COLOUR_RGB_RED": "빨강", - "COLOUR_RGB_GREEN": "초록", - "COLOUR_RGB_BLUE": "파랑", - "COLOUR_RGB_TOOLTIP": "빨강,파랑,초록의 값을 이용하여 색을 만드십시오. 모든 값은 0과 100 사이에 있어야 합니다.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "혼합", - "COLOUR_BLEND_COLOUR1": "색 1", - "COLOUR_BLEND_COLOUR2": "색 2", - "COLOUR_BLEND_RATIO": "비율", - "COLOUR_BLEND_TOOLTIP": "두 색을 주어진 비율로 혼합 (0.0 - 1.0)", - "CONTROLS_REPEAT_HELPURL": "https://ko.wikipedia.org/wiki/For_루프", - "CONTROLS_REPEAT_TITLE": "%1회 반복", - "CONTROLS_REPEAT_INPUT_DO": "하기", - "CONTROLS_REPEAT_TOOLTIP": "여러 번 반복해 명령들을 실행합니다.", - "CONTROLS_WHILEUNTIL_HELPURL": "https://ko.wikipedia.org/wiki/While_%EB%A3%A8%ED%94%84", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "동안 반복", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "다음까지 반복", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "값이 참일 때, 몇 가지 선언을 합니다.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "값이 거짓일 때, 몇 가지 선언을 합니다.", - "CONTROLS_FOR_HELPURL": "https://ko.wikipedia.org/wiki/For_%EB%A3%A8%ED%94%84", - "CONTROLS_FOR_TOOLTIP": "변수 \"%1\"은 지정된 간격으로 시작 수에서 끝 수까지를 세어 지정된 블록을 수행해야 합니다.", - "CONTROLS_FOR_TITLE": "으로 계산 %1 %2에서 %4을 이용하여 %3로", - "CONTROLS_FOREACH_HELPURL": "https://ko.wikipedia.org/wiki/For_%EB%A3%A8%ED%94%84#.EC.9E.84.EC.9D.98.EC.9D.98_.EC.A7.91.ED.95.A9", - "CONTROLS_FOREACH_TITLE": "각 항목에 대해 %1 목록으로 %2", - "CONTROLS_FOREACH_TOOLTIP": "리스트 안에 들어있는 각 아이템들을, 순서대로 변수 '%1' 에 한 번씩 저장시키고, 그 때 마다 명령을 실행합니다.", - "CONTROLS_FLOW_STATEMENTS_HELPURL": "https://ko.wikipedia.org/wiki/%EC%A0%9C%EC%96%B4_%ED%9D%90%EB%A6%84", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "반복 중단", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "다음 반복", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "현재 반복 실행 블럭을 빠져나갑니다.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "나머지 반복 부분을 더 이상 실행하지 않고, 다음 반복을 수행합니다.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "경고 : 이 블록은 반복 실행 블럭 안에서만 사용됩니다.", - "CONTROLS_IF_HELPURL": "https://ko.wikipedia.org/wiki/%EC%A1%B0%EA%B1%B4%EB%AC%B8", - "CONTROLS_IF_TOOLTIP_1": "조건식의 계산 결과가 참이면, 명령을 실행합니다.", - "CONTROLS_IF_TOOLTIP_2": "조건식의 계산 결과가 참이면, 첫 번째 블럭의 명령을 실행하고, 그렇지 않으면 두 번째 블럭의 명령을 실행합니다.", - "CONTROLS_IF_TOOLTIP_3": "첫 번째 조건식의 계산 결과가 참이면, 첫 번째 블럭의 명령을 실행하고, 두 번째 조건식의 계산 결과가 참이면, 두 번째 블럭의 명령을 실행합니다.", - "CONTROLS_IF_TOOLTIP_4": "첫 번째 조건식의 계산 결과가 참이면, 첫 번째 블럭의 명령을 실행하고, 두 번째 조건식의 계산 결과가 참이면, 두 번째 블럭의 명령을 실행하고, ... , 어떤 조건식의 계산 결과도 참이 아니면, 마지막 블럭의 명령을 실행합니다.", - "CONTROLS_IF_MSG_IF": "만약", - "CONTROLS_IF_MSG_ELSEIF": "다른 경우", - "CONTROLS_IF_MSG_ELSE": "아니라면", - "CONTROLS_IF_IF_TOOLTIP": "섹션을 추가, 제거하거나 순서를 변경하여 이 if 블럭을 재구성합니다.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "\"만약\" 블럭에 조건 검사를 추가합니다.", - "CONTROLS_IF_ELSE_TOOLTIP": "\"만약\" 블럭의 마지막에, 모든 검사 결과가 거짓인 경우 실행할 부분을 추가합니다.", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "두 값이 같으면, 참(true) 값을 돌려줍니다.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "두 값이 서로 다르면, 참(true) 값을 돌려줍니다.", - "LOGIC_COMPARE_TOOLTIP_LT": "첫 번째 값이 두 번째 값보다 작으면, 참(true) 값을 돌려줍니다.", - "LOGIC_COMPARE_TOOLTIP_LTE": "첫 번째 값이 두 번째 값보다 작거나 같으면, 참(true) 값을 돌려줍니다.", - "LOGIC_COMPARE_TOOLTIP_GT": "첫 번째 값이 두 번째 값보다 크면, 참(true) 값을 돌려줍니다.", - "LOGIC_COMPARE_TOOLTIP_GTE": "첫 번째 값이 두 번째 값보다 크거나 같으면, 참(true) 값을 돌려줍니다.", - "LOGIC_OPERATION_HELPURL": "https://ko.wikipedia.org/wiki/%EB%B6%88_%EB%85%BC%EB%A6%AC", - "LOGIC_OPERATION_TOOLTIP_AND": "두 값이 모두 참(true) 값이면, 참 값을 돌려줍니다.", - "LOGIC_OPERATION_AND": "그리고", - "LOGIC_OPERATION_TOOLTIP_OR": "적어도 하나의 값이 참일 경우 참을 반환합니다.", - "LOGIC_OPERATION_OR": "또는", - "LOGIC_NEGATE_HELPURL": "https://ko.wikipedia.org/wiki/%EB%B6%80%EC%A0%95", - "LOGIC_NEGATE_TITLE": "%1가 아닙니다", - "LOGIC_NEGATE_TOOLTIP": "입력값이 거짓이라면 참을 반환합니다. 참이라면 거짓을 반환합니다.", - "LOGIC_BOOLEAN_HELPURL": "https://ko.wikipedia.org/wiki/%EC%A7%84%EB%A6%BF%EA%B0%92", - "LOGIC_BOOLEAN_TRUE": "참", - "LOGIC_BOOLEAN_FALSE": "거짓", - "LOGIC_BOOLEAN_TOOLTIP": "참 혹은 거짓 모두 반환합니다.", - "LOGIC_NULL_HELPURL": "https://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "빈 값", - "LOGIC_NULL_TOOLTIP": "빈 값을 반환합니다.", - "LOGIC_TERNARY_HELPURL": "https://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "테스트", - "LOGIC_TERNARY_IF_TRUE": "만약 참이라면", - "LOGIC_TERNARY_IF_FALSE": "만약 거짓이라면", - "LOGIC_TERNARY_TOOLTIP": "'test'의 조건을 검사합니다. 조건이 참이면 'if true' 값을 반환합니다. 거짓이면 'if false' 값을 반환합니다.", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "수", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "x", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tan", - "MATH_TRIG_ASIN": "asin", - "MATH_TRIG_ACOS": "acos", - "MATH_TRIG_ATAN": "atan", - "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/Arithmetic", - "MATH_ARITHMETIC_TOOLTIP_ADD": "두 수의 합을 반환합니다.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "두 수간의 차이를 반환합니다.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "두 수의 곱을 반환합니다.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "두 수의 나눈 결과를 반환합니다.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "첫 번째 수를 두 번째 수 만큼, 거듭제곱 한 결과값을 돌려줍니다.", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "제곱근", - "MATH_SINGLE_TOOLTIP_ROOT": "숫자의 제곱근을 반환합니다.", - "MATH_SINGLE_OP_ABSOLUTE": "절대값", - "MATH_SINGLE_TOOLTIP_ABS": "어떤 수의 절대값(absolute)을 계산한 결과를, 정수값으로 돌려줍니다.", - "MATH_SINGLE_TOOLTIP_NEG": "음(-)/양(+), 부호를 반대로 하여 값을 돌려줍니다.", - "MATH_SINGLE_TOOLTIP_LN": "어떤 수의, 자연로그(natural logarithm) 값을 돌려줍니다.(밑 e, 예시 log e x)", - "MATH_SINGLE_TOOLTIP_LOG10": "어떤 수의, 기본로그(logarithm) 값을 돌려줍니다.(밑 10, 예시 log 10 x)", - "MATH_SINGLE_TOOLTIP_EXP": "e의 거듭제곱 값을 반환합니다.", - "MATH_SINGLE_TOOLTIP_POW10": "10의 거듭제곱 값을 반환합니다.", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "각도의 사인을 반환합니다. (라디안 아님)", - "MATH_TRIG_TOOLTIP_COS": "각도의 코사인을 반환합니다. (라디안 아님)", - "MATH_TRIG_TOOLTIP_TAN": "각도의 탄젠트를 반환합니다. (라디안 아님)", - "MATH_TRIG_TOOLTIP_ASIN": "어떤 수에 대한, asin(arcsine) 값을 돌려줍니다.", - "MATH_TRIG_TOOLTIP_ACOS": "어떤 수에 대한, acos(arccosine) 값을 돌려줍니다.", - "MATH_TRIG_TOOLTIP_ATAN": "어떤 수에 대한, atan(arctangent) 값을 돌려줍니다.", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "일반적인 상수 값들 중 하나를 돌려줍니다. : π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).", - "MATH_IS_EVEN": "가 짝수(even) 이면", - "MATH_IS_ODD": "가 홀수(odd) 이면", - "MATH_IS_PRIME": "가 소수(prime) 이면", - "MATH_IS_WHOLE": "가 정수이면", - "MATH_IS_POSITIVE": "가 양(+)수 이면", - "MATH_IS_NEGATIVE": "가 음(-)수 이면", - "MATH_IS_DIVISIBLE_BY": "가 다음 수로 나누어 떨어지면 :", - "MATH_IS_TOOLTIP": "어떤 수가 짝 수, 홀 수, 소 수, 정 수, 양 수, 음 수, 나누어 떨어지는 수 인지 검사해 결과값을 돌려줍니다. 참(true) 또는 거짓(false) 값을 돌려줌.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "바꾸기 %1 만큼 %2", - "MATH_CHANGE_TOOLTIP": "변수 '%1' 에 저장되어있는 값에, 어떤 수를 더해, 변수에 다시 저장합니다.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "어떤 수를 반올림/올림/버림한 결과를, 정수값으로 돌려줍니다.", - "MATH_ROUND_OPERATOR_ROUND": "반올림", - "MATH_ROUND_OPERATOR_ROUNDUP": "올림", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "버림", - "MATH_ONLIST_HELPURL": "", - "MATH_ONLIST_OPERATOR_SUM": "합", - "MATH_ONLIST_TOOLTIP_SUM": "리스트에 들어있는 수(값)들을, 모두 합(sum) 한, 총합(sum)을 돌려줍니다.", - "MATH_ONLIST_OPERATOR_MIN": "최소값", - "MATH_ONLIST_TOOLTIP_MIN": "리스트에 들어있는 수(값) 들 중, 가장 작은(min) 수(값)를 돌려줍니다.", - "MATH_ONLIST_OPERATOR_MAX": "최대값", - "MATH_ONLIST_TOOLTIP_MAX": "리스트에 들어있는 수(값) 들 중, 가장 큰(max) 수(값)를 돌려줍니다.", - "MATH_ONLIST_OPERATOR_AVERAGE": "평균값", - "MATH_ONLIST_TOOLTIP_AVERAGE": "리스트에 들어있는 수(값)들에 대해, 산술 평균(arithmetic mean) 한 값을 돌려줍니다.", - "MATH_ONLIST_OPERATOR_MEDIAN": "중간값", - "MATH_ONLIST_TOOLTIP_MEDIAN": "리스트에 들어있는 수(값) 들 중, 중간(median) 수(값)를 돌려줍니다.", - "MATH_ONLIST_OPERATOR_MODE": "가장 여러 개 있는 값", - "MATH_ONLIST_TOOLTIP_MODE": "리스트에 들어있는 아이템들 중에서, 가장 여러 번 들어있는 아이템들을 리스트로 만들어 돌려줍니다. (최빈값, modes)", - "MATH_ONLIST_OPERATOR_STD_DEV": "표준 편차", - "MATH_ONLIST_TOOLTIP_STD_DEV": "이 리스트의 표준 편차를 반환합니다.", - "MATH_ONLIST_OPERATOR_RANDOM": "목록의 임의 항목", - "MATH_ONLIST_TOOLTIP_RANDOM": "목록에서 임의의 아이템을 돌려줍니다.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "%1 ÷ %2의 나머지", - "MATH_MODULO_TOOLTIP": "첫 번째 수를 두 번째 수로 나눈, 나머지 값을 돌려줍니다.", - "MATH_CONSTRAIN_HELPURL": "https://ko.wikipedia.org/wiki/%ED%81%B4%EB%9E%A8%ED%95%91_(%EA%B7%B8%EB%9E%98%ED%94%BD)", - "MATH_CONSTRAIN_TITLE": "%1의 값을, 최소 %2 최대 %3으로 조정", - "MATH_CONSTRAIN_TOOLTIP": "어떤 수를, 특정 범위의 값이 되도록 강제로 조정합니다.", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "랜덤정수(%1<= n <=%2)", - "MATH_RANDOM_INT_TOOLTIP": "두 주어진 제한된 범위 사이의 임의 정수값을 돌려줍니다.", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "임의 분수", - "MATH_RANDOM_FLOAT_TOOLTIP": "0.0 (포함)과 1.0 (배타적) 사이의 임의 분수 값을 돌려줍니다.", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "문자, 단어, 문장.", - "TEXT_JOIN_HELPURL": "https://github.com/google/blockly/wiki/Text#text-creation", - "TEXT_JOIN_TITLE_CREATEWITH": "텍스트 만들기", - "TEXT_JOIN_TOOLTIP": "여러 개의 아이템들을 연결해(묶어), 새로운 문장을 만듭니다.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "가입", - "TEXT_CREATE_JOIN_TOOLTIP": "섹션을 추가, 제거하거나 순서를 변경하여 이 텍스트 블럭을 재구성합니다.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "텍스트에 항목을 추가합니다.", - "TEXT_APPEND_HELPURL": "https://github.com/google/blockly/wiki/Text#text-modification", - "TEXT_APPEND_TO": "다음", - "TEXT_APPEND_APPENDTEXT": "내용 덧붙이기", - "TEXT_APPEND_TOOLTIP": "'%1' 변수의 끝에 일부 텍스트를 덧붙입니다.", - "TEXT_LENGTH_HELPURL": "https://github.com/google/blockly/wiki/Text#text-modification", - "TEXT_LENGTH_TITLE": "다음 문장의 문자 개수 %1", - "TEXT_LENGTH_TOOLTIP": "입력된 문장의, 문자 개수를 돌려줍니다.(공백문자 포함)", - "TEXT_ISEMPTY_HELPURL": "https://github.com/google/blockly/wiki/Text#checking-for-empty-text", - "TEXT_ISEMPTY_TITLE": "%1이 비어 있습니다", - "TEXT_ISEMPTY_TOOLTIP": "입력된 문장이, 빈 문장(\"\")이면 참(true) 값을 돌려줍니다.", - "TEXT_INDEXOF_HELPURL": "https://github.com/google/blockly/wiki/Text#finding-text", - "TEXT_INDEXOF_TOOLTIP": "두 번째 텍스트에서 첫 번째 텍스트가 처음 또는 마지막으로 발생한 색인 위치를 반환합니다. 텍스트가 없으면 %1을 반환합니다.", - "TEXT_INDEXOF_INPUT_INTEXT": "문장", - "TEXT_INDEXOF_OPERATOR_FIRST": "에서 다음 문장이 처음으로 나타난 위치 찾기 :", - "TEXT_INDEXOF_OPERATOR_LAST": "에서 다음 문장이 마지막으로 나타난 위치 찾기 :", - "TEXT_INDEXOF_TAIL": "", - "TEXT_CHARAT_HELPURL": "https://github.com/google/blockly/wiki/Text#extracting-text", - "TEXT_CHARAT_INPUT_INTEXT": "문장", - "TEXT_CHARAT_FROM_START": "에서, 앞에서부터 # 번째 위치의 문자 얻기", - "TEXT_CHARAT_FROM_END": "에서, 마지막부터 # 번째 위치의 문자 얻기", - "TEXT_CHARAT_FIRST": "에서, 첫 번째 문자 얻기", - "TEXT_CHARAT_LAST": "에서, 마지막 문자 얻기", - "TEXT_CHARAT_RANDOM": "에서, 랜덤하게 한 문자 얻기", - "TEXT_CHARAT_TAIL": "", - "TEXT_CHARAT_TOOLTIP": "특정 번째 위치에서, 문자를 얻어내 돌려줍니다.", - "TEXT_GET_SUBSTRING_TOOLTIP": "문장 중 일부를 얻어내 돌려줍니다.", - "TEXT_GET_SUBSTRING_HELPURL": "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "문장", - "TEXT_GET_SUBSTRING_START_FROM_START": "에서, 처음부터 # 번째 문자부터 얻어냄", - "TEXT_GET_SUBSTRING_START_FROM_END": "에서, 마지막에서 # 번째부터 얻어냄", - "TEXT_GET_SUBSTRING_START_FIRST": "에서, 처음부터 얻어냄", - "TEXT_GET_SUBSTRING_END_FROM_START": "# 번째 문자까지", - "TEXT_GET_SUBSTRING_END_FROM_END": "끝에서부터 # 번째 문자까지", - "TEXT_GET_SUBSTRING_END_LAST": "마지막 문자까지", - "TEXT_GET_SUBSTRING_TAIL": "", - "TEXT_CHANGECASE_HELPURL": "https://github.com/google/blockly/wiki/Text#adjusting-text-case", - "TEXT_CHANGECASE_TOOLTIP": "영문 대소문자 형태를 변경해 돌려줍니다.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "대문자로", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "소문자로", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "첫 문자만 대문자로", - "TEXT_TRIM_HELPURL": "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces", - "TEXT_TRIM_TOOLTIP": "문장의 왼쪽/오른쪽/양쪽에서 스페이스 문자를 제거해 돌려줍니다.", - "TEXT_TRIM_OPERATOR_BOTH": "양쪽의 공백 문자 제거", - "TEXT_TRIM_OPERATOR_LEFT": "왼쪽의 공백 문자 제거", - "TEXT_TRIM_OPERATOR_RIGHT": "오른쪽의 공백 문자 제거", - "TEXT_PRINT_HELPURL": "https://github.com/google/blockly/wiki/Text#printing-text", - "TEXT_PRINT_TITLE": "다음 내용 출력 %1", - "TEXT_PRINT_TOOLTIP": "원하는 문장, 수, 값 등을 출력합니다.", - "TEXT_PROMPT_HELPURL": "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user", - "TEXT_PROMPT_TYPE_TEXT": "메시지를 활용해 문장 입력", - "TEXT_PROMPT_TYPE_NUMBER": "메시지를 활용해 수 입력", - "TEXT_PROMPT_TOOLTIP_NUMBER": "수에 대해 사용자의 입력을 받습니다.", - "TEXT_PROMPT_TOOLTIP_TEXT": "문장에 대해 사용자의 입력을 받습니다.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "빈 리스트 생성", - "LISTS_CREATE_EMPTY_TOOLTIP": "데이터 레코드가 없는, 길이가 0인 목록을 반환합니다.", - "LISTS_CREATE_WITH_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_CREATE_WITH_TOOLTIP": "원하는 수의 항목들로 목록을 생성합니다.", - "LISTS_CREATE_WITH_INPUT_WITH": "리스트 만들기", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "리스트", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "섹션을 추가, 제거하거나 순서를 변경하여 이 리스트 블럭을 재구성합니다.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "아이템을 리스트에 추가합니다.", - "LISTS_REPEAT_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_REPEAT_TOOLTIP": "원하는 값을, 원하는 갯수 만큼 넣어, 목록을 생성합니다.", - "LISTS_REPEAT_TITLE": "%1을 %2번 넣어, 리스트 생성", - "LISTS_LENGTH_HELPURL": "https://github.com/google/blockly/wiki/Lists#length-of", - "LISTS_LENGTH_TITLE": "%1의 길이", - "LISTS_LENGTH_TOOLTIP": "목록의 길이를 반환합니다.", - "LISTS_ISEMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#is-empty", - "LISTS_ISEMPTY_TITLE": "%1이 비어 있습니다", - "LISTS_ISEMPTY_TOOLTIP": "목록이 비었을 때 참을 반환합니다.", - "LISTS_INLIST": "리스트", - "LISTS_INDEX_OF_HELPURL": "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list", - "LISTS_INDEX_OF_FIRST": "처음으로 나타난 위치", - "LISTS_INDEX_OF_LAST": "마지막으로 나타난 위치", - "LISTS_INDEX_OF_TOOLTIP": "목록에서 항목이 처음 또는 마지막으로 발생한 색인 위치를 반환합니다. 항목이 없으면 %1을 반환합니다.", - "LISTS_GET_INDEX_GET": "가져오기", - "LISTS_GET_INDEX_GET_REMOVE": "잘라 내기", - "LISTS_GET_INDEX_REMOVE": "삭제", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "마지막 번째 위치부터, # 번째", - "LISTS_GET_INDEX_FIRST": "첫 번째", - "LISTS_GET_INDEX_LAST": "마지막", - "LISTS_GET_INDEX_RANDOM": "임의로", - "LISTS_GET_INDEX_TAIL": "", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1은 첫 번째 항목입니다.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1은(는) 마지막 항목입니다.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "목록에서 특정 위치의 항목을 반환합니다.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "첫 번째 아이템을 찾아 돌려줍니다.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "마지막 아이템을 찾아 돌려줍니다.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "리스트의 아이템들 중, 랜덤으로 선택해 돌려줍니다.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "목록의 특정 위치에 있는 항목을 제거하고 반환합니다.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "첫 번째 아이템을 찾아내 돌려주고, 그 아이템을 리스트에서 삭제합니다.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "마지막 아이템을 찾아내 돌려주고, 그 아이템을 리스트에서 삭제합니다.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "목록에서 임의 위치의 아이템을 찾아내 삭제하고 돌려줍니다.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "목록에서 특정 위치의 항목을 삭제합니다.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "리스트에서 첫 번째 아이템을 삭제합니다.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "리스트에서 마지막 아이템을 찾아 삭제합니다.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "리스트에서 랜덤하게 아이템을 삭제합니다.", - "LISTS_SET_INDEX_HELPURL": "https://github.com/google/blockly/wiki/Lists#in-list--set", - "LISTS_SET_INDEX_SET": "에서 설정", - "LISTS_SET_INDEX_INSERT": "에서 원하는 위치에 삽입", - "LISTS_SET_INDEX_INPUT_TO": "에", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "목록의 특정 위치에 있는 항목으로 설정합니다.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "첫 번째 위치의 아이템으로 설정합니다.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "마지막 아이템으로 설정합니다.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "목록에서 임의 위치의 아이템을 설정합니다.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "목록의 특정 위치에 항목을 삽입합니다.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "항목을 목록의 처음 위치에 삽입합니다.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "리스트의 마지막에 아이템을 추가합니다.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "목록에서 임의 위치에 아이템을 삽입합니다.", - "LISTS_GET_SUBLIST_HELPURL": "https://github.com/google/blockly/wiki/Lists#getting-a-sublist", - "LISTS_GET_SUBLIST_START_FROM_START": "처음 # 번째 위치부터, 서브 리스트 추출", - "LISTS_GET_SUBLIST_START_FROM_END": "마지막부터 # 번째 위치부터, 서브 리스트 추출", - "LISTS_GET_SUBLIST_START_FIRST": "첫 번째 위치부터, 서브 리스트 추출", - "LISTS_GET_SUBLIST_END_FROM_START": "앞에서부터 # 번째로", - "LISTS_GET_SUBLIST_END_FROM_END": "끝에서부터 # 번째로", - "LISTS_GET_SUBLIST_END_LAST": "마지막으로", - "LISTS_GET_SUBLIST_TAIL": "", - "LISTS_GET_SUBLIST_TOOLTIP": "목록의 특정 부분에 대한 복사본을 만듭니다.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "정렬 %1 %2 %3", - "LISTS_SORT_TOOLTIP": "목록의 사본을 정렬합니다.", - "LISTS_SORT_ORDER_ASCENDING": "오름차순", - "LISTS_SORT_ORDER_DESCENDING": "내림차순", - "LISTS_SORT_TYPE_NUMERIC": "숫자순", - "LISTS_SORT_TYPE_TEXT": "알파벳순", - "LISTS_SORT_TYPE_IGNORECASE": "알파벳순 (대소문자 구분 안 함)", - "LISTS_SPLIT_HELPURL": "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists", - "LISTS_SPLIT_LIST_FROM_TEXT": "텍스트에서 목록 만들기", - "LISTS_SPLIT_TEXT_FROM_LIST": "목록에서 텍스트 만들기", - "LISTS_SPLIT_WITH_DELIMITER": "분리와", - "LISTS_SPLIT_TOOLTIP_SPLIT": "각 속보, 텍스트의 목록들에서 텍스트를 분할합니다.", - "LISTS_SPLIT_TOOLTIP_JOIN": "구분 기호로 구분하여 텍스트 목록을 하나의 텍스트에 병합합니다.", - "ORDINAL_NUMBER_SUFFIX": "", - "VARIABLES_GET_HELPURL": "https://ko.wikipedia.org/wiki/%EB%B3%80%EC%88%98_(%EC%BB%B4%ED%93%A8%ED%84%B0_%EA%B3%BC%ED%95%99)", - "VARIABLES_GET_TOOLTIP": "변수에 저장 되어있는 값을 돌려줍니다.", - "VARIABLES_GET_CREATE_SET": "'집합 %1' 생성", - "VARIABLES_SET_HELPURL": "https://ko.wikipedia.org/wiki/%EB%B3%80%EC%88%98_(%EC%BB%B4%ED%93%A8%ED%84%B0_%EA%B3%BC%ED%95%99)", - "VARIABLES_SET": "%1를 %2로 설정", - "VARIABLES_SET_TOOLTIP": "변수의 값을 입력한 값으로 변경해 줍니다.", - "VARIABLES_SET_CREATE_GET": "'%1 값 읽기' 블럭 생성", - "PROCEDURES_DEFNORETURN_HELPURL": "https://ko.wikipedia.org/wiki/%ED%95%A8%EC%88%98_%28%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%29", - "PROCEDURES_DEFNORETURN_TITLE": "함수", - "PROCEDURES_DEFNORETURN_PROCEDURE": "함수 이름", - "PROCEDURES_BEFORE_PARAMS": "사용:", - "PROCEDURES_CALL_BEFORE_PARAMS": "사용:", - "PROCEDURES_DEFNORETURN_DO": "", - "PROCEDURES_DEFNORETURN_TOOLTIP": "실행 후, 결과 값을 돌려주지 않는 함수를 만듭니다.", - "PROCEDURES_DEFNORETURN_COMMENT": "이 함수를 설명하세요...", - "PROCEDURES_DEFRETURN_HELPURL": "https://ko.wikipedia.org/wiki/%ED%95%A8%EC%88%98_%28%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%29", - "PROCEDURES_DEFRETURN_RETURN": "다음을 돌려줌", - "PROCEDURES_DEFRETURN_TOOLTIP": "실행 후, 결과 값을 돌려주는 함수를 만듭니다.", - "PROCEDURES_ALLOW_STATEMENTS": "서술 허가", - "PROCEDURES_DEF_DUPLICATE_WARNING": "경고: 이 함수에는, 같은 이름을 사용하는 매개 변수들이 있습니다.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "미리 정의해 둔 '%1' 함수를 실행합니다.", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "미리 정의해 둔 '%1' 함수를 실행하고, 함수를 실행한 결과 값을 돌려줍니다.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "매개 변수들", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "이 함수를 추가, 삭제, 혹은 재정렬합니다.", - "PROCEDURES_MUTATORARG_TITLE": "매개 변수:", - "PROCEDURES_MUTATORARG_TOOLTIP": "함수에 값을 더합니다.", - "PROCEDURES_HIGHLIGHT_DEF": "함수 정의 찾기", - "PROCEDURES_CREATE_DO": "'%1' 생성", - "PROCEDURES_IFRETURN_TOOLTIP": "값이 참이라면, 두 번째 값을 반환합니다.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "경고: 이 블럭은, 함수 정의 블럭 안에서만 사용할 수 있습니다." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/lb.json b/backend/_pv_1_3_5/static/blockly/msg/json/lb.json deleted file mode 100755 index 50e4668a5..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/lb.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Robby", - "Soued031", - "Les Meloures" - ] - }, - "VARIABLES_DEFAULT_NAME": "Element", - "TODAY": "Haut", - "DUPLICATE_BLOCK": "Eng Kopie maachen", - "ADD_COMMENT": "Bemierkung derbäisetzen", - "REMOVE_COMMENT": "Bemierkung ewechhuelen", - "DELETE_BLOCK": "Block läschen", - "DELETE_X_BLOCKS": "%1 Bléck läschen", - "CLEAN_UP": "Bléck opraumen", - "COLLAPSE_BLOCK": "Block zesummeklappen", - "COLLAPSE_ALL": "Bléck zesummeklappen", - "EXPAND_BLOCK": "Block opklappen", - "EXPAND_ALL": "Bléck opklappen", - "DISABLE_BLOCK": "Block desaktivéieren", - "ENABLE_BLOCK": "Block aktivéieren", - "HELP": "Hëllef", - "UNDO": "Réckgängeg maachen", - "REDO": "Widderhuelen", - "CHANGE_VALUE_TITLE": "Wäert änneren:", - "RENAME_VARIABLE": "Variabel ëmbenennen...", - "RENAME_VARIABLE_TITLE": "All '%1' Variabelen ëmbenennen op:", - "NEW_VARIABLE": "Variabel uleeën...", - "NEW_VARIABLE_TITLE": "Neie variabelen Numm:", - "COLOUR_PICKER_TOOLTIP": "Sicht eng Faarf an der Palette eraus.", - "COLOUR_RANDOM_TITLE": "zoufälleg Faarf", - "COLOUR_RANDOM_TOOLTIP": "Eng zoufälleg Faarf eraussichen.", - "COLOUR_RGB_TITLE": "fierwe mat", - "COLOUR_RGB_RED": "rout", - "COLOUR_RGB_GREEN": "gréng", - "COLOUR_RGB_BLUE": "blo", - "COLOUR_BLEND_TITLE": "mëschen", - "COLOUR_BLEND_COLOUR1": "Faarf 1", - "COLOUR_BLEND_COLOUR2": "Faarf 2", - "COLOUR_BLEND_RATIO": "ratio", - "CONTROLS_REPEAT_TITLE": "%1-mol widderhuelen", - "CONTROLS_REPEAT_INPUT_DO": "maach", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "Widderhuel soulaang", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "widderhuele bis", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Féiert d'Uweisungen aus, soulaang wéi de Wäert richteg ass", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Féiert d'Uweisungen aus, soulaang wéi de Wäert falsch ass.", - "CONTROLS_FOR_TITLE": "zielt mat %1 vun %2 bis %3 mat %4", - "CONTROLS_FOREACH_TITLE": "fir all Element %1 an der Lëscht %2", - "CONTROLS_IF_MSG_IF": "wann", - "CONTROLS_IF_MSG_ELSE": "soss", - "LOGIC_OPERATION_AND": "an", - "LOGIC_OPERATION_OR": "oder", - "LOGIC_NEGATE_TITLE": "net %1", - "LOGIC_BOOLEAN_TRUE": "wouer", - "LOGIC_BOOLEAN_FALSE": "falsch", - "LOGIC_BOOLEAN_TOOLTIP": "Schéckt entweder richteg oder falsch zréck.", - "LOGIC_NULL": "null", - "LOGIC_TERNARY_HELPURL": "https://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "Test", - "LOGIC_TERNARY_IF_TRUE": "wa wouer", - "LOGIC_TERNARY_IF_FALSE": "wa falsch", - "MATH_NUMBER_TOOLTIP": "Eng Zuel.", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Den Total vun den zwou Zuelen zréckginn.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "D'Produkt vun den zwou Zuelen zréckginn.", - "MATH_SINGLE_HELPURL": "https://lb.wikipedia.org/wiki/Racine carrée", - "MATH_SINGLE_OP_ROOT": "Quadratwuerzel", - "MATH_SINGLE_OP_ABSOLUTE": "absolut", - "MATH_IS_EVEN": "ass gerued", - "MATH_IS_ODD": "ass ongerued", - "MATH_IS_PRIME": "ass eng Primzuel", - "MATH_IS_WHOLE": "ass eng ganz Zuel", - "MATH_IS_POSITIVE": "ass positiv", - "MATH_IS_NEGATIVE": "ass negativ", - "MATH_CHANGE_TITLE": "änneren %1 ëm %2", - "MATH_ROUND_TOOLTIP": "Eng Zuel op- oder ofrënnen.", - "MATH_ROUND_OPERATOR_ROUND": "opronnen", - "MATH_ROUND_OPERATOR_ROUNDUP": "oprënnen", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "ofrënnen", - "MATH_ONLIST_OPERATOR_MAX": "Maximum aus der Lëscht", - "MATH_ONLIST_TOOLTIP_MAX": "Schéckt de gréisste Wäert aus enger Lëscht zréck.", - "MATH_ONLIST_OPERATOR_AVERAGE": "Moyenne vun der Lëscht", - "MATH_ONLIST_OPERATOR_RANDOM": "zoufällegt Element vun enger Lëscht", - "MATH_MODULO_TITLE": "Rescht vu(n) %1 ÷ %2", - "MATH_RANDOM_INT_TITLE": "zoufälleg ganz Zuel tëscht %1 a(n) %2", - "TEXT_TEXT_TOOLTIP": "E Buschtaf, e Wuert oder eng Textzeil.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "En Element bei den Text derbäisetzen.", - "TEXT_APPEND_APPENDTEXT": "Text drunhänken", - "TEXT_LENGTH_TITLE": "Längt vu(n) %1", - "TEXT_ISEMPTY_TITLE": "%1 ass eidel", - "TEXT_INDEXOF_INPUT_INTEXT": "am Text", - "TEXT_CHARAT_INPUT_INTEXT": "am Text", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "am Text", - "TEXT_GET_SUBSTRING_END_FROM_START": "bis bei de Buschtaf #", - "TEXT_GET_SUBSTRING_END_LAST": "bis bei de leschte Buschtaw", - "TEXT_PRINT_TITLE": "%1 drécken", - "TEXT_PROMPT_TOOLTIP_TEXT": "Frot de Benotzer no engem Text.", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "Lëscht", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "En Element op d'Lëscht derbäisetzen.", - "LISTS_LENGTH_TITLE": "Längt vu(n) %1", - "LISTS_ISEMPTY_TITLE": "%1 ass eidel", - "LISTS_INLIST": "an der Lëscht", - "LISTS_GET_INDEX_REMOVE": "ewechhuelen", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# vun hannen", - "LISTS_GET_INDEX_FIRST": "éischt", - "LISTS_GET_INDEX_LAST": "lescht", - "LISTS_GET_INDEX_RANDOM": "Zoufall", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 ass dat éischt Element.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 ass dat éischt Element.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Schéckt en zoufällegt Element aus enger Lëscht zréck.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Hëlt dat lescht Element aus enger Lëscht eraus.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Hëlt en zoufällegt Element aus enger Lëscht eraus.", - "LISTS_SET_INDEX_INSERT": "asetzen op", - "LISTS_SET_INDEX_INPUT_TO": "als", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Setzt en zoufällegt Element an eng Lëscht.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Setzt d'Element um Enn vun enger Lëscht derbäi.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Setzt d'Element op eng zoufälleg Plaz an d'Lëscht derbäi.", - "LISTS_SORT_TYPE_NUMERIC": "numeresch", - "LISTS_SORT_TYPE_TEXT": "alphabetesch", - "PROCEDURES_DEFNORETURN_PROCEDURE": "eppes maachen", - "PROCEDURES_BEFORE_PARAMS": "mat:", - "PROCEDURES_CALL_BEFORE_PARAMS": "mat:", - "PROCEDURES_DEFNORETURN_COMMENT": "Dës Funktioun beschreiwen...", - "PROCEDURES_DEFRETURN_RETURN": "zréck" -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/lki.json b/backend/_pv_1_3_5/static/blockly/msg/json/lki.json deleted file mode 100755 index ca97a8926..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/lki.json +++ /dev/null @@ -1,296 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Hosseinblue", - "Lakzon" - ] - }, - "VARIABLES_DEFAULT_NAME": "آیتم", - "TODAY": "ایمڕۆ", - "DUPLICATE_BLOCK": "کؤپی کردن", - "ADD_COMMENT": "گةپ دائن", - "REMOVE_COMMENT": "پاک کردن گةپةل/قِسةل", - "EXTERNAL_INPUTS": "ورودیةل خروجی", - "INLINE_INPUTS": "ورودیةل نوم جا", - "DELETE_BLOCK": "پاک کردن بلاک", - "DELETE_X_BLOCKS": "حةذف %1 بلاکةل", - "DELETE_ALL_BLOCKS": "حةذف کؤل %1 بلاکةل?", - "CLEAN_UP": "تمیزکردن بلاکةل", - "COLLAPSE_BLOCK": "چؤیچانن/پشکانن بلاک", - "COLLAPSE_ALL": "چؤیچانن/پشکانن بلاکةل", - "EXPAND_BLOCK": "کةلنگآ کردِن بلاک", - "EXPAND_ALL": "کةلنگآ کردِن بلاکةل", - "DISABLE_BLOCK": "إ کار کةتن(غیرفعال‌سازی) بلاک", - "ENABLE_BLOCK": "إ کارآشتن(فعال)بلاک", - "HELP": "کؤمةک", - "CHANGE_VALUE_TITLE": "تةغییر مقدار:", - "RENAME_VARIABLE": "تغییر نام متغیر...", - "RENAME_VARIABLE_TITLE": "تغییر نام همهٔ متغیرهای «%1» به:", - "NEW_VARIABLE": "متغیر تازه...", - "NEW_VARIABLE_TITLE": "نام متغیر تازه:", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/رةنگ", - "COLOUR_PICKER_TOOLTIP": "رةنگێ إژ تةختة رةنگ انتخاب کةن", - "COLOUR_RANDOM_TITLE": "رةنگ بةختةکی", - "COLOUR_RANDOM_TOOLTIP": ".رةنگئ بةختةکی انتخاب کةن", - "COLOUR_RGB_TITLE": "رةنگ وة", - "COLOUR_RGB_RED": "سۆر", - "COLOUR_RGB_GREEN": "سؤز", - "COLOUR_RGB_BLUE": "کاوو", - "COLOUR_RGB_TOOLTIP": "ساخت یک رنگ با مقدار مشخص‌شده‌ای از سۆر، سؤز و کاوو. همهٔ مقادیر باید بین ۰ تا ۱۰۰ باشند.", - "COLOUR_BLEND_TITLE": "قاتی پاتی", - "COLOUR_BLEND_COLOUR1": "رةنگ 1", - "COLOUR_BLEND_COLOUR2": "رةنگ 2", - "COLOUR_BLEND_RATIO": "نسبت", - "COLOUR_BLEND_TOOLTIP": "دو رنگ را با نسبت مشخص‌شده مخلوط می‌کند (۰٫۰ - ۱٫۰)", - "CONTROLS_REPEAT_HELPURL": "https://lki.wikipedia.org/wiki/حلقه_فور", - "CONTROLS_REPEAT_TITLE": "%بار تکرار 1", - "CONTROLS_REPEAT_INPUT_DO": "انجوم بی", - "CONTROLS_REPEAT_TOOLTIP": "انجام چةن عبارت چندین گِل.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "تکرار در حالی که", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "تکرار تا وةختێ گإ", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "تا زمانی که یک مقدار صحیح است، چند عبارت را انجام بده.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "تا زمانی که یک مقدار ناصحیح است، چند عبارت را انجام بده.", - "CONTROLS_FOR_TOOLTIP": "متغیر %1 را در مقادیر شروع‌شده از عدد انتهای به عدد انتهایی را دارد، با فواصل مشخص‌شده می‌شمارد و این بلوک مشخص‌شده را انجام می‌دهد.", - "CONTROLS_FOR_TITLE": "با تعداد %1 از %2 به %3 با گام‌های %4", - "CONTROLS_FOREACH_TITLE": "ئةرا هر مورد %1 وۀ نام لیست%2", - "CONTROLS_FOREACH_TOOLTIP": "برای هر مورد در این فهرست، تنظیم متغیر «%1» به مورد و انجام تعدادی عبارت.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "شکانِن حلقه", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "ادامه با تکرار بعدی حلقه", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "شکستن حلقهٔ شامل.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "پریدن از بقیهٔ حلقه و ادامه با تکرار بعدی.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "اخطار: این بلوک ممکن است فقط داخل یک حلقه استفاده شود.", - "CONTROLS_IF_TOOLTIP_1": "اگر یک مقدار صحیح است، سپس چند عبارت را انجام بده.", - "CONTROLS_IF_TOOLTIP_2": "اگر یک مقدار صحیح است، اول بلوک اول عبارات را انجام بده. در غیر این صورت بلوک دوم عبارات انجام بده.", - "CONTROLS_IF_TOOLTIP_3": "اگر مقدار اول صحیح بود، از آن بلوک اول عبارات را انجام بده. در غیر این صورت، اگر مقدار دوم صحیح است، بلوک دوم عبارات را انجام بده.", - "CONTROLS_IF_TOOLTIP_4": "اگر مقدار اول درست است، بلوک اول عبارات را انجام بده. در غیر این صورت، اگر مقدار دوم درست باشد بلوک دوم عبارات را انجام بده. اگر هیچ از مقادیر درست نبود، آخرین بلوک عبارات را انجام بده.", - "CONTROLS_IF_MSG_IF": "اگر", - "CONTROLS_IF_MSG_ELSEIF": "اگر آنگاه", - "CONTROLS_IF_MSG_ELSE": "آنگاه", - "CONTROLS_IF_IF_TOOLTIP": "افزودن، حذف یا بازمرتب‌سازی قسمت‌ها برای پیکربندی دوبارهٔ این بلوک اگر.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "افزودن یک شرط به بلوک اگر.", - "CONTROLS_IF_ELSE_TOOLTIP": "اضافه‌کردن نهایی، گرفتن همهٔ شرایط به بلوک اگر.", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "بازگشت صحیح اگر هر دو ورودی با یکدیگر برابر باشد.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "برگرداندن صحیح اگر هر دو ورودی با یکدیگر برابر نباشند.", - "LOGIC_COMPARE_TOOLTIP_LT": "بازگرداندن صحیح اگر ورودی اول کوچکتر از ورودی دوم باشد.", - "LOGIC_COMPARE_TOOLTIP_LTE": "بازگرداندن صحیح اگر ورودی اول کوچکتر یا مساوی با ورودی دوم باشد.", - "LOGIC_COMPARE_TOOLTIP_GT": "بازگرداندن صحیح اگر ورودی اول بزرگتر از ورودی دوم باشد.", - "LOGIC_COMPARE_TOOLTIP_GTE": "بازگرداندن صحیح اگر ورودی اول بزرگتر یا مساوی یا ورودی دوم باشد.", - "LOGIC_OPERATION_TOOLTIP_AND": "بازگرداندن صحیح اگر هر دو ورودی صحیح باشد.", - "LOGIC_OPERATION_AND": "و", - "LOGIC_OPERATION_TOOLTIP_OR": "بازگرداندن صحیح اگر یکی از دو ورودی صحیح باشد.", - "LOGIC_OPERATION_OR": "یا", - "LOGIC_NEGATE_TITLE": "نه %1", - "LOGIC_NEGATE_TOOLTIP": "صجیج باز می‌گرداند اگر ورودی نا صحیح باشند. ناصحیح بازمی‌گرداند اگر ورودی صحیح باشد.", - "LOGIC_BOOLEAN_TRUE": "درست", - "LOGIC_BOOLEAN_FALSE": "نادرست", - "LOGIC_BOOLEAN_TOOLTIP": "بازگرداندن یکی از صحیح یا ناصحیح.", - "LOGIC_NULL": "پةتی/خالی", - "LOGIC_NULL_TOOLTIP": "تهی باز می گرداند", - "LOGIC_TERNARY_CONDITION": "آزمائشت", - "LOGIC_TERNARY_IF_TRUE": "اگر درست", - "LOGIC_TERNARY_IF_FALSE": "اگر نادرست", - "LOGIC_TERNARY_TOOLTIP": "بررسی وضعیت در «آزمایش». اگر وضعیت صحیح باشد، مقدار «اگر صحیح» را بر می‌گرداند در غیر اینصورت مقدار «اگر ناصحیح» را.", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "شؤمارە یەک", - "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/Arithmetic", - "MATH_ARITHMETIC_TOOLTIP_ADD": "بازگرداندن مقدار جمع دو عدد.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "بازگرداندن تفاوت دو عدد.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "بازگرداندن حاصلضرب دو عدد.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "بازگرداندن باقی‌ماندهٔ دو عدد.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "بازگرداندن اولین عددی که از توان عدد دوم حاصل شده باشد.", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "ریشهٔ دوم", - "MATH_SINGLE_TOOLTIP_ROOT": "ریشهٔ دوم یک عدد را باز می‌گرداند.", - "MATH_SINGLE_OP_ABSOLUTE": "مطلق", - "MATH_SINGLE_TOOLTIP_ABS": "قدر مطلق یک عدد را بازمی‌گرداند.", - "MATH_SINGLE_TOOLTIP_NEG": "منفی‌شدهٔ یک عدد را باز می‌گرداند.", - "MATH_SINGLE_TOOLTIP_LN": "لوگاریتم طبیعی یک عدد را باز می‌گرداند.", - "MATH_SINGLE_TOOLTIP_LOG10": "بازگرداندن لگاریتم بر پایهٔ ۱۰ یک عدد.", - "MATH_SINGLE_TOOLTIP_EXP": "بازگرداندن توان e یک عدد.", - "MATH_SINGLE_TOOLTIP_POW10": "بازگرداندن توان ۱۰ یک عدد.", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "بازگرداندن سینوس درجه (نه رادیان).", - "MATH_TRIG_TOOLTIP_COS": "بازگرداندن کسینوس درجه (نه رادیان).", - "MATH_TRIG_TOOLTIP_TAN": "بازگرداندن تانژانت یک درجه (نه رادیان).", - "MATH_TRIG_TOOLTIP_ASIN": ".(بازگرداندن آرک‌سینوس درجه (نه رادیان", - "MATH_TRIG_TOOLTIP_ACOS": "بازگرداندن آرک‌کسینوس درجه (نه رادیان).", - "MATH_TRIG_TOOLTIP_ATAN": "بازگرداندن آرک‌تانژانت درجه (نه رادیان).", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "یکی از مقادیر مشترک را برمی‌گرداند: π (۳٫۱۴۱…)، e (۲٫۷۱۸...)، φ (۱٫۶۱۸)، sqrt(۲) (۱٫۴۱۴)، sqrt(۱/۲) (۰٫۷۰۷...) و یا ∞ (بی‌نهایت).", - "MATH_IS_EVEN": "زوج است", - "MATH_IS_ODD": "فرد است", - "MATH_IS_PRIME": "عدد اول است", - "MATH_IS_WHOLE": "کامل است", - "MATH_IS_POSITIVE": "مثبت است", - "MATH_IS_NEGATIVE": "منفی است", - "MATH_IS_DIVISIBLE_BY": "تقسیم شده بر", - "MATH_IS_TOOLTIP": "بررسی می‌کند که آیا یک عدد زوج، فرد، اول، کامل، مثبت، منفی یا بخش‌پذیر عدد خاصی باشد را بررسی می‌کند. درست یا نادرست باز می‌گرداند.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "تغییر %1 با %2", - "MATH_CHANGE_TOOLTIP": "افزودن یک عدد به متغیر '%1'.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "گردکردن یک عدد به بالا یا پایین.", - "MATH_ROUND_OPERATOR_ROUND": "گردکردن", - "MATH_ROUND_OPERATOR_ROUNDUP": "گرد به بالا", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "گرد به پایین", - "MATH_ONLIST_OPERATOR_SUM": "جمع لیست", - "MATH_ONLIST_TOOLTIP_SUM": "جمع همهٔ عددهای فهرست را باز می‌گرداند.", - "MATH_ONLIST_OPERATOR_MIN": "گوجةرتةرین لیست", - "MATH_ONLIST_TOOLTIP_MIN": "کوچک‌ترین عدد در فهرست را باز می‌گرداند.", - "MATH_ONLIST_OPERATOR_MAX": "بزرگ‌ترین فهرست", - "MATH_ONLIST_TOOLTIP_MAX": "بزرگ‌ترین عدد در فهرست را باز می‌گرداند.", - "MATH_ONLIST_OPERATOR_AVERAGE": "میانگین فهرست", - "MATH_ONLIST_TOOLTIP_AVERAGE": "میانگین (میانگین ریاضی) مقادیر عددی فهرست را بر می‌گرداند.", - "MATH_ONLIST_OPERATOR_MEDIAN": "میانهٔ فهرست", - "MATH_ONLIST_TOOLTIP_MEDIAN": "میانهٔ عدد در فهرست را بر می‌گرداند.", - "MATH_ONLIST_OPERATOR_MODE": "مد فهرست", - "MATH_ONLIST_TOOLTIP_MODE": "شایع‌ترین قلم(های) در فهرست را بر می‌گرداند.", - "MATH_ONLIST_OPERATOR_STD_DEV": "انحراف معیار فهرست", - "MATH_ONLIST_TOOLTIP_STD_DEV": "انحراف معیار فهرست را بر می‌گرداند.", - "MATH_ONLIST_OPERATOR_RANDOM": "مورد تصادفی از فهرست", - "MATH_ONLIST_TOOLTIP_RANDOM": "موردی تصادفی از فهرست را بر می‌گرداند.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "باقی‌ماندهٔ %1 + %2", - "MATH_MODULO_TOOLTIP": "باقی‌ماندهٔ تقسیم دو عدد را بر می‌گرداند.", - "MATH_CONSTRAIN_TITLE": "محدودکردن %1 پایین %2 بالا %3", - "MATH_CONSTRAIN_TOOLTIP": "محدودکردن یک عدد بین محدودیت‌های مشخص‌شده (بسته).", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "عدد صحیح تصادفی بین %1 تا %2", - "MATH_RANDOM_INT_TOOLTIP": "یک عدد تصادفی بین دو مقدار مشخص‌شده به صورت بسته باز می‌گرداند.", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "کسر تصادفی", - "MATH_RANDOM_FLOAT_TOOLTIP": "بازگرداندن کسری تصادفی بین ۰٫۰ (بسته) تا ۱٫۰ (باز).", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "یک حرف، کلمه یا خطی از متن.", - "TEXT_JOIN_TITLE_CREATEWITH": "ایجاد متن با", - "TEXT_JOIN_TOOLTIP": "یک تکه‌ای از متن را با چسپاندن همهٔ تعداد از موارد ایجاد می‌کند.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "نام نؤیسی", - "TEXT_CREATE_JOIN_TOOLTIP": "اضافه‌کردن، حذف یا مرتب‌سازی بحش‌ها برای تنظیم مجدد این بلوک متنی.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "افزودن یک مورد به متن.", - "TEXT_APPEND_TO": "به", - "TEXT_APPEND_APPENDTEXT": "چسباندن متن", - "TEXT_APPEND_TOOLTIP": "الحاق متنی به متغیر «%1».", - "TEXT_LENGTH_TITLE": "طول %1", - "TEXT_LENGTH_TOOLTIP": "بازگرداندن عددی از حروف (شامل فاصله‌ها) در متن فراهم‌شده.", - "TEXT_ISEMPTY_TITLE": "%1 خالی است", - "TEXT_ISEMPTY_TOOLTIP": "اضافه‌کردن صحیح اگر متن فراهم‌شده خالی است.", - "TEXT_INDEXOF_TOOLTIP": "شاخصی از اولین آخرین رخ‌داد متن اول در متن دوم بر می‌گرداند. اگر متن یافت نشد %1 باز می‌گرداند.", - "TEXT_INDEXOF_INPUT_INTEXT": "در متن", - "TEXT_INDEXOF_OPERATOR_FIRST": "اولین رخداد متن را بیاب", - "TEXT_INDEXOF_OPERATOR_LAST": "آخرین رخداد متن را بیاب", - "TEXT_CHARAT_INPUT_INTEXT": "در متن", - "TEXT_CHARAT_FROM_START": "گرفتن حرف #", - "TEXT_CHARAT_FROM_END": "گرفتن حرف # از آخر", - "TEXT_CHARAT_FIRST": "گرفتن اولین حرف", - "TEXT_CHARAT_LAST": "گرفتن آخرین حرف", - "TEXT_CHARAT_RANDOM": "گرفتن حرف تصادفی", - "TEXT_CHARAT_TOOLTIP": "حرفی در موقعیت مشخص‌شده بر می‌گرداند.", - "TEXT_GET_SUBSTRING_TOOLTIP": "قسمت مشخصی‌شده‌ای از متن را بر می‌گرداند.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "در متن", - "TEXT_GET_SUBSTRING_START_FROM_START": "گرفتن زیرمتن از حرف #", - "TEXT_GET_SUBSTRING_START_FROM_END": "گرفتن زیرمتن از حرف # به انتها", - "TEXT_GET_SUBSTRING_START_FIRST": "گرفتن زیرمتن از اولین حرف", - "TEXT_GET_SUBSTRING_END_FROM_START": "به حرف #", - "TEXT_GET_SUBSTRING_END_FROM_END": "به حرف # از انتها", - "TEXT_GET_SUBSTRING_END_LAST": "به آخرین حرف", - "TEXT_CHANGECASE_TOOLTIP": "بازگرداندن کپی متن در حالتی متفاوت.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "به حروف بزرگ", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "به حروف کوچک", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "به حروف بزرگ عنوان", - "TEXT_TRIM_TOOLTIP": "کپی از متن با فاصله‌های حذف‌شده از یک یا هر دو پایان باز می‌گرداند.", - "TEXT_TRIM_OPERATOR_BOTH": "تراشیدن فاصله‌ها از هر دو طرف", - "TEXT_TRIM_OPERATOR_LEFT": "تراشیدن فاصله‌ها از طرف چپ", - "TEXT_TRIM_OPERATOR_RIGHT": "تراشیدن فاصله‌ها از طرف چپ", - "TEXT_PRINT_TITLE": "چاپ %1", - "TEXT_PRINT_TOOLTIP": "چاپ متن، عدد یا هر مقدار دیگر مشخص‌شده.", - "TEXT_PROMPT_TYPE_TEXT": "اعلان برای متن با پیام", - "TEXT_PROMPT_TYPE_NUMBER": "اعلان برای عدد با پیام", - "TEXT_PROMPT_TOOLTIP_NUMBER": "اعلان برای کاربر با یک عدد.", - "TEXT_PROMPT_TOOLTIP_TEXT": "اعلان برای کاربر برای یک متن.", - "LISTS_CREATE_EMPTY_TITLE": "ایجاد فهرست خالی", - "LISTS_CREATE_EMPTY_TOOLTIP": "فهرستی با طول صفر شامل هیچ رکورد داده‌ای بر می‌گرداند.", - "LISTS_CREATE_WITH_TOOLTIP": "فهرستی از هر عددی از موارد می‌سازد.", - "LISTS_CREATE_WITH_INPUT_WITH": "ایجاد فهرست با", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "لیست", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "اضافه‌کردن، حذف‌کردن یا ترتیب‌سازی مجدد بخش‌ها این بلوک فهرستی.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "اضافه‌کردن یک مورد به فهرست.", - "LISTS_REPEAT_TOOLTIP": "فهرستی شامل مقادیر داده‌شدهٔ تکرار شده عدد مشخص‌شده می‌سازد.", - "LISTS_REPEAT_TITLE": "فهرستی با %1 تکرارشده به اندازهٔ %2 می‌سازد", - "LISTS_LENGTH_TITLE": "طول %1", - "LISTS_LENGTH_TOOLTIP": "طول یک فهرست را برمی‌گرداند.", - "LISTS_ISEMPTY_TITLE": "%1 خالی است", - "LISTS_ISEMPTY_TOOLTIP": "اگر فهرست خالی است مقدار صجیج بر می‌گرداند.", - "LISTS_INLIST": "در فهرست", - "LISTS_INDEX_OF_FIRST": "یافتن اولین رخ‌داد مورد", - "LISTS_INDEX_OF_LAST": "یافتن آخرین رخ‌داد مورد", - "LISTS_INDEX_OF_TOOLTIP": "شاخصی از اولین/آخرین رخ‌داد مورد در فهرست را بر می‌گرداند. %1 بر می‌گرداند اگر آیتم موجود نبود.", - "LISTS_GET_INDEX_GET": "گِرتِن", - "LISTS_GET_INDEX_GET_REMOVE": "گِرتِن و حةذف کردن", - "LISTS_GET_INDEX_REMOVE": "حةذف کردن", - "LISTS_GET_INDEX_FROM_END": "# إژ دؤما آخر", - "LISTS_GET_INDEX_FIRST": "إژ أؤةل", - "LISTS_GET_INDEX_LAST": "دؤمائن/آخرین", - "LISTS_GET_INDEX_RANDOM": "بةختةکی", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 اولین مورد است.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 آخرین مورد است.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "موردی در محل مشخص‌شده بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "اولین مورد یک فهرست را بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "آخرین مورد در یک فهرست را بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "یک مورد تصادفی در یک فهرست بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "مورد در محل مشخص‌شده در فهرست را حذف و بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "اولین مورد مشخص‌شده در فهرست را حذف و بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "آخرین مورد مشخص‌شده در فهرست را حذف و بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "مورد تصادفی‌ای را در فهرست حذف و بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "مورد مشخص‌شده در موقعیت مشخص در یک فهرست را حذف و بر می‌گرداند.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "اولین مورد را در یک فهرست حذف می‌کند.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "آخرین مورد را در یک فهرست حذف می‌کند.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "یک مورد تصادفی را یک فهرست حذف می‌کند.", - "LISTS_SET_INDEX_SET": "مجموعه", - "LISTS_SET_INDEX_INSERT": "درج در", - "LISTS_SET_INDEX_INPUT_TO": "به عنوان", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "مورد مشخص‌شده در یک فهرست را قرار می‌دهد.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "اولین مورد در یک فهرست را تعیین می‌کند.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "آخرین مورد در یک فهرست را تعیین می‌کند.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "یک مورد تصادفی در یک فهرست را تعیین می‌کند.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "موردی در موقعیت مشخص‌شده در یک فهرست اضافه می‌کند.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "موردی به ته فهرست اضافه می‌کند.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "موردی به ته فهرست الحاق می‌کند.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "مورد را به صورت تصادفی در یک فهرست می‌افزاید.", - "LISTS_GET_SUBLIST_START_FROM_START": "گرفتن زیرمجموعه‌ای از #", - "LISTS_GET_SUBLIST_START_FROM_END": "گرفتن زیرمجموعه‌ای از # از انتها", - "LISTS_GET_SUBLIST_START_FIRST": "گرفتن زیرمجموعه‌ای از ابتدا", - "LISTS_GET_SUBLIST_END_FROM_START": "به #", - "LISTS_GET_SUBLIST_END_FROM_END": "به # از انتها", - "LISTS_GET_SUBLIST_END_LAST": "به آخرین", - "LISTS_GET_SUBLIST_TOOLTIP": "کپی از قسمت مشخص‌شدهٔ لیست درست می‌کند.", - "LISTS_SPLIT_LIST_FROM_TEXT": "ساخت لیست إژ متن", - "LISTS_SPLIT_TEXT_FROM_LIST": "ساخت متن إژ لیست", - "LISTS_SPLIT_WITH_DELIMITER": "همراه جداساز", - "VARIABLES_GET_TOOLTIP": "مقدار این متغیر را بر می‌گرداند.", - "VARIABLES_GET_CREATE_SET": "درست‌کردن «تنظیم %1»", - "VARIABLES_SET": "مجموعه %1 به %2", - "VARIABLES_SET_TOOLTIP": "متغیر برابر با خروجی را مشخص می‌کند.", - "VARIABLES_SET_CREATE_GET": "درست‌کردن «گرفتن %1»", - "PROCEDURES_DEFNORETURN_TITLE": "به", - "PROCEDURES_DEFNORETURN_PROCEDURE": "انجام چیزی", - "PROCEDURES_BEFORE_PARAMS": "با:", - "PROCEDURES_CALL_BEFORE_PARAMS": "با:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "تابعی می‌سازد بدون هیچ خروجی.", - "PROCEDURES_DEFRETURN_RETURN": "بازگشت", - "PROCEDURES_DEFRETURN_TOOLTIP": "تابعی با یک خروجی می‌سازد.", - "PROCEDURES_ALLOW_STATEMENTS": "اجازه اظهارات", - "PROCEDURES_DEF_DUPLICATE_WARNING": "اخطار: این تابعی پارامتر تکراری دارد.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "اجرای تابع تعریف‌شده توسط کاربر «%1».", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "اجرای تابع تعریف‌شده توسط کاربر «%1» و استفاده از خروجی آن.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "ورودی‌ها", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "افزودن، حذف یا دوباره مرتب‌کردن ورودی این تابع.", - "PROCEDURES_MUTATORARG_TITLE": "نام ورودی:", - "PROCEDURES_MUTATORARG_TOOLTIP": "اضافه کردن ورودی به تابع.", - "PROCEDURES_HIGHLIGHT_DEF": "برجسته‌سازی تعریف تابع", - "PROCEDURES_CREATE_DO": "ساختن «%1»", - "PROCEDURES_IFRETURN_TOOLTIP": "اگر یک مقدار صحیح است، مقدار دوم را برگردان.", - "PROCEDURES_IFRETURN_WARNING": "اخطار: این بلوک احتمالاً فقط داخل یک تابع استفاده می‌شود." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/lrc.json b/backend/_pv_1_3_5/static/blockly/msg/json/lrc.json deleted file mode 100755 index 6877555b1..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/lrc.json +++ /dev/null @@ -1,133 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Mogoeilor" - ] - }, - "VARIABLES_DEFAULT_NAME": "قلم", - "TODAY": "ئمروٙ", - "DUPLICATE_BLOCK": "کپی کردن", - "ADD_COMMENT": "نظرتونه اضاف بکید", - "REMOVE_COMMENT": "نظر جا وه جا کو", - "EXTERNAL_INPUTS": "داده یا وه دری", - "INLINE_INPUTS": "داده یا مئنجا", - "DELETE_BLOCK": "پاکسا کردن برشت", - "DELETE_X_BLOCKS": "پاکسا کردن%1 د برشتیا", - "COLLAPSE_BLOCK": "کوچک کردن برشت", - "COLLAPSE_ALL": "کوچک کردن برشتیا", - "EXPAND_BLOCK": "گپ کردن برشت", - "EXPAND_ALL": "گپ کردن برشتیا", - "DISABLE_BLOCK": "ناکشتگر کردن برشت", - "ENABLE_BLOCK": "کنشتگر کردن برشت", - "HELP": "هومياری", - "CHANGE_VALUE_TITLE": "ارزشت آلشت کو:", - "RENAME_VARIABLE": "د نو نوم نیائن آلشتگر...", - "RENAME_VARIABLE_TITLE": "د نو نوم نیائن %1 د تموم آلشتگریا د:", - "NEW_VARIABLE": "آلشتگر تازه...", - "NEW_VARIABLE_TITLE": "نوم آلشتگر تازه:", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "یه رن د رنگ دو انتخاو بکید", - "COLOUR_RANDOM_TITLE": "رن بختکی", - "COLOUR_RANDOM_TOOLTIP": "یه رنگ بختکی انتخاو بکید", - "COLOUR_RGB_TITLE": "رن وا", - "COLOUR_RGB_RED": "سور", - "COLOUR_RGB_GREEN": "سوز", - "COLOUR_RGB_BLUE": "آوی", - "COLOUR_BLEND_TITLE": "شیوسته", - "COLOUR_BLEND_COLOUR1": "رن 1", - "COLOUR_BLEND_COLOUR2": "رن 2", - "COLOUR_BLEND_RATIO": "نسوت", - "COLOUR_BLEND_TOOLTIP": "هر کوم د رنگیانه وا نسوت دائه بیه به شیون(0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "%1 تکرار کو چن بار", - "CONTROLS_REPEAT_INPUT_DO": "انجوم بئه", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "تا تکرار کو", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "تا تکرار کو", - "CONTROLS_FOR_TITLE": "اشماردن وا %1 د %2 سی %3 وا %4", - "CONTROLS_FOREACH_TITLE": "سی هر قلم %1 د نوم گه %2", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "حلقه نه خراو کو", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "حلقه شومل بیه نه خراو کو", - "CONTROLS_IF_MSG_IF": "ار", - "CONTROLS_IF_MSG_ELSEIF": "هنی ار", - "CONTROLS_IF_MSG_ELSE": "هنی", - "LOGIC_OPERATION_AND": "و", - "LOGIC_OPERATION_OR": "یا", - "LOGIC_NEGATE_TITLE": "نه %1", - "LOGIC_BOOLEAN_TRUE": "راست و دوروست", - "LOGIC_BOOLEAN_FALSE": "غلط", - "LOGIC_BOOLEAN_TOOLTIP": "هم غلط و هم راس ورگن", - "LOGIC_NULL": "خمثی", - "LOGIC_TERNARY_CONDITION": "آزماشت کردن", - "LOGIC_TERNARY_IF_TRUE": "ار درس بی", - "LOGIC_TERNARY_IF_FALSE": "ار غلط بی", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "یه شماره.", - "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/Arithmetic", - "MATH_ARITHMETIC_TOOLTIP_ADD": "وه انازه دو گل شماره ورگن.", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "چارسوک ریشه", - "MATH_SINGLE_OP_ABSOLUTE": "تموم و کمال", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_IS_EVEN": "همیشه هیئش", - "MATH_IS_ODD": "تهنائه", - "MATH_IS_PRIME": "وه اوله", - "MATH_IS_WHOLE": "همشه", - "MATH_IS_POSITIVE": "مثبته", - "MATH_IS_NEGATIVE": "منفیه", - "MATH_IS_DIVISIBLE_BY": "یه وا بهر بیه", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "آلشت بكيد %1 وا %2", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_OPERATOR_ROUND": "گرد کردن", - "MATH_ROUND_OPERATOR_ROUNDUP": "وه رو گرد کردن", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "وه هار گرد کردن", - "MATH_ONLIST_OPERATOR_SUM": "جم کردن نومگه", - "MATH_ONLIST_OPERATOR_MIN": "کمترونه د نومگه", - "MATH_ONLIST_OPERATOR_MAX": "بیشترونه د نومگه", - "MATH_ONLIST_OPERATOR_AVERAGE": "مینجاگه نوم گه", - "MATH_ONLIST_OPERATOR_MEDIAN": "مینجا نوم گه", - "MATH_ONLIST_OPERATOR_MODE": "بیشری د نومگه", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_JOIN_TITLE_CREATEWITH": "راس کردن متن وا", - "TEXT_CREATE_JOIN_TITLE_JOIN": "پیوسن", - "TEXT_APPEND_TO": "سی", - "TEXT_ISEMPTY_TITLE": "%1 حالیه", - "TEXT_INDEXOF_INPUT_INTEXT": "د متن", - "TEXT_CHARAT_INPUT_INTEXT": "د متن", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "د متن", - "TEXT_GET_SUBSTRING_END_FROM_START": "سی واج#", - "TEXT_GET_SUBSTRING_END_FROM_END": "سی واج# تا آخر", - "TEXT_GET_SUBSTRING_END_LAST": "سی آخرین واج", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "سی حرف گپ", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "سی واج کؤچک", - "LISTS_CREATE_EMPTY_TITLE": "یه گل نوم گه حالی راس بکیت", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "نوم گه", - "LISTS_ISEMPTY_TITLE": "%1 حالیه", - "LISTS_INLIST": "د نوم گه", - "LISTS_GET_INDEX_GET": "گرتن", - "LISTS_GET_INDEX_GET_REMOVE": "گرتن و جاوه جا بیئن", - "LISTS_GET_INDEX_REMOVE": "ؤرداشتن", - "LISTS_GET_INDEX_FROM_END": "# تا آخر", - "LISTS_GET_INDEX_FIRST": "اولی", - "LISTS_GET_INDEX_LAST": "آخر", - "LISTS_GET_INDEX_RANDOM": "بختكی", - "LISTS_SET_INDEX_INSERT": "بنه د", - "LISTS_SET_INDEX_INPUT_TO": "چی", - "LISTS_GET_SUBLIST_END_FROM_START": "سی#", - "LISTS_GET_SUBLIST_END_LAST": "سی آخر", - "VARIABLES_SET": "میزوکاری %1 سی %2", - "PROCEDURES_DEFNORETURN_TITLE": "سی", - "PROCEDURES_DEFNORETURN_PROCEDURE": "یه کار انجوم بیئت", - "PROCEDURES_BEFORE_PARAMS": "وا:", - "PROCEDURES_CALL_BEFORE_PARAMS": "وا:", - "PROCEDURES_DEFRETURN_RETURN": "ورگنیئن", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_MUTATORCONTAINER_TITLE": "داده یا", - "PROCEDURES_MUTATORARG_TITLE": "نوم داده:", - "PROCEDURES_CREATE_DO": "راس کردن%1" -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/lt.json b/backend/_pv_1_3_5/static/blockly/msg/json/lt.json deleted file mode 100755 index c4198f7b9..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/lt.json +++ /dev/null @@ -1,257 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Eitvys200", - "Jurgis", - "Zygimantus" - ] - }, - "VARIABLES_DEFAULT_NAME": "elementas", - "TODAY": "Šiandien", - "DUPLICATE_BLOCK": "Kopijuoti", - "ADD_COMMENT": "Palikti komentarą", - "REMOVE_COMMENT": "Pašalinti komentarą", - "EXTERNAL_INPUTS": "Išdėstyti stulpeliu, kai daug parametrų", - "INLINE_INPUTS": "Išdėstyti vienoje eilutėje", - "DELETE_BLOCK": "Ištrinti bloką", - "DELETE_X_BLOCKS": "Ištrinti %1 blokus", - "DELETE_ALL_BLOCKS": "Ištrinti visus %1 blokus?", - "CLEAN_UP": "Išvalyti blokus", - "COLLAPSE_BLOCK": "Suskleisti bloką", - "COLLAPSE_ALL": "Suskleisti blokus", - "EXPAND_BLOCK": "Išskleisti bloką", - "EXPAND_ALL": "Išskleisti blokus", - "DISABLE_BLOCK": "Išjungti bloką", - "ENABLE_BLOCK": "Įjungti bloką", - "HELP": "Pagalba", - "UNDO": "Anuliuoti", - "REDO": "Atkurti", - "CHANGE_VALUE_TITLE": "Keisti reikšmę:", - "RENAME_VARIABLE": "Pervardyti kintamajį...", - "RENAME_VARIABLE_TITLE": "Pervadinti visus '%1' kintamuosius į:", - "NEW_VARIABLE": "Naujas kintamasis...", - "NEW_VARIABLE_TITLE": "Naujo kintamojo pavadinimas:", - "DELETE_VARIABLE": "Ištrinti '%1' kintamąjį", - "COLOUR_PICKER_HELPURL": "https://lt.wikipedia.org/wiki/Spalva", - "COLOUR_PICKER_TOOLTIP": "Pasirinkti spalvą iš paletės.", - "COLOUR_RANDOM_TITLE": "atsitiktinė spalva", - "COLOUR_RANDOM_TOOLTIP": "Pasirinkti spalvą atsitiktinai.", - "COLOUR_RGB_TITLE": "spalva su", - "COLOUR_RGB_RED": "raudona", - "COLOUR_RGB_GREEN": "žalia", - "COLOUR_RGB_BLUE": "mėlyna", - "COLOUR_RGB_TOOLTIP": "Spalvą galima sudaryti iš raudonos, žalios ir mėlynos dedamųjų. Kiekvienos intensyvumas nuo 0 iki 100.", - "COLOUR_BLEND_TITLE": "sumaišyk", - "COLOUR_BLEND_COLOUR1": "1 spalva", - "COLOUR_BLEND_COLOUR2": "2 spalva", - "COLOUR_BLEND_RATIO": "santykis", - "COLOUR_BLEND_TOOLTIP": "Sumaišo dvi spalvas su pateiktu santykiu (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "pakartokite %1 kartus", - "CONTROLS_REPEAT_INPUT_DO": "daryti", - "CONTROLS_REPEAT_TOOLTIP": "Leidžia atlikti išvardintus veiksmus kelis kartus.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "kartok kol", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "kartok, kol pasieksi", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Kartoja veiksmus, kol sąlyga tenkinama.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Kartoja veiksmus, kol bus pasiekta nurodyta sąlyga.", - "CONTROLS_FOR_TOOLTIP": "Kartoti veiksmus su kiekvienu sąrašo elementu, priskirtu kintamajam \"%1\".", - "CONTROLS_FOR_TITLE": "kartok, kai %1 kinta nuo %2 iki %3 po %4", - "CONTROLS_FOREACH_TITLE": "kartok su kiekvienu %1 iš sąrašo %2", - "CONTROLS_FOREACH_TOOLTIP": "Kartok veiksmus, kol kintamasis \"%1\" paeiliui gauna kiekvieną sąrašo reikšmę.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "nutraukti kartojimą", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "šį kartą praleisti likusius veiksmus ir tęsti kartojimą", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Nutraukia (artimiausią) vykstantį kartojimą.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Praleidžia žemiau išvardintus kartojimo veiksmus (ir tęsia darbą nuo kartojimo pradinio veiksmo).", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Atsargiai: šis blokas gali būt naudojamas tik kartojimo bloko viduje.", - "CONTROLS_IF_TOOLTIP_1": "Jeigu sąlyga tenkinama, tai atlik veiksmus.", - "CONTROLS_IF_TOOLTIP_2": "Jei sąlyga tenkinama, atlikti jai priklausančius veiksmus, o jei ne -- atlikti kitus nurodytus veiksmus.", - "CONTROLS_IF_TOOLTIP_3": "Jei pirma sąlyga tenkinama, atlikti jai priklausančius veiksmus, O jei ne, tikrinti antrą sąlygą -- ir jei ši tenkinama, atlikti jos veiksmus.", - "CONTROLS_IF_TOOLTIP_4": "Jei pirma sąlyga tenkinama, atlikti jai priklausančius veiksmus, O jei ne, tikrinti antrą sąlygą -- ir jei ši tenkinama, atlikti jos veiksmus. Kitais atvejais -- atlikti paskutinio bloko veiksmus.", - "CONTROLS_IF_MSG_IF": "jei", - "CONTROLS_IF_MSG_ELSEIF": "arba jei", - "CONTROLS_IF_MSG_ELSE": "kitu atveju", - "CONTROLS_IF_IF_TOOLTIP": "Galite pridėt/pašalinti/pertvarkyti sąlygų \"šakas\".", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Pridėti sąlygą „jei“ blokui.", - "CONTROLS_IF_ELSE_TOOLTIP": "Pridėti veiksmų vykdymo variantą/\"šaką\", kai netenkinama nė viena sąlyga.", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Tenkinama, jei abu reiškiniai lygūs.", - "LOGIC_OPERATION_TOOLTIP_AND": "Bus teisinga, kai abi sąlygos bus tenkinamos.", - "LOGIC_OPERATION_AND": "ir", - "LOGIC_OPERATION_OR": "arba", - "LOGIC_NEGATE_TITLE": "ne %1", - "LOGIC_BOOLEAN_TRUE": "tiesa", - "LOGIC_BOOLEAN_FALSE": "klaidinga", - "LOGIC_BOOLEAN_TOOLTIP": "Reikšmė gali būti \"teisinga\"/\"Taip\" arba \"klaidinga\"/\"Ne\".", - "LOGIC_NULL": "nieko", - "LOGIC_NULL_TOOLTIP": "Reikšmė nebuvo nurodyta...", - "LOGIC_TERNARY_CONDITION": "sąlyga", - "LOGIC_TERNARY_IF_TRUE": "jei taip", - "LOGIC_TERNARY_IF_FALSE": "jei ne", - "LOGIC_TERNARY_TOOLTIP": "Jeigu sąlygą tenkinama, grąžina pirmą reikšmę, o jei ne - antrąją.", - "MATH_NUMBER_HELPURL": "https://lt.wikipedia.org/wiki/Skaičius", - "MATH_NUMBER_TOOLTIP": "Skaičius.", - "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/Arithmetic", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Grąžina dviejų skaičių sumą.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Grąžina dviejų skaičių skirtumą.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Grąžina dviejų skaičių sandaugą.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Grąžina dviejų skaičių dalmenį.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Grąžina pirmą skaičių pakeltą laipsniu pagal antrą skaičių.", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "kvadratinė šaknis", - "MATH_SINGLE_OP_ABSOLUTE": "modulis", - "MATH_SINGLE_TOOLTIP_ABS": "Skaičiaus modulis - reikšmė be ženklo (panaikina minusą).", - "MATH_SINGLE_TOOLTIP_NEG": "Grąžina skaičiui priešingą skaičių.", - "MATH_SINGLE_TOOLTIP_LN": "Grąžinti skaičiaus natūrinį logaritmą.", - "MATH_SINGLE_TOOLTIP_EXP": "Grąžinti skaičių laipsniu e.", - "MATH_SINGLE_TOOLTIP_POW10": "Grąžinti skaičių laipsniu 10.", - "MATH_TRIG_HELPURL": "https://lt.wikipedia.org/wiki/Trigonometrinės_funkcijos", - "MATH_TRIG_TOOLTIP_SIN": "Grąžinti laipsnio sinusą (ne radiano).", - "MATH_TRIG_TOOLTIP_COS": "Grąžinti laipsnio kosinusą (ne radiano).", - "MATH_TRIG_TOOLTIP_TAN": "Grąžinti laipsnio tangentą (ne radiano).", - "MATH_TRIG_TOOLTIP_ASIN": "Grąžinti skaičiaus arksinusą.", - "MATH_TRIG_TOOLTIP_ACOS": "Grąžinti skaičiaus arkkosinusą.", - "MATH_TRIG_TOOLTIP_ATAN": "Grąžinti skaičiaus arktangentą.", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_IS_EVEN": "yra lyginis", - "MATH_IS_ODD": "yra nelyginis", - "MATH_IS_PRIME": "yra pirminis", - "MATH_IS_WHOLE": "yra sveikasis", - "MATH_IS_POSITIVE": "yra teigiamas", - "MATH_IS_NEGATIVE": "yra neigiamas", - "MATH_IS_DIVISIBLE_BY": "yra dalus iš", - "MATH_IS_TOOLTIP": "Patikrina skaičiaus savybę: (ne)lyginis/pirminis/sveikasis/teigiamas/neigiamas/dalus iš x.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "padidink %1 (emptypage) %2", - "MATH_CHANGE_TOOLTIP": "Prideda skaičių prie kintamojo '%1'. Kai skaičius neigiamas - gaunasi atimtis.", - "MATH_ROUND_HELPURL": "https://lt.wikipedia.org/wiki/Apvalinimas", - "MATH_ROUND_TOOLTIP": "Suapvalinti skaičių į žemesnę ar aukštesnę reikšmę.", - "MATH_ROUND_OPERATOR_ROUND": "apvalink", - "MATH_ROUND_OPERATOR_ROUNDUP": "apvalink aukštyn", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "apvalink žemyn", - "MATH_ONLIST_OPERATOR_SUM": "suma", - "MATH_ONLIST_TOOLTIP_SUM": "didžiausia reikšmė", - "MATH_ONLIST_OPERATOR_MIN": "mažiausia reikšmė sąraše", - "MATH_ONLIST_OPERATOR_MAX": "didžiausia reikšmė sąraše", - "MATH_ONLIST_OPERATOR_AVERAGE": "vidurkis", - "MATH_ONLIST_OPERATOR_MEDIAN": "mediana sąrašui", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Grąžinti sąrašo medianą.", - "MATH_ONLIST_OPERATOR_MODE": "statistinė moda sąrašui", - "MATH_ONLIST_TOOLTIP_MODE": "Grąžinti sąrašą dažniausių elementų sąraše.", - "MATH_ONLIST_OPERATOR_STD_DEV": "standartinis nuokrypis sąraše", - "MATH_ONLIST_OPERATOR_RANDOM": "atsitiktinis elementas iš sąrašo", - "MATH_ONLIST_TOOLTIP_RANDOM": "Grąžinti atsitiktinį elementą iš sąrašo.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "dalybos liekana %1 ÷ %2", - "MATH_CONSTRAIN_TITLE": "apribok %1 tarp %2 ir %3", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "atsitiktinis sveikas sk. nuo %1 iki %2", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "atsitiktinė trupmena", - "MATH_RANDOM_FLOAT_TOOLTIP": "Atsitiktinė trupmena nuo 0 (imtinai) iki 1 (neimtinai).", - "TEXT_TEXT_TOOLTIP": "Tekstas (arba žodis, ar raidė)", - "TEXT_JOIN_TITLE_CREATEWITH": "sukurti tekstą su", - "TEXT_CREATE_JOIN_TITLE_JOIN": "sujunk", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Pridėti teksto elementą.", - "TEXT_APPEND_TO": "prie", - "TEXT_APPEND_APPENDTEXT": "pridėk tekstą", - "TEXT_LENGTH_TITLE": "teksto %1 ilgis", - "TEXT_LENGTH_TOOLTIP": "Suranda teksto simbolių kiekį (įskaitant ir tarpus)", - "TEXT_ISEMPTY_TITLE": "%1 yra tuščias", - "TEXT_INDEXOF_INPUT_INTEXT": "tekste", - "TEXT_INDEXOF_OPERATOR_FIRST": "rask,kur pirmą kartą paminėta", - "TEXT_INDEXOF_OPERATOR_LAST": "rask,kur paskutinį kartą paminėta", - "TEXT_CHARAT_INPUT_INTEXT": "tekste", - "TEXT_CHARAT_FROM_START": "gauti raidę #", - "TEXT_CHARAT_FROM_END": "raidė nuo galo #", - "TEXT_CHARAT_FIRST": "gauti pirmą raidę", - "TEXT_CHARAT_LAST": "gauti paskutinę raidę", - "TEXT_CHARAT_RANDOM": "gauti atsitiktinę raidę", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "tekste", - "TEXT_GET_SUBSTRING_START_FROM_START": "dalis nuo raidės #", - "TEXT_GET_SUBSTRING_START_FROM_END": "dalis nuo raidės #", - "TEXT_GET_SUBSTRING_START_FIRST": "dalis nuo pradžios", - "TEXT_GET_SUBSTRING_END_FROM_START": "iki raidės #", - "TEXT_GET_SUBSTRING_END_FROM_END": "iki raidės nuo galo #", - "TEXT_GET_SUBSTRING_END_LAST": "iki pabaigos", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": " DIDŽIOSIOM RAIDĖM", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": " mažosiom raidėm", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": " Pavadinimo Raidėmis", - "TEXT_TRIM_OPERATOR_BOTH": "išvalyk tarpus šonuose", - "TEXT_TRIM_OPERATOR_LEFT": "išvalyk tarpus pradžioje", - "TEXT_TRIM_OPERATOR_RIGHT": "išvalyk tarpus pabaigoje", - "TEXT_PRINT_TITLE": "spausdinti %1", - "TEXT_PROMPT_TYPE_TEXT": "paprašyk įvesti tekstą :", - "TEXT_PROMPT_TYPE_NUMBER": "paprašyk įvesti skaičių :", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Prašyti vartotoją įvesti skaičių.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Prašyti vartotoją įvesti tekstą.", - "LISTS_CREATE_EMPTY_TITLE": "tuščias sąrašas", - "LISTS_CREATE_EMPTY_TOOLTIP": "Grąžina sąrašą, ilgio 0, neturintį duomenų", - "LISTS_CREATE_WITH_TOOLTIP": "Sukurti sąrašą iš bet kokio skaičiaus elementų.", - "LISTS_CREATE_WITH_INPUT_WITH": "sukurti sąrašą su", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "sąrašas", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Pridėti elementą į sąrašą.", - "LISTS_REPEAT_TITLE": "sukurk sąrašą, kuriame %1 bus %2 kartus", - "LISTS_LENGTH_TITLE": "ilgis %1", - "LISTS_LENGTH_TOOLTIP": "Grąžina sąrašo ilgį.", - "LISTS_ISEMPTY_TITLE": "%1 yra tuščias", - "LISTS_ISEMPTY_TOOLTIP": "Grąžina „true“, jeigu sąrašas tuščias.", - "LISTS_INLIST": "sąraše", - "LISTS_INDEX_OF_FIRST": "rask pirmą reikšmę", - "LISTS_INDEX_OF_LAST": "rask paskutinę reikšmę", - "LISTS_INDEX_OF_TOOLTIP": "Grąžina pirmos/paskutinės reikšmės eilės nr. sąraše. Grąžina %1, jei reikšmės neranda.", - "LISTS_GET_INDEX_GET": "paimk", - "LISTS_GET_INDEX_GET_REMOVE": "paimk ir ištrink", - "LISTS_GET_INDEX_REMOVE": "pašalinti", - "LISTS_GET_INDEX_FROM_END": "# nuo galo", - "LISTS_GET_INDEX_FIRST": "pirmas", - "LISTS_GET_INDEX_LAST": "paskutinis", - "LISTS_GET_INDEX_RANDOM": "atsitiktinis", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 yra pirmasis objektas.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 yra paskutinis objektas.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Gražina objektą į nurodyta poziciją sąraše.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Grąžina pirmąjį sąrašo elementą.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Grąžina paskutinį elementą iš sąrašo.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Grąžina atsitiktinį elementą iš sąrašo.", - "LISTS_SET_INDEX_SET": "priskirk elementui", - "LISTS_SET_INDEX_INSERT": "įterpk į vietą", - "LISTS_SET_INDEX_INPUT_TO": "kaip", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Įterpią objektą į nurodytą poziciją sąraše.", - "LISTS_GET_SUBLIST_START_FROM_START": "sąrašo dalis nuo #", - "LISTS_GET_SUBLIST_START_FROM_END": "sąrašo dalis nuo # nuo galo", - "LISTS_GET_SUBLIST_START_FIRST": "sąrašo dalis nuo pradžios", - "LISTS_GET_SUBLIST_END_FROM_START": "iki #", - "LISTS_GET_SUBLIST_END_FROM_END": "iki # nuo galo", - "LISTS_GET_SUBLIST_END_LAST": "iki galo", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "rūšiuoti %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Rūšiuoti sąrašo kopiją.", - "LISTS_SORT_ORDER_ASCENDING": "didėjančia tvarka", - "LISTS_SORT_ORDER_DESCENDING": "mažėjančia tvarka", - "LISTS_SORT_TYPE_NUMERIC": "skaitmeninis", - "LISTS_SORT_TYPE_TEXT": "abėcėlės", - "LISTS_SORT_TYPE_IGNORECASE": "abecėlės, ignoruoti raidžių dydį", - "LISTS_SPLIT_WITH_DELIMITER": "su dalikliu", - "VARIABLES_GET_CREATE_SET": "Sukurk \"priskirk %1\"", - "VARIABLES_SET": "priskirk %1 = %2", - "VARIABLES_SET_CREATE_GET": "Sukurti 'kintamasis %1'", - "PROCEDURES_DEFNORETURN_TITLE": "komanda:", - "PROCEDURES_DEFNORETURN_PROCEDURE": "daryk kažką", - "PROCEDURES_BEFORE_PARAMS": "pagal:", - "PROCEDURES_CALL_BEFORE_PARAMS": "su:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Sukuria procedūrą - komandą, kuri nepateikia jokio rezultato (tik atlieka veiksmus).", - "PROCEDURES_DEFRETURN_RETURN": "duok", - "PROCEDURES_DEFRETURN_TOOLTIP": "Sukuria funkciją - komandą, kuri ne tik atlieka veiksmus bet ir pateikia (grąžina/duoda) rezultatą.", - "PROCEDURES_ALLOW_STATEMENTS": "leisti vidinius veiksmus", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Ši komanda turi du vienodus gaunamų duomenų pavadinimus.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Vykdyti sukurtą komandą \"%1\".", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Įvykdyti komandą \"%1\" ir naudoti jos suskaičiuotą (atiduotą) reikšmę.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "gaunami duomenys (parametrai)", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Tvarkyti komandos gaunamus duomenis (parametrus).", - "PROCEDURES_MUTATORARG_TITLE": "parametro pavadinimas:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Pridėti funkcijos parametrą (gaunamų duomenų pavadinimą).", - "PROCEDURES_CREATE_DO": "Sukurti \"%1\"", - "PROCEDURES_IFRETURN_TOOLTIP": "Jeigu pirma reikšmė yra teisinga (sąlyga tenkinama), grąžina antrą reikšmę.", - "PROCEDURES_IFRETURN_WARNING": "Perspėjimas: šis blokas gali būti naudojamas tik aprašant funkciją." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/mk.json b/backend/_pv_1_3_5/static/blockly/msg/json/mk.json deleted file mode 100755 index c9f8a866e..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/mk.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Bjankuloski06" - ] - }, - "VARIABLES_DEFAULT_NAME": "елемент", - "DUPLICATE_BLOCK": "Ископирај", - "ADD_COMMENT": "Додај коментар:", - "REMOVE_COMMENT": "Отстрани коментар", - "EXTERNAL_INPUTS": "Надворешен внос", - "INLINE_INPUTS": "Внатрешен внос", - "DELETE_BLOCK": "Избриши блок", - "DELETE_X_BLOCKS": "Избриши %1 блока", - "DELETE_ALL_BLOCKS": "Да ги избришам сите %1 блокчиња?", - "COLLAPSE_BLOCK": "Собери блок", - "COLLAPSE_ALL": "Собери блокови", - "EXPAND_BLOCK": "Рашири го блокови", - "EXPAND_ALL": "Рашири блокови", - "DISABLE_BLOCK": "Исклучи блок", - "ENABLE_BLOCK": "Вклучи блок", - "HELP": "Помош", - "CHANGE_VALUE_TITLE": "Смена на вредност:", - "NEW_VARIABLE": "Нова променлива...", - "NEW_VARIABLE_TITLE": "Назив на новата променлива:", - "RENAME_VARIABLE": "Преименувај променлива...", - "RENAME_VARIABLE_TITLE": "Преименувај ги сите променливи „%1“ во:", - "COLOUR_PICKER_HELPURL": "https://mk.wikipedia.org/wiki/Боја", - "COLOUR_PICKER_TOOLTIP": "Изберете боја од палетата.", - "COLOUR_RANDOM_TITLE": "случајна боја", - "COLOUR_RANDOM_TOOLTIP": "Избери боја на тепка.", - "COLOUR_RGB_TITLE": "боја со", - "COLOUR_RGB_RED": "црвена", - "COLOUR_RGB_GREEN": "зелена", - "COLOUR_RGB_BLUE": "сина", - "COLOUR_RGB_TOOLTIP": "Создајте боја со укажаните износи на црвена, зелена и сина. Сите вредности мора да бидат помеѓу 0 и 100.", - "COLOUR_BLEND_TITLE": "смешај", - "COLOUR_BLEND_COLOUR1": "боја 1", - "COLOUR_BLEND_COLOUR2": "боја 2", - "COLOUR_BLEND_RATIO": "сооднос", - "COLOUR_BLEND_TOOLTIP": "Меша две бои во даден сооднос (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://mk.wikipedia.org/wiki/For-јамка", - "CONTROLS_REPEAT_TITLE": "повтори %1 пати", - "CONTROLS_REPEAT_INPUT_DO": "исполни", - "CONTROLS_REPEAT_TOOLTIP": "Исполнува наредби неколку пати.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "повторувај додека", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "повторувај сè до", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Додека вредноста е вистинита, исполнува наредби.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Додека вредноста е невистинита, исполнува наредби.", - "CONTROLS_FOR_TOOLTIP": "Променливата \"%1\" да ги земе вредностите од почетниот до завршниот број, броејќи според укажаниот интервал и ги исполнува укажаните блокови.", - "CONTROLS_FOR_TITLE": "број со %1 од %2 до %3 со %4", - "CONTROLS_FOREACH_TITLE": "за секој елемент %1 на списокот %2", - "CONTROLS_FOREACH_TOOLTIP": "Му ја задава променливата „%1“ на секој елемент на списокот, а потоа исполнува наредби.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "излези од јамката", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "продолжи со следното повторување на јамката", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Излези од содржечката јамка.", - "CONTROLS_IF_MSG_IF": "ако", - "CONTROLS_IF_MSG_ELSEIF": "инаку ако", - "CONTROLS_IF_MSG_ELSE": "инаку", - "CONTROLS_IF_IF_TOOLTIP": "Додава, отстранува или прередува делови за прераспоредување на овој блок „ако“.", - "LOGIC_COMPARE_HELPURL": "https://mk.wikipedia.org/wiki/Неравенство", - "LOGIC_COMPARE_TOOLTIP_EQ": "Дава вистина ако обата вноса се еднакви.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Дава вистина ако обата вноса не се еднакви.", - "LOGIC_COMPARE_TOOLTIP_LT": "Дава вистина ако првиот внос е помал од вториот.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Дава вистина ако првиот внос е помал или еднаков на вториот.", - "LOGIC_COMPARE_TOOLTIP_GT": "Дава вистина ако првиот внос е поголем од вториот.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Дава вистина ако првиот внос е поголем или еднаков на вториот.", - "LOGIC_OPERATION_TOOLTIP_AND": "Дава вистина ако обата вноса се вистинити.", - "LOGIC_OPERATION_AND": "и", - "LOGIC_OPERATION_TOOLTIP_OR": "Дава вистина ако барем еден од вносовите е вистинит.", - "LOGIC_OPERATION_OR": "или", - "LOGIC_NEGATE_TITLE": "не %1", - "LOGIC_NEGATE_TOOLTIP": "Дава вистина ако вносот е невистинит. Дава невистина ако вносот е вистинит.", - "LOGIC_BOOLEAN_TRUE": "вистина", - "LOGIC_BOOLEAN_FALSE": "невистина", - "LOGIC_BOOLEAN_TOOLTIP": "Дава или вистина или невистина.", - "LOGIC_NULL": "ништо", - "LOGIC_NULL_TOOLTIP": "Дава ништо.", - "LOGIC_TERNARY_CONDITION": "испробај", - "LOGIC_TERNARY_IF_TRUE": "ако е вистинито", - "LOGIC_TERNARY_IF_FALSE": "ако е невистинито", - "MATH_CONSTANT_HELPURL": "https://mk.wikipedia.org/wiki/Математичка_константа", - "MATH_CONSTANT_TOOLTIP": "Дава една од вообичаените константи: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), или ∞ (бесконечност).", - "MATH_IS_EVEN": "е парен", - "MATH_IS_ODD": "е непарен", - "MATH_IS_PRIME": "е прост", - "MATH_IS_WHOLE": "е цел", - "MATH_IS_POSITIVE": "е позитивен", - "MATH_IS_NEGATIVE": "е негативен", - "MATH_IS_DIVISIBLE_BY": "е делив со", - "MATH_IS_TOOLTIP": "Проверува дали бројот е парен, непарен, прост, цел, позитивен, негативен или делив со некој број. Дава вистина или невистина.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter?uselang=mk", - "MATH_CHANGE_TITLE": "повиши %1 за %2", - "MATH_CHANGE_TOOLTIP": "Ѝ додава број на променливата „%1“.", - "MATH_ROUND_HELPURL": "https://mk.wikipedia.org/wiki/Заокружување", - "MATH_ROUND_TOOLTIP": "Го заокружува бројот на поголем или помал.", - "MATH_ROUND_OPERATOR_ROUND": "заокружи", - "MATH_ROUND_OPERATOR_ROUNDUP": "заокружи на поголемо", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "заокружи на помало", - "MATH_ONLIST_OPERATOR_SUM": "збир од списокот", - "MATH_ONLIST_TOOLTIP_SUM": "Дава збир од сите броеви на списокот.", - "MATH_ONLIST_OPERATOR_MIN": "најмал на списокот", - "MATH_ONLIST_TOOLTIP_MIN": "Го дава најмалиот број на списокот.", - "MATH_ONLIST_OPERATOR_MAX": "најголем на списокот", - "MATH_ONLIST_TOOLTIP_MAX": "Го дава најголемиот број на списокот.", - "MATH_ONLIST_OPERATOR_AVERAGE": "просек на списокот", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Дава просек (аритметичка средина) од броевите на списокот.", - "MATH_ONLIST_OPERATOR_MEDIAN": "медијана на списокот", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Дава медијана од броевите на списокот.", - "MATH_ONLIST_OPERATOR_MODE": "модул на списокот", - "MATH_ONLIST_TOOLTIP_MODE": "Дава список на најзастапен(и) елемент(и) на списокот." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/ms.json b/backend/_pv_1_3_5/static/blockly/msg/json/ms.json deleted file mode 100755 index cd7d82864..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/ms.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Anakmalaysia", - "Espertus" - ] - }, - "VARIABLES_DEFAULT_NAME": "Perkara", - "TODAY": "Hari ini", - "DUPLICATE_BLOCK": "Pendua", - "ADD_COMMENT": "Berikan Komen", - "REMOVE_COMMENT": "Padamkan Komen", - "EXTERNAL_INPUTS": "Input Luaran", - "INLINE_INPUTS": "Input Sebaris", - "DELETE_BLOCK": "Hapuskan Blok", - "DELETE_X_BLOCKS": "Hapuskan %1 Blok", - "DELETE_ALL_BLOCKS": "Hapuskan kesemua %1 blok?", - "CLEAN_UP": "Kemaskan Blok", - "COLLAPSE_BLOCK": "Lipat Blok", - "COLLAPSE_ALL": "Lipat Blok²", - "EXPAND_BLOCK": "Buka Blok", - "EXPAND_ALL": "Buka Blok²", - "DISABLE_BLOCK": "Matikan Blok", - "ENABLE_BLOCK": "Hidupkan Blok", - "HELP": "Bantuan", - "CHANGE_VALUE_TITLE": "Ubah nilai:", - "RENAME_VARIABLE": "Tukar nama pembolehubah...", - "RENAME_VARIABLE_TITLE": "Tukar nama semua pembolehubah '%1' kepada:", - "NEW_VARIABLE": "Pembolehubah baru...", - "NEW_VARIABLE_TITLE": "Nama pembolehubah baru:", - "COLOUR_PICKER_HELPURL": "https://ms.wikipedia.org/wiki/Warna", - "COLOUR_PICKER_TOOLTIP": "Pilih satu warna daripada palet.", - "COLOUR_RANDOM_TITLE": "warna rawak", - "COLOUR_RANDOM_TOOLTIP": "Pilih satu warna secara rawak.", - "COLOUR_RGB_TITLE": "warnakan", - "COLOUR_RGB_RED": "merah", - "COLOUR_RGB_GREEN": "hijau", - "COLOUR_RGB_BLUE": "biru", - "COLOUR_RGB_TOOLTIP": "Peroleh satu warna dengan menentukan amaun campuran merah, hijau dan biru. Kesemua nilai haruslah antara 0 hingga 100.", - "COLOUR_BLEND_TITLE": "adun", - "COLOUR_BLEND_COLOUR1": "warna 1", - "COLOUR_BLEND_COLOUR2": "warna 2", - "COLOUR_BLEND_RATIO": "nisbah", - "COLOUR_BLEND_TOOLTIP": "Campurkan dua warna sekali pada nisbah yang ditentukan (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "ulang %1 kali", - "CONTROLS_REPEAT_INPUT_DO": "lakukan", - "CONTROLS_REPEAT_TOOLTIP": "Lakukan perintah berulang kali.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "ulangi apabila", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "ulangi sehingga", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Lakukan beberapa perintah apabila nilainya benar (true).", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Lakukan beberapa perintah apabila nilainya palsu (false).", - "CONTROLS_FOR_TOOLTIP": "Gunakan pembolehubah '%1' pada nilai-nilai dari nombor pangkal hingga nombor hujung, mengira mengikut selang yang ditentukan, dan lakukan blok-blok yang tertentu.", - "CONTROLS_FOR_TITLE": "kira dengan %1 dari %2 hingga %3 selang %4", - "CONTROLS_FOREACH_TITLE": "untuk setiap perkara %1 dalam senarai %2", - "CONTROLS_FOREACH_TOOLTIP": "Untuk setiap perkara dalam senarai, tetapkan pembolehubah '%1' pada perkara, kemudian lakukan beberapa perintah.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "hentikan gelung", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "teruskan dengan lelaran gelung seterusnya", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Keluar dari gelung pengandung.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Langkau seluruh gelung yang tinggal dan bersambung dengan lelaran seterusnya.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Amaran: Blok ini hanya boleh digunakan dalam satu gelung.", - "CONTROLS_IF_TOOLTIP_1": "Jika nilai yang benar, lakukan beberapa penyata.", - "CONTROLS_IF_TOOLTIP_2": "Jika suatu nilai benar, lakukan penyata blok pertama. Jika tidak, bina penyata blok kedua.", - "CONTROLS_IF_TOOLTIP_3": "Jika nilai yang pertama adalah benar, lakukan penyata pertama blok. Sebaliknya, jika nilai kedua adalah benar, lakukan penyata blok kedua.", - "CONTROLS_IF_TOOLTIP_4": "Jika nilai yang pertama adalah benar, lakukan penyata blok pertama. Sebaliknya, jika nilai kedua adalah benar, lakukan penyata blok kedua. Jika tiada nilai adalah benar, lakukan penyata blok terakhir.", - "CONTROLS_IF_MSG_IF": "jika", - "CONTROLS_IF_MSG_ELSEIF": "lain jika", - "CONTROLS_IF_MSG_ELSE": "lain", - "CONTROLS_IF_IF_TOOLTIP": "Tambah, alih keluar, atau susun semula bahagian-bahagian untuk menyusun semula blok jika.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Tambah satu syarat kepada blok jika.", - "CONTROLS_IF_ELSE_TOOLTIP": "Tambah yang terakhir, alihkan semua keadaan ke blok jika.", - "LOGIC_COMPARE_HELPURL": "https://id.wikipedia.org/wiki/Pertidaksamaan", - "LOGIC_COMPARE_TOOLTIP_EQ": "Kembali benar jika kedua-dua input benar antara satu sama lain.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Taip balik benar jika kedua-dua input tidak sama.", - "LOGIC_COMPARE_TOOLTIP_LT": "Kembali benar jika input pertama adalah lebih kecil daripada input kedua.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Kembali benar jika input pertama adalah lebih kecil daripada atau sama dengan input kedua.", - "LOGIC_COMPARE_TOOLTIP_GT": "Kembali benar jika input pertama adalah lebih besar daripada input kedua.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Kembali benar jika input pertama adalah lebih besar daripada atau sama dengan input kedua.", - "LOGIC_OPERATION_TOOLTIP_AND": "Return true if both inputs are true.", - "LOGIC_OPERATION_AND": "dan", - "LOGIC_OPERATION_TOOLTIP_OR": "Return true if at least one of the inputs is true.", - "LOGIC_OPERATION_OR": "atau", - "LOGIC_NEGATE_TITLE": "bukan %1", - "LOGIC_NEGATE_TOOLTIP": "'Benar' akan dibalas jika inputnya salah. 'Salah' akan dibalas jika inputnya benar.", - "LOGIC_BOOLEAN_TRUE": "benar", - "LOGIC_BOOLEAN_FALSE": "palsu", - "LOGIC_BOOLEAN_TOOLTIP": "Kembalikan samada benar atau palsu.", - "LOGIC_NULL": "null", - "LOGIC_NULL_TOOLTIP": "Returns null.", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "Jika benar", - "LOGIC_TERNARY_IF_FALSE": "Jika palsu", - "LOGIC_TERNARY_TOOLTIP": "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value.", - "MATH_NUMBER_HELPURL": "https://ms.wikipedia.org/wiki/Nombor", - "MATH_NUMBER_TOOLTIP": "Suatu nombor.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tan", - "MATH_TRIG_ASIN": "asin", - "MATH_TRIG_ACOS": "acos", - "MATH_TRIG_ATAN": "atan", - "MATH_ARITHMETIC_HELPURL": "https://ms.wikipedia.org/wiki/Aritmetik", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Kembalikan jumlah kedua-dua bilangan.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Taip balik hasil tolak dua nombor tersebut.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Taip balik hasil darab dua nombor tersebut.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Taip balik hasil bahagi dua nombor tersebut.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Return the first number raised to the power of the second number.", - "MATH_SINGLE_HELPURL": "https://ms.wikipedia.org/wiki/Punca_kuasa_dua", - "MATH_SINGLE_OP_ROOT": "Punca kuasa dua", - "MATH_SINGLE_TOOLTIP_ROOT": "Kembalikan punca kuasa nombor.", - "MATH_SINGLE_OP_ABSOLUTE": "mutlak", - "MATH_SINGLE_TOOLTIP_ABS": "Kembalikan nilai mutlak suatu nombor.", - "MATH_SINGLE_TOOLTIP_NEG": "Kembalikan nombor yang songsang.", - "MATH_SINGLE_TOOLTIP_LN": "Kembali dalam logaritma nombor asli.", - "MATH_SINGLE_TOOLTIP_LOG10": "Kembali logarithm 10 asas nombor.", - "MATH_SINGLE_TOOLTIP_EXP": "Kembalikan e kepada kuasa nombor.", - "MATH_SINGLE_TOOLTIP_POW10": "Kembalikan 10 kepada kuasa nombor.", - "MATH_TRIG_HELPURL": "https://ms.wikipedia.org/wiki/Fungsi_trigonometri", - "MATH_TRIG_TOOLTIP_SIN": "Kembalikan darjah sine (bukan radian).", - "MATH_TRIG_TOOLTIP_COS": "Kembalikan darjah kosinus (bukan radian).", - "MATH_TRIG_TOOLTIP_TAN": "Kembalikan darjah tangen (bukan radian).", - "MATH_TRIG_TOOLTIP_ASIN": "Kembalikan arcsince beberapa nombor.", - "MATH_TRIG_TOOLTIP_ACOS": "Kembali arccosine beberapa nombor.", - "MATH_TRIG_TOOLTIP_ATAN": "Kembalikan beberapa nombor arctangent.", - "MATH_CONSTANT_HELPURL": "https://ms.wikipedia.org/wiki/Pemalar_matematik", - "MATH_CONSTANT_TOOLTIP": "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).", - "MATH_IS_EVEN": "Adalah genap", - "MATH_IS_ODD": "aneh", - "MATH_IS_PRIME": "is prime", - "MATH_IS_WHOLE": "is whole", - "MATH_IS_POSITIVE": "adalah positif", - "MATH_IS_NEGATIVE": "negatif", - "MATH_IS_DIVISIBLE_BY": "Boleh dibahagikan dengan", - "MATH_IS_TOOLTIP": "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false.", - "MATH_CHANGE_HELPURL": "https://id.wikipedia.org/wiki/Perjumlahan", - "MATH_CHANGE_TITLE": "perubahan %1 oleh %2", - "MATH_CHANGE_TOOLTIP": "Tambah nombor kepada pembolehubah '%1'.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Bulat nombor yang naik atau turun.", - "MATH_ROUND_OPERATOR_ROUND": "pusingan", - "MATH_ROUND_OPERATOR_ROUNDUP": "pusingan ke atas", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "Pusingan ke bawah", - "MATH_ONLIST_OPERATOR_SUM": "Jumlah senarai", - "MATH_ONLIST_TOOLTIP_SUM": "Kembalikan jumlah semua nombor dalam senarai.", - "MATH_ONLIST_OPERATOR_MIN": "min dalam senarai", - "MATH_ONLIST_TOOLTIP_MIN": "Kembalikan nombor terkecil dalam senarai.", - "MATH_ONLIST_OPERATOR_MAX": "Max senarai", - "MATH_ONLIST_TOOLTIP_MAX": "Pulangkan jumlah terbesar dalam senarai.", - "MATH_ONLIST_OPERATOR_AVERAGE": "purata daripada senarai", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Kembalikan purata (min aritmetik) nilai-nilai angka di dalam senarai.", - "MATH_ONLIST_OPERATOR_MEDIAN": "Median senarai", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Kembalikan nombor median dalam senarai.", - "MATH_ONLIST_OPERATOR_MODE": "jenis senarai", - "MATH_ONLIST_TOOLTIP_MODE": "Kembali senarai item yang paling biasa dalam senarai.", - "MATH_ONLIST_OPERATOR_STD_DEV": "sisihan piawai bagi senarai", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Kembali dengan sisihan piawai daripada senarai.", - "MATH_ONLIST_OPERATOR_RANDOM": "Item rawak daripada senarai", - "MATH_ONLIST_TOOLTIP_RANDOM": "Kembalikan elemen rawak daripada senarai.", - "MATH_MODULO_HELPURL": "https://id.wikipedia.org/wiki/Operasi_modulus", - "MATH_MODULO_TITLE": "remainder of %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Taip balik baki yang didapat daripada pembahagian dua nombor tersebut.", - "MATH_CONSTRAIN_TITLE": "constrain %1 low %2 high %3", - "MATH_CONSTRAIN_TOOLTIP": "Constrain a number to be between the specified limits (inclusive).", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "integer rawak dari %1ke %2", - "MATH_RANDOM_INT_TOOLTIP": "Kembalikan integer rawak diantara dua had yang ditentukan, inklusif.", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "pecahan rawak", - "MATH_RANDOM_FLOAT_TOOLTIP": "Kembali sebahagian kecil rawak antara 0.0 (inklusif) dan 1.0 (eksklusif).", - "TEXT_TEXT_HELPURL": "https://ms.wikipedia.org/wiki/Rentetan", - "TEXT_TEXT_TOOLTIP": "Huruf, perkataan, atau baris teks.", - "TEXT_JOIN_TITLE_CREATEWITH": "hasilkan teks dengan", - "TEXT_JOIN_TOOLTIP": "Hasilkan sebahagian teks dengan menghubungkan apa jua nombor item.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "Sertai", - "TEXT_CREATE_JOIN_TOOLTIP": "Add, remove, or reorder sections to reconfigure this text block.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Add an item to the text.", - "TEXT_APPEND_TO": "Untuk", - "TEXT_APPEND_APPENDTEXT": "append text", - "TEXT_APPEND_TOOLTIP": "Append some text to variable '%1'.", - "TEXT_LENGTH_TITLE": "panjang %1", - "TEXT_LENGTH_TOOLTIP": "Kembalikan jumlah huruf (termasuk ruang) dalam teks yang disediakan.", - "TEXT_ISEMPTY_TITLE": "%1 adalah kosong", - "TEXT_ISEMPTY_TOOLTIP": "Kembalikan benar jika teks yang disediakan adalah kosong.", - "TEXT_INDEXOF_TOOLTIP": "Kembalikan Indeks kejadian pertama/terakhir dari teks pertama ke dalam teks kedua. Kembalikan %1 Jika teks tidak ditemui.", - "TEXT_INDEXOF_INPUT_INTEXT": "dalam teks", - "TEXT_INDEXOF_OPERATOR_FIRST": "mencari kejadian pertama teks", - "TEXT_INDEXOF_OPERATOR_LAST": "mencari kejadian terakhir teks", - "TEXT_CHARAT_INPUT_INTEXT": "Dalam teks", - "TEXT_CHARAT_FROM_START": "get letter #", - "TEXT_CHARAT_FROM_END": "get letter # from end", - "TEXT_CHARAT_FIRST": "get first letter", - "TEXT_CHARAT_LAST": "Dapatkan abjad terakhir", - "TEXT_CHARAT_RANDOM": "Dapatkan abjad rawak", - "TEXT_CHARAT_TOOLTIP": "Returns the letter at the specified position.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Returns a specified portion of the text.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "dalam teks", - "TEXT_GET_SUBSTRING_START_FROM_START": "get substring from letter #", - "TEXT_GET_SUBSTRING_START_FROM_END": "get substring from letter # from end", - "TEXT_GET_SUBSTRING_START_FIRST": "get substring from first letter", - "TEXT_GET_SUBSTRING_END_FROM_START": "to letter #", - "TEXT_GET_SUBSTRING_END_FROM_END": "to letter # from end", - "TEXT_GET_SUBSTRING_END_LAST": "untuk huruf terakhir", - "TEXT_CHANGECASE_TOOLTIP": "Return a copy of the text in a different case.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "Kepada HURUF BESAR", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "Kepada huruf kecil", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "to Title Case", - "TEXT_TRIM_TOOLTIP": "Kembali salinan teks dengan ruang yang dikeluarkan daripada satu atau hujung kedua belah.", - "TEXT_TRIM_OPERATOR_BOTH": "mengurangkan kawasan dari kedua-dua belah", - "TEXT_TRIM_OPERATOR_LEFT": "mengurangkan ruang dari sebelah kiri", - "TEXT_TRIM_OPERATOR_RIGHT": "mengurangkan kawasan dari sisi kanan", - "TEXT_PRINT_TITLE": "cetak %1", - "TEXT_PRINT_TOOLTIP": "Cetak teks yang ditentukan, nombor atau nilai lain.", - "TEXT_PROMPT_TYPE_TEXT": "Prom untuk teks dengan mesej", - "TEXT_PROMPT_TYPE_NUMBER": "Prom untuk nombor dengan mesej", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Peringatan kepada pengguna untuk nombor.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Peringatkan pengguna untuk sebahagian teks.", - "LISTS_CREATE_EMPTY_TITLE": "Wujudkan senarai kosong", - "LISTS_CREATE_EMPTY_TOOLTIP": "Kembalikan senarai panjang 0, yang tidak mengandungi rekod data", - "LISTS_CREATE_WITH_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_CREATE_WITH_TOOLTIP": "Wujudkan senarai dengan apa jua nombor item.", - "LISTS_CREATE_WITH_INPUT_WITH": "wujudkan senarai dengan", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "senarai", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Tambah, alih keluar, atau susun semula bahagian-bahagian untuk menyusun semula senarai blok.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Tambah item ke dalam senarai.", - "LISTS_REPEAT_TOOLTIP": "Wujudkan senarai yang terdiri daripada nilai berulang mengikut nombor yang ditentukan.", - "LISTS_REPEAT_TITLE": "wujudkan senarai dengan item %1 diulangi %2 kali", - "LISTS_LENGTH_TITLE": "panjang %1", - "LISTS_LENGTH_TOOLTIP": "Kembalikan panjang senarai", - "LISTS_ISEMPTY_TITLE": "%1 adalah kosong", - "LISTS_ISEMPTY_TOOLTIP": "Kembalikan benar jika senarai kosong.", - "LISTS_INLIST": "dalam senarai", - "LISTS_INDEX_OF_FIRST": "cari pertama item kejadian", - "LISTS_INDEX_OF_LAST": "cari kejadian akhir item", - "LISTS_INDEX_OF_TOOLTIP": "Menyatakan indeks kejadian pertama/terakhir item berkenaan dalam senarai. Menyatakan %1 jika item berkenaan tidak ditemui.", - "LISTS_GET_INDEX_GET": "dapatkan", - "LISTS_GET_INDEX_GET_REMOVE": "dapat dan alihkan", - "LISTS_GET_INDEX_REMOVE": "alihkan", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# dari akhir", - "LISTS_GET_INDEX_FIRST": "pertama", - "LISTS_GET_INDEX_LAST": "terakhir", - "LISTS_GET_INDEX_RANDOM": "rawak", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 ialah item pertama.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 ialah item terakhir.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Kembalikan item dalam kedudukan yang ditetapkan dalam senarai.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Kembalikan item pertama dalam senarai.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Kembalikan item pertama dalam senarai.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Kembalikan item rawak dalam senarai.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Alihkan dan kembalikan item mengikut spesifikasi posisi dalam senarai.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Alihkan dan kembalikan item pertama dalam senarai.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Alihkan dan kembalikan item terakhir dalam senarai.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Alihkan dan kembalikan item rawak dalam senarai.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Alihkan item pada posisi mengikut spesifikasi dalam senarai.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Alihkan item pertama dalam senarai.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Alihkan item terakhir dalam senarai.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Alihkan item rawak dalam senarai.", - "LISTS_SET_INDEX_SET": "set", - "LISTS_SET_INDEX_INSERT": "masukkan pada", - "LISTS_SET_INDEX_INPUT_TO": "sebagai", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Masukkan item pada posisi yang ditentukan dalam senarai.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Set item pertama dalam senarai.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Set item terakhir dalam senarai.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Set item rawak dalam senarai.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Masukkan item pada posisi yand ditentukan dalam senarai.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Selit item pada permulaan senarai.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Tambahkan item dalam senarai akhir.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Selit item secara rawak di dalam senarai.", - "LISTS_GET_SUBLIST_START_FROM_START": "dapatkan sub-senarai daripada #", - "LISTS_GET_SUBLIST_START_FROM_END": "dapatkan sub-senarai daripada # daripada terakhir", - "LISTS_GET_SUBLIST_START_FIRST": "dapatkan sub-senarai daripada pertama", - "LISTS_GET_SUBLIST_END_FROM_START": "ke #", - "LISTS_GET_SUBLIST_END_FROM_END": "ke # dari akhir", - "LISTS_GET_SUBLIST_END_LAST": "ke akhir", - "LISTS_GET_SUBLIST_TOOLTIP": "Wujudkan salinan bahagian yang ditentukan dari senarai.", - "LISTS_SPLIT_HELPURL": "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists", - "LISTS_SPLIT_LIST_FROM_TEXT": "buat senarai dgn teks", - "LISTS_SPLIT_TEXT_FROM_LIST": "buat teks drpd senarai", - "LISTS_SPLIT_WITH_DELIMITER": "dengan delimiter", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Pecahkan teks kepada senarai teks, berpecah di setiap delimiter.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Cantumkan senarai teks menjadi satu teks, dipecahkan oleh delimiter.", - "VARIABLES_GET_TOOLTIP": "Kembalikan nilai pemboleh ubah ini.", - "VARIABLES_GET_CREATE_SET": "Hasilkan 'set %1'", - "VARIABLES_SET": "set %1 ke %2", - "VARIABLES_SET_TOOLTIP": "Set pembolehubah ini supaya sama dengan input.", - "VARIABLES_SET_CREATE_GET": "Hasilkan 'set %1'", - "PROCEDURES_DEFNORETURN_TITLE": "Untuk", - "PROCEDURES_DEFNORETURN_PROCEDURE": "Buat sesuatu", - "PROCEDURES_BEFORE_PARAMS": "dengan:", - "PROCEDURES_CALL_BEFORE_PARAMS": "dengan:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Menghasilkan suatu fungsi tanpa output.", - "PROCEDURES_DEFNORETURN_COMMENT": "Terangkan fungsi ini...", - "PROCEDURES_DEFRETURN_RETURN": "kembali", - "PROCEDURES_DEFRETURN_TOOLTIP": "Mencipta satu fungsi dengan pengeluaran.", - "PROCEDURES_ALLOW_STATEMENTS": "bolehkan kenyataan", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Amaran: Fungsi ini mempunyai parameter yang berganda.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://ms.wikipedia.org/wiki/Fungsi", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Run the user-defined function '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "https://ms.wikipedia.org/wiki/Fungsi", - "PROCEDURES_CALLRETURN_TOOLTIP": "Run the user-defined function '%1' and use its output.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "Input-input", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Tambah, alih keluar atau susun semula input pada fungsi ini.", - "PROCEDURES_MUTATORARG_TITLE": "Nama input:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Tambah satu input pada fungsi.", - "PROCEDURES_HIGHLIGHT_DEF": "Serlahkan definisi fungsi", - "PROCEDURES_CREATE_DO": "Hasilkan '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "If a value is true, then return a second value.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Amaran: Blok ini hanya boleh digunakan dalam fungsi definisi." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/nb.json b/backend/_pv_1_3_5/static/blockly/msg/json/nb.json deleted file mode 100755 index e6787fd7e..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/nb.json +++ /dev/null @@ -1,324 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Cocu", - "Kingu", - "아라", - "SuperPotato" - ] - }, - "VARIABLES_DEFAULT_NAME": "element", - "TODAY": "I dag", - "DUPLICATE_BLOCK": "duplikat", - "ADD_COMMENT": "Legg til kommentar", - "REMOVE_COMMENT": "Fjern kommentar", - "EXTERNAL_INPUTS": "Eksterne kilder", - "INLINE_INPUTS": "Interne kilder", - "DELETE_BLOCK": "Slett blokk", - "DELETE_X_BLOCKS": "Slett %1 blokker", - "DELETE_ALL_BLOCKS": "Slett alle %1 blokker?", - "CLEAN_UP": "Rydd opp Blocks", - "COLLAPSE_BLOCK": "Skjul blokk", - "COLLAPSE_ALL": "Skjul blokker", - "EXPAND_BLOCK": "Utvid blokk", - "EXPAND_ALL": "Utvid blokker", - "DISABLE_BLOCK": "Deaktiver blokk", - "ENABLE_BLOCK": "Aktiver blokk", - "HELP": "Hjelp", - "CHANGE_VALUE_TITLE": "Bytt verdi:", - "RENAME_VARIABLE": "Gi nytt navn til variabel...", - "RENAME_VARIABLE_TITLE": "Endre navnet til alle '%1' variabler til:", - "NEW_VARIABLE": "Ny variabel...", - "NEW_VARIABLE_TITLE": "Nytt variabelnavn:", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "Velg en farge fra paletten.", - "COLOUR_RANDOM_TITLE": "tilfeldig farge", - "COLOUR_RANDOM_TOOLTIP": "Velg en tilfeldig farge.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "farge med", - "COLOUR_RGB_RED": "rød", - "COLOUR_RGB_GREEN": "grønn", - "COLOUR_RGB_BLUE": "blå", - "COLOUR_RGB_TOOLTIP": "Lag en farge med angitt verdi av rød, grønn og blå. Alle verdier må være mellom 0 og 100.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "blande", - "COLOUR_BLEND_COLOUR1": "farge 1", - "COLOUR_BLEND_COLOUR2": "farge 2", - "COLOUR_BLEND_RATIO": "forhold", - "COLOUR_BLEND_TOOLTIP": "Blander to farger sammen med et gitt forhold (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "gjenta %1 ganger", - "CONTROLS_REPEAT_INPUT_DO": "gjør", - "CONTROLS_REPEAT_TOOLTIP": "Gjenta noen instruksjoner flere ganger.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "gjenta mens", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "gjenta til", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Så lenge et utsagn stemmer, utfør noen instruksjoner.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Så lenge et utsagn ikke stemmer, gjør noen instruksjoner.", - "CONTROLS_FOR_TOOLTIP": "Ha variabel \"%1\" ta verdiene fra start nummer til slutt nummer, telle med spesifisert intervall og lag de spesifiserte blokkene.", - "CONTROLS_FOR_TITLE": "tell med %1 fra %2 til %3 med %4", - "CONTROLS_FOREACH_TITLE": "for hvert element %1 i listen %2", - "CONTROLS_FOREACH_TOOLTIP": "For hvert element i en liste, angi variabelen '%1' til elementet, og deretter lag noen setninger.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "bryt ut av løkken", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "fortsett med neste gjentakelse av løkken", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Bryt ut av den gjeldende løkken.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Hopp over resten av denne løkken og fortsett med neste gjentakelse.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Advarsel: Denne blokken kan kun brukes innenfor en løkke.", - "CONTROLS_IF_TOOLTIP_1": "Hvis dette er sant, så gjør følgende.", - "CONTROLS_IF_TOOLTIP_2": "Hvis dette er sant, så utfør den første blokken av instruksjoner. Hvis ikke, utfør den andre blokken.", - "CONTROLS_IF_TOOLTIP_3": "Hvis det første stemmer, så utfør den første blokken av instruksjoner. Ellers, hvis det andre stemmer, utfør den andre blokken av instruksjoner.", - "CONTROLS_IF_TOOLTIP_4": "Hvis den første verdien er sann, så utfør den første blokken med setninger. Ellers, hvis den andre verdien er sann, så utfør den andre blokken med setninger. Hvis ingen av verdiene er sanne, så utfør den siste blokken med setninger.", - "CONTROLS_IF_MSG_IF": "hvis", - "CONTROLS_IF_MSG_ELSEIF": "ellers hvis", - "CONTROLS_IF_MSG_ELSE": "ellers", - "CONTROLS_IF_IF_TOOLTIP": "Legg til, fjern eller flytt seksjoner i denne hvis-blokken.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Legg til en betingelse til hvis blokken.", - "CONTROLS_IF_ELSE_TOOLTIP": "Legg til hva som skal skje hvis de andre ikke slår til.", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Returnerer sann hvis begge inputene er like hverandre.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Returnerer sant hvis begge argumentene er ulike hverandre.", - "LOGIC_COMPARE_TOOLTIP_LT": "Returnerer sant hvis det første argumentet er mindre enn det andre argumentet.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Returnerer sant hvis det første argumentet er mindre enn eller likt det andre argumentet.", - "LOGIC_COMPARE_TOOLTIP_GT": "Returnerer sant hvis det første argumentet er større enn den andre argumentet.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Returnerer sant hvis det første argumentet er større enn eller likt det andre argumentet.", - "LOGIC_OPERATION_TOOLTIP_AND": "Returnerer sant hvis begge argumentene er sanne.", - "LOGIC_OPERATION_AND": "og", - "LOGIC_OPERATION_TOOLTIP_OR": "Returnerer sant hvis minst ett av argumentene er sant.", - "LOGIC_OPERATION_OR": "eller", - "LOGIC_NEGATE_TITLE": "ikke %1", - "LOGIC_NEGATE_TOOLTIP": "Returnerer sant hvis argumentet er usant. Returnerer usant hvis argumentet er sant.", - "LOGIC_BOOLEAN_TRUE": "sann", - "LOGIC_BOOLEAN_FALSE": "usann", - "LOGIC_BOOLEAN_TOOLTIP": "Returnerer enten sann eller usann.", - "LOGIC_NULL_HELPURL": "https://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "null", - "LOGIC_NULL_TOOLTIP": "Returnerer null.", - "LOGIC_TERNARY_HELPURL": "https://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "hvis sant", - "LOGIC_TERNARY_IF_FALSE": "hvis usant", - "LOGIC_TERNARY_TOOLTIP": "Sjekk betingelsen i 'test'. Hvis betingelsen er sann, da returneres 'hvis sant' verdien. Hvis ikke returneres 'hvis usant' verdien.", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "Et tall.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "x", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tan", - "MATH_TRIG_ASIN": "asin", - "MATH_TRIG_ACOS": "acos", - "MATH_TRIG_ATAN": "atan", - "MATH_ARITHMETIC_HELPURL": "https://no.wikipedia.org/wiki/Aritmetikk", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Returnerer summen av to tall.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Returner differansen mellom to tall.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Returner produktet av to tall.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Returner kvotienten av to tall.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Returner det første tallet opphøyd i den andre tallet.", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "kvadratrot", - "MATH_SINGLE_TOOLTIP_ROOT": "Returner kvadratroten av et tall.", - "MATH_SINGLE_OP_ABSOLUTE": "absoluttverdi", - "MATH_SINGLE_TOOLTIP_ABS": "Returner absoluttverdien av et tall.", - "MATH_SINGLE_TOOLTIP_NEG": "Returner det negative tallet.", - "MATH_SINGLE_TOOLTIP_LN": "Returner den naturlige logaritmen til et tall.", - "MATH_SINGLE_TOOLTIP_LOG10": "Returner base-10 logaritmen til et tall.", - "MATH_SINGLE_TOOLTIP_EXP": "Returner e opphøyd i et tall.", - "MATH_SINGLE_TOOLTIP_POW10": "Returner 10 opphøyd i et tall.", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "Returner sinus av en vinkel (ikke radian).", - "MATH_TRIG_TOOLTIP_COS": "Returner cosinus av en vinkel (ikke radian).", - "MATH_TRIG_TOOLTIP_TAN": "Returner tangenten av en vinkel (ikke radian).", - "MATH_TRIG_TOOLTIP_ASIN": "Returner arcsinus til et tall.", - "MATH_TRIG_TOOLTIP_ACOS": "Returner arccosinus til et tall.", - "MATH_TRIG_TOOLTIP_ATAN": "Returner arctangens til et tall.", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "Returner en av felleskonstantene π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), eller ∞ (uendelig).", - "MATH_IS_EVEN": "er et partall", - "MATH_IS_ODD": "er et oddetall", - "MATH_IS_PRIME": "er et primtall", - "MATH_IS_WHOLE": "er et heltall", - "MATH_IS_POSITIVE": "er positivt", - "MATH_IS_NEGATIVE": "er negativer negativt", - "MATH_IS_DIVISIBLE_BY": "er delelig med", - "MATH_IS_TOOLTIP": "Sjekk om et tall er et partall, oddetall, primtall, heltall, positivt, negativt, eller om det er delelig med et annet tall. Returnerer sant eller usant.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "endre %1 ved %2", - "MATH_CHANGE_TOOLTIP": "Addere et tall til variabelen '%1'.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Avrund et tall ned eller opp.", - "MATH_ROUND_OPERATOR_ROUND": "avrunding", - "MATH_ROUND_OPERATOR_ROUNDUP": "rund opp", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "rund ned", - "MATH_ONLIST_HELPURL": "", - "MATH_ONLIST_OPERATOR_SUM": "summen av listen", - "MATH_ONLIST_TOOLTIP_SUM": "Returner summen av alle tallene i listen.", - "MATH_ONLIST_OPERATOR_MIN": "minimum av listen", - "MATH_ONLIST_TOOLTIP_MIN": "Returner det minste tallet i listen.", - "MATH_ONLIST_OPERATOR_MAX": "maksimum av liste", - "MATH_ONLIST_TOOLTIP_MAX": "Returner det største tallet i listen.", - "MATH_ONLIST_OPERATOR_AVERAGE": "gjennomsnittet av listen", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Returner det aritmetiske gjennomsnittet av tallene i listen.", - "MATH_ONLIST_OPERATOR_MEDIAN": "medianen til listen", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Returner listens median.", - "MATH_ONLIST_OPERATOR_MODE": "Listens typetall", - "MATH_ONLIST_TOOLTIP_MODE": "Returner en liste av de vanligste elementene i listen.", - "MATH_ONLIST_OPERATOR_STD_DEV": "standardavviket til listen", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Returner listens standardavvik.", - "MATH_ONLIST_OPERATOR_RANDOM": "tilfeldig element i listen", - "MATH_ONLIST_TOOLTIP_RANDOM": "Returner et tilfeldig element fra listen.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "resten av %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Returner resten fra delingen av to tall.", - "MATH_CONSTRAIN_TITLE": "begrense %1 lav %2 høy %3", - "MATH_CONSTRAIN_TOOLTIP": "Begrens et tall til å være mellom de angitte grenseverdiene (inklusiv).", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "Et tilfeldig heltall mellom %1 og %2", - "MATH_RANDOM_INT_TOOLTIP": "Returner et tilfeldig tall mellom de to spesifiserte grensene, inkludert de to.", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "tilfeldig flyttall", - "MATH_RANDOM_FLOAT_TOOLTIP": "Returner et tilfeldig flyttall mellom 0.0 (inkludert) og 1.0 (ikke inkludert).", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "En bokstav, ett ord eller en linje med tekst.", - "TEXT_JOIN_TITLE_CREATEWITH": "lage tekst med", - "TEXT_JOIN_TOOLTIP": "Opprett en tekst ved å sette sammen et antall elementer.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "føy sammen", - "TEXT_CREATE_JOIN_TOOLTIP": "Legg til, fjern eller forandre rekkefølgen for å forandre på denne tekstblokken.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Legg til et element til teksten.", - "TEXT_APPEND_TO": "til", - "TEXT_APPEND_APPENDTEXT": "tilføy tekst", - "TEXT_APPEND_TOOLTIP": "Tilføy tekst til variabelen '%1'.", - "TEXT_LENGTH_TITLE": "lengden av %1", - "TEXT_LENGTH_TOOLTIP": "Returnerer antall bokstaver (inkludert mellomrom) i den angitte teksten.", - "TEXT_ISEMPTY_TITLE": "%1 er tom", - "TEXT_ISEMPTY_TOOLTIP": "Returnerer sann hvis den angitte teksten er tom.", - "TEXT_INDEXOF_TOOLTIP": "Returnerer posisjonen for første/siste forekomsten av den første tekst i den andre teksten. Returnerer %1 hvis teksten ikke blir funnet.", - "TEXT_INDEXOF_INPUT_INTEXT": "i tekst", - "TEXT_INDEXOF_OPERATOR_FIRST": "finn første forekomst av tekst", - "TEXT_INDEXOF_OPERATOR_LAST": "finn siste forekomst av tekst", - "TEXT_INDEXOF_TAIL": "", - "TEXT_CHARAT_INPUT_INTEXT": "i tekst", - "TEXT_CHARAT_FROM_START": "hent bokstav #", - "TEXT_CHARAT_FROM_END": "hent bokstav # fra slutten", - "TEXT_CHARAT_FIRST": "hent første bokstav", - "TEXT_CHARAT_LAST": "hent den siste bokstaven", - "TEXT_CHARAT_RANDOM": "hent en tilfeldig bokstav", - "TEXT_CHARAT_TAIL": "", - "TEXT_CHARAT_TOOLTIP": "Returnerer bokstaven på angitt plassering.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Returnerer den angitte delen av teksten.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "i tekst", - "TEXT_GET_SUBSTRING_START_FROM_START": "hent delstreng fra bokstav #", - "TEXT_GET_SUBSTRING_START_FROM_END": "hent delstreng fra bokstav # fra slutten", - "TEXT_GET_SUBSTRING_START_FIRST": "hent delstreng fra første bokstav", - "TEXT_GET_SUBSTRING_END_FROM_START": "til bokstav #", - "TEXT_GET_SUBSTRING_END_FROM_END": "til bokstav # fra slutten", - "TEXT_GET_SUBSTRING_END_LAST": "til siste bokstav", - "TEXT_GET_SUBSTRING_TAIL": "", - "TEXT_CHANGECASE_TOOLTIP": "Returnerer en kopi av teksten der store og små bokstaver er byttet om.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "til STORE BOKSTAVER", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "til små bokstaver", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "til store forbokstaver", - "TEXT_TRIM_TOOLTIP": "Returner en kopi av teksten med mellomrom fjernet fra en eller begge sidene.", - "TEXT_TRIM_OPERATOR_BOTH": "fjern mellomrom fra begge sider av", - "TEXT_TRIM_OPERATOR_LEFT": "fjern mellomrom fra venstre side av", - "TEXT_TRIM_OPERATOR_RIGHT": "fjern mellomrom fra høyre side av", - "TEXT_PRINT_TITLE": "skriv ut %1", - "TEXT_PRINT_TOOLTIP": "Skriv ut angitt tekst, tall eller annet innhold.", - "TEXT_PROMPT_TYPE_TEXT": "spør om tekst med en melding", - "TEXT_PROMPT_TYPE_NUMBER": "spør om et tall med en melding", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Be brukeren om et tall.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Spør brukeren om tekst.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "opprett en tom liste", - "LISTS_CREATE_EMPTY_TOOLTIP": "Returnerer en tom liste, altså med lengde 0", - "LISTS_CREATE_WITH_TOOLTIP": "Lag en liste med et vilkårlig antall elementer.", - "LISTS_CREATE_WITH_INPUT_WITH": "lag en liste med", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "liste", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Legg til, fjern eller endre rekkefølgen for å endre på denne delen av listen.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Tilføy et element til listen.", - "LISTS_REPEAT_TOOLTIP": "Lager en liste hvor den gitte verdien gjentas et antall ganger.", - "LISTS_REPEAT_TITLE": "Lag en liste hvor elementet %1 forekommer %2 ganger", - "LISTS_LENGTH_TITLE": "lengden på %1", - "LISTS_LENGTH_TOOLTIP": "Returnerer lengden til en liste.", - "LISTS_ISEMPTY_TITLE": "%1 er tom", - "LISTS_ISEMPTY_TOOLTIP": "Returnerer sann hvis listen er tom.", - "LISTS_INLIST": "i listen", - "LISTS_INDEX_OF_FIRST": "finn første forekomst av elementet", - "LISTS_INDEX_OF_LAST": "finn siste forekomst av elementet", - "LISTS_INDEX_OF_TOOLTIP": "Returnerer indeksen av den første/siste forekomsten av elementet i lista. Returnerer %1 hvis ikke funnet.", - "LISTS_GET_INDEX_GET": "hent", - "LISTS_GET_INDEX_GET_REMOVE": "hent og fjern", - "LISTS_GET_INDEX_REMOVE": "fjern", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# fra slutten", - "LISTS_GET_INDEX_FIRST": "først", - "LISTS_GET_INDEX_LAST": "siste", - "LISTS_GET_INDEX_RANDOM": "tilfeldig", - "LISTS_GET_INDEX_TAIL": "", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 er det første elementet.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 er det siste elementet.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Returner elementet på den angitte posisjonen i en liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Returnerer det første elementet i en liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Returnerer det siste elementet i en liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Returnerer et tilfeldig element i en liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Fjerner og returnerer elementet ved en gitt posisjon i en liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Fjerner og returnerer det første elementet i en liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Fjerner og returnerer det siste elementet i en liste.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Fjerner og returnerer et tilfeldig element i en liste.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Fjerner et element ved en gitt posisjon i en liste.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Fjerner det første elementet i en liste.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Fjerner det siste elementet i en liste.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Fjerner et tilfeldig element i en liste.", - "LISTS_SET_INDEX_SET": "sett", - "LISTS_SET_INDEX_INSERT": "sett inn ved", - "LISTS_SET_INDEX_INPUT_TO": "som", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Setter inn elementet ved den angitte posisjonen i en liste.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Angir det første elementet i en liste.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Angir det siste elementet i en liste.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Angir et tilfeldig element i en liste.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Setter inn elementet ved den angitte posisjonen i en liste.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Setter inn elementet i starten av en liste.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Tilføy elementet til slutten av en liste.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Setter inn elementet ved en tilfeldig posisjon i en liste.", - "LISTS_GET_SUBLIST_START_FROM_START": "Hent del-listen fra #", - "LISTS_GET_SUBLIST_START_FROM_END": "Hent de siste # elementene", - "LISTS_GET_SUBLIST_START_FIRST": "Hent en del av listen", - "LISTS_GET_SUBLIST_END_FROM_START": "til #", - "LISTS_GET_SUBLIST_END_FROM_END": "til # fra slutten", - "LISTS_GET_SUBLIST_END_LAST": "til siste", - "LISTS_GET_SUBLIST_TAIL": "", - "LISTS_GET_SUBLIST_TOOLTIP": "Kopiérer en ønsket del av en liste.", - "LISTS_SPLIT_LIST_FROM_TEXT": "lag liste av tekst", - "LISTS_SPLIT_TEXT_FROM_LIST": "lag tekst av liste", - "ORDINAL_NUMBER_SUFFIX": "", - "VARIABLES_GET_TOOLTIP": "Returnerer verdien av denne variabelen.", - "VARIABLES_GET_CREATE_SET": "Opprett 'sett %1'", - "VARIABLES_SET": "sett %1 til %2", - "VARIABLES_SET_TOOLTIP": "Setter verdien av denne variablen lik parameteren.", - "VARIABLES_SET_CREATE_GET": "Opprett 'hent %1'", - "PROCEDURES_DEFNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFNORETURN_TITLE": "til", - "PROCEDURES_DEFNORETURN_PROCEDURE": "gjør noe", - "PROCEDURES_BEFORE_PARAMS": "med:", - "PROCEDURES_CALL_BEFORE_PARAMS": "med:", - "PROCEDURES_DEFNORETURN_DO": "", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Opprett en funksjon som ikke har noe resultat.", - "PROCEDURES_DEFRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFRETURN_RETURN": "returner", - "PROCEDURES_DEFRETURN_TOOLTIP": "Oppretter en funksjon som har et resultat.", - "PROCEDURES_ALLOW_STATEMENTS": "tillat uttalelser", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Advarsel: Denne funksjonen har duplikate parametere.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Kjør den brukerdefinerte funksjonen '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Kjør den brukerdefinerte funksjonen'%1' og bruk resultatet av den.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "parametere", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Legg til, fjern eller endre rekkefølgen på input til denne funksjonen.", - "PROCEDURES_MUTATORARG_TITLE": "Navn på parameter:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Legg til en input til funksjonen.", - "PROCEDURES_HIGHLIGHT_DEF": "Marker funksjonsdefinisjonen", - "PROCEDURES_CREATE_DO": "Opprett '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Hvis en verdi er sann, returner da en annen verdi.", - "PROCEDURES_IFRETURN_WARNING": "Advarsel: Denne blokken kan bare benyttes innenfor en funksjonsdefinisjon." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/nl.json b/backend/_pv_1_3_5/static/blockly/msg/json/nl.json deleted file mode 100755 index df433497c..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/nl.json +++ /dev/null @@ -1,361 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Siebrand", - "McDutchie", - "Ribert", - "MedShot", - "아라", - "JaapDeKleine", - "Sjoerddebruin", - "Lemondoge", - "Jeleniccz" - ] - }, - "VARIABLES_DEFAULT_NAME": "item", - "TODAY": "Vandaag", - "DUPLICATE_BLOCK": "Duplicaat", - "ADD_COMMENT": "Reactie toevoegen", - "REMOVE_COMMENT": "Opmerking verwijderen", - "EXTERNAL_INPUTS": "Externe invoer", - "INLINE_INPUTS": "Inline invoer", - "DELETE_BLOCK": "Blok verwijderen", - "DELETE_X_BLOCKS": "%1 blokken verwijderen", - "DELETE_ALL_BLOCKS": "Alle %1 blokken verwijderen?", - "CLEAN_UP": "Blokken opschonen", - "COLLAPSE_BLOCK": "Blok samenvouwen", - "COLLAPSE_ALL": "Blokken samenvouwen", - "EXPAND_BLOCK": "Blok uitvouwen", - "EXPAND_ALL": "Blokken uitvouwen", - "DISABLE_BLOCK": "Blok uitschakelen", - "ENABLE_BLOCK": "Blok inschakelen", - "HELP": "Hulp", - "UNDO": "Ongedaan maken", - "REDO": "Opnieuw", - "CHANGE_VALUE_TITLE": "Waarde wijzigen:", - "RENAME_VARIABLE": "Variabele hernoemen...", - "RENAME_VARIABLE_TITLE": "Alle variabelen \"%1\" hernoemen naar:", - "NEW_VARIABLE": "Nieuwe variabele...", - "NEW_VARIABLE_TITLE": "Nieuwe variabelenaam:", - "COLOUR_PICKER_HELPURL": "https://nl.wikipedia.org/wiki/Kleur", - "COLOUR_PICKER_TOOLTIP": "Kies een kleur in het palet.", - "COLOUR_RANDOM_TITLE": "willekeurige kleur", - "COLOUR_RANDOM_TOOLTIP": "Kies een willekeurige kleur.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "kleuren met", - "COLOUR_RGB_RED": "rood", - "COLOUR_RGB_GREEN": "groen", - "COLOUR_RGB_BLUE": "blauw", - "COLOUR_RGB_TOOLTIP": "Maak een kleur met de opgegeven hoeveelheid rood, groen en blauw. Alle waarden moeten tussen 0 en 100 liggen.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "mengen", - "COLOUR_BLEND_COLOUR1": "kleur 1", - "COLOUR_BLEND_COLOUR2": "kleur 2", - "COLOUR_BLEND_RATIO": "verhouding", - "COLOUR_BLEND_TOOLTIP": "Mengt twee kleuren samen met een bepaalde verhouding (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://nl.wikipedia.org/wiki/Repetitie_(informatica)#For_en_Foreach", - "CONTROLS_REPEAT_TITLE": "%1 keer herhalen", - "CONTROLS_REPEAT_INPUT_DO": "voer uit", - "CONTROLS_REPEAT_TOOLTIP": "Voer een aantal opdrachten meerdere keren uit.", - "CONTROLS_WHILEUNTIL_HELPURL": "https://github.com/google/blockly/wiki/Loops#repeat", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "herhalen zolang", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "herhalen totdat", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Terwijl een waarde waar is de volgende opdrachten uitvoeren.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Terwijl een waarde onwaar is de volgende opdrachten uitvoeren.", - "CONTROLS_FOR_HELPURL": "https://github.com/google/blockly/wiki/Loops#count-with", - "CONTROLS_FOR_TOOLTIP": "Laat de variabele \"%1\" de waarden aannemen van het beginnummer tot het laatste nummer, tellende met het opgegeven interval, en met uitvoering van de opgegeven blokken.", - "CONTROLS_FOR_TITLE": "rekenen met %1 van %2 tot %3 in stappen van %4", - "CONTROLS_FOREACH_TITLE": "voor ieder item %1 in lijst %2", - "CONTROLS_FOREACH_TOOLTIP": "Voor ieder item in een lijst, stel de variabele \"%1\" in op het item en voer daarna opdrachten uit.", - "CONTROLS_FLOW_STATEMENTS_HELPURL": "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "uit lus breken", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "doorgaan met de volgende iteratie van de lus", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "uit de bovenliggende lus breken", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "De rest van deze lus overslaan en doorgaan met de volgende herhaling.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Waarschuwing: dit blok mag alleen gebruikt worden in een lus.", - "CONTROLS_IF_HELPURL": "https://github.com/google/blockly/wiki/IfElse", - "CONTROLS_IF_TOOLTIP_1": "Als een waarde waar is, voer dan opdrachten uit.", - "CONTROLS_IF_TOOLTIP_2": "Als een waarde waar is, voert dan het eerste blok met opdrachten uit. Voer andere het tweede blok met opdrachten uit.", - "CONTROLS_IF_TOOLTIP_3": "Als de eerste waarde waar is, voer dan het eerste blok met opdrachten uit. Voer anders, als de tweede waarde waar is, het tweede blok met opdrachten uit.", - "CONTROLS_IF_TOOLTIP_4": "Als de eerste waarde \"waar\" is, voer dan het eerste blok uit. Voer anders wanneer de tweede waarde \"waar\" is, het tweede blok uit. Als geen van beide waarden waar zijn, voer dan het laatste blok uit.", - "CONTROLS_IF_MSG_IF": "als", - "CONTROLS_IF_MSG_ELSEIF": "anders als", - "CONTROLS_IF_MSG_ELSE": "anders", - "CONTROLS_IF_IF_TOOLTIP": "Voeg stukken toe, verwijder of wijzig de volgorde om dit \"als\"-blok te wijzigen.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Voeg een voorwaarde toe aan het als-blok.", - "CONTROLS_IF_ELSE_TOOLTIP": "Voeg een laatste, vang-alles conditie toe aan het als-statement.", - "LOGIC_COMPARE_HELPURL": "https://nl.wikipedia.org/wiki/Ongelijkheid_(wiskunde)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Geeft \"waar\", als beide waarden gelijk aan elkaar zijn.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Geeft \"waar\" terug als de waarden niet gelijk zijn aan elkaar.", - "LOGIC_COMPARE_TOOLTIP_LT": "Geeft \"waar\" als de eerste invoer kleiner is dan de tweede invoer.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Geeft \"waar\" terug als de eerste invoer kleiner of gelijk is aan de tweede invoer.", - "LOGIC_COMPARE_TOOLTIP_GT": "Geeft \"waar\" terug als de eerste invoer meer is dan de tweede invoer.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Geeft \"waar\" terug als de eerste invoer groter is of gelijk aan de tweede invoer.", - "LOGIC_OPERATION_HELPURL": "https://github.com/google/blockly/wiki/Logic#logical-operations", - "LOGIC_OPERATION_TOOLTIP_AND": "Geeft waar als beide waarden waar zijn.", - "LOGIC_OPERATION_AND": "en", - "LOGIC_OPERATION_TOOLTIP_OR": "Geeft \"waar\" terug als in ieder geval één van de waarden waar is.", - "LOGIC_OPERATION_OR": "of", - "LOGIC_NEGATE_HELPURL": "https://github.com/google/blockly/wiki/Logic#not", - "LOGIC_NEGATE_TITLE": "niet %1", - "LOGIC_NEGATE_TOOLTIP": "Geeft \"waar\" terug als de invoer \"onwaar\" is. Geeft \"onwaar\" als de invoer \"waar\" is.", - "LOGIC_BOOLEAN_HELPURL": "https://github.com/google/blockly/wiki/Logic#values", - "LOGIC_BOOLEAN_TRUE": "waar", - "LOGIC_BOOLEAN_FALSE": "onwaar", - "LOGIC_BOOLEAN_TOOLTIP": "Geeft \"waar\" of \"onwaar\" terug.", - "LOGIC_NULL_HELPURL": "https://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "niets", - "LOGIC_NULL_TOOLTIP": "Geeft niets terug.", - "LOGIC_TERNARY_HELPURL": "https://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "als waar", - "LOGIC_TERNARY_IF_FALSE": "als onwaar", - "LOGIC_TERNARY_TOOLTIP": "Test de voorwaarde in \"test\". Als de voorwaarde \"waar\" is, geef de waarde van \"als waar\" terug; geef anders de waarde van \"als onwaar\" terug.", - "MATH_NUMBER_HELPURL": "https://nl.wikipedia.org/wiki/Getal_%28wiskunde%29", - "MATH_NUMBER_TOOLTIP": "Een getal.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tan", - "MATH_TRIG_ASIN": "asin", - "MATH_TRIG_ACOS": "acos", - "MATH_TRIG_ATAN": "arctan", - "MATH_ARITHMETIC_HELPURL": "https://nl.wikipedia.org/wiki/Rekenen", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Geeft de som van 2 getallen.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Geeft het verschil van de twee getallen.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Geeft het product terug van de twee getallen.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Geeft de gedeelde waarde van twee getallen.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Geeft het eerste getal tot de macht van het tweede getal.", - "MATH_SINGLE_HELPURL": "https://nl.wikipedia.org/wiki/Vierkantswortel", - "MATH_SINGLE_OP_ROOT": "wortel", - "MATH_SINGLE_TOOLTIP_ROOT": "Geeft de wortel van een getal.", - "MATH_SINGLE_OP_ABSOLUTE": "absoluut", - "MATH_SINGLE_TOOLTIP_ABS": "Geeft de absolute waarde van een getal.", - "MATH_SINGLE_TOOLTIP_NEG": "Geeft de negatief van een getal.", - "MATH_SINGLE_TOOLTIP_LN": "Geeft het natuurlijk logaritme van een getal.", - "MATH_SINGLE_TOOLTIP_LOG10": "Geeft het logaritme basis 10 van een getal.", - "MATH_SINGLE_TOOLTIP_EXP": "Geeft e tot de macht van een getal.", - "MATH_SINGLE_TOOLTIP_POW10": "Geeft 10 tot de macht van een getal.", - "MATH_TRIG_HELPURL": "https://nl.wikipedia.org/wiki/Goniometrische_functie", - "MATH_TRIG_TOOLTIP_SIN": "Geeft de sinus van een graad (geen radialen).", - "MATH_TRIG_TOOLTIP_COS": "Geeft de cosinus van een graad (geen radialen).", - "MATH_TRIG_TOOLTIP_TAN": "Geeft de tangens van een graad (geen radialen).", - "MATH_TRIG_TOOLTIP_ASIN": "Geeft de arcsinus van een getal.", - "MATH_TRIG_TOOLTIP_ACOS": "Geeft de arccosinus van een getal.", - "MATH_TRIG_TOOLTIP_ATAN": "Geeft de arctangens van een getal.", - "MATH_CONSTANT_HELPURL": "https://nl.wikipedia.org/wiki/Wiskundige_constante", - "MATH_CONSTANT_TOOLTIP": "Geeft een van de vaak voorkomende constante waardes: π (3.141…), e (2.718…), φ (1.618…), √2 (1.414…), √½ (0.707…), of ∞ (oneindig).", - "MATH_IS_EVEN": "is even", - "MATH_IS_ODD": "is oneven", - "MATH_IS_PRIME": "is priemgetal", - "MATH_IS_WHOLE": "is geheel getal", - "MATH_IS_POSITIVE": "is positief", - "MATH_IS_NEGATIVE": "is negatief", - "MATH_IS_DIVISIBLE_BY": "is deelbaar door", - "MATH_IS_TOOLTIP": "Test of een getal even, oneven, een priemgetal, geheel, positief of negatief is, of deelbaar is door een bepaald getal. Geeft \"waar\" of \"onwaar\".", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "%1 wijzigen met %2", - "MATH_CHANGE_TOOLTIP": "Voegt een getal toe aan variabele \"%1\".", - "MATH_ROUND_HELPURL": "https://nl.wikipedia.org/wiki/Afronden", - "MATH_ROUND_TOOLTIP": "Rondt een getal af omhoog of naar beneden.", - "MATH_ROUND_OPERATOR_ROUND": "afronden", - "MATH_ROUND_OPERATOR_ROUNDUP": "omhoog afronden", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "naar beneden afronden", - "MATH_ONLIST_OPERATOR_SUM": "som van lijst", - "MATH_ONLIST_TOOLTIP_SUM": "Geeft de som van alle getallen in de lijst.", - "MATH_ONLIST_OPERATOR_MIN": "laagste uit lijst", - "MATH_ONLIST_TOOLTIP_MIN": "Geeft het kleinste getal uit een lijst.", - "MATH_ONLIST_OPERATOR_MAX": "hoogste uit lijst", - "MATH_ONLIST_TOOLTIP_MAX": "Geeft het grootste getal in een lijst.", - "MATH_ONLIST_OPERATOR_AVERAGE": "gemiddelde van lijst", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Geeft het gemiddelde terug van de numerieke waardes in een lijst.", - "MATH_ONLIST_OPERATOR_MEDIAN": "mediaan van lijst", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Geeft de mediaan in de lijst.", - "MATH_ONLIST_OPERATOR_MODE": "modi van lijst", - "MATH_ONLIST_TOOLTIP_MODE": "Geeft een lijst van de meest voorkomende onderdelen in de lijst.", - "MATH_ONLIST_OPERATOR_STD_DEV": "standaarddeviatie van lijst", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Geeft de standaardafwijking van de lijst.", - "MATH_ONLIST_OPERATOR_RANDOM": "willekeurige item van lijst", - "MATH_ONLIST_TOOLTIP_RANDOM": "Geeft een willekeurig item uit de lijst terug.", - "MATH_MODULO_HELPURL": "https://nl.wikipedia.org/wiki/Modulair_rekenen", - "MATH_MODULO_TITLE": "restgetal van %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Geeft het restgetal van het resultaat van de deling van de twee getallen.", - "MATH_CONSTRAIN_TITLE": "beperk %1 van minimaal %2 tot maximaal %3", - "MATH_CONSTRAIN_TOOLTIP": "Beperk een getal tussen de twee opgegeven limieten (inclusief).", - "MATH_RANDOM_INT_HELPURL": "https://nl.wikipedia.org/wiki/Toevalsgenerator", - "MATH_RANDOM_INT_TITLE": "willekeurig geheel getal van %1 tot %2", - "MATH_RANDOM_INT_TOOLTIP": "Geeft een willekeurig getal tussen de 2 opgegeven limieten in, inclusief.", - "MATH_RANDOM_FLOAT_HELPURL": "https://nl.wikipedia.org/wiki/Toevalsgenerator", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "willekeurige fractie", - "MATH_RANDOM_FLOAT_TOOLTIP": "Geeft een willekeurige fractie tussen 0.0 (inclusief) en 1.0 (exclusief).", - "TEXT_TEXT_HELPURL": "https://nl.wikipedia.org/wiki/String_%28informatica%29", - "TEXT_TEXT_TOOLTIP": "Een letter, woord of een regel tekst.", - "TEXT_JOIN_HELPURL": "https://github.com/google/blockly/wiki/Text#text-creation", - "TEXT_JOIN_TITLE_CREATEWITH": "maak tekst met", - "TEXT_JOIN_TOOLTIP": "Maakt een stuk tekst door één of meer items samen te voegen.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "samenvoegen", - "TEXT_CREATE_JOIN_TOOLTIP": "Toevoegen, verwijderen of volgorde wijzigen van secties om dit tekstblok opnieuw in te stellen.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Voegt een item aan de tekst toe.", - "TEXT_APPEND_HELPURL": "https://github.com/google/blockly/wiki/Text#text-modification", - "TEXT_APPEND_TO": "voeg toe aan", - "TEXT_APPEND_APPENDTEXT": "tekst", - "TEXT_APPEND_TOOLTIP": "Voeg tekst toe aan de variabele \"%1\".", - "TEXT_LENGTH_HELPURL": "https://github.com/google/blockly/wiki/Text#text-modification", - "TEXT_LENGTH_TITLE": "lengte van %1", - "TEXT_LENGTH_TOOLTIP": "Geeft het aantal tekens terug (inclusief spaties) in de opgegeven tekst.", - "TEXT_ISEMPTY_HELPURL": "https://github.com/google/blockly/wiki/Text#checking-for-empty-text", - "TEXT_ISEMPTY_TITLE": "%1 is leeg", - "TEXT_ISEMPTY_TOOLTIP": "Geeft \"waar\" terug, als de opgegeven tekst leeg is.", - "TEXT_INDEXOF_HELPURL": "https://github.com/google/blockly/wiki/Text#finding-text", - "TEXT_INDEXOF_TOOLTIP": "Geeft de index terug van de eerste/laatste aanwezigheid van de eerste tekst in de tweede tekst. Geeft %1 terug als de tekst niet gevonden is.", - "TEXT_INDEXOF_INPUT_INTEXT": "in tekst", - "TEXT_INDEXOF_OPERATOR_FIRST": "zoek eerste voorkomen van tekst", - "TEXT_INDEXOF_OPERATOR_LAST": "zoek het laatste voorkomen van tekst", - "TEXT_CHARAT_HELPURL": "https://github.com/google/blockly/wiki/Text#extracting-text", - "TEXT_CHARAT_INPUT_INTEXT": "in tekst", - "TEXT_CHARAT_FROM_START": "haal letter # op", - "TEXT_CHARAT_FROM_END": "haal letter # op vanaf einde", - "TEXT_CHARAT_FIRST": "haal eerste letter op", - "TEXT_CHARAT_LAST": "haal laatste letter op", - "TEXT_CHARAT_RANDOM": "haal willekeurige letter op", - "TEXT_CHARAT_TOOLTIP": "Geeft de letter op de opgegeven positie terug.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Geeft het opgegeven onderdeel van de tekst terug.", - "TEXT_GET_SUBSTRING_HELPURL": "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "in tekst", - "TEXT_GET_SUBSTRING_START_FROM_START": "haal subtekst op vanaf letter #", - "TEXT_GET_SUBSTRING_START_FROM_END": "haal subtekst op vanaf letter # vanaf einde", - "TEXT_GET_SUBSTRING_START_FIRST": "haal subtekst op van eerste letter", - "TEXT_GET_SUBSTRING_END_FROM_START": "naar letter #", - "TEXT_GET_SUBSTRING_END_FROM_END": "van letter # tot einde", - "TEXT_GET_SUBSTRING_END_LAST": "naar laatste letter", - "TEXT_CHANGECASE_HELPURL": "https://github.com/google/blockly/wiki/Text#adjusting-text-case", - "TEXT_CHANGECASE_TOOLTIP": "Geef een kopie van de tekst met veranderde hoofdletters terug.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "naar HOOFDLETTERS", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "naar kleine letters", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "naar Hoofdletter Per Woord", - "TEXT_TRIM_HELPURL": "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces", - "TEXT_TRIM_TOOLTIP": "Geeft een kopie van de tekst met verwijderde spaties van één of beide kanten.", - "TEXT_TRIM_OPERATOR_BOTH": "spaties van beide kanten afhalen van", - "TEXT_TRIM_OPERATOR_LEFT": "spaties van de linkerkant verwijderen van", - "TEXT_TRIM_OPERATOR_RIGHT": "spaties van de rechterkant verwijderen van", - "TEXT_PRINT_HELPURL": "https://github.com/google/blockly/wiki/Text#printing-text", - "TEXT_PRINT_TITLE": "tekst weergeven: %1", - "TEXT_PRINT_TOOLTIP": "Drukt de opgegeven tekst, getal of een andere waarde af.", - "TEXT_PROMPT_HELPURL": "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user", - "TEXT_PROMPT_TYPE_TEXT": "vraagt om invoer met bericht", - "TEXT_PROMPT_TYPE_NUMBER": "vraagt de gebruiker om een getal met de tekst", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Vraagt de gebruiker om een getal in te voeren.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Vraagt de gebruiker om invoer.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "maak een lege lijst", - "LISTS_CREATE_EMPTY_TOOLTIP": "Geeft een lijst terug met lengte 0, zonder items", - "LISTS_CREATE_WITH_TOOLTIP": "Maak een lijst met een willekeurig aantal items.", - "LISTS_CREATE_WITH_INPUT_WITH": "maak een lijst met", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "lijst", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Voeg stukken toe, verwijder ze of wijzig de volgorde om dit lijstblok aan te passen.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Voeg iets toe aan de lijst.", - "LISTS_REPEAT_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_REPEAT_TOOLTIP": "Maakt een lijst die bestaat uit de opgegeven waarde, het opgegeven aantal keer herhaald.", - "LISTS_REPEAT_TITLE": "Maak lijst met item %1, %2 keer herhaald", - "LISTS_LENGTH_HELPURL": "https://github.com/google/blockly/wiki/Lists#length-of", - "LISTS_LENGTH_TITLE": "lengte van %1", - "LISTS_LENGTH_TOOLTIP": "Geeft de lengte van een lijst terug.", - "LISTS_ISEMPTY_TITLE": "%1 is leeg", - "LISTS_ISEMPTY_TOOLTIP": "Geeft waar terug als de lijst leeg is.", - "LISTS_INLIST": "in lijst", - "LISTS_INDEX_OF_HELPURL": "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list", - "LISTS_INDEX_OF_FIRST": "zoek eerste voorkomen van item", - "LISTS_INDEX_OF_LAST": "zoek laatste voorkomen van item", - "LISTS_INDEX_OF_TOOLTIP": "Geeft de index terug van het eerste of laatste voorkomen van een item in de lijst. Geeft %1 terug als het item niet is gevonden.", - "LISTS_GET_INDEX_GET": "haal op", - "LISTS_GET_INDEX_GET_REMOVE": "haal op en verwijder", - "LISTS_GET_INDEX_REMOVE": "verwijder", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# van einde", - "LISTS_GET_INDEX_FIRST": "eerste", - "LISTS_GET_INDEX_LAST": "laatste", - "LISTS_GET_INDEX_RANDOM": "willekeurig", - "LISTS_INDEX_FROM_START_TOOLTIP": "Item %1 is het eerste item.", - "LISTS_INDEX_FROM_END_TOOLTIP": "Item %1 is het laatste item.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Geeft het item op de opgegeven positie in een lijst.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Geeft het eerste item in een lijst terug.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Geeft het laatste item in een lijst terug.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Geeft een willekeurig item uit een lijst.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Geeft het item op de opgegeven positie in een lijst terug en verwijdert het.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Geeft het laatste item in een lijst terug en verwijdert het.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Geeft het laatste item uit een lijst terug en verwijdert het.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Geeft een willekeurig item in een lijst terug en verwijdert het.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Verwijdert het item op de opgegeven positie in een lijst.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Verwijdert het eerste item in een lijst.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Verwijdert het laatste item uit een lijst.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Verwijdert een willekeurig item uit een lijst.", - "LISTS_SET_INDEX_HELPURL": "https://github.com/google/blockly/wiki/Lists#in-list--set", - "LISTS_SET_INDEX_SET": "stel in", - "LISTS_SET_INDEX_INSERT": "tussenvoegen op", - "LISTS_SET_INDEX_INPUT_TO": "als", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Stelt het item op de opgegeven positie in de lijst in.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Stelt het eerste item in een lijst in.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Stelt het laatste item van een lijst in.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Stelt een willekeurig item uit de lijst in.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Voegt het item op een opgegeven positie in een lijst in.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Voegt het item toe aan het begin van de lijst.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Voeg het item aan het einde van een lijst toe.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Voegt het item op een willekeurige positie in de lijst in.", - "LISTS_GET_SUBLIST_HELPURL": "https://github.com/google/blockly/wiki/Lists#getting-a-sublist", - "LISTS_GET_SUBLIST_START_FROM_START": "haal sublijst op vanaf positie", - "LISTS_GET_SUBLIST_START_FROM_END": "haal sublijst op van positie vanaf einde", - "LISTS_GET_SUBLIST_START_FIRST": "haal sublijst op vanaf eerste", - "LISTS_GET_SUBLIST_END_FROM_START": "naar item", - "LISTS_GET_SUBLIST_END_FROM_END": "naar # vanaf einde", - "LISTS_GET_SUBLIST_END_LAST": "naar laatste", - "LISTS_GET_SUBLIST_TOOLTIP": "Maakt een kopie van het opgegeven deel van de lijst.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "sorteer %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Sorteer een kopie van een lijst.", - "LISTS_SORT_ORDER_ASCENDING": "oplopend", - "LISTS_SORT_ORDER_DESCENDING": "aflopend", - "LISTS_SORT_TYPE_NUMERIC": "numerieke", - "LISTS_SORT_TYPE_TEXT": "in alfabetische volgorde", - "LISTS_SORT_TYPE_IGNORECASE": "alfabetisch, negeer hoofd-/kleine letters", - "LISTS_SPLIT_LIST_FROM_TEXT": "lijst maken van tekst", - "LISTS_SPLIT_TEXT_FROM_LIST": "tekst maken van lijst", - "LISTS_SPLIT_WITH_DELIMITER": "met scheidingsteken", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Tekst splitsen in een lijst van teksten op basis van een scheidingsteken.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Lijst van tekstdelen samenvoegen in één stuk tekst, waarbij de tekstdelen gescheiden zijn door een scheidingsteken.", - "VARIABLES_GET_HELPURL": "https://github.com/google/blockly/wiki/Variables#get", - "VARIABLES_GET_TOOLTIP": "Geeft de waarde van deze variabele.", - "VARIABLES_GET_CREATE_SET": "Maak \"verander %1\"", - "VARIABLES_SET_HELPURL": "https://github.com/google/blockly/wiki/Variables#set", - "VARIABLES_SET": "stel %1 in op %2", - "VARIABLES_SET_TOOLTIP": "Verandert de waarde van de variabele naar de waarde van de invoer.", - "VARIABLES_SET_CREATE_GET": "Maak 'opvragen van %1'", - "PROCEDURES_DEFNORETURN_HELPURL": "https://nl.wikipedia.org/wiki/Subprogramma", - "PROCEDURES_DEFNORETURN_TITLE": "om", - "PROCEDURES_DEFNORETURN_PROCEDURE": "doe iets", - "PROCEDURES_BEFORE_PARAMS": "met:", - "PROCEDURES_CALL_BEFORE_PARAMS": "met:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Maakt een functie zonder uitvoer.", - "PROCEDURES_DEFNORETURN_COMMENT": "Deze functie beschrijven...", - "PROCEDURES_DEFRETURN_HELPURL": "https://nl.wikipedia.org/wiki/Subprogramma", - "PROCEDURES_DEFRETURN_RETURN": "uitvoeren", - "PROCEDURES_DEFRETURN_TOOLTIP": "Maakt een functie met een uitvoer.", - "PROCEDURES_ALLOW_STATEMENTS": "statements toestaan", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Waarschuwing: deze functie heeft parameters met dezelfde naam.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://nl.wikipedia.org/wiki/Subprogramma", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Voer de door de gebruiker gedefinieerde functie \"%1\" uit.", - "PROCEDURES_CALLRETURN_HELPURL": "https://nl.wikipedia.org/wiki/Subprogramma", - "PROCEDURES_CALLRETURN_TOOLTIP": "Voer de door de gebruiker gedefinieerde functie \"%1\" uit en gebruik de uitvoer.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "ingangen", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Invoer van deze functie toevoegen, verwijderen of herordenen.", - "PROCEDURES_MUTATORARG_TITLE": "invoernaam:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Een invoer aan de functie toevoegen.", - "PROCEDURES_HIGHLIGHT_DEF": "Accentueer functiedefinitie", - "PROCEDURES_CREATE_DO": "Maak \"%1\"", - "PROCEDURES_IFRETURN_TOOLTIP": "Als de eerste waarde \"waar\" is, geef dan de tweede waarde terug.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Waarschuwing: dit blok mag alleen gebruikt worden binnen de definitie van een functie." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/oc.json b/backend/_pv_1_3_5/static/blockly/msg/json/oc.json deleted file mode 100755 index 1abd5061c..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/oc.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Cedric31" - ] - }, - "VARIABLES_DEFAULT_NAME": "element", - "DUPLICATE_BLOCK": "Duplicar", - "ADD_COMMENT": "Apondre un comentari", - "REMOVE_COMMENT": "Suprimir un comentari", - "EXTERNAL_INPUTS": "Entradas extèrnas", - "INLINE_INPUTS": "Entradas en linha", - "DELETE_BLOCK": "Suprimir lo blòt", - "DELETE_X_BLOCKS": "Suprimir %1 blòts", - "DELETE_ALL_BLOCKS": "Suprimir totes los %1 blòts ?", - "COLLAPSE_BLOCK": "Redusir lo blòt", - "COLLAPSE_ALL": "Redusir los blòts", - "EXPAND_BLOCK": "Desvolopar lo blòt", - "EXPAND_ALL": "Desvolopar los blòts", - "DISABLE_BLOCK": "Desactivar lo blòt", - "ENABLE_BLOCK": "Activar lo blòt", - "HELP": "Ajuda", - "CHANGE_VALUE_TITLE": "Modificar la valor :", - "RENAME_VARIABLE": "Renomenar la variabla…", - "NEW_VARIABLE": "Variabla novèla…", - "NEW_VARIABLE_TITLE": "Nom de la novèla variabla :", - "COLOUR_PICKER_HELPURL": "https://oc.wikipedia.org/wiki/Color", - "COLOUR_RANDOM_TITLE": "color aleatòria", - "COLOUR_RANDOM_TOOLTIP": "Causir una color a l'azard.", - "COLOUR_RGB_TITLE": "colorar amb", - "COLOUR_RGB_RED": "roge", - "COLOUR_RGB_GREEN": "verd", - "COLOUR_RGB_BLUE": "blau", - "COLOUR_BLEND_TITLE": "mesclar", - "COLOUR_BLEND_COLOUR1": "color 1", - "COLOUR_BLEND_COLOUR2": "color 2", - "COLOUR_BLEND_RATIO": "ratio", - "CONTROLS_REPEAT_HELPURL": "https://oc.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "repetir %1 còps", - "CONTROLS_REPEAT_INPUT_DO": "far", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "repetir tant que", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "repetir fins a", - "CONTROLS_FOR_TITLE": "comptar amb %1 de %2 a %3 per %4", - "CONTROLS_FOREACH_TITLE": "per cada element %1 dins la lista %2", - "CONTROLS_IF_MSG_IF": "se", - "CONTROLS_IF_MSG_ELSEIF": "siquenon se", - "CONTROLS_IF_MSG_ELSE": "siquenon", - "LOGIC_OPERATION_AND": "e", - "LOGIC_OPERATION_OR": "o", - "LOGIC_NEGATE_TITLE": "pas %1", - "LOGIC_BOOLEAN_TRUE": "verai", - "LOGIC_BOOLEAN_FALSE": "fals", - "LOGIC_NULL": "nul", - "LOGIC_NULL_TOOLTIP": "Renvia nul.", - "LOGIC_TERNARY_CONDITION": "tèst", - "LOGIC_TERNARY_IF_TRUE": "se verai", - "LOGIC_TERNARY_IF_FALSE": "se fals", - "MATH_NUMBER_HELPURL": "https://oc.wikipedia.org/wiki/Nombre", - "MATH_NUMBER_TOOLTIP": "Un nombre.", - "MATH_ARITHMETIC_HELPURL": "https://oc.wikipedia.org/wiki/Aritmetica", - "MATH_SINGLE_OP_ROOT": "raiç carrada", - "MATH_SINGLE_OP_ABSOLUTE": "absolut", - "MATH_IS_EVEN": "es par", - "MATH_IS_ODD": "es impar", - "MATH_IS_PRIME": "es primièr", - "MATH_IS_WHOLE": "es entièr", - "MATH_IS_POSITIVE": "es positiu", - "MATH_IS_NEGATIVE": "es negatiu", - "MATH_IS_DIVISIBLE_BY": "es devesible per", - "MATH_CHANGE_TITLE": "incrementar %1 per %2", - "MATH_ROUND_OPERATOR_ROUND": "arredondir", - "MATH_ROUND_OPERATOR_ROUNDUP": "arredondir al superior", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "arredondir a l’inferior", - "MATH_ONLIST_OPERATOR_SUM": "soma de la lista", - "MATH_ONLIST_OPERATOR_MIN": "minimum de la lista", - "MATH_ONLIST_OPERATOR_MAX": "maximum de la lista", - "MATH_ONLIST_OPERATOR_AVERAGE": "mejana de la lista", - "MATH_ONLIST_OPERATOR_MEDIAN": "mediana de la lista", - "TEXT_APPEND_TO": "a", - "TEXT_APPEND_APPENDTEXT": "apondre lo tèxte", - "TEXT_LENGTH_TITLE": "longor de %1", - "TEXT_ISEMPTY_TITLE": "%1 es void", - "TEXT_INDEXOF_INPUT_INTEXT": "dins lo tèxte", - "TEXT_CHARAT_INPUT_INTEXT": "dins lo tèxte", - "TEXT_CHARAT_FROM_START": "obténer la letra #", - "TEXT_CHARAT_FROM_END": "obténer la letra # dempuèi la fin", - "TEXT_CHARAT_FIRST": "obténer la primièra letra", - "TEXT_CHARAT_LAST": "obténer la darrièra letra", - "TEXT_CHARAT_RANDOM": "obténer una letra a l'azard", - "TEXT_CHARAT_TOOLTIP": "Renvia la letra a la posicion indicada.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "dins lo tèxte", - "TEXT_GET_SUBSTRING_END_FROM_START": "fins a la letra #", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "en MAJUSCULAS", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "en minusculas", - "TEXT_PRINT_TITLE": "afichar %1", - "LISTS_CREATE_WITH_INPUT_WITH": "crear una lista amb", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "lista", - "LISTS_INLIST": "dins la lista", - "LISTS_GET_INDEX_GET": "obténer", - "LISTS_GET_INDEX_GET_REMOVE": "obténer e suprimir", - "LISTS_GET_INDEX_REMOVE": "suprimit", - "LISTS_GET_INDEX_FROM_END": "# dempuèi la fin", - "LISTS_GET_INDEX_FIRST": "primièr", - "LISTS_GET_INDEX_LAST": "darrièr", - "LISTS_GET_INDEX_RANDOM": "aleatòri", - "LISTS_SET_INDEX_SET": "metre", - "LISTS_SET_INDEX_INSERT": "inserir en", - "LISTS_SET_INDEX_INPUT_TO": "coma", - "LISTS_GET_SUBLIST_END_FROM_START": "fins a #", - "LISTS_GET_SUBLIST_END_FROM_END": "fins a # dempuèi la fin", - "LISTS_GET_SUBLIST_END_LAST": "fins a la fin", - "VARIABLES_GET_CREATE_SET": "Crear 'fixar %1'", - "VARIABLES_SET": "fixar %1 a %2", - "PROCEDURES_DEFNORETURN_TITLE": "a", - "PROCEDURES_DEFNORETURN_PROCEDURE": "far quicòm", - "PROCEDURES_BEFORE_PARAMS": "amb :", - "PROCEDURES_CALL_BEFORE_PARAMS": "amb :", - "PROCEDURES_DEFRETURN_RETURN": "retorn", - "PROCEDURES_MUTATORCONTAINER_TITLE": "entradas", - "PROCEDURES_MUTATORARG_TITLE": "nom de l’entrada :", - "PROCEDURES_CREATE_DO": "Crear '%1'" -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/pl.json b/backend/_pv_1_3_5/static/blockly/msg/json/pl.json deleted file mode 100755 index 709886edc..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/pl.json +++ /dev/null @@ -1,345 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Cotidianis", - "Faren", - "Vengir", - "Pbz", - "Pio387", - "아라", - "Mateon1", - "Expert3222", - "Cirasean", - "Fringoo", - "Chrumps" - ] - }, - "VARIABLES_DEFAULT_NAME": "element", - "TODAY": "Dzisiaj", - "DUPLICATE_BLOCK": "Duplikuj", - "ADD_COMMENT": "Dodaj komentarz", - "REMOVE_COMMENT": "Usuń komentarz", - "EXTERNAL_INPUTS": "Zewnętrzne wejścia", - "INLINE_INPUTS": "Wbudowane wejścia", - "DELETE_BLOCK": "Usuń blok", - "DELETE_X_BLOCKS": "Usuń %1 bloki(ów)", - "DELETE_ALL_BLOCKS": "Usunąć wszystkie %1 bloki(ów)?", - "CLEAN_UP": "Uporządkuj bloki", - "COLLAPSE_BLOCK": "Zwiń blok", - "COLLAPSE_ALL": "Zwiń bloki", - "EXPAND_BLOCK": "Rozwiń blok", - "EXPAND_ALL": "Rozwiń bloki", - "DISABLE_BLOCK": "Wyłącz blok", - "ENABLE_BLOCK": "Włącz blok", - "HELP": "Pomoc", - "UNDO": "Cofnij", - "REDO": "Ponów", - "CHANGE_VALUE_TITLE": "Zmień wartość:", - "RENAME_VARIABLE": "Zmień nazwę zmiennej...", - "RENAME_VARIABLE_TITLE": "Zmień nazwy wszystkich '%1' zmiennych na:", - "NEW_VARIABLE": "Nowa zmienna...", - "NEW_VARIABLE_TITLE": "Nowa nazwa zmiennej:", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "Wybierz kolor z palety.", - "COLOUR_RANDOM_TITLE": "losowy kolor", - "COLOUR_RANDOM_TOOLTIP": "Wybierz kolor w sposób losowy.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "kolor z", - "COLOUR_RGB_RED": "czerwony", - "COLOUR_RGB_GREEN": "zielony", - "COLOUR_RGB_BLUE": "niebieski", - "COLOUR_RGB_TOOLTIP": "Połącz czerwony, zielony i niebieski w odpowiednich proporcjach, tak aby powstał nowy kolor. Zawartość każdego z nich określa liczba z przedziału od 0 do 100.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "wymieszaj", - "COLOUR_BLEND_COLOUR1": "kolor 1", - "COLOUR_BLEND_COLOUR2": "kolor 2", - "COLOUR_BLEND_RATIO": "proporcja", - "COLOUR_BLEND_TOOLTIP": "Miesza dwa kolory w danej proporcji (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "powtórz %1 razy", - "CONTROLS_REPEAT_INPUT_DO": "wykonaj", - "CONTROLS_REPEAT_TOOLTIP": "Wykonaj niektóre instrukcje kilka razy.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "powtarzaj dopóki", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "powtarzaj aż", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Gdy wartość jest prawdziwa, wykonaj kilka instrukcji.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Gdy wartość jest nieprawdziwa, wykonaj kilka instrukcji.", - "CONTROLS_FOR_TOOLTIP": "Przypisuje zmiennej %1 wartości od numeru startowego do numeru końcowego, licząc co określony interwał, wykonując określone bloki.", - "CONTROLS_FOR_TITLE": "licz z %1 od %2 do %3 co %4 (wartość kroku)", - "CONTROLS_FOREACH_TITLE": "dla każdego elementu %1 na liście %2", - "CONTROLS_FOREACH_TOOLTIP": "Dla każdego elementu listy ustaw zmienną %1 na ten element, a następnie wykonaj kilka instrukcji.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "wyjdź z pętli", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "przejdź do kolejnej iteracji pętli", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Wyjdź z zawierającej pętli.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Pomiń resztę pętli i kontynuuj w kolejnej iteracji.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Uwaga: Ten blok może być użyty tylko w pętli.", - "CONTROLS_IF_TOOLTIP_1": "Jeśli wartość jest prawdziwa, to wykonaj kilka instrukcji.", - "CONTROLS_IF_TOOLTIP_2": "Jeśli wartość jest prawdziwa, to wykonaj pierwszy blok instrukcji. W przeciwnym razie, wykonaj drugi blok instrukcji.", - "CONTROLS_IF_TOOLTIP_3": "Jeśli pierwsza wartość jest prawdziwa, to wykonaj pierwszy blok instrukcji. W przeciwnym razie, jeśli druga wartość jest prawdziwa, to wykonaj drugi blok instrukcji.", - "CONTROLS_IF_TOOLTIP_4": "Jeśli pierwsza wartość jest prawdziwa, wykonaj pierwszy blok instrukcji. W przeciwnym razie jeśli druga wartość jest prawdziwa, wykonaj drugi blok instrukcji. Jeżeli żadna z wartości nie jest prawdziwa, wykonaj ostatni blok instrukcji.", - "CONTROLS_IF_MSG_IF": "jeśli", - "CONTROLS_IF_MSG_ELSEIF": "w przeciwnym razie, jeśli", - "CONTROLS_IF_MSG_ELSE": "w przeciwnym razie", - "CONTROLS_IF_IF_TOOLTIP": "Dodaj, usuń lub zmień kolejność bloków, żeby zmodyfikować ten blok „jeśli”.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Dodaj warunek do bloku „jeśli”.", - "CONTROLS_IF_ELSE_TOOLTIP": "Dodaj ostatni warunek do bloku „jeśli”, gdy żaden wcześniejszy nie był spełniony.", - "LOGIC_COMPARE_HELPURL": "https://pl.wikipedia.org/wiki/Nierówność", - "LOGIC_COMPARE_TOOLTIP_EQ": "Zwróć \"prawda\", jeśli oba wejścia są sobie równe.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Zwróć \"prawda\", jeśli oba wejścia są sobie nierówne.", - "LOGIC_COMPARE_TOOLTIP_LT": "Zwróć \"prawda\" jeśli pierwsze wejście jest większe od drugiego.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Zwróć \"prawda\", jeśli pierwsze wejście jest większe lub równe drugiemu.", - "LOGIC_COMPARE_TOOLTIP_GT": "Zwróć \"prawda\" jeśli pierwsze wejście jest większe od drugiego.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Zwróć \"prawda\", jeśli pierwsze wejście jest większe lub równe drugiemu.", - "LOGIC_OPERATION_TOOLTIP_AND": "Zwróć \"prawda\" jeśli oba dane elementy mają wartość \"prawda\".", - "LOGIC_OPERATION_AND": "i", - "LOGIC_OPERATION_TOOLTIP_OR": "Zwróć \"prawda\" jeśli co najmniej jeden dany element ma wartość \"prawda\".", - "LOGIC_OPERATION_OR": "lub", - "LOGIC_NEGATE_TITLE": "nie %1", - "LOGIC_NEGATE_TOOLTIP": "Zwraca \"prawda\", jeśli dane wejściowe są fałszywe. Zwraca \"fałsz\", jeśli dana wejściowa jest prawdziwa.", - "LOGIC_BOOLEAN_TRUE": "prawda", - "LOGIC_BOOLEAN_FALSE": "fałsz", - "LOGIC_BOOLEAN_TOOLTIP": "Zwraca 'prawda' lub 'fałsz'.", - "LOGIC_NULL_HELPURL": "https://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "nic", - "LOGIC_NULL_TOOLTIP": "Zwraca nic.", - "LOGIC_TERNARY_HELPURL": "https://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "jeśli prawda", - "LOGIC_TERNARY_IF_FALSE": "jeśli fałsz", - "LOGIC_TERNARY_TOOLTIP": "Sprawdź warunek w „test”. Jeśli warunek jest prawdziwy, to zwróci „jeśli prawda”; jeśli nie jest prawdziwy to zwróci „jeśli fałsz”.", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "Liczba.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "/", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tg", - "MATH_TRIG_ASIN": "arcsin", - "MATH_TRIG_ACOS": "arccos", - "MATH_TRIG_ATAN": "arctg", - "MATH_ARITHMETIC_HELPURL": "https://pl.wikipedia.org/wiki/Arytmetyka", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Zwróć sumę dwóch liczb.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Zwróć różnicę dwóch liczb.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Zwróć iloczyn dwóch liczb.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Zwróć iloraz dwóch liczb.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Zwróć pierwszą liczbę podniesioną do potęgi o wykładniku drugiej liczby.", - "MATH_SINGLE_HELPURL": "https://pl.wikipedia.org/wiki/Pierwiastek_kwadratowy", - "MATH_SINGLE_OP_ROOT": "pierwiastek kwadratowy", - "MATH_SINGLE_TOOLTIP_ROOT": "Zwróć pierwiastek kwadratowy danej liczby.", - "MATH_SINGLE_OP_ABSOLUTE": "wartość bezwzględna", - "MATH_SINGLE_TOOLTIP_ABS": "Zwróć wartość bezwzględną danej liczby.", - "MATH_SINGLE_TOOLTIP_NEG": "Zwróć negację danej liczby.", - "MATH_SINGLE_TOOLTIP_LN": "Zwróć logarytm naturalny danej liczby.", - "MATH_SINGLE_TOOLTIP_LOG10": "Zwraca logarytm dziesiętny danej liczby.", - "MATH_SINGLE_TOOLTIP_EXP": "Zwróć e do potęgi danej liczby.", - "MATH_SINGLE_TOOLTIP_POW10": "Zwróć 10 do potęgi danej liczby.", - "MATH_TRIG_HELPURL": "https://pl.wikipedia.org/wiki/Funkcje_trygonometryczne", - "MATH_TRIG_TOOLTIP_SIN": "Zwróć wartość sinusa o stopniu (nie w radianach).", - "MATH_TRIG_TOOLTIP_COS": "Zwróć wartość cosinusa o stopniu (nie w radianach).", - "MATH_TRIG_TOOLTIP_TAN": "Zwróć tangens o stopniu (nie w radianach).", - "MATH_TRIG_TOOLTIP_ASIN": "Zwróć arcus sinus danej liczby.", - "MATH_TRIG_TOOLTIP_ACOS": "Zwróć arcus cosinus danej liczby.", - "MATH_TRIG_TOOLTIP_ATAN": "Zwróć arcus tangens danej liczby.", - "MATH_CONSTANT_HELPURL": "https://pl.wikipedia.org/wiki/Stała_(matematyka)", - "MATH_CONSTANT_TOOLTIP": "Zwróć jedną wspólną stałą: π (3.141), e (2.718...), φ (1.618...), sqrt(2) (1.414...), sqrt(½) (0.707...) lub ∞ (nieskończoność).", - "MATH_IS_EVEN": "jest parzysta", - "MATH_IS_ODD": "jest nieparzysta", - "MATH_IS_PRIME": "jest liczbą pierwszą", - "MATH_IS_WHOLE": "jest liczbą całkowitą", - "MATH_IS_POSITIVE": "jest dodatnia", - "MATH_IS_NEGATIVE": "jest ujemna", - "MATH_IS_DIVISIBLE_BY": "jest podzielna przez", - "MATH_IS_TOOLTIP": "Sprawdź, czy liczba jest parzysta, nieparzysta, pierwsza, całkowita, dodatnia, ujemna, lub czy jest podzielna przez podaną liczbę. Zwraca wartość \"prawda\" lub \"fałsz\".", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "zmień %1 o %2", - "MATH_CHANGE_TOOLTIP": "Dodaj liczbę do zmiennej '%1'.", - "MATH_ROUND_HELPURL": "https://pl.wikipedia.org/wiki/Zaokrąglanie", - "MATH_ROUND_TOOLTIP": "Zaokrąglij w górę lub w dół.", - "MATH_ROUND_OPERATOR_ROUND": "zaokrąglij", - "MATH_ROUND_OPERATOR_ROUNDUP": "zaokrąglij w górę", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "zaokrąglij w dół", - "MATH_ONLIST_HELPURL": "", - "MATH_ONLIST_OPERATOR_SUM": "suma elementów listy", - "MATH_ONLIST_TOOLTIP_SUM": "Zwróć sumę wszystkich liczb z listy.", - "MATH_ONLIST_OPERATOR_MIN": "minimalna wartość z listy", - "MATH_ONLIST_TOOLTIP_MIN": "Zwróć najmniejszą liczbę w liście.", - "MATH_ONLIST_OPERATOR_MAX": "maksymalna wartość z listy", - "MATH_ONLIST_TOOLTIP_MAX": "Zwróć największą liczbę w liście.", - "MATH_ONLIST_OPERATOR_AVERAGE": "średnia elementów listy", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Zwróć średnią (średnią arytmetyczną) wartości liczbowych z listy.", - "MATH_ONLIST_OPERATOR_MEDIAN": "mediana listy", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Zwróć medianę listy.", - "MATH_ONLIST_OPERATOR_MODE": "dominanty listy", - "MATH_ONLIST_TOOLTIP_MODE": "Zwróć listę najczęściej występujących elementów w liście.", - "MATH_ONLIST_OPERATOR_STD_DEV": "odchylenie standardowe listy", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Zwróć odchylenie standardowe listy.", - "MATH_ONLIST_OPERATOR_RANDOM": "losowy element z listy", - "MATH_ONLIST_TOOLTIP_RANDOM": "Zwróć losowy element z listy.", - "MATH_MODULO_HELPURL": "https://pl.wikipedia.org/wiki/Modulo", - "MATH_MODULO_TITLE": "reszta z dzielenia %1 przez %2", - "MATH_MODULO_TOOLTIP": "Zwróć resztę z dzielenia dwóch liczb przez siebie.", - "MATH_CONSTRAIN_TITLE": "ogranicz %1 z dołu %2 z góry %3", - "MATH_CONSTRAIN_TOOLTIP": "Ogranicz liczbę, aby była w określonych granicach (włącznie).", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "losowa liczba całkowita od %1 do %2", - "MATH_RANDOM_INT_TOOLTIP": "Zwróć losową liczbę całkowitą w ramach dwóch wyznaczonych granic, włącznie.", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "losowy ułamek", - "MATH_RANDOM_FLOAT_TOOLTIP": "Zwróć losowy ułamek między 0.0 (włącznie), a 1.0 (wyłącznie).", - "TEXT_TEXT_HELPURL": "https://pl.wikipedia.org/wiki/Tekstowy_typ_danych", - "TEXT_TEXT_TOOLTIP": "Litera, wyraz lub linia tekstu.", - "TEXT_JOIN_TITLE_CREATEWITH": "utwórz tekst z", - "TEXT_JOIN_TOOLTIP": "Tworzy fragment tekstu, łącząc ze sobą dowolną liczbę tekstów.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "połącz", - "TEXT_CREATE_JOIN_TOOLTIP": "Dodaj, usuń lub zmień kolejność sekcji, aby zmodyfikować blok tekstowy.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Dodaj element do tekstu.", - "TEXT_APPEND_TO": "do", - "TEXT_APPEND_APPENDTEXT": "dołącz tekst", - "TEXT_APPEND_TOOLTIP": "Dołącz tekst do zmiennej '%1'.", - "TEXT_LENGTH_TITLE": "długość %1", - "TEXT_LENGTH_TOOLTIP": "Zwraca liczbę liter (łącznie ze spacjami) w podanym tekście.", - "TEXT_ISEMPTY_TITLE": "%1 jest pusty", - "TEXT_ISEMPTY_TOOLTIP": "Zwraca prawda (true), jeśli podany tekst jest pusty.", - "TEXT_INDEXOF_TOOLTIP": "Zwraca indeks pierwszego/ostatniego wystąpienia pierwszego tekstu w drugim tekście. Zwraca wartość %1, jeśli tekst nie został znaleziony.", - "TEXT_INDEXOF_INPUT_INTEXT": "w tekście", - "TEXT_INDEXOF_OPERATOR_FIRST": "znajdź pierwsze wystąpienie tekstu", - "TEXT_INDEXOF_OPERATOR_LAST": "znajdź ostatnie wystąpienie tekstu", - "TEXT_INDEXOF_TAIL": "", - "TEXT_CHARAT_INPUT_INTEXT": "z tekstu", - "TEXT_CHARAT_FROM_START": "pobierz literę #", - "TEXT_CHARAT_FROM_END": "pobierz literę # od końca", - "TEXT_CHARAT_FIRST": "pobierz pierwszą literę", - "TEXT_CHARAT_LAST": "pobierz ostatnią literę", - "TEXT_CHARAT_RANDOM": "pobierz losową literę", - "TEXT_CHARAT_TAIL": "", - "TEXT_CHARAT_TOOLTIP": "Zwraca literę z określonej pozycji.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Zwraca określoną część tekstu.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "w tekście", - "TEXT_GET_SUBSTRING_START_FROM_START": "pobierz podciąg od # litery", - "TEXT_GET_SUBSTRING_START_FROM_END": "pobierz podciąg od # litery od końca", - "TEXT_GET_SUBSTRING_START_FIRST": "pobierz podciąg od pierwszej litery", - "TEXT_GET_SUBSTRING_END_FROM_START": "do # litery", - "TEXT_GET_SUBSTRING_END_FROM_END": "do # litery od końca", - "TEXT_GET_SUBSTRING_END_LAST": "do ostatniej litery", - "TEXT_GET_SUBSTRING_TAIL": "", - "TEXT_CHANGECASE_TOOLTIP": "Zwraca kopię tekstu z inną wielkością liter.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "zmień na WIELKIE LITERY", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "zmień na małe litery", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "zmień na od Wielkich Liter", - "TEXT_TRIM_TOOLTIP": "Zwraca kopię tekstu z usuniętymi spacjami z jednego lub z obu końców tekstu.", - "TEXT_TRIM_OPERATOR_BOTH": "usuń spacje po obu stronach", - "TEXT_TRIM_OPERATOR_LEFT": "usuń spacje z lewej strony", - "TEXT_TRIM_OPERATOR_RIGHT": "usuń spacje z prawej strony", - "TEXT_PRINT_TITLE": "wydrukuj %1", - "TEXT_PRINT_TOOLTIP": "Drukuj określony tekst, liczbę lub inną wartość.", - "TEXT_PROMPT_TYPE_TEXT": "poproś o tekst z tą wiadomością", - "TEXT_PROMPT_TYPE_NUMBER": "poproś o liczbę z tą wiadomością", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Zapytaj użytkownika o liczbę.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Zapytaj użytkownika o jakiś tekst.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "utwórz pustą listę", - "LISTS_CREATE_EMPTY_TOOLTIP": "Zwraca listę, o długości 0, nie zawierającą rekordów z danymi", - "LISTS_CREATE_WITH_TOOLTIP": "Utwórz listę z dowolną ilością elementów.", - "LISTS_CREATE_WITH_INPUT_WITH": "Tworzenie listy z", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "lista", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Dodaj, usuń lub zmień kolejność sekcji żeby skonfigurować ten blok listy.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Dodaj element do listy.", - "LISTS_REPEAT_TOOLTIP": "Tworzy listę składającą się z podanej wartości powtórzonej odpowiednią liczbę razy.", - "LISTS_REPEAT_TITLE": "stwórz listę, powtarzając element %1 %2 razy", - "LISTS_LENGTH_TITLE": "długość %1", - "LISTS_LENGTH_TOOLTIP": "Zwraca długość listy.", - "LISTS_ISEMPTY_TITLE": "%1 jest pusty", - "LISTS_ISEMPTY_TOOLTIP": "Zwraca \"prawda\" jeśli lista jest pusta.", - "LISTS_INLIST": "na liście", - "LISTS_INDEX_OF_FIRST": "znaleźć pierwsze wystąpienie elementu", - "LISTS_INDEX_OF_LAST": "znajduje ostatanie wystąpienie elementu", - "LISTS_INDEX_OF_TOOLTIP": "Zwraca indeks pierwszego/ostatniego wystąpienia elementu na liście. Zwraca wartość %1, jeśli tekst nie zostanie znaleziony.", - "LISTS_GET_INDEX_GET": "pobierz", - "LISTS_GET_INDEX_GET_REMOVE": "Pobierz i usuń", - "LISTS_GET_INDEX_REMOVE": "usuń", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# od końca", - "LISTS_GET_INDEX_FIRST": "pierwszy", - "LISTS_GET_INDEX_LAST": "ostatni", - "LISTS_GET_INDEX_RANDOM": "losowy", - "LISTS_GET_INDEX_TAIL": "", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 to pierwszy element.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 to ostatni element.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Zwraca element z konkretnej pozycji na liście.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Zwraca pierwszy element z listy.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Zwraca ostatni element z listy.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Zwraca losowy element z listy.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Usuwa i zwraca element z określonej pozycji na liście.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Usuwa i zwraca pierwszy element z listy.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Usuwa i zwraca ostatni element z listy.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Usuwa i zwraca losowy element z listy.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Usuwa element z określonej pozycji na liście.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Usuwa pierwszy element z listy.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Usuwa ostatni element z listy.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Usuwa losowy element z listy.", - "LISTS_SET_INDEX_SET": "ustaw", - "LISTS_SET_INDEX_INSERT": "wstaw w", - "LISTS_SET_INDEX_INPUT_TO": "jako", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Ustawia element w określonym miejscu na liście.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Ustawia pierwszy element na liście.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Ustawia ostatni element na liście.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Ustawia losowy element na liście.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Wstawia element w odpowiednim miejscu na liście.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Wstawia element na początku listy.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Dodaj element na koniec listy.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Wstawia element w losowym miejscu na liście.", - "LISTS_GET_SUBLIST_START_FROM_START": "Pobierz listę podrzędną z #", - "LISTS_GET_SUBLIST_START_FROM_END": "Pobierz listę podrzędną z # od końca", - "LISTS_GET_SUBLIST_START_FIRST": "Pobierz listę podrzędną z pierwszego", - "LISTS_GET_SUBLIST_END_FROM_START": "do #", - "LISTS_GET_SUBLIST_END_FROM_END": "do # od końca", - "LISTS_GET_SUBLIST_END_LAST": "do ostatniego", - "LISTS_GET_SUBLIST_TAIL": "", - "LISTS_GET_SUBLIST_TOOLTIP": "Tworzy kopię z określoną część listy.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "sortuj %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Sortuj kopię listy.", - "LISTS_SORT_ORDER_ASCENDING": "rosnąco", - "LISTS_SORT_ORDER_DESCENDING": "malejąco", - "LISTS_SORT_TYPE_NUMERIC": "numerycznie", - "LISTS_SORT_TYPE_TEXT": "alfabetycznie", - "LISTS_SORT_TYPE_IGNORECASE": "alfabetycznie, bez uwzględniania wielkości liter", - "LISTS_SPLIT_LIST_FROM_TEXT": "stwórz listę z tekstu", - "LISTS_SPLIT_TEXT_FROM_LIST": "stwórz tekst z listy", - "LISTS_SPLIT_WITH_DELIMITER": "z separatorem", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Rozdziela tekst na listę mniejszych tekstów, dzieląc na każdym separatorze.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Łączy listę tekstów w jeden tekst, rozdzielany separatorem.", - "ORDINAL_NUMBER_SUFFIX": "", - "VARIABLES_GET_TOOLTIP": "Zwraca wartość tej zmiennej.", - "VARIABLES_GET_CREATE_SET": "Utwórz blok 'ustaw %1'", - "VARIABLES_SET": "przypisz %1 wartość %2", - "VARIABLES_SET_TOOLTIP": "Nadaj tej zmiennej wartość.", - "VARIABLES_SET_CREATE_GET": "Utwórz blok 'pobierz %1'", - "PROCEDURES_DEFNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFNORETURN_TITLE": "do", - "PROCEDURES_DEFNORETURN_PROCEDURE": "zrób coś", - "PROCEDURES_BEFORE_PARAMS": "z:", - "PROCEDURES_CALL_BEFORE_PARAMS": "z:", - "PROCEDURES_DEFNORETURN_DO": "", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Tworzy funkcję bez wyniku.", - "PROCEDURES_DEFNORETURN_COMMENT": "Opisz tę funkcję...", - "PROCEDURES_DEFRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFRETURN_RETURN": "zwróć", - "PROCEDURES_DEFRETURN_TOOLTIP": "Tworzy funkcję z wynikiem.", - "PROCEDURES_ALLOW_STATEMENTS": "zezwól na instrukcje", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Uwaga: Ta funkcja ma powtórzone parametry.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://pl.wikipedia.org/wiki/Podprogram", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Uruchom funkcję zdefiniowaną przez użytkownika '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "https://pl.wikipedia.org/wiki/Podprogram", - "PROCEDURES_CALLRETURN_TOOLTIP": "Uruchom funkcję zdefiniowaną przez użytkownika '%1' i skorzystaj z jej wyniku.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "wejścia", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Dodaj, usuń lub zmień kolejność danych wejściowych dla tej funkcji.", - "PROCEDURES_MUTATORARG_TITLE": "nazwa wejścia:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Dodaj dane wejściowe do funkcji.", - "PROCEDURES_HIGHLIGHT_DEF": "Podświetl definicję funkcji", - "PROCEDURES_CREATE_DO": "Stwórz '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Jeśli wartość jest prawdziwa, zwróć drugą wartość.", - "PROCEDURES_IFRETURN_WARNING": "Uwaga: Ten blok może być używany tylko w definicji funkcji." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/pms.json b/backend/_pv_1_3_5/static/blockly/msg/json/pms.json deleted file mode 100755 index 1147dfb56..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/pms.json +++ /dev/null @@ -1,314 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Borichèt" - ] - }, - "VARIABLES_DEFAULT_NAME": "element", - "TODAY": "Ancheuj", - "DUPLICATE_BLOCK": "Dupliché", - "ADD_COMMENT": "Gionté un coment", - "REMOVE_COMMENT": "Scancelé un coment", - "EXTERNAL_INPUTS": "Imission esterne", - "INLINE_INPUTS": "Imission an linia", - "DELETE_BLOCK": "Scancelé ël blòch", - "DELETE_X_BLOCKS": "Scancelé %1 blòch", - "DELETE_ALL_BLOCKS": "Scancelé tuti ij %1 blòch?", - "CLEAN_UP": "Dëscancelé ij blòch", - "COLLAPSE_BLOCK": "Arduve ël blòch", - "COLLAPSE_ALL": "Arduve ij blòch", - "EXPAND_BLOCK": "Dësvlupé ël blòch", - "EXPAND_ALL": "Dësvlupé ij blòch", - "DISABLE_BLOCK": "Disativé ël blòch", - "ENABLE_BLOCK": "Ativé ël blòch", - "HELP": "Agiut", - "UNDO": "Anulé", - "REDO": "Fé torna", - "CHANGE_VALUE_TITLE": "Modifiché ël valor:", - "RENAME_VARIABLE": "Arnomé la variàbil...", - "RENAME_VARIABLE_TITLE": "Arnomé tute le variàbij '%1' 'me:", - "NEW_VARIABLE": "Creé na variàbil...", - "NEW_VARIABLE_TITLE": "Nòm ëd la neuva variàbil:", - "VARIABLE_ALREADY_EXISTS": "Na variàbil con ël nòm '%1' a esist già.", - "DELETE_VARIABLE_CONFIRMATION": "Eliminé %1 utilisassion ëd la variàbil '%2'?", - "DELETE_VARIABLE": "Eliminé la variàbil '%1'", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "Serne un color ant la taulòssa.", - "COLOUR_RANDOM_TITLE": "color a asar", - "COLOUR_RANDOM_TOOLTIP": "Serne un color a asar.", - "COLOUR_RGB_TITLE": "coloré con", - "COLOUR_RGB_RED": "ross", - "COLOUR_RGB_GREEN": "verd", - "COLOUR_RGB_BLUE": "bleu", - "COLOUR_RGB_TOOLTIP": "Creé un color con la quantità spessificà ëd ross, verd e bleu. Tuti ij valor a devo esse antra 0 e 100.", - "COLOUR_BLEND_TITLE": "mës-cé", - "COLOUR_BLEND_COLOUR1": "color 1", - "COLOUR_BLEND_COLOUR2": "color 2", - "COLOUR_BLEND_RATIO": "rapòrt", - "COLOUR_BLEND_TOOLTIP": "A mës-cia doi color ansema con un rapòrt dàit (0,0 - 1,0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "arpete %1 vire", - "CONTROLS_REPEAT_INPUT_DO": "fé", - "CONTROLS_REPEAT_TOOLTIP": "Eseguì chèiche anstrussion vàire vire.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "arpete antramentre che", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "arpete fin-a a", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Cand un valor a l'é ver, eseguì chèiche anstrussion.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Cand un valor a l'é fàuss, eseguì chèiche anstrussion.", - "CONTROLS_FOR_TOOLTIP": "Fé an manera che la variàbil \"%1\" a pija ij valor dal nùmer inissial fin-a al nùmer final, an contand për l'antërval ëspessificà, e eseguì ij bloch ëspessificà.", - "CONTROLS_FOR_TITLE": "conté con %1 da %2 a %3 për %4", - "CONTROLS_FOREACH_TITLE": "për minca n'element %1 ant la lista %2", - "CONTROLS_FOREACH_TOOLTIP": "Për minca element an na lista, dé ël valor ëd l'element a la variàbil '%1', peui eseguì chèiche anstrussion.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "seurte da la liassa", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "continué con l'iterassion sucessiva dla liassa", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Seurte da la liassa anglobanta.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Sauté ël rest ëd sa liassa, e continué con l'iterassion apress.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Atension: Ës blòch a peul mach esse dovrà andrinta a na liassa.", - "CONTROLS_IF_TOOLTIP_1": "Si un valor a l'é ver, antlora eseguì chèiche anstrussion.", - "CONTROLS_IF_TOOLTIP_2": "Si un valor a l'é ver, antlora eseguì ël prim blòch d'anstrussion. Dësnò, eseguì ël second blòch d'anstrussion.", - "CONTROLS_IF_TOOLTIP_3": "Si ël prim valor a l'é ver, antlora fé andé ël prim blòch d'anstrussion. Dësnò, si ël second valor a l'é ver, fé andé ël second blòch d'anstrussion.", - "CONTROLS_IF_TOOLTIP_4": "Si ël prim valor a l'é ver, antlora fé andé ël prim blòch d'anstrussion. Dësnò, si ël second valor a l'é ver, fé andé ël second blòcj d'anstrussion. Si gnun dij valor a l'é ver, fé andé l'ùltim blòch d'anstrussion.", - "CONTROLS_IF_MSG_IF": "si", - "CONTROLS_IF_MSG_ELSEIF": "dësnò si", - "CONTROLS_IF_MSG_ELSE": "dësnò", - "CONTROLS_IF_IF_TOOLTIP": "Gionté, gavé o riordiné le session për cinfiguré torna ës blòch si.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Gionté na condission al blòch si.", - "CONTROLS_IF_ELSE_TOOLTIP": "Gionté na condission final ch'a cheuj tut al blòch si.", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Rësponde ver si le doe imission a son uguaj.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Rësponde ver si le doe imission a son nen uguaj.", - "LOGIC_COMPARE_TOOLTIP_LT": "Rësponde ver si la prima imission a l'é pi cita dla sconda.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Rësponde ver si la prima imission a l'é pi cita o ugual a la sconda.", - "LOGIC_COMPARE_TOOLTIP_GT": "Rësponde ver si la prima imission a l'é pi granda che la sconda.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Rësponde ver si la prima imission a l'é pi granda o ugual a la sconda.", - "LOGIC_OPERATION_TOOLTIP_AND": "Rësponde ver se tute doe j'imission a son vere.", - "LOGIC_OPERATION_AND": "e", - "LOGIC_OPERATION_TOOLTIP_OR": "Rësponde ver se almanch un-a d'imission a l'é vera.", - "LOGIC_OPERATION_OR": "o", - "LOGIC_NEGATE_TITLE": "nen %1", - "LOGIC_NEGATE_TOOLTIP": "A rëspond ver se l'imission a l'é fàussa. A rëspond fàuss se l'imission a l'é vera.", - "LOGIC_BOOLEAN_TRUE": "ver", - "LOGIC_BOOLEAN_FALSE": "fàuss", - "LOGIC_BOOLEAN_TOOLTIP": "A rëspond ver o fàuss.", - "LOGIC_NULL": "gnente", - "LOGIC_NULL_TOOLTIP": "A rëspond gnente.", - "LOGIC_TERNARY_CONDITION": "preuva", - "LOGIC_TERNARY_IF_TRUE": "se ver", - "LOGIC_TERNARY_IF_FALSE": "se fàuss", - "LOGIC_TERNARY_TOOLTIP": "Controlé la condission an 'preuva'. Se la condission a l'é vera, a rëspond con ël valor 'se ver'; dësnò a rëspond con ël valor 'se fàuss'.", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "Un nùmer.", - "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/Arithmetic", - "MATH_ARITHMETIC_TOOLTIP_ADD": "A smon la soma ëd doi nùmer.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "A smon la diferensa dij doi nùmer.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "A smon ël prodot dij doi nùmer.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "A smon ël cossient dij doi nùmer.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "A smon ël prim nùmer alvà a la potensa dël second.", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "rèis quadra", - "MATH_SINGLE_TOOLTIP_ROOT": "A smon la rèis quadra d'un nùmer.", - "MATH_SINGLE_OP_ABSOLUTE": "assolù", - "MATH_SINGLE_TOOLTIP_ABS": "A smon ël valor assolù d'un nùmer.", - "MATH_SINGLE_TOOLTIP_NEG": "A smon l'opòst d'un nùmer.", - "MATH_SINGLE_TOOLTIP_LN": "A smon ël logaritm natural d'un nùmer.", - "MATH_SINGLE_TOOLTIP_LOG10": "A smon ël logaritm an base 10 d'un nùmer.", - "MATH_SINGLE_TOOLTIP_EXP": "A smon e a la potensa d'un nùmer.", - "MATH_SINGLE_TOOLTIP_POW10": "A smon 10 a la potensa d'un nùmer.", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "A smon ël sen ëd n'àngol an gré (pa an radiant).", - "MATH_TRIG_TOOLTIP_COS": "A smon ël cosen ëd n'àngol an gré (pa an radiant).", - "MATH_TRIG_TOOLTIP_TAN": "A smon la tangenta ëd n'àngol an gré (pa an radiant).", - "MATH_TRIG_TOOLTIP_ASIN": "A smon l'arch-sen d'un nùmer.", - "MATH_TRIG_TOOLTIP_ACOS": "A smon l'arch-cosen d'un nùmer.", - "MATH_TRIG_TOOLTIP_ATAN": "A smon l'arch-tangenta d'un nùmer.", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "A smon un-a dle costante comun-e π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…) o ∞ (infinì).", - "MATH_IS_EVEN": "a l'é cobi", - "MATH_IS_ODD": "a l'é dëscobi", - "MATH_IS_PRIME": "a l'é prim", - "MATH_IS_WHOLE": "a l'é antregh", - "MATH_IS_POSITIVE": "a l'é positiv", - "MATH_IS_NEGATIVE": "a l'é negativ", - "MATH_IS_DIVISIBLE_BY": "a l'é divisìbil për", - "MATH_IS_TOOLTIP": "A contròla si un nùmer a l'é cobi, dëscobi, prim, antreghm positiv, negativ, o s'a l'é divisìbil për un nùmer dàit. A rëspond ver o fàuss.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "ancrementé %1 për %2", - "MATH_CHANGE_TOOLTIP": "Gionté un nùmer a la variàbil '%1'.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "A arionda un nùmer për difet o ecess.", - "MATH_ROUND_OPERATOR_ROUND": "ariondé", - "MATH_ROUND_OPERATOR_ROUNDUP": "ariondé për ecess", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "ariondé për difet", - "MATH_ONLIST_OPERATOR_SUM": "soma dla lista", - "MATH_ONLIST_TOOLTIP_SUM": "A smon la soma ëd tuti ij nùmer ant la lista.", - "MATH_ONLIST_OPERATOR_MIN": "mìnim ëd la lista", - "MATH_ONLIST_TOOLTIP_MIN": "A smon ël pi cit nùmer ëd la lista.", - "MATH_ONLIST_OPERATOR_MAX": "màssim ëd la lista", - "MATH_ONLIST_TOOLTIP_MAX": "A smon ël pi gròss nùmer ëd la lista.", - "MATH_ONLIST_OPERATOR_AVERAGE": "media dla lista", - "MATH_ONLIST_TOOLTIP_AVERAGE": "A smon la media (aritmética) dij valor numérich ant la lista.", - "MATH_ONLIST_OPERATOR_MEDIAN": "mesan-a dla lista", - "MATH_ONLIST_TOOLTIP_MEDIAN": "A smon ël nùmer mesan ëd la lista.", - "MATH_ONLIST_OPERATOR_MODE": "mòde dla lista", - "MATH_ONLIST_TOOLTIP_MODE": "A smon na lista dj'element pi frequent ëd la lista.", - "MATH_ONLIST_OPERATOR_STD_DEV": "deviassion ëstàndard ëd la lista", - "MATH_ONLIST_TOOLTIP_STD_DEV": "A smon la deviassion ëstàndard ëd la lista.", - "MATH_ONLIST_OPERATOR_RANDOM": "element a l'ancàpit ëd la lista", - "MATH_ONLIST_TOOLTIP_RANDOM": "A smon n'element a l'ancàpit da la lista.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "resta ëd %1:%2", - "MATH_MODULO_TOOLTIP": "A smon la resta ëd la division dij doi nùmer.", - "MATH_CONSTRAIN_TITLE": "limité %1 antra %2 e %3", - "MATH_CONSTRAIN_TOOLTIP": "Limité un nùmer a esse antra le limitassion ëspessificà (comprèise).", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "antregh aleatòri antra %1 e %2", - "MATH_RANDOM_INT_TOOLTIP": "A smon n'antregh aleatòri antra ij doi lìmit ëspessificà, comprèis.", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "frassion aleatòria", - "MATH_RANDOM_FLOAT_TOOLTIP": "A smon na frassion aleatòria antra 0,0 (comprèis) e 1,0 (esclus).", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "Na litra, na paròla o na linia ëd test.", - "TEXT_JOIN_TITLE_CREATEWITH": "creé ël test con", - "TEXT_JOIN_TOOLTIP": "Creé un tòch ëd test an gionzend un nùmer qualsëssìa d'element.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "gionze", - "TEXT_CREATE_JOIN_TOOLTIP": "Gionté, gavé o riordiné le session për configuré torna ës blòch ëd test.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Gionté n'element al test.", - "TEXT_APPEND_TO": "a", - "TEXT_APPEND_APPENDTEXT": "taché ël test", - "TEXT_APPEND_TOOLTIP": "Taché dël test a la variàbil '%1'.", - "TEXT_LENGTH_TITLE": "longheur ëd %1", - "TEXT_LENGTH_TOOLTIP": "A smon ël nùmer ëd litre (spassi comprèis) ant ël test fornì.", - "TEXT_ISEMPTY_TITLE": "%1 a l'é veuid", - "TEXT_ISEMPTY_TOOLTIP": "A smon ver se ël test fornì a l'é veuid.", - "TEXT_INDEXOF_TOOLTIP": "A smon l'ìndes dla prima/ùltima ocorensa dël prim test ant ël second test. A smon %1 se ël test a l'é nen trovà.", - "TEXT_INDEXOF_INPUT_INTEXT": "ant ël test", - "TEXT_INDEXOF_OPERATOR_FIRST": "trové la prima ocorensa dël test", - "TEXT_INDEXOF_OPERATOR_LAST": "trové l'ùltima ocorensa dël test", - "TEXT_CHARAT_INPUT_INTEXT": "ant ël test", - "TEXT_CHARAT_FROM_START": "oten-e la litra #", - "TEXT_CHARAT_FROM_END": "oten-e la litra # da la fin", - "TEXT_CHARAT_FIRST": "oten-e la prima litra", - "TEXT_CHARAT_LAST": "oten-e l'ùltima litra", - "TEXT_CHARAT_RANDOM": "oten-e na litra a l'ancàpit", - "TEXT_CHARAT_TOOLTIP": "A smon la litra ant la posission ëspessificà.", - "TEXT_GET_SUBSTRING_TOOLTIP": "A smon un tòch ëspessificà dël test.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "ant ël test", - "TEXT_GET_SUBSTRING_START_FROM_START": "oten-e la sota-stringa da la litra #", - "TEXT_GET_SUBSTRING_START_FROM_END": "oten-e la sota-stringa da la litra # da la fin", - "TEXT_GET_SUBSTRING_START_FIRST": "oten-e la sota-stringa da la prima litra", - "TEXT_GET_SUBSTRING_END_FROM_START": "fin-a a la litra #", - "TEXT_GET_SUBSTRING_END_FROM_END": "fin-a a la litra # da la fin", - "TEXT_GET_SUBSTRING_END_LAST": "fin-a a l'ùltima litra", - "TEXT_CHANGECASE_TOOLTIP": "A smon na còpia dël test ant un caràter diferent.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "an MAJÙSCOL", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "an minùscul", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "an Majùscol A L'Ancamin Ëd Minca Paròla", - "TEXT_TRIM_TOOLTIP": "A smon na còpia dël test con jë spassi gavà da n'estremità o da tute doe.", - "TEXT_TRIM_OPERATOR_BOTH": "gavé jë spassi da le doe bande ëd", - "TEXT_TRIM_OPERATOR_LEFT": "gavé jë spassi da la banda snistra ëd", - "TEXT_TRIM_OPERATOR_RIGHT": "gavé jë spassi da la banda drita ëd", - "TEXT_PRINT_TITLE": "smon-e %1", - "TEXT_PRINT_TOOLTIP": "Smon-e ël test, ël nùmer o n'àutr valor ëspessificà.", - "TEXT_PROMPT_TYPE_TEXT": "anvit për un test con un mëssagi", - "TEXT_PROMPT_TYPE_NUMBER": "anvit për un nùmer con un mëssagi", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Ciamé un nùmer a l'utent.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Ciamé un test a l'utent.", - "LISTS_CREATE_EMPTY_TITLE": "creé na lista veuida", - "LISTS_CREATE_EMPTY_TOOLTIP": "Smon-e na lista, ëd longheur 0, ch'a conten gnun-a argistrassion", - "LISTS_CREATE_WITH_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_CREATE_WITH_TOOLTIP": "Creé na lista con un nùmer qualsëssìa d'element.", - "LISTS_CREATE_WITH_INPUT_WITH": "creé na lista con", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "lista", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Gionté, gavé o riordiné le session për configuré torna cost blòch ëd lista.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Gionté n'element a la lista.", - "LISTS_REPEAT_TOOLTIP": "A crea na lista ch'a consist dël valor dàit arpetù ël nùmer ëspessificà ëd vire.", - "LISTS_REPEAT_TITLE": "creé na lista con l'element %1 arpetù %2 vire", - "LISTS_LENGTH_TITLE": "longheur ëd %1", - "LISTS_LENGTH_TOOLTIP": "A smon la longheur ¨d na lista.", - "LISTS_ISEMPTY_TITLE": "%1 a l'é veuid", - "LISTS_ISEMPTY_TOOLTIP": "A smon ver se la lista a l'é veuida.", - "LISTS_INLIST": "ant la lista", - "LISTS_INDEX_OF_FIRST": "trové la prima ocorensa dl'element", - "LISTS_INDEX_OF_LAST": "trové l'ùltima ocorensa dl'element", - "LISTS_INDEX_OF_TOOLTIP": "A smon l'ìndes ëd la prima/ùltima ocorensa dl'element ant la lista. A smon %1 se l'element a l'é nen trovà.", - "LISTS_GET_INDEX_GET": "oten-e", - "LISTS_GET_INDEX_GET_REMOVE": "oten-e e eliminé", - "LISTS_GET_INDEX_REMOVE": "eliminé", - "LISTS_GET_INDEX_FROM_END": "# da la fin", - "LISTS_GET_INDEX_FIRST": "prim", - "LISTS_GET_INDEX_LAST": "ùltim", - "LISTS_GET_INDEX_RANDOM": "a l'ancàpit", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 a l'é ël prim element.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 a l'é l'ùltim element.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "A smon l'element a la posission ëspessificà an na lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "A smon ël prim element an na lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "A smon l'ùltim element an na lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "A smon n'element a l'ancàpit an na lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "A gava e a smon l'element a la posission ëspessificà an na lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "A gava e a smon ël prim element an na lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "A gava e a smon l'ùltim element an na lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "A gava e a smon n'element a l'ancàpit an na lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "A gava l'element a la posission ëspessificà an na lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "A gava ël prim element an na lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "A gava l'ùltim element an na lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "A gava n'element a l'ancàpit da na lista.", - "LISTS_SET_INDEX_SET": "buté", - "LISTS_SET_INDEX_INSERT": "anserì an", - "LISTS_SET_INDEX_INPUT_TO": "tanme", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "A fissa l'element a la posission ëspessificà an na lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "A fissa ël prim element an na lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "A fissa l'ùltim element an na lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "A fissa n'element a l'ancàpit an na lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "A anseriss l'element a la posission ëspessificà an na lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "A anseriss l'element al prinsipi ëd na lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Gionté l'element a la fin ëd na lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "A anseriss l'element a l'ancàpit an na lista.", - "LISTS_GET_SUBLIST_START_FROM_START": "oten-e la sot-lista da #", - "LISTS_GET_SUBLIST_START_FROM_END": "oten-e la sot-lista da # da la fin", - "LISTS_GET_SUBLIST_START_FIRST": "oten-e la sot-lista dal prim", - "LISTS_GET_SUBLIST_END_FROM_START": "fin-a a #", - "LISTS_GET_SUBLIST_END_FROM_END": "fin-a a # da la fin", - "LISTS_GET_SUBLIST_END_LAST": "fin-a a l'ùltim", - "LISTS_GET_SUBLIST_TOOLTIP": "A crea na còpia dël tòch ëspessificà ëd na lista.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "ordiné %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Ordiné na còpia ëd na lista.", - "LISTS_SORT_ORDER_ASCENDING": "chërsent", - "LISTS_SORT_ORDER_DESCENDING": "calant", - "LISTS_SORT_TYPE_NUMERIC": "numérich", - "LISTS_SORT_TYPE_TEXT": "alfabétich", - "LISTS_SORT_TYPE_IGNORECASE": "alfabétich, ignorand ël caràter minùscol o majùscol", - "LISTS_SPLIT_HELPURL": "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists", - "LISTS_SPLIT_LIST_FROM_TEXT": "fé na lista da 'n test", - "LISTS_SPLIT_TEXT_FROM_LIST": "fé 'n test da na lista", - "LISTS_SPLIT_WITH_DELIMITER": "con ël separator", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Divide un test an na lista ëd test, tajand a minca 'n separator.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Gionze na lista ëd test ant un test sol, separandje con un separator.", - "VARIABLES_GET_TOOLTIP": "A smon ël valor ëd sa variàbil.", - "VARIABLES_GET_CREATE_SET": "Creé 'fissé %1'", - "VARIABLES_SET": "fissé %1 a %2", - "VARIABLES_SET_TOOLTIP": "Fissé costa variàbil ugual al valor d'imission.", - "VARIABLES_SET_CREATE_GET": "Creé 'oten-e %1'", - "PROCEDURES_DEFNORETURN_TITLE": "a", - "PROCEDURES_DEFNORETURN_PROCEDURE": "fé cheicòs", - "PROCEDURES_BEFORE_PARAMS": "con:", - "PROCEDURES_CALL_BEFORE_PARAMS": "con:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "A crea na fonsion sensa surtìa.", - "PROCEDURES_DEFNORETURN_COMMENT": "Descrive sa fonsion...", - "PROCEDURES_DEFRETURN_RETURN": "artorn", - "PROCEDURES_DEFRETURN_TOOLTIP": "A crea na fonsion con na surtìa.", - "PROCEDURES_ALLOW_STATEMENTS": "përmëtte le diciairassion", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Atension: Costa fonsion a l'ha dij paràmeter duplicà.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Eseguì la fonsion '%1' definìa da l'utent.", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Eseguì la fonsion '%1' definìa da l'utent e dovré sò arzultà.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "imission", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Gionté, gavé o riordiné j'imission ëd sa fonsion.", - "PROCEDURES_MUTATORARG_TITLE": "nòm ëd l'imission:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Gionté n'imission a la fonsion.", - "PROCEDURES_HIGHLIGHT_DEF": "Sot-ligné la definission dla fonsion", - "PROCEDURES_CREATE_DO": "Creé '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Se un valor a l'é ver, antlora smon-e un second valor.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Atension: Ës blòch a podria esse dovrà mach an na definission ëd fonsion." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/pt-br.json b/backend/_pv_1_3_5/static/blockly/msg/json/pt-br.json deleted file mode 100755 index a871e431e..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/pt-br.json +++ /dev/null @@ -1,327 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Espertus", - "Prilopes", - "Mordecaista", - "Amgauna", - "TheGabrielZaum", - "Cainamarques", - "Tuliouel", - "Rodrigo codignoli", - "Webysther", - "Fasouzafreitas", - "Almondega", - "Rogerio Melfi", - "Caçador de Palavras", - "Luk3", - "Cristofer Alves" - ] - }, - "VARIABLES_DEFAULT_NAME": "item", - "TODAY": "Hoje", - "DUPLICATE_BLOCK": "Duplicar", - "ADD_COMMENT": "Adicionar comentário", - "REMOVE_COMMENT": "Remover comentário", - "EXTERNAL_INPUTS": "Entradas externas", - "INLINE_INPUTS": "Entradas incorporadas", - "DELETE_BLOCK": "Deletar bloco", - "DELETE_X_BLOCKS": "Deletar %1 blocos", - "DELETE_ALL_BLOCKS": "Deletar todos os blocos %1?", - "CLEAN_UP": "Limpar blocos", - "COLLAPSE_BLOCK": "Colapsar Bloco", - "COLLAPSE_ALL": "Colapsar Bloco", - "EXPAND_BLOCK": "Expandir bloco", - "EXPAND_ALL": "Expandir blocos", - "DISABLE_BLOCK": "Desabilitar bloco", - "ENABLE_BLOCK": "Habilitar bloco", - "HELP": "Ajuda", - "UNDO": "Desfazer", - "REDO": "Refazer", - "CHANGE_VALUE_TITLE": "Mudar valor:", - "RENAME_VARIABLE": "Renomear variável...", - "RENAME_VARIABLE_TITLE": "Renomear todas as variáveis '%1' para:", - "NEW_VARIABLE": "Criar variável...", - "NEW_VARIABLE_TITLE": "Nome da nova variável:", - "VARIABLE_ALREADY_EXISTS": "A variável chamada '%1' já existe.", - "DELETE_VARIABLE_CONFIRMATION": "Deletar %1 usos da variável '%2'?", - "DELETE_VARIABLE": "Deletar a variável '%1'", - "COLOUR_PICKER_HELPURL": "https://pt.wikipedia.org/wiki/Cor", - "COLOUR_PICKER_TOOLTIP": "Escolher uma cor da palheta de cores.", - "COLOUR_RANDOM_TITLE": "cor aleatória", - "COLOUR_RANDOM_TOOLTIP": "Escolher cor de forma aleatória.", - "COLOUR_RGB_TITLE": "colorir com", - "COLOUR_RGB_RED": "vermelho", - "COLOUR_RGB_GREEN": "verde", - "COLOUR_RGB_BLUE": "azul", - "COLOUR_RGB_TOOLTIP": "Criar uma cor com a quantidade especificada de vermelho, verde e azul. Todos os valores devem estar entre 0 e 100.", - "COLOUR_BLEND_TITLE": "misturar", - "COLOUR_BLEND_COLOUR1": "cor 1", - "COLOUR_BLEND_COLOUR2": "cor 2", - "COLOUR_BLEND_RATIO": "proporção", - "COLOUR_BLEND_TOOLTIP": "Mistura duas cores em uma dada proporção (0,0 - 1,0).", - "CONTROLS_REPEAT_HELPURL": "https://pt.wikipedia.org/wiki/Estrutura_de_repeti%C3%A7%C3%A3o#Repeti.C3.A7.C3.A3o_com_vari.C3.A1vel_de_controle", - "CONTROLS_REPEAT_TITLE": "repita %1 vezes", - "CONTROLS_REPEAT_INPUT_DO": "faça", - "CONTROLS_REPEAT_TOOLTIP": "Faça algumas instruções várias vezes.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "repita enquanto", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "repita até", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Enquanto um valor for verdadeiro, então faça algumas instruções.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Enquanto um valor for falso, então faça algumas instruções.", - "CONTROLS_FOR_TOOLTIP": "Faz com que a variável '%1' assuma os valores do número inicial ao número final, contando de acordo com o intervalo especificado e executa os blocos especificados.", - "CONTROLS_FOR_TITLE": "contar com %1 de %2 até %3 por %4", - "CONTROLS_FOREACH_TITLE": "para cada item %1 na lista %2", - "CONTROLS_FOREACH_TOOLTIP": "Para cada item em uma lista, atribuir o item à variável '%1' e então realiza algumas instruções.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "encerra o laço", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "continua com a próxima iteração do laço", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Encerra o laço.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Ignora o resto deste laço, e continua com a próxima iteração.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Atenção: Este bloco só pode ser usado dentro de um laço.", - "CONTROLS_IF_TOOLTIP_1": "Se um valor for verdadeiro, então realize algumas instruções.", - "CONTROLS_IF_TOOLTIP_2": "Se um valor for verdadeiro, então realize o primeiro bloco de instruções. Senão, realize o segundo bloco de instruções.", - "CONTROLS_IF_TOOLTIP_3": "Se o primeiro valor é verdadeiro, então realize o primeiro bloco de instruções. Senão, se o segundo valor é verdadeiro, realize o segundo bloco de instruções.", - "CONTROLS_IF_TOOLTIP_4": "Se o primeiro valor for verdadeiro, então realize o primeiro bloco de instruções. Senão, se o segundo valor é verdadeiro, realize o segundo bloco de instruções. Se nenhum dos blocos for verdadeiro, realize o último bloco de instruções.", - "CONTROLS_IF_MSG_IF": "se", - "CONTROLS_IF_MSG_ELSEIF": "senão se", - "CONTROLS_IF_MSG_ELSE": "senão", - "CONTROLS_IF_IF_TOOLTIP": "Acrescente, remova ou reordene seções para reconfigurar este bloco.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Acrescente uma condição para o bloco se.", - "CONTROLS_IF_ELSE_TOOLTIP": "Acrescente uma condição final para o bloco se.", - "LOGIC_COMPARE_HELPURL": "https://pt.wikipedia.org/wiki/Inequa%C3%A7%C3%A3o", - "LOGIC_COMPARE_TOOLTIP_EQ": "Retorna verdadeiro se ambas as entradas forem iguais.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Retorna verdadeiro se ambas as entradas forem diferentes.", - "LOGIC_COMPARE_TOOLTIP_LT": "Retorna verdadeiro se a primeira entrada for menor que a segunda entrada.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Retorna verdadeiro se a primeira entrada for menor ou igual à segunda entrada.", - "LOGIC_COMPARE_TOOLTIP_GT": "Retorna verdadeiro se a primeira entrada for maior que a segunda entrada.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Retorna verdadeiro se a primeira entrada for maior ou igual à segunda entrada.", - "LOGIC_OPERATION_TOOLTIP_AND": "Retorna verdadeiro se ambas as entradas forem verdadeiras.", - "LOGIC_OPERATION_AND": "e", - "LOGIC_OPERATION_TOOLTIP_OR": "Retorna verdadeiro se uma das estradas for verdadeira.", - "LOGIC_OPERATION_OR": "ou", - "LOGIC_NEGATE_TITLE": "não %1", - "LOGIC_NEGATE_TOOLTIP": "Retorna verdadeiro se a entrada for falsa. Retorna falsa se a entrada for verdadeira.", - "LOGIC_BOOLEAN_TRUE": "verdadeiro", - "LOGIC_BOOLEAN_FALSE": "falso", - "LOGIC_BOOLEAN_TOOLTIP": "Retorna verdadeiro ou falso.", - "LOGIC_NULL": "nulo", - "LOGIC_NULL_TOOLTIP": "Retorna nulo.", - "LOGIC_TERNARY_CONDITION": "teste", - "LOGIC_TERNARY_IF_TRUE": "se verdadeiro", - "LOGIC_TERNARY_IF_FALSE": "se falso", - "LOGIC_TERNARY_TOOLTIP": "Avalia a condição em \"teste\". Se a condição for verdadeira retorna o valor \"se verdadeiro\", senão retorna o valor \"se falso\".", - "MATH_NUMBER_HELPURL": "https://pt.wikipedia.org/wiki/N%C3%BAmero", - "MATH_NUMBER_TOOLTIP": "Um número.", - "MATH_ARITHMETIC_HELPURL": "https://pt.wikipedia.org/wiki/Aritm%C3%A9tica", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Retorna a soma dos dois números.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Retorna a diferença entre os dois números.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Retorna o produto dos dois números.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Retorna o quociente da divisão dos dois números.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Retorna o primeiro número elevado à potência do segundo número.", - "MATH_SINGLE_HELPURL": "https://pt.wikipedia.org/wiki/Raiz_quadrada", - "MATH_SINGLE_OP_ROOT": "raiz quadrada", - "MATH_SINGLE_TOOLTIP_ROOT": "Retorna a raiz quadrada de um número.", - "MATH_SINGLE_OP_ABSOLUTE": "absoluto", - "MATH_SINGLE_TOOLTIP_ABS": "Retorna o valor absoluto de um número.", - "MATH_SINGLE_TOOLTIP_NEG": "Retorna o oposto de um número.", - "MATH_SINGLE_TOOLTIP_LN": "Retorna o logaritmo natural de um número.", - "MATH_SINGLE_TOOLTIP_LOG10": "Retorna o logaritmo em base 10 de um número.", - "MATH_SINGLE_TOOLTIP_EXP": "Retorna o número e elevado à potência de um número.", - "MATH_SINGLE_TOOLTIP_POW10": "Retorna 10 elevado à potência de um número.", - "MATH_TRIG_HELPURL": "https://pt.wikipedia.org/wiki/Fun%C3%A7%C3%A3o_trigonom%C3%A9trica", - "MATH_TRIG_TOOLTIP_SIN": "Retorna o seno de um grau (não radiano).", - "MATH_TRIG_TOOLTIP_COS": "Retorna o cosseno de um grau (não radiano).", - "MATH_TRIG_TOOLTIP_TAN": "Retorna a tangente de um grau (não radiano).", - "MATH_TRIG_TOOLTIP_ASIN": "Retorna o arco seno de um número.", - "MATH_TRIG_TOOLTIP_ACOS": "Retorna o arco cosseno de um número.", - "MATH_TRIG_TOOLTIP_ATAN": "Retorna o arco tangente de um número.", - "MATH_CONSTANT_HELPURL": "https://pt.wikipedia.org/wiki/Anexo:Lista_de_constantes_matem%C3%A1ticas", - "MATH_CONSTANT_TOOLTIP": "Retorna uma das constantes comuns: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), ou ∞ (infinito).", - "MATH_IS_EVEN": "é par", - "MATH_IS_ODD": "é ímpar", - "MATH_IS_PRIME": "é primo", - "MATH_IS_WHOLE": "é inteiro", - "MATH_IS_POSITIVE": "é positivo", - "MATH_IS_NEGATIVE": "é negativo", - "MATH_IS_DIVISIBLE_BY": "é divisível por", - "MATH_IS_TOOLTIP": "Verifica se um número é par, ímpar, inteiro, positivo, negativo, ou se é divisível por outro número. Retorna verdadeiro ou falso.", - "MATH_CHANGE_HELPURL": "https://pt.wikipedia.org/wiki/Adi%C3%A7%C3%A3o", - "MATH_CHANGE_TITLE": "alterar %1 por %2", - "MATH_CHANGE_TOOLTIP": "Soma um número à variável \"%1\".", - "MATH_ROUND_HELPURL": "https://pt.wikipedia.org/wiki/Arredondamento", - "MATH_ROUND_TOOLTIP": "Arredonda um número para cima ou para baixo.", - "MATH_ROUND_OPERATOR_ROUND": "arredonda", - "MATH_ROUND_OPERATOR_ROUNDUP": "arredonda para cima", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "arredonda para baixo", - "MATH_ONLIST_OPERATOR_SUM": "soma de uma lista", - "MATH_ONLIST_TOOLTIP_SUM": "Retorna a soma de todos os números na lista.", - "MATH_ONLIST_OPERATOR_MIN": "menor da lista", - "MATH_ONLIST_TOOLTIP_MIN": "Retorna o menor número da lista.", - "MATH_ONLIST_OPERATOR_MAX": "maior da lista", - "MATH_ONLIST_TOOLTIP_MAX": "Retorna o maior número da lista.", - "MATH_ONLIST_OPERATOR_AVERAGE": "média da lista", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Retorna a média aritmética dos números da lista.", - "MATH_ONLIST_OPERATOR_MEDIAN": "mediana da lista", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Retorna a mediana dos números da lista.", - "MATH_ONLIST_OPERATOR_MODE": "moda da lista", - "MATH_ONLIST_TOOLTIP_MODE": "Retorna uma lista do(s) item(ns) mais comum(ns) da lista.", - "MATH_ONLIST_OPERATOR_STD_DEV": "desvio padrão da lista", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Retorna o desvio padrão dos números da lista.", - "MATH_ONLIST_OPERATOR_RANDOM": "item aleatório da lista", - "MATH_ONLIST_TOOLTIP_RANDOM": "Retorna um elemento aleatório da lista.", - "MATH_MODULO_HELPURL": "https://pt.wikipedia.org/wiki/Opera%C3%A7%C3%A3o_m%C3%B3dulo", - "MATH_MODULO_TITLE": "resto da divisão de %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Retorna o resto da divisão de dois números.", - "MATH_CONSTRAIN_TITLE": "restringe %1 inferior %2 superior %3", - "MATH_CONSTRAIN_TOOLTIP": "Restringe um número entre os limites especificados (inclusivo).", - "MATH_RANDOM_INT_HELPURL": "https://pt.wikipedia.org/wiki/Gerador_de_n%C3%BAmeros_pseudoaleat%C3%B3rios", - "MATH_RANDOM_INT_TITLE": "inteiro aleatório entre %1 e %2", - "MATH_RANDOM_INT_TOOLTIP": "Retorna um número inteiro entre os dois limites informados, inclusivo.", - "MATH_RANDOM_FLOAT_HELPURL": "https://pt.wikipedia.org/wiki/Gerador_de_n%C3%BAmeros_pseudoaleat%C3%B3rios", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "fração aleatória", - "MATH_RANDOM_FLOAT_TOOLTIP": "Retorna uma fração aleatória entre 0.0 (inclusivo) e 1.0 (exclusivo).", - "TEXT_TEXT_HELPURL": "https://pt.wikipedia.org/wiki/Cadeia_de_caracteres", - "TEXT_TEXT_TOOLTIP": "Uma letra, palavra ou linha de texto.", - "TEXT_JOIN_TITLE_CREATEWITH": "criar texto com", - "TEXT_JOIN_TOOLTIP": "Criar um pedaço de texto juntando qualquer número de itens.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "unir", - "TEXT_CREATE_JOIN_TOOLTIP": "Acrescenta, remove ou reordena seções para reconfigurar este bloco de texto.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Acrescentar um item ao texto.", - "TEXT_APPEND_TO": "para", - "TEXT_APPEND_APPENDTEXT": "acrescentar texto", - "TEXT_APPEND_TOOLTIP": "Acrescentar um pedaço de texto à variável \"%1\".", - "TEXT_LENGTH_TITLE": "tamanho de %1", - "TEXT_LENGTH_TOOLTIP": "Retorna o número de letras (incluindo espaços) no texto fornecido.", - "TEXT_ISEMPTY_TITLE": "%1 é vazio", - "TEXT_ISEMPTY_TOOLTIP": "Retorna verdadeiro se o texto fornecido for vazio.", - "TEXT_INDEXOF_TOOLTIP": "Retorna a posição da primeira/última ocorrência do primeiro texto no segundo texto. Retorna %1 se o texto não for encontrado.", - "TEXT_INDEXOF_INPUT_INTEXT": "no texto", - "TEXT_INDEXOF_OPERATOR_FIRST": "encontre a primeira ocorrência do item", - "TEXT_INDEXOF_OPERATOR_LAST": "encontre a última ocorrência do texto", - "TEXT_CHARAT_INPUT_INTEXT": "no texto", - "TEXT_CHARAT_FROM_START": "obter letra nº", - "TEXT_CHARAT_FROM_END": "obter letra # a partir do final", - "TEXT_CHARAT_FIRST": "obter primeira letra", - "TEXT_CHARAT_LAST": "obter última letra", - "TEXT_CHARAT_RANDOM": "obter letra aleatória", - "TEXT_CHARAT_TOOLTIP": "Retorna a letra na posição especificada.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Retorna o trecho de texto especificado.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "no texto", - "TEXT_GET_SUBSTRING_START_FROM_START": "obter trecho de letra nº", - "TEXT_GET_SUBSTRING_START_FROM_END": "obter trecho de letra nº a partir do final", - "TEXT_GET_SUBSTRING_START_FIRST": "obter trecho de primeira letra", - "TEXT_GET_SUBSTRING_END_FROM_START": "até letra nº", - "TEXT_GET_SUBSTRING_END_FROM_END": "até letra nº a partir do final", - "TEXT_GET_SUBSTRING_END_LAST": "até última letra", - "TEXT_CHANGECASE_TOOLTIP": "Retorna uma cópia do texto em um formato diferente.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "para MAIÚSCULAS", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "para minúsculas", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "para Nomes Próprios", - "TEXT_TRIM_TOOLTIP": "Retorna uma cópia do texto com os espaços removidos de uma ou ambas extremidades.", - "TEXT_TRIM_OPERATOR_BOTH": "remover espaços de ambos os lados de", - "TEXT_TRIM_OPERATOR_LEFT": "remover espaços à esquerda de", - "TEXT_TRIM_OPERATOR_RIGHT": "remover espaços à direita de", - "TEXT_PRINT_TITLE": "imprime %1", - "TEXT_PRINT_TOOLTIP": "Imprime o texto, número ou valor especificado.", - "TEXT_PROMPT_TYPE_TEXT": "Pede um texto com uma mensagem", - "TEXT_PROMPT_TYPE_NUMBER": "Pede um número com uma mensagem", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Pede ao usuário um número.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Pede ao usuário um texto.", - "LISTS_CREATE_EMPTY_TITLE": "criar lista vazia", - "LISTS_CREATE_EMPTY_TOOLTIP": "Retorna uma lista, de tamanho 0, contendo nenhum registro", - "LISTS_CREATE_WITH_TOOLTIP": "Cria uma lista com a quantidade de itens informada.", - "LISTS_CREATE_WITH_INPUT_WITH": "criar lista com", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "lista", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Acrescenta, remove ou reordena seções para reconfigurar este bloco de lista.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Acrescenta um item à lista.", - "LISTS_REPEAT_TOOLTIP": "Cria uma lista consistindo no valor informado repetido o número de vezes especificado.", - "LISTS_REPEAT_TITLE": "criar lista com item %1 repetido %2 vezes", - "LISTS_LENGTH_TITLE": "tamanho de %1", - "LISTS_LENGTH_TOOLTIP": "Retorna o tamanho de uma lista.", - "LISTS_ISEMPTY_TITLE": "%1 é vazia", - "LISTS_ISEMPTY_TOOLTIP": "Retorna ao verdadeiro se a lista estiver vazia.", - "LISTS_INLIST": "na lista", - "LISTS_INDEX_OF_FIRST": "encontre a primeira ocorrência do item", - "LISTS_INDEX_OF_LAST": "encontre a última ocorrência do item", - "LISTS_INDEX_OF_TOOLTIP": "Retorna o índice da primeira/última ocorrência do item na lista. Retorna %1 se o item não for encontrado.", - "LISTS_GET_INDEX_GET": "obter", - "LISTS_GET_INDEX_GET_REMOVE": "obter e remover", - "LISTS_GET_INDEX_REMOVE": "remover", - "LISTS_GET_INDEX_FROM_START": "nº", - "LISTS_GET_INDEX_FROM_END": "nº a partir do final", - "LISTS_GET_INDEX_FIRST": "primeiro", - "LISTS_GET_INDEX_LAST": "último", - "LISTS_GET_INDEX_RANDOM": "aleatório", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 é o primeiro item.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 é o último item.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Retorna o item da lista na posição especificada.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Retorna o primeiro item em uma lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Retorna o último item em uma lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Retorna um item aleatório de uma lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Remove e retorna o item na posição especificada em uma lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Remove e retorna o primeiro item de uma lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Remove e retorna o último item de uma lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Remove e retorna um item aleatório de uma lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Remove o item na posição especificada em uma lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Remove o primeiro item de uma lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Remove o último item de uma lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Remove um item aleatório de uma lista.", - "LISTS_SET_INDEX_SET": "definir", - "LISTS_SET_INDEX_INSERT": "inserir em", - "LISTS_SET_INDEX_INPUT_TO": "como", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Define o item da posição especificada de uma lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Define o primeiro item de uma lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Define o último item de uma lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Define um item aleatório de uma lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Insere o item na posição especificada em uma lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Insere o item no início de uma lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Insere o item no final de uma lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Insere o item em uma posição qualquer de uma lista.", - "LISTS_GET_SUBLIST_START_FROM_START": "obtém sublista de nº", - "LISTS_GET_SUBLIST_START_FROM_END": "obtém sublista de nº a partir do final", - "LISTS_GET_SUBLIST_START_FIRST": "obtém sublista a partir do primeiro", - "LISTS_GET_SUBLIST_END_FROM_START": "até nº", - "LISTS_GET_SUBLIST_END_FROM_END": "até nº a partir do final", - "LISTS_GET_SUBLIST_END_LAST": "até último", - "LISTS_GET_SUBLIST_TOOLTIP": "Cria uma cópia da porção especificada de uma lista.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "ordenar %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Ordenar uma cópia de uma lista.", - "LISTS_SORT_ORDER_ASCENDING": "ascendente", - "LISTS_SORT_ORDER_DESCENDING": "descendente", - "LISTS_SORT_TYPE_NUMERIC": "numérico", - "LISTS_SORT_TYPE_TEXT": "alfabético", - "LISTS_SORT_TYPE_IGNORECASE": "alfabético, ignorar maiúscula/minúscula", - "LISTS_SPLIT_LIST_FROM_TEXT": "Fazer uma lista a partir do texto", - "LISTS_SPLIT_TEXT_FROM_LIST": "fazer um texto a partir da lista", - "LISTS_SPLIT_WITH_DELIMITER": "com delimitador", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Dividir o texto em uma lista de textos, separando-o em cada delimitador.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Juntar uma lista de textos em um único texto, separado por um delimitador.", - "VARIABLES_GET_TOOLTIP": "Retorna o valor desta variável.", - "VARIABLES_GET_CREATE_SET": "Criar \"definir %1\"", - "VARIABLES_SET": "definir %1 para %2", - "VARIABLES_SET_TOOLTIP": "Define esta variável para o valor da entrada.", - "VARIABLES_SET_CREATE_GET": "Criar \"obter %1\"", - "PROCEDURES_DEFNORETURN_TITLE": "para", - "PROCEDURES_DEFNORETURN_PROCEDURE": "faça algo", - "PROCEDURES_BEFORE_PARAMS": "com:", - "PROCEDURES_CALL_BEFORE_PARAMS": "com:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Cria uma função que não tem retorno.", - "PROCEDURES_DEFNORETURN_COMMENT": "Descreva esta função...", - "PROCEDURES_DEFRETURN_RETURN": "retorna", - "PROCEDURES_DEFRETURN_TOOLTIP": "Cria uma função que possui um valor de retorno.", - "PROCEDURES_ALLOW_STATEMENTS": "permitir declarações", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Atenção: Esta função tem parâmetros duplicados.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://pt.wikipedia.org/wiki/Sub-rotina", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Executa a função definida pelo usuário \"%1\".", - "PROCEDURES_CALLRETURN_HELPURL": "https://pt.wikipedia.org/wiki/Sub-rotina", - "PROCEDURES_CALLRETURN_TOOLTIP": "Executa a função definida pelo usuário \"%1\" e usa seu retorno.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "entradas", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Adiciona, remove, ou reordena as entradas para esta função.", - "PROCEDURES_MUTATORARG_TITLE": "nome da entrada:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Adiciona uma entrada para esta função", - "PROCEDURES_HIGHLIGHT_DEF": "Destacar definição da função", - "PROCEDURES_CREATE_DO": "Criar \"%1\"", - "PROCEDURES_IFRETURN_TOOLTIP": "Se um valor é verdadeiro, então retorna um valor.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Atenção: Este bloco só pode ser utilizado dentro da definição de uma função." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/pt.json b/backend/_pv_1_3_5/static/blockly/msg/json/pt.json deleted file mode 100755 index fd402c49b..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/pt.json +++ /dev/null @@ -1,326 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Imperadeiro98", - "Waldir", - "Vitorvicentevalente", - "아라", - "Nicola Nascimento", - "Önni", - "Diniscoelho", - "Fúlvio" - ] - }, - "VARIABLES_DEFAULT_NAME": "item", - "TODAY": "Hoje", - "DUPLICATE_BLOCK": "Duplicar", - "ADD_COMMENT": "Adicionar Comentário", - "REMOVE_COMMENT": "Remover Comentário", - "EXTERNAL_INPUTS": "Entradas externas", - "INLINE_INPUTS": "Entradas Internas", - "DELETE_BLOCK": "Remover Bloco", - "DELETE_X_BLOCKS": "Remover %1 Blocos", - "DELETE_ALL_BLOCKS": "Apagar todos os %1 blocos?", - "CLEAN_UP": "Limpar os blocos", - "COLLAPSE_BLOCK": "Colapsar Bloco", - "COLLAPSE_ALL": "Recolher Blocos", - "EXPAND_BLOCK": "Expandir Bloco", - "EXPAND_ALL": "Expandir Blocos", - "DISABLE_BLOCK": "Desabilitar Bloco", - "ENABLE_BLOCK": "Habilitar Bloco", - "HELP": "Ajuda", - "UNDO": "Desfazer", - "REDO": "Refazer", - "CHANGE_VALUE_TITLE": "Alterar valor:", - "RENAME_VARIABLE": "Renomear variável...", - "RENAME_VARIABLE_TITLE": "Renomear todas as variáveis '%1' para:", - "NEW_VARIABLE": "Nova variável...", - "NEW_VARIABLE_TITLE": "Nome da nova variável:", - "COLOUR_PICKER_HELPURL": "http://pt.wikipedia.org/wiki/Cor", - "COLOUR_PICKER_TOOLTIP": "Escolhe uma cor da paleta de cores.", - "COLOUR_RANDOM_TITLE": "cor aleatória", - "COLOUR_RANDOM_TOOLTIP": "Escolher cor de forma aleatória.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "pinte com", - "COLOUR_RGB_RED": "vermelho", - "COLOUR_RGB_GREEN": "verde", - "COLOUR_RGB_BLUE": "azul", - "COLOUR_RGB_TOOLTIP": "Cria uma cor de acordo com a quantidade especificada de vermelho, verde e azul. Todos os valores devem estar entre 0 e 100.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "misturar", - "COLOUR_BLEND_COLOUR1": "cor 1", - "COLOUR_BLEND_COLOUR2": "cor 2", - "COLOUR_BLEND_RATIO": "proporção", - "COLOUR_BLEND_TOOLTIP": "Mistura duas cores dada uma proporção (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "http://pt.wikipedia.org/wiki/Estrutura_de_repeti%C3%A7%C3%A3o#Repeti.C3.A7.C3.A3o_com_vari.C3.A1vel_de_controle", - "CONTROLS_REPEAT_TITLE": "repita %1 vez", - "CONTROLS_REPEAT_INPUT_DO": "faça", - "CONTROLS_REPEAT_TOOLTIP": "Faça algumas instruções várias vezes.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "repita enquanto", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "repita até", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Enquanto um valor for verdadeiro, então faça algumas instruções.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Enquanto um valor for falso, então faça algumas instruções.", - "CONTROLS_FOR_TOOLTIP": "Faz com que a variável \"%1\" assuma os valores desde o número inicial até ao número final, contando de acordo com o intervalo especificado e executa os blocos especificados.", - "CONTROLS_FOR_TITLE": "contar com %1 de %2 até %3 de %3 em %4", - "CONTROLS_FOREACH_TITLE": "para cada item %1 na lista %2", - "CONTROLS_FOREACH_TOOLTIP": "Para cada item numa lista, define a variável \"%1\" para o item e então faz algumas instruções.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "sair do ciclo", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "continuar com a próxima iteração do ciclo", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Sair do ciclo que está contido.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Ignora o resto deste ciclo e continua na próxima iteração.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Atenção: Este bloco só pode ser usado dentro de um ciclo.", - "CONTROLS_IF_TOOLTIP_1": "Se um valor é verdadeiro, então realize alguns passos.", - "CONTROLS_IF_TOOLTIP_2": "Se um valor é verdadeiro, então realize o primeiro bloco de instruções. Senão, realize o segundo bloco de instruções", - "CONTROLS_IF_TOOLTIP_3": "Se o primeiro valor é verdadeiro, então realize o primeiro bloco de instruções. Senão, se o segundo valor é verdadeiro, realize o segundo bloco de instruções.", - "CONTROLS_IF_TOOLTIP_4": "Se o primeiro valor é verdadeiro, então realize o primeiro bloco de instruções. Senão, se o segundo valor é verdadeiro, realize o segundo bloco de instruções. Se nenhum dos blocos for verdadeiro, realize o último bloco de instruções.", - "CONTROLS_IF_MSG_IF": "se", - "CONTROLS_IF_MSG_ELSEIF": "senão se", - "CONTROLS_IF_MSG_ELSE": "senão", - "CONTROLS_IF_IF_TOOLTIP": "Acrescente, remova ou reordene secções para reconfigurar este bloco se.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Acrescente uma condição ao bloco se.", - "CONTROLS_IF_ELSE_TOOLTIP": "Acrescente uma condição de excepação final para o bloco se.", - "LOGIC_COMPARE_HELPURL": "http://pt.wikipedia.org/wiki/Inequa%C3%A7%C3%A3o", - "LOGIC_COMPARE_TOOLTIP_EQ": "Retorna verdadeiro se ambas as entradas forem iguais entre si.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Retorna verdadeiro se ambas as entradas forem diferentes entre si.", - "LOGIC_COMPARE_TOOLTIP_LT": "Retorna verdadeiro se a primeira entrada for menor que a segunda entrada.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Retorna verdadeiro se a primeira entrada for menor ou igual à segunda entrada.", - "LOGIC_COMPARE_TOOLTIP_GT": "Retorna verdadeiro se a primeira entrada for maior que a segunda entrada.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Retorna verdadeiro se a primeira entrada for maior ou igual à segunda entrada.", - "LOGIC_OPERATION_TOOLTIP_AND": "Retorna verdadeiro se ambas as entradas forem verdadeiras.", - "LOGIC_OPERATION_AND": "e", - "LOGIC_OPERATION_TOOLTIP_OR": "Retorna verdadeiro se pelo menos uma das estradas for verdadeira.", - "LOGIC_OPERATION_OR": "ou", - "LOGIC_NEGATE_TITLE": "não %1", - "LOGIC_NEGATE_TOOLTIP": "Retorna verdadeiro se a entrada for falsa. Retorna falso se a entrada for verdadeira.", - "LOGIC_BOOLEAN_TRUE": "verdadeiro", - "LOGIC_BOOLEAN_FALSE": "falso", - "LOGIC_BOOLEAN_TOOLTIP": "Retorna verdadeiro ou falso.", - "LOGIC_NULL_HELPURL": "http://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "nulo", - "LOGIC_NULL_TOOLTIP": "Retorna nulo.", - "LOGIC_TERNARY_HELPURL": "http://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "teste", - "LOGIC_TERNARY_IF_TRUE": "se verdadeiro", - "LOGIC_TERNARY_IF_FALSE": "se falso", - "LOGIC_TERNARY_TOOLTIP": "Avalia a condição em \"teste\". Se a condição for verdadeira retorna o valor \"se verdadeiro\", senão retorna o valor \"se falso\".", - "MATH_NUMBER_HELPURL": "http://pt.wikipedia.org/wiki/N%C3%BAmero", - "MATH_NUMBER_TOOLTIP": "Um número.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tan", - "MATH_TRIG_ASIN": "asin", - "MATH_TRIG_ACOS": "acos", - "MATH_TRIG_ATAN": "atan", - "MATH_ARITHMETIC_HELPURL": "http://pt.wikipedia.org/wiki/Aritm%C3%A9tica", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Retorna a soma de dois números.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Retorna a diferença de dois números.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Retorna o produto de dois números.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Retorna o quociente da divisão de dois números.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Retorna o primeiro número elevado à potência do segundo número.", - "MATH_SINGLE_HELPURL": "http://pt.wikipedia.org/wiki/Raiz_quadrada", - "MATH_SINGLE_OP_ROOT": "raíz quadrada", - "MATH_SINGLE_TOOLTIP_ROOT": "Retorna a raiz quadrada de um número.", - "MATH_SINGLE_OP_ABSOLUTE": "absoluto", - "MATH_SINGLE_TOOLTIP_ABS": "Retorna o valor absoluto de um número.", - "MATH_SINGLE_TOOLTIP_NEG": "Retorna o oposto de um número.", - "MATH_SINGLE_TOOLTIP_LN": "Retorna o logarítmo natural de um número.", - "MATH_SINGLE_TOOLTIP_LOG10": "Retorna o logarítmo em base 10 de um número.", - "MATH_SINGLE_TOOLTIP_EXP": "Retorna o número e elevado à potência de um número.", - "MATH_SINGLE_TOOLTIP_POW10": "Retorna 10 elevado à potência de um número.", - "MATH_TRIG_HELPURL": "http://pt.wikipedia.org/wiki/Fun%C3%A7%C3%A3o_trigonom%C3%A9trica", - "MATH_TRIG_TOOLTIP_SIN": "Retorna o seno de um grau (não radiano).", - "MATH_TRIG_TOOLTIP_COS": "Retorna o cosseno de um grau (não radiano).", - "MATH_TRIG_TOOLTIP_TAN": "Retorna a tangente de um grau (não radiano).", - "MATH_TRIG_TOOLTIP_ASIN": "Retorna o arco seno de um número.", - "MATH_TRIG_TOOLTIP_ACOS": "Retorna o arco cosseno de um número.", - "MATH_TRIG_TOOLTIP_ATAN": "Retorna o arco tangente de um número.", - "MATH_CONSTANT_HELPURL": "http://pt.wikipedia.org/wiki/Anexo:Lista_de_constantes_matem%C3%A1ticas", - "MATH_CONSTANT_TOOLTIP": "Retorna uma das constantes comuns: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), ou ∞ (infinito).", - "MATH_IS_EVEN": "é par", - "MATH_IS_ODD": "é impar", - "MATH_IS_PRIME": "é primo", - "MATH_IS_WHOLE": "é inteiro", - "MATH_IS_POSITIVE": "é positivo", - "MATH_IS_NEGATIVE": "é negativo", - "MATH_IS_DIVISIBLE_BY": "é divisível por", - "MATH_IS_TOOLTIP": "Verifica se um número é par, impar, primo, inteiro, positivo, negativo, ou se é divisível por outro número. Retorna verdadeiro ou falso.", - "MATH_CHANGE_HELPURL": "http://pt.wikipedia.org/wiki/Adi%C3%A7%C3%A3o", - "MATH_CHANGE_TITLE": "alterar %1 por %2", - "MATH_CHANGE_TOOLTIP": "Soma um número à variável \"%1\".", - "MATH_ROUND_HELPURL": "http://pt.wikipedia.org/wiki/Arredondamento", - "MATH_ROUND_TOOLTIP": "Arredonda um número para cima ou para baixo.", - "MATH_ROUND_OPERATOR_ROUND": "arredonda", - "MATH_ROUND_OPERATOR_ROUNDUP": "arredonda para cima", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "arredonda para baixo", - "MATH_ONLIST_OPERATOR_SUM": "soma da lista", - "MATH_ONLIST_TOOLTIP_SUM": "Retorna a soma de todos os números da lista.", - "MATH_ONLIST_OPERATOR_MIN": "menor de uma lista", - "MATH_ONLIST_TOOLTIP_MIN": "Retorna o menor número da lista.", - "MATH_ONLIST_OPERATOR_MAX": "maior de uma lista", - "MATH_ONLIST_TOOLTIP_MAX": "Retorna o maior número da lista.", - "MATH_ONLIST_OPERATOR_AVERAGE": "média de uma lista", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Retorna a média aritmética dos valores números da lista.", - "MATH_ONLIST_OPERATOR_MEDIAN": "mediana de uma lista", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Retorna a mediana da lista.", - "MATH_ONLIST_OPERATOR_MODE": "moda de uma lista", - "MATH_ONLIST_TOOLTIP_MODE": "Retorna a lista de item(ns) mais comum(ns) da lista.", - "MATH_ONLIST_OPERATOR_STD_DEV": "desvio padrão de uma lista", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Retorna o desvio padrão dos números da lista.", - "MATH_ONLIST_OPERATOR_RANDOM": "item aleatório de uma lista", - "MATH_ONLIST_TOOLTIP_RANDOM": "Retorna um elemento aleatório da lista.", - "MATH_MODULO_HELPURL": "http://pt.wikipedia.org/wiki/Opera%C3%A7%C3%A3o_m%C3%B3dulo", - "MATH_MODULO_TITLE": "resto da divisão de %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Retorna o resto da divisão de dois números.", - "MATH_CONSTRAIN_TITLE": "restringe %1 inferior %2 superior %3", - "MATH_CONSTRAIN_TOOLTIP": "Restringe um número entre os limites especificados (inclusive).", - "MATH_RANDOM_INT_HELPURL": "http://pt.wikipedia.org/wiki/N%C3%BAmero_aleat%C3%B3rio", - "MATH_RANDOM_INT_TITLE": "inteiro aleatório entre %1 e %2", - "MATH_RANDOM_INT_TOOLTIP": "Retorna um número inteiro entre os dois limites especificados, inclusive.", - "MATH_RANDOM_FLOAT_HELPURL": "http://pt.wikipedia.org/wiki/N%C3%BAmero_aleat%C3%B3rio", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "fração aleatória", - "MATH_RANDOM_FLOAT_TOOLTIP": "Insere uma fração aleatória entre 0.0 (inclusive) e 1.0 (exclusive).", - "TEXT_TEXT_HELPURL": "http://pt.wikipedia.org/wiki/Cadeia_de_caracteres", - "TEXT_TEXT_TOOLTIP": "Uma letra, palavra ou linha de texto.", - "TEXT_JOIN_TITLE_CREATEWITH": "criar texto com", - "TEXT_JOIN_TOOLTIP": "Criar um pedaço de texto juntando qualquer número de itens.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "unir", - "TEXT_CREATE_JOIN_TOOLTIP": "Acrescenta, remove ou reordena seções para reconfigurar este bloco de texto.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Acrescentar um item ao texto.", - "TEXT_APPEND_TO": "para", - "TEXT_APPEND_APPENDTEXT": "acrescentar texto", - "TEXT_APPEND_TOOLTIP": "Acrescentar um pedaço de texto à variável \"%1\".", - "TEXT_LENGTH_TITLE": "tamanho de %1", - "TEXT_LENGTH_TOOLTIP": "Devolve o número de letras (incluindo espaços) do texto fornecido.", - "TEXT_ISEMPTY_TITLE": "%1 está vazio", - "TEXT_ISEMPTY_TOOLTIP": "Retorna verdadeiro se o texto fornecido estiver vazio.", - "TEXT_INDEXOF_TOOLTIP": "Retorna a posição da primeira/última ocorrência do primeiro texto no segundo texto. Retorna %1 se o texto não for encontrado.", - "TEXT_INDEXOF_INPUT_INTEXT": "no texto", - "TEXT_INDEXOF_OPERATOR_FIRST": "primeira ocorrência do texto", - "TEXT_INDEXOF_OPERATOR_LAST": "última ocorrência do texto", - "TEXT_CHARAT_INPUT_INTEXT": "no texto", - "TEXT_CHARAT_FROM_START": "obter letra nº", - "TEXT_CHARAT_FROM_END": "obter letra nº a partir do final", - "TEXT_CHARAT_FIRST": "obter primeira letra", - "TEXT_CHARAT_LAST": "obter última letra", - "TEXT_CHARAT_RANDOM": "obter letra aleatória", - "TEXT_CHARAT_TOOLTIP": "Retorna a letra na posição especificada.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Retorna a parte especificada do texto.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "no texto", - "TEXT_GET_SUBSTRING_START_FROM_START": "obter subsequência de tamanho #", - "TEXT_GET_SUBSTRING_START_FROM_END": "obter subsequência de tamanho # a partir do final", - "TEXT_GET_SUBSTRING_START_FIRST": "obter subsequência a partir da primeira letra", - "TEXT_GET_SUBSTRING_END_FROM_START": "até letra nº", - "TEXT_GET_SUBSTRING_END_FROM_END": "até letra nº a partir do final", - "TEXT_GET_SUBSTRING_END_LAST": "até última letra", - "TEXT_CHANGECASE_TOOLTIP": "Retorna uma cópia do texto em formato diferente.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "para MAIÚSCULAS", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "para minúsculas", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "para Iniciais Maiúsculas", - "TEXT_TRIM_TOOLTIP": "Retorna uma cópia do texto com os espaços removidos de uma ou ambas as extremidades.", - "TEXT_TRIM_OPERATOR_BOTH": "remover espaços de ambos os lados", - "TEXT_TRIM_OPERATOR_LEFT": "remover espaços à esquerda de", - "TEXT_TRIM_OPERATOR_RIGHT": "remover espaços à direita", - "TEXT_PRINT_TITLE": "imprime %1", - "TEXT_PRINT_TOOLTIP": "Imprime o texto, número ou outro valor especificado.", - "TEXT_PROMPT_TYPE_TEXT": "Pede um texto com a mensagem", - "TEXT_PROMPT_TYPE_NUMBER": "pede um número com a mensagem", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Pede ao utilizador um número.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Pede ao utilizador um texto.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "criar lista vazia", - "LISTS_CREATE_EMPTY_TOOLTIP": "Retorna uma lista, de tamanho 0, contendo nenhum registo", - "LISTS_CREATE_WITH_TOOLTIP": "Cria uma lista com qualquer número de itens.", - "LISTS_CREATE_WITH_INPUT_WITH": "criar lista com", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "lista", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Acrescente, remova ou reordene as seções para reconfigurar este bloco lista.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Acrescenta um item à lista.", - "LISTS_REPEAT_TOOLTIP": "Cria uma lista constituída por um dado valor repetido o número de vezes especificado.", - "LISTS_REPEAT_TITLE": "criar lista com o item %1 repetido %2 vezes", - "LISTS_LENGTH_TITLE": "tamanho de %1", - "LISTS_LENGTH_TOOLTIP": "Retorna o tamanho de uma lista.", - "LISTS_ISEMPTY_TITLE": "%1 está vazia", - "LISTS_ISEMPTY_TOOLTIP": "Retona verdadeiro se a lista estiver vazia.", - "LISTS_INLIST": "na lista", - "LISTS_INDEX_OF_FIRST": "encontre a primeira ocorrência do item", - "LISTS_INDEX_OF_LAST": "encontre a última ocorrência do item", - "LISTS_INDEX_OF_TOOLTIP": "Retorna a posição da primeira/última ocorrência do item na lista. Retorna %1 se o item não for encontrado.", - "LISTS_GET_INDEX_GET": "obter", - "LISTS_GET_INDEX_GET_REMOVE": "obter e remover", - "LISTS_GET_INDEX_REMOVE": "remover", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# a partir do final", - "LISTS_GET_INDEX_FIRST": "primeiro", - "LISTS_GET_INDEX_LAST": "último", - "LISTS_GET_INDEX_RANDOM": "aleatório", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 é o primeiro item.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 é o último item.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Retorna o item na posição especificada da lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Retorna o primeiro item de uma lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Retorna o último item de uma lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Retorna um item aleatório de uma lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Remove e retorna o item na posição especificada de uma lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Remove e retorna o primeiro item de uma lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Remove e retorna o último item de uma lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Remove e retorna um item aleatório de uma lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Remove o item de uma posição especifica da lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Remove o primeiro item de uma lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Remove o último item de uma lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Remove um item aleatório de uma lista.", - "LISTS_SET_INDEX_SET": "definir", - "LISTS_SET_INDEX_INSERT": "inserir em", - "LISTS_SET_INDEX_INPUT_TO": "como", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Define o item na posição especificada de uma lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Define o primeiro item de uma lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Define o último item de uma lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Define um item aleatório de uma lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Insere o item numa posição especificada numa lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Insere o item no início da lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Insere o item no final da lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Insere o item numa posição aleatória de uma lista.", - "LISTS_GET_SUBLIST_START_FROM_START": "obtem sublista de #", - "LISTS_GET_SUBLIST_START_FROM_END": "obtem sublista de # a partir do final", - "LISTS_GET_SUBLIST_START_FIRST": "obtem sublista da primeira lista", - "LISTS_GET_SUBLIST_END_FROM_START": "até #", - "LISTS_GET_SUBLIST_END_FROM_END": "até #, a partir do final", - "LISTS_GET_SUBLIST_END_LAST": "para o último", - "LISTS_GET_SUBLIST_TOOLTIP": "Cria uma cópia da porção especificada de uma lista.", - "LISTS_SPLIT_LIST_FROM_TEXT": "fazer lista a partir de texto", - "LISTS_SPLIT_TEXT_FROM_LIST": "fazer texto a partir da lista", - "LISTS_SPLIT_WITH_DELIMITER": "com delimitador", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Dividir o texto numa lista de textos, separando-o em cada delimitador.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Juntar uma lista de textos num único texto, separado por um delimitador.", - "VARIABLES_GET_TOOLTIP": "Retorna o valor desta variável.", - "VARIABLES_GET_CREATE_SET": "Criar \"definir %1\"", - "VARIABLES_SET": "definir %1 para %2", - "VARIABLES_SET_TOOLTIP": "Define esta variável para o valor inserido.", - "VARIABLES_SET_CREATE_GET": "Criar \"obter %1\"", - "PROCEDURES_DEFNORETURN_HELPURL": "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFNORETURN_TITLE": "para", - "PROCEDURES_DEFNORETURN_PROCEDURE": "faz algo", - "PROCEDURES_BEFORE_PARAMS": "com:", - "PROCEDURES_CALL_BEFORE_PARAMS": "com:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Cria uma função que não tem retorno.", - "PROCEDURES_DEFNORETURN_COMMENT": "Descreva esta função...", - "PROCEDURES_DEFRETURN_HELPURL": "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFRETURN_RETURN": "retorna", - "PROCEDURES_DEFRETURN_TOOLTIP": "Cria uma função que possui um valor de retorno.", - "PROCEDURES_ALLOW_STATEMENTS": "permitir declarações", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Atenção: Esta função tem parâmetros duplicados.", - "PROCEDURES_CALLNORETURN_HELPURL": "http://pt.wikipedia.org/wiki/Sub-rotina", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Executa a função \"%1\".", - "PROCEDURES_CALLRETURN_HELPURL": "http://pt.wikipedia.org/wiki/Sub-rotina", - "PROCEDURES_CALLRETURN_TOOLTIP": "Executa a função \"%1\" e usa o seu retorno.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "entradas", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Adicionar, remover ou reordenar as entradas para esta função.", - "PROCEDURES_MUTATORARG_TITLE": "nome da entrada:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Adicionar uma entrada para a função.", - "PROCEDURES_HIGHLIGHT_DEF": "Destacar definição da função", - "PROCEDURES_CREATE_DO": "Criar \"%1\"", - "PROCEDURES_IFRETURN_TOOLTIP": "se o valor é verdadeiro, então retorna um segundo valor.", - "PROCEDURES_IFRETURN_WARNING": "Atenção: Este bloco só pode ser utilizado dentro da definição de uma função." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/qqq.json b/backend/_pv_1_3_5/static/blockly/msg/json/qqq.json deleted file mode 100755 index 43f34f64e..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/qqq.json +++ /dev/null @@ -1,372 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Espertus", - "Liuxinyu970226", - "Shirayuki" - ] - }, - "VARIABLES_DEFAULT_NAME": "default name - A simple, general default name for a variable, preferably short. For more context, see [[Translating:Blockly#infrequent_message_types]].\n{{Identical|Item}}", - "TODAY": "button text - Button that sets a calendar to today's date.\n{{Identical|Today}}", - "DUPLICATE_BLOCK": "context menu - Make a copy of the selected block (and any blocks it contains).\n{{Identical|Duplicate}}", - "ADD_COMMENT": "context menu - Add a descriptive comment to the selected block.", - "REMOVE_COMMENT": "context menu - Remove the descriptive comment from the selected block.", - "EXTERNAL_INPUTS": "context menu - Change from 'external' to 'inline' mode for displaying blocks used as inputs to the selected block. See [[Translating:Blockly#context_menus]].", - "INLINE_INPUTS": "context menu - Change from 'internal' to 'external' mode for displaying blocks used as inputs to the selected block. See [[Translating:Blockly#context_menus]].", - "DELETE_BLOCK": "context menu - Permanently delete the selected block.", - "DELETE_X_BLOCKS": "context menu - Permanently delete the %1 selected blocks.\n\nParameters:\n* %1 - an integer greater than 1.", - "DELETE_ALL_BLOCKS": "confirmation prompt - Question the user if they really wanted to permanently delete all %1 blocks.\n\nParameters:\n* %1 - an integer greater than 1.", - "CLEAN_UP": "context menu - Reposition all the blocks so that they form a neat line.", - "COLLAPSE_BLOCK": "context menu - Make the appearance of the selected block smaller by hiding some information about it.", - "COLLAPSE_ALL": "context menu - Make the appearance of all blocks smaller by hiding some information about it. Use the same terminology as in the previous message.", - "EXPAND_BLOCK": "context menu - Restore the appearance of the selected block by showing information about it that was hidden (collapsed) earlier.", - "EXPAND_ALL": "context menu - Restore the appearance of all blocks by showing information about it that was hidden (collapsed) earlier. Use the same terminology as in the previous message.", - "DISABLE_BLOCK": "context menu - Make the selected block have no effect (unless reenabled).", - "ENABLE_BLOCK": "context menu - Make the selected block have effect (after having been disabled earlier).", - "HELP": "context menu - Provide helpful information about the selected block.\n{{Identical|Help}}", - "UNDO": "context menu - Undo the previous action.\n{{Identical|Undo}}", - "REDO": "context menu - Undo the previous undo action.\n{{Identical|Redo}}", - "CHANGE_VALUE_TITLE": "prompt - This message is only seen in the Opera browser. With most browsers, users can edit numeric values in blocks by just clicking and typing. Opera does not allows this, so we have to open a new window and prompt users with this message to chanage a value.", - "RENAME_VARIABLE": "dropdown choice - When the user clicks on a variable block, this is one of the dropdown menu choices. It is used to rename the current variable. See [https://github.com/google/blockly/wiki/Variables#dropdown-menu https://github.com/google/blockly/wiki/Variables#dropdown-menu].", - "RENAME_VARIABLE_TITLE": "prompt - Prompts the user to enter the new name for the selected variable. See [https://github.com/google/blockly/wiki/Variables#dropdown-menu https://github.com/google/blockly/wiki/Variables#dropdown-menu].\n\nParameters:\n* %1 - the name of the variable to be renamed.", - "NEW_VARIABLE": "button text - Text on the button used to launch the variable creation dialogue.", - "NEW_VARIABLE_TITLE": "prompt - Prompts the user to enter the name for a new variable. See [https://github.com/google/blockly/wiki/Variables#dropdown-menu https://github.com/google/blockly/wiki/Variables#dropdown-menu].", - "VARIABLE_ALREADY_EXISTS": "alert - Tells the user that the name they entered is already in use.", - "DELETE_VARIABLE_CONFIRMATION": "confirm - Ask the user to confirm their deletion of multiple uses of a variable.", - "DELETE_VARIABLE": "alert - Tell the user that they can't delete a variable because it's part of the definition of a procedure. dropdown choice - Delete the currently selected variable.", - "COLOUR_PICKER_HELPURL": "url - Information about colour.", - "COLOUR_PICKER_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Colour#picking-a-colour-from-a-palette https://github.com/google/blockly/wiki/Colour#picking-a-colour-from-a-palette].", - "COLOUR_RANDOM_HELPURL": "url - A link that displays a random colour each time you visit it.", - "COLOUR_RANDOM_TITLE": "block text - Title of block that generates a colour at random.", - "COLOUR_RANDOM_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Colour#generating-a-random-colour https://github.com/google/blockly/wiki/Colour#generating-a-random-colour].", - "COLOUR_RGB_HELPURL": "url - A link for color codes with percentages (0-100%) for each component, instead of the more common 0-255, which may be more difficult for beginners.", - "COLOUR_RGB_TITLE": "block text - Title of block for [https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components].", - "COLOUR_RGB_RED": "block input text - The amount of red (from 0 to 100) to use when [https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components].\n{{Identical|Red}}", - "COLOUR_RGB_GREEN": "block input text - The amount of green (from 0 to 100) to use when [https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components].", - "COLOUR_RGB_BLUE": "block input text - The amount of blue (from 0 to 100) to use when [https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components].\n{{Identical|Blue}}", - "COLOUR_RGB_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components].", - "COLOUR_BLEND_HELPURL": "url - A useful link that displays blending of two colors.", - "COLOUR_BLEND_TITLE": "block text - A verb for blending two shades of paint.", - "COLOUR_BLEND_COLOUR1": "block input text - The first of two colours to [https://github.com/google/blockly/wiki/Colour#blending-colours blend].", - "COLOUR_BLEND_COLOUR2": "block input text - The second of two colours to [https://github.com/google/blockly/wiki/Colour#blending-colours blend].", - "COLOUR_BLEND_RATIO": "block input text - The proportion of the [https://github.com/google/blockly/wiki/Colour#blending-colours blend] containing the first color; the remaining proportion is of the second colour. For example, if the first colour is red and the second color blue, a ratio of 1 would yield pure red, a ratio of .5 would yield purple (equal amounts of red and blue), and a ratio of 0 would yield pure blue.\n{{Identical|Ratio}}", - "COLOUR_BLEND_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Colour#blending-colours https://github.com/google/blockly/wiki/Colour#blending-colours].", - "CONTROLS_REPEAT_HELPURL": "url - Describes 'repeat loops' in computer programs; consider using the translation of the page [https://en.wikipedia.org/wiki/Control_flow http://en.wikipedia.org/wiki/Control_flow].", - "CONTROLS_REPEAT_TITLE": "block input text - Title of [https://github.com/google/blockly/wiki/Loops#repeat repeat block].\n\nParameters:\n* %1 - the number of times the body of the loop should be repeated.", - "CONTROLS_REPEAT_INPUT_DO": "block text - Preceding the blocks in the body of the loop. See [https://github.com/google/blockly/wiki/Loops https://github.com/google/blockly/wiki/Loops].\n{{Identical|Do}}", - "CONTROLS_REPEAT_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Loops#repeat https://github.com/google/blockly/wiki/Loops#repeat].", - "CONTROLS_WHILEUNTIL_HELPURL": "url - Describes 'while loops' in computer programs; consider using the translation of [https://en.wikipedia.org/wiki/While_loop https://en.wikipedia.org/wiki/While_loop], if present, or [https://en.wikipedia.org/wiki/Control_flow https://en.wikipedia.org/wiki/Control_flow].", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "dropdown - Specifies that a loop should [https://github.com/google/blockly/wiki/Loops#repeat-while repeat while] the following condition is true.", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "dropdown - Specifies that a loop should [https://github.com/google/blockly/wiki/Loops#repeat-until repeat until] the following condition becomes true.", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "tooltip - See [https://github.com/google/blockly/wiki/Loops#repeat-while Loops#repeat-while https://github.com/google/blockly/wiki/Loops#repeat-while Loops#repeat-while].", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "tooltip - See [https://github.com/google/blockly/wiki/Loops#repeat-until https://github.com/google/blockly/wiki/Loops#repeat-until].", - "CONTROLS_FOR_HELPURL": "url - Describes 'for loops' in computer programs. Consider using your language's translation of [https://en.wikipedia.org/wiki/For_loop https://en.wikipedia.org/wiki/For_loop], if present.", - "CONTROLS_FOR_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Loops#count-with https://github.com/google/blockly/wiki/Loops#count-with].\n\nParameters:\n* %1 - the name of the loop variable.", - "CONTROLS_FOR_TITLE": "block text - Repeatedly counts a variable (%1) starting with a (usually lower) number in a range (%2), ending with a (usually higher) number in a range (%3), and counting the iterations by a number of steps (%4). As in [https://github.com/google/blockly/wiki/Loops#count-with https://github.com/google/blockly/wiki/Loops#count-with]. [[File:Blockly-count-with.png]]", - "CONTROLS_FOREACH_HELPURL": "url - Describes 'for-each loops' in computer programs. Consider using your language's translation of [https://en.wikipedia.org/wiki/Foreach https://en.wikipedia.org/wiki/Foreach] if present.", - "CONTROLS_FOREACH_TITLE": "block text - Title of [https://github.com/google/blockly/wiki/Loops#for-each for each block]. Sequentially assigns every item in array %2 to the valiable %1.", - "CONTROLS_FOREACH_TOOLTIP": "block text - Description of [https://github.com/google/blockly/wiki/Loops#for-each for each blocks].\n\nParameters:\n* %1 - the name of the loop variable.", - "CONTROLS_FLOW_STATEMENTS_HELPURL": "url - Describes control flow in computer programs. Consider using your language's translation of [https://en.wikipedia.org/wiki/Control_flow https://en.wikipedia.org/wiki/Control_flow], if it exists.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "dropdown - The current loop should be exited. See [https://github.com/google/blockly/wiki/Loops#break https://github.com/google/blockly/wiki/Loops#break].", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "dropdown - The current iteration of the loop should be ended and the next should begin. See [https://github.com/google/blockly/wiki/Loops#continue-with-next-iteration https://github.com/google/blockly/wiki/Loops#continue-with-next-iteration].", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "tooltip - See [https://github.com/google/blockly/wiki/Loops#break-out-of-loop https://github.com/google/blockly/wiki/Loops#break-out-of-loop].", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "tooltip - See [https://github.com/google/blockly/wiki/Loops#continue-with-next-iteration https://github.com/google/blockly/wiki/Loops#continue-with-next-iteration].", - "CONTROLS_FLOW_STATEMENTS_WARNING": "warning - The user has tried placing a block outside of a loop (for each, while, repeat, etc.), but this type of block may only be used within a loop. See [https://github.com/google/blockly/wiki/Loops#loop-termination-blocks https://github.com/google/blockly/wiki/Loops#loop-termination-blocks].", - "CONTROLS_IF_HELPURL": "url - Describes conditional statements (if-then-else) in computer programs. Consider using your language's translation of [https://en.wikipedia.org/wiki/If_else https://en.wikipedia.org/wiki/If_else], if present.", - "CONTROLS_IF_TOOLTIP_1": "tooltip - Describes [https://github.com/google/blockly/wiki/IfElse#if-blocks 'if' blocks]. Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present.", - "CONTROLS_IF_TOOLTIP_2": "tooltip - Describes [https://github.com/google/blockly/wiki/IfElse#if-else-blocks if-else blocks]. Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present.", - "CONTROLS_IF_TOOLTIP_3": "tooltip - Describes [https://github.com/google/blockly/wiki/IfElse#if-else-if-blocks if-else-if blocks]. Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present.", - "CONTROLS_IF_TOOLTIP_4": "tooltip - Describes [https://github.com/google/blockly/wiki/IfElse#if-else-if-else-blocks if-else-if-else blocks]. Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present.", - "CONTROLS_IF_MSG_IF": "block text - See [https://github.com/google/blockly/wiki/IfElse https://github.com/google/blockly/wiki/IfElse]. It is recommended, but not essential, that this have text in common with the translation of 'else if'", - "CONTROLS_IF_MSG_ELSEIF": "block text - See [https://github.com/google/blockly/wiki/IfElse https://github.com/google/blockly/wiki/IfElse]. The English words 'otherwise if' would probably be clearer than 'else if', but the latter is used because it is traditional and shorter.", - "CONTROLS_IF_MSG_ELSE": "block text - See [https://github.com/google/blockly/wiki/IfElse https://github.com/google/blockly/wiki/IfElse]. The English word 'otherwise' would probably be superior to 'else', but the latter is used because it is traditional and shorter.", - "CONTROLS_IF_IF_TOOLTIP": "tooltip - Describes [https://github.com/google/blockly/wiki/IfElse#block-modification if block modification].", - "CONTROLS_IF_ELSEIF_TOOLTIP": "tooltip - Describes the 'else if' subblock during [https://github.com/google/blockly/wiki/IfElse#block-modification if block modification].", - "CONTROLS_IF_ELSE_TOOLTIP": "tooltip - Describes the 'else' subblock during [https://github.com/google/blockly/wiki/IfElse#block-modification if block modification].", - "LOGIC_COMPARE_HELPURL": "url - Information about comparisons.", - "LOGIC_COMPARE_TOOLTIP_EQ": "tooltip - Describes the equals (=) block.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "tooltip - Describes the not equals (≠) block.", - "LOGIC_COMPARE_TOOLTIP_LT": "tooltip - Describes the less than (<) block.", - "LOGIC_COMPARE_TOOLTIP_LTE": "tooltip - Describes the less than or equals (≤) block.", - "LOGIC_COMPARE_TOOLTIP_GT": "tooltip - Describes the greater than (>) block.", - "LOGIC_COMPARE_TOOLTIP_GTE": "tooltip - Describes the greater than or equals (≥) block.", - "LOGIC_OPERATION_HELPURL": "url - Information about the Boolean conjunction ('and') and disjunction ('or') operators. Consider using the translation of [https://en.wikipedia.org/wiki/Boolean_logic https://en.wikipedia.org/wiki/Boolean_logic], if it exists in your language.", - "LOGIC_OPERATION_TOOLTIP_AND": "tooltip - See [https://en.wikipedia.org/wiki/Logical_conjunction https://en.wikipedia.org/wiki/Logical_conjunction].", - "LOGIC_OPERATION_AND": "block text - See [https://en.wikipedia.org/wiki/Logical_conjunction https://en.wikipedia.org/wiki/Logical_conjunction].\n{{Identical|And}}", - "LOGIC_OPERATION_TOOLTIP_OR": "block text - See [https://en.wikipedia.org/wiki/Disjunction https://en.wikipedia.org/wiki/Disjunction].", - "LOGIC_OPERATION_OR": "block text - See [https://en.wikipedia.org/wiki/Disjunction https://en.wikipedia.org/wiki/Disjunction].\n{{Identical|Or}}", - "LOGIC_NEGATE_HELPURL": "url - Information about logical negation. The translation of [https://en.wikipedia.org/wiki/Logical_negation https://en.wikipedia.org/wiki/Logical_negation] is recommended if it exists in the target language.", - "LOGIC_NEGATE_TITLE": "block text - This is a unary operator that returns ''false'' when the input is ''true'', and ''true'' when the input is ''false''. \n\nParameters:\n* %1 - the input (which should be either the value 'true' or 'false')", - "LOGIC_NEGATE_TOOLTIP": "tooltip - See [https://en.wikipedia.org/wiki/Logical_negation https://en.wikipedia.org/wiki/Logical_negation].", - "LOGIC_BOOLEAN_HELPURL": "url - Information about the logic values ''true'' and ''false''. Consider using the translation of [https://en.wikipedia.org/wiki/Truth_value https://en.wikipedia.org/wiki/Truth_value] if it exists in your language.", - "LOGIC_BOOLEAN_TRUE": "block text - The word for the [https://en.wikipedia.org/wiki/Truth_value logical value] ''true''.\n{{Identical|True}}", - "LOGIC_BOOLEAN_FALSE": "block text - The word for the [https://en.wikipedia.org/wiki/Truth_value logical value] ''false''.\n{{Identical|False}}", - "LOGIC_BOOLEAN_TOOLTIP": "tooltip - Indicates that the block returns either of the two possible [https://en.wikipedia.org/wiki/Truth_value logical values].", - "LOGIC_NULL_HELPURL": "url - Provide a link to the translation of [https://en.wikipedia.org/wiki/Nullable_type https://en.wikipedia.org/wiki/Nullable_type], if it exists in your language; otherwise, do not worry about translating this advanced concept.", - "LOGIC_NULL": "block text - In computer languages, ''null'' is a special value that indicates that no value has been set. You may use your language's word for 'nothing' or 'invalid'.\n{{Identical|Null}}", - "LOGIC_NULL_TOOLTIP": "tooltip - This should use the word from the previous message.", - "LOGIC_TERNARY_HELPURL": "url - Describes the programming language operator known as the ''ternary'' or ''conditional'' operator. It is recommended that you use the translation of [https://en.wikipedia.org/wiki/%3F: https://en.wikipedia.org/wiki/%3F:] if it exists.", - "LOGIC_TERNARY_CONDITION": "block input text - Label for the input whose value determines which of the other two inputs is returned. In some programming languages, this is called a ''''predicate''''.", - "LOGIC_TERNARY_IF_TRUE": "block input text - Indicates that the following input should be returned (used as output) if the test input is true. Remember to try to keep block text terse (short).", - "LOGIC_TERNARY_IF_FALSE": "block input text - Indicates that the following input should be returned (used as output) if the test input is false.", - "LOGIC_TERNARY_TOOLTIP": "tooltip - See [https://en.wikipedia.org/wiki/%3F: https://en.wikipedia.org/wiki/%3F:].", - "MATH_NUMBER_HELPURL": "url - Information about (real) numbers.", - "MATH_NUMBER_TOOLTIP": "tooltip - Any positive or negative number, not necessarily an integer.", - "MATH_ADDITION_SYMBOL": "{{optional}}\nmath - The symbol for the binary operation addition.", - "MATH_SUBTRACTION_SYMBOL": "{{optional}}\nmath - The symbol for the binary operation indicating that the right operand should be subtracted from the left operand.", - "MATH_DIVISION_SYMBOL": "{{optional}}\nmath - The binary operation indicating that the left operand should be divided by the right operand.", - "MATH_MULTIPLICATION_SYMBOL": "{{optional}}\nmath - The symbol for the binary operation multiplication.", - "MATH_POWER_SYMBOL": "{{optional}}\nmath - The symbol for the binary operation exponentiation. Specifically, if the value of the left operand is L and the value of the right operand (the exponent) is R, multiply L by itself R times. (Fractional and negative exponents are also legal.)", - "MATH_TRIG_SIN": "math - The short name of the trigonometric function [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine].", - "MATH_TRIG_COS": "math - The short name of the trigonometric function [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine].", - "MATH_TRIG_TAN": "math - The short name of the trigonometric function [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent].", - "MATH_TRIG_ASIN": "math - The short name of the ''inverse of'' the trigonometric function [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine].", - "MATH_TRIG_ACOS": "math - The short name of the ''inverse of'' the trigonometric function [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine].", - "MATH_TRIG_ATAN": "math - The short name of the ''inverse of'' the trigonometric function [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent].", - "MATH_ARITHMETIC_HELPURL": "url - Information about addition, subtraction, multiplication, division, and exponentiation.", - "MATH_ARITHMETIC_TOOLTIP_ADD": "tooltip - See [https://en.wikipedia.org/wiki/Addition https://en.wikipedia.org/wiki/Addition].", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "tooltip - See [https://en.wikipedia.org/wiki/Subtraction https://en.wikipedia.org/wiki/Subtraction].", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "tooltip - See [https://en.wikipedia.org/wiki/Multiplication https://en.wikipedia.org/wiki/Multiplication].", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "tooltip - See [https://en.wikipedia.org/wiki/Division_(mathematics) https://en.wikipedia.org/wiki/Division_(mathematics)].", - "MATH_ARITHMETIC_TOOLTIP_POWER": "tooltip - See [https://en.wikipedia.org/wiki/Exponentiation https://en.wikipedia.org/wiki/Exponentiation].", - "MATH_SINGLE_HELPURL": "url - Information about the square root operation.", - "MATH_SINGLE_OP_ROOT": "dropdown - This computes the positive [https://en.wikipedia.org/wiki/Square_root square root] of its input. For example, the square root of 16 is 4.", - "MATH_SINGLE_TOOLTIP_ROOT": "tooltip - Please use the same term as in the previous message.", - "MATH_SINGLE_OP_ABSOLUTE": "dropdown - This leaves positive numeric inputs changed and inverts negative inputs. For example, the absolute value of 5 is 5; the absolute value of -5 is also 5. For more information, see [https://en.wikipedia.org/wiki/Absolute_value https://en.wikipedia.org/wiki/Absolute_value].", - "MATH_SINGLE_TOOLTIP_ABS": "tooltip - Please use the same term as in the previous message.", - "MATH_SINGLE_TOOLTIP_NEG": "tooltip - Calculates '''0-n''', where '''n''' is the single numeric input.", - "MATH_SINGLE_TOOLTIP_LN": "tooltip - Calculates the [https://en.wikipedia.org/wiki/Natural_logarithm|natural logarithm] of its single numeric input.", - "MATH_SINGLE_TOOLTIP_LOG10": "tooltip - Calculates the [https://en.wikipedia.org/wiki/Common_logarithm common logarithm] of its single numeric input.", - "MATH_SINGLE_TOOLTIP_EXP": "tooltip - Multiplies [https://en.wikipedia.org/wiki/E_%28mathematical_constant%29 e] by itself n times, where n is the single numeric input.", - "MATH_SINGLE_TOOLTIP_POW10": "tooltip - Multiplies 10 by itself n times, where n is the single numeric input.", - "MATH_TRIG_HELPURL": "url - Information about the trigonometric functions sine, cosine, tangent, and their inverses (ideally using degrees, not radians).", - "MATH_TRIG_TOOLTIP_SIN": "tooltip - Return the [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine] of an [https://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians.", - "MATH_TRIG_TOOLTIP_COS": "tooltip - Return the [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine] of an [https://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians.", - "MATH_TRIG_TOOLTIP_TAN": "tooltip - Return the [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent] of an [https://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians.", - "MATH_TRIG_TOOLTIP_ASIN": "tooltip - The [https://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [https://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent sine function], using [https://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians.", - "MATH_TRIG_TOOLTIP_ACOS": "tooltip - The [https://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [https://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent cosine] function, using [https://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians.", - "MATH_TRIG_TOOLTIP_ATAN": "tooltip - The [https://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [https://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent tangent] function, using [https://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians.", - "MATH_CONSTANT_HELPURL": "url - Information about the mathematical constants Pi (π), e, the golden ratio (φ), √ 2, √ 1/2, and infinity (∞).", - "MATH_CONSTANT_TOOLTIP": "tooltip - Provides the specified [https://en.wikipedia.org/wiki/Mathematical_constant mathematical constant].", - "MATH_IS_EVEN": "dropdown - A number is '''even''' if it is a multiple of 2. For example, 4 is even (yielding true), but 3 is not (false).", - "MATH_IS_ODD": "dropdown - A number is '''odd''' if it is not a multiple of 2. For example, 3 is odd (yielding true), but 4 is not (false). The opposite of 'odd' is 'even'.", - "MATH_IS_PRIME": "dropdown - A number is [https://en.wikipedia.org/wiki/Prime prime] if it cannot be evenly divided by any positive integers except for 1 and itself. For example, 5 is prime, but 6 is not because 2 × 3 = 6.", - "MATH_IS_WHOLE": "dropdown - A number is '''whole''' if it is an [https://en.wikipedia.org/wiki/Integer integer]. For example, 5 is whole, but 5.1 is not.", - "MATH_IS_POSITIVE": "dropdown - A number is '''positive''' if it is greater than 0. (0 is neither negative nor positive.)", - "MATH_IS_NEGATIVE": "dropdown - A number is '''negative''' if it is less than 0. (0 is neither negative nor positive.)", - "MATH_IS_DIVISIBLE_BY": "dropdown - A number x is divisible by y if y goes into x evenly. For example, 10 is divisible by 5, but 10 is not divisible by 3.", - "MATH_IS_TOOLTIP": "tooltip - This block lets the user specify via a dropdown menu whether to check if the numeric input is even, odd, prime, whole, positive, negative, or divisible by a given value.", - "MATH_CHANGE_HELPURL": "url - Information about incrementing (increasing the value of) a variable. For other languages, just use the translation of the Wikipedia page about addition ([https://en.wikipedia.org/wiki/Addition https://en.wikipedia.org/wiki/Addition]).", - "MATH_CHANGE_TITLE": "- As in: ''change'' [the value of variable] ''item'' ''by'' 1 (e.g., if the variable named 'item' had the value 5, change it to 6). %1 is a variable name. %2 is the amount of change.", - "MATH_CHANGE_TOOLTIP": "tooltip - This updates the value of the variable by adding to it the following numeric input.\n\nParameters:\n* %1 - the name of the variable whose value should be increased.", - "MATH_ROUND_HELPURL": "url - Information about how numbers are rounded to the nearest integer", - "MATH_ROUND_TOOLTIP": "tooltip - See [https://en.wikipedia.org/wiki/Rounding https://en.wikipedia.org/wiki/Rounding].", - "MATH_ROUND_OPERATOR_ROUND": "dropdown - This rounds its input to the nearest whole number. For example, 3.4 is rounded to 3.", - "MATH_ROUND_OPERATOR_ROUNDUP": "dropdown - This rounds its input up to the nearest whole number. For example, if the input was 2.2, the result would be 3.", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "dropdown - This rounds its input down to the nearest whole number. For example, if the input was 3.8, the result would be 3.", - "MATH_ONLIST_HELPURL": "url - Information about applying a function to a list of numbers. (We were unable to find such information in English. Feel free to skip this and any other URLs that are difficult.)", - "MATH_ONLIST_OPERATOR_SUM": "dropdown - This computes the sum of the numeric elements in the list. For example, the sum of the list {1, 4} is 5.", - "MATH_ONLIST_TOOLTIP_SUM": "tooltip - Please use the same term for 'sum' as in the previous message.", - "MATH_ONLIST_OPERATOR_MIN": "dropdown - This finds the smallest (minimum) number in a list. For example, the smallest number in the list [-5, 0, 3] is -5.", - "MATH_ONLIST_TOOLTIP_MIN": "tooltip - Please use the same term for 'min' or 'minimum' as in the previous message.", - "MATH_ONLIST_OPERATOR_MAX": "dropdown - This finds the largest (maximum) number in a list. For example, the largest number in the list [-5, 0, 3] is 3.", - "MATH_ONLIST_TOOLTIP_MAX": "tooltip", - "MATH_ONLIST_OPERATOR_AVERAGE": "dropdown - This adds up all of the numbers in a list and divides the sum by the number of elements in the list. For example, the [https://en.wikipedia.org/wiki/Arithmetic_mean average] of the list [1, 2, 3, 4] is 2.5 (10/4).", - "MATH_ONLIST_TOOLTIP_AVERAGE": "tooltip - See [https://en.wikipedia.org/wiki/Arithmetic_mean https://en.wikipedia.org/wiki/Arithmetic_mean] for more informatin.", - "MATH_ONLIST_OPERATOR_MEDIAN": "dropdown - This finds the [https://en.wikipedia.org/wiki/Median median] of the numeric values in a list. For example, the median of the list {1, 2, 7, 12, 13} is 7.", - "MATH_ONLIST_TOOLTIP_MEDIAN": "tooltip - See [https://en.wikipedia.org/wiki/Median median https://en.wikipedia.org/wiki/Median median] for more information.", - "MATH_ONLIST_OPERATOR_MODE": "dropdown - This finds the most common numbers ([https://en.wikipedia.org/wiki/Mode_(statistics) modes]) in a list. For example, the modes of the list {1, 3, 9, 3, 9} are {3, 9}.", - "MATH_ONLIST_TOOLTIP_MODE": "tooltip - See [https://en.wikipedia.org/wiki/Mode_(statistics) https://en.wikipedia.org/wiki/Mode_(statistics)] for more information.", - "MATH_ONLIST_OPERATOR_STD_DEV": "dropdown - This finds the [https://en.wikipedia.org/wiki/Standard_deviation standard deviation] of the numeric values in a list.", - "MATH_ONLIST_TOOLTIP_STD_DEV": "tooltip - See [https://en.wikipedia.org/wiki/Standard_deviation https://en.wikipedia.org/wiki/Standard_deviation] for more information.", - "MATH_ONLIST_OPERATOR_RANDOM": "dropdown - This choose an element at random from a list. Each element is chosen with equal probability.", - "MATH_ONLIST_TOOLTIP_RANDOM": "tooltip - Please use same term for 'random' as in previous entry.", - "MATH_MODULO_HELPURL": "url - information about the modulo (remainder) operation.", - "MATH_MODULO_TITLE": "block text - Title of block providing the remainder when dividing the first numerical input by the second. For example, the remainder of 10 divided by 3 is 1.\n\nParameters:\n* %1 - the dividend (10, in our example)\n* %2 - the divisor (3 in our example).", - "MATH_MODULO_TOOLTIP": "tooltip - For example, the remainder of 10 divided by 3 is 1.", - "MATH_CONSTRAIN_HELPURL": "url - Information about constraining a numeric value to be in a specific range. (The English URL is not ideal. Recall that translating URLs is the lowest priority.)", - "MATH_CONSTRAIN_TITLE": "block text - The title of the block that '''constrain'''s (forces) a number to be in a given range. For example, if the number 150 is constrained to be between 5 and 100, the result will be 100. \n\nParameters:\n* %1 - the value to constrain (e.g., 150)\n* %2 - the minimum value (e.g., 5)\n* %3 - the maximum value (e.g., 100).", - "MATH_CONSTRAIN_TOOLTIP": "tooltip - This compares a number ''x'' to a low value ''L'' and a high value ''H''. If ''x'' is less then ''L'', the result is ''L''. If ''x'' is greater than ''H'', the result is ''H''. Otherwise, the result is ''x''.", - "MATH_RANDOM_INT_HELPURL": "url - Information about how computers generate random numbers.", - "MATH_RANDOM_INT_TITLE": "block text - The title of the block that generates a random integer (whole number) in the specified range. For example, if the range is from 5 to 7, this returns 5, 6, or 7 with equal likelihood. %1 is a placeholder for the lower number, %2 is the placeholder for the larger number.", - "MATH_RANDOM_INT_TOOLTIP": "tooltip - Return a random integer between two values specified as inputs. For example, if one input was 7 and another 9, any of the numbers 7, 8, or 9 could be produced.", - "MATH_RANDOM_FLOAT_HELPURL": "url - Information about how computers generate random numbers (specifically, numbers in the range from 0 to just below 1).", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "block text - The title of the block that generates a random number greater than or equal to 0 and less than 1.", - "MATH_RANDOM_FLOAT_TOOLTIP": "tooltip - Return a random fraction between 0 and 1. The value may be equal to 0 but must be less than 1.", - "TEXT_TEXT_HELPURL": "url - Information about how computers represent text (sometimes referred to as ''string''s).", - "TEXT_TEXT_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Text https://github.com/google/blockly/wiki/Text].", - "TEXT_JOIN_HELPURL": "url - Information on concatenating/appending pieces of text.", - "TEXT_JOIN_TITLE_CREATEWITH": "block text - See [https://github.com/google/blockly/wiki/Text#text-creation https://github.com/google/blockly/wiki/Text#text-creation].", - "TEXT_JOIN_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Text#text-creation create text with] for more information.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "block text - This is shown when the programmer wants to change the number of pieces of text being joined together. See [https://github.com/google/blockly/wiki/Text#text-creation https://github.com/google/blockly/wiki/Text#text-creation], specifically the last picture in the 'Text creation' section.\n{{Identical|Join}}", - "TEXT_CREATE_JOIN_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Text#text-creation https://github.com/google/blockly/wiki/Text#text-creation], specifically the last picture in the 'Text creation' section.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "block text - See [https://github.com/google/blockly/wiki/Text#text-creation https://github.com/google/blockly/wiki/Text#text-creation], specifically the last picture in the 'Text creation' section.", - "TEXT_APPEND_HELPURL": "url - This and the other text-related URLs are going to be hard to translate. As always, it is okay to leave untranslated or paste in the English-language URL. For these URLs, you might also consider a general URL about how computers represent text (such as the translation of [https://en.wikipedia.org/wiki/String_(computer_science) this Wikipedia page]).", - "TEXT_APPEND_TO": "block input text - Message preceding the name of a variable to which text should be appended. [[File:blockly-append-text.png]]", - "TEXT_APPEND_APPENDTEXT": "block input text - Message following the variable and preceding the piece of text that should be appended, as shown below. [[File:blockly-append-text.png]]", - "TEXT_APPEND_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Text#text-modification https://github.com/google/blockly/wiki/Text#text-modification] for more information.\n\nParameters:\n* %1 - the name of the variable to which text should be appended", - "TEXT_LENGTH_HELPURL": "url - Information about text on computers (usually referred to as 'strings').", - "TEXT_LENGTH_TITLE": "block text - See [https://github.com/google/blockly/wiki/Text#text-length https://github.com/google/blockly/wiki/Text#text-length]. \n\nParameters:\n* %1 - the piece of text to take the length of", - "TEXT_LENGTH_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Text#text-length https://github.com/google/blockly/wiki/Text#text-length].", - "TEXT_ISEMPTY_HELPURL": "url - Information about empty pieces of text on computers (usually referred to as 'empty strings').", - "TEXT_ISEMPTY_TITLE": "block text - See [https://github.com/google/blockly/wiki/Text#checking-for-empty-text https://github.com/google/blockly/wiki/Text#checking-for-empty-text]. \n\nParameters:\n* %1 - the piece of text to test for emptiness", - "TEXT_ISEMPTY_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Text#checking-for-empty-text https://github.com/google/blockly/wiki/Text#checking-for-empty-text].", - "TEXT_INDEXOF_HELPURL": "url - Information about finding a character in a piece of text.", - "TEXT_INDEXOF_TOOLTIP": "tooltip - %1 will be replaced by either the number 0 or -1 depending on the indexing mode. See [https://github.com/google/blockly/wiki/Text#finding-text https://github.com/google/blockly/wiki/Text#finding-text].", - "TEXT_INDEXOF_INPUT_INTEXT": "block text - Title of blocks allowing users to find text. See [https://github.com/google/blockly/wiki/Text#finding-text https://github.com/google/blockly/wiki/Text#finding-text]. [[File:Blockly-find-text.png]].", - "TEXT_INDEXOF_OPERATOR_FIRST": "dropdown - See [https://github.com/google/blockly/wiki/Text#finding-text https://github.com/google/blockly/wiki/Text#finding-text]. [[File:Blockly-find-text.png]].", - "TEXT_INDEXOF_OPERATOR_LAST": "dropdown - See [https://github.com/google/blockly/wiki/Text#finding-text https://github.com/google/blockly/wiki/Text#finding-text]. This would replace 'find first occurrence of text' below. (For more information on how common text is factored out of dropdown menus, see [https://translatewiki.net/wiki/Translating:Blockly#Drop-Down_Menus https://translatewiki.net/wiki/Translating:Blockly#Drop-Down_Menus)].) [[File:Blockly-find-text.png]].", - "TEXT_INDEXOF_TAIL": "block text - Optional text to follow the rightmost block in a [https://github.com/google/blockly/wiki/Text#finding-text https://github.com/google/blockly/wiki/Text#finding-text in text ... find block] (after the 'a' in the below picture). This will be the empty string in most languages. [[File:Blockly-find-text.png]].", - "TEXT_CHARAT_HELPURL": "url - Information about extracting characters (letters, number, symbols, etc.) from text.", - "TEXT_CHARAT_INPUT_INTEXT": "block text - Appears before the piece of text from which a letter (or number, punctuation character, etc.) should be extracted, as shown below. See [https://github.com/google/blockly/wiki/Text#extracting-a-single-character https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. [[File:Blockly-text-get.png]]", - "TEXT_CHARAT_FROM_START": "dropdown - Indicates that the letter (or number, punctuation character, etc.) with the specified index should be obtained from the preceding piece of text. See [https://github.com/google/blockly/wiki/Text#extracting-a-single-character https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. [[File:Blockly-text-get.png]]", - "TEXT_CHARAT_FROM_END": "block text - Indicates that the letter (or number, punctuation character, etc.) with the specified index from the end of a given piece of text should be obtained. See [https://github.com/google/blockly/wiki/Text#extracting-a-single-character https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. [[File:Blockly-text-get.png]]", - "TEXT_CHARAT_FIRST": "block text - Indicates that the first letter of the following piece of text should be retrieved. See [https://github.com/google/blockly/wiki/Text#extracting-a-single-character https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. [[File:Blockly-text-get.png]]", - "TEXT_CHARAT_LAST": "block text - Indicates that the last letter (or number, punctuation mark, etc.) of the following piece of text should be retrieved. See [https://github.com/google/blockly/wiki/Text#extracting-a-single-character https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. [[File:Blockly-text-get.png]]", - "TEXT_CHARAT_RANDOM": "block text - Indicates that any letter (or number, punctuation mark, etc.) in the following piece of text should be randomly selected. See [https://github.com/google/blockly/wiki/Text#extracting-a-single-character https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. [[File:Blockly-text-get.png]]", - "TEXT_CHARAT_TAIL": "block text - Text that goes after the rightmost block/dropdown when getting a single letter from a piece of text, as in [https://blockly-demo.appspot.com/static/apps/code/index.html#3m23km these blocks] or shown below. For most languages, this will be blank. [[File:Blockly-text-get.png]]", - "TEXT_CHARAT_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Text#extracting-a-single-character https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. [[File:Blockly-text-get.png]]", - "TEXT_GET_SUBSTRING_TOOLTIP": "See [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text].", - "TEXT_GET_SUBSTRING_HELPURL": "url - Information about extracting characters from text. Reminder: urls are the lowest priority translations. Feel free to skip.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "block text - Precedes a piece of text from which a portion should be extracted. [[File:Blockly-get-substring.png]]", - "TEXT_GET_SUBSTRING_START_FROM_START": "dropdown - Indicates that the following number specifies the position (relative to the start position) of the beginning of the region of text that should be obtained from the preceding piece of text. See [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. [[File:Blockly-get-substring.png]]", - "TEXT_GET_SUBSTRING_START_FROM_END": "dropdown - Indicates that the following number specifies the position (relative to the end position) of the beginning of the region of text that should be obtained from the preceding piece of text. See [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. Note: If {{msg-Blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will automatically appear ''after'' this and any other [https://translatewiki.net/wiki/Translating:Blockly#Ordinal_numbers ordinal numbers] on this block. [[File:Blockly-get-substring.png]]", - "TEXT_GET_SUBSTRING_START_FIRST": "block text - Indicates that a region starting with the first letter of the preceding piece of text should be extracted. See [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. [[File:Blockly-get-substring.png]]", - "TEXT_GET_SUBSTRING_END_FROM_START": "dropdown - Indicates that the following number specifies the position (relative to the start position) of the end of the region of text that should be obtained from the preceding piece of text. See [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. [[File:Blockly-get-substring.png]]", - "TEXT_GET_SUBSTRING_END_FROM_END": "dropdown - Indicates that the following number specifies the position (relative to the end position) of the end of the region of text that should be obtained from the preceding piece of text. See [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. [[File:Blockly-get-substring.png]]", - "TEXT_GET_SUBSTRING_END_LAST": "block text - Indicates that a region ending with the last letter of the preceding piece of text should be extracted. See [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. [[File:Blockly-get-substring.png]]", - "TEXT_GET_SUBSTRING_TAIL": "block text - Text that should go after the rightmost block/dropdown when [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text extracting a region of text]. In most languages, this will be the empty string. [[File:Blockly-get-substring.png]]", - "TEXT_CHANGECASE_HELPURL": "url - Information about the case of letters (upper-case and lower-case).", - "TEXT_CHANGECASE_TOOLTIP": "tooltip - Describes a block to adjust the case of letters. For more information on this block, see [https://github.com/google/blockly/wiki/Text#adjusting-text-case https://github.com/google/blockly/wiki/Text#adjusting-text-case].", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "block text - Indicates that all of the letters in the following piece of text should be capitalized. If your language does not use case, you may indicate that this is not applicable to your language. For more information on this block, see [https://github.com/google/blockly/wiki/Text#adjusting-text-case https://github.com/google/blockly/wiki/Text#adjusting-text-case].", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "block text - Indicates that all of the letters in the following piece of text should be converted to lower-case. If your language does not use case, you may indicate that this is not applicable to your language. For more information on this block, see [https://github.com/google/blockly/wiki/Text#adjusting-text-case https://github.com/google/blockly/wiki/Text#adjusting-text-case].", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "block text - Indicates that the first letter of each of the following words should be capitalized and the rest converted to lower-case. If your language does not use case, you may indicate that this is not applicable to your language. For more information on this block, see [https://github.com/google/blockly/wiki/Text#adjusting-text-case https://github.com/google/blockly/wiki/Text#adjusting-text-case].", - "TEXT_TRIM_HELPURL": "url - Information about trimming (removing) text off the beginning and ends of pieces of text.", - "TEXT_TRIM_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Text#trimming-removing-spaces https://github.com/google/blockly/wiki/Text#trimming-removing-spaces].", - "TEXT_TRIM_OPERATOR_BOTH": "dropdown - Removes spaces from the beginning and end of a piece of text. See [https://github.com/google/blockly/wiki/Text#trimming-removing-spaces https://github.com/google/blockly/wiki/Text#trimming-removing-spaces]. Note that neither this nor the other options modify the original piece of text (that follows); the block just returns a version of the text without the specified spaces.", - "TEXT_TRIM_OPERATOR_LEFT": "dropdown - Removes spaces from the beginning of a piece of text. See [https://github.com/google/blockly/wiki/Text#trimming-removing-spaces https://github.com/google/blockly/wiki/Text#trimming-removing-spaces]. Note that in right-to-left scripts, this will remove spaces from the right side.", - "TEXT_TRIM_OPERATOR_RIGHT": "dropdown - Removes spaces from the end of a piece of text. See [https://github.com/google/blockly/wiki/Text#trimming-removing-spaces https://github.com/google/blockly/wiki/Text#trimming-removing-spaces]. Note that in right-to-left scripts, this will remove spaces from the left side.", - "TEXT_PRINT_HELPURL": "url - Information about displaying text on computers.", - "TEXT_PRINT_TITLE": "block text - Display the input on the screen. See [https://github.com/google/blockly/wiki/Text#printing-text https://github.com/google/blockly/wiki/Text#printing-text]. \n\nParameters:\n* %1 - the value to print", - "TEXT_PRINT_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Text#printing-text https://github.com/google/blockly/wiki/Text#printing-text].", - "TEXT_PROMPT_HELPURL": "url - Information about getting text from users.", - "TEXT_PROMPT_TYPE_TEXT": "dropdown - Specifies that a piece of text should be requested from the user with the following message. See [https://github.com/google/blockly/wiki/Text#printing-text https://github.com/google/blockly/wiki/Text#printing-text].", - "TEXT_PROMPT_TYPE_NUMBER": "dropdown - Specifies that a number should be requested from the user with the following message. See [https://github.com/google/blockly/wiki/Text#printing-text https://github.com/google/blockly/wiki/Text#printing-text].", - "TEXT_PROMPT_TOOLTIP_NUMBER": "dropdown - Precedes the message with which the user should be prompted for a number. See [https://github.com/google/blockly/wiki/Text#printing-text https://github.com/google/blockly/wiki/Text#printing-text].", - "TEXT_PROMPT_TOOLTIP_TEXT": "dropdown - Precedes the message with which the user should be prompted for some text. See [https://github.com/google/blockly/wiki/Text#printing-text https://github.com/google/blockly/wiki/Text#printing-text].", - "LISTS_CREATE_EMPTY_HELPURL": "url - Information on empty lists.", - "LISTS_CREATE_EMPTY_TITLE": "block text - See [https://github.com/google/blockly/wiki/Lists#create-empty-list https://github.com/google/blockly/wiki/Lists#create-empty-list].", - "LISTS_CREATE_EMPTY_TOOLTIP": "block text - See [https://github.com/google/blockly/wiki/Lists#create-empty-list https://github.com/google/blockly/wiki/Lists#create-empty-list].", - "LISTS_CREATE_WITH_HELPURL": "url - Information on building lists.", - "LISTS_CREATE_WITH_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Lists#create-list-with https://github.com/google/blockly/wiki/Lists#create-list-with].", - "LISTS_CREATE_WITH_INPUT_WITH": "block text - See [https://github.com/google/blockly/wiki/Lists#create-list-with https://github.com/google/blockly/wiki/Lists#create-list-with].", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "block text - This appears in a sub-block when [https://github.com/google/blockly/wiki/Lists#changing-number-of-inputs changing the number of inputs in a ''''create list with'''' block].\n{{Identical|List}}", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Lists#changing-number-of-inputs https://github.com/google/blockly/wiki/Lists#changing-number-of-inputs].", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Lists#changing-number-of-inputs https://github.com/google/blockly/wiki/Lists#changing-number-of-inputs].", - "LISTS_REPEAT_HELPURL": "url - Information about [https://github.com/google/blockly/wiki/Lists#create-list-with creating a list with multiple copies of a single item].", - "LISTS_REPEAT_TOOLTIP": "url - See [https://github.com/google/blockly/wiki/Lists#create-list-with creating a list with multiple copies of a single item].", - "LISTS_REPEAT_TITLE": "block text - See [https://github.com/google/blockly/wiki/Lists#create-list-with https://github.com/google/blockly/wiki/Lists#create-list-with]. \n\nParameters:\n* %1 - the item (text) to be repeated\n* %2 - the number of times to repeat it", - "LISTS_LENGTH_HELPURL": "url - Information about how the length of a list is computed (i.e., by the total number of elements, not the number of different elements).", - "LISTS_LENGTH_TITLE": "block text - See [https://github.com/google/blockly/wiki/Lists#length-of https://github.com/google/blockly/wiki/Lists#length-of]. \n\nParameters:\n* %1 - the list whose length is desired", - "LISTS_LENGTH_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Lists#length-of https://github.com/google/blockly/wiki/Lists#length-of Blockly:Lists:length of].", - "LISTS_ISEMPTY_HELPURL": "url - See [https://github.com/google/blockly/wiki/Lists#is-empty https://github.com/google/blockly/wiki/Lists#is-empty].", - "LISTS_ISEMPTY_TITLE": "block text - See [https://github.com/google/blockly/wiki/Lists#is-empty https://github.com/google/blockly/wiki/Lists#is-empty]. \n\nParameters:\n* %1 - the list to test", - "LISTS_ISEMPTY_TOOLTIP": "block tooltip - See [https://github.com/google/blockly/wiki/Lists#is-empty https://github.com/google/blockly/wiki/Lists#is-empty].", - "LISTS_INLIST": "block text - Title of blocks operating on [https://github.com/google/blockly/wiki/Lists lists].", - "LISTS_INDEX_OF_HELPURL": "url - See [https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list].", - "LISTS_INDEX_OF_FIRST": "dropdown - See [https://github.com/google/blockly/wiki/Lists#finding-items-in-a-list Lists#finding-items-in-a-list]. [[File:Blockly-list-find.png]]", - "LISTS_INDEX_OF_LAST": "dropdown - See [https://github.com/google/blockly/wiki/Lists#finding-items-in-a-list https://github.com/google/blockly/wiki/Lists#finding-items-in-a-list]. [[File:Blockly-list-find.png]]", - "LISTS_INDEX_OF_TOOLTIP": "tooltip - %1 will be replaced by either the number 0 or -1 depending on the indexing mode. See [https://github.com/google/blockly/wiki/Lists#finding-items-in-a-list https://github.com/google/blockly/wiki/Lists#finding-items-in-a-list]. [[File:Blockly-list-find.png]]", - "LISTS_GET_INDEX_GET": "dropdown - Indicates that the user wishes to [https://github.com/google/blockly/wiki/Lists#getting-a-single-item get an item from a list] without removing it from the list.", - "LISTS_GET_INDEX_GET_REMOVE": "dropdown - Indicates that the user wishes to [https://github.com/google/blockly/wiki/Lists#getting-a-single-item get and remove an item from a list], as opposed to merely getting it without modifying the list.", - "LISTS_GET_INDEX_REMOVE": "dropdown - Indicates that the user wishes to [https://github.com/google/blockly/wiki/Lists#removing-an-item remove an item from a list].\n{{Identical|Remove}}", - "LISTS_GET_INDEX_FROM_START": "dropdown - Indicates that an index relative to the front of the list should be used to [https://github.com/google/blockly/wiki/Lists#getting-a-single-item get and/or remove an item from a list]. Note: If {{msg-Blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will automatically appear ''after'' this number (and any other ordinal numbers on this block). See [[Translating:Blockly#Ordinal_numbers]] for more information on ordinal numbers in Blockly. [[File:Blockly-list-get-item.png]]", - "LISTS_GET_INDEX_FROM_END": "dropdown - Indicates that an index relative to the end of the list should be used to [https://github.com/google/blockly/wiki/Lists#getting-a-single-item access an item in a list]. [[File:Blockly-list-get-item.png]]", - "LISTS_GET_INDEX_FIRST": "dropdown - Indicates that the '''first''' item should be [https://github.com/google/blockly/wiki/Lists#getting-a-single-item accessed in a list]. [[File:Blockly-list-get-item.png]]", - "LISTS_GET_INDEX_LAST": "dropdown - Indicates that the '''last''' item should be [https://github.com/google/blockly/wiki/Lists#getting-a-single-item accessed in a list]. [[File:Blockly-list-get-item.png]]", - "LISTS_GET_INDEX_RANDOM": "dropdown - Indicates that a '''random''' item should be [https://github.com/google/blockly/wiki/Lists#getting-a-single-item accessed in a list]. [[File:Blockly-list-get-item.png]]", - "LISTS_GET_INDEX_TAIL": "block text - Text that should go after the rightmost block/dropdown when [https://github.com/google/blockly/wiki/Lists#getting-a-single-item accessing an item from a list]. In most languages, this will be the empty string. [[File:Blockly-list-get-item.png]]", - "LISTS_INDEX_FROM_START_TOOLTIP": "tooltip - Indicates the ordinal number that the first item in a list is referenced by. %1 will be replaced by either '#0' or '#1' depending on the indexing mode.", - "LISTS_INDEX_FROM_END_TOOLTIP": "tooltip - Indicates the ordinal number that the last item in a list is referenced by. %1 will be replaced by either '#0' or '#1' depending on the indexing mode.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for more information.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for more information.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for more information.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for more information.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for '#' or '# from end'.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for 'first'.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for 'last'.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for 'random'.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for '#' or '# from end'.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for 'first'.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for 'last'.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for 'random'.", - "LISTS_SET_INDEX_HELPURL": "url - Information about putting items in lists.", - "LISTS_SET_INDEX_SET": "block text - [https://github.com/google/blockly/wiki/Lists#in-list--set Replaces an item in a list]. [[File:Blockly-in-list-set-insert.png]]", - "LISTS_SET_INDEX_INSERT": "block text - [https://github.com/google/blockly/wiki/Lists#in-list--insert-at Inserts an item into a list]. [[File:Blockly-in-list-set-insert.png]]", - "LISTS_SET_INDEX_INPUT_TO": "block text - The word(s) after the position in the list and before the item to be set/inserted. [[File:Blockly-in-list-set-insert.png]]", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the 'get' block, the idea is the same for the 'set' block).", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the 'get' block, the idea is the same for the 'set' block).", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the 'get' block, the idea is the same for the 'set' block).", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the 'get' block, the idea is the same for the 'set' block).", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the 'get' block, the idea is the same for the 'insert' block).", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the 'get' block, the idea is the same for the 'insert' block).", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the 'get' block, the idea is the same for the 'insert' block).", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the 'get' block, the idea is the same for the 'insert' block).", - "LISTS_GET_SUBLIST_HELPURL": "url - Information describing extracting a sublist from an existing list.", - "LISTS_GET_SUBLIST_START_FROM_START": "dropdown - Indicates that an index relative to the front of the list should be used to specify the beginning of the range from which to [https://github.com/google/blockly/wiki/Lists#getting-a-sublist get a sublist]. [[File:Blockly-get-sublist.png]] Note: If {{msg-Blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will automatically appear ''after'' this number (and any other ordinal numbers on this block). See [[Translating:Blockly#Ordinal_numbers]] for more information on ordinal numbers in Blockly.", - "LISTS_GET_SUBLIST_START_FROM_END": "dropdown - Indicates that an index relative to the end of the list should be used to specify the beginning of the range from which to [https://github.com/google/blockly/wiki/Lists#getting-a-sublist get a sublist].", - "LISTS_GET_SUBLIST_START_FIRST": "dropdown - Indicates that the [https://github.com/google/blockly/wiki/Lists#getting-a-sublist sublist to extract] should begin with the list's first item.", - "LISTS_GET_SUBLIST_END_FROM_START": "dropdown - Indicates that an index relative to the front of the list should be used to specify the end of the range from which to [https://github.com/google/blockly/wiki/Lists#getting-a-sublist get a sublist]. [[File:Blockly-get-sublist.png]]", - "LISTS_GET_SUBLIST_END_FROM_END": "dropdown - Indicates that an index relative to the end of the list should be used to specify the end of the range from which to [https://github.com/google/blockly/wiki/Lists#getting-a-sublist get a sublist]. [[File:Blockly-get-sublist.png]]", - "LISTS_GET_SUBLIST_END_LAST": "dropdown - Indicates that the '''last''' item in the given list should be [https://github.com/google/blockly/wiki/Lists#getting-a-sublist the end of the selected sublist]. [[File:Blockly-get-sublist.png]]", - "LISTS_GET_SUBLIST_TAIL": "block text - This appears in the rightmost position ('tail') of the sublist block, as described at [https://github.com/google/blockly/wiki/Lists#getting-a-sublist https://github.com/google/blockly/wiki/Lists#getting-a-sublist]. In English and most other languages, this is the empty string. [[File:Blockly-get-sublist.png]]", - "LISTS_GET_SUBLIST_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-sublist https://github.com/google/blockly/wiki/Lists#getting-a-sublist] for more information. [[File:Blockly-get-sublist.png]]", - "LISTS_SORT_HELPURL": "url - Information describing sorting a list.", - "LISTS_SORT_TITLE": "Sort as type %1 (numeric or alphabetic) in order %2 (ascending or descending) a list of items %3.\n{{Identical|Sort}}", - "LISTS_SORT_TOOLTIP": "tooltip - See [https://github.com/google/blockly/wiki/Lists#sorting-a-list].", - "LISTS_SORT_ORDER_ASCENDING": "sorting order or direction from low to high value for numeric, or A-Z for alphabetic.\n{{Identical|Ascending}}", - "LISTS_SORT_ORDER_DESCENDING": "sorting order or direction from high to low value for numeric, or Z-A for alphabetic.\n{{Identical|Descending}}", - "LISTS_SORT_TYPE_NUMERIC": "sort by treating each item as a number.", - "LISTS_SORT_TYPE_TEXT": "sort by treating each item alphabetically, case-sensitive.", - "LISTS_SORT_TYPE_IGNORECASE": "sort by treating each item alphabetically, ignoring differences in case.", - "LISTS_SPLIT_HELPURL": "url - Information describing splitting text into a list, or joining a list into text.", - "LISTS_SPLIT_LIST_FROM_TEXT": "dropdown - Indicates that text will be split up into a list (e.g. 'a-b-c' -> ['a', 'b', 'c']).", - "LISTS_SPLIT_TEXT_FROM_LIST": "dropdown - Indicates that a list will be joined together to form text (e.g. ['a', 'b', 'c'] -> 'a-b-c').", - "LISTS_SPLIT_WITH_DELIMITER": "block text - Prompts for a letter to be used as a separator when splitting or joining text.", - "LISTS_SPLIT_TOOLTIP_SPLIT": "tooltip - See [https://github.com/google/blockly/wiki/Lists#make-list-from-text https://github.com/google/blockly/wiki/Lists#make-list-from-text] for more information.", - "LISTS_SPLIT_TOOLTIP_JOIN": "tooltip - See [https://github.com/google/blockly/wiki/Lists#make-text-from-list https://github.com/google/blockly/wiki/Lists#make-text-from-list] for more information.", - "ORDINAL_NUMBER_SUFFIX": "grammar - Text that follows an ordinal number (a number that indicates position relative to other numbers). In most languages, such text appears before the number, so this should be blank. An exception is Hungarian. See [[Translating:Blockly#Ordinal_numbers]] for more information.", - "VARIABLES_GET_HELPURL": "url - Information about ''variables'' in computer programming. Consider using your language's translation of [https://en.wikipedia.org/wiki/Variable_(computer_science) https://en.wikipedia.org/wiki/Variable_(computer_science)], if it exists.", - "VARIABLES_GET_TOOLTIP": "tooltip - This gets the value of the named variable without modifying it.", - "VARIABLES_GET_CREATE_SET": "context menu - Selecting this creates a block to set (change) the value of this variable. \n\nParameters:\n* %1 - the name of the variable.", - "VARIABLES_SET_HELPURL": "url - Information about ''variables'' in computer programming. Consider using your language's translation of [https://en.wikipedia.org/wiki/Variable_(computer_science) https://en.wikipedia.org/wiki/Variable_(computer_science)], if it exists.", - "VARIABLES_SET": "block text - Change the value of a mathematical variable: '''set [the value of] x to 7'''.\n\nParameters:\n* %1 - the name of the variable.\n* %2 - the value to be assigned.", - "VARIABLES_SET_TOOLTIP": "tooltip - This initializes or changes the value of the named variable.", - "VARIABLES_SET_CREATE_GET": "context menu - Selecting this creates a block to get (change) the value of this variable.\n\nParameters:\n* %1 - the name of the variable.", - "PROCEDURES_DEFNORETURN_HELPURL": "url - Information about defining [https://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that do not have return values.", - "PROCEDURES_DEFNORETURN_TITLE": "block text - This precedes the name of the function when defining it. See [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#c84aoc this sample function definition].", - "PROCEDURES_DEFNORETURN_PROCEDURE": "default name - This acts as a placeholder for the name of a function on a function definition block, as shown on [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#w7cfju this block]. The user will replace it with the function's name.", - "PROCEDURES_BEFORE_PARAMS": "block text - This precedes the list of parameters on a function's defiition block. See [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#voztpd this sample function with parameters].", - "PROCEDURES_CALL_BEFORE_PARAMS": "block text - This precedes the list of parameters on a function's caller block. See [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#voztpd this sample function with parameters].", - "PROCEDURES_DEFNORETURN_DO": "block text - This appears next to the function's 'body', the blocks that should be run when the function is called, as shown in [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#voztpd this sample function definition].", - "PROCEDURES_DEFNORETURN_TOOLTIP": "tooltip", - "PROCEDURES_DEFNORETURN_COMMENT": "Placeholder text that the user is encouraged to replace with a description of what their function does.", - "PROCEDURES_DEFRETURN_HELPURL": "url - Information about defining [https://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that have return values.", - "PROCEDURES_DEFRETURN_RETURN": "block text - This imperative or infinite verb precedes the value that is used as the return value (output) of this function. See [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#6ot5y5 this sample function that returns a value].", - "PROCEDURES_DEFRETURN_TOOLTIP": "tooltip", - "PROCEDURES_ALLOW_STATEMENTS": "Label for a checkbox that controls if statements are allowed in a function.", - "PROCEDURES_DEF_DUPLICATE_WARNING": "alert - The user has created a function with two parameters that have the same name. Every parameter must have a different name.", - "PROCEDURES_CALLNORETURN_HELPURL": "url - Information about calling [https://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that do not return values.", - "PROCEDURES_CALLNORETURN_TOOLTIP": "tooltip - This block causes the body (blocks inside) of the named function definition to be run.", - "PROCEDURES_CALLRETURN_HELPURL": "url - Information about calling [https://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that return values.", - "PROCEDURES_CALLRETURN_TOOLTIP": "tooltip - This block causes the body (blocks inside) of the named function definition to be run.\n\nParameters:\n* %1 - the name of the function.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "block text - This text appears on a block in a window that appears when the user clicks on the plus sign or star on a function definition block. It refers to the set of parameters (referred to by the simpler term 'inputs') to the function. See [[Translating:Blockly#function_definitions]].", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "tooltip", - "PROCEDURES_MUTATORARG_TITLE": "block text - This text appears on a block in a window that appears when the user clicks on the plus sign or star on a function definition block]. It appears on the block for adding an individual parameter (referred to by the simpler term 'inputs') to the function. See [[Translating:Blockly#function_definitions]].", - "PROCEDURES_MUTATORARG_TOOLTIP": "tooltip", - "PROCEDURES_HIGHLIGHT_DEF": "context menu - This appears on the context menu for function calls. Selecting it causes the corresponding function definition to be highlighted (as shown at [[Translating:Blockly#context_menus]].", - "PROCEDURES_CREATE_DO": "context menu - This appears on the context menu for function definitions. Selecting it creates a block to call the function.\n\nParameters:\n* %1 - the name of the function.\n{{Identical|Create}}", - "PROCEDURES_IFRETURN_TOOLTIP": "tooltip - If the first value is true, this causes the second value to be returned immediately from the enclosing function.", - "PROCEDURES_IFRETURN_HELPURL": "url - Information about guard clauses.", - "PROCEDURES_IFRETURN_WARNING": "warning - This appears if the user tries to use this block outside of a function definition." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/ro.json b/backend/_pv_1_3_5/static/blockly/msg/json/ro.json deleted file mode 100755 index f85ee988a..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/ro.json +++ /dev/null @@ -1,318 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Minisarm", - "Ely en", - "Hugbear", - "아라" - ] - }, - "VARIABLES_DEFAULT_NAME": "element", - "TODAY": "Astăzi", - "DUPLICATE_BLOCK": "Duplicati", - "ADD_COMMENT": "Adaugă un comentariu", - "REMOVE_COMMENT": "Elimină comentariu", - "EXTERNAL_INPUTS": "Intrări externe", - "INLINE_INPUTS": "Intrări în linie", - "DELETE_BLOCK": "Șterge Bloc", - "DELETE_X_BLOCKS": "Ștergeți %1 Blocuri", - "DELETE_ALL_BLOCKS": "Ștergi toate cele %1 (de) blocuri?", - "COLLAPSE_BLOCK": "Restrange blocul", - "COLLAPSE_ALL": "Restrange blocurile", - "EXPAND_BLOCK": "Extinde bloc", - "EXPAND_ALL": "Extinde blocuri", - "DISABLE_BLOCK": "Dezactivaţi bloc", - "ENABLE_BLOCK": "Permite bloc", - "HELP": "Ajutor", - "CHANGE_VALUE_TITLE": "Schimbaţi valoarea:", - "RENAME_VARIABLE": "Redenumirea variabilei...", - "RENAME_VARIABLE_TITLE": "Redenumeşte toate variabilele '%1' în:", - "NEW_VARIABLE": "Variabilă nouă...", - "NEW_VARIABLE_TITLE": "Noul nume de variabilă:", - "COLOUR_PICKER_HELPURL": "https://ro.wikipedia.org/wiki/Culoare", - "COLOUR_PICKER_TOOLTIP": "Alege o culoare din paleta de culori.", - "COLOUR_RANDOM_TITLE": "culoare aleatorie", - "COLOUR_RANDOM_TOOLTIP": "Alege o culoare la întâmplare.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "colorează cu", - "COLOUR_RGB_RED": "roşu", - "COLOUR_RGB_GREEN": "verde", - "COLOUR_RGB_BLUE": "albastru", - "COLOUR_RGB_TOOLTIP": "Creează o culoare cu suma specificată de roşu, verde şi albastru. Toate valorile trebuie să fie între 0 şi 100.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "amestec", - "COLOUR_BLEND_COLOUR1": "culoare 1", - "COLOUR_BLEND_COLOUR2": "culoare 2", - "COLOUR_BLEND_RATIO": "Raport", - "COLOUR_BLEND_TOOLTIP": "Amestecă două culori cu un raport dat (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "repetă de %1 ori", - "CONTROLS_REPEAT_INPUT_DO": "fă", - "CONTROLS_REPEAT_TOOLTIP": "Face unele afirmaţii de mai multe ori.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "repetă în timp ce", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "Repetaţi până când", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "În timp ce o valoare este adevărat, atunci face unele declaraţii.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "În timp ce o valoare este adevărat, atunci face unele declaraţii.", - "CONTROLS_FOR_TOOLTIP": "Cu variablia \"%1\" ia o valoare din numărul început la numărul final, numara in intervalul specificat, apoi face blocurile specificate.", - "CONTROLS_FOR_TITLE": "numără cu %1 de la %2 la %3 prin %4", - "CONTROLS_FOREACH_TITLE": "pentru fiecare element %1 în listă %2", - "CONTROLS_FOREACH_TOOLTIP": "Pentru fiecare element din listă, setaţi variabila '%1' ca valoarea elementului, şi apoi faceţi unele declaraţii.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "ieşi din bucla", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "continuă cu următoarea iterație a buclei", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Ieși din bucla care conţine.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Sari peste restul aceastei bucle, şi continuă cu urmatoarea iteratie.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Avertisment: Acest bloc pote fi utilizat numai în interiorul unei bucle.", - "CONTROLS_IF_TOOLTIP_1": "Dacă o valoare este adevărată, atunci fa unele declaraţii.", - "CONTROLS_IF_TOOLTIP_2": "Dacă o valoare este adevărat, atunci face primul bloc de declaraţii. Altfel, face al doilea bloc de declaraţii.", - "CONTROLS_IF_TOOLTIP_3": "Dacă prima valoare este adevărat, atunci face primul bloc de declaraţii. Altfel, dacă a doua valoare este adevărat, face al doilea bloc de declaraţii.", - "CONTROLS_IF_TOOLTIP_4": "Dacă prima valoare este adevărat, atunci face primul bloc de declaraţii. Altfel, dacă a doua valoare este adevărat, face al doilea bloc de declaraţii. În cazul în care niciuna din valorilor nu este adevărat, face ultimul bloc de declaraţii.", - "CONTROLS_IF_MSG_IF": "dacă", - "CONTROLS_IF_MSG_ELSEIF": "altfel dacă", - "CONTROLS_IF_MSG_ELSE": "altfel", - "CONTROLS_IF_IF_TOOLTIP": "Adaugă, elimină sau reordonează secţiuni pentru a reconfigura acest bloc if.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Adăugaţi o condiţie in blocul if.", - "CONTROLS_IF_ELSE_TOOLTIP": "Adauga o stare finala, cuprinde toata conditia din blocul if.", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Returnează adevărat dacă ambele intrări sunt egale.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Returnează adevărat daca cele două intrări nu sunt egale.", - "LOGIC_COMPARE_TOOLTIP_LT": "Returnează adevărat dacă prima intrare este mai mică decât a doua intrare.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Returnează adevărat dacă prima intrare este mai mică sau egală cu a doua intrare.", - "LOGIC_COMPARE_TOOLTIP_GT": "Returnează adevărat dacă prima intrare este mai mare decât a doua intrare.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Returnează adevărat dacă prima intrare este mai mare sau egală cu a doua intrare.", - "LOGIC_OPERATION_TOOLTIP_AND": "Returnează adevărat daca ambele intrări sunt adevărate.", - "LOGIC_OPERATION_AND": "şi", - "LOGIC_OPERATION_TOOLTIP_OR": "Returnează adevărat dacă cel puţin una din intrări este adevărată.", - "LOGIC_OPERATION_OR": "sau", - "LOGIC_NEGATE_TITLE": "non %1", - "LOGIC_NEGATE_TOOLTIP": "Returnează adevărat dacă intrarea este falsă. Returnează fals dacă intrarea este adevărată.", - "LOGIC_BOOLEAN_TRUE": "adevărat", - "LOGIC_BOOLEAN_FALSE": "fals", - "LOGIC_BOOLEAN_TOOLTIP": "Returnează adevărat sau fals.", - "LOGIC_NULL_HELPURL": "https://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "nul", - "LOGIC_NULL_TOOLTIP": "returnează nul.", - "LOGIC_TERNARY_HELPURL": "https://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "dacă este adevărat", - "LOGIC_TERNARY_IF_FALSE": "dacă este fals", - "LOGIC_TERNARY_TOOLTIP": "Verifică condiţia din \"test\". Dacă condiţia este adevărată, returnează valoarea \"în cazul în care adevărat\"; în caz contrar întoarce valoarea \"în cazul în care e fals\".", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "Un număr.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tg", - "MATH_TRIG_ASIN": "arcsin", - "MATH_TRIG_ACOS": "arccos", - "MATH_TRIG_ATAN": "arctg", - "MATH_ARITHMETIC_HELPURL": "https://ro.wikipedia.org/wiki/Aritmetic%C4%83", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Returnează suma a două numere.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Returneaza diferenţa dintre cele două numere.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Returnează produsul celor două numere.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Returnează câtul celor două numere.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Returneaza numărul rezultat prin ridicarea primului număr la puterea celui de-al doilea.", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "rădăcina pătrată", - "MATH_SINGLE_TOOLTIP_ROOT": "Returnează rădăcina pătrată a unui număr.", - "MATH_SINGLE_OP_ABSOLUTE": "absolută", - "MATH_SINGLE_TOOLTIP_ABS": "Returnează valoarea absolută a unui număr.", - "MATH_SINGLE_TOOLTIP_NEG": "Returnează negaţia unui număr.", - "MATH_SINGLE_TOOLTIP_LN": "Întoarce logaritmul natural al unui număr.", - "MATH_SINGLE_TOOLTIP_LOG10": "Returnează logaritmul în baza 10 a unui număr.", - "MATH_SINGLE_TOOLTIP_EXP": "Returnează e la puterea unui număr.", - "MATH_SINGLE_TOOLTIP_POW10": "Returnează 10 la puterea unui număr.", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "Întoarce cosinusul unui grad (nu radianul).", - "MATH_TRIG_TOOLTIP_COS": "Întoarce cosinusul unui grad (nu radianul).", - "MATH_TRIG_TOOLTIP_TAN": "Întoarce tangenta unui grad (nu radianul).", - "MATH_TRIG_TOOLTIP_ASIN": "Returnează arcsinusul unui număr.", - "MATH_TRIG_TOOLTIP_ACOS": "Returnează arccosinusul unui număr.", - "MATH_TRIG_TOOLTIP_ATAN": "Returnează arctangenta unui număr.", - "MATH_CONSTANT_HELPURL": "https://ro.wikipedia.org/wiki/Constant%C4%83_matematic%C4%83", - "MATH_CONSTANT_TOOLTIP": "Întoarcă una din constantele comune: π (3.141...), e (2.718...), φ (1,618...), sqrt(2) (1.414...), sqrt(½) (0.707...) sau ∞ (infinitate).", - "MATH_IS_EVEN": "este par", - "MATH_IS_ODD": "este impar", - "MATH_IS_PRIME": "este prim", - "MATH_IS_WHOLE": "este întreg", - "MATH_IS_POSITIVE": "este pozitiv", - "MATH_IS_NEGATIVE": "este negativ", - "MATH_IS_DIVISIBLE_BY": "este divizibil cu", - "MATH_IS_TOOLTIP": "Verifică dacă un număr este un par, impar, prim, întreg, pozitiv, negativ, sau dacă este divizibil cu un anumit număr. Returnează true sau false.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "schimbă %1 de %2", - "MATH_CHANGE_TOOLTIP": "Adaugă un număr variabilei '%1'.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Rotunjirea unui număr în sus sau în jos.", - "MATH_ROUND_OPERATOR_ROUND": "rotund", - "MATH_ROUND_OPERATOR_ROUNDUP": "rotunjește în sus", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "rotunjit", - "MATH_ONLIST_OPERATOR_SUM": "suma listei", - "MATH_ONLIST_TOOLTIP_SUM": "Returnează suma tuturor numerelor din lista.", - "MATH_ONLIST_OPERATOR_MIN": "minimul listei", - "MATH_ONLIST_TOOLTIP_MIN": "Returnează cel mai mic număr din listă.", - "MATH_ONLIST_OPERATOR_MAX": "maximul listei", - "MATH_ONLIST_TOOLTIP_MAX": "Întoarce cel mai mare număr din listă.", - "MATH_ONLIST_OPERATOR_AVERAGE": "media listei", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Întoarce media (aritmetică) a valorilor numerice în listă.", - "MATH_ONLIST_OPERATOR_MEDIAN": "media listei", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Întoarce numărul median în listă.", - "MATH_ONLIST_OPERATOR_MODE": "moduri de listă", - "MATH_ONLIST_TOOLTIP_MODE": "Returnează o listă cu cel(e) mai frecvent(e) element(e) din listă.", - "MATH_ONLIST_OPERATOR_STD_DEV": "deviația standard a listei", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Întoarce deviația standard a listei.", - "MATH_ONLIST_OPERATOR_RANDOM": "element aleatoriu din lista", - "MATH_ONLIST_TOOLTIP_RANDOM": "Returnează un element aleatoriu din listă.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "restul la %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Întoarce restul din împărţirea celor două numere.", - "MATH_CONSTRAIN_TITLE": "constrânge %1 redus %2 ridicat %3", - "MATH_CONSTRAIN_TOOLTIP": "Constrânge un număr să fie între limitele specificate (inclusiv).", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "un număr întreg aleator de la %1 la %2", - "MATH_RANDOM_INT_TOOLTIP": "Returnează un număr întreg aleator aflat între cele două limite specificate, inclusiv.", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "fracții aleatorii", - "MATH_RANDOM_FLOAT_TOOLTIP": "Returnează o fracţie aleatoare între 0.0 (inclusiv) si 1.0 (exclusiv).", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "O literă, cuvânt sau linie de text.", - "TEXT_JOIN_TITLE_CREATEWITH": "crează text cu", - "TEXT_JOIN_TOOLTIP": "Creaţi o bucată de text prin unirea oricărui număr de elemente.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "alăturaţi-vă", - "TEXT_CREATE_JOIN_TOOLTIP": "Adaugă, elimină sau reordonează secțiuni ca să reconfigureze blocul text.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Adaugă un element în text.", - "TEXT_APPEND_TO": "la", - "TEXT_APPEND_APPENDTEXT": "Adăugaţi text", - "TEXT_APPEND_TOOLTIP": "Adăugaţi text la variabila '%1'.", - "TEXT_LENGTH_TITLE": "lungime de %1", - "TEXT_LENGTH_TOOLTIP": "Returnează numărul de litere (inclusiv spaţiile) în textul furnizat.", - "TEXT_ISEMPTY_TITLE": "%1 este gol", - "TEXT_ISEMPTY_TOOLTIP": "Returnează adevărat dacă textul furnizat este gol.", - "TEXT_INDEXOF_TOOLTIP": "Returnează indicele primei/ultimei apariţii din primul text în al doilea text. Returnează %1 dacă textul nu este găsit.", - "TEXT_INDEXOF_INPUT_INTEXT": "în text", - "TEXT_INDEXOF_OPERATOR_FIRST": "găseşte prima apariţie a textului", - "TEXT_INDEXOF_OPERATOR_LAST": "găseşte ultima apariţie a textului", - "TEXT_CHARAT_INPUT_INTEXT": "în text", - "TEXT_CHARAT_FROM_START": "obtine litera #", - "TEXT_CHARAT_FROM_END": "obţine litera # de la sfârșit", - "TEXT_CHARAT_FIRST": "obţine prima litera", - "TEXT_CHARAT_LAST": "obţine o litera oarecare", - "TEXT_CHARAT_RANDOM": "obtine o litera oarecare", - "TEXT_CHARAT_TOOLTIP": "Returnează litera la poziția specificată.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Returnează o anumită parte din text.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "în text", - "TEXT_GET_SUBSTRING_START_FROM_START": "obține subșir de la litera #", - "TEXT_GET_SUBSTRING_START_FROM_END": "obține un subșir de la litera # de la sfârșit", - "TEXT_GET_SUBSTRING_START_FIRST": "obţine un subșir de la prima literă", - "TEXT_GET_SUBSTRING_END_FROM_START": "la litera #", - "TEXT_GET_SUBSTRING_END_FROM_END": "la litera # de la sfarsit", - "TEXT_GET_SUBSTRING_END_LAST": "la ultima literă", - "TEXT_CHANGECASE_TOOLTIP": "Întoarce o copie a textului într-un caz diferit.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "la MAJUSCULE", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "la litere mici", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "către Titlul de caz", - "TEXT_TRIM_TOOLTIP": "Returnează o copie a textului fără spațiile de la unul sau ambele capete.", - "TEXT_TRIM_OPERATOR_BOTH": "taie spațiile de pe ambele părți ale", - "TEXT_TRIM_OPERATOR_LEFT": "tăiaţi spațiile din partea stângă a", - "TEXT_TRIM_OPERATOR_RIGHT": "taie spațiile din partea dreaptă a", - "TEXT_PRINT_TITLE": "imprimare %1", - "TEXT_PRINT_TOOLTIP": "Afișează textul specificat, numărul sau altă valoare.", - "TEXT_PROMPT_TYPE_TEXT": "solicită pentru text cu mesaj", - "TEXT_PROMPT_TYPE_NUMBER": "solicită pentru număr cu mesaj", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Solicită utilizatorul pentru un număr.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Solicită utilizatorul pentru text.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "creează listă goală", - "LISTS_CREATE_EMPTY_TOOLTIP": "Returnează o listă, de lungime 0, care nu conţine înregistrări de date", - "LISTS_CREATE_WITH_TOOLTIP": "Creaţi o listă cu orice număr de elemente.", - "LISTS_CREATE_WITH_INPUT_WITH": "creează listă cu", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "listă", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Adaugă, elimină sau reordonează secţiuni ca să reconfiguraţi aceste blocuri de listă.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Adăugaţi un element la listă.", - "LISTS_REPEAT_TOOLTIP": "Creează o listă alcătuită dintr-o anumită valoare repetată de numărul specificat de ori.", - "LISTS_REPEAT_TITLE": "creaza lista cu %1 elemente repetate de %2 ori", - "LISTS_LENGTH_TITLE": "lungime de %1", - "LISTS_LENGTH_TOOLTIP": "Returnează lungimea unei liste.", - "LISTS_ISEMPTY_TITLE": "%1 este gol", - "LISTS_ISEMPTY_TOOLTIP": "Returnează adevărat dacă lista este goală.", - "LISTS_INLIST": "în listă", - "LISTS_INDEX_OF_FIRST": "Găseşte prima apariţie a elementului", - "LISTS_INDEX_OF_LAST": "găseşte ultima apariţie a elementului", - "LISTS_INDEX_OF_TOOLTIP": "Revine la indexul de la prima/ultima apariție a elementului din listă. Returnează %1 dacă elementul nu este găsit.", - "LISTS_GET_INDEX_GET": "obţine", - "LISTS_GET_INDEX_GET_REMOVE": "obţine şi elimină", - "LISTS_GET_INDEX_REMOVE": "elimină", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# de la sfârșit", - "LISTS_GET_INDEX_FIRST": "primul", - "LISTS_GET_INDEX_LAST": "ultimul", - "LISTS_GET_INDEX_RANDOM": "aleator", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 este primul element.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 este ultimul element.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Returneaza elementul la poziţia specificată într-o listă.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Returnează primul element dintr-o listă.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Returnează ultimul element într-o listă.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Returneaza un element aleatoriu într-o listă.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Elimină şi returneaza elementul la poziţia specificată într-o listă.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Elimină şi returnează primul element într-o listă.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Elimină şi returnează ultimul element într-o listă.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Elimină şi returnează un element aleatoriu într-o listă.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Elimină elementul la poziţia specificată într-o listă.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Elimină primul element într-o listă.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Elimină ultimul element într-o listă.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Elimină un element aleatoriu într-o listă.", - "LISTS_SET_INDEX_SET": "seteaza", - "LISTS_SET_INDEX_INSERT": "introduceţi la", - "LISTS_SET_INDEX_INPUT_TO": "ca", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Setează elementul la poziţia specificată într-o listă.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Setează primul element într-o listă.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Setează ultimul element într-o listă.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Setează un element aleator într-o listă.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Inserează elementul la poziţia specificată într-o listă.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Inserează elementul la începutul unei liste.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Adăugă elementul la sfârşitul unei liste.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Inserează elementul aleatoriu într-o listă.", - "LISTS_GET_SUBLIST_START_FROM_START": "obţine sub-lista de la #", - "LISTS_GET_SUBLIST_START_FROM_END": "obţine sub-lista de la # de la sfârşitul", - "LISTS_GET_SUBLIST_START_FIRST": "obţine sub-lista de la primul", - "LISTS_GET_SUBLIST_END_FROM_START": "la #", - "LISTS_GET_SUBLIST_END_FROM_END": "la # de la sfarsit", - "LISTS_GET_SUBLIST_END_LAST": "la ultima", - "LISTS_GET_SUBLIST_TOOLTIP": "Creează o copie a porţiunii specificate dintr-o listă.", - "LISTS_SPLIT_LIST_FROM_TEXT": "convertește textul în listă", - "LISTS_SPLIT_TEXT_FROM_LIST": "convertește lista în text", - "LISTS_SPLIT_WITH_DELIMITER": "cu separatorul", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Împarte textul într-o listă de texte, despărțite prin fiecare separator", - "LISTS_SPLIT_TOOLTIP_JOIN": "Concatenează o listă de texte (alternate cu separatorul) într-un text unic", - "VARIABLES_GET_TOOLTIP": "Returnează valoarea acestei variabile.", - "VARIABLES_GET_CREATE_SET": "Crează 'set %1'", - "VARIABLES_SET": "seteaza %1 la %2", - "VARIABLES_SET_TOOLTIP": "Setează această variabilă sa fie egală la intrare.", - "VARIABLES_SET_CREATE_GET": "Crează 'get %1'", - "PROCEDURES_DEFNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFNORETURN_TITLE": "la", - "PROCEDURES_DEFNORETURN_PROCEDURE": "fă ceva", - "PROCEDURES_BEFORE_PARAMS": "cu:", - "PROCEDURES_CALL_BEFORE_PARAMS": "cu:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Crează o funcţie cu nici o ieşire.", - "PROCEDURES_DEFRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFRETURN_RETURN": "returnează", - "PROCEDURES_DEFRETURN_TOOLTIP": "Creează o funcţie cu o ieşire.", - "PROCEDURES_ALLOW_STATEMENTS": "permite declarațiile", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Atenţie: Această funcţie are parametri duplicaţi.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Executați funcția '%1 'definită de utilizator.", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Executați funcția '%1 'definită de utilizator şi folosiţi producţia sa.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "intrări", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Adăugă, șterge sau reordonează parametrii de intrare ai acestei funcții.", - "PROCEDURES_MUTATORARG_TITLE": "nume de intrare:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Adaugă un parametru de intrare pentru funcție.", - "PROCEDURES_HIGHLIGHT_DEF": "Evidenţiază definiţia funcţiei", - "PROCEDURES_CREATE_DO": "Creaţi '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Dacă o valoare este adevărată, atunci returnează valoarea a doua.", - "PROCEDURES_IFRETURN_WARNING": "Avertisment: Acest bloc poate fi utilizat numai în definiţia unei funcţii." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/ru.json b/backend/_pv_1_3_5/static/blockly/msg/json/ru.json deleted file mode 100755 index 1dd176e1a..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/ru.json +++ /dev/null @@ -1,320 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Espertus", - "MS", - "Okras", - "RedFox", - "Mailman" - ] - }, - "VARIABLES_DEFAULT_NAME": "элемент", - "TODAY": "Сегодня", - "DUPLICATE_BLOCK": "Скопировать", - "ADD_COMMENT": "Добавить комментарий", - "REMOVE_COMMENT": "Удалить комментарий", - "EXTERNAL_INPUTS": "Вставки снаружи", - "INLINE_INPUTS": "Вставки внутри", - "DELETE_BLOCK": "Удалить блок", - "DELETE_X_BLOCKS": "Удалить %1 блоков", - "DELETE_ALL_BLOCKS": "Удалить все блоки (%1)?", - "CLEAN_UP": "Убрать блоки", - "COLLAPSE_BLOCK": "Свернуть блок", - "COLLAPSE_ALL": "Свернуть блоки", - "EXPAND_BLOCK": "Развернуть блок", - "EXPAND_ALL": "Развернуть блоки", - "DISABLE_BLOCK": "Отключить блок", - "ENABLE_BLOCK": "Включить блок", - "HELP": "Справка", - "UNDO": "Отменить", - "REDO": "Повторить", - "CHANGE_VALUE_TITLE": "Измените значение:", - "RENAME_VARIABLE": "Переименовать переменную…", - "RENAME_VARIABLE_TITLE": "Переименовать все переменные '%1' в:", - "NEW_VARIABLE": "Создать переменную…", - "NEW_VARIABLE_TITLE": "Имя новой переменной:", - "VARIABLE_ALREADY_EXISTS": "Переменная с именем '%1' уже существует.", - "DELETE_VARIABLE_CONFIRMATION": "Удалить %1 использований переменной '%2'?", - "DELETE_VARIABLE": "Удалить переменную '%1'", - "COLOUR_PICKER_HELPURL": "https://ru.wikipedia.org/wiki/Цвет", - "COLOUR_PICKER_TOOLTIP": "Выберите цвет из палитры.", - "COLOUR_RANDOM_TITLE": "случайный цвет", - "COLOUR_RANDOM_TOOLTIP": "Выбирает цвет случайным образом.", - "COLOUR_RGB_TITLE": "цвет из", - "COLOUR_RGB_RED": "красного", - "COLOUR_RGB_GREEN": "зелёного", - "COLOUR_RGB_BLUE": "синего", - "COLOUR_RGB_TOOLTIP": "Создаёт цвет с указанной пропорцией красного, зеленого и синего. Все значения должны быть между 0 и 100.", - "COLOUR_BLEND_TITLE": "смешать", - "COLOUR_BLEND_COLOUR1": "цвет 1", - "COLOUR_BLEND_COLOUR2": "цвет 2", - "COLOUR_BLEND_RATIO": "доля цвета 1", - "COLOUR_BLEND_TOOLTIP": "Смешивает два цвета в заданном соотношении (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://ru.wikipedia.org/wiki/Цикл_(программирование)", - "CONTROLS_REPEAT_TITLE": "повторить %1 раз", - "CONTROLS_REPEAT_INPUT_DO": "выполнить", - "CONTROLS_REPEAT_TOOLTIP": "Выполняет некоторые команды несколько раз.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "повторять, пока", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "повторять, пока не", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Пока значение истинно, выполняет команды.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Пока значение ложно, выполняет команды", - "CONTROLS_FOR_TOOLTIP": "Присваивает переменной '%1' значения от начального до конечного с заданным шагом и выполняет указанные команды.", - "CONTROLS_FOR_TITLE": "цикл по %1 от %2 до %3 с шагом %4", - "CONTROLS_FOREACH_TITLE": "для каждого элемента %1 в списке %2", - "CONTROLS_FOREACH_TOOLTIP": "Для каждого элемента в списке, присваивает переменной '%1' значение элемента и выполняет указанные команды.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "выйти из цикла", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "перейти к следующему шагу цикла", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Прерывает этот цикл.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Пропускает остаток цикла и переходит к следующему шагу.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Предупреждение: этот блок может использоваться только внутри цикла.", - "CONTROLS_IF_TOOLTIP_1": "Если условие истинно, выполняет команды.", - "CONTROLS_IF_TOOLTIP_2": "Если условие истинно, выполняет первый блок команд. Иначе выполняется второй блок команд.", - "CONTROLS_IF_TOOLTIP_3": "Если первое условие истинно, то выполняет первый блок команд. Иначе, если второе условие истинно, выполняет второй блок команд.", - "CONTROLS_IF_TOOLTIP_4": "Если первое условие истинно, то выполняет первый блок команд. В противном случае, если второе условие истинно, выполняет второй блок команд. Если ни одно из условий не истинно, выполняет последний блок команд.", - "CONTROLS_IF_MSG_IF": "если", - "CONTROLS_IF_MSG_ELSEIF": "иначе если", - "CONTROLS_IF_MSG_ELSE": "иначе", - "CONTROLS_IF_IF_TOOLTIP": "Добавьте, удалите, переставьте фрагменты для переделки блока \"если\".", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Добавляет условие к блоку \"если\"", - "CONTROLS_IF_ELSE_TOOLTIP": "Добавить заключительный подблок для случая, когда все условия ложны.", - "LOGIC_COMPARE_HELPURL": "https://ru.wikipedia.org/wiki/Неравенство", - "LOGIC_COMPARE_TOOLTIP_EQ": "Возвращает положительное значение, если вводы равны.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Возвращает положительное значение, если вводы не равны.", - "LOGIC_COMPARE_TOOLTIP_LT": "Возвращает положительное значение, если первый ввод меньше второго.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Возвращает значение истина, если первая вставка меньше или равна второй.", - "LOGIC_COMPARE_TOOLTIP_GT": "Возвращает значение истина, если первая вставка больше второй.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Возвращает значение истина, если первая вставка больше или равна второй.", - "LOGIC_OPERATION_TOOLTIP_AND": "Возвращает значение истина, если обе вставки истинны.", - "LOGIC_OPERATION_AND": "и", - "LOGIC_OPERATION_TOOLTIP_OR": "Возвращает значение истина, если хотя бы одна из вставок истинна.", - "LOGIC_OPERATION_OR": "или", - "LOGIC_NEGATE_TITLE": "не %1", - "LOGIC_NEGATE_TOOLTIP": "Возвращает значение истина, если вставка ложна. Возвращает значение ложь, если вставка истинна.", - "LOGIC_BOOLEAN_TRUE": "истина", - "LOGIC_BOOLEAN_FALSE": "ложь", - "LOGIC_BOOLEAN_TOOLTIP": "Возвращает значение истина или ложь.", - "LOGIC_NULL_HELPURL": "https://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "ничто", - "LOGIC_NULL_TOOLTIP": "Возвращает ничто.", - "LOGIC_TERNARY_HELPURL": "https://ru.wikipedia.org/wiki/Тернарная_условная_операция", - "LOGIC_TERNARY_CONDITION": "выбрать по", - "LOGIC_TERNARY_IF_TRUE": "если истина", - "LOGIC_TERNARY_IF_FALSE": "если ложь", - "LOGIC_TERNARY_TOOLTIP": "Проверяет условие выбора. Если условие истинно, возвращает первое значение, в противном случае возвращает второе значение.", - "MATH_NUMBER_HELPURL": "https://ru.wikipedia.org/wiki/Число", - "MATH_NUMBER_TOOLTIP": "Число.", - "MATH_ARITHMETIC_HELPURL": "https://ru.wikipedia.org/wiki/Арифметика", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Возвращает сумму двух чисел.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Возвращает разность двух чисел.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Возвращает произведение двух чисел.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Возвращает частное от деления первого числа на второе.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Возвращает первое число, возведённое в степень второго числа.", - "MATH_SINGLE_HELPURL": "https://ru.wikipedia.org/wiki/Квадратный_корень", - "MATH_SINGLE_OP_ROOT": "квадратный корень", - "MATH_SINGLE_TOOLTIP_ROOT": "Возвращает квадратный корень числа.", - "MATH_SINGLE_OP_ABSOLUTE": "модуль", - "MATH_SINGLE_TOOLTIP_ABS": "Возвращает модуль числа", - "MATH_SINGLE_TOOLTIP_NEG": "Возвращает противоположное число.", - "MATH_SINGLE_TOOLTIP_LN": "Возвращает натуральный логарифм числа.", - "MATH_SINGLE_TOOLTIP_LOG10": "Возвращает десятичный логарифм числа.", - "MATH_SINGLE_TOOLTIP_EXP": "Возвращает е в указанной степени.", - "MATH_SINGLE_TOOLTIP_POW10": "Возвращает 10 в указанной степени.", - "MATH_TRIG_HELPURL": "https://ru.wikipedia.org/wiki/Тригонометрические_функции", - "MATH_TRIG_TOOLTIP_SIN": "Возвращает синус угла в градусах.", - "MATH_TRIG_TOOLTIP_COS": "Возвращает косинус угла в градусах.", - "MATH_TRIG_TOOLTIP_TAN": "Возвращает тангенс угла в градусах.", - "MATH_TRIG_TOOLTIP_ASIN": "Возвращает арксинус (в градусах).", - "MATH_TRIG_TOOLTIP_ACOS": "Возвращает арккосинус (в градусах).", - "MATH_TRIG_TOOLTIP_ATAN": "Возвращает арктангенс (в градусах)", - "MATH_CONSTANT_HELPURL": "https://ru.wikipedia.org/wiki/Математическая_константа", - "MATH_CONSTANT_TOOLTIP": "Возвращает одну из распространённых констант: π (3.141...), e (2.718...), φ (1.618...), sqrt(2) (1.414...), sqrt(½) (0.707...) или ∞ (бесконечность).", - "MATH_IS_EVEN": "чётное", - "MATH_IS_ODD": "нечётное", - "MATH_IS_PRIME": "простое", - "MATH_IS_WHOLE": "целое", - "MATH_IS_POSITIVE": "положительное", - "MATH_IS_NEGATIVE": "отрицательное", - "MATH_IS_DIVISIBLE_BY": "делится на", - "MATH_IS_TOOLTIP": "Проверяет, является ли число чётным, нечётным, простым, целым, положительным, отрицательным или оно кратно определённому числу. Возвращает значение истина или ложь.", - "MATH_CHANGE_HELPURL": "https://ru.wikipedia.org/wiki/%D0%98%D0%B4%D0%B8%D0%BE%D0%BC%D0%B0_%28%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%29#.D0.98.D0.BD.D0.BA.D1.80.D0.B5.D0.BC.D0.B5.D0.BD.D1.82", - "MATH_CHANGE_TITLE": "увеличить %1 на %2", - "MATH_CHANGE_TOOLTIP": "Добавляет число к переменной '%1'.", - "MATH_ROUND_HELPURL": "https://ru.wikipedia.org/wiki/Округление", - "MATH_ROUND_TOOLTIP": "Округляет число до большего или меньшего.", - "MATH_ROUND_OPERATOR_ROUND": "округлить", - "MATH_ROUND_OPERATOR_ROUNDUP": "округлить к большему", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "округлить к меньшему", - "MATH_ONLIST_OPERATOR_SUM": "сумма списка", - "MATH_ONLIST_TOOLTIP_SUM": "Возвращает сумму всех чисел в списке.", - "MATH_ONLIST_OPERATOR_MIN": "наименьшее в списке", - "MATH_ONLIST_TOOLTIP_MIN": "Возвращает наименьшее число списка.", - "MATH_ONLIST_OPERATOR_MAX": "наибольшее в списке", - "MATH_ONLIST_TOOLTIP_MAX": "Возвращает наибольшее число списка.", - "MATH_ONLIST_OPERATOR_AVERAGE": "среднее арифметическое списка", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Возвращает среднее арифметическое списка.", - "MATH_ONLIST_OPERATOR_MEDIAN": "медиана списка", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Возвращает медиану списка.", - "MATH_ONLIST_OPERATOR_MODE": "моды списка", - "MATH_ONLIST_TOOLTIP_MODE": "Возвращает список наиболее часто встречающихся элементов списка.", - "MATH_ONLIST_OPERATOR_STD_DEV": "стандартное отклонение списка", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Возвращает стандартное отклонение списка.", - "MATH_ONLIST_OPERATOR_RANDOM": "случайный элемент списка", - "MATH_ONLIST_TOOLTIP_RANDOM": "Возвращает случайный элемент списка.", - "MATH_MODULO_HELPURL": "https://ru.wikipedia.org/wiki/Деление_с_остатком", - "MATH_MODULO_TITLE": "остаток от %1 : %2", - "MATH_MODULO_TOOLTIP": "Возвращает остаток от деления двух чисел.", - "MATH_CONSTRAIN_TITLE": "ограничить %1 снизу %2 сверху %3", - "MATH_CONSTRAIN_TOOLTIP": "Ограничивает число нижней и верхней границами (включительно).", - "MATH_RANDOM_INT_HELPURL": "https://ru.wikipedia.org/wiki/Генератор_псевдослучайных_чисел", - "MATH_RANDOM_INT_TITLE": "случайное целое число от %1 для %2", - "MATH_RANDOM_INT_TOOLTIP": "Возвращает случайное число между двумя заданными пределами (включая и их).", - "MATH_RANDOM_FLOAT_HELPURL": "https://ru.wikipedia.org/wiki/Генератор_псевдослучайных_чисел", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "случайное число от 0 (включительно) до 1", - "MATH_RANDOM_FLOAT_TOOLTIP": "Возвращает случайное число от 0.0 (включительно) до 1.0.", - "TEXT_TEXT_HELPURL": "https://ru.wikipedia.org/wiki/Строковый_тип", - "TEXT_TEXT_TOOLTIP": "Буква, слово или строка текста.", - "TEXT_JOIN_TITLE_CREATEWITH": "создать текст из", - "TEXT_JOIN_TOOLTIP": "Создаёт фрагмент текста, объединяя любое число элементов", - "TEXT_CREATE_JOIN_TITLE_JOIN": "соединить", - "TEXT_CREATE_JOIN_TOOLTIP": "Добавьте, удалите, переставьте фрагменты для переделки текстового блока.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Добавить элемент к тексту.", - "TEXT_APPEND_TO": "к", - "TEXT_APPEND_APPENDTEXT": "добавить текст", - "TEXT_APPEND_TOOLTIP": "Добавить текст к переменной «%1».", - "TEXT_LENGTH_TITLE": "длина %1", - "TEXT_LENGTH_TOOLTIP": "Возвращает число символов (включая пробелы) в заданном тексте.", - "TEXT_ISEMPTY_TITLE": "%1 пуст", - "TEXT_ISEMPTY_TOOLTIP": "Возвращает значение истина, если предоставленный текст пуст.", - "TEXT_INDEXOF_TOOLTIP": "Возвращает номер позиции первого/последнего вхождения первого текста во втором. Возвращает %1, если текст не найден.", - "TEXT_INDEXOF_INPUT_INTEXT": "в тексте", - "TEXT_INDEXOF_OPERATOR_FIRST": "найти первое вхождение текста", - "TEXT_INDEXOF_OPERATOR_LAST": "найти последнее вхождение текста", - "TEXT_CHARAT_INPUT_INTEXT": "в тексте", - "TEXT_CHARAT_FROM_START": "взять букву №", - "TEXT_CHARAT_FROM_END": "взять букву № с конца", - "TEXT_CHARAT_FIRST": "взять первую букву", - "TEXT_CHARAT_LAST": "взять последнюю букву", - "TEXT_CHARAT_RANDOM": "взять случайную букву", - "TEXT_CHARAT_TOOLTIP": "Возвращает букву в указанной позиции.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Возвращает указанную часть текста.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "в тексте", - "TEXT_GET_SUBSTRING_START_FROM_START": "взять подстроку с буквы №", - "TEXT_GET_SUBSTRING_START_FROM_END": "взять подстроку с буквы № с конца", - "TEXT_GET_SUBSTRING_START_FIRST": "взять подстроку с первой буквы", - "TEXT_GET_SUBSTRING_END_FROM_START": "по букву №", - "TEXT_GET_SUBSTRING_END_FROM_END": "по букву № с конца", - "TEXT_GET_SUBSTRING_END_LAST": "по последнюю букву", - "TEXT_CHANGECASE_TOOLTIP": "Возвращает копию текста с ЗАГЛАВНЫМИ или строчными буквами.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "в ЗАГЛАВНЫЕ БУКВЫ", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "в строчные буквы", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "в Заглавные Начальные Буквы", - "TEXT_TRIM_TOOLTIP": "Возвращает копию текста с пробелами, удалеными с одного или обоих концов.", - "TEXT_TRIM_OPERATOR_BOTH": "обрезать пробелы с двух сторон", - "TEXT_TRIM_OPERATOR_LEFT": "обрезать пробелы слева", - "TEXT_TRIM_OPERATOR_RIGHT": "обрезать пробелы справа", - "TEXT_PRINT_TITLE": "напечатать %1", - "TEXT_PRINT_TOOLTIP": "Печатает текст, число или другой объект.", - "TEXT_PROMPT_TYPE_TEXT": "запросить текст с подсказкой", - "TEXT_PROMPT_TYPE_NUMBER": "запросить число с подсказкой", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Запросить у пользователя число.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Запросить у пользователя текст.", - "LISTS_CREATE_EMPTY_TITLE": "создать пустой список", - "LISTS_CREATE_EMPTY_TOOLTIP": "Возвращает список длины 0, не содержащий данных", - "LISTS_CREATE_WITH_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_CREATE_WITH_TOOLTIP": "Создаёт список с любым числом элементов.", - "LISTS_CREATE_WITH_INPUT_WITH": "создать список из", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "список", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Добавьте, удалите, переставьте элементы для переделки блока списка.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Добавляет элемент к списку.", - "LISTS_REPEAT_TOOLTIP": "Создаёт список, состоящий из заданного числа копий элемента.", - "LISTS_REPEAT_TITLE": "создать список из элемента %1, повторяющегося %2 раз", - "LISTS_LENGTH_TITLE": "длина %1", - "LISTS_LENGTH_TOOLTIP": "Возвращает длину списка.", - "LISTS_ISEMPTY_TITLE": "%1 пуст", - "LISTS_ISEMPTY_TOOLTIP": "Возвращает значение истина, если список пуст.", - "LISTS_INLIST": "в списке", - "LISTS_INDEX_OF_FIRST": "найти первое вхождение элемента", - "LISTS_INDEX_OF_LAST": "найти последнее вхождение элемента", - "LISTS_INDEX_OF_TOOLTIP": "Возвращает номер позиции первого/последнего вхождения элемента в списке. Возвращает %1, если элемент не найден.", - "LISTS_GET_INDEX_GET": "взять", - "LISTS_GET_INDEX_GET_REMOVE": "взять и удалить", - "LISTS_GET_INDEX_REMOVE": "удалить", - "LISTS_GET_INDEX_FROM_END": "№ с конца", - "LISTS_GET_INDEX_FIRST": "первый", - "LISTS_GET_INDEX_LAST": "последний", - "LISTS_GET_INDEX_RANDOM": "произвольный", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 - первый элемент.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 - последний элемент.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Возвращает элемент в указанной позиции списка.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Возвращает первый элемент списка.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Возвращает последний элемент списка.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Возвращает случайный элемент списка.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Удаляет и возвращает элемент в указанной позиции списка.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Удаляет и возвращает первый элемент списка.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Удаляет и возвращает последний элемент списка.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Удаляет и возвращает случайный элемент списка.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Удаляет элемент в указанной позиции списка.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Удаляет первый элемент списка.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Удаляет последний элемент списка.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Удаляет случайный элемент списка.", - "LISTS_SET_INDEX_SET": "присвоить", - "LISTS_SET_INDEX_INSERT": "вставить в", - "LISTS_SET_INDEX_INPUT_TO": "=", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Присваивает значение элементу в указанной позиции списка.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Присваивает значение первому элементу списка.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Присваивает значение последнему элементу списка.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Присваивает значение случайному элементу списка.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Вставляет элемент в указанной позиции списка.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Вставляет элемент в начало списка.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Добавляет элемент в конец списка.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Вставляет элемент в случайное место в списке.", - "LISTS_GET_SUBLIST_START_FROM_START": "взять подсписок с №", - "LISTS_GET_SUBLIST_START_FROM_END": "взять подсписок с № с конца", - "LISTS_GET_SUBLIST_START_FIRST": "взять подсписок с первого", - "LISTS_GET_SUBLIST_END_FROM_START": "по №", - "LISTS_GET_SUBLIST_END_FROM_END": "по № с конца", - "LISTS_GET_SUBLIST_END_LAST": "по последний", - "LISTS_GET_SUBLIST_TOOLTIP": "Создаёт копию указанной части списка.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "сортировать %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Сортировать копию списка.", - "LISTS_SORT_ORDER_ASCENDING": "по возрастанию", - "LISTS_SORT_ORDER_DESCENDING": "по убыванию", - "LISTS_SORT_TYPE_NUMERIC": "числовая", - "LISTS_SORT_TYPE_TEXT": "по алфавиту", - "LISTS_SORT_TYPE_IGNORECASE": "по алфавиту, без учёта регистра", - "LISTS_SPLIT_HELPURL": "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists", - "LISTS_SPLIT_LIST_FROM_TEXT": "сделать список из текста", - "LISTS_SPLIT_TEXT_FROM_LIST": "собрать текст из списка", - "LISTS_SPLIT_WITH_DELIMITER": "с разделителем", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Разбивает текст в список текстов, по разделителям.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Соединяет сптсок текстов в один текст с разделителями.", - "VARIABLES_GET_TOOLTIP": "Возвращает значение этой переменной.", - "VARIABLES_GET_CREATE_SET": "Создать блок \"присвоить\" для %1", - "VARIABLES_SET": "присвоить %1 = %2", - "VARIABLES_SET_TOOLTIP": "Присваивает переменной значение вставки.", - "VARIABLES_SET_CREATE_GET": "Создать вставку %1", - "PROCEDURES_DEFNORETURN_TITLE": "чтобы", - "PROCEDURES_DEFNORETURN_PROCEDURE": "выполнить что-то", - "PROCEDURES_BEFORE_PARAMS": "с:", - "PROCEDURES_CALL_BEFORE_PARAMS": "с:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Создаёт процедуру, не возвращающую значение.", - "PROCEDURES_DEFNORETURN_COMMENT": "Опишите эту функцию…", - "PROCEDURES_DEFRETURN_RETURN": "вернуть", - "PROCEDURES_DEFRETURN_TOOLTIP": "Создаёт процедуру, возвращающую значение.", - "PROCEDURES_ALLOW_STATEMENTS": "разрешить операторы", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Предупреждение: эта функция имеет повторяющиеся параметры.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://ru.wikipedia.org/wiki/Функция_%28программирование%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Исполняет определённую пользователем процедуру '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "https://ru.wikipedia.org/wiki/Функция_%28программирование%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Исполняет определённую пользователем процедуру '%1' и возвращает вычисленное значение.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "параметры", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Добавить, удалить или изменить порядок входных параметров для этой функции.", - "PROCEDURES_MUTATORARG_TITLE": "имя параметра:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Добавить входной параметр в функцию.", - "PROCEDURES_HIGHLIGHT_DEF": "Выделить определение процедуры", - "PROCEDURES_CREATE_DO": "Создать вызов '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Если первое значение истинно, возвращает второе значение.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Предупреждение: Этот блок может использоваться только внутри определения функции." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/sc.json b/backend/_pv_1_3_5/static/blockly/msg/json/sc.json deleted file mode 100755 index 12396ece6..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/sc.json +++ /dev/null @@ -1,299 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Via maxima", - "Taxandru", - "Uharteko" - ] - }, - "VARIABLES_DEFAULT_NAME": "item", - "TODAY": "Oe", - "DUPLICATE_BLOCK": "Dùplica", - "ADD_COMMENT": "Agiunghe unu cumentu", - "REMOVE_COMMENT": "Fùlia unu cumentu", - "EXTERNAL_INPUTS": "Intradas esternas", - "INLINE_INPUTS": "Intradas in lìnia", - "DELETE_BLOCK": "Fùlia Blocu", - "DELETE_X_BLOCKS": "Fulia %1 Blocus", - "DELETE_ALL_BLOCKS": "Scancellu su %1 de is brocus?", - "CLEAN_UP": "Lìmpia is brocus", - "COLLAPSE_BLOCK": "Serra e stringi Brocu", - "COLLAPSE_ALL": "Serra e stringi Brocus", - "EXPAND_BLOCK": "Aberi Brocu", - "EXPAND_ALL": "Aberi Brocus", - "DISABLE_BLOCK": "Disabìlita Blocu", - "ENABLE_BLOCK": "Abìlita Blocu", - "HELP": "Agiudu", - "CHANGE_VALUE_TITLE": "Muda valori:", - "RENAME_VARIABLE": "Muda nòmini a variabili...", - "RENAME_VARIABLE_TITLE": "A is variabilis '%1' muda nòmini a:", - "NEW_VARIABLE": "Variabili noa...", - "NEW_VARIABLE_TITLE": "Nòmini de sa variabili noa:", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "Scebera unu colori de sa tauledda.", - "COLOUR_RANDOM_TITLE": "Unu colori a brítiu", - "COLOUR_RANDOM_TOOLTIP": "Scebera unu colori a brítiu.", - "COLOUR_RGB_TITLE": "colora cun", - "COLOUR_RGB_RED": "arrùbiu", - "COLOUR_RGB_GREEN": "birdi", - "COLOUR_RGB_BLUE": "blue", - "COLOUR_RGB_TOOLTIP": "Cuncorda unu colori cun su tanti de arrubiu, birdi, e blue. Totu is valoris depint essi intra 0 e 100.", - "COLOUR_BLEND_TITLE": "mestura", - "COLOUR_BLEND_COLOUR1": "colori 1", - "COLOUR_BLEND_COLOUR2": "colori 2", - "COLOUR_BLEND_RATIO": "raportu", - "COLOUR_BLEND_TOOLTIP": "Amestura duus coloris cun unu raportu (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "repiti %1 bortas", - "CONTROLS_REPEAT_INPUT_DO": "fai", - "CONTROLS_REPEAT_TOOLTIP": "Fait pariga de cumandus prus bortas.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "repiti interis", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "repiti fintzas", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Interis su valori est berus, tandu fai pariga de cumandus.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Interis su valori est frassu, tandu fai pariga de cumandus.", - "CONTROLS_FOR_TOOLTIP": "Fait pigai a sa variàbili \"%1\" i valoris de su primu numeru a s'urtimu, a su passu impostau e fait su brocu.", - "CONTROLS_FOR_TITLE": "po %1 de %2 fintzas %3 a passus de %4", - "CONTROLS_FOREACH_TITLE": "po dònnia item %1 in lista %2", - "CONTROLS_FOREACH_TOOLTIP": "Po dònnia item in sa lista, ponit sa variàbili '%1' pari a s'item, e tandu fait pariga de cumandus.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "sàrtiat a foras de sa lòriga", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "sighit cun su repicu afatànti", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Bessit de sa lòriga.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Sartiat su chi abarrat de sa loriga, e sighit cun su repicu afatànti.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Amonestu: Custu brocu ddu podis ponni sceti aintru de una lòriga.", - "CONTROLS_IF_TOOLTIP_1": "Si su valori est berus, tandu fait pariga de cumandus.", - "CONTROLS_IF_TOOLTIP_2": "Si su valori est berus, tandu fai su primu brocu de is cumandus. Sinuncas, fai su segundu brocu de is cumandus.", - "CONTROLS_IF_TOOLTIP_3": "Si su primu valori est beridadi, tandu fai su primu brocu de is cumandus. Sinuncas, si su segundu valori est beridadi, fai su segundu brocu de is cumandus.", - "CONTROLS_IF_TOOLTIP_4": "Si su primu valori est berus, tandu fai su primu brocu de is cumandus. Sinuncas, si su segundu valori est berus, fai su segundu brocu de is cumandus. Si mancu unu valori est berus, tandu fai s'urtimu brocu de is cumandus.", - "CONTROLS_IF_MSG_IF": "si", - "CONTROLS_IF_MSG_ELSEIF": "sinuncas si", - "CONTROLS_IF_MSG_ELSE": "sinuncas", - "CONTROLS_IF_IF_TOOLTIP": "Aciungi, fùlia, o assenta is partis po torrai a sètiu custu brocu si.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Aciungi una cunditzioni a su brocu si.", - "CONTROLS_IF_ELSE_TOOLTIP": "Aciungi una urtima cunditzioni piga-totu a su brocu si.", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Torrat berus si is inputs funt unu uguali a s'àteru.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Torrat berus si is inputs non funt unu uguali a s'àteru.", - "LOGIC_COMPARE_TOOLTIP_LT": "Torrat berus si su primu input est prus piticu de s'àteru.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Torrat berus si su primu input est prus piticu o uguali a s'àteru.", - "LOGIC_COMPARE_TOOLTIP_GT": "Torrat berus si su primu input est prus mannu de s'àteru.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Torrat berus si su primu input est prus mannu o uguali a s'àteru.", - "LOGIC_OPERATION_TOOLTIP_AND": "Torrat berus si ambos is inputs funt berus.", - "LOGIC_OPERATION_AND": "and", - "LOGIC_OPERATION_TOOLTIP_OR": "Torrat berus si assumancu unu de is inputs est berus.", - "LOGIC_OPERATION_OR": "or", - "LOGIC_NEGATE_TITLE": "non %1", - "LOGIC_NEGATE_TOOLTIP": "Torrat berus si s'input est frassu. Torrat frassu si s'input est berus.", - "LOGIC_BOOLEAN_TRUE": "berus", - "LOGIC_BOOLEAN_FALSE": "frassu", - "LOGIC_BOOLEAN_TOOLTIP": "Torrat berus o frassu.", - "LOGIC_NULL": "null", - "LOGIC_NULL_TOOLTIP": "Torrat null.", - "LOGIC_TERNARY_CONDITION": "cumpròa", - "LOGIC_TERNARY_IF_TRUE": "si berus", - "LOGIC_TERNARY_IF_FALSE": "si frassu", - "LOGIC_TERNARY_TOOLTIP": "‎Cumproa sa cunditzioni in 'cumproa'. Si sa cunditzioni est berus, torrat su valori 'si berus'; sinuncas torrat su valori 'si frassu'.", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "Unu numeru", - "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/Arithmetic", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Torrat sa summa de is duus nùmerus.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Torrat sa diferèntzia de is duus nùmerus.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Torrat su produtu de is duus nùmerus.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Torrat su cuotzienti de is duus nùmerus.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Torrat su primu numeru artziau a sa potenza de su segundu nùmeru.", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "arraxina cuadra", - "MATH_SINGLE_TOOLTIP_ROOT": "Torrat s'arraxina cuadra de unu numeru.", - "MATH_SINGLE_OP_ABSOLUTE": "assolutu", - "MATH_SINGLE_TOOLTIP_ABS": "Torrat su valori assolútu de unu numeru.", - "MATH_SINGLE_TOOLTIP_NEG": "Torrat su valori negau de unu numeru.", - "MATH_SINGLE_TOOLTIP_LN": "Torrat su logaritmu naturali de unu numeru.", - "MATH_SINGLE_TOOLTIP_LOG10": "Torrat su logaritmu a basi 10 de unu numeru.", - "MATH_SINGLE_TOOLTIP_EXP": "Torrat (e) a sa potèntzia de unu numeru.", - "MATH_SINGLE_TOOLTIP_POW10": "Torrat (10) a sa potèntzia de unu numeru.", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "Torrat su sinu de unu gradu (no radianti).", - "MATH_TRIG_TOOLTIP_COS": "Torrat su cosinu de unu gradu (no radianti).", - "MATH_TRIG_TOOLTIP_TAN": "Torrat sa tangenti de unu gradu (no radianti).", - "MATH_TRIG_TOOLTIP_ASIN": "Torrat su arcsinu de unu numeru.", - "MATH_TRIG_TOOLTIP_ACOS": "Torrat su arccosinu de unu numeru.", - "MATH_TRIG_TOOLTIP_ATAN": "Torrat su arctangenti de unu numeru.", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "Torrat una de is costantis comunas: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), o ∞ (infiniu).", - "MATH_IS_EVEN": "est paris", - "MATH_IS_ODD": "est dísparu", - "MATH_IS_PRIME": "est primu", - "MATH_IS_WHOLE": "est intreu", - "MATH_IS_POSITIVE": "est positivu", - "MATH_IS_NEGATIVE": "est negativu", - "MATH_IS_DIVISIBLE_BY": "fait a ddu dividi po", - "MATH_IS_TOOLTIP": "Cumprova si unu numeru est paris, dìsparis, primu, intreu, positivu, negativu o si fait a ddu dividi po unu numeru giau. Torrat berus o frassu.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "muda %1 de %2", - "MATH_CHANGE_TOOLTIP": "Aciungi unu numeru a sa variabili '%1'.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Arretunda unu numeru faci a susu o faci a bàsciu.", - "MATH_ROUND_OPERATOR_ROUND": "arretunda", - "MATH_ROUND_OPERATOR_ROUNDUP": "Arretunda faci a susu", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "arretunda faci a bàsciu.", - "MATH_ONLIST_OPERATOR_SUM": "suma sa lista", - "MATH_ONLIST_TOOLTIP_SUM": "Torrat sa suma de totu is numerus de sa lista.", - "MATH_ONLIST_OPERATOR_MIN": "minimu de sa lista", - "MATH_ONLIST_TOOLTIP_MIN": "Torrat su numeru prus piticu de sa lista.", - "MATH_ONLIST_OPERATOR_MAX": "massimu de sa lista", - "MATH_ONLIST_TOOLTIP_MAX": "Torrat su numeru prus mannu de sa lista", - "MATH_ONLIST_OPERATOR_AVERAGE": "mèdia de sa lista", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Torrat sa mèdia (aritimètica) de is valoris de sa lista.", - "MATH_ONLIST_OPERATOR_MEDIAN": "medianu de sa lista", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Torrat su numeru medianu de sa lista.", - "MATH_ONLIST_OPERATOR_MODE": "modas de sa lista", - "MATH_ONLIST_TOOLTIP_MODE": "Torrat una lista de is itams prus frecuentis de sa lista.", - "MATH_ONLIST_OPERATOR_STD_DEV": "deviadura standard de sa lista", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Torrat sa deviadura standard de sa lista.", - "MATH_ONLIST_OPERATOR_RANDOM": "unu item a brìtiu de sa lista", - "MATH_ONLIST_TOOLTIP_RANDOM": "Torrat unu item a brìtiu de sa lista.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "arrestu de %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Torrat s'arrestu de sa divisioni de duus numerus.", - "MATH_CONSTRAIN_TITLE": "custringi %1 de %2 a %3", - "MATH_CONSTRAIN_TOOLTIP": "Custringi unu numeru aintru de is liminaxus giaus (cumprendius).", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "numeru intreu a brítiu de %1 a %2", - "MATH_RANDOM_INT_TOOLTIP": "Torrat unu numeru intreu a brìtiu intra duus nùmerus giaus (cumpresus).", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "una fratzioni a brìtiu", - "MATH_RANDOM_FLOAT_TOOLTIP": "Torrat una fratzioni a brìtiu intra 0.0 (cumpresu) e 1.0 (bogau).", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "Una lìtera, paràula, o linia de testu.", - "TEXT_JOIN_TITLE_CREATEWITH": "scri testu cun", - "TEXT_JOIN_TOOLTIP": "Fait unu testu ponendi a pari parigas de items.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "auni a pari", - "TEXT_CREATE_JOIN_TOOLTIP": "Aciungi, fùlia, o assenta is partis po torrai a sètiu custu brocu de testu.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Acciungi unu item a su testu.", - "TEXT_APPEND_TO": "a", - "TEXT_APPEND_APPENDTEXT": "acciungi su testu", - "TEXT_APPEND_TOOLTIP": "Aciungit testu a sa variàbili '%1'.", - "TEXT_LENGTH_TITLE": "longària de %1", - "TEXT_LENGTH_TOOLTIP": "Torrat su numeru de lìteras (cun is spàtzius) in su testu giau.", - "TEXT_ISEMPTY_TITLE": "%1 est buidu", - "TEXT_ISEMPTY_TOOLTIP": "Torrat berus si su testu giau est buidu.", - "TEXT_INDEXOF_TOOLTIP": "Torrat s'indixi de sa primu/urtima ocasioni de su primu testu in su segundu testu. Torrat %1 si su testu no ddu agatat.", - "TEXT_INDEXOF_INPUT_INTEXT": "in su testu", - "TEXT_INDEXOF_OPERATOR_FIRST": "circa prima ocasioni de su testu", - "TEXT_INDEXOF_OPERATOR_LAST": "circa urtima ocasioni de su testu", - "TEXT_CHARAT_INPUT_INTEXT": "in su testu", - "TEXT_CHARAT_FROM_START": "piga sa lìtera #", - "TEXT_CHARAT_FROM_END": "piga sa lìtera # de sa fini", - "TEXT_CHARAT_FIRST": "piga sa prima lìtera", - "TEXT_CHARAT_LAST": "piga s'urtima lìtera", - "TEXT_CHARAT_RANDOM": "piga una lìtera a brìtiu", - "TEXT_CHARAT_TOOLTIP": "Torrat sa lìtera de su postu giau.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Torrat su testu inditau.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "in su testu", - "TEXT_GET_SUBSTRING_START_FROM_START": "piga suta-stringa de sa lìtera #", - "TEXT_GET_SUBSTRING_START_FROM_END": "piga suta-stringa de sa lìtera # fintzas a fini", - "TEXT_GET_SUBSTRING_START_FIRST": "piga suta-stringa de sa primu lìtera", - "TEXT_GET_SUBSTRING_END_FROM_START": "a sa lìtera #", - "TEXT_GET_SUBSTRING_END_FROM_END": "a sa lìtera # de sa fini", - "TEXT_GET_SUBSTRING_END_LAST": "a s'urtima lìtera", - "TEXT_CHANGECASE_TOOLTIP": "Torrat una copia de su testu inditau mudendi mauschínu/minúdu.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "a mauschínu", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "a minúdu", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "cun Primu lìtera a Mauschínu", - "TEXT_TRIM_TOOLTIP": "Torrat una copia de su testu bogaus is spàtzius de unu o de ambus is càbudus.", - "TEXT_TRIM_OPERATOR_BOTH": "bogat spàtzius de ambus càbudus de", - "TEXT_TRIM_OPERATOR_LEFT": "bogat spàtzius de su càbudu de manca de", - "TEXT_TRIM_OPERATOR_RIGHT": "bogat spàtzius de su càbudu de dereta de", - "TEXT_PRINT_TITLE": "scri %1", - "TEXT_PRINT_TOOLTIP": "Scri su testu, numeru o àteru valori.", - "TEXT_PROMPT_TYPE_TEXT": "pregonta po su testu", - "TEXT_PROMPT_TYPE_NUMBER": "pregonta po unu numeru", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Pregonta unu nùmeru a s'impitadore.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Pregonta testu a s'impitadore.", - "LISTS_CREATE_EMPTY_TITLE": "fait una lista buida", - "LISTS_CREATE_EMPTY_TOOLTIP": "Torrat una lista, de longària 0, chena records de datus.", - "LISTS_CREATE_WITH_TOOLTIP": "Fait una lista cun calisiollat numeru de items.", - "LISTS_CREATE_WITH_INPUT_WITH": "fait una lista cun", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "lista", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Aciungi, fùlia, o assenta is partis po torrai a sètiu custu brocu lista.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Acciungi unu item a sa lista.", - "LISTS_REPEAT_TOOLTIP": "Fait una lista cun unu numeru giau repitiu su tanti de is bortas inditadas.", - "LISTS_REPEAT_TITLE": "fait una lista cun item %1 repitiu %2 bortas", - "LISTS_LENGTH_TITLE": "longària de %1", - "LISTS_LENGTH_TOOLTIP": "Torrat sa longària de una lista.", - "LISTS_ISEMPTY_TITLE": "%1 est buidu", - "LISTS_ISEMPTY_TOOLTIP": "Torrat berus si sa lista est buida.", - "LISTS_INLIST": "in lista", - "LISTS_INDEX_OF_FIRST": "circa prima ocasioni de s'item", - "LISTS_INDEX_OF_LAST": "circa urtima ocasioni de s'item", - "LISTS_INDEX_OF_TOOLTIP": "Torrat s'indixi de sa primu/urtima ocasioni de s'item in sa lista. Torrat %1 si s'item non s'agatat.", - "LISTS_GET_INDEX_GET": "piga", - "LISTS_GET_INDEX_GET_REMOVE": "piga e fùlia", - "LISTS_GET_INDEX_REMOVE": "fùlia", - "LISTS_GET_INDEX_FROM_END": "# de sa fini", - "LISTS_GET_INDEX_FIRST": "primu", - "LISTS_GET_INDEX_LAST": "urtimu", - "LISTS_GET_INDEX_RANDOM": "a brìtiu (random)", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 est po su primu elementu.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 est po s'urtimu elementu.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Torrat s'elementu de su postu inditau de una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Torrat su primu elementu de una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Torrat s'urtimu elementu de una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Torrat un'elementu a brìtiu de una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Fùliat e torrat s'elementu de su postu inditau de una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Fùliat e torrat su primu elementu de una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Fùliat e torrat s'urtimu elementu de una lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Fùliat e torrat un'elementu a brìtiu de una lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Fùliat s'elementu de su postu inditau de una lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Fùliat su primu elementu de una lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Fùliat s'urtimu elementu de una lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Fùliat unu elementu a brìtiu de una lista.", - "LISTS_SET_INDEX_SET": "imposta", - "LISTS_SET_INDEX_INSERT": "inserta a", - "LISTS_SET_INDEX_INPUT_TO": "a", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Impostat s'elementu in su postu inditau de una lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Impostat su primu elementu in una lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Impostat s'urtimu elementu in una lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Impostat unu elementu random in una lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Insertat s'elementu in su postu inditau in una lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Insertat s'elementu a su cumintzu de sa lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Aciungit s'elementu a sa fini de sa lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Aciungit s'elementu a brítiu in sa lista.", - "LISTS_GET_SUBLIST_START_FROM_START": "bogandi suta-lista de #", - "LISTS_GET_SUBLIST_START_FROM_END": "bogandi suta-lista de # de sa fini.", - "LISTS_GET_SUBLIST_START_FIRST": "bogandi suta-lista de su primu", - "LISTS_GET_SUBLIST_END_FROM_START": "fintzas a #", - "LISTS_GET_SUBLIST_END_FROM_END": "a # de sa fini", - "LISTS_GET_SUBLIST_END_LAST": "a s'urtimu", - "LISTS_GET_SUBLIST_TOOLTIP": "Fait una copia de sa parti inditada de sa lista.", - "LISTS_SPLIT_LIST_FROM_TEXT": "fai una lista de unu testu", - "LISTS_SPLIT_TEXT_FROM_LIST": "fai unu testu de una lista", - "LISTS_SPLIT_WITH_DELIMITER": "cun separadori", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Dividi su testu in un'elencu de testus, firmendi po dònnia separadori.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Auni una lista de testus in d-unu sceti, ponendi separadoris.", - "VARIABLES_GET_TOOLTIP": "Torrat su valori de custa variabili.", - "VARIABLES_GET_CREATE_SET": "Fait 'imposta %1'", - "VARIABLES_SET": "imposta %1 a %2", - "VARIABLES_SET_TOOLTIP": "Imposta custa variabili uguali a s'input.", - "VARIABLES_SET_CREATE_GET": "Fait 'piga %1'", - "PROCEDURES_DEFNORETURN_TITLE": "po", - "PROCEDURES_DEFNORETURN_PROCEDURE": "fait calincuna cosa", - "PROCEDURES_BEFORE_PARAMS": "con:", - "PROCEDURES_CALL_BEFORE_PARAMS": "cun", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Fait una funtzioni chena output.", - "PROCEDURES_DEFRETURN_RETURN": "torrat", - "PROCEDURES_DEFRETURN_TOOLTIP": "Fait una funtzioni cun output.", - "PROCEDURES_ALLOW_STATEMENTS": "permiti decraratzionis", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Amonestu: Custa funtzioni tenit parametrus duplicaus.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Arròllia sa funtzione '%1' cuncordada dae s'impitadore.", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Arròllia sa funtzione '%1' cuncordada dae s'impitadore e imprea s'output suu.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "inputs", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Aciungi, fùlia, o assenta is inputs a custa funtzioni.", - "PROCEDURES_MUTATORARG_TITLE": "nomini input:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Aciungi un input a sa funtzioni.", - "PROCEDURES_HIGHLIGHT_DEF": "Marca sa definitzioni de funtzioni.", - "PROCEDURES_CREATE_DO": "Ingenerau'%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Si unu valori est berus, tandu torrat unu segundu valori.", - "PROCEDURES_IFRETURN_WARNING": "Amonestu: Custu brocu ddu podis ponni sceti aintru de una funtzioni." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/sd.json b/backend/_pv_1_3_5/static/blockly/msg/json/sd.json deleted file mode 100755 index 47bf7b86c..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/sd.json +++ /dev/null @@ -1,126 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Aursani", - "Mehtab ahmed" - ] - }, - "VARIABLES_DEFAULT_NAME": "اسم", - "TODAY": "اڄ", - "DUPLICATE_BLOCK": "نقل", - "ADD_COMMENT": "تاثرات ڏيو", - "REMOVE_COMMENT": "تاثرات مِٽايو", - "EXTERNAL_INPUTS": "خارجي ڄاڻ", - "DELETE_BLOCK": "بلاڪ ڊاهيو", - "DELETE_X_BLOCKS": "1٪ بلاڪ ڊاهيو", - "CLEAN_UP": "بندشون هٽايو", - "COLLAPSE_BLOCK": "بلاڪ ڍڪيو", - "COLLAPSE_ALL": "بلاڪَ ڍڪيو", - "EXPAND_BLOCK": "بلاڪ نمايو", - "EXPAND_ALL": "بلاڪَ نمايو", - "DISABLE_BLOCK": "بلاڪ کي غيرفعال بڻايو", - "ENABLE_BLOCK": "بلاڪ کي فعال بڻايو", - "HELP": "مدد", - "CHANGE_VALUE_TITLE": "قدر بدلايو", - "RENAME_VARIABLE": "ڦرڻي کي نئون نالو ڏيو...", - "NEW_VARIABLE": "نئون ڦرڻو...", - "NEW_VARIABLE_TITLE": "ڦرڻي جو نئون نالو:", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "رنگ دٻيءَ مان رنگ چونڊيو.", - "COLOUR_RANDOM_TITLE": "بلا ترتيب رنگ", - "COLOUR_RANDOM_TOOLTIP": "ڪو بہ ‌ڃڳ چونڊيو.", - "COLOUR_RGB_TITLE": "سان رڱيو", - "COLOUR_RGB_RED": "ڳاڙهو", - "COLOUR_RGB_GREEN": "سائو", - "COLOUR_RGB_BLUE": "نيرو", - "COLOUR_RGB_TOOLTIP": "ڳاڙهي، سائي، ۽ نيري جو مقدار ڄاڻائي گھربل رنگ ٺاهيو. سمورا قدر 0 ۽ 100 جي وچ ۾ هجن.", - "COLOUR_BLEND_COLOUR1": "رنگ 1", - "COLOUR_BLEND_COLOUR2": "رنگ 2", - "COLOUR_BLEND_RATIO": "تناسب", - "COLOUR_BLEND_TOOLTIP": "ڄاڻايل تناسب سان ٻہ رنگ پاڻ ۾ ملايو (0.0-1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "1٪ ڀيرا ورجايو", - "CONTROLS_REPEAT_INPUT_DO": "ڪريو", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "ورجايو جڏهن", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "ورجايو جيستائين", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "چڪر مان ٻاهر نڪرو", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "چڪر جاري رکندر نئين ڦيري پايو", - "CONTROLS_IF_MSG_IF": "جيڪڏهن", - "CONTROLS_IF_MSG_ELSEIF": "نہ تہ جي", - "CONTROLS_IF_MSG_ELSE": "نہ تہ", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "جيڪڏهن ٻئي ان پُٽس برابر آهن تہ درست وراڻيو", - "LOGIC_COMPARE_TOOLTIP_NEQ": "جيڪڏهن ٻئي ان پُٽس اڻ برابر آهن تہ درست وراڻيو", - "LOGIC_COMPARE_TOOLTIP_LT": "جيڪڏهن پهريون ان پُٽ ٻين ان پُٽ کان ننڍو آهي تہ درست وراڻيو", - "LOGIC_COMPARE_TOOLTIP_LTE": "جيڪڏهن پهريون ان پُٽ ٻين ان پُٽ کان ننڍو آهي يا ٻئي برابر آهن تہ درست وراڻيو", - "LOGIC_COMPARE_TOOLTIP_GT": "جيڪڏهن پهريون ان پُٽ ٻين ان پُٽ کان وڏو آهي تہ درست وراڻيو.", - "LOGIC_COMPARE_TOOLTIP_GTE": "جيڪڏهن پهريون ان پُٽ ٻين ان پُٽ کان وڏو آهي يا ٻئي برابر آهن تہ درست وراڻيو.", - "LOGIC_OPERATION_TOOLTIP_AND": "جيڪڏهن ٻئي ان پُٽ درست آهن تہ درست وراڻيو.", - "LOGIC_OPERATION_AND": "۽", - "LOGIC_OPERATION_TOOLTIP_OR": "جيڪڏهن ٻنهي ان پُٽس مان ڪو هڪ بہ درست آهي تہ درست وراڻيو.", - "LOGIC_OPERATION_OR": "يا", - "LOGIC_NEGATE_TITLE": "نڪي %1", - "LOGIC_NEGATE_TOOLTIP": "ان پُٽ غير درست آهي تہ درست وراڻيو. ان پُٽ درست آهي تہ غير درست وراڻيو.", - "LOGIC_BOOLEAN_TRUE": "سچ", - "LOGIC_BOOLEAN_FALSE": "ڪُوڙ", - "LOGIC_BOOLEAN_TOOLTIP": "درست يا غير درست وراڻي ٿو.", - "LOGIC_TERNARY_IF_TRUE": "جيڪڏهن سچو", - "LOGIC_TERNARY_IF_FALSE": "جيڪڏهن ڪوڙو", - "MATH_NUMBER_TOOLTIP": "ڪو انگ.", - "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/Arithmetic", - "MATH_ARITHMETIC_TOOLTIP_ADD": "ٻن انگن جي جوڙ اپت ڏيو.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "ٻنهي انگن جو تفاوت ڏيو.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "ٻنهي انگن جي ضرب اُپت ڏيو.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "ٻنهي انگن جي ونڊ ڏيو.", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/ٻيون مول", - "MATH_SINGLE_OP_ROOT": "ٻيون مول", - "MATH_SINGLE_TOOLTIP_ROOT": "ڪنهن انگ جو ٻيون مول ڄاڻايو.", - "MATH_SINGLE_OP_ABSOLUTE": "ٺپ", - "MATH_SINGLE_TOOLTIP_NEG": "ڪنهن انگ جو ڪاٽو ڄاڻايو.", - "MATH_SINGLE_TOOLTIP_LN": "ڪنهن انگ جو قدرتي لاگ ڄاڻايو.", - "MATH_SINGLE_TOOLTIP_LOG10": "ڪنهن انگ جو 10 بنيادي لاگ ڄاڻايو.", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/ٽڪنڊور ڪاڄ", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/رياضياتي استقلال", - "MATH_IS_EVEN": "ٻڌي آهي", - "MATH_IS_ODD": "اِڪي آهي", - "MATH_IS_PRIME": "مفرد آهي", - "MATH_IS_WHOLE": "سڄو آهي", - "MATH_IS_POSITIVE": "واڌو آهي", - "MATH_IS_NEGATIVE": "ڪاٽو آهي", - "MATH_IS_DIVISIBLE_BY": "سان ونڊجندڙ آهي", - "MATH_CHANGE_TITLE": "%1 کي %2 سان مَٽايو", - "MATH_ONLIST_OPERATOR_MIN": "لسٽ جو ننڍي ۾ ننڍو قدر", - "MATH_ONLIST_TOOLTIP_MIN": "لسٽ ۾ ننڍي کان ننڍو قدر ڄاڻايو.", - "MATH_ONLIST_OPERATOR_MAX": "لسٽ جو وڏي ۾ وڏو قدر", - "MATH_ONLIST_TOOLTIP_MAX": "لسٽ ۾ وڏي کان وڏو قدر ڄاڻايو.", - "MATH_ONLIST_OPERATOR_AVERAGE": "لسٽ جي سراسري", - "MATH_ONLIST_OPERATOR_MEDIAN": "لسٽ جو مڌيان", - "MATH_ONLIST_TOOLTIP_MEDIAN": "لسٽ جو مڌيان انگ ڄاڻايو.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "شامل ٿيو", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "وڏن اکرن ڏانهن", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "ننڍن اکر ڏانهن", - "TEXT_PRINT_TITLE": "ڇاپيو %1", - "TEXT_PRINT_TOOLTIP": "ڄاڻايل تحرير، انگ يا ڪو ٻيو قدر ڇاپيو.", - "LISTS_CREATE_EMPTY_TITLE": "خالي فهرست تخليق ڪريو", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "لسٽ", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "فهرست ۾ ڪا شي شامل ڪريو.", - "LISTS_INLIST": "فهرست ۾", - "LISTS_GET_INDEX_REMOVE": "هٽايو", - "LISTS_GET_INDEX_FROM_END": "# آخر کان", - "LISTS_GET_INDEX_FIRST": "پهريون", - "LISTS_GET_INDEX_LAST": "آخري", - "LISTS_GET_INDEX_RANDOM": "بي ترتيب", - "LISTS_SET_INDEX_SET": "ميڙ", - "LISTS_SET_INDEX_INSERT": "تي داخل ڪريو", - "LISTS_SET_INDEX_INPUT_TO": "جيان", - "LISTS_GET_SUBLIST_END_FROM_START": "ڏانهن #", - "LISTS_GET_SUBLIST_END_FROM_END": "ڏانهن # آخر کان", - "LISTS_GET_SUBLIST_END_LAST": "آخري ڏانهن", - "PROCEDURES_DEFNORETURN_TITLE": "ڏانهن", - "PROCEDURES_DEFNORETURN_PROCEDURE": "ڪجھ ڪريو", - "PROCEDURES_BEFORE_PARAMS": "سان:", - "PROCEDURES_CALL_BEFORE_PARAMS": "سان:", - "PROCEDURES_DEFRETURN_RETURN": "واپس ورو", - "PROCEDURES_MUTATORCONTAINER_TITLE": "ان پُٽس", - "PROCEDURES_CREATE_DO": "تخليق ڪريو '%1'" -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/shn.json b/backend/_pv_1_3_5/static/blockly/msg/json/shn.json deleted file mode 100755 index 0f747e58a..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/shn.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Saosukham" - ] - }, - "VARIABLES_DEFAULT_NAME": "ဢၼ်", - "TODAY": "မိူဝ်ႈၼႆႉ", - "DUPLICATE_BLOCK": "ထုတ်ႇ", - "ADD_COMMENT": "သႂ်ႇၶေႃႈၵႂၢမ်း", - "REMOVE_COMMENT": "ဢဝ်ဢွၵ်ႇ ၶေႃႈၵႂၢမ်း", - "EXTERNAL_INPUTS": "ၶိူင်ႈဢၼ်လုၵ်ႉတၢင်းၼွၵ်ႈၶဝ်ႈမႃး", - "INLINE_INPUTS": "ၶိူင်ႈဢၼ်ၶဝ်ႈမႃးၸွမ်းလႅင်း", - "DELETE_BLOCK": "မွတ်ႇပလွၵ်ႉ", - "DELETE_X_BLOCKS": "မွတ်ႇပလွၵ်ႉ %1", - "COLLAPSE_BLOCK": "ပလွၵ်ႉလႅဝ်", - "COLLAPSE_ALL": "ပလွၵ်ႉတင်းၼမ် လႅဝ်", - "EXPAND_BLOCK": "ၶႂၢၵ်ႈပလွၵ်ႉ", - "EXPAND_ALL": "ၶႂၢၵ်ႈပလွၵ်ႉတင်းၼမ်", - "DISABLE_BLOCK": "ဢမ်ႇၸၢင်ႈပလွၵ်ႉ", - "ENABLE_BLOCK": "ၵမ်ႉထႅမ်ပၼ် ပလွၵ်ႉ", - "HELP": "ၸွႆႈထႅမ်", - "CHANGE_VALUE_TITLE": "လႅၵ်ႈလၢႆႈၼမ်ႉၵတ်ႉ", - "NEW_VARIABLE": "လၢႆႈဢၼ်မႂ်ႇ", - "NEW_VARIABLE_TITLE": "ၸိုဝ်ႈဢၼ်လၢႆႈမႂ်ႇ", - "RENAME_VARIABLE": "လိုမ်ႉၶိုၼ်း ဢၼ်လၢႆႈမႂ်ႇ", - "RENAME_VARIABLE_TITLE": "လိုမ်ႉၶိုၼ်း ဢၼ်လၢႆႈမႂ်ႇၸိူဝ်းၼၼ်ႉ '%1' ထိုင်", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Color သီ", - "COLOUR_PICKER_TOOLTIP": "လိူၵ်ႈသီ တမ်ႈတီႈ ၽႃးလႅတ်ႉ", - "COLOUR_RANDOM_TITLE": "သီလၢမ်းလိမ်း", - "COLOUR_RANDOM_TOOLTIP": "လိူၵ်ႈသီတမ်ႈတီႈလွၵ်းလၢမ်းလိမ်း", - "COLOUR_RGB_TITLE": "ႁူမ်ႈၵိုၵ်းသီ", - "COLOUR_RGB_RED": "လီင်", - "COLOUR_RGB_GREEN": "ၶဵဝ်", - "COLOUR_RGB_BLUE": "သွမ်ႇ", - "COLOUR_RGB_TOOLTIP": "ႁဵတ်းတူၺ်း သီဢၼ်ၼိုင်ႈ ၸွမ်းၼင်ႇမၵ်းမၼ်ႈဝႆႉ ၼႂ်းၶႂၢင်ႇ သီလႅင်, ၶဵဝ် လႄႈ သွမ်ႇ။ ၼမ်ႉၼၵ်းသီ တေလႆႈမီးၼႂ်းဝူင်ႈၵၢင် 0 တေႃႇ 100.", - "COLOUR_BLEND_TITLE": "လေႃးလႄး", - "COLOUR_BLEND_COLOUR1": "သီ 1", - "COLOUR_BLEND_COLOUR2": "သီ 2", - "COLOUR_BLEND_RATIO": "သႅၼ်း", - "COLOUR_BLEND_TOOLTIP": "ဢဝ်သီသွင်ဢၼ်လေႃးၵၼ် ၸွမ်းၼမ် သႅၼ်းဢၼ်ပၼ်ဝႆႉ (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop တႃႇတူင်ႇမူၼ်း", - "CONTROLS_REPEAT_TITLE": "ပၼ်ႇၶိုၼ်း %1 ၵမ်း", - "CONTROLS_REPEAT_INPUT_DO": "ႁဵတ်း", - "CONTROLS_REPEAT_TOOLTIP": "ႁဵတ်းၶေႃႈၵဵပ်းထွၼ်ၵမ်ႈၽွင်ႈ တင်းၼမ်", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "ၶၢဝ်းတိုၵ်ႉလိုမ်ႉ", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "တိုၵ်ႉလိုမ်ႉထိုင်", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "ပေႃးဝႃႈ ၵႃႈၶၼ် (ၼမ်ႉၵတ်ႉ) မၢၼ်ႇမႅၼ်ႈယဝ်ႉၸိုင် ႁဵတ်းၶေႃႈၵဵပ်းထွၼ်ၵမ်ႈၽွင်ႈ", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "ပေႃးဝႃႈ ၵႃႈၶၼ် (ၼမ်ႉၵတ်ႉ) ဢမ်ႇမၢၼ်ႇမႅၼ်ႈၸိုင် ႁဵတ်းၶေႃႈၵဵပ်းထွၼ် ၵမ်ႈၽွင်ႈ", - "CONTROLS_FOR_TITLE": "တႄႇဢၢၼ်ႇၵိုၵ်း %1 တေႃႇ %2 တေႃႇ %3 လူၺ်ႈ %4", - "CONTROLS_FOREACH_TITLE": "တႃႇၵူႈဢၼ်ဢၼ် ၼႂ်း %1 သဵၼ်ႈမၢႆ %2", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "ဢွၵ်ႇတီႈၶွပ်ႇမူၼ်း", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "သိုပ်ႇပၼ်ႇထႅင်ႈ ၶွပ်ႇမူၼ်းတၢင်ႇဢၼ်", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "ၵိုတ်းပႅတ်ႈ ၶွပ်ႇမူၼ်း ဢၼ်မီးဝႆႉ", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "ဝဵၼ်ႉဝႆႉ ၶွပ်ႇမူၼ်း ဢၼ်ၵိုတ်းၸိူဝ်ႈဝႆႉ, သေ သိုပ်ႇထႅင်ႈတၢင်ႇဢၼ်", - "CONTROLS_FLOW_STATEMENTS_WARNING": "ၾၢင်ႉ: ပလွၵ်ႉဢၼ်ၼႆႉ ၵူၺ်းၸႂ်ႉလူၺ်ႈတႃႇ ၶွပ်ႇမူၼ်းၵူၺ်း", - "CONTROLS_IF_TOOLTIP_1": "ပေႃးဝႃႈ ၵႃႈၶၼ် (ၼမ်ႉၵတ်ႉ) မၢၼ်ႇမႅၼ်ႈယဝ်ႉၸိုင် ႁဵတ်းၶေႃႈၵဵပ်းထွၼ်ၵမ်ႈၽွင်ႈ", - "CONTROLS_IF_TOOLTIP_2": "သင်ဝႃႈ ၵႃႈၶၼ်(ၼမ်ႉၵတ်ႉ)မၢၼ်ႇမႅၼ်ႈၸိုင် ႁဵတ်းပလွၵ်ႉဢွၼ်တၢင်းသုတ်း တီႈၼႂ်းၶေႃႈၵဵပ်းထွၼ်တ။ လိူဝ်သေၼၼ်ႉ ႁဵတ်းပႅတ်ႈ ပလွၵ်ႉသွင် တီႈၼႂ်းၶေႃႈၵဵပ်းထွၼ်", - "CONTROLS_IF_TOOLTIP_3": "သင်ဝႃႈ ၵႃႈၶၼ်(ၼမ်ႉၵတ်ႉ)မၢႉၼိုင်ႈ မၢၼ်ႇမႅၼ်ႈၸိုင် ႁဵတ်းပလွၵ်ႉဢွၼ်တၢင်းသုတ်း တီႈၼႂ်းၶေႃႈၵဵပ်းထွၼ်တ။ သင်ဝႃႈ ၵႃႈၶၼ်(ၼမ်ႉၵတ်ႉ)မၢႆသွင်မၢၼ်ႇမႅၼ်ႈၸိုင် ႁဵတ်းပႅတ်ႈ ပလွၵ်ႉသွင် တီႈၼႂ်းၶေႃႈၵဵပ်းထွၼ်", - "CONTROLS_IF_TOOLTIP_4": "သင်ဝႃႈ ၵႃႈၶၼ်(ၼမ်ႉၵတ်ႉ)မၢႆၼိုင်ႈ မၢၼ်ႇမႅၼ်ႈၸိုင် ႁဵတ်းပလွၵ်ႉဢွၼ်တၢင်းသုတ်း တီႈၼႂ်းၶေႃႈၵဵပ်းထွၼ်တ။ လိူဝ်သေၼၼ်ႉ, သင်ဝႃႈ ၵႃႈၶၼ် (ၼမ်ႉၵတ်ႉ) မၢႆသွင် မၢၼ်ႇမႅၼ်ႈၸိုင် ႁဵတ်းပႅတ်ႈ ပလွၵ်ႉသွင် တီႈၼႂ်းၶေႃႈၵဵပ်းထွၼ်တ။ သင်ဝႃႈ ၵႃႈၶၼ်(ၼမ်ႉၵတ်ႉ) ဢမ်ႇမီးလွင်ႈမၢၼ်ႇမႅၼ်ႈ သင်ၸိုင် ႁဵတ်းပႅတ်ႈပလွၵ်ႉ ၵမ်းလိုမ်း တီႈၼႂ်းၶေႃႈၵဵပ်းထွၼ်တ။", - "CONTROLS_IF_MSG_IF": "သင်ဝႃႈ", - "CONTROLS_IF_MSG_ELSEIF": "သင်ဝႃႈ လိူဝ်သေၼၼ်ႉ", - "CONTROLS_IF_MSG_ELSE": "လိူဝ်သေၼၼ်ႉ", - "CONTROLS_IF_ELSEIF_TOOLTIP": "သင်ဝႃႈ ပလွၵ်ႉၸိုင် သႂ်ႇပၼ်လွင်ႈတၢင်းမၼ်း တမ်ႈ", - "CONTROLS_IF_ELSE_TOOLTIP": "သႂ်ႇၵမ်းလိုၼ်း, သင်ဝႃႈ ပလွၵ်ႉၸိုင် ဢဝ်လွင်ႈတၢင်းမၼ်းတင်းသဵင်ႈ တမ်ႈ", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(ပၢႆးၼပ်ႉ)", - "LOGIC_COMPARE_TOOLTIP_EQ": "သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ တင်းသွင် မိူၼ်တၢင်ႇဢၼ်ၸိုင် မႄးၶိုၼ်း ႁႂ်ႈမၢၼ်ႇမႅၼ်ႈ", - "LOGIC_COMPARE_TOOLTIP_NEQ": "သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ တင်းသွင် ဢမ်ႇမိူၼ်တၢင်ႇဢၼ်ၸိုင် မႄးၶိုၼ်း ႁႂ်ႈမၢၼ်ႇမႅၼ်ႈ", - "LOGIC_COMPARE_TOOLTIP_LT": "သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ ဢွၼ်တၢင်း မိူၼ် ဢၼ်ၽိူမ်ႉသႂ်ႇ မၢႆသွင်ၸိုင် မႄးၶိုၼ်း ႁႂ်ႈမၢၼ်ႇမႅၼ်ႈ", - "LOGIC_COMPARE_TOOLTIP_LTE": "သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ ဢွၼ်တၢင်း မိူၼ် ဢမ်ႇၼၼ် ၽဵင်ႇပဵင်း ဢၼ်ၽိူမ်ႉသႂ်ႇ မၢႆသွင်ၸိုင် မႄးၶိုၼ်း ႁႂ်ႈမၢၼ်ႇမႅၼ်ႈ", - "LOGIC_COMPARE_TOOLTIP_GT": "သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ ဢွၼ်တၢင်း ယႂ်ႇလိူဝ် ဢၼ်ၽိူမ်ႉသႂ်ႇ မၢႆသွင်ၸိုင် မႄးၶိုၼ်း ႁႂ်ႈမၢၼ်ႇမႅၼ်ႈ", - "LOGIC_COMPARE_TOOLTIP_GTE": "သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ ဢွၼ်တၢင်း ယႂ်ႇလိူဝ် ဢမ်ႇၼၼ် ၽဵင်ႇပဵင်း ဢၼ်ၽိူမ်ႉသႂ်ႇ မၢႆသွင်ၸိုင် မႄးၶိုၼ်း ႁႂ်ႈမၢၼ်ႇမႅၼ်ႈ", - "LOGIC_OPERATION_TOOLTIP_AND": "သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ တင်းသွင်ဢၼ် မၢၼ်ႇမႅၼ်ႈၸိုင်ၸိုင် မႄးၶိုၼ်း ႁႂ်ႈမၢၼ်ႇမႅၼ်ႈ", - "LOGIC_OPERATION_AND": "လႄႈ", - "LOGIC_OPERATION_TOOLTIP_OR": "သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ ၵမ်းလိုၼ်းသုတ်း မၢၼ်ႇမႅၼ်ႈၸိုင် မႄးၶိုၼ်း ႁႂ်ႈမၢၼ်ႇမႅၼ်ႈ", - "LOGIC_OPERATION_OR": "ဢမ်ႇၼၼ်", - "LOGIC_NEGATE_TITLE": "ဢမ်ႇၸႂ်ႈ %1", - "LOGIC_NEGATE_TOOLTIP": "သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ ဢမ်ႇၼႅၼ်ႈၼႃၸိုင် မႄးၶိုၼ်း ႁႂ်ႈမၢၼ်ႇမႅၼ်ႈ။ သင်ဝႃႈ ဢၼ်ၽိူမ်ႉသႂ်ႇ မၢၼ်ႇမႅၼ်ႈၸိုင် ၶိုၼ်းမူၼ်ႉမႄး ႁႂ်ႈၼႅၼ်ႈၼႃ", - "LOGIC_BOOLEAN_TRUE": "မၢၼ်ႇမႅၼ်ႈ", - "LOGIC_BOOLEAN_FALSE": "ဢမ်ႇၼႅၼ်ႈၼႃ", - "LOGIC_BOOLEAN_TOOLTIP": "မၢၼ်ႇမႅၼ်ႈလႄႈသင် ဢမ်ႇၼႅၼ်ႈၼႃလႄႈသင် ႁူၼ်ၶိုၼ်း", - "LOGIC_NULL": "ဢမ်ႇၶဝ်ႈၶႂၢင်ႇ", - "LOGIC_NULL_TOOLTIP": "လဵဝ်ၶိုၼ်း ဢမ်ႇၶဝ်ႈၶႂၢင်ႇ", - "LOGIC_TERNARY_CONDITION": "ၸၢမ်း", - "LOGIC_TERNARY_IF_TRUE": "သင်ဝႃႈ မၢၼ်ႇမႅၼ်ႈ", - "LOGIC_TERNARY_IF_FALSE": "သင်ဝႃႈ ဢမ်ႇၼႅၼ်ႈၼႃ", - "LOGIC_TERNARY_TOOLTIP": "ၸၢမ်းၵူတ်ႇတူၺ်း သၢႆငၢႆ။ သင်ဝႃႈ သၢႆငၢႆမၢၼ်ႇမႅၼ်ႈ, လဵဝ်ၶိုၼ်း ၵႃႈၶၼ် (ၼမ်ႉၵတ်ႉ) 'သင်မၢၼ်ႇမႅၼ်ႈ'; လိူဝ်ၼၼ်ႉ လဵဝ်ၶိုၼ်း ၵႃႈၶၼ် (ၼမ်ႉၵတ်ႉ) 'သင်ဢမ်ႇၼႅၼ်ႈၼႃ'။", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/မၢႆၼပ်ႉ", - "MATH_NUMBER_TOOLTIP": "မၢႆၼပ်ႉ ၼိုင်ႈဢၼ်", - "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/ပၢႆးၼပ်ႉ", - "MATH_ARITHMETIC_TOOLTIP_ADD": "လဵဝ်ၶိုၼ်း တၢင်းၼမ် ၼႂ်းမၢႆၼပ်ႉ သွင်", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "လဵဝ်ၶိုၼ်း ဢၼ်ပႅၵ်ႇပိူင်ႈ ၼႂ်းမၢႆၼပ်ႉ သွင်", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "လဵဝ်ၶိုၼ်း ဢၼ်ဢဝ်ဢွၵ်ႇ ၼႂ်းမၢႆၼပ်ႉ သွင်", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "လဵဝ်ၶိုၼ်း ပမႃႇၼ ၼႂ်းမၢႆၼပ်ႉ သွင်", - "MATH_ARITHMETIC_TOOLTIP_POWER": "လဵဝ်ၶိုၼ်း တူဝ်ၼပ်ႉမၢႆၼိုင်ႈၼႆႉ ၸွႆႈႁႅင်းပၼ် တူဝ်ၼပ်ႉမၢႆသွင်", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root (မၢႆတူပ်ႉမိူၼ်)", - "MATH_SINGLE_OP_ROOT": "မၢႆတူပ်ႉမိူၼ်", - "MATH_SINGLE_TOOLTIP_ROOT": "လဵဝ်ၶိုၼ်း မၢႆတူပ်ႉမိူၼ် ၼႂ်းမၢႆၼပ်ႉ", - "MATH_SINGLE_OP_ABSOLUTE": "ပၵတိ", - "MATH_SINGLE_TOOLTIP_ABS": "လဵဝ်ၶိုၼ်း ၵႃႈၶၼ် (ၼမ်ႉၵတ်ႉ) ပၵတိ ၼႂ်းမၢႆၼပ်ႉ", - "MATH_SINGLE_TOOLTIP_NEG": "လဵဝ်ၶိုၼ်း ဢၼ်သၢၼ်ၶတ်း ၼႂ်း မၢႆၼပ်ႉ", - "MATH_SINGLE_TOOLTIP_LN": "လဵဝ်ၶိုၼ်း လွၵ်းလၢႆးၼပ်ႉ ၼႂ်းမၢႆၼပ်ႉ", - "MATH_SINGLE_TOOLTIP_LOG10": "လဵဝ်ၶိုၼ်း ပိုၼ်ႉထၢၼ် 10 လွၵ်းလၢႆးၼပ်ႉ ၼႂ်းမၢႆၼပ်ႉ", - "MATH_SINGLE_TOOLTIP_EXP": "လဵဝ်ၶိုၼ်း e ၵႂႃႇတီႈ ပႃႇဝႃႇ ၼႂ်းမၢႆၼပ်ႉ", - "MATH_SINGLE_TOOLTIP_POW10": "လဵဝ်ၶိုၼ်း 10 ၵႂႃႇတီႈ ပႃႇဝႃႇ ၼႂ်းမၢႆၼပ်ႉ", - "MATH_IS_EVEN": "ပဵၼ်ၵူပ်ႉ", - "MATH_IS_ODD": "ပဵၼ်ၵိၵ်ႈ" -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/sk.json b/backend/_pv_1_3_5/static/blockly/msg/json/sk.json deleted file mode 100755 index ad8b9b020..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/sk.json +++ /dev/null @@ -1,304 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Jaroslav.micek", - "Marian.stano", - "Mark" - ] - }, - "VARIABLES_DEFAULT_NAME": "prvok", - "TODAY": "Dnes", - "DUPLICATE_BLOCK": "Duplikovať", - "ADD_COMMENT": "Pridať komentár", - "REMOVE_COMMENT": "Odstrániť komentár", - "EXTERNAL_INPUTS": "Vonkajšie vstupy", - "INLINE_INPUTS": "Riadkové vstupy", - "DELETE_BLOCK": "Odstrániť blok", - "DELETE_X_BLOCKS": "Odstrániť %1 blokov", - "DELETE_ALL_BLOCKS": "Zmazať všetkých %1 dielcov?", - "CLEAN_UP": "Narovnať bloky", - "COLLAPSE_BLOCK": "Zvinúť blok", - "COLLAPSE_ALL": "Zvinúť bloky", - "EXPAND_BLOCK": "Rozvinúť blok", - "EXPAND_ALL": "Rozvinúť bloky", - "DISABLE_BLOCK": "Vypnúť blok", - "ENABLE_BLOCK": "Povoliť blok", - "HELP": "Pomoc", - "CHANGE_VALUE_TITLE": "Zmeniť hodnotu:", - "RENAME_VARIABLE": "Premenovať premennú...", - "RENAME_VARIABLE_TITLE": "Premenovať všetky premenné '%1' na:", - "NEW_VARIABLE": "Nová premenná...", - "NEW_VARIABLE_TITLE": "Názov novej premennej:", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "Zvoľte farbu z palety.", - "COLOUR_RANDOM_TITLE": "náhodná farba", - "COLOUR_RANDOM_TOOLTIP": "Zvoliť farbu náhodne.", - "COLOUR_RGB_TITLE": "ofarbiť s", - "COLOUR_RGB_RED": "červená", - "COLOUR_RGB_GREEN": "zelená", - "COLOUR_RGB_BLUE": "modrá", - "COLOUR_RGB_TOOLTIP": "Vytvoriť farbu pomocou zadaného množstva červenej, zelenej a modrej. Množstvo musí byť medzi 0 a 100.", - "COLOUR_BLEND_TITLE": "zmiešať", - "COLOUR_BLEND_COLOUR1": "farba 1", - "COLOUR_BLEND_COLOUR2": "farba 2", - "COLOUR_BLEND_RATIO": "pomer", - "COLOUR_BLEND_TOOLTIP": "Zmieša dve farby v danom pomere (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "opakuj %1 krát", - "CONTROLS_REPEAT_INPUT_DO": "rob", - "CONTROLS_REPEAT_TOOLTIP": "Opakuj určité príkazy viackrát.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "opakuj kým", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "opakuj kým nebude", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Kým je hodnota pravdivá, vykonávaj príkazy.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Kým je hodnota nepravdivá, vykonávaj príkazy.", - "CONTROLS_FOR_TOOLTIP": "Nechá premennú '%1' nadobúdať hodnoty od začiatočného čísla po konečné s daným medzikrokom a vykoná zadané bloky.", - "CONTROLS_FOR_TITLE": "počítať s %1 od %2 do %3 o %4", - "CONTROLS_FOREACH_TITLE": "pre každý prvok %1 v zozname %2", - "CONTROLS_FOREACH_TOOLTIP": "Pre každý prvok v zozname priraď jeho hodnotu do premenej '%1' a vykonaj príkazy.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "opustiť slučku", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "prejdi na nasledujúce opakovanie slučky", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Opustiť túto slučku.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Vynechať zvyšok tejto slučky a pokračovať ďalším opakovaním.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Upozornenie: Tento blok sa môže používať len v rámci slučky.", - "CONTROLS_IF_TOOLTIP_1": "Ak je hodnota pravda, vykonaj príkazy.", - "CONTROLS_IF_TOOLTIP_2": "Ak je hodnota pravda, vykonaj príkazy v prvom bloku. Inak vykonaj príkazy v druhom bloku.", - "CONTROLS_IF_TOOLTIP_3": "Ak je prvá hodnota pravda, vykonaj príkazy v prvom bloku. Inak, ak je druhá hodnota pravda, vykonaj príkazy v druhom bloku.", - "CONTROLS_IF_TOOLTIP_4": "Ak je prvá hodnota pravda, vykonaj príkazy v prvom bloku. Inak, ak je druhá hodnota pravda, vykonaj príkazy v druhom bloku. Ak ani jedna hodnota nie je pravda, vykonaj príkazy v poslednom bloku.", - "CONTROLS_IF_MSG_IF": "ak", - "CONTROLS_IF_MSG_ELSEIF": "inak ak", - "CONTROLS_IF_MSG_ELSE": "inak", - "CONTROLS_IF_IF_TOOLTIP": "Pridať, odstrániť alebo zmeniť poradie oddielov tohto \"ak\" bloku.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Pridať podmienku k \"ak\" bloku.", - "CONTROLS_IF_ELSE_TOOLTIP": "Pridať poslednú záchytnú podmienku k \"ak\" bloku.", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Vráť hodnotu pravda, ak sú vstupy rovnaké.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Vráť hodnotu pravda, ak vstupy nie sú rovnaké.", - "LOGIC_COMPARE_TOOLTIP_LT": "Vráť hodnotu pravda, ak prvý vstup je menší než druhý.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Vráť hodnotu pravda ak prvý vstup je menší alebo rovný druhému.", - "LOGIC_COMPARE_TOOLTIP_GT": "Vráť hodnotu pravda ak prvý vstup je väčší než druhý.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Vráť hodnotu pravda ak prvý vstup je väčší alebo rovný druhému.", - "LOGIC_OPERATION_TOOLTIP_AND": "Vráť hodnotu pravda, ak sú vstupy pravdivé.", - "LOGIC_OPERATION_AND": "a", - "LOGIC_OPERATION_TOOLTIP_OR": "Vráť hodnotu pravda, ak je aspoň jeden vstup pravda.", - "LOGIC_OPERATION_OR": "alebo", - "LOGIC_NEGATE_TITLE": "nie je %1", - "LOGIC_NEGATE_TOOLTIP": "Vráti hodnotu pravda, ak je vstup nepravda. Vráti hodnotu nepravda ak je vstup pravda.", - "LOGIC_BOOLEAN_TRUE": "pravda", - "LOGIC_BOOLEAN_FALSE": "nepravda", - "LOGIC_BOOLEAN_TOOLTIP": "Vráť buď hodnotu pravda alebo nepravda.", - "LOGIC_NULL": "nič", - "LOGIC_NULL_TOOLTIP": "Vráti hodnotu nula.", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "ak pravda", - "LOGIC_TERNARY_IF_FALSE": "ak nepravda", - "LOGIC_TERNARY_TOOLTIP": "Skontroluj podmienku testom. Ak je podmienka pravda, vráť hodnotu \"ak pravda\", inak vráť hodnotu \"ak nepravda\".", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "Číslo.", - "MATH_TRIG_ASIN": "arcsin", - "MATH_TRIG_ACOS": "arccos", - "MATH_TRIG_ATAN": "arctan", - "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/Arithmetic", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Vráť súčet dvoch čísel.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Vráť rozdiel dvoch čísel.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Vráť súčin dvoch čísel.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Vráť podiel dvoch čísel.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Vráť prvé číslo umocnené druhým.", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "druhá odmocnina", - "MATH_SINGLE_TOOLTIP_ROOT": "Vráť druhú odmocninu čísla.", - "MATH_SINGLE_OP_ABSOLUTE": "absolútna hodnota", - "MATH_SINGLE_TOOLTIP_ABS": "Vráť absolútnu hodnotu čísla.", - "MATH_SINGLE_TOOLTIP_NEG": "Vráť opačné číslo.", - "MATH_SINGLE_TOOLTIP_LN": "Vráť prirodzený logaritmus čísla.", - "MATH_SINGLE_TOOLTIP_LOG10": "Vráť logaritmus čísla so základom 10.", - "MATH_SINGLE_TOOLTIP_EXP": "Vráť e umocnené číslom.", - "MATH_SINGLE_TOOLTIP_POW10": "Vráť 10 umocnené číslom.", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "Vráť sínus uhla (v stupňoch).", - "MATH_TRIG_TOOLTIP_COS": "Vráť kosínus uhla (v stupňoch).", - "MATH_TRIG_TOOLTIP_TAN": "Vráť tangens uhla (v stupňoch).", - "MATH_TRIG_TOOLTIP_ASIN": "Vráť arkus sínus čísla.", - "MATH_TRIG_TOOLTIP_ACOS": "Vráť arkus kosínus čísla.", - "MATH_TRIG_TOOLTIP_ATAN": "Vráť arkus tangens čísla.", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant‎", - "MATH_CONSTANT_TOOLTIP": "Vráť jednu zo zvyčajných konštánt: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), alebo ∞ (nekonečno).", - "MATH_IS_EVEN": "je párne", - "MATH_IS_ODD": "je nepárne", - "MATH_IS_PRIME": "je prvočíslo", - "MATH_IS_WHOLE": "je celé číslo", - "MATH_IS_POSITIVE": "je kladné", - "MATH_IS_NEGATIVE": "je záporné", - "MATH_IS_DIVISIBLE_BY": "je deliteľné", - "MATH_IS_TOOLTIP": "Skontroluj či je číslo párne, nepárne, celé, kladné, záporné alebo deliteľné určitým číslom. Vráť hodnotu pravda alebo nepravda.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "zmeniť %1 o %2", - "MATH_CHANGE_TOOLTIP": "Pridaj číslo do premennej \"%1\".", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Zaokrúhli číslo nahor alebo nadol.", - "MATH_ROUND_OPERATOR_ROUND": "zaokrúhli", - "MATH_ROUND_OPERATOR_ROUNDUP": "zaokrúhli nahor", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "zaokrúhli nadol", - "MATH_ONLIST_OPERATOR_SUM": "súčet zoznamu", - "MATH_ONLIST_TOOLTIP_SUM": "Vráť súčet všetkých čísel v zozname.", - "MATH_ONLIST_OPERATOR_MIN": "najmenšie v zozname", - "MATH_ONLIST_TOOLTIP_MIN": "Vrátiť najmenšie číslo v zozname.", - "MATH_ONLIST_OPERATOR_MAX": "najväčšie v zozname", - "MATH_ONLIST_TOOLTIP_MAX": "Vrátiť najväčšie číslo v zozname.", - "MATH_ONLIST_OPERATOR_AVERAGE": "priemer zoznamu", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Vráť aritmetický priemer čísel v zozname.", - "MATH_ONLIST_OPERATOR_MEDIAN": "medián zoznamu", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Vráť medián čísel v zozname.", - "MATH_ONLIST_OPERATOR_MODE": "najčastejšie v zozname", - "MATH_ONLIST_TOOLTIP_MODE": "Vrátiť najčastejší prvok v zozname.", - "MATH_ONLIST_OPERATOR_STD_DEV": "smerodajná odchýlka zoznamu", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Vráť smeroddajnú odchýlku zoznamu.", - "MATH_ONLIST_OPERATOR_RANDOM": "náhodný prvok zoznamu", - "MATH_ONLIST_TOOLTIP_RANDOM": "Vráť náhodne zvolený prvok zoznamu.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "zvyšok po delení %1 + %2", - "MATH_MODULO_TOOLTIP": "Vráť zvyšok po delení jedného čísla druhým.", - "MATH_CONSTRAIN_TITLE": "obmedz %1 od %2 do %3", - "MATH_CONSTRAIN_TOOLTIP": "Obmedzí číslo do zadaných hraníc (vrátane).", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "náhodné celé číslo od %1 do %2", - "MATH_RANDOM_INT_TOOLTIP": "Vráť náhodné celé číslo z určeného intervalu (vrátane).", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "náhodné číslo od 0 do 1", - "MATH_RANDOM_FLOAT_TOOLTIP": "Vráť náhodné číslo z intervalu 0.0 (vrátane) až 1.0.", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "Písmeno, slovo alebo riadok textu.", - "TEXT_JOIN_TITLE_CREATEWITH": "vytvor text z", - "TEXT_JOIN_TOOLTIP": "Vytvor text spojením určitého počtu prvkov.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "spoj", - "TEXT_CREATE_JOIN_TOOLTIP": "Pridaj, odstráň alebo zmeň poradie oddielov v tomto textovom bloku.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Pridaj prvok do textu.", - "TEXT_APPEND_TO": "do", - "TEXT_APPEND_APPENDTEXT": "pridaj text", - "TEXT_APPEND_TOOLTIP": "Pridaj určitý text do premennej '%1'.", - "TEXT_LENGTH_TITLE": "dĺžka %1", - "TEXT_LENGTH_TOOLTIP": "Vráti počet písmen (s medzerami) v zadanom texte.", - "TEXT_ISEMPTY_TITLE": "%1 je prázdny", - "TEXT_ISEMPTY_TOOLTIP": "Vráti hodnotu pravda, ak zadaný text je prázdny.", - "TEXT_INDEXOF_TOOLTIP": "Vráti index prvého/posledného výskytu prvého textu v druhom texte. Ak nenájde, vráti %1.", - "TEXT_INDEXOF_INPUT_INTEXT": "v texte", - "TEXT_INDEXOF_OPERATOR_FIRST": "nájdi prvý výskyt textu", - "TEXT_INDEXOF_OPERATOR_LAST": "nájdi posledný výskyt textu", - "TEXT_CHARAT_INPUT_INTEXT": "v texte", - "TEXT_CHARAT_FROM_START": "zisti písmeno #", - "TEXT_CHARAT_FROM_END": "zisti # písmeno od konca", - "TEXT_CHARAT_FIRST": "zisti prvé písmeno", - "TEXT_CHARAT_LAST": "zisti posledné písmeno", - "TEXT_CHARAT_RANDOM": "vyber náhodné písmeno", - "TEXT_CHARAT_TOOLTIP": "Vráti písmeno na určenej pozícii.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Vráti určenú časť textu.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "v texte", - "TEXT_GET_SUBSTRING_START_FROM_START": "vyber podreťazec od písmena #", - "TEXT_GET_SUBSTRING_START_FROM_END": "vyber podreťazec od # písmena od konca", - "TEXT_GET_SUBSTRING_START_FIRST": "vyber podreťazec od začiatku", - "TEXT_GET_SUBSTRING_END_FROM_START": "po písmeno #", - "TEXT_GET_SUBSTRING_END_FROM_END": "po # písmeno od konca", - "TEXT_GET_SUBSTRING_END_LAST": "po koniec", - "TEXT_CHANGECASE_TOOLTIP": "Vráť kópiu textu s inou veľkosťou písmen.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "na VEĽKÉ PÍSMENÁ", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "na malé písmená", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "na Veľké Začiatočné Písmená", - "TEXT_TRIM_TOOLTIP": "Vráť kópiu textu bez medzier na jednom alebo oboch koncoch.", - "TEXT_TRIM_OPERATOR_BOTH": "odstráň medzery z oboch strán", - "TEXT_TRIM_OPERATOR_LEFT": "odstráň medzery z ľavej strany", - "TEXT_TRIM_OPERATOR_RIGHT": "odstráň medzery z pravej strany", - "TEXT_PRINT_TITLE": "píš %1", - "TEXT_PRINT_TOOLTIP": "Napíš zadaný text, číslo alebo hodnotu.", - "TEXT_PROMPT_TYPE_TEXT": "výzva za zadanie textu so správou", - "TEXT_PROMPT_TYPE_NUMBER": "výzva na zadanie čísla so správou", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Výzva pre používateľa na zadanie čísla.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Výzva pre používateľa na zadanie textu.", - "LISTS_CREATE_EMPTY_TITLE": "prázdny zoznam", - "LISTS_CREATE_EMPTY_TOOLTIP": "Vráti zoznam nulovej dĺžky, ktorý neobsahuje žiadne prvky.", - "LISTS_CREATE_WITH_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_CREATE_WITH_TOOLTIP": "Vytvor zoznam s ľubovoľným počtom prvkov.", - "LISTS_CREATE_WITH_INPUT_WITH": "vytvor zoznam s", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "zoznam", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Pridaj, odstráň alebo zmeň poradie v tomto zoznamovom bloku.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Pridaj prvok do zoznamu.", - "LISTS_REPEAT_TOOLTIP": "Vytvorí zoznam s niekoľkými rovnakými prvkami s danou hodnotou.", - "LISTS_REPEAT_TITLE": "vytvor zoznam s prvkom %1 opakovaným %2 krát", - "LISTS_LENGTH_TITLE": "dĺžka %1", - "LISTS_LENGTH_TOOLTIP": "Vráti dĺžku zoznamu", - "LISTS_ISEMPTY_TITLE": "%1 je prázdny", - "LISTS_ISEMPTY_TOOLTIP": "Vráti pravda, ak je zoznam prázdny.", - "LISTS_INLIST": "v zozname", - "LISTS_INDEX_OF_FIRST": "nájdi prvý výskyt prvku", - "LISTS_INDEX_OF_LAST": "nájdi posledný výskyt prvku", - "LISTS_INDEX_OF_TOOLTIP": "Vráti index prvého/posledného výskytu prvku v zozname. Ak sa nič nenašlo, vráti %1.", - "LISTS_GET_INDEX_GET": "zisti", - "LISTS_GET_INDEX_GET_REMOVE": "zisti a odstráň", - "LISTS_GET_INDEX_REMOVE": "odstráň", - "LISTS_GET_INDEX_FROM_END": "# od konca", - "LISTS_GET_INDEX_FIRST": "prvý", - "LISTS_GET_INDEX_LAST": "posledný", - "LISTS_GET_INDEX_RANDOM": "náhodný", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 je počiatočný prvok.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 je posledný prvok.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Vráti prvok na určenej pozícii v zozname.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Vráti počiatočný prvok zoznamu.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Vráti posledný prvok zoznamu.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Vráti náhodný prvok zoznamu.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Odstráni a vráti prvok z určenej pozície v zozname.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Odstráni a vráti prvý prvok v zozname.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Odstráni a vráti posledný prvok v zozname.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Odstráni a vráti náhodný prvok v zozname.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Odstráni prvok na určenej pozícii v zozname.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Odstráni prvý prvok v zozname.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Odstráni posledný prvok v zozname.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Odstráni náhodný prvok v zozname.", - "LISTS_SET_INDEX_SET": "nastaviť", - "LISTS_SET_INDEX_INSERT": "vložiť na", - "LISTS_SET_INDEX_INPUT_TO": "ako", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Nastaví prvok na určenej pozícii v zozname.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Nastaví prvý prvok v zozname.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Nastaví posledný prvok v zozname.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Nastaví posledný prvok v zozname.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Vsunie prvok na určenú pozíciu v zozname.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Vsunie prvok na začiatok zoznamu.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Pripojí prvok na koniec zoznamu.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Vsunie prvok na náhodné miesto v zozname.", - "LISTS_GET_SUBLIST_START_FROM_START": "získať podzoznam od #", - "LISTS_GET_SUBLIST_START_FROM_END": "Získať podzoznam od # od konca", - "LISTS_GET_SUBLIST_START_FIRST": "Získať podzoznam od začiatku", - "LISTS_GET_SUBLIST_END_FROM_START": "po #", - "LISTS_GET_SUBLIST_END_FROM_END": "po # od konca", - "LISTS_GET_SUBLIST_END_LAST": "po koniec", - "LISTS_GET_SUBLIST_TOOLTIP": "Skopíruje určený úsek zoznamu.", - "LISTS_SPLIT_LIST_FROM_TEXT": "vytvoriť zoznam z textu", - "LISTS_SPLIT_TEXT_FROM_LIST": "vytvoriť text zo zoznamu", - "LISTS_SPLIT_WITH_DELIMITER": "s oddeľovačom", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Rozdelenie textu do zoznamu textov, lámanie na oddeľovačoch.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Spojiť zoznam textov do jedného textu s oddeľovačmi.", - "VARIABLES_GET_TOOLTIP": "Vráti hodnotu tejto premennej.", - "VARIABLES_GET_CREATE_SET": "Vytvoriť \"nastaviť %1\"", - "VARIABLES_SET": "nastaviť %1 na %2", - "VARIABLES_SET_TOOLTIP": "Nastaví túto premennú, aby sa rovnala vstupu.", - "VARIABLES_SET_CREATE_GET": "Vytvoriť \"získať %1\"", - "PROCEDURES_DEFNORETURN_TITLE": "na", - "PROCEDURES_DEFNORETURN_PROCEDURE": "urob niečo", - "PROCEDURES_BEFORE_PARAMS": "s:", - "PROCEDURES_CALL_BEFORE_PARAMS": "s:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Vytvorí funciu bez výstupu.", - "PROCEDURES_DEFNORETURN_COMMENT": "Doplň, čo robí táto funkcia...", - "PROCEDURES_DEFRETURN_RETURN": "vrátiť", - "PROCEDURES_DEFRETURN_TOOLTIP": "Vytvorí funkciu s výstupom.", - "PROCEDURES_ALLOW_STATEMENTS": "povoliť príkazy", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Upozornenie: Táto funkcia má duplicitné parametre.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Spustí používateľom definovanú funkciu '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Spustí používateľom definovanú funkciu '%1' a použije jej výstup.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "vstupy", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Pridať, odstrániť alebo zmeniť poradie vstupov tejto funkcie.", - "PROCEDURES_MUTATORARG_TITLE": "názov vstupu:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Pridať vstup do funkcie.", - "PROCEDURES_HIGHLIGHT_DEF": "Zvýrazniť definíciu funkcie", - "PROCEDURES_CREATE_DO": "Vytvoriť '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Ak je hodnota pravda, tak vráti druhú hodnotu.", - "PROCEDURES_IFRETURN_WARNING": "Upozornenie: Tento blok môže byť len vo vnútri funkcie." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/sl.json b/backend/_pv_1_3_5/static/blockly/msg/json/sl.json deleted file mode 100755 index ade5382cd..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/sl.json +++ /dev/null @@ -1,360 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Anzeljg", - "Miloš Košir", - "Dbc334" - ] - }, - "VARIABLES_DEFAULT_NAME": "element", - "TODAY": "Danes", - "DUPLICATE_BLOCK": "Podvoji", - "ADD_COMMENT": "Dodaj komentar", - "REMOVE_COMMENT": "Odstrani komentar", - "EXTERNAL_INPUTS": "Vnosi zunaj", - "INLINE_INPUTS": "Vnosi v vrsti", - "DELETE_BLOCK": "Izbriši kocko", - "DELETE_X_BLOCKS": "Izbriši kocke", - "DELETE_ALL_BLOCKS": "Izbrišem vseh %1 kock?", - "CLEAN_UP": "Ponastavi kocke", - "COLLAPSE_BLOCK": "Skrči kocko", - "COLLAPSE_ALL": "Skrči kocke", - "EXPAND_BLOCK": "Razširi kocko", - "EXPAND_ALL": "Razširi kocke", - "DISABLE_BLOCK": "Onemogoči kocko", - "ENABLE_BLOCK": "Omogoči kocko", - "HELP": "Pomoč", - "UNDO": "Razveljavi", - "REDO": "Ponovi", - "CHANGE_VALUE_TITLE": "Spremeni vrednost:", - "RENAME_VARIABLE": "Preimenuj spremenljivko...", - "RENAME_VARIABLE_TITLE": "Preimenuj vse spremenljivke '%1' v:", - "NEW_VARIABLE": "Nova spremenljivka...", - "NEW_VARIABLE_TITLE": "Ime nove spremenljivke:", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "Izberi barvo s palete.", - "COLOUR_RANDOM_TITLE": "naključna barva", - "COLOUR_RANDOM_TOOLTIP": "Izbere naključno barvo.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "določena barva", - "COLOUR_RGB_RED": "rdeča", - "COLOUR_RGB_GREEN": "zelena", - "COLOUR_RGB_BLUE": "modra", - "COLOUR_RGB_TOOLTIP": "Ustvari barvo z določeno količino rdeče, zelene in modre. Vse vrednosti morajo biti med 0 in 100.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "mešanica", - "COLOUR_BLEND_COLOUR1": "barva 1", - "COLOUR_BLEND_COLOUR2": "barva 2", - "COLOUR_BLEND_RATIO": "razmerje", - "COLOUR_BLEND_TOOLTIP": "Zmeša dve barvi v danem razmerju (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "ponavljaj %1 krat", - "CONTROLS_REPEAT_INPUT_DO": "izvedi", - "CONTROLS_REPEAT_TOOLTIP": "Kocke se izvedejo večkrat.", - "CONTROLS_WHILEUNTIL_HELPURL": "https://github.com/google/blockly/wiki/Loops#repeat", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "ponavljaj", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "ponavljaj dokler", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Kocke se izvajajo dokler je vrednost resnična.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Kocke se izvajajo dokler je vrednost neresnična.", - "CONTROLS_FOR_HELPURL": "https://github.com/google/blockly/wiki/Loops#count-with", - "CONTROLS_FOR_TOOLTIP": "Vrednost spremenljivke '%1' se spreminja od začetnega števila do končnega števila, z določenim korakom. Pri tem se izvedejo določene kocke.", - "CONTROLS_FOR_TITLE": "štej s/z %1 od %2 do %3 s korakom %4", - "CONTROLS_FOREACH_HELPURL": "https://github.com/google/blockly/wiki/Loops#for-each", - "CONTROLS_FOREACH_TITLE": "za vsak element %1 v seznamu %2", - "CONTROLS_FOREACH_TOOLTIP": "Za vsak element v seznamu, nastavi spremenljivko '%1' na ta element. Pri tem se izvedejo določene kocke.", - "CONTROLS_FLOW_STATEMENTS_HELPURL": "https://github.com/google/blockly/wiki/Loops#loop-termination-blocks", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "izstopi iz zanke", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "nadaljuj z naslednjo ponovitvijo zanke", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Izstopi iz trenutne zanke.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Preskoči preostanek te zanke in nadaljuje z naslednjo ponovitvijo.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Pozor: To kocko lahko uporabiš samo znotraj zanke.", - "CONTROLS_IF_HELPURL": "https://github.com/google/blockly/wiki/IfElse", - "CONTROLS_IF_TOOLTIP_1": "Če je vrednost resnična, izvedi določene kocke.", - "CONTROLS_IF_TOOLTIP_2": "Če je vrednost resnična, izvedi prvo skupino kock. Sicer izvedi drugo skupino kock.", - "CONTROLS_IF_TOOLTIP_3": "Če je prva vrednost resnična, izvedi prvo skupino kock. Sicer, če je resnična druga vrednost, izvedi drugo skupino kock.", - "CONTROLS_IF_TOOLTIP_4": "Če je prva vrednost resnična, izvedi prvo skupino kock. Sicer, če je resnična druga vrednost, izvedi drugo skupino kock. Če nobena izmed vrednosti ni resnična, izvedi zadnjo skupino kock.", - "CONTROLS_IF_MSG_IF": "če", - "CONTROLS_IF_MSG_ELSEIF": "sicer če", - "CONTROLS_IF_MSG_ELSE": "sicer", - "CONTROLS_IF_IF_TOOLTIP": "Dodaj, odstrani ali spremeni vrstni red odsekov za ponovno nastavitev »če« kocke.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Dodaj pogoj »če« kocki.", - "CONTROLS_IF_ELSE_TOOLTIP": "Dodaj končni pogoj »če« kocki.", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Vrne resnično, če sta vnosa enaka.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Vrne resnično, če vnosa nista enaka.", - "LOGIC_COMPARE_TOOLTIP_LT": "Vrne resnično, če je prvi vnos manjši od drugega.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Vrne resnično, če je prvi vnos manjši ali enak drugemu.", - "LOGIC_COMPARE_TOOLTIP_GT": "Vrne resnično, če je prvi vnos večji od drugega.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Vrne resnično, če je prvi vnos večji ali enak drugemu.", - "LOGIC_OPERATION_HELPURL": "https://github.com/google/blockly/wiki/Logic#logical-operations", - "LOGIC_OPERATION_TOOLTIP_AND": "Vrne resnično, če sta oba vnosa resnična.", - "LOGIC_OPERATION_AND": "in", - "LOGIC_OPERATION_TOOLTIP_OR": "Vrne resnično, če je vsaj eden od vnosov resničen.", - "LOGIC_OPERATION_OR": "ali", - "LOGIC_NEGATE_HELPURL": "https://github.com/google/blockly/wiki/Logic#not", - "LOGIC_NEGATE_TITLE": "ne %1", - "LOGIC_NEGATE_TOOLTIP": "Vrne resnično, če je vnos neresničen. Vrne neresnično, če je vnos resničen.", - "LOGIC_BOOLEAN_HELPURL": "https://github.com/google/blockly/wiki/Logic#values", - "LOGIC_BOOLEAN_TRUE": "resnično", - "LOGIC_BOOLEAN_FALSE": "neresnično", - "LOGIC_BOOLEAN_TOOLTIP": "Vrne resnično ali neresnično.", - "LOGIC_NULL_HELPURL": "https://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "prazno", - "LOGIC_NULL_TOOLTIP": "Vrne prazno.", - "LOGIC_TERNARY_HELPURL": "https://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "če resnično", - "LOGIC_TERNARY_IF_FALSE": "če neresnično", - "LOGIC_TERNARY_TOOLTIP": "Preveri pogoj v »testu«. Če je pogoj resničen, potem vrne vrednost »če resnično«; sicer vrne vrednost »če neresnično«.", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "Število.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tan", - "MATH_TRIG_ASIN": "asin", - "MATH_TRIG_ACOS": "acos", - "MATH_TRIG_ATAN": "atan", - "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/Arithmetic", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Vrne vsoto dveh števil.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Vrne razliko dveh števil.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Vrne zmnožek dveh števil.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Vrne kvocient dveh števil.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Vrne prvo število na potenco drugega števila.", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "kvadratni koren", - "MATH_SINGLE_TOOLTIP_ROOT": "Vrne kvadratni koren števila.", - "MATH_SINGLE_OP_ABSOLUTE": "absolutno", - "MATH_SINGLE_TOOLTIP_ABS": "Vrne absolutno vrednost števila.", - "MATH_SINGLE_TOOLTIP_NEG": "Vrne negacijo števila.", - "MATH_SINGLE_TOOLTIP_LN": "Vrne naravni logaritem števila.", - "MATH_SINGLE_TOOLTIP_LOG10": "Vrne desetiški logaritem števila.", - "MATH_SINGLE_TOOLTIP_EXP": "Vrne e na potenco števila.", - "MATH_SINGLE_TOOLTIP_POW10": "Vrne 10 na potenco števila.", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "Vrne sinus kota v stopinjah (ne radianih).", - "MATH_TRIG_TOOLTIP_COS": "Vrne kosinus kota v stopinjah (ne radianih).", - "MATH_TRIG_TOOLTIP_TAN": "Vrne tangens kota v stopinjah (ne radianih).", - "MATH_TRIG_TOOLTIP_ASIN": "Vrne arkus sinus števila.", - "MATH_TRIG_TOOLTIP_ACOS": "Vrne arkus kosinus števila.", - "MATH_TRIG_TOOLTIP_ATAN": "Vrne arkus tangens števila.", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "Vrne eno izmed običajnih konstant: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), ali ∞ (neskončno).", - "MATH_IS_EVEN": "je sodo", - "MATH_IS_ODD": "je liho", - "MATH_IS_PRIME": "je praštevilo", - "MATH_IS_WHOLE": "je celo", - "MATH_IS_POSITIVE": "je pozitivno", - "MATH_IS_NEGATIVE": "je negativno", - "MATH_IS_DIVISIBLE_BY": "je deljivo s/z", - "MATH_IS_TOOLTIP": "Preveri, če je število sodo, liho, praštevilo, celo, pozitivno, negativno ali, če je deljivo z določenim številom. Vrne resnično ali neresnično.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "spremeni %1 za %2", - "MATH_CHANGE_TOOLTIP": "Prišteje število k spremenljivki '%1'.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Zaokroži število navzgor ali navzdol.", - "MATH_ROUND_OPERATOR_ROUND": "zaokroži", - "MATH_ROUND_OPERATOR_ROUNDUP": "zaokroži navzgor", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "zaokroži navzdol", - "MATH_ONLIST_OPERATOR_SUM": "vsota seznama", - "MATH_ONLIST_TOOLTIP_SUM": "Vrne vsoto vseh števil na seznamu.", - "MATH_ONLIST_OPERATOR_MIN": "minimum seznama", - "MATH_ONLIST_TOOLTIP_MIN": "Vrne najmanjše število na seznamu.", - "MATH_ONLIST_OPERATOR_MAX": "maksimum seznama", - "MATH_ONLIST_TOOLTIP_MAX": "Vrne največje število na seznamu.", - "MATH_ONLIST_OPERATOR_AVERAGE": "povprečje seznama", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Vrne povprečje (aritmetično sredino) števil na seznamu.", - "MATH_ONLIST_OPERATOR_MEDIAN": "mediana seznama", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Vrne mediano števil na seznamu.", - "MATH_ONLIST_OPERATOR_MODE": "modus seznama", - "MATH_ONLIST_TOOLTIP_MODE": "Vrne seznam najpogostejšega elementa(-ov) na seznamu.", - "MATH_ONLIST_OPERATOR_STD_DEV": "standardni odklon seznama", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Vrne standardni odklon seznama.", - "MATH_ONLIST_OPERATOR_RANDOM": "naključni element seznama", - "MATH_ONLIST_TOOLTIP_RANDOM": "Vrne naključno število izmed števil na seznamu.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "ostanek pri %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Vrne ostanek pri deljenju dveh števil.", - "MATH_CONSTRAIN_HELPURL": "https://en.wikipedia.org/wiki/Clamping_%28graphics%29", - "MATH_CONSTRAIN_TITLE": "omeji %1 na najmanj %2 in največ %3", - "MATH_CONSTRAIN_TOOLTIP": "Omeji število, da bo med določenima (vključenima) mejama.", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "naključno število med %1 in %2", - "MATH_RANDOM_INT_TOOLTIP": "Vrne naključno število med dvema določenima mejama, vključno z mejama.", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "naključni ulomek", - "MATH_RANDOM_FLOAT_TOOLTIP": "Vrne naključni ulomek med (vključno) 0.0 in 1.0 (izključno).", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "Črka, beseda ali vrstica besedila.", - "TEXT_JOIN_HELPURL": "https://github.com/google/blockly/wiki/Text#text-creation", - "TEXT_JOIN_TITLE_CREATEWITH": "ustvari besedilo iz", - "TEXT_JOIN_TOOLTIP": "Ustvari besedilo tako, da združi poljubno število elementov.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "združi", - "TEXT_CREATE_JOIN_TOOLTIP": "Doda, odstrani ali spremeni vrstni red elementov tega besedila.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Doda element k besedilu.", - "TEXT_APPEND_HELPURL": "https://github.com/google/blockly/wiki/Text#text-modification", - "TEXT_APPEND_TO": "k", - "TEXT_APPEND_APPENDTEXT": "dodaj besedilo", - "TEXT_APPEND_TOOLTIP": "Doda besedilo k spremenljivki '%1'.", - "TEXT_LENGTH_HELPURL": "https://github.com/google/blockly/wiki/Text#text-modification", - "TEXT_LENGTH_TITLE": "dolžina %1", - "TEXT_LENGTH_TOOLTIP": "Vrne število črk oz. znakov (vključno s presledki) v določenem besedilu.", - "TEXT_ISEMPTY_HELPURL": "https://github.com/google/blockly/wiki/Text#checking-for-empty-text", - "TEXT_ISEMPTY_TITLE": "%1 je prazno", - "TEXT_ISEMPTY_TOOLTIP": "Vrne resnično, če je določeno besedilo prazno.", - "TEXT_INDEXOF_HELPURL": "https://github.com/google/blockly/wiki/Text#finding-text", - "TEXT_INDEXOF_TOOLTIP": "Vrne mesto (indeks) prve/zadnje pojavitve drugega besedila v prvem besedilu. Če besedila ne najde, vrne %1.", - "TEXT_INDEXOF_INPUT_INTEXT": "v besedilu", - "TEXT_INDEXOF_OPERATOR_FIRST": "najdi prvo pojavitev besedila", - "TEXT_INDEXOF_OPERATOR_LAST": "najdi zadnjo pojavitev besedila", - "TEXT_CHARAT_HELPURL": "https://github.com/google/blockly/wiki/Text#extracting-text", - "TEXT_CHARAT_INPUT_INTEXT": "iz besedila", - "TEXT_CHARAT_FROM_START": "vrni črko št.", - "TEXT_CHARAT_FROM_END": "vrni črko št. od konca", - "TEXT_CHARAT_FIRST": "vrni prvo črko", - "TEXT_CHARAT_LAST": "vrni zadnjo črko", - "TEXT_CHARAT_RANDOM": "vrni naključno črko", - "TEXT_CHARAT_TOOLTIP": "Vrne črko na določenem mestu v besedilu.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Vrne določen del besedila.", - "TEXT_GET_SUBSTRING_HELPURL": "https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "iz besedila", - "TEXT_GET_SUBSTRING_START_FROM_START": "vrni del od črke št.", - "TEXT_GET_SUBSTRING_START_FROM_END": "vrni del od črke št. od konca", - "TEXT_GET_SUBSTRING_START_FIRST": "vrni del od prve črke", - "TEXT_GET_SUBSTRING_END_FROM_START": "do črke št.", - "TEXT_GET_SUBSTRING_END_FROM_END": "do črke št. od konca", - "TEXT_GET_SUBSTRING_END_LAST": "do zadnje črke", - "TEXT_CHANGECASE_HELPURL": "https://github.com/google/blockly/wiki/Text#adjusting-text-case", - "TEXT_CHANGECASE_TOOLTIP": "Vrne kopijo besedila v drugi obliki.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "v VELIKE ČRKE", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "v male črke", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "v Velike Začetnice", - "TEXT_TRIM_HELPURL": "https://github.com/google/blockly/wiki/Text#trimming-removing-spaces", - "TEXT_TRIM_TOOLTIP": "Vrne kopijo besedila z odstranjenimi presledki z ene ali obeh strani.", - "TEXT_TRIM_OPERATOR_BOTH": "odstrani presledke z obeh strani", - "TEXT_TRIM_OPERATOR_LEFT": "odstrani presledke z leve strani", - "TEXT_TRIM_OPERATOR_RIGHT": "odstrani presledke z desne strani", - "TEXT_PRINT_HELPURL": "https://github.com/google/blockly/wiki/Text#printing-text", - "TEXT_PRINT_TITLE": "izpiši %1", - "TEXT_PRINT_TOOLTIP": "Izpiše določeno besedilo, število ali drugo vrednost.", - "TEXT_PROMPT_HELPURL": "https://github.com/google/blockly/wiki/Text#getting-input-from-the-user", - "TEXT_PROMPT_TYPE_TEXT": "vprašaj za besedilo s sporočilom", - "TEXT_PROMPT_TYPE_NUMBER": "vprašaj za število s sporočilom", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Vpraša uporabnika za vnos števila.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Vpraša uporabnika za vnos besedila.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "ustvari prazen seznam", - "LISTS_CREATE_EMPTY_TOOLTIP": "Vrne seznam, dolžine 0, ki ne vsebuje nobenih podatkov.", - "LISTS_CREATE_WITH_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_CREATE_WITH_TOOLTIP": "Ustvari seznam s poljubnim številom elementov.", - "LISTS_CREATE_WITH_INPUT_WITH": "ustvari seznam s/z", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "seznam", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Doda, odstrani ali spremeni vrstni red elementov tega seznama.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Doda element seznamu.", - "LISTS_REPEAT_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_REPEAT_TOOLTIP": "Ustvari seznam z danim elementom, ki se poljubno mnogo krat ponovi.", - "LISTS_REPEAT_TITLE": "ustvari seznam z elementom %1, ki se ponovi %2 krat", - "LISTS_LENGTH_HELPURL": "https://github.com/google/blockly/wiki/Lists#length-of", - "LISTS_LENGTH_TITLE": "dolžina %1", - "LISTS_LENGTH_TOOLTIP": "Vrne dolžino seznama.", - "LISTS_ISEMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#is-empty", - "LISTS_ISEMPTY_TITLE": "%1 je prazen", - "LISTS_ISEMPTY_TOOLTIP": "Vrne resnično, če je seznam prazen.", - "LISTS_INLIST": "v seznamu", - "LISTS_INDEX_OF_HELPURL": "https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list", - "LISTS_INDEX_OF_FIRST": "najdi prvo pojavitev elementa", - "LISTS_INDEX_OF_LAST": "najdi zadnjo pojavitev elementa", - "LISTS_INDEX_OF_TOOLTIP": "Vrne mesto (indeks) prve/zadnje pojavitve elementa v seznamu. Če elementa ne najde, vrne %1.", - "LISTS_GET_INDEX_GET": "vrni", - "LISTS_GET_INDEX_GET_REMOVE": "odstrani in vrni", - "LISTS_GET_INDEX_REMOVE": "odstrani", - "LISTS_GET_INDEX_FROM_START": "št.", - "LISTS_GET_INDEX_FROM_END": "mesto št. od konca", - "LISTS_GET_INDEX_FIRST": "prvo mesto", - "LISTS_GET_INDEX_LAST": "zadnje mesto", - "LISTS_GET_INDEX_RANDOM": "naključno mesto", - "LISTS_INDEX_FROM_START_TOOLTIP": "Prvi element je št. %1.", - "LISTS_INDEX_FROM_END_TOOLTIP": "Zadnji element je št. %1.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Vrne element na določenem mestu v seznamu.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Vrne prvi element seznama.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Vrne zadnji element seznama.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Vrne naključni element seznama.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Odstrani in vrne element na določenem mestu v seznamu.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Odstrani in vrne prvi element seznama.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Odstrani in vrne zadnji element seznama.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Odstrani in vrne naključni element seznama.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Odstrani element na določenem mestu v seznamu.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Odstrani prvi element seznama.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Odstrani zadnji element seznama.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Odstrani naključni element seznama.", - "LISTS_SET_INDEX_HELPURL": "https://github.com/google/blockly/wiki/Lists#in-list--set", - "LISTS_SET_INDEX_SET": "nastavi na", - "LISTS_SET_INDEX_INSERT": "vstavi na", - "LISTS_SET_INDEX_INPUT_TO": "element", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Nastavi element na določenem mestu v seznamu.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Nastavi prvi element seznama.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Nastavi zadnji element seznama.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Nastavi naključni element seznama.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Vstavi element na določeno mesto v seznamu.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Vstavi element na začetek seznama.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Doda element na konec seznama.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Vstavi element na naključno mesto v seznamu.", - "LISTS_GET_SUBLIST_HELPURL": "https://github.com/google/blockly/wiki/Lists#getting-a-sublist", - "LISTS_GET_SUBLIST_START_FROM_START": "ustvari podseznam od mesta št.", - "LISTS_GET_SUBLIST_START_FROM_END": "ustvari podseznam od mesta št. od konca", - "LISTS_GET_SUBLIST_START_FIRST": "ustvari podseznam od prvega mesta", - "LISTS_GET_SUBLIST_END_FROM_START": "do mesta št.", - "LISTS_GET_SUBLIST_END_FROM_END": "do mesta št. od konca", - "LISTS_GET_SUBLIST_END_LAST": "do zadnjega mesta", - "LISTS_GET_SUBLIST_TOOLTIP": "Ustvari nov seznam, kot kopijo določenega dela seznama.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "uredi %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Uredi kopijo seznama.", - "LISTS_SORT_ORDER_ASCENDING": "naraščajoče", - "LISTS_SORT_ORDER_DESCENDING": "padajoče", - "LISTS_SORT_TYPE_NUMERIC": "številčno", - "LISTS_SORT_TYPE_TEXT": "abecedno", - "LISTS_SORT_TYPE_IGNORECASE": "abecedno, brez velikosti črk", - "LISTS_SPLIT_HELPURL": "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists", - "LISTS_SPLIT_LIST_FROM_TEXT": "ustvari seznam iz besedila", - "LISTS_SPLIT_TEXT_FROM_LIST": "ustvari besedilo iz seznama", - "LISTS_SPLIT_WITH_DELIMITER": "z ločilom", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Razdruži besedilo v seznam besedil. Za razdruževanje besedila uporabi ločilo.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Združi seznam besedil v eno besedilo, ločeno z ločilom.", - "VARIABLES_GET_HELPURL": "https://github.com/google/blockly/wiki/Variables#get", - "VARIABLES_GET_TOOLTIP": "Vrne vrednost spremenljivke.", - "VARIABLES_GET_CREATE_SET": "Ustvari 'nastavi %1'", - "VARIABLES_SET_HELPURL": "https://github.com/google/blockly/wiki/Variables#set", - "VARIABLES_SET": "nastavi %1 na %2", - "VARIABLES_SET_TOOLTIP": "Nastavi, da je vrednost spremenljivke enaka vnosu.", - "VARIABLES_SET_CREATE_GET": "Ustvari 'vrni %1'", - "PROCEDURES_DEFNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFNORETURN_TITLE": "izvedi", - "PROCEDURES_DEFNORETURN_PROCEDURE": "nekaj", - "PROCEDURES_BEFORE_PARAMS": "s/z:", - "PROCEDURES_CALL_BEFORE_PARAMS": "s/z:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Ustvari funkcijo brez izhoda.", - "PROCEDURES_DEFNORETURN_COMMENT": "Opišite funkcijo ...", - "PROCEDURES_DEFRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFRETURN_RETURN": "vrni", - "PROCEDURES_DEFRETURN_TOOLTIP": "Ustvari funkcijo z izhodom.", - "PROCEDURES_ALLOW_STATEMENTS": "dovoli korake", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Pozor: Ta funkcija ima podvojene parametre.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Subroutine", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Izvede uporabniško funkcijo '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Subroutine", - "PROCEDURES_CALLRETURN_TOOLTIP": "Izvede uporabniško funkcijo '%1' in uporabi njen izhod.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "vnosi", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Doda, odstrani ali spremeni vrstni red vnosov te funkcije.", - "PROCEDURES_MUTATORARG_TITLE": "ime vnosa:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Funkciji doda vnos.", - "PROCEDURES_HIGHLIGHT_DEF": "Označi definicijo funkcije", - "PROCEDURES_CREATE_DO": "Ustvari '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Če je vrednost resnična, vrne drugo vrednost.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Pozor: To kocko lahko uporabiš samo znotraj definicije funkcije." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/sq.json b/backend/_pv_1_3_5/static/blockly/msg/json/sq.json deleted file mode 100755 index 31419b5ba..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/sq.json +++ /dev/null @@ -1,305 +0,0 @@ -{ - "@metadata": { - "authors": [ - "아라" - ] - }, - "VARIABLES_DEFAULT_NAME": "send", - "DUPLICATE_BLOCK": "Kopjo", - "ADD_COMMENT": "Vendos nje Koment", - "REMOVE_COMMENT": "Fshij komentin", - "EXTERNAL_INPUTS": "Hyrjet e jashtme", - "INLINE_INPUTS": "Hyrjet e brendshme", - "DELETE_BLOCK": "Fshij bllokun", - "DELETE_X_BLOCKS": "Fshij %1 blloqe", - "COLLAPSE_BLOCK": "Mbyll bllokun", - "COLLAPSE_ALL": "Mbyll blloqet", - "EXPAND_BLOCK": "Zmadho bllokun", - "EXPAND_ALL": "Zmadho blloqet", - "DISABLE_BLOCK": "Çaktivizo bllokun", - "ENABLE_BLOCK": "Aktivizo bllokun", - "HELP": "Ndihmë", - "CHANGE_VALUE_TITLE": "Ndrysho Vlerat:", - "RENAME_VARIABLE": "Ndrysho emrin variables...", - "RENAME_VARIABLE_TITLE": "Ndrysho emrin e te gjitha '%1' variablave ne :", - "NEW_VARIABLE": "Identifikatorë i ri...", - "NEW_VARIABLE_TITLE": "Emri i identifikatorit të ri:", - "COLOUR_PICKER_HELPURL": "http://en.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "Zgjidh nje ngjyre nga nje game ngjyrash.", - "COLOUR_RANDOM_TITLE": "ngjyre e rastesishme", - "COLOUR_RANDOM_TOOLTIP": "Zgjidhni një ngjyrë në mënyrë të rastësishme.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "ngjyre me", - "COLOUR_RGB_RED": "e kuqe", - "COLOUR_RGB_GREEN": "jeshile", - "COLOUR_RGB_BLUE": "blu", - "COLOUR_RGB_TOOLTIP": "Krijo një ngjyrë me shumën e specifikuar te te kuqes, te gjelbëres, dhe bluse. Te gjitha vlerat duhet te jene mes 0 dhe 100.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "Përzierje", - "COLOUR_BLEND_COLOUR1": "Ngjyra 1", - "COLOUR_BLEND_COLOUR2": "Ngjyra 2", - "COLOUR_BLEND_RATIO": "Perpjesetim", - "COLOUR_BLEND_TOOLTIP": "Perzien dy ngjyra së bashku me një raport të dhënë (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "http://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "përsërit %1 herë", - "CONTROLS_REPEAT_INPUT_DO": "ekzekuto", - "CONTROLS_REPEAT_TOOLTIP": "Ekzekuto disa fjali disa herë.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "përsërit përderisa", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "përsërit derisa", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Përderisa një vlerë është e saktë, atëherë ekzekuto disa fjali.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Përderisa një vlerë është e pasaktë, atëherë ekzekuto disa fjali.", - "CONTROLS_FOR_TOOLTIP": "Bëje identifikuesin \"%1\" që ta ketë vlerat prej numrit të fillimit deri tek numri i fundit, duke numëruar nga intervali i specifikuar, dhe ti bëj blloqet e specifikuara.", - "CONTROLS_FOR_TITLE": "numero me %1 nga %2 ne %3 me nga %4", - "CONTROLS_FOREACH_TITLE": "per cdo produkt %1 ne liste %2", - "CONTROLS_FOREACH_TOOLTIP": "Per cdo produkt ne nje \"liste\" \"vendos\" ndryshoren '%1' produktit, dhe pastaj bej disa deklarata.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "dil nga nje faze perseritese", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "vazhdo me elementin tjeter te nje faze perseritese", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Ndahu nga unaza.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Kapërce pjesën e mbetur të unazës, dhe vazhdo me ripërsëritjen tjetër.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Paralajmërim: Ky bllok mund të përdoret vetëm brenda unazës.", - "CONTROLS_IF_TOOLTIP_1": "Nëse një vlerë është e saktë, atëherë ekzekuto disa fjali.", - "CONTROLS_IF_TOOLTIP_2": "Nëse një vlerë është e saktë, atëherë ekzekuto bllokun e parë të fjalive. Përndryshe, ekzekuto bllokun e dytë të fjalive.", - "CONTROLS_IF_TOOLTIP_3": "Nëse vlera e parë është e saktë, atëherë ekzekuto bllokun e parë të fjalive. Përndryshe, nëse vlera e dytë është e saktë, ekzekuto bllokun e dytë të fjalive.", - "CONTROLS_IF_TOOLTIP_4": "Nëse vlera e parë është e saktë, atëherë ekzekuto bllokun e parë të fjalive. Përndryshe, nëse vlera e dytë është e saktë, ekzekuto bllokun e dytë të fjalive. Nëse asnjëra nga vlerat nuk është e saktë, ekzekuto bllokun e fundit të fjalive.", - "CONTROLS_IF_MSG_IF": "nëse", - "CONTROLS_IF_MSG_ELSEIF": "përndryshe nëse", - "CONTROLS_IF_MSG_ELSE": "përndryshe", - "CONTROLS_IF_IF_TOOLTIP": "Shto, fshij, ose rirregullo sektoret për ta rikonfiguruar këte bllok nëse.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "\"Vendos\" \"kushtein\"tek \"pjesa\" \"if\"", - "CONTROLS_IF_ELSE_TOOLTIP": "Shto një përfundues, që i mbërrin të gjitha kushtet në bllokun nëse.", - "LOGIC_COMPARE_HELPURL": "http://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Ktheje të saktë nëse të dy hyrjet janë të barabarta me njëra-tjetrën.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Ktheje të saktë nëse të dy hyrjet nuk janë të barabarta me njëra-tjetrën.", - "LOGIC_COMPARE_TOOLTIP_LT": "Ktheje të saktë nëse hyrja e parë është më e vogël se hyrja e dytë.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Ktheje të saktë nëse hyrja e parë është më e vogël ose e barabartë me hyrjen e dytë.", - "LOGIC_COMPARE_TOOLTIP_GT": "Ktheje të saktë nëse hyrja e parë është më e madhe se hyrja e dytë.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Ktheje të saktë nëse hyrja e parë është më e madhe ose e barabartë me hyrjen e dytë.", - "LOGIC_OPERATION_TOOLTIP_AND": "Kthehet të saktë nëse të dy hyrjet janë të sakta.", - "LOGIC_OPERATION_AND": "dhe", - "LOGIC_OPERATION_TOOLTIP_OR": "Kthehet e saktë nëse së paku njëra nga hyrjet është e saktë.", - "LOGIC_OPERATION_OR": "ose", - "LOGIC_NEGATE_TITLE": "jo %1", - "LOGIC_NEGATE_TOOLTIP": "Kthehet e saktë nëse hyrja është e pasaktë. Kthehet e pasaktë nëse hyrja është e saktë.", - "LOGIC_BOOLEAN_TRUE": "e saktë", - "LOGIC_BOOLEAN_FALSE": "e pasaktë", - "LOGIC_BOOLEAN_TOOLTIP": "Kthehet ose të saktë ose të pasaktë.", - "LOGIC_NULL_HELPURL": "http://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "pavlerë", - "LOGIC_NULL_TOOLTIP": "Kthehet e pavlerë.", - "LOGIC_TERNARY_HELPURL": "http://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "nëse e saktë", - "LOGIC_TERNARY_IF_FALSE": "nëse e pasaktë", - "LOGIC_TERNARY_TOOLTIP": "Kontrollo kushtin në 'test'. Nëse kushti është i saktë, kthen vlerën 'nëse e saktë'; përndryshe kthen vlerën 'nëse e pasaktë'.", - "MATH_NUMBER_HELPURL": "http://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "Një numër.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "x", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tan", - "MATH_TRIG_ASIN": "asinus", - "MATH_TRIG_ACOS": "acosinus", - "MATH_TRIG_ATAN": "atangjentë", - "MATH_ARITHMETIC_HELPURL": "http://sq.wikipedia.org/wiki/Aritmetika", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Kthen shumën e dy numrave.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Kthen ndryshimin e dy numrave.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Kthen produktin e dy numrave.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Kthen herësin e dy numrave.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Kthen numrin e parë të ngritur në fuqinë e numrit të dytë.", - "MATH_SINGLE_HELPURL": "http://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "rrënja katrore", - "MATH_SINGLE_TOOLTIP_ROOT": "Kthen rrënjën katrore të një numri.", - "MATH_SINGLE_OP_ABSOLUTE": "absolut", - "MATH_SINGLE_TOOLTIP_ABS": "Kthen vlerën absolute të një numri.", - "MATH_SINGLE_TOOLTIP_NEG": "Kthe negacionin e një numri.", - "MATH_SINGLE_TOOLTIP_LN": "Kthen logaritmën natyrale të një numri.", - "MATH_SINGLE_TOOLTIP_LOG10": "Kthen 10 logaritmet bazë të një numri.", - "MATH_SINGLE_TOOLTIP_EXP": "Kthen e në fuqinë e një numri.", - "MATH_SINGLE_TOOLTIP_POW10": "Kthen 10 në fuqinë e një numri.", - "MATH_TRIG_HELPURL": "http://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "Kthe kosinusin e nje kendi (jo ne radiant).", - "MATH_TRIG_TOOLTIP_COS": "Kthe kosinusin e nje grade (jo ne radiant).", - "MATH_TRIG_TOOLTIP_TAN": "Kthe tangentin e nje kendi (jo radiant).", - "MATH_TRIG_TOOLTIP_ASIN": "Rikthe sin-1 e nje numeri.", - "MATH_TRIG_TOOLTIP_ACOS": "Rikthe cos-1 e nje numeri.", - "MATH_TRIG_TOOLTIP_ATAN": "Kthe tg-1 e nje numeri.", - "MATH_CONSTANT_HELPURL": "http://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "Kthen një nga konstantet e përbashkëta: : π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infiniti).", - "MATH_IS_EVEN": "është çift", - "MATH_IS_ODD": "është tek", - "MATH_IS_PRIME": "është prim", - "MATH_IS_WHOLE": "është i plotë", - "MATH_IS_POSITIVE": "është pozitiv", - "MATH_IS_NEGATIVE": "është negativ", - "MATH_IS_DIVISIBLE_BY": "është i pjestueshme me", - "MATH_IS_TOOLTIP": "Kontrollo nëse një numër është çift, tek, prim, i plotë, pozitiv, negativ, ose nëse është i pjestueshëm me një numër të caktuar. Kthehet e saktë ose e pasaktë.", - "MATH_CHANGE_HELPURL": "http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "ndrysho %1 nga %2", - "MATH_CHANGE_TOOLTIP": "Shto një numër në ndryshoren '%1'.", - "MATH_ROUND_HELPURL": "http://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Rrumbullakësimi i numrit të lartë ose të ulët.", - "MATH_ROUND_OPERATOR_ROUND": "rrumbullakësimi", - "MATH_ROUND_OPERATOR_ROUNDUP": "rrumbullakësimi i lartë", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "rrumbullakësimi i ulët", - "MATH_ONLIST_OPERATOR_SUM": "mbledhja e listës", - "MATH_ONLIST_TOOLTIP_SUM": "Kthe shumën e të gjithë numrave të listës.", - "MATH_ONLIST_OPERATOR_MIN": "numri më i ulët i listës", - "MATH_ONLIST_TOOLTIP_MIN": "Kthe numrin me të vogël të listës.", - "MATH_ONLIST_OPERATOR_MAX": "numri më i madh i listës", - "MATH_ONLIST_TOOLTIP_MAX": "Kthe numrin më të madh të listës.", - "MATH_ONLIST_OPERATOR_AVERAGE": "mesatarja e listës", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Kthen mesatarën (kuptimi aritmetik) i vlerave numerike të listës.", - "MATH_ONLIST_OPERATOR_MEDIAN": "mediana e listës", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Kthe numrin median të listës.", - "MATH_ONLIST_OPERATOR_MODE": "modat e listës", - "MATH_ONLIST_TOOLTIP_MODE": "Kthe listën e sendit(eve) më të zakonshme të listës.", - "MATH_ONLIST_OPERATOR_STD_DEV": "devijimi standard i listës", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Kthe devijimin standard të listës.", - "MATH_ONLIST_OPERATOR_RANDOM": "send i rastësishëm i listës", - "MATH_ONLIST_TOOLTIP_RANDOM": "Kthe një element të rastësishëm nga lista.", - "MATH_MODULO_HELPURL": "http://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "mbetësi i %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Kthen mbetësin nga pjestimi i dy numrave.", - "MATH_CONSTRAIN_TITLE": "detyro %1 e ulët %2 e lartë %3", - "MATH_CONSTRAIN_TOOLTIP": "Vëni një numër që të jetë në mes të kufive të specifikuara(përfshirëse).", - "MATH_RANDOM_INT_HELPURL": "http://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "numër i plotë i rastësishëm nga %1 deri në %2", - "MATH_RANDOM_INT_TOOLTIP": "Kthe një numër të plotë të rastësishëm të dy kufijve të specifikuar, të përfshirë.", - "MATH_RANDOM_FLOAT_HELPURL": "http://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "fraksioni i rastësishëm", - "MATH_RANDOM_FLOAT_TOOLTIP": "Kthe fraksionin e rastësishëm në mes të 0.0 (përfshirëse) dhe 1.0 (jopërfshirëse).", - "TEXT_TEXT_HELPURL": "http://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "Nje shkronje, fjale, ose rresht teksti.", - "TEXT_JOIN_TITLE_CREATEWITH": "krijo tekst me", - "TEXT_JOIN_TOOLTIP": "Krijo nje pjese te tekstit duke bashkuar se bashku disa sende", - "TEXT_CREATE_JOIN_TITLE_JOIN": "bashkangjit", - "TEXT_CREATE_JOIN_TOOLTIP": "Shto, fshij, ose rirregullo sektoret për ta rikonfiguruar këtë bllok teksti.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Shto nje gje ne tekst", - "TEXT_APPEND_TO": "ne", - "TEXT_APPEND_APPENDTEXT": "shto tekst", - "TEXT_APPEND_TOOLTIP": "shto tekst tek varibla '%1'.", - "TEXT_LENGTH_TITLE": "gjatesi %1", - "TEXT_LENGTH_TOOLTIP": "Pergjigjet me nje numer shkronjash (duke perfshire hapesire) ne tekstin e dhene.", - "TEXT_ISEMPTY_TITLE": "%1 eshte bosh", - "TEXT_ISEMPTY_TOOLTIP": "Kthehet e vertete neqoftese teksti i dhene eshte bosh.", - "TEXT_INDEXOF_TOOLTIP": "Pergjigjet me indeksin e pare/fundit te rastisjes se tekstit te pare ne tekstin e dyte. Pergjigjet me %1 ne qofte se teksti nuk u gjet.", - "TEXT_INDEXOF_INPUT_INTEXT": "ne tekst", - "TEXT_INDEXOF_OPERATOR_FIRST": "gjej rastisjen e pare te tekstit", - "TEXT_INDEXOF_OPERATOR_LAST": "gjej rastisjen e fundit te tekstit", - "TEXT_CHARAT_INPUT_INTEXT": "ne tekst", - "TEXT_CHARAT_FROM_START": "merr shkronjen #", - "TEXT_CHARAT_FROM_END": "merr shkronjen # nga fundi", - "TEXT_CHARAT_FIRST": "merr shkronjen e pare", - "TEXT_CHARAT_LAST": "merr shkronjen e fundit", - "TEXT_CHARAT_RANDOM": "merr nje shkronje te rastesishme", - "TEXT_CHARAT_TOOLTIP": "Kthe nje shkronje nga nje pozicion i caktuar.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Pergjigjet me nje pjese te caktuar teksti.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "ne tekst", - "TEXT_GET_SUBSTRING_START_FROM_START": "Merr nenvargun nga shkronja #", - "TEXT_GET_SUBSTRING_START_FROM_END": "merr nenvargun nga shkronja # nga fundi", - "TEXT_GET_SUBSTRING_START_FIRST": "merr vlerat qe vazhdojne me shkronjen e pare", - "TEXT_GET_SUBSTRING_END_FROM_START": "ne shkronjen #", - "TEXT_GET_SUBSTRING_END_FROM_END": "ne shkronjen # nga fundi", - "TEXT_GET_SUBSTRING_END_LAST": "tek shkronja e fundit", - "TEXT_CHANGECASE_TOOLTIP": "Kthe nje kopje te tekstit ne nje rast te ndryshem.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "me shkronja te medha shtypi", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "me shkronja te vogla shtypi", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "Fillimi me shkronje te madhe shtypi", - "TEXT_TRIM_TOOLTIP": "Pergjigju me nje kopje te tekstit me hapesira te fshira nga njera ane ose te dyja anet.", - "TEXT_TRIM_OPERATOR_BOTH": "prit hapesirat nga te dyja anet", - "TEXT_TRIM_OPERATOR_LEFT": "prit hapesirat nga ana e majte", - "TEXT_TRIM_OPERATOR_RIGHT": "prit hapesirat nga ana e djathte", - "TEXT_PRINT_TITLE": "printo %1", - "TEXT_PRINT_TOOLTIP": "Printo tekstin e caktuar, numer ose vlere tjeter.", - "TEXT_PROMPT_TYPE_TEXT": "kerko tekst me njoftim", - "TEXT_PROMPT_TYPE_NUMBER": "kerko nje numer me njoftim", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Kerkoji perdoruesit nje numer.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Kerkoji perdoruesit ca tekst.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "krijo një listë të zbrazët", - "LISTS_CREATE_EMPTY_TOOLTIP": "Kthen një listë, te gjatësisë 0, duke mos përmbajtur asnjë regjistrim të të dhënave", - "LISTS_CREATE_WITH_TOOLTIP": "Krijo një listë me ndonjë numbër të sendeve.", - "LISTS_CREATE_WITH_INPUT_WITH": "krijo listë me", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "listë", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Shto, fshij, ose rirregullo sektoret për ta rikonfiguruar këtë bllok të listës.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Shto një send në listë.", - "LISTS_REPEAT_TOOLTIP": "Krijon në listë qe përmban vlerën e dhënë të përsëritur aq herë sa numri i specifikuar.", - "LISTS_REPEAT_TITLE": "krijo listën me sendin %1 të përsëritur %2 herë", - "LISTS_LENGTH_TITLE": "gjatësia e %1", - "LISTS_LENGTH_TOOLTIP": "Kthen gjatësinë e listës.", - "LISTS_ISEMPTY_TITLE": "%1 është e zbraztë", - "LISTS_ISEMPTY_TOOLTIP": "Kthehet i saktë nëse lista është e zbraztë.", - "LISTS_INLIST": "në listë", - "LISTS_INDEX_OF_FIRST": "gjen ndodhjen e parë të sendit", - "LISTS_INDEX_OF_LAST": "gjen ndodhjen e fundit të sendit", - "LISTS_INDEX_OF_TOOLTIP": "Kthen indeksin e ndodhjes së parë/fudit të sendit në listë. Kthen %1 nëse teksti nuk është gjetur.", - "LISTS_GET_INDEX_GET": "merr", - "LISTS_GET_INDEX_GET_REMOVE": "merr dhe fshij", - "LISTS_GET_INDEX_REMOVE": "largo", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# nga fundi", - "LISTS_GET_INDEX_FIRST": "i parë", - "LISTS_GET_INDEX_LAST": "i fundit", - "LISTS_GET_INDEX_RANDOM": "i rastësishëm", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 është sendi i parë.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 është sendi i fundit.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Kthen një send në pozicionin e specifikuar në listë.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Rikthen tek artikulli i par në list.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Kthen artikullin e fundit në list.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Kthen një send të rastësishëm në listë.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Fshin dhe kthen sendin në pozicionin e specifikuar në listë.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Fshin dhe kthen sendin e parë në listë.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Fshin dhe kthen sendin e fundit në listë.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Fshin dhe kthen një send të rastësishëm në listë.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Fshin sendin në pozicionin e specifikuar në listë.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Fshin sendin e parë në listë.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Fshin sendin e fundit në listë.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Kthen një send të rastësishëm në listë.", - "LISTS_SET_INDEX_SET": "vendos", - "LISTS_SET_INDEX_INSERT": "fut në", - "LISTS_SET_INDEX_INPUT_TO": "sikurse", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Vendos sendin në pozicionin e specifikuar në listë.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Vendos sendin e parë në listë.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Vendos sendin e fundit në listë.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Vendos një send të rastësishëm në listë.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Fut sendin në pozicionin e specifikuar të listës.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Fut sendin në fillim të listës.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Bashkangjit sendin në fund të listës.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Fut sendin rastësisht në listë.", - "LISTS_GET_SUBLIST_START_FROM_START": "merr nën-listën nga #", - "LISTS_GET_SUBLIST_START_FROM_END": "merr nën listën nga # nga fundi", - "LISTS_GET_SUBLIST_START_FIRST": "merr nën-listën nga i pari", - "LISTS_GET_SUBLIST_END_FROM_START": "tek #", - "LISTS_GET_SUBLIST_END_FROM_END": "tek # nga fundi", - "LISTS_GET_SUBLIST_END_LAST": "tek i fundit", - "LISTS_GET_SUBLIST_TOOLTIP": "Krijon në kopje të pjesës së specifikuar të listës.", - "VARIABLES_GET_TOOLTIP": "Pergjigjet me nje vlere te kesaj variable.", - "VARIABLES_GET_CREATE_SET": "Krijo 'vendos %1", - "VARIABLES_SET": "vendos %1 ne %2", - "VARIABLES_SET_TOOLTIP": "Vendos kete variable te jete e barabarte me te dhenat ne hyrje.", - "VARIABLES_SET_CREATE_GET": "Krijo 'merr %1", - "PROCEDURES_DEFNORETURN_HELPURL": "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFNORETURN_TITLE": "te", - "PROCEDURES_DEFNORETURN_PROCEDURE": "bëj diqka", - "PROCEDURES_BEFORE_PARAMS": "me:", - "PROCEDURES_CALL_BEFORE_PARAMS": "me:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Krijon një funksion pa dalje.", - "PROCEDURES_DEFRETURN_HELPURL": "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFRETURN_RETURN": "rikthe", - "PROCEDURES_DEFRETURN_TOOLTIP": "Krijon një funksion me një dalje.", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Paralajmërim: Ky funksion ka parametra të dyfishuar.", - "PROCEDURES_CALLNORETURN_HELPURL": "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Lësho funksionin e definuar nga përdoruesi '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Lëho funksionin e definuar nga përdoruesi '%1' dhe përdor daljen e tij.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "Informacioni i futur", - "PROCEDURES_MUTATORARG_TITLE": "Fut emrin:", - "PROCEDURES_HIGHLIGHT_DEF": "Thekso definicionin e funksionit", - "PROCEDURES_CREATE_DO": "Krijo '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Nëse një vlerë është e saktë, atëherë kthe një vlerë të dytë.", - "PROCEDURES_IFRETURN_WARNING": "Paralajmërim: Ky bllok mund të përdoret vetëm brenda definicionit të funksionit." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/sr.json b/backend/_pv_1_3_5/static/blockly/msg/json/sr.json deleted file mode 100755 index d0c5f2035..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/sr.json +++ /dev/null @@ -1,332 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Rancher", - "아라", - "Perevod16" - ] - }, - "VARIABLES_DEFAULT_NAME": "ставка", - "TODAY": "Данас", - "DUPLICATE_BLOCK": "Дуплирај", - "ADD_COMMENT": "Додај коментар", - "REMOVE_COMMENT": "Уклони коментар", - "EXTERNAL_INPUTS": "Спољни улази", - "INLINE_INPUTS": "Унутрашњи улази", - "DELETE_BLOCK": "Обриши блок", - "DELETE_X_BLOCKS": "Обриши %1 блокова", - "DELETE_ALL_BLOCKS": "Обрисати %1 блокова?", - "CLEAN_UP": "Уклоните блокова", - "COLLAPSE_BLOCK": "Скупи блок", - "COLLAPSE_ALL": "Скупи блокове", - "EXPAND_BLOCK": "Прошири блок", - "EXPAND_ALL": "Прошири блокове", - "DISABLE_BLOCK": "Онемогући блок", - "ENABLE_BLOCK": "Омогући блок", - "HELP": "Помоћ", - "UNDO": "Опозови", - "REDO": "Понови", - "CHANGE_VALUE_TITLE": "Промените вредност:", - "RENAME_VARIABLE": "Преименуј променљиву…", - "RENAME_VARIABLE_TITLE": "Преименујте све „%1“ променљиве у:", - "NEW_VARIABLE": "Нова променљива…", - "NEW_VARIABLE_TITLE": "Име нове променљиве:", - "COLOUR_PICKER_HELPURL": "https://sr.wikipedia.org/wiki/Боја", - "COLOUR_PICKER_TOOLTIP": "Изаберите боју са палете.", - "COLOUR_RANDOM_TITLE": "случајна боја", - "COLOUR_RANDOM_TOOLTIP": "Изаберите боју насумице.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "боја са", - "COLOUR_RGB_RED": "црвена", - "COLOUR_RGB_GREEN": "зелена", - "COLOUR_RGB_BLUE": "плава", - "COLOUR_RGB_TOOLTIP": "Креирај боју са одређеном количином црвене,зелене, и плаве. Све вредности морају бити између 0 и 100.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "помешај", - "COLOUR_BLEND_COLOUR1": "боја 1", - "COLOUR_BLEND_COLOUR2": "боја 2", - "COLOUR_BLEND_RATIO": "однос", - "COLOUR_BLEND_TOOLTIP": "Помешати две боје заједно са датим односом (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://sr.wikipedia.org/wiki/For_петља", - "CONTROLS_REPEAT_TITLE": "понови %1 пута", - "CONTROLS_REPEAT_INPUT_DO": "изврши", - "CONTROLS_REPEAT_TOOLTIP": "Одрадити неке наредбе неколико пута.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "понављати док", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "понављати до", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Док је вредност тачна, онда извршите неке наредбе.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Док вредност није тачна, онда извршити неке наредбе.", - "CONTROLS_FOR_TOOLTIP": "Имај промењиву \"%1\" узми вредности од почетног броја до задњег броја, бројећи по одређеном интервалу, и изврши одређене блокове.", - "CONTROLS_FOR_TITLE": "преброј са %1 од %2 до %3 од %4", - "CONTROLS_FOREACH_TITLE": "за сваку ставку %1 на списку %2", - "CONTROLS_FOREACH_TOOLTIP": "За сваку ставку унутар листе, подеси промењиву '%1' по ставци, и онда начини неке изјаве-наредбе.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "Изађите из петље", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "настави са следећом итерацијом петље", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Напусти садржај петље.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Прескочи остатак ове петље, и настави са следећом итерацијом(понављанјем).", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Упозорење: Овај блок може да се употреби само унутар петље.", - "CONTROLS_IF_TOOLTIP_1": "ако је вредност тачна, онда изврши неке наредбе-изјаве.", - "CONTROLS_IF_TOOLTIP_2": "ако је вредност тачна, онда изврши први блок наредби, У супротном, изврши други блок наредби.", - "CONTROLS_IF_TOOLTIP_3": "Ако је прва вредност тачна, онда изврши први блок наредби, у супротном, ако је друга вредност тачна , изврши други блок наредби.", - "CONTROLS_IF_TOOLTIP_4": "Ако је прва вредност тачна, онда изврши први блок наредби, у супротном, ако је друга вредност тачна , изврши други блок наредби. Ако ни једна од вредности није тачна, изврши последнји блок наредби.", - "CONTROLS_IF_MSG_IF": "ако", - "CONTROLS_IF_MSG_ELSEIF": "иначе-ако", - "CONTROLS_IF_MSG_ELSE": "иначе", - "CONTROLS_IF_IF_TOOLTIP": "Додај, уклони, или преуреди делове како бих реконфигурисали овај иф блок.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Додајте услов блоку „ако“.", - "CONTROLS_IF_ELSE_TOOLTIP": "Додај коначни, catch-all (ухвати све) услове иф блока.", - "LOGIC_COMPARE_HELPURL": "https://sr.wikipedia.org/wiki/Неједнакост", - "LOGIC_COMPARE_TOOLTIP_EQ": "Враћа вредност „тачно“ ако су оба улаза једнака.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Враћа вредност „тачно“ ако су оба улаза неједнака.", - "LOGIC_COMPARE_TOOLTIP_LT": "Враћа вредност „тачно“ ако је први улаз мањи од другог.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Враћа вредност „тачно“ ако је први улаз мањи или једнак другом.", - "LOGIC_COMPARE_TOOLTIP_GT": "Враћа вредност „тачно“ ако је први улаз већи од другог.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Враћа вредност „тачно“ ако је први улаз већи или једнак другом.", - "LOGIC_OPERATION_TOOLTIP_AND": "Враћа вредност „тачно“ ако су оба улаза тачна.", - "LOGIC_OPERATION_AND": "и", - "LOGIC_OPERATION_TOOLTIP_OR": "Враћа вредност „тачно“ ако је бар један од улаза тачан.", - "LOGIC_OPERATION_OR": "или", - "LOGIC_NEGATE_TITLE": "није %1", - "LOGIC_NEGATE_TOOLTIP": "Враћа вредност „тачно“ ако је улаз нетачан. Враћа вредност „нетачно“ ако је улаз тачан.", - "LOGIC_BOOLEAN_TRUE": "тачно", - "LOGIC_BOOLEAN_FALSE": "нетачно", - "LOGIC_BOOLEAN_TOOLTIP": "враћа вредност или тачно или нетачно.", - "LOGIC_NULL_HELPURL": "https://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "без вредности", - "LOGIC_NULL_TOOLTIP": "Враћа „без вредности“.", - "LOGIC_TERNARY_HELPURL": "https://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "тест", - "LOGIC_TERNARY_IF_TRUE": "ако је тачно", - "LOGIC_TERNARY_IF_FALSE": "ако је нетачно", - "LOGIC_TERNARY_TOOLTIP": "Провери услов у 'test'. Ако је услов тачан, тада враћа 'if true' вредност; у другом случају враћа 'if false' вредност.", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "Неки број.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "син", - "MATH_TRIG_COS": "цос", - "MATH_TRIG_TAN": "тан", - "MATH_TRIG_ASIN": "арц син", - "MATH_TRIG_ACOS": "арц цос", - "MATH_TRIG_ATAN": "арц тан", - "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/Arithmetic", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Вратите збир два броја.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Враћа разлику два броја.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Враћа производ два броја.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Враћа количник два броја.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Враћа први број степенован другим.", - "MATH_SINGLE_HELPURL": "https://sr.wikipedia.org/wiki/Квадратни_корен", - "MATH_SINGLE_OP_ROOT": "квадратни корен", - "MATH_SINGLE_TOOLTIP_ROOT": "Враћа квадратни корен броја.", - "MATH_SINGLE_OP_ABSOLUTE": "апсолутан", - "MATH_SINGLE_TOOLTIP_ABS": "Враћа апсолутну вредност броја.", - "MATH_SINGLE_TOOLTIP_NEG": "Враћа негацију броја.", - "MATH_SINGLE_TOOLTIP_LN": "Враћа природни логаритам броја.", - "MATH_SINGLE_TOOLTIP_LOG10": "Враћа логаритам броја са основом 10.", - "MATH_SINGLE_TOOLTIP_EXP": "вратити е на власти броја.", - "MATH_SINGLE_TOOLTIP_POW10": "Враћа 10-ти степен броја.", - "MATH_TRIG_HELPURL": "https://sr.wikipedia.org/wiki/Тригонометријске_функције", - "MATH_TRIG_TOOLTIP_SIN": "Враћа синус степена (не радијан).", - "MATH_TRIG_TOOLTIP_COS": "Враћа косинус степена (не радијан).", - "MATH_TRIG_TOOLTIP_TAN": "Враћа тангенс степена (не радијан).", - "MATH_TRIG_TOOLTIP_ASIN": "Враћа аркус броја.", - "MATH_TRIG_TOOLTIP_ACOS": "Враћа аркус косинус броја.", - "MATH_TRIG_TOOLTIP_ATAN": "Враћа аркус тангенс броја.", - "MATH_CONSTANT_HELPURL": "https://sr.wikipedia.org/wiki/Математичка_константа", - "MATH_CONSTANT_TOOLTIP": "врати једну од заједничких константи: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), или ∞ (infinity).", - "MATH_IS_EVEN": "је паран", - "MATH_IS_ODD": "је непаран", - "MATH_IS_PRIME": "је прост", - "MATH_IS_WHOLE": "је цео", - "MATH_IS_POSITIVE": "је позитиван", - "MATH_IS_NEGATIVE": "је негативан", - "MATH_IS_DIVISIBLE_BY": "је дељив са", - "MATH_IS_TOOLTIP": "Провјерава да ли је број паран, непаран, прост, цио, позитиван, негативан, или да ли је делјив са одређеним бројем. Враћа тачно или нетачно.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "промени %1 за %2", - "MATH_CHANGE_TOOLTIP": "Додајте број променљивој „%1“.", - "MATH_ROUND_HELPURL": "https://sr.wikipedia.org/wiki/Заокруживање", - "MATH_ROUND_TOOLTIP": "Заокружите број на већу или мању вредност.", - "MATH_ROUND_OPERATOR_ROUND": "заокружи", - "MATH_ROUND_OPERATOR_ROUNDUP": "заокружи навише", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "заокружи наниже", - "MATH_ONLIST_HELPURL": "", - "MATH_ONLIST_OPERATOR_SUM": "збир списка", - "MATH_ONLIST_TOOLTIP_SUM": "Враћа збир свих бројева са списка.", - "MATH_ONLIST_OPERATOR_MIN": "мин. списка", - "MATH_ONLIST_TOOLTIP_MIN": "Враћа најмањи број са списка.", - "MATH_ONLIST_OPERATOR_MAX": "макс. списка", - "MATH_ONLIST_TOOLTIP_MAX": "Враћа највећи број са списка.", - "MATH_ONLIST_OPERATOR_AVERAGE": "просек списка", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Враћа просек нумеричких вредности са списка.", - "MATH_ONLIST_OPERATOR_MEDIAN": "медијана списка", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Враћа медијану са списка.", - "MATH_ONLIST_OPERATOR_MODE": "модус списка", - "MATH_ONLIST_TOOLTIP_MODE": "Враћа најчешће ставке са списка.", - "MATH_ONLIST_OPERATOR_STD_DEV": "стандардна девијација списка", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Враћа стандардну девијацију списка.", - "MATH_ONLIST_OPERATOR_RANDOM": "случајна ставка списка", - "MATH_ONLIST_TOOLTIP_RANDOM": "Враћа случајни елемент са списка.", - "MATH_MODULO_HELPURL": "https://sr.wikipedia.org/wiki/Конгруенција", - "MATH_MODULO_TITLE": "подсетник од %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Враћа подсетник од дељења два броја.", - "MATH_CONSTRAIN_TITLE": "ограничи %1 ниско %2 високо %3", - "MATH_CONSTRAIN_TOOLTIP": "Ограничава број на доње и горње границе (укључиво).", - "MATH_RANDOM_INT_HELPURL": "https://sr.wikipedia.org/wiki/Генератор_случајних_бројева", - "MATH_RANDOM_INT_TITLE": "сличајно одабрани цијели број од %1 до %2", - "MATH_RANDOM_INT_TOOLTIP": "Враћа случајно одабрани цели број између две одређене границе, уклјучиво.", - "MATH_RANDOM_FLOAT_HELPURL": "https://sr.wikipedia.org/wiki/Генератор_случајних_бројева", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "случајни разломак", - "MATH_RANDOM_FLOAT_TOOLTIP": "Враћа случајни разломак између 0.0 (укључиво) и 1.0 (искључиво).", - "TEXT_TEXT_HELPURL": "https://sr.wikipedia.org/wiki/Ниска", - "TEXT_TEXT_TOOLTIP": "Слово, реч или ред текста.", - "TEXT_JOIN_TITLE_CREATEWITH": "напиши текст са", - "TEXT_JOIN_TOOLTIP": "Направити дио текста спајајући различите ставке.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "спајањем", - "TEXT_CREATE_JOIN_TOOLTIP": "Додај, уклони, или другачије поредај одјелке како би изнова поставили овај текст блок.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Додајте ставку у текст.", - "TEXT_APPEND_TO": "на", - "TEXT_APPEND_APPENDTEXT": "додај текст", - "TEXT_APPEND_TOOLTIP": "Додајте текст на променљиву „%1“.", - "TEXT_LENGTH_TITLE": "дужина текста %1", - "TEXT_LENGTH_TOOLTIP": "Враћа број слова (уклјучујући размаке) у датом тексту.", - "TEXT_ISEMPTY_TITLE": "%1 је празан", - "TEXT_ISEMPTY_TOOLTIP": "Враћа тачно ако је доставлјени текст празан.", - "TEXT_INDEXOF_TOOLTIP": "Враћа однос првог/заднјег појавлјиванја текста у другом тексту. Врађа %1 ако текст није пронађен.", - "TEXT_INDEXOF_INPUT_INTEXT": "у тексту", - "TEXT_INDEXOF_OPERATOR_FIRST": "пронађи прво појављивање текста", - "TEXT_INDEXOF_OPERATOR_LAST": "пронађи последње појављивање текста", - "TEXT_INDEXOF_TAIL": "", - "TEXT_CHARAT_INPUT_INTEXT": "у тексту", - "TEXT_CHARAT_FROM_START": "преузми слово #", - "TEXT_CHARAT_FROM_END": "преузми слово # са краја", - "TEXT_CHARAT_FIRST": "преузми прво слово", - "TEXT_CHARAT_LAST": "преузми последње слово", - "TEXT_CHARAT_RANDOM": "преузми случајно слово", - "TEXT_CHARAT_TAIL": "", - "TEXT_CHARAT_TOOLTIP": "Враћа слово на одређени положај.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Враћа одређени део текста.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "у тексту", - "TEXT_GET_SUBSTRING_START_FROM_START": "преузми подниску из слова #", - "TEXT_GET_SUBSTRING_START_FROM_END": "преузми подниску из слова # са краја", - "TEXT_GET_SUBSTRING_START_FIRST": "преузми подниску из првог слова", - "TEXT_GET_SUBSTRING_END_FROM_START": "слову #", - "TEXT_GET_SUBSTRING_END_FROM_END": "слову # са краја", - "TEXT_GET_SUBSTRING_END_LAST": "последњем слову", - "TEXT_GET_SUBSTRING_TAIL": "", - "TEXT_CHANGECASE_TOOLTIP": "Враћа примерак текста са другачијом величином слова.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "великим словима", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "малим словима", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "свака реч великим словом", - "TEXT_TRIM_TOOLTIP": "Враћа копију текста са уклонјеним простором са једног од два краја.", - "TEXT_TRIM_OPERATOR_BOTH": "трим празнине са обе стране", - "TEXT_TRIM_OPERATOR_LEFT": "скратити простор са леве стране", - "TEXT_TRIM_OPERATOR_RIGHT": "скратити простор са десне стране", - "TEXT_PRINT_TITLE": "прикажи %1", - "TEXT_PRINT_TOOLTIP": "Прикажите одређени текст, број или другу вредност на екрану.", - "TEXT_PROMPT_TYPE_TEXT": "питај за текст са поруком", - "TEXT_PROMPT_TYPE_NUMBER": "питај за број са поруком", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Питајте корисника за број.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Питајте корисника за унос текста.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "направи празан списак", - "LISTS_CREATE_EMPTY_TOOLTIP": "враћа листу, дужине 0, не садржавајући евиденцију података", - "LISTS_CREATE_WITH_TOOLTIP": "Креирај листу са било којим бројем ставки.", - "LISTS_CREATE_WITH_INPUT_WITH": "направи списак са", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "списак", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Додајте, избришите, или преуредите делове како би се реорганизовали овај блок листе.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Додајте ставку на списак.", - "LISTS_REPEAT_TOOLTIP": "Прави листу која се састоји од задане вредности коју понавлјамо одређени број шута.", - "LISTS_REPEAT_TITLE": "Направити листу са ставком %1 која се понавлја %2 пута", - "LISTS_LENGTH_TITLE": "дужина списка %1", - "LISTS_LENGTH_TOOLTIP": "Враћа дужину списка.", - "LISTS_ISEMPTY_TITLE": "%1 је празан", - "LISTS_ISEMPTY_TOOLTIP": "Враћа вредност тачно ако је листа празна.", - "LISTS_INLIST": "на списку", - "LISTS_INDEX_OF_FIRST": "пронађи прво појављивање ставке", - "LISTS_INDEX_OF_LAST": "пронађи последње појављивање ставке", - "LISTS_INDEX_OF_TOOLTIP": "Враћа број првог и/последњег уласка елемента у листу. Враћа %1 Ако елемент није пронађен.", - "LISTS_GET_INDEX_GET": "преузми", - "LISTS_GET_INDEX_GET_REMOVE": "преузми и уклони", - "LISTS_GET_INDEX_REMOVE": "уклони", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# са краја", - "LISTS_GET_INDEX_FIRST": "прва", - "LISTS_GET_INDEX_LAST": "последња", - "LISTS_GET_INDEX_RANDOM": "случајна", - "LISTS_GET_INDEX_TAIL": "", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 је прва ставка.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 је последња ставка.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Враћа ставку на одређену позицију на листи.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Враћа прву ставку на списку.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Враћа последњу ставку на списку.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Враћа случајну ставку са списка.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Уклања и враћа ставку са одређеног положаја на списку.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Уклања и враћа прву ставку са списка.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Уклања и враћа последњу ставку са списка.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Уклања и враћа случајну ставку са списка.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Уклања ставку са одређеног положаја на списку.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Уклања прву ставку са списка.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Уклања последњу ставку са списка.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Уклања случајну ставку са списка.", - "LISTS_SET_INDEX_SET": "постави", - "LISTS_SET_INDEX_INSERT": "убаци на", - "LISTS_SET_INDEX_INPUT_TO": "као", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Поставља ставку на одређени положај на списку.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Поставља прву ставку на списку.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Поставља последњу ставку на списку.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Поставља случајну ставку на списку.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Убацује ставку на одређени положај на списку.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Убацује ставку на почетак списка.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Додајте ставку на крај списка.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Убацује ставку на случајно место на списку.", - "LISTS_GET_SUBLIST_START_FROM_START": "преузми подсписак од #", - "LISTS_GET_SUBLIST_START_FROM_END": "преузми подсписак из # са краја", - "LISTS_GET_SUBLIST_START_FIRST": "преузми подсписак од прве", - "LISTS_GET_SUBLIST_END_FROM_START": "до #", - "LISTS_GET_SUBLIST_END_FROM_END": "до # од краја", - "LISTS_GET_SUBLIST_END_LAST": "до последње", - "LISTS_GET_SUBLIST_TAIL": "", - "LISTS_GET_SUBLIST_TOOLTIP": "Прави копију одређеног дела листе.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "сортирај %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Сортирајте копију списка.", - "LISTS_SPLIT_LIST_FROM_TEXT": "направите листу са текста", - "LISTS_SPLIT_TEXT_FROM_LIST": "да текст из листе", - "LISTS_SPLIT_WITH_DELIMITER": "са раздвајање", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Поделити текст у листу текстова, разбијање на сваком граничник.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Да се придружи листу текстова у један текст, подељених за раздвајање.", - "ORDINAL_NUMBER_SUFFIX": "", - "VARIABLES_GET_TOOLTIP": "Враћа вредност ове променљиве.", - "VARIABLES_GET_CREATE_SET": "Направи „постави %1“", - "VARIABLES_SET": "постави %1 у %2", - "VARIABLES_SET_TOOLTIP": "Поставља променљиву тако да буде једнака улазу.", - "VARIABLES_SET_CREATE_GET": "Направи „преузми %1“", - "PROCEDURES_DEFNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFNORETURN_TITLE": "да", - "PROCEDURES_DEFNORETURN_PROCEDURE": "урадите нешто", - "PROCEDURES_BEFORE_PARAMS": "са:", - "PROCEDURES_CALL_BEFORE_PARAMS": "са:", - "PROCEDURES_DEFNORETURN_DO": "", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Прави функцију без излаза.", - "PROCEDURES_DEFNORETURN_COMMENT": "Описати ову функцију...", - "PROCEDURES_DEFRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFRETURN_RETURN": "врати", - "PROCEDURES_DEFRETURN_TOOLTIP": "Прави функцију са излазом.", - "PROCEDURES_ALLOW_STATEMENTS": "дозволити изреке", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Упозорење: Ова функција има дупликате параметара.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://sr.wikipedia.org/wiki/Функција_(програмирање)", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Покрените прилагођену функцију „%1“.", - "PROCEDURES_CALLRETURN_HELPURL": "https://sr.wikipedia.org/wiki/Функција_(програмирање)", - "PROCEDURES_CALLRETURN_TOOLTIP": "Покрените прилагођену функцију „%1“ и користи њен излаз.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "улази", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Да додате, уклоните или переупорядочить улаза за ову функцију.", - "PROCEDURES_MUTATORARG_TITLE": "назив улаза:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Додајте улазна функција.", - "PROCEDURES_HIGHLIGHT_DEF": "Истакни дефиницију функције", - "PROCEDURES_CREATE_DO": "Направи „%1“", - "PROCEDURES_IFRETURN_TOOLTIP": "Уколико је вредност тачна, врати другу вредност.", - "PROCEDURES_IFRETURN_WARNING": "Упозорење: Овај блок се може користити једино у дефиницији функције." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/sv.json b/backend/_pv_1_3_5/static/blockly/msg/json/sv.json deleted file mode 100755 index 16ebd71e5..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/sv.json +++ /dev/null @@ -1,337 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Jopparn", - "WikiPhoenix", - "Abbedabb", - "Aaoo", - "아라" - ] - }, - "VARIABLES_DEFAULT_NAME": "föremål", - "TODAY": "Idag", - "DUPLICATE_BLOCK": "Duplicera", - "ADD_COMMENT": "Lägg till kommentar", - "REMOVE_COMMENT": "Radera kommentar", - "EXTERNAL_INPUTS": "Externa inmatningar", - "INLINE_INPUTS": "Radinmatning", - "DELETE_BLOCK": "Radera block", - "DELETE_X_BLOCKS": "Radera %1 block", - "DELETE_ALL_BLOCKS": "Radera alla %1 block?", - "CLEAN_UP": "Rada upp block", - "COLLAPSE_BLOCK": "Fäll ihop block", - "COLLAPSE_ALL": "Fäll ihop block", - "EXPAND_BLOCK": "Fäll ut block", - "EXPAND_ALL": "Fäll ut block", - "DISABLE_BLOCK": "Inaktivera block", - "ENABLE_BLOCK": "Aktivera block", - "HELP": "Hjälp", - "UNDO": "Ångra", - "REDO": "Gör om", - "CHANGE_VALUE_TITLE": "Ändra värde:", - "RENAME_VARIABLE": "Byt namn på variabel...", - "RENAME_VARIABLE_TITLE": "Byt namn på alla'%1'-variabler till:", - "NEW_VARIABLE": "Skapa variabel...", - "NEW_VARIABLE_TITLE": "Nytt variabelnamn:", - "VARIABLE_ALREADY_EXISTS": "En variabel som heter \"%1\" finns redan.", - "DELETE_VARIABLE_CONFIRMATION": "Radera %1 användningar av variabeln \"%2\"?", - "DELETE_VARIABLE": "Radera variabeln \"%1\"", - "COLOUR_PICKER_HELPURL": "https://sv.wikipedia.org/wiki/Färg", - "COLOUR_PICKER_TOOLTIP": "Välj en färg från paletten.", - "COLOUR_RANDOM_TITLE": "slumpfärg", - "COLOUR_RANDOM_TOOLTIP": "Slumpa fram en färg.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "färg med", - "COLOUR_RGB_RED": "röd", - "COLOUR_RGB_GREEN": "grön", - "COLOUR_RGB_BLUE": "blå", - "COLOUR_RGB_TOOLTIP": "Skapa en färg med det angivna mängden röd, grön och blå. Alla värden måste vara mellan 0 och 100.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "blanda", - "COLOUR_BLEND_COLOUR1": "färg 1", - "COLOUR_BLEND_COLOUR2": "färg 2", - "COLOUR_BLEND_RATIO": "förhållande", - "COLOUR_BLEND_TOOLTIP": "Blandar ihop två färger med ett bestämt förhållande (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "upprepa %1 gånger", - "CONTROLS_REPEAT_INPUT_DO": "utför", - "CONTROLS_REPEAT_TOOLTIP": "Utför några kommandon flera gånger.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "upprepa medan", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "upprepa tills", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Medan ett värde är sant, utför några kommandon.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Medan ett värde är falskt, utför några kommandon.", - "CONTROLS_FOR_TOOLTIP": "Låt variabeln \"%1\" ta värden från starttalet till sluttalet, beräknat med det angivna intervallet, och utför de angivna blocken.", - "CONTROLS_FOR_TITLE": "räkna med %1 från %2 till %3 med %4", - "CONTROLS_FOREACH_TITLE": "för varje föremål %1 i listan %2", - "CONTROLS_FOREACH_TOOLTIP": "För varje objekt i en lista, ange variabeln '%1' till objektet, och utför sedan några kommandon.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "bryt ut ur loop", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "fortsätta med nästa upprepning av loop", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Bryt ut ur den innehållande upprepningen.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Hoppa över resten av denna loop och fortsätt med nästa loop.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Varning: Detta block kan endast användas i en loop.", - "CONTROLS_IF_TOOLTIP_1": "Om ett värde är sant, utför några kommandon.", - "CONTROLS_IF_TOOLTIP_2": "Om värdet är sant, utför det första kommandoblocket. Annars utför det andra kommandoblocket.", - "CONTROLS_IF_TOOLTIP_3": "Om det första värdet är sant, utför det första kommandoblocket. Annars, om det andra värdet är sant, utför det andra kommandoblocket.", - "CONTROLS_IF_TOOLTIP_4": "Om det första värdet är sant, utför det första kommandoblocket. Annars, om det andra värdet är sant, utför det andra kommandoblocket. Om ingen av värdena är sanna, utför det sista kommandoblocket.", - "CONTROLS_IF_MSG_IF": "om", - "CONTROLS_IF_MSG_ELSEIF": "annars om", - "CONTROLS_IF_MSG_ELSE": "annars", - "CONTROLS_IF_IF_TOOLTIP": "Lägg till, ta bort eller ändra ordningen för sektioner för att omkonfigurera blocket \"om\".", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Lägg till ett villkor blocket \"om\".", - "CONTROLS_IF_ELSE_TOOLTIP": "Lägg till ett sista villkor som täcker alla alternativ som är kvar för \"if\"-blocket.", - "LOGIC_COMPARE_HELPURL": "https://sv.wikipedia.org/wiki/Olikhet", - "LOGIC_COMPARE_TOOLTIP_EQ": "Ger tillbaka sant om båda värdena är lika med varandra.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Ger tillbaka sant om båda värdena inte är lika med varandra.", - "LOGIC_COMPARE_TOOLTIP_LT": "Ger tillbaka sant om det första värdet är mindre än det andra.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Ger tillbaka sant om det första värdet är mindre än eller lika med det andra.", - "LOGIC_COMPARE_TOOLTIP_GT": "Ger tillbaka sant om det första värdet är större än det andra.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Ger tillbaka sant om det första värdet är större än eller lika med det andra.", - "LOGIC_OPERATION_TOOLTIP_AND": "Ger tillbaka sant om båda värdena är sanna.", - "LOGIC_OPERATION_AND": "och", - "LOGIC_OPERATION_TOOLTIP_OR": "Ger tillbaka sant om minst ett av värdena är sant.", - "LOGIC_OPERATION_OR": "eller", - "LOGIC_NEGATE_TITLE": "inte %1", - "LOGIC_NEGATE_TOOLTIP": "Ger tillbaka sant om inmatningen är falsk. Ger tillbaka falskt och inmatningen är sann.", - "LOGIC_BOOLEAN_TRUE": "sant", - "LOGIC_BOOLEAN_FALSE": "falskt", - "LOGIC_BOOLEAN_TOOLTIP": "Returnerar antingen sant eller falskt.", - "LOGIC_NULL_HELPURL": "https://sv.wikipedia.org/wiki/Null", - "LOGIC_NULL": "null", - "LOGIC_NULL_TOOLTIP": "Returnerar null.", - "LOGIC_TERNARY_HELPURL": "https://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "om sant", - "LOGIC_TERNARY_IF_FALSE": "om falskt", - "LOGIC_TERNARY_TOOLTIP": "Kontrollera villkoret i \"test\". Om villkoret är sant, ge tillbaka \"om sant\"-värdet; annars ge tillbaka \"om falskt\"-värdet.", - "MATH_NUMBER_HELPURL": "https://sv.wikipedia.org/wiki/Tal", - "MATH_NUMBER_TOOLTIP": "Ett tal.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tan", - "MATH_TRIG_ASIN": "arcsin", - "MATH_TRIG_ACOS": "arccos", - "MATH_TRIG_ATAN": "arctan", - "MATH_ARITHMETIC_HELPURL": "https://sv.wikipedia.org/wiki/Aritmetik", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Returnerar summan av de två talen.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Returnerar differensen mellan de två talen.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Returnerar produkten av de två talen.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Returnerar kvoten av de två talen.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Ger tillbaka det första talet upphöjt till det andra talet.", - "MATH_SINGLE_HELPURL": "https://sv.wikipedia.org/wiki/Kvadratrot", - "MATH_SINGLE_OP_ROOT": "kvadratrot", - "MATH_SINGLE_TOOLTIP_ROOT": "Returnerar kvadratroten av ett tal.", - "MATH_SINGLE_OP_ABSOLUTE": "absolut", - "MATH_SINGLE_TOOLTIP_ABS": "Returnerar absolutvärdet av ett tal.", - "MATH_SINGLE_TOOLTIP_NEG": "Returnerar negationen av ett tal.", - "MATH_SINGLE_TOOLTIP_LN": "Returnera den naturliga logaritmen av ett tal.", - "MATH_SINGLE_TOOLTIP_LOG10": "Returnerar logaritmen för bas 10 av ett tal.", - "MATH_SINGLE_TOOLTIP_EXP": "Ger tillbaka e upphöjt i ett tal.", - "MATH_SINGLE_TOOLTIP_POW10": "Ger tillbaka 10 upphöjt i ett tal.", - "MATH_TRIG_HELPURL": "https://sv.wikipedia.org/wiki/Trigonometrisk_funktion", - "MATH_TRIG_TOOLTIP_SIN": "Ger tillbaka sinus för en grad (inte radian).", - "MATH_TRIG_TOOLTIP_COS": "Ger tillbaka cosinus för en grad (inte radian).", - "MATH_TRIG_TOOLTIP_TAN": "Ger tillbaka tangens för en grad (inte radian).", - "MATH_TRIG_TOOLTIP_ASIN": "Ger tillbaka arcus sinus (arcsin) för ett tal.", - "MATH_TRIG_TOOLTIP_ACOS": "Ger tillbaka arcus cosinus (arccos) för ett tal.", - "MATH_TRIG_TOOLTIP_ATAN": "Ger tillbaka arcus tangens (arctan) av ett tal.", - "MATH_CONSTANT_HELPURL": "https://sv.wikipedia.org/wiki/Matematisk_konstant", - "MATH_CONSTANT_TOOLTIP": "Returnerar en av de vanliga konstanterna: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…) eller ∞ (oändligt).", - "MATH_IS_EVEN": "är jämnt", - "MATH_IS_ODD": "är ojämnt", - "MATH_IS_PRIME": "är ett primtal", - "MATH_IS_WHOLE": "är helt", - "MATH_IS_POSITIVE": "är positivt", - "MATH_IS_NEGATIVE": "är negativt", - "MATH_IS_DIVISIBLE_BY": "är delbart med", - "MATH_IS_TOOLTIP": "Kontrollera om ett tal är jämnt, ojämnt, helt, positivt, negativt eller det är delbart med ett bestämt tal. Returnerar med sant eller falskt.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "ändra %1 med %2", - "MATH_CHANGE_TOOLTIP": "Lägg till ett tal till variabeln '%1'.", - "MATH_ROUND_HELPURL": "https://sv.wikipedia.org/wiki/Avrundning", - "MATH_ROUND_TOOLTIP": "Avrunda ett tal uppåt eller nedåt.", - "MATH_ROUND_OPERATOR_ROUND": "avrunda", - "MATH_ROUND_OPERATOR_ROUNDUP": "avrunda uppåt", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "avrunda nedåt", - "MATH_ONLIST_OPERATOR_SUM": "summan av listan", - "MATH_ONLIST_TOOLTIP_SUM": "Ger tillbaka summan av alla talen i listan.", - "MATH_ONLIST_OPERATOR_MIN": "minsta talet i listan", - "MATH_ONLIST_TOOLTIP_MIN": "Ger tillbaka det minsta talet i listan.", - "MATH_ONLIST_OPERATOR_MAX": "högsta talet i listan", - "MATH_ONLIST_TOOLTIP_MAX": "Ger tillbaka det största talet i listan.", - "MATH_ONLIST_OPERATOR_AVERAGE": "medelvärdet av listan", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Ger tillbaka medelvärdet (aritmetiskt) av de numeriska värdena i listan.", - "MATH_ONLIST_OPERATOR_MEDIAN": "medianen av listan", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Returnerar medianen av talen i listan.", - "MATH_ONLIST_OPERATOR_MODE": "typvärdet i listan", - "MATH_ONLIST_TOOLTIP_MODE": "Ger tillbaka en lista med de(t) vanligaste objekte(t/n) i listan.", - "MATH_ONLIST_OPERATOR_STD_DEV": "standardavvikelsen i listan", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Ger tillbaka standardavvikelsen i listan.", - "MATH_ONLIST_OPERATOR_RANDOM": "slumpmässigt objekt i listan", - "MATH_ONLIST_TOOLTIP_RANDOM": "Returnerar ett slumpmässigt element från listan.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "resten av %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Returnerar kvoten från divisionen av de två talen.", - "MATH_CONSTRAIN_TITLE": "begränsa %1 till mellan %2 och %3", - "MATH_CONSTRAIN_TOOLTIP": "Begränsa ett tal till att mellan de angivna gränsvärden (inkluderande).", - "MATH_RANDOM_INT_HELPURL": "https://sv.wikipedia.org/wiki/Slumptalsgenerator", - "MATH_RANDOM_INT_TITLE": "slumpartat heltal från %1 till %2", - "MATH_RANDOM_INT_TOOLTIP": "Ger tillbaka ett slumpat heltal mellan två värden, inkluderande.", - "MATH_RANDOM_FLOAT_HELPURL": "https://sv.wikipedia.org/wiki/Slumptalsgenerator", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "slumpat decimaltal", - "MATH_RANDOM_FLOAT_TOOLTIP": "Ger tillbaka ett slumpat decimaltal mellan 0.0 (inkluderat) och 1.0 (exkluderat).", - "TEXT_TEXT_HELPURL": "https://sv.wikipedia.org/wiki/Str%C3%A4ng_%28data%29", - "TEXT_TEXT_TOOLTIP": "En bokstav, ord eller textrad.", - "TEXT_JOIN_TITLE_CREATEWITH": "skapa text med", - "TEXT_JOIN_TOOLTIP": "Skapa en textbit genom att sammanfoga ett valfritt antal föremål.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "sammanfoga", - "TEXT_CREATE_JOIN_TOOLTIP": "Lägg till, ta bort eller ändra ordningen för sektioner för att omkonfigurera detta textblock.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Lägg till ett föremål till texten.", - "TEXT_APPEND_TO": "till", - "TEXT_APPEND_APPENDTEXT": "lägg till text", - "TEXT_APPEND_TOOLTIP": "Lägg till lite text till variabeln '%1'.", - "TEXT_LENGTH_TITLE": "längden på %1", - "TEXT_LENGTH_TOOLTIP": "Ger tillbaka antalet bokstäver (inklusive mellanslag) i den angivna texten.", - "TEXT_ISEMPTY_TITLE": "%1 är tom", - "TEXT_ISEMPTY_TOOLTIP": "Returnerar sant om den angivna texten är tom.", - "TEXT_INDEXOF_TOOLTIP": "Ger tillbaka indexet för den första/sista förekomsten av första texten i den andra texten. Ger tillbaka %1 om texten inte hittas.", - "TEXT_INDEXOF_INPUT_INTEXT": "i texten", - "TEXT_INDEXOF_OPERATOR_FIRST": "hitta första förekomsten av texten", - "TEXT_INDEXOF_OPERATOR_LAST": "hitta sista förekomsten av texten", - "TEXT_CHARAT_INPUT_INTEXT": "i texten", - "TEXT_CHARAT_FROM_START": "hämta bokstaven #", - "TEXT_CHARAT_FROM_END": "hämta bokstaven # från slutet", - "TEXT_CHARAT_FIRST": "hämta första bokstaven", - "TEXT_CHARAT_LAST": "hämta sista bokstaven", - "TEXT_CHARAT_RANDOM": "hämta slumpad bokstav", - "TEXT_CHARAT_TOOLTIP": "Ger tillbaka bokstaven på den specificerade positionen.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Ger tillbaka en viss del av texten.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "i texten", - "TEXT_GET_SUBSTRING_START_FROM_START": "få textdel från bokstav #", - "TEXT_GET_SUBSTRING_START_FROM_END": "få textdel från bokstav # från slutet", - "TEXT_GET_SUBSTRING_START_FIRST": "få textdel från första bokstaven", - "TEXT_GET_SUBSTRING_END_FROM_START": "till bokstav #", - "TEXT_GET_SUBSTRING_END_FROM_END": "till bokstav # från slutet", - "TEXT_GET_SUBSTRING_END_LAST": "till sista bokstaven", - "TEXT_CHANGECASE_TOOLTIP": "Returnerar en kopia av texten i ett annat skiftläge.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "till VERSALER", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "till gemener", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "till Versala Initialer", - "TEXT_TRIM_TOOLTIP": "Returnerar en kopia av texten med borttagna mellanrum från en eller båda ändar.", - "TEXT_TRIM_OPERATOR_BOTH": "ta bort mellanrum från båda sidorna av", - "TEXT_TRIM_OPERATOR_LEFT": "ta bort mellanrum från vänstra sidan av", - "TEXT_TRIM_OPERATOR_RIGHT": "ta bort mellanrum från högra sidan av", - "TEXT_PRINT_TITLE": "skriv %1", - "TEXT_PRINT_TOOLTIP": "Skriv den angivna texten, talet eller annat värde.", - "TEXT_PROMPT_TYPE_TEXT": "fråga efter text med meddelande", - "TEXT_PROMPT_TYPE_NUMBER": "fråga efter ett tal med meddelande", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Fråga användaren efter ett tal.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Fråga användaren efter lite text.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "skapa tom lista", - "LISTS_CREATE_EMPTY_TOOLTIP": "Ger tillbaka en lista utan någon data, alltså med längden 0", - "LISTS_CREATE_WITH_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_CREATE_WITH_TOOLTIP": "Skapa en lista med valfritt antal föremål.", - "LISTS_CREATE_WITH_INPUT_WITH": "skapa lista med", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "lista", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Lägg till, ta bort eller ändra ordningen på objekten för att göra om det här \"list\"-blocket.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Lägg till ett föremål till listan.", - "LISTS_REPEAT_TOOLTIP": "Skapar en lista som innehåller ett valt värde upprepat ett bestämt antalet gånger.", - "LISTS_REPEAT_TITLE": "skapa lista med föremålet %1 upprepat %2 gånger", - "LISTS_LENGTH_TITLE": "längden på %1", - "LISTS_LENGTH_TOOLTIP": "Returnerar längden på en lista.", - "LISTS_ISEMPTY_TITLE": "%1 är tom", - "LISTS_ISEMPTY_TOOLTIP": "Returnerar sant om listan är tom.", - "LISTS_INLIST": "i listan", - "LISTS_INDEX_OF_FIRST": "hitta första förekomsten av objektet", - "LISTS_INDEX_OF_LAST": "hitta sista förekomsten av objektet", - "LISTS_INDEX_OF_TOOLTIP": "Ger tillbaka den första/sista förekomsten av objektet i listan. Returnerar %1 om objektet inte hittas.", - "LISTS_GET_INDEX_GET": "hämta", - "LISTS_GET_INDEX_GET_REMOVE": "hämta och ta bort", - "LISTS_GET_INDEX_REMOVE": "ta bort", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# från slutet", - "LISTS_GET_INDEX_FIRST": "första", - "LISTS_GET_INDEX_LAST": "sista", - "LISTS_GET_INDEX_RANDOM": "slumpad", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 är det första objektet.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 är det sista objektet.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Ger tillbaka objektet på den efterfrågade positionen i en lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Returnerar det första objektet i en lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Returnerar det sista objektet i en lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Returnerar ett slumpmässigt objekt i en lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Tar bort och återställer objektet på den specificerade positionen i en lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Tar bort och återställer det första objektet i en lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Tar bort och återställer det sista objektet i en lista.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Tar bort och återställer ett slumpmässigt objekt i en lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Tar bort objektet på den specificerade positionen i en lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Tar bort det första objektet i en lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Tar bort det sista objektet i en lista.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Tar bort en slumpmässig post i en lista.", - "LISTS_SET_INDEX_SET": "ange", - "LISTS_SET_INDEX_INSERT": "Sätt in vid", - "LISTS_SET_INDEX_INPUT_TO": "som", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Sätter in objektet vid en specificerad position i en lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Anger det första objektet i en lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Anger det sista elementet i en lista.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Sätter in ett slumpat objekt i en lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Sätter in objektet vid en specificerad position i en lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "sätter in objektet i början av en lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Lägg till objektet i slutet av en lista.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "sätter in objektet på en slumpad position i en lista.", - "LISTS_GET_SUBLIST_START_FROM_START": "få underlista från #", - "LISTS_GET_SUBLIST_START_FROM_END": "få underlista från # från slutet", - "LISTS_GET_SUBLIST_START_FIRST": "få underlista från första", - "LISTS_GET_SUBLIST_END_FROM_START": "till #", - "LISTS_GET_SUBLIST_END_FROM_END": "till # från slutet", - "LISTS_GET_SUBLIST_END_LAST": "till sista", - "LISTS_GET_SUBLIST_TOOLTIP": "Skapar en kopia av den specificerade delen av en lista.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "sortera %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Sortera en kopia av en lista.", - "LISTS_SORT_ORDER_ASCENDING": "stigande", - "LISTS_SORT_ORDER_DESCENDING": "fallande", - "LISTS_SORT_TYPE_NUMERIC": "numeriskt", - "LISTS_SORT_TYPE_TEXT": "alfabetiskt", - "LISTS_SORT_TYPE_IGNORECASE": "alfabetiskt, ignorera skiftläge", - "LISTS_SPLIT_HELPURL": "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists", - "LISTS_SPLIT_LIST_FROM_TEXT": "skapa lista från text", - "LISTS_SPLIT_TEXT_FROM_LIST": "skapa text från lista", - "LISTS_SPLIT_WITH_DELIMITER": "med avgränsare", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Dela upp text till en textlista och bryt vid varje avgränsare.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Sammanfoga en textlista till en text, som separeras av en avgränsare.", - "VARIABLES_GET_TOOLTIP": "Returnerar värdet av denna variabel.", - "VARIABLES_GET_CREATE_SET": "Skapa \"välj %1\"", - "VARIABLES_SET": "ange %1 till %2", - "VARIABLES_SET_TOOLTIP": "Gör så att den här variabeln blir lika med inputen.", - "VARIABLES_SET_CREATE_GET": "Skapa 'hämta %1'", - "PROCEDURES_DEFNORETURN_HELPURL": "https://sv.wikipedia.org/wiki/Funktion_%28programmering%29", - "PROCEDURES_DEFNORETURN_TITLE": "för att", - "PROCEDURES_DEFNORETURN_PROCEDURE": "göra något", - "PROCEDURES_BEFORE_PARAMS": "med:", - "PROCEDURES_CALL_BEFORE_PARAMS": "med:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Skapar en funktion utan output.", - "PROCEDURES_DEFNORETURN_COMMENT": "Beskriv denna funktion...", - "PROCEDURES_DEFRETURN_HELPURL": "https://sv.wikipedia.org/wiki/Funktion_%28programmering%29", - "PROCEDURES_DEFRETURN_RETURN": "returnera", - "PROCEDURES_DEFRETURN_TOOLTIP": "Skapar en funktion med output.", - "PROCEDURES_ALLOW_STATEMENTS": "tillåta uttalanden", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Varning: Denna funktion har dubbla parametrar.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://sv.wikipedia.org/wiki/Funktion_%28programmering%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Kör den användardefinierade funktionen \"%1\".", - "PROCEDURES_CALLRETURN_HELPURL": "https://sv.wikipedia.org/wiki/Funktion_%28programmering%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Kör den användardefinierade funktionen \"%1\" och använd resultatet av den.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "inmatningar", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Lägg till, ta bort och ändra ordningen för inmatningar till denna funktion.", - "PROCEDURES_MUTATORARG_TITLE": "inmatningsnamn:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Lägg till en inmatning till funktionen.", - "PROCEDURES_HIGHLIGHT_DEF": "Markera funktionsdefinition", - "PROCEDURES_CREATE_DO": "Skapa '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "Om ett värde är sant returneras ett andra värde.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Varning: Detta block får användas endast i en funktionsdefinition." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/synonyms.json b/backend/_pv_1_3_5/static/blockly/msg/json/synonyms.json deleted file mode 100755 index 944aa9bda..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/synonyms.json +++ /dev/null @@ -1 +0,0 @@ -{"PROCEDURES_DEFRETURN_TITLE": "PROCEDURES_DEFNORETURN_TITLE", "CONTROLS_IF_IF_TITLE_IF": "CONTROLS_IF_MSG_IF", "CONTROLS_WHILEUNTIL_INPUT_DO": "CONTROLS_REPEAT_INPUT_DO", "CONTROLS_IF_MSG_THEN": "CONTROLS_REPEAT_INPUT_DO", "LISTS_GET_SUBLIST_INPUT_IN_LIST": "LISTS_INLIST", "CONTROLS_IF_ELSE_TITLE_ELSE": "CONTROLS_IF_MSG_ELSE", "PROCEDURES_DEFRETURN_PROCEDURE": "PROCEDURES_DEFNORETURN_PROCEDURE", "TEXT_CREATE_JOIN_ITEM_TITLE_ITEM": "VARIABLES_DEFAULT_NAME", "LISTS_GET_INDEX_INPUT_IN_LIST": "LISTS_INLIST", "PROCEDURES_DEFRETURN_COMMENT": "PROCEDURES_DEFNORETURN_COMMENT", "CONTROLS_IF_ELSEIF_TITLE_ELSEIF": "CONTROLS_IF_MSG_ELSEIF", "PROCEDURES_DEFRETURN_DO": "PROCEDURES_DEFNORETURN_DO", "CONTROLS_FOR_INPUT_DO": "CONTROLS_REPEAT_INPUT_DO", "LISTS_GET_INDEX_HELPURL": "LISTS_INDEX_OF_HELPURL", "LISTS_INDEX_OF_INPUT_IN_LIST": "LISTS_INLIST", "CONTROLS_FOREACH_INPUT_DO": "CONTROLS_REPEAT_INPUT_DO", "LISTS_CREATE_WITH_ITEM_TITLE": "VARIABLES_DEFAULT_NAME", "TEXT_APPEND_VARIABLE": "VARIABLES_DEFAULT_NAME", "MATH_CHANGE_TITLE_ITEM": "VARIABLES_DEFAULT_NAME", "LISTS_SET_INDEX_INPUT_IN_LIST": "LISTS_INLIST"} \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/ta.json b/backend/_pv_1_3_5/static/blockly/msg/json/ta.json deleted file mode 100755 index 84b90bb57..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/ta.json +++ /dev/null @@ -1,298 +0,0 @@ -{ - "@metadata": { - "authors": [ - "ElangoRamanujam", - "Ezhillang", - "Karuthan", - "Thangamani-arun", - "Mahir78" - ] - }, - "VARIABLES_DEFAULT_NAME": "உருப்படி", - "TODAY": "இன்று", - "DUPLICATE_BLOCK": "மறுநகல்", - "ADD_COMMENT": "கருத்தை சேர்", - "REMOVE_COMMENT": "கருத்தை நீக்கு", - "EXTERNAL_INPUTS": "வெளி கருவிகளுடன் உள்ளீடு", - "INLINE_INPUTS": "சூழமைவில் உள்ளீடு", - "DELETE_BLOCK": "உறுப்பை நீக்கு", - "DELETE_X_BLOCKS": "%1 உறுப்பை நீக்கு", - "DELETE_ALL_BLOCKS": "அனைத்து %1 நிரல் துண்டுகளையும் அழிக்கவா??", - "COLLAPSE_BLOCK": "உறுப்பை மரை", - "COLLAPSE_ALL": "உறுப்புகளை மரை", - "EXPAND_BLOCK": "உறுப்பை காட்டு", - "EXPAND_ALL": "உறுப்புகளை காட்டு", - "DISABLE_BLOCK": "உறுப்பை இயங்காது செய்", - "ENABLE_BLOCK": "உறுப்பை இயங்குமாரு செய்", - "HELP": "உதவி", - "CHANGE_VALUE_TITLE": "மதிப்பை மாற்றவும்:", - "RENAME_VARIABLE": "மாறிலியை மறுபெயரிடுக...", - "RENAME_VARIABLE_TITLE": "அனைத்து '%1' மாறிலிகளையும் பின்வருமாறு மறுபெயரிடுக:", - "NEW_VARIABLE": "புதிய மாறிலி...", - "NEW_VARIABLE_TITLE": "புதிய மாறிலியின் பெயர்:", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "வண்ண தட்டிலிருந்து ஒரு நிறத்தைத் தேர்ந்தெடுக்கவும்.", - "COLOUR_RANDOM_TITLE": "தற்போக்கு நிறம்", - "COLOUR_RANDOM_TOOLTIP": "தற்போக்கில் ஒரு நிறத்தை தேர்ந்தெடுக்கவும்.", - "COLOUR_RGB_TITLE": "நிறத்துடன்", - "COLOUR_RGB_RED": "சிகப்பு", - "COLOUR_RGB_GREEN": "பச்சை", - "COLOUR_RGB_BLUE": "நீலம்", - "COLOUR_RGB_TOOLTIP": "குறிப்பிட்ட அளவு சிவப்பு,பச்சை மற்றும் நீலம் சேர்த்து புது நிறம் உருவாக்கு. மதிப்புகள் 0 முதல் 100 வரை மட்டுமே இருக்க வேண்டும்.", - "COLOUR_BLEND_TITLE": "கலப்பு (வண்ணம்)", - "COLOUR_BLEND_COLOUR1": "நிறம் 1", - "COLOUR_BLEND_COLOUR2": "நிறம் 2", - "COLOUR_BLEND_RATIO": "விகிதம்", - "COLOUR_BLEND_TOOLTIP": "கொடுக்கப்பட்ட விகதத்தில் (0.0 - 1.0) இரு நிறங்களை கலக்குக.", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "'%1' முரை திரும்ப செய்", - "CONTROLS_REPEAT_INPUT_DO": "செய்க", - "CONTROLS_REPEAT_TOOLTIP": "கட்டளைகளை பல முரை செய்ய", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "பலமுரை திரும்ப செய் (வரை)", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "பலமுரை திரும்ப செய் (முடயேனில்)", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "மாறி உண்மை ஆக உள்ள வரை, கட்டளைகளை இயக்கு", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "மாறி பொய் ஆக உள்ள வரை, கட்டளைகளை இயக்கு", - "CONTROLS_FOR_TOOLTIP": "முதல் எண்ணில் இருந்து கடை எண் வரை எடுத்துக்கொள்ள ஒரு மாறியை வைத்துக்கொள், குறித்த இடைவெளியை சேர்த்தவறே தொகுதிகளை செயலாக்கு.", - "CONTROLS_FOR_TITLE": "மாறியை வைத்து எண்ண %1 %2 இல் இருந்து %3 வரை %4-இன் படியாக", - "CONTROLS_FOREACH_TITLE": "உருப்படி ஒவ்வொன்றாக %1 பட்டியலில் உள்ள %2", - "CONTROLS_FOREACH_TOOLTIP": "பட்டியலில் உள்ள உருப்படியில் ஒவ்வொன்றாக, மாறியின் பொருள் '%1' ஆக வைக்க.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "மடக்கு கட்டளையை நிறுத்து.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "மடக்கு கட்டளையின் அடுத்த இயக்கநிலைக்கு செல்", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "மடக்கு கட்டளையின் இயக்கத்தில் இருந்து நிறுத்து.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "மடக்கு கட்டளையின் மீதியை விட்டுவிட்டு அடுத்த இயக்கநிலைக்கு செல்", - "CONTROLS_FLOW_STATEMENTS_WARNING": "எச்சரிக்கை : மடக்கு கூற்றில் இந்த தொகுதி ஒரு முறை மட்டுமே செயல்படுத்தப் படலாம்.", - "CONTROLS_IF_TOOLTIP_1": "மாறி உண்மை ஆக உள்ள வரை, கட்டளைகளை இயக்கு", - "CONTROLS_IF_TOOLTIP_2": "மாறி உண்மை ஆக உள்ள வரை, கட்டளைகளை இயக்கு. அல்லது மற்ற (அடுத்த) கட்டளைகளை இயக்கு.", - "CONTROLS_IF_TOOLTIP_3": "மாறி உண்மை ஆக உள்ள வரை, கட்டளைகளை தொகுப்பு இயக்கு. அல்லது மற்ற (அடுத்த) கட்டளைகளை தொகுப்பு இயக்கு.", - "CONTROLS_IF_TOOLTIP_4": "மாறி உண்மை ஆக உள்ள வரை, கட்டளைகளை தொகுப்பு இயக்கு. அல்லது மற்ற (அடுத்த) கட்டளைகளை தொகுப்பு இயக்கு. இரண்டும் இல்லை என்றால் கடைசி தொகுப்பு இயக்கு.", - "CONTROLS_IF_MSG_IF": "எனில்", - "CONTROLS_IF_MSG_ELSEIF": "இல்லைஆனால்", - "CONTROLS_IF_MSG_ELSE": "இல்லையெனில்", - "CONTROLS_IF_IF_TOOLTIP": "கட்டளைகளை தொகுப்பு திருத்துதம் செய்", - "CONTROLS_IF_ELSEIF_TOOLTIP": "ஆனால் தொகுப்பிற்கு நிபந்தனை சேர்க்க", - "CONTROLS_IF_ELSE_TOOLTIP": "ஆனால் தொகுப்பிற்கு விதிவிலக்கு காப்பை சேர்க்க", - "LOGIC_COMPARE_HELPURL": "https://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "இரண்டு மாறியும் ஈடானால், மெய் பின்கொடு.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "இரண்டு மாறியும் ஈடாகாவிட்டால், மெய் பின்கொடு.", - "LOGIC_COMPARE_TOOLTIP_LT": "முதல் உள்ளீடு இரண்டாவதைவிட குறைவாக இருந்தால், மெய் பின்கொடு.", - "LOGIC_COMPARE_TOOLTIP_LTE": "முதல் உள்ளீடு இரண்டாவதைவிட குறைவாக அல்ல சமமாக இருந்தால், மெய் பின்கொடு", - "LOGIC_COMPARE_TOOLTIP_GT": "முதல் உள்ளீடு இரண்டாவதைவிட அதிகமாக இருந்தால், மெய் பின்கொடு.", - "LOGIC_COMPARE_TOOLTIP_GTE": "முதல் உள்ளீடு இரண்டாவதைவிட அதிகமாக அல்ல சமமாக இருந்தால், மெய் பின்கொடு.", - "LOGIC_OPERATION_TOOLTIP_AND": "இரண்டு மாறியும் மெய் ஆனால், மெய் பின்கொடு.", - "LOGIC_OPERATION_AND": "மற்றும்", - "LOGIC_OPERATION_TOOLTIP_OR": "ஏதேனும் ஒரு மதிப்பு மெய் ஆனால், மெய் பின்கொடு", - "LOGIC_OPERATION_OR": "அல்லது", - "LOGIC_NEGATE_TITLE": "%1 இல்லை", - "LOGIC_NEGATE_TOOLTIP": "மெய் ஆனால், பொய் பின்கொடு. பொய் ஆனால், மெய் பின்கொடு.", - "LOGIC_BOOLEAN_TRUE": "மெய்", - "LOGIC_BOOLEAN_FALSE": "பொய்", - "LOGIC_BOOLEAN_TOOLTIP": "மெய், அல்லது பொய் பின்கொடு.", - "LOGIC_NULL": "பூஜியம்", - "LOGIC_NULL_TOOLTIP": "பூஜியம் பின்கொடு", - "LOGIC_TERNARY_CONDITION": "சோதனை", - "LOGIC_TERNARY_IF_TRUE": "மெய்யெனில்", - "LOGIC_TERNARY_IF_FALSE": "பொய்யெனில்", - "LOGIC_TERNARY_TOOLTIP": "'test' உள்ள நிபந்தனையை சரிபார்க்கவும், நிபந்தனை மெய்யானால்,'if true'வை பின்கொடுக்கும் இல்லையெனில் 'if false'வை பின்கொடுக்கும்.", - "MATH_NUMBER_HELPURL": "https://ta.wikipedia.org/wiki/%E0%AE%8E%E0%AE%A3%E0%AF%8D", - "MATH_NUMBER_TOOLTIP": "ஒரு எண்.", - "MATH_ARITHMETIC_HELPURL": "https://ta.wikipedia.org/wiki/%E0%AE%8E%E0%AE%A3%E0%AF%8D%E0%AE%95%E0%AE%A3%E0%AE%BF%E0%AE%A4%E0%AE%AE%E0%AF%8D", - "MATH_ARITHMETIC_TOOLTIP_ADD": "இரு எண்களின் கூட்டை பின்கொடு", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "இரு எண்களின் கழிப்பை பின்கொடு", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "இரு எண்களின் பெருக்கலை பின்கொடு", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "இரு எண்களின் வகுத்தல் பின்கொடு", - "MATH_ARITHMETIC_TOOLTIP_POWER": "முதல் உள்ளீடு இரண்டாவது எண் அளவான அடுக்கு பெருக்கை கணித்து பின்கொடு.", - "MATH_SINGLE_HELPURL": "https://ta.wikipedia.org/wiki/%E0%AE%B5%E0%AE%B0%E0%AF%8D%E0%AE%95%E0%AF%8D%E0%AE%95%E0%AE%AE%E0%AF%82%E0%AE%B2%E0%AE%AE%E0%AF%8D", - "MATH_SINGLE_OP_ROOT": "வர்க்கமூலம்", - "MATH_SINGLE_TOOLTIP_ROOT": "ஒரு எண்ணின் வர்க்கமூலத்தைத் தரும்.", - "MATH_SINGLE_OP_ABSOLUTE": "தனித்த", - "MATH_SINGLE_TOOLTIP_ABS": "ஒரு எண்ணின் தனித்த மதிப்பை பின்கொடு", - "MATH_SINGLE_TOOLTIP_NEG": "ஒரு எண்ணின் எதிர்மறை மதிப்பை பின்கொடு", - "MATH_SINGLE_TOOLTIP_LN": "ஒரு எண்ணின் (இயற்கை) மடக்கை மதிப்பை பின்கொடு.", - "MATH_SINGLE_TOOLTIP_LOG10": "ஒரு எண்ணின் (10) மடக்கை மதிப்பை பின்கொடு.", - "MATH_SINGLE_TOOLTIP_EXP": "e-இன் எண் அடுக்கு பெருக்கை பின்கொடு.", - "MATH_SINGLE_TOOLTIP_POW10": "10-இன் எண் அடுக்கு பெருக்கை பின்கொடு.", - "MATH_TRIG_HELPURL": "https://ta.wikipedia.org/wiki/%E0%AE%AE%E0%AF%81%E0%AE%95%E0%AF%8D%E0%AE%95%E0%AF%8B%E0%AE%A3%E0%AE%B5%E0%AE%BF%E0%AE%AF%E0%AE%B2%E0%AF%8D_%E0%AE%9A%E0%AE%BE%E0%AE%B0%E0%AF%8D%E0%AE%AA%E0%AF%81%E0%AE%95%E0%AE%B3%E0%AF%8D", - "MATH_TRIG_TOOLTIP_SIN": "டிகிரீ சைன் மதிப்பை பின்கொடு.", - "MATH_TRIG_TOOLTIP_COS": "டிகிரீ கோசைன் மதிப்பை பின்கொடு", - "MATH_TRIG_TOOLTIP_TAN": "டிகிரீ டேஞ்சன்டு மதிப்பை பின்கொடு", - "MATH_TRIG_TOOLTIP_ASIN": "மதிப்பின் நேர்மாறு சைன் பின்கொடு", - "MATH_TRIG_TOOLTIP_ACOS": "மதிப்பின் நேர்மாறு கோசைன் பின்கொடு", - "MATH_TRIG_TOOLTIP_ATAN": "மதிப்பின் நேர்மாறு டேஞ்சன்டு பின்கொடு", - "MATH_CONSTANT_HELPURL": "https://ta.wikipedia.org/wiki/%E0%AE%95%E0%AE%A3%E0%AE%BF%E0%AE%A4_%E0%AE%AE%E0%AE%BE%E0%AE%B1%E0%AE%BF%E0%AE%B2%E0%AE%BF", - "MATH_CONSTANT_TOOLTIP": "ஒரு மாறிலியை பின்கொடு π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (முடிவிலி).", - "MATH_IS_EVEN": "2-ஆல் பகும்", - "MATH_IS_ODD": "2-ஆல் பகாத", - "MATH_IS_PRIME": "எண் பகாத்தனிதானதா?", - "MATH_IS_WHOLE": "எண் முழுதானதா?", - "MATH_IS_POSITIVE": "எண் நேர்ம முழுதானதா ?", - "MATH_IS_NEGATIVE": "எண் குறைவானதா ?", - "MATH_IS_DIVISIBLE_BY": "ஆல் வகுபடக் கூடியது", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "மாற்று %1 மூலம் %2", - "MATH_CHANGE_TOOLTIP": "எண்னை '%1' மதிப்பால் கூட்டு,", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "மேல்/கீழ் வழி முழு எண் ஆக மாற்று.", - "MATH_ROUND_OPERATOR_ROUND": "முழுமையாக்கு", - "MATH_ROUND_OPERATOR_ROUNDUP": "மேல்வழி முழுமையாக்கு", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "கீழ்வழி முழுமையாக்கு", - "MATH_ONLIST_OPERATOR_SUM": "பட்டியலின் கூட்டு", - "MATH_ONLIST_TOOLTIP_SUM": "முழு பட்டியலின் எண் சமம் பின்கொடு,", - "MATH_ONLIST_OPERATOR_MIN": "பட்டியலின் கறைவு", - "MATH_ONLIST_TOOLTIP_MIN": "பட்டியலின் குறைவான எண் பின்கொடு", - "MATH_ONLIST_OPERATOR_MAX": "பட்டியலின் மிகுதி", - "MATH_ONLIST_TOOLTIP_MAX": "பட்டியலின் அதிகமான எண் பின்கொடு", - "MATH_ONLIST_OPERATOR_AVERAGE": "பட்டியலின் எண் சராசரி", - "MATH_ONLIST_TOOLTIP_AVERAGE": "முழு பட்டியலின் எண் சராசரி பின்கொடு", - "MATH_ONLIST_OPERATOR_MEDIAN": "பட்டியலின் நடுக்கோடு", - "MATH_ONLIST_TOOLTIP_MEDIAN": "பட்டியலின் நடுக்கோடு பின்கொடு", - "MATH_ONLIST_OPERATOR_MODE": "பட்டியலின் பொதுவகைகள்", - "MATH_ONLIST_TOOLTIP_MODE": "பட்டியலின் பொதுவகைகள் பின்கொடு", - "MATH_ONLIST_OPERATOR_STD_DEV": "பட்டியலின் நியமவிலகல்", - "MATH_ONLIST_TOOLTIP_STD_DEV": "பட்டியலின் நியமவிலகலை பின்கொடு.", - "MATH_ONLIST_OPERATOR_RANDOM": "ஒரு பட்டியலில் இருந்து சீரற்ற உருப்படி", - "MATH_ONLIST_TOOLTIP_RANDOM": "ஒரு பட்டியலில் இருந்து சீரற்ற உருப்படி பின்கொடு", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "%1 ÷ %2ன் மீதி", - "MATH_MODULO_TOOLTIP": "இரண்டு எண்கள் மூலம் பிரிவில் இருந்து எஞ்சியதை பின்கொடு.", - "MATH_CONSTRAIN_TITLE": "%1 மாறியை %2 மேலும் %3 கீழும் வற்புறுத்து", - "MATH_CONSTRAIN_TOOLTIP": "எண் மாறி வீசுகளம் உள்ளடங்கிய வாறு வற்புறுத்து", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "வீசுகளம் %1 இல் இருந்து %2 உள்ளடங்கிய வாறு சீரற்ற எண்", - "MATH_RANDOM_INT_TOOLTIP": "வீசுகளம் இல் இருந்த (உள்ளடங்கிய) வாறு சீரற்ற எண் பின்கொடு.", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "சீரற்ற எண் பின்னம்", - "MATH_RANDOM_FLOAT_TOOLTIP": "சீரற்ற எண் பின்னம், 0.0 இல் இருந்து 1.0 உட்பட, பின்கொடு.", - "TEXT_TEXT_HELPURL": "https://ta.wikipedia.org/wiki/%E0%AE%9A%E0%AE%B0%E0%AE%AE%E0%AF%8D_%28%E0%AE%95%E0%AE%A3%E0%AE%BF%E0%AE%A9%E0%AE%BF%E0%AE%AF%E0%AE%BF%E0%AE%AF%E0%AE%B2%E0%AF%8D%29", - "TEXT_TEXT_TOOLTIP": "எழுத்து, சரம், சொல், அல்லது உரை சொற்தொடர்.", - "TEXT_JOIN_TITLE_CREATEWITH": "வைத்து உரை உருவாக்க", - "TEXT_JOIN_TOOLTIP": "பல பொருட்களை ஒன்றாக சேர்வதன் மூலம் உரை உருவாக்க.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "சேர்க்க", - "TEXT_CREATE_JOIN_TOOLTIP": "தொகுப்பு உரை திருத்துதம் செய்", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "உருபடியை உரையில் சேர்க்க.", - "TEXT_APPEND_TO": "இந்த மாறியிற்கு", - "TEXT_APPEND_APPENDTEXT": "உரை சேர்க்க", - "TEXT_APPEND_TOOLTIP": "'%1' மாறியில் உரையை சேர்", - "TEXT_LENGTH_TITLE": "%1ன் நீளம்", - "TEXT_LENGTH_TOOLTIP": "தொடரில் உள்ள எழுத்துக்களின் (இடைவெளிகளையும் சேர்த்து) எண்ணிகையை பின்கொடு.", - "TEXT_ISEMPTY_TITLE": "%1 காலியானது", - "TEXT_ISEMPTY_TOOLTIP": "காலியானது என்றால் மெய் மதிப்பை பின்கொடு", - "TEXT_INDEXOF_TOOLTIP": "இரண்டாவது உரையில் முதல் உரையின் முதல்/கடை இருக்கை குறிஎண்ணை பின்கொடு.", - "TEXT_INDEXOF_INPUT_INTEXT": "உரையில்", - "TEXT_INDEXOF_OPERATOR_FIRST": "உரையில் முதல் தோற்ற இடத்தை பின்கொடு", - "TEXT_INDEXOF_OPERATOR_LAST": "உரையில் கடைசி தோற்ற இடத்தை பின்கொடு", - "TEXT_CHARAT_INPUT_INTEXT": "உரையில்", - "TEXT_CHARAT_FROM_START": "# எழுத்தை எடு", - "TEXT_CHARAT_FROM_END": "முடிவில் இருந்து # எழுத்தை எடு", - "TEXT_CHARAT_FIRST": "முதல் எழுத்தைப் பெறுக", - "TEXT_CHARAT_LAST": "இறுதி எழுத்தைப் பெறுக", - "TEXT_CHARAT_RANDOM": "சமவாய்ப்புள்ள எழுத்தை எடு", - "TEXT_CHARAT_TOOLTIP": "கூறிய இடத்தில் உள்ள எழுத்தை எடு", - "TEXT_GET_SUBSTRING_TOOLTIP": "உரையின் குறியிடப்பட்ட சரம் பின்கொடு", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "உரையில்", - "TEXT_GET_SUBSTRING_START_FROM_START": "-இல் உட்கணம் # எழுத்திலிருந்து", - "TEXT_GET_SUBSTRING_START_FROM_END": "-இல் உட்கணம் கடைசி # எழுத்திலிருந்து", - "TEXT_GET_SUBSTRING_START_FIRST": "-இல் உட்கணம் முதல் எழுத்திலிருந்து", - "TEXT_GET_SUBSTRING_END_FROM_START": "எழுத்து # வரை", - "TEXT_GET_SUBSTRING_END_FROM_END": "எழுத்து கடைசியில் இருந்து # வரை", - "TEXT_GET_SUBSTRING_END_LAST": "கடைசி எழுத்து வரை", - "TEXT_CHANGECASE_TOOLTIP": "உரை நகல் எடுத்து பொரிய/சின்ன எழுத்து மாற்றி பின்கொடு.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "பொரிய எழுத்துக்கு மாற்று", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "சின்ன எழுத்துக்கு மாற்று", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "தலைப்பு எழுத்துக்கு மாற்று", - "TEXT_TRIM_TOOLTIP": "உரை நகல் எடுத்து இடைவெளி எழுத்து நீக்கி பின்கொடு.", - "TEXT_TRIM_OPERATOR_BOTH": "இரு பக்கத்திலும் இடைவெளி எழுத்து நேர்த்தி செய்.", - "TEXT_TRIM_OPERATOR_LEFT": "இடது பக்கத்தில் இடைவெளி எழுத்து நேர்த்தி செய்.", - "TEXT_TRIM_OPERATOR_RIGHT": "வலது பக்கத்தில் இடைவெளி எழுத்து நேர்த்தி செய்.", - "TEXT_PRINT_TITLE": "%1 அச்சிடுக", - "TEXT_PRINT_TOOLTIP": "மதிப்பை அச்சிடு", - "TEXT_PROMPT_TYPE_TEXT": "உரை கொண்டு உரை-உள்ளீடு தூண்டுதலை காட்டு", - "TEXT_PROMPT_TYPE_NUMBER": "உரை கொண்டு எண்-உள்ளீடு தூண்டுதலை காட்டு", - "TEXT_PROMPT_TOOLTIP_NUMBER": "எண்-உள்ளீடு தூண்டுதலை காட்டு", - "TEXT_PROMPT_TOOLTIP_TEXT": "உரை-உள்ளீடு தூண்டுதலை காட்டு", - "LISTS_CREATE_EMPTY_TITLE": "காலி பட்டியல் உருவாக்க", - "LISTS_CREATE_EMPTY_TOOLTIP": "காலி பட்டியல் பின்கொடு.", - "LISTS_CREATE_WITH_TOOLTIP": "இவ்வளவு உருப்படிகளை கொண்டு வேண்டுமாலும் ஒரு பட்டியலை உருவாக்கு.", - "LISTS_CREATE_WITH_INPUT_WITH": "வைத்து பட்டியல் உருவாக்க", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "பட்டியல்", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "கட்டளைகளை தொகுப்பு திருத்துதம் செய்", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "பட்டியலில் ஒரு பொருளை சேர்க்க.", - "LISTS_REPEAT_TOOLTIP": "கொடுக்க பட்ட மதிப்பை, கூறியுள்ள தடவைகள் உள்ளவாறு ஒரு பட்டியலை உருவாக்கு", - "LISTS_REPEAT_TITLE": "உருப்படி %1-யை, %2 தடவைகள் உள்ளவாறு ஒரு பட்டியலை உருவாக்கு", - "LISTS_LENGTH_TITLE": "%1 இன் நீளம்", - "LISTS_LENGTH_TOOLTIP": "பட்டியல் நீளம் பின்கொடு", - "LISTS_ISEMPTY_TITLE": "%1 காலியானது", - "LISTS_ISEMPTY_TOOLTIP": "பட்டியல் காலியானது மெய் பின்கொடு,", - "LISTS_INLIST": "பட்டியலில் உள்ள", - "LISTS_INDEX_OF_FIRST": "உரையில் முதல் தோற்ற இடத்தை காட்டு", - "LISTS_INDEX_OF_LAST": "உரையில் கடைசி தோற்ற இடத்தை காட்டு", - "LISTS_INDEX_OF_TOOLTIP": "பட்டியலில் மதிப்பின் முதல், கடைசி தோற்ற இடத்தை பின்கொடு. காணாவிட்டால் %1 பின்கொடு.", - "LISTS_GET_INDEX_GET": "எடு", - "LISTS_GET_INDEX_GET_REMOVE": "பெற்று நீக்குக", - "LISTS_GET_INDEX_REMOVE": "நீக்குக", - "LISTS_GET_INDEX_FROM_END": "கடைசியில் இருந்து #", - "LISTS_GET_INDEX_FIRST": "முதல்", - "LISTS_GET_INDEX_LAST": "கடைசி", - "LISTS_GET_INDEX_RANDOM": "ஏதோ ஒன்று", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 முதல் உருப்படி.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 கடைசி உருப்படி.ி", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "பட்டியலில் இடத்தில் உருப்படி பின்கொடு.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "பட்டியல் முதல் உருப்படியை பின்கொடு,", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "பட்டியல் கடைசி உருப்படியை பின்கொடு,", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "பட்டியல் சீரற்ற உருப்படியை பின்கொடு,", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "பட்டியலில் கேட்ட இடத்தின் உருப்படி நீக்கி பின்கொடு.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "பட்டியல் முதல் உருப்படியை நீக்கியபின் பின்கொடு,", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "பட்டியல் இறுதி உருப்படியை நீக்கியபின் பின்கொடு,", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "பட்டியல் சீரற்ற உருப்படியை நீக்கியபின் பின்கொடு,", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "பட்டியலில் கேட்ட இடத்தின் உருப்படி நீக்கு.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "பட்டியலில் முதல் உருப்படியை நீக்கு", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "பட்டியலில் கடைசி உருப்படியை நீக்கு", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "பட்டியல் சீரற்ற உருப்படியை நீக்கு,", - "LISTS_SET_INDEX_SET": "நியமி", - "LISTS_SET_INDEX_INSERT": "அவ்விடத்தில் நுழை", - "LISTS_SET_INDEX_INPUT_TO": "இதுபொல", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "பட்டியலில் கேட்ட இடத்தில் உருப்படியை வை.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "மதிப்பை பட்டியலில் முதல் உருப்படியில் வை", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "மதிப்பை பட்டியலில் கடைசி உருப்படியில் வை", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "மதிப்பை பட்டியலில் சீரற்ற உருப்படியில் வை", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "பட்டியலில் கேட்ட இடத்தில் உருப்படியை நுழை.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "மதிப்பை பட்டியலின் முதலில் நுழை", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "மதிப்பை பட்டியலின் முடிவில் நுழை", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "மதிப்பை பட்டியலின் சீற்ற இடத்தில் நுழை", - "LISTS_GET_SUBLIST_START_FROM_START": "பகுதி பட்டியலை # இடத்தில் இருந்து கொடு", - "LISTS_GET_SUBLIST_START_FROM_END": "# கடைசியில் இருந்து பகுதி பட்டியலை கொடு", - "LISTS_GET_SUBLIST_START_FIRST": "# முதலில் இருந்து பகுதி பட்டியலை கொடு", - "LISTS_GET_SUBLIST_END_FROM_START": "# வரை", - "LISTS_GET_SUBLIST_END_FROM_END": "முடிவில் இருந்து # வரை", - "LISTS_GET_SUBLIST_END_LAST": "முடிவு வரை", - "LISTS_GET_SUBLIST_TOOLTIP": "குறிப்பட்ட பகுதி பட்டியலின் நகலை கொடு", - "LISTS_SPLIT_LIST_FROM_TEXT": "உரையில் இருந்து பட்டியல் உருவாக்கு", - "LISTS_SPLIT_TEXT_FROM_LIST": "பட்டியலில் இருந்து உரை உருவாக்கு", - "LISTS_SPLIT_WITH_DELIMITER": "தடை எழுத்து", - "LISTS_SPLIT_TOOLTIP_SPLIT": "உரையை வரம்புச் சுட்டி கொண்டு துண்டாக்கு.", - "LISTS_SPLIT_TOOLTIP_JOIN": "வரம்புச் சுட்டியை இடையில் இட்டு, உரைதுண்டுகளை ஒன்று சேர்", - "VARIABLES_GET_TOOLTIP": "இந்த மாறி மதிப்பை பின்கொடு", - "VARIABLES_GET_CREATE_SET": "'%1 நியமி' உருவாக்கு", - "VARIABLES_SET": "நியமி %1 இந்த மாறியிற்கு %2", - "VARIABLES_SET_TOOLTIP": "மாறியின் மதிப்பாய் உள்ளீட்டு மதிப்பை வை.", - "VARIABLES_SET_CREATE_GET": "'எடு %1' உருவாக்கு", - "PROCEDURES_DEFNORETURN_TITLE": "இந்த மாறியிற்கு", - "PROCEDURES_DEFNORETURN_PROCEDURE": "கட்டளைகள் செய்ய (இடம்காட்டி)", - "PROCEDURES_BEFORE_PARAMS": "இத்துடன்", - "PROCEDURES_CALL_BEFORE_PARAMS": "இத்துடன்:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "வெளியீடு இல்லாத ஒரு செயல்பாடு உருவாக்குகிறது", - "PROCEDURES_DEFRETURN_RETURN": "பின்கொடு", - "PROCEDURES_DEFRETURN_TOOLTIP": "வெளியீடு உள்ள ஒரு செயல்பாடு உருவாக்குகிறது", - "PROCEDURES_ALLOW_STATEMENTS": "வாக்குமூலங்களை அனுமதிக்கவும்", - "PROCEDURES_DEF_DUPLICATE_WARNING": "எச்சரிக்கை: இந்த செயற்கூறில் போலியான அளபுருக்கள் உண்டு.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "பயனரின் '%1' செயற்கூற்றை ஓட்டு.", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "பயனரின் '%1' செயற்கூற்றை ஓட்டி வரும் வெளியீட்டை பயன்படுத்து.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "உள்ளீடுகள்", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "செயல்கூறுகளின் உள்ளீட்டை சேர், நீக்கு, or மீண்டும் வரிசை செய்.", - "PROCEDURES_MUTATORARG_TITLE": "பெயரை உள்ளிடுக:", - "PROCEDURES_MUTATORARG_TOOLTIP": "செயல்கூறுக்கு ஒரு உள்ளீட்டை சேர்.", - "PROCEDURES_HIGHLIGHT_DEF": "நிரல்பாகத்தை விளக்கமாக காட்டு", - "PROCEDURES_CREATE_DO": "'%1' உருவாக்குக", - "PROCEDURES_IFRETURN_TOOLTIP": "மதிப்பு உண்மையானால், இரண்டாவது மதிப்பை பின்கொடு." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/tcy.json b/backend/_pv_1_3_5/static/blockly/msg/json/tcy.json deleted file mode 100755 index 37f2f1abd..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/tcy.json +++ /dev/null @@ -1,307 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Vishwanatha Badikana", - "Bharathesha Alasandemajalu" - ] - }, - "VARIABLES_DEFAULT_NAME": "ವಸ್ತು", - "TODAY": "ಇನಿ", - "DUPLICATE_BLOCK": "ನಕಲ್", - "ADD_COMMENT": "ಟಿಪ್ಪಣಿ ಸೇರ್ಸಲೆ", - "REMOVE_COMMENT": "ಟಿಪ್ಪಣಿನ್ ದೆತ್ತ್‌ಪಾಡ್ಲೆ", - "EXTERNAL_INPUTS": "ಬಾಹ್ಯೊ ಪರಿಕರೊ", - "INLINE_INPUTS": "ಉಳಸಾಲ್‍ದ ಉಳಪರಿಪು", - "DELETE_BLOCK": "ಮಾಜಯರ ತಡೆಯಾತ್ಂಡ್", - "DELETE_X_BLOCKS": "ಮಾಜಯರ ಶೇಕಡಾ ೧ ತಡೆಯಾತ್ಂಡ್", - "DELETE_ALL_BLOCKS": "ಮಾತ %1 ನಿರ್ಬಂದೊಲೆನ್ ದೆತ್ತ್ ಪಾಡ್ಲೆ ?", - "CLEAN_UP": "ನಿರ್ಬಂದೊಲೆನ್ ಸ್ವೊಚ್ಚೊ ಮಲ್ಪುಲೆ", - "COLLAPSE_BLOCK": "ಕುಗ್ಗಿಸಾದ್ ತಡೆಪತ್ತುನೆ", - "COLLAPSE_ALL": "ಕುಗ್ಗಿಸಾದ್ ನಿರ್ಬಂಧಿಸಾಪುನೆ", - "EXPAND_BLOCK": "ವಿಸ್ತರಿಸಾದ್ ತಡೆಪತ್ತುನೆ", - "EXPAND_ALL": "ವಿಸ್ತರಿಸಾದ್ ನಿರ್ಬಂದಿಸಾಪುನೆ", - "DISABLE_BLOCK": "ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಾದ್ ತಡೆಪತ್ತುನೆ", - "ENABLE_BLOCK": "ಸಕ್ರಿಯಗೊಳಿಸಾದ್ ತಡೆಪತ್ತುನೆ", - "HELP": "ಸಹಾಯೊ", - "UNDO": "ದುಂಬುದಲೆಕೊ", - "REDO": "ಪಿರವುದಂಚ", - "CHANGE_VALUE_TITLE": "ಮೌಲ್ಯೊದ ಬದಲಾವಣೆ", - "RENAME_VARIABLE": "ಬದಲಾವಣೆ ಆಯಿನ ಪುದರ್‍ನ್ ನಾನೊರೊ ಪನ್ಲೆ", - "RENAME_VARIABLE_TITLE": "ನಾನೊರೊ ಪುದರ್ ಬದಲಾವಣೆ ಆಯಿನ ಮಾಂತ '% 1':", - "NEW_VARIABLE": "ಪೊಸ ಬದಲಾವಣೆ", - "NEW_VARIABLE_TITLE": "ಪುದರ್‍ದ ಪೊಸ ಬದಲಾವಣೆ:", - "COLOUR_PICKER_HELPURL": "https://en.wikipedia.org/wiki/ಬಣ್ಣೊ", - "COLOUR_PICKER_TOOLTIP": "ವರ್ಣಫಲಕೊದ ಒಂಜಿ ಬಣ್ಣೊದ ಆಯ್ಕೆ.", - "COLOUR_RANDOM_TITLE": "ಯಾದೃಚ್ಛಿಕೊ ಬಣ್ಣೊ", - "COLOUR_RANDOM_TOOLTIP": "ಯಾದೃಚ್ಛಿಕವಾಯಿನ ಬಣ್ಣೊದ ಆಯ್ಕೆ.", - "COLOUR_RGB_TITLE": "ಬಣ್ಣೊದೊಟ್ಟುಗೆ", - "COLOUR_RGB_RED": "ಕೆಂಪು ಬಣ್ಣೊ", - "COLOUR_RGB_GREEN": "ಪಚ್ಚೆ", - "COLOUR_RGB_BLUE": "ನೀಲಿ", - "COLOUR_RGB_TOOLTIP": "ತೋಜಿಪಾಯಿನ ಕೆಂಪು, ಪಚ್ಚೆ ಬುಕ್ಕೊ ನೀಲಿ ಬಣ್ಣೊದ ಪ್ರಮಾಣೊನು ರಚಿಸಲೆ. ಮಾಂತ ಮೌಲ್ಯೊಲು 0 ಬುಕ್ಕೊ 100 ನಡುಟೆ ಇಪ್ಪೊಡು.", - "COLOUR_BLEND_TITLE": "ಮಿಸ್ರನೊ", - "COLOUR_BLEND_COLOUR1": "ಬಣ್ಣೊ ೧(ಒಂಜಿ)", - "COLOUR_BLEND_COLOUR2": "ಬಣ್ಣೊ ೨(ರಡ್ಡ್)", - "COLOUR_BLEND_RATIO": "ಅನುಪಾತೊ", - "COLOUR_BLEND_TOOLTIP": "ಕೊರ್‍ನ ಅನುಪಾತೊದ ಒಟ್ಟುಗೆ (0.0- 1.0 ) ರಡ್ಡ್ ಬಣ್ಣೊಲೆನ್ ಜೊತೆಟ್ ಒಂಜಿ ಮಲ್ಪುಂಡು.", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "ನಾನೊರೊ %1 ಸಮಯೊಗು", - "CONTROLS_REPEAT_INPUT_DO": "ಮಲ್ಪು / ಅಂಚನೆ", - "CONTROLS_REPEAT_TOOLTIP": "ಕೆಲವು ಹೇಳಿಕೆಲೆನ್ ಮಸ್ತ್ ಸಮಯೊ ಮಲ್ಪೊಡು", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "ಬುಕ್ಕೊ ಅಂಚನೇ", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "ಬುಕ್ಕೊ ಮುಟ್ಟೊ", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "ಈ ತಿರ್ತ್‌ದ ಸರಿ ಇತ್ತ್ಂಡಲಾ, ಬುಕ್ಕೊದ ಕೆಲವು ಹೇಳಿಕೆಲೆನ್ ಮಲ್ಪುಲ", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "ಈ ತಿರ್ತ್‍ದ ತಪ್ಪಾದುಂಡು, ಬುಕ್ಕೊದ ಕೆಲವು ಹೇಳಿಕೆಲೆನ್ ಮಲ್ಪಪುಲ", - "CONTROLS_FOR_TOOLTIP": "ಸುರೂತ ನಂಬ್ರೊಡ್ದು ಅಕೇರಿದ ನಂಬ್ರೊಗು ಬಿಲೆಟ್ ಮಸ್ತ್ ಹೆಚ್ಚ್‌ಕಮ್ಮಿ ಇತ್ತ್ಂಡಲಾ %1 ದೆತೊಂದ್, ನಿರ್ದಿಸ್ಟೊ ಮಧ್ಯಂತರೊದ ಮೂಲಕೊ ಲೆಕ್ಕೊದೆತೊಂದು ಬುಕ್ಕೊ ನಿಗಂಟ್ ಮಲ್ತ್‌ನ ಬ್ಲಾಕ್‍ಲೆನ್ ಲೆಕ್ಕೊ ಮಲ್ಪುಲ.", - "CONTROLS_FOR_TITLE": "%1ಡ್ದ್ %2ಗ್ ಮುಟ್ಟ %3 ಬುಕ್ಕೊ %4ನ್ ಒಟ್ಟೂಗು ಗೆನ್ಪಿ", - "CONTROLS_FOREACH_TITLE": "ಅತ್ತಂದೆ ಪ್ರತೀ ಅಂಸೊ %1ದ ಉಲಯಿ %2ದ ಪಟ್ಟಿ", - "CONTROLS_FOREACH_TOOLTIP": "ಒಂಜಿ ಪಟ್ಟಿಡ್ ಪ್ರತಿ ವಸ್ತುಗು, ಜೋಡಾಯಿನ ವಸ್ತು ಬದಲಾಪುನಂಚ '% 1', ಬುಕ್ಕೊ ಒಂತೆ ಹೇಳಿಕೆಲೆನ್ ಮಲ್ಲಪುಲೆ.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "ಕುಣಿಕೆದ ಪಿದಯಿ ತುಂಡಾಪುಂಡು", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "ದುಂಬುದ ಆದೇಸೊಡೆ ಪುನರಾವರ್ತನೆ ದುಂಬರಿಪ್ಪುಂಡು", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "ಬಳಕೆಡುಪ್ಪುನ ಕೊಲಿಕೆಡ್ದ್ ಪಿದಯಿ ಪಾಡ್‍ಲೆ", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "ದುಂಬುದ ಆವೃತಿಡ್ ಉಪ್ಪುನಂಚನೆ ಮಾಂತ ಕೊಲಿಕೆಲೆನ್ ದೆತ್ಪುಲೆ ಬುಕ್ಕೊ ದುಂಬರಿಲೆ", - "CONTROLS_FLOW_STATEMENTS_WARNING": "ಎಚ್ಚರೊ: ಈ ನಿರ್ಬಂದೊನು ಕೇವಲ ಒಂಜಿ ಕೊಲಿಕೆದಾಕಾರೊದ ಮುಕ್ತಮಾರ್ಗೊದ ಪರಿಮಿತಿದುಲಯಿಡ್ ಬಳಸೊಲಿ", - "CONTROLS_IF_TOOLTIP_1": "ಇಂದೆತ ಮೌಲ್ಯೊ ನಿಜವಾದಿತ್ತ್‌ಂಡ, ಬುಕ್ಕೊ ಒಂತೆ ನಿರೂಪಣೆಲೆನ್ ಮಲ್ಪುಲೆ", - "CONTROLS_IF_TOOLTIP_2": "ಇಂದೆತ ಮೌಲ್ಯೊ ನಿಜವಾದಿತ್ತ್‌ಂಡ, ಬುಕ್ಕೊದ ನಿರೂಪಣೆಲೆನ್ ಸುರೂಕು ಮಲ್ಪುಲೆ. ಅತ್ತಂಡ ರಡ್ಡನೆದ ನಿರೂಪಣೆನ್ ತಡೆ ಪತ್ತುನಂಚನೆ ಮಲ್ಲಪುಲೆ", - "CONTROLS_IF_TOOLTIP_3": "ಸುರೂತ ಮೌಲ್ಯೊ ನಿಜವಾದಿತ್ತ್‌ಂಡ, ಬುಕ್ಕೊದ ನಿರೂಪಣೆಲೆನ್ ಸುರೂಕು ತಡೆ ಮಲ್ಪುಲೆ. ಅತ್ತಂಡ ರಡ್ಡನೆದ ನಿರೂಪಣೆನ್ ನಿಜವಾದಿತ್ತ್‌ಂಡ ಬುಕ್ಕೊ ಒಂತೆ ನಿರೂಪಣೆಲೆನ್ ಮಲ್ಪುಲೆ", - "CONTROLS_IF_TOOLTIP_4": "ಸುರೂತ ಮೌಲ್ಯೊ ನಿಜವಾದಿತ್ತ್‌ಂಡ, ಸುರೂತ ನಿರೂಪಣೆನ್ ತಡೆ ಮಲ್ಪುಲೆ. ರಡ್ಡನೆದ ನಿರೂಪಣೆ ನಿಜವಾದಿತ್ತ್ಂಡ, ರಡ್ಡನೆದ ನಿರೂಪಣೆನ್ ತಡೆ ಮಲ್ಪುಲೆ. ಉಂದು ಒವ್ವೇ ಮೌಲ್ಯೊ ನಿಜವಾದಿದ್ಯಂಡ, ಅಕೇರಿದ ನಿರೂಪಣೆನ್ ತಡೆ ಮಲ್ಪುಲೆ.", - "CONTROLS_IF_MSG_IF": "ಒಂಜಿ ವೇಲೆ", - "CONTROLS_IF_MSG_ELSEIF": "ಬೇತೆ ಸಮಯೊ", - "CONTROLS_IF_MSG_ELSE": "ಬೇತೆ", - "CONTROLS_IF_IF_TOOLTIP": "ಸೇರಲ, ದೆತ್ತ್‌ ಪಾಡ್‌ಲ, ಅತ್ತಂಡ ಒಂಜಿ ವೇಲೆ ಈ ರಚನೆನ್ ತಡೆದ್, ಇಂದೆತ ಇಬಾಗೊಲೆನ್ ಬೇತೆ ಕ್ರಮೊಟು ಮಲ್ಪುಲೆ", - "CONTROLS_IF_ELSEIF_TOOLTIP": "ಒಂಜಿ ವೇಲೆ ಒಂಜಿ ತಡೆಕ್ ಈ ಪರಿಸ್ಥಿತಿನ್ ಸೇರಲೆ", - "CONTROLS_IF_ELSE_TOOLTIP": "ಒಂಜಿ ವೇಲೆ ಮಾಂತೆನ್ಲಾ ದೀಡೊಂದು ಅಕೇರಿದ ಪರಿಸ್ಥಿಡ್ ಸೇರಲೆ", - "LOGIC_COMPARE_TOOLTIP_EQ": "ರಡ್ಡ್ ಅತ್ತಂದೆ ಬೇತೆ ಸೂಚನೆಲು ನಿಜೊಕ್ಕುಲಾ ಸಮೊ ಇತ್ತ್ಂಡ ಪಿರ ಕೊರ್ಲೆ.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "ರಡ್ಡ್ ಅತ್ತಂದೆ ಬೇತೆ ಸೂಚನೆಲು ನಿಜೊಕ್ಕುಲಾ ಸಮೊ ಆತಿಜಂಡ ಪಿರ ಕೊರ್ಲೆ", - "LOGIC_COMPARE_TOOLTIP_LT": "ಸುರುತ ಅತ್ತಂದೆ ರಡ್ಡನೆದ ಸೂಚನೆ ನಿಜೊಕ್ಕುಲಾ ಒಂಜಿ ವೇಲೆ ಎಲ್ಯೆ ಆದಿತ್ತ್ಂಡ ಪಿರ ಕೊರ್ಲೆ", - "LOGIC_COMPARE_TOOLTIP_LTE": "ಸುರುತ ಅತ್ತಂದೆ ರಡ್ಡನೆದ ಸೂಚನೆ ನಿಜೊಕ್ಕುಲಾ ದಿಂಜ ಎಲ್ಯೆ ಅತ್ತಂಡ ಸಮೊ ಆದಿತ್ತ್ಂಡ ಪಿರ ಕೊರ್ಲೆ", - "LOGIC_COMPARE_TOOLTIP_GT": "ಸುರುತ ಅತ್ತಂದೆ ರಡ್ಡನೆದ ಸೂಚನೆಡ್ದ್ ನಿಜೊಕ್ಕುಲಾ ಮಲ್ಲೆ ಆದಿತ್ತ್ಂಡ ಪಿರ ಕೊರ್ಲೆ", - "LOGIC_COMPARE_TOOLTIP_GTE": "ಸುರುತ ಅತ್ತಂದೆ ರಡ್ಡನೆದ ಸೂಚನೆ ನಿಜೊಕ್ಕುಲಾ ದಿಂಜ ಮಲ್ಲೆ ಅತ್ತಂಡ ಸಮೊ ಆದಿತ್ತ್ಂಡ ಪಿರ ಕೊರ್ಲೆ", - "LOGIC_OPERATION_TOOLTIP_AND": "ರಡ್ಡ್ ಸೂಚನೆಲಾ ನಿಜೊ ಆದಿತ್ತ್ಂಡ ನಿಜವಾತ್ ಪಿರಕೊರ್ಲೆ", - "LOGIC_OPERATION_AND": "ಬುಕ್ಕೊ", - "LOGIC_OPERATION_TOOLTIP_OR": "ನಿಜವಾದ್‍ಲ ಒಂಜಿವೇಳೆ ಇನ್‍ಪುಟ್ ಒಂತೆ ನಿಜವಾದಿತ್ತ್ಂಡ ಪಿರಕೊರು", - "LOGIC_OPERATION_OR": "ಅತ್ತಂಡ", - "LOGIC_NEGATE_TITLE": "%1 ಇದ್ದಿ", - "LOGIC_NEGATE_TOOLTIP": "ನಿಜವಾದ್‍ ಇನ್‍ಪುಟ್ ಸುಲ್ಲಾದಿತ್ತ್‌ಂಡ ಪಿರಕೊರು. ನಿಜವಾದ್ ಸುಲ್ಲು ಇನ್‍ಪುಟ್ ಇತ್ತ್‌ಂಡ ಪಿರಕೊರು", - "LOGIC_BOOLEAN_TRUE": "ಸತ್ಯೊ", - "LOGIC_BOOLEAN_FALSE": "ಸುಲ್ಲು", - "LOGIC_BOOLEAN_TOOLTIP": "ಪೂರ ಸತ್ಯೊ ಅತ್ತಂಡ ಸುಲ್ಲು ಆಂಡ ಪಿರಕೊರು", - "LOGIC_NULL": "ಸೊನ್ನೆ", - "LOGIC_NULL_TOOLTIP": "ಸೊನ್ನೆನ್ ಪರಿಕೊರ್ಪುಂಡು", - "LOGIC_TERNARY_CONDITION": "ಪರೀಕ್ಷೆ", - "LOGIC_TERNARY_IF_TRUE": "ಒಂಜಿ ವೇಲೆ ಸತ್ಯೊ", - "LOGIC_TERNARY_IF_FALSE": "ಒಂಜಿ ವೇಲೆ ಸುಳ್ಳು", - "LOGIC_TERNARY_TOOLTIP": "ಪರೀಕ್ಷೆದ ಸ್ಥಿತಿನ್ ಪರಿಶೀಲನೆ ಮಲ್ಲಪುಲೆ. ಪರಿಸ್ಥಿತಿ ನಿಜವಾದಿತ್ತ್ಂಡ, ನಿಜವಾಯಿನ ಮೌಲ್ಯೊನು ಪಿರಕೊರ್ಲೆ; ಅತ್ತಂಡ ತಪ್ಪು ಮೌಲ್ಯೊನೇ ಪಿರ ಕೊರ್ಲೆ.", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/ಸಂಖ್ಯೆ", - "MATH_NUMBER_TOOLTIP": "ಅ ನಂಬ್ರೊ", - "MATH_ARITHMETIC_HELPURL": "https://en.wikipedia.org/wiki/ಅಂಕಗಣಿತ", - "MATH_ARITHMETIC_TOOLTIP_ADD": "ಸಂಖ್ಯೆದ ಮೊತ್ತನ್ ಪಿರ ಕೊರು.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "ಸಂಖ್ಯೆದ ವ್ಯತ್ಯಾಸೊನು ಪರಕೊರು.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "ಸಂಖ್ಯೆದ ಉತ್ಪನ್ನೊನು ಪಿರ ಕೊರು.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "ಸಂಖ್ಯೆದ ಭಾಗಲಬ್ದೊನು ಪಿರ ಕೊರು.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "ಒಂಜನೆ ಸಂಖ್ಯೆದ ಶಕ್ತಿನ್ ರಡ್ಡನೆ ಸಂಖ್ಯೆಡ್ದ್ ಪಿರ ಹೆಚ್ಚಿಗೆ ಮಲ್ಪುಲೆ.", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/ವರ್ಗೊಮೂಲೊ", - "MATH_SINGLE_OP_ROOT": "ವರ್ಗಮೂಲೊ", - "MATH_SINGLE_TOOLTIP_ROOT": "ಸಂಖ್ಯೆದ ವರ್ಗಮೂಲೊನು ಪಿರ ಕೊರು.", - "MATH_SINGLE_OP_ABSOLUTE": "ಸಂಪೂರ್ನೊ", - "MATH_SINGLE_TOOLTIP_ABS": "ಸಂಖ್ಯೆದ ಸರಿಯಾಯಿನ ಮೌಲ್ಯೊನು ಕೊರು", - "MATH_SINGLE_TOOLTIP_NEG": "ಸಂಖ್ಯೆದ ನಿರಾಕರಣೆನ್ ಪಿರಕೊರು", - "MATH_SINGLE_TOOLTIP_LN": "ಸಂಖ್ಯೆದ ನಿಜವಾಯಿನ ಕ್ರಮಾವಳಿನ್ ಪಿರಕೊರು", - "MATH_SINGLE_TOOLTIP_LOG10": "ಸಂಖ್ಯೆದ ೧೦ ಮೂಲೊ ಕ್ರಮಾವಳಿನ್ ಪಿರಕೊರು", - "MATH_SINGLE_TOOLTIP_EXP": "ಸಂಖ್ಯೆದ ಇ ಗ್ ಅಧಿಕಾರೊನು ಪಿರಕೊರು", - "MATH_SINGLE_TOOLTIP_POW10": "ಸಂಖ್ಯೆದ ೧೦ಗ್ ಅಧಿಕಾರೊನು ಪಿರಕೊರು", - "MATH_TRIG_HELPURL": "https://en.wikipedia.org/wiki/ತ್ರಿಕೋನಮಿತಿದ_ಕಾರ್ಯೊಲು", - "MATH_TRIG_TOOLTIP_SIN": "ಪದವಿದ ಚಿಹ್ನೆನ್ ಪಿರಕೊರು", - "MATH_TRIG_TOOLTIP_COS": "ಪದವಿದ ಸಹ ಚಿಹ್ನೆನ್ ಪಿರಕೊರು", - "MATH_TRIG_TOOLTIP_TAN": "ಪದವಿದ ಸ್ಪರ್ಶಕೊನು ಪಿರಕೊರು", - "MATH_TRIG_TOOLTIP_ASIN": "ಪದವಿದ ಆರ್ಕ್ಸೈನ್ ಪಿರಕೊರು", - "MATH_TRIG_TOOLTIP_ACOS": "ಸಂಖ್ಯೆದ ಆರ್ಕ್ಕೊಸಿನ್ ಪಿರಕೊರು", - "MATH_TRIG_TOOLTIP_ATAN": "ಸಂಖ್ಯೆದ ಆರ್ಕ್ಟ್ಯಾಂಜೆಂಟ್ ಪಿರಕೊರು", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/ಗಣಿತ_ನಿರಂತರ", - "MATH_CONSTANT_TOOLTIP": "ಸಾಮಾನ್ಯವಾದ್ ಒಂಜಿ ಸ್ಥಿರವಾದಿತ್ತ್‌ಂಡ ಪಿರಕೊರು: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).", - "MATH_IS_EVEN": "ಸಮೊ ಆತ್ಂಡ್", - "MATH_IS_ODD": "ಬೆಸೊ ಆತ್ಂಡ್", - "MATH_IS_PRIME": "ಎಡ್ಡೆ ಆತ್ಂಡ್", - "MATH_IS_WHOLE": "ಮಾಂತ ಆತ್ಂಡ್", - "MATH_IS_POSITIVE": "ಗುನೊ ಆತ್ಂಡ್", - "MATH_IS_NEGATIVE": "ರುನೊ ಆತ್ಂಡ್", - "MATH_IS_DIVISIBLE_BY": "ಭಾಗಿಸವೊಲಿಯ", - "MATH_IS_TOOLTIP": "ಒಂಜಿ ವೇಲ್ಯೊ ಸಂಖ್ಯೆ ಸರಿ, ಬೆಸ, ಅವಿಭಾಜ್ಯ, ಇಡೀ, ಕೂಡಬುನ, ಕಲೆವುನ, ಅತ್ತಂಡ ನಿರ್ದಿಷ್ಟ ಸಂಖ್ಯೆಡ್ದ್ ಭಾಗಿಸವುಂಡಂದ್ ಪರಿಶೀಲಿಸ. ಸರಿ ಅತ್ತಂಡ ತಪ್ಪುನು ಪಿರಕೊರು.", - "MATH_CHANGE_TITLE": "%1 ಡ್ದ್ %2 ಬದಲಾಯಿಸವೊಲಿ", - "MATH_CHANGE_TOOLTIP": "'%1' ಬದಲ್ ಮಲ್ಪುನಂಚಿನ ಒಂಜಿ ನಂಬರ್‍ನ್ ಸೇರಾವು", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/ಪೂರ್ಣಾಂಕೊ", - "MATH_ROUND_TOOLTIP": "ಸಂಖ್ಯೆನ್ ಮಿತ್ತ್ ಅತ್ತಂಡ ತಿರ್ತ್ ರೌಂಡ್ ಮಲ್ಪು", - "MATH_ROUND_OPERATOR_ROUND": "ಸುತ್ತು", - "MATH_ROUND_OPERATOR_ROUNDUP": "ಮುಗಿಪುನ ಸಮಯೊ", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "ಸುತ್ತು ಕಡಮೆ", - "MATH_ONLIST_OPERATOR_SUM": "ಒಟ್ಟು ಕೂಡಯಿನಾ ಪಟ್ಟಿ", - "MATH_ONLIST_TOOLTIP_SUM": "ಪಟ್ಟಿದಾ ಮಾಂತ ಸಂಕ್ಯೆಲೆನ್ ಪಿರಕೊರ್ಲೆ", - "MATH_ONLIST_OPERATOR_MIN": "ಕಿನ್ಯ ಪಟ್ಟಿ", - "MATH_ONLIST_TOOLTIP_MIN": "ಪಟ್ಟಿದಾ ಕಿನ್ಯ ಸಂಕ್ಯೆನ್ ಪಿರಕೊರು", - "MATH_ONLIST_OPERATOR_MAX": "ಪಟ್ಟಿನ್ ಮಿಸ್ರೊ ಮಲ್ಪು", - "MATH_ONLIST_TOOLTIP_MAX": "ಪಟ್ಟಿದಾ ಮಲ್ಲ ಸಂಕ್ಯೆನ್ ಪಿರಕೊರು", - "MATH_ONLIST_OPERATOR_AVERAGE": "ಸರಾಸರಿ ಪಟ್ಟಿ", - "MATH_ONLIST_TOOLTIP_AVERAGE": "ಪಟ್ಟಿಡುಪ್ಪುನ ಸರ್ವಸಾಧಾರಣ ಬಿಲೆನ್ ಪಿರಕೋರ್ಲೆ", - "MATH_ONLIST_OPERATOR_MEDIAN": "ನಡುತ ಪಟ್ಟಿ", - "MATH_ONLIST_TOOLTIP_MEDIAN": "ಪಟ್ಟಿದಾ ನಡುತ ಸಂಕ್ಯೆನ್ ಪಿರಕೊರು", - "MATH_ONLIST_OPERATOR_MODE": "ಪಟ್ಟಿದ ಇದಾನೊಲು", - "MATH_ONLIST_TOOLTIP_MODE": "ಪಟ್ಟಿದ ಸಾಮಾನ್ಯೊ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ಪಿರಕೊರು", - "MATH_ONLIST_OPERATOR_STD_DEV": "ಕಬರ್ ಪಟ್ಟಿದ ಪ್ರಮಾನೊ", - "MATH_ONLIST_TOOLTIP_STD_DEV": "ಪಟ್ಟಿದ ಗುಣಮಟ್ಟೊದ ವರ್ಗೀಕರಣೊನು ಪಿರಕೊರು", - "MATH_ONLIST_OPERATOR_RANDOM": "ಗೊತ್ತುಗುರಿ ದಾಂತಿನ ಅಂಸೊದ ಪಟ್ಟಿ", - "MATH_ONLIST_TOOLTIP_RANDOM": "ಪಟ್ಟಿದ ಗೊತ್ತು ಗುರಿದಾಂತಿನ ಅಂಸೊಲೆನ್ ಪಿರಕೊರು", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/ಮೋಡ್ಯುಲೊ_ಒಪರೇಶನ್", - "MATH_MODULO_TITLE": " %1 ÷ %2 ಒರಿನ ಬಾಗೊ", - "MATH_MODULO_TOOLTIP": "ರಡ್ಡ್ ಸಂಖ್ಯೆದ ಇಬಾಗೊಡ್ದು ಒರಿನ ಬಾಗೊನು ಪಿರಕೊರು", - "MATH_CONSTRAIN_TITLE": " %1 ಕಮ್ಮಿ %2 ಜಾಸ್ತಿ %3 ಕಡ್ಡಾಯ ಮಲ್ಪು", - "MATH_CONSTRAIN_TOOLTIP": "ನಿಗದಿತ ನಿಯಮೊಗು ನಡುಟು ದಿಂಜ ನಿರ್ಬಂದೊ(ಸೇರ್‍ನಂಚ)", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/ರಾಂಡಮ್_ನಂಬರ್_ಜನರೇಶನ್", - "MATH_RANDOM_INT_TITLE": " %1 ಡ್ದ್ %2 ಯಾದೃಚ್ಛಿಕ ಪೂರ್ಣಾಂಕೊ", - "MATH_RANDOM_INT_TOOLTIP": "ರಡ್ಡ್ ನಿಗದಿತ ನಿಯಮೊದ ನಡುತ ಯಾದೃಚ್ಛಿಕ ಪೂರ್ಣಾಂಕೊನು ಪಿರಕೊರು", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/ರಾಂಡಮ್_ನಂಬರ್_ಜನರೇಶನ್", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "ಗೊತ್ತುಗುರಿ ದಾಂತಿನ ಬಾಗೊ", - "MATH_RANDOM_FLOAT_TOOLTIP": "0.0 (ಸೇರ್ನಂಚಿನ) and 1.0 (ಸೇರಂದಿನಂಚಿನ) ನಡುತ ಗೊತ್ತು ಗುರಿದಾಂತಿನ ಬಾಗೊನು ಪಿರಕೊರು.", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/ಸ್ಟ್ರಿಂಗ್_(ಕಂಪ್ಯೂಟರ್_ಸೈನ್ಸ್)", - "TEXT_TEXT_TOOLTIP": "ಒಂಜಿ ಅಕ್ಷರೊ, ಪದೊ ಅತ್ತಂಡ ಪಾಟೊದ ಒಂಜಿ ಸಾಲ್", - "TEXT_JOIN_TITLE_CREATEWITH": "ಪಟ್ಯೊನು ರಚನೆ ಮಲ್ಪು", - "TEXT_JOIN_TOOLTIP": "ಒವ್ವೇ ಸಂಖ್ಯೆದ ಪಟ್ಯೊದ ತುಂಡುಲೆನ್ ಒಟ್ಟೂಗೆ ಸೇರಯರ ರಚಿಸಲೆ", - "TEXT_CREATE_JOIN_TITLE_JOIN": "ಸೇರೊಲಿ", - "TEXT_CREATE_JOIN_TOOLTIP": "ಸೇರಯರ, ದೆತ್ತ್‌ ಪಾಡೆರೆ ಅತ್ತಂಡ ಈ ಪಟ್ಯೊಲೆನ್ ತಡೆದ್ ಪತ್ತ್‌ದ್ ಪಿರ ರಚಿಸಯರ ಇಬಾಗೊ ಮಲ್ಪುಲೆ.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "ಪಟ್ಯೊಡು ಅಂಸೊಲೆನ್ ಸೇರಲೆ", - "TEXT_APPEND_TO": "ಇಂದೆಕ್", - "TEXT_APPEND_APPENDTEXT": "ಪಟ್ಯೊನು ಸೇರವೆ", - "TEXT_APPEND_TOOLTIP": "%1 ಬದಲಾಪುನ ಕೆಲವು ಪಟ್ಯೊಲೆನ್ ಸೇರಾವೊಂಡು.", - "TEXT_LENGTH_TITLE": "೧% ಉದ್ದೊ", - "TEXT_LENGTH_TOOLTIP": "ಕೊರ್‌ನ ಪಟ್ಯೊದ ಅಕ್ಷರೊಲೆನ(ಅಂತರೊಲು ಸೇರ್‌ನಂಚ) ಸಂಖ್ಯೆನ್ ಪಿರಕೊರು.", - "TEXT_ISEMPTY_TITLE": "%1 ಕಾಲಿ", - "TEXT_ISEMPTY_TOOLTIP": "ಕೊರ್‌ನ ಪಟ್ಯೊ ಕಾಲಿಂದ್ ಸತ್ಯೊ ಆಂಡ ಪಿರಕೊರು", - "TEXT_INDEXOF_TOOLTIP": "ಸುರುತ ಪಟ್ಯೊದ ಸೂಚ್ಯಿ/ಅಕೇರಿಟ್ ಸಂಭವಿಸವುನ ಸುರುತ ಪಟ್ಟಯೊದುಲಯಿದ ರಡ್ಡನೆ ಪಟ್ಯೊನು ಪಿರಕೊರು. %1 ಪಟ್ಯೊ ತಿಕಂದಿತ್ತ್‌ಂಡ ಪಿರಕೊರು.", - "TEXT_INDEXOF_INPUT_INTEXT": "ಪಟ್ಯೊಡು", - "TEXT_INDEXOF_OPERATOR_FIRST": "ಸುರುಟು ಸಂಭವಿಸಯಿನ ಪಟ್ಯೊನು ನಾಡ್‍ಲ", - "TEXT_INDEXOF_OPERATOR_LAST": "ದುಂಬು ಕರಿನ ಪಟ್ಯೊನು ನಾಡ್‍ಲೆ", - "TEXT_CHARAT_INPUT_INTEXT": "ಪಟ್ಯೊಡು", - "TEXT_CHARAT_FROM_START": "ಅಕ್ಸರೊನು ದೆತೊನುಲೆ#", - "TEXT_CHARAT_FROM_END": "ಅಕ್ಷರೊ ನಟೊನ್#ಅಕೇರಿಡ್ದ್", - "TEXT_CHARAT_FIRST": "ಸುರುಡ್ದ್ ಅಕ್ಷರೊನು ನಟೊನ್ಲ", - "TEXT_CHARAT_LAST": "ಅಕೇರಿದ ಅಕ್ಷರೊನು ನಟೊನ್ಲ", - "TEXT_CHARAT_RANDOM": "ಗೊತ್ತುಗುರಿದಾಂತಿ ಅಕ್ಷರೊನು ನಟೊನ್ಲ", - "TEXT_CHARAT_TOOLTIP": "ಅಕ್ಷರೊನು ನಿರ್ದಿಷ್ಟ ಜಾಗೆಡ್ ಪಿರಕೊರು.", - "TEXT_GET_SUBSTRING_TOOLTIP": "ಪಟ್ಯೊನು ನಿರ್ದಿಷ್ಟ ಬಾಗೊಡು ಪಿರಕೊರು", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "ಪಟ್ಯೊಡು", - "TEXT_GET_SUBSTRING_START_FROM_START": "ಉಪ ವಾಕ್ಯೊಡ್ದು ಅಕ್ಷರೊನು ನಟೊನ್ಲ", - "TEXT_GET_SUBSTRING_START_FROM_END": "ಉಪ ವಾಕ್ಯೊಡ್ದು ಅಕ್ಷರೊನು ನಟೊನ್ಲ#ಅಕೇರಿಡ್ದ್", - "TEXT_GET_SUBSTRING_START_FIRST": "ಉಪ ವಾಕ್ಯೊಡ್ದು ಸುರುತ ಅಕ್ಷರೊನು ನಟೊನ್ಲ", - "TEXT_GET_SUBSTRING_END_FROM_START": "ಅಕ್ಷರೊಗು#", - "TEXT_GET_SUBSTRING_END_FROM_END": "ಅಕ್ಷರೊಗು#ಅಕೇರಿಡ್ದ್", - "TEXT_GET_SUBSTRING_END_LAST": "ಅಕೇರಿದ ಅಕ್ಷರೊಗು", - "TEXT_CHANGECASE_TOOLTIP": "ಪಟ್ಯೊದ ಒಂಜಿ ನಕಲ್‍ನ್ ಬೇತೆ ಸಮಯೊಡು ಪಿರಕೊರು", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "ಮಲ್ಲ ಅಕ್ಷರೊಗು", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "ಎಲ್ಯ ಅಕ್ಷರೊಗು", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "ತರೆಬರವುಗು", - "TEXT_TRIM_TOOLTIP": "ಒಂಜಿ ಅತ್ತಂಡ ರಡ್ಡ್ ಕೊಡಿಡ್ದ್ ದೆತ್ತ್‌ನ ಕಅಲಿ ಪಟ್ಯೊದ ಪ್ರತಿನ್ ಪಿರಕೊರು.", - "TEXT_TRIM_OPERATOR_BOTH": "ರಡ್ಡ್ ಬರಿತ ಜಾಗೆನ್ಲ ಕತ್ತೆರಿಪುಲೆ.", - "TEXT_TRIM_OPERATOR_LEFT": "ಎಡತ ಬರಿತ ಜಾಗೆನ್ ಕತ್ತೆರಿಪುಲೆ.", - "TEXT_TRIM_OPERATOR_RIGHT": "ಬಲತ ಬರಿತ ಜಾಗೆನ್ ಕತ್ತೆರಿಪುಲೆ.", - "TEXT_PRINT_TITLE": "%1 ಮುದ್ರಿತ", - "TEXT_PRINT_TOOLTIP": "ನಿರ್ದಿಷ್ಟ ಪಟ್ಯೊ, ಸಂಖ್ಯೆ ಅತ್ತಂಡ ಬೇತೆ ಮೌಲ್ಯೊನು ಮುದ್ರಿಸಲೆ.", - "TEXT_PROMPT_TYPE_TEXT": "ಪಟ್ಯೊದೊಟ್ಟುಗೆ ಸಂದೇಸೊನು ಕೇನುಂಡು.", - "TEXT_PROMPT_TYPE_NUMBER": "ಸಂಖ್ಯೆದೊಟ್ಟುಗೆ ಸಂದೇಸೊನು ಕೇನುಂಡು", - "TEXT_PROMPT_TOOLTIP_NUMBER": "ದಿಂಜ ಬಳಕೆದಾರೆರೆನ್ ಕೇನುಂಡು.", - "TEXT_PROMPT_TOOLTIP_TEXT": "ಕೆಲವು ಪಟ್ಯೊದ ಬಳಕೆದಾರೆರೆನ್ ಕೇನುಂಡು.", - "LISTS_CREATE_EMPTY_TITLE": "ಕಾಲಿ ಪಟ್ಟಿನ್ ಸ್ರಿಸ್ಟಿಸಲೆ", - "LISTS_CREATE_EMPTY_TOOLTIP": "ಒಂಜಿ ಪಟ್ಟಿ, ೦ದ ಉದ್ದೊ, ಒವ್ವೇ ಅಂಕಿಅಂಸೊ ಇದ್ಯಾಂತಿನ ದಾಖಲೆ ಪಿರಕೊರು.", - "LISTS_CREATE_WITH_TOOLTIP": "ಒವ್ವೇ ಸಂಖ್ಯೆದ ಪಟ್ಟಿಲೆ ಅಂಸೊದೊಟ್ಟುಗೆ ರಚಿಸಲೆ", - "LISTS_CREATE_WITH_INPUT_WITH": "ಜತೆ ಪಟ್ಟಿನ್ ರಚಿಸಲೆ", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "ಪಟ್ಟಿ", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "ಸೇರಯರ, ದೆತ್ತ್‌ ಪಾಡೆರೆ ಅತ್ತಂಡ ಈ ಪಟ್ಯೊಲೆನ್ ತಡೆದ್ ಪತ್ತ್‌ದ್ ಇಬಾಗೊ ಮಲ್ಪುಲೆ.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "ಪಟ್ಟಿಡ್ ಕೆಲವು ಅಂಸೊಲೆನ್ ಸೇರಲೆ.", - "LISTS_REPEAT_TOOLTIP": "ಕೊರ್‍ನ ಮೌಲ್ಯಡು ನಿರ್ದಿಷ್ಟ ಕಾಲೊಡು ಪಿರೊತ ಪಟ್ಟಿನ್ ರಚಿಸಲೆ.", - "LISTS_REPEAT_TITLE": "%1 ಪಿರೊರ %2 ಕಾಲೊಡು ಪಟ್ಟಿಲೆನ ಅಂಸೊನು ರಚಿಸಲೆ.", - "LISTS_LENGTH_TITLE": "೧% ಉದ್ದೊ", - "LISTS_LENGTH_TOOLTIP": "ಪಟ್ಟಿದ ಉದ್ದೊನು ಪಿರಕೊರು.", - "LISTS_ISEMPTY_TITLE": "%1 ಕಾಲಿ", - "LISTS_ISEMPTY_TOOLTIP": "ಪಟ್ಯೊ ಕಾಲಿ ಪನ್ಪುನವು ಸತ್ಯೊ ಆಂಡ ಪಿರಕೊರು.", - "LISTS_INLIST": "ಪಟ್ಟಿಡ್", - "LISTS_INDEX_OF_FIRST": "ದುಂಬು ಕರಿನ ಪಟ್ಯೊನು ನಾಡ್‍ಲೆ", - "LISTS_INDEX_OF_LAST": "ಅಕೆರಿಗ್ ಕರಿನ ಪಟ್ಯೊನು ನಾಡ್‍ಲೆ", - "LISTS_INDEX_OF_TOOLTIP": "ಸುರುತ ಪಟ್ಯೊದ ಸೂಚ್ಯಿ/ಅಕೇರಿಟ್ ಸಂಭವಿಸವುನ ಸುರುತ ಪಟ್ಟಯೊದುಲಯಿದ ರಡ್ಡನೆ ಪಟ್ಯೊನು ಪಿರಕೊರು. %1 ಪಟ್ಯೊ ತಿಕಂದಿತ್ತ್‌ಂಡ ಪಿರಕೊರು.", - "LISTS_GET_INDEX_GET": "ದೆತೊನು", - "LISTS_GET_INDEX_GET_REMOVE": "ದೆತೊನಿಯರ ಬುಕ್ಕೊ ದೆಪ್ಪೆರೆ", - "LISTS_GET_INDEX_REMOVE": "ದೆಪ್ಪುಲೆ", - "LISTS_GET_INDEX_FROM_END": "# ಅಕೇರಿಡ್ದ್", - "LISTS_GET_INDEX_FIRST": "ಸುರುತ", - "LISTS_GET_INDEX_LAST": "ಕಡೆತ", - "LISTS_GET_INDEX_RANDOM": "ಗೊತ್ತು ಗುರಿದಾಂತಿನ", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 ಸುರುತ ಅಂಸೊ", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 ಅಕೇರಿತ ಅಂಸೊ", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "ನಿರ್ದಸ್ಟೊ ಜಾಗೆಡುಪ್ಪುನ ಅಂಸೊಲೆ ಪಟ್ಟಿನ್ ಪಿರಕೊರು", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "ಸುರುತ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ಪಿರಕೊರು.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "ಅಕೇರಿದ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ಪಿರಕೊರು.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "ಗೊತ್ತುಗುರಿದಾಂತಿನ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ಪಿರಕೊರು.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "ನಿರ್ದಿಸ್ಟೊ ಜಾಗೆಡುಪ್ಪುನ ಅಂಸೊಲೆ ಪಟ್ಟಿನ್ ದೆಪ್ಪು ಅತ್ತಂಡ ಪಿರಕೊರು", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "ಸುರುತ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ದೆಪ್ಪು ಅತ್ತಂಡ ಪಿರಕೊರು.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "ಅಕೇರಿದ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ದೆಪ್ಪು ಅತ್ತಂಡ ಪಿರಕೊರು.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "ಗೊತ್ತುಗುರಿದಾಂತಿನ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ದೆಪ್ಪು ಅತ್ತಂಡ ಪಿರಕೊರು.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "ನಿರ್ದಿಸ್ಟೊ ಜಾಗೆಡುಪ್ಪುನ ಅಂಸೊಲೆ ಪಟ್ಟಿನ್ ದೆಪ್ಪುಲೆ", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "ಸುರುತ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ದೆಪ್ಪು.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "ಅಕೇರಿದ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ದೆಪ್ಪು.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "ಗೊತ್ತುಗುರಿದಾಂತಿನ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ದೆಪ್ಪು.", - "LISTS_SET_INDEX_SET": "ಮಾಲ್ಪು", - "LISTS_SET_INDEX_INSERT": "ಸೇರಲ", - "LISTS_SET_INDEX_INPUT_TO": "ಅಂಚ", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "ನಿರ್ದಿಸ್ಟೊ ಜಾಗೆಡುಪ್ಪುನ ಅಂಸೊಲೆ ಪಟ್ಟಿನ್ ಮಾಲ್ಪು", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "ಸುರುತ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ಮಾಲ್ಪು.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "ಅಕೇರಿದ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ಮಾಲ್ಪು.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "ಗೊತ್ತುಗುರಿದಾಂತಿನ ಅಂಸೊಲೆನ ಪಟ್ಟಿನ್ ಮಾಲ್ಪು.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "ನಿರ್ದಿಸ್ಟೊ ಜಾಗೆಡುಪ್ಪುನ ಅಂಸೊಲೆ ಪಟ್ಟಿನ್ ಸೇರಲ", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "ಸುರುತ ಅಂಸೊಲೆ ಪಟ್ಟಿನ್ ಸೇರಲ.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "ಪಟ್ಟಿದ ಅಕೇರಿಗ್ ಈ ಅಂಸೊಲೆನ್ ಸೇರಲ.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "ಪಟ್ಟಿಗ್ ಗೊತ್ತುಗುರಿದಾಂತೆ ಅಂಸೊಲೆನ್ ಸೇರಲ.", - "LISTS_GET_SUBLIST_START_FROM_START": "ಉಪ-ಪಟ್ಯೊನು ದೆತೊನು#", - "LISTS_GET_SUBLIST_START_FROM_END": "ಉಪ-ಪಟ್ಯೊನು ದೆತೊನು#ಅಕೇರಿಡ್ದ್", - "LISTS_GET_SUBLIST_START_FIRST": "ಉಪ-ಪಟ್ಯೊನು ಸುರುಡ್ದು ದೆತೊನು", - "LISTS_GET_SUBLIST_END_FROM_START": "ಡ್ದ್", - "LISTS_GET_SUBLIST_END_FROM_END": "ಡ್ದ್ # ಅಕೇರಿಗ್", - "LISTS_GET_SUBLIST_END_LAST": "ಅಕೇರಿಡ್ದ್", - "LISTS_GET_SUBLIST_TOOLTIP": "ಪಟ್ಯೊದ ನಿರ್ದಿಷ್ಟ ಬಾಗೊದ ಪ್ರತಿನ್ ಸ್ರಸ್ಟಿಸವುಂಡು.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "%1 %2 %3 ಇಂಗಡಿಪು", - "LISTS_SORT_TOOLTIP": "ಪಟ್ಟಿಲೆ ಪ್ರತಿನ್ ಇಂಗಡಿಪುಲೆ", - "LISTS_SORT_ORDER_ASCENDING": "ಮಿತ್ತ್ ಪೋಪುನೆ", - "LISTS_SORT_ORDER_DESCENDING": "ತಿರ್ತ್ ಪೋಪುನೆ", - "LISTS_SORT_TYPE_NUMERIC": "ಸಂಕೇತೊ", - "LISTS_SORT_TYPE_TEXT": "ಅಕ್ಷರೊಲು", - "LISTS_SORT_TYPE_IGNORECASE": "ಅಕ್ಷರೊಲು, ಸಂದರ್ಭೊಡು ನಿರ್ಲಕ್ಷಿಸಲೆ", - "LISTS_SPLIT_LIST_FROM_TEXT": "ಪಟ್ಯೊಲೆ ಪಟ್ಟಿನ್ ತಯಾರ್ ಮಲ್ಪುಲೆ", - "LISTS_SPLIT_TEXT_FROM_LIST": "ಪಟ್ಟಿದ ಪಟ್ಯೊನು ತಯಾರ್ ಮಲ್ಪುಲೆ", - "LISTS_SPLIT_WITH_DELIMITER": "ಮಿತಿಸೂಚಕೊದ ಒಟ್ಟುಗು", - "LISTS_SPLIT_TOOLTIP_SPLIT": "ಗ್ರಂತೊಲೆನ ಪಟ್ಟಿಡ್ದ್ ಪಟ್ಯೊಲೆನ್ ಬೇತೆ ಮಾಲ್ತ್‌ಂಡ,ಪ್ರತಿ ಮಿತಿಸೂಚಕೊಡು ಬೇತೆ ಆಪುಂಡು.", - "LISTS_SPLIT_TOOLTIP_JOIN": "ಒಂಜಿ ಗ್ರಂತೊಡ್ದು ಒಂಜಿ ಪಟ್ಯೊದ ಪಟ್ಟಿಗ್ ಸೇರಾದ್, ಮಿತಿಸೂಚಕೊದ ಮೂಲಕೊ ಬೇತೆ ಮಲ್ಪುಲೆ.", - "VARIABLES_GET_TOOLTIP": "ಈ ವ್ಯತ್ಯಯೊದ ಮೌಲ್ಯೊನು ಪಿರಕೊರು.", - "VARIABLES_GET_CREATE_SET": "'%1' ರಚನೆ ಮಲ್ಪುಲೆ", - "VARIABLES_SET": "%1 ಡ್ದು %2 ಮಲ್ಪುಲೆ", - "VARIABLES_SET_TOOLTIP": "ಉಲಯಿ ಬರ್ಪುನವು ಸಮಪಾಲ್ ಇಪ್ಪುನಂಚ ವ್ಯತ್ಯಾಸೊ ಮಾಲ್ಪು", - "VARIABLES_SET_CREATE_GET": "'%1' ರಚನೆ ಮಲ್ಪುಲೆ", - "PROCEDURES_DEFNORETURN_TITLE": "ಇಂದೆಕ್", - "PROCEDURES_DEFNORETURN_PROCEDURE": "ಎಂಚಿನಾಂಡಲ ಮಲ್ಪು", - "PROCEDURES_BEFORE_PARAMS": "ಜೊತೆ:", - "PROCEDURES_CALL_BEFORE_PARAMS": "ಜೊತೆ:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "ಉತ್ಪಾದನೆ ದಾಂತಿನ ಕಾರ್ಯೊನು ಸ್ರಿಸ್ಟಿಸಲೆ.", - "PROCEDURES_DEFNORETURN_COMMENT": "ಈ ಕಾರ್ಯೊನು ಇವರಿಸಲೆ...", - "PROCEDURES_DEFRETURN_RETURN": "ಪಿರಪೋ", - "PROCEDURES_DEFRETURN_TOOLTIP": "ಉತ್ಪಾದನೆ ದಾಂತಿನ ಕಾರ್ಯೊನು ಸ್ರಿಸ್ಟಿಸಲೆ.", - "PROCEDURES_ALLOW_STATEMENTS": "ಹೇಳಿಕೆಗ್ ಅವಕಾಸೊ", - "PROCEDURES_DEF_DUPLICATE_WARNING": "ಎಚ್ಚರಿಕೆ: ಈ ಕಾರ್ಯೊ ನಕಲಿ ಮಾನದಂಡೊನು ಹೊಂದ್‍ದ್ಂಡ್.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/ಪ್ರೊಸಿಜರ್_%28ಕಂಪ್ಯೂಟರ್_ಸೈನ್ಸ್%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "'%1' ಬಳಕೆದಾರೆರೆ ಕಾರ್ಯೊನು ನಡಪಾಲೆ.", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/ಪ್ರೊಸಿಜರ್_%28ಕಂಪ್ಯೂಟರ್_ಸೈನ್ಸ್%29", - "PROCEDURES_CALLRETURN_TOOLTIP": " '%1' ಬಳಕೆದಾರೆರೆ ಕಾರ್ಯೊನು ನಡಪಾಲೆ ಬುಕ್ಕೊ ಅಯಿತ ಉತ್ಪಾದನೆನ್ ಉಪಯೋಗಿಸಲೆ.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "ಉಲಪರಿಪು", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "ಸೇರಯರ, ದೆತ್ತ್‌ ಪಾಡೆರೆ ಅತ್ತಂಡ ಪಿರಕೋರಿಕೆದ ಉಲಪರಿಪುದ ಕಾರ್ಯೊನು ಮಲ್ಪುಲೆ.", - "PROCEDURES_MUTATORARG_TITLE": "ಉಲಪರಿಪುದ ಪುದರ್:", - "PROCEDURES_MUTATORARG_TOOLTIP": "ಕಾರ್ಯೊದ ಉಲಪರಿಪುನು ಸೇರಲೆ.", - "PROCEDURES_HIGHLIGHT_DEF": "ದೇರ್ತ್ ತೋಜುನ ಕಾರ್ಯೊದ ವ್ಯಾಕ್ಯಾನೊ", - "PROCEDURES_CREATE_DO": " '%1'ನ್ ರಚಿಸಲೆ", - "PROCEDURES_IFRETURN_TOOLTIP": "ಮೌಲ್ಯೊ ಸತ್ಯೊ ಆಯಿನೆಡ್ದ್ ಬುಕ್ಕೊನೆ ರಡ್ಡನೆ ಮೌಲ್ಯೊನು ಪಿರಕೊರು.", - "PROCEDURES_IFRETURN_WARNING": "ಎಚ್ಚರಿಕೆ:ವ್ಯಾಕ್ಯಾನೊದ ಕಾರ್ಯೊನು ತಡೆ ಮಲ್ಪೆರೆ ಮಾತ್ರೊ ಇಂದೆತ ಉಪಯೊಗ." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/th.json b/backend/_pv_1_3_5/static/blockly/msg/json/th.json deleted file mode 100755 index 4955576d7..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/th.json +++ /dev/null @@ -1,311 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Azpirin", - "Octahedron80", - "Horus", - "Roysheng" - ] - }, - "VARIABLES_DEFAULT_NAME": "รายการ", - "TODAY": "วันนี้", - "DUPLICATE_BLOCK": "ทำสำเนา", - "ADD_COMMENT": "ใส่คำอธิบาย", - "REMOVE_COMMENT": "เอาคำอธิบายออก", - "EXTERNAL_INPUTS": "อินพุตภายนอก", - "INLINE_INPUTS": "อินพุตในบรรทัด", - "DELETE_BLOCK": "ลบบล็อก", - "DELETE_X_BLOCKS": "ลบ %1 บล็อก", - "DELETE_ALL_BLOCKS": "ลบ %1 บล็อกทั้งหมด?", - "CLEAN_UP": "จัดเรียงบล็อกให้เป็นแถว", - "COLLAPSE_BLOCK": "ย่อบล็อก", - "COLLAPSE_ALL": "ย่อบล็อก", - "EXPAND_BLOCK": "ขยายบล็อก", - "EXPAND_ALL": "ขยายบล็อก", - "DISABLE_BLOCK": "ปิดใช้งานบล็อก", - "ENABLE_BLOCK": "เปิดใช้งานบล็อก", - "HELP": "ช่วยเหลือ", - "UNDO": "ย้อนกลับ", - "REDO": "ทำซ้ำ", - "CHANGE_VALUE_TITLE": "เปลี่ยนค่า:", - "RENAME_VARIABLE": "เปลี่ยนชื่อตัวแปร...", - "RENAME_VARIABLE_TITLE": "เปลี่ยนชื่อตัวแปร '%1' ทั้งหมดเป็น:", - "NEW_VARIABLE": "สร้างตัวแปร...", - "NEW_VARIABLE_TITLE": "ชื่อตัวแปรใหม่:", - "COLOUR_PICKER_HELPURL": "https://th.wikipedia.org/wiki/สี", - "COLOUR_PICKER_TOOLTIP": "เลือกสีจากจานสี", - "COLOUR_RANDOM_TITLE": "สุ่มสี", - "COLOUR_RANDOM_TOOLTIP": "เลือกสีแบบสุ่ม", - "COLOUR_RGB_TITLE": "สีที่ประกอบด้วย", - "COLOUR_RGB_RED": "ค่าสีแดง", - "COLOUR_RGB_GREEN": "ค่าสีเขียว", - "COLOUR_RGB_BLUE": "ค่าสีน้ำเงิน", - "COLOUR_RGB_TOOLTIP": "สร้างสีด้วยการกำหนดค่าสีแดง เขียว และน้ำเงิน ค่าทั้งหมดต้องอยู่ระหว่าง 0 ถึง 100", - "COLOUR_BLEND_TITLE": "ผสม", - "COLOUR_BLEND_COLOUR1": "สีที่ 1", - "COLOUR_BLEND_COLOUR2": "สีที่ 2", - "COLOUR_BLEND_RATIO": "อัตราส่วน", - "COLOUR_BLEND_TOOLTIP": "ผสมสองสีเข้าด้วยกันด้วยอัตราส่วน (0.0 - 1.0)", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "ทำซ้ำ %1 ครั้ง", - "CONTROLS_REPEAT_INPUT_DO": "ทำ:", - "CONTROLS_REPEAT_TOOLTIP": "ทำซ้ำบางคำสั่งหลายครั้ง", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "ทำซ้ำขณะที่", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "ทำซ้ำจนกระทั่ง", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "ขณะที่ค่าเป็นจริง ก็จะทำบางคำสั่ง", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "ขณะที่ค่าเป็นเท็จ ก็จะทำบางคำสั่ง", - "CONTROLS_FOR_TOOLTIP": "ตัวแปร '%1' จะเริ่มจากจำนวนเริ่มต้น ไปจนถึงจำนวนสุดท้าย ตามระยะที่กำหนด และ ทำบล็อกที่กำหนดไว้", - "CONTROLS_FOR_TITLE": "นับด้วย %1 จาก %2 จนถึง %3 เปลี่ยนค่าทีละ %4", - "CONTROLS_FOREACH_TITLE": "จากทุกรายการ %1 ในรายชื่อ %2", - "CONTROLS_FOREACH_TOOLTIP": "จากทุกรายการในรายชื่อ ตั้งค่าตัวแปร \"%1\" เป็นรายการ และทำตามคำสั่งที่กำหนดไว้", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "ออกจากการวนซ้ำ", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "เริ่มการวนซ้ำรอบต่อไป", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "ออกจากการวนซ้ำที่อยู่", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "ข้ามคำสั่งที่เหลืออยู่ และเริ่มต้นวนซ้ำรอบต่อไป", - "CONTROLS_FLOW_STATEMENTS_WARNING": "คำเตือน: บล็อกนี้ใช้งานได้ภายในการวนซ้ำเท่านั้น", - "CONTROLS_IF_TOOLTIP_1": "ว่าเงื่อนไขเป็นจริง ก็จะ \"ทำ\" ตามที่กำหนด", - "CONTROLS_IF_TOOLTIP_2": "ถ้าเงื่อนไขเป็นจริง ก็จะ \"ทำ\" ตามที่กำหนด แต่ถ้าเงื่อนไขเป็นเท็จก็จะทำ \"นอกเหนือจากนี้\"", - "CONTROLS_IF_TOOLTIP_3": "ถ้าเงื่อนไขแรกเป็นจริง ก็จะทำตามคำสั่งในบล็อกแรก แต่ถ้าไม่ก็จะไปตรวจเงื่อนไขที่สอง ถ้าเงื่อนไขที่สองเป็นจริง ก็จะทำตามเงื่อนไขในบล็อกที่สองนี้", - "CONTROLS_IF_TOOLTIP_4": "ถ้าเงื่อนไขแรกเป็นจริง ก็จะทำคำสั่งในบล็อกแรก จากนั้นจะข้ามคำสั่งในบล็อกที่เหลือ แต่ถ้าเงื่อนไขแรกเป็นเท็จ ก็จะทำการตรวจเงื่อนไขที่สอง ถ้าเงื่อนไขที่สองเป็นจริง ก็จะทำตามคำสั่งในบล็อกที่สอง จากนั้นจะข้ามคำสั่งในบล็อกที่เหลือ แต่ถ้าทั้งเงื่อนไขแรกและเงื่อนไขที่สองเป็นเท็จทั้งหมด ก็จะมาทำบล็อกที่สาม", - "CONTROLS_IF_MSG_IF": "ถ้า", - "CONTROLS_IF_MSG_ELSEIF": "นอกเหนือจากนี้ ถ้า", - "CONTROLS_IF_MSG_ELSE": "นอกเหนือจากนี้", - "CONTROLS_IF_IF_TOOLTIP": "เพิ่ม ลบ หรือจัดเรียงบล็อก \"ถ้า\" นี้ใหม่", - "CONTROLS_IF_ELSEIF_TOOLTIP": "กำหนดเงื่อนไขของบล็อก \"ถ้า\"", - "CONTROLS_IF_ELSE_TOOLTIP": "เพิ่มสิ่งสุดท้าย ที่จะตรวจจับความเป็นไปได้ทั้งหมดของบล็อก \"ถ้า\"", - "LOGIC_COMPARE_HELPURL": "https://th.wikipedia.org/wiki/อสมการ", - "LOGIC_COMPARE_TOOLTIP_EQ": "คืนค่าเป็น \"จริง\" ถ้าค่าที่ใส่ทั้งสองค่านั้นเท่ากัน", - "LOGIC_COMPARE_TOOLTIP_NEQ": "คืนค่าเป็น \"จริง\" ถ้าค่าที่ใส่ทั้งสองค่านั้นไม่เท่ากัน", - "LOGIC_COMPARE_TOOLTIP_LT": "คืนค่าเป็น \"จริง\" ถ้าค่าแรกน้อยกว่าค่าที่สอง", - "LOGIC_COMPARE_TOOLTIP_LTE": "คืนค่าเป็น \"จริง\" ถ้าค่าแรกน้อยกว่าหรือเท่ากับค่าที่สอง", - "LOGIC_COMPARE_TOOLTIP_GT": "คืนค่าเป็น \"จริง\" ถ้าค่าแรกมากกว่าค่าที่สอง", - "LOGIC_COMPARE_TOOLTIP_GTE": "คืนค่าเป็น \"จริง\" ถ้าค่าแรกมากกว่าหรือเท่ากับค่าที่สอง", - "LOGIC_OPERATION_TOOLTIP_AND": "คืนค่าเป็น \"จริง\" ถ้าค่าทั้งสองค่าเป็นจริง", - "LOGIC_OPERATION_AND": "และ", - "LOGIC_OPERATION_TOOLTIP_OR": "คืนค่าเป็น \"จริง\" ถ้ามีอย่างน้อยหนึ่งค่าที่เป็นจริง", - "LOGIC_OPERATION_OR": "หรือ", - "LOGIC_NEGATE_TITLE": "ไม่ %1", - "LOGIC_NEGATE_TOOLTIP": "คืนค่าเป็น \"จริง\" ถ้าค่าที่ใส่เป็นเท็จ คืนค่าเป็น \"เท็จ\" ถ้าค่าที่ใส่เป็นจริง", - "LOGIC_BOOLEAN_TRUE": "จริง", - "LOGIC_BOOLEAN_FALSE": "เท็จ", - "LOGIC_BOOLEAN_TOOLTIP": "คืนค่าเป็นจริงหรือเท็จ", - "LOGIC_NULL": "ไม่กำหนด", - "LOGIC_NULL_TOOLTIP": "คืนค่า \"ไม่กำหนด\"", - "LOGIC_TERNARY_CONDITION": "ทดสอบ", - "LOGIC_TERNARY_IF_TRUE": "ถ้า เป็นจริง", - "LOGIC_TERNARY_IF_FALSE": "ถ้า เป็นเท็จ", - "LOGIC_TERNARY_TOOLTIP": "ตรวจสอบเงื่อนไขใน \"ทดสอบ\" ถ้าเงื่อนไขเป็นจริง จะคืนค่า \"ถ้า เป็นจริง\" ถ้าเงื่อนไขเป็นเท็จ จะคืนค่า \"ถ้า เป็นเท็จ\"", - "MATH_NUMBER_HELPURL": "https://th.wikipedia.org/wiki/จำนวน", - "MATH_NUMBER_TOOLTIP": "จำนวน", - "MATH_ARITHMETIC_HELPURL": "https://th.wikipedia.org/wiki/เลขคณิต", - "MATH_ARITHMETIC_TOOLTIP_ADD": "คืนค่าผลรวมของตัวเลขทั้งสองจำนวน", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "คืนค่าผลต่างของตัวเลขทั้งสองจำนวน", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "คืนค่าผลคูณของตัวเลขทั้งสองจำนวน", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "คืนค่าผลหารของตัวเลขทั้งสองจำนวน", - "MATH_ARITHMETIC_TOOLTIP_POWER": "คืนค่าผลการยกกำลัง โดยตัวเลขแรกเป็นฐาน และตัวเลขที่สองเป็นเลขชี้กำลัง", - "MATH_SINGLE_HELPURL": "https://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "รากที่สอง", - "MATH_SINGLE_TOOLTIP_ROOT": "คืนค่ารากที่สองของตัวเลข", - "MATH_SINGLE_OP_ABSOLUTE": "ค่าสัมบูรณ์", - "MATH_SINGLE_TOOLTIP_ABS": "คืนค่าค่าสัมบูรณ์ของตัวเลข", - "MATH_SINGLE_TOOLTIP_NEG": "คืนค่าติดลบของตัวเลข", - "MATH_SINGLE_TOOLTIP_LN": "คืนค่าลอการิทึมธรรมชาติของตัวเลข", - "MATH_SINGLE_TOOLTIP_LOG10": "คืนค่าลอการิทึมฐานสิบของตัวเลข", - "MATH_SINGLE_TOOLTIP_EXP": "คืนค่า e ยกกำลังด้วยตัวเลข", - "MATH_SINGLE_TOOLTIP_POW10": "คืนค่า 10 ยกกำลังด้วยตัวเลข", - "MATH_TRIG_HELPURL": "https://th.wikipedia.org/wiki/ฟังก์ชันตรีโกณมิติ", - "MATH_TRIG_TOOLTIP_SIN": "คืนค่า sine ขององศา (ไม่ใช่เรเดียน)", - "MATH_TRIG_TOOLTIP_COS": "คืนค่า cosine ขององศา (ไม่ใช่เรเดียน)", - "MATH_TRIG_TOOLTIP_TAN": "คืนค่า tangent ขององศา (ไม่ใช่เรเดียน)", - "MATH_TRIG_TOOLTIP_ASIN": "คืนค่า arcsine ของตัวเลข", - "MATH_TRIG_TOOLTIP_ACOS": "คืนค่า arccosine ของตัวเลข", - "MATH_TRIG_TOOLTIP_ATAN": "คืนค่า arctangent ของตัวเลข", - "MATH_CONSTANT_HELPURL": "https://th.wikipedia.org/wiki/ค่าคงตัวทางคณิตศาสตร์", - "MATH_CONSTANT_TOOLTIP": "คืนค่าคงตัวทางคณิตศาสตร์ที่พบบ่อยๆ เช่น π (3.141…), e (2.718…), φ (1.618…), รากที่สอง (1.414…), รากที่ ½ (0.707…), ∞ (อนันต์)", - "MATH_IS_EVEN": "เป็นจำนวนคู่", - "MATH_IS_ODD": "เป็นจำนวนคี่", - "MATH_IS_PRIME": "เป็นจำนวนเฉพาะ", - "MATH_IS_WHOLE": "เป็นเลขจำนวนเต็ม", - "MATH_IS_POSITIVE": "เป็นเลขบวก", - "MATH_IS_NEGATIVE": "เป็นเลขติดลบ", - "MATH_IS_DIVISIBLE_BY": "หารลงตัว", - "MATH_IS_TOOLTIP": "ตรวจว่าตัวเลขเป็นจำนวนคู่ จำนวนคี่ จำนวนเฉพาะ จำนวนเต็ม เลขบวก เลขติดลบ หรือหารด้วยเลขที่กำหนดลงตัวหรือไม่ คืนค่าเป็นจริงหรือเท็จ", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "เปลี่ยนค่า %1 เป็น %2", - "MATH_CHANGE_TOOLTIP": "เพิ่มค่าของตัวแปร \"%1\"", - "MATH_ROUND_HELPURL": "https://th.wikipedia.org/wiki/การปัดเศษ", - "MATH_ROUND_TOOLTIP": "ปัดเศษของตัวเลขขึ้นหรือลง", - "MATH_ROUND_OPERATOR_ROUND": "ปัดเศษ", - "MATH_ROUND_OPERATOR_ROUNDUP": "ปัดเศษขึ้น", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "ปัดเศษลง", - "MATH_ONLIST_OPERATOR_SUM": "ผลรวมของรายการ", - "MATH_ONLIST_TOOLTIP_SUM": "คืนค่าผลรวมของตัวเลขทั้งหมดในรายการ", - "MATH_ONLIST_OPERATOR_MIN": "น้อยที่สุดในรายการ", - "MATH_ONLIST_TOOLTIP_MIN": "คืนค่าตัวเลขที่น้อยที่สุดในรายการ", - "MATH_ONLIST_OPERATOR_MAX": "มากที่สุดในรายการ", - "MATH_ONLIST_TOOLTIP_MAX": "คืนค่าตัวเลขที่มากที่สุดในรายการ", - "MATH_ONLIST_OPERATOR_AVERAGE": "ค่าเฉลี่ยของรายการ", - "MATH_ONLIST_TOOLTIP_AVERAGE": "คืนค่าเฉลี่ยของรายการ", - "MATH_ONLIST_OPERATOR_MEDIAN": "ค่ามัธยฐานของรายการ", - "MATH_ONLIST_TOOLTIP_MEDIAN": "คืนค่ามัธยฐานของรายการ", - "MATH_ONLIST_OPERATOR_MODE": "ฐานนิยมของรายการ", - "MATH_ONLIST_TOOLTIP_MODE": "คืนค่าฐานนิยมของรายการ", - "MATH_ONLIST_OPERATOR_STD_DEV": "ส่วนเบี่ยงเบนมาตรฐานของรายการ", - "MATH_ONLIST_TOOLTIP_STD_DEV": "คืนค่าส่วนเบี่ยงเบนมาตรฐานของรายการ", - "MATH_ONLIST_OPERATOR_RANDOM": "สุ่มรายการ", - "MATH_ONLIST_TOOLTIP_RANDOM": "สุ่มคืนค่าสิ่งที่อยู่ในรายการ", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "เศษของ %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "คืนค่าเศษที่ได้จากการหารของตัวเลขทั้งสองจำนวน", - "MATH_CONSTRAIN_TITLE": "จำกัดค่า %1 ต่ำสุด %2 สูงสุด %3", - "MATH_CONSTRAIN_TOOLTIP": "จำกัดค่าของตัวเลขให้อยู่ในช่วงที่กำหนด", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "สุ่มเลขจำนวนเต็มตั้งแต่ %1 จนถึง %2", - "MATH_RANDOM_INT_TOOLTIP": "สุ่มเลขจำนวนเต็มจากช่วงที่กำหนด", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "สุ่มเลขเศษส่วน", - "MATH_RANDOM_FLOAT_TOOLTIP": "สุ่มเลขเศษส่วน ตั้งแต่ 0.0 แต่ไม่เกิน 1.0", - "TEXT_TEXT_HELPURL": "https://th.wikipedia.org/wiki/สายอักขระ", - "TEXT_TEXT_TOOLTIP": "ตัวหนังสือ คำ หรือข้อความ", - "TEXT_JOIN_TITLE_CREATEWITH": "สร้างข้อความด้วย", - "TEXT_JOIN_TOOLTIP": "สร้างข้อความด้วยการรวมจำนวนของรายการเข้าด้วยกัน", - "TEXT_CREATE_JOIN_TITLE_JOIN": "รวม", - "TEXT_CREATE_JOIN_TOOLTIP": "เพิ่ม ลบ หรือจัดเรียงบล็อกข้อความนี้ใหม่", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "เพิ่มรายการเข้าไปในข้อความ", - "TEXT_APPEND_TO": "นำเอา", - "TEXT_APPEND_APPENDTEXT": "ต่อด้วยข้อความ", - "TEXT_APPEND_TOOLTIP": "ต่อข้อความให้ตัวแปร \"%1\"", - "TEXT_LENGTH_TITLE": "ความยาวของ %1", - "TEXT_LENGTH_TOOLTIP": "คืนค่าความยาวของข้อความ (รวมช่องว่าง)", - "TEXT_ISEMPTY_TITLE": "%1 ว่าง", - "TEXT_ISEMPTY_TOOLTIP": "คืนค่าจริง ถ้าข้อความยังว่าง", - "TEXT_INDEXOF_TOOLTIP": "คืนค่าตำแหน่งที่พบข้อความแรกอยู่ในข้อความที่สอง คืนค่า %1 ถ้าหาไม่พบ", - "TEXT_INDEXOF_INPUT_INTEXT": "ในข้อความ", - "TEXT_INDEXOF_OPERATOR_FIRST": "หาข้อความแรกที่พบ", - "TEXT_INDEXOF_OPERATOR_LAST": "หาข้อความสุดท้ายที่พบ", - "TEXT_CHARAT_INPUT_INTEXT": "ในข้อความ", - "TEXT_CHARAT_FROM_START": "ดึง ตัวอักษรตัวที่", - "TEXT_CHARAT_FROM_END": "ดึง ตัวอักษรตัวที่ # จากท้าย", - "TEXT_CHARAT_FIRST": "ดึง ตัวอักษรตัวแรก", - "TEXT_CHARAT_LAST": "ดึง ตัวอักษรตัวสุดท้าย", - "TEXT_CHARAT_RANDOM": "ถึงตัวอักษรแบบสุ่ม", - "TEXT_CHARAT_TOOLTIP": "คืนค่าตัวอักษรจากตำแหน่งที่ระบุ", - "TEXT_GET_SUBSTRING_TOOLTIP": "คืนค่าบางส่วนของข้อความ", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "ในข้อความ", - "TEXT_GET_SUBSTRING_START_FROM_START": "แยกข้อความย่อยตั้งแต่ ตัวอักษรที่", - "TEXT_GET_SUBSTRING_START_FROM_END": "แยกข้อความย่อยตั้งแต่ ตัวอักษรที่ # จากท้าย", - "TEXT_GET_SUBSTRING_START_FIRST": "แยกข้อความย่อยตั้งแต่ ตัวอักษรแรก", - "TEXT_GET_SUBSTRING_END_FROM_START": "จนถึง ตัวอักษรที่", - "TEXT_GET_SUBSTRING_END_FROM_END": "จนถึง ตัวอักษรที่ # จากท้าย", - "TEXT_GET_SUBSTRING_END_LAST": "จนถึง ตัวอักษรสุดท้าย", - "TEXT_CHANGECASE_TOOLTIP": "คืนค่าสำเนาของข้อความในกรณีต่างๆ", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "เปลี่ยนเป็น ตัวพิมพ์ใหญ่", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "เปลี่ยนเป็น ตัวพิมพ์เล็ก", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "เปลี่ยนเป็น ตัวอักษรแรกเป็นตัวพิมพ์ใหญ่", - "TEXT_TRIM_TOOLTIP": "คืนค่าสำเนาของข้อความที่ลบเอาช่องว่างหน้าและหลังข้อความออกแล้ว", - "TEXT_TRIM_OPERATOR_BOTH": "ลบช่องว่างทั้งสองข้างของ", - "TEXT_TRIM_OPERATOR_LEFT": "ลบช่องว่างด้านหน้าของ", - "TEXT_TRIM_OPERATOR_RIGHT": "ลบช่องว่างข้างท้ายของ", - "TEXT_PRINT_TITLE": "พิมพ์ %1", - "TEXT_PRINT_TOOLTIP": "พิมพ์ข้อความ ตัวเลข หรือค่าอื่นๆ", - "TEXT_PROMPT_TYPE_TEXT": "แสดงหน้าต่างข้อความ", - "TEXT_PROMPT_TYPE_NUMBER": "แสดงหน้าต่างตัวเลข", - "TEXT_PROMPT_TOOLTIP_NUMBER": "แสดงหน้าต่างให้ผู้ใช้ใส่ตัวเลข", - "TEXT_PROMPT_TOOLTIP_TEXT": "แสดงหน้าต่างให้ผู้ใช้ใส่ข้อความ", - "LISTS_CREATE_EMPTY_TITLE": "สร้างรายการเปล่า", - "LISTS_CREATE_EMPTY_TOOLTIP": "สร้างรายการเปล่า (ความยาวเป็น 0) ยังไม่มีข้อมูลใดๆ อยู่", - "LISTS_CREATE_WITH_TOOLTIP": "สร้างรายการพร้อมด้วยไอเท็ม", - "LISTS_CREATE_WITH_INPUT_WITH": "สร้างข้อความด้วย", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "รายการ", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "เพิ่ม ลบ หรือจัดเรียงบล็อกรายการนี้ใหม่", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "เพิ่มไอเท็มเข้าไปในรายการ", - "LISTS_REPEAT_TOOLTIP": "สร้างรายการที่ประกอบด้วยค่าตามที่ระบุในจำนวนตามที่ต้องการ", - "LISTS_REPEAT_TITLE": "สร้างรายการที่มีไอเท็ม %1 จำนวน %2", - "LISTS_LENGTH_TITLE": "ความยาวของ %1", - "LISTS_LENGTH_TOOLTIP": "ส่งคืนค่าความยาวของรายการ", - "LISTS_ISEMPTY_TITLE": "%1 ว่างเปล่า", - "LISTS_ISEMPTY_TOOLTIP": "คืนค่าเป็นจริง ถ้ารายการยังว่างเปล่า", - "LISTS_INLIST": "ในรายการ", - "LISTS_INDEX_OF_FIRST": "หาอันแรกที่พบ", - "LISTS_INDEX_OF_LAST": "หาอันสุดท้ายที่พบ", - "LISTS_INDEX_OF_TOOLTIP": "คืนค่าตำแหน่งของไอเท็มอันแรก/สุดท้ายที่พบในรายการ คืนค่า %1 ถ้าหาไม่พบ", - "LISTS_GET_INDEX_GET": "เรียกดู", - "LISTS_GET_INDEX_GET_REMOVE": "เรียกดูและเอาออก", - "LISTS_GET_INDEX_REMOVE": "เอาออก", - "LISTS_GET_INDEX_FROM_END": "# จากท้าย", - "LISTS_GET_INDEX_FIRST": "แรกสุด", - "LISTS_GET_INDEX_LAST": "ท้ายสุด", - "LISTS_GET_INDEX_RANDOM": "สุ่ม", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 คือไอเท็มอันแรกสุด", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 คือไอเท็มอันท้ายสุด", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "คืนค่าเป็นไอเท็มตามตำแหน่งที่ระบุ", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "คืนค่าไอเท็มอันแรกในรายการ", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "คืนค่าไอเท็มอันสุดท้ายในรายการ", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "คืนค่าไอเท็มแบบสุ่มจากรายการ", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "เอาออก และคืนค่าไอเท็มในตำแหน่งที่ระบุจากรายการ", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "เอาออก และคืนค่าไอเท็มอันแรกในรายการ", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "เอาออก และคืนค่าไอเท็มอันสุดท้ายในรายการ", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "เอาออก และคืนค่าไอเท็มแบบสุ่มจากรายการ", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "คืนค่าเป็นไอเท็มตามตำแหน่งที่ระบุ", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "เอาไอเท็มแรกสุดในรายการออก", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "เอาไอเท็มอันท้ายสุดในรายการออก", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "เอาไอเท็มแบบสุ่มจากรายการออก", - "LISTS_SET_INDEX_SET": "กำหนด", - "LISTS_SET_INDEX_INSERT": "แทรกที่", - "LISTS_SET_INDEX_INPUT_TO": "เป็น", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "กำหนดไอเท็มในตำแหน่งที่ระบุในรายการ", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "กำหนดไอเท็มอันแรกในรายการ", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "กำหนดไอเท็มอันสุดท้ายในรายการ", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "กำหนดไอเท็มแบบสุ่มในรายการ", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "แทรกไอเท็มเข้าไปในตำแหน่งที่กำหนด", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "แทรกไอเท็มเข้าไปเป็นอันแรกสุดของรายการ", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "เพิ่มไอเท็มเข้าไปท้ายสุดของรายการ", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "เพิ่มไอเท็มเข้าไปในรายการแบบสุ่ม", - "LISTS_GET_SUBLIST_START_FROM_START": "ดึงรายการย่อยจาก #", - "LISTS_GET_SUBLIST_START_FROM_END": "ดึงรายการย่อยจาก # จากท้ายสุด", - "LISTS_GET_SUBLIST_START_FIRST": "ดึงรายการย่อยทั้งแต่แรกสุด", - "LISTS_GET_SUBLIST_END_FROM_START": "จนถึง #", - "LISTS_GET_SUBLIST_END_FROM_END": "ถึง # จากท้ายสุด", - "LISTS_GET_SUBLIST_END_LAST": "ถึง ท้ายสุด", - "LISTS_GET_SUBLIST_TOOLTIP": "สร้างสำเนารายการในช่วงที่กำหนด", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "เรียงลำดับ %1 %2 %3", - "LISTS_SORT_TOOLTIP": "เรียงลำดับสำเนาของรายชื่อ", - "LISTS_SORT_ORDER_ASCENDING": "น้อยไปหามาก", - "LISTS_SORT_ORDER_DESCENDING": "มากไปหาน้อย", - "LISTS_SORT_TYPE_NUMERIC": "ตัวเลข", - "LISTS_SORT_TYPE_TEXT": "ตัวอักษร", - "LISTS_SORT_TYPE_IGNORECASE": "ตัวอักษร", - "LISTS_SPLIT_LIST_FROM_TEXT": "สร้างรายการจากข้อความ", - "LISTS_SPLIT_TEXT_FROM_LIST": "สร้างข้อความจากรายการ", - "LISTS_SPLIT_WITH_DELIMITER": "ด้วยตัวคั่น", - "LISTS_SPLIT_TOOLTIP_SPLIT": "แบ่งข้อความเป็นรายการข้อความ แยกแต่ละรายการด้วยตัวคั่น", - "LISTS_SPLIT_TOOLTIP_JOIN": "รวมรายการข้อความเป็นข้อความเดียว แบ่งด้วยตัวคั่น", - "VARIABLES_GET_TOOLTIP": "คืนค่าของตัวแปรนี้", - "VARIABLES_GET_CREATE_SET": "สร้าง \"กำหนด %1\"", - "VARIABLES_SET": "กำหนด %1 จนถึง %2", - "VARIABLES_SET_TOOLTIP": "กำหนดให้ตัวแปรนี้เท่ากับการป้อนข้อมูล", - "VARIABLES_SET_CREATE_GET": "สร้าง \"get %1\"", - "PROCEDURES_DEFNORETURN_TITLE": "ถึง", - "PROCEDURES_DEFNORETURN_PROCEDURE": "ทำอะไรบางอย่าง", - "PROCEDURES_BEFORE_PARAMS": "ด้วย:", - "PROCEDURES_CALL_BEFORE_PARAMS": "ด้วย:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "สร้างฟังก์ชันที่ไม่มีผลลัพธ์", - "PROCEDURES_DEFNORETURN_COMMENT": "อธิบายฟังก์ชันนี้", - "PROCEDURES_DEFRETURN_RETURN": "คืนค่า", - "PROCEDURES_DEFRETURN_TOOLTIP": "สร้างฟังก์ชันที่มีผลลัพธ์", - "PROCEDURES_ALLOW_STATEMENTS": "ข้อความที่ใช้ได้", - "PROCEDURES_DEF_DUPLICATE_WARNING": "ระวัง: ฟังก์ชันนี้มีพารามิเตอร์ที่มีชื่อซ้ำกัน", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_(computer_science)", - "PROCEDURES_CALLNORETURN_TOOLTIP": "เรียกใช้ฟังก์ชันที่สร้างโดยผู้ใช้ \"%1\"", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_(computer_science)", - "PROCEDURES_CALLRETURN_TOOLTIP": "เรียกใช้ฟังก์ชันที่สร้างโดยผู้ใช้ \"%1\" และใช้ผลลัพธ์ของมัน", - "PROCEDURES_MUTATORCONTAINER_TITLE": "นำเข้า", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "เพิ่ม, ลบ, หรือจัดเรียง ข้อมูลที่ป้อนเข้าฟังก์ชันนี้", - "PROCEDURES_MUTATORARG_TITLE": "ชื่อนำเข้า:", - "PROCEDURES_MUTATORARG_TOOLTIP": "เพิ่มค่าป้อนเข้าฟังก์ชัน", - "PROCEDURES_HIGHLIGHT_DEF": "เน้นฟังก์ชันนิยาม", - "PROCEDURES_CREATE_DO": "สร้าง \"%1\"", - "PROCEDURES_IFRETURN_TOOLTIP": "ถ้ามีค่าเป็นจริง ให้คืนค่าที่สอง", - "PROCEDURES_IFRETURN_WARNING": "ระวัง: บล็อกนี้ใช้เฉพาะในการสร้างฟังก์ชันเท่านั้น" -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/tl.json b/backend/_pv_1_3_5/static/blockly/msg/json/tl.json deleted file mode 100755 index 57988fa19..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/tl.json +++ /dev/null @@ -1,305 +0,0 @@ -{ - "@metadata": { - "authors": [ - "아라" - ] - }, - "VARIABLES_DEFAULT_NAME": "item", - "DUPLICATE_BLOCK": "Kaparehas", - "ADD_COMMENT": "Dagdag komento", - "REMOVE_COMMENT": "Remove Comment", - "EXTERNAL_INPUTS": "Panlabas na Inputs", - "INLINE_INPUTS": "Inline na Inputs", - "DELETE_BLOCK": "burahin ang bloke", - "DELETE_X_BLOCKS": "burahin %1 ng bloke", - "COLLAPSE_BLOCK": "bloke", - "COLLAPSE_ALL": "bloke", - "EXPAND_BLOCK": "Palawakin ang Block", - "EXPAND_ALL": "Palawakin ang Blocks", - "DISABLE_BLOCK": "Ipangwalang bisa ang Block", - "ENABLE_BLOCK": "Bigyan ng bisa ang Block", - "HELP": "Tulong", - "CHANGE_VALUE_TITLE": "pagbago ng value:", - "RENAME_VARIABLE": "Rename variable...", - "RENAME_VARIABLE_TITLE": "Rename all '%1' variables to:", - "NEW_VARIABLE": "New variable...", - "NEW_VARIABLE_TITLE": "New variable name:", - "COLOUR_PICKER_HELPURL": "http://en.wikipedia.org/wiki/Color", - "COLOUR_PICKER_TOOLTIP": "pagpili ng kulay sa paleta.", - "COLOUR_RANDOM_TITLE": "iba ibang kulay", - "COLOUR_RANDOM_TOOLTIP": "pagpili ng iba't ibang kulay.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "kulayan ng", - "COLOUR_RGB_RED": "pula", - "COLOUR_RGB_GREEN": "berde", - "COLOUR_RGB_BLUE": "asul", - "COLOUR_RGB_TOOLTIP": "gumawa ng kulay ng may espisipikong dami ng kulay pula, berde, at asul. lahat ng halaga ay dapat sa pagitan ng 0 at 100.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "halo", - "COLOUR_BLEND_COLOUR1": "kulay 1", - "COLOUR_BLEND_COLOUR2": "kulay 2", - "COLOUR_BLEND_RATIO": "proporsyon", - "COLOUR_BLEND_TOOLTIP": "Paghalo ng dalawang kulay kasama ng ibinigay na proporsyon (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "http://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "ulitin %1 beses", - "CONTROLS_REPEAT_INPUT_DO": "gawin", - "CONTROLS_REPEAT_TOOLTIP": "gumawa ng ilang pangungusap ng ilang ulit.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "ulitin habang", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "ulitin hanggang", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Habang ang value ay true, gagawin ang ibang statements.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Habang ang value ay false, gagawin ang ibang statements.", - "CONTROLS_FOR_TOOLTIP": "Magkaroon ng mga variable na \"%1\" na tanggalin ng mga halaga mula sa simulang numero hanggang sa dulong numero, at bilangin sa pamamagitan ng tinukoy na agwat, at gawin ang mga tinukoy na mga blocks.", - "CONTROLS_FOR_TITLE": "bilangin %1 mula %2 hanggang %3 ng %4", - "CONTROLS_FOREACH_TITLE": "sa bawat bagay %1 sa listahan %2", - "CONTROLS_FOREACH_TOOLTIP": "Para sa bawat item sa isang list, i-set ang variable ng '%1' sa mga item, at pagkatapos ay gumawa ng ilang mga statements.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "putulin ang paulit ulit", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "Magpatuloy sa susunod na pag-ulit ng loop", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Hatiin ang nilalaman ng loop.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Laktawan ang natitirang bahagi ng loop, at magpatuloy sa susunod na pag-ulit.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Babala: Ang block ito ay maaari lamang magamit sa loob ng loop.", - "CONTROLS_IF_TOOLTIP_1": "kung ang value ay true, gagawin ang do statements.", - "CONTROLS_IF_TOOLTIP_2": "Kung ang value ay true, gagawin ang unang block ng do statements. Kung hindi, gagawin ang pangalawang block ng statement.", - "CONTROLS_IF_TOOLTIP_3": "Kung ang unang value ay true, gagawin ang first block ng statement. Kung hindi, kung ang second value ay true, gagawin ang second block ng statement.", - "CONTROLS_IF_TOOLTIP_4": "Kung ang first value ay true, gagawin ang first block ng statement. Kung hindi true ang second value, gagawin ang second block ng statement. Kung wala sa mga values ay true, gagawin ang last block ng statements.", - "CONTROLS_IF_MSG_IF": "kung", - "CONTROLS_IF_MSG_ELSEIF": "else if", - "CONTROLS_IF_MSG_ELSE": "else", - "CONTROLS_IF_IF_TOOLTIP": "Mag Add, remove o kaya mag reorder ng sections para maayos ang if block.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Mag dagdag ng condition sa if block.", - "CONTROLS_IF_ELSE_TOOLTIP": "Mag Add ng final, kunin lahat ng condition sa if block.", - "LOGIC_COMPARE_HELPURL": "http://en.wikipedia.org/wiki/Inequality_(mathematics)", - "LOGIC_COMPARE_TOOLTIP_EQ": "Nag babalik ng true kung ang pinasok ay parehong magkatumbas.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Return true if both inputs are not equal to each other.", - "LOGIC_COMPARE_TOOLTIP_LT": "Nag babalik ng true kung ang unang pinasok ay maliit kaysa sa pangalawang pinasok.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Nag babalik ng true kung ang unang pinasok ay maliit sa o katumbas sa pangalawang pinasok.", - "LOGIC_COMPARE_TOOLTIP_GT": "Nagbabalik ng true kung ang unang pinasok ay mas malaki kaysa pangalawang pinasok.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Nag babalik ng true kung ang unang pinasok ay mas malaki or katumbas ng pangalawang pinasok.", - "LOGIC_OPERATION_TOOLTIP_AND": "Return true if both inputs are true.", - "LOGIC_OPERATION_AND": "at", - "LOGIC_OPERATION_TOOLTIP_OR": "Return true if at least one of the inputs is true.", - "LOGIC_OPERATION_OR": "o", - "LOGIC_NEGATE_TITLE": "not %1", - "LOGIC_NEGATE_TOOLTIP": "Returns true if the input is false. Returns false if the input is true.", - "LOGIC_BOOLEAN_TRUE": "tama", - "LOGIC_BOOLEAN_FALSE": "mali", - "LOGIC_BOOLEAN_TOOLTIP": "Nag babalik ng true or false.", - "LOGIC_NULL_HELPURL": "http://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "blangko", - "LOGIC_NULL_TOOLTIP": "Returns null.", - "LOGIC_TERNARY_HELPURL": "http://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "kung tama", - "LOGIC_TERNARY_IF_FALSE": "kung mali", - "LOGIC_TERNARY_TOOLTIP": "Check the condition in 'test'. If the condition is true, returns the 'if true' value; otherwise returns the 'if false' value.", - "MATH_NUMBER_HELPURL": "http://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "A number.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tan", - "MATH_TRIG_ASIN": "asin", - "MATH_TRIG_ACOS": "acos", - "MATH_TRIG_ATAN": "atan", - "MATH_ARITHMETIC_HELPURL": "http://en.wikipedia.org/wiki/Arithmetic", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Return the sum of the two numbers.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Return the difference of the two numbers.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Return the product of the two numbers.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Return the quotient of the two numbers.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Return the first number raised to the power of the second number.", - "MATH_SINGLE_HELPURL": "http://en.wikipedia.org/wiki/Square_root", - "MATH_SINGLE_OP_ROOT": "square root", - "MATH_SINGLE_TOOLTIP_ROOT": "Return the square root of a number.", - "MATH_SINGLE_OP_ABSOLUTE": "absolute", - "MATH_SINGLE_TOOLTIP_ABS": "Return the absolute value of a number.", - "MATH_SINGLE_TOOLTIP_NEG": "Return the negation of a number.", - "MATH_SINGLE_TOOLTIP_LN": "Return the natural logarithm of a number.", - "MATH_SINGLE_TOOLTIP_LOG10": "Return the base 10 logarithm of a number.", - "MATH_SINGLE_TOOLTIP_EXP": "Return e to the power of a number.", - "MATH_SINGLE_TOOLTIP_POW10": "Return 10 to the power of a number.", - "MATH_TRIG_HELPURL": "http://en.wikipedia.org/wiki/Trigonometric_functions", - "MATH_TRIG_TOOLTIP_SIN": "Return the sine of a degree (not radian).", - "MATH_TRIG_TOOLTIP_COS": "Return the cosine of a degree (not radian).", - "MATH_TRIG_TOOLTIP_TAN": "Return the tangent of a degree (not radian).", - "MATH_TRIG_TOOLTIP_ASIN": "Return the arcsine of a number.", - "MATH_TRIG_TOOLTIP_ACOS": "Return the arccosine of a number.", - "MATH_TRIG_TOOLTIP_ATAN": "Return the arctangent of a number.", - "MATH_CONSTANT_HELPURL": "http://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).", - "MATH_IS_EVEN": "is even", - "MATH_IS_ODD": "is odd", - "MATH_IS_PRIME": "is prime", - "MATH_IS_WHOLE": "is whole", - "MATH_IS_POSITIVE": "ay positibo", - "MATH_IS_NEGATIVE": "ay negatibo", - "MATH_IS_DIVISIBLE_BY": "is divisible by", - "MATH_IS_TOOLTIP": "Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false.", - "MATH_CHANGE_HELPURL": "http://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "baguhin %1 by %2", - "MATH_CHANGE_TOOLTIP": "Add a number to variable '%1'.", - "MATH_ROUND_HELPURL": "http://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Round a number up or down.", - "MATH_ROUND_OPERATOR_ROUND": "round", - "MATH_ROUND_OPERATOR_ROUNDUP": "round up", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "round down", - "MATH_ONLIST_OPERATOR_SUM": "sum of list", - "MATH_ONLIST_TOOLTIP_SUM": "Return the sum of all the numbers in the list.", - "MATH_ONLIST_OPERATOR_MIN": "min of list", - "MATH_ONLIST_TOOLTIP_MIN": "Return the smallest number in the list.", - "MATH_ONLIST_OPERATOR_MAX": "max of list", - "MATH_ONLIST_TOOLTIP_MAX": "Return the largest number in the list.", - "MATH_ONLIST_OPERATOR_AVERAGE": "average of list", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Return the average (arithmetic mean) of the numeric values in the list.", - "MATH_ONLIST_OPERATOR_MEDIAN": "median of list", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Return the median number in the list.", - "MATH_ONLIST_OPERATOR_MODE": "modes of list", - "MATH_ONLIST_TOOLTIP_MODE": "Return a list of the most common item(s) in the list.", - "MATH_ONLIST_OPERATOR_STD_DEV": "standard deviation of list", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Return the standard deviation of the list.", - "MATH_ONLIST_OPERATOR_RANDOM": "random item of list", - "MATH_ONLIST_TOOLTIP_RANDOM": "Return a random element from the list.", - "MATH_MODULO_HELPURL": "http://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "remainder of %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Return the remainder from dividing the two numbers.", - "MATH_CONSTRAIN_TITLE": "constrain %1 low %2 high %3", - "MATH_CONSTRAIN_TOOLTIP": "Constrain a number to be between the specified limits (inclusive).", - "MATH_RANDOM_INT_HELPURL": "http://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "random integer from %1 to %2", - "MATH_RANDOM_INT_TOOLTIP": "Return a random integer between the two specified limits, inclusive.", - "MATH_RANDOM_FLOAT_HELPURL": "http://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "random fraction", - "MATH_RANDOM_FLOAT_TOOLTIP": "Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).", - "TEXT_TEXT_HELPURL": "http://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "A letter, word, or line of text.", - "TEXT_JOIN_TITLE_CREATEWITH": "create text with", - "TEXT_JOIN_TOOLTIP": "Create a piece of text by joining together any number of items.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "join", - "TEXT_CREATE_JOIN_TOOLTIP": "Add, remove, or reorder sections to reconfigure this text block.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Add an item to the text.", - "TEXT_APPEND_TO": "to", - "TEXT_APPEND_APPENDTEXT": "append text", - "TEXT_APPEND_TOOLTIP": "Append some text to variable '%1'.", - "TEXT_LENGTH_TITLE": "length of %1", - "TEXT_LENGTH_TOOLTIP": "Returns the number of letters (including spaces) in the provided text.", - "TEXT_ISEMPTY_TITLE": "%1 is empty", - "TEXT_ISEMPTY_TOOLTIP": "Returns true if the provided text is empty.", - "TEXT_INDEXOF_TOOLTIP": "Returns the index of the first/last occurrence of first text in the second text. Returns %1 if text is not found.", - "TEXT_INDEXOF_INPUT_INTEXT": "in text", - "TEXT_INDEXOF_OPERATOR_FIRST": "find first occurrence of text", - "TEXT_INDEXOF_OPERATOR_LAST": "find last occurrence of text", - "TEXT_CHARAT_INPUT_INTEXT": "in text", - "TEXT_CHARAT_FROM_START": "get letter #", - "TEXT_CHARAT_FROM_END": "get letter # from end", - "TEXT_CHARAT_FIRST": "get first letter", - "TEXT_CHARAT_LAST": "get last letter", - "TEXT_CHARAT_RANDOM": "get random letter", - "TEXT_CHARAT_TOOLTIP": "Returns the letter at the specified position.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Returns a specified portion of the text.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "in text", - "TEXT_GET_SUBSTRING_START_FROM_START": "get substring from letter #", - "TEXT_GET_SUBSTRING_START_FROM_END": "get substring from letter # from end", - "TEXT_GET_SUBSTRING_START_FIRST": "get substring from first letter", - "TEXT_GET_SUBSTRING_END_FROM_START": "to letter #", - "TEXT_GET_SUBSTRING_END_FROM_END": "to letter # from end", - "TEXT_GET_SUBSTRING_END_LAST": "to last letter", - "TEXT_CHANGECASE_TOOLTIP": "Return a copy of the text in a different case.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "to UPPER CASE", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "to lower case", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "to Title Case", - "TEXT_TRIM_TOOLTIP": "Return a copy of the text with spaces removed from one or both ends.", - "TEXT_TRIM_OPERATOR_BOTH": "trim spaces from both sides", - "TEXT_TRIM_OPERATOR_LEFT": "trim spaces from left side", - "TEXT_TRIM_OPERATOR_RIGHT": "trim spaces from right side", - "TEXT_PRINT_TITLE": "print %1", - "TEXT_PRINT_TOOLTIP": "Print the specified text, number or other value.", - "TEXT_PROMPT_TYPE_TEXT": "prompt for text with message", - "TEXT_PROMPT_TYPE_NUMBER": "prompt for number with message", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Prompt for user for a number.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Prompt for user for some text.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "Gumawa ng walang laman na list", - "LISTS_CREATE_EMPTY_TOOLTIP": "Ibabalik ang list, na may haba na 0, nag lalaman ng walang data records", - "LISTS_CREATE_WITH_TOOLTIP": "Gumawa ng list na may kahit anong number ng items.", - "LISTS_CREATE_WITH_INPUT_WITH": "gumawa ng list kasama", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "list", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Magdagdag, mag tanggal or mag ayos ng sections para muling maayos ang listahan ng block.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Mag dagdag ng item sa list.", - "LISTS_REPEAT_TOOLTIP": "Pag gawa ng list na binubuo ng binigay na value at inulit na tinuloy na bilang ng beses.", - "LISTS_REPEAT_TITLE": "pag gawa ng list kasama ng item %1 inuulit %2 beses", - "LISTS_LENGTH_TITLE": "haba ng %1", - "LISTS_LENGTH_TOOLTIP": "Pag balik ng haba ng list.", - "LISTS_ISEMPTY_TITLE": "%1 ay walang laman", - "LISTS_ISEMPTY_TOOLTIP": "Nagbabalik ng true kung ang list ay walang laman.", - "LISTS_INLIST": "sa list", - "LISTS_INDEX_OF_FIRST": "Hanapin ang unang pangyayari ng item", - "LISTS_INDEX_OF_LAST": "hanapin ang huling pangyayari ng item", - "LISTS_INDEX_OF_TOOLTIP": "Pagbalik ng index ng una/huli pangyayari ng item sa list. Pagbalik ng %1 kung ang item ay hindi makita.", - "LISTS_GET_INDEX_GET": "kunin", - "LISTS_GET_INDEX_GET_REMOVE": "kunin at tanggalin", - "LISTS_GET_INDEX_REMOVE": "tanggalin", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# mula katapusan", - "LISTS_GET_INDEX_FIRST": "Una", - "LISTS_GET_INDEX_LAST": "huli", - "LISTS_GET_INDEX_RANDOM": "nang hindi pinipili", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 ay ang unang item.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 ay ang huling item.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Ibalik ang item sa itinakdang posisyon sa list.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Ibalik ang unang item sa list.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Ibalik ang huling item sa list.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Nag babalik ng hindi pinipiling item sa list.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Nag tatanggal at nag babalik ng mga items sa tinukoy na posisyon sa list.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Nag tatanggal at nag babalik ng mga unang item sa list.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Nag tatanggal at nag babalik ng huling item sa list.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Nag tatanggal at nag babalik ng mga hindi pinipiling item sa list.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Nag tatanggal ng item sa tinukoy na posisyon sa list.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Nag tatanggal ng unang item sa list.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Nag tatanggal ng huling item sa list.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Nag tatanggal ng item mula sa walang pinipiling list.", - "LISTS_SET_INDEX_SET": "set", - "LISTS_SET_INDEX_INSERT": "isingit sa", - "LISTS_SET_INDEX_INPUT_TO": "gaya ng", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Pag set ng item sa tinukoy na position sa isang list.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Pag set ng unang item sa isang list.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Pag set sa huling item sa isang list.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Pag set ng walang pinipiling item sa isang list.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Nag singit ng item sa tinukoy na posistion sa list.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Nag singit ng item sa simula ng list.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Idagdag ang item sa huli ng isang list.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Isingit ang item ng walang pinipili sa isang list.", - "LISTS_GET_SUBLIST_START_FROM_START": "pag kuha ng sub-list mula #", - "LISTS_GET_SUBLIST_START_FROM_END": "pag kuha ng sub-list mula sa # mula huli", - "LISTS_GET_SUBLIST_START_FIRST": "pag kuha ng sub-list mula sa una", - "LISTS_GET_SUBLIST_END_FROM_START": "mula #", - "LISTS_GET_SUBLIST_END_FROM_END": "mula # hanggang huli", - "LISTS_GET_SUBLIST_END_LAST": "hanggang huli", - "LISTS_GET_SUBLIST_TOOLTIP": "Gumagawa ng kopya ng tinukoy na bahagi ng list.", - "VARIABLES_GET_TOOLTIP": "Returns the value of this variable.", - "VARIABLES_GET_CREATE_SET": "Create 'set %1'", - "VARIABLES_SET": "set %1 to %2", - "VARIABLES_SET_TOOLTIP": "Sets this variable to be equal to the input.", - "VARIABLES_SET_CREATE_GET": "Create 'get %1'", - "PROCEDURES_DEFNORETURN_HELPURL": "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFNORETURN_TITLE": "to", - "PROCEDURES_DEFNORETURN_PROCEDURE": "do something", - "PROCEDURES_BEFORE_PARAMS": "with:", - "PROCEDURES_CALL_BEFORE_PARAMS": "with:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Creates a function with no output.", - "PROCEDURES_DEFRETURN_HELPURL": "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFRETURN_RETURN": "return", - "PROCEDURES_DEFRETURN_TOOLTIP": "Creates a function with an output.", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Warning: This function has duplicate parameters.", - "PROCEDURES_CALLNORETURN_HELPURL": "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Run the user-defined function '%1'.", - "PROCEDURES_CALLRETURN_HELPURL": "http://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Run the user-defined function '%1' and use its output.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "inputs", - "PROCEDURES_MUTATORARG_TITLE": "input name:", - "PROCEDURES_HIGHLIGHT_DEF": "Highlight function definition", - "PROCEDURES_CREATE_DO": "Create '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "If a value is true, then return a second value.", - "PROCEDURES_IFRETURN_WARNING": "Warning: This block may be used only within a function definition." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/tlh.json b/backend/_pv_1_3_5/static/blockly/msg/json/tlh.json deleted file mode 100755 index 8be1d1dac..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/tlh.json +++ /dev/null @@ -1,182 +0,0 @@ -{ - "@metadata": { - "author": "Neil Fraser ", - "lastupdated": "2014-03-24 23:00:00.000000", - "locale": "tlh", - "messagedocumentation" : "qqq" - }, - "VARIABLES_DEFAULT_NAME": "Doch", - "TODAY": "DaHjaj", - "DUPLICATE_BLOCK": "velqa' chenmoH", - "ADD_COMMENT": "QInHom chel", - "REMOVE_COMMENT": "QInHom chelHa'", - "EXTERNAL_INPUTS": "Hur rar", - "INLINE_INPUTS": "qoD rar", - "DELETE_BLOCK": "ngogh Qaw'", - "DELETE_X_BLOCKS": "%1 ngoghmey Qaw'", - "DELETE_ALL_BLOCKS": "Hoch %1 ngoghmey Qaw'?", - "CLEAN_UP": "ngoghmeyvaD tlhegh rurmoH", - "COLLAPSE_BLOCK": "ngogh DejmoH", - "COLLAPSE_ALL": "ngoghmey DejmoH", - "EXPAND_BLOCK": "ngogh DejHa'moH", - "EXPAND_ALL": "ngoghmey DejHa'moH", - "DISABLE_BLOCK": "ngogh Qotlh", - "ENABLE_BLOCK": "ngogh QotlhHa'", - "HELP": "QaH", - "UNDO": "vangHa'", - "REDO": "vangqa'", - "CHANGE_VALUE_TITLE": "choH:", - "NEW_VARIABLE": "lIw chu'...", - "NEW_VARIABLE_TITLE": "lIw chu' pong:", - "RENAME_VARIABLE": "lIw pong choH...", - "RENAME_VARIABLE_TITLE": "Hoch \"%1\" lIwmey pongmey choH:", - "COLOUR_RANDOM_TITLE": "rItlh vISaHbe'", - "COLOUR_RGB_TITLE": "rItlh wIv", - "COLOUR_RGB_RED": "'Iw rItlh", - "COLOUR_RGB_GREEN": "tI rItlh", - "COLOUR_RGB_BLUE": "chal rItlh", - "COLOUR_BLEND_TITLE": "DuD", - "COLOUR_BLEND_COLOUR1": "rItlh wa'", - "COLOUR_BLEND_COLOUR2": "rItlh cha'", - "COLOUR_BLEND_RATIO": "'ar", - "CONTROLS_REPEAT_TITLE": "%1-logh qaSmoH", - "CONTROLS_REPEAT_INPUT_DO": "ruch", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "teHtaHvIS qaSmoH", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "teHpa' qaSmoH", - "CONTROLS_FOR_TITLE": "togh %1 mung %2 ghoch %3 Do %4", - "CONTROLS_FOREACH_TITLE": "ngIq Doch %1 ngaSbogh tetlh %2 nuDDI'", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "gho Haw'", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "gho taHqa'", - "CONTROLS_FLOW_STATEMENTS_WARNING": "yIqIm! ghoDaq neH ngoghvam lo'laH vay'.", - "CONTROLS_IF_MSG_IF": "teHchugh", - "CONTROLS_IF_MSG_ELSEIF": "pagh teHchugh", - "CONTROLS_IF_MSG_ELSE": "pagh", - "LOGIC_OPERATION_AND": "'ej", - "LOGIC_OPERATION_OR": "qoj", - "LOGIC_NEGATE_TITLE": "yoymoH %1", - "LOGIC_BOOLEAN_TRUE": "teH", - "LOGIC_BOOLEAN_FALSE": "teHbe'", - "LOGIC_NULL": "paghna'", - "LOGIC_TERNARY_CONDITION": "chov", - "LOGIC_TERNARY_IF_TRUE": "teHchugh", - "LOGIC_TERNARY_IF_FALSE": "teHbe'chugh", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "-", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "×", - "MATH_POWER_SYMBOL": "^", - "MATH_TRIG_SIN": "sin", - "MATH_TRIG_COS": "cos", - "MATH_TRIG_TAN": "tan", - "MATH_TRIG_ASIN": "asin", - "MATH_TRIG_ACOS": "acos", - "MATH_TRIG_ATAN": "atan", - "MATH_SINGLE_OP_ROOT": "cha'DIch wav", - "MATH_SINGLE_OP_ABSOLUTE": "Dung pagh choH", - "MATH_IS_EVEN": "lang'a' mI'", - "MATH_IS_ODD": "ror'a' mI'", - "MATH_IS_PRIME": "potlh'a' mI'", - "MATH_IS_WHOLE": "ngoHlaHbe''a'", - "MATH_IS_POSITIVE": "Dung pagh", - "MATH_IS_NEGATIVE": "bIng pagh", - "MATH_IS_DIVISIBLE_BY": "wav'a'", - "MATH_CHANGE_TITLE": "choH %1 chel %2", - "MATH_ROUND_OPERATOR_ROUND": "ngoH", - "MATH_ROUND_OPERATOR_ROUNDUP": "Dung ngoH", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "bIng ngoH", - "MATH_ONLIST_OPERATOR_SUM": "chelwI' SIm tetlh", - "MATH_ONLIST_OPERATOR_MIN": "machwI''a' SIm tetlh", - "MATH_ONLIST_OPERATOR_MAX": "tInwI''a' SIm tetlh", - "MATH_ONLIST_OPERATOR_AVERAGE": "beQwI' SIm tetlh", - "MATH_ONLIST_OPERATOR_MEDIAN": "beQwI'botlh SIm tetlh", - "MATH_ONLIST_OPERATOR_MODE": "beQwI' motlh SIm tetlh", - "MATH_ONLIST_OPERATOR_STD_DEV": "motlhbe'wI' SIm tetlh", - "MATH_ONLIST_OPERATOR_RANDOM": "SaHbe' SIm tetlh", - "MATH_MODULO_TITLE": "ratlwI' SIm %1 ÷ %2", - "MATH_CONSTRAIN_TITLE": "jon %1 bIng %2 Dung %3", - "MATH_RANDOM_INT_TITLE": "ngoH mI'SaHbe' bIng %1 Dung %2", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "mI'HomSaHbe'", - "TEXT_JOIN_TITLE_CREATEWITH": "ghItlh ghom", - "TEXT_CREATE_JOIN_TITLE_JOIN": "ghom", - "TEXT_APPEND_TO": "chel", - "TEXT_APPEND_APPENDTEXT": "ghItlh", - "TEXT_LENGTH_TITLE": "chuq %1", - "TEXT_ISEMPTY_TITLE": "%1 chIm'a'", - "TEXT_INDEXOF_INPUT_INTEXT": "ghItlhDaq", - "TEXT_INDEXOF_OPERATOR_FIRST": "ghItlh wa'DIch Sam", - "TEXT_INDEXOF_OPERATOR_LAST": "ghItlh Qav Sam", - "TEXT_INDEXOF_TAIL": "", - "TEXT_CHARAT_INPUT_INTEXT": "ghItlhDaq", - "TEXT_CHARAT_FROM_START": "mu'Hom #", - "TEXT_CHARAT_FROM_END": "mu'Hom # Qav", - "TEXT_CHARAT_FIRST": "mu'Hom wa'DIch", - "TEXT_CHARAT_LAST": "mu'Hom Qav", - "TEXT_CHARAT_RANDOM": "mu'Hom SaHbe'", - "TEXT_CHARAT_TAIL": "Suq", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "ghItlhDaq", - "TEXT_GET_SUBSTRING_START_FROM_START": "ghItlhHom moHaq mu'Hom #", - "TEXT_GET_SUBSTRING_START_FROM_END": "ghItlhHom moHaq mu'Hom # Qav", - "TEXT_GET_SUBSTRING_START_FIRST": "ghItlhHom moHaq mu'Hom wa'DIch", - "TEXT_GET_SUBSTRING_END_FROM_START": "mojaq mu'Hom #", - "TEXT_GET_SUBSTRING_END_FROM_END": "mojaq mu'Hom # Qav", - "TEXT_GET_SUBSTRING_END_LAST": "mojaq mu'Hom Qav", - "TEXT_GET_SUBSTRING_TAIL": "Suq", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "tInchoH", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "machchoH", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "DojchoH", - "TEXT_TRIM_OPERATOR_BOTH": "poSnIHlogh pei", - "TEXT_TRIM_OPERATOR_LEFT": "poSlogh pei", - "TEXT_TRIM_OPERATOR_RIGHT": "nIHlogh pei", - "TEXT_PRINT_TITLE": "maq %1", - "TEXT_PROMPT_TYPE_TEXT": "ghItln tlhob 'ej maq", - "TEXT_PROMPT_TYPE_NUMBER": "mI' tlhob 'ej maq", - "LISTS_CREATE_EMPTY_TITLE": "tetlh chIm", - "LISTS_CREATE_WITH_INPUT_WITH": "tetlh ghom", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "tetlh", - "LISTS_REPEAT_TITLE": "tetlh ghom %2 Dochmey %1 pus", - "LISTS_LENGTH_TITLE": "chuq %1", - "LISTS_ISEMPTY_TITLE": "%1 chIm'a'", - "LISTS_INLIST": "tetlhDaq", - "LISTS_INDEX_OF_FIRST": "Doch sam wa'DIch", - "LISTS_INDEX_OF_LAST": "Doch sam Qav", - "LISTS_GET_INDEX_GET": "Suq", - "LISTS_GET_INDEX_GET_REMOVE": "Suq vaj pej", - "LISTS_GET_INDEX_REMOVE": "pej", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# Qav", - "LISTS_GET_INDEX_FIRST": "wa'DIch", - "LISTS_GET_INDEX_LAST": "Qav", - "LISTS_GET_INDEX_RANDOM": "Sahbe'", - "LISTS_GET_INDEX_TAIL": "", - "LISTS_SET_INDEX_SET": "choH", - "LISTS_SET_INDEX_INSERT": "lIH", - "LISTS_SET_INDEX_INPUT_TO": "Dos", - "LISTS_GET_SUBLIST_START_FROM_START": "tetlhHom moHaq #", - "LISTS_GET_SUBLIST_START_FROM_END": "tetlhHom moHaq # Qav", - "LISTS_GET_SUBLIST_START_FIRST": "tetlhHom moHaq wa'DIch", - "LISTS_GET_SUBLIST_END_FROM_START": "mojaQ #", - "LISTS_GET_SUBLIST_END_FROM_END": "mojaQ # Qav", - "LISTS_GET_SUBLIST_END_LAST": "mojaQ Qav", - "LISTS_GET_SUBLIST_TAIL": "Suq", - "LISTS_SPLIT_LIST_FROM_TEXT": "tetlh ghermeH ghItlh wav", - "LISTS_SPLIT_TEXT_FROM_LIST": "ghItlh chenmoHmeH tetlh gherHa'", - "LISTS_SPLIT_WITH_DELIMITER": "rarwI'Hom lo'", - "ORDINAL_NUMBER_SUFFIX": "", - "VARIABLES_GET_CREATE_SET": "chel 'choH %1'", - "VARIABLES_SET": "choH %1 %2", - "VARIABLES_SET_CREATE_GET": "chel 'Suq %1'", - "PROCEDURES_DEFNORETURN_TITLE": "ruch", - "PROCEDURES_DEFNORETURN_PROCEDURE": "mIw", - "PROCEDURES_BEFORE_PARAMS": "qel:", - "PROCEDURES_CALL_BEFORE_PARAMS": "qel:", - "PROCEDURES_DEFNORETURN_DO": "", - "PROCEDURES_DEFNORETURN_COMMENT": "mIw yIDel...", - "PROCEDURES_DEFRETURN_RETURN": "chegh", - "PROCEDURES_ALLOW_STATEMENTS": "mu'tlhegh chaw'", - "PROCEDURES_DEF_DUPLICATE_WARNING": "ghuHmoHna': qelwI' cha'logh chen.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "qelwI'mey", - "PROCEDURES_MUTATORARG_TITLE": "pong:", - "PROCEDURES_HIGHLIGHT_DEF": "mIwna' wew", - "PROCEDURES_CREATE_DO": "chel '%1'", - "PROCEDURES_IFRETURN_WARNING": "ghoHmoHna': ngoghvam ngaSbe' mIwDaq." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/tr.json b/backend/_pv_1_3_5/static/blockly/msg/json/tr.json deleted file mode 100755 index 1db02bd02..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/tr.json +++ /dev/null @@ -1,351 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Meelo", - "Joseph", - "WikiBronze", - "Mavrikant", - "아라", - "Watermelon juice", - "Uğurkent", - "McAang", - "Gurkanht", - "HakanIST", - "Imabadplayer", - "Kumkumuk", - "Alpkant" - ] - }, - "VARIABLES_DEFAULT_NAME": "öge", - "TODAY": "Bugün", - "DUPLICATE_BLOCK": "Çoğalt", - "ADD_COMMENT": "Yorum Ekle", - "REMOVE_COMMENT": "Yorumu Sil", - "EXTERNAL_INPUTS": "Harici Girişler", - "INLINE_INPUTS": "Satır içi girdiler", - "DELETE_BLOCK": "Bloğu Sil", - "DELETE_X_BLOCKS": "%1 Blokları Sil", - "DELETE_ALL_BLOCKS": "Tüm %1 blok silinsin mi?", - "CLEAN_UP": "Blokları temizle", - "COLLAPSE_BLOCK": "Blok'u Daralt", - "COLLAPSE_ALL": "Blokları Daralt", - "EXPAND_BLOCK": "Bloğu Genişlet", - "EXPAND_ALL": "Blokları Genişlet", - "DISABLE_BLOCK": "Bloğu Devre Dışı Bırak", - "ENABLE_BLOCK": "Bloğu Etkinleştir", - "HELP": "Yardım", - "UNDO": "Geri al", - "REDO": "Yinele", - "CHANGE_VALUE_TITLE": "Değeri değiştir:", - "RENAME_VARIABLE": "Değişkeni yeniden adlandır...", - "RENAME_VARIABLE_TITLE": "Tüm '%1' değişkenlerini yeniden isimlendir:", - "NEW_VARIABLE": "Değişken oluştur...", - "NEW_VARIABLE_TITLE": "Yeni değişken ismi :", - "VARIABLE_ALREADY_EXISTS": "'%1' isimli değişken adı zaten var.", - "DELETE_VARIABLE_CONFIRMATION": "'%2' değişkeninin %1 kullanımını silmek istiyor musunuz?", - "DELETE_VARIABLE": "'%1' değişkenini silmek istiyor musunuz?", - "COLOUR_PICKER_HELPURL": "https://tr.wikipedia.org/wiki/Renk", - "COLOUR_PICKER_TOOLTIP": "Paletten bir renk seçin.", - "COLOUR_RANDOM_TITLE": "rastgele renk", - "COLOUR_RANDOM_TOOLTIP": "Rastgele bir renk seçin.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "renk değerleri", - "COLOUR_RGB_RED": "kırmızı", - "COLOUR_RGB_GREEN": "yeşil", - "COLOUR_RGB_BLUE": "mavi", - "COLOUR_RGB_TOOLTIP": "Kırmızı, yeşil ve mavinin belirtilen miktarıyla bir renk oluşturun. Tüm değerler 0 ile 100 arasında olmalıdır.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "karıştır", - "COLOUR_BLEND_COLOUR1": "renk 1", - "COLOUR_BLEND_COLOUR2": "renk 2", - "COLOUR_BLEND_RATIO": "oran", - "COLOUR_BLEND_TOOLTIP": "Verilen bir orana bağlı olarak iki rengi karıştırır. (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://tr.wikipedia.org/wiki/For_d%C3%B6ng%C3%BCs%C3%BC", - "CONTROLS_REPEAT_TITLE": "%1 kez tekrarla", - "CONTROLS_REPEAT_INPUT_DO": "yap", - "CONTROLS_REPEAT_TOOLTIP": "Bazı işlemleri birkaç kez yap.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "tekrar ederken", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "kadar tekrarla", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Bir değer doğru olduğunda bazı beyanlarda bulun.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Bir değer yanlış olduğunda bazı beyanlarda bulun.", - "CONTROLS_FOR_TOOLTIP": "Başlangıç sayısından bitiş sayısına kadar belirtilen aralık ve belirtilen engeller ile devam eden değerler alan '%1' değişkeni oluştur.", - "CONTROLS_FOR_TITLE": "ile sayılır %1 %2 den %3 ye, her adımda %4 değişim", - "CONTROLS_FOREACH_TITLE": "her öğe için %1 listede %2", - "CONTROLS_FOREACH_TOOLTIP": "Bir listedeki her öğe için '%1' değişkenini maddeye atayın ve bundan sonra bazı açıklamalar yapın.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "döngüden çık", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "döngünün sonraki adımından devam et", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "İçeren döngüden çık.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Bu döngünün geri kalanını atlayın ve sonraki adım ile devam edin.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Uyarı: Bu blok sadece bir döngü içinde kullanılabilir.", - "CONTROLS_IF_TOOLTIP_1": "Eğer değişken true , yani gerçekleşmiş ise , ardından gelen işlemi yerine getir .", - "CONTROLS_IF_TOOLTIP_2": "Eğer değişken true, yani gerçekleşiyor ise ilk blok'taki işlemleri yerine getir, Aksi halde ikinci blok'taki işlemleri yerine getir.", - "CONTROLS_IF_TOOLTIP_3": "Eğer ilk değişken true, yani koşul gerçekleşmiş ise ilk blok içerisindeki işlem(ler)i gerçekleştir. Eğer ikinci değişken true ise, ikinci bloktaki işlem(ler)i gerçekleştir .", - "CONTROLS_IF_TOOLTIP_4": "Eğer ilk değer true, yani olumlu ise, ilk blok'taki işlem(ler)i gerçekleştir. İlk değer true değil ama ikinci değer true ise, ikinci bloktaki işlem(ler)i gerçekleştir. Eğer değerlerin hiçbiri true değil ise son blok'taki işlem(ler)i gerçekleştir.", - "CONTROLS_IF_MSG_IF": "eğer", - "CONTROLS_IF_MSG_ELSEIF": "değilse eğer", - "CONTROLS_IF_MSG_ELSE": "değilse", - "CONTROLS_IF_IF_TOOLTIP": "If bloğuna ekle, kaldır veya yeniden düzenleme yap.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "If bloğuna bir koşul ekleyin.", - "CONTROLS_IF_ELSE_TOOLTIP": "If bloğuna kalan durumları \"yakalayan\" bir son ekle.", - "LOGIC_COMPARE_HELPURL": "https://tr.wikipedia.org/wiki/E%C5%9Fitsizlikler", - "LOGIC_COMPARE_TOOLTIP_EQ": "Girilen iki değer birbirine eşitse \"True\" değerini verir.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Girilen iki değerde birbirine eşit değilse \"True\" değerini verir.", - "LOGIC_COMPARE_TOOLTIP_LT": "Girilen ilk değer ikinci değerden küçükse \"True\" değerini verir.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Girilen ilk değer ikinci değerden küçük veya eşitse \"True\" değerini verir.", - "LOGIC_COMPARE_TOOLTIP_GT": "Girilen ilk değer ikinci değerden daha büyükse \"True\" değerini verir.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Girilen ilk değer ikinci değerden büyük veya eşitse \"True\" değerini verir.", - "LOGIC_OPERATION_TOOLTIP_AND": "Girilen iki değerde doğruysa \"True\" değerini verir.", - "LOGIC_OPERATION_AND": "ve", - "LOGIC_OPERATION_TOOLTIP_OR": "Girilen iki değerden en az biri doğruysa \"True\" değerini verir.", - "LOGIC_OPERATION_OR": "veya", - "LOGIC_NEGATE_TITLE": "%1 değil", - "LOGIC_NEGATE_TOOLTIP": "Girilen değer yanlışsa \"True\" değerini verir.Girilen değer doğruysa \"False\" değerini verir.", - "LOGIC_BOOLEAN_TRUE": "Olumlu", - "LOGIC_BOOLEAN_FALSE": "false = Olumsuz", - "LOGIC_BOOLEAN_TOOLTIP": "Ya 'True' yada 'False' değerini verir.", - "LOGIC_NULL_HELPURL": "https://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "sıfır", - "LOGIC_NULL_TOOLTIP": "sıfır verir.", - "LOGIC_TERNARY_HELPURL": "https://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "test", - "LOGIC_TERNARY_IF_TRUE": "doğru ise", - "LOGIC_TERNARY_IF_FALSE": "yanlış ise", - "LOGIC_TERNARY_TOOLTIP": "'test'deki şartı test eder. Eğer şart doğru ise 'doğru' değeri döndürür, aksi halde 'yanlış' değeri döndürür.", - "MATH_NUMBER_HELPURL": "https://en.wikipedia.org/wiki/Number", - "MATH_NUMBER_TOOLTIP": "Bir sayı.", - "MATH_ADDITION_SYMBOL": "+", - "MATH_SUBTRACTION_SYMBOL": "tire", - "MATH_DIVISION_SYMBOL": "÷", - "MATH_MULTIPLICATION_SYMBOL": "x", - "MATH_POWER_SYMBOL": "üst alma", - "MATH_TRIG_SIN": "Sinüs", - "MATH_TRIG_COS": "kosünüs", - "MATH_TRIG_TAN": "tanjant", - "MATH_TRIG_ASIN": "asinüs", - "MATH_TRIG_ACOS": "akosünüs", - "MATH_TRIG_ATAN": "atanjant", - "MATH_ARITHMETIC_HELPURL": "https://tr.wikipedia.org/wiki/Aritmetik", - "MATH_ARITHMETIC_TOOLTIP_ADD": "İki rakamın toplamını döndür.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "İki sayını farkını döndür.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "İki sayının çarpımını döndür.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "İki sayının bölümünü döndür.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "İlk sayinin ikincinin kuvvetine yükseltilmişini döndür.", - "MATH_SINGLE_HELPURL": "https://tr.wikipedia.org/wiki/Karek%C3%B6k", - "MATH_SINGLE_OP_ROOT": "Kare kök", - "MATH_SINGLE_TOOLTIP_ROOT": "Bir sayının karekökü nü döndür .", - "MATH_SINGLE_OP_ABSOLUTE": "Kesin", - "MATH_SINGLE_TOOLTIP_ABS": "Bir sayının tam değerini döndür .", - "MATH_SINGLE_TOOLTIP_NEG": "Bir sayıyı geçersiz olarak döndür .", - "MATH_SINGLE_TOOLTIP_LN": "Bir sayının doğal logaritmasını döndür .", - "MATH_SINGLE_TOOLTIP_LOG10": "Bir sayının 10 temelinde logaritmasını döndür .", - "MATH_SINGLE_TOOLTIP_EXP": "Bir sayının e ' inci kuvvetini döndür .", - "MATH_SINGLE_TOOLTIP_POW10": "Bir sayının 10. kuvvetini döndür .", - "MATH_TRIG_HELPURL": "https://tr.wikipedia.org/wiki/Trigonometrik_fonksiyonlar", - "MATH_TRIG_TOOLTIP_SIN": "Bir açının sinüsünü döndür(radyan olarak değil).", - "MATH_TRIG_TOOLTIP_COS": "Bir açının kosinüsünü döndür(radyan olarak değil).", - "MATH_TRIG_TOOLTIP_TAN": "Bir açının tanjantını döndür(radyan olarak değil).", - "MATH_TRIG_TOOLTIP_ASIN": "Bir sayının ters sinüsünü döndür .", - "MATH_TRIG_TOOLTIP_ACOS": "Bir sayının ters kosunusunu döndür .", - "MATH_TRIG_TOOLTIP_ATAN": "Bir sayının ters tanjantını döndür .", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "Yaygın sabitlerden birini döndür:π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (sonsuz).", - "MATH_IS_EVEN": "çift", - "MATH_IS_ODD": "tek", - "MATH_IS_PRIME": "asal", - "MATH_IS_WHOLE": "Bütün olduğunu", - "MATH_IS_POSITIVE": "pozitif", - "MATH_IS_NEGATIVE": "negatif", - "MATH_IS_DIVISIBLE_BY": "bölünebilir", - "MATH_IS_TOOLTIP": "Bir sayinin çift mi tek mi , tam mı, asal mı , pozitif mi, negatif mi, veya tam bir sayıyla bölünebilirliğini kontrol et.'True' veya 'False' değerini döndür.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "%1'i %2 kadar değiştir", - "MATH_CHANGE_TOOLTIP": "'%1' değişkenine bir sayı ekle.", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding Yuvarlama fonksiyonu için araştırma yapınız, sayfanın Türkçe çevirisi henüz mevcut değil.", - "MATH_ROUND_TOOLTIP": "Bir sayı yı yukarı yada aşağı yuvarla .", - "MATH_ROUND_OPERATOR_ROUND": "Yuvarla", - "MATH_ROUND_OPERATOR_ROUNDUP": "yukarı yuvarla", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "aşağı yuvarla", - "MATH_ONLIST_HELPURL": "", - "MATH_ONLIST_OPERATOR_SUM": "Listenin toplamı", - "MATH_ONLIST_TOOLTIP_SUM": "Listede ki tüm sayıların toplamını döndür.", - "MATH_ONLIST_OPERATOR_MIN": "Listenin en küçüğü", - "MATH_ONLIST_TOOLTIP_MIN": "Listenin en küçüğünü döndür.", - "MATH_ONLIST_OPERATOR_MAX": "en büyük sayı", - "MATH_ONLIST_TOOLTIP_MAX": "Listenin en büyüğünü döndür.", - "MATH_ONLIST_OPERATOR_AVERAGE": "listenin ortalaması", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Listedeki sayısal değerlerin ortalamasını (aritmetik anlamda) döndür.", - "MATH_ONLIST_OPERATOR_MEDIAN": "Listenin medyanı", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Listenin medyanını döndür.", - "MATH_ONLIST_OPERATOR_MODE": "Listenin modları", - "MATH_ONLIST_TOOLTIP_MODE": "Listede ki en yaygın öğe veya öğelerinin listesini döndür.", - "MATH_ONLIST_OPERATOR_STD_DEV": "Listenin standart sapması", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Listenin standart sapmasını döndür.", - "MATH_ONLIST_OPERATOR_RANDOM": "Listenin rastgele öğesi", - "MATH_ONLIST_TOOLTIP_RANDOM": "Listeden rastgele bir element döndür.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "%1 ÷ %2 nin kalanı", - "MATH_MODULO_TOOLTIP": "İki sayının bölümünden kalanı döndür.", - "MATH_CONSTRAIN_TITLE": "%1 i en düşük %2 en yüksek %3 ile sınırla", - "MATH_CONSTRAIN_TOOLTIP": "Bir sayıyı belirli iki sayı arasında sınırlandır(dahil).", - "MATH_RANDOM_INT_HELPURL": "https://tr.wikipedia.org/wiki/Rastgele_say%C4%B1_%C3%BCretimi", - "MATH_RANDOM_INT_TITLE": "%1 ile %2 arasında rastgele tam sayı üret", - "MATH_RANDOM_INT_TOOLTIP": "Herhangi iki sayı arasında , sayılar dahil olmak üzere , rastgele bir tam sayı döndür.", - "MATH_RANDOM_FLOAT_HELPURL": "https://tr.wikipedia.org/wiki/Rastgele_say%C4%B1_%C3%BCretimi", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "Rast gele kesirli sayı , yada parça", - "MATH_RANDOM_FLOAT_TOOLTIP": "0.0(dahil) ve 1.0 (hariç) sayıları arasında bir sayı döndür .", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/String_(computer_science)", - "TEXT_TEXT_TOOLTIP": "Metnin bir harfi,kelimesi veya satırı.", - "TEXT_JOIN_TITLE_CREATEWITH": "ile metin oluştur", - "TEXT_JOIN_TOOLTIP": "Herhangi bir sayıda ki öğeleri bir araya getirerek metnin bir parçasını oluştur.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "Katıl", - "TEXT_CREATE_JOIN_TOOLTIP": "Bu metin bloğunu düzenlemek için bölüm ekle,sil veya yeniden görevlendir.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Metine bir öğe ekle.", - "TEXT_APPEND_TO": "e", - "TEXT_APPEND_APPENDTEXT": "Metin Ekle", - "TEXT_APPEND_TOOLTIP": "Değişken '%1' e bazı metinler ekleyin.", - "TEXT_LENGTH_TITLE": "%1 in uzunluğu", - "TEXT_LENGTH_TOOLTIP": "Yazı içerisinde verilen harflerin ( harf arasındaki boşluklar dahil) sayısını verir .", - "TEXT_ISEMPTY_TITLE": "%1 boş", - "TEXT_ISEMPTY_TOOLTIP": "Verilen metin boşsa true(doğru) değerini verir.", - "TEXT_INDEXOF_TOOLTIP": "İlk metnin ikinci metnin içindeki ilk ve son varoluşlarının indeksini döndürür.Metin bulunamadıysa %1 döndürür.", - "TEXT_INDEXOF_INPUT_INTEXT": "metinde", - "TEXT_INDEXOF_OPERATOR_FIRST": "Metnin ilk varolduğu yeri bul", - "TEXT_INDEXOF_OPERATOR_LAST": "Metnin son varolduğu yeri bul", - "TEXT_INDEXOF_TAIL": "", - "TEXT_CHARAT_INPUT_INTEXT": "metinde", - "TEXT_CHARAT_FROM_START": "# harfini al", - "TEXT_CHARAT_FROM_END": "# dan sona harfleri al", - "TEXT_CHARAT_FIRST": "İlk harfini al", - "TEXT_CHARAT_LAST": "son harfi al", - "TEXT_CHARAT_RANDOM": "Rastgele bir harf al", - "TEXT_CHARAT_TAIL": "", - "TEXT_CHARAT_TOOLTIP": "Belirli pozisyonda ki bir harfi döndürür.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Metinin belirli bir kısmını döndürür.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "metinde", - "TEXT_GET_SUBSTRING_START_FROM_START": "n inci harften alt-string alma", - "TEXT_GET_SUBSTRING_START_FROM_END": "n inci harften sona kadar alt-string alma", - "TEXT_GET_SUBSTRING_START_FIRST": "ilk harften başlayarak alt-string alma", - "TEXT_GET_SUBSTRING_END_FROM_START": "# harfe", - "TEXT_GET_SUBSTRING_END_FROM_END": "Sondan # harfe", - "TEXT_GET_SUBSTRING_END_LAST": "son harfe", - "TEXT_GET_SUBSTRING_TAIL": "", - "TEXT_CHANGECASE_TOOLTIP": "Metnin bir kopyasını farklı bir harf durumunda (HEPSİ BÜYÜK - hepsi küçük) getirir.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "büyük harf", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "küçük harf", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "Baş Harfler Büyük", - "TEXT_TRIM_TOOLTIP": "Metnin bir veya her iki sondan da boşlukları silinmiş şekilde kopyasını verir.", - "TEXT_TRIM_OPERATOR_BOTH": "iki tarafından da boşlukları temizle", - "TEXT_TRIM_OPERATOR_LEFT": "solundan boşlukları temizle", - "TEXT_TRIM_OPERATOR_RIGHT": "sağından boşlukları temizle", - "TEXT_PRINT_TITLE": "%1 ' i Yaz", - "TEXT_PRINT_TOOLTIP": "Belirli bir metni,sayıyı veya başka bir değeri yaz.", - "TEXT_PROMPT_TYPE_TEXT": "Kullanıcıdan yazım al , istek mesajıyla", - "TEXT_PROMPT_TYPE_NUMBER": "Kullanıcıdan sayı al , istek mesajı göstererek", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Kullanıcıdan sayı al .", - "TEXT_PROMPT_TOOLTIP_TEXT": "Kullanıcıdan Yazım al .", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "Boş liste oluştur", - "LISTS_CREATE_EMPTY_TOOLTIP": "Veri kaydı içermeyen uzunluğu 0 olan bir listeyi verir", - "LISTS_CREATE_WITH_TOOLTIP": "Herhangi sayıda nesne içeren bir liste oluştur.", - "LISTS_CREATE_WITH_INPUT_WITH": "İle liste oluşturma", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "liste", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Bu liste bloğunu yeniden yapılandırmak için bölüm ekle,kaldır veya yeniden çağır.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Listeye bir nesne ekle.", - "LISTS_REPEAT_TOOLTIP": "Verilen bir değerin , belirli bir sayıda tekrarlanmasından oluşan bir liste yaratır .", - "LISTS_REPEAT_TITLE": "%1 nesnenin %2 kez tekrarlandığı bir liste yarat", - "LISTS_LENGTH_TITLE": "%1'in uzunluğu", - "LISTS_LENGTH_TOOLTIP": "Bir listenin uzunluğunu verir.", - "LISTS_ISEMPTY_TITLE": "%1 boş", - "LISTS_ISEMPTY_TOOLTIP": "Eğer liste boş ise true döndürür .", - "LISTS_INLIST": "Listede", - "LISTS_INDEX_OF_FIRST": "Öğenin ilk varolduğu yeri bul", - "LISTS_INDEX_OF_LAST": "Öğenin son varolduğu yeri bul", - "LISTS_INDEX_OF_TOOLTIP": "Listedeki öğenin ilk/son oluşumunun indeksini döndürür. Eğer öğe bulunamaz ise %1 döndürür.", - "LISTS_GET_INDEX_GET": "Al", - "LISTS_GET_INDEX_GET_REMOVE": "al ve kaldır", - "LISTS_GET_INDEX_REMOVE": "kaldır", - "LISTS_GET_INDEX_FROM_START": "# Kare", - "LISTS_GET_INDEX_FROM_END": "# sonundan", - "LISTS_GET_INDEX_FIRST": "ilk", - "LISTS_GET_INDEX_LAST": "son", - "LISTS_GET_INDEX_RANDOM": "rastgele", - "LISTS_GET_INDEX_TAIL": "", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 ilk öğedir.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 son öğedir.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Listede belirli pozisyondaki bir öğeyi verir.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Listedeki ilk öğeyi verir.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Listedeki son öğeyi verir.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Listedeki rastgele bir öğeyi verir.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Kaldırır ve listede belirtilen konumdaki bir öğeyi döndürür.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Kaldırır ve listedeki ilk öğeyi döndürür.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Kaldırır ve listedeki son öğeyi döndürür.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Kaldırır ve listedeki rastgele bir öğeyi verir.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Bir liste içerisinde , tanımlanan pozisyonda ki öğeyi kaldırır.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Listedeki ilk nesneyi kaldırır.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Listedeki son nesneyi kaldırır.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Listedeki rastgele bir nesneyi kaldırır.", - "LISTS_SET_INDEX_SET": "yerleştir", - "LISTS_SET_INDEX_INSERT": "e yerleştir", - "LISTS_SET_INDEX_INPUT_TO": "olarak", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Bir öğeyi belirtilen yere göre listeye yerleştirir .", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Bir listenin ilk öğesini yerleştirir .", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Bir listedeki son öğeyi yerleştirir .", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Listeye rast gele bir öğe yerleştirir .", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Bir öğeyi belirtilen pozisyona göre listeye yerleştirir .", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Nesneyi listenin başlangıcına ekler.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Öğeyi listenin sonuna ekle .", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Bir öğeyi listeye rast gele ekler .", - "LISTS_GET_SUBLIST_START_FROM_START": "# dan alt liste al", - "LISTS_GET_SUBLIST_START_FROM_END": "# işaretinden sonra gelen ifadeye göre alt liste al , # sondan", - "LISTS_GET_SUBLIST_START_FIRST": "ilk öğeden alt liste al", - "LISTS_GET_SUBLIST_END_FROM_START": "#'a", - "LISTS_GET_SUBLIST_END_FROM_END": "Sondan #'a kadar", - "LISTS_GET_SUBLIST_END_LAST": "Sona kadar", - "LISTS_GET_SUBLIST_TAIL": "", - "LISTS_GET_SUBLIST_TOOLTIP": "Listenin belirli bir kısmının kopyasını yaratır.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "kısa %1 %2 %3", - "LISTS_SORT_TOOLTIP": "Listenin kısa bir kopyası.", - "LISTS_SORT_ORDER_ASCENDING": "artan", - "LISTS_SORT_ORDER_DESCENDING": "azalan", - "LISTS_SORT_TYPE_NUMERIC": "sayısal", - "LISTS_SORT_TYPE_TEXT": "alfabetik", - "LISTS_SORT_TYPE_IGNORECASE": "alfabetik, gözardı et", - "LISTS_SPLIT_LIST_FROM_TEXT": "metinden liste yap", - "LISTS_SPLIT_TEXT_FROM_LIST": "listeden metin yap", - "LISTS_SPLIT_WITH_DELIMITER": "sınırlayıcı ile", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Her sınırlayıcıda kesen metinleri bir metin listesine ayır.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Bir sınırlayıcı tarafından kesilen metinlerin listesini bir metine ekle.", - "ORDINAL_NUMBER_SUFFIX": "", - "VARIABLES_GET_TOOLTIP": "Bu değişkenin değerini verir.", - "VARIABLES_GET_CREATE_SET": "'set %1' oluştur", - "VARIABLES_SET": "Atamak %1 e %2", - "VARIABLES_SET_TOOLTIP": "Bu değişkeni girilen değere eşitler.", - "VARIABLES_SET_CREATE_GET": "'get %1' oluştur", - "PROCEDURES_DEFNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFNORETURN_TITLE": "e", - "PROCEDURES_DEFNORETURN_PROCEDURE": "birşey yap", - "PROCEDURES_BEFORE_PARAMS": "ile :", - "PROCEDURES_CALL_BEFORE_PARAMS": "ile :", - "PROCEDURES_DEFNORETURN_DO": "", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Çıktı vermeyen bir fonksiyon yaratır .", - "PROCEDURES_DEFNORETURN_COMMENT": "Bu işlevi açıkla...", - "PROCEDURES_DEFRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_DEFRETURN_RETURN": "Geri dön", - "PROCEDURES_DEFRETURN_TOOLTIP": "Çıktı veren bir fonksiyon oluşturur.", - "PROCEDURES_ALLOW_STATEMENTS": "Eğer ifadelerine izin ver", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Uyarı: Bu fonksiyon yinelenen parametreler vardır.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Kullanıcı tanımlı fonksiyonu çalıştır '%1' .", - "PROCEDURES_CALLRETURN_HELPURL": "https://en.wikipedia.org/wiki/Procedure_%28computer_science%29", - "PROCEDURES_CALLRETURN_TOOLTIP": "Kullanıcı tanımlı fonksiyonu çalıştır '%1' ve çıktısını kullan .", - "PROCEDURES_MUTATORCONTAINER_TITLE": "girdiler", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Bu işlevin girdilerini ekleyin, çıkarın, ya da yeniden sıralayın.", - "PROCEDURES_MUTATORARG_TITLE": "girdi adı:", - "PROCEDURES_MUTATORARG_TOOLTIP": "İşleve bir girdi ekleyin.", - "PROCEDURES_HIGHLIGHT_DEF": "Fonksiyon tanımı vurgulamak", - "PROCEDURES_CREATE_DO": "'%1' oluştur", - "PROCEDURES_IFRETURN_TOOLTIP": "Eğer değer doğruysa, ikinci değere geri dön.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Uyarı: Bu blok yalnızca bir fonksiyon tanımı içinde kullanılır." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/uk.json b/backend/_pv_1_3_5/static/blockly/msg/json/uk.json deleted file mode 100755 index 158d9d857..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/uk.json +++ /dev/null @@ -1,332 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Andriykopanytsia", - "Base", - "Igor Zavadsky", - "Lxlalexlxl", - "아라", - "Visem" - ] - }, - "VARIABLES_DEFAULT_NAME": "елемент", - "TODAY": "Сьогодні", - "DUPLICATE_BLOCK": "Дублювати", - "ADD_COMMENT": "Додати коментар", - "REMOVE_COMMENT": "Видалити коментар", - "EXTERNAL_INPUTS": "Зовнішні входи", - "INLINE_INPUTS": "Вбудовані входи", - "DELETE_BLOCK": "Видалити блок", - "DELETE_X_BLOCKS": "Видалити %1 блоків", - "DELETE_ALL_BLOCKS": "Вилучити всі блоки %1?", - "CLEAN_UP": "Вирівняти блоки", - "COLLAPSE_BLOCK": "Згорнути блок", - "COLLAPSE_ALL": "Згорнути блоки", - "EXPAND_BLOCK": "Розгорнути блок", - "EXPAND_ALL": "Розгорнути блоки", - "DISABLE_BLOCK": "Вимкнути блок", - "ENABLE_BLOCK": "Увімкнути блок", - "HELP": "Довідка", - "UNDO": "Скасувати", - "REDO": "Повторити", - "CHANGE_VALUE_TITLE": "Змінити значення:", - "RENAME_VARIABLE": "Перейменувати змінну...", - "RENAME_VARIABLE_TITLE": "Перейменувати усі змінні \"%1\" до:", - "NEW_VARIABLE": "Нова змінна...", - "NEW_VARIABLE_TITLE": "Нова назва змінної:", - "COLOUR_PICKER_HELPURL": "https://uk.wikipedia.org/wiki/Колір", - "COLOUR_PICKER_TOOLTIP": "Вибрати колір з палітри.", - "COLOUR_RANDOM_TITLE": "випадковий колір", - "COLOUR_RANDOM_TOOLTIP": "Вибрати колір навмання.", - "COLOUR_RGB_HELPURL": "http://www.december.com/html/spec/colorper.html", - "COLOUR_RGB_TITLE": "колір з", - "COLOUR_RGB_RED": "червоний", - "COLOUR_RGB_GREEN": "зелений", - "COLOUR_RGB_BLUE": "синій", - "COLOUR_RGB_TOOLTIP": "Створити колір зі вказаними рівнями червоного, зеленого та синього. Усі значення мають бути від 0 до 100.", - "COLOUR_BLEND_HELPURL": "http://meyerweb.com/eric/tools/color-blend/", - "COLOUR_BLEND_TITLE": "змішати", - "COLOUR_BLEND_COLOUR1": "колір 1", - "COLOUR_BLEND_COLOUR2": "колір 2", - "COLOUR_BLEND_RATIO": "співвідношення", - "COLOUR_BLEND_TOOLTIP": "Змішує два кольори разом у вказаному співвідношені (0.0 - 1.0).", - "CONTROLS_REPEAT_HELPURL": "https://uk.wikipedia.org/wiki/Цикл_(програмування)#.D0.A6.D0.B8.D0.BA.D0.BB_.D0.B7_.D0.BB.D1.96.D1.87.D0.B8.D0.BB.D1.8C.D0.BD.D0.B8.D0.BA.D0.BE.D0.BC", - "CONTROLS_REPEAT_TITLE": "повторити %1 разів", - "CONTROLS_REPEAT_INPUT_DO": "виконати", - "CONTROLS_REPEAT_TOOLTIP": "Виконати певні дії декілька разів.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "повторювати поки", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "повторювати, доки не", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Поки значення істинне, виконувати певні дії.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Поки значення хибне, виконувати певні дії.", - "CONTROLS_FOR_TOOLTIP": "Наявна змінна \"%1\" набуває значень від початкового до кінцевого, враховуючи заданий інтервал, і виконуються вказані блоки.", - "CONTROLS_FOR_TITLE": "рахувати з %1 від %2 до %3 через %4", - "CONTROLS_FOREACH_TITLE": "для кожного елемента %1 у списку %2", - "CONTROLS_FOREACH_TOOLTIP": "Для кожного елемента в списку змінна '%1' отримує значення елемента, а потім виконуються певні дії.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "перервати цикл", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "продовжити з наступної ітерації циклу", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Перервати виконання циклу.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Пропустити залишок цього циклу і перейти до виконання наступної ітерації.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Попередження: цей блок може бути використаний тільки в межах циклу.", - "CONTROLS_IF_TOOLTIP_1": "Якщо значення істинне, то виконати певні дії.", - "CONTROLS_IF_TOOLTIP_2": "Якщо значення істинне, то виконується перший блок операторів. В іншому випадку виконується другий блок операторів.", - "CONTROLS_IF_TOOLTIP_3": "Якщо перше значення істинне, то виконується перший блок операторів. В іншому випадку, якщо друге значення істина, то виконується другий блок операторів.", - "CONTROLS_IF_TOOLTIP_4": "Якщо перше значення істинне, то виконується перший блок операторів. В іншому випадку, якщо друге значення істинне, то виконується другий блок операторів. Якщо жодне із значень не є істинним, то виконується останній блок операторів.", - "CONTROLS_IF_MSG_IF": "якщо", - "CONTROLS_IF_MSG_ELSEIF": "інакше якщо", - "CONTROLS_IF_MSG_ELSE": "інакше", - "CONTROLS_IF_IF_TOOLTIP": "Додайте, вилучіть або змініть порядок секцій, щоб переналаштувати цей блок 'якщо'.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Додайте умову до блока 'якщо'.", - "CONTROLS_IF_ELSE_TOOLTIP": "Додати остаточну, всеосяжну умову до блоку 'якщо'.", - "LOGIC_COMPARE_HELPURL": "https://uk.wikipedia.org/wiki/Нерівність", - "LOGIC_COMPARE_TOOLTIP_EQ": "Повертає істину, якщо обидва входи рівні один одному.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Повертає істину, якщо обидва входи не дорівнюють один одному.", - "LOGIC_COMPARE_TOOLTIP_LT": "Повертає істину, якщо перше вхідне значення менше, ніж друге.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Повертає істину, якщо перше вхідне значення менше або дорівнює другому.", - "LOGIC_COMPARE_TOOLTIP_GT": "Повертає істину, якщо перше вхідне значення більше, ніж друге.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Повертає істину, якщо перше вхідне значення більше або дорівнює другому.", - "LOGIC_OPERATION_TOOLTIP_AND": "Повертає істину, якщо обидва входи істинні.", - "LOGIC_OPERATION_AND": "та", - "LOGIC_OPERATION_TOOLTIP_OR": "Повертає істину, якщо принаймні один з входів істинний.", - "LOGIC_OPERATION_OR": "або", - "LOGIC_NEGATE_TITLE": "не %1", - "LOGIC_NEGATE_TOOLTIP": "Повертає істину, якщо вхідне значення хибне. Повертає хибність, якщо вхідне значення істинне.", - "LOGIC_BOOLEAN_TRUE": "істина", - "LOGIC_BOOLEAN_FALSE": "хибність", - "LOGIC_BOOLEAN_TOOLTIP": "Повертає значення істина або хибність.", - "LOGIC_NULL_HELPURL": "https://en.wikipedia.org/wiki/Nullable_type", - "LOGIC_NULL": "ніщо", - "LOGIC_NULL_TOOLTIP": "Повертає ніщо.", - "LOGIC_TERNARY_HELPURL": "https://en.wikipedia.org/wiki/%3F:", - "LOGIC_TERNARY_CONDITION": "тест", - "LOGIC_TERNARY_IF_TRUE": "якщо істина", - "LOGIC_TERNARY_IF_FALSE": "якщо хибність", - "LOGIC_TERNARY_TOOLTIP": "Перевіряє умову в 'тест'. Якщо умова істинна, то повертає значення 'якщо істина'; в іншому випадку повертає значення 'якщо хибність'.", - "MATH_NUMBER_HELPURL": "https://uk.wikipedia.org/wiki/Число", - "MATH_NUMBER_TOOLTIP": "Число.", - "MATH_ARITHMETIC_HELPURL": "https://uk.wikipedia.org/wiki/Арифметика", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Повертає суму двох чисел.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Повертає різницю двох чисел.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Повертає добуток двох чисел.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Повертає частку двох чисел.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Повертає перше число, піднесене до степеня, вираженого другим числом.", - "MATH_SINGLE_HELPURL": "https://uk.wikipedia.org/wiki/Квадратний_корінь", - "MATH_SINGLE_OP_ROOT": "квадратний корінь", - "MATH_SINGLE_TOOLTIP_ROOT": "Повертає квадратний корінь з числа.", - "MATH_SINGLE_OP_ABSOLUTE": "модуль", - "MATH_SINGLE_TOOLTIP_ABS": "Повертає модуль числа.", - "MATH_SINGLE_TOOLTIP_NEG": "Повертає протилежне число.", - "MATH_SINGLE_TOOLTIP_LN": "Повертає натуральний логарифм числа.", - "MATH_SINGLE_TOOLTIP_LOG10": "Повертає десятковий логарифм числа.", - "MATH_SINGLE_TOOLTIP_EXP": "Повертає e у степені.", - "MATH_SINGLE_TOOLTIP_POW10": "Повертає 10 у степені.", - "MATH_TRIG_HELPURL": "https://uk.wikipedia.org/wiki/Тригонометричні_функції", - "MATH_TRIG_TOOLTIP_SIN": "Повертає синус кута в градусах (не в радіанах).", - "MATH_TRIG_TOOLTIP_COS": "Повертає косинус кута в градусах (не в радіанах).", - "MATH_TRIG_TOOLTIP_TAN": "Повертає тангенс кута в градусах (не в радіанах).", - "MATH_TRIG_TOOLTIP_ASIN": "Повертає арксинус числа.", - "MATH_TRIG_TOOLTIP_ACOS": "Повертає арккосинус числа.", - "MATH_TRIG_TOOLTIP_ATAN": "Повертає арктангенс числа.", - "MATH_CONSTANT_HELPURL": "https://uk.wikipedia.org/wiki/Математична_константа", - "MATH_CONSTANT_TOOLTIP": "Повертає одну з поширених констант: π (3.141...), e (2.718...), φ (1,618...), sqrt(2) (1.414...), sqrt(½) (0.707...) або ∞ (нескінченність).", - "MATH_IS_EVEN": "парне", - "MATH_IS_ODD": "непарне", - "MATH_IS_PRIME": "просте", - "MATH_IS_WHOLE": "ціле", - "MATH_IS_POSITIVE": "додатне", - "MATH_IS_NEGATIVE": "від'ємне", - "MATH_IS_DIVISIBLE_BY": "ділиться на", - "MATH_IS_TOOLTIP": "Перевіряє, чи число парне, непарне, просте, ціле, додатне, від'ємне або чи воно ділиться на певне число без остачі. Повертає істину або хибність.", - "MATH_CHANGE_HELPURL": "https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter", - "MATH_CHANGE_TITLE": "змінити %1 на %2", - "MATH_CHANGE_TOOLTIP": "Додати число до змінної '%1'.", - "MATH_ROUND_HELPURL": "https://uk.wikipedia.org/wiki/Округлення", - "MATH_ROUND_TOOLTIP": "Округлення числа до більшого або до меншого.", - "MATH_ROUND_OPERATOR_ROUND": "округлити", - "MATH_ROUND_OPERATOR_ROUNDUP": "округлити до більшого", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "округлити до меншого", - "MATH_ONLIST_HELPURL": "http://www.mapleprimes.com/questions/100441-Applying-Function-To-List-Of-Numbers", - "MATH_ONLIST_OPERATOR_SUM": "сума списку", - "MATH_ONLIST_TOOLTIP_SUM": "Повертає суму всіх чисел у списку.", - "MATH_ONLIST_OPERATOR_MIN": "мінімум списку", - "MATH_ONLIST_TOOLTIP_MIN": "Повертає найменше число у списку.", - "MATH_ONLIST_OPERATOR_MAX": "максимум списку", - "MATH_ONLIST_TOOLTIP_MAX": "Повертає найбільше число у списку.", - "MATH_ONLIST_OPERATOR_AVERAGE": "середнє списку", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Повертає середнє (арифметичне) числових значень у списку.", - "MATH_ONLIST_OPERATOR_MEDIAN": "медіана списку", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Повертає медіану списку.", - "MATH_ONLIST_OPERATOR_MODE": "моди списку", - "MATH_ONLIST_TOOLTIP_MODE": "Повертає перелік найпоширеніших елементів у списку.", - "MATH_ONLIST_OPERATOR_STD_DEV": "стандартне відхилення списку", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Повертає стандартне відхилення списку.", - "MATH_ONLIST_OPERATOR_RANDOM": "випадковий елемент списку", - "MATH_ONLIST_TOOLTIP_RANDOM": "Повертає випадковий елемент зі списку.", - "MATH_MODULO_HELPURL": "https://uk.wikipedia.org/wiki/Ділення_з_остачею", - "MATH_MODULO_TITLE": "остача від %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Повертає остачу від ділення двох чисел.", - "MATH_CONSTRAIN_TITLE": "обмежити %1 від %2 до %3", - "MATH_CONSTRAIN_TOOLTIP": "Обмежує число вказаними межами (включно).", - "MATH_RANDOM_INT_HELPURL": "https://uk.wikipedia.org/wiki/Генерація_випадкових_чисел", - "MATH_RANDOM_INT_TITLE": "випадкове ціле число від %1 до %2", - "MATH_RANDOM_INT_TOOLTIP": "Повертає випадкове ціле число між двома заданими межами включно.", - "MATH_RANDOM_FLOAT_HELPURL": "https://uk.wikipedia.org/wiki/Генерація_випадкових_чисел", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "випадковий дріб", - "MATH_RANDOM_FLOAT_TOOLTIP": "Повертає випадковий дріб від 0,0 (включно) та 1.0 (не включно).", - "TEXT_TEXT_HELPURL": "https://uk.wikipedia.org/wiki/Рядок_(програмування)", - "TEXT_TEXT_TOOLTIP": "Символ, слово або рядок тексту.", - "TEXT_JOIN_HELPURL": "http://www.chemie.fu-berlin.de/chemnet/use/info/make/make_8.html", - "TEXT_JOIN_TITLE_CREATEWITH": "створити текст з", - "TEXT_JOIN_TOOLTIP": "Створити фрагмент тексту шляхом з'єднування будь-якого числа елементів.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "приєднати", - "TEXT_CREATE_JOIN_TOOLTIP": "Додайте, вилучіть або змініть порядок секцій для переналаштування текстового блоку.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "Додати елемент до тексту.", - "TEXT_APPEND_TO": "до", - "TEXT_APPEND_APPENDTEXT": "додати текст", - "TEXT_APPEND_TOOLTIP": "Додати деякий текст до змінної '%1'.", - "TEXT_LENGTH_TITLE": "довжина %1", - "TEXT_LENGTH_TOOLTIP": "Повертає число символів (включно з пропусками) у даному тексті.", - "TEXT_ISEMPTY_TITLE": "%1 є порожнім", - "TEXT_ISEMPTY_TOOLTIP": "Повертає істину, якщо вказаний текст порожній.", - "TEXT_INDEXOF_TOOLTIP": "Повертає індекс першого/останнього входження першого тексту в другий. Повертає %1, якщо текст не знайдено.", - "TEXT_INDEXOF_INPUT_INTEXT": "у тексті", - "TEXT_INDEXOF_OPERATOR_FIRST": "знайти перше входження тексту", - "TEXT_INDEXOF_OPERATOR_LAST": "знайти останнє входження тексту", - "TEXT_INDEXOF_TAIL": ".", - "TEXT_CHARAT_HELPURL": "http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Farsubex.htm", - "TEXT_CHARAT_INPUT_INTEXT": "у тексті", - "TEXT_CHARAT_FROM_START": "отримати символ #", - "TEXT_CHARAT_FROM_END": "отримати символ # з кінця", - "TEXT_CHARAT_FIRST": "отримати перший символ", - "TEXT_CHARAT_LAST": "отримати останній символ", - "TEXT_CHARAT_RANDOM": "отримати випадковий символ", - "TEXT_CHARAT_TAIL": "-ий.", - "TEXT_CHARAT_TOOLTIP": "Повертає символ у зазначеній позиції.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Повертає заданий фрагмент тексту.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "у тексті", - "TEXT_GET_SUBSTRING_START_FROM_START": "отримати підрядок від символу #", - "TEXT_GET_SUBSTRING_START_FROM_END": "отримати підрядок від символу # з кінця", - "TEXT_GET_SUBSTRING_START_FIRST": "отримати підрядок від першого символу", - "TEXT_GET_SUBSTRING_END_FROM_START": "до символу #", - "TEXT_GET_SUBSTRING_END_FROM_END": "до символу # з кінця", - "TEXT_GET_SUBSTRING_END_LAST": "до останнього символу", - "TEXT_GET_SUBSTRING_TAIL": "-ого.", - "TEXT_CHANGECASE_TOOLTIP": "В іншому випадку повертає копію тексту.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "до ВЕРХНЬОГО регістру", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "до нижнього регістру", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "Великі Перші Букви", - "TEXT_TRIM_TOOLTIP": "Повертає копію тексту з вилученими пропусками з одного або обох кінців.", - "TEXT_TRIM_OPERATOR_BOTH": "вилучити крайні пропуски з обох кінців", - "TEXT_TRIM_OPERATOR_LEFT": "вилучити пропуски з лівого боку", - "TEXT_TRIM_OPERATOR_RIGHT": "вилучити пропуски з правого боку", - "TEXT_PRINT_TITLE": "друк %1", - "TEXT_PRINT_TOOLTIP": "Надрукувати заданий текст, числа або інші значення.", - "TEXT_PROMPT_TYPE_TEXT": "запит тексту з повідомленням", - "TEXT_PROMPT_TYPE_NUMBER": "запит числа з повідомленням", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Запитати у користувача число.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Запитати у користувача деякий текст.", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "створити порожній список", - "LISTS_CREATE_EMPTY_TOOLTIP": "Повертає список, довжиною 0, що не містить записів даних", - "LISTS_CREATE_WITH_TOOLTIP": "Створює список з будь-якою кількістю елементів.", - "LISTS_CREATE_WITH_INPUT_WITH": "створити список з", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "список", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Додайте, вилучіть або змініть порядок секцій для переналаштування блока списку.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Додати елемент до списку.", - "LISTS_REPEAT_TOOLTIP": "Створює список, що складається з заданого значення повтореного задану кількість разів.", - "LISTS_REPEAT_TITLE": "створити список з елемента %1 повтореного %2 разів", - "LISTS_LENGTH_TITLE": "довжина %1", - "LISTS_LENGTH_TOOLTIP": "Повертає довжину списку.", - "LISTS_ISEMPTY_TITLE": "%1 є порожнім", - "LISTS_ISEMPTY_TOOLTIP": "Повертає істину, якщо список порожній.", - "LISTS_INLIST": "у списку", - "LISTS_INDEX_OF_FIRST": "знайти перше входження елемента", - "LISTS_INDEX_OF_LAST": "знайти останнє входження елемента", - "LISTS_INDEX_OF_TOOLTIP": "Повертає індекс першого/останнього входження елемента у списку. Повертає %1, якщо елемент не знайдено.", - "LISTS_GET_INDEX_GET": "отримати", - "LISTS_GET_INDEX_GET_REMOVE": "отримати і вилучити", - "LISTS_GET_INDEX_REMOVE": "вилучити", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "# з кінця", - "LISTS_GET_INDEX_FIRST": "перший", - "LISTS_GET_INDEX_LAST": "останній", - "LISTS_GET_INDEX_RANDOM": "випадковий", - "LISTS_GET_INDEX_TAIL": "-ий.", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 - це перший елемент.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 - це останній елемент.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Повертає елемент у заданій позиції у списку.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Повертає перший елемент списку.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Повертає останній елемент списку.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Повертає випадковий елемент списку.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Видаляє і повертає елемент у заданій позиції у списку.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Видаляє і повертає перший елемент списку.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Видаляє і повертає останній елемент списку.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Видаляє і повертає випадковий елемент списоку.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Вилучає зі списку елемент у вказаній позиції.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Вилучає перший елемент списку.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Вилучає останній елемент списку.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Вилучає випадковий елемент списку.", - "LISTS_SET_INDEX_SET": "встановити", - "LISTS_SET_INDEX_INSERT": "вставити в", - "LISTS_SET_INDEX_INPUT_TO": "як", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Задає елемент списку у вказаній позиції.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Задає перший елемент списку.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Задає останній елемент списку.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Задає випадковий елемент у списку.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Вставка елемента у вказану позицію списку.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Вставляє елемент на початок списку.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Додає елемент у кінці списку.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Випадковим чином вставляє елемент у список.", - "LISTS_GET_SUBLIST_START_FROM_START": "отримати вкладений список з #", - "LISTS_GET_SUBLIST_START_FROM_END": "отримати вкладений список від # з кінця", - "LISTS_GET_SUBLIST_START_FIRST": "отримати вкладений список з першого", - "LISTS_GET_SUBLIST_END_FROM_START": "до #", - "LISTS_GET_SUBLIST_END_FROM_END": "до # з кінця", - "LISTS_GET_SUBLIST_END_LAST": "до останнього", - "LISTS_GET_SUBLIST_TAIL": "символу.", - "LISTS_GET_SUBLIST_TOOLTIP": "Створює копію вказаної частини списку.", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "сортувати %3 %1 %2", - "LISTS_SORT_TOOLTIP": "Сортувати копію списку.", - "LISTS_SORT_ORDER_ASCENDING": "за зростанням", - "LISTS_SORT_ORDER_DESCENDING": "за спаданням", - "LISTS_SORT_TYPE_NUMERIC": "як числа", - "LISTS_SORT_TYPE_TEXT": "за абеткою", - "LISTS_SORT_TYPE_IGNORECASE": "за абеткою, ігноруючи регістр", - "LISTS_SPLIT_LIST_FROM_TEXT": "зробити з тексту список", - "LISTS_SPLIT_TEXT_FROM_LIST": "зробити зі списку текст", - "LISTS_SPLIT_WITH_DELIMITER": "з розділювачем", - "LISTS_SPLIT_TOOLTIP_SPLIT": "Поділити текст на список текстів, розриваючи на кожному розділювачі.", - "LISTS_SPLIT_TOOLTIP_JOIN": "Злити список текстів у єдиний текст, відокремивши розділювачами.", - "ORDINAL_NUMBER_SUFFIX": "-ий.", - "VARIABLES_GET_TOOLTIP": "Повертає значення цієї змінної.", - "VARIABLES_GET_CREATE_SET": "Створити 'встановити %1'", - "VARIABLES_SET": "встановити %1 до %2", - "VARIABLES_SET_TOOLTIP": "Задає цю змінну рівною входу.", - "VARIABLES_SET_CREATE_GET": "Створити 'отримати %1'", - "PROCEDURES_DEFNORETURN_HELPURL": "https://uk.wikipedia.org/wiki/Підпрограма", - "PROCEDURES_DEFNORETURN_TITLE": "до", - "PROCEDURES_DEFNORETURN_PROCEDURE": "щось зробити", - "PROCEDURES_BEFORE_PARAMS": "з:", - "PROCEDURES_CALL_BEFORE_PARAMS": "з:", - "PROCEDURES_DEFNORETURN_DO": "блок тексту", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Створює функцію без виводу.", - "PROCEDURES_DEFNORETURN_COMMENT": "Опишіть цю функцію...", - "PROCEDURES_DEFRETURN_HELPURL": "https://uk.wikipedia.org/wiki/Підпрограма", - "PROCEDURES_DEFRETURN_RETURN": "повернути", - "PROCEDURES_DEFRETURN_TOOLTIP": "Створює функцію з виводом.", - "PROCEDURES_ALLOW_STATEMENTS": "дозволити дії", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Увага: ця функція має дубльовані параметри.", - "PROCEDURES_CALLNORETURN_HELPURL": "https://uk.wikipedia.org/wiki/Підпрограма", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Запустити користувацьку функцію \"%1\".", - "PROCEDURES_CALLRETURN_HELPURL": "https://uk.wikipedia.org/wiki/Підпрограма", - "PROCEDURES_CALLRETURN_TOOLTIP": "Запустити користувацьку функцію \"%1\" і використати її вивід.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "входи", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Додайте, вилучіть або змініть порядок вхідних параметрів для цієї функції.", - "PROCEDURES_MUTATORARG_TITLE": "назва входу:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Додати до функції вхідні параметри.", - "PROCEDURES_HIGHLIGHT_DEF": "Підсвітити визначення функції", - "PROCEDURES_CREATE_DO": "Створити \"%1\"", - "PROCEDURES_IFRETURN_TOOLTIP": "Якщо значення істинне, то повернути друге значення.", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "Попередження: цей блок може використовуватися лише в межах визначення функції." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/vi.json b/backend/_pv_1_3_5/static/blockly/msg/json/vi.json deleted file mode 100755 index cfe6c7dbb..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/vi.json +++ /dev/null @@ -1,298 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Baonguyen21022003", - "Espertus", - "Qneutron", - "Withoutaname", - "Dstream" - ] - }, - "VARIABLES_DEFAULT_NAME": "vật", - "DUPLICATE_BLOCK": "Tạo Bản Sao", - "ADD_COMMENT": "Thêm Chú Giải", - "REMOVE_COMMENT": "Xóa Chú Giải", - "EXTERNAL_INPUTS": "Chỗ Gắn Bên Ngoài", - "INLINE_INPUTS": "Chỗ Gắn Cùng Dòng", - "DELETE_BLOCK": "Xóa Mảnh Này", - "DELETE_X_BLOCKS": "Xóa %1 Mảnh", - "DELETE_ALL_BLOCKS": "Xóa hết %1 mảnh?", - "COLLAPSE_BLOCK": "Thu Nhỏ Mảnh", - "COLLAPSE_ALL": "Thu Nhỏ Mọi Mảnh", - "EXPAND_BLOCK": "Mở Lớn Mảnh", - "EXPAND_ALL": "Mở Lớn Mọi Mảnh", - "DISABLE_BLOCK": "Ngưng Tác Dụng", - "ENABLE_BLOCK": "Phục Hồi Tác Dụng", - "HELP": "Trợ Giúp", - "CHANGE_VALUE_TITLE": "Thay giá trị thành:", - "RENAME_VARIABLE": "Thay tên biến...", - "RENAME_VARIABLE_TITLE": "Thay tên tất cả \"%1\" biến này thành:", - "NEW_VARIABLE": "Biến mới...", - "NEW_VARIABLE_TITLE": "Tên của biến mới:", - "COLOUR_PICKER_HELPURL": "https://vi.wikipedia.org/wiki/M%C3%A0u_s%E1%BA%AFc", - "COLOUR_PICKER_TOOLTIP": "Chọn một màu từ bảng màu.", - "COLOUR_RANDOM_TITLE": "màu bất kỳ", - "COLOUR_RANDOM_TOOLTIP": "chọn một màu bất kỳ.", - "COLOUR_RGB_TITLE": "Tạo màu từ", - "COLOUR_RGB_RED": "màu đỏ", - "COLOUR_RGB_GREEN": "màu xanh lá cây", - "COLOUR_RGB_BLUE": "màu xanh dương", - "COLOUR_RGB_TOOLTIP": "Tạo màu từ ba màu: đỏ, xanh lá cây, xanh dương với số lượng cụ thể. Mỗi số phải có giá trị từ 0 đến 100.", - "COLOUR_BLEND_TITLE": "pha", - "COLOUR_BLEND_COLOUR1": "màu 1", - "COLOUR_BLEND_COLOUR2": "màu 2", - "COLOUR_BLEND_RATIO": "tỉ lệ", - "COLOUR_BLEND_TOOLTIP": "Pha hai màu với nhau theo tỉ lệ (0 - 100).", - "CONTROLS_REPEAT_HELPURL": "https://en.wikipedia.org/wiki/For_loop", - "CONTROLS_REPEAT_TITLE": "lặp lại %1 lần", - "CONTROLS_REPEAT_INPUT_DO": "thực hiện", - "CONTROLS_REPEAT_TOOLTIP": "Thực hiện các lệnh vài lần.", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "lặp lại trong khi", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "lặp lại cho đến khi", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "Miễn là điều kiện còn đúng, thì thực hiện các lệnh.", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "Miễn là điều kiện còn sai, thì thực hiện các lệnh. Khi điều kiện đúng thì ngưng.", - "CONTROLS_FOR_TOOLTIP": "Đếm từ số đầu đến số cuối. Khi đến mỗi số, gán số vào biến \"%1\" rồi thực hiện các lệnh.", - "CONTROLS_FOR_TITLE": "đếm theo %1 từ %2 đến %3 mỗi lần thêm %4", - "CONTROLS_FOREACH_TITLE": "với mỗi thành phần %1 trong danh sách %2", - "CONTROLS_FOREACH_TOOLTIP": "Trong một danh sách, lấy từng thành phần, gán vào biến \"%1\", rồi thực hiện một số lệnh.", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "thoát", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "sang lần lặp tiếp theo", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "Thoát khỏi vòng lặp hiện tại.", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "Bỏ qua phần còn lại trong vòng lặp này, và sang lần lặp tiếp theo.", - "CONTROLS_FLOW_STATEMENTS_WARNING": "Chú ý: Mảnh này chỉ có thế dùng trong các vòng lặp.", - "CONTROLS_IF_TOOLTIP_1": "Nếu điều kiện đúng, thực hiện các lệnh.", - "CONTROLS_IF_TOOLTIP_2": "Nếu điều kiện đúng, thực hiện các lệnh đầu. Nếu sai, thực hiện các lệnh sau.", - "CONTROLS_IF_TOOLTIP_3": "Nếu điều kiện đúng, thực hiện các lệnh đầu. Nếu không, nếu điều kiện thứ hai đúng, thực hiện các lệnh thứ hai.", - "CONTROLS_IF_TOOLTIP_4": "Nếu điều kiện đúng, thực hiện các lệnh đầu. Nếu không, nếu điều kiện thứ hai đúng, thực hiện các lệnh thứ hai. Nếu không điều kiện nào đúng, thực hiện các lệnh cuối cùng.", - "CONTROLS_IF_MSG_IF": "nếu", - "CONTROLS_IF_MSG_ELSEIF": "nếu không nếu", - "CONTROLS_IF_MSG_ELSE": "nếu không", - "CONTROLS_IF_IF_TOOLTIP": "Thêm, bỏ, hoặc đổi thứ tự các mảnh con để tạo cấu trúc mới cho mảnh nếu.", - "CONTROLS_IF_ELSEIF_TOOLTIP": "Thêm một điều kiện vào mảnh nếu.", - "CONTROLS_IF_ELSE_TOOLTIP": "Cuối cùng, khi không điều kiện nào đúng.", - "LOGIC_COMPARE_HELPURL": "https://vi.wikipedia.org/wiki/B%E1%BA%A5t_%C4%91%E1%BA%B3ng_th%E1%BB%A9c", - "LOGIC_COMPARE_TOOLTIP_EQ": "Hoàn trả giá trị \"đúng\" (true) nếu giá trị hai đầu vào bằng nhau.", - "LOGIC_COMPARE_TOOLTIP_NEQ": "Hoàn trả giá trị \"đúng\" (true) nếu giá trị hai đầu vào không bằng nhau.", - "LOGIC_COMPARE_TOOLTIP_LT": "Hoàn trả giá trị \"đúng\" (true) nếu đầu vào thứ nhất nhỏ hơn đầu vào thứ hai.", - "LOGIC_COMPARE_TOOLTIP_LTE": "Hoàn trả giá trị \"đúng\" (true) nếu đầu vào thứ nhất nhỏ hơn hoặc bằng đầu vào thứ hai.", - "LOGIC_COMPARE_TOOLTIP_GT": "Hoàn trả giá trị \"đúng\" (true) nếu đầu vào thứ nhất lớn hơn đầu vào thứ hai.", - "LOGIC_COMPARE_TOOLTIP_GTE": "Hoàn trả giá trị \"đúng\" (true) nếu đầu vào thứ nhất lớn hơn hoặc bằng đầu vào thứ hai.", - "LOGIC_OPERATION_TOOLTIP_AND": "Hoàn trả \"đúng\" (true) nếu cả hai đầu vào đều đúng.", - "LOGIC_OPERATION_AND": "và", - "LOGIC_OPERATION_TOOLTIP_OR": "Hoàn trả \"đúng\" (true) nếu ít nhất một trong hai đầu vào đúng.", - "LOGIC_OPERATION_OR": "hoặc", - "LOGIC_NEGATE_TITLE": "không %1", - "LOGIC_NEGATE_TOOLTIP": "Hoàn trả \"đúng\" (true) nếu đầu vào sai. Hoàn trả \"sai\" (false) nếu đầu vào đúng.", - "LOGIC_BOOLEAN_TRUE": "đúng", - "LOGIC_BOOLEAN_FALSE": "sai", - "LOGIC_BOOLEAN_TOOLTIP": "Hoàn trả \"đúng\" hoặc \"sai\".", - "LOGIC_NULL": "trống không", - "LOGIC_NULL_TOOLTIP": "Hoàn trả trống không.", - "LOGIC_TERNARY_CONDITION": "kiểm tra", - "LOGIC_TERNARY_IF_TRUE": "nếu đúng", - "LOGIC_TERNARY_IF_FALSE": "nếu sai", - "LOGIC_TERNARY_TOOLTIP": "Kiểm tra điều kiện. Nếu điều kiện đúng, hoàn trả giá trị từ mệnh đề \"nếu đúng\" nếu không đúng, hoàn trả giá trị từ mệnh đề \"nếu sai\".", - "MATH_NUMBER_HELPURL": "https://vi.wikipedia.org/wiki/S%E1%BB%91", - "MATH_NUMBER_TOOLTIP": "Một con số.", - "MATH_ARITHMETIC_HELPURL": "https://vi.wikipedia.org/wiki/S%E1%BB%91_h%E1%BB%8Dc", - "MATH_ARITHMETIC_TOOLTIP_ADD": "Hoàn trả tổng của hai con số.", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "Hoàn trả hiệu của hai con số.", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "Hoàn trả tích của hai con số.", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "Hoàn trả thương của hai con số.", - "MATH_ARITHMETIC_TOOLTIP_POWER": "Hoàn trả số lũy thừa với số thứ nhất là cơ số và số thứ hai là số mũ.", - "MATH_SINGLE_HELPURL": "https://vi.wikipedia.org/wiki/C%C4%83n_b%E1%BA%ADc_hai", - "MATH_SINGLE_OP_ROOT": "căn bật hai", - "MATH_SINGLE_TOOLTIP_ROOT": "Hoàn trả căn bật hai của số đầu vào.", - "MATH_SINGLE_OP_ABSOLUTE": "giá trị tuyệt đối", - "MATH_SINGLE_TOOLTIP_ABS": "Hoàn trả giá trị tuyệt đối của số đầu vào.", - "MATH_SINGLE_TOOLTIP_NEG": "Đổi dấu của số đầu vào: âm thành dương và dương thành âm, và hoàn trả số mới.", - "MATH_SINGLE_TOOLTIP_LN": "Hoàn trả lôgarit tự nhiên của số đầu vào.", - "MATH_SINGLE_TOOLTIP_LOG10": "Hoàn trả lôgarit cơ số 10 của số đầu vào.", - "MATH_SINGLE_TOOLTIP_EXP": "Hoàn trả lũy thừa của số e với số mũ đầu vào.", - "MATH_SINGLE_TOOLTIP_POW10": "Hoàn trả lũy thừa của số 10 với số mũ đầu vào.", - "MATH_TRIG_HELPURL": "https://vi.wikipedia.org/wiki/H%C3%A0m_l%C6%B0%E1%BB%A3ng_gi%C3%A1c", - "MATH_TRIG_TOOLTIP_SIN": "Hoàn trả Sin của một góc (theo độ).", - "MATH_TRIG_TOOLTIP_COS": "Hoàn trả Cos của một góc (theo độ).", - "MATH_TRIG_TOOLTIP_TAN": "Hoàn trả Tang của một góc (theo độ).", - "MATH_TRIG_TOOLTIP_ASIN": "Hoàn trả Arcsin của một góc (theo độ).", - "MATH_TRIG_TOOLTIP_ACOS": "Hoàn trả Arccos của một góc (theo độ).", - "MATH_TRIG_TOOLTIP_ATAN": "Hoàn trả Arctang của một góc (theo độ).", - "MATH_CONSTANT_HELPURL": "https://en.wikipedia.org/wiki/Mathematical_constant", - "MATH_CONSTANT_TOOLTIP": "Hoàn trả các đẳng số thường gặp: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (vô cực).", - "MATH_IS_EVEN": "chẵn", - "MATH_IS_ODD": "lẻ", - "MATH_IS_PRIME": "là số nguyên tố", - "MATH_IS_WHOLE": "là số nguyên", - "MATH_IS_POSITIVE": "là số dương", - "MATH_IS_NEGATIVE": "là số âm", - "MATH_IS_DIVISIBLE_BY": "chia hết cho", - "MATH_IS_TOOLTIP": "Kiểm tra con số xem nó có phải là số chẵn, lẻ, nguyên tố, nguyên, dương, âm, hay xem nó có chia hết cho số đầu vào hay không. Hoàn trả đúng hay sai.", - "MATH_CHANGE_HELPURL": "https://vi.wikipedia.org/wiki/Ph%C3%A9p_c%E1%BB%99ng", - "MATH_CHANGE_TITLE": "cộng vào %1 giá trị %2", - "MATH_CHANGE_TOOLTIP": "Cộng số đầu vào vào biến \"%1\".", - "MATH_ROUND_HELPURL": "https://en.wikipedia.org/wiki/Rounding", - "MATH_ROUND_TOOLTIP": "Làm tròn lên hoặc tròn xuống số đầu vào.", - "MATH_ROUND_OPERATOR_ROUND": "làm tròn", - "MATH_ROUND_OPERATOR_ROUNDUP": "làm tròn lên", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "làm tròn xuống", - "MATH_ONLIST_HELPURL": "", - "MATH_ONLIST_OPERATOR_SUM": "tổng của một danh sách", - "MATH_ONLIST_TOOLTIP_SUM": "Hoàn trả tổng số của tất cả các số trong danh sách.", - "MATH_ONLIST_OPERATOR_MIN": "số nhỏ nhất của một danh sách", - "MATH_ONLIST_TOOLTIP_MIN": "Hoàn trả số nhỏ nhất trong tất cả các số trong danh sách.", - "MATH_ONLIST_OPERATOR_MAX": "số lớn nhât của một danh sách", - "MATH_ONLIST_TOOLTIP_MAX": "Hoàn trả số lớn nhất trong tất cả các số trong danh sách.", - "MATH_ONLIST_OPERATOR_AVERAGE": "giá trị trung bình của một danh sách", - "MATH_ONLIST_TOOLTIP_AVERAGE": "Hoàn trả giá trị trung bình từ của danh sách số.", - "MATH_ONLIST_OPERATOR_MEDIAN": "số trung vị của một danh sách", - "MATH_ONLIST_TOOLTIP_MEDIAN": "Hoàn trả số trung vị của danh sách số.", - "MATH_ONLIST_OPERATOR_MODE": "các mode của một danh sách", - "MATH_ONLIST_TOOLTIP_MODE": "Hoàn trả các số có mặt nhiều nhất trong danh sách.", - "MATH_ONLIST_OPERATOR_STD_DEV": "độ lệch chuẩn của một danh sách", - "MATH_ONLIST_TOOLTIP_STD_DEV": "Hoàn trả độ lệch chuẩn của danh sách số.", - "MATH_ONLIST_OPERATOR_RANDOM": "một số bất kỳ của một danh sách", - "MATH_ONLIST_TOOLTIP_RANDOM": "Hoàn trả một số bất kỳ từ các số trong danh sách.", - "MATH_MODULO_HELPURL": "https://en.wikipedia.org/wiki/Modulo_operation", - "MATH_MODULO_TITLE": "số dư của %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "Chia số thứ nhất cho số thứ hai rồi hoàn trả số dư từ.", - "MATH_CONSTRAIN_TITLE": "giới hạn %1 không dưới %2 không hơn %3", - "MATH_CONSTRAIN_TOOLTIP": "Giới hạn số đầu vào để không dưới số thứ nhất và không hơn số thứ hai.", - "MATH_RANDOM_INT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_INT_TITLE": "Một số nguyên bất kỳ từ %1 đến %2", - "MATH_RANDOM_INT_TOOLTIP": "Hoàn trả một số nguyên bất kỳ lớn hơn hoặc bằng số đầu và nhỏ hơn hoặc bằng số sau.", - "MATH_RANDOM_FLOAT_HELPURL": "https://en.wikipedia.org/wiki/Random_number_generation", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "phân số bất kỳ", - "MATH_RANDOM_FLOAT_TOOLTIP": "Hoàn trả một phân số bất kỳ không nhỏ hơn 0.0 và không lớn hơn 1.0.", - "TEXT_TEXT_HELPURL": "https://en.wikipedia.org/wiki/string_(computer_science)", - "TEXT_TEXT_TOOLTIP": "Một ký tự, một từ, hay một dòng.", - "TEXT_JOIN_HELPURL": "", - "TEXT_JOIN_TITLE_CREATEWITH": "tạo văn bản từ", - "TEXT_JOIN_TOOLTIP": "Tạo một văn bản từ các thành phần.", - "TEXT_CREATE_JOIN_TITLE_JOIN": "kết nối", - "TEXT_CREATE_JOIN_TOOLTIP": "Thêm, bỏ, hoặc sắp xếp lại các thành phần để tạo dựng mảnh văn bản này.", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "thêm vật mới vào văn bản.", - "TEXT_APPEND_TO": "ở cuối", - "TEXT_APPEND_APPENDTEXT": "thêm văn bản", - "TEXT_APPEND_TOOLTIP": "Thêm một mảng văn bản vào biến \"%1\".", - "TEXT_LENGTH_TITLE": "độ dài của %1", - "TEXT_LENGTH_TOOLTIP": "Hoàn trả số lượng ký tự (kể cả khoảng trắng) trong văn bản đầu vào.", - "TEXT_ISEMPTY_TITLE": "%1 trống không", - "TEXT_ISEMPTY_TOOLTIP": "Hoàn trả “đúng nếu văn bản không có ký tự nào.", - "TEXT_INDEXOF_TOOLTIP": "Hoàn trả vị trí xuất hiện đầu/cuối của văn bản thứ nhất trong văn bản thứ hai. Nếu không tìm thấy thì hoàn trả số %1.", - "TEXT_INDEXOF_INPUT_INTEXT": "trong văn bản", - "TEXT_INDEXOF_OPERATOR_FIRST": "tìm sự có mặt đầu tiên của", - "TEXT_INDEXOF_OPERATOR_LAST": "tìm sự có mặt cuối cùng của", - "TEXT_CHARAT_INPUT_INTEXT": "trong văn bản", - "TEXT_CHARAT_FROM_START": "lấy ký tự thứ", - "TEXT_CHARAT_FROM_END": "lấy từ phía cuối, ký tự thứ", - "TEXT_CHARAT_FIRST": "lấy ký tự đầu tiên", - "TEXT_CHARAT_LAST": "lấy ký tự cuối cùng", - "TEXT_CHARAT_RANDOM": "lấy ký tự bất kỳ", - "TEXT_CHARAT_TAIL": "", - "TEXT_CHARAT_TOOLTIP": "Hoàn trả ký tự ở vị trí đặt ra.", - "TEXT_GET_SUBSTRING_TOOLTIP": "Hoàn trả một mảng ký tự ấn định từ trong văn bản.", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "trong văn bản", - "TEXT_GET_SUBSTRING_START_FROM_START": "lấy từ ký tự thứ", - "TEXT_GET_SUBSTRING_START_FROM_END": "lấy từ phía cuối, ký tự thứ", - "TEXT_GET_SUBSTRING_START_FIRST": "lấy từ ký tự đầu tiên", - "TEXT_GET_SUBSTRING_END_FROM_START": "đến ký tự thứ", - "TEXT_GET_SUBSTRING_END_FROM_END": "đến từ phía cuối, ký tự thứ", - "TEXT_GET_SUBSTRING_END_LAST": "đến ký tự cuối cùng", - "TEXT_GET_SUBSTRING_TAIL": "", - "TEXT_CHANGECASE_TOOLTIP": "Hoàn trả văn bản sau khi chuyển đổi chữ in hoa hay thường.", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "thành CHỮ IN HOA", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "thành chữ thường", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "thành Chữ In Đầu Mỗi Từ", - "TEXT_TRIM_TOOLTIP": "Hoàn trả bản sao của văn bản sau khi xóa khoảng trắng từ một hoặc hai bên.", - "TEXT_TRIM_OPERATOR_BOTH": "cắt các không gian từ cả hai mặt của", - "TEXT_TRIM_OPERATOR_LEFT": "cắt các không gian từ bên trái của", - "TEXT_TRIM_OPERATOR_RIGHT": "cắt các không gian từ bên phải của", - "TEXT_PRINT_TITLE": "in lên màng hình %1", - "TEXT_PRINT_TOOLTIP": "In ra màng hình một văn bản, con số, hay một giá trị đầu vào khác.", - "TEXT_PROMPT_TYPE_TEXT": "Xin người dùng nhập vào văn bản với dòng hướng dẫn", - "TEXT_PROMPT_TYPE_NUMBER": "Xin người dùng nhập vào con số với dòng hướng dẫn", - "TEXT_PROMPT_TOOLTIP_NUMBER": "Xin người dùng nhập vào một con số.", - "TEXT_PROMPT_TOOLTIP_TEXT": "Xin người dùng nhập vào một văn bản.", - "LISTS_CREATE_EMPTY_TITLE": "tạo danh sách trống", - "LISTS_CREATE_EMPTY_TOOLTIP": "Hoàn trả một danh sách, với độ dài 0, không có thành tố nào cả", - "LISTS_CREATE_WITH_TOOLTIP": "Tạo một danh sách bao gồm nhiều vậts, với một số lượng bất kỳ.", - "LISTS_CREATE_WITH_INPUT_WITH": "tạo danh sách gồm", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "danh sách", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "Thêm, bỏ, hoặc sắp xếp lại các thành phần để tạo dựng mảnh danh sách này.", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "Thêm vật vào danh sách.", - "LISTS_REPEAT_TOOLTIP": "Tạo danh sách gồm một số lượng vật nhất định với mỗi vật đều giống nhau.", - "LISTS_REPEAT_TITLE": "tạo danh sách gồm một vật %1 lặp lại %2 lần", - "LISTS_LENGTH_TITLE": "độ dài của %1", - "LISTS_LENGTH_TOOLTIP": "Hoàn trả độ dài của một danh sách.", - "LISTS_ISEMPTY_TITLE": "%1 trống rỗng", - "LISTS_ISEMPTY_TOOLTIP": "Hoàn trả “đúng\" nếu danh sách không có thành tử nào.", - "LISTS_INLIST": "trong dánh sách", - "LISTS_INDEX_OF_FIRST": "tìm sự có mặt đầu tiên của vật", - "LISTS_INDEX_OF_LAST": "tìm sự có mặt cuối cùng của vật", - "LISTS_INDEX_OF_TOOLTIP": "Hoàn trả vị trí xuất hiện đầu/cuối của vật trong danh sách. Nếu không tìm thấy thì hoàn trả số %1.", - "LISTS_GET_INDEX_GET": "lấy thành tố", - "LISTS_GET_INDEX_GET_REMOVE": "lấy và xóa thành tố", - "LISTS_GET_INDEX_REMOVE": "xóa thành tố", - "LISTS_GET_INDEX_FROM_START": "thứ", - "LISTS_GET_INDEX_FROM_END": "(đếm từ cuối) thứ", - "LISTS_GET_INDEX_FIRST": "đầu tiên", - "LISTS_GET_INDEX_LAST": "cuối cùng", - "LISTS_GET_INDEX_RANDOM": "bất kỳ", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 là thành tố đầu tiên.", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 là thành tố cuối cùng.", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "Hoàn trả thành tố trong danh sách ở vị trí ấn định.", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "Hoàn trả thành tố đầu tiên trong danh sách.", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "Hoàn trả thành tố cuối cùng trong danh sách.", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "Hoàn trả một thành tố bất kỳ trong danh sách.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "Hoàn trả và xóa thành tố trong danh sách ở vị trí ấn định.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "Hoàn trả và xóa thành tố đầu tiên trong danh sách.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "Hoàn trả và xóa thành tố cuối cùng trong danh sách.", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "Hoàn trả và xóa mộtthành tố bất kỳ trong danh sách.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "Xóa thành tố trong danh sách ở vị trí ấn định.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "Xóa thành tố đầu tiên trong danh sách.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "Xóa thành tố cuối cùng trong danh sách.", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "Xóa thành tố bất kỳ trong danh sách.", - "LISTS_SET_INDEX_SET": "đặt thành tố", - "LISTS_SET_INDEX_INSERT": "gắn chèn vào vị trí", - "LISTS_SET_INDEX_INPUT_TO": "giá trị", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "Đặt giá trị của thành tố ở vị trí ấn định trong một danh sách.", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "Đặt giá trị của thành tố đầu tiên trong danh sách.", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "Đặt giá trị của thành tố cuối cùng trong danh sách.", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "Đặt giá trị của thành tố ngẫu nhiên trong danh sách.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "Gắn chèn vật vào danh sách theo vị trí ấn định.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "Gắn chèn vật vào đầu danh sách.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "Gắn thêm vật vào cuối danh sách.", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "Gắn chèn vật vào danh sách ở vị trí ngẫu nhiên.", - "LISTS_GET_SUBLIST_START_FROM_START": "lấy một danh sách con từ thứ", - "LISTS_GET_SUBLIST_START_FROM_END": "lấy một danh sách con từ (đếm từ cuối) thứ", - "LISTS_GET_SUBLIST_START_FIRST": "lấy một danh sách con từ đầu tiên", - "LISTS_GET_SUBLIST_END_FROM_START": "đến thứ", - "LISTS_GET_SUBLIST_END_FROM_END": "đến (đếm từ cuối) thứ", - "LISTS_GET_SUBLIST_END_LAST": "đến cuối cùng", - "LISTS_GET_SUBLIST_TOOLTIP": "Lấy một mảng của danh sách này để tạo danh sách con.", - "VARIABLES_GET_TOOLTIP": "Hoàn trả giá trị của.", - "VARIABLES_GET_CREATE_SET": "Tạo mảnh \"đặt vào %1\"", - "VARIABLES_SET": "cho %1 bằng %2", - "VARIABLES_SET_TOOLTIP": "Đặt giá trị của biến này thành...", - "VARIABLES_SET_CREATE_GET": "Tạo mảnh \"lấy %1\"", - "PROCEDURES_DEFNORETURN_TITLE": "", - "PROCEDURES_DEFNORETURN_PROCEDURE": "thủ tục", - "PROCEDURES_BEFORE_PARAMS": "với:", - "PROCEDURES_CALL_BEFORE_PARAMS": "với:", - "PROCEDURES_DEFNORETURN_DO": "", - "PROCEDURES_DEFNORETURN_TOOLTIP": "Một thủ tục không có giá trị hoàn trả.", - "PROCEDURES_DEFRETURN_RETURN": "hoàn trả", - "PROCEDURES_DEFRETURN_TOOLTIP": "Một thủ tục có giá trị hoàn trả.", - "PROCEDURES_ALLOW_STATEMENTS": "cho phép báo cáo", - "PROCEDURES_DEF_DUPLICATE_WARNING": "Chú ý: Thủ tục này có lặp lại tên các tham số.", - "PROCEDURES_CALLNORETURN_TOOLTIP": "Chạy một thủ tục không có giá trị hoàn trả.", - "PROCEDURES_CALLRETURN_TOOLTIP": "Chạy một thủ tục có giá trị hoàn trả.", - "PROCEDURES_MUTATORCONTAINER_TITLE": "các tham số", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "Thêm, xóa hoặc sắp xếp lại các đầu vào cho hàm này.", - "PROCEDURES_MUTATORARG_TITLE": "biến:", - "PROCEDURES_MUTATORARG_TOOLTIP": "Thêm một đầu vào cho hàm.", - "PROCEDURES_HIGHLIGHT_DEF": "Làm nổi bật thủ tục", - "PROCEDURES_CREATE_DO": "Tạo mảnh \"thực hiện %1\"", - "PROCEDURES_IFRETURN_TOOLTIP": "Khi điều kiện đúng thì hoàn trả một giá trị.", - "PROCEDURES_IFRETURN_WARNING": "Chú ý: Mảnh này chỉ có thể dùng trong một thủ tục." -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/zh-hans.json b/backend/_pv_1_3_5/static/blockly/msg/json/zh-hans.json deleted file mode 100755 index a4af49e2d..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/zh-hans.json +++ /dev/null @@ -1,336 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Espertus", - "Liuxinyu970226", - "Luotiancheng", - "Qiyue2001", - "Xiaomingyan", - "Yfdyh000", - "아라", - "Hudafu", - "Shatteredwind", - "Duzc2" - ] - }, - "VARIABLES_DEFAULT_NAME": "项目", - "TODAY": "今天", - "DUPLICATE_BLOCK": "复制", - "ADD_COMMENT": "添加注释", - "REMOVE_COMMENT": "删除注释", - "EXTERNAL_INPUTS": "外部输入", - "INLINE_INPUTS": "单行输入", - "DELETE_BLOCK": "删除块", - "DELETE_X_BLOCKS": "删除 %1 块", - "DELETE_ALL_BLOCKS": "删除所有%1块吗?", - "CLEAN_UP": "整理块", - "COLLAPSE_BLOCK": "折叠块", - "COLLAPSE_ALL": "折叠块", - "EXPAND_BLOCK": "展开块", - "EXPAND_ALL": "展开块", - "DISABLE_BLOCK": "禁用块", - "ENABLE_BLOCK": "启用块", - "HELP": "帮助", - "UNDO": "撤销", - "REDO": "重做", - "CHANGE_VALUE_TITLE": "更改值:", - "RENAME_VARIABLE": "重命名变量...", - "RENAME_VARIABLE_TITLE": "将所有“%1”变量重命名为:", - "NEW_VARIABLE": "创建变量...", - "NEW_VARIABLE_TITLE": "新变量的名称:", - "VARIABLE_ALREADY_EXISTS": "已存在名为“%1”的变量。", - "DELETE_VARIABLE_CONFIRMATION": "删除“%2”变量的%1种用途么?", - "DELETE_VARIABLE": "删除“%1”变量", - "COLOUR_PICKER_HELPURL": "https://zh.wikipedia.org/wiki/颜色", - "COLOUR_PICKER_TOOLTIP": "从调色板中选择一种颜色。", - "COLOUR_RANDOM_TITLE": "随机颜色", - "COLOUR_RANDOM_TOOLTIP": "随机选择一种颜色。", - "COLOUR_RGB_TITLE": "颜色", - "COLOUR_RGB_RED": "红色", - "COLOUR_RGB_GREEN": "绿色", - "COLOUR_RGB_BLUE": "蓝色", - "COLOUR_RGB_TOOLTIP": "通过指定红色、绿色和蓝色的量创建一种颜色。所有的值必须介于0和100之间。", - "COLOUR_BLEND_TITLE": "混合", - "COLOUR_BLEND_COLOUR1": "颜色1", - "COLOUR_BLEND_COLOUR2": "颜色2", - "COLOUR_BLEND_RATIO": "比例", - "COLOUR_BLEND_TOOLTIP": "用一个给定的比率(0.0-1.0)混合两种颜色。", - "CONTROLS_REPEAT_HELPURL": "https://zh.wikipedia.org/wiki/For循环", - "CONTROLS_REPEAT_TITLE": "重复 %1 次", - "CONTROLS_REPEAT_INPUT_DO": "执行", - "CONTROLS_REPEAT_TOOLTIP": "多次执行一些语句。", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "重复当", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "重复直到", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "只要值为真,执行一些语句。", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "只要值为假,执行一些语句。", - "CONTROLS_FOR_TOOLTIP": "从起始数到结尾数中取出变量“%1”的值,按指定的时间间隔,执行指定的块。", - "CONTROLS_FOR_TITLE": "使用 %1 从范围 %2 到 %3 每隔 %4", - "CONTROLS_FOREACH_TITLE": "为每个项目 %1 在列表中 %2", - "CONTROLS_FOREACH_TOOLTIP": "遍历每个列表中的项目,将变量“%1”设定到该项中,然后执行某些语句。", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "中断循环", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "继续下一次循环", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "中断包含它的循环。", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "跳过这个循环的剩余部分,并继续下一次迭代。", - "CONTROLS_FLOW_STATEMENTS_WARNING": "警告:此块仅可用于在一个循环内。", - "CONTROLS_IF_TOOLTIP_1": "如果值为真,执行一些语句。", - "CONTROLS_IF_TOOLTIP_2": "如果值为真,则执行第一块语句。否则,则执行第二块语句。", - "CONTROLS_IF_TOOLTIP_3": "如果第一个值为真,则执行第一块的语句。否则,如果第二个值为真,则执行第二块的语句。", - "CONTROLS_IF_TOOLTIP_4": "如果第一个值为真,则执行第一块对语句。否则,如果第二个值为真,则执行语句的第二块。如果没有值为真,则执行最后一块的语句。", - "CONTROLS_IF_MSG_IF": "如果", - "CONTROLS_IF_MSG_ELSEIF": "否则如果", - "CONTROLS_IF_MSG_ELSE": "否则", - "CONTROLS_IF_IF_TOOLTIP": "增加、删除或重新排列各节来重新配置“if”块。", - "CONTROLS_IF_ELSEIF_TOOLTIP": "在if语句块中增加一个条件。", - "CONTROLS_IF_ELSE_TOOLTIP": "添加一个最终的,包括所有情况的节到if块中。", - "LOGIC_COMPARE_HELPURL": "https://zh.wikipedia.org/wiki/不等", - "LOGIC_COMPARE_TOOLTIP_EQ": "如果两个输入结果相等,则返回真。", - "LOGIC_COMPARE_TOOLTIP_NEQ": "如果两个输入结果不相等,则返回真。", - "LOGIC_COMPARE_TOOLTIP_LT": "如果第一个输入结果比第二个小,则返回真。", - "LOGIC_COMPARE_TOOLTIP_LTE": "如果第一个输入结果小于或等于第二个输入结果,则返回真。", - "LOGIC_COMPARE_TOOLTIP_GT": "如果第一个输入结果比第二个大,则返回真。", - "LOGIC_COMPARE_TOOLTIP_GTE": "如果第一个输入结果大于或等于第二个输入结果,则返回真。", - "LOGIC_OPERATION_TOOLTIP_AND": "如果两个输入结果都为真,则返回真。", - "LOGIC_OPERATION_AND": "和", - "LOGIC_OPERATION_TOOLTIP_OR": "如果至少有一个输入结果为真,则返回真。", - "LOGIC_OPERATION_OR": "或", - "LOGIC_NEGATE_HELPURL": "https://github.com/google/blockly/wiki/Logic#not", - "LOGIC_NEGATE_TITLE": "非%1", - "LOGIC_NEGATE_TOOLTIP": "如果输入结果为假,则返回真;如果输入结果为真,则返回假。", - "LOGIC_BOOLEAN_TRUE": "真", - "LOGIC_BOOLEAN_FALSE": "假", - "LOGIC_BOOLEAN_TOOLTIP": "返回真或假。", - "LOGIC_NULL": "空", - "LOGIC_NULL_TOOLTIP": "返回空值。", - "LOGIC_TERNARY_HELPURL": "https://zh.wikipedia.org/wiki/条件运算符", - "LOGIC_TERNARY_CONDITION": "测试", - "LOGIC_TERNARY_IF_TRUE": "如果为真", - "LOGIC_TERNARY_IF_FALSE": "如果为假", - "LOGIC_TERNARY_TOOLTIP": "检查“test”中的条件。如果条件为真,则返回“if true”的值,否则,则返回“if false”的值。", - "MATH_NUMBER_HELPURL": "https://zh.wikipedia.org/wiki/数", - "MATH_NUMBER_TOOLTIP": "一个数字。", - "MATH_ARITHMETIC_HELPURL": "https://zh.wikipedia.org/wiki/算术", - "MATH_ARITHMETIC_TOOLTIP_ADD": "返回两个数字的和。", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "返回两个数字的区别。", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "返回两个数字的乘积。", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "返回两个数字的商。", - "MATH_ARITHMETIC_TOOLTIP_POWER": "返回第一个数的第二个数次幂。", - "MATH_SINGLE_HELPURL": "https://zh.wikipedia.org/wiki/平方根", - "MATH_SINGLE_OP_ROOT": "平方根", - "MATH_SINGLE_TOOLTIP_ROOT": "返回数的平方根。", - "MATH_SINGLE_OP_ABSOLUTE": "绝对", - "MATH_SINGLE_TOOLTIP_ABS": "返回一个数的绝对值。", - "MATH_SINGLE_TOOLTIP_NEG": "返回数的逻辑非。", - "MATH_SINGLE_TOOLTIP_LN": "返回一个数的自然对数。", - "MATH_SINGLE_TOOLTIP_LOG10": "返回数字的对数。", - "MATH_SINGLE_TOOLTIP_EXP": "返回数的e次幂。", - "MATH_SINGLE_TOOLTIP_POW10": "返回数的10次幂。", - "MATH_TRIG_HELPURL": "https://zh.wikipedia.org/wiki/三角函数", - "MATH_TRIG_TOOLTIP_SIN": "返回指定角度的正弦值(非弧度)。", - "MATH_TRIG_TOOLTIP_COS": "返回指定角度的余弦值(非弧度)。", - "MATH_TRIG_TOOLTIP_TAN": "返回指定角度的正切值(非弧度)。", - "MATH_TRIG_TOOLTIP_ASIN": "返回一个数的反正弦值。", - "MATH_TRIG_TOOLTIP_ACOS": "返回一个数的反余弦值。", - "MATH_TRIG_TOOLTIP_ATAN": "返回指定角度的反正切值。", - "MATH_CONSTANT_HELPURL": "https://zh.wikipedia.org/wiki/数学常数", - "MATH_CONSTANT_TOOLTIP": "返回一个常见常量:π (3.141......),e (2.718...)、φ (1.618...)、 sqrt(2) (1.414......)、sqrt(½) (0.707......)或 ∞(无穷大)。", - "MATH_IS_EVEN": "是偶数", - "MATH_IS_ODD": "是奇数", - "MATH_IS_PRIME": "是质数", - "MATH_IS_WHOLE": "为整数", - "MATH_IS_POSITIVE": "为正", - "MATH_IS_NEGATIVE": "为负", - "MATH_IS_DIVISIBLE_BY": "可被整除", - "MATH_IS_TOOLTIP": "如果数字是偶数、奇数、非负整数、正数、负数或如果它可被某数字整除,则返回真或假。", - "MATH_CHANGE_HELPURL": "https://zh.wikipedia.org/wiki/%E5%8A%A0%E6%B3%95", - "MATH_CHANGE_TITLE": "更改 %1 由 %2", - "MATH_CHANGE_TOOLTIP": "将一个数添加到变量“%1”。", - "MATH_ROUND_HELPURL": "https://zh.wikipedia.org/wiki/数值修约", - "MATH_ROUND_TOOLTIP": "数字向上或向下舍入。", - "MATH_ROUND_OPERATOR_ROUND": "向下舍入", - "MATH_ROUND_OPERATOR_ROUNDUP": "向上舍入", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "向下舍入", - "MATH_ONLIST_OPERATOR_SUM": "列表中的数的总和", - "MATH_ONLIST_TOOLTIP_SUM": "返回列表中的所有数字的和。", - "MATH_ONLIST_OPERATOR_MIN": "列表中的最小值", - "MATH_ONLIST_TOOLTIP_MIN": "返回列表中最小数。", - "MATH_ONLIST_OPERATOR_MAX": "列表中的最大值", - "MATH_ONLIST_TOOLTIP_MAX": "返回列表中最大数。", - "MATH_ONLIST_OPERATOR_AVERAGE": "列表中的平均数", - "MATH_ONLIST_TOOLTIP_AVERAGE": "返回列表中的数值的平均值。", - "MATH_ONLIST_OPERATOR_MEDIAN": "列表中位数", - "MATH_ONLIST_TOOLTIP_MEDIAN": "返回列表中的中位数。", - "MATH_ONLIST_OPERATOR_MODE": "列表模式", - "MATH_ONLIST_TOOLTIP_MODE": "返回列表中的最常见的项的列表。", - "MATH_ONLIST_OPERATOR_STD_DEV": "列表中的标准差", - "MATH_ONLIST_TOOLTIP_STD_DEV": "返回列表的标准偏差。", - "MATH_ONLIST_OPERATOR_RANDOM": "列表的随机项", - "MATH_ONLIST_TOOLTIP_RANDOM": "从列表中返回一个随机的元素。", - "MATH_MODULO_HELPURL": "https://zh.wikipedia.org/wiki/模除", - "MATH_MODULO_TITLE": "取余数自 %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "返回这两个数字相除后的余数。", - "MATH_CONSTRAIN_TITLE": "限制数字 %1 介于 (低) %2 到 (高) %3", - "MATH_CONSTRAIN_TOOLTIP": "限制数字介于两个指定的数字之间", - "MATH_RANDOM_INT_HELPURL": "https://zh.wikipedia.org/wiki/随机数生成器", - "MATH_RANDOM_INT_TITLE": "从 %1 到 %2 之间的随机整数", - "MATH_RANDOM_INT_TOOLTIP": "返回两个指定的范围(含)之间的随机整数。", - "MATH_RANDOM_FLOAT_HELPURL": "https://zh.wikipedia.org/wiki/随机数生成器", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "随机分数", - "MATH_RANDOM_FLOAT_TOOLTIP": "返回介于(包含)0.0到1.0之间的随机数。", - "TEXT_TEXT_HELPURL": "https://zh.wikipedia.org/wiki/字符串", - "TEXT_TEXT_TOOLTIP": "一个字母、单词或一行文本。", - "TEXT_JOIN_TITLE_CREATEWITH": "建立字串使用", - "TEXT_JOIN_TOOLTIP": "通过串起任意数量的项以建立一段文字。", - "TEXT_CREATE_JOIN_TITLE_JOIN": "加入", - "TEXT_CREATE_JOIN_TOOLTIP": "添加、移除或重新排列各节来重新配置这个文本块。", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "将一个项添加到文本中。", - "TEXT_APPEND_TO": "在", - "TEXT_APPEND_APPENDTEXT": "追加文本", - "TEXT_APPEND_TOOLTIP": "将一些文本追加到变量“%1”。", - "TEXT_LENGTH_TITLE": "%1的长度", - "TEXT_LENGTH_TOOLTIP": "返回提供文本的字母数(包括空格)。", - "TEXT_ISEMPTY_TITLE": "%1是空的", - "TEXT_ISEMPTY_TOOLTIP": "如果提供的文本为空,则返回真。", - "TEXT_INDEXOF_TOOLTIP": "返回在第二个字串中的第一/最后一个匹配项的索引值。如果未找到则返回%1。", - "TEXT_INDEXOF_INPUT_INTEXT": "自文本", - "TEXT_INDEXOF_OPERATOR_FIRST": "寻找第一个出现的文本", - "TEXT_INDEXOF_OPERATOR_LAST": "寻找最后一个出现的文本", - "TEXT_INDEXOF_TAIL": "空白", - "TEXT_CHARAT_INPUT_INTEXT": "于文本中", - "TEXT_CHARAT_FROM_START": "获得字符#", - "TEXT_CHARAT_FROM_END": "获得倒数第#个字符", - "TEXT_CHARAT_FIRST": "获得第一个字符", - "TEXT_CHARAT_LAST": "获得最后一个字符", - "TEXT_CHARAT_RANDOM": "获取随机的字母", - "TEXT_CHARAT_TAIL": "空白", - "TEXT_CHARAT_TOOLTIP": "返回位于指定位置的字母。", - "TEXT_GET_SUBSTRING_TOOLTIP": "返回指定的部分文本。", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "自文本", - "TEXT_GET_SUBSTRING_START_FROM_START": "取得一段字串自#", - "TEXT_GET_SUBSTRING_START_FROM_END": "取得一段字串自倒数第#个字符", - "TEXT_GET_SUBSTRING_START_FIRST": "取得一段字串自第一个字符", - "TEXT_GET_SUBSTRING_END_FROM_START": "到字符#", - "TEXT_GET_SUBSTRING_END_FROM_END": "到倒数第#个字符", - "TEXT_GET_SUBSTRING_END_LAST": "到最后一个字符", - "TEXT_GET_SUBSTRING_TAIL": "空白", - "TEXT_CHANGECASE_TOOLTIP": "使用不同的大小写复制这段文字。", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "为大写", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "为小写", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "为首字母大写", - "TEXT_TRIM_TOOLTIP": "复制这段文字的同时删除两端多余的空格。", - "TEXT_TRIM_OPERATOR_BOTH": "消除两侧空格", - "TEXT_TRIM_OPERATOR_LEFT": "消除左侧空格", - "TEXT_TRIM_OPERATOR_RIGHT": "消除右侧空格", - "TEXT_PRINT_TITLE": "打印%1", - "TEXT_PRINT_TOOLTIP": "打印指定的文字、数字或其他值。", - "TEXT_PROMPT_TYPE_TEXT": "输入数字并显示提示消息", - "TEXT_PROMPT_TYPE_NUMBER": "输入数字并显示提示消息", - "TEXT_PROMPT_TOOLTIP_NUMBER": "提示用户输入数字。", - "TEXT_PROMPT_TOOLTIP_TEXT": "提示用户输入一些文本。", - "LISTS_CREATE_EMPTY_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-empty-list", - "LISTS_CREATE_EMPTY_TITLE": "创建空列表", - "LISTS_CREATE_EMPTY_TOOLTIP": "返回一个列表,长度为 0,不包含任何数据记录", - "LISTS_CREATE_WITH_HELPURL": "https://github.com/google/blockly/wiki/Lists#create-list-with", - "LISTS_CREATE_WITH_TOOLTIP": "建立一个具有任意数量项目的列表。", - "LISTS_CREATE_WITH_INPUT_WITH": "建立字串使用", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "列表", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "增加、删除或重新排列各部分以此重新配置这个列表块。", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "将一个项添加到列表中。", - "LISTS_REPEAT_TOOLTIP": "建立包含指定重复次数的值的列表。", - "LISTS_REPEAT_TITLE": "建立列表使用项 %1 重复 %2 次", - "LISTS_LENGTH_TITLE": "%1的长度", - "LISTS_LENGTH_TOOLTIP": "返回列表的长度。", - "LISTS_ISEMPTY_TITLE": "%1是空的", - "LISTS_ISEMPTY_TOOLTIP": "如果改列表为空,则返回真。", - "LISTS_INLIST": "在列表中", - "LISTS_INDEX_OF_FIRST": "找出第一个项出现", - "LISTS_INDEX_OF_LAST": "找出最后一个项出现", - "LISTS_INDEX_OF_TOOLTIP": "返回在列表中的第一/最后一个匹配项的索引值。如果找不到项目则返回%1。", - "LISTS_GET_INDEX_GET": "获得", - "LISTS_GET_INDEX_GET_REMOVE": "取出并移除", - "LISTS_GET_INDEX_REMOVE": "移除", - "LISTS_GET_INDEX_FROM_START": "#", - "LISTS_GET_INDEX_FROM_END": "倒数第#", - "LISTS_GET_INDEX_FIRST": "第一", - "LISTS_GET_INDEX_LAST": "最后", - "LISTS_GET_INDEX_RANDOM": "随机", - "LISTS_GET_INDEX_TAIL": "空白", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1是第一个项目。", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1是最后一项。", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "返回在列表中的指定位置的项。", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "返回列表中的第一个项目。", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "返回列表中的最后一项。", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "随机返回列表中的一个项目。", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "移除并返回列表中的指定位置的项。", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "移除并返回列表中的第一个项目。", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "移除并返回列表中的最后一个项目。", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "移除并返回列表中的一个随机项目中。", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "移除在列表中的指定位置的项。", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "移除列表中的第一项", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "移除列表中的最后一项", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "删除列表中的一个随机的项。", - "LISTS_SET_INDEX_SET": "设置", - "LISTS_SET_INDEX_INSERT": "插入在", - "LISTS_SET_INDEX_INPUT_TO": "为", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "设置在列表中指定位置的项。", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "设置列表中的第一个项目。", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "设置列表中的最后一项。", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "设置列表中一个随机的项目。", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "插入在列表中指定位置的项。", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "在列表的起始处添加该项。", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "将该项追加到列表的末尾。", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "在列表中随机插入项。", - "LISTS_GET_SUBLIST_START_FROM_START": "从#取得子列表", - "LISTS_GET_SUBLIST_START_FROM_END": "从倒数#取得子列表", - "LISTS_GET_SUBLIST_START_FIRST": "从头获得子列表", - "LISTS_GET_SUBLIST_END_FROM_START": "到#", - "LISTS_GET_SUBLIST_END_FROM_END": "到倒数第#", - "LISTS_GET_SUBLIST_END_LAST": "到最后", - "LISTS_GET_SUBLIST_TAIL": "空白", - "LISTS_GET_SUBLIST_TOOLTIP": "复制列表中指定的部分。", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "排序%1 %2 %3", - "LISTS_SORT_TOOLTIP": "排序一个列表的拷贝。", - "LISTS_SORT_ORDER_ASCENDING": "升序", - "LISTS_SORT_ORDER_DESCENDING": "降序", - "LISTS_SORT_TYPE_NUMERIC": "按数字排序", - "LISTS_SORT_TYPE_TEXT": "按字母排序", - "LISTS_SORT_TYPE_IGNORECASE": "按字母排序,忽略大小写", - "LISTS_SPLIT_HELPURL": "https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists", - "LISTS_SPLIT_LIST_FROM_TEXT": "从文本制作列表", - "LISTS_SPLIT_TEXT_FROM_LIST": "从列表拆出文本", - "LISTS_SPLIT_WITH_DELIMITER": "用分隔符", - "LISTS_SPLIT_TOOLTIP_SPLIT": "拆分文本到文本列表,按每个分隔符拆分。", - "LISTS_SPLIT_TOOLTIP_JOIN": "加入文本列表至一个文本,由分隔符分隔。", - "ORDINAL_NUMBER_SUFFIX": "空白", - "VARIABLES_GET_TOOLTIP": "返回此变量的值。", - "VARIABLES_GET_CREATE_SET": "创建“设定%1”", - "VARIABLES_SET": "赋值 %1 到 %2", - "VARIABLES_SET_TOOLTIP": "设置此变量,以使它和输入值相等。", - "VARIABLES_SET_CREATE_GET": "创建“获得%1”", - "PROCEDURES_DEFNORETURN_HELPURL": "https://zh.wikipedia.org/wiki/子程序", - "PROCEDURES_DEFNORETURN_TITLE": "至", - "PROCEDURES_DEFNORETURN_PROCEDURE": "做点什么", - "PROCEDURES_BEFORE_PARAMS": "与:", - "PROCEDURES_CALL_BEFORE_PARAMS": "与:", - "PROCEDURES_DEFNORETURN_DO": "空白", - "PROCEDURES_DEFNORETURN_TOOLTIP": "创建一个不带输出值的函数。", - "PROCEDURES_DEFNORETURN_COMMENT": "描述该功能...", - "PROCEDURES_DEFRETURN_HELPURL": "https://zh.wikipedia.org/wiki/子程序", - "PROCEDURES_DEFRETURN_RETURN": "返回", - "PROCEDURES_DEFRETURN_TOOLTIP": "创建一个有输出值的函数。", - "PROCEDURES_ALLOW_STATEMENTS": "允许声明", - "PROCEDURES_DEF_DUPLICATE_WARNING": "警告: 此函数具有重复参数。", - "PROCEDURES_CALLNORETURN_HELPURL": "https://zh.wikipedia.org/wiki/子程序", - "PROCEDURES_CALLNORETURN_TOOLTIP": "运行用户定义的函数“%1”。", - "PROCEDURES_CALLRETURN_HELPURL": "https://zh.wikipedia.org/wiki/子程序", - "PROCEDURES_CALLRETURN_TOOLTIP": "运行用户定义的函数“%1”,并使用它的输出值。", - "PROCEDURES_MUTATORCONTAINER_TITLE": "输入", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "添加、删除或重新排此函数的输入。", - "PROCEDURES_MUTATORARG_TITLE": "输入名称:", - "PROCEDURES_MUTATORARG_TOOLTIP": "添加函数输入。", - "PROCEDURES_HIGHLIGHT_DEF": "突出显示函数定义", - "PROCEDURES_CREATE_DO": "创建“%1”", - "PROCEDURES_IFRETURN_TOOLTIP": "如果值为真,则返回第二个值。", - "PROCEDURES_IFRETURN_HELPURL": "http://c2.com/cgi/wiki?GuardClause", - "PROCEDURES_IFRETURN_WARNING": "警告: 仅在定义函数内可使用此块。" -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/json/zh-hant.json b/backend/_pv_1_3_5/static/blockly/msg/json/zh-hant.json deleted file mode 100755 index 3931ca812..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/json/zh-hant.json +++ /dev/null @@ -1,319 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Gasolin", - "Wehwei", - "Liuxinyu970226", - "LNDDYL", - "Cwlin0416", - "Kasimtan", - "Kly" - ] - }, - "VARIABLES_DEFAULT_NAME": "變數", - "TODAY": "今天", - "DUPLICATE_BLOCK": "複製", - "ADD_COMMENT": "加入註解", - "REMOVE_COMMENT": "移除註解", - "EXTERNAL_INPUTS": "多行輸入", - "INLINE_INPUTS": "單行輸入", - "DELETE_BLOCK": "刪除積木", - "DELETE_X_BLOCKS": "刪除 %1 塊積木", - "DELETE_ALL_BLOCKS": "刪除共 %1 塊積木?", - "CLEAN_UP": "清理積木", - "COLLAPSE_BLOCK": "收合積木", - "COLLAPSE_ALL": "收合積木", - "EXPAND_BLOCK": "展開積木", - "EXPAND_ALL": "展開積木", - "DISABLE_BLOCK": "停用積木", - "ENABLE_BLOCK": "啟用積木", - "HELP": "說明", - "UNDO": "還原", - "REDO": "重試", - "CHANGE_VALUE_TITLE": "修改值:", - "RENAME_VARIABLE": "重新命名變數...", - "RENAME_VARIABLE_TITLE": "將所有 \"%1\" 變數重新命名為:", - "NEW_VARIABLE": "建立變數...", - "NEW_VARIABLE_TITLE": "新變數名稱:", - "VARIABLE_ALREADY_EXISTS": "一個名為%1的變數已存在。", - "DELETE_VARIABLE_CONFIRMATION": "刪除%1使用的%2變數?", - "DELETE_VARIABLE": "刪除%1變數", - "COLOUR_PICKER_HELPURL": "https://zh.wikipedia.org/wiki/顏色", - "COLOUR_PICKER_TOOLTIP": "從調色板中選擇一種顏色。", - "COLOUR_RANDOM_TITLE": "隨機顏色", - "COLOUR_RANDOM_TOOLTIP": "隨機選擇一種顏色。", - "COLOUR_RGB_TITLE": "顏色", - "COLOUR_RGB_RED": "紅", - "COLOUR_RGB_GREEN": "綠", - "COLOUR_RGB_BLUE": "藍", - "COLOUR_RGB_TOOLTIP": "透過指定紅、綠、 藍色的值來建立一種顏色。所有的值必須介於 0 和 100 之間。", - "COLOUR_BLEND_TITLE": "混合", - "COLOUR_BLEND_COLOUR1": "顏色 1", - "COLOUR_BLEND_COLOUR2": "顏色 2", - "COLOUR_BLEND_RATIO": "比例", - "COLOUR_BLEND_TOOLTIP": "透過一個比率 (0.0-1.0)來混合兩種顏色。", - "CONTROLS_REPEAT_HELPURL": "https://zh.wikipedia.org/wiki/For迴圈", - "CONTROLS_REPEAT_TITLE": "重複 %1 次", - "CONTROLS_REPEAT_INPUT_DO": "執行", - "CONTROLS_REPEAT_TOOLTIP": "多次執行一些語句", - "CONTROLS_WHILEUNTIL_OPERATOR_WHILE": "重複 當", - "CONTROLS_WHILEUNTIL_OPERATOR_UNTIL": "重複 直到", - "CONTROLS_WHILEUNTIL_TOOLTIP_WHILE": "當值為真時,執行一些語句", - "CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL": "當值為否時,執行一些語句", - "CONTROLS_FOR_TOOLTIP": "從起始數到結尾數中取出變數 \"%1\" 的值,按指定的時間間隔,執行指定的積木。", - "CONTROLS_FOR_TITLE": "使用 %1 從範圍 %2 到 %3 每隔 %4", - "CONTROLS_FOREACH_TITLE": "取出每個 %1 自列表 %2", - "CONTROLS_FOREACH_TOOLTIP": "遍歷每個列表中的項目,將變數 '%1' 設定到該項目中,然後執行某些語句", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK": "停止 迴圈", - "CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE": "繼續下一個 迴圈", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK": "離開當前的 迴圈", - "CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE": "跳過這個迴圈的其餘步驟,並繼續下一次的迴圈運算。", - "CONTROLS_FLOW_STATEMENTS_WARNING": "警告: 此積木僅可用於迴圈內。", - "CONTROLS_IF_TOOLTIP_1": "當值為真時,執行一些語句", - "CONTROLS_IF_TOOLTIP_2": "當值為真時,執行第一個語句,否則則執行第二個語句", - "CONTROLS_IF_TOOLTIP_3": "如果第一個值為真,則執行第一個語句。否則當第二個值為真時,則執行第二個語句", - "CONTROLS_IF_TOOLTIP_4": "如果第一個值為真,則執行第一個語句。否則當第二個值為真時,則執行第二個語句。如果前幾個敘述都不為真,則執行最後一個語句", - "CONTROLS_IF_MSG_IF": "如果", - "CONTROLS_IF_MSG_ELSEIF": "否則如果", - "CONTROLS_IF_MSG_ELSE": "否則", - "CONTROLS_IF_IF_TOOLTIP": "添加、 刪除或重新排列各區塊來此重新配置這個'如果'積木。", - "CONTROLS_IF_ELSEIF_TOOLTIP": "將條件添加到'如果'積木。", - "CONTROLS_IF_ELSE_TOOLTIP": "加入一個最終,所有條件下都都執行的區塊到'如果'積木中", - "LOGIC_COMPARE_HELPURL": "https://zh.wikipedia.org/wiki/不等", - "LOGIC_COMPARE_TOOLTIP_EQ": "如果這兩個輸入區塊內容相等,返回 真。", - "LOGIC_COMPARE_TOOLTIP_NEQ": "如果這兩個輸入區塊內容不相等,返回 真。", - "LOGIC_COMPARE_TOOLTIP_LT": "如果第一個輸入小於第二個輸入,返回 真。", - "LOGIC_COMPARE_TOOLTIP_LTE": "如果第一個輸入是小於或等於第二個輸入,返回 真。", - "LOGIC_COMPARE_TOOLTIP_GT": "如果第一個輸入大於第二個輸入,返回 真。", - "LOGIC_COMPARE_TOOLTIP_GTE": "如果第一個輸入大於或等於第二個輸入,返回 真。", - "LOGIC_OPERATION_TOOLTIP_AND": "如果這兩個輸入值都為 真,則返回 真。", - "LOGIC_OPERATION_AND": "且", - "LOGIC_OPERATION_TOOLTIP_OR": "如果至少一個輸入的值為 真,返回 真。", - "LOGIC_OPERATION_OR": "或", - "LOGIC_NEGATE_TITLE": "非 %1", - "LOGIC_NEGATE_TOOLTIP": "如果輸入的值是 否,則返回 真。如果輸入的值是 真 返回 否。", - "LOGIC_BOOLEAN_TRUE": "真", - "LOGIC_BOOLEAN_FALSE": "否", - "LOGIC_BOOLEAN_TOOLTIP": "返回 真 或 否。", - "LOGIC_NULL": "空", - "LOGIC_NULL_TOOLTIP": "返回 空。", - "LOGIC_TERNARY_HELPURL": "https://zh.wikipedia.org/wiki/條件運算符", - "LOGIC_TERNARY_CONDITION": "測試", - "LOGIC_TERNARY_IF_TRUE": "如果為真", - "LOGIC_TERNARY_IF_FALSE": "如果為非", - "LOGIC_TERNARY_TOOLTIP": "檢查 'test' 中的條件。如果條件為 真,將返回 '如果為 真' 值 ;否則,返回 '如果為 否' 的值。", - "MATH_NUMBER_HELPURL": "https://zh.wikipedia.org/wiki/數", - "MATH_NUMBER_TOOLTIP": "一個數字。", - "MATH_ARITHMETIC_HELPURL": "https://zh.wikipedia.org/wiki/算術", - "MATH_ARITHMETIC_TOOLTIP_ADD": "返回兩個數字的總和。", - "MATH_ARITHMETIC_TOOLTIP_MINUS": "返回兩個數字的差。", - "MATH_ARITHMETIC_TOOLTIP_MULTIPLY": "返回兩個數字的乘積。", - "MATH_ARITHMETIC_TOOLTIP_DIVIDE": "返回兩個數字的商。", - "MATH_ARITHMETIC_TOOLTIP_POWER": "返回第二個數字的指數的第一個數字。", - "MATH_SINGLE_HELPURL": "https://zh.wikipedia.org/wiki/平方根", - "MATH_SINGLE_OP_ROOT": "開根號", - "MATH_SINGLE_TOOLTIP_ROOT": "返回指定數字的平方根。", - "MATH_SINGLE_OP_ABSOLUTE": "絕對值", - "MATH_SINGLE_TOOLTIP_ABS": "返回指定數字的絕對值。", - "MATH_SINGLE_TOOLTIP_NEG": "返回指定數字的 negation。", - "MATH_SINGLE_TOOLTIP_LN": "返回指定數字的自然對數。", - "MATH_SINGLE_TOOLTIP_LOG10": "返回指定數字的對數。", - "MATH_SINGLE_TOOLTIP_EXP": "返回指定數字指數的 e", - "MATH_SINGLE_TOOLTIP_POW10": "返回指定數字指數的10的冪次。", - "MATH_TRIG_HELPURL": "https://zh.wikipedia.org/wiki/三角函數", - "MATH_TRIG_TOOLTIP_SIN": "返回指定角度的正弦值(非弧度)。", - "MATH_TRIG_TOOLTIP_COS": "返回指定角度的餘弦值(非弧度)。", - "MATH_TRIG_TOOLTIP_TAN": "返回指定角度的正切值(非弧度)。", - "MATH_TRIG_TOOLTIP_ASIN": "返回指定角度的反正弦值(非弧度)。", - "MATH_TRIG_TOOLTIP_ACOS": "返回指定角度的反餘弦值(非弧度)。", - "MATH_TRIG_TOOLTIP_ATAN": "返回指定角度的反正切值。", - "MATH_CONSTANT_HELPURL": "https://zh.wikipedia.org/wiki/數學常數", - "MATH_CONSTANT_TOOLTIP": "返回一個的常見常量: π (3.141......),e (2.718...)、 φ (1.618...)、 開方(2) (1.414......)、 開方(½) (0.707......) 或 ∞ (無窮大)。", - "MATH_IS_EVEN": "是偶數", - "MATH_IS_ODD": "是奇數", - "MATH_IS_PRIME": "是質數", - "MATH_IS_WHOLE": "是非負整數", - "MATH_IS_POSITIVE": "是正值", - "MATH_IS_NEGATIVE": "是負值", - "MATH_IS_DIVISIBLE_BY": "可被整除", - "MATH_IS_TOOLTIP": "如果數字是偶數,奇數,非負整數,正數、 負數或如果它是可被某數字整除,則返回 真 或 否。", - "MATH_CHANGE_HELPURL": "https://zh.wikipedia.org/wiki/加法", - "MATH_CHANGE_TITLE": "修改 %1 自 %2", - "MATH_CHANGE_TOOLTIP": "將數字添加到變數 '%1'。", - "MATH_ROUND_HELPURL": "https://zh.wikipedia.org/wiki/數值簡化", - "MATH_ROUND_TOOLTIP": "將數字向上或向下舍入。", - "MATH_ROUND_OPERATOR_ROUND": "四捨五入", - "MATH_ROUND_OPERATOR_ROUNDUP": "無條件進位", - "MATH_ROUND_OPERATOR_ROUNDDOWN": "無條件捨去", - "MATH_ONLIST_OPERATOR_SUM": "總和 自列表", - "MATH_ONLIST_TOOLTIP_SUM": "返回列表中的所有數字的總和。", - "MATH_ONLIST_OPERATOR_MIN": "最小值 自列表", - "MATH_ONLIST_TOOLTIP_MIN": "返回列表中的最小數字。", - "MATH_ONLIST_OPERATOR_MAX": "最大值 自列表", - "MATH_ONLIST_TOOLTIP_MAX": "返回列表中的最大數字。", - "MATH_ONLIST_OPERATOR_AVERAGE": "平均值 自列表", - "MATH_ONLIST_TOOLTIP_AVERAGE": "返回列表中數值的平均值 (算術平均值)。", - "MATH_ONLIST_OPERATOR_MEDIAN": "中位數 自列表", - "MATH_ONLIST_TOOLTIP_MEDIAN": "返回列表中數值的中位數。", - "MATH_ONLIST_OPERATOR_MODE": "比較眾數 自列表", - "MATH_ONLIST_TOOLTIP_MODE": "返回一個列表中的最常見項目的列表。", - "MATH_ONLIST_OPERATOR_STD_DEV": "標準差 自列表", - "MATH_ONLIST_TOOLTIP_STD_DEV": "返回列表中數字的標準差。", - "MATH_ONLIST_OPERATOR_RANDOM": "隨機抽取 自列表", - "MATH_ONLIST_TOOLTIP_RANDOM": "從列表中返回一個隨機的項目。", - "MATH_MODULO_HELPURL": "https://zh.wikipedia.org/wiki/模除", - "MATH_MODULO_TITLE": "取餘數自 %1 ÷ %2", - "MATH_MODULO_TOOLTIP": "回傳兩個數字相除的餘數", - "MATH_CONSTRAIN_TITLE": "限制數字 %1 介於 (低) %2 到 (高) %3", - "MATH_CONSTRAIN_TOOLTIP": "限制數字介於兩個指定的數字之間", - "MATH_RANDOM_INT_HELPURL": "https://zh.wikipedia.org/wiki/隨機數生成器", - "MATH_RANDOM_INT_TITLE": "取隨機整數介於 (低) %1 到 %2", - "MATH_RANDOM_INT_TOOLTIP": "回傳限制的數字區間內的隨機數字", - "MATH_RANDOM_FLOAT_HELPURL": "https://zh.wikipedia.org/wiki/隨機數生成器", - "MATH_RANDOM_FLOAT_TITLE_RANDOM": "取隨機分數", - "MATH_RANDOM_FLOAT_TOOLTIP": "返回介於 (包含) 0.0 到 1.0 之間的隨機數。", - "TEXT_TEXT_HELPURL": "https://zh.wikipedia.org/wiki/字串", - "TEXT_TEXT_TOOLTIP": "字元、 單詞或一行文字。", - "TEXT_JOIN_TITLE_CREATEWITH": "建立字串使用", - "TEXT_JOIN_TOOLTIP": "通過串起任意數量的項目來建立一段文字。", - "TEXT_CREATE_JOIN_TITLE_JOIN": "加入", - "TEXT_CREATE_JOIN_TOOLTIP": "添加、 刪除或重新排列各區塊來此重新配置這個文字積木。", - "TEXT_CREATE_JOIN_ITEM_TOOLTIP": "將一個項目加入到字串中。", - "TEXT_APPEND_TO": "在", - "TEXT_APPEND_APPENDTEXT": "後加入文字", - "TEXT_APPEND_TOOLTIP": "將一些文字追加到變數 '%1'。", - "TEXT_LENGTH_TITLE": "長度 %1", - "TEXT_LENGTH_TOOLTIP": "返回這串文字的字元數(含空格) 。", - "TEXT_ISEMPTY_TITLE": "%1 為空", - "TEXT_ISEMPTY_TOOLTIP": "如果提供的字串為空,則返回 真。", - "TEXT_INDEXOF_TOOLTIP": "返回在第二個字串中的第一個/最後一個匹配項目的索引值。如果未找到則返回 %1。", - "TEXT_INDEXOF_INPUT_INTEXT": "在字串", - "TEXT_INDEXOF_OPERATOR_FIRST": "尋找 第一個 出現的字串", - "TEXT_INDEXOF_OPERATOR_LAST": "尋找 最後一個 出現的字串", - "TEXT_CHARAT_INPUT_INTEXT": "的字元在字串", - "TEXT_CHARAT_FROM_START": "取得 字元 #", - "TEXT_CHARAT_FROM_END": "取得 倒數第 # 個字元", - "TEXT_CHARAT_FIRST": "取第一個字元", - "TEXT_CHARAT_LAST": "取最後一個字元", - "TEXT_CHARAT_RANDOM": "取隨機一個字元", - "TEXT_CHARAT_TAIL": "", - "TEXT_CHARAT_TOOLTIP": "返回位於指定位置的字元。", - "TEXT_GET_SUBSTRING_TOOLTIP": "返回指定的部分文字。", - "TEXT_GET_SUBSTRING_INPUT_IN_TEXT": "自字串", - "TEXT_GET_SUBSTRING_START_FROM_START": "取得一段字串自 #", - "TEXT_GET_SUBSTRING_START_FROM_END": "取得一段字串自 #", - "TEXT_GET_SUBSTRING_START_FIRST": "取得一段字串 自 第一個字元", - "TEXT_GET_SUBSTRING_END_FROM_START": "到 字元 #", - "TEXT_GET_SUBSTRING_END_FROM_END": "到 倒數第 # 個字元", - "TEXT_GET_SUBSTRING_END_LAST": "到 最後一個字元", - "TEXT_CHANGECASE_TOOLTIP": "使用不同的大小寫複製這段文字。", - "TEXT_CHANGECASE_OPERATOR_UPPERCASE": "轉成 大寫", - "TEXT_CHANGECASE_OPERATOR_LOWERCASE": "轉成 小寫", - "TEXT_CHANGECASE_OPERATOR_TITLECASE": "轉成 首字母大寫", - "TEXT_TRIM_TOOLTIP": "複製這段文字的同時刪除兩端多餘的空格。", - "TEXT_TRIM_OPERATOR_BOTH": "消除兩側空格", - "TEXT_TRIM_OPERATOR_LEFT": "消除左側空格", - "TEXT_TRIM_OPERATOR_RIGHT": "消除右側空格", - "TEXT_PRINT_TITLE": "印出 %1", - "TEXT_PRINT_TOOLTIP": "印出指定的文字、 數字或其他值。", - "TEXT_PROMPT_TYPE_TEXT": "輸入 文字 並顯示提示訊息", - "TEXT_PROMPT_TYPE_NUMBER": "輸入 數字 並顯示提示訊息", - "TEXT_PROMPT_TOOLTIP_NUMBER": "輸入數字", - "TEXT_PROMPT_TOOLTIP_TEXT": "輸入文字", - "LISTS_CREATE_EMPTY_TITLE": "建立空列表", - "LISTS_CREATE_EMPTY_TOOLTIP": "返回一個長度為 0 的列表,不包含任何資料記錄", - "LISTS_CREATE_WITH_TOOLTIP": "建立一個具備任意數量項目的列表。", - "LISTS_CREATE_WITH_INPUT_WITH": "使用這些值建立列表", - "LISTS_CREATE_WITH_CONTAINER_TITLE_ADD": "列表", - "LISTS_CREATE_WITH_CONTAINER_TOOLTIP": "添加、 刪除或重新排列各區塊來此重新配置這個 列表 積木。", - "LISTS_CREATE_WITH_ITEM_TOOLTIP": "將一個項目加入到列表中。", - "LISTS_REPEAT_TOOLTIP": "建立包含指定重複次數的 值 的列表。", - "LISTS_REPEAT_TITLE": "建立列表使用項目 %1 重複 %2 次數", - "LISTS_LENGTH_TITLE": "長度 %1", - "LISTS_LENGTH_TOOLTIP": "返回列表的長度。", - "LISTS_ISEMPTY_TITLE": "%1 值為空", - "LISTS_ISEMPTY_TOOLTIP": "如果該列表為空,則返回 真。", - "LISTS_INLIST": "自列表", - "LISTS_INDEX_OF_FIRST": "找出 第一個 項目出現", - "LISTS_INDEX_OF_LAST": "找出 最後一個 項目出現", - "LISTS_INDEX_OF_TOOLTIP": "返回在列表中的第一個/最後一個匹配項目的索引值。如果未找到則返回 %1。", - "LISTS_GET_INDEX_GET": "取值", - "LISTS_GET_INDEX_GET_REMOVE": "取出並移除", - "LISTS_GET_INDEX_REMOVE": "移除", - "LISTS_GET_INDEX_FROM_END": "倒數第#筆", - "LISTS_GET_INDEX_FIRST": "第一筆", - "LISTS_GET_INDEX_LAST": "最後一筆", - "LISTS_GET_INDEX_RANDOM": "隨機", - "LISTS_INDEX_FROM_START_TOOLTIP": "%1 是第一個項目。", - "LISTS_INDEX_FROM_END_TOOLTIP": "%1 是最後一個項目。", - "LISTS_GET_INDEX_TOOLTIP_GET_FROM": "返回在列表中的指定位置的項目。", - "LISTS_GET_INDEX_TOOLTIP_GET_FIRST": "返回列表中的第一個項目", - "LISTS_GET_INDEX_TOOLTIP_GET_LAST": "返回列表中的最後一個項目", - "LISTS_GET_INDEX_TOOLTIP_GET_RANDOM": "返回列表中隨機的一個項目", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM": "移除並返回列表中的指定位置的項目。", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST": "移除並返回列表中的第一個項目", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST": "移除並返回列表中的最後一個項目", - "LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM": "移除並返回列表中的隨機一個項目", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM": "移除在列表中的指定位置的項目。", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST": "移除列表中的第一個項目", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST": "移除列表中的最後一個項目", - "LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM": "移除列表中隨機的一個項目", - "LISTS_SET_INDEX_SET": "設定", - "LISTS_SET_INDEX_INSERT": "插入在", - "LISTS_SET_INDEX_INPUT_TO": "為", - "LISTS_SET_INDEX_TOOLTIP_SET_FROM": "設定在列表中的指定位置的項目。", - "LISTS_SET_INDEX_TOOLTIP_SET_FIRST": "設定列表中的第一個項目", - "LISTS_SET_INDEX_TOOLTIP_SET_LAST": "設定列表中的最後一個項目", - "LISTS_SET_INDEX_TOOLTIP_SET_RANDOM": "設定列表中隨機的一個項目", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FROM": "插入在列表中的指定位置的項目。", - "LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST": "在列表的起始處添加一個項目", - "LISTS_SET_INDEX_TOOLTIP_INSERT_LAST": "在列表的尾端加入一個項目", - "LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM": "在列表中隨機插入項目", - "LISTS_GET_SUBLIST_START_FROM_START": "從 # 取得子列表", - "LISTS_GET_SUBLIST_START_FROM_END": "從倒數 # 取得子列表", - "LISTS_GET_SUBLIST_START_FIRST": "從 頭 取得子列表", - "LISTS_GET_SUBLIST_END_FROM_START": "到 #", - "LISTS_GET_SUBLIST_END_FROM_END": "到 倒數 # 位", - "LISTS_GET_SUBLIST_END_LAST": "到 最後", - "LISTS_GET_SUBLIST_TOOLTIP": "複製列表中指定的部分。", - "LISTS_SORT_HELPURL": "https://github.com/google/blockly/wiki/Lists#sorting-a-list", - "LISTS_SORT_TITLE": "依%1%2%3排序", - "LISTS_SORT_TOOLTIP": "排序清單的複製內容", - "LISTS_SORT_ORDER_ASCENDING": "升冪排序", - "LISTS_SORT_ORDER_DESCENDING": "降冪排序", - "LISTS_SORT_TYPE_NUMERIC": "依數字排序", - "LISTS_SORT_TYPE_TEXT": "依字母排序", - "LISTS_SORT_TYPE_IGNORECASE": "依字母排序並忽略大小寫", - "LISTS_SPLIT_LIST_FROM_TEXT": "從文本製作列表", - "LISTS_SPLIT_TEXT_FROM_LIST": "從列表拆出文本", - "LISTS_SPLIT_WITH_DELIMITER": "用分隔符", - "LISTS_SPLIT_TOOLTIP_SPLIT": "拆分文本到文本列表,按每個分隔符拆分。", - "LISTS_SPLIT_TOOLTIP_JOIN": "串起文本列表成一個文本,由分隔符分隔。", - "VARIABLES_GET_TOOLTIP": "返回此變數的值。", - "VARIABLES_GET_CREATE_SET": "建立 '設定 %1'", - "VARIABLES_SET": "賦值 %1 到 %2", - "VARIABLES_SET_TOOLTIP": "設定此變數,好和輸入值相等。", - "VARIABLES_SET_CREATE_GET": "建立 '取得 %1'", - "PROCEDURES_DEFNORETURN_TITLE": "到", - "PROCEDURES_DEFNORETURN_PROCEDURE": "流程", - "PROCEDURES_BEFORE_PARAMS": "與:", - "PROCEDURES_CALL_BEFORE_PARAMS": "與:", - "PROCEDURES_DEFNORETURN_TOOLTIP": "創建一個無回傳值的函數。", - "PROCEDURES_DEFNORETURN_COMMENT": "描述此函數...", - "PROCEDURES_DEFRETURN_RETURN": "回傳", - "PROCEDURES_DEFRETURN_TOOLTIP": "創建一個有回傳值的函數。", - "PROCEDURES_ALLOW_STATEMENTS": "允許語句", - "PROCEDURES_DEF_DUPLICATE_WARNING": "警告: 此函數中有重複的參數。", - "PROCEDURES_CALLNORETURN_HELPURL": "https://zh.wikipedia.org/wiki/子程式", - "PROCEDURES_CALLNORETURN_TOOLTIP": "執行使用者定義的函數 '%1'。", - "PROCEDURES_CALLRETURN_HELPURL": "https://zh.wikipedia.org/wiki/子程式", - "PROCEDURES_CALLRETURN_TOOLTIP": "執行使用者定義的函數 '%1' 並使用它的回傳值", - "PROCEDURES_MUTATORCONTAINER_TITLE": "參數", - "PROCEDURES_MUTATORCONTAINER_TOOLTIP": "添加、刪除或重新排列此函數的輸入。", - "PROCEDURES_MUTATORARG_TITLE": "變數:", - "PROCEDURES_MUTATORARG_TOOLTIP": "添加函數輸入。", - "PROCEDURES_HIGHLIGHT_DEF": "反白顯示函式定義", - "PROCEDURES_CREATE_DO": "建立 '%1'", - "PROCEDURES_IFRETURN_TOOLTIP": "如果值為 真,則返回第二個值。", - "PROCEDURES_IFRETURN_WARNING": "警告: 此積木僅可在定義函式時使用。" -} diff --git a/backend/_pv_1_3_5/static/blockly/msg/messages.js b/backend/_pv_1_3_5/static/blockly/msg/messages.js deleted file mode 100755 index f4b05591c..000000000 --- a/backend/_pv_1_3_5/static/blockly/msg/messages.js +++ /dev/null @@ -1,1113 +0,0 @@ -/** - * @license - * Visual Blocks Language - * - * Copyright 2012 Google Inc. - * https://developers.google.com/blockly/ - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @fileoverview English strings. - * @author fraser@google.com (Neil Fraser) - * - * After modifying this file, either run "build.py" from the parent directory, - * or run (from this directory): - * ../i18n/js_to_json.py - * to regenerate json/{en,qqq,synonyms}.json. - * - * To convert all of the json files to .js files, run: - * ../i18n/create_messages.py json/*.json - */ -'use strict'; - -goog.provide('Blockly.Msg.en'); - -goog.require('Blockly.Msg'); - - -/** - * Due to the frequency of long strings, the 80-column wrap rule need not apply - * to message files. - */ - -/** - * Each message is preceded with a tripple-slash comment that becomes the - * message descriptor. The build process extracts these descriptors, adds - * them to msg/json/qqq.json, and they show up in the translation console. - */ - -/// default name - A simple, general default name for a variable, preferably short. -/// For more context, see -/// [[Translating:Blockly#infrequent_message_types]].\n{{Identical|Item}} -Blockly.Msg.VARIABLES_DEFAULT_NAME = 'item'; -/// button text - Button that sets a calendar to today's date.\n{{Identical|Today}} -Blockly.Msg.TODAY = 'Today'; - -// Context menus. -/// context menu - Make a copy of the selected block (and any blocks it contains).\n{{Identical|Duplicate}} -Blockly.Msg.DUPLICATE_BLOCK = 'Duplicate'; -/// context menu - Add a descriptive comment to the selected block. -Blockly.Msg.ADD_COMMENT = 'Add Comment'; -/// context menu - Remove the descriptive comment from the selected block. -Blockly.Msg.REMOVE_COMMENT = 'Remove Comment'; -/// context menu - Change from 'external' to 'inline' mode for displaying blocks used as inputs to the selected block. See [[Translating:Blockly#context_menus]]. -Blockly.Msg.EXTERNAL_INPUTS = 'External Inputs'; -/// context menu - Change from 'internal' to 'external' mode for displaying blocks used as inputs to the selected block. See [[Translating:Blockly#context_menus]]. -Blockly.Msg.INLINE_INPUTS = 'Inline Inputs'; -/// context menu - Permanently delete the selected block. -Blockly.Msg.DELETE_BLOCK = 'Delete Block'; -/// context menu - Permanently delete the %1 selected blocks.\n\nParameters:\n* %1 - an integer greater than 1. -Blockly.Msg.DELETE_X_BLOCKS = 'Delete %1 Blocks'; -/// confirmation prompt - Question the user if they really wanted to permanently delete all %1 blocks.\n\nParameters:\n* %1 - an integer greater than 1. -Blockly.Msg.DELETE_ALL_BLOCKS = 'Delete all %1 blocks?'; -/// context menu - Reposition all the blocks so that they form a neat line. -Blockly.Msg.CLEAN_UP = 'Clean up Blocks'; -/// context menu - Make the appearance of the selected block smaller by hiding some information about it. -Blockly.Msg.COLLAPSE_BLOCK = 'Collapse Block'; -/// context menu - Make the appearance of all blocks smaller by hiding some information about it. Use the same terminology as in the previous message. -Blockly.Msg.COLLAPSE_ALL = 'Collapse Blocks'; -/// context menu - Restore the appearance of the selected block by showing information about it that was hidden (collapsed) earlier. -Blockly.Msg.EXPAND_BLOCK = 'Expand Block'; -/// context menu - Restore the appearance of all blocks by showing information about it that was hidden (collapsed) earlier. Use the same terminology as in the previous message. -Blockly.Msg.EXPAND_ALL = 'Expand Blocks'; -/// context menu - Make the selected block have no effect (unless reenabled). -Blockly.Msg.DISABLE_BLOCK = 'Disable Block'; -/// context menu - Make the selected block have effect (after having been disabled earlier). -Blockly.Msg.ENABLE_BLOCK = 'Enable Block'; -/// context menu - Provide helpful information about the selected block.\n{{Identical|Help}} -Blockly.Msg.HELP = 'Help'; -/// context menu - Undo the previous action.\n{{Identical|Undo}} -Blockly.Msg.UNDO = 'Undo'; -/// context menu - Undo the previous undo action.\n{{Identical|Redo}} -Blockly.Msg.REDO = 'Redo'; - -// Variable renaming. -/// prompt - This message is only seen in the Opera browser. With most browsers, users can edit numeric values in blocks by just clicking and typing. Opera does not allows this, so we have to open a new window and prompt users with this message to chanage a value. -Blockly.Msg.CHANGE_VALUE_TITLE = 'Change value:'; -/// dropdown choice - When the user clicks on a variable block, this is one of the dropdown menu choices. It is used to rename the current variable. See [https://github.com/google/blockly/wiki/Variables#dropdown-menu https://github.com/google/blockly/wiki/Variables#dropdown-menu]. -Blockly.Msg.RENAME_VARIABLE = 'Rename variable...'; -/// prompt - Prompts the user to enter the new name for the selected variable. See [https://github.com/google/blockly/wiki/Variables#dropdown-menu https://github.com/google/blockly/wiki/Variables#dropdown-menu].\n\nParameters:\n* %1 - the name of the variable to be renamed. -Blockly.Msg.RENAME_VARIABLE_TITLE = 'Rename all "%1" variables to:'; - -// Variable creation -/// button text - Text on the button used to launch the variable creation dialogue. -Blockly.Msg.NEW_VARIABLE = 'Create variable...'; -/// prompt - Prompts the user to enter the name for a new variable. See [https://github.com/google/blockly/wiki/Variables#dropdown-menu https://github.com/google/blockly/wiki/Variables#dropdown-menu]. -Blockly.Msg.NEW_VARIABLE_TITLE = 'New variable name:'; -/// alert - Tells the user that the name they entered is already in use. -Blockly.Msg.VARIABLE_ALREADY_EXISTS = 'A variable named "%1" already exists.' - -// Variable deletion. -/// confirm - Ask the user to confirm their deletion of multiple uses of a variable. -Blockly.Msg.DELETE_VARIABLE_CONFIRMATION = 'Delete %1 uses of the "%2" variable?'; -/// alert - Tell the user that they can't delete a variable because it's part of the definition of a procedure. -Blockly.Msg.CANNOT_DELETE_VARIABLE_PROCEDURE = 'Can\'t delete the variable "%1" because it is part of the definition of the procedure "%2"'; -/// dropdown choice - Delete the currently selected variable. -Blockly.Msg.DELETE_VARIABLE = 'Delete the "%1" variable'; - -// Colour Blocks. -/// url - Information about colour. -Blockly.Msg.COLOUR_PICKER_HELPURL = 'https://en.wikipedia.org/wiki/Color'; -/// tooltip - See [https://github.com/google/blockly/wiki/Colour#picking-a-colour-from-a-palette https://github.com/google/blockly/wiki/Colour#picking-a-colour-from-a-palette]. -Blockly.Msg.COLOUR_PICKER_TOOLTIP = 'Choose a colour from the palette.'; -/// url - A link that displays a random colour each time you visit it. -Blockly.Msg.COLOUR_RANDOM_HELPURL = 'http://randomcolour.com'; -/// block text - Title of block that generates a colour at random. -Blockly.Msg.COLOUR_RANDOM_TITLE = 'random colour'; -/// tooltip - See [https://github.com/google/blockly/wiki/Colour#generating-a-random-colour https://github.com/google/blockly/wiki/Colour#generating-a-random-colour]. -Blockly.Msg.COLOUR_RANDOM_TOOLTIP = 'Choose a colour at random.'; -/// url - A link for color codes with percentages (0-100%) for each component, instead of the more common 0-255, which may be more difficult for beginners. -Blockly.Msg.COLOUR_RGB_HELPURL = 'http://www.december.com/html/spec/colorper.html'; -/// block text - Title of block for [https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components]. -Blockly.Msg.COLOUR_RGB_TITLE = 'colour with'; -/// block input text - The amount of red (from 0 to 100) to use when [https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components].\n{{Identical|Red}} -Blockly.Msg.COLOUR_RGB_RED = 'red'; -/// block input text - The amount of green (from 0 to 100) to use when [https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components]. -Blockly.Msg.COLOUR_RGB_GREEN = 'green'; -/// block input text - The amount of blue (from 0 to 100) to use when [https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components].\n{{Identical|Blue}} -Blockly.Msg.COLOUR_RGB_BLUE = 'blue'; -/// tooltip - See [https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components https://github.com/google/blockly/wiki/Colour#creating-a-colour-from-red-green-and-blue-components]. -Blockly.Msg.COLOUR_RGB_TOOLTIP = 'Create a colour with the specified amount of red, green, and blue. All values must be between 0 and 100.'; -/// url - A useful link that displays blending of two colors. -Blockly.Msg.COLOUR_BLEND_HELPURL = 'http://meyerweb.com/eric/tools/color-blend/'; -/// block text - A verb for blending two shades of paint. -Blockly.Msg.COLOUR_BLEND_TITLE = 'blend'; -/// block input text - The first of two colours to [https://github.com/google/blockly/wiki/Colour#blending-colours blend]. -Blockly.Msg.COLOUR_BLEND_COLOUR1 = 'colour 1'; -/// block input text - The second of two colours to [https://github.com/google/blockly/wiki/Colour#blending-colours blend]. -Blockly.Msg.COLOUR_BLEND_COLOUR2 = 'colour 2'; -/// block input text - The proportion of the [https://github.com/google/blockly/wiki/Colour#blending-colours blend] containing the first color; the remaining proportion is of the second colour. For example, if the first colour is red and the second color blue, a ratio of 1 would yield pure red, a ratio of .5 would yield purple (equal amounts of red and blue), and a ratio of 0 would yield pure blue.\n{{Identical|Ratio}} -Blockly.Msg.COLOUR_BLEND_RATIO = 'ratio'; -/// tooltip - See [https://github.com/google/blockly/wiki/Colour#blending-colours https://github.com/google/blockly/wiki/Colour#blending-colours]. -Blockly.Msg.COLOUR_BLEND_TOOLTIP = 'Blends two colours together with a given ratio (0.0 - 1.0).'; - -// Loop Blocks. -/// url - Describes 'repeat loops' in computer programs; consider using the translation of the page [https://en.wikipedia.org/wiki/Control_flow http://en.wikipedia.org/wiki/Control_flow]. -Blockly.Msg.CONTROLS_REPEAT_HELPURL = 'https://en.wikipedia.org/wiki/For_loop'; -/// block input text - Title of [https://github.com/google/blockly/wiki/Loops#repeat repeat block].\n\nParameters:\n* %1 - the number of times the body of the loop should be repeated. -Blockly.Msg.CONTROLS_REPEAT_TITLE = 'repeat %1 times'; -/// block text - Preceding the blocks in the body of the loop. See [https://github.com/google/blockly/wiki/Loops https://github.com/google/blockly/wiki/Loops].\n{{Identical|Do}} -Blockly.Msg.CONTROLS_REPEAT_INPUT_DO = 'do'; -/// tooltip - See [https://github.com/google/blockly/wiki/Loops#repeat https://github.com/google/blockly/wiki/Loops#repeat]. -Blockly.Msg.CONTROLS_REPEAT_TOOLTIP = 'Do some statements several times.'; -/// url - Describes 'while loops' in computer programs; consider using the translation of [https://en.wikipedia.org/wiki/While_loop https://en.wikipedia.org/wiki/While_loop], if present, or [https://en.wikipedia.org/wiki/Control_flow https://en.wikipedia.org/wiki/Control_flow]. -Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL = 'https://github.com/google/blockly/wiki/Loops#repeat'; -Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -/// dropdown - Specifies that a loop should [https://github.com/google/blockly/wiki/Loops#repeat-while repeat while] the following condition is true. -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE = 'repeat while'; -/// dropdown - Specifies that a loop should [https://github.com/google/blockly/wiki/Loops#repeat-until repeat until] the following condition becomes true. -Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL = 'repeat until'; -/// tooltip - See [https://github.com/google/blockly/wiki/Loops#repeat-while Loops#repeat-while https://github.com/google/blockly/wiki/Loops#repeat-while Loops#repeat-while]. -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE = 'While a value is true, then do some statements.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Loops#repeat-until https://github.com/google/blockly/wiki/Loops#repeat-until]. -Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL = 'While a value is false, then do some statements.'; - -/// url - Describes 'for loops' in computer programs. Consider using your language's translation of [https://en.wikipedia.org/wiki/For_loop https://en.wikipedia.org/wiki/For_loop], if present. -Blockly.Msg.CONTROLS_FOR_HELPURL = 'https://github.com/google/blockly/wiki/Loops#count-with'; -/// tooltip - See [https://github.com/google/blockly/wiki/Loops#count-with https://github.com/google/blockly/wiki/Loops#count-with].\n\nParameters:\n* %1 - the name of the loop variable. -Blockly.Msg.CONTROLS_FOR_TOOLTIP = 'Have the variable "%1" take on the values from the start number to the end number, counting by the specified interval, and do the specified blocks.'; -/// block text - Repeatedly counts a variable (%1) -/// starting with a (usually lower) number in a range (%2), -/// ending with a (usually higher) number in a range (%3), and counting the -/// iterations by a number of steps (%4). As in -/// [https://github.com/google/blockly/wiki/Loops#count-with -/// https://github.com/google/blockly/wiki/Loops#count-with]. -/// [[File:Blockly-count-with.png]] -Blockly.Msg.CONTROLS_FOR_TITLE = 'count with %1 from %2 to %3 by %4'; -Blockly.Msg.CONTROLS_FOR_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; - -/// url - Describes 'for-each loops' in computer programs. Consider using your language's translation of [https://en.wikipedia.org/wiki/Foreach https://en.wikipedia.org/wiki/Foreach] if present. -Blockly.Msg.CONTROLS_FOREACH_HELPURL = 'https://github.com/google/blockly/wiki/Loops#for-each'; -/// block text - Title of [https://github.com/google/blockly/wiki/Loops#for-each for each block]. -/// Sequentially assigns every item in array %2 to the valiable %1. -Blockly.Msg.CONTROLS_FOREACH_TITLE = 'for each item %1 in list %2'; -Blockly.Msg.CONTROLS_FOREACH_INPUT_DO = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -/// block text - Description of [https://github.com/google/blockly/wiki/Loops#for-each for each blocks].\n\nParameters:\n* %1 - the name of the loop variable. -Blockly.Msg.CONTROLS_FOREACH_TOOLTIP = 'For each item in a list, set the variable "%1" to the item, and then do some statements.'; - -/// url - Describes control flow in computer programs. Consider using your language's translation of [https://en.wikipedia.org/wiki/Control_flow https://en.wikipedia.org/wiki/Control_flow], if it exists. -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL = 'https://github.com/google/blockly/wiki/Loops#loop-termination-blocks'; -/// dropdown - The current loop should be exited. See [https://github.com/google/blockly/wiki/Loops#break https://github.com/google/blockly/wiki/Loops#break]. -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK = 'break out of loop'; -/// dropdown - The current iteration of the loop should be ended and the next should begin. See [https://github.com/google/blockly/wiki/Loops#continue-with-next-iteration https://github.com/google/blockly/wiki/Loops#continue-with-next-iteration]. -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE = 'continue with next iteration of loop'; -/// tooltip - See [https://github.com/google/blockly/wiki/Loops#break-out-of-loop https://github.com/google/blockly/wiki/Loops#break-out-of-loop]. -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK = 'Break out of the containing loop.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Loops#continue-with-next-iteration https://github.com/google/blockly/wiki/Loops#continue-with-next-iteration]. -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE = 'Skip the rest of this loop, and continue with the next iteration.'; -/// warning - The user has tried placing a block outside of a loop (for each, while, repeat, etc.), but this type of block may only be used within a loop. See [https://github.com/google/blockly/wiki/Loops#loop-termination-blocks https://github.com/google/blockly/wiki/Loops#loop-termination-blocks]. -Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING = 'Warning: This block may only be used within a loop.'; - -// Logic Blocks. -/// url - Describes conditional statements (if-then-else) in computer programs. Consider using your language's translation of [https://en.wikipedia.org/wiki/If_else https://en.wikipedia.org/wiki/If_else], if present. -Blockly.Msg.CONTROLS_IF_HELPURL = 'https://github.com/google/blockly/wiki/IfElse'; -/// tooltip - Describes [https://github.com/google/blockly/wiki/IfElse#if-blocks 'if' blocks]. Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present. -Blockly.Msg.CONTROLS_IF_TOOLTIP_1 = 'If a value is true, then do some statements.'; -/// tooltip - Describes [https://github.com/google/blockly/wiki/IfElse#if-else-blocks if-else blocks]. Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present. -Blockly.Msg.CONTROLS_IF_TOOLTIP_2 = 'If a value is true, then do the first block of statements. Otherwise, do the second block of statements.'; -/// tooltip - Describes [https://github.com/google/blockly/wiki/IfElse#if-else-if-blocks if-else-if blocks]. Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present. -Blockly.Msg.CONTROLS_IF_TOOLTIP_3 = 'If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements.'; -/// tooltip - Describes [https://github.com/google/blockly/wiki/IfElse#if-else-if-else-blocks if-else-if-else blocks]. Consider using your language's translation of [https://en.wikipedia.org/wiki/If_statement https://en.wikipedia.org/wiki/If_statement], if present. -Blockly.Msg.CONTROLS_IF_TOOLTIP_4 = 'If the first value is true, then do the first block of statements. Otherwise, if the second value is true, do the second block of statements. If none of the values are true, do the last block of statements.'; -/// block text - See [https://github.com/google/blockly/wiki/IfElse https://github.com/google/blockly/wiki/IfElse]. -/// It is recommended, but not essential, that this have text in common with the translation of 'else if' -Blockly.Msg.CONTROLS_IF_MSG_IF = 'if'; -/// block text - See [https://github.com/google/blockly/wiki/IfElse https://github.com/google/blockly/wiki/IfElse]. The English words "otherwise if" would probably be clearer than "else if", but the latter is used because it is traditional and shorter. -Blockly.Msg.CONTROLS_IF_MSG_ELSEIF = 'else if'; -/// block text - See [https://github.com/google/blockly/wiki/IfElse https://github.com/google/blockly/wiki/IfElse]. The English word "otherwise" would probably be superior to "else", but the latter is used because it is traditional and shorter. -Blockly.Msg.CONTROLS_IF_MSG_ELSE = 'else'; -Blockly.Msg.CONTROLS_IF_MSG_THEN = Blockly.Msg.CONTROLS_REPEAT_INPUT_DO; -Blockly.Msg.CONTROLS_IF_IF_TITLE_IF = Blockly.Msg.CONTROLS_IF_MSG_IF; -/// tooltip - Describes [https://github.com/google/blockly/wiki/IfElse#block-modification if block modification]. -Blockly.Msg.CONTROLS_IF_IF_TOOLTIP = 'Add, remove, or reorder sections to reconfigure this if block.'; -Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF = Blockly.Msg.CONTROLS_IF_MSG_ELSEIF; -/// tooltip - Describes the 'else if' subblock during [https://github.com/google/blockly/wiki/IfElse#block-modification if block modification]. -Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP = 'Add a condition to the if block.'; -Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE = Blockly.Msg.CONTROLS_IF_MSG_ELSE; -/// tooltip - Describes the 'else' subblock during [https://github.com/google/blockly/wiki/IfElse#block-modification if block modification]. -Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP = 'Add a final, catch-all condition to the if block.'; - -/// url - Information about comparisons. -Blockly.Msg.LOGIC_COMPARE_HELPURL = 'https://en.wikipedia.org/wiki/Inequality_(mathematics)'; -/// tooltip - Describes the equals (=) block. -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ = 'Return true if both inputs equal each other.'; -/// tooltip - Describes the not equals (≠) block. -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ = 'Return true if both inputs are not equal to each other.'; -/// tooltip - Describes the less than (<) block. -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT = 'Return true if the first input is smaller than the second input.'; -/// tooltip - Describes the less than or equals (≤) block. -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE = 'Return true if the first input is smaller than or equal to the second input.'; -/// tooltip - Describes the greater than (>) block. -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT = 'Return true if the first input is greater than the second input.'; -/// tooltip - Describes the greater than or equals (≥) block. -Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE = 'Return true if the first input is greater than or equal to the second input.'; - -/// url - Information about the Boolean conjunction ("and") and disjunction ("or") operators. Consider using the translation of [https://en.wikipedia.org/wiki/Boolean_logic https://en.wikipedia.org/wiki/Boolean_logic], if it exists in your language. -Blockly.Msg.LOGIC_OPERATION_HELPURL = 'https://github.com/google/blockly/wiki/Logic#logical-operations'; -/// tooltip - See [https://en.wikipedia.org/wiki/Logical_conjunction https://en.wikipedia.org/wiki/Logical_conjunction]. -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND = 'Return true if both inputs are true.'; -/// block text - See [https://en.wikipedia.org/wiki/Logical_conjunction https://en.wikipedia.org/wiki/Logical_conjunction].\n{{Identical|And}} -Blockly.Msg.LOGIC_OPERATION_AND = 'and'; -/// block text - See [https://en.wikipedia.org/wiki/Disjunction https://en.wikipedia.org/wiki/Disjunction]. -Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR = 'Return true if at least one of the inputs is true.'; -/// block text - See [https://en.wikipedia.org/wiki/Disjunction https://en.wikipedia.org/wiki/Disjunction].\n{{Identical|Or}} -Blockly.Msg.LOGIC_OPERATION_OR = 'or'; - -/// url - Information about logical negation. The translation of [https://en.wikipedia.org/wiki/Logical_negation https://en.wikipedia.org/wiki/Logical_negation] is recommended if it exists in the target language. -Blockly.Msg.LOGIC_NEGATE_HELPURL = 'https://github.com/google/blockly/wiki/Logic#not'; -/// block text - This is a unary operator that returns ''false'' when the input is ''true'', and ''true'' when the input is ''false''. -/// \n\nParameters:\n* %1 - the input (which should be either the value "true" or "false") -Blockly.Msg.LOGIC_NEGATE_TITLE = 'not %1'; -/// tooltip - See [https://en.wikipedia.org/wiki/Logical_negation https://en.wikipedia.org/wiki/Logical_negation]. -Blockly.Msg.LOGIC_NEGATE_TOOLTIP = 'Returns true if the input is false. Returns false if the input is true.'; - -/// url - Information about the logic values ''true'' and ''false''. Consider using the translation of [https://en.wikipedia.org/wiki/Truth_value https://en.wikipedia.org/wiki/Truth_value] if it exists in your language. -Blockly.Msg.LOGIC_BOOLEAN_HELPURL = 'https://github.com/google/blockly/wiki/Logic#values'; -/// block text - The word for the [https://en.wikipedia.org/wiki/Truth_value logical value] ''true''.\n{{Identical|True}} -Blockly.Msg.LOGIC_BOOLEAN_TRUE = 'true'; -/// block text - The word for the [https://en.wikipedia.org/wiki/Truth_value logical value] ''false''.\n{{Identical|False}} -Blockly.Msg.LOGIC_BOOLEAN_FALSE = 'false'; -/// tooltip - Indicates that the block returns either of the two possible [https://en.wikipedia.org/wiki/Truth_value logical values]. -Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP = 'Returns either true or false.'; - -/// url - Provide a link to the translation of [https://en.wikipedia.org/wiki/Nullable_type https://en.wikipedia.org/wiki/Nullable_type], if it exists in your language; otherwise, do not worry about translating this advanced concept. -Blockly.Msg.LOGIC_NULL_HELPURL = 'https://en.wikipedia.org/wiki/Nullable_type'; -/// block text - In computer languages, ''null'' is a special value that indicates that no value has been set. You may use your language's word for "nothing" or "invalid".\n{{Identical|Null}} -Blockly.Msg.LOGIC_NULL = 'null'; -/// tooltip - This should use the word from the previous message. -Blockly.Msg.LOGIC_NULL_TOOLTIP = 'Returns null.'; - -/// url - Describes the programming language operator known as the ''ternary'' or ''conditional'' operator. It is recommended that you use the translation of [https://en.wikipedia.org/wiki/%3F: https://en.wikipedia.org/wiki/%3F:] if it exists. -Blockly.Msg.LOGIC_TERNARY_HELPURL = 'https://en.wikipedia.org/wiki/%3F:'; -/// block input text - Label for the input whose value determines which of the other two inputs is returned. In some programming languages, this is called a ''''predicate''''. -Blockly.Msg.LOGIC_TERNARY_CONDITION = 'test'; -/// block input text - Indicates that the following input should be returned (used as output) if the test input is true. Remember to try to keep block text terse (short). -Blockly.Msg.LOGIC_TERNARY_IF_TRUE = 'if true'; -/// block input text - Indicates that the following input should be returned (used as output) if the test input is false. -Blockly.Msg.LOGIC_TERNARY_IF_FALSE = 'if false'; -/// tooltip - See [https://en.wikipedia.org/wiki/%3F: https://en.wikipedia.org/wiki/%3F:]. -Blockly.Msg.LOGIC_TERNARY_TOOLTIP = 'Check the condition in "test". If the condition is true, returns the "if true" value; otherwise returns the "if false" value.'; - -// Math Blocks. -/// url - Information about (real) numbers. -Blockly.Msg.MATH_NUMBER_HELPURL = 'https://en.wikipedia.org/wiki/Number'; -/// tooltip - Any positive or negative number, not necessarily an integer. -Blockly.Msg.MATH_NUMBER_TOOLTIP = 'A number.'; - -/// {{optional}}\nmath - The symbol for the binary operation addition. -Blockly.Msg.MATH_ADDITION_SYMBOL = '+'; -/// {{optional}}\nmath - The symbol for the binary operation indicating that the right operand should be -/// subtracted from the left operand. -Blockly.Msg.MATH_SUBTRACTION_SYMBOL = '-'; -/// {{optional}}\nmath - The binary operation indicating that the left operand should be divided by -/// the right operand. -Blockly.Msg.MATH_DIVISION_SYMBOL = '÷'; -/// {{optional}}\nmath - The symbol for the binary operation multiplication. -Blockly.Msg.MATH_MULTIPLICATION_SYMBOL = '×'; -/// {{optional}}\nmath - The symbol for the binary operation exponentiation. Specifically, if the -/// value of the left operand is L and the value of the right operand (the exponent) is -/// R, multiply L by itself R times. (Fractional and negative exponents are also legal.) -Blockly.Msg.MATH_POWER_SYMBOL = '^'; - -/// math - The short name of the trigonometric function -/// [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine]. -Blockly.Msg.MATH_TRIG_SIN = 'sin'; -/// math - The short name of the trigonometric function -/// [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine]. -Blockly.Msg.MATH_TRIG_COS = 'cos'; -/// math - The short name of the trigonometric function -/// [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent]. -Blockly.Msg.MATH_TRIG_TAN = 'tan'; -/// math - The short name of the ''inverse of'' the trigonometric function -/// [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine]. -Blockly.Msg.MATH_TRIG_ASIN = 'asin'; -/// math - The short name of the ''inverse of'' the trigonometric function -/// [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine]. -Blockly.Msg.MATH_TRIG_ACOS = 'acos'; -/// math - The short name of the ''inverse of'' the trigonometric function -/// [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent]. -Blockly.Msg.MATH_TRIG_ATAN = 'atan'; - -/// url - Information about addition, subtraction, multiplication, division, and exponentiation. -Blockly.Msg.MATH_ARITHMETIC_HELPURL = 'https://en.wikipedia.org/wiki/Arithmetic'; -/// tooltip - See [https://en.wikipedia.org/wiki/Addition https://en.wikipedia.org/wiki/Addition]. -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD = 'Return the sum of the two numbers.'; -/// tooltip - See [https://en.wikipedia.org/wiki/Subtraction https://en.wikipedia.org/wiki/Subtraction]. -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS = 'Return the difference of the two numbers.'; -/// tooltip - See [https://en.wikipedia.org/wiki/Multiplication https://en.wikipedia.org/wiki/Multiplication]. -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY = 'Return the product of the two numbers.'; -/// tooltip - See [https://en.wikipedia.org/wiki/Division_(mathematics) https://en.wikipedia.org/wiki/Division_(mathematics)]. -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE = 'Return the quotient of the two numbers.'; -/// tooltip - See [https://en.wikipedia.org/wiki/Exponentiation https://en.wikipedia.org/wiki/Exponentiation]. -Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER = 'Return the first number raised to the power of the second number.'; - -/// url - Information about the square root operation. -Blockly.Msg.MATH_SINGLE_HELPURL = 'https://en.wikipedia.org/wiki/Square_root'; -/// dropdown - This computes the positive [https://en.wikipedia.org/wiki/Square_root square root] of its input. For example, the square root of 16 is 4. -Blockly.Msg.MATH_SINGLE_OP_ROOT = 'square root'; -/// tooltip - Please use the same term as in the previous message. -Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT = 'Return the square root of a number.'; -/// dropdown - This leaves positive numeric inputs changed and inverts negative inputs. For example, the absolute value of 5 is 5; the absolute value of -5 is also 5. For more information, see [https://en.wikipedia.org/wiki/Absolute_value https://en.wikipedia.org/wiki/Absolute_value]. -Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE = 'absolute'; -/// tooltip - Please use the same term as in the previous message. -Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS = 'Return the absolute value of a number.'; - -/// tooltip - Calculates '''0-n''', where '''n''' is the single numeric input. -Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG = 'Return the negation of a number.'; -/// tooltip - Calculates the [https://en.wikipedia.org/wiki/Natural_logarithm|natural logarithm] of its single numeric input. -Blockly.Msg.MATH_SINGLE_TOOLTIP_LN = 'Return the natural logarithm of a number.'; -/// tooltip - Calculates the [https://en.wikipedia.org/wiki/Common_logarithm common logarithm] of its single numeric input. -Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10 = 'Return the base 10 logarithm of a number.'; -/// tooltip - Multiplies [https://en.wikipedia.org/wiki/E_%28mathematical_constant%29 e] by itself n times, where n is the single numeric input. -Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP = 'Return e to the power of a number.'; -/// tooltip - Multiplies 10 by itself n times, where n is the single numeric input. -Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10 = 'Return 10 to the power of a number.'; - -/// url - Information about the trigonometric functions sine, cosine, tangent, and their inverses (ideally using degrees, not radians). -Blockly.Msg.MATH_TRIG_HELPURL = 'https://en.wikipedia.org/wiki/Trigonometric_functions'; -/// tooltip - Return the [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent sine] of an [https://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians. -Blockly.Msg.MATH_TRIG_TOOLTIP_SIN = 'Return the sine of a degree (not radian).'; -/// tooltip - Return the [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent cosine] of an [https://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians. -Blockly.Msg.MATH_TRIG_TOOLTIP_COS = 'Return the cosine of a degree (not radian).'; -/// tooltip - Return the [https://en.wikipedia.org/wiki/Trigonometric_functions#Sine.2C_cosine_and_tangent tangent] of an [https://en.wikipedia.org/wiki/Degree_(angle) angle in degrees], not radians. -Blockly.Msg.MATH_TRIG_TOOLTIP_TAN = 'Return the tangent of a degree (not radian).'; -/// tooltip - The [https://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [https://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent sine function], using [https://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians. -Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN = 'Return the arcsine of a number.'; -/// tooltip - The [https://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [https://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent cosine] function, using [https://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians. -Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS = 'Return the arccosine of a number.'; -/// tooltip - The [https://en.wikipedia.org/wiki/Inverse_trigonometric_functions inverse] of the [https://en.wikipedia.org/wiki/Cosine#Sine.2C_cosine_and_tangent tangent] function, using [https://en.wikipedia.org/wiki/Degree_(angle) degrees], not radians. -Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN = 'Return the arctangent of a number.'; - -/// url - Information about the mathematical constants Pi (π), e, the golden ratio (φ), √ 2, √ 1/2, and infinity (∞). -Blockly.Msg.MATH_CONSTANT_HELPURL = 'https://en.wikipedia.org/wiki/Mathematical_constant'; -/// tooltip - Provides the specified [https://en.wikipedia.org/wiki/Mathematical_constant mathematical constant]. -Blockly.Msg.MATH_CONSTANT_TOOLTIP = 'Return one of the common constants: π (3.141…), e (2.718…), φ (1.618…), sqrt(2) (1.414…), sqrt(½) (0.707…), or ∞ (infinity).'; -/// dropdown - A number is '''even''' if it is a multiple of 2. For example, 4 is even (yielding true), but 3 is not (false). -Blockly.Msg.MATH_IS_EVEN = 'is even'; -/// dropdown - A number is '''odd''' if it is not a multiple of 2. For example, 3 is odd (yielding true), but 4 is not (false). The opposite of "odd" is "even". -Blockly.Msg.MATH_IS_ODD = 'is odd'; -/// dropdown - A number is [https://en.wikipedia.org/wiki/Prime prime] if it cannot be evenly divided by any positive integers except for 1 and itself. For example, 5 is prime, but 6 is not because 2 × 3 = 6. -Blockly.Msg.MATH_IS_PRIME = 'is prime'; -/// dropdown - A number is '''whole''' if it is an [https://en.wikipedia.org/wiki/Integer integer]. For example, 5 is whole, but 5.1 is not. -Blockly.Msg.MATH_IS_WHOLE = 'is whole'; -/// dropdown - A number is '''positive''' if it is greater than 0. (0 is neither negative nor positive.) -Blockly.Msg.MATH_IS_POSITIVE = 'is positive'; -/// dropdown - A number is '''negative''' if it is less than 0. (0 is neither negative nor positive.) -Blockly.Msg.MATH_IS_NEGATIVE = 'is negative'; -/// dropdown - A number x is divisible by y if y goes into x evenly. For example, 10 is divisible by 5, but 10 is not divisible by 3. -Blockly.Msg.MATH_IS_DIVISIBLE_BY = 'is divisible by'; -/// tooltip - This block lets the user specify via a dropdown menu whether to check if the numeric input is even, odd, prime, whole, positive, negative, or divisible by a given value. -Blockly.Msg.MATH_IS_TOOLTIP = 'Check if a number is an even, odd, prime, whole, positive, negative, or if it is divisible by certain number. Returns true or false.'; - -/// url - Information about incrementing (increasing the value of) a variable. -/// For other languages, just use the translation of the Wikipedia page about -/// addition ([https://en.wikipedia.org/wiki/Addition https://en.wikipedia.org/wiki/Addition]). -Blockly.Msg.MATH_CHANGE_HELPURL = 'https://en.wikipedia.org/wiki/Programming_idiom#Incrementing_a_counter'; -/// - As in: ''change'' [the value of variable] ''item'' ''by'' 1 (e.g., if the variable named 'item' had the value 5, change it to 6). -/// %1 is a variable name. -/// %2 is the amount of change. -Blockly.Msg.MATH_CHANGE_TITLE = 'change %1 by %2'; -Blockly.Msg.MATH_CHANGE_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -/// tooltip - This updates the value of the variable by adding to it the following numeric input.\n\nParameters:\n* %1 - the name of the variable whose value should be increased. -Blockly.Msg.MATH_CHANGE_TOOLTIP = 'Add a number to variable "%1".'; - -/// url - Information about how numbers are rounded to the nearest integer -Blockly.Msg.MATH_ROUND_HELPURL = 'https://en.wikipedia.org/wiki/Rounding'; -/// tooltip - See [https://en.wikipedia.org/wiki/Rounding https://en.wikipedia.org/wiki/Rounding]. -Blockly.Msg.MATH_ROUND_TOOLTIP = 'Round a number up or down.'; -/// dropdown - This rounds its input to the nearest whole number. For example, 3.4 is rounded to 3. -Blockly.Msg.MATH_ROUND_OPERATOR_ROUND = 'round'; -/// dropdown - This rounds its input up to the nearest whole number. For example, if the input was 2.2, the result would be 3. -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP = 'round up'; -/// dropdown - This rounds its input down to the nearest whole number. For example, if the input was 3.8, the result would be 3. -Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN = 'round down'; - -/// url - Information about applying a function to a list of numbers. (We were unable to find such information in English. Feel free to skip this and any other URLs that are difficult.) -Blockly.Msg.MATH_ONLIST_HELPURL = ''; -/// dropdown - This computes the sum of the numeric elements in the list. For example, the sum of the list {1, 4} is 5. -Blockly.Msg.MATH_ONLIST_OPERATOR_SUM = 'sum of list'; -/// tooltip - Please use the same term for "sum" as in the previous message. -Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM = 'Return the sum of all the numbers in the list.'; -/// dropdown - This finds the smallest (minimum) number in a list. For example, the smallest number in the list [-5, 0, 3] is -5. -Blockly.Msg.MATH_ONLIST_OPERATOR_MIN = 'min of list'; -/// tooltip - Please use the same term for "min" or "minimum" as in the previous message. -Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN = 'Return the smallest number in the list.'; -/// dropdown - This finds the largest (maximum) number in a list. For example, the largest number in the list [-5, 0, 3] is 3. -Blockly.Msg.MATH_ONLIST_OPERATOR_MAX = 'max of list'; -/// tooltip -Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX = 'Return the largest number in the list.'; -/// dropdown - This adds up all of the numbers in a list and divides the sum by the number of elements in the list. For example, the [https://en.wikipedia.org/wiki/Arithmetic_mean average] of the list [1, 2, 3, 4] is 2.5 (10/4). -Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE = 'average of list'; -/// tooltip - See [https://en.wikipedia.org/wiki/Arithmetic_mean https://en.wikipedia.org/wiki/Arithmetic_mean] for more informatin. -Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE = 'Return the average (arithmetic mean) of the numeric values in the list.'; -/// dropdown - This finds the [https://en.wikipedia.org/wiki/Median median] of the numeric values in a list. For example, the median of the list {1, 2, 7, 12, 13} is 7. -Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN = 'median of list'; -/// tooltip - See [https://en.wikipedia.org/wiki/Median median https://en.wikipedia.org/wiki/Median median] for more information. -Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN = 'Return the median number in the list.'; -/// dropdown - This finds the most common numbers ([https://en.wikipedia.org/wiki/Mode_(statistics) modes]) in a list. For example, the modes of the list {1, 3, 9, 3, 9} are {3, 9}. -Blockly.Msg.MATH_ONLIST_OPERATOR_MODE = 'modes of list'; -/// tooltip - See [https://en.wikipedia.org/wiki/Mode_(statistics) https://en.wikipedia.org/wiki/Mode_(statistics)] for more information. -Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE = 'Return a list of the most common item(s) in the list.'; -/// dropdown - This finds the [https://en.wikipedia.org/wiki/Standard_deviation standard deviation] of the numeric values in a list. -Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV = 'standard deviation of list'; -/// tooltip - See [https://en.wikipedia.org/wiki/Standard_deviation https://en.wikipedia.org/wiki/Standard_deviation] for more information. -Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV = 'Return the standard deviation of the list.'; -/// dropdown - This choose an element at random from a list. Each element is chosen with equal probability. -Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM = 'random item of list'; -/// tooltip - Please use same term for 'random' as in previous entry. -Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM = 'Return a random element from the list.'; - -/// url - information about the modulo (remainder) operation. -Blockly.Msg.MATH_MODULO_HELPURL = 'https://en.wikipedia.org/wiki/Modulo_operation'; -/// block text - Title of block providing the remainder when dividing the first numerical input by the second. For example, the remainder of 10 divided by 3 is 1.\n\nParameters:\n* %1 - the dividend (10, in our example)\n* %2 - the divisor (3 in our example). -Blockly.Msg.MATH_MODULO_TITLE = 'remainder of %1 ÷ %2'; -/// tooltip - For example, the remainder of 10 divided by 3 is 1. -Blockly.Msg.MATH_MODULO_TOOLTIP = 'Return the remainder from dividing the two numbers.'; - -/// url - Information about constraining a numeric value to be in a specific range. (The English URL is not ideal. Recall that translating URLs is the lowest priority.) -Blockly.Msg.MATH_CONSTRAIN_HELPURL = 'https://en.wikipedia.org/wiki/Clamping_%28graphics%29'; -/// block text - The title of the block that '''constrain'''s (forces) a number to be in a given range. -///For example, if the number 150 is constrained to be between 5 and 100, the result will be 100. -///\n\nParameters:\n* %1 - the value to constrain (e.g., 150)\n* %2 - the minimum value (e.g., 5)\n* %3 - the maximum value (e.g., 100). -Blockly.Msg.MATH_CONSTRAIN_TITLE = 'constrain %1 low %2 high %3'; -/// tooltip - This compares a number ''x'' to a low value ''L'' and a high value ''H''. If ''x'' is less then ''L'', the result is ''L''. If ''x'' is greater than ''H'', the result is ''H''. Otherwise, the result is ''x''. -Blockly.Msg.MATH_CONSTRAIN_TOOLTIP = 'Constrain a number to be between the specified limits (inclusive).'; - -/// url - Information about how computers generate random numbers. -Blockly.Msg.MATH_RANDOM_INT_HELPURL = 'https://en.wikipedia.org/wiki/Random_number_generation'; -/// block text - The title of the block that generates a random integer (whole number) in the specified range. For example, if the range is from 5 to 7, this returns 5, 6, or 7 with equal likelihood. %1 is a placeholder for the lower number, %2 is the placeholder for the larger number. -Blockly.Msg.MATH_RANDOM_INT_TITLE = 'random integer from %1 to %2'; -/// tooltip - Return a random integer between two values specified as inputs. For example, if one input was 7 and another 9, any of the numbers 7, 8, or 9 could be produced. -Blockly.Msg.MATH_RANDOM_INT_TOOLTIP = 'Return a random integer between the two specified limits, inclusive.'; - -/// url - Information about how computers generate random numbers (specifically, numbers in the range from 0 to just below 1). -Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL = 'https://en.wikipedia.org/wiki/Random_number_generation'; -/// block text - The title of the block that generates a random number greater than or equal to 0 and less than 1. -Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM = 'random fraction'; -/// tooltip - Return a random fraction between 0 and 1. The value may be equal to 0 but must be less than 1. -Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP = 'Return a random fraction between 0.0 (inclusive) and 1.0 (exclusive).'; - -// Text Blocks. -/// url - Information about how computers represent text (sometimes referred to as ''string''s). -Blockly.Msg.TEXT_TEXT_HELPURL = 'https://en.wikipedia.org/wiki/String_(computer_science)'; -/// tooltip - See [https://github.com/google/blockly/wiki/Text https://github.com/google/blockly/wiki/Text]. -Blockly.Msg.TEXT_TEXT_TOOLTIP = 'A letter, word, or line of text.'; - -/// url - Information on concatenating/appending pieces of text. -Blockly.Msg.TEXT_JOIN_HELPURL = 'https://github.com/google/blockly/wiki/Text#text-creation'; -/// block text - See [https://github.com/google/blockly/wiki/Text#text-creation https://github.com/google/blockly/wiki/Text#text-creation]. -Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH = 'create text with'; -/// tooltip - See [https://github.com/google/blockly/wiki/Text#text-creation create text with] for more information. -Blockly.Msg.TEXT_JOIN_TOOLTIP = 'Create a piece of text by joining together any number of items.'; - -/// block text - This is shown when the programmer wants to change the number of pieces of text being joined together. See [https://github.com/google/blockly/wiki/Text#text-creation https://github.com/google/blockly/wiki/Text#text-creation], specifically the last picture in the 'Text creation' section.\n{{Identical|Join}} -Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN = 'join'; -/// tooltip - See [https://github.com/google/blockly/wiki/Text#text-creation https://github.com/google/blockly/wiki/Text#text-creation], specifically the last picture in the 'Text creation' section. -Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP = 'Add, remove, or reorder sections to reconfigure this text block.'; -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM = Blockly.Msg.VARIABLES_DEFAULT_NAME; -/// block text - See [https://github.com/google/blockly/wiki/Text#text-creation https://github.com/google/blockly/wiki/Text#text-creation], specifically the last picture in the 'Text creation' section. -Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP = 'Add an item to the text.'; - -/// url - This and the other text-related URLs are going to be hard to translate. As always, it is okay to leave untranslated or paste in the English-language URL. For these URLs, you might also consider a general URL about how computers represent text (such as the translation of [https://en.wikipedia.org/wiki/String_(computer_science) this Wikipedia page]). -Blockly.Msg.TEXT_APPEND_HELPURL = 'https://github.com/google/blockly/wiki/Text#text-modification'; -/// block input text - Message preceding the name of a variable to which text should be appended. -/// [[File:blockly-append-text.png]] -Blockly.Msg.TEXT_APPEND_TO = 'to'; -/// block input text - Message following the variable and preceding the piece of text that should -/// be appended, as shown below. -/// [[File:blockly-append-text.png]] -Blockly.Msg.TEXT_APPEND_APPENDTEXT = 'append text'; -Blockly.Msg.TEXT_APPEND_VARIABLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -/// tooltip - See [https://github.com/google/blockly/wiki/Text#text-modification https://github.com/google/blockly/wiki/Text#text-modification] for more information.\n\nParameters:\n* %1 - the name of the variable to which text should be appended -Blockly.Msg.TEXT_APPEND_TOOLTIP = 'Append some text to variable "%1".'; - -/// url - Information about text on computers (usually referred to as 'strings'). -Blockly.Msg.TEXT_LENGTH_HELPURL = 'https://github.com/google/blockly/wiki/Text#text-modification'; -/// block text - See [https://github.com/google/blockly/wiki/Text#text-length https://github.com/google/blockly/wiki/Text#text-length]. -/// \n\nParameters:\n* %1 - the piece of text to take the length of -Blockly.Msg.TEXT_LENGTH_TITLE = 'length of %1'; -/// tooltip - See [https://github.com/google/blockly/wiki/Text#text-length https://github.com/google/blockly/wiki/Text#text-length]. -Blockly.Msg.TEXT_LENGTH_TOOLTIP = 'Returns the number of letters (including spaces) in the provided text.'; - -/// url - Information about empty pieces of text on computers (usually referred to as 'empty strings'). -Blockly.Msg.TEXT_ISEMPTY_HELPURL = 'https://github.com/google/blockly/wiki/Text#checking-for-empty-text'; -/// block text - See [https://github.com/google/blockly/wiki/Text#checking-for-empty-text https://github.com/google/blockly/wiki/Text#checking-for-empty-text]. -/// \n\nParameters:\n* %1 - the piece of text to test for emptiness -Blockly.Msg.TEXT_ISEMPTY_TITLE = '%1 is empty'; -/// tooltip - See [https://github.com/google/blockly/wiki/Text#checking-for-empty-text https://github.com/google/blockly/wiki/Text#checking-for-empty-text]. -Blockly.Msg.TEXT_ISEMPTY_TOOLTIP = 'Returns true if the provided text is empty.'; - -/// url - Information about finding a character in a piece of text. -Blockly.Msg.TEXT_INDEXOF_HELPURL = 'https://github.com/google/blockly/wiki/Text#finding-text'; -/// tooltip - %1 will be replaced by either the number 0 or -1 depending on the indexing mode. See [https://github.com/google/blockly/wiki/Text#finding-text https://github.com/google/blockly/wiki/Text#finding-text]. -Blockly.Msg.TEXT_INDEXOF_TOOLTIP = 'Returns the index of the first/last occurrence of the first text in the second text. Returns %1 if text is not found.'; -/// block text - Title of blocks allowing users to find text. See -/// [https://github.com/google/blockly/wiki/Text#finding-text -/// https://github.com/google/blockly/wiki/Text#finding-text]. -/// [[File:Blockly-find-text.png]]. -Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT = 'in text'; -/// dropdown - See [https://github.com/google/blockly/wiki/Text#finding-text -/// https://github.com/google/blockly/wiki/Text#finding-text]. -/// [[File:Blockly-find-text.png]]. -Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST = 'find first occurrence of text'; -/// dropdown - See [https://github.com/google/blockly/wiki/Text#finding-text -/// https://github.com/google/blockly/wiki/Text#finding-text]. This would -/// replace "find first occurrence of text" below. (For more information on -/// how common text is factored out of dropdown menus, see -/// [https://translatewiki.net/wiki/Translating:Blockly#Drop-Down_Menus -/// https://translatewiki.net/wiki/Translating:Blockly#Drop-Down_Menus)].) -/// [[File:Blockly-find-text.png]]. -Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST = 'find last occurrence of text'; -/// block text - Optional text to follow the rightmost block in a -/// [https://github.com/google/blockly/wiki/Text#finding-text -/// https://github.com/google/blockly/wiki/Text#finding-text in text ... find block] -/// (after the "a" in the below picture). This will be the empty string in most languages. -/// [[File:Blockly-find-text.png]]. -Blockly.Msg.TEXT_INDEXOF_TAIL = ''; - -/// url - Information about extracting characters (letters, number, symbols, etc.) from text. -Blockly.Msg.TEXT_CHARAT_HELPURL = 'https://github.com/google/blockly/wiki/Text#extracting-text'; -/// block text - Appears before the piece of text from which a letter (or number, -/// punctuation character, etc.) should be extracted, as shown below. See -/// [https://github.com/google/blockly/wiki/Text#extracting-a-single-character -/// https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. -/// [[File:Blockly-text-get.png]] -Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT = 'in text'; -/// dropdown - Indicates that the letter (or number, punctuation character, etc.) with the -/// specified index should be obtained from the preceding piece of text. See -/// [https://github.com/google/blockly/wiki/Text#extracting-a-single-character -/// https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. -/// [[File:Blockly-text-get.png]] -Blockly.Msg.TEXT_CHARAT_FROM_START = 'get letter #'; -/// block text - Indicates that the letter (or number, punctuation character, etc.) with the -/// specified index from the end of a given piece of text should be obtained. See -/// [https://github.com/google/blockly/wiki/Text#extracting-a-single-character -/// https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. -/// [[File:Blockly-text-get.png]] -Blockly.Msg.TEXT_CHARAT_FROM_END = 'get letter # from end'; -/// block text - Indicates that the first letter of the following piece of text should be -/// retrieved. See [https://github.com/google/blockly/wiki/Text#extracting-a-single-character -/// https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. -/// [[File:Blockly-text-get.png]] -Blockly.Msg.TEXT_CHARAT_FIRST = 'get first letter'; -/// block text - Indicates that the last letter (or number, punctuation mark, etc.) of the -/// following piece of text should be retrieved. See -/// [https://github.com/google/blockly/wiki/Text#extracting-a-single-character -/// https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. -/// [[File:Blockly-text-get.png]] -Blockly.Msg.TEXT_CHARAT_LAST = 'get last letter'; -/// block text - Indicates that any letter (or number, punctuation mark, etc.) in the -/// following piece of text should be randomly selected. See -/// [https://github.com/google/blockly/wiki/Text#extracting-a-single-character -/// https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. -/// [[File:Blockly-text-get.png]] -Blockly.Msg.TEXT_CHARAT_RANDOM = 'get random letter'; -/// block text - Text that goes after the rightmost block/dropdown when getting a single letter from -/// a piece of text, as in [https://blockly-demo.appspot.com/static/apps/code/index.html#3m23km these -/// blocks] or shown below. For most languages, this will be blank. -/// [[File:Blockly-text-get.png]] -Blockly.Msg.TEXT_CHARAT_TAIL = ''; -/// tooltip - See [https://github.com/google/blockly/wiki/Text#extracting-a-single-character -/// https://github.com/google/blockly/wiki/Text#extracting-a-single-character]. -/// [[File:Blockly-text-get.png]] -Blockly.Msg.TEXT_CHARAT_TOOLTIP = 'Returns the letter at the specified position.'; - -/// See [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text -/// https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. -Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP = 'Returns a specified portion of the text.'; -/// url - Information about extracting characters from text. Reminder: urls are the -/// lowest priority translations. Feel free to skip. -Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL = 'https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text'; -/// block text - Precedes a piece of text from which a portion should be extracted. -/// [[File:Blockly-get-substring.png]] -Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT = 'in text'; -/// dropdown - Indicates that the following number specifies the position (relative to the start -/// position) of the beginning of the region of text that should be obtained from the preceding -/// piece of text. See [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text -/// https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. -/// [[File:Blockly-get-substring.png]] -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START = 'get substring from letter #'; -/// dropdown - Indicates that the following number specifies the position (relative to the end -/// position) of the beginning of the region of text that should be obtained from the preceding -/// piece of text. See [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text -/// https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. -/// Note: If {{msg-Blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will -/// automatically appear ''after'' this and any other -/// [https://translatewiki.net/wiki/Translating:Blockly#Ordinal_numbers ordinal numbers] -/// on this block. -/// [[File:Blockly-get-substring.png]] -Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END = 'get substring from letter # from end'; -/// block text - Indicates that a region starting with the first letter of the preceding piece -/// of text should be extracted. See -/// [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text -/// https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. -/// [[File:Blockly-get-substring.png]] -Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST = 'get substring from first letter'; -/// dropdown - Indicates that the following number specifies the position (relative to -/// the start position) of the end of the region of text that should be obtained from the -/// preceding piece of text. See -/// [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text -/// https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. -/// [[File:Blockly-get-substring.png]] -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START = 'to letter #'; -/// dropdown - Indicates that the following number specifies the position (relative to the -/// end position) of the end of the region of text that should be obtained from the preceding -/// piece of text. See -/// [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text -/// https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. -/// [[File:Blockly-get-substring.png]] -Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END = 'to letter # from end'; -/// block text - Indicates that a region ending with the last letter of the preceding piece -/// of text should be extracted. See -/// [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text -/// https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text]. -/// [[File:Blockly-get-substring.png]] -Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST = 'to last letter'; -/// block text - Text that should go after the rightmost block/dropdown when -/// [https://github.com/google/blockly/wiki/Text#extracting-a-region-of-text -/// extracting a region of text]. In most languages, this will be the empty string. -/// [[File:Blockly-get-substring.png]] -Blockly.Msg.TEXT_GET_SUBSTRING_TAIL = ''; - -/// url - Information about the case of letters (upper-case and lower-case). -Blockly.Msg.TEXT_CHANGECASE_HELPURL = 'https://github.com/google/blockly/wiki/Text#adjusting-text-case'; -/// tooltip - Describes a block to adjust the case of letters. For more information on this block, -/// see [https://github.com/google/blockly/wiki/Text#adjusting-text-case -/// https://github.com/google/blockly/wiki/Text#adjusting-text-case]. -Blockly.Msg.TEXT_CHANGECASE_TOOLTIP = 'Return a copy of the text in a different case.'; -/// block text - Indicates that all of the letters in the following piece of text should be -/// capitalized. If your language does not use case, you may indicate that this is not -/// applicable to your language. For more information on this block, see -/// [https://github.com/google/blockly/wiki/Text#adjusting-text-case -/// https://github.com/google/blockly/wiki/Text#adjusting-text-case]. -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE = 'to UPPER CASE'; -/// block text - Indicates that all of the letters in the following piece of text should be converted to lower-case. If your language does not use case, you may indicate that this is not applicable to your language. For more information on this block, see [https://github.com/google/blockly/wiki/Text#adjusting-text-case https://github.com/google/blockly/wiki/Text#adjusting-text-case]. -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE = 'to lower case'; -/// block text - Indicates that the first letter of each of the following words should be capitalized and the rest converted to lower-case. If your language does not use case, you may indicate that this is not applicable to your language. For more information on this block, see [https://github.com/google/blockly/wiki/Text#adjusting-text-case https://github.com/google/blockly/wiki/Text#adjusting-text-case]. -Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE = 'to Title Case'; - -/// url - Information about trimming (removing) text off the beginning and ends of pieces of text. -Blockly.Msg.TEXT_TRIM_HELPURL = 'https://github.com/google/blockly/wiki/Text#trimming-removing-spaces'; -/// tooltip - See [https://github.com/google/blockly/wiki/Text#trimming-removing-spaces -/// https://github.com/google/blockly/wiki/Text#trimming-removing-spaces]. -Blockly.Msg.TEXT_TRIM_TOOLTIP = 'Return a copy of the text with spaces removed from one or both ends.'; -/// dropdown - Removes spaces from the beginning and end of a piece of text. See -/// [https://github.com/google/blockly/wiki/Text#trimming-removing-spaces -/// https://github.com/google/blockly/wiki/Text#trimming-removing-spaces]. Note that neither -/// this nor the other options modify the original piece of text (that follows); -/// the block just returns a version of the text without the specified spaces. -Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH = 'trim spaces from both sides of'; -/// dropdown - Removes spaces from the beginning of a piece of text. See -/// [https://github.com/google/blockly/wiki/Text#trimming-removing-spaces -/// https://github.com/google/blockly/wiki/Text#trimming-removing-spaces]. -/// Note that in right-to-left scripts, this will remove spaces from the right side. -Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT = 'trim spaces from left side of'; -/// dropdown - Removes spaces from the end of a piece of text. See -/// [https://github.com/google/blockly/wiki/Text#trimming-removing-spaces -/// https://github.com/google/blockly/wiki/Text#trimming-removing-spaces]. -/// Note that in right-to-left scripts, this will remove spaces from the left side. -Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT = 'trim spaces from right side of'; - -/// url - Information about displaying text on computers. -Blockly.Msg.TEXT_PRINT_HELPURL = 'https://github.com/google/blockly/wiki/Text#printing-text'; -/// block text - Display the input on the screen. See -/// [https://github.com/google/blockly/wiki/Text#printing-text -/// https://github.com/google/blockly/wiki/Text#printing-text]. -/// \n\nParameters:\n* %1 - the value to print -Blockly.Msg.TEXT_PRINT_TITLE = 'print %1'; -/// tooltip - See [https://github.com/google/blockly/wiki/Text#printing-text -/// https://github.com/google/blockly/wiki/Text#printing-text]. -Blockly.Msg.TEXT_PRINT_TOOLTIP = 'Print the specified text, number or other value.'; -/// url - Information about getting text from users. -Blockly.Msg.TEXT_PROMPT_HELPURL = 'https://github.com/google/blockly/wiki/Text#getting-input-from-the-user'; -/// dropdown - Specifies that a piece of text should be requested from the user with -/// the following message. See [https://github.com/google/blockly/wiki/Text#printing-text -/// https://github.com/google/blockly/wiki/Text#printing-text]. -Blockly.Msg.TEXT_PROMPT_TYPE_TEXT = 'prompt for text with message'; -/// dropdown - Specifies that a number should be requested from the user with the -/// following message. See [https://github.com/google/blockly/wiki/Text#printing-text -/// https://github.com/google/blockly/wiki/Text#printing-text]. -Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER = 'prompt for number with message'; -/// dropdown - Precedes the message with which the user should be prompted for -/// a number. See [https://github.com/google/blockly/wiki/Text#printing-text -/// https://github.com/google/blockly/wiki/Text#printing-text]. -Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER = 'Prompt for user for a number.'; -/// dropdown - Precedes the message with which the user should be prompted for some text. -/// See [https://github.com/google/blockly/wiki/Text#printing-text -/// https://github.com/google/blockly/wiki/Text#printing-text]. -Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT = 'Prompt for user for some text.'; - -// Lists Blocks. -/// url - Information on empty lists. -Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL = 'https://github.com/google/blockly/wiki/Lists#create-empty-list'; -/// block text - See [https://github.com/google/blockly/wiki/Lists#create-empty-list https://github.com/google/blockly/wiki/Lists#create-empty-list]. -Blockly.Msg.LISTS_CREATE_EMPTY_TITLE = 'create empty list'; -/// block text - See [https://github.com/google/blockly/wiki/Lists#create-empty-list https://github.com/google/blockly/wiki/Lists#create-empty-list]. -Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP = 'Returns a list, of length 0, containing no data records'; - -/// url - Information on building lists. -Blockly.Msg.LISTS_CREATE_WITH_HELPURL = 'https://github.com/google/blockly/wiki/Lists#create-list-with'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#create-list-with https://github.com/google/blockly/wiki/Lists#create-list-with]. -Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP = 'Create a list with any number of items.'; -/// block text - See [https://github.com/google/blockly/wiki/Lists#create-list-with https://github.com/google/blockly/wiki/Lists#create-list-with]. -Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH = 'create list with'; -/// block text - This appears in a sub-block when [https://github.com/google/blockly/wiki/Lists#changing-number-of-inputs changing the number of inputs in a ''''create list with'''' block].\n{{Identical|List}} -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD = 'list'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#changing-number-of-inputs https://github.com/google/blockly/wiki/Lists#changing-number-of-inputs]. -Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP = 'Add, remove, or reorder sections to reconfigure this list block.'; -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE = Blockly.Msg.VARIABLES_DEFAULT_NAME; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#changing-number-of-inputs https://github.com/google/blockly/wiki/Lists#changing-number-of-inputs]. -Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP = 'Add an item to the list.'; - -/// url - Information about [https://github.com/google/blockly/wiki/Lists#create-list-with creating a list with multiple copies of a single item]. -Blockly.Msg.LISTS_REPEAT_HELPURL = 'https://github.com/google/blockly/wiki/Lists#create-list-with'; -/// url - See [https://github.com/google/blockly/wiki/Lists#create-list-with creating a list with multiple copies of a single item]. -Blockly.Msg.LISTS_REPEAT_TOOLTIP = 'Creates a list consisting of the given value repeated the specified number of times.'; -/// block text - See [https://github.com/google/blockly/wiki/Lists#create-list-with -/// https://github.com/google/blockly/wiki/Lists#create-list-with]. -///\n\nParameters:\n* %1 - the item (text) to be repeated\n* %2 - the number of times to repeat it -Blockly.Msg.LISTS_REPEAT_TITLE = 'create list with item %1 repeated %2 times'; - -/// url - Information about how the length of a list is computed (i.e., by the total number of elements, not the number of different elements). -Blockly.Msg.LISTS_LENGTH_HELPURL = 'https://github.com/google/blockly/wiki/Lists#length-of'; -/// block text - See [https://github.com/google/blockly/wiki/Lists#length-of https://github.com/google/blockly/wiki/Lists#length-of]. -/// \n\nParameters:\n* %1 - the list whose length is desired -Blockly.Msg.LISTS_LENGTH_TITLE = 'length of %1'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#length-of https://github.com/google/blockly/wiki/Lists#length-of Blockly:Lists:length of]. -Blockly.Msg.LISTS_LENGTH_TOOLTIP = 'Returns the length of a list.'; - -/// url - See [https://github.com/google/blockly/wiki/Lists#is-empty https://github.com/google/blockly/wiki/Lists#is-empty]. -Blockly.Msg.LISTS_ISEMPTY_HELPURL = 'https://github.com/google/blockly/wiki/Lists#is-empty'; -/// block text - See [https://github.com/google/blockly/wiki/Lists#is-empty -/// https://github.com/google/blockly/wiki/Lists#is-empty]. -/// \n\nParameters:\n* %1 - the list to test -Blockly.Msg.LISTS_ISEMPTY_TITLE = '%1 is empty'; -/// block tooltip - See [https://github.com/google/blockly/wiki/Lists#is-empty -/// https://github.com/google/blockly/wiki/Lists#is-empty]. -Blockly.Msg.LISTS_ISEMPTY_TOOLTIP = 'Returns true if the list is empty.'; - -/// block text - Title of blocks operating on [https://github.com/google/blockly/wiki/Lists lists]. -Blockly.Msg.LISTS_INLIST = 'in list'; - -/// url - See [https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list -/// https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list]. -Blockly.Msg.LISTS_INDEX_OF_HELPURL = 'https://github.com/google/blockly/wiki/Lists#getting-items-from-a-list'; -Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -/// dropdown - See [https://github.com/google/blockly/wiki/Lists#finding-items-in-a-list -/// Lists#finding-items-in-a-list]. -/// [[File:Blockly-list-find.png]] -Blockly.Msg.LISTS_INDEX_OF_FIRST = 'find first occurrence of item'; -/// dropdown - See [https://github.com/google/blockly/wiki/Lists#finding-items-in-a-list -/// https://github.com/google/blockly/wiki/Lists#finding-items-in-a-list]. -/// [[File:Blockly-list-find.png]] -Blockly.Msg.LISTS_INDEX_OF_LAST = 'find last occurrence of item'; -/// tooltip - %1 will be replaced by either the number 0 or -1 depending on the indexing mode. See [https://github.com/google/blockly/wiki/Lists#finding-items-in-a-list -/// https://github.com/google/blockly/wiki/Lists#finding-items-in-a-list]. -/// [[File:Blockly-list-find.png]] -Blockly.Msg.LISTS_INDEX_OF_TOOLTIP = 'Returns the index of the first/last occurrence of the item in the list. Returns %1 if item is not found.'; - -Blockly.Msg.LISTS_GET_INDEX_HELPURL = Blockly.Msg.LISTS_INDEX_OF_HELPURL; -/// dropdown - Indicates that the user wishes to -/// [https://github.com/google/blockly/wiki/Lists#getting-a-single-item -/// get an item from a list] without removing it from the list. -Blockly.Msg.LISTS_GET_INDEX_GET = 'get'; -/// dropdown - Indicates that the user wishes to -/// [https://github.com/google/blockly/wiki/Lists#getting-a-single-item -/// get and remove an item from a list], as opposed to merely getting -/// it without modifying the list. -Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE = 'get and remove'; -/// dropdown - Indicates that the user wishes to -/// [https://github.com/google/blockly/wiki/Lists#removing-an-item -/// remove an item from a list].\n{{Identical|Remove}} -Blockly.Msg.LISTS_GET_INDEX_REMOVE = 'remove'; -/// dropdown - Indicates that an index relative to the front of the list should be used to -/// [https://github.com/google/blockly/wiki/Lists#getting-a-single-item get and/or remove -/// an item from a list]. Note: If {{msg-Blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will -/// automatically appear ''after'' this number (and any other ordinal numbers on this block). -/// See [[Translating:Blockly#Ordinal_numbers]] for more information on ordinal numbers in Blockly. -/// [[File:Blockly-list-get-item.png]] -Blockly.Msg.LISTS_GET_INDEX_FROM_START = '#'; -/// dropdown - Indicates that an index relative to the end of the list should be used -/// to [https://github.com/google/blockly/wiki/Lists#getting-a-single-item access an item in a list]. -/// [[File:Blockly-list-get-item.png]] -Blockly.Msg.LISTS_GET_INDEX_FROM_END = '# from end'; -/// dropdown - Indicates that the '''first''' item should be -/// [https://github.com/google/blockly/wiki/Lists#getting-a-single-item accessed in a list]. -/// [[File:Blockly-list-get-item.png]] -Blockly.Msg.LISTS_GET_INDEX_FIRST = 'first'; -/// dropdown - Indicates that the '''last''' item should be -/// [https://github.com/google/blockly/wiki/Lists#getting-a-single-item accessed in a list]. -/// [[File:Blockly-list-get-item.png]] -Blockly.Msg.LISTS_GET_INDEX_LAST = 'last'; -/// dropdown - Indicates that a '''random''' item should be -/// [https://github.com/google/blockly/wiki/Lists#getting-a-single-item accessed in a list]. -/// [[File:Blockly-list-get-item.png]] -Blockly.Msg.LISTS_GET_INDEX_RANDOM = 'random'; -/// block text - Text that should go after the rightmost block/dropdown when -/// [https://github.com/google/blockly/wiki/Lists#getting-a-single-item -/// accessing an item from a list]. In most languages, this will be the empty string. -/// [[File:Blockly-list-get-item.png]] -Blockly.Msg.LISTS_GET_INDEX_TAIL = ''; -Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -/// tooltip - Indicates the ordinal number that the first item in a list is referenced by. %1 will be replaced by either "#0" or "#1" depending on the indexing mode. -Blockly.Msg.LISTS_INDEX_FROM_START_TOOLTIP = '%1 is the first item.'; -/// tooltip - Indicates the ordinal number that the last item in a list is referenced by. %1 will be replaced by either "#0" or "#1" depending on the indexing mode. -Blockly.Msg.LISTS_INDEX_FROM_END_TOOLTIP = '%1 is the last item.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for more information. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FROM = 'Returns the item at the specified position in a list.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for more information. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_FIRST = 'Returns the first item in a list.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for more information. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_LAST = 'Returns the last item in a list.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for more information. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_RANDOM = 'Returns a random item in a list.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for '#' or '# from end'. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FROM = 'Removes and returns the item at the specified position in a list.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for 'first'. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_FIRST = 'Removes and returns the first item in a list.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for 'last'. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_LAST = 'Removes and returns the last item in a list.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for 'random'. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_GET_REMOVE_RANDOM = 'Removes and returns a random item in a list.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for '#' or '# from end'. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FROM = 'Removes the item at the specified position in a list.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for 'first'. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_FIRST = 'Removes the first item in a list.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for 'last'. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_LAST = 'Removes the last item in a list.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-and-removing-an-item] (for remove and return) and [https://github.com/google/blockly/wiki/Lists#getting-a-single-item] for 'random'. -Blockly.Msg.LISTS_GET_INDEX_TOOLTIP_REMOVE_RANDOM = 'Removes a random item in a list.'; -/// url - Information about putting items in lists. -Blockly.Msg.LISTS_SET_INDEX_HELPURL = 'https://github.com/google/blockly/wiki/Lists#in-list--set'; -Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -/// block text - [https://github.com/google/blockly/wiki/Lists#in-list--set -/// Replaces an item in a list]. -/// [[File:Blockly-in-list-set-insert.png]] -Blockly.Msg.LISTS_SET_INDEX_SET = 'set'; -/// block text - [https://github.com/google/blockly/wiki/Lists#in-list--insert-at -/// Inserts an item into a list]. -/// [[File:Blockly-in-list-set-insert.png]] -Blockly.Msg.LISTS_SET_INDEX_INSERT = 'insert at'; -/// block text - The word(s) after the position in the list and before the item to be set/inserted. -/// [[File:Blockly-in-list-set-insert.png]] -Blockly.Msg.LISTS_SET_INDEX_INPUT_TO = 'as'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the "get" block, the idea is the same for the "set" block). -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FROM = 'Sets the item at the specified position in a list.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the "get" block, the idea is the same for the "set" block). -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_FIRST = 'Sets the first item in a list.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the "get" block, the idea is the same for the "set" block). -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_LAST = 'Sets the last item in a list.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the "get" block, the idea is the same for the "set" block). -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_SET_RANDOM = 'Sets a random item in a list.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the "get" block, the idea is the same for the "insert" block). -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FROM = 'Inserts the item at the specified position in a list.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the "get" block, the idea is the same for the "insert" block). -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_FIRST = 'Inserts the item at the start of a list.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the "get" block, the idea is the same for the "insert" block). -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_LAST = 'Append the item to the end of a list.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-single-item} (even though the page describes the "get" block, the idea is the same for the "insert" block). -Blockly.Msg.LISTS_SET_INDEX_TOOLTIP_INSERT_RANDOM = 'Inserts the item randomly in a list.'; - -/// url - Information describing extracting a sublist from an existing list. -Blockly.Msg.LISTS_GET_SUBLIST_HELPURL = 'https://github.com/google/blockly/wiki/Lists#getting-a-sublist'; -Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST = Blockly.Msg.LISTS_INLIST; -/// dropdown - Indicates that an index relative to the front of the list should be used -/// to specify the beginning of the range from which to -/// [https://github.com/google/blockly/wiki/Lists#getting-a-sublist get a sublist]. -/// [[File:Blockly-get-sublist.png]] -/// Note: If {{msg-Blockly|ORDINAL_NUMBER_SUFFIX}} is defined, it will -/// automatically appear ''after'' this number (and any other ordinal numbers on this block). -/// See [[Translating:Blockly#Ordinal_numbers]] for more information on ordinal numbers in Blockly. -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START = 'get sub-list from #'; -/// dropdown - Indicates that an index relative to the end of the list should be used -/// to specify the beginning of the range from which to -/// [https://github.com/google/blockly/wiki/Lists#getting-a-sublist get a sublist]. -Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END = 'get sub-list from # from end'; -/// dropdown - Indicates that the -/// [https://github.com/google/blockly/wiki/Lists#getting-a-sublist sublist to extract] -/// should begin with the list's first item. -Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST = 'get sub-list from first'; -/// dropdown - Indicates that an index relative to the front of the list should be -/// used to specify the end of the range from which to -/// [https://github.com/google/blockly/wiki/Lists#getting-a-sublist get a sublist]. -/// [[File:Blockly-get-sublist.png]] -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START = 'to #'; -/// dropdown - Indicates that an index relative to the end of the list should be -/// used to specify the end of the range from which to -/// [https://github.com/google/blockly/wiki/Lists#getting-a-sublist get a sublist]. -/// [[File:Blockly-get-sublist.png]] -Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END = 'to # from end'; -/// dropdown - Indicates that the '''last''' item in the given list should be -/// [https://github.com/google/blockly/wiki/Lists#getting-a-sublist the end -/// of the selected sublist]. -/// [[File:Blockly-get-sublist.png]] -Blockly.Msg.LISTS_GET_SUBLIST_END_LAST = 'to last'; -/// block text - This appears in the rightmost position ("tail") of the -/// sublist block, as described at -/// [https://github.com/google/blockly/wiki/Lists#getting-a-sublist -/// https://github.com/google/blockly/wiki/Lists#getting-a-sublist]. -/// In English and most other languages, this is the empty string. -/// [[File:Blockly-get-sublist.png]] -Blockly.Msg.LISTS_GET_SUBLIST_TAIL = ''; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#getting-a-sublist -/// https://github.com/google/blockly/wiki/Lists#getting-a-sublist] for more information. -/// [[File:Blockly-get-sublist.png]] -Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP = 'Creates a copy of the specified portion of a list.'; - -/// url - Information describing sorting a list. -Blockly.Msg.LISTS_SORT_HELPURL = 'https://github.com/google/blockly/wiki/Lists#sorting-a-list'; -/// Sort as type %1 (numeric or alphabetic) in order %2 (ascending or descending) a list of items %3.\n{{Identical|Sort}} -Blockly.Msg.LISTS_SORT_TITLE = 'sort %1 %2 %3'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#sorting-a-list]. -Blockly.Msg.LISTS_SORT_TOOLTIP = 'Sort a copy of a list.'; -/// sorting order or direction from low to high value for numeric, or A-Z for alphabetic.\n{{Identical|Ascending}} -Blockly.Msg.LISTS_SORT_ORDER_ASCENDING = 'ascending'; -/// sorting order or direction from high to low value for numeric, or Z-A for alphabetic.\n{{Identical|Descending}} -Blockly.Msg.LISTS_SORT_ORDER_DESCENDING = 'descending'; -/// sort by treating each item as a number. -Blockly.Msg.LISTS_SORT_TYPE_NUMERIC = 'numeric'; -/// sort by treating each item alphabetically, case-sensitive. -Blockly.Msg.LISTS_SORT_TYPE_TEXT = 'alphabetic'; -/// sort by treating each item alphabetically, ignoring differences in case. -Blockly.Msg.LISTS_SORT_TYPE_IGNORECASE = 'alphabetic, ignore case'; - -/// url - Information describing splitting text into a list, or joining a list into text. -Blockly.Msg.LISTS_SPLIT_HELPURL = 'https://github.com/google/blockly/wiki/Lists#splitting-strings-and-joining-lists'; -/// dropdown - Indicates that text will be split up into a list (e.g. "a-b-c" -> ["a", "b", "c"]). -Blockly.Msg.LISTS_SPLIT_LIST_FROM_TEXT = 'make list from text'; -/// dropdown - Indicates that a list will be joined together to form text (e.g. ["a", "b", "c"] -> "a-b-c"). -Blockly.Msg.LISTS_SPLIT_TEXT_FROM_LIST = 'make text from list'; -/// block text - Prompts for a letter to be used as a separator when splitting or joining text. -Blockly.Msg.LISTS_SPLIT_WITH_DELIMITER = 'with delimiter'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#make-list-from-text -/// https://github.com/google/blockly/wiki/Lists#make-list-from-text] for more information. -Blockly.Msg.LISTS_SPLIT_TOOLTIP_SPLIT = 'Split text into a list of texts, breaking at each delimiter.'; -/// tooltip - See [https://github.com/google/blockly/wiki/Lists#make-text-from-list -/// https://github.com/google/blockly/wiki/Lists#make-text-from-list] for more information. -Blockly.Msg.LISTS_SPLIT_TOOLTIP_JOIN = 'Join a list of texts into one text, separated by a delimiter.'; - -/// grammar - Text that follows an ordinal number (a number that indicates -/// position relative to other numbers). In most languages, such text appears -/// before the number, so this should be blank. An exception is Hungarian. -/// See [[Translating:Blockly#Ordinal_numbers]] for more information. -Blockly.Msg.ORDINAL_NUMBER_SUFFIX = ''; - -// Variables Blocks. -/// url - Information about ''variables'' in computer programming. Consider using your language's translation of [https://en.wikipedia.org/wiki/Variable_(computer_science) https://en.wikipedia.org/wiki/Variable_(computer_science)], if it exists. -Blockly.Msg.VARIABLES_GET_HELPURL = 'https://github.com/google/blockly/wiki/Variables#get'; -/// tooltip - This gets the value of the named variable without modifying it. -Blockly.Msg.VARIABLES_GET_TOOLTIP = 'Returns the value of this variable.'; -/// context menu - Selecting this creates a block to set (change) the value of this variable. -/// \n\nParameters:\n* %1 - the name of the variable. -Blockly.Msg.VARIABLES_GET_CREATE_SET = 'Create "set %1"'; - -/// url - Information about ''variables'' in computer programming. Consider using your language's translation of [https://en.wikipedia.org/wiki/Variable_(computer_science) https://en.wikipedia.org/wiki/Variable_(computer_science)], if it exists. -Blockly.Msg.VARIABLES_SET_HELPURL = 'https://github.com/google/blockly/wiki/Variables#set'; -/// block text - Change the value of a mathematical variable: '''set [the value of] x to 7'''.\n\nParameters:\n* %1 - the name of the variable.\n* %2 - the value to be assigned. -Blockly.Msg.VARIABLES_SET = 'set %1 to %2'; -/// tooltip - This initializes or changes the value of the named variable. -Blockly.Msg.VARIABLES_SET_TOOLTIP = 'Sets this variable to be equal to the input.'; -/// context menu - Selecting this creates a block to get (change) the value of -/// this variable.\n\nParameters:\n* %1 - the name of the variable. -Blockly.Msg.VARIABLES_SET_CREATE_GET = 'Create "get %1"'; - -// Procedures Blocks. -/// url - Information about defining [https://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that do not have return values. -Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL = 'https://en.wikipedia.org/wiki/Procedure_%28computer_science%29'; -/// block text - This precedes the name of the function when defining it. See -/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#c84aoc this sample -/// function definition]. -Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE = 'to'; -/// default name - This acts as a placeholder for the name of a function on a -/// function definition block, as shown on -/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#w7cfju this block]. -/// The user will replace it with the function's name. -Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE = 'do something'; -/// block text - This precedes the list of parameters on a function's defiition block. See -/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#voztpd this sample -/// function with parameters]. -Blockly.Msg.PROCEDURES_BEFORE_PARAMS = 'with:'; -/// block text - This precedes the list of parameters on a function's caller block. See -/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#voztpd this sample -/// function with parameters]. -Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS = 'with:'; -/// block text - This appears next to the function's "body", the blocks that should be -/// run when the function is called, as shown in -/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#voztpd this sample -/// function definition]. -Blockly.Msg.PROCEDURES_DEFNORETURN_DO = ''; -/// tooltip -Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP = 'Creates a function with no output.'; -/// Placeholder text that the user is encouraged to replace with a description of what their function does. -Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT = 'Describe this function...'; -/// url - Information about defining [https://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that have return values. -Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL = 'https://en.wikipedia.org/wiki/Procedure_%28computer_science%29'; -Blockly.Msg.PROCEDURES_DEFRETURN_TITLE = Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE; -Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE = Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE; -Blockly.Msg.PROCEDURES_DEFRETURN_DO = Blockly.Msg.PROCEDURES_DEFNORETURN_DO; -Blockly.Msg.PROCEDURES_DEFRETURN_COMMENT = Blockly.Msg.PROCEDURES_DEFNORETURN_COMMENT; -/// block text - This imperative or infinite verb precedes the value that is used as the return value -/// (output) of this function. See -/// [https://blockly-demo.appspot.com/static/apps/code/index.html?lang=en#6ot5y5 this sample -/// function that returns a value]. -Blockly.Msg.PROCEDURES_DEFRETURN_RETURN = 'return'; -/// tooltip -Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP = 'Creates a function with an output.'; -/// Label for a checkbox that controls if statements are allowed in a function. -Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS = 'allow statements'; - -/// alert - The user has created a function with two parameters that have the same name. Every parameter must have a different name. -Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING = 'Warning: This function has duplicate parameters.'; - -/// url - Information about calling [https://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that do not return values. -Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL = 'https://en.wikipedia.org/wiki/Procedure_%28computer_science%29'; -/// tooltip - This block causes the body (blocks inside) of the named function definition to be run. -Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP = 'Run the user-defined function "%1".'; - -/// url - Information about calling [https://en.wikipedia.org/wiki/Procedure_(computer_science) functions] that return values. -Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL = 'https://en.wikipedia.org/wiki/Procedure_%28computer_science%29'; -/// tooltip - This block causes the body (blocks inside) of the named function definition to be run.\n\nParameters:\n* %1 - the name of the function. -Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP = 'Run the user-defined function "%1" and use its output.'; - -/// block text - This text appears on a block in a window that appears when the user clicks -/// on the plus sign or star on a function definition block. It refers to the set of parameters -/// (referred to by the simpler term "inputs") to the function. See -/// [[Translating:Blockly#function_definitions]]. -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE = 'inputs'; -/// tooltip -Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP = 'Add, remove, or reorder inputs to this function.'; -/// block text - This text appears on a block in a window that appears when the user clicks -/// on the plus sign or star on a function definition block]. It appears on the block for -/// adding an individual parameter (referred to by the simpler term "inputs") to the function. -/// See [[Translating:Blockly#function_definitions]]. -Blockly.Msg.PROCEDURES_MUTATORARG_TITLE = 'input name:'; -/// tooltip -Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP = 'Add an input to the function.'; - -/// context menu - This appears on the context menu for function calls. Selecting -/// it causes the corresponding function definition to be highlighted (as shown at -/// [[Translating:Blockly#context_menus]]. -Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF = 'Highlight function definition'; -/// context menu - This appears on the context menu for function definitions. -/// Selecting it creates a block to call the function.\n\nParameters:\n* %1 - the name of the function.\n{{Identical|Create}} -Blockly.Msg.PROCEDURES_CREATE_DO = 'Create "%1"'; - -/// tooltip - If the first value is true, this causes the second value to be returned -/// immediately from the enclosing function. -Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP = 'If a value is true, then return a second value.'; -/// url - Information about guard clauses. -Blockly.Msg.PROCEDURES_IFRETURN_HELPURL = 'http://c2.com/cgi/wiki?GuardClause'; -/// warning - This appears if the user tries to use this block outside of a function definition. -Blockly.Msg.PROCEDURES_IFRETURN_WARNING = 'Warning: This block may be used only within a function definition.'; diff --git a/backend/_pv_1_3_5/static/blockly/php_compressed.js b/backend/_pv_1_3_5/static/blockly/php_compressed.js deleted file mode 100755 index f77843760..000000000 --- a/backend/_pv_1_3_5/static/blockly/php_compressed.js +++ /dev/null @@ -1,84 +0,0 @@ -// Do not edit this file; automatically generated by build.py. -'use strict'; - - -// Copyright 2015 Google Inc. Apache License 2.0 -Blockly.PHP=new Blockly.Generator("PHP");Blockly.PHP.addReservedWords("__halt_compiler,abstract,and,array,as,break,callable,case,catch,class,clone,const,continue,declare,default,die,do,echo,else,elseif,empty,enddeclare,endfor,endforeach,endif,endswitch,endwhile,eval,exit,extends,final,for,foreach,function,global,goto,if,implements,include,include_once,instanceof,insteadof,interface,isset,list,namespace,new,or,print,private,protected,public,require,require_once,return,static,switch,throw,trait,try,unset,use,var,while,xor,PHP_VERSION,PHP_MAJOR_VERSION,PHP_MINOR_VERSION,PHP_RELEASE_VERSION,PHP_VERSION_ID,PHP_EXTRA_VERSION,PHP_ZTS,PHP_DEBUG,PHP_MAXPATHLEN,PHP_OS,PHP_SAPI,PHP_EOL,PHP_INT_MAX,PHP_INT_SIZE,DEFAULT_INCLUDE_PATH,PEAR_INSTALL_DIR,PEAR_EXTENSION_DIR,PHP_EXTENSION_DIR,PHP_PREFIX,PHP_BINDIR,PHP_BINARY,PHP_MANDIR,PHP_LIBDIR,PHP_DATADIR,PHP_SYSCONFDIR,PHP_LOCALSTATEDIR,PHP_CONFIG_FILE_PATH,PHP_CONFIG_FILE_SCAN_DIR,PHP_SHLIB_SUFFIX,E_ERROR,E_WARNING,E_PARSE,E_NOTICE,E_CORE_ERROR,E_CORE_WARNING,E_COMPILE_ERROR,E_COMPILE_WARNING,E_USER_ERROR,E_USER_WARNING,E_USER_NOTICE,E_DEPRECATED,E_USER_DEPRECATED,E_ALL,E_STRICT,__COMPILER_HALT_OFFSET__,TRUE,FALSE,NULL,__CLASS__,__DIR__,__FILE__,__FUNCTION__,__LINE__,__METHOD__,__NAMESPACE__,__TRAIT__"); -Blockly.PHP.ORDER_ATOMIC=0;Blockly.PHP.ORDER_CLONE=1;Blockly.PHP.ORDER_NEW=1;Blockly.PHP.ORDER_MEMBER=2.1;Blockly.PHP.ORDER_FUNCTION_CALL=2.2;Blockly.PHP.ORDER_POWER=3;Blockly.PHP.ORDER_INCREMENT=4;Blockly.PHP.ORDER_DECREMENT=4;Blockly.PHP.ORDER_BITWISE_NOT=4;Blockly.PHP.ORDER_CAST=4;Blockly.PHP.ORDER_SUPPRESS_ERROR=4;Blockly.PHP.ORDER_INSTANCEOF=5;Blockly.PHP.ORDER_LOGICAL_NOT=6;Blockly.PHP.ORDER_UNARY_PLUS=7.1;Blockly.PHP.ORDER_UNARY_NEGATION=7.2;Blockly.PHP.ORDER_MULTIPLICATION=8.1; -Blockly.PHP.ORDER_DIVISION=8.2;Blockly.PHP.ORDER_MODULUS=8.3;Blockly.PHP.ORDER_ADDITION=9.1;Blockly.PHP.ORDER_SUBTRACTION=9.2;Blockly.PHP.ORDER_STRING_CONCAT=9.3;Blockly.PHP.ORDER_BITWISE_SHIFT=10;Blockly.PHP.ORDER_RELATIONAL=11;Blockly.PHP.ORDER_EQUALITY=12;Blockly.PHP.ORDER_REFERENCE=13;Blockly.PHP.ORDER_BITWISE_AND=13;Blockly.PHP.ORDER_BITWISE_XOR=14;Blockly.PHP.ORDER_BITWISE_OR=15;Blockly.PHP.ORDER_LOGICAL_AND=16;Blockly.PHP.ORDER_LOGICAL_OR=17;Blockly.PHP.ORDER_IF_NULL=18; -Blockly.PHP.ORDER_CONDITIONAL=19;Blockly.PHP.ORDER_ASSIGNMENT=20;Blockly.PHP.ORDER_LOGICAL_AND_WEAK=21;Blockly.PHP.ORDER_LOGICAL_XOR=22;Blockly.PHP.ORDER_LOGICAL_OR_WEAK=23;Blockly.PHP.ORDER_COMMA=24;Blockly.PHP.ORDER_NONE=99; -Blockly.PHP.ORDER_OVERRIDES=[[Blockly.PHP.ORDER_MEMBER,Blockly.PHP.ORDER_FUNCTION_CALL],[Blockly.PHP.ORDER_MEMBER,Blockly.PHP.ORDER_MEMBER],[Blockly.PHP.ORDER_LOGICAL_NOT,Blockly.PHP.ORDER_LOGICAL_NOT],[Blockly.PHP.ORDER_MULTIPLICATION,Blockly.PHP.ORDER_MULTIPLICATION],[Blockly.PHP.ORDER_ADDITION,Blockly.PHP.ORDER_ADDITION],[Blockly.PHP.ORDER_LOGICAL_AND,Blockly.PHP.ORDER_LOGICAL_AND],[Blockly.PHP.ORDER_LOGICAL_OR,Blockly.PHP.ORDER_LOGICAL_OR]];Blockly.PHP.ONE_BASED_INDEXING=!0; -Blockly.PHP.init=function(a){Blockly.PHP.definitions_=Object.create(null);Blockly.PHP.functionNames_=Object.create(null);Blockly.PHP.variableDB_?Blockly.PHP.variableDB_.reset():Blockly.PHP.variableDB_=new Blockly.Names(Blockly.PHP.RESERVED_WORDS_,"$");var b=[];a=Blockly.Variables.allVariables(a);for(var c=0;cc?Blockly.PHP.valueToCode(a,b,Blockly.PHP.ORDER_SUBTRACTION)||g:d?Blockly.PHP.valueToCode(a,b,Blockly.PHP.ORDER_UNARY_NEGATION)||g:Blockly.PHP.valueToCode(a,b,e)||g;if(Blockly.isNumber(a))a=parseFloat(a)+c,d&&(a=-a);else{if(0c&& -(a=a+" - "+-c,f=Blockly.PHP.ORDER_SUBTRACTION);d&&(a=c?"-("+a+")":"-"+a,f=Blockly.PHP.ORDER_UNARY_NEGATION);f=Math.floor(f);e=Math.floor(e);f&&e>=f&&(a="("+a+")")}return a};Blockly.PHP.lists={};Blockly.PHP.lists_create_empty=function(a){return["array()",Blockly.PHP.ORDER_FUNCTION_CALL]};Blockly.PHP.lists_create_with=function(a){for(var b=Array(a.itemCount_),c=0;c "strnatcasecmp",',' "TEXT" => "strcmp",',' "IGNORE_CASE" => "strcasecmp"'," );"," $sortCmp = $sortCmpFuncs[$type];"," $list2 = $list;"," usort($list2, $sortCmp);", -" if ($direction == -1) {"," $list2 = array_reverse($list2);"," }"," return $list2;","}"])+"("+b+', "'+a+'", '+c+")",Blockly.PHP.ORDER_FUNCTION_CALL]};Blockly.PHP.lists_split=function(a){var b=Blockly.PHP.valueToCode(a,"INPUT",Blockly.PHP.ORDER_COMMA),c=Blockly.PHP.valueToCode(a,"DELIM",Blockly.PHP.ORDER_COMMA)||"''";a=a.getFieldValue("MODE");if("SPLIT"==a)b||(b="''"),a="explode";else if("JOIN"==a)b||(b="array()"),a="implode";else throw"Unknown mode: "+a;return[a+"("+c+", "+b+")",Blockly.PHP.ORDER_FUNCTION_CALL]};Blockly.PHP.math={};Blockly.PHP.math_number=function(a){a=parseFloat(a.getFieldValue("NUM"));Infinity==a?a="INF":-Infinity==a&&(a="-INF");return[a,Blockly.PHP.ORDER_ATOMIC]}; -Blockly.PHP.math_arithmetic=function(a){var b={ADD:[" + ",Blockly.PHP.ORDER_ADDITION],MINUS:[" - ",Blockly.PHP.ORDER_SUBTRACTION],MULTIPLY:[" * ",Blockly.PHP.ORDER_MULTIPLICATION],DIVIDE:[" / ",Blockly.PHP.ORDER_DIVISION],POWER:[" ** ",Blockly.PHP.ORDER_POWER]}[a.getFieldValue("OP")],c=b[0],b=b[1],d=Blockly.PHP.valueToCode(a,"A",b)||"0";a=Blockly.PHP.valueToCode(a,"B",b)||"0";return[d+c+a,b]}; -Blockly.PHP.math_single=function(a){var b=a.getFieldValue("OP"),c;if("NEG"==b)return a=Blockly.PHP.valueToCode(a,"NUM",Blockly.PHP.ORDER_UNARY_NEGATION)||"0","-"==a[0]&&(a=" "+a),["-"+a,Blockly.PHP.ORDER_UNARY_NEGATION];a="SIN"==b||"COS"==b||"TAN"==b?Blockly.PHP.valueToCode(a,"NUM",Blockly.PHP.ORDER_DIVISION)||"0":Blockly.PHP.valueToCode(a,"NUM",Blockly.PHP.ORDER_NONE)||"0";switch(b){case "ABS":c="abs("+a+")";break;case "ROOT":c="sqrt("+a+")";break;case "LN":c="log("+a+")";break;case "EXP":c="exp("+ -a+")";break;case "POW10":c="pow(10,"+a+")";break;case "ROUND":c="round("+a+")";break;case "ROUNDUP":c="ceil("+a+")";break;case "ROUNDDOWN":c="floor("+a+")";break;case "SIN":c="sin("+a+" / 180 * pi())";break;case "COS":c="cos("+a+" / 180 * pi())";break;case "TAN":c="tan("+a+" / 180 * pi())"}if(c)return[c,Blockly.PHP.ORDER_FUNCTION_CALL];switch(b){case "LOG10":c="log("+a+") / log(10)";break;case "ASIN":c="asin("+a+") / pi() * 180";break;case "ACOS":c="acos("+a+") / pi() * 180";break;case "ATAN":c="atan("+ -a+") / pi() * 180";break;default:throw"Unknown math operator: "+b;}return[c,Blockly.PHP.ORDER_DIVISION]};Blockly.PHP.math_constant=function(a){return{PI:["M_PI",Blockly.PHP.ORDER_ATOMIC],E:["M_E",Blockly.PHP.ORDER_ATOMIC],GOLDEN_RATIO:["(1 + sqrt(5)) / 2",Blockly.PHP.ORDER_DIVISION],SQRT2:["M_SQRT2",Blockly.PHP.ORDER_ATOMIC],SQRT1_2:["M_SQRT1_2",Blockly.PHP.ORDER_ATOMIC],INFINITY:["INF",Blockly.PHP.ORDER_ATOMIC]}[a.getFieldValue("CONSTANT")]}; -Blockly.PHP.math_number_property=function(a){var b=Blockly.PHP.valueToCode(a,"NUMBER_TO_CHECK",Blockly.PHP.ORDER_MODULUS)||"0",c=a.getFieldValue("PROPERTY"),d;if("PRIME"==c)return[Blockly.PHP.provideFunction_("math_isPrime",["function "+Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_+"($n) {"," // https://en.wikipedia.org/wiki/Primality_test#Naive_methods"," if ($n == 2 || $n == 3) {"," return true;"," }"," // False if n is NaN, negative, is 1, or not whole."," // And false if n is divisible by 2 or 3.", -" if (!is_numeric($n) || $n <= 1 || $n % 1 != 0 || $n % 2 == 0 || $n % 3 == 0) {"," return false;"," }"," // Check all the numbers of form 6k +/- 1, up to sqrt(n)."," for ($x = 6; $x <= sqrt($n) + 1; $x += 6) {"," if ($n % ($x - 1) == 0 || $n % ($x + 1) == 0) {"," return false;"," }"," }"," return true;","}"])+"("+b+")",Blockly.JavaScript.ORDER_FUNCTION_CALL];switch(c){case "EVEN":d=b+" % 2 == 0";break;case "ODD":d=b+" % 2 == 1";break;case "WHOLE":d="is_int("+b+")";break;case "POSITIVE":d= -b+" > 0";break;case "NEGATIVE":d=b+" < 0";break;case "DIVISIBLE_BY":a=Blockly.PHP.valueToCode(a,"DIVISOR",Blockly.PHP.ORDER_MODULUS)||"0",d=b+" % "+a+" == 0"}return[d,Blockly.PHP.ORDER_EQUALITY]};Blockly.PHP.math_change=function(a){var b=Blockly.PHP.valueToCode(a,"DELTA",Blockly.PHP.ORDER_ADDITION)||"0";return Blockly.PHP.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE)+" += "+b+";\n"};Blockly.PHP.math_round=Blockly.PHP.math_single;Blockly.PHP.math_trig=Blockly.PHP.math_single; -Blockly.PHP.math_on_list=function(a){var b=a.getFieldValue("OP");switch(b){case "SUM":a=Blockly.PHP.valueToCode(a,"LIST",Blockly.PHP.ORDER_FUNCTION_CALL)||"array()";a="array_sum("+a+")";break;case "MIN":a=Blockly.PHP.valueToCode(a,"LIST",Blockly.PHP.ORDER_FUNCTION_CALL)||"array()";a="min("+a+")";break;case "MAX":a=Blockly.PHP.valueToCode(a,"LIST",Blockly.PHP.ORDER_FUNCTION_CALL)||"array()";a="max("+a+")";break;case "AVERAGE":b=Blockly.PHP.provideFunction_("math_mean",["function "+Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_+ -"($myList) {"," return array_sum($myList) / count($myList);","}"]);a=Blockly.PHP.valueToCode(a,"LIST",Blockly.PHP.ORDER_NONE)||"array()";a=b+"("+a+")";break;case "MEDIAN":b=Blockly.PHP.provideFunction_("math_median",["function "+Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_+"($arr) {"," sort($arr,SORT_NUMERIC);"," return (count($arr) % 2) ? $arr[floor(count($arr)/2)] : "," ($arr[floor(count($arr)/2)] + $arr[floor(count($arr)/2) - 1]) / 2;","}"]);a=Blockly.PHP.valueToCode(a,"LIST",Blockly.PHP.ORDER_NONE)|| -"[]";a=b+"("+a+")";break;case "MODE":b=Blockly.PHP.provideFunction_("math_modes",["function "+Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_+"($values) {"," if (empty($values)) return array();"," $counts = array_count_values($values);"," arsort($counts); // Sort counts in descending order"," $modes = array_keys($counts, current($counts), true);"," return $modes;","}"]);a=Blockly.PHP.valueToCode(a,"LIST",Blockly.PHP.ORDER_NONE)||"[]";a=b+"("+a+")";break;case "STD_DEV":b=Blockly.PHP.provideFunction_("math_standard_deviation", -["function "+Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_+"($numbers) {"," $n = count($numbers);"," if (!$n) return null;"," $mean = array_sum($numbers) / count($numbers);"," foreach($numbers as $key => $num) $devs[$key] = pow($num - $mean, 2);"," return sqrt(array_sum($devs) / (count($devs) - 1));","}"]);a=Blockly.PHP.valueToCode(a,"LIST",Blockly.PHP.ORDER_NONE)||"[]";a=b+"("+a+")";break;case "RANDOM":b=Blockly.PHP.provideFunction_("math_random_list",["function "+Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_+ -"($list) {"," $x = rand(0, count($list)-1);"," return $list[$x];","}"]);a=Blockly.PHP.valueToCode(a,"LIST",Blockly.PHP.ORDER_NONE)||"[]";a=b+"("+a+")";break;default:throw"Unknown operator: "+b;}return[a,Blockly.PHP.ORDER_FUNCTION_CALL]};Blockly.PHP.math_modulo=function(a){var b=Blockly.PHP.valueToCode(a,"DIVIDEND",Blockly.PHP.ORDER_MODULUS)||"0";a=Blockly.PHP.valueToCode(a,"DIVISOR",Blockly.PHP.ORDER_MODULUS)||"0";return[b+" % "+a,Blockly.PHP.ORDER_MODULUS]}; -Blockly.PHP.math_constrain=function(a){var b=Blockly.PHP.valueToCode(a,"VALUE",Blockly.PHP.ORDER_COMMA)||"0",c=Blockly.PHP.valueToCode(a,"LOW",Blockly.PHP.ORDER_COMMA)||"0";a=Blockly.PHP.valueToCode(a,"HIGH",Blockly.PHP.ORDER_COMMA)||"Infinity";return["min(max("+b+", "+c+"), "+a+")",Blockly.PHP.ORDER_FUNCTION_CALL]}; -Blockly.PHP.math_random_int=function(a){var b=Blockly.PHP.valueToCode(a,"FROM",Blockly.PHP.ORDER_COMMA)||"0";a=Blockly.PHP.valueToCode(a,"TO",Blockly.PHP.ORDER_COMMA)||"0";return[Blockly.PHP.provideFunction_("math_random_int",["function "+Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_+"($a, $b) {"," if ($a > $b) {"," return rand($b, $a);"," }"," return rand($a, $b);","}"])+"("+b+", "+a+")",Blockly.PHP.ORDER_FUNCTION_CALL]}; -Blockly.PHP.math_random_float=function(a){return["(float)rand()/(float)getrandmax()",Blockly.PHP.ORDER_FUNCTION_CALL]};Blockly.PHP.variables={};Blockly.PHP.variables_get=function(a){return[Blockly.PHP.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE),Blockly.PHP.ORDER_ATOMIC]};Blockly.PHP.variables_set=function(a){var b=Blockly.PHP.valueToCode(a,"VALUE",Blockly.PHP.ORDER_ASSIGNMENT)||"0";return Blockly.PHP.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE)+" = "+b+";\n"};Blockly.PHP.colour={};Blockly.PHP.colour_picker=function(a){return["'"+a.getFieldValue("COLOUR")+"'",Blockly.PHP.ORDER_ATOMIC]};Blockly.PHP.colour_random=function(a){return[Blockly.PHP.provideFunction_("colour_random",["function "+Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_+"() {"," return '#' . str_pad(dechex(mt_rand(0, 0xFFFFFF)), 6, '0', STR_PAD_LEFT);","}"])+"()",Blockly.PHP.ORDER_FUNCTION_CALL]}; -Blockly.PHP.colour_rgb=function(a){var b=Blockly.PHP.valueToCode(a,"RED",Blockly.PHP.ORDER_COMMA)||0,c=Blockly.PHP.valueToCode(a,"GREEN",Blockly.PHP.ORDER_COMMA)||0;a=Blockly.PHP.valueToCode(a,"BLUE",Blockly.PHP.ORDER_COMMA)||0;return[Blockly.PHP.provideFunction_("colour_rgb",["function "+Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_+"($r, $g, $b) {"," $r = round(max(min($r, 100), 0) * 2.55);"," $g = round(max(min($g, 100), 0) * 2.55);"," $b = round(max(min($b, 100), 0) * 2.55);"," $hex = '#';"," $hex .= str_pad(dechex($r), 2, '0', STR_PAD_LEFT);", -" $hex .= str_pad(dechex($g), 2, '0', STR_PAD_LEFT);"," $hex .= str_pad(dechex($b), 2, '0', STR_PAD_LEFT);"," return $hex;","}"])+"("+b+", "+c+", "+a+")",Blockly.PHP.ORDER_FUNCTION_CALL]}; -Blockly.PHP.colour_blend=function(a){var b=Blockly.PHP.valueToCode(a,"COLOUR1",Blockly.PHP.ORDER_COMMA)||"'#000000'",c=Blockly.PHP.valueToCode(a,"COLOUR2",Blockly.PHP.ORDER_COMMA)||"'#000000'";a=Blockly.PHP.valueToCode(a,"RATIO",Blockly.PHP.ORDER_COMMA)||.5;return[Blockly.PHP.provideFunction_("colour_blend",["function "+Blockly.PHP.FUNCTION_NAME_PLACEHOLDER_+"($c1, $c2, $ratio) {"," $ratio = max(min($ratio, 1), 0);"," $r1 = hexdec(substr($c1, 1, 2));"," $g1 = hexdec(substr($c1, 3, 2));"," $b1 = hexdec(substr($c1, 5, 2));", -" $r2 = hexdec(substr($c2, 1, 2));"," $g2 = hexdec(substr($c2, 3, 2));"," $b2 = hexdec(substr($c2, 5, 2));"," $r = round($r1 * (1 - $ratio) + $r2 * $ratio);"," $g = round($g1 * (1 - $ratio) + $g2 * $ratio);"," $b = round($b1 * (1 - $ratio) + $b2 * $ratio);"," $hex = '#';"," $hex .= str_pad(dechex($r), 2, '0', STR_PAD_LEFT);"," $hex .= str_pad(dechex($g), 2, '0', STR_PAD_LEFT);"," $hex .= str_pad(dechex($b), 2, '0', STR_PAD_LEFT);"," return $hex;","}"])+"("+b+", "+c+", "+a+")",Blockly.PHP.ORDER_FUNCTION_CALL]};Blockly.PHP.procedures={}; -Blockly.PHP.procedures_defreturn=function(a){for(var b=a.workspace.variableList,c=b.length-1;0<=c;c--){var d=b[c];-1==a.arguments_.indexOf(d)?b[c]=Blockly.PHP.variableDB_.getName(d,Blockly.Variables.NAME_TYPE):b.splice(c,1)}var b=b.length?" global "+b.join(", ")+";\n":"",d=Blockly.PHP.variableDB_.getName(a.getFieldValue("NAME"),Blockly.Procedures.NAME_TYPE),e=Blockly.PHP.statementToCode(a,"STACK");Blockly.PHP.STATEMENT_PREFIX&&(e=Blockly.PHP.prefixLines(Blockly.PHP.STATEMENT_PREFIX.replace(/%1/g,"'"+ -a.id+"'"),Blockly.PHP.INDENT)+e);Blockly.PHP.INFINITE_LOOP_TRAP&&(e=Blockly.PHP.INFINITE_LOOP_TRAP.replace(/%1/g,"'"+a.id+"'")+e);var g=Blockly.PHP.valueToCode(a,"RETURN",Blockly.PHP.ORDER_NONE)||"";g&&(g=" return "+g+";\n");for(var f=[],c=0;c= ")+d+"; "+b;b=Math.abs(parseFloat(e));a=(1==b?a+(f?"++":"--"):a+((f?" += ":" -= ")+b))+(") {\n"+g+"}\n")}else a="",f=c,c.match(/^\w+$/)||Blockly.isNumber(c)||(f=Blockly.PHP.variableDB_.getDistinctName(b+"_start",Blockly.Variables.NAME_TYPE),a+=f+" = "+c+";\n"),c=d,d.match(/^\w+$/)||Blockly.isNumber(d)||(c=Blockly.PHP.variableDB_.getDistinctName(b+"_end",Blockly.Variables.NAME_TYPE),a+=c+" = "+d+";\n"),d=Blockly.PHP.variableDB_.getDistinctName(b+"_inc",Blockly.Variables.NAME_TYPE), -a+=d+" = ",a=Blockly.isNumber(e)?a+(Math.abs(e)+";\n"):a+("abs("+e+");\n"),a=a+("if ("+f+" > "+c+") {\n")+(Blockly.PHP.INDENT+d+" = -"+d+";\n"),a+="}\n",a+="for ("+b+" = "+f+"; "+d+" >= 0 ? "+b+" <= "+c+" : "+b+" >= "+c+"; "+b+" += "+d+") {\n"+g+"}\n";return a}; -Blockly.PHP.controls_forEach=function(a){var b=Blockly.PHP.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE),c=Blockly.PHP.valueToCode(a,"LIST",Blockly.PHP.ORDER_ASSIGNMENT)||"[]",d=Blockly.PHP.statementToCode(a,"DO"),d=Blockly.PHP.addLoopTrap(d,a.id);return""+("foreach ("+c+" as "+b+") {\n"+d+"}\n")}; -Blockly.PHP.controls_flow_statements=function(a){switch(a.getFieldValue("FLOW")){case "BREAK":return"break;\n";case "CONTINUE":return"continue;\n"}throw"Unknown flow statement.";};Blockly.PHP.logic={};Blockly.PHP.controls_if=function(a){for(var b=0,c=Blockly.PHP.valueToCode(a,"IF"+b,Blockly.PHP.ORDER_NONE)||"false",d=Blockly.PHP.statementToCode(a,"DO"+b),e="if ("+c+") {\n"+d+"}",b=1;b<=a.elseifCount_;b++)c=Blockly.PHP.valueToCode(a,"IF"+b,Blockly.PHP.ORDER_NONE)||"false",d=Blockly.PHP.statementToCode(a,"DO"+b),e+=" else if ("+c+") {\n"+d+"}";a.elseCount_&&(d=Blockly.PHP.statementToCode(a,"ELSE"),e+=" else {\n"+d+"}");return e+"\n"}; -Blockly.PHP.logic_compare=function(a){var b={EQ:"==",NEQ:"!=",LT:"<",LTE:"<=",GT:">",GTE:">="}[a.getFieldValue("OP")],c="=="==b||"!="==b?Blockly.PHP.ORDER_EQUALITY:Blockly.PHP.ORDER_RELATIONAL,d=Blockly.PHP.valueToCode(a,"A",c)||"0";a=Blockly.PHP.valueToCode(a,"B",c)||"0";return[d+" "+b+" "+a,c]}; -Blockly.PHP.logic_operation=function(a){var b="AND"==a.getFieldValue("OP")?"&&":"||",c="&&"==b?Blockly.PHP.ORDER_LOGICAL_AND:Blockly.PHP.ORDER_LOGICAL_OR,d=Blockly.PHP.valueToCode(a,"A",c);a=Blockly.PHP.valueToCode(a,"B",c);if(d||a){var e="&&"==b?"true":"false";d||(d=e);a||(a=e)}else a=d="false";return[d+" "+b+" "+a,c]};Blockly.PHP.logic_negate=function(a){var b=Blockly.PHP.ORDER_LOGICAL_NOT;return["!"+(Blockly.PHP.valueToCode(a,"BOOL",b)||"true"),b]}; -Blockly.PHP.logic_boolean=function(a){return["TRUE"==a.getFieldValue("BOOL")?"true":"false",Blockly.PHP.ORDER_ATOMIC]};Blockly.PHP.logic_null=function(a){return["null",Blockly.PHP.ORDER_ATOMIC]};Blockly.PHP.logic_ternary=function(a){var b=Blockly.PHP.valueToCode(a,"IF",Blockly.PHP.ORDER_CONDITIONAL)||"false",c=Blockly.PHP.valueToCode(a,"THEN",Blockly.PHP.ORDER_CONDITIONAL)||"null";a=Blockly.PHP.valueToCode(a,"ELSE",Blockly.PHP.ORDER_CONDITIONAL)||"null";return[b+" ? "+c+" : "+a,Blockly.PHP.ORDER_CONDITIONAL]}; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/blockly/python_compressed.js b/backend/_pv_1_3_5/static/blockly/python_compressed.js deleted file mode 100755 index d6231616a..000000000 --- a/backend/_pv_1_3_5/static/blockly/python_compressed.js +++ /dev/null @@ -1,79 +0,0 @@ -// Do not edit this file; automatically generated by build.py. -'use strict'; - - -// Copyright 2012 Google Inc. Apache License 2.0 -Blockly.Python=new Blockly.Generator("Python");Blockly.Python.addReservedWords("and,as,assert,break,class,continue,def,del,elif,else,except,exec,finally,for,from,global,if,import,in,is,lambda,not,or,pass,print,raise,return,try,while,with,yield,True,False,None,NotImplemented,Ellipsis,__debug__,quit,exit,copyright,license,credits,abs,divmod,input,open,staticmethod,all,enumerate,int,ord,str,any,eval,isinstance,pow,sum,basestring,execfile,issubclass,print,super,bin,file,iter,property,tuple,bool,filter,len,range,type,bytearray,float,list,raw_input,unichr,callable,format,locals,reduce,unicode,chr,frozenset,long,reload,vars,classmethod,getattr,map,repr,xrange,cmp,globals,max,reversed,zip,compile,hasattr,memoryview,round,__import__,complex,hash,min,set,apply,delattr,help,next,setattr,buffer,dict,hex,object,slice,coerce,dir,id,oct,sorted,intern"); -Blockly.Python.ORDER_ATOMIC=0;Blockly.Python.ORDER_COLLECTION=1;Blockly.Python.ORDER_STRING_CONVERSION=1;Blockly.Python.ORDER_MEMBER=2.1;Blockly.Python.ORDER_FUNCTION_CALL=2.2;Blockly.Python.ORDER_EXPONENTIATION=3;Blockly.Python.ORDER_UNARY_SIGN=4;Blockly.Python.ORDER_BITWISE_NOT=4;Blockly.Python.ORDER_MULTIPLICATIVE=5;Blockly.Python.ORDER_ADDITIVE=6;Blockly.Python.ORDER_BITWISE_SHIFT=7;Blockly.Python.ORDER_BITWISE_AND=8;Blockly.Python.ORDER_BITWISE_XOR=9;Blockly.Python.ORDER_BITWISE_OR=10; -Blockly.Python.ORDER_RELATIONAL=11;Blockly.Python.ORDER_LOGICAL_NOT=12;Blockly.Python.ORDER_LOGICAL_AND=13;Blockly.Python.ORDER_LOGICAL_OR=14;Blockly.Python.ORDER_CONDITIONAL=15;Blockly.Python.ORDER_LAMBDA=16;Blockly.Python.ORDER_NONE=99;Blockly.Python.ONE_BASED_INDEXING=!0; -Blockly.Python.ORDER_OVERRIDES=[[Blockly.Python.ORDER_FUNCTION_CALL,Blockly.Python.ORDER_MEMBER],[Blockly.Python.ORDER_FUNCTION_CALL,Blockly.Python.ORDER_FUNCTION_CALL],[Blockly.Python.ORDER_MEMBER,Blockly.Python.ORDER_MEMBER],[Blockly.Python.ORDER_MEMBER,Blockly.Python.ORDER_FUNCTION_CALL],[Blockly.Python.ORDER_LOGICAL_NOT,Blockly.Python.ORDER_LOGICAL_NOT],[Blockly.Python.ORDER_LOGICAL_AND,Blockly.Python.ORDER_LOGICAL_AND],[Blockly.Python.ORDER_LOGICAL_OR,Blockly.Python.ORDER_LOGICAL_OR]]; -Blockly.Python.init=function(a){Blockly.Python.PASS=this.INDENT+"pass\n";Blockly.Python.definitions_=Object.create(null);Blockly.Python.functionNames_=Object.create(null);Blockly.Python.variableDB_?Blockly.Python.variableDB_.reset():Blockly.Python.variableDB_=new Blockly.Names(Blockly.Python.RESERVED_WORDS_);var b=[];a=a.variableList;for(var c=0;cc?"int("+a+" - "+-c+")":"int("+a+")",d&&(a="-"+a));return a};Blockly.Python.lists={};Blockly.Python.lists_create_empty=function(a){return["[]",Blockly.Python.ORDER_ATOMIC]};Blockly.Python.lists_create_with=function(a){for(var b=Array(a.itemCount_),c=0;ca?Blockly.Python.ORDER_UNARY_SIGN:Blockly.Python.ORDER_ATOMIC;return[a,b]}; -Blockly.Python.math_arithmetic=function(a){var b={ADD:[" + ",Blockly.Python.ORDER_ADDITIVE],MINUS:[" - ",Blockly.Python.ORDER_ADDITIVE],MULTIPLY:[" * ",Blockly.Python.ORDER_MULTIPLICATIVE],DIVIDE:[" / ",Blockly.Python.ORDER_MULTIPLICATIVE],POWER:[" ** ",Blockly.Python.ORDER_EXPONENTIATION]}[a.getFieldValue("OP")],c=b[0],b=b[1],d=Blockly.Python.valueToCode(a,"A",b)||"0";a=Blockly.Python.valueToCode(a,"B",b)||"0";return[d+c+a,b]}; -Blockly.Python.math_single=function(a){var b=a.getFieldValue("OP"),c;if("NEG"==b)return c=Blockly.Python.valueToCode(a,"NUM",Blockly.Python.ORDER_UNARY_SIGN)||"0",["-"+c,Blockly.Python.ORDER_UNARY_SIGN];Blockly.Python.definitions_.import_math="import math";a="SIN"==b||"COS"==b||"TAN"==b?Blockly.Python.valueToCode(a,"NUM",Blockly.Python.ORDER_MULTIPLICATIVE)||"0":Blockly.Python.valueToCode(a,"NUM",Blockly.Python.ORDER_NONE)||"0";switch(b){case "ABS":c="math.fabs("+a+")";break;case "ROOT":c="math.sqrt("+ -a+")";break;case "LN":c="math.log("+a+")";break;case "LOG10":c="math.log10("+a+")";break;case "EXP":c="math.exp("+a+")";break;case "POW10":c="math.pow(10,"+a+")";break;case "ROUND":c="round("+a+")";break;case "ROUNDUP":c="math.ceil("+a+")";break;case "ROUNDDOWN":c="math.floor("+a+")";break;case "SIN":c="math.sin("+a+" / 180.0 * math.pi)";break;case "COS":c="math.cos("+a+" / 180.0 * math.pi)";break;case "TAN":c="math.tan("+a+" / 180.0 * math.pi)"}if(c)return[c,Blockly.Python.ORDER_FUNCTION_CALL];switch(b){case "ASIN":c= -"math.asin("+a+") / math.pi * 180";break;case "ACOS":c="math.acos("+a+") / math.pi * 180";break;case "ATAN":c="math.atan("+a+") / math.pi * 180";break;default:throw"Unknown math operator: "+b;}return[c,Blockly.Python.ORDER_MULTIPLICATIVE]}; -Blockly.Python.math_constant=function(a){var b={PI:["math.pi",Blockly.Python.ORDER_MEMBER],E:["math.e",Blockly.Python.ORDER_MEMBER],GOLDEN_RATIO:["(1 + math.sqrt(5)) / 2",Blockly.Python.ORDER_MULTIPLICATIVE],SQRT2:["math.sqrt(2)",Blockly.Python.ORDER_MEMBER],SQRT1_2:["math.sqrt(1.0 / 2)",Blockly.Python.ORDER_MEMBER],INFINITY:["float('inf')",Blockly.Python.ORDER_ATOMIC]};a=a.getFieldValue("CONSTANT");"INFINITY"!=a&&(Blockly.Python.definitions_.import_math="import math");return b[a]}; -Blockly.Python.math_number_property=function(a){var b=Blockly.Python.valueToCode(a,"NUMBER_TO_CHECK",Blockly.Python.ORDER_MULTIPLICATIVE)||"0",c=a.getFieldValue("PROPERTY"),d;if("PRIME"==c)return Blockly.Python.definitions_.import_math="import math",Blockly.Python.definitions_.from_numbers_import_Number="from numbers import Number",[Blockly.Python.provideFunction_("math_isPrime",["def "+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+"(n):"," # https://en.wikipedia.org/wiki/Primality_test#Naive_methods", -" # If n is not a number but a string, try parsing it."," if not isinstance(n, Number):"," try:"," n = float(n)"," except:"," return False"," if n == 2 or n == 3:"," return True"," # False if n is negative, is 1, or not whole, or if n is divisible by 2 or 3."," if n <= 1 or n % 1 != 0 or n % 2 == 0 or n % 3 == 0:"," return False"," # Check all the numbers of form 6k +/- 1, up to sqrt(n)."," for x in range(6, int(math.sqrt(n)) + 2, 6):"," if n % (x - 1) == 0 or n % (x + 1) == 0:", -" return False"," return True"])+"("+b+")",Blockly.Python.ORDER_FUNCTION_CALL];switch(c){case "EVEN":d=b+" % 2 == 0";break;case "ODD":d=b+" % 2 == 1";break;case "WHOLE":d=b+" % 1 == 0";break;case "POSITIVE":d=b+" > 0";break;case "NEGATIVE":d=b+" < 0";break;case "DIVISIBLE_BY":a=Blockly.Python.valueToCode(a,"DIVISOR",Blockly.Python.ORDER_MULTIPLICATIVE);if(!a||"0"==a)return["False",Blockly.Python.ORDER_ATOMIC];d=b+" % "+a+" == 0"}return[d,Blockly.Python.ORDER_RELATIONAL]}; -Blockly.Python.math_change=function(a){Blockly.Python.definitions_.from_numbers_import_Number="from numbers import Number";var b=Blockly.Python.valueToCode(a,"DELTA",Blockly.Python.ORDER_ADDITIVE)||"0";a=Blockly.Python.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE);return a+" = ("+a+" if isinstance("+a+", Number) else 0) + "+b+"\n"};Blockly.Python.math_round=Blockly.Python.math_single;Blockly.Python.math_trig=Blockly.Python.math_single; -Blockly.Python.math_on_list=function(a){var b=a.getFieldValue("OP");a=Blockly.Python.valueToCode(a,"LIST",Blockly.Python.ORDER_NONE)||"[]";switch(b){case "SUM":b="sum("+a+")";break;case "MIN":b="min("+a+")";break;case "MAX":b="max("+a+")";break;case "AVERAGE":Blockly.Python.definitions_.from_numbers_import_Number="from numbers import Number";b=Blockly.Python.provideFunction_("math_mean",["def "+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+"(myList):"," localList = [e for e in myList if isinstance(e, Number)]", -" if not localList: return"," return float(sum(localList)) / len(localList)"]);b=b+"("+a+")";break;case "MEDIAN":Blockly.Python.definitions_.from_numbers_import_Number="from numbers import Number";b=Blockly.Python.provideFunction_("math_median",["def "+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+"(myList):"," localList = sorted([e for e in myList if isinstance(e, Number)])"," if not localList: return"," if len(localList) % 2 == 0:"," return (localList[len(localList) // 2 - 1] + localList[len(localList) // 2]) / 2.0", -" else:"," return localList[(len(localList) - 1) // 2]"]);b=b+"("+a+")";break;case "MODE":b=Blockly.Python.provideFunction_("math_modes",["def "+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+"(some_list):"," modes = []"," # Using a lists of [item, count] to keep count rather than dict",' # to avoid "unhashable" errors when the counted item is itself a list or dict.'," counts = []"," maxCount = 1"," for item in some_list:"," found = False"," for count in counts:"," if count[0] == item:", -" count[1] += 1"," maxCount = max(maxCount, count[1])"," found = True"," if not found:"," counts.append([item, 1])"," for counted_item, item_count in counts:"," if item_count == maxCount:"," modes.append(counted_item)"," return modes"]);b=b+"("+a+")";break;case "STD_DEV":Blockly.Python.definitions_.import_math="import math";b=Blockly.Python.provideFunction_("math_standard_deviation",["def "+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+"(numbers):"," n = len(numbers)", -" if n == 0: return"," mean = float(sum(numbers)) / n"," variance = sum((x - mean) ** 2 for x in numbers) / n"," return math.sqrt(variance)"]);b=b+"("+a+")";break;case "RANDOM":Blockly.Python.definitions_.import_random="import random";b="random.choice("+a+")";break;default:throw"Unknown operator: "+b;}return[b,Blockly.Python.ORDER_FUNCTION_CALL]}; -Blockly.Python.math_modulo=function(a){var b=Blockly.Python.valueToCode(a,"DIVIDEND",Blockly.Python.ORDER_MULTIPLICATIVE)||"0";a=Blockly.Python.valueToCode(a,"DIVISOR",Blockly.Python.ORDER_MULTIPLICATIVE)||"0";return[b+" % "+a,Blockly.Python.ORDER_MULTIPLICATIVE]}; -Blockly.Python.math_constrain=function(a){var b=Blockly.Python.valueToCode(a,"VALUE",Blockly.Python.ORDER_NONE)||"0",c=Blockly.Python.valueToCode(a,"LOW",Blockly.Python.ORDER_NONE)||"0";a=Blockly.Python.valueToCode(a,"HIGH",Blockly.Python.ORDER_NONE)||"float('inf')";return["min(max("+b+", "+c+"), "+a+")",Blockly.Python.ORDER_FUNCTION_CALL]}; -Blockly.Python.math_random_int=function(a){Blockly.Python.definitions_.import_random="import random";var b=Blockly.Python.valueToCode(a,"FROM",Blockly.Python.ORDER_NONE)||"0";a=Blockly.Python.valueToCode(a,"TO",Blockly.Python.ORDER_NONE)||"0";return["random.randint("+b+", "+a+")",Blockly.Python.ORDER_FUNCTION_CALL]};Blockly.Python.math_random_float=function(a){Blockly.Python.definitions_.import_random="import random";return["random.random()",Blockly.Python.ORDER_FUNCTION_CALL]};Blockly.Python.variables={};Blockly.Python.variables_get=function(a){return[Blockly.Python.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE),Blockly.Python.ORDER_ATOMIC]};Blockly.Python.variables_set=function(a){var b=Blockly.Python.valueToCode(a,"VALUE",Blockly.Python.ORDER_NONE)||"0";return Blockly.Python.variableDB_.getName(a.getFieldValue("VAR"),Blockly.Variables.NAME_TYPE)+" = "+b+"\n"};Blockly.Python.colour={};Blockly.Python.colour_picker=function(a){return["'"+a.getFieldValue("COLOUR")+"'",Blockly.Python.ORDER_ATOMIC]};Blockly.Python.colour_random=function(a){Blockly.Python.definitions_.import_random="import random";return["'#%06x' % random.randint(0, 2**24 - 1)",Blockly.Python.ORDER_FUNCTION_CALL]}; -Blockly.Python.colour_rgb=function(a){var b=Blockly.Python.provideFunction_("colour_rgb",["def "+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+"(r, g, b):"," r = round(min(100, max(0, r)) * 2.55)"," g = round(min(100, max(0, g)) * 2.55)"," b = round(min(100, max(0, b)) * 2.55)"," return '#%02x%02x%02x' % (r, g, b)"]),c=Blockly.Python.valueToCode(a,"RED",Blockly.Python.ORDER_NONE)||0,d=Blockly.Python.valueToCode(a,"GREEN",Blockly.Python.ORDER_NONE)||0;a=Blockly.Python.valueToCode(a,"BLUE",Blockly.Python.ORDER_NONE)|| -0;return[b+"("+c+", "+d+", "+a+")",Blockly.Python.ORDER_FUNCTION_CALL]}; -Blockly.Python.colour_blend=function(a){var b=Blockly.Python.provideFunction_("colour_blend",["def "+Blockly.Python.FUNCTION_NAME_PLACEHOLDER_+"(colour1, colour2, ratio):"," r1, r2 = int(colour1[1:3], 16), int(colour2[1:3], 16)"," g1, g2 = int(colour1[3:5], 16), int(colour2[3:5], 16)"," b1, b2 = int(colour1[5:7], 16), int(colour2[5:7], 16)"," ratio = min(1, max(0, ratio))"," r = round(r1 * (1 - ratio) + r2 * ratio)"," g = round(g1 * (1 - ratio) + g2 * ratio)"," b = round(b1 * (1 - ratio) + b2 * ratio)", -" return '#%02x%02x%02x' % (r, g, b)"]),c=Blockly.Python.valueToCode(a,"COLOUR1",Blockly.Python.ORDER_NONE)||"'#000000'",d=Blockly.Python.valueToCode(a,"COLOUR2",Blockly.Python.ORDER_NONE)||"'#000000'";a=Blockly.Python.valueToCode(a,"RATIO",Blockly.Python.ORDER_NONE)||0;return[b+"("+c+", "+d+", "+a+")",Blockly.Python.ORDER_FUNCTION_CALL]};Blockly.Python.procedures={}; -Blockly.Python.procedures_defreturn=function(a){for(var b=a.workspace.variableList,c=b.length-1;0<=c;c--){var d=b[c];-1==a.arguments_.indexOf(d)?b[c]=Blockly.Python.variableDB_.getName(d,Blockly.Variables.NAME_TYPE):b.splice(c,1)}var b=b.length?" global "+b.join(", ")+"\n":"",d=Blockly.Python.variableDB_.getName(a.getFieldValue("NAME"),Blockly.Procedures.NAME_TYPE),e=Blockly.Python.statementToCode(a,"STACK");Blockly.Python.STATEMENT_PREFIX&&(e=Blockly.Python.prefixLines(Blockly.Python.STATEMENT_PREFIX.replace(/%1/g,"'"+ -a.id+"'"),Blockly.Python.INDENT)+e);Blockly.Python.INFINITE_LOOP_TRAP&&(e=Blockly.Python.INFINITE_LOOP_TRAP.replace(/%1/g,'"'+a.id+'"')+e);var f=Blockly.Python.valueToCode(a,"RETURN",Blockly.Python.ORDER_NONE)||"";f?f=" return "+f+"\n":e||(e=Blockly.Python.PASS);for(var g=[],c=0;c= stop:"," yield start"," start -= abs(step)"])};a=function(a,b,c){return"("+a+" <= "+b+") and "+h()+"("+a+", "+b+", "+c+") or "+k()+"("+a+", "+b+", "+c+")"};if(Blockly.isNumber(c)&&Blockly.isNumber(d)&& -Blockly.isNumber(e))c=parseFloat(c),d=parseFloat(d),e=Math.abs(parseFloat(e)),0===c%1&&0===d%1&&0===e%1?(c<=d?(d++,a=0==c&&1==e?d:c+", "+d,1!=e&&(a+=", "+e)):(d--,a=c+", "+d+", -"+e),a="range("+a+")"):(a=c",GTE:">="}[a.getFieldValue("OP")],c=Blockly.Python.ORDER_RELATIONAL,d=Blockly.Python.valueToCode(a,"A",c)||"0";a=Blockly.Python.valueToCode(a,"B",c)||"0";return[d+" "+b+" "+a,c]}; -Blockly.Python.logic_operation=function(a){var b="AND"==a.getFieldValue("OP")?"and":"or",c="and"==b?Blockly.Python.ORDER_LOGICAL_AND:Blockly.Python.ORDER_LOGICAL_OR,d=Blockly.Python.valueToCode(a,"A",c);a=Blockly.Python.valueToCode(a,"B",c);if(d||a){var e="and"==b?"True":"False";d||(d=e);a||(a=e)}else a=d="False";return[d+" "+b+" "+a,c]};Blockly.Python.logic_negate=function(a){return["not "+(Blockly.Python.valueToCode(a,"BOOL",Blockly.Python.ORDER_LOGICAL_NOT)||"True"),Blockly.Python.ORDER_LOGICAL_NOT]}; -Blockly.Python.logic_boolean=function(a){return["TRUE"==a.getFieldValue("BOOL")?"True":"False",Blockly.Python.ORDER_ATOMIC]};Blockly.Python.logic_null=function(a){return["None",Blockly.Python.ORDER_ATOMIC]}; -Blockly.Python.logic_ternary=function(a){var b=Blockly.Python.valueToCode(a,"IF",Blockly.Python.ORDER_CONDITIONAL)||"False",c=Blockly.Python.valueToCode(a,"THEN",Blockly.Python.ORDER_CONDITIONAL)||"None";a=Blockly.Python.valueToCode(a,"ELSE",Blockly.Python.ORDER_CONDITIONAL)||"None";return[c+" if "+b+" else "+a,Blockly.Python.ORDER_CONDITIONAL]}; \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/codemirror/AUTHORS b/backend/_pv_1_3_5/static/codemirror/AUTHORS deleted file mode 100755 index 866c78f84..000000000 --- a/backend/_pv_1_3_5/static/codemirror/AUTHORS +++ /dev/null @@ -1,625 +0,0 @@ -List of CodeMirror contributors. Updated before every release. - -4r2r -Aaron Brooks -Abdelouahab -Abe Fettig -Adam Ahmed -Adam King -adanlobato -Adán Lobato -Adrian Aichner -Adrian Heine -Adrien Bertrand -aeroson -Ahmad Amireh -Ahmad M. Zawawi -ahoward -Akeksandr Motsjonov -Alasdair Smith -Alberto González Palomo -Alberto Pose -Albert Xing -Alexander Pavlov -Alexander Schepanovski -Alexander Shvets -Alexander Solovyov -Alexandre Bique -alexey-k -Alex Piggott -Aliaksei Chapyzhenka -Allen Sarkisyan -Amin Shali -Amin Ullah Khan -amshali@google.com -Amsul -amuntean -Amy -Ananya Sen -anaran -AndersMad -Anders Nawroth -Anderson Mesquita -Anders Wåglund -Andrea G -Andreas Reischuck -Andres Taylor -Andre von Houck -Andrew Cheng -Andrey Fedorov -Andrey Klyuchnikov -Andrey Lushnikov -Andrey Shchekin -Andy Joslin -Andy Kimball -Andy Li -Angelo -angelozerr -angelo.zerr@gmail.com -Ankit -Ankit Ahuja -Ansel Santosa -Anthony Dugois -anthonygego -Anthony Gégo -Anthony Grimes -Anton Kovalyov -Apollo Zhu -AQNOUCH Mohammed -areos -Arnab Bose -as3boyan -atelierbram -AtomicPages LLC -Atul Bhouraskar -Aurelian Oancea -Barret Rennie -Basarat Ali Syed -Bastian Müller -belhaj -Bem Jones-Bey -benbro -Beni Cherniavsky-Paskin -Benjamin DeCoste -Ben Keen -Ben Miller -Ben Mosher -Bernhard Sirlinger -Bert Chang -Bharad -BigBlueHat -Billy Moon -binny -B Krishna Chaitanya -Blaine G -blukat29 -boomyjee -borawjm -Brad Metcalf -Brandon Frohs -Brandon Wamboldt -Brett Zamir -Brian Grinstead -Brian Sletten -Bruce Mitchener -Caitlin Potter -Calin Barbat -callodacity -Camilo Roca -Chad Jolly -Chandra Sekhar Pydi -Charles Skelton -Cheah Chu Yeow -Chris Coyier -Chris Ford -Chris Granger -Chris Houseknecht -Chris Lohfink -Chris Morgan -Chris Smith -Christian Oyarzun -Christian Petrov -Christopher Brown -Christopher Mitchell -Christopher Pfohl -Chunliang Lyu -ciaranj -CodeAnimal -coderaiser -Cole R Lawrence -ComFreek -Curtis Gagliardi -dagsta -daines -Dale Jung -Dan Bentley -Dan Heberden -Daniel, Dao Quang Minh -Daniele Di Sarli -Daniel Faust -Daniel Huigens -Daniel Kesler -Daniel KJ -Daniel Neel -Daniel Parnell -Danny Yoo -darealshinji -Darius Roberts -Dave Brondsema -Dave Myers -David Barnett -David H. Bronke -David Mignot -David Pathakjee -David Vázquez -David Whittington -deebugger -Deep Thought -Devin Abbott -Devon Carew -Dick Choi -dignifiedquire -Dimage Sapelkin -Dmitry Kiselyov -domagoj412 -Dominator008 -Domizio Demichelis -Doug Wikle -Drew Bratcher -Drew Hintz -Drew Khoury -Drini Cami -Dror BG -duralog -eborden -edsharp -ekhaled -Elisée -Emmanuel Schanzer -Enam Mijbah Noor -Eric Allam -Erik Welander -eustas -Fabien O'Carroll -Fabio Zendhi Nagao -Faiza Alsaied -Fauntleroy -fbuchinger -feizhang365 -Felipe Lalanne -Felix Raab -ficristo -Filip Noetzel -Filip Stollár -flack -ForbesLindesay -Forbes Lindesay -Ford_Lawnmower -Forrest Oliphant -Frank Wiegand -Gabriel Gheorghian -Gabriel Horner -Gabriel Nahmias -galambalazs -Gary Sheng -Gautam Mehta -Gavin Douglas -gekkoe -geowarin -Gerard Braad -Gergely Hegykozi -Giovanni Calò -Glebov Boris -Glenn Jorde -Glenn Ruehle -Golevka -Google Inc. -Gordon Smith -Grant Skinner -greengiant -Gregory Koberger -Grzegorz Mazur -Guillaume Massé -Guillaume Massé -guraga -Gustavo Rodrigues -Hakan Tunc -Hans Engel -Hardest -Harshvardhan Gupta -Hasan Karahan -Hector Oswaldo Caballero -Hendrik Wallbaum -Herculano Campos -Hiroyuki Makino -hitsthings -Hocdoc -Hugues Malphettes -Ian Beck -Ian Dickinson -Ian Wehrman -Ian Wetherbee -Ice White -ICHIKAWA, Yuji -idleberg -ilvalle -Ingo Richter -Irakli Gozalishvili -Ivan Kurnosov -Ivoah -Jacob Lee -Jake Peyser -Jakob Miland -Jakub Vrana -Jakub Vrána -James Campos -James Howard -James Thorne -Jamie Hill -Jan Jongboom -jankeromnes -Jan Keromnes -Jan Odvarko -Jan Schär -Jan T. Sott -Jared Dean -Jared Forsyth -Jared Jacobs -Jason -Jason Barnabe -Jason Grout -Jason Johnston -Jason San Jose -Jason Siefken -Jaydeep Solanki -Jean Boussier -Jeff Blaisdell -Jeff Jenkins -jeffkenton -Jeff Pickhardt -jem (graphite) -Jeremy Parmenter -Jim -Jim Avery -JobJob -jochenberger -Jochen Berger -Joel Einbinder -joelpinheiro -Johan Ask -John Connor -John-David Dalton -John Engler -John Lees-Miller -John Snelson -John Van Der Loo -Jon Ander Peñalba -Jonas Döbertin -Jonathan Malmaud -Jon Gacnik -jongalloway -Jon Malmaud -Jon Sangster -Joost-Wim Boekesteijn -Joseph Pecoraro -Josh Cohen -Josh Soref -Joshua Newman -Josh Watzman -jots -jsoojeon -ju1ius -Juan Benavides Romero -Jucovschi Constantin -Juho Vuori -Julien Rebetez -Justin Andresen -Justin Hileman -jwallers@gmail.com -kaniga -karevn -Kayur Patel -Kazuhito Hokamura -Ken Newman -ken restivo -Ken Rockot -Kevin Earls -Kevin Sawicki -Kevin Ushey -Klaus Silveira -Koh Zi Han, Cliff -komakino -Konstantin Lopuhin -koops -Kris Ciccarello -ks-ifware -kubelsmieci -KwanEsq -Kyle Kelley -Lanfei -Lanny -Laszlo Vidacs -leaf corcoran -Leonid Khachaturov -Leon Sorokin -Leonya Khachaturov -Liam Newman -Libo Cannici -LloydMilligan -LM -lochel -Lorenzo Stoakes -Luciano Longo -Lu Fangjian -Luke Browning -Luke Granger-Brown -Luke Stagner -lynschinzer -M1cha -Madhura Jayaratne -Maksim Lin -Maksym Taran -Malay Majithia -Manideep -Manuel Rego Casasnovas -Marat Dreizin -Marcel Gerber -Marcelo Camargo -Marco Aurélio -Marco Munizaga -Marcus Bointon -Marek Rudnicki -Marijn Haverbeke -Mário Gonçalves -Mario Pietsch -Mark Anderson -Mark Lentczner -Marko Bonaci -Mark Peace -Markus Bordihn -Martin Balek -Martín Gaitán -Martin Hasoň -Martin Hunt -Martin Laine -Martin Zagora -Mason Malone -Mateusz Paprocki -Mathias Bynens -mats cronqvist -Matt Gaide -Matthew Bauer -Matthew Beale -matthewhayes -Matthew Rathbone -Matthias Bussonnier -Matthias BUSSONNIER -Matt McDonald -Matt Pass -Matt Sacks -mauricio -Maximilian Hils -Maxim Kraev -Max Kirsch -Max Schaefer -Max Xiantu -mbarkhau -McBrainy -melpon -Metatheos -Micah Dubinko -Michael -Michael Goderbauer -Michael Grey -Michael Kaminsky -Michael Lehenbauer -Michael Zhou -Michal Dorner -Mighty Guava -Miguel Castillo -mihailik -Mike -Mike Brevoort -Mike Diaz -Mike Ivanov -Mike Kadin -Mike Kobit -MinRK -Miraculix87 -misfo -mkaminsky11 -mloginov -Moritz Schwörer -mps -ms -mtaran-google -Mu-An Chiou -Narciso Jaramillo -Nathan Williams -ndr -nerbert -nextrevision -ngn -nguillaumin -Ng Zhi An -Nicholas Bollweg -Nicholas Bollweg (Nick) -Nick Kreeger -Nick Small -Nicolò Ribaudo -Niels van Groningen -nightwing -Nikita Beloglazov -Nikita Vasilyev -Nikolay Kostov -nilp0inter -Nisarg Jhaveri -nlwillia -noragrossman -Norman Rzepka -Oreoluwa Onatemowo -Oskar Segersvärd -pablo -pabloferz -Page -Panupong Pasupat -paris -Paris -Paris Kasidiaris -Patil Arpith -Patrick Stoica -Patrick Strawderman -Paul Garvin -Paul Ivanov -Paul Masson -Pavel -Pavel Feldman -Pavel Petržela -Pavel Strashkin -Paweł Bartkiewicz -peteguhl -peter -Peter Flynn -peterkroon -Peter Kroon -Philipp A -Philip Stadermann -Pierre Gerold -Piët Delport -Pontus Melke -prasanthj -Prasanth J -Prayag Verma -Radek Piórkowski -Rahul -Rahul Anand -ramwin1 -Randall Mason -Randy Burden -Randy Edmunds -Rasmus Erik Voel Jensen -ray ratchup -Ray Ratchup -Remi Nyborg -Richard Denton -Richard van der Meer -Richard Z.H. Wang -Rishi Goomar -Robert Crossfield -Roberto Abdelkader Martínez Pérez -robertop23 -Robert Plummer -Rrandom -Ruslan Osmanov -Ryan Prior -sabaca -Sam Lee -Samuel Ainsworth -Sam Wilson -sandeepshetty -Sander AKA Redsandro -Sander Verweij -santec -Sascha Peilicke -satamas -satchmorun -sathyamoorthi -S. Chris Colbert -SCLINIC\jdecker -Scott Aikin -Scott Goodhew -Sebastian Zaha -Sergey Goder -Sergey Tselovalnikov -Se-Won Kim -shaund -shaun gilchrist -Shawn A -Shea Bunge -sheopory -Shiv Deepak -Shmuel Englard -Shubham Jain -Siamak Mokhtari -silverwind -sinkuu -snasa -soliton4 -sonson -spastorelli -srajanpaliwal -Stanislav Oaserele -Stas Kobzar -Stefan Borsje -Steffen Beyer -Steffen Bruchmann -Stephen Lavelle -Steve Champagne -Steve Hoover -Steve O'Hara -stoskov -Stu Kennedy -Sungho Kim -sverweij -Taha Jahangir -takamori -Tako Schotanus -Takuji Shimokawa -Tarmil -TDaglis -tel -tfjgeorge -Thaddee Tyl -thanasis -TheHowl -themrmax -think -Thomas Dvornik -Thomas Kluyver -Thomas Schmid -Tim Alby -Tim Baumann -Timothy Farrell -Timothy Gu -Timothy Hatcher -TobiasBg -Todd Berman -Tomas-A -Tomas Varaneckas -Tom Erik Støwer -Tom Klancer -Tom MacWright -Tony Jian -Travis Heppe -Triangle717 -Tristan Tarrant -TSUYUSATO Kitsune -twifkak -VapidWorx -Vestimir Markov -vf -Victor Bocharsky -Vincent Woo -Volker Mische -Weiyan Shao -wenli -Wes Cossick -Wesley Wiser -Will Binns-Smith -Will Dean -William Jamieson -William Stein -Willy -Wojtek Ptak -Wu Cheng-Han -Xavier Mendez -Yassin N. Hassan -YNH Webdev -Yunchi Luo -Yuvi Panda -Zac Anger -Zachary Dremann -Zeno Rocha -Zhang Hao -zziuni -魏鹏刚 diff --git a/backend/_pv_1_3_5/static/codemirror/CHANGELOG.md b/backend/_pv_1_3_5/static/codemirror/CHANGELOG.md deleted file mode 100755 index 07ed0295e..000000000 --- a/backend/_pv_1_3_5/static/codemirror/CHANGELOG.md +++ /dev/null @@ -1,984 +0,0 @@ -## 5.23.0 (2017-01-19) - -### Bug fixes - -Presentation-related elements DOM elements are now marked as such to help screen readers. - -[markdown mode](http://codemirror.net/mode/markdown/): Be more picky about what HTML tags look like to avoid false positives. - -### New features - -`findModeByMIME` now understands `+json` and `+xml` MIME suffixes. - -[closebrackets addon](http://codemirror.net/doc/manual.html#addon_closebrackets): Add support for an `override` option to ignore language-specific defaults. - -[panel addon](http://codemirror.net/doc/manual.html#addon_panel): Add a `stable` option that auto-scrolls the content to keep it in the same place when inserting/removing a panel. - -## 5.22.2 (2017-01-12) - -### Bug fixes - -Include rollup.config.js in NPM package, so that it can be used to build from source. - -## 5.22.0 (2016-12-20) - -### Bug fixes - -[sublime bindings](http://codemirror.net/demo/sublime.html): Make `selectBetweenBrackets` work with multiple cursors. - -[javascript mode](http://codemirror.net/mode/javascript/): Fix issues with parsing complex TypeScript types, imports, and exports. - -A contentEditable editor instance with autofocus enabled no longer crashes during initializing. - -### New features - -[emacs bindings](http://codemirror.net/demo/emacs.html): Export `CodeMirror.emacs` to allow other addons to hook into Emacs-style functionality. - -[active-line addon](http://codemirror.net/doc/manual.html#addon_active-line): Add `nonEmpty` option. - -New event: [`optionChange`](http://codemirror.net/doc/manual.html#event_optionChange). - -## 5.21.0 (2016-11-21) - -### Bug fixes - -Tapping/clicking the editor in [contentEditable mode](http://codemirror.net/doc/manual.html#option_inputStyle) on Chrome now puts the cursor at the tapped position. - -Fix various crashes and misbehaviors when reading composition events in [contentEditable mode](http://codemirror.net/doc/manual.html#option_inputStyle). - -Catches and ignores an IE 'Unspecified Error' when creating an editor in an iframe before there is a ``. - -[merge addon](http://codemirror.net/doc/manual.html#addon_merge): Fix several issues in the chunk-aligning feature. - -[verilog mode](http://codemirror.net/mode/verilog): Rewritten to address various issues. - -[julia mode](http://codemirror.net/mode/julia): Recognize Julia 0.5 syntax. - -[swift mode](http://codemirror.net/mode/swift): Various fixes and adjustments to current syntax. - -[markdown mode](http://codemirror.net/mode/markdown): Allow lists without a blank line above them. - -### New features - -The [`setGutterMarker`](http://codemirror.net/doc/manual.html#setGutterMarker), [`clearGutter`](http://codemirror.net/doc/manual.html#clearGutter), and [`lineInfo`](http://codemirror.net/doc/manual.html#lineInfo) methods are now available on `Doc` objects. - -The [`heightAtLine`](http://codemirror.net/doc/manual.html#heightAtLine) method now takes an extra argument to allow finding the height at the top of the line's line widgets. - -[ruby mode](http://codemirror.net/mode/ruby): `else` and `elsif` are now immediately indented. - -[vim bindings](http://codemirror.net/demo/vim.html): Bind Ctrl-T and Ctrl-D to in- and dedent in insert mode. - -## 5.20.2 (2016-10-21) - -### Bug fixes - -Fix `CodeMirror.version` returning the wrong version number. - -## 5.20.0 (2016-10-20) - -### Bug fixes - -Make `newlineAndIndent` command work with multiple cursors on the same line. - -Make sure keypress events for backspace are ignored. - -Tokens styled with overlays no longer get a nonsense `cm-cm-overlay` class. - -Line endings for pasted content are now normalized to the editor's [preferred ending](http://codemirror.net/doc/manual.html#option_lineSeparator). - -[javascript mode](http://codemirror.net/mode/javascript): Improve support for class expressions. Support TypeScript optional class properties, the `abstract` keyword, and return type declarations for arrow functions. - -[css mode](http://codemirror.net/mode/css): Fix highlighting of mixed-case keywords. - -[closebrackets addon](http://codemirror.net/doc/manual.html#addon_closebrackets): Improve behavior when typing a quote before a string. - -### New features - -The core is now maintained as a number of small files, using ES6 syntax and modules, under the `src/` directory. A git checkout no longer contains a working `codemirror.js` until you `npm build` (but when installing from NPM, it is included). - -The [`refresh`](http://codemirror.net/doc/manual.html#event_refresh) event is now documented and stable. - -## 5.19.0 (2016-09-20) - -### Bugfixes - -[erlang mode](http://codemirror.net/mode/erlang): Fix mode crash when trying to read an empty context. - -[comment addon](http://codemirror.net/doc/manual.html#addon_comment): Fix broken behavior when toggling comments inside a comment. - -xml-fold addon: Fix a null-dereference bug. - -Page up and page down now do something even in single-line documents. - -Fix an issue where the cursor position could be off in really long (~8000 character) tokens. - -### New features - -[javascript mode](http://codemirror.net/mode/javascript): Better indentation when semicolons are missing. Better support for TypeScript classes, optional parameters, and the `type` keyword. - -The [`blur`](http://codemirror.net/doc/manual.html#event_blur) and [`focus`](http://codemirror.net/doc/manual.html#event_focus) events now pass the DOM event to their handlers. - -## 5.18.2 (2016-08-23) - -### Bugfixes - -[vue mode](http://codemirror.net/mode/vue): Fix outdated references to renamed Pug mode dependency. - -## 5.18.0 (2016-08-22) - -### Bugfixes - -Make sure [gutter backgrounds](http://codemirror.net/doc/manual.html#addLineClass) stick to the rest of the gutter during horizontal scrolling. - -The contenteditable [`inputStyle`](http://codemirror.net/doc/manual.html#option_inputStyle) now properly supports pasting on pre-Edge IE versions. - -[javascript mode](http://codemirror.net/mode/javascript): Fix some small parsing bugs and improve TypeScript support. - -[matchbrackets addon](http://codemirror.net/doc/manual.html#addon_matchbrackets): Fix bug where active highlighting was left in editor when the addon was disabled. - -[match-highlighter addon](http://codemirror.net/doc/manual.html#addon_match-highlighter): Only start highlighting things when the editor gains focus. - -[javascript-hint addon](http://codemirror.net/doc/manual.html#addon_javascript-hint): Also complete non-enumerable properties. - -### New features - -The [`addOverlay`](http://codemirror.net/doc/manual.html#addOverlay) method now supports a `priority` option to control the order in which overlays are applied. - -MIME types that end in `+json` now default to the JSON mode when the MIME itself is not defined. - -### Breaking changes - -The mode formerly known as Jade was renamed to [Pug](http://codemirror.net/mode/pug). - -The [Python mode](http://codemirror.net/mode/python) now defaults to Python 3 (rather than 2) syntax. - -## 5.17.0 (2016-07-19) - -### Bugfixes - -Fix problem with wrapped trailing whitespace displaying incorrectly. - -Prevent IME dialog from overlapping typed content in Chrome. - -Improve measuring of characters near a line wrap. - -[javascript mode](http://codemirror.net/mode/javascript): Improve support for `async`, allow trailing commas in `import` lists. - -[vim bindings](http://codemirror.net/demo/vim.html): Fix backspace in replace mode. - -[sublime bindings](http://codemirror.net/demo/sublime.html): Fix some key bindings on OS X to match Sublime Text. - -### New features - -[markdown mode](http://codemirror.net/mode/markdown): Add more classes to image links in highlight-formatting mode. - -## 5.16.0 (2016-06-20) - -### Bugfixes - -Fix glitches when dragging content caused by the drop indicator receiving mouse events. - -Make Control-drag work on Firefox. - -Make clicking or selection-dragging at the end of a wrapped line select the right position. - -[show-hint addon](http://codemirror.net/doc/manual.html#addon_show-hint): Prevent widget scrollbar from hiding part of the hint text. - -[rulers addon](http://codemirror.net/doc/manual.html#addon_rulers): Prevent rulers from forcing a horizontal editor scrollbar. - -### New features - -[search addon](http://codemirror.net/doc/manual.html#addon_search): Automatically bind search-related keys in persistent dialog. - -[sublime keymap](http://codemirror.net/demo/sublime.html): Add a multi-cursor aware smart backspace binding. - -## 5.15.2 (2016-05-20) - -### Bugfixes - -Fix a critical document corruption bug that occurs when a document is gradually grown. - -## 5.15.0 (2016-05-20) - -### Bugfixes - -Fix bug that caused the selection to reset when focusing the editor in contentEditable input mode. - -Fix issue where not all ASCII control characters were being replaced by placeholders. - -Remove the assumption that all modes have a `startState` method from several wrapping modes. - -Fix issue where the editor would complain about overlapping collapsed ranges when there weren't any. - -Optimize document tree building when loading or pasting huge chunks of content. - -[markdown mode](http://codemirror.net/mode/markdown/): Fix several issues in matching link targets. - -[clike mode](http://codemirror.net/mode/clike/): Improve indentation of C++ template declarations. - -### New features - -Explicitly bind Ctrl-O on OS X to make that binding (“open line”) act as expected. - -Pasting [linewise-copied](http://codemirror.net/doc/manual.html#option_lineWiseCopyCut) content when there is no selection now inserts the lines above the current line. - -[javascript mode](http://codemirror.net/mode/javascript/): Support `async`/`await` and improve support for TypeScript type syntax. - -## 5.14.2 (2016-04-20) - -### Bugfixes - -Push a new package to NPM due to an [NPM bug](https://github.com/npm/npm/issues/5082) omitting the LICENSE file in 5.14.0. - -Set `dataTransfer.effectAllowed` in `dragstart` handler to help browsers use the right drag icon. - -Add the [mbox mode](http://codemirror.net/mode/mbox/index.html) to `mode/meta.js`. - -## 5.14.0 (2016-04-20) - -### Bugfixes - -[`posFromIndex`](http://codemirror.net/doc/manual.html#posFromIndex) and [`indexFromPos`](http://codemirror.net/doc/manual.html#indexFromPos) now take [`lineSeparator`](http://codemirror.net/doc/manual.html#option_lineSeparator) into account. - -[vim bindings](http://codemirror.net/demo/vim.html): Only call `.save()` when it is actually available. - -[comment addon](http://codemirror.net/doc/manual.html#addon_comment): Be careful not to mangle multi-line strings. - -[Python mode](http://codemirror.net/mode/python/index.html): Improve distinguishing of decorators from `@` operators. - -[`findMarks`](http://codemirror.net/doc/manual.html#findMarks): No longer return marks that touch but don't overlap given range. - -### New features - -[vim bindings](http://codemirror.net/demo/vim.html): Add yank command. - -[match-highlighter addon](http://codemirror.net/doc/manual.html#addon_match-highlighter): Add `trim` option to disable ignoring of whitespace. - -[PowerShell mode](http://codemirror.net/mode/powershell/index.html): Added. - -[Yacas mode](http://codemirror.net/mode/yacas/index.html): Added. - -[Web IDL mode](http://codemirror.net/mode/webidl/index.html): Added. - -[SAS mode](http://codemirror.net/mode/sas/index.html): Added. - -[mbox mode](http://codemirror.net/mode/mbox/index.html): Added. - -## 5.13.2 (2016-03-23) - -### Bugfixes - -Solves a problem where the gutter would sometimes not extend all the way to the end of the document. - -## 5.13.0 (2016-03-21) - -### New features - -New DOM event forwarded: [`"dragleave"`](http://codemirror.net/doc/manual.html#event_dom). - -[protobuf mode](http://codemirror.net/mode/protobuf/index.html): Newly added. - -### Bugfixes - -Fix problem where [`findMarks`](http://codemirror.net/doc/manual.html#findMarks) sometimes failed to find multi-line marks. - -Fix crash that showed up when atomic ranges and bidi text were combined. - -[show-hint addon](http://codemirror.net/demo/complete.html): Completion widgets no longer close when the line indented or dedented. - -[merge addon](http://codemirror.net/demo/merge.html): Fix bug when merging chunks at the end of the file. - -[placeholder addon](http://codemirror.net/doc/manual.html#addon_placeholder): No longer gets confused by [`swapDoc`](http://codemirror.net/doc/manual.html#swapDoc). - -[simplescrollbars addon](http://codemirror.net/doc/manual.html#addon_simplescrollbars): Fix invalid state when deleting at end of document. - -[clike mode](http://codemirror.net/mode/clike/index.html): No longer gets confused when a comment starts after an operator. - -[markdown mode](http://codemirror.net/mode/markdown/index.html): Now supports CommonMark-style flexible list indentation. - -[dylan mode](http://codemirror.net/mode/dylan/index.html): Several improvements and fixes. - -## 5.12.0 (2016-02-19) - -### New features - -[Vim bindings](http://codemirror.net/demo/vim.html): Ctrl-Q is now an alias for Ctrl-V. - -[Vim bindings](http://codemirror.net/demo/vim.html): The Vim API now exposes an `unmap` method to unmap bindings. - -[active-line addon](http://codemirror.net/demo/activeline.html): This addon can now style the active line's gutter. - -[FCL mode](http://codemirror.net/mode/fcl/): Newly added. - -[SQL mode](http://codemirror.net/mode/sql/): Now has a Postgresql dialect. - -### Bugfixes - -Fix [issue](https://github.com/codemirror/CodeMirror/issues/3781) where trying to scroll to a horizontal position outside of the document's width could cause the gutter to be positioned incorrectly. - -Use absolute, rather than fixed positioning in the context-menu intercept hack, to work around a [problem](https://github.com/codemirror/CodeMirror/issues/3238) when the editor is inside a transformed parent container. - -Solve a [problem](https://github.com/codemirror/CodeMirror/issues/3821) where the horizontal scrollbar could hide text in Firefox. - -Fix a [bug](https://github.com/codemirror/CodeMirror/issues/3834) that caused phantom scroll space under the text in some situations. - -[Sublime Text bindings](http://codemirror.net/demo/sublime.html): Bind delete-line to Shift-Ctrl-K on OS X. - -[Markdown mode](http://codemirror.net/mode/markdown/): Fix [issue](https://github.com/codemirror/CodeMirror/issues/3787) where the mode would keep state related to fenced code blocks in an unsafe way, leading to occasional corrupted parses. - -[Markdown mode](http://codemirror.net/mode/markdown/): Ignore backslashes in code fragments. - -[Markdown mode](http://codemirror.net/mode/markdown/): Use whichever mode is registered as `text/html` to parse HTML. - -[Clike mode](http://codemirror.net/mode/clike/): Improve indentation of Scala `=>` functions. - -[Python mode](http://codemirror.net/mode/python/): Improve indentation of bracketed code. - -[HTMLMixed mode](http://codemirror.net/mode/htmlmixed/): Support multi-line opening tags for sub-languages (` - - - -
    - -

    (Re-) Implementing A Syntax-Highlighting Editor in JavaScript

    - -

    - Topic: JavaScript, code editor implementation
    - Author: Marijn Haverbeke
    - Date: March 2nd 2011 (updated November 13th 2011) -

    - -

    Caution: this text was written briefly after -version 2 was initially written. It no longer (even including the -update at the bottom) fully represents the current implementation. I'm -leaving it here as a historic document. For more up-to-date -information, look at the entries -tagged cm-internals -on my blog.

    - -

    This is a followup to -my Brutal Odyssey to the -Dark Side of the DOM Tree story. That one describes the -mind-bending process of implementing (what would become) CodeMirror 1. -This one describes the internals of CodeMirror 2, a complete rewrite -and rethink of the old code base. I wanted to give this piece another -Hunter Thompson copycat subtitle, but somehow that would be out of -place—the process this time around was one of straightforward -engineering, requiring no serious mind-bending whatsoever.

    - -

    So, what is wrong with CodeMirror 1? I'd estimate, by mailing list -activity and general search-engine presence, that it has been -integrated into about a thousand systems by now. The most prominent -one, since a few weeks, -being Google -code's project hosting. It works, and it's being used widely.

    - -

    Still, I did not start replacing it because I was bored. CodeMirror -1 was heavily reliant on designMode -or contentEditable (depending on the browser). Neither of -these are well specified (HTML5 tries -to specify -their basics), and, more importantly, they tend to be one of the more -obscure and buggy areas of browser functionality—CodeMirror, by using -this functionality in a non-typical way, was constantly running up -against browser bugs. WebKit wouldn't show an empty line at the end of -the document, and in some releases would suddenly get unbearably slow. -Firefox would show the cursor in the wrong place. Internet Explorer -would insist on linkifying everything that looked like a URL or email -address, a behaviour that can't be turned off. Some bugs I managed to -work around (which was often a frustrating, painful process), others, -such as the Firefox cursor placement, I gave up on, and had to tell -user after user that they were known problems, but not something I -could help.

    - -

    Also, there is the fact that designMode (which seemed -to be less buggy than contentEditable in Webkit and -Firefox, and was thus used by CodeMirror 1 in those browsers) requires -a frame. Frames are another tricky area. It takes some effort to -prevent getting tripped up by domain restrictions, they don't -initialize synchronously, behave strangely in response to the back -button, and, on several browsers, can't be moved around the DOM -without having them re-initialize. They did provide a very nice way to -namespace the library, though—CodeMirror 1 could freely pollute the -namespace inside the frame.

    - -

    Finally, working with an editable document means working with -selection in arbitrary DOM structures. Internet Explorer (8 and -before) has an utterly different (and awkward) selection API than all -of the other browsers, and even among the different implementations of -document.selection, details about how exactly a selection -is represented vary quite a bit. Add to that the fact that Opera's -selection support tended to be very buggy until recently, and you can -imagine why CodeMirror 1 contains 700 lines of selection-handling -code.

    - -

    And that brings us to the main issue with the CodeMirror 1 -code base: The proportion of browser-bug-workarounds to real -application code was getting dangerously high. By building on top of a -few dodgy features, I put the system in a vulnerable position—any -incompatibility and bugginess in these features, I had to paper over -with my own code. Not only did I have to do some serious stunt-work to -get it to work on older browsers (as detailed in the -previous story), things -also kept breaking in newly released versions, requiring me to come up -with new scary hacks in order to keep up. This was starting -to lose its appeal.

    - -
    -

    General Approach

    - -

    What CodeMirror 2 does is try to sidestep most of the hairy hacks -that came up in version 1. I owe a lot to the -ACE editor for inspiration on how to -approach this.

    - -

    I absolutely did not want to be completely reliant on key events to -generate my input. Every JavaScript programmer knows that key event -information is horrible and incomplete. Some people (most awesomely -Mihai Bazon with Ymacs) have been able -to build more or less functioning editors by directly reading key -events, but it takes a lot of work (the kind of never-ending, fragile -work I described earlier), and will never be able to properly support -things like multi-keystoke international character -input. [see below for caveat]

    - -

    So what I do is focus a hidden textarea, and let the browser -believe that the user is typing into that. What we show to the user is -a DOM structure we built to represent his document. If this is updated -quickly enough, and shows some kind of believable cursor, it feels -like a real text-input control.

    - -

    Another big win is that this DOM representation does not have to -span the whole document. Some CodeMirror 1 users insisted that they -needed to put a 30 thousand line XML document into CodeMirror. Putting -all that into the DOM takes a while, especially since, for some -reason, an editable DOM tree is slower than a normal one on most -browsers. If we have full control over what we show, we must only -ensure that the visible part of the document has been added, and can -do the rest only when needed. (Fortunately, the onscroll -event works almost the same on all browsers, and lends itself well to -displaying things only as they are scrolled into view.)

    -
    -
    -

    Input

    - -

    ACE uses its hidden textarea only as a text input shim, and does -all cursor movement and things like text deletion itself by directly -handling key events. CodeMirror's way is to let the browser do its -thing as much as possible, and not, for example, define its own set of -key bindings. One way to do this would have been to have the whole -document inside the hidden textarea, and after each key event update -the display DOM to reflect what's in that textarea.

    - -

    That'd be simple, but it is not realistic. For even medium-sized -document the editor would be constantly munging huge strings, and get -terribly slow. What CodeMirror 2 does is put the current selection, -along with an extra line on the top and on the bottom, into the -textarea.

    - -

    This means that the arrow keys (and their ctrl-variations), home, -end, etcetera, do not have to be handled specially. We just read the -cursor position in the textarea, and update our cursor to match it. -Also, copy and paste work pretty much for free, and people get their -native key bindings, without any special work on my part. For example, -I have emacs key bindings configured for Chrome and Firefox. There is -no way for a script to detect this. [no longer the case]

    - -

    Of course, since only a small part of the document sits in the -textarea, keys like page up and ctrl-end won't do the right thing. -CodeMirror is catching those events and handling them itself.

    -
    -
    -

    Selection

    - -

    Getting and setting the selection range of a textarea in modern -browsers is trivial—you just use the selectionStart -and selectionEnd properties. On IE you have to do some -insane stuff with temporary ranges and compensating for the fact that -moving the selection by a 'character' will treat \r\n as a single -character, but even there it is possible to build functions that -reliably set and get the selection range.

    - -

    But consider this typical case: When I'm somewhere in my document, -press shift, and press the up arrow, something gets selected. Then, if -I, still holding shift, press the up arrow again, the top of my -selection is adjusted. The selection remembers where its head -and its anchor are, and moves the head when we shift-move. -This is a generally accepted property of selections, and done right by -every editing component built in the past twenty years.

    - -

    But not something that the browser selection APIs expose.

    - -

    Great. So when someone creates an 'upside-down' selection, the next -time CodeMirror has to update the textarea, it'll re-create the -selection as an 'upside-up' selection, with the anchor at the top, and -the next cursor motion will behave in an unexpected way—our second -up-arrow press in the example above will not do anything, since it is -interpreted in exactly the same way as the first.

    - -

    No problem. We'll just, ehm, detect that the selection is -upside-down (you can tell by the way it was created), and then, when -an upside-down selection is present, and a cursor-moving key is -pressed in combination with shift, we quickly collapse the selection -in the textarea to its start, allow the key to take effect, and then -combine its new head with its old anchor to get the real -selection.

    - -

    In short, scary hacks could not be avoided entirely in CodeMirror -2.

    - -

    And, the observant reader might ask, how do you even know that a -key combo is a cursor-moving combo, if you claim you support any -native key bindings? Well, we don't, but we can learn. The editor -keeps a set known cursor-movement combos (initialized to the -predictable defaults), and updates this set when it observes that -pressing a certain key had (only) the effect of moving the cursor. -This, of course, doesn't work if the first time the key is used was -for extending an inverted selection, but it works most of the -time.

    -
    -
    -

    Intelligent Updating

    - -

    One thing that always comes up when you have a complicated internal -state that's reflected in some user-visible external representation -(in this case, the displayed code and the textarea's content) is -keeping the two in sync. The naive way is to just update the display -every time you change your state, but this is not only error prone -(you'll forget), it also easily leads to duplicate work on big, -composite operations. Then you start passing around flags indicating -whether the display should be updated in an attempt to be efficient -again and, well, at that point you might as well give up completely.

    - -

    I did go down that road, but then switched to a much simpler model: -simply keep track of all the things that have been changed during an -action, and then, only at the end, use this information to update the -user-visible display.

    - -

    CodeMirror uses a concept of operations, which start by -calling a specific set-up function that clears the state and end by -calling another function that reads this state and does the required -updating. Most event handlers, and all the user-visible methods that -change state are wrapped like this. There's a method -called operation that accepts a function, and returns -another function that wraps the given function as an operation.

    - -

    It's trivial to extend this (as CodeMirror does) to detect nesting, -and, when an operation is started inside an operation, simply -increment the nesting count, and only do the updating when this count -reaches zero again.

    - -

    If we have a set of changed ranges and know the currently shown -range, we can (with some awkward code to deal with the fact that -changes can add and remove lines, so we're dealing with a changing -coordinate system) construct a map of the ranges that were left -intact. We can then compare this map with the part of the document -that's currently visible (based on scroll offset and editor height) to -determine whether something needs to be updated.

    - -

    CodeMirror uses two update algorithms—a full refresh, where it just -discards the whole part of the DOM that contains the edited text and -rebuilds it, and a patch algorithm, where it uses the information -about changed and intact ranges to update only the out-of-date parts -of the DOM. When more than 30 percent (which is the current heuristic, -might change) of the lines need to be updated, the full refresh is -chosen (since it's faster to do than painstakingly finding and -updating all the changed lines), in the other case it does the -patching (so that, if you scroll a line or select another character, -the whole screen doesn't have to be -re-rendered). [the full-refresh -algorithm was dropped, it wasn't really faster than the patching -one]

    - -

    All updating uses innerHTML rather than direct DOM -manipulation, since that still seems to be by far the fastest way to -build documents. There's a per-line function that combines the -highlighting, marking, and -selection info for that line into a snippet of HTML. The patch updater -uses this to reset individual lines, the refresh updater builds an -HTML chunk for the whole visible document at once, and then uses a -single innerHTML update to do the refresh.

    -
    -
    -

    Parsers can be Simple

    - -

    When I wrote CodeMirror 1, I -thought interruptable -parsers were a hugely scary and complicated thing, and I used a -bunch of heavyweight abstractions to keep this supposed complexity -under control: parsers -were iterators -that consumed input from another iterator, and used funny -closure-resetting tricks to copy and resume themselves.

    - -

    This made for a rather nice system, in that parsers formed strictly -separate modules, and could be composed in predictable ways. -Unfortunately, it was quite slow (stacking three or four iterators on -top of each other), and extremely intimidating to people not used to a -functional programming style.

    - -

    With a few small changes, however, we can keep all those -advantages, but simplify the API and make the whole thing less -indirect and inefficient. CodeMirror -2's mode API uses explicit state -objects, and makes the parser/tokenizer a function that simply takes a -state and a character stream abstraction, advances the stream one -token, and returns the way the token should be styled. This state may -be copied, optionally in a mode-defined way, in order to be able to -continue a parse at a given point. Even someone who's never touched a -lambda in his life can understand this approach. Additionally, far -fewer objects are allocated in the course of parsing now.

    - -

    The biggest speedup comes from the fact that the parsing no longer -has to touch the DOM though. In CodeMirror 1, on an older browser, you -could see the parser work its way through the document, -managing some twenty lines in each 50-millisecond time slice it got. It -was reading its input from the DOM, and updating the DOM as it went -along, which any experienced JavaScript programmer will immediately -spot as a recipe for slowness. In CodeMirror 2, the parser usually -finishes the whole document in a single 100-millisecond time slice—it -manages some 1500 lines during that time on Chrome. All it has to do -is munge strings, so there is no real reason for it to be slow -anymore.

    -
    -
    -

    What Gives?

    - -

    Given all this, what can you expect from CodeMirror 2?

    - -
      - -
    • Small. the base library is -some 45k when minified -now, 17k when gzipped. It's smaller than -its own logo.
    • - -
    • Lightweight. CodeMirror 2 initializes very -quickly, and does almost no work when it is not focused. This means -you can treat it almost like a textarea, have multiple instances on a -page without trouble.
    • - -
    • Huge document support. Since highlighting is -really fast, and no DOM structure is being built for non-visible -content, you don't have to worry about locking up your browser when a -user enters a megabyte-sized document.
    • - -
    • Extended API. Some things kept coming up in the -mailing list, such as marking pieces of text or lines, which were -extremely hard to do with CodeMirror 1. The new version has proper -support for these built in.
    • - -
    • Tab support. Tabs inside editable documents were, -for some reason, a no-go. At least six different people announced they -were going to add tab support to CodeMirror 1, none survived (I mean, -none delivered a working version). CodeMirror 2 no longer removes tabs -from your document.
    • - -
    • Sane styling. iframe nodes aren't -really known for respecting document flow. Now that an editor instance -is a plain div element, it is much easier to size it to -fit the surrounding elements. You don't even have to make it scroll if -you do not want to.
    • - -
    - -

    On the downside, a CodeMirror 2 instance is not a native -editable component. Though it does its best to emulate such a -component as much as possible, there is functionality that browsers -just do not allow us to hook into. Doing select-all from the context -menu, for example, is not currently detected by CodeMirror.

    - -

    [Updates from November 13th 2011] Recently, I've made -some changes to the codebase that cause some of the text above to no -longer be current. I've left the text intact, but added markers at the -passages that are now inaccurate. The new situation is described -below.

    -
    -
    -

    Content Representation

    - -

    The original implementation of CodeMirror 2 represented the -document as a flat array of line objects. This worked well—splicing -arrays will require the part of the array after the splice to be -moved, but this is basically just a simple memmove of a -bunch of pointers, so it is cheap even for huge documents.

    - -

    However, I recently added line wrapping and code folding (line -collapsing, basically). Once lines start taking up a non-constant -amount of vertical space, looking up a line by vertical position -(which is needed when someone clicks the document, and to determine -the visible part of the document during scrolling) can only be done -with a linear scan through the whole array, summing up line heights as -you go. Seeing how I've been going out of my way to make big documents -fast, this is not acceptable.

    - -

    The new representation is based on a B-tree. The leaves of the tree -contain arrays of line objects, with a fixed minimum and maximum size, -and the non-leaf nodes simply hold arrays of child nodes. Each node -stores both the amount of lines that live below them and the vertical -space taken up by these lines. This allows the tree to be indexed both -by line number and by vertical position, and all access has -logarithmic complexity in relation to the document size.

    - -

    I gave line objects and tree nodes parent pointers, to the node -above them. When a line has to update its height, it can simply walk -these pointers to the top of the tree, adding or subtracting the -difference in height from each node it encounters. The parent pointers -also make it cheaper (in complexity terms, the difference is probably -tiny in normal-sized documents) to find the current line number when -given a line object. In the old approach, the whole document array had -to be searched. Now, we can just walk up the tree and count the sizes -of the nodes coming before us at each level.

    - -

    I chose B-trees, not regular binary trees, mostly because they -allow for very fast bulk insertions and deletions. When there is a big -change to a document, it typically involves adding, deleting, or -replacing a chunk of subsequent lines. In a regular balanced tree, all -these inserts or deletes would have to be done separately, which could -be really expensive. In a B-tree, to insert a chunk, you just walk -down the tree once to find where it should go, insert them all in one -shot, and then break up the node if needed. This breaking up might -involve breaking up nodes further up, but only requires a single pass -back up the tree. For deletion, I'm somewhat lax in keeping things -balanced—I just collapse nodes into a leaf when their child count goes -below a given number. This means that there are some weird editing -patterns that may result in a seriously unbalanced tree, but even such -an unbalanced tree will perform well, unless you spend a day making -strangely repeating edits to a really big document.

    -
    -
    -

    Keymaps

    - -

    Above, I claimed that directly catching key -events for things like cursor movement is impractical because it -requires some browser-specific kludges. I then proceeded to explain -some awful hacks that were needed to make it -possible for the selection changes to be detected through the -textarea. In fact, the second hack is about as bad as the first.

    - -

    On top of that, in the presence of user-configurable tab sizes and -collapsed and wrapped lines, lining up cursor movement in the textarea -with what's visible on the screen becomes a nightmare. Thus, I've -decided to move to a model where the textarea's selection is no longer -depended on.

    - -

    So I moved to a model where all cursor movement is handled by my -own code. This adds support for a goal column, proper interaction of -cursor movement with collapsed lines, and makes it possible for -vertical movement to move through wrapped lines properly, instead of -just treating them like non-wrapped lines.

    - -

    The key event handlers now translate the key event into a string, -something like Ctrl-Home or Shift-Cmd-R, and -use that string to look up an action to perform. To make keybinding -customizable, this lookup goes through -a table, using a scheme that -allows such tables to be chained together (for example, the default -Mac bindings fall through to a table named 'emacsy', which defines -basic Emacs-style bindings like Ctrl-F, and which is also -used by the custom Emacs bindings).

    - -

    A new -option extraKeys -allows ad-hoc keybindings to be defined in a much nicer way than what -was possible with the -old onKeyEvent -callback. You simply provide an object mapping key identifiers to -functions, instead of painstakingly looking at raw key events.

    - -

    Built-in commands map to strings, rather than functions, for -example "goLineUp" is the default action bound to the up -arrow key. This allows new keymaps to refer to them without -duplicating any code. New commands can be defined by assigning to -the CodeMirror.commands object, which maps such commands -to functions.

    - -

    The hidden textarea now only holds the current selection, with no -extra characters around it. This has a nice advantage: polling for -input becomes much, much faster. If there's a big selection, this text -does not have to be read from the textarea every time—when we poll, -just noticing that something is still selected is enough to tell us -that no new text was typed.

    - -

    The reason that cheap polling is important is that many browsers do -not fire useful events on IME (input method engine) input, which is -the thing where people inputting a language like Japanese or Chinese -use multiple keystrokes to create a character or sequence of -characters. Most modern browsers fire input when the -composing is finished, but many don't fire anything when the character -is updated during composition. So we poll, whenever the -editor is focused, to provide immediate updates of the display.

    - -
    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/doc/logo.png b/backend/_pv_1_3_5/static/codemirror/doc/logo.png deleted file mode 100755 index 9aabda1d709f565bb115fa083cc16b6d52db64cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9310 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 diff --git a/backend/_pv_1_3_5/static/codemirror/doc/logo.svg b/backend/_pv_1_3_5/static/codemirror/doc/logo.svg deleted file mode 100755 index 0aa6323f9..000000000 --- a/backend/_pv_1_3_5/static/codemirror/doc/logo.svg +++ /dev/null @@ -1,181 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/codemirror/doc/manual.html b/backend/_pv_1_3_5/static/codemirror/doc/manual.html deleted file mode 100755 index a5eb22335..000000000 --- a/backend/_pv_1_3_5/static/codemirror/doc/manual.html +++ /dev/null @@ -1,3433 +0,0 @@ - - -CodeMirror: User Manual - - - - - - - - - - - - - - - - -
    - -
    -

    - User manual and reference guide - version 5.23.0 -

    - -

    CodeMirror is a code-editor component that can be embedded in - Web pages. The core library provides only the editor - component, no accompanying buttons, auto-completion, or other IDE - functionality. It does provide a rich API on top of which such - functionality can be straightforwardly implemented. See - the addons included in the distribution, - and the list - of externally hosted addons, for reusable - implementations of extra features.

    - -

    CodeMirror works with language-specific modes. Modes are - JavaScript programs that help color (and optionally indent) text - written in a given language. The distribution comes with a number - of modes (see the mode/ - directory), and it isn't hard to write new - ones for other languages.

    -
    - -
    -

    Basic Usage

    - -

    The easiest way to use CodeMirror is to simply load the script - and style sheet found under lib/ in the distribution, - plus a mode script from one of the mode/ directories. - For example:

    - -
    <script src="lib/codemirror.js"></script>
    -<link rel="stylesheet" href="lib/codemirror.css">
    -<script src="mode/javascript/javascript.js"></script>
    - -

    (Alternatively, use a module loader. More - about that later.)

    - -

    Having done this, an editor instance can be created like - this:

    - -
    var myCodeMirror = CodeMirror(document.body);
    - -

    The editor will be appended to the document body, will start - empty, and will use the mode that we loaded. To have more control - over the new editor, a configuration object can be passed - to CodeMirror as a second - argument:

    - -
    var myCodeMirror = CodeMirror(document.body, {
    -  value: "function myScript(){return 100;}\n",
    -  mode:  "javascript"
    -});
    - -

    This will initialize the editor with a piece of code already in - it, and explicitly tell it to use the JavaScript mode (which is - useful when multiple modes are loaded). - See below for a full discussion of the - configuration options that CodeMirror accepts.

    - -

    In cases where you don't want to append the editor to an - element, and need more control over the way it is inserted, the - first argument to the CodeMirror function can also - be a function that, when given a DOM element, inserts it into the - document somewhere. This could be used to, for example, replace a - textarea with a real editor:

    - -
    var myCodeMirror = CodeMirror(function(elt) {
    -  myTextArea.parentNode.replaceChild(elt, myTextArea);
    -}, {value: myTextArea.value});
    - -

    However, for this use case, which is a common way to use - CodeMirror, the library provides a much more powerful - shortcut:

    - -
    var myCodeMirror = CodeMirror.fromTextArea(myTextArea);
    - -

    This will, among other things, ensure that the textarea's value - is updated with the editor's contents when the form (if it is part - of a form) is submitted. See the API - reference for a full description of this method.

    - -

    Module loaders

    - -

    The files in the CodeMirror distribution contain shims for - loading them (and their dependencies) in AMD or CommonJS - environments. If the variables exports - and module exist and have type object, CommonJS-style - require will be used. If not, but there is a - function define with an amd property - present, AMD-style (RequireJS) will be used.

    - -

    It is possible to - use Browserify or similar - tools to statically build modules using CodeMirror. Alternatively, - use RequireJS to dynamically - load dependencies at runtime. Both of these approaches have the - advantage that they don't use the global namespace and can, thus, - do things like load multiple versions of CodeMirror alongside each - other.

    - -

    Here's a simple example of using RequireJS to load CodeMirror:

    - -
    require([
    -  "cm/lib/codemirror", "cm/mode/htmlmixed/htmlmixed"
    -], function(CodeMirror) {
    -  CodeMirror.fromTextArea(document.getElementById("code"), {
    -    lineNumbers: true,
    -    mode: "htmlmixed"
    -  });
    -});
    - -

    It will automatically load the modes that the mixed HTML mode - depends on (XML, JavaScript, and CSS). Do not use - RequireJS' paths option to configure the path to - CodeMirror, since it will break loading submodules through - relative paths. Use - the packages - configuration option instead, as in:

    - -
    require.config({
    -  packages: [{
    -    name: "codemirror",
    -    location: "../path/to/codemirror",
    -    main: "lib/codemirror"
    -  }]
    -});
    - -
    - -
    -

    Configuration

    - -

    Both the CodeMirror - function and its fromTextArea method take as second - (optional) argument an object containing configuration options. - Any option not supplied like this will be taken - from CodeMirror.defaults, an - object containing the default options. You can update this object - to change the defaults on your page.

    - -

    Options are not checked in any way, so setting bogus option - values is bound to lead to odd errors.

    - -

    These are the supported options:

    - -
    -
    value: string|CodeMirror.Doc
    -
    The starting value of the editor. Can be a string, or - a document object.
    - -
    mode: string|object
    -
    The mode to use. When not given, this will default to the - first mode that was loaded. It may be a string, which either - simply names the mode or is - a MIME type - associated with the mode. Alternatively, it may be an object - containing configuration options for the mode, with - a name property that names the mode (for - example {name: "javascript", json: true}). The demo - pages for each mode contain information about what configuration - parameters the mode supports. You can ask CodeMirror which modes - and MIME types have been defined by inspecting - the CodeMirror.modes - and CodeMirror.mimeModes objects. The first maps - mode names to their constructors, and the second maps MIME types - to mode specs.
    - -
    lineSeparator: string|null
    -
    Explicitly set the line separator for the editor. By default - (value null), the document will be split on CRLFs - as well as lone CRs and LFs, and a single LF will be used as - line separator in all output (such - as getValue). When a - specific string is given, lines will only be split on that - string, and output will, by default, use that same - separator.
    - -
    theme: string
    -
    The theme to style the editor with. You must make sure the - CSS file defining the corresponding .cm-s-[name] - styles is loaded (see - the theme directory in the - distribution). The default is "default", for which - colors are included in codemirror.css. It is - possible to use multiple theming classes at once—for - example "foo bar" will assign both - the cm-s-foo and the cm-s-bar classes - to the editor.
    - -
    indentUnit: integer
    -
    How many spaces a block (whatever that means in the edited - language) should be indented. The default is 2.
    - -
    smartIndent: boolean
    -
    Whether to use the context-sensitive indentation that the - mode provides (or just indent the same as the line before). - Defaults to true.
    - -
    tabSize: integer
    -
    The width of a tab character. Defaults to 4.
    - -
    indentWithTabs: boolean
    -
    Whether, when indenting, the first N*tabSize - spaces should be replaced by N tabs. Default is false.
    - -
    electricChars: boolean
    -
    Configures whether the editor should re-indent the current - line when a character is typed that might change its proper - indentation (only works if the mode supports indentation). - Default is true.
    - -
    specialChars: RegExp
    -
    A regular expression used to determine which characters - should be replaced by a - special placeholder. - Mostly useful for non-printing special characters. The default - is /[\u0000-\u001f\u007f\u00ad\u200b-\u200f\u2028\u2029\ufeff]/.
    -
    specialCharPlaceholder: function(char) → Element
    -
    A function that, given a special character identified by - the specialChars - option, produces a DOM node that is used to represent the - character. By default, a red dot () - is shown, with a title tooltip to indicate the character code.
    - -
    rtlMoveVisually: boolean
    -
    Determines whether horizontal cursor movement through - right-to-left (Arabic, Hebrew) text is visual (pressing the left - arrow moves the cursor left) or logical (pressing the left arrow - moves to the next lower index in the string, which is visually - right in right-to-left text). The default is false - on Windows, and true on other platforms.
    - -
    keyMap: string
    -
    Configures the key map to use. The default - is "default", which is the only key map defined - in codemirror.js itself. Extra key maps are found in - the key map directory. See - the section on key maps for more - information.
    - -
    extraKeys: object
    -
    Can be used to specify extra key bindings for the editor, - alongside the ones defined - by keyMap. Should be - either null, or a valid key map value.
    - -
    lineWrapping: boolean
    -
    Whether CodeMirror should scroll or wrap for long lines. - Defaults to false (scroll).
    - -
    lineNumbers: boolean
    -
    Whether to show line numbers to the left of the editor.
    - -
    firstLineNumber: integer
    -
    At which number to start counting lines. Default is 1.
    - -
    lineNumberFormatter: function(line: integer) → string
    -
    A function used to format line numbers. The function is - passed the line number, and should return a string that will be - shown in the gutter.
    - -
    gutters: array<string>
    -
    Can be used to add extra gutters (beyond or instead of the - line number gutter). Should be an array of CSS class names, each - of which defines a width (and optionally a - background), and which will be used to draw the background of - the gutters. May include - the CodeMirror-linenumbers class, in order to - explicitly set the position of the line number gutter (it will - default to be to the right of all other gutters). These class - names are the keys passed - to setGutterMarker.
    - -
    fixedGutter: boolean
    -
    Determines whether the gutter scrolls along with the content - horizontally (false) or whether it stays fixed during horizontal - scrolling (true, the default).
    - -
    scrollbarStyle: string
    -
    Chooses a scrollbar implementation. The default - is "native", showing native scrollbars. The core - library also provides the "null" style, which - completely hides the - scrollbars. Addons can - implement additional scrollbar models.
    - -
    coverGutterNextToScrollbar: boolean
    -
    When fixedGutter - is on, and there is a horizontal scrollbar, by default the - gutter will be visible to the left of this scrollbar. If this - option is set to true, it will be covered by an element with - class CodeMirror-gutter-filler.
    - -
    inputStyle: string
    -
    Selects the way CodeMirror handles input and focus. The core - library defines the "textarea" - and "contenteditable" input models. On mobile - browsers, the default is "contenteditable". On - desktop browsers, the default is "textarea". - Support for IME and screen readers is better in - the "contenteditable" model. The intention is to - make it the default on modern desktop browsers in the - future.
    - -
    readOnly: boolean|string
    -
    This disables editing of the editor content by the user. If - the special value "nocursor" is given (instead of - simply true), focusing of the editor is also - disallowed.
    - -
    showCursorWhenSelecting: boolean
    -
    Whether the cursor should be drawn when a selection is - active. Defaults to false.
    - -
    lineWiseCopyCut: boolean
    -
    When enabled, which is the default, doing copy or cut when - there is no selection will copy or cut the whole lines that have - cursors on them.
    - -
    undoDepth: integer
    -
    The maximum number of undo levels that the editor stores. - Note that this includes selection change events. Defaults to - 200.
    - -
    historyEventDelay: integer
    -
    The period of inactivity (in milliseconds) that will cause a - new history event to be started when typing or deleting. - Defaults to 1250.
    - -
    tabindex: integer
    -
    The tab - index to assign to the editor. If not given, no tab index - will be assigned.
    - -
    autofocus: boolean
    -
    Can be used to make CodeMirror focus itself on - initialization. Defaults to off. - When fromTextArea is - used, and no explicit value is given for this option, it will be - set to true when either the source textarea is focused, or it - has an autofocus attribute and no other element is - focused.
    -
    - -

    Below this a few more specialized, low-level options are - listed. These are only useful in very specific situations, you - might want to skip them the first time you read this manual.

    - -
    -
    dragDrop: boolean
    -
    Controls whether drag-and-drop is enabled. On by default.
    - -
    allowDropFileTypes: array<string>
    -
    When set (default is null) only files whose - type is in the array can be dropped into the editor. The strings - should be MIME types, and will be checked against - the type - of the File object as reported by the browser.
    - -
    cursorBlinkRate: number
    -
    Half-period in milliseconds used for cursor blinking. The default blink - rate is 530ms. By setting this to zero, blinking can be disabled. A - negative value hides the cursor entirely.
    - -
    cursorScrollMargin: number
    -
    How much extra space to always keep above and below the - cursor when approaching the top or bottom of the visible view in - a scrollable document. Default is 0.
    - -
    cursorHeight: number
    -
    Determines the height of the cursor. Default is 1, meaning - it spans the whole height of the line. For some fonts (and by - some tastes) a smaller height (for example 0.85), - which causes the cursor to not reach all the way to the bottom - of the line, looks better
    - -
    resetSelectionOnContextMenu: boolean
    -
    Controls whether, when the context menu is opened with a - click outside of the current selection, the cursor is moved to - the point of the click. Defaults to true.
    - -
    workTime, workDelay: number
    -
    Highlighting is done by a pseudo background-thread that will - work for workTime milliseconds, and then use - timeout to sleep for workDelay milliseconds. The - defaults are 200 and 300, you can change these options to make - the highlighting more or less aggressive.
    - -
    pollInterval: number
    -
    Indicates how quickly CodeMirror should poll its input - textarea for changes (when focused). Most input is captured by - events, but some things, like IME input on some browsers, don't - generate events that allow CodeMirror to properly detect it. - Thus, it polls. Default is 100 milliseconds.
    - -
    flattenSpans: boolean
    -
    By default, CodeMirror will combine adjacent tokens into a - single span if they have the same class. This will result in a - simpler DOM tree, and thus perform better. With some kinds of - styling (such as rounded corners), this will change the way the - document looks. You can set this option to false to disable this - behavior.
    - -
    addModeClass: boolean
    -
    When enabled (off by default), an extra CSS class will be - added to each token, indicating the - (inner) mode that produced it, prefixed - with "cm-m-". For example, tokens from the XML mode - will get the cm-m-xml class.
    - -
    maxHighlightLength: number
    -
    When highlighting long lines, in order to stay responsive, - the editor will give up and simply style the rest of the line as - plain text when it reaches a certain position. The default is - 10 000. You can set this to Infinity to turn off - this behavior.
    - -
    viewportMargin: integer
    -
    Specifies the amount of lines that are rendered above and - below the part of the document that's currently scrolled into - view. This affects the amount of updates needed when scrolling, - and the amount of work that such an update does. You should - usually leave it at its default, 10. Can be set - to Infinity to make sure the whole document is - always rendered, and thus the browser's text search works on it. - This will have bad effects on performance of big - documents.
    -
    -
    - -
    -

    Events

    - -

    Various CodeMirror-related objects emit events, which allow - client code to react to various situations. Handlers for such - events can be registered with the on - and off methods on the objects - that the event fires on. To fire your own events, - use CodeMirror.signal(target, name, args...), - where target is a non-DOM-node object.

    - -

    An editor instance fires the following events. - The instance argument always refers to the editor - itself.

    - -
    -
    "change" (instance: CodeMirror, changeObj: object)
    -
    Fires every time the content of the editor is changed. - The changeObj is a {from, to, text, removed, - origin} object containing information about the changes - that occurred as second argument. from - and to are the positions (in the pre-change - coordinate system) where the change started and ended (for - example, it might be {ch:0, line:18} if the - position is at the beginning of line #19). text is - an array of strings representing the text that replaced the - changed range (split by line). removed is the text - that used to be between from and to, - which is overwritten by this change. This event is - fired before the end of - an operation, before the DOM updates - happen.
    - -
    "changes" (instance: CodeMirror, changes: array<object>)
    -
    Like the "change" - event, but batched per operation, - passing an array containing all the changes that happened in the - operation. This event is fired after the operation finished, and - display changes it makes will trigger a new operation.
    - -
    "beforeChange" (instance: CodeMirror, changeObj: object)
    -
    This event is fired before a change is applied, and its - handler may choose to modify or cancel the change. - The changeObj object - has from, to, and text - properties, as with - the "change" event. It - also has a cancel() method, which can be called to - cancel the change, and, if the change isn't - coming from an undo or redo event, an update(from, to, - text) method, which may be used to modify the change. - Undo or redo changes can't be modified, because they hold some - metainformation for restoring old marked ranges that is only - valid for that specific change. All three arguments - to update are optional, and can be left off to - leave the existing value for that field - intact. Note: you may not do anything from - a "beforeChange" handler that would cause changes - to the document or its visualization. Doing so will, since this - handler is called directly from the bowels of the CodeMirror - implementation, probably cause the editor to become - corrupted.
    - -
    "cursorActivity" (instance: CodeMirror)
    -
    Will be fired when the cursor or selection moves, or any - change is made to the editor content.
    - -
    "keyHandled" (instance: CodeMirror, name: string, event: Event)
    -
    Fired after a key is handled through a - key map. name is the name of the handled key (for - example "Ctrl-X" or "'q'"), - and event is the DOM keydown - or keypress event.
    - -
    "inputRead" (instance: CodeMirror, changeObj: object)
    -
    Fired whenever new input is read from the hidden textarea - (typed or pasted by the user).
    - -
    "electricInput" (instance: CodeMirror, line: integer)
    -
    Fired if text input matched the - mode's electric patterns, - and this caused the line's indentation to change.
    - -
    "beforeSelectionChange" (instance: CodeMirror, obj: {ranges, origin, update})
    -
    This event is fired before the selection is moved. Its - handler may inspect the set of selection ranges, present as an - array of {anchor, head} objects in - the ranges property of the obj - argument, and optionally change them by calling - the update method on this object, passing an array - of ranges in the same format. The object also contains - an origin property holding the origin string passed - to the selection-changing method, if any. Handlers for this - event have the same restriction - as "beforeChange" - handlers — they should not do anything to directly update the - state of the editor.
    - -
    "viewportChange" (instance: CodeMirror, from: number, to: number)
    -
    Fires whenever the view port of - the editor changes (due to scrolling, editing, or any other - factor). The from and to arguments - give the new start and end of the viewport.
    - -
    "swapDoc" (instance: CodeMirror, oldDoc: Doc)
    -
    This is signalled when the editor's document is replaced - using the swapDoc - method.
    - -
    "gutterClick" (instance: CodeMirror, line: integer, gutter: string, clickEvent: Event)
    -
    Fires when the editor gutter (the line-number area) is - clicked. Will pass the editor instance as first argument, the - (zero-based) number of the line that was clicked as second - argument, the CSS class of the gutter that was clicked as third - argument, and the raw mousedown event object as - fourth argument.
    - -
    "gutterContextMenu" (instance: CodeMirror, line: integer, gutter: string, contextMenu: Event: Event)
    -
    Fires when the editor gutter (the line-number area) - receives a contextmenu event. Will pass the editor - instance as first argument, the (zero-based) number of the line - that was clicked as second argument, the CSS class of the - gutter that was clicked as third argument, and the raw - contextmenu mouse event object as fourth argument. - You can preventDefault the event, to signal that - CodeMirror should do no further handling.
    - -
    "focus" (instance: CodeMirror, event: Event)
    -
    Fires whenever the editor is focused.
    - -
    "blur" (instance: CodeMirror, event: Event)
    -
    Fires whenever the editor is unfocused.
    - -
    "scroll" (instance: CodeMirror)
    -
    Fires when the editor is scrolled.
    - -
    "refresh" (instance: CodeMirror)
    -
    Fires when the editor is refreshed - or resized. Mostly useful to invalidate - cached values that depend on the editor or character size.
    - -
    "optionChange" (instance: CodeMirror, option: string)
    -
    Dispatched every time an option is changed with setOption.
    - -
    "scrollCursorIntoView" (instance: CodeMirror, event: Event)
    -
    Fires when the editor tries to scroll its cursor into view. - Can be hooked into to take care of additional scrollable - containers around the editor. When the event object has - its preventDefault method called, CodeMirror will - not itself try to scroll the window.
    - -
    "update" (instance: CodeMirror)
    -
    Will be fired whenever CodeMirror updates its DOM display.
    - -
    "renderLine" (instance: CodeMirror, line: LineHandle, element: Element)
    -
    Fired whenever a line is (re-)rendered to the DOM. Fired - right after the DOM element is built, before it is - added to the document. The handler may mess with the style of - the resulting element, or add event handlers, but - should not try to change the state of the editor.
    - -
    "mousedown", - "dblclick", "touchstart", "contextmenu", - "keydown", "keypress", - "keyup", "cut", "copy", "paste", - "dragstart", "dragenter", - "dragover", "dragleave", - "drop" - (instance: CodeMirror, event: Event)
    -
    Fired when CodeMirror is handling a DOM event of this type. - You can preventDefault the event, or give it a - truthy codemirrorIgnore property, to signal that - CodeMirror should do no further handling.
    -
    - -

    Document objects (instances - of CodeMirror.Doc) emit the - following events:

    - -
    -
    "change" (doc: CodeMirror.Doc, changeObj: object)
    -
    Fired whenever a change occurs to the - document. changeObj has a similar type as the - object passed to the - editor's "change" - event.
    - -
    "beforeChange" (doc: CodeMirror.Doc, change: object)
    -
    See the description of the - same event on editor instances.
    - -
    "cursorActivity" (doc: CodeMirror.Doc)
    -
    Fired whenever the cursor or selection in this document - changes.
    - -
    "beforeSelectionChange" (doc: CodeMirror.Doc, selection: {head, anchor})
    -
    Equivalent to - the event by the same - name as fired on editor instances.
    -
    - -

    Line handles (as returned by, for - example, getLineHandle) - support these events:

    - -
    -
    "delete" ()
    -
    Will be fired when the line object is deleted. A line object - is associated with the start of the line. Mostly useful - when you need to find out when your gutter - markers on a given line are removed.
    -
    "change" (line: LineHandle, changeObj: object)
    -
    Fires when the line's text content is changed in any way - (but the line is not deleted outright). The change - object is similar to the one passed - to change event on the editor - object.
    -
    - -

    Marked range handles (CodeMirror.TextMarker), as returned - by markText - and setBookmark, emit the - following events:

    - -
    -
    "beforeCursorEnter" ()
    -
    Fired when the cursor enters the marked range. From this - event handler, the editor state may be inspected - but not modified, with the exception that the range on - which the event fires may be cleared.
    -
    "clear" (from: {line, ch}, to: {line, ch})
    -
    Fired when the range is cleared, either through cursor - movement in combination - with clearOnEnter - or through a call to its clear() method. Will only - be fired once per handle. Note that deleting the range through - text editing does not fire this event, because an undo action - might bring the range back into existence. from - and to give the part of the document that the range - spanned when it was cleared.
    -
    "hide" ()
    -
    Fired when the last part of the marker is removed from the - document by editing operations.
    -
    "unhide" ()
    -
    Fired when, after the marker was removed by editing, a undo - operation brought the marker back.
    -
    - -

    Line widgets (CodeMirror.LineWidget), returned - by addLineWidget, fire - these events:

    - -
    -
    "redraw" ()
    -
    Fired whenever the editor re-adds the widget to the DOM. - This will happen once right after the widget is added (if it is - scrolled into view), and then again whenever it is scrolled out - of view and back in again, or when changes to the editor options - or the line the widget is on require the widget to be - redrawn.
    -
    -
    - -
    -

    Key Maps

    - -

    Key maps are ways to associate keys with functionality. A key map - is an object mapping strings that identify the keys to functions - that implement their functionality.

    - -

    The CodeMirror distributions comes - with Emacs, Vim, - and Sublime Text-style keymaps.

    - -

    Keys are identified either by name or by character. - The CodeMirror.keyNames object defines names for - common keys and associates them with their key codes. Examples of - names defined here are Enter, F5, - and Q. These can be prefixed - with Shift-, Cmd-, Ctrl-, - and Alt- to specify a modifier. So for - example, Shift-Ctrl-Space would be a valid key - identifier.

    - -

    Common example: map the Tab key to insert spaces instead of a tab - character.

    - -
    -editor.setOption("extraKeys", {
    -  Tab: function(cm) {
    -    var spaces = Array(cm.getOption("indentUnit") + 1).join(" ");
    -    cm.replaceSelection(spaces);
    -  }
    -});
    - -

    Alternatively, a character can be specified directly by - surrounding it in single quotes, for example '$' - or 'q'. Due to limitations in the way browsers fire - key events, these may not be prefixed with modifiers.

    - -

    Multi-stroke key bindings can be specified - by separating the key names by spaces in the property name, for - example Ctrl-X Ctrl-V. When a map contains - multi-stoke bindings or keys with modifiers that are not specified - in the default order (Shift-Cmd-Ctrl-Alt), you must - call CodeMirror.normalizeKeyMap on it before it can - be used. This function takes a keymap and modifies it to normalize - modifier order and properly recognize multi-stroke bindings. It - will return the keymap itself.

    - -

    The CodeMirror.keyMap object associates key maps - with names. User code and key map definitions can assign extra - properties to this object. Anywhere where a key map is expected, a - string can be given, which will be looked up in this object. It - also contains the "default" key map holding the - default bindings.

    - -

    The values of properties in key maps can be either functions of - a single argument (the CodeMirror instance), strings, or - false. Strings refer - to commands, which are described below. If - the property is set to false, CodeMirror leaves - handling of the key up to the browser. A key handler function may - return CodeMirror.Pass to indicate that it has - decided not to handle the key, and other handlers (or the default - behavior) should be given a turn.

    - -

    Keys mapped to command names that start with the - characters "go" or to functions that have a - truthy motion property (which should be used for - cursor-movement actions) will be fired even when an - extra Shift modifier is present (i.e. "Up": - "goLineUp" matches both up and shift-up). This is used to - easily implement shift-selection.

    - -

    Key maps can defer to each other by defining - a fallthrough property. This indicates that when a - key is not found in the map itself, one or more other maps should - be searched. It can hold either a single key map or an array of - key maps.

    - -

    When a key map needs to set something up when it becomes - active, or tear something down when deactivated, it can - contain attach and/or detach properties, - which should hold functions that take the editor instance and the - next or previous keymap. Note that this only works for the - top-level keymap, not for fallthrough - maps or maps added - with extraKeys - or addKeyMap.

    -
    - -
    -

    Commands

    - -

    Commands are parameter-less actions that can be performed on an - editor. Their main use is for key bindings. Commands are defined by - adding properties to the CodeMirror.commands object. - A number of common commands are defined by the library itself, - most of them used by the default key bindings. The value of a - command property must be a function of one argument (an editor - instance).

    - -

    Some of the commands below are referenced in the default - key map, but not defined by the core library. These are intended to - be defined by user code or addons.

    - -

    Commands can also be run with - the execCommand - method.

    - -
    -
    selectAllCtrl-A (PC), Cmd-A (Mac)
    -
    Select the whole content of the editor.
    - -
    singleSelectionEsc
    -
    When multiple selections are present, this deselects all but - the primary selection.
    - -
    killLineCtrl-K (Mac)
    -
    Emacs-style line killing. Deletes the part of the line after - the cursor. If that consists only of whitespace, the newline at - the end of the line is also deleted.
    - -
    deleteLineCtrl-D (PC), Cmd-D (Mac)
    -
    Deletes the whole line under the cursor, including newline at the end.
    - -
    delLineLeft
    -
    Delete the part of the line before the cursor.
    - -
    delWrappedLineLeftCmd-Backspace (Mac)
    -
    Delete the part of the line from the left side of the visual line the cursor is on to the cursor.
    - -
    delWrappedLineRightCmd-Delete (Mac)
    -
    Delete the part of the line from the cursor to the right side of the visual line the cursor is on.
    - -
    undoCtrl-Z (PC), Cmd-Z (Mac)
    -
    Undo the last change.
    - -
    redoCtrl-Y (PC), Shift-Cmd-Z (Mac), Cmd-Y (Mac)
    -
    Redo the last undone change.
    - -
    undoSelectionCtrl-U (PC), Cmd-U (Mac)
    -
    Undo the last change to the selection, or if there are no - selection-only changes at the top of the history, undo the last - change.
    - -
    redoSelectionAlt-U (PC), Shift-Cmd-U (Mac)
    -
    Redo the last change to the selection, or the last text change if - no selection changes remain.
    - -
    goDocStartCtrl-Home (PC), Cmd-Up (Mac), Cmd-Home (Mac)
    -
    Move the cursor to the start of the document.
    - -
    goDocEndCtrl-End (PC), Cmd-End (Mac), Cmd-Down (Mac)
    -
    Move the cursor to the end of the document.
    - -
    goLineStartAlt-Left (PC), Ctrl-A (Mac)
    -
    Move the cursor to the start of the line.
    - -
    goLineStartSmartHome
    -
    Move to the start of the text on the line, or if we are - already there, to the actual start of the line (including - whitespace).
    - -
    goLineEndAlt-Right (PC), Ctrl-E (Mac)
    -
    Move the cursor to the end of the line.
    - -
    goLineRightCmd-Right (Mac)
    -
    Move the cursor to the right side of the visual line it is on.
    - -
    goLineLeftCmd-Left (Mac)
    -
    Move the cursor to the left side of the visual line it is on. If - this line is wrapped, that may not be the start of the line.
    - -
    goLineLeftSmart
    -
    Move the cursor to the left side of the visual line it is - on. If that takes it to the start of the line, behave - like goLineStartSmart.
    - -
    goLineUpUp, Ctrl-P (Mac)
    -
    Move the cursor up one line.
    - -
    goLineDownDown, Ctrl-N (Mac)
    -
    Move down one line.
    - -
    goPageUpPageUp, Shift-Ctrl-V (Mac)
    -
    Move the cursor up one screen, and scroll up by the same distance.
    - -
    goPageDownPageDown, Ctrl-V (Mac)
    -
    Move the cursor down one screen, and scroll down by the same distance.
    - -
    goCharLeftLeft, Ctrl-B (Mac)
    -
    Move the cursor one character left, going to the previous line - when hitting the start of line.
    - -
    goCharRightRight, Ctrl-F (Mac)
    -
    Move the cursor one character right, going to the next line - when hitting the end of line.
    - -
    goColumnLeft
    -
    Move the cursor one character left, but don't cross line boundaries.
    - -
    goColumnRight
    -
    Move the cursor one character right, don't cross line boundaries.
    - -
    goWordLeftAlt-B (Mac)
    -
    Move the cursor to the start of the previous word.
    - -
    goWordRightAlt-F (Mac)
    -
    Move the cursor to the end of the next word.
    - -
    goGroupLeftCtrl-Left (PC), Alt-Left (Mac)
    -
    Move to the left of the group before the cursor. A group is - a stretch of word characters, a stretch of punctuation - characters, a newline, or a stretch of more than one - whitespace character.
    - -
    goGroupRightCtrl-Right (PC), Alt-Right (Mac)
    -
    Move to the right of the group after the cursor - (see above).
    - -
    delCharBeforeShift-Backspace, Ctrl-H (Mac)
    -
    Delete the character before the cursor.
    - -
    delCharAfterDelete, Ctrl-D (Mac)
    -
    Delete the character after the cursor.
    - -
    delWordBeforeAlt-Backspace (Mac)
    -
    Delete up to the start of the word before the cursor.
    - -
    delWordAfterAlt-D (Mac)
    -
    Delete up to the end of the word after the cursor.
    - -
    delGroupBeforeCtrl-Backspace (PC), Alt-Backspace (Mac)
    -
    Delete to the left of the group before the cursor.
    - -
    delGroupAfterCtrl-Delete (PC), Ctrl-Alt-Backspace (Mac), Alt-Delete (Mac)
    -
    Delete to the start of the group after the cursor.
    - -
    indentAutoShift-Tab
    -
    Auto-indent the current line or selection.
    - -
    indentMoreCtrl-] (PC), Cmd-] (Mac)
    -
    Indent the current line or selection by one indent unit.
    - -
    indentLessCtrl-[ (PC), Cmd-[ (Mac)
    -
    Dedent the current line or selection by one indent unit.
    - -
    insertTab
    -
    Insert a tab character at the cursor.
    - -
    insertSoftTab
    -
    Insert the amount of spaces that match the width a tab at - the cursor position would have.
    - -
    defaultTabTab
    -
    If something is selected, indent it by - one indent unit. If nothing is - selected, insert a tab character.
    - -
    transposeCharsCtrl-T (Mac)
    -
    Swap the characters before and after the cursor.
    - -
    newlineAndIndentEnter
    -
    Insert a newline and auto-indent the new line.
    - -
    toggleOverwriteInsert
    -
    Flip the overwrite flag.
    - -
    saveCtrl-S (PC), Cmd-S (Mac)
    -
    Not defined by the core library, only referred to in - key maps. Intended to provide an easy way for user code to define - a save command.
    - -
    findCtrl-F (PC), Cmd-F (Mac)
    -
    findNextCtrl-G (PC), Cmd-G (Mac)
    -
    findPrevShift-Ctrl-G (PC), Shift-Cmd-G (Mac)
    -
    replaceShift-Ctrl-F (PC), Cmd-Alt-F (Mac)
    -
    replaceAllShift-Ctrl-R (PC), Shift-Cmd-Alt-F (Mac)
    -
    Not defined by the core library, but defined in - the search addon (or custom client - addons).
    - -
    - -
    - -
    -

    Customized Styling

    - -

    Up to a certain extent, CodeMirror's look can be changed by - modifying style sheet files. The style sheets supplied by modes - simply provide the colors for that mode, and can be adapted in a - very straightforward way. To style the editor itself, it is - possible to alter or override the styles defined - in codemirror.css.

    - -

    Some care must be taken there, since a lot of the rules in this - file are necessary to have CodeMirror function properly. Adjusting - colors should be safe, of course, and with some care a lot of - other things can be changed as well. The CSS classes defined in - this file serve the following roles:

    - -
    -
    CodeMirror
    -
    The outer element of the editor. This should be used for the - editor width, height, borders and positioning. Can also be used - to set styles that should hold for everything inside the editor - (such as font and font size), or to set a background. Setting - this class' height style to auto will - make the editor resize to fit its - content (it is recommended to also set - the viewportMargin - option to Infinity when doing this.
    - -
    CodeMirror-focused
    -
    Whenever the editor is focused, the top element gets this - class. This is used to hide the cursor and give the selection a - different color when the editor is not focused.
    - -
    CodeMirror-gutters
    -
    This is the backdrop for all gutters. Use it to set the - default gutter background color, and optionally add a border on - the right of the gutters.
    - -
    CodeMirror-linenumbers
    -
    Use this for giving a background or width to the line number - gutter.
    - -
    CodeMirror-linenumber
    -
    Used to style the actual individual line numbers. These - won't be children of the CodeMirror-linenumbers - (plural) element, but rather will be absolutely positioned to - overlay it. Use this to set alignment and text properties for - the line numbers.
    - -
    CodeMirror-lines
    -
    The visible lines. This is where you specify vertical - padding for the editor content.
    - -
    CodeMirror-cursor
    -
    The cursor is a block element that is absolutely positioned. - You can make it look whichever way you want.
    - -
    CodeMirror-selected
    -
    The selection is represented by span elements - with this class.
    - -
    CodeMirror-matchingbracket, - CodeMirror-nonmatchingbracket
    -
    These are used to style matched (or unmatched) brackets.
    -
    - -

    If your page's style sheets do funky things to - all div or pre elements (you probably - shouldn't do that), you'll have to define rules to cancel these - effects out again for elements under the CodeMirror - class.

    - -

    Themes are also simply CSS files, which define colors for - various syntactic elements. See the files in - the theme directory.

    -
    - -
    -

    Programming API

    - -

    A lot of CodeMirror features are only available through its - API. Thus, you need to write code (or - use addons) if you want to expose them to - your users.

    - -

    Whenever points in the document are represented, the API uses - objects with line and ch properties. - Both are zero-based. CodeMirror makes sure to 'clip' any positions - passed by client code so that they fit inside the document, so you - shouldn't worry too much about sanitizing your coordinates. If you - give ch a value of null, or don't - specify it, it will be replaced with the length of the specified - line.

    - -

    Methods prefixed with doc. can, unless otherwise - specified, be called both on CodeMirror (editor) - instances and CodeMirror.Doc instances. Methods - prefixed with cm. are only available - on CodeMirror instances.

    - -

    Constructor

    - -

    Constructing an editor instance is done with - the CodeMirror(place: Element|fn(Element), - ?option: object) constructor. If the place - argument is a DOM element, the editor will be appended to it. If - it is a function, it will be called, and is expected to place the - editor into the document. options may be an element - mapping option names to values. The options - that it doesn't explicitly specify (or all options, if it is not - passed) will be taken - from CodeMirror.defaults.

    - -

    Note that the options object passed to the constructor will be - mutated when the instance's options - are changed, so you shouldn't share such - objects between instances.

    - -

    See CodeMirror.fromTextArea - for another way to construct an editor instance.

    - -

    Content manipulation methods

    - -
    -
    doc.getValue(?separator: string) → string
    -
    Get the current editor content. You can pass it an optional - argument to specify the string to be used to separate lines - (defaults to "\n").
    -
    doc.setValue(content: string)
    -
    Set the editor content.
    - -
    doc.getRange(from: {line, ch}, to: {line, ch}, ?separator: string) → string
    -
    Get the text between the given points in the editor, which - should be {line, ch} objects. An optional third - argument can be given to indicate the line separator string to - use (defaults to "\n").
    -
    doc.replaceRange(replacement: string, from: {line, ch}, to: {line, ch}, ?origin: string)
    -
    Replace the part of the document between from - and to with the given string. from - and to must be {line, ch} - objects. to can be left off to simply insert the - string at position from. When origin - is given, it will be passed on - to "change" events, and - its first letter will be used to determine whether this change - can be merged with previous history events, in the way described - for selection origins.
    - -
    doc.getLine(n: integer) → string
    -
    Get the content of line n.
    - -
    doc.lineCount() → integer
    -
    Get the number of lines in the editor.
    -
    doc.firstLine() → integer
    -
    Get the first line of the editor. This will - usually be zero but for linked sub-views, - or documents instantiated with a non-zero - first line, it might return other values.
    -
    doc.lastLine() → integer
    -
    Get the last line of the editor. This will - usually be doc.lineCount() - 1, - but for linked sub-views, - it might return other values.
    - -
    doc.getLineHandle(num: integer) → LineHandle
    -
    Fetches the line handle for the given line number.
    -
    doc.getLineNumber(handle: LineHandle) → integer
    -
    Given a line handle, returns the current position of that - line (or null when it is no longer in the - document).
    -
    doc.eachLine(f: (line: LineHandle))
    -
    doc.eachLine(start: integer, end: integer, f: (line: LineHandle))
    -
    Iterate over the whole document, or if start - and end line numbers are given, the range - from start up to (not including) end, - and call f for each line, passing the line handle. - This is a faster way to visit a range of line handlers than - calling getLineHandle - for each of them. Note that line handles have - a text property containing the line's content (as a - string).
    - -
    doc.markClean()
    -
    Set the editor content as 'clean', a flag that it will - retain until it is edited, and which will be set again when such - an edit is undone again. Useful to track whether the content - needs to be saved. This function is deprecated in favor - of changeGeneration, - which allows multiple subsystems to track different notions of - cleanness without interfering.
    -
    doc.changeGeneration(?closeEvent: boolean) → integer
    -
    Returns a number that can later be passed - to isClean to test whether - any edits were made (and not undone) in the meantime. - If closeEvent is true, the current history event - will be ‘closed’, meaning it can't be combined with further - changes (rapid typing or deleting events are typically - combined).
    -
    doc.isClean(?generation: integer) → boolean
    -
    Returns whether the document is currently clean — not - modified since initialization or the last call - to markClean if no - argument is passed, or since the matching call - to changeGeneration - if a generation value is given.
    -
    - -

    Cursor and selection methods

    - -
    -
    doc.getSelection(?lineSep: string) → string
    -
    Get the currently selected code. Optionally pass a line - separator to put between the lines in the output. When multiple - selections are present, they are concatenated with instances - of lineSep in between.
    -
    doc.getSelections(?lineSep: string) → array<string>
    -
    Returns an array containing a string for each selection, - representing the content of the selections.
    - -
    doc.replaceSelection(replacement: string, ?select: string)
    -
    Replace the selection(s) with the given string. By default, - the new selection ends up after the inserted text. The - optional select argument can be used to change - this—passing "around" will cause the new text to be - selected, passing "start" will collapse the - selection to the start of the inserted text.
    -
    doc.replaceSelections(replacements: array<string>, ?select: string)
    -
    The length of the given array should be the same as the - number of active selections. Replaces the content of the - selections with the strings in the array. - The select argument works the same as - in replaceSelection.
    - -
    doc.getCursor(?start: string) → {line, ch}
    -
    Retrieve one end of the primary - selection. start is an optional string indicating - which end of the selection to return. It may - be "from", "to", "head" - (the side of the selection that moves when you press - shift+arrow), or "anchor" (the fixed side of the - selection). Omitting the argument is the same as - passing "head". A {line, ch} object - will be returned.
    -
    doc.listSelections() → array<{anchor, head}>
    -
    Retrieves a list of all current selections. These will - always be sorted, and never overlap (overlapping selections are - merged). Each object in the array contains anchor - and head properties referring to {line, - ch} objects.
    - -
    doc.somethingSelected() → boolean
    -
    Return true if any text is selected.
    -
    doc.setCursor(pos: {line, ch}|number, ?ch: number, ?options: object)
    -
    Set the cursor position. You can either pass a - single {line, ch} object, or the line and the - character as two separate parameters. Will replace all - selections with a single, empty selection at the given position. - The supported options are the same as for setSelection.
    - -
    doc.setSelection(anchor: {line, ch}, ?head: {line, ch}, ?options: object)
    -
    Set a single selection range. anchor - and head should be {line, ch} - objects. head defaults to anchor when - not given. These options are supported: -
    -
    scroll: boolean
    -
    Determines whether the selection head should be scrolled - into view. Defaults to true.
    -
    origin: string
    -
    Determines whether the selection history event may be - merged with the previous one. When an origin starts with the - character +, and the last recorded selection had - the same origin and was similar (close - in time, both - collapsed or both non-collapsed), the new one will replace the - old one. When it starts with *, it will always - replace the previous event (if that had the same origin). - Built-in motion uses the "+move" origin. User input uses the "+input" origin.
    -
    bias: number
    -
    Determine the direction into which the selection endpoints - should be adjusted when they fall inside - an atomic range. Can be either -1 - (backward) or 1 (forward). When not given, the bias will be - based on the relative position of the old selection—the editor - will try to move further away from that, to prevent getting - stuck.
    -
    - -
    doc.setSelections(ranges: array<{anchor, head}>, ?primary: integer, ?options: object)
    -
    Sets a new set of selections. There must be at least one - selection in the given array. When primary is a - number, it determines which selection is the primary one. When - it is not given, the primary index is taken from the previous - selection, or set to the last range if the previous selection - had less ranges than the new one. Supports the same options - as setSelection.
    -
    doc.addSelection(anchor: {line, ch}, ?head: {line, ch})
    -
    Adds a new selection to the existing set of selections, and - makes it the primary selection.
    - -
    doc.extendSelection(from: {line, ch}, ?to: {line, ch}, ?options: object)
    -
    Similar - to setSelection, but - will, if shift is held or - the extending flag is set, move the - head of the selection while leaving the anchor at its current - place. to is optional, and can be passed to ensure - a region (for example a word or paragraph) will end up selected - (in addition to whatever lies between that region and the - current anchor). When multiple selections are present, all but - the primary selection will be dropped by this method. - Supports the same options as setSelection.
    -
    doc.extendSelections(heads: array<{line, ch}>, ?options: object)
    -
    An equivalent - of extendSelection - that acts on all selections at once.
    -
    doc.extendSelectionsBy(f: function(range: {anchor, head}) → {line, ch}), ?options: object)
    -
    Applies the given function to all existing selections, and - calls extendSelections - on the result.
    -
    doc.setExtending(value: boolean)
    -
    Sets or clears the 'extending' flag, which acts similar to - the shift key, in that it will cause cursor movement and calls - to extendSelection - to leave the selection anchor in place.
    -
    doc.getExtending() → boolean
    -
    Get the value of the 'extending' flag.
    - -
    cm.hasFocus() → boolean
    -
    Tells you whether the editor currently has focus.
    - -
    cm.findPosH(start: {line, ch}, amount: integer, unit: string, visually: boolean) → {line, ch, ?hitSide: boolean}
    -
    Used to find the target position for horizontal cursor - motion. start is a {line, ch} - object, amount an integer (may be negative), - and unit one of the - string "char", "column", - or "word". Will return a position that is produced - by moving amount times the distance specified - by unit. When visually is true, motion - in right-to-left text will be visual rather than logical. When - the motion was clipped by hitting the end or start of the - document, the returned value will have a hitSide - property set to true.
    -
    cm.findPosV(start: {line, ch}, amount: integer, unit: string) → {line, ch, ?hitSide: boolean}
    -
    Similar to findPosH, - but used for vertical motion. unit may - be "line" or "page". The other - arguments and the returned value have the same interpretation as - they have in findPosH.
    - -
    cm.findWordAt(pos: {line, ch}) → {anchor: {line, ch}, head: {line, ch}}
    -
    Returns the start and end of the 'word' (the stretch of - letters, whitespace, or punctuation) at the given position.
    -
    - -

    Configuration methods

    - -
    -
    cm.setOption(option: string, value: any)
    -
    Change the configuration of the editor. option - should the name of an option, - and value should be a valid value for that - option.
    -
    cm.getOption(option: string) → any
    -
    Retrieves the current value of the given option for this - editor instance.
    - -
    cm.addKeyMap(map: object, bottom: boolean)
    -
    Attach an additional key map to the - editor. This is mostly useful for addons that need to register - some key handlers without trampling on - the extraKeys - option. Maps added in this way have a higher precedence than - the extraKeys - and keyMap options, - and between them, the maps added earlier have a lower precedence - than those added later, unless the bottom argument - was passed, in which case they end up below other key maps added - with this method.
    -
    cm.removeKeyMap(map: object)
    -
    Disable a keymap added - with addKeyMap. Either - pass in the key map object itself, or a string, which will be - compared against the name property of the active - key maps.
    - -
    cm.addOverlay(mode: string|object, ?options: object)
    -
    Enable a highlighting overlay. This is a stateless mini-mode - that can be used to add extra highlighting. For example, - the search addon uses it to - highlight the term that's currently being - searched. mode can be a mode - spec or a mode object (an object with - a token method). - The options parameter is optional. If given, it - should be an object, optionally containing the following options: -
    -
    opaque: bool
    -
    Defaults to off, but can be given to allow the overlay - styling, when not null, to override the styling of - the base mode entirely, instead of the two being applied - together.
    -
    priority: number
    -
    Determines the ordering in which the overlays are - applied. Those with high priority are applied after those - with lower priority, and able to override the opaqueness of - the ones that come before. Defaults to 0.
    -
    -
    - -
    cm.removeOverlay(mode: string|object)
    -
    Pass this the exact value passed for the mode - parameter to addOverlay, - or a string that corresponds to the name property of - that value, to remove an overlay again.
    - -
    cm.on(type: string, func: (...args))
    -
    Register an event handler for the given event type (a - string) on the editor instance. There is also - a CodeMirror.on(object, type, func) version - that allows registering of events on any object.
    -
    cm.off(type: string, func: (...args))
    -
    Remove an event handler on the editor instance. An - equivalent CodeMirror.off(object, type, - func) also exists.
    -
    - -

    Document management methods

    - -

    Each editor is associated with an instance - of CodeMirror.Doc, its document. A document - represents the editor content, plus a selection, an undo history, - and a mode. A document can only be - associated with a single editor at a time. You can create new - documents by calling the CodeMirror.Doc(text, mode, - firstLineNumber) constructor. The last two arguments are - optional and can be used to set a mode for the document and make - it start at a line number other than 0, respectively.

    - -
    -
    cm.getDoc() → Doc
    -
    Retrieve the currently active document from an editor.
    -
    doc.getEditor() → CodeMirror
    -
    Retrieve the editor associated with a document. May - return null.
    - -
    cm.swapDoc(doc: CodeMirror.Doc) → Doc
    -
    Attach a new document to the editor. Returns the old - document, which is now no longer associated with an editor.
    - -
    doc.copy(copyHistory: boolean) → Doc
    -
    Create an identical copy of the given doc. - When copyHistory is true, the history will also be - copied. Can not be called directly on an editor.
    - -
    doc.linkedDoc(options: object) → Doc
    -
    Create a new document that's linked to the target document. - Linked documents will stay in sync (changes to one are also - applied to the other) until unlinked. - These are the options that are supported: -
    -
    sharedHist: boolean
    -
    When turned on, the linked copy will share an undo - history with the original. Thus, something done in one of - the two can be undone in the other, and vice versa.
    -
    from: integer
    -
    to: integer
    -
    Can be given to make the new document a subview of the - original. Subviews only show a given range of lines. Note - that line coordinates inside the subview will be consistent - with those of the parent, so that for example a subview - starting at line 10 will refer to its first line as line 10, - not 0.
    -
    mode: string|object
    -
    By default, the new document inherits the mode of the - parent. This option can be set to - a mode spec to give it a - different mode.
    -
    -
    doc.unlinkDoc(doc: CodeMirror.Doc)
    -
    Break the link between two documents. After calling this, - changes will no longer propagate between the documents, and, if - they had a shared history, the history will become - separate.
    -
    doc.iterLinkedDocs(function: (doc: CodeMirror.Doc, sharedHist: boolean))
    -
    Will call the given function for all documents linked to the - target document. It will be passed two arguments, the linked document - and a boolean indicating whether that document shares history - with the target.
    -
    - -

    History-related methods

    - -
    -
    doc.undo()
    -
    Undo one edit (if any undo events are stored).
    -
    doc.redo()
    -
    Redo one undone edit.
    - -
    doc.undoSelection()
    -
    Undo one edit or selection change.
    -
    doc.redoSelection()
    -
    Redo one undone edit or selection change.
    - -
    doc.historySize() → {undo: integer, redo: integer}
    -
    Returns an object with {undo, redo} properties, - both of which hold integers, indicating the amount of stored - undo and redo operations.
    -
    doc.clearHistory()
    -
    Clears the editor's undo history.
    -
    doc.getHistory() → object
    -
    Get a (JSON-serializable) representation of the undo history.
    -
    doc.setHistory(history: object)
    -
    Replace the editor's undo history with the one provided, - which must be a value as returned - by getHistory. Note that - this will have entirely undefined results if the editor content - isn't also the same as it was when getHistory was - called.
    -
    - -

    Text-marking methods

    - -
    -
    doc.markText(from: {line, ch}, to: {line, ch}, ?options: object) → TextMarker
    -
    Can be used to mark a range of text with a specific CSS - class name. from and to should - be {line, ch} objects. The options - parameter is optional. When given, it should be an object that - may contain the following configuration options: -
    -
    className: string
    -
    Assigns a CSS class to the marked stretch of text.
    -
    inclusiveLeft: boolean
    -
    Determines whether - text inserted on the left of the marker will end up inside - or outside of it.
    -
    inclusiveRight: boolean
    -
    Like inclusiveLeft, - but for the right side.
    -
    atomic: boolean
    -
    Atomic ranges act as a single unit when cursor movement is - concerned—i.e. it is impossible to place the cursor inside of - them. In atomic ranges, inclusiveLeft - and inclusiveRight have a different meaning—they - will prevent the cursor from being placed respectively - directly before and directly after the range.
    -
    collapsed: boolean
    -
    Collapsed ranges do not show up in the display. Setting a - range to be collapsed will automatically make it atomic.
    -
    clearOnEnter: boolean
    -
    When enabled, will cause the mark to clear itself whenever - the cursor enters its range. This is mostly useful for - text-replacement widgets that need to 'snap open' when the - user tries to edit them. The - "clear" event - fired on the range handle can be used to be notified when this - happens.
    -
    clearWhenEmpty: boolean
    -
    Determines whether the mark is automatically cleared when - it becomes empty. Default is true.
    -
    replacedWith: Element
    -
    Use a given node to display this range. Implies both - collapsed and atomic. The given DOM node must be an - inline element (as opposed to a block element).
    -
    handleMouseEvents: boolean
    -
    When replacedWith is given, this determines - whether the editor will capture mouse and drag events - occurring in this widget. Default is false—the events will be - left alone for the default browser handler, or specific - handlers on the widget, to capture.
    -
    readOnly: boolean
    -
    A read-only span can, as long as it is not cleared, not be - modified except by - calling setValue to reset - the whole document. Note: adding a read-only span - currently clears the undo history of the editor, because - existing undo events being partially nullified by read-only - spans would corrupt the history (in the current - implementation).
    -
    addToHistory: boolean
    -
    When set to true (default is false), adding this marker - will create an event in the undo history that can be - individually undone (clearing the marker).
    -
    startStyle: string
    Can be used to specify - an extra CSS class to be applied to the leftmost span that - is part of the marker.
    -
    endStyle: string
    Equivalent - to startStyle, but for the rightmost span.
    -
    css: string
    -
    A string of CSS to be applied to the covered text. For example "color: #fe3".
    -
    title: - string
    When given, will give the nodes created - for this span a HTML title attribute with the - given value.
    -
    shared: boolean
    When the - target document is linked to other - documents, you can set shared to true to make the - marker appear in all documents. By default, a marker appears - only in its target document.
    -
    - The method will return an object that represents the marker - (with constructor CodeMirror.TextMarker), which - exposes three methods: - clear(), to remove the mark, - find(), which returns - a {from, to} object (both holding document - positions), indicating the current position of the marked range, - or undefined if the marker is no longer in the - document, and finally changed(), - which you can call if you've done something that might change - the size of the marker (for example changing the content of - a replacedWith - node), and want to cheaply update the display.
    - -
    doc.setBookmark(pos: {line, ch}, ?options: object) → TextMarker
    -
    Inserts a bookmark, a handle that follows the text around it - as it is being edited, at the given position. A bookmark has two - methods find() and clear(). The first - returns the current position of the bookmark, if it is still in - the document, and the second explicitly removes the bookmark. - The options argument is optional. If given, the following - properties are recognized: -
    -
    widget: Element
    Can be used to display a DOM - node at the current location of the bookmark (analogous to - the replacedWith - option to markText).
    -
    insertLeft: boolean
    By default, text typed - when the cursor is on top of the bookmark will end up to the - right of the bookmark. Set this option to true to make it go - to the left instead.
    -
    shared: boolean
    See - the corresponding option - to markText.
    -
    handleMouseEvents: boolean
    -
    As with markText, - this determines whether mouse events on the widget inserted - for this bookmark are handled by CodeMirror. The default is - false.
    -
    - -
    doc.findMarks(from: {line, ch}, to: {line, ch}) → array<TextMarker>
    -
    Returns an array of all the bookmarks and marked ranges - found between the given positions (non-inclusive).
    -
    doc.findMarksAt(pos: {line, ch}) → array<TextMarker>
    -
    Returns an array of all the bookmarks and marked ranges - present at the given position.
    -
    doc.getAllMarks() → array<TextMarker>
    -
    Returns an array containing all marked ranges in the document.
    -
    - -

    Widget, gutter, and decoration methods

    - -
    -
    doc.setGutterMarker(line: integer|LineHandle, gutterID: string, value: Element) → LineHandle
    -
    Sets the gutter marker for the given gutter (identified by - its CSS class, see - the gutters option) - to the given value. Value can be either null, to - clear the marker, or a DOM element, to set it. The DOM element - will be shown in the specified gutter next to the specified - line.
    - -
    doc.clearGutter(gutterID: string)
    -
    Remove all gutter markers in - the gutter with the given ID.
    - -
    doc.addLineClass(line: integer|LineHandle, where: string, class: string) → LineHandle
    -
    Set a CSS class name for the given line. line - can be a number or a line handle. where determines - to which element this class should be applied, can can be one - of "text" (the text element, which lies in front of - the selection), "background" (a background element - that will be behind the selection), "gutter" (the - line's gutter space), or "wrap" (the wrapper node - that wraps all of the line's elements, including gutter - elements). class should be the name of the class to - apply.
    - -
    doc.removeLineClass(line: integer|LineHandle, where: string, class: string) → LineHandle
    -
    Remove a CSS class from a line. line can be a - line handle or number. where should be one - of "text", "background", - or "wrap" - (see addLineClass). class - can be left off to remove all classes for the specified node, or - be a string to remove only a specific class.
    - -
    doc.lineInfo(line: integer|LineHandle) → object
    -
    Returns the line number, text content, and marker status of - the given line, which can be either a number or a line handle. - The returned object has the structure {line, handle, text, - gutterMarkers, textClass, bgClass, wrapClass, widgets}, - where gutterMarkers is an object mapping gutter IDs - to marker elements, and widgets is an array - of line widgets attached to this - line, and the various class properties refer to classes added - with addLineClass.
    - -
    cm.addWidget(pos: {line, ch}, node: Element, scrollIntoView: boolean)
    -
    Puts node, which should be an absolutely - positioned DOM node, into the editor, positioned right below the - given {line, ch} position. - When scrollIntoView is true, the editor will ensure - that the entire node is visible (if possible). To remove the - widget again, simply use DOM methods (move it somewhere else, or - call removeChild on its parent).
    - -
    doc.addLineWidget(line: integer|LineHandle, node: Element, ?options: object) → LineWidget
    -
    Adds a line widget, an element shown below a line, spanning - the whole of the editor's width, and moving the lines below it - downwards. line should be either an integer or a - line handle, and node should be a DOM node, which - will be displayed below the given line. options, - when given, should be an object that configures the behavior of - the widget. The following options are supported (all default to - false): -
    -
    coverGutter: boolean
    -
    Whether the widget should cover the gutter.
    -
    noHScroll: boolean
    -
    Whether the widget should stay fixed in the face of - horizontal scrolling.
    -
    above: boolean
    -
    Causes the widget to be placed above instead of below - the text of the line.
    -
    handleMouseEvents: boolean
    -
    Determines whether the editor will capture mouse and - drag events occurring in this widget. Default is false—the - events will be left alone for the default browser handler, - or specific handlers on the widget, to capture.
    -
    insertAt: integer
    -
    By default, the widget is added below other widgets for - the line. This option can be used to place it at a different - position (zero for the top, N to put it after the Nth other - widget). Note that this only has effect once, when the - widget is created. -
    - Note that the widget node will become a descendant of nodes with - CodeMirror-specific CSS classes, and those classes might in some - cases affect it. This method returns an object that represents - the widget placement. It'll have a line property - pointing at the line handle that it is associated with, and the following methods: -
    -
    clear()
    Removes the widget.
    -
    changed()
    Call - this if you made some change to the widget's DOM node that - might affect its height. It'll force CodeMirror to update - the height of the line that contains the widget.
    -
    -
    -
    - -

    Sizing, scrolling and positioning methods

    - -
    -
    cm.setSize(width: number|string, height: number|string)
    -
    Programmatically set the size of the editor (overriding the - applicable CSS - rules). width and height - can be either numbers (interpreted as pixels) or CSS units - ("100%", for example). You can - pass null for either of them to indicate that that - dimension should not be changed.
    - -
    cm.scrollTo(x: number, y: number)
    -
    Scroll the editor to a given (pixel) position. Both - arguments may be left as null - or undefined to have no effect.
    -
    cm.getScrollInfo() → {left, top, width, height, clientWidth, clientHeight}
    -
    Get an {left, top, width, height, clientWidth, - clientHeight} object that represents the current scroll - position, the size of the scrollable area, and the size of the - visible area (minus scrollbars).
    -
    cm.scrollIntoView(what: {line, ch}|{left, top, right, bottom}|{from, to}|null, ?margin: number)
    -
    Scrolls the given position into view. what may - be null to scroll the cursor into view, - a {line, ch} position to scroll a character into - view, a {left, top, right, bottom} pixel range (in - editor-local coordinates), or a range {from, to} - containing either two character positions or two pixel squares. - The margin parameter is optional. When given, it - indicates the amount of vertical pixels around the given area - that should be made visible as well.
    - -
    cm.cursorCoords(where: boolean|{line, ch}, mode: string) → {left, top, bottom}
    -
    Returns an {left, top, bottom} object - containing the coordinates of the cursor position. - If mode is "local", they will be - relative to the top-left corner of the editable document. If it - is "page" or not given, they are relative to the - top-left corner of the page. If mode - is "window", the coordinates are relative to the - top-left corner of the currently visible (scrolled) - window. where can be a boolean indicating whether - you want the start (true) or the end - (false) of the selection, or, if a {line, - ch} object is given, it specifies the precise position at - which you want to measure.
    -
    cm.charCoords(pos: {line, ch}, ?mode: string) → {left, right, top, bottom}
    -
    Returns the position and dimensions of an arbitrary - character. pos should be a {line, ch} - object. This differs from cursorCoords in that - it'll give the size of the whole character, rather than just the - position that the cursor would have when it would sit at that - position.
    -
    cm.coordsChar(object: {left, top}, ?mode: string) → {line, ch}
    -
    Given an {left, top} object, returns - the {line, ch} position that corresponds to it. The - optional mode parameter determines relative to what - the coordinates are interpreted. It may - be "window", "page" (the default), - or "local".
    -
    cm.lineAtHeight(height: number, ?mode: string) → number
    -
    Computes the line at the given pixel - height. mode can be one of the same strings - that coordsChar - accepts.
    -
    cm.heightAtLine(line: integer|LineHandle, ?mode: string, ?includeWidgets: bool) → number
    -
    Computes the height of the top of a line, in the coordinate - system specified by mode - (see coordsChar), which - defaults to "page". When a line below the bottom of - the document is specified, the returned value is the bottom of - the last line in the document. By default, the position of the - actual text is returned. If `includeWidgets` is true and the - line has line widgets, the position above the first line widget - is returned.
    -
    cm.defaultTextHeight() → number
    -
    Returns the line height of the default font for the editor.
    -
    cm.defaultCharWidth() → number
    -
    Returns the pixel width of an 'x' in the default font for - the editor. (Note that for non-monospace fonts, this is mostly - useless, and even for monospace fonts, non-ascii characters - might have a different width).
    - -
    cm.getViewport() → {from: number, to: number}
    -
    Returns a {from, to} object indicating the - start (inclusive) and end (exclusive) of the currently rendered - part of the document. In big documents, when most content is - scrolled out of view, CodeMirror will only render the visible - part, and a margin around it. See also - the viewportChange - event.
    - -
    cm.refresh()
    -
    If your code does something to change the size of the editor - element (window resizes are already listened for), or unhides - it, you should probably follow up by calling this method to - ensure CodeMirror is still looking as intended. See also - the autorefresh addon.
    -
    - -

    Mode, state, and token-related methods

    - -

    When writing language-aware functionality, it can often be - useful to hook into the knowledge that the CodeMirror language - mode has. See the section on modes for a - more detailed description of how these work.

    - -
    -
    doc.getMode() → object
    -
    Gets the (outer) mode object for the editor. Note that this - is distinct from getOption("mode"), which gives you - the mode specification, rather than the resolved, instantiated - mode object.
    - -
    cm.getModeAt(pos: {line, ch}) → object
    -
    Gets the inner mode at a given position. This will return - the same as getMode for - simple modes, but will return an inner mode for nesting modes - (such as htmlmixed).
    - -
    cm.getTokenAt(pos: {line, ch}, ?precise: boolean) → object
    -
    Retrieves information about the token the current mode found - before the given position (a {line, ch} object). The - returned object has the following properties: -
    -
    start
    The character (on the given line) at which the token starts.
    -
    end
    The character at which the token ends.
    -
    string
    The token's string.
    -
    type
    The token type the mode assigned - to the token, such as "keyword" - or "comment" (may also be null).
    -
    state
    The mode's state at the end of this token.
    -
    - If precise is true, the token will be guaranteed to be accurate based on recent edits. If false or - not specified, the token will use cached state information, which will be faster but might not be accurate if - edits were recently made and highlighting has not yet completed. -
    - -
    cm.getLineTokens(line: integer, ?precise: boolean) → array<{start, end, string, type, state}>
    -
    This is similar - to getTokenAt, but - collects all tokens for a given line into an array. It is much - cheaper than repeatedly calling getTokenAt, which - re-parses the part of the line before the token for every call.
    - -
    cm.getTokenTypeAt(pos: {line, ch}) → string
    -
    This is a (much) cheaper version - of getTokenAt useful for - when you just need the type of the token at a given position, - and no other information. Will return null for - unstyled tokens, and a string, potentially containing multiple - space-separated style names, otherwise.
    - -
    cm.getHelpers(pos: {line, ch}, type: string) → array<helper>
    -
    Fetch the set of applicable helper values for the given - position. Helpers provide a way to look up functionality - appropriate for a mode. The type argument provides - the helper namespace (see - registerHelper), in - which the values will be looked up. When the mode itself has a - property that corresponds to the type, that - directly determines the keys that are used to look up the helper - values (it may be either a single string, or an array of - strings). Failing that, the mode's helperType - property and finally the mode's name are used.
    -
    For example, the JavaScript mode has a - property fold containing "brace". When - the brace-fold addon is loaded, that defines a - helper named brace in the fold - namespace. This is then used by - the foldcode addon to - figure out that it can use that folding function to fold - JavaScript code.
    -
    When any 'global' - helpers are defined for the given namespace, their predicates - are called on the current mode and editor, and all those that - declare they are applicable will also be added to the array that - is returned.
    - -
    cm.getHelper(pos: {line, ch}, type: string) → helper
    -
    Returns the first applicable helper value. - See getHelpers.
    - -
    cm.getStateAfter(?line: integer, ?precise: boolean) → object
    -
    Returns the mode's parser state, if any, at the end of the - given line number. If no line number is given, the state at the - end of the document is returned. This can be useful for storing - parsing errors in the state, or getting other kinds of - contextual information for a line. precise is defined - as in getTokenAt().
    -
    - -

    Miscellaneous methods

    - -
    -
    cm.operation(func: () → any) → any
    -
    CodeMirror internally buffers changes and only updates its - DOM structure after it has finished performing some operation. - If you need to perform a lot of operations on a CodeMirror - instance, you can call this method with a function argument. It - will call the function, buffering up all changes, and only doing - the expensive update after the function returns. This can be a - lot faster. The return value from this method will be the return - value of your function.
    - -
    cm.indentLine(line: integer, ?dir: string|integer)
    -
    Adjust the indentation of the given line. The second - argument (which defaults to "smart") may be one of: -
    -
    "prev"
    -
    Base indentation on the indentation of the previous line.
    -
    "smart"
    -
    Use the mode's smart indentation if available, behave - like "prev" otherwise.
    -
    "add"
    -
    Increase the indentation of the line by - one indent unit.
    -
    "subtract"
    -
    Reduce the indentation of the line.
    -
    <integer>
    -
    Add (positive number) or reduce (negative number) the - indentation by the given amount of spaces.
    -
    - -
    cm.toggleOverwrite(?value: boolean)
    -
    Switches between overwrite and normal insert mode (when not - given an argument), or sets the overwrite mode to a specific - state (when given an argument).
    - -
    cm.isReadOnly() → boolean
    -
    Tells you whether the editor's content can be edited by the - user.
    - -
    doc.lineSeparator()
    -
    Returns the preferred line separator string for this - document, as per the option - by the same name. When that option is null, the - string "\n" is returned.
    - -
    cm.execCommand(name: string)
    -
    Runs the command with the given name on the editor.
    - -
    doc.posFromIndex(index: integer) → {line, ch}
    -
    Calculates and returns a {line, ch} object for a - zero-based index who's value is relative to the start of the - editor's text. If the index is out of range of the text then - the returned object is clipped to start or end of the text - respectively.
    -
    doc.indexFromPos(object: {line, ch}) → integer
    -
    The reverse of posFromIndex.
    - -
    cm.focus()
    -
    Give the editor focus.
    - -
    cm.getInputField() → Element
    -
    Returns the input field for the editor. Will be a textarea - or an editable div, depending on the value of - the inputStyle - option.
    -
    cm.getWrapperElement() → Element
    -
    Returns the DOM node that represents the editor, and - controls its size. Remove this from your tree to delete an - editor instance.
    -
    cm.getScrollerElement() → Element
    -
    Returns the DOM node that is responsible for the scrolling - of the editor.
    -
    cm.getGutterElement() → Element
    -
    Fetches the DOM node that contains the editor gutters.
    -
    - -

    Static properties

    -

    The CodeMirror object itself provides - several useful properties.

    - -
    -
    CodeMirror.version: string
    -
    It contains a string that indicates the version of the - library. This is a triple of - integers "major.minor.patch", - where patch is zero for releases, and something - else (usually one) for dev snapshots.
    - -
    CodeMirror.fromTextArea(textArea: TextAreaElement, ?config: object)
    -
    This method provides another way to initialize an editor. It - takes a textarea DOM node as first argument and an optional - configuration object as second. It will replace the textarea - with a CodeMirror instance, and wire up the form of that - textarea (if any) to make sure the editor contents are put into - the textarea when the form is submitted. The text in the - textarea will provide the content for the editor. A CodeMirror - instance created this way has three additional methods: -
    -
    cm.save()
    -
    Copy the content of the editor into the textarea.
    - -
    cm.toTextArea()
    -
    Remove the editor, and restore the original textarea (with - the editor's current content). If you dynamically create and - destroy editors made with `fromTextArea`, without destroying - the form they are part of, you should make sure to call - `toTextArea` to remove the editor, or its `"submit"` handler - on the form will cause a memory leak.
    - -
    cm.getTextArea() → TextAreaElement
    -
    Returns the textarea that the instance was based on.
    -
    -
    - -
    CodeMirror.defaults: object
    -
    An object containing default values for - all options. You can assign to its - properties to modify defaults (though this won't affect editors - that have already been created).
    - -
    CodeMirror.defineExtension(name: string, value: any)
    -
    If you want to define extra methods in terms of the - CodeMirror API, it is possible to - use defineExtension. This will cause the given - value (usually a method) to be added to all CodeMirror instances - created from then on.
    - -
    CodeMirror.defineDocExtension(name: string, value: any)
    -
    Like defineExtension, - but the method will be added to the interface - for Doc objects instead.
    - -
    CodeMirror.defineOption(name: string, - default: any, updateFunc: function)
    -
    Similarly, defineOption can be used to define new options for - CodeMirror. The updateFunc will be called with the - editor instance and the new value when an editor is initialized, - and whenever the option is modified - through setOption.
    - -
    CodeMirror.defineInitHook(func: function)
    -
    If your extension just needs to run some - code whenever a CodeMirror instance is initialized, - use CodeMirror.defineInitHook. Give it a function as - its only argument, and from then on, that function will be called - (with the instance as argument) whenever a new CodeMirror instance - is initialized.
    - -
    CodeMirror.registerHelper(type: string, name: string, value: helper)
    -
    Registers a helper value with the given name in - the given namespace (type). This is used to define - functionality that may be looked up by mode. Will create (if it - doesn't already exist) a property on the CodeMirror - object for the given type, pointing to an object - that maps names to values. I.e. after - doing CodeMirror.registerHelper("hint", "foo", - myFoo), the value CodeMirror.hint.foo will - point to myFoo.
    - -
    CodeMirror.registerGlobalHelper(type: string, name: string, predicate: fn(mode, CodeMirror), value: helper)
    -
    Acts - like registerHelper, - but also registers this helper as 'global', meaning that it will - be included by getHelpers - whenever the given predicate returns true when - called with the local mode and editor.
    - -
    CodeMirror.Pos(line: integer, ?ch: integer)
    -
    A constructor for the {line, ch} objects that - are used to represent positions in editor documents.
    - -
    CodeMirror.changeEnd(change: object) → {line, ch}
    -
    Utility function that computes an end position from a change - (an object with from, to, - and text properties, as passed to - various event handlers). The - returned position will be the end of the changed - range, after the change is applied.
    -
    -
    - -
    -

    Addons

    - -

    The addon directory in the distribution contains a - number of reusable components that implement extra editor - functionality (on top of extension functions - like defineOption, defineExtension, - and registerHelper). In - brief, they are:

    - -
    -
    dialog/dialog.js
    -
    Provides a very simple way to query users for text input. - Adds the openDialog(template, callback, options) → - closeFunction method to CodeMirror instances, - which can be called with an HTML fragment or a detached DOM - node that provides the prompt (should include an input - or button tag), and a callback function that is called - when the user presses enter. It returns a function closeFunction - which, if called, will close the dialog immediately. - openDialog takes the following options: -
    -
    closeOnEnter: bool
    -
    If true, the dialog will be closed when the user presses - enter in the input. Defaults to true.
    -
    closeOnBlur: bool
    -
    Determines whether the dialog is closed when it loses focus. Defaults to true.
    -
    onKeyDown: fn(event: KeyboardEvent, value: string, close: fn()) → bool
    -
    An event handler that will be called whenever keydown fires in the - dialog's input. If your callback returns true, - the dialog will not do any further processing of the event.
    -
    onKeyUp: fn(event: KeyboardEvent, value: string, close: fn()) → bool
    -
    Same as onKeyDown but for the - keyup event.
    -
    onInput: fn(event: InputEvent, value: string, close: fn()) → bool
    -
    Same as onKeyDown but for the - input event.
    -
    onClose: fn(instance):
    -
    A callback that will be called after the dialog has been closed and - removed from the DOM. No return value.
    -
    - -

    Also adds an openNotification(template, options) → - closeFunction function that simply shows an HTML - fragment as a notification at the top of the editor. It takes a - single option: duration, the amount of time after - which the notification will be automatically closed. If - duration is zero, the dialog will not be closed automatically.

    - -

    Depends on addon/dialog/dialog.css.

    - -
    search/searchcursor.js
    -
    Adds the getSearchCursor(query, start, caseFold) → - cursor method to CodeMirror instances, which can be used - to implement search/replace functionality. query - can be a regular expression or a string (only strings will match - across lines—if they contain newlines). start - provides the starting position of the search. It can be - a {line, ch} object, or can be left off to default - to the start of the document. caseFold is only - relevant when matching a string. It will cause the search to be - case-insensitive. A search cursor has the following methods: -
    -
    findNext() → boolean
    -
    findPrevious() → boolean
    -
    Search forward or backward from the current position. - The return value indicates whether a match was found. If - matching a regular expression, the return value will be the - array returned by the match method, in case you - want to extract matched groups.
    -
    from() → {line, ch}
    -
    to() → {line, ch}
    -
    These are only valid when the last call - to findNext or findPrevious did - not return false. They will return {line, ch} - objects pointing at the start and end of the match.
    -
    replace(text: string, ?origin: string)
    -
    Replaces the currently found match with the given text - and adjusts the cursor position to reflect the - replacement.
    -
    - - -
    Implements the search commands. CodeMirror has keys bound to - these by default, but will not do anything with them unless an - implementation is provided. Depends - on searchcursor.js, and will make use - of openDialog when - available to make prompting for search queries less ugly.
    - -
    search/jump-to-line.js
    -
    Implements a jumpToLine command and binding Alt-G to it. - Accepts linenumber, +/-linenumber, line:char, - scroll% and :linenumber formats. - This will make use of openDialog - when available to make prompting for line number neater.
    - -
    search/matchesonscrollbar.js
    -
    Adds a showMatchesOnScrollbar method to editor - instances, which should be given a query (string or regular - expression), optionally a case-fold flag (only applicable for - strings), and optionally a class name (defaults - to CodeMirror-search-match) as arguments. When - called, matches of the given query will be displayed on the - editor's vertical scrollbar. The method returns an object with - a clear method that can be called to remove the - matches. Depends on - the annotatescrollbar - addon, and - the matchesonscrollbar.css - file provides a default (transparent yellowish) definition of - the CSS class applied to the matches. Note that the matches are - only perfectly aligned if your scrollbar does not have buttons - at the top and bottom. You can use - the simplescrollbar - addon to make sure of this. If this addon is loaded, - the search addon will - automatically use it.
    - -
    edit/matchbrackets.js
    -
    Defines an option matchBrackets which, when set - to true, causes matching brackets to be highlighted whenever the - cursor is next to them. It also adds a - method matchBrackets that forces this to happen - once, and a method findMatchingBracket that can be - used to run the bracket-finding algorithm that this uses - internally.
    - -
    edit/closebrackets.js
    -
    Defines an option autoCloseBrackets that will - auto-close brackets and quotes when typed. By default, it'll - auto-close ()[]{}''"", but you can pass it a string - similar to that (containing pairs of matching characters), or an - object with pairs and - optionally explode properties to customize - it. explode should be a similar string that gives - the pairs of characters that, when enter is pressed between - them, should have the second character also moved to its own - line. By default, if the active mode has - a closeBrackets property, that overrides the - configuration given in the option. But you can add - an override property with a truthy value to - override mode-specific - configuration. Demo - here.
    - -
    edit/matchtags.js
    -
    Defines an option matchTags that, when enabled, - will cause the tags around the cursor to be highlighted (using - the CodeMirror-matchingtag class). Also - defines - a command toMatchingTag, - which you can bind a key to in order to jump to the tag matching - the one under the cursor. Depends on - the addon/fold/xml-fold.js - addon. Demo here.
    - -
    edit/trailingspace.js
    -
    Adds an option showTrailingSpace which, when - enabled, adds the CSS class cm-trailingspace to - stretches of whitespace at the end of lines. - The demo has a nice - squiggly underline style for this class.
    - -
    edit/closetag.js
    -
    Defines an autoCloseTags option that will - auto-close XML tags when '>' or '/' - is typed, and - a closeTag command that - closes the nearest open tag. Depends on - the fold/xml-fold.js addon. See - the demo.
    - -
    edit/continuelist.js
    -
    Markdown specific. Defines - a "newlineAndIndentContinueMarkdownList" command - that can be bound to enter to automatically - insert the leading characters for continuing a list. See - the Markdown mode - demo.
    - -
    comment/comment.js
    -
    Addon for commenting and uncommenting code. Adds four - methods to CodeMirror instances: -
    -
    toggleComment(from: {line, ch}, to: {line, ch}, ?options: object)
    -
    Tries to uncomment the current selection, and if that - fails, line-comments it.
    -
    lineComment(from: {line, ch}, to: {line, ch}, ?options: object)
    -
    Set the lines in the given range to be line comments. Will - fall back to blockComment when no line comment - style is defined for the mode.
    -
    blockComment(from: {line, ch}, to: {line, ch}, ?options: object)
    -
    Wrap the code in the given range in a block comment. Will - fall back to lineComment when no block comment - style is defined for the mode.
    -
    uncomment(from: {line, ch}, to: {line, ch}, ?options: object) → boolean
    -
    Try to uncomment the given range. - Returns true if a comment range was found and - removed, false otherwise.
    -
    - The options object accepted by these methods may - have the following properties: -
    -
    blockCommentStart, blockCommentEnd, blockCommentLead, lineComment: string
    -
    Override the comment string - properties of the mode with custom comment strings.
    -
    padding: string
    -
    A string that will be inserted after opening and leading - markers, and before closing comment markers. Defaults to a - single space.
    -
    commentBlankLines: boolean
    -
    Whether, when adding line comments, to also comment lines - that contain only whitespace.
    -
    indent: boolean
    -
    When adding line comments and this is turned on, it will - align the comment block to the current indentation of the - first line of the block.
    -
    fullLines: boolean
    -
    When block commenting, this controls whether the whole - lines are indented, or only the precise range that is given. - Defaults to true.
    -
    - The addon also defines - a toggleComment command, - which is a shorthand command for calling - toggleComment with no options.
    - -
    fold/foldcode.js
    -
    Helps with code folding. Adds a foldCode method - to editor instances, which will try to do a code fold starting - at the given line, or unfold the fold that is already present. - The method takes as first argument the position that should be - folded (may be a line number or - a Pos), and as second optional - argument either a range-finder function, or an options object, - supporting the following properties: -
    -
    rangeFinder: fn(CodeMirror, Pos)
    -
    The function that is used to find - foldable ranges. If this is not directly passed, it will - default to CodeMirror.fold.auto, which - uses getHelpers with - a "fold" type to find folding functions - appropriate for the local mode. There are files in - the addon/fold/ - directory providing CodeMirror.fold.brace, which - finds blocks in brace languages (JavaScript, C, Java, - etc), CodeMirror.fold.indent, for languages where - indentation determines block structure (Python, Haskell), - and CodeMirror.fold.xml, for XML-style languages, - and CodeMirror.fold.comment, for folding comment - blocks.
    -
    widget: string|Element
    -
    The widget to show for folded ranges. Can be either a - string, in which case it'll become a span with - class CodeMirror-foldmarker, or a DOM node.
    -
    scanUp: boolean
    -
    When true (default is false), the addon will try to find - foldable ranges on the lines above the current one if there - isn't an eligible one on the given line.
    -
    minFoldSize: integer
    -
    The minimum amount of lines that a fold should span to be - accepted. Defaults to 0, which also allows single-line - folds.
    -
    - See the demo for an - example.
    - -
    fold/foldgutter.js
    -
    Provides an option foldGutter, which can be - used to create a gutter with markers indicating the blocks that - can be folded. Create a gutter using - the gutters option, - giving it the class CodeMirror-foldgutter or - something else if you configure the addon to use a different - class, and this addon will show markers next to folded and - foldable blocks, and handle clicks in this gutter. Note that - CSS styles should be applied to make the gutter, and the fold - markers within it, visible. A default set of CSS styles are - available in: - - addon/fold/foldgutter.css - . - The option - can be either set to true, or an object containing - the following optional option fields: -
    -
    gutter: string
    -
    The CSS class of the gutter. Defaults - to "CodeMirror-foldgutter". You will have to - style this yourself to give it a width (and possibly a - background). See the default gutter style rules above.
    -
    indicatorOpen: string | Element
    -
    A CSS class or DOM element to be used as the marker for - open, foldable blocks. Defaults - to "CodeMirror-foldgutter-open".
    -
    indicatorFolded: string | Element
    -
    A CSS class or DOM element to be used as the marker for - folded blocks. Defaults to "CodeMirror-foldgutter-folded".
    -
    rangeFinder: fn(CodeMirror, Pos)
    -
    The range-finder function to use when determining whether - something can be folded. When not - given, CodeMirror.fold.auto - will be used as default.
    -
    - The foldOptions editor option can be set to an - object to provide an editor-wide default configuration. - Demo here.
    - -
    runmode/runmode.js
    -
    Can be used to run a CodeMirror mode over text without - actually opening an editor instance. - See the demo for an example. - There are alternate versions of the file available for - running stand-alone - (without including all of CodeMirror) and - for running under - node.js (see bin/source-highlight for an example of using the latter).
    - -
    runmode/colorize.js
    -
    Provides a convenient way to syntax-highlight code snippets - in a webpage. Depends on - the runmode addon (or - its standalone variant). Provides - a CodeMirror.colorize function that can be called - with an array (or other array-ish collection) of DOM nodes that - represent the code snippets. By default, it'll get - all pre tags. Will read the data-lang - attribute of these nodes to figure out their language, and - syntax-color their content using the relevant CodeMirror mode - (you'll have to load the scripts for the relevant modes - yourself). A second argument may be provided to give a default - mode, used when no language attribute is found for a node. Used - in this manual to highlight example code.
    - -
    mode/overlay.js
    -
    Mode combinator that can be used to extend a mode with an - 'overlay' — a secondary mode is run over the stream, along with - the base mode, and can color specific pieces of text without - interfering with the base mode. - Defines CodeMirror.overlayMode, which is used to - create such a mode. See this - demo for a detailed example.
    - -
    mode/multiplex.js
    -
    Mode combinator that can be used to easily 'multiplex' - between several modes. - Defines CodeMirror.multiplexingMode which, when - given as first argument a mode object, and as other arguments - any number of {open, close, mode [, delimStyle, innerStyle, parseDelimiters]} - objects, will return a mode object that starts parsing using the - mode passed as first argument, but will switch to another mode - as soon as it encounters a string that occurs in one of - the open fields of the passed objects. When in a - sub-mode, it will go back to the top mode again when - the close string is encountered. - Pass "\n" for open or close - if you want to switch on a blank line. -
    • When delimStyle is specified, it will be the token - style returned for the delimiter tokens (as well as - [delimStyle]-open on the opening token and - [delimStyle]-close on the closing token).
    • -
    • When innerStyle is specified, it will be the token - style added for each inner mode token.
    • -
    • When parseDelimiters is true, the content of - the delimiters will also be passed to the inner mode. - (And delimStyle is ignored.)
    The outer - mode will not see the content between the delimiters. - See this demo for an - example.
    - -
    hint/show-hint.js
    -
    Provides a framework for showing autocompletion hints. - Defines editor.showHint, which takes an optional - options object, and pops up a widget that allows the user to - select a completion. Finding hints is done with a hinting - functions (the hint option), which is a function - that take an editor instance and options object, and return - a {list, from, to} object, where list - is an array of strings or objects (the completions), - and from and to give the start and end - of the token that is being completed as {line, ch} - objects. An optional selectedHint property (an - integer) can be added to the completion object to control the - initially selected hint.
    -
    If no hinting function is given, the addon will - use CodeMirror.hint.auto, which - calls getHelpers with - the "hint" type to find applicable hinting - functions, and tries them one by one. If that fails, it looks - for a "hintWords" helper to fetch a list of - completable words for the mode, and - uses CodeMirror.hint.fromList to complete from - those.
    -
    When completions aren't simple strings, they should be - objects with the following properties: -
    -
    text: string
    -
    The completion text. This is the only required - property.
    -
    displayText: string
    -
    The text that should be displayed in the menu.
    -
    className: string
    -
    A CSS class name to apply to the completion's line in the - menu.
    -
    render: fn(Element, self, data)
    -
    A method used to create the DOM structure for showing the - completion by appending it to its first argument.
    -
    hint: fn(CodeMirror, self, data)
    -
    A method used to actually apply the completion, instead of - the default behavior.
    -
    from: {line, ch}
    -
    Optional from position that will be used by pick() instead - of the global one passed with the full list of completions.
    -
    to: {line, ch}
    -
    Optional to position that will be used by pick() instead - of the global one passed with the full list of completions.
    -
    - -
    The plugin understands the following options (the options object - will also be passed along to the hinting function, which may - understand additional options): -
    -
    hint: function
    -
    A hinting function, as specified above. It is possible to - set the async property on a hinting function to - true, in which case it will be called with - arguments (cm, callback, ?options), and the - completion interface will only be popped up when the hinting - function calls the callback, passing it the object holding the - completions. - The hinting function can also return a promise, and the completion - interface will only be popped when the promise resolves. - By default, hinting only works when there is no - selection. You can give a hinting function - a supportsSelection property with a truthy value - to indicate that it supports selections.
    -
    completeSingle: boolean
    -
    Determines whether, when only a single completion is - available, it is completed without showing the dialog. - Defaults to true.
    -
    alignWithWord: boolean
    -
    Whether the pop-up should be horizontally aligned with the - start of the word (true, default), or with the cursor (false).
    -
    closeOnUnfocus: boolean
    -
    When enabled (which is the default), the pop-up will close - when the editor is unfocused.
    -
    customKeys: keymap
    -
    Allows you to provide a custom key map of keys to be active - when the pop-up is active. The handlers will be called with an - extra argument, a handle to the completion menu, which - has moveFocus(n), setFocus(n), pick(), - and close() methods (see the source for details), - that can be used to change the focused element, pick the - current element or close the menu. Additionally menuSize() - can give you access to the size of the current dropdown menu, - length give you the number of available completions, and - data give you full access to the completion returned by the - hinting function.
    -
    extraKeys: keymap
    -
    Like customKeys above, but the bindings will - be added to the set of default bindings, instead of replacing - them.
    -
    - The following events will be fired on the completions object - during completion: -
    -
    "shown" ()
    -
    Fired when the pop-up is shown.
    -
    "select" (completion, Element)
    -
    Fired when a completion is selected. Passed the completion - value (string or object) and the DOM node that represents it - in the menu.
    -
    "pick" (completion)
    -
    Fired when a completion is picked. Passed the completion value - (string or object).
    -
    "close" ()
    -
    Fired when the completion is finished.
    -
    - This addon depends on styles - from addon/hint/show-hint.css. Check - out the demo for an - example.
    - -
    hint/javascript-hint.js
    -
    Defines a simple hinting function for JavaScript - (CodeMirror.hint.javascript) and CoffeeScript - (CodeMirror.hint.coffeescript) code. This will - simply use the JavaScript environment that the editor runs in as - a source of information about objects and their properties.
    - -
    hint/xml-hint.js
    -
    Defines CodeMirror.hint.xml, which produces - hints for XML tagnames, attribute names, and attribute values, - guided by a schemaInfo option (a property of the - second argument passed to the hinting function, or the third - argument passed to CodeMirror.showHint).
    The - schema info should be an object mapping tag names to information - about these tags, with optionally a "!top" property - containing a list of the names of valid top-level tags. The - values of the properties should be objects with optional - properties children (an array of valid child - element names, omit to simply allow all tags to appear) - and attrs (an object mapping attribute names - to null for free-form attributes, and an array of - valid values for restricted - attributes). Demo - here.
    - -
    hint/html-hint.js
    -
    Provides schema info to - the xml-hint addon for HTML - documents. Defines a schema - object CodeMirror.htmlSchema that you can pass to - as a schemaInfo option, and - a CodeMirror.hint.html hinting function that - automatically calls CodeMirror.hint.xml with this - schema data. See - the demo.
    - -
    hint/css-hint.js
    -
    A hinting function for CSS, SCSS, or LESS code. - Defines CodeMirror.hint.css.
    - -
    hint/anyword-hint.js
    -
    A very simple hinting function - (CodeMirror.hint.anyword) that simply looks for - words in the nearby code and completes to those. Takes two - optional options, word, a regular expression that - matches words (sequences of one or more character), - and range, which defines how many lines the addon - should scan when completing (defaults to 500).
    - -
    hint/sql-hint.js
    -
    A simple SQL hinter. Defines CodeMirror.hint.sql. - Takes two optional options, tables, a object with - table names as keys and array of respective column names as values, - and defaultTable, a string corresponding to a - table name in tables for autocompletion.
    - -
    search/match-highlighter.js
    -
    Adds a highlightSelectionMatches option that - can be enabled to highlight all instances of a currently - selected word. Can be set either to true or to an object - containing the following options: minChars, for the - minimum amount of selected characters that triggers a highlight - (default 2), style, for the style to be used to - highlight the matches (default "matchhighlight", - which will correspond to CSS - class cm-matchhighlight), trim, which - controls whether whitespace is trimmed from the selection, - and showToken which can be set to true - or to a regexp matching the characters that make up a word. When - enabled, it causes the current word to be highlighted when - nothing is selected (defaults to off). - Demo here.
    - -
    lint/lint.js
    -
    Defines an interface component for showing linting warnings, - with pluggable warning sources - (see html-lint.js, - json-lint.js, - javascript-lint.js, - coffeescript-lint.js, - and css-lint.js - in the same directory). Defines a lint option that - can be set to an annotation source (for - example CodeMirror.lint.javascript), to an options - object (in which case the getAnnotations field is - used as annotation source), or simply to true. When - no annotation source is - specified, getHelper with - type "lint" is used to find an annotation function. - An annotation source function should, when given a document - string, an options object, and an editor instance, return an - array of {message, severity, from, to} objects - representing problems. When the function has - an async property with a truthy value, it will be - called with an additional second argument, which is a callback - to pass the array to. By default, the linter will run - (debounced) whenever the document is changed. You can pass - a lintOnChange: false option to disable that. - Depends on addon/lint/lint.css. A demo can be - found here.
    - -
    selection/mark-selection.js
    -
    Causes the selected text to be marked with the CSS class - CodeMirror-selectedtext when the styleSelectedText option - is enabled. Useful to change the colour of the selection (in addition to the background), - like in this demo.
    - -
    selection/active-line.js
    -
    Defines a styleActiveLine option that, when - enabled, gives the wrapper of the line that contains the cursor - the class CodeMirror-activeline, adds a background - with the class CodeMirror-activeline-background, - and adds the class CodeMirror-activeline-gutter to - the line's gutter space is enabled. The option's value may be a - boolean or an object specifying the following options: -
    -
    nonEmpty: bool
    -
    Controls whether single-line selections, or just cursor - selections, are styled. Defaults to false (only cursor - selections).
    -
    - See the demo.
    - -
    selection/selection-pointer.js
    -
    Defines a selectionPointer option which you can - use to control the mouse cursor appearance when hovering over - the selection. It can be set to a string, - like "pointer", or to true, in which case - the "default" (arrow) cursor will be used. You can - see a demo here.
    - -
    mode/loadmode.js
    -
    Defines a CodeMirror.requireMode(modename, - callback) function that will try to load a given mode and - call the callback when it succeeded. You'll have to - set CodeMirror.modeURL to a string that mode paths - can be constructed from, for - example "mode/%N/%N.js"—the %N's will - be replaced with the mode name. Also - defines CodeMirror.autoLoadMode(instance, mode), - which will ensure the given mode is loaded and cause the given - editor instance to refresh its mode when the loading - succeeded. See the demo.
    - -
    mode/meta.js
    -
    Provides meta-information about all the modes in the - distribution in a single file. - Defines CodeMirror.modeInfo, an array of objects - with {name, mime, mode} properties, - where name is the human-readable - name, mime the MIME type, and mode the - name of the mode file that defines this MIME. There are optional - properties mimes, which holds an array of MIME - types for modes with multiple MIMEs associated, - and ext, which holds an array of file extensions - associated with this mode. Four convenience - functions, CodeMirror.findModeByMIME, - CodeMirror.findModeByExtension, - CodeMirror.findModeByFileName - and CodeMirror.findModeByName are provided, which - return such an object given a MIME, extension, file name or mode name - string. Note that, for historical reasons, this file resides in the - top-level mode directory, not - under addon. Demo.
    - -
    comment/continuecomment.js
    -
    Adds a continueComments option, which sets whether the - editor will make the next line continue a comment when you press Enter - inside a comment block. Can be set to a boolean to enable/disable this - functionality. Set to a string, it will continue comments using a custom - shortcut. Set to an object, it will use the key property for - a custom shortcut and the boolean continueLineComment - property to determine whether single-line comments should be continued - (defaulting to true).
    - -
    display/placeholder.js
    -
    Adds a placeholder option that can be used to - make content appear in the editor when it is empty and not - focused. It can hold either a string or a DOM node. Also gives - the editor a CodeMirror-empty CSS class whenever it - doesn't contain any text. - See the demo.
    - -
    display/fullscreen.js
    -
    Defines an option fullScreen that, when set - to true, will make the editor full-screen (as in, - taking up the whole browser window). Depends - on fullscreen.css. Demo - here.
    - -
    display/autorefresh.js
    -
    This addon can be useful when initializing an editor in a - hidden DOM node, in cases where it is difficult to - call refresh when the editor - becomes visible. It defines an option autoRefresh - which you can set to true to ensure that, if the editor wasn't - visible on initialization, it will be refreshed the first time - it becomes visible. This is done by polling every 250 - milliseconds (you can pass a value like {delay: - 500} as the option value to configure this). Note that - this addon will only refresh the editor once when it - first becomes visible, and won't take care of further restyling - and resizing.
    - -
    scroll/simplescrollbars.js
    -
    Defines two additional scrollbar - models, "simple" and "overlay" - (see demo) that can - be selected with - the scrollbarStyle - option. Depends - on simplescrollbars.css, - which can be further overridden to style your own - scrollbars.
    - -
    scroll/annotatescrollbar.js
    -
    Provides functionality for showing markers on the scrollbar - to call out certain parts of the document. Adds a - method annotateScrollbar to editor instances that - can be called, with a CSS class name as argument, to create a - set of annotations. The method returns an object - whose update method can be called with an array - of {from: Pos, to: Pos} objects marking the ranges - to be highlighted. To detach the annotations, call the - object's clear method.
    - -
    display/rulers.js
    -
    Adds a rulers option, which can be used to show - one or more vertical rulers in the editor. The option, if - defined, should be given an array of {column [, className, - color, lineStyle, width]} objects or numbers (which - indicate a column). The ruler will be displayed at the column - indicated by the number or the column property. - The className property can be used to assign a - custom style to a ruler. Demo - here.
    - -
    display/panel.js
    -
    Defines an addPanel method for CodeMirror - instances, which places a DOM node above or below an editor, and - shrinks the editor to make room for the node. The method takes - as first argument as DOM node, and as second an optional options - object. The Panel object returned by this method - has a clear method that is used to remove the - panel, and a changed method that can be used to - notify the addon when the size of the panel's DOM node has - changed.
    - The method accepts the following options: -
    -
    position: string
    -
    Controls the position of the newly added panel. The - following values are recognized: -
    -
    top (default)
    -
    Adds the panel at the very top.
    -
    after-top
    -
    Adds the panel at the bottom of the top panels.
    -
    bottom
    -
    Adds the panel at the very bottom.
    -
    before-bottom
    -
    Adds the panel at the top of the bottom panels.
    -
    -
    -
    before: Panel
    -
    The new panel will be added before the given panel.
    -
    after: Panel
    -
    The new panel will be added after the given panel.
    -
    replace: Panel
    -
    The new panel will replace the given panel.
    -
    stable: bool
    -
    Whether to scroll the editor to keep the text's vertical - position stable, when adding a panel above it. Defaults to false.
    -
    - When using the after, before or replace options, - if the panel doesn't exists or has been removed, - the value of the position option will be used as a fallback. -
    - A demo of the addon is available here. -
    - -
    wrap/hardwrap.js
    -
    Addon to perform hard line wrapping/breaking for paragraphs - of text. Adds these methods to editor instances: -
    -
    wrapParagraph(?pos: {line, ch}, ?options: object)
    -
    Wraps the paragraph at the given position. - If pos is not given, it defaults to the cursor - position.
    -
    wrapRange(from: {line, ch}, to: {line, ch}, ?options: object)
    -
    Wraps the given range as one big paragraph.
    -
    wrapParagraphsInRange(from: {line, ch}, to: {line, ch}, ?options: object)
    -
    Wraps the paragraphs in (and overlapping with) the - given range individually.
    -
    - The following options are recognized: -
    -
    paragraphStart, paragraphEnd: RegExp
    -
    Blank lines are always considered paragraph boundaries. - These options can be used to specify a pattern that causes - lines to be considered the start or end of a paragraph.
    -
    column: number
    -
    The column to wrap at. Defaults to 80.
    -
    wrapOn: RegExp
    -
    A regular expression that matches only those - two-character strings that allow wrapping. By default, the - addon wraps on whitespace and after dash characters.
    -
    killTrailingSpace: boolean
    -
    Whether trailing space caused by wrapping should be - preserved, or deleted. Defaults to true.
    -
    - A demo of the addon is available here. -
    - -
    merge/merge.js
    -
    Implements an interface for merging changes, using either a - 2-way or a 3-way view. The CodeMirror.MergeView - constructor takes arguments similar to - the CodeMirror - constructor, first a node to append the interface to, and then - an options object. Options are passed through to the editors - inside the view. These extra options are recognized: -
    -
    origLeft and origRight: string
    -
    If given these provide original versions of the - document, which will be shown to the left and right of the - editor in non-editable CodeMirror instances. The merge - interface will highlight changes between the editable - document and the original(s). To create a 2-way (as opposed - to 3-way) merge view, provide only one of them.
    -
    revertButtons: boolean
    -
    Determines whether buttons that allow the user to revert - changes are shown. Defaults to true.
    -
    connect: string
    -
    Sets the style used to connect changed chunks of code. - By default, connectors are drawn. When this is set - to "align", the smaller chunk is padded to - align with the bigger chunk instead.
    -
    collapseIdentical: boolean|number
    -
    When true (default is false), stretches of unchanged - text will be collapsed. When a number is given, this - indicates the amount of lines to leave visible around such - stretches (which defaults to 2).
    -
    allowEditingOriginals: boolean
    -
    Determines whether the original editor allows editing. - Defaults to false.
    -
    showDifferences: boolean
    -
    When true (the default), changed pieces of text are - highlighted.
    -
    chunkClassLocation: string|Array
    -
    By default the chunk highlights are added - using addLineClass - with "background". Override this to customize it to be any - valid `where` parameter or an Array of valid `where` - parameters.
    -
    - The addon also defines commands "goNextDiff" - and "goPrevDiff" to quickly jump to the next - changed chunk. Demo - here.
    - -
    tern/tern.js
    -
    Provides integration with - the Tern JavaScript analysis - engine, for completion, definition finding, and minor - refactoring help. See the demo - for a very simple integration. For more involved scenarios, see - the comments at the top of - the addon and the - implementation of the - (multi-file) demonstration - on the Tern website.
    -
    -
    - -
    -

    Writing CodeMirror Modes

    - -

    Modes typically consist of a single JavaScript file. This file - defines, in the simplest case, a lexer (tokenizer) for your - language—a function that takes a character stream as input, - advances it past a token, and returns a style for that token. More - advanced modes can also handle indentation for the language.

    - -

    This section describes the low-level mode interface. Many modes - are written directly against this, since it offers a lot of - control, but for a quick mode definition, you might want to use - the simple mode addon.

    - -

    The mode script should - call CodeMirror.defineMode to - register itself with CodeMirror. This function takes two - arguments. The first should be the name of the mode, for which you - should use a lowercase string, preferably one that is also the - name of the files that define the mode (i.e. "xml" is - defined in xml.js). The second argument should be a - function that, given a CodeMirror configuration object (the thing - passed to the CodeMirror function) and an optional - mode configuration object (as in - the mode option), returns - a mode object.

    - -

    Typically, you should use this second argument - to defineMode as your module scope function (modes - should not leak anything into the global scope!), i.e. write your - whole mode inside this function.

    - -

    The main responsibility of a mode script is parsing - the content of the editor. Depending on the language and the - amount of functionality desired, this can be done in really easy - or extremely complicated ways. Some parsers can be stateless, - meaning that they look at one element (token) of the code - at a time, with no memory of what came before. Most, however, will - need to remember something. This is done by using a state - object, which is an object that is always passed when - reading a token, and which can be mutated by the tokenizer.

    - -

    Modes that use a state must define - a startState method on their mode - object. This is a function of no arguments that produces a state - object to be used at the start of a document.

    - -

    The most important part of a mode object is - its token(stream, state) method. All - modes must define this method. It should read one token from the - stream it is given as an argument, optionally update its state, - and return a style string, or null for tokens that do - not have to be styled. For your styles, you are encouraged to use - the 'standard' names defined in the themes (without - the cm- prefix). If that fails, it is also possible - to come up with your own and write your own CSS theme file.

    - -

    A typical token string would - be "variable" or "comment". Multiple - styles can be returned (separated by spaces), for - example "string error" for a thing that looks like a - string but is invalid somehow (say, missing its closing quote). - When a style is prefixed by "line-" - or "line-background-", the style will be applied to - the whole line, analogous to what - the addLineClass method - does—styling the "text" in the simple case, and - the "background" element - when "line-background-" is prefixed.

    - -

    The stream object that's passed - to token encapsulates a line of code (tokens may - never span lines) and our current position in that line. It has - the following API:

    - -
    -
    eol() → boolean
    -
    Returns true only if the stream is at the end of the - line.
    -
    sol() → boolean
    -
    Returns true only if the stream is at the start of the - line.
    - -
    peek() → string
    -
    Returns the next character in the stream without advancing - it. Will return a null at the end of the - line.
    -
    next() → string
    -
    Returns the next character in the stream and advances it. - Also returns null when no more characters are - available.
    - -
    eat(match: string|regexp|function(char: string) → boolean) → string
    -
    match can be a character, a regular expression, - or a function that takes a character and returns a boolean. If - the next character in the stream 'matches' the given argument, - it is consumed and returned. Otherwise, undefined - is returned.
    -
    eatWhile(match: string|regexp|function(char: string) → boolean) → boolean
    -
    Repeatedly calls eat with the given argument, - until it fails. Returns true if any characters were eaten.
    -
    eatSpace() → boolean
    -
    Shortcut for eatWhile when matching - white-space.
    -
    skipToEnd()
    -
    Moves the position to the end of the line.
    -
    skipTo(ch: string) → boolean
    -
    Skips to the next occurrence of the given character, if - found on the current line (doesn't advance the stream if the - character does not occur on the line). Returns true if the - character was found.
    -
    match(pattern: string, ?consume: boolean, ?caseFold: boolean) → boolean
    -
    match(pattern: regexp, ?consume: boolean) → array<string>
    -
    Act like a - multi-character eat—if consume is true - or not given—or a look-ahead that doesn't update the stream - position—if it is false. pattern can be either a - string or a regular expression starting with ^. - When it is a string, caseFold can be set to true to - make the match case-insensitive. When successfully matching a - regular expression, the returned value will be the array - returned by match, in case you need to extract - matched groups.
    - -
    backUp(n: integer)
    -
    Backs up the stream n characters. Backing it up - further than the start of the current token will cause things to - break, so be careful.
    -
    column() → integer
    -
    Returns the column (taking into account tabs) at which the - current token starts.
    -
    indentation() → integer
    -
    Tells you how far the current line has been indented, in - spaces. Corrects for tab characters.
    - -
    current() → string
    -
    Get the string between the start of the current token and - the current stream position.
    -
    - -

    By default, blank lines are simply skipped when - tokenizing a document. For languages that have significant blank - lines, you can define - a blankLine(state) method on your - mode that will get called whenever a blank line is passed over, so - that it can update the parser state.

    - -

    Because state object are mutated, and CodeMirror - needs to keep valid versions of a state around so that it can - restart a parse at any line, copies must be made of state objects. - The default algorithm used is that a new state object is created, - which gets all the properties of the old object. Any properties - which hold arrays get a copy of these arrays (since arrays tend to - be used as mutable stacks). When this is not correct, for example - because a mode mutates non-array properties of its state object, a - mode object should define - a copyState method, which is given a - state and should return a safe copy of that state.

    - -

    If you want your mode to provide smart indentation - (through the indentLine - method and the indentAuto - and newlineAndIndent commands, to which keys can be - bound), you must define - an indent(state, textAfter) method - on your mode object.

    - -

    The indentation method should inspect the given state object, - and optionally the textAfter string, which contains - the text on the line that is being indented, and return an - integer, the amount of spaces to indent. It should usually take - the indentUnit - option into account. An indentation method may - return CodeMirror.Pass to indicate that it - could not come up with a precise indentation.

    - -

    To work well with - the commenting addon, a mode may - define lineComment (string that - starts a line - comment), blockCommentStart, blockCommentEnd - (strings that start and end block comments), - and blockCommentLead (a string to put at the start of - continued lines in a block comment). All of these are - optional.

    - -

    Finally, a mode may define either - an electricChars or an electricInput - property, which are used to automatically reindent the line when - certain patterns are typed and - the electricChars - option is enabled. electricChars may be a string, and - will trigger a reindent whenever one of the characters in that - string are typed. Often, it is more appropriate to - use electricInput, which should hold a regular - expression, and will trigger indentation when the part of the - line before the cursor matches the expression. It should - usually end with a $ character, so that it only - matches when the indentation-changing pattern was just typed, not when something was - typed after the pattern.

    - -

    So, to summarize, a mode must provide - a token method, and it may - provide startState, copyState, - and indent methods. For an example of a trivial mode, - see the diff mode, for a more - involved example, see the C-like - mode.

    - -

    Sometimes, it is useful for modes to nest—to have one - mode delegate work to another mode. An example of this kind of - mode is the mixed-mode HTML - mode. To implement such nesting, it is usually necessary to - create mode objects and copy states yourself. To create a mode - object, there are CodeMirror.getMode(options, - parserConfig), where the first argument is a configuration - object as passed to the mode constructor function, and the second - argument is a mode specification as in - the mode option. To copy a - state object, call CodeMirror.copyState(mode, state), - where mode is the mode that created the given - state.

    - -

    In a nested mode, it is recommended to add an - extra method, innerMode which, given - a state object, returns a {state, mode} object with - the inner mode and its state for the current position. These are - used by utility scripts such as the tag - closer to get context information. Use - the CodeMirror.innerMode helper function to, starting - from a mode and a state, recursively walk down to the innermost - mode and state.

    - -

    To make indentation work properly in a nested parser, it is - advisable to give the startState method of modes that - are intended to be nested an optional argument that provides the - base indentation for the block of code. The JavaScript and CSS - parser do this, for example, to allow JavaScript and CSS code - inside the mixed-mode HTML mode to be properly indented.

    - -

    It is possible, and encouraged, to associate - your mode, or a certain configuration of your mode, with - a MIME type. For - example, the JavaScript mode associates itself - with text/javascript, and its JSON variant - with application/json. To do this, - call CodeMirror.defineMIME(mime, - modeSpec), where modeSpec can be a string or - object specifying a mode, as in - the mode option.

    - -

    If a mode specification wants to add some properties to the - resulting mode object, typically for use - with getHelpers, it may - contain a modeProps property, which holds an object. - This object's properties will be copied to the actual mode - object.

    - -

    Sometimes, it is useful to add or override mode - object properties from external code. - The CodeMirror.extendMode function - can be used to add properties to mode objects produced for a - specific mode. Its first argument is the name of the mode, its - second an object that specifies the properties that should be - added. This is mostly useful to add utilities that can later be - looked up through getMode.

    -
    - -
    -

    VIM Mode API

    - -

    CodeMirror has a robust VIM mode that attempts to faithfully - emulate VIM's most useful features. It can be enabled by - including keymap/vim.js - and setting the keyMap option to - "vim".

    - -

    Configuration

    - -

    VIM mode accepts configuration options for customizing - behavior at run time. These methods can be called at any time - and will affect all existing CodeMirror instances unless - specified otherwise. The methods are exposed on the - CodeMirror.Vim object.

    - -
    -
    setOption(name: string, value: any, ?cm: CodeMirror, ?cfg: object)
    -
    Sets the value of a VIM option. name should - be the name of an option. If cfg.scope is not set - and cm is provided, then sets the global and - instance values of the option. Otherwise, sets either the - global or instance value of the option depending on whether - cfg.scope is global or - local.
    -
    getOption(name: string, ?cm: CodeMirror: ?cfg: object)
    -
    Gets the current value of a VIM option. If - cfg.scope is not set and cm is - provided, then gets the instance value of the option, falling - back to the global value if not set. If cfg.scope is provided, then gets the global or - local value without checking the other.
    - -
    map(lhs: string, rhs: string, ?context: string)
    -
    Maps a key sequence to another key sequence. Implements - VIM's :map command. To map ; to : in VIM would be - :map ; :. That would translate to - CodeMirror.Vim.map(';', ':');. - The context can be normal, - visual, or insert, which correspond - to :nmap, :vmap, and - :imap - respectively.
    - -
    mapCommand(keys: string, type: string, name: string, ?args: object, ?extra: object)
    -
    Maps a key sequence to a motion, - operator, or action type command. - The args object is passed through to the command when it is - invoked by the provided key sequence. - extras.context can be normal, - visual, or insert, to map the key - sequence only in the corresponding mode. - extras.isEdit is applicable only to actions, - determining whether it is recorded for replay for the - . single-repeat command. -
    - -

    Extending VIM

    - -

    CodeMirror's VIM mode implements a large subset of VIM's core - editing functionality. But since there's always more to be - desired, there is a set of APIs for extending VIM's - functionality. As with the configuration API, the methods are - exposed on CodeMirror.Vim and may - be called at any time.

    - -
    -
    defineOption(name: string, default: any, type: string, ?aliases: array<string>, ?callback: function (?value: any, ?cm: CodeMirror) → ?any)
    -
    Defines a VIM style option and makes it available to the - :set command. Type can be boolean or - string, used for validation and by - :set to determine which syntax to accept. If a - callback is passed in, VIM does not store the value of the - option itself, but instead uses the callback as a setter/getter. If the - first argument to the callback is undefined, then the - callback should return the value of the option. Otherwise, it should set - instead. Since VIM options have global and instance values, whether a - CodeMirror instance is passed in denotes whether the global - or local value should be used. Consequently, it's possible for the - callback to be called twice for a single setOption or - getOption call. Note that right now, VIM does not support - defining buffer-local options that do not have global values. If an - option should not have a global value, either always ignore the - cm parameter in the callback, or always pass in a - cfg.scope to setOption and - getOption.
    - -
    defineMotion(name: string, fn: function(cm: CodeMirror, head: {line, ch}, ?motionArgs: object}) → {line, ch})
    -
    Defines a motion command for VIM. The motion should return - the desired result position of the cursor. head - is the current position of the cursor. It can differ from - cm.getCursor('head') if VIM is in visual mode. - motionArgs is the object passed into - mapCommand().
    - -
    defineOperator(name: string, fn: function(cm: CodeMirror, ?operatorArgs: object, ranges: array<{anchor, head}>) → ?{line, ch})
    -
    Defines an operator command, similar to - defineMotion. ranges is the range - of text the operator should operate on. If the cursor should - be set to a certain position after the operation finishes, it - can return a cursor object.
    - -
    defineAction(name: string, fn: function(cm: CodeMirror, ?actionArgs: object))
    -
    Defines an action command, similar to - defineMotion. Action commands - can have arbitrary behavior, making them more flexible than - motions and operators, at the loss of orthogonality.
    - -
    defineEx(name: string, ?prefix: string, fn: function(cm: CodeMirror, ?params: object))
    -
    Defines an Ex command, and maps it to :name. - If a prefix is provided, it, and any prefixed substring of the - name beginning with the prefix can - be used to invoke the command. If the prefix is - falsy, then name is used as the prefix. - params.argString contains the part of the prompted - string after the command name. params.args is - params.argString split by whitespace. If the - command was prefixed with a - line range, - params.line and params.lineEnd will - be set. -
    - -
    - -
    - - diff --git a/backend/_pv_1_3_5/static/codemirror/doc/realworld.html b/backend/_pv_1_3_5/static/codemirror/doc/realworld.html deleted file mode 100755 index 2429ba165..000000000 --- a/backend/_pv_1_3_5/static/codemirror/doc/realworld.html +++ /dev/null @@ -1,187 +0,0 @@ - - -CodeMirror: Real-world Uses - - - - - -
    - -

    CodeMirror real-world uses

    - -

    Create a pull - request if you'd like your project to be added to this list.

    - - - -
    - diff --git a/backend/_pv_1_3_5/static/codemirror/doc/releases.html b/backend/_pv_1_3_5/static/codemirror/doc/releases.html deleted file mode 100755 index 69c0e66b1..000000000 --- a/backend/_pv_1_3_5/static/codemirror/doc/releases.html +++ /dev/null @@ -1,1386 +0,0 @@ - - -CodeMirror: Release History - - - - - - -
    - -

    Release notes and version history

    - -
    - -

    Version 5.x

    - -

    19-01-2017: Version 5.23.0:

    - -
      -
    • Presentation-related elements DOM elements are now marked as such to help screen readers.
    • -
    • markdown mode: Be more picky about what HTML tags look like to avoid false positives.
    • -
    • findModeByMIME now understands +json and +xml MIME suffixes.
    • -
    • closebrackets addon: Add support for an override option to ignore language-specific defaults.
    • -
    • panel addon: Add a stable option that auto-scrolls the content to keep it in the same place when inserting/removing a panel.
    • -
    - -

    20-12-2016: Version 5.22.0:

    - -
      -
    • sublime bindings: Make selectBetweenBrackets work with multiple cursors.
    • -
    • javascript mode: Fix issues with parsing complex TypeScript types, imports, and exports.
    • -
    • A contentEditable editor instance with autofocus enabled no longer crashes during initializing.
    • -
    • emacs bindings: Export CodeMirror.emacs to allow other addons to hook into Emacs-style functionality.
    • -
    • active-line addon: Add nonEmpty option.
    • -
    • New event: optionChange.
    • -
    - -

    21-11-2016: Version 5.21.0:

    - -
      -
    • Tapping/clicking the editor in contentEditable mode on Chrome now puts the cursor at the tapped position.
    • -
    • Fix various crashes and misbehaviors when reading composition events in contentEditable mode.
    • -
    • Catches and ignores an IE 'Unspecified Error' when creating an editor in an iframe before there is a <body>.
    • -
    • merge addon: Fix several issues in the chunk-aligning feature.
    • -
    • verilog mode: Rewritten to address various issues.
    • -
    • julia mode: Recognize Julia 0.5 syntax.
    • -
    • swift mode: Various fixes and adjustments to current syntax.
    • -
    • markdown mode: Allow lists without a blank line above them.
    • -
    • The setGutterMarker, clearGutter, and lineInfo methods are now available on Doc objects.
    • -
    • The heightAtLine method now takes an extra argument to allow finding the height at the top of the line's line widgets.
    • -
    • ruby mode: else and elsif are now immediately indented.
    • -
    • vim bindings: Bind Ctrl-T and Ctrl-D to in- and dedent in insert mode.
    • -
    - -

    20-10-2016: Version 5.20.0:

    - -
      -
    • Make newlineAndIndent command work with multiple cursors on the same line.
    • -
    • Make sure keypress events for backspace are ignored.
    • -
    • Tokens styled with overlays no longer get a nonsense cm-cm-overlay class.
    • -
    • Line endings for pasted content are now normalized to the editor's preferred ending.
    • -
    • javascript mode: Improve support for class expressions. Support TypeScript optional class properties, the abstract keyword, and return type declarations for arrow functions.
    • -
    • css mode: Fix highlighting of mixed-case keywords.
    • -
    • closebrackets addon: Improve behavior when typing a quote before a string.
    • -
    • The core is now maintained as a number of small files, using ES6 syntax and modules, under the src/ directory. A git checkout no longer contains a working codemirror.js until you npm build (but when installing from NPM, it is included).
    • -
    • The refresh event is now documented and stable.
    • -
    - -

    20-09-2016: Version 5.19.0:

    - -
      -
    • erlang mode: Fix mode crash when trying to read an empty context.
    • -
    • comment addon: Fix broken behavior when toggling comments inside a comment.
    • -
    • xml-fold addon: Fix a null-dereference bug.
    • -
    • Page up and page down now do something even in single-line documents.
    • -
    • Fix an issue where the cursor position could be off in really long (~8000 character) tokens.
    • -
    • javascript mode: Better indentation when semicolons are missing. Better support for TypeScript classes, optional parameters, and the type keyword.
    • -
    • The blur and focus events now pass the DOM event to their handlers.
    • -
    - -

    23-08-2016: Version 5.18.2:

    - -
      -
    • vue mode: Fix outdated references to renamed Pug mode dependency.
    • -
    - -

    22-08-2016: Version 5.18.0:

    - -
      -
    • Make sure gutter backgrounds stick to the rest of the gutter during horizontal scrolling.
    • -
    • The contenteditable inputStyle now properly supports pasting on pre-Edge IE versions.
    • -
    • javascript mode: Fix some small parsing bugs and improve TypeScript support.
    • -
    • matchbrackets addon: Fix bug where active highlighting was left in editor when the addon was disabled.
    • -
    • match-highlighter addon: Only start highlighting things when the editor gains focus.
    • -
    • javascript-hint addon: Also complete non-enumerable properties.
    • -
    • The addOverlay method now supports a priority option to control the order in which overlays are applied.
    • -
    • MIME types that end in +json now default to the JSON mode when the MIME itself is not defined.
    • -
    • The mode formerly known as Jade was renamed to Pug.
    • -
    • The Python mode now defaults to Python 3 (rather than 2) syntax.
    • -
    - -

    19-07-2016: Version 5.17.0:

    - -
      -
    • Fix problem with wrapped trailing whitespace displaying incorrectly.
    • -
    • Prevent IME dialog from overlapping typed content in Chrome.
    • -
    • Improve measuring of characters near a line wrap.
    • -
    • javascript mode: Improve support for async, allow trailing commas in import lists.
    • -
    • vim bindings: Fix backspace in replace mode.
    • -
    • sublime bindings: Fix some key bindings on OS X to match Sublime Text.
    • -
    • markdown mode: Add more classes to image links in highlight-formatting mode.
    • -
    - -

    20-06-2016: Version 5.16.0:

    - -
      -
    • Fix glitches when dragging content caused by the drop indicator receiving mouse events.
    • -
    • Make Control-drag work on Firefox.
    • -
    • Make clicking or selection-dragging at the end of a wrapped line select the right position.
    • -
    • show-hint addon: Prevent widget scrollbar from hiding part of the hint text.
    • -
    • rulers addon: Prevent rulers from forcing a horizontal editor scrollbar.
    • -
    • search addon: Automatically bind search-related keys in persistent dialog.
    • -
    • sublime keymap: Add a multi-cursor aware smart backspace binding.
    • -
    - -

    20-05-2016: Version 5.15.2:

    - -
      -
    • Fix a critical document corruption bug that occurs when a document is gradually grown.
    • -
    - -

    20-05-2016: Version 5.15.0:

    - -
      -
    • Fix bug that caused the selection to reset when focusing the editor in contentEditable input mode.
    • -
    • Fix issue where not all ASCII control characters were being replaced by placeholders.
    • -
    • Remove the assumption that all modes have a startState method from several wrapping modes.
    • -
    • Fix issue where the editor would complain about overlapping collapsed ranges when there weren't any.
    • -
    • Optimize document tree building when loading or pasting huge chunks of content.
    • -
    • Explicitly bind Ctrl-O on OS X to make that binding (“open line”) act as expected.
    • -
    • Pasting linewise-copied content when there is no selection now inserts the lines above the current line.
    • -
    • markdown mode: Fix several issues in matching link targets.
    • -
    • clike mode: Improve indentation of C++ template declarations.
    • -
    • javascript mode: Support async/await and improve support for TypeScript type syntax.
    • -
    - -

    20-04-2016: Version 5.14.0:

    - - - -

    21-03-2016: Version 5.13.2:

    - -
      -
    • Solves a problem where the gutter would sometimes not extend all the way to the end of the document.
    • -
    - -

    21-03-2016: Version 5.13:

    - - - -

    19-02-2016: Version 5.12:

    - -
      -
    • Vim bindings: Ctrl-Q is now an alias for Ctrl-V.
    • -
    • Vim bindings: The Vim API now exposes an unmap method to unmap bindings.
    • -
    • active-line addon: This addon can now style the active line's gutter.
    • -
    • FCL mode: Newly added.
    • -
    • SQL mode: Now has a Postgresql dialect.
    • -
    • Fix issue where trying to scroll to a horizontal position outside of the document's width could cause the gutter to be positioned incorrectly.
    • -
    • Use absolute, rather than fixed positioning in the context-menu intercept hack, to work around a problem when the editor is inside a transformed parent container.
    • -
    • Solve a problem where the horizontal scrollbar could hide text in Firefox.
    • -
    • Fix a bug that caused phantom scroll space under the text in some situations.
    • -
    • Sublime Text bindings: Bind delete-line to Shift-Ctrl-K on OS X.
    • -
    • Markdown mode: Fix issue where the mode would keep state related to fenced code blocks in an unsafe way, leading to occasional corrupted parses.
    • -
    • Markdown mode: Ignore backslashes in code fragments.
    • -
    • Markdown mode: Use whichever mode is registered as text/html to parse HTML.
    • -
    • Clike mode: Improve indentation of Scala => functions.
    • -
    • Python mode: Improve indentation of bracketed code.
    • -
    • HTMLMixed mode: Support multi-line opening tags for sub-languages (<script>, <style>, etc).
    • -
    • Spreadsheet mode: Fix bug where the mode did not advance the stream when finding a backslash.
    • -
    • XML mode: The mode now takes a matchClosing option to configure whether mismatched closing tags should be highlighted as errors.
    • -
    - -

    20-01-2016: Version 5.11:

    - -
      -
    • New modes: JSX, literate Haskell
    • -
    • The editor now forwards more DOM events: cut, copy, paste, and touchstart. It will also forward mousedown for drag events
    • -
    • Fixes a bug where bookmarks next to collapsed spans were not rendered
    • -
    • The Swift mode now supports auto-indentation
    • -
    • Frontmatters in the YAML frontmatter mode are now optional as intended
    • -
    • Full list of patches
    • -
    - -

    21-12-2015: Version 5.10:

    - - - -

    23-11-2015: Version 5.9:

    - -
      -
    • Improve the way overlay (OS X-style) scrollbars are handled
    • -
    • Make annotatescrollbar and scrollpastend addons work properly together
    • -
    • Make show-hint addon select options on single click by default, move selection to hovered item
    • -
    • Properly fold comments that include block-comment-start markers
    • -
    • Many small language mode fixes
    • -
    • Full list of patches
    • -
    - -

    20-10-2015: Version 5.8:

    - - - -

    20-09-2015: Version 5.7:

    - - - -

    20-08-2015: Version 5.6:

    - -
      -
    • Fix bug where you could paste into a readOnly editor
    • -
    • Show a cursor at the drop location when dragging over the editor
    • -
    • The Rust mode was rewritten to handle modern Rust
    • -
    • The editor and theme CSS was cleaned up. Some selectors are now less specific than before
    • -
    • New theme: abcdef
    • -
    • Lines longer than maxHighlightLength are now less likely to mess up indentation
    • -
    • New addons: autorefresh for refreshing an editor the first time it becomes visible, and html-lint for using HTMLHint
    • -
    • The search addon now recognizes \r and \n in pattern and replacement input
    • -
    • Full list of patches
    • -
    - -

    20-07-2015: Version 5.5:

    - - - -

    25-06-2015: Version 5.4:

    - - - -

    20-05-2015: Version 5.3:

    - - - -

    20-04-2015: Version 5.2:

    - - - -

    23-03-2015: Version 5.1:

    - - - -

    20-02-2015: Version 5.0:

    - -
      -
    • Experimental mobile support (tested on iOS, Android Chrome, stock Android browser)
    • -
    • New option inputStyle to switch between hidden textarea and contenteditable input.
    • -
    • The getInputField - method is no longer guaranteed to return a textarea.
    • -
    • Full list of patches.
    • -
    - -
    - -
    - -

    Version 4.x

    - -

    20-02-2015: Version 4.13:

    - - - -

    22-01-2015: Version 4.12:

    - - - -

    9-01-2015: Version 4.11:

    - -

    Unfortunately, 4.10 did not take care of the - Firefox scrolling issue entirely. This release adds two more patches - to address that.

    - -

    29-12-2014: Version 4.10:

    - -

    Emergency single-patch update to 4.9. Fixes - Firefox-specific problem where the cursor could end up behind the - horizontal scrollbar.

    - -

    23-12-2014: Version 4.9:

    - - - -

    22-11-2014: Version 4.8:

    - - - -

    20-10-2014: Version 4.7:

    - -
      -
    • Incompatible: - The lint addon now passes the - editor's value as first argument to asynchronous lint functions, - for consistency. The editor is still passed, as fourth - argument.
    • -
    • Improved handling of unicode identifiers in modes for - languages that support them.
    • -
    • More mode - improvements: CoffeeScript - (indentation), Verilog - (indentation), Scala - (indentation, triple-quoted strings), - and PHP (interpolated - variables in heredoc strings).
    • -
    • New modes: Textile and Tornado templates.
    • -
    • Experimental new way to define modes.
    • -
    • Improvements to the Vim - bindings: Arbitrary insert mode key mappings are now possible, - and text objects are supported in visual mode.
    • -
    • The mode meta-information file - now includes information about file extensions, - and helper - functions findModeByMIME - and findModeByExtension.
    • -
    • New logo!
    • -
    • Full list of patches.
    • -
    - -

    19-09-2014: Version 4.6:

    - - - -

    21-08-2014: Version 4.5:

    - -
      -
    • Fix several serious bugs with horizontal scrolling
    • -
    • New mode: Slim
    • -
    • New command: goLineLeftSmart
    • -
    • More fixes and extensions for the Vim visual block mode
    • -
    • Full list of patches.
    • -
    - -

    21-07-2014: Version 4.4:

    - -
      -
    • Note: Some events might now fire in slightly - different order ("change" is still guaranteed to fire - before "cursorActivity")
    • -
    • Nested operations in multiple editors are now synced (complete - at same time, reducing DOM reflows)
    • -
    • Visual block mode for vim (<C-v>) is nearly complete
    • -
    • New mode: Kotlin
    • -
    • Better multi-selection paste for text copied from multiple CodeMirror selections
    • -
    • Full list of patches.
    • -
    - -

    23-06-2014: Version 4.3:

    - -
      -
    • Several vim bindings - improvements: search and exCommand history, global flag - for :substitute, :global command. -
    • Allow hiding the cursor by - setting cursorBlinkRate - to a negative value.
    • -
    • Make gutter markers themeable, use this in foldgutter.
    • -
    • Full list of patches.
    • -
    - -

    19-05-2014: Version 4.2:

    - -
      -
    • Fix problem where some modes were broken by the fact that empty tokens were forbidden.
    • -
    • Several fixes to context menu handling.
    • -
    • On undo, scroll change, not cursor, into view.
    • -
    • Rewritten Jade mode.
    • -
    • Various improvements to Shell (support for more syntax) and Python (better indentation) modes.
    • -
    • New mode: Cypher.
    • -
    • New theme: Neo.
    • -
    • Support direct styling options (color, line style, width) in the rulers addon.
    • -
    • Recognize per-editor configuration for the show-hint and foldcode addons.
    • -
    • More intelligent scanning for existing close tags in closetag addon.
    • -
    • In the Vim bindings: Fix bracket matching, support case conversion in visual mode, visual paste, append action.
    • -
    • Full list of patches.
    • -
    - -

    22-04-2014: Version 4.1:

    - -
      -
    • Slightly incompatible: - The "cursorActivity" - event now fires after all other events for the operation (and only - for handlers that were actually registered at the time the - activity happened).
    • -
    • New command: insertSoftTab.
    • -
    • New mode: Django.
    • -
    • Improved modes: Verilog (rewritten), Jinja2, Haxe, PHP (string interpolation highlighted), JavaScript (indentation of trailing else, template strings), LiveScript (multi-line strings).
    • -
    • Many small issues from the 3.x→4.x transition were found and fixed.
    • -
    • Full list of patches.
    • -
    - -

    20-03-2014: Version 4.0:

    - -

    This is a new major version of CodeMirror. There - are a few incompatible changes in the API. Upgrade - with care, and read the upgrading - guide.

    - - - -
    - -
    - -

    Version 3.x

    - -

    22-04-2014: Version 3.24:

    - -

    Merges the improvements from 4.1 that could - easily be applied to the 3.x code. Also improves the way the editor - size is updated when line widgets change.

    - -

    20-03-2014: Version 3.23:

    - -
      -
    • In the XML mode, - add brackets style to angle brackets, fix - case-sensitivity of tags for HTML.
    • -
    • New mode: Dylan.
    • -
    • Many improvements to the Vim bindings.
    • -
    - -

    21-02-2014: Version 3.22:

    - - - -

    16-01-2014: Version 3.21:

    - -
      -
    • Auto-indenting a block will no longer add trailing whitespace to blank lines.
    • -
    • Marking text has a new option clearWhenEmpty to control auto-removal.
    • -
    • Several bugfixes in the handling of bidirectional text.
    • -
    • The XML and CSS modes were largely rewritten. LESS support was added to the CSS mode.
    • -
    • The OCaml mode was moved to an mllike mode, F# support added.
    • -
    • Make it possible to fetch multiple applicable helper values with getHelpers, and to register helpers matched on predicates with registerGlobalHelper.
    • -
    • New theme pastel-on-dark.
    • -
    • Better ECMAScript 6 support in JavaScript mode.
    • -
    • Full list of patches.
    • -
    - -

    21-11-2013: Version 3.20:

    - - - -

    21-10-2013: Version 3.19:

    - - - -

    23-09-2013: Version 3.18:

    - -

    Emergency release to fix a problem in 3.17 - where .setOption("lineNumbers", false) would raise an - error.

    - -

    23-09-2013: Version 3.17:

    - - - -

    21-08-2013: Version 3.16:

    - - - -

    29-07-2013: Version 3.15:

    - - - -

    20-06-2013: Version 3.14:

    - - - -

    20-05-2013: Version 3.13:

    - - - -

    19-04-2013: Version 3.12:

    - - - -

    20-03-2013: Version 3.11:

    - - - -

    21-02-2013: Version 3.1:

    - - - - -

    25-01-2013: Version 3.02:

    - -

    Single-bugfix release. Fixes a problem that - prevents CodeMirror instances from being garbage-collected after - they become unused.

    - -

    21-01-2013: Version 3.01:

    - - - -

    10-12-2012: Version 3.0:

    - -

    New major version. Only - partially backwards-compatible. See - the upgrading guide for more - information. Changes since release candidate 2:

    - -
      -
    • Rewritten VIM mode.
    • -
    • Fix a few minor scrolling and sizing issues.
    • -
    • Work around Safari segfault when dragging.
    • -
    • Full list of patches.
    • -
    - -

    20-11-2012: Version 3.0, release candidate 2:

    - -
      -
    • New mode: HTTP.
    • -
    • Improved handling of selection anchor position.
    • -
    • Improve IE performance on longer lines.
    • -
    • Reduce gutter glitches during horiz. scrolling.
    • -
    • Add addKeyMap and removeKeyMap methods.
    • -
    • Rewrite formatting and closetag add-ons.
    • -
    • Full list of patches.
    • -
    - -

    20-11-2012: Version 3.0, release candidate 1:

    - - - -

    22-10-2012: Version 3.0, beta 2:

    - -
      -
    • Fix page-based coordinate computation.
    • -
    • Fix firing of gutterClick event.
    • -
    • Add cursorHeight option.
    • -
    • Fix bi-directional text regression.
    • -
    • Add viewportMargin option.
    • -
    • Directly handle mousewheel events (again, hopefully better).
    • -
    • Make vertical cursor movement more robust (through widgets, big line gaps).
    • -
    • Add flattenSpans option.
    • -
    • Many optimizations. Poor responsiveness should be fixed.
    • -
    • Initialization in hidden state works again.
    • -
    • Full list of patches.
    • -
    - -

    19-09-2012: Version 3.0, beta 1:

    - -
      -
    • Bi-directional text support.
    • -
    • More powerful gutter model.
    • -
    • Support for arbitrary text/widget height.
    • -
    • In-line widgets.
    • -
    • Generalized event handling.
    • -
    - -
    - -
    - -

    Version 2.x

    - -

    21-01-2013: Version 2.38:

    - -

    Integrate some bugfixes, enhancements to the vim keymap, and new - modes - (D, Sass, APL) - from the v3 branch.

    - -

    20-12-2012: Version 2.37:

    - -
      -
    • New mode: SQL (will replace plsql and mysql modes).
    • -
    • Further work on the new VIM mode.
    • -
    • Fix Cmd/Ctrl keys on recent Operas on OS X.
    • -
    • Full list of patches.
    • -
    - -

    20-11-2012: Version 2.36:

    - - - -

    22-10-2012: Version 2.35:

    - -
      -
    • New (sub) mode: TypeScript.
    • -
    • Don't overwrite (insert key) when pasting.
    • -
    • Fix several bugs in markText/undo interaction.
    • -
    • Better indentation of JavaScript code without semicolons.
    • -
    • Add defineInitHook function.
    • -
    • Full list of patches.
    • -
    - -

    19-09-2012: Version 2.34:

    - -
      -
    • New mode: Common Lisp.
    • -
    • Fix right-click select-all on most browsers.
    • -
    • Change the way highlighting happens:
        Saves memory and CPU cycles.
        compareStates is no longer needed.
        onHighlightComplete no longer works.
    • -
    • Integrate mode (Markdown, XQuery, CSS, sTex) tests in central testsuite.
    • -
    • Add a CodeMirror.version property.
    • -
    • More robust handling of nested modes in formatting and closetag plug-ins.
    • -
    • Un/redo now preserves marked text and bookmarks.
    • -
    • Full list of patches.
    • -
    - -

    23-08-2012: Version 2.33:

    - -
      -
    • New mode: Sieve.
    • -
    • New getViewPort and onViewportChange API.
    • -
    • Configurable cursor blink rate.
    • -
    • Make binding a key to false disabling handling (again).
    • -
    • Show non-printing characters as red dots.
    • -
    • More tweaks to the scrolling model.
    • -
    • Expanded testsuite. Basic linter added.
    • -
    • Remove most uses of innerHTML. Remove CodeMirror.htmlEscape.
    • -
    • Full list of patches.
    • -
    - -

    23-07-2012: Version 2.32:

    - -

    Emergency fix for a bug where an editor with - line wrapping on IE will break when there is no - scrollbar.

    - -

    20-07-2012: Version 2.31:

    - - - -

    22-06-2012: Version 2.3:

    - -
      -
    • New scrollbar implementation. Should flicker less. Changes DOM structure of the editor.
    • -
    • New theme: vibrant-ink.
    • -
    • Many extensions to the VIM keymap (including text objects).
    • -
    • Add mode-multiplexing utility script.
    • -
    • Fix bug where right-click paste works in read-only mode.
    • -
    • Add a getScrollInfo method.
    • -
    • Lots of other fixes.
    • -
    - -

    23-05-2012: Version 2.25:

    - -
      -
    • New mode: Erlang.
    • -
    • Remove xmlpure mode (use xml.js).
    • -
    • Fix line-wrapping in Opera.
    • -
    • Fix X Windows middle-click paste in Chrome.
    • -
    • Fix bug that broke pasting of huge documents.
    • -
    • Fix backspace and tab key repeat in Opera.
    • -
    - -

    23-04-2012: Version 2.24:

    - -
      -
    • Drop support for Internet Explorer 6.
    • -
    • New - modes: Shell, Tiki - wiki, Pig Latin.
    • -
    • New themes: Ambiance, Blackboard.
    • -
    • More control over drag/drop - with dragDrop - and onDragEvent - options.
    • -
    • Make HTML mode a bit less pedantic.
    • -
    • Add compoundChange API method.
    • -
    • Several fixes in undo history and line hiding.
    • -
    • Remove (broken) support for catchall in key maps, - add nofallthrough boolean field instead.
    • -
    - -

    26-03-2012: Version 2.23:

    - -
      -
    • Change default binding for tab [more] - -
    • -
    • New modes: XQuery and VBScript.
    • -
    • Two new themes: lesser-dark and xq-dark.
    • -
    • Differentiate between background and text styles in setLineClass.
    • -
    • Fix drag-and-drop in IE9+.
    • -
    • Extend charCoords - and cursorCoords with a mode argument.
    • -
    • Add autofocus option.
    • -
    • Add findMarksAt method.
    • -
    - -

    27-02-2012: Version 2.22:

    - - - -

    27-01-2012: Version 2.21:

    - -
      -
    • Added LESS, MySQL, - Go, and Verilog modes.
    • -
    • Add smartIndent - option.
    • -
    • Support a cursor in readOnly-mode.
    • -
    • Support assigning multiple styles to a token.
    • -
    • Use a new approach to drawing the selection.
    • -
    • Add scrollTo method.
    • -
    • Allow undo/redo events to span non-adjacent lines.
    • -
    • Lots and lots of bugfixes.
    • -
    - -

    20-12-2011: Version 2.2:

    - - - -

    21-11-2011: Version 2.18:

    -

    Fixes TextMarker.clear, which is broken in 2.17.

    - -

    21-11-2011: Version 2.17:

    -
      -
    • Add support for line - wrapping and code - folding.
    • -
    • Add Github-style Markdown mode.
    • -
    • Add Monokai - and Rubyblue themes.
    • -
    • Add setBookmark method.
    • -
    • Move some of the demo code into reusable components - under lib/util.
    • -
    • Make screen-coord-finding code faster and more reliable.
    • -
    • Fix drag-and-drop in Firefox.
    • -
    • Improve support for IME.
    • -
    • Speed up content rendering.
    • -
    • Fix browser's built-in search in Webkit.
    • -
    • Make double- and triple-click work in IE.
    • -
    • Various fixes to modes.
    • -
    - -

    27-10-2011: Version 2.16:

    -
      -
    • Add Perl, Rust, TiddlyWiki, and Groovy modes.
    • -
    • Dragging text inside the editor now moves, rather than copies.
    • -
    • Add a coordsFromIndex method.
    • -
    • API change: setValue now no longer clears history. Use clearHistory for that.
    • -
    • API change: markText now - returns an object with clear and find - methods. Marked text is now more robust when edited.
    • -
    • Fix editing code with tabs in Internet Explorer.
    • -
    - -

    26-09-2011: Version 2.15:

    -

    Fix bug that snuck into 2.14: Clicking the - character that currently has the cursor didn't re-focus the - editor.

    - -

    26-09-2011: Version 2.14:

    - - - -

    23-08-2011: Version 2.13:

    - - -

    25-07-2011: Version 2.12:

    -
      -
    • Add a SPARQL mode.
    • -
    • Fix bug with cursor jumping around in an unfocused editor in IE.
    • -
    • Allow key and mouse events to bubble out of the editor. Ignore widget clicks.
    • -
    • Solve cursor flakiness after undo/redo.
    • -
    • Fix block-reindent ignoring the last few lines.
    • -
    • Fix parsing of multi-line attrs in XML mode.
    • -
    • Use innerHTML for HTML-escaping.
    • -
    • Some fixes to indentation in C-like mode.
    • -
    • Shrink horiz scrollbars when long lines removed.
    • -
    • Fix width feedback loop bug that caused the width of an inner DIV to shrink.
    • -
    - -

    04-07-2011: Version 2.11:

    -
      -
    • Add a Scheme mode.
    • -
    • Add a replace method to search cursors, for cursor-preserving replacements.
    • -
    • Make the C-like mode mode more customizable.
    • -
    • Update XML mode to spot mismatched tags.
    • -
    • Add getStateAfter API and compareState mode API methods for finer-grained mode magic.
    • -
    • Add a getScrollerElement API method to manipulate the scrolling DIV.
    • -
    • Fix drag-and-drop for Firefox.
    • -
    • Add a C# configuration for the C-like mode.
    • -
    • Add full-screen editing and mode-changing demos.
    • -
    - -

    07-06-2011: Version 2.1:

    -

    Add - a theme system - (demo). Note that this is not - backwards-compatible—you'll have to update your styles and - modes!

    - -

    07-06-2011: Version 2.02:

    -
      -
    • Add a Lua mode.
    • -
    • Fix reverse-searching for a regexp.
    • -
    • Empty lines can no longer break highlighting.
    • -
    • Rework scrolling model (the outer wrapper no longer does the scrolling).
    • -
    • Solve horizontal jittering on long lines.
    • -
    • Add runmode.js.
    • -
    • Immediately re-highlight text when typing.
    • -
    • Fix problem with 'sticking' horizontal scrollbar.
    • -
    - -

    26-05-2011: Version 2.01:

    -
      -
    • Add a Smalltalk mode.
    • -
    • Add a reStructuredText mode.
    • -
    • Add a Python mode.
    • -
    • Add a PL/SQL mode.
    • -
    • coordsChar now works
    • -
    • Fix a problem where onCursorActivity interfered with onChange.
    • -
    • Fix a number of scrolling and mouse-click-position glitches.
    • -
    • Pass information about the changed lines to onChange.
    • -
    • Support cmd-up/down on OS X.
    • -
    • Add triple-click line selection.
    • -
    • Don't handle shift when changing the selection through the API.
    • -
    • Support "nocursor" mode for readOnly option.
    • -
    • Add an onHighlightComplete option.
    • -
    • Fix the context menu for Firefox.
    • -
    - -

    28-03-2011: Version 2.0:

    -

    CodeMirror 2 is a complete rewrite that's - faster, smaller, simpler to use, and less dependent on browser - quirks. See this - and this - for more information.

    - -

    22-02-2011: Version 2.0 beta 2:

    -

    Somewhat more mature API, lots of bugs shaken out.

    - -

    17-02-2011: Version 0.94:

    -
      -
    • tabMode: "spaces" was modified slightly (now indents when something is selected).
    • -
    • Fixes a bug that would cause the selection code to break on some IE versions.
    • -
    • Disabling spell-check on WebKit browsers now works.
    • -
    - -

    08-02-2011: Version 2.0 beta 1:

    -

    CodeMirror 2 is a complete rewrite of - CodeMirror, no longer depending on an editable frame.

    - -

    19-01-2011: Version 0.93:

    -
      -
    • Added a Regular Expression parser.
    • -
    • Fixes to the PHP parser.
    • -
    • Support for regular expression in search/replace.
    • -
    • Add save method to instances created with fromTextArea.
    • -
    • Add support for MS T-SQL in the SQL parser.
    • -
    • Support use of CSS classes for highlighting brackets.
    • -
    • Fix yet another hang with line-numbering in hidden editors.
    • -
    -
    - -
    - -

    Version 0.x

    - -

    28-03-2011: Version 1.0:

    -
      -
    • Fix error when debug history overflows.
    • -
    • Refine handling of C# verbatim strings.
    • -
    • Fix some issues with JavaScript indentation.
    • -
    - -

    17-12-2010: Version 0.92:

    -
      -
    • Make CodeMirror work in XHTML documents.
    • -
    • Fix bug in handling of backslashes in Python strings.
    • -
    • The styleNumbers option is now officially - supported and documented.
    • -
    • onLineNumberClick option added.
    • -
    • More consistent names onLoad and - onCursorActivity callbacks. Old names still work, but - are deprecated.
    • -
    • Add a Freemarker mode.
    • -
    - -

    11-11-2010: Version 0.91:

    -
      -
    • Adds support for Java.
    • -
    • Small additions to the PHP and SQL parsers.
    • -
    • Work around various Webkit issues.
    • -
    • Fix toTextArea to update the code in the textarea.
    • -
    • Add a noScriptCaching option (hack to ease development).
    • -
    • Make sub-modes of HTML mixed mode configurable.
    • -
    - -

    02-10-2010: Version 0.9:

    -
      -
    • Add support for searching backwards.
    • -
    • There are now parsers for Scheme, XQuery, and OmetaJS.
    • -
    • Makes height: "dynamic" more robust.
    • -
    • Fixes bug where paste did not work on OS X.
    • -
    • Add a enterMode and electricChars options to make indentation even more customizable.
    • -
    • Add firstLineNumber option.
    • -
    • Fix bad handling of @media rules by the CSS parser.
    • -
    • Take a new, more robust approach to working around the invisible-last-line bug in WebKit.
    • -
    - -

    22-07-2010: Version 0.8:

    -
      -
    • Add a cursorCoords method to find the screen - coordinates of the cursor.
    • -
    • A number of fixes and support for more syntax in the PHP parser.
    • -
    • Fix indentation problem with JSON-mode JS parser in Webkit.
    • -
    • Add a minification UI.
    • -
    • Support a height: dynamic mode, where the editor's - height will adjust to the size of its content.
    • -
    • Better support for IME input mode.
    • -
    • Fix JavaScript parser getting confused when seeing a no-argument - function call.
    • -
    • Have CSS parser see the difference between selectors and other - identifiers.
    • -
    • Fix scrolling bug when pasting in a horizontally-scrolled - editor.
    • -
    • Support toTextArea method in instances created with - fromTextArea.
    • -
    • Work around new Opera cursor bug that causes the cursor to jump - when pressing backspace at the end of a line.
    • -
    - -

    27-04-2010: Version - 0.67:

    -

    More consistent page-up/page-down behaviour - across browsers. Fix some issues with hidden editors looping forever - when line-numbers were enabled. Make PHP parser parse - "\\" correctly. Have jumpToLine work on - line handles, and add cursorLine function to fetch the - line handle where the cursor currently is. Add new - setStylesheet function to switch style-sheets in a - running editor.

    - -

    01-03-2010: Version - 0.66:

    -

    Adds removeLine method to API. - Introduces the PLSQL parser. - Marks XML errors by adding (rather than replacing) a CSS class, so - that they can be disabled by modifying their style. Fixes several - selection bugs, and a number of small glitches.

    - -

    12-11-2009: Version - 0.65:

    -

    Add support for having both line-wrapping and - line-numbers turned on, make paren-highlighting style customisable - (markParen and unmarkParen config - options), work around a selection bug that Opera - reintroduced in version 10.

    - -

    23-10-2009: Version - 0.64:

    -

    Solves some issues introduced by the - paste-handling changes from the previous release. Adds - setSpellcheck, setTextWrapping, - setIndentUnit, setUndoDepth, - setTabMode, and setLineNumbers to - customise a running editor. Introduces an SQL parser. Fixes a few small - problems in the Python - parser. And, as usual, add workarounds for various newly discovered - browser incompatibilities.

    - -

    31-08-2009: Version 0.63:

    -

    Overhaul of paste-handling (less fragile), fixes for several - serious IE8 issues (cursor jumping, end-of-document bugs) and a number - of small problems.

    - -

    30-05-2009: Version 0.62:

    -

    Introduces Python - and Lua parsers. Add - setParser (on-the-fly mode changing) and - clearHistory methods. Make parsing passes time-based - instead of lines-based (see the passTime option).

    - -
    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/doc/reporting.html b/backend/_pv_1_3_5/static/codemirror/doc/reporting.html deleted file mode 100755 index 3c582d961..000000000 --- a/backend/_pv_1_3_5/static/codemirror/doc/reporting.html +++ /dev/null @@ -1,61 +0,0 @@ - - -CodeMirror: Reporting Bugs - - - - - -
    - -

    Reporting bugs effectively

    - -
    - -

    So you found a problem in CodeMirror. By all means, report it! Bug -reports from users are the main drive behind improvements to -CodeMirror. But first, please read over these points:

    - -
      -
    1. CodeMirror is maintained by volunteers. They don't owe you - anything, so be polite. Reports with an indignant or belligerent - tone tend to be moved to the bottom of the pile.
    2. - -
    3. Include information about the browser in which the - problem occurred. Even if you tested several browsers, and - the problem occurred in all of them, mention this fact in the bug - report. Also include browser version numbers and the operating - system that you're on.
    4. - -
    5. Mention which release of CodeMirror you're using. Preferably, - try also with the current development snapshot, to ensure the - problem has not already been fixed.
    6. - -
    7. Mention very precisely what went wrong. "X is broken" is not a - good bug report. What did you expect to happen? What happened - instead? Describe the exact steps a maintainer has to take to make - the problem occur. We can not fix something that we can not - observe.
    8. - -
    9. If the problem can not be reproduced in any of the demos - included in the CodeMirror distribution, please provide an HTML - document that demonstrates the problem. The best way to do this is - to go to jsbin.com, enter - it there, press save, and include the resulting link in your bug - report.
    10. -
    - -
    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/doc/upgrade_v2.2.html b/backend/_pv_1_3_5/static/codemirror/doc/upgrade_v2.2.html deleted file mode 100755 index 3948ce6e5..000000000 --- a/backend/_pv_1_3_5/static/codemirror/doc/upgrade_v2.2.html +++ /dev/null @@ -1,96 +0,0 @@ - - -CodeMirror: Version 2.2 upgrade guide - - - - - -
    - -

    Upgrading to v2.2

    - -

    There are a few things in the 2.2 release that require some care -when upgrading.

    - -

    No more default.css

    - -

    The default theme is now included -in codemirror.css, so -you do not have to included it separately anymore. (It was tiny, so -even if you're not using it, the extra data overhead is negligible.) - -

    Different key customization

    - -

    CodeMirror has moved to a system -where keymaps are used to -bind behavior to keys. This means custom -bindings are now possible.

    - -

    Three options that influenced key -behavior, tabMode, enterMode, -and smartHome, are no longer supported. Instead, you can -provide custom bindings to influence the way these keys act. This is -done through the -new extraKeys -option, which can hold an object mapping key names to functionality. A -simple example would be:

    - -
      extraKeys: {
    -    "Ctrl-S": function(instance) { saveText(instance.getValue()); },
    -    "Ctrl-/": "undo"
    -  }
    - -

    Keys can be mapped either to functions, which will be given the -editor instance as argument, or to strings, which are mapped through -functions through the CodeMirror.commands table, which -contains all the built-in editing commands, and can be inspected and -extended by external code.

    - -

    By default, the Home key is bound to -the "goLineStartSmart" command, which moves the cursor to -the first non-whitespace character on the line. You can set do this to -make it always go to the very start instead:

    - -
      extraKeys: {"Home": "goLineStart"}
    - -

    Similarly, Enter is bound -to "newlineAndIndent" by default. You can bind it to -something else to get different behavior. To disable special handling -completely and only get a newline character inserted, you can bind it -to false:

    - -
      extraKeys: {"Enter": false}
    - -

    The same works for Tab. If you don't want CodeMirror -to handle it, bind it to false. The default behaviour is -to indent the current line more ("indentMore" command), -and indent it less when shift is held ("indentLess"). -There are also "indentAuto" (smart indent) -and "insertTab" commands provided for alternate -behaviors. Or you can write your own handler function to do something -different altogether.

    - -

    Tabs

    - -

    Handling of tabs changed completely. The display width of tabs can -now be set with the tabSize option, and tabs can -be styled by setting CSS rules -for the cm-tab class.

    - -

    The default width for tabs is now 4, as opposed to the 8 that is -hard-wired into browsers. If you are relying on 8-space tabs, make -sure you explicitly set tabSize: 8 in your options.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/doc/upgrade_v3.html b/backend/_pv_1_3_5/static/codemirror/doc/upgrade_v3.html deleted file mode 100755 index 5f94067aa..000000000 --- a/backend/_pv_1_3_5/static/codemirror/doc/upgrade_v3.html +++ /dev/null @@ -1,230 +0,0 @@ - - -CodeMirror: Version 3 upgrade guide - - - - - - - - - - - - - - -
    - -

    Upgrading to version 3

    - -

    Version 3 does not depart too much from 2.x API, and sites that use -CodeMirror in a very simple way might be able to upgrade without -trouble. But it does introduce a number of incompatibilities. Please -at least skim this text before upgrading.

    - -

    Note that version 3 drops full support for Internet -Explorer 7. The editor will mostly work on that browser, but -it'll be significantly glitchy.

    - -
    -

    DOM structure

    - -

    This one is the most likely to cause problems. The internal -structure of the editor has changed quite a lot, mostly to implement a -new scrolling model.

    - -

    Editor height is now set on the outer wrapper element (CSS -class CodeMirror), not on the scroller element -(CodeMirror-scroll).

    - -

    Other nodes were moved, dropped, and added. If you have any code -that makes assumptions about the internal DOM structure of the editor, -you'll have to re-test it and probably update it to work with v3.

    - -

    See the styling section of the -manual for more information.

    -
    -
    -

    Gutter model

    - -

    In CodeMirror 2.x, there was a single gutter, and line markers -created with setMarker would have to somehow coexist with -the line numbers (if present). Version 3 allows you to specify an -array of gutters, by class -name, -use setGutterMarker -to add or remove markers in individual gutters, and clear whole -gutters -with clearGutter. -Gutter markers are now specified as DOM nodes, rather than HTML -snippets.

    - -

    The gutters no longer horizontally scrolls along with the content. -The fixedGutter option was removed (since it is now the -only behavior).

    - -
    -<style>
    -  /* Define a gutter style */
    -  .note-gutter { width: 3em; background: cyan; }
    -</style>
    -<script>
    -  // Create an instance with two gutters -- line numbers and notes
    -  var cm = new CodeMirror(document.body, {
    -    gutters: ["note-gutter", "CodeMirror-linenumbers"],
    -    lineNumbers: true
    -  });
    -  // Add a note to line 0
    -  cm.setGutterMarker(0, "note-gutter", document.createTextNode("hi"));
    -</script>
    -
    -
    -
    -

    Event handling

    - -

    Most of the onXYZ options have been removed. The same -effect is now obtained by calling -the on method with a string -identifying the event type. Multiple handlers can now be registered -(and individually unregistered) for an event, and objects such as line -handlers now also expose events. See the -full list here.

    - -

    (The onKeyEvent and onDragEvent options, -which act more as hooks than as event handlers, are still there in -their old form.)

    - -
    -cm.on("change", function(cm, change) {
    -  console.log("something changed! (" + change.origin + ")");
    -});
    -
    -
    -
    -

    markText method arguments

    - -

    The markText method -(which has gained some interesting new features, such as creating -atomic and read-only spans, or replacing spans with widgets) no longer -takes the CSS class name as a separate argument, but makes it an -optional field in the options object instead.

    - -
    -// Style first ten lines, and forbid the cursor from entering them
    -cm.markText({line: 0, ch: 0}, {line: 10, ch: 0}, {
    -  className: "magic-text",
    -  inclusiveLeft: true,
    -  atomic: true
    -});
    -
    -
    -
    -

    Line folding

    - -

    The interface for hiding lines has been -removed. markText can -now be used to do the same in a more flexible and powerful way.

    - -

    The folding script has been -updated to use the new interface, and should now be more robust.

    - -
    -// Fold a range, replacing it with the text "??"
    -var range = cm.markText({line: 4, ch: 2}, {line: 8, ch: 1}, {
    -  replacedWith: document.createTextNode("??"),
    -  // Auto-unfold when cursor moves into the range
    -  clearOnEnter: true
    -});
    -// Get notified when auto-unfolding
    -CodeMirror.on(range, "clear", function() {
    -  console.log("boom");
    -});
    -
    -
    -
    -

    Line CSS classes

    - -

    The setLineClass method has been replaced -by addLineClass -and removeLineClass, -which allow more modular control over the classes attached to a line.

    - -
    -var marked = cm.addLineClass(10, "background", "highlighted-line");
    -setTimeout(function() {
    -  cm.removeLineClass(marked, "background", "highlighted-line");
    -});
    -
    -
    -
    -

    Position properties

    - -

    All methods that take or return objects that represent screen -positions now use {left, top, bottom, right} properties -(not always all of them) instead of the {x, y, yBot} used -by some methods in v2.x.

    - -

    Affected methods -are cursorCoords, charCoords, coordsChar, -and getScrollInfo.

    -
    -
    -

    Bracket matching no longer in core

    - -

    The matchBrackets -option is no longer defined in the core editor. -Load addon/edit/matchbrackets.js to enable it.

    -
    -
    -

    Mode management

    - -

    The CodeMirror.listModes -and CodeMirror.listMIMEs functions, used for listing -defined modes, are gone. You are now encouraged to simply -inspect CodeMirror.modes (mapping mode names to mode -constructors) and CodeMirror.mimeModes (mapping MIME -strings to mode specs).

    -
    -
    -

    New features

    - -

    Some more reasons to upgrade to version 3.

    - -
      -
    • Bi-directional text support. CodeMirror will now mostly do the - right thing when editing Arabic or Hebrew text.
    • -
    • Arbitrary line heights. Using fonts with different heights - inside the editor (whether off by one pixel or fifty) is now - supported and handled gracefully.
    • -
    • In-line widgets. See the demo - and the docs.
    • -
    • Defining custom options - with CodeMirror.defineOption.
    • -
    -
    -
    - - diff --git a/backend/_pv_1_3_5/static/codemirror/doc/upgrade_v4.html b/backend/_pv_1_3_5/static/codemirror/doc/upgrade_v4.html deleted file mode 100755 index 09df00ca1..000000000 --- a/backend/_pv_1_3_5/static/codemirror/doc/upgrade_v4.html +++ /dev/null @@ -1,144 +0,0 @@ - - -CodeMirror: Version 4 upgrade guide - - - - - - -
    - -

    Upgrading to version 4

    - -

    CodeMirror 4's interface is very close version 3, but it -does fix a few awkward details in a backwards-incompatible ways. At -least skim the text below before upgrading.

    - -

    Multiple selections

    - -

    The main new feature in version 4 is multiple selections. The -single-selection variants of methods are still there, but now -typically act only on the primary selection (usually the last -one added).

    - -

    The exception to this -is getSelection, -which will now return the content of all selections -(separated by newlines, or whatever lineSep parameter you passed -it).

    - -
    - -

    The beforeSelectionChange event

    - -

    This event still exists, but the object it is passed has -a completely new -interface, because such changes now concern multiple -selections.

    - -
    - -

    replaceSelection's collapsing behavior

    - -

    By -default, replaceSelection -would leave the newly inserted text selected. This is only rarely what -you want, and also (slightly) more expensive in the new model, so the -default was changed to "end", meaning the old behavior -must be explicitly specified by passing a second argument -of "around".

    - -
    - -

    change event data

    - -

    Rather than forcing client code to follow next -pointers from one change object to the next, the library will now -simply fire -multiple "change" -events. Existing code will probably continue to work unmodified.

    - -
    - -

    showIfHidden option to line widgets

    - -

    This option, which conceptually caused line widgets to be visible -even if their line was hidden, was never really well-defined, and was -buggy from the start. It would be a rather expensive feature, both in -code complexity and run-time performance, to implement properly. It -has been dropped entirely in 4.0.

    - -
    - -

    Module loaders

    - -

    All modules in the CodeMirror distribution are now wrapped in a -shim function to make them compatible with both AMD -(requirejs) and CommonJS (as used -by node -and browserify) module loaders. -When neither of these is present, they fall back to simply using the -global CodeMirror variable.

    - -

    If you have a module loader present in your environment, CodeMirror -will attempt to use it, and you might need to change the way you load -CodeMirror modules.

    - -
    - -

    Mutating shared data structures

    - -

    Data structures produced by the library should not be mutated -unless explicitly allowed, in general. This is slightly more strict in -4.0 than it was in earlier versions, which copied the position objects -returned by getCursor -for nebulous, historic reasons. In 4.0, mutating these -objects will corrupt your editor's selection.

    - -
    - -

    Deprecated interfaces dropped

    - -

    A few properties and methods that have been deprecated for a while -are now gone. Most notably, the onKeyEvent -and onDragEvent options (use the -corresponding events instead).

    - -

    Two silly methods, which were mostly there to stay close to the 0.x -API, setLine and removeLine are now gone. -Use the more -flexible replaceRange -method instead.

    - -

    The long names for folding and completing functions -(CodeMirror.braceRangeFinder, CodeMirror.javascriptHint, -etc) are also gone -(use CodeMirror.fold.brace, CodeMirror.hint.javascript).

    - -

    The className property in the return value -of getTokenAt, which -has been superseded by the type property, is also no -longer present.

    - -
    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/doc/yinyang.png b/backend/_pv_1_3_5/static/codemirror/doc/yinyang.png deleted file mode 100755 index 2eafd3f1ca137898ede8c27d0e64d99919bdc1ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4633 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 - -CodeMirror - - - - - - - - - - - - - - - - - -
    - -
    -

    CodeMirror is a versatile text editor - implemented in JavaScript for the browser. It is specialized for - editing code, and comes with a number of language modes and addons - that implement more advanced editing functionality.

    - -

    A rich programming API and a - CSS theming system are - available for customizing CodeMirror to fit your application, and - extending it with new functionality.

    -
    - -
    -

    This is CodeMirror

    -
    -
    - - -
    -
    - - - -
    -
    - Get the current version: 5.23.0.
    - You can see the code,
    - read the release notes,
    - or study the user manual. -
    -
    - Software needs maintenance,
    - maintainers need to subsist.
    - Current funding status =
    - You can help per month or - once. -
    - - -
    -
    -
    - -
    - -
    -

    Features

    - -
    - -
    -

    Community

    - -

    CodeMirror is an open-source project shared under - an MIT license. It is the editor used in the - dev tools for - both Firefox - and Chrome, Light - Table, Adobe - Brackets, Bitbucket, - and many other projects.

    - -

    Development and bug tracking happens - on github - (alternate git - repository). - Please read these - pointers before submitting a bug. Use pull requests to submit - patches. All contributions must be released under the same MIT - license that CodeMirror uses.

    - -

    Discussion around the project is done on - a discussion forum. - Announcements related to the project, such as new versions, are - posted in the - forum's "announce" - category. If needed, you can - contact the maintainer - directly. We aim to be an inclusive, welcoming community. To make - that explicit, we have - a code of - conduct that applies to communication around the project.

    - -

    A list of CodeMirror-related software that is not part of the - main distribution is maintained - on our - wiki. Feel free to add your project.

    -
    - -
    -

    Browser support

    -

    The desktop versions of the following browsers, - in standards mode (HTML5 <!doctype html> - recommended) are supported:

    - - - - - - -
    Firefoxversion 4 and up
    Chromeany version
    Safariversion 5.2 and up
    Internet Explorerversion 8 and up
    Operaversion 9 and up
    -

    Support for modern mobile browsers is experimental. Recent - versions of the iOS browser and Chrome on Android should work - pretty well.

    -
    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/keymap/emacs.js b/backend/_pv_1_3_5/static/codemirror/keymap/emacs.js deleted file mode 100755 index 57cf6e852..000000000 --- a/backend/_pv_1_3_5/static/codemirror/keymap/emacs.js +++ /dev/null @@ -1,414 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - var Pos = CodeMirror.Pos; - function posEq(a, b) { return a.line == b.line && a.ch == b.ch; } - - // Kill 'ring' - - var killRing = []; - function addToRing(str) { - killRing.push(str); - if (killRing.length > 50) killRing.shift(); - } - function growRingTop(str) { - if (!killRing.length) return addToRing(str); - killRing[killRing.length - 1] += str; - } - function getFromRing(n) { return killRing[killRing.length - (n ? Math.min(n, 1) : 1)] || ""; } - function popFromRing() { if (killRing.length > 1) killRing.pop(); return getFromRing(); } - - var lastKill = null; - - function kill(cm, from, to, mayGrow, text) { - if (text == null) text = cm.getRange(from, to); - - if (mayGrow && lastKill && lastKill.cm == cm && posEq(from, lastKill.pos) && cm.isClean(lastKill.gen)) - growRingTop(text); - else - addToRing(text); - cm.replaceRange("", from, to, "+delete"); - - if (mayGrow) lastKill = {cm: cm, pos: from, gen: cm.changeGeneration()}; - else lastKill = null; - } - - // Boundaries of various units - - function byChar(cm, pos, dir) { - return cm.findPosH(pos, dir, "char", true); - } - - function byWord(cm, pos, dir) { - return cm.findPosH(pos, dir, "word", true); - } - - function byLine(cm, pos, dir) { - return cm.findPosV(pos, dir, "line", cm.doc.sel.goalColumn); - } - - function byPage(cm, pos, dir) { - return cm.findPosV(pos, dir, "page", cm.doc.sel.goalColumn); - } - - function byParagraph(cm, pos, dir) { - var no = pos.line, line = cm.getLine(no); - var sawText = /\S/.test(dir < 0 ? line.slice(0, pos.ch) : line.slice(pos.ch)); - var fst = cm.firstLine(), lst = cm.lastLine(); - for (;;) { - no += dir; - if (no < fst || no > lst) - return cm.clipPos(Pos(no - dir, dir < 0 ? 0 : null)); - line = cm.getLine(no); - var hasText = /\S/.test(line); - if (hasText) sawText = true; - else if (sawText) return Pos(no, 0); - } - } - - function bySentence(cm, pos, dir) { - var line = pos.line, ch = pos.ch; - var text = cm.getLine(pos.line), sawWord = false; - for (;;) { - var next = text.charAt(ch + (dir < 0 ? -1 : 0)); - if (!next) { // End/beginning of line reached - if (line == (dir < 0 ? cm.firstLine() : cm.lastLine())) return Pos(line, ch); - text = cm.getLine(line + dir); - if (!/\S/.test(text)) return Pos(line, ch); - line += dir; - ch = dir < 0 ? text.length : 0; - continue; - } - if (sawWord && /[!?.]/.test(next)) return Pos(line, ch + (dir > 0 ? 1 : 0)); - if (!sawWord) sawWord = /\w/.test(next); - ch += dir; - } - } - - function byExpr(cm, pos, dir) { - var wrap; - if (cm.findMatchingBracket && (wrap = cm.findMatchingBracket(pos, true)) - && wrap.match && (wrap.forward ? 1 : -1) == dir) - return dir > 0 ? Pos(wrap.to.line, wrap.to.ch + 1) : wrap.to; - - for (var first = true;; first = false) { - var token = cm.getTokenAt(pos); - var after = Pos(pos.line, dir < 0 ? token.start : token.end); - if (first && dir > 0 && token.end == pos.ch || !/\w/.test(token.string)) { - var newPos = cm.findPosH(after, dir, "char"); - if (posEq(after, newPos)) return pos; - else pos = newPos; - } else { - return after; - } - } - } - - // Prefixes (only crudely supported) - - function getPrefix(cm, precise) { - var digits = cm.state.emacsPrefix; - if (!digits) return precise ? null : 1; - clearPrefix(cm); - return digits == "-" ? -1 : Number(digits); - } - - function repeated(cmd) { - var f = typeof cmd == "string" ? function(cm) { cm.execCommand(cmd); } : cmd; - return function(cm) { - var prefix = getPrefix(cm); - f(cm); - for (var i = 1; i < prefix; ++i) f(cm); - }; - } - - function findEnd(cm, pos, by, dir) { - var prefix = getPrefix(cm); - if (prefix < 0) { dir = -dir; prefix = -prefix; } - for (var i = 0; i < prefix; ++i) { - var newPos = by(cm, pos, dir); - if (posEq(newPos, pos)) break; - pos = newPos; - } - return pos; - } - - function move(by, dir) { - var f = function(cm) { - cm.extendSelection(findEnd(cm, cm.getCursor(), by, dir)); - }; - f.motion = true; - return f; - } - - function killTo(cm, by, dir) { - var selections = cm.listSelections(), cursor; - var i = selections.length; - while (i--) { - cursor = selections[i].head; - kill(cm, cursor, findEnd(cm, cursor, by, dir), true); - } - } - - function killRegion(cm) { - if (cm.somethingSelected()) { - var selections = cm.listSelections(), selection; - var i = selections.length; - while (i--) { - selection = selections[i]; - kill(cm, selection.anchor, selection.head); - } - return true; - } - } - - function addPrefix(cm, digit) { - if (cm.state.emacsPrefix) { - if (digit != "-") cm.state.emacsPrefix += digit; - return; - } - // Not active yet - cm.state.emacsPrefix = digit; - cm.on("keyHandled", maybeClearPrefix); - cm.on("inputRead", maybeDuplicateInput); - } - - var prefixPreservingKeys = {"Alt-G": true, "Ctrl-X": true, "Ctrl-Q": true, "Ctrl-U": true}; - - function maybeClearPrefix(cm, arg) { - if (!cm.state.emacsPrefixMap && !prefixPreservingKeys.hasOwnProperty(arg)) - clearPrefix(cm); - } - - function clearPrefix(cm) { - cm.state.emacsPrefix = null; - cm.off("keyHandled", maybeClearPrefix); - cm.off("inputRead", maybeDuplicateInput); - } - - function maybeDuplicateInput(cm, event) { - var dup = getPrefix(cm); - if (dup > 1 && event.origin == "+input") { - var one = event.text.join("\n"), txt = ""; - for (var i = 1; i < dup; ++i) txt += one; - cm.replaceSelection(txt); - } - } - - function addPrefixMap(cm) { - cm.state.emacsPrefixMap = true; - cm.addKeyMap(prefixMap); - cm.on("keyHandled", maybeRemovePrefixMap); - cm.on("inputRead", maybeRemovePrefixMap); - } - - function maybeRemovePrefixMap(cm, arg) { - if (typeof arg == "string" && (/^\d$/.test(arg) || arg == "Ctrl-U")) return; - cm.removeKeyMap(prefixMap); - cm.state.emacsPrefixMap = false; - cm.off("keyHandled", maybeRemovePrefixMap); - cm.off("inputRead", maybeRemovePrefixMap); - } - - // Utilities - - function setMark(cm) { - cm.setCursor(cm.getCursor()); - cm.setExtending(!cm.getExtending()); - cm.on("change", function() { cm.setExtending(false); }); - } - - function clearMark(cm) { - cm.setExtending(false); - cm.setCursor(cm.getCursor()); - } - - function getInput(cm, msg, f) { - if (cm.openDialog) - cm.openDialog(msg + ": ", f, {bottom: true}); - else - f(prompt(msg, "")); - } - - function operateOnWord(cm, op) { - var start = cm.getCursor(), end = cm.findPosH(start, 1, "word"); - cm.replaceRange(op(cm.getRange(start, end)), start, end); - cm.setCursor(end); - } - - function toEnclosingExpr(cm) { - var pos = cm.getCursor(), line = pos.line, ch = pos.ch; - var stack = []; - while (line >= cm.firstLine()) { - var text = cm.getLine(line); - for (var i = ch == null ? text.length : ch; i > 0;) { - var ch = text.charAt(--i); - if (ch == ")") - stack.push("("); - else if (ch == "]") - stack.push("["); - else if (ch == "}") - stack.push("{"); - else if (/[\(\{\[]/.test(ch) && (!stack.length || stack.pop() != ch)) - return cm.extendSelection(Pos(line, i)); - } - --line; ch = null; - } - } - - function quit(cm) { - cm.execCommand("clearSearch"); - clearMark(cm); - } - - CodeMirror.emacs = {kill: kill, killRegion: killRegion, repeated: repeated}; - - // Actual keymap - - var keyMap = CodeMirror.keyMap.emacs = CodeMirror.normalizeKeyMap({ - "Ctrl-W": function(cm) {kill(cm, cm.getCursor("start"), cm.getCursor("end"));}, - "Ctrl-K": repeated(function(cm) { - var start = cm.getCursor(), end = cm.clipPos(Pos(start.line)); - var text = cm.getRange(start, end); - if (!/\S/.test(text)) { - text += "\n"; - end = Pos(start.line + 1, 0); - } - kill(cm, start, end, true, text); - }), - "Alt-W": function(cm) { - addToRing(cm.getSelection()); - clearMark(cm); - }, - "Ctrl-Y": function(cm) { - var start = cm.getCursor(); - cm.replaceRange(getFromRing(getPrefix(cm)), start, start, "paste"); - cm.setSelection(start, cm.getCursor()); - }, - "Alt-Y": function(cm) {cm.replaceSelection(popFromRing(), "around", "paste");}, - - "Ctrl-Space": setMark, "Ctrl-Shift-2": setMark, - - "Ctrl-F": move(byChar, 1), "Ctrl-B": move(byChar, -1), - "Right": move(byChar, 1), "Left": move(byChar, -1), - "Ctrl-D": function(cm) { killTo(cm, byChar, 1); }, - "Delete": function(cm) { killRegion(cm) || killTo(cm, byChar, 1); }, - "Ctrl-H": function(cm) { killTo(cm, byChar, -1); }, - "Backspace": function(cm) { killRegion(cm) || killTo(cm, byChar, -1); }, - - "Alt-F": move(byWord, 1), "Alt-B": move(byWord, -1), - "Alt-D": function(cm) { killTo(cm, byWord, 1); }, - "Alt-Backspace": function(cm) { killTo(cm, byWord, -1); }, - - "Ctrl-N": move(byLine, 1), "Ctrl-P": move(byLine, -1), - "Down": move(byLine, 1), "Up": move(byLine, -1), - "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", - "End": "goLineEnd", "Home": "goLineStart", - - "Alt-V": move(byPage, -1), "Ctrl-V": move(byPage, 1), - "PageUp": move(byPage, -1), "PageDown": move(byPage, 1), - - "Ctrl-Up": move(byParagraph, -1), "Ctrl-Down": move(byParagraph, 1), - - "Alt-A": move(bySentence, -1), "Alt-E": move(bySentence, 1), - "Alt-K": function(cm) { killTo(cm, bySentence, 1); }, - - "Ctrl-Alt-K": function(cm) { killTo(cm, byExpr, 1); }, - "Ctrl-Alt-Backspace": function(cm) { killTo(cm, byExpr, -1); }, - "Ctrl-Alt-F": move(byExpr, 1), "Ctrl-Alt-B": move(byExpr, -1), - - "Shift-Ctrl-Alt-2": function(cm) { - var cursor = cm.getCursor(); - cm.setSelection(findEnd(cm, cursor, byExpr, 1), cursor); - }, - "Ctrl-Alt-T": function(cm) { - var leftStart = byExpr(cm, cm.getCursor(), -1), leftEnd = byExpr(cm, leftStart, 1); - var rightEnd = byExpr(cm, leftEnd, 1), rightStart = byExpr(cm, rightEnd, -1); - cm.replaceRange(cm.getRange(rightStart, rightEnd) + cm.getRange(leftEnd, rightStart) + - cm.getRange(leftStart, leftEnd), leftStart, rightEnd); - }, - "Ctrl-Alt-U": repeated(toEnclosingExpr), - - "Alt-Space": function(cm) { - var pos = cm.getCursor(), from = pos.ch, to = pos.ch, text = cm.getLine(pos.line); - while (from && /\s/.test(text.charAt(from - 1))) --from; - while (to < text.length && /\s/.test(text.charAt(to))) ++to; - cm.replaceRange(" ", Pos(pos.line, from), Pos(pos.line, to)); - }, - "Ctrl-O": repeated(function(cm) { cm.replaceSelection("\n", "start"); }), - "Ctrl-T": repeated(function(cm) { - cm.execCommand("transposeChars"); - }), - - "Alt-C": repeated(function(cm) { - operateOnWord(cm, function(w) { - var letter = w.search(/\w/); - if (letter == -1) return w; - return w.slice(0, letter) + w.charAt(letter).toUpperCase() + w.slice(letter + 1).toLowerCase(); - }); - }), - "Alt-U": repeated(function(cm) { - operateOnWord(cm, function(w) { return w.toUpperCase(); }); - }), - "Alt-L": repeated(function(cm) { - operateOnWord(cm, function(w) { return w.toLowerCase(); }); - }), - - "Alt-;": "toggleComment", - - "Ctrl-/": repeated("undo"), "Shift-Ctrl--": repeated("undo"), - "Ctrl-Z": repeated("undo"), "Cmd-Z": repeated("undo"), - "Shift-Alt-,": "goDocStart", "Shift-Alt-.": "goDocEnd", - "Ctrl-S": "findNext", "Ctrl-R": "findPrev", "Ctrl-G": quit, "Shift-Alt-5": "replace", - "Alt-/": "autocomplete", - "Ctrl-J": "newlineAndIndent", "Enter": false, "Tab": "indentAuto", - - "Alt-G G": function(cm) { - var prefix = getPrefix(cm, true); - if (prefix != null && prefix > 0) return cm.setCursor(prefix - 1); - - getInput(cm, "Goto line", function(str) { - var num; - if (str && !isNaN(num = Number(str)) && num == (num|0) && num > 0) - cm.setCursor(num - 1); - }); - }, - - "Ctrl-X Tab": function(cm) { - cm.indentSelection(getPrefix(cm, true) || cm.getOption("indentUnit")); - }, - "Ctrl-X Ctrl-X": function(cm) { - cm.setSelection(cm.getCursor("head"), cm.getCursor("anchor")); - }, - "Ctrl-X Ctrl-S": "save", - "Ctrl-X Ctrl-W": "save", - "Ctrl-X S": "saveAll", - "Ctrl-X F": "open", - "Ctrl-X U": repeated("undo"), - "Ctrl-X K": "close", - "Ctrl-X Delete": function(cm) { kill(cm, cm.getCursor(), bySentence(cm, cm.getCursor(), 1), true); }, - "Ctrl-X H": "selectAll", - - "Ctrl-Q Tab": repeated("insertTab"), - "Ctrl-U": addPrefixMap - }); - - var prefixMap = {"Ctrl-G": clearPrefix}; - function regPrefix(d) { - prefixMap[d] = function(cm) { addPrefix(cm, d); }; - keyMap["Ctrl-" + d] = function(cm) { addPrefix(cm, d); }; - prefixPreservingKeys["Ctrl-" + d] = true; - } - for (var i = 0; i < 10; ++i) regPrefix(String(i)); - regPrefix("-"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/keymap/sublime.js b/backend/_pv_1_3_5/static/codemirror/keymap/sublime.js deleted file mode 100755 index 3d112ab96..000000000 --- a/backend/_pv_1_3_5/static/codemirror/keymap/sublime.js +++ /dev/null @@ -1,589 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// A rough approximation of Sublime Text's keybindings -// Depends on addon/search/searchcursor.js and optionally addon/dialog/dialogs.js - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../lib/codemirror"), require("../addon/search/searchcursor"), require("../addon/edit/matchbrackets")); - else if (typeof define == "function" && define.amd) // AMD - define(["../lib/codemirror", "../addon/search/searchcursor", "../addon/edit/matchbrackets"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - var map = CodeMirror.keyMap.sublime = {fallthrough: "default"}; - var cmds = CodeMirror.commands; - var Pos = CodeMirror.Pos; - var mac = CodeMirror.keyMap["default"] == CodeMirror.keyMap.macDefault; - var ctrl = mac ? "Cmd-" : "Ctrl-"; - - // This is not exactly Sublime's algorithm. I couldn't make heads or tails of that. - function findPosSubword(doc, start, dir) { - if (dir < 0 && start.ch == 0) return doc.clipPos(Pos(start.line - 1)); - var line = doc.getLine(start.line); - if (dir > 0 && start.ch >= line.length) return doc.clipPos(Pos(start.line + 1, 0)); - var state = "start", type; - for (var pos = start.ch, e = dir < 0 ? 0 : line.length, i = 0; pos != e; pos += dir, i++) { - var next = line.charAt(dir < 0 ? pos - 1 : pos); - var cat = next != "_" && CodeMirror.isWordChar(next) ? "w" : "o"; - if (cat == "w" && next.toUpperCase() == next) cat = "W"; - if (state == "start") { - if (cat != "o") { state = "in"; type = cat; } - } else if (state == "in") { - if (type != cat) { - if (type == "w" && cat == "W" && dir < 0) pos--; - if (type == "W" && cat == "w" && dir > 0) { type = "w"; continue; } - break; - } - } - } - return Pos(start.line, pos); - } - - function moveSubword(cm, dir) { - cm.extendSelectionsBy(function(range) { - if (cm.display.shift || cm.doc.extend || range.empty()) - return findPosSubword(cm.doc, range.head, dir); - else - return dir < 0 ? range.from() : range.to(); - }); - } - - var goSubwordCombo = mac ? "Ctrl-" : "Alt-"; - - cmds[map[goSubwordCombo + "Left"] = "goSubwordLeft"] = function(cm) { moveSubword(cm, -1); }; - cmds[map[goSubwordCombo + "Right"] = "goSubwordRight"] = function(cm) { moveSubword(cm, 1); }; - - if (mac) map["Cmd-Left"] = "goLineStartSmart"; - - var scrollLineCombo = mac ? "Ctrl-Alt-" : "Ctrl-"; - - cmds[map[scrollLineCombo + "Up"] = "scrollLineUp"] = function(cm) { - var info = cm.getScrollInfo(); - if (!cm.somethingSelected()) { - var visibleBottomLine = cm.lineAtHeight(info.top + info.clientHeight, "local"); - if (cm.getCursor().line >= visibleBottomLine) - cm.execCommand("goLineUp"); - } - cm.scrollTo(null, info.top - cm.defaultTextHeight()); - }; - cmds[map[scrollLineCombo + "Down"] = "scrollLineDown"] = function(cm) { - var info = cm.getScrollInfo(); - if (!cm.somethingSelected()) { - var visibleTopLine = cm.lineAtHeight(info.top, "local")+1; - if (cm.getCursor().line <= visibleTopLine) - cm.execCommand("goLineDown"); - } - cm.scrollTo(null, info.top + cm.defaultTextHeight()); - }; - - cmds[map["Shift-" + ctrl + "L"] = "splitSelectionByLine"] = function(cm) { - var ranges = cm.listSelections(), lineRanges = []; - for (var i = 0; i < ranges.length; i++) { - var from = ranges[i].from(), to = ranges[i].to(); - for (var line = from.line; line <= to.line; ++line) - if (!(to.line > from.line && line == to.line && to.ch == 0)) - lineRanges.push({anchor: line == from.line ? from : Pos(line, 0), - head: line == to.line ? to : Pos(line)}); - } - cm.setSelections(lineRanges, 0); - }; - - map["Shift-Tab"] = "indentLess"; - - cmds[map["Esc"] = "singleSelectionTop"] = function(cm) { - var range = cm.listSelections()[0]; - cm.setSelection(range.anchor, range.head, {scroll: false}); - }; - - cmds[map[ctrl + "L"] = "selectLine"] = function(cm) { - var ranges = cm.listSelections(), extended = []; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - extended.push({anchor: Pos(range.from().line, 0), - head: Pos(range.to().line + 1, 0)}); - } - cm.setSelections(extended); - }; - - map["Shift-Ctrl-K"] = "deleteLine"; - - function insertLine(cm, above) { - if (cm.isReadOnly()) return CodeMirror.Pass - cm.operation(function() { - var len = cm.listSelections().length, newSelection = [], last = -1; - for (var i = 0; i < len; i++) { - var head = cm.listSelections()[i].head; - if (head.line <= last) continue; - var at = Pos(head.line + (above ? 0 : 1), 0); - cm.replaceRange("\n", at, null, "+insertLine"); - cm.indentLine(at.line, null, true); - newSelection.push({head: at, anchor: at}); - last = head.line + 1; - } - cm.setSelections(newSelection); - }); - cm.execCommand("indentAuto"); - } - - cmds[map[ctrl + "Enter"] = "insertLineAfter"] = function(cm) { return insertLine(cm, false); }; - - cmds[map["Shift-" + ctrl + "Enter"] = "insertLineBefore"] = function(cm) { return insertLine(cm, true); }; - - function wordAt(cm, pos) { - var start = pos.ch, end = start, line = cm.getLine(pos.line); - while (start && CodeMirror.isWordChar(line.charAt(start - 1))) --start; - while (end < line.length && CodeMirror.isWordChar(line.charAt(end))) ++end; - return {from: Pos(pos.line, start), to: Pos(pos.line, end), word: line.slice(start, end)}; - } - - cmds[map[ctrl + "D"] = "selectNextOccurrence"] = function(cm) { - var from = cm.getCursor("from"), to = cm.getCursor("to"); - var fullWord = cm.state.sublimeFindFullWord == cm.doc.sel; - if (CodeMirror.cmpPos(from, to) == 0) { - var word = wordAt(cm, from); - if (!word.word) return; - cm.setSelection(word.from, word.to); - fullWord = true; - } else { - var text = cm.getRange(from, to); - var query = fullWord ? new RegExp("\\b" + text + "\\b") : text; - var cur = cm.getSearchCursor(query, to); - if (cur.findNext()) { - cm.addSelection(cur.from(), cur.to()); - } else { - cur = cm.getSearchCursor(query, Pos(cm.firstLine(), 0)); - if (cur.findNext()) - cm.addSelection(cur.from(), cur.to()); - } - } - if (fullWord) - cm.state.sublimeFindFullWord = cm.doc.sel; - }; - - var mirror = "(){}[]"; - function selectBetweenBrackets(cm) { - var ranges = cm.listSelections(), newRanges = [] - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i], pos = range.head, opening = cm.scanForBracket(pos, -1); - if (!opening) return false; - for (;;) { - var closing = cm.scanForBracket(pos, 1); - if (!closing) return false; - if (closing.ch == mirror.charAt(mirror.indexOf(opening.ch) + 1)) { - newRanges.push({anchor: Pos(opening.pos.line, opening.pos.ch + 1), - head: closing.pos}); - break; - } - pos = Pos(closing.pos.line, closing.pos.ch + 1); - } - } - cm.setSelections(newRanges); - return true; - } - - cmds[map["Shift-" + ctrl + "Space"] = "selectScope"] = function(cm) { - selectBetweenBrackets(cm) || cm.execCommand("selectAll"); - }; - cmds[map["Shift-" + ctrl + "M"] = "selectBetweenBrackets"] = function(cm) { - if (!selectBetweenBrackets(cm)) return CodeMirror.Pass; - }; - - cmds[map[ctrl + "M"] = "goToBracket"] = function(cm) { - cm.extendSelectionsBy(function(range) { - var next = cm.scanForBracket(range.head, 1); - if (next && CodeMirror.cmpPos(next.pos, range.head) != 0) return next.pos; - var prev = cm.scanForBracket(range.head, -1); - return prev && Pos(prev.pos.line, prev.pos.ch + 1) || range.head; - }); - }; - - var swapLineCombo = mac ? "Cmd-Ctrl-" : "Shift-Ctrl-"; - - cmds[map[swapLineCombo + "Up"] = "swapLineUp"] = function(cm) { - if (cm.isReadOnly()) return CodeMirror.Pass - var ranges = cm.listSelections(), linesToMove = [], at = cm.firstLine() - 1, newSels = []; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i], from = range.from().line - 1, to = range.to().line; - newSels.push({anchor: Pos(range.anchor.line - 1, range.anchor.ch), - head: Pos(range.head.line - 1, range.head.ch)}); - if (range.to().ch == 0 && !range.empty()) --to; - if (from > at) linesToMove.push(from, to); - else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to; - at = to; - } - cm.operation(function() { - for (var i = 0; i < linesToMove.length; i += 2) { - var from = linesToMove[i], to = linesToMove[i + 1]; - var line = cm.getLine(from); - cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine"); - if (to > cm.lastLine()) - cm.replaceRange("\n" + line, Pos(cm.lastLine()), null, "+swapLine"); - else - cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine"); - } - cm.setSelections(newSels); - cm.scrollIntoView(); - }); - }; - - cmds[map[swapLineCombo + "Down"] = "swapLineDown"] = function(cm) { - if (cm.isReadOnly()) return CodeMirror.Pass - var ranges = cm.listSelections(), linesToMove = [], at = cm.lastLine() + 1; - for (var i = ranges.length - 1; i >= 0; i--) { - var range = ranges[i], from = range.to().line + 1, to = range.from().line; - if (range.to().ch == 0 && !range.empty()) from--; - if (from < at) linesToMove.push(from, to); - else if (linesToMove.length) linesToMove[linesToMove.length - 1] = to; - at = to; - } - cm.operation(function() { - for (var i = linesToMove.length - 2; i >= 0; i -= 2) { - var from = linesToMove[i], to = linesToMove[i + 1]; - var line = cm.getLine(from); - if (from == cm.lastLine()) - cm.replaceRange("", Pos(from - 1), Pos(from), "+swapLine"); - else - cm.replaceRange("", Pos(from, 0), Pos(from + 1, 0), "+swapLine"); - cm.replaceRange(line + "\n", Pos(to, 0), null, "+swapLine"); - } - cm.scrollIntoView(); - }); - }; - - cmds[map[ctrl + "/"] = "toggleCommentIndented"] = function(cm) { - cm.toggleComment({ indent: true }); - } - - cmds[map[ctrl + "J"] = "joinLines"] = function(cm) { - var ranges = cm.listSelections(), joined = []; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i], from = range.from(); - var start = from.line, end = range.to().line; - while (i < ranges.length - 1 && ranges[i + 1].from().line == end) - end = ranges[++i].to().line; - joined.push({start: start, end: end, anchor: !range.empty() && from}); - } - cm.operation(function() { - var offset = 0, ranges = []; - for (var i = 0; i < joined.length; i++) { - var obj = joined[i]; - var anchor = obj.anchor && Pos(obj.anchor.line - offset, obj.anchor.ch), head; - for (var line = obj.start; line <= obj.end; line++) { - var actual = line - offset; - if (line == obj.end) head = Pos(actual, cm.getLine(actual).length + 1); - if (actual < cm.lastLine()) { - cm.replaceRange(" ", Pos(actual), Pos(actual + 1, /^\s*/.exec(cm.getLine(actual + 1))[0].length)); - ++offset; - } - } - ranges.push({anchor: anchor || head, head: head}); - } - cm.setSelections(ranges, 0); - }); - }; - - cmds[map["Shift-" + ctrl + "D"] = "duplicateLine"] = function(cm) { - cm.operation(function() { - var rangeCount = cm.listSelections().length; - for (var i = 0; i < rangeCount; i++) { - var range = cm.listSelections()[i]; - if (range.empty()) - cm.replaceRange(cm.getLine(range.head.line) + "\n", Pos(range.head.line, 0)); - else - cm.replaceRange(cm.getRange(range.from(), range.to()), range.from()); - } - cm.scrollIntoView(); - }); - }; - - if (!mac) map[ctrl + "T"] = "transposeChars"; - - function sortLines(cm, caseSensitive) { - if (cm.isReadOnly()) return CodeMirror.Pass - var ranges = cm.listSelections(), toSort = [], selected; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - if (range.empty()) continue; - var from = range.from().line, to = range.to().line; - while (i < ranges.length - 1 && ranges[i + 1].from().line == to) - to = ranges[++i].to().line; - if (!ranges[i].to().ch) to--; - toSort.push(from, to); - } - if (toSort.length) selected = true; - else toSort.push(cm.firstLine(), cm.lastLine()); - - cm.operation(function() { - var ranges = []; - for (var i = 0; i < toSort.length; i += 2) { - var from = toSort[i], to = toSort[i + 1]; - var start = Pos(from, 0), end = Pos(to); - var lines = cm.getRange(start, end, false); - if (caseSensitive) - lines.sort(); - else - lines.sort(function(a, b) { - var au = a.toUpperCase(), bu = b.toUpperCase(); - if (au != bu) { a = au; b = bu; } - return a < b ? -1 : a == b ? 0 : 1; - }); - cm.replaceRange(lines, start, end); - if (selected) ranges.push({anchor: start, head: Pos(to + 1, 0)}); - } - if (selected) cm.setSelections(ranges, 0); - }); - } - - cmds[map["F9"] = "sortLines"] = function(cm) { sortLines(cm, true); }; - cmds[map[ctrl + "F9"] = "sortLinesInsensitive"] = function(cm) { sortLines(cm, false); }; - - cmds[map["F2"] = "nextBookmark"] = function(cm) { - var marks = cm.state.sublimeBookmarks; - if (marks) while (marks.length) { - var current = marks.shift(); - var found = current.find(); - if (found) { - marks.push(current); - return cm.setSelection(found.from, found.to); - } - } - }; - - cmds[map["Shift-F2"] = "prevBookmark"] = function(cm) { - var marks = cm.state.sublimeBookmarks; - if (marks) while (marks.length) { - marks.unshift(marks.pop()); - var found = marks[marks.length - 1].find(); - if (!found) - marks.pop(); - else - return cm.setSelection(found.from, found.to); - } - }; - - cmds[map[ctrl + "F2"] = "toggleBookmark"] = function(cm) { - var ranges = cm.listSelections(); - var marks = cm.state.sublimeBookmarks || (cm.state.sublimeBookmarks = []); - for (var i = 0; i < ranges.length; i++) { - var from = ranges[i].from(), to = ranges[i].to(); - var found = cm.findMarks(from, to); - for (var j = 0; j < found.length; j++) { - if (found[j].sublimeBookmark) { - found[j].clear(); - for (var k = 0; k < marks.length; k++) - if (marks[k] == found[j]) - marks.splice(k--, 1); - break; - } - } - if (j == found.length) - marks.push(cm.markText(from, to, {sublimeBookmark: true, clearWhenEmpty: false})); - } - }; - - cmds[map["Shift-" + ctrl + "F2"] = "clearBookmarks"] = function(cm) { - var marks = cm.state.sublimeBookmarks; - if (marks) for (var i = 0; i < marks.length; i++) marks[i].clear(); - marks.length = 0; - }; - - cmds[map["Alt-F2"] = "selectBookmarks"] = function(cm) { - var marks = cm.state.sublimeBookmarks, ranges = []; - if (marks) for (var i = 0; i < marks.length; i++) { - var found = marks[i].find(); - if (!found) - marks.splice(i--, 0); - else - ranges.push({anchor: found.from, head: found.to}); - } - if (ranges.length) - cm.setSelections(ranges, 0); - }; - - map["Alt-Q"] = "wrapLines"; - - var cK = ctrl + "K "; - - function modifyWordOrSelection(cm, mod) { - cm.operation(function() { - var ranges = cm.listSelections(), indices = [], replacements = []; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - if (range.empty()) { indices.push(i); replacements.push(""); } - else replacements.push(mod(cm.getRange(range.from(), range.to()))); - } - cm.replaceSelections(replacements, "around", "case"); - for (var i = indices.length - 1, at; i >= 0; i--) { - var range = ranges[indices[i]]; - if (at && CodeMirror.cmpPos(range.head, at) > 0) continue; - var word = wordAt(cm, range.head); - at = word.from; - cm.replaceRange(mod(word.word), word.from, word.to); - } - }); - } - - map[cK + ctrl + "Backspace"] = "delLineLeft"; - - cmds[map["Backspace"] = "smartBackspace"] = function(cm) { - if (cm.somethingSelected()) return CodeMirror.Pass; - - cm.operation(function() { - var cursors = cm.listSelections(); - var indentUnit = cm.getOption("indentUnit"); - - for (var i = cursors.length - 1; i >= 0; i--) { - var cursor = cursors[i].head; - var toStartOfLine = cm.getRange({line: cursor.line, ch: 0}, cursor); - var column = CodeMirror.countColumn(toStartOfLine, null, cm.getOption("tabSize")); - - // Delete by one character by default - var deletePos = cm.findPosH(cursor, -1, "char", false); - - if (toStartOfLine && !/\S/.test(toStartOfLine) && column % indentUnit == 0) { - var prevIndent = new Pos(cursor.line, - CodeMirror.findColumn(toStartOfLine, column - indentUnit, indentUnit)); - - // Smart delete only if we found a valid prevIndent location - if (prevIndent.ch != cursor.ch) deletePos = prevIndent; - } - - cm.replaceRange("", deletePos, cursor, "+delete"); - } - }); - }; - - cmds[map[cK + ctrl + "K"] = "delLineRight"] = function(cm) { - cm.operation(function() { - var ranges = cm.listSelections(); - for (var i = ranges.length - 1; i >= 0; i--) - cm.replaceRange("", ranges[i].anchor, Pos(ranges[i].to().line), "+delete"); - cm.scrollIntoView(); - }); - }; - - cmds[map[cK + ctrl + "U"] = "upcaseAtCursor"] = function(cm) { - modifyWordOrSelection(cm, function(str) { return str.toUpperCase(); }); - }; - cmds[map[cK + ctrl + "L"] = "downcaseAtCursor"] = function(cm) { - modifyWordOrSelection(cm, function(str) { return str.toLowerCase(); }); - }; - - cmds[map[cK + ctrl + "Space"] = "setSublimeMark"] = function(cm) { - if (cm.state.sublimeMark) cm.state.sublimeMark.clear(); - cm.state.sublimeMark = cm.setBookmark(cm.getCursor()); - }; - cmds[map[cK + ctrl + "A"] = "selectToSublimeMark"] = function(cm) { - var found = cm.state.sublimeMark && cm.state.sublimeMark.find(); - if (found) cm.setSelection(cm.getCursor(), found); - }; - cmds[map[cK + ctrl + "W"] = "deleteToSublimeMark"] = function(cm) { - var found = cm.state.sublimeMark && cm.state.sublimeMark.find(); - if (found) { - var from = cm.getCursor(), to = found; - if (CodeMirror.cmpPos(from, to) > 0) { var tmp = to; to = from; from = tmp; } - cm.state.sublimeKilled = cm.getRange(from, to); - cm.replaceRange("", from, to); - } - }; - cmds[map[cK + ctrl + "X"] = "swapWithSublimeMark"] = function(cm) { - var found = cm.state.sublimeMark && cm.state.sublimeMark.find(); - if (found) { - cm.state.sublimeMark.clear(); - cm.state.sublimeMark = cm.setBookmark(cm.getCursor()); - cm.setCursor(found); - } - }; - cmds[map[cK + ctrl + "Y"] = "sublimeYank"] = function(cm) { - if (cm.state.sublimeKilled != null) - cm.replaceSelection(cm.state.sublimeKilled, null, "paste"); - }; - - map[cK + ctrl + "G"] = "clearBookmarks"; - cmds[map[cK + ctrl + "C"] = "showInCenter"] = function(cm) { - var pos = cm.cursorCoords(null, "local"); - cm.scrollTo(null, (pos.top + pos.bottom) / 2 - cm.getScrollInfo().clientHeight / 2); - }; - - var selectLinesCombo = mac ? "Ctrl-Shift-" : "Ctrl-Alt-"; - cmds[map[selectLinesCombo + "Up"] = "selectLinesUpward"] = function(cm) { - cm.operation(function() { - var ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - if (range.head.line > cm.firstLine()) - cm.addSelection(Pos(range.head.line - 1, range.head.ch)); - } - }); - }; - cmds[map[selectLinesCombo + "Down"] = "selectLinesDownward"] = function(cm) { - cm.operation(function() { - var ranges = cm.listSelections(); - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - if (range.head.line < cm.lastLine()) - cm.addSelection(Pos(range.head.line + 1, range.head.ch)); - } - }); - }; - - function getTarget(cm) { - var from = cm.getCursor("from"), to = cm.getCursor("to"); - if (CodeMirror.cmpPos(from, to) == 0) { - var word = wordAt(cm, from); - if (!word.word) return; - from = word.from; - to = word.to; - } - return {from: from, to: to, query: cm.getRange(from, to), word: word}; - } - - function findAndGoTo(cm, forward) { - var target = getTarget(cm); - if (!target) return; - var query = target.query; - var cur = cm.getSearchCursor(query, forward ? target.to : target.from); - - if (forward ? cur.findNext() : cur.findPrevious()) { - cm.setSelection(cur.from(), cur.to()); - } else { - cur = cm.getSearchCursor(query, forward ? Pos(cm.firstLine(), 0) - : cm.clipPos(Pos(cm.lastLine()))); - if (forward ? cur.findNext() : cur.findPrevious()) - cm.setSelection(cur.from(), cur.to()); - else if (target.word) - cm.setSelection(target.from, target.to); - } - }; - cmds[map[ctrl + "F3"] = "findUnder"] = function(cm) { findAndGoTo(cm, true); }; - cmds[map["Shift-" + ctrl + "F3"] = "findUnderPrevious"] = function(cm) { findAndGoTo(cm,false); }; - cmds[map["Alt-F3"] = "findAllUnder"] = function(cm) { - var target = getTarget(cm); - if (!target) return; - var cur = cm.getSearchCursor(target.query); - var matches = []; - var primaryIndex = -1; - while (cur.findNext()) { - matches.push({anchor: cur.from(), head: cur.to()}); - if (cur.from().line <= target.from.line && cur.from().ch <= target.from.ch) - primaryIndex++; - } - cm.setSelections(matches, primaryIndex); - }; - - map["Shift-" + ctrl + "["] = "fold"; - map["Shift-" + ctrl + "]"] = "unfold"; - map[cK + ctrl + "0"] = map[cK + ctrl + "J"] = "unfoldAll"; - - map[ctrl + "I"] = "findIncremental"; - map["Shift-" + ctrl + "I"] = "findIncrementalReverse"; - map[ctrl + "H"] = "replace"; - map["F3"] = "findNext"; - map["Shift-F3"] = "findPrev"; - - CodeMirror.normalizeKeyMap(map); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/keymap/vim.js b/backend/_pv_1_3_5/static/codemirror/keymap/vim.js deleted file mode 100755 index 34570bb88..000000000 --- a/backend/_pv_1_3_5/static/codemirror/keymap/vim.js +++ /dev/null @@ -1,5088 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** - * Supported keybindings: - * Too many to list. Refer to defaultKeyMap below. - * - * Supported Ex commands: - * Refer to defaultExCommandMap below. - * - * Registers: unnamed, -, a-z, A-Z, 0-9 - * (Does not respect the special case for number registers when delete - * operator is made with these commands: %, (, ), , /, ?, n, N, {, } ) - * TODO: Implement the remaining registers. - * - * Marks: a-z, A-Z, and 0-9 - * TODO: Implement the remaining special marks. They have more complex - * behavior. - * - * Events: - * 'vim-mode-change' - raised on the editor anytime the current mode changes, - * Event object: {mode: "visual", subMode: "linewise"} - * - * Code structure: - * 1. Default keymap - * 2. Variable declarations and short basic helpers - * 3. Instance (External API) implementation - * 4. Internal state tracking objects (input state, counter) implementation - * and instantiation - * 5. Key handler (the main command dispatcher) implementation - * 6. Motion, operator, and action implementations - * 7. Helper functions for the key handler, motions, operators, and actions - * 8. Set up Vim to work as a keymap for CodeMirror. - * 9. Ex command implementations. - */ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../lib/codemirror"), require("../addon/search/searchcursor"), require("../addon/dialog/dialog"), require("../addon/edit/matchbrackets.js")); - else if (typeof define == "function" && define.amd) // AMD - define(["../lib/codemirror", "../addon/search/searchcursor", "../addon/dialog/dialog", "../addon/edit/matchbrackets"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - 'use strict'; - - var defaultKeymap = [ - // Key to key mapping. This goes first to make it possible to override - // existing mappings. - { keys: '', type: 'keyToKey', toKeys: 'h' }, - { keys: '', type: 'keyToKey', toKeys: 'l' }, - { keys: '', type: 'keyToKey', toKeys: 'k' }, - { keys: '', type: 'keyToKey', toKeys: 'j' }, - { keys: '', type: 'keyToKey', toKeys: 'l' }, - { keys: '', type: 'keyToKey', toKeys: 'h', context: 'normal'}, - { keys: '', type: 'keyToKey', toKeys: 'W' }, - { keys: '', type: 'keyToKey', toKeys: 'B', context: 'normal' }, - { keys: '', type: 'keyToKey', toKeys: 'w' }, - { keys: '', type: 'keyToKey', toKeys: 'b', context: 'normal' }, - { keys: '', type: 'keyToKey', toKeys: 'j' }, - { keys: '', type: 'keyToKey', toKeys: 'k' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, - { keys: '', type: 'keyToKey', toKeys: '', context: 'insert' }, - { keys: 's', type: 'keyToKey', toKeys: 'cl', context: 'normal' }, - { keys: 's', type: 'keyToKey', toKeys: 'c', context: 'visual'}, - { keys: 'S', type: 'keyToKey', toKeys: 'cc', context: 'normal' }, - { keys: 'S', type: 'keyToKey', toKeys: 'VdO', context: 'visual' }, - { keys: '', type: 'keyToKey', toKeys: '0' }, - { keys: '', type: 'keyToKey', toKeys: '$' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: '' }, - { keys: '', type: 'keyToKey', toKeys: 'j^', context: 'normal' }, - { keys: '', type: 'action', action: 'toggleOverwrite', context: 'insert' }, - // Motions - { keys: 'H', type: 'motion', motion: 'moveToTopLine', motionArgs: { linewise: true, toJumplist: true }}, - { keys: 'M', type: 'motion', motion: 'moveToMiddleLine', motionArgs: { linewise: true, toJumplist: true }}, - { keys: 'L', type: 'motion', motion: 'moveToBottomLine', motionArgs: { linewise: true, toJumplist: true }}, - { keys: 'h', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: false }}, - { keys: 'l', type: 'motion', motion: 'moveByCharacters', motionArgs: { forward: true }}, - { keys: 'j', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, linewise: true }}, - { keys: 'k', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, linewise: true }}, - { keys: 'gj', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: true }}, - { keys: 'gk', type: 'motion', motion: 'moveByDisplayLines', motionArgs: { forward: false }}, - { keys: 'w', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false }}, - { keys: 'W', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: false, bigWord: true }}, - { keys: 'e', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, inclusive: true }}, - { keys: 'E', type: 'motion', motion: 'moveByWords', motionArgs: { forward: true, wordEnd: true, bigWord: true, inclusive: true }}, - { keys: 'b', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }}, - { keys: 'B', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false, bigWord: true }}, - { keys: 'ge', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, inclusive: true }}, - { keys: 'gE', type: 'motion', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: true, bigWord: true, inclusive: true }}, - { keys: '{', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: false, toJumplist: true }}, - { keys: '}', type: 'motion', motion: 'moveByParagraph', motionArgs: { forward: true, toJumplist: true }}, - { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: true }}, - { keys: '', type: 'motion', motion: 'moveByPage', motionArgs: { forward: false }}, - { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: true, explicitRepeat: true }}, - { keys: '', type: 'motion', motion: 'moveByScroll', motionArgs: { forward: false, explicitRepeat: true }}, - { keys: 'gg', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: false, explicitRepeat: true, linewise: true, toJumplist: true }}, - { keys: 'G', type: 'motion', motion: 'moveToLineOrEdgeOfDocument', motionArgs: { forward: true, explicitRepeat: true, linewise: true, toJumplist: true }}, - { keys: '0', type: 'motion', motion: 'moveToStartOfLine' }, - { keys: '^', type: 'motion', motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: '+', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true }}, - { keys: '-', type: 'motion', motion: 'moveByLines', motionArgs: { forward: false, toFirstChar:true }}, - { keys: '_', type: 'motion', motion: 'moveByLines', motionArgs: { forward: true, toFirstChar:true, repeatOffset:-1 }}, - { keys: '$', type: 'motion', motion: 'moveToEol', motionArgs: { inclusive: true }}, - { keys: '%', type: 'motion', motion: 'moveToMatchedSymbol', motionArgs: { inclusive: true, toJumplist: true }}, - { keys: 'f', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: true , inclusive: true }}, - { keys: 'F', type: 'motion', motion: 'moveToCharacter', motionArgs: { forward: false }}, - { keys: 't', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: true, inclusive: true }}, - { keys: 'T', type: 'motion', motion: 'moveTillCharacter', motionArgs: { forward: false }}, - { keys: ';', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: true }}, - { keys: ',', type: 'motion', motion: 'repeatLastCharacterSearch', motionArgs: { forward: false }}, - { keys: '\'', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true, linewise: true}}, - { keys: '`', type: 'motion', motion: 'goToMark', motionArgs: {toJumplist: true}}, - { keys: ']`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true } }, - { keys: '[`', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false } }, - { keys: ']\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: true, linewise: true } }, - { keys: '[\'', type: 'motion', motion: 'jumpToMark', motionArgs: { forward: false, linewise: true } }, - // the next two aren't motions but must come before more general motion declarations - { keys: ']p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true, matchIndent: true}}, - { keys: '[p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true, matchIndent: true}}, - { keys: ']', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: true, toJumplist: true}}, - { keys: '[', type: 'motion', motion: 'moveToSymbol', motionArgs: { forward: false, toJumplist: true}}, - { keys: '|', type: 'motion', motion: 'moveToColumn'}, - { keys: 'o', type: 'motion', motion: 'moveToOtherHighlightedEnd', context:'visual'}, - { keys: 'O', type: 'motion', motion: 'moveToOtherHighlightedEnd', motionArgs: {sameLine: true}, context:'visual'}, - // Operators - { keys: 'd', type: 'operator', operator: 'delete' }, - { keys: 'y', type: 'operator', operator: 'yank' }, - { keys: 'c', type: 'operator', operator: 'change' }, - { keys: '>', type: 'operator', operator: 'indent', operatorArgs: { indentRight: true }}, - { keys: '<', type: 'operator', operator: 'indent', operatorArgs: { indentRight: false }}, - { keys: 'g~', type: 'operator', operator: 'changeCase' }, - { keys: 'gu', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, isEdit: true }, - { keys: 'gU', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, isEdit: true }, - { keys: 'n', type: 'motion', motion: 'findNext', motionArgs: { forward: true, toJumplist: true }}, - { keys: 'N', type: 'motion', motion: 'findNext', motionArgs: { forward: false, toJumplist: true }}, - // Operator-Motion dual commands - { keys: 'x', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorMotionArgs: { visualLine: false }}, - { keys: 'X', type: 'operatorMotion', operator: 'delete', motion: 'moveByCharacters', motionArgs: { forward: false }, operatorMotionArgs: { visualLine: true }}, - { keys: 'D', type: 'operatorMotion', operator: 'delete', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, - { keys: 'D', type: 'operator', operator: 'delete', operatorArgs: { linewise: true }, context: 'visual'}, - { keys: 'Y', type: 'operatorMotion', operator: 'yank', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, - { keys: 'Y', type: 'operator', operator: 'yank', operatorArgs: { linewise: true }, context: 'visual'}, - { keys: 'C', type: 'operatorMotion', operator: 'change', motion: 'moveToEol', motionArgs: { inclusive: true }, context: 'normal'}, - { keys: 'C', type: 'operator', operator: 'change', operatorArgs: { linewise: true }, context: 'visual'}, - { keys: '~', type: 'operatorMotion', operator: 'changeCase', motion: 'moveByCharacters', motionArgs: { forward: true }, operatorArgs: { shouldMoveCursor: true }, context: 'normal'}, - { keys: '~', type: 'operator', operator: 'changeCase', context: 'visual'}, - { keys: '', type: 'operatorMotion', operator: 'delete', motion: 'moveByWords', motionArgs: { forward: false, wordEnd: false }, context: 'insert' }, - // Actions - { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: true }}, - { keys: '', type: 'action', action: 'jumpListWalk', actionArgs: { forward: false }}, - { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: true, linewise: true }}, - { keys: '', type: 'action', action: 'scroll', actionArgs: { forward: false, linewise: true }}, - { keys: 'a', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'charAfter' }, context: 'normal' }, - { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'eol' }, context: 'normal' }, - { keys: 'A', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'endOfSelectedArea' }, context: 'visual' }, - { keys: 'i', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'inplace' }, context: 'normal' }, - { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'firstNonBlank'}, context: 'normal' }, - { keys: 'I', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { insertAt: 'startOfSelectedArea' }, context: 'visual' }, - { keys: 'o', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: true }, context: 'normal' }, - { keys: 'O', type: 'action', action: 'newLineAndEnterInsertMode', isEdit: true, interlaceInsertRepeat: true, actionArgs: { after: false }, context: 'normal' }, - { keys: 'v', type: 'action', action: 'toggleVisualMode' }, - { keys: 'V', type: 'action', action: 'toggleVisualMode', actionArgs: { linewise: true }}, - { keys: '', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }}, - { keys: '', type: 'action', action: 'toggleVisualMode', actionArgs: { blockwise: true }}, - { keys: 'gv', type: 'action', action: 'reselectLastSelection' }, - { keys: 'J', type: 'action', action: 'joinLines', isEdit: true }, - { keys: 'p', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: true, isEdit: true }}, - { keys: 'P', type: 'action', action: 'paste', isEdit: true, actionArgs: { after: false, isEdit: true }}, - { keys: 'r', type: 'action', action: 'replace', isEdit: true }, - { keys: '@', type: 'action', action: 'replayMacro' }, - { keys: 'q', type: 'action', action: 'enterMacroRecordMode' }, - // Handle Replace-mode as a special case of insert mode. - { keys: 'R', type: 'action', action: 'enterInsertMode', isEdit: true, actionArgs: { replace: true }}, - { keys: 'u', type: 'action', action: 'undo', context: 'normal' }, - { keys: 'u', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: true}, context: 'visual', isEdit: true }, - { keys: 'U', type: 'operator', operator: 'changeCase', operatorArgs: {toLower: false}, context: 'visual', isEdit: true }, - { keys: '', type: 'action', action: 'redo' }, - { keys: 'm', type: 'action', action: 'setMark' }, - { keys: '"', type: 'action', action: 'setRegister' }, - { keys: 'zz', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }}, - { keys: 'z.', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'center' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: 'zt', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }}, - { keys: 'z', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'top' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: 'z-', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }}, - { keys: 'zb', type: 'action', action: 'scrollToCursor', actionArgs: { position: 'bottom' }, motion: 'moveToFirstNonWhiteSpaceCharacter' }, - { keys: '.', type: 'action', action: 'repeatLastEdit' }, - { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: true, backtrack: false}}, - { keys: '', type: 'action', action: 'incrementNumberToken', isEdit: true, actionArgs: {increase: false, backtrack: false}}, - { keys: '', type: 'action', action: 'indent', actionArgs: { indentRight: true }, context: 'insert' }, - { keys: '', type: 'action', action: 'indent', actionArgs: { indentRight: false }, context: 'insert' }, - // Text object motions - { keys: 'a', type: 'motion', motion: 'textObjectManipulation' }, - { keys: 'i', type: 'motion', motion: 'textObjectManipulation', motionArgs: { textObjectInner: true }}, - // Search - { keys: '/', type: 'search', searchArgs: { forward: true, querySrc: 'prompt', toJumplist: true }}, - { keys: '?', type: 'search', searchArgs: { forward: false, querySrc: 'prompt', toJumplist: true }}, - { keys: '*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, - { keys: '#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', wholeWordOnly: true, toJumplist: true }}, - { keys: 'g*', type: 'search', searchArgs: { forward: true, querySrc: 'wordUnderCursor', toJumplist: true }}, - { keys: 'g#', type: 'search', searchArgs: { forward: false, querySrc: 'wordUnderCursor', toJumplist: true }}, - // Ex command - { keys: ':', type: 'ex' } - ]; - - /** - * Ex commands - * Care must be taken when adding to the default Ex command map. For any - * pair of commands that have a shared prefix, at least one of their - * shortNames must not match the prefix of the other command. - */ - var defaultExCommandMap = [ - { name: 'colorscheme', shortName: 'colo' }, - { name: 'map' }, - { name: 'imap', shortName: 'im' }, - { name: 'nmap', shortName: 'nm' }, - { name: 'vmap', shortName: 'vm' }, - { name: 'unmap' }, - { name: 'write', shortName: 'w' }, - { name: 'undo', shortName: 'u' }, - { name: 'redo', shortName: 'red' }, - { name: 'set', shortName: 'se' }, - { name: 'set', shortName: 'se' }, - { name: 'setlocal', shortName: 'setl' }, - { name: 'setglobal', shortName: 'setg' }, - { name: 'sort', shortName: 'sor' }, - { name: 'substitute', shortName: 's', possiblyAsync: true }, - { name: 'nohlsearch', shortName: 'noh' }, - { name: 'yank', shortName: 'y' }, - { name: 'delmarks', shortName: 'delm' }, - { name: 'registers', shortName: 'reg', excludeFromCommandHistory: true }, - { name: 'global', shortName: 'g' } - ]; - - var Pos = CodeMirror.Pos; - - var Vim = function() { - function enterVimMode(cm) { - cm.setOption('disableInput', true); - cm.setOption('showCursorWhenSelecting', false); - CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); - cm.on('cursorActivity', onCursorActivity); - maybeInitVimState(cm); - CodeMirror.on(cm.getInputField(), 'paste', getOnPasteFn(cm)); - } - - function leaveVimMode(cm) { - cm.setOption('disableInput', false); - cm.off('cursorActivity', onCursorActivity); - CodeMirror.off(cm.getInputField(), 'paste', getOnPasteFn(cm)); - cm.state.vim = null; - } - - function detachVimMap(cm, next) { - if (this == CodeMirror.keyMap.vim) - CodeMirror.rmClass(cm.getWrapperElement(), "cm-fat-cursor"); - - if (!next || next.attach != attachVimMap) - leaveVimMode(cm, false); - } - function attachVimMap(cm, prev) { - if (this == CodeMirror.keyMap.vim) - CodeMirror.addClass(cm.getWrapperElement(), "cm-fat-cursor"); - - if (!prev || prev.attach != attachVimMap) - enterVimMode(cm); - } - - // Deprecated, simply setting the keymap works again. - CodeMirror.defineOption('vimMode', false, function(cm, val, prev) { - if (val && cm.getOption("keyMap") != "vim") - cm.setOption("keyMap", "vim"); - else if (!val && prev != CodeMirror.Init && /^vim/.test(cm.getOption("keyMap"))) - cm.setOption("keyMap", "default"); - }); - - function cmKey(key, cm) { - if (!cm) { return undefined; } - if (this[key]) { return this[key]; } - var vimKey = cmKeyToVimKey(key); - if (!vimKey) { - return false; - } - var cmd = CodeMirror.Vim.findKey(cm, vimKey); - if (typeof cmd == 'function') { - CodeMirror.signal(cm, 'vim-keypress', vimKey); - } - return cmd; - } - - var modifiers = {'Shift': 'S', 'Ctrl': 'C', 'Alt': 'A', 'Cmd': 'D', 'Mod': 'A'}; - var specialKeys = {Enter:'CR',Backspace:'BS',Delete:'Del',Insert:'Ins'}; - function cmKeyToVimKey(key) { - if (key.charAt(0) == '\'') { - // Keypress character binding of format "'a'" - return key.charAt(1); - } - var pieces = key.split(/-(?!$)/); - var lastPiece = pieces[pieces.length - 1]; - if (pieces.length == 1 && pieces[0].length == 1) { - // No-modifier bindings use literal character bindings above. Skip. - return false; - } else if (pieces.length == 2 && pieces[0] == 'Shift' && lastPiece.length == 1) { - // Ignore Shift+char bindings as they should be handled by literal character. - return false; - } - var hasCharacter = false; - for (var i = 0; i < pieces.length; i++) { - var piece = pieces[i]; - if (piece in modifiers) { pieces[i] = modifiers[piece]; } - else { hasCharacter = true; } - if (piece in specialKeys) { pieces[i] = specialKeys[piece]; } - } - if (!hasCharacter) { - // Vim does not support modifier only keys. - return false; - } - // TODO: Current bindings expect the character to be lower case, but - // it looks like vim key notation uses upper case. - if (isUpperCase(lastPiece)) { - pieces[pieces.length - 1] = lastPiece.toLowerCase(); - } - return '<' + pieces.join('-') + '>'; - } - - function getOnPasteFn(cm) { - var vim = cm.state.vim; - if (!vim.onPasteFn) { - vim.onPasteFn = function() { - if (!vim.insertMode) { - cm.setCursor(offsetCursor(cm.getCursor(), 0, 1)); - actions.enterInsertMode(cm, {}, vim); - } - }; - } - return vim.onPasteFn; - } - - var numberRegex = /[\d]/; - var wordCharTest = [CodeMirror.isWordChar, function(ch) { - return ch && !CodeMirror.isWordChar(ch) && !/\s/.test(ch); - }], bigWordCharTest = [function(ch) { - return /\S/.test(ch); - }]; - function makeKeyRange(start, size) { - var keys = []; - for (var i = start; i < start + size; i++) { - keys.push(String.fromCharCode(i)); - } - return keys; - } - var upperCaseAlphabet = makeKeyRange(65, 26); - var lowerCaseAlphabet = makeKeyRange(97, 26); - var numbers = makeKeyRange(48, 10); - var validMarks = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['<', '>']); - var validRegisters = [].concat(upperCaseAlphabet, lowerCaseAlphabet, numbers, ['-', '"', '.', ':', '/']); - - function isLine(cm, line) { - return line >= cm.firstLine() && line <= cm.lastLine(); - } - function isLowerCase(k) { - return (/^[a-z]$/).test(k); - } - function isMatchableSymbol(k) { - return '()[]{}'.indexOf(k) != -1; - } - function isNumber(k) { - return numberRegex.test(k); - } - function isUpperCase(k) { - return (/^[A-Z]$/).test(k); - } - function isWhiteSpaceString(k) { - return (/^\s*$/).test(k); - } - function inArray(val, arr) { - for (var i = 0; i < arr.length; i++) { - if (arr[i] == val) { - return true; - } - } - return false; - } - - var options = {}; - function defineOption(name, defaultValue, type, aliases, callback) { - if (defaultValue === undefined && !callback) { - throw Error('defaultValue is required unless callback is provided'); - } - if (!type) { type = 'string'; } - options[name] = { - type: type, - defaultValue: defaultValue, - callback: callback - }; - if (aliases) { - for (var i = 0; i < aliases.length; i++) { - options[aliases[i]] = options[name]; - } - } - if (defaultValue) { - setOption(name, defaultValue); - } - } - - function setOption(name, value, cm, cfg) { - var option = options[name]; - cfg = cfg || {}; - var scope = cfg.scope; - if (!option) { - throw Error('Unknown option: ' + name); - } - if (option.type == 'boolean') { - if (value && value !== true) { - throw Error('Invalid argument: ' + name + '=' + value); - } else if (value !== false) { - // Boolean options are set to true if value is not defined. - value = true; - } - } - if (option.callback) { - if (scope !== 'local') { - option.callback(value, undefined); - } - if (scope !== 'global' && cm) { - option.callback(value, cm); - } - } else { - if (scope !== 'local') { - option.value = option.type == 'boolean' ? !!value : value; - } - if (scope !== 'global' && cm) { - cm.state.vim.options[name] = {value: value}; - } - } - } - - function getOption(name, cm, cfg) { - var option = options[name]; - cfg = cfg || {}; - var scope = cfg.scope; - if (!option) { - throw Error('Unknown option: ' + name); - } - if (option.callback) { - var local = cm && option.callback(undefined, cm); - if (scope !== 'global' && local !== undefined) { - return local; - } - if (scope !== 'local') { - return option.callback(); - } - return; - } else { - var local = (scope !== 'global') && (cm && cm.state.vim.options[name]); - return (local || (scope !== 'local') && option || {}).value; - } - } - - defineOption('filetype', undefined, 'string', ['ft'], function(name, cm) { - // Option is local. Do nothing for global. - if (cm === undefined) { - return; - } - // The 'filetype' option proxies to the CodeMirror 'mode' option. - if (name === undefined) { - var mode = cm.getOption('mode'); - return mode == 'null' ? '' : mode; - } else { - var mode = name == '' ? 'null' : name; - cm.setOption('mode', mode); - } - }); - - var createCircularJumpList = function() { - var size = 100; - var pointer = -1; - var head = 0; - var tail = 0; - var buffer = new Array(size); - function add(cm, oldCur, newCur) { - var current = pointer % size; - var curMark = buffer[current]; - function useNextSlot(cursor) { - var next = ++pointer % size; - var trashMark = buffer[next]; - if (trashMark) { - trashMark.clear(); - } - buffer[next] = cm.setBookmark(cursor); - } - if (curMark) { - var markPos = curMark.find(); - // avoid recording redundant cursor position - if (markPos && !cursorEqual(markPos, oldCur)) { - useNextSlot(oldCur); - } - } else { - useNextSlot(oldCur); - } - useNextSlot(newCur); - head = pointer; - tail = pointer - size + 1; - if (tail < 0) { - tail = 0; - } - } - function move(cm, offset) { - pointer += offset; - if (pointer > head) { - pointer = head; - } else if (pointer < tail) { - pointer = tail; - } - var mark = buffer[(size + pointer) % size]; - // skip marks that are temporarily removed from text buffer - if (mark && !mark.find()) { - var inc = offset > 0 ? 1 : -1; - var newCur; - var oldCur = cm.getCursor(); - do { - pointer += inc; - mark = buffer[(size + pointer) % size]; - // skip marks that are the same as current position - if (mark && - (newCur = mark.find()) && - !cursorEqual(oldCur, newCur)) { - break; - } - } while (pointer < head && pointer > tail); - } - return mark; - } - return { - cachedCursor: undefined, //used for # and * jumps - add: add, - move: move - }; - }; - - // Returns an object to track the changes associated insert mode. It - // clones the object that is passed in, or creates an empty object one if - // none is provided. - var createInsertModeChanges = function(c) { - if (c) { - // Copy construction - return { - changes: c.changes, - expectCursorActivityForChange: c.expectCursorActivityForChange - }; - } - return { - // Change list - changes: [], - // Set to true on change, false on cursorActivity. - expectCursorActivityForChange: false - }; - }; - - function MacroModeState() { - this.latestRegister = undefined; - this.isPlaying = false; - this.isRecording = false; - this.replaySearchQueries = []; - this.onRecordingDone = undefined; - this.lastInsertModeChanges = createInsertModeChanges(); - } - MacroModeState.prototype = { - exitMacroRecordMode: function() { - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.onRecordingDone) { - macroModeState.onRecordingDone(); // close dialog - } - macroModeState.onRecordingDone = undefined; - macroModeState.isRecording = false; - }, - enterMacroRecordMode: function(cm, registerName) { - var register = - vimGlobalState.registerController.getRegister(registerName); - if (register) { - register.clear(); - this.latestRegister = registerName; - if (cm.openDialog) { - this.onRecordingDone = cm.openDialog( - '(recording)['+registerName+']', null, {bottom:true}); - } - this.isRecording = true; - } - } - }; - - function maybeInitVimState(cm) { - if (!cm.state.vim) { - // Store instance state in the CodeMirror object. - cm.state.vim = { - inputState: new InputState(), - // Vim's input state that triggered the last edit, used to repeat - // motions and operators with '.'. - lastEditInputState: undefined, - // Vim's action command before the last edit, used to repeat actions - // with '.' and insert mode repeat. - lastEditActionCommand: undefined, - // When using jk for navigation, if you move from a longer line to a - // shorter line, the cursor may clip to the end of the shorter line. - // If j is pressed again and cursor goes to the next line, the - // cursor should go back to its horizontal position on the longer - // line if it can. This is to keep track of the horizontal position. - lastHPos: -1, - // Doing the same with screen-position for gj/gk - lastHSPos: -1, - // The last motion command run. Cleared if a non-motion command gets - // executed in between. - lastMotion: null, - marks: {}, - // Mark for rendering fake cursor for visual mode. - fakeCursor: null, - insertMode: false, - // Repeat count for changes made in insert mode, triggered by key - // sequences like 3,i. Only exists when insertMode is true. - insertModeRepeat: undefined, - visualMode: false, - // If we are in visual line mode. No effect if visualMode is false. - visualLine: false, - visualBlock: false, - lastSelection: null, - lastPastedText: null, - sel: {}, - // Buffer-local/window-local values of vim options. - options: {} - }; - } - return cm.state.vim; - } - var vimGlobalState; - function resetVimGlobalState() { - vimGlobalState = { - // The current search query. - searchQuery: null, - // Whether we are searching backwards. - searchIsReversed: false, - // Replace part of the last substituted pattern - lastSubstituteReplacePart: undefined, - jumpList: createCircularJumpList(), - macroModeState: new MacroModeState, - // Recording latest f, t, F or T motion command. - lastCharacterSearch: {increment:0, forward:true, selectedCharacter:''}, - registerController: new RegisterController({}), - // search history buffer - searchHistoryController: new HistoryController({}), - // ex Command history buffer - exCommandHistoryController : new HistoryController({}) - }; - for (var optionName in options) { - var option = options[optionName]; - option.value = option.defaultValue; - } - } - - var lastInsertModeKeyTimer; - var vimApi= { - buildKeyMap: function() { - // TODO: Convert keymap into dictionary format for fast lookup. - }, - // Testing hook, though it might be useful to expose the register - // controller anyways. - getRegisterController: function() { - return vimGlobalState.registerController; - }, - // Testing hook. - resetVimGlobalState_: resetVimGlobalState, - - // Testing hook. - getVimGlobalState_: function() { - return vimGlobalState; - }, - - // Testing hook. - maybeInitVimState_: maybeInitVimState, - - suppressErrorLogging: false, - - InsertModeKey: InsertModeKey, - map: function(lhs, rhs, ctx) { - // Add user defined key bindings. - exCommandDispatcher.map(lhs, rhs, ctx); - }, - unmap: function(lhs, ctx) { - exCommandDispatcher.unmap(lhs, ctx); - }, - // TODO: Expose setOption and getOption as instance methods. Need to decide how to namespace - // them, or somehow make them work with the existing CodeMirror setOption/getOption API. - setOption: setOption, - getOption: getOption, - defineOption: defineOption, - defineEx: function(name, prefix, func){ - if (!prefix) { - prefix = name; - } else if (name.indexOf(prefix) !== 0) { - throw new Error('(Vim.defineEx) "'+prefix+'" is not a prefix of "'+name+'", command not registered'); - } - exCommands[name]=func; - exCommandDispatcher.commandMap_[prefix]={name:name, shortName:prefix, type:'api'}; - }, - handleKey: function (cm, key, origin) { - var command = this.findKey(cm, key, origin); - if (typeof command === 'function') { - return command(); - } - }, - /** - * This is the outermost function called by CodeMirror, after keys have - * been mapped to their Vim equivalents. - * - * Finds a command based on the key (and cached keys if there is a - * multi-key sequence). Returns `undefined` if no key is matched, a noop - * function if a partial match is found (multi-key), and a function to - * execute the bound command if a a key is matched. The function always - * returns true. - */ - findKey: function(cm, key, origin) { - var vim = maybeInitVimState(cm); - function handleMacroRecording() { - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isRecording) { - if (key == 'q') { - macroModeState.exitMacroRecordMode(); - clearInputState(cm); - return true; - } - if (origin != 'mapping') { - logKey(macroModeState, key); - } - } - } - function handleEsc() { - if (key == '') { - // Clear input state and get back to normal mode. - clearInputState(cm); - if (vim.visualMode) { - exitVisualMode(cm); - } else if (vim.insertMode) { - exitInsertMode(cm); - } - return true; - } - } - function doKeyToKey(keys) { - // TODO: prevent infinite recursion. - var match; - while (keys) { - // Pull off one command key, which is either a single character - // or a special sequence wrapped in '<' and '>', e.g. ''. - match = (/<\w+-.+?>|<\w+>|./).exec(keys); - key = match[0]; - keys = keys.substring(match.index + key.length); - CodeMirror.Vim.handleKey(cm, key, 'mapping'); - } - } - - function handleKeyInsertMode() { - if (handleEsc()) { return true; } - var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; - var keysAreChars = key.length == 1; - var match = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); - // Need to check all key substrings in insert mode. - while (keys.length > 1 && match.type != 'full') { - var keys = vim.inputState.keyBuffer = keys.slice(1); - var thisMatch = commandDispatcher.matchCommand(keys, defaultKeymap, vim.inputState, 'insert'); - if (thisMatch.type != 'none') { match = thisMatch; } - } - if (match.type == 'none') { clearInputState(cm); return false; } - else if (match.type == 'partial') { - if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } - lastInsertModeKeyTimer = window.setTimeout( - function() { if (vim.insertMode && vim.inputState.keyBuffer) { clearInputState(cm); } }, - getOption('insertModeEscKeysTimeout')); - return !keysAreChars; - } - - if (lastInsertModeKeyTimer) { window.clearTimeout(lastInsertModeKeyTimer); } - if (keysAreChars) { - var selections = cm.listSelections(); - for (var i = 0; i < selections.length; i++) { - var here = selections[i].head; - cm.replaceRange('', offsetCursor(here, 0, -(keys.length - 1)), here, '+input'); - } - vimGlobalState.macroModeState.lastInsertModeChanges.changes.pop(); - } - clearInputState(cm); - return match.command; - } - - function handleKeyNonInsertMode() { - if (handleMacroRecording() || handleEsc()) { return true; }; - - var keys = vim.inputState.keyBuffer = vim.inputState.keyBuffer + key; - if (/^[1-9]\d*$/.test(keys)) { return true; } - - var keysMatcher = /^(\d*)(.*)$/.exec(keys); - if (!keysMatcher) { clearInputState(cm); return false; } - var context = vim.visualMode ? 'visual' : - 'normal'; - var match = commandDispatcher.matchCommand(keysMatcher[2] || keysMatcher[1], defaultKeymap, vim.inputState, context); - if (match.type == 'none') { clearInputState(cm); return false; } - else if (match.type == 'partial') { return true; } - - vim.inputState.keyBuffer = ''; - var keysMatcher = /^(\d*)(.*)$/.exec(keys); - if (keysMatcher[1] && keysMatcher[1] != '0') { - vim.inputState.pushRepeatDigit(keysMatcher[1]); - } - return match.command; - } - - var command; - if (vim.insertMode) { command = handleKeyInsertMode(); } - else { command = handleKeyNonInsertMode(); } - if (command === false) { - return undefined; - } else if (command === true) { - // TODO: Look into using CodeMirror's multi-key handling. - // Return no-op since we are caching the key. Counts as handled, but - // don't want act on it just yet. - return function() { return true; }; - } else { - return function() { - return cm.operation(function() { - cm.curOp.isVimOp = true; - try { - if (command.type == 'keyToKey') { - doKeyToKey(command.toKeys); - } else { - commandDispatcher.processCommand(cm, vim, command); - } - } catch (e) { - // clear VIM state in case it's in a bad state. - cm.state.vim = undefined; - maybeInitVimState(cm); - if (!CodeMirror.Vim.suppressErrorLogging) { - console['log'](e); - } - throw e; - } - return true; - }); - }; - } - }, - handleEx: function(cm, input) { - exCommandDispatcher.processCommand(cm, input); - }, - - defineMotion: defineMotion, - defineAction: defineAction, - defineOperator: defineOperator, - mapCommand: mapCommand, - _mapCommand: _mapCommand, - - defineRegister: defineRegister, - - exitVisualMode: exitVisualMode, - exitInsertMode: exitInsertMode - }; - - // Represents the current input state. - function InputState() { - this.prefixRepeat = []; - this.motionRepeat = []; - - this.operator = null; - this.operatorArgs = null; - this.motion = null; - this.motionArgs = null; - this.keyBuffer = []; // For matching multi-key commands. - this.registerName = null; // Defaults to the unnamed register. - } - InputState.prototype.pushRepeatDigit = function(n) { - if (!this.operator) { - this.prefixRepeat = this.prefixRepeat.concat(n); - } else { - this.motionRepeat = this.motionRepeat.concat(n); - } - }; - InputState.prototype.getRepeat = function() { - var repeat = 0; - if (this.prefixRepeat.length > 0 || this.motionRepeat.length > 0) { - repeat = 1; - if (this.prefixRepeat.length > 0) { - repeat *= parseInt(this.prefixRepeat.join(''), 10); - } - if (this.motionRepeat.length > 0) { - repeat *= parseInt(this.motionRepeat.join(''), 10); - } - } - return repeat; - }; - - function clearInputState(cm, reason) { - cm.state.vim.inputState = new InputState(); - CodeMirror.signal(cm, 'vim-command-done', reason); - } - - /* - * Register stores information about copy and paste registers. Besides - * text, a register must store whether it is linewise (i.e., when it is - * pasted, should it insert itself into a new line, or should the text be - * inserted at the cursor position.) - */ - function Register(text, linewise, blockwise) { - this.clear(); - this.keyBuffer = [text || '']; - this.insertModeChanges = []; - this.searchQueries = []; - this.linewise = !!linewise; - this.blockwise = !!blockwise; - } - Register.prototype = { - setText: function(text, linewise, blockwise) { - this.keyBuffer = [text || '']; - this.linewise = !!linewise; - this.blockwise = !!blockwise; - }, - pushText: function(text, linewise) { - // if this register has ever been set to linewise, use linewise. - if (linewise) { - if (!this.linewise) { - this.keyBuffer.push('\n'); - } - this.linewise = true; - } - this.keyBuffer.push(text); - }, - pushInsertModeChanges: function(changes) { - this.insertModeChanges.push(createInsertModeChanges(changes)); - }, - pushSearchQuery: function(query) { - this.searchQueries.push(query); - }, - clear: function() { - this.keyBuffer = []; - this.insertModeChanges = []; - this.searchQueries = []; - this.linewise = false; - }, - toString: function() { - return this.keyBuffer.join(''); - } - }; - - /** - * Defines an external register. - * - * The name should be a single character that will be used to reference the register. - * The register should support setText, pushText, clear, and toString(). See Register - * for a reference implementation. - */ - function defineRegister(name, register) { - var registers = vimGlobalState.registerController.registers[name]; - if (!name || name.length != 1) { - throw Error('Register name must be 1 character'); - } - if (registers[name]) { - throw Error('Register already defined ' + name); - } - registers[name] = register; - validRegisters.push(name); - } - - /* - * vim registers allow you to keep many independent copy and paste buffers. - * See http://usevim.com/2012/04/13/registers/ for an introduction. - * - * RegisterController keeps the state of all the registers. An initial - * state may be passed in. The unnamed register '"' will always be - * overridden. - */ - function RegisterController(registers) { - this.registers = registers; - this.unnamedRegister = registers['"'] = new Register(); - registers['.'] = new Register(); - registers[':'] = new Register(); - registers['/'] = new Register(); - } - RegisterController.prototype = { - pushText: function(registerName, operator, text, linewise, blockwise) { - if (linewise && text.charAt(0) == '\n') { - text = text.slice(1) + '\n'; - } - if (linewise && text.charAt(text.length - 1) !== '\n'){ - text += '\n'; - } - // Lowercase and uppercase registers refer to the same register. - // Uppercase just means append. - var register = this.isValidRegister(registerName) ? - this.getRegister(registerName) : null; - // if no register/an invalid register was specified, things go to the - // default registers - if (!register) { - switch (operator) { - case 'yank': - // The 0 register contains the text from the most recent yank. - this.registers['0'] = new Register(text, linewise, blockwise); - break; - case 'delete': - case 'change': - if (text.indexOf('\n') == -1) { - // Delete less than 1 line. Update the small delete register. - this.registers['-'] = new Register(text, linewise); - } else { - // Shift down the contents of the numbered registers and put the - // deleted text into register 1. - this.shiftNumericRegisters_(); - this.registers['1'] = new Register(text, linewise); - } - break; - } - // Make sure the unnamed register is set to what just happened - this.unnamedRegister.setText(text, linewise, blockwise); - return; - } - - // If we've gotten to this point, we've actually specified a register - var append = isUpperCase(registerName); - if (append) { - register.pushText(text, linewise); - } else { - register.setText(text, linewise, blockwise); - } - // The unnamed register always has the same value as the last used - // register. - this.unnamedRegister.setText(register.toString(), linewise); - }, - // Gets the register named @name. If one of @name doesn't already exist, - // create it. If @name is invalid, return the unnamedRegister. - getRegister: function(name) { - if (!this.isValidRegister(name)) { - return this.unnamedRegister; - } - name = name.toLowerCase(); - if (!this.registers[name]) { - this.registers[name] = new Register(); - } - return this.registers[name]; - }, - isValidRegister: function(name) { - return name && inArray(name, validRegisters); - }, - shiftNumericRegisters_: function() { - for (var i = 9; i >= 2; i--) { - this.registers[i] = this.getRegister('' + (i - 1)); - } - } - }; - function HistoryController() { - this.historyBuffer = []; - this.iterator = 0; - this.initialPrefix = null; - } - HistoryController.prototype = { - // the input argument here acts a user entered prefix for a small time - // until we start autocompletion in which case it is the autocompleted. - nextMatch: function (input, up) { - var historyBuffer = this.historyBuffer; - var dir = up ? -1 : 1; - if (this.initialPrefix === null) this.initialPrefix = input; - for (var i = this.iterator + dir; up ? i >= 0 : i < historyBuffer.length; i+= dir) { - var element = historyBuffer[i]; - for (var j = 0; j <= element.length; j++) { - if (this.initialPrefix == element.substring(0, j)) { - this.iterator = i; - return element; - } - } - } - // should return the user input in case we reach the end of buffer. - if (i >= historyBuffer.length) { - this.iterator = historyBuffer.length; - return this.initialPrefix; - } - // return the last autocompleted query or exCommand as it is. - if (i < 0 ) return input; - }, - pushInput: function(input) { - var index = this.historyBuffer.indexOf(input); - if (index > -1) this.historyBuffer.splice(index, 1); - if (input.length) this.historyBuffer.push(input); - }, - reset: function() { - this.initialPrefix = null; - this.iterator = this.historyBuffer.length; - } - }; - var commandDispatcher = { - matchCommand: function(keys, keyMap, inputState, context) { - var matches = commandMatches(keys, keyMap, context, inputState); - if (!matches.full && !matches.partial) { - return {type: 'none'}; - } else if (!matches.full && matches.partial) { - return {type: 'partial'}; - } - - var bestMatch; - for (var i = 0; i < matches.full.length; i++) { - var match = matches.full[i]; - if (!bestMatch) { - bestMatch = match; - } - } - if (bestMatch.keys.slice(-11) == '') { - inputState.selectedCharacter = lastChar(keys); - } - return {type: 'full', command: bestMatch}; - }, - processCommand: function(cm, vim, command) { - vim.inputState.repeatOverride = command.repeatOverride; - switch (command.type) { - case 'motion': - this.processMotion(cm, vim, command); - break; - case 'operator': - this.processOperator(cm, vim, command); - break; - case 'operatorMotion': - this.processOperatorMotion(cm, vim, command); - break; - case 'action': - this.processAction(cm, vim, command); - break; - case 'search': - this.processSearch(cm, vim, command); - break; - case 'ex': - case 'keyToEx': - this.processEx(cm, vim, command); - break; - default: - break; - } - }, - processMotion: function(cm, vim, command) { - vim.inputState.motion = command.motion; - vim.inputState.motionArgs = copyArgs(command.motionArgs); - this.evalInput(cm, vim); - }, - processOperator: function(cm, vim, command) { - var inputState = vim.inputState; - if (inputState.operator) { - if (inputState.operator == command.operator) { - // Typing an operator twice like 'dd' makes the operator operate - // linewise - inputState.motion = 'expandToLine'; - inputState.motionArgs = { linewise: true }; - this.evalInput(cm, vim); - return; - } else { - // 2 different operators in a row doesn't make sense. - clearInputState(cm); - } - } - inputState.operator = command.operator; - inputState.operatorArgs = copyArgs(command.operatorArgs); - if (vim.visualMode) { - // Operating on a selection in visual mode. We don't need a motion. - this.evalInput(cm, vim); - } - }, - processOperatorMotion: function(cm, vim, command) { - var visualMode = vim.visualMode; - var operatorMotionArgs = copyArgs(command.operatorMotionArgs); - if (operatorMotionArgs) { - // Operator motions may have special behavior in visual mode. - if (visualMode && operatorMotionArgs.visualLine) { - vim.visualLine = true; - } - } - this.processOperator(cm, vim, command); - if (!visualMode) { - this.processMotion(cm, vim, command); - } - }, - processAction: function(cm, vim, command) { - var inputState = vim.inputState; - var repeat = inputState.getRepeat(); - var repeatIsExplicit = !!repeat; - var actionArgs = copyArgs(command.actionArgs) || {}; - if (inputState.selectedCharacter) { - actionArgs.selectedCharacter = inputState.selectedCharacter; - } - // Actions may or may not have motions and operators. Do these first. - if (command.operator) { - this.processOperator(cm, vim, command); - } - if (command.motion) { - this.processMotion(cm, vim, command); - } - if (command.motion || command.operator) { - this.evalInput(cm, vim); - } - actionArgs.repeat = repeat || 1; - actionArgs.repeatIsExplicit = repeatIsExplicit; - actionArgs.registerName = inputState.registerName; - clearInputState(cm); - vim.lastMotion = null; - if (command.isEdit) { - this.recordLastEdit(vim, inputState, command); - } - actions[command.action](cm, actionArgs, vim); - }, - processSearch: function(cm, vim, command) { - if (!cm.getSearchCursor) { - // Search depends on SearchCursor. - return; - } - var forward = command.searchArgs.forward; - var wholeWordOnly = command.searchArgs.wholeWordOnly; - getSearchState(cm).setReversed(!forward); - var promptPrefix = (forward) ? '/' : '?'; - var originalQuery = getSearchState(cm).getQuery(); - var originalScrollPos = cm.getScrollInfo(); - function handleQuery(query, ignoreCase, smartCase) { - vimGlobalState.searchHistoryController.pushInput(query); - vimGlobalState.searchHistoryController.reset(); - try { - updateSearchQuery(cm, query, ignoreCase, smartCase); - } catch (e) { - showConfirm(cm, 'Invalid regex: ' + query); - clearInputState(cm); - return; - } - commandDispatcher.processMotion(cm, vim, { - type: 'motion', - motion: 'findNext', - motionArgs: { forward: true, toJumplist: command.searchArgs.toJumplist } - }); - } - function onPromptClose(query) { - cm.scrollTo(originalScrollPos.left, originalScrollPos.top); - handleQuery(query, true /** ignoreCase */, true /** smartCase */); - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isRecording) { - logSearchQuery(macroModeState, query); - } - } - function onPromptKeyUp(e, query, close) { - var keyName = CodeMirror.keyName(e), up; - if (keyName == 'Up' || keyName == 'Down') { - up = keyName == 'Up' ? true : false; - query = vimGlobalState.searchHistoryController.nextMatch(query, up) || ''; - close(query); - } else { - if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift') - vimGlobalState.searchHistoryController.reset(); - } - var parsedQuery; - try { - parsedQuery = updateSearchQuery(cm, query, - true /** ignoreCase */, true /** smartCase */); - } catch (e) { - // Swallow bad regexes for incremental search. - } - if (parsedQuery) { - cm.scrollIntoView(findNext(cm, !forward, parsedQuery), 30); - } else { - clearSearchHighlight(cm); - cm.scrollTo(originalScrollPos.left, originalScrollPos.top); - } - } - function onPromptKeyDown(e, query, close) { - var keyName = CodeMirror.keyName(e); - if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' || - (keyName == 'Backspace' && query == '')) { - vimGlobalState.searchHistoryController.pushInput(query); - vimGlobalState.searchHistoryController.reset(); - updateSearchQuery(cm, originalQuery); - clearSearchHighlight(cm); - cm.scrollTo(originalScrollPos.left, originalScrollPos.top); - CodeMirror.e_stop(e); - clearInputState(cm); - close(); - cm.focus(); - } else if (keyName == 'Ctrl-U') { - // Ctrl-U clears input. - CodeMirror.e_stop(e); - close(''); - } - } - switch (command.searchArgs.querySrc) { - case 'prompt': - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isPlaying) { - var query = macroModeState.replaySearchQueries.shift(); - handleQuery(query, true /** ignoreCase */, false /** smartCase */); - } else { - showPrompt(cm, { - onClose: onPromptClose, - prefix: promptPrefix, - desc: searchPromptDesc, - onKeyUp: onPromptKeyUp, - onKeyDown: onPromptKeyDown - }); - } - break; - case 'wordUnderCursor': - var word = expandWordUnderCursor(cm, false /** inclusive */, - true /** forward */, false /** bigWord */, - true /** noSymbol */); - var isKeyword = true; - if (!word) { - word = expandWordUnderCursor(cm, false /** inclusive */, - true /** forward */, false /** bigWord */, - false /** noSymbol */); - isKeyword = false; - } - if (!word) { - return; - } - var query = cm.getLine(word.start.line).substring(word.start.ch, - word.end.ch); - if (isKeyword && wholeWordOnly) { - query = '\\b' + query + '\\b'; - } else { - query = escapeRegex(query); - } - - // cachedCursor is used to save the old position of the cursor - // when * or # causes vim to seek for the nearest word and shift - // the cursor before entering the motion. - vimGlobalState.jumpList.cachedCursor = cm.getCursor(); - cm.setCursor(word.start); - - handleQuery(query, true /** ignoreCase */, false /** smartCase */); - break; - } - }, - processEx: function(cm, vim, command) { - function onPromptClose(input) { - // Give the prompt some time to close so that if processCommand shows - // an error, the elements don't overlap. - vimGlobalState.exCommandHistoryController.pushInput(input); - vimGlobalState.exCommandHistoryController.reset(); - exCommandDispatcher.processCommand(cm, input); - } - function onPromptKeyDown(e, input, close) { - var keyName = CodeMirror.keyName(e), up; - if (keyName == 'Esc' || keyName == 'Ctrl-C' || keyName == 'Ctrl-[' || - (keyName == 'Backspace' && input == '')) { - vimGlobalState.exCommandHistoryController.pushInput(input); - vimGlobalState.exCommandHistoryController.reset(); - CodeMirror.e_stop(e); - clearInputState(cm); - close(); - cm.focus(); - } - if (keyName == 'Up' || keyName == 'Down') { - up = keyName == 'Up' ? true : false; - input = vimGlobalState.exCommandHistoryController.nextMatch(input, up) || ''; - close(input); - } else if (keyName == 'Ctrl-U') { - // Ctrl-U clears input. - CodeMirror.e_stop(e); - close(''); - } else { - if ( keyName != 'Left' && keyName != 'Right' && keyName != 'Ctrl' && keyName != 'Alt' && keyName != 'Shift') - vimGlobalState.exCommandHistoryController.reset(); - } - } - if (command.type == 'keyToEx') { - // Handle user defined Ex to Ex mappings - exCommandDispatcher.processCommand(cm, command.exArgs.input); - } else { - if (vim.visualMode) { - showPrompt(cm, { onClose: onPromptClose, prefix: ':', value: '\'<,\'>', - onKeyDown: onPromptKeyDown}); - } else { - showPrompt(cm, { onClose: onPromptClose, prefix: ':', - onKeyDown: onPromptKeyDown}); - } - } - }, - evalInput: function(cm, vim) { - // If the motion command is set, execute both the operator and motion. - // Otherwise return. - var inputState = vim.inputState; - var motion = inputState.motion; - var motionArgs = inputState.motionArgs || {}; - var operator = inputState.operator; - var operatorArgs = inputState.operatorArgs || {}; - var registerName = inputState.registerName; - var sel = vim.sel; - // TODO: Make sure cm and vim selections are identical outside visual mode. - var origHead = copyCursor(vim.visualMode ? clipCursorToContent(cm, sel.head): cm.getCursor('head')); - var origAnchor = copyCursor(vim.visualMode ? clipCursorToContent(cm, sel.anchor) : cm.getCursor('anchor')); - var oldHead = copyCursor(origHead); - var oldAnchor = copyCursor(origAnchor); - var newHead, newAnchor; - var repeat; - if (operator) { - this.recordLastEdit(vim, inputState); - } - if (inputState.repeatOverride !== undefined) { - // If repeatOverride is specified, that takes precedence over the - // input state's repeat. Used by Ex mode and can be user defined. - repeat = inputState.repeatOverride; - } else { - repeat = inputState.getRepeat(); - } - if (repeat > 0 && motionArgs.explicitRepeat) { - motionArgs.repeatIsExplicit = true; - } else if (motionArgs.noRepeat || - (!motionArgs.explicitRepeat && repeat === 0)) { - repeat = 1; - motionArgs.repeatIsExplicit = false; - } - if (inputState.selectedCharacter) { - // If there is a character input, stick it in all of the arg arrays. - motionArgs.selectedCharacter = operatorArgs.selectedCharacter = - inputState.selectedCharacter; - } - motionArgs.repeat = repeat; - clearInputState(cm); - if (motion) { - var motionResult = motions[motion](cm, origHead, motionArgs, vim); - vim.lastMotion = motions[motion]; - if (!motionResult) { - return; - } - if (motionArgs.toJumplist) { - var jumpList = vimGlobalState.jumpList; - // if the current motion is # or *, use cachedCursor - var cachedCursor = jumpList.cachedCursor; - if (cachedCursor) { - recordJumpPosition(cm, cachedCursor, motionResult); - delete jumpList.cachedCursor; - } else { - recordJumpPosition(cm, origHead, motionResult); - } - } - if (motionResult instanceof Array) { - newAnchor = motionResult[0]; - newHead = motionResult[1]; - } else { - newHead = motionResult; - } - // TODO: Handle null returns from motion commands better. - if (!newHead) { - newHead = copyCursor(origHead); - } - if (vim.visualMode) { - if (!(vim.visualBlock && newHead.ch === Infinity)) { - newHead = clipCursorToContent(cm, newHead, vim.visualBlock); - } - if (newAnchor) { - newAnchor = clipCursorToContent(cm, newAnchor, true); - } - newAnchor = newAnchor || oldAnchor; - sel.anchor = newAnchor; - sel.head = newHead; - updateCmSelection(cm); - updateMark(cm, vim, '<', - cursorIsBefore(newAnchor, newHead) ? newAnchor - : newHead); - updateMark(cm, vim, '>', - cursorIsBefore(newAnchor, newHead) ? newHead - : newAnchor); - } else if (!operator) { - newHead = clipCursorToContent(cm, newHead); - cm.setCursor(newHead.line, newHead.ch); - } - } - if (operator) { - if (operatorArgs.lastSel) { - // Replaying a visual mode operation - newAnchor = oldAnchor; - var lastSel = operatorArgs.lastSel; - var lineOffset = Math.abs(lastSel.head.line - lastSel.anchor.line); - var chOffset = Math.abs(lastSel.head.ch - lastSel.anchor.ch); - if (lastSel.visualLine) { - // Linewise Visual mode: The same number of lines. - newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch); - } else if (lastSel.visualBlock) { - // Blockwise Visual mode: The same number of lines and columns. - newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch + chOffset); - } else if (lastSel.head.line == lastSel.anchor.line) { - // Normal Visual mode within one line: The same number of characters. - newHead = Pos(oldAnchor.line, oldAnchor.ch + chOffset); - } else { - // Normal Visual mode with several lines: The same number of lines, in the - // last line the same number of characters as in the last line the last time. - newHead = Pos(oldAnchor.line + lineOffset, oldAnchor.ch); - } - vim.visualMode = true; - vim.visualLine = lastSel.visualLine; - vim.visualBlock = lastSel.visualBlock; - sel = vim.sel = { - anchor: newAnchor, - head: newHead - }; - updateCmSelection(cm); - } else if (vim.visualMode) { - operatorArgs.lastSel = { - anchor: copyCursor(sel.anchor), - head: copyCursor(sel.head), - visualBlock: vim.visualBlock, - visualLine: vim.visualLine - }; - } - var curStart, curEnd, linewise, mode; - var cmSel; - if (vim.visualMode) { - // Init visual op - curStart = cursorMin(sel.head, sel.anchor); - curEnd = cursorMax(sel.head, sel.anchor); - linewise = vim.visualLine || operatorArgs.linewise; - mode = vim.visualBlock ? 'block' : - linewise ? 'line' : - 'char'; - cmSel = makeCmSelection(cm, { - anchor: curStart, - head: curEnd - }, mode); - if (linewise) { - var ranges = cmSel.ranges; - if (mode == 'block') { - // Linewise operators in visual block mode extend to end of line - for (var i = 0; i < ranges.length; i++) { - ranges[i].head.ch = lineLength(cm, ranges[i].head.line); - } - } else if (mode == 'line') { - ranges[0].head = Pos(ranges[0].head.line + 1, 0); - } - } - } else { - // Init motion op - curStart = copyCursor(newAnchor || oldAnchor); - curEnd = copyCursor(newHead || oldHead); - if (cursorIsBefore(curEnd, curStart)) { - var tmp = curStart; - curStart = curEnd; - curEnd = tmp; - } - linewise = motionArgs.linewise || operatorArgs.linewise; - if (linewise) { - // Expand selection to entire line. - expandSelectionToLine(cm, curStart, curEnd); - } else if (motionArgs.forward) { - // Clip to trailing newlines only if the motion goes forward. - clipToLine(cm, curStart, curEnd); - } - mode = 'char'; - var exclusive = !motionArgs.inclusive || linewise; - cmSel = makeCmSelection(cm, { - anchor: curStart, - head: curEnd - }, mode, exclusive); - } - cm.setSelections(cmSel.ranges, cmSel.primary); - vim.lastMotion = null; - operatorArgs.repeat = repeat; // For indent in visual mode. - operatorArgs.registerName = registerName; - // Keep track of linewise as it affects how paste and change behave. - operatorArgs.linewise = linewise; - var operatorMoveTo = operators[operator]( - cm, operatorArgs, cmSel.ranges, oldAnchor, newHead); - if (vim.visualMode) { - exitVisualMode(cm, operatorMoveTo != null); - } - if (operatorMoveTo) { - cm.setCursor(operatorMoveTo); - } - } - }, - recordLastEdit: function(vim, inputState, actionCommand) { - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isPlaying) { return; } - vim.lastEditInputState = inputState; - vim.lastEditActionCommand = actionCommand; - macroModeState.lastInsertModeChanges.changes = []; - macroModeState.lastInsertModeChanges.expectCursorActivityForChange = false; - } - }; - - /** - * typedef {Object{line:number,ch:number}} Cursor An object containing the - * position of the cursor. - */ - // All of the functions below return Cursor objects. - var motions = { - moveToTopLine: function(cm, _head, motionArgs) { - var line = getUserVisibleLines(cm).top + motionArgs.repeat -1; - return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); - }, - moveToMiddleLine: function(cm) { - var range = getUserVisibleLines(cm); - var line = Math.floor((range.top + range.bottom) * 0.5); - return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); - }, - moveToBottomLine: function(cm, _head, motionArgs) { - var line = getUserVisibleLines(cm).bottom - motionArgs.repeat +1; - return Pos(line, findFirstNonWhiteSpaceCharacter(cm.getLine(line))); - }, - expandToLine: function(_cm, head, motionArgs) { - // Expands forward to end of line, and then to next line if repeat is - // >1. Does not handle backward motion! - var cur = head; - return Pos(cur.line + motionArgs.repeat - 1, Infinity); - }, - findNext: function(cm, _head, motionArgs) { - var state = getSearchState(cm); - var query = state.getQuery(); - if (!query) { - return; - } - var prev = !motionArgs.forward; - // If search is initiated with ? instead of /, negate direction. - prev = (state.isReversed()) ? !prev : prev; - highlightSearchMatches(cm, query); - return findNext(cm, prev/** prev */, query, motionArgs.repeat); - }, - goToMark: function(cm, _head, motionArgs, vim) { - var mark = vim.marks[motionArgs.selectedCharacter]; - if (mark) { - var pos = mark.find(); - return motionArgs.linewise ? { line: pos.line, ch: findFirstNonWhiteSpaceCharacter(cm.getLine(pos.line)) } : pos; - } - return null; - }, - moveToOtherHighlightedEnd: function(cm, _head, motionArgs, vim) { - if (vim.visualBlock && motionArgs.sameLine) { - var sel = vim.sel; - return [ - clipCursorToContent(cm, Pos(sel.anchor.line, sel.head.ch)), - clipCursorToContent(cm, Pos(sel.head.line, sel.anchor.ch)) - ]; - } else { - return ([vim.sel.head, vim.sel.anchor]); - } - }, - jumpToMark: function(cm, head, motionArgs, vim) { - var best = head; - for (var i = 0; i < motionArgs.repeat; i++) { - var cursor = best; - for (var key in vim.marks) { - if (!isLowerCase(key)) { - continue; - } - var mark = vim.marks[key].find(); - var isWrongDirection = (motionArgs.forward) ? - cursorIsBefore(mark, cursor) : cursorIsBefore(cursor, mark); - - if (isWrongDirection) { - continue; - } - if (motionArgs.linewise && (mark.line == cursor.line)) { - continue; - } - - var equal = cursorEqual(cursor, best); - var between = (motionArgs.forward) ? - cursorIsBetween(cursor, mark, best) : - cursorIsBetween(best, mark, cursor); - - if (equal || between) { - best = mark; - } - } - } - - if (motionArgs.linewise) { - // Vim places the cursor on the first non-whitespace character of - // the line if there is one, else it places the cursor at the end - // of the line, regardless of whether a mark was found. - best = Pos(best.line, findFirstNonWhiteSpaceCharacter(cm.getLine(best.line))); - } - return best; - }, - moveByCharacters: function(_cm, head, motionArgs) { - var cur = head; - var repeat = motionArgs.repeat; - var ch = motionArgs.forward ? cur.ch + repeat : cur.ch - repeat; - return Pos(cur.line, ch); - }, - moveByLines: function(cm, head, motionArgs, vim) { - var cur = head; - var endCh = cur.ch; - // Depending what our last motion was, we may want to do different - // things. If our last motion was moving vertically, we want to - // preserve the HPos from our last horizontal move. If our last motion - // was going to the end of a line, moving vertically we should go to - // the end of the line, etc. - switch (vim.lastMotion) { - case this.moveByLines: - case this.moveByDisplayLines: - case this.moveByScroll: - case this.moveToColumn: - case this.moveToEol: - endCh = vim.lastHPos; - break; - default: - vim.lastHPos = endCh; - } - var repeat = motionArgs.repeat+(motionArgs.repeatOffset||0); - var line = motionArgs.forward ? cur.line + repeat : cur.line - repeat; - var first = cm.firstLine(); - var last = cm.lastLine(); - // Vim go to line begin or line end when cursor at first/last line and - // move to previous/next line is triggered. - if (line < first && cur.line == first){ - return this.moveToStartOfLine(cm, head, motionArgs, vim); - }else if (line > last && cur.line == last){ - return this.moveToEol(cm, head, motionArgs, vim); - } - if (motionArgs.toFirstChar){ - endCh=findFirstNonWhiteSpaceCharacter(cm.getLine(line)); - vim.lastHPos = endCh; - } - vim.lastHSPos = cm.charCoords(Pos(line, endCh),'div').left; - return Pos(line, endCh); - }, - moveByDisplayLines: function(cm, head, motionArgs, vim) { - var cur = head; - switch (vim.lastMotion) { - case this.moveByDisplayLines: - case this.moveByScroll: - case this.moveByLines: - case this.moveToColumn: - case this.moveToEol: - break; - default: - vim.lastHSPos = cm.charCoords(cur,'div').left; - } - var repeat = motionArgs.repeat; - var res=cm.findPosV(cur,(motionArgs.forward ? repeat : -repeat),'line',vim.lastHSPos); - if (res.hitSide) { - if (motionArgs.forward) { - var lastCharCoords = cm.charCoords(res, 'div'); - var goalCoords = { top: lastCharCoords.top + 8, left: vim.lastHSPos }; - var res = cm.coordsChar(goalCoords, 'div'); - } else { - var resCoords = cm.charCoords(Pos(cm.firstLine(), 0), 'div'); - resCoords.left = vim.lastHSPos; - res = cm.coordsChar(resCoords, 'div'); - } - } - vim.lastHPos = res.ch; - return res; - }, - moveByPage: function(cm, head, motionArgs) { - // CodeMirror only exposes functions that move the cursor page down, so - // doing this bad hack to move the cursor and move it back. evalInput - // will move the cursor to where it should be in the end. - var curStart = head; - var repeat = motionArgs.repeat; - return cm.findPosV(curStart, (motionArgs.forward ? repeat : -repeat), 'page'); - }, - moveByParagraph: function(cm, head, motionArgs) { - var dir = motionArgs.forward ? 1 : -1; - return findParagraph(cm, head, motionArgs.repeat, dir); - }, - moveByScroll: function(cm, head, motionArgs, vim) { - var scrollbox = cm.getScrollInfo(); - var curEnd = null; - var repeat = motionArgs.repeat; - if (!repeat) { - repeat = scrollbox.clientHeight / (2 * cm.defaultTextHeight()); - } - var orig = cm.charCoords(head, 'local'); - motionArgs.repeat = repeat; - var curEnd = motions.moveByDisplayLines(cm, head, motionArgs, vim); - if (!curEnd) { - return null; - } - var dest = cm.charCoords(curEnd, 'local'); - cm.scrollTo(null, scrollbox.top + dest.top - orig.top); - return curEnd; - }, - moveByWords: function(cm, head, motionArgs) { - return moveToWord(cm, head, motionArgs.repeat, !!motionArgs.forward, - !!motionArgs.wordEnd, !!motionArgs.bigWord); - }, - moveTillCharacter: function(cm, _head, motionArgs) { - var repeat = motionArgs.repeat; - var curEnd = moveToCharacter(cm, repeat, motionArgs.forward, - motionArgs.selectedCharacter); - var increment = motionArgs.forward ? -1 : 1; - recordLastCharacterSearch(increment, motionArgs); - if (!curEnd) return null; - curEnd.ch += increment; - return curEnd; - }, - moveToCharacter: function(cm, head, motionArgs) { - var repeat = motionArgs.repeat; - recordLastCharacterSearch(0, motionArgs); - return moveToCharacter(cm, repeat, motionArgs.forward, - motionArgs.selectedCharacter) || head; - }, - moveToSymbol: function(cm, head, motionArgs) { - var repeat = motionArgs.repeat; - return findSymbol(cm, repeat, motionArgs.forward, - motionArgs.selectedCharacter) || head; - }, - moveToColumn: function(cm, head, motionArgs, vim) { - var repeat = motionArgs.repeat; - // repeat is equivalent to which column we want to move to! - vim.lastHPos = repeat - 1; - vim.lastHSPos = cm.charCoords(head,'div').left; - return moveToColumn(cm, repeat); - }, - moveToEol: function(cm, head, motionArgs, vim) { - var cur = head; - vim.lastHPos = Infinity; - var retval= Pos(cur.line + motionArgs.repeat - 1, Infinity); - var end=cm.clipPos(retval); - end.ch--; - vim.lastHSPos = cm.charCoords(end,'div').left; - return retval; - }, - moveToFirstNonWhiteSpaceCharacter: function(cm, head) { - // Go to the start of the line where the text begins, or the end for - // whitespace-only lines - var cursor = head; - return Pos(cursor.line, - findFirstNonWhiteSpaceCharacter(cm.getLine(cursor.line))); - }, - moveToMatchedSymbol: function(cm, head) { - var cursor = head; - var line = cursor.line; - var ch = cursor.ch; - var lineText = cm.getLine(line); - var symbol; - do { - symbol = lineText.charAt(ch++); - if (symbol && isMatchableSymbol(symbol)) { - var style = cm.getTokenTypeAt(Pos(line, ch)); - if (style !== "string" && style !== "comment") { - break; - } - } - } while (symbol); - if (symbol) { - var matched = cm.findMatchingBracket(Pos(line, ch)); - return matched.to; - } else { - return cursor; - } - }, - moveToStartOfLine: function(_cm, head) { - return Pos(head.line, 0); - }, - moveToLineOrEdgeOfDocument: function(cm, _head, motionArgs) { - var lineNum = motionArgs.forward ? cm.lastLine() : cm.firstLine(); - if (motionArgs.repeatIsExplicit) { - lineNum = motionArgs.repeat - cm.getOption('firstLineNumber'); - } - return Pos(lineNum, - findFirstNonWhiteSpaceCharacter(cm.getLine(lineNum))); - }, - textObjectManipulation: function(cm, head, motionArgs, vim) { - // TODO: lots of possible exceptions that can be thrown here. Try da( - // outside of a () block. - - // TODO: adding <> >< to this map doesn't work, presumably because - // they're operators - var mirroredPairs = {'(': ')', ')': '(', - '{': '}', '}': '{', - '[': ']', ']': '['}; - var selfPaired = {'\'': true, '"': true}; - - var character = motionArgs.selectedCharacter; - // 'b' refers to '()' block. - // 'B' refers to '{}' block. - if (character == 'b') { - character = '('; - } else if (character == 'B') { - character = '{'; - } - - // Inclusive is the difference between a and i - // TODO: Instead of using the additional text object map to perform text - // object operations, merge the map into the defaultKeyMap and use - // motionArgs to define behavior. Define separate entries for 'aw', - // 'iw', 'a[', 'i[', etc. - var inclusive = !motionArgs.textObjectInner; - - var tmp; - if (mirroredPairs[character]) { - tmp = selectCompanionObject(cm, head, character, inclusive); - } else if (selfPaired[character]) { - tmp = findBeginningAndEnd(cm, head, character, inclusive); - } else if (character === 'W') { - tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, - true /** bigWord */); - } else if (character === 'w') { - tmp = expandWordUnderCursor(cm, inclusive, true /** forward */, - false /** bigWord */); - } else if (character === 'p') { - tmp = findParagraph(cm, head, motionArgs.repeat, 0, inclusive); - motionArgs.linewise = true; - if (vim.visualMode) { - if (!vim.visualLine) { vim.visualLine = true; } - } else { - var operatorArgs = vim.inputState.operatorArgs; - if (operatorArgs) { operatorArgs.linewise = true; } - tmp.end.line--; - } - } else { - // No text object defined for this, don't move. - return null; - } - - if (!cm.state.vim.visualMode) { - return [tmp.start, tmp.end]; - } else { - return expandSelection(cm, tmp.start, tmp.end); - } - }, - - repeatLastCharacterSearch: function(cm, head, motionArgs) { - var lastSearch = vimGlobalState.lastCharacterSearch; - var repeat = motionArgs.repeat; - var forward = motionArgs.forward === lastSearch.forward; - var increment = (lastSearch.increment ? 1 : 0) * (forward ? -1 : 1); - cm.moveH(-increment, 'char'); - motionArgs.inclusive = forward ? true : false; - var curEnd = moveToCharacter(cm, repeat, forward, lastSearch.selectedCharacter); - if (!curEnd) { - cm.moveH(increment, 'char'); - return head; - } - curEnd.ch += increment; - return curEnd; - } - }; - - function defineMotion(name, fn) { - motions[name] = fn; - } - - function fillArray(val, times) { - var arr = []; - for (var i = 0; i < times; i++) { - arr.push(val); - } - return arr; - } - /** - * An operator acts on a text selection. It receives the list of selections - * as input. The corresponding CodeMirror selection is guaranteed to - * match the input selection. - */ - var operators = { - change: function(cm, args, ranges) { - var finalHead, text; - var vim = cm.state.vim; - vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock = vim.visualBlock; - if (!vim.visualMode) { - var anchor = ranges[0].anchor, - head = ranges[0].head; - text = cm.getRange(anchor, head); - var lastState = vim.lastEditInputState || {}; - if (lastState.motion == "moveByWords" && !isWhiteSpaceString(text)) { - // Exclude trailing whitespace if the range is not all whitespace. - var match = (/\s+$/).exec(text); - if (match && lastState.motionArgs && lastState.motionArgs.forward) { - head = offsetCursor(head, 0, - match[0].length); - text = text.slice(0, - match[0].length); - } - } - var prevLineEnd = new Pos(anchor.line - 1, Number.MAX_VALUE); - var wasLastLine = cm.firstLine() == cm.lastLine(); - if (head.line > cm.lastLine() && args.linewise && !wasLastLine) { - cm.replaceRange('', prevLineEnd, head); - } else { - cm.replaceRange('', anchor, head); - } - if (args.linewise) { - // Push the next line back down, if there is a next line. - if (!wasLastLine) { - cm.setCursor(prevLineEnd); - CodeMirror.commands.newlineAndIndent(cm); - } - // make sure cursor ends up at the end of the line. - anchor.ch = Number.MAX_VALUE; - } - finalHead = anchor; - } else { - text = cm.getSelection(); - var replacement = fillArray('', ranges.length); - cm.replaceSelections(replacement); - finalHead = cursorMin(ranges[0].head, ranges[0].anchor); - } - vimGlobalState.registerController.pushText( - args.registerName, 'change', text, - args.linewise, ranges.length > 1); - actions.enterInsertMode(cm, {head: finalHead}, cm.state.vim); - }, - // delete is a javascript keyword. - 'delete': function(cm, args, ranges) { - var finalHead, text; - var vim = cm.state.vim; - if (!vim.visualBlock) { - var anchor = ranges[0].anchor, - head = ranges[0].head; - if (args.linewise && - head.line != cm.firstLine() && - anchor.line == cm.lastLine() && - anchor.line == head.line - 1) { - // Special case for dd on last line (and first line). - if (anchor.line == cm.firstLine()) { - anchor.ch = 0; - } else { - anchor = Pos(anchor.line - 1, lineLength(cm, anchor.line - 1)); - } - } - text = cm.getRange(anchor, head); - cm.replaceRange('', anchor, head); - finalHead = anchor; - if (args.linewise) { - finalHead = motions.moveToFirstNonWhiteSpaceCharacter(cm, anchor); - } - } else { - text = cm.getSelection(); - var replacement = fillArray('', ranges.length); - cm.replaceSelections(replacement); - finalHead = ranges[0].anchor; - } - vimGlobalState.registerController.pushText( - args.registerName, 'delete', text, - args.linewise, vim.visualBlock); - return clipCursorToContent(cm, finalHead); - }, - indent: function(cm, args, ranges) { - var vim = cm.state.vim; - var startLine = ranges[0].anchor.line; - var endLine = vim.visualBlock ? - ranges[ranges.length - 1].anchor.line : - ranges[0].head.line; - // In visual mode, n> shifts the selection right n times, instead of - // shifting n lines right once. - var repeat = (vim.visualMode) ? args.repeat : 1; - if (args.linewise) { - // The only way to delete a newline is to delete until the start of - // the next line, so in linewise mode evalInput will include the next - // line. We don't want this in indent, so we go back a line. - endLine--; - } - for (var i = startLine; i <= endLine; i++) { - for (var j = 0; j < repeat; j++) { - cm.indentLine(i, args.indentRight); - } - } - return motions.moveToFirstNonWhiteSpaceCharacter(cm, ranges[0].anchor); - }, - changeCase: function(cm, args, ranges, oldAnchor, newHead) { - var selections = cm.getSelections(); - var swapped = []; - var toLower = args.toLower; - for (var j = 0; j < selections.length; j++) { - var toSwap = selections[j]; - var text = ''; - if (toLower === true) { - text = toSwap.toLowerCase(); - } else if (toLower === false) { - text = toSwap.toUpperCase(); - } else { - for (var i = 0; i < toSwap.length; i++) { - var character = toSwap.charAt(i); - text += isUpperCase(character) ? character.toLowerCase() : - character.toUpperCase(); - } - } - swapped.push(text); - } - cm.replaceSelections(swapped); - if (args.shouldMoveCursor){ - return newHead; - } else if (!cm.state.vim.visualMode && args.linewise && ranges[0].anchor.line + 1 == ranges[0].head.line) { - return motions.moveToFirstNonWhiteSpaceCharacter(cm, oldAnchor); - } else if (args.linewise){ - return oldAnchor; - } else { - return cursorMin(ranges[0].anchor, ranges[0].head); - } - }, - yank: function(cm, args, ranges, oldAnchor) { - var vim = cm.state.vim; - var text = cm.getSelection(); - var endPos = vim.visualMode - ? cursorMin(vim.sel.anchor, vim.sel.head, ranges[0].head, ranges[0].anchor) - : oldAnchor; - vimGlobalState.registerController.pushText( - args.registerName, 'yank', - text, args.linewise, vim.visualBlock); - return endPos; - } - }; - - function defineOperator(name, fn) { - operators[name] = fn; - } - - var actions = { - jumpListWalk: function(cm, actionArgs, vim) { - if (vim.visualMode) { - return; - } - var repeat = actionArgs.repeat; - var forward = actionArgs.forward; - var jumpList = vimGlobalState.jumpList; - - var mark = jumpList.move(cm, forward ? repeat : -repeat); - var markPos = mark ? mark.find() : undefined; - markPos = markPos ? markPos : cm.getCursor(); - cm.setCursor(markPos); - }, - scroll: function(cm, actionArgs, vim) { - if (vim.visualMode) { - return; - } - var repeat = actionArgs.repeat || 1; - var lineHeight = cm.defaultTextHeight(); - var top = cm.getScrollInfo().top; - var delta = lineHeight * repeat; - var newPos = actionArgs.forward ? top + delta : top - delta; - var cursor = copyCursor(cm.getCursor()); - var cursorCoords = cm.charCoords(cursor, 'local'); - if (actionArgs.forward) { - if (newPos > cursorCoords.top) { - cursor.line += (newPos - cursorCoords.top) / lineHeight; - cursor.line = Math.ceil(cursor.line); - cm.setCursor(cursor); - cursorCoords = cm.charCoords(cursor, 'local'); - cm.scrollTo(null, cursorCoords.top); - } else { - // Cursor stays within bounds. Just reposition the scroll window. - cm.scrollTo(null, newPos); - } - } else { - var newBottom = newPos + cm.getScrollInfo().clientHeight; - if (newBottom < cursorCoords.bottom) { - cursor.line -= (cursorCoords.bottom - newBottom) / lineHeight; - cursor.line = Math.floor(cursor.line); - cm.setCursor(cursor); - cursorCoords = cm.charCoords(cursor, 'local'); - cm.scrollTo( - null, cursorCoords.bottom - cm.getScrollInfo().clientHeight); - } else { - // Cursor stays within bounds. Just reposition the scroll window. - cm.scrollTo(null, newPos); - } - } - }, - scrollToCursor: function(cm, actionArgs) { - var lineNum = cm.getCursor().line; - var charCoords = cm.charCoords(Pos(lineNum, 0), 'local'); - var height = cm.getScrollInfo().clientHeight; - var y = charCoords.top; - var lineHeight = charCoords.bottom - y; - switch (actionArgs.position) { - case 'center': y = y - (height / 2) + lineHeight; - break; - case 'bottom': y = y - height + lineHeight; - break; - } - cm.scrollTo(null, y); - }, - replayMacro: function(cm, actionArgs, vim) { - var registerName = actionArgs.selectedCharacter; - var repeat = actionArgs.repeat; - var macroModeState = vimGlobalState.macroModeState; - if (registerName == '@') { - registerName = macroModeState.latestRegister; - } - while(repeat--){ - executeMacroRegister(cm, vim, macroModeState, registerName); - } - }, - enterMacroRecordMode: function(cm, actionArgs) { - var macroModeState = vimGlobalState.macroModeState; - var registerName = actionArgs.selectedCharacter; - macroModeState.enterMacroRecordMode(cm, registerName); - }, - toggleOverwrite: function(cm) { - if (!cm.state.overwrite) { - cm.toggleOverwrite(true); - cm.setOption('keyMap', 'vim-replace'); - CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"}); - } else { - cm.toggleOverwrite(false); - cm.setOption('keyMap', 'vim-insert'); - CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"}); - } - }, - enterInsertMode: function(cm, actionArgs, vim) { - if (cm.getOption('readOnly')) { return; } - vim.insertMode = true; - vim.insertModeRepeat = actionArgs && actionArgs.repeat || 1; - var insertAt = (actionArgs) ? actionArgs.insertAt : null; - var sel = vim.sel; - var head = actionArgs.head || cm.getCursor('head'); - var height = cm.listSelections().length; - if (insertAt == 'eol') { - head = Pos(head.line, lineLength(cm, head.line)); - } else if (insertAt == 'charAfter') { - head = offsetCursor(head, 0, 1); - } else if (insertAt == 'firstNonBlank') { - head = motions.moveToFirstNonWhiteSpaceCharacter(cm, head); - } else if (insertAt == 'startOfSelectedArea') { - if (!vim.visualBlock) { - if (sel.head.line < sel.anchor.line) { - head = sel.head; - } else { - head = Pos(sel.anchor.line, 0); - } - } else { - head = Pos( - Math.min(sel.head.line, sel.anchor.line), - Math.min(sel.head.ch, sel.anchor.ch)); - height = Math.abs(sel.head.line - sel.anchor.line) + 1; - } - } else if (insertAt == 'endOfSelectedArea') { - if (!vim.visualBlock) { - if (sel.head.line >= sel.anchor.line) { - head = offsetCursor(sel.head, 0, 1); - } else { - head = Pos(sel.anchor.line, 0); - } - } else { - head = Pos( - Math.min(sel.head.line, sel.anchor.line), - Math.max(sel.head.ch + 1, sel.anchor.ch)); - height = Math.abs(sel.head.line - sel.anchor.line) + 1; - } - } else if (insertAt == 'inplace') { - if (vim.visualMode){ - return; - } - } - cm.setOption('disableInput', false); - if (actionArgs && actionArgs.replace) { - // Handle Replace-mode as a special case of insert mode. - cm.toggleOverwrite(true); - cm.setOption('keyMap', 'vim-replace'); - CodeMirror.signal(cm, "vim-mode-change", {mode: "replace"}); - } else { - cm.toggleOverwrite(false); - cm.setOption('keyMap', 'vim-insert'); - CodeMirror.signal(cm, "vim-mode-change", {mode: "insert"}); - } - if (!vimGlobalState.macroModeState.isPlaying) { - // Only record if not replaying. - cm.on('change', onChange); - CodeMirror.on(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown); - } - if (vim.visualMode) { - exitVisualMode(cm); - } - selectForInsert(cm, head, height); - }, - toggleVisualMode: function(cm, actionArgs, vim) { - var repeat = actionArgs.repeat; - var anchor = cm.getCursor(); - var head; - // TODO: The repeat should actually select number of characters/lines - // equal to the repeat times the size of the previous visual - // operation. - if (!vim.visualMode) { - // Entering visual mode - vim.visualMode = true; - vim.visualLine = !!actionArgs.linewise; - vim.visualBlock = !!actionArgs.blockwise; - head = clipCursorToContent( - cm, Pos(anchor.line, anchor.ch + repeat - 1), - true /** includeLineBreak */); - vim.sel = { - anchor: anchor, - head: head - }; - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""}); - updateCmSelection(cm); - updateMark(cm, vim, '<', cursorMin(anchor, head)); - updateMark(cm, vim, '>', cursorMax(anchor, head)); - } else if (vim.visualLine ^ actionArgs.linewise || - vim.visualBlock ^ actionArgs.blockwise) { - // Toggling between modes - vim.visualLine = !!actionArgs.linewise; - vim.visualBlock = !!actionArgs.blockwise; - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual", subMode: vim.visualLine ? "linewise" : vim.visualBlock ? "blockwise" : ""}); - updateCmSelection(cm); - } else { - exitVisualMode(cm); - } - }, - reselectLastSelection: function(cm, _actionArgs, vim) { - var lastSelection = vim.lastSelection; - if (vim.visualMode) { - updateLastSelection(cm, vim); - } - if (lastSelection) { - var anchor = lastSelection.anchorMark.find(); - var head = lastSelection.headMark.find(); - if (!anchor || !head) { - // If the marks have been destroyed due to edits, do nothing. - return; - } - vim.sel = { - anchor: anchor, - head: head - }; - vim.visualMode = true; - vim.visualLine = lastSelection.visualLine; - vim.visualBlock = lastSelection.visualBlock; - updateCmSelection(cm); - updateMark(cm, vim, '<', cursorMin(anchor, head)); - updateMark(cm, vim, '>', cursorMax(anchor, head)); - CodeMirror.signal(cm, 'vim-mode-change', { - mode: 'visual', - subMode: vim.visualLine ? 'linewise' : - vim.visualBlock ? 'blockwise' : ''}); - } - }, - joinLines: function(cm, actionArgs, vim) { - var curStart, curEnd; - if (vim.visualMode) { - curStart = cm.getCursor('anchor'); - curEnd = cm.getCursor('head'); - if (cursorIsBefore(curEnd, curStart)) { - var tmp = curEnd; - curEnd = curStart; - curStart = tmp; - } - curEnd.ch = lineLength(cm, curEnd.line) - 1; - } else { - // Repeat is the number of lines to join. Minimum 2 lines. - var repeat = Math.max(actionArgs.repeat, 2); - curStart = cm.getCursor(); - curEnd = clipCursorToContent(cm, Pos(curStart.line + repeat - 1, - Infinity)); - } - var finalCh = 0; - for (var i = curStart.line; i < curEnd.line; i++) { - finalCh = lineLength(cm, curStart.line); - var tmp = Pos(curStart.line + 1, - lineLength(cm, curStart.line + 1)); - var text = cm.getRange(curStart, tmp); - text = text.replace(/\n\s*/g, ' '); - cm.replaceRange(text, curStart, tmp); - } - var curFinalPos = Pos(curStart.line, finalCh); - if (vim.visualMode) { - exitVisualMode(cm, false); - } - cm.setCursor(curFinalPos); - }, - newLineAndEnterInsertMode: function(cm, actionArgs, vim) { - vim.insertMode = true; - var insertAt = copyCursor(cm.getCursor()); - if (insertAt.line === cm.firstLine() && !actionArgs.after) { - // Special case for inserting newline before start of document. - cm.replaceRange('\n', Pos(cm.firstLine(), 0)); - cm.setCursor(cm.firstLine(), 0); - } else { - insertAt.line = (actionArgs.after) ? insertAt.line : - insertAt.line - 1; - insertAt.ch = lineLength(cm, insertAt.line); - cm.setCursor(insertAt); - var newlineFn = CodeMirror.commands.newlineAndIndentContinueComment || - CodeMirror.commands.newlineAndIndent; - newlineFn(cm); - } - this.enterInsertMode(cm, { repeat: actionArgs.repeat }, vim); - }, - paste: function(cm, actionArgs, vim) { - var cur = copyCursor(cm.getCursor()); - var register = vimGlobalState.registerController.getRegister( - actionArgs.registerName); - var text = register.toString(); - if (!text) { - return; - } - if (actionArgs.matchIndent) { - var tabSize = cm.getOption("tabSize"); - // length that considers tabs and tabSize - var whitespaceLength = function(str) { - var tabs = (str.split("\t").length - 1); - var spaces = (str.split(" ").length - 1); - return tabs * tabSize + spaces * 1; - }; - var currentLine = cm.getLine(cm.getCursor().line); - var indent = whitespaceLength(currentLine.match(/^\s*/)[0]); - // chomp last newline b/c don't want it to match /^\s*/gm - var chompedText = text.replace(/\n$/, ''); - var wasChomped = text !== chompedText; - var firstIndent = whitespaceLength(text.match(/^\s*/)[0]); - var text = chompedText.replace(/^\s*/gm, function(wspace) { - var newIndent = indent + (whitespaceLength(wspace) - firstIndent); - if (newIndent < 0) { - return ""; - } - else if (cm.getOption("indentWithTabs")) { - var quotient = Math.floor(newIndent / tabSize); - return Array(quotient + 1).join('\t'); - } - else { - return Array(newIndent + 1).join(' '); - } - }); - text += wasChomped ? "\n" : ""; - } - if (actionArgs.repeat > 1) { - var text = Array(actionArgs.repeat + 1).join(text); - } - var linewise = register.linewise; - var blockwise = register.blockwise; - if (linewise) { - if(vim.visualMode) { - text = vim.visualLine ? text.slice(0, -1) : '\n' + text.slice(0, text.length - 1) + '\n'; - } else if (actionArgs.after) { - // Move the newline at the end to the start instead, and paste just - // before the newline character of the line we are on right now. - text = '\n' + text.slice(0, text.length - 1); - cur.ch = lineLength(cm, cur.line); - } else { - cur.ch = 0; - } - } else { - if (blockwise) { - text = text.split('\n'); - for (var i = 0; i < text.length; i++) { - text[i] = (text[i] == '') ? ' ' : text[i]; - } - } - cur.ch += actionArgs.after ? 1 : 0; - } - var curPosFinal; - var idx; - if (vim.visualMode) { - // save the pasted text for reselection if the need arises - vim.lastPastedText = text; - var lastSelectionCurEnd; - var selectedArea = getSelectedAreaRange(cm, vim); - var selectionStart = selectedArea[0]; - var selectionEnd = selectedArea[1]; - var selectedText = cm.getSelection(); - var selections = cm.listSelections(); - var emptyStrings = new Array(selections.length).join('1').split('1'); - // save the curEnd marker before it get cleared due to cm.replaceRange. - if (vim.lastSelection) { - lastSelectionCurEnd = vim.lastSelection.headMark.find(); - } - // push the previously selected text to unnamed register - vimGlobalState.registerController.unnamedRegister.setText(selectedText); - if (blockwise) { - // first delete the selected text - cm.replaceSelections(emptyStrings); - // Set new selections as per the block length of the yanked text - selectionEnd = Pos(selectionStart.line + text.length-1, selectionStart.ch); - cm.setCursor(selectionStart); - selectBlock(cm, selectionEnd); - cm.replaceSelections(text); - curPosFinal = selectionStart; - } else if (vim.visualBlock) { - cm.replaceSelections(emptyStrings); - cm.setCursor(selectionStart); - cm.replaceRange(text, selectionStart, selectionStart); - curPosFinal = selectionStart; - } else { - cm.replaceRange(text, selectionStart, selectionEnd); - curPosFinal = cm.posFromIndex(cm.indexFromPos(selectionStart) + text.length - 1); - } - // restore the the curEnd marker - if(lastSelectionCurEnd) { - vim.lastSelection.headMark = cm.setBookmark(lastSelectionCurEnd); - } - if (linewise) { - curPosFinal.ch=0; - } - } else { - if (blockwise) { - cm.setCursor(cur); - for (var i = 0; i < text.length; i++) { - var line = cur.line+i; - if (line > cm.lastLine()) { - cm.replaceRange('\n', Pos(line, 0)); - } - var lastCh = lineLength(cm, line); - if (lastCh < cur.ch) { - extendLineToColumn(cm, line, cur.ch); - } - } - cm.setCursor(cur); - selectBlock(cm, Pos(cur.line + text.length-1, cur.ch)); - cm.replaceSelections(text); - curPosFinal = cur; - } else { - cm.replaceRange(text, cur); - // Now fine tune the cursor to where we want it. - if (linewise && actionArgs.after) { - curPosFinal = Pos( - cur.line + 1, - findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line + 1))); - } else if (linewise && !actionArgs.after) { - curPosFinal = Pos( - cur.line, - findFirstNonWhiteSpaceCharacter(cm.getLine(cur.line))); - } else if (!linewise && actionArgs.after) { - idx = cm.indexFromPos(cur); - curPosFinal = cm.posFromIndex(idx + text.length - 1); - } else { - idx = cm.indexFromPos(cur); - curPosFinal = cm.posFromIndex(idx + text.length); - } - } - } - if (vim.visualMode) { - exitVisualMode(cm, false); - } - cm.setCursor(curPosFinal); - }, - undo: function(cm, actionArgs) { - cm.operation(function() { - repeatFn(cm, CodeMirror.commands.undo, actionArgs.repeat)(); - cm.setCursor(cm.getCursor('anchor')); - }); - }, - redo: function(cm, actionArgs) { - repeatFn(cm, CodeMirror.commands.redo, actionArgs.repeat)(); - }, - setRegister: function(_cm, actionArgs, vim) { - vim.inputState.registerName = actionArgs.selectedCharacter; - }, - setMark: function(cm, actionArgs, vim) { - var markName = actionArgs.selectedCharacter; - updateMark(cm, vim, markName, cm.getCursor()); - }, - replace: function(cm, actionArgs, vim) { - var replaceWith = actionArgs.selectedCharacter; - var curStart = cm.getCursor(); - var replaceTo; - var curEnd; - var selections = cm.listSelections(); - if (vim.visualMode) { - curStart = cm.getCursor('start'); - curEnd = cm.getCursor('end'); - } else { - var line = cm.getLine(curStart.line); - replaceTo = curStart.ch + actionArgs.repeat; - if (replaceTo > line.length) { - replaceTo=line.length; - } - curEnd = Pos(curStart.line, replaceTo); - } - if (replaceWith=='\n') { - if (!vim.visualMode) cm.replaceRange('', curStart, curEnd); - // special case, where vim help says to replace by just one line-break - (CodeMirror.commands.newlineAndIndentContinueComment || CodeMirror.commands.newlineAndIndent)(cm); - } else { - var replaceWithStr = cm.getRange(curStart, curEnd); - //replace all characters in range by selected, but keep linebreaks - replaceWithStr = replaceWithStr.replace(/[^\n]/g, replaceWith); - if (vim.visualBlock) { - // Tabs are split in visua block before replacing - var spaces = new Array(cm.getOption("tabSize")+1).join(' '); - replaceWithStr = cm.getSelection(); - replaceWithStr = replaceWithStr.replace(/\t/g, spaces).replace(/[^\n]/g, replaceWith).split('\n'); - cm.replaceSelections(replaceWithStr); - } else { - cm.replaceRange(replaceWithStr, curStart, curEnd); - } - if (vim.visualMode) { - curStart = cursorIsBefore(selections[0].anchor, selections[0].head) ? - selections[0].anchor : selections[0].head; - cm.setCursor(curStart); - exitVisualMode(cm, false); - } else { - cm.setCursor(offsetCursor(curEnd, 0, -1)); - } - } - }, - incrementNumberToken: function(cm, actionArgs) { - var cur = cm.getCursor(); - var lineStr = cm.getLine(cur.line); - var re = /-?\d+/g; - var match; - var start; - var end; - var numberStr; - var token; - while ((match = re.exec(lineStr)) !== null) { - token = match[0]; - start = match.index; - end = start + token.length; - if (cur.ch < end)break; - } - if (!actionArgs.backtrack && (end <= cur.ch))return; - if (token) { - var increment = actionArgs.increase ? 1 : -1; - var number = parseInt(token) + (increment * actionArgs.repeat); - var from = Pos(cur.line, start); - var to = Pos(cur.line, end); - numberStr = number.toString(); - cm.replaceRange(numberStr, from, to); - } else { - return; - } - cm.setCursor(Pos(cur.line, start + numberStr.length - 1)); - }, - repeatLastEdit: function(cm, actionArgs, vim) { - var lastEditInputState = vim.lastEditInputState; - if (!lastEditInputState) { return; } - var repeat = actionArgs.repeat; - if (repeat && actionArgs.repeatIsExplicit) { - vim.lastEditInputState.repeatOverride = repeat; - } else { - repeat = vim.lastEditInputState.repeatOverride || repeat; - } - repeatLastEdit(cm, vim, repeat, false /** repeatForInsert */); - }, - indent: function(cm, actionArgs) { - cm.indentLine(cm.getCursor().line, actionArgs.indentRight); - }, - exitInsertMode: exitInsertMode - }; - - function defineAction(name, fn) { - actions[name] = fn; - } - - /* - * Below are miscellaneous utility functions used by vim.js - */ - - /** - * Clips cursor to ensure that line is within the buffer's range - * If includeLineBreak is true, then allow cur.ch == lineLength. - */ - function clipCursorToContent(cm, cur, includeLineBreak) { - var line = Math.min(Math.max(cm.firstLine(), cur.line), cm.lastLine() ); - var maxCh = lineLength(cm, line) - 1; - maxCh = (includeLineBreak) ? maxCh + 1 : maxCh; - var ch = Math.min(Math.max(0, cur.ch), maxCh); - return Pos(line, ch); - } - function copyArgs(args) { - var ret = {}; - for (var prop in args) { - if (args.hasOwnProperty(prop)) { - ret[prop] = args[prop]; - } - } - return ret; - } - function offsetCursor(cur, offsetLine, offsetCh) { - if (typeof offsetLine === 'object') { - offsetCh = offsetLine.ch; - offsetLine = offsetLine.line; - } - return Pos(cur.line + offsetLine, cur.ch + offsetCh); - } - function getOffset(anchor, head) { - return { - line: head.line - anchor.line, - ch: head.line - anchor.line - }; - } - function commandMatches(keys, keyMap, context, inputState) { - // Partial matches are not applied. They inform the key handler - // that the current key sequence is a subsequence of a valid key - // sequence, so that the key buffer is not cleared. - var match, partial = [], full = []; - for (var i = 0; i < keyMap.length; i++) { - var command = keyMap[i]; - if (context == 'insert' && command.context != 'insert' || - command.context && command.context != context || - inputState.operator && command.type == 'action' || - !(match = commandMatch(keys, command.keys))) { continue; } - if (match == 'partial') { partial.push(command); } - if (match == 'full') { full.push(command); } - } - return { - partial: partial.length && partial, - full: full.length && full - }; - } - function commandMatch(pressed, mapped) { - if (mapped.slice(-11) == '') { - // Last character matches anything. - var prefixLen = mapped.length - 11; - var pressedPrefix = pressed.slice(0, prefixLen); - var mappedPrefix = mapped.slice(0, prefixLen); - return pressedPrefix == mappedPrefix && pressed.length > prefixLen ? 'full' : - mappedPrefix.indexOf(pressedPrefix) == 0 ? 'partial' : false; - } else { - return pressed == mapped ? 'full' : - mapped.indexOf(pressed) == 0 ? 'partial' : false; - } - } - function lastChar(keys) { - var match = /^.*(<[\w\-]+>)$/.exec(keys); - var selectedCharacter = match ? match[1] : keys.slice(-1); - if (selectedCharacter.length > 1){ - switch(selectedCharacter){ - case '': - selectedCharacter='\n'; - break; - case '': - selectedCharacter=' '; - break; - default: - break; - } - } - return selectedCharacter; - } - function repeatFn(cm, fn, repeat) { - return function() { - for (var i = 0; i < repeat; i++) { - fn(cm); - } - }; - } - function copyCursor(cur) { - return Pos(cur.line, cur.ch); - } - function cursorEqual(cur1, cur2) { - return cur1.ch == cur2.ch && cur1.line == cur2.line; - } - function cursorIsBefore(cur1, cur2) { - if (cur1.line < cur2.line) { - return true; - } - if (cur1.line == cur2.line && cur1.ch < cur2.ch) { - return true; - } - return false; - } - function cursorMin(cur1, cur2) { - if (arguments.length > 2) { - cur2 = cursorMin.apply(undefined, Array.prototype.slice.call(arguments, 1)); - } - return cursorIsBefore(cur1, cur2) ? cur1 : cur2; - } - function cursorMax(cur1, cur2) { - if (arguments.length > 2) { - cur2 = cursorMax.apply(undefined, Array.prototype.slice.call(arguments, 1)); - } - return cursorIsBefore(cur1, cur2) ? cur2 : cur1; - } - function cursorIsBetween(cur1, cur2, cur3) { - // returns true if cur2 is between cur1 and cur3. - var cur1before2 = cursorIsBefore(cur1, cur2); - var cur2before3 = cursorIsBefore(cur2, cur3); - return cur1before2 && cur2before3; - } - function lineLength(cm, lineNum) { - return cm.getLine(lineNum).length; - } - function trim(s) { - if (s.trim) { - return s.trim(); - } - return s.replace(/^\s+|\s+$/g, ''); - } - function escapeRegex(s) { - return s.replace(/([.?*+$\[\]\/\\(){}|\-])/g, '\\$1'); - } - function extendLineToColumn(cm, lineNum, column) { - var endCh = lineLength(cm, lineNum); - var spaces = new Array(column-endCh+1).join(' '); - cm.setCursor(Pos(lineNum, endCh)); - cm.replaceRange(spaces, cm.getCursor()); - } - // This functions selects a rectangular block - // of text with selectionEnd as any of its corner - // Height of block: - // Difference in selectionEnd.line and first/last selection.line - // Width of the block: - // Distance between selectionEnd.ch and any(first considered here) selection.ch - function selectBlock(cm, selectionEnd) { - var selections = [], ranges = cm.listSelections(); - var head = copyCursor(cm.clipPos(selectionEnd)); - var isClipped = !cursorEqual(selectionEnd, head); - var curHead = cm.getCursor('head'); - var primIndex = getIndex(ranges, curHead); - var wasClipped = cursorEqual(ranges[primIndex].head, ranges[primIndex].anchor); - var max = ranges.length - 1; - var index = max - primIndex > primIndex ? max : 0; - var base = ranges[index].anchor; - - var firstLine = Math.min(base.line, head.line); - var lastLine = Math.max(base.line, head.line); - var baseCh = base.ch, headCh = head.ch; - - var dir = ranges[index].head.ch - baseCh; - var newDir = headCh - baseCh; - if (dir > 0 && newDir <= 0) { - baseCh++; - if (!isClipped) { headCh--; } - } else if (dir < 0 && newDir >= 0) { - baseCh--; - if (!wasClipped) { headCh++; } - } else if (dir < 0 && newDir == -1) { - baseCh--; - headCh++; - } - for (var line = firstLine; line <= lastLine; line++) { - var range = {anchor: new Pos(line, baseCh), head: new Pos(line, headCh)}; - selections.push(range); - } - primIndex = head.line == lastLine ? selections.length - 1 : 0; - cm.setSelections(selections); - selectionEnd.ch = headCh; - base.ch = baseCh; - return base; - } - function selectForInsert(cm, head, height) { - var sel = []; - for (var i = 0; i < height; i++) { - var lineHead = offsetCursor(head, i, 0); - sel.push({anchor: lineHead, head: lineHead}); - } - cm.setSelections(sel, 0); - } - // getIndex returns the index of the cursor in the selections. - function getIndex(ranges, cursor, end) { - for (var i = 0; i < ranges.length; i++) { - var atAnchor = end != 'head' && cursorEqual(ranges[i].anchor, cursor); - var atHead = end != 'anchor' && cursorEqual(ranges[i].head, cursor); - if (atAnchor || atHead) { - return i; - } - } - return -1; - } - function getSelectedAreaRange(cm, vim) { - var lastSelection = vim.lastSelection; - var getCurrentSelectedAreaRange = function() { - var selections = cm.listSelections(); - var start = selections[0]; - var end = selections[selections.length-1]; - var selectionStart = cursorIsBefore(start.anchor, start.head) ? start.anchor : start.head; - var selectionEnd = cursorIsBefore(end.anchor, end.head) ? end.head : end.anchor; - return [selectionStart, selectionEnd]; - }; - var getLastSelectedAreaRange = function() { - var selectionStart = cm.getCursor(); - var selectionEnd = cm.getCursor(); - var block = lastSelection.visualBlock; - if (block) { - var width = block.width; - var height = block.height; - selectionEnd = Pos(selectionStart.line + height, selectionStart.ch + width); - var selections = []; - // selectBlock creates a 'proper' rectangular block. - // We do not want that in all cases, so we manually set selections. - for (var i = selectionStart.line; i < selectionEnd.line; i++) { - var anchor = Pos(i, selectionStart.ch); - var head = Pos(i, selectionEnd.ch); - var range = {anchor: anchor, head: head}; - selections.push(range); - } - cm.setSelections(selections); - } else { - var start = lastSelection.anchorMark.find(); - var end = lastSelection.headMark.find(); - var line = end.line - start.line; - var ch = end.ch - start.ch; - selectionEnd = {line: selectionEnd.line + line, ch: line ? selectionEnd.ch : ch + selectionEnd.ch}; - if (lastSelection.visualLine) { - selectionStart = Pos(selectionStart.line, 0); - selectionEnd = Pos(selectionEnd.line, lineLength(cm, selectionEnd.line)); - } - cm.setSelection(selectionStart, selectionEnd); - } - return [selectionStart, selectionEnd]; - }; - if (!vim.visualMode) { - // In case of replaying the action. - return getLastSelectedAreaRange(); - } else { - return getCurrentSelectedAreaRange(); - } - } - // Updates the previous selection with the current selection's values. This - // should only be called in visual mode. - function updateLastSelection(cm, vim) { - var anchor = vim.sel.anchor; - var head = vim.sel.head; - // To accommodate the effect of lastPastedText in the last selection - if (vim.lastPastedText) { - head = cm.posFromIndex(cm.indexFromPos(anchor) + vim.lastPastedText.length); - vim.lastPastedText = null; - } - vim.lastSelection = {'anchorMark': cm.setBookmark(anchor), - 'headMark': cm.setBookmark(head), - 'anchor': copyCursor(anchor), - 'head': copyCursor(head), - 'visualMode': vim.visualMode, - 'visualLine': vim.visualLine, - 'visualBlock': vim.visualBlock}; - } - function expandSelection(cm, start, end) { - var sel = cm.state.vim.sel; - var head = sel.head; - var anchor = sel.anchor; - var tmp; - if (cursorIsBefore(end, start)) { - tmp = end; - end = start; - start = tmp; - } - if (cursorIsBefore(head, anchor)) { - head = cursorMin(start, head); - anchor = cursorMax(anchor, end); - } else { - anchor = cursorMin(start, anchor); - head = cursorMax(head, end); - head = offsetCursor(head, 0, -1); - if (head.ch == -1 && head.line != cm.firstLine()) { - head = Pos(head.line - 1, lineLength(cm, head.line - 1)); - } - } - return [anchor, head]; - } - /** - * Updates the CodeMirror selection to match the provided vim selection. - * If no arguments are given, it uses the current vim selection state. - */ - function updateCmSelection(cm, sel, mode) { - var vim = cm.state.vim; - sel = sel || vim.sel; - var mode = mode || - vim.visualLine ? 'line' : vim.visualBlock ? 'block' : 'char'; - var cmSel = makeCmSelection(cm, sel, mode); - cm.setSelections(cmSel.ranges, cmSel.primary); - updateFakeCursor(cm); - } - function makeCmSelection(cm, sel, mode, exclusive) { - var head = copyCursor(sel.head); - var anchor = copyCursor(sel.anchor); - if (mode == 'char') { - var headOffset = !exclusive && !cursorIsBefore(sel.head, sel.anchor) ? 1 : 0; - var anchorOffset = cursorIsBefore(sel.head, sel.anchor) ? 1 : 0; - head = offsetCursor(sel.head, 0, headOffset); - anchor = offsetCursor(sel.anchor, 0, anchorOffset); - return { - ranges: [{anchor: anchor, head: head}], - primary: 0 - }; - } else if (mode == 'line') { - if (!cursorIsBefore(sel.head, sel.anchor)) { - anchor.ch = 0; - - var lastLine = cm.lastLine(); - if (head.line > lastLine) { - head.line = lastLine; - } - head.ch = lineLength(cm, head.line); - } else { - head.ch = 0; - anchor.ch = lineLength(cm, anchor.line); - } - return { - ranges: [{anchor: anchor, head: head}], - primary: 0 - }; - } else if (mode == 'block') { - var top = Math.min(anchor.line, head.line), - left = Math.min(anchor.ch, head.ch), - bottom = Math.max(anchor.line, head.line), - right = Math.max(anchor.ch, head.ch) + 1; - var height = bottom - top + 1; - var primary = head.line == top ? 0 : height - 1; - var ranges = []; - for (var i = 0; i < height; i++) { - ranges.push({ - anchor: Pos(top + i, left), - head: Pos(top + i, right) - }); - } - return { - ranges: ranges, - primary: primary - }; - } - } - function getHead(cm) { - var cur = cm.getCursor('head'); - if (cm.getSelection().length == 1) { - // Small corner case when only 1 character is selected. The "real" - // head is the left of head and anchor. - cur = cursorMin(cur, cm.getCursor('anchor')); - } - return cur; - } - - /** - * If moveHead is set to false, the CodeMirror selection will not be - * touched. The caller assumes the responsibility of putting the cursor - * in the right place. - */ - function exitVisualMode(cm, moveHead) { - var vim = cm.state.vim; - if (moveHead !== false) { - cm.setCursor(clipCursorToContent(cm, vim.sel.head)); - } - updateLastSelection(cm, vim); - vim.visualMode = false; - vim.visualLine = false; - vim.visualBlock = false; - CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); - if (vim.fakeCursor) { - vim.fakeCursor.clear(); - } - } - - // Remove any trailing newlines from the selection. For - // example, with the caret at the start of the last word on the line, - // 'dw' should word, but not the newline, while 'w' should advance the - // caret to the first character of the next line. - function clipToLine(cm, curStart, curEnd) { - var selection = cm.getRange(curStart, curEnd); - // Only clip if the selection ends with trailing newline + whitespace - if (/\n\s*$/.test(selection)) { - var lines = selection.split('\n'); - // We know this is all whitespace. - lines.pop(); - - // Cases: - // 1. Last word is an empty line - do not clip the trailing '\n' - // 2. Last word is not an empty line - clip the trailing '\n' - var line; - // Find the line containing the last word, and clip all whitespace up - // to it. - for (var line = lines.pop(); lines.length > 0 && line && isWhiteSpaceString(line); line = lines.pop()) { - curEnd.line--; - curEnd.ch = 0; - } - // If the last word is not an empty line, clip an additional newline - if (line) { - curEnd.line--; - curEnd.ch = lineLength(cm, curEnd.line); - } else { - curEnd.ch = 0; - } - } - } - - // Expand the selection to line ends. - function expandSelectionToLine(_cm, curStart, curEnd) { - curStart.ch = 0; - curEnd.ch = 0; - curEnd.line++; - } - - function findFirstNonWhiteSpaceCharacter(text) { - if (!text) { - return 0; - } - var firstNonWS = text.search(/\S/); - return firstNonWS == -1 ? text.length : firstNonWS; - } - - function expandWordUnderCursor(cm, inclusive, _forward, bigWord, noSymbol) { - var cur = getHead(cm); - var line = cm.getLine(cur.line); - var idx = cur.ch; - - // Seek to first word or non-whitespace character, depending on if - // noSymbol is true. - var test = noSymbol ? wordCharTest[0] : bigWordCharTest [0]; - while (!test(line.charAt(idx))) { - idx++; - if (idx >= line.length) { return null; } - } - - if (bigWord) { - test = bigWordCharTest[0]; - } else { - test = wordCharTest[0]; - if (!test(line.charAt(idx))) { - test = wordCharTest[1]; - } - } - - var end = idx, start = idx; - while (test(line.charAt(end)) && end < line.length) { end++; } - while (test(line.charAt(start)) && start >= 0) { start--; } - start++; - - if (inclusive) { - // If present, include all whitespace after word. - // Otherwise, include all whitespace before word, except indentation. - var wordEnd = end; - while (/\s/.test(line.charAt(end)) && end < line.length) { end++; } - if (wordEnd == end) { - var wordStart = start; - while (/\s/.test(line.charAt(start - 1)) && start > 0) { start--; } - if (!start) { start = wordStart; } - } - } - return { start: Pos(cur.line, start), end: Pos(cur.line, end) }; - } - - function recordJumpPosition(cm, oldCur, newCur) { - if (!cursorEqual(oldCur, newCur)) { - vimGlobalState.jumpList.add(cm, oldCur, newCur); - } - } - - function recordLastCharacterSearch(increment, args) { - vimGlobalState.lastCharacterSearch.increment = increment; - vimGlobalState.lastCharacterSearch.forward = args.forward; - vimGlobalState.lastCharacterSearch.selectedCharacter = args.selectedCharacter; - } - - var symbolToMode = { - '(': 'bracket', ')': 'bracket', '{': 'bracket', '}': 'bracket', - '[': 'section', ']': 'section', - '*': 'comment', '/': 'comment', - 'm': 'method', 'M': 'method', - '#': 'preprocess' - }; - var findSymbolModes = { - bracket: { - isComplete: function(state) { - if (state.nextCh === state.symb) { - state.depth++; - if (state.depth >= 1)return true; - } else if (state.nextCh === state.reverseSymb) { - state.depth--; - } - return false; - } - }, - section: { - init: function(state) { - state.curMoveThrough = true; - state.symb = (state.forward ? ']' : '[') === state.symb ? '{' : '}'; - }, - isComplete: function(state) { - return state.index === 0 && state.nextCh === state.symb; - } - }, - comment: { - isComplete: function(state) { - var found = state.lastCh === '*' && state.nextCh === '/'; - state.lastCh = state.nextCh; - return found; - } - }, - // TODO: The original Vim implementation only operates on level 1 and 2. - // The current implementation doesn't check for code block level and - // therefore it operates on any levels. - method: { - init: function(state) { - state.symb = (state.symb === 'm' ? '{' : '}'); - state.reverseSymb = state.symb === '{' ? '}' : '{'; - }, - isComplete: function(state) { - if (state.nextCh === state.symb)return true; - return false; - } - }, - preprocess: { - init: function(state) { - state.index = 0; - }, - isComplete: function(state) { - if (state.nextCh === '#') { - var token = state.lineText.match(/#(\w+)/)[1]; - if (token === 'endif') { - if (state.forward && state.depth === 0) { - return true; - } - state.depth++; - } else if (token === 'if') { - if (!state.forward && state.depth === 0) { - return true; - } - state.depth--; - } - if (token === 'else' && state.depth === 0)return true; - } - return false; - } - } - }; - function findSymbol(cm, repeat, forward, symb) { - var cur = copyCursor(cm.getCursor()); - var increment = forward ? 1 : -1; - var endLine = forward ? cm.lineCount() : -1; - var curCh = cur.ch; - var line = cur.line; - var lineText = cm.getLine(line); - var state = { - lineText: lineText, - nextCh: lineText.charAt(curCh), - lastCh: null, - index: curCh, - symb: symb, - reverseSymb: (forward ? { ')': '(', '}': '{' } : { '(': ')', '{': '}' })[symb], - forward: forward, - depth: 0, - curMoveThrough: false - }; - var mode = symbolToMode[symb]; - if (!mode)return cur; - var init = findSymbolModes[mode].init; - var isComplete = findSymbolModes[mode].isComplete; - if (init) { init(state); } - while (line !== endLine && repeat) { - state.index += increment; - state.nextCh = state.lineText.charAt(state.index); - if (!state.nextCh) { - line += increment; - state.lineText = cm.getLine(line) || ''; - if (increment > 0) { - state.index = 0; - } else { - var lineLen = state.lineText.length; - state.index = (lineLen > 0) ? (lineLen-1) : 0; - } - state.nextCh = state.lineText.charAt(state.index); - } - if (isComplete(state)) { - cur.line = line; - cur.ch = state.index; - repeat--; - } - } - if (state.nextCh || state.curMoveThrough) { - return Pos(line, state.index); - } - return cur; - } - - /** - * Returns the boundaries of the next word. If the cursor in the middle of - * the word, then returns the boundaries of the current word, starting at - * the cursor. If the cursor is at the start/end of a word, and we are going - * forward/backward, respectively, find the boundaries of the next word. - * - * @param {CodeMirror} cm CodeMirror object. - * @param {Cursor} cur The cursor position. - * @param {boolean} forward True to search forward. False to search - * backward. - * @param {boolean} bigWord True if punctuation count as part of the word. - * False if only [a-zA-Z0-9] characters count as part of the word. - * @param {boolean} emptyLineIsWord True if empty lines should be treated - * as words. - * @return {Object{from:number, to:number, line: number}} The boundaries of - * the word, or null if there are no more words. - */ - function findWord(cm, cur, forward, bigWord, emptyLineIsWord) { - var lineNum = cur.line; - var pos = cur.ch; - var line = cm.getLine(lineNum); - var dir = forward ? 1 : -1; - var charTests = bigWord ? bigWordCharTest: wordCharTest; - - if (emptyLineIsWord && line == '') { - lineNum += dir; - line = cm.getLine(lineNum); - if (!isLine(cm, lineNum)) { - return null; - } - pos = (forward) ? 0 : line.length; - } - - while (true) { - if (emptyLineIsWord && line == '') { - return { from: 0, to: 0, line: lineNum }; - } - var stop = (dir > 0) ? line.length : -1; - var wordStart = stop, wordEnd = stop; - // Find bounds of next word. - while (pos != stop) { - var foundWord = false; - for (var i = 0; i < charTests.length && !foundWord; ++i) { - if (charTests[i](line.charAt(pos))) { - wordStart = pos; - // Advance to end of word. - while (pos != stop && charTests[i](line.charAt(pos))) { - pos += dir; - } - wordEnd = pos; - foundWord = wordStart != wordEnd; - if (wordStart == cur.ch && lineNum == cur.line && - wordEnd == wordStart + dir) { - // We started at the end of a word. Find the next one. - continue; - } else { - return { - from: Math.min(wordStart, wordEnd + 1), - to: Math.max(wordStart, wordEnd), - line: lineNum }; - } - } - } - if (!foundWord) { - pos += dir; - } - } - // Advance to next/prev line. - lineNum += dir; - if (!isLine(cm, lineNum)) { - return null; - } - line = cm.getLine(lineNum); - pos = (dir > 0) ? 0 : line.length; - } - } - - /** - * @param {CodeMirror} cm CodeMirror object. - * @param {Pos} cur The position to start from. - * @param {int} repeat Number of words to move past. - * @param {boolean} forward True to search forward. False to search - * backward. - * @param {boolean} wordEnd True to move to end of word. False to move to - * beginning of word. - * @param {boolean} bigWord True if punctuation count as part of the word. - * False if only alphabet characters count as part of the word. - * @return {Cursor} The position the cursor should move to. - */ - function moveToWord(cm, cur, repeat, forward, wordEnd, bigWord) { - var curStart = copyCursor(cur); - var words = []; - if (forward && !wordEnd || !forward && wordEnd) { - repeat++; - } - // For 'e', empty lines are not considered words, go figure. - var emptyLineIsWord = !(forward && wordEnd); - for (var i = 0; i < repeat; i++) { - var word = findWord(cm, cur, forward, bigWord, emptyLineIsWord); - if (!word) { - var eodCh = lineLength(cm, cm.lastLine()); - words.push(forward - ? {line: cm.lastLine(), from: eodCh, to: eodCh} - : {line: 0, from: 0, to: 0}); - break; - } - words.push(word); - cur = Pos(word.line, forward ? (word.to - 1) : word.from); - } - var shortCircuit = words.length != repeat; - var firstWord = words[0]; - var lastWord = words.pop(); - if (forward && !wordEnd) { - // w - if (!shortCircuit && (firstWord.from != curStart.ch || firstWord.line != curStart.line)) { - // We did not start in the middle of a word. Discard the extra word at the end. - lastWord = words.pop(); - } - return Pos(lastWord.line, lastWord.from); - } else if (forward && wordEnd) { - return Pos(lastWord.line, lastWord.to - 1); - } else if (!forward && wordEnd) { - // ge - if (!shortCircuit && (firstWord.to != curStart.ch || firstWord.line != curStart.line)) { - // We did not start in the middle of a word. Discard the extra word at the end. - lastWord = words.pop(); - } - return Pos(lastWord.line, lastWord.to); - } else { - // b - return Pos(lastWord.line, lastWord.from); - } - } - - function moveToCharacter(cm, repeat, forward, character) { - var cur = cm.getCursor(); - var start = cur.ch; - var idx; - for (var i = 0; i < repeat; i ++) { - var line = cm.getLine(cur.line); - idx = charIdxInLine(start, line, character, forward, true); - if (idx == -1) { - return null; - } - start = idx; - } - return Pos(cm.getCursor().line, idx); - } - - function moveToColumn(cm, repeat) { - // repeat is always >= 1, so repeat - 1 always corresponds - // to the column we want to go to. - var line = cm.getCursor().line; - return clipCursorToContent(cm, Pos(line, repeat - 1)); - } - - function updateMark(cm, vim, markName, pos) { - if (!inArray(markName, validMarks)) { - return; - } - if (vim.marks[markName]) { - vim.marks[markName].clear(); - } - vim.marks[markName] = cm.setBookmark(pos); - } - - function charIdxInLine(start, line, character, forward, includeChar) { - // Search for char in line. - // motion_options: {forward, includeChar} - // If includeChar = true, include it too. - // If forward = true, search forward, else search backwards. - // If char is not found on this line, do nothing - var idx; - if (forward) { - idx = line.indexOf(character, start + 1); - if (idx != -1 && !includeChar) { - idx -= 1; - } - } else { - idx = line.lastIndexOf(character, start - 1); - if (idx != -1 && !includeChar) { - idx += 1; - } - } - return idx; - } - - function findParagraph(cm, head, repeat, dir, inclusive) { - var line = head.line; - var min = cm.firstLine(); - var max = cm.lastLine(); - var start, end, i = line; - function isEmpty(i) { return !cm.getLine(i); } - function isBoundary(i, dir, any) { - if (any) { return isEmpty(i) != isEmpty(i + dir); } - return !isEmpty(i) && isEmpty(i + dir); - } - if (dir) { - while (min <= i && i <= max && repeat > 0) { - if (isBoundary(i, dir)) { repeat--; } - i += dir; - } - return new Pos(i, 0); - } - - var vim = cm.state.vim; - if (vim.visualLine && isBoundary(line, 1, true)) { - var anchor = vim.sel.anchor; - if (isBoundary(anchor.line, -1, true)) { - if (!inclusive || anchor.line != line) { - line += 1; - } - } - } - var startState = isEmpty(line); - for (i = line; i <= max && repeat; i++) { - if (isBoundary(i, 1, true)) { - if (!inclusive || isEmpty(i) != startState) { - repeat--; - } - } - } - end = new Pos(i, 0); - // select boundary before paragraph for the last one - if (i > max && !startState) { startState = true; } - else { inclusive = false; } - for (i = line; i > min; i--) { - if (!inclusive || isEmpty(i) == startState || i == line) { - if (isBoundary(i, -1, true)) { break; } - } - } - start = new Pos(i, 0); - return { start: start, end: end }; - } - - // TODO: perhaps this finagling of start and end positions belonds - // in codemirror/replaceRange? - function selectCompanionObject(cm, head, symb, inclusive) { - var cur = head, start, end; - - var bracketRegexp = ({ - '(': /[()]/, ')': /[()]/, - '[': /[[\]]/, ']': /[[\]]/, - '{': /[{}]/, '}': /[{}]/})[symb]; - var openSym = ({ - '(': '(', ')': '(', - '[': '[', ']': '[', - '{': '{', '}': '{'})[symb]; - var curChar = cm.getLine(cur.line).charAt(cur.ch); - // Due to the behavior of scanForBracket, we need to add an offset if the - // cursor is on a matching open bracket. - var offset = curChar === openSym ? 1 : 0; - - start = cm.scanForBracket(Pos(cur.line, cur.ch + offset), -1, null, {'bracketRegex': bracketRegexp}); - end = cm.scanForBracket(Pos(cur.line, cur.ch + offset), 1, null, {'bracketRegex': bracketRegexp}); - - if (!start || !end) { - return { start: cur, end: cur }; - } - - start = start.pos; - end = end.pos; - - if ((start.line == end.line && start.ch > end.ch) - || (start.line > end.line)) { - var tmp = start; - start = end; - end = tmp; - } - - if (inclusive) { - end.ch += 1; - } else { - start.ch += 1; - } - - return { start: start, end: end }; - } - - // Takes in a symbol and a cursor and tries to simulate text objects that - // have identical opening and closing symbols - // TODO support across multiple lines - function findBeginningAndEnd(cm, head, symb, inclusive) { - var cur = copyCursor(head); - var line = cm.getLine(cur.line); - var chars = line.split(''); - var start, end, i, len; - var firstIndex = chars.indexOf(symb); - - // the decision tree is to always look backwards for the beginning first, - // but if the cursor is in front of the first instance of the symb, - // then move the cursor forward - if (cur.ch < firstIndex) { - cur.ch = firstIndex; - // Why is this line even here??? - // cm.setCursor(cur.line, firstIndex+1); - } - // otherwise if the cursor is currently on the closing symbol - else if (firstIndex < cur.ch && chars[cur.ch] == symb) { - end = cur.ch; // assign end to the current cursor - --cur.ch; // make sure to look backwards - } - - // if we're currently on the symbol, we've got a start - if (chars[cur.ch] == symb && !end) { - start = cur.ch + 1; // assign start to ahead of the cursor - } else { - // go backwards to find the start - for (i = cur.ch; i > -1 && !start; i--) { - if (chars[i] == symb) { - start = i + 1; - } - } - } - - // look forwards for the end symbol - if (start && !end) { - for (i = start, len = chars.length; i < len && !end; i++) { - if (chars[i] == symb) { - end = i; - } - } - } - - // nothing found - if (!start || !end) { - return { start: cur, end: cur }; - } - - // include the symbols - if (inclusive) { - --start; ++end; - } - - return { - start: Pos(cur.line, start), - end: Pos(cur.line, end) - }; - } - - // Search functions - defineOption('pcre', true, 'boolean'); - function SearchState() {} - SearchState.prototype = { - getQuery: function() { - return vimGlobalState.query; - }, - setQuery: function(query) { - vimGlobalState.query = query; - }, - getOverlay: function() { - return this.searchOverlay; - }, - setOverlay: function(overlay) { - this.searchOverlay = overlay; - }, - isReversed: function() { - return vimGlobalState.isReversed; - }, - setReversed: function(reversed) { - vimGlobalState.isReversed = reversed; - }, - getScrollbarAnnotate: function() { - return this.annotate; - }, - setScrollbarAnnotate: function(annotate) { - this.annotate = annotate; - } - }; - function getSearchState(cm) { - var vim = cm.state.vim; - return vim.searchState_ || (vim.searchState_ = new SearchState()); - } - function dialog(cm, template, shortText, onClose, options) { - if (cm.openDialog) { - cm.openDialog(template, onClose, { bottom: true, value: options.value, - onKeyDown: options.onKeyDown, onKeyUp: options.onKeyUp, - selectValueOnOpen: false}); - } - else { - onClose(prompt(shortText, '')); - } - } - function splitBySlash(argString) { - var slashes = findUnescapedSlashes(argString) || []; - if (!slashes.length) return []; - var tokens = []; - // in case of strings like foo/bar - if (slashes[0] !== 0) return; - for (var i = 0; i < slashes.length; i++) { - if (typeof slashes[i] == 'number') - tokens.push(argString.substring(slashes[i] + 1, slashes[i+1])); - } - return tokens; - } - - function findUnescapedSlashes(str) { - var escapeNextChar = false; - var slashes = []; - for (var i = 0; i < str.length; i++) { - var c = str.charAt(i); - if (!escapeNextChar && c == '/') { - slashes.push(i); - } - escapeNextChar = !escapeNextChar && (c == '\\'); - } - return slashes; - } - - // Translates a search string from ex (vim) syntax into javascript form. - function translateRegex(str) { - // When these match, add a '\' if unescaped or remove one if escaped. - var specials = '|(){'; - // Remove, but never add, a '\' for these. - var unescape = '}'; - var escapeNextChar = false; - var out = []; - for (var i = -1; i < str.length; i++) { - var c = str.charAt(i) || ''; - var n = str.charAt(i+1) || ''; - var specialComesNext = (n && specials.indexOf(n) != -1); - if (escapeNextChar) { - if (c !== '\\' || !specialComesNext) { - out.push(c); - } - escapeNextChar = false; - } else { - if (c === '\\') { - escapeNextChar = true; - // Treat the unescape list as special for removing, but not adding '\'. - if (n && unescape.indexOf(n) != -1) { - specialComesNext = true; - } - // Not passing this test means removing a '\'. - if (!specialComesNext || n === '\\') { - out.push(c); - } - } else { - out.push(c); - if (specialComesNext && n !== '\\') { - out.push('\\'); - } - } - } - } - return out.join(''); - } - - // Translates the replace part of a search and replace from ex (vim) syntax into - // javascript form. Similar to translateRegex, but additionally fixes back references - // (translates '\[0..9]' to '$[0..9]') and follows different rules for escaping '$'. - var charUnescapes = {'\\n': '\n', '\\r': '\r', '\\t': '\t'}; - function translateRegexReplace(str) { - var escapeNextChar = false; - var out = []; - for (var i = -1; i < str.length; i++) { - var c = str.charAt(i) || ''; - var n = str.charAt(i+1) || ''; - if (charUnescapes[c + n]) { - out.push(charUnescapes[c+n]); - i++; - } else if (escapeNextChar) { - // At any point in the loop, escapeNextChar is true if the previous - // character was a '\' and was not escaped. - out.push(c); - escapeNextChar = false; - } else { - if (c === '\\') { - escapeNextChar = true; - if ((isNumber(n) || n === '$')) { - out.push('$'); - } else if (n !== '/' && n !== '\\') { - out.push('\\'); - } - } else { - if (c === '$') { - out.push('$'); - } - out.push(c); - if (n === '/') { - out.push('\\'); - } - } - } - } - return out.join(''); - } - - // Unescape \ and / in the replace part, for PCRE mode. - var unescapes = {'\\/': '/', '\\\\': '\\', '\\n': '\n', '\\r': '\r', '\\t': '\t'}; - function unescapeRegexReplace(str) { - var stream = new CodeMirror.StringStream(str); - var output = []; - while (!stream.eol()) { - // Search for \. - while (stream.peek() && stream.peek() != '\\') { - output.push(stream.next()); - } - var matched = false; - for (var matcher in unescapes) { - if (stream.match(matcher, true)) { - matched = true; - output.push(unescapes[matcher]); - break; - } - } - if (!matched) { - // Don't change anything - output.push(stream.next()); - } - } - return output.join(''); - } - - /** - * Extract the regular expression from the query and return a Regexp object. - * Returns null if the query is blank. - * If ignoreCase is passed in, the Regexp object will have the 'i' flag set. - * If smartCase is passed in, and the query contains upper case letters, - * then ignoreCase is overridden, and the 'i' flag will not be set. - * If the query contains the /i in the flag part of the regular expression, - * then both ignoreCase and smartCase are ignored, and 'i' will be passed - * through to the Regex object. - */ - function parseQuery(query, ignoreCase, smartCase) { - // First update the last search register - var lastSearchRegister = vimGlobalState.registerController.getRegister('/'); - lastSearchRegister.setText(query); - // Check if the query is already a regex. - if (query instanceof RegExp) { return query; } - // First try to extract regex + flags from the input. If no flags found, - // extract just the regex. IE does not accept flags directly defined in - // the regex string in the form /regex/flags - var slashes = findUnescapedSlashes(query); - var regexPart; - var forceIgnoreCase; - if (!slashes.length) { - // Query looks like 'regexp' - regexPart = query; - } else { - // Query looks like 'regexp/...' - regexPart = query.substring(0, slashes[0]); - var flagsPart = query.substring(slashes[0]); - forceIgnoreCase = (flagsPart.indexOf('i') != -1); - } - if (!regexPart) { - return null; - } - if (!getOption('pcre')) { - regexPart = translateRegex(regexPart); - } - if (smartCase) { - ignoreCase = (/^[^A-Z]*$/).test(regexPart); - } - var regexp = new RegExp(regexPart, - (ignoreCase || forceIgnoreCase) ? 'i' : undefined); - return regexp; - } - function showConfirm(cm, text) { - if (cm.openNotification) { - cm.openNotification('' + text + '', - {bottom: true, duration: 5000}); - } else { - alert(text); - } - } - function makePrompt(prefix, desc) { - var raw = '' + - (prefix || "") + ''; - if (desc) - raw += ' ' + desc + ''; - return raw; - } - var searchPromptDesc = '(Javascript regexp)'; - function showPrompt(cm, options) { - var shortText = (options.prefix || '') + ' ' + (options.desc || ''); - var prompt = makePrompt(options.prefix, options.desc); - dialog(cm, prompt, shortText, options.onClose, options); - } - function regexEqual(r1, r2) { - if (r1 instanceof RegExp && r2 instanceof RegExp) { - var props = ['global', 'multiline', 'ignoreCase', 'source']; - for (var i = 0; i < props.length; i++) { - var prop = props[i]; - if (r1[prop] !== r2[prop]) { - return false; - } - } - return true; - } - return false; - } - // Returns true if the query is valid. - function updateSearchQuery(cm, rawQuery, ignoreCase, smartCase) { - if (!rawQuery) { - return; - } - var state = getSearchState(cm); - var query = parseQuery(rawQuery, !!ignoreCase, !!smartCase); - if (!query) { - return; - } - highlightSearchMatches(cm, query); - if (regexEqual(query, state.getQuery())) { - return query; - } - state.setQuery(query); - return query; - } - function searchOverlay(query) { - if (query.source.charAt(0) == '^') { - var matchSol = true; - } - return { - token: function(stream) { - if (matchSol && !stream.sol()) { - stream.skipToEnd(); - return; - } - var match = stream.match(query, false); - if (match) { - if (match[0].length == 0) { - // Matched empty string, skip to next. - stream.next(); - return 'searching'; - } - if (!stream.sol()) { - // Backtrack 1 to match \b - stream.backUp(1); - if (!query.exec(stream.next() + match[0])) { - stream.next(); - return null; - } - } - stream.match(query); - return 'searching'; - } - while (!stream.eol()) { - stream.next(); - if (stream.match(query, false)) break; - } - }, - query: query - }; - } - function highlightSearchMatches(cm, query) { - var searchState = getSearchState(cm); - var overlay = searchState.getOverlay(); - if (!overlay || query != overlay.query) { - if (overlay) { - cm.removeOverlay(overlay); - } - overlay = searchOverlay(query); - cm.addOverlay(overlay); - if (cm.showMatchesOnScrollbar) { - if (searchState.getScrollbarAnnotate()) { - searchState.getScrollbarAnnotate().clear(); - } - searchState.setScrollbarAnnotate(cm.showMatchesOnScrollbar(query)); - } - searchState.setOverlay(overlay); - } - } - function findNext(cm, prev, query, repeat) { - if (repeat === undefined) { repeat = 1; } - return cm.operation(function() { - var pos = cm.getCursor(); - var cursor = cm.getSearchCursor(query, pos); - for (var i = 0; i < repeat; i++) { - var found = cursor.find(prev); - if (i == 0 && found && cursorEqual(cursor.from(), pos)) { found = cursor.find(prev); } - if (!found) { - // SearchCursor may have returned null because it hit EOF, wrap - // around and try again. - cursor = cm.getSearchCursor(query, - (prev) ? Pos(cm.lastLine()) : Pos(cm.firstLine(), 0) ); - if (!cursor.find(prev)) { - return; - } - } - } - return cursor.from(); - }); - } - function clearSearchHighlight(cm) { - var state = getSearchState(cm); - cm.removeOverlay(getSearchState(cm).getOverlay()); - state.setOverlay(null); - if (state.getScrollbarAnnotate()) { - state.getScrollbarAnnotate().clear(); - state.setScrollbarAnnotate(null); - } - } - /** - * Check if pos is in the specified range, INCLUSIVE. - * Range can be specified with 1 or 2 arguments. - * If the first range argument is an array, treat it as an array of line - * numbers. Match pos against any of the lines. - * If the first range argument is a number, - * if there is only 1 range argument, check if pos has the same line - * number - * if there are 2 range arguments, then check if pos is in between the two - * range arguments. - */ - function isInRange(pos, start, end) { - if (typeof pos != 'number') { - // Assume it is a cursor position. Get the line number. - pos = pos.line; - } - if (start instanceof Array) { - return inArray(pos, start); - } else { - if (end) { - return (pos >= start && pos <= end); - } else { - return pos == start; - } - } - } - function getUserVisibleLines(cm) { - var scrollInfo = cm.getScrollInfo(); - var occludeToleranceTop = 6; - var occludeToleranceBottom = 10; - var from = cm.coordsChar({left:0, top: occludeToleranceTop + scrollInfo.top}, 'local'); - var bottomY = scrollInfo.clientHeight - occludeToleranceBottom + scrollInfo.top; - var to = cm.coordsChar({left:0, top: bottomY}, 'local'); - return {top: from.line, bottom: to.line}; - } - - var ExCommandDispatcher = function() { - this.buildCommandMap_(); - }; - ExCommandDispatcher.prototype = { - processCommand: function(cm, input, opt_params) { - var that = this; - cm.operation(function () { - cm.curOp.isVimOp = true; - that._processCommand(cm, input, opt_params); - }); - }, - _processCommand: function(cm, input, opt_params) { - var vim = cm.state.vim; - var commandHistoryRegister = vimGlobalState.registerController.getRegister(':'); - var previousCommand = commandHistoryRegister.toString(); - if (vim.visualMode) { - exitVisualMode(cm); - } - var inputStream = new CodeMirror.StringStream(input); - // update ": with the latest command whether valid or invalid - commandHistoryRegister.setText(input); - var params = opt_params || {}; - params.input = input; - try { - this.parseInput_(cm, inputStream, params); - } catch(e) { - showConfirm(cm, e); - throw e; - } - var command; - var commandName; - if (!params.commandName) { - // If only a line range is defined, move to the line. - if (params.line !== undefined) { - commandName = 'move'; - } - } else { - command = this.matchCommand_(params.commandName); - if (command) { - commandName = command.name; - if (command.excludeFromCommandHistory) { - commandHistoryRegister.setText(previousCommand); - } - this.parseCommandArgs_(inputStream, params, command); - if (command.type == 'exToKey') { - // Handle Ex to Key mapping. - for (var i = 0; i < command.toKeys.length; i++) { - CodeMirror.Vim.handleKey(cm, command.toKeys[i], 'mapping'); - } - return; - } else if (command.type == 'exToEx') { - // Handle Ex to Ex mapping. - this.processCommand(cm, command.toInput); - return; - } - } - } - if (!commandName) { - showConfirm(cm, 'Not an editor command ":' + input + '"'); - return; - } - try { - exCommands[commandName](cm, params); - // Possibly asynchronous commands (e.g. substitute, which might have a - // user confirmation), are responsible for calling the callback when - // done. All others have it taken care of for them here. - if ((!command || !command.possiblyAsync) && params.callback) { - params.callback(); - } - } catch(e) { - showConfirm(cm, e); - throw e; - } - }, - parseInput_: function(cm, inputStream, result) { - inputStream.eatWhile(':'); - // Parse range. - if (inputStream.eat('%')) { - result.line = cm.firstLine(); - result.lineEnd = cm.lastLine(); - } else { - result.line = this.parseLineSpec_(cm, inputStream); - if (result.line !== undefined && inputStream.eat(',')) { - result.lineEnd = this.parseLineSpec_(cm, inputStream); - } - } - - // Parse command name. - var commandMatch = inputStream.match(/^(\w+)/); - if (commandMatch) { - result.commandName = commandMatch[1]; - } else { - result.commandName = inputStream.match(/.*/)[0]; - } - - return result; - }, - parseLineSpec_: function(cm, inputStream) { - var numberMatch = inputStream.match(/^(\d+)/); - if (numberMatch) { - return parseInt(numberMatch[1], 10) - 1; - } - switch (inputStream.next()) { - case '.': - return cm.getCursor().line; - case '$': - return cm.lastLine(); - case '\'': - var mark = cm.state.vim.marks[inputStream.next()]; - if (mark && mark.find()) { - return mark.find().line; - } - throw new Error('Mark not set'); - default: - inputStream.backUp(1); - return undefined; - } - }, - parseCommandArgs_: function(inputStream, params, command) { - if (inputStream.eol()) { - return; - } - params.argString = inputStream.match(/.*/)[0]; - // Parse command-line arguments - var delim = command.argDelimiter || /\s+/; - var args = trim(params.argString).split(delim); - if (args.length && args[0]) { - params.args = args; - } - }, - matchCommand_: function(commandName) { - // Return the command in the command map that matches the shortest - // prefix of the passed in command name. The match is guaranteed to be - // unambiguous if the defaultExCommandMap's shortNames are set up - // correctly. (see @code{defaultExCommandMap}). - for (var i = commandName.length; i > 0; i--) { - var prefix = commandName.substring(0, i); - if (this.commandMap_[prefix]) { - var command = this.commandMap_[prefix]; - if (command.name.indexOf(commandName) === 0) { - return command; - } - } - } - return null; - }, - buildCommandMap_: function() { - this.commandMap_ = {}; - for (var i = 0; i < defaultExCommandMap.length; i++) { - var command = defaultExCommandMap[i]; - var key = command.shortName || command.name; - this.commandMap_[key] = command; - } - }, - map: function(lhs, rhs, ctx) { - if (lhs != ':' && lhs.charAt(0) == ':') { - if (ctx) { throw Error('Mode not supported for ex mappings'); } - var commandName = lhs.substring(1); - if (rhs != ':' && rhs.charAt(0) == ':') { - // Ex to Ex mapping - this.commandMap_[commandName] = { - name: commandName, - type: 'exToEx', - toInput: rhs.substring(1), - user: true - }; - } else { - // Ex to key mapping - this.commandMap_[commandName] = { - name: commandName, - type: 'exToKey', - toKeys: rhs, - user: true - }; - } - } else { - if (rhs != ':' && rhs.charAt(0) == ':') { - // Key to Ex mapping. - var mapping = { - keys: lhs, - type: 'keyToEx', - exArgs: { input: rhs.substring(1) }, - user: true}; - if (ctx) { mapping.context = ctx; } - defaultKeymap.unshift(mapping); - } else { - // Key to key mapping - var mapping = { - keys: lhs, - type: 'keyToKey', - toKeys: rhs, - user: true - }; - if (ctx) { mapping.context = ctx; } - defaultKeymap.unshift(mapping); - } - } - }, - unmap: function(lhs, ctx) { - if (lhs != ':' && lhs.charAt(0) == ':') { - // Ex to Ex or Ex to key mapping - if (ctx) { throw Error('Mode not supported for ex mappings'); } - var commandName = lhs.substring(1); - if (this.commandMap_[commandName] && this.commandMap_[commandName].user) { - delete this.commandMap_[commandName]; - return; - } - } else { - // Key to Ex or key to key mapping - var keys = lhs; - for (var i = 0; i < defaultKeymap.length; i++) { - if (keys == defaultKeymap[i].keys - && defaultKeymap[i].context === ctx - && defaultKeymap[i].user) { - defaultKeymap.splice(i, 1); - return; - } - } - } - throw Error('No such mapping.'); - } - }; - - var exCommands = { - colorscheme: function(cm, params) { - if (!params.args || params.args.length < 1) { - showConfirm(cm, cm.getOption('theme')); - return; - } - cm.setOption('theme', params.args[0]); - }, - map: function(cm, params, ctx) { - var mapArgs = params.args; - if (!mapArgs || mapArgs.length < 2) { - if (cm) { - showConfirm(cm, 'Invalid mapping: ' + params.input); - } - return; - } - exCommandDispatcher.map(mapArgs[0], mapArgs[1], ctx); - }, - imap: function(cm, params) { this.map(cm, params, 'insert'); }, - nmap: function(cm, params) { this.map(cm, params, 'normal'); }, - vmap: function(cm, params) { this.map(cm, params, 'visual'); }, - unmap: function(cm, params, ctx) { - var mapArgs = params.args; - if (!mapArgs || mapArgs.length < 1) { - if (cm) { - showConfirm(cm, 'No such mapping: ' + params.input); - } - return; - } - exCommandDispatcher.unmap(mapArgs[0], ctx); - }, - move: function(cm, params) { - commandDispatcher.processCommand(cm, cm.state.vim, { - type: 'motion', - motion: 'moveToLineOrEdgeOfDocument', - motionArgs: { forward: false, explicitRepeat: true, - linewise: true }, - repeatOverride: params.line+1}); - }, - set: function(cm, params) { - var setArgs = params.args; - // Options passed through to the setOption/getOption calls. May be passed in by the - // local/global versions of the set command - var setCfg = params.setCfg || {}; - if (!setArgs || setArgs.length < 1) { - if (cm) { - showConfirm(cm, 'Invalid mapping: ' + params.input); - } - return; - } - var expr = setArgs[0].split('='); - var optionName = expr[0]; - var value = expr[1]; - var forceGet = false; - - if (optionName.charAt(optionName.length - 1) == '?') { - // If post-fixed with ?, then the set is actually a get. - if (value) { throw Error('Trailing characters: ' + params.argString); } - optionName = optionName.substring(0, optionName.length - 1); - forceGet = true; - } - if (value === undefined && optionName.substring(0, 2) == 'no') { - // To set boolean options to false, the option name is prefixed with - // 'no'. - optionName = optionName.substring(2); - value = false; - } - - var optionIsBoolean = options[optionName] && options[optionName].type == 'boolean'; - if (optionIsBoolean && value == undefined) { - // Calling set with a boolean option sets it to true. - value = true; - } - // If no value is provided, then we assume this is a get. - if (!optionIsBoolean && value === undefined || forceGet) { - var oldValue = getOption(optionName, cm, setCfg); - if (oldValue === true || oldValue === false) { - showConfirm(cm, ' ' + (oldValue ? '' : 'no') + optionName); - } else { - showConfirm(cm, ' ' + optionName + '=' + oldValue); - } - } else { - setOption(optionName, value, cm, setCfg); - } - }, - setlocal: function (cm, params) { - // setCfg is passed through to setOption - params.setCfg = {scope: 'local'}; - this.set(cm, params); - }, - setglobal: function (cm, params) { - // setCfg is passed through to setOption - params.setCfg = {scope: 'global'}; - this.set(cm, params); - }, - registers: function(cm, params) { - var regArgs = params.args; - var registers = vimGlobalState.registerController.registers; - var regInfo = '----------Registers----------

    '; - if (!regArgs) { - for (var registerName in registers) { - var text = registers[registerName].toString(); - if (text.length) { - regInfo += '"' + registerName + ' ' + text + '
    '; - } - } - } else { - var registerName; - regArgs = regArgs.join(''); - for (var i = 0; i < regArgs.length; i++) { - registerName = regArgs.charAt(i); - if (!vimGlobalState.registerController.isValidRegister(registerName)) { - continue; - } - var register = registers[registerName] || new Register(); - regInfo += '"' + registerName + ' ' + register.toString() + '
    '; - } - } - showConfirm(cm, regInfo); - }, - sort: function(cm, params) { - var reverse, ignoreCase, unique, number; - function parseArgs() { - if (params.argString) { - var args = new CodeMirror.StringStream(params.argString); - if (args.eat('!')) { reverse = true; } - if (args.eol()) { return; } - if (!args.eatSpace()) { return 'Invalid arguments'; } - var opts = args.match(/[a-z]+/); - if (opts) { - opts = opts[0]; - ignoreCase = opts.indexOf('i') != -1; - unique = opts.indexOf('u') != -1; - var decimal = opts.indexOf('d') != -1 && 1; - var hex = opts.indexOf('x') != -1 && 1; - var octal = opts.indexOf('o') != -1 && 1; - if (decimal + hex + octal > 1) { return 'Invalid arguments'; } - number = decimal && 'decimal' || hex && 'hex' || octal && 'octal'; - } - if (args.match(/\/.*\//)) { return 'patterns not supported'; } - } - } - var err = parseArgs(); - if (err) { - showConfirm(cm, err + ': ' + params.argString); - return; - } - var lineStart = params.line || cm.firstLine(); - var lineEnd = params.lineEnd || params.line || cm.lastLine(); - if (lineStart == lineEnd) { return; } - var curStart = Pos(lineStart, 0); - var curEnd = Pos(lineEnd, lineLength(cm, lineEnd)); - var text = cm.getRange(curStart, curEnd).split('\n'); - var numberRegex = (number == 'decimal') ? /(-?)([\d]+)/ : - (number == 'hex') ? /(-?)(?:0x)?([0-9a-f]+)/i : - (number == 'octal') ? /([0-7]+)/ : null; - var radix = (number == 'decimal') ? 10 : (number == 'hex') ? 16 : (number == 'octal') ? 8 : null; - var numPart = [], textPart = []; - if (number) { - for (var i = 0; i < text.length; i++) { - if (numberRegex.exec(text[i])) { - numPart.push(text[i]); - } else { - textPart.push(text[i]); - } - } - } else { - textPart = text; - } - function compareFn(a, b) { - if (reverse) { var tmp; tmp = a; a = b; b = tmp; } - if (ignoreCase) { a = a.toLowerCase(); b = b.toLowerCase(); } - var anum = number && numberRegex.exec(a); - var bnum = number && numberRegex.exec(b); - if (!anum) { return a < b ? -1 : 1; } - anum = parseInt((anum[1] + anum[2]).toLowerCase(), radix); - bnum = parseInt((bnum[1] + bnum[2]).toLowerCase(), radix); - return anum - bnum; - } - numPart.sort(compareFn); - textPart.sort(compareFn); - text = (!reverse) ? textPart.concat(numPart) : numPart.concat(textPart); - if (unique) { // Remove duplicate lines - var textOld = text; - var lastLine; - text = []; - for (var i = 0; i < textOld.length; i++) { - if (textOld[i] != lastLine) { - text.push(textOld[i]); - } - lastLine = textOld[i]; - } - } - cm.replaceRange(text.join('\n'), curStart, curEnd); - }, - global: function(cm, params) { - // a global command is of the form - // :[range]g/pattern/[cmd] - // argString holds the string /pattern/[cmd] - var argString = params.argString; - if (!argString) { - showConfirm(cm, 'Regular Expression missing from global'); - return; - } - // range is specified here - var lineStart = (params.line !== undefined) ? params.line : cm.firstLine(); - var lineEnd = params.lineEnd || params.line || cm.lastLine(); - // get the tokens from argString - var tokens = splitBySlash(argString); - var regexPart = argString, cmd; - if (tokens.length) { - regexPart = tokens[0]; - cmd = tokens.slice(1, tokens.length).join('/'); - } - if (regexPart) { - // If regex part is empty, then use the previous query. Otherwise - // use the regex part as the new query. - try { - updateSearchQuery(cm, regexPart, true /** ignoreCase */, - true /** smartCase */); - } catch (e) { - showConfirm(cm, 'Invalid regex: ' + regexPart); - return; - } - } - // now that we have the regexPart, search for regex matches in the - // specified range of lines - var query = getSearchState(cm).getQuery(); - var matchedLines = [], content = ''; - for (var i = lineStart; i <= lineEnd; i++) { - var matched = query.test(cm.getLine(i)); - if (matched) { - matchedLines.push(i+1); - content+= cm.getLine(i) + '
    '; - } - } - // if there is no [cmd], just display the list of matched lines - if (!cmd) { - showConfirm(cm, content); - return; - } - var index = 0; - var nextCommand = function() { - if (index < matchedLines.length) { - var command = matchedLines[index] + cmd; - exCommandDispatcher.processCommand(cm, command, { - callback: nextCommand - }); - } - index++; - }; - nextCommand(); - }, - substitute: function(cm, params) { - if (!cm.getSearchCursor) { - throw new Error('Search feature not available. Requires searchcursor.js or ' + - 'any other getSearchCursor implementation.'); - } - var argString = params.argString; - var tokens = argString ? splitBySlash(argString) : []; - var regexPart, replacePart = '', trailing, flagsPart, count; - var confirm = false; // Whether to confirm each replace. - var global = false; // True to replace all instances on a line, false to replace only 1. - if (tokens.length) { - regexPart = tokens[0]; - replacePart = tokens[1]; - if (replacePart !== undefined) { - if (getOption('pcre')) { - replacePart = unescapeRegexReplace(replacePart); - } else { - replacePart = translateRegexReplace(replacePart); - } - vimGlobalState.lastSubstituteReplacePart = replacePart; - } - trailing = tokens[2] ? tokens[2].split(' ') : []; - } else { - // either the argString is empty or its of the form ' hello/world' - // actually splitBySlash returns a list of tokens - // only if the string starts with a '/' - if (argString && argString.length) { - showConfirm(cm, 'Substitutions should be of the form ' + - ':s/pattern/replace/'); - return; - } - } - // After the 3rd slash, we can have flags followed by a space followed - // by count. - if (trailing) { - flagsPart = trailing[0]; - count = parseInt(trailing[1]); - if (flagsPart) { - if (flagsPart.indexOf('c') != -1) { - confirm = true; - flagsPart.replace('c', ''); - } - if (flagsPart.indexOf('g') != -1) { - global = true; - flagsPart.replace('g', ''); - } - regexPart = regexPart + '/' + flagsPart; - } - } - if (regexPart) { - // If regex part is empty, then use the previous query. Otherwise use - // the regex part as the new query. - try { - updateSearchQuery(cm, regexPart, true /** ignoreCase */, - true /** smartCase */); - } catch (e) { - showConfirm(cm, 'Invalid regex: ' + regexPart); - return; - } - } - replacePart = replacePart || vimGlobalState.lastSubstituteReplacePart; - if (replacePart === undefined) { - showConfirm(cm, 'No previous substitute regular expression'); - return; - } - var state = getSearchState(cm); - var query = state.getQuery(); - var lineStart = (params.line !== undefined) ? params.line : cm.getCursor().line; - var lineEnd = params.lineEnd || lineStart; - if (lineStart == cm.firstLine() && lineEnd == cm.lastLine()) { - lineEnd = Infinity; - } - if (count) { - lineStart = lineEnd; - lineEnd = lineStart + count - 1; - } - var startPos = clipCursorToContent(cm, Pos(lineStart, 0)); - var cursor = cm.getSearchCursor(query, startPos); - doReplace(cm, confirm, global, lineStart, lineEnd, cursor, query, replacePart, params.callback); - }, - redo: CodeMirror.commands.redo, - undo: CodeMirror.commands.undo, - write: function(cm) { - if (CodeMirror.commands.save) { - // If a save command is defined, call it. - CodeMirror.commands.save(cm); - } else if (cm.save) { - // Saves to text area if no save command is defined and cm.save() is available. - cm.save(); - } - }, - nohlsearch: function(cm) { - clearSearchHighlight(cm); - }, - yank: function (cm) { - var cur = copyCursor(cm.getCursor()); - var line = cur.line; - var lineText = cm.getLine(line); - vimGlobalState.registerController.pushText( - '0', 'yank', lineText, true, true); - }, - delmarks: function(cm, params) { - if (!params.argString || !trim(params.argString)) { - showConfirm(cm, 'Argument required'); - return; - } - - var state = cm.state.vim; - var stream = new CodeMirror.StringStream(trim(params.argString)); - while (!stream.eol()) { - stream.eatSpace(); - - // Record the streams position at the beginning of the loop for use - // in error messages. - var count = stream.pos; - - if (!stream.match(/[a-zA-Z]/, false)) { - showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); - return; - } - - var sym = stream.next(); - // Check if this symbol is part of a range - if (stream.match('-', true)) { - // This symbol is part of a range. - - // The range must terminate at an alphabetic character. - if (!stream.match(/[a-zA-Z]/, false)) { - showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); - return; - } - - var startMark = sym; - var finishMark = stream.next(); - // The range must terminate at an alphabetic character which - // shares the same case as the start of the range. - if (isLowerCase(startMark) && isLowerCase(finishMark) || - isUpperCase(startMark) && isUpperCase(finishMark)) { - var start = startMark.charCodeAt(0); - var finish = finishMark.charCodeAt(0); - if (start >= finish) { - showConfirm(cm, 'Invalid argument: ' + params.argString.substring(count)); - return; - } - - // Because marks are always ASCII values, and we have - // determined that they are the same case, we can use - // their char codes to iterate through the defined range. - for (var j = 0; j <= finish - start; j++) { - var mark = String.fromCharCode(start + j); - delete state.marks[mark]; - } - } else { - showConfirm(cm, 'Invalid argument: ' + startMark + '-'); - return; - } - } else { - // This symbol is a valid mark, and is not part of a range. - delete state.marks[sym]; - } - } - } - }; - - var exCommandDispatcher = new ExCommandDispatcher(); - - /** - * @param {CodeMirror} cm CodeMirror instance we are in. - * @param {boolean} confirm Whether to confirm each replace. - * @param {Cursor} lineStart Line to start replacing from. - * @param {Cursor} lineEnd Line to stop replacing at. - * @param {RegExp} query Query for performing matches with. - * @param {string} replaceWith Text to replace matches with. May contain $1, - * $2, etc for replacing captured groups using Javascript replace. - * @param {function()} callback A callback for when the replace is done. - */ - function doReplace(cm, confirm, global, lineStart, lineEnd, searchCursor, query, - replaceWith, callback) { - // Set up all the functions. - cm.state.vim.exMode = true; - var done = false; - var lastPos = searchCursor.from(); - function replaceAll() { - cm.operation(function() { - while (!done) { - replace(); - next(); - } - stop(); - }); - } - function replace() { - var text = cm.getRange(searchCursor.from(), searchCursor.to()); - var newText = text.replace(query, replaceWith); - searchCursor.replace(newText); - } - function next() { - // The below only loops to skip over multiple occurrences on the same - // line when 'global' is not true. - while(searchCursor.findNext() && - isInRange(searchCursor.from(), lineStart, lineEnd)) { - if (!global && lastPos && searchCursor.from().line == lastPos.line) { - continue; - } - cm.scrollIntoView(searchCursor.from(), 30); - cm.setSelection(searchCursor.from(), searchCursor.to()); - lastPos = searchCursor.from(); - done = false; - return; - } - done = true; - } - function stop(close) { - if (close) { close(); } - cm.focus(); - if (lastPos) { - cm.setCursor(lastPos); - var vim = cm.state.vim; - vim.exMode = false; - vim.lastHPos = vim.lastHSPos = lastPos.ch; - } - if (callback) { callback(); } - } - function onPromptKeyDown(e, _value, close) { - // Swallow all keys. - CodeMirror.e_stop(e); - var keyName = CodeMirror.keyName(e); - switch (keyName) { - case 'Y': - replace(); next(); break; - case 'N': - next(); break; - case 'A': - // replaceAll contains a call to close of its own. We don't want it - // to fire too early or multiple times. - var savedCallback = callback; - callback = undefined; - cm.operation(replaceAll); - callback = savedCallback; - break; - case 'L': - replace(); - // fall through and exit. - case 'Q': - case 'Esc': - case 'Ctrl-C': - case 'Ctrl-[': - stop(close); - break; - } - if (done) { stop(close); } - return true; - } - - // Actually do replace. - next(); - if (done) { - showConfirm(cm, 'No matches for ' + query.source); - return; - } - if (!confirm) { - replaceAll(); - if (callback) { callback(); }; - return; - } - showPrompt(cm, { - prefix: 'replace with ' + replaceWith + ' (y/n/a/q/l)', - onKeyDown: onPromptKeyDown - }); - } - - CodeMirror.keyMap.vim = { - attach: attachVimMap, - detach: detachVimMap, - call: cmKey - }; - - function exitInsertMode(cm) { - var vim = cm.state.vim; - var macroModeState = vimGlobalState.macroModeState; - var insertModeChangeRegister = vimGlobalState.registerController.getRegister('.'); - var isPlaying = macroModeState.isPlaying; - var lastChange = macroModeState.lastInsertModeChanges; - // In case of visual block, the insertModeChanges are not saved as a - // single word, so we convert them to a single word - // so as to update the ". register as expected in real vim. - var text = []; - if (!isPlaying) { - var selLength = lastChange.inVisualBlock ? vim.lastSelection.visualBlock.height : 1; - var changes = lastChange.changes; - var text = []; - var i = 0; - // In case of multiple selections in blockwise visual, - // the inserted text, for example: 'foo', is stored as - // 'f', 'f', InsertModeKey 'o', 'o', 'o', 'o'. (if you have a block with 2 lines). - // We push the contents of the changes array as per the following: - // 1. In case of InsertModeKey, just increment by 1. - // 2. In case of a character, jump by selLength (2 in the example). - while (i < changes.length) { - // This loop will convert 'ffoooo' to 'foo'. - text.push(changes[i]); - if (changes[i] instanceof InsertModeKey) { - i++; - } else { - i+= selLength; - } - } - lastChange.changes = text; - cm.off('change', onChange); - CodeMirror.off(cm.getInputField(), 'keydown', onKeyEventTargetKeyDown); - } - if (!isPlaying && vim.insertModeRepeat > 1) { - // Perform insert mode repeat for commands like 3,a and 3,o. - repeatLastEdit(cm, vim, vim.insertModeRepeat - 1, - true /** repeatForInsert */); - vim.lastEditInputState.repeatOverride = vim.insertModeRepeat; - } - delete vim.insertModeRepeat; - vim.insertMode = false; - cm.setCursor(cm.getCursor().line, cm.getCursor().ch-1); - cm.setOption('keyMap', 'vim'); - cm.setOption('disableInput', true); - cm.toggleOverwrite(false); // exit replace mode if we were in it. - // update the ". register before exiting insert mode - insertModeChangeRegister.setText(lastChange.changes.join('')); - CodeMirror.signal(cm, "vim-mode-change", {mode: "normal"}); - if (macroModeState.isRecording) { - logInsertModeChange(macroModeState); - } - } - - function _mapCommand(command) { - defaultKeymap.unshift(command); - } - - function mapCommand(keys, type, name, args, extra) { - var command = {keys: keys, type: type}; - command[type] = name; - command[type + "Args"] = args; - for (var key in extra) - command[key] = extra[key]; - _mapCommand(command); - } - - // The timeout in milliseconds for the two-character ESC keymap should be - // adjusted according to your typing speed to prevent false positives. - defineOption('insertModeEscKeysTimeout', 200, 'number'); - - CodeMirror.keyMap['vim-insert'] = { - // TODO: override navigation keys so that Esc will cancel automatic - // indentation from o, O, i_ - fallthrough: ['default'], - attach: attachVimMap, - detach: detachVimMap, - call: cmKey - }; - - CodeMirror.keyMap['vim-replace'] = { - 'Backspace': 'goCharLeft', - fallthrough: ['vim-insert'], - attach: attachVimMap, - detach: detachVimMap, - call: cmKey - }; - - function executeMacroRegister(cm, vim, macroModeState, registerName) { - var register = vimGlobalState.registerController.getRegister(registerName); - if (registerName == ':') { - // Read-only register containing last Ex command. - if (register.keyBuffer[0]) { - exCommandDispatcher.processCommand(cm, register.keyBuffer[0]); - } - macroModeState.isPlaying = false; - return; - } - var keyBuffer = register.keyBuffer; - var imc = 0; - macroModeState.isPlaying = true; - macroModeState.replaySearchQueries = register.searchQueries.slice(0); - for (var i = 0; i < keyBuffer.length; i++) { - var text = keyBuffer[i]; - var match, key; - while (text) { - // Pull off one command key, which is either a single character - // or a special sequence wrapped in '<' and '>', e.g. ''. - match = (/<\w+-.+?>|<\w+>|./).exec(text); - key = match[0]; - text = text.substring(match.index + key.length); - CodeMirror.Vim.handleKey(cm, key, 'macro'); - if (vim.insertMode) { - var changes = register.insertModeChanges[imc++].changes; - vimGlobalState.macroModeState.lastInsertModeChanges.changes = - changes; - repeatInsertModeChanges(cm, changes, 1); - exitInsertMode(cm); - } - } - }; - macroModeState.isPlaying = false; - } - - function logKey(macroModeState, key) { - if (macroModeState.isPlaying) { return; } - var registerName = macroModeState.latestRegister; - var register = vimGlobalState.registerController.getRegister(registerName); - if (register) { - register.pushText(key); - } - } - - function logInsertModeChange(macroModeState) { - if (macroModeState.isPlaying) { return; } - var registerName = macroModeState.latestRegister; - var register = vimGlobalState.registerController.getRegister(registerName); - if (register && register.pushInsertModeChanges) { - register.pushInsertModeChanges(macroModeState.lastInsertModeChanges); - } - } - - function logSearchQuery(macroModeState, query) { - if (macroModeState.isPlaying) { return; } - var registerName = macroModeState.latestRegister; - var register = vimGlobalState.registerController.getRegister(registerName); - if (register && register.pushSearchQuery) { - register.pushSearchQuery(query); - } - } - - /** - * Listens for changes made in insert mode. - * Should only be active in insert mode. - */ - function onChange(_cm, changeObj) { - var macroModeState = vimGlobalState.macroModeState; - var lastChange = macroModeState.lastInsertModeChanges; - if (!macroModeState.isPlaying) { - while(changeObj) { - lastChange.expectCursorActivityForChange = true; - if (changeObj.origin == '+input' || changeObj.origin == 'paste' - || changeObj.origin === undefined /* only in testing */) { - var text = changeObj.text.join('\n'); - if (lastChange.maybeReset) { - lastChange.changes = []; - lastChange.maybeReset = false; - } - lastChange.changes.push(text); - } - // Change objects may be chained with next. - changeObj = changeObj.next; - } - } - } - - /** - * Listens for any kind of cursor activity on CodeMirror. - */ - function onCursorActivity(cm) { - var vim = cm.state.vim; - if (vim.insertMode) { - // Tracking cursor activity in insert mode (for macro support). - var macroModeState = vimGlobalState.macroModeState; - if (macroModeState.isPlaying) { return; } - var lastChange = macroModeState.lastInsertModeChanges; - if (lastChange.expectCursorActivityForChange) { - lastChange.expectCursorActivityForChange = false; - } else { - // Cursor moved outside the context of an edit. Reset the change. - lastChange.maybeReset = true; - } - } else if (!cm.curOp.isVimOp) { - handleExternalSelection(cm, vim); - } - if (vim.visualMode) { - updateFakeCursor(cm); - } - } - function updateFakeCursor(cm) { - var vim = cm.state.vim; - var from = clipCursorToContent(cm, copyCursor(vim.sel.head)); - var to = offsetCursor(from, 0, 1); - if (vim.fakeCursor) { - vim.fakeCursor.clear(); - } - vim.fakeCursor = cm.markText(from, to, {className: 'cm-animate-fat-cursor'}); - } - function handleExternalSelection(cm, vim) { - var anchor = cm.getCursor('anchor'); - var head = cm.getCursor('head'); - // Enter or exit visual mode to match mouse selection. - if (vim.visualMode && !cm.somethingSelected()) { - exitVisualMode(cm, false); - } else if (!vim.visualMode && !vim.insertMode && cm.somethingSelected()) { - vim.visualMode = true; - vim.visualLine = false; - CodeMirror.signal(cm, "vim-mode-change", {mode: "visual"}); - } - if (vim.visualMode) { - // Bind CodeMirror selection model to vim selection model. - // Mouse selections are considered visual characterwise. - var headOffset = !cursorIsBefore(head, anchor) ? -1 : 0; - var anchorOffset = cursorIsBefore(head, anchor) ? -1 : 0; - head = offsetCursor(head, 0, headOffset); - anchor = offsetCursor(anchor, 0, anchorOffset); - vim.sel = { - anchor: anchor, - head: head - }; - updateMark(cm, vim, '<', cursorMin(head, anchor)); - updateMark(cm, vim, '>', cursorMax(head, anchor)); - } else if (!vim.insertMode) { - // Reset lastHPos if selection was modified by something outside of vim mode e.g. by mouse. - vim.lastHPos = cm.getCursor().ch; - } - } - - /** Wrapper for special keys pressed in insert mode */ - function InsertModeKey(keyName) { - this.keyName = keyName; - } - - /** - * Handles raw key down events from the text area. - * - Should only be active in insert mode. - * - For recording deletes in insert mode. - */ - function onKeyEventTargetKeyDown(e) { - var macroModeState = vimGlobalState.macroModeState; - var lastChange = macroModeState.lastInsertModeChanges; - var keyName = CodeMirror.keyName(e); - if (!keyName) { return; } - function onKeyFound() { - if (lastChange.maybeReset) { - lastChange.changes = []; - lastChange.maybeReset = false; - } - lastChange.changes.push(new InsertModeKey(keyName)); - return true; - } - if (keyName.indexOf('Delete') != -1 || keyName.indexOf('Backspace') != -1) { - CodeMirror.lookupKey(keyName, 'vim-insert', onKeyFound); - } - } - - /** - * Repeats the last edit, which includes exactly 1 command and at most 1 - * insert. Operator and motion commands are read from lastEditInputState, - * while action commands are read from lastEditActionCommand. - * - * If repeatForInsert is true, then the function was called by - * exitInsertMode to repeat the insert mode changes the user just made. The - * corresponding enterInsertMode call was made with a count. - */ - function repeatLastEdit(cm, vim, repeat, repeatForInsert) { - var macroModeState = vimGlobalState.macroModeState; - macroModeState.isPlaying = true; - var isAction = !!vim.lastEditActionCommand; - var cachedInputState = vim.inputState; - function repeatCommand() { - if (isAction) { - commandDispatcher.processAction(cm, vim, vim.lastEditActionCommand); - } else { - commandDispatcher.evalInput(cm, vim); - } - } - function repeatInsert(repeat) { - if (macroModeState.lastInsertModeChanges.changes.length > 0) { - // For some reason, repeat cw in desktop VIM does not repeat - // insert mode changes. Will conform to that behavior. - repeat = !vim.lastEditActionCommand ? 1 : repeat; - var changeObject = macroModeState.lastInsertModeChanges; - repeatInsertModeChanges(cm, changeObject.changes, repeat); - } - } - vim.inputState = vim.lastEditInputState; - if (isAction && vim.lastEditActionCommand.interlaceInsertRepeat) { - // o and O repeat have to be interlaced with insert repeats so that the - // insertions appear on separate lines instead of the last line. - for (var i = 0; i < repeat; i++) { - repeatCommand(); - repeatInsert(1); - } - } else { - if (!repeatForInsert) { - // Hack to get the cursor to end up at the right place. If I is - // repeated in insert mode repeat, cursor will be 1 insert - // change set left of where it should be. - repeatCommand(); - } - repeatInsert(repeat); - } - vim.inputState = cachedInputState; - if (vim.insertMode && !repeatForInsert) { - // Don't exit insert mode twice. If repeatForInsert is set, then we - // were called by an exitInsertMode call lower on the stack. - exitInsertMode(cm); - } - macroModeState.isPlaying = false; - }; - - function repeatInsertModeChanges(cm, changes, repeat) { - function keyHandler(binding) { - if (typeof binding == 'string') { - CodeMirror.commands[binding](cm); - } else { - binding(cm); - } - return true; - } - var head = cm.getCursor('head'); - var inVisualBlock = vimGlobalState.macroModeState.lastInsertModeChanges.inVisualBlock; - if (inVisualBlock) { - // Set up block selection again for repeating the changes. - var vim = cm.state.vim; - var lastSel = vim.lastSelection; - var offset = getOffset(lastSel.anchor, lastSel.head); - selectForInsert(cm, head, offset.line + 1); - repeat = cm.listSelections().length; - cm.setCursor(head); - } - for (var i = 0; i < repeat; i++) { - if (inVisualBlock) { - cm.setCursor(offsetCursor(head, i, 0)); - } - for (var j = 0; j < changes.length; j++) { - var change = changes[j]; - if (change instanceof InsertModeKey) { - CodeMirror.lookupKey(change.keyName, 'vim-insert', keyHandler); - } else { - var cur = cm.getCursor(); - cm.replaceRange(change, cur, cur); - } - } - } - if (inVisualBlock) { - cm.setCursor(offsetCursor(head, 0, 1)); - } - } - - resetVimGlobalState(); - return vimApi; - }; - // Initialize Vim and make it available as an API. - CodeMirror.Vim = Vim(); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/lib/codemirror.css b/backend/_pv_1_3_5/static/codemirror/lib/codemirror.css deleted file mode 100755 index 2a6a26228..000000000 --- a/backend/_pv_1_3_5/static/codemirror/lib/codemirror.css +++ /dev/null @@ -1,341 +0,0 @@ -/* BASICS */ - -.CodeMirror { - /* Set height, width, borders, and global font properties here */ - font-family: monospace; - height: 300px; - color: black; -} - -/* PADDING */ - -.CodeMirror-lines { - padding: 4px 0; /* Vertical padding around content */ -} -.CodeMirror pre { - padding: 0 4px; /* Horizontal padding of content */ -} - -.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { - background-color: white; /* The little square between H and V scrollbars */ -} - -/* GUTTER */ - -.CodeMirror-gutters { - border-right: 1px solid #ddd; - background-color: #f7f7f7; - white-space: nowrap; -} -.CodeMirror-linenumbers {} -.CodeMirror-linenumber { - padding: 0 3px 0 5px; - min-width: 20px; - text-align: right; - color: #999; - white-space: nowrap; -} - -.CodeMirror-guttermarker { color: black; } -.CodeMirror-guttermarker-subtle { color: #999; } - -/* CURSOR */ - -.CodeMirror-cursor { - border-left: 1px solid black; - border-right: none; - width: 0; -} -/* Shown when moving in bi-directional text */ -.CodeMirror div.CodeMirror-secondarycursor { - border-left: 1px solid silver; -} -.cm-fat-cursor .CodeMirror-cursor { - width: auto; - border: 0 !important; - background: #7e7; -} -.cm-fat-cursor div.CodeMirror-cursors { - z-index: 1; -} - -.cm-animate-fat-cursor { - width: auto; - border: 0; - -webkit-animation: blink 1.06s steps(1) infinite; - -moz-animation: blink 1.06s steps(1) infinite; - animation: blink 1.06s steps(1) infinite; - background-color: #7e7; -} -@-moz-keyframes blink { - 0% {} - 50% { background-color: transparent; } - 100% {} -} -@-webkit-keyframes blink { - 0% {} - 50% { background-color: transparent; } - 100% {} -} -@keyframes blink { - 0% {} - 50% { background-color: transparent; } - 100% {} -} - -/* Can style cursor different in overwrite (non-insert) mode */ -.CodeMirror-overwrite .CodeMirror-cursor {} - -.cm-tab { display: inline-block; text-decoration: inherit; } - -.CodeMirror-rulers { - position: absolute; - left: 0; right: 0; top: -50px; bottom: -20px; - overflow: hidden; -} -.CodeMirror-ruler { - border-left: 1px solid #ccc; - top: 0; bottom: 0; - position: absolute; -} - -/* DEFAULT THEME */ - -.cm-s-default .cm-header {color: blue;} -.cm-s-default .cm-quote {color: #090;} -.cm-negative {color: #d44;} -.cm-positive {color: #292;} -.cm-header, .cm-strong {font-weight: bold;} -.cm-em {font-style: italic;} -.cm-link {text-decoration: underline;} -.cm-strikethrough {text-decoration: line-through;} - -.cm-s-default .cm-keyword {color: #708;} -.cm-s-default .cm-atom {color: #219;} -.cm-s-default .cm-number {color: #164;} -.cm-s-default .cm-def {color: #00f;} -.cm-s-default .cm-variable, -.cm-s-default .cm-punctuation, -.cm-s-default .cm-property, -.cm-s-default .cm-operator {} -.cm-s-default .cm-variable-2 {color: #05a;} -.cm-s-default .cm-variable-3 {color: #085;} -.cm-s-default .cm-comment {color: #a50;} -.cm-s-default .cm-string {color: #a11;} -.cm-s-default .cm-string-2 {color: #f50;} -.cm-s-default .cm-meta {color: #555;} -.cm-s-default .cm-qualifier {color: #555;} -.cm-s-default .cm-builtin {color: #30a;} -.cm-s-default .cm-bracket {color: #997;} -.cm-s-default .cm-tag {color: #170;} -.cm-s-default .cm-attribute {color: #00c;} -.cm-s-default .cm-hr {color: #999;} -.cm-s-default .cm-link {color: #00c;} - -.cm-s-default .cm-error {color: #f00;} -.cm-invalidchar {color: #f00;} - -.CodeMirror-composing { border-bottom: 2px solid; } - -/* Default styles for common addons */ - -div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;} -div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;} -.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); } -.CodeMirror-activeline-background {background: #e8f2ff;} - -/* STOP */ - -/* The rest of this file contains styles related to the mechanics of - the editor. You probably shouldn't touch them. */ - -.CodeMirror { - position: relative; - overflow: hidden; - background: white; -} - -.CodeMirror-scroll { - overflow: scroll !important; /* Things will break if this is overridden */ - /* 30px is the magic margin used to hide the element's real scrollbars */ - /* See overflow: hidden in .CodeMirror */ - margin-bottom: -30px; margin-right: -30px; - padding-bottom: 30px; - height: 100%; - outline: none; /* Prevent dragging from highlighting the element */ - position: relative; -} -.CodeMirror-sizer { - position: relative; - border-right: 30px solid transparent; -} - -/* The fake, visible scrollbars. Used to force redraw during scrolling - before actual scrolling happens, thus preventing shaking and - flickering artifacts. */ -.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { - position: absolute; - z-index: 6; - display: none; -} -.CodeMirror-vscrollbar { - right: 0; top: 0; - overflow-x: hidden; - overflow-y: scroll; -} -.CodeMirror-hscrollbar { - bottom: 0; left: 0; - overflow-y: hidden; - overflow-x: scroll; -} -.CodeMirror-scrollbar-filler { - right: 0; bottom: 0; -} -.CodeMirror-gutter-filler { - left: 0; bottom: 0; -} - -.CodeMirror-gutters { - position: absolute; left: 0; top: 0; - min-height: 100%; - z-index: 3; -} -.CodeMirror-gutter { - white-space: normal; - height: 100%; - display: inline-block; - vertical-align: top; - margin-bottom: -30px; -} -.CodeMirror-gutter-wrapper { - position: absolute; - z-index: 4; - background: none !important; - border: none !important; -} -.CodeMirror-gutter-background { - position: absolute; - top: 0; bottom: 0; - z-index: 4; -} -.CodeMirror-gutter-elt { - position: absolute; - cursor: default; - z-index: 4; -} -.CodeMirror-gutter-wrapper { - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; -} - -.CodeMirror-lines { - cursor: text; - min-height: 1px; /* prevents collapsing before first draw */ -} -.CodeMirror pre { - /* Reset some styles that the rest of the page might have set */ - -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; - border-width: 0; - background: transparent; - font-family: inherit; - font-size: inherit; - margin: 0; - white-space: pre; - word-wrap: normal; - line-height: inherit; - color: inherit; - z-index: 2; - position: relative; - overflow: visible; - -webkit-tap-highlight-color: transparent; - -webkit-font-variant-ligatures: contextual; - font-variant-ligatures: contextual; -} -.CodeMirror-wrap pre { - word-wrap: break-word; - white-space: pre-wrap; - word-break: normal; -} - -.CodeMirror-linebackground { - position: absolute; - left: 0; right: 0; top: 0; bottom: 0; - z-index: 0; -} - -.CodeMirror-linewidget { - position: relative; - z-index: 2; - overflow: auto; -} - -.CodeMirror-widget {} - -.CodeMirror-code { - outline: none; -} - -/* Force content-box sizing for the elements where we expect it */ -.CodeMirror-scroll, -.CodeMirror-sizer, -.CodeMirror-gutter, -.CodeMirror-gutters, -.CodeMirror-linenumber { - -moz-box-sizing: content-box; - box-sizing: content-box; -} - -.CodeMirror-measure { - position: absolute; - width: 100%; - height: 0; - overflow: hidden; - visibility: hidden; -} - -.CodeMirror-cursor { - position: absolute; - pointer-events: none; -} -.CodeMirror-measure pre { position: static; } - -div.CodeMirror-cursors { - visibility: hidden; - position: relative; - z-index: 3; -} -div.CodeMirror-dragcursors { - visibility: visible; -} - -.CodeMirror-focused div.CodeMirror-cursors { - visibility: visible; -} - -.CodeMirror-selected { background: #d9d9d9; } -.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; } -.CodeMirror-crosshair { cursor: crosshair; } -.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; } -.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; } - -.cm-searching { - background: #ffa; - background: rgba(255, 255, 0, .4); -} - -/* Used to force a border model for a node */ -.cm-force-border { padding-right: .1px; } - -@media print { - /* Hide the cursor when printing */ - .CodeMirror div.CodeMirror-cursors { - visibility: hidden; - } -} - -/* See issue #2901 */ -.cm-tab-wrap-hack:after { content: ''; } - -/* Help users use markselection to safely style text background */ -span.CodeMirror-selectedtext { background: none; } diff --git a/backend/_pv_1_3_5/static/codemirror/lib/codemirror.js b/backend/_pv_1_3_5/static/codemirror/lib/codemirror.js deleted file mode 100755 index 3e0cc2b24..000000000 --- a/backend/_pv_1_3_5/static/codemirror/lib/codemirror.js +++ /dev/null @@ -1,9113 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// This is CodeMirror (http://codemirror.net), a code editor -// implemented in JavaScript on top of the browser's DOM. -// -// You can find some technical background for some of the code below -// at http://marijnhaverbeke.nl/blog/#cm-internals . - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global.CodeMirror = factory()); -}(this, (function () { 'use strict'; - -// Kludges for bugs and behavior differences that can't be feature -// detected are enabled based on userAgent etc sniffing. -var userAgent = navigator.userAgent -var platform = navigator.platform - -var gecko = /gecko\/\d/i.test(userAgent) -var ie_upto10 = /MSIE \d/.test(userAgent) -var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent) -var ie = ie_upto10 || ie_11up -var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : ie_11up[1]) -var webkit = /WebKit\//.test(userAgent) -var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent) -var chrome = /Chrome\//.test(userAgent) -var presto = /Opera\//.test(userAgent) -var safari = /Apple Computer/.test(navigator.vendor) -var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent) -var phantom = /PhantomJS/.test(userAgent) - -var ios = /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent) -// This is woefully incomplete. Suggestions for alternative methods welcome. -var mobile = ios || /Android|webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent) -var mac = ios || /Mac/.test(platform) -var chromeOS = /\bCrOS\b/.test(userAgent) -var windows = /win/i.test(platform) - -var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/) -if (presto_version) { presto_version = Number(presto_version[1]) } -if (presto_version && presto_version >= 15) { presto = false; webkit = true } -// Some browsers use the wrong event properties to signal cmd/ctrl on OS X -var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11)) -var captureRightClick = gecko || (ie && ie_version >= 9) - -function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") } - -var rmClass = function(node, cls) { - var current = node.className - var match = classTest(cls).exec(current) - if (match) { - var after = current.slice(match.index + match[0].length) - node.className = current.slice(0, match.index) + (after ? match[1] + after : "") - } -} - -function removeChildren(e) { - for (var count = e.childNodes.length; count > 0; --count) - { e.removeChild(e.firstChild) } - return e -} - -function removeChildrenAndAdd(parent, e) { - return removeChildren(parent).appendChild(e) -} - -function elt(tag, content, className, style) { - var e = document.createElement(tag) - if (className) { e.className = className } - if (style) { e.style.cssText = style } - if (typeof content == "string") { e.appendChild(document.createTextNode(content)) } - else if (content) { for (var i = 0; i < content.length; ++i) { e.appendChild(content[i]) } } - return e -} - -var range -if (document.createRange) { range = function(node, start, end, endNode) { - var r = document.createRange() - r.setEnd(endNode || node, end) - r.setStart(node, start) - return r -} } -else { range = function(node, start, end) { - var r = document.body.createTextRange() - try { r.moveToElementText(node.parentNode) } - catch(e) { return r } - r.collapse(true) - r.moveEnd("character", end) - r.moveStart("character", start) - return r -} } - -function contains(parent, child) { - if (child.nodeType == 3) // Android browser always returns false when child is a textnode - { child = child.parentNode } - if (parent.contains) - { return parent.contains(child) } - do { - if (child.nodeType == 11) { child = child.host } - if (child == parent) { return true } - } while (child = child.parentNode) -} - -function activeElt() { - // IE and Edge may throw an "Unspecified Error" when accessing document.activeElement. - // IE < 10 will throw when accessed while the page is loading or in an iframe. - // IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable. - var activeElement - try { - activeElement = document.activeElement - } catch(e) { - activeElement = document.body || null - } - while (activeElement && activeElement.root && activeElement.root.activeElement) - { activeElement = activeElement.root.activeElement } - return activeElement -} - -function addClass(node, cls) { - var current = node.className - if (!classTest(cls).test(current)) { node.className += (current ? " " : "") + cls } -} -function joinClasses(a, b) { - var as = a.split(" ") - for (var i = 0; i < as.length; i++) - { if (as[i] && !classTest(as[i]).test(b)) { b += " " + as[i] } } - return b -} - -var selectInput = function(node) { node.select() } -if (ios) // Mobile Safari apparently has a bug where select() is broken. - { selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length } } -else if (ie) // Suppress mysterious IE10 errors - { selectInput = function(node) { try { node.select() } catch(_e) {} } } - -function bind(f) { - var args = Array.prototype.slice.call(arguments, 1) - return function(){return f.apply(null, args)} -} - -function copyObj(obj, target, overwrite) { - if (!target) { target = {} } - for (var prop in obj) - { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop))) - { target[prop] = obj[prop] } } - return target -} - -// Counts the column offset in a string, taking tabs into account. -// Used mostly to find indentation. -function countColumn(string, end, tabSize, startIndex, startValue) { - if (end == null) { - end = string.search(/[^\s\u00a0]/) - if (end == -1) { end = string.length } - } - for (var i = startIndex || 0, n = startValue || 0;;) { - var nextTab = string.indexOf("\t", i) - if (nextTab < 0 || nextTab >= end) - { return n + (end - i) } - n += nextTab - i - n += tabSize - (n % tabSize) - i = nextTab + 1 - } -} - -function Delayed() {this.id = null} -Delayed.prototype.set = function(ms, f) { - clearTimeout(this.id) - this.id = setTimeout(f, ms) -} - -function indexOf(array, elt) { - for (var i = 0; i < array.length; ++i) - { if (array[i] == elt) { return i } } - return -1 -} - -// Number of pixels added to scroller and sizer to hide scrollbar -var scrollerGap = 30 - -// Returned or thrown by various protocols to signal 'I'm not -// handling this'. -var Pass = {toString: function(){return "CodeMirror.Pass"}} - -// Reused option objects for setSelection & friends -var sel_dontScroll = {scroll: false}; -var sel_mouse = {origin: "*mouse"}; -var sel_move = {origin: "+move"}; -// The inverse of countColumn -- find the offset that corresponds to -// a particular column. -function findColumn(string, goal, tabSize) { - for (var pos = 0, col = 0;;) { - var nextTab = string.indexOf("\t", pos) - if (nextTab == -1) { nextTab = string.length } - var skipped = nextTab - pos - if (nextTab == string.length || col + skipped >= goal) - { return pos + Math.min(skipped, goal - col) } - col += nextTab - pos - col += tabSize - (col % tabSize) - pos = nextTab + 1 - if (col >= goal) { return pos } - } -} - -var spaceStrs = [""] -function spaceStr(n) { - while (spaceStrs.length <= n) - { spaceStrs.push(lst(spaceStrs) + " ") } - return spaceStrs[n] -} - -function lst(arr) { return arr[arr.length-1] } - -function map(array, f) { - var out = [] - for (var i = 0; i < array.length; i++) { out[i] = f(array[i], i) } - return out -} - -function insertSorted(array, value, score) { - var pos = 0, priority = score(value) - while (pos < array.length && score(array[pos]) <= priority) { pos++ } - array.splice(pos, 0, value) -} - -function nothing() {} - -function createObj(base, props) { - var inst - if (Object.create) { - inst = Object.create(base) - } else { - nothing.prototype = base - inst = new nothing() - } - if (props) { copyObj(props, inst) } - return inst -} - -var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/ -function isWordCharBasic(ch) { - return /\w/.test(ch) || ch > "\x80" && - (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)) -} -function isWordChar(ch, helper) { - if (!helper) { return isWordCharBasic(ch) } - if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) { return true } - return helper.test(ch) -} - -function isEmpty(obj) { - for (var n in obj) { if (obj.hasOwnProperty(n) && obj[n]) { return false } } - return true -} - -// Extending unicode characters. A series of a non-extending char + -// any number of extending chars is treated as a single unit as far -// as editing and measuring is concerned. This is not fully correct, -// since some scripts/fonts/browsers also treat other configurations -// of code points as a group. -var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/ -function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch) } - -// The display handles the DOM integration, both for input reading -// and content drawing. It holds references to DOM nodes and -// display-related state. - -function Display(place, doc, input) { - var d = this - this.input = input - - // Covers bottom-right square when both scrollbars are present. - d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler") - d.scrollbarFiller.setAttribute("cm-not-content", "true") - // Covers bottom of gutter when coverGutterNextToScrollbar is on - // and h scrollbar is present. - d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler") - d.gutterFiller.setAttribute("cm-not-content", "true") - // Will contain the actual code, positioned to cover the viewport. - d.lineDiv = elt("div", null, "CodeMirror-code") - // Elements are added to these to represent selection and cursors. - d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1") - d.cursorDiv = elt("div", null, "CodeMirror-cursors") - // A visibility: hidden element used to find the size of things. - d.measure = elt("div", null, "CodeMirror-measure") - // When lines outside of the viewport are measured, they are drawn in this. - d.lineMeasure = elt("div", null, "CodeMirror-measure") - // Wraps everything that needs to exist inside the vertically-padded coordinate system - d.lineSpace = elt("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv], - null, "position: relative; outline: none") - // Moved around its parent to cover visible view. - d.mover = elt("div", [elt("div", [d.lineSpace], "CodeMirror-lines")], null, "position: relative") - // Set to the height of the document, allowing scrolling. - d.sizer = elt("div", [d.mover], "CodeMirror-sizer") - d.sizerWidth = null - // Behavior of elts with overflow: auto and padding is - // inconsistent across browsers. This is used to ensure the - // scrollable area is big enough. - d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;") - // Will contain the gutters, if any. - d.gutters = elt("div", null, "CodeMirror-gutters") - d.lineGutter = null - // Actual scrollable element. - d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll") - d.scroller.setAttribute("tabIndex", "-1") - // The element in which the editor lives. - d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror") - - // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported) - if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0 } - if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true } - - if (place) { - if (place.appendChild) { place.appendChild(d.wrapper) } - else { place(d.wrapper) } - } - - // Current rendered range (may be bigger than the view window). - d.viewFrom = d.viewTo = doc.first - d.reportedViewFrom = d.reportedViewTo = doc.first - // Information about the rendered lines. - d.view = [] - d.renderedView = null - // Holds info about a single rendered line when it was rendered - // for measurement, while not in view. - d.externalMeasured = null - // Empty space (in pixels) above the view - d.viewOffset = 0 - d.lastWrapHeight = d.lastWrapWidth = 0 - d.updateLineNumbers = null - - d.nativeBarWidth = d.barHeight = d.barWidth = 0 - d.scrollbarsClipped = false - - // Used to only resize the line number gutter when necessary (when - // the amount of lines crosses a boundary that makes its width change) - d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null - // Set to true when a non-horizontal-scrolling line widget is - // added. As an optimization, line widget aligning is skipped when - // this is false. - d.alignWidgets = false - - d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null - - // Tracks the maximum line length so that the horizontal scrollbar - // can be kept static when scrolling. - d.maxLine = null - d.maxLineLength = 0 - d.maxLineChanged = false - - // Used for measuring wheel scrolling granularity - d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null - - // True when shift is held down. - d.shift = false - - // Used to track whether anything happened since the context menu - // was opened. - d.selForContextMenu = null - - d.activeTouch = null - - input.init(d) -} - -// Find the line object corresponding to the given line number. -function getLine(doc, n) { - n -= doc.first - if (n < 0 || n >= doc.size) { throw new Error("There is no line " + (n + doc.first) + " in the document.") } - var chunk = doc - while (!chunk.lines) { - for (var i = 0;; ++i) { - var child = chunk.children[i], sz = child.chunkSize() - if (n < sz) { chunk = child; break } - n -= sz - } - } - return chunk.lines[n] -} - -// Get the part of a document between two positions, as an array of -// strings. -function getBetween(doc, start, end) { - var out = [], n = start.line - doc.iter(start.line, end.line + 1, function (line) { - var text = line.text - if (n == end.line) { text = text.slice(0, end.ch) } - if (n == start.line) { text = text.slice(start.ch) } - out.push(text) - ++n - }) - return out -} -// Get the lines between from and to, as array of strings. -function getLines(doc, from, to) { - var out = [] - doc.iter(from, to, function (line) { out.push(line.text) }) // iter aborts when callback returns truthy value - return out -} - -// Update the height of a line, propagating the height change -// upwards to parent nodes. -function updateLineHeight(line, height) { - var diff = height - line.height - if (diff) { for (var n = line; n; n = n.parent) { n.height += diff } } -} - -// Given a line object, find its line number by walking up through -// its parent links. -function lineNo(line) { - if (line.parent == null) { return null } - var cur = line.parent, no = indexOf(cur.lines, line) - for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { - for (var i = 0;; ++i) { - if (chunk.children[i] == cur) { break } - no += chunk.children[i].chunkSize() - } - } - return no + cur.first -} - -// Find the line at the given vertical position, using the height -// information in the document tree. -function lineAtHeight(chunk, h) { - var n = chunk.first - outer: do { - for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) { - var child = chunk.children[i$1], ch = child.height - if (h < ch) { chunk = child; continue outer } - h -= ch - n += child.chunkSize() - } - return n - } while (!chunk.lines) - var i = 0 - for (; i < chunk.lines.length; ++i) { - var line = chunk.lines[i], lh = line.height - if (h < lh) { break } - h -= lh - } - return n + i -} - -function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size} - -function lineNumberFor(options, i) { - return String(options.lineNumberFormatter(i + options.firstLineNumber)) -} - -// A Pos instance represents a position within the text. -function Pos (line, ch) { - if (!(this instanceof Pos)) { return new Pos(line, ch) } - this.line = line; this.ch = ch -} - -// Compare two positions, return 0 if they are the same, a negative -// number when a is less, and a positive number otherwise. -function cmp(a, b) { return a.line - b.line || a.ch - b.ch } - -function copyPos(x) {return Pos(x.line, x.ch)} -function maxPos(a, b) { return cmp(a, b) < 0 ? b : a } -function minPos(a, b) { return cmp(a, b) < 0 ? a : b } - -// Most of the external API clips given positions to make sure they -// actually exist within the document. -function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1))} -function clipPos(doc, pos) { - if (pos.line < doc.first) { return Pos(doc.first, 0) } - var last = doc.first + doc.size - 1 - if (pos.line > last) { return Pos(last, getLine(doc, last).text.length) } - return clipToLen(pos, getLine(doc, pos.line).text.length) -} -function clipToLen(pos, linelen) { - var ch = pos.ch - if (ch == null || ch > linelen) { return Pos(pos.line, linelen) } - else if (ch < 0) { return Pos(pos.line, 0) } - else { return pos } -} -function clipPosArray(doc, array) { - var out = [] - for (var i = 0; i < array.length; i++) { out[i] = clipPos(doc, array[i]) } - return out -} - -// Optimize some code when these features are not used. -var sawReadOnlySpans = false; -var sawCollapsedSpans = false; -function seeReadOnlySpans() { - sawReadOnlySpans = true -} - -function seeCollapsedSpans() { - sawCollapsedSpans = true -} - -// TEXTMARKER SPANS - -function MarkedSpan(marker, from, to) { - this.marker = marker - this.from = from; this.to = to -} - -// Search an array of spans for a span matching the given marker. -function getMarkedSpanFor(spans, marker) { - if (spans) { for (var i = 0; i < spans.length; ++i) { - var span = spans[i] - if (span.marker == marker) { return span } - } } -} -// Remove a span from an array, returning undefined if no spans are -// left (we don't store arrays for lines without spans). -function removeMarkedSpan(spans, span) { - var r - for (var i = 0; i < spans.length; ++i) - { if (spans[i] != span) { (r || (r = [])).push(spans[i]) } } - return r -} -// Add a span to a line. -function addMarkedSpan(line, span) { - line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span] - span.marker.attachLine(line) -} - -// Used for the algorithm that adjusts markers for a change in the -// document. These functions cut an array of spans at a given -// character position, returning an array of remaining chunks (or -// undefined if nothing remains). -function markedSpansBefore(old, startCh, isInsert) { - var nw - if (old) { for (var i = 0; i < old.length; ++i) { - var span = old[i], marker = span.marker - var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh) - if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) { - var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh) - ;(nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to)) - } - } } - return nw -} -function markedSpansAfter(old, endCh, isInsert) { - var nw - if (old) { for (var i = 0; i < old.length; ++i) { - var span = old[i], marker = span.marker - var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh) - if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) { - var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh) - ;(nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh, - span.to == null ? null : span.to - endCh)) - } - } } - return nw -} - -// Given a change object, compute the new set of marker spans that -// cover the line in which the change took place. Removes spans -// entirely within the change, reconnects spans belonging to the -// same marker that appear on both sides of the change, and cuts off -// spans partially within the change. Returns an array of span -// arrays with one element for each line in (after) the change. -function stretchSpansOverChange(doc, change) { - if (change.full) { return null } - var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans - var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans - if (!oldFirst && !oldLast) { return null } - - var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0 - // Get the spans that 'stick out' on both sides - var first = markedSpansBefore(oldFirst, startCh, isInsert) - var last = markedSpansAfter(oldLast, endCh, isInsert) - - // Next, merge those two ends - var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0) - if (first) { - // Fix up .to properties of first - for (var i = 0; i < first.length; ++i) { - var span = first[i] - if (span.to == null) { - var found = getMarkedSpanFor(last, span.marker) - if (!found) { span.to = startCh } - else if (sameLine) { span.to = found.to == null ? null : found.to + offset } - } - } - } - if (last) { - // Fix up .from in last (or move them into first in case of sameLine) - for (var i$1 = 0; i$1 < last.length; ++i$1) { - var span$1 = last[i$1] - if (span$1.to != null) { span$1.to += offset } - if (span$1.from == null) { - var found$1 = getMarkedSpanFor(first, span$1.marker) - if (!found$1) { - span$1.from = offset - if (sameLine) { (first || (first = [])).push(span$1) } - } - } else { - span$1.from += offset - if (sameLine) { (first || (first = [])).push(span$1) } - } - } - } - // Make sure we didn't create any zero-length spans - if (first) { first = clearEmptySpans(first) } - if (last && last != first) { last = clearEmptySpans(last) } - - var newMarkers = [first] - if (!sameLine) { - // Fill gap with whole-line-spans - var gap = change.text.length - 2, gapMarkers - if (gap > 0 && first) - { for (var i$2 = 0; i$2 < first.length; ++i$2) - { if (first[i$2].to == null) - { (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)) } } } - for (var i$3 = 0; i$3 < gap; ++i$3) - { newMarkers.push(gapMarkers) } - newMarkers.push(last) - } - return newMarkers -} - -// Remove spans that are empty and don't have a clearWhenEmpty -// option of false. -function clearEmptySpans(spans) { - for (var i = 0; i < spans.length; ++i) { - var span = spans[i] - if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false) - { spans.splice(i--, 1) } - } - if (!spans.length) { return null } - return spans -} - -// Used to 'clip' out readOnly ranges when making a change. -function removeReadOnlyRanges(doc, from, to) { - var markers = null - doc.iter(from.line, to.line + 1, function (line) { - if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { - var mark = line.markedSpans[i].marker - if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) - { (markers || (markers = [])).push(mark) } - } } - }) - if (!markers) { return null } - var parts = [{from: from, to: to}] - for (var i = 0; i < markers.length; ++i) { - var mk = markers[i], m = mk.find(0) - for (var j = 0; j < parts.length; ++j) { - var p = parts[j] - if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { continue } - var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to) - if (dfrom < 0 || !mk.inclusiveLeft && !dfrom) - { newParts.push({from: p.from, to: m.from}) } - if (dto > 0 || !mk.inclusiveRight && !dto) - { newParts.push({from: m.to, to: p.to}) } - parts.splice.apply(parts, newParts) - j += newParts.length - 1 - } - } - return parts -} - -// Connect or disconnect spans from a line. -function detachMarkedSpans(line) { - var spans = line.markedSpans - if (!spans) { return } - for (var i = 0; i < spans.length; ++i) - { spans[i].marker.detachLine(line) } - line.markedSpans = null -} -function attachMarkedSpans(line, spans) { - if (!spans) { return } - for (var i = 0; i < spans.length; ++i) - { spans[i].marker.attachLine(line) } - line.markedSpans = spans -} - -// Helpers used when computing which overlapping collapsed span -// counts as the larger one. -function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0 } -function extraRight(marker) { return marker.inclusiveRight ? 1 : 0 } - -// Returns a number indicating which of two overlapping collapsed -// spans is larger (and thus includes the other). Falls back to -// comparing ids when the spans cover exactly the same range. -function compareCollapsedMarkers(a, b) { - var lenDiff = a.lines.length - b.lines.length - if (lenDiff != 0) { return lenDiff } - var aPos = a.find(), bPos = b.find() - var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b) - if (fromCmp) { return -fromCmp } - var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b) - if (toCmp) { return toCmp } - return b.id - a.id -} - -// Find out whether a line ends or starts in a collapsed span. If -// so, return the marker for that span. -function collapsedSpanAtSide(line, start) { - var sps = sawCollapsedSpans && line.markedSpans, found - if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { - sp = sps[i] - if (sp.marker.collapsed && (start ? sp.from : sp.to) == null && - (!found || compareCollapsedMarkers(found, sp.marker) < 0)) - { found = sp.marker } - } } - return found -} -function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) } -function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) } - -// Test whether there exists a collapsed span that partially -// overlaps (covers the start or end, but not both) of a new span. -// Such overlap is not allowed. -function conflictingCollapsedRange(doc, lineNo, from, to, marker) { - var line = getLine(doc, lineNo) - var sps = sawCollapsedSpans && line.markedSpans - if (sps) { for (var i = 0; i < sps.length; ++i) { - var sp = sps[i] - if (!sp.marker.collapsed) { continue } - var found = sp.marker.find(0) - var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker) - var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker) - if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { continue } - if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) || - fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0)) - { return true } - } } -} - -// A visual line is a line as drawn on the screen. Folding, for -// example, can cause multiple logical lines to appear on the same -// visual line. This finds the start of the visual line that the -// given line is part of (usually that is the line itself). -function visualLine(line) { - var merged - while (merged = collapsedSpanAtStart(line)) - { line = merged.find(-1, true).line } - return line -} - -// Returns an array of logical lines that continue the visual line -// started by the argument, or undefined if there are no such lines. -function visualLineContinued(line) { - var merged, lines - while (merged = collapsedSpanAtEnd(line)) { - line = merged.find(1, true).line - ;(lines || (lines = [])).push(line) - } - return lines -} - -// Get the line number of the start of the visual line that the -// given line number is part of. -function visualLineNo(doc, lineN) { - var line = getLine(doc, lineN), vis = visualLine(line) - if (line == vis) { return lineN } - return lineNo(vis) -} - -// Get the line number of the start of the next visual line after -// the given line. -function visualLineEndNo(doc, lineN) { - if (lineN > doc.lastLine()) { return lineN } - var line = getLine(doc, lineN), merged - if (!lineIsHidden(doc, line)) { return lineN } - while (merged = collapsedSpanAtEnd(line)) - { line = merged.find(1, true).line } - return lineNo(line) + 1 -} - -// Compute whether a line is hidden. Lines count as hidden when they -// are part of a visual line that starts with another line, or when -// they are entirely covered by collapsed, non-widget span. -function lineIsHidden(doc, line) { - var sps = sawCollapsedSpans && line.markedSpans - if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { - sp = sps[i] - if (!sp.marker.collapsed) { continue } - if (sp.from == null) { return true } - if (sp.marker.widgetNode) { continue } - if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp)) - { return true } - } } -} -function lineIsHiddenInner(doc, line, span) { - if (span.to == null) { - var end = span.marker.find(1, true) - return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker)) - } - if (span.marker.inclusiveRight && span.to == line.text.length) - { return true } - for (var sp = (void 0), i = 0; i < line.markedSpans.length; ++i) { - sp = line.markedSpans[i] - if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to && - (sp.to == null || sp.to != span.from) && - (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && - lineIsHiddenInner(doc, line, sp)) { return true } - } -} - -// Find the height above the given line. -function heightAtLine(lineObj) { - lineObj = visualLine(lineObj) - - var h = 0, chunk = lineObj.parent - for (var i = 0; i < chunk.lines.length; ++i) { - var line = chunk.lines[i] - if (line == lineObj) { break } - else { h += line.height } - } - for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { - for (var i$1 = 0; i$1 < p.children.length; ++i$1) { - var cur = p.children[i$1] - if (cur == chunk) { break } - else { h += cur.height } - } - } - return h -} - -// Compute the character length of a line, taking into account -// collapsed ranges (see markText) that might hide parts, and join -// other lines onto it. -function lineLength(line) { - if (line.height == 0) { return 0 } - var len = line.text.length, merged, cur = line - while (merged = collapsedSpanAtStart(cur)) { - var found = merged.find(0, true) - cur = found.from.line - len += found.from.ch - found.to.ch - } - cur = line - while (merged = collapsedSpanAtEnd(cur)) { - var found$1 = merged.find(0, true) - len -= cur.text.length - found$1.from.ch - cur = found$1.to.line - len += cur.text.length - found$1.to.ch - } - return len -} - -// Find the longest line in the document. -function findMaxLine(cm) { - var d = cm.display, doc = cm.doc - d.maxLine = getLine(doc, doc.first) - d.maxLineLength = lineLength(d.maxLine) - d.maxLineChanged = true - doc.iter(function (line) { - var len = lineLength(line) - if (len > d.maxLineLength) { - d.maxLineLength = len - d.maxLine = line - } - }) -} - -// BIDI HELPERS - -function iterateBidiSections(order, from, to, f) { - if (!order) { return f(from, to, "ltr") } - var found = false - for (var i = 0; i < order.length; ++i) { - var part = order[i] - if (part.from < to && part.to > from || from == to && part.to == from) { - f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr") - found = true - } - } - if (!found) { f(from, to, "ltr") } -} - -function bidiLeft(part) { return part.level % 2 ? part.to : part.from } -function bidiRight(part) { return part.level % 2 ? part.from : part.to } - -function lineLeft(line) { var order = getOrder(line); return order ? bidiLeft(order[0]) : 0 } -function lineRight(line) { - var order = getOrder(line) - if (!order) { return line.text.length } - return bidiRight(lst(order)) -} - -function compareBidiLevel(order, a, b) { - var linedir = order[0].level - if (a == linedir) { return true } - if (b == linedir) { return false } - return a < b -} - -var bidiOther = null -function getBidiPartAt(order, pos) { - var found - bidiOther = null - for (var i = 0; i < order.length; ++i) { - var cur = order[i] - if (cur.from < pos && cur.to > pos) { return i } - if ((cur.from == pos || cur.to == pos)) { - if (found == null) { - found = i - } else if (compareBidiLevel(order, cur.level, order[found].level)) { - if (cur.from != cur.to) { bidiOther = found } - return i - } else { - if (cur.from != cur.to) { bidiOther = i } - return found - } - } - } - return found -} - -function moveInLine(line, pos, dir, byUnit) { - if (!byUnit) { return pos + dir } - do { pos += dir } - while (pos > 0 && isExtendingChar(line.text.charAt(pos))) - return pos -} - -// This is needed in order to move 'visually' through bi-directional -// text -- i.e., pressing left should make the cursor go left, even -// when in RTL text. The tricky part is the 'jumps', where RTL and -// LTR text touch each other. This often requires the cursor offset -// to move more than one unit, in order to visually move one unit. -function moveVisually(line, start, dir, byUnit) { - var bidi = getOrder(line) - if (!bidi) { return moveLogically(line, start, dir, byUnit) } - var pos = getBidiPartAt(bidi, start), part = bidi[pos] - var target = moveInLine(line, start, part.level % 2 ? -dir : dir, byUnit) - - for (;;) { - if (target > part.from && target < part.to) { return target } - if (target == part.from || target == part.to) { - if (getBidiPartAt(bidi, target) == pos) { return target } - part = bidi[pos += dir] - return (dir > 0) == part.level % 2 ? part.to : part.from - } else { - part = bidi[pos += dir] - if (!part) { return null } - if ((dir > 0) == part.level % 2) - { target = moveInLine(line, part.to, -1, byUnit) } - else - { target = moveInLine(line, part.from, 1, byUnit) } - } - } -} - -function moveLogically(line, start, dir, byUnit) { - var target = start + dir - if (byUnit) { while (target > 0 && isExtendingChar(line.text.charAt(target))) { target += dir } } - return target < 0 || target > line.text.length ? null : target -} - -// Bidirectional ordering algorithm -// See http://unicode.org/reports/tr9/tr9-13.html for the algorithm -// that this (partially) implements. - -// One-char codes used for character types: -// L (L): Left-to-Right -// R (R): Right-to-Left -// r (AL): Right-to-Left Arabic -// 1 (EN): European Number -// + (ES): European Number Separator -// % (ET): European Number Terminator -// n (AN): Arabic Number -// , (CS): Common Number Separator -// m (NSM): Non-Spacing Mark -// b (BN): Boundary Neutral -// s (B): Paragraph Separator -// t (S): Segment Separator -// w (WS): Whitespace -// N (ON): Other Neutrals - -// Returns null if characters are ordered as they appear -// (left-to-right), or an array of sections ({from, to, level} -// objects) in the order in which they occur visually. -var bidiOrdering = (function() { - // Character types for codepoints 0 to 0xff - var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN" - // Character types for codepoints 0x600 to 0x6f9 - var arabicTypes = "nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111" - function charType(code) { - if (code <= 0xf7) { return lowTypes.charAt(code) } - else if (0x590 <= code && code <= 0x5f4) { return "R" } - else if (0x600 <= code && code <= 0x6f9) { return arabicTypes.charAt(code - 0x600) } - else if (0x6ee <= code && code <= 0x8ac) { return "r" } - else if (0x2000 <= code && code <= 0x200b) { return "w" } - else if (code == 0x200c) { return "b" } - else { return "L" } - } - - var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/ - var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/ - // Browsers seem to always treat the boundaries of block elements as being L. - var outerType = "L" - - function BidiSpan(level, from, to) { - this.level = level - this.from = from; this.to = to - } - - return function(str) { - if (!bidiRE.test(str)) { return false } - var len = str.length, types = [] - for (var i = 0; i < len; ++i) - { types.push(charType(str.charCodeAt(i))) } - - // W1. Examine each non-spacing mark (NSM) in the level run, and - // change the type of the NSM to the type of the previous - // character. If the NSM is at the start of the level run, it will - // get the type of sor. - for (var i$1 = 0, prev = outerType; i$1 < len; ++i$1) { - var type = types[i$1] - if (type == "m") { types[i$1] = prev } - else { prev = type } - } - - // W2. Search backwards from each instance of a European number - // until the first strong type (R, L, AL, or sor) is found. If an - // AL is found, change the type of the European number to Arabic - // number. - // W3. Change all ALs to R. - for (var i$2 = 0, cur = outerType; i$2 < len; ++i$2) { - var type$1 = types[i$2] - if (type$1 == "1" && cur == "r") { types[i$2] = "n" } - else if (isStrong.test(type$1)) { cur = type$1; if (type$1 == "r") { types[i$2] = "R" } } - } - - // W4. A single European separator between two European numbers - // changes to a European number. A single common separator between - // two numbers of the same type changes to that type. - for (var i$3 = 1, prev$1 = types[0]; i$3 < len - 1; ++i$3) { - var type$2 = types[i$3] - if (type$2 == "+" && prev$1 == "1" && types[i$3+1] == "1") { types[i$3] = "1" } - else if (type$2 == "," && prev$1 == types[i$3+1] && - (prev$1 == "1" || prev$1 == "n")) { types[i$3] = prev$1 } - prev$1 = type$2 - } - - // W5. A sequence of European terminators adjacent to European - // numbers changes to all European numbers. - // W6. Otherwise, separators and terminators change to Other - // Neutral. - for (var i$4 = 0; i$4 < len; ++i$4) { - var type$3 = types[i$4] - if (type$3 == ",") { types[i$4] = "N" } - else if (type$3 == "%") { - var end = (void 0) - for (end = i$4 + 1; end < len && types[end] == "%"; ++end) {} - var replace = (i$4 && types[i$4-1] == "!") || (end < len && types[end] == "1") ? "1" : "N" - for (var j = i$4; j < end; ++j) { types[j] = replace } - i$4 = end - 1 - } - } - - // W7. Search backwards from each instance of a European number - // until the first strong type (R, L, or sor) is found. If an L is - // found, then change the type of the European number to L. - for (var i$5 = 0, cur$1 = outerType; i$5 < len; ++i$5) { - var type$4 = types[i$5] - if (cur$1 == "L" && type$4 == "1") { types[i$5] = "L" } - else if (isStrong.test(type$4)) { cur$1 = type$4 } - } - - // N1. A sequence of neutrals takes the direction of the - // surrounding strong text if the text on both sides has the same - // direction. European and Arabic numbers act as if they were R in - // terms of their influence on neutrals. Start-of-level-run (sor) - // and end-of-level-run (eor) are used at level run boundaries. - // N2. Any remaining neutrals take the embedding direction. - for (var i$6 = 0; i$6 < len; ++i$6) { - if (isNeutral.test(types[i$6])) { - var end$1 = (void 0) - for (end$1 = i$6 + 1; end$1 < len && isNeutral.test(types[end$1]); ++end$1) {} - var before = (i$6 ? types[i$6-1] : outerType) == "L" - var after = (end$1 < len ? types[end$1] : outerType) == "L" - var replace$1 = before || after ? "L" : "R" - for (var j$1 = i$6; j$1 < end$1; ++j$1) { types[j$1] = replace$1 } - i$6 = end$1 - 1 - } - } - - // Here we depart from the documented algorithm, in order to avoid - // building up an actual levels array. Since there are only three - // levels (0, 1, 2) in an implementation that doesn't take - // explicit embedding into account, we can build up the order on - // the fly, without following the level-based algorithm. - var order = [], m - for (var i$7 = 0; i$7 < len;) { - if (countsAsLeft.test(types[i$7])) { - var start = i$7 - for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {} - order.push(new BidiSpan(0, start, i$7)) - } else { - var pos = i$7, at = order.length - for (++i$7; i$7 < len && types[i$7] != "L"; ++i$7) {} - for (var j$2 = pos; j$2 < i$7;) { - if (countsAsNum.test(types[j$2])) { - if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2)) } - var nstart = j$2 - for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {} - order.splice(at, 0, new BidiSpan(2, nstart, j$2)) - pos = j$2 - } else { ++j$2 } - } - if (pos < i$7) { order.splice(at, 0, new BidiSpan(1, pos, i$7)) } - } - } - if (order[0].level == 1 && (m = str.match(/^\s+/))) { - order[0].from = m[0].length - order.unshift(new BidiSpan(0, 0, m[0].length)) - } - if (lst(order).level == 1 && (m = str.match(/\s+$/))) { - lst(order).to -= m[0].length - order.push(new BidiSpan(0, len - m[0].length, len)) - } - if (order[0].level == 2) - { order.unshift(new BidiSpan(1, order[0].to, order[0].to)) } - if (order[0].level != lst(order).level) - { order.push(new BidiSpan(order[0].level, len, len)) } - - return order - } -})() - -// Get the bidi ordering for the given line (and cache it). Returns -// false for lines that are fully left-to-right, and an array of -// BidiSpan objects otherwise. -function getOrder(line) { - var order = line.order - if (order == null) { order = line.order = bidiOrdering(line.text) } - return order -} - -// EVENT HANDLING - -// Lightweight event framework. on/off also work on DOM nodes, -// registering native DOM handlers. - -var noHandlers = [] - -var on = function(emitter, type, f) { - if (emitter.addEventListener) { - emitter.addEventListener(type, f, false) - } else if (emitter.attachEvent) { - emitter.attachEvent("on" + type, f) - } else { - var map = emitter._handlers || (emitter._handlers = {}) - map[type] = (map[type] || noHandlers).concat(f) - } -} - -function getHandlers(emitter, type) { - return emitter._handlers && emitter._handlers[type] || noHandlers -} - -function off(emitter, type, f) { - if (emitter.removeEventListener) { - emitter.removeEventListener(type, f, false) - } else if (emitter.detachEvent) { - emitter.detachEvent("on" + type, f) - } else { - var map = emitter._handlers, arr = map && map[type] - if (arr) { - var index = indexOf(arr, f) - if (index > -1) - { map[type] = arr.slice(0, index).concat(arr.slice(index + 1)) } - } - } -} - -function signal(emitter, type /*, values...*/) { - var handlers = getHandlers(emitter, type) - if (!handlers.length) { return } - var args = Array.prototype.slice.call(arguments, 2) - for (var i = 0; i < handlers.length; ++i) { handlers[i].apply(null, args) } -} - -// The DOM events that CodeMirror handles can be overridden by -// registering a (non-DOM) handler on the editor for the event name, -// and preventDefault-ing the event in that handler. -function signalDOMEvent(cm, e, override) { - if (typeof e == "string") - { e = {type: e, preventDefault: function() { this.defaultPrevented = true }} } - signal(cm, override || e.type, cm, e) - return e_defaultPrevented(e) || e.codemirrorIgnore -} - -function signalCursorActivity(cm) { - var arr = cm._handlers && cm._handlers.cursorActivity - if (!arr) { return } - var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []) - for (var i = 0; i < arr.length; ++i) { if (indexOf(set, arr[i]) == -1) - { set.push(arr[i]) } } -} - -function hasHandler(emitter, type) { - return getHandlers(emitter, type).length > 0 -} - -// Add on and off methods to a constructor's prototype, to make -// registering events on such objects more convenient. -function eventMixin(ctor) { - ctor.prototype.on = function(type, f) {on(this, type, f)} - ctor.prototype.off = function(type, f) {off(this, type, f)} -} - -// Due to the fact that we still support jurassic IE versions, some -// compatibility wrappers are needed. - -function e_preventDefault(e) { - if (e.preventDefault) { e.preventDefault() } - else { e.returnValue = false } -} -function e_stopPropagation(e) { - if (e.stopPropagation) { e.stopPropagation() } - else { e.cancelBubble = true } -} -function e_defaultPrevented(e) { - return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false -} -function e_stop(e) {e_preventDefault(e); e_stopPropagation(e)} - -function e_target(e) {return e.target || e.srcElement} -function e_button(e) { - var b = e.which - if (b == null) { - if (e.button & 1) { b = 1 } - else if (e.button & 2) { b = 3 } - else if (e.button & 4) { b = 2 } - } - if (mac && e.ctrlKey && b == 1) { b = 3 } - return b -} - -// Detect drag-and-drop -var dragAndDrop = function() { - // There is *some* kind of drag-and-drop support in IE6-8, but I - // couldn't get it to work yet. - if (ie && ie_version < 9) { return false } - var div = elt('div') - return "draggable" in div || "dragDrop" in div -}() - -var zwspSupported -function zeroWidthElement(measure) { - if (zwspSupported == null) { - var test = elt("span", "\u200b") - removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")])) - if (measure.firstChild.offsetHeight != 0) - { zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8) } - } - var node = zwspSupported ? elt("span", "\u200b") : - elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px") - node.setAttribute("cm-text", "") - return node -} - -// Feature-detect IE's crummy client rect reporting for bidi text -var badBidiRects -function hasBadBidiRects(measure) { - if (badBidiRects != null) { return badBidiRects } - var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA")) - var r0 = range(txt, 0, 1).getBoundingClientRect() - var r1 = range(txt, 1, 2).getBoundingClientRect() - removeChildren(measure) - if (!r0 || r0.left == r0.right) { return false } // Safari returns null in some cases (#2780) - return badBidiRects = (r1.right - r0.right < 3) -} - -// See if "".split is the broken IE version, if so, provide an -// alternative way to split lines. -var splitLinesAuto = "\n\nb".split(/\n/).length != 3 ? function (string) { - var pos = 0, result = [], l = string.length - while (pos <= l) { - var nl = string.indexOf("\n", pos) - if (nl == -1) { nl = string.length } - var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl) - var rt = line.indexOf("\r") - if (rt != -1) { - result.push(line.slice(0, rt)) - pos += rt + 1 - } else { - result.push(line) - pos = nl + 1 - } - } - return result -} : function (string) { return string.split(/\r\n?|\n/); } - -var hasSelection = window.getSelection ? function (te) { - try { return te.selectionStart != te.selectionEnd } - catch(e) { return false } -} : function (te) { - var range - try {range = te.ownerDocument.selection.createRange()} - catch(e) {} - if (!range || range.parentElement() != te) { return false } - return range.compareEndPoints("StartToEnd", range) != 0 -} - -var hasCopyEvent = (function () { - var e = elt("div") - if ("oncopy" in e) { return true } - e.setAttribute("oncopy", "return;") - return typeof e.oncopy == "function" -})() - -var badZoomedRects = null -function hasBadZoomedRects(measure) { - if (badZoomedRects != null) { return badZoomedRects } - var node = removeChildrenAndAdd(measure, elt("span", "x")) - var normal = node.getBoundingClientRect() - var fromRange = range(node, 0, 1).getBoundingClientRect() - return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1 -} - -var modes = {}; -var mimeModes = {}; -// Extra arguments are stored as the mode's dependencies, which is -// used by (legacy) mechanisms like loadmode.js to automatically -// load a mode. (Preferred mechanism is the require/define calls.) -function defineMode(name, mode) { - if (arguments.length > 2) - { mode.dependencies = Array.prototype.slice.call(arguments, 2) } - modes[name] = mode -} - -function defineMIME(mime, spec) { - mimeModes[mime] = spec -} - -// Given a MIME type, a {name, ...options} config object, or a name -// string, return a mode config object. -function resolveMode(spec) { - if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { - spec = mimeModes[spec] - } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { - var found = mimeModes[spec.name] - if (typeof found == "string") { found = {name: found} } - spec = createObj(found, spec) - spec.name = found.name - } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { - return resolveMode("application/xml") - } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) { - return resolveMode("application/json") - } - if (typeof spec == "string") { return {name: spec} } - else { return spec || {name: "null"} } -} - -// Given a mode spec (anything that resolveMode accepts), find and -// initialize an actual mode object. -function getMode(options, spec) { - spec = resolveMode(spec) - var mfactory = modes[spec.name] - if (!mfactory) { return getMode(options, "text/plain") } - var modeObj = mfactory(options, spec) - if (modeExtensions.hasOwnProperty(spec.name)) { - var exts = modeExtensions[spec.name] - for (var prop in exts) { - if (!exts.hasOwnProperty(prop)) { continue } - if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop] } - modeObj[prop] = exts[prop] - } - } - modeObj.name = spec.name - if (spec.helperType) { modeObj.helperType = spec.helperType } - if (spec.modeProps) { for (var prop$1 in spec.modeProps) - { modeObj[prop$1] = spec.modeProps[prop$1] } } - - return modeObj -} - -// This can be used to attach properties to mode objects from -// outside the actual mode definition. -var modeExtensions = {} -function extendMode(mode, properties) { - var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}) - copyObj(properties, exts) -} - -function copyState(mode, state) { - if (state === true) { return state } - if (mode.copyState) { return mode.copyState(state) } - var nstate = {} - for (var n in state) { - var val = state[n] - if (val instanceof Array) { val = val.concat([]) } - nstate[n] = val - } - return nstate -} - -// Given a mode and a state (for that mode), find the inner mode and -// state at the position that the state refers to. -function innerMode(mode, state) { - var info - while (mode.innerMode) { - info = mode.innerMode(state) - if (!info || info.mode == mode) { break } - state = info.state - mode = info.mode - } - return info || {mode: mode, state: state} -} - -function startState(mode, a1, a2) { - return mode.startState ? mode.startState(a1, a2) : true -} - -// STRING STREAM - -// Fed to the mode parsers, provides helper functions to make -// parsers more succinct. - -var StringStream = function(string, tabSize) { - this.pos = this.start = 0 - this.string = string - this.tabSize = tabSize || 8 - this.lastColumnPos = this.lastColumnValue = 0 - this.lineStart = 0 -} - -StringStream.prototype = { - eol: function() {return this.pos >= this.string.length}, - sol: function() {return this.pos == this.lineStart}, - peek: function() {return this.string.charAt(this.pos) || undefined}, - next: function() { - if (this.pos < this.string.length) - { return this.string.charAt(this.pos++) } - }, - eat: function(match) { - var ch = this.string.charAt(this.pos) - var ok - if (typeof match == "string") { ok = ch == match } - else { ok = ch && (match.test ? match.test(ch) : match(ch)) } - if (ok) {++this.pos; return ch} - }, - eatWhile: function(match) { - var start = this.pos - while (this.eat(match)){} - return this.pos > start - }, - eatSpace: function() { - var this$1 = this; - - var start = this.pos - while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this$1.pos } - return this.pos > start - }, - skipToEnd: function() {this.pos = this.string.length}, - skipTo: function(ch) { - var found = this.string.indexOf(ch, this.pos) - if (found > -1) {this.pos = found; return true} - }, - backUp: function(n) {this.pos -= n}, - column: function() { - if (this.lastColumnPos < this.start) { - this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue) - this.lastColumnPos = this.start - } - return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0) - }, - indentation: function() { - return countColumn(this.string, null, this.tabSize) - - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0) - }, - match: function(pattern, consume, caseInsensitive) { - if (typeof pattern == "string") { - var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; } - var substr = this.string.substr(this.pos, pattern.length) - if (cased(substr) == cased(pattern)) { - if (consume !== false) { this.pos += pattern.length } - return true - } - } else { - var match = this.string.slice(this.pos).match(pattern) - if (match && match.index > 0) { return null } - if (match && consume !== false) { this.pos += match[0].length } - return match - } - }, - current: function(){return this.string.slice(this.start, this.pos)}, - hideFirstChars: function(n, inner) { - this.lineStart += n - try { return inner() } - finally { this.lineStart -= n } - } -} - -// Compute a style array (an array starting with a mode generation -// -- for invalidation -- followed by pairs of end positions and -// style strings), which is used to highlight the tokens on the -// line. -function highlightLine(cm, line, state, forceToEnd) { - // A styles array always starts with a number identifying the - // mode/overlays that it is based on (for easy invalidation). - var st = [cm.state.modeGen], lineClasses = {} - // Compute the base array of styles - runMode(cm, line.text, cm.doc.mode, state, function (end, style) { return st.push(end, style); }, - lineClasses, forceToEnd) - - // Run overlays, adjust style array. - var loop = function ( o ) { - var overlay = cm.state.overlays[o], i = 1, at = 0 - runMode(cm, line.text, overlay.mode, true, function (end, style) { - var start = i - // Ensure there's a token end at the current position, and that i points at it - while (at < end) { - var i_end = st[i] - if (i_end > end) - { st.splice(i, 1, end, st[i+1], i_end) } - i += 2 - at = Math.min(end, i_end) - } - if (!style) { return } - if (overlay.opaque) { - st.splice(start, i - start, end, "overlay " + style) - i = start + 2 - } else { - for (; start < i; start += 2) { - var cur = st[start+1] - st[start+1] = (cur ? cur + " " : "") + "overlay " + style - } - } - }, lineClasses) - }; - - for (var o = 0; o < cm.state.overlays.length; ++o) loop( o ); - - return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null} -} - -function getLineStyles(cm, line, updateFrontier) { - if (!line.styles || line.styles[0] != cm.state.modeGen) { - var state = getStateBefore(cm, lineNo(line)) - var result = highlightLine(cm, line, line.text.length > cm.options.maxHighlightLength ? copyState(cm.doc.mode, state) : state) - line.stateAfter = state - line.styles = result.styles - if (result.classes) { line.styleClasses = result.classes } - else if (line.styleClasses) { line.styleClasses = null } - if (updateFrontier === cm.doc.frontier) { cm.doc.frontier++ } - } - return line.styles -} - -function getStateBefore(cm, n, precise) { - var doc = cm.doc, display = cm.display - if (!doc.mode.startState) { return true } - var pos = findStartLine(cm, n, precise), state = pos > doc.first && getLine(doc, pos-1).stateAfter - if (!state) { state = startState(doc.mode) } - else { state = copyState(doc.mode, state) } - doc.iter(pos, n, function (line) { - processLine(cm, line.text, state) - var save = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo - line.stateAfter = save ? copyState(doc.mode, state) : null - ++pos - }) - if (precise) { doc.frontier = pos } - return state -} - -// Lightweight form of highlight -- proceed over this line and -// update state, but don't save a style array. Used for lines that -// aren't currently visible. -function processLine(cm, text, state, startAt) { - var mode = cm.doc.mode - var stream = new StringStream(text, cm.options.tabSize) - stream.start = stream.pos = startAt || 0 - if (text == "") { callBlankLine(mode, state) } - while (!stream.eol()) { - readToken(mode, stream, state) - stream.start = stream.pos - } -} - -function callBlankLine(mode, state) { - if (mode.blankLine) { return mode.blankLine(state) } - if (!mode.innerMode) { return } - var inner = innerMode(mode, state) - if (inner.mode.blankLine) { return inner.mode.blankLine(inner.state) } -} - -function readToken(mode, stream, state, inner) { - for (var i = 0; i < 10; i++) { - if (inner) { inner[0] = innerMode(mode, state).mode } - var style = mode.token(stream, state) - if (stream.pos > stream.start) { return style } - } - throw new Error("Mode " + mode.name + " failed to advance stream.") -} - -// Utility for getTokenAt and getLineTokens -function takeToken(cm, pos, precise, asArray) { - var getObj = function (copy) { return ({ - start: stream.start, end: stream.pos, - string: stream.current(), - type: style || null, - state: copy ? copyState(doc.mode, state) : state - }); } - - var doc = cm.doc, mode = doc.mode, style - pos = clipPos(doc, pos) - var line = getLine(doc, pos.line), state = getStateBefore(cm, pos.line, precise) - var stream = new StringStream(line.text, cm.options.tabSize), tokens - if (asArray) { tokens = [] } - while ((asArray || stream.pos < pos.ch) && !stream.eol()) { - stream.start = stream.pos - style = readToken(mode, stream, state) - if (asArray) { tokens.push(getObj(true)) } - } - return asArray ? tokens : getObj() -} - -function extractLineClasses(type, output) { - if (type) { for (;;) { - var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/) - if (!lineClass) { break } - type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length) - var prop = lineClass[1] ? "bgClass" : "textClass" - if (output[prop] == null) - { output[prop] = lineClass[2] } - else if (!(new RegExp("(?:^|\s)" + lineClass[2] + "(?:$|\s)")).test(output[prop])) - { output[prop] += " " + lineClass[2] } - } } - return type -} - -// Run the given mode's parser over a line, calling f for each token. -function runMode(cm, text, mode, state, f, lineClasses, forceToEnd) { - var flattenSpans = mode.flattenSpans - if (flattenSpans == null) { flattenSpans = cm.options.flattenSpans } - var curStart = 0, curStyle = null - var stream = new StringStream(text, cm.options.tabSize), style - var inner = cm.options.addModeClass && [null] - if (text == "") { extractLineClasses(callBlankLine(mode, state), lineClasses) } - while (!stream.eol()) { - if (stream.pos > cm.options.maxHighlightLength) { - flattenSpans = false - if (forceToEnd) { processLine(cm, text, state, stream.pos) } - stream.pos = text.length - style = null - } else { - style = extractLineClasses(readToken(mode, stream, state, inner), lineClasses) - } - if (inner) { - var mName = inner[0].name - if (mName) { style = "m-" + (style ? mName + " " + style : mName) } - } - if (!flattenSpans || curStyle != style) { - while (curStart < stream.start) { - curStart = Math.min(stream.start, curStart + 5000) - f(curStart, curStyle) - } - curStyle = style - } - stream.start = stream.pos - } - while (curStart < stream.pos) { - // Webkit seems to refuse to render text nodes longer than 57444 - // characters, and returns inaccurate measurements in nodes - // starting around 5000 chars. - var pos = Math.min(stream.pos, curStart + 5000) - f(pos, curStyle) - curStart = pos - } -} - -// Finds the line to start with when starting a parse. Tries to -// find a line with a stateAfter, so that it can start with a -// valid state. If that fails, it returns the line with the -// smallest indentation, which tends to need the least context to -// parse correctly. -function findStartLine(cm, n, precise) { - var minindent, minline, doc = cm.doc - var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100) - for (var search = n; search > lim; --search) { - if (search <= doc.first) { return doc.first } - var line = getLine(doc, search - 1) - if (line.stateAfter && (!precise || search <= doc.frontier)) { return search } - var indented = countColumn(line.text, null, cm.options.tabSize) - if (minline == null || minindent > indented) { - minline = search - 1 - minindent = indented - } - } - return minline -} - -// LINE DATA STRUCTURE - -// Line objects. These hold state related to a line, including -// highlighting info (the styles array). -function Line(text, markedSpans, estimateHeight) { - this.text = text - attachMarkedSpans(this, markedSpans) - this.height = estimateHeight ? estimateHeight(this) : 1 -} -eventMixin(Line) -Line.prototype.lineNo = function() { return lineNo(this) } - -// Change the content (text, markers) of a line. Automatically -// invalidates cached information and tries to re-estimate the -// line's height. -function updateLine(line, text, markedSpans, estimateHeight) { - line.text = text - if (line.stateAfter) { line.stateAfter = null } - if (line.styles) { line.styles = null } - if (line.order != null) { line.order = null } - detachMarkedSpans(line) - attachMarkedSpans(line, markedSpans) - var estHeight = estimateHeight ? estimateHeight(line) : 1 - if (estHeight != line.height) { updateLineHeight(line, estHeight) } -} - -// Detach a line from the document tree and its markers. -function cleanUpLine(line) { - line.parent = null - detachMarkedSpans(line) -} - -// Convert a style as returned by a mode (either null, or a string -// containing one or more styles) to a CSS style. This is cached, -// and also looks for line-wide styles. -var styleToClassCache = {}; -var styleToClassCacheWithMode = {}; -function interpretTokenStyle(style, options) { - if (!style || /^\s*$/.test(style)) { return null } - var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache - return cache[style] || - (cache[style] = style.replace(/\S+/g, "cm-$&")) -} - -// Render the DOM representation of the text of a line. Also builds -// up a 'line map', which points at the DOM nodes that represent -// specific stretches of text, and is used by the measuring code. -// The returned object contains the DOM node, this map, and -// information about line-wide styles that were set by the mode. -function buildLineContent(cm, lineView) { - // The padding-right forces the element to have a 'border', which - // is needed on Webkit to be able to get line-level bounding - // rectangles for it (in measureChar). - var content = elt("span", null, null, webkit ? "padding-right: .1px" : null) - var builder = {pre: elt("pre", [content], "CodeMirror-line"), content: content, - col: 0, pos: 0, cm: cm, - trailingSpace: false, - splitSpaces: (ie || webkit) && cm.getOption("lineWrapping")} - // hide from accessibility tree - content.setAttribute("role", "presentation") - builder.pre.setAttribute("role", "presentation") - lineView.measure = {} - - // Iterate over the logical lines that make up this visual line. - for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) { - var line = i ? lineView.rest[i - 1] : lineView.line, order = (void 0) - builder.pos = 0 - builder.addToken = buildToken - // Optionally wire in some hacks into the token-rendering - // algorithm, to deal with browser quirks. - if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line))) - { builder.addToken = buildTokenBadBidi(builder.addToken, order) } - builder.map = [] - var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line) - insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate)) - if (line.styleClasses) { - if (line.styleClasses.bgClass) - { builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || "") } - if (line.styleClasses.textClass) - { builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || "") } - } - - // Ensure at least a single node is present, for measuring. - if (builder.map.length == 0) - { builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))) } - - // Store the map and a cache object for the current logical line - if (i == 0) { - lineView.measure.map = builder.map - lineView.measure.cache = {} - } else { - ;(lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map) - ;(lineView.measure.caches || (lineView.measure.caches = [])).push({}) - } - } - - // See issue #2901 - if (webkit) { - var last = builder.content.lastChild - if (/\bcm-tab\b/.test(last.className) || (last.querySelector && last.querySelector(".cm-tab"))) - { builder.content.className = "cm-tab-wrap-hack" } - } - - signal(cm, "renderLine", cm, lineView.line, builder.pre) - if (builder.pre.className) - { builder.textClass = joinClasses(builder.pre.className, builder.textClass || "") } - - return builder -} - -function defaultSpecialCharPlaceholder(ch) { - var token = elt("span", "\u2022", "cm-invalidchar") - token.title = "\\u" + ch.charCodeAt(0).toString(16) - token.setAttribute("aria-label", token.title) - return token -} - -// Build up the DOM representation for a single token, and add it to -// the line map. Takes care to render special characters separately. -function buildToken(builder, text, style, startStyle, endStyle, title, css) { - if (!text) { return } - var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text - var special = builder.cm.state.specialChars, mustWrap = false - var content - if (!special.test(text)) { - builder.col += text.length - content = document.createTextNode(displayText) - builder.map.push(builder.pos, builder.pos + text.length, content) - if (ie && ie_version < 9) { mustWrap = true } - builder.pos += text.length - } else { - content = document.createDocumentFragment() - var pos = 0 - while (true) { - special.lastIndex = pos - var m = special.exec(text) - var skipped = m ? m.index - pos : text.length - pos - if (skipped) { - var txt = document.createTextNode(displayText.slice(pos, pos + skipped)) - if (ie && ie_version < 9) { content.appendChild(elt("span", [txt])) } - else { content.appendChild(txt) } - builder.map.push(builder.pos, builder.pos + skipped, txt) - builder.col += skipped - builder.pos += skipped - } - if (!m) { break } - pos += skipped + 1 - var txt$1 = (void 0) - if (m[0] == "\t") { - var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize - txt$1 = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")) - txt$1.setAttribute("role", "presentation") - txt$1.setAttribute("cm-text", "\t") - builder.col += tabWidth - } else if (m[0] == "\r" || m[0] == "\n") { - txt$1 = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar")) - txt$1.setAttribute("cm-text", m[0]) - builder.col += 1 - } else { - txt$1 = builder.cm.options.specialCharPlaceholder(m[0]) - txt$1.setAttribute("cm-text", m[0]) - if (ie && ie_version < 9) { content.appendChild(elt("span", [txt$1])) } - else { content.appendChild(txt$1) } - builder.col += 1 - } - builder.map.push(builder.pos, builder.pos + 1, txt$1) - builder.pos++ - } - } - builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32 - if (style || startStyle || endStyle || mustWrap || css) { - var fullStyle = style || "" - if (startStyle) { fullStyle += startStyle } - if (endStyle) { fullStyle += endStyle } - var token = elt("span", [content], fullStyle, css) - if (title) { token.title = title } - return builder.content.appendChild(token) - } - builder.content.appendChild(content) -} - -function splitSpaces(text, trailingBefore) { - if (text.length > 1 && !/ /.test(text)) { return text } - var spaceBefore = trailingBefore, result = "" - for (var i = 0; i < text.length; i++) { - var ch = text.charAt(i) - if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32)) - { ch = "\u00a0" } - result += ch - spaceBefore = ch == " " - } - return result -} - -// Work around nonsense dimensions being reported for stretches of -// right-to-left text. -function buildTokenBadBidi(inner, order) { - return function (builder, text, style, startStyle, endStyle, title, css) { - style = style ? style + " cm-force-border" : "cm-force-border" - var start = builder.pos, end = start + text.length - for (;;) { - // Find the part that overlaps with the start of this text - var part = (void 0) - for (var i = 0; i < order.length; i++) { - part = order[i] - if (part.to > start && part.from <= start) { break } - } - if (part.to >= end) { return inner(builder, text, style, startStyle, endStyle, title, css) } - inner(builder, text.slice(0, part.to - start), style, startStyle, null, title, css) - startStyle = null - text = text.slice(part.to - start) - start = part.to - } - } -} - -function buildCollapsedSpan(builder, size, marker, ignoreWidget) { - var widget = !ignoreWidget && marker.widgetNode - if (widget) { builder.map.push(builder.pos, builder.pos + size, widget) } - if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) { - if (!widget) - { widget = builder.content.appendChild(document.createElement("span")) } - widget.setAttribute("cm-marker", marker.id) - } - if (widget) { - builder.cm.display.input.setUneditable(widget) - builder.content.appendChild(widget) - } - builder.pos += size - builder.trailingSpace = false -} - -// Outputs a number of spans to make up a line, taking highlighting -// and marked text into account. -function insertLineContent(line, builder, styles) { - var spans = line.markedSpans, allText = line.text, at = 0 - if (!spans) { - for (var i$1 = 1; i$1 < styles.length; i$1+=2) - { builder.addToken(builder, allText.slice(at, at = styles[i$1]), interpretTokenStyle(styles[i$1+1], builder.cm.options)) } - return - } - - var len = allText.length, pos = 0, i = 1, text = "", style, css - var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, title, collapsed - for (;;) { - if (nextChange == pos) { // Update current marker set - spanStyle = spanEndStyle = spanStartStyle = title = css = "" - collapsed = null; nextChange = Infinity - var foundBookmarks = [], endStyles = (void 0) - for (var j = 0; j < spans.length; ++j) { - var sp = spans[j], m = sp.marker - if (m.type == "bookmark" && sp.from == pos && m.widgetNode) { - foundBookmarks.push(m) - } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) { - if (sp.to != null && sp.to != pos && nextChange > sp.to) { - nextChange = sp.to - spanEndStyle = "" - } - if (m.className) { spanStyle += " " + m.className } - if (m.css) { css = (css ? css + ";" : "") + m.css } - if (m.startStyle && sp.from == pos) { spanStartStyle += " " + m.startStyle } - if (m.endStyle && sp.to == nextChange) { (endStyles || (endStyles = [])).push(m.endStyle, sp.to) } - if (m.title && !title) { title = m.title } - if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0)) - { collapsed = sp } - } else if (sp.from > pos && nextChange > sp.from) { - nextChange = sp.from - } - } - if (endStyles) { for (var j$1 = 0; j$1 < endStyles.length; j$1 += 2) - { if (endStyles[j$1 + 1] == nextChange) { spanEndStyle += " " + endStyles[j$1] } } } - - if (!collapsed || collapsed.from == pos) { for (var j$2 = 0; j$2 < foundBookmarks.length; ++j$2) - { buildCollapsedSpan(builder, 0, foundBookmarks[j$2]) } } - if (collapsed && (collapsed.from || 0) == pos) { - buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos, - collapsed.marker, collapsed.from == null) - if (collapsed.to == null) { return } - if (collapsed.to == pos) { collapsed = false } - } - } - if (pos >= len) { break } - - var upto = Math.min(len, nextChange) - while (true) { - if (text) { - var end = pos + text.length - if (!collapsed) { - var tokenText = end > upto ? text.slice(0, upto - pos) : text - builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle, - spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", title, css) - } - if (end >= upto) {text = text.slice(upto - pos); pos = upto; break} - pos = end - spanStartStyle = "" - } - text = allText.slice(at, at = styles[i++]) - style = interpretTokenStyle(styles[i++], builder.cm.options) - } - } -} - - -// These objects are used to represent the visible (currently drawn) -// part of the document. A LineView may correspond to multiple -// logical lines, if those are connected by collapsed ranges. -function LineView(doc, line, lineN) { - // The starting line - this.line = line - // Continuing lines, if any - this.rest = visualLineContinued(line) - // Number of logical lines in this visual line - this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1 - this.node = this.text = null - this.hidden = lineIsHidden(doc, line) -} - -// Create a range of LineView objects for the given lines. -function buildViewArray(cm, from, to) { - var array = [], nextPos - for (var pos = from; pos < to; pos = nextPos) { - var view = new LineView(cm.doc, getLine(cm.doc, pos), pos) - nextPos = pos + view.size - array.push(view) - } - return array -} - -var operationGroup = null - -function pushOperation(op) { - if (operationGroup) { - operationGroup.ops.push(op) - } else { - op.ownsGroup = operationGroup = { - ops: [op], - delayedCallbacks: [] - } - } -} - -function fireCallbacksForOps(group) { - // Calls delayed callbacks and cursorActivity handlers until no - // new ones appear - var callbacks = group.delayedCallbacks, i = 0 - do { - for (; i < callbacks.length; i++) - { callbacks[i].call(null) } - for (var j = 0; j < group.ops.length; j++) { - var op = group.ops[j] - if (op.cursorActivityHandlers) - { while (op.cursorActivityCalled < op.cursorActivityHandlers.length) - { op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm) } } - } - } while (i < callbacks.length) -} - -function finishOperation(op, endCb) { - var group = op.ownsGroup - if (!group) { return } - - try { fireCallbacksForOps(group) } - finally { - operationGroup = null - endCb(group) - } -} - -var orphanDelayedCallbacks = null - -// Often, we want to signal events at a point where we are in the -// middle of some work, but don't want the handler to start calling -// other methods on the editor, which might be in an inconsistent -// state or simply not expect any other events to happen. -// signalLater looks whether there are any handlers, and schedules -// them to be executed when the last operation ends, or, if no -// operation is active, when a timeout fires. -function signalLater(emitter, type /*, values...*/) { - var arr = getHandlers(emitter, type) - if (!arr.length) { return } - var args = Array.prototype.slice.call(arguments, 2), list - if (operationGroup) { - list = operationGroup.delayedCallbacks - } else if (orphanDelayedCallbacks) { - list = orphanDelayedCallbacks - } else { - list = orphanDelayedCallbacks = [] - setTimeout(fireOrphanDelayed, 0) - } - var loop = function ( i ) { - list.push(function () { return arr[i].apply(null, args); }) - }; - - for (var i = 0; i < arr.length; ++i) - loop( i ); -} - -function fireOrphanDelayed() { - var delayed = orphanDelayedCallbacks - orphanDelayedCallbacks = null - for (var i = 0; i < delayed.length; ++i) { delayed[i]() } -} - -// When an aspect of a line changes, a string is added to -// lineView.changes. This updates the relevant part of the line's -// DOM structure. -function updateLineForChanges(cm, lineView, lineN, dims) { - for (var j = 0; j < lineView.changes.length; j++) { - var type = lineView.changes[j] - if (type == "text") { updateLineText(cm, lineView) } - else if (type == "gutter") { updateLineGutter(cm, lineView, lineN, dims) } - else if (type == "class") { updateLineClasses(lineView) } - else if (type == "widget") { updateLineWidgets(cm, lineView, dims) } - } - lineView.changes = null -} - -// Lines with gutter elements, widgets or a background class need to -// be wrapped, and have the extra elements added to the wrapper div -function ensureLineWrapped(lineView) { - if (lineView.node == lineView.text) { - lineView.node = elt("div", null, null, "position: relative") - if (lineView.text.parentNode) - { lineView.text.parentNode.replaceChild(lineView.node, lineView.text) } - lineView.node.appendChild(lineView.text) - if (ie && ie_version < 8) { lineView.node.style.zIndex = 2 } - } - return lineView.node -} - -function updateLineBackground(lineView) { - var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass - if (cls) { cls += " CodeMirror-linebackground" } - if (lineView.background) { - if (cls) { lineView.background.className = cls } - else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null } - } else if (cls) { - var wrap = ensureLineWrapped(lineView) - lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild) - } -} - -// Wrapper around buildLineContent which will reuse the structure -// in display.externalMeasured when possible. -function getLineContent(cm, lineView) { - var ext = cm.display.externalMeasured - if (ext && ext.line == lineView.line) { - cm.display.externalMeasured = null - lineView.measure = ext.measure - return ext.built - } - return buildLineContent(cm, lineView) -} - -// Redraw the line's text. Interacts with the background and text -// classes because the mode may output tokens that influence these -// classes. -function updateLineText(cm, lineView) { - var cls = lineView.text.className - var built = getLineContent(cm, lineView) - if (lineView.text == lineView.node) { lineView.node = built.pre } - lineView.text.parentNode.replaceChild(built.pre, lineView.text) - lineView.text = built.pre - if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) { - lineView.bgClass = built.bgClass - lineView.textClass = built.textClass - updateLineClasses(lineView) - } else if (cls) { - lineView.text.className = cls - } -} - -function updateLineClasses(lineView) { - updateLineBackground(lineView) - if (lineView.line.wrapClass) - { ensureLineWrapped(lineView).className = lineView.line.wrapClass } - else if (lineView.node != lineView.text) - { lineView.node.className = "" } - var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass - lineView.text.className = textClass || "" -} - -function updateLineGutter(cm, lineView, lineN, dims) { - if (lineView.gutter) { - lineView.node.removeChild(lineView.gutter) - lineView.gutter = null - } - if (lineView.gutterBackground) { - lineView.node.removeChild(lineView.gutterBackground) - lineView.gutterBackground = null - } - if (lineView.line.gutterClass) { - var wrap = ensureLineWrapped(lineView) - lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass, - ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px; width: " + (dims.gutterTotalWidth) + "px")) - wrap.insertBefore(lineView.gutterBackground, lineView.text) - } - var markers = lineView.line.gutterMarkers - if (cm.options.lineNumbers || markers) { - var wrap$1 = ensureLineWrapped(lineView) - var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px")) - cm.display.input.setUneditable(gutterWrap) - wrap$1.insertBefore(gutterWrap, lineView.text) - if (lineView.line.gutterClass) - { gutterWrap.className += " " + lineView.line.gutterClass } - if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"])) - { lineView.lineNumber = gutterWrap.appendChild( - elt("div", lineNumberFor(cm.options, lineN), - "CodeMirror-linenumber CodeMirror-gutter-elt", - ("left: " + (dims.gutterLeft["CodeMirror-linenumbers"]) + "px; width: " + (cm.display.lineNumInnerWidth) + "px"))) } - if (markers) { for (var k = 0; k < cm.options.gutters.length; ++k) { - var id = cm.options.gutters[k], found = markers.hasOwnProperty(id) && markers[id] - if (found) - { gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", - ("left: " + (dims.gutterLeft[id]) + "px; width: " + (dims.gutterWidth[id]) + "px"))) } - } } - } -} - -function updateLineWidgets(cm, lineView, dims) { - if (lineView.alignable) { lineView.alignable = null } - for (var node = lineView.node.firstChild, next = (void 0); node; node = next) { - next = node.nextSibling - if (node.className == "CodeMirror-linewidget") - { lineView.node.removeChild(node) } - } - insertLineWidgets(cm, lineView, dims) -} - -// Build a line's DOM representation from scratch -function buildLineElement(cm, lineView, lineN, dims) { - var built = getLineContent(cm, lineView) - lineView.text = lineView.node = built.pre - if (built.bgClass) { lineView.bgClass = built.bgClass } - if (built.textClass) { lineView.textClass = built.textClass } - - updateLineClasses(lineView) - updateLineGutter(cm, lineView, lineN, dims) - insertLineWidgets(cm, lineView, dims) - return lineView.node -} - -// A lineView may contain multiple logical lines (when merged by -// collapsed spans). The widgets for all of them need to be drawn. -function insertLineWidgets(cm, lineView, dims) { - insertLineWidgetsFor(cm, lineView.line, lineView, dims, true) - if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++) - { insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false) } } -} - -function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) { - if (!line.widgets) { return } - var wrap = ensureLineWrapped(lineView) - for (var i = 0, ws = line.widgets; i < ws.length; ++i) { - var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget") - if (!widget.handleMouseEvents) { node.setAttribute("cm-ignore-events", "true") } - positionLineWidget(widget, node, lineView, dims) - cm.display.input.setUneditable(node) - if (allowAbove && widget.above) - { wrap.insertBefore(node, lineView.gutter || lineView.text) } - else - { wrap.appendChild(node) } - signalLater(widget, "redraw") - } -} - -function positionLineWidget(widget, node, lineView, dims) { - if (widget.noHScroll) { - ;(lineView.alignable || (lineView.alignable = [])).push(node) - var width = dims.wrapperWidth - node.style.left = dims.fixedPos + "px" - if (!widget.coverGutter) { - width -= dims.gutterTotalWidth - node.style.paddingLeft = dims.gutterTotalWidth + "px" - } - node.style.width = width + "px" - } - if (widget.coverGutter) { - node.style.zIndex = 5 - node.style.position = "relative" - if (!widget.noHScroll) { node.style.marginLeft = -dims.gutterTotalWidth + "px" } - } -} - -function widgetHeight(widget) { - if (widget.height != null) { return widget.height } - var cm = widget.doc.cm - if (!cm) { return 0 } - if (!contains(document.body, widget.node)) { - var parentStyle = "position: relative;" - if (widget.coverGutter) - { parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;" } - if (widget.noHScroll) - { parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;" } - removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle)) - } - return widget.height = widget.node.parentNode.offsetHeight -} - -// Return true when the given mouse event happened in a widget -function eventInWidget(display, e) { - for (var n = e_target(e); n != display.wrapper; n = n.parentNode) { - if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") || - (n.parentNode == display.sizer && n != display.mover)) - { return true } - } -} - -// POSITION MEASUREMENT - -function paddingTop(display) {return display.lineSpace.offsetTop} -function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight} -function paddingH(display) { - if (display.cachedPaddingH) { return display.cachedPaddingH } - var e = removeChildrenAndAdd(display.measure, elt("pre", "x")) - var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle - var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)} - if (!isNaN(data.left) && !isNaN(data.right)) { display.cachedPaddingH = data } - return data -} - -function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth } -function displayWidth(cm) { - return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth -} -function displayHeight(cm) { - return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight -} - -// Ensure the lineView.wrapping.heights array is populated. This is -// an array of bottom offsets for the lines that make up a drawn -// line. When lineWrapping is on, there might be more than one -// height. -function ensureLineHeights(cm, lineView, rect) { - var wrapping = cm.options.lineWrapping - var curWidth = wrapping && displayWidth(cm) - if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) { - var heights = lineView.measure.heights = [] - if (wrapping) { - lineView.measure.width = curWidth - var rects = lineView.text.firstChild.getClientRects() - for (var i = 0; i < rects.length - 1; i++) { - var cur = rects[i], next = rects[i + 1] - if (Math.abs(cur.bottom - next.bottom) > 2) - { heights.push((cur.bottom + next.top) / 2 - rect.top) } - } - } - heights.push(rect.bottom - rect.top) - } -} - -// Find a line map (mapping character offsets to text nodes) and a -// measurement cache for the given line number. (A line view might -// contain multiple lines when collapsed ranges are present.) -function mapFromLineView(lineView, line, lineN) { - if (lineView.line == line) - { return {map: lineView.measure.map, cache: lineView.measure.cache} } - for (var i = 0; i < lineView.rest.length; i++) - { if (lineView.rest[i] == line) - { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } } - for (var i$1 = 0; i$1 < lineView.rest.length; i$1++) - { if (lineNo(lineView.rest[i$1]) > lineN) - { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } } -} - -// Render a line into the hidden node display.externalMeasured. Used -// when measurement is needed for a line that's not in the viewport. -function updateExternalMeasurement(cm, line) { - line = visualLine(line) - var lineN = lineNo(line) - var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN) - view.lineN = lineN - var built = view.built = buildLineContent(cm, view) - view.text = built.pre - removeChildrenAndAdd(cm.display.lineMeasure, built.pre) - return view -} - -// Get a {top, bottom, left, right} box (in line-local coordinates) -// for a given character. -function measureChar(cm, line, ch, bias) { - return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias) -} - -// Find a line view that corresponds to the given line number. -function findViewForLine(cm, lineN) { - if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo) - { return cm.display.view[findViewIndex(cm, lineN)] } - var ext = cm.display.externalMeasured - if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size) - { return ext } -} - -// Measurement can be split in two steps, the set-up work that -// applies to the whole line, and the measurement of the actual -// character. Functions like coordsChar, that need to do a lot of -// measurements in a row, can thus ensure that the set-up work is -// only done once. -function prepareMeasureForLine(cm, line) { - var lineN = lineNo(line) - var view = findViewForLine(cm, lineN) - if (view && !view.text) { - view = null - } else if (view && view.changes) { - updateLineForChanges(cm, view, lineN, getDimensions(cm)) - cm.curOp.forceUpdate = true - } - if (!view) - { view = updateExternalMeasurement(cm, line) } - - var info = mapFromLineView(view, line, lineN) - return { - line: line, view: view, rect: null, - map: info.map, cache: info.cache, before: info.before, - hasHeights: false - } -} - -// Given a prepared measurement object, measures the position of an -// actual character (or fetches it from the cache). -function measureCharPrepared(cm, prepared, ch, bias, varHeight) { - if (prepared.before) { ch = -1 } - var key = ch + (bias || ""), found - if (prepared.cache.hasOwnProperty(key)) { - found = prepared.cache[key] - } else { - if (!prepared.rect) - { prepared.rect = prepared.view.text.getBoundingClientRect() } - if (!prepared.hasHeights) { - ensureLineHeights(cm, prepared.view, prepared.rect) - prepared.hasHeights = true - } - found = measureCharInner(cm, prepared, ch, bias) - if (!found.bogus) { prepared.cache[key] = found } - } - return {left: found.left, right: found.right, - top: varHeight ? found.rtop : found.top, - bottom: varHeight ? found.rbottom : found.bottom} -} - -var nullRect = {left: 0, right: 0, top: 0, bottom: 0} - -function nodeAndOffsetInLineMap(map, ch, bias) { - var node, start, end, collapse, mStart, mEnd - // First, search the line map for the text node corresponding to, - // or closest to, the target character. - for (var i = 0; i < map.length; i += 3) { - mStart = map[i] - mEnd = map[i + 1] - if (ch < mStart) { - start = 0; end = 1 - collapse = "left" - } else if (ch < mEnd) { - start = ch - mStart - end = start + 1 - } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) { - end = mEnd - mStart - start = end - 1 - if (ch >= mEnd) { collapse = "right" } - } - if (start != null) { - node = map[i + 2] - if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right")) - { collapse = bias } - if (bias == "left" && start == 0) - { while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) { - node = map[(i -= 3) + 2] - collapse = "left" - } } - if (bias == "right" && start == mEnd - mStart) - { while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) { - node = map[(i += 3) + 2] - collapse = "right" - } } - break - } - } - return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd} -} - -function getUsefulRect(rects, bias) { - var rect = nullRect - if (bias == "left") { for (var i = 0; i < rects.length; i++) { - if ((rect = rects[i]).left != rect.right) { break } - } } else { for (var i$1 = rects.length - 1; i$1 >= 0; i$1--) { - if ((rect = rects[i$1]).left != rect.right) { break } - } } - return rect -} - -function measureCharInner(cm, prepared, ch, bias) { - var place = nodeAndOffsetInLineMap(prepared.map, ch, bias) - var node = place.node, start = place.start, end = place.end, collapse = place.collapse - - var rect - if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates. - for (var i$1 = 0; i$1 < 4; i$1++) { // Retry a maximum of 4 times when nonsense rectangles are returned - while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) { --start } - while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) { ++end } - if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) - { rect = node.parentNode.getBoundingClientRect() } - else - { rect = getUsefulRect(range(node, start, end).getClientRects(), bias) } - if (rect.left || rect.right || start == 0) { break } - end = start - start = start - 1 - collapse = "right" - } - if (ie && ie_version < 11) { rect = maybeUpdateRectForZooming(cm.display.measure, rect) } - } else { // If it is a widget, simply get the box for the whole widget. - if (start > 0) { collapse = bias = "right" } - var rects - if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1) - { rect = rects[bias == "right" ? rects.length - 1 : 0] } - else - { rect = node.getBoundingClientRect() } - } - if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) { - var rSpan = node.parentNode.getClientRects()[0] - if (rSpan) - { rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom} } - else - { rect = nullRect } - } - - var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top - var mid = (rtop + rbot) / 2 - var heights = prepared.view.measure.heights - var i = 0 - for (; i < heights.length - 1; i++) - { if (mid < heights[i]) { break } } - var top = i ? heights[i - 1] : 0, bot = heights[i] - var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left, - right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left, - top: top, bottom: bot} - if (!rect.left && !rect.right) { result.bogus = true } - if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot } - - return result -} - -// Work around problem with bounding client rects on ranges being -// returned incorrectly when zoomed on IE10 and below. -function maybeUpdateRectForZooming(measure, rect) { - if (!window.screen || screen.logicalXDPI == null || - screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure)) - { return rect } - var scaleX = screen.logicalXDPI / screen.deviceXDPI - var scaleY = screen.logicalYDPI / screen.deviceYDPI - return {left: rect.left * scaleX, right: rect.right * scaleX, - top: rect.top * scaleY, bottom: rect.bottom * scaleY} -} - -function clearLineMeasurementCacheFor(lineView) { - if (lineView.measure) { - lineView.measure.cache = {} - lineView.measure.heights = null - if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++) - { lineView.measure.caches[i] = {} } } - } -} - -function clearLineMeasurementCache(cm) { - cm.display.externalMeasure = null - removeChildren(cm.display.lineMeasure) - for (var i = 0; i < cm.display.view.length; i++) - { clearLineMeasurementCacheFor(cm.display.view[i]) } -} - -function clearCaches(cm) { - clearLineMeasurementCache(cm) - cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null - if (!cm.options.lineWrapping) { cm.display.maxLineChanged = true } - cm.display.lineNumChars = null -} - -function pageScrollX() { return window.pageXOffset || (document.documentElement || document.body).scrollLeft } -function pageScrollY() { return window.pageYOffset || (document.documentElement || document.body).scrollTop } - -// Converts a {top, bottom, left, right} box from line-local -// coordinates into another coordinate system. Context may be one of -// "line", "div" (display.lineDiv), "local"./null (editor), "window", -// or "page". -function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) { - if (!includeWidgets && lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above) { - var size = widgetHeight(lineObj.widgets[i]) - rect.top += size; rect.bottom += size - } } } - if (context == "line") { return rect } - if (!context) { context = "local" } - var yOff = heightAtLine(lineObj) - if (context == "local") { yOff += paddingTop(cm.display) } - else { yOff -= cm.display.viewOffset } - if (context == "page" || context == "window") { - var lOff = cm.display.lineSpace.getBoundingClientRect() - yOff += lOff.top + (context == "window" ? 0 : pageScrollY()) - var xOff = lOff.left + (context == "window" ? 0 : pageScrollX()) - rect.left += xOff; rect.right += xOff - } - rect.top += yOff; rect.bottom += yOff - return rect -} - -// Coverts a box from "div" coords to another coordinate system. -// Context may be "window", "page", "div", or "local"./null. -function fromCoordSystem(cm, coords, context) { - if (context == "div") { return coords } - var left = coords.left, top = coords.top - // First move into "page" coordinate system - if (context == "page") { - left -= pageScrollX() - top -= pageScrollY() - } else if (context == "local" || !context) { - var localBox = cm.display.sizer.getBoundingClientRect() - left += localBox.left - top += localBox.top - } - - var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect() - return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top} -} - -function charCoords(cm, pos, context, lineObj, bias) { - if (!lineObj) { lineObj = getLine(cm.doc, pos.line) } - return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context) -} - -// Returns a box for a given cursor position, which may have an -// 'other' property containing the position of the secondary cursor -// on a bidi boundary. -function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) { - lineObj = lineObj || getLine(cm.doc, pos.line) - if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj) } - function get(ch, right) { - var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight) - if (right) { m.left = m.right; } else { m.right = m.left } - return intoCoordSystem(cm, lineObj, m, context) - } - function getBidi(ch, partPos) { - var part = order[partPos], right = part.level % 2 - if (ch == bidiLeft(part) && partPos && part.level < order[partPos - 1].level) { - part = order[--partPos] - ch = bidiRight(part) - (part.level % 2 ? 0 : 1) - right = true - } else if (ch == bidiRight(part) && partPos < order.length - 1 && part.level < order[partPos + 1].level) { - part = order[++partPos] - ch = bidiLeft(part) - part.level % 2 - right = false - } - if (right && ch == part.to && ch > part.from) { return get(ch - 1) } - return get(ch, right) - } - var order = getOrder(lineObj), ch = pos.ch - if (!order) { return get(ch) } - var partPos = getBidiPartAt(order, ch) - var val = getBidi(ch, partPos) - if (bidiOther != null) { val.other = getBidi(ch, bidiOther) } - return val -} - -// Used to cheaply estimate the coordinates for a position. Used for -// intermediate scroll updates. -function estimateCoords(cm, pos) { - var left = 0 - pos = clipPos(cm.doc, pos) - if (!cm.options.lineWrapping) { left = charWidth(cm.display) * pos.ch } - var lineObj = getLine(cm.doc, pos.line) - var top = heightAtLine(lineObj) + paddingTop(cm.display) - return {left: left, right: left, top: top, bottom: top + lineObj.height} -} - -// Positions returned by coordsChar contain some extra information. -// xRel is the relative x position of the input coordinates compared -// to the found position (so xRel > 0 means the coordinates are to -// the right of the character position, for example). When outside -// is true, that means the coordinates lie outside the line's -// vertical range. -function PosWithInfo(line, ch, outside, xRel) { - var pos = Pos(line, ch) - pos.xRel = xRel - if (outside) { pos.outside = true } - return pos -} - -// Compute the character position closest to the given coordinates. -// Input must be lineSpace-local ("div" coordinate system). -function coordsChar(cm, x, y) { - var doc = cm.doc - y += cm.display.viewOffset - if (y < 0) { return PosWithInfo(doc.first, 0, true, -1) } - var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1 - if (lineN > last) - { return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, true, 1) } - if (x < 0) { x = 0 } - - var lineObj = getLine(doc, lineN) - for (;;) { - var found = coordsCharInner(cm, lineObj, lineN, x, y) - var merged = collapsedSpanAtEnd(lineObj) - var mergedPos = merged && merged.find(0, true) - if (merged && (found.ch > mergedPos.from.ch || found.ch == mergedPos.from.ch && found.xRel > 0)) - { lineN = lineNo(lineObj = mergedPos.to.line) } - else - { return found } - } -} - -function coordsCharInner(cm, lineObj, lineNo, x, y) { - var innerOff = y - heightAtLine(lineObj) - var wrongLine = false, adjust = 2 * cm.display.wrapper.clientWidth - var preparedMeasure = prepareMeasureForLine(cm, lineObj) - - function getX(ch) { - var sp = cursorCoords(cm, Pos(lineNo, ch), "line", lineObj, preparedMeasure) - wrongLine = true - if (innerOff > sp.bottom) { return sp.left - adjust } - else if (innerOff < sp.top) { return sp.left + adjust } - else { wrongLine = false } - return sp.left - } - - var bidi = getOrder(lineObj), dist = lineObj.text.length - var from = lineLeft(lineObj), to = lineRight(lineObj) - var fromX = getX(from), fromOutside = wrongLine, toX = getX(to), toOutside = wrongLine - - if (x > toX) { return PosWithInfo(lineNo, to, toOutside, 1) } - // Do a binary search between these bounds. - for (;;) { - if (bidi ? to == from || to == moveVisually(lineObj, from, 1) : to - from <= 1) { - var ch = x < fromX || x - fromX <= toX - x ? from : to - var outside = ch == from ? fromOutside : toOutside - var xDiff = x - (ch == from ? fromX : toX) - // This is a kludge to handle the case where the coordinates - // are after a line-wrapped line. We should replace it with a - // more general handling of cursor positions around line - // breaks. (Issue #4078) - if (toOutside && !bidi && !/\s/.test(lineObj.text.charAt(ch)) && xDiff > 0 && - ch < lineObj.text.length && preparedMeasure.view.measure.heights.length > 1) { - var charSize = measureCharPrepared(cm, preparedMeasure, ch, "right") - if (innerOff <= charSize.bottom && innerOff >= charSize.top && Math.abs(x - charSize.right) < xDiff) { - outside = false - ch++ - xDiff = x - charSize.right - } - } - while (isExtendingChar(lineObj.text.charAt(ch))) { ++ch } - var pos = PosWithInfo(lineNo, ch, outside, xDiff < -1 ? -1 : xDiff > 1 ? 1 : 0) - return pos - } - var step = Math.ceil(dist / 2), middle = from + step - if (bidi) { - middle = from - for (var i = 0; i < step; ++i) { middle = moveVisually(lineObj, middle, 1) } - } - var middleX = getX(middle) - if (middleX > x) {to = middle; toX = middleX; if (toOutside = wrongLine) { toX += 1000; } dist = step} - else {from = middle; fromX = middleX; fromOutside = wrongLine; dist -= step} - } -} - -var measureText -// Compute the default text height. -function textHeight(display) { - if (display.cachedTextHeight != null) { return display.cachedTextHeight } - if (measureText == null) { - measureText = elt("pre") - // Measure a bunch of lines, for browsers that compute - // fractional heights. - for (var i = 0; i < 49; ++i) { - measureText.appendChild(document.createTextNode("x")) - measureText.appendChild(elt("br")) - } - measureText.appendChild(document.createTextNode("x")) - } - removeChildrenAndAdd(display.measure, measureText) - var height = measureText.offsetHeight / 50 - if (height > 3) { display.cachedTextHeight = height } - removeChildren(display.measure) - return height || 1 -} - -// Compute the default character width. -function charWidth(display) { - if (display.cachedCharWidth != null) { return display.cachedCharWidth } - var anchor = elt("span", "xxxxxxxxxx") - var pre = elt("pre", [anchor]) - removeChildrenAndAdd(display.measure, pre) - var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10 - if (width > 2) { display.cachedCharWidth = width } - return width || 10 -} - -// Do a bulk-read of the DOM positions and sizes needed to draw the -// view, so that we don't interleave reading and writing to the DOM. -function getDimensions(cm) { - var d = cm.display, left = {}, width = {} - var gutterLeft = d.gutters.clientLeft - for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) { - left[cm.options.gutters[i]] = n.offsetLeft + n.clientLeft + gutterLeft - width[cm.options.gutters[i]] = n.clientWidth - } - return {fixedPos: compensateForHScroll(d), - gutterTotalWidth: d.gutters.offsetWidth, - gutterLeft: left, - gutterWidth: width, - wrapperWidth: d.wrapper.clientWidth} -} - -// Computes display.scroller.scrollLeft + display.gutters.offsetWidth, -// but using getBoundingClientRect to get a sub-pixel-accurate -// result. -function compensateForHScroll(display) { - return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left -} - -// Returns a function that estimates the height of a line, to use as -// first approximation until the line becomes visible (and is thus -// properly measurable). -function estimateHeight(cm) { - var th = textHeight(cm.display), wrapping = cm.options.lineWrapping - var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3) - return function (line) { - if (lineIsHidden(cm.doc, line)) { return 0 } - - var widgetsHeight = 0 - if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) { - if (line.widgets[i].height) { widgetsHeight += line.widgets[i].height } - } } - - if (wrapping) - { return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th } - else - { return widgetsHeight + th } - } -} - -function estimateLineHeights(cm) { - var doc = cm.doc, est = estimateHeight(cm) - doc.iter(function (line) { - var estHeight = est(line) - if (estHeight != line.height) { updateLineHeight(line, estHeight) } - }) -} - -// Given a mouse event, find the corresponding position. If liberal -// is false, it checks whether a gutter or scrollbar was clicked, -// and returns null if it was. forRect is used by rectangular -// selections, and tries to estimate a character position even for -// coordinates beyond the right of the text. -function posFromMouse(cm, e, liberal, forRect) { - var display = cm.display - if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") { return null } - - var x, y, space = display.lineSpace.getBoundingClientRect() - // Fails unpredictably on IE[67] when mouse is dragged around quickly. - try { x = e.clientX - space.left; y = e.clientY - space.top } - catch (e) { return null } - var coords = coordsChar(cm, x, y), line - if (forRect && coords.xRel == 1 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) { - var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length - coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff)) - } - return coords -} - -// Find the view element corresponding to a given line. Return null -// when the line isn't visible. -function findViewIndex(cm, n) { - if (n >= cm.display.viewTo) { return null } - n -= cm.display.viewFrom - if (n < 0) { return null } - var view = cm.display.view - for (var i = 0; i < view.length; i++) { - n -= view[i].size - if (n < 0) { return i } - } -} - -function updateSelection(cm) { - cm.display.input.showSelection(cm.display.input.prepareSelection()) -} - -function prepareSelection(cm, primary) { - var doc = cm.doc, result = {} - var curFragment = result.cursors = document.createDocumentFragment() - var selFragment = result.selection = document.createDocumentFragment() - - for (var i = 0; i < doc.sel.ranges.length; i++) { - if (primary === false && i == doc.sel.primIndex) { continue } - var range = doc.sel.ranges[i] - if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) { continue } - var collapsed = range.empty() - if (collapsed || cm.options.showCursorWhenSelecting) - { drawSelectionCursor(cm, range.head, curFragment) } - if (!collapsed) - { drawSelectionRange(cm, range, selFragment) } - } - return result -} - -// Draws a cursor for the given range -function drawSelectionCursor(cm, head, output) { - var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine) - - var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor")) - cursor.style.left = pos.left + "px" - cursor.style.top = pos.top + "px" - cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px" - - if (pos.other) { - // Secondary cursor, shown when on a 'jump' in bi-directional text - var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor")) - otherCursor.style.display = "" - otherCursor.style.left = pos.other.left + "px" - otherCursor.style.top = pos.other.top + "px" - otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px" - } -} - -// Draws the given range as a highlighted selection -function drawSelectionRange(cm, range, output) { - var display = cm.display, doc = cm.doc - var fragment = document.createDocumentFragment() - var padding = paddingH(cm.display), leftSide = padding.left - var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right - - function add(left, top, width, bottom) { - if (top < 0) { top = 0 } - top = Math.round(top) - bottom = Math.round(bottom) - fragment.appendChild(elt("div", null, "CodeMirror-selected", ("position: absolute; left: " + left + "px;\n top: " + top + "px; width: " + (width == null ? rightSide - left : width) + "px;\n height: " + (bottom - top) + "px"))) - } - - function drawForLine(line, fromArg, toArg) { - var lineObj = getLine(doc, line) - var lineLen = lineObj.text.length - var start, end - function coords(ch, bias) { - return charCoords(cm, Pos(line, ch), "div", lineObj, bias) - } - - iterateBidiSections(getOrder(lineObj), fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir) { - var leftPos = coords(from, "left"), rightPos, left, right - if (from == to) { - rightPos = leftPos - left = right = leftPos.left - } else { - rightPos = coords(to - 1, "right") - if (dir == "rtl") { var tmp = leftPos; leftPos = rightPos; rightPos = tmp } - left = leftPos.left - right = rightPos.right - } - if (fromArg == null && from == 0) { left = leftSide } - if (rightPos.top - leftPos.top > 3) { // Different lines, draw top part - add(left, leftPos.top, null, leftPos.bottom) - left = leftSide - if (leftPos.bottom < rightPos.top) { add(left, leftPos.bottom, null, rightPos.top) } - } - if (toArg == null && to == lineLen) { right = rightSide } - if (!start || leftPos.top < start.top || leftPos.top == start.top && leftPos.left < start.left) - { start = leftPos } - if (!end || rightPos.bottom > end.bottom || rightPos.bottom == end.bottom && rightPos.right > end.right) - { end = rightPos } - if (left < leftSide + 1) { left = leftSide } - add(left, rightPos.top, right - left, rightPos.bottom) - }) - return {start: start, end: end} - } - - var sFrom = range.from(), sTo = range.to() - if (sFrom.line == sTo.line) { - drawForLine(sFrom.line, sFrom.ch, sTo.ch) - } else { - var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line) - var singleVLine = visualLine(fromLine) == visualLine(toLine) - var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end - var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start - if (singleVLine) { - if (leftEnd.top < rightStart.top - 2) { - add(leftEnd.right, leftEnd.top, null, leftEnd.bottom) - add(leftSide, rightStart.top, rightStart.left, rightStart.bottom) - } else { - add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom) - } - } - if (leftEnd.bottom < rightStart.top) - { add(leftSide, leftEnd.bottom, null, rightStart.top) } - } - - output.appendChild(fragment) -} - -// Cursor-blinking -function restartBlink(cm) { - if (!cm.state.focused) { return } - var display = cm.display - clearInterval(display.blinker) - var on = true - display.cursorDiv.style.visibility = "" - if (cm.options.cursorBlinkRate > 0) - { display.blinker = setInterval(function () { return display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; }, - cm.options.cursorBlinkRate) } - else if (cm.options.cursorBlinkRate < 0) - { display.cursorDiv.style.visibility = "hidden" } -} - -function ensureFocus(cm) { - if (!cm.state.focused) { cm.display.input.focus(); onFocus(cm) } -} - -function delayBlurEvent(cm) { - cm.state.delayingBlurEvent = true - setTimeout(function () { if (cm.state.delayingBlurEvent) { - cm.state.delayingBlurEvent = false - onBlur(cm) - } }, 100) -} - -function onFocus(cm, e) { - if (cm.state.delayingBlurEvent) { cm.state.delayingBlurEvent = false } - - if (cm.options.readOnly == "nocursor") { return } - if (!cm.state.focused) { - signal(cm, "focus", cm, e) - cm.state.focused = true - addClass(cm.display.wrapper, "CodeMirror-focused") - // This test prevents this from firing when a context - // menu is closed (since the input reset would kill the - // select-all detection hack) - if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) { - cm.display.input.reset() - if (webkit) { setTimeout(function () { return cm.display.input.reset(true); }, 20) } // Issue #1730 - } - cm.display.input.receivedFocus() - } - restartBlink(cm) -} -function onBlur(cm, e) { - if (cm.state.delayingBlurEvent) { return } - - if (cm.state.focused) { - signal(cm, "blur", cm, e) - cm.state.focused = false - rmClass(cm.display.wrapper, "CodeMirror-focused") - } - clearInterval(cm.display.blinker) - setTimeout(function () { if (!cm.state.focused) { cm.display.shift = false } }, 150) -} - -// Re-align line numbers and gutter marks to compensate for -// horizontal scrolling. -function alignHorizontally(cm) { - var display = cm.display, view = display.view - if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return } - var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft - var gutterW = display.gutters.offsetWidth, left = comp + "px" - for (var i = 0; i < view.length; i++) { if (!view[i].hidden) { - if (cm.options.fixedGutter) { - if (view[i].gutter) - { view[i].gutter.style.left = left } - if (view[i].gutterBackground) - { view[i].gutterBackground.style.left = left } - } - var align = view[i].alignable - if (align) { for (var j = 0; j < align.length; j++) - { align[j].style.left = left } } - } } - if (cm.options.fixedGutter) - { display.gutters.style.left = (comp + gutterW) + "px" } -} - -// Used to ensure that the line number gutter is still the right -// size for the current document size. Returns true when an update -// is needed. -function maybeUpdateLineNumberWidth(cm) { - if (!cm.options.lineNumbers) { return false } - var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display - if (last.length != display.lineNumChars) { - var test = display.measure.appendChild(elt("div", [elt("div", last)], - "CodeMirror-linenumber CodeMirror-gutter-elt")) - var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW - display.lineGutter.style.width = "" - display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1 - display.lineNumWidth = display.lineNumInnerWidth + padding - display.lineNumChars = display.lineNumInnerWidth ? last.length : -1 - display.lineGutter.style.width = display.lineNumWidth + "px" - updateGutterSpace(cm) - return true - } - return false -} - -// Read the actual heights of the rendered lines, and update their -// stored heights to match. -function updateHeightsInViewport(cm) { - var display = cm.display - var prevBottom = display.lineDiv.offsetTop - for (var i = 0; i < display.view.length; i++) { - var cur = display.view[i], height = (void 0) - if (cur.hidden) { continue } - if (ie && ie_version < 8) { - var bot = cur.node.offsetTop + cur.node.offsetHeight - height = bot - prevBottom - prevBottom = bot - } else { - var box = cur.node.getBoundingClientRect() - height = box.bottom - box.top - } - var diff = cur.line.height - height - if (height < 2) { height = textHeight(display) } - if (diff > .001 || diff < -.001) { - updateLineHeight(cur.line, height) - updateWidgetHeight(cur.line) - if (cur.rest) { for (var j = 0; j < cur.rest.length; j++) - { updateWidgetHeight(cur.rest[j]) } } - } - } -} - -// Read and store the height of line widgets associated with the -// given line. -function updateWidgetHeight(line) { - if (line.widgets) { for (var i = 0; i < line.widgets.length; ++i) - { line.widgets[i].height = line.widgets[i].node.parentNode.offsetHeight } } -} - -// Compute the lines that are visible in a given viewport (defaults -// the the current scroll position). viewport may contain top, -// height, and ensure (see op.scrollToPos) properties. -function visibleLines(display, doc, viewport) { - var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop - top = Math.floor(top - paddingTop(display)) - var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight - - var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom) - // Ensure is a {from: {line, ch}, to: {line, ch}} object, and - // forces those lines into the viewport (if possible). - if (viewport && viewport.ensure) { - var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line - if (ensureFrom < from) { - from = ensureFrom - to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight) - } else if (Math.min(ensureTo, doc.lastLine()) >= to) { - from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight) - to = ensureTo - } - } - return {from: from, to: Math.max(to, from + 1)} -} - -// Sync the scrollable area and scrollbars, ensure the viewport -// covers the visible area. -function setScrollTop(cm, val) { - if (Math.abs(cm.doc.scrollTop - val) < 2) { return } - cm.doc.scrollTop = val - if (!gecko) { updateDisplaySimple(cm, {top: val}) } - if (cm.display.scroller.scrollTop != val) { cm.display.scroller.scrollTop = val } - cm.display.scrollbars.setScrollTop(val) - if (gecko) { updateDisplaySimple(cm) } - startWorker(cm, 100) -} -// Sync scroller and scrollbar, ensure the gutter elements are -// aligned. -function setScrollLeft(cm, val, isScroller) { - if (isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) { return } - val = Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth) - cm.doc.scrollLeft = val - alignHorizontally(cm) - if (cm.display.scroller.scrollLeft != val) { cm.display.scroller.scrollLeft = val } - cm.display.scrollbars.setScrollLeft(val) -} - -// Since the delta values reported on mouse wheel events are -// unstandardized between browsers and even browser versions, and -// generally horribly unpredictable, this code starts by measuring -// the scroll effect that the first few mouse wheel events have, -// and, from that, detects the way it can convert deltas to pixel -// offsets afterwards. -// -// The reason we want to know the amount a wheel event will scroll -// is that it gives us a chance to update the display before the -// actual scrolling happens, reducing flickering. - -var wheelSamples = 0; -var wheelPixelsPerUnit = null; -// Fill in a browser-detected starting value on browsers where we -// know one. These don't have to be accurate -- the result of them -// being wrong would just be a slight flicker on the first wheel -// scroll (if it is large enough). -if (ie) { wheelPixelsPerUnit = -.53 } -else if (gecko) { wheelPixelsPerUnit = 15 } -else if (chrome) { wheelPixelsPerUnit = -.7 } -else if (safari) { wheelPixelsPerUnit = -1/3 } - -function wheelEventDelta(e) { - var dx = e.wheelDeltaX, dy = e.wheelDeltaY - if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { dx = e.detail } - if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { dy = e.detail } - else if (dy == null) { dy = e.wheelDelta } - return {x: dx, y: dy} -} -function wheelEventPixels(e) { - var delta = wheelEventDelta(e) - delta.x *= wheelPixelsPerUnit - delta.y *= wheelPixelsPerUnit - return delta -} - -function onScrollWheel(cm, e) { - var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y - - var display = cm.display, scroll = display.scroller - // Quit if there's nothing to scroll here - var canScrollX = scroll.scrollWidth > scroll.clientWidth - var canScrollY = scroll.scrollHeight > scroll.clientHeight - if (!(dx && canScrollX || dy && canScrollY)) { return } - - // Webkit browsers on OS X abort momentum scrolls when the target - // of the scroll event is removed from the scrollable element. - // This hack (see related code in patchDisplay) makes sure the - // element is kept around. - if (dy && mac && webkit) { - outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) { - for (var i = 0; i < view.length; i++) { - if (view[i].node == cur) { - cm.display.currentWheelTarget = cur - break outer - } - } - } - } - - // On some browsers, horizontal scrolling will cause redraws to - // happen before the gutter has been realigned, causing it to - // wriggle around in a most unseemly way. When we have an - // estimated pixels/delta value, we just handle horizontal - // scrolling entirely here. It'll be slightly off from native, but - // better than glitching out. - if (dx && !gecko && !presto && wheelPixelsPerUnit != null) { - if (dy && canScrollY) - { setScrollTop(cm, Math.max(0, Math.min(scroll.scrollTop + dy * wheelPixelsPerUnit, scroll.scrollHeight - scroll.clientHeight))) } - setScrollLeft(cm, Math.max(0, Math.min(scroll.scrollLeft + dx * wheelPixelsPerUnit, scroll.scrollWidth - scroll.clientWidth))) - // Only prevent default scrolling if vertical scrolling is - // actually possible. Otherwise, it causes vertical scroll - // jitter on OSX trackpads when deltaX is small and deltaY - // is large (issue #3579) - if (!dy || (dy && canScrollY)) - { e_preventDefault(e) } - display.wheelStartX = null // Abort measurement, if in progress - return - } - - // 'Project' the visible viewport to cover the area that is being - // scrolled into view (if we know enough to estimate it). - if (dy && wheelPixelsPerUnit != null) { - var pixels = dy * wheelPixelsPerUnit - var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight - if (pixels < 0) { top = Math.max(0, top + pixels - 50) } - else { bot = Math.min(cm.doc.height, bot + pixels + 50) } - updateDisplaySimple(cm, {top: top, bottom: bot}) - } - - if (wheelSamples < 20) { - if (display.wheelStartX == null) { - display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop - display.wheelDX = dx; display.wheelDY = dy - setTimeout(function () { - if (display.wheelStartX == null) { return } - var movedX = scroll.scrollLeft - display.wheelStartX - var movedY = scroll.scrollTop - display.wheelStartY - var sample = (movedY && display.wheelDY && movedY / display.wheelDY) || - (movedX && display.wheelDX && movedX / display.wheelDX) - display.wheelStartX = display.wheelStartY = null - if (!sample) { return } - wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1) - ++wheelSamples - }, 200) - } else { - display.wheelDX += dx; display.wheelDY += dy - } - } -} - -// SCROLLBARS - -// Prepare DOM reads needed to update the scrollbars. Done in one -// shot to minimize update/measure roundtrips. -function measureForScrollbars(cm) { - var d = cm.display, gutterW = d.gutters.offsetWidth - var docH = Math.round(cm.doc.height + paddingVert(cm.display)) - return { - clientHeight: d.scroller.clientHeight, - viewHeight: d.wrapper.clientHeight, - scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth, - viewWidth: d.wrapper.clientWidth, - barLeft: cm.options.fixedGutter ? gutterW : 0, - docHeight: docH, - scrollHeight: docH + scrollGap(cm) + d.barHeight, - nativeBarWidth: d.nativeBarWidth, - gutterWidth: gutterW - } -} - -var NativeScrollbars = function(place, scroll, cm) { - this.cm = cm - var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar") - var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar") - place(vert); place(horiz) - - on(vert, "scroll", function () { - if (vert.clientHeight) { scroll(vert.scrollTop, "vertical") } - }) - on(horiz, "scroll", function () { - if (horiz.clientWidth) { scroll(horiz.scrollLeft, "horizontal") } - }) - - this.checkedZeroWidth = false - // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). - if (ie && ie_version < 8) { this.horiz.style.minHeight = this.vert.style.minWidth = "18px" } -}; - -NativeScrollbars.prototype.update = function (measure) { - var needsH = measure.scrollWidth > measure.clientWidth + 1 - var needsV = measure.scrollHeight > measure.clientHeight + 1 - var sWidth = measure.nativeBarWidth - - if (needsV) { - this.vert.style.display = "block" - this.vert.style.bottom = needsH ? sWidth + "px" : "0" - var totalHeight = measure.viewHeight - (needsH ? sWidth : 0) - // A bug in IE8 can cause this value to be negative, so guard it. - this.vert.firstChild.style.height = - Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px" - } else { - this.vert.style.display = "" - this.vert.firstChild.style.height = "0" - } - - if (needsH) { - this.horiz.style.display = "block" - this.horiz.style.right = needsV ? sWidth + "px" : "0" - this.horiz.style.left = measure.barLeft + "px" - var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0) - this.horiz.firstChild.style.width = - (measure.scrollWidth - measure.clientWidth + totalWidth) + "px" - } else { - this.horiz.style.display = "" - this.horiz.firstChild.style.width = "0" - } - - if (!this.checkedZeroWidth && measure.clientHeight > 0) { - if (sWidth == 0) { this.zeroWidthHack() } - this.checkedZeroWidth = true - } - - return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0} -}; - -NativeScrollbars.prototype.setScrollLeft = function (pos) { - if (this.horiz.scrollLeft != pos) { this.horiz.scrollLeft = pos } - if (this.disableHoriz) { this.enableZeroWidthBar(this.horiz, this.disableHoriz) } -}; - -NativeScrollbars.prototype.setScrollTop = function (pos) { - if (this.vert.scrollTop != pos) { this.vert.scrollTop = pos } - if (this.disableVert) { this.enableZeroWidthBar(this.vert, this.disableVert) } -}; - -NativeScrollbars.prototype.zeroWidthHack = function () { - var w = mac && !mac_geMountainLion ? "12px" : "18px" - this.horiz.style.height = this.vert.style.width = w - this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none" - this.disableHoriz = new Delayed - this.disableVert = new Delayed -}; - -NativeScrollbars.prototype.enableZeroWidthBar = function (bar, delay) { - bar.style.pointerEvents = "auto" - function maybeDisable() { - // To find out whether the scrollbar is still visible, we - // check whether the element under the pixel in the bottom - // left corner of the scrollbar box is the scrollbar box - // itself (when the bar is still visible) or its filler child - // (when the bar is hidden). If it is still visible, we keep - // it enabled, if it's hidden, we disable pointer events. - var box = bar.getBoundingClientRect() - var elt = document.elementFromPoint(box.left + 1, box.bottom - 1) - if (elt != bar) { bar.style.pointerEvents = "none" } - else { delay.set(1000, maybeDisable) } - } - delay.set(1000, maybeDisable) -}; - -NativeScrollbars.prototype.clear = function () { - var parent = this.horiz.parentNode - parent.removeChild(this.horiz) - parent.removeChild(this.vert) -}; - -var NullScrollbars = function () {}; - -NullScrollbars.prototype.update = function () { return {bottom: 0, right: 0} }; -NullScrollbars.prototype.setScrollLeft = function () {}; -NullScrollbars.prototype.setScrollTop = function () {}; -NullScrollbars.prototype.clear = function () {}; - -function updateScrollbars(cm, measure) { - if (!measure) { measure = measureForScrollbars(cm) } - var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight - updateScrollbarsInner(cm, measure) - for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) { - if (startWidth != cm.display.barWidth && cm.options.lineWrapping) - { updateHeightsInViewport(cm) } - updateScrollbarsInner(cm, measureForScrollbars(cm)) - startWidth = cm.display.barWidth; startHeight = cm.display.barHeight - } -} - -// Re-synchronize the fake scrollbars with the actual size of the -// content. -function updateScrollbarsInner(cm, measure) { - var d = cm.display - var sizes = d.scrollbars.update(measure) - - d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px" - d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px" - d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent" - - if (sizes.right && sizes.bottom) { - d.scrollbarFiller.style.display = "block" - d.scrollbarFiller.style.height = sizes.bottom + "px" - d.scrollbarFiller.style.width = sizes.right + "px" - } else { d.scrollbarFiller.style.display = "" } - if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) { - d.gutterFiller.style.display = "block" - d.gutterFiller.style.height = sizes.bottom + "px" - d.gutterFiller.style.width = measure.gutterWidth + "px" - } else { d.gutterFiller.style.display = "" } -} - -var scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars} - -function initScrollbars(cm) { - if (cm.display.scrollbars) { - cm.display.scrollbars.clear() - if (cm.display.scrollbars.addClass) - { rmClass(cm.display.wrapper, cm.display.scrollbars.addClass) } - } - - cm.display.scrollbars = new scrollbarModel[cm.options.scrollbarStyle](function (node) { - cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller) - // Prevent clicks in the scrollbars from killing focus - on(node, "mousedown", function () { - if (cm.state.focused) { setTimeout(function () { return cm.display.input.focus(); }, 0) } - }) - node.setAttribute("cm-not-content", "true") - }, function (pos, axis) { - if (axis == "horizontal") { setScrollLeft(cm, pos) } - else { setScrollTop(cm, pos) } - }, cm) - if (cm.display.scrollbars.addClass) - { addClass(cm.display.wrapper, cm.display.scrollbars.addClass) } -} - -// SCROLLING THINGS INTO VIEW - -// If an editor sits on the top or bottom of the window, partially -// scrolled out of view, this ensures that the cursor is visible. -function maybeScrollWindow(cm, coords) { - if (signalDOMEvent(cm, "scrollCursorIntoView")) { return } - - var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null - if (coords.top + box.top < 0) { doScroll = true } - else if (coords.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) { doScroll = false } - if (doScroll != null && !phantom) { - var scrollNode = elt("div", "\u200b", null, ("position: absolute;\n top: " + (coords.top - display.viewOffset - paddingTop(cm.display)) + "px;\n height: " + (coords.bottom - coords.top + scrollGap(cm) + display.barHeight) + "px;\n left: " + (coords.left) + "px; width: 2px;")) - cm.display.lineSpace.appendChild(scrollNode) - scrollNode.scrollIntoView(doScroll) - cm.display.lineSpace.removeChild(scrollNode) - } -} - -// Scroll a given position into view (immediately), verifying that -// it actually became visible (as line heights are accurately -// measured, the position of something may 'drift' during drawing). -function scrollPosIntoView(cm, pos, end, margin) { - if (margin == null) { margin = 0 } - var coords - for (var limit = 0; limit < 5; limit++) { - var changed = false - coords = cursorCoords(cm, pos) - var endCoords = !end || end == pos ? coords : cursorCoords(cm, end) - var scrollPos = calculateScrollPos(cm, Math.min(coords.left, endCoords.left), - Math.min(coords.top, endCoords.top) - margin, - Math.max(coords.left, endCoords.left), - Math.max(coords.bottom, endCoords.bottom) + margin) - var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft - if (scrollPos.scrollTop != null) { - setScrollTop(cm, scrollPos.scrollTop) - if (Math.abs(cm.doc.scrollTop - startTop) > 1) { changed = true } - } - if (scrollPos.scrollLeft != null) { - setScrollLeft(cm, scrollPos.scrollLeft) - if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { changed = true } - } - if (!changed) { break } - } - return coords -} - -// Scroll a given set of coordinates into view (immediately). -function scrollIntoView(cm, x1, y1, x2, y2) { - var scrollPos = calculateScrollPos(cm, x1, y1, x2, y2) - if (scrollPos.scrollTop != null) { setScrollTop(cm, scrollPos.scrollTop) } - if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft) } -} - -// Calculate a new scroll position needed to scroll the given -// rectangle into view. Returns an object with scrollTop and -// scrollLeft properties. When these are undefined, the -// vertical/horizontal position does not need to be adjusted. -function calculateScrollPos(cm, x1, y1, x2, y2) { - var display = cm.display, snapMargin = textHeight(cm.display) - if (y1 < 0) { y1 = 0 } - var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop - var screen = displayHeight(cm), result = {} - if (y2 - y1 > screen) { y2 = y1 + screen } - var docBottom = cm.doc.height + paddingVert(display) - var atTop = y1 < snapMargin, atBottom = y2 > docBottom - snapMargin - if (y1 < screentop) { - result.scrollTop = atTop ? 0 : y1 - } else if (y2 > screentop + screen) { - var newTop = Math.min(y1, (atBottom ? docBottom : y2) - screen) - if (newTop != screentop) { result.scrollTop = newTop } - } - - var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft - var screenw = displayWidth(cm) - (cm.options.fixedGutter ? display.gutters.offsetWidth : 0) - var tooWide = x2 - x1 > screenw - if (tooWide) { x2 = x1 + screenw } - if (x1 < 10) - { result.scrollLeft = 0 } - else if (x1 < screenleft) - { result.scrollLeft = Math.max(0, x1 - (tooWide ? 0 : 10)) } - else if (x2 > screenw + screenleft - 3) - { result.scrollLeft = x2 + (tooWide ? 0 : 10) - screenw } - return result -} - -// Store a relative adjustment to the scroll position in the current -// operation (to be applied when the operation finishes). -function addToScrollPos(cm, left, top) { - if (left != null || top != null) { resolveScrollToPos(cm) } - if (left != null) - { cm.curOp.scrollLeft = (cm.curOp.scrollLeft == null ? cm.doc.scrollLeft : cm.curOp.scrollLeft) + left } - if (top != null) - { cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top } -} - -// Make sure that at the end of the operation the current cursor is -// shown. -function ensureCursorVisible(cm) { - resolveScrollToPos(cm) - var cur = cm.getCursor(), from = cur, to = cur - if (!cm.options.lineWrapping) { - from = cur.ch ? Pos(cur.line, cur.ch - 1) : cur - to = Pos(cur.line, cur.ch + 1) - } - cm.curOp.scrollToPos = {from: from, to: to, margin: cm.options.cursorScrollMargin, isCursor: true} -} - -// When an operation has its scrollToPos property set, and another -// scroll action is applied before the end of the operation, this -// 'simulates' scrolling that position into view in a cheap way, so -// that the effect of intermediate scroll commands is not ignored. -function resolveScrollToPos(cm) { - var range = cm.curOp.scrollToPos - if (range) { - cm.curOp.scrollToPos = null - var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to) - var sPos = calculateScrollPos(cm, Math.min(from.left, to.left), - Math.min(from.top, to.top) - range.margin, - Math.max(from.right, to.right), - Math.max(from.bottom, to.bottom) + range.margin) - cm.scrollTo(sPos.scrollLeft, sPos.scrollTop) - } -} - -// Operations are used to wrap a series of changes to the editor -// state in such a way that each change won't have to update the -// cursor and display (which would be awkward, slow, and -// error-prone). Instead, display updates are batched and then all -// combined and executed at once. - -var nextOpId = 0 -// Start a new operation. -function startOperation(cm) { - cm.curOp = { - cm: cm, - viewChanged: false, // Flag that indicates that lines might need to be redrawn - startHeight: cm.doc.height, // Used to detect need to update scrollbar - forceUpdate: false, // Used to force a redraw - updateInput: null, // Whether to reset the input textarea - typing: false, // Whether this reset should be careful to leave existing text (for compositing) - changeObjs: null, // Accumulated changes, for firing change events - cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on - cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already - selectionChanged: false, // Whether the selection needs to be redrawn - updateMaxLine: false, // Set when the widest line needs to be determined anew - scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet - scrollToPos: null, // Used to scroll to a specific position - focus: false, - id: ++nextOpId // Unique ID - } - pushOperation(cm.curOp) -} - -// Finish an operation, updating the display and signalling delayed events -function endOperation(cm) { - var op = cm.curOp - finishOperation(op, function (group) { - for (var i = 0; i < group.ops.length; i++) - { group.ops[i].cm.curOp = null } - endOperations(group) - }) -} - -// The DOM updates done when an operation finishes are batched so -// that the minimum number of relayouts are required. -function endOperations(group) { - var ops = group.ops - for (var i = 0; i < ops.length; i++) // Read DOM - { endOperation_R1(ops[i]) } - for (var i$1 = 0; i$1 < ops.length; i$1++) // Write DOM (maybe) - { endOperation_W1(ops[i$1]) } - for (var i$2 = 0; i$2 < ops.length; i$2++) // Read DOM - { endOperation_R2(ops[i$2]) } - for (var i$3 = 0; i$3 < ops.length; i$3++) // Write DOM (maybe) - { endOperation_W2(ops[i$3]) } - for (var i$4 = 0; i$4 < ops.length; i$4++) // Read DOM - { endOperation_finish(ops[i$4]) } -} - -function endOperation_R1(op) { - var cm = op.cm, display = cm.display - maybeClipScrollbars(cm) - if (op.updateMaxLine) { findMaxLine(cm) } - - op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null || - op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom || - op.scrollToPos.to.line >= display.viewTo) || - display.maxLineChanged && cm.options.lineWrapping - op.update = op.mustUpdate && - new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate) -} - -function endOperation_W1(op) { - op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update) -} - -function endOperation_R2(op) { - var cm = op.cm, display = cm.display - if (op.updatedDisplay) { updateHeightsInViewport(cm) } - - op.barMeasure = measureForScrollbars(cm) - - // If the max line changed since it was last measured, measure it, - // and ensure the document's width matches it. - // updateDisplay_W2 will use these properties to do the actual resizing - if (display.maxLineChanged && !cm.options.lineWrapping) { - op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3 - cm.display.sizerWidth = op.adjustWidthTo - op.barMeasure.scrollWidth = - Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth) - op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm)) - } - - if (op.updatedDisplay || op.selectionChanged) - { op.preparedSelection = display.input.prepareSelection(op.focus) } -} - -function endOperation_W2(op) { - var cm = op.cm - - if (op.adjustWidthTo != null) { - cm.display.sizer.style.minWidth = op.adjustWidthTo + "px" - if (op.maxScrollLeft < cm.doc.scrollLeft) - { setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true) } - cm.display.maxLineChanged = false - } - - var takeFocus = op.focus && op.focus == activeElt() && (!document.hasFocus || document.hasFocus()) - if (op.preparedSelection) - { cm.display.input.showSelection(op.preparedSelection, takeFocus) } - if (op.updatedDisplay || op.startHeight != cm.doc.height) - { updateScrollbars(cm, op.barMeasure) } - if (op.updatedDisplay) - { setDocumentHeight(cm, op.barMeasure) } - - if (op.selectionChanged) { restartBlink(cm) } - - if (cm.state.focused && op.updateInput) - { cm.display.input.reset(op.typing) } - if (takeFocus) { ensureFocus(op.cm) } -} - -function endOperation_finish(op) { - var cm = op.cm, display = cm.display, doc = cm.doc - - if (op.updatedDisplay) { postUpdateDisplay(cm, op.update) } - - // Abort mouse wheel delta measurement, when scrolling explicitly - if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) - { display.wheelStartX = display.wheelStartY = null } - - // Propagate the scroll position to the actual DOM scroller - if (op.scrollTop != null && (display.scroller.scrollTop != op.scrollTop || op.forceScroll)) { - doc.scrollTop = Math.max(0, Math.min(display.scroller.scrollHeight - display.scroller.clientHeight, op.scrollTop)) - display.scrollbars.setScrollTop(doc.scrollTop) - display.scroller.scrollTop = doc.scrollTop - } - if (op.scrollLeft != null && (display.scroller.scrollLeft != op.scrollLeft || op.forceScroll)) { - doc.scrollLeft = Math.max(0, Math.min(display.scroller.scrollWidth - display.scroller.clientWidth, op.scrollLeft)) - display.scrollbars.setScrollLeft(doc.scrollLeft) - display.scroller.scrollLeft = doc.scrollLeft - alignHorizontally(cm) - } - // If we need to scroll a specific position into view, do so. - if (op.scrollToPos) { - var coords = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from), - clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin) - if (op.scrollToPos.isCursor && cm.state.focused) { maybeScrollWindow(cm, coords) } - } - - // Fire events for markers that are hidden/unidden by editing or - // undoing - var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers - if (hidden) { for (var i = 0; i < hidden.length; ++i) - { if (!hidden[i].lines.length) { signal(hidden[i], "hide") } } } - if (unhidden) { for (var i$1 = 0; i$1 < unhidden.length; ++i$1) - { if (unhidden[i$1].lines.length) { signal(unhidden[i$1], "unhide") } } } - - if (display.wrapper.offsetHeight) - { doc.scrollTop = cm.display.scroller.scrollTop } - - // Fire change events, and delayed event handlers - if (op.changeObjs) - { signal(cm, "changes", cm, op.changeObjs) } - if (op.update) - { op.update.finish() } -} - -// Run the given function in an operation -function runInOp(cm, f) { - if (cm.curOp) { return f() } - startOperation(cm) - try { return f() } - finally { endOperation(cm) } -} -// Wraps a function in an operation. Returns the wrapped function. -function operation(cm, f) { - return function() { - if (cm.curOp) { return f.apply(cm, arguments) } - startOperation(cm) - try { return f.apply(cm, arguments) } - finally { endOperation(cm) } - } -} -// Used to add methods to editor and doc instances, wrapping them in -// operations. -function methodOp(f) { - return function() { - if (this.curOp) { return f.apply(this, arguments) } - startOperation(this) - try { return f.apply(this, arguments) } - finally { endOperation(this) } - } -} -function docMethodOp(f) { - return function() { - var cm = this.cm - if (!cm || cm.curOp) { return f.apply(this, arguments) } - startOperation(cm) - try { return f.apply(this, arguments) } - finally { endOperation(cm) } - } -} - -// Updates the display.view data structure for a given change to the -// document. From and to are in pre-change coordinates. Lendiff is -// the amount of lines added or subtracted by the change. This is -// used for changes that span multiple lines, or change the way -// lines are divided into visual lines. regLineChange (below) -// registers single-line changes. -function regChange(cm, from, to, lendiff) { - if (from == null) { from = cm.doc.first } - if (to == null) { to = cm.doc.first + cm.doc.size } - if (!lendiff) { lendiff = 0 } - - var display = cm.display - if (lendiff && to < display.viewTo && - (display.updateLineNumbers == null || display.updateLineNumbers > from)) - { display.updateLineNumbers = from } - - cm.curOp.viewChanged = true - - if (from >= display.viewTo) { // Change after - if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo) - { resetView(cm) } - } else if (to <= display.viewFrom) { // Change before - if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) { - resetView(cm) - } else { - display.viewFrom += lendiff - display.viewTo += lendiff - } - } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap - resetView(cm) - } else if (from <= display.viewFrom) { // Top overlap - var cut = viewCuttingPoint(cm, to, to + lendiff, 1) - if (cut) { - display.view = display.view.slice(cut.index) - display.viewFrom = cut.lineN - display.viewTo += lendiff - } else { - resetView(cm) - } - } else if (to >= display.viewTo) { // Bottom overlap - var cut$1 = viewCuttingPoint(cm, from, from, -1) - if (cut$1) { - display.view = display.view.slice(0, cut$1.index) - display.viewTo = cut$1.lineN - } else { - resetView(cm) - } - } else { // Gap in the middle - var cutTop = viewCuttingPoint(cm, from, from, -1) - var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1) - if (cutTop && cutBot) { - display.view = display.view.slice(0, cutTop.index) - .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN)) - .concat(display.view.slice(cutBot.index)) - display.viewTo += lendiff - } else { - resetView(cm) - } - } - - var ext = display.externalMeasured - if (ext) { - if (to < ext.lineN) - { ext.lineN += lendiff } - else if (from < ext.lineN + ext.size) - { display.externalMeasured = null } - } -} - -// Register a change to a single line. Type must be one of "text", -// "gutter", "class", "widget" -function regLineChange(cm, line, type) { - cm.curOp.viewChanged = true - var display = cm.display, ext = cm.display.externalMeasured - if (ext && line >= ext.lineN && line < ext.lineN + ext.size) - { display.externalMeasured = null } - - if (line < display.viewFrom || line >= display.viewTo) { return } - var lineView = display.view[findViewIndex(cm, line)] - if (lineView.node == null) { return } - var arr = lineView.changes || (lineView.changes = []) - if (indexOf(arr, type) == -1) { arr.push(type) } -} - -// Clear the view. -function resetView(cm) { - cm.display.viewFrom = cm.display.viewTo = cm.doc.first - cm.display.view = [] - cm.display.viewOffset = 0 -} - -function viewCuttingPoint(cm, oldN, newN, dir) { - var index = findViewIndex(cm, oldN), diff, view = cm.display.view - if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size) - { return {index: index, lineN: newN} } - var n = cm.display.viewFrom - for (var i = 0; i < index; i++) - { n += view[i].size } - if (n != oldN) { - if (dir > 0) { - if (index == view.length - 1) { return null } - diff = (n + view[index].size) - oldN - index++ - } else { - diff = n - oldN - } - oldN += diff; newN += diff - } - while (visualLineNo(cm.doc, newN) != newN) { - if (index == (dir < 0 ? 0 : view.length - 1)) { return null } - newN += dir * view[index - (dir < 0 ? 1 : 0)].size - index += dir - } - return {index: index, lineN: newN} -} - -// Force the view to cover a given range, adding empty view element -// or clipping off existing ones as needed. -function adjustView(cm, from, to) { - var display = cm.display, view = display.view - if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) { - display.view = buildViewArray(cm, from, to) - display.viewFrom = from - } else { - if (display.viewFrom > from) - { display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view) } - else if (display.viewFrom < from) - { display.view = display.view.slice(findViewIndex(cm, from)) } - display.viewFrom = from - if (display.viewTo < to) - { display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)) } - else if (display.viewTo > to) - { display.view = display.view.slice(0, findViewIndex(cm, to)) } - } - display.viewTo = to -} - -// Count the number of lines in the view whose DOM representation is -// out of date (or nonexistent). -function countDirtyView(cm) { - var view = cm.display.view, dirty = 0 - for (var i = 0; i < view.length; i++) { - var lineView = view[i] - if (!lineView.hidden && (!lineView.node || lineView.changes)) { ++dirty } - } - return dirty -} - -// HIGHLIGHT WORKER - -function startWorker(cm, time) { - if (cm.doc.mode.startState && cm.doc.frontier < cm.display.viewTo) - { cm.state.highlight.set(time, bind(highlightWorker, cm)) } -} - -function highlightWorker(cm) { - var doc = cm.doc - if (doc.frontier < doc.first) { doc.frontier = doc.first } - if (doc.frontier >= cm.display.viewTo) { return } - var end = +new Date + cm.options.workTime - var state = copyState(doc.mode, getStateBefore(cm, doc.frontier)) - var changedLines = [] - - doc.iter(doc.frontier, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function (line) { - if (doc.frontier >= cm.display.viewFrom) { // Visible - var oldStyles = line.styles, tooLong = line.text.length > cm.options.maxHighlightLength - var highlighted = highlightLine(cm, line, tooLong ? copyState(doc.mode, state) : state, true) - line.styles = highlighted.styles - var oldCls = line.styleClasses, newCls = highlighted.classes - if (newCls) { line.styleClasses = newCls } - else if (oldCls) { line.styleClasses = null } - var ischange = !oldStyles || oldStyles.length != line.styles.length || - oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass) - for (var i = 0; !ischange && i < oldStyles.length; ++i) { ischange = oldStyles[i] != line.styles[i] } - if (ischange) { changedLines.push(doc.frontier) } - line.stateAfter = tooLong ? state : copyState(doc.mode, state) - } else { - if (line.text.length <= cm.options.maxHighlightLength) - { processLine(cm, line.text, state) } - line.stateAfter = doc.frontier % 5 == 0 ? copyState(doc.mode, state) : null - } - ++doc.frontier - if (+new Date > end) { - startWorker(cm, cm.options.workDelay) - return true - } - }) - if (changedLines.length) { runInOp(cm, function () { - for (var i = 0; i < changedLines.length; i++) - { regLineChange(cm, changedLines[i], "text") } - }) } -} - -// DISPLAY DRAWING - -var DisplayUpdate = function(cm, viewport, force) { - var display = cm.display - - this.viewport = viewport - // Store some values that we'll need later (but don't want to force a relayout for) - this.visible = visibleLines(display, cm.doc, viewport) - this.editorIsHidden = !display.wrapper.offsetWidth - this.wrapperHeight = display.wrapper.clientHeight - this.wrapperWidth = display.wrapper.clientWidth - this.oldDisplayWidth = displayWidth(cm) - this.force = force - this.dims = getDimensions(cm) - this.events = [] -}; - -DisplayUpdate.prototype.signal = function (emitter, type) { - if (hasHandler(emitter, type)) - { this.events.push(arguments) } -}; -DisplayUpdate.prototype.finish = function () { - var this$1 = this; - - for (var i = 0; i < this.events.length; i++) - { signal.apply(null, this$1.events[i]) } -}; - -function maybeClipScrollbars(cm) { - var display = cm.display - if (!display.scrollbarsClipped && display.scroller.offsetWidth) { - display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth - display.heightForcer.style.height = scrollGap(cm) + "px" - display.sizer.style.marginBottom = -display.nativeBarWidth + "px" - display.sizer.style.borderRightWidth = scrollGap(cm) + "px" - display.scrollbarsClipped = true - } -} - -// Does the actual updating of the line display. Bails out -// (returning false) when there is nothing to be done and forced is -// false. -function updateDisplayIfNeeded(cm, update) { - var display = cm.display, doc = cm.doc - - if (update.editorIsHidden) { - resetView(cm) - return false - } - - // Bail out if the visible area is already rendered and nothing changed. - if (!update.force && - update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo && - (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) && - display.renderedView == display.view && countDirtyView(cm) == 0) - { return false } - - if (maybeUpdateLineNumberWidth(cm)) { - resetView(cm) - update.dims = getDimensions(cm) - } - - // Compute a suitable new viewport (from & to) - var end = doc.first + doc.size - var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first) - var to = Math.min(end, update.visible.to + cm.options.viewportMargin) - if (display.viewFrom < from && from - display.viewFrom < 20) { from = Math.max(doc.first, display.viewFrom) } - if (display.viewTo > to && display.viewTo - to < 20) { to = Math.min(end, display.viewTo) } - if (sawCollapsedSpans) { - from = visualLineNo(cm.doc, from) - to = visualLineEndNo(cm.doc, to) - } - - var different = from != display.viewFrom || to != display.viewTo || - display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth - adjustView(cm, from, to) - - display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom)) - // Position the mover div to align with the current scroll position - cm.display.mover.style.top = display.viewOffset + "px" - - var toUpdate = countDirtyView(cm) - if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view && - (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo)) - { return false } - - // For big changes, we hide the enclosing element during the - // update, since that speeds up the operations on most browsers. - var focused = activeElt() - if (toUpdate > 4) { display.lineDiv.style.display = "none" } - patchDisplay(cm, display.updateLineNumbers, update.dims) - if (toUpdate > 4) { display.lineDiv.style.display = "" } - display.renderedView = display.view - // There might have been a widget with a focused element that got - // hidden or updated, if so re-focus it. - if (focused && activeElt() != focused && focused.offsetHeight) { focused.focus() } - - // Prevent selection and cursors from interfering with the scroll - // width and height. - removeChildren(display.cursorDiv) - removeChildren(display.selectionDiv) - display.gutters.style.height = display.sizer.style.minHeight = 0 - - if (different) { - display.lastWrapHeight = update.wrapperHeight - display.lastWrapWidth = update.wrapperWidth - startWorker(cm, 400) - } - - display.updateLineNumbers = null - - return true -} - -function postUpdateDisplay(cm, update) { - var viewport = update.viewport - - for (var first = true;; first = false) { - if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) { - // Clip forced viewport to actual scrollable area. - if (viewport && viewport.top != null) - { viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)} } - // Updated line heights might result in the drawn area not - // actually covering the viewport. Keep looping until it does. - update.visible = visibleLines(cm.display, cm.doc, viewport) - if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo) - { break } - } - if (!updateDisplayIfNeeded(cm, update)) { break } - updateHeightsInViewport(cm) - var barMeasure = measureForScrollbars(cm) - updateSelection(cm) - updateScrollbars(cm, barMeasure) - setDocumentHeight(cm, barMeasure) - } - - update.signal(cm, "update", cm) - if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) { - update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo) - cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo - } -} - -function updateDisplaySimple(cm, viewport) { - var update = new DisplayUpdate(cm, viewport) - if (updateDisplayIfNeeded(cm, update)) { - updateHeightsInViewport(cm) - postUpdateDisplay(cm, update) - var barMeasure = measureForScrollbars(cm) - updateSelection(cm) - updateScrollbars(cm, barMeasure) - setDocumentHeight(cm, barMeasure) - update.finish() - } -} - -// Sync the actual display DOM structure with display.view, removing -// nodes for lines that are no longer in view, and creating the ones -// that are not there yet, and updating the ones that are out of -// date. -function patchDisplay(cm, updateNumbersFrom, dims) { - var display = cm.display, lineNumbers = cm.options.lineNumbers - var container = display.lineDiv, cur = container.firstChild - - function rm(node) { - var next = node.nextSibling - // Works around a throw-scroll bug in OS X Webkit - if (webkit && mac && cm.display.currentWheelTarget == node) - { node.style.display = "none" } - else - { node.parentNode.removeChild(node) } - return next - } - - var view = display.view, lineN = display.viewFrom - // Loop over the elements in the view, syncing cur (the DOM nodes - // in display.lineDiv) with the view as we go. - for (var i = 0; i < view.length; i++) { - var lineView = view[i] - if (lineView.hidden) { - } else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet - var node = buildLineElement(cm, lineView, lineN, dims) - container.insertBefore(node, cur) - } else { // Already drawn - while (cur != lineView.node) { cur = rm(cur) } - var updateNumber = lineNumbers && updateNumbersFrom != null && - updateNumbersFrom <= lineN && lineView.lineNumber - if (lineView.changes) { - if (indexOf(lineView.changes, "gutter") > -1) { updateNumber = false } - updateLineForChanges(cm, lineView, lineN, dims) - } - if (updateNumber) { - removeChildren(lineView.lineNumber) - lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN))) - } - cur = lineView.node.nextSibling - } - lineN += lineView.size - } - while (cur) { cur = rm(cur) } -} - -function updateGutterSpace(cm) { - var width = cm.display.gutters.offsetWidth - cm.display.sizer.style.marginLeft = width + "px" -} - -function setDocumentHeight(cm, measure) { - cm.display.sizer.style.minHeight = measure.docHeight + "px" - cm.display.heightForcer.style.top = measure.docHeight + "px" - cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px" -} - -// Rebuild the gutter elements, ensure the margin to the left of the -// code matches their width. -function updateGutters(cm) { - var gutters = cm.display.gutters, specs = cm.options.gutters - removeChildren(gutters) - var i = 0 - for (; i < specs.length; ++i) { - var gutterClass = specs[i] - var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + gutterClass)) - if (gutterClass == "CodeMirror-linenumbers") { - cm.display.lineGutter = gElt - gElt.style.width = (cm.display.lineNumWidth || 1) + "px" - } - } - gutters.style.display = i ? "" : "none" - updateGutterSpace(cm) -} - -// Make sure the gutters options contains the element -// "CodeMirror-linenumbers" when the lineNumbers option is true. -function setGuttersForLineNumbers(options) { - var found = indexOf(options.gutters, "CodeMirror-linenumbers") - if (found == -1 && options.lineNumbers) { - options.gutters = options.gutters.concat(["CodeMirror-linenumbers"]) - } else if (found > -1 && !options.lineNumbers) { - options.gutters = options.gutters.slice(0) - options.gutters.splice(found, 1) - } -} - -// Selection objects are immutable. A new one is created every time -// the selection changes. A selection is one or more non-overlapping -// (and non-touching) ranges, sorted, and an integer that indicates -// which one is the primary selection (the one that's scrolled into -// view, that getCursor returns, etc). -function Selection(ranges, primIndex) { - this.ranges = ranges - this.primIndex = primIndex -} - -Selection.prototype = { - primary: function() { return this.ranges[this.primIndex] }, - equals: function(other) { - var this$1 = this; - - if (other == this) { return true } - if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) { return false } - for (var i = 0; i < this.ranges.length; i++) { - var here = this$1.ranges[i], there = other.ranges[i] - if (cmp(here.anchor, there.anchor) != 0 || cmp(here.head, there.head) != 0) { return false } - } - return true - }, - deepCopy: function() { - var this$1 = this; - - var out = [] - for (var i = 0; i < this.ranges.length; i++) - { out[i] = new Range(copyPos(this$1.ranges[i].anchor), copyPos(this$1.ranges[i].head)) } - return new Selection(out, this.primIndex) - }, - somethingSelected: function() { - var this$1 = this; - - for (var i = 0; i < this.ranges.length; i++) - { if (!this$1.ranges[i].empty()) { return true } } - return false - }, - contains: function(pos, end) { - var this$1 = this; - - if (!end) { end = pos } - for (var i = 0; i < this.ranges.length; i++) { - var range = this$1.ranges[i] - if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0) - { return i } - } - return -1 - } -} - -function Range(anchor, head) { - this.anchor = anchor; this.head = head -} - -Range.prototype = { - from: function() { return minPos(this.anchor, this.head) }, - to: function() { return maxPos(this.anchor, this.head) }, - empty: function() { - return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch - } -} - -// Take an unsorted, potentially overlapping set of ranges, and -// build a selection out of it. 'Consumes' ranges array (modifying -// it). -function normalizeSelection(ranges, primIndex) { - var prim = ranges[primIndex] - ranges.sort(function (a, b) { return cmp(a.from(), b.from()); }) - primIndex = indexOf(ranges, prim) - for (var i = 1; i < ranges.length; i++) { - var cur = ranges[i], prev = ranges[i - 1] - if (cmp(prev.to(), cur.from()) >= 0) { - var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to()) - var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head - if (i <= primIndex) { --primIndex } - ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to)) - } - } - return new Selection(ranges, primIndex) -} - -function simpleSelection(anchor, head) { - return new Selection([new Range(anchor, head || anchor)], 0) -} - -// Compute the position of the end of a change (its 'to' property -// refers to the pre-change end). -function changeEnd(change) { - if (!change.text) { return change.to } - return Pos(change.from.line + change.text.length - 1, - lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0)) -} - -// Adjust a position to refer to the post-change position of the -// same text, or the end of the change if the change covers it. -function adjustForChange(pos, change) { - if (cmp(pos, change.from) < 0) { return pos } - if (cmp(pos, change.to) <= 0) { return changeEnd(change) } - - var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch - if (pos.line == change.to.line) { ch += changeEnd(change).ch - change.to.ch } - return Pos(line, ch) -} - -function computeSelAfterChange(doc, change) { - var out = [] - for (var i = 0; i < doc.sel.ranges.length; i++) { - var range = doc.sel.ranges[i] - out.push(new Range(adjustForChange(range.anchor, change), - adjustForChange(range.head, change))) - } - return normalizeSelection(out, doc.sel.primIndex) -} - -function offsetPos(pos, old, nw) { - if (pos.line == old.line) - { return Pos(nw.line, pos.ch - old.ch + nw.ch) } - else - { return Pos(nw.line + (pos.line - old.line), pos.ch) } -} - -// Used by replaceSelections to allow moving the selection to the -// start or around the replaced test. Hint may be "start" or "around". -function computeReplacedSel(doc, changes, hint) { - var out = [] - var oldPrev = Pos(doc.first, 0), newPrev = oldPrev - for (var i = 0; i < changes.length; i++) { - var change = changes[i] - var from = offsetPos(change.from, oldPrev, newPrev) - var to = offsetPos(changeEnd(change), oldPrev, newPrev) - oldPrev = change.to - newPrev = to - if (hint == "around") { - var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0 - out[i] = new Range(inv ? to : from, inv ? from : to) - } else { - out[i] = new Range(from, from) - } - } - return new Selection(out, doc.sel.primIndex) -} - -// Used to get the editor into a consistent state again when options change. - -function loadMode(cm) { - cm.doc.mode = getMode(cm.options, cm.doc.modeOption) - resetModeState(cm) -} - -function resetModeState(cm) { - cm.doc.iter(function (line) { - if (line.stateAfter) { line.stateAfter = null } - if (line.styles) { line.styles = null } - }) - cm.doc.frontier = cm.doc.first - startWorker(cm, 100) - cm.state.modeGen++ - if (cm.curOp) { regChange(cm) } -} - -// DOCUMENT DATA STRUCTURE - -// By default, updates that start and end at the beginning of a line -// are treated specially, in order to make the association of line -// widgets and marker elements with the text behave more intuitive. -function isWholeLineUpdate(doc, change) { - return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" && - (!doc.cm || doc.cm.options.wholeLineUpdateBefore) -} - -// Perform a change on the document data structure. -function updateDoc(doc, change, markedSpans, estimateHeight) { - function spansFor(n) {return markedSpans ? markedSpans[n] : null} - function update(line, text, spans) { - updateLine(line, text, spans, estimateHeight) - signalLater(line, "change", line, change) - } - function linesFor(start, end) { - var result = [] - for (var i = start; i < end; ++i) - { result.push(new Line(text[i], spansFor(i), estimateHeight)) } - return result - } - - var from = change.from, to = change.to, text = change.text - var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line) - var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line - - // Adjust the line structure - if (change.full) { - doc.insert(0, linesFor(0, text.length)) - doc.remove(text.length, doc.size - text.length) - } else if (isWholeLineUpdate(doc, change)) { - // This is a whole-line replace. Treated specially to make - // sure line objects move the way they are supposed to. - var added = linesFor(0, text.length - 1) - update(lastLine, lastLine.text, lastSpans) - if (nlines) { doc.remove(from.line, nlines) } - if (added.length) { doc.insert(from.line, added) } - } else if (firstLine == lastLine) { - if (text.length == 1) { - update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans) - } else { - var added$1 = linesFor(1, text.length - 1) - added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight)) - update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)) - doc.insert(from.line + 1, added$1) - } - } else if (text.length == 1) { - update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0)) - doc.remove(from.line + 1, nlines) - } else { - update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)) - update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans) - var added$2 = linesFor(1, text.length - 1) - if (nlines > 1) { doc.remove(from.line + 1, nlines - 1) } - doc.insert(from.line + 1, added$2) - } - - signalLater(doc, "change", doc, change) -} - -// Call f for all linked documents. -function linkedDocs(doc, f, sharedHistOnly) { - function propagate(doc, skip, sharedHist) { - if (doc.linked) { for (var i = 0; i < doc.linked.length; ++i) { - var rel = doc.linked[i] - if (rel.doc == skip) { continue } - var shared = sharedHist && rel.sharedHist - if (sharedHistOnly && !shared) { continue } - f(rel.doc, shared) - propagate(rel.doc, doc, shared) - } } - } - propagate(doc, null, true) -} - -// Attach a document to an editor. -function attachDoc(cm, doc) { - if (doc.cm) { throw new Error("This document is already in use.") } - cm.doc = doc - doc.cm = cm - estimateLineHeights(cm) - loadMode(cm) - if (!cm.options.lineWrapping) { findMaxLine(cm) } - cm.options.mode = doc.modeOption - regChange(cm) -} - -function History(startGen) { - // Arrays of change events and selections. Doing something adds an - // event to done and clears undo. Undoing moves events from done - // to undone, redoing moves them in the other direction. - this.done = []; this.undone = [] - this.undoDepth = Infinity - // Used to track when changes can be merged into a single undo - // event - this.lastModTime = this.lastSelTime = 0 - this.lastOp = this.lastSelOp = null - this.lastOrigin = this.lastSelOrigin = null - // Used by the isClean() method - this.generation = this.maxGeneration = startGen || 1 -} - -// Create a history change event from an updateDoc-style change -// object. -function historyChangeFromChange(doc, change) { - var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)} - attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1) - linkedDocs(doc, function (doc) { return attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); }, true) - return histChange -} - -// Pop all selection events off the end of a history array. Stop at -// a change event. -function clearSelectionEvents(array) { - while (array.length) { - var last = lst(array) - if (last.ranges) { array.pop() } - else { break } - } -} - -// Find the top change event in the history. Pop off selection -// events that are in the way. -function lastChangeEvent(hist, force) { - if (force) { - clearSelectionEvents(hist.done) - return lst(hist.done) - } else if (hist.done.length && !lst(hist.done).ranges) { - return lst(hist.done) - } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) { - hist.done.pop() - return lst(hist.done) - } -} - -// Register a change in the history. Merges changes that are within -// a single operation, or are close together with an origin that -// allows merging (starting with "+") into a single event. -function addChangeToHistory(doc, change, selAfter, opId) { - var hist = doc.history - hist.undone.length = 0 - var time = +new Date, cur - var last - - if ((hist.lastOp == opId || - hist.lastOrigin == change.origin && change.origin && - ((change.origin.charAt(0) == "+" && doc.cm && hist.lastModTime > time - doc.cm.options.historyEventDelay) || - change.origin.charAt(0) == "*")) && - (cur = lastChangeEvent(hist, hist.lastOp == opId))) { - // Merge this change into the last event - last = lst(cur.changes) - if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) { - // Optimized case for simple insertion -- don't want to add - // new changesets for every character typed - last.to = changeEnd(change) - } else { - // Add new sub-event - cur.changes.push(historyChangeFromChange(doc, change)) - } - } else { - // Can not be merged, start a new event. - var before = lst(hist.done) - if (!before || !before.ranges) - { pushSelectionToHistory(doc.sel, hist.done) } - cur = {changes: [historyChangeFromChange(doc, change)], - generation: hist.generation} - hist.done.push(cur) - while (hist.done.length > hist.undoDepth) { - hist.done.shift() - if (!hist.done[0].ranges) { hist.done.shift() } - } - } - hist.done.push(selAfter) - hist.generation = ++hist.maxGeneration - hist.lastModTime = hist.lastSelTime = time - hist.lastOp = hist.lastSelOp = opId - hist.lastOrigin = hist.lastSelOrigin = change.origin - - if (!last) { signal(doc, "historyAdded") } -} - -function selectionEventCanBeMerged(doc, origin, prev, sel) { - var ch = origin.charAt(0) - return ch == "*" || - ch == "+" && - prev.ranges.length == sel.ranges.length && - prev.somethingSelected() == sel.somethingSelected() && - new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500) -} - -// Called whenever the selection changes, sets the new selection as -// the pending selection in the history, and pushes the old pending -// selection into the 'done' array when it was significantly -// different (in number of selected ranges, emptiness, or time). -function addSelectionToHistory(doc, sel, opId, options) { - var hist = doc.history, origin = options && options.origin - - // A new event is started when the previous origin does not match - // the current, or the origins don't allow matching. Origins - // starting with * are always merged, those starting with + are - // merged when similar and close together in time. - if (opId == hist.lastSelOp || - (origin && hist.lastSelOrigin == origin && - (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin || - selectionEventCanBeMerged(doc, origin, lst(hist.done), sel)))) - { hist.done[hist.done.length - 1] = sel } - else - { pushSelectionToHistory(sel, hist.done) } - - hist.lastSelTime = +new Date - hist.lastSelOrigin = origin - hist.lastSelOp = opId - if (options && options.clearRedo !== false) - { clearSelectionEvents(hist.undone) } -} - -function pushSelectionToHistory(sel, dest) { - var top = lst(dest) - if (!(top && top.ranges && top.equals(sel))) - { dest.push(sel) } -} - -// Used to store marked span information in the history. -function attachLocalSpans(doc, change, from, to) { - var existing = change["spans_" + doc.id], n = 0 - doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function (line) { - if (line.markedSpans) - { (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans } - ++n - }) -} - -// When un/re-doing restores text containing marked spans, those -// that have been explicitly cleared should not be restored. -function removeClearedSpans(spans) { - if (!spans) { return null } - var out - for (var i = 0; i < spans.length; ++i) { - if (spans[i].marker.explicitlyCleared) { if (!out) { out = spans.slice(0, i) } } - else if (out) { out.push(spans[i]) } - } - return !out ? spans : out.length ? out : null -} - -// Retrieve and filter the old marked spans stored in a change event. -function getOldSpans(doc, change) { - var found = change["spans_" + doc.id] - if (!found) { return null } - var nw = [] - for (var i = 0; i < change.text.length; ++i) - { nw.push(removeClearedSpans(found[i])) } - return nw -} - -// Used for un/re-doing changes from the history. Combines the -// result of computing the existing spans with the set of spans that -// existed in the history (so that deleting around a span and then -// undoing brings back the span). -function mergeOldSpans(doc, change) { - var old = getOldSpans(doc, change) - var stretched = stretchSpansOverChange(doc, change) - if (!old) { return stretched } - if (!stretched) { return old } - - for (var i = 0; i < old.length; ++i) { - var oldCur = old[i], stretchCur = stretched[i] - if (oldCur && stretchCur) { - spans: for (var j = 0; j < stretchCur.length; ++j) { - var span = stretchCur[j] - for (var k = 0; k < oldCur.length; ++k) - { if (oldCur[k].marker == span.marker) { continue spans } } - oldCur.push(span) - } - } else if (stretchCur) { - old[i] = stretchCur - } - } - return old -} - -// Used both to provide a JSON-safe object in .getHistory, and, when -// detaching a document, to split the history in two -function copyHistoryArray(events, newGroup, instantiateSel) { - var copy = [] - for (var i = 0; i < events.length; ++i) { - var event = events[i] - if (event.ranges) { - copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event) - continue - } - var changes = event.changes, newChanges = [] - copy.push({changes: newChanges}) - for (var j = 0; j < changes.length; ++j) { - var change = changes[j], m = (void 0) - newChanges.push({from: change.from, to: change.to, text: change.text}) - if (newGroup) { for (var prop in change) { if (m = prop.match(/^spans_(\d+)$/)) { - if (indexOf(newGroup, Number(m[1])) > -1) { - lst(newChanges)[prop] = change[prop] - delete change[prop] - } - } } } - } - } - return copy -} - -// The 'scroll' parameter given to many of these indicated whether -// the new cursor position should be scrolled into view after -// modifying the selection. - -// If shift is held or the extend flag is set, extends a range to -// include a given position (and optionally a second position). -// Otherwise, simply returns the range between the given positions. -// Used for cursor motion and such. -function extendRange(doc, range, head, other) { - if (doc.cm && doc.cm.display.shift || doc.extend) { - var anchor = range.anchor - if (other) { - var posBefore = cmp(head, anchor) < 0 - if (posBefore != (cmp(other, anchor) < 0)) { - anchor = head - head = other - } else if (posBefore != (cmp(head, other) < 0)) { - head = other - } - } - return new Range(anchor, head) - } else { - return new Range(other || head, head) - } -} - -// Extend the primary selection range, discard the rest. -function extendSelection(doc, head, other, options) { - setSelection(doc, new Selection([extendRange(doc, doc.sel.primary(), head, other)], 0), options) -} - -// Extend all selections (pos is an array of selections with length -// equal the number of selections) -function extendSelections(doc, heads, options) { - var out = [] - for (var i = 0; i < doc.sel.ranges.length; i++) - { out[i] = extendRange(doc, doc.sel.ranges[i], heads[i], null) } - var newSel = normalizeSelection(out, doc.sel.primIndex) - setSelection(doc, newSel, options) -} - -// Updates a single range in the selection. -function replaceOneSelection(doc, i, range, options) { - var ranges = doc.sel.ranges.slice(0) - ranges[i] = range - setSelection(doc, normalizeSelection(ranges, doc.sel.primIndex), options) -} - -// Reset the selection to a single range. -function setSimpleSelection(doc, anchor, head, options) { - setSelection(doc, simpleSelection(anchor, head), options) -} - -// Give beforeSelectionChange handlers a change to influence a -// selection update. -function filterSelectionChange(doc, sel, options) { - var obj = { - ranges: sel.ranges, - update: function(ranges) { - var this$1 = this; - - this.ranges = [] - for (var i = 0; i < ranges.length; i++) - { this$1.ranges[i] = new Range(clipPos(doc, ranges[i].anchor), - clipPos(doc, ranges[i].head)) } - }, - origin: options && options.origin - } - signal(doc, "beforeSelectionChange", doc, obj) - if (doc.cm) { signal(doc.cm, "beforeSelectionChange", doc.cm, obj) } - if (obj.ranges != sel.ranges) { return normalizeSelection(obj.ranges, obj.ranges.length - 1) } - else { return sel } -} - -function setSelectionReplaceHistory(doc, sel, options) { - var done = doc.history.done, last = lst(done) - if (last && last.ranges) { - done[done.length - 1] = sel - setSelectionNoUndo(doc, sel, options) - } else { - setSelection(doc, sel, options) - } -} - -// Set a new selection. -function setSelection(doc, sel, options) { - setSelectionNoUndo(doc, sel, options) - addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options) -} - -function setSelectionNoUndo(doc, sel, options) { - if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) - { sel = filterSelectionChange(doc, sel, options) } - - var bias = options && options.bias || - (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1) - setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true)) - - if (!(options && options.scroll === false) && doc.cm) - { ensureCursorVisible(doc.cm) } -} - -function setSelectionInner(doc, sel) { - if (sel.equals(doc.sel)) { return } - - doc.sel = sel - - if (doc.cm) { - doc.cm.curOp.updateInput = doc.cm.curOp.selectionChanged = true - signalCursorActivity(doc.cm) - } - signalLater(doc, "cursorActivity", doc) -} - -// Verify that the selection does not partially select any atomic -// marked ranges. -function reCheckSelection(doc) { - setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false), sel_dontScroll) -} - -// Return a selection that does not partially select any atomic -// ranges. -function skipAtomicInSelection(doc, sel, bias, mayClear) { - var out - for (var i = 0; i < sel.ranges.length; i++) { - var range = sel.ranges[i] - var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i] - var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear) - var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear) - if (out || newAnchor != range.anchor || newHead != range.head) { - if (!out) { out = sel.ranges.slice(0, i) } - out[i] = new Range(newAnchor, newHead) - } - } - return out ? normalizeSelection(out, sel.primIndex) : sel -} - -function skipAtomicInner(doc, pos, oldPos, dir, mayClear) { - var line = getLine(doc, pos.line) - if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { - var sp = line.markedSpans[i], m = sp.marker - if ((sp.from == null || (m.inclusiveLeft ? sp.from <= pos.ch : sp.from < pos.ch)) && - (sp.to == null || (m.inclusiveRight ? sp.to >= pos.ch : sp.to > pos.ch))) { - if (mayClear) { - signal(m, "beforeCursorEnter") - if (m.explicitlyCleared) { - if (!line.markedSpans) { break } - else {--i; continue} - } - } - if (!m.atomic) { continue } - - if (oldPos) { - var near = m.find(dir < 0 ? 1 : -1), diff = (void 0) - if (dir < 0 ? m.inclusiveRight : m.inclusiveLeft) - { near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null) } - if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0)) - { return skipAtomicInner(doc, near, pos, dir, mayClear) } - } - - var far = m.find(dir < 0 ? -1 : 1) - if (dir < 0 ? m.inclusiveLeft : m.inclusiveRight) - { far = movePos(doc, far, dir, far.line == pos.line ? line : null) } - return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null - } - } } - return pos -} - -// Ensure a given position is not inside an atomic range. -function skipAtomic(doc, pos, oldPos, bias, mayClear) { - var dir = bias || 1 - var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) || - (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) || - skipAtomicInner(doc, pos, oldPos, -dir, mayClear) || - (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true)) - if (!found) { - doc.cantEdit = true - return Pos(doc.first, 0) - } - return found -} - -function movePos(doc, pos, dir, line) { - if (dir < 0 && pos.ch == 0) { - if (pos.line > doc.first) { return clipPos(doc, Pos(pos.line - 1)) } - else { return null } - } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) { - if (pos.line < doc.first + doc.size - 1) { return Pos(pos.line + 1, 0) } - else { return null } - } else { - return new Pos(pos.line, pos.ch + dir) - } -} - -function selectAll(cm) { - cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll) -} - -// UPDATING - -// Allow "beforeChange" event handlers to influence a change -function filterChange(doc, change, update) { - var obj = { - canceled: false, - from: change.from, - to: change.to, - text: change.text, - origin: change.origin, - cancel: function () { return obj.canceled = true; } - } - if (update) { obj.update = function (from, to, text, origin) { - if (from) { obj.from = clipPos(doc, from) } - if (to) { obj.to = clipPos(doc, to) } - if (text) { obj.text = text } - if (origin !== undefined) { obj.origin = origin } - } } - signal(doc, "beforeChange", doc, obj) - if (doc.cm) { signal(doc.cm, "beforeChange", doc.cm, obj) } - - if (obj.canceled) { return null } - return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin} -} - -// Apply a change to a document, and add it to the document's -// history, and propagating it to all linked documents. -function makeChange(doc, change, ignoreReadOnly) { - if (doc.cm) { - if (!doc.cm.curOp) { return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly) } - if (doc.cm.state.suppressEdits) { return } - } - - if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) { - change = filterChange(doc, change, true) - if (!change) { return } - } - - // Possibly split or suppress the update based on the presence - // of read-only spans in its range. - var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to) - if (split) { - for (var i = split.length - 1; i >= 0; --i) - { makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text}) } - } else { - makeChangeInner(doc, change) - } -} - -function makeChangeInner(doc, change) { - if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) { return } - var selAfter = computeSelAfterChange(doc, change) - addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN) - - makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change)) - var rebased = [] - - linkedDocs(doc, function (doc, sharedHist) { - if (!sharedHist && indexOf(rebased, doc.history) == -1) { - rebaseHist(doc.history, change) - rebased.push(doc.history) - } - makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change)) - }) -} - -// Revert a change stored in a document's history. -function makeChangeFromHistory(doc, type, allowSelectionOnly) { - if (doc.cm && doc.cm.state.suppressEdits && !allowSelectionOnly) { return } - - var hist = doc.history, event, selAfter = doc.sel - var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done - - // Verify that there is a useable event (so that ctrl-z won't - // needlessly clear selection events) - var i = 0 - for (; i < source.length; i++) { - event = source[i] - if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges) - { break } - } - if (i == source.length) { return } - hist.lastOrigin = hist.lastSelOrigin = null - - for (;;) { - event = source.pop() - if (event.ranges) { - pushSelectionToHistory(event, dest) - if (allowSelectionOnly && !event.equals(doc.sel)) { - setSelection(doc, event, {clearRedo: false}) - return - } - selAfter = event - } - else { break } - } - - // Build up a reverse change object to add to the opposite history - // stack (redo when undoing, and vice versa). - var antiChanges = [] - pushSelectionToHistory(selAfter, dest) - dest.push({changes: antiChanges, generation: hist.generation}) - hist.generation = event.generation || ++hist.maxGeneration - - var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange") - - var loop = function ( i ) { - var change = event.changes[i] - change.origin = type - if (filter && !filterChange(doc, change, false)) { - source.length = 0 - return {} - } - - antiChanges.push(historyChangeFromChange(doc, change)) - - var after = i ? computeSelAfterChange(doc, change) : lst(source) - makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)) - if (!i && doc.cm) { doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}) } - var rebased = [] - - // Propagate to the linked documents - linkedDocs(doc, function (doc, sharedHist) { - if (!sharedHist && indexOf(rebased, doc.history) == -1) { - rebaseHist(doc.history, change) - rebased.push(doc.history) - } - makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change)) - }) - }; - - for (var i$1 = event.changes.length - 1; i$1 >= 0; --i$1) { - var returned = loop( i$1 ); - - if ( returned ) return returned.v; - } -} - -// Sub-views need their line numbers shifted when text is added -// above or below them in the parent document. -function shiftDoc(doc, distance) { - if (distance == 0) { return } - doc.first += distance - doc.sel = new Selection(map(doc.sel.ranges, function (range) { return new Range( - Pos(range.anchor.line + distance, range.anchor.ch), - Pos(range.head.line + distance, range.head.ch) - ); }), doc.sel.primIndex) - if (doc.cm) { - regChange(doc.cm, doc.first, doc.first - distance, distance) - for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++) - { regLineChange(doc.cm, l, "gutter") } - } -} - -// More lower-level change function, handling only a single document -// (not linked ones). -function makeChangeSingleDoc(doc, change, selAfter, spans) { - if (doc.cm && !doc.cm.curOp) - { return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans) } - - if (change.to.line < doc.first) { - shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line)) - return - } - if (change.from.line > doc.lastLine()) { return } - - // Clip the change to the size of this doc - if (change.from.line < doc.first) { - var shift = change.text.length - 1 - (doc.first - change.from.line) - shiftDoc(doc, shift) - change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch), - text: [lst(change.text)], origin: change.origin} - } - var last = doc.lastLine() - if (change.to.line > last) { - change = {from: change.from, to: Pos(last, getLine(doc, last).text.length), - text: [change.text[0]], origin: change.origin} - } - - change.removed = getBetween(doc, change.from, change.to) - - if (!selAfter) { selAfter = computeSelAfterChange(doc, change) } - if (doc.cm) { makeChangeSingleDocInEditor(doc.cm, change, spans) } - else { updateDoc(doc, change, spans) } - setSelectionNoUndo(doc, selAfter, sel_dontScroll) -} - -// Handle the interaction of a change to a document with the editor -// that this document is part of. -function makeChangeSingleDocInEditor(cm, change, spans) { - var doc = cm.doc, display = cm.display, from = change.from, to = change.to - - var recomputeMaxLength = false, checkWidthStart = from.line - if (!cm.options.lineWrapping) { - checkWidthStart = lineNo(visualLine(getLine(doc, from.line))) - doc.iter(checkWidthStart, to.line + 1, function (line) { - if (line == display.maxLine) { - recomputeMaxLength = true - return true - } - }) - } - - if (doc.sel.contains(change.from, change.to) > -1) - { signalCursorActivity(cm) } - - updateDoc(doc, change, spans, estimateHeight(cm)) - - if (!cm.options.lineWrapping) { - doc.iter(checkWidthStart, from.line + change.text.length, function (line) { - var len = lineLength(line) - if (len > display.maxLineLength) { - display.maxLine = line - display.maxLineLength = len - display.maxLineChanged = true - recomputeMaxLength = false - } - }) - if (recomputeMaxLength) { cm.curOp.updateMaxLine = true } - } - - // Adjust frontier, schedule worker - doc.frontier = Math.min(doc.frontier, from.line) - startWorker(cm, 400) - - var lendiff = change.text.length - (to.line - from.line) - 1 - // Remember that these lines changed, for updating the display - if (change.full) - { regChange(cm) } - else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change)) - { regLineChange(cm, from.line, "text") } - else - { regChange(cm, from.line, to.line + 1, lendiff) } - - var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change") - if (changeHandler || changesHandler) { - var obj = { - from: from, to: to, - text: change.text, - removed: change.removed, - origin: change.origin - } - if (changeHandler) { signalLater(cm, "change", cm, obj) } - if (changesHandler) { (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj) } - } - cm.display.selForContextMenu = null -} - -function replaceRange(doc, code, from, to, origin) { - if (!to) { to = from } - if (cmp(to, from) < 0) { var tmp = to; to = from; from = tmp } - if (typeof code == "string") { code = doc.splitLines(code) } - makeChange(doc, {from: from, to: to, text: code, origin: origin}) -} - -// Rebasing/resetting history to deal with externally-sourced changes - -function rebaseHistSelSingle(pos, from, to, diff) { - if (to < pos.line) { - pos.line += diff - } else if (from < pos.line) { - pos.line = from - pos.ch = 0 - } -} - -// Tries to rebase an array of history events given a change in the -// document. If the change touches the same lines as the event, the -// event, and everything 'behind' it, is discarded. If the change is -// before the event, the event's positions are updated. Uses a -// copy-on-write scheme for the positions, to avoid having to -// reallocate them all on every rebase, but also avoid problems with -// shared position objects being unsafely updated. -function rebaseHistArray(array, from, to, diff) { - for (var i = 0; i < array.length; ++i) { - var sub = array[i], ok = true - if (sub.ranges) { - if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true } - for (var j = 0; j < sub.ranges.length; j++) { - rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff) - rebaseHistSelSingle(sub.ranges[j].head, from, to, diff) - } - continue - } - for (var j$1 = 0; j$1 < sub.changes.length; ++j$1) { - var cur = sub.changes[j$1] - if (to < cur.from.line) { - cur.from = Pos(cur.from.line + diff, cur.from.ch) - cur.to = Pos(cur.to.line + diff, cur.to.ch) - } else if (from <= cur.to.line) { - ok = false - break - } - } - if (!ok) { - array.splice(0, i + 1) - i = 0 - } - } -} - -function rebaseHist(hist, change) { - var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1 - rebaseHistArray(hist.done, from, to, diff) - rebaseHistArray(hist.undone, from, to, diff) -} - -// Utility for applying a change to a line by handle or number, -// returning the number and optionally registering the line as -// changed. -function changeLine(doc, handle, changeType, op) { - var no = handle, line = handle - if (typeof handle == "number") { line = getLine(doc, clipLine(doc, handle)) } - else { no = lineNo(handle) } - if (no == null) { return null } - if (op(line, no) && doc.cm) { regLineChange(doc.cm, no, changeType) } - return line -} - -// The document is represented as a BTree consisting of leaves, with -// chunk of lines in them, and branches, with up to ten leaves or -// other branch nodes below them. The top node is always a branch -// node, and is the document object itself (meaning it has -// additional methods and properties). -// -// All nodes have parent links. The tree is used both to go from -// line numbers to line objects, and to go from objects to numbers. -// It also indexes by height, and is used to convert between height -// and line object, and to find the total height of the document. -// -// See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html - -function LeafChunk(lines) { - var this$1 = this; - - this.lines = lines - this.parent = null - var height = 0 - for (var i = 0; i < lines.length; ++i) { - lines[i].parent = this$1 - height += lines[i].height - } - this.height = height -} - -LeafChunk.prototype = { - chunkSize: function() { return this.lines.length }, - // Remove the n lines at offset 'at'. - removeInner: function(at, n) { - var this$1 = this; - - for (var i = at, e = at + n; i < e; ++i) { - var line = this$1.lines[i] - this$1.height -= line.height - cleanUpLine(line) - signalLater(line, "delete") - } - this.lines.splice(at, n) - }, - // Helper used to collapse a small branch into a single leaf. - collapse: function(lines) { - lines.push.apply(lines, this.lines) - }, - // Insert the given array of lines at offset 'at', count them as - // having the given height. - insertInner: function(at, lines, height) { - var this$1 = this; - - this.height += height - this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)) - for (var i = 0; i < lines.length; ++i) { lines[i].parent = this$1 } - }, - // Used to iterate over a part of the tree. - iterN: function(at, n, op) { - var this$1 = this; - - for (var e = at + n; at < e; ++at) - { if (op(this$1.lines[at])) { return true } } - } -} - -function BranchChunk(children) { - var this$1 = this; - - this.children = children - var size = 0, height = 0 - for (var i = 0; i < children.length; ++i) { - var ch = children[i] - size += ch.chunkSize(); height += ch.height - ch.parent = this$1 - } - this.size = size - this.height = height - this.parent = null -} - -BranchChunk.prototype = { - chunkSize: function() { return this.size }, - removeInner: function(at, n) { - var this$1 = this; - - this.size -= n - for (var i = 0; i < this.children.length; ++i) { - var child = this$1.children[i], sz = child.chunkSize() - if (at < sz) { - var rm = Math.min(n, sz - at), oldHeight = child.height - child.removeInner(at, rm) - this$1.height -= oldHeight - child.height - if (sz == rm) { this$1.children.splice(i--, 1); child.parent = null } - if ((n -= rm) == 0) { break } - at = 0 - } else { at -= sz } - } - // If the result is smaller than 25 lines, ensure that it is a - // single leaf node. - if (this.size - n < 25 && - (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) { - var lines = [] - this.collapse(lines) - this.children = [new LeafChunk(lines)] - this.children[0].parent = this - } - }, - collapse: function(lines) { - var this$1 = this; - - for (var i = 0; i < this.children.length; ++i) { this$1.children[i].collapse(lines) } - }, - insertInner: function(at, lines, height) { - var this$1 = this; - - this.size += lines.length - this.height += height - for (var i = 0; i < this.children.length; ++i) { - var child = this$1.children[i], sz = child.chunkSize() - if (at <= sz) { - child.insertInner(at, lines, height) - if (child.lines && child.lines.length > 50) { - // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced. - // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest. - var remaining = child.lines.length % 25 + 25 - for (var pos = remaining; pos < child.lines.length;) { - var leaf = new LeafChunk(child.lines.slice(pos, pos += 25)) - child.height -= leaf.height - this$1.children.splice(++i, 0, leaf) - leaf.parent = this$1 - } - child.lines = child.lines.slice(0, remaining) - this$1.maybeSpill() - } - break - } - at -= sz - } - }, - // When a node has grown, check whether it should be split. - maybeSpill: function() { - if (this.children.length <= 10) { return } - var me = this - do { - var spilled = me.children.splice(me.children.length - 5, 5) - var sibling = new BranchChunk(spilled) - if (!me.parent) { // Become the parent node - var copy = new BranchChunk(me.children) - copy.parent = me - me.children = [copy, sibling] - me = copy - } else { - me.size -= sibling.size - me.height -= sibling.height - var myIndex = indexOf(me.parent.children, me) - me.parent.children.splice(myIndex + 1, 0, sibling) - } - sibling.parent = me.parent - } while (me.children.length > 10) - me.parent.maybeSpill() - }, - iterN: function(at, n, op) { - var this$1 = this; - - for (var i = 0; i < this.children.length; ++i) { - var child = this$1.children[i], sz = child.chunkSize() - if (at < sz) { - var used = Math.min(n, sz - at) - if (child.iterN(at, used, op)) { return true } - if ((n -= used) == 0) { break } - at = 0 - } else { at -= sz } - } - } -} - -// Line widgets are block elements displayed above or below a line. - -function LineWidget(doc, node, options) { - var this$1 = this; - - if (options) { for (var opt in options) { if (options.hasOwnProperty(opt)) - { this$1[opt] = options[opt] } } } - this.doc = doc - this.node = node -} -eventMixin(LineWidget) - -function adjustScrollWhenAboveVisible(cm, line, diff) { - if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop)) - { addToScrollPos(cm, null, diff) } -} - -LineWidget.prototype.clear = function() { - var this$1 = this; - - var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line) - if (no == null || !ws) { return } - for (var i = 0; i < ws.length; ++i) { if (ws[i] == this$1) { ws.splice(i--, 1) } } - if (!ws.length) { line.widgets = null } - var height = widgetHeight(this) - updateLineHeight(line, Math.max(0, line.height - height)) - if (cm) { runInOp(cm, function () { - adjustScrollWhenAboveVisible(cm, line, -height) - regLineChange(cm, no, "widget") - }) } -} -LineWidget.prototype.changed = function() { - var oldH = this.height, cm = this.doc.cm, line = this.line - this.height = null - var diff = widgetHeight(this) - oldH - if (!diff) { return } - updateLineHeight(line, line.height + diff) - if (cm) { runInOp(cm, function () { - cm.curOp.forceUpdate = true - adjustScrollWhenAboveVisible(cm, line, diff) - }) } -} - -function addLineWidget(doc, handle, node, options) { - var widget = new LineWidget(doc, node, options) - var cm = doc.cm - if (cm && widget.noHScroll) { cm.display.alignWidgets = true } - changeLine(doc, handle, "widget", function (line) { - var widgets = line.widgets || (line.widgets = []) - if (widget.insertAt == null) { widgets.push(widget) } - else { widgets.splice(Math.min(widgets.length - 1, Math.max(0, widget.insertAt)), 0, widget) } - widget.line = line - if (cm && !lineIsHidden(doc, line)) { - var aboveVisible = heightAtLine(line) < doc.scrollTop - updateLineHeight(line, line.height + widgetHeight(widget)) - if (aboveVisible) { addToScrollPos(cm, null, widget.height) } - cm.curOp.forceUpdate = true - } - return true - }) - return widget -} - -// TEXTMARKERS - -// Created with markText and setBookmark methods. A TextMarker is a -// handle that can be used to clear or find a marked position in the -// document. Line objects hold arrays (markedSpans) containing -// {from, to, marker} object pointing to such marker objects, and -// indicating that such a marker is present on that line. Multiple -// lines may point to the same marker when it spans across lines. -// The spans will have null for their from/to properties when the -// marker continues beyond the start/end of the line. Markers have -// links back to the lines they currently touch. - -// Collapsed markers have unique ids, in order to be able to order -// them, which is needed for uniquely determining an outer marker -// when they overlap (they may nest, but not partially overlap). -var nextMarkerId = 0 - -function TextMarker(doc, type) { - this.lines = [] - this.type = type - this.doc = doc - this.id = ++nextMarkerId -} -eventMixin(TextMarker) - -// Clear the marker. -TextMarker.prototype.clear = function() { - var this$1 = this; - - if (this.explicitlyCleared) { return } - var cm = this.doc.cm, withOp = cm && !cm.curOp - if (withOp) { startOperation(cm) } - if (hasHandler(this, "clear")) { - var found = this.find() - if (found) { signalLater(this, "clear", found.from, found.to) } - } - var min = null, max = null - for (var i = 0; i < this.lines.length; ++i) { - var line = this$1.lines[i] - var span = getMarkedSpanFor(line.markedSpans, this$1) - if (cm && !this$1.collapsed) { regLineChange(cm, lineNo(line), "text") } - else if (cm) { - if (span.to != null) { max = lineNo(line) } - if (span.from != null) { min = lineNo(line) } - } - line.markedSpans = removeMarkedSpan(line.markedSpans, span) - if (span.from == null && this$1.collapsed && !lineIsHidden(this$1.doc, line) && cm) - { updateLineHeight(line, textHeight(cm.display)) } - } - if (cm && this.collapsed && !cm.options.lineWrapping) { for (var i$1 = 0; i$1 < this.lines.length; ++i$1) { - var visual = visualLine(this$1.lines[i$1]), len = lineLength(visual) - if (len > cm.display.maxLineLength) { - cm.display.maxLine = visual - cm.display.maxLineLength = len - cm.display.maxLineChanged = true - } - } } - - if (min != null && cm && this.collapsed) { regChange(cm, min, max + 1) } - this.lines.length = 0 - this.explicitlyCleared = true - if (this.atomic && this.doc.cantEdit) { - this.doc.cantEdit = false - if (cm) { reCheckSelection(cm.doc) } - } - if (cm) { signalLater(cm, "markerCleared", cm, this) } - if (withOp) { endOperation(cm) } - if (this.parent) { this.parent.clear() } -} - -// Find the position of the marker in the document. Returns a {from, -// to} object by default. Side can be passed to get a specific side -// -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the -// Pos objects returned contain a line object, rather than a line -// number (used to prevent looking up the same line twice). -TextMarker.prototype.find = function(side, lineObj) { - var this$1 = this; - - if (side == null && this.type == "bookmark") { side = 1 } - var from, to - for (var i = 0; i < this.lines.length; ++i) { - var line = this$1.lines[i] - var span = getMarkedSpanFor(line.markedSpans, this$1) - if (span.from != null) { - from = Pos(lineObj ? line : lineNo(line), span.from) - if (side == -1) { return from } - } - if (span.to != null) { - to = Pos(lineObj ? line : lineNo(line), span.to) - if (side == 1) { return to } - } - } - return from && {from: from, to: to} -} - -// Signals that the marker's widget changed, and surrounding layout -// should be recomputed. -TextMarker.prototype.changed = function() { - var pos = this.find(-1, true), widget = this, cm = this.doc.cm - if (!pos || !cm) { return } - runInOp(cm, function () { - var line = pos.line, lineN = lineNo(pos.line) - var view = findViewForLine(cm, lineN) - if (view) { - clearLineMeasurementCacheFor(view) - cm.curOp.selectionChanged = cm.curOp.forceUpdate = true - } - cm.curOp.updateMaxLine = true - if (!lineIsHidden(widget.doc, line) && widget.height != null) { - var oldHeight = widget.height - widget.height = null - var dHeight = widgetHeight(widget) - oldHeight - if (dHeight) - { updateLineHeight(line, line.height + dHeight) } - } - }) -} - -TextMarker.prototype.attachLine = function(line) { - if (!this.lines.length && this.doc.cm) { - var op = this.doc.cm.curOp - if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1) - { (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this) } - } - this.lines.push(line) -} -TextMarker.prototype.detachLine = function(line) { - this.lines.splice(indexOf(this.lines, line), 1) - if (!this.lines.length && this.doc.cm) { - var op = this.doc.cm.curOp - ;(op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this) - } -} - -// Create a marker, wire it up to the right lines, and -function markText(doc, from, to, options, type) { - // Shared markers (across linked documents) are handled separately - // (markTextShared will call out to this again, once per - // document). - if (options && options.shared) { return markTextShared(doc, from, to, options, type) } - // Ensure we are in an operation. - if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, markText)(doc, from, to, options, type) } - - var marker = new TextMarker(doc, type), diff = cmp(from, to) - if (options) { copyObj(options, marker, false) } - // Don't connect empty markers unless clearWhenEmpty is false - if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false) - { return marker } - if (marker.replacedWith) { - // Showing up as a widget implies collapsed (widget replaces text) - marker.collapsed = true - marker.widgetNode = elt("span", [marker.replacedWith], "CodeMirror-widget") - marker.widgetNode.setAttribute("role", "presentation") // hide from accessibility tree - if (!options.handleMouseEvents) { marker.widgetNode.setAttribute("cm-ignore-events", "true") } - if (options.insertLeft) { marker.widgetNode.insertLeft = true } - } - if (marker.collapsed) { - if (conflictingCollapsedRange(doc, from.line, from, to, marker) || - from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker)) - { throw new Error("Inserting collapsed marker partially overlapping an existing one") } - seeCollapsedSpans() - } - - if (marker.addToHistory) - { addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN) } - - var curLine = from.line, cm = doc.cm, updateMaxLine - doc.iter(curLine, to.line + 1, function (line) { - if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine) - { updateMaxLine = true } - if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0) } - addMarkedSpan(line, new MarkedSpan(marker, - curLine == from.line ? from.ch : null, - curLine == to.line ? to.ch : null)) - ++curLine - }) - // lineIsHidden depends on the presence of the spans, so needs a second pass - if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) { - if (lineIsHidden(doc, line)) { updateLineHeight(line, 0) } - }) } - - if (marker.clearOnEnter) { on(marker, "beforeCursorEnter", function () { return marker.clear(); }) } - - if (marker.readOnly) { - seeReadOnlySpans() - if (doc.history.done.length || doc.history.undone.length) - { doc.clearHistory() } - } - if (marker.collapsed) { - marker.id = ++nextMarkerId - marker.atomic = true - } - if (cm) { - // Sync editor state - if (updateMaxLine) { cm.curOp.updateMaxLine = true } - if (marker.collapsed) - { regChange(cm, from.line, to.line + 1) } - else if (marker.className || marker.title || marker.startStyle || marker.endStyle || marker.css) - { for (var i = from.line; i <= to.line; i++) { regLineChange(cm, i, "text") } } - if (marker.atomic) { reCheckSelection(cm.doc) } - signalLater(cm, "markerAdded", cm, marker) - } - return marker -} - -// SHARED TEXTMARKERS - -// A shared marker spans multiple linked documents. It is -// implemented as a meta-marker-object controlling multiple normal -// markers. -function SharedTextMarker(markers, primary) { - var this$1 = this; - - this.markers = markers - this.primary = primary - for (var i = 0; i < markers.length; ++i) - { markers[i].parent = this$1 } -} -eventMixin(SharedTextMarker) - -SharedTextMarker.prototype.clear = function() { - var this$1 = this; - - if (this.explicitlyCleared) { return } - this.explicitlyCleared = true - for (var i = 0; i < this.markers.length; ++i) - { this$1.markers[i].clear() } - signalLater(this, "clear") -} -SharedTextMarker.prototype.find = function(side, lineObj) { - return this.primary.find(side, lineObj) -} - -function markTextShared(doc, from, to, options, type) { - options = copyObj(options) - options.shared = false - var markers = [markText(doc, from, to, options, type)], primary = markers[0] - var widget = options.widgetNode - linkedDocs(doc, function (doc) { - if (widget) { options.widgetNode = widget.cloneNode(true) } - markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type)) - for (var i = 0; i < doc.linked.length; ++i) - { if (doc.linked[i].isParent) { return } } - primary = lst(markers) - }) - return new SharedTextMarker(markers, primary) -} - -function findSharedMarkers(doc) { - return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), function (m) { return m.parent; }) -} - -function copySharedMarkers(doc, markers) { - for (var i = 0; i < markers.length; i++) { - var marker = markers[i], pos = marker.find() - var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to) - if (cmp(mFrom, mTo)) { - var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type) - marker.markers.push(subMark) - subMark.parent = marker - } - } -} - -function detachSharedMarkers(markers) { - var loop = function ( i ) { - var marker = markers[i], linked = [marker.primary.doc] - linkedDocs(marker.primary.doc, function (d) { return linked.push(d); }) - for (var j = 0; j < marker.markers.length; j++) { - var subMarker = marker.markers[j] - if (indexOf(linked, subMarker.doc) == -1) { - subMarker.parent = null - marker.markers.splice(j--, 1) - } - } - }; - - for (var i = 0; i < markers.length; i++) loop( i ); -} - -var nextDocId = 0 -var Doc = function(text, mode, firstLine, lineSep) { - if (!(this instanceof Doc)) { return new Doc(text, mode, firstLine, lineSep) } - if (firstLine == null) { firstLine = 0 } - - BranchChunk.call(this, [new LeafChunk([new Line("", null)])]) - this.first = firstLine - this.scrollTop = this.scrollLeft = 0 - this.cantEdit = false - this.cleanGeneration = 1 - this.frontier = firstLine - var start = Pos(firstLine, 0) - this.sel = simpleSelection(start) - this.history = new History(null) - this.id = ++nextDocId - this.modeOption = mode - this.lineSep = lineSep - this.extend = false - - if (typeof text == "string") { text = this.splitLines(text) } - updateDoc(this, {from: start, to: start, text: text}) - setSelection(this, simpleSelection(start), sel_dontScroll) -} - -Doc.prototype = createObj(BranchChunk.prototype, { - constructor: Doc, - // Iterate over the document. Supports two forms -- with only one - // argument, it calls that for each line in the document. With - // three, it iterates over the range given by the first two (with - // the second being non-inclusive). - iter: function(from, to, op) { - if (op) { this.iterN(from - this.first, to - from, op) } - else { this.iterN(this.first, this.first + this.size, from) } - }, - - // Non-public interface for adding and removing lines. - insert: function(at, lines) { - var height = 0 - for (var i = 0; i < lines.length; ++i) { height += lines[i].height } - this.insertInner(at - this.first, lines, height) - }, - remove: function(at, n) { this.removeInner(at - this.first, n) }, - - // From here, the methods are part of the public interface. Most - // are also available from CodeMirror (editor) instances. - - getValue: function(lineSep) { - var lines = getLines(this, this.first, this.first + this.size) - if (lineSep === false) { return lines } - return lines.join(lineSep || this.lineSeparator()) - }, - setValue: docMethodOp(function(code) { - var top = Pos(this.first, 0), last = this.first + this.size - 1 - makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length), - text: this.splitLines(code), origin: "setValue", full: true}, true) - setSelection(this, simpleSelection(top)) - }), - replaceRange: function(code, from, to, origin) { - from = clipPos(this, from) - to = to ? clipPos(this, to) : from - replaceRange(this, code, from, to, origin) - }, - getRange: function(from, to, lineSep) { - var lines = getBetween(this, clipPos(this, from), clipPos(this, to)) - if (lineSep === false) { return lines } - return lines.join(lineSep || this.lineSeparator()) - }, - - getLine: function(line) {var l = this.getLineHandle(line); return l && l.text}, - - getLineHandle: function(line) {if (isLine(this, line)) { return getLine(this, line) }}, - getLineNumber: function(line) {return lineNo(line)}, - - getLineHandleVisualStart: function(line) { - if (typeof line == "number") { line = getLine(this, line) } - return visualLine(line) - }, - - lineCount: function() {return this.size}, - firstLine: function() {return this.first}, - lastLine: function() {return this.first + this.size - 1}, - - clipPos: function(pos) {return clipPos(this, pos)}, - - getCursor: function(start) { - var range = this.sel.primary(), pos - if (start == null || start == "head") { pos = range.head } - else if (start == "anchor") { pos = range.anchor } - else if (start == "end" || start == "to" || start === false) { pos = range.to() } - else { pos = range.from() } - return pos - }, - listSelections: function() { return this.sel.ranges }, - somethingSelected: function() {return this.sel.somethingSelected()}, - - setCursor: docMethodOp(function(line, ch, options) { - setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options) - }), - setSelection: docMethodOp(function(anchor, head, options) { - setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options) - }), - extendSelection: docMethodOp(function(head, other, options) { - extendSelection(this, clipPos(this, head), other && clipPos(this, other), options) - }), - extendSelections: docMethodOp(function(heads, options) { - extendSelections(this, clipPosArray(this, heads), options) - }), - extendSelectionsBy: docMethodOp(function(f, options) { - var heads = map(this.sel.ranges, f) - extendSelections(this, clipPosArray(this, heads), options) - }), - setSelections: docMethodOp(function(ranges, primary, options) { - var this$1 = this; - - if (!ranges.length) { return } - var out = [] - for (var i = 0; i < ranges.length; i++) - { out[i] = new Range(clipPos(this$1, ranges[i].anchor), - clipPos(this$1, ranges[i].head)) } - if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex) } - setSelection(this, normalizeSelection(out, primary), options) - }), - addSelection: docMethodOp(function(anchor, head, options) { - var ranges = this.sel.ranges.slice(0) - ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor))) - setSelection(this, normalizeSelection(ranges, ranges.length - 1), options) - }), - - getSelection: function(lineSep) { - var this$1 = this; - - var ranges = this.sel.ranges, lines - for (var i = 0; i < ranges.length; i++) { - var sel = getBetween(this$1, ranges[i].from(), ranges[i].to()) - lines = lines ? lines.concat(sel) : sel - } - if (lineSep === false) { return lines } - else { return lines.join(lineSep || this.lineSeparator()) } - }, - getSelections: function(lineSep) { - var this$1 = this; - - var parts = [], ranges = this.sel.ranges - for (var i = 0; i < ranges.length; i++) { - var sel = getBetween(this$1, ranges[i].from(), ranges[i].to()) - if (lineSep !== false) { sel = sel.join(lineSep || this$1.lineSeparator()) } - parts[i] = sel - } - return parts - }, - replaceSelection: function(code, collapse, origin) { - var dup = [] - for (var i = 0; i < this.sel.ranges.length; i++) - { dup[i] = code } - this.replaceSelections(dup, collapse, origin || "+input") - }, - replaceSelections: docMethodOp(function(code, collapse, origin) { - var this$1 = this; - - var changes = [], sel = this.sel - for (var i = 0; i < sel.ranges.length; i++) { - var range = sel.ranges[i] - changes[i] = {from: range.from(), to: range.to(), text: this$1.splitLines(code[i]), origin: origin} - } - var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse) - for (var i$1 = changes.length - 1; i$1 >= 0; i$1--) - { makeChange(this$1, changes[i$1]) } - if (newSel) { setSelectionReplaceHistory(this, newSel) } - else if (this.cm) { ensureCursorVisible(this.cm) } - }), - undo: docMethodOp(function() {makeChangeFromHistory(this, "undo")}), - redo: docMethodOp(function() {makeChangeFromHistory(this, "redo")}), - undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true)}), - redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true)}), - - setExtending: function(val) {this.extend = val}, - getExtending: function() {return this.extend}, - - historySize: function() { - var hist = this.history, done = 0, undone = 0 - for (var i = 0; i < hist.done.length; i++) { if (!hist.done[i].ranges) { ++done } } - for (var i$1 = 0; i$1 < hist.undone.length; i$1++) { if (!hist.undone[i$1].ranges) { ++undone } } - return {undo: done, redo: undone} - }, - clearHistory: function() {this.history = new History(this.history.maxGeneration)}, - - markClean: function() { - this.cleanGeneration = this.changeGeneration(true) - }, - changeGeneration: function(forceSplit) { - if (forceSplit) - { this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null } - return this.history.generation - }, - isClean: function (gen) { - return this.history.generation == (gen || this.cleanGeneration) - }, - - getHistory: function() { - return {done: copyHistoryArray(this.history.done), - undone: copyHistoryArray(this.history.undone)} - }, - setHistory: function(histData) { - var hist = this.history = new History(this.history.maxGeneration) - hist.done = copyHistoryArray(histData.done.slice(0), null, true) - hist.undone = copyHistoryArray(histData.undone.slice(0), null, true) - }, - - setGutterMarker: docMethodOp(function(line, gutterID, value) { - return changeLine(this, line, "gutter", function (line) { - var markers = line.gutterMarkers || (line.gutterMarkers = {}) - markers[gutterID] = value - if (!value && isEmpty(markers)) { line.gutterMarkers = null } - return true - }) - }), - - clearGutter: docMethodOp(function(gutterID) { - var this$1 = this; - - this.iter(function (line) { - if (line.gutterMarkers && line.gutterMarkers[gutterID]) { - changeLine(this$1, line, "gutter", function () { - line.gutterMarkers[gutterID] = null - if (isEmpty(line.gutterMarkers)) { line.gutterMarkers = null } - return true - }) - } - }) - }), - - lineInfo: function(line) { - var n - if (typeof line == "number") { - if (!isLine(this, line)) { return null } - n = line - line = getLine(this, line) - if (!line) { return null } - } else { - n = lineNo(line) - if (n == null) { return null } - } - return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers, - textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass, - widgets: line.widgets} - }, - - addLineClass: docMethodOp(function(handle, where, cls) { - return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { - var prop = where == "text" ? "textClass" - : where == "background" ? "bgClass" - : where == "gutter" ? "gutterClass" : "wrapClass" - if (!line[prop]) { line[prop] = cls } - else if (classTest(cls).test(line[prop])) { return false } - else { line[prop] += " " + cls } - return true - }) - }), - removeLineClass: docMethodOp(function(handle, where, cls) { - return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { - var prop = where == "text" ? "textClass" - : where == "background" ? "bgClass" - : where == "gutter" ? "gutterClass" : "wrapClass" - var cur = line[prop] - if (!cur) { return false } - else if (cls == null) { line[prop] = null } - else { - var found = cur.match(classTest(cls)) - if (!found) { return false } - var end = found.index + found[0].length - line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null - } - return true - }) - }), - - addLineWidget: docMethodOp(function(handle, node, options) { - return addLineWidget(this, handle, node, options) - }), - removeLineWidget: function(widget) { widget.clear() }, - - markText: function(from, to, options) { - return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range") - }, - setBookmark: function(pos, options) { - var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options), - insertLeft: options && options.insertLeft, - clearWhenEmpty: false, shared: options && options.shared, - handleMouseEvents: options && options.handleMouseEvents} - pos = clipPos(this, pos) - return markText(this, pos, pos, realOpts, "bookmark") - }, - findMarksAt: function(pos) { - pos = clipPos(this, pos) - var markers = [], spans = getLine(this, pos.line).markedSpans - if (spans) { for (var i = 0; i < spans.length; ++i) { - var span = spans[i] - if ((span.from == null || span.from <= pos.ch) && - (span.to == null || span.to >= pos.ch)) - { markers.push(span.marker.parent || span.marker) } - } } - return markers - }, - findMarks: function(from, to, filter) { - from = clipPos(this, from); to = clipPos(this, to) - var found = [], lineNo = from.line - this.iter(from.line, to.line + 1, function (line) { - var spans = line.markedSpans - if (spans) { for (var i = 0; i < spans.length; i++) { - var span = spans[i] - if (!(span.to != null && lineNo == from.line && from.ch >= span.to || - span.from == null && lineNo != from.line || - span.from != null && lineNo == to.line && span.from >= to.ch) && - (!filter || filter(span.marker))) - { found.push(span.marker.parent || span.marker) } - } } - ++lineNo - }) - return found - }, - getAllMarks: function() { - var markers = [] - this.iter(function (line) { - var sps = line.markedSpans - if (sps) { for (var i = 0; i < sps.length; ++i) - { if (sps[i].from != null) { markers.push(sps[i].marker) } } } - }) - return markers - }, - - posFromIndex: function(off) { - var ch, lineNo = this.first, sepSize = this.lineSeparator().length - this.iter(function (line) { - var sz = line.text.length + sepSize - if (sz > off) { ch = off; return true } - off -= sz - ++lineNo - }) - return clipPos(this, Pos(lineNo, ch)) - }, - indexFromPos: function (coords) { - coords = clipPos(this, coords) - var index = coords.ch - if (coords.line < this.first || coords.ch < 0) { return 0 } - var sepSize = this.lineSeparator().length - this.iter(this.first, coords.line, function (line) { // iter aborts when callback returns a truthy value - index += line.text.length + sepSize - }) - return index - }, - - copy: function(copyHistory) { - var doc = new Doc(getLines(this, this.first, this.first + this.size), - this.modeOption, this.first, this.lineSep) - doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft - doc.sel = this.sel - doc.extend = false - if (copyHistory) { - doc.history.undoDepth = this.history.undoDepth - doc.setHistory(this.getHistory()) - } - return doc - }, - - linkedDoc: function(options) { - if (!options) { options = {} } - var from = this.first, to = this.first + this.size - if (options.from != null && options.from > from) { from = options.from } - if (options.to != null && options.to < to) { to = options.to } - var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep) - if (options.sharedHist) { copy.history = this.history - ; }(this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist}) - copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}] - copySharedMarkers(copy, findSharedMarkers(this)) - return copy - }, - unlinkDoc: function(other) { - var this$1 = this; - - if (other instanceof CodeMirror) { other = other.doc } - if (this.linked) { for (var i = 0; i < this.linked.length; ++i) { - var link = this$1.linked[i] - if (link.doc != other) { continue } - this$1.linked.splice(i, 1) - other.unlinkDoc(this$1) - detachSharedMarkers(findSharedMarkers(this$1)) - break - } } - // If the histories were shared, split them again - if (other.history == this.history) { - var splitIds = [other.id] - linkedDocs(other, function (doc) { return splitIds.push(doc.id); }, true) - other.history = new History(null) - other.history.done = copyHistoryArray(this.history.done, splitIds) - other.history.undone = copyHistoryArray(this.history.undone, splitIds) - } - }, - iterLinkedDocs: function(f) {linkedDocs(this, f)}, - - getMode: function() {return this.mode}, - getEditor: function() {return this.cm}, - - splitLines: function(str) { - if (this.lineSep) { return str.split(this.lineSep) } - return splitLinesAuto(str) - }, - lineSeparator: function() { return this.lineSep || "\n" } -}) - -// Public alias. -Doc.prototype.eachLine = Doc.prototype.iter - -// Kludge to work around strange IE behavior where it'll sometimes -// re-fire a series of drag-related events right after the drop (#1551) -var lastDrop = 0 - -function onDrop(e) { - var cm = this - clearDragCursor(cm) - if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) - { return } - e_preventDefault(e) - if (ie) { lastDrop = +new Date } - var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files - if (!pos || cm.isReadOnly()) { return } - // Might be a file drop, in which case we simply extract the text - // and insert it. - if (files && files.length && window.FileReader && window.File) { - var n = files.length, text = Array(n), read = 0 - var loadFile = function (file, i) { - if (cm.options.allowDropFileTypes && - indexOf(cm.options.allowDropFileTypes, file.type) == -1) - { return } - - var reader = new FileReader - reader.onload = operation(cm, function () { - var content = reader.result - if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) { content = "" } - text[i] = content - if (++read == n) { - pos = clipPos(cm.doc, pos) - var change = {from: pos, to: pos, - text: cm.doc.splitLines(text.join(cm.doc.lineSeparator())), - origin: "paste"} - makeChange(cm.doc, change) - setSelectionReplaceHistory(cm.doc, simpleSelection(pos, changeEnd(change))) - } - }) - reader.readAsText(file) - } - for (var i = 0; i < n; ++i) { loadFile(files[i], i) } - } else { // Normal drop - // Don't do a replace if the drop happened inside of the selected text. - if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) { - cm.state.draggingText(e) - // Ensure the editor is re-focused - setTimeout(function () { return cm.display.input.focus(); }, 20) - return - } - try { - var text$1 = e.dataTransfer.getData("Text") - if (text$1) { - var selected - if (cm.state.draggingText && !cm.state.draggingText.copy) - { selected = cm.listSelections() } - setSelectionNoUndo(cm.doc, simpleSelection(pos, pos)) - if (selected) { for (var i$1 = 0; i$1 < selected.length; ++i$1) - { replaceRange(cm.doc, "", selected[i$1].anchor, selected[i$1].head, "drag") } } - cm.replaceSelection(text$1, "around", "paste") - cm.display.input.focus() - } - } - catch(e){} - } -} - -function onDragStart(cm, e) { - if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return } - if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { return } - - e.dataTransfer.setData("Text", cm.getSelection()) - e.dataTransfer.effectAllowed = "copyMove" - - // Use dummy image instead of default browsers image. - // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. - if (e.dataTransfer.setDragImage && !safari) { - var img = elt("img", null, null, "position: fixed; left: 0; top: 0;") - img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" - if (presto) { - img.width = img.height = 1 - cm.display.wrapper.appendChild(img) - // Force a relayout, or Opera won't use our image for some obscure reason - img._top = img.offsetTop - } - e.dataTransfer.setDragImage(img, 0, 0) - if (presto) { img.parentNode.removeChild(img) } - } -} - -function onDragOver(cm, e) { - var pos = posFromMouse(cm, e) - if (!pos) { return } - var frag = document.createDocumentFragment() - drawSelectionCursor(cm, pos, frag) - if (!cm.display.dragCursor) { - cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors") - cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv) - } - removeChildrenAndAdd(cm.display.dragCursor, frag) -} - -function clearDragCursor(cm) { - if (cm.display.dragCursor) { - cm.display.lineSpace.removeChild(cm.display.dragCursor) - cm.display.dragCursor = null - } -} - -// These must be handled carefully, because naively registering a -// handler for each editor will cause the editors to never be -// garbage collected. - -function forEachCodeMirror(f) { - if (!document.body.getElementsByClassName) { return } - var byClass = document.body.getElementsByClassName("CodeMirror") - for (var i = 0; i < byClass.length; i++) { - var cm = byClass[i].CodeMirror - if (cm) { f(cm) } - } -} - -var globalsRegistered = false -function ensureGlobalHandlers() { - if (globalsRegistered) { return } - registerGlobalHandlers() - globalsRegistered = true -} -function registerGlobalHandlers() { - // When the window resizes, we need to refresh active editors. - var resizeTimer - on(window, "resize", function () { - if (resizeTimer == null) { resizeTimer = setTimeout(function () { - resizeTimer = null - forEachCodeMirror(onResize) - }, 100) } - }) - // When the window loses focus, we want to show the editor as blurred - on(window, "blur", function () { return forEachCodeMirror(onBlur); }) -} -// Called when the window resizes -function onResize(cm) { - var d = cm.display - if (d.lastWrapHeight == d.wrapper.clientHeight && d.lastWrapWidth == d.wrapper.clientWidth) - { return } - // Might be a text scaling operation, clear size caches. - d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null - d.scrollbarsClipped = false - cm.setSize() -} - -var keyNames = { - 3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", - 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", - 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", - 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", - 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 127: "Delete", - 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", - 221: "]", 222: "'", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete", - 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert" -} - -// Number keys -for (var i = 0; i < 10; i++) { keyNames[i + 48] = keyNames[i + 96] = String(i) } -// Alphabetic keys -for (var i$1 = 65; i$1 <= 90; i$1++) { keyNames[i$1] = String.fromCharCode(i$1) } -// Function keys -for (var i$2 = 1; i$2 <= 12; i$2++) { keyNames[i$2 + 111] = keyNames[i$2 + 63235] = "F" + i$2 } - -var keyMap = {} - -keyMap.basic = { - "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", - "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", - "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore", - "Tab": "defaultTab", "Shift-Tab": "indentAuto", - "Enter": "newlineAndIndent", "Insert": "toggleOverwrite", - "Esc": "singleSelection" -} -// Note that the save and find-related commands aren't defined by -// default. User code or addons can define them. Unknown commands -// are simply ignored. -keyMap.pcDefault = { - "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", - "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown", - "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", - "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find", - "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", - "Ctrl-[": "indentLess", "Ctrl-]": "indentMore", - "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection", - fallthrough: "basic" -} -// Very basic readline/emacs-style bindings, which are standard on Mac. -keyMap.emacsy = { - "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", - "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", - "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", - "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars", - "Ctrl-O": "openLine" -} -keyMap.macDefault = { - "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", - "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft", - "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore", - "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find", - "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", - "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight", - "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd", - fallthrough: ["basic", "emacsy"] -} -keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault - -// KEYMAP DISPATCH - -function normalizeKeyName(name) { - var parts = name.split(/-(?!$)/) - name = parts[parts.length - 1] - var alt, ctrl, shift, cmd - for (var i = 0; i < parts.length - 1; i++) { - var mod = parts[i] - if (/^(cmd|meta|m)$/i.test(mod)) { cmd = true } - else if (/^a(lt)?$/i.test(mod)) { alt = true } - else if (/^(c|ctrl|control)$/i.test(mod)) { ctrl = true } - else if (/^s(hift)?$/i.test(mod)) { shift = true } - else { throw new Error("Unrecognized modifier name: " + mod) } - } - if (alt) { name = "Alt-" + name } - if (ctrl) { name = "Ctrl-" + name } - if (cmd) { name = "Cmd-" + name } - if (shift) { name = "Shift-" + name } - return name -} - -// This is a kludge to keep keymaps mostly working as raw objects -// (backwards compatibility) while at the same time support features -// like normalization and multi-stroke key bindings. It compiles a -// new normalized keymap, and then updates the old object to reflect -// this. -function normalizeKeyMap(keymap) { - var copy = {} - for (var keyname in keymap) { if (keymap.hasOwnProperty(keyname)) { - var value = keymap[keyname] - if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) { continue } - if (value == "...") { delete keymap[keyname]; continue } - - var keys = map(keyname.split(" "), normalizeKeyName) - for (var i = 0; i < keys.length; i++) { - var val = (void 0), name = (void 0) - if (i == keys.length - 1) { - name = keys.join(" ") - val = value - } else { - name = keys.slice(0, i + 1).join(" ") - val = "..." - } - var prev = copy[name] - if (!prev) { copy[name] = val } - else if (prev != val) { throw new Error("Inconsistent bindings for " + name) } - } - delete keymap[keyname] - } } - for (var prop in copy) { keymap[prop] = copy[prop] } - return keymap -} - -function lookupKey(key, map, handle, context) { - map = getKeyMap(map) - var found = map.call ? map.call(key, context) : map[key] - if (found === false) { return "nothing" } - if (found === "...") { return "multi" } - if (found != null && handle(found)) { return "handled" } - - if (map.fallthrough) { - if (Object.prototype.toString.call(map.fallthrough) != "[object Array]") - { return lookupKey(key, map.fallthrough, handle, context) } - for (var i = 0; i < map.fallthrough.length; i++) { - var result = lookupKey(key, map.fallthrough[i], handle, context) - if (result) { return result } - } - } -} - -// Modifier key presses don't count as 'real' key presses for the -// purpose of keymap fallthrough. -function isModifierKey(value) { - var name = typeof value == "string" ? value : keyNames[value.keyCode] - return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod" -} - -// Look up the name of a key as indicated by an event object. -function keyName(event, noShift) { - if (presto && event.keyCode == 34 && event["char"]) { return false } - var base = keyNames[event.keyCode], name = base - if (name == null || event.altGraphKey) { return false } - if (event.altKey && base != "Alt") { name = "Alt-" + name } - if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") { name = "Ctrl-" + name } - if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Cmd") { name = "Cmd-" + name } - if (!noShift && event.shiftKey && base != "Shift") { name = "Shift-" + name } - return name -} - -function getKeyMap(val) { - return typeof val == "string" ? keyMap[val] : val -} - -// Helper for deleting text near the selection(s), used to implement -// backspace, delete, and similar functionality. -function deleteNearSelection(cm, compute) { - var ranges = cm.doc.sel.ranges, kill = [] - // Build up a set of ranges to kill first, merging overlapping - // ranges. - for (var i = 0; i < ranges.length; i++) { - var toKill = compute(ranges[i]) - while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) { - var replaced = kill.pop() - if (cmp(replaced.from, toKill.from) < 0) { - toKill.from = replaced.from - break - } - } - kill.push(toKill) - } - // Next, remove those actual ranges. - runInOp(cm, function () { - for (var i = kill.length - 1; i >= 0; i--) - { replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete") } - ensureCursorVisible(cm) - }) -} - -// Commands are parameter-less actions that can be performed on an -// editor, mostly used for keybindings. -var commands = { - selectAll: selectAll, - singleSelection: function (cm) { return cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); }, - killLine: function (cm) { return deleteNearSelection(cm, function (range) { - if (range.empty()) { - var len = getLine(cm.doc, range.head.line).text.length - if (range.head.ch == len && range.head.line < cm.lastLine()) - { return {from: range.head, to: Pos(range.head.line + 1, 0)} } - else - { return {from: range.head, to: Pos(range.head.line, len)} } - } else { - return {from: range.from(), to: range.to()} - } - }); }, - deleteLine: function (cm) { return deleteNearSelection(cm, function (range) { return ({ - from: Pos(range.from().line, 0), - to: clipPos(cm.doc, Pos(range.to().line + 1, 0)) - }); }); }, - delLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { return ({ - from: Pos(range.from().line, 0), to: range.from() - }); }); }, - delWrappedLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { - var top = cm.charCoords(range.head, "div").top + 5 - var leftPos = cm.coordsChar({left: 0, top: top}, "div") - return {from: leftPos, to: range.from()} - }); }, - delWrappedLineRight: function (cm) { return deleteNearSelection(cm, function (range) { - var top = cm.charCoords(range.head, "div").top + 5 - var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div") - return {from: range.from(), to: rightPos } - }); }, - undo: function (cm) { return cm.undo(); }, - redo: function (cm) { return cm.redo(); }, - undoSelection: function (cm) { return cm.undoSelection(); }, - redoSelection: function (cm) { return cm.redoSelection(); }, - goDocStart: function (cm) { return cm.extendSelection(Pos(cm.firstLine(), 0)); }, - goDocEnd: function (cm) { return cm.extendSelection(Pos(cm.lastLine())); }, - goLineStart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStart(cm, range.head.line); }, - {origin: "+move", bias: 1} - ); }, - goLineStartSmart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStartSmart(cm, range.head); }, - {origin: "+move", bias: 1} - ); }, - goLineEnd: function (cm) { return cm.extendSelectionsBy(function (range) { return lineEnd(cm, range.head.line); }, - {origin: "+move", bias: -1} - ); }, - goLineRight: function (cm) { return cm.extendSelectionsBy(function (range) { - var top = cm.charCoords(range.head, "div").top + 5 - return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div") - }, sel_move); }, - goLineLeft: function (cm) { return cm.extendSelectionsBy(function (range) { - var top = cm.charCoords(range.head, "div").top + 5 - return cm.coordsChar({left: 0, top: top}, "div") - }, sel_move); }, - goLineLeftSmart: function (cm) { return cm.extendSelectionsBy(function (range) { - var top = cm.charCoords(range.head, "div").top + 5 - var pos = cm.coordsChar({left: 0, top: top}, "div") - if (pos.ch < cm.getLine(pos.line).search(/\S/)) { return lineStartSmart(cm, range.head) } - return pos - }, sel_move); }, - goLineUp: function (cm) { return cm.moveV(-1, "line"); }, - goLineDown: function (cm) { return cm.moveV(1, "line"); }, - goPageUp: function (cm) { return cm.moveV(-1, "page"); }, - goPageDown: function (cm) { return cm.moveV(1, "page"); }, - goCharLeft: function (cm) { return cm.moveH(-1, "char"); }, - goCharRight: function (cm) { return cm.moveH(1, "char"); }, - goColumnLeft: function (cm) { return cm.moveH(-1, "column"); }, - goColumnRight: function (cm) { return cm.moveH(1, "column"); }, - goWordLeft: function (cm) { return cm.moveH(-1, "word"); }, - goGroupRight: function (cm) { return cm.moveH(1, "group"); }, - goGroupLeft: function (cm) { return cm.moveH(-1, "group"); }, - goWordRight: function (cm) { return cm.moveH(1, "word"); }, - delCharBefore: function (cm) { return cm.deleteH(-1, "char"); }, - delCharAfter: function (cm) { return cm.deleteH(1, "char"); }, - delWordBefore: function (cm) { return cm.deleteH(-1, "word"); }, - delWordAfter: function (cm) { return cm.deleteH(1, "word"); }, - delGroupBefore: function (cm) { return cm.deleteH(-1, "group"); }, - delGroupAfter: function (cm) { return cm.deleteH(1, "group"); }, - indentAuto: function (cm) { return cm.indentSelection("smart"); }, - indentMore: function (cm) { return cm.indentSelection("add"); }, - indentLess: function (cm) { return cm.indentSelection("subtract"); }, - insertTab: function (cm) { return cm.replaceSelection("\t"); }, - insertSoftTab: function (cm) { - var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize - for (var i = 0; i < ranges.length; i++) { - var pos = ranges[i].from() - var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize) - spaces.push(spaceStr(tabSize - col % tabSize)) - } - cm.replaceSelections(spaces) - }, - defaultTab: function (cm) { - if (cm.somethingSelected()) { cm.indentSelection("add") } - else { cm.execCommand("insertTab") } - }, - // Swap the two chars left and right of each selection's head. - // Move cursor behind the two swapped characters afterwards. - // - // Doesn't consider line feeds a character. - // Doesn't scan more than one line above to find a character. - // Doesn't do anything on an empty line. - // Doesn't do anything with non-empty selections. - transposeChars: function (cm) { return runInOp(cm, function () { - var ranges = cm.listSelections(), newSel = [] - for (var i = 0; i < ranges.length; i++) { - if (!ranges[i].empty()) { continue } - var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text - if (line) { - if (cur.ch == line.length) { cur = new Pos(cur.line, cur.ch - 1) } - if (cur.ch > 0) { - cur = new Pos(cur.line, cur.ch + 1) - cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2), - Pos(cur.line, cur.ch - 2), cur, "+transpose") - } else if (cur.line > cm.doc.first) { - var prev = getLine(cm.doc, cur.line - 1).text - if (prev) { - cur = new Pos(cur.line, 1) - cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() + - prev.charAt(prev.length - 1), - Pos(cur.line - 1, prev.length - 1), cur, "+transpose") - } - } - } - newSel.push(new Range(cur, cur)) - } - cm.setSelections(newSel) - }); }, - newlineAndIndent: function (cm) { return runInOp(cm, function () { - var sels = cm.listSelections() - for (var i = sels.length - 1; i >= 0; i--) - { cm.replaceRange(cm.doc.lineSeparator(), sels[i].anchor, sels[i].head, "+input") } - sels = cm.listSelections() - for (var i$1 = 0; i$1 < sels.length; i$1++) - { cm.indentLine(sels[i$1].from().line, null, true) } - ensureCursorVisible(cm) - }); }, - openLine: function (cm) { return cm.replaceSelection("\n", "start"); }, - toggleOverwrite: function (cm) { return cm.toggleOverwrite(); } -} - - -function lineStart(cm, lineN) { - var line = getLine(cm.doc, lineN) - var visual = visualLine(line) - if (visual != line) { lineN = lineNo(visual) } - var order = getOrder(visual) - var ch = !order ? 0 : order[0].level % 2 ? lineRight(visual) : lineLeft(visual) - return Pos(lineN, ch) -} -function lineEnd(cm, lineN) { - var merged, line = getLine(cm.doc, lineN) - while (merged = collapsedSpanAtEnd(line)) { - line = merged.find(1, true).line - lineN = null - } - var order = getOrder(line) - var ch = !order ? line.text.length : order[0].level % 2 ? lineLeft(line) : lineRight(line) - return Pos(lineN == null ? lineNo(line) : lineN, ch) -} -function lineStartSmart(cm, pos) { - var start = lineStart(cm, pos.line) - var line = getLine(cm.doc, start.line) - var order = getOrder(line) - if (!order || order[0].level == 0) { - var firstNonWS = Math.max(0, line.text.search(/\S/)) - var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch - return Pos(start.line, inWS ? 0 : firstNonWS) - } - return start -} - -// Run a handler that was bound to a key. -function doHandleBinding(cm, bound, dropShift) { - if (typeof bound == "string") { - bound = commands[bound] - if (!bound) { return false } - } - // Ensure previous input has been read, so that the handler sees a - // consistent view of the document - cm.display.input.ensurePolled() - var prevShift = cm.display.shift, done = false - try { - if (cm.isReadOnly()) { cm.state.suppressEdits = true } - if (dropShift) { cm.display.shift = false } - done = bound(cm) != Pass - } finally { - cm.display.shift = prevShift - cm.state.suppressEdits = false - } - return done -} - -function lookupKeyForEditor(cm, name, handle) { - for (var i = 0; i < cm.state.keyMaps.length; i++) { - var result = lookupKey(name, cm.state.keyMaps[i], handle, cm) - if (result) { return result } - } - return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm)) - || lookupKey(name, cm.options.keyMap, handle, cm) -} - -var stopSeq = new Delayed -function dispatchKey(cm, name, e, handle) { - var seq = cm.state.keySeq - if (seq) { - if (isModifierKey(name)) { return "handled" } - stopSeq.set(50, function () { - if (cm.state.keySeq == seq) { - cm.state.keySeq = null - cm.display.input.reset() - } - }) - name = seq + " " + name - } - var result = lookupKeyForEditor(cm, name, handle) - - if (result == "multi") - { cm.state.keySeq = name } - if (result == "handled") - { signalLater(cm, "keyHandled", cm, name, e) } - - if (result == "handled" || result == "multi") { - e_preventDefault(e) - restartBlink(cm) - } - - if (seq && !result && /\'$/.test(name)) { - e_preventDefault(e) - return true - } - return !!result -} - -// Handle a key from the keydown event. -function handleKeyBinding(cm, e) { - var name = keyName(e, true) - if (!name) { return false } - - if (e.shiftKey && !cm.state.keySeq) { - // First try to resolve full name (including 'Shift-'). Failing - // that, see if there is a cursor-motion command (starting with - // 'go') bound to the keyname without 'Shift-'. - return dispatchKey(cm, "Shift-" + name, e, function (b) { return doHandleBinding(cm, b, true); }) - || dispatchKey(cm, name, e, function (b) { - if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion) - { return doHandleBinding(cm, b) } - }) - } else { - return dispatchKey(cm, name, e, function (b) { return doHandleBinding(cm, b); }) - } -} - -// Handle a key from the keypress event -function handleCharBinding(cm, e, ch) { - return dispatchKey(cm, "'" + ch + "'", e, function (b) { return doHandleBinding(cm, b, true); }) -} - -var lastStoppedKey = null -function onKeyDown(e) { - var cm = this - cm.curOp.focus = activeElt() - if (signalDOMEvent(cm, e)) { return } - // IE does strange things with escape. - if (ie && ie_version < 11 && e.keyCode == 27) { e.returnValue = false } - var code = e.keyCode - cm.display.shift = code == 16 || e.shiftKey - var handled = handleKeyBinding(cm, e) - if (presto) { - lastStoppedKey = handled ? code : null - // Opera has no cut event... we try to at least catch the key combo - if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey)) - { cm.replaceSelection("", null, "cut") } - } - - // Turn mouse into crosshair when Alt is held on Mac. - if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className)) - { showCrossHair(cm) } -} - -function showCrossHair(cm) { - var lineDiv = cm.display.lineDiv - addClass(lineDiv, "CodeMirror-crosshair") - - function up(e) { - if (e.keyCode == 18 || !e.altKey) { - rmClass(lineDiv, "CodeMirror-crosshair") - off(document, "keyup", up) - off(document, "mouseover", up) - } - } - on(document, "keyup", up) - on(document, "mouseover", up) -} - -function onKeyUp(e) { - if (e.keyCode == 16) { this.doc.sel.shift = false } - signalDOMEvent(this, e) -} - -function onKeyPress(e) { - var cm = this - if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) { return } - var keyCode = e.keyCode, charCode = e.charCode - if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return} - if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) { return } - var ch = String.fromCharCode(charCode == null ? keyCode : charCode) - // Some browsers fire keypress events for backspace - if (ch == "\x08") { return } - if (handleCharBinding(cm, e, ch)) { return } - cm.display.input.onKeyPress(e) -} - -// A mouse down can be a single click, double click, triple click, -// start of selection drag, start of text drag, new cursor -// (ctrl-click), rectangle drag (alt-drag), or xwin -// middle-click-paste. Or it might be a click on something we should -// not interfere with, such as a scrollbar or widget. -function onMouseDown(e) { - var cm = this, display = cm.display - if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) { return } - display.input.ensurePolled() - display.shift = e.shiftKey - - if (eventInWidget(display, e)) { - if (!webkit) { - // Briefly turn off draggability, to allow widgets to do - // normal dragging things. - display.scroller.draggable = false - setTimeout(function () { return display.scroller.draggable = true; }, 100) - } - return - } - if (clickInGutter(cm, e)) { return } - var start = posFromMouse(cm, e) - window.focus() - - switch (e_button(e)) { - case 1: - // #3261: make sure, that we're not starting a second selection - if (cm.state.selectingText) - { cm.state.selectingText(e) } - else if (start) - { leftButtonDown(cm, e, start) } - else if (e_target(e) == display.scroller) - { e_preventDefault(e) } - break - case 2: - if (webkit) { cm.state.lastMiddleDown = +new Date } - if (start) { extendSelection(cm.doc, start) } - setTimeout(function () { return display.input.focus(); }, 20) - e_preventDefault(e) - break - case 3: - if (captureRightClick) { onContextMenu(cm, e) } - else { delayBlurEvent(cm) } - break - } -} - -var lastClick; -var lastDoubleClick; -function leftButtonDown(cm, e, start) { - if (ie) { setTimeout(bind(ensureFocus, cm), 0) } - else { cm.curOp.focus = activeElt() } - - var now = +new Date, type - if (lastDoubleClick && lastDoubleClick.time > now - 400 && cmp(lastDoubleClick.pos, start) == 0) { - type = "triple" - } else if (lastClick && lastClick.time > now - 400 && cmp(lastClick.pos, start) == 0) { - type = "double" - lastDoubleClick = {time: now, pos: start} - } else { - type = "single" - lastClick = {time: now, pos: start} - } - - var sel = cm.doc.sel, modifier = mac ? e.metaKey : e.ctrlKey, contained - if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() && - type == "single" && (contained = sel.contains(start)) > -1 && - (cmp((contained = sel.ranges[contained]).from(), start) < 0 || start.xRel > 0) && - (cmp(contained.to(), start) > 0 || start.xRel < 0)) - { leftButtonStartDrag(cm, e, start, modifier) } - else - { leftButtonSelect(cm, e, start, type, modifier) } -} - -// Start a text drag. When it ends, see if any dragging actually -// happen, and treat as a click if it didn't. -function leftButtonStartDrag(cm, e, start, modifier) { - var display = cm.display, startTime = +new Date - var dragEnd = operation(cm, function (e2) { - if (webkit) { display.scroller.draggable = false } - cm.state.draggingText = false - off(document, "mouseup", dragEnd) - off(display.scroller, "drop", dragEnd) - if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) { - e_preventDefault(e2) - if (!modifier && +new Date - 200 < startTime) - { extendSelection(cm.doc, start) } - // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081) - if (webkit || ie && ie_version == 9) - { setTimeout(function () {document.body.focus(); display.input.focus()}, 20) } - else - { display.input.focus() } - } - }) - // Let the drag handler handle this. - if (webkit) { display.scroller.draggable = true } - cm.state.draggingText = dragEnd - dragEnd.copy = mac ? e.altKey : e.ctrlKey - // IE's approach to draggable - if (display.scroller.dragDrop) { display.scroller.dragDrop() } - on(document, "mouseup", dragEnd) - on(display.scroller, "drop", dragEnd) -} - -// Normal selection, as opposed to text dragging. -function leftButtonSelect(cm, e, start, type, addNew) { - var display = cm.display, doc = cm.doc - e_preventDefault(e) - - var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges - if (addNew && !e.shiftKey) { - ourIndex = doc.sel.contains(start) - if (ourIndex > -1) - { ourRange = ranges[ourIndex] } - else - { ourRange = new Range(start, start) } - } else { - ourRange = doc.sel.primary() - ourIndex = doc.sel.primIndex - } - - if (chromeOS ? e.shiftKey && e.metaKey : e.altKey) { - type = "rect" - if (!addNew) { ourRange = new Range(start, start) } - start = posFromMouse(cm, e, true, true) - ourIndex = -1 - } else if (type == "double") { - var word = cm.findWordAt(start) - if (cm.display.shift || doc.extend) - { ourRange = extendRange(doc, ourRange, word.anchor, word.head) } - else - { ourRange = word } - } else if (type == "triple") { - var line = new Range(Pos(start.line, 0), clipPos(doc, Pos(start.line + 1, 0))) - if (cm.display.shift || doc.extend) - { ourRange = extendRange(doc, ourRange, line.anchor, line.head) } - else - { ourRange = line } - } else { - ourRange = extendRange(doc, ourRange, start) - } - - if (!addNew) { - ourIndex = 0 - setSelection(doc, new Selection([ourRange], 0), sel_mouse) - startSel = doc.sel - } else if (ourIndex == -1) { - ourIndex = ranges.length - setSelection(doc, normalizeSelection(ranges.concat([ourRange]), ourIndex), - {scroll: false, origin: "*mouse"}) - } else if (ranges.length > 1 && ranges[ourIndex].empty() && type == "single" && !e.shiftKey) { - setSelection(doc, normalizeSelection(ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0), - {scroll: false, origin: "*mouse"}) - startSel = doc.sel - } else { - replaceOneSelection(doc, ourIndex, ourRange, sel_mouse) - } - - var lastPos = start - function extendTo(pos) { - if (cmp(lastPos, pos) == 0) { return } - lastPos = pos - - if (type == "rect") { - var ranges = [], tabSize = cm.options.tabSize - var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize) - var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize) - var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol) - for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line)); - line <= end; line++) { - var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize) - if (left == right) - { ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))) } - else if (text.length > leftPos) - { ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))) } - } - if (!ranges.length) { ranges.push(new Range(start, start)) } - setSelection(doc, normalizeSelection(startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), - {origin: "*mouse", scroll: false}) - cm.scrollIntoView(pos) - } else { - var oldRange = ourRange - var anchor = oldRange.anchor, head = pos - if (type != "single") { - var range - if (type == "double") - { range = cm.findWordAt(pos) } - else - { range = new Range(Pos(pos.line, 0), clipPos(doc, Pos(pos.line + 1, 0))) } - if (cmp(range.anchor, anchor) > 0) { - head = range.head - anchor = minPos(oldRange.from(), range.anchor) - } else { - head = range.anchor - anchor = maxPos(oldRange.to(), range.head) - } - } - var ranges$1 = startSel.ranges.slice(0) - ranges$1[ourIndex] = new Range(clipPos(doc, anchor), head) - setSelection(doc, normalizeSelection(ranges$1, ourIndex), sel_mouse) - } - } - - var editorSize = display.wrapper.getBoundingClientRect() - // Used to ensure timeout re-tries don't fire when another extend - // happened in the meantime (clearTimeout isn't reliable -- at - // least on Chrome, the timeouts still happen even when cleared, - // if the clear happens after their scheduled firing time). - var counter = 0 - - function extend(e) { - var curCount = ++counter - var cur = posFromMouse(cm, e, true, type == "rect") - if (!cur) { return } - if (cmp(cur, lastPos) != 0) { - cm.curOp.focus = activeElt() - extendTo(cur) - var visible = visibleLines(display, doc) - if (cur.line >= visible.to || cur.line < visible.from) - { setTimeout(operation(cm, function () {if (counter == curCount) { extend(e) }}), 150) } - } else { - var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0 - if (outside) { setTimeout(operation(cm, function () { - if (counter != curCount) { return } - display.scroller.scrollTop += outside - extend(e) - }), 50) } - } - } - - function done(e) { - cm.state.selectingText = false - counter = Infinity - e_preventDefault(e) - display.input.focus() - off(document, "mousemove", move) - off(document, "mouseup", up) - doc.history.lastSelOrigin = null - } - - var move = operation(cm, function (e) { - if (!e_button(e)) { done(e) } - else { extend(e) } - }) - var up = operation(cm, done) - cm.state.selectingText = up - on(document, "mousemove", move) - on(document, "mouseup", up) -} - - -// Determines whether an event happened in the gutter, and fires the -// handlers for the corresponding event. -function gutterEvent(cm, e, type, prevent) { - var mX, mY - try { mX = e.clientX; mY = e.clientY } - catch(e) { return false } - if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false } - if (prevent) { e_preventDefault(e) } - - var display = cm.display - var lineBox = display.lineDiv.getBoundingClientRect() - - if (mY > lineBox.bottom || !hasHandler(cm, type)) { return e_defaultPrevented(e) } - mY -= lineBox.top - display.viewOffset - - for (var i = 0; i < cm.options.gutters.length; ++i) { - var g = display.gutters.childNodes[i] - if (g && g.getBoundingClientRect().right >= mX) { - var line = lineAtHeight(cm.doc, mY) - var gutter = cm.options.gutters[i] - signal(cm, type, cm, line, gutter, e) - return e_defaultPrevented(e) - } - } -} - -function clickInGutter(cm, e) { - return gutterEvent(cm, e, "gutterClick", true) -} - -// CONTEXT MENU HANDLING - -// To make the context menu work, we need to briefly unhide the -// textarea (making it as unobtrusive as possible) to let the -// right-click take effect on it. -function onContextMenu(cm, e) { - if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) { return } - if (signalDOMEvent(cm, e, "contextmenu")) { return } - cm.display.input.onContextMenu(e) -} - -function contextMenuInGutter(cm, e) { - if (!hasHandler(cm, "gutterContextMenu")) { return false } - return gutterEvent(cm, e, "gutterContextMenu", false) -} - -function themeChanged(cm) { - cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + - cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-") - clearCaches(cm) -} - -var Init = {toString: function(){return "CodeMirror.Init"}} - -var defaults = {} -var optionHandlers = {} - -function defineOptions(CodeMirror) { - var optionHandlers = CodeMirror.optionHandlers - - function option(name, deflt, handle, notOnInit) { - CodeMirror.defaults[name] = deflt - if (handle) { optionHandlers[name] = - notOnInit ? function (cm, val, old) {if (old != Init) { handle(cm, val, old) }} : handle } - } - - CodeMirror.defineOption = option - - // Passed to option handlers when there is no old value. - CodeMirror.Init = Init - - // These two are, on init, called from the constructor because they - // have to be initialized before the editor can start at all. - option("value", "", function (cm, val) { return cm.setValue(val); }, true) - option("mode", null, function (cm, val) { - cm.doc.modeOption = val - loadMode(cm) - }, true) - - option("indentUnit", 2, loadMode, true) - option("indentWithTabs", false) - option("smartIndent", true) - option("tabSize", 4, function (cm) { - resetModeState(cm) - clearCaches(cm) - regChange(cm) - }, true) - option("lineSeparator", null, function (cm, val) { - cm.doc.lineSep = val - if (!val) { return } - var newBreaks = [], lineNo = cm.doc.first - cm.doc.iter(function (line) { - for (var pos = 0;;) { - var found = line.text.indexOf(val, pos) - if (found == -1) { break } - pos = found + val.length - newBreaks.push(Pos(lineNo, found)) - } - lineNo++ - }) - for (var i = newBreaks.length - 1; i >= 0; i--) - { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)) } - }) - option("specialChars", /[\u0000-\u001f\u007f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff]/g, function (cm, val, old) { - cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g") - if (old != Init) { cm.refresh() } - }) - option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function (cm) { return cm.refresh(); }, true) - option("electricChars", true) - option("inputStyle", mobile ? "contenteditable" : "textarea", function () { - throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME - }, true) - option("spellcheck", false, function (cm, val) { return cm.getInputField().spellcheck = val; }, true) - option("rtlMoveVisually", !windows) - option("wholeLineUpdateBefore", true) - - option("theme", "default", function (cm) { - themeChanged(cm) - guttersChanged(cm) - }, true) - option("keyMap", "default", function (cm, val, old) { - var next = getKeyMap(val) - var prev = old != Init && getKeyMap(old) - if (prev && prev.detach) { prev.detach(cm, next) } - if (next.attach) { next.attach(cm, prev || null) } - }) - option("extraKeys", null) - - option("lineWrapping", false, wrappingChanged, true) - option("gutters", [], function (cm) { - setGuttersForLineNumbers(cm.options) - guttersChanged(cm) - }, true) - option("fixedGutter", true, function (cm, val) { - cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0" - cm.refresh() - }, true) - option("coverGutterNextToScrollbar", false, function (cm) { return updateScrollbars(cm); }, true) - option("scrollbarStyle", "native", function (cm) { - initScrollbars(cm) - updateScrollbars(cm) - cm.display.scrollbars.setScrollTop(cm.doc.scrollTop) - cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft) - }, true) - option("lineNumbers", false, function (cm) { - setGuttersForLineNumbers(cm.options) - guttersChanged(cm) - }, true) - option("firstLineNumber", 1, guttersChanged, true) - option("lineNumberFormatter", function (integer) { return integer; }, guttersChanged, true) - option("showCursorWhenSelecting", false, updateSelection, true) - - option("resetSelectionOnContextMenu", true) - option("lineWiseCopyCut", true) - - option("readOnly", false, function (cm, val) { - if (val == "nocursor") { - onBlur(cm) - cm.display.input.blur() - cm.display.disabled = true - } else { - cm.display.disabled = false - } - cm.display.input.readOnlyChanged(val) - }) - option("disableInput", false, function (cm, val) {if (!val) { cm.display.input.reset() }}, true) - option("dragDrop", true, dragDropChanged) - option("allowDropFileTypes", null) - - option("cursorBlinkRate", 530) - option("cursorScrollMargin", 0) - option("cursorHeight", 1, updateSelection, true) - option("singleCursorHeightPerLine", true, updateSelection, true) - option("workTime", 100) - option("workDelay", 100) - option("flattenSpans", true, resetModeState, true) - option("addModeClass", false, resetModeState, true) - option("pollInterval", 100) - option("undoDepth", 200, function (cm, val) { return cm.doc.history.undoDepth = val; }) - option("historyEventDelay", 1250) - option("viewportMargin", 10, function (cm) { return cm.refresh(); }, true) - option("maxHighlightLength", 10000, resetModeState, true) - option("moveInputWithCursor", true, function (cm, val) { - if (!val) { cm.display.input.resetPosition() } - }) - - option("tabindex", null, function (cm, val) { return cm.display.input.getField().tabIndex = val || ""; }) - option("autofocus", null) -} - -function guttersChanged(cm) { - updateGutters(cm) - regChange(cm) - alignHorizontally(cm) -} - -function dragDropChanged(cm, value, old) { - var wasOn = old && old != Init - if (!value != !wasOn) { - var funcs = cm.display.dragFunctions - var toggle = value ? on : off - toggle(cm.display.scroller, "dragstart", funcs.start) - toggle(cm.display.scroller, "dragenter", funcs.enter) - toggle(cm.display.scroller, "dragover", funcs.over) - toggle(cm.display.scroller, "dragleave", funcs.leave) - toggle(cm.display.scroller, "drop", funcs.drop) - } -} - -function wrappingChanged(cm) { - if (cm.options.lineWrapping) { - addClass(cm.display.wrapper, "CodeMirror-wrap") - cm.display.sizer.style.minWidth = "" - cm.display.sizerWidth = null - } else { - rmClass(cm.display.wrapper, "CodeMirror-wrap") - findMaxLine(cm) - } - estimateLineHeights(cm) - regChange(cm) - clearCaches(cm) - setTimeout(function () { return updateScrollbars(cm); }, 100) -} - -// A CodeMirror instance represents an editor. This is the object -// that user code is usually dealing with. - -function CodeMirror(place, options) { - var this$1 = this; - - if (!(this instanceof CodeMirror)) { return new CodeMirror(place, options) } - - this.options = options = options ? copyObj(options) : {} - // Determine effective options based on given values and defaults. - copyObj(defaults, options, false) - setGuttersForLineNumbers(options) - - var doc = options.value - if (typeof doc == "string") { doc = new Doc(doc, options.mode, null, options.lineSeparator) } - this.doc = doc - - var input = new CodeMirror.inputStyles[options.inputStyle](this) - var display = this.display = new Display(place, doc, input) - display.wrapper.CodeMirror = this - updateGutters(this) - themeChanged(this) - if (options.lineWrapping) - { this.display.wrapper.className += " CodeMirror-wrap" } - initScrollbars(this) - - this.state = { - keyMaps: [], // stores maps added by addKeyMap - overlays: [], // highlighting overlays, as added by addOverlay - modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info - overwrite: false, - delayingBlurEvent: false, - focused: false, - suppressEdits: false, // used to disable editing during key handlers when in readOnly mode - pasteIncoming: false, cutIncoming: false, // help recognize paste/cut edits in input.poll - selectingText: false, - draggingText: false, - highlight: new Delayed(), // stores highlight worker timeout - keySeq: null, // Unfinished key sequence - specialChars: null - } - - if (options.autofocus && !mobile) { display.input.focus() } - - // Override magic textarea content restore that IE sometimes does - // on our hidden textarea on reload - if (ie && ie_version < 11) { setTimeout(function () { return this$1.display.input.reset(true); }, 20) } - - registerEventHandlers(this) - ensureGlobalHandlers() - - startOperation(this) - this.curOp.forceUpdate = true - attachDoc(this, doc) - - if ((options.autofocus && !mobile) || this.hasFocus()) - { setTimeout(bind(onFocus, this), 20) } - else - { onBlur(this) } - - for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt)) - { optionHandlers[opt](this$1, options[opt], Init) } } - maybeUpdateLineNumberWidth(this) - if (options.finishInit) { options.finishInit(this) } - for (var i = 0; i < initHooks.length; ++i) { initHooks[i](this$1) } - endOperation(this) - // Suppress optimizelegibility in Webkit, since it breaks text - // measuring on line wrapping boundaries. - if (webkit && options.lineWrapping && - getComputedStyle(display.lineDiv).textRendering == "optimizelegibility") - { display.lineDiv.style.textRendering = "auto" } -} - -// The default configuration options. -CodeMirror.defaults = defaults -// Functions to run when options are changed. -CodeMirror.optionHandlers = optionHandlers - -// Attach the necessary event handlers when initializing the editor -function registerEventHandlers(cm) { - var d = cm.display - on(d.scroller, "mousedown", operation(cm, onMouseDown)) - // Older IE's will not fire a second mousedown for a double click - if (ie && ie_version < 11) - { on(d.scroller, "dblclick", operation(cm, function (e) { - if (signalDOMEvent(cm, e)) { return } - var pos = posFromMouse(cm, e) - if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) { return } - e_preventDefault(e) - var word = cm.findWordAt(pos) - extendSelection(cm.doc, word.anchor, word.head) - })) } - else - { on(d.scroller, "dblclick", function (e) { return signalDOMEvent(cm, e) || e_preventDefault(e); }) } - // Some browsers fire contextmenu *after* opening the menu, at - // which point we can't mess with it anymore. Context menu is - // handled in onMouseDown for these browsers. - if (!captureRightClick) { on(d.scroller, "contextmenu", function (e) { return onContextMenu(cm, e); }) } - - // Used to suppress mouse event handling when a touch happens - var touchFinished, prevTouch = {end: 0} - function finishTouch() { - if (d.activeTouch) { - touchFinished = setTimeout(function () { return d.activeTouch = null; }, 1000) - prevTouch = d.activeTouch - prevTouch.end = +new Date - } - } - function isMouseLikeTouchEvent(e) { - if (e.touches.length != 1) { return false } - var touch = e.touches[0] - return touch.radiusX <= 1 && touch.radiusY <= 1 - } - function farAway(touch, other) { - if (other.left == null) { return true } - var dx = other.left - touch.left, dy = other.top - touch.top - return dx * dx + dy * dy > 20 * 20 - } - on(d.scroller, "touchstart", function (e) { - if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e)) { - d.input.ensurePolled() - clearTimeout(touchFinished) - var now = +new Date - d.activeTouch = {start: now, moved: false, - prev: now - prevTouch.end <= 300 ? prevTouch : null} - if (e.touches.length == 1) { - d.activeTouch.left = e.touches[0].pageX - d.activeTouch.top = e.touches[0].pageY - } - } - }) - on(d.scroller, "touchmove", function () { - if (d.activeTouch) { d.activeTouch.moved = true } - }) - on(d.scroller, "touchend", function (e) { - var touch = d.activeTouch - if (touch && !eventInWidget(d, e) && touch.left != null && - !touch.moved && new Date - touch.start < 300) { - var pos = cm.coordsChar(d.activeTouch, "page"), range - if (!touch.prev || farAway(touch, touch.prev)) // Single tap - { range = new Range(pos, pos) } - else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap - { range = cm.findWordAt(pos) } - else // Triple tap - { range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) } - cm.setSelection(range.anchor, range.head) - cm.focus() - e_preventDefault(e) - } - finishTouch() - }) - on(d.scroller, "touchcancel", finishTouch) - - // Sync scrolling between fake scrollbars and real scrollable - // area, ensure viewport is updated when scrolling. - on(d.scroller, "scroll", function () { - if (d.scroller.clientHeight) { - setScrollTop(cm, d.scroller.scrollTop) - setScrollLeft(cm, d.scroller.scrollLeft, true) - signal(cm, "scroll", cm) - } - }) - - // Listen to wheel events in order to try and update the viewport on time. - on(d.scroller, "mousewheel", function (e) { return onScrollWheel(cm, e); }) - on(d.scroller, "DOMMouseScroll", function (e) { return onScrollWheel(cm, e); }) - - // Prevent wrapper from ever scrolling - on(d.wrapper, "scroll", function () { return d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; }) - - d.dragFunctions = { - enter: function (e) {if (!signalDOMEvent(cm, e)) { e_stop(e) }}, - over: function (e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e) }}, - start: function (e) { return onDragStart(cm, e); }, - drop: operation(cm, onDrop), - leave: function (e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm) }} - } - - var inp = d.input.getField() - on(inp, "keyup", function (e) { return onKeyUp.call(cm, e); }) - on(inp, "keydown", operation(cm, onKeyDown)) - on(inp, "keypress", operation(cm, onKeyPress)) - on(inp, "focus", function (e) { return onFocus(cm, e); }) - on(inp, "blur", function (e) { return onBlur(cm, e); }) -} - -var initHooks = [] -CodeMirror.defineInitHook = function (f) { return initHooks.push(f); } - -// Indent the given line. The how parameter can be "smart", -// "add"/null, "subtract", or "prev". When aggressive is false -// (typically set to true for forced single-line indents), empty -// lines are not indented, and places where the mode returns Pass -// are left alone. -function indentLine(cm, n, how, aggressive) { - var doc = cm.doc, state - if (how == null) { how = "add" } - if (how == "smart") { - // Fall back to "prev" when the mode doesn't have an indentation - // method. - if (!doc.mode.indent) { how = "prev" } - else { state = getStateBefore(cm, n) } - } - - var tabSize = cm.options.tabSize - var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize) - if (line.stateAfter) { line.stateAfter = null } - var curSpaceString = line.text.match(/^\s*/)[0], indentation - if (!aggressive && !/\S/.test(line.text)) { - indentation = 0 - how = "not" - } else if (how == "smart") { - indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text) - if (indentation == Pass || indentation > 150) { - if (!aggressive) { return } - how = "prev" - } - } - if (how == "prev") { - if (n > doc.first) { indentation = countColumn(getLine(doc, n-1).text, null, tabSize) } - else { indentation = 0 } - } else if (how == "add") { - indentation = curSpace + cm.options.indentUnit - } else if (how == "subtract") { - indentation = curSpace - cm.options.indentUnit - } else if (typeof how == "number") { - indentation = curSpace + how - } - indentation = Math.max(0, indentation) - - var indentString = "", pos = 0 - if (cm.options.indentWithTabs) - { for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t"} } - if (pos < indentation) { indentString += spaceStr(indentation - pos) } - - if (indentString != curSpaceString) { - replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input") - line.stateAfter = null - return true - } else { - // Ensure that, if the cursor was in the whitespace at the start - // of the line, it is moved to the end of that space. - for (var i$1 = 0; i$1 < doc.sel.ranges.length; i$1++) { - var range = doc.sel.ranges[i$1] - if (range.head.line == n && range.head.ch < curSpaceString.length) { - var pos$1 = Pos(n, curSpaceString.length) - replaceOneSelection(doc, i$1, new Range(pos$1, pos$1)) - break - } - } - } -} - -// This will be set to a {lineWise: bool, text: [string]} object, so -// that, when pasting, we know what kind of selections the copied -// text was made out of. -var lastCopied = null - -function setLastCopied(newLastCopied) { - lastCopied = newLastCopied -} - -function applyTextInput(cm, inserted, deleted, sel, origin) { - var doc = cm.doc - cm.display.shift = false - if (!sel) { sel = doc.sel } - - var paste = cm.state.pasteIncoming || origin == "paste" - var textLines = splitLinesAuto(inserted), multiPaste = null - // When pasing N lines into N selections, insert one line per selection - if (paste && sel.ranges.length > 1) { - if (lastCopied && lastCopied.text.join("\n") == inserted) { - if (sel.ranges.length % lastCopied.text.length == 0) { - multiPaste = [] - for (var i = 0; i < lastCopied.text.length; i++) - { multiPaste.push(doc.splitLines(lastCopied.text[i])) } - } - } else if (textLines.length == sel.ranges.length) { - multiPaste = map(textLines, function (l) { return [l]; }) - } - } - - var updateInput - // Normal behavior is to insert the new text into every selection - for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) { - var range = sel.ranges[i$1] - var from = range.from(), to = range.to() - if (range.empty()) { - if (deleted && deleted > 0) // Handle deletion - { from = Pos(from.line, from.ch - deleted) } - else if (cm.state.overwrite && !paste) // Handle overwrite - { to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)) } - else if (lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == inserted) - { from = to = Pos(from.line, 0) } - } - updateInput = cm.curOp.updateInput - var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines, - origin: origin || (paste ? "paste" : cm.state.cutIncoming ? "cut" : "+input")} - makeChange(cm.doc, changeEvent) - signalLater(cm, "inputRead", cm, changeEvent) - } - if (inserted && !paste) - { triggerElectric(cm, inserted) } - - ensureCursorVisible(cm) - cm.curOp.updateInput = updateInput - cm.curOp.typing = true - cm.state.pasteIncoming = cm.state.cutIncoming = false -} - -function handlePaste(e, cm) { - var pasted = e.clipboardData && e.clipboardData.getData("Text") - if (pasted) { - e.preventDefault() - if (!cm.isReadOnly() && !cm.options.disableInput) - { runInOp(cm, function () { return applyTextInput(cm, pasted, 0, null, "paste"); }) } - return true - } -} - -function triggerElectric(cm, inserted) { - // When an 'electric' character is inserted, immediately trigger a reindent - if (!cm.options.electricChars || !cm.options.smartIndent) { return } - var sel = cm.doc.sel - - for (var i = sel.ranges.length - 1; i >= 0; i--) { - var range = sel.ranges[i] - if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) { continue } - var mode = cm.getModeAt(range.head) - var indented = false - if (mode.electricChars) { - for (var j = 0; j < mode.electricChars.length; j++) - { if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) { - indented = indentLine(cm, range.head.line, "smart") - break - } } - } else if (mode.electricInput) { - if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch))) - { indented = indentLine(cm, range.head.line, "smart") } - } - if (indented) { signalLater(cm, "electricInput", cm, range.head.line) } - } -} - -function copyableRanges(cm) { - var text = [], ranges = [] - for (var i = 0; i < cm.doc.sel.ranges.length; i++) { - var line = cm.doc.sel.ranges[i].head.line - var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)} - ranges.push(lineRange) - text.push(cm.getRange(lineRange.anchor, lineRange.head)) - } - return {text: text, ranges: ranges} -} - -function disableBrowserMagic(field, spellcheck) { - field.setAttribute("autocorrect", "off") - field.setAttribute("autocapitalize", "off") - field.setAttribute("spellcheck", !!spellcheck) -} - -function hiddenTextarea() { - var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none") - var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;") - // The textarea is kept positioned near the cursor to prevent the - // fact that it'll be scrolled into view on input from scrolling - // our fake cursor out of view. On webkit, when wrap=off, paste is - // very slow. So make the area wide instead. - if (webkit) { te.style.width = "1000px" } - else { te.setAttribute("wrap", "off") } - // If border: 0; -- iOS fails to open keyboard (issue #1287) - if (ios) { te.style.border = "1px solid black" } - disableBrowserMagic(te) - return div -} - -// The publicly visible API. Note that methodOp(f) means -// 'wrap f in an operation, performed on its `this` parameter'. - -// This is not the complete set of editor methods. Most of the -// methods defined on the Doc type are also injected into -// CodeMirror.prototype, for backwards compatibility and -// convenience. - -function addEditorMethods(CodeMirror) { - var optionHandlers = CodeMirror.optionHandlers - - var helpers = CodeMirror.helpers = {} - - CodeMirror.prototype = { - constructor: CodeMirror, - focus: function(){window.focus(); this.display.input.focus()}, - - setOption: function(option, value) { - var options = this.options, old = options[option] - if (options[option] == value && option != "mode") { return } - options[option] = value - if (optionHandlers.hasOwnProperty(option)) - { operation(this, optionHandlers[option])(this, value, old) } - signal(this, "optionChange", this, option) - }, - - getOption: function(option) {return this.options[option]}, - getDoc: function() {return this.doc}, - - addKeyMap: function(map, bottom) { - this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map)) - }, - removeKeyMap: function(map) { - var maps = this.state.keyMaps - for (var i = 0; i < maps.length; ++i) - { if (maps[i] == map || maps[i].name == map) { - maps.splice(i, 1) - return true - } } - }, - - addOverlay: methodOp(function(spec, options) { - var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec) - if (mode.startState) { throw new Error("Overlays may not be stateful.") } - insertSorted(this.state.overlays, - {mode: mode, modeSpec: spec, opaque: options && options.opaque, - priority: (options && options.priority) || 0}, - function (overlay) { return overlay.priority; }) - this.state.modeGen++ - regChange(this) - }), - removeOverlay: methodOp(function(spec) { - var this$1 = this; - - var overlays = this.state.overlays - for (var i = 0; i < overlays.length; ++i) { - var cur = overlays[i].modeSpec - if (cur == spec || typeof spec == "string" && cur.name == spec) { - overlays.splice(i, 1) - this$1.state.modeGen++ - regChange(this$1) - return - } - } - }), - - indentLine: methodOp(function(n, dir, aggressive) { - if (typeof dir != "string" && typeof dir != "number") { - if (dir == null) { dir = this.options.smartIndent ? "smart" : "prev" } - else { dir = dir ? "add" : "subtract" } - } - if (isLine(this.doc, n)) { indentLine(this, n, dir, aggressive) } - }), - indentSelection: methodOp(function(how) { - var this$1 = this; - - var ranges = this.doc.sel.ranges, end = -1 - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i] - if (!range.empty()) { - var from = range.from(), to = range.to() - var start = Math.max(end, from.line) - end = Math.min(this$1.lastLine(), to.line - (to.ch ? 0 : 1)) + 1 - for (var j = start; j < end; ++j) - { indentLine(this$1, j, how) } - var newRanges = this$1.doc.sel.ranges - if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0) - { replaceOneSelection(this$1.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll) } - } else if (range.head.line > end) { - indentLine(this$1, range.head.line, how, true) - end = range.head.line - if (i == this$1.doc.sel.primIndex) { ensureCursorVisible(this$1) } - } - } - }), - - // Fetch the parser token for a given character. Useful for hacks - // that want to inspect the mode state (say, for completion). - getTokenAt: function(pos, precise) { - return takeToken(this, pos, precise) - }, - - getLineTokens: function(line, precise) { - return takeToken(this, Pos(line), precise, true) - }, - - getTokenTypeAt: function(pos) { - pos = clipPos(this.doc, pos) - var styles = getLineStyles(this, getLine(this.doc, pos.line)) - var before = 0, after = (styles.length - 1) / 2, ch = pos.ch - var type - if (ch == 0) { type = styles[2] } - else { for (;;) { - var mid = (before + after) >> 1 - if ((mid ? styles[mid * 2 - 1] : 0) >= ch) { after = mid } - else if (styles[mid * 2 + 1] < ch) { before = mid + 1 } - else { type = styles[mid * 2 + 2]; break } - } } - var cut = type ? type.indexOf("overlay ") : -1 - return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1) - }, - - getModeAt: function(pos) { - var mode = this.doc.mode - if (!mode.innerMode) { return mode } - return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode - }, - - getHelper: function(pos, type) { - return this.getHelpers(pos, type)[0] - }, - - getHelpers: function(pos, type) { - var this$1 = this; - - var found = [] - if (!helpers.hasOwnProperty(type)) { return found } - var help = helpers[type], mode = this.getModeAt(pos) - if (typeof mode[type] == "string") { - if (help[mode[type]]) { found.push(help[mode[type]]) } - } else if (mode[type]) { - for (var i = 0; i < mode[type].length; i++) { - var val = help[mode[type][i]] - if (val) { found.push(val) } - } - } else if (mode.helperType && help[mode.helperType]) { - found.push(help[mode.helperType]) - } else if (help[mode.name]) { - found.push(help[mode.name]) - } - for (var i$1 = 0; i$1 < help._global.length; i$1++) { - var cur = help._global[i$1] - if (cur.pred(mode, this$1) && indexOf(found, cur.val) == -1) - { found.push(cur.val) } - } - return found - }, - - getStateAfter: function(line, precise) { - var doc = this.doc - line = clipLine(doc, line == null ? doc.first + doc.size - 1: line) - return getStateBefore(this, line + 1, precise) - }, - - cursorCoords: function(start, mode) { - var pos, range = this.doc.sel.primary() - if (start == null) { pos = range.head } - else if (typeof start == "object") { pos = clipPos(this.doc, start) } - else { pos = start ? range.from() : range.to() } - return cursorCoords(this, pos, mode || "page") - }, - - charCoords: function(pos, mode) { - return charCoords(this, clipPos(this.doc, pos), mode || "page") - }, - - coordsChar: function(coords, mode) { - coords = fromCoordSystem(this, coords, mode || "page") - return coordsChar(this, coords.left, coords.top) - }, - - lineAtHeight: function(height, mode) { - height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top - return lineAtHeight(this.doc, height + this.display.viewOffset) - }, - heightAtLine: function(line, mode, includeWidgets) { - var end = false, lineObj - if (typeof line == "number") { - var last = this.doc.first + this.doc.size - 1 - if (line < this.doc.first) { line = this.doc.first } - else if (line > last) { line = last; end = true } - lineObj = getLine(this.doc, line) - } else { - lineObj = line - } - return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page", includeWidgets).top + - (end ? this.doc.height - heightAtLine(lineObj) : 0) - }, - - defaultTextHeight: function() { return textHeight(this.display) }, - defaultCharWidth: function() { return charWidth(this.display) }, - - getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo}}, - - addWidget: function(pos, node, scroll, vert, horiz) { - var display = this.display - pos = cursorCoords(this, clipPos(this.doc, pos)) - var top = pos.bottom, left = pos.left - node.style.position = "absolute" - node.setAttribute("cm-ignore-events", "true") - this.display.input.setUneditable(node) - display.sizer.appendChild(node) - if (vert == "over") { - top = pos.top - } else if (vert == "above" || vert == "near") { - var vspace = Math.max(display.wrapper.clientHeight, this.doc.height), - hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth) - // Default to positioning above (if specified and possible); otherwise default to positioning below - if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight) - { top = pos.top - node.offsetHeight } - else if (pos.bottom + node.offsetHeight <= vspace) - { top = pos.bottom } - if (left + node.offsetWidth > hspace) - { left = hspace - node.offsetWidth } - } - node.style.top = top + "px" - node.style.left = node.style.right = "" - if (horiz == "right") { - left = display.sizer.clientWidth - node.offsetWidth - node.style.right = "0px" - } else { - if (horiz == "left") { left = 0 } - else if (horiz == "middle") { left = (display.sizer.clientWidth - node.offsetWidth) / 2 } - node.style.left = left + "px" - } - if (scroll) - { scrollIntoView(this, left, top, left + node.offsetWidth, top + node.offsetHeight) } - }, - - triggerOnKeyDown: methodOp(onKeyDown), - triggerOnKeyPress: methodOp(onKeyPress), - triggerOnKeyUp: onKeyUp, - - execCommand: function(cmd) { - if (commands.hasOwnProperty(cmd)) - { return commands[cmd].call(null, this) } - }, - - triggerElectric: methodOp(function(text) { triggerElectric(this, text) }), - - findPosH: function(from, amount, unit, visually) { - var this$1 = this; - - var dir = 1 - if (amount < 0) { dir = -1; amount = -amount } - var cur = clipPos(this.doc, from) - for (var i = 0; i < amount; ++i) { - cur = findPosH(this$1.doc, cur, dir, unit, visually) - if (cur.hitSide) { break } - } - return cur - }, - - moveH: methodOp(function(dir, unit) { - var this$1 = this; - - this.extendSelectionsBy(function (range) { - if (this$1.display.shift || this$1.doc.extend || range.empty()) - { return findPosH(this$1.doc, range.head, dir, unit, this$1.options.rtlMoveVisually) } - else - { return dir < 0 ? range.from() : range.to() } - }, sel_move) - }), - - deleteH: methodOp(function(dir, unit) { - var sel = this.doc.sel, doc = this.doc - if (sel.somethingSelected()) - { doc.replaceSelection("", null, "+delete") } - else - { deleteNearSelection(this, function (range) { - var other = findPosH(doc, range.head, dir, unit, false) - return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other} - }) } - }), - - findPosV: function(from, amount, unit, goalColumn) { - var this$1 = this; - - var dir = 1, x = goalColumn - if (amount < 0) { dir = -1; amount = -amount } - var cur = clipPos(this.doc, from) - for (var i = 0; i < amount; ++i) { - var coords = cursorCoords(this$1, cur, "div") - if (x == null) { x = coords.left } - else { coords.left = x } - cur = findPosV(this$1, coords, dir, unit) - if (cur.hitSide) { break } - } - return cur - }, - - moveV: methodOp(function(dir, unit) { - var this$1 = this; - - var doc = this.doc, goals = [] - var collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected() - doc.extendSelectionsBy(function (range) { - if (collapse) - { return dir < 0 ? range.from() : range.to() } - var headPos = cursorCoords(this$1, range.head, "div") - if (range.goalColumn != null) { headPos.left = range.goalColumn } - goals.push(headPos.left) - var pos = findPosV(this$1, headPos, dir, unit) - if (unit == "page" && range == doc.sel.primary()) - { addToScrollPos(this$1, null, charCoords(this$1, pos, "div").top - headPos.top) } - return pos - }, sel_move) - if (goals.length) { for (var i = 0; i < doc.sel.ranges.length; i++) - { doc.sel.ranges[i].goalColumn = goals[i] } } - }), - - // Find the word at the given position (as returned by coordsChar). - findWordAt: function(pos) { - var doc = this.doc, line = getLine(doc, pos.line).text - var start = pos.ch, end = pos.ch - if (line) { - var helper = this.getHelper(pos, "wordChars") - if ((pos.xRel < 0 || end == line.length) && start) { --start; } else { ++end } - var startChar = line.charAt(start) - var check = isWordChar(startChar, helper) - ? function (ch) { return isWordChar(ch, helper); } - : /\s/.test(startChar) ? function (ch) { return /\s/.test(ch); } - : function (ch) { return (!/\s/.test(ch) && !isWordChar(ch)); } - while (start > 0 && check(line.charAt(start - 1))) { --start } - while (end < line.length && check(line.charAt(end))) { ++end } - } - return new Range(Pos(pos.line, start), Pos(pos.line, end)) - }, - - toggleOverwrite: function(value) { - if (value != null && value == this.state.overwrite) { return } - if (this.state.overwrite = !this.state.overwrite) - { addClass(this.display.cursorDiv, "CodeMirror-overwrite") } - else - { rmClass(this.display.cursorDiv, "CodeMirror-overwrite") } - - signal(this, "overwriteToggle", this, this.state.overwrite) - }, - hasFocus: function() { return this.display.input.getField() == activeElt() }, - isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) }, - - scrollTo: methodOp(function(x, y) { - if (x != null || y != null) { resolveScrollToPos(this) } - if (x != null) { this.curOp.scrollLeft = x } - if (y != null) { this.curOp.scrollTop = y } - }), - getScrollInfo: function() { - var scroller = this.display.scroller - return {left: scroller.scrollLeft, top: scroller.scrollTop, - height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight, - width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth, - clientHeight: displayHeight(this), clientWidth: displayWidth(this)} - }, - - scrollIntoView: methodOp(function(range, margin) { - if (range == null) { - range = {from: this.doc.sel.primary().head, to: null} - if (margin == null) { margin = this.options.cursorScrollMargin } - } else if (typeof range == "number") { - range = {from: Pos(range, 0), to: null} - } else if (range.from == null) { - range = {from: range, to: null} - } - if (!range.to) { range.to = range.from } - range.margin = margin || 0 - - if (range.from.line != null) { - resolveScrollToPos(this) - this.curOp.scrollToPos = range - } else { - var sPos = calculateScrollPos(this, Math.min(range.from.left, range.to.left), - Math.min(range.from.top, range.to.top) - range.margin, - Math.max(range.from.right, range.to.right), - Math.max(range.from.bottom, range.to.bottom) + range.margin) - this.scrollTo(sPos.scrollLeft, sPos.scrollTop) - } - }), - - setSize: methodOp(function(width, height) { - var this$1 = this; - - var interpret = function (val) { return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; } - if (width != null) { this.display.wrapper.style.width = interpret(width) } - if (height != null) { this.display.wrapper.style.height = interpret(height) } - if (this.options.lineWrapping) { clearLineMeasurementCache(this) } - var lineNo = this.display.viewFrom - this.doc.iter(lineNo, this.display.viewTo, function (line) { - if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) - { if (line.widgets[i].noHScroll) { regLineChange(this$1, lineNo, "widget"); break } } } - ++lineNo - }) - this.curOp.forceUpdate = true - signal(this, "refresh", this) - }), - - operation: function(f){return runInOp(this, f)}, - - refresh: methodOp(function() { - var oldHeight = this.display.cachedTextHeight - regChange(this) - this.curOp.forceUpdate = true - clearCaches(this) - this.scrollTo(this.doc.scrollLeft, this.doc.scrollTop) - updateGutterSpace(this) - if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5) - { estimateLineHeights(this) } - signal(this, "refresh", this) - }), - - swapDoc: methodOp(function(doc) { - var old = this.doc - old.cm = null - attachDoc(this, doc) - clearCaches(this) - this.display.input.reset() - this.scrollTo(doc.scrollLeft, doc.scrollTop) - this.curOp.forceScroll = true - signalLater(this, "swapDoc", this, old) - return old - }), - - getInputField: function(){return this.display.input.getField()}, - getWrapperElement: function(){return this.display.wrapper}, - getScrollerElement: function(){return this.display.scroller}, - getGutterElement: function(){return this.display.gutters} - } - eventMixin(CodeMirror) - - CodeMirror.registerHelper = function(type, name, value) { - if (!helpers.hasOwnProperty(type)) { helpers[type] = CodeMirror[type] = {_global: []} } - helpers[type][name] = value - } - CodeMirror.registerGlobalHelper = function(type, name, predicate, value) { - CodeMirror.registerHelper(type, name, value) - helpers[type]._global.push({pred: predicate, val: value}) - } -} - -// Used for horizontal relative motion. Dir is -1 or 1 (left or -// right), unit can be "char", "column" (like char, but doesn't -// cross line boundaries), "word" (across next word), or "group" (to -// the start of next group of word or non-word-non-whitespace -// chars). The visually param controls whether, in right-to-left -// text, direction 1 means to move towards the next index in the -// string, or towards the character to the right of the current -// position. The resulting position will have a hitSide=true -// property if it reached the end of the document. -function findPosH(doc, pos, dir, unit, visually) { - var line = pos.line, ch = pos.ch, origDir = dir - var lineObj = getLine(doc, line) - function findNextLine() { - var l = line + dir - if (l < doc.first || l >= doc.first + doc.size) { return false } - line = l - return lineObj = getLine(doc, l) - } - function moveOnce(boundToLine) { - var next = (visually ? moveVisually : moveLogically)(lineObj, ch, dir, true) - if (next == null) { - if (!boundToLine && findNextLine()) { - if (visually) { ch = (dir < 0 ? lineRight : lineLeft)(lineObj) } - else { ch = dir < 0 ? lineObj.text.length : 0 } - } else { return false } - } else { ch = next } - return true - } - - if (unit == "char") { - moveOnce() - } else if (unit == "column") { - moveOnce(true) - } else if (unit == "word" || unit == "group") { - var sawType = null, group = unit == "group" - var helper = doc.cm && doc.cm.getHelper(pos, "wordChars") - for (var first = true;; first = false) { - if (dir < 0 && !moveOnce(!first)) { break } - var cur = lineObj.text.charAt(ch) || "\n" - var type = isWordChar(cur, helper) ? "w" - : group && cur == "\n" ? "n" - : !group || /\s/.test(cur) ? null - : "p" - if (group && !first && !type) { type = "s" } - if (sawType && sawType != type) { - if (dir < 0) {dir = 1; moveOnce()} - break - } - - if (type) { sawType = type } - if (dir > 0 && !moveOnce(!first)) { break } - } - } - var result = skipAtomic(doc, Pos(line, ch), pos, origDir, true) - if (!cmp(pos, result)) { result.hitSide = true } - return result -} - -// For relative vertical movement. Dir may be -1 or 1. Unit can be -// "page" or "line". The resulting position will have a hitSide=true -// property if it reached the end of the document. -function findPosV(cm, pos, dir, unit) { - var doc = cm.doc, x = pos.left, y - if (unit == "page") { - var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight) - var moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3) - y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount - - } else if (unit == "line") { - y = dir > 0 ? pos.bottom + 3 : pos.top - 3 - } - var target - for (;;) { - target = coordsChar(cm, x, y) - if (!target.outside) { break } - if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break } - y += dir * 5 - } - return target -} - -// CONTENTEDITABLE INPUT STYLE - -var ContentEditableInput = function(cm) { - this.cm = cm - this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null - this.polling = new Delayed() - this.composing = null - this.gracePeriod = false - this.readDOMTimeout = null -}; - -ContentEditableInput.prototype.init = function (display) { - var this$1 = this; - - var input = this, cm = input.cm - var div = input.div = display.lineDiv - disableBrowserMagic(div, cm.options.spellcheck) - - on(div, "paste", function (e) { - if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } - // IE doesn't fire input events, so we schedule a read for the pasted content in this way - if (ie_version <= 11) { setTimeout(operation(cm, function () { - if (!input.pollContent()) { regChange(cm) } - }), 20) } - }) - - on(div, "compositionstart", function (e) { - this$1.composing = {data: e.data, done: false} - }) - on(div, "compositionupdate", function (e) { - if (!this$1.composing) { this$1.composing = {data: e.data, done: false} } - }) - on(div, "compositionend", function (e) { - if (this$1.composing) { - if (e.data != this$1.composing.data) { this$1.readFromDOMSoon() } - this$1.composing.done = true - } - }) - - on(div, "touchstart", function () { return input.forceCompositionEnd(); }) - - on(div, "input", function () { - if (!this$1.composing) { this$1.readFromDOMSoon() } - }) - - function onCopyCut(e) { - if (signalDOMEvent(cm, e)) { return } - if (cm.somethingSelected()) { - setLastCopied({lineWise: false, text: cm.getSelections()}) - if (e.type == "cut") { cm.replaceSelection("", null, "cut") } - } else if (!cm.options.lineWiseCopyCut) { - return - } else { - var ranges = copyableRanges(cm) - setLastCopied({lineWise: true, text: ranges.text}) - if (e.type == "cut") { - cm.operation(function () { - cm.setSelections(ranges.ranges, 0, sel_dontScroll) - cm.replaceSelection("", null, "cut") - }) - } - } - if (e.clipboardData) { - e.clipboardData.clearData() - var content = lastCopied.text.join("\n") - // iOS exposes the clipboard API, but seems to discard content inserted into it - e.clipboardData.setData("Text", content) - if (e.clipboardData.getData("Text") == content) { - e.preventDefault() - return - } - } - // Old-fashioned briefly-focus-a-textarea hack - var kludge = hiddenTextarea(), te = kludge.firstChild - cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild) - te.value = lastCopied.text.join("\n") - var hadFocus = document.activeElement - selectInput(te) - setTimeout(function () { - cm.display.lineSpace.removeChild(kludge) - hadFocus.focus() - if (hadFocus == div) { input.showPrimarySelection() } - }, 50) - } - on(div, "copy", onCopyCut) - on(div, "cut", onCopyCut) -}; - -ContentEditableInput.prototype.prepareSelection = function () { - var result = prepareSelection(this.cm, false) - result.focus = this.cm.state.focused - return result -}; - -ContentEditableInput.prototype.showSelection = function (info, takeFocus) { - if (!info || !this.cm.display.view.length) { return } - if (info.focus || takeFocus) { this.showPrimarySelection() } - this.showMultipleSelections(info) -}; - -ContentEditableInput.prototype.showPrimarySelection = function () { - var sel = window.getSelection(), prim = this.cm.doc.sel.primary() - var curAnchor = domToPos(this.cm, sel.anchorNode, sel.anchorOffset) - var curFocus = domToPos(this.cm, sel.focusNode, sel.focusOffset) - if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad && - cmp(minPos(curAnchor, curFocus), prim.from()) == 0 && - cmp(maxPos(curAnchor, curFocus), prim.to()) == 0) - { return } - - var start = posToDOM(this.cm, prim.from()) - var end = posToDOM(this.cm, prim.to()) - if (!start && !end) { return } - - var view = this.cm.display.view - var old = sel.rangeCount && sel.getRangeAt(0) - if (!start) { - start = {node: view[0].measure.map[2], offset: 0} - } else if (!end) { // FIXME dangerously hacky - var measure = view[view.length - 1].measure - var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map - end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]} - } - - var rng - try { rng = range(start.node, start.offset, end.offset, end.node) } - catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible - if (rng) { - if (!gecko && this.cm.state.focused) { - sel.collapse(start.node, start.offset) - if (!rng.collapsed) { - sel.removeAllRanges() - sel.addRange(rng) - } - } else { - sel.removeAllRanges() - sel.addRange(rng) - } - if (old && sel.anchorNode == null) { sel.addRange(old) } - else if (gecko) { this.startGracePeriod() } - } - this.rememberSelection() -}; - -ContentEditableInput.prototype.startGracePeriod = function () { - var this$1 = this; - - clearTimeout(this.gracePeriod) - this.gracePeriod = setTimeout(function () { - this$1.gracePeriod = false - if (this$1.selectionChanged()) - { this$1.cm.operation(function () { return this$1.cm.curOp.selectionChanged = true; }) } - }, 20) -}; - -ContentEditableInput.prototype.showMultipleSelections = function (info) { - removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors) - removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection) -}; - -ContentEditableInput.prototype.rememberSelection = function () { - var sel = window.getSelection() - this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset - this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset -}; - -ContentEditableInput.prototype.selectionInEditor = function () { - var sel = window.getSelection() - if (!sel.rangeCount) { return false } - var node = sel.getRangeAt(0).commonAncestorContainer - return contains(this.div, node) -}; - -ContentEditableInput.prototype.focus = function () { - if (this.cm.options.readOnly != "nocursor") { - if (!this.selectionInEditor()) - { this.showSelection(this.prepareSelection(), true) } - this.div.focus() - } -}; -ContentEditableInput.prototype.blur = function () { this.div.blur() }; -ContentEditableInput.prototype.getField = function () { return this.div }; - -ContentEditableInput.prototype.supportsTouch = function () { return true }; - -ContentEditableInput.prototype.receivedFocus = function () { - var input = this - if (this.selectionInEditor()) - { this.pollSelection() } - else - { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }) } - - function poll() { - if (input.cm.state.focused) { - input.pollSelection() - input.polling.set(input.cm.options.pollInterval, poll) - } - } - this.polling.set(this.cm.options.pollInterval, poll) -}; - -ContentEditableInput.prototype.selectionChanged = function () { - var sel = window.getSelection() - return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset || - sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset -}; - -ContentEditableInput.prototype.pollSelection = function () { - if (!this.composing && this.readDOMTimeout == null && !this.gracePeriod && this.selectionChanged()) { - var sel = window.getSelection(), cm = this.cm - this.rememberSelection() - var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset) - var head = domToPos(cm, sel.focusNode, sel.focusOffset) - if (anchor && head) { runInOp(cm, function () { - setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll) - if (anchor.bad || head.bad) { cm.curOp.selectionChanged = true } - }) } - } -}; - -ContentEditableInput.prototype.pollContent = function () { - if (this.readDOMTimeout != null) { - clearTimeout(this.readDOMTimeout) - this.readDOMTimeout = null - } - - var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary() - var from = sel.from(), to = sel.to() - if (from.ch == 0 && from.line > cm.firstLine()) - { from = Pos(from.line - 1, getLine(cm.doc, from.line - 1).length) } - if (to.ch == getLine(cm.doc, to.line).text.length && to.line < cm.lastLine()) - { to = Pos(to.line + 1, 0) } - if (from.line < display.viewFrom || to.line > display.viewTo - 1) { return false } - - var fromIndex, fromLine, fromNode - if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) { - fromLine = lineNo(display.view[0].line) - fromNode = display.view[0].node - } else { - fromLine = lineNo(display.view[fromIndex].line) - fromNode = display.view[fromIndex - 1].node.nextSibling - } - var toIndex = findViewIndex(cm, to.line) - var toLine, toNode - if (toIndex == display.view.length - 1) { - toLine = display.viewTo - 1 - toNode = display.lineDiv.lastChild - } else { - toLine = lineNo(display.view[toIndex + 1].line) - 1 - toNode = display.view[toIndex + 1].node.previousSibling - } - - if (!fromNode) { return false } - var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine)) - var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length)) - while (newText.length > 1 && oldText.length > 1) { - if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine-- } - else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++ } - else { break } - } - - var cutFront = 0, cutEnd = 0 - var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length) - while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront)) - { ++cutFront } - var newBot = lst(newText), oldBot = lst(oldText) - var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0), - oldBot.length - (oldText.length == 1 ? cutFront : 0)) - while (cutEnd < maxCutEnd && - newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) - { ++cutEnd } - - newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd).replace(/^\u200b+/, "") - newText[0] = newText[0].slice(cutFront).replace(/\u200b+$/, "") - - var chFrom = Pos(fromLine, cutFront) - var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0) - if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) { - replaceRange(cm.doc, newText, chFrom, chTo, "+input") - return true - } -}; - -ContentEditableInput.prototype.ensurePolled = function () { - this.forceCompositionEnd() -}; -ContentEditableInput.prototype.reset = function () { - this.forceCompositionEnd() -}; -ContentEditableInput.prototype.forceCompositionEnd = function () { - if (!this.composing) { return } - clearTimeout(this.readDOMTimeout) - this.composing = null - if (!this.pollContent()) { regChange(this.cm) } - this.div.blur() - this.div.focus() -}; -ContentEditableInput.prototype.readFromDOMSoon = function () { - var this$1 = this; - - if (this.readDOMTimeout != null) { return } - this.readDOMTimeout = setTimeout(function () { - this$1.readDOMTimeout = null - if (this$1.composing) { - if (this$1.composing.done) { this$1.composing = null } - else { return } - } - if (this$1.cm.isReadOnly() || !this$1.pollContent()) - { runInOp(this$1.cm, function () { return regChange(this$1.cm); }) } - }, 80) -}; - -ContentEditableInput.prototype.setUneditable = function (node) { - node.contentEditable = "false" -}; - -ContentEditableInput.prototype.onKeyPress = function (e) { - e.preventDefault() - if (!this.cm.isReadOnly()) - { operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0) } -}; - -ContentEditableInput.prototype.readOnlyChanged = function (val) { - this.div.contentEditable = String(val != "nocursor") -}; - -ContentEditableInput.prototype.onContextMenu = function () {}; -ContentEditableInput.prototype.resetPosition = function () {}; - -ContentEditableInput.prototype.needsContentAttribute = true - -function posToDOM(cm, pos) { - var view = findViewForLine(cm, pos.line) - if (!view || view.hidden) { return null } - var line = getLine(cm.doc, pos.line) - var info = mapFromLineView(view, line, pos.line) - - var order = getOrder(line), side = "left" - if (order) { - var partPos = getBidiPartAt(order, pos.ch) - side = partPos % 2 ? "right" : "left" - } - var result = nodeAndOffsetInLineMap(info.map, pos.ch, side) - result.offset = result.collapse == "right" ? result.end : result.start - return result -} - -function badPos(pos, bad) { if (bad) { pos.bad = true; } return pos } - -function domTextBetween(cm, from, to, fromLine, toLine) { - var text = "", closing = false, lineSep = cm.doc.lineSeparator() - function recognizeMarker(id) { return function (marker) { return marker.id == id; } } - function walk(node) { - if (node.nodeType == 1) { - var cmText = node.getAttribute("cm-text") - if (cmText != null) { - if (cmText == "") { text += node.textContent.replace(/\u200b/g, "") } - else { text += cmText } - return - } - var markerID = node.getAttribute("cm-marker"), range - if (markerID) { - var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID)) - if (found.length && (range = found[0].find())) - { text += getBetween(cm.doc, range.from, range.to).join(lineSep) } - return - } - if (node.getAttribute("contenteditable") == "false") { return } - for (var i = 0; i < node.childNodes.length; i++) - { walk(node.childNodes[i]) } - if (/^(pre|div|p)$/i.test(node.nodeName)) - { closing = true } - } else if (node.nodeType == 3) { - var val = node.nodeValue - if (!val) { return } - if (closing) { - text += lineSep - closing = false - } - text += val - } - } - for (;;) { - walk(from) - if (from == to) { break } - from = from.nextSibling - } - return text -} - -function domToPos(cm, node, offset) { - var lineNode - if (node == cm.display.lineDiv) { - lineNode = cm.display.lineDiv.childNodes[offset] - if (!lineNode) { return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true) } - node = null; offset = 0 - } else { - for (lineNode = node;; lineNode = lineNode.parentNode) { - if (!lineNode || lineNode == cm.display.lineDiv) { return null } - if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) { break } - } - } - for (var i = 0; i < cm.display.view.length; i++) { - var lineView = cm.display.view[i] - if (lineView.node == lineNode) - { return locateNodeInLineView(lineView, node, offset) } - } -} - -function locateNodeInLineView(lineView, node, offset) { - var wrapper = lineView.text.firstChild, bad = false - if (!node || !contains(wrapper, node)) { return badPos(Pos(lineNo(lineView.line), 0), true) } - if (node == wrapper) { - bad = true - node = wrapper.childNodes[offset] - offset = 0 - if (!node) { - var line = lineView.rest ? lst(lineView.rest) : lineView.line - return badPos(Pos(lineNo(line), line.text.length), bad) - } - } - - var textNode = node.nodeType == 3 ? node : null, topNode = node - if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) { - textNode = node.firstChild - if (offset) { offset = textNode.nodeValue.length } - } - while (topNode.parentNode != wrapper) { topNode = topNode.parentNode } - var measure = lineView.measure, maps = measure.maps - - function find(textNode, topNode, offset) { - for (var i = -1; i < (maps ? maps.length : 0); i++) { - var map = i < 0 ? measure.map : maps[i] - for (var j = 0; j < map.length; j += 3) { - var curNode = map[j + 2] - if (curNode == textNode || curNode == topNode) { - var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]) - var ch = map[j] + offset - if (offset < 0 || curNode != textNode) { ch = map[j + (offset ? 1 : 0)] } - return Pos(line, ch) - } - } - } - } - var found = find(textNode, topNode, offset) - if (found) { return badPos(found, bad) } - - // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems - for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) { - found = find(after, after.firstChild, 0) - if (found) - { return badPos(Pos(found.line, found.ch - dist), bad) } - else - { dist += after.textContent.length } - } - for (var before = topNode.previousSibling, dist$1 = offset; before; before = before.previousSibling) { - found = find(before, before.firstChild, -1) - if (found) - { return badPos(Pos(found.line, found.ch + dist$1), bad) } - else - { dist$1 += before.textContent.length } - } -} - -// TEXTAREA INPUT STYLE - -var TextareaInput = function(cm) { - this.cm = cm - // See input.poll and input.reset - this.prevInput = "" - - // Flag that indicates whether we expect input to appear real soon - // now (after some event like 'keypress' or 'input') and are - // polling intensively. - this.pollingFast = false - // Self-resetting timeout for the poller - this.polling = new Delayed() - // Tracks when input.reset has punted to just putting a short - // string into the textarea instead of the full selection. - this.inaccurateSelection = false - // Used to work around IE issue with selection being forgotten when focus moves away from textarea - this.hasSelection = false - this.composing = null -}; - -TextareaInput.prototype.init = function (display) { - var this$1 = this; - - var input = this, cm = this.cm - - // Wraps and hides input textarea - var div = this.wrapper = hiddenTextarea() - // The semihidden textarea that is focused when the editor is - // focused, and receives input. - var te = this.textarea = div.firstChild - display.wrapper.insertBefore(div, display.wrapper.firstChild) - - // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore) - if (ios) { te.style.width = "0px" } - - on(te, "input", function () { - if (ie && ie_version >= 9 && this$1.hasSelection) { this$1.hasSelection = null } - input.poll() - }) - - on(te, "paste", function (e) { - if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } - - cm.state.pasteIncoming = true - input.fastPoll() - }) - - function prepareCopyCut(e) { - if (signalDOMEvent(cm, e)) { return } - if (cm.somethingSelected()) { - setLastCopied({lineWise: false, text: cm.getSelections()}) - if (input.inaccurateSelection) { - input.prevInput = "" - input.inaccurateSelection = false - te.value = lastCopied.text.join("\n") - selectInput(te) - } - } else if (!cm.options.lineWiseCopyCut) { - return - } else { - var ranges = copyableRanges(cm) - setLastCopied({lineWise: true, text: ranges.text}) - if (e.type == "cut") { - cm.setSelections(ranges.ranges, null, sel_dontScroll) - } else { - input.prevInput = "" - te.value = ranges.text.join("\n") - selectInput(te) - } - } - if (e.type == "cut") { cm.state.cutIncoming = true } - } - on(te, "cut", prepareCopyCut) - on(te, "copy", prepareCopyCut) - - on(display.scroller, "paste", function (e) { - if (eventInWidget(display, e) || signalDOMEvent(cm, e)) { return } - cm.state.pasteIncoming = true - input.focus() - }) - - // Prevent normal selection in the editor (we handle our own) - on(display.lineSpace, "selectstart", function (e) { - if (!eventInWidget(display, e)) { e_preventDefault(e) } - }) - - on(te, "compositionstart", function () { - var start = cm.getCursor("from") - if (input.composing) { input.composing.range.clear() } - input.composing = { - start: start, - range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"}) - } - }) - on(te, "compositionend", function () { - if (input.composing) { - input.poll() - input.composing.range.clear() - input.composing = null - } - }) -}; - -TextareaInput.prototype.prepareSelection = function () { - // Redraw the selection and/or cursor - var cm = this.cm, display = cm.display, doc = cm.doc - var result = prepareSelection(cm) - - // Move the hidden textarea near the cursor to prevent scrolling artifacts - if (cm.options.moveInputWithCursor) { - var headPos = cursorCoords(cm, doc.sel.primary().head, "div") - var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect() - result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10, - headPos.top + lineOff.top - wrapOff.top)) - result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10, - headPos.left + lineOff.left - wrapOff.left)) - } - - return result -}; - -TextareaInput.prototype.showSelection = function (drawn) { - var cm = this.cm, display = cm.display - removeChildrenAndAdd(display.cursorDiv, drawn.cursors) - removeChildrenAndAdd(display.selectionDiv, drawn.selection) - if (drawn.teTop != null) { - this.wrapper.style.top = drawn.teTop + "px" - this.wrapper.style.left = drawn.teLeft + "px" - } -}; - -// Reset the input to correspond to the selection (or to be empty, -// when not typing and nothing is selected) -TextareaInput.prototype.reset = function (typing) { - if (this.contextMenuPending) { return } - var minimal, selected, cm = this.cm, doc = cm.doc - if (cm.somethingSelected()) { - this.prevInput = "" - var range = doc.sel.primary() - minimal = hasCopyEvent && - (range.to().line - range.from().line > 100 || (selected = cm.getSelection()).length > 1000) - var content = minimal ? "-" : selected || cm.getSelection() - this.textarea.value = content - if (cm.state.focused) { selectInput(this.textarea) } - if (ie && ie_version >= 9) { this.hasSelection = content } - } else if (!typing) { - this.prevInput = this.textarea.value = "" - if (ie && ie_version >= 9) { this.hasSelection = null } - } - this.inaccurateSelection = minimal -}; - -TextareaInput.prototype.getField = function () { return this.textarea }; - -TextareaInput.prototype.supportsTouch = function () { return false }; - -TextareaInput.prototype.focus = function () { - if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) { - try { this.textarea.focus() } - catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM - } -}; - -TextareaInput.prototype.blur = function () { this.textarea.blur() }; - -TextareaInput.prototype.resetPosition = function () { - this.wrapper.style.top = this.wrapper.style.left = 0 -}; - -TextareaInput.prototype.receivedFocus = function () { this.slowPoll() }; - -// Poll for input changes, using the normal rate of polling. This -// runs as long as the editor is focused. -TextareaInput.prototype.slowPoll = function () { - var this$1 = this; - - if (this.pollingFast) { return } - this.polling.set(this.cm.options.pollInterval, function () { - this$1.poll() - if (this$1.cm.state.focused) { this$1.slowPoll() } - }) -}; - -// When an event has just come in that is likely to add or change -// something in the input textarea, we poll faster, to ensure that -// the change appears on the screen quickly. -TextareaInput.prototype.fastPoll = function () { - var missed = false, input = this - input.pollingFast = true - function p() { - var changed = input.poll() - if (!changed && !missed) {missed = true; input.polling.set(60, p)} - else {input.pollingFast = false; input.slowPoll()} - } - input.polling.set(20, p) -}; - -// Read input from the textarea, and update the document to match. -// When something is selected, it is present in the textarea, and -// selected (unless it is huge, in which case a placeholder is -// used). When nothing is selected, the cursor sits after previously -// seen text (can be empty), which is stored in prevInput (we must -// not reset the textarea when typing, because that breaks IME). -TextareaInput.prototype.poll = function () { - var this$1 = this; - - var cm = this.cm, input = this.textarea, prevInput = this.prevInput - // Since this is called a *lot*, try to bail out as cheaply as - // possible when it is clear that nothing happened. hasSelection - // will be the case when there is a lot of text in the textarea, - // in which case reading its value would be expensive. - if (this.contextMenuPending || !cm.state.focused || - (hasSelection(input) && !prevInput && !this.composing) || - cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq) - { return false } - - var text = input.value - // If nothing changed, bail. - if (text == prevInput && !cm.somethingSelected()) { return false } - // Work around nonsensical selection resetting in IE9/10, and - // inexplicable appearance of private area unicode characters on - // some key combos in Mac (#2689). - if (ie && ie_version >= 9 && this.hasSelection === text || - mac && /[\uf700-\uf7ff]/.test(text)) { - cm.display.input.reset() - return false - } - - if (cm.doc.sel == cm.display.selForContextMenu) { - var first = text.charCodeAt(0) - if (first == 0x200b && !prevInput) { prevInput = "\u200b" } - if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo") } - } - // Find the part of the input that is actually new - var same = 0, l = Math.min(prevInput.length, text.length) - while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) { ++same } - - runInOp(cm, function () { - applyTextInput(cm, text.slice(same), prevInput.length - same, - null, this$1.composing ? "*compose" : null) - - // Don't leave long text in the textarea, since it makes further polling slow - if (text.length > 1000 || text.indexOf("\n") > -1) { input.value = this$1.prevInput = "" } - else { this$1.prevInput = text } - - if (this$1.composing) { - this$1.composing.range.clear() - this$1.composing.range = cm.markText(this$1.composing.start, cm.getCursor("to"), - {className: "CodeMirror-composing"}) - } - }) - return true -}; - -TextareaInput.prototype.ensurePolled = function () { - if (this.pollingFast && this.poll()) { this.pollingFast = false } -}; - -TextareaInput.prototype.onKeyPress = function () { - if (ie && ie_version >= 9) { this.hasSelection = null } - this.fastPoll() -}; - -TextareaInput.prototype.onContextMenu = function (e) { - var input = this, cm = input.cm, display = cm.display, te = input.textarea - var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop - if (!pos || presto) { return } // Opera is difficult. - - // Reset the current text selection only if the click is done outside of the selection - // and 'resetSelectionOnContextMenu' option is true. - var reset = cm.options.resetSelectionOnContextMenu - if (reset && cm.doc.sel.contains(pos) == -1) - { operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll) } - - var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText - input.wrapper.style.cssText = "position: absolute" - var wrapperBox = input.wrapper.getBoundingClientRect() - te.style.cssText = "position: absolute; width: 30px; height: 30px;\n top: " + (e.clientY - wrapperBox.top - 5) + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px;\n z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + ";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);" - var oldScrollY - if (webkit) { oldScrollY = window.scrollY } // Work around Chrome issue (#2712) - display.input.focus() - if (webkit) { window.scrollTo(null, oldScrollY) } - display.input.reset() - // Adds "Select all" to context menu in FF - if (!cm.somethingSelected()) { te.value = input.prevInput = " " } - input.contextMenuPending = true - display.selForContextMenu = cm.doc.sel - clearTimeout(display.detectingSelectAll) - - // Select-all will be greyed out if there's nothing to select, so - // this adds a zero-width space so that we can later check whether - // it got selected. - function prepareSelectAllHack() { - if (te.selectionStart != null) { - var selected = cm.somethingSelected() - var extval = "\u200b" + (selected ? te.value : "") - te.value = "\u21da" // Used to catch context-menu undo - te.value = extval - input.prevInput = selected ? "" : "\u200b" - te.selectionStart = 1; te.selectionEnd = extval.length - // Re-set this, in case some other handler touched the - // selection in the meantime. - display.selForContextMenu = cm.doc.sel - } - } - function rehide() { - input.contextMenuPending = false - input.wrapper.style.cssText = oldWrapperCSS - te.style.cssText = oldCSS - if (ie && ie_version < 9) { display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos) } - - // Try to detect the user choosing select-all - if (te.selectionStart != null) { - if (!ie || (ie && ie_version < 9)) { prepareSelectAllHack() } - var i = 0, poll = function () { - if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 && - te.selectionEnd > 0 && input.prevInput == "\u200b") - { operation(cm, selectAll)(cm) } - else if (i++ < 10) { display.detectingSelectAll = setTimeout(poll, 500) } - else { display.input.reset() } - } - display.detectingSelectAll = setTimeout(poll, 200) - } - } - - if (ie && ie_version >= 9) { prepareSelectAllHack() } - if (captureRightClick) { - e_stop(e) - var mouseup = function () { - off(window, "mouseup", mouseup) - setTimeout(rehide, 20) - } - on(window, "mouseup", mouseup) - } else { - setTimeout(rehide, 50) - } -}; - -TextareaInput.prototype.readOnlyChanged = function (val) { - if (!val) { this.reset() } -}; - -TextareaInput.prototype.setUneditable = function () {}; - -TextareaInput.prototype.needsContentAttribute = false - -function fromTextArea(textarea, options) { - options = options ? copyObj(options) : {} - options.value = textarea.value - if (!options.tabindex && textarea.tabIndex) - { options.tabindex = textarea.tabIndex } - if (!options.placeholder && textarea.placeholder) - { options.placeholder = textarea.placeholder } - // Set autofocus to true if this textarea is focused, or if it has - // autofocus and no other element is focused. - if (options.autofocus == null) { - var hasFocus = activeElt() - options.autofocus = hasFocus == textarea || - textarea.getAttribute("autofocus") != null && hasFocus == document.body - } - - function save() {textarea.value = cm.getValue()} - - var realSubmit - if (textarea.form) { - on(textarea.form, "submit", save) - // Deplorable hack to make the submit method do the right thing. - if (!options.leaveSubmitMethodAlone) { - var form = textarea.form - realSubmit = form.submit - try { - var wrappedSubmit = form.submit = function () { - save() - form.submit = realSubmit - form.submit() - form.submit = wrappedSubmit - } - } catch(e) {} - } - } - - options.finishInit = function (cm) { - cm.save = save - cm.getTextArea = function () { return textarea; } - cm.toTextArea = function () { - cm.toTextArea = isNaN // Prevent this from being ran twice - save() - textarea.parentNode.removeChild(cm.getWrapperElement()) - textarea.style.display = "" - if (textarea.form) { - off(textarea.form, "submit", save) - if (typeof textarea.form.submit == "function") - { textarea.form.submit = realSubmit } - } - } - } - - textarea.style.display = "none" - var cm = CodeMirror(function (node) { return textarea.parentNode.insertBefore(node, textarea.nextSibling); }, - options) - return cm -} - -function addLegacyProps(CodeMirror) { - CodeMirror.off = off - CodeMirror.on = on - CodeMirror.wheelEventPixels = wheelEventPixels - CodeMirror.Doc = Doc - CodeMirror.splitLines = splitLinesAuto - CodeMirror.countColumn = countColumn - CodeMirror.findColumn = findColumn - CodeMirror.isWordChar = isWordCharBasic - CodeMirror.Pass = Pass - CodeMirror.signal = signal - CodeMirror.Line = Line - CodeMirror.changeEnd = changeEnd - CodeMirror.scrollbarModel = scrollbarModel - CodeMirror.Pos = Pos - CodeMirror.cmpPos = cmp - CodeMirror.modes = modes - CodeMirror.mimeModes = mimeModes - CodeMirror.resolveMode = resolveMode - CodeMirror.getMode = getMode - CodeMirror.modeExtensions = modeExtensions - CodeMirror.extendMode = extendMode - CodeMirror.copyState = copyState - CodeMirror.startState = startState - CodeMirror.innerMode = innerMode - CodeMirror.commands = commands - CodeMirror.keyMap = keyMap - CodeMirror.keyName = keyName - CodeMirror.isModifierKey = isModifierKey - CodeMirror.lookupKey = lookupKey - CodeMirror.normalizeKeyMap = normalizeKeyMap - CodeMirror.StringStream = StringStream - CodeMirror.SharedTextMarker = SharedTextMarker - CodeMirror.TextMarker = TextMarker - CodeMirror.LineWidget = LineWidget - CodeMirror.e_preventDefault = e_preventDefault - CodeMirror.e_stopPropagation = e_stopPropagation - CodeMirror.e_stop = e_stop - CodeMirror.addClass = addClass - CodeMirror.contains = contains - CodeMirror.rmClass = rmClass - CodeMirror.keyNames = keyNames -} - -// EDITOR CONSTRUCTOR - -defineOptions(CodeMirror) - -addEditorMethods(CodeMirror) - -// Set up methods on CodeMirror's prototype to redirect to the editor's document. -var dontDelegate = "iter insert remove copy getEditor constructor".split(" ") -for (var prop in Doc.prototype) { if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0) - { CodeMirror.prototype[prop] = (function(method) { - return function() {return method.apply(this.doc, arguments)} - })(Doc.prototype[prop]) } } - -eventMixin(Doc) - -// INPUT HANDLING - -CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput} - -// MODE DEFINITION AND QUERYING - -// Extra arguments are stored as the mode's dependencies, which is -// used by (legacy) mechanisms like loadmode.js to automatically -// load a mode. (Preferred mechanism is the require/define calls.) -CodeMirror.defineMode = function(name/*, mode, …*/) { - if (!CodeMirror.defaults.mode && name != "null") { CodeMirror.defaults.mode = name } - defineMode.apply(this, arguments) -} - -CodeMirror.defineMIME = defineMIME - -// Minimal default mode. -CodeMirror.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); }) -CodeMirror.defineMIME("text/plain", "null") - -// EXTENSIONS - -CodeMirror.defineExtension = function (name, func) { - CodeMirror.prototype[name] = func -} -CodeMirror.defineDocExtension = function (name, func) { - Doc.prototype[name] = func -} - -CodeMirror.fromTextArea = fromTextArea - -addLegacyProps(CodeMirror) - -CodeMirror.version = "5.23.0" - -return CodeMirror; - -}))); \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/codemirror/mode/apl/apl.js b/backend/_pv_1_3_5/static/codemirror/mode/apl/apl.js deleted file mode 100755 index caafe4e91..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/apl/apl.js +++ /dev/null @@ -1,174 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("apl", function() { - var builtInOps = { - ".": "innerProduct", - "\\": "scan", - "/": "reduce", - "⌿": "reduce1Axis", - "⍀": "scan1Axis", - "¨": "each", - "⍣": "power" - }; - var builtInFuncs = { - "+": ["conjugate", "add"], - "−": ["negate", "subtract"], - "×": ["signOf", "multiply"], - "÷": ["reciprocal", "divide"], - "⌈": ["ceiling", "greaterOf"], - "⌊": ["floor", "lesserOf"], - "∣": ["absolute", "residue"], - "⍳": ["indexGenerate", "indexOf"], - "?": ["roll", "deal"], - "⋆": ["exponentiate", "toThePowerOf"], - "⍟": ["naturalLog", "logToTheBase"], - "○": ["piTimes", "circularFuncs"], - "!": ["factorial", "binomial"], - "⌹": ["matrixInverse", "matrixDivide"], - "<": [null, "lessThan"], - "≤": [null, "lessThanOrEqual"], - "=": [null, "equals"], - ">": [null, "greaterThan"], - "≥": [null, "greaterThanOrEqual"], - "≠": [null, "notEqual"], - "≡": ["depth", "match"], - "≢": [null, "notMatch"], - "∈": ["enlist", "membership"], - "⍷": [null, "find"], - "∪": ["unique", "union"], - "∩": [null, "intersection"], - "∼": ["not", "without"], - "∨": [null, "or"], - "∧": [null, "and"], - "⍱": [null, "nor"], - "⍲": [null, "nand"], - "⍴": ["shapeOf", "reshape"], - ",": ["ravel", "catenate"], - "⍪": [null, "firstAxisCatenate"], - "⌽": ["reverse", "rotate"], - "⊖": ["axis1Reverse", "axis1Rotate"], - "⍉": ["transpose", null], - "↑": ["first", "take"], - "↓": [null, "drop"], - "⊂": ["enclose", "partitionWithAxis"], - "⊃": ["diclose", "pick"], - "⌷": [null, "index"], - "⍋": ["gradeUp", null], - "⍒": ["gradeDown", null], - "⊤": ["encode", null], - "⊥": ["decode", null], - "⍕": ["format", "formatByExample"], - "⍎": ["execute", null], - "⊣": ["stop", "left"], - "⊢": ["pass", "right"] - }; - - var isOperator = /[\.\/⌿⍀¨⍣]/; - var isNiladic = /⍬/; - var isFunction = /[\+−×÷⌈⌊∣⍳\?⋆⍟○!⌹<≤=>≥≠≡≢∈⍷∪∩∼∨∧⍱⍲⍴,⍪⌽⊖⍉↑↓⊂⊃⌷⍋⍒⊤⊥⍕⍎⊣⊢]/; - var isArrow = /←/; - var isComment = /[⍝#].*$/; - - var stringEater = function(type) { - var prev; - prev = false; - return function(c) { - prev = c; - if (c === type) { - return prev === "\\"; - } - return true; - }; - }; - return { - startState: function() { - return { - prev: false, - func: false, - op: false, - string: false, - escape: false - }; - }, - token: function(stream, state) { - var ch, funcName; - if (stream.eatSpace()) { - return null; - } - ch = stream.next(); - if (ch === '"' || ch === "'") { - stream.eatWhile(stringEater(ch)); - stream.next(); - state.prev = true; - return "string"; - } - if (/[\[{\(]/.test(ch)) { - state.prev = false; - return null; - } - if (/[\]}\)]/.test(ch)) { - state.prev = true; - return null; - } - if (isNiladic.test(ch)) { - state.prev = false; - return "niladic"; - } - if (/[¯\d]/.test(ch)) { - if (state.func) { - state.func = false; - state.prev = false; - } else { - state.prev = true; - } - stream.eatWhile(/[\w\.]/); - return "number"; - } - if (isOperator.test(ch)) { - return "operator apl-" + builtInOps[ch]; - } - if (isArrow.test(ch)) { - return "apl-arrow"; - } - if (isFunction.test(ch)) { - funcName = "apl-"; - if (builtInFuncs[ch] != null) { - if (state.prev) { - funcName += builtInFuncs[ch][1]; - } else { - funcName += builtInFuncs[ch][0]; - } - } - state.func = true; - state.prev = false; - return "function " + funcName; - } - if (isComment.test(ch)) { - stream.skipToEnd(); - return "comment"; - } - if (ch === "∘" && stream.peek() === ".") { - stream.next(); - return "function jot-dot"; - } - stream.eatWhile(/[\w\$_]/); - state.prev = true; - return "keyword"; - } - }; -}); - -CodeMirror.defineMIME("text/apl", "apl"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/apl/index.html b/backend/_pv_1_3_5/static/codemirror/mode/apl/index.html deleted file mode 100755 index 53dda6b58..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/apl/index.html +++ /dev/null @@ -1,72 +0,0 @@ - - -CodeMirror: APL mode - - - - - - - - - - -
    -

    APL mode

    -
    - - - -

    Simple mode that tries to handle APL as well as it can.

    -

    It attempts to label functions/operators based upon - monadic/dyadic usage (but this is far from fully fleshed out). - This means there are meaningful classnames so hover states can - have popups etc.

    - -

    MIME types defined: text/apl (APL code)

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/asciiarmor/asciiarmor.js b/backend/_pv_1_3_5/static/codemirror/mode/asciiarmor/asciiarmor.js deleted file mode 100755 index d83090376..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/asciiarmor/asciiarmor.js +++ /dev/null @@ -1,73 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - function errorIfNotEmpty(stream) { - var nonWS = stream.match(/^\s*\S/); - stream.skipToEnd(); - return nonWS ? "error" : null; - } - - CodeMirror.defineMode("asciiarmor", function() { - return { - token: function(stream, state) { - var m; - if (state.state == "top") { - if (stream.sol() && (m = stream.match(/^-----BEGIN (.*)?-----\s*$/))) { - state.state = "headers"; - state.type = m[1]; - return "tag"; - } - return errorIfNotEmpty(stream); - } else if (state.state == "headers") { - if (stream.sol() && stream.match(/^\w+:/)) { - state.state = "header"; - return "atom"; - } else { - var result = errorIfNotEmpty(stream); - if (result) state.state = "body"; - return result; - } - } else if (state.state == "header") { - stream.skipToEnd(); - state.state = "headers"; - return "string"; - } else if (state.state == "body") { - if (stream.sol() && (m = stream.match(/^-----END (.*)?-----\s*$/))) { - if (m[1] != state.type) return "error"; - state.state = "end"; - return "tag"; - } else { - if (stream.eatWhile(/[A-Za-z0-9+\/=]/)) { - return null; - } else { - stream.next(); - return "error"; - } - } - } else if (state.state == "end") { - return errorIfNotEmpty(stream); - } - }, - blankLine: function(state) { - if (state.state == "headers") state.state = "body"; - }, - startState: function() { - return {state: "top", type: null}; - } - }; - }); - - CodeMirror.defineMIME("application/pgp", "asciiarmor"); - CodeMirror.defineMIME("application/pgp-keys", "asciiarmor"); - CodeMirror.defineMIME("application/pgp-signature", "asciiarmor"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/asciiarmor/index.html b/backend/_pv_1_3_5/static/codemirror/mode/asciiarmor/index.html deleted file mode 100755 index 8ba1b5c76..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/asciiarmor/index.html +++ /dev/null @@ -1,46 +0,0 @@ - - -CodeMirror: ASCII Armor (PGP) mode - - - - - - - - - -
    -

    ASCII Armor (PGP) mode

    -
    - - - -

    MIME types -defined: application/pgp, application/pgp-keys, application/pgp-signature

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/asn.1/asn.1.js b/backend/_pv_1_3_5/static/codemirror/mode/asn.1/asn.1.js deleted file mode 100755 index 9600247ea..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/asn.1/asn.1.js +++ /dev/null @@ -1,204 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("asn.1", function(config, parserConfig) { - var indentUnit = config.indentUnit, - keywords = parserConfig.keywords || {}, - cmipVerbs = parserConfig.cmipVerbs || {}, - compareTypes = parserConfig.compareTypes || {}, - status = parserConfig.status || {}, - tags = parserConfig.tags || {}, - storage = parserConfig.storage || {}, - modifier = parserConfig.modifier || {}, - accessTypes = parserConfig.accessTypes|| {}, - multiLineStrings = parserConfig.multiLineStrings, - indentStatements = parserConfig.indentStatements !== false; - var isOperatorChar = /[\|\^]/; - var curPunc; - - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"' || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - if (/[\[\]\(\){}:=,;]/.test(ch)) { - curPunc = ch; - return "punctuation"; - } - if (ch == "-"){ - if (stream.eat("-")) { - stream.skipToEnd(); - return "comment"; - } - } - if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - - stream.eatWhile(/[\w\-]/); - var cur = stream.current(); - if (keywords.propertyIsEnumerable(cur)) return "keyword"; - if (cmipVerbs.propertyIsEnumerable(cur)) return "variable cmipVerbs"; - if (compareTypes.propertyIsEnumerable(cur)) return "atom compareTypes"; - if (status.propertyIsEnumerable(cur)) return "comment status"; - if (tags.propertyIsEnumerable(cur)) return "variable-3 tags"; - if (storage.propertyIsEnumerable(cur)) return "builtin storage"; - if (modifier.propertyIsEnumerable(cur)) return "string-2 modifier"; - if (accessTypes.propertyIsEnumerable(cur)) return "atom accessTypes"; - - return "variable"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped){ - var afterNext = stream.peek(); - //look if the character if the quote is like the B in '10100010'B - if (afterNext){ - afterNext = afterNext.toLowerCase(); - if(afterNext == "b" || afterNext == "h" || afterNext == "o") - stream.next(); - } - end = true; break; - } - escaped = !escaped && next == "\\"; - } - if (end || !(escaped || multiLineStrings)) - state.tokenize = null; - return "string"; - }; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - function pushContext(state, col, type) { - var indent = state.indented; - if (state.context && state.context.type == "statement") - indent = state.context.indented; - return state.context = new Context(indent, col, type, null, state.context); - } - function popContext(state) { - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") - state.indented = state.context.indented; - return state.context = state.context.prev; - } - - //Interface - return { - startState: function(basecolumn) { - return { - tokenize: null, - context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), - indented: 0, - startOfLine: true - }; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - } - if (stream.eatSpace()) return null; - curPunc = null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment") return style; - if (ctx.align == null) ctx.align = true; - - if ((curPunc == ";" || curPunc == ":" || curPunc == ",") - && ctx.type == "statement"){ - popContext(state); - } - else if (curPunc == "{") pushContext(state, stream.column(), "}"); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == "}") { - while (ctx.type == "statement") ctx = popContext(state); - if (ctx.type == "}") ctx = popContext(state); - while (ctx.type == "statement") ctx = popContext(state); - } - else if (curPunc == ctx.type) popContext(state); - else if (indentStatements && (((ctx.type == "}" || ctx.type == "top") - && curPunc != ';') || (ctx.type == "statement" - && curPunc == "newstatement"))) - pushContext(state, stream.column(), "statement"); - - state.startOfLine = false; - return style; - }, - - electricChars: "{}", - lineComment: "--", - fold: "brace" - }; - }); - - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - CodeMirror.defineMIME("text/x-ttcn-asn", { - name: "asn.1", - keywords: words("DEFINITIONS OBJECTS IF DERIVED INFORMATION ACTION" + - " REPLY ANY NAMED CHARACTERIZED BEHAVIOUR REGISTERED" + - " WITH AS IDENTIFIED CONSTRAINED BY PRESENT BEGIN" + - " IMPORTS FROM UNITS SYNTAX MIN-ACCESS MAX-ACCESS" + - " MINACCESS MAXACCESS REVISION STATUS DESCRIPTION" + - " SEQUENCE SET COMPONENTS OF CHOICE DistinguishedName" + - " ENUMERATED SIZE MODULE END INDEX AUGMENTS EXTENSIBILITY" + - " IMPLIED EXPORTS"), - cmipVerbs: words("ACTIONS ADD GET NOTIFICATIONS REPLACE REMOVE"), - compareTypes: words("OPTIONAL DEFAULT MANAGED MODULE-TYPE MODULE_IDENTITY" + - " MODULE-COMPLIANCE OBJECT-TYPE OBJECT-IDENTITY" + - " OBJECT-COMPLIANCE MODE CONFIRMED CONDITIONAL" + - " SUBORDINATE SUPERIOR CLASS TRUE FALSE NULL" + - " TEXTUAL-CONVENTION"), - status: words("current deprecated mandatory obsolete"), - tags: words("APPLICATION AUTOMATIC EXPLICIT IMPLICIT PRIVATE TAGS" + - " UNIVERSAL"), - storage: words("BOOLEAN INTEGER OBJECT IDENTIFIER BIT OCTET STRING" + - " UTCTime InterfaceIndex IANAifType CMIP-Attribute" + - " REAL PACKAGE PACKAGES IpAddress PhysAddress" + - " NetworkAddress BITS BMPString TimeStamp TimeTicks" + - " TruthValue RowStatus DisplayString GeneralString" + - " GraphicString IA5String NumericString" + - " PrintableString SnmpAdminAtring TeletexString" + - " UTF8String VideotexString VisibleString StringStore" + - " ISO646String T61String UniversalString Unsigned32" + - " Integer32 Gauge Gauge32 Counter Counter32 Counter64"), - modifier: words("ATTRIBUTE ATTRIBUTES MANDATORY-GROUP MANDATORY-GROUPS" + - " GROUP GROUPS ELEMENTS EQUALITY ORDERING SUBSTRINGS" + - " DEFINED"), - accessTypes: words("not-accessible accessible-for-notify read-only" + - " read-create read-write"), - multiLineStrings: true - }); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/asn.1/index.html b/backend/_pv_1_3_5/static/codemirror/mode/asn.1/index.html deleted file mode 100755 index 699fd4473..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/asn.1/index.html +++ /dev/null @@ -1,77 +0,0 @@ - - -CodeMirror: ASN.1 mode - - - - - - - - -
    -

    ASN.1 example

    -
    - -
    - - -
    -

    Language: Abstract Syntax Notation One - (ASN.1) -

    -

    MIME types defined: text/x-ttcn-asn

    - -
    -

    The development of this mode has been sponsored by Ericsson - .

    -

    Coded by Asmelash Tsegay Gebretsadkan

    -
    - diff --git a/backend/_pv_1_3_5/static/codemirror/mode/asterisk/asterisk.js b/backend/_pv_1_3_5/static/codemirror/mode/asterisk/asterisk.js deleted file mode 100755 index b7ebfc5ad..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/asterisk/asterisk.js +++ /dev/null @@ -1,196 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/* - * ===================================================================================== - * - * Filename: mode/asterisk/asterisk.js - * - * Description: CodeMirror mode for Asterisk dialplan - * - * Created: 05/17/2012 09:20:25 PM - * Revision: none - * - * Author: Stas Kobzar (stas@modulis.ca), - * Company: Modulis.ca Inc. - * - * ===================================================================================== - */ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("asterisk", function() { - var atoms = ["exten", "same", "include","ignorepat","switch"], - dpcmd = ["#include","#exec"], - apps = [ - "addqueuemember","adsiprog","aelsub","agentlogin","agentmonitoroutgoing","agi", - "alarmreceiver","amd","answer","authenticate","background","backgrounddetect", - "bridge","busy","callcompletioncancel","callcompletionrequest","celgenuserevent", - "changemonitor","chanisavail","channelredirect","chanspy","clearhash","confbridge", - "congestion","continuewhile","controlplayback","dahdiacceptr2call","dahdibarge", - "dahdiras","dahdiscan","dahdisendcallreroutingfacility","dahdisendkeypadfacility", - "datetime","dbdel","dbdeltree","deadagi","dial","dictate","directory","disa", - "dumpchan","eagi","echo","endwhile","exec","execif","execiftime","exitwhile","extenspy", - "externalivr","festival","flash","followme","forkcdr","getcpeid","gosub","gosubif", - "goto","gotoif","gotoiftime","hangup","iax2provision","ices","importvar","incomplete", - "ivrdemo","jabberjoin","jabberleave","jabbersend","jabbersendgroup","jabberstatus", - "jack","log","macro","macroexclusive","macroexit","macroif","mailboxexists","meetme", - "meetmeadmin","meetmechanneladmin","meetmecount","milliwatt","minivmaccmess","minivmdelete", - "minivmgreet","minivmmwi","minivmnotify","minivmrecord","mixmonitor","monitor","morsecode", - "mp3player","mset","musiconhold","nbscat","nocdr","noop","odbc","odbc","odbcfinish", - "originate","ospauth","ospfinish","osplookup","ospnext","page","park","parkandannounce", - "parkedcall","pausemonitor","pausequeuemember","pickup","pickupchan","playback","playtones", - "privacymanager","proceeding","progress","queue","queuelog","raiseexception","read","readexten", - "readfile","receivefax","receivefax","receivefax","record","removequeuemember", - "resetcdr","retrydial","return","ringing","sayalpha","saycountedadj","saycountednoun", - "saycountpl","saydigits","saynumber","sayphonetic","sayunixtime","senddtmf","sendfax", - "sendfax","sendfax","sendimage","sendtext","sendurl","set","setamaflags", - "setcallerpres","setmusiconhold","sipaddheader","sipdtmfmode","sipremoveheader","skel", - "slastation","slatrunk","sms","softhangup","speechactivategrammar","speechbackground", - "speechcreate","speechdeactivategrammar","speechdestroy","speechloadgrammar","speechprocessingsound", - "speechstart","speechunloadgrammar","stackpop","startmusiconhold","stopmixmonitor","stopmonitor", - "stopmusiconhold","stopplaytones","system","testclient","testserver","transfer","tryexec", - "trysystem","unpausemonitor","unpausequeuemember","userevent","verbose","vmauthenticate", - "vmsayname","voicemail","voicemailmain","wait","waitexten","waitfornoise","waitforring", - "waitforsilence","waitmusiconhold","waituntil","while","zapateller" - ]; - - function basicToken(stream,state){ - var cur = ''; - var ch = stream.next(); - // comment - if(ch == ";") { - stream.skipToEnd(); - return "comment"; - } - // context - if(ch == '[') { - stream.skipTo(']'); - stream.eat(']'); - return "header"; - } - // string - if(ch == '"') { - stream.skipTo('"'); - return "string"; - } - if(ch == "'") { - stream.skipTo("'"); - return "string-2"; - } - // dialplan commands - if(ch == '#') { - stream.eatWhile(/\w/); - cur = stream.current(); - if(dpcmd.indexOf(cur) !== -1) { - stream.skipToEnd(); - return "strong"; - } - } - // application args - if(ch == '$'){ - var ch1 = stream.peek(); - if(ch1 == '{'){ - stream.skipTo('}'); - stream.eat('}'); - return "variable-3"; - } - } - // extension - stream.eatWhile(/\w/); - cur = stream.current(); - if(atoms.indexOf(cur) !== -1) { - state.extenStart = true; - switch(cur) { - case 'same': state.extenSame = true; break; - case 'include': - case 'switch': - case 'ignorepat': - state.extenInclude = true;break; - default:break; - } - return "atom"; - } - } - - return { - startState: function() { - return { - extenStart: false, - extenSame: false, - extenInclude: false, - extenExten: false, - extenPriority: false, - extenApplication: false - }; - }, - token: function(stream, state) { - - var cur = ''; - if(stream.eatSpace()) return null; - // extension started - if(state.extenStart){ - stream.eatWhile(/[^\s]/); - cur = stream.current(); - if(/^=>?$/.test(cur)){ - state.extenExten = true; - state.extenStart = false; - return "strong"; - } else { - state.extenStart = false; - stream.skipToEnd(); - return "error"; - } - } else if(state.extenExten) { - // set exten and priority - state.extenExten = false; - state.extenPriority = true; - stream.eatWhile(/[^,]/); - if(state.extenInclude) { - stream.skipToEnd(); - state.extenPriority = false; - state.extenInclude = false; - } - if(state.extenSame) { - state.extenPriority = false; - state.extenSame = false; - state.extenApplication = true; - } - return "tag"; - } else if(state.extenPriority) { - state.extenPriority = false; - state.extenApplication = true; - stream.next(); // get comma - if(state.extenSame) return null; - stream.eatWhile(/[^,]/); - return "number"; - } else if(state.extenApplication) { - stream.eatWhile(/,/); - cur = stream.current(); - if(cur === ',') return null; - stream.eatWhile(/\w/); - cur = stream.current().toLowerCase(); - state.extenApplication = false; - if(apps.indexOf(cur) !== -1){ - return "def strong"; - } - } else{ - return basicToken(stream,state); - } - - return null; - } - }; -}); - -CodeMirror.defineMIME("text/x-asterisk", "asterisk"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/asterisk/index.html b/backend/_pv_1_3_5/static/codemirror/mode/asterisk/index.html deleted file mode 100755 index 257bd3987..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/asterisk/index.html +++ /dev/null @@ -1,154 +0,0 @@ - - -CodeMirror: Asterisk dialplan mode - - - - - - - - - -
    -

    Asterisk dialplan mode

    -
    - - -

    MIME types defined: text/x-asterisk.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/brainfuck/brainfuck.js b/backend/_pv_1_3_5/static/codemirror/mode/brainfuck/brainfuck.js deleted file mode 100755 index 3becf2a5a..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/brainfuck/brainfuck.js +++ /dev/null @@ -1,85 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Brainfuck mode created by Michael Kaminsky https://github.com/mkaminsky11 - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") - mod(require("../../lib/codemirror")) - else if (typeof define == "function" && define.amd) - define(["../../lib/codemirror"], mod) - else - mod(CodeMirror) -})(function(CodeMirror) { - "use strict" - var reserve = "><+-.,[]".split(""); - /* - comments can be either: - placed behind lines - - +++ this is a comment - - where reserved characters cannot be used - or in a loop - [ - this is ok to use [ ] and stuff - ] - or preceded by # - */ - CodeMirror.defineMode("brainfuck", function() { - return { - startState: function() { - return { - commentLine: false, - left: 0, - right: 0, - commentLoop: false - } - }, - token: function(stream, state) { - if (stream.eatSpace()) return null - if(stream.sol()){ - state.commentLine = false; - } - var ch = stream.next().toString(); - if(reserve.indexOf(ch) !== -1){ - if(state.commentLine === true){ - if(stream.eol()){ - state.commentLine = false; - } - return "comment"; - } - if(ch === "]" || ch === "["){ - if(ch === "["){ - state.left++; - } - else{ - state.right++; - } - return "bracket"; - } - else if(ch === "+" || ch === "-"){ - return "keyword"; - } - else if(ch === "<" || ch === ">"){ - return "atom"; - } - else if(ch === "." || ch === ","){ - return "def"; - } - } - else{ - state.commentLine = true; - if(stream.eol()){ - state.commentLine = false; - } - return "comment"; - } - if(stream.eol()){ - state.commentLine = false; - } - } - }; - }); -CodeMirror.defineMIME("text/x-brainfuck","brainfuck") -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/brainfuck/index.html b/backend/_pv_1_3_5/static/codemirror/mode/brainfuck/index.html deleted file mode 100755 index 6048fc241..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/brainfuck/index.html +++ /dev/null @@ -1,85 +0,0 @@ - - -CodeMirror: Brainfuck mode - - - - - - - - - - -
    -

    Brainfuck mode

    -
    - - - -

    A mode for Brainfuck

    - -

    MIME types defined: text/x-brainfuck

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/clike/clike.js b/backend/_pv_1_3_5/static/codemirror/mode/clike/clike.js deleted file mode 100755 index cad2d5145..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/clike/clike.js +++ /dev/null @@ -1,785 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -function Context(indented, column, type, info, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.info = info; - this.align = align; - this.prev = prev; -} -function pushContext(state, col, type, info) { - var indent = state.indented; - if (state.context && state.context.type == "statement" && type != "statement") - indent = state.context.indented; - return state.context = new Context(indent, col, type, info, null, state.context); -} -function popContext(state) { - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") - state.indented = state.context.indented; - return state.context = state.context.prev; -} - -function typeBefore(stream, state, pos) { - if (state.prevToken == "variable" || state.prevToken == "variable-3") return true; - if (/\S(?:[^- ]>|[*\]])\s*$|\*$/.test(stream.string.slice(0, pos))) return true; - if (state.typeAtEndOfLine && stream.column() == stream.indentation()) return true; -} - -function isTopScope(context) { - for (;;) { - if (!context || context.type == "top") return true; - if (context.type == "}" && context.prev.info != "namespace") return false; - context = context.prev; - } -} - -CodeMirror.defineMode("clike", function(config, parserConfig) { - var indentUnit = config.indentUnit, - statementIndentUnit = parserConfig.statementIndentUnit || indentUnit, - dontAlignCalls = parserConfig.dontAlignCalls, - keywords = parserConfig.keywords || {}, - types = parserConfig.types || {}, - builtin = parserConfig.builtin || {}, - blockKeywords = parserConfig.blockKeywords || {}, - defKeywords = parserConfig.defKeywords || {}, - atoms = parserConfig.atoms || {}, - hooks = parserConfig.hooks || {}, - multiLineStrings = parserConfig.multiLineStrings, - indentStatements = parserConfig.indentStatements !== false, - indentSwitch = parserConfig.indentSwitch !== false, - namespaceSeparator = parserConfig.namespaceSeparator, - isPunctuationChar = parserConfig.isPunctuationChar || /[\[\]{}\(\),;\:\.]/, - numberStart = parserConfig.numberStart || /[\d\.]/, - number = parserConfig.number || /^(?:0x[a-f\d]+|0b[01]+|(?:\d+\.?\d*|\.\d+)(?:e[-+]?\d+)?)(u|ll?|l|f)?/i, - isOperatorChar = parserConfig.isOperatorChar || /[+\-*&%=<>!?|\/]/; - - var curPunc, isDefKeyword; - - function tokenBase(stream, state) { - var ch = stream.next(); - if (hooks[ch]) { - var result = hooks[ch](stream, state); - if (result !== false) return result; - } - if (ch == '"' || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - if (isPunctuationChar.test(ch)) { - curPunc = ch; - return null; - } - if (numberStart.test(ch)) { - stream.backUp(1) - if (stream.match(number)) return "number" - stream.next() - } - if (ch == "/") { - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - } - if (isOperatorChar.test(ch)) { - while (!stream.match(/^\/[\/*]/, false) && stream.eat(isOperatorChar)) {} - return "operator"; - } - stream.eatWhile(/[\w\$_\xa1-\uffff]/); - if (namespaceSeparator) while (stream.match(namespaceSeparator)) - stream.eatWhile(/[\w\$_\xa1-\uffff]/); - - var cur = stream.current(); - if (contains(keywords, cur)) { - if (contains(blockKeywords, cur)) curPunc = "newstatement"; - if (contains(defKeywords, cur)) isDefKeyword = true; - return "keyword"; - } - if (contains(types, cur)) return "variable-3"; - if (contains(builtin, cur)) { - if (contains(blockKeywords, cur)) curPunc = "newstatement"; - return "builtin"; - } - if (contains(atoms, cur)) return "atom"; - return "variable"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) {end = true; break;} - escaped = !escaped && next == "\\"; - } - if (end || !(escaped || multiLineStrings)) - state.tokenize = null; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = null; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function maybeEOL(stream, state) { - if (parserConfig.typeFirstDefinitions && stream.eol() && isTopScope(state.context)) - state.typeAtEndOfLine = typeBefore(stream, state, stream.pos) - } - - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: null, - context: new Context((basecolumn || 0) - indentUnit, 0, "top", null, false), - indented: 0, - startOfLine: true, - prevToken: null - }; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - } - if (stream.eatSpace()) { maybeEOL(stream, state); return null; } - curPunc = isDefKeyword = null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment" || style == "meta") return style; - if (ctx.align == null) ctx.align = true; - - if (curPunc == ";" || curPunc == ":" || (curPunc == "," && stream.match(/^\s*(?:\/\/.*)?$/, false))) - while (state.context.type == "statement") popContext(state); - else if (curPunc == "{") pushContext(state, stream.column(), "}"); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == "}") { - while (ctx.type == "statement") ctx = popContext(state); - if (ctx.type == "}") ctx = popContext(state); - while (ctx.type == "statement") ctx = popContext(state); - } - else if (curPunc == ctx.type) popContext(state); - else if (indentStatements && - (((ctx.type == "}" || ctx.type == "top") && curPunc != ";") || - (ctx.type == "statement" && curPunc == "newstatement"))) { - pushContext(state, stream.column(), "statement", stream.current()); - } - - if (style == "variable" && - ((state.prevToken == "def" || - (parserConfig.typeFirstDefinitions && typeBefore(stream, state, stream.start) && - isTopScope(state.context) && stream.match(/^\s*\(/, false))))) - style = "def"; - - if (hooks.token) { - var result = hooks.token(stream, state, style); - if (result !== undefined) style = result; - } - - if (style == "def" && parserConfig.styleDefs === false) style = "variable"; - - state.startOfLine = false; - state.prevToken = isDefKeyword ? "def" : style || curPunc; - maybeEOL(stream, state); - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase && state.tokenize != null || state.typeAtEndOfLine) return CodeMirror.Pass; - var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); - if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev; - if (parserConfig.dontIndentStatements) - while (ctx.type == "statement" && parserConfig.dontIndentStatements.test(ctx.info)) - ctx = ctx.prev - if (hooks.indent) { - var hook = hooks.indent(state, ctx, textAfter); - if (typeof hook == "number") return hook - } - var closing = firstChar == ctx.type; - var switchBlock = ctx.prev && ctx.prev.info == "switch"; - if (parserConfig.allmanIndentation && /[{(]/.test(firstChar)) { - while (ctx.type != "top" && ctx.type != "}") ctx = ctx.prev - return ctx.indented - } - if (ctx.type == "statement") - return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit); - if (ctx.align && (!dontAlignCalls || ctx.type != ")")) - return ctx.column + (closing ? 0 : 1); - if (ctx.type == ")" && !closing) - return ctx.indented + statementIndentUnit; - - return ctx.indented + (closing ? 0 : indentUnit) + - (!closing && switchBlock && !/^(?:case|default)\b/.test(textAfter) ? indentUnit : 0); - }, - - electricInput: indentSwitch ? /^\s*(?:case .*?:|default:|\{\}?|\})$/ : /^\s*[{}]$/, - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: "//", - fold: "brace" - }; -}); - - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - function contains(words, word) { - if (typeof words === "function") { - return words(word); - } else { - return words.propertyIsEnumerable(word); - } - } - var cKeywords = "auto if break case register continue return default do sizeof " + - "static else struct switch extern typedef union for goto while enum const volatile"; - var cTypes = "int long char short double float unsigned signed void size_t ptrdiff_t"; - - function cppHook(stream, state) { - if (!state.startOfLine) return false - for (var ch, next = null; ch = stream.peek();) { - if (ch == "\\" && stream.match(/^.$/)) { - next = cppHook - break - } else if (ch == "/" && stream.match(/^\/[\/\*]/, false)) { - break - } - stream.next() - } - state.tokenize = next - return "meta" - } - - function pointerHook(_stream, state) { - if (state.prevToken == "variable-3") return "variable-3"; - return false; - } - - function cpp14Literal(stream) { - stream.eatWhile(/[\w\.']/); - return "number"; - } - - function cpp11StringHook(stream, state) { - stream.backUp(1); - // Raw strings. - if (stream.match(/(R|u8R|uR|UR|LR)/)) { - var match = stream.match(/"([^\s\\()]{0,16})\(/); - if (!match) { - return false; - } - state.cpp11RawStringDelim = match[1]; - state.tokenize = tokenRawString; - return tokenRawString(stream, state); - } - // Unicode strings/chars. - if (stream.match(/(u8|u|U|L)/)) { - if (stream.match(/["']/, /* eat */ false)) { - return "string"; - } - return false; - } - // Ignore this hook. - stream.next(); - return false; - } - - function cppLooksLikeConstructor(word) { - var lastTwo = /(\w+)::(\w+)$/.exec(word); - return lastTwo && lastTwo[1] == lastTwo[2]; - } - - // C#-style strings where "" escapes a quote. - function tokenAtString(stream, state) { - var next; - while ((next = stream.next()) != null) { - if (next == '"' && !stream.eat('"')) { - state.tokenize = null; - break; - } - } - return "string"; - } - - // C++11 raw string literal is "( anything )", where - // can be a string up to 16 characters long. - function tokenRawString(stream, state) { - // Escape characters that have special regex meanings. - var delim = state.cpp11RawStringDelim.replace(/[^\w\s]/g, '\\$&'); - var match = stream.match(new RegExp(".*?\\)" + delim + '"')); - if (match) - state.tokenize = null; - else - stream.skipToEnd(); - return "string"; - } - - function def(mimes, mode) { - if (typeof mimes == "string") mimes = [mimes]; - var words = []; - function add(obj) { - if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop)) - words.push(prop); - } - add(mode.keywords); - add(mode.types); - add(mode.builtin); - add(mode.atoms); - if (words.length) { - mode.helperType = mimes[0]; - CodeMirror.registerHelper("hintWords", mimes[0], words); - } - - for (var i = 0; i < mimes.length; ++i) - CodeMirror.defineMIME(mimes[i], mode); - } - - def(["text/x-csrc", "text/x-c", "text/x-chdr"], { - name: "clike", - keywords: words(cKeywords), - types: words(cTypes + " bool _Complex _Bool float_t double_t intptr_t intmax_t " + - "int8_t int16_t int32_t int64_t uintptr_t uintmax_t uint8_t uint16_t " + - "uint32_t uint64_t"), - blockKeywords: words("case do else for if switch while struct"), - defKeywords: words("struct"), - typeFirstDefinitions: true, - atoms: words("null true false"), - hooks: {"#": cppHook, "*": pointerHook}, - modeProps: {fold: ["brace", "include"]} - }); - - def(["text/x-c++src", "text/x-c++hdr"], { - name: "clike", - keywords: words(cKeywords + " asm dynamic_cast namespace reinterpret_cast try explicit new " + - "static_cast typeid catch operator template typename class friend private " + - "this using const_cast inline public throw virtual delete mutable protected " + - "alignas alignof constexpr decltype nullptr noexcept thread_local final " + - "static_assert override"), - types: words(cTypes + " bool wchar_t"), - blockKeywords: words("catch class do else finally for if struct switch try while"), - defKeywords: words("class namespace struct enum union"), - typeFirstDefinitions: true, - atoms: words("true false null"), - dontIndentStatements: /^template$/, - hooks: { - "#": cppHook, - "*": pointerHook, - "u": cpp11StringHook, - "U": cpp11StringHook, - "L": cpp11StringHook, - "R": cpp11StringHook, - "0": cpp14Literal, - "1": cpp14Literal, - "2": cpp14Literal, - "3": cpp14Literal, - "4": cpp14Literal, - "5": cpp14Literal, - "6": cpp14Literal, - "7": cpp14Literal, - "8": cpp14Literal, - "9": cpp14Literal, - token: function(stream, state, style) { - if (style == "variable" && stream.peek() == "(" && - (state.prevToken == ";" || state.prevToken == null || - state.prevToken == "}") && - cppLooksLikeConstructor(stream.current())) - return "def"; - } - }, - namespaceSeparator: "::", - modeProps: {fold: ["brace", "include"]} - }); - - def("text/x-java", { - name: "clike", - keywords: words("abstract assert break case catch class const continue default " + - "do else enum extends final finally float for goto if implements import " + - "instanceof interface native new package private protected public " + - "return static strictfp super switch synchronized this throw throws transient " + - "try volatile while"), - types: words("byte short int long float double boolean char void Boolean Byte Character Double Float " + - "Integer Long Number Object Short String StringBuffer StringBuilder Void"), - blockKeywords: words("catch class do else finally for if switch try while"), - defKeywords: words("class interface package enum"), - typeFirstDefinitions: true, - atoms: words("true false null"), - number: /^(?:0x[a-f\d_]+|0b[01_]+|(?:[\d_]+\.?\d*|\.\d+)(?:e[-+]?[\d_]+)?)(u|ll?|l|f)?/i, - hooks: { - "@": function(stream) { - stream.eatWhile(/[\w\$_]/); - return "meta"; - } - }, - modeProps: {fold: ["brace", "import"]} - }); - - def("text/x-csharp", { - name: "clike", - keywords: words("abstract as async await base break case catch checked class const continue" + - " default delegate do else enum event explicit extern finally fixed for" + - " foreach goto if implicit in interface internal is lock namespace new" + - " operator out override params private protected public readonly ref return sealed" + - " sizeof stackalloc static struct switch this throw try typeof unchecked" + - " unsafe using virtual void volatile while add alias ascending descending dynamic from get" + - " global group into join let orderby partial remove select set value var yield"), - types: words("Action Boolean Byte Char DateTime DateTimeOffset Decimal Double Func" + - " Guid Int16 Int32 Int64 Object SByte Single String Task TimeSpan UInt16 UInt32" + - " UInt64 bool byte char decimal double short int long object" + - " sbyte float string ushort uint ulong"), - blockKeywords: words("catch class do else finally for foreach if struct switch try while"), - defKeywords: words("class interface namespace struct var"), - typeFirstDefinitions: true, - atoms: words("true false null"), - hooks: { - "@": function(stream, state) { - if (stream.eat('"')) { - state.tokenize = tokenAtString; - return tokenAtString(stream, state); - } - stream.eatWhile(/[\w\$_]/); - return "meta"; - } - } - }); - - function tokenTripleString(stream, state) { - var escaped = false; - while (!stream.eol()) { - if (!escaped && stream.match('"""')) { - state.tokenize = null; - break; - } - escaped = stream.next() == "\\" && !escaped; - } - return "string"; - } - - def("text/x-scala", { - name: "clike", - keywords: words( - - /* scala */ - "abstract case catch class def do else extends final finally for forSome if " + - "implicit import lazy match new null object override package private protected return " + - "sealed super this throw trait try type val var while with yield _ : = => <- <: " + - "<% >: # @ " + - - /* package scala */ - "assert assume require print println printf readLine readBoolean readByte readShort " + - "readChar readInt readLong readFloat readDouble " + - - ":: #:: " - ), - types: words( - "AnyVal App Application Array BufferedIterator BigDecimal BigInt Char Console Either " + - "Enumeration Equiv Error Exception Fractional Function IndexedSeq Int Integral Iterable " + - "Iterator List Map Numeric Nil NotNull Option Ordered Ordering PartialFunction PartialOrdering " + - "Product Proxy Range Responder Seq Serializable Set Specializable Stream StringBuilder " + - "StringContext Symbol Throwable Traversable TraversableOnce Tuple Unit Vector " + - - /* package java.lang */ - "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " + - "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " + - "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " + - "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void" - ), - multiLineStrings: true, - blockKeywords: words("catch class do else finally for forSome if match switch try while"), - defKeywords: words("class def object package trait type val var"), - atoms: words("true false null"), - indentStatements: false, - indentSwitch: false, - hooks: { - "@": function(stream) { - stream.eatWhile(/[\w\$_]/); - return "meta"; - }, - '"': function(stream, state) { - if (!stream.match('""')) return false; - state.tokenize = tokenTripleString; - return state.tokenize(stream, state); - }, - "'": function(stream) { - stream.eatWhile(/[\w\$_\xa1-\uffff]/); - return "atom"; - }, - "=": function(stream, state) { - var cx = state.context - if (cx.type == "}" && cx.align && stream.eat(">")) { - state.context = new Context(cx.indented, cx.column, cx.type, cx.info, null, cx.prev) - return "operator" - } else { - return false - } - } - }, - modeProps: {closeBrackets: {triples: '"'}} - }); - - function tokenKotlinString(tripleString){ - return function (stream, state) { - var escaped = false, next, end = false; - while (!stream.eol()) { - if (!tripleString && !escaped && stream.match('"') ) {end = true; break;} - if (tripleString && stream.match('"""')) {end = true; break;} - next = stream.next(); - if(!escaped && next == "$" && stream.match('{')) - stream.skipTo("}"); - escaped = !escaped && next == "\\" && !tripleString; - } - if (end || !tripleString) - state.tokenize = null; - return "string"; - } - } - - def("text/x-kotlin", { - name: "clike", - keywords: words( - /*keywords*/ - "package as typealias class interface this super val " + - "var fun for is in This throw return " + - "break continue object if else while do try when !in !is as? " + - - /*soft keywords*/ - "file import where by get set abstract enum open inner override private public internal " + - "protected catch finally out final vararg reified dynamic companion constructor init " + - "sealed field property receiver param sparam lateinit data inline noinline tailrec " + - "external annotation crossinline const operator infix" - ), - types: words( - /* package java.lang */ - "Boolean Byte Character CharSequence Class ClassLoader Cloneable Comparable " + - "Compiler Double Exception Float Integer Long Math Number Object Package Pair Process " + - "Runtime Runnable SecurityManager Short StackTraceElement StrictMath String " + - "StringBuffer System Thread ThreadGroup ThreadLocal Throwable Triple Void" - ), - intendSwitch: false, - indentStatements: false, - multiLineStrings: true, - blockKeywords: words("catch class do else finally for if where try while enum"), - defKeywords: words("class val var object package interface fun"), - atoms: words("true false null this"), - hooks: { - '"': function(stream, state) { - state.tokenize = tokenKotlinString(stream.match('""')); - return state.tokenize(stream, state); - } - }, - modeProps: {closeBrackets: {triples: '"'}} - }); - - def(["x-shader/x-vertex", "x-shader/x-fragment"], { - name: "clike", - keywords: words("sampler1D sampler2D sampler3D samplerCube " + - "sampler1DShadow sampler2DShadow " + - "const attribute uniform varying " + - "break continue discard return " + - "for while do if else struct " + - "in out inout"), - types: words("float int bool void " + - "vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 " + - "mat2 mat3 mat4"), - blockKeywords: words("for while do if else struct"), - builtin: words("radians degrees sin cos tan asin acos atan " + - "pow exp log exp2 sqrt inversesqrt " + - "abs sign floor ceil fract mod min max clamp mix step smoothstep " + - "length distance dot cross normalize ftransform faceforward " + - "reflect refract matrixCompMult " + - "lessThan lessThanEqual greaterThan greaterThanEqual " + - "equal notEqual any all not " + - "texture1D texture1DProj texture1DLod texture1DProjLod " + - "texture2D texture2DProj texture2DLod texture2DProjLod " + - "texture3D texture3DProj texture3DLod texture3DProjLod " + - "textureCube textureCubeLod " + - "shadow1D shadow2D shadow1DProj shadow2DProj " + - "shadow1DLod shadow2DLod shadow1DProjLod shadow2DProjLod " + - "dFdx dFdy fwidth " + - "noise1 noise2 noise3 noise4"), - atoms: words("true false " + - "gl_FragColor gl_SecondaryColor gl_Normal gl_Vertex " + - "gl_MultiTexCoord0 gl_MultiTexCoord1 gl_MultiTexCoord2 gl_MultiTexCoord3 " + - "gl_MultiTexCoord4 gl_MultiTexCoord5 gl_MultiTexCoord6 gl_MultiTexCoord7 " + - "gl_FogCoord gl_PointCoord " + - "gl_Position gl_PointSize gl_ClipVertex " + - "gl_FrontColor gl_BackColor gl_FrontSecondaryColor gl_BackSecondaryColor " + - "gl_TexCoord gl_FogFragCoord " + - "gl_FragCoord gl_FrontFacing " + - "gl_FragData gl_FragDepth " + - "gl_ModelViewMatrix gl_ProjectionMatrix gl_ModelViewProjectionMatrix " + - "gl_TextureMatrix gl_NormalMatrix gl_ModelViewMatrixInverse " + - "gl_ProjectionMatrixInverse gl_ModelViewProjectionMatrixInverse " + - "gl_TexureMatrixTranspose gl_ModelViewMatrixInverseTranspose " + - "gl_ProjectionMatrixInverseTranspose " + - "gl_ModelViewProjectionMatrixInverseTranspose " + - "gl_TextureMatrixInverseTranspose " + - "gl_NormalScale gl_DepthRange gl_ClipPlane " + - "gl_Point gl_FrontMaterial gl_BackMaterial gl_LightSource gl_LightModel " + - "gl_FrontLightModelProduct gl_BackLightModelProduct " + - "gl_TextureColor gl_EyePlaneS gl_EyePlaneT gl_EyePlaneR gl_EyePlaneQ " + - "gl_FogParameters " + - "gl_MaxLights gl_MaxClipPlanes gl_MaxTextureUnits gl_MaxTextureCoords " + - "gl_MaxVertexAttribs gl_MaxVertexUniformComponents gl_MaxVaryingFloats " + - "gl_MaxVertexTextureImageUnits gl_MaxTextureImageUnits " + - "gl_MaxFragmentUniformComponents gl_MaxCombineTextureImageUnits " + - "gl_MaxDrawBuffers"), - indentSwitch: false, - hooks: {"#": cppHook}, - modeProps: {fold: ["brace", "include"]} - }); - - def("text/x-nesc", { - name: "clike", - keywords: words(cKeywords + "as atomic async call command component components configuration event generic " + - "implementation includes interface module new norace nx_struct nx_union post provides " + - "signal task uses abstract extends"), - types: words(cTypes), - blockKeywords: words("case do else for if switch while struct"), - atoms: words("null true false"), - hooks: {"#": cppHook}, - modeProps: {fold: ["brace", "include"]} - }); - - def("text/x-objectivec", { - name: "clike", - keywords: words(cKeywords + "inline restrict _Bool _Complex _Imaginary BOOL Class bycopy byref id IMP in " + - "inout nil oneway out Protocol SEL self super atomic nonatomic retain copy readwrite readonly"), - types: words(cTypes), - atoms: words("YES NO NULL NILL ON OFF true false"), - hooks: { - "@": function(stream) { - stream.eatWhile(/[\w\$]/); - return "keyword"; - }, - "#": cppHook, - indent: function(_state, ctx, textAfter) { - if (ctx.type == "statement" && /^@\w/.test(textAfter)) return ctx.indented - } - }, - modeProps: {fold: "brace"} - }); - - def("text/x-squirrel", { - name: "clike", - keywords: words("base break clone continue const default delete enum extends function in class" + - " foreach local resume return this throw typeof yield constructor instanceof static"), - types: words(cTypes), - blockKeywords: words("case catch class else for foreach if switch try while"), - defKeywords: words("function local class"), - typeFirstDefinitions: true, - atoms: words("true false null"), - hooks: {"#": cppHook}, - modeProps: {fold: ["brace", "include"]} - }); - - // Ceylon Strings need to deal with interpolation - var stringTokenizer = null; - function tokenCeylonString(type) { - return function(stream, state) { - var escaped = false, next, end = false; - while (!stream.eol()) { - if (!escaped && stream.match('"') && - (type == "single" || stream.match('""'))) { - end = true; - break; - } - if (!escaped && stream.match('``')) { - stringTokenizer = tokenCeylonString(type); - end = true; - break; - } - next = stream.next(); - escaped = type == "single" && !escaped && next == "\\"; - } - if (end) - state.tokenize = null; - return "string"; - } - } - - def("text/x-ceylon", { - name: "clike", - keywords: words("abstracts alias assembly assert assign break case catch class continue dynamic else" + - " exists extends finally for function given if import in interface is let module new" + - " nonempty object of out outer package return satisfies super switch then this throw" + - " try value void while"), - types: function(word) { - // In Ceylon all identifiers that start with an uppercase are types - var first = word.charAt(0); - return (first === first.toUpperCase() && first !== first.toLowerCase()); - }, - blockKeywords: words("case catch class dynamic else finally for function if interface module new object switch try while"), - defKeywords: words("class dynamic function interface module object package value"), - builtin: words("abstract actual aliased annotation by default deprecated doc final formal late license" + - " native optional sealed see serializable shared suppressWarnings tagged throws variable"), - isPunctuationChar: /[\[\]{}\(\),;\:\.`]/, - isOperatorChar: /[+\-*&%=<>!?|^~:\/]/, - numberStart: /[\d#$]/, - number: /^(?:#[\da-fA-F_]+|\$[01_]+|[\d_]+[kMGTPmunpf]?|[\d_]+\.[\d_]+(?:[eE][-+]?\d+|[kMGTPmunpf]|)|)/i, - multiLineStrings: true, - typeFirstDefinitions: true, - atoms: words("true false null larger smaller equal empty finished"), - indentSwitch: false, - styleDefs: false, - hooks: { - "@": function(stream) { - stream.eatWhile(/[\w\$_]/); - return "meta"; - }, - '"': function(stream, state) { - state.tokenize = tokenCeylonString(stream.match('""') ? "triple" : "single"); - return state.tokenize(stream, state); - }, - '`': function(stream, state) { - if (!stringTokenizer || !stream.match('`')) return false; - state.tokenize = stringTokenizer; - stringTokenizer = null; - return state.tokenize(stream, state); - }, - "'": function(stream) { - stream.eatWhile(/[\w\$_\xa1-\uffff]/); - return "atom"; - }, - token: function(_stream, state, style) { - if ((style == "variable" || style == "variable-3") && - state.prevToken == ".") { - return "variable-2"; - } - } - }, - modeProps: { - fold: ["brace", "import"], - closeBrackets: {triples: '"'} - } - }); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/clike/index.html b/backend/_pv_1_3_5/static/codemirror/mode/clike/index.html deleted file mode 100755 index 45c670ae5..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/clike/index.html +++ /dev/null @@ -1,360 +0,0 @@ - - -CodeMirror: C-like mode - - - - - - - - - - - - -
    -

    C-like mode

    - -
    - -

    C++ example

    - -
    - -

    Objective-C example

    - -
    - -

    Java example

    - -
    - -

    Scala example

    - -
    - -

    Kotlin mode

    - -
    - -

    Ceylon mode

    - -
    - - - -

    Simple mode that tries to handle C-like languages as well as it - can. Takes two configuration parameters: keywords, an - object whose property names are the keywords in the language, - and useCPP, which determines whether C preprocessor - directives are recognized.

    - -

    MIME types defined: text/x-csrc - (C), text/x-c++src (C++), text/x-java - (Java), text/x-csharp (C#), - text/x-objectivec (Objective-C), - text/x-scala (Scala), text/x-vertex - x-shader/x-fragment (shader programs), - text/x-squirrel (Squirrel) and - text/x-ceylon (Ceylon)

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/clike/scala.html b/backend/_pv_1_3_5/static/codemirror/mode/clike/scala.html deleted file mode 100755 index aa04cf0f0..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/clike/scala.html +++ /dev/null @@ -1,767 +0,0 @@ - - -CodeMirror: Scala mode - - - - - - - - - - -
    -

    Scala mode

    -
    - -
    - - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/clike/test.js b/backend/_pv_1_3_5/static/codemirror/mode/clike/test.js deleted file mode 100755 index bea85b869..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/clike/test.js +++ /dev/null @@ -1,55 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-c"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT("indent", - "[variable-3 void] [def foo]([variable-3 void*] [variable a], [variable-3 int] [variable b]) {", - " [variable-3 int] [variable c] [operator =] [variable b] [operator +]", - " [number 1];", - " [keyword return] [operator *][variable a];", - "}"); - - MT("indent_switch", - "[keyword switch] ([variable x]) {", - " [keyword case] [number 10]:", - " [keyword return] [number 20];", - " [keyword default]:", - " [variable printf]([string \"foo %c\"], [variable x]);", - "}"); - - MT("def", - "[variable-3 void] [def foo]() {}", - "[keyword struct] [def bar]{}", - "[variable-3 int] [variable-3 *][def baz]() {}"); - - MT("def_new_line", - "::[variable std]::[variable SomeTerribleType][operator <][variable T][operator >]", - "[def SomeLongMethodNameThatDoesntFitIntoOneLine]([keyword const] [variable MyType][operator &] [variable param]) {}") - - MT("double_block", - "[keyword for] (;;)", - " [keyword for] (;;)", - " [variable x][operator ++];", - "[keyword return];"); - - MT("preprocessor", - "[meta #define FOO 3]", - "[variable-3 int] [variable foo];", - "[meta #define BAR\\]", - "[meta 4]", - "[variable-3 unsigned] [variable-3 int] [variable bar] [operator =] [number 8];", - "[meta #include ][comment // comment]") - - - var mode_cpp = CodeMirror.getMode({indentUnit: 2}, "text/x-c++src"); - function MTCPP(name) { test.mode(name, mode_cpp, Array.prototype.slice.call(arguments, 1)); } - - MTCPP("cpp14_literal", - "[number 10'000];", - "[number 0b10'000];", - "[number 0x10'000];", - "[string '100000'];"); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/clojure/clojure.js b/backend/_pv_1_3_5/static/codemirror/mode/clojure/clojure.js deleted file mode 100755 index ed6af2c83..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/clojure/clojure.js +++ /dev/null @@ -1,306 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** - * Author: Hans Engel - * Branched from CodeMirror's Scheme mode (by Koh Zi Han, based on implementation by Koh Zi Chun) - */ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("clojure", function (options) { - var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", CHARACTER = "string-2", - ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD = "keyword", VAR = "variable"; - var INDENT_WORD_SKIP = options.indentUnit || 2; - var NORMAL_INDENT_UNIT = options.indentUnit || 2; - - function makeKeywords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - var atoms = makeKeywords("true false nil"); - - var keywords = makeKeywords( - "defn defn- def def- defonce defmulti defmethod defmacro defstruct deftype defprotocol defrecord defproject deftest " + - "slice defalias defhinted defmacro- defn-memo defnk defnk defonce- defunbound defunbound- defvar defvar- let letfn " + - "do case cond condp for loop recur when when-not when-let when-first if if-let if-not . .. -> ->> doto and or dosync " + - "doseq dotimes dorun doall load import unimport ns in-ns refer try catch finally throw with-open with-local-vars " + - "binding gen-class gen-and-load-class gen-and-save-class handler-case handle"); - - var builtins = makeKeywords( - "* *' *1 *2 *3 *agent* *allow-unresolved-vars* *assert* *clojure-version* *command-line-args* *compile-files* " + - "*compile-path* *compiler-options* *data-readers* *e *err* *file* *flush-on-newline* *fn-loader* *in* " + - "*math-context* *ns* *out* *print-dup* *print-length* *print-level* *print-meta* *print-readably* *read-eval* " + - "*source-path* *unchecked-math* *use-context-classloader* *verbose-defrecords* *warn-on-reflection* + +' - -' -> " + - "->> ->ArrayChunk ->Vec ->VecNode ->VecSeq -cache-protocol-fn -reset-methods .. / < <= = == > >= EMPTY-NODE accessor " + - "aclone add-classpath add-watch agent agent-error agent-errors aget alength alias all-ns alter alter-meta! " + - "alter-var-root amap ancestors and apply areduce array-map aset aset-boolean aset-byte aset-char aset-double " + - "aset-float aset-int aset-long aset-short assert assoc assoc! assoc-in associative? atom await await-for await1 " + - "bases bean bigdec bigint biginteger binding bit-and bit-and-not bit-clear bit-flip bit-not bit-or bit-set " + - "bit-shift-left bit-shift-right bit-test bit-xor boolean boolean-array booleans bound-fn bound-fn* bound? butlast " + - "byte byte-array bytes case cat cast char char-array char-escape-string char-name-string char? chars chunk chunk-append " + - "chunk-buffer chunk-cons chunk-first chunk-next chunk-rest chunked-seq? class class? clear-agent-errors " + - "clojure-version coll? comment commute comp comparator compare compare-and-set! compile complement completing concat cond condp " + - "conj conj! cons constantly construct-proxy contains? count counted? create-ns create-struct cycle dec dec' decimal? " + - "declare dedupe default-data-readers definline definterface defmacro defmethod defmulti defn defn- defonce defprotocol " + - "defrecord defstruct deftype delay delay? deliver denominator deref derive descendants destructure disj disj! dissoc " + - "dissoc! distinct distinct? doall dorun doseq dosync dotimes doto double double-array doubles drop drop-last " + - "drop-while eduction empty empty? ensure enumeration-seq error-handler error-mode eval even? every-pred every? ex-data ex-info " + - "extend extend-protocol extend-type extenders extends? false? ffirst file-seq filter filterv find find-keyword " + - "find-ns find-protocol-impl find-protocol-method find-var first flatten float float-array float? floats flush fn fn? " + - "fnext fnil for force format frequencies future future-call future-cancel future-cancelled? future-done? future? " + - "gen-class gen-interface gensym get get-in get-method get-proxy-class get-thread-bindings get-validator group-by hash " + - "hash-combine hash-map hash-set identical? identity if-let if-not ifn? import in-ns inc inc' init-proxy instance? " + - "int int-array integer? interleave intern interpose into into-array ints io! isa? iterate iterator-seq juxt keep " + - "keep-indexed key keys keyword keyword? last lazy-cat lazy-seq let letfn line-seq list list* list? load load-file " + - "load-reader load-string loaded-libs locking long long-array longs loop macroexpand macroexpand-1 make-array " + - "make-hierarchy map map-indexed map? mapcat mapv max max-key memfn memoize merge merge-with meta method-sig methods " + - "min min-key mod munge name namespace namespace-munge neg? newline next nfirst nil? nnext not not-any? not-empty " + - "not-every? not= ns ns-aliases ns-imports ns-interns ns-map ns-name ns-publics ns-refers ns-resolve ns-unalias " + - "ns-unmap nth nthnext nthrest num number? numerator object-array odd? or parents partial partition partition-all " + - "partition-by pcalls peek persistent! pmap pop pop! pop-thread-bindings pos? pr pr-str prefer-method prefers " + - "primitives-classnames print print-ctor print-dup print-method print-simple print-str printf println println-str " + - "prn prn-str promise proxy proxy-call-with-super proxy-mappings proxy-name proxy-super push-thread-bindings pvalues " + - "quot rand rand-int rand-nth random-sample range ratio? rational? rationalize re-find re-groups re-matcher re-matches re-pattern " + - "re-seq read read-line read-string realized? reduce reduce-kv reductions ref ref-history-count ref-max-history " + - "ref-min-history ref-set refer refer-clojure reify release-pending-sends rem remove remove-all-methods " + - "remove-method remove-ns remove-watch repeat repeatedly replace replicate require reset! reset-meta! resolve rest " + - "restart-agent resultset-seq reverse reversible? rseq rsubseq satisfies? second select-keys send send-off seq seq? " + - "seque sequence sequential? set set-error-handler! set-error-mode! set-validator! set? short short-array shorts " + - "shuffle shutdown-agents slurp some some-fn sort sort-by sorted-map sorted-map-by sorted-set sorted-set-by sorted? " + - "special-symbol? spit split-at split-with str string? struct struct-map subs subseq subvec supers swap! symbol " + - "symbol? sync take take-last take-nth take-while test the-ns thread-bound? time to-array to-array-2d trampoline transduce " + - "transient tree-seq true? type unchecked-add unchecked-add-int unchecked-byte unchecked-char unchecked-dec " + - "unchecked-dec-int unchecked-divide-int unchecked-double unchecked-float unchecked-inc unchecked-inc-int " + - "unchecked-int unchecked-long unchecked-multiply unchecked-multiply-int unchecked-negate unchecked-negate-int "+ - "unchecked-remainder-int unchecked-short unchecked-subtract unchecked-subtract-int underive unquote " + - "unquote-splicing update update-in update-proxy use val vals var-get var-set var? vary-meta vec vector vector-of " + - "vector? volatile! volatile? vreset! vswap! when when-first when-let when-not while with-bindings with-bindings* with-in-str with-loading-context " + - "with-local-vars with-meta with-open with-out-str with-precision with-redefs with-redefs-fn xml-seq zero? zipmap " + - "*default-data-reader-fn* as-> cond-> cond->> reduced reduced? send-via set-agent-send-executor! " + - "set-agent-send-off-executor! some-> some->>"); - - var indentKeys = makeKeywords( - // Built-ins - "ns fn def defn defmethod bound-fn if if-not case condp when while when-not when-first do future comment doto " + - "locking proxy with-open with-precision reify deftype defrecord defprotocol extend extend-protocol extend-type " + - "try catch " + - - // Binding forms - "let letfn binding loop for doseq dotimes when-let if-let " + - - // Data structures - "defstruct struct-map assoc " + - - // clojure.test - "testing deftest " + - - // contrib - "handler-case handle dotrace deftrace"); - - var tests = { - digit: /\d/, - digit_or_colon: /[\d:]/, - hex: /[0-9a-f]/i, - sign: /[+-]/, - exponent: /e/i, - keyword_char: /[^\s\(\[\;\)\]]/, - symbol: /[\w*+!\-\._?:<>\/\xa1-\uffff]/, - block_indent: /^(?:def|with)[^\/]+$|\/(?:def|with)/ - }; - - function stateStack(indent, type, prev) { // represents a state stack object - this.indent = indent; - this.type = type; - this.prev = prev; - } - - function pushStack(state, indent, type) { - state.indentStack = new stateStack(indent, type, state.indentStack); - } - - function popStack(state) { - state.indentStack = state.indentStack.prev; - } - - function isNumber(ch, stream){ - // hex - if ( ch === '0' && stream.eat(/x/i) ) { - stream.eatWhile(tests.hex); - return true; - } - - // leading sign - if ( ( ch == '+' || ch == '-' ) && ( tests.digit.test(stream.peek()) ) ) { - stream.eat(tests.sign); - ch = stream.next(); - } - - if ( tests.digit.test(ch) ) { - stream.eat(ch); - stream.eatWhile(tests.digit); - - if ( '.' == stream.peek() ) { - stream.eat('.'); - stream.eatWhile(tests.digit); - } else if ('/' == stream.peek() ) { - stream.eat('/'); - stream.eatWhile(tests.digit); - } - - if ( stream.eat(tests.exponent) ) { - stream.eat(tests.sign); - stream.eatWhile(tests.digit); - } - - return true; - } - - return false; - } - - // Eat character that starts after backslash \ - function eatCharacter(stream) { - var first = stream.next(); - // Read special literals: backspace, newline, space, return. - // Just read all lowercase letters. - if (first && first.match(/[a-z]/) && stream.match(/[a-z]+/, true)) { - return; - } - // Read unicode character: \u1000 \uA0a1 - if (first === "u") { - stream.match(/[0-9a-z]{4}/i, true); - } - } - - return { - startState: function () { - return { - indentStack: null, - indentation: 0, - mode: false - }; - }, - - token: function (stream, state) { - if (state.indentStack == null && stream.sol()) { - // update indentation, but only if indentStack is empty - state.indentation = stream.indentation(); - } - - // skip spaces - if (state.mode != "string" && stream.eatSpace()) { - return null; - } - var returnType = null; - - switch(state.mode){ - case "string": // multi-line string parsing mode - var next, escaped = false; - while ((next = stream.next()) != null) { - if (next == "\"" && !escaped) { - - state.mode = false; - break; - } - escaped = !escaped && next == "\\"; - } - returnType = STRING; // continue on in string mode - break; - default: // default parsing mode - var ch = stream.next(); - - if (ch == "\"") { - state.mode = "string"; - returnType = STRING; - } else if (ch == "\\") { - eatCharacter(stream); - returnType = CHARACTER; - } else if (ch == "'" && !( tests.digit_or_colon.test(stream.peek()) )) { - returnType = ATOM; - } else if (ch == ";") { // comment - stream.skipToEnd(); // rest of the line is a comment - returnType = COMMENT; - } else if (isNumber(ch,stream)){ - returnType = NUMBER; - } else if (ch == "(" || ch == "[" || ch == "{" ) { - var keyWord = '', indentTemp = stream.column(), letter; - /** - Either - (indent-word .. - (non-indent-word .. - (;something else, bracket, etc. - */ - - if (ch == "(") while ((letter = stream.eat(tests.keyword_char)) != null) { - keyWord += letter; - } - - if (keyWord.length > 0 && (indentKeys.propertyIsEnumerable(keyWord) || - tests.block_indent.test(keyWord))) { // indent-word - pushStack(state, indentTemp + INDENT_WORD_SKIP, ch); - } else { // non-indent word - // we continue eating the spaces - stream.eatSpace(); - if (stream.eol() || stream.peek() == ";") { - // nothing significant after - // we restart indentation the user defined spaces after - pushStack(state, indentTemp + NORMAL_INDENT_UNIT, ch); - } else { - pushStack(state, indentTemp + stream.current().length, ch); // else we match - } - } - stream.backUp(stream.current().length - 1); // undo all the eating - - returnType = BRACKET; - } else if (ch == ")" || ch == "]" || ch == "}") { - returnType = BRACKET; - if (state.indentStack != null && state.indentStack.type == (ch == ")" ? "(" : (ch == "]" ? "[" :"{"))) { - popStack(state); - } - } else if ( ch == ":" ) { - stream.eatWhile(tests.symbol); - return ATOM; - } else { - stream.eatWhile(tests.symbol); - - if (keywords && keywords.propertyIsEnumerable(stream.current())) { - returnType = KEYWORD; - } else if (builtins && builtins.propertyIsEnumerable(stream.current())) { - returnType = BUILTIN; - } else if (atoms && atoms.propertyIsEnumerable(stream.current())) { - returnType = ATOM; - } else { - returnType = VAR; - } - } - } - - return returnType; - }, - - indent: function (state) { - if (state.indentStack == null) return state.indentation; - return state.indentStack.indent; - }, - - closeBrackets: {pairs: "()[]{}\"\""}, - lineComment: ";;" - }; -}); - -CodeMirror.defineMIME("text/x-clojure", "clojure"); -CodeMirror.defineMIME("text/x-clojurescript", "clojure"); -CodeMirror.defineMIME("application/edn", "clojure"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/clojure/index.html b/backend/_pv_1_3_5/static/codemirror/mode/clojure/index.html deleted file mode 100755 index 81294bc14..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/clojure/index.html +++ /dev/null @@ -1,91 +0,0 @@ - - -CodeMirror: Clojure mode - - - - - - - - - -
    -

    Clojure mode

    -
    - - -

    MIME types defined: text/x-clojure.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/cmake/cmake.js b/backend/_pv_1_3_5/static/codemirror/mode/cmake/cmake.js deleted file mode 100755 index 9f9eda541..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/cmake/cmake.js +++ /dev/null @@ -1,97 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) - define(["../../lib/codemirror"], mod); - else - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("cmake", function () { - var variable_regex = /({)?[a-zA-Z0-9_]+(})?/; - - function tokenString(stream, state) { - var current, prev, found_var = false; - while (!stream.eol() && (current = stream.next()) != state.pending) { - if (current === '$' && prev != '\\' && state.pending == '"') { - found_var = true; - break; - } - prev = current; - } - if (found_var) { - stream.backUp(1); - } - if (current == state.pending) { - state.continueString = false; - } else { - state.continueString = true; - } - return "string"; - } - - function tokenize(stream, state) { - var ch = stream.next(); - - // Have we found a variable? - if (ch === '$') { - if (stream.match(variable_regex)) { - return 'variable-2'; - } - return 'variable'; - } - // Should we still be looking for the end of a string? - if (state.continueString) { - // If so, go through the loop again - stream.backUp(1); - return tokenString(stream, state); - } - // Do we just have a function on our hands? - // In 'cmake_minimum_required (VERSION 2.8.8)', 'cmake_minimum_required' is matched - if (stream.match(/(\s+)?\w+\(/) || stream.match(/(\s+)?\w+\ \(/)) { - stream.backUp(1); - return 'def'; - } - if (ch == "#") { - stream.skipToEnd(); - return "comment"; - } - // Have we found a string? - if (ch == "'" || ch == '"') { - // Store the type (single or double) - state.pending = ch; - // Perform the looping function to find the end - return tokenString(stream, state); - } - if (ch == '(' || ch == ')') { - return 'bracket'; - } - if (ch.match(/[0-9]/)) { - return 'number'; - } - stream.eatWhile(/[\w-]/); - return null; - } - return { - startState: function () { - var state = {}; - state.inDefinition = false; - state.inInclude = false; - state.continueString = false; - state.pending = false; - return state; - }, - token: function (stream, state) { - if (stream.eatSpace()) return null; - return tokenize(stream, state); - } - }; -}); - -CodeMirror.defineMIME("text/x-cmake", "cmake"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/cmake/index.html b/backend/_pv_1_3_5/static/codemirror/mode/cmake/index.html deleted file mode 100755 index ed114fece..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/cmake/index.html +++ /dev/null @@ -1,129 +0,0 @@ - - -CodeMirror: CMake mode - - - - - - - - - - -
    -

    CMake mode

    -
    - - -

    MIME types defined: text/x-cmake.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/cobol/cobol.js b/backend/_pv_1_3_5/static/codemirror/mode/cobol/cobol.js deleted file mode 100755 index 897022b18..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/cobol/cobol.js +++ /dev/null @@ -1,255 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** - * Author: Gautam Mehta - * Branched from CodeMirror's Scheme mode - */ -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("cobol", function () { - var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", - ATOM = "atom", NUMBER = "number", KEYWORD = "keyword", MODTAG = "header", - COBOLLINENUM = "def", PERIOD = "link"; - function makeKeywords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - var atoms = makeKeywords("TRUE FALSE ZEROES ZEROS ZERO SPACES SPACE LOW-VALUE LOW-VALUES "); - var keywords = makeKeywords( - "ACCEPT ACCESS ACQUIRE ADD ADDRESS " + - "ADVANCING AFTER ALIAS ALL ALPHABET " + - "ALPHABETIC ALPHABETIC-LOWER ALPHABETIC-UPPER ALPHANUMERIC ALPHANUMERIC-EDITED " + - "ALSO ALTER ALTERNATE AND ANY " + - "ARE AREA AREAS ARITHMETIC ASCENDING " + - "ASSIGN AT ATTRIBUTE AUTHOR AUTO " + - "AUTO-SKIP AUTOMATIC B-AND B-EXOR B-LESS " + - "B-NOT B-OR BACKGROUND-COLOR BACKGROUND-COLOUR BEEP " + - "BEFORE BELL BINARY BIT BITS " + - "BLANK BLINK BLOCK BOOLEAN BOTTOM " + - "BY CALL CANCEL CD CF " + - "CH CHARACTER CHARACTERS CLASS CLOCK-UNITS " + - "CLOSE COBOL CODE CODE-SET COL " + - "COLLATING COLUMN COMMA COMMIT COMMITMENT " + - "COMMON COMMUNICATION COMP COMP-0 COMP-1 " + - "COMP-2 COMP-3 COMP-4 COMP-5 COMP-6 " + - "COMP-7 COMP-8 COMP-9 COMPUTATIONAL COMPUTATIONAL-0 " + - "COMPUTATIONAL-1 COMPUTATIONAL-2 COMPUTATIONAL-3 COMPUTATIONAL-4 COMPUTATIONAL-5 " + - "COMPUTATIONAL-6 COMPUTATIONAL-7 COMPUTATIONAL-8 COMPUTATIONAL-9 COMPUTE " + - "CONFIGURATION CONNECT CONSOLE CONTAINED CONTAINS " + - "CONTENT CONTINUE CONTROL CONTROL-AREA CONTROLS " + - "CONVERTING COPY CORR CORRESPONDING COUNT " + - "CRT CRT-UNDER CURRENCY CURRENT CURSOR " + - "DATA DATE DATE-COMPILED DATE-WRITTEN DAY " + - "DAY-OF-WEEK DB DB-ACCESS-CONTROL-KEY DB-DATA-NAME DB-EXCEPTION " + - "DB-FORMAT-NAME DB-RECORD-NAME DB-SET-NAME DB-STATUS DBCS " + - "DBCS-EDITED DE DEBUG-CONTENTS DEBUG-ITEM DEBUG-LINE " + - "DEBUG-NAME DEBUG-SUB-1 DEBUG-SUB-2 DEBUG-SUB-3 DEBUGGING " + - "DECIMAL-POINT DECLARATIVES DEFAULT DELETE DELIMITED " + - "DELIMITER DEPENDING DESCENDING DESCRIBED DESTINATION " + - "DETAIL DISABLE DISCONNECT DISPLAY DISPLAY-1 " + - "DISPLAY-2 DISPLAY-3 DISPLAY-4 DISPLAY-5 DISPLAY-6 " + - "DISPLAY-7 DISPLAY-8 DISPLAY-9 DIVIDE DIVISION " + - "DOWN DROP DUPLICATE DUPLICATES DYNAMIC " + - "EBCDIC EGI EJECT ELSE EMI " + - "EMPTY EMPTY-CHECK ENABLE END END. END-ACCEPT END-ACCEPT. " + - "END-ADD END-CALL END-COMPUTE END-DELETE END-DISPLAY " + - "END-DIVIDE END-EVALUATE END-IF END-INVOKE END-MULTIPLY " + - "END-OF-PAGE END-PERFORM END-READ END-RECEIVE END-RETURN " + - "END-REWRITE END-SEARCH END-START END-STRING END-SUBTRACT " + - "END-UNSTRING END-WRITE END-XML ENTER ENTRY " + - "ENVIRONMENT EOP EQUAL EQUALS ERASE " + - "ERROR ESI EVALUATE EVERY EXCEEDS " + - "EXCEPTION EXCLUSIVE EXIT EXTEND EXTERNAL " + - "EXTERNALLY-DESCRIBED-KEY FD FETCH FILE FILE-CONTROL " + - "FILE-STREAM FILES FILLER FINAL FIND " + - "FINISH FIRST FOOTING FOR FOREGROUND-COLOR " + - "FOREGROUND-COLOUR FORMAT FREE FROM FULL " + - "FUNCTION GENERATE GET GIVING GLOBAL " + - "GO GOBACK GREATER GROUP HEADING " + - "HIGH-VALUE HIGH-VALUES HIGHLIGHT I-O I-O-CONTROL " + - "ID IDENTIFICATION IF IN INDEX " + - "INDEX-1 INDEX-2 INDEX-3 INDEX-4 INDEX-5 " + - "INDEX-6 INDEX-7 INDEX-8 INDEX-9 INDEXED " + - "INDIC INDICATE INDICATOR INDICATORS INITIAL " + - "INITIALIZE INITIATE INPUT INPUT-OUTPUT INSPECT " + - "INSTALLATION INTO INVALID INVOKE IS " + - "JUST JUSTIFIED KANJI KEEP KEY " + - "LABEL LAST LD LEADING LEFT " + - "LEFT-JUSTIFY LENGTH LENGTH-CHECK LESS LIBRARY " + - "LIKE LIMIT LIMITS LINAGE LINAGE-COUNTER " + - "LINE LINE-COUNTER LINES LINKAGE LOCAL-STORAGE " + - "LOCALE LOCALLY LOCK " + - "MEMBER MEMORY MERGE MESSAGE METACLASS " + - "MODE MODIFIED MODIFY MODULES MOVE " + - "MULTIPLE MULTIPLY NATIONAL NATIVE NEGATIVE " + - "NEXT NO NO-ECHO NONE NOT " + - "NULL NULL-KEY-MAP NULL-MAP NULLS NUMBER " + - "NUMERIC NUMERIC-EDITED OBJECT OBJECT-COMPUTER OCCURS " + - "OF OFF OMITTED ON ONLY " + - "OPEN OPTIONAL OR ORDER ORGANIZATION " + - "OTHER OUTPUT OVERFLOW OWNER PACKED-DECIMAL " + - "PADDING PAGE PAGE-COUNTER PARSE PERFORM " + - "PF PH PIC PICTURE PLUS " + - "POINTER POSITION POSITIVE PREFIX PRESENT " + - "PRINTING PRIOR PROCEDURE PROCEDURE-POINTER PROCEDURES " + - "PROCEED PROCESS PROCESSING PROGRAM PROGRAM-ID " + - "PROMPT PROTECTED PURGE QUEUE QUOTE " + - "QUOTES RANDOM RD READ READY " + - "REALM RECEIVE RECONNECT RECORD RECORD-NAME " + - "RECORDS RECURSIVE REDEFINES REEL REFERENCE " + - "REFERENCE-MONITOR REFERENCES RELATION RELATIVE RELEASE " + - "REMAINDER REMOVAL RENAMES REPEATED REPLACE " + - "REPLACING REPORT REPORTING REPORTS REPOSITORY " + - "REQUIRED RERUN RESERVE RESET RETAINING " + - "RETRIEVAL RETURN RETURN-CODE RETURNING REVERSE-VIDEO " + - "REVERSED REWIND REWRITE RF RH " + - "RIGHT RIGHT-JUSTIFY ROLLBACK ROLLING ROUNDED " + - "RUN SAME SCREEN SD SEARCH " + - "SECTION SECURE SECURITY SEGMENT SEGMENT-LIMIT " + - "SELECT SEND SENTENCE SEPARATE SEQUENCE " + - "SEQUENTIAL SET SHARED SIGN SIZE " + - "SKIP1 SKIP2 SKIP3 SORT SORT-MERGE " + - "SORT-RETURN SOURCE SOURCE-COMPUTER SPACE-FILL " + - "SPECIAL-NAMES STANDARD STANDARD-1 STANDARD-2 " + - "START STARTING STATUS STOP STORE " + - "STRING SUB-QUEUE-1 SUB-QUEUE-2 SUB-QUEUE-3 SUB-SCHEMA " + - "SUBFILE SUBSTITUTE SUBTRACT SUM SUPPRESS " + - "SYMBOLIC SYNC SYNCHRONIZED SYSIN SYSOUT " + - "TABLE TALLYING TAPE TENANT TERMINAL " + - "TERMINATE TEST TEXT THAN THEN " + - "THROUGH THRU TIME TIMES TITLE " + - "TO TOP TRAILING TRAILING-SIGN TRANSACTION " + - "TYPE TYPEDEF UNDERLINE UNEQUAL UNIT " + - "UNSTRING UNTIL UP UPDATE UPON " + - "USAGE USAGE-MODE USE USING VALID " + - "VALIDATE VALUE VALUES VARYING VLR " + - "WAIT WHEN WHEN-COMPILED WITH WITHIN " + - "WORDS WORKING-STORAGE WRITE XML XML-CODE " + - "XML-EVENT XML-NTEXT XML-TEXT ZERO ZERO-FILL " ); - - var builtins = makeKeywords("- * ** / + < <= = > >= "); - var tests = { - digit: /\d/, - digit_or_colon: /[\d:]/, - hex: /[0-9a-f]/i, - sign: /[+-]/, - exponent: /e/i, - keyword_char: /[^\s\(\[\;\)\]]/, - symbol: /[\w*+\-]/ - }; - function isNumber(ch, stream){ - // hex - if ( ch === '0' && stream.eat(/x/i) ) { - stream.eatWhile(tests.hex); - return true; - } - // leading sign - if ( ( ch == '+' || ch == '-' ) && ( tests.digit.test(stream.peek()) ) ) { - stream.eat(tests.sign); - ch = stream.next(); - } - if ( tests.digit.test(ch) ) { - stream.eat(ch); - stream.eatWhile(tests.digit); - if ( '.' == stream.peek()) { - stream.eat('.'); - stream.eatWhile(tests.digit); - } - if ( stream.eat(tests.exponent) ) { - stream.eat(tests.sign); - stream.eatWhile(tests.digit); - } - return true; - } - return false; - } - return { - startState: function () { - return { - indentStack: null, - indentation: 0, - mode: false - }; - }, - token: function (stream, state) { - if (state.indentStack == null && stream.sol()) { - // update indentation, but only if indentStack is empty - state.indentation = 6 ; //stream.indentation(); - } - // skip spaces - if (stream.eatSpace()) { - return null; - } - var returnType = null; - switch(state.mode){ - case "string": // multi-line string parsing mode - var next = false; - while ((next = stream.next()) != null) { - if (next == "\"" || next == "\'") { - state.mode = false; - break; - } - } - returnType = STRING; // continue on in string mode - break; - default: // default parsing mode - var ch = stream.next(); - var col = stream.column(); - if (col >= 0 && col <= 5) { - returnType = COBOLLINENUM; - } else if (col >= 72 && col <= 79) { - stream.skipToEnd(); - returnType = MODTAG; - } else if (ch == "*" && col == 6) { // comment - stream.skipToEnd(); // rest of the line is a comment - returnType = COMMENT; - } else if (ch == "\"" || ch == "\'") { - state.mode = "string"; - returnType = STRING; - } else if (ch == "'" && !( tests.digit_or_colon.test(stream.peek()) )) { - returnType = ATOM; - } else if (ch == ".") { - returnType = PERIOD; - } else if (isNumber(ch,stream)){ - returnType = NUMBER; - } else { - if (stream.current().match(tests.symbol)) { - while (col < 71) { - if (stream.eat(tests.symbol) === undefined) { - break; - } else { - col++; - } - } - } - if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) { - returnType = KEYWORD; - } else if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase())) { - returnType = BUILTIN; - } else if (atoms && atoms.propertyIsEnumerable(stream.current().toUpperCase())) { - returnType = ATOM; - } else returnType = null; - } - } - return returnType; - }, - indent: function (state) { - if (state.indentStack == null) return state.indentation; - return state.indentStack.indent; - } - }; -}); - -CodeMirror.defineMIME("text/x-cobol", "cobol"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/cobol/index.html b/backend/_pv_1_3_5/static/codemirror/mode/cobol/index.html deleted file mode 100755 index 4352419a0..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/cobol/index.html +++ /dev/null @@ -1,210 +0,0 @@ - - -CodeMirror: COBOL mode - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -

    COBOL mode

    - -

    Select Theme Select Font Size - - - - -

    - - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/coffeescript/coffeescript.js b/backend/_pv_1_3_5/static/codemirror/mode/coffeescript/coffeescript.js deleted file mode 100755 index adf2184fd..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/coffeescript/coffeescript.js +++ /dev/null @@ -1,355 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** - * Link to the project's GitHub page: - * https://github.com/pickhardt/coffeescript-codemirror-mode - */ -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("coffeescript", function(conf, parserConf) { - var ERRORCLASS = "error"; - - function wordRegexp(words) { - return new RegExp("^((" + words.join(")|(") + "))\\b"); - } - - var operators = /^(?:->|=>|\+[+=]?|-[\-=]?|\*[\*=]?|\/[\/=]?|[=!]=|<[><]?=?|>>?=?|%=?|&=?|\|=?|\^=?|\~|!|\?|(or|and|\|\||&&|\?)=)/; - var delimiters = /^(?:[()\[\]{},:`=;]|\.\.?\.?)/; - var identifiers = /^[_A-Za-z$][_A-Za-z$0-9]*/; - var atProp = /^@[_A-Za-z$][_A-Za-z$0-9]*/; - - var wordOperators = wordRegexp(["and", "or", "not", - "is", "isnt", "in", - "instanceof", "typeof"]); - var indentKeywords = ["for", "while", "loop", "if", "unless", "else", - "switch", "try", "catch", "finally", "class"]; - var commonKeywords = ["break", "by", "continue", "debugger", "delete", - "do", "in", "of", "new", "return", "then", - "this", "@", "throw", "when", "until", "extends"]; - - var keywords = wordRegexp(indentKeywords.concat(commonKeywords)); - - indentKeywords = wordRegexp(indentKeywords); - - - var stringPrefixes = /^('{3}|\"{3}|['\"])/; - var regexPrefixes = /^(\/{3}|\/)/; - var commonConstants = ["Infinity", "NaN", "undefined", "null", "true", "false", "on", "off", "yes", "no"]; - var constants = wordRegexp(commonConstants); - - // Tokenizers - function tokenBase(stream, state) { - // Handle scope changes - if (stream.sol()) { - if (state.scope.align === null) state.scope.align = false; - var scopeOffset = state.scope.offset; - if (stream.eatSpace()) { - var lineOffset = stream.indentation(); - if (lineOffset > scopeOffset && state.scope.type == "coffee") { - return "indent"; - } else if (lineOffset < scopeOffset) { - return "dedent"; - } - return null; - } else { - if (scopeOffset > 0) { - dedent(stream, state); - } - } - } - if (stream.eatSpace()) { - return null; - } - - var ch = stream.peek(); - - // Handle docco title comment (single line) - if (stream.match("####")) { - stream.skipToEnd(); - return "comment"; - } - - // Handle multi line comments - if (stream.match("###")) { - state.tokenize = longComment; - return state.tokenize(stream, state); - } - - // Single line comment - if (ch === "#") { - stream.skipToEnd(); - return "comment"; - } - - // Handle number literals - if (stream.match(/^-?[0-9\.]/, false)) { - var floatLiteral = false; - // Floats - if (stream.match(/^-?\d*\.\d+(e[\+\-]?\d+)?/i)) { - floatLiteral = true; - } - if (stream.match(/^-?\d+\.\d*/)) { - floatLiteral = true; - } - if (stream.match(/^-?\.\d+/)) { - floatLiteral = true; - } - - if (floatLiteral) { - // prevent from getting extra . on 1.. - if (stream.peek() == "."){ - stream.backUp(1); - } - return "number"; - } - // Integers - var intLiteral = false; - // Hex - if (stream.match(/^-?0x[0-9a-f]+/i)) { - intLiteral = true; - } - // Decimal - if (stream.match(/^-?[1-9]\d*(e[\+\-]?\d+)?/)) { - intLiteral = true; - } - // Zero by itself with no other piece of number. - if (stream.match(/^-?0(?![\dx])/i)) { - intLiteral = true; - } - if (intLiteral) { - return "number"; - } - } - - // Handle strings - if (stream.match(stringPrefixes)) { - state.tokenize = tokenFactory(stream.current(), false, "string"); - return state.tokenize(stream, state); - } - // Handle regex literals - if (stream.match(regexPrefixes)) { - if (stream.current() != "/" || stream.match(/^.*\//, false)) { // prevent highlight of division - state.tokenize = tokenFactory(stream.current(), true, "string-2"); - return state.tokenize(stream, state); - } else { - stream.backUp(1); - } - } - - - - // Handle operators and delimiters - if (stream.match(operators) || stream.match(wordOperators)) { - return "operator"; - } - if (stream.match(delimiters)) { - return "punctuation"; - } - - if (stream.match(constants)) { - return "atom"; - } - - if (stream.match(atProp) || state.prop && stream.match(identifiers)) { - return "property"; - } - - if (stream.match(keywords)) { - return "keyword"; - } - - if (stream.match(identifiers)) { - return "variable"; - } - - // Handle non-detected items - stream.next(); - return ERRORCLASS; - } - - function tokenFactory(delimiter, singleline, outclass) { - return function(stream, state) { - while (!stream.eol()) { - stream.eatWhile(/[^'"\/\\]/); - if (stream.eat("\\")) { - stream.next(); - if (singleline && stream.eol()) { - return outclass; - } - } else if (stream.match(delimiter)) { - state.tokenize = tokenBase; - return outclass; - } else { - stream.eat(/['"\/]/); - } - } - if (singleline) { - if (parserConf.singleLineStringErrors) { - outclass = ERRORCLASS; - } else { - state.tokenize = tokenBase; - } - } - return outclass; - }; - } - - function longComment(stream, state) { - while (!stream.eol()) { - stream.eatWhile(/[^#]/); - if (stream.match("###")) { - state.tokenize = tokenBase; - break; - } - stream.eatWhile("#"); - } - return "comment"; - } - - function indent(stream, state, type) { - type = type || "coffee"; - var offset = 0, align = false, alignOffset = null; - for (var scope = state.scope; scope; scope = scope.prev) { - if (scope.type === "coffee" || scope.type == "}") { - offset = scope.offset + conf.indentUnit; - break; - } - } - if (type !== "coffee") { - align = null; - alignOffset = stream.column() + stream.current().length; - } else if (state.scope.align) { - state.scope.align = false; - } - state.scope = { - offset: offset, - type: type, - prev: state.scope, - align: align, - alignOffset: alignOffset - }; - } - - function dedent(stream, state) { - if (!state.scope.prev) return; - if (state.scope.type === "coffee") { - var _indent = stream.indentation(); - var matched = false; - for (var scope = state.scope; scope; scope = scope.prev) { - if (_indent === scope.offset) { - matched = true; - break; - } - } - if (!matched) { - return true; - } - while (state.scope.prev && state.scope.offset !== _indent) { - state.scope = state.scope.prev; - } - return false; - } else { - state.scope = state.scope.prev; - return false; - } - } - - function tokenLexer(stream, state) { - var style = state.tokenize(stream, state); - var current = stream.current(); - - // Handle scope changes. - if (current === "return") { - state.dedent = true; - } - if (((current === "->" || current === "=>") && stream.eol()) - || style === "indent") { - indent(stream, state); - } - var delimiter_index = "[({".indexOf(current); - if (delimiter_index !== -1) { - indent(stream, state, "])}".slice(delimiter_index, delimiter_index+1)); - } - if (indentKeywords.exec(current)){ - indent(stream, state); - } - if (current == "then"){ - dedent(stream, state); - } - - - if (style === "dedent") { - if (dedent(stream, state)) { - return ERRORCLASS; - } - } - delimiter_index = "])}".indexOf(current); - if (delimiter_index !== -1) { - while (state.scope.type == "coffee" && state.scope.prev) - state.scope = state.scope.prev; - if (state.scope.type == current) - state.scope = state.scope.prev; - } - if (state.dedent && stream.eol()) { - if (state.scope.type == "coffee" && state.scope.prev) - state.scope = state.scope.prev; - state.dedent = false; - } - - return style; - } - - var external = { - startState: function(basecolumn) { - return { - tokenize: tokenBase, - scope: {offset:basecolumn || 0, type:"coffee", prev: null, align: false}, - prop: false, - dedent: 0 - }; - }, - - token: function(stream, state) { - var fillAlign = state.scope.align === null && state.scope; - if (fillAlign && stream.sol()) fillAlign.align = false; - - var style = tokenLexer(stream, state); - if (style && style != "comment") { - if (fillAlign) fillAlign.align = true; - state.prop = style == "punctuation" && stream.current() == "." - } - - return style; - }, - - indent: function(state, text) { - if (state.tokenize != tokenBase) return 0; - var scope = state.scope; - var closer = text && "])}".indexOf(text.charAt(0)) > -1; - if (closer) while (scope.type == "coffee" && scope.prev) scope = scope.prev; - var closes = closer && scope.type === text.charAt(0); - if (scope.align) - return scope.alignOffset - (closes ? 1 : 0); - else - return (closes ? scope.prev : scope).offset; - }, - - lineComment: "#", - fold: "indent" - }; - return external; -}); - -CodeMirror.defineMIME("text/x-coffeescript", "coffeescript"); -CodeMirror.defineMIME("text/coffeescript", "coffeescript"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/coffeescript/index.html b/backend/_pv_1_3_5/static/codemirror/mode/coffeescript/index.html deleted file mode 100755 index 93a5f4f30..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/coffeescript/index.html +++ /dev/null @@ -1,740 +0,0 @@ - - -CodeMirror: CoffeeScript mode - - - - - - - - - -
    -

    CoffeeScript mode

    -
    - - -

    MIME types defined: text/x-coffeescript.

    - -

    The CoffeeScript mode was written by Jeff Pickhardt.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/commonlisp/commonlisp.js b/backend/_pv_1_3_5/static/codemirror/mode/commonlisp/commonlisp.js deleted file mode 100755 index 5b407a928..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/commonlisp/commonlisp.js +++ /dev/null @@ -1,124 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("commonlisp", function (config) { - var specialForm = /^(block|let*|return-from|catch|load-time-value|setq|eval-when|locally|symbol-macrolet|flet|macrolet|tagbody|function|multiple-value-call|the|go|multiple-value-prog1|throw|if|progn|unwind-protect|labels|progv|let|quote)$/; - var assumeBody = /^with|^def|^do|^prog|case$|^cond$|bind$|when$|unless$/; - var numLiteral = /^(?:[+\-]?(?:\d+|\d*\.\d+)(?:[efd][+\-]?\d+)?|[+\-]?\d+(?:\/[+\-]?\d+)?|#b[+\-]?[01]+|#o[+\-]?[0-7]+|#x[+\-]?[\da-f]+)/; - var symbol = /[^\s'`,@()\[\]";]/; - var type; - - function readSym(stream) { - var ch; - while (ch = stream.next()) { - if (ch == "\\") stream.next(); - else if (!symbol.test(ch)) { stream.backUp(1); break; } - } - return stream.current(); - } - - function base(stream, state) { - if (stream.eatSpace()) {type = "ws"; return null;} - if (stream.match(numLiteral)) return "number"; - var ch = stream.next(); - if (ch == "\\") ch = stream.next(); - - if (ch == '"') return (state.tokenize = inString)(stream, state); - else if (ch == "(") { type = "open"; return "bracket"; } - else if (ch == ")" || ch == "]") { type = "close"; return "bracket"; } - else if (ch == ";") { stream.skipToEnd(); type = "ws"; return "comment"; } - else if (/['`,@]/.test(ch)) return null; - else if (ch == "|") { - if (stream.skipTo("|")) { stream.next(); return "symbol"; } - else { stream.skipToEnd(); return "error"; } - } else if (ch == "#") { - var ch = stream.next(); - if (ch == "[") { type = "open"; return "bracket"; } - else if (/[+\-=\.']/.test(ch)) return null; - else if (/\d/.test(ch) && stream.match(/^\d*#/)) return null; - else if (ch == "|") return (state.tokenize = inComment)(stream, state); - else if (ch == ":") { readSym(stream); return "meta"; } - else if (ch == "\\") { stream.next(); readSym(stream); return "string-2" } - else return "error"; - } else { - var name = readSym(stream); - if (name == ".") return null; - type = "symbol"; - if (name == "nil" || name == "t" || name.charAt(0) == ":") return "atom"; - if (state.lastType == "open" && (specialForm.test(name) || assumeBody.test(name))) return "keyword"; - if (name.charAt(0) == "&") return "variable-2"; - return "variable"; - } - } - - function inString(stream, state) { - var escaped = false, next; - while (next = stream.next()) { - if (next == '"' && !escaped) { state.tokenize = base; break; } - escaped = !escaped && next == "\\"; - } - return "string"; - } - - function inComment(stream, state) { - var next, last; - while (next = stream.next()) { - if (next == "#" && last == "|") { state.tokenize = base; break; } - last = next; - } - type = "ws"; - return "comment"; - } - - return { - startState: function () { - return {ctx: {prev: null, start: 0, indentTo: 0}, lastType: null, tokenize: base}; - }, - - token: function (stream, state) { - if (stream.sol() && typeof state.ctx.indentTo != "number") - state.ctx.indentTo = state.ctx.start + 1; - - type = null; - var style = state.tokenize(stream, state); - if (type != "ws") { - if (state.ctx.indentTo == null) { - if (type == "symbol" && assumeBody.test(stream.current())) - state.ctx.indentTo = state.ctx.start + config.indentUnit; - else - state.ctx.indentTo = "next"; - } else if (state.ctx.indentTo == "next") { - state.ctx.indentTo = stream.column(); - } - state.lastType = type; - } - if (type == "open") state.ctx = {prev: state.ctx, start: stream.column(), indentTo: null}; - else if (type == "close") state.ctx = state.ctx.prev || state.ctx; - return style; - }, - - indent: function (state, _textAfter) { - var i = state.ctx.indentTo; - return typeof i == "number" ? i : state.ctx.start + 1; - }, - - closeBrackets: {pairs: "()[]{}\"\""}, - lineComment: ";;", - blockCommentStart: "#|", - blockCommentEnd: "|#" - }; -}); - -CodeMirror.defineMIME("text/x-common-lisp", "commonlisp"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/commonlisp/index.html b/backend/_pv_1_3_5/static/codemirror/mode/commonlisp/index.html deleted file mode 100755 index f2bf4522d..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/commonlisp/index.html +++ /dev/null @@ -1,177 +0,0 @@ - - -CodeMirror: Common Lisp mode - - - - - - - - - -
    -

    Common Lisp mode

    -
    - - -

    MIME types defined: text/x-common-lisp.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/crystal/crystal.js b/backend/_pv_1_3_5/static/codemirror/mode/crystal/crystal.js deleted file mode 100755 index e63627cee..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/crystal/crystal.js +++ /dev/null @@ -1,391 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("crystal", function(config) { - function wordRegExp(words, end) { - return new RegExp((end ? "" : "^") + "(?:" + words.join("|") + ")" + (end ? "$" : "\\b")); - } - - function chain(tokenize, stream, state) { - state.tokenize.push(tokenize); - return tokenize(stream, state); - } - - var operators = /^(?:[-+/%|&^]|\*\*?|[<>]{2})/; - var conditionalOperators = /^(?:[=!]~|===|<=>|[<>=!]=?|[|&]{2}|~)/; - var indexingOperators = /^(?:\[\][?=]?)/; - var anotherOperators = /^(?:\.(?:\.{2})?|->|[?:])/; - var idents = /^[a-z_\u009F-\uFFFF][a-zA-Z0-9_\u009F-\uFFFF]*/; - var types = /^[A-Z_\u009F-\uFFFF][a-zA-Z0-9_\u009F-\uFFFF]*/; - var keywords = wordRegExp([ - "abstract", "alias", "as", "asm", "begin", "break", "case", "class", "def", "do", - "else", "elsif", "end", "ensure", "enum", "extend", "for", "fun", "if", "ifdef", - "include", "instance_sizeof", "lib", "macro", "module", "next", "of", "out", "pointerof", - "private", "protected", "rescue", "return", "require", "sizeof", "struct", - "super", "then", "type", "typeof", "union", "unless", "until", "when", "while", "with", - "yield", "__DIR__", "__FILE__", "__LINE__" - ]); - var atomWords = wordRegExp(["true", "false", "nil", "self"]); - var indentKeywordsArray = [ - "def", "fun", "macro", - "class", "module", "struct", "lib", "enum", "union", - "if", "unless", "case", "while", "until", "begin", "then", - "do", - "for", "ifdef" - ]; - var indentKeywords = wordRegExp(indentKeywordsArray); - var dedentKeywordsArray = [ - "end", - "else", "elsif", - "rescue", "ensure" - ]; - var dedentKeywords = wordRegExp(dedentKeywordsArray); - var dedentPunctualsArray = ["\\)", "\\}", "\\]"]; - var dedentPunctuals = new RegExp("^(?:" + dedentPunctualsArray.join("|") + ")$"); - var nextTokenizer = { - "def": tokenFollowIdent, "fun": tokenFollowIdent, "macro": tokenMacroDef, - "class": tokenFollowType, "module": tokenFollowType, "struct": tokenFollowType, - "lib": tokenFollowType, "enum": tokenFollowType, "union": tokenFollowType - }; - var matching = {"[": "]", "{": "}", "(": ")", "<": ">"}; - - function tokenBase(stream, state) { - if (stream.eatSpace()) { - return null; - } - - // Macros - if (state.lastToken != "\\" && stream.match("{%", false)) { - return chain(tokenMacro("%", "%"), stream, state); - } - - if (state.lastToken != "\\" && stream.match("{{", false)) { - return chain(tokenMacro("{", "}"), stream, state); - } - - // Comments - if (stream.peek() == "#") { - stream.skipToEnd(); - return "comment"; - } - - // Variables and keywords - var matched; - if (stream.match(idents)) { - stream.eat(/[?!]/); - - matched = stream.current(); - if (stream.eat(":")) { - return "atom"; - } else if (state.lastToken == ".") { - return "property"; - } else if (keywords.test(matched)) { - if (state.lastToken != "abstract" && indentKeywords.test(matched)) { - if (!(matched == "fun" && state.blocks.indexOf("lib") >= 0)) { - state.blocks.push(matched); - state.currentIndent += 1; - } - } else if (dedentKeywords.test(matched)) { - state.blocks.pop(); - state.currentIndent -= 1; - } - - if (nextTokenizer.hasOwnProperty(matched)) { - state.tokenize.push(nextTokenizer[matched]); - } - - return "keyword"; - } else if (atomWords.test(matched)) { - return "atom"; - } - - return "variable"; - } - - // Class variables and instance variables - // or attributes - if (stream.eat("@")) { - if (stream.peek() == "[") { - return chain(tokenNest("[", "]", "meta"), stream, state); - } - - stream.eat("@"); - stream.match(idents) || stream.match(types); - return "variable-2"; - } - - // Global variables - if (stream.eat("$")) { - stream.eat(/[0-9]+|\?/) || stream.match(idents) || stream.match(types); - return "variable-3"; - } - - // Constants and types - if (stream.match(types)) { - return "tag"; - } - - // Symbols or ':' operator - if (stream.eat(":")) { - if (stream.eat("\"")) { - return chain(tokenQuote("\"", "atom", false), stream, state); - } else if (stream.match(idents) || stream.match(types) || - stream.match(operators) || stream.match(conditionalOperators) || stream.match(indexingOperators)) { - return "atom"; - } - stream.eat(":"); - return "operator"; - } - - // Strings - if (stream.eat("\"")) { - return chain(tokenQuote("\"", "string", true), stream, state); - } - - // Strings or regexps or macro variables or '%' operator - if (stream.peek() == "%") { - var style = "string"; - var embed = true; - var delim; - - if (stream.match("%r")) { - // Regexps - style = "string-2"; - delim = stream.next(); - } else if (stream.match("%w")) { - embed = false; - delim = stream.next(); - } else { - if(delim = stream.match(/^%([^\w\s=])/)) { - delim = delim[1]; - } else if (stream.match(/^%[a-zA-Z0-9_\u009F-\uFFFF]*/)) { - // Macro variables - return "meta"; - } else { - // '%' operator - return "operator"; - } - } - - if (matching.hasOwnProperty(delim)) { - delim = matching[delim]; - } - return chain(tokenQuote(delim, style, embed), stream, state); - } - - // Characters - if (stream.eat("'")) { - stream.match(/^(?:[^']|\\(?:[befnrtv0'"]|[0-7]{3}|u(?:[0-9a-fA-F]{4}|\{[0-9a-fA-F]{1,6}\})))/); - stream.eat("'"); - return "atom"; - } - - // Numbers - if (stream.eat("0")) { - if (stream.eat("x")) { - stream.match(/^[0-9a-fA-F]+/); - } else if (stream.eat("o")) { - stream.match(/^[0-7]+/); - } else if (stream.eat("b")) { - stream.match(/^[01]+/); - } - return "number"; - } - - if (stream.eat(/\d/)) { - stream.match(/^\d*(?:\.\d+)?(?:[eE][+-]?\d+)?/); - return "number"; - } - - // Operators - if (stream.match(operators)) { - stream.eat("="); // Operators can follow assign symbol. - return "operator"; - } - - if (stream.match(conditionalOperators) || stream.match(anotherOperators)) { - return "operator"; - } - - // Parens and braces - if (matched = stream.match(/[({[]/, false)) { - matched = matched[0]; - return chain(tokenNest(matched, matching[matched], null), stream, state); - } - - // Escapes - if (stream.eat("\\")) { - stream.next(); - return "meta"; - } - - stream.next(); - return null; - } - - function tokenNest(begin, end, style, started) { - return function (stream, state) { - if (!started && stream.match(begin)) { - state.tokenize[state.tokenize.length - 1] = tokenNest(begin, end, style, true); - state.currentIndent += 1; - return style; - } - - var nextStyle = tokenBase(stream, state); - if (stream.current() === end) { - state.tokenize.pop(); - state.currentIndent -= 1; - nextStyle = style; - } - - return nextStyle; - }; - } - - function tokenMacro(begin, end, started) { - return function (stream, state) { - if (!started && stream.match("{" + begin)) { - state.currentIndent += 1; - state.tokenize[state.tokenize.length - 1] = tokenMacro(begin, end, true); - return "meta"; - } - - if (stream.match(end + "}")) { - state.currentIndent -= 1; - state.tokenize.pop(); - return "meta"; - } - - return tokenBase(stream, state); - }; - } - - function tokenMacroDef(stream, state) { - if (stream.eatSpace()) { - return null; - } - - var matched; - if (matched = stream.match(idents)) { - if (matched == "def") { - return "keyword"; - } - stream.eat(/[?!]/); - } - - state.tokenize.pop(); - return "def"; - } - - function tokenFollowIdent(stream, state) { - if (stream.eatSpace()) { - return null; - } - - if (stream.match(idents)) { - stream.eat(/[!?]/); - } else { - stream.match(operators) || stream.match(conditionalOperators) || stream.match(indexingOperators); - } - state.tokenize.pop(); - return "def"; - } - - function tokenFollowType(stream, state) { - if (stream.eatSpace()) { - return null; - } - - stream.match(types); - state.tokenize.pop(); - return "def"; - } - - function tokenQuote(end, style, embed) { - return function (stream, state) { - var escaped = false; - - while (stream.peek()) { - if (!escaped) { - if (stream.match("{%", false)) { - state.tokenize.push(tokenMacro("%", "%")); - return style; - } - - if (stream.match("{{", false)) { - state.tokenize.push(tokenMacro("{", "}")); - return style; - } - - if (embed && stream.match("#{", false)) { - state.tokenize.push(tokenNest("#{", "}", "meta")); - return style; - } - - var ch = stream.next(); - - if (ch == end) { - state.tokenize.pop(); - return style; - } - - escaped = ch == "\\"; - } else { - stream.next(); - escaped = false; - } - } - - return style; - }; - } - - return { - startState: function () { - return { - tokenize: [tokenBase], - currentIndent: 0, - lastToken: null, - blocks: [] - }; - }, - - token: function (stream, state) { - var style = state.tokenize[state.tokenize.length - 1](stream, state); - var token = stream.current(); - - if (style && style != "comment") { - state.lastToken = token; - } - - return style; - }, - - indent: function (state, textAfter) { - textAfter = textAfter.replace(/^\s*(?:\{%)?\s*|\s*(?:%\})?\s*$/g, ""); - - if (dedentKeywords.test(textAfter) || dedentPunctuals.test(textAfter)) { - return config.indentUnit * (state.currentIndent - 1); - } - - return config.indentUnit * state.currentIndent; - }, - - fold: "indent", - electricInput: wordRegExp(dedentPunctualsArray.concat(dedentKeywordsArray), true), - lineComment: '#' - }; - }); - - CodeMirror.defineMIME("text/x-crystal", "crystal"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/crystal/index.html b/backend/_pv_1_3_5/static/codemirror/mode/crystal/index.html deleted file mode 100755 index ec03e2509..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/crystal/index.html +++ /dev/null @@ -1,119 +0,0 @@ - - -CodeMirror: Crystal mode - - - - - - - - - - - -
    -

    Crystal mode

    -
    - - -

    MIME types defined: text/x-crystal.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/css/css.js b/backend/_pv_1_3_5/static/codemirror/mode/css/css.js deleted file mode 100755 index 90de4ee79..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/css/css.js +++ /dev/null @@ -1,825 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("css", function(config, parserConfig) { - var inline = parserConfig.inline - if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css"); - - var indentUnit = config.indentUnit, - tokenHooks = parserConfig.tokenHooks, - documentTypes = parserConfig.documentTypes || {}, - mediaTypes = parserConfig.mediaTypes || {}, - mediaFeatures = parserConfig.mediaFeatures || {}, - mediaValueKeywords = parserConfig.mediaValueKeywords || {}, - propertyKeywords = parserConfig.propertyKeywords || {}, - nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {}, - fontProperties = parserConfig.fontProperties || {}, - counterDescriptors = parserConfig.counterDescriptors || {}, - colorKeywords = parserConfig.colorKeywords || {}, - valueKeywords = parserConfig.valueKeywords || {}, - allowNested = parserConfig.allowNested, - supportsAtComponent = parserConfig.supportsAtComponent === true; - - var type, override; - function ret(style, tp) { type = tp; return style; } - - // Tokenizers - - function tokenBase(stream, state) { - var ch = stream.next(); - if (tokenHooks[ch]) { - var result = tokenHooks[ch](stream, state); - if (result !== false) return result; - } - if (ch == "@") { - stream.eatWhile(/[\w\\\-]/); - return ret("def", stream.current()); - } else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) { - return ret(null, "compare"); - } else if (ch == "\"" || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } else if (ch == "#") { - stream.eatWhile(/[\w\\\-]/); - return ret("atom", "hash"); - } else if (ch == "!") { - stream.match(/^\s*\w*/); - return ret("keyword", "important"); - } else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) { - stream.eatWhile(/[\w.%]/); - return ret("number", "unit"); - } else if (ch === "-") { - if (/[\d.]/.test(stream.peek())) { - stream.eatWhile(/[\w.%]/); - return ret("number", "unit"); - } else if (stream.match(/^-[\w\\\-]+/)) { - stream.eatWhile(/[\w\\\-]/); - if (stream.match(/^\s*:/, false)) - return ret("variable-2", "variable-definition"); - return ret("variable-2", "variable"); - } else if (stream.match(/^\w+-/)) { - return ret("meta", "meta"); - } - } else if (/[,+>*\/]/.test(ch)) { - return ret(null, "select-op"); - } else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) { - return ret("qualifier", "qualifier"); - } else if (/[:;{}\[\]\(\)]/.test(ch)) { - return ret(null, ch); - } else if ((ch == "u" && stream.match(/rl(-prefix)?\(/)) || - (ch == "d" && stream.match("omain(")) || - (ch == "r" && stream.match("egexp("))) { - stream.backUp(1); - state.tokenize = tokenParenthesized; - return ret("property", "word"); - } else if (/[\w\\\-]/.test(ch)) { - stream.eatWhile(/[\w\\\-]/); - return ret("property", "word"); - } else { - return ret(null, null); - } - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) { - if (quote == ")") stream.backUp(1); - break; - } - escaped = !escaped && ch == "\\"; - } - if (ch == quote || !escaped && quote != ")") state.tokenize = null; - return ret("string", "string"); - }; - } - - function tokenParenthesized(stream, state) { - stream.next(); // Must be '(' - if (!stream.match(/\s*[\"\')]/, false)) - state.tokenize = tokenString(")"); - else - state.tokenize = null; - return ret(null, "("); - } - - // Context management - - function Context(type, indent, prev) { - this.type = type; - this.indent = indent; - this.prev = prev; - } - - function pushContext(state, stream, type, indent) { - state.context = new Context(type, stream.indentation() + (indent === false ? 0 : indentUnit), state.context); - return type; - } - - function popContext(state) { - if (state.context.prev) - state.context = state.context.prev; - return state.context.type; - } - - function pass(type, stream, state) { - return states[state.context.type](type, stream, state); - } - function popAndPass(type, stream, state, n) { - for (var i = n || 1; i > 0; i--) - state.context = state.context.prev; - return pass(type, stream, state); - } - - // Parser - - function wordAsValue(stream) { - var word = stream.current().toLowerCase(); - if (valueKeywords.hasOwnProperty(word)) - override = "atom"; - else if (colorKeywords.hasOwnProperty(word)) - override = "keyword"; - else - override = "variable"; - } - - var states = {}; - - states.top = function(type, stream, state) { - if (type == "{") { - return pushContext(state, stream, "block"); - } else if (type == "}" && state.context.prev) { - return popContext(state); - } else if (supportsAtComponent && /@component/.test(type)) { - return pushContext(state, stream, "atComponentBlock"); - } else if (/^@(-moz-)?document$/.test(type)) { - return pushContext(state, stream, "documentTypes"); - } else if (/^@(media|supports|(-moz-)?document|import)$/.test(type)) { - return pushContext(state, stream, "atBlock"); - } else if (/^@(font-face|counter-style)/.test(type)) { - state.stateArg = type; - return "restricted_atBlock_before"; - } else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) { - return "keyframes"; - } else if (type && type.charAt(0) == "@") { - return pushContext(state, stream, "at"); - } else if (type == "hash") { - override = "builtin"; - } else if (type == "word") { - override = "tag"; - } else if (type == "variable-definition") { - return "maybeprop"; - } else if (type == "interpolation") { - return pushContext(state, stream, "interpolation"); - } else if (type == ":") { - return "pseudo"; - } else if (allowNested && type == "(") { - return pushContext(state, stream, "parens"); - } - return state.context.type; - }; - - states.block = function(type, stream, state) { - if (type == "word") { - var word = stream.current().toLowerCase(); - if (propertyKeywords.hasOwnProperty(word)) { - override = "property"; - return "maybeprop"; - } else if (nonStandardPropertyKeywords.hasOwnProperty(word)) { - override = "string-2"; - return "maybeprop"; - } else if (allowNested) { - override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag"; - return "block"; - } else { - override += " error"; - return "maybeprop"; - } - } else if (type == "meta") { - return "block"; - } else if (!allowNested && (type == "hash" || type == "qualifier")) { - override = "error"; - return "block"; - } else { - return states.top(type, stream, state); - } - }; - - states.maybeprop = function(type, stream, state) { - if (type == ":") return pushContext(state, stream, "prop"); - return pass(type, stream, state); - }; - - states.prop = function(type, stream, state) { - if (type == ";") return popContext(state); - if (type == "{" && allowNested) return pushContext(state, stream, "propBlock"); - if (type == "}" || type == "{") return popAndPass(type, stream, state); - if (type == "(") return pushContext(state, stream, "parens"); - - if (type == "hash" && !/^#([0-9a-fA-f]{3,4}|[0-9a-fA-f]{6}|[0-9a-fA-f]{8})$/.test(stream.current())) { - override += " error"; - } else if (type == "word") { - wordAsValue(stream); - } else if (type == "interpolation") { - return pushContext(state, stream, "interpolation"); - } - return "prop"; - }; - - states.propBlock = function(type, _stream, state) { - if (type == "}") return popContext(state); - if (type == "word") { override = "property"; return "maybeprop"; } - return state.context.type; - }; - - states.parens = function(type, stream, state) { - if (type == "{" || type == "}") return popAndPass(type, stream, state); - if (type == ")") return popContext(state); - if (type == "(") return pushContext(state, stream, "parens"); - if (type == "interpolation") return pushContext(state, stream, "interpolation"); - if (type == "word") wordAsValue(stream); - return "parens"; - }; - - states.pseudo = function(type, stream, state) { - if (type == "word") { - override = "variable-3"; - return state.context.type; - } - return pass(type, stream, state); - }; - - states.documentTypes = function(type, stream, state) { - if (type == "word" && documentTypes.hasOwnProperty(stream.current())) { - override = "tag"; - return state.context.type; - } else { - return states.atBlock(type, stream, state); - } - }; - - states.atBlock = function(type, stream, state) { - if (type == "(") return pushContext(state, stream, "atBlock_parens"); - if (type == "}" || type == ";") return popAndPass(type, stream, state); - if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top"); - - if (type == "interpolation") return pushContext(state, stream, "interpolation"); - - if (type == "word") { - var word = stream.current().toLowerCase(); - if (word == "only" || word == "not" || word == "and" || word == "or") - override = "keyword"; - else if (mediaTypes.hasOwnProperty(word)) - override = "attribute"; - else if (mediaFeatures.hasOwnProperty(word)) - override = "property"; - else if (mediaValueKeywords.hasOwnProperty(word)) - override = "keyword"; - else if (propertyKeywords.hasOwnProperty(word)) - override = "property"; - else if (nonStandardPropertyKeywords.hasOwnProperty(word)) - override = "string-2"; - else if (valueKeywords.hasOwnProperty(word)) - override = "atom"; - else if (colorKeywords.hasOwnProperty(word)) - override = "keyword"; - else - override = "error"; - } - return state.context.type; - }; - - states.atComponentBlock = function(type, stream, state) { - if (type == "}") - return popAndPass(type, stream, state); - if (type == "{") - return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top", false); - if (type == "word") - override = "error"; - return state.context.type; - }; - - states.atBlock_parens = function(type, stream, state) { - if (type == ")") return popContext(state); - if (type == "{" || type == "}") return popAndPass(type, stream, state, 2); - return states.atBlock(type, stream, state); - }; - - states.restricted_atBlock_before = function(type, stream, state) { - if (type == "{") - return pushContext(state, stream, "restricted_atBlock"); - if (type == "word" && state.stateArg == "@counter-style") { - override = "variable"; - return "restricted_atBlock_before"; - } - return pass(type, stream, state); - }; - - states.restricted_atBlock = function(type, stream, state) { - if (type == "}") { - state.stateArg = null; - return popContext(state); - } - if (type == "word") { - if ((state.stateArg == "@font-face" && !fontProperties.hasOwnProperty(stream.current().toLowerCase())) || - (state.stateArg == "@counter-style" && !counterDescriptors.hasOwnProperty(stream.current().toLowerCase()))) - override = "error"; - else - override = "property"; - return "maybeprop"; - } - return "restricted_atBlock"; - }; - - states.keyframes = function(type, stream, state) { - if (type == "word") { override = "variable"; return "keyframes"; } - if (type == "{") return pushContext(state, stream, "top"); - return pass(type, stream, state); - }; - - states.at = function(type, stream, state) { - if (type == ";") return popContext(state); - if (type == "{" || type == "}") return popAndPass(type, stream, state); - if (type == "word") override = "tag"; - else if (type == "hash") override = "builtin"; - return "at"; - }; - - states.interpolation = function(type, stream, state) { - if (type == "}") return popContext(state); - if (type == "{" || type == ";") return popAndPass(type, stream, state); - if (type == "word") override = "variable"; - else if (type != "variable" && type != "(" && type != ")") override = "error"; - return "interpolation"; - }; - - return { - startState: function(base) { - return {tokenize: null, - state: inline ? "block" : "top", - stateArg: null, - context: new Context(inline ? "block" : "top", base || 0, null)}; - }, - - token: function(stream, state) { - if (!state.tokenize && stream.eatSpace()) return null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style && typeof style == "object") { - type = style[1]; - style = style[0]; - } - override = style; - state.state = states[state.state](type, stream, state); - return override; - }, - - indent: function(state, textAfter) { - var cx = state.context, ch = textAfter && textAfter.charAt(0); - var indent = cx.indent; - if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev; - if (cx.prev) { - if (ch == "}" && (cx.type == "block" || cx.type == "top" || - cx.type == "interpolation" || cx.type == "restricted_atBlock")) { - // Resume indentation from parent context. - cx = cx.prev; - indent = cx.indent; - } else if (ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") || - ch == "{" && (cx.type == "at" || cx.type == "atBlock")) { - // Dedent relative to current context. - indent = Math.max(0, cx.indent - indentUnit); - cx = cx.prev; - } - } - return indent; - }, - - electricChars: "}", - blockCommentStart: "/*", - blockCommentEnd: "*/", - fold: "brace" - }; -}); - - function keySet(array) { - var keys = {}; - for (var i = 0; i < array.length; ++i) { - keys[array[i].toLowerCase()] = true; - } - return keys; - } - - var documentTypes_ = [ - "domain", "regexp", "url", "url-prefix" - ], documentTypes = keySet(documentTypes_); - - var mediaTypes_ = [ - "all", "aural", "braille", "handheld", "print", "projection", "screen", - "tty", "tv", "embossed" - ], mediaTypes = keySet(mediaTypes_); - - var mediaFeatures_ = [ - "width", "min-width", "max-width", "height", "min-height", "max-height", - "device-width", "min-device-width", "max-device-width", "device-height", - "min-device-height", "max-device-height", "aspect-ratio", - "min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio", - "min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color", - "max-color", "color-index", "min-color-index", "max-color-index", - "monochrome", "min-monochrome", "max-monochrome", "resolution", - "min-resolution", "max-resolution", "scan", "grid", "orientation", - "device-pixel-ratio", "min-device-pixel-ratio", "max-device-pixel-ratio", - "pointer", "any-pointer", "hover", "any-hover" - ], mediaFeatures = keySet(mediaFeatures_); - - var mediaValueKeywords_ = [ - "landscape", "portrait", "none", "coarse", "fine", "on-demand", "hover", - "interlace", "progressive" - ], mediaValueKeywords = keySet(mediaValueKeywords_); - - var propertyKeywords_ = [ - "align-content", "align-items", "align-self", "alignment-adjust", - "alignment-baseline", "anchor-point", "animation", "animation-delay", - "animation-direction", "animation-duration", "animation-fill-mode", - "animation-iteration-count", "animation-name", "animation-play-state", - "animation-timing-function", "appearance", "azimuth", "backface-visibility", - "background", "background-attachment", "background-blend-mode", "background-clip", - "background-color", "background-image", "background-origin", "background-position", - "background-repeat", "background-size", "baseline-shift", "binding", - "bleed", "bookmark-label", "bookmark-level", "bookmark-state", - "bookmark-target", "border", "border-bottom", "border-bottom-color", - "border-bottom-left-radius", "border-bottom-right-radius", - "border-bottom-style", "border-bottom-width", "border-collapse", - "border-color", "border-image", "border-image-outset", - "border-image-repeat", "border-image-slice", "border-image-source", - "border-image-width", "border-left", "border-left-color", - "border-left-style", "border-left-width", "border-radius", "border-right", - "border-right-color", "border-right-style", "border-right-width", - "border-spacing", "border-style", "border-top", "border-top-color", - "border-top-left-radius", "border-top-right-radius", "border-top-style", - "border-top-width", "border-width", "bottom", "box-decoration-break", - "box-shadow", "box-sizing", "break-after", "break-before", "break-inside", - "caption-side", "clear", "clip", "color", "color-profile", "column-count", - "column-fill", "column-gap", "column-rule", "column-rule-color", - "column-rule-style", "column-rule-width", "column-span", "column-width", - "columns", "content", "counter-increment", "counter-reset", "crop", "cue", - "cue-after", "cue-before", "cursor", "direction", "display", - "dominant-baseline", "drop-initial-after-adjust", - "drop-initial-after-align", "drop-initial-before-adjust", - "drop-initial-before-align", "drop-initial-size", "drop-initial-value", - "elevation", "empty-cells", "fit", "fit-position", "flex", "flex-basis", - "flex-direction", "flex-flow", "flex-grow", "flex-shrink", "flex-wrap", - "float", "float-offset", "flow-from", "flow-into", "font", "font-feature-settings", - "font-family", "font-kerning", "font-language-override", "font-size", "font-size-adjust", - "font-stretch", "font-style", "font-synthesis", "font-variant", - "font-variant-alternates", "font-variant-caps", "font-variant-east-asian", - "font-variant-ligatures", "font-variant-numeric", "font-variant-position", - "font-weight", "grid", "grid-area", "grid-auto-columns", "grid-auto-flow", - "grid-auto-rows", "grid-column", "grid-column-end", "grid-column-gap", - "grid-column-start", "grid-gap", "grid-row", "grid-row-end", "grid-row-gap", - "grid-row-start", "grid-template", "grid-template-areas", "grid-template-columns", - "grid-template-rows", "hanging-punctuation", "height", "hyphens", - "icon", "image-orientation", "image-rendering", "image-resolution", - "inline-box-align", "justify-content", "left", "letter-spacing", - "line-break", "line-height", "line-stacking", "line-stacking-ruby", - "line-stacking-shift", "line-stacking-strategy", "list-style", - "list-style-image", "list-style-position", "list-style-type", "margin", - "margin-bottom", "margin-left", "margin-right", "margin-top", - "marks", "marquee-direction", "marquee-loop", - "marquee-play-count", "marquee-speed", "marquee-style", "max-height", - "max-width", "min-height", "min-width", "move-to", "nav-down", "nav-index", - "nav-left", "nav-right", "nav-up", "object-fit", "object-position", - "opacity", "order", "orphans", "outline", - "outline-color", "outline-offset", "outline-style", "outline-width", - "overflow", "overflow-style", "overflow-wrap", "overflow-x", "overflow-y", - "padding", "padding-bottom", "padding-left", "padding-right", "padding-top", - "page", "page-break-after", "page-break-before", "page-break-inside", - "page-policy", "pause", "pause-after", "pause-before", "perspective", - "perspective-origin", "pitch", "pitch-range", "play-during", "position", - "presentation-level", "punctuation-trim", "quotes", "region-break-after", - "region-break-before", "region-break-inside", "region-fragment", - "rendering-intent", "resize", "rest", "rest-after", "rest-before", "richness", - "right", "rotation", "rotation-point", "ruby-align", "ruby-overhang", - "ruby-position", "ruby-span", "shape-image-threshold", "shape-inside", "shape-margin", - "shape-outside", "size", "speak", "speak-as", "speak-header", - "speak-numeral", "speak-punctuation", "speech-rate", "stress", "string-set", - "tab-size", "table-layout", "target", "target-name", "target-new", - "target-position", "text-align", "text-align-last", "text-decoration", - "text-decoration-color", "text-decoration-line", "text-decoration-skip", - "text-decoration-style", "text-emphasis", "text-emphasis-color", - "text-emphasis-position", "text-emphasis-style", "text-height", - "text-indent", "text-justify", "text-outline", "text-overflow", "text-shadow", - "text-size-adjust", "text-space-collapse", "text-transform", "text-underline-position", - "text-wrap", "top", "transform", "transform-origin", "transform-style", - "transition", "transition-delay", "transition-duration", - "transition-property", "transition-timing-function", "unicode-bidi", - "user-select", "vertical-align", "visibility", "voice-balance", "voice-duration", - "voice-family", "voice-pitch", "voice-range", "voice-rate", "voice-stress", - "voice-volume", "volume", "white-space", "widows", "width", "will-change", "word-break", - "word-spacing", "word-wrap", "z-index", - // SVG-specific - "clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color", - "flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events", - "color-interpolation", "color-interpolation-filters", - "color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering", - "marker", "marker-end", "marker-mid", "marker-start", "shape-rendering", "stroke", - "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", - "stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering", - "baseline-shift", "dominant-baseline", "glyph-orientation-horizontal", - "glyph-orientation-vertical", "text-anchor", "writing-mode" - ], propertyKeywords = keySet(propertyKeywords_); - - var nonStandardPropertyKeywords_ = [ - "scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color", - "scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color", - "scrollbar-3d-light-color", "scrollbar-track-color", "shape-inside", - "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button", - "searchfield-results-decoration", "zoom" - ], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_); - - var fontProperties_ = [ - "font-family", "src", "unicode-range", "font-variant", "font-feature-settings", - "font-stretch", "font-weight", "font-style" - ], fontProperties = keySet(fontProperties_); - - var counterDescriptors_ = [ - "additive-symbols", "fallback", "negative", "pad", "prefix", "range", - "speak-as", "suffix", "symbols", "system" - ], counterDescriptors = keySet(counterDescriptors_); - - var colorKeywords_ = [ - "aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige", - "bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown", - "burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue", - "cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod", - "darkgray", "darkgreen", "darkkhaki", "darkmagenta", "darkolivegreen", - "darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen", - "darkslateblue", "darkslategray", "darkturquoise", "darkviolet", - "deeppink", "deepskyblue", "dimgray", "dodgerblue", "firebrick", - "floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite", - "gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew", - "hotpink", "indianred", "indigo", "ivory", "khaki", "lavender", - "lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral", - "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightpink", - "lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", - "lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta", - "maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple", - "mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise", - "mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin", - "navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered", - "orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred", - "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue", - "purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown", - "salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue", - "slateblue", "slategray", "snow", "springgreen", "steelblue", "tan", - "teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white", - "whitesmoke", "yellow", "yellowgreen" - ], colorKeywords = keySet(colorKeywords_); - - var valueKeywords_ = [ - "above", "absolute", "activeborder", "additive", "activecaption", "afar", - "after-white-space", "ahead", "alias", "all", "all-scroll", "alphabetic", "alternate", - "always", "amharic", "amharic-abegede", "antialiased", "appworkspace", - "arabic-indic", "armenian", "asterisks", "attr", "auto", "auto-flow", "avoid", "avoid-column", "avoid-page", - "avoid-region", "background", "backwards", "baseline", "below", "bidi-override", "binary", - "bengali", "blink", "block", "block-axis", "bold", "bolder", "border", "border-box", - "both", "bottom", "break", "break-all", "break-word", "bullets", "button", "button-bevel", - "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "cambodian", - "capitalize", "caps-lock-indicator", "caption", "captiontext", "caret", - "cell", "center", "checkbox", "circle", "cjk-decimal", "cjk-earthly-branch", - "cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote", - "col-resize", "collapse", "color", "color-burn", "color-dodge", "column", "column-reverse", - "compact", "condensed", "contain", "content", "contents", - "content-box", "context-menu", "continuous", "copy", "counter", "counters", "cover", "crop", - "cross", "crosshair", "currentcolor", "cursive", "cyclic", "darken", "dashed", "decimal", - "decimal-leading-zero", "default", "default-button", "dense", "destination-atop", - "destination-in", "destination-out", "destination-over", "devanagari", "difference", - "disc", "discard", "disclosure-closed", "disclosure-open", "document", - "dot-dash", "dot-dot-dash", - "dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out", - "element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede", - "ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er", - "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er", - "ethiopic-halehame-aa-et", "ethiopic-halehame-am-et", - "ethiopic-halehame-gez", "ethiopic-halehame-om-et", - "ethiopic-halehame-sid-et", "ethiopic-halehame-so-et", - "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig", - "ethiopic-numeric", "ew-resize", "exclusion", "expanded", "extends", "extra-condensed", - "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes", - "forwards", "from", "geometricPrecision", "georgian", "graytext", "grid", "groove", - "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hard-light", "hebrew", - "help", "hidden", "hide", "higher", "highlight", "highlighttext", - "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "hue", "icon", "ignore", - "inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite", - "infobackground", "infotext", "inherit", "initial", "inline", "inline-axis", - "inline-block", "inline-flex", "inline-grid", "inline-table", "inset", "inside", "intrinsic", "invert", - "italic", "japanese-formal", "japanese-informal", "justify", "kannada", - "katakana", "katakana-iroha", "keep-all", "khmer", - "korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal", - "landscape", "lao", "large", "larger", "left", "level", "lighter", "lighten", - "line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem", - "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian", - "lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian", - "lower-roman", "lowercase", "ltr", "luminosity", "malayalam", "match", "matrix", "matrix3d", - "media-controls-background", "media-current-time-display", - "media-fullscreen-button", "media-mute-button", "media-play-button", - "media-return-to-realtime-button", "media-rewind-button", - "media-seek-back-button", "media-seek-forward-button", "media-slider", - "media-sliderthumb", "media-time-remaining-display", "media-volume-slider", - "media-volume-slider-container", "media-volume-sliderthumb", "medium", - "menu", "menulist", "menulist-button", "menulist-text", - "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic", - "mix", "mongolian", "monospace", "move", "multiple", "multiply", "myanmar", "n-resize", - "narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop", - "no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap", - "ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "opacity", "open-quote", - "optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset", - "outside", "outside-shape", "overlay", "overline", "padding", "padding-box", - "painted", "page", "paused", "persian", "perspective", "plus-darker", "plus-lighter", - "pointer", "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d", - "progress", "push-button", "radial-gradient", "radio", "read-only", - "read-write", "read-write-plaintext-only", "rectangle", "region", - "relative", "repeat", "repeating-linear-gradient", - "repeating-radial-gradient", "repeat-x", "repeat-y", "reset", "reverse", - "rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY", - "rotateZ", "round", "row", "row-resize", "row-reverse", "rtl", "run-in", "running", - "s-resize", "sans-serif", "saturation", "scale", "scale3d", "scaleX", "scaleY", "scaleZ", "screen", - "scroll", "scrollbar", "scroll-position", "se-resize", "searchfield", - "searchfield-cancel-button", "searchfield-decoration", - "searchfield-results-button", "searchfield-results-decoration", - "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama", - "simp-chinese-formal", "simp-chinese-informal", "single", - "skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal", - "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow", - "small", "small-caps", "small-caption", "smaller", "soft-light", "solid", "somali", - "source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "spell-out", "square", - "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub", - "subpixel-antialiased", "super", "sw-resize", "symbolic", "symbols", "table", - "table-caption", "table-cell", "table-column", "table-column-group", - "table-footer-group", "table-header-group", "table-row", "table-row-group", - "tamil", - "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai", - "thick", "thin", "threeddarkshadow", "threedface", "threedhighlight", - "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er", - "tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top", - "trad-chinese-formal", "trad-chinese-informal", "transform", - "translate", "translate3d", "translateX", "translateY", "translateZ", - "transparent", "ultra-condensed", "ultra-expanded", "underline", "unset", "up", - "upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal", - "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url", - "var", "vertical", "vertical-text", "visible", "visibleFill", "visiblePainted", - "visibleStroke", "visual", "w-resize", "wait", "wave", "wider", - "window", "windowframe", "windowtext", "words", "wrap", "wrap-reverse", "x-large", "x-small", "xor", - "xx-large", "xx-small" - ], valueKeywords = keySet(valueKeywords_); - - var allWords = documentTypes_.concat(mediaTypes_).concat(mediaFeatures_).concat(mediaValueKeywords_) - .concat(propertyKeywords_).concat(nonStandardPropertyKeywords_).concat(colorKeywords_) - .concat(valueKeywords_); - CodeMirror.registerHelper("hintWords", "css", allWords); - - function tokenCComment(stream, state) { - var maybeEnd = false, ch; - while ((ch = stream.next()) != null) { - if (maybeEnd && ch == "/") { - state.tokenize = null; - break; - } - maybeEnd = (ch == "*"); - } - return ["comment", "comment"]; - } - - CodeMirror.defineMIME("text/css", { - documentTypes: documentTypes, - mediaTypes: mediaTypes, - mediaFeatures: mediaFeatures, - mediaValueKeywords: mediaValueKeywords, - propertyKeywords: propertyKeywords, - nonStandardPropertyKeywords: nonStandardPropertyKeywords, - fontProperties: fontProperties, - counterDescriptors: counterDescriptors, - colorKeywords: colorKeywords, - valueKeywords: valueKeywords, - tokenHooks: { - "/": function(stream, state) { - if (!stream.eat("*")) return false; - state.tokenize = tokenCComment; - return tokenCComment(stream, state); - } - }, - name: "css" - }); - - CodeMirror.defineMIME("text/x-scss", { - mediaTypes: mediaTypes, - mediaFeatures: mediaFeatures, - mediaValueKeywords: mediaValueKeywords, - propertyKeywords: propertyKeywords, - nonStandardPropertyKeywords: nonStandardPropertyKeywords, - colorKeywords: colorKeywords, - valueKeywords: valueKeywords, - fontProperties: fontProperties, - allowNested: true, - tokenHooks: { - "/": function(stream, state) { - if (stream.eat("/")) { - stream.skipToEnd(); - return ["comment", "comment"]; - } else if (stream.eat("*")) { - state.tokenize = tokenCComment; - return tokenCComment(stream, state); - } else { - return ["operator", "operator"]; - } - }, - ":": function(stream) { - if (stream.match(/\s*\{/)) - return [null, "{"]; - return false; - }, - "$": function(stream) { - stream.match(/^[\w-]+/); - if (stream.match(/^\s*:/, false)) - return ["variable-2", "variable-definition"]; - return ["variable-2", "variable"]; - }, - "#": function(stream) { - if (!stream.eat("{")) return false; - return [null, "interpolation"]; - } - }, - name: "css", - helperType: "scss" - }); - - CodeMirror.defineMIME("text/x-less", { - mediaTypes: mediaTypes, - mediaFeatures: mediaFeatures, - mediaValueKeywords: mediaValueKeywords, - propertyKeywords: propertyKeywords, - nonStandardPropertyKeywords: nonStandardPropertyKeywords, - colorKeywords: colorKeywords, - valueKeywords: valueKeywords, - fontProperties: fontProperties, - allowNested: true, - tokenHooks: { - "/": function(stream, state) { - if (stream.eat("/")) { - stream.skipToEnd(); - return ["comment", "comment"]; - } else if (stream.eat("*")) { - state.tokenize = tokenCComment; - return tokenCComment(stream, state); - } else { - return ["operator", "operator"]; - } - }, - "@": function(stream) { - if (stream.eat("{")) return [null, "interpolation"]; - if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/, false)) return false; - stream.eatWhile(/[\w\\\-]/); - if (stream.match(/^\s*:/, false)) - return ["variable-2", "variable-definition"]; - return ["variable-2", "variable"]; - }, - "&": function() { - return ["atom", "atom"]; - } - }, - name: "css", - helperType: "less" - }); - - CodeMirror.defineMIME("text/x-gss", { - documentTypes: documentTypes, - mediaTypes: mediaTypes, - mediaFeatures: mediaFeatures, - propertyKeywords: propertyKeywords, - nonStandardPropertyKeywords: nonStandardPropertyKeywords, - fontProperties: fontProperties, - counterDescriptors: counterDescriptors, - colorKeywords: colorKeywords, - valueKeywords: valueKeywords, - supportsAtComponent: true, - tokenHooks: { - "/": function(stream, state) { - if (!stream.eat("*")) return false; - state.tokenize = tokenCComment; - return tokenCComment(stream, state); - } - }, - name: "css", - helperType: "gss" - }); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/css/gss.html b/backend/_pv_1_3_5/static/codemirror/mode/css/gss.html deleted file mode 100755 index 232fe8c12..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/css/gss.html +++ /dev/null @@ -1,103 +0,0 @@ - - -CodeMirror: Closure Stylesheets (GSS) mode - - - - - - - - - - - - -
    -

    Closure Stylesheets (GSS) mode

    -
    - - -

    A mode for Closure Stylesheets (GSS).

    -

    MIME type defined: text/x-gss.

    - -

    Parsing/Highlighting Tests: normal, verbose.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/css/gss_test.js b/backend/_pv_1_3_5/static/codemirror/mode/css/gss_test.js deleted file mode 100755 index d56e59280..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/css/gss_test.js +++ /dev/null @@ -1,17 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - "use strict"; - - var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-gss"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "gss"); } - - MT("atComponent", - "[def @component] {", - "[tag foo] {", - " [property color]: [keyword black];", - "}", - "}"); - -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/css/index.html b/backend/_pv_1_3_5/static/codemirror/mode/css/index.html deleted file mode 100755 index 2d2b9b073..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/css/index.html +++ /dev/null @@ -1,75 +0,0 @@ - - -CodeMirror: CSS mode - - - - - - - - - - - - -
    -

    CSS mode

    -
    - - -

    MIME types defined: text/css, text/x-scss (demo), text/x-less (demo).

    - -

    Parsing/Highlighting Tests: normal, verbose.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/css/less.html b/backend/_pv_1_3_5/static/codemirror/mode/css/less.html deleted file mode 100755 index adf7427d3..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/css/less.html +++ /dev/null @@ -1,152 +0,0 @@ - - -CodeMirror: LESS mode - - - - - - - - - - -
    -

    LESS mode

    -
    - - -

    The LESS mode is a sub-mode of the CSS mode (defined in css.js).

    - -

    Parsing/Highlighting Tests: normal, verbose.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/css/less_test.js b/backend/_pv_1_3_5/static/codemirror/mode/css/less_test.js deleted file mode 100755 index dd821558b..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/css/less_test.js +++ /dev/null @@ -1,54 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - "use strict"; - - var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-less"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "less"); } - - MT("variable", - "[variable-2 @base]: [atom #f04615];", - "[qualifier .class] {", - " [property width]: [variable percentage]([number 0.5]); [comment // returns `50%`]", - " [property color]: [variable saturate]([variable-2 @base], [number 5%]);", - "}"); - - MT("amp", - "[qualifier .child], [qualifier .sibling] {", - " [qualifier .parent] [atom &] {", - " [property color]: [keyword black];", - " }", - " [atom &] + [atom &] {", - " [property color]: [keyword red];", - " }", - "}"); - - MT("mixin", - "[qualifier .mixin] ([variable dark]; [variable-2 @color]) {", - " [property color]: [atom darken]([variable-2 @color], [number 10%]);", - "}", - "[qualifier .mixin] ([variable light]; [variable-2 @color]) {", - " [property color]: [atom lighten]([variable-2 @color], [number 10%]);", - "}", - "[qualifier .mixin] ([variable-2 @_]; [variable-2 @color]) {", - " [property display]: [atom block];", - "}", - "[variable-2 @switch]: [variable light];", - "[qualifier .class] {", - " [qualifier .mixin]([variable-2 @switch]; [atom #888]);", - "}"); - - MT("nest", - "[qualifier .one] {", - " [def @media] ([property width]: [number 400px]) {", - " [property font-size]: [number 1.2em];", - " [def @media] [attribute print] [keyword and] [property color] {", - " [property color]: [keyword blue];", - " }", - " }", - "}"); - - - MT("interpolation", ".@{[variable foo]} { [property font-weight]: [atom bold]; }"); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/css/scss.html b/backend/_pv_1_3_5/static/codemirror/mode/css/scss.html deleted file mode 100755 index f8e4d3736..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/css/scss.html +++ /dev/null @@ -1,157 +0,0 @@ - - -CodeMirror: SCSS mode - - - - - - - - - -
    -

    SCSS mode

    -
    - - -

    The SCSS mode is a sub-mode of the CSS mode (defined in css.js).

    - -

    Parsing/Highlighting Tests: normal, verbose.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/css/scss_test.js b/backend/_pv_1_3_5/static/codemirror/mode/css/scss_test.js deleted file mode 100755 index 785921b39..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/css/scss_test.js +++ /dev/null @@ -1,110 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-scss"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); } - - MT('url_with_quotation', - "[tag foo] { [property background]:[atom url]([string test.jpg]) }"); - - MT('url_with_double_quotes', - "[tag foo] { [property background]:[atom url]([string \"test.jpg\"]) }"); - - MT('url_with_single_quotes', - "[tag foo] { [property background]:[atom url]([string \'test.jpg\']) }"); - - MT('string', - "[def @import] [string \"compass/css3\"]"); - - MT('important_keyword', - "[tag foo] { [property background]:[atom url]([string \'test.jpg\']) [keyword !important] }"); - - MT('variable', - "[variable-2 $blue]:[atom #333]"); - - MT('variable_as_attribute', - "[tag foo] { [property color]:[variable-2 $blue] }"); - - MT('numbers', - "[tag foo] { [property padding]:[number 10px] [number 10] [number 10em] [number 8in] }"); - - MT('number_percentage', - "[tag foo] { [property width]:[number 80%] }"); - - MT('selector', - "[builtin #hello][qualifier .world]{}"); - - MT('singleline_comment', - "[comment // this is a comment]"); - - MT('multiline_comment', - "[comment /*foobar*/]"); - - MT('attribute_with_hyphen', - "[tag foo] { [property font-size]:[number 10px] }"); - - MT('string_after_attribute', - "[tag foo] { [property content]:[string \"::\"] }"); - - MT('directives', - "[def @include] [qualifier .mixin]"); - - MT('basic_structure', - "[tag p] { [property background]:[keyword red]; }"); - - MT('nested_structure', - "[tag p] { [tag a] { [property color]:[keyword red]; } }"); - - MT('mixin', - "[def @mixin] [tag table-base] {}"); - - MT('number_without_semicolon', - "[tag p] {[property width]:[number 12]}", - "[tag a] {[property color]:[keyword red];}"); - - MT('atom_in_nested_block', - "[tag p] { [tag a] { [property color]:[atom #000]; } }"); - - MT('interpolation_in_property', - "[tag foo] { #{[variable-2 $hello]}:[number 2]; }"); - - MT('interpolation_in_selector', - "[tag foo]#{[variable-2 $hello]} { [property color]:[atom #000]; }"); - - MT('interpolation_error', - "[tag foo]#{[variable foo]} { [property color]:[atom #000]; }"); - - MT("divide_operator", - "[tag foo] { [property width]:[number 4] [operator /] [number 2] }"); - - MT('nested_structure_with_id_selector', - "[tag p] { [builtin #hello] { [property color]:[keyword red]; } }"); - - MT('indent_mixin', - "[def @mixin] [tag container] (", - " [variable-2 $a]: [number 10],", - " [variable-2 $b]: [number 10])", - "{}"); - - MT('indent_nested', - "[tag foo] {", - " [tag bar] {", - " }", - "}"); - - MT('indent_parentheses', - "[tag foo] {", - " [property color]: [atom darken]([variable-2 $blue],", - " [number 9%]);", - "}"); - - MT('indent_vardef', - "[variable-2 $name]:", - " [string 'val'];", - "[tag tag] {", - " [tag inner] {", - " [property margin]: [number 3px];", - " }", - "}"); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/css/test.js b/backend/_pv_1_3_5/static/codemirror/mode/css/test.js deleted file mode 100755 index 7a496fb09..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/css/test.js +++ /dev/null @@ -1,200 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "css"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - // Error, because "foobarhello" is neither a known type or property, but - // property was expected (after "and"), and it should be in parentheses. - MT("atMediaUnknownType", - "[def @media] [attribute screen] [keyword and] [error foobarhello] { }"); - - // Soft error, because "foobarhello" is not a known property or type. - MT("atMediaUnknownProperty", - "[def @media] [attribute screen] [keyword and] ([error foobarhello]) { }"); - - // Make sure nesting works with media queries - MT("atMediaMaxWidthNested", - "[def @media] [attribute screen] [keyword and] ([property max-width]: [number 25px]) { [tag foo] { } }"); - - MT("atMediaFeatureValueKeyword", - "[def @media] ([property orientation]: [keyword landscape]) { }"); - - MT("atMediaUnknownFeatureValueKeyword", - "[def @media] ([property orientation]: [error upsidedown]) { }"); - - MT("tagSelector", - "[tag foo] { }"); - - MT("classSelector", - "[qualifier .foo-bar_hello] { }"); - - MT("idSelector", - "[builtin #foo] { [error #foo] }"); - - MT("tagSelectorUnclosed", - "[tag foo] { [property margin]: [number 0] } [tag bar] { }"); - - MT("tagStringNoQuotes", - "[tag foo] { [property font-family]: [variable hello] [variable world]; }"); - - MT("tagStringDouble", - "[tag foo] { [property font-family]: [string \"hello world\"]; }"); - - MT("tagStringSingle", - "[tag foo] { [property font-family]: [string 'hello world']; }"); - - MT("tagColorKeyword", - "[tag foo] {", - " [property color]: [keyword black];", - " [property color]: [keyword navy];", - " [property color]: [keyword yellow];", - "}"); - - MT("tagColorHex3", - "[tag foo] { [property background]: [atom #fff]; }"); - - MT("tagColorHex4", - "[tag foo] { [property background]: [atom #ffff]; }"); - - MT("tagColorHex6", - "[tag foo] { [property background]: [atom #ffffff]; }"); - - MT("tagColorHex8", - "[tag foo] { [property background]: [atom #ffffffff]; }"); - - MT("tagColorHex5Invalid", - "[tag foo] { [property background]: [atom&error #fffff]; }"); - - MT("tagColorHexInvalid", - "[tag foo] { [property background]: [atom&error #ffg]; }"); - - MT("tagNegativeNumber", - "[tag foo] { [property margin]: [number -5px]; }"); - - MT("tagPositiveNumber", - "[tag foo] { [property padding]: [number 5px]; }"); - - MT("tagVendor", - "[tag foo] { [meta -foo-][property box-sizing]: [meta -foo-][atom border-box]; }"); - - MT("tagBogusProperty", - "[tag foo] { [property&error barhelloworld]: [number 0]; }"); - - MT("tagTwoProperties", - "[tag foo] { [property margin]: [number 0]; [property padding]: [number 0]; }"); - - MT("tagTwoPropertiesURL", - "[tag foo] { [property background]: [atom url]([string //example.com/foo.png]); [property padding]: [number 0]; }"); - - MT("indent_tagSelector", - "[tag strong], [tag em] {", - " [property background]: [atom rgba](", - " [number 255], [number 255], [number 0], [number .2]", - " );", - "}"); - - MT("indent_atMedia", - "[def @media] {", - " [tag foo] {", - " [property color]:", - " [keyword yellow];", - " }", - "}"); - - MT("indent_comma", - "[tag foo] {", - " [property font-family]: [variable verdana],", - " [atom sans-serif];", - "}"); - - MT("indent_parentheses", - "[tag foo]:[variable-3 before] {", - " [property background]: [atom url](", - "[string blahblah]", - "[string etc]", - "[string ]) [keyword !important];", - "}"); - - MT("font_face", - "[def @font-face] {", - " [property font-family]: [string 'myfont'];", - " [error nonsense]: [string 'abc'];", - " [property src]: [atom url]([string http://blah]),", - " [atom url]([string http://foo]);", - "}"); - - MT("empty_url", - "[def @import] [atom url]() [attribute screen];"); - - MT("parens", - "[qualifier .foo] {", - " [property background-image]: [variable fade]([atom #000], [number 20%]);", - " [property border-image]: [atom linear-gradient](", - " [atom to] [atom bottom],", - " [variable fade]([atom #000], [number 20%]) [number 0%],", - " [variable fade]([atom #000], [number 20%]) [number 100%]", - " );", - "}"); - - MT("css_variable", - ":[variable-3 root] {", - " [variable-2 --main-color]: [atom #06c];", - "}", - "[tag h1][builtin #foo] {", - " [property color]: [atom var]([variable-2 --main-color]);", - "}"); - - MT("supports", - "[def @supports] ([keyword not] (([property text-align-last]: [atom justify]) [keyword or] ([meta -moz-][property text-align-last]: [atom justify])) {", - " [property text-align-last]: [atom justify];", - "}"); - - MT("document", - "[def @document] [tag url]([string http://blah]),", - " [tag url-prefix]([string https://]),", - " [tag domain]([string blah.com]),", - " [tag regexp]([string \".*blah.+\"]) {", - " [builtin #id] {", - " [property background-color]: [keyword white];", - " }", - " [tag foo] {", - " [property font-family]: [variable Verdana], [atom sans-serif];", - " }", - "}"); - - MT("document_url", - "[def @document] [tag url]([string http://blah]) { [qualifier .class] { } }"); - - MT("document_urlPrefix", - "[def @document] [tag url-prefix]([string https://]) { [builtin #id] { } }"); - - MT("document_domain", - "[def @document] [tag domain]([string blah.com]) { [tag foo] { } }"); - - MT("document_regexp", - "[def @document] [tag regexp]([string \".*blah.+\"]) { [builtin #id] { } }"); - - MT("counter-style", - "[def @counter-style] [variable binary] {", - " [property system]: [atom numeric];", - " [property symbols]: [number 0] [number 1];", - " [property suffix]: [string \".\"];", - " [property range]: [atom infinite];", - " [property speak-as]: [atom numeric];", - "}"); - - MT("counter-style-additive-symbols", - "[def @counter-style] [variable simple-roman] {", - " [property system]: [atom additive];", - " [property additive-symbols]: [number 10] [variable X], [number 5] [variable V], [number 1] [variable I];", - " [property range]: [number 1] [number 49];", - "}"); - - MT("counter-style-use", - "[tag ol][qualifier .roman] { [property list-style]: [variable simple-roman]; }"); - - MT("counter-style-symbols", - "[tag ol] { [property list-style]: [atom symbols]([atom cyclic] [string \"*\"] [string \"\\2020\"] [string \"\\2021\"] [string \"\\A7\"]); }"); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/cypher/cypher.js b/backend/_pv_1_3_5/static/codemirror/mode/cypher/cypher.js deleted file mode 100755 index 9b2490014..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/cypher/cypher.js +++ /dev/null @@ -1,150 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// By the Neo4j Team and contributors. -// https://github.com/neo4j-contrib/CodeMirror - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - var wordRegexp = function(words) { - return new RegExp("^(?:" + words.join("|") + ")$", "i"); - }; - - CodeMirror.defineMode("cypher", function(config) { - var tokenBase = function(stream/*, state*/) { - var ch = stream.next(); - if (ch ==='"') { - stream.match(/.*?"/); - return "string"; - } - if (ch === "'") { - stream.match(/.*?'/); - return "string"; - } - if (/[{}\(\),\.;\[\]]/.test(ch)) { - curPunc = ch; - return "node"; - } else if (ch === "/" && stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } else if (operatorChars.test(ch)) { - stream.eatWhile(operatorChars); - return null; - } else { - stream.eatWhile(/[_\w\d]/); - if (stream.eat(":")) { - stream.eatWhile(/[\w\d_\-]/); - return "atom"; - } - var word = stream.current(); - if (funcs.test(word)) return "builtin"; - if (preds.test(word)) return "def"; - if (keywords.test(word)) return "keyword"; - return "variable"; - } - }; - var pushContext = function(state, type, col) { - return state.context = { - prev: state.context, - indent: state.indent, - col: col, - type: type - }; - }; - var popContext = function(state) { - state.indent = state.context.indent; - return state.context = state.context.prev; - }; - var indentUnit = config.indentUnit; - var curPunc; - var funcs = wordRegexp(["abs", "acos", "allShortestPaths", "asin", "atan", "atan2", "avg", "ceil", "coalesce", "collect", "cos", "cot", "count", "degrees", "e", "endnode", "exp", "extract", "filter", "floor", "haversin", "head", "id", "keys", "labels", "last", "left", "length", "log", "log10", "lower", "ltrim", "max", "min", "node", "nodes", "percentileCont", "percentileDisc", "pi", "radians", "rand", "range", "reduce", "rel", "relationship", "relationships", "replace", "reverse", "right", "round", "rtrim", "shortestPath", "sign", "sin", "size", "split", "sqrt", "startnode", "stdev", "stdevp", "str", "substring", "sum", "tail", "tan", "timestamp", "toFloat", "toInt", "toString", "trim", "type", "upper"]); - var preds = wordRegexp(["all", "and", "any", "contains", "exists", "has", "in", "none", "not", "or", "single", "xor"]); - var keywords = wordRegexp(["as", "asc", "ascending", "assert", "by", "case", "commit", "constraint", "create", "csv", "cypher", "delete", "desc", "descending", "detach", "distinct", "drop", "else", "end", "ends", "explain", "false", "fieldterminator", "foreach", "from", "headers", "in", "index", "is", "join", "limit", "load", "match", "merge", "null", "on", "optional", "order", "periodic", "profile", "remove", "return", "scan", "set", "skip", "start", "starts", "then", "true", "union", "unique", "unwind", "using", "when", "where", "with", "call", "yield"]); - var operatorChars = /[*+\-<>=&|~%^]/; - - return { - startState: function(/*base*/) { - return { - tokenize: tokenBase, - context: null, - indent: 0, - col: 0 - }; - }, - token: function(stream, state) { - if (stream.sol()) { - if (state.context && (state.context.align == null)) { - state.context.align = false; - } - state.indent = stream.indentation(); - } - if (stream.eatSpace()) { - return null; - } - var style = state.tokenize(stream, state); - if (style !== "comment" && state.context && (state.context.align == null) && state.context.type !== "pattern") { - state.context.align = true; - } - if (curPunc === "(") { - pushContext(state, ")", stream.column()); - } else if (curPunc === "[") { - pushContext(state, "]", stream.column()); - } else if (curPunc === "{") { - pushContext(state, "}", stream.column()); - } else if (/[\]\}\)]/.test(curPunc)) { - while (state.context && state.context.type === "pattern") { - popContext(state); - } - if (state.context && curPunc === state.context.type) { - popContext(state); - } - } else if (curPunc === "." && state.context && state.context.type === "pattern") { - popContext(state); - } else if (/atom|string|variable/.test(style) && state.context) { - if (/[\}\]]/.test(state.context.type)) { - pushContext(state, "pattern", stream.column()); - } else if (state.context.type === "pattern" && !state.context.align) { - state.context.align = true; - state.context.col = stream.column(); - } - } - return style; - }, - indent: function(state, textAfter) { - var firstChar = textAfter && textAfter.charAt(0); - var context = state.context; - if (/[\]\}]/.test(firstChar)) { - while (context && context.type === "pattern") { - context = context.prev; - } - } - var closing = context && firstChar === context.type; - if (!context) return 0; - if (context.type === "keywords") return CodeMirror.commands.newlineAndIndent; - if (context.align) return context.col + (closing ? 0 : 1); - return context.indent + (closing ? 0 : indentUnit); - } - }; - }); - - CodeMirror.modeExtensions["cypher"] = { - autoFormatLineBreaks: function(text) { - var i, lines, reProcessedPortion; - var lines = text.split("\n"); - var reProcessedPortion = /\s+\b(return|where|order by|match|with|skip|limit|create|delete|set)\b\s/g; - for (var i = 0; i < lines.length; i++) - lines[i] = lines[i].replace(reProcessedPortion, " \n$1 ").trim(); - return lines.join("\n"); - } - }; - - CodeMirror.defineMIME("application/x-cypher-query", "cypher"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/cypher/index.html b/backend/_pv_1_3_5/static/codemirror/mode/cypher/index.html deleted file mode 100755 index b8bd75c8b..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/cypher/index.html +++ /dev/null @@ -1,63 +0,0 @@ - - -CodeMirror: Cypher Mode for CodeMirror - - - - - - - - - - -
    -

    Cypher Mode for CodeMirror

    -
    - -
    -

    MIME types defined: - application/x-cypher-query -

    - - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/cypher/test.js b/backend/_pv_1_3_5/static/codemirror/mode/cypher/test.js deleted file mode 100755 index 76d0d0829..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/cypher/test.js +++ /dev/null @@ -1,37 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, "cypher"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT("unbalancedDoubledQuotedString", - "[string \"a'b\"][variable c]"); - - MT("unbalancedSingleQuotedString", - "[string 'a\"b'][variable c]"); - - MT("doubleQuotedString", - "[string \"a\"][variable b]"); - - MT("singleQuotedString", - "[string 'a'][variable b]"); - - MT("single attribute (with content)", - "[node {][atom a:][string 'a'][node }]"); - - MT("multiple attribute, singleQuotedString (with content)", - "[node {][atom a:][string 'a'][node ,][atom b:][string 'b'][node }]"); - - MT("multiple attribute, doubleQuotedString (with content)", - "[node {][atom a:][string \"a\"][node ,][atom b:][string \"b\"][node }]"); - - MT("single attribute (without content)", - "[node {][atom a:][string 'a'][node }]"); - - MT("multiple attribute, singleQuotedString (without content)", - "[node {][atom a:][string ''][node ,][atom b:][string ''][node }]"); - - MT("multiple attribute, doubleQuotedString (without content)", - "[node {][atom a:][string \"\"][node ,][atom b:][string \"\"][node }]"); - })(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/d/d.js b/backend/_pv_1_3_5/static/codemirror/mode/d/d.js deleted file mode 100755 index c927a7e35..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/d/d.js +++ /dev/null @@ -1,218 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("d", function(config, parserConfig) { - var indentUnit = config.indentUnit, - statementIndentUnit = parserConfig.statementIndentUnit || indentUnit, - keywords = parserConfig.keywords || {}, - builtin = parserConfig.builtin || {}, - blockKeywords = parserConfig.blockKeywords || {}, - atoms = parserConfig.atoms || {}, - hooks = parserConfig.hooks || {}, - multiLineStrings = parserConfig.multiLineStrings; - var isOperatorChar = /[+\-*&%=<>!?|\/]/; - - var curPunc; - - function tokenBase(stream, state) { - var ch = stream.next(); - if (hooks[ch]) { - var result = hooks[ch](stream, state); - if (result !== false) return result; - } - if (ch == '"' || ch == "'" || ch == "`") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - curPunc = ch; - return null; - } - if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - if (ch == "/") { - if (stream.eat("+")) { - state.tokenize = tokenComment; - return tokenNestedComment(stream, state); - } - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - } - if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - stream.eatWhile(/[\w\$_\xa1-\uffff]/); - var cur = stream.current(); - if (keywords.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "keyword"; - } - if (builtin.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "builtin"; - } - if (atoms.propertyIsEnumerable(cur)) return "atom"; - return "variable"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) {end = true; break;} - escaped = !escaped && next == "\\"; - } - if (end || !(escaped || multiLineStrings)) - state.tokenize = null; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = null; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function tokenNestedComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = null; - break; - } - maybeEnd = (ch == "+"); - } - return "comment"; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - function pushContext(state, col, type) { - var indent = state.indented; - if (state.context && state.context.type == "statement") - indent = state.context.indented; - return state.context = new Context(indent, col, type, null, state.context); - } - function popContext(state) { - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") - state.indented = state.context.indented; - return state.context = state.context.prev; - } - - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: null, - context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), - indented: 0, - startOfLine: true - }; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - } - if (stream.eatSpace()) return null; - curPunc = null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment" || style == "meta") return style; - if (ctx.align == null) ctx.align = true; - - if ((curPunc == ";" || curPunc == ":" || curPunc == ",") && ctx.type == "statement") popContext(state); - else if (curPunc == "{") pushContext(state, stream.column(), "}"); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == "}") { - while (ctx.type == "statement") ctx = popContext(state); - if (ctx.type == "}") ctx = popContext(state); - while (ctx.type == "statement") ctx = popContext(state); - } - else if (curPunc == ctx.type) popContext(state); - else if (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || (ctx.type == "statement" && curPunc == "newstatement")) - pushContext(state, stream.column(), "statement"); - state.startOfLine = false; - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass; - var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); - if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev; - var closing = firstChar == ctx.type; - if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit); - else if (ctx.align) return ctx.column + (closing ? 0 : 1); - else return ctx.indented + (closing ? 0 : indentUnit); - }, - - electricChars: "{}" - }; -}); - - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - var blockKeywords = "body catch class do else enum for foreach foreach_reverse if in interface mixin " + - "out scope struct switch try union unittest version while with"; - - CodeMirror.defineMIME("text/x-d", { - name: "d", - keywords: words("abstract alias align asm assert auto break case cast cdouble cent cfloat const continue " + - "debug default delegate delete deprecated export extern final finally function goto immutable " + - "import inout invariant is lazy macro module new nothrow override package pragma private " + - "protected public pure ref return shared short static super synchronized template this " + - "throw typedef typeid typeof volatile __FILE__ __LINE__ __gshared __traits __vector __parameters " + - blockKeywords), - blockKeywords: words(blockKeywords), - builtin: words("bool byte char creal dchar double float idouble ifloat int ireal long real short ubyte " + - "ucent uint ulong ushort wchar wstring void size_t sizediff_t"), - atoms: words("exit failure success true false null"), - hooks: { - "@": function(stream, _state) { - stream.eatWhile(/[\w\$_]/); - return "meta"; - } - } - }); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/d/index.html b/backend/_pv_1_3_5/static/codemirror/mode/d/index.html deleted file mode 100755 index 08cabd8a2..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/d/index.html +++ /dev/null @@ -1,273 +0,0 @@ - - -CodeMirror: D mode - - - - - - - - - - -
    -

    D mode

    -
    - - - -

    Simple mode that handle D-Syntax (DLang Homepage).

    - -

    MIME types defined: text/x-d - .

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/dart/dart.js b/backend/_pv_1_3_5/static/codemirror/mode/dart/dart.js deleted file mode 100755 index 8d383a95e..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/dart/dart.js +++ /dev/null @@ -1,157 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../clike/clike")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../clike/clike"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - var keywords = ("this super static final const abstract class extends external factory " + - "implements get native operator set typedef with enum throw rethrow " + - "assert break case continue default in return new deferred async await " + - "try catch finally do else for if switch while import library export " + - "part of show hide is as").split(" "); - var blockKeywords = "try catch finally do else for if switch while".split(" "); - var atoms = "true false null".split(" "); - var builtins = "void bool num int double dynamic var String".split(" "); - - function set(words) { - var obj = {}; - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - function pushInterpolationStack(state) { - (state.interpolationStack || (state.interpolationStack = [])).push(state.tokenize); - } - - function popInterpolationStack(state) { - return (state.interpolationStack || (state.interpolationStack = [])).pop(); - } - - function sizeInterpolationStack(state) { - return state.interpolationStack ? state.interpolationStack.length : 0; - } - - CodeMirror.defineMIME("application/dart", { - name: "clike", - keywords: set(keywords), - blockKeywords: set(blockKeywords), - builtin: set(builtins), - atoms: set(atoms), - hooks: { - "@": function(stream) { - stream.eatWhile(/[\w\$_\.]/); - return "meta"; - }, - - // custom string handling to deal with triple-quoted strings and string interpolation - "'": function(stream, state) { - return tokenString("'", stream, state, false); - }, - "\"": function(stream, state) { - return tokenString("\"", stream, state, false); - }, - "r": function(stream, state) { - var peek = stream.peek(); - if (peek == "'" || peek == "\"") { - return tokenString(stream.next(), stream, state, true); - } - return false; - }, - - "}": function(_stream, state) { - // "}" is end of interpolation, if interpolation stack is non-empty - if (sizeInterpolationStack(state) > 0) { - state.tokenize = popInterpolationStack(state); - return null; - } - return false; - }, - - "/": function(stream, state) { - if (!stream.eat("*")) return false - state.tokenize = tokenNestedComment(1) - return state.tokenize(stream, state) - } - } - }); - - function tokenString(quote, stream, state, raw) { - var tripleQuoted = false; - if (stream.eat(quote)) { - if (stream.eat(quote)) tripleQuoted = true; - else return "string"; //empty string - } - function tokenStringHelper(stream, state) { - var escaped = false; - while (!stream.eol()) { - if (!raw && !escaped && stream.peek() == "$") { - pushInterpolationStack(state); - state.tokenize = tokenInterpolation; - return "string"; - } - var next = stream.next(); - if (next == quote && !escaped && (!tripleQuoted || stream.match(quote + quote))) { - state.tokenize = null; - break; - } - escaped = !raw && !escaped && next == "\\"; - } - return "string"; - } - state.tokenize = tokenStringHelper; - return tokenStringHelper(stream, state); - } - - function tokenInterpolation(stream, state) { - stream.eat("$"); - if (stream.eat("{")) { - // let clike handle the content of ${...}, - // we take over again when "}" appears (see hooks). - state.tokenize = null; - } else { - state.tokenize = tokenInterpolationIdentifier; - } - return null; - } - - function tokenInterpolationIdentifier(stream, state) { - stream.eatWhile(/[\w_]/); - state.tokenize = popInterpolationStack(state); - return "variable"; - } - - function tokenNestedComment(depth) { - return function (stream, state) { - var ch - while (ch = stream.next()) { - if (ch == "*" && stream.eat("/")) { - if (depth == 1) { - state.tokenize = null - break - } else { - state.tokenize = tokenNestedComment(depth - 1) - return state.tokenize(stream, state) - } - } else if (ch == "/" && stream.eat("*")) { - state.tokenize = tokenNestedComment(depth + 1) - return state.tokenize(stream, state) - } - } - return "comment" - } - } - - CodeMirror.registerHelper("hintWords", "application/dart", keywords.concat(atoms).concat(builtins)); - - // This is needed to make loading through meta.js work. - CodeMirror.defineMode("dart", function(conf) { - return CodeMirror.getMode(conf, "application/dart"); - }, "clike"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/dart/index.html b/backend/_pv_1_3_5/static/codemirror/mode/dart/index.html deleted file mode 100755 index e79da5a8b..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/dart/index.html +++ /dev/null @@ -1,71 +0,0 @@ - - -CodeMirror: Dart mode - - - - - - - - - -
    -

    Dart mode

    -
    - -
    - - - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/diff/diff.js b/backend/_pv_1_3_5/static/codemirror/mode/diff/diff.js deleted file mode 100755 index fe0305e7b..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/diff/diff.js +++ /dev/null @@ -1,47 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("diff", function() { - - var TOKEN_NAMES = { - '+': 'positive', - '-': 'negative', - '@': 'meta' - }; - - return { - token: function(stream) { - var tw_pos = stream.string.search(/[\t ]+?$/); - - if (!stream.sol() || tw_pos === 0) { - stream.skipToEnd(); - return ("error " + ( - TOKEN_NAMES[stream.string.charAt(0)] || '')).replace(/ $/, ''); - } - - var token_name = TOKEN_NAMES[stream.peek()] || stream.skipToEnd(); - - if (tw_pos === -1) { - stream.skipToEnd(); - } else { - stream.pos = tw_pos; - } - - return token_name; - } - }; -}); - -CodeMirror.defineMIME("text/x-diff", "diff"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/diff/index.html b/backend/_pv_1_3_5/static/codemirror/mode/diff/index.html deleted file mode 100755 index 0af611fa4..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/diff/index.html +++ /dev/null @@ -1,117 +0,0 @@ - - -CodeMirror: Diff mode - - - - - - - - - -
    -

    Diff mode

    -
    - - -

    MIME types defined: text/x-diff.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/django/django.js b/backend/_pv_1_3_5/static/codemirror/mode/django/django.js deleted file mode 100755 index 7b4ef3b56..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/django/django.js +++ /dev/null @@ -1,356 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), - require("../../addon/mode/overlay")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../htmlmixed/htmlmixed", - "../../addon/mode/overlay"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("django:inner", function() { - var keywords = ["block", "endblock", "for", "endfor", "true", "false", "filter", "endfilter", - "loop", "none", "self", "super", "if", "elif", "endif", "as", "else", "import", - "with", "endwith", "without", "context", "ifequal", "endifequal", "ifnotequal", - "endifnotequal", "extends", "include", "load", "comment", "endcomment", - "empty", "url", "static", "trans", "blocktrans", "endblocktrans", "now", - "regroup", "lorem", "ifchanged", "endifchanged", "firstof", "debug", "cycle", - "csrf_token", "autoescape", "endautoescape", "spaceless", "endspaceless", - "ssi", "templatetag", "verbatim", "endverbatim", "widthratio"], - filters = ["add", "addslashes", "capfirst", "center", "cut", "date", - "default", "default_if_none", "dictsort", - "dictsortreversed", "divisibleby", "escape", "escapejs", - "filesizeformat", "first", "floatformat", "force_escape", - "get_digit", "iriencode", "join", "last", "length", - "length_is", "linebreaks", "linebreaksbr", "linenumbers", - "ljust", "lower", "make_list", "phone2numeric", "pluralize", - "pprint", "random", "removetags", "rjust", "safe", - "safeseq", "slice", "slugify", "stringformat", "striptags", - "time", "timesince", "timeuntil", "title", "truncatechars", - "truncatechars_html", "truncatewords", "truncatewords_html", - "unordered_list", "upper", "urlencode", "urlize", - "urlizetrunc", "wordcount", "wordwrap", "yesno"], - operators = ["==", "!=", "<", ">", "<=", ">="], - wordOperators = ["in", "not", "or", "and"]; - - keywords = new RegExp("^\\b(" + keywords.join("|") + ")\\b"); - filters = new RegExp("^\\b(" + filters.join("|") + ")\\b"); - operators = new RegExp("^\\b(" + operators.join("|") + ")\\b"); - wordOperators = new RegExp("^\\b(" + wordOperators.join("|") + ")\\b"); - - // We have to return "null" instead of null, in order to avoid string - // styling as the default, when using Django templates inside HTML - // element attributes - function tokenBase (stream, state) { - // Attempt to identify a variable, template or comment tag respectively - if (stream.match("{{")) { - state.tokenize = inVariable; - return "tag"; - } else if (stream.match("{%")) { - state.tokenize = inTag; - return "tag"; - } else if (stream.match("{#")) { - state.tokenize = inComment; - return "comment"; - } - - // Ignore completely any stream series that do not match the - // Django template opening tags. - while (stream.next() != null && !stream.match(/\{[{%#]/, false)) {} - return null; - } - - // A string can be included in either single or double quotes (this is - // the delimiter). Mark everything as a string until the start delimiter - // occurs again. - function inString (delimiter, previousTokenizer) { - return function (stream, state) { - if (!state.escapeNext && stream.eat(delimiter)) { - state.tokenize = previousTokenizer; - } else { - if (state.escapeNext) { - state.escapeNext = false; - } - - var ch = stream.next(); - - // Take into account the backslash for escaping characters, such as - // the string delimiter. - if (ch == "\\") { - state.escapeNext = true; - } - } - - return "string"; - }; - } - - // Apply Django template variable syntax highlighting - function inVariable (stream, state) { - // Attempt to match a dot that precedes a property - if (state.waitDot) { - state.waitDot = false; - - if (stream.peek() != ".") { - return "null"; - } - - // Dot followed by a non-word character should be considered an error. - if (stream.match(/\.\W+/)) { - return "error"; - } else if (stream.eat(".")) { - state.waitProperty = true; - return "null"; - } else { - throw Error ("Unexpected error while waiting for property."); - } - } - - // Attempt to match a pipe that precedes a filter - if (state.waitPipe) { - state.waitPipe = false; - - if (stream.peek() != "|") { - return "null"; - } - - // Pipe followed by a non-word character should be considered an error. - if (stream.match(/\.\W+/)) { - return "error"; - } else if (stream.eat("|")) { - state.waitFilter = true; - return "null"; - } else { - throw Error ("Unexpected error while waiting for filter."); - } - } - - // Highlight properties - if (state.waitProperty) { - state.waitProperty = false; - if (stream.match(/\b(\w+)\b/)) { - state.waitDot = true; // A property can be followed by another property - state.waitPipe = true; // A property can be followed by a filter - return "property"; - } - } - - // Highlight filters - if (state.waitFilter) { - state.waitFilter = false; - if (stream.match(filters)) { - return "variable-2"; - } - } - - // Ignore all white spaces - if (stream.eatSpace()) { - state.waitProperty = false; - return "null"; - } - - // Identify numbers - if (stream.match(/\b\d+(\.\d+)?\b/)) { - return "number"; - } - - // Identify strings - if (stream.match("'")) { - state.tokenize = inString("'", state.tokenize); - return "string"; - } else if (stream.match('"')) { - state.tokenize = inString('"', state.tokenize); - return "string"; - } - - // Attempt to find the variable - if (stream.match(/\b(\w+)\b/) && !state.foundVariable) { - state.waitDot = true; - state.waitPipe = true; // A property can be followed by a filter - return "variable"; - } - - // If found closing tag reset - if (stream.match("}}")) { - state.waitProperty = null; - state.waitFilter = null; - state.waitDot = null; - state.waitPipe = null; - state.tokenize = tokenBase; - return "tag"; - } - - // If nothing was found, advance to the next character - stream.next(); - return "null"; - } - - function inTag (stream, state) { - // Attempt to match a dot that precedes a property - if (state.waitDot) { - state.waitDot = false; - - if (stream.peek() != ".") { - return "null"; - } - - // Dot followed by a non-word character should be considered an error. - if (stream.match(/\.\W+/)) { - return "error"; - } else if (stream.eat(".")) { - state.waitProperty = true; - return "null"; - } else { - throw Error ("Unexpected error while waiting for property."); - } - } - - // Attempt to match a pipe that precedes a filter - if (state.waitPipe) { - state.waitPipe = false; - - if (stream.peek() != "|") { - return "null"; - } - - // Pipe followed by a non-word character should be considered an error. - if (stream.match(/\.\W+/)) { - return "error"; - } else if (stream.eat("|")) { - state.waitFilter = true; - return "null"; - } else { - throw Error ("Unexpected error while waiting for filter."); - } - } - - // Highlight properties - if (state.waitProperty) { - state.waitProperty = false; - if (stream.match(/\b(\w+)\b/)) { - state.waitDot = true; // A property can be followed by another property - state.waitPipe = true; // A property can be followed by a filter - return "property"; - } - } - - // Highlight filters - if (state.waitFilter) { - state.waitFilter = false; - if (stream.match(filters)) { - return "variable-2"; - } - } - - // Ignore all white spaces - if (stream.eatSpace()) { - state.waitProperty = false; - return "null"; - } - - // Identify numbers - if (stream.match(/\b\d+(\.\d+)?\b/)) { - return "number"; - } - - // Identify strings - if (stream.match("'")) { - state.tokenize = inString("'", state.tokenize); - return "string"; - } else if (stream.match('"')) { - state.tokenize = inString('"', state.tokenize); - return "string"; - } - - // Attempt to match an operator - if (stream.match(operators)) { - return "operator"; - } - - // Attempt to match a word operator - if (stream.match(wordOperators)) { - return "keyword"; - } - - // Attempt to match a keyword - var keywordMatch = stream.match(keywords); - if (keywordMatch) { - if (keywordMatch[0] == "comment") { - state.blockCommentTag = true; - } - return "keyword"; - } - - // Attempt to match a variable - if (stream.match(/\b(\w+)\b/)) { - state.waitDot = true; - state.waitPipe = true; // A property can be followed by a filter - return "variable"; - } - - // If found closing tag reset - if (stream.match("%}")) { - state.waitProperty = null; - state.waitFilter = null; - state.waitDot = null; - state.waitPipe = null; - // If the tag that closes is a block comment tag, we want to mark the - // following code as comment, until the tag closes. - if (state.blockCommentTag) { - state.blockCommentTag = false; // Release the "lock" - state.tokenize = inBlockComment; - } else { - state.tokenize = tokenBase; - } - return "tag"; - } - - // If nothing was found, advance to the next character - stream.next(); - return "null"; - } - - // Mark everything as comment inside the tag and the tag itself. - function inComment (stream, state) { - if (stream.match(/^.*?#\}/)) state.tokenize = tokenBase - else stream.skipToEnd() - return "comment"; - } - - // Mark everything as a comment until the `blockcomment` tag closes. - function inBlockComment (stream, state) { - if (stream.match(/\{%\s*endcomment\s*%\}/, false)) { - state.tokenize = inTag; - stream.match("{%"); - return "tag"; - } else { - stream.next(); - return "comment"; - } - } - - return { - startState: function () { - return {tokenize: tokenBase}; - }, - token: function (stream, state) { - return state.tokenize(stream, state); - }, - blockCommentStart: "{% comment %}", - blockCommentEnd: "{% endcomment %}" - }; - }); - - CodeMirror.defineMode("django", function(config) { - var htmlBase = CodeMirror.getMode(config, "text/html"); - var djangoInner = CodeMirror.getMode(config, "django:inner"); - return CodeMirror.overlayMode(htmlBase, djangoInner); - }); - - CodeMirror.defineMIME("text/x-django", "django"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/django/index.html b/backend/_pv_1_3_5/static/codemirror/mode/django/index.html deleted file mode 100755 index 41ea07c91..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/django/index.html +++ /dev/null @@ -1,73 +0,0 @@ - - -CodeMirror: Django template mode - - - - - - - - - - - - - -
    -

    Django template mode

    -
    - - - -

    Mode for HTML with embedded Django template markup.

    - -

    MIME types defined: text/x-django

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/dockerfile/dockerfile.js b/backend/_pv_1_3_5/static/codemirror/mode/dockerfile/dockerfile.js deleted file mode 100755 index 4419009af..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/dockerfile/dockerfile.js +++ /dev/null @@ -1,79 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../../addon/mode/simple")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../../addon/mode/simple"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - // Collect all Dockerfile directives - var instructions = ["from", "maintainer", "run", "cmd", "expose", "env", - "add", "copy", "entrypoint", "volume", "user", - "workdir", "onbuild"], - instructionRegex = "(" + instructions.join('|') + ")", - instructionOnlyLine = new RegExp(instructionRegex + "\\s*$", "i"), - instructionWithArguments = new RegExp(instructionRegex + "(\\s+)", "i"); - - CodeMirror.defineSimpleMode("dockerfile", { - start: [ - // Block comment: This is a line starting with a comment - { - regex: /#.*$/, - token: "comment" - }, - // Highlight an instruction without any arguments (for convenience) - { - regex: instructionOnlyLine, - token: "variable-2" - }, - // Highlight an instruction followed by arguments - { - regex: instructionWithArguments, - token: ["variable-2", null], - next: "arguments" - }, - { - regex: /./, - token: null - } - ], - arguments: [ - { - // Line comment without instruction arguments is an error - regex: /#.*$/, - token: "error", - next: "start" - }, - { - regex: /[^#]+\\$/, - token: null - }, - { - // Match everything except for the inline comment - regex: /[^#]+/, - token: null, - next: "start" - }, - { - regex: /$/, - token: null, - next: "start" - }, - // Fail safe return to start - { - token: null, - next: "start" - } - ], - meta: { - lineComment: "#" - } - }); - - CodeMirror.defineMIME("text/x-dockerfile", "dockerfile"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/dockerfile/index.html b/backend/_pv_1_3_5/static/codemirror/mode/dockerfile/index.html deleted file mode 100755 index a31759bce..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/dockerfile/index.html +++ /dev/null @@ -1,73 +0,0 @@ - - -CodeMirror: Dockerfile mode - - - - - - - - - - -
    -

    Dockerfile mode

    -
    - - - -

    Dockerfile syntax highlighting for CodeMirror. Depends on - the simplemode addon.

    - -

    MIME types defined: text/x-dockerfile

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/dtd/dtd.js b/backend/_pv_1_3_5/static/codemirror/mode/dtd/dtd.js deleted file mode 100755 index 52d76ee11..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/dtd/dtd.js +++ /dev/null @@ -1,142 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/* - DTD mode - Ported to CodeMirror by Peter Kroon - Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues - GitHub: @peterkroon -*/ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("dtd", function(config) { - var indentUnit = config.indentUnit, type; - function ret(style, tp) {type = tp; return style;} - - function tokenBase(stream, state) { - var ch = stream.next(); - - if (ch == "<" && stream.eat("!") ) { - if (stream.eatWhile(/[\-]/)) { - state.tokenize = tokenSGMLComment; - return tokenSGMLComment(stream, state); - } else if (stream.eatWhile(/[\w]/)) return ret("keyword", "doindent"); - } else if (ch == "<" && stream.eat("?")) { //xml declaration - state.tokenize = inBlock("meta", "?>"); - return ret("meta", ch); - } else if (ch == "#" && stream.eatWhile(/[\w]/)) return ret("atom", "tag"); - else if (ch == "|") return ret("keyword", "seperator"); - else if (ch.match(/[\(\)\[\]\-\.,\+\?>]/)) return ret(null, ch);//if(ch === ">") return ret(null, "endtag"); else - else if (ch.match(/[\[\]]/)) return ret("rule", ch); - else if (ch == "\"" || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } else if (stream.eatWhile(/[a-zA-Z\?\+\d]/)) { - var sc = stream.current(); - if( sc.substr(sc.length-1,sc.length).match(/\?|\+/) !== null )stream.backUp(1); - return ret("tag", "tag"); - } else if (ch == "%" || ch == "*" ) return ret("number", "number"); - else { - stream.eatWhile(/[\w\\\-_%.{,]/); - return ret(null, null); - } - } - - function tokenSGMLComment(stream, state) { - var dashes = 0, ch; - while ((ch = stream.next()) != null) { - if (dashes >= 2 && ch == ">") { - state.tokenize = tokenBase; - break; - } - dashes = (ch == "-") ? dashes + 1 : 0; - } - return ret("comment", "comment"); - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) { - state.tokenize = tokenBase; - break; - } - escaped = !escaped && ch == "\\"; - } - return ret("string", "tag"); - }; - } - - function inBlock(style, terminator) { - return function(stream, state) { - while (!stream.eol()) { - if (stream.match(terminator)) { - state.tokenize = tokenBase; - break; - } - stream.next(); - } - return style; - }; - } - - return { - startState: function(base) { - return {tokenize: tokenBase, - baseIndent: base || 0, - stack: []}; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - - var context = state.stack[state.stack.length-1]; - if (stream.current() == "[" || type === "doindent" || type == "[") state.stack.push("rule"); - else if (type === "endtag") state.stack[state.stack.length-1] = "endtag"; - else if (stream.current() == "]" || type == "]" || (type == ">" && context == "rule")) state.stack.pop(); - else if (type == "[") state.stack.push("["); - return style; - }, - - indent: function(state, textAfter) { - var n = state.stack.length; - - if( textAfter.match(/\]\s+|\]/) )n=n-1; - else if(textAfter.substr(textAfter.length-1, textAfter.length) === ">"){ - if(textAfter.substr(0,1) === "<") {} - else if( type == "doindent" && textAfter.length > 1 ) {} - else if( type == "doindent")n--; - else if( type == ">" && textAfter.length > 1) {} - else if( type == "tag" && textAfter !== ">") {} - else if( type == "tag" && state.stack[state.stack.length-1] == "rule")n--; - else if( type == "tag")n++; - else if( textAfter === ">" && state.stack[state.stack.length-1] == "rule" && type === ">")n--; - else if( textAfter === ">" && state.stack[state.stack.length-1] == "rule") {} - else if( textAfter.substr(0,1) !== "<" && textAfter.substr(0,1) === ">" )n=n-1; - else if( textAfter === ">") {} - else n=n-1; - //over rule them all - if(type == null || type == "]")n--; - } - - return state.baseIndent + n * indentUnit; - }, - - electricChars: "]>" - }; -}); - -CodeMirror.defineMIME("application/xml-dtd", "dtd"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/dtd/index.html b/backend/_pv_1_3_5/static/codemirror/mode/dtd/index.html deleted file mode 100755 index e6798a748..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/dtd/index.html +++ /dev/null @@ -1,89 +0,0 @@ - - -CodeMirror: DTD mode - - - - - - - - - -
    -

    DTD mode

    -
    - - -

    MIME types defined: application/xml-dtd.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/dylan/dylan.js b/backend/_pv_1_3_5/static/codemirror/mode/dylan/dylan.js deleted file mode 100755 index 1b46bc828..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/dylan/dylan.js +++ /dev/null @@ -1,344 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("dylan", function(_config) { - // Words - var words = { - // Words that introduce unnamed definitions like "define interface" - unnamedDefinition: ["interface"], - - // Words that introduce simple named definitions like "define library" - namedDefinition: ["module", "library", "macro", - "C-struct", "C-union", - "C-function", "C-callable-wrapper" - ], - - // Words that introduce type definitions like "define class". - // These are also parameterized like "define method" and are - // appended to otherParameterizedDefinitionWords - typeParameterizedDefinition: ["class", "C-subtype", "C-mapped-subtype"], - - // Words that introduce trickier definitions like "define method". - // These require special definitions to be added to startExpressions - otherParameterizedDefinition: ["method", "function", - "C-variable", "C-address" - ], - - // Words that introduce module constant definitions. - // These must also be simple definitions and are - // appended to otherSimpleDefinitionWords - constantSimpleDefinition: ["constant"], - - // Words that introduce module variable definitions. - // These must also be simple definitions and are - // appended to otherSimpleDefinitionWords - variableSimpleDefinition: ["variable"], - - // Other words that introduce simple definitions - // (without implicit bodies). - otherSimpleDefinition: ["generic", "domain", - "C-pointer-type", - "table" - ], - - // Words that begin statements with implicit bodies. - statement: ["if", "block", "begin", "method", "case", - "for", "select", "when", "unless", "until", - "while", "iterate", "profiling", "dynamic-bind" - ], - - // Patterns that act as separators in compound statements. - // This may include any general pattern that must be indented - // specially. - separator: ["finally", "exception", "cleanup", "else", - "elseif", "afterwards" - ], - - // Keywords that do not require special indentation handling, - // but which should be highlighted - other: ["above", "below", "by", "from", "handler", "in", - "instance", "let", "local", "otherwise", "slot", - "subclass", "then", "to", "keyed-by", "virtual" - ], - - // Condition signaling function calls - signalingCalls: ["signal", "error", "cerror", - "break", "check-type", "abort" - ] - }; - - words["otherDefinition"] = - words["unnamedDefinition"] - .concat(words["namedDefinition"]) - .concat(words["otherParameterizedDefinition"]); - - words["definition"] = - words["typeParameterizedDefinition"] - .concat(words["otherDefinition"]); - - words["parameterizedDefinition"] = - words["typeParameterizedDefinition"] - .concat(words["otherParameterizedDefinition"]); - - words["simpleDefinition"] = - words["constantSimpleDefinition"] - .concat(words["variableSimpleDefinition"]) - .concat(words["otherSimpleDefinition"]); - - words["keyword"] = - words["statement"] - .concat(words["separator"]) - .concat(words["other"]); - - // Patterns - var symbolPattern = "[-_a-zA-Z?!*@<>$%]+"; - var symbol = new RegExp("^" + symbolPattern); - var patterns = { - // Symbols with special syntax - symbolKeyword: symbolPattern + ":", - symbolClass: "<" + symbolPattern + ">", - symbolGlobal: "\\*" + symbolPattern + "\\*", - symbolConstant: "\\$" + symbolPattern - }; - var patternStyles = { - symbolKeyword: "atom", - symbolClass: "tag", - symbolGlobal: "variable-2", - symbolConstant: "variable-3" - }; - - // Compile all patterns to regular expressions - for (var patternName in patterns) - if (patterns.hasOwnProperty(patternName)) - patterns[patternName] = new RegExp("^" + patterns[patternName]); - - // Names beginning "with-" and "without-" are commonly - // used as statement macro - patterns["keyword"] = [/^with(?:out)?-[-_a-zA-Z?!*@<>$%]+/]; - - var styles = {}; - styles["keyword"] = "keyword"; - styles["definition"] = "def"; - styles["simpleDefinition"] = "def"; - styles["signalingCalls"] = "builtin"; - - // protected words lookup table - var wordLookup = {}; - var styleLookup = {}; - - [ - "keyword", - "definition", - "simpleDefinition", - "signalingCalls" - ].forEach(function(type) { - words[type].forEach(function(word) { - wordLookup[word] = type; - styleLookup[word] = styles[type]; - }); - }); - - - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - - function tokenBase(stream, state) { - // String - var ch = stream.peek(); - if (ch == "'" || ch == '"') { - stream.next(); - return chain(stream, state, tokenString(ch, "string")); - } - // Comment - else if (ch == "/") { - stream.next(); - if (stream.eat("*")) { - return chain(stream, state, tokenComment); - } else if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - stream.backUp(1); - } - // Decimal - else if (/[+\-\d\.]/.test(ch)) { - if (stream.match(/^[+-]?[0-9]*\.[0-9]*([esdx][+-]?[0-9]+)?/i) || - stream.match(/^[+-]?[0-9]+([esdx][+-]?[0-9]+)/i) || - stream.match(/^[+-]?\d+/)) { - return "number"; - } - } - // Hash - else if (ch == "#") { - stream.next(); - // Symbol with string syntax - ch = stream.peek(); - if (ch == '"') { - stream.next(); - return chain(stream, state, tokenString('"', "string")); - } - // Binary number - else if (ch == "b") { - stream.next(); - stream.eatWhile(/[01]/); - return "number"; - } - // Hex number - else if (ch == "x") { - stream.next(); - stream.eatWhile(/[\da-f]/i); - return "number"; - } - // Octal number - else if (ch == "o") { - stream.next(); - stream.eatWhile(/[0-7]/); - return "number"; - } - // Token concatenation in macros - else if (ch == '#') { - stream.next(); - return "punctuation"; - } - // Sequence literals - else if ((ch == '[') || (ch == '(')) { - stream.next(); - return "bracket"; - // Hash symbol - } else if (stream.match(/f|t|all-keys|include|key|next|rest/i)) { - return "atom"; - } else { - stream.eatWhile(/[-a-zA-Z]/); - return "error"; - } - } else if (ch == "~") { - stream.next(); - ch = stream.peek(); - if (ch == "=") { - stream.next(); - ch = stream.peek(); - if (ch == "=") { - stream.next(); - return "operator"; - } - return "operator"; - } - return "operator"; - } else if (ch == ":") { - stream.next(); - ch = stream.peek(); - if (ch == "=") { - stream.next(); - return "operator"; - } else if (ch == ":") { - stream.next(); - return "punctuation"; - } - } else if ("[](){}".indexOf(ch) != -1) { - stream.next(); - return "bracket"; - } else if (".,".indexOf(ch) != -1) { - stream.next(); - return "punctuation"; - } else if (stream.match("end")) { - return "keyword"; - } - for (var name in patterns) { - if (patterns.hasOwnProperty(name)) { - var pattern = patterns[name]; - if ((pattern instanceof Array && pattern.some(function(p) { - return stream.match(p); - })) || stream.match(pattern)) - return patternStyles[name]; - } - } - if (/[+\-*\/^=<>&|]/.test(ch)) { - stream.next(); - return "operator"; - } - if (stream.match("define")) { - return "def"; - } else { - stream.eatWhile(/[\w\-]/); - // Keyword - if (wordLookup[stream.current()]) { - return styleLookup[stream.current()]; - } else if (stream.current().match(symbol)) { - return "variable"; - } else { - stream.next(); - return "variable-2"; - } - } - } - - function tokenComment(stream, state) { - var maybeEnd = false, maybeNested = false, nestedCount = 0, ch; - while ((ch = stream.next())) { - if (ch == "/" && maybeEnd) { - if (nestedCount > 0) { - nestedCount--; - } else { - state.tokenize = tokenBase; - break; - } - } else if (ch == "*" && maybeNested) { - nestedCount++; - } - maybeEnd = (ch == "*"); - maybeNested = (ch == "/"); - } - return "comment"; - } - - function tokenString(quote, style) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) { - end = true; - break; - } - escaped = !escaped && next == "\\"; - } - if (end || !escaped) { - state.tokenize = tokenBase; - } - return style; - }; - } - - // Interface - return { - startState: function() { - return { - tokenize: tokenBase, - currentIndent: 0 - }; - }, - token: function(stream, state) { - if (stream.eatSpace()) - return null; - var style = state.tokenize(stream, state); - return style; - }, - blockCommentStart: "/*", - blockCommentEnd: "*/" - }; -}); - -CodeMirror.defineMIME("text/x-dylan", "dylan"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/dylan/index.html b/backend/_pv_1_3_5/static/codemirror/mode/dylan/index.html deleted file mode 100755 index ddf5ad067..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/dylan/index.html +++ /dev/null @@ -1,407 +0,0 @@ - - -CodeMirror: Dylan mode - - - - - - - - - - - - -
    -

    Dylan mode

    - - -
    - - - -

    MIME types defined: text/x-dylan.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/dylan/test.js b/backend/_pv_1_3_5/static/codemirror/mode/dylan/test.js deleted file mode 100755 index bf25be27e..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/dylan/test.js +++ /dev/null @@ -1,88 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "dylan"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT('comments', - '[comment // This is a line comment]', - '[comment /* This is a block comment */]', - '[comment /* This is a multi]', - '[comment line comment]', - '[comment */]', - '[comment /* And this is a /*]', - '[comment /* nested */ comment */]'); - - MT('unary_operators', - '[operator -][variable a]', - '[operator -] [variable a]', - '[operator ~][variable a]', - '[operator ~] [variable a]'); - - MT('binary_operators', - '[variable a] [operator +] [variable b]', - '[variable a] [operator -] [variable b]', - '[variable a] [operator *] [variable b]', - '[variable a] [operator /] [variable b]', - '[variable a] [operator ^] [variable b]', - '[variable a] [operator =] [variable b]', - '[variable a] [operator ==] [variable b]', - '[variable a] [operator ~=] [variable b]', - '[variable a] [operator ~==] [variable b]', - '[variable a] [operator <] [variable b]', - '[variable a] [operator <=] [variable b]', - '[variable a] [operator >] [variable b]', - '[variable a] [operator >=] [variable b]', - '[variable a] [operator &] [variable b]', - '[variable a] [operator |] [variable b]', - '[variable a] [operator :=] [variable b]'); - - MT('integers', - '[number 1]', - '[number 123]', - '[number -123]', - '[number +456]', - '[number #b010]', - '[number #o073]', - '[number #xabcDEF123]'); - - MT('floats', - '[number .3]', - '[number -1.]', - '[number -2.335]', - '[number +3.78d1]', - '[number 3.78s-1]', - '[number -3.32e+5]'); - - MT('characters_and_strings', - "[string 'a']", - "[string '\\\\'']", - '[string ""]', - '[string "a"]', - '[string "abc def"]', - '[string "More escaped characters: \\\\\\\\ \\\\a \\\\b \\\\e \\\\f \\\\n \\\\r \\\\t \\\\0 ..."]'); - - MT('brackets', - '[bracket #[[]]]', - '[bracket #()]', - '[bracket #(][number 1][bracket )]', - '[bracket [[][number 1][punctuation ,] [number 3][bracket ]]]', - '[bracket ()]', - '[bracket {}]', - '[keyword if] [bracket (][variable foo][bracket )]', - '[bracket (][number 1][bracket )]', - '[bracket [[][number 1][bracket ]]]'); - - MT('hash_words', - '[punctuation ##]', - '[atom #f]', '[atom #F]', - '[atom #t]', '[atom #T]', - '[atom #all-keys]', - '[atom #include]', - '[atom #key]', - '[atom #next]', - '[atom #rest]', - '[string #"foo"]', - '[error #invalid]'); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/ebnf/ebnf.js b/backend/_pv_1_3_5/static/codemirror/mode/ebnf/ebnf.js deleted file mode 100755 index 9618f8e42..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/ebnf/ebnf.js +++ /dev/null @@ -1,195 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("ebnf", function (config) { - var commentType = {slash: 0, parenthesis: 1}; - var stateType = {comment: 0, _string: 1, characterClass: 2}; - var bracesMode = null; - - if (config.bracesMode) - bracesMode = CodeMirror.getMode(config, config.bracesMode); - - return { - startState: function () { - return { - stringType: null, - commentType: null, - braced: 0, - lhs: true, - localState: null, - stack: [], - inDefinition: false - }; - }, - token: function (stream, state) { - if (!stream) return; - - //check for state changes - if (state.stack.length === 0) { - //strings - if ((stream.peek() == '"') || (stream.peek() == "'")) { - state.stringType = stream.peek(); - stream.next(); // Skip quote - state.stack.unshift(stateType._string); - } else if (stream.match(/^\/\*/)) { //comments starting with /* - state.stack.unshift(stateType.comment); - state.commentType = commentType.slash; - } else if (stream.match(/^\(\*/)) { //comments starting with (* - state.stack.unshift(stateType.comment); - state.commentType = commentType.parenthesis; - } - } - - //return state - //stack has - switch (state.stack[0]) { - case stateType._string: - while (state.stack[0] === stateType._string && !stream.eol()) { - if (stream.peek() === state.stringType) { - stream.next(); // Skip quote - state.stack.shift(); // Clear flag - } else if (stream.peek() === "\\") { - stream.next(); - stream.next(); - } else { - stream.match(/^.[^\\\"\']*/); - } - } - return state.lhs ? "property string" : "string"; // Token style - - case stateType.comment: - while (state.stack[0] === stateType.comment && !stream.eol()) { - if (state.commentType === commentType.slash && stream.match(/\*\//)) { - state.stack.shift(); // Clear flag - state.commentType = null; - } else if (state.commentType === commentType.parenthesis && stream.match(/\*\)/)) { - state.stack.shift(); // Clear flag - state.commentType = null; - } else { - stream.match(/^.[^\*]*/); - } - } - return "comment"; - - case stateType.characterClass: - while (state.stack[0] === stateType.characterClass && !stream.eol()) { - if (!(stream.match(/^[^\]\\]+/) || stream.match(/^\\./))) { - state.stack.shift(); - } - } - return "operator"; - } - - var peek = stream.peek(); - - if (bracesMode !== null && (state.braced || peek === "{")) { - if (state.localState === null) - state.localState = CodeMirror.startState(bracesMode); - - var token = bracesMode.token(stream, state.localState), - text = stream.current(); - - if (!token) { - for (var i = 0; i < text.length; i++) { - if (text[i] === "{") { - if (state.braced === 0) { - token = "matchingbracket"; - } - state.braced++; - } else if (text[i] === "}") { - state.braced--; - if (state.braced === 0) { - token = "matchingbracket"; - } - } - } - } - return token; - } - - //no stack - switch (peek) { - case "[": - stream.next(); - state.stack.unshift(stateType.characterClass); - return "bracket"; - case ":": - case "|": - case ";": - stream.next(); - return "operator"; - case "%": - if (stream.match("%%")) { - return "header"; - } else if (stream.match(/[%][A-Za-z]+/)) { - return "keyword"; - } else if (stream.match(/[%][}]/)) { - return "matchingbracket"; - } - break; - case "/": - if (stream.match(/[\/][A-Za-z]+/)) { - return "keyword"; - } - case "\\": - if (stream.match(/[\][a-z]+/)) { - return "string-2"; - } - case ".": - if (stream.match(".")) { - return "atom"; - } - case "*": - case "-": - case "+": - case "^": - if (stream.match(peek)) { - return "atom"; - } - case "$": - if (stream.match("$$")) { - return "builtin"; - } else if (stream.match(/[$][0-9]+/)) { - return "variable-3"; - } - case "<": - if (stream.match(/<<[a-zA-Z_]+>>/)) { - return "builtin"; - } - } - - if (stream.match(/^\/\//)) { - stream.skipToEnd(); - return "comment"; - } else if (stream.match(/return/)) { - return "operator"; - } else if (stream.match(/^[a-zA-Z_][a-zA-Z0-9_]*/)) { - if (stream.match(/(?=[\(.])/)) { - return "variable"; - } else if (stream.match(/(?=[\s\n]*[:=])/)) { - return "def"; - } - return "variable-2"; - } else if (["[", "]", "(", ")"].indexOf(stream.peek()) != -1) { - stream.next(); - return "bracket"; - } else if (!stream.eatSpace()) { - stream.next(); - } - return null; - } - }; - }); - - CodeMirror.defineMIME("text/x-ebnf", "ebnf"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/ebnf/index.html b/backend/_pv_1_3_5/static/codemirror/mode/ebnf/index.html deleted file mode 100755 index 13845629b..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/ebnf/index.html +++ /dev/null @@ -1,102 +0,0 @@ - - - - CodeMirror: EBNF Mode - - - - - - - - - - - - -
    -

    EBNF Mode (bracesMode setting = "javascript")

    -
    - -

    The EBNF Mode

    -

    Created by Robert Plummer

    -
    - - diff --git a/backend/_pv_1_3_5/static/codemirror/mode/ecl/ecl.js b/backend/_pv_1_3_5/static/codemirror/mode/ecl/ecl.js deleted file mode 100755 index 8df7ebe4a..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/ecl/ecl.js +++ /dev/null @@ -1,206 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("ecl", function(config) { - - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - function metaHook(stream, state) { - if (!state.startOfLine) return false; - stream.skipToEnd(); - return "meta"; - } - - var indentUnit = config.indentUnit; - var keyword = words("abs acos allnodes ascii asin asstring atan atan2 ave case choose choosen choosesets clustersize combine correlation cos cosh count covariance cron dataset dedup define denormalize distribute distributed distribution ebcdic enth error evaluate event eventextra eventname exists exp failcode failmessage fetch fromunicode getisvalid global graph group hash hash32 hash64 hashcrc hashmd5 having if index intformat isvalid iterate join keyunicode length library limit ln local log loop map matched matchlength matchposition matchtext matchunicode max merge mergejoin min nolocal nonempty normalize parse pipe power preload process project pull random range rank ranked realformat recordof regexfind regexreplace regroup rejected rollup round roundup row rowdiff sample set sin sinh sizeof soapcall sort sorted sqrt stepped stored sum table tan tanh thisnode topn tounicode transfer trim truncate typeof ungroup unicodeorder variance which workunit xmldecode xmlencode xmltext xmlunicode"); - var variable = words("apply assert build buildindex evaluate fail keydiff keypatch loadxml nothor notify output parallel sequential soapcall wait"); - var variable_2 = words("__compressed__ all and any as atmost before beginc++ best between case const counter csv descend encrypt end endc++ endmacro except exclusive expire export extend false few first flat from full function group header heading hole ifblock import in interface joined keep keyed last left limit load local locale lookup macro many maxcount maxlength min skew module named nocase noroot noscan nosort not of only opt or outer overwrite packed partition penalty physicallength pipe quote record relationship repeat return right scan self separator service shared skew skip sql store terminator thor threshold token transform trim true type unicodeorder unsorted validate virtual whole wild within xml xpath"); - var variable_3 = words("ascii big_endian boolean data decimal ebcdic integer pattern qstring real record rule set of string token udecimal unicode unsigned varstring varunicode"); - var builtin = words("checkpoint deprecated failcode failmessage failure global independent onwarning persist priority recovery stored success wait when"); - var blockKeywords = words("catch class do else finally for if switch try while"); - var atoms = words("true false null"); - var hooks = {"#": metaHook}; - var isOperatorChar = /[+\-*&%=<>!?|\/]/; - - var curPunc; - - function tokenBase(stream, state) { - var ch = stream.next(); - if (hooks[ch]) { - var result = hooks[ch](stream, state); - if (result !== false) return result; - } - if (ch == '"' || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - curPunc = ch; - return null; - } - if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - if (ch == "/") { - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - } - if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - stream.eatWhile(/[\w\$_]/); - var cur = stream.current().toLowerCase(); - if (keyword.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "keyword"; - } else if (variable.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "variable"; - } else if (variable_2.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "variable-2"; - } else if (variable_3.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "variable-3"; - } else if (builtin.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - return "builtin"; - } else { //Data types are of from KEYWORD## - var i = cur.length - 1; - while(i >= 0 && (!isNaN(cur[i]) || cur[i] == '_')) - --i; - - if (i > 0) { - var cur2 = cur.substr(0, i + 1); - if (variable_3.propertyIsEnumerable(cur2)) { - if (blockKeywords.propertyIsEnumerable(cur2)) curPunc = "newstatement"; - return "variable-3"; - } - } - } - if (atoms.propertyIsEnumerable(cur)) return "atom"; - return null; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) {end = true; break;} - escaped = !escaped && next == "\\"; - } - if (end || !escaped) - state.tokenize = tokenBase; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - function pushContext(state, col, type) { - return state.context = new Context(state.indented, col, type, null, state.context); - } - function popContext(state) { - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") - state.indented = state.context.indented; - return state.context = state.context.prev; - } - - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: null, - context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), - indented: 0, - startOfLine: true - }; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - } - if (stream.eatSpace()) return null; - curPunc = null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment" || style == "meta") return style; - if (ctx.align == null) ctx.align = true; - - if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state); - else if (curPunc == "{") pushContext(state, stream.column(), "}"); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == "}") { - while (ctx.type == "statement") ctx = popContext(state); - if (ctx.type == "}") ctx = popContext(state); - while (ctx.type == "statement") ctx = popContext(state); - } - else if (curPunc == ctx.type) popContext(state); - else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement")) - pushContext(state, stream.column(), "statement"); - state.startOfLine = false; - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase && state.tokenize != null) return 0; - var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); - if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev; - var closing = firstChar == ctx.type; - if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : indentUnit); - else if (ctx.align) return ctx.column + (closing ? 0 : 1); - else return ctx.indented + (closing ? 0 : indentUnit); - }, - - electricChars: "{}" - }; -}); - -CodeMirror.defineMIME("text/x-ecl", "ecl"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/ecl/index.html b/backend/_pv_1_3_5/static/codemirror/mode/ecl/index.html deleted file mode 100755 index 2306860dc..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/ecl/index.html +++ /dev/null @@ -1,52 +0,0 @@ - - -CodeMirror: ECL mode - - - - - - - - - -
    -

    ECL mode

    -
    - - -

    Based on CodeMirror's clike mode. For more information see HPCC Systems web site.

    -

    MIME types defined: text/x-ecl.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/eiffel/eiffel.js b/backend/_pv_1_3_5/static/codemirror/mode/eiffel/eiffel.js deleted file mode 100755 index b8b70e36e..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/eiffel/eiffel.js +++ /dev/null @@ -1,160 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("eiffel", function() { - function wordObj(words) { - var o = {}; - for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true; - return o; - } - var keywords = wordObj([ - 'note', - 'across', - 'when', - 'variant', - 'until', - 'unique', - 'undefine', - 'then', - 'strip', - 'select', - 'retry', - 'rescue', - 'require', - 'rename', - 'reference', - 'redefine', - 'prefix', - 'once', - 'old', - 'obsolete', - 'loop', - 'local', - 'like', - 'is', - 'inspect', - 'infix', - 'include', - 'if', - 'frozen', - 'from', - 'external', - 'export', - 'ensure', - 'end', - 'elseif', - 'else', - 'do', - 'creation', - 'create', - 'check', - 'alias', - 'agent', - 'separate', - 'invariant', - 'inherit', - 'indexing', - 'feature', - 'expanded', - 'deferred', - 'class', - 'Void', - 'True', - 'Result', - 'Precursor', - 'False', - 'Current', - 'create', - 'attached', - 'detachable', - 'as', - 'and', - 'implies', - 'not', - 'or' - ]); - var operators = wordObj([":=", "and then","and", "or","<<",">>"]); - - function chain(newtok, stream, state) { - state.tokenize.push(newtok); - return newtok(stream, state); - } - - function tokenBase(stream, state) { - if (stream.eatSpace()) return null; - var ch = stream.next(); - if (ch == '"'||ch == "'") { - return chain(readQuoted(ch, "string"), stream, state); - } else if (ch == "-"&&stream.eat("-")) { - stream.skipToEnd(); - return "comment"; - } else if (ch == ":"&&stream.eat("=")) { - return "operator"; - } else if (/[0-9]/.test(ch)) { - stream.eatWhile(/[xXbBCc0-9\.]/); - stream.eat(/[\?\!]/); - return "ident"; - } else if (/[a-zA-Z_0-9]/.test(ch)) { - stream.eatWhile(/[a-zA-Z_0-9]/); - stream.eat(/[\?\!]/); - return "ident"; - } else if (/[=+\-\/*^%<>~]/.test(ch)) { - stream.eatWhile(/[=+\-\/*^%<>~]/); - return "operator"; - } else { - return null; - } - } - - function readQuoted(quote, style, unescaped) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && (unescaped || !escaped)) { - state.tokenize.pop(); - break; - } - escaped = !escaped && ch == "%"; - } - return style; - }; - } - - return { - startState: function() { - return {tokenize: [tokenBase]}; - }, - - token: function(stream, state) { - var style = state.tokenize[state.tokenize.length-1](stream, state); - if (style == "ident") { - var word = stream.current(); - style = keywords.propertyIsEnumerable(stream.current()) ? "keyword" - : operators.propertyIsEnumerable(stream.current()) ? "operator" - : /^[A-Z][A-Z_0-9]*$/g.test(word) ? "tag" - : /^0[bB][0-1]+$/g.test(word) ? "number" - : /^0[cC][0-7]+$/g.test(word) ? "number" - : /^0[xX][a-fA-F0-9]+$/g.test(word) ? "number" - : /^([0-9]+\.[0-9]*)|([0-9]*\.[0-9]+)$/g.test(word) ? "number" - : /^[0-9]+$/g.test(word) ? "number" - : "variable"; - } - return style; - }, - lineComment: "--" - }; -}); - -CodeMirror.defineMIME("text/x-eiffel", "eiffel"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/eiffel/index.html b/backend/_pv_1_3_5/static/codemirror/mode/eiffel/index.html deleted file mode 100755 index 108a71bec..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/eiffel/index.html +++ /dev/null @@ -1,429 +0,0 @@ - - -CodeMirror: Eiffel mode - - - - - - - - - - -
    -

    Eiffel mode

    -
    - - -

    MIME types defined: text/x-eiffel.

    - -

    Created by YNH.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/elm/elm.js b/backend/_pv_1_3_5/static/codemirror/mode/elm/elm.js deleted file mode 100755 index b31e66375..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/elm/elm.js +++ /dev/null @@ -1,205 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("elm", function() { - - function switchState(source, setState, f) { - setState(f); - return f(source, setState); - } - - // These should all be Unicode extended, as per the Haskell 2010 report - var smallRE = /[a-z_]/; - var largeRE = /[A-Z]/; - var digitRE = /[0-9]/; - var hexitRE = /[0-9A-Fa-f]/; - var octitRE = /[0-7]/; - var idRE = /[a-z_A-Z0-9\']/; - var symbolRE = /[-!#$%&*+.\/<=>?@\\^|~:\u03BB\u2192]/; - var specialRE = /[(),;[\]`{}]/; - var whiteCharRE = /[ \t\v\f]/; // newlines are handled in tokenizer - - function normal() { - return function (source, setState) { - if (source.eatWhile(whiteCharRE)) { - return null; - } - - var ch = source.next(); - if (specialRE.test(ch)) { - if (ch == '{' && source.eat('-')) { - var t = "comment"; - if (source.eat('#')) t = "meta"; - return switchState(source, setState, ncomment(t, 1)); - } - return null; - } - - if (ch == '\'') { - if (source.eat('\\')) - source.next(); // should handle other escapes here - else - source.next(); - - if (source.eat('\'')) - return "string"; - return "error"; - } - - if (ch == '"') { - return switchState(source, setState, stringLiteral); - } - - if (largeRE.test(ch)) { - source.eatWhile(idRE); - if (source.eat('.')) - return "qualifier"; - return "variable-2"; - } - - if (smallRE.test(ch)) { - var isDef = source.pos === 1; - source.eatWhile(idRE); - return isDef ? "variable-3" : "variable"; - } - - if (digitRE.test(ch)) { - if (ch == '0') { - if (source.eat(/[xX]/)) { - source.eatWhile(hexitRE); // should require at least 1 - return "integer"; - } - if (source.eat(/[oO]/)) { - source.eatWhile(octitRE); // should require at least 1 - return "number"; - } - } - source.eatWhile(digitRE); - var t = "number"; - if (source.eat('.')) { - t = "number"; - source.eatWhile(digitRE); // should require at least 1 - } - if (source.eat(/[eE]/)) { - t = "number"; - source.eat(/[-+]/); - source.eatWhile(digitRE); // should require at least 1 - } - return t; - } - - if (symbolRE.test(ch)) { - if (ch == '-' && source.eat(/-/)) { - source.eatWhile(/-/); - if (!source.eat(symbolRE)) { - source.skipToEnd(); - return "comment"; - } - } - source.eatWhile(symbolRE); - return "builtin"; - } - - return "error"; - } - } - - function ncomment(type, nest) { - if (nest == 0) { - return normal(); - } - return function(source, setState) { - var currNest = nest; - while (!source.eol()) { - var ch = source.next(); - if (ch == '{' && source.eat('-')) { - ++currNest; - } else if (ch == '-' && source.eat('}')) { - --currNest; - if (currNest == 0) { - setState(normal()); - return type; - } - } - } - setState(ncomment(type, currNest)); - return type; - } - } - - function stringLiteral(source, setState) { - while (!source.eol()) { - var ch = source.next(); - if (ch == '"') { - setState(normal()); - return "string"; - } - if (ch == '\\') { - if (source.eol() || source.eat(whiteCharRE)) { - setState(stringGap); - return "string"; - } - if (!source.eat('&')) source.next(); // should handle other escapes here - } - } - setState(normal()); - return "error"; - } - - function stringGap(source, setState) { - if (source.eat('\\')) { - return switchState(source, setState, stringLiteral); - } - source.next(); - setState(normal()); - return "error"; - } - - - var wellKnownWords = (function() { - var wkw = {}; - - var keywords = [ - "case", "of", "as", - "if", "then", "else", - "let", "in", - "infix", "infixl", "infixr", - "type", "alias", - "input", "output", "foreign", "loopback", - "module", "where", "import", "exposing", - "_", "..", "|", ":", "=", "\\", "\"", "->", "<-" - ]; - - for (var i = keywords.length; i--;) - wkw[keywords[i]] = "keyword"; - - return wkw; - })(); - - - - return { - startState: function () { return { f: normal() }; }, - copyState: function (s) { return { f: s.f }; }, - - token: function(stream, state) { - var t = state.f(stream, function(s) { state.f = s; }); - var w = stream.current(); - return (wellKnownWords.hasOwnProperty(w)) ? wellKnownWords[w] : t; - } - }; - - }); - - CodeMirror.defineMIME("text/x-elm", "elm"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/elm/index.html b/backend/_pv_1_3_5/static/codemirror/mode/elm/index.html deleted file mode 100755 index d5cb16abf..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/elm/index.html +++ /dev/null @@ -1,61 +0,0 @@ - - -CodeMirror: Elm mode - - - - - - - - - -
    -

    Elm mode

    - -
    - - - -

    MIME types defined: text/x-elm.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/erlang/erlang.js b/backend/_pv_1_3_5/static/codemirror/mode/erlang/erlang.js deleted file mode 100755 index 9528e19f9..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/erlang/erlang.js +++ /dev/null @@ -1,619 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/*jshint unused:true, eqnull:true, curly:true, bitwise:true */ -/*jshint undef:true, latedef:true, trailing:true */ -/*global CodeMirror:true */ - -// erlang mode. -// tokenizer -> token types -> CodeMirror styles -// tokenizer maintains a parse stack -// indenter uses the parse stack - -// TODO indenter: -// bit syntax -// old guard/bif/conversion clashes (e.g. "float/1") -// type/spec/opaque - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMIME("text/x-erlang", "erlang"); - -CodeMirror.defineMode("erlang", function(cmCfg) { - "use strict"; - -///////////////////////////////////////////////////////////////////////////// -// constants - - var typeWords = [ - "-type", "-spec", "-export_type", "-opaque"]; - - var keywordWords = [ - "after","begin","catch","case","cond","end","fun","if", - "let","of","query","receive","try","when"]; - - var separatorRE = /[\->,;]/; - var separatorWords = [ - "->",";",","]; - - var operatorAtomWords = [ - "and","andalso","band","bnot","bor","bsl","bsr","bxor", - "div","not","or","orelse","rem","xor"]; - - var operatorSymbolRE = /[\+\-\*\/<>=\|:!]/; - var operatorSymbolWords = [ - "=","+","-","*","/",">",">=","<","=<","=:=","==","=/=","/=","||","<-","!"]; - - var openParenRE = /[<\(\[\{]/; - var openParenWords = [ - "<<","(","[","{"]; - - var closeParenRE = /[>\)\]\}]/; - var closeParenWords = [ - "}","]",")",">>"]; - - var guardWords = [ - "is_atom","is_binary","is_bitstring","is_boolean","is_float", - "is_function","is_integer","is_list","is_number","is_pid", - "is_port","is_record","is_reference","is_tuple", - "atom","binary","bitstring","boolean","function","integer","list", - "number","pid","port","record","reference","tuple"]; - - var bifWords = [ - "abs","adler32","adler32_combine","alive","apply","atom_to_binary", - "atom_to_list","binary_to_atom","binary_to_existing_atom", - "binary_to_list","binary_to_term","bit_size","bitstring_to_list", - "byte_size","check_process_code","contact_binary","crc32", - "crc32_combine","date","decode_packet","delete_module", - "disconnect_node","element","erase","exit","float","float_to_list", - "garbage_collect","get","get_keys","group_leader","halt","hd", - "integer_to_list","internal_bif","iolist_size","iolist_to_binary", - "is_alive","is_atom","is_binary","is_bitstring","is_boolean", - "is_float","is_function","is_integer","is_list","is_number","is_pid", - "is_port","is_process_alive","is_record","is_reference","is_tuple", - "length","link","list_to_atom","list_to_binary","list_to_bitstring", - "list_to_existing_atom","list_to_float","list_to_integer", - "list_to_pid","list_to_tuple","load_module","make_ref","module_loaded", - "monitor_node","node","node_link","node_unlink","nodes","notalive", - "now","open_port","pid_to_list","port_close","port_command", - "port_connect","port_control","pre_loaded","process_flag", - "process_info","processes","purge_module","put","register", - "registered","round","self","setelement","size","spawn","spawn_link", - "spawn_monitor","spawn_opt","split_binary","statistics", - "term_to_binary","time","throw","tl","trunc","tuple_size", - "tuple_to_list","unlink","unregister","whereis"]; - -// upper case: [A-Z] [Ø-Þ] [À-Ö] -// lower case: [a-z] [ß-ö] [ø-ÿ] - var anumRE = /[\w@Ø-ÞÀ-Öß-öø-ÿ]/; - var escapesRE = - /[0-7]{1,3}|[bdefnrstv\\"']|\^[a-zA-Z]|x[0-9a-zA-Z]{2}|x{[0-9a-zA-Z]+}/; - -///////////////////////////////////////////////////////////////////////////// -// tokenizer - - function tokenizer(stream,state) { - // in multi-line string - if (state.in_string) { - state.in_string = (!doubleQuote(stream)); - return rval(state,stream,"string"); - } - - // in multi-line atom - if (state.in_atom) { - state.in_atom = (!singleQuote(stream)); - return rval(state,stream,"atom"); - } - - // whitespace - if (stream.eatSpace()) { - return rval(state,stream,"whitespace"); - } - - // attributes and type specs - if (!peekToken(state) && - stream.match(/-\s*[a-zß-öø-ÿ][\wØ-ÞÀ-Öß-öø-ÿ]*/)) { - if (is_member(stream.current(),typeWords)) { - return rval(state,stream,"type"); - }else{ - return rval(state,stream,"attribute"); - } - } - - var ch = stream.next(); - - // comment - if (ch == '%') { - stream.skipToEnd(); - return rval(state,stream,"comment"); - } - - // colon - if (ch == ":") { - return rval(state,stream,"colon"); - } - - // macro - if (ch == '?') { - stream.eatSpace(); - stream.eatWhile(anumRE); - return rval(state,stream,"macro"); - } - - // record - if (ch == "#") { - stream.eatSpace(); - stream.eatWhile(anumRE); - return rval(state,stream,"record"); - } - - // dollar escape - if (ch == "$") { - if (stream.next() == "\\" && !stream.match(escapesRE)) { - return rval(state,stream,"error"); - } - return rval(state,stream,"number"); - } - - // dot - if (ch == ".") { - return rval(state,stream,"dot"); - } - - // quoted atom - if (ch == '\'') { - if (!(state.in_atom = (!singleQuote(stream)))) { - if (stream.match(/\s*\/\s*[0-9]/,false)) { - stream.match(/\s*\/\s*[0-9]/,true); - return rval(state,stream,"fun"); // 'f'/0 style fun - } - if (stream.match(/\s*\(/,false) || stream.match(/\s*:/,false)) { - return rval(state,stream,"function"); - } - } - return rval(state,stream,"atom"); - } - - // string - if (ch == '"') { - state.in_string = (!doubleQuote(stream)); - return rval(state,stream,"string"); - } - - // variable - if (/[A-Z_Ø-ÞÀ-Ö]/.test(ch)) { - stream.eatWhile(anumRE); - return rval(state,stream,"variable"); - } - - // atom/keyword/BIF/function - if (/[a-z_ß-öø-ÿ]/.test(ch)) { - stream.eatWhile(anumRE); - - if (stream.match(/\s*\/\s*[0-9]/,false)) { - stream.match(/\s*\/\s*[0-9]/,true); - return rval(state,stream,"fun"); // f/0 style fun - } - - var w = stream.current(); - - if (is_member(w,keywordWords)) { - return rval(state,stream,"keyword"); - }else if (is_member(w,operatorAtomWords)) { - return rval(state,stream,"operator"); - }else if (stream.match(/\s*\(/,false)) { - // 'put' and 'erlang:put' are bifs, 'foo:put' is not - if (is_member(w,bifWords) && - ((peekToken(state).token != ":") || - (peekToken(state,2).token == "erlang"))) { - return rval(state,stream,"builtin"); - }else if (is_member(w,guardWords)) { - return rval(state,stream,"guard"); - }else{ - return rval(state,stream,"function"); - } - }else if (lookahead(stream) == ":") { - if (w == "erlang") { - return rval(state,stream,"builtin"); - } else { - return rval(state,stream,"function"); - } - }else if (is_member(w,["true","false"])) { - return rval(state,stream,"boolean"); - }else{ - return rval(state,stream,"atom"); - } - } - - // number - var digitRE = /[0-9]/; - var radixRE = /[0-9a-zA-Z]/; // 36#zZ style int - if (digitRE.test(ch)) { - stream.eatWhile(digitRE); - if (stream.eat('#')) { // 36#aZ style integer - if (!stream.eatWhile(radixRE)) { - stream.backUp(1); //"36#" - syntax error - } - } else if (stream.eat('.')) { // float - if (!stream.eatWhile(digitRE)) { - stream.backUp(1); // "3." - probably end of function - } else { - if (stream.eat(/[eE]/)) { // float with exponent - if (stream.eat(/[-+]/)) { - if (!stream.eatWhile(digitRE)) { - stream.backUp(2); // "2e-" - syntax error - } - } else { - if (!stream.eatWhile(digitRE)) { - stream.backUp(1); // "2e" - syntax error - } - } - } - } - } - return rval(state,stream,"number"); // normal integer - } - - // open parens - if (nongreedy(stream,openParenRE,openParenWords)) { - return rval(state,stream,"open_paren"); - } - - // close parens - if (nongreedy(stream,closeParenRE,closeParenWords)) { - return rval(state,stream,"close_paren"); - } - - // separators - if (greedy(stream,separatorRE,separatorWords)) { - return rval(state,stream,"separator"); - } - - // operators - if (greedy(stream,operatorSymbolRE,operatorSymbolWords)) { - return rval(state,stream,"operator"); - } - - return rval(state,stream,null); - } - -///////////////////////////////////////////////////////////////////////////// -// utilities - function nongreedy(stream,re,words) { - if (stream.current().length == 1 && re.test(stream.current())) { - stream.backUp(1); - while (re.test(stream.peek())) { - stream.next(); - if (is_member(stream.current(),words)) { - return true; - } - } - stream.backUp(stream.current().length-1); - } - return false; - } - - function greedy(stream,re,words) { - if (stream.current().length == 1 && re.test(stream.current())) { - while (re.test(stream.peek())) { - stream.next(); - } - while (0 < stream.current().length) { - if (is_member(stream.current(),words)) { - return true; - }else{ - stream.backUp(1); - } - } - stream.next(); - } - return false; - } - - function doubleQuote(stream) { - return quote(stream, '"', '\\'); - } - - function singleQuote(stream) { - return quote(stream,'\'','\\'); - } - - function quote(stream,quoteChar,escapeChar) { - while (!stream.eol()) { - var ch = stream.next(); - if (ch == quoteChar) { - return true; - }else if (ch == escapeChar) { - stream.next(); - } - } - return false; - } - - function lookahead(stream) { - var m = stream.match(/([\n\s]+|%[^\n]*\n)*(.)/,false); - return m ? m.pop() : ""; - } - - function is_member(element,list) { - return (-1 < list.indexOf(element)); - } - - function rval(state,stream,type) { - - // parse stack - pushToken(state,realToken(type,stream)); - - // map erlang token type to CodeMirror style class - // erlang -> CodeMirror tag - switch (type) { - case "atom": return "atom"; - case "attribute": return "attribute"; - case "boolean": return "atom"; - case "builtin": return "builtin"; - case "close_paren": return null; - case "colon": return null; - case "comment": return "comment"; - case "dot": return null; - case "error": return "error"; - case "fun": return "meta"; - case "function": return "tag"; - case "guard": return "property"; - case "keyword": return "keyword"; - case "macro": return "variable-2"; - case "number": return "number"; - case "open_paren": return null; - case "operator": return "operator"; - case "record": return "bracket"; - case "separator": return null; - case "string": return "string"; - case "type": return "def"; - case "variable": return "variable"; - default: return null; - } - } - - function aToken(tok,col,ind,typ) { - return {token: tok, - column: col, - indent: ind, - type: typ}; - } - - function realToken(type,stream) { - return aToken(stream.current(), - stream.column(), - stream.indentation(), - type); - } - - function fakeToken(type) { - return aToken(type,0,0,type); - } - - function peekToken(state,depth) { - var len = state.tokenStack.length; - var dep = (depth ? depth : 1); - - if (len < dep) { - return false; - }else{ - return state.tokenStack[len-dep]; - } - } - - function pushToken(state,token) { - - if (!(token.type == "comment" || token.type == "whitespace")) { - state.tokenStack = maybe_drop_pre(state.tokenStack,token); - state.tokenStack = maybe_drop_post(state.tokenStack); - } - } - - function maybe_drop_pre(s,token) { - var last = s.length-1; - - if (0 < last && s[last].type === "record" && token.type === "dot") { - s.pop(); - }else if (0 < last && s[last].type === "group") { - s.pop(); - s.push(token); - }else{ - s.push(token); - } - return s; - } - - function maybe_drop_post(s) { - if (!s.length) return s - var last = s.length-1; - - if (s[last].type === "dot") { - return []; - } - if (last > 1 && s[last].type === "fun" && s[last-1].token === "fun") { - return s.slice(0,last-1); - } - switch (s[last].token) { - case "}": return d(s,{g:["{"]}); - case "]": return d(s,{i:["["]}); - case ")": return d(s,{i:["("]}); - case ">>": return d(s,{i:["<<"]}); - case "end": return d(s,{i:["begin","case","fun","if","receive","try"]}); - case ",": return d(s,{e:["begin","try","when","->", - ",","(","[","{","<<"]}); - case "->": return d(s,{r:["when"], - m:["try","if","case","receive"]}); - case ";": return d(s,{E:["case","fun","if","receive","try","when"]}); - case "catch":return d(s,{e:["try"]}); - case "of": return d(s,{e:["case"]}); - case "after":return d(s,{e:["receive","try"]}); - default: return s; - } - } - - function d(stack,tt) { - // stack is a stack of Token objects. - // tt is an object; {type:tokens} - // type is a char, tokens is a list of token strings. - // The function returns (possibly truncated) stack. - // It will descend the stack, looking for a Token such that Token.token - // is a member of tokens. If it does not find that, it will normally (but - // see "E" below) return stack. If it does find a match, it will remove - // all the Tokens between the top and the matched Token. - // If type is "m", that is all it does. - // If type is "i", it will also remove the matched Token and the top Token. - // If type is "g", like "i", but add a fake "group" token at the top. - // If type is "r", it will remove the matched Token, but not the top Token. - // If type is "e", it will keep the matched Token but not the top Token. - // If type is "E", it behaves as for type "e", except if there is no match, - // in which case it will return an empty stack. - - for (var type in tt) { - var len = stack.length-1; - var tokens = tt[type]; - for (var i = len-1; -1 < i ; i--) { - if (is_member(stack[i].token,tokens)) { - var ss = stack.slice(0,i); - switch (type) { - case "m": return ss.concat(stack[i]).concat(stack[len]); - case "r": return ss.concat(stack[len]); - case "i": return ss; - case "g": return ss.concat(fakeToken("group")); - case "E": return ss.concat(stack[i]); - case "e": return ss.concat(stack[i]); - } - } - } - } - return (type == "E" ? [] : stack); - } - -///////////////////////////////////////////////////////////////////////////// -// indenter - - function indenter(state,textAfter) { - var t; - var unit = cmCfg.indentUnit; - var wordAfter = wordafter(textAfter); - var currT = peekToken(state,1); - var prevT = peekToken(state,2); - - if (state.in_string || state.in_atom) { - return CodeMirror.Pass; - }else if (!prevT) { - return 0; - }else if (currT.token == "when") { - return currT.column+unit; - }else if (wordAfter === "when" && prevT.type === "function") { - return prevT.indent+unit; - }else if (wordAfter === "(" && currT.token === "fun") { - return currT.column+3; - }else if (wordAfter === "catch" && (t = getToken(state,["try"]))) { - return t.column; - }else if (is_member(wordAfter,["end","after","of"])) { - t = getToken(state,["begin","case","fun","if","receive","try"]); - return t ? t.column : CodeMirror.Pass; - }else if (is_member(wordAfter,closeParenWords)) { - t = getToken(state,openParenWords); - return t ? t.column : CodeMirror.Pass; - }else if (is_member(currT.token,[",","|","||"]) || - is_member(wordAfter,[",","|","||"])) { - t = postcommaToken(state); - return t ? t.column+t.token.length : unit; - }else if (currT.token == "->") { - if (is_member(prevT.token, ["receive","case","if","try"])) { - return prevT.column+unit+unit; - }else{ - return prevT.column+unit; - } - }else if (is_member(currT.token,openParenWords)) { - return currT.column+currT.token.length; - }else{ - t = defaultToken(state); - return truthy(t) ? t.column+unit : 0; - } - } - - function wordafter(str) { - var m = str.match(/,|[a-z]+|\}|\]|\)|>>|\|+|\(/); - - return truthy(m) && (m.index === 0) ? m[0] : ""; - } - - function postcommaToken(state) { - var objs = state.tokenStack.slice(0,-1); - var i = getTokenIndex(objs,"type",["open_paren"]); - - return truthy(objs[i]) ? objs[i] : false; - } - - function defaultToken(state) { - var objs = state.tokenStack; - var stop = getTokenIndex(objs,"type",["open_paren","separator","keyword"]); - var oper = getTokenIndex(objs,"type",["operator"]); - - if (truthy(stop) && truthy(oper) && stop < oper) { - return objs[stop+1]; - } else if (truthy(stop)) { - return objs[stop]; - } else { - return false; - } - } - - function getToken(state,tokens) { - var objs = state.tokenStack; - var i = getTokenIndex(objs,"token",tokens); - - return truthy(objs[i]) ? objs[i] : false; - } - - function getTokenIndex(objs,propname,propvals) { - - for (var i = objs.length-1; -1 < i ; i--) { - if (is_member(objs[i][propname],propvals)) { - return i; - } - } - return false; - } - - function truthy(x) { - return (x !== false) && (x != null); - } - -///////////////////////////////////////////////////////////////////////////// -// this object defines the mode - - return { - startState: - function() { - return {tokenStack: [], - in_string: false, - in_atom: false}; - }, - - token: - function(stream, state) { - return tokenizer(stream, state); - }, - - indent: - function(state, textAfter) { - return indenter(state,textAfter); - }, - - lineComment: "%" - }; -}); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/erlang/index.html b/backend/_pv_1_3_5/static/codemirror/mode/erlang/index.html deleted file mode 100755 index 6d06a890a..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/erlang/index.html +++ /dev/null @@ -1,76 +0,0 @@ - - -CodeMirror: Erlang mode - - - - - - - - - - - -
    -

    Erlang mode

    -
    - - - -

    MIME types defined: text/x-erlang.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/factor/factor.js b/backend/_pv_1_3_5/static/codemirror/mode/factor/factor.js deleted file mode 100755 index 86d7adf62..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/factor/factor.js +++ /dev/null @@ -1,83 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Factor syntax highlight - simple mode -// -// by Dimage Sapelkin (https://github.com/kerabromsmu) - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../../addon/mode/simple")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../../addon/mode/simple"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineSimpleMode("factor", { - // The start state contains the rules that are intially used - start: [ - // comments - {regex: /#?!.*/, token: "comment"}, - // strings """, multiline --> state - {regex: /"""/, token: "string", next: "string3"}, - {regex: /"/, token: "string", next: "string"}, - // numbers: dec, hex, unicode, bin, fractional, complex - {regex: /(?:[+-]?)(?:0x[\d,a-f]+)|(?:0o[0-7]+)|(?:0b[0,1]+)|(?:\d+.?\d*)/, token: "number"}, - //{regex: /[+-]?/} //fractional - // definition: defining word, defined word, etc - {regex: /(\:)(\s+)(\S+)(\s+)(\()/, token: ["keyword", null, "def", null, "keyword"], next: "stack"}, - // vocabulary using --> state - {regex: /USING\:/, token: "keyword", next: "vocabulary"}, - // vocabulary definition/use - {regex: /(USE\:|IN\:)(\s+)(\S+)/, token: ["keyword", null, "variable-2"]}, - // - {regex: /<\S+>/, token: "builtin"}, - // "keywords", incl. ; t f . [ ] { } defining words - {regex: /;|t|f|if|\.|\[|\]|\{|\}|MAIN:/, token: "keyword"}, - // any id (?) - {regex: /\S+/, token: "variable"}, - - { - regex: /./, - token: null - } - ], - vocabulary: [ - {regex: /;/, token: "keyword", next: "start"}, - {regex: /\S+/, token: "variable-2"}, - { - regex: /./, - token: null - } - ], - string: [ - {regex: /(?:[^\\]|\\.)*?"/, token: "string", next: "start"}, - {regex: /.*/, token: "string"} - ], - string3: [ - {regex: /(?:[^\\]|\\.)*?"""/, token: "string", next: "start"}, - {regex: /.*/, token: "string"} - ], - stack: [ - {regex: /\)/, token: "meta", next: "start"}, - {regex: /--/, token: "meta"}, - {regex: /\S+/, token: "variable-3"}, - { - regex: /./, - token: null - } - ], - // The meta property contains global information about the mode. It - // can contain properties like lineComment, which are supported by - // all modes, and also directives like dontIndentStates, which are - // specific to simple modes. - meta: { - dontIndentStates: ["start", "vocabulary", "string", "string3", "stack"], - lineComment: [ "!", "#!" ] - } - }); - - CodeMirror.defineMIME("text/x-factor", "factor"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/factor/index.html b/backend/_pv_1_3_5/static/codemirror/mode/factor/index.html deleted file mode 100755 index 9f1548914..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/factor/index.html +++ /dev/null @@ -1,77 +0,0 @@ - - -CodeMirror: Factor mode - - - - - - - - - - - -
    - -

    Factor mode

    - -
    -
    - - -

    -

    Simple mode that handles Factor Syntax (Factor on WikiPedia).

    - -

    MIME types defined: text/x-factor.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/fcl/fcl.js b/backend/_pv_1_3_5/static/codemirror/mode/fcl/fcl.js deleted file mode 100755 index 518116976..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/fcl/fcl.js +++ /dev/null @@ -1,173 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("fcl", function(config) { - var indentUnit = config.indentUnit; - - var keywords = { - "term": true, - "method": true, "accu": true, - "rule": true, "then": true, "is": true, "and": true, "or": true, - "if": true, "default": true - }; - - var start_blocks = { - "var_input": true, - "var_output": true, - "fuzzify": true, - "defuzzify": true, - "function_block": true, - "ruleblock": true - }; - - var end_blocks = { - "end_ruleblock": true, - "end_defuzzify": true, - "end_function_block": true, - "end_fuzzify": true, - "end_var": true - }; - - var atoms = { - "true": true, "false": true, "nan": true, - "real": true, "min": true, "max": true, "cog": true, "cogs": true - }; - - var isOperatorChar = /[+\-*&^%:=<>!|\/]/; - - function tokenBase(stream, state) { - var ch = stream.next(); - - if (/[\d\.]/.test(ch)) { - if (ch == ".") { - stream.match(/^[0-9]+([eE][\-+]?[0-9]+)?/); - } else if (ch == "0") { - stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/); - } else { - stream.match(/^[0-9]*\.?[0-9]*([eE][\-+]?[0-9]+)?/); - } - return "number"; - } - - if (ch == "/" || ch == "(") { - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - } - if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - stream.eatWhile(/[\w\$_\xa1-\uffff]/); - - var cur = stream.current().toLowerCase(); - if (keywords.propertyIsEnumerable(cur) || - start_blocks.propertyIsEnumerable(cur) || - end_blocks.propertyIsEnumerable(cur)) { - return "keyword"; - } - if (atoms.propertyIsEnumerable(cur)) return "atom"; - return "variable"; - } - - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if ((ch == "/" || ch == ")") && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - - function pushContext(state, col, type) { - return state.context = new Context(state.indented, col, type, null, state.context); - } - - function popContext(state) { - if (!state.context.prev) return; - var t = state.context.type; - if (t == "end_block") - state.indented = state.context.indented; - return state.context = state.context.prev; - } - - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: null, - context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), - indented: 0, - startOfLine: true - }; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - } - if (stream.eatSpace()) return null; - - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment") return style; - if (ctx.align == null) ctx.align = true; - - var cur = stream.current().toLowerCase(); - - if (start_blocks.propertyIsEnumerable(cur)) pushContext(state, stream.column(), "end_block"); - else if (end_blocks.propertyIsEnumerable(cur)) popContext(state); - - state.startOfLine = false; - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase && state.tokenize != null) return 0; - var ctx = state.context; - - var closing = end_blocks.propertyIsEnumerable(textAfter); - if (ctx.align) return ctx.column + (closing ? 0 : 1); - else return ctx.indented + (closing ? 0 : indentUnit); - }, - - electricChars: "ryk", - fold: "brace", - blockCommentStart: "(*", - blockCommentEnd: "*)", - lineComment: "//" - }; -}); - -CodeMirror.defineMIME("text/x-fcl", "fcl"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/fcl/index.html b/backend/_pv_1_3_5/static/codemirror/mode/fcl/index.html deleted file mode 100755 index 3c18d0b3c..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/fcl/index.html +++ /dev/null @@ -1,108 +0,0 @@ - - -CodeMirror: FCL mode - - - - - - - - - - - -
    -

    FCL mode

    -
    - - - -

    MIME type: text/x-fcl

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/forth/forth.js b/backend/_pv_1_3_5/static/codemirror/mode/forth/forth.js deleted file mode 100755 index 1f519d886..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/forth/forth.js +++ /dev/null @@ -1,180 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Author: Aliaksei Chapyzhenka - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - function toWordList(words) { - var ret = []; - words.split(' ').forEach(function(e){ - ret.push({name: e}); - }); - return ret; - } - - var coreWordList = toWordList( -'INVERT AND OR XOR\ - 2* 2/ LSHIFT RSHIFT\ - 0= = 0< < > U< MIN MAX\ - 2DROP 2DUP 2OVER 2SWAP ?DUP DEPTH DROP DUP OVER ROT SWAP\ - >R R> R@\ - + - 1+ 1- ABS NEGATE\ - S>D * M* UM*\ - FM/MOD SM/REM UM/MOD */ */MOD / /MOD MOD\ - HERE , @ ! CELL+ CELLS C, C@ C! CHARS 2@ 2!\ - ALIGN ALIGNED +! ALLOT\ - CHAR [CHAR] [ ] BL\ - FIND EXECUTE IMMEDIATE COUNT LITERAL STATE\ - ; DOES> >BODY\ - EVALUATE\ - SOURCE >IN\ - <# # #S #> HOLD SIGN BASE >NUMBER HEX DECIMAL\ - FILL MOVE\ - . CR EMIT SPACE SPACES TYPE U. .R U.R\ - ACCEPT\ - TRUE FALSE\ - <> U> 0<> 0>\ - NIP TUCK ROLL PICK\ - 2>R 2R@ 2R>\ - WITHIN UNUSED MARKER\ - I J\ - TO\ - COMPILE, [COMPILE]\ - SAVE-INPUT RESTORE-INPUT\ - PAD ERASE\ - 2LITERAL DNEGATE\ - D- D+ D0< D0= D2* D2/ D< D= DMAX DMIN D>S DABS\ - M+ M*/ D. D.R 2ROT DU<\ - CATCH THROW\ - FREE RESIZE ALLOCATE\ - CS-PICK CS-ROLL\ - GET-CURRENT SET-CURRENT FORTH-WORDLIST GET-ORDER SET-ORDER\ - PREVIOUS SEARCH-WORDLIST WORDLIST FIND ALSO ONLY FORTH DEFINITIONS ORDER\ - -TRAILING /STRING SEARCH COMPARE CMOVE CMOVE> BLANK SLITERAL'); - - var immediateWordList = toWordList('IF ELSE THEN BEGIN WHILE REPEAT UNTIL RECURSE [IF] [ELSE] [THEN] ?DO DO LOOP +LOOP UNLOOP LEAVE EXIT AGAIN CASE OF ENDOF ENDCASE'); - - CodeMirror.defineMode('forth', function() { - function searchWordList (wordList, word) { - var i; - for (i = wordList.length - 1; i >= 0; i--) { - if (wordList[i].name === word.toUpperCase()) { - return wordList[i]; - } - } - return undefined; - } - return { - startState: function() { - return { - state: '', - base: 10, - coreWordList: coreWordList, - immediateWordList: immediateWordList, - wordList: [] - }; - }, - token: function (stream, stt) { - var mat; - if (stream.eatSpace()) { - return null; - } - if (stt.state === '') { // interpretation - if (stream.match(/^(\]|:NONAME)(\s|$)/i)) { - stt.state = ' compilation'; - return 'builtin compilation'; - } - mat = stream.match(/^(\:)\s+(\S+)(\s|$)+/); - if (mat) { - stt.wordList.push({name: mat[2].toUpperCase()}); - stt.state = ' compilation'; - return 'def' + stt.state; - } - mat = stream.match(/^(VARIABLE|2VARIABLE|CONSTANT|2CONSTANT|CREATE|POSTPONE|VALUE|WORD)\s+(\S+)(\s|$)+/i); - if (mat) { - stt.wordList.push({name: mat[2].toUpperCase()}); - return 'def' + stt.state; - } - mat = stream.match(/^(\'|\[\'\])\s+(\S+)(\s|$)+/); - if (mat) { - return 'builtin' + stt.state; - } - } else { // compilation - // ; [ - if (stream.match(/^(\;|\[)(\s)/)) { - stt.state = ''; - stream.backUp(1); - return 'builtin compilation'; - } - if (stream.match(/^(\;|\[)($)/)) { - stt.state = ''; - return 'builtin compilation'; - } - if (stream.match(/^(POSTPONE)\s+\S+(\s|$)+/)) { - return 'builtin'; - } - } - - // dynamic wordlist - mat = stream.match(/^(\S+)(\s+|$)/); - if (mat) { - if (searchWordList(stt.wordList, mat[1]) !== undefined) { - return 'variable' + stt.state; - } - - // comments - if (mat[1] === '\\') { - stream.skipToEnd(); - return 'comment' + stt.state; - } - - // core words - if (searchWordList(stt.coreWordList, mat[1]) !== undefined) { - return 'builtin' + stt.state; - } - if (searchWordList(stt.immediateWordList, mat[1]) !== undefined) { - return 'keyword' + stt.state; - } - - if (mat[1] === '(') { - stream.eatWhile(function (s) { return s !== ')'; }); - stream.eat(')'); - return 'comment' + stt.state; - } - - // // strings - if (mat[1] === '.(') { - stream.eatWhile(function (s) { return s !== ')'; }); - stream.eat(')'); - return 'string' + stt.state; - } - if (mat[1] === 'S"' || mat[1] === '."' || mat[1] === 'C"') { - stream.eatWhile(function (s) { return s !== '"'; }); - stream.eat('"'); - return 'string' + stt.state; - } - - // numbers - if (mat[1] - 0xfffffffff) { - return 'number' + stt.state; - } - // if (mat[1].match(/^[-+]?[0-9]+\.[0-9]*/)) { - // return 'number' + stt.state; - // } - - return 'atom' + stt.state; - } - } - }; - }); - CodeMirror.defineMIME("text/x-forth", "forth"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/forth/index.html b/backend/_pv_1_3_5/static/codemirror/mode/forth/index.html deleted file mode 100755 index ae8cd3458..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/forth/index.html +++ /dev/null @@ -1,75 +0,0 @@ - - -CodeMirror: Forth mode - - - - - - - - - - - -
    - -

    Forth mode

    - -
    -
    - - - -

    Simple mode that handle Forth-Syntax (Forth on WikiPedia).

    - -

    MIME types defined: text/x-forth.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/fortran/fortran.js b/backend/_pv_1_3_5/static/codemirror/mode/fortran/fortran.js deleted file mode 100755 index 4d88f006a..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/fortran/fortran.js +++ /dev/null @@ -1,188 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("fortran", function() { - function words(array) { - var keys = {}; - for (var i = 0; i < array.length; ++i) { - keys[array[i]] = true; - } - return keys; - } - - var keywords = words([ - "abstract", "accept", "allocatable", "allocate", - "array", "assign", "asynchronous", "backspace", - "bind", "block", "byte", "call", "case", - "class", "close", "common", "contains", - "continue", "cycle", "data", "deallocate", - "decode", "deferred", "dimension", "do", - "elemental", "else", "encode", "end", - "endif", "entry", "enumerator", "equivalence", - "exit", "external", "extrinsic", "final", - "forall", "format", "function", "generic", - "go", "goto", "if", "implicit", "import", "include", - "inquire", "intent", "interface", "intrinsic", - "module", "namelist", "non_intrinsic", - "non_overridable", "none", "nopass", - "nullify", "open", "optional", "options", - "parameter", "pass", "pause", "pointer", - "print", "private", "program", "protected", - "public", "pure", "read", "recursive", "result", - "return", "rewind", "save", "select", "sequence", - "stop", "subroutine", "target", "then", "to", "type", - "use", "value", "volatile", "where", "while", - "write"]); - var builtins = words(["abort", "abs", "access", "achar", "acos", - "adjustl", "adjustr", "aimag", "aint", "alarm", - "all", "allocated", "alog", "amax", "amin", - "amod", "and", "anint", "any", "asin", - "associated", "atan", "besj", "besjn", "besy", - "besyn", "bit_size", "btest", "cabs", "ccos", - "ceiling", "cexp", "char", "chdir", "chmod", - "clog", "cmplx", "command_argument_count", - "complex", "conjg", "cos", "cosh", "count", - "cpu_time", "cshift", "csin", "csqrt", "ctime", - "c_funloc", "c_loc", "c_associated", "c_null_ptr", - "c_null_funptr", "c_f_pointer", "c_null_char", - "c_alert", "c_backspace", "c_form_feed", - "c_new_line", "c_carriage_return", - "c_horizontal_tab", "c_vertical_tab", "dabs", - "dacos", "dasin", "datan", "date_and_time", - "dbesj", "dbesj", "dbesjn", "dbesy", "dbesy", - "dbesyn", "dble", "dcos", "dcosh", "ddim", "derf", - "derfc", "dexp", "digits", "dim", "dint", "dlog", - "dlog", "dmax", "dmin", "dmod", "dnint", - "dot_product", "dprod", "dsign", "dsinh", - "dsin", "dsqrt", "dtanh", "dtan", "dtime", - "eoshift", "epsilon", "erf", "erfc", "etime", - "exit", "exp", "exponent", "extends_type_of", - "fdate", "fget", "fgetc", "float", "floor", - "flush", "fnum", "fputc", "fput", "fraction", - "fseek", "fstat", "ftell", "gerror", "getarg", - "get_command", "get_command_argument", - "get_environment_variable", "getcwd", - "getenv", "getgid", "getlog", "getpid", - "getuid", "gmtime", "hostnm", "huge", "iabs", - "iachar", "iand", "iargc", "ibclr", "ibits", - "ibset", "ichar", "idate", "idim", "idint", - "idnint", "ieor", "ierrno", "ifix", "imag", - "imagpart", "index", "int", "ior", "irand", - "isatty", "ishft", "ishftc", "isign", - "iso_c_binding", "is_iostat_end", "is_iostat_eor", - "itime", "kill", "kind", "lbound", "len", "len_trim", - "lge", "lgt", "link", "lle", "llt", "lnblnk", "loc", - "log", "logical", "long", "lshift", "lstat", "ltime", - "matmul", "max", "maxexponent", "maxloc", "maxval", - "mclock", "merge", "move_alloc", "min", "minexponent", - "minloc", "minval", "mod", "modulo", "mvbits", - "nearest", "new_line", "nint", "not", "or", "pack", - "perror", "precision", "present", "product", "radix", - "rand", "random_number", "random_seed", "range", - "real", "realpart", "rename", "repeat", "reshape", - "rrspacing", "rshift", "same_type_as", "scale", - "scan", "second", "selected_int_kind", - "selected_real_kind", "set_exponent", "shape", - "short", "sign", "signal", "sinh", "sin", "sleep", - "sngl", "spacing", "spread", "sqrt", "srand", "stat", - "sum", "symlnk", "system", "system_clock", "tan", - "tanh", "time", "tiny", "transfer", "transpose", - "trim", "ttynam", "ubound", "umask", "unlink", - "unpack", "verify", "xor", "zabs", "zcos", "zexp", - "zlog", "zsin", "zsqrt"]); - - var dataTypes = words(["c_bool", "c_char", "c_double", "c_double_complex", - "c_float", "c_float_complex", "c_funptr", "c_int", - "c_int16_t", "c_int32_t", "c_int64_t", "c_int8_t", - "c_int_fast16_t", "c_int_fast32_t", "c_int_fast64_t", - "c_int_fast8_t", "c_int_least16_t", "c_int_least32_t", - "c_int_least64_t", "c_int_least8_t", "c_intmax_t", - "c_intptr_t", "c_long", "c_long_double", - "c_long_double_complex", "c_long_long", "c_ptr", - "c_short", "c_signed_char", "c_size_t", "character", - "complex", "double", "integer", "logical", "real"]); - var isOperatorChar = /[+\-*&=<>\/\:]/; - var litOperator = new RegExp("(\.and\.|\.or\.|\.eq\.|\.lt\.|\.le\.|\.gt\.|\.ge\.|\.ne\.|\.not\.|\.eqv\.|\.neqv\.)", "i"); - - function tokenBase(stream, state) { - - if (stream.match(litOperator)){ - return 'operator'; - } - - var ch = stream.next(); - if (ch == "!") { - stream.skipToEnd(); - return "comment"; - } - if (ch == '"' || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - if (/[\[\]\(\),]/.test(ch)) { - return null; - } - if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - stream.eatWhile(/[\w\$_]/); - var word = stream.current().toLowerCase(); - - if (keywords.hasOwnProperty(word)){ - return 'keyword'; - } - if (builtins.hasOwnProperty(word) || dataTypes.hasOwnProperty(word)) { - return 'builtin'; - } - return "variable"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) { - end = true; - break; - } - escaped = !escaped && next == "\\"; - } - if (end || !escaped) state.tokenize = null; - return "string"; - }; - } - - // Interface - - return { - startState: function() { - return {tokenize: null}; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment" || style == "meta") return style; - return style; - } - }; -}); - -CodeMirror.defineMIME("text/x-fortran", "fortran"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/fortran/index.html b/backend/_pv_1_3_5/static/codemirror/mode/fortran/index.html deleted file mode 100755 index 9aed0efcc..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/fortran/index.html +++ /dev/null @@ -1,81 +0,0 @@ - - -CodeMirror: Fortran mode - - - - - - - - - -
    -

    Fortran mode

    - - -
    - - - -

    MIME types defined: text/x-fortran.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/gas/gas.js b/backend/_pv_1_3_5/static/codemirror/mode/gas/gas.js deleted file mode 100755 index 0c74bedc5..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/gas/gas.js +++ /dev/null @@ -1,345 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("gas", function(_config, parserConfig) { - 'use strict'; - - // If an architecture is specified, its initialization function may - // populate this array with custom parsing functions which will be - // tried in the event that the standard functions do not find a match. - var custom = []; - - // The symbol used to start a line comment changes based on the target - // architecture. - // If no architecture is pased in "parserConfig" then only multiline - // comments will have syntax support. - var lineCommentStartSymbol = ""; - - // These directives are architecture independent. - // Machine specific directives should go in their respective - // architecture initialization function. - // Reference: - // http://sourceware.org/binutils/docs/as/Pseudo-Ops.html#Pseudo-Ops - var directives = { - ".abort" : "builtin", - ".align" : "builtin", - ".altmacro" : "builtin", - ".ascii" : "builtin", - ".asciz" : "builtin", - ".balign" : "builtin", - ".balignw" : "builtin", - ".balignl" : "builtin", - ".bundle_align_mode" : "builtin", - ".bundle_lock" : "builtin", - ".bundle_unlock" : "builtin", - ".byte" : "builtin", - ".cfi_startproc" : "builtin", - ".comm" : "builtin", - ".data" : "builtin", - ".def" : "builtin", - ".desc" : "builtin", - ".dim" : "builtin", - ".double" : "builtin", - ".eject" : "builtin", - ".else" : "builtin", - ".elseif" : "builtin", - ".end" : "builtin", - ".endef" : "builtin", - ".endfunc" : "builtin", - ".endif" : "builtin", - ".equ" : "builtin", - ".equiv" : "builtin", - ".eqv" : "builtin", - ".err" : "builtin", - ".error" : "builtin", - ".exitm" : "builtin", - ".extern" : "builtin", - ".fail" : "builtin", - ".file" : "builtin", - ".fill" : "builtin", - ".float" : "builtin", - ".func" : "builtin", - ".global" : "builtin", - ".gnu_attribute" : "builtin", - ".hidden" : "builtin", - ".hword" : "builtin", - ".ident" : "builtin", - ".if" : "builtin", - ".incbin" : "builtin", - ".include" : "builtin", - ".int" : "builtin", - ".internal" : "builtin", - ".irp" : "builtin", - ".irpc" : "builtin", - ".lcomm" : "builtin", - ".lflags" : "builtin", - ".line" : "builtin", - ".linkonce" : "builtin", - ".list" : "builtin", - ".ln" : "builtin", - ".loc" : "builtin", - ".loc_mark_labels" : "builtin", - ".local" : "builtin", - ".long" : "builtin", - ".macro" : "builtin", - ".mri" : "builtin", - ".noaltmacro" : "builtin", - ".nolist" : "builtin", - ".octa" : "builtin", - ".offset" : "builtin", - ".org" : "builtin", - ".p2align" : "builtin", - ".popsection" : "builtin", - ".previous" : "builtin", - ".print" : "builtin", - ".protected" : "builtin", - ".psize" : "builtin", - ".purgem" : "builtin", - ".pushsection" : "builtin", - ".quad" : "builtin", - ".reloc" : "builtin", - ".rept" : "builtin", - ".sbttl" : "builtin", - ".scl" : "builtin", - ".section" : "builtin", - ".set" : "builtin", - ".short" : "builtin", - ".single" : "builtin", - ".size" : "builtin", - ".skip" : "builtin", - ".sleb128" : "builtin", - ".space" : "builtin", - ".stab" : "builtin", - ".string" : "builtin", - ".struct" : "builtin", - ".subsection" : "builtin", - ".symver" : "builtin", - ".tag" : "builtin", - ".text" : "builtin", - ".title" : "builtin", - ".type" : "builtin", - ".uleb128" : "builtin", - ".val" : "builtin", - ".version" : "builtin", - ".vtable_entry" : "builtin", - ".vtable_inherit" : "builtin", - ".warning" : "builtin", - ".weak" : "builtin", - ".weakref" : "builtin", - ".word" : "builtin" - }; - - var registers = {}; - - function x86(_parserConfig) { - lineCommentStartSymbol = "#"; - - registers.ax = "variable"; - registers.eax = "variable-2"; - registers.rax = "variable-3"; - - registers.bx = "variable"; - registers.ebx = "variable-2"; - registers.rbx = "variable-3"; - - registers.cx = "variable"; - registers.ecx = "variable-2"; - registers.rcx = "variable-3"; - - registers.dx = "variable"; - registers.edx = "variable-2"; - registers.rdx = "variable-3"; - - registers.si = "variable"; - registers.esi = "variable-2"; - registers.rsi = "variable-3"; - - registers.di = "variable"; - registers.edi = "variable-2"; - registers.rdi = "variable-3"; - - registers.sp = "variable"; - registers.esp = "variable-2"; - registers.rsp = "variable-3"; - - registers.bp = "variable"; - registers.ebp = "variable-2"; - registers.rbp = "variable-3"; - - registers.ip = "variable"; - registers.eip = "variable-2"; - registers.rip = "variable-3"; - - registers.cs = "keyword"; - registers.ds = "keyword"; - registers.ss = "keyword"; - registers.es = "keyword"; - registers.fs = "keyword"; - registers.gs = "keyword"; - } - - function armv6(_parserConfig) { - // Reference: - // http://infocenter.arm.com/help/topic/com.arm.doc.qrc0001l/QRC0001_UAL.pdf - // http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301h/DDI0301H_arm1176jzfs_r0p7_trm.pdf - lineCommentStartSymbol = "@"; - directives.syntax = "builtin"; - - registers.r0 = "variable"; - registers.r1 = "variable"; - registers.r2 = "variable"; - registers.r3 = "variable"; - registers.r4 = "variable"; - registers.r5 = "variable"; - registers.r6 = "variable"; - registers.r7 = "variable"; - registers.r8 = "variable"; - registers.r9 = "variable"; - registers.r10 = "variable"; - registers.r11 = "variable"; - registers.r12 = "variable"; - - registers.sp = "variable-2"; - registers.lr = "variable-2"; - registers.pc = "variable-2"; - registers.r13 = registers.sp; - registers.r14 = registers.lr; - registers.r15 = registers.pc; - - custom.push(function(ch, stream) { - if (ch === '#') { - stream.eatWhile(/\w/); - return "number"; - } - }); - } - - var arch = (parserConfig.architecture || "x86").toLowerCase(); - if (arch === "x86") { - x86(parserConfig); - } else if (arch === "arm" || arch === "armv6") { - armv6(parserConfig); - } - - function nextUntilUnescaped(stream, end) { - var escaped = false, next; - while ((next = stream.next()) != null) { - if (next === end && !escaped) { - return false; - } - escaped = !escaped && next === "\\"; - } - return escaped; - } - - function clikeComment(stream, state) { - var maybeEnd = false, ch; - while ((ch = stream.next()) != null) { - if (ch === "/" && maybeEnd) { - state.tokenize = null; - break; - } - maybeEnd = (ch === "*"); - } - return "comment"; - } - - return { - startState: function() { - return { - tokenize: null - }; - }, - - token: function(stream, state) { - if (state.tokenize) { - return state.tokenize(stream, state); - } - - if (stream.eatSpace()) { - return null; - } - - var style, cur, ch = stream.next(); - - if (ch === "/") { - if (stream.eat("*")) { - state.tokenize = clikeComment; - return clikeComment(stream, state); - } - } - - if (ch === lineCommentStartSymbol) { - stream.skipToEnd(); - return "comment"; - } - - if (ch === '"') { - nextUntilUnescaped(stream, '"'); - return "string"; - } - - if (ch === '.') { - stream.eatWhile(/\w/); - cur = stream.current().toLowerCase(); - style = directives[cur]; - return style || null; - } - - if (ch === '=') { - stream.eatWhile(/\w/); - return "tag"; - } - - if (ch === '{') { - return "braket"; - } - - if (ch === '}') { - return "braket"; - } - - if (/\d/.test(ch)) { - if (ch === "0" && stream.eat("x")) { - stream.eatWhile(/[0-9a-fA-F]/); - return "number"; - } - stream.eatWhile(/\d/); - return "number"; - } - - if (/\w/.test(ch)) { - stream.eatWhile(/\w/); - if (stream.eat(":")) { - return 'tag'; - } - cur = stream.current().toLowerCase(); - style = registers[cur]; - return style || null; - } - - for (var i = 0; i < custom.length; i++) { - style = custom[i](ch, stream, state); - if (style) { - return style; - } - } - }, - - lineComment: lineCommentStartSymbol, - blockCommentStart: "/*", - blockCommentEnd: "*/" - }; -}); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/gas/index.html b/backend/_pv_1_3_5/static/codemirror/mode/gas/index.html deleted file mode 100755 index df75ca2db..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/gas/index.html +++ /dev/null @@ -1,68 +0,0 @@ - - -CodeMirror: Gas mode - - - - - - - - - -
    -

    Gas mode

    -
    - -
    - - - -

    Handles AT&T assembler syntax (more specifically this handles - the GNU Assembler (gas) syntax.) - It takes a single optional configuration parameter: - architecture, which can be one of "ARM", - "ARMv6" or "x86". - Including the parameter adds syntax for the registers and special - directives for the supplied architecture. - -

    MIME types defined: text/x-gas

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/gfm/gfm.js b/backend/_pv_1_3_5/static/codemirror/mode/gfm/gfm.js deleted file mode 100755 index 6e74ad4fd..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/gfm/gfm.js +++ /dev/null @@ -1,130 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../markdown/markdown"), require("../../addon/mode/overlay")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../markdown/markdown", "../../addon/mode/overlay"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -var urlRE = /^((?:(?:aaas?|about|acap|adiumxtra|af[ps]|aim|apt|attachment|aw|beshare|bitcoin|bolo|callto|cap|chrome(?:-extension)?|cid|coap|com-eventbrite-attendee|content|crid|cvs|data|dav|dict|dlna-(?:playcontainer|playsingle)|dns|doi|dtn|dvb|ed2k|facetime|feed|file|finger|fish|ftp|geo|gg|git|gizmoproject|go|gopher|gtalk|h323|hcp|https?|iax|icap|icon|im|imap|info|ipn|ipp|irc[6s]?|iris(?:\.beep|\.lwz|\.xpc|\.xpcs)?|itms|jar|javascript|jms|keyparc|lastfm|ldaps?|magnet|mailto|maps|market|message|mid|mms|ms-help|msnim|msrps?|mtqp|mumble|mupdate|mvn|news|nfs|nih?|nntp|notes|oid|opaquelocktoken|palm|paparazzi|platform|pop|pres|proxy|psyc|query|res(?:ource)?|rmi|rsync|rtmp|rtsp|secondlife|service|session|sftp|sgn|shttp|sieve|sips?|skype|sm[bs]|snmp|soap\.beeps?|soldat|spotify|ssh|steam|svn|tag|teamspeak|tel(?:net)?|tftp|things|thismessage|tip|tn3270|tv|udp|unreal|urn|ut2004|vemmi|ventrilo|view-source|webcal|wss?|wtai|wyciwyg|xcon(?:-userid)?|xfire|xmlrpc\.beeps?|xmpp|xri|ymsgr|z39\.50[rs]?):(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>]|\([^\s()<>]*\))+(?:\([^\s()<>]*\)|[^\s`*!()\[\]{};:'".,<>?«»“”‘’]))/i - -CodeMirror.defineMode("gfm", function(config, modeConfig) { - var codeDepth = 0; - function blankLine(state) { - state.code = false; - return null; - } - var gfmOverlay = { - startState: function() { - return { - code: false, - codeBlock: false, - ateSpace: false - }; - }, - copyState: function(s) { - return { - code: s.code, - codeBlock: s.codeBlock, - ateSpace: s.ateSpace - }; - }, - token: function(stream, state) { - state.combineTokens = null; - - // Hack to prevent formatting override inside code blocks (block and inline) - if (state.codeBlock) { - if (stream.match(/^```+/)) { - state.codeBlock = false; - return null; - } - stream.skipToEnd(); - return null; - } - if (stream.sol()) { - state.code = false; - } - if (stream.sol() && stream.match(/^```+/)) { - stream.skipToEnd(); - state.codeBlock = true; - return null; - } - // If this block is changed, it may need to be updated in Markdown mode - if (stream.peek() === '`') { - stream.next(); - var before = stream.pos; - stream.eatWhile('`'); - var difference = 1 + stream.pos - before; - if (!state.code) { - codeDepth = difference; - state.code = true; - } else { - if (difference === codeDepth) { // Must be exact - state.code = false; - } - } - return null; - } else if (state.code) { - stream.next(); - return null; - } - // Check if space. If so, links can be formatted later on - if (stream.eatSpace()) { - state.ateSpace = true; - return null; - } - if (stream.sol() || state.ateSpace) { - state.ateSpace = false; - if (modeConfig.gitHubSpice !== false) { - if(stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+@)?(?:[a-f0-9]{7,40}\b)/)) { - // User/Project@SHA - // User@SHA - // SHA - state.combineTokens = true; - return "link"; - } else if (stream.match(/^(?:[a-zA-Z0-9\-_]+\/)?(?:[a-zA-Z0-9\-_]+)?#[0-9]+\b/)) { - // User/Project#Num - // User#Num - // #Num - state.combineTokens = true; - return "link"; - } - } - } - if (stream.match(urlRE) && - stream.string.slice(stream.start - 2, stream.start) != "](" && - (stream.start == 0 || /\W/.test(stream.string.charAt(stream.start - 1)))) { - // URLs - // Taken from http://daringfireball.net/2010/07/improved_regex_for_matching_urls - // And then (issue #1160) simplified to make it not crash the Chrome Regexp engine - // And then limited url schemes to the CommonMark list, so foo:bar isn't matched as a URL - state.combineTokens = true; - return "link"; - } - stream.next(); - return null; - }, - blankLine: blankLine - }; - - var markdownConfig = { - underscoresBreakWords: false, - taskLists: true, - fencedCodeBlocks: '```', - strikethrough: true - }; - for (var attr in modeConfig) { - markdownConfig[attr] = modeConfig[attr]; - } - markdownConfig.name = "markdown"; - return CodeMirror.overlayMode(CodeMirror.getMode(config, markdownConfig), gfmOverlay); - -}, "markdown"); - - CodeMirror.defineMIME("text/x-gfm", "gfm"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/gfm/index.html b/backend/_pv_1_3_5/static/codemirror/mode/gfm/index.html deleted file mode 100755 index 24c90c068..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/gfm/index.html +++ /dev/null @@ -1,93 +0,0 @@ - - -CodeMirror: GFM mode - - - - - - - - - - - - - - - - - -
    -

    GFM mode

    -
    - - - -

    Optionally depends on other modes for properly highlighted code blocks.

    - -

    Parsing/Highlighting Tests: normal, verbose.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/gfm/test.js b/backend/_pv_1_3_5/static/codemirror/mode/gfm/test.js deleted file mode 100755 index 7a1a4ccf2..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/gfm/test.js +++ /dev/null @@ -1,236 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({tabSize: 4}, "gfm"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - var modeHighlightFormatting = CodeMirror.getMode({tabSize: 4}, {name: "gfm", highlightFormatting: true}); - function FT(name) { test.mode(name, modeHighlightFormatting, Array.prototype.slice.call(arguments, 1)); } - - FT("codeBackticks", - "[comment&formatting&formatting-code `][comment foo][comment&formatting&formatting-code `]"); - - FT("doubleBackticks", - "[comment&formatting&formatting-code ``][comment foo ` bar][comment&formatting&formatting-code ``]"); - - FT("codeBlock", - "[comment&formatting&formatting-code-block ```css]", - "[tag foo]", - "[comment&formatting&formatting-code-block ```]"); - - FT("taskList", - "[variable-2&formatting&formatting-list&formatting-list-ul - ][meta&formatting&formatting-task [ ]]][variable-2 foo]", - "[variable-2&formatting&formatting-list&formatting-list-ul - ][property&formatting&formatting-task [x]]][variable-2 foo]"); - - FT("formatting_strikethrough", - "[strikethrough&formatting&formatting-strikethrough ~~][strikethrough foo][strikethrough&formatting&formatting-strikethrough ~~]"); - - FT("formatting_strikethrough", - "foo [strikethrough&formatting&formatting-strikethrough ~~][strikethrough bar][strikethrough&formatting&formatting-strikethrough ~~]"); - - MT("emInWordAsterisk", - "foo[em *bar*]hello"); - - MT("emInWordUnderscore", - "foo_bar_hello"); - - MT("emStrongUnderscore", - "[strong __][em&strong _foo__][em _] bar"); - - MT("fencedCodeBlocks", - "[comment ```]", - "[comment foo]", - "", - "[comment ```]", - "bar"); - - MT("fencedCodeBlockModeSwitching", - "[comment ```javascript]", - "[variable foo]", - "", - "[comment ```]", - "bar"); - - MT("fencedCodeBlockModeSwitchingObjc", - "[comment ```objective-c]", - "[keyword @property] [variable NSString] [operator *] [variable foo];", - "[comment ```]", - "bar"); - - MT("fencedCodeBlocksNoTildes", - "~~~", - "foo", - "~~~"); - - MT("taskListAsterisk", - "[variable-2 * []] foo]", // Invalid; must have space or x between [] - "[variable-2 * [ ]]bar]", // Invalid; must have space after ] - "[variable-2 * [x]]hello]", // Invalid; must have space after ] - "[variable-2 * ][meta [ ]]][variable-2 [world]]]", // Valid; tests reference style links - " [variable-3 * ][property [x]]][variable-3 foo]"); // Valid; can be nested - - MT("taskListPlus", - "[variable-2 + []] foo]", // Invalid; must have space or x between [] - "[variable-2 + [ ]]bar]", // Invalid; must have space after ] - "[variable-2 + [x]]hello]", // Invalid; must have space after ] - "[variable-2 + ][meta [ ]]][variable-2 [world]]]", // Valid; tests reference style links - " [variable-3 + ][property [x]]][variable-3 foo]"); // Valid; can be nested - - MT("taskListDash", - "[variable-2 - []] foo]", // Invalid; must have space or x between [] - "[variable-2 - [ ]]bar]", // Invalid; must have space after ] - "[variable-2 - [x]]hello]", // Invalid; must have space after ] - "[variable-2 - ][meta [ ]]][variable-2 [world]]]", // Valid; tests reference style links - " [variable-3 - ][property [x]]][variable-3 foo]"); // Valid; can be nested - - MT("taskListNumber", - "[variable-2 1. []] foo]", // Invalid; must have space or x between [] - "[variable-2 2. [ ]]bar]", // Invalid; must have space after ] - "[variable-2 3. [x]]hello]", // Invalid; must have space after ] - "[variable-2 4. ][meta [ ]]][variable-2 [world]]]", // Valid; tests reference style links - " [variable-3 1. ][property [x]]][variable-3 foo]"); // Valid; can be nested - - MT("SHA", - "foo [link be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] bar"); - - MT("SHAEmphasis", - "[em *foo ][em&link be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2][em *]"); - - MT("shortSHA", - "foo [link be6a8cc] bar"); - - MT("tooShortSHA", - "foo be6a8c bar"); - - MT("longSHA", - "foo be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd22 bar"); - - MT("badSHA", - "foo be6a8cc1c1ecfe9489fb51e4869af15a13fc2cg2 bar"); - - MT("userSHA", - "foo [link bar@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] hello"); - - MT("userSHAEmphasis", - "[em *foo ][em&link bar@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2][em *]"); - - MT("userProjectSHA", - "foo [link bar/hello@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2] world"); - - MT("userProjectSHAEmphasis", - "[em *foo ][em&link bar/hello@be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2][em *]"); - - MT("num", - "foo [link #1] bar"); - - MT("numEmphasis", - "[em *foo ][em&link #1][em *]"); - - MT("badNum", - "foo #1bar hello"); - - MT("userNum", - "foo [link bar#1] hello"); - - MT("userNumEmphasis", - "[em *foo ][em&link bar#1][em *]"); - - MT("userProjectNum", - "foo [link bar/hello#1] world"); - - MT("userProjectNumEmphasis", - "[em *foo ][em&link bar/hello#1][em *]"); - - MT("vanillaLink", - "foo [link http://www.example.com/] bar"); - - MT("vanillaLinkNoScheme", - "foo [link www.example.com] bar"); - - MT("vanillaLinkHttps", - "foo [link https://www.example.com/] bar"); - - MT("vanillaLinkDataSchema", - "foo [link data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==] bar"); - - MT("vanillaLinkPunctuation", - "foo [link http://www.example.com/]. bar"); - - MT("vanillaLinkExtension", - "foo [link http://www.example.com/index.html] bar"); - - MT("vanillaLinkEmphasis", - "foo [em *][em&link http://www.example.com/index.html][em *] bar"); - - MT("notALink", - "foo asfd:asdf bar"); - - MT("notALink", - "[comment ```css]", - "[tag foo] {[property color]:[keyword black];}", - "[comment ```][link http://www.example.com/]"); - - MT("notALink", - "[comment ``foo `bar` http://www.example.com/``] hello"); - - MT("notALink", - "[comment `foo]", - "[comment&link http://www.example.com/]", - "[comment `] foo", - "", - "[link http://www.example.com/]"); - - MT("headerCodeBlockGithub", - "[header&header-1 # heading]", - "", - "[comment ```]", - "[comment code]", - "[comment ```]", - "", - "Commit: [link be6a8cc1c1ecfe9489fb51e4869af15a13fc2cd2]", - "Issue: [link #1]", - "Link: [link http://www.example.com/]"); - - MT("strikethrough", - "[strikethrough ~~foo~~]"); - - MT("strikethroughWithStartingSpace", - "~~ foo~~"); - - MT("strikethroughUnclosedStrayTildes", - "[strikethrough ~~foo~~~]"); - - MT("strikethroughUnclosedStrayTildes", - "[strikethrough ~~foo ~~]"); - - MT("strikethroughUnclosedStrayTildes", - "[strikethrough ~~foo ~~ bar]"); - - MT("strikethroughUnclosedStrayTildes", - "[strikethrough ~~foo ~~ bar~~]hello"); - - MT("strikethroughOneLetter", - "[strikethrough ~~a~~]"); - - MT("strikethroughWrapped", - "[strikethrough ~~foo]", - "[strikethrough foo~~]"); - - MT("strikethroughParagraph", - "[strikethrough ~~foo]", - "", - "foo[strikethrough ~~bar]"); - - MT("strikethroughEm", - "[strikethrough ~~foo][em&strikethrough *bar*][strikethrough ~~]"); - - MT("strikethroughEm", - "[em *][em&strikethrough ~~foo~~][em *]"); - - MT("strikethroughStrong", - "[strikethrough ~~][strong&strikethrough **foo**][strikethrough ~~]"); - - MT("strikethroughStrong", - "[strong **][strong&strikethrough ~~foo~~][strong **]"); - -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/gherkin/gherkin.js b/backend/_pv_1_3_5/static/codemirror/mode/gherkin/gherkin.js deleted file mode 100755 index fc2ebee16..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/gherkin/gherkin.js +++ /dev/null @@ -1,178 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/* -Gherkin mode - http://www.cukes.info/ -Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues -*/ - -// Following Objs from Brackets implementation: https://github.com/tregusti/brackets-gherkin/blob/master/main.js -//var Quotes = { -// SINGLE: 1, -// DOUBLE: 2 -//}; - -//var regex = { -// keywords: /(Feature| {2}(Scenario|In order to|As|I)| {4}(Given|When|Then|And))/ -//}; - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("gherkin", function () { - return { - startState: function () { - return { - lineNumber: 0, - tableHeaderLine: false, - allowFeature: true, - allowBackground: false, - allowScenario: false, - allowSteps: false, - allowPlaceholders: false, - allowMultilineArgument: false, - inMultilineString: false, - inMultilineTable: false, - inKeywordLine: false - }; - }, - token: function (stream, state) { - if (stream.sol()) { - state.lineNumber++; - state.inKeywordLine = false; - if (state.inMultilineTable) { - state.tableHeaderLine = false; - if (!stream.match(/\s*\|/, false)) { - state.allowMultilineArgument = false; - state.inMultilineTable = false; - } - } - } - - stream.eatSpace(); - - if (state.allowMultilineArgument) { - - // STRING - if (state.inMultilineString) { - if (stream.match('"""')) { - state.inMultilineString = false; - state.allowMultilineArgument = false; - } else { - stream.match(/.*/); - } - return "string"; - } - - // TABLE - if (state.inMultilineTable) { - if (stream.match(/\|\s*/)) { - return "bracket"; - } else { - stream.match(/[^\|]*/); - return state.tableHeaderLine ? "header" : "string"; - } - } - - // DETECT START - if (stream.match('"""')) { - // String - state.inMultilineString = true; - return "string"; - } else if (stream.match("|")) { - // Table - state.inMultilineTable = true; - state.tableHeaderLine = true; - return "bracket"; - } - - } - - // LINE COMMENT - if (stream.match(/#.*/)) { - return "comment"; - - // TAG - } else if (!state.inKeywordLine && stream.match(/@\S+/)) { - return "tag"; - - // FEATURE - } else if (!state.inKeywordLine && state.allowFeature && stream.match(/(機能|功能|フィーチャ|기능|โครงหลัก|ความสามารถ|ความต้องการทางธุรกิจ|ಹೆಚ್ಚಳ|గుణము|ਮੁਹਾਂਦਰਾ|ਨਕਸ਼ ਨੁਹਾਰ|ਖਾਸੀਅਤ|रूप लेख|وِیژگی|خاصية|תכונה|Функціонал|Функция|Функционалност|Функционал|Үзенчәлеклелек|Свойство|Особина|Мөмкинлек|Могућност|Λειτουργία|Δυνατότητα|Właściwość|Vlastnosť|Trajto|Tính năng|Savybė|Pretty much|Požiadavka|Požadavek|Potrzeba biznesowa|Özellik|Osobina|Ominaisuus|Omadus|OH HAI|Mogućnost|Mogucnost|Jellemző|Hwæt|Hwaet|Funzionalità|Funktionalitéit|Funktionalität|Funkcja|Funkcionalnost|Funkcionalitāte|Funkcia|Fungsi|Functionaliteit|Funcționalitate|Funcţionalitate|Functionalitate|Funcionalitat|Funcionalidade|Fonctionnalité|Fitur|Fīča|Feature|Eiginleiki|Egenskap|Egenskab|Característica|Caracteristica|Business Need|Aspekt|Arwedd|Ahoy matey!|Ability):/)) { - state.allowScenario = true; - state.allowBackground = true; - state.allowPlaceholders = false; - state.allowSteps = false; - state.allowMultilineArgument = false; - state.inKeywordLine = true; - return "keyword"; - - // BACKGROUND - } else if (!state.inKeywordLine && state.allowBackground && stream.match(/(背景|배경|แนวคิด|ಹಿನ್ನೆಲೆ|నేపథ్యం|ਪਿਛੋਕੜ|पृष्ठभूमि|زمینه|الخلفية|רקע|Тарих|Предыстория|Предистория|Позадина|Передумова|Основа|Контекст|Кереш|Υπόβαθρο|Założenia|Yo\-ho\-ho|Tausta|Taust|Situācija|Rerefons|Pozadina|Pozadie|Pozadí|Osnova|Latar Belakang|Kontext|Konteksts|Kontekstas|Kontekst|Háttér|Hannergrond|Grundlage|Geçmiş|Fundo|Fono|First off|Dis is what went down|Dasar|Contexto|Contexte|Context|Contesto|Cenário de Fundo|Cenario de Fundo|Cefndir|Bối cảnh|Bakgrunnur|Bakgrunn|Bakgrund|Baggrund|Background|B4|Antecedents|Antecedentes|Ær|Aer|Achtergrond):/)) { - state.allowPlaceholders = false; - state.allowSteps = true; - state.allowBackground = false; - state.allowMultilineArgument = false; - state.inKeywordLine = true; - return "keyword"; - - // SCENARIO OUTLINE - } else if (!state.inKeywordLine && state.allowScenario && stream.match(/(場景大綱|场景大纲|劇本大綱|剧本大纲|テンプレ|シナリオテンプレート|シナリオテンプレ|シナリオアウトライン|시나리오 개요|สรุปเหตุการณ์|โครงสร้างของเหตุการณ์|ವಿವರಣೆ|కథనం|ਪਟਕਥਾ ਰੂਪ ਰੇਖਾ|ਪਟਕਥਾ ਢਾਂਚਾ|परिदृश्य रूपरेखा|سيناريو مخطط|الگوی سناریو|תבנית תרחיש|Сценарийның төзелеше|Сценарий структураси|Структура сценарію|Структура сценария|Структура сценарија|Скица|Рамка на сценарий|Концепт|Περιγραφή Σεναρίου|Wharrimean is|Template Situai|Template Senario|Template Keadaan|Tapausaihio|Szenariogrundriss|Szablon scenariusza|Swa hwær swa|Swa hwaer swa|Struktura scenarija|Structură scenariu|Structura scenariu|Skica|Skenario konsep|Shiver me timbers|Senaryo taslağı|Schema dello scenario|Scenariomall|Scenariomal|Scenario Template|Scenario Outline|Scenario Amlinellol|Scenārijs pēc parauga|Scenarijaus šablonas|Reckon it's like|Raamstsenaarium|Plang vum Szenario|Plan du Scénario|Plan du scénario|Osnova scénáře|Osnova Scenára|Náčrt Scenáru|Náčrt Scénáře|Náčrt Scenára|MISHUN SRSLY|Menggariskan Senario|Lýsing Dæma|Lýsing Atburðarásar|Konturo de la scenaro|Koncept|Khung tình huống|Khung kịch bản|Forgatókönyv vázlat|Esquema do Cenário|Esquema do Cenario|Esquema del escenario|Esquema de l'escenari|Esbozo do escenario|Delineação do Cenário|Delineacao do Cenario|All y'all|Abstrakt Scenario|Abstract Scenario):/)) { - state.allowPlaceholders = true; - state.allowSteps = true; - state.allowMultilineArgument = false; - state.inKeywordLine = true; - return "keyword"; - - // EXAMPLES - } else if (state.allowScenario && stream.match(/(例子|例|サンプル|예|ชุดของเหตุการณ์|ชุดของตัวอย่าง|ಉದಾಹರಣೆಗಳು|ఉదాహరణలు|ਉਦਾਹਰਨਾਂ|उदाहरण|نمونه ها|امثلة|דוגמאות|Үрнәкләр|Сценарији|Примеры|Примери|Приклади|Мисоллар|Мисаллар|Σενάρια|Παραδείγματα|You'll wanna|Voorbeelden|Variantai|Tapaukset|Se þe|Se the|Se ðe|Scenarios|Scenariji|Scenarijai|Przykłady|Primjeri|Primeri|Příklady|Príklady|Piemēri|Példák|Pavyzdžiai|Paraugs|Örnekler|Juhtumid|Exemplos|Exemples|Exemple|Exempel|EXAMPLZ|Examples|Esempi|Enghreifftiau|Ekzemploj|Eksempler|Ejemplos|Dữ liệu|Dead men tell no tales|Dæmi|Contoh|Cenários|Cenarios|Beispiller|Beispiele|Atburðarásir):/)) { - state.allowPlaceholders = false; - state.allowSteps = true; - state.allowBackground = false; - state.allowMultilineArgument = true; - return "keyword"; - - // SCENARIO - } else if (!state.inKeywordLine && state.allowScenario && stream.match(/(場景|场景|劇本|剧本|シナリオ|시나리오|เหตุการณ์|ಕಥಾಸಾರಾಂಶ|సన్నివేశం|ਪਟਕਥਾ|परिदृश्य|سيناريو|سناریو|תרחיש|Сценарій|Сценарио|Сценарий|Пример|Σενάριο|Tình huống|The thing of it is|Tapaus|Szenario|Swa|Stsenaarium|Skenario|Situai|Senaryo|Senario|Scenaro|Scenariusz|Scenariu|Scénario|Scenario|Scenarijus|Scenārijs|Scenarij|Scenarie|Scénář|Scenár|Primer|MISHUN|Kịch bản|Keadaan|Heave to|Forgatókönyv|Escenario|Escenari|Cenário|Cenario|Awww, look mate|Atburðarás):/)) { - state.allowPlaceholders = false; - state.allowSteps = true; - state.allowBackground = false; - state.allowMultilineArgument = false; - state.inKeywordLine = true; - return "keyword"; - - // STEPS - } else if (!state.inKeywordLine && state.allowSteps && stream.match(/(那麼|那么|而且|當|当|并且|同時|同时|前提|假设|假設|假定|假如|但是|但し|並且|もし|ならば|ただし|しかし|かつ|하지만|조건|먼저|만일|만약|단|그리고|그러면|และ |เมื่อ |แต่ |ดังนั้น |กำหนดให้ |ಸ್ಥಿತಿಯನ್ನು |ಮತ್ತು |ನೀಡಿದ |ನಂತರ |ಆದರೆ |మరియు |చెప్పబడినది |కాని |ఈ పరిస్థితిలో |అప్పుడు |ਪਰ |ਤਦ |ਜੇਕਰ |ਜਿਵੇਂ ਕਿ |ਜਦੋਂ |ਅਤੇ |यदि |परन्तु |पर |तब |तदा |तथा |जब |चूंकि |किन्तु |कदा |और |अगर |و |هنگامی |متى |لكن |عندما |ثم |بفرض |با فرض |اما |اذاً |آنگاه |כאשר |וגם |בהינתן |אזי |אז |אבל |Якщо |Һәм |Унда |Тоді |Тогда |То |Также |Та |Пусть |Припустимо, що |Припустимо |Онда |Но |Нехай |Нәтиҗәдә |Лекин |Ләкин |Коли |Когда |Когато |Када |Кад |К тому же |І |И |Задато |Задати |Задате |Если |Допустим |Дано |Дадено |Вә |Ва |Бирок |Әмма |Әйтик |Әгәр |Аммо |Али |Але |Агар |А також |А |Τότε |Όταν |Και |Δεδομένου |Αλλά |Þurh |Þegar |Þa þe |Þá |Þa |Zatati |Zakładając |Zadato |Zadate |Zadano |Zadani |Zadan |Za předpokladu |Za predpokladu |Youse know when youse got |Youse know like when |Yna |Yeah nah |Y'know |Y |Wun |Wtedy |When y'all |When |Wenn |WEN |wann |Ve |Và |Und |Un |ugeholl |Too right |Thurh |Thì |Then y'all |Then |Tha the |Tha |Tetapi |Tapi |Tak |Tada |Tad |Stel |Soit |Siis |Și |Şi |Si |Sed |Se |Så |Quando |Quand |Quan |Pryd |Potom |Pokud |Pokiaľ |Però |Pero |Pak |Oraz |Onda |Ond |Oletetaan |Og |Och |O zaman |Niin |Nhưng |När |Når |Mutta |Men |Mas |Maka |Majd |Mając |Mais |Maar |mä |Ma |Lorsque |Lorsqu'|Logo |Let go and haul |Kun |Kuid |Kui |Kiedy |Khi |Ketika |Kemudian |Keď |Když |Kaj |Kai |Kada |Kad |Jeżeli |Jeśli |Ja |It's just unbelievable |Ir |I CAN HAZ |I |Ha |Givun |Givet |Given y'all |Given |Gitt |Gegeven |Gegeben seien |Gegeben sei |Gdy |Gangway! |Fakat |Étant donnés |Etant donnés |Étant données |Etant données |Étant donnée |Etant donnée |Étant donné |Etant donné |Et |És |Entonces |Entón |Então |Entao |En |Eğer ki |Ef |Eeldades |E |Ðurh |Duota |Dun |Donitaĵo |Donat |Donada |Do |Diyelim ki |Diberi |Dengan |Den youse gotta |DEN |De |Dato |Dați fiind |Daţi fiind |Dati fiind |Dati |Date fiind |Date |Data |Dat fiind |Dar |Dann |dann |Dan |Dados |Dado |Dadas |Dada |Ða ðe |Ða |Cuando |Cho |Cando |Când |Cand |Cal |But y'all |But at the end of the day I reckon |BUT |But |Buh |Blimey! |Biết |Bet |Bagi |Aye |awer |Avast! |Atunci |Atesa |Atès |Apabila |Anrhegedig a |Angenommen |And y'all |And |AN |An |an |Amikor |Amennyiben |Ama |Als |Alors |Allora |Ali |Aleshores |Ale |Akkor |Ak |Adott |Ac |Aber |A zároveň |A tiež |A taktiež |A také |A |a |7 |\* )/)) { - state.inStep = true; - state.allowPlaceholders = true; - state.allowMultilineArgument = true; - state.inKeywordLine = true; - return "keyword"; - - // INLINE STRING - } else if (stream.match(/"[^"]*"?/)) { - return "string"; - - // PLACEHOLDER - } else if (state.allowPlaceholders && stream.match(/<[^>]*>?/)) { - return "variable"; - - // Fall through - } else { - stream.next(); - stream.eatWhile(/[^@"<#]/); - return null; - } - } - }; -}); - -CodeMirror.defineMIME("text/x-feature", "gherkin"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/gherkin/index.html b/backend/_pv_1_3_5/static/codemirror/mode/gherkin/index.html deleted file mode 100755 index af8184c98..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/gherkin/index.html +++ /dev/null @@ -1,48 +0,0 @@ - - -CodeMirror: Gherkin mode - - - - - - - - - -
    -

    Gherkin mode

    -
    - - -

    MIME types defined: text/x-feature.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/go/go.js b/backend/_pv_1_3_5/static/codemirror/mode/go/go.js deleted file mode 100755 index 803a5ba27..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/go/go.js +++ /dev/null @@ -1,186 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("go", function(config) { - var indentUnit = config.indentUnit; - - var keywords = { - "break":true, "case":true, "chan":true, "const":true, "continue":true, - "default":true, "defer":true, "else":true, "fallthrough":true, "for":true, - "func":true, "go":true, "goto":true, "if":true, "import":true, - "interface":true, "map":true, "package":true, "range":true, "return":true, - "select":true, "struct":true, "switch":true, "type":true, "var":true, - "bool":true, "byte":true, "complex64":true, "complex128":true, - "float32":true, "float64":true, "int8":true, "int16":true, "int32":true, - "int64":true, "string":true, "uint8":true, "uint16":true, "uint32":true, - "uint64":true, "int":true, "uint":true, "uintptr":true, "error": true - }; - - var atoms = { - "true":true, "false":true, "iota":true, "nil":true, "append":true, - "cap":true, "close":true, "complex":true, "copy":true, "imag":true, - "len":true, "make":true, "new":true, "panic":true, "print":true, - "println":true, "real":true, "recover":true - }; - - var isOperatorChar = /[+\-*&^%:=<>!|\/]/; - - var curPunc; - - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"' || ch == "'" || ch == "`") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - if (/[\d\.]/.test(ch)) { - if (ch == ".") { - stream.match(/^[0-9]+([eE][\-+]?[0-9]+)?/); - } else if (ch == "0") { - stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/); - } else { - stream.match(/^[0-9]*\.?[0-9]*([eE][\-+]?[0-9]+)?/); - } - return "number"; - } - if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - curPunc = ch; - return null; - } - if (ch == "/") { - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - } - if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - stream.eatWhile(/[\w\$_\xa1-\uffff]/); - var cur = stream.current(); - if (keywords.propertyIsEnumerable(cur)) { - if (cur == "case" || cur == "default") curPunc = "case"; - return "keyword"; - } - if (atoms.propertyIsEnumerable(cur)) return "atom"; - return "variable"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) {end = true; break;} - escaped = !escaped && quote != "`" && next == "\\"; - } - if (end || !(escaped || quote == "`")) - state.tokenize = tokenBase; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - function pushContext(state, col, type) { - return state.context = new Context(state.indented, col, type, null, state.context); - } - function popContext(state) { - if (!state.context.prev) return; - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") - state.indented = state.context.indented; - return state.context = state.context.prev; - } - - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: null, - context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), - indented: 0, - startOfLine: true - }; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - if (ctx.type == "case") ctx.type = "}"; - } - if (stream.eatSpace()) return null; - curPunc = null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment") return style; - if (ctx.align == null) ctx.align = true; - - if (curPunc == "{") pushContext(state, stream.column(), "}"); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == "case") ctx.type = "case"; - else if (curPunc == "}" && ctx.type == "}") ctx = popContext(state); - else if (curPunc == ctx.type) popContext(state); - state.startOfLine = false; - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase && state.tokenize != null) return 0; - var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); - if (ctx.type == "case" && /^(?:case|default)\b/.test(textAfter)) { - state.context.type = "}"; - return ctx.indented; - } - var closing = firstChar == ctx.type; - if (ctx.align) return ctx.column + (closing ? 0 : 1); - else return ctx.indented + (closing ? 0 : indentUnit); - }, - - electricChars: "{}):", - closeBrackets: "()[]{}''\"\"``", - fold: "brace", - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: "//" - }; -}); - -CodeMirror.defineMIME("text/x-go", "go"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/go/index.html b/backend/_pv_1_3_5/static/codemirror/mode/go/index.html deleted file mode 100755 index 72e3b364c..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/go/index.html +++ /dev/null @@ -1,85 +0,0 @@ - - -CodeMirror: Go mode - - - - - - - - - - - -
    -

    Go mode

    -
    - - - -

    MIME type: text/x-go

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/groovy/groovy.js b/backend/_pv_1_3_5/static/codemirror/mode/groovy/groovy.js deleted file mode 100755 index daa798722..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/groovy/groovy.js +++ /dev/null @@ -1,230 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("groovy", function(config) { - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - var keywords = words( - "abstract as assert boolean break byte case catch char class const continue def default " + - "do double else enum extends final finally float for goto if implements import in " + - "instanceof int interface long native new package private protected public return " + - "short static strictfp super switch synchronized threadsafe throw throws transient " + - "try void volatile while"); - var blockKeywords = words("catch class do else finally for if switch try while enum interface def"); - var standaloneKeywords = words("return break continue"); - var atoms = words("null true false this"); - - var curPunc; - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"' || ch == "'") { - return startString(ch, stream, state); - } - if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - curPunc = ch; - return null; - } - if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - if (stream.eat(/eE/)) { stream.eat(/\+\-/); stream.eatWhile(/\d/); } - return "number"; - } - if (ch == "/") { - if (stream.eat("*")) { - state.tokenize.push(tokenComment); - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - if (expectExpression(state.lastToken, false)) { - return startString(ch, stream, state); - } - } - if (ch == "-" && stream.eat(">")) { - curPunc = "->"; - return null; - } - if (/[+\-*&%=<>!?|\/~]/.test(ch)) { - stream.eatWhile(/[+\-*&%=<>|~]/); - return "operator"; - } - stream.eatWhile(/[\w\$_]/); - if (ch == "@") { stream.eatWhile(/[\w\$_\.]/); return "meta"; } - if (state.lastToken == ".") return "property"; - if (stream.eat(":")) { curPunc = "proplabel"; return "property"; } - var cur = stream.current(); - if (atoms.propertyIsEnumerable(cur)) { return "atom"; } - if (keywords.propertyIsEnumerable(cur)) { - if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement"; - else if (standaloneKeywords.propertyIsEnumerable(cur)) curPunc = "standalone"; - return "keyword"; - } - return "variable"; - } - tokenBase.isBase = true; - - function startString(quote, stream, state) { - var tripleQuoted = false; - if (quote != "/" && stream.eat(quote)) { - if (stream.eat(quote)) tripleQuoted = true; - else return "string"; - } - function t(stream, state) { - var escaped = false, next, end = !tripleQuoted; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) { - if (!tripleQuoted) { break; } - if (stream.match(quote + quote)) { end = true; break; } - } - if (quote == '"' && next == "$" && !escaped && stream.eat("{")) { - state.tokenize.push(tokenBaseUntilBrace()); - return "string"; - } - escaped = !escaped && next == "\\"; - } - if (end) state.tokenize.pop(); - return "string"; - } - state.tokenize.push(t); - return t(stream, state); - } - - function tokenBaseUntilBrace() { - var depth = 1; - function t(stream, state) { - if (stream.peek() == "}") { - depth--; - if (depth == 0) { - state.tokenize.pop(); - return state.tokenize[state.tokenize.length-1](stream, state); - } - } else if (stream.peek() == "{") { - depth++; - } - return tokenBase(stream, state); - } - t.isBase = true; - return t; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize.pop(); - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function expectExpression(last, newline) { - return !last || last == "operator" || last == "->" || /[\.\[\{\(,;:]/.test(last) || - last == "newstatement" || last == "keyword" || last == "proplabel" || - (last == "standalone" && !newline); - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - function pushContext(state, col, type) { - return state.context = new Context(state.indented, col, type, null, state.context); - } - function popContext(state) { - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") - state.indented = state.context.indented; - return state.context = state.context.prev; - } - - // Interface - - return { - startState: function(basecolumn) { - return { - tokenize: [tokenBase], - context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false), - indented: 0, - startOfLine: true, - lastToken: null - }; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - // Automatic semicolon insertion - if (ctx.type == "statement" && !expectExpression(state.lastToken, true)) { - popContext(state); ctx = state.context; - } - } - if (stream.eatSpace()) return null; - curPunc = null; - var style = state.tokenize[state.tokenize.length-1](stream, state); - if (style == "comment") return style; - if (ctx.align == null) ctx.align = true; - - if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state); - // Handle indentation for {x -> \n ... } - else if (curPunc == "->" && ctx.type == "statement" && ctx.prev.type == "}") { - popContext(state); - state.context.align = false; - } - else if (curPunc == "{") pushContext(state, stream.column(), "}"); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == "}") { - while (ctx.type == "statement") ctx = popContext(state); - if (ctx.type == "}") ctx = popContext(state); - while (ctx.type == "statement") ctx = popContext(state); - } - else if (curPunc == ctx.type) popContext(state); - else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement")) - pushContext(state, stream.column(), "statement"); - state.startOfLine = false; - state.lastToken = curPunc || style; - return style; - }, - - indent: function(state, textAfter) { - if (!state.tokenize[state.tokenize.length-1].isBase) return CodeMirror.Pass; - var firstChar = textAfter && textAfter.charAt(0), ctx = state.context; - if (ctx.type == "statement" && !expectExpression(state.lastToken, true)) ctx = ctx.prev; - var closing = firstChar == ctx.type; - if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : config.indentUnit); - else if (ctx.align) return ctx.column + (closing ? 0 : 1); - else return ctx.indented + (closing ? 0 : config.indentUnit); - }, - - electricChars: "{}", - closeBrackets: {triples: "'\""}, - fold: "brace" - }; -}); - -CodeMirror.defineMIME("text/x-groovy", "groovy"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/groovy/index.html b/backend/_pv_1_3_5/static/codemirror/mode/groovy/index.html deleted file mode 100755 index bb0df078c..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/groovy/index.html +++ /dev/null @@ -1,84 +0,0 @@ - - -CodeMirror: Groovy mode - - - - - - - - - - -
    -

    Groovy mode

    -
    - - - -

    MIME types defined: text/x-groovy

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/haml/haml.js b/backend/_pv_1_3_5/static/codemirror/mode/haml/haml.js deleted file mode 100755 index 20ae1e19c..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/haml/haml.js +++ /dev/null @@ -1,161 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../ruby/ruby")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../ruby/ruby"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - - // full haml mode. This handled embedded ruby and html fragments too - CodeMirror.defineMode("haml", function(config) { - var htmlMode = CodeMirror.getMode(config, {name: "htmlmixed"}); - var rubyMode = CodeMirror.getMode(config, "ruby"); - - function rubyInQuote(endQuote) { - return function(stream, state) { - var ch = stream.peek(); - if (ch == endQuote && state.rubyState.tokenize.length == 1) { - // step out of ruby context as it seems to complete processing all the braces - stream.next(); - state.tokenize = html; - return "closeAttributeTag"; - } else { - return ruby(stream, state); - } - }; - } - - function ruby(stream, state) { - if (stream.match("-#")) { - stream.skipToEnd(); - return "comment"; - } - return rubyMode.token(stream, state.rubyState); - } - - function html(stream, state) { - var ch = stream.peek(); - - // handle haml declarations. All declarations that cant be handled here - // will be passed to html mode - if (state.previousToken.style == "comment" ) { - if (state.indented > state.previousToken.indented) { - stream.skipToEnd(); - return "commentLine"; - } - } - - if (state.startOfLine) { - if (ch == "!" && stream.match("!!")) { - stream.skipToEnd(); - return "tag"; - } else if (stream.match(/^%[\w:#\.]+=/)) { - state.tokenize = ruby; - return "hamlTag"; - } else if (stream.match(/^%[\w:]+/)) { - return "hamlTag"; - } else if (ch == "/" ) { - stream.skipToEnd(); - return "comment"; - } - } - - if (state.startOfLine || state.previousToken.style == "hamlTag") { - if ( ch == "#" || ch == ".") { - stream.match(/[\w-#\.]*/); - return "hamlAttribute"; - } - } - - // donot handle --> as valid ruby, make it HTML close comment instead - if (state.startOfLine && !stream.match("-->", false) && (ch == "=" || ch == "-" )) { - state.tokenize = ruby; - return state.tokenize(stream, state); - } - - if (state.previousToken.style == "hamlTag" || - state.previousToken.style == "closeAttributeTag" || - state.previousToken.style == "hamlAttribute") { - if (ch == "(") { - state.tokenize = rubyInQuote(")"); - return state.tokenize(stream, state); - } else if (ch == "{") { - if (!stream.match(/^\{%.*/)) { - state.tokenize = rubyInQuote("}"); - return state.tokenize(stream, state); - } - } - } - - return htmlMode.token(stream, state.htmlState); - } - - return { - // default to html mode - startState: function() { - var htmlState = CodeMirror.startState(htmlMode); - var rubyState = CodeMirror.startState(rubyMode); - return { - htmlState: htmlState, - rubyState: rubyState, - indented: 0, - previousToken: { style: null, indented: 0}, - tokenize: html - }; - }, - - copyState: function(state) { - return { - htmlState : CodeMirror.copyState(htmlMode, state.htmlState), - rubyState: CodeMirror.copyState(rubyMode, state.rubyState), - indented: state.indented, - previousToken: state.previousToken, - tokenize: state.tokenize - }; - }, - - token: function(stream, state) { - if (stream.sol()) { - state.indented = stream.indentation(); - state.startOfLine = true; - } - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - state.startOfLine = false; - // dont record comment line as we only want to measure comment line with - // the opening comment block - if (style && style != "commentLine") { - state.previousToken = { style: style, indented: state.indented }; - } - // if current state is ruby and the previous token is not `,` reset the - // tokenize to html - if (stream.eol() && state.tokenize == ruby) { - stream.backUp(1); - var ch = stream.peek(); - stream.next(); - if (ch && ch != ",") { - state.tokenize = html; - } - } - // reprocess some of the specific style tag when finish setting previousToken - if (style == "hamlTag") { - style = "tag"; - } else if (style == "commentLine") { - style = "comment"; - } else if (style == "hamlAttribute") { - style = "attribute"; - } else if (style == "closeAttributeTag") { - style = null; - } - return style; - } - }; - }, "htmlmixed", "ruby"); - - CodeMirror.defineMIME("text/x-haml", "haml"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/haml/index.html b/backend/_pv_1_3_5/static/codemirror/mode/haml/index.html deleted file mode 100755 index 2894a938e..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/haml/index.html +++ /dev/null @@ -1,79 +0,0 @@ - - -CodeMirror: HAML mode - - - - - - - - - - - - - -
    -

    HAML mode

    -
    - - -

    MIME types defined: text/x-haml.

    - -

    Parsing/Highlighting Tests: normal, verbose.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/haml/test.js b/backend/_pv_1_3_5/static/codemirror/mode/haml/test.js deleted file mode 100755 index 508458a43..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/haml/test.js +++ /dev/null @@ -1,97 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, "haml"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - // Requires at least one media query - MT("elementName", - "[tag %h1] Hey There"); - - MT("oneElementPerLine", - "[tag %h1] Hey There %h2"); - - MT("idSelector", - "[tag %h1][attribute #test] Hey There"); - - MT("classSelector", - "[tag %h1][attribute .hello] Hey There"); - - MT("docType", - "[tag !!! XML]"); - - MT("comment", - "[comment / Hello WORLD]"); - - MT("notComment", - "[tag %h1] This is not a / comment "); - - MT("attributes", - "[tag %a]([variable title][operator =][string \"test\"]){[atom :title] [operator =>] [string \"test\"]}"); - - MT("htmlCode", - "[tag&bracket <][tag h1][tag&bracket >]Title[tag&bracket ]"); - - MT("rubyBlock", - "[operator =][variable-2 @item]"); - - MT("selectorRubyBlock", - "[tag %a.selector=] [variable-2 @item]"); - - MT("nestedRubyBlock", - "[tag %a]", - " [operator =][variable puts] [string \"test\"]"); - - MT("multilinePlaintext", - "[tag %p]", - " Hello,", - " World"); - - MT("multilineRuby", - "[tag %p]", - " [comment -# this is a comment]", - " [comment and this is a comment too]", - " Date/Time", - " [operator -] [variable now] [operator =] [tag DateTime][operator .][property now]", - " [tag %strong=] [variable now]", - " [operator -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][property parse]([string \"December 31, 2006\"])", - " [operator =][string \"Happy\"]", - " [operator =][string \"Belated\"]", - " [operator =][string \"Birthday\"]"); - - MT("multilineComment", - "[comment /]", - " [comment Multiline]", - " [comment Comment]"); - - MT("hamlComment", - "[comment -# this is a comment]"); - - MT("multilineHamlComment", - "[comment -# this is a comment]", - " [comment and this is a comment too]"); - - MT("multilineHTMLComment", - "[comment ]"); - - MT("hamlAfterRubyTag", - "[attribute .block]", - " [tag %strong=] [variable now]", - " [attribute .test]", - " [operator =][variable now]", - " [attribute .right]"); - - MT("stretchedRuby", - "[operator =] [variable puts] [string \"Hello\"],", - " [string \"World\"]"); - - MT("interpolationInHashAttribute", - //"[tag %div]{[atom :id] [operator =>] [string \"#{][variable test][string }_#{][variable ting][string }\"]} test"); - "[tag %div]{[atom :id] [operator =>] [string \"#{][variable test][string }_#{][variable ting][string }\"]} test"); - - MT("interpolationInHTMLAttribute", - "[tag %div]([variable title][operator =][string \"#{][variable test][string }_#{][variable ting]()[string }\"]) Test"); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/handlebars/handlebars.js b/backend/_pv_1_3_5/static/codemirror/mode/handlebars/handlebars.js deleted file mode 100755 index 2174e5384..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/handlebars/handlebars.js +++ /dev/null @@ -1,62 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../../addon/mode/simple"), require("../../addon/mode/multiplex")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../../addon/mode/simple", "../../addon/mode/multiplex"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineSimpleMode("handlebars-tags", { - start: [ - { regex: /\{\{!--/, push: "dash_comment", token: "comment" }, - { regex: /\{\{!/, push: "comment", token: "comment" }, - { regex: /\{\{/, push: "handlebars", token: "tag" } - ], - handlebars: [ - { regex: /\}\}/, pop: true, token: "tag" }, - - // Double and single quotes - { regex: /"(?:[^\\"]|\\.)*"?/, token: "string" }, - { regex: /'(?:[^\\']|\\.)*'?/, token: "string" }, - - // Handlebars keywords - { regex: />|[#\/]([A-Za-z_]\w*)/, token: "keyword" }, - { regex: /(?:else|this)\b/, token: "keyword" }, - - // Numeral - { regex: /\d+/i, token: "number" }, - - // Atoms like = and . - { regex: /=|~|@|true|false/, token: "atom" }, - - // Paths - { regex: /(?:\.\.\/)*(?:[A-Za-z_][\w\.]*)+/, token: "variable-2" } - ], - dash_comment: [ - { regex: /--\}\}/, pop: true, token: "comment" }, - - // Commented code - { regex: /./, token: "comment"} - ], - comment: [ - { regex: /\}\}/, pop: true, token: "comment" }, - { regex: /./, token: "comment" } - ] - }); - - CodeMirror.defineMode("handlebars", function(config, parserConfig) { - var handlebars = CodeMirror.getMode(config, "handlebars-tags"); - if (!parserConfig || !parserConfig.base) return handlebars; - return CodeMirror.multiplexingMode( - CodeMirror.getMode(config, parserConfig.base), - {open: "{{", close: "}}", mode: handlebars, parseDelimiters: true} - ); - }); - - CodeMirror.defineMIME("text/x-handlebars-template", "handlebars"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/handlebars/index.html b/backend/_pv_1_3_5/static/codemirror/mode/handlebars/index.html deleted file mode 100755 index b1bfad1ca..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/handlebars/index.html +++ /dev/null @@ -1,79 +0,0 @@ - - -CodeMirror: Handlebars mode - - - - - - - - - - - - -
    -

    Handlebars

    -
    - - -

    Handlebars syntax highlighting for CodeMirror.

    - -

    MIME types defined: text/x-handlebars-template

    - -

    Supported options: base to set the mode to - wrap. For example, use

    -
    mode: {name: "handlebars", base: "text/html"}
    -

    to highlight an HTML template.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/haskell-literate/haskell-literate.js b/backend/_pv_1_3_5/static/codemirror/mode/haskell-literate/haskell-literate.js deleted file mode 100755 index 906415b4c..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/haskell-literate/haskell-literate.js +++ /dev/null @@ -1,43 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function (mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../haskell/haskell")) - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../haskell/haskell"], mod) - else // Plain browser env - mod(CodeMirror) -})(function (CodeMirror) { - "use strict" - - CodeMirror.defineMode("haskell-literate", function (config, parserConfig) { - var baseMode = CodeMirror.getMode(config, (parserConfig && parserConfig.base) || "haskell") - - return { - startState: function () { - return { - inCode: false, - baseState: CodeMirror.startState(baseMode) - } - }, - token: function (stream, state) { - if (stream.sol()) { - if (state.inCode = stream.eat(">")) - return "meta" - } - if (state.inCode) { - return baseMode.token(stream, state.baseState) - } else { - stream.skipToEnd() - return "comment" - } - }, - innerMode: function (state) { - return state.inCode ? {state: state.baseState, mode: baseMode} : null - } - } - }, "haskell") - - CodeMirror.defineMIME("text/x-literate-haskell", "haskell-literate") -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/haskell-literate/index.html b/backend/_pv_1_3_5/static/codemirror/mode/haskell-literate/index.html deleted file mode 100755 index 8c9bc60d1..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/haskell-literate/index.html +++ /dev/null @@ -1,282 +0,0 @@ - - -CodeMirror: Haskell-literate mode - - - - - - - - - - -
    -

    Haskell literate mode

    -
    - -
    - -

    MIME types - defined: text/x-literate-haskell.

    - -

    Parser configuration parameters recognized: base to - set the base mode (defaults to "haskell").

    - - - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/haskell/haskell.js b/backend/_pv_1_3_5/static/codemirror/mode/haskell/haskell.js deleted file mode 100755 index 4197666a4..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/haskell/haskell.js +++ /dev/null @@ -1,267 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("haskell", function(_config, modeConfig) { - - function switchState(source, setState, f) { - setState(f); - return f(source, setState); - } - - // These should all be Unicode extended, as per the Haskell 2010 report - var smallRE = /[a-z_]/; - var largeRE = /[A-Z]/; - var digitRE = /\d/; - var hexitRE = /[0-9A-Fa-f]/; - var octitRE = /[0-7]/; - var idRE = /[a-z_A-Z0-9'\xa1-\uffff]/; - var symbolRE = /[-!#$%&*+.\/<=>?@\\^|~:]/; - var specialRE = /[(),;[\]`{}]/; - var whiteCharRE = /[ \t\v\f]/; // newlines are handled in tokenizer - - function normal(source, setState) { - if (source.eatWhile(whiteCharRE)) { - return null; - } - - var ch = source.next(); - if (specialRE.test(ch)) { - if (ch == '{' && source.eat('-')) { - var t = "comment"; - if (source.eat('#')) { - t = "meta"; - } - return switchState(source, setState, ncomment(t, 1)); - } - return null; - } - - if (ch == '\'') { - if (source.eat('\\')) { - source.next(); // should handle other escapes here - } - else { - source.next(); - } - if (source.eat('\'')) { - return "string"; - } - return "string error"; - } - - if (ch == '"') { - return switchState(source, setState, stringLiteral); - } - - if (largeRE.test(ch)) { - source.eatWhile(idRE); - if (source.eat('.')) { - return "qualifier"; - } - return "variable-2"; - } - - if (smallRE.test(ch)) { - source.eatWhile(idRE); - return "variable"; - } - - if (digitRE.test(ch)) { - if (ch == '0') { - if (source.eat(/[xX]/)) { - source.eatWhile(hexitRE); // should require at least 1 - return "integer"; - } - if (source.eat(/[oO]/)) { - source.eatWhile(octitRE); // should require at least 1 - return "number"; - } - } - source.eatWhile(digitRE); - var t = "number"; - if (source.match(/^\.\d+/)) { - t = "number"; - } - if (source.eat(/[eE]/)) { - t = "number"; - source.eat(/[-+]/); - source.eatWhile(digitRE); // should require at least 1 - } - return t; - } - - if (ch == "." && source.eat(".")) - return "keyword"; - - if (symbolRE.test(ch)) { - if (ch == '-' && source.eat(/-/)) { - source.eatWhile(/-/); - if (!source.eat(symbolRE)) { - source.skipToEnd(); - return "comment"; - } - } - var t = "variable"; - if (ch == ':') { - t = "variable-2"; - } - source.eatWhile(symbolRE); - return t; - } - - return "error"; - } - - function ncomment(type, nest) { - if (nest == 0) { - return normal; - } - return function(source, setState) { - var currNest = nest; - while (!source.eol()) { - var ch = source.next(); - if (ch == '{' && source.eat('-')) { - ++currNest; - } - else if (ch == '-' && source.eat('}')) { - --currNest; - if (currNest == 0) { - setState(normal); - return type; - } - } - } - setState(ncomment(type, currNest)); - return type; - }; - } - - function stringLiteral(source, setState) { - while (!source.eol()) { - var ch = source.next(); - if (ch == '"') { - setState(normal); - return "string"; - } - if (ch == '\\') { - if (source.eol() || source.eat(whiteCharRE)) { - setState(stringGap); - return "string"; - } - if (source.eat('&')) { - } - else { - source.next(); // should handle other escapes here - } - } - } - setState(normal); - return "string error"; - } - - function stringGap(source, setState) { - if (source.eat('\\')) { - return switchState(source, setState, stringLiteral); - } - source.next(); - setState(normal); - return "error"; - } - - - var wellKnownWords = (function() { - var wkw = {}; - function setType(t) { - return function () { - for (var i = 0; i < arguments.length; i++) - wkw[arguments[i]] = t; - }; - } - - setType("keyword")( - "case", "class", "data", "default", "deriving", "do", "else", "foreign", - "if", "import", "in", "infix", "infixl", "infixr", "instance", "let", - "module", "newtype", "of", "then", "type", "where", "_"); - - setType("keyword")( - "\.\.", ":", "::", "=", "\\", "<-", "->", "@", "~", "=>"); - - setType("builtin")( - "!!", "$!", "$", "&&", "+", "++", "-", ".", "/", "/=", "<", "<=", "=<<", - "==", ">", ">=", ">>", ">>=", "^", "^^", "||", "*", "**"); - - setType("builtin")( - "Bool", "Bounded", "Char", "Double", "EQ", "Either", "Enum", "Eq", - "False", "FilePath", "Float", "Floating", "Fractional", "Functor", "GT", - "IO", "IOError", "Int", "Integer", "Integral", "Just", "LT", "Left", - "Maybe", "Monad", "Nothing", "Num", "Ord", "Ordering", "Rational", "Read", - "ReadS", "Real", "RealFloat", "RealFrac", "Right", "Show", "ShowS", - "String", "True"); - - setType("builtin")( - "abs", "acos", "acosh", "all", "and", "any", "appendFile", "asTypeOf", - "asin", "asinh", "atan", "atan2", "atanh", "break", "catch", "ceiling", - "compare", "concat", "concatMap", "const", "cos", "cosh", "curry", - "cycle", "decodeFloat", "div", "divMod", "drop", "dropWhile", "either", - "elem", "encodeFloat", "enumFrom", "enumFromThen", "enumFromThenTo", - "enumFromTo", "error", "even", "exp", "exponent", "fail", "filter", - "flip", "floatDigits", "floatRadix", "floatRange", "floor", "fmap", - "foldl", "foldl1", "foldr", "foldr1", "fromEnum", "fromInteger", - "fromIntegral", "fromRational", "fst", "gcd", "getChar", "getContents", - "getLine", "head", "id", "init", "interact", "ioError", "isDenormalized", - "isIEEE", "isInfinite", "isNaN", "isNegativeZero", "iterate", "last", - "lcm", "length", "lex", "lines", "log", "logBase", "lookup", "map", - "mapM", "mapM_", "max", "maxBound", "maximum", "maybe", "min", "minBound", - "minimum", "mod", "negate", "not", "notElem", "null", "odd", "or", - "otherwise", "pi", "pred", "print", "product", "properFraction", - "putChar", "putStr", "putStrLn", "quot", "quotRem", "read", "readFile", - "readIO", "readList", "readLn", "readParen", "reads", "readsPrec", - "realToFrac", "recip", "rem", "repeat", "replicate", "return", "reverse", - "round", "scaleFloat", "scanl", "scanl1", "scanr", "scanr1", "seq", - "sequence", "sequence_", "show", "showChar", "showList", "showParen", - "showString", "shows", "showsPrec", "significand", "signum", "sin", - "sinh", "snd", "span", "splitAt", "sqrt", "subtract", "succ", "sum", - "tail", "take", "takeWhile", "tan", "tanh", "toEnum", "toInteger", - "toRational", "truncate", "uncurry", "undefined", "unlines", "until", - "unwords", "unzip", "unzip3", "userError", "words", "writeFile", "zip", - "zip3", "zipWith", "zipWith3"); - - var override = modeConfig.overrideKeywords; - if (override) for (var word in override) if (override.hasOwnProperty(word)) - wkw[word] = override[word]; - - return wkw; - })(); - - - - return { - startState: function () { return { f: normal }; }, - copyState: function (s) { return { f: s.f }; }, - - token: function(stream, state) { - var t = state.f(stream, function(s) { state.f = s; }); - var w = stream.current(); - return wellKnownWords.hasOwnProperty(w) ? wellKnownWords[w] : t; - }, - - blockCommentStart: "{-", - blockCommentEnd: "-}", - lineComment: "--" - }; - -}); - -CodeMirror.defineMIME("text/x-haskell", "haskell"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/haskell/index.html b/backend/_pv_1_3_5/static/codemirror/mode/haskell/index.html deleted file mode 100755 index 42240b0f2..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/haskell/index.html +++ /dev/null @@ -1,73 +0,0 @@ - - -CodeMirror: Haskell mode - - - - - - - - - - - -
    -

    Haskell mode

    -
    - - - -

    MIME types defined: text/x-haskell.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/haxe/haxe.js b/backend/_pv_1_3_5/static/codemirror/mode/haxe/haxe.js deleted file mode 100755 index a9573dd71..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/haxe/haxe.js +++ /dev/null @@ -1,515 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("haxe", function(config, parserConfig) { - var indentUnit = config.indentUnit; - - // Tokenizer - - function kw(type) {return {type: type, style: "keyword"};} - var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); - var operator = kw("operator"), atom = {type: "atom", style: "atom"}, attribute = {type:"attribute", style: "attribute"}; - var type = kw("typedef"); - var keywords = { - "if": A, "while": A, "else": B, "do": B, "try": B, - "return": C, "break": C, "continue": C, "new": C, "throw": C, - "var": kw("var"), "inline":attribute, "static": attribute, "using":kw("import"), - "public": attribute, "private": attribute, "cast": kw("cast"), "import": kw("import"), "macro": kw("macro"), - "function": kw("function"), "catch": kw("catch"), "untyped": kw("untyped"), "callback": kw("cb"), - "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), - "in": operator, "never": kw("property_access"), "trace":kw("trace"), - "class": type, "abstract":type, "enum":type, "interface":type, "typedef":type, "extends":type, "implements":type, "dynamic":type, - "true": atom, "false": atom, "null": atom - }; - - var isOperatorChar = /[+\-*&%=<>!?|]/; - - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - - function toUnescaped(stream, end) { - var escaped = false, next; - while ((next = stream.next()) != null) { - if (next == end && !escaped) - return true; - escaped = !escaped && next == "\\"; - } - } - - // Used as scratch variables to communicate multiple values without - // consing up tons of objects. - var type, content; - function ret(tp, style, cont) { - type = tp; content = cont; - return style; - } - - function haxeTokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"' || ch == "'") { - return chain(stream, state, haxeTokenString(ch)); - } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - return ret(ch); - } else if (ch == "0" && stream.eat(/x/i)) { - stream.eatWhile(/[\da-f]/i); - return ret("number", "number"); - } else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) { - stream.match(/^\d*(?:\.\d*(?!\.))?(?:[eE][+\-]?\d+)?/); - return ret("number", "number"); - } else if (state.reAllowed && (ch == "~" && stream.eat(/\//))) { - toUnescaped(stream, "/"); - stream.eatWhile(/[gimsu]/); - return ret("regexp", "string-2"); - } else if (ch == "/") { - if (stream.eat("*")) { - return chain(stream, state, haxeTokenComment); - } else if (stream.eat("/")) { - stream.skipToEnd(); - return ret("comment", "comment"); - } else { - stream.eatWhile(isOperatorChar); - return ret("operator", null, stream.current()); - } - } else if (ch == "#") { - stream.skipToEnd(); - return ret("conditional", "meta"); - } else if (ch == "@") { - stream.eat(/:/); - stream.eatWhile(/[\w_]/); - return ret ("metadata", "meta"); - } else if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return ret("operator", null, stream.current()); - } else { - var word; - if(/[A-Z]/.test(ch)) { - stream.eatWhile(/[\w_<>]/); - word = stream.current(); - return ret("type", "variable-3", word); - } else { - stream.eatWhile(/[\w_]/); - var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word]; - return (known && state.kwAllowed) ? ret(known.type, known.style, word) : - ret("variable", "variable", word); - } - } - } - - function haxeTokenString(quote) { - return function(stream, state) { - if (toUnescaped(stream, quote)) - state.tokenize = haxeTokenBase; - return ret("string", "string"); - }; - } - - function haxeTokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = haxeTokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return ret("comment", "comment"); - } - - // Parser - - var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true}; - - function HaxeLexical(indented, column, type, align, prev, info) { - this.indented = indented; - this.column = column; - this.type = type; - this.prev = prev; - this.info = info; - if (align != null) this.align = align; - } - - function inScope(state, varname) { - for (var v = state.localVars; v; v = v.next) - if (v.name == varname) return true; - } - - function parseHaxe(state, style, type, content, stream) { - var cc = state.cc; - // Communicate our context to the combinators. - // (Less wasteful than consing up a hundred closures on every call.) - cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; - - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = true; - - while(true) { - var combinator = cc.length ? cc.pop() : statement; - if (combinator(type, content)) { - while(cc.length && cc[cc.length - 1].lex) - cc.pop()(); - if (cx.marked) return cx.marked; - if (type == "variable" && inScope(state, content)) return "variable-2"; - if (type == "variable" && imported(state, content)) return "variable-3"; - return style; - } - } - } - - function imported(state, typename) { - if (/[a-z]/.test(typename.charAt(0))) - return false; - var len = state.importedtypes.length; - for (var i = 0; i= 0; i--) cx.cc.push(arguments[i]); - } - function cont() { - pass.apply(null, arguments); - return true; - } - function inList(name, list) { - for (var v = list; v; v = v.next) - if (v.name == name) return true; - return false; - } - function register(varname) { - var state = cx.state; - if (state.context) { - cx.marked = "def"; - if (inList(varname, state.localVars)) return; - state.localVars = {name: varname, next: state.localVars}; - } else if (state.globalVars) { - if (inList(varname, state.globalVars)) return; - state.globalVars = {name: varname, next: state.globalVars}; - } - } - - // Combinators - - var defaultVars = {name: "this", next: null}; - function pushcontext() { - if (!cx.state.context) cx.state.localVars = defaultVars; - cx.state.context = {prev: cx.state.context, vars: cx.state.localVars}; - } - function popcontext() { - cx.state.localVars = cx.state.context.vars; - cx.state.context = cx.state.context.prev; - } - popcontext.lex = true; - function pushlex(type, info) { - var result = function() { - var state = cx.state; - state.lexical = new HaxeLexical(state.indented, cx.stream.column(), type, null, state.lexical, info); - }; - result.lex = true; - return result; - } - function poplex() { - var state = cx.state; - if (state.lexical.prev) { - if (state.lexical.type == ")") - state.indented = state.lexical.indented; - state.lexical = state.lexical.prev; - } - } - poplex.lex = true; - - function expect(wanted) { - function f(type) { - if (type == wanted) return cont(); - else if (wanted == ";") return pass(); - else return cont(f); - } - return f; - } - - function statement(type) { - if (type == "@") return cont(metadef); - if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex); - if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex); - if (type == "keyword b") return cont(pushlex("form"), statement, poplex); - if (type == "{") return cont(pushlex("}"), pushcontext, block, poplex, popcontext); - if (type == ";") return cont(); - if (type == "attribute") return cont(maybeattribute); - if (type == "function") return cont(functiondef); - if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"), - poplex, statement, poplex); - if (type == "variable") return cont(pushlex("stat"), maybelabel); - if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"), - block, poplex, poplex); - if (type == "case") return cont(expression, expect(":")); - if (type == "default") return cont(expect(":")); - if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), - statement, poplex, popcontext); - if (type == "import") return cont(importdef, expect(";")); - if (type == "typedef") return cont(typedef); - return pass(pushlex("stat"), expression, expect(";"), poplex); - } - function expression(type) { - if (atomicTypes.hasOwnProperty(type)) return cont(maybeoperator); - if (type == "type" ) return cont(maybeoperator); - if (type == "function") return cont(functiondef); - if (type == "keyword c") return cont(maybeexpression); - if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeoperator); - if (type == "operator") return cont(expression); - if (type == "[") return cont(pushlex("]"), commasep(maybeexpression, "]"), poplex, maybeoperator); - if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeoperator); - return cont(); - } - function maybeexpression(type) { - if (type.match(/[;\}\)\],]/)) return pass(); - return pass(expression); - } - - function maybeoperator(type, value) { - if (type == "operator" && /\+\+|--/.test(value)) return cont(maybeoperator); - if (type == "operator" || type == ":") return cont(expression); - if (type == ";") return; - if (type == "(") return cont(pushlex(")"), commasep(expression, ")"), poplex, maybeoperator); - if (type == ".") return cont(property, maybeoperator); - if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, maybeoperator); - } - - function maybeattribute(type) { - if (type == "attribute") return cont(maybeattribute); - if (type == "function") return cont(functiondef); - if (type == "var") return cont(vardef1); - } - - function metadef(type) { - if(type == ":") return cont(metadef); - if(type == "variable") return cont(metadef); - if(type == "(") return cont(pushlex(")"), commasep(metaargs, ")"), poplex, statement); - } - function metaargs(type) { - if(type == "variable") return cont(); - } - - function importdef (type, value) { - if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); } - else if(type == "variable" || type == "property" || type == "." || value == "*") return cont(importdef); - } - - function typedef (type, value) - { - if(type == "variable" && /[A-Z]/.test(value.charAt(0))) { registerimport(value); return cont(); } - else if (type == "type" && /[A-Z]/.test(value.charAt(0))) { return cont(); } - } - - function maybelabel(type) { - if (type == ":") return cont(poplex, statement); - return pass(maybeoperator, expect(";"), poplex); - } - function property(type) { - if (type == "variable") {cx.marked = "property"; return cont();} - } - function objprop(type) { - if (type == "variable") cx.marked = "property"; - if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expression); - } - function commasep(what, end) { - function proceed(type) { - if (type == ",") return cont(what, proceed); - if (type == end) return cont(); - return cont(expect(end)); - } - return function(type) { - if (type == end) return cont(); - else return pass(what, proceed); - }; - } - function block(type) { - if (type == "}") return cont(); - return pass(statement, block); - } - function vardef1(type, value) { - if (type == "variable"){register(value); return cont(typeuse, vardef2);} - return cont(); - } - function vardef2(type, value) { - if (value == "=") return cont(expression, vardef2); - if (type == ",") return cont(vardef1); - } - function forspec1(type, value) { - if (type == "variable") { - register(value); - return cont(forin, expression) - } else { - return pass() - } - } - function forin(_type, value) { - if (value == "in") return cont(); - } - function functiondef(type, value) { - //function names starting with upper-case letters are recognised as types, so cludging them together here. - if (type == "variable" || type == "type") {register(value); return cont(functiondef);} - if (value == "new") return cont(functiondef); - if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, typeuse, statement, popcontext); - } - function typeuse(type) { - if(type == ":") return cont(typestring); - } - function typestring(type) { - if(type == "type") return cont(); - if(type == "variable") return cont(); - if(type == "{") return cont(pushlex("}"), commasep(typeprop, "}"), poplex); - } - function typeprop(type) { - if(type == "variable") return cont(typeuse); - } - function funarg(type, value) { - if (type == "variable") {register(value); return cont(typeuse);} - } - - // Interface - return { - startState: function(basecolumn) { - var defaulttypes = ["Int", "Float", "String", "Void", "Std", "Bool", "Dynamic", "Array"]; - var state = { - tokenize: haxeTokenBase, - reAllowed: true, - kwAllowed: true, - cc: [], - lexical: new HaxeLexical((basecolumn || 0) - indentUnit, 0, "block", false), - localVars: parserConfig.localVars, - importedtypes: defaulttypes, - context: parserConfig.localVars && {vars: parserConfig.localVars}, - indented: 0 - }; - if (parserConfig.globalVars && typeof parserConfig.globalVars == "object") - state.globalVars = parserConfig.globalVars; - return state; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = false; - state.indented = stream.indentation(); - } - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - if (type == "comment") return style; - state.reAllowed = !!(type == "operator" || type == "keyword c" || type.match(/^[\[{}\(,;:]$/)); - state.kwAllowed = type != '.'; - return parseHaxe(state, style, type, content, stream); - }, - - indent: function(state, textAfter) { - if (state.tokenize != haxeTokenBase) return 0; - var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical; - if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev; - var type = lexical.type, closing = firstChar == type; - if (type == "vardef") return lexical.indented + 4; - else if (type == "form" && firstChar == "{") return lexical.indented; - else if (type == "stat" || type == "form") return lexical.indented + indentUnit; - else if (lexical.info == "switch" && !closing) - return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit); - else if (lexical.align) return lexical.column + (closing ? 0 : 1); - else return lexical.indented + (closing ? 0 : indentUnit); - }, - - electricChars: "{}", - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: "//" - }; -}); - -CodeMirror.defineMIME("text/x-haxe", "haxe"); - -CodeMirror.defineMode("hxml", function () { - - return { - startState: function () { - return { - define: false, - inString: false - }; - }, - token: function (stream, state) { - var ch = stream.peek(); - var sol = stream.sol(); - - ///* comments */ - if (ch == "#") { - stream.skipToEnd(); - return "comment"; - } - if (sol && ch == "-") { - var style = "variable-2"; - - stream.eat(/-/); - - if (stream.peek() == "-") { - stream.eat(/-/); - style = "keyword a"; - } - - if (stream.peek() == "D") { - stream.eat(/[D]/); - style = "keyword c"; - state.define = true; - } - - stream.eatWhile(/[A-Z]/i); - return style; - } - - var ch = stream.peek(); - - if (state.inString == false && ch == "'") { - state.inString = true; - ch = stream.next(); - } - - if (state.inString == true) { - if (stream.skipTo("'")) { - - } else { - stream.skipToEnd(); - } - - if (stream.peek() == "'") { - stream.next(); - state.inString = false; - } - - return "string"; - } - - stream.next(); - return null; - }, - lineComment: "#" - }; -}); - -CodeMirror.defineMIME("text/x-hxml", "hxml"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/haxe/index.html b/backend/_pv_1_3_5/static/codemirror/mode/haxe/index.html deleted file mode 100755 index d415b5e10..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/haxe/index.html +++ /dev/null @@ -1,124 +0,0 @@ - - -CodeMirror: Haxe mode - - - - - - - - - -
    -

    Haxe mode

    - - -

    - -

    Hxml mode:

    - -

    -
    - - - -

    MIME types defined: text/x-haxe, text/x-hxml.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/htmlembedded/htmlembedded.js b/backend/_pv_1_3_5/static/codemirror/mode/htmlembedded/htmlembedded.js deleted file mode 100755 index 464dc57f8..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/htmlembedded/htmlembedded.js +++ /dev/null @@ -1,28 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), - require("../../addon/mode/multiplex")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../htmlmixed/htmlmixed", - "../../addon/mode/multiplex"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("htmlembedded", function(config, parserConfig) { - return CodeMirror.multiplexingMode(CodeMirror.getMode(config, "htmlmixed"), { - open: parserConfig.open || parserConfig.scriptStartRegex || "<%", - close: parserConfig.close || parserConfig.scriptEndRegex || "%>", - mode: CodeMirror.getMode(config, parserConfig.scriptingModeSpec) - }); - }, "htmlmixed"); - - CodeMirror.defineMIME("application/x-ejs", {name: "htmlembedded", scriptingModeSpec:"javascript"}); - CodeMirror.defineMIME("application/x-aspx", {name: "htmlembedded", scriptingModeSpec:"text/x-csharp"}); - CodeMirror.defineMIME("application/x-jsp", {name: "htmlembedded", scriptingModeSpec:"text/x-java"}); - CodeMirror.defineMIME("application/x-erb", {name: "htmlembedded", scriptingModeSpec:"ruby"}); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/htmlembedded/index.html b/backend/_pv_1_3_5/static/codemirror/mode/htmlembedded/index.html deleted file mode 100755 index 9ed33cffe..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/htmlembedded/index.html +++ /dev/null @@ -1,60 +0,0 @@ - - -CodeMirror: Html Embedded Scripts mode - - - - - - - - - - - - - - -
    -

    Html Embedded Scripts mode

    -
    - - - -

    Mode for html embedded scripts like JSP and ASP.NET. Depends on multiplex and HtmlMixed which in turn depends on - JavaScript, CSS and XML.
    Other dependencies include those of the scripting language chosen.

    - -

    MIME types defined: application/x-aspx (ASP.NET), - application/x-ejs (Embedded Javascript), application/x-jsp (JavaServer Pages) - and application/x-erb

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/htmlmixed/htmlmixed.js b/backend/_pv_1_3_5/static/codemirror/mode/htmlmixed/htmlmixed.js deleted file mode 100755 index eb21fcc14..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/htmlmixed/htmlmixed.js +++ /dev/null @@ -1,152 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript"), require("../css/css")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript", "../css/css"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - var defaultTags = { - script: [ - ["lang", /(javascript|babel)/i, "javascript"], - ["type", /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i, "javascript"], - ["type", /./, "text/plain"], - [null, null, "javascript"] - ], - style: [ - ["lang", /^css$/i, "css"], - ["type", /^(text\/)?(x-)?(stylesheet|css)$/i, "css"], - ["type", /./, "text/plain"], - [null, null, "css"] - ] - }; - - function maybeBackup(stream, pat, style) { - var cur = stream.current(), close = cur.search(pat); - if (close > -1) { - stream.backUp(cur.length - close); - } else if (cur.match(/<\/?$/)) { - stream.backUp(cur.length); - if (!stream.match(pat, false)) stream.match(cur); - } - return style; - } - - var attrRegexpCache = {}; - function getAttrRegexp(attr) { - var regexp = attrRegexpCache[attr]; - if (regexp) return regexp; - return attrRegexpCache[attr] = new RegExp("\\s+" + attr + "\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*"); - } - - function getAttrValue(text, attr) { - var match = text.match(getAttrRegexp(attr)) - return match ? /^\s*(.*?)\s*$/.exec(match[2])[1] : "" - } - - function getTagRegexp(tagName, anchored) { - return new RegExp((anchored ? "^" : "") + "<\/\s*" + tagName + "\s*>", "i"); - } - - function addTags(from, to) { - for (var tag in from) { - var dest = to[tag] || (to[tag] = []); - var source = from[tag]; - for (var i = source.length - 1; i >= 0; i--) - dest.unshift(source[i]) - } - } - - function findMatchingMode(tagInfo, tagText) { - for (var i = 0; i < tagInfo.length; i++) { - var spec = tagInfo[i]; - if (!spec[0] || spec[1].test(getAttrValue(tagText, spec[0]))) return spec[2]; - } - } - - CodeMirror.defineMode("htmlmixed", function (config, parserConfig) { - var htmlMode = CodeMirror.getMode(config, { - name: "xml", - htmlMode: true, - multilineTagIndentFactor: parserConfig.multilineTagIndentFactor, - multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag - }); - - var tags = {}; - var configTags = parserConfig && parserConfig.tags, configScript = parserConfig && parserConfig.scriptTypes; - addTags(defaultTags, tags); - if (configTags) addTags(configTags, tags); - if (configScript) for (var i = configScript.length - 1; i >= 0; i--) - tags.script.unshift(["type", configScript[i].matches, configScript[i].mode]) - - function html(stream, state) { - var style = htmlMode.token(stream, state.htmlState), tag = /\btag\b/.test(style), tagName - if (tag && !/[<>\s\/]/.test(stream.current()) && - (tagName = state.htmlState.tagName && state.htmlState.tagName.toLowerCase()) && - tags.hasOwnProperty(tagName)) { - state.inTag = tagName + " " - } else if (state.inTag && tag && />$/.test(stream.current())) { - var inTag = /^([\S]+) (.*)/.exec(state.inTag) - state.inTag = null - var modeSpec = stream.current() == ">" && findMatchingMode(tags[inTag[1]], inTag[2]) - var mode = CodeMirror.getMode(config, modeSpec) - var endTagA = getTagRegexp(inTag[1], true), endTag = getTagRegexp(inTag[1], false); - state.token = function (stream, state) { - if (stream.match(endTagA, false)) { - state.token = html; - state.localState = state.localMode = null; - return null; - } - return maybeBackup(stream, endTag, state.localMode.token(stream, state.localState)); - }; - state.localMode = mode; - state.localState = CodeMirror.startState(mode, htmlMode.indent(state.htmlState, "")); - } else if (state.inTag) { - state.inTag += stream.current() - if (stream.eol()) state.inTag += " " - } - return style; - }; - - return { - startState: function () { - var state = CodeMirror.startState(htmlMode); - return {token: html, inTag: null, localMode: null, localState: null, htmlState: state}; - }, - - copyState: function (state) { - var local; - if (state.localState) { - local = CodeMirror.copyState(state.localMode, state.localState); - } - return {token: state.token, inTag: state.inTag, - localMode: state.localMode, localState: local, - htmlState: CodeMirror.copyState(htmlMode, state.htmlState)}; - }, - - token: function (stream, state) { - return state.token(stream, state); - }, - - indent: function (state, textAfter) { - if (!state.localMode || /^\s*<\//.test(textAfter)) - return htmlMode.indent(state.htmlState, textAfter); - else if (state.localMode.indent) - return state.localMode.indent(state.localState, textAfter); - else - return CodeMirror.Pass; - }, - - innerMode: function (state) { - return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode}; - } - }; - }, "xml", "javascript", "css"); - - CodeMirror.defineMIME("text/html", "htmlmixed"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/htmlmixed/index.html b/backend/_pv_1_3_5/static/codemirror/mode/htmlmixed/index.html deleted file mode 100755 index caa7546c1..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/htmlmixed/index.html +++ /dev/null @@ -1,100 +0,0 @@ - - -CodeMirror: HTML mixed mode - - - - - - - - - - - - - - -
    -

    HTML mixed mode

    -
    - - -

    The HTML mixed mode depends on the XML, JavaScript, and CSS modes.

    - -

    It takes an optional mode configuration - option, tags, which can be used to add custom - behavior for specific tags. When given, it should be an object - mapping tag names (for example script) to arrays or - three-element arrays. Those inner arrays indicate [attributeName, - valueRegexp, modeSpec] - specifications. For example, you could use ["type", /^foo$/, - "foo"] to map the attribute type="foo" to - the foo mode. When the first two fields are null - ([null, null, "mode"]), the given mode is used for - any such tag that doesn't match any of the previously given - attributes. For example:

    - -
    var myModeSpec = {
    -  name: "htmlmixed",
    -  tags: {
    -    style: [["type", /^text/(x-)?scss$/, "text/x-scss"],
    -            [null, null, "css"]],
    -    custom: [[null, null, "customMode"]]
    -  }
    -}
    - -

    MIME types defined: text/html - (redefined, only takes effect if you load this parser after the - XML parser).

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/http/http.js b/backend/_pv_1_3_5/static/codemirror/mode/http/http.js deleted file mode 100755 index 9a3c5f9fd..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/http/http.js +++ /dev/null @@ -1,113 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("http", function() { - function failFirstLine(stream, state) { - stream.skipToEnd(); - state.cur = header; - return "error"; - } - - function start(stream, state) { - if (stream.match(/^HTTP\/\d\.\d/)) { - state.cur = responseStatusCode; - return "keyword"; - } else if (stream.match(/^[A-Z]+/) && /[ \t]/.test(stream.peek())) { - state.cur = requestPath; - return "keyword"; - } else { - return failFirstLine(stream, state); - } - } - - function responseStatusCode(stream, state) { - var code = stream.match(/^\d+/); - if (!code) return failFirstLine(stream, state); - - state.cur = responseStatusText; - var status = Number(code[0]); - if (status >= 100 && status < 200) { - return "positive informational"; - } else if (status >= 200 && status < 300) { - return "positive success"; - } else if (status >= 300 && status < 400) { - return "positive redirect"; - } else if (status >= 400 && status < 500) { - return "negative client-error"; - } else if (status >= 500 && status < 600) { - return "negative server-error"; - } else { - return "error"; - } - } - - function responseStatusText(stream, state) { - stream.skipToEnd(); - state.cur = header; - return null; - } - - function requestPath(stream, state) { - stream.eatWhile(/\S/); - state.cur = requestProtocol; - return "string-2"; - } - - function requestProtocol(stream, state) { - if (stream.match(/^HTTP\/\d\.\d$/)) { - state.cur = header; - return "keyword"; - } else { - return failFirstLine(stream, state); - } - } - - function header(stream) { - if (stream.sol() && !stream.eat(/[ \t]/)) { - if (stream.match(/^.*?:/)) { - return "atom"; - } else { - stream.skipToEnd(); - return "error"; - } - } else { - stream.skipToEnd(); - return "string"; - } - } - - function body(stream) { - stream.skipToEnd(); - return null; - } - - return { - token: function(stream, state) { - var cur = state.cur; - if (cur != header && cur != body && stream.eatSpace()) return null; - return cur(stream, state); - }, - - blankLine: function(state) { - state.cur = body; - }, - - startState: function() { - return {cur: start}; - } - }; -}); - -CodeMirror.defineMIME("message/http", "http"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/http/index.html b/backend/_pv_1_3_5/static/codemirror/mode/http/index.html deleted file mode 100755 index 0b8d5315d..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/http/index.html +++ /dev/null @@ -1,45 +0,0 @@ - - -CodeMirror: HTTP mode - - - - - - - - - -
    -

    HTTP mode

    - - -
    - - - -

    MIME types defined: message/http.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/idl/idl.js b/backend/_pv_1_3_5/static/codemirror/mode/idl/idl.js deleted file mode 100755 index 07308d71d..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/idl/idl.js +++ /dev/null @@ -1,290 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - function wordRegexp(words) { - return new RegExp('^((' + words.join(')|(') + '))\\b', 'i'); - }; - - var builtinArray = [ - 'a_correlate', 'abs', 'acos', 'adapt_hist_equal', 'alog', - 'alog2', 'alog10', 'amoeba', 'annotate', 'app_user_dir', - 'app_user_dir_query', 'arg_present', 'array_equal', 'array_indices', - 'arrow', 'ascii_template', 'asin', 'assoc', 'atan', - 'axis', 'axis', 'bandpass_filter', 'bandreject_filter', 'barplot', - 'bar_plot', 'beseli', 'beselj', 'beselk', 'besely', - 'beta', 'biginteger', 'bilinear', 'bin_date', 'binary_template', - 'bindgen', 'binomial', 'bit_ffs', 'bit_population', 'blas_axpy', - 'blk_con', 'boolarr', 'boolean', 'boxplot', 'box_cursor', - 'breakpoint', 'broyden', 'bubbleplot', 'butterworth', 'bytarr', - 'byte', 'byteorder', 'bytscl', 'c_correlate', 'calendar', - 'caldat', 'call_external', 'call_function', 'call_method', - 'call_procedure', 'canny', 'catch', 'cd', 'cdf', 'ceil', - 'chebyshev', 'check_math', 'chisqr_cvf', 'chisqr_pdf', 'choldc', - 'cholsol', 'cindgen', 'cir_3pnt', 'clipboard', 'close', - 'clust_wts', 'cluster', 'cluster_tree', 'cmyk_convert', 'code_coverage', - 'color_convert', 'color_exchange', 'color_quan', 'color_range_map', - 'colorbar', 'colorize_sample', 'colormap_applicable', - 'colormap_gradient', 'colormap_rotation', 'colortable', - 'comfit', 'command_line_args', 'common', 'compile_opt', 'complex', - 'complexarr', 'complexround', 'compute_mesh_normals', 'cond', 'congrid', - 'conj', 'constrained_min', 'contour', 'contour', 'convert_coord', - 'convol', 'convol_fft', 'coord2to3', 'copy_lun', 'correlate', - 'cos', 'cosh', 'cpu', 'cramer', 'createboxplotdata', - 'create_cursor', 'create_struct', 'create_view', 'crossp', 'crvlength', - 'ct_luminance', 'cti_test', 'cursor', 'curvefit', 'cv_coord', - 'cvttobm', 'cw_animate', 'cw_animate_getp', 'cw_animate_load', - 'cw_animate_run', 'cw_arcball', 'cw_bgroup', 'cw_clr_index', - 'cw_colorsel', 'cw_defroi', 'cw_field', 'cw_filesel', 'cw_form', - 'cw_fslider', 'cw_light_editor', 'cw_light_editor_get', - 'cw_light_editor_set', 'cw_orient', 'cw_palette_editor', - 'cw_palette_editor_get', 'cw_palette_editor_set', 'cw_pdmenu', - 'cw_rgbslider', 'cw_tmpl', 'cw_zoom', 'db_exists', - 'dblarr', 'dcindgen', 'dcomplex', 'dcomplexarr', 'define_key', - 'define_msgblk', 'define_msgblk_from_file', 'defroi', 'defsysv', - 'delvar', 'dendro_plot', 'dendrogram', 'deriv', 'derivsig', - 'determ', 'device', 'dfpmin', 'diag_matrix', 'dialog_dbconnect', - 'dialog_message', 'dialog_pickfile', 'dialog_printersetup', - 'dialog_printjob', 'dialog_read_image', - 'dialog_write_image', 'dictionary', 'digital_filter', 'dilate', 'dindgen', - 'dissolve', 'dist', 'distance_measure', 'dlm_load', 'dlm_register', - 'doc_library', 'double', 'draw_roi', 'edge_dog', 'efont', - 'eigenql', 'eigenvec', 'ellipse', 'elmhes', 'emboss', - 'empty', 'enable_sysrtn', 'eof', 'eos', 'erase', - 'erf', 'erfc', 'erfcx', 'erode', 'errorplot', - 'errplot', 'estimator_filter', 'execute', 'exit', 'exp', - 'expand', 'expand_path', 'expint', 'extrac', 'extract_slice', - 'f_cvf', 'f_pdf', 'factorial', 'fft', 'file_basename', - 'file_chmod', 'file_copy', 'file_delete', 'file_dirname', - 'file_expand_path', 'file_gunzip', 'file_gzip', 'file_info', - 'file_lines', 'file_link', 'file_mkdir', 'file_move', - 'file_poll_input', 'file_readlink', 'file_same', - 'file_search', 'file_tar', 'file_test', 'file_untar', 'file_unzip', - 'file_which', 'file_zip', 'filepath', 'findgen', 'finite', - 'fix', 'flick', 'float', 'floor', 'flow3', - 'fltarr', 'flush', 'format_axis_values', 'forward_function', 'free_lun', - 'fstat', 'fulstr', 'funct', 'function', 'fv_test', - 'fx_root', 'fz_roots', 'gamma', 'gamma_ct', 'gauss_cvf', - 'gauss_pdf', 'gauss_smooth', 'gauss2dfit', 'gaussfit', - 'gaussian_function', 'gaussint', 'get_drive_list', 'get_dxf_objects', - 'get_kbrd', 'get_login_info', - 'get_lun', 'get_screen_size', 'getenv', 'getwindows', 'greg2jul', - 'grib', 'grid_input', 'grid_tps', 'grid3', 'griddata', - 'gs_iter', 'h_eq_ct', 'h_eq_int', 'hanning', 'hash', - 'hdf', 'hdf5', 'heap_free', 'heap_gc', 'heap_nosave', - 'heap_refcount', 'heap_save', 'help', 'hilbert', 'hist_2d', - 'hist_equal', 'histogram', 'hls', 'hough', 'hqr', - 'hsv', 'i18n_multibytetoutf8', - 'i18n_multibytetowidechar', 'i18n_utf8tomultibyte', - 'i18n_widechartomultibyte', - 'ibeta', 'icontour', 'iconvertcoord', 'idelete', 'identity', - 'idl_base64', 'idl_container', 'idl_validname', - 'idlexbr_assistant', 'idlitsys_createtool', - 'idlunit', 'iellipse', 'igamma', 'igetcurrent', 'igetdata', - 'igetid', 'igetproperty', 'iimage', 'image', 'image_cont', - 'image_statistics', 'image_threshold', 'imaginary', 'imap', 'indgen', - 'int_2d', 'int_3d', 'int_tabulated', 'intarr', 'interpol', - 'interpolate', 'interval_volume', 'invert', 'ioctl', 'iopen', - 'ir_filter', 'iplot', 'ipolygon', 'ipolyline', 'iputdata', - 'iregister', 'ireset', 'iresolve', 'irotate', 'isa', - 'isave', 'iscale', 'isetcurrent', 'isetproperty', 'ishft', - 'isocontour', 'isosurface', 'isurface', 'itext', 'itranslate', - 'ivector', 'ivolume', 'izoom', 'journal', 'json_parse', - 'json_serialize', 'jul2greg', 'julday', 'keyword_set', 'krig2d', - 'kurtosis', 'kw_test', 'l64indgen', 'la_choldc', 'la_cholmprove', - 'la_cholsol', 'la_determ', 'la_eigenproblem', 'la_eigenql', 'la_eigenvec', - 'la_elmhes', 'la_gm_linear_model', 'la_hqr', 'la_invert', - 'la_least_square_equality', 'la_least_squares', 'la_linear_equation', - 'la_ludc', 'la_lumprove', 'la_lusol', - 'la_svd', 'la_tridc', 'la_trimprove', 'la_triql', 'la_trired', - 'la_trisol', 'label_date', 'label_region', 'ladfit', 'laguerre', - 'lambda', 'lambdap', 'lambertw', 'laplacian', 'least_squares_filter', - 'leefilt', 'legend', 'legendre', 'linbcg', 'lindgen', - 'linfit', 'linkimage', 'list', 'll_arc_distance', 'lmfit', - 'lmgr', 'lngamma', 'lnp_test', 'loadct', 'locale_get', - 'logical_and', 'logical_or', 'logical_true', 'lon64arr', 'lonarr', - 'long', 'long64', 'lsode', 'lu_complex', 'ludc', - 'lumprove', 'lusol', 'm_correlate', 'machar', 'make_array', - 'make_dll', 'make_rt', 'map', 'mapcontinents', 'mapgrid', - 'map_2points', 'map_continents', 'map_grid', 'map_image', 'map_patch', - 'map_proj_forward', 'map_proj_image', 'map_proj_info', - 'map_proj_init', 'map_proj_inverse', - 'map_set', 'matrix_multiply', 'matrix_power', 'max', 'md_test', - 'mean', 'meanabsdev', 'mean_filter', 'median', 'memory', - 'mesh_clip', 'mesh_decimate', 'mesh_issolid', - 'mesh_merge', 'mesh_numtriangles', - 'mesh_obj', 'mesh_smooth', 'mesh_surfacearea', - 'mesh_validate', 'mesh_volume', - 'message', 'min', 'min_curve_surf', 'mk_html_help', 'modifyct', - 'moment', 'morph_close', 'morph_distance', - 'morph_gradient', 'morph_hitormiss', - 'morph_open', 'morph_thin', 'morph_tophat', 'multi', 'n_elements', - 'n_params', 'n_tags', 'ncdf', 'newton', 'noise_hurl', - 'noise_pick', 'noise_scatter', 'noise_slur', 'norm', 'obj_class', - 'obj_destroy', 'obj_hasmethod', 'obj_isa', 'obj_new', 'obj_valid', - 'objarr', 'on_error', 'on_ioerror', 'online_help', 'openr', - 'openu', 'openw', 'oplot', 'oploterr', 'orderedhash', - 'p_correlate', 'parse_url', 'particle_trace', 'path_cache', 'path_sep', - 'pcomp', 'plot', 'plot3d', 'plot', 'plot_3dbox', - 'plot_field', 'ploterr', 'plots', 'polar_contour', 'polar_surface', - 'polyfill', 'polyshade', 'pnt_line', 'point_lun', 'polarplot', - 'poly', 'poly_2d', 'poly_area', 'poly_fit', 'polyfillv', - 'polygon', 'polyline', 'polywarp', 'popd', 'powell', - 'pref_commit', 'pref_get', 'pref_set', 'prewitt', 'primes', - 'print', 'printf', 'printd', 'pro', 'product', - 'profile', 'profiler', 'profiles', 'project_vol', 'ps_show_fonts', - 'psafm', 'pseudo', 'ptr_free', 'ptr_new', 'ptr_valid', - 'ptrarr', 'pushd', 'qgrid3', 'qhull', 'qromb', - 'qromo', 'qsimp', 'query_*', 'query_ascii', 'query_bmp', - 'query_csv', 'query_dicom', 'query_gif', 'query_image', 'query_jpeg', - 'query_jpeg2000', 'query_mrsid', 'query_pict', 'query_png', 'query_ppm', - 'query_srf', 'query_tiff', 'query_video', 'query_wav', 'r_correlate', - 'r_test', 'radon', 'randomn', 'randomu', 'ranks', - 'rdpix', 'read', 'readf', 'read_ascii', 'read_binary', - 'read_bmp', 'read_csv', 'read_dicom', 'read_gif', 'read_image', - 'read_interfile', 'read_jpeg', 'read_jpeg2000', 'read_mrsid', 'read_pict', - 'read_png', 'read_ppm', 'read_spr', 'read_srf', 'read_sylk', - 'read_tiff', 'read_video', 'read_wav', 'read_wave', 'read_x11_bitmap', - 'read_xwd', 'reads', 'readu', 'real_part', 'rebin', - 'recall_commands', 'recon3', 'reduce_colors', 'reform', 'region_grow', - 'register_cursor', 'regress', 'replicate', - 'replicate_inplace', 'resolve_all', - 'resolve_routine', 'restore', 'retall', 'return', 'reverse', - 'rk4', 'roberts', 'rot', 'rotate', 'round', - 'routine_filepath', 'routine_info', 'rs_test', 's_test', 'save', - 'savgol', 'scale3', 'scale3d', 'scatterplot', 'scatterplot3d', - 'scope_level', 'scope_traceback', 'scope_varfetch', - 'scope_varname', 'search2d', - 'search3d', 'sem_create', 'sem_delete', 'sem_lock', 'sem_release', - 'set_plot', 'set_shading', 'setenv', 'sfit', 'shade_surf', - 'shade_surf_irr', 'shade_volume', 'shift', 'shift_diff', 'shmdebug', - 'shmmap', 'shmunmap', 'shmvar', 'show3', 'showfont', - 'signum', 'simplex', 'sin', 'sindgen', 'sinh', - 'size', 'skewness', 'skip_lun', 'slicer3', 'slide_image', - 'smooth', 'sobel', 'socket', 'sort', 'spawn', - 'sph_4pnt', 'sph_scat', 'spher_harm', 'spl_init', 'spl_interp', - 'spline', 'spline_p', 'sprsab', 'sprsax', 'sprsin', - 'sprstp', 'sqrt', 'standardize', 'stddev', 'stop', - 'strarr', 'strcmp', 'strcompress', 'streamline', 'streamline', - 'stregex', 'stretch', 'string', 'strjoin', 'strlen', - 'strlowcase', 'strmatch', 'strmessage', 'strmid', 'strpos', - 'strput', 'strsplit', 'strtrim', 'struct_assign', 'struct_hide', - 'strupcase', 'surface', 'surface', 'surfr', 'svdc', - 'svdfit', 'svsol', 'swap_endian', 'swap_endian_inplace', 'symbol', - 'systime', 't_cvf', 't_pdf', 't3d', 'tag_names', - 'tan', 'tanh', 'tek_color', 'temporary', 'terminal_size', - 'tetra_clip', 'tetra_surface', 'tetra_volume', 'text', 'thin', - 'thread', 'threed', 'tic', 'time_test2', 'timegen', - 'timer', 'timestamp', 'timestamptovalues', 'tm_test', 'toc', - 'total', 'trace', 'transpose', 'tri_surf', 'triangulate', - 'trigrid', 'triql', 'trired', 'trisol', 'truncate_lun', - 'ts_coef', 'ts_diff', 'ts_fcast', 'ts_smooth', 'tv', - 'tvcrs', 'tvlct', 'tvrd', 'tvscl', 'typename', - 'uindgen', 'uint', 'uintarr', 'ul64indgen', 'ulindgen', - 'ulon64arr', 'ulonarr', 'ulong', 'ulong64', 'uniq', - 'unsharp_mask', 'usersym', 'value_locate', 'variance', 'vector', - 'vector_field', 'vel', 'velovect', 'vert_t3d', 'voigt', - 'volume', 'voronoi', 'voxel_proj', 'wait', 'warp_tri', - 'watershed', 'wdelete', 'wf_draw', 'where', 'widget_base', - 'widget_button', 'widget_combobox', 'widget_control', - 'widget_displaycontextmenu', 'widget_draw', - 'widget_droplist', 'widget_event', 'widget_info', - 'widget_label', 'widget_list', - 'widget_propertysheet', 'widget_slider', 'widget_tab', - 'widget_table', 'widget_text', - 'widget_tree', 'widget_tree_move', 'widget_window', - 'wiener_filter', 'window', - 'window', 'write_bmp', 'write_csv', 'write_gif', 'write_image', - 'write_jpeg', 'write_jpeg2000', 'write_nrif', 'write_pict', 'write_png', - 'write_ppm', 'write_spr', 'write_srf', 'write_sylk', 'write_tiff', - 'write_video', 'write_wav', 'write_wave', 'writeu', 'wset', - 'wshow', 'wtn', 'wv_applet', 'wv_cwt', 'wv_cw_wavelet', - 'wv_denoise', 'wv_dwt', 'wv_fn_coiflet', - 'wv_fn_daubechies', 'wv_fn_gaussian', - 'wv_fn_haar', 'wv_fn_morlet', 'wv_fn_paul', - 'wv_fn_symlet', 'wv_import_data', - 'wv_import_wavelet', 'wv_plot3d_wps', 'wv_plot_multires', - 'wv_pwt', 'wv_tool_denoise', - 'xbm_edit', 'xdisplayfile', 'xdxf', 'xfont', 'xinteranimate', - 'xloadct', 'xmanager', 'xmng_tmpl', 'xmtool', 'xobjview', - 'xobjview_rotate', 'xobjview_write_image', - 'xpalette', 'xpcolor', 'xplot3d', - 'xregistered', 'xroi', 'xsq_test', 'xsurface', 'xvaredit', - 'xvolume', 'xvolume_rotate', 'xvolume_write_image', - 'xyouts', 'zlib_compress', 'zlib_uncompress', 'zoom', 'zoom_24' - ]; - var builtins = wordRegexp(builtinArray); - - var keywordArray = [ - 'begin', 'end', 'endcase', 'endfor', - 'endwhile', 'endif', 'endrep', 'endforeach', - 'break', 'case', 'continue', 'for', - 'foreach', 'goto', 'if', 'then', 'else', - 'repeat', 'until', 'switch', 'while', - 'do', 'pro', 'function' - ]; - var keywords = wordRegexp(keywordArray); - - CodeMirror.registerHelper("hintWords", "idl", builtinArray.concat(keywordArray)); - - var identifiers = new RegExp('^[_a-z\xa1-\uffff][_a-z0-9\xa1-\uffff]*', 'i'); - - var singleOperators = /[+\-*&=<>\/@#~$]/; - var boolOperators = new RegExp('(and|or|eq|lt|le|gt|ge|ne|not)', 'i'); - - function tokenBase(stream) { - // whitespaces - if (stream.eatSpace()) return null; - - // Handle one line Comments - if (stream.match(';')) { - stream.skipToEnd(); - return 'comment'; - } - - // Handle Number Literals - if (stream.match(/^[0-9\.+-]/, false)) { - if (stream.match(/^[+-]?0x[0-9a-fA-F]+/)) - return 'number'; - if (stream.match(/^[+-]?\d*\.\d+([EeDd][+-]?\d+)?/)) - return 'number'; - if (stream.match(/^[+-]?\d+([EeDd][+-]?\d+)?/)) - return 'number'; - } - - // Handle Strings - if (stream.match(/^"([^"]|(""))*"/)) { return 'string'; } - if (stream.match(/^'([^']|(''))*'/)) { return 'string'; } - - // Handle words - if (stream.match(keywords)) { return 'keyword'; } - if (stream.match(builtins)) { return 'builtin'; } - if (stream.match(identifiers)) { return 'variable'; } - - if (stream.match(singleOperators) || stream.match(boolOperators)) { - return 'operator'; } - - // Handle non-detected items - stream.next(); - return null; - }; - - CodeMirror.defineMode('idl', function() { - return { - token: function(stream) { - return tokenBase(stream); - } - }; - }); - - CodeMirror.defineMIME('text/x-idl', 'idl'); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/idl/index.html b/backend/_pv_1_3_5/static/codemirror/mode/idl/index.html deleted file mode 100755 index 4c169e2d6..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/idl/index.html +++ /dev/null @@ -1,64 +0,0 @@ - - -CodeMirror: IDL mode - - - - - - - - - -
    -

    IDL mode

    - -
    - - -

    MIME types defined: text/x-idl.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/index.html b/backend/_pv_1_3_5/static/codemirror/mode/index.html deleted file mode 100755 index c0001a53e..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/index.html +++ /dev/null @@ -1,165 +0,0 @@ - - -CodeMirror: Language Modes - - - - - -
    - -

    Language modes

    - -

    This is a list of every mode in the distribution. Each mode lives -in a subdirectory of the mode/ directory, and typically -defines a single JavaScript file that implements the mode. Loading -such file will make the language available to CodeMirror, through -the mode -option.

    - -
    - -
    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/javascript/index.html b/backend/_pv_1_3_5/static/codemirror/mode/javascript/index.html deleted file mode 100755 index 592a133d8..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/javascript/index.html +++ /dev/null @@ -1,114 +0,0 @@ - - -CodeMirror: JavaScript mode - - - - - - - - - - - - -
    -

    JavaScript mode

    - - -
    - - - -

    - JavaScript mode supports several configuration options: -

      -
    • json which will set the mode to expect JSON - data rather than a JavaScript program.
    • -
    • jsonld which will set the mode to expect - JSON-LD linked data rather - than a JavaScript program (demo).
    • -
    • typescript which will activate additional - syntax highlighting and some other things for TypeScript code - (demo).
    • -
    • statementIndent which (given a number) will - determine the amount of indentation to use for statements - continued on a new line.
    • -
    • wordCharacters, a regexp that indicates which - characters should be considered part of an identifier. - Defaults to /[\w$]/, which does not handle - non-ASCII identifiers. Can be set to something more elaborate - to improve Unicode support.
    • -
    -

    - -

    MIME types defined: text/javascript, application/json, application/ld+json, text/typescript, application/typescript.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/javascript/javascript.js b/backend/_pv_1_3_5/static/codemirror/mode/javascript/javascript.js deleted file mode 100755 index 17890dcc1..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/javascript/javascript.js +++ /dev/null @@ -1,797 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -function expressionAllowed(stream, state, backUp) { - return /^(?:operator|sof|keyword c|case|new|export|default|[\[{}\(,;:]|=>)$/.test(state.lastType) || - (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0)))) -} - -CodeMirror.defineMode("javascript", function(config, parserConfig) { - var indentUnit = config.indentUnit; - var statementIndent = parserConfig.statementIndent; - var jsonldMode = parserConfig.jsonld; - var jsonMode = parserConfig.json || jsonldMode; - var isTS = parserConfig.typescript; - var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/; - - // Tokenizer - - var keywords = function(){ - function kw(type) {return {type: type, style: "keyword"};} - var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); - var operator = kw("operator"), atom = {type: "atom", style: "atom"}; - - var jsKeywords = { - "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, - "return": C, "break": C, "continue": C, "new": kw("new"), "delete": C, "throw": C, "debugger": C, - "var": kw("var"), "const": kw("var"), "let": kw("var"), - "function": kw("function"), "catch": kw("catch"), - "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), - "in": operator, "typeof": operator, "instanceof": operator, - "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, - "this": kw("this"), "class": kw("class"), "super": kw("atom"), - "yield": C, "export": kw("export"), "import": kw("import"), "extends": C, - "await": C, "async": kw("async") - }; - - // Extend the 'normal' keywords with the TypeScript language extensions - if (isTS) { - var type = {type: "variable", style: "variable-3"}; - var tsKeywords = { - // object-like things - "interface": kw("class"), - "implements": C, - "namespace": C, - "module": kw("module"), - "enum": kw("module"), - "type": kw("type"), - - // scope modifiers - "public": kw("modifier"), - "private": kw("modifier"), - "protected": kw("modifier"), - "abstract": kw("modifier"), - - // operators - "as": operator, - - // types - "string": type, "number": type, "boolean": type, "any": type - }; - - for (var attr in tsKeywords) { - jsKeywords[attr] = tsKeywords[attr]; - } - } - - return jsKeywords; - }(); - - var isOperatorChar = /[+\-*&%=<>!?|~^]/; - var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/; - - function readRegexp(stream) { - var escaped = false, next, inSet = false; - while ((next = stream.next()) != null) { - if (!escaped) { - if (next == "/" && !inSet) return; - if (next == "[") inSet = true; - else if (inSet && next == "]") inSet = false; - } - escaped = !escaped && next == "\\"; - } - } - - // Used as scratch variables to communicate multiple values without - // consing up tons of objects. - var type, content; - function ret(tp, style, cont) { - type = tp; content = cont; - return style; - } - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"' || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) { - return ret("number", "number"); - } else if (ch == "." && stream.match("..")) { - return ret("spread", "meta"); - } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - return ret(ch); - } else if (ch == "=" && stream.eat(">")) { - return ret("=>", "operator"); - } else if (ch == "0" && stream.eat(/x/i)) { - stream.eatWhile(/[\da-f]/i); - return ret("number", "number"); - } else if (ch == "0" && stream.eat(/o/i)) { - stream.eatWhile(/[0-7]/i); - return ret("number", "number"); - } else if (ch == "0" && stream.eat(/b/i)) { - stream.eatWhile(/[01]/i); - return ret("number", "number"); - } else if (/\d/.test(ch)) { - stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/); - return ret("number", "number"); - } else if (ch == "/") { - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } else if (stream.eat("/")) { - stream.skipToEnd(); - return ret("comment", "comment"); - } else if (expressionAllowed(stream, state, 1)) { - readRegexp(stream); - stream.match(/^\b(([gimyu])(?![gimyu]*\2))+\b/); - return ret("regexp", "string-2"); - } else { - stream.eatWhile(isOperatorChar); - return ret("operator", "operator", stream.current()); - } - } else if (ch == "`") { - state.tokenize = tokenQuasi; - return tokenQuasi(stream, state); - } else if (ch == "#") { - stream.skipToEnd(); - return ret("error", "error"); - } else if (isOperatorChar.test(ch)) { - if (ch != ">" || !state.lexical || state.lexical.type != ">") - stream.eatWhile(isOperatorChar); - return ret("operator", "operator", stream.current()); - } else if (wordRE.test(ch)) { - stream.eatWhile(wordRE); - var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word]; - return (known && state.lastType != ".") ? ret(known.type, known.style, word) : - ret("variable", "variable", word); - } - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next; - if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){ - state.tokenize = tokenBase; - return ret("jsonld-keyword", "meta"); - } - while ((next = stream.next()) != null) { - if (next == quote && !escaped) break; - escaped = !escaped && next == "\\"; - } - if (!escaped) state.tokenize = tokenBase; - return ret("string", "string"); - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return ret("comment", "comment"); - } - - function tokenQuasi(stream, state) { - var escaped = false, next; - while ((next = stream.next()) != null) { - if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) { - state.tokenize = tokenBase; - break; - } - escaped = !escaped && next == "\\"; - } - return ret("quasi", "string-2", stream.current()); - } - - var brackets = "([{}])"; - // This is a crude lookahead trick to try and notice that we're - // parsing the argument patterns for a fat-arrow function before we - // actually hit the arrow token. It only works if the arrow is on - // the same line as the arguments and there's no strange noise - // (comments) in between. Fallback is to only notice when we hit the - // arrow, and not declare the arguments as locals for the arrow - // body. - function findFatArrow(stream, state) { - if (state.fatArrowAt) state.fatArrowAt = null; - var arrow = stream.string.indexOf("=>", stream.start); - if (arrow < 0) return; - - if (isTS) { // Try to skip TypeScript return type declarations after the arguments - var m = /:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(stream.string.slice(stream.start, arrow)) - if (m) arrow = m.index - } - - var depth = 0, sawSomething = false; - for (var pos = arrow - 1; pos >= 0; --pos) { - var ch = stream.string.charAt(pos); - var bracket = brackets.indexOf(ch); - if (bracket >= 0 && bracket < 3) { - if (!depth) { ++pos; break; } - if (--depth == 0) { if (ch == "(") sawSomething = true; break; } - } else if (bracket >= 3 && bracket < 6) { - ++depth; - } else if (wordRE.test(ch)) { - sawSomething = true; - } else if (/["'\/]/.test(ch)) { - return; - } else if (sawSomething && !depth) { - ++pos; - break; - } - } - if (sawSomething && !depth) state.fatArrowAt = pos; - } - - // Parser - - var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true}; - - function JSLexical(indented, column, type, align, prev, info) { - this.indented = indented; - this.column = column; - this.type = type; - this.prev = prev; - this.info = info; - if (align != null) this.align = align; - } - - function inScope(state, varname) { - for (var v = state.localVars; v; v = v.next) - if (v.name == varname) return true; - for (var cx = state.context; cx; cx = cx.prev) { - for (var v = cx.vars; v; v = v.next) - if (v.name == varname) return true; - } - } - - function parseJS(state, style, type, content, stream) { - var cc = state.cc; - // Communicate our context to the combinators. - // (Less wasteful than consing up a hundred closures on every call.) - cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style; - - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = true; - - while(true) { - var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement; - if (combinator(type, content)) { - while(cc.length && cc[cc.length - 1].lex) - cc.pop()(); - if (cx.marked) return cx.marked; - if (type == "variable" && inScope(state, content)) return "variable-2"; - return style; - } - } - } - - // Combinator utils - - var cx = {state: null, column: null, marked: null, cc: null}; - function pass() { - for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]); - } - function cont() { - pass.apply(null, arguments); - return true; - } - function register(varname) { - function inList(list) { - for (var v = list; v; v = v.next) - if (v.name == varname) return true; - return false; - } - var state = cx.state; - cx.marked = "def"; - if (state.context) { - if (inList(state.localVars)) return; - state.localVars = {name: varname, next: state.localVars}; - } else { - if (inList(state.globalVars)) return; - if (parserConfig.globalVars) - state.globalVars = {name: varname, next: state.globalVars}; - } - } - - // Combinators - - var defaultVars = {name: "this", next: {name: "arguments"}}; - function pushcontext() { - cx.state.context = {prev: cx.state.context, vars: cx.state.localVars}; - cx.state.localVars = defaultVars; - } - function popcontext() { - cx.state.localVars = cx.state.context.vars; - cx.state.context = cx.state.context.prev; - } - function pushlex(type, info) { - var result = function() { - var state = cx.state, indent = state.indented; - if (state.lexical.type == "stat") indent = state.lexical.indented; - else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev) - indent = outer.indented; - state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info); - }; - result.lex = true; - return result; - } - function poplex() { - var state = cx.state; - if (state.lexical.prev) { - if (state.lexical.type == ")") - state.indented = state.lexical.indented; - state.lexical = state.lexical.prev; - } - } - poplex.lex = true; - - function expect(wanted) { - function exp(type) { - if (type == wanted) return cont(); - else if (wanted == ";") return pass(); - else return cont(exp); - }; - return exp; - } - - function statement(type, value) { - if (type == "var") return cont(pushlex("vardef", value.length), vardef, expect(";"), poplex); - if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex); - if (type == "keyword b") return cont(pushlex("form"), statement, poplex); - if (type == "{") return cont(pushlex("}"), block, poplex); - if (type == ";") return cont(); - if (type == "if") { - if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex) - cx.state.cc.pop()(); - return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse); - } - if (type == "function") return cont(functiondef); - if (type == "for") return cont(pushlex("form"), forspec, statement, poplex); - if (type == "variable") return cont(pushlex("stat"), maybelabel); - if (type == "switch") return cont(pushlex("form"), parenExpr, pushlex("}", "switch"), expect("{"), - block, poplex, poplex); - if (type == "case") return cont(expression, expect(":")); - if (type == "default") return cont(expect(":")); - if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"), - statement, poplex, popcontext); - if (type == "class") return cont(pushlex("form"), className, poplex); - if (type == "export") return cont(pushlex("stat"), afterExport, poplex); - if (type == "import") return cont(pushlex("stat"), afterImport, poplex); - if (type == "module") return cont(pushlex("form"), pattern, pushlex("}"), expect("{"), block, poplex, poplex) - if (type == "type") return cont(typeexpr, expect("operator"), typeexpr, expect(";")); - if (type == "async") return cont(statement) - return pass(pushlex("stat"), expression, expect(";"), poplex); - } - function expression(type) { - return expressionInner(type, false); - } - function expressionNoComma(type) { - return expressionInner(type, true); - } - function parenExpr(type) { - if (type != "(") return pass() - return cont(pushlex(")"), expression, expect(")"), poplex) - } - function expressionInner(type, noComma) { - if (cx.state.fatArrowAt == cx.stream.start) { - var body = noComma ? arrowBodyNoComma : arrowBody; - if (type == "(") return cont(pushcontext, pushlex(")"), commasep(pattern, ")"), poplex, expect("=>"), body, popcontext); - else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext); - } - - var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma; - if (atomicTypes.hasOwnProperty(type)) return cont(maybeop); - if (type == "function") return cont(functiondef, maybeop); - if (type == "class") return cont(pushlex("form"), classExpression, poplex); - if (type == "keyword c" || type == "async") return cont(noComma ? maybeexpressionNoComma : maybeexpression); - if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop); - if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression); - if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop); - if (type == "{") return contCommasep(objprop, "}", null, maybeop); - if (type == "quasi") return pass(quasi, maybeop); - if (type == "new") return cont(maybeTarget(noComma)); - return cont(); - } - function maybeexpression(type) { - if (type.match(/[;\}\)\],]/)) return pass(); - return pass(expression); - } - function maybeexpressionNoComma(type) { - if (type.match(/[;\}\)\],]/)) return pass(); - return pass(expressionNoComma); - } - - function maybeoperatorComma(type, value) { - if (type == ",") return cont(expression); - return maybeoperatorNoComma(type, value, false); - } - function maybeoperatorNoComma(type, value, noComma) { - var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma; - var expr = noComma == false ? expression : expressionNoComma; - if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext); - if (type == "operator") { - if (/\+\+|--/.test(value)) return cont(me); - if (value == "?") return cont(expression, expect(":"), expr); - return cont(expr); - } - if (type == "quasi") { return pass(quasi, me); } - if (type == ";") return; - if (type == "(") return contCommasep(expressionNoComma, ")", "call", me); - if (type == ".") return cont(property, me); - if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); - } - function quasi(type, value) { - if (type != "quasi") return pass(); - if (value.slice(value.length - 2) != "${") return cont(quasi); - return cont(expression, continueQuasi); - } - function continueQuasi(type) { - if (type == "}") { - cx.marked = "string-2"; - cx.state.tokenize = tokenQuasi; - return cont(quasi); - } - } - function arrowBody(type) { - findFatArrow(cx.stream, cx.state); - return pass(type == "{" ? statement : expression); - } - function arrowBodyNoComma(type) { - findFatArrow(cx.stream, cx.state); - return pass(type == "{" ? statement : expressionNoComma); - } - function maybeTarget(noComma) { - return function(type) { - if (type == ".") return cont(noComma ? targetNoComma : target); - else return pass(noComma ? expressionNoComma : expression); - }; - } - function target(_, value) { - if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorComma); } - } - function targetNoComma(_, value) { - if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorNoComma); } - } - function maybelabel(type) { - if (type == ":") return cont(poplex, statement); - return pass(maybeoperatorComma, expect(";"), poplex); - } - function property(type) { - if (type == "variable") {cx.marked = "property"; return cont();} - } - function objprop(type, value) { - if (type == "async") { - cx.marked = "property"; - return cont(objprop); - } else if (type == "variable" || cx.style == "keyword") { - cx.marked = "property"; - if (value == "get" || value == "set") return cont(getterSetter); - return cont(afterprop); - } else if (type == "number" || type == "string") { - cx.marked = jsonldMode ? "property" : (cx.style + " property"); - return cont(afterprop); - } else if (type == "jsonld-keyword") { - return cont(afterprop); - } else if (type == "modifier") { - return cont(objprop) - } else if (type == "[") { - return cont(expression, expect("]"), afterprop); - } else if (type == "spread") { - return cont(expression); - } else if (type == ":") { - return pass(afterprop) - } - } - function getterSetter(type) { - if (type != "variable") return pass(afterprop); - cx.marked = "property"; - return cont(functiondef); - } - function afterprop(type) { - if (type == ":") return cont(expressionNoComma); - if (type == "(") return pass(functiondef); - } - function commasep(what, end, sep) { - function proceed(type, value) { - if (sep ? sep.indexOf(type) > -1 : type == ",") { - var lex = cx.state.lexical; - if (lex.info == "call") lex.pos = (lex.pos || 0) + 1; - return cont(function(type, value) { - if (type == end || value == end) return pass() - return pass(what) - }, proceed); - } - if (type == end || value == end) return cont(); - return cont(expect(end)); - } - return function(type, value) { - if (type == end || value == end) return cont(); - return pass(what, proceed); - }; - } - function contCommasep(what, end, info) { - for (var i = 3; i < arguments.length; i++) - cx.cc.push(arguments[i]); - return cont(pushlex(end, info), commasep(what, end), poplex); - } - function block(type) { - if (type == "}") return cont(); - return pass(statement, block); - } - function maybetype(type, value) { - if (isTS) { - if (type == ":") return cont(typeexpr); - if (value == "?") return cont(maybetype); - } - } - function typeexpr(type) { - if (type == "variable") {cx.marked = "variable-3"; return cont(afterType);} - if (type == "string" || type == "number" || type == "atom") return cont(afterType); - if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex) - if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType) - } - function maybeReturnType(type) { - if (type == "=>") return cont(typeexpr) - } - function typeprop(type, value) { - if (type == "variable" || cx.style == "keyword") { - cx.marked = "property" - return cont(typeprop) - } else if (value == "?") { - return cont(typeprop) - } else if (type == ":") { - return cont(typeexpr) - } - } - function typearg(type) { - if (type == "variable") return cont(typearg) - else if (type == ":") return cont(typeexpr) - } - function afterType(type, value) { - if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType) - if (value == "|" || type == ".") return cont(typeexpr) - if (type == "[") return cont(expect("]"), afterType) - } - function vardef() { - return pass(pattern, maybetype, maybeAssign, vardefCont); - } - function pattern(type, value) { - if (type == "modifier") return cont(pattern) - if (type == "variable") { register(value); return cont(); } - if (type == "spread") return cont(pattern); - if (type == "[") return contCommasep(pattern, "]"); - if (type == "{") return contCommasep(proppattern, "}"); - } - function proppattern(type, value) { - if (type == "variable" && !cx.stream.match(/^\s*:/, false)) { - register(value); - return cont(maybeAssign); - } - if (type == "variable") cx.marked = "property"; - if (type == "spread") return cont(pattern); - if (type == "}") return pass(); - return cont(expect(":"), pattern, maybeAssign); - } - function maybeAssign(_type, value) { - if (value == "=") return cont(expressionNoComma); - } - function vardefCont(type) { - if (type == ",") return cont(vardef); - } - function maybeelse(type, value) { - if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex); - } - function forspec(type) { - if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex); - } - function forspec1(type) { - if (type == "var") return cont(vardef, expect(";"), forspec2); - if (type == ";") return cont(forspec2); - if (type == "variable") return cont(formaybeinof); - return pass(expression, expect(";"), forspec2); - } - function formaybeinof(_type, value) { - if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } - return cont(maybeoperatorComma, forspec2); - } - function forspec2(type, value) { - if (type == ";") return cont(forspec3); - if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } - return pass(expression, expect(";"), forspec3); - } - function forspec3(type) { - if (type != ")") cont(expression); - } - function functiondef(type, value) { - if (value == "*") {cx.marked = "keyword"; return cont(functiondef);} - if (type == "variable") {register(value); return cont(functiondef);} - if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, maybetype, statement, popcontext); - } - function funarg(type) { - if (type == "spread") return cont(funarg); - return pass(pattern, maybetype, maybeAssign); - } - function classExpression(type, value) { - // Class expressions may have an optional name. - if (type == "variable") return className(type, value); - return classNameAfter(type, value); - } - function className(type, value) { - if (type == "variable") {register(value); return cont(classNameAfter);} - } - function classNameAfter(type, value) { - if (value == "extends" || value == "implements") return cont(isTS ? typeexpr : expression, classNameAfter); - if (type == "{") return cont(pushlex("}"), classBody, poplex); - } - function classBody(type, value) { - if (type == "variable" || cx.style == "keyword") { - if ((value == "static" || value == "get" || value == "set" || - (isTS && (value == "public" || value == "private" || value == "protected" || value == "readonly" || value == "abstract"))) && - cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false)) { - cx.marked = "keyword"; - return cont(classBody); - } - cx.marked = "property"; - return cont(isTS ? classfield : functiondef, classBody); - } - if (value == "*") { - cx.marked = "keyword"; - return cont(classBody); - } - if (type == ";") return cont(classBody); - if (type == "}") return cont(); - } - function classfield(type, value) { - if (value == "?") return cont(classfield) - if (type == ":") return cont(typeexpr, maybeAssign) - return pass(functiondef) - } - function afterExport(type, value) { - if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); } - if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); } - if (type == "{") return cont(commasep(exportField, "}"), maybeFrom, expect(";")); - return pass(statement); - } - function exportField(type, value) { - if (value == "as") { cx.marked = "keyword"; return cont(expect("variable")); } - if (type == "variable") return pass(expressionNoComma, exportField); - } - function afterImport(type) { - if (type == "string") return cont(); - return pass(importSpec, maybeMoreImports, maybeFrom); - } - function importSpec(type, value) { - if (type == "{") return contCommasep(importSpec, "}"); - if (type == "variable") register(value); - if (value == "*") cx.marked = "keyword"; - return cont(maybeAs); - } - function maybeMoreImports(type) { - if (type == ",") return cont(importSpec, maybeMoreImports) - } - function maybeAs(_type, value) { - if (value == "as") { cx.marked = "keyword"; return cont(importSpec); } - } - function maybeFrom(_type, value) { - if (value == "from") { cx.marked = "keyword"; return cont(expression); } - } - function arrayLiteral(type) { - if (type == "]") return cont(); - return pass(commasep(expressionNoComma, "]")); - } - - function isContinuedStatement(state, textAfter) { - return state.lastType == "operator" || state.lastType == "," || - isOperatorChar.test(textAfter.charAt(0)) || - /[,.]/.test(textAfter.charAt(0)); - } - - // Interface - - return { - startState: function(basecolumn) { - var state = { - tokenize: tokenBase, - lastType: "sof", - cc: [], - lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), - localVars: parserConfig.localVars, - context: parserConfig.localVars && {vars: parserConfig.localVars}, - indented: basecolumn || 0 - }; - if (parserConfig.globalVars && typeof parserConfig.globalVars == "object") - state.globalVars = parserConfig.globalVars; - return state; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = false; - state.indented = stream.indentation(); - findFatArrow(stream, state); - } - if (state.tokenize != tokenComment && stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - if (type == "comment") return style; - state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type; - return parseJS(state, style, type, content, stream); - }, - - indent: function(state, textAfter) { - if (state.tokenize == tokenComment) return CodeMirror.Pass; - if (state.tokenize != tokenBase) return 0; - var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top - // Kludge to prevent 'maybelse' from blocking lexical scope pops - if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) { - var c = state.cc[i]; - if (c == poplex) lexical = lexical.prev; - else if (c != maybeelse) break; - } - while ((lexical.type == "stat" || lexical.type == "form") && - (firstChar == "}" || ((top = state.cc[state.cc.length - 1]) && - (top == maybeoperatorComma || top == maybeoperatorNoComma) && - !/^[,\.=+\-*:?[\(]/.test(textAfter)))) - lexical = lexical.prev; - if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat") - lexical = lexical.prev; - var type = lexical.type, closing = firstChar == type; - - if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info + 1 : 0); - else if (type == "form" && firstChar == "{") return lexical.indented; - else if (type == "form") return lexical.indented + indentUnit; - else if (type == "stat") - return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0); - else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false) - return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit); - else if (lexical.align) return lexical.column + (closing ? 0 : 1); - else return lexical.indented + (closing ? 0 : indentUnit); - }, - - electricInput: /^\s*(?:case .*?:|default:|\{|\})$/, - blockCommentStart: jsonMode ? null : "/*", - blockCommentEnd: jsonMode ? null : "*/", - lineComment: jsonMode ? null : "//", - fold: "brace", - closeBrackets: "()[]{}''\"\"``", - - helperType: jsonMode ? "json" : "javascript", - jsonldMode: jsonldMode, - jsonMode: jsonMode, - - expressionAllowed: expressionAllowed, - skipExpression: function(state) { - var top = state.cc[state.cc.length - 1] - if (top == expression || top == expressionNoComma) state.cc.pop() - } - }; -}); - -CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/); - -CodeMirror.defineMIME("text/javascript", "javascript"); -CodeMirror.defineMIME("text/ecmascript", "javascript"); -CodeMirror.defineMIME("application/javascript", "javascript"); -CodeMirror.defineMIME("application/x-javascript", "javascript"); -CodeMirror.defineMIME("application/ecmascript", "javascript"); -CodeMirror.defineMIME("application/json", {name: "javascript", json: true}); -CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true}); -CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true}); -CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true }); -CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true }); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/javascript/json-ld.html b/backend/_pv_1_3_5/static/codemirror/mode/javascript/json-ld.html deleted file mode 100755 index 3a37f0bce..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/javascript/json-ld.html +++ /dev/null @@ -1,72 +0,0 @@ - - -CodeMirror: JSON-LD mode - - - - - - - - - - - - -
    -

    JSON-LD mode

    - - -
    - - - -

    This is a specialization of the JavaScript mode.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/javascript/test.js b/backend/_pv_1_3_5/static/codemirror/mode/javascript/test.js deleted file mode 100755 index c02eb06c3..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/javascript/test.js +++ /dev/null @@ -1,307 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "javascript"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT("locals", - "[keyword function] [def foo]([def a], [def b]) { [keyword var] [def c] [operator =] [number 10]; [keyword return] [variable-2 a] [operator +] [variable-2 c] [operator +] [variable d]; }"); - - MT("comma-and-binop", - "[keyword function](){ [keyword var] [def x] [operator =] [number 1] [operator +] [number 2], [def y]; }"); - - MT("destructuring", - "([keyword function]([def a], [[[def b], [def c] ]]) {", - " [keyword let] {[def d], [property foo]: [def c][operator =][number 10], [def x]} [operator =] [variable foo]([variable-2 a]);", - " [[[variable-2 c], [variable y] ]] [operator =] [variable-2 c];", - "})();"); - - MT("destructure_trailing_comma", - "[keyword let] {[def a], [def b],} [operator =] [variable foo];", - "[keyword let] [def c];"); // Parser still in good state? - - MT("class_body", - "[keyword class] [def Foo] {", - " [property constructor]() {}", - " [property sayName]() {", - " [keyword return] [string-2 `foo${][variable foo][string-2 }oo`];", - " }", - "}"); - - MT("class", - "[keyword class] [def Point] [keyword extends] [variable SuperThing] {", - " [keyword get] [property prop]() { [keyword return] [number 24]; }", - " [property constructor]([def x], [def y]) {", - " [keyword super]([string 'something']);", - " [keyword this].[property x] [operator =] [variable-2 x];", - " }", - "}"); - - MT("anonymous_class_expression", - "[keyword const] [def Adder] [operator =] [keyword class] [keyword extends] [variable Arithmetic] {", - " [property add]([def a], [def b]) {}", - "};"); - - MT("named_class_expression", - "[keyword const] [def Subber] [operator =] [keyword class] [def Subtract] {", - " [property sub]([def a], [def b]) {}", - "};"); - - MT("import", - "[keyword function] [def foo]() {", - " [keyword import] [def $] [keyword from] [string 'jquery'];", - " [keyword import] { [def encrypt], [def decrypt] } [keyword from] [string 'crypto'];", - "}"); - - MT("import_trailing_comma", - "[keyword import] {[def foo], [def bar],} [keyword from] [string 'baz']") - - MT("const", - "[keyword function] [def f]() {", - " [keyword const] [[ [def a], [def b] ]] [operator =] [[ [number 1], [number 2] ]];", - "}"); - - MT("for/of", - "[keyword for]([keyword let] [def of] [keyword of] [variable something]) {}"); - - MT("generator", - "[keyword function*] [def repeat]([def n]) {", - " [keyword for]([keyword var] [def i] [operator =] [number 0]; [variable-2 i] [operator <] [variable-2 n]; [operator ++][variable-2 i])", - " [keyword yield] [variable-2 i];", - "}"); - - MT("quotedStringAddition", - "[keyword let] [def f] [operator =] [variable a] [operator +] [string 'fatarrow'] [operator +] [variable c];"); - - MT("quotedFatArrow", - "[keyword let] [def f] [operator =] [variable a] [operator +] [string '=>'] [operator +] [variable c];"); - - MT("fatArrow", - "[variable array].[property filter]([def a] [operator =>] [variable-2 a] [operator +] [number 1]);", - "[variable a];", // No longer in scope - "[keyword let] [def f] [operator =] ([[ [def a], [def b] ]], [def c]) [operator =>] [variable-2 a] [operator +] [variable-2 c];", - "[variable c];"); - - MT("spread", - "[keyword function] [def f]([def a], [meta ...][def b]) {", - " [variable something]([variable-2 a], [meta ...][variable-2 b]);", - "}"); - - MT("quasi", - "[variable re][string-2 `fofdlakj${][variable x] [operator +] ([variable re][string-2 `foo`]) [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]"); - - MT("quasi_no_function", - "[variable x] [operator =] [string-2 `fofdlakj${][variable x] [operator +] [string-2 `foo`] [operator +] [number 1][string-2 }fdsa`] [operator +] [number 2]"); - - MT("indent_statement", - "[keyword var] [def x] [operator =] [number 10]", - "[variable x] [operator +=] [variable y] [operator +]", - " [atom Infinity]", - "[keyword debugger];"); - - MT("indent_if", - "[keyword if] ([number 1])", - " [keyword break];", - "[keyword else] [keyword if] ([number 2])", - " [keyword continue];", - "[keyword else]", - " [number 10];", - "[keyword if] ([number 1]) {", - " [keyword break];", - "} [keyword else] [keyword if] ([number 2]) {", - " [keyword continue];", - "} [keyword else] {", - " [number 10];", - "}"); - - MT("indent_for", - "[keyword for] ([keyword var] [def i] [operator =] [number 0];", - " [variable i] [operator <] [number 100];", - " [variable i][operator ++])", - " [variable doSomething]([variable i]);", - "[keyword debugger];"); - - MT("indent_c_style", - "[keyword function] [def foo]()", - "{", - " [keyword debugger];", - "}"); - - MT("indent_else", - "[keyword for] (;;)", - " [keyword if] ([variable foo])", - " [keyword if] ([variable bar])", - " [number 1];", - " [keyword else]", - " [number 2];", - " [keyword else]", - " [number 3];"); - - MT("indent_funarg", - "[variable foo]([number 10000],", - " [keyword function]([def a]) {", - " [keyword debugger];", - "};"); - - MT("indent_below_if", - "[keyword for] (;;)", - " [keyword if] ([variable foo])", - " [number 1];", - "[number 2];"); - - MT("indent_semicolonless_if", - "[keyword function] [def foo]() {", - " [keyword if] ([variable x])", - " [variable foo]()", - "}") - - MT("indent_semicolonless_if_with_statement", - "[keyword function] [def foo]() {", - " [keyword if] ([variable x])", - " [variable foo]()", - " [variable bar]()", - "}") - - MT("multilinestring", - "[keyword var] [def x] [operator =] [string 'foo\\]", - "[string bar'];"); - - MT("scary_regexp", - "[string-2 /foo[[/]]bar/];"); - - MT("indent_strange_array", - "[keyword var] [def x] [operator =] [[", - " [number 1],,", - " [number 2],", - "]];", - "[number 10];"); - - MT("param_default", - "[keyword function] [def foo]([def x] [operator =] [string-2 `foo${][number 10][string-2 }bar`]) {", - " [keyword return] [variable-2 x];", - "}"); - - MT("new_target", - "[keyword function] [def F]([def target]) {", - " [keyword if] ([variable-2 target] [operator &&] [keyword new].[keyword target].[property name]) {", - " [keyword return] [keyword new]", - " .[keyword target];", - " }", - "}"); - - MT("async", - "[keyword async] [keyword function] [def foo]([def args]) { [keyword return] [atom true]; }"); - - MT("async_assignment", - "[keyword const] [def foo] [operator =] [keyword async] [keyword function] ([def args]) { [keyword return] [atom true]; };"); - - MT("async_object", - "[keyword let] [def obj] [operator =] { [property async]: [atom false] };"); - - // async be highlighet as keyword and foo as def, but it requires potentially expensive look-ahead. See #4173 - MT("async_object_function", - "[keyword let] [def obj] [operator =] { [property async] [property foo]([def args]) { [keyword return] [atom true]; } };"); - - MT("async_object_properties", - "[keyword let] [def obj] [operator =] {", - " [property prop1]: [keyword async] [keyword function] ([def args]) { [keyword return] [atom true]; },", - " [property prop2]: [keyword async] [keyword function] ([def args]) { [keyword return] [atom true]; },", - " [property prop3]: [keyword async] [keyword function] [def prop3]([def args]) { [keyword return] [atom true]; },", - "};"); - - MT("async_arrow", - "[keyword const] [def foo] [operator =] [keyword async] ([def args]) [operator =>] { [keyword return] [atom true]; };"); - - MT("async_jquery", - "[variable $].[property ajax]({", - " [property url]: [variable url],", - " [property async]: [atom true],", - " [property method]: [string 'GET']", - "});"); - - var ts_mode = CodeMirror.getMode({indentUnit: 2}, "application/typescript") - function TS(name) { - test.mode(name, ts_mode, Array.prototype.slice.call(arguments, 1)) - } - - TS("extend_type", - "[keyword class] [def Foo] [keyword extends] [variable-3 Some][operator <][variable-3 Type][operator >] {}") - - TS("arrow_type", - "[keyword let] [def x]: ([variable arg]: [variable-3 Type]) [operator =>] [variable-3 ReturnType]") - - TS("typescript_class", - "[keyword class] [def Foo] {", - " [keyword public] [keyword static] [property main]() {}", - " [keyword private] [property _foo]: [variable-3 string];", - "}") - - TS("typescript_literal_types", - "[keyword import] [keyword *] [keyword as] [def Sequelize] [keyword from] [string 'sequelize'];", - "[keyword interface] [def MyAttributes] {", - " [property truthy]: [string 'true'] [operator |] [number 1] [operator |] [atom true];", - " [property falsy]: [string 'false'] [operator |] [number 0] [operator |] [atom false];", - "}", - "[keyword interface] [def MyInstance] [keyword extends] [variable-3 Sequelize].[variable-3 Instance] [operator <] [variable-3 MyAttributes] [operator >] {", - " [property rawAttributes]: [variable-3 MyAttributes];", - " [property truthy]: [string 'true'] [operator |] [number 1] [operator |] [atom true];", - " [property falsy]: [string 'false'] [operator |] [number 0] [operator |] [atom false];", - "}") - - TS("typescript_extend_operators", - "[keyword export] [keyword interface] [def UserModel] [keyword extends]", - " [variable-3 Sequelize].[variable-3 Model] [operator <] [variable-3 UserInstance], [variable-3 UserAttributes] [operator >] {", - " [property findById]: (", - " [variable userId]: [variable-3 number]", - " ) [operator =>] [variable-3 Promise] [operator <] [variable-3 Array] [operator <] { [property id], [property name] } [operator >>];", - " [property updateById]: (", - " [variable userId]: [variable-3 number],", - " [variable isActive]: [variable-3 boolean]", - " ) [operator =>] [variable-3 Promise] [operator <] [variable-3 AccountHolderNotificationPreferenceInstance] [operator >];", - " }") - - TS("typescript_interface_with_const", - "[keyword const] [def hello]: {", - " [property prop1][operator ?]: [variable-3 string];", - " [property prop2][operator ?]: [variable-3 string];", - "} [operator =] {};") - - var jsonld_mode = CodeMirror.getMode( - {indentUnit: 2}, - {name: "javascript", jsonld: true} - ); - function LD(name) { - test.mode(name, jsonld_mode, Array.prototype.slice.call(arguments, 1)); - } - - LD("json_ld_keywords", - '{', - ' [meta "@context"]: {', - ' [meta "@base"]: [string "http://example.com"],', - ' [meta "@vocab"]: [string "http://xmlns.com/foaf/0.1/"],', - ' [property "likesFlavor"]: {', - ' [meta "@container"]: [meta "@list"]', - ' [meta "@reverse"]: [string "@beFavoriteOf"]', - ' },', - ' [property "nick"]: { [meta "@container"]: [meta "@set"] },', - ' [property "nick"]: { [meta "@container"]: [meta "@index"] }', - ' },', - ' [meta "@graph"]: [[ {', - ' [meta "@id"]: [string "http://dbpedia.org/resource/John_Lennon"],', - ' [property "name"]: [string "John Lennon"],', - ' [property "modified"]: {', - ' [meta "@value"]: [string "2010-05-29T14:17:39+02:00"],', - ' [meta "@type"]: [string "http://www.w3.org/2001/XMLSchema#dateTime"]', - ' }', - ' } ]]', - '}'); - - LD("json_ld_fake", - '{', - ' [property "@fake"]: [string "@fake"],', - ' [property "@contextual"]: [string "@identifier"],', - ' [property "user@domain.com"]: [string "@graphical"],', - ' [property "@ID"]: [string "@@ID"]', - '}'); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/javascript/typescript.html b/backend/_pv_1_3_5/static/codemirror/mode/javascript/typescript.html deleted file mode 100755 index 1f26d7fe1..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/javascript/typescript.html +++ /dev/null @@ -1,61 +0,0 @@ - - -CodeMirror: TypeScript mode - - - - - - - - - -
    -

    TypeScript mode

    - - -
    - - - -

    This is a specialization of the JavaScript mode.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/jinja2/index.html b/backend/_pv_1_3_5/static/codemirror/mode/jinja2/index.html deleted file mode 100755 index 5a70e9153..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/jinja2/index.html +++ /dev/null @@ -1,54 +0,0 @@ - - -CodeMirror: Jinja2 mode - - - - - - - - - -
    -

    Jinja2 mode

    -
    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/jinja2/jinja2.js b/backend/_pv_1_3_5/static/codemirror/mode/jinja2/jinja2.js deleted file mode 100755 index ed195581c..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/jinja2/jinja2.js +++ /dev/null @@ -1,142 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("jinja2", function() { - var keywords = ["and", "as", "block", "endblock", "by", "cycle", "debug", "else", "elif", - "extends", "filter", "endfilter", "firstof", "for", - "endfor", "if", "endif", "ifchanged", "endifchanged", - "ifequal", "endifequal", "ifnotequal", - "endifnotequal", "in", "include", "load", "not", "now", "or", - "parsed", "regroup", "reversed", "spaceless", - "endspaceless", "ssi", "templatetag", "openblock", - "closeblock", "openvariable", "closevariable", - "openbrace", "closebrace", "opencomment", - "closecomment", "widthratio", "url", "with", "endwith", - "get_current_language", "trans", "endtrans", "noop", "blocktrans", - "endblocktrans", "get_available_languages", - "get_current_language_bidi", "plural"], - operator = /^[+\-*&%=<>!?|~^]/, - sign = /^[:\[\(\{]/, - atom = ["true", "false"], - number = /^(\d[+\-\*\/])?\d+(\.\d+)?/; - - keywords = new RegExp("((" + keywords.join(")|(") + "))\\b"); - atom = new RegExp("((" + atom.join(")|(") + "))\\b"); - - function tokenBase (stream, state) { - var ch = stream.peek(); - - //Comment - if (state.incomment) { - if(!stream.skipTo("#}")) { - stream.skipToEnd(); - } else { - stream.eatWhile(/\#|}/); - state.incomment = false; - } - return "comment"; - //Tag - } else if (state.intag) { - //After operator - if(state.operator) { - state.operator = false; - if(stream.match(atom)) { - return "atom"; - } - if(stream.match(number)) { - return "number"; - } - } - //After sign - if(state.sign) { - state.sign = false; - if(stream.match(atom)) { - return "atom"; - } - if(stream.match(number)) { - return "number"; - } - } - - if(state.instring) { - if(ch == state.instring) { - state.instring = false; - } - stream.next(); - return "string"; - } else if(ch == "'" || ch == '"') { - state.instring = ch; - stream.next(); - return "string"; - } else if(stream.match(state.intag + "}") || stream.eat("-") && stream.match(state.intag + "}")) { - state.intag = false; - return "tag"; - } else if(stream.match(operator)) { - state.operator = true; - return "operator"; - } else if(stream.match(sign)) { - state.sign = true; - } else { - if(stream.eat(" ") || stream.sol()) { - if(stream.match(keywords)) { - return "keyword"; - } - if(stream.match(atom)) { - return "atom"; - } - if(stream.match(number)) { - return "number"; - } - if(stream.sol()) { - stream.next(); - } - } else { - stream.next(); - } - - } - return "variable"; - } else if (stream.eat("{")) { - if (ch = stream.eat("#")) { - state.incomment = true; - if(!stream.skipTo("#}")) { - stream.skipToEnd(); - } else { - stream.eatWhile(/\#|}/); - state.incomment = false; - } - return "comment"; - //Open tag - } else if (ch = stream.eat(/\{|%/)) { - //Cache close tag - state.intag = ch; - if(ch == "{") { - state.intag = "}"; - } - stream.eat("-"); - return "tag"; - } - } - stream.next(); - }; - - return { - startState: function () { - return {tokenize: tokenBase}; - }, - token: function (stream, state) { - return state.tokenize(stream, state); - } - }; - }); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/jsx/index.html b/backend/_pv_1_3_5/static/codemirror/mode/jsx/index.html deleted file mode 100755 index 1054bbcc0..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/jsx/index.html +++ /dev/null @@ -1,89 +0,0 @@ - - -CodeMirror: JSX mode - - - - - - - - - - - -
    -

    JSX mode

    - -
    - - - -

    JSX Mode for React's -JavaScript syntax extension.

    - -

    MIME types defined: text/jsx, text/typescript-jsx.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/jsx/jsx.js b/backend/_pv_1_3_5/static/codemirror/mode/jsx/jsx.js deleted file mode 100755 index 45c3024ab..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/jsx/jsx.js +++ /dev/null @@ -1,148 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../xml/xml"), require("../javascript/javascript")) - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../xml/xml", "../javascript/javascript"], mod) - else // Plain browser env - mod(CodeMirror) -})(function(CodeMirror) { - "use strict" - - // Depth means the amount of open braces in JS context, in XML - // context 0 means not in tag, 1 means in tag, and 2 means in tag - // and js block comment. - function Context(state, mode, depth, prev) { - this.state = state; this.mode = mode; this.depth = depth; this.prev = prev - } - - function copyContext(context) { - return new Context(CodeMirror.copyState(context.mode, context.state), - context.mode, - context.depth, - context.prev && copyContext(context.prev)) - } - - CodeMirror.defineMode("jsx", function(config, modeConfig) { - var xmlMode = CodeMirror.getMode(config, {name: "xml", allowMissing: true, multilineTagIndentPastTag: false}) - var jsMode = CodeMirror.getMode(config, modeConfig && modeConfig.base || "javascript") - - function flatXMLIndent(state) { - var tagName = state.tagName - state.tagName = null - var result = xmlMode.indent(state, "") - state.tagName = tagName - return result - } - - function token(stream, state) { - if (state.context.mode == xmlMode) - return xmlToken(stream, state, state.context) - else - return jsToken(stream, state, state.context) - } - - function xmlToken(stream, state, cx) { - if (cx.depth == 2) { // Inside a JS /* */ comment - if (stream.match(/^.*?\*\//)) cx.depth = 1 - else stream.skipToEnd() - return "comment" - } - - if (stream.peek() == "{") { - xmlMode.skipAttribute(cx.state) - - var indent = flatXMLIndent(cx.state), xmlContext = cx.state.context - // If JS starts on same line as tag - if (xmlContext && stream.match(/^[^>]*>\s*$/, false)) { - while (xmlContext.prev && !xmlContext.startOfLine) - xmlContext = xmlContext.prev - // If tag starts the line, use XML indentation level - if (xmlContext.startOfLine) indent -= config.indentUnit - // Else use JS indentation level - else if (cx.prev.state.lexical) indent = cx.prev.state.lexical.indented - // Else if inside of tag - } else if (cx.depth == 1) { - indent += config.indentUnit - } - - state.context = new Context(CodeMirror.startState(jsMode, indent), - jsMode, 0, state.context) - return null - } - - if (cx.depth == 1) { // Inside of tag - if (stream.peek() == "<") { // Tag inside of tag - xmlMode.skipAttribute(cx.state) - state.context = new Context(CodeMirror.startState(xmlMode, flatXMLIndent(cx.state)), - xmlMode, 0, state.context) - return null - } else if (stream.match("//")) { - stream.skipToEnd() - return "comment" - } else if (stream.match("/*")) { - cx.depth = 2 - return token(stream, state) - } - } - - var style = xmlMode.token(stream, cx.state), cur = stream.current(), stop - if (/\btag\b/.test(style)) { - if (/>$/.test(cur)) { - if (cx.state.context) cx.depth = 0 - else state.context = state.context.prev - } else if (/^ -1) { - stream.backUp(cur.length - stop) - } - return style - } - - function jsToken(stream, state, cx) { - if (stream.peek() == "<" && jsMode.expressionAllowed(stream, cx.state)) { - jsMode.skipExpression(cx.state) - state.context = new Context(CodeMirror.startState(xmlMode, jsMode.indent(cx.state, "")), - xmlMode, 0, state.context) - return null - } - - var style = jsMode.token(stream, cx.state) - if (!style && cx.depth != null) { - var cur = stream.current() - if (cur == "{") { - cx.depth++ - } else if (cur == "}") { - if (--cx.depth == 0) state.context = state.context.prev - } - } - return style - } - - return { - startState: function() { - return {context: new Context(CodeMirror.startState(jsMode), jsMode)} - }, - - copyState: function(state) { - return {context: copyContext(state.context)} - }, - - token: token, - - indent: function(state, textAfter, fullLine) { - return state.context.mode.indent(state.context.state, textAfter, fullLine) - }, - - innerMode: function(state) { - return state.context - } - } - }, "xml", "javascript") - - CodeMirror.defineMIME("text/jsx", "jsx") - CodeMirror.defineMIME("text/typescript-jsx", {name: "jsx", base: {name: "javascript", typescript: true}}) -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/jsx/test.js b/backend/_pv_1_3_5/static/codemirror/mode/jsx/test.js deleted file mode 100755 index c54a8b24c..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/jsx/test.js +++ /dev/null @@ -1,69 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "jsx") - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)) } - - MT("selfclose", - "[keyword var] [def x] [operator =] [bracket&tag <] [tag foo] [bracket&tag />] [operator +] [number 1];") - - MT("openclose", - "([bracket&tag <][tag foo][bracket&tag >]hello [atom &][bracket&tag ][operator ++])") - - MT("attr", - "([bracket&tag <][tag foo] [attribute abc]=[string 'value'][bracket&tag >]hello [atom &][bracket&tag ][operator ++])") - - MT("braced_attr", - "([bracket&tag <][tag foo] [attribute abc]={[number 10]}[bracket&tag >]hello [atom &][bracket&tag ][operator ++])") - - MT("braced_text", - "([bracket&tag <][tag foo][bracket&tag >]hello {[number 10]} [atom &][bracket&tag ][operator ++])") - - MT("nested_tag", - "([bracket&tag <][tag foo][bracket&tag ><][tag bar][bracket&tag >][operator ++])") - - MT("nested_jsx", - "[keyword return] (", - " [bracket&tag <][tag foo][bracket&tag >]", - " say {[number 1] [operator +] [bracket&tag <][tag bar] [attribute attr]={[number 10]}[bracket&tag />]}!", - " [bracket&tag ][operator ++]", - ")") - - MT("preserve_js_context", - "[variable x] [operator =] [string-2 `quasi${][bracket&tag <][tag foo][bracket&tag />][string-2 }quoted`]") - - MT("line_comment", - "([bracket&tag <][tag foo] [comment // hello]", - " [bracket&tag >][operator ++])") - - MT("line_comment_not_in_tag", - "([bracket&tag <][tag foo][bracket&tag >] // hello", - " [bracket&tag ][operator ++])") - - MT("block_comment", - "([bracket&tag <][tag foo] [comment /* hello]", - "[comment line 2]", - "[comment line 3 */] [bracket&tag >][operator ++])") - - MT("block_comment_not_in_tag", - "([bracket&tag <][tag foo][bracket&tag >]/* hello", - " line 2", - " line 3 */ [bracket&tag ][operator ++])") - - MT("missing_attr", - "([bracket&tag <][tag foo] [attribute selected][bracket&tag />][operator ++])") - - MT("indent_js", - "([bracket&tag <][tag foo][bracket&tag >]", - " [bracket&tag <][tag bar] [attribute baz]={[keyword function]() {", - " [keyword return] [number 10]", - " }}[bracket&tag />]", - " [bracket&tag ])") - - MT("spread", - "([bracket&tag <][tag foo] [attribute bar]={[meta ...][variable baz] [operator /][number 2]}[bracket&tag />])") - - MT("tag_attribute", - "([bracket&tag <][tag foo] [attribute bar]=[bracket&tag <][tag foo][bracket&tag />/>][operator ++])") -})() diff --git a/backend/_pv_1_3_5/static/codemirror/mode/julia/index.html b/backend/_pv_1_3_5/static/codemirror/mode/julia/index.html deleted file mode 100755 index e1492c210..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/julia/index.html +++ /dev/null @@ -1,195 +0,0 @@ - - -CodeMirror: Julia mode - - - - - - - - - -
    -

    Julia mode

    - -
    - - -

    MIME types defined: text/x-julia.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/julia/julia.js b/backend/_pv_1_3_5/static/codemirror/mode/julia/julia.js deleted file mode 100755 index 0174210b5..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/julia/julia.js +++ /dev/null @@ -1,410 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("julia", function(config, parserConf) { - function wordRegexp(words, end) { - if (typeof end === "undefined") { end = "\\b"; } - return new RegExp("^((" + words.join(")|(") + "))" + end); - } - - var octChar = "\\\\[0-7]{1,3}"; - var hexChar = "\\\\x[A-Fa-f0-9]{1,2}"; - var sChar = "\\\\[abefnrtv0%?'\"\\\\]"; - var uChar = "([^\\u0027\\u005C\\uD800-\\uDFFF]|[\\uD800-\\uDFFF][\\uDC00-\\uDFFF])"; - - var operators = parserConf.operators || wordRegexp([ - "\\.?[\\\\%*+\\-<>!=\\/^]=?", "\\.?[|&\\u00F7\\u2260\\u2264\\u2265]", - "\\u00D7", "\\u2208", "\\u2209", "\\u220B", "\\u220C", "\\u2229", - "\\u222A", "\\u2286", "\\u2288", "\\u228A", "\\u22c5", "\\?", "~", ":", - "\\$", "\\.[<>]", "<<=?", ">>>?=?", "\\.[<>=]=", "->?", "\\/\\/", "=>", - "<:", "\\bin\\b(?!\\()"], ""); - var delimiters = parserConf.delimiters || /^[;,()[\]{}]/; - var identifiers = parserConf.identifiers || /^[_A-Za-z\u00A1-\uFFFF][\w\u00A1-\uFFFF]*!*/; - - var chars = wordRegexp([octChar, hexChar, sChar, uChar], "'"); - var openers = wordRegexp(["begin", "function", "type", "immutable", "let", - "macro", "for", "while", "quote", "if", "else", "elseif", "try", - "finally", "catch", "do"]); - var closers = wordRegexp(["end", "else", "elseif", "catch", "finally"]); - var keywords = wordRegexp(["if", "else", "elseif", "while", "for", "begin", - "let", "end", "do", "try", "catch", "finally", "return", "break", - "continue", "global", "local", "const", "export", "import", "importall", - "using", "function", "macro", "module", "baremodule", "type", - "immutable", "quote", "typealias", "abstract", "bitstype"]); - var builtins = wordRegexp(["true", "false", "nothing", "NaN", "Inf"]); - - var macro = /^@[_A-Za-z][\w]*/; - var symbol = /^:[_A-Za-z\u00A1-\uFFFF][\w\u00A1-\uFFFF]*!*/; - var stringPrefixes = /^(`|"{3}|([_A-Za-z\u00A1-\uFFFF]*"))/; - - function inArray(state) { - return inGenerator(state, '[') - } - - function inGenerator(state, bracket) { - var curr = currentScope(state), - prev = currentScope(state, 1); - if (typeof(bracket) === "undefined") { bracket = '('; } - if (curr === bracket || (prev === bracket && curr === "for")) { - return true; - } - return false; - } - - function currentScope(state, n) { - if (typeof(n) === "undefined") { n = 0; } - if (state.scopes.length <= n) { - return null; - } - return state.scopes[state.scopes.length - (n + 1)]; - } - - // tokenizers - function tokenBase(stream, state) { - // Handle multiline comments - if (stream.match(/^#=/, false)) { - state.tokenize = tokenComment; - return state.tokenize(stream, state); - } - - // Handle scope changes - var leavingExpr = state.leavingExpr; - if (stream.sol()) { - leavingExpr = false; - } - state.leavingExpr = false; - - if (leavingExpr) { - if (stream.match(/^'+/)) { - return "operator"; - } - } - - if (stream.match(/^\.{2,3}/)) { - return "operator"; - } - - if (stream.eatSpace()) { - return null; - } - - var ch = stream.peek(); - - // Handle single line comments - if (ch === '#') { - stream.skipToEnd(); - return "comment"; - } - - if (ch === '[') { - state.scopes.push('['); - } - - if (ch === '(') { - state.scopes.push('('); - } - - var scope = currentScope(state); - - if (inArray(state) && ch === ']') { - if (scope === "for") { state.scopes.pop(); } - state.scopes.pop(); - state.leavingExpr = true; - } - - if (inGenerator(state) && ch === ')') { - if (scope === "for") { state.scopes.pop(); } - state.scopes.pop(); - state.leavingExpr = true; - } - - var match; - if (match = stream.match(openers, false)) { - state.scopes.push(match[0]); - } - - if (stream.match(closers, false)) { - state.scopes.pop(); - } - - if (inArray(state)) { - if (state.lastToken == "end" && stream.match(/^:/)) { - return "operator"; - } - if (stream.match(/^end/)) { - return "number"; - } - } - - // Handle type annotations - if (stream.match(/^::(?![:\$])/)) { - state.tokenize = tokenAnnotation; - return state.tokenize(stream, state); - } - - // Handle symbols - if (!leavingExpr && stream.match(symbol) || stream.match(/:\./)) { - return "builtin"; - } - - // Handle parametric types - if (stream.match(/^{[^}]*}(?=\()/)) { - return "builtin"; - } - - // Handle operators and Delimiters - if (stream.match(operators)) { - return "operator"; - } - - // Handle Number Literals - if (stream.match(/^[0-9\.]/, false)) { - var imMatcher = RegExp(/^im\b/); - var numberLiteral = false; - // Floats - if (stream.match(/^\d*\.(?!\.)\d*([Eef][\+\-]?\d+)?/i)) { numberLiteral = true; } - if (stream.match(/^\d+\.(?!\.)\d*/)) { numberLiteral = true; } - if (stream.match(/^\.\d+/)) { numberLiteral = true; } - if (stream.match(/^0x\.[0-9a-f]+p[\+\-]?\d+/i)) { numberLiteral = true; } - // Integers - if (stream.match(/^0x[0-9a-f]+/i)) { numberLiteral = true; } // Hex - if (stream.match(/^0b[01]+/i)) { numberLiteral = true; } // Binary - if (stream.match(/^0o[0-7]+/i)) { numberLiteral = true; } // Octal - if (stream.match(/^[1-9]\d*(e[\+\-]?\d+)?/)) { numberLiteral = true; } // Decimal - // Zero by itself with no other piece of number. - if (stream.match(/^0(?![\dx])/i)) { numberLiteral = true; } - if (numberLiteral) { - // Integer literals may be "long" - stream.match(imMatcher); - state.leavingExpr = true; - return "number"; - } - } - - // Handle Chars - if (stream.match(/^'/)) { - state.tokenize = tokenChar; - return state.tokenize(stream, state); - } - - // Handle Strings - if (stream.match(stringPrefixes)) { - state.tokenize = tokenStringFactory(stream.current()); - return state.tokenize(stream, state); - } - - if (stream.match(macro)) { - return "meta"; - } - - if (stream.match(delimiters)) { - return null; - } - - if (stream.match(keywords)) { - return "keyword"; - } - - if (stream.match(builtins)) { - return "builtin"; - } - - var isDefinition = state.isDefinition || state.lastToken == "function" || - state.lastToken == "macro" || state.lastToken == "type" || - state.lastToken == "immutable"; - - if (stream.match(identifiers)) { - if (isDefinition) { - if (stream.peek() === '.') { - state.isDefinition = true; - return "variable"; - } - state.isDefinition = false; - return "def"; - } - if (stream.match(/^({[^}]*})*\(/, false)) { - return callOrDef(stream, state); - } - state.leavingExpr = true; - return "variable"; - } - - // Handle non-detected items - stream.next(); - return "error"; - } - - function callOrDef(stream, state) { - var match = stream.match(/^(\(\s*)/); - if (match) { - if (state.firstParenPos < 0) - state.firstParenPos = state.scopes.length; - state.scopes.push('('); - state.charsAdvanced += match[1].length; - } - if (currentScope(state) == '(' && stream.match(/^\)/)) { - state.scopes.pop(); - state.charsAdvanced += 1; - if (state.scopes.length <= state.firstParenPos) { - var isDefinition = stream.match(/^\s*?=(?!=)/, false); - stream.backUp(state.charsAdvanced); - state.firstParenPos = -1; - state.charsAdvanced = 0; - if (isDefinition) - return "def"; - return "builtin"; - } - } - // Unfortunately javascript does not support multiline strings, so we have - // to undo anything done upto here if a function call or definition splits - // over two or more lines. - if (stream.match(/^$/g, false)) { - stream.backUp(state.charsAdvanced); - while (state.scopes.length > state.firstParenPos) - state.scopes.pop(); - state.firstParenPos = -1; - state.charsAdvanced = 0; - return "builtin"; - } - state.charsAdvanced += stream.match(/^([^()]*)/)[1].length; - return callOrDef(stream, state); - } - - function tokenAnnotation(stream, state) { - stream.match(/.*?(?=,|;|{|}|\(|\)|=|$|\s)/); - if (stream.match(/^{/)) { - state.nestedLevels++; - } else if (stream.match(/^}/)) { - state.nestedLevels--; - } - if (state.nestedLevels > 0) { - stream.match(/.*?(?={|})/); - } else if (state.nestedLevels == 0) { - state.tokenize = tokenBase; - } - return "builtin"; - } - - function tokenComment(stream, state) { - if (stream.match(/^#=/)) { - state.nestedLevels++; - } - if (!stream.match(/.*?(?=(#=|=#))/)) { - stream.skipToEnd(); - } - if (stream.match(/^=#/)) { - state.nestedLevels--; - if (state.nestedLevels == 0) - state.tokenize = tokenBase; - } - return "comment"; - } - - function tokenChar(stream, state) { - var isChar = false, match; - if (stream.match(chars)) { - isChar = true; - } else if (match = stream.match(/\\u([a-f0-9]{1,4})(?=')/i)) { - var value = parseInt(match[1], 16); - if (value <= 55295 || value >= 57344) { // (U+0,U+D7FF), (U+E000,U+FFFF) - isChar = true; - stream.next(); - } - } else if (match = stream.match(/\\U([A-Fa-f0-9]{5,8})(?=')/)) { - var value = parseInt(match[1], 16); - if (value <= 1114111) { // U+10FFFF - isChar = true; - stream.next(); - } - } - if (isChar) { - state.leavingExpr = true; - state.tokenize = tokenBase; - return "string"; - } - if (!stream.match(/^[^']+(?=')/)) { stream.skipToEnd(); } - if (stream.match(/^'/)) { state.tokenize = tokenBase; } - return "error"; - } - - function tokenStringFactory(delimiter) { - delimiter = (delimiter === '`' || delimiter === '"""') ? delimiter : '"'; - function tokenString(stream, state) { - if (stream.eat('\\')) { - stream.next(); - } else if (stream.match(delimiter)) { - state.tokenize = tokenBase; - state.leavingExpr = true; - return "string"; - } else { - stream.eat(/[`"]/); - } - stream.eatWhile(/[^\\`"]/); - return "string"; - } - return tokenString; - } - - var external = { - startState: function() { - return { - tokenize: tokenBase, - scopes: [], - lastToken: null, - leavingExpr: false, - isDefinition: false, - nestedLevels: 0, - charsAdvanced: 0, - firstParenPos: -1 - }; - }, - - token: function(stream, state) { - var style = state.tokenize(stream, state); - var current = stream.current(); - - if (current && style) { - state.lastToken = current; - } - - // Handle '.' connected identifiers - if (current === '.') { - style = stream.match(identifiers, false) || stream.match(macro, false) || - stream.match(/\(/, false) ? "operator" : "error"; - } - return style; - }, - - indent: function(state, textAfter) { - var delta = 0; - if ( textAfter === ']' || textAfter === ')' || textAfter === "end" || - textAfter === "else" || textAfter === "catch" || - textAfter === "finally" ) { - delta = -1; - } - return (state.scopes.length + delta) * config.indentUnit; - }, - - electricInput: /\b(end|else|catch|finally)\b/, - blockCommentStart: "#=", - blockCommentEnd: "=#", - lineComment: "#", - fold: "indent" - }; - return external; -}); - - -CodeMirror.defineMIME("text/x-julia", "julia"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/livescript/index.html b/backend/_pv_1_3_5/static/codemirror/mode/livescript/index.html deleted file mode 100755 index f41547987..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/livescript/index.html +++ /dev/null @@ -1,459 +0,0 @@ - - -CodeMirror: LiveScript mode - - - - - - - - - - -
    -

    LiveScript mode

    -
    - - -

    MIME types defined: text/x-livescript.

    - -

    The LiveScript mode was written by Kenneth Bentley.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/livescript/livescript.js b/backend/_pv_1_3_5/static/codemirror/mode/livescript/livescript.js deleted file mode 100755 index 1e363f876..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/livescript/livescript.js +++ /dev/null @@ -1,280 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** - * Link to the project's GitHub page: - * https://github.com/duralog/CodeMirror - */ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode('livescript', function(){ - var tokenBase = function(stream, state) { - var next_rule = state.next || "start"; - if (next_rule) { - state.next = state.next; - var nr = Rules[next_rule]; - if (nr.splice) { - for (var i$ = 0; i$ < nr.length; ++i$) { - var r = nr[i$]; - if (r.regex && stream.match(r.regex)) { - state.next = r.next || state.next; - return r.token; - } - } - stream.next(); - return 'error'; - } - if (stream.match(r = Rules[next_rule])) { - if (r.regex && stream.match(r.regex)) { - state.next = r.next; - return r.token; - } else { - stream.next(); - return 'error'; - } - } - } - stream.next(); - return 'error'; - }; - var external = { - startState: function(){ - return { - next: 'start', - lastToken: {style: null, indent: 0, content: ""} - }; - }, - token: function(stream, state){ - while (stream.pos == stream.start) - var style = tokenBase(stream, state); - state.lastToken = { - style: style, - indent: stream.indentation(), - content: stream.current() - }; - return style.replace(/\./g, ' '); - }, - indent: function(state){ - var indentation = state.lastToken.indent; - if (state.lastToken.content.match(indenter)) { - indentation += 2; - } - return indentation; - } - }; - return external; - }); - - var identifier = '(?![\\d\\s])[$\\w\\xAA-\\uFFDC](?:(?!\\s)[$\\w\\xAA-\\uFFDC]|-[A-Za-z])*'; - var indenter = RegExp('(?:[({[=:]|[-~]>|\\b(?:e(?:lse|xport)|d(?:o|efault)|t(?:ry|hen)|finally|import(?:\\s*all)?|const|var|let|new|catch(?:\\s*' + identifier + ')?))\\s*$'); - var keywordend = '(?![$\\w]|-[A-Za-z]|\\s*:(?![:=]))'; - var stringfill = { - token: 'string', - regex: '.+' - }; - var Rules = { - start: [ - { - token: 'comment.doc', - regex: '/\\*', - next: 'comment' - }, { - token: 'comment', - regex: '#.*' - }, { - token: 'keyword', - regex: '(?:t(?:h(?:is|row|en)|ry|ypeof!?)|c(?:on(?:tinue|st)|a(?:se|tch)|lass)|i(?:n(?:stanceof)?|mp(?:ort(?:\\s+all)?|lements)|[fs])|d(?:e(?:fault|lete|bugger)|o)|f(?:or(?:\\s+own)?|inally|unction)|s(?:uper|witch)|e(?:lse|x(?:tends|port)|val)|a(?:nd|rguments)|n(?:ew|ot)|un(?:less|til)|w(?:hile|ith)|o[fr]|return|break|let|var|loop)' + keywordend - }, { - token: 'constant.language', - regex: '(?:true|false|yes|no|on|off|null|void|undefined)' + keywordend - }, { - token: 'invalid.illegal', - regex: '(?:p(?:ackage|r(?:ivate|otected)|ublic)|i(?:mplements|nterface)|enum|static|yield)' + keywordend - }, { - token: 'language.support.class', - regex: '(?:R(?:e(?:gExp|ferenceError)|angeError)|S(?:tring|yntaxError)|E(?:rror|valError)|Array|Boolean|Date|Function|Number|Object|TypeError|URIError)' + keywordend - }, { - token: 'language.support.function', - regex: '(?:is(?:NaN|Finite)|parse(?:Int|Float)|Math|JSON|(?:en|de)codeURI(?:Component)?)' + keywordend - }, { - token: 'variable.language', - regex: '(?:t(?:hat|il|o)|f(?:rom|allthrough)|it|by|e)' + keywordend - }, { - token: 'identifier', - regex: identifier + '\\s*:(?![:=])' - }, { - token: 'variable', - regex: identifier - }, { - token: 'keyword.operator', - regex: '(?:\\.{3}|\\s+\\?)' - }, { - token: 'keyword.variable', - regex: '(?:@+|::|\\.\\.)', - next: 'key' - }, { - token: 'keyword.operator', - regex: '\\.\\s*', - next: 'key' - }, { - token: 'string', - regex: '\\\\\\S[^\\s,;)}\\]]*' - }, { - token: 'string.doc', - regex: '\'\'\'', - next: 'qdoc' - }, { - token: 'string.doc', - regex: '"""', - next: 'qqdoc' - }, { - token: 'string', - regex: '\'', - next: 'qstring' - }, { - token: 'string', - regex: '"', - next: 'qqstring' - }, { - token: 'string', - regex: '`', - next: 'js' - }, { - token: 'string', - regex: '<\\[', - next: 'words' - }, { - token: 'string.regex', - regex: '//', - next: 'heregex' - }, { - token: 'string.regex', - regex: '\\/(?:[^[\\/\\n\\\\]*(?:(?:\\\\.|\\[[^\\]\\n\\\\]*(?:\\\\.[^\\]\\n\\\\]*)*\\])[^[\\/\\n\\\\]*)*)\\/[gimy$]{0,4}', - next: 'key' - }, { - token: 'constant.numeric', - regex: '(?:0x[\\da-fA-F][\\da-fA-F_]*|(?:[2-9]|[12]\\d|3[0-6])r[\\da-zA-Z][\\da-zA-Z_]*|(?:\\d[\\d_]*(?:\\.\\d[\\d_]*)?|\\.\\d[\\d_]*)(?:e[+-]?\\d[\\d_]*)?[\\w$]*)' - }, { - token: 'lparen', - regex: '[({[]' - }, { - token: 'rparen', - regex: '[)}\\]]', - next: 'key' - }, { - token: 'keyword.operator', - regex: '\\S+' - }, { - token: 'text', - regex: '\\s+' - } - ], - heregex: [ - { - token: 'string.regex', - regex: '.*?//[gimy$?]{0,4}', - next: 'start' - }, { - token: 'string.regex', - regex: '\\s*#{' - }, { - token: 'comment.regex', - regex: '\\s+(?:#.*)?' - }, { - token: 'string.regex', - regex: '\\S+' - } - ], - key: [ - { - token: 'keyword.operator', - regex: '[.?@!]+' - }, { - token: 'identifier', - regex: identifier, - next: 'start' - }, { - token: 'text', - regex: '', - next: 'start' - } - ], - comment: [ - { - token: 'comment.doc', - regex: '.*?\\*/', - next: 'start' - }, { - token: 'comment.doc', - regex: '.+' - } - ], - qdoc: [ - { - token: 'string', - regex: ".*?'''", - next: 'key' - }, stringfill - ], - qqdoc: [ - { - token: 'string', - regex: '.*?"""', - next: 'key' - }, stringfill - ], - qstring: [ - { - token: 'string', - regex: '[^\\\\\']*(?:\\\\.[^\\\\\']*)*\'', - next: 'key' - }, stringfill - ], - qqstring: [ - { - token: 'string', - regex: '[^\\\\"]*(?:\\\\.[^\\\\"]*)*"', - next: 'key' - }, stringfill - ], - js: [ - { - token: 'string', - regex: '[^\\\\`]*(?:\\\\.[^\\\\`]*)*`', - next: 'key' - }, stringfill - ], - words: [ - { - token: 'string', - regex: '.*?\\]>', - next: 'key' - }, stringfill - ] - }; - for (var idx in Rules) { - var r = Rules[idx]; - if (r.splice) { - for (var i = 0, len = r.length; i < len; ++i) { - var rr = r[i]; - if (typeof rr.regex === 'string') { - Rules[idx][i].regex = new RegExp('^' + rr.regex); - } - } - } else if (typeof rr.regex === 'string') { - Rules[idx].regex = new RegExp('^' + r.regex); - } - } - - CodeMirror.defineMIME('text/x-livescript', 'livescript'); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/lua/index.html b/backend/_pv_1_3_5/static/codemirror/mode/lua/index.html deleted file mode 100755 index fc98b9446..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/lua/index.html +++ /dev/null @@ -1,85 +0,0 @@ - - -CodeMirror: Lua mode - - - - - - - - - - - -
    -

    Lua mode

    -
    - - -

    Loosely based on Franciszek - Wawrzak's CodeMirror - 1 mode. One configuration parameter is - supported, specials, to which you can provide an - array of strings to have those identifiers highlighted with - the lua-special style.

    -

    MIME types defined: text/x-lua.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/lua/lua.js b/backend/_pv_1_3_5/static/codemirror/mode/lua/lua.js deleted file mode 100755 index 0b19abd30..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/lua/lua.js +++ /dev/null @@ -1,159 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// LUA mode. Ported to CodeMirror 2 from Franciszek Wawrzak's -// CodeMirror 1 mode. -// highlights keywords, strings, comments (no leveling supported! ("[==[")), tokens, basic indenting - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("lua", function(config, parserConfig) { - var indentUnit = config.indentUnit; - - function prefixRE(words) { - return new RegExp("^(?:" + words.join("|") + ")", "i"); - } - function wordRE(words) { - return new RegExp("^(?:" + words.join("|") + ")$", "i"); - } - var specials = wordRE(parserConfig.specials || []); - - // long list of standard functions from lua manual - var builtins = wordRE([ - "_G","_VERSION","assert","collectgarbage","dofile","error","getfenv","getmetatable","ipairs","load", - "loadfile","loadstring","module","next","pairs","pcall","print","rawequal","rawget","rawset","require", - "select","setfenv","setmetatable","tonumber","tostring","type","unpack","xpcall", - - "coroutine.create","coroutine.resume","coroutine.running","coroutine.status","coroutine.wrap","coroutine.yield", - - "debug.debug","debug.getfenv","debug.gethook","debug.getinfo","debug.getlocal","debug.getmetatable", - "debug.getregistry","debug.getupvalue","debug.setfenv","debug.sethook","debug.setlocal","debug.setmetatable", - "debug.setupvalue","debug.traceback", - - "close","flush","lines","read","seek","setvbuf","write", - - "io.close","io.flush","io.input","io.lines","io.open","io.output","io.popen","io.read","io.stderr","io.stdin", - "io.stdout","io.tmpfile","io.type","io.write", - - "math.abs","math.acos","math.asin","math.atan","math.atan2","math.ceil","math.cos","math.cosh","math.deg", - "math.exp","math.floor","math.fmod","math.frexp","math.huge","math.ldexp","math.log","math.log10","math.max", - "math.min","math.modf","math.pi","math.pow","math.rad","math.random","math.randomseed","math.sin","math.sinh", - "math.sqrt","math.tan","math.tanh", - - "os.clock","os.date","os.difftime","os.execute","os.exit","os.getenv","os.remove","os.rename","os.setlocale", - "os.time","os.tmpname", - - "package.cpath","package.loaded","package.loaders","package.loadlib","package.path","package.preload", - "package.seeall", - - "string.byte","string.char","string.dump","string.find","string.format","string.gmatch","string.gsub", - "string.len","string.lower","string.match","string.rep","string.reverse","string.sub","string.upper", - - "table.concat","table.insert","table.maxn","table.remove","table.sort" - ]); - var keywords = wordRE(["and","break","elseif","false","nil","not","or","return", - "true","function", "end", "if", "then", "else", "do", - "while", "repeat", "until", "for", "in", "local" ]); - - var indentTokens = wordRE(["function", "if","repeat","do", "\\(", "{"]); - var dedentTokens = wordRE(["end", "until", "\\)", "}"]); - var dedentPartial = prefixRE(["end", "until", "\\)", "}", "else", "elseif"]); - - function readBracket(stream) { - var level = 0; - while (stream.eat("=")) ++level; - stream.eat("["); - return level; - } - - function normal(stream, state) { - var ch = stream.next(); - if (ch == "-" && stream.eat("-")) { - if (stream.eat("[") && stream.eat("[")) - return (state.cur = bracketed(readBracket(stream), "comment"))(stream, state); - stream.skipToEnd(); - return "comment"; - } - if (ch == "\"" || ch == "'") - return (state.cur = string(ch))(stream, state); - if (ch == "[" && /[\[=]/.test(stream.peek())) - return (state.cur = bracketed(readBracket(stream), "string"))(stream, state); - if (/\d/.test(ch)) { - stream.eatWhile(/[\w.%]/); - return "number"; - } - if (/[\w_]/.test(ch)) { - stream.eatWhile(/[\w\\\-_.]/); - return "variable"; - } - return null; - } - - function bracketed(level, style) { - return function(stream, state) { - var curlev = null, ch; - while ((ch = stream.next()) != null) { - if (curlev == null) {if (ch == "]") curlev = 0;} - else if (ch == "=") ++curlev; - else if (ch == "]" && curlev == level) { state.cur = normal; break; } - else curlev = null; - } - return style; - }; - } - - function string(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) break; - escaped = !escaped && ch == "\\"; - } - if (!escaped) state.cur = normal; - return "string"; - }; - } - - return { - startState: function(basecol) { - return {basecol: basecol || 0, indentDepth: 0, cur: normal}; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - var style = state.cur(stream, state); - var word = stream.current(); - if (style == "variable") { - if (keywords.test(word)) style = "keyword"; - else if (builtins.test(word)) style = "builtin"; - else if (specials.test(word)) style = "variable-2"; - } - if ((style != "comment") && (style != "string")){ - if (indentTokens.test(word)) ++state.indentDepth; - else if (dedentTokens.test(word)) --state.indentDepth; - } - return style; - }, - - indent: function(state, textAfter) { - var closing = dedentPartial.test(textAfter); - return state.basecol + indentUnit * (state.indentDepth - (closing ? 1 : 0)); - }, - - lineComment: "--", - blockCommentStart: "--[[", - blockCommentEnd: "]]" - }; -}); - -CodeMirror.defineMIME("text/x-lua", "lua"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/markdown/index.html b/backend/_pv_1_3_5/static/codemirror/mode/markdown/index.html deleted file mode 100755 index 15660c261..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/markdown/index.html +++ /dev/null @@ -1,361 +0,0 @@ - - -CodeMirror: Markdown mode - - - - - - - - - - - -
    -

    Markdown mode

    -
    - - - -

    You might want to use the Github-Flavored Markdown mode instead, which adds support for fenced code blocks and a few other things.

    - -

    Optionally depends on the XML mode for properly highlighted inline XML blocks.

    - -

    MIME types defined: text/x-markdown.

    - -

    Parsing/Highlighting Tests: normal, verbose.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/markdown/markdown.js b/backend/_pv_1_3_5/static/codemirror/mode/markdown/markdown.js deleted file mode 100755 index 1aeb34414..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/markdown/markdown.js +++ /dev/null @@ -1,813 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../xml/xml"), require("../meta")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../xml/xml", "../meta"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("markdown", function(cmCfg, modeCfg) { - - var htmlMode = CodeMirror.getMode(cmCfg, "text/html"); - var htmlModeMissing = htmlMode.name == "null" - - function getMode(name) { - if (CodeMirror.findModeByName) { - var found = CodeMirror.findModeByName(name); - if (found) name = found.mime || found.mimes[0]; - } - var mode = CodeMirror.getMode(cmCfg, name); - return mode.name == "null" ? null : mode; - } - - // Should characters that affect highlighting be highlighted separate? - // Does not include characters that will be output (such as `1.` and `-` for lists) - if (modeCfg.highlightFormatting === undefined) - modeCfg.highlightFormatting = false; - - // Maximum number of nested blockquotes. Set to 0 for infinite nesting. - // Excess `>` will emit `error` token. - if (modeCfg.maxBlockquoteDepth === undefined) - modeCfg.maxBlockquoteDepth = 0; - - // Should underscores in words open/close em/strong? - if (modeCfg.underscoresBreakWords === undefined) - modeCfg.underscoresBreakWords = true; - - // Use `fencedCodeBlocks` to configure fenced code blocks. false to - // disable, string to specify a precise regexp that the fence should - // match, and true to allow three or more backticks or tildes (as - // per CommonMark). - - // Turn on task lists? ("- [ ] " and "- [x] ") - if (modeCfg.taskLists === undefined) modeCfg.taskLists = false; - - // Turn on strikethrough syntax - if (modeCfg.strikethrough === undefined) - modeCfg.strikethrough = false; - - // Allow token types to be overridden by user-provided token types. - if (modeCfg.tokenTypeOverrides === undefined) - modeCfg.tokenTypeOverrides = {}; - - var tokenTypes = { - header: "header", - code: "comment", - quote: "quote", - list1: "variable-2", - list2: "variable-3", - list3: "keyword", - hr: "hr", - image: "image", - imageAltText: "image-alt-text", - imageMarker: "image-marker", - formatting: "formatting", - linkInline: "link", - linkEmail: "link", - linkText: "link", - linkHref: "string", - em: "em", - strong: "strong", - strikethrough: "strikethrough" - }; - - for (var tokenType in tokenTypes) { - if (tokenTypes.hasOwnProperty(tokenType) && modeCfg.tokenTypeOverrides[tokenType]) { - tokenTypes[tokenType] = modeCfg.tokenTypeOverrides[tokenType]; - } - } - - var hrRE = /^([*\-_])(?:\s*\1){2,}\s*$/ - , listRE = /^(?:[*\-+]|^[0-9]+([.)]))\s+/ - , taskListRE = /^\[(x| )\](?=\s)/ // Must follow listRE - , atxHeaderRE = modeCfg.allowAtxHeaderWithoutSpace ? /^(#+)/ : /^(#+)(?: |$)/ - , setextHeaderRE = /^ *(?:\={1,}|-{1,})\s*$/ - , textRE = /^[^#!\[\]*_\\<>` "'(~]+/ - , fencedCodeRE = new RegExp("^(" + (modeCfg.fencedCodeBlocks === true ? "~~~+|```+" : modeCfg.fencedCodeBlocks) + - ")[ \\t]*([\\w+#\-]*)"); - - function switchInline(stream, state, f) { - state.f = state.inline = f; - return f(stream, state); - } - - function switchBlock(stream, state, f) { - state.f = state.block = f; - return f(stream, state); - } - - function lineIsEmpty(line) { - return !line || !/\S/.test(line.string) - } - - // Blocks - - function blankLine(state) { - // Reset linkTitle state - state.linkTitle = false; - // Reset EM state - state.em = false; - // Reset STRONG state - state.strong = false; - // Reset strikethrough state - state.strikethrough = false; - // Reset state.quote - state.quote = 0; - // Reset state.indentedCode - state.indentedCode = false; - if (htmlModeMissing && state.f == htmlBlock) { - state.f = inlineNormal; - state.block = blockNormal; - } - // Reset state.trailingSpace - state.trailingSpace = 0; - state.trailingSpaceNewLine = false; - // Mark this line as blank - state.prevLine = state.thisLine - state.thisLine = null - return null; - } - - function blockNormal(stream, state) { - - var sol = stream.sol(); - - var prevLineIsList = state.list !== false, - prevLineIsIndentedCode = state.indentedCode; - - state.indentedCode = false; - - if (prevLineIsList) { - if (state.indentationDiff >= 0) { // Continued list - if (state.indentationDiff < 4) { // Only adjust indentation if *not* a code block - state.indentation -= state.indentationDiff; - } - state.list = null; - } else if (state.indentation > 0) { - state.list = null; - } else { // No longer a list - state.list = false; - } - } - - var match = null; - if (state.indentationDiff >= 4) { - stream.skipToEnd(); - if (prevLineIsIndentedCode || lineIsEmpty(state.prevLine)) { - state.indentation -= 4; - state.indentedCode = true; - return tokenTypes.code; - } else { - return null; - } - } else if (stream.eatSpace()) { - return null; - } else if ((match = stream.match(atxHeaderRE)) && match[1].length <= 6) { - state.header = match[1].length; - if (modeCfg.highlightFormatting) state.formatting = "header"; - state.f = state.inline; - return getType(state); - } else if (!lineIsEmpty(state.prevLine) && !state.quote && !prevLineIsList && - !prevLineIsIndentedCode && (match = stream.match(setextHeaderRE))) { - state.header = match[0].charAt(0) == '=' ? 1 : 2; - if (modeCfg.highlightFormatting) state.formatting = "header"; - state.f = state.inline; - return getType(state); - } else if (stream.eat('>')) { - state.quote = sol ? 1 : state.quote + 1; - if (modeCfg.highlightFormatting) state.formatting = "quote"; - stream.eatSpace(); - return getType(state); - } else if (stream.peek() === '[') { - return switchInline(stream, state, footnoteLink); - } else if (stream.match(hrRE, true)) { - state.hr = true; - return tokenTypes.hr; - } else if (match = stream.match(listRE)) { - var listType = match[1] ? "ol" : "ul"; - state.indentation = stream.column() + stream.current().length; - state.list = true; - - // While this list item's marker's indentation - // is less than the deepest list item's content's indentation, - // pop the deepest list item indentation off the stack. - while (state.listStack && stream.column() < state.listStack[state.listStack.length - 1]) { - state.listStack.pop(); - } - - // Add this list item's content's indentation to the stack - state.listStack.push(state.indentation); - - if (modeCfg.taskLists && stream.match(taskListRE, false)) { - state.taskList = true; - } - state.f = state.inline; - if (modeCfg.highlightFormatting) state.formatting = ["list", "list-" + listType]; - return getType(state); - } else if (modeCfg.fencedCodeBlocks && (match = stream.match(fencedCodeRE, true))) { - state.fencedChars = match[1] - // try switching mode - state.localMode = getMode(match[2]); - if (state.localMode) state.localState = CodeMirror.startState(state.localMode); - state.f = state.block = local; - if (modeCfg.highlightFormatting) state.formatting = "code-block"; - state.code = -1 - return getType(state); - } - - return switchInline(stream, state, state.inline); - } - - function htmlBlock(stream, state) { - var style = htmlMode.token(stream, state.htmlState); - if (!htmlModeMissing) { - var inner = CodeMirror.innerMode(htmlMode, state.htmlState) - if ((inner.mode.name == "xml" && inner.state.tagStart === null && - (!inner.state.context && inner.state.tokenize.isInText)) || - (state.md_inside && stream.current().indexOf(">") > -1)) { - state.f = inlineNormal; - state.block = blockNormal; - state.htmlState = null; - } - } - return style; - } - - function local(stream, state) { - if (state.fencedChars && stream.match(state.fencedChars, false)) { - state.localMode = state.localState = null; - state.f = state.block = leavingLocal; - return null; - } else if (state.localMode) { - return state.localMode.token(stream, state.localState); - } else { - stream.skipToEnd(); - return tokenTypes.code; - } - } - - function leavingLocal(stream, state) { - stream.match(state.fencedChars); - state.block = blockNormal; - state.f = inlineNormal; - state.fencedChars = null; - if (modeCfg.highlightFormatting) state.formatting = "code-block"; - state.code = 1 - var returnType = getType(state); - state.code = 0 - return returnType; - } - - // Inline - function getType(state) { - var styles = []; - - if (state.formatting) { - styles.push(tokenTypes.formatting); - - if (typeof state.formatting === "string") state.formatting = [state.formatting]; - - for (var i = 0; i < state.formatting.length; i++) { - styles.push(tokenTypes.formatting + "-" + state.formatting[i]); - - if (state.formatting[i] === "header") { - styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.header); - } - - // Add `formatting-quote` and `formatting-quote-#` for blockquotes - // Add `error` instead if the maximum blockquote nesting depth is passed - if (state.formatting[i] === "quote") { - if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) { - styles.push(tokenTypes.formatting + "-" + state.formatting[i] + "-" + state.quote); - } else { - styles.push("error"); - } - } - } - } - - if (state.taskOpen) { - styles.push("meta"); - return styles.length ? styles.join(' ') : null; - } - if (state.taskClosed) { - styles.push("property"); - return styles.length ? styles.join(' ') : null; - } - - if (state.linkHref) { - styles.push(tokenTypes.linkHref, "url"); - } else { // Only apply inline styles to non-url text - if (state.strong) { styles.push(tokenTypes.strong); } - if (state.em) { styles.push(tokenTypes.em); } - if (state.strikethrough) { styles.push(tokenTypes.strikethrough); } - if (state.linkText) { styles.push(tokenTypes.linkText); } - if (state.code) { styles.push(tokenTypes.code); } - if (state.image) { styles.push(tokenTypes.image); } - if (state.imageAltText) { styles.push(tokenTypes.imageAltText, "link"); } - if (state.imageMarker) { styles.push(tokenTypes.imageMarker); } - } - - if (state.header) { styles.push(tokenTypes.header, tokenTypes.header + "-" + state.header); } - - if (state.quote) { - styles.push(tokenTypes.quote); - - // Add `quote-#` where the maximum for `#` is modeCfg.maxBlockquoteDepth - if (!modeCfg.maxBlockquoteDepth || modeCfg.maxBlockquoteDepth >= state.quote) { - styles.push(tokenTypes.quote + "-" + state.quote); - } else { - styles.push(tokenTypes.quote + "-" + modeCfg.maxBlockquoteDepth); - } - } - - if (state.list !== false) { - var listMod = (state.listStack.length - 1) % 3; - if (!listMod) { - styles.push(tokenTypes.list1); - } else if (listMod === 1) { - styles.push(tokenTypes.list2); - } else { - styles.push(tokenTypes.list3); - } - } - - if (state.trailingSpaceNewLine) { - styles.push("trailing-space-new-line"); - } else if (state.trailingSpace) { - styles.push("trailing-space-" + (state.trailingSpace % 2 ? "a" : "b")); - } - - return styles.length ? styles.join(' ') : null; - } - - function handleText(stream, state) { - if (stream.match(textRE, true)) { - return getType(state); - } - return undefined; - } - - function inlineNormal(stream, state) { - var style = state.text(stream, state); - if (typeof style !== 'undefined') - return style; - - if (state.list) { // List marker (*, +, -, 1., etc) - state.list = null; - return getType(state); - } - - if (state.taskList) { - var taskOpen = stream.match(taskListRE, true)[1] !== "x"; - if (taskOpen) state.taskOpen = true; - else state.taskClosed = true; - if (modeCfg.highlightFormatting) state.formatting = "task"; - state.taskList = false; - return getType(state); - } - - state.taskOpen = false; - state.taskClosed = false; - - if (state.header && stream.match(/^#+$/, true)) { - if (modeCfg.highlightFormatting) state.formatting = "header"; - return getType(state); - } - - // Get sol() value now, before character is consumed - var sol = stream.sol(); - - var ch = stream.next(); - - // Matches link titles present on next line - if (state.linkTitle) { - state.linkTitle = false; - var matchCh = ch; - if (ch === '(') { - matchCh = ')'; - } - matchCh = (matchCh+'').replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"); - var regex = '^\\s*(?:[^' + matchCh + '\\\\]+|\\\\\\\\|\\\\.)' + matchCh; - if (stream.match(new RegExp(regex), true)) { - return tokenTypes.linkHref; - } - } - - // If this block is changed, it may need to be updated in GFM mode - if (ch === '`') { - var previousFormatting = state.formatting; - if (modeCfg.highlightFormatting) state.formatting = "code"; - stream.eatWhile('`'); - var count = stream.current().length - if (state.code == 0) { - state.code = count - return getType(state) - } else if (count == state.code) { // Must be exact - var t = getType(state) - state.code = 0 - return t - } else { - state.formatting = previousFormatting - return getType(state) - } - } else if (state.code) { - return getType(state); - } - - if (ch === '\\') { - stream.next(); - if (modeCfg.highlightFormatting) { - var type = getType(state); - var formattingEscape = tokenTypes.formatting + "-escape"; - return type ? type + " " + formattingEscape : formattingEscape; - } - } - - if (ch === '!' && stream.match(/\[[^\]]*\] ?(?:\(|\[)/, false)) { - state.imageMarker = true; - state.image = true; - if (modeCfg.highlightFormatting) state.formatting = "image"; - return getType(state); - } - - if (ch === '[' && state.imageMarker && stream.match(/[^\]]*\](\(.*?\)| ?\[.*?\])/, false)) { - state.imageMarker = false; - state.imageAltText = true - if (modeCfg.highlightFormatting) state.formatting = "image"; - return getType(state); - } - - if (ch === ']' && state.imageAltText) { - if (modeCfg.highlightFormatting) state.formatting = "image"; - var type = getType(state); - state.imageAltText = false; - state.image = false; - state.inline = state.f = linkHref; - return type; - } - - if (ch === '[' && stream.match(/[^\]]*\](\(.*\)| ?\[.*?\])/, false) && !state.image) { - state.linkText = true; - if (modeCfg.highlightFormatting) state.formatting = "link"; - return getType(state); - } - - if (ch === ']' && state.linkText && stream.match(/\(.*?\)| ?\[.*?\]/, false)) { - if (modeCfg.highlightFormatting) state.formatting = "link"; - var type = getType(state); - state.linkText = false; - state.inline = state.f = linkHref; - return type; - } - - if (ch === '<' && stream.match(/^(https?|ftps?):\/\/(?:[^\\>]|\\.)+>/, false)) { - state.f = state.inline = linkInline; - if (modeCfg.highlightFormatting) state.formatting = "link"; - var type = getType(state); - if (type){ - type += " "; - } else { - type = ""; - } - return type + tokenTypes.linkInline; - } - - if (ch === '<' && stream.match(/^[^> \\]+@(?:[^\\>]|\\.)+>/, false)) { - state.f = state.inline = linkInline; - if (modeCfg.highlightFormatting) state.formatting = "link"; - var type = getType(state); - if (type){ - type += " "; - } else { - type = ""; - } - return type + tokenTypes.linkEmail; - } - - if (ch === '<' && stream.match(/^(!--|[a-z]+(?:\s+[a-z_:.\-]+(?:\s*=\s*[^ >]+)?)*\s*>)/i, false)) { - var end = stream.string.indexOf(">", stream.pos); - if (end != -1) { - var atts = stream.string.substring(stream.start, end); - if (/markdown\s*=\s*('|"){0,1}1('|"){0,1}/.test(atts)) state.md_inside = true; - } - stream.backUp(1); - state.htmlState = CodeMirror.startState(htmlMode); - return switchBlock(stream, state, htmlBlock); - } - - if (ch === '<' && stream.match(/^\/\w*?>/)) { - state.md_inside = false; - return "tag"; - } - - var ignoreUnderscore = false; - if (!modeCfg.underscoresBreakWords) { - if (ch === '_' && stream.peek() !== '_' && stream.match(/(\w)/, false)) { - var prevPos = stream.pos - 2; - if (prevPos >= 0) { - var prevCh = stream.string.charAt(prevPos); - if (prevCh !== '_' && prevCh.match(/(\w)/, false)) { - ignoreUnderscore = true; - } - } - } - } - if (ch === '*' || (ch === '_' && !ignoreUnderscore)) { - if (sol && stream.peek() === ' ') { - // Do nothing, surrounded by newline and space - } else if (state.strong === ch && stream.eat(ch)) { // Remove STRONG - if (modeCfg.highlightFormatting) state.formatting = "strong"; - var t = getType(state); - state.strong = false; - return t; - } else if (!state.strong && stream.eat(ch)) { // Add STRONG - state.strong = ch; - if (modeCfg.highlightFormatting) state.formatting = "strong"; - return getType(state); - } else if (state.em === ch) { // Remove EM - if (modeCfg.highlightFormatting) state.formatting = "em"; - var t = getType(state); - state.em = false; - return t; - } else if (!state.em) { // Add EM - state.em = ch; - if (modeCfg.highlightFormatting) state.formatting = "em"; - return getType(state); - } - } else if (ch === ' ') { - if (stream.eat('*') || stream.eat('_')) { // Probably surrounded by spaces - if (stream.peek() === ' ') { // Surrounded by spaces, ignore - return getType(state); - } else { // Not surrounded by spaces, back up pointer - stream.backUp(1); - } - } - } - - if (modeCfg.strikethrough) { - if (ch === '~' && stream.eatWhile(ch)) { - if (state.strikethrough) {// Remove strikethrough - if (modeCfg.highlightFormatting) state.formatting = "strikethrough"; - var t = getType(state); - state.strikethrough = false; - return t; - } else if (stream.match(/^[^\s]/, false)) {// Add strikethrough - state.strikethrough = true; - if (modeCfg.highlightFormatting) state.formatting = "strikethrough"; - return getType(state); - } - } else if (ch === ' ') { - if (stream.match(/^~~/, true)) { // Probably surrounded by space - if (stream.peek() === ' ') { // Surrounded by spaces, ignore - return getType(state); - } else { // Not surrounded by spaces, back up pointer - stream.backUp(2); - } - } - } - } - - if (ch === ' ') { - if (stream.match(/ +$/, false)) { - state.trailingSpace++; - } else if (state.trailingSpace) { - state.trailingSpaceNewLine = true; - } - } - - return getType(state); - } - - function linkInline(stream, state) { - var ch = stream.next(); - - if (ch === ">") { - state.f = state.inline = inlineNormal; - if (modeCfg.highlightFormatting) state.formatting = "link"; - var type = getType(state); - if (type){ - type += " "; - } else { - type = ""; - } - return type + tokenTypes.linkInline; - } - - stream.match(/^[^>]+/, true); - - return tokenTypes.linkInline; - } - - function linkHref(stream, state) { - // Check if space, and return NULL if so (to avoid marking the space) - if(stream.eatSpace()){ - return null; - } - var ch = stream.next(); - if (ch === '(' || ch === '[') { - state.f = state.inline = getLinkHrefInside(ch === "(" ? ")" : "]", 0); - if (modeCfg.highlightFormatting) state.formatting = "link-string"; - state.linkHref = true; - return getType(state); - } - return 'error'; - } - - var linkRE = { - ")": /^(?:[^\\\(\)]|\\.|\((?:[^\\\(\)]|\\.)*\))*?(?=\))/, - "]": /^(?:[^\\\[\]]|\\.|\[(?:[^\\\[\\]]|\\.)*\])*?(?=\])/ - } - - function getLinkHrefInside(endChar) { - return function(stream, state) { - var ch = stream.next(); - - if (ch === endChar) { - state.f = state.inline = inlineNormal; - if (modeCfg.highlightFormatting) state.formatting = "link-string"; - var returnState = getType(state); - state.linkHref = false; - return returnState; - } - - stream.match(linkRE[endChar]) - state.linkHref = true; - return getType(state); - }; - } - - function footnoteLink(stream, state) { - if (stream.match(/^([^\]\\]|\\.)*\]:/, false)) { - state.f = footnoteLinkInside; - stream.next(); // Consume [ - if (modeCfg.highlightFormatting) state.formatting = "link"; - state.linkText = true; - return getType(state); - } - return switchInline(stream, state, inlineNormal); - } - - function footnoteLinkInside(stream, state) { - if (stream.match(/^\]:/, true)) { - state.f = state.inline = footnoteUrl; - if (modeCfg.highlightFormatting) state.formatting = "link"; - var returnType = getType(state); - state.linkText = false; - return returnType; - } - - stream.match(/^([^\]\\]|\\.)+/, true); - - return tokenTypes.linkText; - } - - function footnoteUrl(stream, state) { - // Check if space, and return NULL if so (to avoid marking the space) - if(stream.eatSpace()){ - return null; - } - // Match URL - stream.match(/^[^\s]+/, true); - // Check for link title - if (stream.peek() === undefined) { // End of line, set flag to check next line - state.linkTitle = true; - } else { // More content on line, check if link title - stream.match(/^(?:\s+(?:"(?:[^"\\]|\\\\|\\.)+"|'(?:[^'\\]|\\\\|\\.)+'|\((?:[^)\\]|\\\\|\\.)+\)))?/, true); - } - state.f = state.inline = inlineNormal; - return tokenTypes.linkHref + " url"; - } - - var mode = { - startState: function() { - return { - f: blockNormal, - - prevLine: null, - thisLine: null, - - block: blockNormal, - htmlState: null, - indentation: 0, - - inline: inlineNormal, - text: handleText, - - formatting: false, - linkText: false, - linkHref: false, - linkTitle: false, - code: 0, - em: false, - strong: false, - header: 0, - hr: false, - taskList: false, - list: false, - listStack: [], - quote: 0, - trailingSpace: 0, - trailingSpaceNewLine: false, - strikethrough: false, - fencedChars: null - }; - }, - - copyState: function(s) { - return { - f: s.f, - - prevLine: s.prevLine, - thisLine: s.thisLine, - - block: s.block, - htmlState: s.htmlState && CodeMirror.copyState(htmlMode, s.htmlState), - indentation: s.indentation, - - localMode: s.localMode, - localState: s.localMode ? CodeMirror.copyState(s.localMode, s.localState) : null, - - inline: s.inline, - text: s.text, - formatting: false, - linkTitle: s.linkTitle, - code: s.code, - em: s.em, - strong: s.strong, - strikethrough: s.strikethrough, - header: s.header, - hr: s.hr, - taskList: s.taskList, - list: s.list, - listStack: s.listStack.slice(0), - quote: s.quote, - indentedCode: s.indentedCode, - trailingSpace: s.trailingSpace, - trailingSpaceNewLine: s.trailingSpaceNewLine, - md_inside: s.md_inside, - fencedChars: s.fencedChars - }; - }, - - token: function(stream, state) { - - // Reset state.formatting - state.formatting = false; - - if (stream != state.thisLine) { - var forceBlankLine = state.header || state.hr; - - // Reset state.header and state.hr - state.header = 0; - state.hr = false; - - if (stream.match(/^\s*$/, true) || forceBlankLine) { - blankLine(state); - if (!forceBlankLine) return null - state.prevLine = null - } - - state.prevLine = state.thisLine - state.thisLine = stream - - // Reset state.taskList - state.taskList = false; - - // Reset state.trailingSpace - state.trailingSpace = 0; - state.trailingSpaceNewLine = false; - - state.f = state.block; - var indentation = stream.match(/^\s*/, true)[0].replace(/\t/g, ' ').length; - state.indentationDiff = Math.min(indentation - state.indentation, 4); - state.indentation = state.indentation + state.indentationDiff; - if (indentation > 0) return null; - } - return state.f(stream, state); - }, - - innerMode: function(state) { - if (state.block == htmlBlock) return {state: state.htmlState, mode: htmlMode}; - if (state.localState) return {state: state.localState, mode: state.localMode}; - return {state: state, mode: mode}; - }, - - blankLine: blankLine, - - getType: getType, - - closeBrackets: "()[]{}''\"\"``", - fold: "markdown" - }; - return mode; -}, "xml"); - -CodeMirror.defineMIME("text/x-markdown", "markdown"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/markdown/test.js b/backend/_pv_1_3_5/static/codemirror/mode/markdown/test.js deleted file mode 100755 index 37ecb4bbf..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/markdown/test.js +++ /dev/null @@ -1,989 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({tabSize: 4}, "markdown"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - var modeHighlightFormatting = CodeMirror.getMode({tabSize: 4}, {name: "markdown", highlightFormatting: true}); - function FT(name) { test.mode(name, modeHighlightFormatting, Array.prototype.slice.call(arguments, 1)); } - var modeAtxNoSpace = CodeMirror.getMode({tabSize: 4}, {name: "markdown", allowAtxHeaderWithoutSpace: true}); - function AtxNoSpaceTest(name) { test.mode(name, modeAtxNoSpace, Array.prototype.slice.call(arguments, 1)); } - var modeFenced = CodeMirror.getMode({tabSize: 4}, {name: "markdown", fencedCodeBlocks: true}); - function FencedTest(name) { test.mode(name, modeFenced, Array.prototype.slice.call(arguments, 1)); } - var modeOverrideClasses = CodeMirror.getMode({tabsize: 4}, { - name: "markdown", - strikethrough: true, - tokenTypeOverrides: { - "header" : "override-header", - "code" : "override-code", - "quote" : "override-quote", - "list1" : "override-list1", - "list2" : "override-list2", - "list3" : "override-list3", - "hr" : "override-hr", - "image" : "override-image", - "imageAltText": "override-image-alt-text", - "imageMarker": "override-image-marker", - "linkInline" : "override-link-inline", - "linkEmail" : "override-link-email", - "linkText" : "override-link-text", - "linkHref" : "override-link-href", - "em" : "override-em", - "strong" : "override-strong", - "strikethrough" : "override-strikethrough" - }}); - function TokenTypeOverrideTest(name) { test.mode(name, modeOverrideClasses, Array.prototype.slice.call(arguments, 1)); } - var modeFormattingOverride = CodeMirror.getMode({tabsize: 4}, { - name: "markdown", - highlightFormatting: true, - tokenTypeOverrides: { - "formatting" : "override-formatting" - }}); - function FormatTokenTypeOverrideTest(name) { test.mode(name, modeFormattingOverride, Array.prototype.slice.call(arguments, 1)); } - - - FT("formatting_emAsterisk", - "[em&formatting&formatting-em *][em foo][em&formatting&formatting-em *]"); - - FT("formatting_emUnderscore", - "[em&formatting&formatting-em _][em foo][em&formatting&formatting-em _]"); - - FT("formatting_strongAsterisk", - "[strong&formatting&formatting-strong **][strong foo][strong&formatting&formatting-strong **]"); - - FT("formatting_strongUnderscore", - "[strong&formatting&formatting-strong __][strong foo][strong&formatting&formatting-strong __]"); - - FT("formatting_codeBackticks", - "[comment&formatting&formatting-code `][comment foo][comment&formatting&formatting-code `]"); - - FT("formatting_doubleBackticks", - "[comment&formatting&formatting-code ``][comment foo ` bar][comment&formatting&formatting-code ``]"); - - FT("formatting_atxHeader", - "[header&header-1&formatting&formatting-header&formatting-header-1 # ][header&header-1 foo # bar ][header&header-1&formatting&formatting-header&formatting-header-1 #]"); - - FT("formatting_setextHeader", - "foo", - "[header&header-1&formatting&formatting-header&formatting-header-1 =]"); - - FT("formatting_blockquote", - "[quote"e-1&formatting&formatting-quote&formatting-quote-1 > ][quote"e-1 foo]"); - - FT("formatting_list", - "[variable-2&formatting&formatting-list&formatting-list-ul - ][variable-2 foo]"); - FT("formatting_list", - "[variable-2&formatting&formatting-list&formatting-list-ol 1. ][variable-2 foo]"); - - FT("formatting_link", - "[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string&url (][string&url http://example.com/][string&formatting&formatting-link-string&url )]"); - - FT("formatting_linkReference", - "[link&formatting&formatting-link [][link foo][link&formatting&formatting-link ]]][string&formatting&formatting-link-string&url [][string&url bar][string&formatting&formatting-link-string&url ]]]", - "[link&formatting&formatting-link [][link bar][link&formatting&formatting-link ]]:] [string&url http://example.com/]"); - - FT("formatting_linkWeb", - "[link&formatting&formatting-link <][link http://example.com/][link&formatting&formatting-link >]"); - - FT("formatting_linkEmail", - "[link&formatting&formatting-link <][link user@example.com][link&formatting&formatting-link >]"); - - FT("formatting_escape", - "[formatting-escape \\*]"); - - FT("formatting_image", - "[formatting&formatting-image&image&image-marker !][formatting&formatting-image&image&image-alt-text&link [[][image&image-alt-text&link alt text][formatting&formatting-image&image&image-alt-text&link ]]][formatting&formatting-link-string&string&url (][url&string http://link.to/image.jpg][formatting&formatting-link-string&string&url )]"); - - MT("plainText", - "foo"); - - // Don't style single trailing space - MT("trailingSpace1", - "foo "); - - // Two or more trailing spaces should be styled with line break character - MT("trailingSpace2", - "foo[trailing-space-a ][trailing-space-new-line ]"); - - MT("trailingSpace3", - "foo[trailing-space-a ][trailing-space-b ][trailing-space-new-line ]"); - - MT("trailingSpace4", - "foo[trailing-space-a ][trailing-space-b ][trailing-space-a ][trailing-space-new-line ]"); - - // Code blocks using 4 spaces (regardless of CodeMirror.tabSize value) - MT("codeBlocksUsing4Spaces", - " [comment foo]"); - - // Code blocks using 4 spaces with internal indentation - MT("codeBlocksUsing4SpacesIndentation", - " [comment bar]", - " [comment hello]", - " [comment world]", - " [comment foo]", - "bar"); - - // Code blocks should end even after extra indented lines - MT("codeBlocksWithTrailingIndentedLine", - " [comment foo]", - " [comment bar]", - " [comment baz]", - " ", - "hello"); - - // Code blocks using 1 tab (regardless of CodeMirror.indentWithTabs value) - MT("codeBlocksUsing1Tab", - "\t[comment foo]"); - - // No code blocks directly after paragraph - // http://spec.commonmark.org/0.19/#example-65 - MT("noCodeBlocksAfterParagraph", - "Foo", - " Bar"); - - // Inline code using backticks - MT("inlineCodeUsingBackticks", - "foo [comment `bar`]"); - - // Block code using single backtick (shouldn't work) - MT("blockCodeSingleBacktick", - "[comment `]", - "[comment foo]", - "[comment `]"); - - // Unclosed backticks - // Instead of simply marking as CODE, it would be nice to have an - // incomplete flag for CODE, that is styled slightly different. - MT("unclosedBackticks", - "foo [comment `bar]"); - - // Per documentation: "To include a literal backtick character within a - // code span, you can use multiple backticks as the opening and closing - // delimiters" - MT("doubleBackticks", - "[comment ``foo ` bar``]"); - - // Tests based on Dingus - // http://daringfireball.net/projects/markdown/dingus - // - // Multiple backticks within an inline code block - MT("consecutiveBackticks", - "[comment `foo```bar`]"); - - // Multiple backticks within an inline code block with a second code block - MT("consecutiveBackticks", - "[comment `foo```bar`] hello [comment `world`]"); - - // Unclosed with several different groups of backticks - MT("unclosedBackticks", - "[comment ``foo ``` bar` hello]"); - - // Closed with several different groups of backticks - MT("closedBackticks", - "[comment ``foo ``` bar` hello``] world"); - - // atx headers - // http://daringfireball.net/projects/markdown/syntax#header - - MT("atxH1", - "[header&header-1 # foo]"); - - MT("atxH2", - "[header&header-2 ## foo]"); - - MT("atxH3", - "[header&header-3 ### foo]"); - - MT("atxH4", - "[header&header-4 #### foo]"); - - MT("atxH5", - "[header&header-5 ##### foo]"); - - MT("atxH6", - "[header&header-6 ###### foo]"); - - // http://spec.commonmark.org/0.19/#example-24 - MT("noAtxH7", - "####### foo"); - - // http://spec.commonmark.org/0.19/#example-25 - MT("noAtxH1WithoutSpace", - "#5 bolt"); - - // CommonMark requires a space after # but most parsers don't - AtxNoSpaceTest("atxNoSpaceAllowed_H1NoSpace", - "[header&header-1 #foo]"); - - AtxNoSpaceTest("atxNoSpaceAllowed_H4NoSpace", - "[header&header-4 ####foo]"); - - AtxNoSpaceTest("atxNoSpaceAllowed_H1Space", - "[header&header-1 # foo]"); - - // Inline styles should be parsed inside headers - MT("atxH1inline", - "[header&header-1 # foo ][header&header-1&em *bar*]"); - - // Setext headers - H1, H2 - // Per documentation, "Any number of underlining =’s or -’s will work." - // http://daringfireball.net/projects/markdown/syntax#header - // Ideally, the text would be marked as `header` as well, but this is - // not really feasible at the moment. So, instead, we're testing against - // what works today, to avoid any regressions. - // - // Check if single underlining = works - MT("setextH1", - "foo", - "[header&header-1 =]"); - - // Check if 3+ ='s work - MT("setextH1", - "foo", - "[header&header-1 ===]"); - - // Check if single underlining - works - MT("setextH2", - "foo", - "[header&header-2 -]"); - - // Check if 3+ -'s work - MT("setextH2", - "foo", - "[header&header-2 ---]"); - - // http://spec.commonmark.org/0.19/#example-45 - MT("setextH2AllowSpaces", - "foo", - " [header&header-2 ---- ]"); - - // http://spec.commonmark.org/0.19/#example-44 - MT("noSetextAfterIndentedCodeBlock", - " [comment foo]", - "[hr ---]"); - - // http://spec.commonmark.org/0.19/#example-51 - MT("noSetextAfterQuote", - "[quote"e-1 > foo]", - "[hr ---]"); - - MT("noSetextAfterList", - "[variable-2 - foo]", - "[hr ---]"); - - // Single-line blockquote with trailing space - MT("blockquoteSpace", - "[quote"e-1 > foo]"); - - // Single-line blockquote - MT("blockquoteNoSpace", - "[quote"e-1 >foo]"); - - // No blank line before blockquote - MT("blockquoteNoBlankLine", - "foo", - "[quote"e-1 > bar]"); - - // Nested blockquote - MT("blockquoteSpace", - "[quote"e-1 > foo]", - "[quote"e-1 >][quote"e-2 > foo]", - "[quote"e-1 >][quote"e-2 >][quote"e-3 > foo]"); - - // Single-line blockquote followed by normal paragraph - MT("blockquoteThenParagraph", - "[quote"e-1 >foo]", - "", - "bar"); - - // Multi-line blockquote (lazy mode) - MT("multiBlockquoteLazy", - "[quote"e-1 >foo]", - "[quote"e-1 bar]"); - - // Multi-line blockquote followed by normal paragraph (lazy mode) - MT("multiBlockquoteLazyThenParagraph", - "[quote"e-1 >foo]", - "[quote"e-1 bar]", - "", - "hello"); - - // Multi-line blockquote (non-lazy mode) - MT("multiBlockquote", - "[quote"e-1 >foo]", - "[quote"e-1 >bar]"); - - // Multi-line blockquote followed by normal paragraph (non-lazy mode) - MT("multiBlockquoteThenParagraph", - "[quote"e-1 >foo]", - "[quote"e-1 >bar]", - "", - "hello"); - - // Header with leading space after continued blockquote (#3287, negative indentation) - MT("headerAfterContinuedBlockquote", - "[quote"e-1 > foo]", - "[quote"e-1 bar]", - "", - " [header&header-1 # hello]"); - - // Check list types - - MT("listAsterisk", - "foo", - "bar", - "", - "[variable-2 * foo]", - "[variable-2 * bar]"); - - MT("listPlus", - "foo", - "bar", - "", - "[variable-2 + foo]", - "[variable-2 + bar]"); - - MT("listDash", - "foo", - "bar", - "", - "[variable-2 - foo]", - "[variable-2 - bar]"); - - MT("listNumber", - "foo", - "bar", - "", - "[variable-2 1. foo]", - "[variable-2 2. bar]"); - - MT("listFromParagraph", - "foo", - "[variable-2 1. bar]", - "[variable-2 2. hello]"); - - // List after hr - MT("listAfterHr", - "[hr ---]", - "[variable-2 - bar]"); - - // List after header - MT("listAfterHeader", - "[header&header-1 # foo]", - "[variable-2 - bar]"); - - // hr after list - MT("hrAfterList", - "[variable-2 - foo]", - "[hr -----]"); - - // Formatting in lists (*) - MT("listAsteriskFormatting", - "[variable-2 * ][variable-2&em *foo*][variable-2 bar]", - "[variable-2 * ][variable-2&strong **foo**][variable-2 bar]", - "[variable-2 * ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]", - "[variable-2 * ][variable-2&comment `foo`][variable-2 bar]"); - - // Formatting in lists (+) - MT("listPlusFormatting", - "[variable-2 + ][variable-2&em *foo*][variable-2 bar]", - "[variable-2 + ][variable-2&strong **foo**][variable-2 bar]", - "[variable-2 + ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]", - "[variable-2 + ][variable-2&comment `foo`][variable-2 bar]"); - - // Formatting in lists (-) - MT("listDashFormatting", - "[variable-2 - ][variable-2&em *foo*][variable-2 bar]", - "[variable-2 - ][variable-2&strong **foo**][variable-2 bar]", - "[variable-2 - ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]", - "[variable-2 - ][variable-2&comment `foo`][variable-2 bar]"); - - // Formatting in lists (1.) - MT("listNumberFormatting", - "[variable-2 1. ][variable-2&em *foo*][variable-2 bar]", - "[variable-2 2. ][variable-2&strong **foo**][variable-2 bar]", - "[variable-2 3. ][variable-2&strong **][variable-2&em&strong *foo**][variable-2&em *][variable-2 bar]", - "[variable-2 4. ][variable-2&comment `foo`][variable-2 bar]"); - - // Paragraph lists - MT("listParagraph", - "[variable-2 * foo]", - "", - "[variable-2 * bar]"); - - // Multi-paragraph lists - // - // 4 spaces - MT("listMultiParagraph", - "[variable-2 * foo]", - "", - "[variable-2 * bar]", - "", - " [variable-2 hello]"); - - // 4 spaces, extra blank lines (should still be list, per Dingus) - MT("listMultiParagraphExtra", - "[variable-2 * foo]", - "", - "[variable-2 * bar]", - "", - "", - " [variable-2 hello]"); - - // 4 spaces, plus 1 space (should still be list, per Dingus) - MT("listMultiParagraphExtraSpace", - "[variable-2 * foo]", - "", - "[variable-2 * bar]", - "", - " [variable-2 hello]", - "", - " [variable-2 world]"); - - // 1 tab - MT("listTab", - "[variable-2 * foo]", - "", - "[variable-2 * bar]", - "", - "\t[variable-2 hello]"); - - // No indent - MT("listNoIndent", - "[variable-2 * foo]", - "", - "[variable-2 * bar]", - "", - "hello"); - - MT("listCommonMarkIndentationCode", - "[variable-2 * Code blocks also affect]", - " [variable-3 * The next level starts where the contents start.]", - " [variable-3 * Anything less than that will keep the item on the same level.]", - " [variable-3 * Each list item can indent the first level further and further.]", - " [variable-3 * For the most part, this makes sense while writing a list.]", - " [keyword * This means two items with same indentation can be different levels.]", - " [keyword * Each level has an indent requirement that can change between items.]", - " [keyword * A list item that meets this will be part of the next level.]", - " [variable-3 * Otherwise, it will be part of the level where it does meet this.]", - " [variable-2 * World]"); - - // Blockquote - MT("blockquote", - "[variable-2 * foo]", - "", - "[variable-2 * bar]", - "", - " [variable-2"e"e-1 > hello]"); - - // Code block - MT("blockquoteCode", - "[variable-2 * foo]", - "", - "[variable-2 * bar]", - "", - " [comment > hello]", - "", - " [variable-2 world]"); - - // Code block followed by text - MT("blockquoteCodeText", - "[variable-2 * foo]", - "", - " [variable-2 bar]", - "", - " [comment hello]", - "", - " [variable-2 world]"); - - // Nested list - - MT("listAsteriskNested", - "[variable-2 * foo]", - "", - " [variable-3 * bar]"); - - MT("listPlusNested", - "[variable-2 + foo]", - "", - " [variable-3 + bar]"); - - MT("listDashNested", - "[variable-2 - foo]", - "", - " [variable-3 - bar]"); - - MT("listNumberNested", - "[variable-2 1. foo]", - "", - " [variable-3 2. bar]"); - - MT("listMixed", - "[variable-2 * foo]", - "", - " [variable-3 + bar]", - "", - " [keyword - hello]", - "", - " [variable-2 1. world]"); - - MT("listBlockquote", - "[variable-2 * foo]", - "", - " [variable-3 + bar]", - "", - " [quote"e-1&variable-3 > hello]"); - - MT("listCode", - "[variable-2 * foo]", - "", - " [variable-3 + bar]", - "", - " [comment hello]"); - - // Code with internal indentation - MT("listCodeIndentation", - "[variable-2 * foo]", - "", - " [comment bar]", - " [comment hello]", - " [comment world]", - " [comment foo]", - " [variable-2 bar]"); - - // List nesting edge cases - MT("listNested", - "[variable-2 * foo]", - "", - " [variable-3 * bar]", - "", - " [variable-3 hello]" - ); - MT("listNested", - "[variable-2 * foo]", - "", - " [variable-3 * bar]", - "", - " [keyword * foo]" - ); - - // Code followed by text - MT("listCodeText", - "[variable-2 * foo]", - "", - " [comment bar]", - "", - "hello"); - - // Following tests directly from official Markdown documentation - // http://daringfireball.net/projects/markdown/syntax#hr - - MT("hrSpace", - "[hr * * *]"); - - MT("hr", - "[hr ***]"); - - MT("hrLong", - "[hr *****]"); - - MT("hrSpaceDash", - "[hr - - -]"); - - MT("hrDashLong", - "[hr ---------------------------------------]"); - - //Images - MT("Images", - "[image&image-marker !][image&image-alt-text&link [[alt text]]][string&url (http://link.to/image.jpg)]") - - //Images with highlight alt text - MT("imageEm", - "[image&image-marker !][image&image-alt-text&link [[][image-alt-text&em&image&link *alt text*][image&image-alt-text&link ]]][string&url (http://link.to/image.jpg)]"); - - MT("imageStrong", - "[image&image-marker !][image&image-alt-text&link [[][image-alt-text&strong&image&link **alt text**][image&image-alt-text&link ]]][string&url (http://link.to/image.jpg)]"); - - MT("imageEmStrong", - "[image&image-marker !][image&image-alt-text&link [[][image-alt-text&image&strong&link **][image&image-alt-text&em&strong&link *alt text**][image&image-alt-text&em&link *][image&image-alt-text&link ]]][string&url (http://link.to/image.jpg)]"); - - // Inline link with title - MT("linkTitle", - "[link [[foo]]][string&url (http://example.com/ \"bar\")] hello"); - - // Inline link without title - MT("linkNoTitle", - "[link [[foo]]][string&url (http://example.com/)] bar"); - - // Inline link with image - MT("linkImage", - "[link [[][link&image&image-marker !][link&image&image-alt-text&link [[alt text]]][string&url (http://link.to/image.jpg)][link ]]][string&url (http://example.com/)] bar"); - - // Inline link with Em - MT("linkEm", - "[link [[][link&em *foo*][link ]]][string&url (http://example.com/)] bar"); - - // Inline link with Strong - MT("linkStrong", - "[link [[][link&strong **foo**][link ]]][string&url (http://example.com/)] bar"); - - // Inline link with EmStrong - MT("linkEmStrong", - "[link [[][link&strong **][link&em&strong *foo**][link&em *][link ]]][string&url (http://example.com/)] bar"); - - // Image with title - MT("imageTitle", - "[image&image-marker !][image&image-alt-text&link [[alt text]]][string&url (http://example.com/ \"bar\")] hello"); - - // Image without title - MT("imageNoTitle", - "[image&image-marker !][image&image-alt-text&link [[alt text]]][string&url (http://example.com/)] bar"); - - // Image with asterisks - MT("imageAsterisks", - "[image&image-marker !][image&image-alt-text&link [[ ][image&image-alt-text&em&link *alt text*][image&image-alt-text&link ]]][string&url (http://link.to/image.jpg)] bar"); - - // Not a link. Should be normal text due to square brackets being used - // regularly in text, especially in quoted material, and no space is allowed - // between square brackets and parentheses (per Dingus). - MT("notALink", - "[[foo]] (bar)"); - - // Reference-style links - MT("linkReference", - "[link [[foo]]][string&url [[bar]]] hello"); - - // Reference-style links with Em - MT("linkReferenceEm", - "[link [[][link&em *foo*][link ]]][string&url [[bar]]] hello"); - - // Reference-style links with Strong - MT("linkReferenceStrong", - "[link [[][link&strong **foo**][link ]]][string&url [[bar]]] hello"); - - // Reference-style links with EmStrong - MT("linkReferenceEmStrong", - "[link [[][link&strong **][link&em&strong *foo**][link&em *][link ]]][string&url [[bar]]] hello"); - - // Reference-style links with optional space separator (per documentation) - // "You can optionally use a space to separate the sets of brackets" - MT("linkReferenceSpace", - "[link [[foo]]] [string&url [[bar]]] hello"); - - // Should only allow a single space ("...use *a* space...") - MT("linkReferenceDoubleSpace", - "[[foo]] [[bar]] hello"); - - // Reference-style links with implicit link name - MT("linkImplicit", - "[link [[foo]]][string&url [[]]] hello"); - - // @todo It would be nice if, at some point, the document was actually - // checked to see if the referenced link exists - - // Link label, for reference-style links (taken from documentation) - - MT("labelNoTitle", - "[link [[foo]]:] [string&url http://example.com/]"); - - MT("labelIndented", - " [link [[foo]]:] [string&url http://example.com/]"); - - MT("labelSpaceTitle", - "[link [[foo bar]]:] [string&url http://example.com/ \"hello\"]"); - - MT("labelDoubleTitle", - "[link [[foo bar]]:] [string&url http://example.com/ \"hello\"] \"world\""); - - MT("labelTitleDoubleQuotes", - "[link [[foo]]:] [string&url http://example.com/ \"bar\"]"); - - MT("labelTitleSingleQuotes", - "[link [[foo]]:] [string&url http://example.com/ 'bar']"); - - MT("labelTitleParentheses", - "[link [[foo]]:] [string&url http://example.com/ (bar)]"); - - MT("labelTitleInvalid", - "[link [[foo]]:] [string&url http://example.com/] bar"); - - MT("labelLinkAngleBrackets", - "[link [[foo]]:] [string&url \"bar\"]"); - - MT("labelTitleNextDoubleQuotes", - "[link [[foo]]:] [string&url http://example.com/]", - "[string \"bar\"] hello"); - - MT("labelTitleNextSingleQuotes", - "[link [[foo]]:] [string&url http://example.com/]", - "[string 'bar'] hello"); - - MT("labelTitleNextParentheses", - "[link [[foo]]:] [string&url http://example.com/]", - "[string (bar)] hello"); - - MT("labelTitleNextMixed", - "[link [[foo]]:] [string&url http://example.com/]", - "(bar\" hello"); - - MT("labelEscape", - "[link [[foo \\]] ]]:] [string&url http://example.com/]"); - - MT("labelEscapeColon", - "[link [[foo \\]]: bar]]:] [string&url http://example.com/]"); - - MT("labelEscapeEnd", - "[[foo\\]]: http://example.com/"); - - MT("linkWeb", - "[link ] foo"); - - MT("linkWebDouble", - "[link ] foo [link ]"); - - MT("linkEmail", - "[link ] foo"); - - MT("linkEmailDouble", - "[link ] foo [link ]"); - - MT("emAsterisk", - "[em *foo*] bar"); - - MT("emUnderscore", - "[em _foo_] bar"); - - MT("emInWordAsterisk", - "foo[em *bar*]hello"); - - MT("emInWordUnderscore", - "foo[em _bar_]hello"); - - // Per documentation: "...surround an * or _ with spaces, it’ll be - // treated as a literal asterisk or underscore." - - MT("emEscapedBySpaceIn", - "foo [em _bar _ hello_] world"); - - MT("emEscapedBySpaceOut", - "foo _ bar[em _hello_]world"); - - MT("emEscapedByNewline", - "foo", - "_ bar[em _hello_]world"); - - // Unclosed emphasis characters - // Instead of simply marking as EM / STRONG, it would be nice to have an - // incomplete flag for EM and STRONG, that is styled slightly different. - MT("emIncompleteAsterisk", - "foo [em *bar]"); - - MT("emIncompleteUnderscore", - "foo [em _bar]"); - - MT("strongAsterisk", - "[strong **foo**] bar"); - - MT("strongUnderscore", - "[strong __foo__] bar"); - - MT("emStrongAsterisk", - "[em *foo][em&strong **bar*][strong hello**] world"); - - MT("emStrongUnderscore", - "[em _foo][em&strong __bar_][strong hello__] world"); - - // "...same character must be used to open and close an emphasis span."" - MT("emStrongMixed", - "[em _foo][em&strong **bar*hello__ world]"); - - MT("emStrongMixed", - "[em *foo][em&strong __bar_hello** world]"); - - MT("linkWithNestedParens", - "[link [[foo]]][string&url (bar(baz))]") - - // These characters should be escaped: - // \ backslash - // ` backtick - // * asterisk - // _ underscore - // {} curly braces - // [] square brackets - // () parentheses - // # hash mark - // + plus sign - // - minus sign (hyphen) - // . dot - // ! exclamation mark - - MT("escapeBacktick", - "foo \\`bar\\`"); - - MT("doubleEscapeBacktick", - "foo \\\\[comment `bar\\\\`]"); - - MT("escapeAsterisk", - "foo \\*bar\\*"); - - MT("doubleEscapeAsterisk", - "foo \\\\[em *bar\\\\*]"); - - MT("escapeUnderscore", - "foo \\_bar\\_"); - - MT("doubleEscapeUnderscore", - "foo \\\\[em _bar\\\\_]"); - - MT("escapeHash", - "\\# foo"); - - MT("doubleEscapeHash", - "\\\\# foo"); - - MT("escapeNewline", - "\\", - "[em *foo*]"); - - // Class override tests - TokenTypeOverrideTest("overrideHeader1", - "[override-header&override-header-1 # Foo]"); - - TokenTypeOverrideTest("overrideHeader2", - "[override-header&override-header-2 ## Foo]"); - - TokenTypeOverrideTest("overrideHeader3", - "[override-header&override-header-3 ### Foo]"); - - TokenTypeOverrideTest("overrideHeader4", - "[override-header&override-header-4 #### Foo]"); - - TokenTypeOverrideTest("overrideHeader5", - "[override-header&override-header-5 ##### Foo]"); - - TokenTypeOverrideTest("overrideHeader6", - "[override-header&override-header-6 ###### Foo]"); - - TokenTypeOverrideTest("overrideCode", - "[override-code `foo`]"); - - TokenTypeOverrideTest("overrideCodeBlock", - "[override-code ```]", - "[override-code foo]", - "[override-code ```]"); - - TokenTypeOverrideTest("overrideQuote", - "[override-quote&override-quote-1 > foo]", - "[override-quote&override-quote-1 > bar]"); - - TokenTypeOverrideTest("overrideQuoteNested", - "[override-quote&override-quote-1 > foo]", - "[override-quote&override-quote-1 >][override-quote&override-quote-2 > bar]", - "[override-quote&override-quote-1 >][override-quote&override-quote-2 >][override-quote&override-quote-3 > baz]"); - - TokenTypeOverrideTest("overrideLists", - "[override-list1 - foo]", - "", - " [override-list2 + bar]", - "", - " [override-list3 * baz]", - "", - " [override-list1 1. qux]", - "", - " [override-list2 - quux]"); - - TokenTypeOverrideTest("overrideHr", - "[override-hr * * *]"); - - TokenTypeOverrideTest("overrideImage", - "[override-image&override-image-marker !][override-image&override-image-alt-text&link [[alt text]]][override-link-href&url (http://link.to/image.jpg)]"); - - TokenTypeOverrideTest("overrideLinkText", - "[override-link-text [[foo]]][override-link-href&url (http://example.com)]"); - - TokenTypeOverrideTest("overrideLinkEmailAndInline", - "[override-link-email <][override-link-inline foo@example.com>]"); - - TokenTypeOverrideTest("overrideEm", - "[override-em *foo*]"); - - TokenTypeOverrideTest("overrideStrong", - "[override-strong **foo**]"); - - TokenTypeOverrideTest("overrideStrikethrough", - "[override-strikethrough ~~foo~~]"); - - FormatTokenTypeOverrideTest("overrideFormatting", - "[override-formatting-escape \\*]"); - - // Tests to make sure GFM-specific things aren't getting through - - MT("taskList", - "[variable-2 * [ ]] bar]"); - - MT("noFencedCodeBlocks", - "~~~", - "foo", - "~~~"); - - FencedTest("fencedCodeBlocks", - "[comment ```]", - "[comment foo]", - "[comment ```]", - "bar"); - - FencedTest("fencedCodeBlocksMultipleChars", - "[comment `````]", - "[comment foo]", - "[comment ```]", - "[comment foo]", - "[comment `````]", - "bar"); - - FencedTest("fencedCodeBlocksTildes", - "[comment ~~~]", - "[comment foo]", - "[comment ~~~]", - "bar"); - - FencedTest("fencedCodeBlocksTildesMultipleChars", - "[comment ~~~~~]", - "[comment ~~~]", - "[comment foo]", - "[comment ~~~~~]", - "bar"); - - FencedTest("fencedCodeBlocksMultipleChars", - "[comment `````]", - "[comment foo]", - "[comment ```]", - "[comment foo]", - "[comment `````]", - "bar"); - - FencedTest("fencedCodeBlocksMixed", - "[comment ~~~]", - "[comment ```]", - "[comment foo]", - "[comment ~~~]", - "bar"); - - // Tests that require XML mode - - MT("xmlMode", - "[tag&bracket <][tag div][tag&bracket >]", - "*foo*", - "[tag&bracket <][tag http://github.com][tag&bracket />]", - "[tag&bracket ]", - "[link ]"); - - MT("xmlModeWithMarkdownInside", - "[tag&bracket <][tag div] [attribute markdown]=[string 1][tag&bracket >]", - "[em *foo*]", - "[link ]", - "[tag
  • ]", - "[link ]", - "[tag&bracket <][tag div][tag&bracket >]", - "[tag&bracket ]"); - -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/mathematica/index.html b/backend/_pv_1_3_5/static/codemirror/mode/mathematica/index.html deleted file mode 100755 index 57c429853..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/mathematica/index.html +++ /dev/null @@ -1,72 +0,0 @@ - - -CodeMirror: Mathematica mode - - - - - - - - - - -
    -

    Mathematica mode

    - - - - - - -

    MIME types defined: text/x-mathematica (Mathematica).

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/mathematica/mathematica.js b/backend/_pv_1_3_5/static/codemirror/mode/mathematica/mathematica.js deleted file mode 100755 index d6977088c..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/mathematica/mathematica.js +++ /dev/null @@ -1,176 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Mathematica mode copyright (c) 2015 by Calin Barbat -// Based on code by Patrick Scheibe (halirutan) -// See: https://github.com/halirutan/Mathematica-Source-Highlighting/tree/master/src/lang-mma.js - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode('mathematica', function(_config, _parserConfig) { - - // used pattern building blocks - var Identifier = '[a-zA-Z\\$][a-zA-Z0-9\\$]*'; - var pBase = "(?:\\d+)"; - var pFloat = "(?:\\.\\d+|\\d+\\.\\d*|\\d+)"; - var pFloatBase = "(?:\\.\\w+|\\w+\\.\\w*|\\w+)"; - var pPrecision = "(?:`(?:`?"+pFloat+")?)"; - - // regular expressions - var reBaseForm = new RegExp('(?:'+pBase+'(?:\\^\\^'+pFloatBase+pPrecision+'?(?:\\*\\^[+-]?\\d+)?))'); - var reFloatForm = new RegExp('(?:' + pFloat + pPrecision + '?(?:\\*\\^[+-]?\\d+)?)'); - var reIdInContext = new RegExp('(?:`?)(?:' + Identifier + ')(?:`(?:' + Identifier + '))*(?:`?)'); - - function tokenBase(stream, state) { - var ch; - - // get next character - ch = stream.next(); - - // string - if (ch === '"') { - state.tokenize = tokenString; - return state.tokenize(stream, state); - } - - // comment - if (ch === '(') { - if (stream.eat('*')) { - state.commentLevel++; - state.tokenize = tokenComment; - return state.tokenize(stream, state); - } - } - - // go back one character - stream.backUp(1); - - // look for numbers - // Numbers in a baseform - if (stream.match(reBaseForm, true, false)) { - return 'number'; - } - - // Mathematica numbers. Floats (1.2, .2, 1.) can have optionally a precision (`float) or an accuracy definition - // (``float). Note: while 1.2` is possible 1.2`` is not. At the end an exponent (float*^+12) can follow. - if (stream.match(reFloatForm, true, false)) { - return 'number'; - } - - /* In[23] and Out[34] */ - if (stream.match(/(?:In|Out)\[[0-9]*\]/, true, false)) { - return 'atom'; - } - - // usage - if (stream.match(/([a-zA-Z\$]+(?:`?[a-zA-Z0-9\$])*::usage)/, true, false)) { - return 'meta'; - } - - // message - if (stream.match(/([a-zA-Z\$]+(?:`?[a-zA-Z0-9\$])*::[a-zA-Z\$][a-zA-Z0-9\$]*):?/, true, false)) { - return 'string-2'; - } - - // this makes a look-ahead match for something like variable:{_Integer} - // the match is then forwarded to the mma-patterns tokenizer. - if (stream.match(/([a-zA-Z\$][a-zA-Z0-9\$]*\s*:)(?:(?:[a-zA-Z\$][a-zA-Z0-9\$]*)|(?:[^:=>~@\^\&\*\)\[\]'\?,\|])).*/, true, false)) { - return 'variable-2'; - } - - // catch variables which are used together with Blank (_), BlankSequence (__) or BlankNullSequence (___) - // Cannot start with a number, but can have numbers at any other position. Examples - // blub__Integer, a1_, b34_Integer32 - if (stream.match(/[a-zA-Z\$][a-zA-Z0-9\$]*_+[a-zA-Z\$][a-zA-Z0-9\$]*/, true, false)) { - return 'variable-2'; - } - if (stream.match(/[a-zA-Z\$][a-zA-Z0-9\$]*_+/, true, false)) { - return 'variable-2'; - } - if (stream.match(/_+[a-zA-Z\$][a-zA-Z0-9\$]*/, true, false)) { - return 'variable-2'; - } - - // Named characters in Mathematica, like \[Gamma]. - if (stream.match(/\\\[[a-zA-Z\$][a-zA-Z0-9\$]*\]/, true, false)) { - return 'variable-3'; - } - - // Match all braces separately - if (stream.match(/(?:\[|\]|{|}|\(|\))/, true, false)) { - return 'bracket'; - } - - // Catch Slots (#, ##, #3, ##9 and the V10 named slots #name). I have never seen someone using more than one digit after #, so we match - // only one. - if (stream.match(/(?:#[a-zA-Z\$][a-zA-Z0-9\$]*|#+[0-9]?)/, true, false)) { - return 'variable-2'; - } - - // Literals like variables, keywords, functions - if (stream.match(reIdInContext, true, false)) { - return 'keyword'; - } - - // operators. Note that operators like @@ or /; are matched separately for each symbol. - if (stream.match(/(?:\\|\+|\-|\*|\/|,|;|\.|:|@|~|=|>|<|&|\||_|`|'|\^|\?|!|%)/, true, false)) { - return 'operator'; - } - - // everything else is an error - stream.next(); // advance the stream. - return 'error'; - } - - function tokenString(stream, state) { - var next, end = false, escaped = false; - while ((next = stream.next()) != null) { - if (next === '"' && !escaped) { - end = true; - break; - } - escaped = !escaped && next === '\\'; - } - if (end && !escaped) { - state.tokenize = tokenBase; - } - return 'string'; - }; - - function tokenComment(stream, state) { - var prev, next; - while(state.commentLevel > 0 && (next = stream.next()) != null) { - if (prev === '(' && next === '*') state.commentLevel++; - if (prev === '*' && next === ')') state.commentLevel--; - prev = next; - } - if (state.commentLevel <= 0) { - state.tokenize = tokenBase; - } - return 'comment'; - } - - return { - startState: function() {return {tokenize: tokenBase, commentLevel: 0};}, - token: function(stream, state) { - if (stream.eatSpace()) return null; - return state.tokenize(stream, state); - }, - blockCommentStart: "(*", - blockCommentEnd: "*)" - }; -}); - -CodeMirror.defineMIME('text/x-mathematica', { - name: 'mathematica' -}); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/mbox/index.html b/backend/_pv_1_3_5/static/codemirror/mode/mbox/index.html deleted file mode 100755 index 248ea98e1..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/mbox/index.html +++ /dev/null @@ -1,44 +0,0 @@ - - -CodeMirror: mbox mode - - - - - - - - - -
    -

    mbox mode

    -
    - - -

    MIME types defined: application/mbox.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/mbox/mbox.js b/backend/_pv_1_3_5/static/codemirror/mode/mbox/mbox.js deleted file mode 100755 index ba2416ac8..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/mbox/mbox.js +++ /dev/null @@ -1,129 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -var rfc2822 = [ - "From", "Sender", "Reply-To", "To", "Cc", "Bcc", "Message-ID", - "In-Reply-To", "References", "Resent-From", "Resent-Sender", "Resent-To", - "Resent-Cc", "Resent-Bcc", "Resent-Message-ID", "Return-Path", "Received" -]; -var rfc2822NoEmail = [ - "Date", "Subject", "Comments", "Keywords", "Resent-Date" -]; - -CodeMirror.registerHelper("hintWords", "mbox", rfc2822.concat(rfc2822NoEmail)); - -var whitespace = /^[ \t]/; -var separator = /^From /; // See RFC 4155 -var rfc2822Header = new RegExp("^(" + rfc2822.join("|") + "): "); -var rfc2822HeaderNoEmail = new RegExp("^(" + rfc2822NoEmail.join("|") + "): "); -var header = /^[^:]+:/; // Optional fields defined in RFC 2822 -var email = /^[^ ]+@[^ ]+/; -var untilEmail = /^.*?(?=[^ ]+?@[^ ]+)/; -var bracketedEmail = /^<.*?>/; -var untilBracketedEmail = /^.*?(?=<.*>)/; - -function styleForHeader(header) { - if (header === "Subject") return "header"; - return "string"; -} - -function readToken(stream, state) { - if (stream.sol()) { - // From last line - state.inSeparator = false; - if (state.inHeader && stream.match(whitespace)) { - // Header folding - return null; - } else { - state.inHeader = false; - state.header = null; - } - - if (stream.match(separator)) { - state.inHeaders = true; - state.inSeparator = true; - return "atom"; - } - - var match; - var emailPermitted = false; - if ((match = stream.match(rfc2822HeaderNoEmail)) || - (emailPermitted = true) && (match = stream.match(rfc2822Header))) { - state.inHeaders = true; - state.inHeader = true; - state.emailPermitted = emailPermitted; - state.header = match[1]; - return "atom"; - } - - // Use vim's heuristics: recognize custom headers only if the line is in a - // block of legitimate headers. - if (state.inHeaders && (match = stream.match(header))) { - state.inHeader = true; - state.emailPermitted = true; - state.header = match[1]; - return "atom"; - } - - state.inHeaders = false; - stream.skipToEnd(); - return null; - } - - if (state.inSeparator) { - if (stream.match(email)) return "link"; - if (stream.match(untilEmail)) return "atom"; - stream.skipToEnd(); - return "atom"; - } - - if (state.inHeader) { - var style = styleForHeader(state.header); - - if (state.emailPermitted) { - if (stream.match(bracketedEmail)) return style + " link"; - if (stream.match(untilBracketedEmail)) return style; - } - stream.skipToEnd(); - return style; - } - - stream.skipToEnd(); - return null; -}; - -CodeMirror.defineMode("mbox", function() { - return { - startState: function() { - return { - // Is in a mbox separator - inSeparator: false, - // Is in a mail header - inHeader: false, - // If bracketed email is permitted. Only applicable when inHeader - emailPermitted: false, - // Name of current header - header: null, - // Is in a region of mail headers - inHeaders: false - }; - }, - token: readToken, - blankLine: function(state) { - state.inHeaders = state.inSeparator = state.inHeader = false; - } - }; -}); - -CodeMirror.defineMIME("application/mbox", "mbox"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/meta.js b/backend/_pv_1_3_5/static/codemirror/mode/meta.js deleted file mode 100755 index bb6050241..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/meta.js +++ /dev/null @@ -1,212 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.modeInfo = [ - {name: "APL", mime: "text/apl", mode: "apl", ext: ["dyalog", "apl"]}, - {name: "PGP", mimes: ["application/pgp", "application/pgp-keys", "application/pgp-signature"], mode: "asciiarmor", ext: ["pgp"]}, - {name: "ASN.1", mime: "text/x-ttcn-asn", mode: "asn.1", ext: ["asn", "asn1"]}, - {name: "Asterisk", mime: "text/x-asterisk", mode: "asterisk", file: /^extensions\.conf$/i}, - {name: "Brainfuck", mime: "text/x-brainfuck", mode: "brainfuck", ext: ["b", "bf"]}, - {name: "C", mime: "text/x-csrc", mode: "clike", ext: ["c", "h"]}, - {name: "C++", mime: "text/x-c++src", mode: "clike", ext: ["cpp", "c++", "cc", "cxx", "hpp", "h++", "hh", "hxx"], alias: ["cpp"]}, - {name: "Cobol", mime: "text/x-cobol", mode: "cobol", ext: ["cob", "cpy"]}, - {name: "C#", mime: "text/x-csharp", mode: "clike", ext: ["cs"], alias: ["csharp"]}, - {name: "Clojure", mime: "text/x-clojure", mode: "clojure", ext: ["clj", "cljc", "cljx"]}, - {name: "ClojureScript", mime: "text/x-clojurescript", mode: "clojure", ext: ["cljs"]}, - {name: "Closure Stylesheets (GSS)", mime: "text/x-gss", mode: "css", ext: ["gss"]}, - {name: "CMake", mime: "text/x-cmake", mode: "cmake", ext: ["cmake", "cmake.in"], file: /^CMakeLists.txt$/}, - {name: "CoffeeScript", mime: "text/x-coffeescript", mode: "coffeescript", ext: ["coffee"], alias: ["coffee", "coffee-script"]}, - {name: "Common Lisp", mime: "text/x-common-lisp", mode: "commonlisp", ext: ["cl", "lisp", "el"], alias: ["lisp"]}, - {name: "Cypher", mime: "application/x-cypher-query", mode: "cypher", ext: ["cyp", "cypher"]}, - {name: "Cython", mime: "text/x-cython", mode: "python", ext: ["pyx", "pxd", "pxi"]}, - {name: "Crystal", mime: "text/x-crystal", mode: "crystal", ext: ["cr"]}, - {name: "CSS", mime: "text/css", mode: "css", ext: ["css"]}, - {name: "CQL", mime: "text/x-cassandra", mode: "sql", ext: ["cql"]}, - {name: "D", mime: "text/x-d", mode: "d", ext: ["d"]}, - {name: "Dart", mimes: ["application/dart", "text/x-dart"], mode: "dart", ext: ["dart"]}, - {name: "diff", mime: "text/x-diff", mode: "diff", ext: ["diff", "patch"]}, - {name: "Django", mime: "text/x-django", mode: "django"}, - {name: "Dockerfile", mime: "text/x-dockerfile", mode: "dockerfile", file: /^Dockerfile$/}, - {name: "DTD", mime: "application/xml-dtd", mode: "dtd", ext: ["dtd"]}, - {name: "Dylan", mime: "text/x-dylan", mode: "dylan", ext: ["dylan", "dyl", "intr"]}, - {name: "EBNF", mime: "text/x-ebnf", mode: "ebnf"}, - {name: "ECL", mime: "text/x-ecl", mode: "ecl", ext: ["ecl"]}, - {name: "edn", mime: "application/edn", mode: "clojure", ext: ["edn"]}, - {name: "Eiffel", mime: "text/x-eiffel", mode: "eiffel", ext: ["e"]}, - {name: "Elm", mime: "text/x-elm", mode: "elm", ext: ["elm"]}, - {name: "Embedded Javascript", mime: "application/x-ejs", mode: "htmlembedded", ext: ["ejs"]}, - {name: "Embedded Ruby", mime: "application/x-erb", mode: "htmlembedded", ext: ["erb"]}, - {name: "Erlang", mime: "text/x-erlang", mode: "erlang", ext: ["erl"]}, - {name: "Factor", mime: "text/x-factor", mode: "factor", ext: ["factor"]}, - {name: "FCL", mime: "text/x-fcl", mode: "fcl"}, - {name: "Forth", mime: "text/x-forth", mode: "forth", ext: ["forth", "fth", "4th"]}, - {name: "Fortran", mime: "text/x-fortran", mode: "fortran", ext: ["f", "for", "f77", "f90"]}, - {name: "F#", mime: "text/x-fsharp", mode: "mllike", ext: ["fs"], alias: ["fsharp"]}, - {name: "Gas", mime: "text/x-gas", mode: "gas", ext: ["s"]}, - {name: "Gherkin", mime: "text/x-feature", mode: "gherkin", ext: ["feature"]}, - {name: "GitHub Flavored Markdown", mime: "text/x-gfm", mode: "gfm", file: /^(readme|contributing|history).md$/i}, - {name: "Go", mime: "text/x-go", mode: "go", ext: ["go"]}, - {name: "Groovy", mime: "text/x-groovy", mode: "groovy", ext: ["groovy", "gradle"], file: /^Jenkinsfile$/}, - {name: "HAML", mime: "text/x-haml", mode: "haml", ext: ["haml"]}, - {name: "Haskell", mime: "text/x-haskell", mode: "haskell", ext: ["hs"]}, - {name: "Haskell (Literate)", mime: "text/x-literate-haskell", mode: "haskell-literate", ext: ["lhs"]}, - {name: "Haxe", mime: "text/x-haxe", mode: "haxe", ext: ["hx"]}, - {name: "HXML", mime: "text/x-hxml", mode: "haxe", ext: ["hxml"]}, - {name: "ASP.NET", mime: "application/x-aspx", mode: "htmlembedded", ext: ["aspx"], alias: ["asp", "aspx"]}, - {name: "HTML", mime: "text/html", mode: "htmlmixed", ext: ["html", "htm"], alias: ["xhtml"]}, - {name: "HTTP", mime: "message/http", mode: "http"}, - {name: "IDL", mime: "text/x-idl", mode: "idl", ext: ["pro"]}, - {name: "Pug", mime: "text/x-pug", mode: "pug", ext: ["jade", "pug"], alias: ["jade"]}, - {name: "Java", mime: "text/x-java", mode: "clike", ext: ["java"]}, - {name: "Java Server Pages", mime: "application/x-jsp", mode: "htmlembedded", ext: ["jsp"], alias: ["jsp"]}, - {name: "JavaScript", mimes: ["text/javascript", "text/ecmascript", "application/javascript", "application/x-javascript", "application/ecmascript"], - mode: "javascript", ext: ["js"], alias: ["ecmascript", "js", "node"]}, - {name: "JSON", mimes: ["application/json", "application/x-json"], mode: "javascript", ext: ["json", "map"], alias: ["json5"]}, - {name: "JSON-LD", mime: "application/ld+json", mode: "javascript", ext: ["jsonld"], alias: ["jsonld"]}, - {name: "JSX", mime: "text/jsx", mode: "jsx", ext: ["jsx"]}, - {name: "Jinja2", mime: "null", mode: "jinja2"}, - {name: "Julia", mime: "text/x-julia", mode: "julia", ext: ["jl"]}, - {name: "Kotlin", mime: "text/x-kotlin", mode: "clike", ext: ["kt"]}, - {name: "LESS", mime: "text/x-less", mode: "css", ext: ["less"]}, - {name: "LiveScript", mime: "text/x-livescript", mode: "livescript", ext: ["ls"], alias: ["ls"]}, - {name: "Lua", mime: "text/x-lua", mode: "lua", ext: ["lua"]}, - {name: "Markdown", mime: "text/x-markdown", mode: "markdown", ext: ["markdown", "md", "mkd"]}, - {name: "mIRC", mime: "text/mirc", mode: "mirc"}, - {name: "MariaDB SQL", mime: "text/x-mariadb", mode: "sql"}, - {name: "Mathematica", mime: "text/x-mathematica", mode: "mathematica", ext: ["m", "nb"]}, - {name: "Modelica", mime: "text/x-modelica", mode: "modelica", ext: ["mo"]}, - {name: "MUMPS", mime: "text/x-mumps", mode: "mumps", ext: ["mps"]}, - {name: "MS SQL", mime: "text/x-mssql", mode: "sql"}, - {name: "mbox", mime: "application/mbox", mode: "mbox", ext: ["mbox"]}, - {name: "MySQL", mime: "text/x-mysql", mode: "sql"}, - {name: "Nginx", mime: "text/x-nginx-conf", mode: "nginx", file: /nginx.*\.conf$/i}, - {name: "NSIS", mime: "text/x-nsis", mode: "nsis", ext: ["nsh", "nsi"]}, - {name: "NTriples", mime: "text/n-triples", mode: "ntriples", ext: ["nt"]}, - {name: "Objective C", mime: "text/x-objectivec", mode: "clike", ext: ["m", "mm"], alias: ["objective-c", "objc"]}, - {name: "OCaml", mime: "text/x-ocaml", mode: "mllike", ext: ["ml", "mli", "mll", "mly"]}, - {name: "Octave", mime: "text/x-octave", mode: "octave", ext: ["m"]}, - {name: "Oz", mime: "text/x-oz", mode: "oz", ext: ["oz"]}, - {name: "Pascal", mime: "text/x-pascal", mode: "pascal", ext: ["p", "pas"]}, - {name: "PEG.js", mime: "null", mode: "pegjs", ext: ["jsonld"]}, - {name: "Perl", mime: "text/x-perl", mode: "perl", ext: ["pl", "pm"]}, - {name: "PHP", mime: "application/x-httpd-php", mode: "php", ext: ["php", "php3", "php4", "php5", "phtml"]}, - {name: "Pig", mime: "text/x-pig", mode: "pig", ext: ["pig"]}, - {name: "Plain Text", mime: "text/plain", mode: "null", ext: ["txt", "text", "conf", "def", "list", "log"]}, - {name: "PLSQL", mime: "text/x-plsql", mode: "sql", ext: ["pls"]}, - {name: "PowerShell", mime: "application/x-powershell", mode: "powershell", ext: ["ps1", "psd1", "psm1"]}, - {name: "Properties files", mime: "text/x-properties", mode: "properties", ext: ["properties", "ini", "in"], alias: ["ini", "properties"]}, - {name: "ProtoBuf", mime: "text/x-protobuf", mode: "protobuf", ext: ["proto"]}, - {name: "Python", mime: "text/x-python", mode: "python", ext: ["BUILD", "bzl", "py", "pyw"], file: /^(BUCK|BUILD)$/}, - {name: "Puppet", mime: "text/x-puppet", mode: "puppet", ext: ["pp"]}, - {name: "Q", mime: "text/x-q", mode: "q", ext: ["q"]}, - {name: "R", mime: "text/x-rsrc", mode: "r", ext: ["r", "R"], alias: ["rscript"]}, - {name: "reStructuredText", mime: "text/x-rst", mode: "rst", ext: ["rst"], alias: ["rst"]}, - {name: "RPM Changes", mime: "text/x-rpm-changes", mode: "rpm"}, - {name: "RPM Spec", mime: "text/x-rpm-spec", mode: "rpm", ext: ["spec"]}, - {name: "Ruby", mime: "text/x-ruby", mode: "ruby", ext: ["rb"], alias: ["jruby", "macruby", "rake", "rb", "rbx"]}, - {name: "Rust", mime: "text/x-rustsrc", mode: "rust", ext: ["rs"]}, - {name: "SAS", mime: "text/x-sas", mode: "sas", ext: ["sas"]}, - {name: "Sass", mime: "text/x-sass", mode: "sass", ext: ["sass"]}, - {name: "Scala", mime: "text/x-scala", mode: "clike", ext: ["scala"]}, - {name: "Scheme", mime: "text/x-scheme", mode: "scheme", ext: ["scm", "ss"]}, - {name: "SCSS", mime: "text/x-scss", mode: "css", ext: ["scss"]}, - {name: "Shell", mime: "text/x-sh", mode: "shell", ext: ["sh", "ksh", "bash"], alias: ["bash", "sh", "zsh"], file: /^PKGBUILD$/}, - {name: "Sieve", mime: "application/sieve", mode: "sieve", ext: ["siv", "sieve"]}, - {name: "Slim", mimes: ["text/x-slim", "application/x-slim"], mode: "slim", ext: ["slim"]}, - {name: "Smalltalk", mime: "text/x-stsrc", mode: "smalltalk", ext: ["st"]}, - {name: "Smarty", mime: "text/x-smarty", mode: "smarty", ext: ["tpl"]}, - {name: "Solr", mime: "text/x-solr", mode: "solr"}, - {name: "Soy", mime: "text/x-soy", mode: "soy", ext: ["soy"], alias: ["closure template"]}, - {name: "SPARQL", mime: "application/sparql-query", mode: "sparql", ext: ["rq", "sparql"], alias: ["sparul"]}, - {name: "Spreadsheet", mime: "text/x-spreadsheet", mode: "spreadsheet", alias: ["excel", "formula"]}, - {name: "SQL", mime: "text/x-sql", mode: "sql", ext: ["sql"]}, - {name: "Squirrel", mime: "text/x-squirrel", mode: "clike", ext: ["nut"]}, - {name: "Stylus", mime: "text/x-styl", mode: "stylus", ext: ["styl"]}, - {name: "Swift", mime: "text/x-swift", mode: "swift", ext: ["swift"]}, - {name: "sTeX", mime: "text/x-stex", mode: "stex"}, - {name: "LaTeX", mime: "text/x-latex", mode: "stex", ext: ["text", "ltx"], alias: ["tex"]}, - {name: "SystemVerilog", mime: "text/x-systemverilog", mode: "verilog", ext: ["v"]}, - {name: "Tcl", mime: "text/x-tcl", mode: "tcl", ext: ["tcl"]}, - {name: "Textile", mime: "text/x-textile", mode: "textile", ext: ["textile"]}, - {name: "TiddlyWiki ", mime: "text/x-tiddlywiki", mode: "tiddlywiki"}, - {name: "Tiki wiki", mime: "text/tiki", mode: "tiki"}, - {name: "TOML", mime: "text/x-toml", mode: "toml", ext: ["toml"]}, - {name: "Tornado", mime: "text/x-tornado", mode: "tornado"}, - {name: "troff", mime: "text/troff", mode: "troff", ext: ["1", "2", "3", "4", "5", "6", "7", "8", "9"]}, - {name: "TTCN", mime: "text/x-ttcn", mode: "ttcn", ext: ["ttcn", "ttcn3", "ttcnpp"]}, - {name: "TTCN_CFG", mime: "text/x-ttcn-cfg", mode: "ttcn-cfg", ext: ["cfg"]}, - {name: "Turtle", mime: "text/turtle", mode: "turtle", ext: ["ttl"]}, - {name: "TypeScript", mime: "application/typescript", mode: "javascript", ext: ["ts"], alias: ["ts"]}, - {name: "Twig", mime: "text/x-twig", mode: "twig"}, - {name: "Web IDL", mime: "text/x-webidl", mode: "webidl", ext: ["webidl"]}, - {name: "VB.NET", mime: "text/x-vb", mode: "vb", ext: ["vb"]}, - {name: "VBScript", mime: "text/vbscript", mode: "vbscript", ext: ["vbs"]}, - {name: "Velocity", mime: "text/velocity", mode: "velocity", ext: ["vtl"]}, - {name: "Verilog", mime: "text/x-verilog", mode: "verilog", ext: ["v"]}, - {name: "VHDL", mime: "text/x-vhdl", mode: "vhdl", ext: ["vhd", "vhdl"]}, - {name: "Vue.js Component", mimes: ["script/x-vue", "text/x-vue"], mode: "vue", ext: ["vue"]}, - {name: "XML", mimes: ["application/xml", "text/xml"], mode: "xml", ext: ["xml", "xsl", "xsd", "svg"], alias: ["rss", "wsdl", "xsd"]}, - {name: "XQuery", mime: "application/xquery", mode: "xquery", ext: ["xy", "xquery"]}, - {name: "Yacas", mime: "text/x-yacas", mode: "yacas", ext: ["ys"]}, - {name: "YAML", mimes: ["text/x-yaml", "text/yaml"], mode: "yaml", ext: ["yaml", "yml"], alias: ["yml"]}, - {name: "Z80", mime: "text/x-z80", mode: "z80", ext: ["z80"]}, - {name: "mscgen", mime: "text/x-mscgen", mode: "mscgen", ext: ["mscgen", "mscin", "msc"]}, - {name: "xu", mime: "text/x-xu", mode: "mscgen", ext: ["xu"]}, - {name: "msgenny", mime: "text/x-msgenny", mode: "mscgen", ext: ["msgenny"]} - ]; - // Ensure all modes have a mime property for backwards compatibility - for (var i = 0; i < CodeMirror.modeInfo.length; i++) { - var info = CodeMirror.modeInfo[i]; - if (info.mimes) info.mime = info.mimes[0]; - } - - CodeMirror.findModeByMIME = function(mime) { - mime = mime.toLowerCase(); - for (var i = 0; i < CodeMirror.modeInfo.length; i++) { - var info = CodeMirror.modeInfo[i]; - if (info.mime == mime) return info; - if (info.mimes) for (var j = 0; j < info.mimes.length; j++) - if (info.mimes[j] == mime) return info; - } - if (/\+xml$/.test(mime)) return CodeMirror.findModeByMIME("application/xml") - if (/\+json$/.test(mime)) return CodeMirror.findModeByMIME("application/json") - }; - - CodeMirror.findModeByExtension = function(ext) { - for (var i = 0; i < CodeMirror.modeInfo.length; i++) { - var info = CodeMirror.modeInfo[i]; - if (info.ext) for (var j = 0; j < info.ext.length; j++) - if (info.ext[j] == ext) return info; - } - }; - - CodeMirror.findModeByFileName = function(filename) { - for (var i = 0; i < CodeMirror.modeInfo.length; i++) { - var info = CodeMirror.modeInfo[i]; - if (info.file && info.file.test(filename)) return info; - } - var dot = filename.lastIndexOf("."); - var ext = dot > -1 && filename.substring(dot + 1, filename.length); - if (ext) return CodeMirror.findModeByExtension(ext); - }; - - CodeMirror.findModeByName = function(name) { - name = name.toLowerCase(); - for (var i = 0; i < CodeMirror.modeInfo.length; i++) { - var info = CodeMirror.modeInfo[i]; - if (info.name.toLowerCase() == name) return info; - if (info.alias) for (var j = 0; j < info.alias.length; j++) - if (info.alias[j].toLowerCase() == name) return info; - } - }; -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/mirc/index.html b/backend/_pv_1_3_5/static/codemirror/mode/mirc/index.html deleted file mode 100755 index fd2f34e4b..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/mirc/index.html +++ /dev/null @@ -1,160 +0,0 @@ - - -CodeMirror: mIRC mode - - - - - - - - - - -
    -

    mIRC mode

    -
    - - -

    MIME types defined: text/mirc.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/mirc/mirc.js b/backend/_pv_1_3_5/static/codemirror/mode/mirc/mirc.js deleted file mode 100755 index f0d5c6ad5..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/mirc/mirc.js +++ /dev/null @@ -1,193 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -//mIRC mode by Ford_Lawnmower :: Based on Velocity mode by Steve O'Hara - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMIME("text/mirc", "mirc"); -CodeMirror.defineMode("mirc", function() { - function parseWords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - var specials = parseWords("$! $$ $& $? $+ $abook $abs $active $activecid " + - "$activewid $address $addtok $agent $agentname $agentstat $agentver " + - "$alias $and $anick $ansi2mirc $aop $appactive $appstate $asc $asctime " + - "$asin $atan $avoice $away $awaymsg $awaytime $banmask $base $bfind " + - "$binoff $biton $bnick $bvar $bytes $calc $cb $cd $ceil $chan $chanmodes " + - "$chantypes $chat $chr $cid $clevel $click $cmdbox $cmdline $cnick $color " + - "$com $comcall $comchan $comerr $compact $compress $comval $cos $count " + - "$cr $crc $creq $crlf $ctime $ctimer $ctrlenter $date $day $daylight " + - "$dbuh $dbuw $dccignore $dccport $dde $ddename $debug $decode $decompress " + - "$deltok $devent $dialog $did $didreg $didtok $didwm $disk $dlevel $dll " + - "$dllcall $dname $dns $duration $ebeeps $editbox $emailaddr $encode $error " + - "$eval $event $exist $feof $ferr $fgetc $file $filename $filtered $finddir " + - "$finddirn $findfile $findfilen $findtok $fline $floor $fopen $fread $fserve " + - "$fulladdress $fulldate $fullname $fullscreen $get $getdir $getdot $gettok $gmt " + - "$group $halted $hash $height $hfind $hget $highlight $hnick $hotline " + - "$hotlinepos $ial $ialchan $ibl $idle $iel $ifmatch $ignore $iif $iil " + - "$inelipse $ini $inmidi $inpaste $inpoly $input $inrect $inroundrect " + - "$insong $instok $int $inwave $ip $isalias $isbit $isdde $isdir $isfile " + - "$isid $islower $istok $isupper $keychar $keyrpt $keyval $knick $lactive " + - "$lactivecid $lactivewid $left $len $level $lf $line $lines $link $lock " + - "$lock $locked $log $logstamp $logstampfmt $longfn $longip $lower $ltimer " + - "$maddress $mask $matchkey $matchtok $md5 $me $menu $menubar $menucontext " + - "$menutype $mid $middir $mircdir $mircexe $mircini $mklogfn $mnick $mode " + - "$modefirst $modelast $modespl $mouse $msfile $network $newnick $nick $nofile " + - "$nopath $noqt $not $notags $notify $null $numeric $numok $oline $onpoly " + - "$opnick $or $ord $os $passivedcc $pic $play $pnick $port $portable $portfree " + - "$pos $prefix $prop $protect $puttok $qt $query $rand $r $rawmsg $read $readomo " + - "$readn $regex $regml $regsub $regsubex $remove $remtok $replace $replacex " + - "$reptok $result $rgb $right $round $scid $scon $script $scriptdir $scriptline " + - "$sdir $send $server $serverip $sfile $sha1 $shortfn $show $signal $sin " + - "$site $sline $snick $snicks $snotify $sock $sockbr $sockerr $sockname " + - "$sorttok $sound $sqrt $ssl $sreq $sslready $status $strip $str $stripped " + - "$syle $submenu $switchbar $tan $target $ticks $time $timer $timestamp " + - "$timestampfmt $timezone $tip $titlebar $toolbar $treebar $trust $ulevel " + - "$ulist $upper $uptime $url $usermode $v1 $v2 $var $vcmd $vcmdstat $vcmdver " + - "$version $vnick $vol $wid $width $wildsite $wildtok $window $wrap $xor"); - var keywords = parseWords("abook ajinvite alias aline ame amsg anick aop auser autojoin avoice " + - "away background ban bcopy beep bread break breplace bset btrunc bunset bwrite " + - "channel clear clearall cline clipboard close cnick color comclose comopen " + - "comreg continue copy creq ctcpreply ctcps dcc dccserver dde ddeserver " + - "debug dec describe dialog did didtok disable disconnect dlevel dline dll " + - "dns dqwindow drawcopy drawdot drawfill drawline drawpic drawrect drawreplace " + - "drawrot drawsave drawscroll drawtext ebeeps echo editbox emailaddr enable " + - "events exit fclose filter findtext finger firewall flash flist flood flush " + - "flushini font fopen fseek fsend fserve fullname fwrite ghide gload gmove " + - "gopts goto gplay gpoint gqreq groups gshow gsize gstop gtalk gunload hadd " + - "halt haltdef hdec hdel help hfree hinc hload hmake hop hsave ial ialclear " + - "ialmark identd if ignore iline inc invite iuser join kick linesep links list " + - "load loadbuf localinfo log mdi me menubar mkdir mnick mode msg nick noop notice " + - "notify omsg onotice part partall pdcc perform play playctrl pop protect pvoice " + - "qme qmsg query queryn quit raw reload remini remote remove rename renwin " + - "reseterror resetidle return rlevel rline rmdir run ruser save savebuf saveini " + - "say scid scon server set showmirc signam sline sockaccept sockclose socklist " + - "socklisten sockmark sockopen sockpause sockread sockrename sockudp sockwrite " + - "sound speak splay sreq strip switchbar timer timestamp titlebar tnick tokenize " + - "toolbar topic tray treebar ulist unload unset unsetall updatenl url uwho " + - "var vcadd vcmd vcrem vol while whois window winhelp write writeint if isalnum " + - "isalpha isaop isavoice isban ischan ishop isignore isin isincs isletter islower " + - "isnotify isnum ison isop isprotect isreg isupper isvoice iswm iswmcs " + - "elseif else goto menu nicklist status title icon size option text edit " + - "button check radio box scroll list combo link tab item"); - var functions = parseWords("if elseif else and not or eq ne in ni for foreach while switch"); - var isOperatorChar = /[+\-*&%=<>!?^\/\|]/; - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - function tokenBase(stream, state) { - var beforeParams = state.beforeParams; - state.beforeParams = false; - var ch = stream.next(); - if (/[\[\]{}\(\),\.]/.test(ch)) { - if (ch == "(" && beforeParams) state.inParams = true; - else if (ch == ")") state.inParams = false; - return null; - } - else if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - else if (ch == "\\") { - stream.eat("\\"); - stream.eat(/./); - return "number"; - } - else if (ch == "/" && stream.eat("*")) { - return chain(stream, state, tokenComment); - } - else if (ch == ";" && stream.match(/ *\( *\(/)) { - return chain(stream, state, tokenUnparsed); - } - else if (ch == ";" && !state.inParams) { - stream.skipToEnd(); - return "comment"; - } - else if (ch == '"') { - stream.eat(/"/); - return "keyword"; - } - else if (ch == "$") { - stream.eatWhile(/[$_a-z0-9A-Z\.:]/); - if (specials && specials.propertyIsEnumerable(stream.current().toLowerCase())) { - return "keyword"; - } - else { - state.beforeParams = true; - return "builtin"; - } - } - else if (ch == "%") { - stream.eatWhile(/[^,^\s^\(^\)]/); - state.beforeParams = true; - return "string"; - } - else if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - else { - stream.eatWhile(/[\w\$_{}]/); - var word = stream.current().toLowerCase(); - if (keywords && keywords.propertyIsEnumerable(word)) - return "keyword"; - if (functions && functions.propertyIsEnumerable(word)) { - state.beforeParams = true; - return "keyword"; - } - return null; - } - } - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - function tokenUnparsed(stream, state) { - var maybeEnd = 0, ch; - while (ch = stream.next()) { - if (ch == ";" && maybeEnd == 2) { - state.tokenize = tokenBase; - break; - } - if (ch == ")") - maybeEnd++; - else if (ch != " ") - maybeEnd = 0; - } - return "meta"; - } - return { - startState: function() { - return { - tokenize: tokenBase, - beforeParams: false, - inParams: false - }; - }, - token: function(stream, state) { - if (stream.eatSpace()) return null; - return state.tokenize(stream, state); - } - }; -}); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/mllike/index.html b/backend/_pv_1_3_5/static/codemirror/mode/mllike/index.html deleted file mode 100755 index 5923af8f8..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/mllike/index.html +++ /dev/null @@ -1,179 +0,0 @@ - - -CodeMirror: ML-like mode - - - - - - - - - - -
    -

    OCaml mode

    - - - - -

    F# mode

    - - - - - -

    MIME types defined: text/x-ocaml (OCaml) and text/x-fsharp (F#).

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/mllike/mllike.js b/backend/_pv_1_3_5/static/codemirror/mode/mllike/mllike.js deleted file mode 100755 index 4d0be609c..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/mllike/mllike.js +++ /dev/null @@ -1,208 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode('mllike', function(_config, parserConfig) { - var words = { - 'let': 'keyword', - 'rec': 'keyword', - 'in': 'keyword', - 'of': 'keyword', - 'and': 'keyword', - 'if': 'keyword', - 'then': 'keyword', - 'else': 'keyword', - 'for': 'keyword', - 'to': 'keyword', - 'while': 'keyword', - 'do': 'keyword', - 'done': 'keyword', - 'fun': 'keyword', - 'function': 'keyword', - 'val': 'keyword', - 'type': 'keyword', - 'mutable': 'keyword', - 'match': 'keyword', - 'with': 'keyword', - 'try': 'keyword', - 'open': 'builtin', - 'ignore': 'builtin', - 'begin': 'keyword', - 'end': 'keyword' - }; - - var extraWords = parserConfig.extraWords || {}; - for (var prop in extraWords) { - if (extraWords.hasOwnProperty(prop)) { - words[prop] = parserConfig.extraWords[prop]; - } - } - - function tokenBase(stream, state) { - var ch = stream.next(); - - if (ch === '"') { - state.tokenize = tokenString; - return state.tokenize(stream, state); - } - if (ch === '(') { - if (stream.eat('*')) { - state.commentLevel++; - state.tokenize = tokenComment; - return state.tokenize(stream, state); - } - } - if (ch === '~') { - stream.eatWhile(/\w/); - return 'variable-2'; - } - if (ch === '`') { - stream.eatWhile(/\w/); - return 'quote'; - } - if (ch === '/' && parserConfig.slashComments && stream.eat('/')) { - stream.skipToEnd(); - return 'comment'; - } - if (/\d/.test(ch)) { - stream.eatWhile(/[\d]/); - if (stream.eat('.')) { - stream.eatWhile(/[\d]/); - } - return 'number'; - } - if ( /[+\-*&%=<>!?|]/.test(ch)) { - return 'operator'; - } - if (/[\w\xa1-\uffff]/.test(ch)) { - stream.eatWhile(/[\w\xa1-\uffff]/); - var cur = stream.current(); - return words.hasOwnProperty(cur) ? words[cur] : 'variable'; - } - return null - } - - function tokenString(stream, state) { - var next, end = false, escaped = false; - while ((next = stream.next()) != null) { - if (next === '"' && !escaped) { - end = true; - break; - } - escaped = !escaped && next === '\\'; - } - if (end && !escaped) { - state.tokenize = tokenBase; - } - return 'string'; - }; - - function tokenComment(stream, state) { - var prev, next; - while(state.commentLevel > 0 && (next = stream.next()) != null) { - if (prev === '(' && next === '*') state.commentLevel++; - if (prev === '*' && next === ')') state.commentLevel--; - prev = next; - } - if (state.commentLevel <= 0) { - state.tokenize = tokenBase; - } - return 'comment'; - } - - return { - startState: function() {return {tokenize: tokenBase, commentLevel: 0};}, - token: function(stream, state) { - if (stream.eatSpace()) return null; - return state.tokenize(stream, state); - }, - - blockCommentStart: "(*", - blockCommentEnd: "*)", - lineComment: parserConfig.slashComments ? "//" : null - }; -}); - -CodeMirror.defineMIME('text/x-ocaml', { - name: 'mllike', - extraWords: { - 'succ': 'keyword', - 'trace': 'builtin', - 'exit': 'builtin', - 'print_string': 'builtin', - 'print_endline': 'builtin', - 'true': 'atom', - 'false': 'atom', - 'raise': 'keyword' - } -}); - -CodeMirror.defineMIME('text/x-fsharp', { - name: 'mllike', - extraWords: { - 'abstract': 'keyword', - 'as': 'keyword', - 'assert': 'keyword', - 'base': 'keyword', - 'class': 'keyword', - 'default': 'keyword', - 'delegate': 'keyword', - 'downcast': 'keyword', - 'downto': 'keyword', - 'elif': 'keyword', - 'exception': 'keyword', - 'extern': 'keyword', - 'finally': 'keyword', - 'global': 'keyword', - 'inherit': 'keyword', - 'inline': 'keyword', - 'interface': 'keyword', - 'internal': 'keyword', - 'lazy': 'keyword', - 'let!': 'keyword', - 'member' : 'keyword', - 'module': 'keyword', - 'namespace': 'keyword', - 'new': 'keyword', - 'null': 'keyword', - 'override': 'keyword', - 'private': 'keyword', - 'public': 'keyword', - 'return': 'keyword', - 'return!': 'keyword', - 'select': 'keyword', - 'static': 'keyword', - 'struct': 'keyword', - 'upcast': 'keyword', - 'use': 'keyword', - 'use!': 'keyword', - 'val': 'keyword', - 'when': 'keyword', - 'yield': 'keyword', - 'yield!': 'keyword', - - 'List': 'builtin', - 'Seq': 'builtin', - 'Map': 'builtin', - 'Set': 'builtin', - 'int': 'builtin', - 'string': 'builtin', - 'raise': 'builtin', - 'failwith': 'builtin', - 'not': 'builtin', - 'true': 'builtin', - 'false': 'builtin' - }, - slashComments: true -}); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/modelica/index.html b/backend/_pv_1_3_5/static/codemirror/mode/modelica/index.html deleted file mode 100755 index 408c3b17e..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/modelica/index.html +++ /dev/null @@ -1,67 +0,0 @@ - - -CodeMirror: Modelica mode - - - - - - - - - - - - -
    -

    Modelica mode

    - -
    - - - -

    Simple mode that tries to handle Modelica as well as it can.

    - -

    MIME types defined: text/x-modelica - (Modlica code).

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/modelica/modelica.js b/backend/_pv_1_3_5/static/codemirror/mode/modelica/modelica.js deleted file mode 100755 index 77ec7a3c1..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/modelica/modelica.js +++ /dev/null @@ -1,245 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Modelica support for CodeMirror, copyright (c) by Lennart Ochel - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -}) - -(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("modelica", function(config, parserConfig) { - - var indentUnit = config.indentUnit; - var keywords = parserConfig.keywords || {}; - var builtin = parserConfig.builtin || {}; - var atoms = parserConfig.atoms || {}; - - var isSingleOperatorChar = /[;=\(:\),{}.*<>+\-\/^\[\]]/; - var isDoubleOperatorChar = /(:=|<=|>=|==|<>|\.\+|\.\-|\.\*|\.\/|\.\^)/; - var isDigit = /[0-9]/; - var isNonDigit = /[_a-zA-Z]/; - - function tokenLineComment(stream, state) { - stream.skipToEnd(); - state.tokenize = null; - return "comment"; - } - - function tokenBlockComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (maybeEnd && ch == "/") { - state.tokenize = null; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function tokenString(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == '"' && !escaped) { - state.tokenize = null; - state.sol = false; - break; - } - escaped = !escaped && ch == "\\"; - } - - return "string"; - } - - function tokenIdent(stream, state) { - stream.eatWhile(isDigit); - while (stream.eat(isDigit) || stream.eat(isNonDigit)) { } - - - var cur = stream.current(); - - if(state.sol && (cur == "package" || cur == "model" || cur == "when" || cur == "connector")) state.level++; - else if(state.sol && cur == "end" && state.level > 0) state.level--; - - state.tokenize = null; - state.sol = false; - - if (keywords.propertyIsEnumerable(cur)) return "keyword"; - else if (builtin.propertyIsEnumerable(cur)) return "builtin"; - else if (atoms.propertyIsEnumerable(cur)) return "atom"; - else return "variable"; - } - - function tokenQIdent(stream, state) { - while (stream.eat(/[^']/)) { } - - state.tokenize = null; - state.sol = false; - - if(stream.eat("'")) - return "variable"; - else - return "error"; - } - - function tokenUnsignedNuber(stream, state) { - stream.eatWhile(isDigit); - if (stream.eat('.')) { - stream.eatWhile(isDigit); - } - if (stream.eat('e') || stream.eat('E')) { - if (!stream.eat('-')) - stream.eat('+'); - stream.eatWhile(isDigit); - } - - state.tokenize = null; - state.sol = false; - return "number"; - } - - // Interface - return { - startState: function() { - return { - tokenize: null, - level: 0, - sol: true - }; - }, - - token: function(stream, state) { - if(state.tokenize != null) { - return state.tokenize(stream, state); - } - - if(stream.sol()) { - state.sol = true; - } - - // WHITESPACE - if(stream.eatSpace()) { - state.tokenize = null; - return null; - } - - var ch = stream.next(); - - // LINECOMMENT - if(ch == '/' && stream.eat('/')) { - state.tokenize = tokenLineComment; - } - // BLOCKCOMMENT - else if(ch == '/' && stream.eat('*')) { - state.tokenize = tokenBlockComment; - } - // TWO SYMBOL TOKENS - else if(isDoubleOperatorChar.test(ch+stream.peek())) { - stream.next(); - state.tokenize = null; - return "operator"; - } - // SINGLE SYMBOL TOKENS - else if(isSingleOperatorChar.test(ch)) { - state.tokenize = null; - return "operator"; - } - // IDENT - else if(isNonDigit.test(ch)) { - state.tokenize = tokenIdent; - } - // Q-IDENT - else if(ch == "'" && stream.peek() && stream.peek() != "'") { - state.tokenize = tokenQIdent; - } - // STRING - else if(ch == '"') { - state.tokenize = tokenString; - } - // UNSIGNED_NUBER - else if(isDigit.test(ch)) { - state.tokenize = tokenUnsignedNuber; - } - // ERROR - else { - state.tokenize = null; - return "error"; - } - - return state.tokenize(stream, state); - }, - - indent: function(state, textAfter) { - if (state.tokenize != null) return CodeMirror.Pass; - - var level = state.level; - if(/(algorithm)/.test(textAfter)) level--; - if(/(equation)/.test(textAfter)) level--; - if(/(initial algorithm)/.test(textAfter)) level--; - if(/(initial equation)/.test(textAfter)) level--; - if(/(end)/.test(textAfter)) level--; - - if(level > 0) - return indentUnit*level; - else - return 0; - }, - - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: "//" - }; - }); - - function words(str) { - var obj = {}, words = str.split(" "); - for (var i=0; i - -CodeMirror: MscGen mode - - - - - - - - - -
    -

    MscGen mode

    - -
    - -

    Xù mode

    - -
    - -

    MsGenny mode

    -
    - -

    - Simple mode for highlighting MscGen and two derived sequence - chart languages. -

    - - - -

    MIME types defined: - text/x-mscgen - text/x-xu - text/x-msgenny -

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/mscgen/mscgen.js b/backend/_pv_1_3_5/static/codemirror/mode/mscgen/mscgen.js deleted file mode 100755 index 2cd6f4270..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/mscgen/mscgen.js +++ /dev/null @@ -1,175 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// mode(s) for the sequence chart dsl's mscgen, xù and msgenny -// For more information on mscgen, see the site of the original author: -// http://www.mcternan.me.uk/mscgen -// -// This mode for mscgen and the two derivative languages were -// originally made for use in the mscgen_js interpreter -// (https://sverweij.github.io/mscgen_js) - -(function(mod) { - if ( typeof exports == "object" && typeof module == "object")// CommonJS - mod(require("../../lib/codemirror")); - else if ( typeof define == "function" && define.amd)// AMD - define(["../../lib/codemirror"], mod); - else// Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - var languages = { - mscgen: { - "keywords" : ["msc"], - "options" : ["hscale", "width", "arcgradient", "wordwraparcs"], - "constants" : ["true", "false", "on", "off"], - "attributes" : ["label", "idurl", "id", "url", "linecolor", "linecolour", "textcolor", "textcolour", "textbgcolor", "textbgcolour", "arclinecolor", "arclinecolour", "arctextcolor", "arctextcolour", "arctextbgcolor", "arctextbgcolour", "arcskip"], - "brackets" : ["\\{", "\\}"], // [ and ] are brackets too, but these get handled in with lists - "arcsWords" : ["note", "abox", "rbox", "box"], - "arcsOthers" : ["\\|\\|\\|", "\\.\\.\\.", "---", "--", "<->", "==", "<<=>>", "<=>", "\\.\\.", "<<>>", "::", "<:>", "->", "=>>", "=>", ">>", ":>", "<-", "<<=", "<=", "<<", "<:", "x-", "-x"], - "singlecomment" : ["//", "#"], - "operators" : ["="] - }, - xu: { - "keywords" : ["msc", "xu"], - "options" : ["hscale", "width", "arcgradient", "wordwraparcs", "watermark"], - "constants" : ["true", "false", "on", "off", "auto"], - "attributes" : ["label", "idurl", "id", "url", "linecolor", "linecolour", "textcolor", "textcolour", "textbgcolor", "textbgcolour", "arclinecolor", "arclinecolour", "arctextcolor", "arctextcolour", "arctextbgcolor", "arctextbgcolour", "arcskip"], - "brackets" : ["\\{", "\\}"], // [ and ] are brackets too, but these get handled in with lists - "arcsWords" : ["note", "abox", "rbox", "box", "alt", "else", "opt", "break", "par", "seq", "strict", "neg", "critical", "ignore", "consider", "assert", "loop", "ref", "exc"], - "arcsOthers" : ["\\|\\|\\|", "\\.\\.\\.", "---", "--", "<->", "==", "<<=>>", "<=>", "\\.\\.", "<<>>", "::", "<:>", "->", "=>>", "=>", ">>", ":>", "<-", "<<=", "<=", "<<", "<:", "x-", "-x"], - "singlecomment" : ["//", "#"], - "operators" : ["="] - }, - msgenny: { - "keywords" : null, - "options" : ["hscale", "width", "arcgradient", "wordwraparcs", "watermark"], - "constants" : ["true", "false", "on", "off", "auto"], - "attributes" : null, - "brackets" : ["\\{", "\\}"], - "arcsWords" : ["note", "abox", "rbox", "box", "alt", "else", "opt", "break", "par", "seq", "strict", "neg", "critical", "ignore", "consider", "assert", "loop", "ref", "exc"], - "arcsOthers" : ["\\|\\|\\|", "\\.\\.\\.", "---", "--", "<->", "==", "<<=>>", "<=>", "\\.\\.", "<<>>", "::", "<:>", "->", "=>>", "=>", ">>", ":>", "<-", "<<=", "<=", "<<", "<:", "x-", "-x"], - "singlecomment" : ["//", "#"], - "operators" : ["="] - } - } - - CodeMirror.defineMode("mscgen", function(_, modeConfig) { - var language = languages[modeConfig && modeConfig.language || "mscgen"] - return { - startState: startStateFn, - copyState: copyStateFn, - token: produceTokenFunction(language), - lineComment : "#", - blockCommentStart : "/*", - blockCommentEnd : "*/" - }; - }); - - CodeMirror.defineMIME("text/x-mscgen", "mscgen"); - CodeMirror.defineMIME("text/x-xu", {name: "mscgen", language: "xu"}); - CodeMirror.defineMIME("text/x-msgenny", {name: "mscgen", language: "msgenny"}); - - function wordRegexpBoundary(pWords) { - return new RegExp("\\b(" + pWords.join("|") + ")\\b", "i"); - } - - function wordRegexp(pWords) { - return new RegExp("(" + pWords.join("|") + ")", "i"); - } - - function startStateFn() { - return { - inComment : false, - inString : false, - inAttributeList : false, - inScript : false - }; - } - - function copyStateFn(pState) { - return { - inComment : pState.inComment, - inString : pState.inString, - inAttributeList : pState.inAttributeList, - inScript : pState.inScript - }; - } - - function produceTokenFunction(pConfig) { - - return function(pStream, pState) { - if (pStream.match(wordRegexp(pConfig.brackets), true, true)) { - return "bracket"; - } - /* comments */ - if (!pState.inComment) { - if (pStream.match(/\/\*[^\*\/]*/, true, true)) { - pState.inComment = true; - return "comment"; - } - if (pStream.match(wordRegexp(pConfig.singlecomment), true, true)) { - pStream.skipToEnd(); - return "comment"; - } - } - if (pState.inComment) { - if (pStream.match(/[^\*\/]*\*\//, true, true)) - pState.inComment = false; - else - pStream.skipToEnd(); - return "comment"; - } - /* strings */ - if (!pState.inString && pStream.match(/\"(\\\"|[^\"])*/, true, true)) { - pState.inString = true; - return "string"; - } - if (pState.inString) { - if (pStream.match(/[^\"]*\"/, true, true)) - pState.inString = false; - else - pStream.skipToEnd(); - return "string"; - } - /* keywords & operators */ - if (!!pConfig.keywords && pStream.match(wordRegexpBoundary(pConfig.keywords), true, true)) - return "keyword"; - - if (pStream.match(wordRegexpBoundary(pConfig.options), true, true)) - return "keyword"; - - if (pStream.match(wordRegexpBoundary(pConfig.arcsWords), true, true)) - return "keyword"; - - if (pStream.match(wordRegexp(pConfig.arcsOthers), true, true)) - return "keyword"; - - if (!!pConfig.operators && pStream.match(wordRegexp(pConfig.operators), true, true)) - return "operator"; - - if (!!pConfig.constants && pStream.match(wordRegexp(pConfig.constants), true, true)) - return "variable"; - - /* attribute lists */ - if (!pConfig.inAttributeList && !!pConfig.attributes && pStream.match(/\[/, true, true)) { - pConfig.inAttributeList = true; - return "bracket"; - } - if (pConfig.inAttributeList) { - if (pConfig.attributes !== null && pStream.match(wordRegexpBoundary(pConfig.attributes), true, true)) { - return "attribute"; - } - if (pStream.match(/]/, true, true)) { - pConfig.inAttributeList = false; - return "bracket"; - } - } - - pStream.next(); - return "base"; - }; - } - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/mscgen/mscgen_test.js b/backend/_pv_1_3_5/static/codemirror/mode/mscgen/mscgen_test.js deleted file mode 100755 index 956c5758e..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/mscgen/mscgen_test.js +++ /dev/null @@ -1,83 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "mscgen"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT("empty chart", - "[keyword msc][bracket {]", - "[base ]", - "[bracket }]" - ); - - MT("comments", - "[comment // a single line comment]", - "[comment # another single line comment /* and */ ignored here]", - "[comment /* A multi-line comment even though it contains]", - "[comment msc keywords and \"quoted text\"*/]"); - - MT("strings", - "[string \"// a string\"]", - "[string \"a string running over]", - "[string two lines\"]", - "[string \"with \\\"escaped quote\"]" - ); - - MT("xù/ msgenny keywords classify as 'base'", - "[base watermark]", - "[base alt loop opt ref else break par seq assert]" - ); - - MT("xù/ msgenny constants classify as 'base'", - "[base auto]" - ); - - MT("mscgen constants classify as 'variable'", - "[variable true]", "[variable false]", "[variable on]", "[variable off]" - ); - - MT("mscgen options classify as keyword", - "[keyword hscale]", "[keyword width]", "[keyword arcgradient]", "[keyword wordwraparcs]" - ); - - MT("mscgen arcs classify as keyword", - "[keyword note]","[keyword abox]","[keyword rbox]","[keyword box]", - "[keyword |||...---]", "[keyword ..--==::]", - "[keyword ->]", "[keyword <-]", "[keyword <->]", - "[keyword =>]", "[keyword <=]", "[keyword <=>]", - "[keyword =>>]", "[keyword <<=]", "[keyword <<=>>]", - "[keyword >>]", "[keyword <<]", "[keyword <<>>]", - "[keyword -x]", "[keyword x-]", "[keyword -X]", "[keyword X-]", - "[keyword :>]", "[keyword <:]", "[keyword <:>]" - ); - - MT("within an attribute list, attributes classify as attribute", - "[bracket [[][attribute label]", - "[attribute id]","[attribute url]","[attribute idurl]", - "[attribute linecolor]","[attribute linecolour]","[attribute textcolor]","[attribute textcolour]","[attribute textbgcolor]","[attribute textbgcolour]", - "[attribute arclinecolor]","[attribute arclinecolour]","[attribute arctextcolor]","[attribute arctextcolour]","[attribute arctextbgcolor]","[attribute arctextbgcolour]", - "[attribute arcskip][bracket ]]]" - ); - - MT("outside an attribute list, attributes classify as base", - "[base label]", - "[base id]","[base url]","[base idurl]", - "[base linecolor]","[base linecolour]","[base textcolor]","[base textcolour]","[base textbgcolor]","[base textbgcolour]", - "[base arclinecolor]","[base arclinecolour]","[base arctextcolor]","[base arctextcolour]","[base arctextbgcolor]","[base arctextbgcolour]", - "[base arcskip]" - ); - - MT("a typical program", - "[comment # typical mscgen program]", - "[keyword msc][base ][bracket {]", - "[keyword wordwraparcs][operator =][variable true][base , ][keyword hscale][operator =][string \"0.8\"][base , ][keyword arcgradient][operator =][base 30;]", - "[base a][bracket [[][attribute label][operator =][string \"Entity A\"][bracket ]]][base ,]", - "[base b][bracket [[][attribute label][operator =][string \"Entity B\"][bracket ]]][base ,]", - "[base c][bracket [[][attribute label][operator =][string \"Entity C\"][bracket ]]][base ;]", - "[base a ][keyword =>>][base b][bracket [[][attribute label][operator =][string \"Hello entity B\"][bracket ]]][base ;]", - "[base a ][keyword <<][base b][bracket [[][attribute label][operator =][string \"Here's an answer dude!\"][bracket ]]][base ;]", - "[base c ][keyword :>][base *][bracket [[][attribute label][operator =][string \"What about me?\"][base , ][attribute textcolor][operator =][base red][bracket ]]][base ;]", - "[bracket }]" - ); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/mscgen/msgenny_test.js b/backend/_pv_1_3_5/static/codemirror/mode/mscgen/msgenny_test.js deleted file mode 100755 index edf9da09a..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/mscgen/msgenny_test.js +++ /dev/null @@ -1,76 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-msgenny"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "msgenny"); } - - MT("comments", - "[comment // a single line comment]", - "[comment # another single line comment /* and */ ignored here]", - "[comment /* A multi-line comment even though it contains]", - "[comment msc keywords and \"quoted text\"*/]"); - - MT("strings", - "[string \"// a string\"]", - "[string \"a string running over]", - "[string two lines\"]", - "[string \"with \\\"escaped quote\"]" - ); - - MT("xù/ msgenny keywords classify as 'keyword'", - "[keyword watermark]", - "[keyword alt]","[keyword loop]","[keyword opt]","[keyword ref]","[keyword else]","[keyword break]","[keyword par]","[keyword seq]","[keyword assert]" - ); - - MT("xù/ msgenny constants classify as 'variable'", - "[variable auto]", - "[variable true]", "[variable false]", "[variable on]", "[variable off]" - ); - - MT("mscgen options classify as keyword", - "[keyword hscale]", "[keyword width]", "[keyword arcgradient]", "[keyword wordwraparcs]" - ); - - MT("mscgen arcs classify as keyword", - "[keyword note]","[keyword abox]","[keyword rbox]","[keyword box]", - "[keyword |||...---]", "[keyword ..--==::]", - "[keyword ->]", "[keyword <-]", "[keyword <->]", - "[keyword =>]", "[keyword <=]", "[keyword <=>]", - "[keyword =>>]", "[keyword <<=]", "[keyword <<=>>]", - "[keyword >>]", "[keyword <<]", "[keyword <<>>]", - "[keyword -x]", "[keyword x-]", "[keyword -X]", "[keyword X-]", - "[keyword :>]", "[keyword <:]", "[keyword <:>]" - ); - - MT("within an attribute list, mscgen/ xù attributes classify as base", - "[base [[label]", - "[base idurl id url]", - "[base linecolor linecolour textcolor textcolour textbgcolor textbgcolour]", - "[base arclinecolor arclinecolour arctextcolor arctextcolour arctextbgcolor arctextbgcolour]", - "[base arcskip]]]" - ); - - MT("outside an attribute list, mscgen/ xù attributes classify as base", - "[base label]", - "[base idurl id url]", - "[base linecolor linecolour textcolor textcolour textbgcolor textbgcolour]", - "[base arclinecolor arclinecolour arctextcolor arctextcolour arctextbgcolor arctextbgcolour]", - "[base arcskip]" - ); - - MT("a typical program", - "[comment # typical msgenny program]", - "[keyword wordwraparcs][operator =][variable true][base , ][keyword hscale][operator =][string \"0.8\"][base , ][keyword arcgradient][operator =][base 30;]", - "[base a : ][string \"Entity A\"][base ,]", - "[base b : Entity B,]", - "[base c : Entity C;]", - "[base a ][keyword =>>][base b: ][string \"Hello entity B\"][base ;]", - "[base a ][keyword alt][base c][bracket {]", - "[base a ][keyword <<][base b: ][string \"Here's an answer dude!\"][base ;]", - "[keyword ---][base : ][string \"sorry, won't march - comm glitch\"]", - "[base a ][keyword x-][base b: ][string \"Here's an answer dude! (won't arrive...)\"][base ;]", - "[bracket }]", - "[base c ][keyword :>][base *: What about me?;]" - ); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/mscgen/xu_test.js b/backend/_pv_1_3_5/static/codemirror/mode/mscgen/xu_test.js deleted file mode 100755 index 950aeca1f..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/mscgen/xu_test.js +++ /dev/null @@ -1,86 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-xu"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "xu"); } - - MT("empty chart", - "[keyword msc][bracket {]", - "[base ]", - "[bracket }]" - ); - - MT("empty chart", - "[keyword xu][bracket {]", - "[base ]", - "[bracket }]" - ); - - MT("comments", - "[comment // a single line comment]", - "[comment # another single line comment /* and */ ignored here]", - "[comment /* A multi-line comment even though it contains]", - "[comment msc keywords and \"quoted text\"*/]"); - - MT("strings", - "[string \"// a string\"]", - "[string \"a string running over]", - "[string two lines\"]", - "[string \"with \\\"escaped quote\"]" - ); - - MT("xù/ msgenny keywords classify as 'keyword'", - "[keyword watermark]", - "[keyword alt]","[keyword loop]","[keyword opt]","[keyword ref]","[keyword else]","[keyword break]","[keyword par]","[keyword seq]","[keyword assert]" - ); - - MT("xù/ msgenny constants classify as 'variable'", - "[variable auto]", - "[variable true]", "[variable false]", "[variable on]", "[variable off]" - ); - - MT("mscgen options classify as keyword", - "[keyword hscale]", "[keyword width]", "[keyword arcgradient]", "[keyword wordwraparcs]" - ); - - MT("mscgen arcs classify as keyword", - "[keyword note]","[keyword abox]","[keyword rbox]","[keyword box]", - "[keyword |||...---]", "[keyword ..--==::]", - "[keyword ->]", "[keyword <-]", "[keyword <->]", - "[keyword =>]", "[keyword <=]", "[keyword <=>]", - "[keyword =>>]", "[keyword <<=]", "[keyword <<=>>]", - "[keyword >>]", "[keyword <<]", "[keyword <<>>]", - "[keyword -x]", "[keyword x-]", "[keyword -X]", "[keyword X-]", - "[keyword :>]", "[keyword <:]", "[keyword <:>]" - ); - - MT("within an attribute list, attributes classify as attribute", - "[bracket [[][attribute label]", - "[attribute id]","[attribute url]","[attribute idurl]", - "[attribute linecolor]","[attribute linecolour]","[attribute textcolor]","[attribute textcolour]","[attribute textbgcolor]","[attribute textbgcolour]", - "[attribute arclinecolor]","[attribute arclinecolour]","[attribute arctextcolor]","[attribute arctextcolour]","[attribute arctextbgcolor]","[attribute arctextbgcolour]", - "[attribute arcskip][bracket ]]]" - ); - - MT("outside an attribute list, attributes classify as base", - "[base label]", - "[base id]","[base url]","[base idurl]", - "[base linecolor]","[base linecolour]","[base textcolor]","[base textcolour]","[base textbgcolor]","[base textbgcolour]", - "[base arclinecolor]","[base arclinecolour]","[base arctextcolor]","[base arctextcolour]","[base arctextbgcolor]","[base arctextbgcolour]", - "[base arcskip]" - ); - - MT("a typical program", - "[comment # typical xu program]", - "[keyword xu][base ][bracket {]", - "[keyword wordwraparcs][operator =][string \"true\"][base , ][keyword hscale][operator =][string \"0.8\"][base , ][keyword arcgradient][operator =][base 30, ][keyword width][operator =][variable auto][base ;]", - "[base a][bracket [[][attribute label][operator =][string \"Entity A\"][bracket ]]][base ,]", - "[base b][bracket [[][attribute label][operator =][string \"Entity B\"][bracket ]]][base ,]", - "[base c][bracket [[][attribute label][operator =][string \"Entity C\"][bracket ]]][base ;]", - "[base a ][keyword =>>][base b][bracket [[][attribute label][operator =][string \"Hello entity B\"][bracket ]]][base ;]", - "[base a ][keyword <<][base b][bracket [[][attribute label][operator =][string \"Here's an answer dude!\"][bracket ]]][base ;]", - "[base c ][keyword :>][base *][bracket [[][attribute label][operator =][string \"What about me?\"][base , ][attribute textcolor][operator =][base red][bracket ]]][base ;]", - "[bracket }]" - ); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/mumps/index.html b/backend/_pv_1_3_5/static/codemirror/mode/mumps/index.html deleted file mode 100755 index b1f92c213..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/mumps/index.html +++ /dev/null @@ -1,85 +0,0 @@ - - -CodeMirror: MUMPS mode - - - - - - - - - -
    -

    MUMPS mode

    - - -
    - - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/mumps/mumps.js b/backend/_pv_1_3_5/static/codemirror/mode/mumps/mumps.js deleted file mode 100755 index 469f8c3d1..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/mumps/mumps.js +++ /dev/null @@ -1,148 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/* - This MUMPS Language script was constructed using vbscript.js as a template. -*/ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("mumps", function() { - function wordRegexp(words) { - return new RegExp("^((" + words.join(")|(") + "))\\b", "i"); - } - - var singleOperators = new RegExp("^[\\+\\-\\*/&#!_?\\\\<>=\\'\\[\\]]"); - var doubleOperators = new RegExp("^(('=)|(<=)|(>=)|('>)|('<)|([[)|(]])|(^$))"); - var singleDelimiters = new RegExp("^[\\.,:]"); - var brackets = new RegExp("[()]"); - var identifiers = new RegExp("^[%A-Za-z][A-Za-z0-9]*"); - var commandKeywords = ["break","close","do","else","for","goto", "halt", "hang", "if", "job","kill","lock","merge","new","open", "quit", "read", "set", "tcommit", "trollback", "tstart", "use", "view", "write", "xecute", "b","c","d","e","f","g", "h", "i", "j","k","l","m","n","o", "q", "r", "s", "tc", "tro", "ts", "u", "v", "w", "x"]; - // The following list includes instrinsic functions _and_ special variables - var intrinsicFuncsWords = ["\\$ascii", "\\$char", "\\$data", "\\$ecode", "\\$estack", "\\$etrap", "\\$extract", "\\$find", "\\$fnumber", "\\$get", "\\$horolog", "\\$io", "\\$increment", "\\$job", "\\$justify", "\\$length", "\\$name", "\\$next", "\\$order", "\\$piece", "\\$qlength", "\\$qsubscript", "\\$query", "\\$quit", "\\$random", "\\$reverse", "\\$select", "\\$stack", "\\$test", "\\$text", "\\$translate", "\\$view", "\\$x", "\\$y", "\\$a", "\\$c", "\\$d", "\\$e", "\\$ec", "\\$es", "\\$et", "\\$f", "\\$fn", "\\$g", "\\$h", "\\$i", "\\$j", "\\$l", "\\$n", "\\$na", "\\$o", "\\$p", "\\$q", "\\$ql", "\\$qs", "\\$r", "\\$re", "\\$s", "\\$st", "\\$t", "\\$tr", "\\$v", "\\$z"]; - var intrinsicFuncs = wordRegexp(intrinsicFuncsWords); - var command = wordRegexp(commandKeywords); - - function tokenBase(stream, state) { - if (stream.sol()) { - state.label = true; - state.commandMode = 0; - } - - // The character has meaning in MUMPS. Ignoring consecutive - // spaces would interfere with interpreting whether the next non-space - // character belongs to the command or argument context. - - // Examine each character and update a mode variable whose interpretation is: - // >0 => command 0 => argument <0 => command post-conditional - var ch = stream.peek(); - - if (ch == " " || ch == "\t") { // Pre-process - state.label = false; - if (state.commandMode == 0) - state.commandMode = 1; - else if ((state.commandMode < 0) || (state.commandMode == 2)) - state.commandMode = 0; - } else if ((ch != ".") && (state.commandMode > 0)) { - if (ch == ":") - state.commandMode = -1; // SIS - Command post-conditional - else - state.commandMode = 2; - } - - // Do not color parameter list as line tag - if ((ch === "(") || (ch === "\u0009")) - state.label = false; - - // MUMPS comment starts with ";" - if (ch === ";") { - stream.skipToEnd(); - return "comment"; - } - - // Number Literals // SIS/RLM - MUMPS permits canonic number followed by concatenate operator - if (stream.match(/^[-+]?\d+(\.\d+)?([eE][-+]?\d+)?/)) - return "number"; - - // Handle Strings - if (ch == '"') { - if (stream.skipTo('"')) { - stream.next(); - return "string"; - } else { - stream.skipToEnd(); - return "error"; - } - } - - // Handle operators and Delimiters - if (stream.match(doubleOperators) || stream.match(singleOperators)) - return "operator"; - - // Prevents leading "." in DO block from falling through to error - if (stream.match(singleDelimiters)) - return null; - - if (brackets.test(ch)) { - stream.next(); - return "bracket"; - } - - if (state.commandMode > 0 && stream.match(command)) - return "variable-2"; - - if (stream.match(intrinsicFuncs)) - return "builtin"; - - if (stream.match(identifiers)) - return "variable"; - - // Detect dollar-sign when not a documented intrinsic function - // "^" may introduce a GVN or SSVN - Color same as function - if (ch === "$" || ch === "^") { - stream.next(); - return "builtin"; - } - - // MUMPS Indirection - if (ch === "@") { - stream.next(); - return "string-2"; - } - - if (/[\w%]/.test(ch)) { - stream.eatWhile(/[\w%]/); - return "variable"; - } - - // Handle non-detected items - stream.next(); - return "error"; - } - - return { - startState: function() { - return { - label: false, - commandMode: 0 - }; - }, - - token: function(stream, state) { - var style = tokenBase(stream, state); - if (state.label) return "tag"; - return style; - } - }; - }); - - CodeMirror.defineMIME("text/x-mumps", "mumps"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/nginx/index.html b/backend/_pv_1_3_5/static/codemirror/mode/nginx/index.html deleted file mode 100755 index 03cf67149..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/nginx/index.html +++ /dev/null @@ -1,181 +0,0 @@ - - -CodeMirror: NGINX mode - - - - - - - - - - - - - -
    -

    NGINX mode

    -
    - - -

    MIME types defined: text/nginx.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/nginx/nginx.js b/backend/_pv_1_3_5/static/codemirror/mode/nginx/nginx.js deleted file mode 100755 index 00a322492..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/nginx/nginx.js +++ /dev/null @@ -1,178 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("nginx", function(config) { - - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - var keywords = words( - /* ngxDirectiveControl */ "break return rewrite set" + - /* ngxDirective */ " accept_mutex accept_mutex_delay access_log add_after_body add_before_body add_header addition_types aio alias allow ancient_browser ancient_browser_value auth_basic auth_basic_user_file auth_http auth_http_header auth_http_timeout autoindex autoindex_exact_size autoindex_localtime charset charset_types client_body_buffer_size client_body_in_file_only client_body_in_single_buffer client_body_temp_path client_body_timeout client_header_buffer_size client_header_timeout client_max_body_size connection_pool_size create_full_put_path daemon dav_access dav_methods debug_connection debug_points default_type degradation degrade deny devpoll_changes devpoll_events directio directio_alignment empty_gif env epoll_events error_log eventport_events expires fastcgi_bind fastcgi_buffer_size fastcgi_buffers fastcgi_busy_buffers_size fastcgi_cache fastcgi_cache_key fastcgi_cache_methods fastcgi_cache_min_uses fastcgi_cache_path fastcgi_cache_use_stale fastcgi_cache_valid fastcgi_catch_stderr fastcgi_connect_timeout fastcgi_hide_header fastcgi_ignore_client_abort fastcgi_ignore_headers fastcgi_index fastcgi_intercept_errors fastcgi_max_temp_file_size fastcgi_next_upstream fastcgi_param fastcgi_pass_header fastcgi_pass_request_body fastcgi_pass_request_headers fastcgi_read_timeout fastcgi_send_lowat fastcgi_send_timeout fastcgi_split_path_info fastcgi_store fastcgi_store_access fastcgi_temp_file_write_size fastcgi_temp_path fastcgi_upstream_fail_timeout fastcgi_upstream_max_fails flv geoip_city geoip_country google_perftools_profiles gzip gzip_buffers gzip_comp_level gzip_disable gzip_hash gzip_http_version gzip_min_length gzip_no_buffer gzip_proxied gzip_static gzip_types gzip_vary gzip_window if_modified_since ignore_invalid_headers image_filter image_filter_buffer image_filter_jpeg_quality image_filter_transparency imap_auth imap_capabilities imap_client_buffer index ip_hash keepalive_requests keepalive_timeout kqueue_changes kqueue_events large_client_header_buffers limit_conn limit_conn_log_level limit_rate limit_rate_after limit_req limit_req_log_level limit_req_zone limit_zone lingering_time lingering_timeout lock_file log_format log_not_found log_subrequest map_hash_bucket_size map_hash_max_size master_process memcached_bind memcached_buffer_size memcached_connect_timeout memcached_next_upstream memcached_read_timeout memcached_send_timeout memcached_upstream_fail_timeout memcached_upstream_max_fails merge_slashes min_delete_depth modern_browser modern_browser_value msie_padding msie_refresh multi_accept open_file_cache open_file_cache_errors open_file_cache_events open_file_cache_min_uses open_file_cache_valid open_log_file_cache output_buffers override_charset perl perl_modules perl_require perl_set pid pop3_auth pop3_capabilities port_in_redirect postpone_gzipping postpone_output protocol proxy proxy_bind proxy_buffer proxy_buffer_size proxy_buffering proxy_buffers proxy_busy_buffers_size proxy_cache proxy_cache_key proxy_cache_methods proxy_cache_min_uses proxy_cache_path proxy_cache_use_stale proxy_cache_valid proxy_connect_timeout proxy_headers_hash_bucket_size proxy_headers_hash_max_size proxy_hide_header proxy_ignore_client_abort proxy_ignore_headers proxy_intercept_errors proxy_max_temp_file_size proxy_method proxy_next_upstream proxy_pass_error_message proxy_pass_header proxy_pass_request_body proxy_pass_request_headers proxy_read_timeout proxy_redirect proxy_send_lowat proxy_send_timeout proxy_set_body proxy_set_header proxy_ssl_session_reuse proxy_store proxy_store_access proxy_temp_file_write_size proxy_temp_path proxy_timeout proxy_upstream_fail_timeout proxy_upstream_max_fails random_index read_ahead real_ip_header recursive_error_pages request_pool_size reset_timedout_connection resolver resolver_timeout rewrite_log rtsig_overflow_events rtsig_overflow_test rtsig_overflow_threshold rtsig_signo satisfy secure_link_secret send_lowat send_timeout sendfile sendfile_max_chunk server_name_in_redirect server_names_hash_bucket_size server_names_hash_max_size server_tokens set_real_ip_from smtp_auth smtp_capabilities smtp_client_buffer smtp_greeting_delay so_keepalive source_charset ssi ssi_ignore_recycled_buffers ssi_min_file_chunk ssi_silent_errors ssi_types ssi_value_length ssl ssl_certificate ssl_certificate_key ssl_ciphers ssl_client_certificate ssl_crl ssl_dhparam ssl_engine ssl_prefer_server_ciphers ssl_protocols ssl_session_cache ssl_session_timeout ssl_verify_client ssl_verify_depth starttls stub_status sub_filter sub_filter_once sub_filter_types tcp_nodelay tcp_nopush thread_stack_size timeout timer_resolution types_hash_bucket_size types_hash_max_size underscores_in_headers uninitialized_variable_warn use user userid userid_domain userid_expires userid_mark userid_name userid_p3p userid_path userid_service valid_referers variables_hash_bucket_size variables_hash_max_size worker_connections worker_cpu_affinity worker_priority worker_processes worker_rlimit_core worker_rlimit_nofile worker_rlimit_sigpending worker_threads working_directory xclient xml_entities xslt_stylesheet xslt_typesdrew@li229-23" - ); - - var keywords_block = words( - /* ngxDirectiveBlock */ "http mail events server types location upstream charset_map limit_except if geo map" - ); - - var keywords_important = words( - /* ngxDirectiveImportant */ "include root server server_name listen internal proxy_pass memcached_pass fastcgi_pass try_files" - ); - - var indentUnit = config.indentUnit, type; - function ret(style, tp) {type = tp; return style;} - - function tokenBase(stream, state) { - - - stream.eatWhile(/[\w\$_]/); - - var cur = stream.current(); - - - if (keywords.propertyIsEnumerable(cur)) { - return "keyword"; - } - else if (keywords_block.propertyIsEnumerable(cur)) { - return "variable-2"; - } - else if (keywords_important.propertyIsEnumerable(cur)) { - return "string-2"; - } - /**/ - - var ch = stream.next(); - if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("meta", stream.current());} - else if (ch == "/" && stream.eat("*")) { - state.tokenize = tokenCComment; - return tokenCComment(stream, state); - } - else if (ch == "<" && stream.eat("!")) { - state.tokenize = tokenSGMLComment; - return tokenSGMLComment(stream, state); - } - else if (ch == "=") ret(null, "compare"); - else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare"); - else if (ch == "\"" || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - else if (ch == "#") { - stream.skipToEnd(); - return ret("comment", "comment"); - } - else if (ch == "!") { - stream.match(/^\s*\w*/); - return ret("keyword", "important"); - } - else if (/\d/.test(ch)) { - stream.eatWhile(/[\w.%]/); - return ret("number", "unit"); - } - else if (/[,.+>*\/]/.test(ch)) { - return ret(null, "select-op"); - } - else if (/[;{}:\[\]]/.test(ch)) { - return ret(null, ch); - } - else { - stream.eatWhile(/[\w\\\-]/); - return ret("variable", "variable"); - } - } - - function tokenCComment(stream, state) { - var maybeEnd = false, ch; - while ((ch = stream.next()) != null) { - if (maybeEnd && ch == "/") { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return ret("comment", "comment"); - } - - function tokenSGMLComment(stream, state) { - var dashes = 0, ch; - while ((ch = stream.next()) != null) { - if (dashes >= 2 && ch == ">") { - state.tokenize = tokenBase; - break; - } - dashes = (ch == "-") ? dashes + 1 : 0; - } - return ret("comment", "comment"); - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) - break; - escaped = !escaped && ch == "\\"; - } - if (!escaped) state.tokenize = tokenBase; - return ret("string", "string"); - }; - } - - return { - startState: function(base) { - return {tokenize: tokenBase, - baseIndent: base || 0, - stack: []}; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - type = null; - var style = state.tokenize(stream, state); - - var context = state.stack[state.stack.length-1]; - if (type == "hash" && context == "rule") style = "atom"; - else if (style == "variable") { - if (context == "rule") style = "number"; - else if (!context || context == "@media{") style = "tag"; - } - - if (context == "rule" && /^[\{\};]$/.test(type)) - state.stack.pop(); - if (type == "{") { - if (context == "@media") state.stack[state.stack.length-1] = "@media{"; - else state.stack.push("{"); - } - else if (type == "}") state.stack.pop(); - else if (type == "@media") state.stack.push("@media"); - else if (context == "{" && type != "comment") state.stack.push("rule"); - return style; - }, - - indent: function(state, textAfter) { - var n = state.stack.length; - if (/^\}/.test(textAfter)) - n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1; - return state.baseIndent + n * indentUnit; - }, - - electricChars: "}" - }; -}); - -CodeMirror.defineMIME("text/x-nginx-conf", "nginx"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/nsis/index.html b/backend/_pv_1_3_5/static/codemirror/mode/nsis/index.html deleted file mode 100755 index 2afae87f0..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/nsis/index.html +++ /dev/null @@ -1,80 +0,0 @@ - - -CodeMirror: NSIS mode - - - - - - - - - - - -
    -

    NSIS mode

    - - - - - - -

    MIME types defined: text/x-nsis.

    -
    \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/codemirror/mode/nsis/nsis.js b/backend/_pv_1_3_5/static/codemirror/mode/nsis/nsis.js deleted file mode 100755 index dc8c74cdf..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/nsis/nsis.js +++ /dev/null @@ -1,95 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Author: Jan T. Sott (http://github.com/idleberg) - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../../addon/mode/simple")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../../addon/mode/simple"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineSimpleMode("nsis",{ - start:[ - // Numbers - {regex: /(?:[+-]?)(?:0x[\d,a-f]+)|(?:0o[0-7]+)|(?:0b[0,1]+)|(?:\d+.?\d*)/, token: "number"}, - - // Strings - { regex: /"(?:[^\\"]|\\.)*"?/, token: "string" }, - { regex: /'(?:[^\\']|\\.)*'?/, token: "string" }, - { regex: /`(?:[^\\`]|\\.)*`?/, token: "string" }, - - // Compile Time Commands - {regex: /^\s*(?:\!(include|addincludedir|addplugindir|appendfile|cd|delfile|echo|error|execute|packhdr|finalize|getdllversion|system|tempfile|warning|verbose|define|undef|insertmacro|makensis|searchparse|searchreplace))\b/, token: "keyword"}, - - // Conditional Compilation - {regex: /^\s*(?:\!(if(?:n?def)?|ifmacron?def|macro))\b/, token: "keyword", indent: true}, - {regex: /^\s*(?:\!(else|endif|macroend))\b/, token: "keyword", dedent: true}, - - // Runtime Commands - {regex: /^\s*(?:Abort|AddBrandingImage|AddSize|AllowRootDirInstall|AllowSkipFiles|AutoCloseWindow|BGFont|BGGradient|BrandingText|BringToFront|Call|CallInstDLL|Caption|ChangeUI|CheckBitmap|ClearErrors|CompletedText|ComponentText|CopyFiles|CRCCheck|CreateDirectory|CreateFont|CreateShortCut|Delete|DeleteINISec|DeleteINIStr|DeleteRegKey|DeleteRegValue|DetailPrint|DetailsButtonText|DirText|DirVar|DirVerify|EnableWindow|EnumRegKey|EnumRegValue|Exch|Exec|ExecShell|ExecWait|ExpandEnvStrings|File|FileBufSize|FileClose|FileErrorText|FileOpen|FileRead|FileReadByte|FileReadUTF16LE|FileReadWord|FileWriteUTF16LE|FileSeek|FileWrite|FileWriteByte|FileWriteWord|FindClose|FindFirst|FindNext|FindWindow|FlushINI|GetCurInstType|GetCurrentAddress|GetDlgItem|GetDLLVersion|GetDLLVersionLocal|GetErrorLevel|GetFileTime|GetFileTimeLocal|GetFullPathName|GetFunctionAddress|GetInstDirError|GetLabelAddress|GetTempFileName|Goto|HideWindow|Icon|IfAbort|IfErrors|IfFileExists|IfRebootFlag|IfSilent|InitPluginsDir|InstallButtonText|InstallColors|InstallDir|InstallDirRegKey|InstProgressFlags|InstType|InstTypeGetText|InstTypeSetText|IntCmp|IntCmpU|IntFmt|IntOp|IsWindow|LangString|LicenseBkColor|LicenseData|LicenseForceSelection|LicenseLangString|LicenseText|LoadLanguageFile|LockWindow|LogSet|LogText|ManifestDPIAware|ManifestSupportedOS|MessageBox|MiscButtonText|Name|Nop|OutFile|Page|PageCallbacks|Pop|Push|Quit|ReadEnvStr|ReadINIStr|ReadRegDWORD|ReadRegStr|Reboot|RegDLL|Rename|RequestExecutionLevel|ReserveFile|Return|RMDir|SearchPath|SectionGetFlags|SectionGetInstTypes|SectionGetSize|SectionGetText|SectionIn|SectionSetFlags|SectionSetInstTypes|SectionSetSize|SectionSetText|SendMessage|SetAutoClose|SetBrandingImage|SetCompress|SetCompressor|SetCompressorDictSize|SetCtlColors|SetCurInstType|SetDatablockOptimize|SetDateSave|SetDetailsPrint|SetDetailsView|SetErrorLevel|SetErrors|SetFileAttributes|SetFont|SetOutPath|SetOverwrite|SetRebootFlag|SetRegView|SetShellVarContext|SetSilent|ShowInstDetails|ShowUninstDetails|ShowWindow|SilentInstall|SilentUnInstall|Sleep|SpaceTexts|StrCmp|StrCmpS|StrCpy|StrLen|SubCaption|Unicode|UninstallButtonText|UninstallCaption|UninstallIcon|UninstallSubCaption|UninstallText|UninstPage|UnRegDLL|Var|VIAddVersionKey|VIFileVersion|VIProductVersion|WindowIcon|WriteINIStr|WriteRegBin|WriteRegDWORD|WriteRegExpandStr|WriteRegStr|WriteUninstaller|XPStyle)\b/, token: "keyword"}, - {regex: /^\s*(?:Function|PageEx|Section(?:Group)?)\b/, token: "keyword", indent: true}, - {regex: /^\s*(?:(Function|PageEx|Section(?:Group)?)End)\b/, token: "keyword", dedent: true}, - - // Command Options - {regex: /\b(?:ARCHIVE|FILE_ATTRIBUTE_ARCHIVE|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_NORMAL|FILE_ATTRIBUTE_OFFLINE|FILE_ATTRIBUTE_READONLY|FILE_ATTRIBUTE_SYSTEM|FILE_ATTRIBUTE_TEMPORARY|HIDDEN|HKCC|HKCR|HKCU|HKDD|HKEY_CLASSES_ROOT|HKEY_CURRENT_CONFIG|HKEY_CURRENT_USER|HKEY_DYN_DATA|HKEY_LOCAL_MACHINE|HKEY_PERFORMANCE_DATA|HKEY_USERS|HKLM|HKPD|HKU|IDABORT|IDCANCEL|IDD_DIR|IDD_INST|IDD_INSTFILES|IDD_LICENSE|IDD_SELCOM|IDD_UNINST|IDD_VERIFY|IDIGNORE|IDNO|IDOK|IDRETRY|IDYES|MB_ABORTRETRYIGNORE|MB_DEFBUTTON1|MB_DEFBUTTON2|MB_DEFBUTTON3|MB_DEFBUTTON4|MB_ICONEXCLAMATION|MB_ICONINFORMATION|MB_ICONQUESTION|MB_ICONSTOP|MB_OK|MB_OKCANCEL|MB_RETRYCANCEL|MB_RIGHT|MB_RTLREADING|MB_SETFOREGROUND|MB_TOPMOST|MB_USERICON|MB_YESNO|MB_YESNOCANCEL|NORMAL|OFFLINE|READONLY|SHCTX|SHELL_CONTEXT|SW_HIDE|SW_SHOWDEFAULT|SW_SHOWMAXIMIZED|SW_SHOWMINIMIZED|SW_SHOWNORMAL|SYSTEM|TEMPORARY)\b/, token: "atom"}, - {regex: /\b(?:admin|all|auto|both|bottom|bzip2|components|current|custom|directory|force|hide|highest|ifdiff|ifnewer|instfiles|lastused|leave|left|license|listonly|lzma|nevershow|none|normal|notset|right|show|silent|silentlog|textonly|top|try|un\.components|un\.custom|un\.directory|un\.instfiles|un\.license|uninstConfirm|user|Win10|Win7|Win8|WinVista|zlib)\b/, token: "builtin"}, - - // LogicLib.nsh - {regex: /\$\{(?:And(?:If(?:Not)?|Unless)|Break|Case(?:Else)?|Continue|Default|Do(?:Until|While)?|Else(?:If(?:Not)?|Unless)?|End(?:If|Select|Switch)|Exit(?:Do|For|While)|For(?:Each)?|If(?:Cmd|Not(?:Then)?|Then)?|Loop(?:Until|While)?|Or(?:If(?:Not)?|Unless)|Select|Switch|Unless|While)\}/, token: "variable-2", indent: true}, - - // FileFunc.nsh - {regex: /\$\{(?:BannerTrimPath|DirState|DriveSpace|Get(BaseName|Drives|ExeName|ExePath|FileAttributes|FileExt|FileName|FileVersion|Options|OptionsS|Parameters|Parent|Root|Size|Time)|Locate|RefreshShellIcons)\}/, token: "variable-2", dedent: true}, - - // Memento.nsh - {regex: /\$\{(?:Memento(?:Section(?:Done|End|Restore|Save)?|UnselectedSection))\}/, token: "variable-2", dedent: true}, - - // TextFunc.nsh - {regex: /\$\{(?:Config(?:Read|ReadS|Write|WriteS)|File(?:Join|ReadFromEnd|Recode)|Line(?:Find|Read|Sum)|Text(?:Compare|CompareS)|TrimNewLines)\}/, token: "variable-2", dedent: true}, - - // WinVer.nsh - {regex: /\$\{(?:(?:At(?:Least|Most)|Is)(?:ServicePack|Win(?:7|8|10|95|98|200(?:0|3|8(?:R2)?)|ME|NT4|Vista|XP))|Is(?:NT|Server))\}/, token: "variable", dedent: true}, - - // WordFunc.nsh - {regex: /\$\{(?:StrFilterS?|Version(?:Compare|Convert)|Word(?:AddS?|Find(?:(?:2|3)X)?S?|InsertS?|ReplaceS?))\}/, token: "variable-2", dedent: true}, - - // x64.nsh - {regex: /\$\{(?:RunningX64)\}/, token: "variable", dedent: true}, - {regex: /\$\{(?:Disable|Enable)X64FSRedirection\}/, token: "variable-2", dedent: true}, - - // Line Comment - {regex: /(#|;).*/, token: "comment"}, - - // Block Comment - {regex: /\/\*/, token: "comment", next: "comment"}, - - // Operator - {regex: /[-+\/*=<>!]+/, token: "operator"}, - - // Variable - {regex: /\$\w+/, token: "variable"}, - - // Constant - {regex: /\${[\w\.:-]+}/, token: "variable-2"}, - - // Language String - {regex: /\$\([\w\.:-]+\)/, token: "variable-3"} - ], - comment: [ - {regex: /.*?\*\//, token: "comment", next: "start"}, - {regex: /.*/, token: "comment"} - ], - meta: { - electricInput: /^\s*((Function|PageEx|Section|Section(Group)?)End|(\!(endif|macroend))|\$\{(End(If|Unless|While)|Loop(Until)|Next)\})$/, - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: ["#", ";"] - } -}); - -CodeMirror.defineMIME("text/x-nsis", "nsis"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/ntriples/index.html b/backend/_pv_1_3_5/static/codemirror/mode/ntriples/index.html deleted file mode 100755 index 1355e7189..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/ntriples/index.html +++ /dev/null @@ -1,45 +0,0 @@ - - -CodeMirror: NTriples mode - - - - - - - - - -
    -

    NTriples mode

    -
    - -
    - - -

    MIME types defined: text/n-triples.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/ntriples/ntriples.js b/backend/_pv_1_3_5/static/codemirror/mode/ntriples/ntriples.js deleted file mode 100755 index 0524b1e8a..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/ntriples/ntriples.js +++ /dev/null @@ -1,186 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/********************************************************** -* This script provides syntax highlighting support for -* the Ntriples format. -* Ntriples format specification: -* http://www.w3.org/TR/rdf-testcases/#ntriples -***********************************************************/ - -/* - The following expression defines the defined ASF grammar transitions. - - pre_subject -> - { - ( writing_subject_uri | writing_bnode_uri ) - -> pre_predicate - -> writing_predicate_uri - -> pre_object - -> writing_object_uri | writing_object_bnode | - ( - writing_object_literal - -> writing_literal_lang | writing_literal_type - ) - -> post_object - -> BEGIN - } otherwise { - -> ERROR - } -*/ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("ntriples", function() { - - var Location = { - PRE_SUBJECT : 0, - WRITING_SUB_URI : 1, - WRITING_BNODE_URI : 2, - PRE_PRED : 3, - WRITING_PRED_URI : 4, - PRE_OBJ : 5, - WRITING_OBJ_URI : 6, - WRITING_OBJ_BNODE : 7, - WRITING_OBJ_LITERAL : 8, - WRITING_LIT_LANG : 9, - WRITING_LIT_TYPE : 10, - POST_OBJ : 11, - ERROR : 12 - }; - function transitState(currState, c) { - var currLocation = currState.location; - var ret; - - // Opening. - if (currLocation == Location.PRE_SUBJECT && c == '<') ret = Location.WRITING_SUB_URI; - else if(currLocation == Location.PRE_SUBJECT && c == '_') ret = Location.WRITING_BNODE_URI; - else if(currLocation == Location.PRE_PRED && c == '<') ret = Location.WRITING_PRED_URI; - else if(currLocation == Location.PRE_OBJ && c == '<') ret = Location.WRITING_OBJ_URI; - else if(currLocation == Location.PRE_OBJ && c == '_') ret = Location.WRITING_OBJ_BNODE; - else if(currLocation == Location.PRE_OBJ && c == '"') ret = Location.WRITING_OBJ_LITERAL; - - // Closing. - else if(currLocation == Location.WRITING_SUB_URI && c == '>') ret = Location.PRE_PRED; - else if(currLocation == Location.WRITING_BNODE_URI && c == ' ') ret = Location.PRE_PRED; - else if(currLocation == Location.WRITING_PRED_URI && c == '>') ret = Location.PRE_OBJ; - else if(currLocation == Location.WRITING_OBJ_URI && c == '>') ret = Location.POST_OBJ; - else if(currLocation == Location.WRITING_OBJ_BNODE && c == ' ') ret = Location.POST_OBJ; - else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '"') ret = Location.POST_OBJ; - else if(currLocation == Location.WRITING_LIT_LANG && c == ' ') ret = Location.POST_OBJ; - else if(currLocation == Location.WRITING_LIT_TYPE && c == '>') ret = Location.POST_OBJ; - - // Closing typed and language literal. - else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '@') ret = Location.WRITING_LIT_LANG; - else if(currLocation == Location.WRITING_OBJ_LITERAL && c == '^') ret = Location.WRITING_LIT_TYPE; - - // Spaces. - else if( c == ' ' && - ( - currLocation == Location.PRE_SUBJECT || - currLocation == Location.PRE_PRED || - currLocation == Location.PRE_OBJ || - currLocation == Location.POST_OBJ - ) - ) ret = currLocation; - - // Reset. - else if(currLocation == Location.POST_OBJ && c == '.') ret = Location.PRE_SUBJECT; - - // Error - else ret = Location.ERROR; - - currState.location=ret; - } - - return { - startState: function() { - return { - location : Location.PRE_SUBJECT, - uris : [], - anchors : [], - bnodes : [], - langs : [], - types : [] - }; - }, - token: function(stream, state) { - var ch = stream.next(); - if(ch == '<') { - transitState(state, ch); - var parsedURI = ''; - stream.eatWhile( function(c) { if( c != '#' && c != '>' ) { parsedURI += c; return true; } return false;} ); - state.uris.push(parsedURI); - if( stream.match('#', false) ) return 'variable'; - stream.next(); - transitState(state, '>'); - return 'variable'; - } - if(ch == '#') { - var parsedAnchor = ''; - stream.eatWhile(function(c) { if(c != '>' && c != ' ') { parsedAnchor+= c; return true; } return false;}); - state.anchors.push(parsedAnchor); - return 'variable-2'; - } - if(ch == '>') { - transitState(state, '>'); - return 'variable'; - } - if(ch == '_') { - transitState(state, ch); - var parsedBNode = ''; - stream.eatWhile(function(c) { if( c != ' ' ) { parsedBNode += c; return true; } return false;}); - state.bnodes.push(parsedBNode); - stream.next(); - transitState(state, ' '); - return 'builtin'; - } - if(ch == '"') { - transitState(state, ch); - stream.eatWhile( function(c) { return c != '"'; } ); - stream.next(); - if( stream.peek() != '@' && stream.peek() != '^' ) { - transitState(state, '"'); - } - return 'string'; - } - if( ch == '@' ) { - transitState(state, '@'); - var parsedLang = ''; - stream.eatWhile(function(c) { if( c != ' ' ) { parsedLang += c; return true; } return false;}); - state.langs.push(parsedLang); - stream.next(); - transitState(state, ' '); - return 'string-2'; - } - if( ch == '^' ) { - stream.next(); - transitState(state, '^'); - var parsedType = ''; - stream.eatWhile(function(c) { if( c != '>' ) { parsedType += c; return true; } return false;} ); - state.types.push(parsedType); - stream.next(); - transitState(state, '>'); - return 'variable'; - } - if( ch == ' ' ) { - transitState(state, ch); - } - if( ch == '.' ) { - transitState(state, ch); - } - } - }; -}); - -CodeMirror.defineMIME("text/n-triples", "ntriples"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/octave/index.html b/backend/_pv_1_3_5/static/codemirror/mode/octave/index.html deleted file mode 100755 index 3490ee637..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/octave/index.html +++ /dev/null @@ -1,83 +0,0 @@ - - -CodeMirror: Octave mode - - - - - - - - - -
    -

    Octave mode

    - -
    - - -

    MIME types defined: text/x-octave.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/octave/octave.js b/backend/_pv_1_3_5/static/codemirror/mode/octave/octave.js deleted file mode 100755 index a7bec030c..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/octave/octave.js +++ /dev/null @@ -1,135 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("octave", function() { - function wordRegexp(words) { - return new RegExp("^((" + words.join(")|(") + "))\\b"); - } - - var singleOperators = new RegExp("^[\\+\\-\\*/&|\\^~<>!@'\\\\]"); - var singleDelimiters = new RegExp('^[\\(\\[\\{\\},:=;]'); - var doubleOperators = new RegExp("^((==)|(~=)|(<=)|(>=)|(<<)|(>>)|(\\.[\\+\\-\\*/\\^\\\\]))"); - var doubleDelimiters = new RegExp("^((!=)|(\\+=)|(\\-=)|(\\*=)|(/=)|(&=)|(\\|=)|(\\^=))"); - var tripleDelimiters = new RegExp("^((>>=)|(<<=))"); - var expressionEnd = new RegExp("^[\\]\\)]"); - var identifiers = new RegExp("^[_A-Za-z\xa1-\uffff][_A-Za-z0-9\xa1-\uffff]*"); - - var builtins = wordRegexp([ - 'error', 'eval', 'function', 'abs', 'acos', 'atan', 'asin', 'cos', - 'cosh', 'exp', 'log', 'prod', 'sum', 'log10', 'max', 'min', 'sign', 'sin', 'sinh', - 'sqrt', 'tan', 'reshape', 'break', 'zeros', 'default', 'margin', 'round', 'ones', - 'rand', 'syn', 'ceil', 'floor', 'size', 'clear', 'zeros', 'eye', 'mean', 'std', 'cov', - 'det', 'eig', 'inv', 'norm', 'rank', 'trace', 'expm', 'logm', 'sqrtm', 'linspace', 'plot', - 'title', 'xlabel', 'ylabel', 'legend', 'text', 'grid', 'meshgrid', 'mesh', 'num2str', - 'fft', 'ifft', 'arrayfun', 'cellfun', 'input', 'fliplr', 'flipud', 'ismember' - ]); - - var keywords = wordRegexp([ - 'return', 'case', 'switch', 'else', 'elseif', 'end', 'endif', 'endfunction', - 'if', 'otherwise', 'do', 'for', 'while', 'try', 'catch', 'classdef', 'properties', 'events', - 'methods', 'global', 'persistent', 'endfor', 'endwhile', 'printf', 'sprintf', 'disp', 'until', - 'continue', 'pkg' - ]); - - - // tokenizers - function tokenTranspose(stream, state) { - if (!stream.sol() && stream.peek() === '\'') { - stream.next(); - state.tokenize = tokenBase; - return 'operator'; - } - state.tokenize = tokenBase; - return tokenBase(stream, state); - } - - - function tokenComment(stream, state) { - if (stream.match(/^.*%}/)) { - state.tokenize = tokenBase; - return 'comment'; - }; - stream.skipToEnd(); - return 'comment'; - } - - function tokenBase(stream, state) { - // whitespaces - if (stream.eatSpace()) return null; - - // Handle one line Comments - if (stream.match('%{')){ - state.tokenize = tokenComment; - stream.skipToEnd(); - return 'comment'; - } - - if (stream.match(/^[%#]/)){ - stream.skipToEnd(); - return 'comment'; - } - - // Handle Number Literals - if (stream.match(/^[0-9\.+-]/, false)) { - if (stream.match(/^[+-]?0x[0-9a-fA-F]+[ij]?/)) { - stream.tokenize = tokenBase; - return 'number'; }; - if (stream.match(/^[+-]?\d*\.\d+([EeDd][+-]?\d+)?[ij]?/)) { return 'number'; }; - if (stream.match(/^[+-]?\d+([EeDd][+-]?\d+)?[ij]?/)) { return 'number'; }; - } - if (stream.match(wordRegexp(['nan','NaN','inf','Inf']))) { return 'number'; }; - - // Handle Strings - if (stream.match(/^"([^"]|(""))*"/)) { return 'string'; } ; - if (stream.match(/^'([^']|(''))*'/)) { return 'string'; } ; - - // Handle words - if (stream.match(keywords)) { return 'keyword'; } ; - if (stream.match(builtins)) { return 'builtin'; } ; - if (stream.match(identifiers)) { return 'variable'; } ; - - if (stream.match(singleOperators) || stream.match(doubleOperators)) { return 'operator'; }; - if (stream.match(singleDelimiters) || stream.match(doubleDelimiters) || stream.match(tripleDelimiters)) { return null; }; - - if (stream.match(expressionEnd)) { - state.tokenize = tokenTranspose; - return null; - }; - - - // Handle non-detected items - stream.next(); - return 'error'; - }; - - - return { - startState: function() { - return { - tokenize: tokenBase - }; - }, - - token: function(stream, state) { - var style = state.tokenize(stream, state); - if (style === 'number' || style === 'variable'){ - state.tokenize = tokenTranspose; - } - return style; - } - }; -}); - -CodeMirror.defineMIME("text/x-octave", "octave"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/oz/index.html b/backend/_pv_1_3_5/static/codemirror/mode/oz/index.html deleted file mode 100755 index febd82a59..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/oz/index.html +++ /dev/null @@ -1,59 +0,0 @@ - - -CodeMirror: Oz mode - - - - - - - - - - -
    -

    Oz mode

    - -

    MIME type defined: text/x-oz.

    - - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/oz/oz.js b/backend/_pv_1_3_5/static/codemirror/mode/oz/oz.js deleted file mode 100755 index ee8cb0ad1..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/oz/oz.js +++ /dev/null @@ -1,252 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("oz", function (conf) { - - function wordRegexp(words) { - return new RegExp("^((" + words.join(")|(") + "))\\b"); - } - - var singleOperators = /[\^@!\|<>#~\.\*\-\+\\/,=]/; - var doubleOperators = /(<-)|(:=)|(=<)|(>=)|(<=)|(<:)|(>:)|(=:)|(\\=)|(\\=:)|(!!)|(==)|(::)/; - var tripleOperators = /(:::)|(\.\.\.)|(=<:)|(>=:)/; - - var middle = ["in", "then", "else", "of", "elseof", "elsecase", "elseif", "catch", - "finally", "with", "require", "prepare", "import", "export", "define", "do"]; - var end = ["end"]; - - var atoms = wordRegexp(["true", "false", "nil", "unit"]); - var commonKeywords = wordRegexp(["andthen", "at", "attr", "declare", "feat", "from", "lex", - "mod", "mode", "orelse", "parser", "prod", "prop", "scanner", "self", "syn", "token"]); - var openingKeywords = wordRegexp(["local", "proc", "fun", "case", "class", "if", "cond", "or", "dis", - "choice", "not", "thread", "try", "raise", "lock", "for", "suchthat", "meth", "functor"]); - var middleKeywords = wordRegexp(middle); - var endKeywords = wordRegexp(end); - - // Tokenizers - function tokenBase(stream, state) { - if (stream.eatSpace()) { - return null; - } - - // Brackets - if(stream.match(/[{}]/)) { - return "bracket"; - } - - // Special [] keyword - if (stream.match(/(\[])/)) { - return "keyword" - } - - // Operators - if (stream.match(tripleOperators) || stream.match(doubleOperators)) { - return "operator"; - } - - // Atoms - if(stream.match(atoms)) { - return 'atom'; - } - - // Opening keywords - var matched = stream.match(openingKeywords); - if (matched) { - if (!state.doInCurrentLine) - state.currentIndent++; - else - state.doInCurrentLine = false; - - // Special matching for signatures - if(matched[0] == "proc" || matched[0] == "fun") - state.tokenize = tokenFunProc; - else if(matched[0] == "class") - state.tokenize = tokenClass; - else if(matched[0] == "meth") - state.tokenize = tokenMeth; - - return 'keyword'; - } - - // Middle and other keywords - if (stream.match(middleKeywords) || stream.match(commonKeywords)) { - return "keyword" - } - - // End keywords - if (stream.match(endKeywords)) { - state.currentIndent--; - return 'keyword'; - } - - // Eat the next char for next comparisons - var ch = stream.next(); - - // Strings - if (ch == '"' || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - - // Numbers - if (/[~\d]/.test(ch)) { - if (ch == "~") { - if(! /^[0-9]/.test(stream.peek())) - return null; - else if (( stream.next() == "0" && stream.match(/^[xX][0-9a-fA-F]+/)) || stream.match(/^[0-9]*(\.[0-9]+)?([eE][~+]?[0-9]+)?/)) - return "number"; - } - - if ((ch == "0" && stream.match(/^[xX][0-9a-fA-F]+/)) || stream.match(/^[0-9]*(\.[0-9]+)?([eE][~+]?[0-9]+)?/)) - return "number"; - - return null; - } - - // Comments - if (ch == "%") { - stream.skipToEnd(); - return 'comment'; - } - else if (ch == "/") { - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - } - - // Single operators - if(singleOperators.test(ch)) { - return "operator"; - } - - // If nothing match, we skip the entire alphanumerical block - stream.eatWhile(/\w/); - - return "variable"; - } - - function tokenClass(stream, state) { - if (stream.eatSpace()) { - return null; - } - stream.match(/([A-Z][A-Za-z0-9_]*)|(`.+`)/); - state.tokenize = tokenBase; - return "variable-3" - } - - function tokenMeth(stream, state) { - if (stream.eatSpace()) { - return null; - } - stream.match(/([a-zA-Z][A-Za-z0-9_]*)|(`.+`)/); - state.tokenize = tokenBase; - return "def" - } - - function tokenFunProc(stream, state) { - if (stream.eatSpace()) { - return null; - } - - if(!state.hasPassedFirstStage && stream.eat("{")) { - state.hasPassedFirstStage = true; - return "bracket"; - } - else if(state.hasPassedFirstStage) { - stream.match(/([A-Z][A-Za-z0-9_]*)|(`.+`)|\$/); - state.hasPassedFirstStage = false; - state.tokenize = tokenBase; - return "def" - } - else { - state.tokenize = tokenBase; - return null; - } - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function tokenString(quote) { - return function (stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) { - end = true; - break; - } - escaped = !escaped && next == "\\"; - } - if (end || !escaped) - state.tokenize = tokenBase; - return "string"; - }; - } - - function buildElectricInputRegEx() { - // Reindentation should occur on [] or on a match of any of - // the block closing keywords, at the end of a line. - var allClosings = middle.concat(end); - return new RegExp("[\\[\\]]|(" + allClosings.join("|") + ")$"); - } - - return { - - startState: function () { - return { - tokenize: tokenBase, - currentIndent: 0, - doInCurrentLine: false, - hasPassedFirstStage: false - }; - }, - - token: function (stream, state) { - if (stream.sol()) - state.doInCurrentLine = 0; - - return state.tokenize(stream, state); - }, - - indent: function (state, textAfter) { - var trueText = textAfter.replace(/^\s+|\s+$/g, ''); - - if (trueText.match(endKeywords) || trueText.match(middleKeywords) || trueText.match(/(\[])/)) - return conf.indentUnit * (state.currentIndent - 1); - - if (state.currentIndent < 0) - return 0; - - return state.currentIndent * conf.indentUnit; - }, - fold: "indent", - electricInput: buildElectricInputRegEx(), - lineComment: "%", - blockCommentStart: "/*", - blockCommentEnd: "*/" - }; -}); - -CodeMirror.defineMIME("text/x-oz", "oz"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/pascal/index.html b/backend/_pv_1_3_5/static/codemirror/mode/pascal/index.html deleted file mode 100755 index f8a99ad01..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/pascal/index.html +++ /dev/null @@ -1,61 +0,0 @@ - - -CodeMirror: Pascal mode - - - - - - - - - -
    -

    Pascal mode

    - - -
    - - - -

    MIME types defined: text/x-pascal.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/pascal/pascal.js b/backend/_pv_1_3_5/static/codemirror/mode/pascal/pascal.js deleted file mode 100755 index 2d0c3d424..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/pascal/pascal.js +++ /dev/null @@ -1,109 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("pascal", function() { - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - var keywords = words("and array begin case const div do downto else end file for forward integer " + - "boolean char function goto if in label mod nil not of or packed procedure " + - "program record repeat set string then to type until var while with"); - var atoms = {"null": true}; - - var isOperatorChar = /[+\-*&%=<>!?|\/]/; - - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == "#" && state.startOfLine) { - stream.skipToEnd(); - return "meta"; - } - if (ch == '"' || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - if (ch == "(" && stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - return null; - } - if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - if (ch == "/") { - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - } - if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - stream.eatWhile(/[\w\$_]/); - var cur = stream.current(); - if (keywords.propertyIsEnumerable(cur)) return "keyword"; - if (atoms.propertyIsEnumerable(cur)) return "atom"; - return "variable"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) {end = true; break;} - escaped = !escaped && next == "\\"; - } - if (end || !escaped) state.tokenize = null; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == ")" && maybeEnd) { - state.tokenize = null; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - // Interface - - return { - startState: function() { - return {tokenize: null}; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment" || style == "meta") return style; - return style; - }, - - electricChars: "{}" - }; -}); - -CodeMirror.defineMIME("text/x-pascal", "pascal"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/pegjs/index.html b/backend/_pv_1_3_5/static/codemirror/mode/pegjs/index.html deleted file mode 100755 index 0c7460488..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/pegjs/index.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - CodeMirror: PEG.js Mode - - - - - - - - - - - - -
    -

    PEG.js Mode

    -
    - -

    The PEG.js Mode

    -

    Created by Forbes Lindesay.

    -
    - - diff --git a/backend/_pv_1_3_5/static/codemirror/mode/pegjs/pegjs.js b/backend/_pv_1_3_5/static/codemirror/mode/pegjs/pegjs.js deleted file mode 100755 index 6c7207466..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/pegjs/pegjs.js +++ /dev/null @@ -1,114 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../javascript/javascript")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../javascript/javascript"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("pegjs", function (config) { - var jsMode = CodeMirror.getMode(config, "javascript"); - - function identifier(stream) { - return stream.match(/^[a-zA-Z_][a-zA-Z0-9_]*/); - } - - return { - startState: function () { - return { - inString: false, - stringType: null, - inComment: false, - inCharacterClass: false, - braced: 0, - lhs: true, - localState: null - }; - }, - token: function (stream, state) { - if (stream) - - //check for state changes - if (!state.inString && !state.inComment && ((stream.peek() == '"') || (stream.peek() == "'"))) { - state.stringType = stream.peek(); - stream.next(); // Skip quote - state.inString = true; // Update state - } - if (!state.inString && !state.inComment && stream.match(/^\/\*/)) { - state.inComment = true; - } - - //return state - if (state.inString) { - while (state.inString && !stream.eol()) { - if (stream.peek() === state.stringType) { - stream.next(); // Skip quote - state.inString = false; // Clear flag - } else if (stream.peek() === '\\') { - stream.next(); - stream.next(); - } else { - stream.match(/^.[^\\\"\']*/); - } - } - return state.lhs ? "property string" : "string"; // Token style - } else if (state.inComment) { - while (state.inComment && !stream.eol()) { - if (stream.match(/\*\//)) { - state.inComment = false; // Clear flag - } else { - stream.match(/^.[^\*]*/); - } - } - return "comment"; - } else if (state.inCharacterClass) { - while (state.inCharacterClass && !stream.eol()) { - if (!(stream.match(/^[^\]\\]+/) || stream.match(/^\\./))) { - state.inCharacterClass = false; - } - } - } else if (stream.peek() === '[') { - stream.next(); - state.inCharacterClass = true; - return 'bracket'; - } else if (stream.match(/^\/\//)) { - stream.skipToEnd(); - return "comment"; - } else if (state.braced || stream.peek() === '{') { - if (state.localState === null) { - state.localState = CodeMirror.startState(jsMode); - } - var token = jsMode.token(stream, state.localState); - var text = stream.current(); - if (!token) { - for (var i = 0; i < text.length; i++) { - if (text[i] === '{') { - state.braced++; - } else if (text[i] === '}') { - state.braced--; - } - }; - } - return token; - } else if (identifier(stream)) { - if (stream.peek() === ':') { - return 'variable'; - } - return 'variable-2'; - } else if (['[', ']', '(', ')'].indexOf(stream.peek()) != -1) { - stream.next(); - return 'bracket'; - } else if (!stream.eatSpace()) { - stream.next(); - } - return null; - } - }; -}, "javascript"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/perl/index.html b/backend/_pv_1_3_5/static/codemirror/mode/perl/index.html deleted file mode 100755 index 8c1021c42..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/perl/index.html +++ /dev/null @@ -1,75 +0,0 @@ - - -CodeMirror: Perl mode - - - - - - - - - -
    -

    Perl mode

    - - -
    - - - -

    MIME types defined: text/x-perl.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/perl/perl.js b/backend/_pv_1_3_5/static/codemirror/mode/perl/perl.js deleted file mode 100755 index 66e4ed034..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/perl/perl.js +++ /dev/null @@ -1,837 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// CodeMirror2 mode/perl/perl.js (text/x-perl) beta 0.10 (2011-11-08) -// This is a part of CodeMirror from https://github.com/sabaca/CodeMirror_mode_perl (mail@sabaca.com) - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("perl",function(){ - // http://perldoc.perl.org - var PERL={ // null - magic touch - // 1 - keyword - // 2 - def - // 3 - atom - // 4 - operator - // 5 - variable-2 (predefined) - // [x,y] - x=1,2,3; y=must be defined if x{...} - // PERL operators - '->' : 4, - '++' : 4, - '--' : 4, - '**' : 4, - // ! ~ \ and unary + and - - '=~' : 4, - '!~' : 4, - '*' : 4, - '/' : 4, - '%' : 4, - 'x' : 4, - '+' : 4, - '-' : 4, - '.' : 4, - '<<' : 4, - '>>' : 4, - // named unary operators - '<' : 4, - '>' : 4, - '<=' : 4, - '>=' : 4, - 'lt' : 4, - 'gt' : 4, - 'le' : 4, - 'ge' : 4, - '==' : 4, - '!=' : 4, - '<=>' : 4, - 'eq' : 4, - 'ne' : 4, - 'cmp' : 4, - '~~' : 4, - '&' : 4, - '|' : 4, - '^' : 4, - '&&' : 4, - '||' : 4, - '//' : 4, - '..' : 4, - '...' : 4, - '?' : 4, - ':' : 4, - '=' : 4, - '+=' : 4, - '-=' : 4, - '*=' : 4, // etc. ??? - ',' : 4, - '=>' : 4, - '::' : 4, - // list operators (rightward) - 'not' : 4, - 'and' : 4, - 'or' : 4, - 'xor' : 4, - // PERL predefined variables (I know, what this is a paranoid idea, but may be needed for people, who learn PERL, and for me as well, ...and may be for you?;) - 'BEGIN' : [5,1], - 'END' : [5,1], - 'PRINT' : [5,1], - 'PRINTF' : [5,1], - 'GETC' : [5,1], - 'READ' : [5,1], - 'READLINE' : [5,1], - 'DESTROY' : [5,1], - 'TIE' : [5,1], - 'TIEHANDLE' : [5,1], - 'UNTIE' : [5,1], - 'STDIN' : 5, - 'STDIN_TOP' : 5, - 'STDOUT' : 5, - 'STDOUT_TOP' : 5, - 'STDERR' : 5, - 'STDERR_TOP' : 5, - '$ARG' : 5, - '$_' : 5, - '@ARG' : 5, - '@_' : 5, - '$LIST_SEPARATOR' : 5, - '$"' : 5, - '$PROCESS_ID' : 5, - '$PID' : 5, - '$$' : 5, - '$REAL_GROUP_ID' : 5, - '$GID' : 5, - '$(' : 5, - '$EFFECTIVE_GROUP_ID' : 5, - '$EGID' : 5, - '$)' : 5, - '$PROGRAM_NAME' : 5, - '$0' : 5, - '$SUBSCRIPT_SEPARATOR' : 5, - '$SUBSEP' : 5, - '$;' : 5, - '$REAL_USER_ID' : 5, - '$UID' : 5, - '$<' : 5, - '$EFFECTIVE_USER_ID' : 5, - '$EUID' : 5, - '$>' : 5, - '$a' : 5, - '$b' : 5, - '$COMPILING' : 5, - '$^C' : 5, - '$DEBUGGING' : 5, - '$^D' : 5, - '${^ENCODING}' : 5, - '$ENV' : 5, - '%ENV' : 5, - '$SYSTEM_FD_MAX' : 5, - '$^F' : 5, - '@F' : 5, - '${^GLOBAL_PHASE}' : 5, - '$^H' : 5, - '%^H' : 5, - '@INC' : 5, - '%INC' : 5, - '$INPLACE_EDIT' : 5, - '$^I' : 5, - '$^M' : 5, - '$OSNAME' : 5, - '$^O' : 5, - '${^OPEN}' : 5, - '$PERLDB' : 5, - '$^P' : 5, - '$SIG' : 5, - '%SIG' : 5, - '$BASETIME' : 5, - '$^T' : 5, - '${^TAINT}' : 5, - '${^UNICODE}' : 5, - '${^UTF8CACHE}' : 5, - '${^UTF8LOCALE}' : 5, - '$PERL_VERSION' : 5, - '$^V' : 5, - '${^WIN32_SLOPPY_STAT}' : 5, - '$EXECUTABLE_NAME' : 5, - '$^X' : 5, - '$1' : 5, // - regexp $1, $2... - '$MATCH' : 5, - '$&' : 5, - '${^MATCH}' : 5, - '$PREMATCH' : 5, - '$`' : 5, - '${^PREMATCH}' : 5, - '$POSTMATCH' : 5, - "$'" : 5, - '${^POSTMATCH}' : 5, - '$LAST_PAREN_MATCH' : 5, - '$+' : 5, - '$LAST_SUBMATCH_RESULT' : 5, - '$^N' : 5, - '@LAST_MATCH_END' : 5, - '@+' : 5, - '%LAST_PAREN_MATCH' : 5, - '%+' : 5, - '@LAST_MATCH_START' : 5, - '@-' : 5, - '%LAST_MATCH_START' : 5, - '%-' : 5, - '$LAST_REGEXP_CODE_RESULT' : 5, - '$^R' : 5, - '${^RE_DEBUG_FLAGS}' : 5, - '${^RE_TRIE_MAXBUF}' : 5, - '$ARGV' : 5, - '@ARGV' : 5, - 'ARGV' : 5, - 'ARGVOUT' : 5, - '$OUTPUT_FIELD_SEPARATOR' : 5, - '$OFS' : 5, - '$,' : 5, - '$INPUT_LINE_NUMBER' : 5, - '$NR' : 5, - '$.' : 5, - '$INPUT_RECORD_SEPARATOR' : 5, - '$RS' : 5, - '$/' : 5, - '$OUTPUT_RECORD_SEPARATOR' : 5, - '$ORS' : 5, - '$\\' : 5, - '$OUTPUT_AUTOFLUSH' : 5, - '$|' : 5, - '$ACCUMULATOR' : 5, - '$^A' : 5, - '$FORMAT_FORMFEED' : 5, - '$^L' : 5, - '$FORMAT_PAGE_NUMBER' : 5, - '$%' : 5, - '$FORMAT_LINES_LEFT' : 5, - '$-' : 5, - '$FORMAT_LINE_BREAK_CHARACTERS' : 5, - '$:' : 5, - '$FORMAT_LINES_PER_PAGE' : 5, - '$=' : 5, - '$FORMAT_TOP_NAME' : 5, - '$^' : 5, - '$FORMAT_NAME' : 5, - '$~' : 5, - '${^CHILD_ERROR_NATIVE}' : 5, - '$EXTENDED_OS_ERROR' : 5, - '$^E' : 5, - '$EXCEPTIONS_BEING_CAUGHT' : 5, - '$^S' : 5, - '$WARNING' : 5, - '$^W' : 5, - '${^WARNING_BITS}' : 5, - '$OS_ERROR' : 5, - '$ERRNO' : 5, - '$!' : 5, - '%OS_ERROR' : 5, - '%ERRNO' : 5, - '%!' : 5, - '$CHILD_ERROR' : 5, - '$?' : 5, - '$EVAL_ERROR' : 5, - '$@' : 5, - '$OFMT' : 5, - '$#' : 5, - '$*' : 5, - '$ARRAY_BASE' : 5, - '$[' : 5, - '$OLD_PERL_VERSION' : 5, - '$]' : 5, - // PERL blocks - 'if' :[1,1], - elsif :[1,1], - 'else' :[1,1], - 'while' :[1,1], - unless :[1,1], - 'for' :[1,1], - foreach :[1,1], - // PERL functions - 'abs' :1, // - absolute value function - accept :1, // - accept an incoming socket connect - alarm :1, // - schedule a SIGALRM - 'atan2' :1, // - arctangent of Y/X in the range -PI to PI - bind :1, // - binds an address to a socket - binmode :1, // - prepare binary files for I/O - bless :1, // - create an object - bootstrap :1, // - 'break' :1, // - break out of a "given" block - caller :1, // - get context of the current subroutine call - chdir :1, // - change your current working directory - chmod :1, // - changes the permissions on a list of files - chomp :1, // - remove a trailing record separator from a string - chop :1, // - remove the last character from a string - chown :1, // - change the ownership on a list of files - chr :1, // - get character this number represents - chroot :1, // - make directory new root for path lookups - close :1, // - close file (or pipe or socket) handle - closedir :1, // - close directory handle - connect :1, // - connect to a remote socket - 'continue' :[1,1], // - optional trailing block in a while or foreach - 'cos' :1, // - cosine function - crypt :1, // - one-way passwd-style encryption - dbmclose :1, // - breaks binding on a tied dbm file - dbmopen :1, // - create binding on a tied dbm file - 'default' :1, // - defined :1, // - test whether a value, variable, or function is defined - 'delete' :1, // - deletes a value from a hash - die :1, // - raise an exception or bail out - 'do' :1, // - turn a BLOCK into a TERM - dump :1, // - create an immediate core dump - each :1, // - retrieve the next key/value pair from a hash - endgrent :1, // - be done using group file - endhostent :1, // - be done using hosts file - endnetent :1, // - be done using networks file - endprotoent :1, // - be done using protocols file - endpwent :1, // - be done using passwd file - endservent :1, // - be done using services file - eof :1, // - test a filehandle for its end - 'eval' :1, // - catch exceptions or compile and run code - 'exec' :1, // - abandon this program to run another - exists :1, // - test whether a hash key is present - exit :1, // - terminate this program - 'exp' :1, // - raise I to a power - fcntl :1, // - file control system call - fileno :1, // - return file descriptor from filehandle - flock :1, // - lock an entire file with an advisory lock - fork :1, // - create a new process just like this one - format :1, // - declare a picture format with use by the write() function - formline :1, // - internal function used for formats - getc :1, // - get the next character from the filehandle - getgrent :1, // - get next group record - getgrgid :1, // - get group record given group user ID - getgrnam :1, // - get group record given group name - gethostbyaddr :1, // - get host record given its address - gethostbyname :1, // - get host record given name - gethostent :1, // - get next hosts record - getlogin :1, // - return who logged in at this tty - getnetbyaddr :1, // - get network record given its address - getnetbyname :1, // - get networks record given name - getnetent :1, // - get next networks record - getpeername :1, // - find the other end of a socket connection - getpgrp :1, // - get process group - getppid :1, // - get parent process ID - getpriority :1, // - get current nice value - getprotobyname :1, // - get protocol record given name - getprotobynumber :1, // - get protocol record numeric protocol - getprotoent :1, // - get next protocols record - getpwent :1, // - get next passwd record - getpwnam :1, // - get passwd record given user login name - getpwuid :1, // - get passwd record given user ID - getservbyname :1, // - get services record given its name - getservbyport :1, // - get services record given numeric port - getservent :1, // - get next services record - getsockname :1, // - retrieve the sockaddr for a given socket - getsockopt :1, // - get socket options on a given socket - given :1, // - glob :1, // - expand filenames using wildcards - gmtime :1, // - convert UNIX time into record or string using Greenwich time - 'goto' :1, // - create spaghetti code - grep :1, // - locate elements in a list test true against a given criterion - hex :1, // - convert a string to a hexadecimal number - 'import' :1, // - patch a module's namespace into your own - index :1, // - find a substring within a string - 'int' :1, // - get the integer portion of a number - ioctl :1, // - system-dependent device control system call - 'join' :1, // - join a list into a string using a separator - keys :1, // - retrieve list of indices from a hash - kill :1, // - send a signal to a process or process group - last :1, // - exit a block prematurely - lc :1, // - return lower-case version of a string - lcfirst :1, // - return a string with just the next letter in lower case - length :1, // - return the number of bytes in a string - 'link' :1, // - create a hard link in the filesytem - listen :1, // - register your socket as a server - local : 2, // - create a temporary value for a global variable (dynamic scoping) - localtime :1, // - convert UNIX time into record or string using local time - lock :1, // - get a thread lock on a variable, subroutine, or method - 'log' :1, // - retrieve the natural logarithm for a number - lstat :1, // - stat a symbolic link - m :null, // - match a string with a regular expression pattern - map :1, // - apply a change to a list to get back a new list with the changes - mkdir :1, // - create a directory - msgctl :1, // - SysV IPC message control operations - msgget :1, // - get SysV IPC message queue - msgrcv :1, // - receive a SysV IPC message from a message queue - msgsnd :1, // - send a SysV IPC message to a message queue - my : 2, // - declare and assign a local variable (lexical scoping) - 'new' :1, // - next :1, // - iterate a block prematurely - no :1, // - unimport some module symbols or semantics at compile time - oct :1, // - convert a string to an octal number - open :1, // - open a file, pipe, or descriptor - opendir :1, // - open a directory - ord :1, // - find a character's numeric representation - our : 2, // - declare and assign a package variable (lexical scoping) - pack :1, // - convert a list into a binary representation - 'package' :1, // - declare a separate global namespace - pipe :1, // - open a pair of connected filehandles - pop :1, // - remove the last element from an array and return it - pos :1, // - find or set the offset for the last/next m//g search - print :1, // - output a list to a filehandle - printf :1, // - output a formatted list to a filehandle - prototype :1, // - get the prototype (if any) of a subroutine - push :1, // - append one or more elements to an array - q :null, // - singly quote a string - qq :null, // - doubly quote a string - qr :null, // - Compile pattern - quotemeta :null, // - quote regular expression magic characters - qw :null, // - quote a list of words - qx :null, // - backquote quote a string - rand :1, // - retrieve the next pseudorandom number - read :1, // - fixed-length buffered input from a filehandle - readdir :1, // - get a directory from a directory handle - readline :1, // - fetch a record from a file - readlink :1, // - determine where a symbolic link is pointing - readpipe :1, // - execute a system command and collect standard output - recv :1, // - receive a message over a Socket - redo :1, // - start this loop iteration over again - ref :1, // - find out the type of thing being referenced - rename :1, // - change a filename - require :1, // - load in external functions from a library at runtime - reset :1, // - clear all variables of a given name - 'return' :1, // - get out of a function early - reverse :1, // - flip a string or a list - rewinddir :1, // - reset directory handle - rindex :1, // - right-to-left substring search - rmdir :1, // - remove a directory - s :null, // - replace a pattern with a string - say :1, // - print with newline - scalar :1, // - force a scalar context - seek :1, // - reposition file pointer for random-access I/O - seekdir :1, // - reposition directory pointer - select :1, // - reset default output or do I/O multiplexing - semctl :1, // - SysV semaphore control operations - semget :1, // - get set of SysV semaphores - semop :1, // - SysV semaphore operations - send :1, // - send a message over a socket - setgrent :1, // - prepare group file for use - sethostent :1, // - prepare hosts file for use - setnetent :1, // - prepare networks file for use - setpgrp :1, // - set the process group of a process - setpriority :1, // - set a process's nice value - setprotoent :1, // - prepare protocols file for use - setpwent :1, // - prepare passwd file for use - setservent :1, // - prepare services file for use - setsockopt :1, // - set some socket options - shift :1, // - remove the first element of an array, and return it - shmctl :1, // - SysV shared memory operations - shmget :1, // - get SysV shared memory segment identifier - shmread :1, // - read SysV shared memory - shmwrite :1, // - write SysV shared memory - shutdown :1, // - close down just half of a socket connection - 'sin' :1, // - return the sine of a number - sleep :1, // - block for some number of seconds - socket :1, // - create a socket - socketpair :1, // - create a pair of sockets - 'sort' :1, // - sort a list of values - splice :1, // - add or remove elements anywhere in an array - 'split' :1, // - split up a string using a regexp delimiter - sprintf :1, // - formatted print into a string - 'sqrt' :1, // - square root function - srand :1, // - seed the random number generator - stat :1, // - get a file's status information - state :1, // - declare and assign a state variable (persistent lexical scoping) - study :1, // - optimize input data for repeated searches - 'sub' :1, // - declare a subroutine, possibly anonymously - 'substr' :1, // - get or alter a portion of a stirng - symlink :1, // - create a symbolic link to a file - syscall :1, // - execute an arbitrary system call - sysopen :1, // - open a file, pipe, or descriptor - sysread :1, // - fixed-length unbuffered input from a filehandle - sysseek :1, // - position I/O pointer on handle used with sysread and syswrite - system :1, // - run a separate program - syswrite :1, // - fixed-length unbuffered output to a filehandle - tell :1, // - get current seekpointer on a filehandle - telldir :1, // - get current seekpointer on a directory handle - tie :1, // - bind a variable to an object class - tied :1, // - get a reference to the object underlying a tied variable - time :1, // - return number of seconds since 1970 - times :1, // - return elapsed time for self and child processes - tr :null, // - transliterate a string - truncate :1, // - shorten a file - uc :1, // - return upper-case version of a string - ucfirst :1, // - return a string with just the next letter in upper case - umask :1, // - set file creation mode mask - undef :1, // - remove a variable or function definition - unlink :1, // - remove one link to a file - unpack :1, // - convert binary structure into normal perl variables - unshift :1, // - prepend more elements to the beginning of a list - untie :1, // - break a tie binding to a variable - use :1, // - load in a module at compile time - utime :1, // - set a file's last access and modify times - values :1, // - return a list of the values in a hash - vec :1, // - test or set particular bits in a string - wait :1, // - wait for any child process to die - waitpid :1, // - wait for a particular child process to die - wantarray :1, // - get void vs scalar vs list context of current subroutine call - warn :1, // - print debugging info - when :1, // - write :1, // - print a picture record - y :null}; // - transliterate a string - - var RXstyle="string-2"; - var RXmodifiers=/[goseximacplud]/; // NOTE: "m", "s", "y" and "tr" need to correct real modifiers for each regexp type - - function tokenChain(stream,state,chain,style,tail){ // NOTE: chain.length > 2 is not working now (it's for s[...][...]geos;) - state.chain=null; // 12 3tail - state.style=null; - state.tail=null; - state.tokenize=function(stream,state){ - var e=false,c,i=0; - while(c=stream.next()){ - if(c===chain[i]&&!e){ - if(chain[++i]!==undefined){ - state.chain=chain[i]; - state.style=style; - state.tail=tail;} - else if(tail) - stream.eatWhile(tail); - state.tokenize=tokenPerl; - return style;} - e=!e&&c=="\\";} - return style;}; - return state.tokenize(stream,state);} - - function tokenSOMETHING(stream,state,string){ - state.tokenize=function(stream,state){ - if(stream.string==string) - state.tokenize=tokenPerl; - stream.skipToEnd(); - return "string";}; - return state.tokenize(stream,state);} - - function tokenPerl(stream,state){ - if(stream.eatSpace()) - return null; - if(state.chain) - return tokenChain(stream,state,state.chain,state.style,state.tail); - if(stream.match(/^\-?[\d\.]/,false)) - if(stream.match(/^(\-?(\d*\.\d+(e[+-]?\d+)?|\d+\.\d*)|0x[\da-fA-F]+|0b[01]+|\d+(e[+-]?\d+)?)/)) - return 'number'; - if(stream.match(/^<<(?=\w)/)){ // NOTE: <"],RXstyle,RXmodifiers);} - if(/[\^'"!~\/]/.test(c)){ - eatSuffix(stream, 1); - return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}} - else if(c=="q"){ - c=look(stream, 1); - if(c=="("){ - eatSuffix(stream, 2); - return tokenChain(stream,state,[")"],"string");} - if(c=="["){ - eatSuffix(stream, 2); - return tokenChain(stream,state,["]"],"string");} - if(c=="{"){ - eatSuffix(stream, 2); - return tokenChain(stream,state,["}"],"string");} - if(c=="<"){ - eatSuffix(stream, 2); - return tokenChain(stream,state,[">"],"string");} - if(/[\^'"!~\/]/.test(c)){ - eatSuffix(stream, 1); - return tokenChain(stream,state,[stream.eat(c)],"string");}} - else if(c=="w"){ - c=look(stream, 1); - if(c=="("){ - eatSuffix(stream, 2); - return tokenChain(stream,state,[")"],"bracket");} - if(c=="["){ - eatSuffix(stream, 2); - return tokenChain(stream,state,["]"],"bracket");} - if(c=="{"){ - eatSuffix(stream, 2); - return tokenChain(stream,state,["}"],"bracket");} - if(c=="<"){ - eatSuffix(stream, 2); - return tokenChain(stream,state,[">"],"bracket");} - if(/[\^'"!~\/]/.test(c)){ - eatSuffix(stream, 1); - return tokenChain(stream,state,[stream.eat(c)],"bracket");}} - else if(c=="r"){ - c=look(stream, 1); - if(c=="("){ - eatSuffix(stream, 2); - return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);} - if(c=="["){ - eatSuffix(stream, 2); - return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);} - if(c=="{"){ - eatSuffix(stream, 2); - return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);} - if(c=="<"){ - eatSuffix(stream, 2); - return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);} - if(/[\^'"!~\/]/.test(c)){ - eatSuffix(stream, 1); - return tokenChain(stream,state,[stream.eat(c)],RXstyle,RXmodifiers);}} - else if(/[\^'"!~\/(\[{<]/.test(c)){ - if(c=="("){ - eatSuffix(stream, 1); - return tokenChain(stream,state,[")"],"string");} - if(c=="["){ - eatSuffix(stream, 1); - return tokenChain(stream,state,["]"],"string");} - if(c=="{"){ - eatSuffix(stream, 1); - return tokenChain(stream,state,["}"],"string");} - if(c=="<"){ - eatSuffix(stream, 1); - return tokenChain(stream,state,[">"],"string");} - if(/[\^'"!~\/]/.test(c)){ - return tokenChain(stream,state,[stream.eat(c)],"string");}}}} - if(ch=="m"){ - var c=look(stream, -2); - if(!(c&&/\w/.test(c))){ - c=stream.eat(/[(\[{<\^'"!~\/]/); - if(c){ - if(/[\^'"!~\/]/.test(c)){ - return tokenChain(stream,state,[c],RXstyle,RXmodifiers);} - if(c=="("){ - return tokenChain(stream,state,[")"],RXstyle,RXmodifiers);} - if(c=="["){ - return tokenChain(stream,state,["]"],RXstyle,RXmodifiers);} - if(c=="{"){ - return tokenChain(stream,state,["}"],RXstyle,RXmodifiers);} - if(c=="<"){ - return tokenChain(stream,state,[">"],RXstyle,RXmodifiers);}}}} - if(ch=="s"){ - var c=/[\/>\]})\w]/.test(look(stream, -2)); - if(!c){ - c=stream.eat(/[(\[{<\^'"!~\/]/); - if(c){ - if(c=="[") - return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers); - if(c=="{") - return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers); - if(c=="<") - return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers); - if(c=="(") - return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers); - return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}} - if(ch=="y"){ - var c=/[\/>\]})\w]/.test(look(stream, -2)); - if(!c){ - c=stream.eat(/[(\[{<\^'"!~\/]/); - if(c){ - if(c=="[") - return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers); - if(c=="{") - return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers); - if(c=="<") - return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers); - if(c=="(") - return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers); - return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}} - if(ch=="t"){ - var c=/[\/>\]})\w]/.test(look(stream, -2)); - if(!c){ - c=stream.eat("r");if(c){ - c=stream.eat(/[(\[{<\^'"!~\/]/); - if(c){ - if(c=="[") - return tokenChain(stream,state,["]","]"],RXstyle,RXmodifiers); - if(c=="{") - return tokenChain(stream,state,["}","}"],RXstyle,RXmodifiers); - if(c=="<") - return tokenChain(stream,state,[">",">"],RXstyle,RXmodifiers); - if(c=="(") - return tokenChain(stream,state,[")",")"],RXstyle,RXmodifiers); - return tokenChain(stream,state,[c,c],RXstyle,RXmodifiers);}}}} - if(ch=="`"){ - return tokenChain(stream,state,[ch],"variable-2");} - if(ch=="/"){ - if(!/~\s*$/.test(prefix(stream))) - return "operator"; - else - return tokenChain(stream,state,[ch],RXstyle,RXmodifiers);} - if(ch=="$"){ - var p=stream.pos; - if(stream.eatWhile(/\d/)||stream.eat("{")&&stream.eatWhile(/\d/)&&stream.eat("}")) - return "variable-2"; - else - stream.pos=p;} - if(/[$@%]/.test(ch)){ - var p=stream.pos; - if(stream.eat("^")&&stream.eat(/[A-Z]/)||!/[@$%&]/.test(look(stream, -2))&&stream.eat(/[=|\\\-#?@;:&`~\^!\[\]*'"$+.,\/<>()]/)){ - var c=stream.current(); - if(PERL[c]) - return "variable-2";} - stream.pos=p;} - if(/[$@%&]/.test(ch)){ - if(stream.eatWhile(/[\w$\[\]]/)||stream.eat("{")&&stream.eatWhile(/[\w$\[\]]/)&&stream.eat("}")){ - var c=stream.current(); - if(PERL[c]) - return "variable-2"; - else - return "variable";}} - if(ch=="#"){ - if(look(stream, -2)!="$"){ - stream.skipToEnd(); - return "comment";}} - if(/[:+\-\^*$&%@=<>!?|\/~\.]/.test(ch)){ - var p=stream.pos; - stream.eatWhile(/[:+\-\^*$&%@=<>!?|\/~\.]/); - if(PERL[stream.current()]) - return "operator"; - else - stream.pos=p;} - if(ch=="_"){ - if(stream.pos==1){ - if(suffix(stream, 6)=="_END__"){ - return tokenChain(stream,state,['\0'],"comment");} - else if(suffix(stream, 7)=="_DATA__"){ - return tokenChain(stream,state,['\0'],"variable-2");} - else if(suffix(stream, 7)=="_C__"){ - return tokenChain(stream,state,['\0'],"string");}}} - if(/\w/.test(ch)){ - var p=stream.pos; - if(look(stream, -2)=="{"&&(look(stream, 0)=="}"||stream.eatWhile(/\w/)&&look(stream, 0)=="}")) - return "string"; - else - stream.pos=p;} - if(/[A-Z]/.test(ch)){ - var l=look(stream, -2); - var p=stream.pos; - stream.eatWhile(/[A-Z_]/); - if(/[\da-z]/.test(look(stream, 0))){ - stream.pos=p;} - else{ - var c=PERL[stream.current()]; - if(!c) - return "meta"; - if(c[1]) - c=c[0]; - if(l!=":"){ - if(c==1) - return "keyword"; - else if(c==2) - return "def"; - else if(c==3) - return "atom"; - else if(c==4) - return "operator"; - else if(c==5) - return "variable-2"; - else - return "meta";} - else - return "meta";}} - if(/[a-zA-Z_]/.test(ch)){ - var l=look(stream, -2); - stream.eatWhile(/\w/); - var c=PERL[stream.current()]; - if(!c) - return "meta"; - if(c[1]) - c=c[0]; - if(l!=":"){ - if(c==1) - return "keyword"; - else if(c==2) - return "def"; - else if(c==3) - return "atom"; - else if(c==4) - return "operator"; - else if(c==5) - return "variable-2"; - else - return "meta";} - else - return "meta";} - return null;} - - return { - startState: function() { - return { - tokenize: tokenPerl, - chain: null, - style: null, - tail: null - }; - }, - token: function(stream, state) { - return (state.tokenize || tokenPerl)(stream, state); - }, - lineComment: '#' - }; -}); - -CodeMirror.registerHelper("wordChars", "perl", /[\w$]/); - -CodeMirror.defineMIME("text/x-perl", "perl"); - -// it's like "peek", but need for look-ahead or look-behind if index < 0 -function look(stream, c){ - return stream.string.charAt(stream.pos+(c||0)); -} - -// return a part of prefix of current stream from current position -function prefix(stream, c){ - if(c){ - var x=stream.pos-c; - return stream.string.substr((x>=0?x:0),c);} - else{ - return stream.string.substr(0,stream.pos-1); - } -} - -// return a part of suffix of current stream from current position -function suffix(stream, c){ - var y=stream.string.length; - var x=y-stream.pos+1; - return stream.string.substr(stream.pos,(c&&c=(y=stream.string.length-1)) - stream.pos=y; - else - stream.pos=x; -} - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/php/index.html b/backend/_pv_1_3_5/static/codemirror/mode/php/index.html deleted file mode 100755 index adf6b1be2..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/php/index.html +++ /dev/null @@ -1,64 +0,0 @@ - - -CodeMirror: PHP mode - - - - - - - - - - - - - - - -
    -

    PHP mode

    -
    - - - -

    Simple HTML/PHP mode based on - the C-like mode. Depends on XML, - JavaScript, CSS, HTMLMixed, and C-like modes.

    - -

    MIME types defined: application/x-httpd-php (HTML with PHP code), text/x-php (plain, non-wrapped PHP code).

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/php/php.js b/backend/_pv_1_3_5/static/codemirror/mode/php/php.js deleted file mode 100755 index 57ba812d7..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/php/php.js +++ /dev/null @@ -1,234 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../clike/clike")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../clike/clike"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - function keywords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - // Helper for phpString - function matchSequence(list, end, escapes) { - if (list.length == 0) return phpString(end); - return function (stream, state) { - var patterns = list[0]; - for (var i = 0; i < patterns.length; i++) if (stream.match(patterns[i][0])) { - state.tokenize = matchSequence(list.slice(1), end); - return patterns[i][1]; - } - state.tokenize = phpString(end, escapes); - return "string"; - }; - } - function phpString(closing, escapes) { - return function(stream, state) { return phpString_(stream, state, closing, escapes); }; - } - function phpString_(stream, state, closing, escapes) { - // "Complex" syntax - if (escapes !== false && stream.match("${", false) || stream.match("{$", false)) { - state.tokenize = null; - return "string"; - } - - // Simple syntax - if (escapes !== false && stream.match(/^\$[a-zA-Z_][a-zA-Z0-9_]*/)) { - // After the variable name there may appear array or object operator. - if (stream.match("[", false)) { - // Match array operator - state.tokenize = matchSequence([ - [["[", null]], - [[/\d[\w\.]*/, "number"], - [/\$[a-zA-Z_][a-zA-Z0-9_]*/, "variable-2"], - [/[\w\$]+/, "variable"]], - [["]", null]] - ], closing, escapes); - } - if (stream.match(/\-\>\w/, false)) { - // Match object operator - state.tokenize = matchSequence([ - [["->", null]], - [[/[\w]+/, "variable"]] - ], closing, escapes); - } - return "variable-2"; - } - - var escaped = false; - // Normal string - while (!stream.eol() && - (escaped || escapes === false || - (!stream.match("{$", false) && - !stream.match(/^(\$[a-zA-Z_][a-zA-Z0-9_]*|\$\{)/, false)))) { - if (!escaped && stream.match(closing)) { - state.tokenize = null; - state.tokStack.pop(); state.tokStack.pop(); - break; - } - escaped = stream.next() == "\\" && !escaped; - } - return "string"; - } - - var phpKeywords = "abstract and array as break case catch class clone const continue declare default " + - "do else elseif enddeclare endfor endforeach endif endswitch endwhile extends final " + - "for foreach function global goto if implements interface instanceof namespace " + - "new or private protected public static switch throw trait try use var while xor " + - "die echo empty exit eval include include_once isset list require require_once return " + - "print unset __halt_compiler self static parent yield insteadof finally"; - var phpAtoms = "true false null TRUE FALSE NULL __CLASS__ __DIR__ __FILE__ __LINE__ __METHOD__ __FUNCTION__ __NAMESPACE__ __TRAIT__"; - var phpBuiltin = "func_num_args func_get_arg func_get_args strlen strcmp strncmp strcasecmp strncasecmp each error_reporting define defined trigger_error user_error set_error_handler restore_error_handler get_declared_classes get_loaded_extensions extension_loaded get_extension_funcs debug_backtrace constant bin2hex hex2bin sleep usleep time mktime gmmktime strftime gmstrftime strtotime date gmdate getdate localtime checkdate flush wordwrap htmlspecialchars htmlentities html_entity_decode md5 md5_file crc32 getimagesize image_type_to_mime_type phpinfo phpversion phpcredits strnatcmp strnatcasecmp substr_count strspn strcspn strtok strtoupper strtolower strpos strrpos strrev hebrev hebrevc nl2br basename dirname pathinfo stripslashes stripcslashes strstr stristr strrchr str_shuffle str_word_count strcoll substr substr_replace quotemeta ucfirst ucwords strtr addslashes addcslashes rtrim str_replace str_repeat count_chars chunk_split trim ltrim strip_tags similar_text explode implode setlocale localeconv parse_str str_pad chop strchr sprintf printf vprintf vsprintf sscanf fscanf parse_url urlencode urldecode rawurlencode rawurldecode readlink linkinfo link unlink exec system escapeshellcmd escapeshellarg passthru shell_exec proc_open proc_close rand srand getrandmax mt_rand mt_srand mt_getrandmax base64_decode base64_encode abs ceil floor round is_finite is_nan is_infinite bindec hexdec octdec decbin decoct dechex base_convert number_format fmod ip2long long2ip getenv putenv getopt microtime gettimeofday getrusage uniqid quoted_printable_decode set_time_limit get_cfg_var magic_quotes_runtime set_magic_quotes_runtime get_magic_quotes_gpc get_magic_quotes_runtime import_request_variables error_log serialize unserialize memory_get_usage var_dump var_export debug_zval_dump print_r highlight_file show_source highlight_string ini_get ini_get_all ini_set ini_alter ini_restore get_include_path set_include_path restore_include_path setcookie header headers_sent connection_aborted connection_status ignore_user_abort parse_ini_file is_uploaded_file move_uploaded_file intval floatval doubleval strval gettype settype is_null is_resource is_bool is_long is_float is_int is_integer is_double is_real is_numeric is_string is_array is_object is_scalar ereg ereg_replace eregi eregi_replace split spliti join sql_regcase dl pclose popen readfile rewind rmdir umask fclose feof fgetc fgets fgetss fread fopen fpassthru ftruncate fstat fseek ftell fflush fwrite fputs mkdir rename copy tempnam tmpfile file file_get_contents file_put_contents stream_select stream_context_create stream_context_set_params stream_context_set_option stream_context_get_options stream_filter_prepend stream_filter_append fgetcsv flock get_meta_tags stream_set_write_buffer set_file_buffer set_socket_blocking stream_set_blocking socket_set_blocking stream_get_meta_data stream_register_wrapper stream_wrapper_register stream_set_timeout socket_set_timeout socket_get_status realpath fnmatch fsockopen pfsockopen pack unpack get_browser crypt opendir closedir chdir getcwd rewinddir readdir dir glob fileatime filectime filegroup fileinode filemtime fileowner fileperms filesize filetype file_exists is_writable is_writeable is_readable is_executable is_file is_dir is_link stat lstat chown touch clearstatcache mail ob_start ob_flush ob_clean ob_end_flush ob_end_clean ob_get_flush ob_get_clean ob_get_length ob_get_level ob_get_status ob_get_contents ob_implicit_flush ob_list_handlers ksort krsort natsort natcasesort asort arsort sort rsort usort uasort uksort shuffle array_walk count end prev next reset current key min max in_array array_search extract compact array_fill range array_multisort array_push array_pop array_shift array_unshift array_splice array_slice array_merge array_merge_recursive array_keys array_values array_count_values array_reverse array_reduce array_pad array_flip array_change_key_case array_rand array_unique array_intersect array_intersect_assoc array_diff array_diff_assoc array_sum array_filter array_map array_chunk array_key_exists array_intersect_key array_combine array_column pos sizeof key_exists assert assert_options version_compare ftok str_rot13 aggregate session_name session_module_name session_save_path session_id session_regenerate_id session_decode session_register session_unregister session_is_registered session_encode session_start session_destroy session_unset session_set_save_handler session_cache_limiter session_cache_expire session_set_cookie_params session_get_cookie_params session_write_close preg_match preg_match_all preg_replace preg_replace_callback preg_split preg_quote preg_grep overload ctype_alnum ctype_alpha ctype_cntrl ctype_digit ctype_lower ctype_graph ctype_print ctype_punct ctype_space ctype_upper ctype_xdigit virtual apache_request_headers apache_note apache_lookup_uri apache_child_terminate apache_setenv apache_response_headers apache_get_version getallheaders mysql_connect mysql_pconnect mysql_close mysql_select_db mysql_create_db mysql_drop_db mysql_query mysql_unbuffered_query mysql_db_query mysql_list_dbs mysql_list_tables mysql_list_fields mysql_list_processes mysql_error mysql_errno mysql_affected_rows mysql_insert_id mysql_result mysql_num_rows mysql_num_fields mysql_fetch_row mysql_fetch_array mysql_fetch_assoc mysql_fetch_object mysql_data_seek mysql_fetch_lengths mysql_fetch_field mysql_field_seek mysql_free_result mysql_field_name mysql_field_table mysql_field_len mysql_field_type mysql_field_flags mysql_escape_string mysql_real_escape_string mysql_stat mysql_thread_id mysql_client_encoding mysql_get_client_info mysql_get_host_info mysql_get_proto_info mysql_get_server_info mysql_info mysql mysql_fieldname mysql_fieldtable mysql_fieldlen mysql_fieldtype mysql_fieldflags mysql_selectdb mysql_createdb mysql_dropdb mysql_freeresult mysql_numfields mysql_numrows mysql_listdbs mysql_listtables mysql_listfields mysql_db_name mysql_dbname mysql_tablename mysql_table_name pg_connect pg_pconnect pg_close pg_connection_status pg_connection_busy pg_connection_reset pg_host pg_dbname pg_port pg_tty pg_options pg_ping pg_query pg_send_query pg_cancel_query pg_fetch_result pg_fetch_row pg_fetch_assoc pg_fetch_array pg_fetch_object pg_fetch_all pg_affected_rows pg_get_result pg_result_seek pg_result_status pg_free_result pg_last_oid pg_num_rows pg_num_fields pg_field_name pg_field_num pg_field_size pg_field_type pg_field_prtlen pg_field_is_null pg_get_notify pg_get_pid pg_result_error pg_last_error pg_last_notice pg_put_line pg_end_copy pg_copy_to pg_copy_from pg_trace pg_untrace pg_lo_create pg_lo_unlink pg_lo_open pg_lo_close pg_lo_read pg_lo_write pg_lo_read_all pg_lo_import pg_lo_export pg_lo_seek pg_lo_tell pg_escape_string pg_escape_bytea pg_unescape_bytea pg_client_encoding pg_set_client_encoding pg_meta_data pg_convert pg_insert pg_update pg_delete pg_select pg_exec pg_getlastoid pg_cmdtuples pg_errormessage pg_numrows pg_numfields pg_fieldname pg_fieldsize pg_fieldtype pg_fieldnum pg_fieldprtlen pg_fieldisnull pg_freeresult pg_result pg_loreadall pg_locreate pg_lounlink pg_loopen pg_loclose pg_loread pg_lowrite pg_loimport pg_loexport http_response_code get_declared_traits getimagesizefromstring socket_import_stream stream_set_chunk_size trait_exists header_register_callback class_uses session_status session_register_shutdown echo print global static exit array empty eval isset unset die include require include_once require_once json_decode json_encode json_last_error json_last_error_msg curl_close curl_copy_handle curl_errno curl_error curl_escape curl_exec curl_file_create curl_getinfo curl_init curl_multi_add_handle curl_multi_close curl_multi_exec curl_multi_getcontent curl_multi_info_read curl_multi_init curl_multi_remove_handle curl_multi_select curl_multi_setopt curl_multi_strerror curl_pause curl_reset curl_setopt_array curl_setopt curl_share_close curl_share_init curl_share_setopt curl_strerror curl_unescape curl_version mysqli_affected_rows mysqli_autocommit mysqli_change_user mysqli_character_set_name mysqli_close mysqli_commit mysqli_connect_errno mysqli_connect_error mysqli_connect mysqli_data_seek mysqli_debug mysqli_dump_debug_info mysqli_errno mysqli_error_list mysqli_error mysqli_fetch_all mysqli_fetch_array mysqli_fetch_assoc mysqli_fetch_field_direct mysqli_fetch_field mysqli_fetch_fields mysqli_fetch_lengths mysqli_fetch_object mysqli_fetch_row mysqli_field_count mysqli_field_seek mysqli_field_tell mysqli_free_result mysqli_get_charset mysqli_get_client_info mysqli_get_client_stats mysqli_get_client_version mysqli_get_connection_stats mysqli_get_host_info mysqli_get_proto_info mysqli_get_server_info mysqli_get_server_version mysqli_info mysqli_init mysqli_insert_id mysqli_kill mysqli_more_results mysqli_multi_query mysqli_next_result mysqli_num_fields mysqli_num_rows mysqli_options mysqli_ping mysqli_prepare mysqli_query mysqli_real_connect mysqli_real_escape_string mysqli_real_query mysqli_reap_async_query mysqli_refresh mysqli_rollback mysqli_select_db mysqli_set_charset mysqli_set_local_infile_default mysqli_set_local_infile_handler mysqli_sqlstate mysqli_ssl_set mysqli_stat mysqli_stmt_init mysqli_store_result mysqli_thread_id mysqli_thread_safe mysqli_use_result mysqli_warning_count"; - CodeMirror.registerHelper("hintWords", "php", [phpKeywords, phpAtoms, phpBuiltin].join(" ").split(" ")); - CodeMirror.registerHelper("wordChars", "php", /[\w$]/); - - var phpConfig = { - name: "clike", - helperType: "php", - keywords: keywords(phpKeywords), - blockKeywords: keywords("catch do else elseif for foreach if switch try while finally"), - defKeywords: keywords("class function interface namespace trait"), - atoms: keywords(phpAtoms), - builtin: keywords(phpBuiltin), - multiLineStrings: true, - hooks: { - "$": function(stream) { - stream.eatWhile(/[\w\$_]/); - return "variable-2"; - }, - "<": function(stream, state) { - var before; - if (before = stream.match(/<<\s*/)) { - var quoted = stream.eat(/['"]/); - stream.eatWhile(/[\w\.]/); - var delim = stream.current().slice(before[0].length + (quoted ? 2 : 1)); - if (quoted) stream.eat(quoted); - if (delim) { - (state.tokStack || (state.tokStack = [])).push(delim, 0); - state.tokenize = phpString(delim, quoted != "'"); - return "string"; - } - } - return false; - }, - "#": function(stream) { - while (!stream.eol() && !stream.match("?>", false)) stream.next(); - return "comment"; - }, - "/": function(stream) { - if (stream.eat("/")) { - while (!stream.eol() && !stream.match("?>", false)) stream.next(); - return "comment"; - } - return false; - }, - '"': function(_stream, state) { - (state.tokStack || (state.tokStack = [])).push('"', 0); - state.tokenize = phpString('"'); - return "string"; - }, - "{": function(_stream, state) { - if (state.tokStack && state.tokStack.length) - state.tokStack[state.tokStack.length - 1]++; - return false; - }, - "}": function(_stream, state) { - if (state.tokStack && state.tokStack.length > 0 && - !--state.tokStack[state.tokStack.length - 1]) { - state.tokenize = phpString(state.tokStack[state.tokStack.length - 2]); - } - return false; - } - } - }; - - CodeMirror.defineMode("php", function(config, parserConfig) { - var htmlMode = CodeMirror.getMode(config, "text/html"); - var phpMode = CodeMirror.getMode(config, phpConfig); - - function dispatch(stream, state) { - var isPHP = state.curMode == phpMode; - if (stream.sol() && state.pending && state.pending != '"' && state.pending != "'") state.pending = null; - if (!isPHP) { - if (stream.match(/^<\?\w*/)) { - state.curMode = phpMode; - if (!state.php) state.php = CodeMirror.startState(phpMode, htmlMode.indent(state.html, "")) - state.curState = state.php; - return "meta"; - } - if (state.pending == '"' || state.pending == "'") { - while (!stream.eol() && stream.next() != state.pending) {} - var style = "string"; - } else if (state.pending && stream.pos < state.pending.end) { - stream.pos = state.pending.end; - var style = state.pending.style; - } else { - var style = htmlMode.token(stream, state.curState); - } - if (state.pending) state.pending = null; - var cur = stream.current(), openPHP = cur.search(/<\?/), m; - if (openPHP != -1) { - if (style == "string" && (m = cur.match(/[\'\"]$/)) && !/\?>/.test(cur)) state.pending = m[0]; - else state.pending = {end: stream.pos, style: style}; - stream.backUp(cur.length - openPHP); - } - return style; - } else if (isPHP && state.php.tokenize == null && stream.match("?>")) { - state.curMode = htmlMode; - state.curState = state.html; - if (!state.php.context.prev) state.php = null; - return "meta"; - } else { - return phpMode.token(stream, state.curState); - } - } - - return { - startState: function() { - var html = CodeMirror.startState(htmlMode) - var php = parserConfig.startOpen ? CodeMirror.startState(phpMode) : null - return {html: html, - php: php, - curMode: parserConfig.startOpen ? phpMode : htmlMode, - curState: parserConfig.startOpen ? php : html, - pending: null}; - }, - - copyState: function(state) { - var html = state.html, htmlNew = CodeMirror.copyState(htmlMode, html), - php = state.php, phpNew = php && CodeMirror.copyState(phpMode, php), cur; - if (state.curMode == htmlMode) cur = htmlNew; - else cur = phpNew; - return {html: htmlNew, php: phpNew, curMode: state.curMode, curState: cur, - pending: state.pending}; - }, - - token: dispatch, - - indent: function(state, textAfter) { - if ((state.curMode != phpMode && /^\s*<\//.test(textAfter)) || - (state.curMode == phpMode && /^\?>/.test(textAfter))) - return htmlMode.indent(state.html, textAfter); - return state.curMode.indent(state.curState, textAfter); - }, - - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: "//", - - innerMode: function(state) { return {state: state.curState, mode: state.curMode}; } - }; - }, "htmlmixed", "clike"); - - CodeMirror.defineMIME("application/x-httpd-php", "php"); - CodeMirror.defineMIME("application/x-httpd-php-open", {name: "php", startOpen: true}); - CodeMirror.defineMIME("text/x-php", phpConfig); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/php/test.js b/backend/_pv_1_3_5/static/codemirror/mode/php/test.js deleted file mode 100755 index e2ecefc18..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/php/test.js +++ /dev/null @@ -1,154 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "php"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT('simple_test', - '[meta ]'); - - MT('variable_interpolation_non_alphanumeric', - '[meta $/$\\$}$\\\"$:$;$?$|$[[$]]$+$=aaa"]', - '[meta ?>]'); - - MT('variable_interpolation_digits', - '[meta ]'); - - MT('variable_interpolation_simple_syntax_1', - '[meta ]'); - - MT('variable_interpolation_simple_syntax_2', - '[meta ]'); - - MT('variable_interpolation_simple_syntax_3', - '[meta [variable aaaaa][string .aaaaaa"];', - '[keyword echo] [string "aaa][variable-2 $aaaa][string ->][variable-2 $aaaaa][string .aaaaaa"];', - '[keyword echo] [string "aaa][variable-2 $aaaa]->[variable aaaaa][string [[2]].aaaaaa"];', - '[keyword echo] [string "aaa][variable-2 $aaaa]->[variable aaaaa][string ->aaaa2.aaaaaa"];', - '[meta ?>]'); - - MT('variable_interpolation_escaping', - '[meta aaa.aaa"];', - '[keyword echo] [string "aaa\\$aaaa[[2]]aaa.aaa"];', - '[keyword echo] [string "aaa\\$aaaa[[asd]]aaa.aaa"];', - '[keyword echo] [string "aaa{\\$aaaa->aaa.aaa"];', - '[keyword echo] [string "aaa{\\$aaaa[[2]]aaa.aaa"];', - '[keyword echo] [string "aaa{\\aaaaa[[asd]]aaa.aaa"];', - '[keyword echo] [string "aaa\\${aaaa->aaa.aaa"];', - '[keyword echo] [string "aaa\\${aaaa[[2]]aaa.aaa"];', - '[keyword echo] [string "aaa\\${aaaa[[asd]]aaa.aaa"];', - '[meta ?>]'); - - MT('variable_interpolation_complex_syntax_1', - '[meta aaa.aaa"];', - '[keyword echo] [string "aaa][variable-2 $]{[variable-2 $aaaa]}[string ->aaa.aaa"];', - '[keyword echo] [string "aaa][variable-2 $]{[variable-2 $aaaa][[',' [number 42]',']]}[string ->aaa.aaa"];', - '[keyword echo] [string "aaa][variable-2 $]{[variable aaaa][meta ?>]aaaaaa'); - - MT('variable_interpolation_complex_syntax_2', - '[meta } $aaaaaa.aaa"];', - '[keyword echo] [string "][variable-2 $]{[variable aaa][comment /*}?>*/][[',' [string "aaa][variable-2 $aaa][string {}][variable-2 $]{[variable aaa]}[string "]',']]}[string ->aaa.aaa"];', - '[keyword echo] [string "][variable-2 $]{[variable aaa][comment /*} } $aaa } */]}[string ->aaa.aaa"];'); - - - function build_recursive_monsters(nt, t, n){ - var monsters = [t]; - for (var i = 1; i <= n; ++i) - monsters[i] = nt.join(monsters[i - 1]); - return monsters; - } - - var m1 = build_recursive_monsters( - ['[string "][variable-2 $]{[variable aaa] [operator +] ', '}[string "]'], - '[comment /* }?>} */] [string "aaa][variable-2 $aaa][string .aaa"]', - 10 - ); - - MT('variable_interpolation_complex_syntax_3_1', - '[meta ]'); - - var m2 = build_recursive_monsters( - ['[string "a][variable-2 $]{[variable aaa] [operator +] ', ' [operator +] ', '}[string .a"]'], - '[comment /* }?>{{ */] [string "a?>}{{aa][variable-2 $aaa][string .a}a?>a"]', - 5 - ); - - MT('variable_interpolation_complex_syntax_3_2', - '[meta ]'); - - function build_recursive_monsters_2(mf1, mf2, nt, t, n){ - var monsters = [t]; - for (var i = 1; i <= n; ++i) - monsters[i] = nt[0] + mf1[i - 1] + nt[1] + mf2[i - 1] + nt[2] + monsters[i - 1] + nt[3]; - return monsters; - } - - var m3 = build_recursive_monsters_2( - m1, - m2, - ['[string "a][variable-2 $]{[variable aaa] [operator +] ', ' [operator +] ', ' [operator +] ', '}[string .a"]'], - '[comment /* }?>{{ */] [string "a?>}{{aa][variable-2 $aaa][string .a}a?>a"]', - 4 - ); - - MT('variable_interpolation_complex_syntax_3_3', - '[meta ]'); - - MT("variable_interpolation_heredoc", - "[meta -CodeMirror: Pig Latin mode - - - - - - - - - -
    -

    Pig Latin mode

    -
    - - - -

    - Simple mode that handles Pig Latin language. -

    - -

    MIME type defined: text/x-pig - (PIG code) -

    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/pig/pig.js b/backend/_pv_1_3_5/static/codemirror/mode/pig/pig.js deleted file mode 100755 index 5b567272e..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/pig/pig.js +++ /dev/null @@ -1,178 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/* - * Pig Latin Mode for CodeMirror 2 - * @author Prasanth Jayachandran - * @link https://github.com/prasanthj/pig-codemirror-2 - * This implementation is adapted from PL/SQL mode in CodeMirror 2. - */ -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("pig", function(_config, parserConfig) { - var keywords = parserConfig.keywords, - builtins = parserConfig.builtins, - types = parserConfig.types, - multiLineStrings = parserConfig.multiLineStrings; - - var isOperatorChar = /[*+\-%<>=&?:\/!|]/; - - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - - function tokenComment(stream, state) { - var isEnd = false; - var ch; - while(ch = stream.next()) { - if(ch == "/" && isEnd) { - state.tokenize = tokenBase; - break; - } - isEnd = (ch == "*"); - } - return "comment"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while((next = stream.next()) != null) { - if (next == quote && !escaped) { - end = true; break; - } - escaped = !escaped && next == "\\"; - } - if (end || !(escaped || multiLineStrings)) - state.tokenize = tokenBase; - return "error"; - }; - } - - - function tokenBase(stream, state) { - var ch = stream.next(); - - // is a start of string? - if (ch == '"' || ch == "'") - return chain(stream, state, tokenString(ch)); - // is it one of the special chars - else if(/[\[\]{}\(\),;\.]/.test(ch)) - return null; - // is it a number? - else if(/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - // multi line comment or operator - else if (ch == "/") { - if (stream.eat("*")) { - return chain(stream, state, tokenComment); - } - else { - stream.eatWhile(isOperatorChar); - return "operator"; - } - } - // single line comment or operator - else if (ch=="-") { - if(stream.eat("-")){ - stream.skipToEnd(); - return "comment"; - } - else { - stream.eatWhile(isOperatorChar); - return "operator"; - } - } - // is it an operator - else if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - else { - // get the while word - stream.eatWhile(/[\w\$_]/); - // is it one of the listed keywords? - if (keywords && keywords.propertyIsEnumerable(stream.current().toUpperCase())) { - //keywords can be used as variables like flatten(group), group.$0 etc.. - if (!stream.eat(")") && !stream.eat(".")) - return "keyword"; - } - // is it one of the builtin functions? - if (builtins && builtins.propertyIsEnumerable(stream.current().toUpperCase())) - return "variable-2"; - // is it one of the listed types? - if (types && types.propertyIsEnumerable(stream.current().toUpperCase())) - return "variable-3"; - // default is a 'variable' - return "variable"; - } - } - - // Interface - return { - startState: function() { - return { - tokenize: tokenBase, - startOfLine: true - }; - }, - - token: function(stream, state) { - if(stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - return style; - } - }; -}); - -(function() { - function keywords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - // builtin funcs taken from trunk revision 1303237 - var pBuiltins = "ABS ACOS ARITY ASIN ATAN AVG BAGSIZE BINSTORAGE BLOOM BUILDBLOOM CBRT CEIL " - + "CONCAT COR COS COSH COUNT COUNT_STAR COV CONSTANTSIZE CUBEDIMENSIONS DIFF DISTINCT DOUBLEABS " - + "DOUBLEAVG DOUBLEBASE DOUBLEMAX DOUBLEMIN DOUBLEROUND DOUBLESUM EXP FLOOR FLOATABS FLOATAVG " - + "FLOATMAX FLOATMIN FLOATROUND FLOATSUM GENERICINVOKER INDEXOF INTABS INTAVG INTMAX INTMIN " - + "INTSUM INVOKEFORDOUBLE INVOKEFORFLOAT INVOKEFORINT INVOKEFORLONG INVOKEFORSTRING INVOKER " - + "ISEMPTY JSONLOADER JSONMETADATA JSONSTORAGE LAST_INDEX_OF LCFIRST LOG LOG10 LOWER LONGABS " - + "LONGAVG LONGMAX LONGMIN LONGSUM MAX MIN MAPSIZE MONITOREDUDF NONDETERMINISTIC OUTPUTSCHEMA " - + "PIGSTORAGE PIGSTREAMING RANDOM REGEX_EXTRACT REGEX_EXTRACT_ALL REPLACE ROUND SIN SINH SIZE " - + "SQRT STRSPLIT SUBSTRING SUM STRINGCONCAT STRINGMAX STRINGMIN STRINGSIZE TAN TANH TOBAG " - + "TOKENIZE TOMAP TOP TOTUPLE TRIM TEXTLOADER TUPLESIZE UCFIRST UPPER UTF8STORAGECONVERTER "; - - // taken from QueryLexer.g - var pKeywords = "VOID IMPORT RETURNS DEFINE LOAD FILTER FOREACH ORDER CUBE DISTINCT COGROUP " - + "JOIN CROSS UNION SPLIT INTO IF OTHERWISE ALL AS BY USING INNER OUTER ONSCHEMA PARALLEL " - + "PARTITION GROUP AND OR NOT GENERATE FLATTEN ASC DESC IS STREAM THROUGH STORE MAPREDUCE " - + "SHIP CACHE INPUT OUTPUT STDERROR STDIN STDOUT LIMIT SAMPLE LEFT RIGHT FULL EQ GT LT GTE LTE " - + "NEQ MATCHES TRUE FALSE DUMP"; - - // data types - var pTypes = "BOOLEAN INT LONG FLOAT DOUBLE CHARARRAY BYTEARRAY BAG TUPLE MAP "; - - CodeMirror.defineMIME("text/x-pig", { - name: "pig", - builtins: keywords(pBuiltins), - keywords: keywords(pKeywords), - types: keywords(pTypes) - }); - - CodeMirror.registerHelper("hintWords", "pig", (pBuiltins + pTypes + pKeywords).split(" ")); -}()); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/powershell/index.html b/backend/_pv_1_3_5/static/codemirror/mode/powershell/index.html deleted file mode 100755 index 6b235df8f..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/powershell/index.html +++ /dev/null @@ -1,204 +0,0 @@ - - - - - CodeMirror: Powershell mode - - - - - - - - -
    -

    PowerShell mode

    - -
    - - -

    MIME types defined: application/x-powershell.

    -
    - - diff --git a/backend/_pv_1_3_5/static/codemirror/mode/powershell/powershell.js b/backend/_pv_1_3_5/static/codemirror/mode/powershell/powershell.js deleted file mode 100755 index c443e7232..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/powershell/powershell.js +++ /dev/null @@ -1,396 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - 'use strict'; - if (typeof exports == 'object' && typeof module == 'object') // CommonJS - mod(require('codemirror')); - else if (typeof define == 'function' && define.amd) // AMD - define(['codemirror'], mod); - else // Plain browser env - mod(window.CodeMirror); -})(function(CodeMirror) { -'use strict'; - -CodeMirror.defineMode('powershell', function() { - function buildRegexp(patterns, options) { - options = options || {}; - var prefix = options.prefix !== undefined ? options.prefix : '^'; - var suffix = options.suffix !== undefined ? options.suffix : '\\b'; - - for (var i = 0; i < patterns.length; i++) { - if (patterns[i] instanceof RegExp) { - patterns[i] = patterns[i].source; - } - else { - patterns[i] = patterns[i].replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); - } - } - - return new RegExp(prefix + '(' + patterns.join('|') + ')' + suffix, 'i'); - } - - var notCharacterOrDash = '(?=[^A-Za-z\\d\\-_]|$)'; - var varNames = /[\w\-:]/ - var keywords = buildRegexp([ - /begin|break|catch|continue|data|default|do|dynamicparam/, - /else|elseif|end|exit|filter|finally|for|foreach|from|function|if|in/, - /param|process|return|switch|throw|trap|try|until|where|while/ - ], { suffix: notCharacterOrDash }); - - var punctuation = /[\[\]{},;`\.]|@[({]/; - var wordOperators = buildRegexp([ - 'f', - /b?not/, - /[ic]?split/, 'join', - /is(not)?/, 'as', - /[ic]?(eq|ne|[gl][te])/, - /[ic]?(not)?(like|match|contains)/, - /[ic]?replace/, - /b?(and|or|xor)/ - ], { prefix: '-' }); - var symbolOperators = /[+\-*\/%]=|\+\+|--|\.\.|[+\-*&^%:=!|\/]|<(?!#)|(?!#)>/; - var operators = buildRegexp([wordOperators, symbolOperators], { suffix: '' }); - - var numbers = /^((0x[\da-f]+)|((\d+\.\d+|\d\.|\.\d+|\d+)(e[\+\-]?\d+)?))[ld]?([kmgtp]b)?/i; - - var identifiers = /^[A-Za-z\_][A-Za-z\-\_\d]*\b/; - - var symbolBuiltins = /[A-Z]:|%|\?/i; - var namedBuiltins = buildRegexp([ - /Add-(Computer|Content|History|Member|PSSnapin|Type)/, - /Checkpoint-Computer/, - /Clear-(Content|EventLog|History|Host|Item(Property)?|Variable)/, - /Compare-Object/, - /Complete-Transaction/, - /Connect-PSSession/, - /ConvertFrom-(Csv|Json|SecureString|StringData)/, - /Convert-Path/, - /ConvertTo-(Csv|Html|Json|SecureString|Xml)/, - /Copy-Item(Property)?/, - /Debug-Process/, - /Disable-(ComputerRestore|PSBreakpoint|PSRemoting|PSSessionConfiguration)/, - /Disconnect-PSSession/, - /Enable-(ComputerRestore|PSBreakpoint|PSRemoting|PSSessionConfiguration)/, - /(Enter|Exit)-PSSession/, - /Export-(Alias|Clixml|Console|Counter|Csv|FormatData|ModuleMember|PSSession)/, - /ForEach-Object/, - /Format-(Custom|List|Table|Wide)/, - new RegExp('Get-(Acl|Alias|AuthenticodeSignature|ChildItem|Command|ComputerRestorePoint|Content|ControlPanelItem|Counter|Credential' - + '|Culture|Date|Event|EventLog|EventSubscriber|ExecutionPolicy|FormatData|Help|History|Host|HotFix|Item|ItemProperty|Job' - + '|Location|Member|Module|PfxCertificate|Process|PSBreakpoint|PSCallStack|PSDrive|PSProvider|PSSession|PSSessionConfiguration' - + '|PSSnapin|Random|Service|TraceSource|Transaction|TypeData|UICulture|Unique|Variable|Verb|WinEvent|WmiObject)'), - /Group-Object/, - /Import-(Alias|Clixml|Counter|Csv|LocalizedData|Module|PSSession)/, - /ImportSystemModules/, - /Invoke-(Command|Expression|History|Item|RestMethod|WebRequest|WmiMethod)/, - /Join-Path/, - /Limit-EventLog/, - /Measure-(Command|Object)/, - /Move-Item(Property)?/, - new RegExp('New-(Alias|Event|EventLog|Item(Property)?|Module|ModuleManifest|Object|PSDrive|PSSession|PSSessionConfigurationFile' - + '|PSSessionOption|PSTransportOption|Service|TimeSpan|Variable|WebServiceProxy|WinEvent)'), - /Out-(Default|File|GridView|Host|Null|Printer|String)/, - /Pause/, - /(Pop|Push)-Location/, - /Read-Host/, - /Receive-(Job|PSSession)/, - /Register-(EngineEvent|ObjectEvent|PSSessionConfiguration|WmiEvent)/, - /Remove-(Computer|Event|EventLog|Item(Property)?|Job|Module|PSBreakpoint|PSDrive|PSSession|PSSnapin|TypeData|Variable|WmiObject)/, - /Rename-(Computer|Item(Property)?)/, - /Reset-ComputerMachinePassword/, - /Resolve-Path/, - /Restart-(Computer|Service)/, - /Restore-Computer/, - /Resume-(Job|Service)/, - /Save-Help/, - /Select-(Object|String|Xml)/, - /Send-MailMessage/, - new RegExp('Set-(Acl|Alias|AuthenticodeSignature|Content|Date|ExecutionPolicy|Item(Property)?|Location|PSBreakpoint|PSDebug' + - '|PSSessionConfiguration|Service|StrictMode|TraceSource|Variable|WmiInstance)'), - /Show-(Command|ControlPanelItem|EventLog)/, - /Sort-Object/, - /Split-Path/, - /Start-(Job|Process|Service|Sleep|Transaction|Transcript)/, - /Stop-(Computer|Job|Process|Service|Transcript)/, - /Suspend-(Job|Service)/, - /TabExpansion2/, - /Tee-Object/, - /Test-(ComputerSecureChannel|Connection|ModuleManifest|Path|PSSessionConfigurationFile)/, - /Trace-Command/, - /Unblock-File/, - /Undo-Transaction/, - /Unregister-(Event|PSSessionConfiguration)/, - /Update-(FormatData|Help|List|TypeData)/, - /Use-Transaction/, - /Wait-(Event|Job|Process)/, - /Where-Object/, - /Write-(Debug|Error|EventLog|Host|Output|Progress|Verbose|Warning)/, - /cd|help|mkdir|more|oss|prompt/, - /ac|asnp|cat|cd|chdir|clc|clear|clhy|cli|clp|cls|clv|cnsn|compare|copy|cp|cpi|cpp|cvpa|dbp|del|diff|dir|dnsn|ebp/, - /echo|epal|epcsv|epsn|erase|etsn|exsn|fc|fl|foreach|ft|fw|gal|gbp|gc|gci|gcm|gcs|gdr|ghy|gi|gjb|gl|gm|gmo|gp|gps/, - /group|gsn|gsnp|gsv|gu|gv|gwmi|h|history|icm|iex|ihy|ii|ipal|ipcsv|ipmo|ipsn|irm|ise|iwmi|iwr|kill|lp|ls|man|md/, - /measure|mi|mount|move|mp|mv|nal|ndr|ni|nmo|npssc|nsn|nv|ogv|oh|popd|ps|pushd|pwd|r|rbp|rcjb|rcsn|rd|rdr|ren|ri/, - /rjb|rm|rmdir|rmo|rni|rnp|rp|rsn|rsnp|rujb|rv|rvpa|rwmi|sajb|sal|saps|sasv|sbp|sc|select|set|shcm|si|sl|sleep|sls/, - /sort|sp|spjb|spps|spsv|start|sujb|sv|swmi|tee|trcm|type|where|wjb|write/ - ], { prefix: '', suffix: '' }); - var variableBuiltins = buildRegexp([ - /[$?^_]|Args|ConfirmPreference|ConsoleFileName|DebugPreference|Error|ErrorActionPreference|ErrorView|ExecutionContext/, - /FormatEnumerationLimit|Home|Host|Input|MaximumAliasCount|MaximumDriveCount|MaximumErrorCount|MaximumFunctionCount/, - /MaximumHistoryCount|MaximumVariableCount|MyInvocation|NestedPromptLevel|OutputEncoding|Pid|Profile|ProgressPreference/, - /PSBoundParameters|PSCommandPath|PSCulture|PSDefaultParameterValues|PSEmailServer|PSHome|PSScriptRoot|PSSessionApplicationName/, - /PSSessionConfigurationName|PSSessionOption|PSUICulture|PSVersionTable|Pwd|ShellId|StackTrace|VerbosePreference/, - /WarningPreference|WhatIfPreference/, - - /Event|EventArgs|EventSubscriber|Sender/, - /Matches|Ofs|ForEach|LastExitCode|PSCmdlet|PSItem|PSSenderInfo|This/, - /true|false|null/ - ], { prefix: '\\$', suffix: '' }); - - var builtins = buildRegexp([symbolBuiltins, namedBuiltins, variableBuiltins], { suffix: notCharacterOrDash }); - - var grammar = { - keyword: keywords, - number: numbers, - operator: operators, - builtin: builtins, - punctuation: punctuation, - identifier: identifiers - }; - - // tokenizers - function tokenBase(stream, state) { - // Handle Comments - //var ch = stream.peek(); - - var parent = state.returnStack[state.returnStack.length - 1]; - if (parent && parent.shouldReturnFrom(state)) { - state.tokenize = parent.tokenize; - state.returnStack.pop(); - return state.tokenize(stream, state); - } - - if (stream.eatSpace()) { - return null; - } - - if (stream.eat('(')) { - state.bracketNesting += 1; - return 'punctuation'; - } - - if (stream.eat(')')) { - state.bracketNesting -= 1; - return 'punctuation'; - } - - for (var key in grammar) { - if (stream.match(grammar[key])) { - return key; - } - } - - var ch = stream.next(); - - // single-quote string - if (ch === "'") { - return tokenSingleQuoteString(stream, state); - } - - if (ch === '$') { - return tokenVariable(stream, state); - } - - // double-quote string - if (ch === '"') { - return tokenDoubleQuoteString(stream, state); - } - - if (ch === '<' && stream.eat('#')) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - - if (ch === '#') { - stream.skipToEnd(); - return 'comment'; - } - - if (ch === '@') { - var quoteMatch = stream.eat(/["']/); - if (quoteMatch && stream.eol()) { - state.tokenize = tokenMultiString; - state.startQuote = quoteMatch[0]; - return tokenMultiString(stream, state); - } else if (stream.peek().match(/[({]/)) { - return 'punctuation'; - } else if (stream.peek().match(varNames)) { - // splatted variable - return tokenVariable(stream, state); - } - } - return 'error'; - } - - function tokenSingleQuoteString(stream, state) { - var ch; - while ((ch = stream.peek()) != null) { - stream.next(); - - if (ch === "'" && !stream.eat("'")) { - state.tokenize = tokenBase; - return 'string'; - } - } - - return 'error'; - } - - function tokenDoubleQuoteString(stream, state) { - var ch; - while ((ch = stream.peek()) != null) { - if (ch === '$') { - state.tokenize = tokenStringInterpolation; - return 'string'; - } - - stream.next(); - if (ch === '`') { - stream.next(); - continue; - } - - if (ch === '"' && !stream.eat('"')) { - state.tokenize = tokenBase; - return 'string'; - } - } - - return 'error'; - } - - function tokenStringInterpolation(stream, state) { - return tokenInterpolation(stream, state, tokenDoubleQuoteString); - } - - function tokenMultiStringReturn(stream, state) { - state.tokenize = tokenMultiString; - state.startQuote = '"' - return tokenMultiString(stream, state); - } - - function tokenHereStringInterpolation(stream, state) { - return tokenInterpolation(stream, state, tokenMultiStringReturn); - } - - function tokenInterpolation(stream, state, parentTokenize) { - if (stream.match('$(')) { - var savedBracketNesting = state.bracketNesting; - state.returnStack.push({ - /*jshint loopfunc:true */ - shouldReturnFrom: function(state) { - return state.bracketNesting === savedBracketNesting; - }, - tokenize: parentTokenize - }); - state.tokenize = tokenBase; - state.bracketNesting += 1; - return 'punctuation'; - } else { - stream.next(); - state.returnStack.push({ - shouldReturnFrom: function() { return true; }, - tokenize: parentTokenize - }); - state.tokenize = tokenVariable; - return state.tokenize(stream, state); - } - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while ((ch = stream.next()) != null) { - if (maybeEnd && ch == '>') { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch === '#'); - } - return 'comment'; - } - - function tokenVariable(stream, state) { - var ch = stream.peek(); - if (stream.eat('{')) { - state.tokenize = tokenVariableWithBraces; - return tokenVariableWithBraces(stream, state); - } else if (ch != undefined && ch.match(varNames)) { - stream.eatWhile(varNames); - state.tokenize = tokenBase; - return 'variable-2'; - } else { - state.tokenize = tokenBase; - return 'error'; - } - } - - function tokenVariableWithBraces(stream, state) { - var ch; - while ((ch = stream.next()) != null) { - if (ch === '}') { - state.tokenize = tokenBase; - break; - } - } - return 'variable-2'; - } - - function tokenMultiString(stream, state) { - var quote = state.startQuote; - if (stream.sol() && stream.match(new RegExp(quote + '@'))) { - state.tokenize = tokenBase; - } - else if (quote === '"') { - while (!stream.eol()) { - var ch = stream.peek(); - if (ch === '$') { - state.tokenize = tokenHereStringInterpolation; - return 'string'; - } - - stream.next(); - if (ch === '`') { - stream.next(); - } - } - } - else { - stream.skipToEnd(); - } - - return 'string'; - } - - var external = { - startState: function() { - return { - returnStack: [], - bracketNesting: 0, - tokenize: tokenBase - }; - }, - - token: function(stream, state) { - return state.tokenize(stream, state); - }, - - blockCommentStart: '<#', - blockCommentEnd: '#>', - lineComment: '#', - fold: 'brace' - }; - return external; -}); - -CodeMirror.defineMIME('application/x-powershell', 'powershell'); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/powershell/test.js b/backend/_pv_1_3_5/static/codemirror/mode/powershell/test.js deleted file mode 100755 index 59b8e6fca..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/powershell/test.js +++ /dev/null @@ -1,72 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "powershell"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT('comment', '[number 1][comment # A]'); - MT('comment_multiline', '[number 1][comment <#]', - '[comment ABC]', - '[comment #>][number 2]'); - - [ - '0', '1234', - '12kb', '12mb', '12Gb', '12Tb', '12PB', '12L', '12D', '12lkb', '12dtb', - '1.234', '1.234e56', '1.', '1.e2', '.2', '.2e34', - '1.2MB', '1.kb', '.1dTB', '1.e1gb', '.2', '.2e34', - '0x1', '0xabcdef', '0x3tb', '0xelmb' - ].forEach(function(number) { - MT("number_" + number, "[number " + number + "]"); - }); - - MT('string_literal_escaping', "[string 'a''']"); - MT('string_literal_variable', "[string 'a $x']"); - MT('string_escaping_1', '[string "a `""]'); - MT('string_escaping_2', '[string "a """]'); - MT('string_variable_escaping', '[string "a `$x"]'); - MT('string_variable', '[string "a ][variable-2 $x][string b"]'); - MT('string_variable_spaces', '[string "a ][variable-2 ${x y}][string b"]'); - MT('string_expression', '[string "a ][punctuation $(][variable-2 $x][operator +][number 3][punctuation )][string b"]'); - MT('string_expression_nested', '[string "A][punctuation $(][string "a][punctuation $(][string "w"][punctuation )][string b"][punctuation )][string B"]'); - - MT('string_heredoc', '[string @"]', - '[string abc]', - '[string "@]'); - MT('string_heredoc_quotes', '[string @"]', - '[string abc "\']', - '[string "@]'); - MT('string_heredoc_variable', '[string @"]', - '[string a ][variable-2 $x][string b]', - '[string "@]'); - MT('string_heredoc_nested_string', '[string @"]', - '[string a][punctuation $(][string "w"][punctuation )][string b]', - '[string "@]'); - MT('string_heredoc_literal_quotes', "[string @']", - '[string abc "\']', - "[string '@]"); - - MT('array', "[punctuation @(][string 'a'][punctuation ,][string 'b'][punctuation )]"); - MT('hash', "[punctuation @{][string 'key'][operator :][string 'value'][punctuation }]"); - - MT('variable', "[variable-2 $test]"); - MT('variable_global', "[variable-2 $global:test]"); - MT('variable_spaces', "[variable-2 ${test test}]"); - MT('operator_splat', "[variable-2 @x]"); - MT('variable_builtin', "[builtin $ErrorActionPreference]"); - MT('variable_builtin_symbols', "[builtin $$]"); - - MT('operator', "[operator +]"); - MT('operator_unary', "[operator +][number 3]"); - MT('operator_long', "[operator -match]"); - - [ - '(', ')', '[[', ']]', '{', '}', ',', '`', ';', '.' - ].forEach(function(punctuation) { - MT("punctuation_" + punctuation.replace(/^[\[\]]/,''), "[punctuation " + punctuation + "]"); - }); - - MT('keyword', "[keyword if]"); - - MT('call_builtin', "[builtin Get-ChildItem]"); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/properties/index.html b/backend/_pv_1_3_5/static/codemirror/mode/properties/index.html deleted file mode 100755 index f885302de..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/properties/index.html +++ /dev/null @@ -1,53 +0,0 @@ - - -CodeMirror: Properties files mode - - - - - - - - - -
    -

    Properties files mode

    -
    - - -

    MIME types defined: text/x-properties, - text/x-ini.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/properties/properties.js b/backend/_pv_1_3_5/static/codemirror/mode/properties/properties.js deleted file mode 100755 index ef8bf37ee..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/properties/properties.js +++ /dev/null @@ -1,78 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("properties", function() { - return { - token: function(stream, state) { - var sol = stream.sol() || state.afterSection; - var eol = stream.eol(); - - state.afterSection = false; - - if (sol) { - if (state.nextMultiline) { - state.inMultiline = true; - state.nextMultiline = false; - } else { - state.position = "def"; - } - } - - if (eol && ! state.nextMultiline) { - state.inMultiline = false; - state.position = "def"; - } - - if (sol) { - while(stream.eatSpace()) {} - } - - var ch = stream.next(); - - if (sol && (ch === "#" || ch === "!" || ch === ";")) { - state.position = "comment"; - stream.skipToEnd(); - return "comment"; - } else if (sol && ch === "[") { - state.afterSection = true; - stream.skipTo("]"); stream.eat("]"); - return "header"; - } else if (ch === "=" || ch === ":") { - state.position = "quote"; - return null; - } else if (ch === "\\" && state.position === "quote") { - if (stream.eol()) { // end of line? - // Multiline value - state.nextMultiline = true; - } - } - - return state.position; - }, - - startState: function() { - return { - position : "def", // Current position, "def", "quote" or "comment" - nextMultiline : false, // Is the next line multiline value - inMultiline : false, // Is the current line a multiline value - afterSection : false // Did we just open a section - }; - } - - }; -}); - -CodeMirror.defineMIME("text/x-properties", "properties"); -CodeMirror.defineMIME("text/x-ini", "properties"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/protobuf/index.html b/backend/_pv_1_3_5/static/codemirror/mode/protobuf/index.html deleted file mode 100755 index cfe7b9dcd..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/protobuf/index.html +++ /dev/null @@ -1,64 +0,0 @@ - - -CodeMirror: ProtoBuf mode - - - - - - - - - -
    -

    ProtoBuf mode

    -
    - - -

    MIME types defined: text/x-protobuf.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/protobuf/protobuf.js b/backend/_pv_1_3_5/static/codemirror/mode/protobuf/protobuf.js deleted file mode 100755 index bcae276e8..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/protobuf/protobuf.js +++ /dev/null @@ -1,68 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - function wordRegexp(words) { - return new RegExp("^((" + words.join(")|(") + "))\\b", "i"); - }; - - var keywordArray = [ - "package", "message", "import", "syntax", - "required", "optional", "repeated", "reserved", "default", "extensions", "packed", - "bool", "bytes", "double", "enum", "float", "string", - "int32", "int64", "uint32", "uint64", "sint32", "sint64", "fixed32", "fixed64", "sfixed32", "sfixed64" - ]; - var keywords = wordRegexp(keywordArray); - - CodeMirror.registerHelper("hintWords", "protobuf", keywordArray); - - var identifiers = new RegExp("^[_A-Za-z\xa1-\uffff][_A-Za-z0-9\xa1-\uffff]*"); - - function tokenBase(stream) { - // whitespaces - if (stream.eatSpace()) return null; - - // Handle one line Comments - if (stream.match("//")) { - stream.skipToEnd(); - return "comment"; - } - - // Handle Number Literals - if (stream.match(/^[0-9\.+-]/, false)) { - if (stream.match(/^[+-]?0x[0-9a-fA-F]+/)) - return "number"; - if (stream.match(/^[+-]?\d*\.\d+([EeDd][+-]?\d+)?/)) - return "number"; - if (stream.match(/^[+-]?\d+([EeDd][+-]?\d+)?/)) - return "number"; - } - - // Handle Strings - if (stream.match(/^"([^"]|(""))*"/)) { return "string"; } - if (stream.match(/^'([^']|(''))*'/)) { return "string"; } - - // Handle words - if (stream.match(keywords)) { return "keyword"; } - if (stream.match(identifiers)) { return "variable"; } ; - - // Handle non-detected items - stream.next(); - return null; - }; - - CodeMirror.defineMode("protobuf", function() { - return {token: tokenBase}; - }); - - CodeMirror.defineMIME("text/x-protobuf", "protobuf"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/pug/index.html b/backend/_pv_1_3_5/static/codemirror/mode/pug/index.html deleted file mode 100755 index 1765853a1..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/pug/index.html +++ /dev/null @@ -1,70 +0,0 @@ - - -CodeMirror: Pug Templating Mode - - - - - - - - - - - - - -
    -

    Pug Templating Mode

    -
    - -

    The Pug Templating Mode

    -

    Created by Forbes Lindesay. Managed as part of a Brackets extension at https://github.com/ForbesLindesay/jade-brackets.

    -

    MIME type defined: text/x-pug, text/x-jade.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/pug/pug.js b/backend/_pv_1_3_5/static/codemirror/mode/pug/pug.js deleted file mode 100755 index 401823365..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/pug/pug.js +++ /dev/null @@ -1,591 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../javascript/javascript"), require("../css/css"), require("../htmlmixed/htmlmixed")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../javascript/javascript", "../css/css", "../htmlmixed/htmlmixed"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("pug", function (config) { - // token types - var KEYWORD = 'keyword'; - var DOCTYPE = 'meta'; - var ID = 'builtin'; - var CLASS = 'qualifier'; - - var ATTRS_NEST = { - '{': '}', - '(': ')', - '[': ']' - }; - - var jsMode = CodeMirror.getMode(config, 'javascript'); - - function State() { - this.javaScriptLine = false; - this.javaScriptLineExcludesColon = false; - - this.javaScriptArguments = false; - this.javaScriptArgumentsDepth = 0; - - this.isInterpolating = false; - this.interpolationNesting = 0; - - this.jsState = CodeMirror.startState(jsMode); - - this.restOfLine = ''; - - this.isIncludeFiltered = false; - this.isEach = false; - - this.lastTag = ''; - this.scriptType = ''; - - // Attributes Mode - this.isAttrs = false; - this.attrsNest = []; - this.inAttributeName = true; - this.attributeIsType = false; - this.attrValue = ''; - - // Indented Mode - this.indentOf = Infinity; - this.indentToken = ''; - - this.innerMode = null; - this.innerState = null; - - this.innerModeForLine = false; - } - /** - * Safely copy a state - * - * @return {State} - */ - State.prototype.copy = function () { - var res = new State(); - res.javaScriptLine = this.javaScriptLine; - res.javaScriptLineExcludesColon = this.javaScriptLineExcludesColon; - res.javaScriptArguments = this.javaScriptArguments; - res.javaScriptArgumentsDepth = this.javaScriptArgumentsDepth; - res.isInterpolating = this.isInterpolating; - res.interpolationNesting = this.interpolationNesting; - - res.jsState = CodeMirror.copyState(jsMode, this.jsState); - - res.innerMode = this.innerMode; - if (this.innerMode && this.innerState) { - res.innerState = CodeMirror.copyState(this.innerMode, this.innerState); - } - - res.restOfLine = this.restOfLine; - - res.isIncludeFiltered = this.isIncludeFiltered; - res.isEach = this.isEach; - res.lastTag = this.lastTag; - res.scriptType = this.scriptType; - res.isAttrs = this.isAttrs; - res.attrsNest = this.attrsNest.slice(); - res.inAttributeName = this.inAttributeName; - res.attributeIsType = this.attributeIsType; - res.attrValue = this.attrValue; - res.indentOf = this.indentOf; - res.indentToken = this.indentToken; - - res.innerModeForLine = this.innerModeForLine; - - return res; - }; - - function javaScript(stream, state) { - if (stream.sol()) { - // if javaScriptLine was set at end of line, ignore it - state.javaScriptLine = false; - state.javaScriptLineExcludesColon = false; - } - if (state.javaScriptLine) { - if (state.javaScriptLineExcludesColon && stream.peek() === ':') { - state.javaScriptLine = false; - state.javaScriptLineExcludesColon = false; - return; - } - var tok = jsMode.token(stream, state.jsState); - if (stream.eol()) state.javaScriptLine = false; - return tok || true; - } - } - function javaScriptArguments(stream, state) { - if (state.javaScriptArguments) { - if (state.javaScriptArgumentsDepth === 0 && stream.peek() !== '(') { - state.javaScriptArguments = false; - return; - } - if (stream.peek() === '(') { - state.javaScriptArgumentsDepth++; - } else if (stream.peek() === ')') { - state.javaScriptArgumentsDepth--; - } - if (state.javaScriptArgumentsDepth === 0) { - state.javaScriptArguments = false; - return; - } - - var tok = jsMode.token(stream, state.jsState); - return tok || true; - } - } - - function yieldStatement(stream) { - if (stream.match(/^yield\b/)) { - return 'keyword'; - } - } - - function doctype(stream) { - if (stream.match(/^(?:doctype) *([^\n]+)?/)) { - return DOCTYPE; - } - } - - function interpolation(stream, state) { - if (stream.match('#{')) { - state.isInterpolating = true; - state.interpolationNesting = 0; - return 'punctuation'; - } - } - - function interpolationContinued(stream, state) { - if (state.isInterpolating) { - if (stream.peek() === '}') { - state.interpolationNesting--; - if (state.interpolationNesting < 0) { - stream.next(); - state.isInterpolating = false; - return 'punctuation'; - } - } else if (stream.peek() === '{') { - state.interpolationNesting++; - } - return jsMode.token(stream, state.jsState) || true; - } - } - - function caseStatement(stream, state) { - if (stream.match(/^case\b/)) { - state.javaScriptLine = true; - return KEYWORD; - } - } - - function when(stream, state) { - if (stream.match(/^when\b/)) { - state.javaScriptLine = true; - state.javaScriptLineExcludesColon = true; - return KEYWORD; - } - } - - function defaultStatement(stream) { - if (stream.match(/^default\b/)) { - return KEYWORD; - } - } - - function extendsStatement(stream, state) { - if (stream.match(/^extends?\b/)) { - state.restOfLine = 'string'; - return KEYWORD; - } - } - - function append(stream, state) { - if (stream.match(/^append\b/)) { - state.restOfLine = 'variable'; - return KEYWORD; - } - } - function prepend(stream, state) { - if (stream.match(/^prepend\b/)) { - state.restOfLine = 'variable'; - return KEYWORD; - } - } - function block(stream, state) { - if (stream.match(/^block\b *(?:(prepend|append)\b)?/)) { - state.restOfLine = 'variable'; - return KEYWORD; - } - } - - function include(stream, state) { - if (stream.match(/^include\b/)) { - state.restOfLine = 'string'; - return KEYWORD; - } - } - - function includeFiltered(stream, state) { - if (stream.match(/^include:([a-zA-Z0-9\-]+)/, false) && stream.match('include')) { - state.isIncludeFiltered = true; - return KEYWORD; - } - } - - function includeFilteredContinued(stream, state) { - if (state.isIncludeFiltered) { - var tok = filter(stream, state); - state.isIncludeFiltered = false; - state.restOfLine = 'string'; - return tok; - } - } - - function mixin(stream, state) { - if (stream.match(/^mixin\b/)) { - state.javaScriptLine = true; - return KEYWORD; - } - } - - function call(stream, state) { - if (stream.match(/^\+([-\w]+)/)) { - if (!stream.match(/^\( *[-\w]+ *=/, false)) { - state.javaScriptArguments = true; - state.javaScriptArgumentsDepth = 0; - } - return 'variable'; - } - if (stream.match(/^\+#{/, false)) { - stream.next(); - state.mixinCallAfter = true; - return interpolation(stream, state); - } - } - function callArguments(stream, state) { - if (state.mixinCallAfter) { - state.mixinCallAfter = false; - if (!stream.match(/^\( *[-\w]+ *=/, false)) { - state.javaScriptArguments = true; - state.javaScriptArgumentsDepth = 0; - } - return true; - } - } - - function conditional(stream, state) { - if (stream.match(/^(if|unless|else if|else)\b/)) { - state.javaScriptLine = true; - return KEYWORD; - } - } - - function each(stream, state) { - if (stream.match(/^(- *)?(each|for)\b/)) { - state.isEach = true; - return KEYWORD; - } - } - function eachContinued(stream, state) { - if (state.isEach) { - if (stream.match(/^ in\b/)) { - state.javaScriptLine = true; - state.isEach = false; - return KEYWORD; - } else if (stream.sol() || stream.eol()) { - state.isEach = false; - } else if (stream.next()) { - while (!stream.match(/^ in\b/, false) && stream.next()); - return 'variable'; - } - } - } - - function whileStatement(stream, state) { - if (stream.match(/^while\b/)) { - state.javaScriptLine = true; - return KEYWORD; - } - } - - function tag(stream, state) { - var captures; - if (captures = stream.match(/^(\w(?:[-:\w]*\w)?)\/?/)) { - state.lastTag = captures[1].toLowerCase(); - if (state.lastTag === 'script') { - state.scriptType = 'application/javascript'; - } - return 'tag'; - } - } - - function filter(stream, state) { - if (stream.match(/^:([\w\-]+)/)) { - var innerMode; - if (config && config.innerModes) { - innerMode = config.innerModes(stream.current().substring(1)); - } - if (!innerMode) { - innerMode = stream.current().substring(1); - } - if (typeof innerMode === 'string') { - innerMode = CodeMirror.getMode(config, innerMode); - } - setInnerMode(stream, state, innerMode); - return 'atom'; - } - } - - function code(stream, state) { - if (stream.match(/^(!?=|-)/)) { - state.javaScriptLine = true; - return 'punctuation'; - } - } - - function id(stream) { - if (stream.match(/^#([\w-]+)/)) { - return ID; - } - } - - function className(stream) { - if (stream.match(/^\.([\w-]+)/)) { - return CLASS; - } - } - - function attrs(stream, state) { - if (stream.peek() == '(') { - stream.next(); - state.isAttrs = true; - state.attrsNest = []; - state.inAttributeName = true; - state.attrValue = ''; - state.attributeIsType = false; - return 'punctuation'; - } - } - - function attrsContinued(stream, state) { - if (state.isAttrs) { - if (ATTRS_NEST[stream.peek()]) { - state.attrsNest.push(ATTRS_NEST[stream.peek()]); - } - if (state.attrsNest[state.attrsNest.length - 1] === stream.peek()) { - state.attrsNest.pop(); - } else if (stream.eat(')')) { - state.isAttrs = false; - return 'punctuation'; - } - if (state.inAttributeName && stream.match(/^[^=,\)!]+/)) { - if (stream.peek() === '=' || stream.peek() === '!') { - state.inAttributeName = false; - state.jsState = CodeMirror.startState(jsMode); - if (state.lastTag === 'script' && stream.current().trim().toLowerCase() === 'type') { - state.attributeIsType = true; - } else { - state.attributeIsType = false; - } - } - return 'attribute'; - } - - var tok = jsMode.token(stream, state.jsState); - if (state.attributeIsType && tok === 'string') { - state.scriptType = stream.current().toString(); - } - if (state.attrsNest.length === 0 && (tok === 'string' || tok === 'variable' || tok === 'keyword')) { - try { - Function('', 'var x ' + state.attrValue.replace(/,\s*$/, '').replace(/^!/, '')); - state.inAttributeName = true; - state.attrValue = ''; - stream.backUp(stream.current().length); - return attrsContinued(stream, state); - } catch (ex) { - //not the end of an attribute - } - } - state.attrValue += stream.current(); - return tok || true; - } - } - - function attributesBlock(stream, state) { - if (stream.match(/^&attributes\b/)) { - state.javaScriptArguments = true; - state.javaScriptArgumentsDepth = 0; - return 'keyword'; - } - } - - function indent(stream) { - if (stream.sol() && stream.eatSpace()) { - return 'indent'; - } - } - - function comment(stream, state) { - if (stream.match(/^ *\/\/(-)?([^\n]*)/)) { - state.indentOf = stream.indentation(); - state.indentToken = 'comment'; - return 'comment'; - } - } - - function colon(stream) { - if (stream.match(/^: */)) { - return 'colon'; - } - } - - function text(stream, state) { - if (stream.match(/^(?:\| ?| )([^\n]+)/)) { - return 'string'; - } - if (stream.match(/^(<[^\n]*)/, false)) { - // html string - setInnerMode(stream, state, 'htmlmixed'); - state.innerModeForLine = true; - return innerMode(stream, state, true); - } - } - - function dot(stream, state) { - if (stream.eat('.')) { - var innerMode = null; - if (state.lastTag === 'script' && state.scriptType.toLowerCase().indexOf('javascript') != -1) { - innerMode = state.scriptType.toLowerCase().replace(/"|'/g, ''); - } else if (state.lastTag === 'style') { - innerMode = 'css'; - } - setInnerMode(stream, state, innerMode); - return 'dot'; - } - } - - function fail(stream) { - stream.next(); - return null; - } - - - function setInnerMode(stream, state, mode) { - mode = CodeMirror.mimeModes[mode] || mode; - mode = config.innerModes ? config.innerModes(mode) || mode : mode; - mode = CodeMirror.mimeModes[mode] || mode; - mode = CodeMirror.getMode(config, mode); - state.indentOf = stream.indentation(); - - if (mode && mode.name !== 'null') { - state.innerMode = mode; - } else { - state.indentToken = 'string'; - } - } - function innerMode(stream, state, force) { - if (stream.indentation() > state.indentOf || (state.innerModeForLine && !stream.sol()) || force) { - if (state.innerMode) { - if (!state.innerState) { - state.innerState = state.innerMode.startState ? CodeMirror.startState(state.innerMode, stream.indentation()) : {}; - } - return stream.hideFirstChars(state.indentOf + 2, function () { - return state.innerMode.token(stream, state.innerState) || true; - }); - } else { - stream.skipToEnd(); - return state.indentToken; - } - } else if (stream.sol()) { - state.indentOf = Infinity; - state.indentToken = null; - state.innerMode = null; - state.innerState = null; - } - } - function restOfLine(stream, state) { - if (stream.sol()) { - // if restOfLine was set at end of line, ignore it - state.restOfLine = ''; - } - if (state.restOfLine) { - stream.skipToEnd(); - var tok = state.restOfLine; - state.restOfLine = ''; - return tok; - } - } - - - function startState() { - return new State(); - } - function copyState(state) { - return state.copy(); - } - /** - * Get the next token in the stream - * - * @param {Stream} stream - * @param {State} state - */ - function nextToken(stream, state) { - var tok = innerMode(stream, state) - || restOfLine(stream, state) - || interpolationContinued(stream, state) - || includeFilteredContinued(stream, state) - || eachContinued(stream, state) - || attrsContinued(stream, state) - || javaScript(stream, state) - || javaScriptArguments(stream, state) - || callArguments(stream, state) - - || yieldStatement(stream, state) - || doctype(stream, state) - || interpolation(stream, state) - || caseStatement(stream, state) - || when(stream, state) - || defaultStatement(stream, state) - || extendsStatement(stream, state) - || append(stream, state) - || prepend(stream, state) - || block(stream, state) - || include(stream, state) - || includeFiltered(stream, state) - || mixin(stream, state) - || call(stream, state) - || conditional(stream, state) - || each(stream, state) - || whileStatement(stream, state) - || tag(stream, state) - || filter(stream, state) - || code(stream, state) - || id(stream, state) - || className(stream, state) - || attrs(stream, state) - || attributesBlock(stream, state) - || indent(stream, state) - || text(stream, state) - || comment(stream, state) - || colon(stream, state) - || dot(stream, state) - || fail(stream, state); - - return tok === true ? null : tok; - } - return { - startState: startState, - copyState: copyState, - token: nextToken - }; -}, 'javascript', 'css', 'htmlmixed'); - -CodeMirror.defineMIME('text/x-pug', 'pug'); -CodeMirror.defineMIME('text/x-jade', 'pug'); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/puppet/index.html b/backend/_pv_1_3_5/static/codemirror/mode/puppet/index.html deleted file mode 100755 index 5614c3695..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/puppet/index.html +++ /dev/null @@ -1,121 +0,0 @@ - - -CodeMirror: Puppet mode - - - - - - - - - - -
    -

    Puppet mode

    -
    - - -

    MIME types defined: text/x-puppet.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/puppet/puppet.js b/backend/_pv_1_3_5/static/codemirror/mode/puppet/puppet.js deleted file mode 100755 index 57041300a..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/puppet/puppet.js +++ /dev/null @@ -1,220 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("puppet", function () { - // Stores the words from the define method - var words = {}; - // Taken, mostly, from the Puppet official variable standards regex - var variable_regex = /({)?([a-z][a-z0-9_]*)?((::[a-z][a-z0-9_]*)*::)?[a-zA-Z0-9_]+(})?/; - - // Takes a string of words separated by spaces and adds them as - // keys with the value of the first argument 'style' - function define(style, string) { - var split = string.split(' '); - for (var i = 0; i < split.length; i++) { - words[split[i]] = style; - } - } - - // Takes commonly known puppet types/words and classifies them to a style - define('keyword', 'class define site node include import inherits'); - define('keyword', 'case if else in and elsif default or'); - define('atom', 'false true running present absent file directory undef'); - define('builtin', 'action augeas burst chain computer cron destination dport exec ' + - 'file filebucket group host icmp iniface interface jump k5login limit log_level ' + - 'log_prefix macauthorization mailalias maillist mcx mount nagios_command ' + - 'nagios_contact nagios_contactgroup nagios_host nagios_hostdependency ' + - 'nagios_hostescalation nagios_hostextinfo nagios_hostgroup nagios_service ' + - 'nagios_servicedependency nagios_serviceescalation nagios_serviceextinfo ' + - 'nagios_servicegroup nagios_timeperiod name notify outiface package proto reject ' + - 'resources router schedule scheduled_task selboolean selmodule service source ' + - 'sport ssh_authorized_key sshkey stage state table tidy todest toports tosource ' + - 'user vlan yumrepo zfs zone zpool'); - - // After finding a start of a string ('|") this function attempts to find the end; - // If a variable is encountered along the way, we display it differently when it - // is encapsulated in a double-quoted string. - function tokenString(stream, state) { - var current, prev, found_var = false; - while (!stream.eol() && (current = stream.next()) != state.pending) { - if (current === '$' && prev != '\\' && state.pending == '"') { - found_var = true; - break; - } - prev = current; - } - if (found_var) { - stream.backUp(1); - } - if (current == state.pending) { - state.continueString = false; - } else { - state.continueString = true; - } - return "string"; - } - - // Main function - function tokenize(stream, state) { - // Matches one whole word - var word = stream.match(/[\w]+/, false); - // Matches attributes (i.e. ensure => present ; 'ensure' would be matched) - var attribute = stream.match(/(\s+)?\w+\s+=>.*/, false); - // Matches non-builtin resource declarations - // (i.e. "apache::vhost {" or "mycustomclasss {" would be matched) - var resource = stream.match(/(\s+)?[\w:_]+(\s+)?{/, false); - // Matches virtual and exported resources (i.e. @@user { ; and the like) - var special_resource = stream.match(/(\s+)?[@]{1,2}[\w:_]+(\s+)?{/, false); - - // Finally advance the stream - var ch = stream.next(); - - // Have we found a variable? - if (ch === '$') { - if (stream.match(variable_regex)) { - // If so, and its in a string, assign it a different color - return state.continueString ? 'variable-2' : 'variable'; - } - // Otherwise return an invalid variable - return "error"; - } - // Should we still be looking for the end of a string? - if (state.continueString) { - // If so, go through the loop again - stream.backUp(1); - return tokenString(stream, state); - } - // Are we in a definition (class, node, define)? - if (state.inDefinition) { - // If so, return def (i.e. for 'class myclass {' ; 'myclass' would be matched) - if (stream.match(/(\s+)?[\w:_]+(\s+)?/)) { - return 'def'; - } - // Match the rest it the next time around - stream.match(/\s+{/); - state.inDefinition = false; - } - // Are we in an 'include' statement? - if (state.inInclude) { - // Match and return the included class - stream.match(/(\s+)?\S+(\s+)?/); - state.inInclude = false; - return 'def'; - } - // Do we just have a function on our hands? - // In 'ensure_resource("myclass")', 'ensure_resource' is matched - if (stream.match(/(\s+)?\w+\(/)) { - stream.backUp(1); - return 'def'; - } - // Have we matched the prior attribute regex? - if (attribute) { - stream.match(/(\s+)?\w+/); - return 'tag'; - } - // Do we have Puppet specific words? - if (word && words.hasOwnProperty(word)) { - // Negates the initial next() - stream.backUp(1); - // rs move the stream - stream.match(/[\w]+/); - // We want to process these words differently - // do to the importance they have in Puppet - if (stream.match(/\s+\S+\s+{/, false)) { - state.inDefinition = true; - } - if (word == 'include') { - state.inInclude = true; - } - // Returns their value as state in the prior define methods - return words[word]; - } - // Is there a match on a reference? - if (/(^|\s+)[A-Z][\w:_]+/.test(word)) { - // Negate the next() - stream.backUp(1); - // Match the full reference - stream.match(/(^|\s+)[A-Z][\w:_]+/); - return 'def'; - } - // Have we matched the prior resource regex? - if (resource) { - stream.match(/(\s+)?[\w:_]+/); - return 'def'; - } - // Have we matched the prior special_resource regex? - if (special_resource) { - stream.match(/(\s+)?[@]{1,2}/); - return 'special'; - } - // Match all the comments. All of them. - if (ch == "#") { - stream.skipToEnd(); - return "comment"; - } - // Have we found a string? - if (ch == "'" || ch == '"') { - // Store the type (single or double) - state.pending = ch; - // Perform the looping function to find the end - return tokenString(stream, state); - } - // Match all the brackets - if (ch == '{' || ch == '}') { - return 'bracket'; - } - // Match characters that we are going to assume - // are trying to be regex - if (ch == '/') { - stream.match(/.*?\//); - return 'variable-3'; - } - // Match all the numbers - if (ch.match(/[0-9]/)) { - stream.eatWhile(/[0-9]+/); - return 'number'; - } - // Match the '=' and '=>' operators - if (ch == '=') { - if (stream.peek() == '>') { - stream.next(); - } - return "operator"; - } - // Keep advancing through all the rest - stream.eatWhile(/[\w-]/); - // Return a blank line for everything else - return null; - } - // Start it all - return { - startState: function () { - var state = {}; - state.inDefinition = false; - state.inInclude = false; - state.continueString = false; - state.pending = false; - return state; - }, - token: function (stream, state) { - // Strip the spaces, but regex will account for them eitherway - if (stream.eatSpace()) return null; - // Go through the main process - return tokenize(stream, state); - } - }; -}); - -CodeMirror.defineMIME("text/x-puppet", "puppet"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/python/index.html b/backend/_pv_1_3_5/static/codemirror/mode/python/index.html deleted file mode 100755 index 0ac02a333..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/python/index.html +++ /dev/null @@ -1,198 +0,0 @@ - - -CodeMirror: Python mode - - - - - - - - - - -
    -

    Python mode

    - -
    - - -

    Cython mode

    - -
    - - -

    Configuration Options for Python mode:

    -
      -
    • version - 2/3 - The version of Python to recognize. Default is 3.
    • -
    • singleLineStringErrors - true/false - If you have a single-line string that is not terminated at the end of the line, this will show subsequent lines as errors if true, otherwise it will consider the newline as the end of the string. Default is false.
    • -
    • hangingIndent - int - If you want to write long arguments to a function starting on a new line, how much that line should be indented. Defaults to one normal indentation unit.
    • -
    -

    Advanced Configuration Options:

    -

    Usefull for superset of python syntax like Enthought enaml, IPython magics and questionmark help

    -
      -
    • singleOperators - RegEx - Regular Expression for single operator matching, default :
      ^[\\+\\-\\*/%&|\\^~<>!]
      including
      @
      on Python 3
    • -
    • singleDelimiters - RegEx - Regular Expression for single delimiter matching, default :
      ^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]
    • -
    • doubleOperators - RegEx - Regular Expression for double operators matching, default :
      ^((==)|(!=)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))
    • -
    • doubleDelimiters - RegEx - Regular Expression for double delimiters matching, default :
      ^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))
    • -
    • tripleDelimiters - RegEx - Regular Expression for triple delimiters matching, default :
      ^((//=)|(>>=)|(<<=)|(\\*\\*=))
    • -
    • identifiers - RegEx - Regular Expression for identifier, default :
      ^[_A-Za-z][_A-Za-z0-9]*
      on Python 2 and
      ^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*
      on Python 3.
    • -
    • extra_keywords - list of string - List of extra words ton consider as keywords
    • -
    • extra_builtins - list of string - List of extra words ton consider as builtins
    • -
    - - -

    MIME types defined: text/x-python and text/x-cython.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/python/python.js b/backend/_pv_1_3_5/static/codemirror/mode/python/python.js deleted file mode 100755 index 4310f9fb6..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/python/python.js +++ /dev/null @@ -1,340 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - function wordRegexp(words) { - return new RegExp("^((" + words.join(")|(") + "))\\b"); - } - - var wordOperators = wordRegexp(["and", "or", "not", "is"]); - var commonKeywords = ["as", "assert", "break", "class", "continue", - "def", "del", "elif", "else", "except", "finally", - "for", "from", "global", "if", "import", - "lambda", "pass", "raise", "return", - "try", "while", "with", "yield", "in"]; - var commonBuiltins = ["abs", "all", "any", "bin", "bool", "bytearray", "callable", "chr", - "classmethod", "compile", "complex", "delattr", "dict", "dir", "divmod", - "enumerate", "eval", "filter", "float", "format", "frozenset", - "getattr", "globals", "hasattr", "hash", "help", "hex", "id", - "input", "int", "isinstance", "issubclass", "iter", "len", - "list", "locals", "map", "max", "memoryview", "min", "next", - "object", "oct", "open", "ord", "pow", "property", "range", - "repr", "reversed", "round", "set", "setattr", "slice", - "sorted", "staticmethod", "str", "sum", "super", "tuple", - "type", "vars", "zip", "__import__", "NotImplemented", - "Ellipsis", "__debug__"]; - CodeMirror.registerHelper("hintWords", "python", commonKeywords.concat(commonBuiltins)); - - function top(state) { - return state.scopes[state.scopes.length - 1]; - } - - CodeMirror.defineMode("python", function(conf, parserConf) { - var ERRORCLASS = "error"; - - var singleDelimiters = parserConf.singleDelimiters || /^[\(\)\[\]\{\}@,:`=;\.]/; - var doubleOperators = parserConf.doubleOperators || /^([!<>]==|<>|<<|>>|\/\/|\*\*)/; - var doubleDelimiters = parserConf.doubleDelimiters || /^(\+=|\-=|\*=|%=|\/=|&=|\|=|\^=)/; - var tripleDelimiters = parserConf.tripleDelimiters || /^(\/\/=|>>=|<<=|\*\*=)/; - - var hangingIndent = parserConf.hangingIndent || conf.indentUnit; - - var myKeywords = commonKeywords, myBuiltins = commonBuiltins; - if (parserConf.extra_keywords != undefined) - myKeywords = myKeywords.concat(parserConf.extra_keywords); - - if (parserConf.extra_builtins != undefined) - myBuiltins = myBuiltins.concat(parserConf.extra_builtins); - - var py3 = !(parserConf.version && Number(parserConf.version) < 3) - if (py3) { - // since http://legacy.python.org/dev/peps/pep-0465/ @ is also an operator - var singleOperators = parserConf.singleOperators || /^[\+\-\*\/%&|\^~<>!@]/; - var identifiers = parserConf.identifiers|| /^[_A-Za-z\u00A1-\uFFFF][_A-Za-z0-9\u00A1-\uFFFF]*/; - myKeywords = myKeywords.concat(["nonlocal", "False", "True", "None", "async", "await"]); - myBuiltins = myBuiltins.concat(["ascii", "bytes", "exec", "print"]); - var stringPrefixes = new RegExp("^(([rbuf]|(br))?('{3}|\"{3}|['\"]))", "i"); - } else { - var singleOperators = parserConf.singleOperators || /^[\+\-\*\/%&|\^~<>!]/; - var identifiers = parserConf.identifiers|| /^[_A-Za-z][_A-Za-z0-9]*/; - myKeywords = myKeywords.concat(["exec", "print"]); - myBuiltins = myBuiltins.concat(["apply", "basestring", "buffer", "cmp", "coerce", "execfile", - "file", "intern", "long", "raw_input", "reduce", "reload", - "unichr", "unicode", "xrange", "False", "True", "None"]); - var stringPrefixes = new RegExp("^(([rubf]|(ur)|(br))?('{3}|\"{3}|['\"]))", "i"); - } - var keywords = wordRegexp(myKeywords); - var builtins = wordRegexp(myBuiltins); - - // tokenizers - function tokenBase(stream, state) { - if (stream.sol()) state.indent = stream.indentation() - // Handle scope changes - if (stream.sol() && top(state).type == "py") { - var scopeOffset = top(state).offset; - if (stream.eatSpace()) { - var lineOffset = stream.indentation(); - if (lineOffset > scopeOffset) - pushPyScope(state); - else if (lineOffset < scopeOffset && dedent(stream, state) && stream.peek() != "#") - state.errorToken = true; - return null; - } else { - var style = tokenBaseInner(stream, state); - if (scopeOffset > 0 && dedent(stream, state)) - style += " " + ERRORCLASS; - return style; - } - } - return tokenBaseInner(stream, state); - } - - function tokenBaseInner(stream, state) { - if (stream.eatSpace()) return null; - - var ch = stream.peek(); - - // Handle Comments - if (ch == "#") { - stream.skipToEnd(); - return "comment"; - } - - // Handle Number Literals - if (stream.match(/^[0-9\.]/, false)) { - var floatLiteral = false; - // Floats - if (stream.match(/^\d*\.\d+(e[\+\-]?\d+)?/i)) { floatLiteral = true; } - if (stream.match(/^\d+\.\d*/)) { floatLiteral = true; } - if (stream.match(/^\.\d+/)) { floatLiteral = true; } - if (floatLiteral) { - // Float literals may be "imaginary" - stream.eat(/J/i); - return "number"; - } - // Integers - var intLiteral = false; - // Hex - if (stream.match(/^0x[0-9a-f]+/i)) intLiteral = true; - // Binary - if (stream.match(/^0b[01]+/i)) intLiteral = true; - // Octal - if (stream.match(/^0o[0-7]+/i)) intLiteral = true; - // Decimal - if (stream.match(/^[1-9]\d*(e[\+\-]?\d+)?/)) { - // Decimal literals may be "imaginary" - stream.eat(/J/i); - // TODO - Can you have imaginary longs? - intLiteral = true; - } - // Zero by itself with no other piece of number. - if (stream.match(/^0(?![\dx])/i)) intLiteral = true; - if (intLiteral) { - // Integer literals may be "long" - stream.eat(/L/i); - return "number"; - } - } - - // Handle Strings - if (stream.match(stringPrefixes)) { - state.tokenize = tokenStringFactory(stream.current()); - return state.tokenize(stream, state); - } - - // Handle operators and Delimiters - if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) - return "punctuation"; - - if (stream.match(doubleOperators) || stream.match(singleOperators)) - return "operator"; - - if (stream.match(singleDelimiters)) - return "punctuation"; - - if (state.lastToken == "." && stream.match(identifiers)) - return "property"; - - if (stream.match(keywords) || stream.match(wordOperators)) - return "keyword"; - - if (stream.match(builtins)) - return "builtin"; - - if (stream.match(/^(self|cls)\b/)) - return "variable-2"; - - if (stream.match(identifiers)) { - if (state.lastToken == "def" || state.lastToken == "class") - return "def"; - return "variable"; - } - - // Handle non-detected items - stream.next(); - return ERRORCLASS; - } - - function tokenStringFactory(delimiter) { - while ("rubf".indexOf(delimiter.charAt(0).toLowerCase()) >= 0) - delimiter = delimiter.substr(1); - - var singleline = delimiter.length == 1; - var OUTCLASS = "string"; - - function tokenString(stream, state) { - while (!stream.eol()) { - stream.eatWhile(/[^'"\\]/); - if (stream.eat("\\")) { - stream.next(); - if (singleline && stream.eol()) - return OUTCLASS; - } else if (stream.match(delimiter)) { - state.tokenize = tokenBase; - return OUTCLASS; - } else { - stream.eat(/['"]/); - } - } - if (singleline) { - if (parserConf.singleLineStringErrors) - return ERRORCLASS; - else - state.tokenize = tokenBase; - } - return OUTCLASS; - } - tokenString.isString = true; - return tokenString; - } - - function pushPyScope(state) { - while (top(state).type != "py") state.scopes.pop() - state.scopes.push({offset: top(state).offset + conf.indentUnit, - type: "py", - align: null}) - } - - function pushBracketScope(stream, state, type) { - var align = stream.match(/^([\s\[\{\(]|#.*)*$/, false) ? null : stream.column() + 1 - state.scopes.push({offset: state.indent + hangingIndent, - type: type, - align: align}) - } - - function dedent(stream, state) { - var indented = stream.indentation(); - while (state.scopes.length > 1 && top(state).offset > indented) { - if (top(state).type != "py") return true; - state.scopes.pop(); - } - return top(state).offset != indented; - } - - function tokenLexer(stream, state) { - if (stream.sol()) state.beginningOfLine = true; - - var style = state.tokenize(stream, state); - var current = stream.current(); - - // Handle decorators - if (state.beginningOfLine && current == "@") - return stream.match(identifiers, false) ? "meta" : py3 ? "operator" : ERRORCLASS; - - if (/\S/.test(current)) state.beginningOfLine = false; - - if ((style == "variable" || style == "builtin") - && state.lastToken == "meta") - style = "meta"; - - // Handle scope changes. - if (current == "pass" || current == "return") - state.dedent += 1; - - if (current == "lambda") state.lambda = true; - if (current == ":" && !state.lambda && top(state).type == "py") - pushPyScope(state); - - var delimiter_index = current.length == 1 ? "[({".indexOf(current) : -1; - if (delimiter_index != -1) - pushBracketScope(stream, state, "])}".slice(delimiter_index, delimiter_index+1)); - - delimiter_index = "])}".indexOf(current); - if (delimiter_index != -1) { - if (top(state).type == current) state.indent = state.scopes.pop().offset - hangingIndent - else return ERRORCLASS; - } - if (state.dedent > 0 && stream.eol() && top(state).type == "py") { - if (state.scopes.length > 1) state.scopes.pop(); - state.dedent -= 1; - } - - return style; - } - - var external = { - startState: function(basecolumn) { - return { - tokenize: tokenBase, - scopes: [{offset: basecolumn || 0, type: "py", align: null}], - indent: basecolumn || 0, - lastToken: null, - lambda: false, - dedent: 0 - }; - }, - - token: function(stream, state) { - var addErr = state.errorToken; - if (addErr) state.errorToken = false; - var style = tokenLexer(stream, state); - - if (style && style != "comment") - state.lastToken = (style == "keyword" || style == "punctuation") ? stream.current() : style; - if (style == "punctuation") style = null; - - if (stream.eol() && state.lambda) - state.lambda = false; - return addErr ? style + " " + ERRORCLASS : style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase) - return state.tokenize.isString ? CodeMirror.Pass : 0; - - var scope = top(state), closing = scope.type == textAfter.charAt(0) - if (scope.align != null) - return scope.align - (closing ? 1 : 0) - else - return scope.offset - (closing ? hangingIndent : 0) - }, - - electricInput: /^\s*[\}\]\)]$/, - closeBrackets: {triples: "'\""}, - lineComment: "#", - fold: "indent" - }; - return external; - }); - - CodeMirror.defineMIME("text/x-python", "python"); - - var words = function(str) { return str.split(" "); }; - - CodeMirror.defineMIME("text/x-cython", { - name: "python", - extra_keywords: words("by cdef cimport cpdef ctypedef enum except"+ - "extern gil include nogil property public"+ - "readonly struct union DEF IF ELIF ELSE") - }); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/python/test.js b/backend/_pv_1_3_5/static/codemirror/mode/python/test.js deleted file mode 100755 index c1a9c6a99..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/python/test.js +++ /dev/null @@ -1,30 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 4}, - {name: "python", - version: 3, - singleLineStringErrors: false}); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - // Error, because "foobarhello" is neither a known type or property, but - // property was expected (after "and"), and it should be in parentheses. - MT("decoratorStartOfLine", - "[meta @dec]", - "[keyword def] [def function]():", - " [keyword pass]"); - - MT("decoratorIndented", - "[keyword class] [def Foo]:", - " [meta @dec]", - " [keyword def] [def function]():", - " [keyword pass]"); - - MT("matmulWithSpace:", "[variable a] [operator @] [variable b]"); - MT("matmulWithoutSpace:", "[variable a][operator @][variable b]"); - MT("matmulSpaceBefore:", "[variable a] [operator @][variable b]"); - - MT("fValidStringPrefix", "[string f'this is a {formatted} string']"); - MT("uValidStringPrefix", "[string u'this is an unicode string']"); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/q/index.html b/backend/_pv_1_3_5/static/codemirror/mode/q/index.html deleted file mode 100755 index 72785ba3b..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/q/index.html +++ /dev/null @@ -1,144 +0,0 @@ - - -CodeMirror: Q mode - - - - - - - - - - -
    -

    Q mode

    - - -
    - - - -

    MIME type defined: text/x-q.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/q/q.js b/backend/_pv_1_3_5/static/codemirror/mode/q/q.js deleted file mode 100755 index a4af9383e..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/q/q.js +++ /dev/null @@ -1,139 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("q",function(config){ - var indentUnit=config.indentUnit, - curPunc, - keywords=buildRE(["abs","acos","aj","aj0","all","and","any","asc","asin","asof","atan","attr","avg","avgs","bin","by","ceiling","cols","cor","cos","count","cov","cross","csv","cut","delete","deltas","desc","dev","differ","distinct","div","do","each","ej","enlist","eval","except","exec","exit","exp","fby","fills","first","fkeys","flip","floor","from","get","getenv","group","gtime","hclose","hcount","hdel","hopen","hsym","iasc","idesc","if","ij","in","insert","inter","inv","key","keys","last","like","list","lj","load","log","lower","lsq","ltime","ltrim","mavg","max","maxs","mcount","md5","mdev","med","meta","min","mins","mmax","mmin","mmu","mod","msum","neg","next","not","null","or","over","parse","peach","pj","plist","prd","prds","prev","prior","rand","rank","ratios","raze","read0","read1","reciprocal","reverse","rload","rotate","rsave","rtrim","save","scan","select","set","setenv","show","signum","sin","sqrt","ss","ssr","string","sublist","sum","sums","sv","system","tables","tan","til","trim","txf","type","uj","ungroup","union","update","upper","upsert","value","var","view","views","vs","wavg","where","where","while","within","wj","wj1","wsum","xasc","xbar","xcol","xcols","xdesc","xexp","xgroup","xkey","xlog","xprev","xrank"]), - E=/[|/&^!+:\\\-*%$=~#;@><,?_\'\"\[\(\]\)\s{}]/; - function buildRE(w){return new RegExp("^("+w.join("|")+")$");} - function tokenBase(stream,state){ - var sol=stream.sol(),c=stream.next(); - curPunc=null; - if(sol) - if(c=="/") - return(state.tokenize=tokenLineComment)(stream,state); - else if(c=="\\"){ - if(stream.eol()||/\s/.test(stream.peek())) - return stream.skipToEnd(),/^\\\s*$/.test(stream.current())?(state.tokenize=tokenCommentToEOF)(stream, state):state.tokenize=tokenBase,"comment"; - else - return state.tokenize=tokenBase,"builtin"; - } - if(/\s/.test(c)) - return stream.peek()=="/"?(stream.skipToEnd(),"comment"):"whitespace"; - if(c=='"') - return(state.tokenize=tokenString)(stream,state); - if(c=='`') - return stream.eatWhile(/[A-Z|a-z|\d|_|:|\/|\.]/),"symbol"; - if(("."==c&&/\d/.test(stream.peek()))||/\d/.test(c)){ - var t=null; - stream.backUp(1); - if(stream.match(/^\d{4}\.\d{2}(m|\.\d{2}([D|T](\d{2}(:\d{2}(:\d{2}(\.\d{1,9})?)?)?)?)?)/) - || stream.match(/^\d+D(\d{2}(:\d{2}(:\d{2}(\.\d{1,9})?)?)?)/) - || stream.match(/^\d{2}:\d{2}(:\d{2}(\.\d{1,9})?)?/) - || stream.match(/^\d+[ptuv]{1}/)) - t="temporal"; - else if(stream.match(/^0[NwW]{1}/) - || stream.match(/^0x[\d|a-f|A-F]*/) - || stream.match(/^[0|1]+[b]{1}/) - || stream.match(/^\d+[chijn]{1}/) - || stream.match(/-?\d*(\.\d*)?(e[+\-]?\d+)?(e|f)?/)) - t="number"; - return(t&&(!(c=stream.peek())||E.test(c)))?t:(stream.next(),"error"); - } - if(/[A-Z|a-z]|\./.test(c)) - return stream.eatWhile(/[A-Z|a-z|\.|_|\d]/),keywords.test(stream.current())?"keyword":"variable"; - if(/[|/&^!+:\\\-*%$=~#;@><\.,?_\']/.test(c)) - return null; - if(/[{}\(\[\]\)]/.test(c)) - return null; - return"error"; - } - function tokenLineComment(stream,state){ - return stream.skipToEnd(),/\/\s*$/.test(stream.current())?(state.tokenize=tokenBlockComment)(stream,state):(state.tokenize=tokenBase),"comment"; - } - function tokenBlockComment(stream,state){ - var f=stream.sol()&&stream.peek()=="\\"; - stream.skipToEnd(); - if(f&&/^\\\s*$/.test(stream.current())) - state.tokenize=tokenBase; - return"comment"; - } - function tokenCommentToEOF(stream){return stream.skipToEnd(),"comment";} - function tokenString(stream,state){ - var escaped=false,next,end=false; - while((next=stream.next())){ - if(next=="\""&&!escaped){end=true;break;} - escaped=!escaped&&next=="\\"; - } - if(end)state.tokenize=tokenBase; - return"string"; - } - function pushContext(state,type,col){state.context={prev:state.context,indent:state.indent,col:col,type:type};} - function popContext(state){state.indent=state.context.indent;state.context=state.context.prev;} - return{ - startState:function(){ - return{tokenize:tokenBase, - context:null, - indent:0, - col:0}; - }, - token:function(stream,state){ - if(stream.sol()){ - if(state.context&&state.context.align==null) - state.context.align=false; - state.indent=stream.indentation(); - } - //if (stream.eatSpace()) return null; - var style=state.tokenize(stream,state); - if(style!="comment"&&state.context&&state.context.align==null&&state.context.type!="pattern"){ - state.context.align=true; - } - if(curPunc=="(")pushContext(state,")",stream.column()); - else if(curPunc=="[")pushContext(state,"]",stream.column()); - else if(curPunc=="{")pushContext(state,"}",stream.column()); - else if(/[\]\}\)]/.test(curPunc)){ - while(state.context&&state.context.type=="pattern")popContext(state); - if(state.context&&curPunc==state.context.type)popContext(state); - } - else if(curPunc=="."&&state.context&&state.context.type=="pattern")popContext(state); - else if(/atom|string|variable/.test(style)&&state.context){ - if(/[\}\]]/.test(state.context.type)) - pushContext(state,"pattern",stream.column()); - else if(state.context.type=="pattern"&&!state.context.align){ - state.context.align=true; - state.context.col=stream.column(); - } - } - return style; - }, - indent:function(state,textAfter){ - var firstChar=textAfter&&textAfter.charAt(0); - var context=state.context; - if(/[\]\}]/.test(firstChar)) - while (context&&context.type=="pattern")context=context.prev; - var closing=context&&firstChar==context.type; - if(!context) - return 0; - else if(context.type=="pattern") - return context.col; - else if(context.align) - return context.col+(closing?0:1); - else - return context.indent+(closing?0:indentUnit); - } - }; -}); -CodeMirror.defineMIME("text/x-q","q"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/r/index.html b/backend/_pv_1_3_5/static/codemirror/mode/r/index.html deleted file mode 100755 index 01b6e664b..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/r/index.html +++ /dev/null @@ -1,88 +0,0 @@ - - -CodeMirror: R mode - - - - - - - - - -
    -

    R mode

    -
    - - -

    MIME types defined: text/x-rsrc.

    - -

    Development of the CodeMirror R mode was kindly sponsored - by Ubalo.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/r/r.js b/backend/_pv_1_3_5/static/codemirror/mode/r/r.js deleted file mode 100755 index 7e15beac6..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/r/r.js +++ /dev/null @@ -1,171 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.registerHelper("wordChars", "r", /[\w.]/); - -CodeMirror.defineMode("r", function(config) { - function wordObj(str) { - var words = str.split(" "), res = {}; - for (var i = 0; i < words.length; ++i) res[words[i]] = true; - return res; - } - var atoms = wordObj("NULL NA Inf NaN NA_integer_ NA_real_ NA_complex_ NA_character_"); - var builtins = wordObj("list quote bquote eval return call parse deparse"); - var keywords = wordObj("if else repeat while function for in next break"); - var blockkeywords = wordObj("if else repeat while function for"); - var opChars = /[+\-*\/^<>=!&|~$:]/; - var curPunc; - - function tokenBase(stream, state) { - curPunc = null; - var ch = stream.next(); - if (ch == "#") { - stream.skipToEnd(); - return "comment"; - } else if (ch == "0" && stream.eat("x")) { - stream.eatWhile(/[\da-f]/i); - return "number"; - } else if (ch == "." && stream.eat(/\d/)) { - stream.match(/\d*(?:e[+\-]?\d+)?/); - return "number"; - } else if (/\d/.test(ch)) { - stream.match(/\d*(?:\.\d+)?(?:e[+\-]\d+)?L?/); - return "number"; - } else if (ch == "'" || ch == '"') { - state.tokenize = tokenString(ch); - return "string"; - } else if (ch == "`") { - stream.match(/[^`]+`/); - return "variable-3"; - } else if (ch == "." && stream.match(/.[.\d]+/)) { - return "keyword"; - } else if (/[\w\.]/.test(ch) && ch != "_") { - stream.eatWhile(/[\w\.]/); - var word = stream.current(); - if (atoms.propertyIsEnumerable(word)) return "atom"; - if (keywords.propertyIsEnumerable(word)) { - // Block keywords start new blocks, except 'else if', which only starts - // one new block for the 'if', no block for the 'else'. - if (blockkeywords.propertyIsEnumerable(word) && - !stream.match(/\s*if(\s+|$)/, false)) - curPunc = "block"; - return "keyword"; - } - if (builtins.propertyIsEnumerable(word)) return "builtin"; - return "variable"; - } else if (ch == "%") { - if (stream.skipTo("%")) stream.next(); - return "operator variable-2"; - } else if ( - (ch == "<" && stream.eat("-")) || - (ch == "<" && stream.match("<-")) || - (ch == "-" && stream.match(/>>?/)) - ) { - return "operator arrow"; - } else if (ch == "=" && state.ctx.argList) { - return "arg-is"; - } else if (opChars.test(ch)) { - if (ch == "$") return "operator dollar"; - stream.eatWhile(opChars); - return "operator"; - } else if (/[\(\){}\[\];]/.test(ch)) { - curPunc = ch; - if (ch == ";") return "semi"; - return null; - } else { - return null; - } - } - - function tokenString(quote) { - return function(stream, state) { - if (stream.eat("\\")) { - var ch = stream.next(); - if (ch == "x") stream.match(/^[a-f0-9]{2}/i); - else if ((ch == "u" || ch == "U") && stream.eat("{") && stream.skipTo("}")) stream.next(); - else if (ch == "u") stream.match(/^[a-f0-9]{4}/i); - else if (ch == "U") stream.match(/^[a-f0-9]{8}/i); - else if (/[0-7]/.test(ch)) stream.match(/^[0-7]{1,2}/); - return "string-2"; - } else { - var next; - while ((next = stream.next()) != null) { - if (next == quote) { state.tokenize = tokenBase; break; } - if (next == "\\") { stream.backUp(1); break; } - } - return "string"; - } - }; - } - - function push(state, type, stream) { - state.ctx = {type: type, - indent: state.indent, - align: null, - column: stream.column(), - prev: state.ctx}; - } - function pop(state) { - state.indent = state.ctx.indent; - state.ctx = state.ctx.prev; - } - - return { - startState: function() { - return {tokenize: tokenBase, - ctx: {type: "top", - indent: -config.indentUnit, - align: false}, - indent: 0, - afterIdent: false}; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (state.ctx.align == null) state.ctx.align = false; - state.indent = stream.indentation(); - } - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - if (style != "comment" && state.ctx.align == null) state.ctx.align = true; - - var ctype = state.ctx.type; - if ((curPunc == ";" || curPunc == "{" || curPunc == "}") && ctype == "block") pop(state); - if (curPunc == "{") push(state, "}", stream); - else if (curPunc == "(") { - push(state, ")", stream); - if (state.afterIdent) state.ctx.argList = true; - } - else if (curPunc == "[") push(state, "]", stream); - else if (curPunc == "block") push(state, "block", stream); - else if (curPunc == ctype) pop(state); - state.afterIdent = style == "variable" || style == "keyword"; - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase) return 0; - var firstChar = textAfter && textAfter.charAt(0), ctx = state.ctx, - closing = firstChar == ctx.type; - if (ctx.type == "block") return ctx.indent + (firstChar == "{" ? 0 : config.indentUnit); - else if (ctx.align) return ctx.column + (closing ? 0 : 1); - else return ctx.indent + (closing ? 0 : config.indentUnit); - }, - - lineComment: "#" - }; -}); - -CodeMirror.defineMIME("text/x-rsrc", "r"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/rpm/changes/index.html b/backend/_pv_1_3_5/static/codemirror/mode/rpm/changes/index.html deleted file mode 100755 index 6e5031bd1..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/rpm/changes/index.html +++ /dev/null @@ -1,66 +0,0 @@ - - -CodeMirror: RPM changes mode - - - - - - - - - - - -
    -

    RPM changes mode

    - -
    - - -

    MIME types defined: text/x-rpm-changes.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/rpm/index.html b/backend/_pv_1_3_5/static/codemirror/mode/rpm/index.html deleted file mode 100755 index 9a34e6dfb..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/rpm/index.html +++ /dev/null @@ -1,149 +0,0 @@ - - -CodeMirror: RPM changes mode - - - - - - - - - - - -
    -

    RPM changes mode

    - -
    - - -

    RPM spec mode

    - -
    - - -

    MIME types defined: text/x-rpm-spec, text/x-rpm-changes.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/rpm/rpm.js b/backend/_pv_1_3_5/static/codemirror/mode/rpm/rpm.js deleted file mode 100755 index 87cde591a..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/rpm/rpm.js +++ /dev/null @@ -1,109 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("rpm-changes", function() { - var headerSeperator = /^-+$/; - var headerLine = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ?\d{1,2} \d{2}:\d{2}(:\d{2})? [A-Z]{3,4} \d{4} - /; - var simpleEmail = /^[\w+.-]+@[\w.-]+/; - - return { - token: function(stream) { - if (stream.sol()) { - if (stream.match(headerSeperator)) { return 'tag'; } - if (stream.match(headerLine)) { return 'tag'; } - } - if (stream.match(simpleEmail)) { return 'string'; } - stream.next(); - return null; - } - }; -}); - -CodeMirror.defineMIME("text/x-rpm-changes", "rpm-changes"); - -// Quick and dirty spec file highlighting - -CodeMirror.defineMode("rpm-spec", function() { - var arch = /^(i386|i586|i686|x86_64|ppc64le|ppc64|ppc|ia64|s390x|s390|sparc64|sparcv9|sparc|noarch|alphaev6|alpha|hppa|mipsel)/; - - var preamble = /^[a-zA-Z0-9()]+:/; - var section = /^%(debug_package|package|description|prep|build|install|files|clean|changelog|preinstall|preun|postinstall|postun|pretrans|posttrans|pre|post|triggerin|triggerun|verifyscript|check|triggerpostun|triggerprein|trigger)/; - var control_flow_complex = /^%(ifnarch|ifarch|if)/; // rpm control flow macros - var control_flow_simple = /^%(else|endif)/; // rpm control flow macros - var operators = /^(\!|\?|\<\=|\<|\>\=|\>|\=\=|\&\&|\|\|)/; // operators in control flow macros - - return { - startState: function () { - return { - controlFlow: false, - macroParameters: false, - section: false - }; - }, - token: function (stream, state) { - var ch = stream.peek(); - if (ch == "#") { stream.skipToEnd(); return "comment"; } - - if (stream.sol()) { - if (stream.match(preamble)) { return "header"; } - if (stream.match(section)) { return "atom"; } - } - - if (stream.match(/^\$\w+/)) { return "def"; } // Variables like '$RPM_BUILD_ROOT' - if (stream.match(/^\$\{\w+\}/)) { return "def"; } // Variables like '${RPM_BUILD_ROOT}' - - if (stream.match(control_flow_simple)) { return "keyword"; } - if (stream.match(control_flow_complex)) { - state.controlFlow = true; - return "keyword"; - } - if (state.controlFlow) { - if (stream.match(operators)) { return "operator"; } - if (stream.match(/^(\d+)/)) { return "number"; } - if (stream.eol()) { state.controlFlow = false; } - } - - if (stream.match(arch)) { - if (stream.eol()) { state.controlFlow = false; } - return "number"; - } - - // Macros like '%make_install' or '%attr(0775,root,root)' - if (stream.match(/^%[\w]+/)) { - if (stream.match(/^\(/)) { state.macroParameters = true; } - return "keyword"; - } - if (state.macroParameters) { - if (stream.match(/^\d+/)) { return "number";} - if (stream.match(/^\)/)) { - state.macroParameters = false; - return "keyword"; - } - } - - // Macros like '%{defined fedora}' - if (stream.match(/^%\{\??[\w \-\:\!]+\}/)) { - if (stream.eol()) { state.controlFlow = false; } - return "def"; - } - - //TODO: Include bash script sub-parser (CodeMirror supports that) - stream.next(); - return null; - } - }; -}); - -CodeMirror.defineMIME("text/x-rpm-spec", "rpm-spec"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/rst/index.html b/backend/_pv_1_3_5/static/codemirror/mode/rst/index.html deleted file mode 100755 index 2902dea23..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/rst/index.html +++ /dev/null @@ -1,535 +0,0 @@ - - -CodeMirror: reStructuredText mode - - - - - - - - - - -
    -

    reStructuredText mode

    -
    - - -

    - The python mode will be used for highlighting blocks - containing Python/IPython terminal sessions: blocks starting with - >>> (for Python) or In [num]: (for - IPython). - - Further, the stex mode will be used for highlighting - blocks containing LaTex code. -

    - -

    MIME types defined: text/x-rst.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/rst/rst.js b/backend/_pv_1_3_5/static/codemirror/mode/rst/rst.js deleted file mode 100755 index bcf110c1a..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/rst/rst.js +++ /dev/null @@ -1,557 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../python/python"), require("../stex/stex"), require("../../addon/mode/overlay")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../python/python", "../stex/stex", "../../addon/mode/overlay"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode('rst', function (config, options) { - - var rx_strong = /^\*\*[^\*\s](?:[^\*]*[^\*\s])?\*\*/; - var rx_emphasis = /^\*[^\*\s](?:[^\*]*[^\*\s])?\*/; - var rx_literal = /^``[^`\s](?:[^`]*[^`\s])``/; - - var rx_number = /^(?:[\d]+(?:[\.,]\d+)*)/; - var rx_positive = /^(?:\s\+[\d]+(?:[\.,]\d+)*)/; - var rx_negative = /^(?:\s\-[\d]+(?:[\.,]\d+)*)/; - - var rx_uri_protocol = "[Hh][Tt][Tt][Pp][Ss]?://"; - var rx_uri_domain = "(?:[\\d\\w.-]+)\\.(?:\\w{2,6})"; - var rx_uri_path = "(?:/[\\d\\w\\#\\%\\&\\-\\.\\,\\/\\:\\=\\?\\~]+)*"; - var rx_uri = new RegExp("^" + rx_uri_protocol + rx_uri_domain + rx_uri_path); - - var overlay = { - token: function (stream) { - - if (stream.match(rx_strong) && stream.match (/\W+|$/, false)) - return 'strong'; - if (stream.match(rx_emphasis) && stream.match (/\W+|$/, false)) - return 'em'; - if (stream.match(rx_literal) && stream.match (/\W+|$/, false)) - return 'string-2'; - if (stream.match(rx_number)) - return 'number'; - if (stream.match(rx_positive)) - return 'positive'; - if (stream.match(rx_negative)) - return 'negative'; - if (stream.match(rx_uri)) - return 'link'; - - while (stream.next() != null) { - if (stream.match(rx_strong, false)) break; - if (stream.match(rx_emphasis, false)) break; - if (stream.match(rx_literal, false)) break; - if (stream.match(rx_number, false)) break; - if (stream.match(rx_positive, false)) break; - if (stream.match(rx_negative, false)) break; - if (stream.match(rx_uri, false)) break; - } - - return null; - } - }; - - var mode = CodeMirror.getMode( - config, options.backdrop || 'rst-base' - ); - - return CodeMirror.overlayMode(mode, overlay, true); // combine -}, 'python', 'stex'); - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -CodeMirror.defineMode('rst-base', function (config) { - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - function format(string) { - var args = Array.prototype.slice.call(arguments, 1); - return string.replace(/{(\d+)}/g, function (match, n) { - return typeof args[n] != 'undefined' ? args[n] : match; - }); - } - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - var mode_python = CodeMirror.getMode(config, 'python'); - var mode_stex = CodeMirror.getMode(config, 'stex'); - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - var SEPA = "\\s+"; - var TAIL = "(?:\\s*|\\W|$)", - rx_TAIL = new RegExp(format('^{0}', TAIL)); - - var NAME = - "(?:[^\\W\\d_](?:[\\w!\"#$%&'()\\*\\+,\\-\\.\/:;<=>\\?]*[^\\W_])?)", - rx_NAME = new RegExp(format('^{0}', NAME)); - var NAME_WWS = - "(?:[^\\W\\d_](?:[\\w\\s!\"#$%&'()\\*\\+,\\-\\.\/:;<=>\\?]*[^\\W_])?)"; - var REF_NAME = format('(?:{0}|`{1}`)', NAME, NAME_WWS); - - var TEXT1 = "(?:[^\\s\\|](?:[^\\|]*[^\\s\\|])?)"; - var TEXT2 = "(?:[^\\`]+)", - rx_TEXT2 = new RegExp(format('^{0}', TEXT2)); - - var rx_section = new RegExp( - "^([!'#$%&\"()*+,-./:;<=>?@\\[\\\\\\]^_`{|}~])\\1{3,}\\s*$"); - var rx_explicit = new RegExp( - format('^\\.\\.{0}', SEPA)); - var rx_link = new RegExp( - format('^_{0}:{1}|^__:{1}', REF_NAME, TAIL)); - var rx_directive = new RegExp( - format('^{0}::{1}', REF_NAME, TAIL)); - var rx_substitution = new RegExp( - format('^\\|{0}\\|{1}{2}::{3}', TEXT1, SEPA, REF_NAME, TAIL)); - var rx_footnote = new RegExp( - format('^\\[(?:\\d+|#{0}?|\\*)]{1}', REF_NAME, TAIL)); - var rx_citation = new RegExp( - format('^\\[{0}\\]{1}', REF_NAME, TAIL)); - - var rx_substitution_ref = new RegExp( - format('^\\|{0}\\|', TEXT1)); - var rx_footnote_ref = new RegExp( - format('^\\[(?:\\d+|#{0}?|\\*)]_', REF_NAME)); - var rx_citation_ref = new RegExp( - format('^\\[{0}\\]_', REF_NAME)); - var rx_link_ref1 = new RegExp( - format('^{0}__?', REF_NAME)); - var rx_link_ref2 = new RegExp( - format('^`{0}`_', TEXT2)); - - var rx_role_pre = new RegExp( - format('^:{0}:`{1}`{2}', NAME, TEXT2, TAIL)); - var rx_role_suf = new RegExp( - format('^`{1}`:{0}:{2}', NAME, TEXT2, TAIL)); - var rx_role = new RegExp( - format('^:{0}:{1}', NAME, TAIL)); - - var rx_directive_name = new RegExp(format('^{0}', REF_NAME)); - var rx_directive_tail = new RegExp(format('^::{0}', TAIL)); - var rx_substitution_text = new RegExp(format('^\\|{0}\\|', TEXT1)); - var rx_substitution_sepa = new RegExp(format('^{0}', SEPA)); - var rx_substitution_name = new RegExp(format('^{0}', REF_NAME)); - var rx_substitution_tail = new RegExp(format('^::{0}', TAIL)); - var rx_link_head = new RegExp("^_"); - var rx_link_name = new RegExp(format('^{0}|_', REF_NAME)); - var rx_link_tail = new RegExp(format('^:{0}', TAIL)); - - var rx_verbatim = new RegExp('^::\\s*$'); - var rx_examples = new RegExp('^\\s+(?:>>>|In \\[\\d+\\]:)\\s'); - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - function to_normal(stream, state) { - var token = null; - - if (stream.sol() && stream.match(rx_examples, false)) { - change(state, to_mode, { - mode: mode_python, local: CodeMirror.startState(mode_python) - }); - } else if (stream.sol() && stream.match(rx_explicit)) { - change(state, to_explicit); - token = 'meta'; - } else if (stream.sol() && stream.match(rx_section)) { - change(state, to_normal); - token = 'header'; - } else if (phase(state) == rx_role_pre || - stream.match(rx_role_pre, false)) { - - switch (stage(state)) { - case 0: - change(state, to_normal, context(rx_role_pre, 1)); - stream.match(/^:/); - token = 'meta'; - break; - case 1: - change(state, to_normal, context(rx_role_pre, 2)); - stream.match(rx_NAME); - token = 'keyword'; - - if (stream.current().match(/^(?:math|latex)/)) { - state.tmp_stex = true; - } - break; - case 2: - change(state, to_normal, context(rx_role_pre, 3)); - stream.match(/^:`/); - token = 'meta'; - break; - case 3: - if (state.tmp_stex) { - state.tmp_stex = undefined; state.tmp = { - mode: mode_stex, local: CodeMirror.startState(mode_stex) - }; - } - - if (state.tmp) { - if (stream.peek() == '`') { - change(state, to_normal, context(rx_role_pre, 4)); - state.tmp = undefined; - break; - } - - token = state.tmp.mode.token(stream, state.tmp.local); - break; - } - - change(state, to_normal, context(rx_role_pre, 4)); - stream.match(rx_TEXT2); - token = 'string'; - break; - case 4: - change(state, to_normal, context(rx_role_pre, 5)); - stream.match(/^`/); - token = 'meta'; - break; - case 5: - change(state, to_normal, context(rx_role_pre, 6)); - stream.match(rx_TAIL); - break; - default: - change(state, to_normal); - } - } else if (phase(state) == rx_role_suf || - stream.match(rx_role_suf, false)) { - - switch (stage(state)) { - case 0: - change(state, to_normal, context(rx_role_suf, 1)); - stream.match(/^`/); - token = 'meta'; - break; - case 1: - change(state, to_normal, context(rx_role_suf, 2)); - stream.match(rx_TEXT2); - token = 'string'; - break; - case 2: - change(state, to_normal, context(rx_role_suf, 3)); - stream.match(/^`:/); - token = 'meta'; - break; - case 3: - change(state, to_normal, context(rx_role_suf, 4)); - stream.match(rx_NAME); - token = 'keyword'; - break; - case 4: - change(state, to_normal, context(rx_role_suf, 5)); - stream.match(/^:/); - token = 'meta'; - break; - case 5: - change(state, to_normal, context(rx_role_suf, 6)); - stream.match(rx_TAIL); - break; - default: - change(state, to_normal); - } - } else if (phase(state) == rx_role || stream.match(rx_role, false)) { - - switch (stage(state)) { - case 0: - change(state, to_normal, context(rx_role, 1)); - stream.match(/^:/); - token = 'meta'; - break; - case 1: - change(state, to_normal, context(rx_role, 2)); - stream.match(rx_NAME); - token = 'keyword'; - break; - case 2: - change(state, to_normal, context(rx_role, 3)); - stream.match(/^:/); - token = 'meta'; - break; - case 3: - change(state, to_normal, context(rx_role, 4)); - stream.match(rx_TAIL); - break; - default: - change(state, to_normal); - } - } else if (phase(state) == rx_substitution_ref || - stream.match(rx_substitution_ref, false)) { - - switch (stage(state)) { - case 0: - change(state, to_normal, context(rx_substitution_ref, 1)); - stream.match(rx_substitution_text); - token = 'variable-2'; - break; - case 1: - change(state, to_normal, context(rx_substitution_ref, 2)); - if (stream.match(/^_?_?/)) token = 'link'; - break; - default: - change(state, to_normal); - } - } else if (stream.match(rx_footnote_ref)) { - change(state, to_normal); - token = 'quote'; - } else if (stream.match(rx_citation_ref)) { - change(state, to_normal); - token = 'quote'; - } else if (stream.match(rx_link_ref1)) { - change(state, to_normal); - if (!stream.peek() || stream.peek().match(/^\W$/)) { - token = 'link'; - } - } else if (phase(state) == rx_link_ref2 || - stream.match(rx_link_ref2, false)) { - - switch (stage(state)) { - case 0: - if (!stream.peek() || stream.peek().match(/^\W$/)) { - change(state, to_normal, context(rx_link_ref2, 1)); - } else { - stream.match(rx_link_ref2); - } - break; - case 1: - change(state, to_normal, context(rx_link_ref2, 2)); - stream.match(/^`/); - token = 'link'; - break; - case 2: - change(state, to_normal, context(rx_link_ref2, 3)); - stream.match(rx_TEXT2); - break; - case 3: - change(state, to_normal, context(rx_link_ref2, 4)); - stream.match(/^`_/); - token = 'link'; - break; - default: - change(state, to_normal); - } - } else if (stream.match(rx_verbatim)) { - change(state, to_verbatim); - } - - else { - if (stream.next()) change(state, to_normal); - } - - return token; - } - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - function to_explicit(stream, state) { - var token = null; - - if (phase(state) == rx_substitution || - stream.match(rx_substitution, false)) { - - switch (stage(state)) { - case 0: - change(state, to_explicit, context(rx_substitution, 1)); - stream.match(rx_substitution_text); - token = 'variable-2'; - break; - case 1: - change(state, to_explicit, context(rx_substitution, 2)); - stream.match(rx_substitution_sepa); - break; - case 2: - change(state, to_explicit, context(rx_substitution, 3)); - stream.match(rx_substitution_name); - token = 'keyword'; - break; - case 3: - change(state, to_explicit, context(rx_substitution, 4)); - stream.match(rx_substitution_tail); - token = 'meta'; - break; - default: - change(state, to_normal); - } - } else if (phase(state) == rx_directive || - stream.match(rx_directive, false)) { - - switch (stage(state)) { - case 0: - change(state, to_explicit, context(rx_directive, 1)); - stream.match(rx_directive_name); - token = 'keyword'; - - if (stream.current().match(/^(?:math|latex)/)) - state.tmp_stex = true; - else if (stream.current().match(/^python/)) - state.tmp_py = true; - break; - case 1: - change(state, to_explicit, context(rx_directive, 2)); - stream.match(rx_directive_tail); - token = 'meta'; - - if (stream.match(/^latex\s*$/) || state.tmp_stex) { - state.tmp_stex = undefined; change(state, to_mode, { - mode: mode_stex, local: CodeMirror.startState(mode_stex) - }); - } - break; - case 2: - change(state, to_explicit, context(rx_directive, 3)); - if (stream.match(/^python\s*$/) || state.tmp_py) { - state.tmp_py = undefined; change(state, to_mode, { - mode: mode_python, local: CodeMirror.startState(mode_python) - }); - } - break; - default: - change(state, to_normal); - } - } else if (phase(state) == rx_link || stream.match(rx_link, false)) { - - switch (stage(state)) { - case 0: - change(state, to_explicit, context(rx_link, 1)); - stream.match(rx_link_head); - stream.match(rx_link_name); - token = 'link'; - break; - case 1: - change(state, to_explicit, context(rx_link, 2)); - stream.match(rx_link_tail); - token = 'meta'; - break; - default: - change(state, to_normal); - } - } else if (stream.match(rx_footnote)) { - change(state, to_normal); - token = 'quote'; - } else if (stream.match(rx_citation)) { - change(state, to_normal); - token = 'quote'; - } - - else { - stream.eatSpace(); - if (stream.eol()) { - change(state, to_normal); - } else { - stream.skipToEnd(); - change(state, to_comment); - token = 'comment'; - } - } - - return token; - } - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - function to_comment(stream, state) { - return as_block(stream, state, 'comment'); - } - - function to_verbatim(stream, state) { - return as_block(stream, state, 'meta'); - } - - function as_block(stream, state, token) { - if (stream.eol() || stream.eatSpace()) { - stream.skipToEnd(); - return token; - } else { - change(state, to_normal); - return null; - } - } - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - function to_mode(stream, state) { - - if (state.ctx.mode && state.ctx.local) { - - if (stream.sol()) { - if (!stream.eatSpace()) change(state, to_normal); - return null; - } - - return state.ctx.mode.token(stream, state.ctx.local); - } - - change(state, to_normal); - return null; - } - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - function context(phase, stage, mode, local) { - return {phase: phase, stage: stage, mode: mode, local: local}; - } - - function change(state, tok, ctx) { - state.tok = tok; - state.ctx = ctx || {}; - } - - function stage(state) { - return state.ctx.stage || 0; - } - - function phase(state) { - return state.ctx.phase; - } - - /////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////// - - return { - startState: function () { - return {tok: to_normal, ctx: context(undefined, 0)}; - }, - - copyState: function (state) { - var ctx = state.ctx, tmp = state.tmp; - if (ctx.local) - ctx = {mode: ctx.mode, local: CodeMirror.copyState(ctx.mode, ctx.local)}; - if (tmp) - tmp = {mode: tmp.mode, local: CodeMirror.copyState(tmp.mode, tmp.local)}; - return {tok: state.tok, ctx: ctx, tmp: tmp}; - }, - - innerMode: function (state) { - return state.tmp ? {state: state.tmp.local, mode: state.tmp.mode} - : state.ctx.mode ? {state: state.ctx.local, mode: state.ctx.mode} - : null; - }, - - token: function (stream, state) { - return state.tok(stream, state); - } - }; -}, 'python', 'stex'); - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -CodeMirror.defineMIME('text/x-rst', 'rst'); - -/////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////// - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/ruby/index.html b/backend/_pv_1_3_5/static/codemirror/mode/ruby/index.html deleted file mode 100755 index 97544babc..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/ruby/index.html +++ /dev/null @@ -1,183 +0,0 @@ - - -CodeMirror: Ruby mode - - - - - - - - - - -
    -

    Ruby mode

    -
    - - -

    MIME types defined: text/x-ruby.

    - -

    Development of the CodeMirror Ruby mode was kindly sponsored - by Ubalo.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/ruby/ruby.js b/backend/_pv_1_3_5/static/codemirror/mode/ruby/ruby.js deleted file mode 100755 index 085f909f5..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/ruby/ruby.js +++ /dev/null @@ -1,285 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("ruby", function(config) { - function wordObj(words) { - var o = {}; - for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true; - return o; - } - var keywords = wordObj([ - "alias", "and", "BEGIN", "begin", "break", "case", "class", "def", "defined?", "do", "else", - "elsif", "END", "end", "ensure", "false", "for", "if", "in", "module", "next", "not", "or", - "redo", "rescue", "retry", "return", "self", "super", "then", "true", "undef", "unless", - "until", "when", "while", "yield", "nil", "raise", "throw", "catch", "fail", "loop", "callcc", - "caller", "lambda", "proc", "public", "protected", "private", "require", "load", - "require_relative", "extend", "autoload", "__END__", "__FILE__", "__LINE__", "__dir__" - ]); - var indentWords = wordObj(["def", "class", "case", "for", "while", "until", "module", "then", - "catch", "loop", "proc", "begin"]); - var dedentWords = wordObj(["end", "until"]); - var matching = {"[": "]", "{": "}", "(": ")"}; - var curPunc; - - function chain(newtok, stream, state) { - state.tokenize.push(newtok); - return newtok(stream, state); - } - - function tokenBase(stream, state) { - if (stream.sol() && stream.match("=begin") && stream.eol()) { - state.tokenize.push(readBlockComment); - return "comment"; - } - if (stream.eatSpace()) return null; - var ch = stream.next(), m; - if (ch == "`" || ch == "'" || ch == '"') { - return chain(readQuoted(ch, "string", ch == '"' || ch == "`"), stream, state); - } else if (ch == "/") { - var currentIndex = stream.current().length; - if (stream.skipTo("/")) { - var search_till = stream.current().length; - stream.backUp(stream.current().length - currentIndex); - var balance = 0; // balance brackets - while (stream.current().length < search_till) { - var chchr = stream.next(); - if (chchr == "(") balance += 1; - else if (chchr == ")") balance -= 1; - if (balance < 0) break; - } - stream.backUp(stream.current().length - currentIndex); - if (balance == 0) - return chain(readQuoted(ch, "string-2", true), stream, state); - } - return "operator"; - } else if (ch == "%") { - var style = "string", embed = true; - if (stream.eat("s")) style = "atom"; - else if (stream.eat(/[WQ]/)) style = "string"; - else if (stream.eat(/[r]/)) style = "string-2"; - else if (stream.eat(/[wxq]/)) { style = "string"; embed = false; } - var delim = stream.eat(/[^\w\s=]/); - if (!delim) return "operator"; - if (matching.propertyIsEnumerable(delim)) delim = matching[delim]; - return chain(readQuoted(delim, style, embed, true), stream, state); - } else if (ch == "#") { - stream.skipToEnd(); - return "comment"; - } else if (ch == "<" && (m = stream.match(/^<-?[\`\"\']?([a-zA-Z_?]\w*)[\`\"\']?(?:;|$)/))) { - return chain(readHereDoc(m[1]), stream, state); - } else if (ch == "0") { - if (stream.eat("x")) stream.eatWhile(/[\da-fA-F]/); - else if (stream.eat("b")) stream.eatWhile(/[01]/); - else stream.eatWhile(/[0-7]/); - return "number"; - } else if (/\d/.test(ch)) { - stream.match(/^[\d_]*(?:\.[\d_]+)?(?:[eE][+\-]?[\d_]+)?/); - return "number"; - } else if (ch == "?") { - while (stream.match(/^\\[CM]-/)) {} - if (stream.eat("\\")) stream.eatWhile(/\w/); - else stream.next(); - return "string"; - } else if (ch == ":") { - if (stream.eat("'")) return chain(readQuoted("'", "atom", false), stream, state); - if (stream.eat('"')) return chain(readQuoted('"', "atom", true), stream, state); - - // :> :>> :< :<< are valid symbols - if (stream.eat(/[\<\>]/)) { - stream.eat(/[\<\>]/); - return "atom"; - } - - // :+ :- :/ :* :| :& :! are valid symbols - if (stream.eat(/[\+\-\*\/\&\|\:\!]/)) { - return "atom"; - } - - // Symbols can't start by a digit - if (stream.eat(/[a-zA-Z$@_\xa1-\uffff]/)) { - stream.eatWhile(/[\w$\xa1-\uffff]/); - // Only one ? ! = is allowed and only as the last character - stream.eat(/[\?\!\=]/); - return "atom"; - } - return "operator"; - } else if (ch == "@" && stream.match(/^@?[a-zA-Z_\xa1-\uffff]/)) { - stream.eat("@"); - stream.eatWhile(/[\w\xa1-\uffff]/); - return "variable-2"; - } else if (ch == "$") { - if (stream.eat(/[a-zA-Z_]/)) { - stream.eatWhile(/[\w]/); - } else if (stream.eat(/\d/)) { - stream.eat(/\d/); - } else { - stream.next(); // Must be a special global like $: or $! - } - return "variable-3"; - } else if (/[a-zA-Z_\xa1-\uffff]/.test(ch)) { - stream.eatWhile(/[\w\xa1-\uffff]/); - stream.eat(/[\?\!]/); - if (stream.eat(":")) return "atom"; - return "ident"; - } else if (ch == "|" && (state.varList || state.lastTok == "{" || state.lastTok == "do")) { - curPunc = "|"; - return null; - } else if (/[\(\)\[\]{}\\;]/.test(ch)) { - curPunc = ch; - return null; - } else if (ch == "-" && stream.eat(">")) { - return "arrow"; - } else if (/[=+\-\/*:\.^%<>~|]/.test(ch)) { - var more = stream.eatWhile(/[=+\-\/*:\.^%<>~|]/); - if (ch == "." && !more) curPunc = "."; - return "operator"; - } else { - return null; - } - } - - function tokenBaseUntilBrace(depth) { - if (!depth) depth = 1; - return function(stream, state) { - if (stream.peek() == "}") { - if (depth == 1) { - state.tokenize.pop(); - return state.tokenize[state.tokenize.length-1](stream, state); - } else { - state.tokenize[state.tokenize.length - 1] = tokenBaseUntilBrace(depth - 1); - } - } else if (stream.peek() == "{") { - state.tokenize[state.tokenize.length - 1] = tokenBaseUntilBrace(depth + 1); - } - return tokenBase(stream, state); - }; - } - function tokenBaseOnce() { - var alreadyCalled = false; - return function(stream, state) { - if (alreadyCalled) { - state.tokenize.pop(); - return state.tokenize[state.tokenize.length-1](stream, state); - } - alreadyCalled = true; - return tokenBase(stream, state); - }; - } - function readQuoted(quote, style, embed, unescaped) { - return function(stream, state) { - var escaped = false, ch; - - if (state.context.type === 'read-quoted-paused') { - state.context = state.context.prev; - stream.eat("}"); - } - - while ((ch = stream.next()) != null) { - if (ch == quote && (unescaped || !escaped)) { - state.tokenize.pop(); - break; - } - if (embed && ch == "#" && !escaped) { - if (stream.eat("{")) { - if (quote == "}") { - state.context = {prev: state.context, type: 'read-quoted-paused'}; - } - state.tokenize.push(tokenBaseUntilBrace()); - break; - } else if (/[@\$]/.test(stream.peek())) { - state.tokenize.push(tokenBaseOnce()); - break; - } - } - escaped = !escaped && ch == "\\"; - } - return style; - }; - } - function readHereDoc(phrase) { - return function(stream, state) { - if (stream.match(phrase)) state.tokenize.pop(); - else stream.skipToEnd(); - return "string"; - }; - } - function readBlockComment(stream, state) { - if (stream.sol() && stream.match("=end") && stream.eol()) - state.tokenize.pop(); - stream.skipToEnd(); - return "comment"; - } - - return { - startState: function() { - return {tokenize: [tokenBase], - indented: 0, - context: {type: "top", indented: -config.indentUnit}, - continuedLine: false, - lastTok: null, - varList: false}; - }, - - token: function(stream, state) { - curPunc = null; - if (stream.sol()) state.indented = stream.indentation(); - var style = state.tokenize[state.tokenize.length-1](stream, state), kwtype; - var thisTok = curPunc; - if (style == "ident") { - var word = stream.current(); - style = state.lastTok == "." ? "property" - : keywords.propertyIsEnumerable(stream.current()) ? "keyword" - : /^[A-Z]/.test(word) ? "tag" - : (state.lastTok == "def" || state.lastTok == "class" || state.varList) ? "def" - : "variable"; - if (style == "keyword") { - thisTok = word; - if (indentWords.propertyIsEnumerable(word)) kwtype = "indent"; - else if (dedentWords.propertyIsEnumerable(word)) kwtype = "dedent"; - else if ((word == "if" || word == "unless") && stream.column() == stream.indentation()) - kwtype = "indent"; - else if (word == "do" && state.context.indented < state.indented) - kwtype = "indent"; - } - } - if (curPunc || (style && style != "comment")) state.lastTok = thisTok; - if (curPunc == "|") state.varList = !state.varList; - - if (kwtype == "indent" || /[\(\[\{]/.test(curPunc)) - state.context = {prev: state.context, type: curPunc || style, indented: state.indented}; - else if ((kwtype == "dedent" || /[\)\]\}]/.test(curPunc)) && state.context.prev) - state.context = state.context.prev; - - if (stream.eol()) - state.continuedLine = (curPunc == "\\" || style == "operator"); - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize[state.tokenize.length-1] != tokenBase) return 0; - var firstChar = textAfter && textAfter.charAt(0); - var ct = state.context; - var closing = ct.type == matching[firstChar] || - ct.type == "keyword" && /^(?:end|until|else|elsif|when|rescue)\b/.test(textAfter); - return ct.indented + (closing ? 0 : config.indentUnit) + - (state.continuedLine ? config.indentUnit : 0); - }, - - electricInput: /^\s*(?:end|rescue|elsif|else|\})$/, - lineComment: "#" - }; -}); - -CodeMirror.defineMIME("text/x-ruby", "ruby"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/ruby/test.js b/backend/_pv_1_3_5/static/codemirror/mode/ruby/test.js deleted file mode 100755 index cade864ff..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/ruby/test.js +++ /dev/null @@ -1,14 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "ruby"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT("divide_equal_operator", - "[variable bar] [operator /=] [variable foo]"); - - MT("divide_equal_operator_no_spacing", - "[variable foo][operator /=][number 42]"); - -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/rust/index.html b/backend/_pv_1_3_5/static/codemirror/mode/rust/index.html deleted file mode 100755 index 1fe0ad1e6..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/rust/index.html +++ /dev/null @@ -1,64 +0,0 @@ - - -CodeMirror: Rust mode - - - - - - - - - - -
    -

    Rust mode

    - - -
    - - - -

    MIME types defined: text/x-rustsrc.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/rust/rust.js b/backend/_pv_1_3_5/static/codemirror/mode/rust/rust.js deleted file mode 100755 index 8558b53fe..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/rust/rust.js +++ /dev/null @@ -1,71 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../../addon/mode/simple")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../../addon/mode/simple"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineSimpleMode("rust",{ - start: [ - // string and byte string - {regex: /b?"/, token: "string", next: "string"}, - // raw string and raw byte string - {regex: /b?r"/, token: "string", next: "string_raw"}, - {regex: /b?r#+"/, token: "string", next: "string_raw_hash"}, - // character - {regex: /'(?:[^'\\]|\\(?:[nrt0'"]|x[\da-fA-F]{2}|u\{[\da-fA-F]{6}\}))'/, token: "string-2"}, - // byte - {regex: /b'(?:[^']|\\(?:['\\nrt0]|x[\da-fA-F]{2}))'/, token: "string-2"}, - - {regex: /(?:(?:[0-9][0-9_]*)(?:(?:[Ee][+-]?[0-9_]+)|\.[0-9_]+(?:[Ee][+-]?[0-9_]+)?)(?:f32|f64)?)|(?:0(?:b[01_]+|(?:o[0-7_]+)|(?:x[0-9a-fA-F_]+))|(?:[0-9][0-9_]*))(?:u8|u16|u32|u64|i8|i16|i32|i64|isize|usize)?/, - token: "number"}, - {regex: /(let(?:\s+mut)?|fn|enum|mod|struct|type)(\s+)([a-zA-Z_][a-zA-Z0-9_]*)/, token: ["keyword", null, "def"]}, - {regex: /(?:abstract|alignof|as|box|break|continue|const|crate|do|else|enum|extern|fn|for|final|if|impl|in|loop|macro|match|mod|move|offsetof|override|priv|proc|pub|pure|ref|return|self|sizeof|static|struct|super|trait|type|typeof|unsafe|unsized|use|virtual|where|while|yield)\b/, token: "keyword"}, - {regex: /\b(?:Self|isize|usize|char|bool|u8|u16|u32|u64|f16|f32|f64|i8|i16|i32|i64|str|Option)\b/, token: "atom"}, - {regex: /\b(?:true|false|Some|None|Ok|Err)\b/, token: "builtin"}, - {regex: /\b(fn)(\s+)([a-zA-Z_][a-zA-Z0-9_]*)/, - token: ["keyword", null ,"def"]}, - {regex: /#!?\[.*\]/, token: "meta"}, - {regex: /\/\/.*/, token: "comment"}, - {regex: /\/\*/, token: "comment", next: "comment"}, - {regex: /[-+\/*=<>!]+/, token: "operator"}, - {regex: /[a-zA-Z_]\w*!/,token: "variable-3"}, - {regex: /[a-zA-Z_]\w*/, token: "variable"}, - {regex: /[\{\[\(]/, indent: true}, - {regex: /[\}\]\)]/, dedent: true} - ], - string: [ - {regex: /"/, token: "string", next: "start"}, - {regex: /(?:[^\\"]|\\(?:.|$))*/, token: "string"} - ], - string_raw: [ - {regex: /"/, token: "string", next: "start"}, - {regex: /[^"]*/, token: "string"} - ], - string_raw_hash: [ - {regex: /"#+/, token: "string", next: "start"}, - {regex: /(?:[^"]|"(?!#))*/, token: "string"} - ], - comment: [ - {regex: /.*?\*\//, token: "comment", next: "start"}, - {regex: /.*/, token: "comment"} - ], - meta: { - dontIndentStates: ["comment"], - electricInput: /^\s*\}$/, - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: "//", - fold: "brace" - } -}); - - -CodeMirror.defineMIME("text/x-rustsrc", "rust"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/rust/test.js b/backend/_pv_1_3_5/static/codemirror/mode/rust/test.js deleted file mode 100755 index eb256c47e..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/rust/test.js +++ /dev/null @@ -1,39 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 4}, "rust"); - function MT(name) {test.mode(name, mode, Array.prototype.slice.call(arguments, 1));} - - MT('integer_test', - '[number 123i32]', - '[number 123u32]', - '[number 123_u32]', - '[number 0xff_u8]', - '[number 0o70_i16]', - '[number 0b1111_1111_1001_0000_i32]', - '[number 0usize]'); - - MT('float_test', - '[number 123.0f64]', - '[number 0.1f64]', - '[number 0.1f32]', - '[number 12E+99_f64]'); - - MT('string-literals-test', - '[string "foo"]', - '[string r"foo"]', - '[string "\\"foo\\""]', - '[string r#""foo""#]', - '[string "foo #\\"# bar"]', - - '[string b"foo"]', - '[string br"foo"]', - '[string b"\\"foo\\""]', - '[string br#""foo""#]', - '[string br##"foo #" bar"##]', - - "[string-2 'h']", - "[string-2 b'h']"); - -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/sas/index.html b/backend/_pv_1_3_5/static/codemirror/mode/sas/index.html deleted file mode 100755 index 636e06594..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/sas/index.html +++ /dev/null @@ -1,81 +0,0 @@ - - -CodeMirror: SAS mode - - - - - - - - - - -
    -

    SAS mode

    -
    - - - -

    MIME types defined: text/x-sas.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/sas/sas.js b/backend/_pv_1_3_5/static/codemirror/mode/sas/sas.js deleted file mode 100755 index a6109eb11..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/sas/sas.js +++ /dev/null @@ -1,316 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - - -// SAS mode copyright (c) 2016 Jared Dean, SAS Institute -// Created by Jared Dean - -// TODO -// indent and de-indent -// identify macro variables - - -//Definitions -// comment -- text withing * ; or /* */ -// keyword -- SAS language variable -// variable -- macro variables starts with '&' or variable formats -// variable-2 -- DATA Step, proc, or macro names -// string -- text within ' ' or " " -// operator -- numeric operator + / - * ** le eq ge ... and so on -// builtin -- proc %macro data run mend -// atom -// def - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("sas", function () { - var words = {}; - var isDoubleOperatorSym = { - eq: 'operator', - lt: 'operator', - le: 'operator', - gt: 'operator', - ge: 'operator', - "in": 'operator', - ne: 'operator', - or: 'operator' - }; - var isDoubleOperatorChar = /(<=|>=|!=|<>)/; - var isSingleOperatorChar = /[=\(:\),{}.*<>+\-\/^\[\]]/; - - // Takes a string of words separated by spaces and adds them as - // keys with the value of the first argument 'style' - function define(style, string, context) { - if (context) { - var split = string.split(' '); - for (var i = 0; i < split.length; i++) { - words[split[i]] = {style: style, state: context}; - } - } - } - //datastep - define('def', 'stack pgm view source debug nesting nolist', ['inDataStep']); - define('def', 'if while until for do do; end end; then else cancel', ['inDataStep']); - define('def', 'label format _n_ _error_', ['inDataStep']); - define('def', 'ALTER BUFNO BUFSIZE CNTLLEV COMPRESS DLDMGACTION ENCRYPT ENCRYPTKEY EXTENDOBSCOUNTER GENMAX GENNUM INDEX LABEL OBSBUF OUTREP PW PWREQ READ REPEMPTY REPLACE REUSE ROLE SORTEDBY SPILL TOBSNO TYPE WRITE FILECLOSE FIRSTOBS IN OBS POINTOBS WHERE WHEREUP IDXNAME IDXWHERE DROP KEEP RENAME', ['inDataStep']); - define('def', 'filevar finfo finv fipname fipnamel fipstate first firstobs floor', ['inDataStep']); - define('def', 'varfmt varinfmt varlabel varlen varname varnum varray varrayx vartype verify vformat vformatd vformatdx vformatn vformatnx vformatw vformatwx vformatx vinarray vinarrayx vinformat vinformatd vinformatdx vinformatn vinformatnx vinformatw vinformatwx vinformatx vlabel vlabelx vlength vlengthx vname vnamex vnferr vtype vtypex weekday', ['inDataStep']); - define('def', 'zipfips zipname zipnamel zipstate', ['inDataStep']); - define('def', 'put putc putn', ['inDataStep']); - define('builtin', 'data run', ['inDataStep']); - - - //proc - define('def', 'data', ['inProc']); - - // flow control for macros - define('def', '%if %end %end; %else %else; %do %do; %then', ['inMacro']); - - //everywhere - define('builtin', 'proc run; quit; libname filename %macro %mend option options', ['ALL']); - - define('def', 'footnote title libname ods', ['ALL']); - define('def', '%let %put %global %sysfunc %eval ', ['ALL']); - // automatic macro variables http://support.sas.com/documentation/cdl/en/mcrolref/61885/HTML/default/viewer.htm#a003167023.htm - define('variable', '&sysbuffr &syscc &syscharwidth &syscmd &sysdate &sysdate9 &sysday &sysdevic &sysdmg &sysdsn &sysencoding &sysenv &syserr &syserrortext &sysfilrc &syshostname &sysindex &sysinfo &sysjobid &syslast &syslckrc &syslibrc &syslogapplname &sysmacroname &sysmenv &sysmsg &sysncpu &sysodspath &sysparm &syspbuff &sysprocessid &sysprocessname &sysprocname &sysrc &sysscp &sysscpl &sysscpl &syssite &sysstartid &sysstartname &systcpiphostname &systime &sysuserid &sysver &sysvlong &sysvlong4 &syswarningtext', ['ALL']); - - //footnote[1-9]? title[1-9]? - - //options statement - define('def', 'source2 nosource2 page pageno pagesize', ['ALL']); - - //proc and datastep - define('def', '_all_ _character_ _cmd_ _freq_ _i_ _infile_ _last_ _msg_ _null_ _numeric_ _temporary_ _type_ abort abs addr adjrsq airy alpha alter altlog altprint and arcos array arsin as atan attrc attrib attrn authserver autoexec awscontrol awsdef awsmenu awsmenumerge awstitle backward band base betainv between blocksize blshift bnot bor brshift bufno bufsize bxor by byerr byline byte calculated call cards cards4 catcache cbufno cdf ceil center cexist change chisq cinv class cleanup close cnonct cntllev coalesce codegen col collate collin column comamid comaux1 comaux2 comdef compbl compound compress config continue convert cos cosh cpuid create cross crosstab css curobs cv daccdb daccdbsl daccsl daccsyd dacctab dairy datalines datalines4 datejul datepart datetime day dbcslang dbcstype dclose ddm delete delimiter depdb depdbsl depsl depsyd deptab dequote descending descript design= device dflang dhms dif digamma dim dinfo display distinct dkricond dkrocond dlm dnum do dopen doptname doptnum dread drop dropnote dsname dsnferr echo else emaildlg emailid emailpw emailserver emailsys encrypt end endsas engine eof eov erf erfc error errorcheck errors exist exp fappend fclose fcol fdelete feedback fetch fetchobs fexist fget file fileclose fileexist filefmt filename fileref fmterr fmtsearch fnonct fnote font fontalias fopen foptname foptnum force formatted formchar formdelim formdlim forward fpoint fpos fput fread frewind frlen from fsep fuzz fwrite gaminv gamma getoption getvarc getvarn go goto group gwindow hbar hbound helpenv helploc hms honorappearance hosthelp hostprint hour hpct html hvar ibessel ibr id if index indexc indexw initcmd initstmt inner input inputc inputn inr insert int intck intnx into intrr invaliddata irr is jbessel join juldate keep kentb kurtosis label lag last lbound leave left length levels lgamma lib library libref line linesize link list log log10 log2 logpdf logpmf logsdf lostcard lowcase lrecl ls macro macrogen maps mautosource max maxdec maxr mdy mean measures median memtype merge merror min minute missing missover mlogic mod mode model modify month mopen mort mprint mrecall msglevel msymtabmax mvarsize myy n nest netpv new news nmiss no nobatch nobs nocaps nocardimage nocenter nocharcode nocmdmac nocol nocum nodate nodbcs nodetails nodmr nodms nodmsbatch nodup nodupkey noduplicates noechoauto noequals noerrorabend noexitwindows nofullstimer noicon noimplmac noint nolist noloadlist nomiss nomlogic nomprint nomrecall nomsgcase nomstored nomultenvappl nonotes nonumber noobs noovp nopad nopercent noprint noprintinit normal norow norsasuser nosetinit nosplash nosymbolgen note notes notitle notitles notsorted noverbose noxsync noxwait npv null number numkeys nummousekeys nway obs on open order ordinal otherwise out outer outp= output over ovp p(1 5 10 25 50 75 90 95 99) pad pad2 paired parm parmcards path pathdll pathname pdf peek peekc pfkey pmf point poisson poke position printer probbeta probbnml probchi probf probgam probhypr probit probnegb probnorm probsig probt procleave prt ps pw pwreq qtr quote r ranbin rancau ranexp rangam range ranks rannor ranpoi rantbl rantri ranuni read recfm register regr remote remove rename repeat replace resolve retain return reuse reverse rewind right round rsquare rtf rtrace rtraceloc s s2 samploc sasautos sascontrol sasfrscr sasmsg sasmstore sasscript sasuser saving scan sdf second select selection separated seq serror set setcomm setot sign simple sin sinh siteinfo skewness skip sle sls sortedby sortpgm sortseq sortsize soundex spedis splashlocation split spool sqrt start std stderr stdin stfips stimer stname stnamel stop stopover subgroup subpopn substr sum sumwgt symbol symbolgen symget symput sysget sysin sysleave sysmsg sysparm sysprint sysprintfont sysprod sysrc system t table tables tan tanh tapeclose tbufsize terminal test then timepart tinv tnonct to today tol tooldef totper transformout translate trantab tranwrd trigamma trim trimn trunc truncover type unformatted uniform union until upcase update user usericon uss validate value var weight when where while wincharset window work workinit workterm write wsum xsync xwait yearcutoff yes yyq min max', ['inDataStep', 'inProc']); - define('operator', 'and not ', ['inDataStep', 'inProc']); - - // Main function - function tokenize(stream, state) { - // Finally advance the stream - var ch = stream.next(); - - // BLOCKCOMMENT - if (ch === '/' && stream.eat('*')) { - state.continueComment = true; - return "comment"; - } else if (state.continueComment === true) { // in comment block - //comment ends at the beginning of the line - if (ch === '*' && stream.peek() === '/') { - stream.next(); - state.continueComment = false; - } else if (stream.skipTo('*')) { //comment is potentially later in line - stream.skipTo('*'); - stream.next(); - if (stream.eat('/')) - state.continueComment = false; - } else { - stream.skipToEnd(); - } - return "comment"; - } - - // DoubleOperator match - var doubleOperator = ch + stream.peek(); - - // Match all line comments. - var myString = stream.string; - var myRegexp = /(?:^\s*|[;]\s*)(\*.*?);/ig; - var match = myRegexp.exec(myString); - if (match !== null) { - if (match.index === 0 && (stream.column() !== (match.index + match[0].length - 1))) { - stream.backUp(stream.column()); - stream.skipTo(';'); - stream.next(); - return 'comment'; - } else if (match.index + 1 < stream.column() && stream.column() < match.index + match[0].length - 1) { - // the ';' triggers the match so move one past it to start - // the comment block that is why match.index+1 - stream.backUp(stream.column() - match.index - 1); - stream.skipTo(';'); - stream.next(); - return 'comment'; - } - } else if ((ch === '"' || ch === "'") && !state.continueString) { - state.continueString = ch - return "string" - } else if (state.continueString) { - if (state.continueString == ch) { - state.continueString = null; - } else if (stream.skipTo(state.continueString)) { - // quote found on this line - stream.next(); - state.continueString = null; - } else { - stream.skipToEnd(); - } - return "string"; - } else if (state.continueString !== null && stream.eol()) { - stream.skipTo(state.continueString) || stream.skipToEnd(); - return "string"; - } else if (/[\d\.]/.test(ch)) { //find numbers - if (ch === ".") - stream.match(/^[0-9]+([eE][\-+]?[0-9]+)?/); - else if (ch === "0") - stream.match(/^[xX][0-9a-fA-F]+/) || stream.match(/^0[0-7]+/); - else - stream.match(/^[0-9]*\.?[0-9]*([eE][\-+]?[0-9]+)?/); - return "number"; - } else if (isDoubleOperatorChar.test(ch + stream.peek())) { // TWO SYMBOL TOKENS - stream.next(); - return "operator"; - } else if (isDoubleOperatorSym.hasOwnProperty(doubleOperator)) { - stream.next(); - if (stream.peek() === ' ') - return isDoubleOperatorSym[doubleOperator.toLowerCase()]; - } else if (isSingleOperatorChar.test(ch)) { // SINGLE SYMBOL TOKENS - return "operator"; - } - - // Matches one whole word -- even if the word is a character - var word; - if (stream.match(/[%&;\w]+/, false) != null) { - word = ch + stream.match(/[%&;\w]+/, true); - if (/&/.test(word)) return 'variable' - } else { - word = ch; - } - // the word after DATA PROC or MACRO - if (state.nextword) { - stream.match(/[\w]+/); - // match memname.libname - if (stream.peek() === '.') stream.skipTo(' '); - state.nextword = false; - return 'variable-2'; - } - - word = word.toLowerCase() - // Are we in a DATA Step? - if (state.inDataStep) { - if (word === 'run;' || stream.match(/run\s;/)) { - state.inDataStep = false; - return 'builtin'; - } - // variable formats - if ((word) && stream.next() === '.') { - //either a format or libname.memname - if (/\w/.test(stream.peek())) return 'variable-2'; - else return 'variable'; - } - // do we have a DATA Step keyword - if (word && words.hasOwnProperty(word) && - (words[word].state.indexOf("inDataStep") !== -1 || - words[word].state.indexOf("ALL") !== -1)) { - //backup to the start of the word - if (stream.start < stream.pos) - stream.backUp(stream.pos - stream.start); - //advance the length of the word and return - for (var i = 0; i < word.length; ++i) stream.next(); - return words[word].style; - } - } - // Are we in an Proc statement? - if (state.inProc) { - if (word === 'run;' || word === 'quit;') { - state.inProc = false; - return 'builtin'; - } - // do we have a proc keyword - if (word && words.hasOwnProperty(word) && - (words[word].state.indexOf("inProc") !== -1 || - words[word].state.indexOf("ALL") !== -1)) { - stream.match(/[\w]+/); - return words[word].style; - } - } - // Are we in a Macro statement? - if (state.inMacro) { - if (word === '%mend') { - if (stream.peek() === ';') stream.next(); - state.inMacro = false; - return 'builtin'; - } - if (word && words.hasOwnProperty(word) && - (words[word].state.indexOf("inMacro") !== -1 || - words[word].state.indexOf("ALL") !== -1)) { - stream.match(/[\w]+/); - return words[word].style; - } - - return 'atom'; - } - // Do we have Keywords specific words? - if (word && words.hasOwnProperty(word)) { - // Negates the initial next() - stream.backUp(1); - // Actually move the stream - stream.match(/[\w]+/); - if (word === 'data' && /=/.test(stream.peek()) === false) { - state.inDataStep = true; - state.nextword = true; - return 'builtin'; - } - if (word === 'proc') { - state.inProc = true; - state.nextword = true; - return 'builtin'; - } - if (word === '%macro') { - state.inMacro = true; - state.nextword = true; - return 'builtin'; - } - if (/title[1-9]/.test(word)) return 'def'; - - if (word === 'footnote') { - stream.eat(/[1-9]/); - return 'def'; - } - - // Returns their value as state in the prior define methods - if (state.inDataStep === true && words[word].state.indexOf("inDataStep") !== -1) - return words[word].style; - if (state.inProc === true && words[word].state.indexOf("inProc") !== -1) - return words[word].style; - if (state.inMacro === true && words[word].state.indexOf("inMacro") !== -1) - return words[word].style; - if (words[word].state.indexOf("ALL") !== -1) - return words[word].style; - return null; - } - // Unrecognized syntax - return null; - } - - return { - startState: function () { - return { - inDataStep: false, - inProc: false, - inMacro: false, - nextword: false, - continueString: null, - continueComment: false - }; - }, - token: function (stream, state) { - // Strip the spaces, but regex will account for them either way - if (stream.eatSpace()) return null; - // Go through the main process - return tokenize(stream, state); - }, - - blockCommentStart: "/*", - blockCommentEnd: "*/" - }; - - }); - - CodeMirror.defineMIME("text/x-sas", "sas"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/sass/index.html b/backend/_pv_1_3_5/static/codemirror/mode/sass/index.html deleted file mode 100755 index 9f4a79022..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/sass/index.html +++ /dev/null @@ -1,66 +0,0 @@ - - -CodeMirror: Sass mode - - - - - - - - - - -
    -

    Sass mode

    -
    - - -

    MIME types defined: text/x-sass.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/sass/sass.js b/backend/_pv_1_3_5/static/codemirror/mode/sass/sass.js deleted file mode 100755 index 6973ece29..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/sass/sass.js +++ /dev/null @@ -1,414 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("sass", function(config) { - function tokenRegexp(words) { - return new RegExp("^" + words.join("|")); - } - - var keywords = ["true", "false", "null", "auto"]; - var keywordsRegexp = new RegExp("^" + keywords.join("|")); - - var operators = ["\\(", "\\)", "=", ">", "<", "==", ">=", "<=", "\\+", "-", - "\\!=", "/", "\\*", "%", "and", "or", "not", ";","\\{","\\}",":"]; - var opRegexp = tokenRegexp(operators); - - var pseudoElementsRegexp = /^::?[a-zA-Z_][\w\-]*/; - - function urlTokens(stream, state) { - var ch = stream.peek(); - - if (ch === ")") { - stream.next(); - state.tokenizer = tokenBase; - return "operator"; - } else if (ch === "(") { - stream.next(); - stream.eatSpace(); - - return "operator"; - } else if (ch === "'" || ch === '"') { - state.tokenizer = buildStringTokenizer(stream.next()); - return "string"; - } else { - state.tokenizer = buildStringTokenizer(")", false); - return "string"; - } - } - function comment(indentation, multiLine) { - return function(stream, state) { - if (stream.sol() && stream.indentation() <= indentation) { - state.tokenizer = tokenBase; - return tokenBase(stream, state); - } - - if (multiLine && stream.skipTo("*/")) { - stream.next(); - stream.next(); - state.tokenizer = tokenBase; - } else { - stream.skipToEnd(); - } - - return "comment"; - }; - } - - function buildStringTokenizer(quote, greedy) { - if (greedy == null) { greedy = true; } - - function stringTokenizer(stream, state) { - var nextChar = stream.next(); - var peekChar = stream.peek(); - var previousChar = stream.string.charAt(stream.pos-2); - - var endingString = ((nextChar !== "\\" && peekChar === quote) || (nextChar === quote && previousChar !== "\\")); - - if (endingString) { - if (nextChar !== quote && greedy) { stream.next(); } - state.tokenizer = tokenBase; - return "string"; - } else if (nextChar === "#" && peekChar === "{") { - state.tokenizer = buildInterpolationTokenizer(stringTokenizer); - stream.next(); - return "operator"; - } else { - return "string"; - } - } - - return stringTokenizer; - } - - function buildInterpolationTokenizer(currentTokenizer) { - return function(stream, state) { - if (stream.peek() === "}") { - stream.next(); - state.tokenizer = currentTokenizer; - return "operator"; - } else { - return tokenBase(stream, state); - } - }; - } - - function indent(state) { - if (state.indentCount == 0) { - state.indentCount++; - var lastScopeOffset = state.scopes[0].offset; - var currentOffset = lastScopeOffset + config.indentUnit; - state.scopes.unshift({ offset:currentOffset }); - } - } - - function dedent(state) { - if (state.scopes.length == 1) return; - - state.scopes.shift(); - } - - function tokenBase(stream, state) { - var ch = stream.peek(); - - // Comment - if (stream.match("/*")) { - state.tokenizer = comment(stream.indentation(), true); - return state.tokenizer(stream, state); - } - if (stream.match("//")) { - state.tokenizer = comment(stream.indentation(), false); - return state.tokenizer(stream, state); - } - - // Interpolation - if (stream.match("#{")) { - state.tokenizer = buildInterpolationTokenizer(tokenBase); - return "operator"; - } - - // Strings - if (ch === '"' || ch === "'") { - stream.next(); - state.tokenizer = buildStringTokenizer(ch); - return "string"; - } - - if(!state.cursorHalf){// state.cursorHalf === 0 - // first half i.e. before : for key-value pairs - // including selectors - - if (ch === ".") { - stream.next(); - if (stream.match(/^[\w-]+/)) { - indent(state); - return "atom"; - } else if (stream.peek() === "#") { - indent(state); - return "atom"; - } - } - - if (ch === "#") { - stream.next(); - // ID selectors - if (stream.match(/^[\w-]+/)) { - indent(state); - return "atom"; - } - if (stream.peek() === "#") { - indent(state); - return "atom"; - } - } - - // Variables - if (ch === "$") { - stream.next(); - stream.eatWhile(/[\w-]/); - return "variable-2"; - } - - // Numbers - if (stream.match(/^-?[0-9\.]+/)) - return "number"; - - // Units - if (stream.match(/^(px|em|in)\b/)) - return "unit"; - - if (stream.match(keywordsRegexp)) - return "keyword"; - - if (stream.match(/^url/) && stream.peek() === "(") { - state.tokenizer = urlTokens; - return "atom"; - } - - if (ch === "=") { - // Match shortcut mixin definition - if (stream.match(/^=[\w-]+/)) { - indent(state); - return "meta"; - } - } - - if (ch === "+") { - // Match shortcut mixin definition - if (stream.match(/^\+[\w-]+/)){ - return "variable-3"; - } - } - - if(ch === "@"){ - if(stream.match(/@extend/)){ - if(!stream.match(/\s*[\w]/)) - dedent(state); - } - } - - - // Indent Directives - if (stream.match(/^@(else if|if|media|else|for|each|while|mixin|function)/)) { - indent(state); - return "meta"; - } - - // Other Directives - if (ch === "@") { - stream.next(); - stream.eatWhile(/[\w-]/); - return "meta"; - } - - if (stream.eatWhile(/[\w-]/)){ - if(stream.match(/ *: *[\w-\+\$#!\("']/,false)){ - return "property"; - } - else if(stream.match(/ *:/,false)){ - indent(state); - state.cursorHalf = 1; - return "atom"; - } - else if(stream.match(/ *,/,false)){ - return "atom"; - } - else{ - indent(state); - return "atom"; - } - } - - if(ch === ":"){ - if (stream.match(pseudoElementsRegexp)){ // could be a pseudo-element - return "keyword"; - } - stream.next(); - state.cursorHalf=1; - return "operator"; - } - - } // cursorHalf===0 ends here - else{ - - if (ch === "#") { - stream.next(); - // Hex numbers - if (stream.match(/[0-9a-fA-F]{6}|[0-9a-fA-F]{3}/)){ - if(!stream.peek()){ - state.cursorHalf = 0; - } - return "number"; - } - } - - // Numbers - if (stream.match(/^-?[0-9\.]+/)){ - if(!stream.peek()){ - state.cursorHalf = 0; - } - return "number"; - } - - // Units - if (stream.match(/^(px|em|in)\b/)){ - if(!stream.peek()){ - state.cursorHalf = 0; - } - return "unit"; - } - - if (stream.match(keywordsRegexp)){ - if(!stream.peek()){ - state.cursorHalf = 0; - } - return "keyword"; - } - - if (stream.match(/^url/) && stream.peek() === "(") { - state.tokenizer = urlTokens; - if(!stream.peek()){ - state.cursorHalf = 0; - } - return "atom"; - } - - // Variables - if (ch === "$") { - stream.next(); - stream.eatWhile(/[\w-]/); - if(!stream.peek()){ - state.cursorHalf = 0; - } - return "variable-3"; - } - - // bang character for !important, !default, etc. - if (ch === "!") { - stream.next(); - if(!stream.peek()){ - state.cursorHalf = 0; - } - return stream.match(/^[\w]+/) ? "keyword": "operator"; - } - - if (stream.match(opRegexp)){ - if(!stream.peek()){ - state.cursorHalf = 0; - } - return "operator"; - } - - // attributes - if (stream.eatWhile(/[\w-]/)) { - if(!stream.peek()){ - state.cursorHalf = 0; - } - return "attribute"; - } - - //stream.eatSpace(); - if(!stream.peek()){ - state.cursorHalf = 0; - return null; - } - - } // else ends here - - if (stream.match(opRegexp)) - return "operator"; - - // If we haven't returned by now, we move 1 character - // and return an error - stream.next(); - return null; - } - - function tokenLexer(stream, state) { - if (stream.sol()) state.indentCount = 0; - var style = state.tokenizer(stream, state); - var current = stream.current(); - - if (current === "@return" || current === "}"){ - dedent(state); - } - - if (style !== null) { - var startOfToken = stream.pos - current.length; - - var withCurrentIndent = startOfToken + (config.indentUnit * state.indentCount); - - var newScopes = []; - - for (var i = 0; i < state.scopes.length; i++) { - var scope = state.scopes[i]; - - if (scope.offset <= withCurrentIndent) - newScopes.push(scope); - } - - state.scopes = newScopes; - } - - - return style; - } - - return { - startState: function() { - return { - tokenizer: tokenBase, - scopes: [{offset: 0, type: "sass"}], - indentCount: 0, - cursorHalf: 0, // cursor half tells us if cursor lies after (1) - // or before (0) colon (well... more or less) - definedVars: [], - definedMixins: [] - }; - }, - token: function(stream, state) { - var style = tokenLexer(stream, state); - - state.lastToken = { style: style, content: stream.current() }; - - return style; - }, - - indent: function(state) { - return state.scopes[0].offset; - } - }; -}); - -CodeMirror.defineMIME("text/x-sass", "sass"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/scheme/index.html b/backend/_pv_1_3_5/static/codemirror/mode/scheme/index.html deleted file mode 100755 index 04d5c6a2a..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/scheme/index.html +++ /dev/null @@ -1,77 +0,0 @@ - - -CodeMirror: Scheme mode - - - - - - - - - -
    -

    Scheme mode

    -
    - - -

    MIME types defined: text/x-scheme.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/scheme/scheme.js b/backend/_pv_1_3_5/static/codemirror/mode/scheme/scheme.js deleted file mode 100755 index 223464591..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/scheme/scheme.js +++ /dev/null @@ -1,249 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** - * Author: Koh Zi Han, based on implementation by Koh Zi Chun - */ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("scheme", function () { - var BUILTIN = "builtin", COMMENT = "comment", STRING = "string", - ATOM = "atom", NUMBER = "number", BRACKET = "bracket"; - var INDENT_WORD_SKIP = 2; - - function makeKeywords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - var keywords = makeKeywords("λ case-lambda call/cc class define-class exit-handler field import inherit init-field interface let*-values let-values let/ec mixin opt-lambda override protect provide public rename require require-for-syntax syntax syntax-case syntax-error unit/sig unless when with-syntax and begin call-with-current-continuation call-with-input-file call-with-output-file case cond define define-syntax delay do dynamic-wind else for-each if lambda let let* let-syntax letrec letrec-syntax map or syntax-rules abs acos angle append apply asin assoc assq assv atan boolean? caar cadr call-with-input-file call-with-output-file call-with-values car cdddar cddddr cdr ceiling char->integer char-alphabetic? char-ci<=? char-ci=? char-ci>? char-downcase char-lower-case? char-numeric? char-ready? char-upcase char-upper-case? char-whitespace? char<=? char=? char>? char? close-input-port close-output-port complex? cons cos current-input-port current-output-port denominator display eof-object? eq? equal? eqv? eval even? exact->inexact exact? exp expt #f floor force gcd imag-part inexact->exact inexact? input-port? integer->char integer? interaction-environment lcm length list list->string list->vector list-ref list-tail list? load log magnitude make-polar make-rectangular make-string make-vector max member memq memv min modulo negative? newline not null-environment null? number->string number? numerator odd? open-input-file open-output-file output-port? pair? peek-char port? positive? procedure? quasiquote quote quotient rational? rationalize read read-char real-part real? remainder reverse round scheme-report-environment set! set-car! set-cdr! sin sqrt string string->list string->number string->symbol string-append string-ci<=? string-ci=? string-ci>? string-copy string-fill! string-length string-ref string-set! string<=? string=? string>? string? substring symbol->string symbol? #t tan transcript-off transcript-on truncate values vector vector->list vector-fill! vector-length vector-ref vector-set! with-input-from-file with-output-to-file write write-char zero?"); - var indentKeys = makeKeywords("define let letrec let* lambda"); - - function stateStack(indent, type, prev) { // represents a state stack object - this.indent = indent; - this.type = type; - this.prev = prev; - } - - function pushStack(state, indent, type) { - state.indentStack = new stateStack(indent, type, state.indentStack); - } - - function popStack(state) { - state.indentStack = state.indentStack.prev; - } - - var binaryMatcher = new RegExp(/^(?:[-+]i|[-+][01]+#*(?:\/[01]+#*)?i|[-+]?[01]+#*(?:\/[01]+#*)?@[-+]?[01]+#*(?:\/[01]+#*)?|[-+]?[01]+#*(?:\/[01]+#*)?[-+](?:[01]+#*(?:\/[01]+#*)?)?i|[-+]?[01]+#*(?:\/[01]+#*)?)(?=[()\s;"]|$)/i); - var octalMatcher = new RegExp(/^(?:[-+]i|[-+][0-7]+#*(?:\/[0-7]+#*)?i|[-+]?[0-7]+#*(?:\/[0-7]+#*)?@[-+]?[0-7]+#*(?:\/[0-7]+#*)?|[-+]?[0-7]+#*(?:\/[0-7]+#*)?[-+](?:[0-7]+#*(?:\/[0-7]+#*)?)?i|[-+]?[0-7]+#*(?:\/[0-7]+#*)?)(?=[()\s;"]|$)/i); - var hexMatcher = new RegExp(/^(?:[-+]i|[-+][\da-f]+#*(?:\/[\da-f]+#*)?i|[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?@[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?|[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?[-+](?:[\da-f]+#*(?:\/[\da-f]+#*)?)?i|[-+]?[\da-f]+#*(?:\/[\da-f]+#*)?)(?=[()\s;"]|$)/i); - var decimalMatcher = new RegExp(/^(?:[-+]i|[-+](?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)i|[-+]?(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)@[-+]?(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)|[-+]?(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)[-+](?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*)?i|(?:(?:(?:\d+#+\.?#*|\d+\.\d*#*|\.\d+#*|\d+)(?:[esfdl][-+]?\d+)?)|\d+#*\/\d+#*))(?=[()\s;"]|$)/i); - - function isBinaryNumber (stream) { - return stream.match(binaryMatcher); - } - - function isOctalNumber (stream) { - return stream.match(octalMatcher); - } - - function isDecimalNumber (stream, backup) { - if (backup === true) { - stream.backUp(1); - } - return stream.match(decimalMatcher); - } - - function isHexNumber (stream) { - return stream.match(hexMatcher); - } - - return { - startState: function () { - return { - indentStack: null, - indentation: 0, - mode: false, - sExprComment: false - }; - }, - - token: function (stream, state) { - if (state.indentStack == null && stream.sol()) { - // update indentation, but only if indentStack is empty - state.indentation = stream.indentation(); - } - - // skip spaces - if (stream.eatSpace()) { - return null; - } - var returnType = null; - - switch(state.mode){ - case "string": // multi-line string parsing mode - var next, escaped = false; - while ((next = stream.next()) != null) { - if (next == "\"" && !escaped) { - - state.mode = false; - break; - } - escaped = !escaped && next == "\\"; - } - returnType = STRING; // continue on in scheme-string mode - break; - case "comment": // comment parsing mode - var next, maybeEnd = false; - while ((next = stream.next()) != null) { - if (next == "#" && maybeEnd) { - - state.mode = false; - break; - } - maybeEnd = (next == "|"); - } - returnType = COMMENT; - break; - case "s-expr-comment": // s-expr commenting mode - state.mode = false; - if(stream.peek() == "(" || stream.peek() == "["){ - // actually start scheme s-expr commenting mode - state.sExprComment = 0; - }else{ - // if not we just comment the entire of the next token - stream.eatWhile(/[^/s]/); // eat non spaces - returnType = COMMENT; - break; - } - default: // default parsing mode - var ch = stream.next(); - - if (ch == "\"") { - state.mode = "string"; - returnType = STRING; - - } else if (ch == "'") { - returnType = ATOM; - } else if (ch == '#') { - if (stream.eat("|")) { // Multi-line comment - state.mode = "comment"; // toggle to comment mode - returnType = COMMENT; - } else if (stream.eat(/[tf]/i)) { // #t/#f (atom) - returnType = ATOM; - } else if (stream.eat(';')) { // S-Expr comment - state.mode = "s-expr-comment"; - returnType = COMMENT; - } else { - var numTest = null, hasExactness = false, hasRadix = true; - if (stream.eat(/[ei]/i)) { - hasExactness = true; - } else { - stream.backUp(1); // must be radix specifier - } - if (stream.match(/^#b/i)) { - numTest = isBinaryNumber; - } else if (stream.match(/^#o/i)) { - numTest = isOctalNumber; - } else if (stream.match(/^#x/i)) { - numTest = isHexNumber; - } else if (stream.match(/^#d/i)) { - numTest = isDecimalNumber; - } else if (stream.match(/^[-+0-9.]/, false)) { - hasRadix = false; - numTest = isDecimalNumber; - // re-consume the intial # if all matches failed - } else if (!hasExactness) { - stream.eat('#'); - } - if (numTest != null) { - if (hasRadix && !hasExactness) { - // consume optional exactness after radix - stream.match(/^#[ei]/i); - } - if (numTest(stream)) - returnType = NUMBER; - } - } - } else if (/^[-+0-9.]/.test(ch) && isDecimalNumber(stream, true)) { // match non-prefixed number, must be decimal - returnType = NUMBER; - } else if (ch == ";") { // comment - stream.skipToEnd(); // rest of the line is a comment - returnType = COMMENT; - } else if (ch == "(" || ch == "[") { - var keyWord = ''; var indentTemp = stream.column(), letter; - /** - Either - (indent-word .. - (non-indent-word .. - (;something else, bracket, etc. - */ - - while ((letter = stream.eat(/[^\s\(\[\;\)\]]/)) != null) { - keyWord += letter; - } - - if (keyWord.length > 0 && indentKeys.propertyIsEnumerable(keyWord)) { // indent-word - - pushStack(state, indentTemp + INDENT_WORD_SKIP, ch); - } else { // non-indent word - // we continue eating the spaces - stream.eatSpace(); - if (stream.eol() || stream.peek() == ";") { - // nothing significant after - // we restart indentation 1 space after - pushStack(state, indentTemp + 1, ch); - } else { - pushStack(state, indentTemp + stream.current().length, ch); // else we match - } - } - stream.backUp(stream.current().length - 1); // undo all the eating - - if(typeof state.sExprComment == "number") state.sExprComment++; - - returnType = BRACKET; - } else if (ch == ")" || ch == "]") { - returnType = BRACKET; - if (state.indentStack != null && state.indentStack.type == (ch == ")" ? "(" : "[")) { - popStack(state); - - if(typeof state.sExprComment == "number"){ - if(--state.sExprComment == 0){ - returnType = COMMENT; // final closing bracket - state.sExprComment = false; // turn off s-expr commenting mode - } - } - } - } else { - stream.eatWhile(/[\w\$_\-!$%&*+\.\/:<=>?@\^~]/); - - if (keywords && keywords.propertyIsEnumerable(stream.current())) { - returnType = BUILTIN; - } else returnType = "variable"; - } - } - return (typeof state.sExprComment == "number") ? COMMENT : returnType; - }, - - indent: function (state) { - if (state.indentStack == null) return state.indentation; - return state.indentStack.indent; - }, - - closeBrackets: {pairs: "()[]{}\"\""}, - lineComment: ";;" - }; -}); - -CodeMirror.defineMIME("text/x-scheme", "scheme"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/shell/index.html b/backend/_pv_1_3_5/static/codemirror/mode/shell/index.html deleted file mode 100755 index 0b56300b1..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/shell/index.html +++ /dev/null @@ -1,66 +0,0 @@ - - -CodeMirror: Shell mode - - - - - - - - - - -
    -

    Shell mode

    - - - - - - -

    MIME types defined: text/x-sh.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/shell/shell.js b/backend/_pv_1_3_5/static/codemirror/mode/shell/shell.js deleted file mode 100755 index 570b4e241..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/shell/shell.js +++ /dev/null @@ -1,140 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode('shell', function() { - - var words = {}; - function define(style, string) { - var split = string.split(' '); - for(var i = 0; i < split.length; i++) { - words[split[i]] = style; - } - }; - - // Atoms - define('atom', 'true false'); - - // Keywords - define('keyword', 'if then do else elif while until for in esac fi fin ' + - 'fil done exit set unset export function'); - - // Commands - define('builtin', 'ab awk bash beep cat cc cd chown chmod chroot clear cp ' + - 'curl cut diff echo find gawk gcc get git grep kill killall ln ls make ' + - 'mkdir openssl mv nc node npm ping ps restart rm rmdir sed service sh ' + - 'shopt shred source sort sleep ssh start stop su sudo tee telnet top ' + - 'touch vi vim wall wc wget who write yes zsh'); - - function tokenBase(stream, state) { - if (stream.eatSpace()) return null; - - var sol = stream.sol(); - var ch = stream.next(); - - if (ch === '\\') { - stream.next(); - return null; - } - if (ch === '\'' || ch === '"' || ch === '`') { - state.tokens.unshift(tokenString(ch)); - return tokenize(stream, state); - } - if (ch === '#') { - if (sol && stream.eat('!')) { - stream.skipToEnd(); - return 'meta'; // 'comment'? - } - stream.skipToEnd(); - return 'comment'; - } - if (ch === '$') { - state.tokens.unshift(tokenDollar); - return tokenize(stream, state); - } - if (ch === '+' || ch === '=') { - return 'operator'; - } - if (ch === '-') { - stream.eat('-'); - stream.eatWhile(/\w/); - return 'attribute'; - } - if (/\d/.test(ch)) { - stream.eatWhile(/\d/); - if(stream.eol() || !/\w/.test(stream.peek())) { - return 'number'; - } - } - stream.eatWhile(/[\w-]/); - var cur = stream.current(); - if (stream.peek() === '=' && /\w+/.test(cur)) return 'def'; - return words.hasOwnProperty(cur) ? words[cur] : null; - } - - function tokenString(quote) { - return function(stream, state) { - var next, end = false, escaped = false; - while ((next = stream.next()) != null) { - if (next === quote && !escaped) { - end = true; - break; - } - if (next === '$' && !escaped && quote !== '\'') { - escaped = true; - stream.backUp(1); - state.tokens.unshift(tokenDollar); - break; - } - escaped = !escaped && next === '\\'; - } - if (end || !escaped) { - state.tokens.shift(); - } - return (quote === '`' || quote === ')' ? 'quote' : 'string'); - }; - }; - - var tokenDollar = function(stream, state) { - if (state.tokens.length > 1) stream.eat('$'); - var ch = stream.next(), hungry = /\w/; - if (ch === '{') hungry = /[^}]/; - if (ch === '(') { - state.tokens[0] = tokenString(')'); - return tokenize(stream, state); - } - if (!/\d/.test(ch)) { - stream.eatWhile(hungry); - stream.eat('}'); - } - state.tokens.shift(); - return 'def'; - }; - - function tokenize(stream, state) { - return (state.tokens[0] || tokenBase) (stream, state); - }; - - return { - startState: function() {return {tokens:[]};}, - token: function(stream, state) { - return tokenize(stream, state); - }, - closeBrackets: "()[]{}''\"\"``", - lineComment: '#', - fold: "brace" - }; -}); - -CodeMirror.defineMIME('text/x-sh', 'shell'); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/shell/test.js b/backend/_pv_1_3_5/static/codemirror/mode/shell/test.js deleted file mode 100755 index a413b5a40..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/shell/test.js +++ /dev/null @@ -1,58 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({}, "shell"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT("var", - "text [def $var] text"); - MT("varBraces", - "text[def ${var}]text"); - MT("varVar", - "text [def $a$b] text"); - MT("varBracesVarBraces", - "text[def ${a}${b}]text"); - - MT("singleQuotedVar", - "[string 'text $var text']"); - MT("singleQuotedVarBraces", - "[string 'text ${var} text']"); - - MT("doubleQuotedVar", - '[string "text ][def $var][string text"]'); - MT("doubleQuotedVarBraces", - '[string "text][def ${var}][string text"]'); - MT("doubleQuotedVarPunct", - '[string "text ][def $@][string text"]'); - MT("doubleQuotedVarVar", - '[string "][def $a$b][string "]'); - MT("doubleQuotedVarBracesVarBraces", - '[string "][def ${a}${b}][string "]'); - - MT("notAString", - "text\\'text"); - MT("escapes", - "outside\\'\\\"\\`\\\\[string \"inside\\`\\'\\\"\\\\`\\$notAVar\"]outside\\$\\(notASubShell\\)"); - - MT("subshell", - "[builtin echo] [quote $(whoami)] s log, stardate [quote `date`]."); - MT("doubleQuotedSubshell", - "[builtin echo] [string \"][quote $(whoami)][string 's log, stardate `date`.\"]"); - - MT("hashbang", - "[meta #!/bin/bash]"); - MT("comment", - "text [comment # Blurb]"); - - MT("numbers", - "[number 0] [number 1] [number 2]"); - MT("keywords", - "[keyword while] [atom true]; [keyword do]", - " [builtin sleep] [number 3]", - "[keyword done]"); - MT("options", - "[builtin ls] [attribute -l] [attribute --human-readable]"); - MT("operator", - "[def var][operator =]value"); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/sieve/index.html b/backend/_pv_1_3_5/static/codemirror/mode/sieve/index.html deleted file mode 100755 index 6f029b623..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/sieve/index.html +++ /dev/null @@ -1,93 +0,0 @@ - - -CodeMirror: Sieve (RFC5228) mode - - - - - - - - - -
    -

    Sieve (RFC5228) mode

    -
    - - -

    MIME types defined: application/sieve.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/sieve/sieve.js b/backend/_pv_1_3_5/static/codemirror/mode/sieve/sieve.js deleted file mode 100755 index f67db2f55..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/sieve/sieve.js +++ /dev/null @@ -1,193 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("sieve", function(config) { - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - var keywords = words("if elsif else stop require"); - var atoms = words("true false not"); - var indentUnit = config.indentUnit; - - function tokenBase(stream, state) { - - var ch = stream.next(); - if (ch == "/" && stream.eat("*")) { - state.tokenize = tokenCComment; - return tokenCComment(stream, state); - } - - if (ch === '#') { - stream.skipToEnd(); - return "comment"; - } - - if (ch == "\"") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - - if (ch == "(") { - state._indent.push("("); - // add virtual angel wings so that editor behaves... - // ...more sane incase of broken brackets - state._indent.push("{"); - return null; - } - - if (ch === "{") { - state._indent.push("{"); - return null; - } - - if (ch == ")") { - state._indent.pop(); - state._indent.pop(); - } - - if (ch === "}") { - state._indent.pop(); - return null; - } - - if (ch == ",") - return null; - - if (ch == ";") - return null; - - - if (/[{}\(\),;]/.test(ch)) - return null; - - // 1*DIGIT "K" / "M" / "G" - if (/\d/.test(ch)) { - stream.eatWhile(/[\d]/); - stream.eat(/[KkMmGg]/); - return "number"; - } - - // ":" (ALPHA / "_") *(ALPHA / DIGIT / "_") - if (ch == ":") { - stream.eatWhile(/[a-zA-Z_]/); - stream.eatWhile(/[a-zA-Z0-9_]/); - - return "operator"; - } - - stream.eatWhile(/\w/); - var cur = stream.current(); - - // "text:" *(SP / HTAB) (hash-comment / CRLF) - // *(multiline-literal / multiline-dotstart) - // "." CRLF - if ((cur == "text") && stream.eat(":")) - { - state.tokenize = tokenMultiLineString; - return "string"; - } - - if (keywords.propertyIsEnumerable(cur)) - return "keyword"; - - if (atoms.propertyIsEnumerable(cur)) - return "atom"; - - return null; - } - - function tokenMultiLineString(stream, state) - { - state._multiLineString = true; - // the first line is special it may contain a comment - if (!stream.sol()) { - stream.eatSpace(); - - if (stream.peek() == "#") { - stream.skipToEnd(); - return "comment"; - } - - stream.skipToEnd(); - return "string"; - } - - if ((stream.next() == ".") && (stream.eol())) - { - state._multiLineString = false; - state.tokenize = tokenBase; - } - - return "string"; - } - - function tokenCComment(stream, state) { - var maybeEnd = false, ch; - while ((ch = stream.next()) != null) { - if (maybeEnd && ch == "/") { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) - break; - escaped = !escaped && ch == "\\"; - } - if (!escaped) state.tokenize = tokenBase; - return "string"; - }; - } - - return { - startState: function(base) { - return {tokenize: tokenBase, - baseIndent: base || 0, - _indent: []}; - }, - - token: function(stream, state) { - if (stream.eatSpace()) - return null; - - return (state.tokenize || tokenBase)(stream, state);; - }, - - indent: function(state, _textAfter) { - var length = state._indent.length; - if (_textAfter && (_textAfter[0] == "}")) - length--; - - if (length <0) - length = 0; - - return length * indentUnit; - }, - - electricChars: "}" - }; -}); - -CodeMirror.defineMIME("application/sieve", "sieve"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/slim/index.html b/backend/_pv_1_3_5/static/codemirror/mode/slim/index.html deleted file mode 100755 index 7fa4e50df..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/slim/index.html +++ /dev/null @@ -1,96 +0,0 @@ - - -CodeMirror: SLIM mode - - - - - - - - - - - - - - - - - - - - -
    -

    SLIM mode

    -
    - - -

    MIME types defined: application/x-slim.

    - -

    - Parsing/Highlighting Tests: - normal, - verbose. -

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/slim/slim.js b/backend/_pv_1_3_5/static/codemirror/mode/slim/slim.js deleted file mode 100755 index 991a97efc..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/slim/slim.js +++ /dev/null @@ -1,575 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Slim Highlighting for CodeMirror copyright (c) HicknHack Software Gmbh - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), require("../ruby/ruby")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../htmlmixed/htmlmixed", "../ruby/ruby"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - - CodeMirror.defineMode("slim", function(config) { - var htmlMode = CodeMirror.getMode(config, {name: "htmlmixed"}); - var rubyMode = CodeMirror.getMode(config, "ruby"); - var modes = { html: htmlMode, ruby: rubyMode }; - var embedded = { - ruby: "ruby", - javascript: "javascript", - css: "text/css", - sass: "text/x-sass", - scss: "text/x-scss", - less: "text/x-less", - styl: "text/x-styl", // no highlighting so far - coffee: "coffeescript", - asciidoc: "text/x-asciidoc", - markdown: "text/x-markdown", - textile: "text/x-textile", // no highlighting so far - creole: "text/x-creole", // no highlighting so far - wiki: "text/x-wiki", // no highlighting so far - mediawiki: "text/x-mediawiki", // no highlighting so far - rdoc: "text/x-rdoc", // no highlighting so far - builder: "text/x-builder", // no highlighting so far - nokogiri: "text/x-nokogiri", // no highlighting so far - erb: "application/x-erb" - }; - var embeddedRegexp = function(map){ - var arr = []; - for(var key in map) arr.push(key); - return new RegExp("^("+arr.join('|')+"):"); - }(embedded); - - var styleMap = { - "commentLine": "comment", - "slimSwitch": "operator special", - "slimTag": "tag", - "slimId": "attribute def", - "slimClass": "attribute qualifier", - "slimAttribute": "attribute", - "slimSubmode": "keyword special", - "closeAttributeTag": null, - "slimDoctype": null, - "lineContinuation": null - }; - var closing = { - "{": "}", - "[": "]", - "(": ")" - }; - - var nameStartChar = "_a-zA-Z\xC0-\xD6\xD8-\xF6\xF8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD"; - var nameChar = nameStartChar + "\\-0-9\xB7\u0300-\u036F\u203F-\u2040"; - var nameRegexp = new RegExp("^[:"+nameStartChar+"](?::["+nameChar+"]|["+nameChar+"]*)"); - var attributeNameRegexp = new RegExp("^[:"+nameStartChar+"][:\\."+nameChar+"]*(?=\\s*=)"); - var wrappedAttributeNameRegexp = new RegExp("^[:"+nameStartChar+"][:\\."+nameChar+"]*"); - var classNameRegexp = /^\.-?[_a-zA-Z]+[\w\-]*/; - var classIdRegexp = /^#[_a-zA-Z]+[\w\-]*/; - - function backup(pos, tokenize, style) { - var restore = function(stream, state) { - state.tokenize = tokenize; - if (stream.pos < pos) { - stream.pos = pos; - return style; - } - return state.tokenize(stream, state); - }; - return function(stream, state) { - state.tokenize = restore; - return tokenize(stream, state); - }; - } - - function maybeBackup(stream, state, pat, offset, style) { - var cur = stream.current(); - var idx = cur.search(pat); - if (idx > -1) { - state.tokenize = backup(stream.pos, state.tokenize, style); - stream.backUp(cur.length - idx - offset); - } - return style; - } - - function continueLine(state, column) { - state.stack = { - parent: state.stack, - style: "continuation", - indented: column, - tokenize: state.line - }; - state.line = state.tokenize; - } - function finishContinue(state) { - if (state.line == state.tokenize) { - state.line = state.stack.tokenize; - state.stack = state.stack.parent; - } - } - - function lineContinuable(column, tokenize) { - return function(stream, state) { - finishContinue(state); - if (stream.match(/^\\$/)) { - continueLine(state, column); - return "lineContinuation"; - } - var style = tokenize(stream, state); - if (stream.eol() && stream.current().match(/(?:^|[^\\])(?:\\\\)*\\$/)) { - stream.backUp(1); - } - return style; - }; - } - function commaContinuable(column, tokenize) { - return function(stream, state) { - finishContinue(state); - var style = tokenize(stream, state); - if (stream.eol() && stream.current().match(/,$/)) { - continueLine(state, column); - } - return style; - }; - } - - function rubyInQuote(endQuote, tokenize) { - // TODO: add multi line support - return function(stream, state) { - var ch = stream.peek(); - if (ch == endQuote && state.rubyState.tokenize.length == 1) { - // step out of ruby context as it seems to complete processing all the braces - stream.next(); - state.tokenize = tokenize; - return "closeAttributeTag"; - } else { - return ruby(stream, state); - } - }; - } - function startRubySplat(tokenize) { - var rubyState; - var runSplat = function(stream, state) { - if (state.rubyState.tokenize.length == 1 && !state.rubyState.context.prev) { - stream.backUp(1); - if (stream.eatSpace()) { - state.rubyState = rubyState; - state.tokenize = tokenize; - return tokenize(stream, state); - } - stream.next(); - } - return ruby(stream, state); - }; - return function(stream, state) { - rubyState = state.rubyState; - state.rubyState = CodeMirror.startState(rubyMode); - state.tokenize = runSplat; - return ruby(stream, state); - }; - } - - function ruby(stream, state) { - return rubyMode.token(stream, state.rubyState); - } - - function htmlLine(stream, state) { - if (stream.match(/^\\$/)) { - return "lineContinuation"; - } - return html(stream, state); - } - function html(stream, state) { - if (stream.match(/^#\{/)) { - state.tokenize = rubyInQuote("}", state.tokenize); - return null; - } - return maybeBackup(stream, state, /[^\\]#\{/, 1, htmlMode.token(stream, state.htmlState)); - } - - function startHtmlLine(lastTokenize) { - return function(stream, state) { - var style = htmlLine(stream, state); - if (stream.eol()) state.tokenize = lastTokenize; - return style; - }; - } - - function startHtmlMode(stream, state, offset) { - state.stack = { - parent: state.stack, - style: "html", - indented: stream.column() + offset, // pipe + space - tokenize: state.line - }; - state.line = state.tokenize = html; - return null; - } - - function comment(stream, state) { - stream.skipToEnd(); - return state.stack.style; - } - - function commentMode(stream, state) { - state.stack = { - parent: state.stack, - style: "comment", - indented: state.indented + 1, - tokenize: state.line - }; - state.line = comment; - return comment(stream, state); - } - - function attributeWrapper(stream, state) { - if (stream.eat(state.stack.endQuote)) { - state.line = state.stack.line; - state.tokenize = state.stack.tokenize; - state.stack = state.stack.parent; - return null; - } - if (stream.match(wrappedAttributeNameRegexp)) { - state.tokenize = attributeWrapperAssign; - return "slimAttribute"; - } - stream.next(); - return null; - } - function attributeWrapperAssign(stream, state) { - if (stream.match(/^==?/)) { - state.tokenize = attributeWrapperValue; - return null; - } - return attributeWrapper(stream, state); - } - function attributeWrapperValue(stream, state) { - var ch = stream.peek(); - if (ch == '"' || ch == "\'") { - state.tokenize = readQuoted(ch, "string", true, false, attributeWrapper); - stream.next(); - return state.tokenize(stream, state); - } - if (ch == '[') { - return startRubySplat(attributeWrapper)(stream, state); - } - if (stream.match(/^(true|false|nil)\b/)) { - state.tokenize = attributeWrapper; - return "keyword"; - } - return startRubySplat(attributeWrapper)(stream, state); - } - - function startAttributeWrapperMode(state, endQuote, tokenize) { - state.stack = { - parent: state.stack, - style: "wrapper", - indented: state.indented + 1, - tokenize: tokenize, - line: state.line, - endQuote: endQuote - }; - state.line = state.tokenize = attributeWrapper; - return null; - } - - function sub(stream, state) { - if (stream.match(/^#\{/)) { - state.tokenize = rubyInQuote("}", state.tokenize); - return null; - } - var subStream = new CodeMirror.StringStream(stream.string.slice(state.stack.indented), stream.tabSize); - subStream.pos = stream.pos - state.stack.indented; - subStream.start = stream.start - state.stack.indented; - subStream.lastColumnPos = stream.lastColumnPos - state.stack.indented; - subStream.lastColumnValue = stream.lastColumnValue - state.stack.indented; - var style = state.subMode.token(subStream, state.subState); - stream.pos = subStream.pos + state.stack.indented; - return style; - } - function firstSub(stream, state) { - state.stack.indented = stream.column(); - state.line = state.tokenize = sub; - return state.tokenize(stream, state); - } - - function createMode(mode) { - var query = embedded[mode]; - var spec = CodeMirror.mimeModes[query]; - if (spec) { - return CodeMirror.getMode(config, spec); - } - var factory = CodeMirror.modes[query]; - if (factory) { - return factory(config, {name: query}); - } - return CodeMirror.getMode(config, "null"); - } - - function getMode(mode) { - if (!modes.hasOwnProperty(mode)) { - return modes[mode] = createMode(mode); - } - return modes[mode]; - } - - function startSubMode(mode, state) { - var subMode = getMode(mode); - var subState = CodeMirror.startState(subMode); - - state.subMode = subMode; - state.subState = subState; - - state.stack = { - parent: state.stack, - style: "sub", - indented: state.indented + 1, - tokenize: state.line - }; - state.line = state.tokenize = firstSub; - return "slimSubmode"; - } - - function doctypeLine(stream, _state) { - stream.skipToEnd(); - return "slimDoctype"; - } - - function startLine(stream, state) { - var ch = stream.peek(); - if (ch == '<') { - return (state.tokenize = startHtmlLine(state.tokenize))(stream, state); - } - if (stream.match(/^[|']/)) { - return startHtmlMode(stream, state, 1); - } - if (stream.match(/^\/(!|\[\w+])?/)) { - return commentMode(stream, state); - } - if (stream.match(/^(-|==?[<>]?)/)) { - state.tokenize = lineContinuable(stream.column(), commaContinuable(stream.column(), ruby)); - return "slimSwitch"; - } - if (stream.match(/^doctype\b/)) { - state.tokenize = doctypeLine; - return "keyword"; - } - - var m = stream.match(embeddedRegexp); - if (m) { - return startSubMode(m[1], state); - } - - return slimTag(stream, state); - } - - function slim(stream, state) { - if (state.startOfLine) { - return startLine(stream, state); - } - return slimTag(stream, state); - } - - function slimTag(stream, state) { - if (stream.eat('*')) { - state.tokenize = startRubySplat(slimTagExtras); - return null; - } - if (stream.match(nameRegexp)) { - state.tokenize = slimTagExtras; - return "slimTag"; - } - return slimClass(stream, state); - } - function slimTagExtras(stream, state) { - if (stream.match(/^(<>?|> state.indented && state.last != "slimSubmode") { - state.line = state.tokenize = state.stack.tokenize; - state.stack = state.stack.parent; - state.subMode = null; - state.subState = null; - } - } - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - state.startOfLine = false; - if (style) state.last = style; - return styleMap.hasOwnProperty(style) ? styleMap[style] : style; - }, - - blankLine: function(state) { - if (state.subMode && state.subMode.blankLine) { - return state.subMode.blankLine(state.subState); - } - }, - - innerMode: function(state) { - if (state.subMode) return {state: state.subState, mode: state.subMode}; - return {state: state, mode: mode}; - } - - //indent: function(state) { - // return state.indented; - //} - }; - return mode; - }, "htmlmixed", "ruby"); - - CodeMirror.defineMIME("text/x-slim", "slim"); - CodeMirror.defineMIME("application/x-slim", "slim"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/slim/test.js b/backend/_pv_1_3_5/static/codemirror/mode/slim/test.js deleted file mode 100755 index be4ddacb6..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/slim/test.js +++ /dev/null @@ -1,96 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Slim Highlighting for CodeMirror copyright (c) HicknHack Software Gmbh - -(function() { - var mode = CodeMirror.getMode({tabSize: 4, indentUnit: 2}, "slim"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - // Requires at least one media query - MT("elementName", - "[tag h1] Hey There"); - - MT("oneElementPerLine", - "[tag h1] Hey There .h2"); - - MT("idShortcut", - "[attribute&def #test] Hey There"); - - MT("tagWithIdShortcuts", - "[tag h1][attribute&def #test] Hey There"); - - MT("classShortcut", - "[attribute&qualifier .hello] Hey There"); - - MT("tagWithIdAndClassShortcuts", - "[tag h1][attribute&def #test][attribute&qualifier .hello] Hey There"); - - MT("docType", - "[keyword doctype] xml"); - - MT("comment", - "[comment / Hello WORLD]"); - - MT("notComment", - "[tag h1] This is not a / comment "); - - MT("attributes", - "[tag a]([attribute title]=[string \"test\"]) [attribute href]=[string \"link\"]}"); - - MT("multiLineAttributes", - "[tag a]([attribute title]=[string \"test\"]", - " ) [attribute href]=[string \"link\"]}"); - - MT("htmlCode", - "[tag&bracket <][tag h1][tag&bracket >]Title[tag&bracket ]"); - - MT("rubyBlock", - "[operator&special =][variable-2 @item]"); - - MT("selectorRubyBlock", - "[tag a][attribute&qualifier .test][operator&special =] [variable-2 @item]"); - - MT("nestedRubyBlock", - "[tag a]", - " [operator&special =][variable puts] [string \"test\"]"); - - MT("multilinePlaintext", - "[tag p]", - " | Hello,", - " World"); - - MT("multilineRuby", - "[tag p]", - " [comment /# this is a comment]", - " [comment and this is a comment too]", - " | Date/Time", - " [operator&special -] [variable now] [operator =] [tag DateTime][operator .][property now]", - " [tag strong][operator&special =] [variable now]", - " [operator&special -] [keyword if] [variable now] [operator >] [tag DateTime][operator .][property parse]([string \"December 31, 2006\"])", - " [operator&special =][string \"Happy\"]", - " [operator&special =][string \"Belated\"]", - " [operator&special =][string \"Birthday\"]"); - - MT("multilineComment", - "[comment /]", - " [comment Multiline]", - " [comment Comment]"); - - MT("hamlAfterRubyTag", - "[attribute&qualifier .block]", - " [tag strong][operator&special =] [variable now]", - " [attribute&qualifier .test]", - " [operator&special =][variable now]", - " [attribute&qualifier .right]"); - - MT("stretchedRuby", - "[operator&special =] [variable puts] [string \"Hello\"],", - " [string \"World\"]"); - - MT("interpolationInHashAttribute", - "[tag div]{[attribute id] = [string \"]#{[variable test]}[string _]#{[variable ting]}[string \"]} test"); - - MT("interpolationInHTMLAttribute", - "[tag div]([attribute title]=[string \"]#{[variable test]}[string _]#{[variable ting]()}[string \"]) Test"); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/smalltalk/index.html b/backend/_pv_1_3_5/static/codemirror/mode/smalltalk/index.html deleted file mode 100755 index 2155ebc2a..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/smalltalk/index.html +++ /dev/null @@ -1,68 +0,0 @@ - - -CodeMirror: Smalltalk mode - - - - - - - - - - -
    -

    Smalltalk mode

    -
    - - - -

    Simple Smalltalk mode.

    - -

    MIME types defined: text/x-stsrc.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/smalltalk/smalltalk.js b/backend/_pv_1_3_5/static/codemirror/mode/smalltalk/smalltalk.js deleted file mode 100755 index bb510ba2e..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/smalltalk/smalltalk.js +++ /dev/null @@ -1,168 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode('smalltalk', function(config) { - - var specialChars = /[+\-\/\\*~<>=@%|&?!.,:;^]/; - var keywords = /true|false|nil|self|super|thisContext/; - - var Context = function(tokenizer, parent) { - this.next = tokenizer; - this.parent = parent; - }; - - var Token = function(name, context, eos) { - this.name = name; - this.context = context; - this.eos = eos; - }; - - var State = function() { - this.context = new Context(next, null); - this.expectVariable = true; - this.indentation = 0; - this.userIndentationDelta = 0; - }; - - State.prototype.userIndent = function(indentation) { - this.userIndentationDelta = indentation > 0 ? (indentation / config.indentUnit - this.indentation) : 0; - }; - - var next = function(stream, context, state) { - var token = new Token(null, context, false); - var aChar = stream.next(); - - if (aChar === '"') { - token = nextComment(stream, new Context(nextComment, context)); - - } else if (aChar === '\'') { - token = nextString(stream, new Context(nextString, context)); - - } else if (aChar === '#') { - if (stream.peek() === '\'') { - stream.next(); - token = nextSymbol(stream, new Context(nextSymbol, context)); - } else { - if (stream.eatWhile(/[^\s.{}\[\]()]/)) - token.name = 'string-2'; - else - token.name = 'meta'; - } - - } else if (aChar === '$') { - if (stream.next() === '<') { - stream.eatWhile(/[^\s>]/); - stream.next(); - } - token.name = 'string-2'; - - } else if (aChar === '|' && state.expectVariable) { - token.context = new Context(nextTemporaries, context); - - } else if (/[\[\]{}()]/.test(aChar)) { - token.name = 'bracket'; - token.eos = /[\[{(]/.test(aChar); - - if (aChar === '[') { - state.indentation++; - } else if (aChar === ']') { - state.indentation = Math.max(0, state.indentation - 1); - } - - } else if (specialChars.test(aChar)) { - stream.eatWhile(specialChars); - token.name = 'operator'; - token.eos = aChar !== ';'; // ; cascaded message expression - - } else if (/\d/.test(aChar)) { - stream.eatWhile(/[\w\d]/); - token.name = 'number'; - - } else if (/[\w_]/.test(aChar)) { - stream.eatWhile(/[\w\d_]/); - token.name = state.expectVariable ? (keywords.test(stream.current()) ? 'keyword' : 'variable') : null; - - } else { - token.eos = state.expectVariable; - } - - return token; - }; - - var nextComment = function(stream, context) { - stream.eatWhile(/[^"]/); - return new Token('comment', stream.eat('"') ? context.parent : context, true); - }; - - var nextString = function(stream, context) { - stream.eatWhile(/[^']/); - return new Token('string', stream.eat('\'') ? context.parent : context, false); - }; - - var nextSymbol = function(stream, context) { - stream.eatWhile(/[^']/); - return new Token('string-2', stream.eat('\'') ? context.parent : context, false); - }; - - var nextTemporaries = function(stream, context) { - var token = new Token(null, context, false); - var aChar = stream.next(); - - if (aChar === '|') { - token.context = context.parent; - token.eos = true; - - } else { - stream.eatWhile(/[^|]/); - token.name = 'variable'; - } - - return token; - }; - - return { - startState: function() { - return new State; - }, - - token: function(stream, state) { - state.userIndent(stream.indentation()); - - if (stream.eatSpace()) { - return null; - } - - var token = state.context.next(stream, state.context, state); - state.context = token.context; - state.expectVariable = token.eos; - - return token.name; - }, - - blankLine: function(state) { - state.userIndent(0); - }, - - indent: function(state, textAfter) { - var i = state.context.next === next && textAfter && textAfter.charAt(0) === ']' ? -1 : state.userIndentationDelta; - return (state.indentation + i) * config.indentUnit; - }, - - electricChars: ']' - }; - -}); - -CodeMirror.defineMIME('text/x-stsrc', {name: 'smalltalk'}); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/smarty/index.html b/backend/_pv_1_3_5/static/codemirror/mode/smarty/index.html deleted file mode 100755 index b19c8f09b..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/smarty/index.html +++ /dev/null @@ -1,138 +0,0 @@ - - -CodeMirror: Smarty mode - - - - - - - - - - -
    -

    Smarty mode

    -
    - -

    Mode for Smarty version 2 or 3, which allows for custom delimiter tags.

    - -

    Several configuration parameters are supported:

    - -
      -
    • leftDelimiter and rightDelimiter, - which should be strings that determine where the Smarty syntax - starts and ends.
    • -
    • version, which should be 2 or 3.
    • -
    • baseMode, which can be a mode spec - like "text/html" to set a different background mode.
    • -
    - -

    MIME types defined: text/x-smarty

    - -

    Smarty 2, custom delimiters

    - -
    - -

    Smarty 3

    - - - - - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/smarty/smarty.js b/backend/_pv_1_3_5/static/codemirror/mode/smarty/smarty.js deleted file mode 100755 index 6e0fbed42..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/smarty/smarty.js +++ /dev/null @@ -1,225 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/** - * Smarty 2 and 3 mode. - */ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("smarty", function(config, parserConf) { - var rightDelimiter = parserConf.rightDelimiter || "}"; - var leftDelimiter = parserConf.leftDelimiter || "{"; - var version = parserConf.version || 2; - var baseMode = CodeMirror.getMode(config, parserConf.baseMode || "null"); - - var keyFunctions = ["debug", "extends", "function", "include", "literal"]; - var regs = { - operatorChars: /[+\-*&%=<>!?]/, - validIdentifier: /[a-zA-Z0-9_]/, - stringChar: /['"]/ - }; - - var last; - function cont(style, lastType) { - last = lastType; - return style; - } - - function chain(stream, state, parser) { - state.tokenize = parser; - return parser(stream, state); - } - - // Smarty 3 allows { and } surrounded by whitespace to NOT slip into Smarty mode - function doesNotCount(stream, pos) { - if (pos == null) pos = stream.pos; - return version === 3 && leftDelimiter == "{" && - (pos == stream.string.length || /\s/.test(stream.string.charAt(pos))); - } - - function tokenTop(stream, state) { - var string = stream.string; - for (var scan = stream.pos;;) { - var nextMatch = string.indexOf(leftDelimiter, scan); - scan = nextMatch + leftDelimiter.length; - if (nextMatch == -1 || !doesNotCount(stream, nextMatch + leftDelimiter.length)) break; - } - if (nextMatch == stream.pos) { - stream.match(leftDelimiter); - if (stream.eat("*")) { - return chain(stream, state, tokenBlock("comment", "*" + rightDelimiter)); - } else { - state.depth++; - state.tokenize = tokenSmarty; - last = "startTag"; - return "tag"; - } - } - - if (nextMatch > -1) stream.string = string.slice(0, nextMatch); - var token = baseMode.token(stream, state.base); - if (nextMatch > -1) stream.string = string; - return token; - } - - // parsing Smarty content - function tokenSmarty(stream, state) { - if (stream.match(rightDelimiter, true)) { - if (version === 3) { - state.depth--; - if (state.depth <= 0) { - state.tokenize = tokenTop; - } - } else { - state.tokenize = tokenTop; - } - return cont("tag", null); - } - - if (stream.match(leftDelimiter, true)) { - state.depth++; - return cont("tag", "startTag"); - } - - var ch = stream.next(); - if (ch == "$") { - stream.eatWhile(regs.validIdentifier); - return cont("variable-2", "variable"); - } else if (ch == "|") { - return cont("operator", "pipe"); - } else if (ch == ".") { - return cont("operator", "property"); - } else if (regs.stringChar.test(ch)) { - state.tokenize = tokenAttribute(ch); - return cont("string", "string"); - } else if (regs.operatorChars.test(ch)) { - stream.eatWhile(regs.operatorChars); - return cont("operator", "operator"); - } else if (ch == "[" || ch == "]") { - return cont("bracket", "bracket"); - } else if (ch == "(" || ch == ")") { - return cont("bracket", "operator"); - } else if (/\d/.test(ch)) { - stream.eatWhile(/\d/); - return cont("number", "number"); - } else { - - if (state.last == "variable") { - if (ch == "@") { - stream.eatWhile(regs.validIdentifier); - return cont("property", "property"); - } else if (ch == "|") { - stream.eatWhile(regs.validIdentifier); - return cont("qualifier", "modifier"); - } - } else if (state.last == "pipe") { - stream.eatWhile(regs.validIdentifier); - return cont("qualifier", "modifier"); - } else if (state.last == "whitespace") { - stream.eatWhile(regs.validIdentifier); - return cont("attribute", "modifier"); - } if (state.last == "property") { - stream.eatWhile(regs.validIdentifier); - return cont("property", null); - } else if (/\s/.test(ch)) { - last = "whitespace"; - return null; - } - - var str = ""; - if (ch != "/") { - str += ch; - } - var c = null; - while (c = stream.eat(regs.validIdentifier)) { - str += c; - } - for (var i=0, j=keyFunctions.length; i - -CodeMirror: Solr mode - - - - - - - - - -
    -

    Solr mode

    - -
    - -
    - - - -

    MIME types defined: text/x-solr.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/solr/solr.js b/backend/_pv_1_3_5/static/codemirror/mode/solr/solr.js deleted file mode 100755 index f7f708789..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/solr/solr.js +++ /dev/null @@ -1,104 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("solr", function() { - "use strict"; - - var isStringChar = /[^\s\|\!\+\-\*\?\~\^\&\:\(\)\[\]\{\}\^\"\\]/; - var isOperatorChar = /[\|\!\+\-\*\?\~\^\&]/; - var isOperatorString = /^(OR|AND|NOT|TO)$/i; - - function isNumber(word) { - return parseFloat(word, 10).toString() === word; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) break; - escaped = !escaped && next == "\\"; - } - - if (!escaped) state.tokenize = tokenBase; - return "string"; - }; - } - - function tokenOperator(operator) { - return function(stream, state) { - var style = "operator"; - if (operator == "+") - style += " positive"; - else if (operator == "-") - style += " negative"; - else if (operator == "|") - stream.eat(/\|/); - else if (operator == "&") - stream.eat(/\&/); - else if (operator == "^") - style += " boost"; - - state.tokenize = tokenBase; - return style; - }; - } - - function tokenWord(ch) { - return function(stream, state) { - var word = ch; - while ((ch = stream.peek()) && ch.match(isStringChar) != null) { - word += stream.next(); - } - - state.tokenize = tokenBase; - if (isOperatorString.test(word)) - return "operator"; - else if (isNumber(word)) - return "number"; - else if (stream.peek() == ":") - return "field"; - else - return "string"; - }; - } - - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"') - state.tokenize = tokenString(ch); - else if (isOperatorChar.test(ch)) - state.tokenize = tokenOperator(ch); - else if (isStringChar.test(ch)) - state.tokenize = tokenWord(ch); - - return (state.tokenize != tokenBase) ? state.tokenize(stream, state) : null; - } - - return { - startState: function() { - return { - tokenize: tokenBase - }; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - return state.tokenize(stream, state); - } - }; -}); - -CodeMirror.defineMIME("text/x-solr", "solr"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/soy/index.html b/backend/_pv_1_3_5/static/codemirror/mode/soy/index.html deleted file mode 100755 index f0216f097..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/soy/index.html +++ /dev/null @@ -1,68 +0,0 @@ - - -CodeMirror: Soy (Closure Template) mode - - - - - - - - - - - - - - -
    -

    Soy (Closure Template) mode

    -
    - - - -

    A mode for Closure Templates (Soy).

    -

    MIME type defined: text/x-soy.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/soy/soy.js b/backend/_pv_1_3_5/static/codemirror/mode/soy/soy.js deleted file mode 100755 index b9eec59a4..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/soy/soy.js +++ /dev/null @@ -1,303 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../htmlmixed/htmlmixed"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - var indentingTags = ["template", "literal", "msg", "fallbackmsg", "let", "if", "elseif", - "else", "switch", "case", "default", "foreach", "ifempty", "for", - "call", "param", "deltemplate", "delcall", "log"]; - - CodeMirror.defineMode("soy", function(config) { - var textMode = CodeMirror.getMode(config, "text/plain"); - var modes = { - html: CodeMirror.getMode(config, {name: "text/html", multilineTagIndentFactor: 2, multilineTagIndentPastTag: false}), - attributes: textMode, - text: textMode, - uri: textMode, - css: CodeMirror.getMode(config, "text/css"), - js: CodeMirror.getMode(config, {name: "text/javascript", statementIndent: 2 * config.indentUnit}) - }; - - function last(array) { - return array[array.length - 1]; - } - - function tokenUntil(stream, state, untilRegExp) { - var oldString = stream.string; - var match = untilRegExp.exec(oldString.substr(stream.pos)); - if (match) { - // We don't use backUp because it backs up just the position, not the state. - // This uses an undocumented API. - stream.string = oldString.substr(0, stream.pos + match.index); - } - var result = stream.hideFirstChars(state.indent, function() { - return state.localMode.token(stream, state.localState); - }); - stream.string = oldString; - return result; - } - - function contains(list, element) { - while (list) { - if (list.element === element) return true; - list = list.next; - } - return false; - } - - function prepend(list, element) { - return { - element: element, - next: list - }; - } - - // Reference a variable `name` in `list`. - // Let `loose` be truthy to ignore missing identifiers. - function ref(list, name, loose) { - return contains(list, name) ? "variable-2" : (loose ? "variable" : "variable-2 error"); - } - - function popscope(state) { - if (state.scopes) { - state.variables = state.scopes.element; - state.scopes = state.scopes.next; - } - } - - return { - startState: function() { - return { - kind: [], - kindTag: [], - soyState: [], - templates: null, - variables: null, - scopes: null, - indent: 0, - localMode: modes.html, - localState: CodeMirror.startState(modes.html) - }; - }, - - copyState: function(state) { - return { - tag: state.tag, // Last seen Soy tag. - kind: state.kind.concat([]), // Values of kind="" attributes. - kindTag: state.kindTag.concat([]), // Opened tags with kind="" attributes. - soyState: state.soyState.concat([]), - templates: state.templates, - variables: state.variables, - scopes: state.scopes, - indent: state.indent, // Indentation of the following line. - localMode: state.localMode, - localState: CodeMirror.copyState(state.localMode, state.localState) - }; - }, - - token: function(stream, state) { - var match; - - switch (last(state.soyState)) { - case "comment": - if (stream.match(/^.*?\*\//)) { - state.soyState.pop(); - } else { - stream.skipToEnd(); - } - return "comment"; - - case "templ-def": - if (match = stream.match(/^\.?([\w]+(?!\.[\w]+)*)/)) { - state.templates = prepend(state.templates, match[1]); - state.scopes = prepend(state.scopes, state.variables); - state.soyState.pop(); - return "def"; - } - stream.next(); - return null; - - case "templ-ref": - if (match = stream.match(/^\.?([\w]+)/)) { - state.soyState.pop(); - // If the first character is '.', try to match against a local template name. - if (match[0][0] == '.') { - return ref(state.templates, match[1], true); - } - // Otherwise - return "variable"; - } - stream.next(); - return null; - - case "param-def": - if (match = stream.match(/^([\w]+)(?=:)/)) { - state.variables = prepend(state.variables, match[1]); - state.soyState.pop(); - state.soyState.push("param-type"); - return "def"; - } - stream.next(); - return null; - - case "param-type": - if (stream.peek() == "}") { - state.soyState.pop(); - return null; - } - if (stream.eatWhile(/^[\w]+/)) { - return "variable-3"; - } - stream.next(); - return null; - - case "var-def": - if (match = stream.match(/^\$([\w]+)/)) { - state.variables = prepend(state.variables, match[1]); - state.soyState.pop(); - return "def"; - } - stream.next(); - return null; - - case "tag": - if (stream.match(/^\/?}/)) { - if (state.tag == "/template" || state.tag == "/deltemplate") { - popscope(state); - state.indent = 0; - } else { - if (state.tag == "/for" || state.tag == "/foreach") { - popscope(state); - } - state.indent -= config.indentUnit * - (stream.current() == "/}" || indentingTags.indexOf(state.tag) == -1 ? 2 : 1); - } - state.soyState.pop(); - return "keyword"; - } else if (stream.match(/^([\w?]+)(?==)/)) { - if (stream.current() == "kind" && (match = stream.match(/^="([^"]+)/, false))) { - var kind = match[1]; - state.kind.push(kind); - state.kindTag.push(state.tag); - state.localMode = modes[kind] || modes.html; - state.localState = CodeMirror.startState(state.localMode); - } - return "attribute"; - } else if (stream.match(/^"/)) { - state.soyState.push("string"); - return "string"; - } - if (match = stream.match(/^\$([\w]+)/)) { - return ref(state.variables, match[1]); - } - if (match = stream.match(/^\w+/)) { - return /^(?:as|and|or|not|in)$/.test(match[0]) ? "keyword" : null; - } - stream.next(); - return null; - - case "literal": - if (stream.match(/^(?=\{\/literal})/)) { - state.indent -= config.indentUnit; - state.soyState.pop(); - return this.token(stream, state); - } - return tokenUntil(stream, state, /\{\/literal}/); - - case "string": - var match = stream.match(/^.*?("|\\[\s\S])/); - if (!match) { - stream.skipToEnd(); - } else if (match[1] == "\"") { - state.soyState.pop(); - } - return "string"; - } - - if (stream.match(/^\/\*/)) { - state.soyState.push("comment"); - return "comment"; - } else if (stream.match(stream.sol() ? /^\s*\/\/.*/ : /^\s+\/\/.*/)) { - return "comment"; - } else if (stream.match(/^\{literal}/)) { - state.indent += config.indentUnit; - state.soyState.push("literal"); - return "keyword"; - } else if (match = stream.match(/^\{([\/@\\]?[\w?]*)/)) { - if (match[1] != "/switch") - state.indent += (/^(\/|(else|elseif|ifempty|case|default)$)/.test(match[1]) && state.tag != "switch" ? 1 : 2) * config.indentUnit; - state.tag = match[1]; - if (state.tag == "/" + last(state.kindTag)) { - // We found the tag that opened the current kind="". - state.kind.pop(); - state.kindTag.pop(); - state.localMode = modes[last(state.kind)] || modes.html; - state.localState = CodeMirror.startState(state.localMode); - } - state.soyState.push("tag"); - if (state.tag == "template" || state.tag == "deltemplate") { - state.soyState.push("templ-def"); - } - if (state.tag == "call" || state.tag == "delcall") { - state.soyState.push("templ-ref"); - } - if (state.tag == "let") { - state.soyState.push("var-def"); - } - if (state.tag == "for" || state.tag == "foreach") { - state.scopes = prepend(state.scopes, state.variables); - state.soyState.push("var-def"); - } - if (state.tag.match(/^@param\??/)) { - state.soyState.push("param-def"); - } - return "keyword"; - } - - return tokenUntil(stream, state, /\{|\s+\/\/|\/\*/); - }, - - indent: function(state, textAfter) { - var indent = state.indent, top = last(state.soyState); - if (top == "comment") return CodeMirror.Pass; - - if (top == "literal") { - if (/^\{\/literal}/.test(textAfter)) indent -= config.indentUnit; - } else { - if (/^\s*\{\/(template|deltemplate)\b/.test(textAfter)) return 0; - if (/^\{(\/|(fallbackmsg|elseif|else|ifempty)\b)/.test(textAfter)) indent -= config.indentUnit; - if (state.tag != "switch" && /^\{(case|default)\b/.test(textAfter)) indent -= config.indentUnit; - if (/^\{\/switch\b/.test(textAfter)) indent -= config.indentUnit; - } - if (indent && state.localMode.indent) - indent += state.localMode.indent(state.localState, textAfter); - return indent; - }, - - innerMode: function(state) { - if (state.soyState.length && last(state.soyState) != "literal") return null; - else return {state: state.localState, mode: state.localMode}; - }, - - electricInput: /^\s*\{(\/|\/template|\/deltemplate|\/switch|fallbackmsg|elseif|else|case|default|ifempty|\/literal\})$/, - lineComment: "//", - blockCommentStart: "/*", - blockCommentEnd: "*/", - blockCommentContinue: " * ", - fold: "indent" - }; - }, "htmlmixed"); - - CodeMirror.registerHelper("hintWords", "soy", indentingTags.concat( - ["delpackage", "namespace", "alias", "print", "css", "debugger"])); - - CodeMirror.defineMIME("text/x-soy", "soy"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/soy/test.js b/backend/_pv_1_3_5/static/codemirror/mode/soy/test.js deleted file mode 100755 index 9e265c1b0..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/soy/test.js +++ /dev/null @@ -1,83 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "soy"); - function MT(name) {test.mode(name, mode, Array.prototype.slice.call(arguments, 1));} - - // Test of small keywords and words containing them. - MT('keywords-test', - '[keyword {] [keyword as] worrying [keyword and] notorious [keyword as]', - ' the Fandor-alias assassin, [keyword or]', - ' Corcand cannot fit [keyword in] [keyword }]'); - - MT('let-test', - '[keyword {template] [def .name][keyword }]', - ' [keyword {let] [def $name]: [string "world"][keyword /}]', - ' [tag&bracket <][tag h1][tag&bracket >]', - ' Hello, [keyword {][variable-2 $name][keyword }]', - ' [tag&bracket ]', - '[keyword {/template}]', - ''); - - MT('param-type-test', - '[keyword {@param] [def a]: ' + - '[variable-3 list]<[[[variable-3 a]: [variable-3 int], ' + - '[variable-3 b]: [variable-3 map]<[variable-3 string], ' + - '[variable-3 bool]>]]>][keyword }]'); - - MT('undefined-var', - '[keyword {][variable-2&error $var]'); - - MT('param-scope-test', - '[keyword {template] [def .a][keyword }]', - ' [keyword {@param] [def x]: [variable-3 string][keyword }]', - ' [keyword {][variable-2 $x][keyword }]', - '[keyword {/template}]', - '', - '[keyword {template] [def .b][keyword }]', - ' [keyword {][variable-2&error $x][keyword }]', - '[keyword {/template}]', - ''); - - MT('if-variable-test', - '[keyword {if] [variable-2&error $showThing][keyword }]', - ' Yo!', - '[keyword {/if}]', - ''); - - MT('defined-if-variable-test', - '[keyword {template] [def .foo][keyword }]', - ' [keyword {@param?] [def showThing]: [variable-3 bool][keyword }]', - ' [keyword {if] [variable-2 $showThing][keyword }]', - ' Yo!', - ' [keyword {/if}]', - '[keyword {/template}]', - ''); - - MT('template-calls-test', - '[keyword {template] [def .foo][keyword }]', - ' Yo!', - '[keyword {/template}]', - '[keyword {call] [variable-2 .foo][keyword /}]', - '[keyword {call] [variable foo][keyword /}]', - '[keyword {call] [variable .bar][keyword /}]', - '[keyword {call] [variable bar][keyword /}]', - ''); - - MT('foreach-scope-test', - '[keyword {@param] [def bar]: [variable-3 string][keyword }]', - '[keyword {foreach] [def $foo] [keyword in] [variable-2&error $foos][keyword }]', - ' [keyword {][variable-2 $foo][keyword }]', - '[keyword {/foreach}]', - '[keyword {][variable-2&error $foo][keyword }]', - '[keyword {][variable-2 $bar][keyword }]'); - - MT('foreach-ifempty-indent-test', - '[keyword {foreach] [def $foo] [keyword in] [variable-2&error $foos][keyword }]', - ' something', - '[keyword {ifempty}]', - ' nothing', - '[keyword {/foreach}]', - ''); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/sparql/index.html b/backend/_pv_1_3_5/static/codemirror/mode/sparql/index.html deleted file mode 100755 index 84ef4d363..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/sparql/index.html +++ /dev/null @@ -1,61 +0,0 @@ - - -CodeMirror: SPARQL mode - - - - - - - - - - -
    -

    SPARQL mode

    -
    - - -

    MIME types defined: application/sparql-query.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/sparql/sparql.js b/backend/_pv_1_3_5/static/codemirror/mode/sparql/sparql.js deleted file mode 100755 index 095dcca65..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/sparql/sparql.js +++ /dev/null @@ -1,180 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("sparql", function(config) { - var indentUnit = config.indentUnit; - var curPunc; - - function wordRegexp(words) { - return new RegExp("^(?:" + words.join("|") + ")$", "i"); - } - var ops = wordRegexp(["str", "lang", "langmatches", "datatype", "bound", "sameterm", "isiri", "isuri", - "iri", "uri", "bnode", "count", "sum", "min", "max", "avg", "sample", - "group_concat", "rand", "abs", "ceil", "floor", "round", "concat", "substr", "strlen", - "replace", "ucase", "lcase", "encode_for_uri", "contains", "strstarts", "strends", - "strbefore", "strafter", "year", "month", "day", "hours", "minutes", "seconds", - "timezone", "tz", "now", "uuid", "struuid", "md5", "sha1", "sha256", "sha384", - "sha512", "coalesce", "if", "strlang", "strdt", "isnumeric", "regex", "exists", - "isblank", "isliteral", "a", "bind"]); - var keywords = wordRegexp(["base", "prefix", "select", "distinct", "reduced", "construct", "describe", - "ask", "from", "named", "where", "order", "limit", "offset", "filter", "optional", - "graph", "by", "asc", "desc", "as", "having", "undef", "values", "group", - "minus", "in", "not", "service", "silent", "using", "insert", "delete", "union", - "true", "false", "with", - "data", "copy", "to", "move", "add", "create", "drop", "clear", "load"]); - var operatorChars = /[*+\-<>=&|\^\/!\?]/; - - function tokenBase(stream, state) { - var ch = stream.next(); - curPunc = null; - if (ch == "$" || ch == "?") { - if(ch == "?" && stream.match(/\s/, false)){ - return "operator"; - } - stream.match(/^[\w\d]*/); - return "variable-2"; - } - else if (ch == "<" && !stream.match(/^[\s\u00a0=]/, false)) { - stream.match(/^[^\s\u00a0>]*>?/); - return "atom"; - } - else if (ch == "\"" || ch == "'") { - state.tokenize = tokenLiteral(ch); - return state.tokenize(stream, state); - } - else if (/[{}\(\),\.;\[\]]/.test(ch)) { - curPunc = ch; - return "bracket"; - } - else if (ch == "#") { - stream.skipToEnd(); - return "comment"; - } - else if (operatorChars.test(ch)) { - stream.eatWhile(operatorChars); - return "operator"; - } - else if (ch == ":") { - stream.eatWhile(/[\w\d\._\-]/); - return "atom"; - } - else if (ch == "@") { - stream.eatWhile(/[a-z\d\-]/i); - return "meta"; - } - else { - stream.eatWhile(/[_\w\d]/); - if (stream.eat(":")) { - stream.eatWhile(/[\w\d_\-]/); - return "atom"; - } - var word = stream.current(); - if (ops.test(word)) - return "builtin"; - else if (keywords.test(word)) - return "keyword"; - else - return "variable"; - } - } - - function tokenLiteral(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) { - state.tokenize = tokenBase; - break; - } - escaped = !escaped && ch == "\\"; - } - return "string"; - }; - } - - function pushContext(state, type, col) { - state.context = {prev: state.context, indent: state.indent, col: col, type: type}; - } - function popContext(state) { - state.indent = state.context.indent; - state.context = state.context.prev; - } - - return { - startState: function() { - return {tokenize: tokenBase, - context: null, - indent: 0, - col: 0}; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (state.context && state.context.align == null) state.context.align = false; - state.indent = stream.indentation(); - } - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - - if (style != "comment" && state.context && state.context.align == null && state.context.type != "pattern") { - state.context.align = true; - } - - if (curPunc == "(") pushContext(state, ")", stream.column()); - else if (curPunc == "[") pushContext(state, "]", stream.column()); - else if (curPunc == "{") pushContext(state, "}", stream.column()); - else if (/[\]\}\)]/.test(curPunc)) { - while (state.context && state.context.type == "pattern") popContext(state); - if (state.context && curPunc == state.context.type) { - popContext(state); - if (curPunc == "}" && state.context && state.context.type == "pattern") - popContext(state); - } - } - else if (curPunc == "." && state.context && state.context.type == "pattern") popContext(state); - else if (/atom|string|variable/.test(style) && state.context) { - if (/[\}\]]/.test(state.context.type)) - pushContext(state, "pattern", stream.column()); - else if (state.context.type == "pattern" && !state.context.align) { - state.context.align = true; - state.context.col = stream.column(); - } - } - - return style; - }, - - indent: function(state, textAfter) { - var firstChar = textAfter && textAfter.charAt(0); - var context = state.context; - if (/[\]\}]/.test(firstChar)) - while (context && context.type == "pattern") context = context.prev; - - var closing = context && firstChar == context.type; - if (!context) - return 0; - else if (context.type == "pattern") - return context.col; - else if (context.align) - return context.col + (closing ? 0 : 1); - else - return context.indent + (closing ? 0 : indentUnit); - }, - - lineComment: "#" - }; -}); - -CodeMirror.defineMIME("application/sparql-query", "sparql"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/spreadsheet/index.html b/backend/_pv_1_3_5/static/codemirror/mode/spreadsheet/index.html deleted file mode 100755 index a52f76f05..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/spreadsheet/index.html +++ /dev/null @@ -1,42 +0,0 @@ - - -CodeMirror: Spreadsheet mode - - - - - - - - - - -
    -

    Spreadsheet mode

    -
    - - - -

    MIME types defined: text/x-spreadsheet.

    - -

    The Spreadsheet Mode

    -

    Created by Robert Plummer

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/spreadsheet/spreadsheet.js b/backend/_pv_1_3_5/static/codemirror/mode/spreadsheet/spreadsheet.js deleted file mode 100755 index 222f29766..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/spreadsheet/spreadsheet.js +++ /dev/null @@ -1,112 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("spreadsheet", function () { - return { - startState: function () { - return { - stringType: null, - stack: [] - }; - }, - token: function (stream, state) { - if (!stream) return; - - //check for state changes - if (state.stack.length === 0) { - //strings - if ((stream.peek() == '"') || (stream.peek() == "'")) { - state.stringType = stream.peek(); - stream.next(); // Skip quote - state.stack.unshift("string"); - } - } - - //return state - //stack has - switch (state.stack[0]) { - case "string": - while (state.stack[0] === "string" && !stream.eol()) { - if (stream.peek() === state.stringType) { - stream.next(); // Skip quote - state.stack.shift(); // Clear flag - } else if (stream.peek() === "\\") { - stream.next(); - stream.next(); - } else { - stream.match(/^.[^\\\"\']*/); - } - } - return "string"; - - case "characterClass": - while (state.stack[0] === "characterClass" && !stream.eol()) { - if (!(stream.match(/^[^\]\\]+/) || stream.match(/^\\./))) - state.stack.shift(); - } - return "operator"; - } - - var peek = stream.peek(); - - //no stack - switch (peek) { - case "[": - stream.next(); - state.stack.unshift("characterClass"); - return "bracket"; - case ":": - stream.next(); - return "operator"; - case "\\": - if (stream.match(/\\[a-z]+/)) return "string-2"; - else { - stream.next(); - return "atom"; - } - case ".": - case ",": - case ";": - case "*": - case "-": - case "+": - case "^": - case "<": - case "/": - case "=": - stream.next(); - return "atom"; - case "$": - stream.next(); - return "builtin"; - } - - if (stream.match(/\d+/)) { - if (stream.match(/^\w+/)) return "error"; - return "number"; - } else if (stream.match(/^[a-zA-Z_]\w*/)) { - if (stream.match(/(?=[\(.])/, false)) return "keyword"; - return "variable-2"; - } else if (["[", "]", "(", ")", "{", "}"].indexOf(peek) != -1) { - stream.next(); - return "bracket"; - } else if (!stream.eatSpace()) { - stream.next(); - } - return null; - } - }; - }); - - CodeMirror.defineMIME("text/x-spreadsheet", "spreadsheet"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/sql/index.html b/backend/_pv_1_3_5/static/codemirror/mode/sql/index.html deleted file mode 100755 index dba069dc8..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/sql/index.html +++ /dev/null @@ -1,86 +0,0 @@ - - -CodeMirror: SQL Mode for CodeMirror - - - - - - - - - - - - -
    -

    SQL Mode for CodeMirror

    -
    - -
    -

    MIME types defined: - text/x-sql, - text/x-mysql, - text/x-mariadb, - text/x-cassandra, - text/x-plsql, - text/x-mssql, - text/x-hive, - text/x-pgsql, - text/x-gql. -

    - - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/sql/sql.js b/backend/_pv_1_3_5/static/codemirror/mode/sql/sql.js deleted file mode 100755 index 32ced3e9d..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/sql/sql.js +++ /dev/null @@ -1,413 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("sql", function(config, parserConfig) { - "use strict"; - - var client = parserConfig.client || {}, - atoms = parserConfig.atoms || {"false": true, "true": true, "null": true}, - builtin = parserConfig.builtin || {}, - keywords = parserConfig.keywords || {}, - operatorChars = parserConfig.operatorChars || /^[*+\-%<>!=&|~^]/, - support = parserConfig.support || {}, - hooks = parserConfig.hooks || {}, - dateSQL = parserConfig.dateSQL || {"date" : true, "time" : true, "timestamp" : true}; - - function tokenBase(stream, state) { - var ch = stream.next(); - - // call hooks from the mime type - if (hooks[ch]) { - var result = hooks[ch](stream, state); - if (result !== false) return result; - } - - if (support.hexNumber && - ((ch == "0" && stream.match(/^[xX][0-9a-fA-F]+/)) - || (ch == "x" || ch == "X") && stream.match(/^'[0-9a-fA-F]+'/))) { - // hex - // ref: http://dev.mysql.com/doc/refman/5.5/en/hexadecimal-literals.html - return "number"; - } else if (support.binaryNumber && - (((ch == "b" || ch == "B") && stream.match(/^'[01]+'/)) - || (ch == "0" && stream.match(/^b[01]+/)))) { - // bitstring - // ref: http://dev.mysql.com/doc/refman/5.5/en/bit-field-literals.html - return "number"; - } else if (ch.charCodeAt(0) > 47 && ch.charCodeAt(0) < 58) { - // numbers - // ref: http://dev.mysql.com/doc/refman/5.5/en/number-literals.html - stream.match(/^[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/); - support.decimallessFloat && stream.eat('.'); - return "number"; - } else if (ch == "?" && (stream.eatSpace() || stream.eol() || stream.eat(";"))) { - // placeholders - return "variable-3"; - } else if (ch == "'" || (ch == '"' && support.doubleQuote)) { - // strings - // ref: http://dev.mysql.com/doc/refman/5.5/en/string-literals.html - state.tokenize = tokenLiteral(ch); - return state.tokenize(stream, state); - } else if ((((support.nCharCast && (ch == "n" || ch == "N")) - || (support.charsetCast && ch == "_" && stream.match(/[a-z][a-z0-9]*/i))) - && (stream.peek() == "'" || stream.peek() == '"'))) { - // charset casting: _utf8'str', N'str', n'str' - // ref: http://dev.mysql.com/doc/refman/5.5/en/string-literals.html - return "keyword"; - } else if (/^[\(\),\;\[\]]/.test(ch)) { - // no highlighting - return null; - } else if (support.commentSlashSlash && ch == "/" && stream.eat("/")) { - // 1-line comment - stream.skipToEnd(); - return "comment"; - } else if ((support.commentHash && ch == "#") - || (ch == "-" && stream.eat("-") && (!support.commentSpaceRequired || stream.eat(" ")))) { - // 1-line comments - // ref: https://kb.askmonty.org/en/comment-syntax/ - stream.skipToEnd(); - return "comment"; - } else if (ch == "/" && stream.eat("*")) { - // multi-line comments - // ref: https://kb.askmonty.org/en/comment-syntax/ - state.tokenize = tokenComment; - return state.tokenize(stream, state); - } else if (ch == ".") { - // .1 for 0.1 - if (support.zerolessFloat && stream.match(/^(?:\d+(?:e[+-]?\d+)?)/i)) { - return "number"; - } - // .table_name (ODBC) - // // ref: http://dev.mysql.com/doc/refman/5.6/en/identifier-qualifiers.html - if (support.ODBCdotTable && stream.match(/^[a-zA-Z_]+/)) { - return "variable-2"; - } - } else if (operatorChars.test(ch)) { - // operators - stream.eatWhile(operatorChars); - return null; - } else if (ch == '{' && - (stream.match(/^( )*(d|D|t|T|ts|TS)( )*'[^']*'( )*}/) || stream.match(/^( )*(d|D|t|T|ts|TS)( )*"[^"]*"( )*}/))) { - // dates (weird ODBC syntax) - // ref: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-literals.html - return "number"; - } else { - stream.eatWhile(/^[_\w\d]/); - var word = stream.current().toLowerCase(); - // dates (standard SQL syntax) - // ref: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-literals.html - if (dateSQL.hasOwnProperty(word) && (stream.match(/^( )+'[^']*'/) || stream.match(/^( )+"[^"]*"/))) - return "number"; - if (atoms.hasOwnProperty(word)) return "atom"; - if (builtin.hasOwnProperty(word)) return "builtin"; - if (keywords.hasOwnProperty(word)) return "keyword"; - if (client.hasOwnProperty(word)) return "string-2"; - return null; - } - } - - // 'string', with char specified in quote escaped by '\' - function tokenLiteral(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) { - state.tokenize = tokenBase; - break; - } - escaped = !escaped && ch == "\\"; - } - return "string"; - }; - } - function tokenComment(stream, state) { - while (true) { - if (stream.skipTo("*")) { - stream.next(); - if (stream.eat("/")) { - state.tokenize = tokenBase; - break; - } - } else { - stream.skipToEnd(); - break; - } - } - return "comment"; - } - - function pushContext(stream, state, type) { - state.context = { - prev: state.context, - indent: stream.indentation(), - col: stream.column(), - type: type - }; - } - - function popContext(state) { - state.indent = state.context.indent; - state.context = state.context.prev; - } - - return { - startState: function() { - return {tokenize: tokenBase, context: null}; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (state.context && state.context.align == null) - state.context.align = false; - } - if (stream.eatSpace()) return null; - - var style = state.tokenize(stream, state); - if (style == "comment") return style; - - if (state.context && state.context.align == null) - state.context.align = true; - - var tok = stream.current(); - if (tok == "(") - pushContext(stream, state, ")"); - else if (tok == "[") - pushContext(stream, state, "]"); - else if (state.context && state.context.type == tok) - popContext(state); - return style; - }, - - indent: function(state, textAfter) { - var cx = state.context; - if (!cx) return CodeMirror.Pass; - var closing = textAfter.charAt(0) == cx.type; - if (cx.align) return cx.col + (closing ? 0 : 1); - else return cx.indent + (closing ? 0 : config.indentUnit); - }, - - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: support.commentSlashSlash ? "//" : support.commentHash ? "#" : null - }; -}); - -(function() { - "use strict"; - - // `identifier` - function hookIdentifier(stream) { - // MySQL/MariaDB identifiers - // ref: http://dev.mysql.com/doc/refman/5.6/en/identifier-qualifiers.html - var ch; - while ((ch = stream.next()) != null) { - if (ch == "`" && !stream.eat("`")) return "variable-2"; - } - stream.backUp(stream.current().length - 1); - return stream.eatWhile(/\w/) ? "variable-2" : null; - } - - // variable token - function hookVar(stream) { - // variables - // @@prefix.varName @varName - // varName can be quoted with ` or ' or " - // ref: http://dev.mysql.com/doc/refman/5.5/en/user-variables.html - if (stream.eat("@")) { - stream.match(/^session\./); - stream.match(/^local\./); - stream.match(/^global\./); - } - - if (stream.eat("'")) { - stream.match(/^.*'/); - return "variable-2"; - } else if (stream.eat('"')) { - stream.match(/^.*"/); - return "variable-2"; - } else if (stream.eat("`")) { - stream.match(/^.*`/); - return "variable-2"; - } else if (stream.match(/^[0-9a-zA-Z$\.\_]+/)) { - return "variable-2"; - } - return null; - }; - - // short client keyword token - function hookClient(stream) { - // \N means NULL - // ref: http://dev.mysql.com/doc/refman/5.5/en/null-values.html - if (stream.eat("N")) { - return "atom"; - } - // \g, etc - // ref: http://dev.mysql.com/doc/refman/5.5/en/mysql-commands.html - return stream.match(/^[a-zA-Z.#!?]/) ? "variable-2" : null; - } - - // these keywords are used by all SQL dialects (however, a mode can still overwrite it) - var sqlKeywords = "alter and as asc between by count create delete desc distinct drop from group having in insert into is join like not on or order select set table union update values where limit "; - - // turn a space-separated list into an array - function set(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - // A generic SQL Mode. It's not a standard, it just try to support what is generally supported - CodeMirror.defineMIME("text/x-sql", { - name: "sql", - keywords: set(sqlKeywords + "begin"), - builtin: set("bool boolean bit blob enum long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision real date datetime year unsigned signed decimal numeric"), - atoms: set("false true null unknown"), - operatorChars: /^[*+\-%<>!=]/, - dateSQL: set("date time timestamp"), - support: set("ODBCdotTable doubleQuote binaryNumber hexNumber") - }); - - CodeMirror.defineMIME("text/x-mssql", { - name: "sql", - client: set("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"), - keywords: set(sqlKeywords + "begin trigger proc view index for add constraint key primary foreign collate clustered nonclustered declare exec"), - builtin: set("bigint numeric bit smallint decimal smallmoney int tinyint money float real char varchar text nchar nvarchar ntext binary varbinary image cursor timestamp hierarchyid uniqueidentifier sql_variant xml table "), - atoms: set("false true null unknown"), - operatorChars: /^[*+\-%<>!=]/, - dateSQL: set("date datetimeoffset datetime2 smalldatetime datetime time"), - hooks: { - "@": hookVar - } - }); - - CodeMirror.defineMIME("text/x-mysql", { - name: "sql", - client: set("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"), - keywords: set(sqlKeywords + "accessible action add after algorithm all analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general get global grant grants group group_concat handler hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show signal slave slow smallint snapshot soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views warnings when while with work write xa xor year_month zerofill begin do then else loop repeat"), - builtin: set("bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric"), - atoms: set("false true null unknown"), - operatorChars: /^[*+\-%<>!=&|^]/, - dateSQL: set("date time timestamp"), - support: set("ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber doubleQuote nCharCast charsetCast commentHash commentSpaceRequired"), - hooks: { - "@": hookVar, - "`": hookIdentifier, - "\\": hookClient - } - }); - - CodeMirror.defineMIME("text/x-mariadb", { - name: "sql", - client: set("charset clear connect edit ego exit go help nopager notee nowarning pager print prompt quit rehash source status system tee"), - keywords: set(sqlKeywords + "accessible action add after algorithm all always analyze asensitive at authors auto_increment autocommit avg avg_row_length before binary binlog both btree cache call cascade cascaded case catalog_name chain change changed character check checkpoint checksum class_origin client_statistics close coalesce code collate collation collations column columns comment commit committed completion concurrent condition connection consistent constraint contains continue contributors convert cross current current_date current_time current_timestamp current_user cursor data database databases day_hour day_microsecond day_minute day_second deallocate dec declare default delay_key_write delayed delimiter des_key_file describe deterministic dev_pop dev_samp deviance diagnostics directory disable discard distinctrow div dual dumpfile each elseif enable enclosed end ends engine engines enum errors escape escaped even event events every execute exists exit explain extended fast fetch field fields first flush for force foreign found_rows full fulltext function general generated get global grant grants group groupby_concat handler hard hash help high_priority hosts hour_microsecond hour_minute hour_second if ignore ignore_server_ids import index index_statistics infile inner innodb inout insensitive insert_method install interval invoker isolation iterate key keys kill language last leading leave left level limit linear lines list load local localtime localtimestamp lock logs low_priority master master_heartbeat_period master_ssl_verify_server_cert masters match max max_rows maxvalue message_text middleint migrate min min_rows minute_microsecond minute_second mod mode modifies modify mutex mysql_errno natural next no no_write_to_binlog offline offset one online open optimize option optionally out outer outfile pack_keys parser partition partitions password persistent phase plugin plugins prepare preserve prev primary privileges procedure processlist profile profiles purge query quick range read read_write reads real rebuild recover references regexp relaylog release remove rename reorganize repair repeatable replace require resignal restrict resume return returns revoke right rlike rollback rollup row row_format rtree savepoint schedule schema schema_name schemas second_microsecond security sensitive separator serializable server session share show shutdown signal slave slow smallint snapshot soft soname spatial specific sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_no_cache sql_small_result sqlexception sqlstate sqlwarning ssl start starting starts status std stddev stddev_pop stddev_samp storage straight_join subclass_origin sum suspend table_name table_statistics tables tablespace temporary terminated to trailing transaction trigger triggers truncate uncommitted undo uninstall unique unlock upgrade usage use use_frm user user_resources user_statistics using utc_date utc_time utc_timestamp value variables varying view views virtual warnings when while with work write xa xor year_month zerofill begin do then else loop repeat"), - builtin: set("bool boolean bit blob decimal double float long longblob longtext medium mediumblob mediumint mediumtext time timestamp tinyblob tinyint tinytext text bigint int int1 int2 int3 int4 int8 integer float float4 float8 double char varbinary varchar varcharacter precision date datetime year unsigned signed numeric"), - atoms: set("false true null unknown"), - operatorChars: /^[*+\-%<>!=&|^]/, - dateSQL: set("date time timestamp"), - support: set("ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber doubleQuote nCharCast charsetCast commentHash commentSpaceRequired"), - hooks: { - "@": hookVar, - "`": hookIdentifier, - "\\": hookClient - } - }); - - // the query language used by Apache Cassandra is called CQL, but this mime type - // is called Cassandra to avoid confusion with Contextual Query Language - CodeMirror.defineMIME("text/x-cassandra", { - name: "sql", - client: { }, - keywords: set("add all allow alter and any apply as asc authorize batch begin by clustering columnfamily compact consistency count create custom delete desc distinct drop each_quorum exists filtering from grant if in index insert into key keyspace keyspaces level limit local_one local_quorum modify nan norecursive nosuperuser not of on one order password permission permissions primary quorum rename revoke schema select set storage superuser table three to token truncate ttl two type unlogged update use user users using values where with writetime"), - builtin: set("ascii bigint blob boolean counter decimal double float frozen inet int list map static text timestamp timeuuid tuple uuid varchar varint"), - atoms: set("false true infinity NaN"), - operatorChars: /^[<>=]/, - dateSQL: { }, - support: set("commentSlashSlash decimallessFloat"), - hooks: { } - }); - - // this is based on Peter Raganitsch's 'plsql' mode - CodeMirror.defineMIME("text/x-plsql", { - name: "sql", - client: set("appinfo arraysize autocommit autoprint autorecovery autotrace blockterminator break btitle cmdsep colsep compatibility compute concat copycommit copytypecheck define describe echo editfile embedded escape exec execute feedback flagger flush heading headsep instance linesize lno loboffset logsource long longchunksize markup native newpage numformat numwidth pagesize pause pno recsep recsepchar release repfooter repheader serveroutput shiftinout show showmode size spool sqlblanklines sqlcase sqlcode sqlcontinue sqlnumber sqlpluscompatibility sqlprefix sqlprompt sqlterminator suffix tab term termout time timing trimout trimspool ttitle underline verify version wrap"), - keywords: set("abort accept access add all alter and any array arraylen as asc assert assign at attributes audit authorization avg base_table begin between binary_integer body boolean by case cast char char_base check close cluster clusters colauth column comment commit compress connect connected constant constraint crash create current currval cursor data_base database date dba deallocate debugoff debugon decimal declare default definition delay delete desc digits dispose distinct do drop else elseif elsif enable end entry escape exception exception_init exchange exclusive exists exit external fast fetch file for force form from function generic goto grant group having identified if immediate in increment index indexes indicator initial initrans insert interface intersect into is key level library like limited local lock log logging long loop master maxextents maxtrans member minextents minus mislabel mode modify multiset new next no noaudit nocompress nologging noparallel not nowait number_base object of off offline on online only open option or order out package parallel partition pctfree pctincrease pctused pls_integer positive positiven pragma primary prior private privileges procedure public raise range raw read rebuild record ref references refresh release rename replace resource restrict return returning returns reverse revoke rollback row rowid rowlabel rownum rows run savepoint schema segment select separate session set share snapshot some space split sql start statement storage subtype successful synonym tabauth table tables tablespace task terminate then to trigger truncate type union unique unlimited unrecoverable unusable update use using validate value values variable view views when whenever where while with work"), - builtin: set("abs acos add_months ascii asin atan atan2 average bfile bfilename bigserial bit blob ceil character chartorowid chr clob concat convert cos cosh count dec decode deref dual dump dup_val_on_index empty error exp false float floor found glb greatest hextoraw initcap instr instrb int integer isopen last_day least length lengthb ln lower lpad ltrim lub make_ref max min mlslabel mod months_between natural naturaln nchar nclob new_time next_day nextval nls_charset_decl_len nls_charset_id nls_charset_name nls_initcap nls_lower nls_sort nls_upper nlssort no_data_found notfound null number numeric nvarchar2 nvl others power rawtohex real reftohex round rowcount rowidtochar rowtype rpad rtrim serial sign signtype sin sinh smallint soundex sqlcode sqlerrm sqrt stddev string substr substrb sum sysdate tan tanh to_char text to_date to_label to_multi_byte to_number to_single_byte translate true trunc uid unlogged upper user userenv varchar varchar2 variance varying vsize xml"), - operatorChars: /^[*+\-%<>!=~]/, - dateSQL: set("date time timestamp"), - support: set("doubleQuote nCharCast zerolessFloat binaryNumber hexNumber") - }); - - // Created to support specific hive keywords - CodeMirror.defineMIME("text/x-hive", { - name: "sql", - keywords: set("select alter $elem$ $key$ $value$ add after all analyze and archive as asc before between binary both bucket buckets by cascade case cast change cluster clustered clusterstatus collection column columns comment compute concatenate continue create cross cursor data database databases dbproperties deferred delete delimited desc describe directory disable distinct distribute drop else enable end escaped exclusive exists explain export extended external false fetch fields fileformat first format formatted from full function functions grant group having hold_ddltime idxproperties if import in index indexes inpath inputdriver inputformat insert intersect into is items join keys lateral left like limit lines load local location lock locks mapjoin materialized minus msck no_drop nocompress not of offline on option or order out outer outputdriver outputformat overwrite partition partitioned partitions percent plus preserve procedure purge range rcfile read readonly reads rebuild recordreader recordwriter recover reduce regexp rename repair replace restrict revoke right rlike row schema schemas semi sequencefile serde serdeproperties set shared show show_database sort sorted ssl statistics stored streamtable table tables tablesample tblproperties temporary terminated textfile then tmp to touch transform trigger true unarchive undo union uniquejoin unlock update use using utc utc_tmestamp view when where while with"), - builtin: set("bool boolean long timestamp tinyint smallint bigint int float double date datetime unsigned string array struct map uniontype"), - atoms: set("false true null unknown"), - operatorChars: /^[*+\-%<>!=]/, - dateSQL: set("date timestamp"), - support: set("ODBCdotTable doubleQuote binaryNumber hexNumber") - }); - - CodeMirror.defineMIME("text/x-pgsql", { - name: "sql", - client: set("source"), - // http://www.postgresql.org/docs/9.5/static/sql-keywords-appendix.html - keywords: set(sqlKeywords + "a abort abs absent absolute access according action ada add admin after aggregate all allocate also always analyse analyze any are array array_agg array_max_cardinality asensitive assertion assignment asymmetric at atomic attribute attributes authorization avg backward base64 before begin begin_frame begin_partition bernoulli binary bit_length blob blocked bom both breadth c cache call called cardinality cascade cascaded case cast catalog catalog_name ceil ceiling chain characteristics characters character_length character_set_catalog character_set_name character_set_schema char_length check checkpoint class class_origin clob close cluster coalesce cobol collate collation collation_catalog collation_name collation_schema collect column columns column_name command_function command_function_code comment comments commit committed concurrently condition condition_number configuration conflict connect connection connection_name constraint constraints constraint_catalog constraint_name constraint_schema constructor contains content continue control conversion convert copy corr corresponding cost covar_pop covar_samp cross csv cube cume_dist current current_catalog current_date current_default_transform_group current_path current_role current_row current_schema current_time current_timestamp current_transform_group_for_type current_user cursor cursor_name cycle data database datalink datetime_interval_code datetime_interval_precision day db deallocate dec declare default defaults deferrable deferred defined definer degree delimiter delimiters dense_rank depth deref derived describe descriptor deterministic diagnostics dictionary disable discard disconnect dispatch dlnewcopy dlpreviouscopy dlurlcomplete dlurlcompleteonly dlurlcompletewrite dlurlpath dlurlpathonly dlurlpathwrite dlurlscheme dlurlserver dlvalue do document domain dynamic dynamic_function dynamic_function_code each element else empty enable encoding encrypted end end-exec end_frame end_partition enforced enum equals escape event every except exception exclude excluding exclusive exec execute exists exp explain expression extension external extract false family fetch file filter final first first_value flag float floor following for force foreign fortran forward found frame_row free freeze fs full function functions fusion g general generated get global go goto grant granted greatest grouping groups handler header hex hierarchy hold hour id identity if ignore ilike immediate immediately immutable implementation implicit import including increment indent index indexes indicator inherit inherits initially inline inner inout input insensitive instance instantiable instead integrity intersect intersection invoker isnull isolation k key key_member key_type label lag language large last last_value lateral lead leading leakproof least left length level library like_regex link listen ln load local localtime localtimestamp location locator lock locked logged lower m map mapping match matched materialized max maxvalue max_cardinality member merge message_length message_octet_length message_text method min minute minvalue mod mode modifies module month more move multiset mumps name names namespace national natural nchar nclob nesting new next nfc nfd nfkc nfkd nil no none normalize normalized nothing notify notnull nowait nth_value ntile null nullable nullif nulls number object occurrences_regex octets octet_length of off offset oids old only open operator option options ordering ordinality others out outer output over overlaps overlay overriding owned owner p pad parameter parameter_mode parameter_name parameter_ordinal_position parameter_specific_catalog parameter_specific_name parameter_specific_schema parser partial partition pascal passing passthrough password percent percentile_cont percentile_disc percent_rank period permission placing plans pli policy portion position position_regex power precedes preceding prepare prepared preserve primary prior privileges procedural procedure program public quote range rank read reads reassign recheck recovery recursive ref references referencing refresh regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy regr_syy reindex relative release rename repeatable replace replica requiring reset respect restart restore restrict result return returned_cardinality returned_length returned_octet_length returned_sqlstate returning returns revoke right role rollback rollup routine routine_catalog routine_name routine_schema row rows row_count row_number rule savepoint scale schema schema_name scope scope_catalog scope_name scope_schema scroll search second section security selective self sensitive sequence sequences serializable server server_name session session_user setof sets share show similar simple size skip snapshot some source space specific specifictype specific_name sql sqlcode sqlerror sqlexception sqlstate sqlwarning sqrt stable standalone start state statement static statistics stddev_pop stddev_samp stdin stdout storage strict strip structure style subclass_origin submultiset substring substring_regex succeeds sum symmetric sysid system system_time system_user t tables tablesample tablespace table_name temp template temporary then ties timezone_hour timezone_minute to token top_level_count trailing transaction transactions_committed transactions_rolled_back transaction_active transform transforms translate translate_regex translation treat trigger trigger_catalog trigger_name trigger_schema trim trim_array true truncate trusted type types uescape unbounded uncommitted under unencrypted unique unknown unlink unlisten unlogged unnamed unnest until untyped upper uri usage user user_defined_type_catalog user_defined_type_code user_defined_type_name user_defined_type_schema using vacuum valid validate validator value value_of varbinary variadic var_pop var_samp verbose version versioning view views volatile when whenever whitespace width_bucket window within work wrapper write xmlagg xmlattributes xmlbinary xmlcast xmlcomment xmlconcat xmldeclaration xmldocument xmlelement xmlexists xmlforest xmliterate xmlnamespaces xmlparse xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltext xmlvalidate year yes loop repeat"), - // http://www.postgresql.org/docs/9.5/static/datatype.html - builtin: set("bigint int8 bigserial serial8 bit varying varbit boolean bool box bytea character char varchar cidr circle date double precision float8 inet integer int int4 interval json jsonb line lseg macaddr money numeric decimal path pg_lsn point polygon real float4 smallint int2 smallserial serial2 serial serial4 text time without zone with timetz timestamp timestamptz tsquery tsvector txid_snapshot uuid xml"), - atoms: set("false true null unknown"), - operatorChars: /^[*+\-%<>!=&|^\/#@?~]/, - dateSQL: set("date time timestamp"), - support: set("ODBCdotTable decimallessFloat zerolessFloat binaryNumber hexNumber nCharCast charsetCast") - }); - - // Google's SQL-like query language, GQL - CodeMirror.defineMIME("text/x-gql", { - name: "sql", - keywords: set("ancestor and asc by contains desc descendant distinct from group has in is limit offset on order select superset where"), - atoms: set("false true"), - builtin: set("blob datetime first key __key__ string integer double boolean null"), - operatorChars: /^[*+\-%<>!=]/ - }); -}()); - -}); - -/* - How Properties of Mime Types are used by SQL Mode - ================================================= - - keywords: - A list of keywords you want to be highlighted. - builtin: - A list of builtin types you want to be highlighted (if you want types to be of class "builtin" instead of "keyword"). - operatorChars: - All characters that must be handled as operators. - client: - Commands parsed and executed by the client (not the server). - support: - A list of supported syntaxes which are not common, but are supported by more than 1 DBMS. - * ODBCdotTable: .tableName - * zerolessFloat: .1 - * doubleQuote - * nCharCast: N'string' - * charsetCast: _utf8'string' - * commentHash: use # char for comments - * commentSlashSlash: use // for comments - * commentSpaceRequired: require a space after -- for comments - atoms: - Keywords that must be highlighted as atoms,. Some DBMS's support more atoms than others: - UNKNOWN, INFINITY, UNDERFLOW, NaN... - dateSQL: - Used for date/time SQL standard syntax, because not all DBMS's support same temporal types. -*/ diff --git a/backend/_pv_1_3_5/static/codemirror/mode/stex/index.html b/backend/_pv_1_3_5/static/codemirror/mode/stex/index.html deleted file mode 100755 index 14679da4f..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/stex/index.html +++ /dev/null @@ -1,110 +0,0 @@ - - -CodeMirror: sTeX mode - - - - - - - - - -
    -

    sTeX mode

    -
    - - -

    MIME types defined: text/x-stex.

    - -

    Parsing/Highlighting Tests: normal, verbose.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/stex/stex.js b/backend/_pv_1_3_5/static/codemirror/mode/stex/stex.js deleted file mode 100755 index 835ed46d1..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/stex/stex.js +++ /dev/null @@ -1,251 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/* - * Author: Constantin Jucovschi (c.jucovschi@jacobs-university.de) - * Licence: MIT - */ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("stex", function() { - "use strict"; - - function pushCommand(state, command) { - state.cmdState.push(command); - } - - function peekCommand(state) { - if (state.cmdState.length > 0) { - return state.cmdState[state.cmdState.length - 1]; - } else { - return null; - } - } - - function popCommand(state) { - var plug = state.cmdState.pop(); - if (plug) { - plug.closeBracket(); - } - } - - // returns the non-default plugin closest to the end of the list - function getMostPowerful(state) { - var context = state.cmdState; - for (var i = context.length - 1; i >= 0; i--) { - var plug = context[i]; - if (plug.name == "DEFAULT") { - continue; - } - return plug; - } - return { styleIdentifier: function() { return null; } }; - } - - function addPluginPattern(pluginName, cmdStyle, styles) { - return function () { - this.name = pluginName; - this.bracketNo = 0; - this.style = cmdStyle; - this.styles = styles; - this.argument = null; // \begin and \end have arguments that follow. These are stored in the plugin - - this.styleIdentifier = function() { - return this.styles[this.bracketNo - 1] || null; - }; - this.openBracket = function() { - this.bracketNo++; - return "bracket"; - }; - this.closeBracket = function() {}; - }; - } - - var plugins = {}; - - plugins["importmodule"] = addPluginPattern("importmodule", "tag", ["string", "builtin"]); - plugins["documentclass"] = addPluginPattern("documentclass", "tag", ["", "atom"]); - plugins["usepackage"] = addPluginPattern("usepackage", "tag", ["atom"]); - plugins["begin"] = addPluginPattern("begin", "tag", ["atom"]); - plugins["end"] = addPluginPattern("end", "tag", ["atom"]); - - plugins["DEFAULT"] = function () { - this.name = "DEFAULT"; - this.style = "tag"; - - this.styleIdentifier = this.openBracket = this.closeBracket = function() {}; - }; - - function setState(state, f) { - state.f = f; - } - - // called when in a normal (no environment) context - function normal(source, state) { - var plug; - // Do we look like '\command' ? If so, attempt to apply the plugin 'command' - if (source.match(/^\\[a-zA-Z@]+/)) { - var cmdName = source.current().slice(1); - plug = plugins[cmdName] || plugins["DEFAULT"]; - plug = new plug(); - pushCommand(state, plug); - setState(state, beginParams); - return plug.style; - } - - // escape characters - if (source.match(/^\\[$&%#{}_]/)) { - return "tag"; - } - - // white space control characters - if (source.match(/^\\[,;!\/\\]/)) { - return "tag"; - } - - // find if we're starting various math modes - if (source.match("\\[")) { - setState(state, function(source, state){ return inMathMode(source, state, "\\]"); }); - return "keyword"; - } - if (source.match("$$")) { - setState(state, function(source, state){ return inMathMode(source, state, "$$"); }); - return "keyword"; - } - if (source.match("$")) { - setState(state, function(source, state){ return inMathMode(source, state, "$"); }); - return "keyword"; - } - - var ch = source.next(); - if (ch == "%") { - source.skipToEnd(); - return "comment"; - } else if (ch == '}' || ch == ']') { - plug = peekCommand(state); - if (plug) { - plug.closeBracket(ch); - setState(state, beginParams); - } else { - return "error"; - } - return "bracket"; - } else if (ch == '{' || ch == '[') { - plug = plugins["DEFAULT"]; - plug = new plug(); - pushCommand(state, plug); - return "bracket"; - } else if (/\d/.test(ch)) { - source.eatWhile(/[\w.%]/); - return "atom"; - } else { - source.eatWhile(/[\w\-_]/); - plug = getMostPowerful(state); - if (plug.name == 'begin') { - plug.argument = source.current(); - } - return plug.styleIdentifier(); - } - } - - function inMathMode(source, state, endModeSeq) { - if (source.eatSpace()) { - return null; - } - if (source.match(endModeSeq)) { - setState(state, normal); - return "keyword"; - } - if (source.match(/^\\[a-zA-Z@]+/)) { - return "tag"; - } - if (source.match(/^[a-zA-Z]+/)) { - return "variable-2"; - } - // escape characters - if (source.match(/^\\[$&%#{}_]/)) { - return "tag"; - } - // white space control characters - if (source.match(/^\\[,;!\/]/)) { - return "tag"; - } - // special math-mode characters - if (source.match(/^[\^_&]/)) { - return "tag"; - } - // non-special characters - if (source.match(/^[+\-<>|=,\/@!*:;'"`~#?]/)) { - return null; - } - if (source.match(/^(\d+\.\d*|\d*\.\d+|\d+)/)) { - return "number"; - } - var ch = source.next(); - if (ch == "{" || ch == "}" || ch == "[" || ch == "]" || ch == "(" || ch == ")") { - return "bracket"; - } - - if (ch == "%") { - source.skipToEnd(); - return "comment"; - } - return "error"; - } - - function beginParams(source, state) { - var ch = source.peek(), lastPlug; - if (ch == '{' || ch == '[') { - lastPlug = peekCommand(state); - lastPlug.openBracket(ch); - source.eat(ch); - setState(state, normal); - return "bracket"; - } - if (/[ \t\r]/.test(ch)) { - source.eat(ch); - return null; - } - setState(state, normal); - popCommand(state); - - return normal(source, state); - } - - return { - startState: function() { - return { - cmdState: [], - f: normal - }; - }, - copyState: function(s) { - return { - cmdState: s.cmdState.slice(), - f: s.f - }; - }, - token: function(stream, state) { - return state.f(stream, state); - }, - blankLine: function(state) { - state.f = normal; - state.cmdState.length = 0; - }, - lineComment: "%" - }; - }); - - CodeMirror.defineMIME("text/x-stex", "stex"); - CodeMirror.defineMIME("text/x-latex", "stex"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/stex/test.js b/backend/_pv_1_3_5/static/codemirror/mode/stex/test.js deleted file mode 100755 index 22f027ec7..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/stex/test.js +++ /dev/null @@ -1,123 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({tabSize: 4}, "stex"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT("word", - "foo"); - - MT("twoWords", - "foo bar"); - - MT("beginEndDocument", - "[tag \\begin][bracket {][atom document][bracket }]", - "[tag \\end][bracket {][atom document][bracket }]"); - - MT("beginEndEquation", - "[tag \\begin][bracket {][atom equation][bracket }]", - " E=mc^2", - "[tag \\end][bracket {][atom equation][bracket }]"); - - MT("beginModule", - "[tag \\begin][bracket {][atom module][bracket }[[]]]"); - - MT("beginModuleId", - "[tag \\begin][bracket {][atom module][bracket }[[]id=bbt-size[bracket ]]]"); - - MT("importModule", - "[tag \\importmodule][bracket [[][string b-b-t][bracket ]]{][builtin b-b-t][bracket }]"); - - MT("importModulePath", - "[tag \\importmodule][bracket [[][tag \\KWARCslides][bracket {][string dmath/en/cardinality][bracket }]]{][builtin card][bracket }]"); - - MT("psForPDF", - "[tag \\PSforPDF][bracket [[][atom 1][bracket ]]{]#1[bracket }]"); - - MT("comment", - "[comment % foo]"); - - MT("tagComment", - "[tag \\item][comment % bar]"); - - MT("commentTag", - " [comment % \\item]"); - - MT("commentLineBreak", - "[comment %]", - "foo"); - - MT("tagErrorCurly", - "[tag \\begin][error }][bracket {]"); - - MT("tagErrorSquare", - "[tag \\item][error ]]][bracket {]"); - - MT("commentCurly", - "[comment % }]"); - - MT("tagHash", - "the [tag \\#] key"); - - MT("tagNumber", - "a [tag \\$][atom 5] stetson"); - - MT("tagPercent", - "[atom 100][tag \\%] beef"); - - MT("tagAmpersand", - "L [tag \\&] N"); - - MT("tagUnderscore", - "foo[tag \\_]bar"); - - MT("tagBracketOpen", - "[tag \\emph][bracket {][tag \\{][bracket }]"); - - MT("tagBracketClose", - "[tag \\emph][bracket {][tag \\}][bracket }]"); - - MT("tagLetterNumber", - "section [tag \\S][atom 1]"); - - MT("textTagNumber", - "para [tag \\P][atom 2]"); - - MT("thinspace", - "x[tag \\,]y"); - - MT("thickspace", - "x[tag \\;]y"); - - MT("negativeThinspace", - "x[tag \\!]y"); - - MT("periodNotSentence", - "J.\\ L.\\ is"); - - MT("periodSentence", - "X[tag \\@]. The"); - - MT("italicCorrection", - "[bracket {][tag \\em] If[tag \\/][bracket }] I"); - - MT("tagBracket", - "[tag \\newcommand][bracket {][tag \\pop][bracket }]"); - - MT("inlineMathTagFollowedByNumber", - "[keyword $][tag \\pi][number 2][keyword $]"); - - MT("inlineMath", - "[keyword $][number 3][variable-2 x][tag ^][number 2.45]-[tag \\sqrt][bracket {][tag \\$\\alpha][bracket }] = [number 2][keyword $] other text"); - - MT("displayMath", - "More [keyword $$]\t[variable-2 S][tag ^][variable-2 n][tag \\sum] [variable-2 i][keyword $$] other text"); - - MT("mathWithComment", - "[keyword $][variable-2 x] [comment % $]", - "[variable-2 y][keyword $] other text"); - - MT("lineBreakArgument", - "[tag \\\\][bracket [[][atom 1cm][bracket ]]]"); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/stylus/index.html b/backend/_pv_1_3_5/static/codemirror/mode/stylus/index.html deleted file mode 100755 index 862c18f25..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/stylus/index.html +++ /dev/null @@ -1,106 +0,0 @@ - - -CodeMirror: Stylus mode - - - - - - - - - - - -
    -

    Stylus mode

    -
    -
    - - -

    MIME types defined: text/x-styl.

    -

    Created by Dmitry Kiselyov

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/stylus/stylus.js b/backend/_pv_1_3_5/static/codemirror/mode/stylus/stylus.js deleted file mode 100755 index 8d83a0180..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/stylus/stylus.js +++ /dev/null @@ -1,769 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Stylus mode created by Dmitry Kiselyov http://git.io/AaRB - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("stylus", function(config) { - var indentUnit = config.indentUnit, - tagKeywords = keySet(tagKeywords_), - tagVariablesRegexp = /^(a|b|i|s|col|em)$/i, - propertyKeywords = keySet(propertyKeywords_), - nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_), - valueKeywords = keySet(valueKeywords_), - colorKeywords = keySet(colorKeywords_), - documentTypes = keySet(documentTypes_), - documentTypesRegexp = wordRegexp(documentTypes_), - mediaFeatures = keySet(mediaFeatures_), - mediaTypes = keySet(mediaTypes_), - fontProperties = keySet(fontProperties_), - operatorsRegexp = /^\s*([.]{2,3}|&&|\|\||\*\*|[?!=:]?=|[-+*\/%<>]=?|\?:|\~)/, - wordOperatorKeywordsRegexp = wordRegexp(wordOperatorKeywords_), - blockKeywords = keySet(blockKeywords_), - vendorPrefixesRegexp = new RegExp(/^\-(moz|ms|o|webkit)-/i), - commonAtoms = keySet(commonAtoms_), - firstWordMatch = "", - states = {}, - ch, - style, - type, - override; - - /** - * Tokenizers - */ - function tokenBase(stream, state) { - firstWordMatch = stream.string.match(/(^[\w-]+\s*=\s*$)|(^\s*[\w-]+\s*=\s*[\w-])|(^\s*(\.|#|@|\$|\&|\[|\d|\+|::?|\{|\>|~|\/)?\s*[\w-]*([a-z0-9-]|\*|\/\*)(\(|,)?)/); - state.context.line.firstWord = firstWordMatch ? firstWordMatch[0].replace(/^\s*/, "") : ""; - state.context.line.indent = stream.indentation(); - ch = stream.peek(); - - // Line comment - if (stream.match("//")) { - stream.skipToEnd(); - return ["comment", "comment"]; - } - // Block comment - if (stream.match("/*")) { - state.tokenize = tokenCComment; - return tokenCComment(stream, state); - } - // String - if (ch == "\"" || ch == "'") { - stream.next(); - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - // Def - if (ch == "@") { - stream.next(); - stream.eatWhile(/[\w\\-]/); - return ["def", stream.current()]; - } - // ID selector or Hex color - if (ch == "#") { - stream.next(); - // Hex color - if (stream.match(/^[0-9a-f]{6}|[0-9a-f]{3}/i)) { - return ["atom", "atom"]; - } - // ID selector - if (stream.match(/^[a-z][\w-]*/i)) { - return ["builtin", "hash"]; - } - } - // Vendor prefixes - if (stream.match(vendorPrefixesRegexp)) { - return ["meta", "vendor-prefixes"]; - } - // Numbers - if (stream.match(/^-?[0-9]?\.?[0-9]/)) { - stream.eatWhile(/[a-z%]/i); - return ["number", "unit"]; - } - // !important|optional - if (ch == "!") { - stream.next(); - return [stream.match(/^(important|optional)/i) ? "keyword": "operator", "important"]; - } - // Class - if (ch == "." && stream.match(/^\.[a-z][\w-]*/i)) { - return ["qualifier", "qualifier"]; - } - // url url-prefix domain regexp - if (stream.match(documentTypesRegexp)) { - if (stream.peek() == "(") state.tokenize = tokenParenthesized; - return ["property", "word"]; - } - // Mixins / Functions - if (stream.match(/^[a-z][\w-]*\(/i)) { - stream.backUp(1); - return ["keyword", "mixin"]; - } - // Block mixins - if (stream.match(/^(\+|-)[a-z][\w-]*\(/i)) { - stream.backUp(1); - return ["keyword", "block-mixin"]; - } - // Parent Reference BEM naming - if (stream.string.match(/^\s*&/) && stream.match(/^[-_]+[a-z][\w-]*/)) { - return ["qualifier", "qualifier"]; - } - // / Root Reference & Parent Reference - if (stream.match(/^(\/|&)(-|_|:|\.|#|[a-z])/)) { - stream.backUp(1); - return ["variable-3", "reference"]; - } - if (stream.match(/^&{1}\s*$/)) { - return ["variable-3", "reference"]; - } - // Word operator - if (stream.match(wordOperatorKeywordsRegexp)) { - return ["operator", "operator"]; - } - // Word - if (stream.match(/^\$?[-_]*[a-z0-9]+[\w-]*/i)) { - // Variable - if (stream.match(/^(\.|\[)[\w-\'\"\]]+/i, false)) { - if (!wordIsTag(stream.current())) { - stream.match(/\./); - return ["variable-2", "variable-name"]; - } - } - return ["variable-2", "word"]; - } - // Operators - if (stream.match(operatorsRegexp)) { - return ["operator", stream.current()]; - } - // Delimiters - if (/[:;,{}\[\]\(\)]/.test(ch)) { - stream.next(); - return [null, ch]; - } - // Non-detected items - stream.next(); - return [null, null]; - } - - /** - * Token comment - */ - function tokenCComment(stream, state) { - var maybeEnd = false, ch; - while ((ch = stream.next()) != null) { - if (maybeEnd && ch == "/") { - state.tokenize = null; - break; - } - maybeEnd = (ch == "*"); - } - return ["comment", "comment"]; - } - - /** - * Token string - */ - function tokenString(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) { - if (quote == ")") stream.backUp(1); - break; - } - escaped = !escaped && ch == "\\"; - } - if (ch == quote || !escaped && quote != ")") state.tokenize = null; - return ["string", "string"]; - }; - } - - /** - * Token parenthesized - */ - function tokenParenthesized(stream, state) { - stream.next(); // Must be "(" - if (!stream.match(/\s*[\"\')]/, false)) - state.tokenize = tokenString(")"); - else - state.tokenize = null; - return [null, "("]; - } - - /** - * Context management - */ - function Context(type, indent, prev, line) { - this.type = type; - this.indent = indent; - this.prev = prev; - this.line = line || {firstWord: "", indent: 0}; - } - - function pushContext(state, stream, type, indent) { - indent = indent >= 0 ? indent : indentUnit; - state.context = new Context(type, stream.indentation() + indent, state.context); - return type; - } - - function popContext(state, currentIndent) { - var contextIndent = state.context.indent - indentUnit; - currentIndent = currentIndent || false; - state.context = state.context.prev; - if (currentIndent) state.context.indent = contextIndent; - return state.context.type; - } - - function pass(type, stream, state) { - return states[state.context.type](type, stream, state); - } - - function popAndPass(type, stream, state, n) { - for (var i = n || 1; i > 0; i--) - state.context = state.context.prev; - return pass(type, stream, state); - } - - - /** - * Parser - */ - function wordIsTag(word) { - return word.toLowerCase() in tagKeywords; - } - - function wordIsProperty(word) { - word = word.toLowerCase(); - return word in propertyKeywords || word in fontProperties; - } - - function wordIsBlock(word) { - return word.toLowerCase() in blockKeywords; - } - - function wordIsVendorPrefix(word) { - return word.toLowerCase().match(vendorPrefixesRegexp); - } - - function wordAsValue(word) { - var wordLC = word.toLowerCase(); - var override = "variable-2"; - if (wordIsTag(word)) override = "tag"; - else if (wordIsBlock(word)) override = "block-keyword"; - else if (wordIsProperty(word)) override = "property"; - else if (wordLC in valueKeywords || wordLC in commonAtoms) override = "atom"; - else if (wordLC == "return" || wordLC in colorKeywords) override = "keyword"; - - // Font family - else if (word.match(/^[A-Z]/)) override = "string"; - return override; - } - - function typeIsBlock(type, stream) { - return ((endOfLine(stream) && (type == "{" || type == "]" || type == "hash" || type == "qualifier")) || type == "block-mixin"); - } - - function typeIsInterpolation(type, stream) { - return type == "{" && stream.match(/^\s*\$?[\w-]+/i, false); - } - - function typeIsPseudo(type, stream) { - return type == ":" && stream.match(/^[a-z-]+/, false); - } - - function startOfLine(stream) { - return stream.sol() || stream.string.match(new RegExp("^\\s*" + escapeRegExp(stream.current()))); - } - - function endOfLine(stream) { - return stream.eol() || stream.match(/^\s*$/, false); - } - - function firstWordOfLine(line) { - var re = /^\s*[-_]*[a-z0-9]+[\w-]*/i; - var result = typeof line == "string" ? line.match(re) : line.string.match(re); - return result ? result[0].replace(/^\s*/, "") : ""; - } - - - /** - * Block - */ - states.block = function(type, stream, state) { - if ((type == "comment" && startOfLine(stream)) || - (type == "," && endOfLine(stream)) || - type == "mixin") { - return pushContext(state, stream, "block", 0); - } - if (typeIsInterpolation(type, stream)) { - return pushContext(state, stream, "interpolation"); - } - if (endOfLine(stream) && type == "]") { - if (!/^\s*(\.|#|:|\[|\*|&)/.test(stream.string) && !wordIsTag(firstWordOfLine(stream))) { - return pushContext(state, stream, "block", 0); - } - } - if (typeIsBlock(type, stream, state)) { - return pushContext(state, stream, "block"); - } - if (type == "}" && endOfLine(stream)) { - return pushContext(state, stream, "block", 0); - } - if (type == "variable-name") { - if (stream.string.match(/^\s?\$[\w-\.\[\]\'\"]+$/) || wordIsBlock(firstWordOfLine(stream))) { - return pushContext(state, stream, "variableName"); - } - else { - return pushContext(state, stream, "variableName", 0); - } - } - if (type == "=") { - if (!endOfLine(stream) && !wordIsBlock(firstWordOfLine(stream))) { - return pushContext(state, stream, "block", 0); - } - return pushContext(state, stream, "block"); - } - if (type == "*") { - if (endOfLine(stream) || stream.match(/\s*(,|\.|#|\[|:|{)/,false)) { - override = "tag"; - return pushContext(state, stream, "block"); - } - } - if (typeIsPseudo(type, stream)) { - return pushContext(state, stream, "pseudo"); - } - if (/@(font-face|media|supports|(-moz-)?document)/.test(type)) { - return pushContext(state, stream, endOfLine(stream) ? "block" : "atBlock"); - } - if (/@(-(moz|ms|o|webkit)-)?keyframes$/.test(type)) { - return pushContext(state, stream, "keyframes"); - } - if (/@extends?/.test(type)) { - return pushContext(state, stream, "extend", 0); - } - if (type && type.charAt(0) == "@") { - - // Property Lookup - if (stream.indentation() > 0 && wordIsProperty(stream.current().slice(1))) { - override = "variable-2"; - return "block"; - } - if (/(@import|@require|@charset)/.test(type)) { - return pushContext(state, stream, "block", 0); - } - return pushContext(state, stream, "block"); - } - if (type == "reference" && endOfLine(stream)) { - return pushContext(state, stream, "block"); - } - if (type == "(") { - return pushContext(state, stream, "parens"); - } - - if (type == "vendor-prefixes") { - return pushContext(state, stream, "vendorPrefixes"); - } - if (type == "word") { - var word = stream.current(); - override = wordAsValue(word); - - if (override == "property") { - if (startOfLine(stream)) { - return pushContext(state, stream, "block", 0); - } else { - override = "atom"; - return "block"; - } - } - - if (override == "tag") { - - // tag is a css value - if (/embed|menu|pre|progress|sub|table/.test(word)) { - if (wordIsProperty(firstWordOfLine(stream))) { - override = "atom"; - return "block"; - } - } - - // tag is an attribute - if (stream.string.match(new RegExp("\\[\\s*" + word + "|" + word +"\\s*\\]"))) { - override = "atom"; - return "block"; - } - - // tag is a variable - if (tagVariablesRegexp.test(word)) { - if ((startOfLine(stream) && stream.string.match(/=/)) || - (!startOfLine(stream) && - !stream.string.match(/^(\s*\.|#|\&|\[|\/|>|\*)/) && - !wordIsTag(firstWordOfLine(stream)))) { - override = "variable-2"; - if (wordIsBlock(firstWordOfLine(stream))) return "block"; - return pushContext(state, stream, "block", 0); - } - } - - if (endOfLine(stream)) return pushContext(state, stream, "block"); - } - if (override == "block-keyword") { - override = "keyword"; - - // Postfix conditionals - if (stream.current(/(if|unless)/) && !startOfLine(stream)) { - return "block"; - } - return pushContext(state, stream, "block"); - } - if (word == "return") return pushContext(state, stream, "block", 0); - - // Placeholder selector - if (override == "variable-2" && stream.string.match(/^\s?\$[\w-\.\[\]\'\"]+$/)) { - return pushContext(state, stream, "block"); - } - } - return state.context.type; - }; - - - /** - * Parens - */ - states.parens = function(type, stream, state) { - if (type == "(") return pushContext(state, stream, "parens"); - if (type == ")") { - if (state.context.prev.type == "parens") { - return popContext(state); - } - if ((stream.string.match(/^[a-z][\w-]*\(/i) && endOfLine(stream)) || - wordIsBlock(firstWordOfLine(stream)) || - /(\.|#|:|\[|\*|&|>|~|\+|\/)/.test(firstWordOfLine(stream)) || - (!stream.string.match(/^-?[a-z][\w-\.\[\]\'\"]*\s*=/) && - wordIsTag(firstWordOfLine(stream)))) { - return pushContext(state, stream, "block"); - } - if (stream.string.match(/^[\$-]?[a-z][\w-\.\[\]\'\"]*\s*=/) || - stream.string.match(/^\s*(\(|\)|[0-9])/) || - stream.string.match(/^\s+[a-z][\w-]*\(/i) || - stream.string.match(/^\s+[\$-]?[a-z]/i)) { - return pushContext(state, stream, "block", 0); - } - if (endOfLine(stream)) return pushContext(state, stream, "block"); - else return pushContext(state, stream, "block", 0); - } - if (type && type.charAt(0) == "@" && wordIsProperty(stream.current().slice(1))) { - override = "variable-2"; - } - if (type == "word") { - var word = stream.current(); - override = wordAsValue(word); - if (override == "tag" && tagVariablesRegexp.test(word)) { - override = "variable-2"; - } - if (override == "property" || word == "to") override = "atom"; - } - if (type == "variable-name") { - return pushContext(state, stream, "variableName"); - } - if (typeIsPseudo(type, stream)) { - return pushContext(state, stream, "pseudo"); - } - return state.context.type; - }; - - - /** - * Vendor prefixes - */ - states.vendorPrefixes = function(type, stream, state) { - if (type == "word") { - override = "property"; - return pushContext(state, stream, "block", 0); - } - return popContext(state); - }; - - - /** - * Pseudo - */ - states.pseudo = function(type, stream, state) { - if (!wordIsProperty(firstWordOfLine(stream.string))) { - stream.match(/^[a-z-]+/); - override = "variable-3"; - if (endOfLine(stream)) return pushContext(state, stream, "block"); - return popContext(state); - } - return popAndPass(type, stream, state); - }; - - - /** - * atBlock - */ - states.atBlock = function(type, stream, state) { - if (type == "(") return pushContext(state, stream, "atBlock_parens"); - if (typeIsBlock(type, stream, state)) { - return pushContext(state, stream, "block"); - } - if (typeIsInterpolation(type, stream)) { - return pushContext(state, stream, "interpolation"); - } - if (type == "word") { - var word = stream.current().toLowerCase(); - if (/^(only|not|and|or)$/.test(word)) - override = "keyword"; - else if (documentTypes.hasOwnProperty(word)) - override = "tag"; - else if (mediaTypes.hasOwnProperty(word)) - override = "attribute"; - else if (mediaFeatures.hasOwnProperty(word)) - override = "property"; - else if (nonStandardPropertyKeywords.hasOwnProperty(word)) - override = "string-2"; - else override = wordAsValue(stream.current()); - if (override == "tag" && endOfLine(stream)) { - return pushContext(state, stream, "block"); - } - } - if (type == "operator" && /^(not|and|or)$/.test(stream.current())) { - override = "keyword"; - } - return state.context.type; - }; - - states.atBlock_parens = function(type, stream, state) { - if (type == "{" || type == "}") return state.context.type; - if (type == ")") { - if (endOfLine(stream)) return pushContext(state, stream, "block"); - else return pushContext(state, stream, "atBlock"); - } - if (type == "word") { - var word = stream.current().toLowerCase(); - override = wordAsValue(word); - if (/^(max|min)/.test(word)) override = "property"; - if (override == "tag") { - tagVariablesRegexp.test(word) ? override = "variable-2" : override = "atom"; - } - return state.context.type; - } - return states.atBlock(type, stream, state); - }; - - - /** - * Keyframes - */ - states.keyframes = function(type, stream, state) { - if (stream.indentation() == "0" && ((type == "}" && startOfLine(stream)) || type == "]" || type == "hash" - || type == "qualifier" || wordIsTag(stream.current()))) { - return popAndPass(type, stream, state); - } - if (type == "{") return pushContext(state, stream, "keyframes"); - if (type == "}") { - if (startOfLine(stream)) return popContext(state, true); - else return pushContext(state, stream, "keyframes"); - } - if (type == "unit" && /^[0-9]+\%$/.test(stream.current())) { - return pushContext(state, stream, "keyframes"); - } - if (type == "word") { - override = wordAsValue(stream.current()); - if (override == "block-keyword") { - override = "keyword"; - return pushContext(state, stream, "keyframes"); - } - } - if (/@(font-face|media|supports|(-moz-)?document)/.test(type)) { - return pushContext(state, stream, endOfLine(stream) ? "block" : "atBlock"); - } - if (type == "mixin") { - return pushContext(state, stream, "block", 0); - } - return state.context.type; - }; - - - /** - * Interpolation - */ - states.interpolation = function(type, stream, state) { - if (type == "{") popContext(state) && pushContext(state, stream, "block"); - if (type == "}") { - if (stream.string.match(/^\s*(\.|#|:|\[|\*|&|>|~|\+|\/)/i) || - (stream.string.match(/^\s*[a-z]/i) && wordIsTag(firstWordOfLine(stream)))) { - return pushContext(state, stream, "block"); - } - if (!stream.string.match(/^(\{|\s*\&)/) || - stream.match(/\s*[\w-]/,false)) { - return pushContext(state, stream, "block", 0); - } - return pushContext(state, stream, "block"); - } - if (type == "variable-name") { - return pushContext(state, stream, "variableName", 0); - } - if (type == "word") { - override = wordAsValue(stream.current()); - if (override == "tag") override = "atom"; - } - return state.context.type; - }; - - - /** - * Extend/s - */ - states.extend = function(type, stream, state) { - if (type == "[" || type == "=") return "extend"; - if (type == "]") return popContext(state); - if (type == "word") { - override = wordAsValue(stream.current()); - return "extend"; - } - return popContext(state); - }; - - - /** - * Variable name - */ - states.variableName = function(type, stream, state) { - if (type == "string" || type == "[" || type == "]" || stream.current().match(/^(\.|\$)/)) { - if (stream.current().match(/^\.[\w-]+/i)) override = "variable-2"; - return "variableName"; - } - return popAndPass(type, stream, state); - }; - - - return { - startState: function(base) { - return { - tokenize: null, - state: "block", - context: new Context("block", base || 0, null) - }; - }, - token: function(stream, state) { - if (!state.tokenize && stream.eatSpace()) return null; - style = (state.tokenize || tokenBase)(stream, state); - if (style && typeof style == "object") { - type = style[1]; - style = style[0]; - } - override = style; - state.state = states[state.state](type, stream, state); - return override; - }, - indent: function(state, textAfter, line) { - - var cx = state.context, - ch = textAfter && textAfter.charAt(0), - indent = cx.indent, - lineFirstWord = firstWordOfLine(textAfter), - lineIndent = line.length - line.replace(/^\s*/, "").length, - prevLineFirstWord = state.context.prev ? state.context.prev.line.firstWord : "", - prevLineIndent = state.context.prev ? state.context.prev.line.indent : lineIndent; - - if (cx.prev && - (ch == "}" && (cx.type == "block" || cx.type == "atBlock" || cx.type == "keyframes") || - ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") || - ch == "{" && (cx.type == "at"))) { - indent = cx.indent - indentUnit; - cx = cx.prev; - } else if (!(/(\})/.test(ch))) { - if (/@|\$|\d/.test(ch) || - /^\{/.test(textAfter) || -/^\s*\/(\/|\*)/.test(textAfter) || - /^\s*\/\*/.test(prevLineFirstWord) || - /^\s*[\w-\.\[\]\'\"]+\s*(\?|:|\+)?=/i.test(textAfter) || -/^(\+|-)?[a-z][\w-]*\(/i.test(textAfter) || -/^return/.test(textAfter) || - wordIsBlock(lineFirstWord)) { - indent = lineIndent; - } else if (/(\.|#|:|\[|\*|&|>|~|\+|\/)/.test(ch) || wordIsTag(lineFirstWord)) { - if (/\,\s*$/.test(prevLineFirstWord)) { - indent = prevLineIndent; - } else if (/^\s+/.test(line) && (/(\.|#|:|\[|\*|&|>|~|\+|\/)/.test(prevLineFirstWord) || wordIsTag(prevLineFirstWord))) { - indent = lineIndent <= prevLineIndent ? prevLineIndent : prevLineIndent + indentUnit; - } else { - indent = lineIndent; - } - } else if (!/,\s*$/.test(line) && (wordIsVendorPrefix(lineFirstWord) || wordIsProperty(lineFirstWord))) { - if (wordIsBlock(prevLineFirstWord)) { - indent = lineIndent <= prevLineIndent ? prevLineIndent : prevLineIndent + indentUnit; - } else if (/^\{/.test(prevLineFirstWord)) { - indent = lineIndent <= prevLineIndent ? lineIndent : prevLineIndent + indentUnit; - } else if (wordIsVendorPrefix(prevLineFirstWord) || wordIsProperty(prevLineFirstWord)) { - indent = lineIndent >= prevLineIndent ? prevLineIndent : lineIndent; - } else if (/^(\.|#|:|\[|\*|&|@|\+|\-|>|~|\/)/.test(prevLineFirstWord) || - /=\s*$/.test(prevLineFirstWord) || - wordIsTag(prevLineFirstWord) || - /^\$[\w-\.\[\]\'\"]/.test(prevLineFirstWord)) { - indent = prevLineIndent + indentUnit; - } else { - indent = lineIndent; - } - } - } - return indent; - }, - electricChars: "}", - lineComment: "//", - fold: "indent" - }; - }); - - // developer.mozilla.org/en-US/docs/Web/HTML/Element - var tagKeywords_ = ["a","abbr","address","area","article","aside","audio", "b", "base","bdi", "bdo","bgsound","blockquote","body","br","button","canvas","caption","cite", "code","col","colgroup","data","datalist","dd","del","details","dfn","div", "dl","dt","em","embed","fieldset","figcaption","figure","footer","form","h1", "h2","h3","h4","h5","h6","head","header","hgroup","hr","html","i","iframe", "img","input","ins","kbd","keygen","label","legend","li","link","main","map", "mark","marquee","menu","menuitem","meta","meter","nav","nobr","noframes", "noscript","object","ol","optgroup","option","output","p","param","pre", "progress","q","rp","rt","ruby","s","samp","script","section","select", "small","source","span","strong","style","sub","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","track", "u","ul","var","video"]; - - // github.com/codemirror/CodeMirror/blob/master/mode/css/css.js - var documentTypes_ = ["domain", "regexp", "url", "url-prefix"]; - var mediaTypes_ = ["all","aural","braille","handheld","print","projection","screen","tty","tv","embossed"]; - var mediaFeatures_ = ["width","min-width","max-width","height","min-height","max-height","device-width","min-device-width","max-device-width","device-height","min-device-height","max-device-height","aspect-ratio","min-aspect-ratio","max-aspect-ratio","device-aspect-ratio","min-device-aspect-ratio","max-device-aspect-ratio","color","min-color","max-color","color-index","min-color-index","max-color-index","monochrome","min-monochrome","max-monochrome","resolution","min-resolution","max-resolution","scan","grid"]; - var propertyKeywords_ = ["align-content","align-items","align-self","alignment-adjust","alignment-baseline","anchor-point","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","appearance","azimuth","backface-visibility","background","background-attachment","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","baseline-shift","binding","bleed","bookmark-label","bookmark-level","bookmark-state","bookmark-target","border","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","clear","clip","color","color-profile","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","content","counter-increment","counter-reset","crop","cue","cue-after","cue-before","cursor","direction","display","dominant-baseline","drop-initial-after-adjust","drop-initial-after-align","drop-initial-before-adjust","drop-initial-before-align","drop-initial-size","drop-initial-value","elevation","empty-cells","fit","fit-position","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","float-offset","flow-from","flow-into","font","font-feature-settings","font-family","font-kerning","font-language-override","font-size","font-size-adjust","font-stretch","font-style","font-synthesis","font-variant","font-variant-alternates","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position","font-weight","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-position","grid-auto-rows","grid-column","grid-column-end","grid-column-start","grid-row","grid-row-end","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphens","icon","image-orientation","image-rendering","image-resolution","inline-box-align","justify-content","left","letter-spacing","line-break","line-height","line-stacking","line-stacking-ruby","line-stacking-shift","line-stacking-strategy","list-style","list-style-image","list-style-position","list-style-type","margin","margin-bottom","margin-left","margin-right","margin-top","marker-offset","marks","marquee-direction","marquee-loop","marquee-play-count","marquee-speed","marquee-style","max-height","max-width","min-height","min-width","move-to","nav-down","nav-index","nav-left","nav-right","nav-up","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-style","overflow-wrap","overflow-x","overflow-y","padding","padding-bottom","padding-left","padding-right","padding-top","page","page-break-after","page-break-before","page-break-inside","page-policy","pause","pause-after","pause-before","perspective","perspective-origin","pitch","pitch-range","play-during","position","presentation-level","punctuation-trim","quotes","region-break-after","region-break-before","region-break-inside","region-fragment","rendering-intent","resize","rest","rest-after","rest-before","richness","right","rotation","rotation-point","ruby-align","ruby-overhang","ruby-position","ruby-span","shape-image-threshold","shape-inside","shape-margin","shape-outside","size","speak","speak-as","speak-header","speak-numeral","speak-punctuation","speech-rate","stress","string-set","tab-size","table-layout","target","target-name","target-new","target-position","text-align","text-align-last","text-decoration","text-decoration-color","text-decoration-line","text-decoration-skip","text-decoration-style","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-height","text-indent","text-justify","text-outline","text-overflow","text-shadow","text-size-adjust","text-space-collapse","text-transform","text-underline-position","text-wrap","top","transform","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vertical-align","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","volume","white-space","widows","width","will-change","word-break","word-spacing","word-wrap","z-index","clip-path","clip-rule","mask","enable-background","filter","flood-color","flood-opacity","lighting-color","stop-color","stop-opacity","pointer-events","color-interpolation","color-interpolation-filters","color-rendering","fill","fill-opacity","fill-rule","image-rendering","marker","marker-end","marker-mid","marker-start","shape-rendering","stroke","stroke-dasharray","stroke-dashoffset","stroke-linecap","stroke-linejoin","stroke-miterlimit","stroke-opacity","stroke-width","text-rendering","baseline-shift","dominant-baseline","glyph-orientation-horizontal","glyph-orientation-vertical","text-anchor","writing-mode","font-smoothing","osx-font-smoothing"]; - var nonStandardPropertyKeywords_ = ["scrollbar-arrow-color","scrollbar-base-color","scrollbar-dark-shadow-color","scrollbar-face-color","scrollbar-highlight-color","scrollbar-shadow-color","scrollbar-3d-light-color","scrollbar-track-color","shape-inside","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","zoom"]; - var fontProperties_ = ["font-family","src","unicode-range","font-variant","font-feature-settings","font-stretch","font-weight","font-style"]; - var colorKeywords_ = ["aliceblue","antiquewhite","aqua","aquamarine","azure","beige","bisque","black","blanchedalmond","blue","blueviolet","brown","burlywood","cadetblue","chartreuse","chocolate","coral","cornflowerblue","cornsilk","crimson","cyan","darkblue","darkcyan","darkgoldenrod","darkgray","darkgreen","darkkhaki","darkmagenta","darkolivegreen","darkorange","darkorchid","darkred","darksalmon","darkseagreen","darkslateblue","darkslategray","darkturquoise","darkviolet","deeppink","deepskyblue","dimgray","dodgerblue","firebrick","floralwhite","forestgreen","fuchsia","gainsboro","ghostwhite","gold","goldenrod","gray","grey","green","greenyellow","honeydew","hotpink","indianred","indigo","ivory","khaki","lavender","lavenderblush","lawngreen","lemonchiffon","lightblue","lightcoral","lightcyan","lightgoldenrodyellow","lightgray","lightgreen","lightpink","lightsalmon","lightseagreen","lightskyblue","lightslategray","lightsteelblue","lightyellow","lime","limegreen","linen","magenta","maroon","mediumaquamarine","mediumblue","mediumorchid","mediumpurple","mediumseagreen","mediumslateblue","mediumspringgreen","mediumturquoise","mediumvioletred","midnightblue","mintcream","mistyrose","moccasin","navajowhite","navy","oldlace","olive","olivedrab","orange","orangered","orchid","palegoldenrod","palegreen","paleturquoise","palevioletred","papayawhip","peachpuff","peru","pink","plum","powderblue","purple","rebeccapurple","red","rosybrown","royalblue","saddlebrown","salmon","sandybrown","seagreen","seashell","sienna","silver","skyblue","slateblue","slategray","snow","springgreen","steelblue","tan","teal","thistle","tomato","turquoise","violet","wheat","white","whitesmoke","yellow","yellowgreen"]; - var valueKeywords_ = ["above","absolute","activeborder","additive","activecaption","afar","after-white-space","ahead","alias","all","all-scroll","alphabetic","alternate","always","amharic","amharic-abegede","antialiased","appworkspace","arabic-indic","armenian","asterisks","attr","auto","avoid","avoid-column","avoid-page","avoid-region","background","backwards","baseline","below","bidi-override","binary","bengali","blink","block","block-axis","bold","bolder","border","border-box","both","bottom","break","break-all","break-word","bullets","button","button-bevel","buttonface","buttonhighlight","buttonshadow","buttontext","calc","cambodian","capitalize","caps-lock-indicator","caption","captiontext","caret","cell","center","checkbox","circle","cjk-decimal","cjk-earthly-branch","cjk-heavenly-stem","cjk-ideographic","clear","clip","close-quote","col-resize","collapse","column","compact","condensed","contain","content","contents","content-box","context-menu","continuous","copy","counter","counters","cover","crop","cross","crosshair","currentcolor","cursive","cyclic","dashed","decimal","decimal-leading-zero","default","default-button","destination-atop","destination-in","destination-out","destination-over","devanagari","disc","discard","disclosure-closed","disclosure-open","document","dot-dash","dot-dot-dash","dotted","double","down","e-resize","ease","ease-in","ease-in-out","ease-out","element","ellipse","ellipsis","embed","end","ethiopic","ethiopic-abegede","ethiopic-abegede-am-et","ethiopic-abegede-gez","ethiopic-abegede-ti-er","ethiopic-abegede-ti-et","ethiopic-halehame-aa-er","ethiopic-halehame-aa-et","ethiopic-halehame-am-et","ethiopic-halehame-gez","ethiopic-halehame-om-et","ethiopic-halehame-sid-et","ethiopic-halehame-so-et","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","ethiopic-halehame-tig","ethiopic-numeric","ew-resize","expanded","extends","extra-condensed","extra-expanded","fantasy","fast","fill","fixed","flat","flex","footnotes","forwards","from","geometricPrecision","georgian","graytext","groove","gujarati","gurmukhi","hand","hangul","hangul-consonant","hebrew","help","hidden","hide","higher","highlight","highlighttext","hiragana","hiragana-iroha","horizontal","hsl","hsla","icon","ignore","inactiveborder","inactivecaption","inactivecaptiontext","infinite","infobackground","infotext","inherit","initial","inline","inline-axis","inline-block","inline-flex","inline-table","inset","inside","intrinsic","invert","italic","japanese-formal","japanese-informal","justify","kannada","katakana","katakana-iroha","keep-all","khmer","korean-hangul-formal","korean-hanja-formal","korean-hanja-informal","landscape","lao","large","larger","left","level","lighter","line-through","linear","linear-gradient","lines","list-item","listbox","listitem","local","logical","loud","lower","lower-alpha","lower-armenian","lower-greek","lower-hexadecimal","lower-latin","lower-norwegian","lower-roman","lowercase","ltr","malayalam","match","matrix","matrix3d","media-controls-background","media-current-time-display","media-fullscreen-button","media-mute-button","media-play-button","media-return-to-realtime-button","media-rewind-button","media-seek-back-button","media-seek-forward-button","media-slider","media-sliderthumb","media-time-remaining-display","media-volume-slider","media-volume-slider-container","media-volume-sliderthumb","medium","menu","menulist","menulist-button","menulist-text","menulist-textfield","menutext","message-box","middle","min-intrinsic","mix","mongolian","monospace","move","multiple","myanmar","n-resize","narrower","ne-resize","nesw-resize","no-close-quote","no-drop","no-open-quote","no-repeat","none","normal","not-allowed","nowrap","ns-resize","numbers","numeric","nw-resize","nwse-resize","oblique","octal","open-quote","optimizeLegibility","optimizeSpeed","oriya","oromo","outset","outside","outside-shape","overlay","overline","padding","padding-box","painted","page","paused","persian","perspective","plus-darker","plus-lighter","pointer","polygon","portrait","pre","pre-line","pre-wrap","preserve-3d","progress","push-button","radial-gradient","radio","read-only","read-write","read-write-plaintext-only","rectangle","region","relative","repeat","repeating-linear-gradient","repeating-radial-gradient","repeat-x","repeat-y","reset","reverse","rgb","rgba","ridge","right","rotate","rotate3d","rotateX","rotateY","rotateZ","round","row-resize","rtl","run-in","running","s-resize","sans-serif","scale","scale3d","scaleX","scaleY","scaleZ","scroll","scrollbar","scroll-position","se-resize","searchfield","searchfield-cancel-button","searchfield-decoration","searchfield-results-button","searchfield-results-decoration","semi-condensed","semi-expanded","separate","serif","show","sidama","simp-chinese-formal","simp-chinese-informal","single","skew","skewX","skewY","skip-white-space","slide","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","slow","small","small-caps","small-caption","smaller","solid","somali","source-atop","source-in","source-out","source-over","space","spell-out","square","square-button","start","static","status-bar","stretch","stroke","sub","subpixel-antialiased","super","sw-resize","symbolic","symbols","table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row","table-row-group","tamil","telugu","text","text-bottom","text-top","textarea","textfield","thai","thick","thin","threeddarkshadow","threedface","threedhighlight","threedlightshadow","threedshadow","tibetan","tigre","tigrinya-er","tigrinya-er-abegede","tigrinya-et","tigrinya-et-abegede","to","top","trad-chinese-formal","trad-chinese-informal","translate","translate3d","translateX","translateY","translateZ","transparent","ultra-condensed","ultra-expanded","underline","up","upper-alpha","upper-armenian","upper-greek","upper-hexadecimal","upper-latin","upper-norwegian","upper-roman","uppercase","urdu","url","var","vertical","vertical-text","visible","visibleFill","visiblePainted","visibleStroke","visual","w-resize","wait","wave","wider","window","windowframe","windowtext","words","x-large","x-small","xor","xx-large","xx-small","bicubic","optimizespeed","grayscale","row","row-reverse","wrap","wrap-reverse","column-reverse","flex-start","flex-end","space-between","space-around", "unset"]; - - var wordOperatorKeywords_ = ["in","and","or","not","is not","is a","is","isnt","defined","if unless"], - blockKeywords_ = ["for","if","else","unless", "from", "to"], - commonAtoms_ = ["null","true","false","href","title","type","not-allowed","readonly","disabled"], - commonDef_ = ["@font-face", "@keyframes", "@media", "@viewport", "@page", "@host", "@supports", "@block", "@css"]; - - var hintWords = tagKeywords_.concat(documentTypes_,mediaTypes_,mediaFeatures_, - propertyKeywords_,nonStandardPropertyKeywords_, - colorKeywords_,valueKeywords_,fontProperties_, - wordOperatorKeywords_,blockKeywords_, - commonAtoms_,commonDef_); - - function wordRegexp(words) { - words = words.sort(function(a,b){return b > a;}); - return new RegExp("^((" + words.join(")|(") + "))\\b"); - } - - function keySet(array) { - var keys = {}; - for (var i = 0; i < array.length; ++i) keys[array[i]] = true; - return keys; - } - - function escapeRegExp(text) { - return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); - } - - CodeMirror.registerHelper("hintWords", "stylus", hintWords); - CodeMirror.defineMIME("text/x-styl", "stylus"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/swift/index.html b/backend/_pv_1_3_5/static/codemirror/mode/swift/index.html deleted file mode 100755 index 109f3fdb0..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/swift/index.html +++ /dev/null @@ -1,88 +0,0 @@ - - -CodeMirror: Swift mode - - - - - - - - - - -
    -

    Swift mode

    -
    - - - -

    A simple mode for Swift

    - -

    MIME types defined: text/x-swift (Swift code)

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/swift/swift.js b/backend/_pv_1_3_5/static/codemirror/mode/swift/swift.js deleted file mode 100755 index 43ab7c8fb..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/swift/swift.js +++ /dev/null @@ -1,210 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Swift mode created by Michael Kaminsky https://github.com/mkaminsky11 - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") - mod(require("../../lib/codemirror")) - else if (typeof define == "function" && define.amd) - define(["../../lib/codemirror"], mod) - else - mod(CodeMirror) -})(function(CodeMirror) { - "use strict" - - function wordSet(words) { - var set = {} - for (var i = 0; i < words.length; i++) set[words[i]] = true - return set - } - - var keywords = wordSet(["_","var","let","class","enum","extension","import","protocol","struct","func","typealias","associatedtype", - "open","public","internal","fileprivate","private","deinit","init","new","override","self","subscript","super", - "convenience","dynamic","final","indirect","lazy","required","static","unowned","unowned(safe)","unowned(unsafe)","weak","as","is", - "break","case","continue","default","else","fallthrough","for","guard","if","in","repeat","switch","where","while", - "defer","return","inout","mutating","nonmutating","catch","do","rethrows","throw","throws","try","didSet","get","set","willSet", - "assignment","associativity","infix","left","none","operator","postfix","precedence","precedencegroup","prefix","right", - "Any","AnyObject","Type","dynamicType","Self","Protocol","__COLUMN__","__FILE__","__FUNCTION__","__LINE__"]) - var definingKeywords = wordSet(["var","let","class","enum","extension","import","protocol","struct","func","typealias","associatedtype","for"]) - var atoms = wordSet(["true","false","nil","self","super","_"]) - var types = wordSet(["Array","Bool","Character","Dictionary","Double","Float","Int","Int8","Int16","Int32","Int64","Never","Optional","Set","String", - "UInt8","UInt16","UInt32","UInt64","Void"]) - var operators = "+-/*%=|&<>~^?!" - var punc = ":;,.(){}[]" - var binary = /^\-?0b[01][01_]*/ - var octal = /^\-?0o[0-7][0-7_]*/ - var hexadecimal = /^\-?0x[\dA-Fa-f][\dA-Fa-f_]*(?:(?:\.[\dA-Fa-f][\dA-Fa-f_]*)?[Pp]\-?\d[\d_]*)?/ - var decimal = /^\-?\d[\d_]*(?:\.\d[\d_]*)?(?:[Ee]\-?\d[\d_]*)?/ - var identifier = /^\$\d+|(`?)[_A-Za-z][_A-Za-z$0-9]*\1/ - var property = /^\.(?:\$\d+|(`?)[_A-Za-z][_A-Za-z$0-9]*\1)/ - var instruction = /^\#[A-Za-z]+/ - var attribute = /^@(?:\$\d+|(`?)[_A-Za-z][_A-Za-z$0-9]*\1)/ - //var regexp = /^\/(?!\s)(?:\/\/)?(?:\\.|[^\/])+\// - - function tokenBase(stream, state, prev) { - if (stream.sol()) state.indented = stream.indentation() - if (stream.eatSpace()) return null - - var ch = stream.peek() - if (ch == "/") { - if (stream.match("//")) { - stream.skipToEnd() - return "comment" - } - if (stream.match("/*")) { - state.tokenize.push(tokenComment) - return tokenComment(stream, state) - } - } - if (stream.match(instruction)) return "builtin" - if (stream.match(attribute)) return "attribute" - if (stream.match(binary)) return "number" - if (stream.match(octal)) return "number" - if (stream.match(hexadecimal)) return "number" - if (stream.match(decimal)) return "number" - if (stream.match(property)) return "property" - if (operators.indexOf(ch) > -1) { - stream.next() - return "operator" - } - if (punc.indexOf(ch) > -1) { - stream.next() - stream.match("..") - return "punctuation" - } - if (ch == '"' || ch == "'") { - stream.next() - var tokenize = tokenString(ch) - state.tokenize.push(tokenize) - return tokenize(stream, state) - } - - if (stream.match(identifier)) { - var ident = stream.current() - if (types.hasOwnProperty(ident)) return "variable-2" - if (atoms.hasOwnProperty(ident)) return "atom" - if (keywords.hasOwnProperty(ident)) { - if (definingKeywords.hasOwnProperty(ident)) - state.prev = "define" - return "keyword" - } - if (prev == "define") return "def" - return "variable" - } - - stream.next() - return null - } - - function tokenUntilClosingParen() { - var depth = 0 - return function(stream, state, prev) { - var inner = tokenBase(stream, state, prev) - if (inner == "punctuation") { - if (stream.current() == "(") ++depth - else if (stream.current() == ")") { - if (depth == 0) { - stream.backUp(1) - state.tokenize.pop() - return state.tokenize[state.tokenize.length - 1](stream, state) - } - else --depth - } - } - return inner - } - } - - function tokenString(quote) { - return function(stream, state) { - var ch, escaped = false - while (ch = stream.next()) { - if (escaped) { - if (ch == "(") { - state.tokenize.push(tokenUntilClosingParen()) - return "string" - } - escaped = false - } else if (ch == quote) { - break - } else { - escaped = ch == "\\" - } - } - state.tokenize.pop() - return "string" - } - } - - function tokenComment(stream, state) { - stream.match(/^(?:[^*]|\*(?!\/))*/) - if (stream.match("*/")) state.tokenize.pop() - return "comment" - } - - function Context(prev, align, indented) { - this.prev = prev - this.align = align - this.indented = indented - } - - function pushContext(state, stream) { - var align = stream.match(/^\s*($|\/[\/\*])/, false) ? null : stream.column() + 1 - state.context = new Context(state.context, align, state.indented) - } - - function popContext(state) { - if (state.context) { - state.indented = state.context.indented - state.context = state.context.prev - } - } - - CodeMirror.defineMode("swift", function(config) { - return { - startState: function() { - return { - prev: null, - context: null, - indented: 0, - tokenize: [] - } - }, - - token: function(stream, state) { - var prev = state.prev - state.prev = null - var tokenize = state.tokenize[state.tokenize.length - 1] || tokenBase - var style = tokenize(stream, state, prev) - if (!style || style == "comment") state.prev = prev - else if (!state.prev) state.prev = style - - if (style == "punctuation") { - var bracket = /[\(\[\{]|([\]\)\}])/.exec(stream.current()) - if (bracket) (bracket[1] ? popContext : pushContext)(state, stream) - } - - return style - }, - - indent: function(state, textAfter) { - var cx = state.context - if (!cx) return 0 - var closing = /^[\]\}\)]/.test(textAfter) - if (cx.align != null) return cx.align - (closing ? 1 : 0) - return cx.indented + (closing ? 0 : config.indentUnit) - }, - - electricInput: /^\s*[\)\}\]]$/, - - lineComment: "//", - blockCommentStart: "/*", - blockCommentEnd: "*/", - fold: "brace", - closeBrackets: "()[]{}''\"\"``" - } - }) - - CodeMirror.defineMIME("text/x-swift","swift") -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/swift/test.js b/backend/_pv_1_3_5/static/codemirror/mode/swift/test.js deleted file mode 100755 index 786b89e29..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/swift/test.js +++ /dev/null @@ -1,149 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "swift"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - // Ensure all number types are properly represented. - MT("numbers", - "[keyword var] [def a] [operator =] [number 17]", - "[keyword var] [def b] [operator =] [number -0.5]", - "[keyword var] [def c] [operator =] [number 0.3456e-4]", - "[keyword var] [def d] [operator =] [number 345e2]", - "[keyword var] [def e] [operator =] [number 0o7324]", - "[keyword var] [def f] [operator =] [number 0b10010]", - "[keyword var] [def g] [operator =] [number -0x35ade]", - "[keyword var] [def h] [operator =] [number 0xaea.ep-13]", - "[keyword var] [def i] [operator =] [number 0x13ep6]"); - - // Variable/class/etc definition. - MT("definition", - "[keyword var] [def a] [operator =] [number 5]", - "[keyword let] [def b][punctuation :] [variable-2 Int] [operator =] [number 10]", - "[keyword class] [def C] [punctuation {] [punctuation }]", - "[keyword struct] [def D] [punctuation {] [punctuation }]", - "[keyword enum] [def E] [punctuation {] [punctuation }]", - "[keyword extension] [def F] [punctuation {] [punctuation }]", - "[keyword protocol] [def G] [punctuation {] [punctuation }]", - "[keyword func] [def h][punctuation ()] [punctuation {] [punctuation }]", - "[keyword import] [def Foundation]", - "[keyword typealias] [def NewString] [operator =] [variable-2 String]", - "[keyword associatedtype] [def I]", - "[keyword for] [def j] [keyword in] [number 0][punctuation ..][operator <][number 3] [punctuation {] [punctuation }]"); - - // Strings and string interpolation. - MT("strings", - "[keyword var] [def a][punctuation :] [variable-2 String] [operator =] [string \"test\"]", - "[keyword var] [def b][punctuation :] [variable-2 String] [operator =] [string \"\\(][variable a][string )\"]"); - - // Comments. - MT("comments", - "[comment // This is a comment]", - "[comment /* This is another comment */]", - "[keyword var] [def a] [operator =] [number 5] [comment // Third comment]"); - - // Atoms. - MT("atoms", - "[keyword class] [def FooClass] [punctuation {]", - " [keyword let] [def fooBool][punctuation :] [variable-2 Bool][operator ?]", - " [keyword let] [def fooInt][punctuation :] [variable-2 Int][operator ?]", - " [keyword func] [keyword init][punctuation (][variable fooBool][punctuation :] [variable-2 Bool][punctuation ,] [variable barBool][punctuation :] [variable-2 Bool][punctuation )] [punctuation {]", - " [atom super][property .init][punctuation ()]", - " [atom self][property .fooBool] [operator =] [variable fooBool]", - " [variable fooInt] [operator =] [atom nil]", - " [keyword if] [variable barBool] [operator ==] [atom true] [punctuation {]", - " [variable print][punctuation (][string \"True!\"][punctuation )]", - " [punctuation }] [keyword else] [keyword if] [variable barBool] [operator ==] [atom false] [punctuation {]", - " [keyword for] [atom _] [keyword in] [number 0][punctuation ...][number 5] [punctuation {]", - " [variable print][punctuation (][string \"False!\"][punctuation )]", - " [punctuation }]", - " [punctuation }]", - " [punctuation }]", - "[punctuation }]"); - - // Types. - MT("types", - "[keyword var] [def a] [operator =] [variable-2 Array][operator <][variable-2 Int][operator >]", - "[keyword var] [def b] [operator =] [variable-2 Set][operator <][variable-2 Bool][operator >]", - "[keyword var] [def c] [operator =] [variable-2 Dictionary][operator <][variable-2 String][punctuation ,][variable-2 Character][operator >]", - "[keyword var] [def d][punctuation :] [variable-2 Int64][operator ?] [operator =] [variable-2 Optional][punctuation (][number 8][punctuation )]", - "[keyword func] [def e][punctuation ()] [operator ->] [variable-2 Void] [punctuation {]", - " [keyword var] [def e1][punctuation :] [variable-2 Float] [operator =] [number 1.2]", - "[punctuation }]", - "[keyword func] [def f][punctuation ()] [operator ->] [variable-2 Never] [punctuation {]", - " [keyword var] [def f1][punctuation :] [variable-2 Double] [operator =] [number 2.4]", - "[punctuation }]"); - - // Operators. - MT("operators", - "[keyword var] [def a] [operator =] [number 1] [operator +] [number 2]", - "[keyword var] [def b] [operator =] [number 1] [operator -] [number 2]", - "[keyword var] [def c] [operator =] [number 1] [operator *] [number 2]", - "[keyword var] [def d] [operator =] [number 1] [operator /] [number 2]", - "[keyword var] [def e] [operator =] [number 1] [operator %] [number 2]", - "[keyword var] [def f] [operator =] [number 1] [operator |] [number 2]", - "[keyword var] [def g] [operator =] [number 1] [operator &] [number 2]", - "[keyword var] [def h] [operator =] [number 1] [operator <<] [number 2]", - "[keyword var] [def i] [operator =] [number 1] [operator >>] [number 2]", - "[keyword var] [def j] [operator =] [number 1] [operator ^] [number 2]", - "[keyword var] [def k] [operator =] [operator ~][number 1]", - "[keyword var] [def l] [operator =] [variable foo] [operator ?] [number 1] [punctuation :] [number 2]", - "[keyword var] [def m][punctuation :] [variable-2 Int] [operator =] [variable-2 Optional][punctuation (][number 8][punctuation )][operator !]"); - - // Punctuation. - MT("punctuation", - "[keyword let] [def a] [operator =] [number 1][punctuation ;] [keyword let] [def b] [operator =] [number 2]", - "[keyword let] [def testArr][punctuation :] [punctuation [[][variable-2 Int][punctuation ]]] [operator =] [punctuation [[][variable a][punctuation ,] [variable b][punctuation ]]]", - "[keyword for] [def i] [keyword in] [number 0][punctuation ..][operator <][variable testArr][property .count] [punctuation {]", - " [variable print][punctuation (][variable testArr][punctuation [[][variable i][punctuation ]])]", - "[punctuation }]"); - - // Identifiers. - MT("identifiers", - "[keyword let] [def abc] [operator =] [number 1]", - "[keyword let] [def ABC] [operator =] [number 2]", - "[keyword let] [def _123] [operator =] [number 3]", - "[keyword let] [def _$1$2$3] [operator =] [number 4]", - "[keyword let] [def A1$_c32_$_] [operator =] [number 5]", - "[keyword let] [def `var`] [operator =] [punctuation [[][number 1][punctuation ,] [number 2][punctuation ,] [number 3][punctuation ]]]", - "[keyword let] [def square$] [operator =] [variable `var`][property .map] [punctuation {][variable $0] [operator *] [variable $0][punctuation }]", - "$$ [number 1][variable a] $[atom _] [variable _$] [variable __] `[variable a] [variable b]`"); - - // Properties. - MT("properties", - "[variable print][punctuation (][variable foo][property .abc][punctuation )]", - "[variable print][punctuation (][variable foo][property .ABC][punctuation )]", - "[variable print][punctuation (][variable foo][property ._123][punctuation )]", - "[variable print][punctuation (][variable foo][property ._$1$2$3][punctuation )]", - "[variable print][punctuation (][variable foo][property .A1$_c32_$_][punctuation )]", - "[variable print][punctuation (][variable foo][property .`var`][punctuation )]", - "[variable print][punctuation (][variable foo][property .__][punctuation )]"); - - // Instructions or other things that start with #. - MT("instructions", - "[keyword if] [builtin #available][punctuation (][variable iOS] [number 9][punctuation ,] [operator *][punctuation )] [punctuation {}]", - "[variable print][punctuation (][builtin #file][punctuation ,] [builtin #function][punctuation )]", - "[variable print][punctuation (][builtin #line][punctuation ,] [builtin #column][punctuation )]", - "[builtin #if] [atom true]", - "[keyword import] [def A]", - "[builtin #elseif] [atom false]", - "[keyword import] [def B]", - "[builtin #endif]", - "[builtin #sourceLocation][punctuation (][variable file][punctuation :] [string \"file.swift\"][punctuation ,] [variable line][punctuation :] [number 2][punctuation )]"); - - // Attributes; things that start with @. - MT("attributes", - "[attribute @objc][punctuation (][variable objcFoo][punctuation :)]", - "[attribute @available][punctuation (][variable iOS][punctuation )]"); - - // Property/number edge case. - MT("property_number", - "[variable print][punctuation (][variable foo][property ._123][punctuation )]", - "[variable print][punctuation (]") - - // TODO: correctly identify when multiple variables are being declared - // by use of a comma-separated list. - // TODO: correctly identify when variables are being declared in a tuple. - // TODO: identify protocols as types when used before an extension? -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/tcl/index.html b/backend/_pv_1_3_5/static/codemirror/mode/tcl/index.html deleted file mode 100755 index ce4ad3423..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/tcl/index.html +++ /dev/null @@ -1,142 +0,0 @@ - - -CodeMirror: Tcl mode - - - - - - - - - - -
    -

    Tcl mode

    -
    - - -

    MIME types defined: text/x-tcl.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/tcl/tcl.js b/backend/_pv_1_3_5/static/codemirror/mode/tcl/tcl.js deleted file mode 100755 index 8c76d52ca..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/tcl/tcl.js +++ /dev/null @@ -1,139 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -//tcl mode by Ford_Lawnmower :: Based on Velocity mode by Steve O'Hara - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("tcl", function() { - function parseWords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - var keywords = parseWords("Tcl safe after append array auto_execok auto_import auto_load " + - "auto_mkindex auto_mkindex_old auto_qualify auto_reset bgerror " + - "binary break catch cd close concat continue dde eof encoding error " + - "eval exec exit expr fblocked fconfigure fcopy file fileevent filename " + - "filename flush for foreach format gets glob global history http if " + - "incr info interp join lappend lindex linsert list llength load lrange " + - "lreplace lsearch lset lsort memory msgcat namespace open package parray " + - "pid pkg::create pkg_mkIndex proc puts pwd re_syntax read regex regexp " + - "registry regsub rename resource return scan seek set socket source split " + - "string subst switch tcl_endOfWord tcl_findLibrary tcl_startOfNextWord " + - "tcl_wordBreakAfter tcl_startOfPreviousWord tcl_wordBreakBefore tcltest " + - "tclvars tell time trace unknown unset update uplevel upvar variable " + - "vwait"); - var functions = parseWords("if elseif else and not or eq ne in ni for foreach while switch"); - var isOperatorChar = /[+\-*&%=<>!?^\/\|]/; - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - function tokenBase(stream, state) { - var beforeParams = state.beforeParams; - state.beforeParams = false; - var ch = stream.next(); - if ((ch == '"' || ch == "'") && state.inParams) { - return chain(stream, state, tokenString(ch)); - } else if (/[\[\]{}\(\),;\.]/.test(ch)) { - if (ch == "(" && beforeParams) state.inParams = true; - else if (ch == ")") state.inParams = false; - return null; - } else if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } else if (ch == "#") { - if (stream.eat("*")) - return chain(stream, state, tokenComment); - if (ch == "#" && stream.match(/ *\[ *\[/)) - return chain(stream, state, tokenUnparsed); - stream.skipToEnd(); - return "comment"; - } else if (ch == '"') { - stream.skipTo(/"/); - return "comment"; - } else if (ch == "$") { - stream.eatWhile(/[$_a-z0-9A-Z\.{:]/); - stream.eatWhile(/}/); - state.beforeParams = true; - return "builtin"; - } else if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "comment"; - } else { - stream.eatWhile(/[\w\$_{}\xa1-\uffff]/); - var word = stream.current().toLowerCase(); - if (keywords && keywords.propertyIsEnumerable(word)) - return "keyword"; - if (functions && functions.propertyIsEnumerable(word)) { - state.beforeParams = true; - return "keyword"; - } - return null; - } - } - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) { - end = true; - break; - } - escaped = !escaped && next == "\\"; - } - if (end) state.tokenize = tokenBase; - return "string"; - }; - } - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "#" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - function tokenUnparsed(stream, state) { - var maybeEnd = 0, ch; - while (ch = stream.next()) { - if (ch == "#" && maybeEnd == 2) { - state.tokenize = tokenBase; - break; - } - if (ch == "]") - maybeEnd++; - else if (ch != " ") - maybeEnd = 0; - } - return "meta"; - } - return { - startState: function() { - return { - tokenize: tokenBase, - beforeParams: false, - inParams: false - }; - }, - token: function(stream, state) { - if (stream.eatSpace()) return null; - return state.tokenize(stream, state); - } - }; -}); -CodeMirror.defineMIME("text/x-tcl", "tcl"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/textile/index.html b/backend/_pv_1_3_5/static/codemirror/mode/textile/index.html deleted file mode 100755 index 42b156b1e..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/textile/index.html +++ /dev/null @@ -1,191 +0,0 @@ - - -CodeMirror: Textile mode - - - - - - - - - -
    -

    Textile mode

    -
    - - -

    MIME types defined: text/x-textile.

    - -

    Parsing/Highlighting Tests: normal, verbose.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/textile/test.js b/backend/_pv_1_3_5/static/codemirror/mode/textile/test.js deleted file mode 100755 index 49cdaf9c9..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/textile/test.js +++ /dev/null @@ -1,417 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({tabSize: 4}, 'textile'); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT('simpleParagraphs', - 'Some text.', - '', - 'Some more text.'); - - /* - * Phrase Modifiers - */ - - MT('em', - 'foo [em _bar_]'); - - MT('emBoogus', - 'code_mirror'); - - MT('strong', - 'foo [strong *bar*]'); - - MT('strongBogus', - '3 * 3 = 9'); - - MT('italic', - 'foo [em __bar__]'); - - MT('italicBogus', - 'code__mirror'); - - MT('bold', - 'foo [strong **bar**]'); - - MT('boldBogus', - '3 ** 3 = 27'); - - MT('simpleLink', - '[link "CodeMirror":http://codemirror.net]'); - - MT('referenceLink', - '[link "CodeMirror":code_mirror]', - 'Normal Text.', - '[link [[code_mirror]]http://codemirror.net]'); - - MT('footCite', - 'foo bar[qualifier [[1]]]'); - - MT('footCiteBogus', - 'foo bar[[1a2]]'); - - MT('special-characters', - 'Registered [tag (r)], ' + - 'Trademark [tag (tm)], and ' + - 'Copyright [tag (c)] 2008'); - - MT('cite', - "A book is [keyword ??The Count of Monte Cristo??] by Dumas."); - - MT('additionAndDeletion', - 'The news networks declared [negative -Al Gore-] ' + - '[positive +George W. Bush+] the winner in Florida.'); - - MT('subAndSup', - 'f(x, n) = log [builtin ~4~] x [builtin ^n^]'); - - MT('spanAndCode', - 'A [quote %span element%] and [atom @code element@]'); - - MT('spanBogus', - 'Percentage 25% is not a span.'); - - MT('citeBogus', - 'Question? is not a citation.'); - - MT('codeBogus', - 'user@example.com'); - - MT('subBogus', - '~username'); - - MT('supBogus', - 'foo ^ bar'); - - MT('deletionBogus', - '3 - 3 = 0'); - - MT('additionBogus', - '3 + 3 = 6'); - - MT('image', - 'An image: [string !http://www.example.com/image.png!]'); - - MT('imageWithAltText', - 'An image: [string !http://www.example.com/image.png (Alt Text)!]'); - - MT('imageWithUrl', - 'An image: [string !http://www.example.com/image.png!:http://www.example.com/]'); - - /* - * Headers - */ - - MT('h1', - '[header&header-1 h1. foo]'); - - MT('h2', - '[header&header-2 h2. foo]'); - - MT('h3', - '[header&header-3 h3. foo]'); - - MT('h4', - '[header&header-4 h4. foo]'); - - MT('h5', - '[header&header-5 h5. foo]'); - - MT('h6', - '[header&header-6 h6. foo]'); - - MT('h7Bogus', - 'h7. foo'); - - MT('multipleHeaders', - '[header&header-1 h1. Heading 1]', - '', - 'Some text.', - '', - '[header&header-2 h2. Heading 2]', - '', - 'More text.'); - - MT('h1inline', - '[header&header-1 h1. foo ][header&header-1&em _bar_][header&header-1 baz]'); - - /* - * Lists - */ - - MT('ul', - 'foo', - 'bar', - '', - '[variable-2 * foo]', - '[variable-2 * bar]'); - - MT('ulNoBlank', - 'foo', - 'bar', - '[variable-2 * foo]', - '[variable-2 * bar]'); - - MT('ol', - 'foo', - 'bar', - '', - '[variable-2 # foo]', - '[variable-2 # bar]'); - - MT('olNoBlank', - 'foo', - 'bar', - '[variable-2 # foo]', - '[variable-2 # bar]'); - - MT('ulFormatting', - '[variable-2 * ][variable-2&em _foo_][variable-2 bar]', - '[variable-2 * ][variable-2&strong *][variable-2&em&strong _foo_]' + - '[variable-2&strong *][variable-2 bar]', - '[variable-2 * ][variable-2&strong *foo*][variable-2 bar]'); - - MT('olFormatting', - '[variable-2 # ][variable-2&em _foo_][variable-2 bar]', - '[variable-2 # ][variable-2&strong *][variable-2&em&strong _foo_]' + - '[variable-2&strong *][variable-2 bar]', - '[variable-2 # ][variable-2&strong *foo*][variable-2 bar]'); - - MT('ulNested', - '[variable-2 * foo]', - '[variable-3 ** bar]', - '[keyword *** bar]', - '[variable-2 **** bar]', - '[variable-3 ** bar]'); - - MT('olNested', - '[variable-2 # foo]', - '[variable-3 ## bar]', - '[keyword ### bar]', - '[variable-2 #### bar]', - '[variable-3 ## bar]'); - - MT('ulNestedWithOl', - '[variable-2 * foo]', - '[variable-3 ## bar]', - '[keyword *** bar]', - '[variable-2 #### bar]', - '[variable-3 ** bar]'); - - MT('olNestedWithUl', - '[variable-2 # foo]', - '[variable-3 ** bar]', - '[keyword ### bar]', - '[variable-2 **** bar]', - '[variable-3 ## bar]'); - - MT('definitionList', - '[number - coffee := Hot ][number&em _and_][number black]', - '', - 'Normal text.'); - - MT('definitionListSpan', - '[number - coffee :=]', - '', - '[number Hot ][number&em _and_][number black =:]', - '', - 'Normal text.'); - - MT('boo', - '[number - dog := woof woof]', - '[number - cat := meow meow]', - '[number - whale :=]', - '[number Whale noises.]', - '', - '[number Also, ][number&em _splashing_][number . =:]'); - - /* - * Attributes - */ - - MT('divWithAttribute', - '[punctuation div][punctuation&attribute (#my-id)][punctuation . foo bar]'); - - MT('divWithAttributeAnd2emRightPadding', - '[punctuation div][punctuation&attribute (#my-id)((][punctuation . foo bar]'); - - MT('divWithClassAndId', - '[punctuation div][punctuation&attribute (my-class#my-id)][punctuation . foo bar]'); - - MT('paragraphWithCss', - 'p[attribute {color:red;}]. foo bar'); - - MT('paragraphNestedStyles', - 'p. [strong *foo ][strong&em _bar_][strong *]'); - - MT('paragraphWithLanguage', - 'p[attribute [[fr]]]. Parlez-vous français?'); - - MT('paragraphLeftAlign', - 'p[attribute <]. Left'); - - MT('paragraphRightAlign', - 'p[attribute >]. Right'); - - MT('paragraphRightAlign', - 'p[attribute =]. Center'); - - MT('paragraphJustified', - 'p[attribute <>]. Justified'); - - MT('paragraphWithLeftIndent1em', - 'p[attribute (]. Left'); - - MT('paragraphWithRightIndent1em', - 'p[attribute )]. Right'); - - MT('paragraphWithLeftIndent2em', - 'p[attribute ((]. Left'); - - MT('paragraphWithRightIndent2em', - 'p[attribute ))]. Right'); - - MT('paragraphWithLeftIndent3emRightIndent2em', - 'p[attribute ((())]. Right'); - - MT('divFormatting', - '[punctuation div. ][punctuation&strong *foo ]' + - '[punctuation&strong&em _bar_][punctuation&strong *]'); - - MT('phraseModifierAttributes', - 'p[attribute (my-class)]. This is a paragraph that has a class and' + - ' this [em _][em&attribute (#special-phrase)][em emphasized phrase_]' + - ' has an id.'); - - MT('linkWithClass', - '[link "(my-class). This is a link with class":http://redcloth.org]'); - - /* - * Layouts - */ - - MT('paragraphLayouts', - 'p. This is one paragraph.', - '', - 'p. This is another.'); - - MT('div', - '[punctuation div. foo bar]'); - - MT('pre', - '[operator pre. Text]'); - - MT('bq.', - '[bracket bq. foo bar]', - '', - 'Normal text.'); - - MT('footnote', - '[variable fn123. foo ][variable&strong *bar*]'); - - /* - * Spanning Layouts - */ - - MT('bq..ThenParagraph', - '[bracket bq.. foo bar]', - '', - '[bracket More quote.]', - 'p. Normal Text'); - - MT('bq..ThenH1', - '[bracket bq.. foo bar]', - '', - '[bracket More quote.]', - '[header&header-1 h1. Header Text]'); - - MT('bc..ThenParagraph', - '[atom bc.. # Some ruby code]', - '[atom obj = {foo: :bar}]', - '[atom puts obj]', - '', - '[atom obj[[:love]] = "*love*"]', - '[atom puts obj.love.upcase]', - '', - 'p. Normal text.'); - - MT('fn1..ThenParagraph', - '[variable fn1.. foo bar]', - '', - '[variable More.]', - 'p. Normal Text'); - - MT('pre..ThenParagraph', - '[operator pre.. foo bar]', - '', - '[operator More.]', - 'p. Normal Text'); - - /* - * Tables - */ - - MT('table', - '[variable-3&operator |_. name |_. age|]', - '[variable-3 |][variable-3&strong *Walter*][variable-3 | 5 |]', - '[variable-3 |Florence| 6 |]', - '', - 'p. Normal text.'); - - MT('tableWithAttributes', - '[variable-3&operator |_. name |_. age|]', - '[variable-3 |][variable-3&attribute /2.][variable-3 Jim |]', - '[variable-3 |][variable-3&attribute \\2{color: red}.][variable-3 Sam |]'); - - /* - * HTML - */ - - MT('html', - '[comment
    ]', - '[comment
    ]', - '', - '[header&header-1 h1. Welcome]', - '', - '[variable-2 * Item one]', - '[variable-2 * Item two]', - '', - '[comment Example]', - '', - '[comment
    ]', - '[comment
    ]'); - - MT('inlineHtml', - 'I can use HTML directly in my [comment Textile].'); - - /* - * No-Textile - */ - - MT('notextile', - '[string-2 notextile. *No* formatting]'); - - MT('notextileInline', - 'Use [string-2 ==*asterisks*==] for [strong *strong*] text.'); - - MT('notextileWithPre', - '[operator pre. *No* formatting]'); - - MT('notextileWithSpanningPre', - '[operator pre.. *No* formatting]', - '', - '[operator *No* formatting]'); - - /* Only toggling phrases between non-word chars. */ - - MT('phrase-in-word', - 'foo_bar_baz'); - - MT('phrase-non-word', - '[negative -x-] aaa-bbb ccc-ddd [negative -eee-] fff [negative -ggg-]'); - - MT('phrase-lone-dash', - 'foo - bar - baz'); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/textile/textile.js b/backend/_pv_1_3_5/static/codemirror/mode/textile/textile.js deleted file mode 100755 index a6f757658..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/textile/textile.js +++ /dev/null @@ -1,469 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") { // CommonJS - mod(require("../../lib/codemirror")); - } else if (typeof define == "function" && define.amd) { // AMD - define(["../../lib/codemirror"], mod); - } else { // Plain browser env - mod(CodeMirror); - } -})(function(CodeMirror) { - "use strict"; - - var TOKEN_STYLES = { - addition: "positive", - attributes: "attribute", - bold: "strong", - cite: "keyword", - code: "atom", - definitionList: "number", - deletion: "negative", - div: "punctuation", - em: "em", - footnote: "variable", - footCite: "qualifier", - header: "header", - html: "comment", - image: "string", - italic: "em", - link: "link", - linkDefinition: "link", - list1: "variable-2", - list2: "variable-3", - list3: "keyword", - notextile: "string-2", - pre: "operator", - p: "property", - quote: "bracket", - span: "quote", - specialChar: "tag", - strong: "strong", - sub: "builtin", - sup: "builtin", - table: "variable-3", - tableHeading: "operator" - }; - - function startNewLine(stream, state) { - state.mode = Modes.newLayout; - state.tableHeading = false; - - if (state.layoutType === "definitionList" && state.spanningLayout && - stream.match(RE("definitionListEnd"), false)) - state.spanningLayout = false; - } - - function handlePhraseModifier(stream, state, ch) { - if (ch === "_") { - if (stream.eat("_")) - return togglePhraseModifier(stream, state, "italic", /__/, 2); - else - return togglePhraseModifier(stream, state, "em", /_/, 1); - } - - if (ch === "*") { - if (stream.eat("*")) { - return togglePhraseModifier(stream, state, "bold", /\*\*/, 2); - } - return togglePhraseModifier(stream, state, "strong", /\*/, 1); - } - - if (ch === "[") { - if (stream.match(/\d+\]/)) state.footCite = true; - return tokenStyles(state); - } - - if (ch === "(") { - var spec = stream.match(/^(r|tm|c)\)/); - if (spec) - return tokenStylesWith(state, TOKEN_STYLES.specialChar); - } - - if (ch === "<" && stream.match(/(\w+)[^>]+>[^<]+<\/\1>/)) - return tokenStylesWith(state, TOKEN_STYLES.html); - - if (ch === "?" && stream.eat("?")) - return togglePhraseModifier(stream, state, "cite", /\?\?/, 2); - - if (ch === "=" && stream.eat("=")) - return togglePhraseModifier(stream, state, "notextile", /==/, 2); - - if (ch === "-" && !stream.eat("-")) - return togglePhraseModifier(stream, state, "deletion", /-/, 1); - - if (ch === "+") - return togglePhraseModifier(stream, state, "addition", /\+/, 1); - - if (ch === "~") - return togglePhraseModifier(stream, state, "sub", /~/, 1); - - if (ch === "^") - return togglePhraseModifier(stream, state, "sup", /\^/, 1); - - if (ch === "%") - return togglePhraseModifier(stream, state, "span", /%/, 1); - - if (ch === "@") - return togglePhraseModifier(stream, state, "code", /@/, 1); - - if (ch === "!") { - var type = togglePhraseModifier(stream, state, "image", /(?:\([^\)]+\))?!/, 1); - stream.match(/^:\S+/); // optional Url portion - return type; - } - return tokenStyles(state); - } - - function togglePhraseModifier(stream, state, phraseModifier, closeRE, openSize) { - var charBefore = stream.pos > openSize ? stream.string.charAt(stream.pos - openSize - 1) : null; - var charAfter = stream.peek(); - if (state[phraseModifier]) { - if ((!charAfter || /\W/.test(charAfter)) && charBefore && /\S/.test(charBefore)) { - var type = tokenStyles(state); - state[phraseModifier] = false; - return type; - } - } else if ((!charBefore || /\W/.test(charBefore)) && charAfter && /\S/.test(charAfter) && - stream.match(new RegExp("^.*\\S" + closeRE.source + "(?:\\W|$)"), false)) { - state[phraseModifier] = true; - state.mode = Modes.attributes; - } - return tokenStyles(state); - }; - - function tokenStyles(state) { - var disabled = textileDisabled(state); - if (disabled) return disabled; - - var styles = []; - if (state.layoutType) styles.push(TOKEN_STYLES[state.layoutType]); - - styles = styles.concat(activeStyles( - state, "addition", "bold", "cite", "code", "deletion", "em", "footCite", - "image", "italic", "link", "span", "strong", "sub", "sup", "table", "tableHeading")); - - if (state.layoutType === "header") - styles.push(TOKEN_STYLES.header + "-" + state.header); - - return styles.length ? styles.join(" ") : null; - } - - function textileDisabled(state) { - var type = state.layoutType; - - switch(type) { - case "notextile": - case "code": - case "pre": - return TOKEN_STYLES[type]; - default: - if (state.notextile) - return TOKEN_STYLES.notextile + (type ? (" " + TOKEN_STYLES[type]) : ""); - return null; - } - } - - function tokenStylesWith(state, extraStyles) { - var disabled = textileDisabled(state); - if (disabled) return disabled; - - var type = tokenStyles(state); - if (extraStyles) - return type ? (type + " " + extraStyles) : extraStyles; - else - return type; - } - - function activeStyles(state) { - var styles = []; - for (var i = 1; i < arguments.length; ++i) { - if (state[arguments[i]]) - styles.push(TOKEN_STYLES[arguments[i]]); - } - return styles; - } - - function blankLine(state) { - var spanningLayout = state.spanningLayout, type = state.layoutType; - - for (var key in state) if (state.hasOwnProperty(key)) - delete state[key]; - - state.mode = Modes.newLayout; - if (spanningLayout) { - state.layoutType = type; - state.spanningLayout = true; - } - } - - var REs = { - cache: {}, - single: { - bc: "bc", - bq: "bq", - definitionList: /- [^(?::=)]+:=+/, - definitionListEnd: /.*=:\s*$/, - div: "div", - drawTable: /\|.*\|/, - foot: /fn\d+/, - header: /h[1-6]/, - html: /\s*<(?:\/)?(\w+)(?:[^>]+)?>(?:[^<]+<\/\1>)?/, - link: /[^"]+":\S/, - linkDefinition: /\[[^\s\]]+\]\S+/, - list: /(?:#+|\*+)/, - notextile: "notextile", - para: "p", - pre: "pre", - table: "table", - tableCellAttributes: /[\/\\]\d+/, - tableHeading: /\|_\./, - tableText: /[^"_\*\[\(\?\+~\^%@|-]+/, - text: /[^!"_=\*\[\(<\?\+~\^%@-]+/ - }, - attributes: { - align: /(?:<>|<|>|=)/, - selector: /\([^\(][^\)]+\)/, - lang: /\[[^\[\]]+\]/, - pad: /(?:\(+|\)+){1,2}/, - css: /\{[^\}]+\}/ - }, - createRe: function(name) { - switch (name) { - case "drawTable": - return REs.makeRe("^", REs.single.drawTable, "$"); - case "html": - return REs.makeRe("^", REs.single.html, "(?:", REs.single.html, ")*", "$"); - case "linkDefinition": - return REs.makeRe("^", REs.single.linkDefinition, "$"); - case "listLayout": - return REs.makeRe("^", REs.single.list, RE("allAttributes"), "*\\s+"); - case "tableCellAttributes": - return REs.makeRe("^", REs.choiceRe(REs.single.tableCellAttributes, - RE("allAttributes")), "+\\."); - case "type": - return REs.makeRe("^", RE("allTypes")); - case "typeLayout": - return REs.makeRe("^", RE("allTypes"), RE("allAttributes"), - "*\\.\\.?", "(\\s+|$)"); - case "attributes": - return REs.makeRe("^", RE("allAttributes"), "+"); - - case "allTypes": - return REs.choiceRe(REs.single.div, REs.single.foot, - REs.single.header, REs.single.bc, REs.single.bq, - REs.single.notextile, REs.single.pre, REs.single.table, - REs.single.para); - - case "allAttributes": - return REs.choiceRe(REs.attributes.selector, REs.attributes.css, - REs.attributes.lang, REs.attributes.align, REs.attributes.pad); - - default: - return REs.makeRe("^", REs.single[name]); - } - }, - makeRe: function() { - var pattern = ""; - for (var i = 0; i < arguments.length; ++i) { - var arg = arguments[i]; - pattern += (typeof arg === "string") ? arg : arg.source; - } - return new RegExp(pattern); - }, - choiceRe: function() { - var parts = [arguments[0]]; - for (var i = 1; i < arguments.length; ++i) { - parts[i * 2 - 1] = "|"; - parts[i * 2] = arguments[i]; - } - - parts.unshift("(?:"); - parts.push(")"); - return REs.makeRe.apply(null, parts); - } - }; - - function RE(name) { - return (REs.cache[name] || (REs.cache[name] = REs.createRe(name))); - } - - var Modes = { - newLayout: function(stream, state) { - if (stream.match(RE("typeLayout"), false)) { - state.spanningLayout = false; - return (state.mode = Modes.blockType)(stream, state); - } - var newMode; - if (!textileDisabled(state)) { - if (stream.match(RE("listLayout"), false)) - newMode = Modes.list; - else if (stream.match(RE("drawTable"), false)) - newMode = Modes.table; - else if (stream.match(RE("linkDefinition"), false)) - newMode = Modes.linkDefinition; - else if (stream.match(RE("definitionList"))) - newMode = Modes.definitionList; - else if (stream.match(RE("html"), false)) - newMode = Modes.html; - } - return (state.mode = (newMode || Modes.text))(stream, state); - }, - - blockType: function(stream, state) { - var match, type; - state.layoutType = null; - - if (match = stream.match(RE("type"))) - type = match[0]; - else - return (state.mode = Modes.text)(stream, state); - - if (match = type.match(RE("header"))) { - state.layoutType = "header"; - state.header = parseInt(match[0][1]); - } else if (type.match(RE("bq"))) { - state.layoutType = "quote"; - } else if (type.match(RE("bc"))) { - state.layoutType = "code"; - } else if (type.match(RE("foot"))) { - state.layoutType = "footnote"; - } else if (type.match(RE("notextile"))) { - state.layoutType = "notextile"; - } else if (type.match(RE("pre"))) { - state.layoutType = "pre"; - } else if (type.match(RE("div"))) { - state.layoutType = "div"; - } else if (type.match(RE("table"))) { - state.layoutType = "table"; - } - - state.mode = Modes.attributes; - return tokenStyles(state); - }, - - text: function(stream, state) { - if (stream.match(RE("text"))) return tokenStyles(state); - - var ch = stream.next(); - if (ch === '"') - return (state.mode = Modes.link)(stream, state); - return handlePhraseModifier(stream, state, ch); - }, - - attributes: function(stream, state) { - state.mode = Modes.layoutLength; - - if (stream.match(RE("attributes"))) - return tokenStylesWith(state, TOKEN_STYLES.attributes); - else - return tokenStyles(state); - }, - - layoutLength: function(stream, state) { - if (stream.eat(".") && stream.eat(".")) - state.spanningLayout = true; - - state.mode = Modes.text; - return tokenStyles(state); - }, - - list: function(stream, state) { - var match = stream.match(RE("list")); - state.listDepth = match[0].length; - var listMod = (state.listDepth - 1) % 3; - if (!listMod) - state.layoutType = "list1"; - else if (listMod === 1) - state.layoutType = "list2"; - else - state.layoutType = "list3"; - - state.mode = Modes.attributes; - return tokenStyles(state); - }, - - link: function(stream, state) { - state.mode = Modes.text; - if (stream.match(RE("link"))) { - stream.match(/\S+/); - return tokenStylesWith(state, TOKEN_STYLES.link); - } - return tokenStyles(state); - }, - - linkDefinition: function(stream, state) { - stream.skipToEnd(); - return tokenStylesWith(state, TOKEN_STYLES.linkDefinition); - }, - - definitionList: function(stream, state) { - stream.match(RE("definitionList")); - - state.layoutType = "definitionList"; - - if (stream.match(/\s*$/)) - state.spanningLayout = true; - else - state.mode = Modes.attributes; - - return tokenStyles(state); - }, - - html: function(stream, state) { - stream.skipToEnd(); - return tokenStylesWith(state, TOKEN_STYLES.html); - }, - - table: function(stream, state) { - state.layoutType = "table"; - return (state.mode = Modes.tableCell)(stream, state); - }, - - tableCell: function(stream, state) { - if (stream.match(RE("tableHeading"))) - state.tableHeading = true; - else - stream.eat("|"); - - state.mode = Modes.tableCellAttributes; - return tokenStyles(state); - }, - - tableCellAttributes: function(stream, state) { - state.mode = Modes.tableText; - - if (stream.match(RE("tableCellAttributes"))) - return tokenStylesWith(state, TOKEN_STYLES.attributes); - else - return tokenStyles(state); - }, - - tableText: function(stream, state) { - if (stream.match(RE("tableText"))) - return tokenStyles(state); - - if (stream.peek() === "|") { // end of cell - state.mode = Modes.tableCell; - return tokenStyles(state); - } - return handlePhraseModifier(stream, state, stream.next()); - } - }; - - CodeMirror.defineMode("textile", function() { - return { - startState: function() { - return { mode: Modes.newLayout }; - }, - token: function(stream, state) { - if (stream.sol()) startNewLine(stream, state); - return state.mode(stream, state); - }, - blankLine: blankLine - }; - }); - - CodeMirror.defineMIME("text/x-textile", "textile"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/tiddlywiki/index.html b/backend/_pv_1_3_5/static/codemirror/mode/tiddlywiki/index.html deleted file mode 100755 index 77dd0457c..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/tiddlywiki/index.html +++ /dev/null @@ -1,154 +0,0 @@ - - -CodeMirror: TiddlyWiki mode - - - - - - - - - - - -
    -

    TiddlyWiki mode

    - - -
    - - - -

    TiddlyWiki mode supports a single configuration.

    - -

    MIME types defined: text/x-tiddlywiki.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/tiddlywiki/tiddlywiki.css b/backend/_pv_1_3_5/static/codemirror/mode/tiddlywiki/tiddlywiki.css deleted file mode 100755 index 9a69b639f..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/tiddlywiki/tiddlywiki.css +++ /dev/null @@ -1,14 +0,0 @@ -span.cm-underlined { - text-decoration: underline; -} -span.cm-strikethrough { - text-decoration: line-through; -} -span.cm-brace { - color: #170; - font-weight: bold; -} -span.cm-table { - color: blue; - font-weight: bold; -} diff --git a/backend/_pv_1_3_5/static/codemirror/mode/tiddlywiki/tiddlywiki.js b/backend/_pv_1_3_5/static/codemirror/mode/tiddlywiki/tiddlywiki.js deleted file mode 100755 index 1a3b3bc68..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/tiddlywiki/tiddlywiki.js +++ /dev/null @@ -1,308 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/*** - |''Name''|tiddlywiki.js| - |''Description''|Enables TiddlyWikiy syntax highlighting using CodeMirror| - |''Author''|PMario| - |''Version''|0.1.7| - |''Status''|''stable''| - |''Source''|[[GitHub|https://github.com/pmario/CodeMirror2/blob/tw-syntax/mode/tiddlywiki]]| - |''Documentation''|http://codemirror.tiddlyspace.com/| - |''License''|[[MIT License|http://www.opensource.org/licenses/mit-license.php]]| - |''CoreVersion''|2.5.0| - |''Requires''|codemirror.js| - |''Keywords''|syntax highlighting color code mirror codemirror| - ! Info - CoreVersion parameter is needed for TiddlyWiki only! -***/ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("tiddlywiki", function () { - // Tokenizer - var textwords = {}; - - var keywords = { - "allTags": true, "closeAll": true, "list": true, - "newJournal": true, "newTiddler": true, - "permaview": true, "saveChanges": true, - "search": true, "slider": true, "tabs": true, - "tag": true, "tagging": true, "tags": true, - "tiddler": true, "timeline": true, - "today": true, "version": true, "option": true, - "with": true, "filter": true - }; - - var isSpaceName = /[\w_\-]/i, - reHR = /^\-\-\-\-+$/, //
    - reWikiCommentStart = /^\/\*\*\*$/, // /*** - reWikiCommentStop = /^\*\*\*\/$/, // ***/ - reBlockQuote = /^<<<$/, - - reJsCodeStart = /^\/\/\{\{\{$/, // //{{{ js block start - reJsCodeStop = /^\/\/\}\}\}$/, // //}}} js stop - reXmlCodeStart = /^$/, // xml block start - reXmlCodeStop = /^$/, // xml stop - - reCodeBlockStart = /^\{\{\{$/, // {{{ TW text div block start - reCodeBlockStop = /^\}\}\}$/, // }}} TW text stop - - reUntilCodeStop = /.*?\}\}\}/; - - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - - function tokenBase(stream, state) { - var sol = stream.sol(), ch = stream.peek(); - - state.block = false; // indicates the start of a code block. - - // check start of blocks - if (sol && /[<\/\*{}\-]/.test(ch)) { - if (stream.match(reCodeBlockStart)) { - state.block = true; - return chain(stream, state, twTokenCode); - } - if (stream.match(reBlockQuote)) - return 'quote'; - if (stream.match(reWikiCommentStart) || stream.match(reWikiCommentStop)) - return 'comment'; - if (stream.match(reJsCodeStart) || stream.match(reJsCodeStop) || stream.match(reXmlCodeStart) || stream.match(reXmlCodeStop)) - return 'comment'; - if (stream.match(reHR)) - return 'hr'; - } - - stream.next(); - if (sol && /[\/\*!#;:>|]/.test(ch)) { - if (ch == "!") { // tw header - stream.skipToEnd(); - return "header"; - } - if (ch == "*") { // tw list - stream.eatWhile('*'); - return "comment"; - } - if (ch == "#") { // tw numbered list - stream.eatWhile('#'); - return "comment"; - } - if (ch == ";") { // definition list, term - stream.eatWhile(';'); - return "comment"; - } - if (ch == ":") { // definition list, description - stream.eatWhile(':'); - return "comment"; - } - if (ch == ">") { // single line quote - stream.eatWhile(">"); - return "quote"; - } - if (ch == '|') - return 'header'; - } - - if (ch == '{' && stream.match(/\{\{/)) - return chain(stream, state, twTokenCode); - - // rudimentary html:// file:// link matching. TW knows much more ... - if (/[hf]/i.test(ch) && - /[ti]/i.test(stream.peek()) && - stream.match(/\b(ttps?|tp|ile):\/\/[\-A-Z0-9+&@#\/%?=~_|$!:,.;]*[A-Z0-9+&@#\/%=~_|$]/i)) - return "link"; - - // just a little string indicator, don't want to have the whole string covered - if (ch == '"') - return 'string'; - - if (ch == '~') // _no_ CamelCase indicator should be bold - return 'brace'; - - if (/[\[\]]/.test(ch) && stream.match(ch)) // check for [[..]] - return 'brace'; - - if (ch == "@") { // check for space link. TODO fix @@...@@ highlighting - stream.eatWhile(isSpaceName); - return "link"; - } - - if (/\d/.test(ch)) { // numbers - stream.eatWhile(/\d/); - return "number"; - } - - if (ch == "/") { // tw invisible comment - if (stream.eat("%")) { - return chain(stream, state, twTokenComment); - } else if (stream.eat("/")) { // - return chain(stream, state, twTokenEm); - } - } - - if (ch == "_" && stream.eat("_")) // tw underline - return chain(stream, state, twTokenUnderline); - - // strikethrough and mdash handling - if (ch == "-" && stream.eat("-")) { - // if strikethrough looks ugly, change CSS. - if (stream.peek() != ' ') - return chain(stream, state, twTokenStrike); - // mdash - if (stream.peek() == ' ') - return 'brace'; - } - - if (ch == "'" && stream.eat("'")) // tw bold - return chain(stream, state, twTokenStrong); - - if (ch == "<" && stream.eat("<")) // tw macro - return chain(stream, state, twTokenMacro); - - // core macro handling - stream.eatWhile(/[\w\$_]/); - return textwords.propertyIsEnumerable(stream.current()) ? "keyword" : null - } - - // tw invisible comment - function twTokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "%"); - } - return "comment"; - } - - // tw strong / bold - function twTokenStrong(stream, state) { - var maybeEnd = false, - ch; - while (ch = stream.next()) { - if (ch == "'" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "'"); - } - return "strong"; - } - - // tw code - function twTokenCode(stream, state) { - var sb = state.block; - - if (sb && stream.current()) { - return "comment"; - } - - if (!sb && stream.match(reUntilCodeStop)) { - state.tokenize = tokenBase; - return "comment"; - } - - if (sb && stream.sol() && stream.match(reCodeBlockStop)) { - state.tokenize = tokenBase; - return "comment"; - } - - stream.next(); - return "comment"; - } - - // tw em / italic - function twTokenEm(stream, state) { - var maybeEnd = false, - ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "/"); - } - return "em"; - } - - // tw underlined text - function twTokenUnderline(stream, state) { - var maybeEnd = false, - ch; - while (ch = stream.next()) { - if (ch == "_" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "_"); - } - return "underlined"; - } - - // tw strike through text looks ugly - // change CSS if needed - function twTokenStrike(stream, state) { - var maybeEnd = false, ch; - - while (ch = stream.next()) { - if (ch == "-" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "-"); - } - return "strikethrough"; - } - - // macro - function twTokenMacro(stream, state) { - if (stream.current() == '<<') { - return 'macro'; - } - - var ch = stream.next(); - if (!ch) { - state.tokenize = tokenBase; - return null; - } - if (ch == ">") { - if (stream.peek() == '>') { - stream.next(); - state.tokenize = tokenBase; - return "macro"; - } - } - - stream.eatWhile(/[\w\$_]/); - return keywords.propertyIsEnumerable(stream.current()) ? "keyword" : null - } - - // Interface - return { - startState: function () { - return {tokenize: tokenBase}; - }, - - token: function (stream, state) { - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - return style; - } - }; -}); - -CodeMirror.defineMIME("text/x-tiddlywiki", "tiddlywiki"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/tiki/index.html b/backend/_pv_1_3_5/static/codemirror/mode/tiki/index.html deleted file mode 100755 index 091c5fb2a..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/tiki/index.html +++ /dev/null @@ -1,95 +0,0 @@ - - -CodeMirror: Tiki wiki mode - - - - - - - - - - -
    -

    Tiki wiki mode

    - - -
    - - - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/tiki/tiki.css b/backend/_pv_1_3_5/static/codemirror/mode/tiki/tiki.css deleted file mode 100755 index 1d8704c78..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/tiki/tiki.css +++ /dev/null @@ -1,26 +0,0 @@ -.cm-tw-syntaxerror { - color: #FFF; - background-color: #900; -} - -.cm-tw-deleted { - text-decoration: line-through; -} - -.cm-tw-header5 { - font-weight: bold; -} -.cm-tw-listitem:first-child { /*Added first child to fix duplicate padding when highlighting*/ - padding-left: 10px; -} - -.cm-tw-box { - border-top-width: 0px !important; - border-style: solid; - border-width: 1px; - border-color: inherit; -} - -.cm-tw-underline { - text-decoration: underline; -} \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/codemirror/mode/tiki/tiki.js b/backend/_pv_1_3_5/static/codemirror/mode/tiki/tiki.js deleted file mode 100755 index 5e05b1ff0..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/tiki/tiki.js +++ /dev/null @@ -1,312 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode('tiki', function(config) { - function inBlock(style, terminator, returnTokenizer) { - return function(stream, state) { - while (!stream.eol()) { - if (stream.match(terminator)) { - state.tokenize = inText; - break; - } - stream.next(); - } - - if (returnTokenizer) state.tokenize = returnTokenizer; - - return style; - }; - } - - function inLine(style) { - return function(stream, state) { - while(!stream.eol()) { - stream.next(); - } - state.tokenize = inText; - return style; - }; - } - - function inText(stream, state) { - function chain(parser) { - state.tokenize = parser; - return parser(stream, state); - } - - var sol = stream.sol(); - var ch = stream.next(); - - //non start of line - switch (ch) { //switch is generally much faster than if, so it is used here - case "{": //plugin - stream.eat("/"); - stream.eatSpace(); - stream.eatWhile(/[^\s\u00a0=\"\'\/?(}]/); - state.tokenize = inPlugin; - return "tag"; - case "_": //bold - if (stream.eat("_")) - return chain(inBlock("strong", "__", inText)); - break; - case "'": //italics - if (stream.eat("'")) - return chain(inBlock("em", "''", inText)); - break; - case "(":// Wiki Link - if (stream.eat("(")) - return chain(inBlock("variable-2", "))", inText)); - break; - case "[":// Weblink - return chain(inBlock("variable-3", "]", inText)); - break; - case "|": //table - if (stream.eat("|")) - return chain(inBlock("comment", "||")); - break; - case "-": - if (stream.eat("=")) {//titleBar - return chain(inBlock("header string", "=-", inText)); - } else if (stream.eat("-")) {//deleted - return chain(inBlock("error tw-deleted", "--", inText)); - } - break; - case "=": //underline - if (stream.match("==")) - return chain(inBlock("tw-underline", "===", inText)); - break; - case ":": - if (stream.eat(":")) - return chain(inBlock("comment", "::")); - break; - case "^": //box - return chain(inBlock("tw-box", "^")); - break; - case "~": //np - if (stream.match("np~")) - return chain(inBlock("meta", "~/np~")); - break; - } - - //start of line types - if (sol) { - switch (ch) { - case "!": //header at start of line - if (stream.match('!!!!!')) { - return chain(inLine("header string")); - } else if (stream.match('!!!!')) { - return chain(inLine("header string")); - } else if (stream.match('!!!')) { - return chain(inLine("header string")); - } else if (stream.match('!!')) { - return chain(inLine("header string")); - } else { - return chain(inLine("header string")); - } - break; - case "*": //unordered list line item, or
  • at start of line - case "#": //ordered list line item, or
  • at start of line - case "+": //ordered list line item, or
  • at start of line - return chain(inLine("tw-listitem bracket")); - break; - } - } - - //stream.eatWhile(/[&{]/); was eating up plugins, turned off to act less like html and more like tiki - return null; - } - - var indentUnit = config.indentUnit; - - // Return variables for tokenizers - var pluginName, type; - function inPlugin(stream, state) { - var ch = stream.next(); - var peek = stream.peek(); - - if (ch == "}") { - state.tokenize = inText; - //type = ch == ")" ? "endPlugin" : "selfclosePlugin"; inPlugin - return "tag"; - } else if (ch == "(" || ch == ")") { - return "bracket"; - } else if (ch == "=") { - type = "equals"; - - if (peek == ">") { - ch = stream.next(); - peek = stream.peek(); - } - - //here we detect values directly after equal character with no quotes - if (!/[\'\"]/.test(peek)) { - state.tokenize = inAttributeNoQuote(); - } - //end detect values - - return "operator"; - } else if (/[\'\"]/.test(ch)) { - state.tokenize = inAttribute(ch); - return state.tokenize(stream, state); - } else { - stream.eatWhile(/[^\s\u00a0=\"\'\/?]/); - return "keyword"; - } - } - - function inAttribute(quote) { - return function(stream, state) { - while (!stream.eol()) { - if (stream.next() == quote) { - state.tokenize = inPlugin; - break; - } - } - return "string"; - }; - } - - function inAttributeNoQuote() { - return function(stream, state) { - while (!stream.eol()) { - var ch = stream.next(); - var peek = stream.peek(); - if (ch == " " || ch == "," || /[ )}]/.test(peek)) { - state.tokenize = inPlugin; - break; - } - } - return "string"; -}; - } - -var curState, setStyle; -function pass() { - for (var i = arguments.length - 1; i >= 0; i--) curState.cc.push(arguments[i]); -} - -function cont() { - pass.apply(null, arguments); - return true; -} - -function pushContext(pluginName, startOfLine) { - var noIndent = curState.context && curState.context.noIndent; - curState.context = { - prev: curState.context, - pluginName: pluginName, - indent: curState.indented, - startOfLine: startOfLine, - noIndent: noIndent - }; -} - -function popContext() { - if (curState.context) curState.context = curState.context.prev; -} - -function element(type) { - if (type == "openPlugin") {curState.pluginName = pluginName; return cont(attributes, endplugin(curState.startOfLine));} - else if (type == "closePlugin") { - var err = false; - if (curState.context) { - err = curState.context.pluginName != pluginName; - popContext(); - } else { - err = true; - } - if (err) setStyle = "error"; - return cont(endcloseplugin(err)); - } - else if (type == "string") { - if (!curState.context || curState.context.name != "!cdata") pushContext("!cdata"); - if (curState.tokenize == inText) popContext(); - return cont(); - } - else return cont(); -} - -function endplugin(startOfLine) { - return function(type) { - if ( - type == "selfclosePlugin" || - type == "endPlugin" - ) - return cont(); - if (type == "endPlugin") {pushContext(curState.pluginName, startOfLine); return cont();} - return cont(); - }; -} - -function endcloseplugin(err) { - return function(type) { - if (err) setStyle = "error"; - if (type == "endPlugin") return cont(); - return pass(); - }; -} - -function attributes(type) { - if (type == "keyword") {setStyle = "attribute"; return cont(attributes);} - if (type == "equals") return cont(attvalue, attributes); - return pass(); -} -function attvalue(type) { - if (type == "keyword") {setStyle = "string"; return cont();} - if (type == "string") return cont(attvaluemaybe); - return pass(); -} -function attvaluemaybe(type) { - if (type == "string") return cont(attvaluemaybe); - else return pass(); -} -return { - startState: function() { - return {tokenize: inText, cc: [], indented: 0, startOfLine: true, pluginName: null, context: null}; - }, - token: function(stream, state) { - if (stream.sol()) { - state.startOfLine = true; - state.indented = stream.indentation(); - } - if (stream.eatSpace()) return null; - - setStyle = type = pluginName = null; - var style = state.tokenize(stream, state); - if ((style || type) && style != "comment") { - curState = state; - while (true) { - var comb = state.cc.pop() || element; - if (comb(type || style)) break; - } - } - state.startOfLine = false; - return setStyle || style; - }, - indent: function(state, textAfter) { - var context = state.context; - if (context && context.noIndent) return 0; - if (context && /^{\//.test(textAfter)) - context = context.prev; - while (context && !context.startOfLine) - context = context.prev; - if (context) return context.indent + indentUnit; - else return 0; - }, - electricChars: "/" - }; -}); - -CodeMirror.defineMIME("text/tiki", "tiki"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/toml/index.html b/backend/_pv_1_3_5/static/codemirror/mode/toml/index.html deleted file mode 100755 index 90a2a0215..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/toml/index.html +++ /dev/null @@ -1,73 +0,0 @@ - - -CodeMirror: TOML Mode - - - - - - - - - -
    -

    TOML Mode

    -
    - -

    The TOML Mode

    -

    Created by Forbes Lindesay.

    -

    MIME type defined: text/x-toml.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/toml/toml.js b/backend/_pv_1_3_5/static/codemirror/mode/toml/toml.js deleted file mode 100755 index baeca1556..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/toml/toml.js +++ /dev/null @@ -1,88 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("toml", function () { - return { - startState: function () { - return { - inString: false, - stringType: "", - lhs: true, - inArray: 0 - }; - }, - token: function (stream, state) { - //check for state changes - if (!state.inString && ((stream.peek() == '"') || (stream.peek() == "'"))) { - state.stringType = stream.peek(); - stream.next(); // Skip quote - state.inString = true; // Update state - } - if (stream.sol() && state.inArray === 0) { - state.lhs = true; - } - //return state - if (state.inString) { - while (state.inString && !stream.eol()) { - if (stream.peek() === state.stringType) { - stream.next(); // Skip quote - state.inString = false; // Clear flag - } else if (stream.peek() === '\\') { - stream.next(); - stream.next(); - } else { - stream.match(/^.[^\\\"\']*/); - } - } - return state.lhs ? "property string" : "string"; // Token style - } else if (state.inArray && stream.peek() === ']') { - stream.next(); - state.inArray--; - return 'bracket'; - } else if (state.lhs && stream.peek() === '[' && stream.skipTo(']')) { - stream.next();//skip closing ] - // array of objects has an extra open & close [] - if (stream.peek() === ']') stream.next(); - return "atom"; - } else if (stream.peek() === "#") { - stream.skipToEnd(); - return "comment"; - } else if (stream.eatSpace()) { - return null; - } else if (state.lhs && stream.eatWhile(function (c) { return c != '=' && c != ' '; })) { - return "property"; - } else if (state.lhs && stream.peek() === "=") { - stream.next(); - state.lhs = false; - return null; - } else if (!state.lhs && stream.match(/^\d\d\d\d[\d\-\:\.T]*Z/)) { - return 'atom'; //date - } else if (!state.lhs && (stream.match('true') || stream.match('false'))) { - return 'atom'; - } else if (!state.lhs && stream.peek() === '[') { - state.inArray++; - stream.next(); - return 'bracket'; - } else if (!state.lhs && stream.match(/^\-?\d+(?:\.\d+)?/)) { - return 'number'; - } else if (!stream.eatSpace()) { - stream.next(); - } - return null; - } - }; -}); - -CodeMirror.defineMIME('text/x-toml', 'toml'); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/tornado/index.html b/backend/_pv_1_3_5/static/codemirror/mode/tornado/index.html deleted file mode 100755 index 8ee7ef56c..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/tornado/index.html +++ /dev/null @@ -1,63 +0,0 @@ - - -CodeMirror: Tornado template mode - - - - - - - - - - - - -
    -

    Tornado template mode

    -
    - - - -

    Mode for HTML with embedded Tornado template markup.

    - -

    MIME types defined: text/x-tornado

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/tornado/tornado.js b/backend/_pv_1_3_5/static/codemirror/mode/tornado/tornado.js deleted file mode 100755 index dbfbc3489..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/tornado/tornado.js +++ /dev/null @@ -1,68 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../htmlmixed/htmlmixed"), - require("../../addon/mode/overlay")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../htmlmixed/htmlmixed", - "../../addon/mode/overlay"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("tornado:inner", function() { - var keywords = ["and","as","assert","autoescape","block","break","class","comment","context", - "continue","datetime","def","del","elif","else","end","escape","except", - "exec","extends","false","finally","for","from","global","if","import","in", - "include","is","json_encode","lambda","length","linkify","load","module", - "none","not","or","pass","print","put","raise","raw","return","self","set", - "squeeze","super","true","try","url_escape","while","with","without","xhtml_escape","yield"]; - keywords = new RegExp("^((" + keywords.join(")|(") + "))\\b"); - - function tokenBase (stream, state) { - stream.eatWhile(/[^\{]/); - var ch = stream.next(); - if (ch == "{") { - if (ch = stream.eat(/\{|%|#/)) { - state.tokenize = inTag(ch); - return "tag"; - } - } - } - function inTag (close) { - if (close == "{") { - close = "}"; - } - return function (stream, state) { - var ch = stream.next(); - if ((ch == close) && stream.eat("}")) { - state.tokenize = tokenBase; - return "tag"; - } - if (stream.match(keywords)) { - return "keyword"; - } - return close == "#" ? "comment" : "string"; - }; - } - return { - startState: function () { - return {tokenize: tokenBase}; - }, - token: function (stream, state) { - return state.tokenize(stream, state); - } - }; - }); - - CodeMirror.defineMode("tornado", function(config) { - var htmlBase = CodeMirror.getMode(config, "text/html"); - var tornadoInner = CodeMirror.getMode(config, "tornado:inner"); - return CodeMirror.overlayMode(htmlBase, tornadoInner); - }); - - CodeMirror.defineMIME("text/x-tornado", "tornado"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/troff/index.html b/backend/_pv_1_3_5/static/codemirror/mode/troff/index.html deleted file mode 100755 index 7c5a54e54..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/troff/index.html +++ /dev/null @@ -1,146 +0,0 @@ - - -CodeMirror: troff mode - - - - - - - - - - -
    -

    troff

    - - - - - - -

    MIME types defined: troff.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/troff/troff.js b/backend/_pv_1_3_5/static/codemirror/mode/troff/troff.js deleted file mode 100755 index 86154b6e1..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/troff/troff.js +++ /dev/null @@ -1,84 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) - define(["../../lib/codemirror"], mod); - else - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode('troff', function() { - - var words = {}; - - function tokenBase(stream) { - if (stream.eatSpace()) return null; - - var sol = stream.sol(); - var ch = stream.next(); - - if (ch === '\\') { - if (stream.match('fB') || stream.match('fR') || stream.match('fI') || - stream.match('u') || stream.match('d') || - stream.match('%') || stream.match('&')) { - return 'string'; - } - if (stream.match('m[')) { - stream.skipTo(']'); - stream.next(); - return 'string'; - } - if (stream.match('s+') || stream.match('s-')) { - stream.eatWhile(/[\d-]/); - return 'string'; - } - if (stream.match('\(') || stream.match('*\(')) { - stream.eatWhile(/[\w-]/); - return 'string'; - } - return 'string'; - } - if (sol && (ch === '.' || ch === '\'')) { - if (stream.eat('\\') && stream.eat('\"')) { - stream.skipToEnd(); - return 'comment'; - } - } - if (sol && ch === '.') { - if (stream.match('B ') || stream.match('I ') || stream.match('R ')) { - return 'attribute'; - } - if (stream.match('TH ') || stream.match('SH ') || stream.match('SS ') || stream.match('HP ')) { - stream.skipToEnd(); - return 'quote'; - } - if ((stream.match(/[A-Z]/) && stream.match(/[A-Z]/)) || (stream.match(/[a-z]/) && stream.match(/[a-z]/))) { - return 'attribute'; - } - } - stream.eatWhile(/[\w-]/); - var cur = stream.current(); - return words.hasOwnProperty(cur) ? words[cur] : null; - } - - function tokenize(stream, state) { - return (state.tokens[0] || tokenBase) (stream, state); - }; - - return { - startState: function() {return {tokens:[]};}, - token: function(stream, state) { - return tokenize(stream, state); - } - }; -}); - -CodeMirror.defineMIME('text/troff', 'troff'); -CodeMirror.defineMIME('text/x-troff', 'troff'); -CodeMirror.defineMIME('application/x-troff', 'troff'); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/ttcn-cfg/index.html b/backend/_pv_1_3_5/static/codemirror/mode/ttcn-cfg/index.html deleted file mode 100755 index 4a4cd4571..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/ttcn-cfg/index.html +++ /dev/null @@ -1,115 +0,0 @@ - - -CodeMirror: TTCN-CFG mode - - - - - - - - -
    -

    TTCN-CFG example

    -
    - -
    - - -
    -

    Language: Testing and Test Control Notation - - Configuration files - (TTCN-CFG) -

    -

    MIME types defined: text/x-ttcn-cfg.

    - -
    -

    The development of this mode has been sponsored by Ericsson - .

    -

    Coded by Asmelash Tsegay Gebretsadkan

    -
    - diff --git a/backend/_pv_1_3_5/static/codemirror/mode/ttcn-cfg/ttcn-cfg.js b/backend/_pv_1_3_5/static/codemirror/mode/ttcn-cfg/ttcn-cfg.js deleted file mode 100755 index e10805119..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/ttcn-cfg/ttcn-cfg.js +++ /dev/null @@ -1,214 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("ttcn-cfg", function(config, parserConfig) { - var indentUnit = config.indentUnit, - keywords = parserConfig.keywords || {}, - fileNCtrlMaskOptions = parserConfig.fileNCtrlMaskOptions || {}, - externalCommands = parserConfig.externalCommands || {}, - multiLineStrings = parserConfig.multiLineStrings, - indentStatements = parserConfig.indentStatements !== false; - var isOperatorChar = /[\|]/; - var curPunc; - - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"' || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - if (/[:=]/.test(ch)) { - curPunc = ch; - return "punctuation"; - } - if (ch == "#"){ - stream.skipToEnd(); - return "comment"; - } - if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - if (isOperatorChar.test(ch)) { - stream.eatWhile(isOperatorChar); - return "operator"; - } - if (ch == "["){ - stream.eatWhile(/[\w_\]]/); - return "number sectionTitle"; - } - - stream.eatWhile(/[\w\$_]/); - var cur = stream.current(); - if (keywords.propertyIsEnumerable(cur)) return "keyword"; - if (fileNCtrlMaskOptions.propertyIsEnumerable(cur)) - return "negative fileNCtrlMaskOptions"; - if (externalCommands.propertyIsEnumerable(cur)) return "negative externalCommands"; - - return "variable"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped){ - var afterNext = stream.peek(); - //look if the character if the quote is like the B in '10100010'B - if (afterNext){ - afterNext = afterNext.toLowerCase(); - if(afterNext == "b" || afterNext == "h" || afterNext == "o") - stream.next(); - } - end = true; break; - } - escaped = !escaped && next == "\\"; - } - if (end || !(escaped || multiLineStrings)) - state.tokenize = null; - return "string"; - }; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - function pushContext(state, col, type) { - var indent = state.indented; - if (state.context && state.context.type == "statement") - indent = state.context.indented; - return state.context = new Context(indent, col, type, null, state.context); - } - function popContext(state) { - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") - state.indented = state.context.indented; - return state.context = state.context.prev; - } - - //Interface - return { - startState: function(basecolumn) { - return { - tokenize: null, - context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), - indented: 0, - startOfLine: true - }; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - } - if (stream.eatSpace()) return null; - curPunc = null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment") return style; - if (ctx.align == null) ctx.align = true; - - if ((curPunc == ";" || curPunc == ":" || curPunc == ",") - && ctx.type == "statement"){ - popContext(state); - } - else if (curPunc == "{") pushContext(state, stream.column(), "}"); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == "}") { - while (ctx.type == "statement") ctx = popContext(state); - if (ctx.type == "}") ctx = popContext(state); - while (ctx.type == "statement") ctx = popContext(state); - } - else if (curPunc == ctx.type) popContext(state); - else if (indentStatements && (((ctx.type == "}" || ctx.type == "top") - && curPunc != ';') || (ctx.type == "statement" - && curPunc == "newstatement"))) - pushContext(state, stream.column(), "statement"); - state.startOfLine = false; - return style; - }, - - electricChars: "{}", - lineComment: "#", - fold: "brace" - }; - }); - - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) - obj[words[i]] = true; - return obj; - } - - CodeMirror.defineMIME("text/x-ttcn-cfg", { - name: "ttcn-cfg", - keywords: words("Yes No LogFile FileMask ConsoleMask AppendFile" + - " TimeStampFormat LogEventTypes SourceInfoFormat" + - " LogEntityName LogSourceInfo DiskFullAction" + - " LogFileNumber LogFileSize MatchingHints Detailed" + - " Compact SubCategories Stack Single None Seconds" + - " DateTime Time Stop Error Retry Delete TCPPort KillTimer" + - " NumHCs UnixSocketsEnabled LocalAddress"), - fileNCtrlMaskOptions: words("TTCN_EXECUTOR TTCN_ERROR TTCN_WARNING" + - " TTCN_PORTEVENT TTCN_TIMEROP TTCN_VERDICTOP" + - " TTCN_DEFAULTOP TTCN_TESTCASE TTCN_ACTION" + - " TTCN_USER TTCN_FUNCTION TTCN_STATISTICS" + - " TTCN_PARALLEL TTCN_MATCHING TTCN_DEBUG" + - " EXECUTOR ERROR WARNING PORTEVENT TIMEROP" + - " VERDICTOP DEFAULTOP TESTCASE ACTION USER" + - " FUNCTION STATISTICS PARALLEL MATCHING DEBUG" + - " LOG_ALL LOG_NOTHING ACTION_UNQUALIFIED" + - " DEBUG_ENCDEC DEBUG_TESTPORT" + - " DEBUG_UNQUALIFIED DEFAULTOP_ACTIVATE" + - " DEFAULTOP_DEACTIVATE DEFAULTOP_EXIT" + - " DEFAULTOP_UNQUALIFIED ERROR_UNQUALIFIED" + - " EXECUTOR_COMPONENT EXECUTOR_CONFIGDATA" + - " EXECUTOR_EXTCOMMAND EXECUTOR_LOGOPTIONS" + - " EXECUTOR_RUNTIME EXECUTOR_UNQUALIFIED" + - " FUNCTION_RND FUNCTION_UNQUALIFIED" + - " MATCHING_DONE MATCHING_MCSUCCESS" + - " MATCHING_MCUNSUCC MATCHING_MMSUCCESS" + - " MATCHING_MMUNSUCC MATCHING_PCSUCCESS" + - " MATCHING_PCUNSUCC MATCHING_PMSUCCESS" + - " MATCHING_PMUNSUCC MATCHING_PROBLEM" + - " MATCHING_TIMEOUT MATCHING_UNQUALIFIED" + - " PARALLEL_PORTCONN PARALLEL_PORTMAP" + - " PARALLEL_PTC PARALLEL_UNQUALIFIED" + - " PORTEVENT_DUALRECV PORTEVENT_DUALSEND" + - " PORTEVENT_MCRECV PORTEVENT_MCSEND" + - " PORTEVENT_MMRECV PORTEVENT_MMSEND" + - " PORTEVENT_MQUEUE PORTEVENT_PCIN" + - " PORTEVENT_PCOUT PORTEVENT_PMIN" + - " PORTEVENT_PMOUT PORTEVENT_PQUEUE" + - " PORTEVENT_STATE PORTEVENT_UNQUALIFIED" + - " STATISTICS_UNQUALIFIED STATISTICS_VERDICT" + - " TESTCASE_FINISH TESTCASE_START" + - " TESTCASE_UNQUALIFIED TIMEROP_GUARD" + - " TIMEROP_READ TIMEROP_START TIMEROP_STOP" + - " TIMEROP_TIMEOUT TIMEROP_UNQUALIFIED" + - " USER_UNQUALIFIED VERDICTOP_FINAL" + - " VERDICTOP_GETVERDICT VERDICTOP_SETVERDICT" + - " VERDICTOP_UNQUALIFIED WARNING_UNQUALIFIED"), - externalCommands: words("BeginControlPart EndControlPart BeginTestCase" + - " EndTestCase"), - multiLineStrings: true - }); -}); \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/codemirror/mode/ttcn/index.html b/backend/_pv_1_3_5/static/codemirror/mode/ttcn/index.html deleted file mode 100755 index f1ef81131..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/ttcn/index.html +++ /dev/null @@ -1,118 +0,0 @@ - - -CodeMirror: TTCN mode - - - - - - - - -
    -

    TTCN example

    -
    - -
    - - -
    -

    Language: Testing and Test Control Notation - (TTCN) -

    -

    MIME types defined: text/x-ttcn, - text/x-ttcn3, text/x-ttcnpp.

    -
    -

    The development of this mode has been sponsored by Ericsson - .

    -

    Coded by Asmelash Tsegay Gebretsadkan

    -
    - diff --git a/backend/_pv_1_3_5/static/codemirror/mode/ttcn/ttcn.js b/backend/_pv_1_3_5/static/codemirror/mode/ttcn/ttcn.js deleted file mode 100755 index 305185177..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/ttcn/ttcn.js +++ /dev/null @@ -1,283 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("ttcn", function(config, parserConfig) { - var indentUnit = config.indentUnit, - keywords = parserConfig.keywords || {}, - builtin = parserConfig.builtin || {}, - timerOps = parserConfig.timerOps || {}, - portOps = parserConfig.portOps || {}, - configOps = parserConfig.configOps || {}, - verdictOps = parserConfig.verdictOps || {}, - sutOps = parserConfig.sutOps || {}, - functionOps = parserConfig.functionOps || {}, - - verdictConsts = parserConfig.verdictConsts || {}, - booleanConsts = parserConfig.booleanConsts || {}, - otherConsts = parserConfig.otherConsts || {}, - - types = parserConfig.types || {}, - visibilityModifiers = parserConfig.visibilityModifiers || {}, - templateMatch = parserConfig.templateMatch || {}, - multiLineStrings = parserConfig.multiLineStrings, - indentStatements = parserConfig.indentStatements !== false; - var isOperatorChar = /[+\-*&@=<>!\/]/; - var curPunc; - - function tokenBase(stream, state) { - var ch = stream.next(); - - if (ch == '"' || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - if (/[\[\]{}\(\),;\\:\?\.]/.test(ch)) { - curPunc = ch; - return "punctuation"; - } - if (ch == "#"){ - stream.skipToEnd(); - return "atom preprocessor"; - } - if (ch == "%"){ - stream.eatWhile(/\b/); - return "atom ttcn3Macros"; - } - if (/\d/.test(ch)) { - stream.eatWhile(/[\w\.]/); - return "number"; - } - if (ch == "/") { - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - } - if (isOperatorChar.test(ch)) { - if(ch == "@"){ - if(stream.match("try") || stream.match("catch") - || stream.match("lazy")){ - return "keyword"; - } - } - stream.eatWhile(isOperatorChar); - return "operator"; - } - stream.eatWhile(/[\w\$_\xa1-\uffff]/); - var cur = stream.current(); - - if (keywords.propertyIsEnumerable(cur)) return "keyword"; - if (builtin.propertyIsEnumerable(cur)) return "builtin"; - - if (timerOps.propertyIsEnumerable(cur)) return "def timerOps"; - if (configOps.propertyIsEnumerable(cur)) return "def configOps"; - if (verdictOps.propertyIsEnumerable(cur)) return "def verdictOps"; - if (portOps.propertyIsEnumerable(cur)) return "def portOps"; - if (sutOps.propertyIsEnumerable(cur)) return "def sutOps"; - if (functionOps.propertyIsEnumerable(cur)) return "def functionOps"; - - if (verdictConsts.propertyIsEnumerable(cur)) return "string verdictConsts"; - if (booleanConsts.propertyIsEnumerable(cur)) return "string booleanConsts"; - if (otherConsts.propertyIsEnumerable(cur)) return "string otherConsts"; - - if (types.propertyIsEnumerable(cur)) return "builtin types"; - if (visibilityModifiers.propertyIsEnumerable(cur)) - return "builtin visibilityModifiers"; - if (templateMatch.propertyIsEnumerable(cur)) return "atom templateMatch"; - - return "variable"; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped){ - var afterQuote = stream.peek(); - //look if the character after the quote is like the B in '10100010'B - if (afterQuote){ - afterQuote = afterQuote.toLowerCase(); - if(afterQuote == "b" || afterQuote == "h" || afterQuote == "o") - stream.next(); - } - end = true; break; - } - escaped = !escaped && next == "\\"; - } - if (end || !(escaped || multiLineStrings)) - state.tokenize = null; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = null; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - - function pushContext(state, col, type) { - var indent = state.indented; - if (state.context && state.context.type == "statement") - indent = state.context.indented; - return state.context = new Context(indent, col, type, null, state.context); - } - - function popContext(state) { - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") - state.indented = state.context.indented; - return state.context = state.context.prev; - } - - //Interface - return { - startState: function(basecolumn) { - return { - tokenize: null, - context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), - indented: 0, - startOfLine: true - }; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - } - if (stream.eatSpace()) return null; - curPunc = null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment") return style; - if (ctx.align == null) ctx.align = true; - - if ((curPunc == ";" || curPunc == ":" || curPunc == ",") - && ctx.type == "statement"){ - popContext(state); - } - else if (curPunc == "{") pushContext(state, stream.column(), "}"); - else if (curPunc == "[") pushContext(state, stream.column(), "]"); - else if (curPunc == "(") pushContext(state, stream.column(), ")"); - else if (curPunc == "}") { - while (ctx.type == "statement") ctx = popContext(state); - if (ctx.type == "}") ctx = popContext(state); - while (ctx.type == "statement") ctx = popContext(state); - } - else if (curPunc == ctx.type) popContext(state); - else if (indentStatements && - (((ctx.type == "}" || ctx.type == "top") && curPunc != ';') || - (ctx.type == "statement" && curPunc == "newstatement"))) - pushContext(state, stream.column(), "statement"); - - state.startOfLine = false; - - return style; - }, - - electricChars: "{}", - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: "//", - fold: "brace" - }; - }); - - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - function def(mimes, mode) { - if (typeof mimes == "string") mimes = [mimes]; - var words = []; - function add(obj) { - if (obj) for (var prop in obj) if (obj.hasOwnProperty(prop)) - words.push(prop); - } - - add(mode.keywords); - add(mode.builtin); - add(mode.timerOps); - add(mode.portOps); - - if (words.length) { - mode.helperType = mimes[0]; - CodeMirror.registerHelper("hintWords", mimes[0], words); - } - - for (var i = 0; i < mimes.length; ++i) - CodeMirror.defineMIME(mimes[i], mode); - } - - def(["text/x-ttcn", "text/x-ttcn3", "text/x-ttcnpp"], { - name: "ttcn", - keywords: words("activate address alive all alt altstep and and4b any" + - " break case component const continue control deactivate" + - " display do else encode enumerated except exception" + - " execute extends extension external for from function" + - " goto group if import in infinity inout interleave" + - " label language length log match message mixed mod" + - " modifies module modulepar mtc noblock not not4b nowait" + - " of on optional or or4b out override param pattern port" + - " procedure record recursive rem repeat return runs select" + - " self sender set signature system template testcase to" + - " type union value valueof var variant while with xor xor4b"), - builtin: words("bit2hex bit2int bit2oct bit2str char2int char2oct encvalue" + - " decomp decvalue float2int float2str hex2bit hex2int" + - " hex2oct hex2str int2bit int2char int2float int2hex" + - " int2oct int2str int2unichar isbound ischosen ispresent" + - " isvalue lengthof log2str oct2bit oct2char oct2hex oct2int" + - " oct2str regexp replace rnd sizeof str2bit str2float" + - " str2hex str2int str2oct substr unichar2int unichar2char" + - " enum2int"), - types: words("anytype bitstring boolean char charstring default float" + - " hexstring integer objid octetstring universal verdicttype timer"), - timerOps: words("read running start stop timeout"), - portOps: words("call catch check clear getcall getreply halt raise receive" + - " reply send trigger"), - configOps: words("create connect disconnect done kill killed map unmap"), - verdictOps: words("getverdict setverdict"), - sutOps: words("action"), - functionOps: words("apply derefers refers"), - - verdictConsts: words("error fail inconc none pass"), - booleanConsts: words("true false"), - otherConsts: words("null NULL omit"), - - visibilityModifiers: words("private public friend"), - templateMatch: words("complement ifpresent subset superset permutation"), - multiLineStrings: true - }); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/turtle/index.html b/backend/_pv_1_3_5/static/codemirror/mode/turtle/index.html deleted file mode 100755 index a4962b617..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/turtle/index.html +++ /dev/null @@ -1,50 +0,0 @@ - - -CodeMirror: Turtle mode - - - - - - - - - -
    -

    Turtle mode

    -
    - - -

    MIME types defined: text/turtle.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/turtle/turtle.js b/backend/_pv_1_3_5/static/codemirror/mode/turtle/turtle.js deleted file mode 100755 index 0988f0a44..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/turtle/turtle.js +++ /dev/null @@ -1,162 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("turtle", function(config) { - var indentUnit = config.indentUnit; - var curPunc; - - function wordRegexp(words) { - return new RegExp("^(?:" + words.join("|") + ")$", "i"); - } - var ops = wordRegexp([]); - var keywords = wordRegexp(["@prefix", "@base", "a"]); - var operatorChars = /[*+\-<>=&|]/; - - function tokenBase(stream, state) { - var ch = stream.next(); - curPunc = null; - if (ch == "<" && !stream.match(/^[\s\u00a0=]/, false)) { - stream.match(/^[^\s\u00a0>]*>?/); - return "atom"; - } - else if (ch == "\"" || ch == "'") { - state.tokenize = tokenLiteral(ch); - return state.tokenize(stream, state); - } - else if (/[{}\(\),\.;\[\]]/.test(ch)) { - curPunc = ch; - return null; - } - else if (ch == "#") { - stream.skipToEnd(); - return "comment"; - } - else if (operatorChars.test(ch)) { - stream.eatWhile(operatorChars); - return null; - } - else if (ch == ":") { - return "operator"; - } else { - stream.eatWhile(/[_\w\d]/); - if(stream.peek() == ":") { - return "variable-3"; - } else { - var word = stream.current(); - - if(keywords.test(word)) { - return "meta"; - } - - if(ch >= "A" && ch <= "Z") { - return "comment"; - } else { - return "keyword"; - } - } - var word = stream.current(); - if (ops.test(word)) - return null; - else if (keywords.test(word)) - return "meta"; - else - return "variable"; - } - } - - function tokenLiteral(quote) { - return function(stream, state) { - var escaped = false, ch; - while ((ch = stream.next()) != null) { - if (ch == quote && !escaped) { - state.tokenize = tokenBase; - break; - } - escaped = !escaped && ch == "\\"; - } - return "string"; - }; - } - - function pushContext(state, type, col) { - state.context = {prev: state.context, indent: state.indent, col: col, type: type}; - } - function popContext(state) { - state.indent = state.context.indent; - state.context = state.context.prev; - } - - return { - startState: function() { - return {tokenize: tokenBase, - context: null, - indent: 0, - col: 0}; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (state.context && state.context.align == null) state.context.align = false; - state.indent = stream.indentation(); - } - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - - if (style != "comment" && state.context && state.context.align == null && state.context.type != "pattern") { - state.context.align = true; - } - - if (curPunc == "(") pushContext(state, ")", stream.column()); - else if (curPunc == "[") pushContext(state, "]", stream.column()); - else if (curPunc == "{") pushContext(state, "}", stream.column()); - else if (/[\]\}\)]/.test(curPunc)) { - while (state.context && state.context.type == "pattern") popContext(state); - if (state.context && curPunc == state.context.type) popContext(state); - } - else if (curPunc == "." && state.context && state.context.type == "pattern") popContext(state); - else if (/atom|string|variable/.test(style) && state.context) { - if (/[\}\]]/.test(state.context.type)) - pushContext(state, "pattern", stream.column()); - else if (state.context.type == "pattern" && !state.context.align) { - state.context.align = true; - state.context.col = stream.column(); - } - } - - return style; - }, - - indent: function(state, textAfter) { - var firstChar = textAfter && textAfter.charAt(0); - var context = state.context; - if (/[\]\}]/.test(firstChar)) - while (context && context.type == "pattern") context = context.prev; - - var closing = context && firstChar == context.type; - if (!context) - return 0; - else if (context.type == "pattern") - return context.col; - else if (context.align) - return context.col + (closing ? 0 : 1); - else - return context.indent + (closing ? 0 : indentUnit); - }, - - lineComment: "#" - }; -}); - -CodeMirror.defineMIME("text/turtle", "turtle"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/twig/index.html b/backend/_pv_1_3_5/static/codemirror/mode/twig/index.html deleted file mode 100755 index 02493a5cb..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/twig/index.html +++ /dev/null @@ -1,45 +0,0 @@ - - -CodeMirror: Twig mode - - - - - - - - - -
    -

    Twig mode

    -
    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/twig/twig.js b/backend/_pv_1_3_5/static/codemirror/mode/twig/twig.js deleted file mode 100755 index 1f2854bef..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/twig/twig.js +++ /dev/null @@ -1,141 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../../addon/mode/multiplex")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../../addon/mode/multiplex"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - CodeMirror.defineMode("twig:inner", function() { - var keywords = ["and", "as", "autoescape", "endautoescape", "block", "do", "endblock", "else", "elseif", "extends", "for", "endfor", "embed", "endembed", "filter", "endfilter", "flush", "from", "if", "endif", "in", "is", "include", "import", "not", "or", "set", "spaceless", "endspaceless", "with", "endwith", "trans", "endtrans", "blocktrans", "endblocktrans", "macro", "endmacro", "use", "verbatim", "endverbatim"], - operator = /^[+\-*&%=<>!?|~^]/, - sign = /^[:\[\(\{]/, - atom = ["true", "false", "null", "empty", "defined", "divisibleby", "divisible by", "even", "odd", "iterable", "sameas", "same as"], - number = /^(\d[+\-\*\/])?\d+(\.\d+)?/; - - keywords = new RegExp("((" + keywords.join(")|(") + "))\\b"); - atom = new RegExp("((" + atom.join(")|(") + "))\\b"); - - function tokenBase (stream, state) { - var ch = stream.peek(); - - //Comment - if (state.incomment) { - if (!stream.skipTo("#}")) { - stream.skipToEnd(); - } else { - stream.eatWhile(/\#|}/); - state.incomment = false; - } - return "comment"; - //Tag - } else if (state.intag) { - //After operator - if (state.operator) { - state.operator = false; - if (stream.match(atom)) { - return "atom"; - } - if (stream.match(number)) { - return "number"; - } - } - //After sign - if (state.sign) { - state.sign = false; - if (stream.match(atom)) { - return "atom"; - } - if (stream.match(number)) { - return "number"; - } - } - - if (state.instring) { - if (ch == state.instring) { - state.instring = false; - } - stream.next(); - return "string"; - } else if (ch == "'" || ch == '"') { - state.instring = ch; - stream.next(); - return "string"; - } else if (stream.match(state.intag + "}") || stream.eat("-") && stream.match(state.intag + "}")) { - state.intag = false; - return "tag"; - } else if (stream.match(operator)) { - state.operator = true; - return "operator"; - } else if (stream.match(sign)) { - state.sign = true; - } else { - if (stream.eat(" ") || stream.sol()) { - if (stream.match(keywords)) { - return "keyword"; - } - if (stream.match(atom)) { - return "atom"; - } - if (stream.match(number)) { - return "number"; - } - if (stream.sol()) { - stream.next(); - } - } else { - stream.next(); - } - - } - return "variable"; - } else if (stream.eat("{")) { - if (ch = stream.eat("#")) { - state.incomment = true; - if (!stream.skipTo("#}")) { - stream.skipToEnd(); - } else { - stream.eatWhile(/\#|}/); - state.incomment = false; - } - return "comment"; - //Open tag - } else if (ch = stream.eat(/\{|%/)) { - //Cache close tag - state.intag = ch; - if (ch == "{") { - state.intag = "}"; - } - stream.eat("-"); - return "tag"; - } - } - stream.next(); - }; - - return { - startState: function () { - return {}; - }, - token: function (stream, state) { - return tokenBase(stream, state); - } - }; - }); - - CodeMirror.defineMode("twig", function(config, parserConfig) { - var twigInner = CodeMirror.getMode(config, "twig:inner"); - if (!parserConfig || !parserConfig.base) return twigInner; - return CodeMirror.multiplexingMode( - CodeMirror.getMode(config, parserConfig.base), { - open: /\{[{#%]/, close: /[}#%]\}/, mode: twigInner, parseDelimiters: true - } - ); - }); - CodeMirror.defineMIME("text/x-twig", "twig"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/vb/index.html b/backend/_pv_1_3_5/static/codemirror/mode/vb/index.html deleted file mode 100755 index adcc44fd3..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/vb/index.html +++ /dev/null @@ -1,102 +0,0 @@ - - -CodeMirror: VB.NET mode - - - - - - - - - - - -
    -

    VB.NET mode

    - - - -
    - -
    -
    
    -  

    MIME type defined: text/x-vb.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/vb/vb.js b/backend/_pv_1_3_5/static/codemirror/mode/vb/vb.js deleted file mode 100755 index d78f91f70..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/vb/vb.js +++ /dev/null @@ -1,276 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("vb", function(conf, parserConf) { - var ERRORCLASS = 'error'; - - function wordRegexp(words) { - return new RegExp("^((" + words.join(")|(") + "))\\b", "i"); - } - - var singleOperators = new RegExp("^[\\+\\-\\*/%&\\\\|\\^~<>!]"); - var singleDelimiters = new RegExp('^[\\(\\)\\[\\]\\{\\}@,:`=;\\.]'); - var doubleOperators = new RegExp("^((==)|(<>)|(<=)|(>=)|(<>)|(<<)|(>>)|(//)|(\\*\\*))"); - var doubleDelimiters = new RegExp("^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&=)|(\\|=)|(\\^=))"); - var tripleDelimiters = new RegExp("^((//=)|(>>=)|(<<=)|(\\*\\*=))"); - var identifiers = new RegExp("^[_A-Za-z][_A-Za-z0-9]*"); - - var openingKeywords = ['class','module', 'sub','enum','select','while','if','function', 'get','set','property', 'try']; - var middleKeywords = ['else','elseif','case', 'catch']; - var endKeywords = ['next','loop']; - - var operatorKeywords = ['and', 'or', 'not', 'xor', 'in']; - var wordOperators = wordRegexp(operatorKeywords); - var commonKeywords = ['as', 'dim', 'break', 'continue','optional', 'then', 'until', - 'goto', 'byval','byref','new','handles','property', 'return', - 'const','private', 'protected', 'friend', 'public', 'shared', 'static', 'true','false']; - var commontypes = ['integer','string','double','decimal','boolean','short','char', 'float','single']; - - var keywords = wordRegexp(commonKeywords); - var types = wordRegexp(commontypes); - var stringPrefixes = '"'; - - var opening = wordRegexp(openingKeywords); - var middle = wordRegexp(middleKeywords); - var closing = wordRegexp(endKeywords); - var doubleClosing = wordRegexp(['end']); - var doOpening = wordRegexp(['do']); - - var indentInfo = null; - - CodeMirror.registerHelper("hintWords", "vb", openingKeywords.concat(middleKeywords).concat(endKeywords) - .concat(operatorKeywords).concat(commonKeywords).concat(commontypes)); - - function indent(_stream, state) { - state.currentIndent++; - } - - function dedent(_stream, state) { - state.currentIndent--; - } - // tokenizers - function tokenBase(stream, state) { - if (stream.eatSpace()) { - return null; - } - - var ch = stream.peek(); - - // Handle Comments - if (ch === "'") { - stream.skipToEnd(); - return 'comment'; - } - - - // Handle Number Literals - if (stream.match(/^((&H)|(&O))?[0-9\.a-f]/i, false)) { - var floatLiteral = false; - // Floats - if (stream.match(/^\d*\.\d+F?/i)) { floatLiteral = true; } - else if (stream.match(/^\d+\.\d*F?/)) { floatLiteral = true; } - else if (stream.match(/^\.\d+F?/)) { floatLiteral = true; } - - if (floatLiteral) { - // Float literals may be "imaginary" - stream.eat(/J/i); - return 'number'; - } - // Integers - var intLiteral = false; - // Hex - if (stream.match(/^&H[0-9a-f]+/i)) { intLiteral = true; } - // Octal - else if (stream.match(/^&O[0-7]+/i)) { intLiteral = true; } - // Decimal - else if (stream.match(/^[1-9]\d*F?/)) { - // Decimal literals may be "imaginary" - stream.eat(/J/i); - // TODO - Can you have imaginary longs? - intLiteral = true; - } - // Zero by itself with no other piece of number. - else if (stream.match(/^0(?![\dx])/i)) { intLiteral = true; } - if (intLiteral) { - // Integer literals may be "long" - stream.eat(/L/i); - return 'number'; - } - } - - // Handle Strings - if (stream.match(stringPrefixes)) { - state.tokenize = tokenStringFactory(stream.current()); - return state.tokenize(stream, state); - } - - // Handle operators and Delimiters - if (stream.match(tripleDelimiters) || stream.match(doubleDelimiters)) { - return null; - } - if (stream.match(doubleOperators) - || stream.match(singleOperators) - || stream.match(wordOperators)) { - return 'operator'; - } - if (stream.match(singleDelimiters)) { - return null; - } - if (stream.match(doOpening)) { - indent(stream,state); - state.doInCurrentLine = true; - return 'keyword'; - } - if (stream.match(opening)) { - if (! state.doInCurrentLine) - indent(stream,state); - else - state.doInCurrentLine = false; - return 'keyword'; - } - if (stream.match(middle)) { - return 'keyword'; - } - - if (stream.match(doubleClosing)) { - dedent(stream,state); - dedent(stream,state); - return 'keyword'; - } - if (stream.match(closing)) { - dedent(stream,state); - return 'keyword'; - } - - if (stream.match(types)) { - return 'keyword'; - } - - if (stream.match(keywords)) { - return 'keyword'; - } - - if (stream.match(identifiers)) { - return 'variable'; - } - - // Handle non-detected items - stream.next(); - return ERRORCLASS; - } - - function tokenStringFactory(delimiter) { - var singleline = delimiter.length == 1; - var OUTCLASS = 'string'; - - return function(stream, state) { - while (!stream.eol()) { - stream.eatWhile(/[^'"]/); - if (stream.match(delimiter)) { - state.tokenize = tokenBase; - return OUTCLASS; - } else { - stream.eat(/['"]/); - } - } - if (singleline) { - if (parserConf.singleLineStringErrors) { - return ERRORCLASS; - } else { - state.tokenize = tokenBase; - } - } - return OUTCLASS; - }; - } - - - function tokenLexer(stream, state) { - var style = state.tokenize(stream, state); - var current = stream.current(); - - // Handle '.' connected identifiers - if (current === '.') { - style = state.tokenize(stream, state); - current = stream.current(); - if (style === 'variable') { - return 'variable'; - } else { - return ERRORCLASS; - } - } - - - var delimiter_index = '[({'.indexOf(current); - if (delimiter_index !== -1) { - indent(stream, state ); - } - if (indentInfo === 'dedent') { - if (dedent(stream, state)) { - return ERRORCLASS; - } - } - delimiter_index = '])}'.indexOf(current); - if (delimiter_index !== -1) { - if (dedent(stream, state)) { - return ERRORCLASS; - } - } - - return style; - } - - var external = { - electricChars:"dDpPtTfFeE ", - startState: function() { - return { - tokenize: tokenBase, - lastToken: null, - currentIndent: 0, - nextLineIndent: 0, - doInCurrentLine: false - - - }; - }, - - token: function(stream, state) { - if (stream.sol()) { - state.currentIndent += state.nextLineIndent; - state.nextLineIndent = 0; - state.doInCurrentLine = 0; - } - var style = tokenLexer(stream, state); - - state.lastToken = {style:style, content: stream.current()}; - - - - return style; - }, - - indent: function(state, textAfter) { - var trueText = textAfter.replace(/^\s+|\s+$/g, '') ; - if (trueText.match(closing) || trueText.match(doubleClosing) || trueText.match(middle)) return conf.indentUnit*(state.currentIndent-1); - if(state.currentIndent < 0) return 0; - return state.currentIndent * conf.indentUnit; - }, - - lineComment: "'" - }; - return external; -}); - -CodeMirror.defineMIME("text/x-vb", "vb"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/vbscript/index.html b/backend/_pv_1_3_5/static/codemirror/mode/vbscript/index.html deleted file mode 100755 index ad7532d7d..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/vbscript/index.html +++ /dev/null @@ -1,55 +0,0 @@ - - -CodeMirror: VBScript mode - - - - - - - - - -
    -

    VBScript mode

    - - -
    - - - -

    MIME types defined: text/vbscript.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/vbscript/vbscript.js b/backend/_pv_1_3_5/static/codemirror/mode/vbscript/vbscript.js deleted file mode 100755 index b66df2239..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/vbscript/vbscript.js +++ /dev/null @@ -1,350 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -/* -For extra ASP classic objects, initialize CodeMirror instance with this option: - isASP: true - -E.G.: - var editor = CodeMirror.fromTextArea(document.getElementById("code"), { - lineNumbers: true, - isASP: true - }); -*/ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("vbscript", function(conf, parserConf) { - var ERRORCLASS = 'error'; - - function wordRegexp(words) { - return new RegExp("^((" + words.join(")|(") + "))\\b", "i"); - } - - var singleOperators = new RegExp("^[\\+\\-\\*/&\\\\\\^<>=]"); - var doubleOperators = new RegExp("^((<>)|(<=)|(>=))"); - var singleDelimiters = new RegExp('^[\\.,]'); - var brakets = new RegExp('^[\\(\\)]'); - var identifiers = new RegExp("^[A-Za-z][_A-Za-z0-9]*"); - - var openingKeywords = ['class','sub','select','while','if','function', 'property', 'with', 'for']; - var middleKeywords = ['else','elseif','case']; - var endKeywords = ['next','loop','wend']; - - var wordOperators = wordRegexp(['and', 'or', 'not', 'xor', 'is', 'mod', 'eqv', 'imp']); - var commonkeywords = ['dim', 'redim', 'then', 'until', 'randomize', - 'byval','byref','new','property', 'exit', 'in', - 'const','private', 'public', - 'get','set','let', 'stop', 'on error resume next', 'on error goto 0', 'option explicit', 'call', 'me']; - - //This list was from: http://msdn.microsoft.com/en-us/library/f8tbc79x(v=vs.84).aspx - var atomWords = ['true', 'false', 'nothing', 'empty', 'null']; - //This list was from: http://msdn.microsoft.com/en-us/library/3ca8tfek(v=vs.84).aspx - var builtinFuncsWords = ['abs', 'array', 'asc', 'atn', 'cbool', 'cbyte', 'ccur', 'cdate', 'cdbl', 'chr', 'cint', 'clng', 'cos', 'csng', 'cstr', 'date', 'dateadd', 'datediff', 'datepart', - 'dateserial', 'datevalue', 'day', 'escape', 'eval', 'execute', 'exp', 'filter', 'formatcurrency', 'formatdatetime', 'formatnumber', 'formatpercent', 'getlocale', 'getobject', - 'getref', 'hex', 'hour', 'inputbox', 'instr', 'instrrev', 'int', 'fix', 'isarray', 'isdate', 'isempty', 'isnull', 'isnumeric', 'isobject', 'join', 'lbound', 'lcase', 'left', - 'len', 'loadpicture', 'log', 'ltrim', 'rtrim', 'trim', 'maths', 'mid', 'minute', 'month', 'monthname', 'msgbox', 'now', 'oct', 'replace', 'rgb', 'right', 'rnd', 'round', - 'scriptengine', 'scriptenginebuildversion', 'scriptenginemajorversion', 'scriptengineminorversion', 'second', 'setlocale', 'sgn', 'sin', 'space', 'split', 'sqr', 'strcomp', - 'string', 'strreverse', 'tan', 'time', 'timer', 'timeserial', 'timevalue', 'typename', 'ubound', 'ucase', 'unescape', 'vartype', 'weekday', 'weekdayname', 'year']; - - //This list was from: http://msdn.microsoft.com/en-us/library/ydz4cfk3(v=vs.84).aspx - var builtinConsts = ['vbBlack', 'vbRed', 'vbGreen', 'vbYellow', 'vbBlue', 'vbMagenta', 'vbCyan', 'vbWhite', 'vbBinaryCompare', 'vbTextCompare', - 'vbSunday', 'vbMonday', 'vbTuesday', 'vbWednesday', 'vbThursday', 'vbFriday', 'vbSaturday', 'vbUseSystemDayOfWeek', 'vbFirstJan1', 'vbFirstFourDays', 'vbFirstFullWeek', - 'vbGeneralDate', 'vbLongDate', 'vbShortDate', 'vbLongTime', 'vbShortTime', 'vbObjectError', - 'vbOKOnly', 'vbOKCancel', 'vbAbortRetryIgnore', 'vbYesNoCancel', 'vbYesNo', 'vbRetryCancel', 'vbCritical', 'vbQuestion', 'vbExclamation', 'vbInformation', 'vbDefaultButton1', 'vbDefaultButton2', - 'vbDefaultButton3', 'vbDefaultButton4', 'vbApplicationModal', 'vbSystemModal', 'vbOK', 'vbCancel', 'vbAbort', 'vbRetry', 'vbIgnore', 'vbYes', 'vbNo', - 'vbCr', 'VbCrLf', 'vbFormFeed', 'vbLf', 'vbNewLine', 'vbNullChar', 'vbNullString', 'vbTab', 'vbVerticalTab', 'vbUseDefault', 'vbTrue', 'vbFalse', - 'vbEmpty', 'vbNull', 'vbInteger', 'vbLong', 'vbSingle', 'vbDouble', 'vbCurrency', 'vbDate', 'vbString', 'vbObject', 'vbError', 'vbBoolean', 'vbVariant', 'vbDataObject', 'vbDecimal', 'vbByte', 'vbArray']; - //This list was from: http://msdn.microsoft.com/en-us/library/hkc375ea(v=vs.84).aspx - var builtinObjsWords = ['WScript', 'err', 'debug', 'RegExp']; - var knownProperties = ['description', 'firstindex', 'global', 'helpcontext', 'helpfile', 'ignorecase', 'length', 'number', 'pattern', 'source', 'value', 'count']; - var knownMethods = ['clear', 'execute', 'raise', 'replace', 'test', 'write', 'writeline', 'close', 'open', 'state', 'eof', 'update', 'addnew', 'end', 'createobject', 'quit']; - - var aspBuiltinObjsWords = ['server', 'response', 'request', 'session', 'application']; - var aspKnownProperties = ['buffer', 'cachecontrol', 'charset', 'contenttype', 'expires', 'expiresabsolute', 'isclientconnected', 'pics', 'status', //response - 'clientcertificate', 'cookies', 'form', 'querystring', 'servervariables', 'totalbytes', //request - 'contents', 'staticobjects', //application - 'codepage', 'lcid', 'sessionid', 'timeout', //session - 'scripttimeout']; //server - var aspKnownMethods = ['addheader', 'appendtolog', 'binarywrite', 'end', 'flush', 'redirect', //response - 'binaryread', //request - 'remove', 'removeall', 'lock', 'unlock', //application - 'abandon', //session - 'getlasterror', 'htmlencode', 'mappath', 'transfer', 'urlencode']; //server - - var knownWords = knownMethods.concat(knownProperties); - - builtinObjsWords = builtinObjsWords.concat(builtinConsts); - - if (conf.isASP){ - builtinObjsWords = builtinObjsWords.concat(aspBuiltinObjsWords); - knownWords = knownWords.concat(aspKnownMethods, aspKnownProperties); - }; - - var keywords = wordRegexp(commonkeywords); - var atoms = wordRegexp(atomWords); - var builtinFuncs = wordRegexp(builtinFuncsWords); - var builtinObjs = wordRegexp(builtinObjsWords); - var known = wordRegexp(knownWords); - var stringPrefixes = '"'; - - var opening = wordRegexp(openingKeywords); - var middle = wordRegexp(middleKeywords); - var closing = wordRegexp(endKeywords); - var doubleClosing = wordRegexp(['end']); - var doOpening = wordRegexp(['do']); - var noIndentWords = wordRegexp(['on error resume next', 'exit']); - var comment = wordRegexp(['rem']); - - - function indent(_stream, state) { - state.currentIndent++; - } - - function dedent(_stream, state) { - state.currentIndent--; - } - // tokenizers - function tokenBase(stream, state) { - if (stream.eatSpace()) { - return 'space'; - //return null; - } - - var ch = stream.peek(); - - // Handle Comments - if (ch === "'") { - stream.skipToEnd(); - return 'comment'; - } - if (stream.match(comment)){ - stream.skipToEnd(); - return 'comment'; - } - - - // Handle Number Literals - if (stream.match(/^((&H)|(&O))?[0-9\.]/i, false) && !stream.match(/^((&H)|(&O))?[0-9\.]+[a-z_]/i, false)) { - var floatLiteral = false; - // Floats - if (stream.match(/^\d*\.\d+/i)) { floatLiteral = true; } - else if (stream.match(/^\d+\.\d*/)) { floatLiteral = true; } - else if (stream.match(/^\.\d+/)) { floatLiteral = true; } - - if (floatLiteral) { - // Float literals may be "imaginary" - stream.eat(/J/i); - return 'number'; - } - // Integers - var intLiteral = false; - // Hex - if (stream.match(/^&H[0-9a-f]+/i)) { intLiteral = true; } - // Octal - else if (stream.match(/^&O[0-7]+/i)) { intLiteral = true; } - // Decimal - else if (stream.match(/^[1-9]\d*F?/)) { - // Decimal literals may be "imaginary" - stream.eat(/J/i); - // TODO - Can you have imaginary longs? - intLiteral = true; - } - // Zero by itself with no other piece of number. - else if (stream.match(/^0(?![\dx])/i)) { intLiteral = true; } - if (intLiteral) { - // Integer literals may be "long" - stream.eat(/L/i); - return 'number'; - } - } - - // Handle Strings - if (stream.match(stringPrefixes)) { - state.tokenize = tokenStringFactory(stream.current()); - return state.tokenize(stream, state); - } - - // Handle operators and Delimiters - if (stream.match(doubleOperators) - || stream.match(singleOperators) - || stream.match(wordOperators)) { - return 'operator'; - } - if (stream.match(singleDelimiters)) { - return null; - } - - if (stream.match(brakets)) { - return "bracket"; - } - - if (stream.match(noIndentWords)) { - state.doInCurrentLine = true; - - return 'keyword'; - } - - if (stream.match(doOpening)) { - indent(stream,state); - state.doInCurrentLine = true; - - return 'keyword'; - } - if (stream.match(opening)) { - if (! state.doInCurrentLine) - indent(stream,state); - else - state.doInCurrentLine = false; - - return 'keyword'; - } - if (stream.match(middle)) { - return 'keyword'; - } - - - if (stream.match(doubleClosing)) { - dedent(stream,state); - dedent(stream,state); - - return 'keyword'; - } - if (stream.match(closing)) { - if (! state.doInCurrentLine) - dedent(stream,state); - else - state.doInCurrentLine = false; - - return 'keyword'; - } - - if (stream.match(keywords)) { - return 'keyword'; - } - - if (stream.match(atoms)) { - return 'atom'; - } - - if (stream.match(known)) { - return 'variable-2'; - } - - if (stream.match(builtinFuncs)) { - return 'builtin'; - } - - if (stream.match(builtinObjs)){ - return 'variable-2'; - } - - if (stream.match(identifiers)) { - return 'variable'; - } - - // Handle non-detected items - stream.next(); - return ERRORCLASS; - } - - function tokenStringFactory(delimiter) { - var singleline = delimiter.length == 1; - var OUTCLASS = 'string'; - - return function(stream, state) { - while (!stream.eol()) { - stream.eatWhile(/[^'"]/); - if (stream.match(delimiter)) { - state.tokenize = tokenBase; - return OUTCLASS; - } else { - stream.eat(/['"]/); - } - } - if (singleline) { - if (parserConf.singleLineStringErrors) { - return ERRORCLASS; - } else { - state.tokenize = tokenBase; - } - } - return OUTCLASS; - }; - } - - - function tokenLexer(stream, state) { - var style = state.tokenize(stream, state); - var current = stream.current(); - - // Handle '.' connected identifiers - if (current === '.') { - style = state.tokenize(stream, state); - - current = stream.current(); - if (style && (style.substr(0, 8) === 'variable' || style==='builtin' || style==='keyword')){//|| knownWords.indexOf(current.substring(1)) > -1) { - if (style === 'builtin' || style === 'keyword') style='variable'; - if (knownWords.indexOf(current.substr(1)) > -1) style='variable-2'; - - return style; - } else { - return ERRORCLASS; - } - } - - return style; - } - - var external = { - electricChars:"dDpPtTfFeE ", - startState: function() { - return { - tokenize: tokenBase, - lastToken: null, - currentIndent: 0, - nextLineIndent: 0, - doInCurrentLine: false, - ignoreKeyword: false - - - }; - }, - - token: function(stream, state) { - if (stream.sol()) { - state.currentIndent += state.nextLineIndent; - state.nextLineIndent = 0; - state.doInCurrentLine = 0; - } - var style = tokenLexer(stream, state); - - state.lastToken = {style:style, content: stream.current()}; - - if (style==='space') style=null; - - return style; - }, - - indent: function(state, textAfter) { - var trueText = textAfter.replace(/^\s+|\s+$/g, '') ; - if (trueText.match(closing) || trueText.match(doubleClosing) || trueText.match(middle)) return conf.indentUnit*(state.currentIndent-1); - if(state.currentIndent < 0) return 0; - return state.currentIndent * conf.indentUnit; - } - - }; - return external; -}); - -CodeMirror.defineMIME("text/vbscript", "vbscript"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/velocity/index.html b/backend/_pv_1_3_5/static/codemirror/mode/velocity/index.html deleted file mode 100755 index 7eba8f418..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/velocity/index.html +++ /dev/null @@ -1,120 +0,0 @@ - - -CodeMirror: Velocity mode - - - - - - - - - - -
    -

    Velocity mode

    -
    - - -

    MIME types defined: text/velocity.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/velocity/velocity.js b/backend/_pv_1_3_5/static/codemirror/mode/velocity/velocity.js deleted file mode 100755 index 12ee22124..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/velocity/velocity.js +++ /dev/null @@ -1,201 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("velocity", function() { - function parseWords(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - var keywords = parseWords("#end #else #break #stop #[[ #]] " + - "#{end} #{else} #{break} #{stop}"); - var functions = parseWords("#if #elseif #foreach #set #include #parse #macro #define #evaluate " + - "#{if} #{elseif} #{foreach} #{set} #{include} #{parse} #{macro} #{define} #{evaluate}"); - var specials = parseWords("$foreach.count $foreach.hasNext $foreach.first $foreach.last $foreach.topmost $foreach.parent.count $foreach.parent.hasNext $foreach.parent.first $foreach.parent.last $foreach.parent $velocityCount $!bodyContent $bodyContent"); - var isOperatorChar = /[+\-*&%=<>!?:\/|]/; - - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - function tokenBase(stream, state) { - var beforeParams = state.beforeParams; - state.beforeParams = false; - var ch = stream.next(); - // start of unparsed string? - if ((ch == "'") && !state.inString && state.inParams) { - state.lastTokenWasBuiltin = false; - return chain(stream, state, tokenString(ch)); - } - // start of parsed string? - else if ((ch == '"')) { - state.lastTokenWasBuiltin = false; - if (state.inString) { - state.inString = false; - return "string"; - } - else if (state.inParams) - return chain(stream, state, tokenString(ch)); - } - // is it one of the special signs []{}().,;? Seperator? - else if (/[\[\]{}\(\),;\.]/.test(ch)) { - if (ch == "(" && beforeParams) - state.inParams = true; - else if (ch == ")") { - state.inParams = false; - state.lastTokenWasBuiltin = true; - } - return null; - } - // start of a number value? - else if (/\d/.test(ch)) { - state.lastTokenWasBuiltin = false; - stream.eatWhile(/[\w\.]/); - return "number"; - } - // multi line comment? - else if (ch == "#" && stream.eat("*")) { - state.lastTokenWasBuiltin = false; - return chain(stream, state, tokenComment); - } - // unparsed content? - else if (ch == "#" && stream.match(/ *\[ *\[/)) { - state.lastTokenWasBuiltin = false; - return chain(stream, state, tokenUnparsed); - } - // single line comment? - else if (ch == "#" && stream.eat("#")) { - state.lastTokenWasBuiltin = false; - stream.skipToEnd(); - return "comment"; - } - // variable? - else if (ch == "$") { - stream.eatWhile(/[\w\d\$_\.{}]/); - // is it one of the specials? - if (specials && specials.propertyIsEnumerable(stream.current())) { - return "keyword"; - } - else { - state.lastTokenWasBuiltin = true; - state.beforeParams = true; - return "builtin"; - } - } - // is it a operator? - else if (isOperatorChar.test(ch)) { - state.lastTokenWasBuiltin = false; - stream.eatWhile(isOperatorChar); - return "operator"; - } - else { - // get the whole word - stream.eatWhile(/[\w\$_{}@]/); - var word = stream.current(); - // is it one of the listed keywords? - if (keywords && keywords.propertyIsEnumerable(word)) - return "keyword"; - // is it one of the listed functions? - if (functions && functions.propertyIsEnumerable(word) || - (stream.current().match(/^#@?[a-z0-9_]+ *$/i) && stream.peek()=="(") && - !(functions && functions.propertyIsEnumerable(word.toLowerCase()))) { - state.beforeParams = true; - state.lastTokenWasBuiltin = false; - return "keyword"; - } - if (state.inString) { - state.lastTokenWasBuiltin = false; - return "string"; - } - if (stream.pos > word.length && stream.string.charAt(stream.pos-word.length-1)=="." && state.lastTokenWasBuiltin) - return "builtin"; - // default: just a "word" - state.lastTokenWasBuiltin = false; - return null; - } - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if ((next == quote) && !escaped) { - end = true; - break; - } - if (quote=='"' && stream.peek() == '$' && !escaped) { - state.inString = true; - end = true; - break; - } - escaped = !escaped && next == "\\"; - } - if (end) state.tokenize = tokenBase; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "#" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function tokenUnparsed(stream, state) { - var maybeEnd = 0, ch; - while (ch = stream.next()) { - if (ch == "#" && maybeEnd == 2) { - state.tokenize = tokenBase; - break; - } - if (ch == "]") - maybeEnd++; - else if (ch != " ") - maybeEnd = 0; - } - return "meta"; - } - // Interface - - return { - startState: function() { - return { - tokenize: tokenBase, - beforeParams: false, - inParams: false, - inString: false, - lastTokenWasBuiltin: false - }; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - return state.tokenize(stream, state); - }, - blockCommentStart: "#*", - blockCommentEnd: "*#", - lineComment: "##", - fold: "velocity" - }; -}); - -CodeMirror.defineMIME("text/velocity", "velocity"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/verilog/index.html b/backend/_pv_1_3_5/static/codemirror/mode/verilog/index.html deleted file mode 100755 index 9c52722af..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/verilog/index.html +++ /dev/null @@ -1,120 +0,0 @@ - - -CodeMirror: Verilog/SystemVerilog mode - - - - - - - - - - -
    -

    SystemVerilog mode

    - -
    - - - -

    -Syntax highlighting and indentation for the Verilog and SystemVerilog languages (IEEE 1800). -

    Configuration options:

    -
      -
    • noIndentKeywords - List of keywords which should not cause indentation to increase. E.g. ["package", "module"]. Default: None
    • -
    -

    - -

    MIME types defined: text/x-verilog and text/x-systemverilog.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/verilog/test.js b/backend/_pv_1_3_5/static/codemirror/mode/verilog/test.js deleted file mode 100755 index 8334fab05..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/verilog/test.js +++ /dev/null @@ -1,273 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 4}, "verilog"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT("binary_literals", - "[number 1'b0]", - "[number 1'b1]", - "[number 1'bx]", - "[number 1'bz]", - "[number 1'bX]", - "[number 1'bZ]", - "[number 1'B0]", - "[number 1'B1]", - "[number 1'Bx]", - "[number 1'Bz]", - "[number 1'BX]", - "[number 1'BZ]", - "[number 1'b0]", - "[number 1'b1]", - "[number 2'b01]", - "[number 2'bxz]", - "[number 2'b11]", - "[number 2'b10]", - "[number 2'b1Z]", - "[number 12'b0101_0101_0101]", - "[number 1'b 0]", - "[number 'b0101]" - ); - - MT("octal_literals", - "[number 3'o7]", - "[number 3'O7]", - "[number 3'so7]", - "[number 3'SO7]" - ); - - MT("decimal_literals", - "[number 0]", - "[number 1]", - "[number 7]", - "[number 123_456]", - "[number 'd33]", - "[number 8'd255]", - "[number 8'D255]", - "[number 8'sd255]", - "[number 8'SD255]", - "[number 32'd123]", - "[number 32 'd123]", - "[number 32 'd 123]" - ); - - MT("hex_literals", - "[number 4'h0]", - "[number 4'ha]", - "[number 4'hF]", - "[number 4'hx]", - "[number 4'hz]", - "[number 4'hX]", - "[number 4'hZ]", - "[number 32'hdc78]", - "[number 32'hDC78]", - "[number 32 'hDC78]", - "[number 32'h DC78]", - "[number 32 'h DC78]", - "[number 32'h44x7]", - "[number 32'hFFF?]" - ); - - MT("real_number_literals", - "[number 1.2]", - "[number 0.1]", - "[number 2394.26331]", - "[number 1.2E12]", - "[number 1.2e12]", - "[number 1.30e-2]", - "[number 0.1e-0]", - "[number 23E10]", - "[number 29E-2]", - "[number 236.123_763_e-12]" - ); - - MT("operators", - "[meta ^]" - ); - - MT("keywords", - "[keyword logic]", - "[keyword logic] [variable foo]", - "[keyword reg] [variable abc]" - ); - - MT("variables", - "[variable _leading_underscore]", - "[variable _if]", - "[number 12] [variable foo]", - "[variable foo] [number 14]" - ); - - MT("tick_defines", - "[def `FOO]", - "[def `foo]", - "[def `FOO_bar]" - ); - - MT("system_calls", - "[meta $display]", - "[meta $vpi_printf]" - ); - - MT("line_comment", "[comment // Hello world]"); - - // Alignment tests - MT("align_port_map_style1", - /** - * mod mod(.a(a), - * .b(b) - * ); - */ - "[variable mod] [variable mod][bracket (].[variable a][bracket (][variable a][bracket )],", - " .[variable b][bracket (][variable b][bracket )]", - " [bracket )];", - "" - ); - - MT("align_port_map_style2", - /** - * mod mod( - * .a(a), - * .b(b) - * ); - */ - "[variable mod] [variable mod][bracket (]", - " .[variable a][bracket (][variable a][bracket )],", - " .[variable b][bracket (][variable b][bracket )]", - "[bracket )];", - "" - ); - - // Indentation tests - MT("indent_single_statement_if", - "[keyword if] [bracket (][variable foo][bracket )]", - " [keyword break];", - "" - ); - - MT("no_indent_after_single_line_if", - "[keyword if] [bracket (][variable foo][bracket )] [keyword break];", - "" - ); - - MT("indent_after_if_begin_same_line", - "[keyword if] [bracket (][variable foo][bracket )] [keyword begin]", - " [keyword break];", - " [keyword break];", - "[keyword end]", - "" - ); - - MT("indent_after_if_begin_next_line", - "[keyword if] [bracket (][variable foo][bracket )]", - " [keyword begin]", - " [keyword break];", - " [keyword break];", - " [keyword end]", - "" - ); - - MT("indent_single_statement_if_else", - "[keyword if] [bracket (][variable foo][bracket )]", - " [keyword break];", - "[keyword else]", - " [keyword break];", - "" - ); - - MT("indent_if_else_begin_same_line", - "[keyword if] [bracket (][variable foo][bracket )] [keyword begin]", - " [keyword break];", - " [keyword break];", - "[keyword end] [keyword else] [keyword begin]", - " [keyword break];", - " [keyword break];", - "[keyword end]", - "" - ); - - MT("indent_if_else_begin_next_line", - "[keyword if] [bracket (][variable foo][bracket )]", - " [keyword begin]", - " [keyword break];", - " [keyword break];", - " [keyword end]", - "[keyword else]", - " [keyword begin]", - " [keyword break];", - " [keyword break];", - " [keyword end]", - "" - ); - - MT("indent_if_nested_without_begin", - "[keyword if] [bracket (][variable foo][bracket )]", - " [keyword if] [bracket (][variable foo][bracket )]", - " [keyword if] [bracket (][variable foo][bracket )]", - " [keyword break];", - "" - ); - - MT("indent_case", - "[keyword case] [bracket (][variable state][bracket )]", - " [variable FOO]:", - " [keyword break];", - " [variable BAR]:", - " [keyword break];", - "[keyword endcase]", - "" - ); - - MT("unindent_after_end_with_preceding_text", - "[keyword begin]", - " [keyword break]; [keyword end]", - "" - ); - - MT("export_function_one_line_does_not_indent", - "[keyword export] [string \"DPI-C\"] [keyword function] [variable helloFromSV];", - "" - ); - - MT("export_task_one_line_does_not_indent", - "[keyword export] [string \"DPI-C\"] [keyword task] [variable helloFromSV];", - "" - ); - - MT("export_function_two_lines_indents_properly", - "[keyword export]", - " [string \"DPI-C\"] [keyword function] [variable helloFromSV];", - "" - ); - - MT("export_task_two_lines_indents_properly", - "[keyword export]", - " [string \"DPI-C\"] [keyword task] [variable helloFromSV];", - "" - ); - - MT("import_function_one_line_does_not_indent", - "[keyword import] [string \"DPI-C\"] [keyword function] [variable helloFromC];", - "" - ); - - MT("import_task_one_line_does_not_indent", - "[keyword import] [string \"DPI-C\"] [keyword task] [variable helloFromC];", - "" - ); - - MT("import_package_single_line_does_not_indent", - "[keyword import] [variable p]::[variable x];", - "[keyword import] [variable p]::[variable y];", - "" - ); - - MT("covergroup_with_function_indents_properly", - "[keyword covergroup] [variable cg] [keyword with] [keyword function] [variable sample][bracket (][keyword bit] [variable b][bracket )];", - " [variable c] : [keyword coverpoint] [variable c];", - "[keyword endgroup]: [variable cg]", - "" - ); - -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/verilog/verilog.js b/backend/_pv_1_3_5/static/codemirror/mode/verilog/verilog.js deleted file mode 100755 index 460cdb3b1..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/verilog/verilog.js +++ /dev/null @@ -1,675 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("verilog", function(config, parserConfig) { - - var indentUnit = config.indentUnit, - statementIndentUnit = parserConfig.statementIndentUnit || indentUnit, - dontAlignCalls = parserConfig.dontAlignCalls, - noIndentKeywords = parserConfig.noIndentKeywords || [], - multiLineStrings = parserConfig.multiLineStrings, - hooks = parserConfig.hooks || {}; - - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - /** - * Keywords from IEEE 1800-2012 - */ - var keywords = words( - "accept_on alias always always_comb always_ff always_latch and assert assign assume automatic before begin bind " + - "bins binsof bit break buf bufif0 bufif1 byte case casex casez cell chandle checker class clocking cmos config " + - "const constraint context continue cover covergroup coverpoint cross deassign default defparam design disable " + - "dist do edge else end endcase endchecker endclass endclocking endconfig endfunction endgenerate endgroup " + - "endinterface endmodule endpackage endprimitive endprogram endproperty endspecify endsequence endtable endtask " + - "enum event eventually expect export extends extern final first_match for force foreach forever fork forkjoin " + - "function generate genvar global highz0 highz1 if iff ifnone ignore_bins illegal_bins implements implies import " + - "incdir include initial inout input inside instance int integer interconnect interface intersect join join_any " + - "join_none large let liblist library local localparam logic longint macromodule matches medium modport module " + - "nand negedge nettype new nexttime nmos nor noshowcancelled not notif0 notif1 null or output package packed " + - "parameter pmos posedge primitive priority program property protected pull0 pull1 pulldown pullup " + - "pulsestyle_ondetect pulsestyle_onevent pure rand randc randcase randsequence rcmos real realtime ref reg " + - "reject_on release repeat restrict return rnmos rpmos rtran rtranif0 rtranif1 s_always s_eventually s_nexttime " + - "s_until s_until_with scalared sequence shortint shortreal showcancelled signed small soft solve specify " + - "specparam static string strong strong0 strong1 struct super supply0 supply1 sync_accept_on sync_reject_on " + - "table tagged task this throughout time timeprecision timeunit tran tranif0 tranif1 tri tri0 tri1 triand trior " + - "trireg type typedef union unique unique0 unsigned until until_with untyped use uwire var vectored virtual void " + - "wait wait_order wand weak weak0 weak1 while wildcard wire with within wor xnor xor"); - - /** Operators from IEEE 1800-2012 - unary_operator ::= - + | - | ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~ - binary_operator ::= - + | - | * | / | % | == | != | === | !== | ==? | !=? | && | || | ** - | < | <= | > | >= | & | | | ^ | ^~ | ~^ | >> | << | >>> | <<< - | -> | <-> - inc_or_dec_operator ::= ++ | -- - unary_module_path_operator ::= - ! | ~ | & | ~& | | | ~| | ^ | ~^ | ^~ - binary_module_path_operator ::= - == | != | && | || | & | | | ^ | ^~ | ~^ - */ - var isOperatorChar = /[\+\-\*\/!~&|^%=?:]/; - var isBracketChar = /[\[\]{}()]/; - - var unsignedNumber = /\d[0-9_]*/; - var decimalLiteral = /\d*\s*'s?d\s*\d[0-9_]*/i; - var binaryLiteral = /\d*\s*'s?b\s*[xz01][xz01_]*/i; - var octLiteral = /\d*\s*'s?o\s*[xz0-7][xz0-7_]*/i; - var hexLiteral = /\d*\s*'s?h\s*[0-9a-fxz?][0-9a-fxz?_]*/i; - var realLiteral = /(\d[\d_]*(\.\d[\d_]*)?E-?[\d_]+)|(\d[\d_]*\.\d[\d_]*)/i; - - var closingBracketOrWord = /^((\w+)|[)}\]])/; - var closingBracket = /[)}\]]/; - - var curPunc; - var curKeyword; - - // Block openings which are closed by a matching keyword in the form of ("end" + keyword) - // E.g. "task" => "endtask" - var blockKeywords = words( - "case checker class clocking config function generate interface module package" + - "primitive program property specify sequence table task" - ); - - // Opening/closing pairs - var openClose = {}; - for (var keyword in blockKeywords) { - openClose[keyword] = "end" + keyword; - } - openClose["begin"] = "end"; - openClose["casex"] = "endcase"; - openClose["casez"] = "endcase"; - openClose["do" ] = "while"; - openClose["fork" ] = "join;join_any;join_none"; - openClose["covergroup"] = "endgroup"; - - for (var i in noIndentKeywords) { - var keyword = noIndentKeywords[i]; - if (openClose[keyword]) { - openClose[keyword] = undefined; - } - } - - // Keywords which open statements that are ended with a semi-colon - var statementKeywords = words("always always_comb always_ff always_latch assert assign assume else export for foreach forever if import initial repeat while"); - - function tokenBase(stream, state) { - var ch = stream.peek(), style; - if (hooks[ch] && (style = hooks[ch](stream, state)) != false) return style; - if (hooks.tokenBase && (style = hooks.tokenBase(stream, state)) != false) - return style; - - if (/[,;:\.]/.test(ch)) { - curPunc = stream.next(); - return null; - } - if (isBracketChar.test(ch)) { - curPunc = stream.next(); - return "bracket"; - } - // Macros (tick-defines) - if (ch == '`') { - stream.next(); - if (stream.eatWhile(/[\w\$_]/)) { - return "def"; - } else { - return null; - } - } - // System calls - if (ch == '$') { - stream.next(); - if (stream.eatWhile(/[\w\$_]/)) { - return "meta"; - } else { - return null; - } - } - // Time literals - if (ch == '#') { - stream.next(); - stream.eatWhile(/[\d_.]/); - return "def"; - } - // Strings - if (ch == '"') { - stream.next(); - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } - // Comments - if (ch == "/") { - stream.next(); - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - stream.backUp(1); - } - - // Numeric literals - if (stream.match(realLiteral) || - stream.match(decimalLiteral) || - stream.match(binaryLiteral) || - stream.match(octLiteral) || - stream.match(hexLiteral) || - stream.match(unsignedNumber) || - stream.match(realLiteral)) { - return "number"; - } - - // Operators - if (stream.eatWhile(isOperatorChar)) { - return "meta"; - } - - // Keywords / plain variables - if (stream.eatWhile(/[\w\$_]/)) { - var cur = stream.current(); - if (keywords[cur]) { - if (openClose[cur]) { - curPunc = "newblock"; - } - if (statementKeywords[cur]) { - curPunc = "newstatement"; - } - curKeyword = cur; - return "keyword"; - } - return "variable"; - } - - stream.next(); - return null; - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next, end = false; - while ((next = stream.next()) != null) { - if (next == quote && !escaped) {end = true; break;} - escaped = !escaped && next == "\\"; - } - if (end || !(escaped || multiLineStrings)) - state.tokenize = tokenBase; - return "string"; - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return "comment"; - } - - function Context(indented, column, type, align, prev) { - this.indented = indented; - this.column = column; - this.type = type; - this.align = align; - this.prev = prev; - } - function pushContext(state, col, type) { - var indent = state.indented; - var c = new Context(indent, col, type, null, state.context); - return state.context = c; - } - function popContext(state) { - var t = state.context.type; - if (t == ")" || t == "]" || t == "}") { - state.indented = state.context.indented; - } - return state.context = state.context.prev; - } - - function isClosing(text, contextClosing) { - if (text == contextClosing) { - return true; - } else { - // contextClosing may be multiple keywords separated by ; - var closingKeywords = contextClosing.split(";"); - for (var i in closingKeywords) { - if (text == closingKeywords[i]) { - return true; - } - } - return false; - } - } - - function buildElectricInputRegEx() { - // Reindentation should occur on any bracket char: {}()[] - // or on a match of any of the block closing keywords, at - // the end of a line - var allClosings = []; - for (var i in openClose) { - if (openClose[i]) { - var closings = openClose[i].split(";"); - for (var j in closings) { - allClosings.push(closings[j]); - } - } - } - var re = new RegExp("[{}()\\[\\]]|(" + allClosings.join("|") + ")$"); - return re; - } - - // Interface - return { - - // Regex to force current line to reindent - electricInput: buildElectricInputRegEx(), - - startState: function(basecolumn) { - var state = { - tokenize: null, - context: new Context((basecolumn || 0) - indentUnit, 0, "top", false), - indented: 0, - startOfLine: true - }; - if (hooks.startState) hooks.startState(state); - return state; - }, - - token: function(stream, state) { - var ctx = state.context; - if (stream.sol()) { - if (ctx.align == null) ctx.align = false; - state.indented = stream.indentation(); - state.startOfLine = true; - } - if (hooks.token) { - // Call hook, with an optional return value of a style to override verilog styling. - var style = hooks.token(stream, state); - if (style !== undefined) { - return style; - } - } - if (stream.eatSpace()) return null; - curPunc = null; - curKeyword = null; - var style = (state.tokenize || tokenBase)(stream, state); - if (style == "comment" || style == "meta" || style == "variable") return style; - if (ctx.align == null) ctx.align = true; - - if (curPunc == ctx.type) { - popContext(state); - } else if ((curPunc == ";" && ctx.type == "statement") || - (ctx.type && isClosing(curKeyword, ctx.type))) { - ctx = popContext(state); - while (ctx && ctx.type == "statement") ctx = popContext(state); - } else if (curPunc == "{") { - pushContext(state, stream.column(), "}"); - } else if (curPunc == "[") { - pushContext(state, stream.column(), "]"); - } else if (curPunc == "(") { - pushContext(state, stream.column(), ")"); - } else if (ctx && ctx.type == "endcase" && curPunc == ":") { - pushContext(state, stream.column(), "statement"); - } else if (curPunc == "newstatement") { - pushContext(state, stream.column(), "statement"); - } else if (curPunc == "newblock") { - if (curKeyword == "function" && ctx && (ctx.type == "statement" || ctx.type == "endgroup")) { - // The 'function' keyword can appear in some other contexts where it actually does not - // indicate a function (import/export DPI and covergroup definitions). - // Do nothing in this case - } else if (curKeyword == "task" && ctx && ctx.type == "statement") { - // Same thing for task - } else { - var close = openClose[curKeyword]; - pushContext(state, stream.column(), close); - } - } - - state.startOfLine = false; - return style; - }, - - indent: function(state, textAfter) { - if (state.tokenize != tokenBase && state.tokenize != null) return CodeMirror.Pass; - if (hooks.indent) { - var fromHook = hooks.indent(state); - if (fromHook >= 0) return fromHook; - } - var ctx = state.context, firstChar = textAfter && textAfter.charAt(0); - if (ctx.type == "statement" && firstChar == "}") ctx = ctx.prev; - var closing = false; - var possibleClosing = textAfter.match(closingBracketOrWord); - if (possibleClosing) - closing = isClosing(possibleClosing[0], ctx.type); - if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : statementIndentUnit); - else if (closingBracket.test(ctx.type) && ctx.align && !dontAlignCalls) return ctx.column + (closing ? 0 : 1); - else if (ctx.type == ")" && !closing) return ctx.indented + statementIndentUnit; - else return ctx.indented + (closing ? 0 : indentUnit); - }, - - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: "//" - }; -}); - - CodeMirror.defineMIME("text/x-verilog", { - name: "verilog" - }); - - CodeMirror.defineMIME("text/x-systemverilog", { - name: "verilog" - }); - - - - // TL-Verilog mode. - // See tl-x.org for language spec. - // See the mode in action at makerchip.com. - // Contact: steve.hoover@redwoodeda.com - - // TLV Identifier prefixes. - // Note that sign is not treated separately, so "+/-" versions of numeric identifiers - // are included. - var tlvIdentifierStyle = { - "|": "link", - ">": "property", // Should condition this off for > TLV 1c. - "$": "variable", - "$$": "variable", - "?$": "qualifier", - "?*": "qualifier", - "-": "hr", - "/": "property", - "/-": "property", - "@": "variable-3", - "@-": "variable-3", - "@++": "variable-3", - "@+=": "variable-3", - "@+=-": "variable-3", - "@--": "variable-3", - "@-=": "variable-3", - "%+": "tag", - "%-": "tag", - "%": "tag", - ">>": "tag", - "<<": "tag", - "<>": "tag", - "#": "tag", // Need to choose a style for this. - "^": "attribute", - "^^": "attribute", - "^!": "attribute", - "*": "variable-2", - "**": "variable-2", - "\\": "keyword", - "\"": "comment" - }; - - // Lines starting with these characters define scope (result in indentation). - var tlvScopePrefixChars = { - "/": "beh-hier", - ">": "beh-hier", - "-": "phys-hier", - "|": "pipe", - "?": "when", - "@": "stage", - "\\": "keyword" - }; - var tlvIndentUnit = 3; - var tlvTrackStatements = false; - var tlvIdentMatch = /^([~!@#\$%\^&\*-\+=\?\/\\\|'"<>]+)([\d\w_]*)/; // Matches an identifiere. - // Note that ':' is excluded, because of it's use in [:]. - var tlvFirstLevelIndentMatch = /^[! ] /; - var tlvLineIndentationMatch = /^[! ] */; - var tlvCommentMatch = /^\/[\/\*]/; - - - // Returns a style specific to the scope at the given indentation column. - // Type is one of: "indent", "scope-ident", "before-scope-ident". - function tlvScopeStyle(state, indentation, type) { - // Begin scope. - var depth = indentation / tlvIndentUnit; // TODO: Pass this in instead. - return "tlv-" + state.tlvIndentationStyle[depth] + "-" + type; - } - - // Return true if the next thing in the stream is an identifier with a mnemonic. - function tlvIdentNext(stream) { - var match; - return (match = stream.match(tlvIdentMatch, false)) && match[2].length > 0; - } - - CodeMirror.defineMIME("text/x-tlv", { - name: "verilog", - - hooks: { - - electricInput: false, - - - // Return undefined for verilog tokenizing, or style for TLV token (null not used). - // Standard CM styles are used for most formatting, but some TL-Verilog-specific highlighting - // can be enabled with the definition of cm-tlv-* styles, including highlighting for: - // - M4 tokens - // - TLV scope indentation - // - Statement delimitation (enabled by tlvTrackStatements) - token: function(stream, state) { - var style = undefined; - var match; // Return value of pattern matches. - - // Set highlighting mode based on code region (TLV or SV). - if (stream.sol() && ! state.tlvInBlockComment) { - // Process region. - if (stream.peek() == '\\') { - style = "def"; - stream.skipToEnd(); - if (stream.string.match(/\\SV/)) { - state.tlvCodeActive = false; - } else if (stream.string.match(/\\TLV/)){ - state.tlvCodeActive = true; - } - } - // Correct indentation in the face of a line prefix char. - if (state.tlvCodeActive && stream.pos == 0 && - (state.indented == 0) && (match = stream.match(tlvLineIndentationMatch, false))) { - state.indented = match[0].length; - } - - // Compute indentation state: - // o Auto indentation on next line - // o Indentation scope styles - var indented = state.indented; - var depth = indented / tlvIndentUnit; - if (depth <= state.tlvIndentationStyle.length) { - // not deeper than current scope - - var blankline = stream.string.length == indented; - var chPos = depth * tlvIndentUnit; - if (chPos < stream.string.length) { - var bodyString = stream.string.slice(chPos); - var ch = bodyString[0]; - if (tlvScopePrefixChars[ch] && ((match = bodyString.match(tlvIdentMatch)) && - tlvIdentifierStyle[match[1]])) { - // This line begins scope. - // Next line gets indented one level. - indented += tlvIndentUnit; - // Style the next level of indentation (except non-region keyword identifiers, - // which are statements themselves) - if (!(ch == "\\" && chPos > 0)) { - state.tlvIndentationStyle[depth] = tlvScopePrefixChars[ch]; - if (tlvTrackStatements) {state.statementComment = false;} - depth++; - } - } - } - // Clear out deeper indentation levels unless line is blank. - if (!blankline) { - while (state.tlvIndentationStyle.length > depth) { - state.tlvIndentationStyle.pop(); - } - } - } - // Set next level of indentation. - state.tlvNextIndent = indented; - } - - if (state.tlvCodeActive) { - // Highlight as TLV. - - var beginStatement = false; - if (tlvTrackStatements) { - // This starts a statement if the position is at the scope level - // and we're not within a statement leading comment. - beginStatement = - (stream.peek() != " ") && // not a space - (style === undefined) && // not a region identifier - !state.tlvInBlockComment && // not in block comment - //!stream.match(tlvCommentMatch, false) && // not comment start - (stream.column() == state.tlvIndentationStyle.length * tlvIndentUnit); // at scope level - if (beginStatement) { - if (state.statementComment) { - // statement already started by comment - beginStatement = false; - } - state.statementComment = - stream.match(tlvCommentMatch, false); // comment start - } - } - - var match; - if (style !== undefined) { - // Region line. - style += " " + tlvScopeStyle(state, 0, "scope-ident") - } else if (((stream.pos / tlvIndentUnit) < state.tlvIndentationStyle.length) && - (match = stream.match(stream.sol() ? tlvFirstLevelIndentMatch : /^ /))) { - // Indentation - style = // make this style distinct from the previous one to prevent - // codemirror from combining spans - "tlv-indent-" + (((stream.pos % 2) == 0) ? "even" : "odd") + - // and style it - " " + tlvScopeStyle(state, stream.pos - tlvIndentUnit, "indent"); - // Style the line prefix character. - if (match[0].charAt(0) == "!") { - style += " tlv-alert-line-prefix"; - } - // Place a class before a scope identifier. - if (tlvIdentNext(stream)) { - style += " " + tlvScopeStyle(state, stream.pos, "before-scope-ident"); - } - } else if (state.tlvInBlockComment) { - // In a block comment. - if (stream.match(/^.*?\*\//)) { - // Exit block comment. - state.tlvInBlockComment = false; - if (tlvTrackStatements && !stream.eol()) { - // Anything after comment is assumed to be real statement content. - state.statementComment = false; - } - } else { - stream.skipToEnd(); - } - style = "comment"; - } else if ((match = stream.match(tlvCommentMatch)) && !state.tlvInBlockComment) { - // Start comment. - if (match[0] == "//") { - // Line comment. - stream.skipToEnd(); - } else { - // Block comment. - state.tlvInBlockComment = true; - } - style = "comment"; - } else if (match = stream.match(tlvIdentMatch)) { - // looks like an identifier (or identifier prefix) - var prefix = match[1]; - var mnemonic = match[2]; - if (// is identifier prefix - (prefix in tlvIdentifierStyle) && - // has mnemonic or we're at the end of the line (maybe it hasn't been typed yet) - (mnemonic.length > 0 || stream.eol())) { - style = tlvIdentifierStyle[prefix]; - if (stream.column() == state.indented) { - // Begin scope. - style += " " + tlvScopeStyle(state, stream.column(), "scope-ident") - } - } else { - // Just swallow one character and try again. - // This enables subsequent identifier match with preceding symbol character, which - // is legal within a statement. (Eg, !$reset). It also enables detection of - // comment start with preceding symbols. - stream.backUp(stream.current().length - 1); - style = "tlv-default"; - } - } else if (stream.match(/^\t+/)) { - // Highlight tabs, which are illegal. - style = "tlv-tab"; - } else if (stream.match(/^[\[\]{}\(\);\:]+/)) { - // [:], (), {}, ;. - style = "meta"; - } else if (match = stream.match(/^[mM]4([\+_])?[\w\d_]*/)) { - // m4 pre proc - style = (match[1] == "+") ? "tlv-m4-plus" : "tlv-m4"; - } else if (stream.match(/^ +/)){ - // Skip over spaces. - if (stream.eol()) { - // Trailing spaces. - style = "error"; - } else { - // Non-trailing spaces. - style = "tlv-default"; - } - } else if (stream.match(/^[\w\d_]+/)) { - // alpha-numeric token. - style = "number"; - } else { - // Eat the next char w/ no formatting. - stream.next(); - style = "tlv-default"; - } - if (beginStatement) { - style += " tlv-statement"; - } - } else { - if (stream.match(/^[mM]4([\w\d_]*)/)) { - // m4 pre proc - style = "tlv-m4"; - } - } - return style; - }, - - indent: function(state) { - return (state.tlvCodeActive == true) ? state.tlvNextIndent : -1; - }, - - startState: function(state) { - state.tlvIndentationStyle = []; // Styles to use for each level of indentation. - state.tlvCodeActive = true; // True when we're in a TLV region (and at beginning of file). - state.tlvNextIndent = -1; // The number of spaces to autoindent the next line if tlvCodeActive. - state.tlvInBlockComment = false; // True inside /**/ comment. - if (tlvTrackStatements) { - state.statementComment = false; // True inside a statement's header comment. - } - } - - } - }); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/vhdl/index.html b/backend/_pv_1_3_5/static/codemirror/mode/vhdl/index.html deleted file mode 100755 index 3051bc37e..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/vhdl/index.html +++ /dev/null @@ -1,95 +0,0 @@ - - -CodeMirror: VHDL mode - - - - - - - - - - -
    -

    VHDL mode

    - -
    - - - -

    -Syntax highlighting and indentation for the VHDL language. -

    Configuration options:

    -
      -
    • atoms - List of atom words. Default: "null"
    • -
    • hooks - List of meta hooks. Default: ["`", "$"]
    • -
    • multiLineStrings - Whether multi-line strings are accepted. Default: false
    • -
    -

    - -

    MIME types defined: text/x-vhdl.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/vhdl/vhdl.js b/backend/_pv_1_3_5/static/codemirror/mode/vhdl/vhdl.js deleted file mode 100755 index 97e086e42..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/vhdl/vhdl.js +++ /dev/null @@ -1,189 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Originally written by Alf Nielsen, re-written by Michael Zhou -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -function words(str) { - var obj = {}, words = str.split(","); - for (var i = 0; i < words.length; ++i) { - var allCaps = words[i].toUpperCase(); - var firstCap = words[i].charAt(0).toUpperCase() + words[i].slice(1); - obj[words[i]] = true; - obj[allCaps] = true; - obj[firstCap] = true; - } - return obj; -} - -function metaHook(stream) { - stream.eatWhile(/[\w\$_]/); - return "meta"; -} - -CodeMirror.defineMode("vhdl", function(config, parserConfig) { - var indentUnit = config.indentUnit, - atoms = parserConfig.atoms || words("null"), - hooks = parserConfig.hooks || {"`": metaHook, "$": metaHook}, - multiLineStrings = parserConfig.multiLineStrings; - - var keywords = words("abs,access,after,alias,all,and,architecture,array,assert,attribute,begin,block," + - "body,buffer,bus,case,component,configuration,constant,disconnect,downto,else,elsif,end,end block,end case," + - "end component,end for,end generate,end if,end loop,end process,end record,end units,entity,exit,file,for," + - "function,generate,generic,generic map,group,guarded,if,impure,in,inertial,inout,is,label,library,linkage," + - "literal,loop,map,mod,nand,new,next,nor,null,of,on,open,or,others,out,package,package body,port,port map," + - "postponed,procedure,process,pure,range,record,register,reject,rem,report,return,rol,ror,select,severity,signal," + - "sla,sll,sra,srl,subtype,then,to,transport,type,unaffected,units,until,use,variable,wait,when,while,with,xnor,xor"); - - var blockKeywords = words("architecture,entity,begin,case,port,else,elsif,end,for,function,if"); - - var isOperatorChar = /[&|~> - -CodeMirror: Vue.js mode - - - - - - - - - - - - - - - - - - - - - -
    -

    Vue.js mode

    -
    - - -

    MIME types defined: text/x-vue

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/vue/vue.js b/backend/_pv_1_3_5/static/codemirror/mode/vue/vue.js deleted file mode 100755 index c0eab6b82..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/vue/vue.js +++ /dev/null @@ -1,70 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function (mod) { - "use strict"; - if (typeof exports === "object" && typeof module === "object") {// CommonJS - mod(require("../../lib/codemirror"), - require("../../addon/mode/overlay"), - require("../xml/xml"), - require("../javascript/javascript"), - require("../coffeescript/coffeescript"), - require("../css/css"), - require("../sass/sass"), - require("../stylus/stylus"), - require("../pug/pug"), - require("../handlebars/handlebars")); - } else if (typeof define === "function" && define.amd) { // AMD - define(["../../lib/codemirror", - "../../addon/mode/overlay", - "../xml/xml", - "../javascript/javascript", - "../coffeescript/coffeescript", - "../css/css", - "../sass/sass", - "../stylus/stylus", - "../pug/pug", - "../handlebars/handlebars"], mod); - } else { // Plain browser env - mod(CodeMirror); - } -})(function (CodeMirror) { - var tagLanguages = { - script: [ - ["lang", /coffee(script)?/, "coffeescript"], - ["type", /^(?:text|application)\/(?:x-)?coffee(?:script)?$/, "coffeescript"] - ], - style: [ - ["lang", /^stylus$/i, "stylus"], - ["lang", /^sass$/i, "sass"], - ["type", /^(text\/)?(x-)?styl(us)?$/i, "stylus"], - ["type", /^text\/sass/i, "sass"] - ], - template: [ - ["lang", /^vue-template$/i, "vue"], - ["lang", /^pug$/i, "pug"], - ["lang", /^handlebars$/i, "handlebars"], - ["type", /^(text\/)?(x-)?pug$/i, "pug"], - ["type", /^text\/x-handlebars-template$/i, "handlebars"], - [null, null, "vue-template"] - ] - }; - - CodeMirror.defineMode("vue-template", function (config, parserConfig) { - var mustacheOverlay = { - token: function (stream) { - if (stream.match(/^\{\{.*?\}\}/)) return "meta mustache"; - while (stream.next() && !stream.match("{{", false)) {} - return null; - } - }; - return CodeMirror.overlayMode(CodeMirror.getMode(config, parserConfig.backdrop || "text/html"), mustacheOverlay); - }); - - CodeMirror.defineMode("vue", function (config) { - return CodeMirror.getMode(config, {name: "htmlmixed", tags: tagLanguages}); - }, "htmlmixed", "xml", "javascript", "coffeescript", "css", "sass", "stylus", "pug", "handlebars"); - - CodeMirror.defineMIME("script/x-vue", "vue"); - CodeMirror.defineMIME("text/x-vue", "vue"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/webidl/index.html b/backend/_pv_1_3_5/static/codemirror/mode/webidl/index.html deleted file mode 100755 index 1d4112e1c..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/webidl/index.html +++ /dev/null @@ -1,71 +0,0 @@ - - -CodeMirror: Web IDL mode - - - - - - - - - - -
    -

    Web IDL mode

    - -
    - -
    - - - -

    MIME type defined: text/x-webidl.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/webidl/webidl.js b/backend/_pv_1_3_5/static/codemirror/mode/webidl/webidl.js deleted file mode 100755 index 814333620..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/webidl/webidl.js +++ /dev/null @@ -1,195 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -function wordRegexp(words) { - return new RegExp("^((" + words.join(")|(") + "))\\b"); -}; - -var builtinArray = [ - "Clamp", - "Constructor", - "EnforceRange", - "Exposed", - "ImplicitThis", - "Global", "PrimaryGlobal", - "LegacyArrayClass", - "LegacyUnenumerableNamedProperties", - "LenientThis", - "NamedConstructor", - "NewObject", - "NoInterfaceObject", - "OverrideBuiltins", - "PutForwards", - "Replaceable", - "SameObject", - "TreatNonObjectAsNull", - "TreatNullAs", - "EmptyString", - "Unforgeable", - "Unscopeable" -]; -var builtins = wordRegexp(builtinArray); - -var typeArray = [ - "unsigned", "short", "long", // UnsignedIntegerType - "unrestricted", "float", "double", // UnrestrictedFloatType - "boolean", "byte", "octet", // Rest of PrimitiveType - "Promise", // PromiseType - "ArrayBuffer", "DataView", "Int8Array", "Int16Array", "Int32Array", - "Uint8Array", "Uint16Array", "Uint32Array", "Uint8ClampedArray", - "Float32Array", "Float64Array", // BufferRelatedType - "ByteString", "DOMString", "USVString", "sequence", "object", "RegExp", - "Error", "DOMException", "FrozenArray", // Rest of NonAnyType - "any", // Rest of SingleType - "void" // Rest of ReturnType -]; -var types = wordRegexp(typeArray); - -var keywordArray = [ - "attribute", "callback", "const", "deleter", "dictionary", "enum", "getter", - "implements", "inherit", "interface", "iterable", "legacycaller", "maplike", - "partial", "required", "serializer", "setlike", "setter", "static", - "stringifier", "typedef", // ArgumentNameKeyword except - // "unrestricted" - "optional", "readonly", "or" -]; -var keywords = wordRegexp(keywordArray); - -var atomArray = [ - "true", "false", // BooleanLiteral - "Infinity", "NaN", // FloatLiteral - "null" // Rest of ConstValue -]; -var atoms = wordRegexp(atomArray); - -CodeMirror.registerHelper("hintWords", "webidl", - builtinArray.concat(typeArray).concat(keywordArray).concat(atomArray)); - -var startDefArray = ["callback", "dictionary", "enum", "interface"]; -var startDefs = wordRegexp(startDefArray); - -var endDefArray = ["typedef"]; -var endDefs = wordRegexp(endDefArray); - -var singleOperators = /^[:<=>?]/; -var integers = /^-?([1-9][0-9]*|0[Xx][0-9A-Fa-f]+|0[0-7]*)/; -var floats = /^-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+)/; -var identifiers = /^_?[A-Za-z][0-9A-Z_a-z-]*/; -var identifiersEnd = /^_?[A-Za-z][0-9A-Z_a-z-]*(?=\s*;)/; -var strings = /^"[^"]*"/; -var multilineComments = /^\/\*.*?\*\//; -var multilineCommentsStart = /^\/\*.*/; -var multilineCommentsEnd = /^.*?\*\//; - -function readToken(stream, state) { - // whitespace - if (stream.eatSpace()) return null; - - // comment - if (state.inComment) { - if (stream.match(multilineCommentsEnd)) { - state.inComment = false; - return "comment"; - } - stream.skipToEnd(); - return "comment"; - } - if (stream.match("//")) { - stream.skipToEnd(); - return "comment"; - } - if (stream.match(multilineComments)) return "comment"; - if (stream.match(multilineCommentsStart)) { - state.inComment = true; - return "comment"; - } - - // integer and float - if (stream.match(/^-?[0-9\.]/, false)) { - if (stream.match(integers) || stream.match(floats)) return "number"; - } - - // string - if (stream.match(strings)) return "string"; - - // identifier - if (state.startDef && stream.match(identifiers)) return "def"; - - if (state.endDef && stream.match(identifiersEnd)) { - state.endDef = false; - return "def"; - } - - if (stream.match(keywords)) return "keyword"; - - if (stream.match(types)) { - var lastToken = state.lastToken; - var nextToken = (stream.match(/^\s*(.+?)\b/, false) || [])[1]; - - if (lastToken === ":" || lastToken === "implements" || - nextToken === "implements" || nextToken === "=") { - // Used as identifier - return "builtin"; - } else { - // Used as type - return "variable-3"; - } - } - - if (stream.match(builtins)) return "builtin"; - if (stream.match(atoms)) return "atom"; - if (stream.match(identifiers)) return "variable"; - - // other - if (stream.match(singleOperators)) return "operator"; - - // unrecognized - stream.next(); - return null; -}; - -CodeMirror.defineMode("webidl", function() { - return { - startState: function() { - return { - // Is in multiline comment - inComment: false, - // Last non-whitespace, matched token - lastToken: "", - // Next token is a definition - startDef: false, - // Last token of the statement is a definition - endDef: false - }; - }, - token: function(stream, state) { - var style = readToken(stream, state); - - if (style) { - var cur = stream.current(); - state.lastToken = cur; - if (style === "keyword") { - state.startDef = startDefs.test(cur); - state.endDef = state.endDef || endDefs.test(cur); - } else { - state.startDef = false; - } - } - - return style; - } - }; -}); - -CodeMirror.defineMIME("text/x-webidl", "webidl"); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/xml/index.html b/backend/_pv_1_3_5/static/codemirror/mode/xml/index.html deleted file mode 100755 index c56b8b6eb..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/xml/index.html +++ /dev/null @@ -1,61 +0,0 @@ - - -CodeMirror: XML mode - - - - - - - - - -
    -

    XML mode

    -
    - -

    The XML mode supports these configuration parameters:

    -
    -
    htmlMode (boolean)
    -
    This switches the mode to parse HTML instead of XML. This - means attributes do not have to be quoted, and some elements - (such as br) do not require a closing tag.
    -
    matchClosing (boolean)
    -
    Controls whether the mode checks that close tags match the - corresponding opening tag, and highlights mismatches as errors. - Defaults to true.
    -
    alignCDATA (boolean)
    -
    Setting this to true will force the opening tag of CDATA - blocks to not be indented.
    -
    - -

    MIME types defined: application/xml, text/html.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/xml/test.js b/backend/_pv_1_3_5/static/codemirror/mode/xml/test.js deleted file mode 100755 index f48156b51..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/xml/test.js +++ /dev/null @@ -1,51 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var mode = CodeMirror.getMode({indentUnit: 2}, "xml"), mname = "xml"; - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), mname); } - - MT("matching", - "[tag&bracket <][tag top][tag&bracket >]", - " text", - " [tag&bracket <][tag inner][tag&bracket />]", - "[tag&bracket ]"); - - MT("nonmatching", - "[tag&bracket <][tag top][tag&bracket >]", - " [tag&bracket <][tag inner][tag&bracket />]", - " [tag&bracket ]"); - - MT("doctype", - "[meta ]", - "[tag&bracket <][tag top][tag&bracket />]"); - - MT("cdata", - "[tag&bracket <][tag top][tag&bracket >]", - " [atom ]", - "[tag&bracket ]"); - - // HTML tests - mode = CodeMirror.getMode({indentUnit: 2}, "text/html"); - - MT("selfclose", - "[tag&bracket <][tag html][tag&bracket >]", - " [tag&bracket <][tag link] [attribute rel]=[string stylesheet] [attribute href]=[string \"/foobar\"][tag&bracket >]", - "[tag&bracket ]"); - - MT("list", - "[tag&bracket <][tag ol][tag&bracket >]", - " [tag&bracket <][tag li][tag&bracket >]one", - " [tag&bracket <][tag li][tag&bracket >]two", - "[tag&bracket ]"); - - MT("valueless", - "[tag&bracket <][tag input] [attribute type]=[string checkbox] [attribute checked][tag&bracket />]"); - - MT("pThenArticle", - "[tag&bracket <][tag p][tag&bracket >]", - " foo", - "[tag&bracket <][tag article][tag&bracket >]bar"); - -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/xml/xml.js b/backend/_pv_1_3_5/static/codemirror/mode/xml/xml.js deleted file mode 100755 index f987a3a3c..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/xml/xml.js +++ /dev/null @@ -1,394 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -var htmlConfig = { - autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true, - 'embed': true, 'frame': true, 'hr': true, 'img': true, 'input': true, - 'keygen': true, 'link': true, 'meta': true, 'param': true, 'source': true, - 'track': true, 'wbr': true, 'menuitem': true}, - implicitlyClosed: {'dd': true, 'li': true, 'optgroup': true, 'option': true, 'p': true, - 'rp': true, 'rt': true, 'tbody': true, 'td': true, 'tfoot': true, - 'th': true, 'tr': true}, - contextGrabbers: { - 'dd': {'dd': true, 'dt': true}, - 'dt': {'dd': true, 'dt': true}, - 'li': {'li': true}, - 'option': {'option': true, 'optgroup': true}, - 'optgroup': {'optgroup': true}, - 'p': {'address': true, 'article': true, 'aside': true, 'blockquote': true, 'dir': true, - 'div': true, 'dl': true, 'fieldset': true, 'footer': true, 'form': true, - 'h1': true, 'h2': true, 'h3': true, 'h4': true, 'h5': true, 'h6': true, - 'header': true, 'hgroup': true, 'hr': true, 'menu': true, 'nav': true, 'ol': true, - 'p': true, 'pre': true, 'section': true, 'table': true, 'ul': true}, - 'rp': {'rp': true, 'rt': true}, - 'rt': {'rp': true, 'rt': true}, - 'tbody': {'tbody': true, 'tfoot': true}, - 'td': {'td': true, 'th': true}, - 'tfoot': {'tbody': true}, - 'th': {'td': true, 'th': true}, - 'thead': {'tbody': true, 'tfoot': true}, - 'tr': {'tr': true} - }, - doNotIndent: {"pre": true}, - allowUnquoted: true, - allowMissing: true, - caseFold: true -} - -var xmlConfig = { - autoSelfClosers: {}, - implicitlyClosed: {}, - contextGrabbers: {}, - doNotIndent: {}, - allowUnquoted: false, - allowMissing: false, - caseFold: false -} - -CodeMirror.defineMode("xml", function(editorConf, config_) { - var indentUnit = editorConf.indentUnit - var config = {} - var defaults = config_.htmlMode ? htmlConfig : xmlConfig - for (var prop in defaults) config[prop] = defaults[prop] - for (var prop in config_) config[prop] = config_[prop] - - // Return variables for tokenizers - var type, setStyle; - - function inText(stream, state) { - function chain(parser) { - state.tokenize = parser; - return parser(stream, state); - } - - var ch = stream.next(); - if (ch == "<") { - if (stream.eat("!")) { - if (stream.eat("[")) { - if (stream.match("CDATA[")) return chain(inBlock("atom", "]]>")); - else return null; - } else if (stream.match("--")) { - return chain(inBlock("comment", "-->")); - } else if (stream.match("DOCTYPE", true, true)) { - stream.eatWhile(/[\w\._\-]/); - return chain(doctype(1)); - } else { - return null; - } - } else if (stream.eat("?")) { - stream.eatWhile(/[\w\._\-]/); - state.tokenize = inBlock("meta", "?>"); - return "meta"; - } else { - type = stream.eat("/") ? "closeTag" : "openTag"; - state.tokenize = inTag; - return "tag bracket"; - } - } else if (ch == "&") { - var ok; - if (stream.eat("#")) { - if (stream.eat("x")) { - ok = stream.eatWhile(/[a-fA-F\d]/) && stream.eat(";"); - } else { - ok = stream.eatWhile(/[\d]/) && stream.eat(";"); - } - } else { - ok = stream.eatWhile(/[\w\.\-:]/) && stream.eat(";"); - } - return ok ? "atom" : "error"; - } else { - stream.eatWhile(/[^&<]/); - return null; - } - } - inText.isInText = true; - - function inTag(stream, state) { - var ch = stream.next(); - if (ch == ">" || (ch == "/" && stream.eat(">"))) { - state.tokenize = inText; - type = ch == ">" ? "endTag" : "selfcloseTag"; - return "tag bracket"; - } else if (ch == "=") { - type = "equals"; - return null; - } else if (ch == "<") { - state.tokenize = inText; - state.state = baseState; - state.tagName = state.tagStart = null; - var next = state.tokenize(stream, state); - return next ? next + " tag error" : "tag error"; - } else if (/[\'\"]/.test(ch)) { - state.tokenize = inAttribute(ch); - state.stringStartCol = stream.column(); - return state.tokenize(stream, state); - } else { - stream.match(/^[^\s\u00a0=<>\"\']*[^\s\u00a0=<>\"\'\/]/); - return "word"; - } - } - - function inAttribute(quote) { - var closure = function(stream, state) { - while (!stream.eol()) { - if (stream.next() == quote) { - state.tokenize = inTag; - break; - } - } - return "string"; - }; - closure.isInAttribute = true; - return closure; - } - - function inBlock(style, terminator) { - return function(stream, state) { - while (!stream.eol()) { - if (stream.match(terminator)) { - state.tokenize = inText; - break; - } - stream.next(); - } - return style; - }; - } - function doctype(depth) { - return function(stream, state) { - var ch; - while ((ch = stream.next()) != null) { - if (ch == "<") { - state.tokenize = doctype(depth + 1); - return state.tokenize(stream, state); - } else if (ch == ">") { - if (depth == 1) { - state.tokenize = inText; - break; - } else { - state.tokenize = doctype(depth - 1); - return state.tokenize(stream, state); - } - } - } - return "meta"; - }; - } - - function Context(state, tagName, startOfLine) { - this.prev = state.context; - this.tagName = tagName; - this.indent = state.indented; - this.startOfLine = startOfLine; - if (config.doNotIndent.hasOwnProperty(tagName) || (state.context && state.context.noIndent)) - this.noIndent = true; - } - function popContext(state) { - if (state.context) state.context = state.context.prev; - } - function maybePopContext(state, nextTagName) { - var parentTagName; - while (true) { - if (!state.context) { - return; - } - parentTagName = state.context.tagName; - if (!config.contextGrabbers.hasOwnProperty(parentTagName) || - !config.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)) { - return; - } - popContext(state); - } - } - - function baseState(type, stream, state) { - if (type == "openTag") { - state.tagStart = stream.column(); - return tagNameState; - } else if (type == "closeTag") { - return closeTagNameState; - } else { - return baseState; - } - } - function tagNameState(type, stream, state) { - if (type == "word") { - state.tagName = stream.current(); - setStyle = "tag"; - return attrState; - } else { - setStyle = "error"; - return tagNameState; - } - } - function closeTagNameState(type, stream, state) { - if (type == "word") { - var tagName = stream.current(); - if (state.context && state.context.tagName != tagName && - config.implicitlyClosed.hasOwnProperty(state.context.tagName)) - popContext(state); - if ((state.context && state.context.tagName == tagName) || config.matchClosing === false) { - setStyle = "tag"; - return closeState; - } else { - setStyle = "tag error"; - return closeStateErr; - } - } else { - setStyle = "error"; - return closeStateErr; - } - } - - function closeState(type, _stream, state) { - if (type != "endTag") { - setStyle = "error"; - return closeState; - } - popContext(state); - return baseState; - } - function closeStateErr(type, stream, state) { - setStyle = "error"; - return closeState(type, stream, state); - } - - function attrState(type, _stream, state) { - if (type == "word") { - setStyle = "attribute"; - return attrEqState; - } else if (type == "endTag" || type == "selfcloseTag") { - var tagName = state.tagName, tagStart = state.tagStart; - state.tagName = state.tagStart = null; - if (type == "selfcloseTag" || - config.autoSelfClosers.hasOwnProperty(tagName)) { - maybePopContext(state, tagName); - } else { - maybePopContext(state, tagName); - state.context = new Context(state, tagName, tagStart == state.indented); - } - return baseState; - } - setStyle = "error"; - return attrState; - } - function attrEqState(type, stream, state) { - if (type == "equals") return attrValueState; - if (!config.allowMissing) setStyle = "error"; - return attrState(type, stream, state); - } - function attrValueState(type, stream, state) { - if (type == "string") return attrContinuedState; - if (type == "word" && config.allowUnquoted) {setStyle = "string"; return attrState;} - setStyle = "error"; - return attrState(type, stream, state); - } - function attrContinuedState(type, stream, state) { - if (type == "string") return attrContinuedState; - return attrState(type, stream, state); - } - - return { - startState: function(baseIndent) { - var state = {tokenize: inText, - state: baseState, - indented: baseIndent || 0, - tagName: null, tagStart: null, - context: null} - if (baseIndent != null) state.baseIndent = baseIndent - return state - }, - - token: function(stream, state) { - if (!state.tagName && stream.sol()) - state.indented = stream.indentation(); - - if (stream.eatSpace()) return null; - type = null; - var style = state.tokenize(stream, state); - if ((style || type) && style != "comment") { - setStyle = null; - state.state = state.state(type || style, stream, state); - if (setStyle) - style = setStyle == "error" ? style + " error" : setStyle; - } - return style; - }, - - indent: function(state, textAfter, fullLine) { - var context = state.context; - // Indent multi-line strings (e.g. css). - if (state.tokenize.isInAttribute) { - if (state.tagStart == state.indented) - return state.stringStartCol + 1; - else - return state.indented + indentUnit; - } - if (context && context.noIndent) return CodeMirror.Pass; - if (state.tokenize != inTag && state.tokenize != inText) - return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0; - // Indent the starts of attribute names. - if (state.tagName) { - if (config.multilineTagIndentPastTag !== false) - return state.tagStart + state.tagName.length + 2; - else - return state.tagStart + indentUnit * (config.multilineTagIndentFactor || 1); - } - if (config.alignCDATA && /$/, - blockCommentStart: "", - - configuration: config.htmlMode ? "html" : "xml", - helperType: config.htmlMode ? "html" : "xml", - - skipAttribute: function(state) { - if (state.state == attrValueState) - state.state = attrState - } - }; -}); - -CodeMirror.defineMIME("text/xml", "xml"); -CodeMirror.defineMIME("application/xml", "xml"); -if (!CodeMirror.mimeModes.hasOwnProperty("text/html")) - CodeMirror.defineMIME("text/html", {name: "xml", htmlMode: true}); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/xquery/index.html b/backend/_pv_1_3_5/static/codemirror/mode/xquery/index.html deleted file mode 100755 index 7ac5aaeff..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/xquery/index.html +++ /dev/null @@ -1,210 +0,0 @@ - - -CodeMirror: XQuery mode - - - - - - - - - - -
    -

    XQuery mode

    - - -
    - -
    - - - -

    MIME types defined: application/xquery.

    - -

    Development of the CodeMirror XQuery mode was sponsored by - MarkLogic and developed by - Mike Brevoort. -

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/xquery/test.js b/backend/_pv_1_3_5/static/codemirror/mode/xquery/test.js deleted file mode 100755 index 1f148cdbb..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/xquery/test.js +++ /dev/null @@ -1,67 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Don't take these too seriously -- the expected results appear to be -// based on the results of actual runs without any serious manual -// verification. If a change you made causes them to fail, the test is -// as likely to wrong as the code. - -(function() { - var mode = CodeMirror.getMode({tabSize: 4}, "xquery"); - function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } - - MT("eviltest", - "[keyword xquery] [keyword version] [variable "1][keyword .][atom 0][keyword -][variable ml"][def&variable ;] [comment (: this is : a \"comment\" :)]", - " [keyword let] [variable $let] [keyword :=] [variable <x] [variable attr][keyword =][variable "value">"test"<func>][def&variable ;function]() [variable $var] {[keyword function]()} {[variable $var]}[variable <][keyword /][variable func><][keyword /][variable x>]", - " [keyword let] [variable $joe][keyword :=][atom 1]", - " [keyword return] [keyword element] [variable element] {", - " [keyword attribute] [variable attribute] { [atom 1] },", - " [keyword element] [variable test] { [variable 'a'] }, [keyword attribute] [variable foo] { [variable "bar"] },", - " [def&variable fn:doc]()[[ [variable foo][keyword /][variable @bar] [keyword eq] [variable $let] ]],", - " [keyword //][variable x] } [comment (: a more 'evil' test :)]", - " [comment (: Modified Blakeley example (: with nested comment :) ... :)]", - " [keyword declare] [keyword private] [keyword function] [def&variable local:declare]() {()}[variable ;]", - " [keyword declare] [keyword private] [keyword function] [def&variable local:private]() {()}[variable ;]", - " [keyword declare] [keyword private] [keyword function] [def&variable local:function]() {()}[variable ;]", - " [keyword declare] [keyword private] [keyword function] [def&variable local:local]() {()}[variable ;]", - " [keyword let] [variable $let] [keyword :=] [variable <let>let] [variable $let] [keyword :=] [variable "let"<][keyword /let][variable >]", - " [keyword return] [keyword element] [variable element] {", - " [keyword attribute] [variable attribute] { [keyword try] { [def&variable xdmp:version]() } [keyword catch]([variable $e]) { [def&variable xdmp:log]([variable $e]) } },", - " [keyword attribute] [variable fn:doc] { [variable "bar"] [variable castable] [keyword as] [atom xs:string] },", - " [keyword element] [variable text] { [keyword text] { [variable "text"] } },", - " [def&variable fn:doc]()[[ [qualifier child::][variable eq][keyword /]([variable @bar] [keyword |] [qualifier attribute::][variable attribute]) [keyword eq] [variable $let] ]],", - " [keyword //][variable fn:doc]", - " }"); - - MT("testEmptySequenceKeyword", - "[string \"foo\"] [keyword instance] [keyword of] [keyword empty-sequence]()"); - - MT("testMultiAttr", - "[tag

    ][variable hello] [variable world][tag

    ]"); - - MT("test namespaced variable", - "[keyword declare] [keyword namespace] [variable e] [keyword =] [string \"http://example.com/ANamespace\"][variable ;declare] [keyword variable] [variable $e:exampleComThisVarIsNotRecognized] [keyword as] [keyword element]([keyword *]) [variable external;]"); - - MT("test EQName variable", - "[keyword declare] [keyword variable] [variable $\"http://www.example.com/ns/my\":var] [keyword :=] [atom 12][variable ;]", - "[tag ]{[variable $\"http://www.example.com/ns/my\":var]}[tag ]"); - - MT("test EQName function", - "[keyword declare] [keyword function] [def&variable \"http://www.example.com/ns/my\":fn] ([variable $a] [keyword as] [atom xs:integer]) [keyword as] [atom xs:integer] {", - " [variable $a] [keyword +] [atom 2]", - "}[variable ;]", - "[tag ]{[def&variable \"http://www.example.com/ns/my\":fn]([atom 12])}[tag ]"); - - MT("test EQName function with single quotes", - "[keyword declare] [keyword function] [def&variable 'http://www.example.com/ns/my':fn] ([variable $a] [keyword as] [atom xs:integer]) [keyword as] [atom xs:integer] {", - " [variable $a] [keyword +] [atom 2]", - "}[variable ;]", - "[tag ]{[def&variable 'http://www.example.com/ns/my':fn]([atom 12])}[tag ]"); - - MT("testProcessingInstructions", - "[def&variable data]([comment&meta ]) [keyword instance] [keyword of] [atom xs:string]"); - - MT("testQuoteEscapeDouble", - "[keyword let] [variable $rootfolder] [keyword :=] [string \"c:\\builds\\winnt\\HEAD\\qa\\scripts\\\"]", - "[keyword let] [variable $keysfolder] [keyword :=] [def&variable concat]([variable $rootfolder], [string \"keys\\\"])"); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/xquery/xquery.js b/backend/_pv_1_3_5/static/codemirror/mode/xquery/xquery.js deleted file mode 100755 index 75dcbee3e..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/xquery/xquery.js +++ /dev/null @@ -1,437 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("xquery", function() { - - // The keywords object is set to the result of this self executing - // function. Each keyword is a property of the keywords object whose - // value is {type: atype, style: astyle} - var keywords = function(){ - // convenience functions used to build keywords object - function kw(type) {return {type: type, style: "keyword"};} - var A = kw("keyword a") - , B = kw("keyword b") - , C = kw("keyword c") - , operator = kw("operator") - , atom = {type: "atom", style: "atom"} - , punctuation = {type: "punctuation", style: null} - , qualifier = {type: "axis_specifier", style: "qualifier"}; - - // kwObj is what is return from this function at the end - var kwObj = { - 'if': A, 'switch': A, 'while': A, 'for': A, - 'else': B, 'then': B, 'try': B, 'finally': B, 'catch': B, - 'element': C, 'attribute': C, 'let': C, 'implements': C, 'import': C, 'module': C, 'namespace': C, - 'return': C, 'super': C, 'this': C, 'throws': C, 'where': C, 'private': C, - ',': punctuation, - 'null': atom, 'fn:false()': atom, 'fn:true()': atom - }; - - // a list of 'basic' keywords. For each add a property to kwObj with the value of - // {type: basic[i], style: "keyword"} e.g. 'after' --> {type: "after", style: "keyword"} - var basic = ['after','ancestor','ancestor-or-self','and','as','ascending','assert','attribute','before', - 'by','case','cast','child','comment','declare','default','define','descendant','descendant-or-self', - 'descending','document','document-node','element','else','eq','every','except','external','following', - 'following-sibling','follows','for','function','if','import','in','instance','intersect','item', - 'let','module','namespace','node','node','of','only','or','order','parent','precedes','preceding', - 'preceding-sibling','processing-instruction','ref','return','returns','satisfies','schema','schema-element', - 'self','some','sortby','stable','text','then','to','treat','typeswitch','union','variable','version','where', - 'xquery', 'empty-sequence']; - for(var i=0, l=basic.length; i < l; i++) { kwObj[basic[i]] = kw(basic[i]);}; - - // a list of types. For each add a property to kwObj with the value of - // {type: "atom", style: "atom"} - var types = ['xs:string', 'xs:float', 'xs:decimal', 'xs:double', 'xs:integer', 'xs:boolean', 'xs:date', 'xs:dateTime', - 'xs:time', 'xs:duration', 'xs:dayTimeDuration', 'xs:time', 'xs:yearMonthDuration', 'numeric', 'xs:hexBinary', - 'xs:base64Binary', 'xs:anyURI', 'xs:QName', 'xs:byte','xs:boolean','xs:anyURI','xf:yearMonthDuration']; - for(var i=0, l=types.length; i < l; i++) { kwObj[types[i]] = atom;}; - - // each operator will add a property to kwObj with value of {type: "operator", style: "keyword"} - var operators = ['eq', 'ne', 'lt', 'le', 'gt', 'ge', ':=', '=', '>', '>=', '<', '<=', '.', '|', '?', 'and', 'or', 'div', 'idiv', 'mod', '*', '/', '+', '-']; - for(var i=0, l=operators.length; i < l; i++) { kwObj[operators[i]] = operator;}; - - // each axis_specifiers will add a property to kwObj with value of {type: "axis_specifier", style: "qualifier"} - var axis_specifiers = ["self::", "attribute::", "child::", "descendant::", "descendant-or-self::", "parent::", - "ancestor::", "ancestor-or-self::", "following::", "preceding::", "following-sibling::", "preceding-sibling::"]; - for(var i=0, l=axis_specifiers.length; i < l; i++) { kwObj[axis_specifiers[i]] = qualifier; }; - - return kwObj; - }(); - - function chain(stream, state, f) { - state.tokenize = f; - return f(stream, state); - } - - // the primary mode tokenizer - function tokenBase(stream, state) { - var ch = stream.next(), - mightBeFunction = false, - isEQName = isEQNameAhead(stream); - - // an XML tag (if not in some sub, chained tokenizer) - if (ch == "<") { - if(stream.match("!--", true)) - return chain(stream, state, tokenXMLComment); - - if(stream.match("![CDATA", false)) { - state.tokenize = tokenCDATA; - return "tag"; - } - - if(stream.match("?", false)) { - return chain(stream, state, tokenPreProcessing); - } - - var isclose = stream.eat("/"); - stream.eatSpace(); - var tagName = "", c; - while ((c = stream.eat(/[^\s\u00a0=<>\"\'\/?]/))) tagName += c; - - return chain(stream, state, tokenTag(tagName, isclose)); - } - // start code block - else if(ch == "{") { - pushStateStack(state,{ type: "codeblock"}); - return null; - } - // end code block - else if(ch == "}") { - popStateStack(state); - return null; - } - // if we're in an XML block - else if(isInXmlBlock(state)) { - if(ch == ">") - return "tag"; - else if(ch == "/" && stream.eat(">")) { - popStateStack(state); - return "tag"; - } - else - return "variable"; - } - // if a number - else if (/\d/.test(ch)) { - stream.match(/^\d*(?:\.\d*)?(?:E[+\-]?\d+)?/); - return "atom"; - } - // comment start - else if (ch === "(" && stream.eat(":")) { - pushStateStack(state, { type: "comment"}); - return chain(stream, state, tokenComment); - } - // quoted string - else if ( !isEQName && (ch === '"' || ch === "'")) - return chain(stream, state, tokenString(ch)); - // variable - else if(ch === "$") { - return chain(stream, state, tokenVariable); - } - // assignment - else if(ch ===":" && stream.eat("=")) { - return "keyword"; - } - // open paren - else if(ch === "(") { - pushStateStack(state, { type: "paren"}); - return null; - } - // close paren - else if(ch === ")") { - popStateStack(state); - return null; - } - // open paren - else if(ch === "[") { - pushStateStack(state, { type: "bracket"}); - return null; - } - // close paren - else if(ch === "]") { - popStateStack(state); - return null; - } - else { - var known = keywords.propertyIsEnumerable(ch) && keywords[ch]; - - // if there's a EQName ahead, consume the rest of the string portion, it's likely a function - if(isEQName && ch === '\"') while(stream.next() !== '"'){} - if(isEQName && ch === '\'') while(stream.next() !== '\''){} - - // gobble up a word if the character is not known - if(!known) stream.eatWhile(/[\w\$_-]/); - - // gobble a colon in the case that is a lib func type call fn:doc - var foundColon = stream.eat(":"); - - // if there's not a second colon, gobble another word. Otherwise, it's probably an axis specifier - // which should get matched as a keyword - if(!stream.eat(":") && foundColon) { - stream.eatWhile(/[\w\$_-]/); - } - // if the next non whitespace character is an open paren, this is probably a function (if not a keyword of other sort) - if(stream.match(/^[ \t]*\(/, false)) { - mightBeFunction = true; - } - // is the word a keyword? - var word = stream.current(); - known = keywords.propertyIsEnumerable(word) && keywords[word]; - - // if we think it's a function call but not yet known, - // set style to variable for now for lack of something better - if(mightBeFunction && !known) known = {type: "function_call", style: "variable def"}; - - // if the previous word was element, attribute, axis specifier, this word should be the name of that - if(isInXmlConstructor(state)) { - popStateStack(state); - return "variable"; - } - // as previously checked, if the word is element,attribute, axis specifier, call it an "xmlconstructor" and - // push the stack so we know to look for it on the next word - if(word == "element" || word == "attribute" || known.type == "axis_specifier") pushStateStack(state, {type: "xmlconstructor"}); - - // if the word is known, return the details of that else just call this a generic 'word' - return known ? known.style : "variable"; - } - } - - // handle comments, including nested - function tokenComment(stream, state) { - var maybeEnd = false, maybeNested = false, nestedCount = 0, ch; - while (ch = stream.next()) { - if (ch == ")" && maybeEnd) { - if(nestedCount > 0) - nestedCount--; - else { - popStateStack(state); - break; - } - } - else if(ch == ":" && maybeNested) { - nestedCount++; - } - maybeEnd = (ch == ":"); - maybeNested = (ch == "("); - } - - return "comment"; - } - - // tokenizer for string literals - // optionally pass a tokenizer function to set state.tokenize back to when finished - function tokenString(quote, f) { - return function(stream, state) { - var ch; - - if(isInString(state) && stream.current() == quote) { - popStateStack(state); - if(f) state.tokenize = f; - return "string"; - } - - pushStateStack(state, { type: "string", name: quote, tokenize: tokenString(quote, f) }); - - // if we're in a string and in an XML block, allow an embedded code block - if(stream.match("{", false) && isInXmlAttributeBlock(state)) { - state.tokenize = tokenBase; - return "string"; - } - - - while (ch = stream.next()) { - if (ch == quote) { - popStateStack(state); - if(f) state.tokenize = f; - break; - } - else { - // if we're in a string and in an XML block, allow an embedded code block in an attribute - if(stream.match("{", false) && isInXmlAttributeBlock(state)) { - state.tokenize = tokenBase; - return "string"; - } - - } - } - - return "string"; - }; - } - - // tokenizer for variables - function tokenVariable(stream, state) { - var isVariableChar = /[\w\$_-]/; - - // a variable may start with a quoted EQName so if the next character is quote, consume to the next quote - if(stream.eat("\"")) { - while(stream.next() !== '\"'){}; - stream.eat(":"); - } else { - stream.eatWhile(isVariableChar); - if(!stream.match(":=", false)) stream.eat(":"); - } - stream.eatWhile(isVariableChar); - state.tokenize = tokenBase; - return "variable"; - } - - // tokenizer for XML tags - function tokenTag(name, isclose) { - return function(stream, state) { - stream.eatSpace(); - if(isclose && stream.eat(">")) { - popStateStack(state); - state.tokenize = tokenBase; - return "tag"; - } - // self closing tag without attributes? - if(!stream.eat("/")) - pushStateStack(state, { type: "tag", name: name, tokenize: tokenBase}); - if(!stream.eat(">")) { - state.tokenize = tokenAttribute; - return "tag"; - } - else { - state.tokenize = tokenBase; - } - return "tag"; - }; - } - - // tokenizer for XML attributes - function tokenAttribute(stream, state) { - var ch = stream.next(); - - if(ch == "/" && stream.eat(">")) { - if(isInXmlAttributeBlock(state)) popStateStack(state); - if(isInXmlBlock(state)) popStateStack(state); - return "tag"; - } - if(ch == ">") { - if(isInXmlAttributeBlock(state)) popStateStack(state); - return "tag"; - } - if(ch == "=") - return null; - // quoted string - if (ch == '"' || ch == "'") - return chain(stream, state, tokenString(ch, tokenAttribute)); - - if(!isInXmlAttributeBlock(state)) - pushStateStack(state, { type: "attribute", tokenize: tokenAttribute}); - - stream.eat(/[a-zA-Z_:]/); - stream.eatWhile(/[-a-zA-Z0-9_:.]/); - stream.eatSpace(); - - // the case where the attribute has not value and the tag was closed - if(stream.match(">", false) || stream.match("/", false)) { - popStateStack(state); - state.tokenize = tokenBase; - } - - return "attribute"; - } - - // handle comments, including nested - function tokenXMLComment(stream, state) { - var ch; - while (ch = stream.next()) { - if (ch == "-" && stream.match("->", true)) { - state.tokenize = tokenBase; - return "comment"; - } - } - } - - - // handle CDATA - function tokenCDATA(stream, state) { - var ch; - while (ch = stream.next()) { - if (ch == "]" && stream.match("]", true)) { - state.tokenize = tokenBase; - return "comment"; - } - } - } - - // handle preprocessing instructions - function tokenPreProcessing(stream, state) { - var ch; - while (ch = stream.next()) { - if (ch == "?" && stream.match(">", true)) { - state.tokenize = tokenBase; - return "comment meta"; - } - } - } - - - // functions to test the current context of the state - function isInXmlBlock(state) { return isIn(state, "tag"); } - function isInXmlAttributeBlock(state) { return isIn(state, "attribute"); } - function isInXmlConstructor(state) { return isIn(state, "xmlconstructor"); } - function isInString(state) { return isIn(state, "string"); } - - function isEQNameAhead(stream) { - // assume we've already eaten a quote (") - if(stream.current() === '"') - return stream.match(/^[^\"]+\"\:/, false); - else if(stream.current() === '\'') - return stream.match(/^[^\"]+\'\:/, false); - else - return false; - } - - function isIn(state, type) { - return (state.stack.length && state.stack[state.stack.length - 1].type == type); - } - - function pushStateStack(state, newState) { - state.stack.push(newState); - } - - function popStateStack(state) { - state.stack.pop(); - var reinstateTokenize = state.stack.length && state.stack[state.stack.length-1].tokenize; - state.tokenize = reinstateTokenize || tokenBase; - } - - // the interface for the mode API - return { - startState: function() { - return { - tokenize: tokenBase, - cc: [], - stack: [] - }; - }, - - token: function(stream, state) { - if (stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - return style; - }, - - blockCommentStart: "(:", - blockCommentEnd: ":)" - - }; - -}); - -CodeMirror.defineMIME("application/xquery", "xquery"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/yacas/index.html b/backend/_pv_1_3_5/static/codemirror/mode/yacas/index.html deleted file mode 100755 index 8e52cafb1..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/yacas/index.html +++ /dev/null @@ -1,87 +0,0 @@ - - -CodeMirror: yacas mode - - - - - - - - - - -
    -

    yacas mode

    - - - - - - -

    MIME types defined: text/x-yacas (yacas).

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/yacas/yacas.js b/backend/_pv_1_3_5/static/codemirror/mode/yacas/yacas.js deleted file mode 100755 index 30bd60b2f..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/yacas/yacas.js +++ /dev/null @@ -1,204 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// Yacas mode copyright (c) 2015 by Grzegorz Mazur -// Loosely based on mathematica mode by Calin Barbat - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode('yacas', function(_config, _parserConfig) { - - function words(str) { - var obj = {}, words = str.split(" "); - for (var i = 0; i < words.length; ++i) obj[words[i]] = true; - return obj; - } - - var bodiedOps = words("Assert BackQuote D Defun Deriv For ForEach FromFile " + - "FromString Function Integrate InverseTaylor Limit " + - "LocalSymbols Macro MacroRule MacroRulePattern " + - "NIntegrate Rule RulePattern Subst TD TExplicitSum " + - "TSum Taylor Taylor1 Taylor2 Taylor3 ToFile " + - "ToStdout ToString TraceRule Until While"); - - // patterns - var pFloatForm = "(?:(?:\\.\\d+|\\d+\\.\\d*|\\d+)(?:[eE][+-]?\\d+)?)"; - var pIdentifier = "(?:[a-zA-Z\\$'][a-zA-Z0-9\\$']*)"; - - // regular expressions - var reFloatForm = new RegExp(pFloatForm); - var reIdentifier = new RegExp(pIdentifier); - var rePattern = new RegExp(pIdentifier + "?_" + pIdentifier); - var reFunctionLike = new RegExp(pIdentifier + "\\s*\\("); - - function tokenBase(stream, state) { - var ch; - - // get next character - ch = stream.next(); - - // string - if (ch === '"') { - state.tokenize = tokenString; - return state.tokenize(stream, state); - } - - // comment - if (ch === '/') { - if (stream.eat('*')) { - state.tokenize = tokenComment; - return state.tokenize(stream, state); - } - if (stream.eat("/")) { - stream.skipToEnd(); - return "comment"; - } - } - - // go back one character - stream.backUp(1); - - // update scope info - var m = stream.match(/^(\w+)\s*\(/, false); - if (m !== null && bodiedOps.hasOwnProperty(m[1])) - state.scopes.push('bodied'); - - var scope = currentScope(state); - - if (scope === 'bodied' && ch === '[') - state.scopes.pop(); - - if (ch === '[' || ch === '{' || ch === '(') - state.scopes.push(ch); - - scope = currentScope(state); - - if (scope === '[' && ch === ']' || - scope === '{' && ch === '}' || - scope === '(' && ch === ')') - state.scopes.pop(); - - if (ch === ';') { - while (scope === 'bodied') { - state.scopes.pop(); - scope = currentScope(state); - } - } - - // look for ordered rules - if (stream.match(/\d+ *#/, true, false)) { - return 'qualifier'; - } - - // look for numbers - if (stream.match(reFloatForm, true, false)) { - return 'number'; - } - - // look for placeholders - if (stream.match(rePattern, true, false)) { - return 'variable-3'; - } - - // match all braces separately - if (stream.match(/(?:\[|\]|{|}|\(|\))/, true, false)) { - return 'bracket'; - } - - // literals looking like function calls - if (stream.match(reFunctionLike, true, false)) { - stream.backUp(1); - return 'variable'; - } - - // all other identifiers - if (stream.match(reIdentifier, true, false)) { - return 'variable-2'; - } - - // operators; note that operators like @@ or /; are matched separately for each symbol. - if (stream.match(/(?:\\|\+|\-|\*|\/|,|;|\.|:|@|~|=|>|<|&|\||_|`|'|\^|\?|!|%)/, true, false)) { - return 'operator'; - } - - // everything else is an error - return 'error'; - } - - function tokenString(stream, state) { - var next, end = false, escaped = false; - while ((next = stream.next()) != null) { - if (next === '"' && !escaped) { - end = true; - break; - } - escaped = !escaped && next === '\\'; - } - if (end && !escaped) { - state.tokenize = tokenBase; - } - return 'string'; - }; - - function tokenComment(stream, state) { - var prev, next; - while((next = stream.next()) != null) { - if (prev === '*' && next === '/') { - state.tokenize = tokenBase; - break; - } - prev = next; - } - return 'comment'; - } - - function currentScope(state) { - var scope = null; - if (state.scopes.length > 0) - scope = state.scopes[state.scopes.length - 1]; - return scope; - } - - return { - startState: function() { - return { - tokenize: tokenBase, - scopes: [] - }; - }, - token: function(stream, state) { - if (stream.eatSpace()) return null; - return state.tokenize(stream, state); - }, - indent: function(state, textAfter) { - if (state.tokenize !== tokenBase && state.tokenize !== null) - return CodeMirror.Pass; - - var delta = 0; - if (textAfter === ']' || textAfter === '];' || - textAfter === '}' || textAfter === '};' || - textAfter === ');') - delta = -1; - - return (state.scopes.length + delta) * _config.indentUnit; - }, - electricChars: "{}[]();", - blockCommentStart: "/*", - blockCommentEnd: "*/", - lineComment: "//" - }; -}); - -CodeMirror.defineMIME('text/x-yacas', { - name: 'yacas' -}); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/yaml-frontmatter/index.html b/backend/_pv_1_3_5/static/codemirror/mode/yaml-frontmatter/index.html deleted file mode 100755 index 30cb294e8..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/yaml-frontmatter/index.html +++ /dev/null @@ -1,121 +0,0 @@ - - -CodeMirror: YAML front matter mode - - - - - - - - - - - - - -
    -

    YAML front matter mode

    -
    - -

    Defines a mode that parses -a YAML frontmatter -at the start of a file, switching to a base mode at the end of that. -Takes a mode configuration option base to configure the -base mode, which defaults to "gfm".

    - - - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/yaml-frontmatter/yaml-frontmatter.js b/backend/_pv_1_3_5/static/codemirror/mode/yaml-frontmatter/yaml-frontmatter.js deleted file mode 100755 index 5f4977237..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/yaml-frontmatter/yaml-frontmatter.js +++ /dev/null @@ -1,68 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function (mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror"), require("../yaml/yaml")) - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror", "../yaml/yaml"], mod) - else // Plain browser env - mod(CodeMirror) -})(function (CodeMirror) { - - var START = 0, FRONTMATTER = 1, BODY = 2 - - // a mixed mode for Markdown text with an optional YAML front matter - CodeMirror.defineMode("yaml-frontmatter", function (config, parserConfig) { - var yamlMode = CodeMirror.getMode(config, "yaml") - var innerMode = CodeMirror.getMode(config, parserConfig && parserConfig.base || "gfm") - - function curMode(state) { - return state.state == BODY ? innerMode : yamlMode - } - - return { - startState: function () { - return { - state: START, - inner: CodeMirror.startState(yamlMode) - } - }, - copyState: function (state) { - return { - state: state.state, - inner: CodeMirror.copyState(curMode(state), state.inner) - } - }, - token: function (stream, state) { - if (state.state == START) { - if (stream.match(/---/, false)) { - state.state = FRONTMATTER - return yamlMode.token(stream, state.inner) - } else { - state.state = BODY - state.inner = CodeMirror.startState(innerMode) - return innerMode.token(stream, state.inner) - } - } else if (state.state == FRONTMATTER) { - var end = stream.sol() && stream.match(/---/, false) - var style = yamlMode.token(stream, state.inner) - if (end) { - state.state = BODY - state.inner = CodeMirror.startState(innerMode) - } - return style - } else { - return innerMode.token(stream, state.inner) - } - }, - innerMode: function (state) { - return {mode: curMode(state), state: state.inner} - }, - blankLine: function (state) { - var mode = curMode(state) - if (mode.blankLine) return mode.blankLine(state.inner) - } - } - }) -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/yaml/index.html b/backend/_pv_1_3_5/static/codemirror/mode/yaml/index.html deleted file mode 100755 index be9b63236..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/yaml/index.html +++ /dev/null @@ -1,80 +0,0 @@ - - -CodeMirror: YAML mode - - - - - - - - - -
    -

    YAML mode

    -
    - - -

    MIME types defined: text/x-yaml.

    - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/yaml/yaml.js b/backend/_pv_1_3_5/static/codemirror/mode/yaml/yaml.js deleted file mode 100755 index 59c0ecdbe..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/yaml/yaml.js +++ /dev/null @@ -1,118 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("yaml", function() { - - var cons = ['true', 'false', 'on', 'off', 'yes', 'no']; - var keywordRegex = new RegExp("\\b(("+cons.join(")|(")+"))$", 'i'); - - return { - token: function(stream, state) { - var ch = stream.peek(); - var esc = state.escaped; - state.escaped = false; - /* comments */ - if (ch == "#" && (stream.pos == 0 || /\s/.test(stream.string.charAt(stream.pos - 1)))) { - stream.skipToEnd(); - return "comment"; - } - - if (stream.match(/^('([^']|\\.)*'?|"([^"]|\\.)*"?)/)) - return "string"; - - if (state.literal && stream.indentation() > state.keyCol) { - stream.skipToEnd(); return "string"; - } else if (state.literal) { state.literal = false; } - if (stream.sol()) { - state.keyCol = 0; - state.pair = false; - state.pairStart = false; - /* document start */ - if(stream.match(/---/)) { return "def"; } - /* document end */ - if (stream.match(/\.\.\./)) { return "def"; } - /* array list item */ - if (stream.match(/\s*-\s+/)) { return 'meta'; } - } - /* inline pairs/lists */ - if (stream.match(/^(\{|\}|\[|\])/)) { - if (ch == '{') - state.inlinePairs++; - else if (ch == '}') - state.inlinePairs--; - else if (ch == '[') - state.inlineList++; - else - state.inlineList--; - return 'meta'; - } - - /* list seperator */ - if (state.inlineList > 0 && !esc && ch == ',') { - stream.next(); - return 'meta'; - } - /* pairs seperator */ - if (state.inlinePairs > 0 && !esc && ch == ',') { - state.keyCol = 0; - state.pair = false; - state.pairStart = false; - stream.next(); - return 'meta'; - } - - /* start of value of a pair */ - if (state.pairStart) { - /* block literals */ - if (stream.match(/^\s*(\||\>)\s*/)) { state.literal = true; return 'meta'; }; - /* references */ - if (stream.match(/^\s*(\&|\*)[a-z0-9\._-]+\b/i)) { return 'variable-2'; } - /* numbers */ - if (state.inlinePairs == 0 && stream.match(/^\s*-?[0-9\.\,]+\s?$/)) { return 'number'; } - if (state.inlinePairs > 0 && stream.match(/^\s*-?[0-9\.\,]+\s?(?=(,|}))/)) { return 'number'; } - /* keywords */ - if (stream.match(keywordRegex)) { return 'keyword'; } - } - - /* pairs (associative arrays) -> key */ - if (!state.pair && stream.match(/^\s*(?:[,\[\]{}&*!|>'"%@`][^\s'":]|[^,\[\]{}#&*!|>'"%@`])[^#]*?(?=\s*:($|\s))/)) { - state.pair = true; - state.keyCol = stream.indentation(); - return "atom"; - } - if (state.pair && stream.match(/^:\s*/)) { state.pairStart = true; return 'meta'; } - - /* nothing found, continue */ - state.pairStart = false; - state.escaped = (ch == '\\'); - stream.next(); - return null; - }, - startState: function() { - return { - pair: false, - pairStart: false, - keyCol: 0, - inlinePairs: 0, - inlineList: 0, - literal: false, - escaped: false - }; - } - }; -}); - -CodeMirror.defineMIME("text/x-yaml", "yaml"); -CodeMirror.defineMIME("text/yaml", "yaml"); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/mode/z80/index.html b/backend/_pv_1_3_5/static/codemirror/mode/z80/index.html deleted file mode 100755 index a41b7473e..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/z80/index.html +++ /dev/null @@ -1,53 +0,0 @@ - - -CodeMirror: Z80 assembly mode - - - - - - - - - -
    -

    Z80 assembly mode

    - - -
    - - - -

    MIME types defined: text/x-z80, text/x-ez80.

    -
    diff --git a/backend/_pv_1_3_5/static/codemirror/mode/z80/z80.js b/backend/_pv_1_3_5/static/codemirror/mode/z80/z80.js deleted file mode 100755 index aae70216f..000000000 --- a/backend/_pv_1_3_5/static/codemirror/mode/z80/z80.js +++ /dev/null @@ -1,116 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../../lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../../lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode('z80', function(_config, parserConfig) { - var ez80 = parserConfig.ez80; - var keywords1, keywords2; - if (ez80) { - keywords1 = /^(exx?|(ld|cp)([di]r?)?|[lp]ea|pop|push|ad[cd]|cpl|daa|dec|inc|neg|sbc|sub|and|bit|[cs]cf|x?or|res|set|r[lr]c?a?|r[lr]d|s[lr]a|srl|djnz|nop|[de]i|halt|im|in([di]mr?|ir?|irx|2r?)|ot(dmr?|[id]rx|imr?)|out(0?|[di]r?|[di]2r?)|tst(io)?|slp)(\.([sl]?i)?[sl])?\b/i; - keywords2 = /^(((call|j[pr]|rst|ret[in]?)(\.([sl]?i)?[sl])?)|(rs|st)mix)\b/i; - } else { - keywords1 = /^(exx?|(ld|cp|in)([di]r?)?|pop|push|ad[cd]|cpl|daa|dec|inc|neg|sbc|sub|and|bit|[cs]cf|x?or|res|set|r[lr]c?a?|r[lr]d|s[lr]a|srl|djnz|nop|rst|[de]i|halt|im|ot[di]r|out[di]?)\b/i; - keywords2 = /^(call|j[pr]|ret[in]?|b_?(call|jump))\b/i; - } - - var variables1 = /^(af?|bc?|c|de?|e|hl?|l|i[xy]?|r|sp)\b/i; - var variables2 = /^(n?[zc]|p[oe]?|m)\b/i; - var errors = /^([hl][xy]|i[xy][hl]|slia|sll)\b/i; - var numbers = /^([\da-f]+h|[0-7]+o|[01]+b|\d+d?)\b/i; - - return { - startState: function() { - return { - context: 0 - }; - }, - token: function(stream, state) { - if (!stream.column()) - state.context = 0; - - if (stream.eatSpace()) - return null; - - var w; - - if (stream.eatWhile(/\w/)) { - if (ez80 && stream.eat('.')) { - stream.eatWhile(/\w/); - } - w = stream.current(); - - if (stream.indentation()) { - if ((state.context == 1 || state.context == 4) && variables1.test(w)) { - state.context = 4; - return 'var2'; - } - - if (state.context == 2 && variables2.test(w)) { - state.context = 4; - return 'var3'; - } - - if (keywords1.test(w)) { - state.context = 1; - return 'keyword'; - } else if (keywords2.test(w)) { - state.context = 2; - return 'keyword'; - } else if (state.context == 4 && numbers.test(w)) { - return 'number'; - } - - if (errors.test(w)) - return 'error'; - } else if (stream.match(numbers)) { - return 'number'; - } else { - return null; - } - } else if (stream.eat(';')) { - stream.skipToEnd(); - return 'comment'; - } else if (stream.eat('"')) { - while (w = stream.next()) { - if (w == '"') - break; - - if (w == '\\') - stream.next(); - } - return 'string'; - } else if (stream.eat('\'')) { - if (stream.match(/\\?.'/)) - return 'number'; - } else if (stream.eat('.') || stream.sol() && stream.eat('#')) { - state.context = 5; - - if (stream.eatWhile(/\w/)) - return 'def'; - } else if (stream.eat('$')) { - if (stream.eatWhile(/[\da-f]/i)) - return 'number'; - } else if (stream.eat('%')) { - if (stream.eatWhile(/[01]/)) - return 'number'; - } else { - stream.next(); - } - return null; - } - }; -}); - -CodeMirror.defineMIME("text/x-z80", "z80"); -CodeMirror.defineMIME("text/x-ez80", { name: "z80", ez80: true }); - -}); diff --git a/backend/_pv_1_3_5/static/codemirror/package.json b/backend/_pv_1_3_5/static/codemirror/package.json deleted file mode 100755 index f7b617cd2..000000000 --- a/backend/_pv_1_3_5/static/codemirror/package.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "name": "codemirror", - "version": "5.23.0", - "main": "lib/codemirror.js", - "description": "Full-featured in-browser code editor", - "license": "MIT", - "directories": { - "lib": "./lib" - }, - "scripts": { - "build": "rollup -c", - "watch": "rollup -w -c", - "prepublish": "npm run-script build", - "test": "node ./test/run.js", - "lint": "bin/lint" - }, - "devDependencies": { - "blint": "^0.5.1", - "node-static": "0.6.0", - "phantomjs-prebuilt": "^2.1.12", - "rollup": "^0.34.10", - "rollup-plugin-buble": "^0.15.0", - "rollup-watch": "^2.5.0" - }, - "bugs": "http://github.com/codemirror/CodeMirror/issues", - "keywords": [ - "JavaScript", - "CodeMirror", - "Editor" - ], - "homepage": "http://codemirror.net", - "maintainers": [ - { - "name": "Marijn Haverbeke", - "email": "marijnh@gmail.com", - "web": "http://marijnhaverbeke.nl" - } - ], - "repository": { - "type": "git", - "url": "https://github.com/codemirror/CodeMirror.git" - }, - "jspm": { - "directories": {}, - "dependencies": {}, - "devDependencies": {} - } -} diff --git a/backend/_pv_1_3_5/static/codemirror/rollup.config.js b/backend/_pv_1_3_5/static/codemirror/rollup.config.js deleted file mode 100755 index 9a17b24ff..000000000 --- a/backend/_pv_1_3_5/static/codemirror/rollup.config.js +++ /dev/null @@ -1,18 +0,0 @@ -import buble from 'rollup-plugin-buble'; - -export default { - banner: `// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -// This is CodeMirror (http://codemirror.net), a code editor -// implemented in JavaScript on top of the browser's DOM. -// -// You can find some technical background for some of the code below -// at http://marijnhaverbeke.nl/blog/#cm-internals . -`, - entry: "src/codemirror.js", - format: "umd", - dest: "lib/codemirror.js", - moduleName: "CodeMirror", - plugins: [ buble({namedFunctionExpressions: false}) ] -}; diff --git a/backend/_pv_1_3_5/static/codemirror/test/comment_test.js b/backend/_pv_1_3_5/static/codemirror/test/comment_test.js deleted file mode 100755 index c6b9fe810..000000000 --- a/backend/_pv_1_3_5/static/codemirror/test/comment_test.js +++ /dev/null @@ -1,114 +0,0 @@ -namespace = "comment_"; - -(function() { - function test(name, mode, run, before, after) { - return testCM(name, function(cm) { - run(cm); - eq(cm.getValue(), after); - }, {value: before, mode: mode}); - } - - var simpleProg = "function foo() {\n return bar;\n}"; - var inlineBlock = "foo(/* bar */ true);"; - var inlineBlocks = "foo(/* bar */ true, /* baz */ false);"; - var multiLineInlineBlock = ["above();", "foo(/* bar */ true);", "below();"]; - - test("block", "javascript", function(cm) { - cm.blockComment(Pos(0, 3), Pos(3, 0), {blockCommentLead: " *"}); - }, simpleProg + "\n", "/* function foo() {\n * return bar;\n * }\n */"); - - test("blockToggle", "javascript", function(cm) { - cm.blockComment(Pos(0, 3), Pos(2, 0), {blockCommentLead: " *"}); - cm.uncomment(Pos(0, 3), Pos(2, 0), {blockCommentLead: " *"}); - }, simpleProg, simpleProg); - - test("blockToggle2", "javascript", function(cm) { - cm.setCursor({line: 0, ch: 7 /* inside the block comment */}); - cm.execCommand("toggleComment"); - }, inlineBlock, "foo(bar true);"); - - // This test should work but currently fails. - // test("blockToggle3", "javascript", function(cm) { - // cm.setCursor({line: 0, ch: 7 /* inside the first block comment */}); - // cm.execCommand("toggleComment"); - // }, inlineBlocks, "foo(bar true, /* baz */ false);"); - - test("line", "javascript", function(cm) { - cm.lineComment(Pos(1, 1), Pos(1, 1)); - }, simpleProg, "function foo() {\n// return bar;\n}"); - - test("lineToggle", "javascript", function(cm) { - cm.lineComment(Pos(0, 0), Pos(2, 1)); - cm.uncomment(Pos(0, 0), Pos(2, 1)); - }, simpleProg, simpleProg); - - test("fallbackToBlock", "css", function(cm) { - cm.lineComment(Pos(0, 0), Pos(2, 1)); - }, "html {\n border: none;\n}", "/* html {\n border: none;\n} */"); - - test("fallbackToLine", "ruby", function(cm) { - cm.blockComment(Pos(0, 0), Pos(1)); - }, "def blah()\n return hah\n", "# def blah()\n# return hah\n"); - - test("ignoreExternalBlockComments", "javascript", function(cm) { - cm.execCommand("toggleComment"); - }, inlineBlocks, "// " + inlineBlocks); - - test("ignoreExternalBlockComments2", "javascript", function(cm) { - cm.setCursor({line: 0, ch: null /* eol */}); - cm.execCommand("toggleComment"); - }, inlineBlocks, "// " + inlineBlocks); - - test("ignoreExternalBlockCommentsMultiLineAbove", "javascript", function(cm) { - cm.setSelection({line: 0, ch: 0}, {line: 1, ch: 1}); - cm.execCommand("toggleComment"); - }, multiLineInlineBlock.join("\n"), ["// " + multiLineInlineBlock[0], - "// " + multiLineInlineBlock[1], - multiLineInlineBlock[2]].join("\n")); - - test("ignoreExternalBlockCommentsMultiLineBelow", "javascript", function(cm) { - cm.setSelection({line: 1, ch: 13 /* after end of block comment */}, {line: 2, ch: 1}); - cm.execCommand("toggleComment"); - }, multiLineInlineBlock.join("\n"), [multiLineInlineBlock[0], - "// " + multiLineInlineBlock[1], - "// " + multiLineInlineBlock[2]].join("\n")); - - test("commentRange", "javascript", function(cm) { - cm.blockComment(Pos(1, 2), Pos(1, 13), {fullLines: false}); - }, simpleProg, "function foo() {\n /*return bar;*/\n}"); - - test("indented", "javascript", function(cm) { - cm.lineComment(Pos(1, 0), Pos(2), {indent: true}); - }, simpleProg, "function foo() {\n// return bar;\n// }"); - - test("singleEmptyLine", "javascript", function(cm) { - cm.setCursor(1); - cm.execCommand("toggleComment"); - }, "a;\n\nb;", "a;\n// \nb;"); - - test("dontMessWithStrings", "javascript", function(cm) { - cm.execCommand("toggleComment"); - }, "console.log(\"/*string*/\");", "// console.log(\"/*string*/\");"); - - test("dontMessWithStrings2", "javascript", function(cm) { - cm.execCommand("toggleComment"); - }, "console.log(\"// string\");", "// console.log(\"// string\");"); - - test("dontMessWithStrings3", "javascript", function(cm) { - cm.execCommand("toggleComment"); - }, "// console.log(\"// string\");", "console.log(\"// string\");"); - - test("includeLastLine", "javascript", function(cm) { - cm.execCommand("selectAll") - cm.execCommand("toggleComment") - }, "// foo\n// bar\nbaz", "// // foo\n// // bar\n// baz") - - test("uncommentWithTrailingBlockEnd", "xml", function(cm) { - cm.execCommand("toggleComment") - }, " -->", "foo -->") - - test("dontCommentInComment", "xml", function(cm) { - cm.setCursor(1, 0) - cm.execCommand("toggleComment") - }, "", "") -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/test/doc_test.js b/backend/_pv_1_3_5/static/codemirror/test/doc_test.js deleted file mode 100755 index 5f242f658..000000000 --- a/backend/_pv_1_3_5/static/codemirror/test/doc_test.js +++ /dev/null @@ -1,371 +0,0 @@ -(function() { - // A minilanguage for instantiating linked CodeMirror instances and Docs - function instantiateSpec(spec, place, opts) { - var names = {}, pos = 0, l = spec.length, editors = []; - while (spec) { - var m = spec.match(/^(\w+)(\*?)(?:='([^\']*)'|<(~?)(\w+)(?:\/(\d+)-(\d+))?)\s*/); - var name = m[1], isDoc = m[2], cur; - if (m[3]) { - cur = isDoc ? CodeMirror.Doc(m[3]) : CodeMirror(place, clone(opts, {value: m[3]})); - } else { - var other = m[5]; - if (!names.hasOwnProperty(other)) { - names[other] = editors.length; - editors.push(CodeMirror(place, opts)); - } - var doc = editors[names[other]].linkedDoc({ - sharedHist: !m[4], - from: m[6] ? Number(m[6]) : null, - to: m[7] ? Number(m[7]) : null - }); - cur = isDoc ? doc : CodeMirror(place, clone(opts, {value: doc})); - } - names[name] = editors.length; - editors.push(cur); - spec = spec.slice(m[0].length); - } - return editors; - } - - function clone(obj, props) { - if (!obj) return; - clone.prototype = obj; - var inst = new clone(); - if (props) for (var n in props) if (props.hasOwnProperty(n)) - inst[n] = props[n]; - return inst; - } - - function eqAll(val) { - var end = arguments.length, msg = null; - if (typeof arguments[end-1] == "string") - msg = arguments[--end]; - if (i == end) throw new Error("No editors provided to eqAll"); - for (var i = 1; i < end; ++i) - eq(arguments[i].getValue(), val, msg) - } - - function testDoc(name, spec, run, opts, expectFail) { - if (!opts) opts = {}; - - return test("doc_" + name, function() { - var place = document.getElementById("testground"); - var editors = instantiateSpec(spec, place, opts); - var successful = false; - - try { - run.apply(null, editors); - successful = true; - } finally { - if (!successful || verbose) { - place.style.visibility = "visible"; - } else { - for (var i = 0; i < editors.length; ++i) - if (editors[i] instanceof CodeMirror) - place.removeChild(editors[i].getWrapperElement()); - } - } - }, expectFail); - } - - var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent); - - function testBasic(a, b) { - eqAll("x", a, b); - a.setValue("hey"); - eqAll("hey", a, b); - b.setValue("wow"); - eqAll("wow", a, b); - a.replaceRange("u\nv\nw", Pos(0, 3)); - b.replaceRange("i", Pos(0, 4)); - b.replaceRange("j", Pos(2, 1)); - eqAll("wowui\nv\nwj", a, b); - } - - testDoc("basic", "A='x' B 0, "not at left"); - is(pos.top > 0, "not at top"); - }); - - testDoc("copyDoc", "A='u'", function(a) { - var copy = a.getDoc().copy(true); - a.setValue("foo"); - copy.setValue("bar"); - var old = a.swapDoc(copy); - eq(a.getValue(), "bar"); - a.undo(); - eq(a.getValue(), "u"); - a.swapDoc(old); - eq(a.getValue(), "foo"); - eq(old.historySize().undo, 1); - eq(old.copy(false).historySize().undo, 0); - }); - - testDoc("docKeepsMode", "A='1+1'", function(a) { - var other = CodeMirror.Doc("hi", "text/x-markdown"); - a.setOption("mode", "text/javascript"); - var old = a.swapDoc(other); - eq(a.getOption("mode"), "text/x-markdown"); - eq(a.getMode().name, "markdown"); - a.swapDoc(old); - eq(a.getOption("mode"), "text/javascript"); - eq(a.getMode().name, "javascript"); - }); - - testDoc("subview", "A='1\n2\n3\n4\n5' B<~A/1-3", function(a, b) { - eq(b.getValue(), "2\n3"); - eq(b.firstLine(), 1); - b.setCursor(Pos(4)); - eqPos(b.getCursor(), Pos(2, 1)); - a.replaceRange("-1\n0\n", Pos(0, 0)); - eq(b.firstLine(), 3); - eqPos(b.getCursor(), Pos(4, 1)); - a.undo(); - eqPos(b.getCursor(), Pos(2, 1)); - b.replaceRange("oyoy\n", Pos(2, 0)); - eq(a.getValue(), "1\n2\noyoy\n3\n4\n5"); - b.undo(); - eq(a.getValue(), "1\n2\n3\n4\n5"); - }); - - testDoc("subviewEditOnBoundary", "A='11\n22\n33\n44\n55' B<~A/1-4", function(a, b) { - a.replaceRange("x\nyy\nz", Pos(0, 1), Pos(2, 1)); - eq(b.firstLine(), 2); - eq(b.lineCount(), 2); - eq(b.getValue(), "z3\n44"); - a.replaceRange("q\nrr\ns", Pos(3, 1), Pos(4, 1)); - eq(b.firstLine(), 2); - eq(b.getValue(), "z3\n4q"); - eq(a.getValue(), "1x\nyy\nz3\n4q\nrr\ns5"); - a.execCommand("selectAll"); - a.replaceSelection("!"); - eqAll("!", a, b); - }); - - - testDoc("sharedMarker", "A='ab\ncd\nef\ngh' B 500){ - totalTime = 0; - delay = 50; - } - setTimeout(function(){step(i + 1);}, delay); - } else { // Quit tests - running = false; - return null; - } - } - step(0); -} - -function label(str, msg) { - if (msg) return str + " (" + msg + ")"; - return str; -} -function eq(a, b, msg) { - if (a != b) throw new Failure(label(a + " != " + b, msg)); -} -function near(a, b, margin, msg) { - if (Math.abs(a - b) > margin) - throw new Failure(label(a + " is not close to " + b + " (" + margin + ")", msg)); -} -function eqPos(a, b, msg) { - function str(p) { return "{line:" + p.line + ",ch:" + p.ch + "}"; } - if (a == b) return; - if (a == null) throw new Failure(label("comparing null to " + str(b), msg)); - if (b == null) throw new Failure(label("comparing " + str(a) + " to null", msg)); - if (a.line != b.line || a.ch != b.ch) throw new Failure(label(str(a) + " != " + str(b), msg)); -} -function is(a, msg) { - if (!a) throw new Failure(label("assertion failed", msg)); -} - -function countTests() { - if (!filters.length) return tests.length; - var sum = 0; - for (var i = 0; i < tests.length; ++i) { - var name = tests[i].name; - for (var j = 0; j < filters.length; j++) { - if (name.match(filters[j])) { - ++sum; - break; - } - } - } - return sum; -} - -function parseTestFilter(s) { - if (/_\*$/.test(s)) return new RegExp("^" + s.slice(0, s.length - 2), "i"); - else return new RegExp(s, "i"); -} diff --git a/backend/_pv_1_3_5/static/codemirror/test/emacs_test.js b/backend/_pv_1_3_5/static/codemirror/test/emacs_test.js deleted file mode 100755 index 628651c78..000000000 --- a/backend/_pv_1_3_5/static/codemirror/test/emacs_test.js +++ /dev/null @@ -1,147 +0,0 @@ -(function() { - "use strict"; - - var Pos = CodeMirror.Pos; - namespace = "emacs_"; - - var eventCache = {}; - function fakeEvent(keyName) { - var event = eventCache[key]; - if (event) return event; - - var ctrl, shift, alt; - var key = keyName.replace(/\w+-/g, function(type) { - if (type == "Ctrl-") ctrl = true; - else if (type == "Alt-") alt = true; - else if (type == "Shift-") shift = true; - return ""; - }); - var code; - for (var c in CodeMirror.keyNames) - if (CodeMirror.keyNames[c] == key) { code = c; break; } - if (code == null) throw new Error("Unknown key: " + key); - - return eventCache[keyName] = { - type: "keydown", keyCode: code, ctrlKey: ctrl, shiftKey: shift, altKey: alt, - preventDefault: function(){}, stopPropagation: function(){} - }; - } - - function sim(name, start /*, actions... */) { - var keys = Array.prototype.slice.call(arguments, 2); - testCM(name, function(cm) { - for (var i = 0; i < keys.length; ++i) { - var cur = keys[i]; - if (cur instanceof Pos) cm.setCursor(cur); - else if (cur.call) cur(cm); - else cm.triggerOnKeyDown(fakeEvent(cur)); - } - }, {keyMap: "emacs", value: start, mode: "javascript"}); - } - - function at(line, ch) { return function(cm) { eqPos(cm.getCursor(), Pos(line, ch)); }; } - function txt(str) { return function(cm) { eq(cm.getValue(), str); }; } - - sim("motionHSimple", "abc", "Ctrl-F", "Ctrl-F", "Ctrl-B", at(0, 1)); - sim("motionHMulti", "abcde", - "Ctrl-4", "Ctrl-F", at(0, 4), "Ctrl--", "Ctrl-2", "Ctrl-F", at(0, 2), - "Ctrl-5", "Ctrl-B", at(0, 0)); - - sim("motionHWord", "abc. def ghi", - "Alt-F", at(0, 3), "Alt-F", at(0, 8), - "Ctrl-B", "Alt-B", at(0, 5), "Alt-B", at(0, 0)); - sim("motionHWordMulti", "abc. def ghi ", - "Ctrl-3", "Alt-F", at(0, 12), "Ctrl-2", "Alt-B", at(0, 5), - "Ctrl--", "Alt-B", at(0, 8)); - - sim("motionVSimple", "a\nb\nc\n", "Ctrl-N", "Ctrl-N", "Ctrl-P", at(1, 0)); - sim("motionVMulti", "a\nb\nc\nd\ne\n", - "Ctrl-2", "Ctrl-N", at(2, 0), "Ctrl-F", "Ctrl--", "Ctrl-N", at(1, 1), - "Ctrl--", "Ctrl-3", "Ctrl-P", at(4, 1)); - - sim("killYank", "abc\ndef\nghi", - "Ctrl-F", "Ctrl-Space", "Ctrl-N", "Ctrl-N", "Ctrl-W", "Ctrl-E", "Ctrl-Y", - txt("ahibc\ndef\ng")); - sim("killRing", "abcdef", - "Ctrl-Space", "Ctrl-F", "Ctrl-W", "Ctrl-Space", "Ctrl-F", "Ctrl-W", - "Ctrl-Y", "Alt-Y", - txt("acdef")); - sim("copyYank", "abcd", - "Ctrl-Space", "Ctrl-E", "Alt-W", "Ctrl-Y", - txt("abcdabcd")); - - sim("killLineSimple", "foo\nbar", "Ctrl-F", "Ctrl-K", txt("f\nbar")); - sim("killLineEmptyLine", "foo\n \nbar", "Ctrl-N", "Ctrl-K", txt("foo\nbar")); - sim("killLineMulti", "foo\nbar\nbaz", - "Ctrl-F", "Ctrl-F", "Ctrl-K", "Ctrl-K", "Ctrl-K", "Ctrl-A", "Ctrl-Y", - txt("o\nbarfo\nbaz")); - - sim("moveByParagraph", "abc\ndef\n\n\nhij\nklm\n\n", - "Ctrl-F", "Ctrl-Down", at(2, 0), "Ctrl-Down", at(6, 0), - "Ctrl-N", "Ctrl-Up", at(3, 0), "Ctrl-Up", at(0, 0), - Pos(1, 2), "Ctrl-Down", at(2, 0), Pos(4, 2), "Ctrl-Up", at(3, 0)); - sim("moveByParagraphMulti", "abc\n\ndef\n\nhij\n\nklm", - "Ctrl-U", "2", "Ctrl-Down", at(3, 0), - "Shift-Alt-.", "Ctrl-3", "Ctrl-Up", at(1, 0)); - - sim("moveBySentence", "sentence one! sentence\ntwo\n\nparagraph two", - "Alt-E", at(0, 13), "Alt-E", at(1, 3), "Ctrl-F", "Alt-A", at(0, 13)); - - sim("moveByExpr", "function foo(a, b) {}", - "Ctrl-Alt-F", at(0, 8), "Ctrl-Alt-F", at(0, 12), "Ctrl-Alt-F", at(0, 18), - "Ctrl-Alt-B", at(0, 12), "Ctrl-Alt-B", at(0, 9)); - sim("moveByExprMulti", "foo bar baz bug", - "Ctrl-2", "Ctrl-Alt-F", at(0, 7), - "Ctrl--", "Ctrl-Alt-F", at(0, 4), - "Ctrl--", "Ctrl-2", "Ctrl-Alt-B", at(0, 11)); - sim("delExpr", "var x = [\n a,\n b\n c\n];", - Pos(0, 8), "Ctrl-Alt-K", txt("var x = ;"), "Ctrl-/", - Pos(4, 1), "Ctrl-Alt-Backspace", txt("var x = ;")); - sim("delExprMulti", "foo bar baz", - "Ctrl-2", "Ctrl-Alt-K", txt(" baz"), - "Ctrl-/", "Ctrl-E", "Ctrl-2", "Ctrl-Alt-Backspace", txt("foo ")); - - sim("justOneSpace", "hi bye ", - Pos(0, 4), "Alt-Space", txt("hi bye "), - Pos(0, 4), "Alt-Space", txt("hi b ye "), - "Ctrl-A", "Alt-Space", "Ctrl-E", "Alt-Space", txt(" hi b ye ")); - - sim("openLine", "foo bar", "Alt-F", "Ctrl-O", txt("foo\n bar")) - - sim("transposeChar", "abcd\ne", - "Ctrl-F", "Ctrl-T", "Ctrl-T", txt("bcad\ne"), at(0, 3), - "Ctrl-F", "Ctrl-T", "Ctrl-T", "Ctrl-T", txt("bcda\ne"), at(0, 4), - "Ctrl-F", "Ctrl-T", txt("bcde\na"), at(1, 1)); - - sim("manipWordCase", "foo BAR bAZ", - "Alt-C", "Alt-L", "Alt-U", txt("Foo bar BAZ"), - "Ctrl-A", "Alt-U", "Alt-L", "Alt-C", txt("FOO bar Baz")); - sim("manipWordCaseMulti", "foo Bar bAz", - "Ctrl-2", "Alt-U", txt("FOO BAR bAz"), - "Ctrl-A", "Ctrl-3", "Alt-C", txt("Foo Bar Baz")); - - sim("upExpr", "foo {\n bar[];\n baz(blah);\n}", - Pos(2, 7), "Ctrl-Alt-U", at(2, 5), "Ctrl-Alt-U", at(0, 4)); - sim("transposeExpr", "do foo[bar] dah", - Pos(0, 6), "Ctrl-Alt-T", txt("do [bar]foo dah")); - - sim("clearMark", "abcde", Pos(0, 2), "Ctrl-Space", "Ctrl-F", "Ctrl-F", - "Ctrl-G", "Ctrl-W", txt("abcde")); - - sim("delRegion", "abcde", "Ctrl-Space", "Ctrl-F", "Ctrl-F", "Delete", txt("cde")); - sim("backspaceRegion", "abcde", "Ctrl-Space", "Ctrl-F", "Ctrl-F", "Backspace", txt("cde")); - - testCM("save", function(cm) { - var saved = false; - CodeMirror.commands.save = function(cm) { saved = cm.getValue(); }; - cm.triggerOnKeyDown(fakeEvent("Ctrl-X")); - cm.triggerOnKeyDown(fakeEvent("Ctrl-S")); - is(saved, "hi"); - }, {value: "hi", keyMap: "emacs"}); - - testCM("gotoInvalidLineFloat", function(cm) { - cm.openDialog = function(_, cb) { cb("2.2"); }; - cm.triggerOnKeyDown(fakeEvent("Alt-G")); - cm.triggerOnKeyDown(fakeEvent("G")); - }, {value: "1\n2\n3\n4", keyMap: "emacs"}); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/test/index.html b/backend/_pv_1_3_5/static/codemirror/test/index.html deleted file mode 100755 index 6ddf5b102..000000000 --- a/backend/_pv_1_3_5/static/codemirror/test/index.html +++ /dev/null @@ -1,264 +0,0 @@ - - - -CodeMirror: Test Suite - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -

    Test Suite

    - -

    A limited set of programmatic sanity tests for CodeMirror.

    - -
    -
    Ran 0 of 0 tests
    -
    -

    Please enable JavaScript...

    -
    - -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    diff --git a/backend/_pv_1_3_5/static/codemirror/test/lint.js b/backend/_pv_1_3_5/static/codemirror/test/lint.js deleted file mode 100755 index 502706de8..000000000 --- a/backend/_pv_1_3_5/static/codemirror/test/lint.js +++ /dev/null @@ -1,19 +0,0 @@ -var blint = require("blint"); - -["mode", "lib", "addon", "keymap"].forEach(function(dir) { - blint.checkDir(dir, { - browser: true, - allowedGlobals: ["CodeMirror", "define", "test", "requirejs"], - ecmaVersion: 5 - }); -}); - -["src"].forEach(function(dir) { - blint.checkDir(dir, { - browser: true, - ecmaVersion: 6, - semicolons: false - }); -}); - -module.exports = {ok: blint.success()}; diff --git a/backend/_pv_1_3_5/static/codemirror/test/mode_test.css b/backend/_pv_1_3_5/static/codemirror/test/mode_test.css deleted file mode 100755 index f83271b4e..000000000 --- a/backend/_pv_1_3_5/static/codemirror/test/mode_test.css +++ /dev/null @@ -1,23 +0,0 @@ -.mt-output .mt-token { - border: 1px solid #ddd; - white-space: pre; - font-family: "Consolas", monospace; - text-align: center; -} - -.mt-output .mt-style { - font-size: x-small; -} - -.mt-output .mt-state { - font-size: x-small; - vertical-align: top; -} - -.mt-output .mt-state-row { - display: none; -} - -.mt-state-unhide .mt-output .mt-state-row { - display: table-row; -} diff --git a/backend/_pv_1_3_5/static/codemirror/test/mode_test.js b/backend/_pv_1_3_5/static/codemirror/test/mode_test.js deleted file mode 100755 index 0aed50f7d..000000000 --- a/backend/_pv_1_3_5/static/codemirror/test/mode_test.js +++ /dev/null @@ -1,192 +0,0 @@ -/** - * Helper to test CodeMirror highlighting modes. It pretty prints output of the - * highlighter and can check against expected styles. - * - * Mode tests are registered by calling test.mode(testName, mode, - * tokens), where mode is a mode object as returned by - * CodeMirror.getMode, and tokens is an array of lines that make up - * the test. - * - * These lines are strings, in which styled stretches of code are - * enclosed in brackets `[]`, and prefixed by their style. For - * example, `[keyword if]`. Brackets in the code itself must be - * duplicated to prevent them from being interpreted as token - * boundaries. For example `a[[i]]` for `a[i]`. If a token has - * multiple styles, the styles must be separated by ampersands, for - * example `[tag&error ]`. - * - * See the test.js files in the css, markdown, gfm, and stex mode - * directories for examples. - */ -(function() { - function findSingle(str, pos, ch) { - for (;;) { - var found = str.indexOf(ch, pos); - if (found == -1) return null; - if (str.charAt(found + 1) != ch) return found; - pos = found + 2; - } - } - - var styleName = /[\w&-_]+/g; - function parseTokens(strs) { - var tokens = [], plain = ""; - for (var i = 0; i < strs.length; ++i) { - if (i) plain += "\n"; - var str = strs[i], pos = 0; - while (pos < str.length) { - var style = null, text; - if (str.charAt(pos) == "[" && str.charAt(pos+1) != "[") { - styleName.lastIndex = pos + 1; - var m = styleName.exec(str); - style = m[0].replace(/&/g, " "); - var textStart = pos + style.length + 2; - var end = findSingle(str, textStart, "]"); - if (end == null) throw new Error("Unterminated token at " + pos + " in '" + str + "'" + style); - text = str.slice(textStart, end); - pos = end + 1; - } else { - var end = findSingle(str, pos, "["); - if (end == null) end = str.length; - text = str.slice(pos, end); - pos = end; - } - text = text.replace(/\[\[|\]\]/g, function(s) {return s.charAt(0);}); - tokens.push({style: style, text: text}); - plain += text; - } - } - return {tokens: tokens, plain: plain}; - } - - test.mode = function(name, mode, tokens, modeName) { - var data = parseTokens(tokens); - return test((modeName || mode.name) + "_" + name, function() { - return compare(data.plain, data.tokens, mode); - }); - }; - - function esc(str) { - return str.replace('&', '&').replace('<', '<').replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'"); -; - } - - function compare(text, expected, mode) { - - var expectedOutput = []; - for (var i = 0; i < expected.length; ++i) { - var sty = expected[i].style; - if (sty && sty.indexOf(" ")) sty = sty.split(' ').sort().join(' '); - expectedOutput.push({style: sty, text: expected[i].text}); - } - - var observedOutput = highlight(text, mode); - - var s = ""; - var diff = highlightOutputsDifferent(expectedOutput, observedOutput); - if (diff != null) { - s += '
    '; - s += '
    ' + esc(text) + '
    '; - s += '
    '; - s += 'expected:'; - s += prettyPrintOutputTable(expectedOutput, diff); - s += 'observed: [display states]'; - s += prettyPrintOutputTable(observedOutput, diff); - s += '
    '; - s += '
    '; - } - if (observedOutput.indentFailures) { - for (var i = 0; i < observedOutput.indentFailures.length; i++) - s += "
    " + esc(observedOutput.indentFailures[i]) + "
    "; - } - if (s) throw new Failure(s); - } - - function stringify(obj) { - function replacer(key, obj) { - if (typeof obj == "function") { - var m = obj.toString().match(/function\s*[^\s(]*/); - return m ? m[0] : "function"; - } - return obj; - } - if (window.JSON && JSON.stringify) - return JSON.stringify(obj, replacer, 2); - return "[unsupported]"; // Fail safely if no native JSON. - } - - function highlight(string, mode) { - var state = mode.startState(); - - var lines = string.replace(/\r\n/g,'\n').split('\n'); - var st = [], pos = 0; - for (var i = 0; i < lines.length; ++i) { - var line = lines[i], newLine = true; - if (mode.indent) { - var ws = line.match(/^\s*/)[0]; - var indent = mode.indent(state, line.slice(ws.length)); - if (indent != CodeMirror.Pass && indent != ws.length) - (st.indentFailures || (st.indentFailures = [])).push( - "Indentation of line " + (i + 1) + " is " + indent + " (expected " + ws.length + ")"); - } - var stream = new CodeMirror.StringStream(line); - if (line == "" && mode.blankLine) mode.blankLine(state); - /* Start copied code from CodeMirror.highlight */ - while (!stream.eol()) { - for (var j = 0; j < 10 && stream.start >= stream.pos; j++) - var compare = mode.token(stream, state); - if (j == 10) - throw new Failure("Failed to advance the stream." + stream.string + " " + stream.pos); - var substr = stream.current(); - if (compare && compare.indexOf(" ") > -1) compare = compare.split(' ').sort().join(' '); - stream.start = stream.pos; - if (pos && st[pos-1].style == compare && !newLine) { - st[pos-1].text += substr; - } else if (substr) { - st[pos++] = {style: compare, text: substr, state: stringify(state)}; - } - // Give up when line is ridiculously long - if (stream.pos > 5000) { - st[pos++] = {style: null, text: this.text.slice(stream.pos)}; - break; - } - newLine = false; - } - } - - return st; - } - - function highlightOutputsDifferent(o1, o2) { - var minLen = Math.min(o1.length, o2.length); - for (var i = 0; i < minLen; ++i) - if (o1[i].style != o2[i].style || o1[i].text != o2[i].text) return i; - if (o1.length > minLen || o2.length > minLen) return minLen; - } - - function prettyPrintOutputTable(output, diffAt) { - var s = ''; - s += ''; - for (var i = 0; i < output.length; ++i) { - var style = output[i].style, val = output[i].text; - s += - ''; - } - s += ''; - for (var i = 0; i < output.length; ++i) { - s += ''; - } - if(output[0].state) { - s += ''; - for (var i = 0; i < output.length; ++i) { - s += ''; - } - } - s += '
    ' + - '' + - esc(val.replace(/ /g,'\xb7')) + // · MIDDLE DOT - '' + - '
    ' + (output[i].style || null) + '
    ' + esc(output[i].state) + '
    '; - return s; - } -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/test/multi_test.js b/backend/_pv_1_3_5/static/codemirror/test/multi_test.js deleted file mode 100755 index a8e760d27..000000000 --- a/backend/_pv_1_3_5/static/codemirror/test/multi_test.js +++ /dev/null @@ -1,285 +0,0 @@ -(function() { - namespace = "multi_"; - - function hasSelections(cm) { - var sels = cm.listSelections(); - var given = (arguments.length - 1) / 4; - if (sels.length != given) - throw new Failure("expected " + given + " selections, found " + sels.length); - for (var i = 0, p = 1; i < given; i++, p += 4) { - var anchor = Pos(arguments[p], arguments[p + 1]); - var head = Pos(arguments[p + 2], arguments[p + 3]); - eqPos(sels[i].anchor, anchor, "anchor of selection " + i); - eqPos(sels[i].head, head, "head of selection " + i); - } - } - function hasCursors(cm) { - var sels = cm.listSelections(); - var given = (arguments.length - 1) / 2; - if (sels.length != given) - throw new Failure("expected " + given + " selections, found " + sels.length); - for (var i = 0, p = 1; i < given; i++, p += 2) { - eqPos(sels[i].anchor, sels[i].head, "something selected for " + i); - var head = Pos(arguments[p], arguments[p + 1]); - eqPos(sels[i].head, head, "selection " + i); - } - } - - testCM("getSelection", function(cm) { - select(cm, {anchor: Pos(0, 0), head: Pos(1, 2)}, {anchor: Pos(2, 2), head: Pos(2, 0)}); - eq(cm.getSelection(), "1234\n56\n90"); - eq(cm.getSelection(false).join("|"), "1234|56|90"); - eq(cm.getSelections().join("|"), "1234\n56|90"); - }, {value: "1234\n5678\n90"}); - - testCM("setSelection", function(cm) { - select(cm, Pos(3, 0), Pos(0, 0), {anchor: Pos(2, 5), head: Pos(1, 0)}); - hasSelections(cm, 0, 0, 0, 0, - 2, 5, 1, 0, - 3, 0, 3, 0); - cm.setSelection(Pos(1, 2), Pos(1, 1)); - hasSelections(cm, 1, 2, 1, 1); - select(cm, {anchor: Pos(1, 1), head: Pos(2, 4)}, - {anchor: Pos(0, 0), head: Pos(1, 3)}, - Pos(3, 0), Pos(2, 2)); - hasSelections(cm, 0, 0, 2, 4, - 3, 0, 3, 0); - cm.setSelections([{anchor: Pos(0, 1), head: Pos(0, 2)}, - {anchor: Pos(1, 1), head: Pos(1, 2)}, - {anchor: Pos(2, 1), head: Pos(2, 2)}], 1); - eqPos(cm.getCursor("head"), Pos(1, 2)); - eqPos(cm.getCursor("anchor"), Pos(1, 1)); - eqPos(cm.getCursor("from"), Pos(1, 1)); - eqPos(cm.getCursor("to"), Pos(1, 2)); - cm.setCursor(Pos(1, 1)); - hasCursors(cm, 1, 1); - }, {value: "abcde\nabcde\nabcde\n"}); - - testCM("somethingSelected", function(cm) { - select(cm, Pos(0, 1), {anchor: Pos(0, 3), head: Pos(0, 5)}); - eq(cm.somethingSelected(), true); - select(cm, Pos(0, 1), Pos(0, 3), Pos(0, 5)); - eq(cm.somethingSelected(), false); - }, {value: "123456789"}); - - testCM("extendSelection", function(cm) { - select(cm, Pos(0, 1), Pos(1, 1), Pos(2, 1)); - cm.setExtending(true); - cm.extendSelections([Pos(0, 2), Pos(1, 0), Pos(2, 3)]); - hasSelections(cm, 0, 1, 0, 2, - 1, 1, 1, 0, - 2, 1, 2, 3); - cm.extendSelection(Pos(2, 4), Pos(2, 0)); - hasSelections(cm, 2, 4, 2, 0); - }, {value: "1234\n1234\n1234"}); - - testCM("addSelection", function(cm) { - select(cm, Pos(0, 1), Pos(1, 1)); - cm.addSelection(Pos(0, 0), Pos(0, 4)); - hasSelections(cm, 0, 0, 0, 4, - 1, 1, 1, 1); - cm.addSelection(Pos(2, 2)); - hasSelections(cm, 0, 0, 0, 4, - 1, 1, 1, 1, - 2, 2, 2, 2); - }, {value: "1234\n1234\n1234"}); - - testCM("replaceSelection", function(cm) { - var selections = [{anchor: Pos(0, 0), head: Pos(0, 1)}, - {anchor: Pos(0, 2), head: Pos(0, 3)}, - {anchor: Pos(0, 4), head: Pos(0, 5)}, - {anchor: Pos(2, 1), head: Pos(2, 4)}, - {anchor: Pos(2, 5), head: Pos(2, 6)}]; - var val = "123456\n123456\n123456"; - cm.setValue(val); - cm.setSelections(selections); - cm.replaceSelection("ab", "around"); - eq(cm.getValue(), "ab2ab4ab6\n123456\n1ab5ab"); - hasSelections(cm, 0, 0, 0, 2, - 0, 3, 0, 5, - 0, 6, 0, 8, - 2, 1, 2, 3, - 2, 4, 2, 6); - cm.setValue(val); - cm.setSelections(selections); - cm.replaceSelection("", "around"); - eq(cm.getValue(), "246\n123456\n15"); - hasSelections(cm, 0, 0, 0, 0, - 0, 1, 0, 1, - 0, 2, 0, 2, - 2, 1, 2, 1, - 2, 2, 2, 2); - cm.setValue(val); - cm.setSelections(selections); - cm.replaceSelection("X\nY\nZ", "around"); - hasSelections(cm, 0, 0, 2, 1, - 2, 2, 4, 1, - 4, 2, 6, 1, - 8, 1, 10, 1, - 10, 2, 12, 1); - cm.replaceSelection("a", "around"); - hasSelections(cm, 0, 0, 0, 1, - 0, 2, 0, 3, - 0, 4, 0, 5, - 2, 1, 2, 2, - 2, 3, 2, 4); - cm.replaceSelection("xy", "start"); - hasSelections(cm, 0, 0, 0, 0, - 0, 3, 0, 3, - 0, 6, 0, 6, - 2, 1, 2, 1, - 2, 4, 2, 4); - cm.replaceSelection("z\nf"); - hasSelections(cm, 1, 1, 1, 1, - 2, 1, 2, 1, - 3, 1, 3, 1, - 6, 1, 6, 1, - 7, 1, 7, 1); - eq(cm.getValue(), "z\nfxy2z\nfxy4z\nfxy6\n123456\n1z\nfxy5z\nfxy"); - }); - - function select(cm) { - var sels = []; - for (var i = 1; i < arguments.length; i++) { - var arg = arguments[i]; - if (arg.head) sels.push(arg); - else sels.push({head: arg, anchor: arg}); - } - cm.setSelections(sels, sels.length - 1); - } - - testCM("indentSelection", function(cm) { - select(cm, Pos(0, 1), Pos(1, 1)); - cm.indentSelection(4); - eq(cm.getValue(), " foo\n bar\nbaz"); - - select(cm, Pos(0, 2), Pos(0, 3), Pos(0, 4)); - cm.indentSelection(-2); - eq(cm.getValue(), " foo\n bar\nbaz"); - - select(cm, {anchor: Pos(0, 0), head: Pos(1, 2)}, - {anchor: Pos(1, 3), head: Pos(2, 0)}); - cm.indentSelection(-2); - eq(cm.getValue(), "foo\n bar\nbaz"); - }, {value: "foo\nbar\nbaz"}); - - testCM("killLine", function(cm) { - select(cm, Pos(0, 1), Pos(0, 2), Pos(1, 1)); - cm.execCommand("killLine"); - eq(cm.getValue(), "f\nb\nbaz"); - cm.execCommand("killLine"); - eq(cm.getValue(), "fbbaz"); - cm.setValue("foo\nbar\nbaz"); - select(cm, Pos(0, 1), {anchor: Pos(0, 2), head: Pos(2, 1)}); - cm.execCommand("killLine"); - eq(cm.getValue(), "faz"); - }, {value: "foo\nbar\nbaz"}); - - testCM("deleteLine", function(cm) { - select(cm, Pos(0, 0), - {head: Pos(0, 1), anchor: Pos(2, 0)}, - Pos(4, 0)); - cm.execCommand("deleteLine"); - eq(cm.getValue(), "4\n6\n7"); - select(cm, Pos(2, 1)); - cm.execCommand("deleteLine"); - eq(cm.getValue(), "4\n6\n"); - }, {value: "1\n2\n3\n4\n5\n6\n7"}); - - testCM("deleteH", function(cm) { - select(cm, Pos(0, 4), {anchor: Pos(1, 4), head: Pos(1, 5)}); - cm.execCommand("delWordAfter"); - eq(cm.getValue(), "foo bar baz\nabc ef ghi\n"); - cm.execCommand("delWordAfter"); - eq(cm.getValue(), "foo baz\nabc ghi\n"); - cm.execCommand("delCharBefore"); - cm.execCommand("delCharBefore"); - eq(cm.getValue(), "fo baz\nab ghi\n"); - select(cm, Pos(0, 3), Pos(0, 4), Pos(0, 5)); - cm.execCommand("delWordAfter"); - eq(cm.getValue(), "fo \nab ghi\n"); - }, {value: "foo bar baz\nabc def ghi\n"}); - - testCM("goLineStart", function(cm) { - select(cm, Pos(0, 2), Pos(0, 3), Pos(1, 1)); - cm.execCommand("goLineStart"); - hasCursors(cm, 0, 0, 1, 0); - select(cm, Pos(1, 1), Pos(0, 1)); - cm.setExtending(true); - cm.execCommand("goLineStart"); - hasSelections(cm, 0, 1, 0, 0, - 1, 1, 1, 0); - }, {value: "foo\nbar\nbaz"}); - - testCM("moveV", function(cm) { - select(cm, Pos(0, 2), Pos(1, 2)); - cm.execCommand("goLineDown"); - hasCursors(cm, 1, 2, 2, 2); - cm.execCommand("goLineUp"); - hasCursors(cm, 0, 2, 1, 2); - cm.execCommand("goLineUp"); - hasCursors(cm, 0, 0, 0, 2); - cm.execCommand("goLineUp"); - hasCursors(cm, 0, 0); - select(cm, Pos(0, 2), Pos(1, 2)); - cm.setExtending(true); - cm.execCommand("goLineDown"); - hasSelections(cm, 0, 2, 2, 2); - }, {value: "12345\n12345\n12345"}); - - testCM("moveH", function(cm) { - select(cm, Pos(0, 1), Pos(0, 3), Pos(0, 5), Pos(2, 3)); - cm.execCommand("goCharRight"); - hasCursors(cm, 0, 2, 0, 4, 1, 0, 2, 4); - cm.execCommand("goCharLeft"); - hasCursors(cm, 0, 1, 0, 3, 0, 5, 2, 3); - for (var i = 0; i < 15; i++) - cm.execCommand("goCharRight"); - hasCursors(cm, 2, 4, 2, 5); - }, {value: "12345\n12345\n12345"}); - - testCM("newlineAndIndent", function(cm) { - select(cm, Pos(0, 5), Pos(1, 5)); - cm.execCommand("newlineAndIndent"); - hasCursors(cm, 1, 2, 3, 2); - eq(cm.getValue(), "x = [\n 1];\ny = [\n 2];"); - cm.undo(); - eq(cm.getValue(), "x = [1];\ny = [2];"); - hasCursors(cm, 0, 5, 1, 5); - select(cm, Pos(0, 5), Pos(0, 6)); - cm.execCommand("newlineAndIndent"); - hasCursors(cm, 1, 2, 2, 0); - eq(cm.getValue(), "x = [\n 1\n];\ny = [2];"); - }, {value: "x = [1];\ny = [2];", mode: "javascript"}); - - testCM("goDocStartEnd", function(cm) { - select(cm, Pos(0, 1), Pos(1, 1)); - cm.execCommand("goDocStart"); - hasCursors(cm, 0, 0); - select(cm, Pos(0, 1), Pos(1, 1)); - cm.execCommand("goDocEnd"); - hasCursors(cm, 1, 3); - select(cm, Pos(0, 1), Pos(1, 1)); - cm.setExtending(true); - cm.execCommand("goDocEnd"); - hasSelections(cm, 1, 1, 1, 3); - }, {value: "abc\ndef"}); - - testCM("selectionHistory", function(cm) { - for (var i = 0; i < 3; ++i) - cm.addSelection(Pos(0, i * 2), Pos(0, i * 2 + 1)); - cm.execCommand("undoSelection"); - eq(cm.getSelection(), "1\n2"); - cm.execCommand("undoSelection"); - eq(cm.getSelection(), "1"); - cm.execCommand("undoSelection"); - eq(cm.getSelection(), ""); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("redoSelection"); - eq(cm.getSelection(), "1"); - cm.execCommand("redoSelection"); - eq(cm.getSelection(), "1\n2"); - cm.execCommand("redoSelection"); - eq(cm.getSelection(), "1\n2\n3"); - }, {value: "1 2 3"}); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/test/phantom_driver.js b/backend/_pv_1_3_5/static/codemirror/test/phantom_driver.js deleted file mode 100755 index dbad08db6..000000000 --- a/backend/_pv_1_3_5/static/codemirror/test/phantom_driver.js +++ /dev/null @@ -1,31 +0,0 @@ -var page = require('webpage').create(); - -page.open("http://localhost:3000/test/index.html", function (status) { - if (status != "success") { - console.log("page couldn't be loaded successfully"); - phantom.exit(1); - } - waitFor(function () { - return page.evaluate(function () { - var output = document.getElementById('status'); - if (!output) { return false; } - return (/^(\d+ failures?|all passed)/i).test(output.innerText); - }); - }, function () { - var failed = page.evaluate(function () { return window.failed; }); - var output = page.evaluate(function () { - return document.getElementById('output').innerText + "\n" + - document.getElementById('status').innerText; - }); - console.log(output); - phantom.exit(failed > 0 ? 1 : 0); - }); -}); - -function waitFor (test, cb) { - if (test()) { - cb(); - } else { - setTimeout(function () { waitFor(test, cb); }, 250); - } -} diff --git a/backend/_pv_1_3_5/static/codemirror/test/run.js b/backend/_pv_1_3_5/static/codemirror/test/run.js deleted file mode 100755 index 54984e73a..000000000 --- a/backend/_pv_1_3_5/static/codemirror/test/run.js +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env node - -var ok = require("./lint").ok; - -var files = new (require('node-static').Server)(); - -var server = require('http').createServer(function (req, res) { - req.addListener('end', function () { - files.serve(req, res, function (err/*, result */) { - if (err) { - console.error(err); - process.exit(1); - } - }); - }).resume(); -}).addListener('error', function (err) { - throw err; -}).listen(3000, function () { - var childProcess = require('child_process'); - var phantomjs = require("phantomjs-prebuilt"); - var childArgs = [ - require("path").join(__dirname, 'phantom_driver.js') - ]; - childProcess.execFile(phantomjs.path, childArgs, function (err, stdout, stderr) { - server.close(); - console.log(stdout); - if (err) console.error(err); - if (stderr) console.error(stderr); - process.exit(err || stderr || !ok ? 1 : 0); - }); -}); diff --git a/backend/_pv_1_3_5/static/codemirror/test/scroll_test.js b/backend/_pv_1_3_5/static/codemirror/test/scroll_test.js deleted file mode 100755 index 55aac78eb..000000000 --- a/backend/_pv_1_3_5/static/codemirror/test/scroll_test.js +++ /dev/null @@ -1,115 +0,0 @@ -(function() { - "use strict"; - - namespace = "scroll_"; - - testCM("bars_hidden", function(cm) { - for (var i = 0;; i++) { - var wrapBox = cm.getWrapperElement().getBoundingClientRect(); - var scrollBox = cm.getScrollerElement().getBoundingClientRect(); - is(wrapBox.bottom < scrollBox.bottom - 10); - is(wrapBox.right < scrollBox.right - 10); - if (i == 1) break; - cm.getWrapperElement().style.height = "auto"; - cm.refresh(); - } - }); - - function barH(cm) { return byClassName(cm.getWrapperElement(), "CodeMirror-hscrollbar")[0]; } - function barV(cm) { return byClassName(cm.getWrapperElement(), "CodeMirror-vscrollbar")[0]; } - - function displayBottom(cm, scrollbar) { - if (scrollbar && cm.display.scroller.offsetHeight > cm.display.scroller.clientHeight) - return barH(cm).getBoundingClientRect().top; - else - return cm.getWrapperElement().getBoundingClientRect().bottom - 1; - } - - function displayRight(cm, scrollbar) { - if (scrollbar && cm.display.scroller.offsetWidth > cm.display.scroller.clientWidth) - return barV(cm).getBoundingClientRect().left; - else - return cm.getWrapperElement().getBoundingClientRect().right - 1; - } - - function testMovedownFixed(cm, hScroll) { - cm.setSize("100px", "100px"); - if (hScroll) cm.setValue(new Array(100).join("x")); - var bottom = displayBottom(cm, hScroll); - for (var i = 0; i < 30; i++) { - cm.replaceSelection("x\n"); - var cursorBottom = cm.cursorCoords(null, "window").bottom; - is(cursorBottom <= bottom); - } - is(cursorBottom >= bottom - 5); - } - - testCM("movedown_fixed", function(cm) {testMovedownFixed(cm, false);}); - testCM("movedown_hscroll_fixed", function(cm) {testMovedownFixed(cm, true);}); - - function testMovedownResize(cm, hScroll) { - cm.getWrapperElement().style.height = "auto"; - if (hScroll) cm.setValue(new Array(100).join("x")); - cm.refresh(); - for (var i = 0; i < 30; i++) { - cm.replaceSelection("x\n"); - var bottom = displayBottom(cm, hScroll); - var cursorBottom = cm.cursorCoords(null, "window").bottom; - is(cursorBottom <= bottom); - is(cursorBottom >= bottom - 5); - } - } - - testCM("movedown_resize", function(cm) {testMovedownResize(cm, false);}); - testCM("movedown_hscroll_resize", function(cm) {testMovedownResize(cm, true);}); - - function testMoveright(cm, wrap, scroll) { - cm.setSize("100px", "100px"); - if (wrap) cm.setOption("lineWrapping", true); - if (scroll) { - cm.setValue("\n" + new Array(100).join("x\n")); - cm.setCursor(Pos(0, 0)); - } - var right = displayRight(cm, scroll); - for (var i = 0; i < 10; i++) { - cm.replaceSelection("xxxxxxxxxx"); - var cursorRight = cm.cursorCoords(null, "window").right; - is(cursorRight < right); - } - if (!wrap) is(cursorRight > right - 20); - } - - testCM("moveright", function(cm) {testMoveright(cm, false, false);}); - testCM("moveright_wrap", function(cm) {testMoveright(cm, true, false);}); - testCM("moveright_scroll", function(cm) {testMoveright(cm, false, true);}); - testCM("moveright_scroll_wrap", function(cm) {testMoveright(cm, true, true);}); - - testCM("suddenly_wide", function(cm) { - addDoc(cm, 100, 100); - cm.replaceSelection(new Array(600).join("l ") + "\n"); - cm.execCommand("goLineUp"); - cm.execCommand("goLineEnd"); - is(barH(cm).scrollLeft > cm.getScrollerElement().scrollLeft - 1); - }); - - testCM("wrap_changes_height", function(cm) { - var line = new Array(20).join("a ") + "\n"; - cm.setValue(new Array(20).join(line)); - var box = cm.getWrapperElement().getBoundingClientRect(); - cm.setSize(cm.cursorCoords(Pos(0), "window").right - box.left + 2, - cm.cursorCoords(Pos(19, 0), "window").bottom - box.top + 2); - cm.setCursor(Pos(19, 0)); - cm.replaceSelection("\n"); - is(cm.cursorCoords(null, "window").bottom < displayBottom(cm, false)); - }, {lineWrapping: true}); - - testCM("height_auto_with_gutter_expect_no_scroll_after_line_delete", function(cm) { - cm.setSize(null, "auto"); - cm.setValue("x\n"); - cm.execCommand("goDocEnd"); - cm.execCommand("delCharBefore"); - eq(cm.getScrollInfo().top, 0); - cm.scrollTo(null, 10); - is(cm.getScrollInfo().top < 5); - }, {lineNumbers: true}); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/test/search_test.js b/backend/_pv_1_3_5/static/codemirror/test/search_test.js deleted file mode 100755 index 04a1e685a..000000000 --- a/backend/_pv_1_3_5/static/codemirror/test/search_test.js +++ /dev/null @@ -1,62 +0,0 @@ -(function() { - "use strict"; - - function test(name) { - var text = Array.prototype.slice.call(arguments, 1, arguments.length - 1).join("\n"); - var body = arguments[arguments.length - 1]; - return window.test("search_" + name, function() { - body(new CodeMirror.Doc(text)); - }); - } - - function run(doc, query, insensitive) { - var cursor = doc.getSearchCursor(query, null, insensitive); - for (var i = 3; i < arguments.length; i += 4) { - var found = cursor.findNext(); - is(found, "not enough results (forward)"); - eqPos(Pos(arguments[i], arguments[i + 1]), cursor.from(), "from, forward, " + (i - 3) / 4); - eqPos(Pos(arguments[i + 2], arguments[i + 3]), cursor.to(), "to, forward, " + (i - 3) / 4); - } - is(!cursor.findNext(), "too many matches (forward)"); - for (var i = arguments.length - 4; i >= 3; i -= 4) { - var found = cursor.findPrevious(); - is(found, "not enough results (backwards)"); - eqPos(Pos(arguments[i], arguments[i + 1]), cursor.from(), "from, backwards, " + (i - 3) / 4); - eqPos(Pos(arguments[i + 2], arguments[i + 3]), cursor.to(), "to, backwards, " + (i - 3) / 4); - } - is(!cursor.findPrevious(), "too many matches (backwards)"); - } - - test("simple", "abcdefg", "abcdefg", function(doc) { - run(doc, "cde", false, 0, 2, 0, 5, 1, 2, 1, 5); - }); - - test("multiline", "hallo", "goodbye", function(doc) { - run(doc, "llo\ngoo", false, 0, 2, 1, 3); - run(doc, "blah\nhall", false); - run(doc, "bye\neye", false); - }); - - test("regexp", "abcde", "abcde", function(doc) { - run(doc, /bcd/, false, 0, 1, 0, 4, 1, 1, 1, 4); - run(doc, /BCD/, false); - run(doc, /BCD/i, false, 0, 1, 0, 4, 1, 1, 1, 4); - }); - - test("insensitive", "hallo", "HALLO", "oink", "hAllO", function(doc) { - run(doc, "All", false, 3, 1, 3, 4); - run(doc, "All", true, 0, 1, 0, 4, 1, 1, 1, 4, 3, 1, 3, 4); - }); - - test("multilineInsensitive", "zie ginds komT", "De Stoomboot", "uit Spanje weer aan", function(doc) { - run(doc, "komt\nde stoomboot\nuit", false); - run(doc, "komt\nde stoomboot\nuit", true, 0, 10, 2, 3); - run(doc, "kOMt\ndE stOOmboot\nuiT", true, 0, 10, 2, 3); - }); - - test("expandingCaseFold", "İİ İİ", "uu uu", function(doc) { - if (phantom) return; // A Phantom bug makes this hang - run(doc, "
    ", true, 0, 8, 0, 12, 1, 8, 1, 12); - run(doc, "İİ", true, 0, 3, 0, 5, 0, 6, 0, 8); - }); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/test/sql-hint-test.js b/backend/_pv_1_3_5/static/codemirror/test/sql-hint-test.js deleted file mode 100755 index 39f2172e1..000000000 --- a/backend/_pv_1_3_5/static/codemirror/test/sql-hint-test.js +++ /dev/null @@ -1,189 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE - -(function() { - var Pos = CodeMirror.Pos; - - var simpleTables = { - "users": ["name", "score", "birthDate"], - "xcountries": ["name", "population", "size"] - }; - - var schemaTables = { - "schema.users": ["name", "score", "birthDate"], - "schema.countries": ["name", "population", "size"] - }; - - var displayTextTables = [{ - text: "mytable", - displayText: "mytable | The main table", - columns: [{text: "id", displayText: "id | Unique ID"}, - {text: "name", displayText: "name | The name"}] - }]; - - namespace = "sql-hint_"; - - function test(name, spec) { - testCM(name, function(cm) { - cm.setValue(spec.value); - cm.setCursor(spec.cursor); - var completion = CodeMirror.hint.sql(cm, {tables: spec.tables}); - if (!deepCompare(completion.list, spec.list)) - throw new Failure("Wrong completion results " + JSON.stringify(completion.list) + " vs " + JSON.stringify(spec.list)); - eqPos(completion.from, spec.from); - eqPos(completion.to, spec.to); - }, { - value: spec.value, - mode: "text/x-mysql" - }); - } - - test("keywords", { - value: "SEL", - cursor: Pos(0, 3), - list: ["SELECT"], - from: Pos(0, 0), - to: Pos(0, 3) - }); - - test("from", { - value: "SELECT * fr", - cursor: Pos(0, 11), - list: ["FROM"], - from: Pos(0, 9), - to: Pos(0, 11) - }); - - test("table", { - value: "SELECT xc", - cursor: Pos(0, 9), - tables: simpleTables, - list: ["xcountries"], - from: Pos(0, 7), - to: Pos(0, 9) - }); - - test("columns", { - value: "SELECT users.", - cursor: Pos(0, 13), - tables: simpleTables, - list: ["users.name", "users.score", "users.birthDate"], - from: Pos(0, 7), - to: Pos(0, 13) - }); - - test("singlecolumn", { - value: "SELECT users.na", - cursor: Pos(0, 15), - tables: simpleTables, - list: ["users.name"], - from: Pos(0, 7), - to: Pos(0, 15) - }); - - test("quoted", { - value: "SELECT `users`.`na", - cursor: Pos(0, 18), - tables: simpleTables, - list: ["`users`.`name`"], - from: Pos(0, 7), - to: Pos(0, 18) - }); - - test("quotedcolumn", { - value: "SELECT users.`na", - cursor: Pos(0, 16), - tables: simpleTables, - list: ["`users`.`name`"], - from: Pos(0, 7), - to: Pos(0, 16) - }); - - test("schema", { - value: "SELECT schem", - cursor: Pos(0, 12), - tables: schemaTables, - list: ["schema.users", "schema.countries", - "SCHEMA", "SCHEMA_NAME", "SCHEMAS"], - from: Pos(0, 7), - to: Pos(0, 12) - }); - - test("schemaquoted", { - value: "SELECT `sch", - cursor: Pos(0, 11), - tables: schemaTables, - list: ["`schema`.`users`", "`schema`.`countries`"], - from: Pos(0, 7), - to: Pos(0, 11) - }); - - test("schemacolumn", { - value: "SELECT schema.users.", - cursor: Pos(0, 20), - tables: schemaTables, - list: ["schema.users.name", - "schema.users.score", - "schema.users.birthDate"], - from: Pos(0, 7), - to: Pos(0, 20) - }); - - test("schemacolumnquoted", { - value: "SELECT `schema`.`users`.", - cursor: Pos(0, 24), - tables: schemaTables, - list: ["`schema`.`users`.`name`", - "`schema`.`users`.`score`", - "`schema`.`users`.`birthDate`"], - from: Pos(0, 7), - to: Pos(0, 24) - }); - - test("displayText_table", { - value: "SELECT myt", - cursor: Pos(0, 10), - tables: displayTextTables, - list: displayTextTables, - from: Pos(0, 7), - to: Pos(0, 10) - }); - - test("displayText_column", { - value: "SELECT mytable.", - cursor: Pos(0, 15), - tables: displayTextTables, - list: [{text: "mytable.id", displayText: "id | Unique ID"}, - {text: "mytable.name", displayText: "name | The name"}], - from: Pos(0, 7), - to: Pos(0, 15) - }); - - test("alias_complete", { - value: "SELECT t. FROM users t", - cursor: Pos(0, 9), - tables: simpleTables, - list: ["t.name", "t.score", "t.birthDate"], - from: Pos(0, 7), - to: Pos(0, 9) - }); - - test("alias_complete_with_displayText", { - value: "SELECT t. FROM mytable t", - cursor: Pos(0, 9), - tables: displayTextTables, - list: [{text: "t.id", displayText: "id | Unique ID"}, - {text: "t.name", displayText: "name | The name"}], - from: Pos(0, 7), - to: Pos(0, 9) - }) - - function deepCompare(a, b) { - if (!a || typeof a != "object") - return a === b; - if (!b || typeof b != "object") - return false; - for (var prop in a) if (!deepCompare(a[prop], b[prop])) return false; - return true; - } -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/test/sublime_test.js b/backend/_pv_1_3_5/static/codemirror/test/sublime_test.js deleted file mode 100755 index 57f16485e..000000000 --- a/backend/_pv_1_3_5/static/codemirror/test/sublime_test.js +++ /dev/null @@ -1,307 +0,0 @@ -(function() { - "use strict"; - - var Pos = CodeMirror.Pos; - namespace = "sublime_"; - - function stTest(name) { - var actions = Array.prototype.slice.call(arguments, 1); - testCM(name, function(cm) { - for (var i = 0; i < actions.length; i++) { - var action = actions[i]; - if (typeof action == "string" && i == 0) - cm.setValue(action); - else if (typeof action == "string") - cm.execCommand(action); - else if (action instanceof Pos) - cm.setCursor(action); - else - action(cm); - } - }); - } - - function at(line, ch, msg) { - return function(cm) { - eq(cm.listSelections().length, 1); - eqPos(cm.getCursor("head"), Pos(line, ch), msg); - eqPos(cm.getCursor("anchor"), Pos(line, ch), msg); - }; - } - - function val(content, msg) { - return function(cm) { eq(cm.getValue(), content, msg); }; - } - - function argsToRanges(args) { - if (args.length % 4) throw new Error("Wrong number of arguments for ranges."); - var ranges = []; - for (var i = 0; i < args.length; i += 4) - ranges.push({anchor: Pos(args[i], args[i + 1]), - head: Pos(args[i + 2], args[i + 3])}); - return ranges; - } - - function setSel() { - var ranges = argsToRanges(arguments); - return function(cm) { cm.setSelections(ranges, 0); }; - } - - function hasSel() { - var ranges = argsToRanges(arguments); - return function(cm) { - var sels = cm.listSelections(); - if (sels.length != ranges.length) - throw new Failure("Expected " + ranges.length + " selections, but found " + sels.length); - for (var i = 0; i < sels.length; i++) { - eqPos(sels[i].anchor, ranges[i].anchor, "anchor " + i); - eqPos(sels[i].head, ranges[i].head, "head " + i); - } - }; - } - - stTest("bySubword", "the foo_bar DooDahBah \n a", - "goSubwordLeft", at(0, 0), - "goSubwordRight", at(0, 3), - "goSubwordRight", at(0, 7), - "goSubwordRight", at(0, 11), - "goSubwordRight", at(0, 15), - "goSubwordRight", at(0, 18), - "goSubwordRight", at(0, 21), - "goSubwordRight", at(0, 22), - "goSubwordRight", at(1, 0), - "goSubwordRight", at(1, 2), - "goSubwordRight", at(1, 2), - "goSubwordLeft", at(1, 1), - "goSubwordLeft", at(1, 0), - "goSubwordLeft", at(0, 22), - "goSubwordLeft", at(0, 18), - "goSubwordLeft", at(0, 15), - "goSubwordLeft", at(0, 12), - "goSubwordLeft", at(0, 8), - "goSubwordLeft", at(0, 4), - "goSubwordLeft", at(0, 0)); - - stTest("splitSelectionByLine", "abc\ndef\nghi", - setSel(0, 1, 2, 2), - "splitSelectionByLine", - hasSel(0, 1, 0, 3, - 1, 0, 1, 3, - 2, 0, 2, 2)); - - stTest("splitSelectionByLineMulti", "abc\ndef\nghi\njkl", - setSel(0, 1, 1, 1, - 1, 2, 3, 2, - 3, 3, 3, 3), - "splitSelectionByLine", - hasSel(0, 1, 0, 3, - 1, 0, 1, 1, - 1, 2, 1, 3, - 2, 0, 2, 3, - 3, 0, 3, 2, - 3, 3, 3, 3)); - - stTest("selectLine", "abc\ndef\nghi", - setSel(0, 1, 0, 1, - 2, 0, 2, 1), - "selectLine", - hasSel(0, 0, 1, 0, - 2, 0, 2, 3), - setSel(0, 1, 1, 0), - "selectLine", - hasSel(0, 0, 2, 0)); - - stTest("insertLineAfter", "abcde\nfghijkl\nmn", - setSel(0, 1, 0, 1, - 0, 3, 0, 3, - 1, 2, 1, 2, - 1, 3, 1, 5), "insertLineAfter", - hasSel(1, 0, 1, 0, - 3, 0, 3, 0), val("abcde\n\nfghijkl\n\nmn")); - - stTest("insertLineBefore", "abcde\nfghijkl\nmn", - setSel(0, 1, 0, 1, - 0, 3, 0, 3, - 1, 2, 1, 2, - 1, 3, 1, 5), "insertLineBefore", - hasSel(0, 0, 0, 0, - 2, 0, 2, 0), val("\nabcde\n\nfghijkl\nmn")); - - stTest("selectNextOccurrence", "a foo bar\nfoobar foo", - setSel(0, 2, 0, 5), - "selectNextOccurrence", hasSel(0, 2, 0, 5, - 1, 0, 1, 3), - "selectNextOccurrence", hasSel(0, 2, 0, 5, - 1, 0, 1, 3, - 1, 7, 1, 10), - "selectNextOccurrence", hasSel(0, 2, 0, 5, - 1, 0, 1, 3, - 1, 7, 1, 10), - Pos(0, 3), "selectNextOccurrence", hasSel(0, 2, 0, 5), - "selectNextOccurrence", hasSel(0, 2, 0, 5, - 1, 7, 1, 10), - setSel(0, 6, 0, 9), - "selectNextOccurrence", hasSel(0, 6, 0, 9, - 1, 3, 1, 6)); - - stTest("selectScope", "foo(a) {\n bar[1, 2];\n}", - "selectScope", hasSel(0, 0, 2, 1), - Pos(0, 4), "selectScope", hasSel(0, 4, 0, 5), - Pos(0, 5), "selectScope", hasSel(0, 4, 0, 5), - Pos(0, 6), "selectScope", hasSel(0, 0, 2, 1), - Pos(0, 8), "selectScope", hasSel(0, 8, 2, 0), - Pos(1, 2), "selectScope", hasSel(0, 8, 2, 0), - Pos(1, 6), "selectScope", hasSel(1, 6, 1, 10), - Pos(1, 9), "selectScope", hasSel(1, 6, 1, 10)); - - stTest("goToBracket", "foo(a) {\n bar[1, 2];\n}", - Pos(0, 0), "goToBracket", at(0, 0), - Pos(0, 4), "goToBracket", at(0, 5), "goToBracket", at(0, 4), - Pos(0, 8), "goToBracket", at(2, 0), "goToBracket", at(0, 8), - Pos(1, 2), "goToBracket", at(2, 0), - Pos(1, 7), "goToBracket", at(1, 10), "goToBracket", at(1, 6)); - - stTest("swapLine", "1\n2\n3---\n4\n5", - "swapLineDown", val("2\n1\n3---\n4\n5"), - "swapLineUp", val("1\n2\n3---\n4\n5"), - "swapLineUp", val("1\n2\n3---\n4\n5"), - Pos(4, 1), "swapLineDown", val("1\n2\n3---\n4\n5"), - setSel(0, 1, 0, 1, - 1, 0, 2, 0, - 2, 2, 2, 2), - "swapLineDown", val("4\n1\n2\n3---\n5"), - hasSel(1, 1, 1, 1, - 2, 0, 3, 0, - 3, 2, 3, 2), - "swapLineUp", val("1\n2\n3---\n4\n5"), - hasSel(0, 1, 0, 1, - 1, 0, 2, 0, - 2, 2, 2, 2)); - - stTest("swapLineEmptyBottomSel", "1\n2\n3", - setSel(0, 1, 1, 0), - "swapLineDown", val("2\n1\n3"), hasSel(1, 1, 2, 0), - "swapLineUp", val("1\n2\n3"), hasSel(0, 1, 1, 0), - "swapLineUp", val("1\n2\n3"), hasSel(0, 0, 0, 0)); - - stTest("swapLineUpFromEnd", "a\nb\nc", - Pos(2, 1), "swapLineUp", - hasSel(1, 1, 1, 1), val("a\nc\nb")); - - stTest("joinLines", "abc\ndef\nghi\njkl", - "joinLines", val("abc def\nghi\njkl"), at(0, 4), - "undo", - setSel(0, 2, 1, 1), "joinLines", - val("abc def ghi\njkl"), hasSel(0, 2, 0, 8), - "undo", - setSel(0, 1, 0, 1, - 1, 1, 1, 1, - 3, 1, 3, 1), "joinLines", - val("abc def ghi\njkl"), hasSel(0, 4, 0, 4, - 0, 8, 0, 8, - 1, 3, 1, 3)); - - stTest("duplicateLine", "abc\ndef\nghi", - Pos(1, 0), "duplicateLine", val("abc\ndef\ndef\nghi"), at(2, 0), - "undo", - setSel(0, 1, 0, 1, - 1, 1, 1, 1, - 2, 1, 2, 1), "duplicateLine", - val("abc\nabc\ndef\ndef\nghi\nghi"), hasSel(1, 1, 1, 1, - 3, 1, 3, 1, - 5, 1, 5, 1)); - stTest("duplicateLineSelection", "abcdef", - setSel(0, 1, 0, 1, - 0, 2, 0, 4, - 0, 5, 0, 5), - "duplicateLine", - val("abcdef\nabcdcdef\nabcdcdef"), hasSel(2, 1, 2, 1, - 2, 4, 2, 6, - 2, 7, 2, 7)); - - stTest("selectLinesUpward", "123\n345\n789\n012", - setSel(0, 1, 0, 1, - 1, 1, 1, 3, - 2, 0, 2, 0, - 3, 0, 3, 0), - "selectLinesUpward", - hasSel(0, 1, 0, 1, - 0, 3, 0, 3, - 1, 0, 1, 0, - 1, 1, 1, 3, - 2, 0, 2, 0, - 3, 0, 3, 0)); - - stTest("selectLinesDownward", "123\n345\n789\n012", - setSel(0, 1, 0, 1, - 1, 1, 1, 3, - 2, 0, 2, 0, - 3, 0, 3, 0), - "selectLinesDownward", - hasSel(0, 1, 0, 1, - 1, 1, 1, 3, - 2, 0, 2, 0, - 2, 3, 2, 3, - 3, 0, 3, 0)); - - stTest("sortLines", "c\nb\na\nC\nB\nA", - "sortLines", val("A\nB\nC\na\nb\nc"), - "undo", - setSel(0, 0, 2, 0, - 3, 0, 5, 0), - "sortLines", val("b\nc\na\nB\nC\nA"), - hasSel(0, 0, 2, 0, - 3, 0, 5, 0), - "undo", - setSel(1, 0, 5, 0), "sortLinesInsensitive", val("c\na\nB\nb\nC\nA")); - - stTest("bookmarks", "abc\ndef\nghi\njkl", - Pos(0, 1), "toggleBookmark", - setSel(1, 1, 1, 2), "toggleBookmark", - setSel(2, 1, 2, 2), "toggleBookmark", - "nextBookmark", hasSel(0, 1, 0, 1), - "nextBookmark", hasSel(1, 1, 1, 2), - "nextBookmark", hasSel(2, 1, 2, 2), - "prevBookmark", hasSel(1, 1, 1, 2), - "prevBookmark", hasSel(0, 1, 0, 1), - "prevBookmark", hasSel(2, 1, 2, 2), - "prevBookmark", hasSel(1, 1, 1, 2), - "toggleBookmark", - "prevBookmark", hasSel(2, 1, 2, 2), - "prevBookmark", hasSel(0, 1, 0, 1), - "selectBookmarks", hasSel(0, 1, 0, 1, - 2, 1, 2, 2), - "clearBookmarks", - Pos(0, 0), "selectBookmarks", at(0, 0)); - - stTest("smartBackspace", " foo\n bar", - setSel(0, 2, 0, 2, 1, 4, 1, 4, 1, 6, 1, 6), "smartBackspace", - val("foo\n br")) - - stTest("upAndDowncaseAtCursor", "abc\ndef x\nghI", - setSel(0, 1, 0, 3, - 1, 1, 1, 1, - 1, 4, 1, 4), "upcaseAtCursor", - val("aBC\nDEF x\nghI"), hasSel(0, 1, 0, 3, - 1, 3, 1, 3, - 1, 4, 1, 4), - "downcaseAtCursor", - val("abc\ndef x\nghI"), hasSel(0, 1, 0, 3, - 1, 3, 1, 3, - 1, 4, 1, 4)); - - stTest("mark", "abc\ndef\nghi", - Pos(1, 1), "setSublimeMark", - Pos(2, 1), "selectToSublimeMark", hasSel(2, 1, 1, 1), - Pos(0, 1), "swapWithSublimeMark", at(1, 1), "swapWithSublimeMark", at(0, 1), - "deleteToSublimeMark", val("aef\nghi"), - "sublimeYank", val("abc\ndef\nghi"), at(1, 1)); - - stTest("findUnder", "foo foobar a", - "findUnder", hasSel(0, 4, 0, 7), - "findUnder", hasSel(0, 0, 0, 3), - "findUnderPrevious", hasSel(0, 4, 0, 7), - "findUnderPrevious", hasSel(0, 0, 0, 3), - Pos(0, 4), "findUnder", hasSel(0, 4, 0, 10), - Pos(0, 11), "findUnder", hasSel(0, 11, 0, 11)); -})(); diff --git a/backend/_pv_1_3_5/static/codemirror/test/test.js b/backend/_pv_1_3_5/static/codemirror/test/test.js deleted file mode 100755 index de2c66e83..000000000 --- a/backend/_pv_1_3_5/static/codemirror/test/test.js +++ /dev/null @@ -1,2200 +0,0 @@ -var Pos = CodeMirror.Pos; - -CodeMirror.defaults.rtlMoveVisually = true; - -function forEach(arr, f) { - for (var i = 0, e = arr.length; i < e; ++i) f(arr[i], i); -} - -function addDoc(cm, width, height) { - var content = [], line = ""; - for (var i = 0; i < width; ++i) line += "x"; - for (var i = 0; i < height; ++i) content.push(line); - cm.setValue(content.join("\n")); -} - -function byClassName(elt, cls) { - if (elt.getElementsByClassName) return elt.getElementsByClassName(cls); - var found = [], re = new RegExp("\\b" + cls + "\\b"); - function search(elt) { - if (elt.nodeType == 3) return; - if (re.test(elt.className)) found.push(elt); - for (var i = 0, e = elt.childNodes.length; i < e; ++i) - search(elt.childNodes[i]); - } - search(elt); - return found; -} - -var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent); -var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent); -var mac = /Mac/.test(navigator.platform); -var phantom = /PhantomJS/.test(navigator.userAgent); -var opera = /Opera\/\./.test(navigator.userAgent); -var opera_version = opera && navigator.userAgent.match(/Version\/(\d+\.\d+)/); -if (opera_version) opera_version = Number(opera_version); -var opera_lt10 = opera && (!opera_version || opera_version < 10); - -namespace = "core_"; - -test("core_fromTextArea", function() { - var te = document.getElementById("code"); - te.value = "CONTENT"; - var cm = CodeMirror.fromTextArea(te); - is(!te.offsetHeight); - eq(cm.getValue(), "CONTENT"); - cm.setValue("foo\nbar"); - eq(cm.getValue(), "foo\nbar"); - cm.save(); - is(/^foo\r?\nbar$/.test(te.value)); - cm.setValue("xxx"); - cm.toTextArea(); - is(te.offsetHeight); - eq(te.value, "xxx"); -}); - -testCM("getRange", function(cm) { - eq(cm.getLine(0), "1234"); - eq(cm.getLine(1), "5678"); - eq(cm.getLine(2), null); - eq(cm.getLine(-1), null); - eq(cm.getRange(Pos(0, 0), Pos(0, 3)), "123"); - eq(cm.getRange(Pos(0, -1), Pos(0, 200)), "1234"); - eq(cm.getRange(Pos(0, 2), Pos(1, 2)), "34\n56"); - eq(cm.getRange(Pos(1, 2), Pos(100, 0)), "78"); -}, {value: "1234\n5678"}); - -testCM("replaceRange", function(cm) { - eq(cm.getValue(), ""); - cm.replaceRange("foo\n", Pos(0, 0)); - eq(cm.getValue(), "foo\n"); - cm.replaceRange("a\nb", Pos(0, 1)); - eq(cm.getValue(), "fa\nboo\n"); - eq(cm.lineCount(), 3); - cm.replaceRange("xyzzy", Pos(0, 0), Pos(1, 1)); - eq(cm.getValue(), "xyzzyoo\n"); - cm.replaceRange("abc", Pos(0, 0), Pos(10, 0)); - eq(cm.getValue(), "abc"); - eq(cm.lineCount(), 1); -}); - -testCM("selection", function(cm) { - cm.setSelection(Pos(0, 4), Pos(2, 2)); - is(cm.somethingSelected()); - eq(cm.getSelection(), "11\n222222\n33"); - eqPos(cm.getCursor(false), Pos(2, 2)); - eqPos(cm.getCursor(true), Pos(0, 4)); - cm.setSelection(Pos(1, 0)); - is(!cm.somethingSelected()); - eq(cm.getSelection(), ""); - eqPos(cm.getCursor(true), Pos(1, 0)); - cm.replaceSelection("abc", "around"); - eq(cm.getSelection(), "abc"); - eq(cm.getValue(), "111111\nabc222222\n333333"); - cm.replaceSelection("def", "end"); - eq(cm.getSelection(), ""); - eqPos(cm.getCursor(true), Pos(1, 3)); - cm.setCursor(Pos(2, 1)); - eqPos(cm.getCursor(true), Pos(2, 1)); - cm.setCursor(1, 2); - eqPos(cm.getCursor(true), Pos(1, 2)); -}, {value: "111111\n222222\n333333"}); - -testCM("extendSelection", function(cm) { - cm.setExtending(true); - addDoc(cm, 10, 10); - cm.setSelection(Pos(3, 5)); - eqPos(cm.getCursor("head"), Pos(3, 5)); - eqPos(cm.getCursor("anchor"), Pos(3, 5)); - cm.setSelection(Pos(2, 5), Pos(5, 5)); - eqPos(cm.getCursor("head"), Pos(5, 5)); - eqPos(cm.getCursor("anchor"), Pos(2, 5)); - eqPos(cm.getCursor("start"), Pos(2, 5)); - eqPos(cm.getCursor("end"), Pos(5, 5)); - cm.setSelection(Pos(5, 5), Pos(2, 5)); - eqPos(cm.getCursor("head"), Pos(2, 5)); - eqPos(cm.getCursor("anchor"), Pos(5, 5)); - eqPos(cm.getCursor("start"), Pos(2, 5)); - eqPos(cm.getCursor("end"), Pos(5, 5)); - cm.extendSelection(Pos(3, 2)); - eqPos(cm.getCursor("head"), Pos(3, 2)); - eqPos(cm.getCursor("anchor"), Pos(5, 5)); - cm.extendSelection(Pos(6, 2)); - eqPos(cm.getCursor("head"), Pos(6, 2)); - eqPos(cm.getCursor("anchor"), Pos(5, 5)); - cm.extendSelection(Pos(6, 3), Pos(6, 4)); - eqPos(cm.getCursor("head"), Pos(6, 4)); - eqPos(cm.getCursor("anchor"), Pos(5, 5)); - cm.extendSelection(Pos(0, 3), Pos(0, 4)); - eqPos(cm.getCursor("head"), Pos(0, 3)); - eqPos(cm.getCursor("anchor"), Pos(5, 5)); - cm.extendSelection(Pos(4, 5), Pos(6, 5)); - eqPos(cm.getCursor("head"), Pos(6, 5)); - eqPos(cm.getCursor("anchor"), Pos(4, 5)); - cm.setExtending(false); - cm.extendSelection(Pos(0, 3), Pos(0, 4)); - eqPos(cm.getCursor("head"), Pos(0, 3)); - eqPos(cm.getCursor("anchor"), Pos(0, 4)); -}); - -testCM("lines", function(cm) { - eq(cm.getLine(0), "111111"); - eq(cm.getLine(1), "222222"); - eq(cm.getLine(-1), null); - cm.replaceRange("", Pos(1, 0), Pos(2, 0)) - cm.replaceRange("abc", Pos(1, 0), Pos(1)); - eq(cm.getValue(), "111111\nabc"); -}, {value: "111111\n222222\n333333"}); - -testCM("indent", function(cm) { - cm.indentLine(1); - eq(cm.getLine(1), " blah();"); - cm.setOption("indentUnit", 8); - cm.indentLine(1); - eq(cm.getLine(1), "\tblah();"); - cm.setOption("indentUnit", 10); - cm.setOption("tabSize", 4); - cm.indentLine(1); - eq(cm.getLine(1), "\t\t blah();"); -}, {value: "if (x) {\nblah();\n}", indentUnit: 3, indentWithTabs: true, tabSize: 8}); - -testCM("indentByNumber", function(cm) { - cm.indentLine(0, 2); - eq(cm.getLine(0), " foo"); - cm.indentLine(0, -200); - eq(cm.getLine(0), "foo"); - cm.setSelection(Pos(0, 0), Pos(1, 2)); - cm.indentSelection(3); - eq(cm.getValue(), " foo\n bar\nbaz"); -}, {value: "foo\nbar\nbaz"}); - -test("core_defaults", function() { - var defsCopy = {}, defs = CodeMirror.defaults; - for (var opt in defs) defsCopy[opt] = defs[opt]; - defs.indentUnit = 5; - defs.value = "uu"; - defs.indentWithTabs = true; - defs.tabindex = 55; - var place = document.getElementById("testground"), cm = CodeMirror(place); - try { - eq(cm.getOption("indentUnit"), 5); - cm.setOption("indentUnit", 10); - eq(defs.indentUnit, 5); - eq(cm.getValue(), "uu"); - eq(cm.getOption("indentWithTabs"), true); - eq(cm.getInputField().tabIndex, 55); - } - finally { - for (var opt in defsCopy) defs[opt] = defsCopy[opt]; - place.removeChild(cm.getWrapperElement()); - } -}); - -testCM("lineInfo", function(cm) { - eq(cm.lineInfo(-1), null); - var mark = document.createElement("span"); - var lh = cm.setGutterMarker(1, "FOO", mark); - var info = cm.lineInfo(1); - eq(info.text, "222222"); - eq(info.gutterMarkers.FOO, mark); - eq(info.line, 1); - eq(cm.lineInfo(2).gutterMarkers, null); - cm.setGutterMarker(lh, "FOO", null); - eq(cm.lineInfo(1).gutterMarkers, null); - cm.setGutterMarker(1, "FOO", mark); - cm.setGutterMarker(0, "FOO", mark); - cm.clearGutter("FOO"); - eq(cm.lineInfo(0).gutterMarkers, null); - eq(cm.lineInfo(1).gutterMarkers, null); -}, {value: "111111\n222222\n333333"}); - -testCM("coords", function(cm) { - cm.setSize(null, 100); - addDoc(cm, 32, 200); - var top = cm.charCoords(Pos(0, 0)); - var bot = cm.charCoords(Pos(200, 30)); - is(top.left < bot.left); - is(top.top < bot.top); - is(top.top < top.bottom); - cm.scrollTo(null, 100); - var top2 = cm.charCoords(Pos(0, 0)); - is(top.top > top2.top); - eq(top.left, top2.left); -}); - -testCM("coordsChar", function(cm) { - addDoc(cm, 35, 70); - for (var i = 0; i < 2; ++i) { - var sys = i ? "local" : "page"; - for (var ch = 0; ch <= 35; ch += 5) { - for (var line = 0; line < 70; line += 5) { - cm.setCursor(line, ch); - var coords = cm.charCoords(Pos(line, ch), sys); - var pos = cm.coordsChar({left: coords.left + 1, top: coords.top + 1}, sys); - eqPos(pos, Pos(line, ch)); - } - } - } -}, {lineNumbers: true}); - -testCM("posFromIndex", function(cm) { - cm.setValue( - "This function should\n" + - "convert a zero based index\n" + - "to line and ch." - ); - - var examples = [ - { index: -1, line: 0, ch: 0 }, // <- Tests clipping - { index: 0, line: 0, ch: 0 }, - { index: 10, line: 0, ch: 10 }, - { index: 39, line: 1, ch: 18 }, - { index: 55, line: 2, ch: 7 }, - { index: 63, line: 2, ch: 15 }, - { index: 64, line: 2, ch: 15 } // <- Tests clipping - ]; - - for (var i = 0; i < examples.length; i++) { - var example = examples[i]; - var pos = cm.posFromIndex(example.index); - eq(pos.line, example.line); - eq(pos.ch, example.ch); - if (example.index >= 0 && example.index < 64) - eq(cm.indexFromPos(pos), example.index); - } -}); - -testCM("undo", function(cm) { - cm.replaceRange("def", Pos(0, 0), Pos(0)); - eq(cm.historySize().undo, 1); - cm.undo(); - eq(cm.getValue(), "abc"); - eq(cm.historySize().undo, 0); - eq(cm.historySize().redo, 1); - cm.redo(); - eq(cm.getValue(), "def"); - eq(cm.historySize().undo, 1); - eq(cm.historySize().redo, 0); - cm.setValue("1\n\n\n2"); - cm.clearHistory(); - eq(cm.historySize().undo, 0); - for (var i = 0; i < 20; ++i) { - cm.replaceRange("a", Pos(0, 0)); - cm.replaceRange("b", Pos(3, 0)); - } - eq(cm.historySize().undo, 40); - for (var i = 0; i < 40; ++i) - cm.undo(); - eq(cm.historySize().redo, 40); - eq(cm.getValue(), "1\n\n\n2"); -}, {value: "abc"}); - -testCM("undoDepth", function(cm) { - cm.replaceRange("d", Pos(0)); - cm.replaceRange("e", Pos(0)); - cm.replaceRange("f", Pos(0)); - cm.undo(); cm.undo(); cm.undo(); - eq(cm.getValue(), "abcd"); -}, {value: "abc", undoDepth: 4}); - -testCM("undoDoesntClearValue", function(cm) { - cm.undo(); - eq(cm.getValue(), "x"); -}, {value: "x"}); - -testCM("undoMultiLine", function(cm) { - cm.operation(function() { - cm.replaceRange("x", Pos(0, 0)); - cm.replaceRange("y", Pos(1, 0)); - }); - cm.undo(); - eq(cm.getValue(), "abc\ndef\nghi"); - cm.operation(function() { - cm.replaceRange("y", Pos(1, 0)); - cm.replaceRange("x", Pos(0, 0)); - }); - cm.undo(); - eq(cm.getValue(), "abc\ndef\nghi"); - cm.operation(function() { - cm.replaceRange("y", Pos(2, 0)); - cm.replaceRange("x", Pos(1, 0)); - cm.replaceRange("z", Pos(2, 0)); - }); - cm.undo(); - eq(cm.getValue(), "abc\ndef\nghi", 3); -}, {value: "abc\ndef\nghi"}); - -testCM("undoComposite", function(cm) { - cm.replaceRange("y", Pos(1)); - cm.operation(function() { - cm.replaceRange("x", Pos(0)); - cm.replaceRange("z", Pos(2)); - }); - eq(cm.getValue(), "ax\nby\ncz\n"); - cm.undo(); - eq(cm.getValue(), "a\nby\nc\n"); - cm.undo(); - eq(cm.getValue(), "a\nb\nc\n"); - cm.redo(); cm.redo(); - eq(cm.getValue(), "ax\nby\ncz\n"); -}, {value: "a\nb\nc\n"}); - -testCM("undoSelection", function(cm) { - cm.setSelection(Pos(0, 2), Pos(0, 4)); - cm.replaceSelection(""); - cm.setCursor(Pos(1, 0)); - cm.undo(); - eqPos(cm.getCursor(true), Pos(0, 2)); - eqPos(cm.getCursor(false), Pos(0, 4)); - cm.setCursor(Pos(1, 0)); - cm.redo(); - eqPos(cm.getCursor(true), Pos(0, 2)); - eqPos(cm.getCursor(false), Pos(0, 2)); -}, {value: "abcdefgh\n"}); - -testCM("undoSelectionAsBefore", function(cm) { - cm.replaceSelection("abc", "around"); - cm.undo(); - cm.redo(); - eq(cm.getSelection(), "abc"); -}); - -testCM("selectionChangeConfusesHistory", function(cm) { - cm.replaceSelection("abc", null, "dontmerge"); - cm.operation(function() { - cm.setCursor(Pos(0, 0)); - cm.replaceSelection("abc", null, "dontmerge"); - }); - eq(cm.historySize().undo, 2); -}); - -testCM("markTextSingleLine", function(cm) { - forEach([{a: 0, b: 1, c: "", f: 2, t: 5}, - {a: 0, b: 4, c: "", f: 0, t: 2}, - {a: 1, b: 2, c: "x", f: 3, t: 6}, - {a: 4, b: 5, c: "", f: 3, t: 5}, - {a: 4, b: 5, c: "xx", f: 3, t: 7}, - {a: 2, b: 5, c: "", f: 2, t: 3}, - {a: 2, b: 5, c: "abcd", f: 6, t: 7}, - {a: 2, b: 6, c: "x", f: null, t: null}, - {a: 3, b: 6, c: "", f: null, t: null}, - {a: 0, b: 9, c: "hallo", f: null, t: null}, - {a: 4, b: 6, c: "x", f: 3, t: 4}, - {a: 4, b: 8, c: "", f: 3, t: 4}, - {a: 6, b: 6, c: "a", f: 3, t: 6}, - {a: 8, b: 9, c: "", f: 3, t: 6}], function(test) { - cm.setValue("1234567890"); - var r = cm.markText(Pos(0, 3), Pos(0, 6), {className: "foo"}); - cm.replaceRange(test.c, Pos(0, test.a), Pos(0, test.b)); - var f = r.find(); - eq(f && f.from.ch, test.f); eq(f && f.to.ch, test.t); - }); -}); - -testCM("markTextMultiLine", function(cm) { - function p(v) { return v && Pos(v[0], v[1]); } - forEach([{a: [0, 0], b: [0, 5], c: "", f: [0, 0], t: [2, 5]}, - {a: [0, 0], b: [0, 5], c: "foo\n", f: [1, 0], t: [3, 5]}, - {a: [0, 1], b: [0, 10], c: "", f: [0, 1], t: [2, 5]}, - {a: [0, 5], b: [0, 6], c: "x", f: [0, 6], t: [2, 5]}, - {a: [0, 0], b: [1, 0], c: "", f: [0, 0], t: [1, 5]}, - {a: [0, 6], b: [2, 4], c: "", f: [0, 5], t: [0, 7]}, - {a: [0, 6], b: [2, 4], c: "aa", f: [0, 5], t: [0, 9]}, - {a: [1, 2], b: [1, 8], c: "", f: [0, 5], t: [2, 5]}, - {a: [0, 5], b: [2, 5], c: "xx", f: null, t: null}, - {a: [0, 0], b: [2, 10], c: "x", f: null, t: null}, - {a: [1, 5], b: [2, 5], c: "", f: [0, 5], t: [1, 5]}, - {a: [2, 0], b: [2, 3], c: "", f: [0, 5], t: [2, 2]}, - {a: [2, 5], b: [3, 0], c: "a\nb", f: [0, 5], t: [2, 5]}, - {a: [2, 3], b: [3, 0], c: "x", f: [0, 5], t: [2, 3]}, - {a: [1, 1], b: [1, 9], c: "1\n2\n3", f: [0, 5], t: [4, 5]}], function(test) { - cm.setValue("aaaaaaaaaa\nbbbbbbbbbb\ncccccccccc\ndddddddd\n"); - var r = cm.markText(Pos(0, 5), Pos(2, 5), - {className: "CodeMirror-matchingbracket"}); - cm.replaceRange(test.c, p(test.a), p(test.b)); - var f = r.find(); - eqPos(f && f.from, p(test.f)); eqPos(f && f.to, p(test.t)); - }); -}); - -testCM("markTextUndo", function(cm) { - var marker1, marker2, bookmark; - marker1 = cm.markText(Pos(0, 1), Pos(0, 3), - {className: "CodeMirror-matchingbracket"}); - marker2 = cm.markText(Pos(0, 0), Pos(2, 1), - {className: "CodeMirror-matchingbracket"}); - bookmark = cm.setBookmark(Pos(1, 5)); - cm.operation(function(){ - cm.replaceRange("foo", Pos(0, 2)); - cm.replaceRange("bar\nbaz\nbug\n", Pos(2, 0), Pos(3, 0)); - }); - var v1 = cm.getValue(); - cm.setValue(""); - eq(marker1.find(), null); eq(marker2.find(), null); eq(bookmark.find(), null); - cm.undo(); - eqPos(bookmark.find(), Pos(1, 5), "still there"); - cm.undo(); - var m1Pos = marker1.find(), m2Pos = marker2.find(); - eqPos(m1Pos.from, Pos(0, 1)); eqPos(m1Pos.to, Pos(0, 3)); - eqPos(m2Pos.from, Pos(0, 0)); eqPos(m2Pos.to, Pos(2, 1)); - eqPos(bookmark.find(), Pos(1, 5)); - cm.redo(); cm.redo(); - eq(bookmark.find(), null); - cm.undo(); - eqPos(bookmark.find(), Pos(1, 5)); - eq(cm.getValue(), v1); -}, {value: "1234\n56789\n00\n"}); - -testCM("markTextStayGone", function(cm) { - var m1 = cm.markText(Pos(0, 0), Pos(0, 1)); - cm.replaceRange("hi", Pos(0, 2)); - m1.clear(); - cm.undo(); - eq(m1.find(), null); -}, {value: "hello"}); - -testCM("markTextAllowEmpty", function(cm) { - var m1 = cm.markText(Pos(0, 1), Pos(0, 2), {clearWhenEmpty: false}); - is(m1.find()); - cm.replaceRange("x", Pos(0, 0)); - is(m1.find()); - cm.replaceRange("y", Pos(0, 2)); - is(m1.find()); - cm.replaceRange("z", Pos(0, 3), Pos(0, 4)); - is(!m1.find()); - var m2 = cm.markText(Pos(0, 1), Pos(0, 2), {clearWhenEmpty: false, - inclusiveLeft: true, - inclusiveRight: true}); - cm.replaceRange("q", Pos(0, 1), Pos(0, 2)); - is(m2.find()); - cm.replaceRange("", Pos(0, 0), Pos(0, 3)); - is(!m2.find()); - var m3 = cm.markText(Pos(0, 1), Pos(0, 1), {clearWhenEmpty: false}); - cm.replaceRange("a", Pos(0, 3)); - is(m3.find()); - cm.replaceRange("b", Pos(0, 1)); - is(!m3.find()); -}, {value: "abcde"}); - -testCM("markTextStacked", function(cm) { - var m1 = cm.markText(Pos(0, 0), Pos(0, 0), {clearWhenEmpty: false}); - var m2 = cm.markText(Pos(0, 0), Pos(0, 0), {clearWhenEmpty: false}); - cm.replaceRange("B", Pos(0, 1)); - is(m1.find() && m2.find()); -}, {value: "A"}); - -testCM("undoPreservesNewMarks", function(cm) { - cm.markText(Pos(0, 3), Pos(0, 4)); - cm.markText(Pos(1, 1), Pos(1, 3)); - cm.replaceRange("", Pos(0, 3), Pos(3, 1)); - var mBefore = cm.markText(Pos(0, 0), Pos(0, 1)); - var mAfter = cm.markText(Pos(0, 5), Pos(0, 6)); - var mAround = cm.markText(Pos(0, 2), Pos(0, 4)); - cm.undo(); - eqPos(mBefore.find().from, Pos(0, 0)); - eqPos(mBefore.find().to, Pos(0, 1)); - eqPos(mAfter.find().from, Pos(3, 3)); - eqPos(mAfter.find().to, Pos(3, 4)); - eqPos(mAround.find().from, Pos(0, 2)); - eqPos(mAround.find().to, Pos(3, 2)); - var found = cm.findMarksAt(Pos(2, 2)); - eq(found.length, 1); - eq(found[0], mAround); -}, {value: "aaaa\nbbbb\ncccc\ndddd"}); - -testCM("markClearBetween", function(cm) { - cm.setValue("aaa\nbbb\nccc\nddd\n"); - cm.markText(Pos(0, 0), Pos(2)); - cm.replaceRange("aaa\nbbb\nccc", Pos(0, 0), Pos(2)); - eq(cm.findMarksAt(Pos(1, 1)).length, 0); -}); - -testCM("findMarksMiddle", function(cm) { - var mark = cm.markText(Pos(1, 1), Pos(3, 1)); - var found = cm.findMarks(Pos(2, 1), Pos(2, 2)); - eq(found.length, 1); - eq(found[0], mark); -}, {value: "line 0\nline 1\nline 2\nline 3"}); - -testCM("deleteSpanCollapsedInclusiveLeft", function(cm) { - var from = Pos(1, 0), to = Pos(1, 1); - var m = cm.markText(from, to, {collapsed: true, inclusiveLeft: true}); - // Delete collapsed span. - cm.replaceRange("", from, to); -}, {value: "abc\nX\ndef"}); - -testCM("markTextCSS", function(cm) { - function present() { - var spans = cm.display.lineDiv.getElementsByTagName("span"); - for (var i = 0; i < spans.length; i++) - if (spans[i].style.color == "cyan" && span[i].textContent == "cdefg") return true; - } - var m = cm.markText(Pos(0, 2), Pos(0, 6), {css: "color: cyan"}); - m.clear(); - is(!present()); -}, {value: "abcdefgh"}); - -testCM("bookmark", function(cm) { - function p(v) { return v && Pos(v[0], v[1]); } - forEach([{a: [1, 0], b: [1, 1], c: "", d: [1, 4]}, - {a: [1, 1], b: [1, 1], c: "xx", d: [1, 7]}, - {a: [1, 4], b: [1, 5], c: "ab", d: [1, 6]}, - {a: [1, 4], b: [1, 6], c: "", d: null}, - {a: [1, 5], b: [1, 6], c: "abc", d: [1, 5]}, - {a: [1, 6], b: [1, 8], c: "", d: [1, 5]}, - {a: [1, 4], b: [1, 4], c: "\n\n", d: [3, 1]}, - {bm: [1, 9], a: [1, 1], b: [1, 1], c: "\n", d: [2, 8]}], function(test) { - cm.setValue("1234567890\n1234567890\n1234567890"); - var b = cm.setBookmark(p(test.bm) || Pos(1, 5)); - cm.replaceRange(test.c, p(test.a), p(test.b)); - eqPos(b.find(), p(test.d)); - }); -}); - -testCM("bookmarkInsertLeft", function(cm) { - var br = cm.setBookmark(Pos(0, 2), {insertLeft: false}); - var bl = cm.setBookmark(Pos(0, 2), {insertLeft: true}); - cm.setCursor(Pos(0, 2)); - cm.replaceSelection("hi"); - eqPos(br.find(), Pos(0, 2)); - eqPos(bl.find(), Pos(0, 4)); - cm.replaceRange("", Pos(0, 4), Pos(0, 5)); - cm.replaceRange("", Pos(0, 2), Pos(0, 4)); - cm.replaceRange("", Pos(0, 1), Pos(0, 2)); - // Verify that deleting next to bookmarks doesn't kill them - eqPos(br.find(), Pos(0, 1)); - eqPos(bl.find(), Pos(0, 1)); -}, {value: "abcdef"}); - -testCM("bookmarkCursor", function(cm) { - var pos01 = cm.cursorCoords(Pos(0, 1)), pos11 = cm.cursorCoords(Pos(1, 1)), - pos20 = cm.cursorCoords(Pos(2, 0)), pos30 = cm.cursorCoords(Pos(3, 0)), - pos41 = cm.cursorCoords(Pos(4, 1)); - cm.setBookmark(Pos(0, 1), {widget: document.createTextNode("←"), insertLeft: true}); - cm.setBookmark(Pos(2, 0), {widget: document.createTextNode("←"), insertLeft: true}); - cm.setBookmark(Pos(1, 1), {widget: document.createTextNode("→")}); - cm.setBookmark(Pos(3, 0), {widget: document.createTextNode("→")}); - var new01 = cm.cursorCoords(Pos(0, 1)), new11 = cm.cursorCoords(Pos(1, 1)), - new20 = cm.cursorCoords(Pos(2, 0)), new30 = cm.cursorCoords(Pos(3, 0)); - near(new01.left, pos01.left, 1); - near(new01.top, pos01.top, 1); - is(new11.left > pos11.left, "at right, middle of line"); - near(new11.top == pos11.top, 1); - near(new20.left, pos20.left, 1); - near(new20.top, pos20.top, 1); - is(new30.left > pos30.left, "at right, empty line"); - near(new30.top, pos30, 1); - cm.setBookmark(Pos(4, 0), {widget: document.createTextNode("→")}); - is(cm.cursorCoords(Pos(4, 1)).left > pos41.left, "single-char bug"); -}, {value: "foo\nbar\n\n\nx\ny"}); - -testCM("multiBookmarkCursor", function(cm) { - if (phantom) return; - var ms = [], m; - function add(insertLeft) { - for (var i = 0; i < 3; ++i) { - var node = document.createElement("span"); - node.innerHTML = "X"; - ms.push(cm.setBookmark(Pos(0, 1), {widget: node, insertLeft: insertLeft})); - } - } - var base1 = cm.cursorCoords(Pos(0, 1)).left, base4 = cm.cursorCoords(Pos(0, 4)).left; - add(true); - near(base1, cm.cursorCoords(Pos(0, 1)).left, 1); - while (m = ms.pop()) m.clear(); - add(false); - near(base4, cm.cursorCoords(Pos(0, 1)).left, 1); -}, {value: "abcdefg"}); - -testCM("getAllMarks", function(cm) { - addDoc(cm, 10, 10); - var m1 = cm.setBookmark(Pos(0, 2)); - var m2 = cm.markText(Pos(0, 2), Pos(3, 2)); - var m3 = cm.markText(Pos(1, 2), Pos(1, 8)); - var m4 = cm.markText(Pos(8, 0), Pos(9, 0)); - eq(cm.getAllMarks().length, 4); - m1.clear(); - m3.clear(); - eq(cm.getAllMarks().length, 2); -}); - -testCM("setValueClears", function(cm) { - cm.addLineClass(0, "wrap", "foo"); - var mark = cm.markText(Pos(0, 0), Pos(1, 1), {inclusiveLeft: true, inclusiveRight: true}); - cm.setValue("foo"); - is(!cm.lineInfo(0).wrapClass); - is(!mark.find()); -}, {value: "a\nb"}); - -testCM("bug577", function(cm) { - cm.setValue("a\nb"); - cm.clearHistory(); - cm.setValue("fooooo"); - cm.undo(); -}); - -testCM("scrollSnap", function(cm) { - cm.setSize(100, 100); - addDoc(cm, 200, 200); - cm.setCursor(Pos(100, 180)); - var info = cm.getScrollInfo(); - is(info.left > 0 && info.top > 0); - cm.setCursor(Pos(0, 0)); - info = cm.getScrollInfo(); - is(info.left == 0 && info.top == 0, "scrolled clean to top"); - cm.setCursor(Pos(100, 180)); - cm.setCursor(Pos(199, 0)); - info = cm.getScrollInfo(); - is(info.left == 0 && info.top + 2 > info.height - cm.getScrollerElement().clientHeight, "scrolled clean to bottom"); -}); - -testCM("scrollIntoView", function(cm) { - if (phantom) return; - var outer = cm.getWrapperElement().getBoundingClientRect(); - function test(line, ch, msg) { - var pos = Pos(line, ch); - cm.scrollIntoView(pos); - var box = cm.charCoords(pos, "window"); - is(box.left >= outer.left, msg + " (left)"); - is(box.right <= outer.right, msg + " (right)"); - is(box.top >= outer.top, msg + " (top)"); - is(box.bottom <= outer.bottom, msg + " (bottom)"); - } - addDoc(cm, 200, 200); - test(199, 199, "bottom right"); - test(0, 0, "top left"); - test(100, 100, "center"); - test(199, 0, "bottom left"); - test(0, 199, "top right"); - test(100, 100, "center again"); -}); - -testCM("scrollBackAndForth", function(cm) { - addDoc(cm, 1, 200); - cm.operation(function() { - cm.scrollIntoView(Pos(199, 0)); - cm.scrollIntoView(Pos(4, 0)); - }); - is(cm.getScrollInfo().top > 0); -}); - -testCM("selectAllNoScroll", function(cm) { - addDoc(cm, 1, 200); - cm.execCommand("selectAll"); - eq(cm.getScrollInfo().top, 0); - cm.setCursor(199); - cm.execCommand("selectAll"); - is(cm.getScrollInfo().top > 0); -}); - -testCM("selectionPos", function(cm) { - if (phantom || cm.getOption("inputStyle") != "textarea") return; - cm.setSize(100, 100); - addDoc(cm, 200, 100); - cm.setSelection(Pos(1, 100), Pos(98, 100)); - var lineWidth = cm.charCoords(Pos(0, 200), "local").left; - var lineHeight = (cm.charCoords(Pos(99)).top - cm.charCoords(Pos(0)).top) / 100; - cm.scrollTo(0, 0); - var selElt = byClassName(cm.getWrapperElement(), "CodeMirror-selected"); - var outer = cm.getWrapperElement().getBoundingClientRect(); - var sawMiddle, sawTop, sawBottom; - for (var i = 0, e = selElt.length; i < e; ++i) { - var box = selElt[i].getBoundingClientRect(); - var atLeft = box.left - outer.left < 30; - var width = box.right - box.left; - var atRight = box.right - outer.left > .8 * lineWidth; - if (atLeft && atRight) { - sawMiddle = true; - is(box.bottom - box.top > 90 * lineHeight, "middle high"); - is(width > .9 * lineWidth, "middle wide"); - } else { - is(width > .4 * lineWidth, "top/bot wide enough"); - is(width < .6 * lineWidth, "top/bot slim enough"); - if (atLeft) { - sawBottom = true; - is(box.top - outer.top > 96 * lineHeight, "bot below"); - } else if (atRight) { - sawTop = true; - is(box.top - outer.top < 2.1 * lineHeight, "top above"); - } - } - } - is(sawTop && sawBottom && sawMiddle, "all parts"); -}, null); - -testCM("restoreHistory", function(cm) { - cm.setValue("abc\ndef"); - cm.replaceRange("hello", Pos(1, 0), Pos(1)); - cm.replaceRange("goop", Pos(0, 0), Pos(0)); - cm.undo(); - var storedVal = cm.getValue(), storedHist = cm.getHistory(); - if (window.JSON) storedHist = JSON.parse(JSON.stringify(storedHist)); - eq(storedVal, "abc\nhello"); - cm.setValue(""); - cm.clearHistory(); - eq(cm.historySize().undo, 0); - cm.setValue(storedVal); - cm.setHistory(storedHist); - cm.redo(); - eq(cm.getValue(), "goop\nhello"); - cm.undo(); cm.undo(); - eq(cm.getValue(), "abc\ndef"); -}); - -testCM("doubleScrollbar", function(cm) { - var dummy = document.body.appendChild(document.createElement("p")); - dummy.style.cssText = "height: 50px; overflow: scroll; width: 50px"; - var scrollbarWidth = dummy.offsetWidth + 1 - dummy.clientWidth; - document.body.removeChild(dummy); - if (scrollbarWidth < 2) return; - cm.setSize(null, 100); - addDoc(cm, 1, 300); - var wrap = cm.getWrapperElement(); - is(wrap.offsetWidth - byClassName(wrap, "CodeMirror-lines")[0].offsetWidth <= scrollbarWidth * 1.5); -}); - -testCM("weirdLinebreaks", function(cm) { - cm.setValue("foo\nbar\rbaz\r\nquux\n\rplop"); - is(cm.getValue(), "foo\nbar\nbaz\nquux\n\nplop"); - is(cm.lineCount(), 6); - cm.setValue("\n\n"); - is(cm.lineCount(), 3); -}); - -testCM("setSize", function(cm) { - cm.setSize(100, 100); - var wrap = cm.getWrapperElement(); - is(wrap.offsetWidth, 100); - is(wrap.offsetHeight, 100); - cm.setSize("100%", "3em"); - is(wrap.style.width, "100%"); - is(wrap.style.height, "3em"); - cm.setSize(null, 40); - is(wrap.style.width, "100%"); - is(wrap.style.height, "40px"); -}); - -function foldLines(cm, start, end, autoClear) { - return cm.markText(Pos(start, 0), Pos(end - 1), { - inclusiveLeft: true, - inclusiveRight: true, - collapsed: true, - clearOnEnter: autoClear - }); -} - -testCM("collapsedLines", function(cm) { - addDoc(cm, 4, 10); - var range = foldLines(cm, 4, 5), cleared = 0; - CodeMirror.on(range, "clear", function() {cleared++;}); - cm.setCursor(Pos(3, 0)); - CodeMirror.commands.goLineDown(cm); - eqPos(cm.getCursor(), Pos(5, 0)); - cm.replaceRange("abcdefg", Pos(3, 0), Pos(3)); - cm.setCursor(Pos(3, 6)); - CodeMirror.commands.goLineDown(cm); - eqPos(cm.getCursor(), Pos(5, 4)); - cm.replaceRange("ab", Pos(3, 0), Pos(3)); - cm.setCursor(Pos(3, 2)); - CodeMirror.commands.goLineDown(cm); - eqPos(cm.getCursor(), Pos(5, 2)); - cm.operation(function() {range.clear(); range.clear();}); - eq(cleared, 1); -}); - -testCM("collapsedRangeCoordsChar", function(cm) { - var pos_1_3 = cm.charCoords(Pos(1, 3)); - pos_1_3.left += 2; pos_1_3.top += 2; - var opts = {collapsed: true, inclusiveLeft: true, inclusiveRight: true}; - var m1 = cm.markText(Pos(0, 0), Pos(2, 0), opts); - eqPos(cm.coordsChar(pos_1_3), Pos(3, 3)); - m1.clear(); - var m1 = cm.markText(Pos(0, 0), Pos(1, 1), {collapsed: true, inclusiveLeft: true}); - var m2 = cm.markText(Pos(1, 1), Pos(2, 0), {collapsed: true, inclusiveRight: true}); - eqPos(cm.coordsChar(pos_1_3), Pos(3, 3)); - m1.clear(); m2.clear(); - var m1 = cm.markText(Pos(0, 0), Pos(1, 6), opts); - eqPos(cm.coordsChar(pos_1_3), Pos(3, 3)); -}, {value: "123456\nabcdef\nghijkl\nmnopqr\n"}); - -testCM("collapsedRangeBetweenLinesSelected", function(cm) { - if (cm.getOption("inputStyle") != "textarea") return; - var widget = document.createElement("span"); - widget.textContent = "\u2194"; - cm.markText(Pos(0, 3), Pos(1, 0), {replacedWith: widget}); - cm.setSelection(Pos(0, 3), Pos(1, 0)); - var selElts = byClassName(cm.getWrapperElement(), "CodeMirror-selected"); - for (var i = 0, w = 0; i < selElts.length; i++) - w += selElts[i].offsetWidth; - is(w > 0); -}, {value: "one\ntwo"}); - -testCM("randomCollapsedRanges", function(cm) { - addDoc(cm, 20, 500); - cm.operation(function() { - for (var i = 0; i < 200; i++) { - var start = Pos(Math.floor(Math.random() * 500), Math.floor(Math.random() * 20)); - if (i % 4) - try { cm.markText(start, Pos(start.line + 2, 1), {collapsed: true}); } - catch(e) { if (!/overlapping/.test(String(e))) throw e; } - else - cm.markText(start, Pos(start.line, start.ch + 4), {"className": "foo"}); - } - }); -}); - -testCM("hiddenLinesAutoUnfold", function(cm) { - var range = foldLines(cm, 1, 3, true), cleared = 0; - CodeMirror.on(range, "clear", function() {cleared++;}); - cm.setCursor(Pos(3, 0)); - eq(cleared, 0); - cm.execCommand("goCharLeft"); - eq(cleared, 1); - range = foldLines(cm, 1, 3, true); - CodeMirror.on(range, "clear", function() {cleared++;}); - eqPos(cm.getCursor(), Pos(3, 0)); - cm.setCursor(Pos(0, 3)); - cm.execCommand("goCharRight"); - eq(cleared, 2); -}, {value: "abc\ndef\nghi\njkl"}); - -testCM("hiddenLinesSelectAll", function(cm) { // Issue #484 - addDoc(cm, 4, 20); - foldLines(cm, 0, 10); - foldLines(cm, 11, 20); - CodeMirror.commands.selectAll(cm); - eqPos(cm.getCursor(true), Pos(10, 0)); - eqPos(cm.getCursor(false), Pos(10, 4)); -}); - - -testCM("everythingFolded", function(cm) { - addDoc(cm, 2, 2); - function enterPress() { - cm.triggerOnKeyDown({type: "keydown", keyCode: 13, preventDefault: function(){}, stopPropagation: function(){}}); - } - var fold = foldLines(cm, 0, 2); - enterPress(); - eq(cm.getValue(), "xx\nxx"); - fold.clear(); - fold = foldLines(cm, 0, 2, true); - eq(fold.find(), null); - enterPress(); - eq(cm.getValue(), "\nxx\nxx"); -}); - -testCM("structuredFold", function(cm) { - if (phantom) return; - addDoc(cm, 4, 8); - var range = cm.markText(Pos(1, 2), Pos(6, 2), { - replacedWith: document.createTextNode("Q") - }); - cm.setCursor(0, 3); - CodeMirror.commands.goLineDown(cm); - eqPos(cm.getCursor(), Pos(6, 2)); - CodeMirror.commands.goCharLeft(cm); - eqPos(cm.getCursor(), Pos(1, 2)); - CodeMirror.commands.delCharAfter(cm); - eq(cm.getValue(), "xxxx\nxxxx\nxxxx"); - addDoc(cm, 4, 8); - range = cm.markText(Pos(1, 2), Pos(6, 2), { - replacedWith: document.createTextNode("M"), - clearOnEnter: true - }); - var cleared = 0; - CodeMirror.on(range, "clear", function(){++cleared;}); - cm.setCursor(0, 3); - CodeMirror.commands.goLineDown(cm); - eqPos(cm.getCursor(), Pos(6, 2)); - CodeMirror.commands.goCharLeft(cm); - eqPos(cm.getCursor(), Pos(6, 1)); - eq(cleared, 1); - range.clear(); - eq(cleared, 1); - range = cm.markText(Pos(1, 2), Pos(6, 2), { - replacedWith: document.createTextNode("Q"), - clearOnEnter: true - }); - range.clear(); - cm.setCursor(1, 2); - CodeMirror.commands.goCharRight(cm); - eqPos(cm.getCursor(), Pos(1, 3)); - range = cm.markText(Pos(2, 0), Pos(4, 4), { - replacedWith: document.createTextNode("M") - }); - cm.setCursor(1, 0); - CodeMirror.commands.goLineDown(cm); - eqPos(cm.getCursor(), Pos(2, 0)); -}, null); - -testCM("nestedFold", function(cm) { - addDoc(cm, 10, 3); - function fold(ll, cl, lr, cr) { - return cm.markText(Pos(ll, cl), Pos(lr, cr), {collapsed: true}); - } - var inner1 = fold(0, 6, 1, 3), inner2 = fold(0, 2, 1, 8), outer = fold(0, 1, 2, 3), inner0 = fold(0, 5, 0, 6); - cm.setCursor(0, 1); - CodeMirror.commands.goCharRight(cm); - eqPos(cm.getCursor(), Pos(2, 3)); - inner0.clear(); - CodeMirror.commands.goCharLeft(cm); - eqPos(cm.getCursor(), Pos(0, 1)); - outer.clear(); - CodeMirror.commands.goCharRight(cm); - eqPos(cm.getCursor(), Pos(0, 2)); - CodeMirror.commands.goCharRight(cm); - eqPos(cm.getCursor(), Pos(1, 8)); - inner2.clear(); - CodeMirror.commands.goCharLeft(cm); - eqPos(cm.getCursor(), Pos(1, 7)); - cm.setCursor(0, 5); - CodeMirror.commands.goCharRight(cm); - eqPos(cm.getCursor(), Pos(0, 6)); - CodeMirror.commands.goCharRight(cm); - eqPos(cm.getCursor(), Pos(1, 3)); -}); - -testCM("badNestedFold", function(cm) { - addDoc(cm, 4, 4); - cm.markText(Pos(0, 2), Pos(3, 2), {collapsed: true}); - var caught; - try {cm.markText(Pos(0, 1), Pos(0, 3), {collapsed: true});} - catch(e) {caught = e;} - is(caught instanceof Error, "no error"); - is(/overlap/i.test(caught.message), "wrong error"); -}); - -testCM("nestedFoldOnSide", function(cm) { - var m1 = cm.markText(Pos(0, 1), Pos(2, 1), {collapsed: true, inclusiveRight: true}); - var m2 = cm.markText(Pos(0, 1), Pos(0, 2), {collapsed: true}); - cm.markText(Pos(0, 1), Pos(0, 2), {collapsed: true}).clear(); - try { cm.markText(Pos(0, 1), Pos(0, 2), {collapsed: true, inclusiveLeft: true}); } - catch(e) { var caught = e; } - is(caught && /overlap/i.test(caught.message)); - var m3 = cm.markText(Pos(2, 0), Pos(2, 1), {collapsed: true}); - var m4 = cm.markText(Pos(2, 0), Pos(2, 1), {collapse: true, inclusiveRight: true}); - m1.clear(); m4.clear(); - m1 = cm.markText(Pos(0, 1), Pos(2, 1), {collapsed: true}); - cm.markText(Pos(2, 0), Pos(2, 1), {collapsed: true}).clear(); - try { cm.markText(Pos(2, 0), Pos(2, 1), {collapsed: true, inclusiveRight: true}); } - catch(e) { var caught = e; } - is(caught && /overlap/i.test(caught.message)); -}, {value: "ab\ncd\ef"}); - -testCM("editInFold", function(cm) { - addDoc(cm, 4, 6); - var m = cm.markText(Pos(1, 2), Pos(3, 2), {collapsed: true}); - cm.replaceRange("", Pos(0, 0), Pos(1, 3)); - cm.replaceRange("", Pos(2, 1), Pos(3, 3)); - cm.replaceRange("a\nb\nc\nd", Pos(0, 1), Pos(1, 0)); - cm.cursorCoords(Pos(0, 0)); -}); - -testCM("wrappingInlineWidget", function(cm) { - cm.setSize("11em"); - var w = document.createElement("span"); - w.style.color = "red"; - w.innerHTML = "one two three four"; - cm.markText(Pos(0, 6), Pos(0, 9), {replacedWith: w}); - var cur0 = cm.cursorCoords(Pos(0, 0)), cur1 = cm.cursorCoords(Pos(0, 10)); - is(cur0.top < cur1.top); - is(cur0.bottom < cur1.bottom); - var curL = cm.cursorCoords(Pos(0, 6)), curR = cm.cursorCoords(Pos(0, 9)); - eq(curL.top, cur0.top); - eq(curL.bottom, cur0.bottom); - eq(curR.top, cur1.top); - eq(curR.bottom, cur1.bottom); - cm.replaceRange("", Pos(0, 9), Pos(0)); - curR = cm.cursorCoords(Pos(0, 9)); - if (phantom) return; - eq(curR.top, cur1.top); - eq(curR.bottom, cur1.bottom); -}, {value: "1 2 3 xxx 4", lineWrapping: true}); - -testCM("showEmptyWidgetSpan", function(cm) { - var marker = cm.markText(Pos(0, 2), Pos(0, 2), { - clearWhenEmpty: false, - replacedWith: document.createTextNode("X") - }); - eq(cm.display.view[0].text.textContent, "abXc"); -}, {value: "abc"}); - -testCM("changedInlineWidget", function(cm) { - cm.setSize("10em"); - var w = document.createElement("span"); - w.innerHTML = "x"; - var m = cm.markText(Pos(0, 4), Pos(0, 5), {replacedWith: w}); - w.innerHTML = "and now the widget is really really long all of a sudden and a scrollbar is needed"; - m.changed(); - var hScroll = byClassName(cm.getWrapperElement(), "CodeMirror-hscrollbar")[0]; - is(hScroll.scrollWidth > hScroll.clientWidth); -}, {value: "hello there"}); - -testCM("changedBookmark", function(cm) { - cm.setSize("10em"); - var w = document.createElement("span"); - w.innerHTML = "x"; - var m = cm.setBookmark(Pos(0, 4), {widget: w}); - w.innerHTML = "and now the widget is really really long all of a sudden and a scrollbar is needed"; - m.changed(); - var hScroll = byClassName(cm.getWrapperElement(), "CodeMirror-hscrollbar")[0]; - is(hScroll.scrollWidth > hScroll.clientWidth); -}, {value: "abcdefg"}); - -testCM("inlineWidget", function(cm) { - var w = cm.setBookmark(Pos(0, 2), {widget: document.createTextNode("uu")}); - cm.setCursor(0, 2); - CodeMirror.commands.goLineDown(cm); - eqPos(cm.getCursor(), Pos(1, 4)); - cm.setCursor(0, 2); - cm.replaceSelection("hi"); - eqPos(w.find(), Pos(0, 2)); - cm.setCursor(0, 1); - cm.replaceSelection("ay"); - eqPos(w.find(), Pos(0, 4)); - eq(cm.getLine(0), "uayuhiuu"); -}, {value: "uuuu\nuuuuuu"}); - -testCM("wrappingAndResizing", function(cm) { - cm.setSize(null, "auto"); - cm.setOption("lineWrapping", true); - var wrap = cm.getWrapperElement(), h0 = wrap.offsetHeight; - var doc = "xxx xxx xxx xxx xxx"; - cm.setValue(doc); - for (var step = 10, w = cm.charCoords(Pos(0, 18), "div").right;; w += step) { - cm.setSize(w); - if (wrap.offsetHeight <= h0 * (opera_lt10 ? 1.2 : 1.5)) { - if (step == 10) { w -= 10; step = 1; } - else break; - } - } - // Ensure that putting the cursor at the end of the maximally long - // line doesn't cause wrapping to happen. - cm.setCursor(Pos(0, doc.length)); - eq(wrap.offsetHeight, h0); - cm.replaceSelection("x"); - is(wrap.offsetHeight > h0, "wrapping happens"); - // Now add a max-height and, in a document consisting of - // almost-wrapped lines, go over it so that a scrollbar appears. - cm.setValue(doc + "\n" + doc + "\n"); - cm.getScrollerElement().style.maxHeight = "100px"; - cm.replaceRange("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n!\n", Pos(2, 0)); - forEach([Pos(0, doc.length), Pos(0, doc.length - 1), - Pos(0, 0), Pos(1, doc.length), Pos(1, doc.length - 1)], - function(pos) { - var coords = cm.charCoords(pos); - eqPos(pos, cm.coordsChar({left: coords.left + 2, top: coords.top + 5})); - }); -}, null, ie_lt8); - -testCM("measureEndOfLine", function(cm) { - if (phantom) return; - cm.setSize(null, "auto"); - var inner = byClassName(cm.getWrapperElement(), "CodeMirror-lines")[0].firstChild; - var lh = inner.offsetHeight; - for (var step = 10, w = cm.charCoords(Pos(0, 7), "div").right;; w += step) { - cm.setSize(w); - if (inner.offsetHeight < 2.5 * lh) { - if (step == 10) { w -= 10; step = 1; } - else break; - } - } - cm.setValue(cm.getValue() + "\n\n"); - var endPos = cm.charCoords(Pos(0, 18), "local"); - is(endPos.top > lh * .8, "not at top"); - is(endPos.left > w - 20, "not at right"); - endPos = cm.charCoords(Pos(0, 18)); - eqPos(cm.coordsChar({left: endPos.left, top: endPos.top + 5}), Pos(0, 18)); -}, {mode: "text/html", value: "", lineWrapping: true}, ie_lt8 || opera_lt10); - -testCM("measureWrappedEndOfLine", function(cm) { - if (phantom) return; - cm.setSize(null, "auto"); - var inner = byClassName(cm.getWrapperElement(), "CodeMirror-lines")[0].firstChild; - var lh = inner.offsetHeight; - for (var step = 10, w = cm.charCoords(Pos(0, 7), "div").right;; w += step) { - cm.setSize(w); - if (inner.offsetHeight < 2.5 * lh) { - if (step == 10) { w -= 10; step = 1; } - else break; - } - } - var endPos = cm.charCoords(Pos(0, 12)); // Next-to-last since last would wrap (#1862) - endPos.left += w; // Add width of editor just to be sure that we are behind last character - eqPos(cm.coordsChar(endPos), Pos(0, 13)); -}, {mode: "text/html", value: "0123456789abcde0123456789", lineWrapping: true}, ie_lt8 || opera_lt10); - -testCM("scrollVerticallyAndHorizontally", function(cm) { - if (cm.getOption("inputStyle") != "textarea") return; - cm.setSize(100, 100); - addDoc(cm, 40, 40); - cm.setCursor(39); - var wrap = cm.getWrapperElement(), bar = byClassName(wrap, "CodeMirror-vscrollbar")[0]; - is(bar.offsetHeight < wrap.offsetHeight, "vertical scrollbar limited by horizontal one"); - var cursorBox = byClassName(wrap, "CodeMirror-cursor")[0].getBoundingClientRect(); - var editorBox = wrap.getBoundingClientRect(); - is(cursorBox.bottom < editorBox.top + cm.getScrollerElement().clientHeight, - "bottom line visible"); -}, {lineNumbers: true}); - -testCM("moveVstuck", function(cm) { - var lines = byClassName(cm.getWrapperElement(), "CodeMirror-lines")[0].firstChild, h0 = lines.offsetHeight; - var val = "fooooooooooooooooooooooooo baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar\n"; - cm.setValue(val); - for (var w = cm.charCoords(Pos(0, 26), "div").right * 2.8;; w += 5) { - cm.setSize(w); - if (lines.offsetHeight <= 3.5 * h0) break; - } - cm.setCursor(Pos(0, val.length - 1)); - cm.moveV(-1, "line"); - eqPos(cm.getCursor(), Pos(0, 26)); -}, {lineWrapping: true}, ie_lt8 || opera_lt10); - -testCM("collapseOnMove", function(cm) { - cm.setSelection(Pos(0, 1), Pos(2, 4)); - cm.execCommand("goLineUp"); - is(!cm.somethingSelected()); - eqPos(cm.getCursor(), Pos(0, 1)); - cm.setSelection(Pos(0, 1), Pos(2, 4)); - cm.execCommand("goPageDown"); - is(!cm.somethingSelected()); - eqPos(cm.getCursor(), Pos(2, 4)); - cm.execCommand("goLineUp"); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(0, 4)); - cm.setSelection(Pos(0, 1), Pos(2, 4)); - cm.execCommand("goCharLeft"); - is(!cm.somethingSelected()); - eqPos(cm.getCursor(), Pos(0, 1)); -}, {value: "aaaaa\nb\nccccc"}); - -testCM("clickTab", function(cm) { - var p0 = cm.charCoords(Pos(0, 0)); - eqPos(cm.coordsChar({left: p0.left + 5, top: p0.top + 5}), Pos(0, 0)); - eqPos(cm.coordsChar({left: p0.right - 5, top: p0.top + 5}), Pos(0, 1)); -}, {value: "\t\n\n", lineWrapping: true, tabSize: 8}); - -testCM("verticalScroll", function(cm) { - cm.setSize(100, 200); - cm.setValue("foo\nbar\nbaz\n"); - var sc = cm.getScrollerElement(), baseWidth = sc.scrollWidth; - cm.replaceRange("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah", Pos(0, 0), Pos(0)); - is(sc.scrollWidth > baseWidth, "scrollbar present"); - cm.replaceRange("foo", Pos(0, 0), Pos(0)); - if (!phantom) eq(sc.scrollWidth, baseWidth, "scrollbar gone"); - cm.replaceRange("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaah", Pos(0, 0), Pos(0)); - cm.replaceRange("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbh", Pos(1, 0), Pos(1)); - is(sc.scrollWidth > baseWidth, "present again"); - var curWidth = sc.scrollWidth; - cm.replaceRange("foo", Pos(0, 0), Pos(0)); - is(sc.scrollWidth < curWidth, "scrollbar smaller"); - is(sc.scrollWidth > baseWidth, "but still present"); -}); - -testCM("extraKeys", function(cm) { - var outcome; - function fakeKey(expected, code, props) { - if (typeof code == "string") code = code.charCodeAt(0); - var e = {type: "keydown", keyCode: code, preventDefault: function(){}, stopPropagation: function(){}}; - if (props) for (var n in props) e[n] = props[n]; - outcome = null; - cm.triggerOnKeyDown(e); - eq(outcome, expected); - } - CodeMirror.commands.testCommand = function() {outcome = "tc";}; - CodeMirror.commands.goTestCommand = function() {outcome = "gtc";}; - cm.setOption("extraKeys", {"Shift-X": function() {outcome = "sx";}, - "X": function() {outcome = "x";}, - "Ctrl-Alt-U": function() {outcome = "cau";}, - "End": "testCommand", - "Home": "goTestCommand", - "Tab": false}); - fakeKey(null, "U"); - fakeKey("cau", "U", {ctrlKey: true, altKey: true}); - fakeKey(null, "U", {shiftKey: true, ctrlKey: true, altKey: true}); - fakeKey("x", "X"); - fakeKey("sx", "X", {shiftKey: true}); - fakeKey("tc", 35); - fakeKey(null, 35, {shiftKey: true}); - fakeKey("gtc", 36); - fakeKey("gtc", 36, {shiftKey: true}); - fakeKey(null, 9); -}, null, window.opera && mac); - -testCM("wordMovementCommands", function(cm) { - cm.execCommand("goWordLeft"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); - eqPos(cm.getCursor(), Pos(0, 7)); - cm.execCommand("goWordLeft"); - eqPos(cm.getCursor(), Pos(0, 5)); - cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); - eqPos(cm.getCursor(), Pos(0, 12)); - cm.execCommand("goWordLeft"); - eqPos(cm.getCursor(), Pos(0, 9)); - cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); - eqPos(cm.getCursor(), Pos(0, 24)); - cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); - eqPos(cm.getCursor(), Pos(1, 9)); - cm.execCommand("goWordRight"); - eqPos(cm.getCursor(), Pos(1, 13)); - cm.execCommand("goWordRight"); cm.execCommand("goWordRight"); - eqPos(cm.getCursor(), Pos(2, 0)); -}, {value: "this is (the) firstline.\na foo12\u00e9\u00f8\u00d7bar\n"}); - -testCM("groupMovementCommands", function(cm) { - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(0, 4)); - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(0, 7)); - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(0, 10)); - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(0, 7)); - cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(0, 15)); - cm.setCursor(Pos(0, 17)); - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(0, 16)); - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(0, 14)); - cm.execCommand("goGroupRight"); cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(0, 20)); - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(1, 0)); - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(1, 2)); - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), Pos(1, 5)); - cm.execCommand("goGroupLeft"); cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(1, 0)); - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(0, 20)); - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), Pos(0, 16)); -}, {value: "booo ba---quux. ffff\n abc d"}); - -testCM("groupsAndWhitespace", function(cm) { - var positions = [Pos(0, 0), Pos(0, 2), Pos(0, 5), Pos(0, 9), Pos(0, 11), - Pos(1, 0), Pos(1, 2), Pos(1, 5)]; - for (var i = 1; i < positions.length; i++) { - cm.execCommand("goGroupRight"); - eqPos(cm.getCursor(), positions[i]); - } - for (var i = positions.length - 2; i >= 0; i--) { - cm.execCommand("goGroupLeft"); - eqPos(cm.getCursor(), i == 2 ? Pos(0, 6) : positions[i]); - } -}, {value: " foo +++ \n bar"}); - -testCM("charMovementCommands", function(cm) { - cm.execCommand("goCharLeft"); cm.execCommand("goColumnLeft"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("goCharRight"); cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(0, 2)); - cm.setCursor(Pos(1, 0)); - cm.execCommand("goColumnLeft"); - eqPos(cm.getCursor(), Pos(1, 0)); - cm.execCommand("goCharLeft"); - eqPos(cm.getCursor(), Pos(0, 5)); - cm.execCommand("goColumnRight"); - eqPos(cm.getCursor(), Pos(0, 5)); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(1, 0)); - cm.execCommand("goLineEnd"); - eqPos(cm.getCursor(), Pos(1, 5)); - cm.execCommand("goLineStartSmart"); - eqPos(cm.getCursor(), Pos(1, 1)); - cm.execCommand("goLineStartSmart"); - eqPos(cm.getCursor(), Pos(1, 0)); - cm.setCursor(Pos(2, 0)); - cm.execCommand("goCharRight"); cm.execCommand("goColumnRight"); - eqPos(cm.getCursor(), Pos(2, 0)); -}, {value: "line1\n ine2\n"}); - -testCM("verticalMovementCommands", function(cm) { - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("goLineDown"); - if (!phantom) // This fails in PhantomJS, though not in a real Webkit - eqPos(cm.getCursor(), Pos(1, 0)); - cm.setCursor(Pos(1, 12)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(2, 5)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(3, 0)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(2, 5)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(1, 12)); - cm.execCommand("goPageDown"); - eqPos(cm.getCursor(), Pos(5, 0)); - cm.execCommand("goPageDown"); cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(5, 0)); - cm.execCommand("goPageUp"); - eqPos(cm.getCursor(), Pos(0, 0)); -}, {value: "line1\nlong long line2\nline3\n\nline5\n"}); - -testCM("verticalMovementCommandsWrapping", function(cm) { - cm.setSize(120); - cm.setCursor(Pos(0, 5)); - cm.execCommand("goLineDown"); - eq(cm.getCursor().line, 0); - is(cm.getCursor().ch > 5, "moved beyond wrap"); - for (var i = 0; ; ++i) { - is(i < 20, "no endless loop"); - cm.execCommand("goLineDown"); - var cur = cm.getCursor(); - if (cur.line == 1) eq(cur.ch, 5); - if (cur.line == 2) { eq(cur.ch, 1); break; } - } -}, {value: "a very long line that wraps around somehow so that we can test cursor movement\nshortone\nk", - lineWrapping: true}); - -testCM("verticalMovementCommandsSingleLine", function(cm) { - cm.display.wrapper.style.height = "auto"; - cm.refresh(); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(0, 11)); - cm.setCursor(Pos(0, 5)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(0, 11)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(0, 11)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("goPageDown"); - eqPos(cm.getCursor(), Pos(0, 11)); - cm.execCommand("goPageDown"); cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(0, 11)); - cm.execCommand("goPageUp"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.setCursor(Pos(0, 5)); - cm.execCommand("goPageUp"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.setCursor(Pos(0, 5)); - cm.execCommand("goPageDown"); - eqPos(cm.getCursor(), Pos(0, 11)); -}, {value: "single line"}); - - -testCM("rtlMovement", function(cm) { - if (cm.getOption("inputStyle") != "textarea") return; - forEach(["خحج", "خحabcخحج", "abخحخحجcd", "abخde", "abخح2342خ1حج", "خ1ح2خح3حxج", - "خحcd", "1خحcd", "abcdeح1ج", "خمرحبها مها!", "foobarر", "خ ة ق", - "", "يتم السحب في 05 فبراير 2014"], function(line) { - var inv = line.charCodeAt(0) > 128; - cm.setValue(line + "\n"); cm.execCommand(inv ? "goLineEnd" : "goLineStart"); - var cursors = byClassName(cm.getWrapperElement(), "CodeMirror-cursors")[0]; - var cursor = cursors.firstChild; - var prevX = cursor.offsetLeft, prevY = cursor.offsetTop; - for (var i = 0; i <= line.length; ++i) { - cm.execCommand("goCharRight"); - cursor = cursors.firstChild; - if (i == line.length) is(cursor.offsetTop > prevY, "next line"); - else is(cursor.offsetLeft > prevX, "moved right"); - prevX = cursor.offsetLeft; prevY = cursor.offsetTop; - } - cm.setCursor(0, 0); cm.execCommand(inv ? "goLineStart" : "goLineEnd"); - prevX = cursors.firstChild.offsetLeft; - for (var i = 0; i < line.length; ++i) { - cm.execCommand("goCharLeft"); - cursor = cursors.firstChild; - is(cursor.offsetLeft < prevX, "moved left"); - prevX = cursor.offsetLeft; - } - }); -}, null, ie_lt9); - -// Verify that updating a line clears its bidi ordering -testCM("bidiUpdate", function(cm) { - cm.setCursor(Pos(0, 2)); - cm.replaceSelection("خحج", "start"); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(0, 4)); -}, {value: "abcd\n"}); - -testCM("movebyTextUnit", function(cm) { - cm.setValue("בְּרֵאשִ\nééé́\n"); - cm.execCommand("goLineEnd"); - for (var i = 0; i < 4; ++i) cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(0, 0)); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(1, 0)); - cm.execCommand("goCharRight"); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(1, 4)); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(1, 7)); -}); - -testCM("lineChangeEvents", function(cm) { - addDoc(cm, 3, 5); - var log = [], want = ["ch 0", "ch 1", "del 2", "ch 0", "ch 0", "del 1", "del 3", "del 4"]; - for (var i = 0; i < 5; ++i) { - CodeMirror.on(cm.getLineHandle(i), "delete", function(i) { - return function() {log.push("del " + i);}; - }(i)); - CodeMirror.on(cm.getLineHandle(i), "change", function(i) { - return function() {log.push("ch " + i);}; - }(i)); - } - cm.replaceRange("x", Pos(0, 1)); - cm.replaceRange("xy", Pos(1, 1), Pos(2)); - cm.replaceRange("foo\nbar", Pos(0, 1)); - cm.replaceRange("", Pos(0, 0), Pos(cm.lineCount())); - eq(log.length, want.length, "same length"); - for (var i = 0; i < log.length; ++i) - eq(log[i], want[i]); -}); - -testCM("scrollEntirelyToRight", function(cm) { - if (phantom || cm.getOption("inputStyle") != "textarea") return; - addDoc(cm, 500, 2); - cm.setCursor(Pos(0, 500)); - var wrap = cm.getWrapperElement(), cur = byClassName(wrap, "CodeMirror-cursor")[0]; - is(wrap.getBoundingClientRect().right > cur.getBoundingClientRect().left); -}); - -testCM("lineWidgets", function(cm) { - addDoc(cm, 500, 3); - var last = cm.charCoords(Pos(2, 0)); - var node = document.createElement("div"); - node.innerHTML = "hi"; - var widget = cm.addLineWidget(1, node); - is(last.top < cm.charCoords(Pos(2, 0)).top, "took up space"); - cm.setCursor(Pos(1, 1)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(2, 1)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(1, 1)); -}); - -testCM("lineWidgetFocus", function(cm) { - var place = document.getElementById("testground"); - place.className = "offscreen"; - try { - addDoc(cm, 500, 10); - var node = document.createElement("input"); - var widget = cm.addLineWidget(1, node); - node.focus(); - eq(document.activeElement, node); - cm.replaceRange("new stuff", Pos(1, 0)); - eq(document.activeElement, node); - } finally { - place.className = ""; - } -}); - -testCM("lineWidgetCautiousRedraw", function(cm) { - var node = document.createElement("div"); - node.innerHTML = "hahah"; - var w = cm.addLineWidget(0, node); - var redrawn = false; - w.on("redraw", function() { redrawn = true; }); - cm.replaceSelection("0"); - is(!redrawn); -}, {value: "123\n456"}); - - -var knownScrollbarWidth; -function scrollbarWidth(measure) { - if (knownScrollbarWidth != null) return knownScrollbarWidth; - var div = document.createElement('div'); - div.style.cssText = "width: 50px; height: 50px; overflow-x: scroll"; - document.body.appendChild(div); - knownScrollbarWidth = div.offsetHeight - div.clientHeight; - document.body.removeChild(div); - return knownScrollbarWidth || 0; -} - -testCM("lineWidgetChanged", function(cm) { - addDoc(cm, 2, 300); - var halfScrollbarWidth = scrollbarWidth(cm.display.measure)/2; - cm.setOption('lineNumbers', true); - cm.setSize(600, cm.defaultTextHeight() * 50); - cm.scrollTo(null, cm.heightAtLine(125, "local")); - - var expectedWidgetHeight = 60; - var expectedLinesInWidget = 3; - function w() { - var node = document.createElement("div"); - // we use these children with just under half width of the line to check measurements are made with correct width - // when placed in the measure div. - // If the widget is measured at a width much narrower than it is displayed at, the underHalf children will span two lines and break the test. - // If the widget is measured at a width much wider than it is displayed at, the overHalf children will combine and break the test. - // Note that this test only checks widgets where coverGutter is true, because these require extra styling to get the width right. - // It may also be worthwhile to check this for non-coverGutter widgets. - // Visually: - // Good: - // | ------------- display width ------------- | - // | ------- widget-width when measured ------ | - // | | -- under-half -- | | -- under-half -- | | - // | | --- over-half --- | | - // | | --- over-half --- | | - // Height: measured as 3 lines, same as it will be when actually displayed - - // Bad (too narrow): - // | ------------- display width ------------- | - // | ------ widget-width when measured ----- | < -- uh oh - // | | -- under-half -- | | - // | | -- under-half -- | | < -- when measured, shoved to next line - // | | --- over-half --- | | - // | | --- over-half --- | | - // Height: measured as 4 lines, more than expected . Will be displayed as 3 lines! - - // Bad (too wide): - // | ------------- display width ------------- | - // | -------- widget-width when measured ------- | < -- uh oh - // | | -- under-half -- | | -- under-half -- | | - // | | --- over-half --- | | --- over-half --- | | < -- when measured, combined on one line - // Height: measured as 2 lines, less than expected. Will be displayed as 3 lines! - - var barelyUnderHalfWidthHtml = '
    '; - var barelyOverHalfWidthHtml = '
    '; - node.innerHTML = new Array(3).join(barelyUnderHalfWidthHtml) + new Array(3).join(barelyOverHalfWidthHtml); - node.style.cssText = "background: yellow;font-size:0;line-height: " + (expectedWidgetHeight/expectedLinesInWidget) + "px;"; - return node; - } - var info0 = cm.getScrollInfo(); - var w0 = cm.addLineWidget(0, w(), { coverGutter: true }); - var w150 = cm.addLineWidget(150, w(), { coverGutter: true }); - var w300 = cm.addLineWidget(300, w(), { coverGutter: true }); - var info1 = cm.getScrollInfo(); - eq(info0.height + (3 * expectedWidgetHeight), info1.height); - eq(info0.top + expectedWidgetHeight, info1.top); - expectedWidgetHeight = 12; - w0.node.style.lineHeight = w150.node.style.lineHeight = w300.node.style.lineHeight = (expectedWidgetHeight/expectedLinesInWidget) + "px"; - w0.changed(); w150.changed(); w300.changed(); - var info2 = cm.getScrollInfo(); - eq(info0.height + (3 * expectedWidgetHeight), info2.height); - eq(info0.top + expectedWidgetHeight, info2.top); -}); - -testCM("getLineNumber", function(cm) { - addDoc(cm, 2, 20); - var h1 = cm.getLineHandle(1); - eq(cm.getLineNumber(h1), 1); - cm.replaceRange("hi\nbye\n", Pos(0, 0)); - eq(cm.getLineNumber(h1), 3); - cm.setValue(""); - eq(cm.getLineNumber(h1), null); -}); - -testCM("jumpTheGap", function(cm) { - if (phantom) return; - var longLine = "abcdef ghiklmnop qrstuvw xyz "; - longLine += longLine; longLine += longLine; longLine += longLine; - cm.replaceRange(longLine, Pos(2, 0), Pos(2)); - cm.setSize("200px", null); - cm.getWrapperElement().style.lineHeight = 2; - cm.refresh(); - cm.setCursor(Pos(0, 1)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(1, 1)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(2, 1)); - cm.execCommand("goLineDown"); - eq(cm.getCursor().line, 2); - is(cm.getCursor().ch > 1); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(2, 1)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(1, 1)); - var node = document.createElement("div"); - node.innerHTML = "hi"; node.style.height = "30px"; - cm.addLineWidget(0, node); - cm.addLineWidget(1, node.cloneNode(true), {above: true}); - cm.setCursor(Pos(0, 2)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(1, 2)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(0, 2)); -}, {lineWrapping: true, value: "abc\ndef\nghi\njkl\n"}); - -testCM("addLineClass", function(cm) { - function cls(line, text, bg, wrap, gutter) { - var i = cm.lineInfo(line); - eq(i.textClass, text); - eq(i.bgClass, bg); - eq(i.wrapClass, wrap); - if (typeof i.handle.gutterClass !== 'undefined') { - eq(i.handle.gutterClass, gutter); - } - } - cm.addLineClass(0, "text", "foo"); - cm.addLineClass(0, "text", "bar"); - cm.addLineClass(1, "background", "baz"); - cm.addLineClass(1, "wrap", "foo"); - cm.addLineClass(1, "gutter", "gutter-class"); - cls(0, "foo bar", null, null, null); - cls(1, null, "baz", "foo", "gutter-class"); - var lines = cm.display.lineDiv; - eq(byClassName(lines, "foo").length, 2); - eq(byClassName(lines, "bar").length, 1); - eq(byClassName(lines, "baz").length, 1); - eq(byClassName(lines, "gutter-class").length, 2); // Gutter classes are reflected in 2 nodes - cm.removeLineClass(0, "text", "foo"); - cls(0, "bar", null, null, null); - cm.removeLineClass(0, "text", "foo"); - cls(0, "bar", null, null, null); - cm.removeLineClass(0, "text", "bar"); - cls(0, null, null, null); - - cm.addLineClass(1, "wrap", "quux"); - cls(1, null, "baz", "foo quux", "gutter-class"); - cm.removeLineClass(1, "wrap"); - cls(1, null, "baz", null, "gutter-class"); - cm.removeLineClass(1, "gutter", "gutter-class"); - eq(byClassName(lines, "gutter-class").length, 0); - cls(1, null, "baz", null, null); - - cm.addLineClass(1, "gutter", "gutter-class"); - cls(1, null, "baz", null, "gutter-class"); - cm.removeLineClass(1, "gutter", "gutter-class"); - cls(1, null, "baz", null, null); - -}, {value: "hohoho\n", lineNumbers: true}); - -testCM("atomicMarker", function(cm) { - addDoc(cm, 10, 10); - function atom(ll, cl, lr, cr, li, ri) { - return cm.markText(Pos(ll, cl), Pos(lr, cr), - {atomic: true, inclusiveLeft: li, inclusiveRight: ri}); - } - var m = atom(0, 1, 0, 5); - cm.setCursor(Pos(0, 1)); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(0, 5)); - cm.execCommand("goCharLeft"); - eqPos(cm.getCursor(), Pos(0, 1)); - m.clear(); - m = atom(0, 0, 0, 5, true); - eqPos(cm.getCursor(), Pos(0, 5), "pushed out"); - cm.execCommand("goCharLeft"); - eqPos(cm.getCursor(), Pos(0, 5)); - m.clear(); - m = atom(8, 4, 9, 10, false, true); - cm.setCursor(Pos(9, 8)); - eqPos(cm.getCursor(), Pos(8, 4), "set"); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(8, 4), "char right"); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(8, 4), "line down"); - cm.execCommand("goCharLeft"); - eqPos(cm.getCursor(), Pos(8, 3)); - m.clear(); - m = atom(1, 1, 3, 8); - cm.setCursor(Pos(0, 0)); - cm.setCursor(Pos(2, 0)); - eqPos(cm.getCursor(), Pos(3, 8)); - cm.execCommand("goCharLeft"); - eqPos(cm.getCursor(), Pos(1, 1)); - cm.execCommand("goCharRight"); - eqPos(cm.getCursor(), Pos(3, 8)); - cm.execCommand("goLineUp"); - eqPos(cm.getCursor(), Pos(1, 1)); - cm.execCommand("goLineDown"); - eqPos(cm.getCursor(), Pos(3, 8)); - cm.execCommand("delCharBefore"); - eq(cm.getValue().length, 80, "del chunk"); - m = atom(3, 0, 5, 5); - cm.setCursor(Pos(3, 0)); - cm.execCommand("delWordAfter"); - eq(cm.getValue().length, 53, "del chunk"); -}); - -testCM("selectionBias", function(cm) { - cm.markText(Pos(0, 1), Pos(0, 3), {atomic: true}); - cm.setCursor(Pos(0, 2)); - eqPos(cm.getCursor(), Pos(0, 1)); - cm.setCursor(Pos(0, 2)); - eqPos(cm.getCursor(), Pos(0, 3)); - cm.setCursor(Pos(0, 2)); - eqPos(cm.getCursor(), Pos(0, 1)); - cm.setCursor(Pos(0, 2), null, {bias: -1}); - eqPos(cm.getCursor(), Pos(0, 1)); - cm.setCursor(Pos(0, 4)); - cm.setCursor(Pos(0, 2), null, {bias: 1}); - eqPos(cm.getCursor(), Pos(0, 3)); -}, {value: "12345"}); - -testCM("selectionHomeEnd", function(cm) { - cm.markText(Pos(1, 0), Pos(1, 1), {atomic: true, inclusiveLeft: true}); - cm.markText(Pos(1, 3), Pos(1, 4), {atomic: true, inclusiveRight: true}); - cm.setCursor(Pos(1, 2)); - cm.execCommand("goLineStart"); - eqPos(cm.getCursor(), Pos(1, 1)); - cm.execCommand("goLineEnd"); - eqPos(cm.getCursor(), Pos(1, 3)); -}, {value: "ab\ncdef\ngh"}); - -testCM("readOnlyMarker", function(cm) { - function mark(ll, cl, lr, cr, at) { - return cm.markText(Pos(ll, cl), Pos(lr, cr), - {readOnly: true, atomic: at}); - } - var m = mark(0, 1, 0, 4); - cm.setCursor(Pos(0, 2)); - cm.replaceSelection("hi", "end"); - eqPos(cm.getCursor(), Pos(0, 2)); - eq(cm.getLine(0), "abcde"); - cm.execCommand("selectAll"); - cm.replaceSelection("oops", "around"); - eq(cm.getValue(), "oopsbcd"); - cm.undo(); - eqPos(m.find().from, Pos(0, 1)); - eqPos(m.find().to, Pos(0, 4)); - m.clear(); - cm.setCursor(Pos(0, 2)); - cm.replaceSelection("hi", "around"); - eq(cm.getLine(0), "abhicde"); - eqPos(cm.getCursor(), Pos(0, 4)); - m = mark(0, 2, 2, 2, true); - cm.setSelection(Pos(1, 1), Pos(2, 4)); - cm.replaceSelection("t", "end"); - eqPos(cm.getCursor(), Pos(2, 3)); - eq(cm.getLine(2), "klto"); - cm.execCommand("goCharLeft"); - cm.execCommand("goCharLeft"); - eqPos(cm.getCursor(), Pos(0, 2)); - cm.setSelection(Pos(0, 1), Pos(0, 3)); - cm.replaceSelection("xx", "around"); - eqPos(cm.getCursor(), Pos(0, 3)); - eq(cm.getLine(0), "axxhicde"); -}, {value: "abcde\nfghij\nklmno\n"}); - -testCM("dirtyBit", function(cm) { - eq(cm.isClean(), true); - cm.replaceSelection("boo", null, "test"); - eq(cm.isClean(), false); - cm.undo(); - eq(cm.isClean(), true); - cm.replaceSelection("boo", null, "test"); - cm.replaceSelection("baz", null, "test"); - cm.undo(); - eq(cm.isClean(), false); - cm.markClean(); - eq(cm.isClean(), true); - cm.undo(); - eq(cm.isClean(), false); - cm.redo(); - eq(cm.isClean(), true); -}); - -testCM("changeGeneration", function(cm) { - cm.replaceSelection("x"); - var softGen = cm.changeGeneration(); - cm.replaceSelection("x"); - cm.undo(); - eq(cm.getValue(), ""); - is(!cm.isClean(softGen)); - cm.replaceSelection("x"); - var hardGen = cm.changeGeneration(true); - cm.replaceSelection("x"); - cm.undo(); - eq(cm.getValue(), "x"); - is(cm.isClean(hardGen)); -}); - -testCM("addKeyMap", function(cm) { - function sendKey(code) { - cm.triggerOnKeyDown({type: "keydown", keyCode: code, - preventDefault: function(){}, stopPropagation: function(){}}); - } - - sendKey(39); - eqPos(cm.getCursor(), Pos(0, 1)); - var test = 0; - var map1 = {Right: function() { ++test; }}, map2 = {Right: function() { test += 10; }} - cm.addKeyMap(map1); - sendKey(39); - eqPos(cm.getCursor(), Pos(0, 1)); - eq(test, 1); - cm.addKeyMap(map2, true); - sendKey(39); - eq(test, 2); - cm.removeKeyMap(map1); - sendKey(39); - eq(test, 12); - cm.removeKeyMap(map2); - sendKey(39); - eq(test, 12); - eqPos(cm.getCursor(), Pos(0, 2)); - cm.addKeyMap({Right: function() { test = 55; }, name: "mymap"}); - sendKey(39); - eq(test, 55); - cm.removeKeyMap("mymap"); - sendKey(39); - eqPos(cm.getCursor(), Pos(0, 3)); -}, {value: "abc"}); - -testCM("findPosH", function(cm) { - forEach([{from: Pos(0, 0), to: Pos(0, 1), by: 1}, - {from: Pos(0, 0), to: Pos(0, 0), by: -1, hitSide: true}, - {from: Pos(0, 0), to: Pos(0, 4), by: 1, unit: "word"}, - {from: Pos(0, 0), to: Pos(0, 8), by: 2, unit: "word"}, - {from: Pos(0, 0), to: Pos(2, 0), by: 20, unit: "word", hitSide: true}, - {from: Pos(0, 7), to: Pos(0, 5), by: -1, unit: "word"}, - {from: Pos(0, 4), to: Pos(0, 8), by: 1, unit: "word"}, - {from: Pos(1, 0), to: Pos(1, 18), by: 3, unit: "word"}, - {from: Pos(1, 22), to: Pos(1, 5), by: -3, unit: "word"}, - {from: Pos(1, 15), to: Pos(1, 10), by: -5}, - {from: Pos(1, 15), to: Pos(1, 10), by: -5, unit: "column"}, - {from: Pos(1, 15), to: Pos(1, 0), by: -50, unit: "column", hitSide: true}, - {from: Pos(1, 15), to: Pos(1, 24), by: 50, unit: "column", hitSide: true}, - {from: Pos(1, 15), to: Pos(2, 0), by: 50, hitSide: true}], function(t) { - var r = cm.findPosH(t.from, t.by, t.unit || "char"); - eqPos(r, t.to); - eq(!!r.hitSide, !!t.hitSide); - }); -}, {value: "line one\nline two.something.other\n"}); - -testCM("beforeChange", function(cm) { - cm.on("beforeChange", function(cm, change) { - var text = []; - for (var i = 0; i < change.text.length; ++i) - text.push(change.text[i].replace(/\s/g, "_")); - change.update(null, null, text); - }); - cm.setValue("hello, i am a\nnew document\n"); - eq(cm.getValue(), "hello,_i_am_a\nnew_document\n"); - CodeMirror.on(cm.getDoc(), "beforeChange", function(doc, change) { - if (change.from.line == 0) change.cancel(); - }); - cm.setValue("oops"); // Canceled - eq(cm.getValue(), "hello,_i_am_a\nnew_document\n"); - cm.replaceRange("hey hey hey", Pos(1, 0), Pos(2, 0)); - eq(cm.getValue(), "hello,_i_am_a\nhey_hey_hey"); -}, {value: "abcdefghijk"}); - -testCM("beforeChangeUndo", function(cm) { - cm.replaceRange("hi", Pos(0, 0), Pos(0)); - cm.replaceRange("bye", Pos(0, 0), Pos(0)); - eq(cm.historySize().undo, 2); - cm.on("beforeChange", function(cm, change) { - is(!change.update); - change.cancel(); - }); - cm.undo(); - eq(cm.historySize().undo, 0); - eq(cm.getValue(), "bye\ntwo"); -}, {value: "one\ntwo"}); - -testCM("beforeSelectionChange", function(cm) { - function notAtEnd(cm, pos) { - var len = cm.getLine(pos.line).length; - if (!len || pos.ch == len) return Pos(pos.line, pos.ch - 1); - return pos; - } - cm.on("beforeSelectionChange", function(cm, obj) { - obj.update([{anchor: notAtEnd(cm, obj.ranges[0].anchor), - head: notAtEnd(cm, obj.ranges[0].head)}]); - }); - - addDoc(cm, 10, 10); - cm.execCommand("goLineEnd"); - eqPos(cm.getCursor(), Pos(0, 9)); - cm.execCommand("selectAll"); - eqPos(cm.getCursor("start"), Pos(0, 0)); - eqPos(cm.getCursor("end"), Pos(9, 9)); -}); - -testCM("change_removedText", function(cm) { - cm.setValue("abc\ndef"); - - var removedText = []; - cm.on("change", function(cm, change) { - removedText.push(change.removed); - }); - - cm.operation(function() { - cm.replaceRange("xyz", Pos(0, 0), Pos(1,1)); - cm.replaceRange("123", Pos(0,0)); - }); - - eq(removedText.length, 2); - eq(removedText[0].join("\n"), "abc\nd"); - eq(removedText[1].join("\n"), ""); - - var removedText = []; - cm.undo(); - eq(removedText.length, 2); - eq(removedText[0].join("\n"), "123"); - eq(removedText[1].join("\n"), "xyz"); - - var removedText = []; - cm.redo(); - eq(removedText.length, 2); - eq(removedText[0].join("\n"), "abc\nd"); - eq(removedText[1].join("\n"), ""); -}); - -testCM("lineStyleFromMode", function(cm) { - CodeMirror.defineMode("test_mode", function() { - return {token: function(stream) { - if (stream.match(/^\[[^\]]*\]/)) return " line-brackets "; - if (stream.match(/^\([^\)]*\)/)) return " line-background-parens "; - if (stream.match(/^<[^>]*>/)) return " span line-line line-background-bg "; - stream.match(/^\s+|^\S+/); - }}; - }); - cm.setOption("mode", "test_mode"); - var bracketElts = byClassName(cm.getWrapperElement(), "brackets"); - eq(bracketElts.length, 1, "brackets count"); - eq(bracketElts[0].nodeName, "PRE"); - is(!/brackets.*brackets/.test(bracketElts[0].className)); - var parenElts = byClassName(cm.getWrapperElement(), "parens"); - eq(parenElts.length, 1, "parens count"); - eq(parenElts[0].nodeName, "DIV"); - is(!/parens.*parens/.test(parenElts[0].className)); - eq(parenElts[0].parentElement.nodeName, "DIV"); - - eq(byClassName(cm.getWrapperElement(), "bg").length, 1); - eq(byClassName(cm.getWrapperElement(), "line").length, 1); - var spanElts = byClassName(cm.getWrapperElement(), "cm-span"); - eq(spanElts.length, 2); - is(/^\s*cm-span\s*$/.test(spanElts[0].className)); -}, {value: "line1: [br] [br]\nline2: (par) (par)\nline3: "}); - -testCM("lineStyleFromBlankLine", function(cm) { - CodeMirror.defineMode("lineStyleFromBlankLine_mode", function() { - return {token: function(stream) { stream.skipToEnd(); return "comment"; }, - blankLine: function() { return "line-blank"; }}; - }); - cm.setOption("mode", "lineStyleFromBlankLine_mode"); - var blankElts = byClassName(cm.getWrapperElement(), "blank"); - eq(blankElts.length, 1); - eq(blankElts[0].nodeName, "PRE"); - cm.replaceRange("x", Pos(1, 0)); - blankElts = byClassName(cm.getWrapperElement(), "blank"); - eq(blankElts.length, 0); -}, {value: "foo\n\nbar"}); - -CodeMirror.registerHelper("xxx", "a", "A"); -CodeMirror.registerHelper("xxx", "b", "B"); -CodeMirror.defineMode("yyy", function() { - return { - token: function(stream) { stream.skipToEnd(); }, - xxx: ["a", "b", "q"] - }; -}); -CodeMirror.registerGlobalHelper("xxx", "c", function(m) { return m.enableC; }, "C"); - -testCM("helpers", function(cm) { - cm.setOption("mode", "yyy"); - eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), "A/B"); - cm.setOption("mode", {name: "yyy", modeProps: {xxx: "b", enableC: true}}); - eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), "B/C"); - cm.setOption("mode", "javascript"); - eq(cm.getHelpers(Pos(0, 0), "xxx").join("/"), ""); -}); - -testCM("selectionHistory", function(cm) { - for (var i = 0; i < 3; i++) { - cm.setExtending(true); - cm.execCommand("goCharRight"); - cm.setExtending(false); - cm.execCommand("goCharRight"); - cm.execCommand("goCharRight"); - } - cm.execCommand("undoSelection"); - eq(cm.getSelection(), "c"); - cm.execCommand("undoSelection"); - eq(cm.getSelection(), ""); - eqPos(cm.getCursor(), Pos(0, 4)); - cm.execCommand("undoSelection"); - eq(cm.getSelection(), "b"); - cm.execCommand("redoSelection"); - eq(cm.getSelection(), ""); - eqPos(cm.getCursor(), Pos(0, 4)); - cm.execCommand("redoSelection"); - eq(cm.getSelection(), "c"); - cm.execCommand("redoSelection"); - eq(cm.getSelection(), ""); - eqPos(cm.getCursor(), Pos(0, 6)); -}, {value: "a b c d"}); - -testCM("selectionChangeReducesRedo", function(cm) { - cm.replaceSelection("X"); - cm.execCommand("goCharRight"); - cm.undoSelection(); - cm.execCommand("selectAll"); - cm.undoSelection(); - eq(cm.getValue(), "Xabc"); - eqPos(cm.getCursor(), Pos(0, 1)); - cm.undoSelection(); - eq(cm.getValue(), "abc"); -}, {value: "abc"}); - -testCM("selectionHistoryNonOverlapping", function(cm) { - cm.setSelection(Pos(0, 0), Pos(0, 1)); - cm.setSelection(Pos(0, 2), Pos(0, 3)); - cm.execCommand("undoSelection"); - eqPos(cm.getCursor("anchor"), Pos(0, 0)); - eqPos(cm.getCursor("head"), Pos(0, 1)); -}, {value: "1234"}); - -testCM("cursorMotionSplitsHistory", function(cm) { - cm.replaceSelection("a"); - cm.execCommand("goCharRight"); - cm.replaceSelection("b"); - cm.replaceSelection("c"); - cm.undo(); - eq(cm.getValue(), "a1234"); - eqPos(cm.getCursor(), Pos(0, 2)); - cm.undo(); - eq(cm.getValue(), "1234"); - eqPos(cm.getCursor(), Pos(0, 0)); -}, {value: "1234"}); - -testCM("selChangeInOperationDoesNotSplit", function(cm) { - for (var i = 0; i < 4; i++) { - cm.operation(function() { - cm.replaceSelection("x"); - cm.setCursor(Pos(0, cm.getCursor().ch - 1)); - }); - } - eqPos(cm.getCursor(), Pos(0, 0)); - eq(cm.getValue(), "xxxxa"); - cm.undo(); - eq(cm.getValue(), "a"); -}, {value: "a"}); - -testCM("alwaysMergeSelEventWithChangeOrigin", function(cm) { - cm.replaceSelection("U", null, "foo"); - cm.setSelection(Pos(0, 0), Pos(0, 1), {origin: "foo"}); - cm.undoSelection(); - eq(cm.getValue(), "a"); - cm.replaceSelection("V", null, "foo"); - cm.setSelection(Pos(0, 0), Pos(0, 1), {origin: "bar"}); - cm.undoSelection(); - eq(cm.getValue(), "Va"); -}, {value: "a"}); - -testCM("getTokenAt", function(cm) { - var tokPlus = cm.getTokenAt(Pos(0, 2)); - eq(tokPlus.type, "operator"); - eq(tokPlus.string, "+"); - var toks = cm.getLineTokens(0); - eq(toks.length, 3); - forEach([["number", "1"], ["operator", "+"], ["number", "2"]], function(expect, i) { - eq(toks[i].type, expect[0]); - eq(toks[i].string, expect[1]); - }); -}, {value: "1+2", mode: "javascript"}); - -testCM("getTokenTypeAt", function(cm) { - eq(cm.getTokenTypeAt(Pos(0, 0)), "number"); - eq(cm.getTokenTypeAt(Pos(0, 6)), "string"); - cm.addOverlay({ - token: function(stream) { - if (stream.match("foo")) return "foo"; - else stream.next(); - } - }); - eq(byClassName(cm.getWrapperElement(), "cm-foo").length, 1); - eq(cm.getTokenTypeAt(Pos(0, 6)), "string"); -}, {value: "1 + 'foo'", mode: "javascript"}); - -testCM("resizeLineWidget", function(cm) { - addDoc(cm, 200, 3); - var widget = document.createElement("pre"); - widget.innerHTML = "imwidget"; - widget.style.background = "yellow"; - cm.addLineWidget(1, widget, {noHScroll: true}); - cm.setSize(40); - is(widget.parentNode.offsetWidth < 42); -}); - -testCM("combinedOperations", function(cm) { - var place = document.getElementById("testground"); - var other = CodeMirror(place, {value: "123"}); - try { - cm.operation(function() { - cm.addLineClass(0, "wrap", "foo"); - other.addLineClass(0, "wrap", "foo"); - }); - eq(byClassName(cm.getWrapperElement(), "foo").length, 1); - eq(byClassName(other.getWrapperElement(), "foo").length, 1); - cm.operation(function() { - cm.removeLineClass(0, "wrap", "foo"); - other.removeLineClass(0, "wrap", "foo"); - }); - eq(byClassName(cm.getWrapperElement(), "foo").length, 0); - eq(byClassName(other.getWrapperElement(), "foo").length, 0); - } finally { - place.removeChild(other.getWrapperElement()); - } -}, {value: "abc"}); - -testCM("eventOrder", function(cm) { - var seen = []; - cm.on("change", function() { - if (!seen.length) cm.replaceSelection("."); - seen.push("change"); - }); - cm.on("cursorActivity", function() { - cm.replaceSelection("!"); - seen.push("activity"); - }); - cm.replaceSelection("/"); - eq(seen.join(","), "change,change,activity,change"); -}); - -testCM("splitSpaces_nonspecial", function(cm) { - eq(byClassName(cm.getWrapperElement(), "cm-invalidchar").length, 0); -}, { - specialChars: /[\u00a0]/, - value: "spaces -> <- between" -}); - -test("core_rmClass", function() { - var node = document.createElement("div"); - node.className = "foo-bar baz-quux yadda"; - CodeMirror.rmClass(node, "quux"); - eq(node.className, "foo-bar baz-quux yadda"); - CodeMirror.rmClass(node, "baz-quux"); - eq(node.className, "foo-bar yadda"); - CodeMirror.rmClass(node, "yadda"); - eq(node.className, "foo-bar"); - CodeMirror.rmClass(node, "foo-bar"); - eq(node.className, ""); - node.className = " foo "; - CodeMirror.rmClass(node, "foo"); - eq(node.className, ""); -}); - -test("core_addClass", function() { - var node = document.createElement("div"); - CodeMirror.addClass(node, "a"); - eq(node.className, "a"); - CodeMirror.addClass(node, "a"); - eq(node.className, "a"); - CodeMirror.addClass(node, "b"); - eq(node.className, "a b"); - CodeMirror.addClass(node, "a"); - CodeMirror.addClass(node, "b"); - eq(node.className, "a b"); -}); - -testCM("lineSeparator", function(cm) { - eq(cm.lineCount(), 3); - eq(cm.getLine(1), "bar\r"); - eq(cm.getLine(2), "baz\rquux"); - cm.setOption("lineSeparator", "\r"); - eq(cm.lineCount(), 5); - eq(cm.getLine(4), "quux"); - eq(cm.getValue(), "foo\rbar\r\rbaz\rquux"); - eq(cm.getValue("\n"), "foo\nbar\n\nbaz\nquux"); - cm.setOption("lineSeparator", null); - cm.setValue("foo\nbar\r\nbaz\rquux"); - eq(cm.lineCount(), 4); -}, {value: "foo\nbar\r\nbaz\rquux", - lineSeparator: "\n"}); diff --git a/backend/_pv_1_3_5/static/codemirror/test/vim_test.js b/backend/_pv_1_3_5/static/codemirror/test/vim_test.js deleted file mode 100755 index 703a07a77..000000000 --- a/backend/_pv_1_3_5/static/codemirror/test/vim_test.js +++ /dev/null @@ -1,4073 +0,0 @@ -CodeMirror.Vim.suppressErrorLogging = true; - -var code = '' + -' wOrd1 (#%\n' + -' word3] \n' + -'aopop pop 0 1 2 3 4\n' + -' (a) [b] {c} \n' + -'int getchar(void) {\n' + -' static char buf[BUFSIZ];\n' + -' static char *bufp = buf;\n' + -' if (n == 0) { /* buffer is empty */\n' + -' n = read(0, buf, sizeof buf);\n' + -' bufp = buf;\n' + -' }\n' + -'\n' + -' return (--n >= 0) ? (unsigned char) *bufp++ : EOF;\n' + -' \n' + -'}\n'; - -var lines = (function() { - lineText = code.split('\n'); - var ret = []; - for (var i = 0; i < lineText.length; i++) { - ret[i] = { - line: i, - length: lineText[i].length, - lineText: lineText[i], - textStart: /^\s*/.exec(lineText[i])[0].length - }; - } - return ret; -})(); -var endOfDocument = makeCursor(lines.length - 1, - lines[lines.length - 1].length); -var wordLine = lines[0]; -var bigWordLine = lines[1]; -var charLine = lines[2]; -var bracesLine = lines[3]; -var seekBraceLine = lines[4]; - -var word1 = { - start: { line: wordLine.line, ch: 1 }, - end: { line: wordLine.line, ch: 5 } -}; -var word2 = { - start: { line: wordLine.line, ch: word1.end.ch + 2 }, - end: { line: wordLine.line, ch: word1.end.ch + 4 } -}; -var word3 = { - start: { line: bigWordLine.line, ch: 1 }, - end: { line: bigWordLine.line, ch: 5 } -}; -var bigWord1 = word1; -var bigWord2 = word2; -var bigWord3 = { - start: { line: bigWordLine.line, ch: 1 }, - end: { line: bigWordLine.line, ch: 7 } -}; -var bigWord4 = { - start: { line: bigWordLine.line, ch: bigWord1.end.ch + 3 }, - end: { line: bigWordLine.line, ch: bigWord1.end.ch + 7 } -}; - -var oChars = [ { line: charLine.line, ch: 1 }, - { line: charLine.line, ch: 3 }, - { line: charLine.line, ch: 7 } ]; -var pChars = [ { line: charLine.line, ch: 2 }, - { line: charLine.line, ch: 4 }, - { line: charLine.line, ch: 6 }, - { line: charLine.line, ch: 8 } ]; -var numChars = [ { line: charLine.line, ch: 10 }, - { line: charLine.line, ch: 12 }, - { line: charLine.line, ch: 14 }, - { line: charLine.line, ch: 16 }, - { line: charLine.line, ch: 18 }]; -var parens1 = { - start: { line: bracesLine.line, ch: 1 }, - end: { line: bracesLine.line, ch: 3 } -}; -var squares1 = { - start: { line: bracesLine.line, ch: 5 }, - end: { line: bracesLine.line, ch: 7 } -}; -var curlys1 = { - start: { line: bracesLine.line, ch: 9 }, - end: { line: bracesLine.line, ch: 11 } -}; -var seekOutside = { - start: { line: seekBraceLine.line, ch: 1 }, - end: { line: seekBraceLine.line, ch: 16 } -}; -var seekInside = { - start: { line: seekBraceLine.line, ch: 14 }, - end: { line: seekBraceLine.line, ch: 11 } -}; - -function copyCursor(cur) { - return { ch: cur.ch, line: cur.line }; -} - -function forEach(arr, func) { - for (var i = 0; i < arr.length; i++) { - func(arr[i], i, arr); - } -} - -function testVim(name, run, opts, expectedFail) { - var vimOpts = { - lineNumbers: true, - vimMode: true, - showCursorWhenSelecting: true, - value: code - }; - for (var prop in opts) { - if (opts.hasOwnProperty(prop)) { - vimOpts[prop] = opts[prop]; - } - } - return test('vim_' + name, function() { - var place = document.getElementById("testground"); - var cm = CodeMirror(place, vimOpts); - var vim = CodeMirror.Vim.maybeInitVimState_(cm); - - function doKeysFn(cm) { - return function(args) { - if (args instanceof Array) { - arguments = args; - } - for (var i = 0; i < arguments.length; i++) { - var result = CodeMirror.Vim.handleKey(cm, arguments[i]); - if (!result && cm.state.vim.insertMode) { - cm.replaceSelections(fillArray(arguments[i], cm.listSelections().length)); - } - } - } - } - function doInsertModeKeysFn(cm) { - return function(args) { - if (args instanceof Array) { arguments = args; } - function executeHandler(handler) { - if (typeof handler == 'string') { - CodeMirror.commands[handler](cm); - } else { - handler(cm); - } - return true; - } - for (var i = 0; i < arguments.length; i++) { - var key = arguments[i]; - // Find key in keymap and handle. - var handled = CodeMirror.lookupKey(key, cm.getOption('keyMap'), executeHandler, cm); - // Record for insert mode. - if (handled == "handled" && cm.state.vim.insertMode && arguments[i] != 'Esc') { - var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges; - if (lastChange && (key.indexOf('Delete') != -1 || key.indexOf('Backspace') != -1)) { - lastChange.changes.push(new CodeMirror.Vim.InsertModeKey(key)); - } - } - } - } - } - function doExFn(cm) { - return function(command) { - cm.openDialog = helpers.fakeOpenDialog(command); - helpers.doKeys(':'); - } - } - function assertCursorAtFn(cm) { - return function(line, ch) { - var pos; - if (ch == null && typeof line.line == 'number') { - pos = line; - } else { - pos = makeCursor(line, ch); - } - eqPos(pos, cm.getCursor()); - } - } - function fakeOpenDialog(result) { - return function(text, callback) { - return callback(result); - } - } - function fakeOpenNotification(matcher) { - return function(text) { - matcher(text); - } - } - var helpers = { - doKeys: doKeysFn(cm), - // Warning: Only emulates keymap events, not character insertions. Use - // replaceRange to simulate character insertions. - // Keys are in CodeMirror format, NOT vim format. - doInsertModeKeys: doInsertModeKeysFn(cm), - doEx: doExFn(cm), - assertCursorAt: assertCursorAtFn(cm), - fakeOpenDialog: fakeOpenDialog, - fakeOpenNotification: fakeOpenNotification, - getRegisterController: function() { - return CodeMirror.Vim.getRegisterController(); - } - } - CodeMirror.Vim.resetVimGlobalState_(); - var successful = false; - var savedOpenNotification = cm.openNotification; - var savedOpenDialog = cm.openDialog; - try { - run(cm, vim, helpers); - successful = true; - } finally { - cm.openNotification = savedOpenNotification; - cm.openDialog = savedOpenDialog; - if (!successful || verbose) { - place.style.visibility = "visible"; - } else { - place.removeChild(cm.getWrapperElement()); - } - } - }, expectedFail); -}; -testVim('qq@q', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'q', 'l', 'l', 'q'); - helpers.assertCursorAt(0,2); - helpers.doKeys('@', 'q'); - helpers.assertCursorAt(0,4); -}, { value: ' '}); -testVim('@@', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'q', 'l', 'l', 'q'); - helpers.assertCursorAt(0,2); - helpers.doKeys('@', 'q'); - helpers.assertCursorAt(0,4); - helpers.doKeys('@', '@'); - helpers.assertCursorAt(0,6); -}, { value: ' '}); -var jumplistScene = ''+ - 'word\n'+ - '(word)\n'+ - '{word\n'+ - 'word.\n'+ - '\n'+ - 'word search\n'+ - '}word\n'+ - 'word\n'+ - 'word\n'; -function testJumplist(name, keys, endPos, startPos, dialog) { - endPos = makeCursor(endPos[0], endPos[1]); - startPos = makeCursor(startPos[0], startPos[1]); - testVim(name, function(cm, vim, helpers) { - CodeMirror.Vim.resetVimGlobalState_(); - if(dialog)cm.openDialog = helpers.fakeOpenDialog('word'); - cm.setCursor(startPos); - helpers.doKeys.apply(null, keys); - helpers.assertCursorAt(endPos); - }, {value: jumplistScene}); -}; -testJumplist('jumplist_H', ['H', ''], [5,2], [5,2]); -testJumplist('jumplist_M', ['M', ''], [2,2], [2,2]); -testJumplist('jumplist_L', ['L', ''], [2,2], [2,2]); -testJumplist('jumplist_[[', ['[', '[', ''], [5,2], [5,2]); -testJumplist('jumplist_]]', [']', ']', ''], [2,2], [2,2]); -testJumplist('jumplist_G', ['G', ''], [5,2], [5,2]); -testJumplist('jumplist_gg', ['g', 'g', ''], [5,2], [5,2]); -testJumplist('jumplist_%', ['%', ''], [1,5], [1,5]); -testJumplist('jumplist_{', ['{', ''], [1,5], [1,5]); -testJumplist('jumplist_}', ['}', ''], [1,5], [1,5]); -testJumplist('jumplist_\'', ['m', 'a', 'h', '\'', 'a', 'h', ''], [1,0], [1,5]); -testJumplist('jumplist_`', ['m', 'a', 'h', '`', 'a', 'h', ''], [1,5], [1,5]); -testJumplist('jumplist_*_cachedCursor', ['*', ''], [1,3], [1,3]); -testJumplist('jumplist_#_cachedCursor', ['#', ''], [1,3], [1,3]); -testJumplist('jumplist_n', ['#', 'n', ''], [1,1], [2,3]); -testJumplist('jumplist_N', ['#', 'N', ''], [1,1], [2,3]); -testJumplist('jumplist_repeat_', ['*', '*', '*', '3', ''], [2,3], [2,3]); -testJumplist('jumplist_repeat_', ['*', '*', '*', '3', '', '2', ''], [5,0], [2,3]); -testJumplist('jumplist_repeated_motion', ['3', '*', ''], [2,3], [2,3]); -testJumplist('jumplist_/', ['/', ''], [2,3], [2,3], 'dialog'); -testJumplist('jumplist_?', ['?', ''], [2,3], [2,3], 'dialog'); -testJumplist('jumplist_skip_deleted_mark', - ['*', 'n', 'n', 'k', 'd', 'k', '', '', ''], - [0,2], [0,2]); -testJumplist('jumplist_skip_deleted_mark', - ['*', 'n', 'n', 'k', 'd', 'k', '', '', ''], - [1,0], [0,2]); - -/** - * @param name Name of the test - * @param keys An array of keys or a string with a single key to simulate. - * @param endPos The expected end position of the cursor. - * @param startPos The position the cursor should start at, defaults to 0, 0. - */ -function testMotion(name, keys, endPos, startPos) { - testVim(name, function(cm, vim, helpers) { - if (!startPos) { - startPos = { line: 0, ch: 0 }; - } - cm.setCursor(startPos); - helpers.doKeys(keys); - helpers.assertCursorAt(endPos); - }); -}; - -function makeCursor(line, ch) { - return { line: line, ch: ch }; -}; - -function offsetCursor(cur, offsetLine, offsetCh) { - return { line: cur.line + offsetLine, ch: cur.ch + offsetCh }; -}; - -// Motion tests -testMotion('|', '|', makeCursor(0, 0), makeCursor(0,4)); -testMotion('|_repeat', ['3', '|'], makeCursor(0, 2), makeCursor(0,4)); -testMotion('h', 'h', makeCursor(0, 0), word1.start); -testMotion('h_repeat', ['3', 'h'], offsetCursor(word1.end, 0, -3), word1.end); -testMotion('l', 'l', makeCursor(0, 1)); -testMotion('l_repeat', ['2', 'l'], makeCursor(0, 2)); -testMotion('j', 'j', offsetCursor(word1.end, 1, 0), word1.end); -testMotion('j_repeat', ['2', 'j'], offsetCursor(word1.end, 2, 0), word1.end); -testMotion('j_repeat_clip', ['1000', 'j'], endOfDocument); -testMotion('k', 'k', offsetCursor(word3.end, -1, 0), word3.end); -testMotion('k_repeat', ['2', 'k'], makeCursor(0, 4), makeCursor(2, 4)); -testMotion('k_repeat_clip', ['1000', 'k'], makeCursor(0, 4), makeCursor(2, 4)); -testMotion('w', 'w', word1.start); -testMotion('w_multiple_newlines_no_space', 'w', makeCursor(12, 2), makeCursor(11, 2)); -testMotion('w_multiple_newlines_with_space', 'w', makeCursor(14, 0), makeCursor(12, 51)); -testMotion('w_repeat', ['2', 'w'], word2.start); -testMotion('w_wrap', ['w'], word3.start, word2.start); -testMotion('w_endOfDocument', 'w', endOfDocument, endOfDocument); -testMotion('w_start_to_end', ['1000', 'w'], endOfDocument, makeCursor(0, 0)); -testMotion('W', 'W', bigWord1.start); -testMotion('W_repeat', ['2', 'W'], bigWord3.start, bigWord1.start); -testMotion('e', 'e', word1.end); -testMotion('e_repeat', ['2', 'e'], word2.end); -testMotion('e_wrap', 'e', word3.end, word2.end); -testMotion('e_endOfDocument', 'e', endOfDocument, endOfDocument); -testMotion('e_start_to_end', ['1000', 'e'], endOfDocument, makeCursor(0, 0)); -testMotion('b', 'b', word3.start, word3.end); -testMotion('b_repeat', ['2', 'b'], word2.start, word3.end); -testMotion('b_wrap', 'b', word2.start, word3.start); -testMotion('b_startOfDocument', 'b', makeCursor(0, 0), makeCursor(0, 0)); -testMotion('b_end_to_start', ['1000', 'b'], makeCursor(0, 0), endOfDocument); -testMotion('ge', ['g', 'e'], word2.end, word3.end); -testMotion('ge_repeat', ['2', 'g', 'e'], word1.end, word3.start); -testMotion('ge_wrap', ['g', 'e'], word2.end, word3.start); -testMotion('ge_startOfDocument', ['g', 'e'], makeCursor(0, 0), - makeCursor(0, 0)); -testMotion('ge_end_to_start', ['1000', 'g', 'e'], makeCursor(0, 0), endOfDocument); -testMotion('gg', ['g', 'g'], makeCursor(lines[0].line, lines[0].textStart), - makeCursor(3, 1)); -testMotion('gg_repeat', ['3', 'g', 'g'], - makeCursor(lines[2].line, lines[2].textStart)); -testMotion('G', 'G', - makeCursor(lines[lines.length - 1].line, lines[lines.length - 1].textStart), - makeCursor(3, 1)); -testMotion('G_repeat', ['3', 'G'], makeCursor(lines[2].line, - lines[2].textStart)); -// TODO: Make the test code long enough to test Ctrl-F and Ctrl-B. -testMotion('0', '0', makeCursor(0, 0), makeCursor(0, 8)); -testMotion('^', '^', makeCursor(0, lines[0].textStart), makeCursor(0, 8)); -testMotion('+', '+', makeCursor(1, lines[1].textStart), makeCursor(0, 8)); -testMotion('-', '-', makeCursor(0, lines[0].textStart), makeCursor(1, 4)); -testMotion('_', ['6','_'], makeCursor(5, lines[5].textStart), makeCursor(0, 8)); -testMotion('$', '$', makeCursor(0, lines[0].length - 1), makeCursor(0, 1)); -testMotion('$_repeat', ['2', '$'], makeCursor(1, lines[1].length - 1), - makeCursor(0, 3)); -testMotion('f', ['f', 'p'], pChars[0], makeCursor(charLine.line, 0)); -testMotion('f_repeat', ['2', 'f', 'p'], pChars[2], pChars[0]); -testMotion('f_num', ['f', '2'], numChars[2], makeCursor(charLine.line, 0)); -testMotion('t', ['t','p'], offsetCursor(pChars[0], 0, -1), - makeCursor(charLine.line, 0)); -testMotion('t_repeat', ['2', 't', 'p'], offsetCursor(pChars[2], 0, -1), - pChars[0]); -testMotion('F', ['F', 'p'], pChars[0], pChars[1]); -testMotion('F_repeat', ['2', 'F', 'p'], pChars[0], pChars[2]); -testMotion('T', ['T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[1]); -testMotion('T_repeat', ['2', 'T', 'p'], offsetCursor(pChars[0], 0, 1), pChars[2]); -testMotion('%_parens', ['%'], parens1.end, parens1.start); -testMotion('%_squares', ['%'], squares1.end, squares1.start); -testMotion('%_braces', ['%'], curlys1.end, curlys1.start); -testMotion('%_seek_outside', ['%'], seekOutside.end, seekOutside.start); -testMotion('%_seek_inside', ['%'], seekInside.end, seekInside.start); -testVim('%_seek_skip', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,9); -}, {value:'01234"("()'}); -testVim('%_skip_string', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,4); - cm.setCursor(0,2); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,0); -}, {value:'(")")'}); -testVim('%_skip_comment', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,6); - cm.setCursor(0,3); - helpers.doKeys(['%']); - helpers.assertCursorAt(0,0); -}, {value:'(/*)*/)'}); -// Make sure that moving down after going to the end of a line always leaves you -// at the end of a line, but preserves the offset in other cases -testVim('Changing lines after Eol operation', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys(['$']); - helpers.doKeys(['j']); - // After moving to Eol and then down, we should be at Eol of line 2 - helpers.assertCursorAt({ line: 1, ch: lines[1].length - 1 }); - helpers.doKeys(['j']); - // After moving down, we should be at Eol of line 3 - helpers.assertCursorAt({ line: 2, ch: lines[2].length - 1 }); - helpers.doKeys(['h']); - helpers.doKeys(['j']); - // After moving back one space and then down, since line 4 is shorter than line 2, we should - // be at Eol of line 2 - 1 - helpers.assertCursorAt({ line: 3, ch: lines[3].length - 1 }); - helpers.doKeys(['j']); - helpers.doKeys(['j']); - // After moving down again, since line 3 has enough characters, we should be back to the - // same place we were at on line 1 - helpers.assertCursorAt({ line: 5, ch: lines[2].length - 2 }); -}); -//making sure gj and gk recover from clipping -testVim('gj_gk_clipping', function(cm,vim,helpers){ - cm.setCursor(0, 1); - helpers.doKeys('g','j','g','j'); - helpers.assertCursorAt(2, 1); - helpers.doKeys('g','k','g','k'); - helpers.assertCursorAt(0, 1); -},{value: 'line 1\n\nline 2'}); -//testing a mix of j/k and gj/gk -testVim('j_k_and_gj_gk', function(cm,vim,helpers){ - cm.setSize(120); - cm.setCursor(0, 0); - //go to the last character on the first line - helpers.doKeys('$'); - //move up/down on the column within the wrapped line - //side-effect: cursor is not locked to eol anymore - helpers.doKeys('g','k'); - var cur=cm.getCursor(); - eq(cur.line,0); - is((cur.ch<176),'gk didn\'t move cursor back (1)'); - helpers.doKeys('g','j'); - helpers.assertCursorAt(0, 176); - //should move to character 177 on line 2 (j/k preserve character index within line) - helpers.doKeys('j'); - //due to different line wrapping, the cursor can be on a different screen-x now - //gj and gk preserve screen-x on movement, much like moveV - helpers.doKeys('3','g','k'); - cur=cm.getCursor(); - eq(cur.line,1); - is((cur.ch<176),'gk didn\'t move cursor back (2)'); - helpers.doKeys('g','j','2','g','j'); - //should return to the same character-index - helpers.doKeys('k'); - helpers.assertCursorAt(0, 176); -},{ lineWrapping:true, value: 'This line is intentially long to test movement of gj and gk over wrapped lines. I will start on the end of this line, then make a step up and back to set the origin for j and k.\nThis line is supposed to be even longer than the previous. I will jump here and make another wiggle with gj and gk, before I jump back to the line above. Both wiggles should not change my cursor\'s target character but both j/k and gj/gk change each other\'s reference position.'}); -testVim('gj_gk', function(cm, vim, helpers) { - if (phantom) return; - cm.setSize(120); - // Test top of document edge case. - cm.setCursor(0, 4); - helpers.doKeys('g', 'j'); - helpers.doKeys('10', 'g', 'k'); - helpers.assertCursorAt(0, 4); - - // Test moving down preserves column position. - helpers.doKeys('g', 'j'); - var pos1 = cm.getCursor(); - var expectedPos2 = { line: 0, ch: (pos1.ch - 4) * 2 + 4}; - helpers.doKeys('g', 'j'); - helpers.assertCursorAt(expectedPos2); - - // Move to the last character - cm.setCursor(0, 0); - // Move left to reset HSPos - helpers.doKeys('h'); - // Test bottom of document edge case. - helpers.doKeys('100', 'g', 'j'); - var endingPos = cm.getCursor(); - is(endingPos != 0, 'gj should not be on wrapped line 0'); - var topLeftCharCoords = cm.charCoords(makeCursor(0, 0)); - var endingCharCoords = cm.charCoords(endingPos); - is(topLeftCharCoords.left == endingCharCoords.left, 'gj should end up on column 0'); -},{ lineNumbers: false, lineWrapping:true, value: 'Thislineisintentionallylongtotestmovementofgjandgkoverwrappedlines.' }); -testVim('}', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('}'); - helpers.assertCursorAt(1, 0); - cm.setCursor(0, 0); - helpers.doKeys('2', '}'); - helpers.assertCursorAt(4, 0); - cm.setCursor(0, 0); - helpers.doKeys('6', '}'); - helpers.assertCursorAt(5, 0); -}, { value: 'a\n\nb\nc\n\nd' }); -testVim('{', function(cm, vim, helpers) { - cm.setCursor(5, 0); - helpers.doKeys('{'); - helpers.assertCursorAt(4, 0); - cm.setCursor(5, 0); - helpers.doKeys('2', '{'); - helpers.assertCursorAt(1, 0); - cm.setCursor(5, 0); - helpers.doKeys('6', '{'); - helpers.assertCursorAt(0, 0); -}, { value: 'a\n\nb\nc\n\nd' }); -testVim('paragraph_motions', function(cm, vim, helpers) { - cm.setCursor(10, 0); - helpers.doKeys('{'); - helpers.assertCursorAt(4, 0); - helpers.doKeys('{'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('2', '}'); - helpers.assertCursorAt(7, 0); - helpers.doKeys('2', '}'); - helpers.assertCursorAt(16, 0); - - cm.setCursor(9, 0); - helpers.doKeys('}'); - helpers.assertCursorAt(14, 0); - - cm.setCursor(6, 0); - helpers.doKeys('}'); - helpers.assertCursorAt(7, 0); - - // ip inside empty space - cm.setCursor(10, 0); - helpers.doKeys('v', 'i', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(12, 0), cm.getCursor('head')); - helpers.doKeys('i', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(13, 1), cm.getCursor('head')); - helpers.doKeys('2', 'i', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(16, 1), cm.getCursor('head')); - - // should switch to visualLine mode - cm.setCursor(14, 0); - helpers.doKeys('', 'v', 'i', 'p'); - helpers.assertCursorAt(14, 0); - - cm.setCursor(14, 0); - helpers.doKeys('', 'V', 'i', 'p'); - eqPos(Pos(16, 1), cm.getCursor('head')); - - // ap inside empty space - cm.setCursor(10, 0); - helpers.doKeys('', 'v', 'a', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(13, 1), cm.getCursor('head')); - helpers.doKeys('a', 'p'); - eqPos(Pos(7, 0), cm.getCursor('anchor')); - eqPos(Pos(16, 1), cm.getCursor('head')); - - cm.setCursor(13, 0); - helpers.doKeys('v', 'a', 'p'); - eqPos(Pos(13, 0), cm.getCursor('anchor')); - eqPos(Pos(14, 0), cm.getCursor('head')); - - cm.setCursor(16, 0); - helpers.doKeys('v', 'a', 'p'); - eqPos(Pos(14, 0), cm.getCursor('anchor')); - eqPos(Pos(16, 1), cm.getCursor('head')); - - cm.setCursor(0, 0); - helpers.doKeys('v', 'a', 'p'); - eqPos(Pos(0, 0), cm.getCursor('anchor')); - eqPos(Pos(4, 0), cm.getCursor('head')); - - cm.setCursor(0, 0); - helpers.doKeys('d', 'i', 'p'); - var register = helpers.getRegisterController().getRegister(); - eq('a\na\n', register.toString()); - is(register.linewise); - helpers.doKeys('3', 'j', 'p'); - helpers.doKeys('y', 'i', 'p'); - is(register.linewise); - eq('b\na\na\nc\n', register.toString()); -}, { value: 'a\na\n\n\n\nb\nc\n\n\n\n\n\n\nd\n\ne\nf' }); - -// Operator tests -testVim('dl', function(cm, vim, helpers) { - var curStart = makeCursor(0, 0); - cm.setCursor(curStart); - helpers.doKeys('d', 'l'); - eq('word1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' ', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dl_eol', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('d', 'l'); - eq(' word1', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' ', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 5); -}, { value: ' word1 ' }); -testVim('dl_repeat', function(cm, vim, helpers) { - var curStart = makeCursor(0, 0); - cm.setCursor(curStart); - helpers.doKeys('2', 'd', 'l'); - eq('ord1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' w', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dh', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'h'); - eq(' wrd1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('o', register.toString()); - is(!register.linewise); - eqPos(offsetCursor(curStart, 0 , -1), cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dj', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'j'); - eq(' word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' word1\nword2\n', register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2\n word3' }); -testVim('dj_end_of_document', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'j'); - eq('', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' word1 \n', register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, 0); -}, { value: ' word1 ' }); -testVim('dk', function(cm, vim, helpers) { - var curStart = makeCursor(1, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'k'); - eq(' word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' word1\nword2\n', register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2\n word3' }); -testVim('dk_start_of_document', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('d', 'k'); - eq('', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' word1 \n', register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, 0); -}, { value: ' word1 ' }); -testVim('dw_space', function(cm, vim, helpers) { - var curStart = makeCursor(0, 0); - cm.setCursor(curStart); - helpers.doKeys('d', 'w'); - eq('word1 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(' ', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('dw_word', function(cm, vim, helpers) { - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('d', 'w'); - eq(' word2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1 ', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 word2' }); -testVim('dw_unicode_word', function(cm, vim, helpers) { - helpers.doKeys('d', 'w'); - eq(cm.getValue().length, 10); - helpers.doKeys('d', 'w'); - eq(cm.getValue().length, 6); - helpers.doKeys('d', 'w'); - eq(cm.getValue().length, 5); - helpers.doKeys('d', 'e'); - eq(cm.getValue().length, 2); -}, { value: ' \u0562\u0561\u0580\u0587\xbbe\xb5g ' }); -testVim('dw_only_word', function(cm, vim, helpers) { - // Test that if there is only 1 word left, dw deletes till the end of the - // line. - cm.setCursor(0, 1); - helpers.doKeys('d', 'w'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1 ', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 0); -}, { value: ' word1 ' }); -testVim('dw_eol', function(cm, vim, helpers) { - // Assert that dw does not delete the newline if last word to delete is at end - // of line. - cm.setCursor(0, 1); - helpers.doKeys('d', 'w'); - eq(' \nword2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 0); -}, { value: ' word1\nword2' }); -testVim('dw_eol_with_multiple_newlines', function(cm, vim, helpers) { - // Assert that dw does not delete the newline if last word to delete is at end - // of line and it is followed by multiple newlines. - cm.setCursor(0, 1); - helpers.doKeys('d', 'w'); - eq(' \n\nword2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 0); -}, { value: ' word1\n\nword2' }); -testVim('dw_empty_line_followed_by_whitespace', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq(' \nword', cm.getValue()); -}, { value: '\n \nword' }); -testVim('dw_empty_line_followed_by_word', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('word', cm.getValue()); -}, { value: '\nword' }); -testVim('dw_empty_line_followed_by_empty_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n', cm.getValue()); -}, { value: '\n\n' }); -testVim('dw_whitespace_followed_by_whitespace', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n \n', cm.getValue()); -}, { value: ' \n \n' }); -testVim('dw_whitespace_followed_by_empty_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n\n', cm.getValue()); -}, { value: ' \n\n' }); -testVim('dw_word_whitespace_word', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'w'); - eq('\n \nword2', cm.getValue()); -}, { value: 'word1\n \nword2'}) -testVim('dw_end_of_document', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('d', 'w'); - eq('\nab', cm.getValue()); -}, { value: '\nabc' }); -testVim('dw_repeat', function(cm, vim, helpers) { - // Assert that dw does delete newline if it should go to the next line, and - // that repeat works properly. - cm.setCursor(0, 1); - helpers.doKeys('d', '2', 'w'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\nword2', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 0); -}, { value: ' word1\nword2' }); -testVim('de_word_start_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'e'); - eq('\n\n', cm.getValue()); -}, { value: 'word\n\n' }); -testVim('de_word_end_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(0, 3); - helpers.doKeys('d', 'e'); - eq('wor', cm.getValue()); -}, { value: 'word\n\n\n' }); -testVim('de_whitespace_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'e'); - eq('', cm.getValue()); -}, { value: ' \n\n\n' }); -testVim('de_end_of_document', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('d', 'e'); - eq('\nab', cm.getValue()); -}, { value: '\nabc' }); -testVim('db_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'b'); - eq('\n\n', cm.getValue()); -}, { value: '\n\n\n' }); -testVim('db_word_start_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'b'); - eq('\nword', cm.getValue()); -}, { value: '\n\nword' }); -testVim('db_word_end_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 3); - helpers.doKeys('d', 'b'); - eq('\n\nd', cm.getValue()); -}, { value: '\n\nword' }); -testVim('db_whitespace_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'b'); - eq('', cm.getValue()); -}, { value: '\n \n' }); -testVim('db_start_of_document', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'b'); - eq('abc\n', cm.getValue()); -}, { value: 'abc\n' }); -testVim('dge_empty_lines', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doKeys('d', 'g', 'e'); - // Note: In real VIM the result should be '', but it's not quite consistent, - // since 2 newlines are deleted. But in the similar case of word\n\n, only - // 1 newline is deleted. We'll diverge from VIM's behavior since it's much - // easier this way. - eq('\n', cm.getValue()); -}, { value: '\n\n' }); -testVim('dge_word_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doKeys('d', 'g', 'e'); - eq('wor\n', cm.getValue()); -}, { value: 'word\n\n'}); -testVim('dge_whitespace_and_empty_lines', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('d', 'g', 'e'); - eq('', cm.getValue()); -}, { value: '\n \n' }); -testVim('dge_start_of_document', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('d', 'g', 'e'); - eq('bc\n', cm.getValue()); -}, { value: 'abc\n' }); -testVim('d_inclusive', function(cm, vim, helpers) { - // Assert that when inclusive is set, the character the cursor is on gets - // deleted too. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('d', 'e'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1 ' }); -testVim('d_reverse', function(cm, vim, helpers) { - // Test that deleting in reverse works. - cm.setCursor(1, 0); - helpers.doKeys('d', 'b'); - eq(' word2 ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\n', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2 ' }); -testVim('dd', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 1, ch: 0 }); - var expectedLineCount = cm.lineCount() - 1; - helpers.doKeys('d', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[1].textStart); -}); -testVim('dd_prefix_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 2, ch: 0 }); - var expectedLineCount = cm.lineCount() - 2; - helpers.doKeys('2', 'd', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[2].textStart); -}); -testVim('dd_motion_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 2, ch: 0 }); - var expectedLineCount = cm.lineCount() - 2; - helpers.doKeys('d', '2', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[2].textStart); -}); -testVim('dd_multiply_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 6, ch: 0 }); - var expectedLineCount = cm.lineCount() - 6; - helpers.doKeys('2', 'd', '3', 'd'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - helpers.assertCursorAt(0, lines[6].textStart); -}); -testVim('dd_lastline', function(cm, vim, helpers) { - cm.setCursor(cm.lineCount(), 0); - var expectedLineCount = cm.lineCount() - 1; - helpers.doKeys('d', 'd'); - eq(expectedLineCount, cm.lineCount()); - helpers.assertCursorAt(cm.lineCount() - 1, 0); -}); -testVim('dd_only_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - var expectedRegister = cm.getValue() + "\n"; - helpers.doKeys('d','d'); - eq(1, cm.lineCount()); - eq('', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedRegister, register.toString()); -}, { value: "thisistheonlyline" }); -// Yank commands should behave the exact same as d commands, expect that nothing -// gets deleted. -testVim('yw_repeat', function(cm, vim, helpers) { - // Assert that yw does yank newline if it should go to the next line, and - // that repeat works properly. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('y', '2', 'w'); - eq(' word1\nword2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\nword2', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1\nword2' }); -testVim('yy_multiply_repeat', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 6, ch: 0 }); - var expectedLineCount = cm.lineCount(); - helpers.doKeys('2', 'y', '3', 'y'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - eqPos(curStart, cm.getCursor()); -}); -// Change commands behave like d commands except that it also enters insert -// mode. In addition, when the change is linewise, an additional newline is -// inserted so that insert mode starts on that line. -testVim('cw', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('c', '2', 'w'); - eq(' word3', cm.getValue()); - helpers.assertCursorAt(0, 0); -}, { value: 'word1 word2 word3'}); -testVim('cw_repeat', function(cm, vim, helpers) { - // Assert that cw does delete newline if it should go to the next line, and - // that repeat works properly. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('c', '2', 'w'); - eq(' ', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('word1\nword2', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: ' word1\nword2' }); -testVim('cc_multiply_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedBuffer = cm.getRange({ line: 0, ch: 0 }, - { line: 6, ch: 0 }); - var expectedLineCount = cm.lineCount() - 5; - helpers.doKeys('2', 'c', '3', 'c'); - eq(expectedLineCount, cm.lineCount()); - var register = helpers.getRegisterController().getRegister(); - eq(expectedBuffer, register.toString()); - is(register.linewise); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('ct', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('c', 't', 'w'); - eq(' word1 word3', cm.getValue()); - helpers.doKeys('', 'c', '|'); - eq(' word3', cm.getValue()); - helpers.assertCursorAt(0, 0); - helpers.doKeys('', '2', 'u', 'w', 'h'); - helpers.doKeys('c', '2', 'g', 'e'); - eq(' wordword3', cm.getValue()); -}, { value: ' word1 word2 word3'}); -testVim('cc_should_not_append_to_document', function(cm, vim, helpers) { - var expectedLineCount = cm.lineCount(); - cm.setCursor(cm.lastLine(), 0); - helpers.doKeys('c', 'c'); - eq(expectedLineCount, cm.lineCount()); -}); -function fillArray(val, times) { - var arr = []; - for (var i = 0; i < times; i++) { - arr.push(val); - } - return arr; -} -testVim('c_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'l', 'l', 'c'); - var replacement = fillArray('hello', 3); - cm.replaceSelections(replacement); - eq('1hello\n5hello\nahellofg', cm.getValue()); - helpers.doKeys(''); - cm.setCursor(2, 3); - helpers.doKeys('', '2', 'k', 'h', 'C'); - replacement = fillArray('world', 3); - cm.replaceSelections(replacement); - eq('1hworld\n5hworld\nahworld', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); -testVim('c_visual_block_replay', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'c'); - var replacement = fillArray('fo', 3); - cm.replaceSelections(replacement); - eq('1fo4\n5fo8\nafodefg', cm.getValue()); - helpers.doKeys(''); - cm.setCursor(0, 0); - helpers.doKeys('.'); - eq('foo4\nfoo8\nfoodefg', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); - -testVim('d_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'l', 'l', 'd'); - eq('1\n5\nafg', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); -testVim('D_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'D'); - eq('1\n5\na', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); - -testVim('s_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'l', 'l', 's'); - var replacement = fillArray('hello{', 3); - cm.replaceSelections(replacement); - eq('1hello{\n5hello{\nahello{fg\n', cm.getValue()); - helpers.doKeys(''); - cm.setCursor(2, 3); - helpers.doKeys('', '1', 'k', 'h', 'S'); - replacement = fillArray('world', 1); - cm.replaceSelections(replacement); - eq('1hello{\n world\n', cm.getValue()); -}, {value: '1234\n5678\nabcdefg\n'}); - -// Swapcase commands edit in place and do not modify registers. -testVim('g~w_repeat', function(cm, vim, helpers) { - // Assert that dw does delete newline if it should go to the next line, and - // that repeat works properly. - var curStart = makeCursor(0, 1); - cm.setCursor(curStart); - helpers.doKeys('g', '~', '2', 'w'); - eq(' WORD1\nWORD2', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1\nword2' }); -testVim('g~g~', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - var expectedLineCount = cm.lineCount(); - var expectedValue = cm.getValue().toUpperCase(); - helpers.doKeys('2', 'g', '~', '3', 'g', '~'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); -}, { value: ' word1\nword2\nword3\nword4\nword5\nword6' }); -testVim('gu_and_gU', function(cm, vim, helpers) { - var curStart = makeCursor(0, 7); - var value = cm.getValue(); - cm.setCursor(curStart); - helpers.doKeys('2', 'g', 'U', 'w'); - eq(cm.getValue(), 'wa wb xX WC wd'); - eqPos(curStart, cm.getCursor()); - helpers.doKeys('2', 'g', 'u', 'w'); - eq(cm.getValue(), value); - - helpers.doKeys('2', 'g', 'U', 'B'); - eq(cm.getValue(), 'wa WB Xx wc wd'); - eqPos(makeCursor(0, 3), cm.getCursor()); - - cm.setCursor(makeCursor(0, 4)); - helpers.doKeys('g', 'u', 'i', 'w'); - eq(cm.getValue(), 'wa wb Xx wc wd'); - eqPos(makeCursor(0, 3), cm.getCursor()); - - // TODO: support gUgU guu - // eqPos(makeCursor(0, 0), cm.getCursor()); - - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); -}, { value: 'wa wb xx wc wd' }); -testVim('visual_block_~', function(cm, vim, helpers) { - cm.setCursor(1, 1); - helpers.doKeys('', 'l', 'l', 'j', '~'); - helpers.assertCursorAt(1, 1); - eq('hello\nwoRLd\naBCDe', cm.getValue()); - cm.setCursor(2, 0); - helpers.doKeys('v', 'l', 'l', '~'); - helpers.assertCursorAt(2, 0); - eq('hello\nwoRLd\nAbcDe', cm.getValue()); -},{value: 'hello\nwOrld\nabcde' }); -testVim('._swapCase_visualBlock', function(cm, vim, helpers) { - helpers.doKeys('', 'j', 'j', 'l', '~'); - cm.setCursor(0, 3); - helpers.doKeys('.'); - eq('HelLO\nWorLd\nAbcdE', cm.getValue()); -},{value: 'hEllo\nwOrlD\naBcDe' }); -testVim('._delete_visualBlock', function(cm, vim, helpers) { - helpers.doKeys('', 'j', 'x'); - eq('ive\ne\nsome\nsugar', cm.getValue()); - helpers.doKeys('.'); - eq('ve\n\nsome\nsugar', cm.getValue()); - helpers.doKeys('j', 'j', '.'); - eq('ve\n\nome\nugar', cm.getValue()); - helpers.doKeys('u', '', '.'); - eq('ve\n\nme\ngar', cm.getValue()); -},{value: 'give\nme\nsome\nsugar' }); -testVim('>{motion}', function(cm, vim, helpers) { - cm.setCursor(1, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\n word2\nword3 '; - helpers.doKeys('>', 'k'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); -testVim('>>', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\n word2\nword3 '; - helpers.doKeys('2', '>', '>'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); -testVim('<{motion}', function(cm, vim, helpers) { - cm.setCursor(1, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\nword2\nword3 '; - helpers.doKeys('<', 'k'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\n word2\nword3 ', indentUnit: 2 }); -testVim('<<', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedLineCount = cm.lineCount(); - var expectedValue = ' word1\nword2\nword3 '; - helpers.doKeys('2', '<', '<'); - eq(expectedValue, cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\n word2\nword3 ', indentUnit: 2 }); - -// Edit tests -function testEdit(name, before, pos, edit, after) { - return testVim(name, function(cm, vim, helpers) { - var ch = before.search(pos) - var line = before.substring(0, ch).split('\n').length - 1; - if (line) { - ch = before.substring(0, ch).split('\n').pop().length; - } - cm.setCursor(line, ch); - helpers.doKeys.apply(this, edit.split('')); - eq(after, cm.getValue()); - }, {value: before}); -} - -// These Delete tests effectively cover word-wise Change, Visual & Yank. -// Tabs are used as differentiated whitespace to catch edge cases. -// Normal word: -testEdit('diw_mid_spc', 'foo \tbAr\t baz', /A/, 'diw', 'foo \t\t baz'); -testEdit('daw_mid_spc', 'foo \tbAr\t baz', /A/, 'daw', 'foo \tbaz'); -testEdit('diw_mid_punct', 'foo \tbAr.\t baz', /A/, 'diw', 'foo \t.\t baz'); -testEdit('daw_mid_punct', 'foo \tbAr.\t baz', /A/, 'daw', 'foo.\t baz'); -testEdit('diw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diw', 'foo \t,.\t baz'); -testEdit('daw_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daw', 'foo \t,.\t baz'); -testEdit('diw_start_spc', 'bAr \tbaz', /A/, 'diw', ' \tbaz'); -testEdit('daw_start_spc', 'bAr \tbaz', /A/, 'daw', 'baz'); -testEdit('diw_start_punct', 'bAr. \tbaz', /A/, 'diw', '. \tbaz'); -testEdit('daw_start_punct', 'bAr. \tbaz', /A/, 'daw', '. \tbaz'); -testEdit('diw_end_spc', 'foo \tbAr', /A/, 'diw', 'foo \t'); -testEdit('daw_end_spc', 'foo \tbAr', /A/, 'daw', 'foo'); -testEdit('diw_end_punct', 'foo \tbAr.', /A/, 'diw', 'foo \t.'); -testEdit('daw_end_punct', 'foo \tbAr.', /A/, 'daw', 'foo.'); -// Big word: -testEdit('diW_mid_spc', 'foo \tbAr\t baz', /A/, 'diW', 'foo \t\t baz'); -testEdit('daW_mid_spc', 'foo \tbAr\t baz', /A/, 'daW', 'foo \tbaz'); -testEdit('diW_mid_punct', 'foo \tbAr.\t baz', /A/, 'diW', 'foo \t\t baz'); -testEdit('daW_mid_punct', 'foo \tbAr.\t baz', /A/, 'daW', 'foo \tbaz'); -testEdit('diW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'diW', 'foo \t\t baz'); -testEdit('daW_mid_punct2', 'foo \t,bAr.\t baz', /A/, 'daW', 'foo \tbaz'); -testEdit('diW_start_spc', 'bAr\t baz', /A/, 'diW', '\t baz'); -testEdit('daW_start_spc', 'bAr\t baz', /A/, 'daW', 'baz'); -testEdit('diW_start_punct', 'bAr.\t baz', /A/, 'diW', '\t baz'); -testEdit('daW_start_punct', 'bAr.\t baz', /A/, 'daW', 'baz'); -testEdit('diW_end_spc', 'foo \tbAr', /A/, 'diW', 'foo \t'); -testEdit('daW_end_spc', 'foo \tbAr', /A/, 'daW', 'foo'); -testEdit('diW_end_punct', 'foo \tbAr.', /A/, 'diW', 'foo \t'); -testEdit('daW_end_punct', 'foo \tbAr.', /A/, 'daW', 'foo'); -// Deleting text objects -// Open and close on same line -testEdit('di(_open_spc', 'foo (bAr) baz', /\(/, 'di(', 'foo () baz'); -testEdit('di)_open_spc', 'foo (bAr) baz', /\(/, 'di)', 'foo () baz'); -testEdit('dib_open_spc', 'foo (bAr) baz', /\(/, 'dib', 'foo () baz'); -testEdit('da(_open_spc', 'foo (bAr) baz', /\(/, 'da(', 'foo baz'); -testEdit('da)_open_spc', 'foo (bAr) baz', /\(/, 'da)', 'foo baz'); - -testEdit('di(_middle_spc', 'foo (bAr) baz', /A/, 'di(', 'foo () baz'); -testEdit('di)_middle_spc', 'foo (bAr) baz', /A/, 'di)', 'foo () baz'); -testEdit('da(_middle_spc', 'foo (bAr) baz', /A/, 'da(', 'foo baz'); -testEdit('da)_middle_spc', 'foo (bAr) baz', /A/, 'da)', 'foo baz'); - -testEdit('di(_close_spc', 'foo (bAr) baz', /\)/, 'di(', 'foo () baz'); -testEdit('di)_close_spc', 'foo (bAr) baz', /\)/, 'di)', 'foo () baz'); -testEdit('da(_close_spc', 'foo (bAr) baz', /\)/, 'da(', 'foo baz'); -testEdit('da)_close_spc', 'foo (bAr) baz', /\)/, 'da)', 'foo baz'); - -// delete around and inner b. -testEdit('dab_on_(_should_delete_around_()block', 'o( in(abc) )', /\(a/, 'dab', 'o( in )'); - -// delete around and inner B. -testEdit('daB_on_{_should_delete_around_{}block', 'o{ in{abc} }', /{a/, 'daB', 'o{ in }'); -testEdit('diB_on_{_should_delete_inner_{}block', 'o{ in{abc} }', /{a/, 'diB', 'o{ in{} }'); - -testEdit('da{_on_{_should_delete_inner_block', 'o{ in{abc} }', /{a/, 'da{', 'o{ in }'); -testEdit('di[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'di[', 'foo (bAr) baz'); -testEdit('di[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'di[', 'foo (bAr) baz'); -testEdit('da[_on_(_should_not_delete', 'foo (bAr) baz', /\(/, 'da[', 'foo (bAr) baz'); -testEdit('da[_on_)_should_not_delete', 'foo (bAr) baz', /\)/, 'da[', 'foo (bAr) baz'); -testMotion('di(_outside_should_stay', ['d', 'i', '('], { line: 0, ch: 0}, { line: 0, ch: 0}); - -// Open and close on different lines, equally indented -testEdit('di{_middle_spc', 'a{\n\tbar\n}b', /r/, 'di{', 'a{}b'); -testEdit('di}_middle_spc', 'a{\n\tbar\n}b', /r/, 'di}', 'a{}b'); -testEdit('da{_middle_spc', 'a{\n\tbar\n}b', /r/, 'da{', 'ab'); -testEdit('da}_middle_spc', 'a{\n\tbar\n}b', /r/, 'da}', 'ab'); -testEdit('daB_middle_spc', 'a{\n\tbar\n}b', /r/, 'daB', 'ab'); - -// open and close on diff lines, open indented less than close -testEdit('di{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di{', 'a{}b'); -testEdit('di}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'di}', 'a{}b'); -testEdit('da{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da{', 'ab'); -testEdit('da}_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'da}', 'ab'); - -// open and close on diff lines, open indented more than close -testEdit('di[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di[', 'a\t[]b'); -testEdit('di]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'di]', 'a\t[]b'); -testEdit('da[_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da[', 'a\tb'); -testEdit('da]_middle_spc', 'a\t[\n\tbar\n]b', /r/, 'da]', 'a\tb'); - -function testSelection(name, before, pos, keys, sel) { - return testVim(name, function(cm, vim, helpers) { - var ch = before.search(pos) - var line = before.substring(0, ch).split('\n').length - 1; - if (line) { - ch = before.substring(0, ch).split('\n').pop().length; - } - cm.setCursor(line, ch); - helpers.doKeys.apply(this, keys.split('')); - eq(sel, cm.getSelection()); - }, {value: before}); -} -testSelection('viw_middle_spc', 'foo \tbAr\t baz', /A/, 'viw', 'bAr'); -testSelection('vaw_middle_spc', 'foo \tbAr\t baz', /A/, 'vaw', 'bAr\t '); -testSelection('viw_middle_punct', 'foo \tbAr,\t baz', /A/, 'viw', 'bAr'); -testSelection('vaW_middle_punct', 'foo \tbAr,\t baz', /A/, 'vaW', 'bAr,\t '); -testSelection('viw_start_spc', 'foo \tbAr\t baz', /b/, 'viw', 'bAr'); -testSelection('viw_end_spc', 'foo \tbAr\t baz', /r/, 'viw', 'bAr'); -testSelection('viw_eol', 'foo \tbAr', /r/, 'viw', 'bAr'); -testSelection('vi{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'vi{', '\n\tbar\n\t'); -testSelection('va{_middle_spc', 'a{\n\tbar\n\t}b', /r/, 'va{', '{\n\tbar\n\t}'); - -testVim('mouse_select', function(cm, vim, helpers) { - cm.setSelection(Pos(0, 2), Pos(0, 4), {origin: '*mouse'}); - is(cm.state.vim.visualMode); - is(!cm.state.vim.visualLine); - is(!cm.state.vim.visualBlock); - helpers.doKeys(''); - is(!cm.somethingSelected()); - helpers.doKeys('g', 'v'); - eq('cd', cm.getSelection()); -}, {value: 'abcdef'}); - -// Operator-motion tests -testVim('D', function(cm, vim, helpers) { - cm.setCursor(0, 3); - helpers.doKeys('D'); - eq(' wo\nword2\n word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('rd1', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 2); -}, { value: ' word1\nword2\n word3' }); -testVim('C', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('C'); - eq(' wo\nword2\n word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('rd1', register.toString()); - is(!register.linewise); - eqPos(curStart, cm.getCursor()); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: ' word1\nword2\n word3' }); -testVim('Y', function(cm, vim, helpers) { - var curStart = makeCursor(0, 3); - cm.setCursor(curStart); - helpers.doKeys('Y'); - eq(' word1\nword2\n word3', cm.getValue()); - var register = helpers.getRegisterController().getRegister(); - eq('rd1', register.toString()); - is(!register.linewise); - helpers.assertCursorAt(0, 3); -}, { value: ' word1\nword2\n word3' }); -testVim('~', function(cm, vim, helpers) { - helpers.doKeys('3', '~'); - eq('ABCdefg', cm.getValue()); - helpers.assertCursorAt(0, 3); -}, { value: 'abcdefg' }); - -// Action tests -testVim('ctrl-a', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(''); - eq('-9', cm.getValue()); - helpers.assertCursorAt(0, 1); - helpers.doKeys('2',''); - eq('-7', cm.getValue()); -}, {value: '-10'}); -testVim('ctrl-x', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(''); - eq('-1', cm.getValue()); - helpers.assertCursorAt(0, 1); - helpers.doKeys('2',''); - eq('-3', cm.getValue()); -}, {value: '0'}); -testVim('/ search forward', function(cm, vim, helpers) { - forEach(['', ''], function(key) { - cm.setCursor(0, 0); - helpers.doKeys(key); - helpers.assertCursorAt(0, 5); - helpers.doKeys('l'); - helpers.doKeys(key); - helpers.assertCursorAt(0, 10); - cm.setCursor(0, 11); - helpers.doKeys(key); - helpers.assertCursorAt(0, 11); - }); -}, {value: '__jmp1 jmp2 jmp'}); -testVim('a', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('a'); - helpers.assertCursorAt(0, 2); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('a_eol', function(cm, vim, helpers) { - cm.setCursor(0, lines[0].length - 1); - helpers.doKeys('a'); - helpers.assertCursorAt(0, lines[0].length); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('A_endOfSelectedArea', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('v', 'j', 'l'); - helpers.doKeys('A'); - helpers.assertCursorAt(1, 2); - eq('vim-insert', cm.getOption('keyMap')); -}, {value: 'foo\nbar'}); -testVim('i', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('i'); - helpers.assertCursorAt(0, 1); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('i_repeat', function(cm, vim, helpers) { - helpers.doKeys('3', 'i'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - eq('testtesttest', cm.getValue()); - helpers.assertCursorAt(0, 11); -}, { value: '' }); -testVim('i_repeat_delete', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('2', 'i'); - cm.replaceRange('z', cm.getCursor()); - helpers.doInsertModeKeys('Backspace', 'Backspace'); - helpers.doKeys(''); - eq('abe', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: 'abcde' }); -testVim('insert', function(cm, vim, helpers) { - helpers.doKeys('i'); - eq('vim-insert', cm.getOption('keyMap')); - eq(false, cm.state.overwrite); - helpers.doKeys(''); - eq('vim-replace', cm.getOption('keyMap')); - eq(true, cm.state.overwrite); - helpers.doKeys(''); - eq('vim-insert', cm.getOption('keyMap')); - eq(false, cm.state.overwrite); -}); -testVim('i_backspace', function(cm, vim, helpers) { - cm.setCursor(0, 10); - helpers.doKeys('i'); - helpers.doInsertModeKeys('Backspace'); - helpers.assertCursorAt(0, 9); - eq('012345678', cm.getValue()); -}, { value: '0123456789'}); -testVim('i_overwrite_backspace', function(cm, vim, helpers) { - cm.setCursor(0, 10); - helpers.doKeys('i'); - helpers.doKeys(''); - helpers.doInsertModeKeys('Backspace'); - helpers.assertCursorAt(0, 9); - eq('0123456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('A', function(cm, vim, helpers) { - helpers.doKeys('A'); - helpers.assertCursorAt(0, lines[0].length); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('A_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', '2', 'j', 'l', 'l', 'A'); - var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' '); - replacement.pop(); - cm.replaceSelections(replacement); - eq('testhello\nmehello\npleahellose', cm.getValue()); - helpers.doKeys(''); - cm.setCursor(0, 0); - helpers.doKeys('.'); - // TODO this doesn't work yet - // eq('teshellothello\nme hello hello\nplehelloahellose', cm.getValue()); -}, {value: 'test\nme\nplease'}); -testVim('I', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('I'); - helpers.assertCursorAt(0, lines[0].textStart); - eq('vim-insert', cm.getOption('keyMap')); -}); -testVim('I_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('3', 'I'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - eq('testtesttestblah', cm.getValue()); - helpers.assertCursorAt(0, 11); -}, { value: 'blah' }); -testVim('I_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', 'l', 'l', 'I'); - var replacement = new Array(cm.listSelections().length+1).join('hello ').split(' '); - replacement.pop(); - cm.replaceSelections(replacement); - eq('hellotest\nhellome\nhelloplease', cm.getValue()); -}, {value: 'test\nme\nplease'}); -testVim('o', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('o'); - eq('word1\n\nword2', cm.getValue()); - helpers.assertCursorAt(1, 0); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'word1\nword2' }); -testVim('o_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('3', 'o'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - eq('\ntest\ntest\ntest', cm.getValue()); - helpers.assertCursorAt(3, 3); -}, { value: '' }); -testVim('O', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('O'); - eq('\nword1\nword2', cm.getValue()); - helpers.assertCursorAt(0, 0); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'word1\nword2' }); -testVim('J', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('J'); - var expectedValue = 'word1 word2\nword3\n word4'; - eq(expectedValue, cm.getValue()); - helpers.assertCursorAt(0, expectedValue.indexOf('word2') - 1); -}, { value: 'word1 \n word2\nword3\n word4' }); -testVim('J_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('3', 'J'); - var expectedValue = 'word1 word2 word3\n word4'; - eq(expectedValue, cm.getValue()); - helpers.assertCursorAt(0, expectedValue.indexOf('word3') - 1); -}, { value: 'word1 \n word2\nword3\n word4' }); -testVim('p', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false); - helpers.doKeys('p'); - eq('__abc\ndef_', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim('p_register', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().getRegister('a').setText('abc\ndef', false); - helpers.doKeys('"', 'a', 'p'); - eq('__abc\ndef_', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim('p_wrong_register', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().getRegister('a').setText('abc\ndef', false); - helpers.doKeys('p'); - eq('___', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: '___' }); -testVim('p_line', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true); - helpers.doKeys('2', 'p'); - eq('___\n a\nd\n a\nd', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim('p_lastline', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', ' a\nd', true); - helpers.doKeys('2', 'p'); - eq('___\n a\nd\n a\nd', cm.getValue()); - helpers.assertCursorAt(1, 2); -}, { value: '___' }); -testVim(']p_first_indent_is_smaller', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys(']', 'p'); - eq(' ___\n abc\n def', cm.getValue()); -}, { value: ' ___' }); -testVim(']p_first_indent_is_larger', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys(']', 'p'); - eq(' ___\n abc\ndef', cm.getValue()); -}, { value: ' ___' }); -testVim(']p_with_tab_indents', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', '\t\tabc\n\t\t\tdef\n', true); - helpers.doKeys(']', 'p'); - eq('\t___\n\tabc\n\t\tdef', cm.getValue()); -}, { value: '\t___', indentWithTabs: true}); -testVim(']p_with_spaces_translated_to_tabs', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys(']', 'p'); - eq('\t___\n\tabc\n\t\tdef', cm.getValue()); -}, { value: '\t___', indentWithTabs: true, tabSize: 2 }); -testVim('[p', function(cm, vim, helpers) { - helpers.getRegisterController().pushText('"', 'yank', ' abc\n def\n', true); - helpers.doKeys('[', 'p'); - eq(' abc\n def\n ___', cm.getValue()); -}, { value: ' ___' }); -testVim('P', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', 'abc\ndef', false); - helpers.doKeys('P'); - eq('_abc\ndef__', cm.getValue()); - helpers.assertCursorAt(1, 3); -}, { value: '___' }); -testVim('P_line', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.getRegisterController().pushText('"', 'yank', ' a\nd\n', true); - helpers.doKeys('2', 'P'); - eq(' a\nd\n a\nd\n___', cm.getValue()); - helpers.assertCursorAt(0, 2); -}, { value: '___' }); -testVim('r', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('3', 'r', 'u'); - eq('wuuuet\nanother', cm.getValue(),'3r failed'); - helpers.assertCursorAt(0, 3); - cm.setCursor(0, 4); - helpers.doKeys('v', 'j', 'h', 'r', ''); - eq('wuuu \n her', cm.getValue(),'Replacing selection by space-characters failed'); -}, { value: 'wordet\nanother' }); -testVim('r_visual_block', function(cm, vim, helpers) { - cm.setCursor(2, 3); - helpers.doKeys('', 'k', 'k', 'h', 'h', 'r', 'l'); - eq('1lll\n5lll\nalllefg', cm.getValue()); - helpers.doKeys('', 'l', 'j', 'r', ''); - eq('1 l\n5 l\nalllefg', cm.getValue()); - cm.setCursor(2, 0); - helpers.doKeys('o'); - helpers.doKeys(''); - cm.replaceRange('\t\t', cm.getCursor()); - helpers.doKeys('', 'h', 'h', 'r', 'r'); - eq('1 l\n5 l\nalllefg\nrrrrrrrr', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); -testVim('R', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('R'); - helpers.assertCursorAt(0, 1); - eq('vim-replace', cm.getOption('keyMap')); - is(cm.state.overwrite, 'Setting overwrite state failed'); -}); -testVim('mark', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys('`', 't'); - helpers.assertCursorAt(2, 2); - cm.setCursor(2, 0); - cm.replaceRange(' h', cm.getCursor()); - cm.setCursor(0, 0); - helpers.doKeys('\'', 't'); - helpers.assertCursorAt(2, 3); -}); -testVim('jumpToMark_next', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(2, 2); - cm.setCursor(0, 0); - helpers.doKeys(']', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_next_repeat', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(0, 0); - helpers.doKeys('2', ']', '`'); - helpers.assertCursorAt(3, 2); - cm.setCursor(0, 0); - helpers.doKeys('2', ']', '\''); - helpers.assertCursorAt(3, 1); -}); -testVim('jumpToMark_next_sameline', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(2, 2); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(2, 4); -}); -testVim('jumpToMark_next_onlyprev', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('m', 'a'); - cm.setCursor(4, 0); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(4, 0); -}); -testVim('jumpToMark_next_nomark', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys(']', '`'); - helpers.assertCursorAt(2, 2); - helpers.doKeys(']', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_next_linewise_over', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(2, 1); - helpers.doKeys(']', '\''); - helpers.assertCursorAt(3, 1); -}); -testVim('jumpToMark_next_action', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys('d', ']', '`'); - helpers.assertCursorAt(0, 0); - var actual = cm.getLine(0); - var expected = 'pop pop 0 1 2 3 4'; - eq(actual, expected, "Deleting while jumping to the next mark failed."); -}); -testVim('jumpToMark_next_line_action', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(0, 0); - helpers.doKeys('d', ']', '\''); - helpers.assertCursorAt(0, 1); - var actual = cm.getLine(0); - var expected = ' (a) [b] {c} ' - eq(actual, expected, "Deleting while jumping to the next mark line failed."); -}); -testVim('jumpToMark_prev', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 't'); - cm.setCursor(4, 0); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 2); - cm.setCursor(4, 0); - helpers.doKeys('[', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_repeat', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(5, 0); - helpers.doKeys('2', '[', '`'); - helpers.assertCursorAt(3, 2); - cm.setCursor(5, 0); - helpers.doKeys('2', '[', '\''); - helpers.assertCursorAt(3, 1); -}); -testVim('jumpToMark_prev_sameline', function(cm, vim, helpers) { - cm.setCursor(2, 0); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(2, 2); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_onlynext', function(cm, vim, helpers) { - cm.setCursor(4, 4); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 0); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_nomark', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('[', '`'); - helpers.assertCursorAt(2, 2); - helpers.doKeys('[', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('jumpToMark_prev_linewise_over', function(cm, vim, helpers) { - cm.setCursor(2, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(3, 4); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 6); - helpers.doKeys('[', '\''); - helpers.assertCursorAt(2, 0); -}); -testVim('delmark_single', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 't'); - helpers.doEx('delmarks t'); - cm.setCursor(0, 0); - helpers.doKeys('`', 't'); - helpers.assertCursorAt(0, 0); -}); -testVim('delmark_range', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks b-d'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(5, 2); -}); -testVim('delmark_multi', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks bcd'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(5, 2); -}); -testVim('delmark_multi_space', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks b c d'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(1, 2); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(5, 2); -}); -testVim('delmark_all', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('m', 'a'); - cm.setCursor(2, 2); - helpers.doKeys('m', 'b'); - cm.setCursor(3, 2); - helpers.doKeys('m', 'c'); - cm.setCursor(4, 2); - helpers.doKeys('m', 'd'); - cm.setCursor(5, 2); - helpers.doKeys('m', 'e'); - helpers.doEx('delmarks a b-de'); - cm.setCursor(0, 0); - helpers.doKeys('`', 'a'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'b'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'c'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'd'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('`', 'e'); - helpers.assertCursorAt(0, 0); -}); -testVim('visual', function(cm, vim, helpers) { - helpers.doKeys('l', 'v', 'l', 'l'); - helpers.assertCursorAt(0, 4); - eqPos(makeCursor(0, 1), cm.getCursor('anchor')); - helpers.doKeys('d'); - eq('15', cm.getValue()); -}, { value: '12345' }); -testVim('visual_yank', function(cm, vim, helpers) { - helpers.doKeys('v', '3', 'l', 'y'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('p'); - eq('aa te test for yank', cm.getValue()); -}, { value: 'a test for yank' }) -testVim('visual_w', function(cm, vim, helpers) { - helpers.doKeys('v', 'w'); - eq(cm.getSelection(), 'motion t'); -}, { value: 'motion test'}); -testVim('visual_initial_selection', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('v'); - cm.getSelection('n'); -}, { value: 'init'}); -testVim('visual_crossover_left', function(cm, vim, helpers) { - cm.setCursor(0, 2); - helpers.doKeys('v', 'l', 'h', 'h'); - cm.getSelection('ro'); -}, { value: 'cross'}); -testVim('visual_crossover_left', function(cm, vim, helpers) { - cm.setCursor(0, 2); - helpers.doKeys('v', 'h', 'l', 'l'); - cm.getSelection('os'); -}, { value: 'cross'}); -testVim('visual_crossover_up', function(cm, vim, helpers) { - cm.setCursor(3, 2); - helpers.doKeys('v', 'j', 'k', 'k'); - eqPos(Pos(2, 2), cm.getCursor('head')); - eqPos(Pos(3, 3), cm.getCursor('anchor')); - helpers.doKeys('k'); - eqPos(Pos(1, 2), cm.getCursor('head')); - eqPos(Pos(3, 3), cm.getCursor('anchor')); -}, { value: 'cross\ncross\ncross\ncross\ncross\n'}); -testVim('visual_crossover_down', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('v', 'k', 'j', 'j'); - eqPos(Pos(2, 3), cm.getCursor('head')); - eqPos(Pos(1, 2), cm.getCursor('anchor')); - helpers.doKeys('j'); - eqPos(Pos(3, 3), cm.getCursor('head')); - eqPos(Pos(1, 2), cm.getCursor('anchor')); -}, { value: 'cross\ncross\ncross\ncross\ncross\n'}); -testVim('visual_exit', function(cm, vim, helpers) { - helpers.doKeys('', 'l', 'j', 'j', ''); - eqPos(cm.getCursor('anchor'), cm.getCursor('head')); - eq(vim.visualMode, false); -}, { value: 'hello\nworld\nfoo' }); -testVim('visual_line', function(cm, vim, helpers) { - helpers.doKeys('l', 'V', 'l', 'j', 'j', 'd'); - eq(' 4\n 5', cm.getValue()); -}, { value: ' 1\n 2\n 3\n 4\n 5' }); -testVim('visual_block_move_to_eol', function(cm, vim, helpers) { - // moveToEol should move all block cursors to end of line - cm.setCursor(0, 0); - helpers.doKeys('', 'G', '$'); - var selections = cm.getSelections().join(); - eq('123,45,6', selections); - // Checks that with cursor at Infinity, finding words backwards still works. - helpers.doKeys('2', 'k', 'b'); - selections = cm.getSelections().join(); - eq('1', selections); -}, {value: '123\n45\n6'}); -testVim('visual_block_different_line_lengths', function(cm, vim, helpers) { - // test the block selection with lines of different length - // i.e. extending the selection - // till the end of the longest line. - helpers.doKeys('', 'l', 'j', 'j', '6', 'l', 'd'); - helpers.doKeys('d', 'd', 'd', 'd'); - eq('', cm.getValue()); -}, {value: '1234\n5678\nabcdefg'}); -testVim('visual_block_truncate_on_short_line', function(cm, vim, helpers) { - // check for left side selection in case - // of moving up to a shorter line. - cm.replaceRange('', cm.getCursor()); - cm.setCursor(3, 4); - helpers.doKeys('', 'l', 'k', 'k', 'd'); - eq('hello world\n{\ntis\nsa!', cm.getValue()); -}, {value: 'hello world\n{\nthis is\nsparta!'}); -testVim('visual_block_corners', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('', '2', 'l', 'k'); - // circle around the anchor - // and check the selections - var selections = cm.getSelections(); - eq('345891', selections.join('')); - helpers.doKeys('4', 'h'); - selections = cm.getSelections(); - eq('123678', selections.join('')); - helpers.doKeys('j', 'j'); - selections = cm.getSelections(); - eq('678abc', selections.join('')); - helpers.doKeys('4', 'l'); - selections = cm.getSelections(); - eq('891cde', selections.join('')); -}, {value: '12345\n67891\nabcde'}); -testVim('visual_block_mode_switch', function(cm, vim, helpers) { - // switch between visual modes - cm.setCursor(1, 1); - // blockwise to characterwise visual - helpers.doKeys('', 'j', 'l', 'v'); - var selections = cm.getSelections(); - eq('7891\nabc', selections.join('')); - // characterwise to blockwise - helpers.doKeys(''); - selections = cm.getSelections(); - eq('78bc', selections.join('')); - // blockwise to linewise visual - helpers.doKeys('V'); - selections = cm.getSelections(); - eq('67891\nabcde', selections.join('')); -}, {value: '12345\n67891\nabcde'}); -testVim('visual_block_crossing_short_line', function(cm, vim, helpers) { - // visual block with long and short lines - cm.setCursor(0, 3); - helpers.doKeys('', 'j', 'j', 'j'); - var selections = cm.getSelections().join(); - eq('4,,d,b', selections); - helpers.doKeys('3', 'k'); - selections = cm.getSelections().join(); - eq('4', selections); - helpers.doKeys('5', 'j', 'k'); - selections = cm.getSelections().join(""); - eq(10, selections.length); -}, {value: '123456\n78\nabcdefg\nfoobar\n}\n'}); -testVim('visual_block_curPos_on_exit', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '3' , 'l', ''); - eqPos(makeCursor(0, 3), cm.getCursor()); - helpers.doKeys('h', '', '2' , 'j' ,'3' , 'l'); - eq(cm.getSelections().join(), "3456,,cdef"); - helpers.doKeys('4' , 'h'); - eq(cm.getSelections().join(), "23,8,bc"); - helpers.doKeys('2' , 'l'); - eq(cm.getSelections().join(), "34,,cd"); -}, {value: '123456\n78\nabcdefg\nfoobar'}); - -testVim('visual_marks', function(cm, vim, helpers) { - helpers.doKeys('l', 'v', 'l', 'l', 'j', 'j', 'v'); - // Test visual mode marks - cm.setCursor(2, 1); - helpers.doKeys('\'', '<'); - helpers.assertCursorAt(0, 1); - helpers.doKeys('\'', '>'); - helpers.assertCursorAt(2, 0); -}); -testVim('visual_join', function(cm, vim, helpers) { - helpers.doKeys('l', 'V', 'l', 'j', 'j', 'J'); - eq(' 1 2 3\n 4\n 5', cm.getValue()); - is(!vim.visualMode); -}, { value: ' 1\n 2\n 3\n 4\n 5' }); -testVim('visual_join_2', function(cm, vim, helpers) { - helpers.doKeys('G', 'V', 'g', 'g', 'J'); - eq('1 2 3 4 5 6 ', cm.getValue()); - is(!vim.visualMode); -}, { value: '1\n2\n3\n4\n5\n6\n'}); -testVim('visual_blank', function(cm, vim, helpers) { - helpers.doKeys('v', 'k'); - eq(vim.visualMode, true); -}, { value: '\n' }); -testVim('reselect_visual', function(cm, vim, helpers) { - helpers.doKeys('l', 'v', 'l', 'l', 'l', 'y', 'g', 'v'); - helpers.assertCursorAt(0, 5); - eqPos(makeCursor(0, 1), cm.getCursor('anchor')); - helpers.doKeys('v'); - cm.setCursor(1, 0); - helpers.doKeys('v', 'l', 'l', 'p'); - eq('123456\n2345\nbar', cm.getValue()); - cm.setCursor(0, 0); - helpers.doKeys('g', 'v'); - // here the fake cursor is at (1, 3) - helpers.assertCursorAt(1, 4); - eqPos(makeCursor(1, 0), cm.getCursor('anchor')); - helpers.doKeys('v'); - cm.setCursor(2, 0); - helpers.doKeys('v', 'l', 'l', 'g', 'v'); - helpers.assertCursorAt(1, 4); - eqPos(makeCursor(1, 0), cm.getCursor('anchor')); - helpers.doKeys('g', 'v'); - helpers.assertCursorAt(2, 3); - eqPos(makeCursor(2, 0), cm.getCursor('anchor')); - eq('123456\n2345\nbar', cm.getValue()); -}, { value: '123456\nfoo\nbar' }); -testVim('reselect_visual_line', function(cm, vim, helpers) { - helpers.doKeys('l', 'V', 'j', 'j', 'V', 'g', 'v', 'd'); - eq('foo\nand\nbar', cm.getValue()); - cm.setCursor(1, 0); - helpers.doKeys('V', 'y', 'j'); - helpers.doKeys('V', 'p' , 'g', 'v', 'd'); - eq('foo\nand', cm.getValue()); -}, { value: 'hello\nthis\nis\nfoo\nand\nbar' }); -testVim('reselect_visual_block', function(cm, vim, helpers) { - cm.setCursor(1, 2); - helpers.doKeys('', 'k', 'h', ''); - cm.setCursor(2, 1); - helpers.doKeys('v', 'l', 'g', 'v'); - eqPos(Pos(1, 2), vim.sel.anchor); - eqPos(Pos(0, 1), vim.sel.head); - // Ensure selection is done with visual block mode rather than one - // continuous range. - eq(cm.getSelections().join(''), '23oo') - helpers.doKeys('g', 'v'); - eqPos(Pos(2, 1), vim.sel.anchor); - eqPos(Pos(2, 2), vim.sel.head); - helpers.doKeys(''); - // Ensure selection of deleted range - cm.setCursor(1, 1); - helpers.doKeys('v', '', 'j', 'd', 'g', 'v'); - eq(cm.getSelections().join(''), 'or'); -}, { value: '123456\nfoo\nbar' }); -testVim('s_normal', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('s'); - helpers.doKeys(''); - eq('ac', cm.getValue()); -}, { value: 'abc'}); -testVim('s_visual', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('v', 's'); - helpers.doKeys(''); - helpers.assertCursorAt(0, 0); - eq('ac', cm.getValue()); -}, { value: 'abc'}); -testVim('o_visual', function(cm, vim, helpers) { - cm.setCursor(0,0); - helpers.doKeys('v','l','l','l','o'); - helpers.assertCursorAt(0,0); - helpers.doKeys('v','v','j','j','j','o'); - helpers.assertCursorAt(0,0); - helpers.doKeys('O'); - helpers.doKeys('l','l') - helpers.assertCursorAt(3, 3); - helpers.doKeys('d'); - eq('p',cm.getValue()); -}, { value: 'abcd\nefgh\nijkl\nmnop'}); -testVim('o_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('','3','j','l','l', 'o'); - eqPos(Pos(3, 3), vim.sel.anchor); - eqPos(Pos(0, 1), vim.sel.head); - helpers.doKeys('O'); - eqPos(Pos(3, 1), vim.sel.anchor); - eqPos(Pos(0, 3), vim.sel.head); - helpers.doKeys('o'); - eqPos(Pos(0, 3), vim.sel.anchor); - eqPos(Pos(3, 1), vim.sel.head); -}, { value: 'abcd\nefgh\nijkl\nmnop'}); -testVim('changeCase_visual', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('v', 'l', 'l'); - helpers.doKeys('U'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('v', 'l', 'l'); - helpers.doKeys('u'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('l', 'l', 'l', '.'); - helpers.assertCursorAt(0, 3); - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 'v', 'j', 'U', 'q'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('j', '@', 'a'); - helpers.assertCursorAt(1, 0); - cm.setCursor(3, 0); - helpers.doKeys('V', 'U', 'j', '.'); - eq('ABCDEF\nGHIJKL\nMnopq\nSHORT LINE\nLONG LINE OF TEXT', cm.getValue()); -}, { value: 'abcdef\nghijkl\nmnopq\nshort line\nlong line of text'}); -testVim('changeCase_visual_block', function(cm, vim, helpers) { - cm.setCursor(2, 1); - helpers.doKeys('', 'k', 'k', 'h', 'U'); - eq('ABcdef\nGHijkl\nMNopq\nfoo', cm.getValue()); - cm.setCursor(0, 2); - helpers.doKeys('.'); - eq('ABCDef\nGHIJkl\nMNOPq\nfoo', cm.getValue()); - // check when last line is shorter. - cm.setCursor(2, 2); - helpers.doKeys('.'); - eq('ABCDef\nGHIJkl\nMNOPq\nfoO', cm.getValue()); -}, { value: 'abcdef\nghijkl\nmnopq\nfoo'}); -testVim('visual_paste', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('v', 'l', 'l', 'y'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('3', 'l', 'j', 'v', 'l', 'p'); - helpers.assertCursorAt(1, 5); - eq('this is a\nunithitest for visual paste', cm.getValue()); - cm.setCursor(0, 0); - // in case of pasting whole line - helpers.doKeys('y', 'y'); - cm.setCursor(1, 6); - helpers.doKeys('v', 'l', 'l', 'l', 'p'); - helpers.assertCursorAt(2, 0); - eq('this is a\nunithi\nthis is a\n for visual paste', cm.getValue()); -}, { value: 'this is a\nunit test for visual paste'}); - -// This checks the contents of the register used to paste the text -testVim('v_paste_from_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'w'); - cm.setCursor(1, 0); - helpers.doKeys('v', 'p'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+register/.test(text)); - }); -}, { value: 'register contents\nare not erased'}); -testVim('S_normal', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('j', 'S'); - helpers.doKeys(''); - helpers.assertCursorAt(1, 1); - eq('aa{\n \ncc', cm.getValue()); - helpers.doKeys('j', 'S'); - eq('aa{\n \n ', cm.getValue()); - helpers.assertCursorAt(2, 2); - helpers.doKeys(''); - helpers.doKeys('d', 'd', 'd', 'd'); - helpers.assertCursorAt(0, 0); - helpers.doKeys('S'); - is(vim.insertMode); - eq('', cm.getValue()); -}, { value: 'aa{\nbb\ncc'}); -testVim('blockwise_paste', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '3', 'j', 'l', 'y'); - cm.setCursor(0, 2); - // paste one char after the current cursor position - helpers.doKeys('p'); - eq('helhelo\nworwold\nfoofo\nbarba', cm.getValue()); - cm.setCursor(0, 0); - helpers.doKeys('v', '4', 'l', 'y'); - cm.setCursor(0, 0); - helpers.doKeys('', '3', 'j', 'p'); - eq('helheelhelo\norwold\noofo\narba', cm.getValue()); -}, { value: 'hello\nworld\nfoo\nbar'}); -testVim('blockwise_paste_long/short_line', function(cm, vim, helpers) { - // extend short lines in case of different line lengths. - cm.setCursor(0, 0); - helpers.doKeys('', 'j', 'j', 'y'); - cm.setCursor(0, 3); - helpers.doKeys('p'); - eq('hellho\nfoo f\nbar b', cm.getValue()); -}, { value: 'hello\nfoo\nbar'}); -testVim('blockwise_paste_cut_paste', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', 'x'); - cm.setCursor(0, 0); - helpers.doKeys('P'); - eq('cut\nand\npaste\nme', cm.getValue()); -}, { value: 'cut\nand\npaste\nme'}); -testVim('blockwise_paste_from_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', '"', 'a', 'y'); - cm.setCursor(0, 3); - helpers.doKeys('"', 'a', 'p'); - eq('foobfar\nhellho\nworlwd', cm.getValue()); -}, { value: 'foobar\nhello\nworld'}); -testVim('blockwise_paste_last_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', '2', 'j', 'l', 'y'); - cm.setCursor(3, 0); - helpers.doKeys('p'); - eq('cut\nand\npaste\nmcue\n an\n pa', cm.getValue()); -}, { value: 'cut\nand\npaste\nme'}); - -testVim('S_visual', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('v', 'j', 'S'); - helpers.doKeys(''); - helpers.assertCursorAt(0, 0); - eq('\ncc', cm.getValue()); -}, { value: 'aa\nbb\ncc'}); - -testVim('d_/', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('match'); - helpers.doKeys('2', 'd', '/'); - helpers.assertCursorAt(0, 0); - eq('match \n next', cm.getValue()); - cm.openDialog = helpers.fakeOpenDialog('2'); - helpers.doKeys('d', ':'); - // TODO eq(' next', cm.getValue()); -}, { value: 'text match match \n next' }); -testVim('/ and n/N', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('match'); - helpers.doKeys('/'); - helpers.assertCursorAt(0, 11); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 6); - helpers.doKeys('N'); - helpers.assertCursorAt(0, 11); - - cm.setCursor(0, 0); - helpers.doKeys('2', '/'); - helpers.assertCursorAt(1, 6); -}, { value: 'match nope match \n nope Match' }); -testVim('/_case', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('Match'); - helpers.doKeys('/'); - helpers.assertCursorAt(1, 6); -}, { value: 'match nope match \n nope Match' }); -testVim('/_2_pcre', function(cm, vim, helpers) { - CodeMirror.Vim.setOption('pcre', true); - cm.openDialog = helpers.fakeOpenDialog('(word){2}'); - helpers.doKeys('/'); - helpers.assertCursorAt(1, 9); - helpers.doKeys('n'); - helpers.assertCursorAt(2, 1); -}, { value: 'word\n another wordword\n wordwordword\n' }); -testVim('/_2_nopcre', function(cm, vim, helpers) { - CodeMirror.Vim.setOption('pcre', false); - cm.openDialog = helpers.fakeOpenDialog('\\(word\\)\\{2}'); - helpers.doKeys('/'); - helpers.assertCursorAt(1, 9); - helpers.doKeys('n'); - helpers.assertCursorAt(2, 1); -}, { value: 'word\n another wordword\n wordwordword\n' }); -testVim('/_nongreedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('aa'); - helpers.doKeys('/'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('?_nongreedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('aa'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('/_greedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a+'); - helpers.doKeys('/'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('?_greedy', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a+'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa \n a aa'}); -testVim('/_greedy_0_or_more', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a*'); - helpers.doKeys('/'); - helpers.assertCursorAt(0, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 5); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 0); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa\n aa'}); -testVim('?_greedy_0_or_more', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('a*'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 1); - helpers.doKeys('n'); - helpers.assertCursorAt(1, 0); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 5); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 3); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 0); -}, { value: 'aaa aa\n aa'}); -testVim('? and n/N', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('match'); - helpers.doKeys('?'); - helpers.assertCursorAt(1, 6); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 11); - helpers.doKeys('N'); - helpers.assertCursorAt(1, 6); - - cm.setCursor(0, 0); - helpers.doKeys('2', '?'); - helpers.assertCursorAt(0, 11); -}, { value: 'match nope match \n nope Match' }); -testVim('*', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('*'); - helpers.assertCursorAt(0, 22); - - cm.setCursor(0, 9); - helpers.doKeys('2', '*'); - helpers.assertCursorAt(1, 8); -}, { value: 'nomatch match nomatch match \nnomatch Match' }); -testVim('*_no_word', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('*'); - helpers.assertCursorAt(0, 0); -}, { value: ' \n match \n' }); -testVim('*_symbol', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('*'); - helpers.assertCursorAt(1, 0); -}, { value: ' /}\n/} match \n' }); -testVim('#', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('#'); - helpers.assertCursorAt(1, 8); - - cm.setCursor(0, 9); - helpers.doKeys('2', '#'); - helpers.assertCursorAt(0, 22); -}, { value: 'nomatch match nomatch match \nnomatch Match' }); -testVim('*_seek', function(cm, vim, helpers) { - // Should skip over space and symbols. - cm.setCursor(0, 3); - helpers.doKeys('*'); - helpers.assertCursorAt(0, 22); -}, { value: ' := match nomatch match \nnomatch Match' }); -testVim('#', function(cm, vim, helpers) { - // Should skip over space and symbols. - cm.setCursor(0, 3); - helpers.doKeys('#'); - helpers.assertCursorAt(1, 8); -}, { value: ' := match nomatch match \nnomatch Match' }); -testVim('g*', function(cm, vim, helpers) { - cm.setCursor(0, 8); - helpers.doKeys('g', '*'); - helpers.assertCursorAt(0, 18); - cm.setCursor(0, 8); - helpers.doKeys('3', 'g', '*'); - helpers.assertCursorAt(1, 8); -}, { value: 'matches match alsoMatch\nmatchme matching' }); -testVim('g#', function(cm, vim, helpers) { - cm.setCursor(0, 8); - helpers.doKeys('g', '#'); - helpers.assertCursorAt(0, 0); - cm.setCursor(0, 8); - helpers.doKeys('3', 'g', '#'); - helpers.assertCursorAt(1, 0); -}, { value: 'matches match alsoMatch\nmatchme matching' }); -testVim('macro_insert', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', '0', 'i'); - cm.replaceRange('foo', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q', '@', 'a'); - eq('foofoo', cm.getValue()); -}, { value: ''}); -testVim('macro_insert_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', '$', 'a'); - cm.replaceRange('larry.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('a'); - cm.replaceRange('curly.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('a'); - cm.replaceRange('moe.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('@', 'a'); - // At this point, the most recent edit should be the 2nd insert change - // inside the macro, i.e. "curly.". - helpers.doKeys('.'); - eq('larry.curly.moe.larry.curly.curly.', cm.getValue()); -}, { value: ''}); -testVim('macro_space', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('', ''); - helpers.assertCursorAt(0, 2); - helpers.doKeys('q', 'a', '', '', 'q'); - helpers.assertCursorAt(0, 4); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0, 6); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0, 8); -}, { value: 'one line of text.'}); -testVim('macro_t_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 't', 'e', 'q'); - helpers.assertCursorAt(0, 1); - helpers.doKeys('l', '@', 'a'); - helpers.assertCursorAt(0, 6); - helpers.doKeys('l', ';'); - helpers.assertCursorAt(0, 12); -}, { value: 'one line of text.'}); -testVim('macro_f_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'b', 'f', 'e', 'q'); - helpers.assertCursorAt(0, 2); - helpers.doKeys('@', 'b'); - helpers.assertCursorAt(0, 7); - helpers.doKeys(';'); - helpers.assertCursorAt(0, 13); -}, { value: 'one line of text.'}); -testVim('macro_slash_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'c'); - cm.openDialog = helpers.fakeOpenDialog('e'); - helpers.doKeys('/', 'q'); - helpers.assertCursorAt(0, 2); - helpers.doKeys('@', 'c'); - helpers.assertCursorAt(0, 7); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 13); -}, { value: 'one line of text.'}); -testVim('macro_multislash_search', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'd'); - cm.openDialog = helpers.fakeOpenDialog('e'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('t'); - helpers.doKeys('/', 'q'); - helpers.assertCursorAt(0, 12); - helpers.doKeys('@', 'd'); - helpers.assertCursorAt(0, 15); -}, { value: 'one line of text to rule them all.'}); -testVim('macro_last_ex_command_register', function (cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doEx('s/a/b'); - helpers.doKeys('2', '@', ':'); - eq('bbbaa', cm.getValue()); - helpers.assertCursorAt(0, 2); -}, { value: 'aaaaa'}); -testVim('macro_parens', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'z', 'i'); - cm.replaceRange('(', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('e', 'a'); - cm.replaceRange(')', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('w', '@', 'z'); - helpers.doKeys('w', '@', 'z'); - eq('(see) (spot) (run)', cm.getValue()); -}, { value: 'see spot run'}); -testVim('macro_overwrite', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'z', '0', 'i'); - cm.replaceRange('I ', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('e'); - // Now replace the macro with something else. - helpers.doKeys('q', 'z', 'a'); - cm.replaceRange('.', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('e', '@', 'z'); - helpers.doKeys('e', '@', 'z'); - eq('I see. spot. run.', cm.getValue()); -}, { value: 'see spot run'}); -testVim('macro_search_f', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 'f', ' '); - helpers.assertCursorAt(0,3); - helpers.doKeys('q', '0'); - helpers.assertCursorAt(0,0); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0,3); -}, { value: 'The quick brown fox jumped over the lazy dog.'}); -testVim('macro_search_2f', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', '2', 'f', ' '); - helpers.assertCursorAt(0,9); - helpers.doKeys('q', '0'); - helpers.assertCursorAt(0,0); - helpers.doKeys('@', 'a'); - helpers.assertCursorAt(0,9); -}, { value: 'The quick brown fox jumped over the lazy dog.'}); -testVim('yank_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'y'); - helpers.doKeys('j', '"', 'b', 'y', 'y'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo/.test(text)); - is(/b\s+bar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_visual_block', function(cm, vim, helpers) { - cm.setCursor(0, 1); - helpers.doKeys('', 'l', 'j', '"', 'a', 'y'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+oo\nar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_line_to_line_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'y'); - helpers.doKeys('j', '"', 'A', 'y', 'y'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo\nbar/.test(text)); - is(/"\s+foo\nbar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_word_to_word_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'w'); - helpers.doKeys('j', '"', 'A', 'y', 'w'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foobar/.test(text)); - is(/"\s+foobar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_line_to_word_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'w'); - helpers.doKeys('j', '"', 'A', 'y', 'y'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo\nbar/.test(text)); - is(/"\s+foo\nbar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('yank_append_word_to_line_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('"', 'a', 'y', 'y'); - helpers.doKeys('j', '"', 'A', 'y', 'w'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+foo\nbar/.test(text)); - is(/"\s+foo\nbar/.test(text)); - }); - helpers.doKeys(':'); -}, { value: 'foo\nbar'}); -testVim('macro_register', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('q', 'a', 'i'); - cm.replaceRange('gangnam', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - helpers.doKeys('q', 'b', 'o'); - cm.replaceRange('style', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('q'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/a\s+i/.test(text)); - is(/b\s+o/.test(text)); - }); - helpers.doKeys(':'); -}, { value: ''}); -testVim('._register', function(cm,vim,helpers) { - cm.setCursor(0,0); - helpers.doKeys('i'); - cm.replaceRange('foo',cm.getCursor()); - helpers.doKeys(''); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/\.\s+foo/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim(':_register', function(cm,vim,helpers) { - helpers.doEx('bar'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/:\s+bar/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim('search_register_escape', function(cm, vim, helpers) { - // Check that the register is restored if the user escapes rather than confirms. - cm.openDialog = helpers.fakeOpenDialog('waldo'); - helpers.doKeys('/'); - var onKeyDown; - var onKeyUp; - var KEYCODES = { - f: 70, - o: 79, - Esc: 27 - }; - cm.openDialog = function(template, callback, options) { - onKeyDown = options.onKeyDown; - onKeyUp = options.onKeyUp; - }; - var close = function() {}; - helpers.doKeys('/'); - // Fake some keyboard events coming in. - onKeyDown({keyCode: KEYCODES.f}, '', close); - onKeyUp({keyCode: KEYCODES.f}, '', close); - onKeyDown({keyCode: KEYCODES.o}, 'f', close); - onKeyUp({keyCode: KEYCODES.o}, 'f', close); - onKeyDown({keyCode: KEYCODES.o}, 'fo', close); - onKeyUp({keyCode: KEYCODES.o}, 'fo', close); - onKeyDown({keyCode: KEYCODES.Esc}, 'foo', close); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/waldo/.test(text)); - is(!/foo/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim('search_register', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('foo'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('registers'); - cm.openNotification = helpers.fakeOpenNotification(function(text) { - is(/\/\s+foo/.test(text)); - }); - helpers.doKeys(':'); -}, {value: ''}); -testVim('search_history', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('this'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('checks'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('search'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('history'); - helpers.doKeys('/'); - cm.openDialog = helpers.fakeOpenDialog('checks'); - helpers.doKeys('/'); - var onKeyDown; - var onKeyUp; - var query = ''; - var keyCodes = { - Up: 38, - Down: 40 - }; - cm.openDialog = function(template, callback, options) { - onKeyUp = options.onKeyUp; - onKeyDown = options.onKeyDown; - }; - var close = function(newVal) { - if (typeof newVal == 'string') query = newVal; - } - helpers.doKeys('/'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'checks'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'history'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'search'); - onKeyDown({keyCode: keyCodes.Up}, query, close); - onKeyUp({keyCode: keyCodes.Up}, query, close); - eq(query, 'this'); - onKeyDown({keyCode: keyCodes.Down}, query, close); - onKeyUp({keyCode: keyCodes.Down}, query, close); - eq(query, 'search'); -}, {value: ''}); -testVim('exCommand_history', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('registers'); - helpers.doKeys(':'); - cm.openDialog = helpers.fakeOpenDialog('sort'); - helpers.doKeys(':'); - cm.openDialog = helpers.fakeOpenDialog('map'); - helpers.doKeys(':'); - cm.openDialog = helpers.fakeOpenDialog('invalid'); - helpers.doKeys(':'); - var onKeyDown; - var onKeyUp; - var input = ''; - var keyCodes = { - Up: 38, - Down: 40, - s: 115 - }; - cm.openDialog = function(template, callback, options) { - onKeyUp = options.onKeyUp; - onKeyDown = options.onKeyDown; - }; - var close = function(newVal) { - if (typeof newVal == 'string') input = newVal; - } - helpers.doKeys(':'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'invalid'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'map'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'sort'); - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'registers'); - onKeyDown({keyCode: keyCodes.s}, '', close); - input = 's'; - onKeyDown({keyCode: keyCodes.Up}, input, close); - eq(input, 'sort'); -}, {value: ''}); -testVim('search_clear', function(cm, vim, helpers) { - var onKeyDown; - var input = ''; - var keyCodes = { - Ctrl: 17, - u: 85 - }; - cm.openDialog = function(template, callback, options) { - onKeyDown = options.onKeyDown; - }; - var close = function(newVal) { - if (typeof newVal == 'string') input = newVal; - } - helpers.doKeys('/'); - input = 'foo'; - onKeyDown({keyCode: keyCodes.Ctrl}, input, close); - onKeyDown({keyCode: keyCodes.u, ctrlKey: true}, input, close); - eq(input, ''); -}); -testVim('exCommand_clear', function(cm, vim, helpers) { - var onKeyDown; - var input = ''; - var keyCodes = { - Ctrl: 17, - u: 85 - }; - cm.openDialog = function(template, callback, options) { - onKeyDown = options.onKeyDown; - }; - var close = function(newVal) { - if (typeof newVal == 'string') input = newVal; - } - helpers.doKeys(':'); - input = 'foo'; - onKeyDown({keyCode: keyCodes.Ctrl}, input, close); - onKeyDown({keyCode: keyCodes.u, ctrlKey: true}, input, close); - eq(input, ''); -}); -testVim('.', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('2', 'd', 'w'); - helpers.doKeys('.'); - eq('5 6', cm.getValue()); -}, { value: '1 2 3 4 5 6'}); -testVim('._repeat', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('2', 'd', 'w'); - helpers.doKeys('3', '.'); - eq('6', cm.getValue()); -}, { value: '1 2 3 4 5 6'}); -testVim('._insert', function(cm, vim, helpers) { - helpers.doKeys('i'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('testestt', cm.getValue()); - helpers.assertCursorAt(0, 6); - helpers.doKeys('O'); - cm.replaceRange('xyz', cm.getCursor()); - helpers.doInsertModeKeys('Backspace'); - helpers.doInsertModeKeys('Down'); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('xy\nxy\ntestestt', cm.getValue()); - helpers.assertCursorAt(1, 1); -}, { value: ''}); -testVim('._insert_repeat', function(cm, vim, helpers) { - helpers.doKeys('i'); - cm.replaceRange('test', cm.getCursor()); - cm.setCursor(0, 4); - helpers.doKeys(''); - helpers.doKeys('2', '.'); - eq('testesttestt', cm.getValue()); - helpers.assertCursorAt(0, 10); -}, { value: ''}); -testVim('._repeat_insert', function(cm, vim, helpers) { - helpers.doKeys('3', 'i'); - cm.replaceRange('te', cm.getCursor()); - cm.setCursor(0, 2); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('tetettetetee', cm.getValue()); - helpers.assertCursorAt(0, 10); -}, { value: ''}); -testVim('._insert_o', function(cm, vim, helpers) { - helpers.doKeys('o'); - cm.replaceRange('z', cm.getCursor()); - cm.setCursor(1, 1); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('\nz\nz', cm.getValue()); - helpers.assertCursorAt(2, 0); -}, { value: ''}); -testVim('._insert_o_repeat', function(cm, vim, helpers) { - helpers.doKeys('o'); - cm.replaceRange('z', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(1, 0); - helpers.doKeys('2', '.'); - eq('\nz\nz\nz', cm.getValue()); - helpers.assertCursorAt(3, 0); -}, { value: ''}); -testVim('._insert_o_indent', function(cm, vim, helpers) { - helpers.doKeys('o'); - cm.replaceRange('z', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(1, 2); - helpers.doKeys('.'); - eq('{\n z\n z', cm.getValue()); - helpers.assertCursorAt(2, 2); -}, { value: '{'}); -testVim('._insert_cw', function(cm, vim, helpers) { - helpers.doKeys('c', 'w'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(0, 3); - helpers.doKeys('2', 'l'); - helpers.doKeys('.'); - eq('test test word3', cm.getValue()); - helpers.assertCursorAt(0, 8); -}, { value: 'word1 word2 word3' }); -testVim('._insert_cw_repeat', function(cm, vim, helpers) { - // For some reason, repeat cw in desktop VIM will does not repeat insert mode - // changes. Will conform to that behavior. - helpers.doKeys('c', 'w'); - cm.replaceRange('test', cm.getCursor()); - helpers.doKeys(''); - cm.setCursor(0, 4); - helpers.doKeys('l'); - helpers.doKeys('2', '.'); - eq('test test', cm.getValue()); - helpers.assertCursorAt(0, 8); -}, { value: 'word1 word2 word3' }); -testVim('._delete', function(cm, vim, helpers) { - cm.setCursor(0, 5); - helpers.doKeys('i'); - helpers.doInsertModeKeys('Backspace'); - helpers.doKeys(''); - helpers.doKeys('.'); - eq('zace', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: 'zabcde'}); -testVim('._delete_repeat', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('i'); - helpers.doInsertModeKeys('Backspace'); - helpers.doKeys(''); - helpers.doKeys('2', '.'); - eq('zzce', cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: 'zzabcde'}); -testVim('._visual_>', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('V', 'j', '>'); - cm.setCursor(2, 0) - helpers.doKeys('.'); - eq(' 1\n 2\n 3\n 4', cm.getValue()); - helpers.assertCursorAt(2, 2); -}, { value: '1\n2\n3\n4'}); -testVim('f;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(9, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('F;', function(cm, vim, helpers) { - cm.setCursor(0, 8); - helpers.doKeys('F', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(2, cm.getCursor().ch); -}, { value: '01x3xx6x8x'}); -testVim('t;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(8, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('T;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', 'x'); - helpers.doKeys(';'); - helpers.doKeys('2', ';'); - eq(2, cm.getCursor().ch); -}, { value: '0xx3xx678x'}); -testVim('f,', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('f', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(2, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('F,', function(cm, vim, helpers) { - cm.setCursor(0, 3); - helpers.doKeys('F', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(9, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('t,', function(cm, vim, helpers) { - cm.setCursor(0, 6); - helpers.doKeys('t', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(3, cm.getCursor().ch); -}, { value: '01x3xx678x'}); -testVim('T,', function(cm, vim, helpers) { - cm.setCursor(0, 4); - helpers.doKeys('T', 'x'); - helpers.doKeys(','); - helpers.doKeys('2', ','); - eq(8, cm.getCursor().ch); -}, { value: '01x3xx67xx'}); -testVim('fd,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', '4'); - cm.setCursor(0, 0); - helpers.doKeys('d', ';'); - eq('56789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('d', ','); - eq('01239', cm.getValue()); -}, { value: '0123456789'}); -testVim('Fd,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('F', '4'); - cm.setCursor(0, 9); - helpers.doKeys('d', ';'); - eq('01239', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('d', ','); - eq('56789', cm.getValue()); -}, { value: '0123456789'}); -testVim('td,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', '4'); - cm.setCursor(0, 0); - helpers.doKeys('d', ';'); - eq('456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('d', ','); - eq('012349', cm.getValue()); -}, { value: '0123456789'}); -testVim('Td,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', '4'); - cm.setCursor(0, 9); - helpers.doKeys('d', ';'); - eq('012349', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('d', ','); - eq('456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('fc,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', '4'); - cm.setCursor(0, 0); - helpers.doKeys('c', ';', ''); - eq('56789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('c', ','); - eq('01239', cm.getValue()); -}, { value: '0123456789'}); -testVim('Fc,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('F', '4'); - cm.setCursor(0, 9); - helpers.doKeys('c', ';', ''); - eq('01239', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('c', ','); - eq('56789', cm.getValue()); -}, { value: '0123456789'}); -testVim('tc,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', '4'); - cm.setCursor(0, 0); - helpers.doKeys('c', ';', ''); - eq('456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('c', ','); - eq('012349', cm.getValue()); -}, { value: '0123456789'}); -testVim('Tc,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', '4'); - cm.setCursor(0, 9); - helpers.doKeys('c', ';', ''); - eq('012349', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('c', ','); - eq('456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('fy,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('f', '4'); - cm.setCursor(0, 0); - helpers.doKeys('y', ';', 'P'); - eq('012340123456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('y', ',', 'P'); - eq('012345678456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('Fy,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('F', '4'); - cm.setCursor(0, 9); - helpers.doKeys('y', ';', 'p'); - eq('012345678945678', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('y', ',', 'P'); - eq('012340123456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('ty,;', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys('t', '4'); - cm.setCursor(0, 0); - helpers.doKeys('y', ';', 'P'); - eq('01230123456789', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 9); - helpers.doKeys('y', ',', 'p'); - eq('01234567895678', cm.getValue()); -}, { value: '0123456789'}); -testVim('Ty,;', function(cm, vim, helpers) { - cm.setCursor(0, 9); - helpers.doKeys('T', '4'); - cm.setCursor(0, 9); - helpers.doKeys('y', ';', 'p'); - eq('01234567895678', cm.getValue()); - helpers.doKeys('u'); - cm.setCursor(0, 0); - helpers.doKeys('y', ',', 'P'); - eq('01230123456789', cm.getValue()); -}, { value: '0123456789'}); -testVim('HML', function(cm, vim, helpers) { - var lines = 35; - var textHeight = cm.defaultTextHeight(); - cm.setSize(600, lines*textHeight); - cm.setCursor(120, 0); - helpers.doKeys('H'); - helpers.assertCursorAt(86, 2); - helpers.doKeys('L'); - helpers.assertCursorAt(120, 4); - helpers.doKeys('M'); - helpers.assertCursorAt(103,4); -}, { value: (function(){ - var lines = new Array(100); - var upper = ' xx\n'; - var lower = ' xx\n'; - upper = lines.join(upper); - lower = lines.join(lower); - return upper + lower; -})()}); - -var zVals = []; -forEach(['zb','zz','zt','z-','z.','z'], function(e, idx){ - var lineNum = 250; - var lines = 35; - testVim(e, function(cm, vim, helpers) { - var k1 = e[0]; - var k2 = e.substring(1); - var textHeight = cm.defaultTextHeight(); - cm.setSize(600, lines*textHeight); - cm.setCursor(lineNum, 0); - helpers.doKeys(k1, k2); - zVals[idx] = cm.getScrollInfo().top; - }, { value: (function(){ - return new Array(500).join('\n'); - })()}); -}); -testVim('zb_to_bottom', function(cm, vim, helpers){ - var lineNum = 250; - cm.setSize(600, 35*cm.defaultTextHeight()); - cm.setCursor(lineNum, 0); - helpers.doKeys('z', 'b'); - var scrollInfo = cm.getScrollInfo(); - eq(scrollInfo.top + scrollInfo.clientHeight, cm.charCoords(Pos(lineNum, 0), 'local').bottom); -}, { value: (function(){ - return new Array(500).join('\n'); -})()}); -testVim('zt_to_top', function(cm, vim, helpers){ - var lineNum = 250; - cm.setSize(600, 35*cm.defaultTextHeight()); - cm.setCursor(lineNum, 0); - helpers.doKeys('z', 't'); - eq(cm.getScrollInfo().top, cm.charCoords(Pos(lineNum, 0), 'local').top); -}, { value: (function(){ - return new Array(500).join('\n'); -})()}); -testVim('zb', function(cm, vim, helpers){ - eq(zVals[2], zVals[5]); -}); - -var moveTillCharacterSandbox = - 'The quick brown fox \n'; -testVim('moveTillCharacter', function(cm, vim, helpers){ - cm.setCursor(0, 0); - // Search for the 'q'. - cm.openDialog = helpers.fakeOpenDialog('q'); - helpers.doKeys('/'); - eq(4, cm.getCursor().ch); - // Jump to just before the first o in the list. - helpers.doKeys('t'); - helpers.doKeys('o'); - eq('The quick brown fox \n', cm.getValue()); - // Delete that one character. - helpers.doKeys('d'); - helpers.doKeys('t'); - helpers.doKeys('o'); - eq('The quick bown fox \n', cm.getValue()); - // Delete everything until the next 'o'. - helpers.doKeys('.'); - eq('The quick box \n', cm.getValue()); - // An unmatched character should have no effect. - helpers.doKeys('d'); - helpers.doKeys('t'); - helpers.doKeys('q'); - eq('The quick box \n', cm.getValue()); - // Matches should only be possible on single lines. - helpers.doKeys('d'); - helpers.doKeys('t'); - helpers.doKeys('z'); - eq('The quick box \n', cm.getValue()); - // After all that, the search for 'q' should still be active, so the 'N' command - // can run it again in reverse. Use that to delete everything back to the 'q'. - helpers.doKeys('d'); - helpers.doKeys('N'); - eq('The ox \n', cm.getValue()); - eq(4, cm.getCursor().ch); -}, { value: moveTillCharacterSandbox}); -testVim('searchForPipe', function(cm, vim, helpers){ - CodeMirror.Vim.setOption('pcre', false); - cm.setCursor(0, 0); - // Search for the '|'. - cm.openDialog = helpers.fakeOpenDialog('|'); - helpers.doKeys('/'); - eq(4, cm.getCursor().ch); -}, { value: 'this|that'}); - - -var scrollMotionSandbox = - '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'; -testVim('scrollMotion', function(cm, vim, helpers){ - var prevCursor, prevScrollInfo; - cm.setCursor(0, 0); - // ctrl-y at the top of the file should have no effect. - helpers.doKeys(''); - eq(0, cm.getCursor().line); - prevScrollInfo = cm.getScrollInfo(); - helpers.doKeys(''); - eq(1, cm.getCursor().line); - is(prevScrollInfo.top < cm.getScrollInfo().top); - // Jump to the end of the sandbox. - cm.setCursor(1000, 0); - prevCursor = cm.getCursor(); - // ctrl-e at the bottom of the file should have no effect. - helpers.doKeys(''); - eq(prevCursor.line, cm.getCursor().line); - prevScrollInfo = cm.getScrollInfo(); - helpers.doKeys(''); - eq(prevCursor.line - 1, cm.getCursor().line, "Y"); - is(prevScrollInfo.top > cm.getScrollInfo().top); -}, { value: scrollMotionSandbox}); - -var squareBracketMotionSandbox = ''+ - '({\n'+//0 - ' ({\n'+//11 - ' /*comment {\n'+//2 - ' */(\n'+//3 - '#else \n'+//4 - ' /* )\n'+//5 - '#if }\n'+//6 - ' )}*/\n'+//7 - ')}\n'+//8 - '{}\n'+//9 - '#else {{\n'+//10 - '{}\n'+//11 - '}\n'+//12 - '{\n'+//13 - '#endif\n'+//14 - '}\n'+//15 - '}\n'+//16 - '#else';//17 -testVim('[[, ]]', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(']', ']'); - helpers.assertCursorAt(9,0); - helpers.doKeys('2', ']', ']'); - helpers.assertCursorAt(13,0); - helpers.doKeys(']', ']'); - helpers.assertCursorAt(17,0); - helpers.doKeys('[', '['); - helpers.assertCursorAt(13,0); - helpers.doKeys('2', '[', '['); - helpers.assertCursorAt(9,0); - helpers.doKeys('[', '['); - helpers.assertCursorAt(0,0); -}, { value: squareBracketMotionSandbox}); -testVim('[], ][', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doKeys(']', '['); - helpers.assertCursorAt(12,0); - helpers.doKeys('2', ']', '['); - helpers.assertCursorAt(16,0); - helpers.doKeys(']', '['); - helpers.assertCursorAt(17,0); - helpers.doKeys('[', ']'); - helpers.assertCursorAt(16,0); - helpers.doKeys('2', '[', ']'); - helpers.assertCursorAt(12,0); - helpers.doKeys('[', ']'); - helpers.assertCursorAt(0,0); -}, { value: squareBracketMotionSandbox}); -testVim('[{, ]}', function(cm, vim, helpers) { - cm.setCursor(4, 10); - helpers.doKeys('[', '{'); - helpers.assertCursorAt(2,12); - helpers.doKeys('2', '[', '{'); - helpers.assertCursorAt(0,1); - cm.setCursor(4, 10); - helpers.doKeys(']', '}'); - helpers.assertCursorAt(6,11); - helpers.doKeys('2', ']', '}'); - helpers.assertCursorAt(8,1); - cm.setCursor(0,1); - helpers.doKeys(']', '}'); - helpers.assertCursorAt(8,1); - helpers.doKeys('[', '{'); - helpers.assertCursorAt(0,1); -}, { value: squareBracketMotionSandbox}); -testVim('[(, ])', function(cm, vim, helpers) { - cm.setCursor(4, 10); - helpers.doKeys('[', '('); - helpers.assertCursorAt(3,14); - helpers.doKeys('2', '[', '('); - helpers.assertCursorAt(0,0); - cm.setCursor(4, 10); - helpers.doKeys(']', ')'); - helpers.assertCursorAt(5,11); - helpers.doKeys('2', ']', ')'); - helpers.assertCursorAt(8,0); - helpers.doKeys('[', '('); - helpers.assertCursorAt(0,0); - helpers.doKeys(']', ')'); - helpers.assertCursorAt(8,0); -}, { value: squareBracketMotionSandbox}); -testVim('[*, ]*, [/, ]/', function(cm, vim, helpers) { - forEach(['*', '/'], function(key){ - cm.setCursor(7, 0); - helpers.doKeys('2', '[', key); - helpers.assertCursorAt(2,2); - helpers.doKeys('2', ']', key); - helpers.assertCursorAt(7,5); - }); -}, { value: squareBracketMotionSandbox}); -testVim('[#, ]#', function(cm, vim, helpers) { - cm.setCursor(10, 3); - helpers.doKeys('2', '[', '#'); - helpers.assertCursorAt(4,0); - helpers.doKeys('5', ']', '#'); - helpers.assertCursorAt(17,0); - cm.setCursor(10, 3); - helpers.doKeys(']', '#'); - helpers.assertCursorAt(14,0); -}, { value: squareBracketMotionSandbox}); -testVim('[m, ]m, [M, ]M', function(cm, vim, helpers) { - cm.setCursor(11, 0); - helpers.doKeys('[', 'm'); - helpers.assertCursorAt(10,7); - helpers.doKeys('4', '[', 'm'); - helpers.assertCursorAt(1,3); - helpers.doKeys('5', ']', 'm'); - helpers.assertCursorAt(11,0); - helpers.doKeys('[', 'M'); - helpers.assertCursorAt(9,1); - helpers.doKeys('3', ']', 'M'); - helpers.assertCursorAt(15,0); - helpers.doKeys('5', '[', 'M'); - helpers.assertCursorAt(7,3); -}, { value: squareBracketMotionSandbox}); - -testVim('i_indent_right', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedValue = ' word1\nword2\nword3 '; - helpers.doKeys('i', ''); - eq(expectedValue, cm.getValue()); - helpers.assertCursorAt(0, 5); -}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); -testVim('i_indent_left', function(cm, vim, helpers) { - cm.setCursor(0, 3); - var expectedValue = ' word1\nword2\nword3 '; - helpers.doKeys('i', ''); - eq(expectedValue, cm.getValue()); - helpers.assertCursorAt(0, 1); -}, { value: ' word1\nword2\nword3 ', indentUnit: 2 }); - -// Ex mode tests -testVim('ex_go_to_line', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doEx('4'); - helpers.assertCursorAt(3, 0); -}, { value: 'a\nb\nc\nd\ne\n'}); -testVim('ex_write', function(cm, vim, helpers) { - var tmp = CodeMirror.commands.save; - var written; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - // Test that w, wr, wri ... write all trigger :write. - var command = 'write'; - for (var i = 1; i < command.length; i++) { - written = false; - actualCm = null; - helpers.doEx(command.substring(0, i)); - eq(written, true); - eq(actualCm, cm); - } - CodeMirror.commands.save = tmp; -}); -testVim('ex_sort', function(cm, vim, helpers) { - helpers.doEx('sort'); - eq('Z\na\nb\nc\nd', cm.getValue()); -}, { value: 'b\nZ\nd\nc\na'}); -testVim('ex_sort_reverse', function(cm, vim, helpers) { - helpers.doEx('sort!'); - eq('d\nc\nb\na', cm.getValue()); -}, { value: 'b\nd\nc\na'}); -testVim('ex_sort_range', function(cm, vim, helpers) { - helpers.doEx('2,3sort'); - eq('b\nc\nd\na', cm.getValue()); -}, { value: 'b\nd\nc\na'}); -testVim('ex_sort_oneline', function(cm, vim, helpers) { - helpers.doEx('2sort'); - // Expect no change. - eq('b\nd\nc\na', cm.getValue()); -}, { value: 'b\nd\nc\na'}); -testVim('ex_sort_ignoreCase', function(cm, vim, helpers) { - helpers.doEx('sort i'); - eq('a\nb\nc\nd\nZ', cm.getValue()); -}, { value: 'b\nZ\nd\nc\na'}); -testVim('ex_sort_unique', function(cm, vim, helpers) { - helpers.doEx('sort u'); - eq('Z\na\nb\nc\nd', cm.getValue()); -}, { value: 'b\nZ\na\na\nd\na\nc\na'}); -testVim('ex_sort_decimal', function(cm, vim, helpers) { - helpers.doEx('sort d'); - eq('d3\n s5\n6\n.9', cm.getValue()); -}, { value: '6\nd3\n s5\n.9'}); -testVim('ex_sort_decimal_negative', function(cm, vim, helpers) { - helpers.doEx('sort d'); - eq('z-9\nd3\n s5\n6\n.9', cm.getValue()); -}, { value: '6\nd3\n s5\n.9\nz-9'}); -testVim('ex_sort_decimal_reverse', function(cm, vim, helpers) { - helpers.doEx('sort! d'); - eq('.9\n6\n s5\nd3', cm.getValue()); -}, { value: '6\nd3\n s5\n.9'}); -testVim('ex_sort_hex', function(cm, vim, helpers) { - helpers.doEx('sort x'); - eq(' s5\n6\n.9\n&0xB\nd3', cm.getValue()); -}, { value: '6\nd3\n s5\n&0xB\n.9'}); -testVim('ex_sort_octal', function(cm, vim, helpers) { - helpers.doEx('sort o'); - eq('.8\n.9\nd3\n s5\n6', cm.getValue()); -}, { value: '6\nd3\n s5\n.9\n.8'}); -testVim('ex_sort_decimal_mixed', function(cm, vim, helpers) { - helpers.doEx('sort d'); - eq('y\nz\nc1\nb2\na3', cm.getValue()); -}, { value: 'a3\nz\nc1\ny\nb2'}); -testVim('ex_sort_decimal_mixed_reverse', function(cm, vim, helpers) { - helpers.doEx('sort! d'); - eq('a3\nb2\nc1\nz\ny', cm.getValue()); -}, { value: 'a3\nz\nc1\ny\nb2'}); -testVim('ex_sort_patterns_not_supported', function(cm, vim, helpers) { - var notified = false; - cm.openNotification = helpers.fakeOpenNotification(function(text) { - notified = /patterns not supported/.test(text); - }); - helpers.doEx('sort /abc/'); - is(notified, 'No notification.'); -}); -// test for :global command -testVim('ex_global', function(cm, vim, helpers) { - cm.setCursor(0, 0); - helpers.doEx('g/one/s//two'); - eq('two two\n two two\n two two', cm.getValue()); - helpers.doEx('1,2g/two/s//one'); - eq('one one\n one one\n two two', cm.getValue()); -}, {value: 'one one\n one one\n one one'}); -testVim('ex_global_confirm', function(cm, vim, helpers) { - cm.setCursor(0, 0); - var onKeyDown; - var openDialogSave = cm.openDialog; - var KEYCODES = { - a: 65, - n: 78, - q: 81, - y: 89 - }; - // Intercept the ex command, 'global' - cm.openDialog = function(template, callback, options) { - // Intercept the prompt for the embedded ex command, 'substitute' - cm.openDialog = function(template, callback, options) { - onKeyDown = options.onKeyDown; - }; - callback('g/one/s//two/gc'); - }; - helpers.doKeys(':'); - var close = function() {}; - onKeyDown({keyCode: KEYCODES.n}, '', close); - onKeyDown({keyCode: KEYCODES.y}, '', close); - onKeyDown({keyCode: KEYCODES.a}, '', close); - onKeyDown({keyCode: KEYCODES.q}, '', close); - onKeyDown({keyCode: KEYCODES.y}, '', close); - eq('one two\n two two\n one one\n two one\n one one', cm.getValue()); -}, {value: 'one one\n one one\n one one\n one one\n one one'}); -// Basic substitute tests. -testVim('ex_substitute_same_line', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doEx('s/one/two/g'); - eq('one one\n two two', cm.getValue()); -}, { value: 'one one\n one one'}); -testVim('ex_substitute_full_file', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doEx('%s/one/two/g'); - eq('two two\n two two', cm.getValue()); -}, { value: 'one one\n one one'}); -testVim('ex_substitute_input_range', function(cm, vim, helpers) { - cm.setCursor(1, 0); - helpers.doEx('1,3s/\\d/0/g'); - eq('0\n0\n0\n4', cm.getValue()); -}, { value: '1\n2\n3\n4' }); -testVim('ex_substitute_visual_range', function(cm, vim, helpers) { - cm.setCursor(1, 0); - // Set last visual mode selection marks '< and '> at lines 2 and 4 - helpers.doKeys('V', '2', 'j', 'v'); - helpers.doEx('\'<,\'>s/\\d/0/g'); - eq('1\n0\n0\n0\n5', cm.getValue()); -}, { value: '1\n2\n3\n4\n5' }); -testVim('ex_substitute_empty_query', function(cm, vim, helpers) { - // If the query is empty, use last query. - cm.setCursor(1, 0); - cm.openDialog = helpers.fakeOpenDialog('1'); - helpers.doKeys('/'); - helpers.doEx('s//b/g'); - eq('abb ab2 ab3', cm.getValue()); -}, { value: 'a11 a12 a13' }); -testVim('ex_substitute_javascript', function(cm, vim, helpers) { - CodeMirror.Vim.setOption('pcre', false); - cm.setCursor(1, 0); - // Throw all the things that javascript likes to treat as special values - // into the replace part. All should be literal (this is VIM). - helpers.doEx('s/\\(\\d+\\)/$$ $\' $` $& \\1/g') - eq('a $$ $\' $` $& 0 b', cm.getValue()); -}, { value: 'a 0 b' }); -testVim('ex_substitute_empty_arguments', function(cm,vim,helpers) { - cm.setCursor(0, 0); - helpers.doEx('s/a/b/g'); - cm.setCursor(1, 0); - helpers.doEx('s'); - eq('b b\nb a', cm.getValue()); -}, {value: 'a a\na a'}); - -// More complex substitute tests that test both pcre and nopcre options. -function testSubstitute(name, options) { - testVim(name + '_pcre', function(cm, vim, helpers) { - cm.setCursor(1, 0); - CodeMirror.Vim.setOption('pcre', true); - helpers.doEx(options.expr); - eq(options.expectedValue, cm.getValue()); - }, options); - // If no noPcreExpr is defined, assume that it's the same as the expr. - var noPcreExpr = options.noPcreExpr ? options.noPcreExpr : options.expr; - testVim(name + '_nopcre', function(cm, vim, helpers) { - cm.setCursor(1, 0); - CodeMirror.Vim.setOption('pcre', false); - helpers.doEx(noPcreExpr); - eq(options.expectedValue, cm.getValue()); - }, options); -} -testSubstitute('ex_substitute_capture', { - value: 'a11 a12 a13', - expectedValue: 'a1111 a1212 a1313', - // $n is a backreference - expr: 's/(\\d+)/$1$1/g', - // \n is a backreference. - noPcreExpr: 's/\\(\\d+\\)/\\1\\1/g'}); -testSubstitute('ex_substitute_capture2', { - value: 'a 0 b', - expectedValue: 'a $00 b', - expr: 's/(\\d+)/$$$1$1/g', - noPcreExpr: 's/\\(\\d+\\)/$\\1\\1/g'}); -testSubstitute('ex_substitute_nocapture', { - value: 'a11 a12 a13', - expectedValue: 'a$1$1 a$1$1 a$1$1', - expr: 's/(\\d+)/$$1$$1/g', - noPcreExpr: 's/\\(\\d+\\)/$1$1/g'}); -testSubstitute('ex_substitute_nocapture2', { - value: 'a 0 b', - expectedValue: 'a $10 b', - expr: 's/(\\d+)/$$1$1/g', - noPcreExpr: 's/\\(\\d+\\)/\\$1\\1/g'}); -testSubstitute('ex_substitute_nocapture', { - value: 'a b c', - expectedValue: 'a $ c', - expr: 's/b/$$/', - noPcreExpr: 's/b/$/'}); -testSubstitute('ex_substitute_slash_regex', { - value: 'one/two \n three/four', - expectedValue: 'one|two \n three|four', - expr: '%s/\\//|'}); -testSubstitute('ex_substitute_pipe_regex', { - value: 'one|two \n three|four', - expectedValue: 'one,two \n three,four', - expr: '%s/\\|/,/', - noPcreExpr: '%s/|/,/'}); -testSubstitute('ex_substitute_or_regex', { - value: 'one|two \n three|four', - expectedValue: 'ana|twa \n thraa|faar', - expr: '%s/o|e|u/a/g', - noPcreExpr: '%s/o\\|e\\|u/a/g'}); -testSubstitute('ex_substitute_or_word_regex', { - value: 'one|two \n three|four', - expectedValue: 'five|five \n three|four', - expr: '%s/(one|two)/five/g', - noPcreExpr: '%s/\\(one\\|two\\)/five/g'}); -testSubstitute('ex_substitute_backslashslash_regex', { - value: 'one\\two \n three\\four', - expectedValue: 'one,two \n three,four', - expr: '%s/\\\\/,'}); -testSubstitute('ex_substitute_slash_replacement', { - value: 'one,two \n three,four', - expectedValue: 'one/two \n three/four', - expr: '%s/,/\\/'}); -testSubstitute('ex_substitute_backslash_replacement', { - value: 'one,two \n three,four', - expectedValue: 'one\\two \n three\\four', - expr: '%s/,/\\\\/g'}); -testSubstitute('ex_substitute_multibackslash_replacement', { - value: 'one,two \n three,four', - expectedValue: 'one\\\\\\\\two \n three\\\\\\\\four', // 2*8 backslashes. - expr: '%s/,/\\\\\\\\\\\\\\\\/g'}); // 16 backslashes. -testSubstitute('ex_substitute_newline_replacement', { - value: 'one,two \n three,four', - expectedValue: 'one\ntwo \n three\nfour', - expr: '%s/,/\\n/g'}); -testSubstitute('ex_substitute_braces_word', { - value: 'ababab abb ab{2}', - expectedValue: 'ab abb ab{2}', - expr: '%s/(ab){2}//g', - noPcreExpr: '%s/\\(ab\\)\\{2\\}//g'}); -testSubstitute('ex_substitute_braces_range', { - value: 'a aa aaa aaaa', - expectedValue: 'a a', - expr: '%s/a{2,3}//g', - noPcreExpr: '%s/a\\{2,3\\}//g'}); -testSubstitute('ex_substitute_braces_literal', { - value: 'ababab abb ab{2}', - expectedValue: 'ababab abb ', - expr: '%s/ab\\{2\\}//g', - noPcreExpr: '%s/ab{2}//g'}); -testSubstitute('ex_substitute_braces_char', { - value: 'ababab abb ab{2}', - expectedValue: 'ababab ab{2}', - expr: '%s/ab{2}//g', - noPcreExpr: '%s/ab\\{2\\}//g'}); -testSubstitute('ex_substitute_braces_no_escape', { - value: 'ababab abb ab{2}', - expectedValue: 'ababab ab{2}', - expr: '%s/ab{2}//g', - noPcreExpr: '%s/ab\\{2}//g'}); -testSubstitute('ex_substitute_count', { - value: '1\n2\n3\n4', - expectedValue: '1\n0\n0\n4', - expr: 's/\\d/0/i 2'}); -testSubstitute('ex_substitute_count_with_range', { - value: '1\n2\n3\n4', - expectedValue: '1\n2\n0\n0', - expr: '1,3s/\\d/0/ 3'}); -testSubstitute('ex_substitute_not_global', { - value: 'aaa\nbaa\ncaa', - expectedValue: 'xaa\nbxa\ncxa', - expr: '%s/a/x/'}); -function testSubstituteConfirm(name, command, initialValue, expectedValue, keys, finalPos) { - testVim(name, function(cm, vim, helpers) { - var savedOpenDialog = cm.openDialog; - var savedKeyName = CodeMirror.keyName; - var onKeyDown; - var recordedCallback; - var closed = true; // Start out closed, set false on second openDialog. - function close() { - closed = true; - } - // First openDialog should save callback. - cm.openDialog = function(template, callback, options) { - recordedCallback = callback; - } - // Do first openDialog. - helpers.doKeys(':'); - // Second openDialog should save keyDown handler. - cm.openDialog = function(template, callback, options) { - onKeyDown = options.onKeyDown; - closed = false; - }; - // Return the command to Vim and trigger second openDialog. - recordedCallback(command); - // The event should really use keyCode, but here just mock it out and use - // key and replace keyName to just return key. - CodeMirror.keyName = function (e) { return e.key; } - keys = keys.toUpperCase(); - for (var i = 0; i < keys.length; i++) { - is(!closed); - onKeyDown({ key: keys.charAt(i) }, '', close); - } - try { - eq(expectedValue, cm.getValue()); - helpers.assertCursorAt(finalPos); - is(closed); - } catch(e) { - throw e - } finally { - // Restore overridden functions. - CodeMirror.keyName = savedKeyName; - cm.openDialog = savedOpenDialog; - } - }, { value: initialValue }); -}; -testSubstituteConfirm('ex_substitute_confirm_emptydoc', - '%s/x/b/c', '', '', '', makeCursor(0, 0)); -testSubstituteConfirm('ex_substitute_confirm_nomatch', - '%s/x/b/c', 'ba a\nbab', 'ba a\nbab', '', makeCursor(0, 0)); -testSubstituteConfirm('ex_substitute_confirm_accept', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'yyy', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_random_keys', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ysdkywerty', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_some', - '%s/a/b/cg', 'ba a\nbab', 'bb a\nbbb', 'yny', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_all', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'a', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_accept_then_all', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbbb', 'ya', makeCursor(1, 1)); -testSubstituteConfirm('ex_substitute_confirm_quit', - '%s/a/b/cg', 'ba a\nbab', 'bb a\nbab', 'yq', makeCursor(0, 3)); -testSubstituteConfirm('ex_substitute_confirm_last', - '%s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3)); -testSubstituteConfirm('ex_substitute_confirm_oneline', - '1s/a/b/cg', 'ba a\nbab', 'bb b\nbab', 'yl', makeCursor(0, 3)); -testSubstituteConfirm('ex_substitute_confirm_range_accept', - '1,2s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyy', makeCursor(1, 0)); -testSubstituteConfirm('ex_substitute_confirm_range_some', - '1,3s/a/b/cg', 'aa\na \na\na', 'ba\nb \nb\na', 'ynyy', makeCursor(2, 0)); -testSubstituteConfirm('ex_substitute_confirm_range_all', - '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \nb\na', 'a', makeCursor(2, 0)); -testSubstituteConfirm('ex_substitute_confirm_range_last', - '1,3s/a/b/cg', 'aa\na \na\na', 'bb\nb \na\na', 'yyl', makeCursor(1, 0)); -//:noh should clear highlighting of search-results but allow to resume search through n -testVim('ex_noh_clearSearchHighlight', function(cm, vim, helpers) { - cm.openDialog = helpers.fakeOpenDialog('match'); - helpers.doKeys('?'); - helpers.doEx('noh'); - eq(vim.searchState_.getOverlay(),null,'match-highlighting wasn\'t cleared'); - helpers.doKeys('n'); - helpers.assertCursorAt(0, 11,'can\'t resume search after clearing highlighting'); -}, { value: 'match nope match \n nope Match' }); -testVim('ex_yank', function (cm, vim, helpers) { - var curStart = makeCursor(3, 0); - cm.setCursor(curStart); - helpers.doEx('y'); - var register = helpers.getRegisterController().getRegister(); - var line = cm.getLine(3); - eq(line + '\n', register.toString()); -}); -testVim('set_boolean', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testoption', true, 'boolean'); - // Test default value is set. - is(CodeMirror.Vim.getOption('testoption')); - try { - // Test fail to set to non-boolean - CodeMirror.Vim.setOption('testoption', '5'); - fail(); - } catch (expected) {} - // Test setOption - CodeMirror.Vim.setOption('testoption', false); - is(!CodeMirror.Vim.getOption('testoption')); -}); -testVim('ex_set_boolean', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testoption', true, 'boolean'); - // Test default value is set. - is(CodeMirror.Vim.getOption('testoption')); - try { - // Test fail to set to non-boolean - helpers.doEx('set testoption=22'); - fail(); - } catch (expected) {} - // Test setOption - helpers.doEx('set notestoption'); - is(!CodeMirror.Vim.getOption('testoption')); -}); -testVim('set_string', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testoption', 'a', 'string'); - // Test default value is set. - eq('a', CodeMirror.Vim.getOption('testoption')); - try { - // Test fail to set non-string. - CodeMirror.Vim.setOption('testoption', true); - fail(); - } catch (expected) {} - try { - // Test fail to set 'notestoption' - CodeMirror.Vim.setOption('notestoption', 'b'); - fail(); - } catch (expected) {} - // Test setOption - CodeMirror.Vim.setOption('testoption', 'c'); - eq('c', CodeMirror.Vim.getOption('testoption')); -}); -testVim('ex_set_string', function(cm, vim, helpers) { - CodeMirror.Vim.defineOption('testopt', 'a', 'string'); - // Test default value is set. - eq('a', CodeMirror.Vim.getOption('testopt')); - try { - // Test fail to set 'notestopt' - helpers.doEx('set notestopt=b'); - fail(); - } catch (expected) {} - // Test setOption - helpers.doEx('set testopt=c') - eq('c', CodeMirror.Vim.getOption('testopt')); - helpers.doEx('set testopt=c') - eq('c', CodeMirror.Vim.getOption('testopt', cm)); //local || global - eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'})); // local - eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'})); // global - eq('c', CodeMirror.Vim.getOption('testopt')); // global - // Test setOption global - helpers.doEx('setg testopt=d') - eq('c', CodeMirror.Vim.getOption('testopt', cm)); - eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'})); - eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'})); - eq('d', CodeMirror.Vim.getOption('testopt')); - // Test setOption local - helpers.doEx('setl testopt=e') - eq('e', CodeMirror.Vim.getOption('testopt', cm)); - eq('e', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'})); - eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'})); - eq('d', CodeMirror.Vim.getOption('testopt')); -}); -testVim('ex_set_callback', function(cm, vim, helpers) { - var global; - - function cb(val, cm, cfg) { - if (val === undefined) { - // Getter - if (cm) { - return cm._local; - } else { - return global; - } - } else { - // Setter - if (cm) { - cm._local = val; - } else { - global = val; - } - } - } - - CodeMirror.Vim.defineOption('testopt', 'a', 'string', cb); - // Test default value is set. - eq('a', CodeMirror.Vim.getOption('testopt')); - try { - // Test fail to set 'notestopt' - helpers.doEx('set notestopt=b'); - fail(); - } catch (expected) {} - // Test setOption (Identical to the string tests, but via callback instead) - helpers.doEx('set testopt=c') - eq('c', CodeMirror.Vim.getOption('testopt', cm)); //local || global - eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'})); // local - eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'})); // global - eq('c', CodeMirror.Vim.getOption('testopt')); // global - // Test setOption global - helpers.doEx('setg testopt=d') - eq('c', CodeMirror.Vim.getOption('testopt', cm)); - eq('c', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'})); - eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'})); - eq('d', CodeMirror.Vim.getOption('testopt')); - // Test setOption local - helpers.doEx('setl testopt=e') - eq('e', CodeMirror.Vim.getOption('testopt', cm)); - eq('e', CodeMirror.Vim.getOption('testopt', cm, {scope: 'local'})); - eq('d', CodeMirror.Vim.getOption('testopt', cm, {scope: 'global'})); - eq('d', CodeMirror.Vim.getOption('testopt')); -}) -testVim('ex_set_filetype', function(cm, vim, helpers) { - CodeMirror.defineMode('test_mode', function() { - return {token: function(stream) { - stream.match(/^\s+|^\S+/); - }}; - }); - CodeMirror.defineMode('test_mode_2', function() { - return {token: function(stream) { - stream.match(/^\s+|^\S+/); - }}; - }); - // Test mode is set. - helpers.doEx('set filetype=test_mode'); - eq('test_mode', cm.getMode().name); - // Test 'ft' alias also sets mode. - helpers.doEx('set ft=test_mode_2'); - eq('test_mode_2', cm.getMode().name); -}); -testVim('ex_set_filetype_null', function(cm, vim, helpers) { - CodeMirror.defineMode('test_mode', function() { - return {token: function(stream) { - stream.match(/^\s+|^\S+/); - }}; - }); - cm.setOption('mode', 'test_mode'); - // Test mode is set to null. - helpers.doEx('set filetype='); - eq('null', cm.getMode().name); -}); -// TODO: Reset key maps after each test. -testVim('ex_map_key2key', function(cm, vim, helpers) { - helpers.doEx('map a x'); - helpers.doKeys('a'); - helpers.assertCursorAt(0, 0); - eq('bc', cm.getValue()); -}, { value: 'abc' }); -testVim('ex_unmap_key2key', function(cm, vim, helpers) { - helpers.doEx('unmap a'); - helpers.doKeys('a'); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'abc' }); -testVim('ex_unmap_key2key_does_not_remove_default', function(cm, vim, helpers) { - try { - helpers.doEx('unmap a'); - fail(); - } catch (expected) {} - helpers.doKeys('a'); - eq('vim-insert', cm.getOption('keyMap')); -}, { value: 'abc' }); -testVim('ex_map_key2key_to_colon', function(cm, vim, helpers) { - helpers.doEx('map ; :'); - var dialogOpened = false; - cm.openDialog = function() { - dialogOpened = true; - } - helpers.doKeys(';'); - eq(dialogOpened, true); -}); -testVim('ex_map_ex2key:', function(cm, vim, helpers) { - helpers.doEx('map :del x'); - helpers.doEx('del'); - helpers.assertCursorAt(0, 0); - eq('bc', cm.getValue()); -}, { value: 'abc' }); -testVim('ex_map_ex2ex', function(cm, vim, helpers) { - helpers.doEx('map :del :w'); - var tmp = CodeMirror.commands.save; - var written = false; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - helpers.doEx('del'); - CodeMirror.commands.save = tmp; - eq(written, true); - eq(actualCm, cm); -}); -testVim('ex_map_key2ex', function(cm, vim, helpers) { - helpers.doEx('map a :w'); - var tmp = CodeMirror.commands.save; - var written = false; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - helpers.doKeys('a'); - CodeMirror.commands.save = tmp; - eq(written, true); - eq(actualCm, cm); -}); -testVim('ex_map_key2key_visual_api', function(cm, vim, helpers) { - CodeMirror.Vim.map('b', ':w', 'visual'); - var tmp = CodeMirror.commands.save; - var written = false; - var actualCm; - CodeMirror.commands.save = function(cm) { - written = true; - actualCm = cm; - }; - // Mapping should not work in normal mode. - helpers.doKeys('b'); - eq(written, false); - // Mapping should work in visual mode. - helpers.doKeys('v', 'b'); - eq(written, true); - eq(actualCm, cm); - - CodeMirror.commands.save = tmp; -}); -testVim('ex_imap', function(cm, vim, helpers) { - CodeMirror.Vim.map('jk', '', 'insert'); - helpers.doKeys('i'); - is(vim.insertMode); - helpers.doKeys('j', 'k'); - is(!vim.insertMode); - cm.setCursor(0, 1); - CodeMirror.Vim.map('jj', '', 'insert'); - helpers.doKeys('', '2', 'j', 'l', 'c'); - var replacement = fillArray('fo', 3); - cm.replaceSelections(replacement); - eq('1fo4\n5fo8\nafodefg', cm.getValue()); - helpers.doKeys('j', 'j'); - cm.setCursor(0, 0); - helpers.doKeys('.'); - eq('foo4\nfoo8\nfoodefg', cm.getValue()); -}, { value: '1234\n5678\nabcdefg' }); -testVim('ex_unmap_api', function(cm, vim, helpers) { - CodeMirror.Vim.map('', 'gg', 'normal'); - is(CodeMirror.Vim.handleKey(cm, "", "normal"), "Alt-X key is mapped"); - CodeMirror.Vim.unmap("", "normal"); - is(!CodeMirror.Vim.handleKey(cm, "", "normal"), "Alt-X key is unmapped"); -}); - -// Testing registration of functions as ex-commands and mapping to -keys -testVim('ex_api_test', function(cm, vim, helpers) { - var res=false; - var val='from'; - CodeMirror.Vim.defineEx('extest','ext',function(cm,params){ - if(params.args)val=params.args[0]; - else res=true; - }); - helpers.doEx(':ext to'); - eq(val,'to','Defining ex-command failed'); - CodeMirror.Vim.map('',':ext'); - helpers.doKeys('',''); - is(res,'Mapping to key failed'); -}); -// For now, this test needs to be last because it messes up : for future tests. -testVim('ex_map_key2key_from_colon', function(cm, vim, helpers) { - helpers.doEx('map : x'); - helpers.doKeys(':'); - helpers.assertCursorAt(0, 0); - eq('bc', cm.getValue()); -}, { value: 'abc' }); - -// Test event handlers -testVim('beforeSelectionChange', function(cm, vim, helpers) { - cm.setCursor(0, 100); - eqPos(cm.getCursor('head'), cm.getCursor('anchor')); -}, { value: 'abc' }); - - diff --git a/backend/_pv_1_3_5/static/codemirror/theme/3024-day.css b/backend/_pv_1_3_5/static/codemirror/theme/3024-day.css deleted file mode 100755 index 713265530..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/3024-day.css +++ /dev/null @@ -1,41 +0,0 @@ -/* - - Name: 3024 day - Author: Jan T. Sott (http://github.com/idleberg) - - CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror) - Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) - -*/ - -.cm-s-3024-day.CodeMirror { background: #f7f7f7; color: #3a3432; } -.cm-s-3024-day div.CodeMirror-selected { background: #d6d5d4; } - -.cm-s-3024-day .CodeMirror-line::selection, .cm-s-3024-day .CodeMirror-line > span::selection, .cm-s-3024-day .CodeMirror-line > span > span::selection { background: #d6d5d4; } -.cm-s-3024-day .CodeMirror-line::-moz-selection, .cm-s-3024-day .CodeMirror-line > span::-moz-selection, .cm-s-3024-day .CodeMirror-line > span > span::selection { background: #d9d9d9; } - -.cm-s-3024-day .CodeMirror-gutters { background: #f7f7f7; border-right: 0px; } -.cm-s-3024-day .CodeMirror-guttermarker { color: #db2d20; } -.cm-s-3024-day .CodeMirror-guttermarker-subtle { color: #807d7c; } -.cm-s-3024-day .CodeMirror-linenumber { color: #807d7c; } - -.cm-s-3024-day .CodeMirror-cursor { border-left: 1px solid #5c5855; } - -.cm-s-3024-day span.cm-comment { color: #cdab53; } -.cm-s-3024-day span.cm-atom { color: #a16a94; } -.cm-s-3024-day span.cm-number { color: #a16a94; } - -.cm-s-3024-day span.cm-property, .cm-s-3024-day span.cm-attribute { color: #01a252; } -.cm-s-3024-day span.cm-keyword { color: #db2d20; } -.cm-s-3024-day span.cm-string { color: #fded02; } - -.cm-s-3024-day span.cm-variable { color: #01a252; } -.cm-s-3024-day span.cm-variable-2 { color: #01a0e4; } -.cm-s-3024-day span.cm-def { color: #e8bbd0; } -.cm-s-3024-day span.cm-bracket { color: #3a3432; } -.cm-s-3024-day span.cm-tag { color: #db2d20; } -.cm-s-3024-day span.cm-link { color: #a16a94; } -.cm-s-3024-day span.cm-error { background: #db2d20; color: #5c5855; } - -.cm-s-3024-day .CodeMirror-activeline-background { background: #e8f2ff; } -.cm-s-3024-day .CodeMirror-matchingbracket { text-decoration: underline; color: #a16a94 !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/3024-night.css b/backend/_pv_1_3_5/static/codemirror/theme/3024-night.css deleted file mode 100755 index adc5900ad..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/3024-night.css +++ /dev/null @@ -1,39 +0,0 @@ -/* - - Name: 3024 night - Author: Jan T. Sott (http://github.com/idleberg) - - CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror) - Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) - -*/ - -.cm-s-3024-night.CodeMirror { background: #090300; color: #d6d5d4; } -.cm-s-3024-night div.CodeMirror-selected { background: #3a3432; } -.cm-s-3024-night .CodeMirror-line::selection, .cm-s-3024-night .CodeMirror-line > span::selection, .cm-s-3024-night .CodeMirror-line > span > span::selection { background: rgba(58, 52, 50, .99); } -.cm-s-3024-night .CodeMirror-line::-moz-selection, .cm-s-3024-night .CodeMirror-line > span::-moz-selection, .cm-s-3024-night .CodeMirror-line > span > span::-moz-selection { background: rgba(58, 52, 50, .99); } -.cm-s-3024-night .CodeMirror-gutters { background: #090300; border-right: 0px; } -.cm-s-3024-night .CodeMirror-guttermarker { color: #db2d20; } -.cm-s-3024-night .CodeMirror-guttermarker-subtle { color: #5c5855; } -.cm-s-3024-night .CodeMirror-linenumber { color: #5c5855; } - -.cm-s-3024-night .CodeMirror-cursor { border-left: 1px solid #807d7c; } - -.cm-s-3024-night span.cm-comment { color: #cdab53; } -.cm-s-3024-night span.cm-atom { color: #a16a94; } -.cm-s-3024-night span.cm-number { color: #a16a94; } - -.cm-s-3024-night span.cm-property, .cm-s-3024-night span.cm-attribute { color: #01a252; } -.cm-s-3024-night span.cm-keyword { color: #db2d20; } -.cm-s-3024-night span.cm-string { color: #fded02; } - -.cm-s-3024-night span.cm-variable { color: #01a252; } -.cm-s-3024-night span.cm-variable-2 { color: #01a0e4; } -.cm-s-3024-night span.cm-def { color: #e8bbd0; } -.cm-s-3024-night span.cm-bracket { color: #d6d5d4; } -.cm-s-3024-night span.cm-tag { color: #db2d20; } -.cm-s-3024-night span.cm-link { color: #a16a94; } -.cm-s-3024-night span.cm-error { background: #db2d20; color: #807d7c; } - -.cm-s-3024-night .CodeMirror-activeline-background { background: #2F2F2F; } -.cm-s-3024-night .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/abcdef.css b/backend/_pv_1_3_5/static/codemirror/theme/abcdef.css deleted file mode 100755 index 7f9d78870..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/abcdef.css +++ /dev/null @@ -1,32 +0,0 @@ -.cm-s-abcdef.CodeMirror { background: #0f0f0f; color: #defdef; } -.cm-s-abcdef div.CodeMirror-selected { background: #515151; } -.cm-s-abcdef .CodeMirror-line::selection, .cm-s-abcdef .CodeMirror-line > span::selection, .cm-s-abcdef .CodeMirror-line > span > span::selection { background: rgba(56, 56, 56, 0.99); } -.cm-s-abcdef .CodeMirror-line::-moz-selection, .cm-s-abcdef .CodeMirror-line > span::-moz-selection, .cm-s-abcdef .CodeMirror-line > span > span::-moz-selection { background: rgba(56, 56, 56, 0.99); } -.cm-s-abcdef .CodeMirror-gutters { background: #555; border-right: 2px solid #314151; } -.cm-s-abcdef .CodeMirror-guttermarker { color: #222; } -.cm-s-abcdef .CodeMirror-guttermarker-subtle { color: azure; } -.cm-s-abcdef .CodeMirror-linenumber { color: #FFFFFF; } -.cm-s-abcdef .CodeMirror-cursor { border-left: 1px solid #00FF00; } - -.cm-s-abcdef span.cm-keyword { color: darkgoldenrod; font-weight: bold; } -.cm-s-abcdef span.cm-atom { color: #77F; } -.cm-s-abcdef span.cm-number { color: violet; } -.cm-s-abcdef span.cm-def { color: #fffabc; } -.cm-s-abcdef span.cm-variable { color: #abcdef; } -.cm-s-abcdef span.cm-variable-2 { color: #cacbcc; } -.cm-s-abcdef span.cm-variable-3 { color: #def; } -.cm-s-abcdef span.cm-property { color: #fedcba; } -.cm-s-abcdef span.cm-operator { color: #ff0; } -.cm-s-abcdef span.cm-comment { color: #7a7b7c; font-style: italic;} -.cm-s-abcdef span.cm-string { color: #2b4; } -.cm-s-abcdef span.cm-meta { color: #C9F; } -.cm-s-abcdef span.cm-qualifier { color: #FFF700; } -.cm-s-abcdef span.cm-builtin { color: #30aabc; } -.cm-s-abcdef span.cm-bracket { color: #8a8a8a; } -.cm-s-abcdef span.cm-tag { color: #FFDD44; } -.cm-s-abcdef span.cm-attribute { color: #DDFF00; } -.cm-s-abcdef span.cm-error { color: #FF0000; } -.cm-s-abcdef span.cm-header { color: aquamarine; font-weight: bold; } -.cm-s-abcdef span.cm-link { color: blueviolet; } - -.cm-s-abcdef .CodeMirror-activeline-background { background: #314151; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/ambiance-mobile.css b/backend/_pv_1_3_5/static/codemirror/theme/ambiance-mobile.css deleted file mode 100755 index 88d332e1a..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/ambiance-mobile.css +++ /dev/null @@ -1,5 +0,0 @@ -.cm-s-ambiance.CodeMirror { - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; -} diff --git a/backend/_pv_1_3_5/static/codemirror/theme/ambiance.css b/backend/_pv_1_3_5/static/codemirror/theme/ambiance.css deleted file mode 100755 index bce344649..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/ambiance.css +++ /dev/null @@ -1,74 +0,0 @@ -/* ambiance theme for codemirror */ - -/* Color scheme */ - -.cm-s-ambiance .cm-header { color: blue; } -.cm-s-ambiance .cm-quote { color: #24C2C7; } - -.cm-s-ambiance .cm-keyword { color: #cda869; } -.cm-s-ambiance .cm-atom { color: #CF7EA9; } -.cm-s-ambiance .cm-number { color: #78CF8A; } -.cm-s-ambiance .cm-def { color: #aac6e3; } -.cm-s-ambiance .cm-variable { color: #ffb795; } -.cm-s-ambiance .cm-variable-2 { color: #eed1b3; } -.cm-s-ambiance .cm-variable-3 { color: #faded3; } -.cm-s-ambiance .cm-property { color: #eed1b3; } -.cm-s-ambiance .cm-operator { color: #fa8d6a; } -.cm-s-ambiance .cm-comment { color: #555; font-style:italic; } -.cm-s-ambiance .cm-string { color: #8f9d6a; } -.cm-s-ambiance .cm-string-2 { color: #9d937c; } -.cm-s-ambiance .cm-meta { color: #D2A8A1; } -.cm-s-ambiance .cm-qualifier { color: yellow; } -.cm-s-ambiance .cm-builtin { color: #9999cc; } -.cm-s-ambiance .cm-bracket { color: #24C2C7; } -.cm-s-ambiance .cm-tag { color: #fee4ff; } -.cm-s-ambiance .cm-attribute { color: #9B859D; } -.cm-s-ambiance .cm-hr { color: pink; } -.cm-s-ambiance .cm-link { color: #F4C20B; } -.cm-s-ambiance .cm-special { color: #FF9D00; } -.cm-s-ambiance .cm-error { color: #AF2018; } - -.cm-s-ambiance .CodeMirror-matchingbracket { color: #0f0; } -.cm-s-ambiance .CodeMirror-nonmatchingbracket { color: #f22; } - -.cm-s-ambiance div.CodeMirror-selected { background: rgba(255, 255, 255, 0.15); } -.cm-s-ambiance.CodeMirror-focused div.CodeMirror-selected { background: rgba(255, 255, 255, 0.10); } -.cm-s-ambiance .CodeMirror-line::selection, .cm-s-ambiance .CodeMirror-line > span::selection, .cm-s-ambiance .CodeMirror-line > span > span::selection { background: rgba(255, 255, 255, 0.10); } -.cm-s-ambiance .CodeMirror-line::-moz-selection, .cm-s-ambiance .CodeMirror-line > span::-moz-selection, .cm-s-ambiance .CodeMirror-line > span > span::-moz-selection { background: rgba(255, 255, 255, 0.10); } - -/* Editor styling */ - -.cm-s-ambiance.CodeMirror { - line-height: 1.40em; - color: #E6E1DC; - background-color: #202020; - -webkit-box-shadow: inset 0 0 10px black; - -moz-box-shadow: inset 0 0 10px black; - box-shadow: inset 0 0 10px black; -} - -.cm-s-ambiance .CodeMirror-gutters { - background: #3D3D3D; - border-right: 1px solid #4D4D4D; - box-shadow: 0 10px 20px black; -} - -.cm-s-ambiance .CodeMirror-linenumber { - text-shadow: 0px 1px 1px #4d4d4d; - color: #111; - padding: 0 5px; -} - -.cm-s-ambiance .CodeMirror-guttermarker { color: #aaa; } -.cm-s-ambiance .CodeMirror-guttermarker-subtle { color: #111; } - -.cm-s-ambiance .CodeMirror-cursor { border-left: 1px solid #7991E8; } - -.cm-s-ambiance .CodeMirror-activeline-background { - background: none repeat scroll 0% 0% rgba(255, 255, 255, 0.031); -} - -.cm-s-ambiance.CodeMirror, -.cm-s-ambiance .CodeMirror-gutters { - background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAQAAAAHUWYVAABFFUlEQVQYGbzBCeDVU/74/6fj9HIcx/FRHx9JCFmzMyGRURhLZIkUsoeRfUjS2FNDtr6WkMhO9sm+S8maJfu+Jcsg+/o/c+Z4z/t97/vezy3z+z8ekGlnYICG/o7gdk+wmSHZ1z4pJItqapjoKXWahm8NmV6eOTbWUOp6/6a/XIg6GQqmenJ2lDHyvCFZ2cBDbmtHA043VFhHwXxClWmeYAdLhV00Bd85go8VmaFCkbVkzlQENzfBDZ5gtN7HwF0KDrTwJ0dypSOzpaKCMwQHKTIreYIxlmhXTzTWkVm+LTynZhiSBT3RZQ7aGfjGEd3qyXQ1FDymqbKxpspERQN2MiRjNZlFFQXfCNFm9nM1zpAsoYjmtRTc5ajwuaXc5xrWskT97RaKzAGe5ARHhVUsDbjKklziiX5WROcJwSNCNI+9w1Jwv4Zb2r7lCMZ4oq5C0EdTx+2GzNuKpJ+iFf38JEWkHJn9DNF7mmBDITrWEg0VWL3pHU20tSZnuqWu+R3BtYa8XxV1HO7GyD32UkOpL/yDloINFTmvtId+nmAjxRw40VMwVKiwrKLE4bK5UOVntYwhOcSSXKrJHKPJedocpGjVz/ZMIbnYUPB10/eKCrs5apqpgVmWzBYWpmtKHecJPjaUuEgRDDaU0oZghCJ6zNMQ5ZhDYx05r5v2muQdM0EILtXUsaKiQX9WMEUotagQzFbUNN6NUPC2nm5pxEWGCjMc3GdJHjSU2kORLK/JGSrkfGEIjncU/CYUnOipoYemwj8tST9NsJmB7TUVXtbUtXATJVZXBMvYeTXJfobgJUPmGMP/yFaWonaa6BcFO3nqcIqCozSZoZoSr1g4zJOzuyGnxTEX3lUEJ7WcZgme8ddaWvWJo2AJR9DZU3CUIbhCSG6ybSwN6qtJVnCU2svDTP2ZInOw2cBTrqtQahtNZn9NcJ4l2NaSmSkkP1noZWnVwkLmdUPOwLZEwy2Z3S3R+4rIG9hcbpPXHFVWcQdZkn2FOta3cKWQnNRC5g1LsJah4GCzSVsKnCOY5OAFRTBekyyryeyilhFKva75r4Mc0aWanGEaThcy31s439KKxTzJYY5WTHPU1FtIHjQU3Oip4xlNzj/lBw23dYZVliQa7WAXf4shetcQfatI+jWRDBPmyNeW6A1P5kdDgyYJlba0BIM8BZu1JfrFwItyjcAMR3K0BWOIrtMEXyhyrlVEx3ui5dUBjmB/Q3CXW85R4mBD0s7B+4q5tKUjOlb9qqmhi5AZ6GFIC5HXtOobdYGlVdMVbNJ8toNTFcHxnoL+muBagcctjWnbNMuR00uI7nQESwg5q2qqrKWIfrNUmeQocY6HuyxJV02wj36w00yhpmUFenv4p6fUkZYqLyuinx2RGOjhCXYyJF84oiU00YMOOhhquNdfbOB7gU88pY4xJO8LVdp6/q2voeB4R04vIdhSE40xZObx1HGGJ/ja0LBthFInKaLPPFzuCaYaoj8JjPME8yoyxo6zlBqkiUZYgq00OYMswbWO5NGmq+xhipxHLRW29ARjNKXO0wRnear8XSg4XFPLKEPUS1GqvyLwiuBUoa7zpZ0l5xxFwWmWZC1H5h5FwU8eQ7K+g8UcVY6TMQreVQT/8uQ8Z+ALIXnSEa2pYZQneE9RZbSBNYXfWYJzW/h/4j4Dp1tYVcFIC5019Vyi4ThPqSFCzjGWaHQTBU8q6vrVwgxP9Lkm840imWKpcLCjYTtrKuwvsKSnrvHCXGkSMk9p6lhckfRpIeis+N2PiszT+mFLspyGleUhDwcLrZqmyeylxwjBcKHEapqkmyangyLZRVOijwOtCY5SsG5zL0OwlCJ4y5KznF3EUNDDrinwiyLZRzOXtlBbK5ITHFGLp8Q0R6ab6mS7enI2cFrxOyHvOCFaT1HThS1krjCwqWeurCkk+willhCC+RSZnRXBiZaC5RXRIZYKp2lyfrHwiKPKR0JDzrdU2EFgpidawlFDR6FgXUMNa+g1FY3bUQh2cLCwosRdnuQTS/S+JVrGLeWIvtQUvONJxlqSQYYKpwoN2kaocLjdVsis4Mk80ESF2YpSkzwldjHkjFCUutI/r+EHDU8oCs6yzL3PhWiEooZdFMkymlas4AcI3KmoMMNSQ3tHzjGWCrcJJdYyZC7QFGwjRL9p+MrRkAGWzIaWCn9W0F3TsK01c2ZvQw0byvxuQU0r1lM0qJO7wW0kRIMdDTtXEdzi4VIh+EoIHm0mWtAtpCixlabgn83fKTI7anJe9ST7WIK1DMGpQmYeA58ImV6ezOGOzK2Kgq01pd60cKWiUi9Lievb/0vIDPHQ05Kzt4ddPckQBQtoaurjyHnek/nKzpQLrVgKPjIkh2v4uyezpv+Xoo7fPFXaGFp1vaLKxQ4uUpQQS5VuQs7BCq4xRJv7fwpVvvFEB3j+620haOuocqMhWd6TTPAEx+mdFNGHdranFe95WrWmIvlY4F1Dle2ECgc6cto7SryuqGGGha0tFQ5V53migUKmg6XKAo4qS3mik+0OZpAhOLeZKicacgaYcyx5hypYQE02ZA4xi/pNhOQxR4klNKyqacj+mpxnLTnnGSo85++3ZCZq6lrZkXlGEX3o+C9FieccJbZWVFjC0Yo1FZnJhoYMFoI1hEZ9r6hwg75HwzBNhbZCdJEfJwTPGzJvaKImw1yYX1HDAmpXR+ZJQ/SmgqMNVQb5vgamGwLtt7VwvP7Qk1xpiM5x5Cyv93E06MZmgs0Nya2azIKOYKCGBQQW97RmhKNKF02JZqHEJ4o58qp7X5EcZmc56trXEqzjCBZ1MFGR87Ql2tSTs6CGxS05PTzRQorkbw7aKoKXFDXsYW42VJih/q+FP2BdTzDTwVqOYB13liM50vG7wy28qagyuIXMeQI/Oqq8bcn5wJI50xH00CRntyfpL1T4hydYpoXgNiFzoIUTDZnLNRzh4TBHwbYGDvZkxmlyJloyr6tRihpeUG94GnKtIznREF0tzJG/OOr73JBcrSh1k6WuTprgLU+mnSGnv6Zge0NNz+kTDdH8nuAuTdJDCNb21LCiIuqlYbqGzT3RAoZofQfjFazkqeNWdYaGvYTM001EW2oKPvVk1ldUGSgUtHFwjKM1h9jnFcmy5lChoLNaQMGGDsYbKixlaMBmmsx1QjCfflwTfO/gckW0ruZ3jugKR3R5W9hGUWqCgxuFgsuaCHorotGKzGaeZB9DMsaTnKCpMtwTvOzhYk0rdrArKCqcaWmVk1+F372ur1YkKxgatI8Qfe1gIX9wE9FgS8ESmuABIXnRUbCapcKe+nO7slClSZFzpV/LkLncEb1qiO42fS3R855Su2mCLh62t1SYZZYVmKwIHjREF2uihTzB20JOkz7dkxzYQnK0UOU494wh+VWRc6Un2kpTaVgLDFEkJ/uhzRcI0YKGgpGWOlocBU/a4fKoJ/pEaNV6jip3+Es9VXY078rGnmAdf7t9ylPXS34RBSuYPs1UecZTU78WanhBCHpZ5sAoTz0LGZKjPf9TRypqWEiTvOFglL1fCEY3wY/++rbk7C8bWebA6p6om6PgOL2kp44TFJlVNBXae2rqqdZztOJpT87GQsE9jqCPIe9VReZuQ/CIgacsyZdCpIScSYqcZk8r+nsyCzhyfhOqHGOIvrLknC8wTpFcaYiGC/RU1NRbUeUpocQOnkRpGOrIOcNRx+1uA0UrzhSSt+VyS3SJpnFWkzNDqOFGIWcfR86DnmARTQ1HKIL33ExPiemeOhYSSjzlSUZZuE4TveoJLnBUOFof6KiysCbnAEcZgcUNTDOwkqWu3RWtmGpZwlHhJENdZ3miGz0lJlsKnjbwqSHQjpxnFDlTLLwqJPMZMjd7KrzkSG7VsxXBZE+F8YZkb01Oe00yyRK9psh5SYh29ySPKBo2ylNht7ZkZnsKenjKNJu9PNEyZpaCHv4Kt6RQsLvAVp7M9kIimmCUwGeWqLMmGuIotYMmWNpSahkhZw9FqZsVnKJhsjAHvtHMsTM9fCI06Dx/u3vfUXCqfsKRc4oFY2jMsoo/7DJDwZ1CsIKnJu+J9ldkpmiCxQx1rWjI+T9FwcWWzOuaYH0Hj7klNRVWEQpmaqosakiGNTFHdjS/qnUdmf0NJW5xsL0HhimCCZZSRzmSPTXJQ4aaztAwtZnoabebJ+htCaZ7Cm535ByoqXKbX1WRc4Eh2MkRXWzImVc96Cj4VdOKVxR84VdQsIUM8Psoou2byVHyZFuq7O8otbSQ2UAoeEWTudATLGSpZzVLlXVkPU2Jc+27lsw2jmg5T5VhbeE3BT083K9WsTTkFU/Osi0rC5lRlpwRHUiesNS0sOvmqGML1aRbPAxTJD9ZKtxuob+hhl8cwYGWpJ8nub7t5p6coYbMovZ1BTdaKn1jYD6h4GFDNFyT/Kqe1XCXphXHOKLZmuRSRdBPEfVUXQzJm5YGPGGJdvAEr7hHNdGZnuBvrpciGmopOLf5N0uVMy0FfYToJk90uUCbJupaVpO53UJXR2bVpoU00V2KOo4zMFrBd0Jtz2pa0clT5Q5L8IpQ177mWQejPMEJhuQjS10ref6HHjdEhy1P1EYR7GtO0uSsKJQYLiTnG1rVScj5lyazpqWGl5uBbRWl7m6ixGOOnEsMJR7z8J0n6KMnCdxhiNYQCoZ6CmYLnO8omC3MkW3bktlPmEt/VQQHejL3+dOE5FlPdK/Mq8hZxxJtLyRrepLThYKbLZxkSb5W52vYxNOaOxUF0yxMUPwBTYqCzy01XayYK0sJyWBLqX0MwU5CzoymRzV0EjjeUeLgDpTo6ij42ZAzvD01dHUUTPLU96MdLbBME8nFBn7zJCMtJcZokn8YoqU0FS5WFKyniHobguMcmW8N0XkWZjkyN3hqOMtS08r+/xTBwpZSZ3qiVRX8SzMHHjfUNFjgHEPmY9PL3ykEzxkSre/1ZD6z/NuznuB0RcE1TWTm9zRgfUWVJiG6yrzgmWPXC8EAR4Wxhlad0ZbgQyEz3pG5RVEwwDJH2mgKpjcTiCOzn1lfUWANFbZ2BA8balnEweJC9J0iuaeZoI+ippFCztEKVvckR2iice1JvhVytrQwUAZpgsubCPaU7xUe9vWnaOpaSBEspalykhC9bUlOMpT42ZHca6hyrqKmw/wMR8H5ZmdFoBVJb03O4UL0tSNnvIeRmkrLWqrs78gcrEn2tpcboh0UPOW3UUR9PMk4T4nnNKWmCjlrefhCwxRNztfmIQVdDElvS4m1/WuOujoZCs5XVOjtKPGokJzsYCtFYoWonSPT21DheU/wWhM19FcElwqNGOsp9Q8N/cwXaiND1MmeL1Q5XROtYYgGeFq1aTMsoMmcrKjQrOFQTQ1fmBYhmW6o8Jkjc7iDJRTBIo5kgJD5yMEYA3srCg7VFKwiVJkmRCc5ohGOKhsYMn/XBLdo5taZjlb9YAlGWRimqbCsoY7HFAXLa5I1HPRxMMsQDHFkWtRNniqT9UEeNjcE7RUlrCJ4R2CSJuqlKHWvJXjAUNcITYkenuBRB84TbeepcqTj3zZyFJzgYQdHnqfgI0ddUwS6GqWpsKWhjq9cV0vBAEMN2znq+EBfIWT+pClYw5xsTlJU6GeIBsjGmmANTzJZiIYpgrM0Oa8ZMjd7NP87jxhqGOhJlnQtjuQpB+8aEE00wZFznSJPyHxgH3HkPOsJFvYk8zqCHzTs1BYOa4J3PFU+UVRZxlHDM4YavlNUuMoRveiZA2d7grMNc2g+RbSCEKzmgYsUmWmazFJyoiOZ4KnyhKOGRzWJa0+moyV4TVHDzn51Awtqaphfk/lRQ08FX1iiqxTB/kLwd0VynKfEvI6cd4XMV5bMhZ7gZUWVzYQ6Nm2BYzxJbw3bGthEUUMfgbGeorae6DxHtJoZ6alhZ0+ytiVoK1R4z5PTrOECT/SugseEOlb1MMNR4VRNcJy+V1Hg9ONClSZFZjdHlc6W6FBLdJja2MC5hhpu0DBYEY1TFGwiFAxRRCsYkiM9JRb0JNMVkW6CZYT/2EiTGWmo8k+h4FhDNE7BvppoTSFnmCV5xZKzvcCdDo7VVPnIU+I+Rc68juApC90MwcFCsJ5hDqxgScYKreruyQwTqrzoqDCmhWi4IbhB0Yrt3RGa6GfDv52rKXWhh28dyZaWUvcZeMTBaZoSGyiCtRU5J8iviioHaErs7Jkj61syVzTTgOcUOQ8buFBTYWdL5g3T4qlpe0+wvD63heAXRfCCIed9RbCsp2CiI7raUOYOTU13N8PNHvpaGvayo4a3LLT1lDrVEPT2zLUlheB1R+ZTRfKWJ+dcocLJfi11vyJ51lLqJ0WD7tRwryezjiV5W28uJO9qykzX8JDe2lHl/9oyBwa2UMfOngpXCixvKdXTk3wrsKmiVYdZIqsoWEERjbcUNDuiaQomGoIbFdEHmsyWnuR+IeriKDVLnlawlyNHKwKlSU631PKep8J4Q+ayjkSLKYLhalNHlYvttb6fHm0p6OApsZ4l2VfdqZkjuysy6ysKLlckf1KUutCTs39bmCgEyyoasIWlVaMF7mgmWtBT8Kol5xpH9IGllo8cJdopcvZ2sImlDmMIbtDk3KIpeNiS08lQw11NFPTwVFlPP6pJ2gvRfI7gQUfmNAtf6Gs0wQxDsKGlVBdF8rCa3jzdwMaGHOsItrZk7hAyOzpK9VS06j5F49b0VNGOOfKs3lDToMsMBe9ZWtHFEgxTJLs7qrygKZjUnmCYoeAqeU6jqWuLJup4WghOdvCYJnrSkSzoyRkm5M2StQwVltPkfCAk58tET/CSg+8MUecmotMEnhBKfWBIZsg2ihruMJQaoIm+tkTLKEqspMh00w95gvFCQRtDwTT1gVDDSEVdlwqZfxoQRbK0g+tbiBZxzKlpnpypejdDwTaeOvorMk/IJE10h9CqRe28hhLbe0pMsdSwv4ZbhKivo2BjDWfL8UKJgeavwlwb5KlwhyE4u4XkGE2ytZCznKLCDZZq42VzT8HLCrpruFbIfOIINmh/qCdZ1ZBc65kLHR1Bkyf5zn6pN3SvGKIlFNGplhrO9QSXanLOMQTLCa0YJCRrCZm/CZmrLTm7WzCK4GJDiWUdFeYx1LCFg3NMd0XmCuF3Y5rITLDUsYS9zoHVzwnJoYpSTQoObyEzr4cFBNqYTopoaU/wkyLZ2lPhX/5Y95ulxGTV7KjhWrOZgl8MyUUafjYraNjNU1N3IWcjT5WzWqjwtoarHSUObGYO3GCJZpsBlnJGPd6ZYLyl1GdCA2625IwwJDP8GUKymbzuyPlZlvTUsaUh5zFDhRWFzPKKZLAlWdcQbObgF9tOqOsmB1dqcqYJmWstFbZRRI9poolmqiLnU0POvxScpah2iSL5UJNzgScY5+AuIbpO0YD3NCW+dLMszFSdFCWGqG6eVq2uYVNDdICGD6W7EPRWZEY5gpsE9rUkS3mijzzJnm6UpUFXG1hCUeVoS5WfNcFpblELL2qqrCvMvRfd45oalvKU2tiQ6ePJOVMRXase9iTtLJztPxJKLWpo2CRDcJwn2sWSLKIO1WQWNTCvpVUvOZhgSC40JD0dOctaSqzkCRbXsKlb11Oip6PCJ0IwSJM31j3akRxlP7Rwn6aGaUL0qiLnJkvB3xWZ2+Q1TfCwpQH3G0o92UzmX4o/oJNQMMSQc547wVHhdk+VCw01DFYEnTxzZKAm74QmeNNR1w6WzEhNK15VJzuCdxQ53dRUDws5KvwgBMOEgpcVNe0hZI6RXT1Jd0cyj5nsaEAHgVmGaJIlWdsc5Ui2ElrRR6jrRAttNMEAIWrTDFubkZaok7/AkzfIwfuWVq0jHzuCK4QabtLUMVPB3kJ0oyHTSVFlqMALilJf2Rf8k5aaHtMfayocLBS8L89oKoxpJvnAkDPa0qp5DAUTHKWmCcnthlou8iCKaFFLHWcINd1nyIwXqrSxMNmSs6KmoL2QrKuWtlQ5V0120xQ5vRyZS1rgFkWwhiOwiuQbR0OOVhQM9iS3tiXp4RawRPMp5tDletOOBL95MpM01dZTBM9pkn5qF010rIeHFcFZhmSGpYpTsI6nwhqe5C9ynhlpp5ophuRb6WcJFldkVnVEwwxVfrVkvnWUuNLCg5bgboFHPDlDPDmnK7hUrWiIbjadDclujlZcaokOFup4Ri1kacV6jmrrK1hN9bGwpKEBQ4Q6DvIUXOmo6U5LqQM6EPyiKNjVkPnJkDPNEaxhiFay5ExW1NXVUGqcpYYdPcGiCq7z/TSlbhL4pplWXKd7NZO5QQFrefhRQW/NHOsqcIglc4UhWklR8K0QzbAw08CBDnpbgqXdeD/QUsM4RZXDFBW6WJKe/mFPdH0LtBgiq57wFLzlyQzz82qYx5D5WJP5yVJDW01BfyHnS6HKO/reZqId1WGa4Hkh2kWodJ8i6KoIPlAj2hPt76CzXsVR6koPRzWTfKqIentatYpQw2me4AA3y1Kind3SwoOKZDcFXTwl9tWU6mfgRk9d71sKtlNwrjnYw5tC5n5LdKiGry3JKNlHEd3oaMCFHrazBPMp/uNJ+V7IudcSbeOIdjUEdwl0VHCOZo5t6YluEuaC9mQeMgSfOyKnYGFHcIeQ84yQWbuJYJpZw5CzglDH7gKnWqqM9ZTaXcN0TeYhR84eQtJT76JJ1lREe7WnnvsMmRc9FQ7SBBM9mV3lCUdmHk/S2RAMt0QjFNFqQpWjDPQ01DXWUdDBkXziKPjGEP3VP+zIWU2t7im41FOloyWzn/L6dkUy3VLDaZ6appgDLHPjJEsyvJngWEPUyVBiAaHCTEXwrLvSEbV1e1gKJniicWorC1MUrVjB3uDhJE/wgSOzk1DXpk0k73qCM8xw2UvD5kJmDUfOomqMpWCkJRlvKXGmoeBm18USjVIk04SClxTB6YrgLAPLWYK9HLUt5cmc0vYES8GnTeRc6skZbQkWdxRsIcyBRzx1DbTk9FbU0caTPOgJHhJKnOGIVhQqvKmo0llRw9sabrZkDtdg3PqaKi9oatjY8B+G371paMg6+mZFNNtQ04mWBq3rYLOmtWWQp8KJnpy9DdFensyjdqZ+yY40VJlH8wcdLzC8PZnvHMFUTZUrDTkLyQaGus5X5LzpYAf3i+e/ZlhqGqWhh6Ou6xTR9Z6oi5AZZtp7Mj2EEm8oSpxiYZCHU/1fbGdNNNRRoZMhmilEb2gqHOEJDtXkHK/JnG6IrvbPCwV3NhONVdS1thBMs1T4QOBcTWa2IzhMk2nW5Kyn9tXUtpv9RsG2msxk+ZsQzRQacJncpgke0+T8y5Fzj8BiGo7XlJjaTIlpQs7KFjpqGnKuoyEPeIKnFMkZHvopgh81ySxNFWvJWcKRs70j2FOT012IllEEO1n4pD1513Yg2ssQPOThOkvyrqHUdEXOSEsihmBbTbKX1kLBPWqWkLOqJbjB3GBIZmoa8qWl4CG/iZ7oiA72ZL7TJNeZUY7kFQftDcHHluBzRbCegzMtrRjVQpX2lgoPKKLJAkcbMl01XK2p7yhL8pCBbQ3BN2avJgKvttcrWDK3CiUOVxQ8ZP+pqXKyIxnmBymCg5vJjNfkPK4+c8cIfK8ocVt7kmfd/I5SR1hKvCzUtb+lhgc00ZaO6CyhIQP1Uv4yIZjload72PXX0OIJvnFU+0Zf6MhsJwTfW0r0UwQfW4LNLZl5HK261JCZ4qnBaAreVAS3WrjV0LBnNDUNNDToCEeFfwgcb4gOEqLRhirWkexrCEYKVV711DLYEE1XBEsp5tpTGjorkomKYF9FDXv7fR3BGwbettSxnyL53MBPjsxDZjMh+VUW9NRxq1DhVk+FSxQcaGjV9Pawv6eGByw5qzoy7xk4RsOShqjJwWKe/1pEEfzkobeD/dQJmpqedcyBTy2sr4nGNRH0c0SPWTLrqAc0OQcb/gemKgqucQT7ySWKCn2EUotoCvpZct7RO2sy/QW0IWcXd7pQRQyZVwT2USRO87uhjioTLKV2brpMUcMQRbKH/N2T+UlTpaMls6cmc6CCNy3JdYYSUzzJQ4oSD3oKLncULOiJvjBEC2oqnCJkJluCYy2ZQ5so9YYlZ1VLlQU1mXEW1jZERwj/MUSRc24TdexlqLKfQBtDTScJUV8FszXBEY5ktpD5Ur9hYB4Nb1iikw3JoYpkKX+RodRKFt53MMuRnKSpY31PwYaGaILh3wxJGz9TkTPEETxoCWZrgvOlmyMzxFEwVJE5xZKzvyJ4WxEc16Gd4Xe3Weq4XH2jKRikqOkGQ87hQnC7wBmGYLAnesX3M+S87eFATauuN+Qcrh7xIxXJbUIdMw3JGE3ylCWzrieaqCn4zhGM19TQ3z1oH1AX+pWEqIc7wNGAkULBo/ZxRaV9NNyh4Br3rCHZzbzmSfawBL0dNRwpW1kK9mxPXR9povcdrGSZK9c2k0xwFGzjuniCtRSZCZ6ccZ7gaktmgAOtKbG/JnOkJrjcQTdFMsxRQ2cLY3WTIrlCw1eWKn8R6pvt4GFDso3QoL4a3nLk3G6JrtME3dSenpx7PNFTmga0EaJTLQ061sEeQoWXhSo9LTXsaSjoJQRXeZLtDclbCrYzfzHHeaKjHCVOUkQHO3JeEepr56mhiyaYYKjjNU+Fed1wS5VlhWSqI/hYUdDOkaxiKehoyOnrCV5yBHtbWFqTHCCwtpDcYolesVR5yUzTZBb3RNMd0d6WP+SvhuBmRcGxnuQzT95IC285cr41cLGQ6aJJhmi4TMGempxeimBRQw1tFKV+8jd6KuzoSTqqDxzRtpZkurvKEHxlqXKRIjjfUNNXQsNOsRScoWFLT+YeRZVD3GRN0MdQcKqQjHDMrdGGVu3iYJpQx3WGUvfbmxwFfR20WBq0oYY7LMFhhgYtr8jpaEnaOzjawWWaTP8mMr0t/EPDPoqcnxTBI5o58L7uoWnMrpoqPwgVrlAUWE+V+TQl9rawoyP6QGAlQw2TPRX+YSkxyBC8Z6jhHkXBgQL7WII3DVFnRfCrBfxewv9D6xsyjys4VkhWb9pUU627JllV0YDNHMku/ldNMMXDEo4aFnAkk4U6frNEU4XgZUPmEKHUl44KrzmYamjAbh0JFvGnaTLPu1s9jPCwjFpYiN7z1DTOk/nc07CfDFzmCf7i+bfNHXhDtLeBXzTBT5rkMvWOIxpl4EMh2LGJBu2syDnAEx2naEhHDWMMzPZEhygyS1mS5RTJr5ZkoKbEUoYqr2kqdDUE8ztK7OaIntJkFrIECwv8LJTaVx5XJE86go8dFeZ3FN3rjabCAYpoYEeC9zzJVULBbmZhDyd7ko09ydpNZ3nm2Kee4FPPXHnYEF1nqOFEC08LUVcDvYXkJHW8gTaKCk9YGOeIJhqiE4ToPEepdp7IWFjdwnWaufGMwJJCMtUTTBBK9BGCOy2tGGrJTHIwyEOzp6aPzNMOtlZkDvcEWpP5SVNhfkvDxhmSazTJXYrM9U1E0xwFVwqZQwzJxw6+kGGGUj2FglGGmnb1/G51udRSMNlTw6GGnCcUwVcOpmsqTHa06o72sw1RL02p9z0VbnMLOaIX3QKaYKSCFQzBKEUNHTSc48k53RH9wxGMtpQa5KjjW0W0n6XCCCG4yxNNdhQ4R4l1Ff+2sSd6UFHiIEOyqqFgT01mEUMD+joy75jPhOA+oVVLm309FR4yVOlp4RhLiScNmSmaYF5Pw0STrOIoWMSR2UkRXOMp+M4SHW8o8Zoi6OZgjKOaFar8zZDzkWzvKOjkKBjmCXby8JahhjXULY4KlzgKLvAwxVGhvyd4zxB1d9T0piazmKLCVZY5sKiD0y2ZSYrkUEPUbIk+dlQ4SJHTR50k1DPaUWIdTZW9NJwnJMOECgd7ou/MnppMJ02O1VT4Wsh85MnZzcFTngpXGKo84qmwgKbCL/orR/SzJ2crA+t6Mp94KvxJUeIbT3CQu1uIdlQEOzlKfS3UMcrTiFmOuroocrZrT2AcmamOKg8YomeEKm/rlT2sociMaybaUlFhuqHCM2qIJ+rg4EcDFymiDSxzaHdPcpE62pD5kyM5SBMoA1PaUtfIthS85ig1VPiPPYXgYEMNk4Qq7TXBgo7oT57gPUdwgCHzhIVFPFU6OYJzHAX9m5oNrVjeE61miDrqQ4VSa1oiURTsKHC0IfjNwU2WzK6eqK8jWln4g15TVBnqmDteCJ501PGAocJhhqjZdtBEB6lnhLreFJKxmlKbeGrqLiSThVIbCdGzloasa6lpMQXHCME2boLpJgT7yWaemu6wBONbqGNVRS0PKIL7LckbjmQtR7K8I5qtqel+T/ChJTNIKLjdUMNIRyvOEko9YYl2cwQveBikCNawJKcLBbc7+JM92mysNvd/Fqp8a0k6CNEe7cnZrxlW0wQXaXjaktnRwNOGZKYiONwS7a1JVheq3WgJHlQUGKHKmp4KAxXR/ULURcNgoa4zhKSLpZR3kxRRb0NmD0OFn+UCS7CzI1nbP6+o4x47QZE5xRCt3ZagnYcvmpYQktXdk5YKXTzBC57kKEe0VVuiSYqapssMS3C9p2CKkHOg8B8Pa8p5atrIw3qezIWanMGa5HRDNF6RM9wcacl0N+Q8Z8hsIkSnaIIdHRUOEebAPy1zbCkhM062FCJtif7PU+UtoVXzWKqM1PxXO8cfdruhFQ/a6x3JKYagvVDhQEtNiyiiSQ7OsuRsZUku0CRNDs4Sog6KKjsZgk2bYJqijgsEenoKeniinRXBn/U3lgpPdyDZynQx8IiioMnCep5Ky8mjGs6Wty0l1hUQTcNWswS3WRp2kCNZwJG8omG8JphPUaFbC8lEfabwP7VtM9yoaNCAjpR41VNhrD9LkbN722v0CoZMByFzhaW+MyzRYEWFDQwN2M4/JiT76PuljT3VU/A36eaIThb+R9oZGOAJ9tewkgGvqOMNRWYjT/Cwu99Q8LqDE4TgbLWxJ1jaDDAERsFOFrobgjUsBScaguXU8kKm2RL19tRypSHnHNlHiIZqgufs4opgQdVdwxBNNFBR6kVFqb8ogimOzB6a6HTzrlDHEpYaxjiiA4TMQobkDg2vejjfwJGWmnbVFAw3H3hq2NyQfG7hz4aC+w3BbwbesG0swYayvpAs6++Ri1Vfzx93mFChvyN5xVHTS+0p9aqCAxyZ6ZacZyw5+7uuQkFPR9DDk9NOiE7X1PCYJVjVUqq7JlrHwWALF5nfHNGjApdpqgzx5OwilDhCiDYTgnc9waGW4BdLNNUQvOtpzDOWHDH8D7TR/A/85KljEQu3NREc4Pl/6B1Hhc8Umb5CsKMmGC9EPcxoT2amwHNCmeOEnOPbklnMkbOgIvO5UMOpQrS9UGVdt6iH/fURjhI/WOpaW9OKLYRod6HCUEdOX000wpDZQ6hwg6LgZfOqo1RfT/CrJzjekXOGhpc1VW71ZLbXyyp+93ILbC1kPtIEYx0FIx1VDrLoVzXRKRYWk809yYlC9ImcrinxtabKnzRJk3lAU1OLEN1j2zrYzr2myHRXJFf4h4QKT1qSTzTB5+ZNTzTRkAxX8FcLV2uS8eoQQ2aAkFzvCM72sJIcJET3WPjRk5wi32uSS9rfZajpWEvj9hW42F4o5NytSXYy8IKHay10VYdrcl4SkqscrXpMwyGOgtkajheSxdQqmpxP1L3t4R5PqasFnrQEjytq6qgp9Y09Qx9o4S1FzhUCn1kyHSzBWLemoSGvOqLNhZyBjmCaAUYpMgt4Ck7wBBMMwWKWgjsUwTaGVsxWC1mYoKiyqqeGKYqonSIRQ3KIkHO0pmAxTdBHkbOvfllfr+AA+7gnc50huVKYK393FOyg7rbPO/izI7hE4CnHHHnJ0ogNPRUGeUpsrZZTBJcrovUcJe51BPsr6GkJdhCCsZ6aTtMEb2pqWkqeVtDXE/QVggsU/Nl86d9RMF3DxvZTA58agu810RWawCiSzzXBeU3MMW9oyJUedvNEvQyNu1f10BSMddR1vaLCYpYa/mGocLSiYDcLbQz8aMn5iyF4xBNMs1P0QEOV7o5gaWGuzSeLue4tt3ro7y4Tgm4G/mopdZgl6q0o6KzJWE3mMksNr3r+a6CbT8g5wZNzT9O7fi/zpaOmnz3BRoqos+tv9zMbdpxsqDBOEewtJLt7cg5wtKKbvldpSzRRCD43VFheCI7yZLppggMVBS/KMAdHODJvOwq2NQSbKKKPLdFWQs7Fqo+mpl01JXYRgq8dnGLhTiFzqmWsUMdpllZdbKlyvSdYxhI9YghOtxR8LgSLWHK62mGGVoxzBE8LNWzqH9CUesQzFy5RQzTc56mhi6fgXEWwpKfE5Z7M05ZgZUPmo6auiv8YKzDYwWBLMErIbKHJvOwIrvEdhOBcQ9JdU1NHQ7CXn2XIDFBKU2WAgcX9UAUzDXWd5alwuyJ41Z9rjKLCL4aCp4WarhPm2rH+SaHUYE001JDZ2ZAzXPjdMpZWvC9wmqIB2lLhQ01D5jO06hghWMndbM7yRJMsoCj1vYbnFQVrW9jak3OlEJ3s/96+p33dEPRV5GxiqaGjIthUU6FFEZyqCa5qJrpBdzSw95IUnOPIrCUUjRZQFrbw5PR0R1qiYx3cb6nrWUMrBmmiBQxVHtTew5ICP/ip6g4hed/Akob/32wvBHsIOX83cI8hGeNeNPCIkPmXe8fPKx84OMSRM1MTdXSwjCZ4S30jVGhvqTRak/OVhgGazHuOCud5onEO1lJr6ecVyaOK6H7zqlBlIaHE0oroCgfvGJIdPcmfLNGLjpz7hZwZQpUbFME0A1cIJa7VNORkgfsMBatbKgwwJM9bSvQXeNOvbIjelg6WWvo5kvbKaJJNHexkKNHL9xRyFlH8Ti2riB5wVPhUk7nGkJnoCe428LR/wRGdYIlmWebCyxou1rCk4g/ShugBDX0V0ZQWkh0dOVsagkM0yV6OoLd5ye+pRlsCr0n+KiQrGuq5yJDzrTAXHtLUMduTDBVKrSm3eHL+6ijxhFDX9Z5gVU/wliHYTMiMFpKLNMEywu80wd3meoFmt6VbRMPenhrOc6DVe4pgXU8DnnHakLOIIrlF4FZPIw6R+zxBP0dyq6OOZ4Q5sLKCcz084ok+VsMMyQhNZmmBgX5xIXOEJTmi7VsGTvMTNdHHhpzdbE8Du2oKxgvBqQKdDDnTFOylCFaxR1syz2iqrOI/FEpNc3C6f11/7+ASS6l2inq2ciTrCCzgyemrCL5SVPjQkdPZUmGy2c9Sw9FtR1sS30RmsKPCS4rkIC/2U0MduwucYolGaPjKEyhzmiPYXagyWbYz8LWBDdzRimAXzxx4z8K9hpzlhLq+NiQ97HuKorMUfK/OVvC2JfiHUPCQI/q7J2gjK+tTDNxkCc4TMssqCs4TGtLVwQihyoAWgj9bosU80XGW6Ac9TJGziaUh5+hnFcHOnlaM1iRn29NaqGENTTTSUHCH2tWTeV0osUhH6psuVLjRUmGWhm6OZEshGeNowABHcJ2Bpy2ZszRcKkRXd2QuKVEeXnbfaEq825FguqfgfE2whlChSRMdron+LATTPQ2Z369t4B9C5gs/ylzv+CMmepIDPclFQl13W0rspPd1JOcbghGOEutqCv5qacURQl3dDKyvyJlqKXGPgcM9FfawJAMVmdcspcYKOZc4GjDYkFlK05olNMHyHn4zFNykyOxt99RkHlfwmiHo60l2EKI+mhreEKp080Tbug08BVPcgoqC5zWt+NLDTZ7oNSF51N1qie7Va3uCCwyZbkINf/NED6jzOsBdZjFN8oqG3wxVunqCSYYKf3EdhJyf9YWGf7tRU2oH3VHgPr1fe5J9hOgHd7xQ0y7qBwXr23aGErP0cm64JVjZwsOGqL+mhNgZmhJLW2oY4UhedsyBgzrCKrq7BmcpNVhR6jBPq64Vgi+kn6XE68pp8J5/+0wRHGOpsKenQn9DZntPzjRLZpDAdD2fnSgkG9tmIXnUwQ6WVighs7Yi2MxQ0N3CqYaCXkJ0oyOztMDJjmSSpcpvlrk0RMMOjmArQ04PRV1DO1FwhCVaUVPpKUM03JK5SxPsIWRu8/CGHi8UHChiqGFDTbSRJWeYUDDcH6vJWUxR4k1FXbMUwV6e4AJFXS8oMqsZKqzvYQ9DDQdZckY4aGsIhtlubbd2r3j4QBMoTamdPZk7O/Bf62lacZwneNjQoGcdVU7zJOd7ghsUHOkosagic6cnWc8+4gg285R6zZP5s1/LUbCKIznTwK36PkdwlOrl4U1LwfdCCa+IrvFkmgw1PCAUXKWo0sURXWcI2muKJlgyFzhynCY4RBOsqCjoI1R5zREco0n2Vt09BQtYSizgKNHfUmUrQ5UOCh51BFcLmY7umhYqXKQomOop8bUnWNNQcIiBcYaC6xzMNOS8JQQfeqKBmmglB+97ok/lfk3ygaHSyZaCRTzRxQo6GzLfa2jWBPepw+UmT7SQEJyiyRkhBLMVOfcoMjcK0eZChfUNzFAUzCsEN5vP/X1uP/n/aoMX+K+nw/Hjr/9xOo7j7Pju61tLcgvJpTWXNbfN5jLpi6VfCOviTktKlFusQixdEKWmEBUKNaIpjZRSSOXSgzaaKLdabrm1/9nZ+/f+vd/vz/v9+Xy+zZ7PRorYoZqyLrCwQdEAixxVOEXNNnjX2nUSRlkqGmWowk8lxR50JPy9Bo6qJXaXwNvREBvnThPEPrewryLhcAnj5WE15Fqi8W7R1sAuEu86S4ENikItFN4xkv9Af4nXSnUVcLiA9xzesFpivRRVeFKtsMRaKBhuSbjOELnAUtlSQUpXgdfB4Z1oSbnFEetbQ0IrAe+Y+pqnDcEJFj6S8LDZzZHwY4e3XONNlARraomNEt2bkvGsosA3ioyHm+6jCMbI59wqt4eeara28IzEmyPgoRaUOEDhTVdEJhmCoTWfC0p8aNkCp0oYqih2iqGi4yXeMkOsn4LdLLnmKfh/YogjNsPebeFGR4m9BJHLzB61XQ3BtpISfS2FugsK9FAtLWX1dCRcrCnUp44CNzuCowUZmxSRgYaE6Za0W2u/E7CVXCiI/UOR8aAm1+OSyE3mOUcwyc1zBBeoX1kiKy0Zfxck1Gsyulti11i83QTBF5Kg3pDQThFMVHiPSlK+0cSedng/VaS8bOZbtsBcTcZAR8JP5KeqQ1OYKAi20njdNNRpgnsU//K+JnaXJaGTomr7aYIphoRn9aeShJWKEq9LcozSF7QleEfDI5LYm5bgVkFkRwVDBCVu0DDIkGupo8TZBq+/pMQURYErJQmPKGKjNDkWOLx7Jd5QizdUweIaKrlP7SwJDhZvONjLkOsBBX9UpGxnydhXkfBLQ8IxgojQbLFnJf81JytSljclYYyEFyx0kVBvKWOFJmONpshGAcsduQY5giVNCV51eOdJYo/pLhbvM0uDHSevNKRcrKZIqnCtJeEsO95RoqcgGK4ocZcho1tTYtcZvH41pNQ7vA0WrhIfOSraIIntIAi+NXWCErdbkvrWwjRLrt0NKUdL6KSOscTOdMSOUtBHwL6OLA0vNSdynaWQEnCpIvKaIrJJEbvHkmuNhn6OjM8VkSGSqn1uYJCGHnq9I3aLhNME3t6GjIkO7xrNFumpyTNX/NrwX7CrIRiqqWijI9JO4d1iieykyfiposQIQ8YjjsjlBh6oHWbwRjgYJQn2NgSnNycmJAk3NiXhx44Sxykihxm8ybUwT1OVKySc7vi3OXVkdBJ4AyXBeksDXG0IhgtYY0lY5ahCD0ehborIk5aUWRJviMA7Xt5kyRjonrXENkm8yYqgs8VzgrJmClK20uMM3jRJ0FiQICQF9hdETlLQWRIb5ki6WDfWRPobvO6a4GP5mcOrNzDFELtTkONLh9dXE8xypEg7z8A9jkhrQ6Fhjlg/QVktJXxt4WXzT/03Q8IaQWSqIuEvloQ2mqC9Jfi7wRul4RX3pSPlzpoVlmCtI2jvKHCFhjcM3sN6lqF6HxnKelLjXWbwrpR4xzuCrTUZx2qq9oAh8p6ixCUGr78g8oyjRAtB5CZFwi80VerVpI0h+IeBxa6Zg6kWvpDHaioYYuEsRbDC3eOmC2JvGYLeioxGknL2UATNJN6hmtj1DlpLvDVmocYbrGCVJKOrg4X6DgddLA203BKMFngdJJFtFd7vJLm6KEpc5yjQrkk7M80SGe34X24nSex1Ra5Omgb71JKyg8SrU3i/kARKwWpH0kOGhKkObyfd0ZGjvyXlAkVZ4xRbYJ2irFMkFY1SwyWxr2oo4zlNiV+7zmaweFpT4kR3kaDAFW6xpSqzJay05FtYR4HmZhc9UxKbbfF2V8RG1MBmSaE+kmC6JnaRXK9gsiXhJHl/U0qM0WTcbyhwkYIvFGwjSbjfwhiJt8ZSQU+Bd5+marPMOkVkD0muxYLIfEuhh60x/J92itguihJSEMySVPQnTewnEm+620rTQEMsOfo4/kP/0ARvWjitlpSX7GxBgcMEsd3EEeYWvdytd+Saawi6aCIj1CkGb6Aj9rwhx16Cf3vAwFy5pyLhVonXzy51FDpdEblbkdJbUcEPDEFzQ8qNmhzzLTmmKWKbFCXeEuRabp6rxbvAtLF442QjQ+wEA9eL1xSR7Q0JXzlSHjJ4exq89yR0laScJ/FW6z4a73pFMEfDiRZvuvijIt86RaSFOl01riV2mD1UEvxGk/Geg5aWwGki1zgKPG9J2U8PEg8qYvMsZeytiTRXBMslCU8JSlxi8EabjwUldlDNLfzTUmCgxWsjqWCOHavYAqsknKFIO0yQ61VL5AVFxk6WhEaCAkdJgt9aSkzXlKNX2jEa79waYuc7gq0N3GDJGCBhoiTXUEPsdknCUE1CK0fwsiaylSF2uiDyO4XX3pFhNd7R4itFGc0k/ElBZwWvq+GC6szVeEoS/MZ+qylwpKNKv9Z469UOjqCjwlusicyTxG6VpNxcQ8IncoR4RhLbR+NdpGGmJWOcIzJGUuKPGpQg8rrG21dOMqQssJQ4RxH5jaUqnZuQ0F4Q+cjxLwPtpZbIAk3QTJHQWBE5S1BokoVtDd6lhqr9UpHSUxMcIYl9pojsb8h4SBOsMQcqvOWC2E8EVehqiJ1hrrAEbQxeK0NGZ0Gkq+guSRgniM23bIHVkqwx4hiHd7smaOyglyIyQuM978j4VS08J/A2G1KeMBRo4fBaSNhKUEZfQewVQ/C1I+MgfbEleEzCUw7mKXI0M3hd1EESVji8x5uQ41nxs1q4RMJCCXs7Iq9acpxn22oSDnQ/sJTxsCbHIYZiLyhY05TY0ZLIOQrGaSJDDN4t8pVaIrsqqFdEegtizc1iTew5Q4ayBDMUsQMkXocaYkc0hZua412siZ1rSXlR460zRJ5SlHGe5j801RLMlJTxtaOM3Q1pvxJ45zUlWFD7rsAbpfEm1JHxG0eh8w2R7QQVzBUw28FhFp5QZzq8t2rx2joqulYTWSuJdTYfWwqMFMcovFmSyJPNyLhE4E10pHzYjOC3huArRa571ZsGajQpQx38SBP5pyZB6lMU3khDnp0MBV51BE9o2E+TY5Ml2E8S7C0o6w1xvCZjf0HkVEHCzFoyNmqC+9wdcqN+Tp7jSDheE9ws8Y5V0NJCn2bk2tqSY4okdrEhx1iDN8cSudwepWmAGXKcJXK65H9to8jYQRH7SBF01ESUJdd0TayVInaWhLkOjlXE5irKGOnI6GSWGCJa482zBI9rCr0jyTVcEuzriC1vcr6mwFGSiqy5zMwxBH/TJHwjSPhL8+01kaaSUuMFKTcLEvaUePcrSmwn8DZrgikWb7CGPxkSjhQwrRk57tctmxLsb9sZvL9LSlyuSLlWkqOjwduo8b6Uv1DkmudIeFF2dHCgxVtk8dpIvHpBxhEOdhKk7OLIUSdJ+cSRY57B+0DgGUUlNfpthTfGkauzxrvTsUUaCVhlKeteTXCoJDCa2NOKhOmC4G1H8JBd4OBZReSRGkqcb/CO1PyLJTLB4j1q8JYaIutEjSLX8YKM+a6phdMsdLFUoV5RTm9JSkuDN8WcIon0NZMNZWh1q8C7SJEwV5HxrmnnTrf3KoJBlmCYI2ilSLlfEvlE4011NNgjgthzEua0oKK7JLE7HZHlEl60BLMVFewg4EWNt0ThrVNEVkkiTwpKXSWJzdRENgvKGq4IhjsiezgSFtsfCUq8qki5S1LRQeYQQ4nemmCkImWMw3tFUoUBZk4NOeZYEp4XRKTGa6wJjrWNHBVJR4m3FCnbuD6aak2WsMTh3SZImGCIPKNgsDpVwnsa70K31lCFJZYcwwSMFcQulGTsZuEaSdBXkPGZhu0FsdUO73RHjq8MPGGIfaGIbVTk6iuI3GFgucHrIQkmWSJdBd7BBu+uOryWAhY7+Lki9rK5wtEQzWwvtbqGhIMFwWRJsElsY4m9IIg9L6lCX0VklaPAYkfkZEGDnOWowlBJjtMUkcGK4Lg6EtoZInMUBVYLgn0UsdmCyCz7gIGHFfk+k1QwTh5We7A9x+IdJ6CvIkEagms0hR50eH9UnTQJ+2oiKyVlLFUE+8gBGu8MQ3CppUHesnjTHN4QB/UGPhCTHLFPHMFrCqa73gqObUJGa03wgbhHkrCfpEpzNLE7JDS25FMKhlhKKWKfCgqstLCPu1zBXy0J2ztwjtixBu8UTRn9LVtkmCN2iyFhtME70JHRQ1KVZXqKI/KNIKYMCYs1GUMEKbM1bKOI9LDXC7zbHS+bt+1MTWS9odA9DtrYtpbImQJ2VHh/lisEwaHqUk1kjKTAKknkBEXkbkdMGwq0dnhzLJF3NJH3JVwrqOB4Sca2hti75nmJN0WzxS6UxDYoEpxpa4htVlRjkYE7DZGzJVU72uC9IyhQL4i8YfGWSYLLNcHXloyz7QhNifmKSE9JgfGmuyLhc403Xm9vqcp6gXe3xuuv8F6VJNxkyTHEkHG2g0aKXL0MsXc1bGfgas2//dCONXiNLCX+5mB7eZIl1kHh7ajwpikyzlUUWOVOsjSQlsS+M0R+pPje/dzBXRZGO0rMtgQrLLG9VSu9n6CMXS3BhwYmSoIBhsjNBmZbgusE9BCPCP5triU4VhNbJfE+swSP27aayE8tuTpYYjtrYjMVGZdp2NpS1s6aBnKSHDsbKuplKbHM4a0wMFd/5/DmGyKrJSUaW4IBrqUhx0vyfzTBBLPIUcnZdrAkNsKR0sWRspumSns6Ch0v/qqIbBYUWKvPU/CFoyrDJGwSNFhbA/MlzKqjrO80hRbpKx0Jewsi/STftwGSlKc1JZyAzx05dhLEdnfQvhZOqiHWWEAHC7+30FuRcZUgaO5gpaIK+xsiHRUsqaPElTV40xQZQ107Q9BZE1nryDVGU9ZSQ47bmhBpLcYpUt7S+xuK/FiT8qKjwXYw5ypS2iuCv7q1gtgjhuBuB8LCFY5cUuCNtsQOFcT+4Ih9JX+k8Ea6v0iCIRZOtCT0Et00JW5UeC85Cg0ScK0k411HcG1zKtre3SeITBRk7WfwDhEvaYLTHP9le0m8By0JDwn4TlLW/aJOvGHxdjYUes+ScZigCkYQdNdEOhkiezgShqkx8ueKjI8lDfK2oNiOFvrZH1hS+tk7NV7nOmLHicGWEgubkXKdwdtZknCLJXaCpkrjZBtLZFsDP9CdxWsSr05Sxl6CMmoFbCOgryX40uDtamB7SVmXW4Ihlgpmq+00tBKUUa83WbjLUNkzDmY7cow1JDygyPGlhgGKYKz4vcV7QBNbJIgM11TUqZaMdwTeSguH6rOaw1JRKzaaGyxVm2EJ/uCIrVWUcZUkcp2grMsEjK+DMwS59jQk3Kd6SEq1d0S6uVmO4Bc1lDXTUcHjluCXEq+1OlBDj1pi9zgiXxnKuE0SqTXwhqbETW6RggMEnGl/q49UT2iCzgJvRwVXS2K/d6+ZkyUl7jawSVLit46EwxVljDZwoSQ20sDBihztHfk2yA8NVZghiXwrYHQdfKAOtzsayjhY9bY0yE2CWEeJ9xfzO423xhL5syS2TFJofO2pboHob0nY4GiAgRrvGQEDa/FWSsoaaYl0syRsEt3kWoH3B01shCXhTUWe9w3Bt44SC9QCh3eShQctwbaK2ApLroGCMlZrYqvlY3qYhM0aXpFkPOuoqJ3Dm6fxXrGwVF9gCWZagjPqznfkuMKQ8DPTQRO8ZqG1hPGKEm9IgpGW4DZDgTNriTxvFiq+Lz+0cKfp4wj6OCK9JSnzNSn9LFU7UhKZZMnYwcJ8s8yRsECScK4j5UOB95HFO0CzhY4xJxuCix0lDlEUeMdS6EZBkTsUkZ4K74dugyTXS7aNgL8aqjDfkCE0ZbwkCXpaWCKhl8P7VD5jxykivSyxyZrYERbe168LYu9ZYh86IkscgVLE7tWPKmJv11CgoyJltMEbrohtVAQfO4ImltiHEroYEs7RxAarVpY8AwXMcMReFOTYWe5iiLRQxJ5Q8DtJ8LQhWOhIeFESPGsILhbNDRljNbHzNRlTFbk2S3L0NOS6V1KFJYKUbSTcIIhM0wQ/s2TM0SRMNcQmSap3jCH4yhJZKSkwyRHpYYgsFeQ4U7xoCB7VVOExhXepo9ABBsYbvGWKXPME3lyH95YioZ0gssQRWWbI+FaSMkXijZXwgiTlYdPdkNLaETxlyDVIwqeaEus0aTcYcg0RVOkpR3CSJqIddK+90JCxzsDVloyrFd5ZAr4TBKfaWa6boEA7C7s6EpYaeFPjveooY72mjIccLHJ9HUwVlDhKkmutJDJBwnp1rvulJZggKDRfbXAkvC/4l3ozQOG9a8lxjx0i7nV4jSXc7vhe3OwIxjgSHjdEhhsif9YkPGlus3iLFDnWOFhtCZbJg0UbQcIaR67JjthoCyMEZRwhiXWyxO5QxI6w5NhT4U1WsJvDO60J34fW9hwzwlKij6ZAW9ne4L0s8C6XeBMEkd/LQy1VucBRot6QMlbivaBhoBgjqGiCJNhsqVp/S2SsG6DIONCR0dXhvWbJ+MRRZJkkuEjgDXJjFQW6SSL7GXK8Z2CZg7cVsbWGoKmEpzQ5elpiy8Ryg7dMkLLUEauzeO86CuwlSOlgYLojZWeJ9xM3S1PWfEfKl5ISLQ0MEKR8YOB2QfCxJBjrKPCN4f9MkaSsqoVXJBmP7EpFZ9UQfOoOFwSzBN4MQ8LsGrymlipcJQhmy0GaQjPqCHaXRwuCZwRbqK2Fg9wlClZqYicrIgMdZfxTQ0c7TBIbrChxmuzoKG8XRaSrIhhiyNFJkrC7oIAWMEOQa5aBekPCRknCo4IKPrYkvCDI8aYmY7WFtprgekcJZ3oLIqssCSMtFbQTJKwXYy3BY5oCh2iKPCpJOE+zRdpYgi6O2KmOAgvVCYaU4ySRek1sgyFhJ403QFHiVEmJHwtybO1gs8Hr5+BETQX3War0qZngYGgtVZtoqd6vFSk/UwdZElYqyjrF4HXUeFspIi9IGKf4j92pKGAdCYMVsbcV3kRF0N+R8LUd5PCsIGWoxDtBkCI0nKofdJQxT+LtZflvuc8Q3CjwWkq8KwUpHzkK/NmSsclCL0nseQdj5FRH5CNHSgtLiW80Of5HU9Hhlsga9bnBq3fEVltKfO5IaSTmGjjc4J0otcP7QsJUSQM8pEj5/wCuUuC2DWz8AAAAAElFTkSuQmCC"); -} diff --git a/backend/_pv_1_3_5/static/codemirror/theme/base16-dark.css b/backend/_pv_1_3_5/static/codemirror/theme/base16-dark.css deleted file mode 100755 index 026a81689..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/base16-dark.css +++ /dev/null @@ -1,38 +0,0 @@ -/* - - Name: Base16 Default Dark - Author: Chris Kempson (http://chriskempson.com) - - CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror) - Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) - -*/ - -.cm-s-base16-dark.CodeMirror { background: #151515; color: #e0e0e0; } -.cm-s-base16-dark div.CodeMirror-selected { background: #303030; } -.cm-s-base16-dark .CodeMirror-line::selection, .cm-s-base16-dark .CodeMirror-line > span::selection, .cm-s-base16-dark .CodeMirror-line > span > span::selection { background: rgba(48, 48, 48, .99); } -.cm-s-base16-dark .CodeMirror-line::-moz-selection, .cm-s-base16-dark .CodeMirror-line > span::-moz-selection, .cm-s-base16-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(48, 48, 48, .99); } -.cm-s-base16-dark .CodeMirror-gutters { background: #151515; border-right: 0px; } -.cm-s-base16-dark .CodeMirror-guttermarker { color: #ac4142; } -.cm-s-base16-dark .CodeMirror-guttermarker-subtle { color: #505050; } -.cm-s-base16-dark .CodeMirror-linenumber { color: #505050; } -.cm-s-base16-dark .CodeMirror-cursor { border-left: 1px solid #b0b0b0; } - -.cm-s-base16-dark span.cm-comment { color: #8f5536; } -.cm-s-base16-dark span.cm-atom { color: #aa759f; } -.cm-s-base16-dark span.cm-number { color: #aa759f; } - -.cm-s-base16-dark span.cm-property, .cm-s-base16-dark span.cm-attribute { color: #90a959; } -.cm-s-base16-dark span.cm-keyword { color: #ac4142; } -.cm-s-base16-dark span.cm-string { color: #f4bf75; } - -.cm-s-base16-dark span.cm-variable { color: #90a959; } -.cm-s-base16-dark span.cm-variable-2 { color: #6a9fb5; } -.cm-s-base16-dark span.cm-def { color: #d28445; } -.cm-s-base16-dark span.cm-bracket { color: #e0e0e0; } -.cm-s-base16-dark span.cm-tag { color: #ac4142; } -.cm-s-base16-dark span.cm-link { color: #aa759f; } -.cm-s-base16-dark span.cm-error { background: #ac4142; color: #b0b0b0; } - -.cm-s-base16-dark .CodeMirror-activeline-background { background: #202020; } -.cm-s-base16-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/base16-light.css b/backend/_pv_1_3_5/static/codemirror/theme/base16-light.css deleted file mode 100755 index 474e0ca9d..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/base16-light.css +++ /dev/null @@ -1,38 +0,0 @@ -/* - - Name: Base16 Default Light - Author: Chris Kempson (http://chriskempson.com) - - CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror) - Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) - -*/ - -.cm-s-base16-light.CodeMirror { background: #f5f5f5; color: #202020; } -.cm-s-base16-light div.CodeMirror-selected { background: #e0e0e0; } -.cm-s-base16-light .CodeMirror-line::selection, .cm-s-base16-light .CodeMirror-line > span::selection, .cm-s-base16-light .CodeMirror-line > span > span::selection { background: #e0e0e0; } -.cm-s-base16-light .CodeMirror-line::-moz-selection, .cm-s-base16-light .CodeMirror-line > span::-moz-selection, .cm-s-base16-light .CodeMirror-line > span > span::-moz-selection { background: #e0e0e0; } -.cm-s-base16-light .CodeMirror-gutters { background: #f5f5f5; border-right: 0px; } -.cm-s-base16-light .CodeMirror-guttermarker { color: #ac4142; } -.cm-s-base16-light .CodeMirror-guttermarker-subtle { color: #b0b0b0; } -.cm-s-base16-light .CodeMirror-linenumber { color: #b0b0b0; } -.cm-s-base16-light .CodeMirror-cursor { border-left: 1px solid #505050; } - -.cm-s-base16-light span.cm-comment { color: #8f5536; } -.cm-s-base16-light span.cm-atom { color: #aa759f; } -.cm-s-base16-light span.cm-number { color: #aa759f; } - -.cm-s-base16-light span.cm-property, .cm-s-base16-light span.cm-attribute { color: #90a959; } -.cm-s-base16-light span.cm-keyword { color: #ac4142; } -.cm-s-base16-light span.cm-string { color: #f4bf75; } - -.cm-s-base16-light span.cm-variable { color: #90a959; } -.cm-s-base16-light span.cm-variable-2 { color: #6a9fb5; } -.cm-s-base16-light span.cm-def { color: #d28445; } -.cm-s-base16-light span.cm-bracket { color: #202020; } -.cm-s-base16-light span.cm-tag { color: #ac4142; } -.cm-s-base16-light span.cm-link { color: #aa759f; } -.cm-s-base16-light span.cm-error { background: #ac4142; color: #505050; } - -.cm-s-base16-light .CodeMirror-activeline-background { background: #DDDCDC; } -.cm-s-base16-light .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/bespin.css b/backend/_pv_1_3_5/static/codemirror/theme/bespin.css deleted file mode 100755 index 60913ba93..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/bespin.css +++ /dev/null @@ -1,34 +0,0 @@ -/* - - Name: Bespin - Author: Mozilla / Jan T. Sott - - CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror) - Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) - -*/ - -.cm-s-bespin.CodeMirror {background: #28211c; color: #9d9b97;} -.cm-s-bespin div.CodeMirror-selected {background: #36312e !important;} -.cm-s-bespin .CodeMirror-gutters {background: #28211c; border-right: 0px;} -.cm-s-bespin .CodeMirror-linenumber {color: #666666;} -.cm-s-bespin .CodeMirror-cursor {border-left: 1px solid #797977 !important;} - -.cm-s-bespin span.cm-comment {color: #937121;} -.cm-s-bespin span.cm-atom {color: #9b859d;} -.cm-s-bespin span.cm-number {color: #9b859d;} - -.cm-s-bespin span.cm-property, .cm-s-bespin span.cm-attribute {color: #54be0d;} -.cm-s-bespin span.cm-keyword {color: #cf6a4c;} -.cm-s-bespin span.cm-string {color: #f9ee98;} - -.cm-s-bespin span.cm-variable {color: #54be0d;} -.cm-s-bespin span.cm-variable-2 {color: #5ea6ea;} -.cm-s-bespin span.cm-def {color: #cf7d34;} -.cm-s-bespin span.cm-error {background: #cf6a4c; color: #797977;} -.cm-s-bespin span.cm-bracket {color: #9d9b97;} -.cm-s-bespin span.cm-tag {color: #cf6a4c;} -.cm-s-bespin span.cm-link {color: #9b859d;} - -.cm-s-bespin .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;} -.cm-s-bespin .CodeMirror-activeline-background { background: #404040; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/blackboard.css b/backend/_pv_1_3_5/static/codemirror/theme/blackboard.css deleted file mode 100755 index b6eaedb18..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/blackboard.css +++ /dev/null @@ -1,32 +0,0 @@ -/* Port of TextMate's Blackboard theme */ - -.cm-s-blackboard.CodeMirror { background: #0C1021; color: #F8F8F8; } -.cm-s-blackboard div.CodeMirror-selected { background: #253B76; } -.cm-s-blackboard .CodeMirror-line::selection, .cm-s-blackboard .CodeMirror-line > span::selection, .cm-s-blackboard .CodeMirror-line > span > span::selection { background: rgba(37, 59, 118, .99); } -.cm-s-blackboard .CodeMirror-line::-moz-selection, .cm-s-blackboard .CodeMirror-line > span::-moz-selection, .cm-s-blackboard .CodeMirror-line > span > span::-moz-selection { background: rgba(37, 59, 118, .99); } -.cm-s-blackboard .CodeMirror-gutters { background: #0C1021; border-right: 0; } -.cm-s-blackboard .CodeMirror-guttermarker { color: #FBDE2D; } -.cm-s-blackboard .CodeMirror-guttermarker-subtle { color: #888; } -.cm-s-blackboard .CodeMirror-linenumber { color: #888; } -.cm-s-blackboard .CodeMirror-cursor { border-left: 1px solid #A7A7A7; } - -.cm-s-blackboard .cm-keyword { color: #FBDE2D; } -.cm-s-blackboard .cm-atom { color: #D8FA3C; } -.cm-s-blackboard .cm-number { color: #D8FA3C; } -.cm-s-blackboard .cm-def { color: #8DA6CE; } -.cm-s-blackboard .cm-variable { color: #FF6400; } -.cm-s-blackboard .cm-operator { color: #FBDE2D; } -.cm-s-blackboard .cm-comment { color: #AEAEAE; } -.cm-s-blackboard .cm-string { color: #61CE3C; } -.cm-s-blackboard .cm-string-2 { color: #61CE3C; } -.cm-s-blackboard .cm-meta { color: #D8FA3C; } -.cm-s-blackboard .cm-builtin { color: #8DA6CE; } -.cm-s-blackboard .cm-tag { color: #8DA6CE; } -.cm-s-blackboard .cm-attribute { color: #8DA6CE; } -.cm-s-blackboard .cm-header { color: #FF6400; } -.cm-s-blackboard .cm-hr { color: #AEAEAE; } -.cm-s-blackboard .cm-link { color: #8DA6CE; } -.cm-s-blackboard .cm-error { background: #9D1E15; color: #F8F8F8; } - -.cm-s-blackboard .CodeMirror-activeline-background { background: #3C3636; } -.cm-s-blackboard .CodeMirror-matchingbracket { outline:1px solid grey;color:white !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/cobalt.css b/backend/_pv_1_3_5/static/codemirror/theme/cobalt.css deleted file mode 100755 index d88223ed8..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/cobalt.css +++ /dev/null @@ -1,25 +0,0 @@ -.cm-s-cobalt.CodeMirror { background: #002240; color: white; } -.cm-s-cobalt div.CodeMirror-selected { background: #b36539; } -.cm-s-cobalt .CodeMirror-line::selection, .cm-s-cobalt .CodeMirror-line > span::selection, .cm-s-cobalt .CodeMirror-line > span > span::selection { background: rgba(179, 101, 57, .99); } -.cm-s-cobalt .CodeMirror-line::-moz-selection, .cm-s-cobalt .CodeMirror-line > span::-moz-selection, .cm-s-cobalt .CodeMirror-line > span > span::-moz-selection { background: rgba(179, 101, 57, .99); } -.cm-s-cobalt .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; } -.cm-s-cobalt .CodeMirror-guttermarker { color: #ffee80; } -.cm-s-cobalt .CodeMirror-guttermarker-subtle { color: #d0d0d0; } -.cm-s-cobalt .CodeMirror-linenumber { color: #d0d0d0; } -.cm-s-cobalt .CodeMirror-cursor { border-left: 1px solid white; } - -.cm-s-cobalt span.cm-comment { color: #08f; } -.cm-s-cobalt span.cm-atom { color: #845dc4; } -.cm-s-cobalt span.cm-number, .cm-s-cobalt span.cm-attribute { color: #ff80e1; } -.cm-s-cobalt span.cm-keyword { color: #ffee80; } -.cm-s-cobalt span.cm-string { color: #3ad900; } -.cm-s-cobalt span.cm-meta { color: #ff9d00; } -.cm-s-cobalt span.cm-variable-2, .cm-s-cobalt span.cm-tag { color: #9effff; } -.cm-s-cobalt span.cm-variable-3, .cm-s-cobalt span.cm-def { color: white; } -.cm-s-cobalt span.cm-bracket { color: #d8d8d8; } -.cm-s-cobalt span.cm-builtin, .cm-s-cobalt span.cm-special { color: #ff9e59; } -.cm-s-cobalt span.cm-link { color: #845dc4; } -.cm-s-cobalt span.cm-error { color: #9d1e15; } - -.cm-s-cobalt .CodeMirror-activeline-background { background: #002D57; } -.cm-s-cobalt .CodeMirror-matchingbracket { outline:1px solid grey;color:white !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/colorforth.css b/backend/_pv_1_3_5/static/codemirror/theme/colorforth.css deleted file mode 100755 index 606899f30..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/colorforth.css +++ /dev/null @@ -1,33 +0,0 @@ -.cm-s-colorforth.CodeMirror { background: #000000; color: #f8f8f8; } -.cm-s-colorforth .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; } -.cm-s-colorforth .CodeMirror-guttermarker { color: #FFBD40; } -.cm-s-colorforth .CodeMirror-guttermarker-subtle { color: #78846f; } -.cm-s-colorforth .CodeMirror-linenumber { color: #bababa; } -.cm-s-colorforth .CodeMirror-cursor { border-left: 1px solid white; } - -.cm-s-colorforth span.cm-comment { color: #ededed; } -.cm-s-colorforth span.cm-def { color: #ff1c1c; font-weight:bold; } -.cm-s-colorforth span.cm-keyword { color: #ffd900; } -.cm-s-colorforth span.cm-builtin { color: #00d95a; } -.cm-s-colorforth span.cm-variable { color: #73ff00; } -.cm-s-colorforth span.cm-string { color: #007bff; } -.cm-s-colorforth span.cm-number { color: #00c4ff; } -.cm-s-colorforth span.cm-atom { color: #606060; } - -.cm-s-colorforth span.cm-variable-2 { color: #EEE; } -.cm-s-colorforth span.cm-variable-3 { color: #DDD; } -.cm-s-colorforth span.cm-property {} -.cm-s-colorforth span.cm-operator {} - -.cm-s-colorforth span.cm-meta { color: yellow; } -.cm-s-colorforth span.cm-qualifier { color: #FFF700; } -.cm-s-colorforth span.cm-bracket { color: #cc7; } -.cm-s-colorforth span.cm-tag { color: #FFBD40; } -.cm-s-colorforth span.cm-attribute { color: #FFF700; } -.cm-s-colorforth span.cm-error { color: #f00; } - -.cm-s-colorforth div.CodeMirror-selected { background: #333d53; } - -.cm-s-colorforth span.cm-compilation { background: rgba(255, 255, 255, 0.12); } - -.cm-s-colorforth .CodeMirror-activeline-background { background: #253540; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/dracula.css b/backend/_pv_1_3_5/static/codemirror/theme/dracula.css deleted file mode 100755 index 53a660b52..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/dracula.css +++ /dev/null @@ -1,40 +0,0 @@ -/* - - Name: dracula - Author: Michael Kaminsky (http://github.com/mkaminsky11) - - Original dracula color scheme by Zeno Rocha (https://github.com/zenorocha/dracula-theme) - -*/ - - -.cm-s-dracula.CodeMirror, .cm-s-dracula .CodeMirror-gutters { - background-color: #282a36 !important; - color: #f8f8f2 !important; - border: none; -} -.cm-s-dracula .CodeMirror-gutters { color: #282a36; } -.cm-s-dracula .CodeMirror-cursor { border-left: solid thin #f8f8f0; } -.cm-s-dracula .CodeMirror-linenumber { color: #6D8A88; } -.cm-s-dracula .CodeMirror-selected { background: rgba(255, 255, 255, 0.10); } -.cm-s-dracula .CodeMirror-line::selection, .cm-s-dracula .CodeMirror-line > span::selection, .cm-s-dracula .CodeMirror-line > span > span::selection { background: rgba(255, 255, 255, 0.10); } -.cm-s-dracula .CodeMirror-line::-moz-selection, .cm-s-dracula .CodeMirror-line > span::-moz-selection, .cm-s-dracula .CodeMirror-line > span > span::-moz-selection { background: rgba(255, 255, 255, 0.10); } -.cm-s-dracula span.cm-comment { color: #6272a4; } -.cm-s-dracula span.cm-string, .cm-s-dracula span.cm-string-2 { color: #f1fa8c; } -.cm-s-dracula span.cm-number { color: #bd93f9; } -.cm-s-dracula span.cm-variable { color: #50fa7b; } -.cm-s-dracula span.cm-variable-2 { color: white; } -.cm-s-dracula span.cm-def { color: #50fa7b; } -.cm-s-dracula span.cm-operator { color: #ff79c6; } -.cm-s-dracula span.cm-keyword { color: #ff79c6; } -.cm-s-dracula span.cm-atom { color: #bd93f9; } -.cm-s-dracula span.cm-meta { color: #f8f8f2; } -.cm-s-dracula span.cm-tag { color: #ff79c6; } -.cm-s-dracula span.cm-attribute { color: #50fa7b; } -.cm-s-dracula span.cm-qualifier { color: #50fa7b; } -.cm-s-dracula span.cm-property { color: #66d9ef; } -.cm-s-dracula span.cm-builtin { color: #50fa7b; } -.cm-s-dracula span.cm-variable-3 { color: #ffb86c; } - -.cm-s-dracula .CodeMirror-activeline-background { background: rgba(255,255,255,0.1); } -.cm-s-dracula .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/duotone-dark.css b/backend/_pv_1_3_5/static/codemirror/theme/duotone-dark.css deleted file mode 100755 index b09a585c9..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/duotone-dark.css +++ /dev/null @@ -1,35 +0,0 @@ -/* -Name: DuoTone-Dark -Author: by Bram de Haan, adapted from DuoTone themes by Simurai (http://simurai.com/projects/2016/01/01/duotone-themes) - -CodeMirror template by Jan T. Sott (https://github.com/idleberg), adapted by Bram de Haan (https://github.com/atelierbram/) -*/ - -.cm-s-duotone-dark.CodeMirror { background: #2a2734; color: #6c6783; } -.cm-s-duotone-dark div.CodeMirror-selected { background: #545167!important; } -.cm-s-duotone-dark .CodeMirror-gutters { background: #2a2734; border-right: 0px; } -.cm-s-duotone-dark .CodeMirror-linenumber { color: #545167; } - -/* begin cursor */ -.cm-s-duotone-dark .CodeMirror-cursor { border-left: 1px solid #ffad5c; /* border-left: 1px solid #ffad5c80; */ border-right: .5em solid #ffad5c; /* border-right: .5em solid #ffad5c80; */ opacity: .5; } -.cm-s-duotone-dark .CodeMirror-activeline-background { background: #363342; /* background: #36334280; */ opacity: .5;} -.cm-s-duotone-dark .cm-fat-cursor .CodeMirror-cursor { background: #ffad5c; /* background: #ffad5c80; */ opacity: .5;} -/* end cursor */ - -.cm-s-duotone-dark span.cm-atom, .cm-s-duotone-dark span.cm-number, .cm-s-duotone-dark span.cm-keyword, .cm-s-duotone-dark span.cm-variable, .cm-s-duotone-dark span.cm-attribute, .cm-s-duotone-dark span.cm-quote, .cm-s-duotone-dark span.cm-hr, .cm-s-duotone-dark span.cm-link { color: #ffcc99; } - -.cm-s-duotone-dark span.cm-property { color: #9a86fd; } -.cm-s-duotone-dark span.cm-punctuation, .cm-s-duotone-dark span.cm-unit, .cm-s-duotone-dark span.cm-negative { color: #e09142; } -.cm-s-duotone-dark span.cm-string { color: #ffb870; } -.cm-s-duotone-dark span.cm-operator { color: #ffad5c; } -.cm-s-duotone-dark span.cm-positive { color: #6a51e6; } - -.cm-s-duotone-dark span.cm-variable-2, .cm-s-duotone-dark span.cm-variable-3, .cm-s-duotone-dark span.cm-string-2, .cm-s-duotone-dark span.cm-url { color: #7a63ee; } -.cm-s-duotone-dark span.cm-def, .cm-s-duotone-dark span.cm-tag, .cm-s-duotone-dark span.cm-builtin, .cm-s-duotone-dark span.cm-qualifier, .cm-s-duotone-dark span.cm-header, .cm-s-duotone-dark span.cm-em { color: #eeebff; } -.cm-s-duotone-dark span.cm-bracket, .cm-s-duotone-dark span.cm-comment { color: #6c6783; } - -/* using #f00 red for errors, don't think any of the colorscheme variables will stand out enough, ... maybe by giving it a background-color ... */ -.cm-s-duotone-dark span.cm-error, .cm-s-duotone-dark span.cm-invalidchar { color: #f00; } - -.cm-s-duotone-dark span.cm-header { font-weight: normal; } -.cm-s-duotone-dark .CodeMirror-matchingbracket { text-decoration: underline; color: #eeebff !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/duotone-light.css b/backend/_pv_1_3_5/static/codemirror/theme/duotone-light.css deleted file mode 100755 index 80203d15d..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/duotone-light.css +++ /dev/null @@ -1,36 +0,0 @@ -/* -Name: DuoTone-Light -Author: by Bram de Haan, adapted from DuoTone themes by Simurai (http://simurai.com/projects/2016/01/01/duotone-themes) - -CodeMirror template by Jan T. Sott (https://github.com/idleberg), adapted by Bram de Haan (https://github.com/atelierbram/) -*/ - -.cm-s-duotone-light.CodeMirror { background: #faf8f5; color: #b29762; } -.cm-s-duotone-light div.CodeMirror-selected { background: #e3dcce !important; } -.cm-s-duotone-light .CodeMirror-gutters { background: #faf8f5; border-right: 0px; } -.cm-s-duotone-light .CodeMirror-linenumber { color: #cdc4b1; } - -/* begin cursor */ -.cm-s-duotone-light .CodeMirror-cursor { border-left: 1px solid #93abdc; /* border-left: 1px solid #93abdc80; */ border-right: .5em solid #93abdc; /* border-right: .5em solid #93abdc80; */ opacity: .5; } -.cm-s-duotone-light .CodeMirror-activeline-background { background: #e3dcce; /* background: #e3dcce80; */ opacity: .5; } -.cm-s-duotone-light .cm-fat-cursor .CodeMirror-cursor { background: #93abdc; /* #93abdc80; */ opacity: .5; } -/* end cursor */ - -.cm-s-duotone-light span.cm-atom, .cm-s-duotone-light span.cm-number, .cm-s-duotone-light span.cm-keyword, .cm-s-duotone-light span.cm-variable, .cm-s-duotone-light span.cm-attribute, .cm-s-duotone-light span.cm-quote, .cm-s-duotone-light-light span.cm-hr, .cm-s-duotone-light-light span.cm-link { color: #063289; } - -.cm-s-duotone-light span.cm-property { color: #b29762; } -.cm-s-duotone-light span.cm-punctuation, .cm-s-duotone-light span.cm-unit, .cm-s-duotone-light span.cm-negative { color: #063289; } -.cm-s-duotone-light span.cm-string, .cm-s-duotone-light span.cm-operator { color: #1659df; } -.cm-s-duotone-light span.cm-positive { color: #896724; } - -.cm-s-duotone-light span.cm-variable-2, .cm-s-duotone-light span.cm-variable-3, .cm-s-duotone-light span.cm-string-2, .cm-s-duotone-light span.cm-url { color: #896724; } -.cm-s-duotone-light span.cm-def, .cm-s-duotone-light span.cm-tag, .cm-s-duotone-light span.cm-builtin, .cm-s-duotone-light span.cm-qualifier, .cm-s-duotone-light span.cm-header, .cm-s-duotone-light span.cm-em { color: #2d2006; } -.cm-s-duotone-light span.cm-bracket, .cm-s-duotone-light span.cm-comment { color: #b6ad9a; } - -/* using #f00 red for errors, don't think any of the colorscheme variables will stand out enough, ... maybe by giving it a background-color ... */ -/* .cm-s-duotone-light span.cm-error { background: #896724; color: #728fcb; } */ -.cm-s-duotone-light span.cm-error, .cm-s-duotone-light span.cm-invalidchar { color: #f00; } - -.cm-s-duotone-light span.cm-header { font-weight: normal; } -.cm-s-duotone-light .CodeMirror-matchingbracket { text-decoration: underline; color: #faf8f5 !important; } - diff --git a/backend/_pv_1_3_5/static/codemirror/theme/eclipse.css b/backend/_pv_1_3_5/static/codemirror/theme/eclipse.css deleted file mode 100755 index 1bde460e9..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/eclipse.css +++ /dev/null @@ -1,23 +0,0 @@ -.cm-s-eclipse span.cm-meta { color: #FF1717; } -.cm-s-eclipse span.cm-keyword { line-height: 1em; font-weight: bold; color: #7F0055; } -.cm-s-eclipse span.cm-atom { color: #219; } -.cm-s-eclipse span.cm-number { color: #164; } -.cm-s-eclipse span.cm-def { color: #00f; } -.cm-s-eclipse span.cm-variable { color: black; } -.cm-s-eclipse span.cm-variable-2 { color: #0000C0; } -.cm-s-eclipse span.cm-variable-3 { color: #0000C0; } -.cm-s-eclipse span.cm-property { color: black; } -.cm-s-eclipse span.cm-operator { color: black; } -.cm-s-eclipse span.cm-comment { color: #3F7F5F; } -.cm-s-eclipse span.cm-string { color: #2A00FF; } -.cm-s-eclipse span.cm-string-2 { color: #f50; } -.cm-s-eclipse span.cm-qualifier { color: #555; } -.cm-s-eclipse span.cm-builtin { color: #30a; } -.cm-s-eclipse span.cm-bracket { color: #cc7; } -.cm-s-eclipse span.cm-tag { color: #170; } -.cm-s-eclipse span.cm-attribute { color: #00c; } -.cm-s-eclipse span.cm-link { color: #219; } -.cm-s-eclipse span.cm-error { color: #f00; } - -.cm-s-eclipse .CodeMirror-activeline-background { background: #e8f2ff; } -.cm-s-eclipse .CodeMirror-matchingbracket { outline:1px solid grey; color:black !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/elegant.css b/backend/_pv_1_3_5/static/codemirror/theme/elegant.css deleted file mode 100755 index 45b3ea655..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/elegant.css +++ /dev/null @@ -1,13 +0,0 @@ -.cm-s-elegant span.cm-number, .cm-s-elegant span.cm-string, .cm-s-elegant span.cm-atom { color: #762; } -.cm-s-elegant span.cm-comment { color: #262; font-style: italic; line-height: 1em; } -.cm-s-elegant span.cm-meta { color: #555; font-style: italic; line-height: 1em; } -.cm-s-elegant span.cm-variable { color: black; } -.cm-s-elegant span.cm-variable-2 { color: #b11; } -.cm-s-elegant span.cm-qualifier { color: #555; } -.cm-s-elegant span.cm-keyword { color: #730; } -.cm-s-elegant span.cm-builtin { color: #30a; } -.cm-s-elegant span.cm-link { color: #762; } -.cm-s-elegant span.cm-error { background-color: #fdd; } - -.cm-s-elegant .CodeMirror-activeline-background { background: #e8f2ff; } -.cm-s-elegant .CodeMirror-matchingbracket { outline:1px solid grey; color:black !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/erlang-dark.css b/backend/_pv_1_3_5/static/codemirror/theme/erlang-dark.css deleted file mode 100755 index 65fe4814c..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/erlang-dark.css +++ /dev/null @@ -1,34 +0,0 @@ -.cm-s-erlang-dark.CodeMirror { background: #002240; color: white; } -.cm-s-erlang-dark div.CodeMirror-selected { background: #b36539; } -.cm-s-erlang-dark .CodeMirror-line::selection, .cm-s-erlang-dark .CodeMirror-line > span::selection, .cm-s-erlang-dark .CodeMirror-line > span > span::selection { background: rgba(179, 101, 57, .99); } -.cm-s-erlang-dark .CodeMirror-line::-moz-selection, .cm-s-erlang-dark .CodeMirror-line > span::-moz-selection, .cm-s-erlang-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(179, 101, 57, .99); } -.cm-s-erlang-dark .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; } -.cm-s-erlang-dark .CodeMirror-guttermarker { color: white; } -.cm-s-erlang-dark .CodeMirror-guttermarker-subtle { color: #d0d0d0; } -.cm-s-erlang-dark .CodeMirror-linenumber { color: #d0d0d0; } -.cm-s-erlang-dark .CodeMirror-cursor { border-left: 1px solid white; } - -.cm-s-erlang-dark span.cm-quote { color: #ccc; } -.cm-s-erlang-dark span.cm-atom { color: #f133f1; } -.cm-s-erlang-dark span.cm-attribute { color: #ff80e1; } -.cm-s-erlang-dark span.cm-bracket { color: #ff9d00; } -.cm-s-erlang-dark span.cm-builtin { color: #eaa; } -.cm-s-erlang-dark span.cm-comment { color: #77f; } -.cm-s-erlang-dark span.cm-def { color: #e7a; } -.cm-s-erlang-dark span.cm-keyword { color: #ffee80; } -.cm-s-erlang-dark span.cm-meta { color: #50fefe; } -.cm-s-erlang-dark span.cm-number { color: #ffd0d0; } -.cm-s-erlang-dark span.cm-operator { color: #d55; } -.cm-s-erlang-dark span.cm-property { color: #ccc; } -.cm-s-erlang-dark span.cm-qualifier { color: #ccc; } -.cm-s-erlang-dark span.cm-special { color: #ffbbbb; } -.cm-s-erlang-dark span.cm-string { color: #3ad900; } -.cm-s-erlang-dark span.cm-string-2 { color: #ccc; } -.cm-s-erlang-dark span.cm-tag { color: #9effff; } -.cm-s-erlang-dark span.cm-variable { color: #50fe50; } -.cm-s-erlang-dark span.cm-variable-2 { color: #e0e; } -.cm-s-erlang-dark span.cm-variable-3 { color: #ccc; } -.cm-s-erlang-dark span.cm-error { color: #9d1e15; } - -.cm-s-erlang-dark .CodeMirror-activeline-background { background: #013461; } -.cm-s-erlang-dark .CodeMirror-matchingbracket { outline:1px solid grey; color:white !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/hopscotch.css b/backend/_pv_1_3_5/static/codemirror/theme/hopscotch.css deleted file mode 100755 index 7d05431bd..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/hopscotch.css +++ /dev/null @@ -1,34 +0,0 @@ -/* - - Name: Hopscotch - Author: Jan T. Sott - - CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror) - Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) - -*/ - -.cm-s-hopscotch.CodeMirror {background: #322931; color: #d5d3d5;} -.cm-s-hopscotch div.CodeMirror-selected {background: #433b42 !important;} -.cm-s-hopscotch .CodeMirror-gutters {background: #322931; border-right: 0px;} -.cm-s-hopscotch .CodeMirror-linenumber {color: #797379;} -.cm-s-hopscotch .CodeMirror-cursor {border-left: 1px solid #989498 !important;} - -.cm-s-hopscotch span.cm-comment {color: #b33508;} -.cm-s-hopscotch span.cm-atom {color: #c85e7c;} -.cm-s-hopscotch span.cm-number {color: #c85e7c;} - -.cm-s-hopscotch span.cm-property, .cm-s-hopscotch span.cm-attribute {color: #8fc13e;} -.cm-s-hopscotch span.cm-keyword {color: #dd464c;} -.cm-s-hopscotch span.cm-string {color: #fdcc59;} - -.cm-s-hopscotch span.cm-variable {color: #8fc13e;} -.cm-s-hopscotch span.cm-variable-2 {color: #1290bf;} -.cm-s-hopscotch span.cm-def {color: #fd8b19;} -.cm-s-hopscotch span.cm-error {background: #dd464c; color: #989498;} -.cm-s-hopscotch span.cm-bracket {color: #d5d3d5;} -.cm-s-hopscotch span.cm-tag {color: #dd464c;} -.cm-s-hopscotch span.cm-link {color: #c85e7c;} - -.cm-s-hopscotch .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;} -.cm-s-hopscotch .CodeMirror-activeline-background { background: #302020; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/icecoder.css b/backend/_pv_1_3_5/static/codemirror/theme/icecoder.css deleted file mode 100755 index ffebaf2f0..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/icecoder.css +++ /dev/null @@ -1,43 +0,0 @@ -/* -ICEcoder default theme by Matt Pass, used in code editor available at https://icecoder.net -*/ - -.cm-s-icecoder { color: #666; background: #1d1d1b; } - -.cm-s-icecoder span.cm-keyword { color: #eee; font-weight:bold; } /* off-white 1 */ -.cm-s-icecoder span.cm-atom { color: #e1c76e; } /* yellow */ -.cm-s-icecoder span.cm-number { color: #6cb5d9; } /* blue */ -.cm-s-icecoder span.cm-def { color: #b9ca4a; } /* green */ - -.cm-s-icecoder span.cm-variable { color: #6cb5d9; } /* blue */ -.cm-s-icecoder span.cm-variable-2 { color: #cc1e5c; } /* pink */ -.cm-s-icecoder span.cm-variable-3 { color: #f9602c; } /* orange */ - -.cm-s-icecoder span.cm-property { color: #eee; } /* off-white 1 */ -.cm-s-icecoder span.cm-operator { color: #9179bb; } /* purple */ -.cm-s-icecoder span.cm-comment { color: #97a3aa; } /* grey-blue */ - -.cm-s-icecoder span.cm-string { color: #b9ca4a; } /* green */ -.cm-s-icecoder span.cm-string-2 { color: #6cb5d9; } /* blue */ - -.cm-s-icecoder span.cm-meta { color: #555; } /* grey */ - -.cm-s-icecoder span.cm-qualifier { color: #555; } /* grey */ -.cm-s-icecoder span.cm-builtin { color: #214e7b; } /* bright blue */ -.cm-s-icecoder span.cm-bracket { color: #cc7; } /* grey-yellow */ - -.cm-s-icecoder span.cm-tag { color: #e8e8e8; } /* off-white 2 */ -.cm-s-icecoder span.cm-attribute { color: #099; } /* teal */ - -.cm-s-icecoder span.cm-header { color: #6a0d6a; } /* purple-pink */ -.cm-s-icecoder span.cm-quote { color: #186718; } /* dark green */ -.cm-s-icecoder span.cm-hr { color: #888; } /* mid-grey */ -.cm-s-icecoder span.cm-link { color: #e1c76e; } /* yellow */ -.cm-s-icecoder span.cm-error { color: #d00; } /* red */ - -.cm-s-icecoder .CodeMirror-cursor { border-left: 1px solid white; } -.cm-s-icecoder div.CodeMirror-selected { color: #fff; background: #037; } -.cm-s-icecoder .CodeMirror-gutters { background: #1d1d1b; min-width: 41px; border-right: 0; } -.cm-s-icecoder .CodeMirror-linenumber { color: #555; cursor: default; } -.cm-s-icecoder .CodeMirror-matchingbracket { color: #fff !important; background: #555 !important; } -.cm-s-icecoder .CodeMirror-activeline-background { background: #000; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/isotope.css b/backend/_pv_1_3_5/static/codemirror/theme/isotope.css deleted file mode 100755 index d0d6263cf..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/isotope.css +++ /dev/null @@ -1,34 +0,0 @@ -/* - - Name: Isotope - Author: David Desandro / Jan T. Sott - - CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror) - Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) - -*/ - -.cm-s-isotope.CodeMirror {background: #000000; color: #e0e0e0;} -.cm-s-isotope div.CodeMirror-selected {background: #404040 !important;} -.cm-s-isotope .CodeMirror-gutters {background: #000000; border-right: 0px;} -.cm-s-isotope .CodeMirror-linenumber {color: #808080;} -.cm-s-isotope .CodeMirror-cursor {border-left: 1px solid #c0c0c0 !important;} - -.cm-s-isotope span.cm-comment {color: #3300ff;} -.cm-s-isotope span.cm-atom {color: #cc00ff;} -.cm-s-isotope span.cm-number {color: #cc00ff;} - -.cm-s-isotope span.cm-property, .cm-s-isotope span.cm-attribute {color: #33ff00;} -.cm-s-isotope span.cm-keyword {color: #ff0000;} -.cm-s-isotope span.cm-string {color: #ff0099;} - -.cm-s-isotope span.cm-variable {color: #33ff00;} -.cm-s-isotope span.cm-variable-2 {color: #0066ff;} -.cm-s-isotope span.cm-def {color: #ff9900;} -.cm-s-isotope span.cm-error {background: #ff0000; color: #c0c0c0;} -.cm-s-isotope span.cm-bracket {color: #e0e0e0;} -.cm-s-isotope span.cm-tag {color: #ff0000;} -.cm-s-isotope span.cm-link {color: #cc00ff;} - -.cm-s-isotope .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;} -.cm-s-isotope .CodeMirror-activeline-background { background: #202020; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/lesser-dark.css b/backend/_pv_1_3_5/static/codemirror/theme/lesser-dark.css deleted file mode 100755 index 690c183d7..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/lesser-dark.css +++ /dev/null @@ -1,47 +0,0 @@ -/* -http://lesscss.org/ dark theme -Ported to CodeMirror by Peter Kroon -*/ -.cm-s-lesser-dark { - line-height: 1.3em; -} -.cm-s-lesser-dark.CodeMirror { background: #262626; color: #EBEFE7; text-shadow: 0 -1px 1px #262626; } -.cm-s-lesser-dark div.CodeMirror-selected { background: #45443B; } /* 33322B*/ -.cm-s-lesser-dark .CodeMirror-line::selection, .cm-s-lesser-dark .CodeMirror-line > span::selection, .cm-s-lesser-dark .CodeMirror-line > span > span::selection { background: rgba(69, 68, 59, .99); } -.cm-s-lesser-dark .CodeMirror-line::-moz-selection, .cm-s-lesser-dark .CodeMirror-line > span::-moz-selection, .cm-s-lesser-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(69, 68, 59, .99); } -.cm-s-lesser-dark .CodeMirror-cursor { border-left: 1px solid white; } -.cm-s-lesser-dark pre { padding: 0 8px; }/*editable code holder*/ - -.cm-s-lesser-dark.CodeMirror span.CodeMirror-matchingbracket { color: #7EFC7E; }/*65FC65*/ - -.cm-s-lesser-dark .CodeMirror-gutters { background: #262626; border-right:1px solid #aaa; } -.cm-s-lesser-dark .CodeMirror-guttermarker { color: #599eff; } -.cm-s-lesser-dark .CodeMirror-guttermarker-subtle { color: #777; } -.cm-s-lesser-dark .CodeMirror-linenumber { color: #777; } - -.cm-s-lesser-dark span.cm-header { color: #a0a; } -.cm-s-lesser-dark span.cm-quote { color: #090; } -.cm-s-lesser-dark span.cm-keyword { color: #599eff; } -.cm-s-lesser-dark span.cm-atom { color: #C2B470; } -.cm-s-lesser-dark span.cm-number { color: #B35E4D; } -.cm-s-lesser-dark span.cm-def { color: white; } -.cm-s-lesser-dark span.cm-variable { color:#D9BF8C; } -.cm-s-lesser-dark span.cm-variable-2 { color: #669199; } -.cm-s-lesser-dark span.cm-variable-3 { color: white; } -.cm-s-lesser-dark span.cm-property { color: #92A75C; } -.cm-s-lesser-dark span.cm-operator { color: #92A75C; } -.cm-s-lesser-dark span.cm-comment { color: #666; } -.cm-s-lesser-dark span.cm-string { color: #BCD279; } -.cm-s-lesser-dark span.cm-string-2 { color: #f50; } -.cm-s-lesser-dark span.cm-meta { color: #738C73; } -.cm-s-lesser-dark span.cm-qualifier { color: #555; } -.cm-s-lesser-dark span.cm-builtin { color: #ff9e59; } -.cm-s-lesser-dark span.cm-bracket { color: #EBEFE7; } -.cm-s-lesser-dark span.cm-tag { color: #669199; } -.cm-s-lesser-dark span.cm-attribute { color: #00c; } -.cm-s-lesser-dark span.cm-hr { color: #999; } -.cm-s-lesser-dark span.cm-link { color: #00c; } -.cm-s-lesser-dark span.cm-error { color: #9d1e15; } - -.cm-s-lesser-dark .CodeMirror-activeline-background { background: #3C3A3A; } -.cm-s-lesser-dark .CodeMirror-matchingbracket { outline:1px solid grey; color:white !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/liquibyte.css b/backend/_pv_1_3_5/static/codemirror/theme/liquibyte.css deleted file mode 100755 index 9db8bde73..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/liquibyte.css +++ /dev/null @@ -1,95 +0,0 @@ -.cm-s-liquibyte.CodeMirror { - background-color: #000; - color: #fff; - line-height: 1.2em; - font-size: 1em; -} -.cm-s-liquibyte .CodeMirror-focused .cm-matchhighlight { - text-decoration: underline; - text-decoration-color: #0f0; - text-decoration-style: wavy; -} -.cm-s-liquibyte .cm-trailingspace { - text-decoration: line-through; - text-decoration-color: #f00; - text-decoration-style: dotted; -} -.cm-s-liquibyte .cm-tab { - text-decoration: line-through; - text-decoration-color: #404040; - text-decoration-style: dotted; -} -.cm-s-liquibyte .CodeMirror-gutters { background-color: #262626; border-right: 1px solid #505050; padding-right: 0.8em; } -.cm-s-liquibyte .CodeMirror-gutter-elt div { font-size: 1.2em; } -.cm-s-liquibyte .CodeMirror-guttermarker { } -.cm-s-liquibyte .CodeMirror-guttermarker-subtle { } -.cm-s-liquibyte .CodeMirror-linenumber { color: #606060; padding-left: 0; } -.cm-s-liquibyte .CodeMirror-cursor { border-left: 1px solid #eee; } - -.cm-s-liquibyte span.cm-comment { color: #008000; } -.cm-s-liquibyte span.cm-def { color: #ffaf40; font-weight: bold; } -.cm-s-liquibyte span.cm-keyword { color: #c080ff; font-weight: bold; } -.cm-s-liquibyte span.cm-builtin { color: #ffaf40; font-weight: bold; } -.cm-s-liquibyte span.cm-variable { color: #5967ff; font-weight: bold; } -.cm-s-liquibyte span.cm-string { color: #ff8000; } -.cm-s-liquibyte span.cm-number { color: #0f0; font-weight: bold; } -.cm-s-liquibyte span.cm-atom { color: #bf3030; font-weight: bold; } - -.cm-s-liquibyte span.cm-variable-2 { color: #007f7f; font-weight: bold; } -.cm-s-liquibyte span.cm-variable-3 { color: #c080ff; font-weight: bold; } -.cm-s-liquibyte span.cm-property { color: #999; font-weight: bold; } -.cm-s-liquibyte span.cm-operator { color: #fff; } - -.cm-s-liquibyte span.cm-meta { color: #0f0; } -.cm-s-liquibyte span.cm-qualifier { color: #fff700; font-weight: bold; } -.cm-s-liquibyte span.cm-bracket { color: #cc7; } -.cm-s-liquibyte span.cm-tag { color: #ff0; font-weight: bold; } -.cm-s-liquibyte span.cm-attribute { color: #c080ff; font-weight: bold; } -.cm-s-liquibyte span.cm-error { color: #f00; } - -.cm-s-liquibyte div.CodeMirror-selected { background-color: rgba(255, 0, 0, 0.25); } - -.cm-s-liquibyte span.cm-compilation { background-color: rgba(255, 255, 255, 0.12); } - -.cm-s-liquibyte .CodeMirror-activeline-background { background-color: rgba(0, 255, 0, 0.15); } - -/* Default styles for common addons */ -.cm-s-liquibyte .CodeMirror span.CodeMirror-matchingbracket { color: #0f0; font-weight: bold; } -.cm-s-liquibyte .CodeMirror span.CodeMirror-nonmatchingbracket { color: #f00; font-weight: bold; } -.CodeMirror-matchingtag { background-color: rgba(150, 255, 0, .3); } -/* Scrollbars */ -/* Simple */ -.cm-s-liquibyte div.CodeMirror-simplescroll-horizontal div:hover, div.CodeMirror-simplescroll-vertical div:hover { - background-color: rgba(80, 80, 80, .7); -} -.cm-s-liquibyte div.CodeMirror-simplescroll-horizontal div, div.CodeMirror-simplescroll-vertical div { - background-color: rgba(80, 80, 80, .3); - border: 1px solid #404040; - border-radius: 5px; -} -.cm-s-liquibyte div.CodeMirror-simplescroll-vertical div { - border-top: 1px solid #404040; - border-bottom: 1px solid #404040; -} -.cm-s-liquibyte div.CodeMirror-simplescroll-horizontal div { - border-left: 1px solid #404040; - border-right: 1px solid #404040; -} -.cm-s-liquibyte div.CodeMirror-simplescroll-vertical { - background-color: #262626; -} -.cm-s-liquibyte div.CodeMirror-simplescroll-horizontal { - background-color: #262626; - border-top: 1px solid #404040; -} -/* Overlay */ -.cm-s-liquibyte div.CodeMirror-overlayscroll-horizontal div, div.CodeMirror-overlayscroll-vertical div { - background-color: #404040; - border-radius: 5px; -} -.cm-s-liquibyte div.CodeMirror-overlayscroll-vertical div { - border: 1px solid #404040; -} -.cm-s-liquibyte div.CodeMirror-overlayscroll-horizontal div { - border: 1px solid #404040; -} diff --git a/backend/_pv_1_3_5/static/codemirror/theme/material.css b/backend/_pv_1_3_5/static/codemirror/theme/material.css deleted file mode 100755 index 01d867932..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/material.css +++ /dev/null @@ -1,53 +0,0 @@ -/* - - Name: material - Author: Michael Kaminsky (http://github.com/mkaminsky11) - - Original material color scheme by Mattia Astorino (https://github.com/equinusocio/material-theme) - -*/ - -.cm-s-material.CodeMirror { - background-color: #263238; - color: rgba(233, 237, 237, 1); -} -.cm-s-material .CodeMirror-gutters { - background: #263238; - color: rgb(83,127,126); - border: none; -} -.cm-s-material .CodeMirror-guttermarker, .cm-s-material .CodeMirror-guttermarker-subtle, .cm-s-material .CodeMirror-linenumber { color: rgb(83,127,126); } -.cm-s-material .CodeMirror-cursor { border-left: 1px solid #f8f8f0; } -.cm-s-material div.CodeMirror-selected { background: rgba(255, 255, 255, 0.15); } -.cm-s-material.CodeMirror-focused div.CodeMirror-selected { background: rgba(255, 255, 255, 0.10); } -.cm-s-material .CodeMirror-line::selection, .cm-s-material .CodeMirror-line > span::selection, .cm-s-material .CodeMirror-line > span > span::selection { background: rgba(255, 255, 255, 0.10); } -.cm-s-material .CodeMirror-line::-moz-selection, .cm-s-material .CodeMirror-line > span::-moz-selection, .cm-s-material .CodeMirror-line > span > span::-moz-selection { background: rgba(255, 255, 255, 0.10); } - -.cm-s-material .CodeMirror-activeline-background { background: rgba(0, 0, 0, 0); } -.cm-s-material .cm-keyword { color: rgba(199, 146, 234, 1); } -.cm-s-material .cm-operator { color: rgba(233, 237, 237, 1); } -.cm-s-material .cm-variable-2 { color: #80CBC4; } -.cm-s-material .cm-variable-3 { color: #82B1FF; } -.cm-s-material .cm-builtin { color: #DECB6B; } -.cm-s-material .cm-atom { color: #F77669; } -.cm-s-material .cm-number { color: #F77669; } -.cm-s-material .cm-def { color: rgba(233, 237, 237, 1); } -.cm-s-material .cm-string { color: #C3E88D; } -.cm-s-material .cm-string-2 { color: #80CBC4; } -.cm-s-material .cm-comment { color: #546E7A; } -.cm-s-material .cm-variable { color: #82B1FF; } -.cm-s-material .cm-tag { color: #80CBC4; } -.cm-s-material .cm-meta { color: #80CBC4; } -.cm-s-material .cm-attribute { color: #FFCB6B; } -.cm-s-material .cm-property { color: #80CBAE; } -.cm-s-material .cm-qualifier { color: #DECB6B; } -.cm-s-material .cm-variable-3 { color: #DECB6B; } -.cm-s-material .cm-tag { color: rgba(255, 83, 112, 1); } -.cm-s-material .cm-error { - color: rgba(255, 255, 255, 1.0); - background-color: #EC5F67; -} -.cm-s-material .CodeMirror-matchingbracket { - text-decoration: underline; - color: white !important; -} diff --git a/backend/_pv_1_3_5/static/codemirror/theme/mbo.css b/backend/_pv_1_3_5/static/codemirror/theme/mbo.css deleted file mode 100755 index e164fcf42..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/mbo.css +++ /dev/null @@ -1,37 +0,0 @@ -/****************************************************************/ -/* Based on mbonaci's Brackets mbo theme */ -/* https://github.com/mbonaci/global/blob/master/Mbo.tmTheme */ -/* Create your own: http://tmtheme-editor.herokuapp.com */ -/****************************************************************/ - -.cm-s-mbo.CodeMirror { background: #2c2c2c; color: #ffffec; } -.cm-s-mbo div.CodeMirror-selected { background: #716C62; } -.cm-s-mbo .CodeMirror-line::selection, .cm-s-mbo .CodeMirror-line > span::selection, .cm-s-mbo .CodeMirror-line > span > span::selection { background: rgba(113, 108, 98, .99); } -.cm-s-mbo .CodeMirror-line::-moz-selection, .cm-s-mbo .CodeMirror-line > span::-moz-selection, .cm-s-mbo .CodeMirror-line > span > span::-moz-selection { background: rgba(113, 108, 98, .99); } -.cm-s-mbo .CodeMirror-gutters { background: #4e4e4e; border-right: 0px; } -.cm-s-mbo .CodeMirror-guttermarker { color: white; } -.cm-s-mbo .CodeMirror-guttermarker-subtle { color: grey; } -.cm-s-mbo .CodeMirror-linenumber { color: #dadada; } -.cm-s-mbo .CodeMirror-cursor { border-left: 1px solid #ffffec; } - -.cm-s-mbo span.cm-comment { color: #95958a; } -.cm-s-mbo span.cm-atom { color: #00a8c6; } -.cm-s-mbo span.cm-number { color: #00a8c6; } - -.cm-s-mbo span.cm-property, .cm-s-mbo span.cm-attribute { color: #9ddfe9; } -.cm-s-mbo span.cm-keyword { color: #ffb928; } -.cm-s-mbo span.cm-string { color: #ffcf6c; } -.cm-s-mbo span.cm-string.cm-property { color: #ffffec; } - -.cm-s-mbo span.cm-variable { color: #ffffec; } -.cm-s-mbo span.cm-variable-2 { color: #00a8c6; } -.cm-s-mbo span.cm-def { color: #ffffec; } -.cm-s-mbo span.cm-bracket { color: #fffffc; font-weight: bold; } -.cm-s-mbo span.cm-tag { color: #9ddfe9; } -.cm-s-mbo span.cm-link { color: #f54b07; } -.cm-s-mbo span.cm-error { border-bottom: #636363; color: #ffffec; } -.cm-s-mbo span.cm-qualifier { color: #ffffec; } - -.cm-s-mbo .CodeMirror-activeline-background { background: #494b41; } -.cm-s-mbo .CodeMirror-matchingbracket { color: #ffb928 !important; } -.cm-s-mbo .CodeMirror-matchingtag { background: rgba(255, 255, 255, .37); } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/mdn-like.css b/backend/_pv_1_3_5/static/codemirror/theme/mdn-like.css deleted file mode 100755 index f325d4500..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/mdn-like.css +++ /dev/null @@ -1,46 +0,0 @@ -/* - MDN-LIKE Theme - Mozilla - Ported to CodeMirror by Peter Kroon - Report bugs/issues here: https://github.com/codemirror/CodeMirror/issues - GitHub: @peterkroon - - The mdn-like theme is inspired on the displayed code examples at: https://developer.mozilla.org/en-US/docs/Web/CSS/animation - -*/ -.cm-s-mdn-like.CodeMirror { color: #999; background-color: #fff; } -.cm-s-mdn-like div.CodeMirror-selected { background: #cfc; } -.cm-s-mdn-like .CodeMirror-line::selection, .cm-s-mdn-like .CodeMirror-line > span::selection, .cm-s-mdn-like .CodeMirror-line > span > span::selection { background: #cfc; } -.cm-s-mdn-like .CodeMirror-line::-moz-selection, .cm-s-mdn-like .CodeMirror-line > span::-moz-selection, .cm-s-mdn-like .CodeMirror-line > span > span::-moz-selection { background: #cfc; } - -.cm-s-mdn-like .CodeMirror-gutters { background: #f8f8f8; border-left: 6px solid rgba(0,83,159,0.65); color: #333; } -.cm-s-mdn-like .CodeMirror-linenumber { color: #aaa; padding-left: 8px; } -.cm-s-mdn-like .CodeMirror-cursor { border-left: 2px solid #222; } - -.cm-s-mdn-like .cm-keyword { color: #6262FF; } -.cm-s-mdn-like .cm-atom { color: #F90; } -.cm-s-mdn-like .cm-number { color: #ca7841; } -.cm-s-mdn-like .cm-def { color: #8DA6CE; } -.cm-s-mdn-like span.cm-variable-2, .cm-s-mdn-like span.cm-tag { color: #690; } -.cm-s-mdn-like span.cm-variable-3, .cm-s-mdn-like span.cm-def { color: #07a; } - -.cm-s-mdn-like .cm-variable { color: #07a; } -.cm-s-mdn-like .cm-property { color: #905; } -.cm-s-mdn-like .cm-qualifier { color: #690; } - -.cm-s-mdn-like .cm-operator { color: #cda869; } -.cm-s-mdn-like .cm-comment { color:#777; font-weight:normal; } -.cm-s-mdn-like .cm-string { color:#07a; font-style:italic; } -.cm-s-mdn-like .cm-string-2 { color:#bd6b18; } /*?*/ -.cm-s-mdn-like .cm-meta { color: #000; } /*?*/ -.cm-s-mdn-like .cm-builtin { color: #9B7536; } /*?*/ -.cm-s-mdn-like .cm-tag { color: #997643; } -.cm-s-mdn-like .cm-attribute { color: #d6bb6d; } /*?*/ -.cm-s-mdn-like .cm-header { color: #FF6400; } -.cm-s-mdn-like .cm-hr { color: #AEAEAE; } -.cm-s-mdn-like .cm-link { color:#ad9361; font-style:italic; text-decoration:none; } -.cm-s-mdn-like .cm-error { border-bottom: 1px solid red; } - -div.cm-s-mdn-like .CodeMirror-activeline-background { background: #efefff; } -div.cm-s-mdn-like span.CodeMirror-matchingbracket { outline:1px solid grey; color: inherit; } - -.cm-s-mdn-like.CodeMirror { background-image: url(data:image/png;base64,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); } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/midnight.css b/backend/_pv_1_3_5/static/codemirror/theme/midnight.css deleted file mode 100755 index e41f10560..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/midnight.css +++ /dev/null @@ -1,45 +0,0 @@ -/* Based on the theme at http://bonsaiden.github.com/JavaScript-Garden */ - -/**/ -.cm-s-midnight span.CodeMirror-matchhighlight { background: #494949; } -.cm-s-midnight.CodeMirror-focused span.CodeMirror-matchhighlight { background: #314D67 !important; } - -/**/ -.cm-s-midnight .CodeMirror-activeline-background { background: #253540; } - -.cm-s-midnight.CodeMirror { - background: #0F192A; - color: #D1EDFF; -} - -.cm-s-midnight.CodeMirror { border-top: 1px solid black; border-bottom: 1px solid black; } - -.cm-s-midnight div.CodeMirror-selected { background: #314D67; } -.cm-s-midnight .CodeMirror-line::selection, .cm-s-midnight .CodeMirror-line > span::selection, .cm-s-midnight .CodeMirror-line > span > span::selection { background: rgba(49, 77, 103, .99); } -.cm-s-midnight .CodeMirror-line::-moz-selection, .cm-s-midnight .CodeMirror-line > span::-moz-selection, .cm-s-midnight .CodeMirror-line > span > span::-moz-selection { background: rgba(49, 77, 103, .99); } -.cm-s-midnight .CodeMirror-gutters { background: #0F192A; border-right: 1px solid; } -.cm-s-midnight .CodeMirror-guttermarker { color: white; } -.cm-s-midnight .CodeMirror-guttermarker-subtle { color: #d0d0d0; } -.cm-s-midnight .CodeMirror-linenumber { color: #D0D0D0; } -.cm-s-midnight .CodeMirror-cursor { border-left: 1px solid #F8F8F0; } - -.cm-s-midnight span.cm-comment { color: #428BDD; } -.cm-s-midnight span.cm-atom { color: #AE81FF; } -.cm-s-midnight span.cm-number { color: #D1EDFF; } - -.cm-s-midnight span.cm-property, .cm-s-midnight span.cm-attribute { color: #A6E22E; } -.cm-s-midnight span.cm-keyword { color: #E83737; } -.cm-s-midnight span.cm-string { color: #1DC116; } - -.cm-s-midnight span.cm-variable { color: #FFAA3E; } -.cm-s-midnight span.cm-variable-2 { color: #FFAA3E; } -.cm-s-midnight span.cm-def { color: #4DD; } -.cm-s-midnight span.cm-bracket { color: #D1EDFF; } -.cm-s-midnight span.cm-tag { color: #449; } -.cm-s-midnight span.cm-link { color: #AE81FF; } -.cm-s-midnight span.cm-error { background: #F92672; color: #F8F8F0; } - -.cm-s-midnight .CodeMirror-matchingbracket { - text-decoration: underline; - color: white !important; -} diff --git a/backend/_pv_1_3_5/static/codemirror/theme/monokai.css b/backend/_pv_1_3_5/static/codemirror/theme/monokai.css deleted file mode 100755 index 7c8a4c5d0..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/monokai.css +++ /dev/null @@ -1,36 +0,0 @@ -/* Based on Sublime Text's Monokai theme */ - -.cm-s-monokai.CodeMirror { background: #272822; color: #f8f8f2; } -.cm-s-monokai div.CodeMirror-selected { background: #49483E; } -.cm-s-monokai .CodeMirror-line::selection, .cm-s-monokai .CodeMirror-line > span::selection, .cm-s-monokai .CodeMirror-line > span > span::selection { background: rgba(73, 72, 62, .99); } -.cm-s-monokai .CodeMirror-line::-moz-selection, .cm-s-monokai .CodeMirror-line > span::-moz-selection, .cm-s-monokai .CodeMirror-line > span > span::-moz-selection { background: rgba(73, 72, 62, .99); } -.cm-s-monokai .CodeMirror-gutters { background: #272822; border-right: 0px; } -.cm-s-monokai .CodeMirror-guttermarker { color: white; } -.cm-s-monokai .CodeMirror-guttermarker-subtle { color: #d0d0d0; } -.cm-s-monokai .CodeMirror-linenumber { color: #d0d0d0; } -.cm-s-monokai .CodeMirror-cursor { border-left: 1px solid #f8f8f0; } - -.cm-s-monokai span.cm-comment { color: #75715e; } -.cm-s-monokai span.cm-atom { color: #ae81ff; } -.cm-s-monokai span.cm-number { color: #ae81ff; } - -.cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute { color: #a6e22e; } -.cm-s-monokai span.cm-keyword { color: #f92672; } -.cm-s-monokai span.cm-builtin { color: #66d9ef; } -.cm-s-monokai span.cm-string { color: #e6db74; } - -.cm-s-monokai span.cm-variable { color: #f8f8f2; } -.cm-s-monokai span.cm-variable-2 { color: #9effff; } -.cm-s-monokai span.cm-variable-3 { color: #66d9ef; } -.cm-s-monokai span.cm-def { color: #fd971f; } -.cm-s-monokai span.cm-bracket { color: #f8f8f2; } -.cm-s-monokai span.cm-tag { color: #f92672; } -.cm-s-monokai span.cm-header { color: #ae81ff; } -.cm-s-monokai span.cm-link { color: #ae81ff; } -.cm-s-monokai span.cm-error { background: #f92672; color: #f8f8f0; } - -.cm-s-monokai .CodeMirror-activeline-background { background: #373831; } -.cm-s-monokai .CodeMirror-matchingbracket { - text-decoration: underline; - color: white !important; -} diff --git a/backend/_pv_1_3_5/static/codemirror/theme/neat.css b/backend/_pv_1_3_5/static/codemirror/theme/neat.css deleted file mode 100755 index 4267b1a37..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/neat.css +++ /dev/null @@ -1,12 +0,0 @@ -.cm-s-neat span.cm-comment { color: #a86; } -.cm-s-neat span.cm-keyword { line-height: 1em; font-weight: bold; color: blue; } -.cm-s-neat span.cm-string { color: #a22; } -.cm-s-neat span.cm-builtin { line-height: 1em; font-weight: bold; color: #077; } -.cm-s-neat span.cm-special { line-height: 1em; font-weight: bold; color: #0aa; } -.cm-s-neat span.cm-variable { color: black; } -.cm-s-neat span.cm-number, .cm-s-neat span.cm-atom { color: #3a3; } -.cm-s-neat span.cm-meta { color: #555; } -.cm-s-neat span.cm-link { color: #3a3; } - -.cm-s-neat .CodeMirror-activeline-background { background: #e8f2ff; } -.cm-s-neat .CodeMirror-matchingbracket { outline:1px solid grey; color:black !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/neo.css b/backend/_pv_1_3_5/static/codemirror/theme/neo.css deleted file mode 100755 index b28d5c65f..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/neo.css +++ /dev/null @@ -1,43 +0,0 @@ -/* neo theme for codemirror */ - -/* Color scheme */ - -.cm-s-neo.CodeMirror { - background-color:#ffffff; - color:#2e383c; - line-height:1.4375; -} -.cm-s-neo .cm-comment { color:#75787b; } -.cm-s-neo .cm-keyword, .cm-s-neo .cm-property { color:#1d75b3; } -.cm-s-neo .cm-atom,.cm-s-neo .cm-number { color:#75438a; } -.cm-s-neo .cm-node,.cm-s-neo .cm-tag { color:#9c3328; } -.cm-s-neo .cm-string { color:#b35e14; } -.cm-s-neo .cm-variable,.cm-s-neo .cm-qualifier { color:#047d65; } - - -/* Editor styling */ - -.cm-s-neo pre { - padding:0; -} - -.cm-s-neo .CodeMirror-gutters { - border:none; - border-right:10px solid transparent; - background-color:transparent; -} - -.cm-s-neo .CodeMirror-linenumber { - padding:0; - color:#e0e2e5; -} - -.cm-s-neo .CodeMirror-guttermarker { color: #1d75b3; } -.cm-s-neo .CodeMirror-guttermarker-subtle { color: #e0e2e5; } - -.cm-s-neo .CodeMirror-cursor { - width: auto; - border: 0; - background: rgba(155,157,162,0.37); - z-index: 1; -} diff --git a/backend/_pv_1_3_5/static/codemirror/theme/night.css b/backend/_pv_1_3_5/static/codemirror/theme/night.css deleted file mode 100755 index fd4e56193..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/night.css +++ /dev/null @@ -1,27 +0,0 @@ -/* Loosely based on the Midnight Textmate theme */ - -.cm-s-night.CodeMirror { background: #0a001f; color: #f8f8f8; } -.cm-s-night div.CodeMirror-selected { background: #447; } -.cm-s-night .CodeMirror-line::selection, .cm-s-night .CodeMirror-line > span::selection, .cm-s-night .CodeMirror-line > span > span::selection { background: rgba(68, 68, 119, .99); } -.cm-s-night .CodeMirror-line::-moz-selection, .cm-s-night .CodeMirror-line > span::-moz-selection, .cm-s-night .CodeMirror-line > span > span::-moz-selection { background: rgba(68, 68, 119, .99); } -.cm-s-night .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; } -.cm-s-night .CodeMirror-guttermarker { color: white; } -.cm-s-night .CodeMirror-guttermarker-subtle { color: #bbb; } -.cm-s-night .CodeMirror-linenumber { color: #f8f8f8; } -.cm-s-night .CodeMirror-cursor { border-left: 1px solid white; } - -.cm-s-night span.cm-comment { color: #8900d1; } -.cm-s-night span.cm-atom { color: #845dc4; } -.cm-s-night span.cm-number, .cm-s-night span.cm-attribute { color: #ffd500; } -.cm-s-night span.cm-keyword { color: #599eff; } -.cm-s-night span.cm-string { color: #37f14a; } -.cm-s-night span.cm-meta { color: #7678e2; } -.cm-s-night span.cm-variable-2, .cm-s-night span.cm-tag { color: #99b2ff; } -.cm-s-night span.cm-variable-3, .cm-s-night span.cm-def { color: white; } -.cm-s-night span.cm-bracket { color: #8da6ce; } -.cm-s-night span.cm-builtin, .cm-s-night span.cm-special { color: #ff9e59; } -.cm-s-night span.cm-link { color: #845dc4; } -.cm-s-night span.cm-error { color: #9d1e15; } - -.cm-s-night .CodeMirror-activeline-background { background: #1C005A; } -.cm-s-night .CodeMirror-matchingbracket { outline:1px solid grey; color:white !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/panda-syntax.css b/backend/_pv_1_3_5/static/codemirror/theme/panda-syntax.css deleted file mode 100755 index c93b2ea03..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/panda-syntax.css +++ /dev/null @@ -1,85 +0,0 @@ -/* - Name: Panda Syntax - Author: Siamak Mokhtari (http://github.com/siamak/) - CodeMirror template by Siamak Mokhtari (https://github.com/siamak/atom-panda-syntax) -*/ -.cm-s-panda-syntax { - background: #292A2B; - color: #E6E6E6; - line-height: 1.5; - font-family: 'Operator Mono', 'Source Sans Pro', Menlo, Monaco, Consolas, Courier New, monospace; -} -.cm-s-panda-syntax .CodeMirror-cursor { border-color: #ff2c6d; } -.cm-s-panda-syntax .CodeMirror-activeline-background { - background: rgba(99, 123, 156, 0.1); -} -.cm-s-panda-syntax .CodeMirror-selected { - background: #FFF; -} -.cm-s-panda-syntax .cm-comment { - font-style: italic; - color: #676B79; -} -.cm-s-panda-syntax .cm-operator { - color: #f3f3f3; -} -.cm-s-panda-syntax .cm-string { - color: #19F9D8; -} -.cm-s-panda-syntax .cm-string-2 { - color: #FFB86C; -} - -.cm-s-panda-syntax .cm-tag { - color: #ff2c6d; -} -.cm-s-panda-syntax .cm-meta { - color: #b084eb; -} - -.cm-s-panda-syntax .cm-number { - color: #FFB86C; -} -.cm-s-panda-syntax .cm-atom { - color: #ff2c6d; -} -.cm-s-panda-syntax .cm-keyword { - color: #FF75B5; -} -.cm-s-panda-syntax .cm-variable { - color: #ffb86c; -} -.cm-s-panda-syntax .cm-variable-2 { - color: #ff9ac1; -} -.cm-s-panda-syntax .cm-variable-3 { - color: #ff9ac1; -} - -.cm-s-panda-syntax .cm-def { - color: #e6e6e6; -} -.cm-s-panda-syntax .cm-property { - color: #f3f3f3; -} -.cm-s-panda-syntax .cm-unit { - color: #ffb86c; -} - -.cm-s-panda-syntax .cm-attribute { - color: #ffb86c; -} - -.cm-s-panda-syntax .CodeMirror-matchingbracket { - border-bottom: 1px dotted #19F9D8; - padding-bottom: 2px; - color: #e6e6e6; -} -.cm-s-panda-syntax .CodeMirror-gutters { - background: #292a2b; - border-right-color: rgba(255, 255, 255, 0.1); -} -.cm-s-panda-syntax .CodeMirror-linenumber { - color: #e6e6e6; - opacity: 0.6; -} diff --git a/backend/_pv_1_3_5/static/codemirror/theme/paraiso-dark.css b/backend/_pv_1_3_5/static/codemirror/theme/paraiso-dark.css deleted file mode 100755 index aa9d207e6..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/paraiso-dark.css +++ /dev/null @@ -1,38 +0,0 @@ -/* - - Name: Paraíso (Dark) - Author: Jan T. Sott - - Color scheme by Jan T. Sott (https://github.com/idleberg/Paraiso-CodeMirror) - Inspired by the art of Rubens LP (http://www.rubenslp.com.br) - -*/ - -.cm-s-paraiso-dark.CodeMirror { background: #2f1e2e; color: #b9b6b0; } -.cm-s-paraiso-dark div.CodeMirror-selected { background: #41323f; } -.cm-s-paraiso-dark .CodeMirror-line::selection, .cm-s-paraiso-dark .CodeMirror-line > span::selection, .cm-s-paraiso-dark .CodeMirror-line > span > span::selection { background: rgba(65, 50, 63, .99); } -.cm-s-paraiso-dark .CodeMirror-line::-moz-selection, .cm-s-paraiso-dark .CodeMirror-line > span::-moz-selection, .cm-s-paraiso-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(65, 50, 63, .99); } -.cm-s-paraiso-dark .CodeMirror-gutters { background: #2f1e2e; border-right: 0px; } -.cm-s-paraiso-dark .CodeMirror-guttermarker { color: #ef6155; } -.cm-s-paraiso-dark .CodeMirror-guttermarker-subtle { color: #776e71; } -.cm-s-paraiso-dark .CodeMirror-linenumber { color: #776e71; } -.cm-s-paraiso-dark .CodeMirror-cursor { border-left: 1px solid #8d8687; } - -.cm-s-paraiso-dark span.cm-comment { color: #e96ba8; } -.cm-s-paraiso-dark span.cm-atom { color: #815ba4; } -.cm-s-paraiso-dark span.cm-number { color: #815ba4; } - -.cm-s-paraiso-dark span.cm-property, .cm-s-paraiso-dark span.cm-attribute { color: #48b685; } -.cm-s-paraiso-dark span.cm-keyword { color: #ef6155; } -.cm-s-paraiso-dark span.cm-string { color: #fec418; } - -.cm-s-paraiso-dark span.cm-variable { color: #48b685; } -.cm-s-paraiso-dark span.cm-variable-2 { color: #06b6ef; } -.cm-s-paraiso-dark span.cm-def { color: #f99b15; } -.cm-s-paraiso-dark span.cm-bracket { color: #b9b6b0; } -.cm-s-paraiso-dark span.cm-tag { color: #ef6155; } -.cm-s-paraiso-dark span.cm-link { color: #815ba4; } -.cm-s-paraiso-dark span.cm-error { background: #ef6155; color: #8d8687; } - -.cm-s-paraiso-dark .CodeMirror-activeline-background { background: #4D344A; } -.cm-s-paraiso-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/paraiso-light.css b/backend/_pv_1_3_5/static/codemirror/theme/paraiso-light.css deleted file mode 100755 index ae0c755f8..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/paraiso-light.css +++ /dev/null @@ -1,38 +0,0 @@ -/* - - Name: Paraíso (Light) - Author: Jan T. Sott - - Color scheme by Jan T. Sott (https://github.com/idleberg/Paraiso-CodeMirror) - Inspired by the art of Rubens LP (http://www.rubenslp.com.br) - -*/ - -.cm-s-paraiso-light.CodeMirror { background: #e7e9db; color: #41323f; } -.cm-s-paraiso-light div.CodeMirror-selected { background: #b9b6b0; } -.cm-s-paraiso-light .CodeMirror-line::selection, .cm-s-paraiso-light .CodeMirror-line > span::selection, .cm-s-paraiso-light .CodeMirror-line > span > span::selection { background: #b9b6b0; } -.cm-s-paraiso-light .CodeMirror-line::-moz-selection, .cm-s-paraiso-light .CodeMirror-line > span::-moz-selection, .cm-s-paraiso-light .CodeMirror-line > span > span::-moz-selection { background: #b9b6b0; } -.cm-s-paraiso-light .CodeMirror-gutters { background: #e7e9db; border-right: 0px; } -.cm-s-paraiso-light .CodeMirror-guttermarker { color: black; } -.cm-s-paraiso-light .CodeMirror-guttermarker-subtle { color: #8d8687; } -.cm-s-paraiso-light .CodeMirror-linenumber { color: #8d8687; } -.cm-s-paraiso-light .CodeMirror-cursor { border-left: 1px solid #776e71; } - -.cm-s-paraiso-light span.cm-comment { color: #e96ba8; } -.cm-s-paraiso-light span.cm-atom { color: #815ba4; } -.cm-s-paraiso-light span.cm-number { color: #815ba4; } - -.cm-s-paraiso-light span.cm-property, .cm-s-paraiso-light span.cm-attribute { color: #48b685; } -.cm-s-paraiso-light span.cm-keyword { color: #ef6155; } -.cm-s-paraiso-light span.cm-string { color: #fec418; } - -.cm-s-paraiso-light span.cm-variable { color: #48b685; } -.cm-s-paraiso-light span.cm-variable-2 { color: #06b6ef; } -.cm-s-paraiso-light span.cm-def { color: #f99b15; } -.cm-s-paraiso-light span.cm-bracket { color: #41323f; } -.cm-s-paraiso-light span.cm-tag { color: #ef6155; } -.cm-s-paraiso-light span.cm-link { color: #815ba4; } -.cm-s-paraiso-light span.cm-error { background: #ef6155; color: #776e71; } - -.cm-s-paraiso-light .CodeMirror-activeline-background { background: #CFD1C4; } -.cm-s-paraiso-light .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/pastel-on-dark.css b/backend/_pv_1_3_5/static/codemirror/theme/pastel-on-dark.css deleted file mode 100755 index 2603d3620..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/pastel-on-dark.css +++ /dev/null @@ -1,52 +0,0 @@ -/** - * Pastel On Dark theme ported from ACE editor - * @license MIT - * @copyright AtomicPages LLC 2014 - * @author Dennis Thompson, AtomicPages LLC - * @version 1.1 - * @source https://github.com/atomicpages/codemirror-pastel-on-dark-theme - */ - -.cm-s-pastel-on-dark.CodeMirror { - background: #2c2827; - color: #8F938F; - line-height: 1.5; -} -.cm-s-pastel-on-dark div.CodeMirror-selected { background: rgba(221,240,255,0.2); } -.cm-s-pastel-on-dark .CodeMirror-line::selection, .cm-s-pastel-on-dark .CodeMirror-line > span::selection, .cm-s-pastel-on-dark .CodeMirror-line > span > span::selection { background: rgba(221,240,255,0.2); } -.cm-s-pastel-on-dark .CodeMirror-line::-moz-selection, .cm-s-pastel-on-dark .CodeMirror-line > span::-moz-selection, .cm-s-pastel-on-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(221,240,255,0.2); } - -.cm-s-pastel-on-dark .CodeMirror-gutters { - background: #34302f; - border-right: 0px; - padding: 0 3px; -} -.cm-s-pastel-on-dark .CodeMirror-guttermarker { color: white; } -.cm-s-pastel-on-dark .CodeMirror-guttermarker-subtle { color: #8F938F; } -.cm-s-pastel-on-dark .CodeMirror-linenumber { color: #8F938F; } -.cm-s-pastel-on-dark .CodeMirror-cursor { border-left: 1px solid #A7A7A7; } -.cm-s-pastel-on-dark span.cm-comment { color: #A6C6FF; } -.cm-s-pastel-on-dark span.cm-atom { color: #DE8E30; } -.cm-s-pastel-on-dark span.cm-number { color: #CCCCCC; } -.cm-s-pastel-on-dark span.cm-property { color: #8F938F; } -.cm-s-pastel-on-dark span.cm-attribute { color: #a6e22e; } -.cm-s-pastel-on-dark span.cm-keyword { color: #AEB2F8; } -.cm-s-pastel-on-dark span.cm-string { color: #66A968; } -.cm-s-pastel-on-dark span.cm-variable { color: #AEB2F8; } -.cm-s-pastel-on-dark span.cm-variable-2 { color: #BEBF55; } -.cm-s-pastel-on-dark span.cm-variable-3 { color: #DE8E30; } -.cm-s-pastel-on-dark span.cm-def { color: #757aD8; } -.cm-s-pastel-on-dark span.cm-bracket { color: #f8f8f2; } -.cm-s-pastel-on-dark span.cm-tag { color: #C1C144; } -.cm-s-pastel-on-dark span.cm-link { color: #ae81ff; } -.cm-s-pastel-on-dark span.cm-qualifier,.cm-s-pastel-on-dark span.cm-builtin { color: #C1C144; } -.cm-s-pastel-on-dark span.cm-error { - background: #757aD8; - color: #f8f8f0; -} -.cm-s-pastel-on-dark .CodeMirror-activeline-background { background: rgba(255, 255, 255, 0.031); } -.cm-s-pastel-on-dark .CodeMirror-matchingbracket { - border: 1px solid rgba(255,255,255,0.25); - color: #8F938F !important; - margin: -1px -1px 0 -1px; -} diff --git a/backend/_pv_1_3_5/static/codemirror/theme/railscasts.css b/backend/_pv_1_3_5/static/codemirror/theme/railscasts.css deleted file mode 100755 index aeff0449d..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/railscasts.css +++ /dev/null @@ -1,34 +0,0 @@ -/* - - Name: Railscasts - Author: Ryan Bates (http://railscasts.com) - - CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror) - Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) - -*/ - -.cm-s-railscasts.CodeMirror {background: #2b2b2b; color: #f4f1ed;} -.cm-s-railscasts div.CodeMirror-selected {background: #272935 !important;} -.cm-s-railscasts .CodeMirror-gutters {background: #2b2b2b; border-right: 0px;} -.cm-s-railscasts .CodeMirror-linenumber {color: #5a647e;} -.cm-s-railscasts .CodeMirror-cursor {border-left: 1px solid #d4cfc9 !important;} - -.cm-s-railscasts span.cm-comment {color: #bc9458;} -.cm-s-railscasts span.cm-atom {color: #b6b3eb;} -.cm-s-railscasts span.cm-number {color: #b6b3eb;} - -.cm-s-railscasts span.cm-property, .cm-s-railscasts span.cm-attribute {color: #a5c261;} -.cm-s-railscasts span.cm-keyword {color: #da4939;} -.cm-s-railscasts span.cm-string {color: #ffc66d;} - -.cm-s-railscasts span.cm-variable {color: #a5c261;} -.cm-s-railscasts span.cm-variable-2 {color: #6d9cbe;} -.cm-s-railscasts span.cm-def {color: #cc7833;} -.cm-s-railscasts span.cm-error {background: #da4939; color: #d4cfc9;} -.cm-s-railscasts span.cm-bracket {color: #f4f1ed;} -.cm-s-railscasts span.cm-tag {color: #da4939;} -.cm-s-railscasts span.cm-link {color: #b6b3eb;} - -.cm-s-railscasts .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;} -.cm-s-railscasts .CodeMirror-activeline-background { background: #303040; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/rubyblue.css b/backend/_pv_1_3_5/static/codemirror/theme/rubyblue.css deleted file mode 100755 index 76d33e779..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/rubyblue.css +++ /dev/null @@ -1,25 +0,0 @@ -.cm-s-rubyblue.CodeMirror { background: #112435; color: white; } -.cm-s-rubyblue div.CodeMirror-selected { background: #38566F; } -.cm-s-rubyblue .CodeMirror-line::selection, .cm-s-rubyblue .CodeMirror-line > span::selection, .cm-s-rubyblue .CodeMirror-line > span > span::selection { background: rgba(56, 86, 111, 0.99); } -.cm-s-rubyblue .CodeMirror-line::-moz-selection, .cm-s-rubyblue .CodeMirror-line > span::-moz-selection, .cm-s-rubyblue .CodeMirror-line > span > span::-moz-selection { background: rgba(56, 86, 111, 0.99); } -.cm-s-rubyblue .CodeMirror-gutters { background: #1F4661; border-right: 7px solid #3E7087; } -.cm-s-rubyblue .CodeMirror-guttermarker { color: white; } -.cm-s-rubyblue .CodeMirror-guttermarker-subtle { color: #3E7087; } -.cm-s-rubyblue .CodeMirror-linenumber { color: white; } -.cm-s-rubyblue .CodeMirror-cursor { border-left: 1px solid white; } - -.cm-s-rubyblue span.cm-comment { color: #999; font-style:italic; line-height: 1em; } -.cm-s-rubyblue span.cm-atom { color: #F4C20B; } -.cm-s-rubyblue span.cm-number, .cm-s-rubyblue span.cm-attribute { color: #82C6E0; } -.cm-s-rubyblue span.cm-keyword { color: #F0F; } -.cm-s-rubyblue span.cm-string { color: #F08047; } -.cm-s-rubyblue span.cm-meta { color: #F0F; } -.cm-s-rubyblue span.cm-variable-2, .cm-s-rubyblue span.cm-tag { color: #7BD827; } -.cm-s-rubyblue span.cm-variable-3, .cm-s-rubyblue span.cm-def { color: white; } -.cm-s-rubyblue span.cm-bracket { color: #F0F; } -.cm-s-rubyblue span.cm-link { color: #F4C20B; } -.cm-s-rubyblue span.CodeMirror-matchingbracket { color:#F0F !important; } -.cm-s-rubyblue span.cm-builtin, .cm-s-rubyblue span.cm-special { color: #FF9D00; } -.cm-s-rubyblue span.cm-error { color: #AF2018; } - -.cm-s-rubyblue .CodeMirror-activeline-background { background: #173047; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/seti.css b/backend/_pv_1_3_5/static/codemirror/theme/seti.css deleted file mode 100755 index 6632d3fc7..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/seti.css +++ /dev/null @@ -1,44 +0,0 @@ -/* - - Name: seti - Author: Michael Kaminsky (http://github.com/mkaminsky11) - - Original seti color scheme by Jesse Weed (https://github.com/jesseweed/seti-syntax) - -*/ - - -.cm-s-seti.CodeMirror { - background-color: #151718 !important; - color: #CFD2D1 !important; - border: none; -} -.cm-s-seti .CodeMirror-gutters { - color: #404b53; - background-color: #0E1112; - border: none; -} -.cm-s-seti .CodeMirror-cursor { border-left: solid thin #f8f8f0; } -.cm-s-seti .CodeMirror-linenumber { color: #6D8A88; } -.cm-s-seti.CodeMirror-focused div.CodeMirror-selected { background: rgba(255, 255, 255, 0.10); } -.cm-s-seti .CodeMirror-line::selection, .cm-s-seti .CodeMirror-line > span::selection, .cm-s-seti .CodeMirror-line > span > span::selection { background: rgba(255, 255, 255, 0.10); } -.cm-s-seti .CodeMirror-line::-moz-selection, .cm-s-seti .CodeMirror-line > span::-moz-selection, .cm-s-seti .CodeMirror-line > span > span::-moz-selection { background: rgba(255, 255, 255, 0.10); } -.cm-s-seti span.cm-comment { color: #41535b; } -.cm-s-seti span.cm-string, .cm-s-seti span.cm-string-2 { color: #55b5db; } -.cm-s-seti span.cm-number { color: #cd3f45; } -.cm-s-seti span.cm-variable { color: #55b5db; } -.cm-s-seti span.cm-variable-2 { color: #a074c4; } -.cm-s-seti span.cm-def { color: #55b5db; } -.cm-s-seti span.cm-keyword { color: #ff79c6; } -.cm-s-seti span.cm-operator { color: #9fca56; } -.cm-s-seti span.cm-keyword { color: #e6cd69; } -.cm-s-seti span.cm-atom { color: #cd3f45; } -.cm-s-seti span.cm-meta { color: #55b5db; } -.cm-s-seti span.cm-tag { color: #55b5db; } -.cm-s-seti span.cm-attribute { color: #9fca56; } -.cm-s-seti span.cm-qualifier { color: #9fca56; } -.cm-s-seti span.cm-property { color: #a074c4; } -.cm-s-seti span.cm-variable-3 { color: #9fca56; } -.cm-s-seti span.cm-builtin { color: #9fca56; } -.cm-s-seti .CodeMirror-activeline-background { background: #101213; } -.cm-s-seti .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/solarized.css b/backend/_pv_1_3_5/static/codemirror/theme/solarized.css deleted file mode 100755 index 1f39c7edb..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/solarized.css +++ /dev/null @@ -1,169 +0,0 @@ -/* -Solarized theme for code-mirror -http://ethanschoonover.com/solarized -*/ - -/* -Solarized color palette -http://ethanschoonover.com/solarized/img/solarized-palette.png -*/ - -.solarized.base03 { color: #002b36; } -.solarized.base02 { color: #073642; } -.solarized.base01 { color: #586e75; } -.solarized.base00 { color: #657b83; } -.solarized.base0 { color: #839496; } -.solarized.base1 { color: #93a1a1; } -.solarized.base2 { color: #eee8d5; } -.solarized.base3 { color: #fdf6e3; } -.solarized.solar-yellow { color: #b58900; } -.solarized.solar-orange { color: #cb4b16; } -.solarized.solar-red { color: #dc322f; } -.solarized.solar-magenta { color: #d33682; } -.solarized.solar-violet { color: #6c71c4; } -.solarized.solar-blue { color: #268bd2; } -.solarized.solar-cyan { color: #2aa198; } -.solarized.solar-green { color: #859900; } - -/* Color scheme for code-mirror */ - -.cm-s-solarized { - line-height: 1.45em; - color-profile: sRGB; - rendering-intent: auto; -} -.cm-s-solarized.cm-s-dark { - color: #839496; - background-color: #002b36; - text-shadow: #002b36 0 1px; -} -.cm-s-solarized.cm-s-light { - background-color: #fdf6e3; - color: #657b83; - text-shadow: #eee8d5 0 1px; -} - -.cm-s-solarized .CodeMirror-widget { - text-shadow: none; -} - -.cm-s-solarized .cm-header { color: #586e75; } -.cm-s-solarized .cm-quote { color: #93a1a1; } - -.cm-s-solarized .cm-keyword { color: #cb4b16; } -.cm-s-solarized .cm-atom { color: #d33682; } -.cm-s-solarized .cm-number { color: #d33682; } -.cm-s-solarized .cm-def { color: #2aa198; } - -.cm-s-solarized .cm-variable { color: #839496; } -.cm-s-solarized .cm-variable-2 { color: #b58900; } -.cm-s-solarized .cm-variable-3 { color: #6c71c4; } - -.cm-s-solarized .cm-property { color: #2aa198; } -.cm-s-solarized .cm-operator { color: #6c71c4; } - -.cm-s-solarized .cm-comment { color: #586e75; font-style:italic; } - -.cm-s-solarized .cm-string { color: #859900; } -.cm-s-solarized .cm-string-2 { color: #b58900; } - -.cm-s-solarized .cm-meta { color: #859900; } -.cm-s-solarized .cm-qualifier { color: #b58900; } -.cm-s-solarized .cm-builtin { color: #d33682; } -.cm-s-solarized .cm-bracket { color: #cb4b16; } -.cm-s-solarized .CodeMirror-matchingbracket { color: #859900; } -.cm-s-solarized .CodeMirror-nonmatchingbracket { color: #dc322f; } -.cm-s-solarized .cm-tag { color: #93a1a1; } -.cm-s-solarized .cm-attribute { color: #2aa198; } -.cm-s-solarized .cm-hr { - color: transparent; - border-top: 1px solid #586e75; - display: block; -} -.cm-s-solarized .cm-link { color: #93a1a1; cursor: pointer; } -.cm-s-solarized .cm-special { color: #6c71c4; } -.cm-s-solarized .cm-em { - color: #999; - text-decoration: underline; - text-decoration-style: dotted; -} -.cm-s-solarized .cm-strong { color: #eee; } -.cm-s-solarized .cm-error, -.cm-s-solarized .cm-invalidchar { - color: #586e75; - border-bottom: 1px dotted #dc322f; -} - -.cm-s-solarized.cm-s-dark div.CodeMirror-selected { background: #073642; } -.cm-s-solarized.cm-s-dark.CodeMirror ::selection { background: rgba(7, 54, 66, 0.99); } -.cm-s-solarized.cm-s-dark .CodeMirror-line::-moz-selection, .cm-s-dark .CodeMirror-line > span::-moz-selection, .cm-s-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(7, 54, 66, 0.99); } - -.cm-s-solarized.cm-s-light div.CodeMirror-selected { background: #eee8d5; } -.cm-s-solarized.cm-s-light .CodeMirror-line::selection, .cm-s-light .CodeMirror-line > span::selection, .cm-s-light .CodeMirror-line > span > span::selection { background: #eee8d5; } -.cm-s-solarized.cm-s-light .CodeMirror-line::-moz-selection, .cm-s-ligh .CodeMirror-line > span::-moz-selection, .cm-s-ligh .CodeMirror-line > span > span::-moz-selection { background: #eee8d5; } - -/* Editor styling */ - - - -/* Little shadow on the view-port of the buffer view */ -.cm-s-solarized.CodeMirror { - -moz-box-shadow: inset 7px 0 12px -6px #000; - -webkit-box-shadow: inset 7px 0 12px -6px #000; - box-shadow: inset 7px 0 12px -6px #000; -} - -/* Remove gutter border */ -.cm-s-solarized .CodeMirror-gutters { - border-right: 0; -} - -/* Gutter colors and line number styling based of color scheme (dark / light) */ - -/* Dark */ -.cm-s-solarized.cm-s-dark .CodeMirror-gutters { - background-color: #073642; -} - -.cm-s-solarized.cm-s-dark .CodeMirror-linenumber { - color: #586e75; - text-shadow: #021014 0 -1px; -} - -/* Light */ -.cm-s-solarized.cm-s-light .CodeMirror-gutters { - background-color: #eee8d5; -} - -.cm-s-solarized.cm-s-light .CodeMirror-linenumber { - color: #839496; -} - -/* Common */ -.cm-s-solarized .CodeMirror-linenumber { - padding: 0 5px; -} -.cm-s-solarized .CodeMirror-guttermarker-subtle { color: #586e75; } -.cm-s-solarized.cm-s-dark .CodeMirror-guttermarker { color: #ddd; } -.cm-s-solarized.cm-s-light .CodeMirror-guttermarker { color: #cb4b16; } - -.cm-s-solarized .CodeMirror-gutter .CodeMirror-gutter-text { - color: #586e75; -} - -/* Cursor */ -.cm-s-solarized .CodeMirror-cursor { border-left: 1px solid #819090; } - -/* Fat cursor */ -.cm-s-solarized.cm-s-light.cm-fat-cursor .CodeMirror-cursor { background: #77ee77; } -.cm-s-solarized.cm-s-light .cm-animate-fat-cursor { background-color: #77ee77; } -.cm-s-solarized.cm-s-dark.cm-fat-cursor .CodeMirror-cursor { background: #586e75; } -.cm-s-solarized.cm-s-dark .cm-animate-fat-cursor { background-color: #586e75; } - -/* Active line */ -.cm-s-solarized.cm-s-dark .CodeMirror-activeline-background { - background: rgba(255, 255, 255, 0.06); -} -.cm-s-solarized.cm-s-light .CodeMirror-activeline-background { - background: rgba(0, 0, 0, 0.06); -} diff --git a/backend/_pv_1_3_5/static/codemirror/theme/the-matrix.css b/backend/_pv_1_3_5/static/codemirror/theme/the-matrix.css deleted file mode 100755 index 3912a8dbd..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/the-matrix.css +++ /dev/null @@ -1,30 +0,0 @@ -.cm-s-the-matrix.CodeMirror { background: #000000; color: #00FF00; } -.cm-s-the-matrix div.CodeMirror-selected { background: #2D2D2D; } -.cm-s-the-matrix .CodeMirror-line::selection, .cm-s-the-matrix .CodeMirror-line > span::selection, .cm-s-the-matrix .CodeMirror-line > span > span::selection { background: rgba(45, 45, 45, 0.99); } -.cm-s-the-matrix .CodeMirror-line::-moz-selection, .cm-s-the-matrix .CodeMirror-line > span::-moz-selection, .cm-s-the-matrix .CodeMirror-line > span > span::-moz-selection { background: rgba(45, 45, 45, 0.99); } -.cm-s-the-matrix .CodeMirror-gutters { background: #060; border-right: 2px solid #00FF00; } -.cm-s-the-matrix .CodeMirror-guttermarker { color: #0f0; } -.cm-s-the-matrix .CodeMirror-guttermarker-subtle { color: white; } -.cm-s-the-matrix .CodeMirror-linenumber { color: #FFFFFF; } -.cm-s-the-matrix .CodeMirror-cursor { border-left: 1px solid #00FF00; } - -.cm-s-the-matrix span.cm-keyword { color: #008803; font-weight: bold; } -.cm-s-the-matrix span.cm-atom { color: #3FF; } -.cm-s-the-matrix span.cm-number { color: #FFB94F; } -.cm-s-the-matrix span.cm-def { color: #99C; } -.cm-s-the-matrix span.cm-variable { color: #F6C; } -.cm-s-the-matrix span.cm-variable-2 { color: #C6F; } -.cm-s-the-matrix span.cm-variable-3 { color: #96F; } -.cm-s-the-matrix span.cm-property { color: #62FFA0; } -.cm-s-the-matrix span.cm-operator { color: #999; } -.cm-s-the-matrix span.cm-comment { color: #CCCCCC; } -.cm-s-the-matrix span.cm-string { color: #39C; } -.cm-s-the-matrix span.cm-meta { color: #C9F; } -.cm-s-the-matrix span.cm-qualifier { color: #FFF700; } -.cm-s-the-matrix span.cm-builtin { color: #30a; } -.cm-s-the-matrix span.cm-bracket { color: #cc7; } -.cm-s-the-matrix span.cm-tag { color: #FFBD40; } -.cm-s-the-matrix span.cm-attribute { color: #FFF700; } -.cm-s-the-matrix span.cm-error { color: #FF0000; } - -.cm-s-the-matrix .CodeMirror-activeline-background { background: #040; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/tomorrow-night-bright.css b/backend/_pv_1_3_5/static/codemirror/theme/tomorrow-night-bright.css deleted file mode 100755 index b6dd4a927..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/tomorrow-night-bright.css +++ /dev/null @@ -1,35 +0,0 @@ -/* - - Name: Tomorrow Night - Bright - Author: Chris Kempson - - Port done by Gerard Braad - -*/ - -.cm-s-tomorrow-night-bright.CodeMirror { background: #000000; color: #eaeaea; } -.cm-s-tomorrow-night-bright div.CodeMirror-selected { background: #424242; } -.cm-s-tomorrow-night-bright .CodeMirror-gutters { background: #000000; border-right: 0px; } -.cm-s-tomorrow-night-bright .CodeMirror-guttermarker { color: #e78c45; } -.cm-s-tomorrow-night-bright .CodeMirror-guttermarker-subtle { color: #777; } -.cm-s-tomorrow-night-bright .CodeMirror-linenumber { color: #424242; } -.cm-s-tomorrow-night-bright .CodeMirror-cursor { border-left: 1px solid #6A6A6A; } - -.cm-s-tomorrow-night-bright span.cm-comment { color: #d27b53; } -.cm-s-tomorrow-night-bright span.cm-atom { color: #a16a94; } -.cm-s-tomorrow-night-bright span.cm-number { color: #a16a94; } - -.cm-s-tomorrow-night-bright span.cm-property, .cm-s-tomorrow-night-bright span.cm-attribute { color: #99cc99; } -.cm-s-tomorrow-night-bright span.cm-keyword { color: #d54e53; } -.cm-s-tomorrow-night-bright span.cm-string { color: #e7c547; } - -.cm-s-tomorrow-night-bright span.cm-variable { color: #b9ca4a; } -.cm-s-tomorrow-night-bright span.cm-variable-2 { color: #7aa6da; } -.cm-s-tomorrow-night-bright span.cm-def { color: #e78c45; } -.cm-s-tomorrow-night-bright span.cm-bracket { color: #eaeaea; } -.cm-s-tomorrow-night-bright span.cm-tag { color: #d54e53; } -.cm-s-tomorrow-night-bright span.cm-link { color: #a16a94; } -.cm-s-tomorrow-night-bright span.cm-error { background: #d54e53; color: #6A6A6A; } - -.cm-s-tomorrow-night-bright .CodeMirror-activeline-background { background: #2a2a2a; } -.cm-s-tomorrow-night-bright .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/tomorrow-night-eighties.css b/backend/_pv_1_3_5/static/codemirror/theme/tomorrow-night-eighties.css deleted file mode 100755 index 2a9debc32..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/tomorrow-night-eighties.css +++ /dev/null @@ -1,38 +0,0 @@ -/* - - Name: Tomorrow Night - Eighties - Author: Chris Kempson - - CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror) - Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16) - -*/ - -.cm-s-tomorrow-night-eighties.CodeMirror { background: #000000; color: #CCCCCC; } -.cm-s-tomorrow-night-eighties div.CodeMirror-selected { background: #2D2D2D; } -.cm-s-tomorrow-night-eighties .CodeMirror-line::selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span::selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span > span::selection { background: rgba(45, 45, 45, 0.99); } -.cm-s-tomorrow-night-eighties .CodeMirror-line::-moz-selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span::-moz-selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span > span::-moz-selection { background: rgba(45, 45, 45, 0.99); } -.cm-s-tomorrow-night-eighties .CodeMirror-gutters { background: #000000; border-right: 0px; } -.cm-s-tomorrow-night-eighties .CodeMirror-guttermarker { color: #f2777a; } -.cm-s-tomorrow-night-eighties .CodeMirror-guttermarker-subtle { color: #777; } -.cm-s-tomorrow-night-eighties .CodeMirror-linenumber { color: #515151; } -.cm-s-tomorrow-night-eighties .CodeMirror-cursor { border-left: 1px solid #6A6A6A; } - -.cm-s-tomorrow-night-eighties span.cm-comment { color: #d27b53; } -.cm-s-tomorrow-night-eighties span.cm-atom { color: #a16a94; } -.cm-s-tomorrow-night-eighties span.cm-number { color: #a16a94; } - -.cm-s-tomorrow-night-eighties span.cm-property, .cm-s-tomorrow-night-eighties span.cm-attribute { color: #99cc99; } -.cm-s-tomorrow-night-eighties span.cm-keyword { color: #f2777a; } -.cm-s-tomorrow-night-eighties span.cm-string { color: #ffcc66; } - -.cm-s-tomorrow-night-eighties span.cm-variable { color: #99cc99; } -.cm-s-tomorrow-night-eighties span.cm-variable-2 { color: #6699cc; } -.cm-s-tomorrow-night-eighties span.cm-def { color: #f99157; } -.cm-s-tomorrow-night-eighties span.cm-bracket { color: #CCCCCC; } -.cm-s-tomorrow-night-eighties span.cm-tag { color: #f2777a; } -.cm-s-tomorrow-night-eighties span.cm-link { color: #a16a94; } -.cm-s-tomorrow-night-eighties span.cm-error { background: #f2777a; color: #6A6A6A; } - -.cm-s-tomorrow-night-eighties .CodeMirror-activeline-background { background: #343600; } -.cm-s-tomorrow-night-eighties .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/ttcn.css b/backend/_pv_1_3_5/static/codemirror/theme/ttcn.css deleted file mode 100755 index b3d465645..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/ttcn.css +++ /dev/null @@ -1,64 +0,0 @@ -.cm-s-ttcn .cm-quote { color: #090; } -.cm-s-ttcn .cm-negative { color: #d44; } -.cm-s-ttcn .cm-positive { color: #292; } -.cm-s-ttcn .cm-header, .cm-strong { font-weight: bold; } -.cm-s-ttcn .cm-em { font-style: italic; } -.cm-s-ttcn .cm-link { text-decoration: underline; } -.cm-s-ttcn .cm-strikethrough { text-decoration: line-through; } -.cm-s-ttcn .cm-header { color: #00f; font-weight: bold; } - -.cm-s-ttcn .cm-atom { color: #219; } -.cm-s-ttcn .cm-attribute { color: #00c; } -.cm-s-ttcn .cm-bracket { color: #997; } -.cm-s-ttcn .cm-comment { color: #333333; } -.cm-s-ttcn .cm-def { color: #00f; } -.cm-s-ttcn .cm-em { font-style: italic; } -.cm-s-ttcn .cm-error { color: #f00; } -.cm-s-ttcn .cm-hr { color: #999; } -.cm-s-ttcn .cm-invalidchar { color: #f00; } -.cm-s-ttcn .cm-keyword { font-weight:bold; } -.cm-s-ttcn .cm-link { color: #00c; text-decoration: underline; } -.cm-s-ttcn .cm-meta { color: #555; } -.cm-s-ttcn .cm-negative { color: #d44; } -.cm-s-ttcn .cm-positive { color: #292; } -.cm-s-ttcn .cm-qualifier { color: #555; } -.cm-s-ttcn .cm-strikethrough { text-decoration: line-through; } -.cm-s-ttcn .cm-string { color: #006400; } -.cm-s-ttcn .cm-string-2 { color: #f50; } -.cm-s-ttcn .cm-strong { font-weight: bold; } -.cm-s-ttcn .cm-tag { color: #170; } -.cm-s-ttcn .cm-variable { color: #8B2252; } -.cm-s-ttcn .cm-variable-2 { color: #05a; } -.cm-s-ttcn .cm-variable-3 { color: #085; } - -.cm-s-ttcn .cm-invalidchar { color: #f00; } - -/* ASN */ -.cm-s-ttcn .cm-accessTypes, -.cm-s-ttcn .cm-compareTypes { color: #27408B; } -.cm-s-ttcn .cm-cmipVerbs { color: #8B2252; } -.cm-s-ttcn .cm-modifier { color:#D2691E; } -.cm-s-ttcn .cm-status { color:#8B4545; } -.cm-s-ttcn .cm-storage { color:#A020F0; } -.cm-s-ttcn .cm-tags { color:#006400; } - -/* CFG */ -.cm-s-ttcn .cm-externalCommands { color: #8B4545; font-weight:bold; } -.cm-s-ttcn .cm-fileNCtrlMaskOptions, -.cm-s-ttcn .cm-sectionTitle { color: #2E8B57; font-weight:bold; } - -/* TTCN */ -.cm-s-ttcn .cm-booleanConsts, -.cm-s-ttcn .cm-otherConsts, -.cm-s-ttcn .cm-verdictConsts { color: #006400; } -.cm-s-ttcn .cm-configOps, -.cm-s-ttcn .cm-functionOps, -.cm-s-ttcn .cm-portOps, -.cm-s-ttcn .cm-sutOps, -.cm-s-ttcn .cm-timerOps, -.cm-s-ttcn .cm-verdictOps { color: #0000FF; } -.cm-s-ttcn .cm-preprocessor, -.cm-s-ttcn .cm-templateMatch, -.cm-s-ttcn .cm-ttcn3Macros { color: #27408B; } -.cm-s-ttcn .cm-types { color: #A52A2A; font-weight:bold; } -.cm-s-ttcn .cm-visibilityModifiers { font-weight:bold; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/twilight.css b/backend/_pv_1_3_5/static/codemirror/theme/twilight.css deleted file mode 100755 index d342b899f..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/twilight.css +++ /dev/null @@ -1,32 +0,0 @@ -.cm-s-twilight.CodeMirror { background: #141414; color: #f7f7f7; } /**/ -.cm-s-twilight div.CodeMirror-selected { background: #323232; } /**/ -.cm-s-twilight .CodeMirror-line::selection, .cm-s-twilight .CodeMirror-line > span::selection, .cm-s-twilight .CodeMirror-line > span > span::selection { background: rgba(50, 50, 50, 0.99); } -.cm-s-twilight .CodeMirror-line::-moz-selection, .cm-s-twilight .CodeMirror-line > span::-moz-selection, .cm-s-twilight .CodeMirror-line > span > span::-moz-selection { background: rgba(50, 50, 50, 0.99); } - -.cm-s-twilight .CodeMirror-gutters { background: #222; border-right: 1px solid #aaa; } -.cm-s-twilight .CodeMirror-guttermarker { color: white; } -.cm-s-twilight .CodeMirror-guttermarker-subtle { color: #aaa; } -.cm-s-twilight .CodeMirror-linenumber { color: #aaa; } -.cm-s-twilight .CodeMirror-cursor { border-left: 1px solid white; } - -.cm-s-twilight .cm-keyword { color: #f9ee98; } /**/ -.cm-s-twilight .cm-atom { color: #FC0; } -.cm-s-twilight .cm-number { color: #ca7841; } /**/ -.cm-s-twilight .cm-def { color: #8DA6CE; } -.cm-s-twilight span.cm-variable-2, .cm-s-twilight span.cm-tag { color: #607392; } /**/ -.cm-s-twilight span.cm-variable-3, .cm-s-twilight span.cm-def { color: #607392; } /**/ -.cm-s-twilight .cm-operator { color: #cda869; } /**/ -.cm-s-twilight .cm-comment { color:#777; font-style:italic; font-weight:normal; } /**/ -.cm-s-twilight .cm-string { color:#8f9d6a; font-style:italic; } /**/ -.cm-s-twilight .cm-string-2 { color:#bd6b18; } /*?*/ -.cm-s-twilight .cm-meta { background-color:#141414; color:#f7f7f7; } /*?*/ -.cm-s-twilight .cm-builtin { color: #cda869; } /*?*/ -.cm-s-twilight .cm-tag { color: #997643; } /**/ -.cm-s-twilight .cm-attribute { color: #d6bb6d; } /*?*/ -.cm-s-twilight .cm-header { color: #FF6400; } -.cm-s-twilight .cm-hr { color: #AEAEAE; } -.cm-s-twilight .cm-link { color:#ad9361; font-style:italic; text-decoration:none; } /**/ -.cm-s-twilight .cm-error { border-bottom: 1px solid red; } - -.cm-s-twilight .CodeMirror-activeline-background { background: #27282E; } -.cm-s-twilight .CodeMirror-matchingbracket { outline:1px solid grey; color:white !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/vibrant-ink.css b/backend/_pv_1_3_5/static/codemirror/theme/vibrant-ink.css deleted file mode 100755 index ac4ec6d87..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/vibrant-ink.css +++ /dev/null @@ -1,34 +0,0 @@ -/* Taken from the popular Visual Studio Vibrant Ink Schema */ - -.cm-s-vibrant-ink.CodeMirror { background: black; color: white; } -.cm-s-vibrant-ink div.CodeMirror-selected { background: #35493c; } -.cm-s-vibrant-ink .CodeMirror-line::selection, .cm-s-vibrant-ink .CodeMirror-line > span::selection, .cm-s-vibrant-ink .CodeMirror-line > span > span::selection { background: rgba(53, 73, 60, 0.99); } -.cm-s-vibrant-ink .CodeMirror-line::-moz-selection, .cm-s-vibrant-ink .CodeMirror-line > span::-moz-selection, .cm-s-vibrant-ink .CodeMirror-line > span > span::-moz-selection { background: rgba(53, 73, 60, 0.99); } - -.cm-s-vibrant-ink .CodeMirror-gutters { background: #002240; border-right: 1px solid #aaa; } -.cm-s-vibrant-ink .CodeMirror-guttermarker { color: white; } -.cm-s-vibrant-ink .CodeMirror-guttermarker-subtle { color: #d0d0d0; } -.cm-s-vibrant-ink .CodeMirror-linenumber { color: #d0d0d0; } -.cm-s-vibrant-ink .CodeMirror-cursor { border-left: 1px solid white; } - -.cm-s-vibrant-ink .cm-keyword { color: #CC7832; } -.cm-s-vibrant-ink .cm-atom { color: #FC0; } -.cm-s-vibrant-ink .cm-number { color: #FFEE98; } -.cm-s-vibrant-ink .cm-def { color: #8DA6CE; } -.cm-s-vibrant-ink span.cm-variable-2, .cm-s-vibrant span.cm-tag { color: #FFC66D; } -.cm-s-vibrant-ink span.cm-variable-3, .cm-s-vibrant span.cm-def { color: #FFC66D; } -.cm-s-vibrant-ink .cm-operator { color: #888; } -.cm-s-vibrant-ink .cm-comment { color: gray; font-weight: bold; } -.cm-s-vibrant-ink .cm-string { color: #A5C25C; } -.cm-s-vibrant-ink .cm-string-2 { color: red; } -.cm-s-vibrant-ink .cm-meta { color: #D8FA3C; } -.cm-s-vibrant-ink .cm-builtin { color: #8DA6CE; } -.cm-s-vibrant-ink .cm-tag { color: #8DA6CE; } -.cm-s-vibrant-ink .cm-attribute { color: #8DA6CE; } -.cm-s-vibrant-ink .cm-header { color: #FF6400; } -.cm-s-vibrant-ink .cm-hr { color: #AEAEAE; } -.cm-s-vibrant-ink .cm-link { color: blue; } -.cm-s-vibrant-ink .cm-error { border-bottom: 1px solid red; } - -.cm-s-vibrant-ink .CodeMirror-activeline-background { background: #27282E; } -.cm-s-vibrant-ink .CodeMirror-matchingbracket { outline:1px solid grey; color:white !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/xq-dark.css b/backend/_pv_1_3_5/static/codemirror/theme/xq-dark.css deleted file mode 100755 index e3bd960bb..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/xq-dark.css +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright (C) 2011 by MarkLogic Corporation -Author: Mike Brevoort - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -.cm-s-xq-dark.CodeMirror { background: #0a001f; color: #f8f8f8; } -.cm-s-xq-dark div.CodeMirror-selected { background: #27007A; } -.cm-s-xq-dark .CodeMirror-line::selection, .cm-s-xq-dark .CodeMirror-line > span::selection, .cm-s-xq-dark .CodeMirror-line > span > span::selection { background: rgba(39, 0, 122, 0.99); } -.cm-s-xq-dark .CodeMirror-line::-moz-selection, .cm-s-xq-dark .CodeMirror-line > span::-moz-selection, .cm-s-xq-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(39, 0, 122, 0.99); } -.cm-s-xq-dark .CodeMirror-gutters { background: #0a001f; border-right: 1px solid #aaa; } -.cm-s-xq-dark .CodeMirror-guttermarker { color: #FFBD40; } -.cm-s-xq-dark .CodeMirror-guttermarker-subtle { color: #f8f8f8; } -.cm-s-xq-dark .CodeMirror-linenumber { color: #f8f8f8; } -.cm-s-xq-dark .CodeMirror-cursor { border-left: 1px solid white; } - -.cm-s-xq-dark span.cm-keyword { color: #FFBD40; } -.cm-s-xq-dark span.cm-atom { color: #6C8CD5; } -.cm-s-xq-dark span.cm-number { color: #164; } -.cm-s-xq-dark span.cm-def { color: #FFF; text-decoration:underline; } -.cm-s-xq-dark span.cm-variable { color: #FFF; } -.cm-s-xq-dark span.cm-variable-2 { color: #EEE; } -.cm-s-xq-dark span.cm-variable-3 { color: #DDD; } -.cm-s-xq-dark span.cm-property {} -.cm-s-xq-dark span.cm-operator {} -.cm-s-xq-dark span.cm-comment { color: gray; } -.cm-s-xq-dark span.cm-string { color: #9FEE00; } -.cm-s-xq-dark span.cm-meta { color: yellow; } -.cm-s-xq-dark span.cm-qualifier { color: #FFF700; } -.cm-s-xq-dark span.cm-builtin { color: #30a; } -.cm-s-xq-dark span.cm-bracket { color: #cc7; } -.cm-s-xq-dark span.cm-tag { color: #FFBD40; } -.cm-s-xq-dark span.cm-attribute { color: #FFF700; } -.cm-s-xq-dark span.cm-error { color: #f00; } - -.cm-s-xq-dark .CodeMirror-activeline-background { background: #27282E; } -.cm-s-xq-dark .CodeMirror-matchingbracket { outline:1px solid grey; color:white !important; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/xq-light.css b/backend/_pv_1_3_5/static/codemirror/theme/xq-light.css deleted file mode 100755 index 8d2fcb667..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/xq-light.css +++ /dev/null @@ -1,43 +0,0 @@ -/* -Copyright (C) 2011 by MarkLogic Corporation -Author: Mike Brevoort - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -.cm-s-xq-light span.cm-keyword { line-height: 1em; font-weight: bold; color: #5A5CAD; } -.cm-s-xq-light span.cm-atom { color: #6C8CD5; } -.cm-s-xq-light span.cm-number { color: #164; } -.cm-s-xq-light span.cm-def { text-decoration:underline; } -.cm-s-xq-light span.cm-variable { color: black; } -.cm-s-xq-light span.cm-variable-2 { color:black; } -.cm-s-xq-light span.cm-variable-3 { color: black; } -.cm-s-xq-light span.cm-property {} -.cm-s-xq-light span.cm-operator {} -.cm-s-xq-light span.cm-comment { color: #0080FF; font-style: italic; } -.cm-s-xq-light span.cm-string { color: red; } -.cm-s-xq-light span.cm-meta { color: yellow; } -.cm-s-xq-light span.cm-qualifier { color: grey; } -.cm-s-xq-light span.cm-builtin { color: #7EA656; } -.cm-s-xq-light span.cm-bracket { color: #cc7; } -.cm-s-xq-light span.cm-tag { color: #3F7F7F; } -.cm-s-xq-light span.cm-attribute { color: #7F007F; } -.cm-s-xq-light span.cm-error { color: #f00; } - -.cm-s-xq-light .CodeMirror-activeline-background { background: #e8f2ff; } -.cm-s-xq-light .CodeMirror-matchingbracket { outline:1px solid grey;color:black !important;background:yellow; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/yeti.css b/backend/_pv_1_3_5/static/codemirror/theme/yeti.css deleted file mode 100755 index c70d4d214..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/yeti.css +++ /dev/null @@ -1,44 +0,0 @@ -/* - - Name: yeti - Author: Michael Kaminsky (http://github.com/mkaminsky11) - - Original yeti color scheme by Jesse Weed (https://github.com/jesseweed/yeti-syntax) - -*/ - - -.cm-s-yeti.CodeMirror { - background-color: #ECEAE8 !important; - color: #d1c9c0 !important; - border: none; -} - -.cm-s-yeti .CodeMirror-gutters { - color: #adaba6; - background-color: #E5E1DB; - border: none; -} -.cm-s-yeti .CodeMirror-cursor { border-left: solid thin #d1c9c0; } -.cm-s-yeti .CodeMirror-linenumber { color: #adaba6; } -.cm-s-yeti.CodeMirror-focused div.CodeMirror-selected { background: #DCD8D2; } -.cm-s-yeti .CodeMirror-line::selection, .cm-s-yeti .CodeMirror-line > span::selection, .cm-s-yeti .CodeMirror-line > span > span::selection { background: #DCD8D2; } -.cm-s-yeti .CodeMirror-line::-moz-selection, .cm-s-yeti .CodeMirror-line > span::-moz-selection, .cm-s-yeti .CodeMirror-line > span > span::-moz-selection { background: #DCD8D2; } -.cm-s-yeti span.cm-comment { color: #d4c8be; } -.cm-s-yeti span.cm-string, .cm-s-yeti span.cm-string-2 { color: #96c0d8; } -.cm-s-yeti span.cm-number { color: #a074c4; } -.cm-s-yeti span.cm-variable { color: #55b5db; } -.cm-s-yeti span.cm-variable-2 { color: #a074c4; } -.cm-s-yeti span.cm-def { color: #55b5db; } -.cm-s-yeti span.cm-operator { color: #9fb96e; } -.cm-s-yeti span.cm-keyword { color: #9fb96e; } -.cm-s-yeti span.cm-atom { color: #a074c4; } -.cm-s-yeti span.cm-meta { color: #96c0d8; } -.cm-s-yeti span.cm-tag { color: #96c0d8; } -.cm-s-yeti span.cm-attribute { color: #9fb96e; } -.cm-s-yeti span.cm-qualifier { color: #96c0d8; } -.cm-s-yeti span.cm-property { color: #a074c4; } -.cm-s-yeti span.cm-builtin { color: #a074c4; } -.cm-s-yeti span.cm-variable-3 { color: #96c0d8; } -.cm-s-yeti .CodeMirror-activeline-background { background: #E7E4E0; } -.cm-s-yeti .CodeMirror-matchingbracket { text-decoration: underline; } diff --git a/backend/_pv_1_3_5/static/codemirror/theme/zenburn.css b/backend/_pv_1_3_5/static/codemirror/theme/zenburn.css deleted file mode 100755 index 781c40aca..000000000 --- a/backend/_pv_1_3_5/static/codemirror/theme/zenburn.css +++ /dev/null @@ -1,37 +0,0 @@ -/** - * " - * Using Zenburn color palette from the Emacs Zenburn Theme - * https://github.com/bbatsov/zenburn-emacs/blob/master/zenburn-theme.el - * - * Also using parts of https://github.com/xavi/coderay-lighttable-theme - * " - * From: https://github.com/wisenomad/zenburn-lighttable-theme/blob/master/zenburn.css - */ - -.cm-s-zenburn .CodeMirror-gutters { background: #3f3f3f !important; } -.cm-s-zenburn .CodeMirror-foldgutter-open, .CodeMirror-foldgutter-folded { color: #999; } -.cm-s-zenburn .CodeMirror-cursor { border-left: 1px solid white; } -.cm-s-zenburn { background-color: #3f3f3f; color: #dcdccc; } -.cm-s-zenburn span.cm-builtin { color: #dcdccc; font-weight: bold; } -.cm-s-zenburn span.cm-comment { color: #7f9f7f; } -.cm-s-zenburn span.cm-keyword { color: #f0dfaf; font-weight: bold; } -.cm-s-zenburn span.cm-atom { color: #bfebbf; } -.cm-s-zenburn span.cm-def { color: #dcdccc; } -.cm-s-zenburn span.cm-variable { color: #dfaf8f; } -.cm-s-zenburn span.cm-variable-2 { color: #dcdccc; } -.cm-s-zenburn span.cm-string { color: #cc9393; } -.cm-s-zenburn span.cm-string-2 { color: #cc9393; } -.cm-s-zenburn span.cm-number { color: #dcdccc; } -.cm-s-zenburn span.cm-tag { color: #93e0e3; } -.cm-s-zenburn span.cm-property { color: #dfaf8f; } -.cm-s-zenburn span.cm-attribute { color: #dfaf8f; } -.cm-s-zenburn span.cm-qualifier { color: #7cb8bb; } -.cm-s-zenburn span.cm-meta { color: #f0dfaf; } -.cm-s-zenburn span.cm-header { color: #f0efd0; } -.cm-s-zenburn span.cm-operator { color: #f0efd0; } -.cm-s-zenburn span.CodeMirror-matchingbracket { box-sizing: border-box; background: transparent; border-bottom: 1px solid; } -.cm-s-zenburn span.CodeMirror-nonmatchingbracket { border-bottom: 1px solid; background: none; } -.cm-s-zenburn .CodeMirror-activeline { background: #000000; } -.cm-s-zenburn .CodeMirror-activeline-background { background: #000000; } -.cm-s-zenburn div.CodeMirror-selected { background: #545454; } -.cm-s-zenburn .CodeMirror-focused div.CodeMirror-selected { background: #4f4f4f; } diff --git a/backend/_pv_1_3_5/static/css/bootstrap-reload.css b/backend/_pv_1_3_5/static/css/bootstrap-reload.css deleted file mode 100755 index 0fd748a6d..000000000 --- a/backend/_pv_1_3_5/static/css/bootstrap-reload.css +++ /dev/null @@ -1,20 +0,0 @@ -.panel-refresh { - min-height:250px; - position:relative; -} - -.refresh-container { - position:absolute; - top:0; - right:0; - background:rgba(0, 0, 0, 0.5); - width:100%; - height:100%; - display: none; - text-align:center; - z-index:4; -} -.refresh-spinner { - padding: 30px; - opacity: 0.8; -} \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/css/bootstrap-theme.css b/backend/_pv_1_3_5/static/css/bootstrap-theme.css deleted file mode 100755 index 31d888266..000000000 --- a/backend/_pv_1_3_5/static/css/bootstrap-theme.css +++ /dev/null @@ -1,587 +0,0 @@ -/*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ -.btn-default, -.btn-primary, -.btn-success, -.btn-info, -.btn-warning, -.btn-danger { - text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); -} -.btn-default:active, -.btn-primary:active, -.btn-success:active, -.btn-info:active, -.btn-warning:active, -.btn-danger:active, -.btn-default.active, -.btn-primary.active, -.btn-success.active, -.btn-info.active, -.btn-warning.active, -.btn-danger.active { - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); -} -.btn-default.disabled, -.btn-primary.disabled, -.btn-success.disabled, -.btn-info.disabled, -.btn-warning.disabled, -.btn-danger.disabled, -.btn-default[disabled], -.btn-primary[disabled], -.btn-success[disabled], -.btn-info[disabled], -.btn-warning[disabled], -.btn-danger[disabled], -fieldset[disabled] .btn-default, -fieldset[disabled] .btn-primary, -fieldset[disabled] .btn-success, -fieldset[disabled] .btn-info, -fieldset[disabled] .btn-warning, -fieldset[disabled] .btn-danger { - -webkit-box-shadow: none; - box-shadow: none; -} -.btn-default .badge, -.btn-primary .badge, -.btn-success .badge, -.btn-info .badge, -.btn-warning .badge, -.btn-danger .badge { - text-shadow: none; -} -.btn:active, -.btn.active { - background-image: none; -} -.btn-default { - text-shadow: 0 1px 0 #fff; - background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); - background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); - background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #dbdbdb; - border-color: #ccc; -} -.btn-default:hover, -.btn-default:focus { - background-color: #e0e0e0; - background-position: 0 -15px; -} -.btn-default:active, -.btn-default.active { - background-color: #e0e0e0; - border-color: #dbdbdb; -} -.btn-default.disabled, -.btn-default[disabled], -fieldset[disabled] .btn-default, -.btn-default.disabled:hover, -.btn-default[disabled]:hover, -fieldset[disabled] .btn-default:hover, -.btn-default.disabled:focus, -.btn-default[disabled]:focus, -fieldset[disabled] .btn-default:focus, -.btn-default.disabled.focus, -.btn-default[disabled].focus, -fieldset[disabled] .btn-default.focus, -.btn-default.disabled:active, -.btn-default[disabled]:active, -fieldset[disabled] .btn-default:active, -.btn-default.disabled.active, -.btn-default[disabled].active, -fieldset[disabled] .btn-default.active { - background-color: #e0e0e0; - background-image: none; -} -.btn-primary { - background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88)); - background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #245580; -} -.btn-primary:hover, -.btn-primary:focus { - background-color: #265a88; - background-position: 0 -15px; -} -.btn-primary:active, -.btn-primary.active { - background-color: #265a88; - border-color: #245580; -} -.btn-primary.disabled, -.btn-primary[disabled], -fieldset[disabled] .btn-primary, -.btn-primary.disabled:hover, -.btn-primary[disabled]:hover, -fieldset[disabled] .btn-primary:hover, -.btn-primary.disabled:focus, -.btn-primary[disabled]:focus, -fieldset[disabled] .btn-primary:focus, -.btn-primary.disabled.focus, -.btn-primary[disabled].focus, -fieldset[disabled] .btn-primary.focus, -.btn-primary.disabled:active, -.btn-primary[disabled]:active, -fieldset[disabled] .btn-primary:active, -.btn-primary.disabled.active, -.btn-primary[disabled].active, -fieldset[disabled] .btn-primary.active { - background-color: #265a88; - background-image: none; -} -.btn-success { - background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); - background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); - background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #3e8f3e; -} -.btn-success:hover, -.btn-success:focus { - background-color: #419641; - background-position: 0 -15px; -} -.btn-success:active, -.btn-success.active { - background-color: #419641; - border-color: #3e8f3e; -} -.btn-success.disabled, -.btn-success[disabled], -fieldset[disabled] .btn-success, -.btn-success.disabled:hover, -.btn-success[disabled]:hover, -fieldset[disabled] .btn-success:hover, -.btn-success.disabled:focus, -.btn-success[disabled]:focus, -fieldset[disabled] .btn-success:focus, -.btn-success.disabled.focus, -.btn-success[disabled].focus, -fieldset[disabled] .btn-success.focus, -.btn-success.disabled:active, -.btn-success[disabled]:active, -fieldset[disabled] .btn-success:active, -.btn-success.disabled.active, -.btn-success[disabled].active, -fieldset[disabled] .btn-success.active { - background-color: #419641; - background-image: none; -} -.btn-info { - background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); - background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); - background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #28a4c9; -} -.btn-info:hover, -.btn-info:focus { - background-color: #2aabd2; - background-position: 0 -15px; -} -.btn-info:active, -.btn-info.active { - background-color: #2aabd2; - border-color: #28a4c9; -} -.btn-info.disabled, -.btn-info[disabled], -fieldset[disabled] .btn-info, -.btn-info.disabled:hover, -.btn-info[disabled]:hover, -fieldset[disabled] .btn-info:hover, -.btn-info.disabled:focus, -.btn-info[disabled]:focus, -fieldset[disabled] .btn-info:focus, -.btn-info.disabled.focus, -.btn-info[disabled].focus, -fieldset[disabled] .btn-info.focus, -.btn-info.disabled:active, -.btn-info[disabled]:active, -fieldset[disabled] .btn-info:active, -.btn-info.disabled.active, -.btn-info[disabled].active, -fieldset[disabled] .btn-info.active { - background-color: #2aabd2; - background-image: none; -} -.btn-warning { - background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); - background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); - background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #e38d13; -} -.btn-warning:hover, -.btn-warning:focus { - background-color: #eb9316; - background-position: 0 -15px; -} -.btn-warning:active, -.btn-warning.active { - background-color: #eb9316; - border-color: #e38d13; -} -.btn-warning.disabled, -.btn-warning[disabled], -fieldset[disabled] .btn-warning, -.btn-warning.disabled:hover, -.btn-warning[disabled]:hover, -fieldset[disabled] .btn-warning:hover, -.btn-warning.disabled:focus, -.btn-warning[disabled]:focus, -fieldset[disabled] .btn-warning:focus, -.btn-warning.disabled.focus, -.btn-warning[disabled].focus, -fieldset[disabled] .btn-warning.focus, -.btn-warning.disabled:active, -.btn-warning[disabled]:active, -fieldset[disabled] .btn-warning:active, -.btn-warning.disabled.active, -.btn-warning[disabled].active, -fieldset[disabled] .btn-warning.active { - background-color: #eb9316; - background-image: none; -} -.btn-danger { - background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); - background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); - background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #b92c28; -} -.btn-danger:hover, -.btn-danger:focus { - background-color: #c12e2a; - background-position: 0 -15px; -} -.btn-danger:active, -.btn-danger.active { - background-color: #c12e2a; - border-color: #b92c28; -} -.btn-danger.disabled, -.btn-danger[disabled], -fieldset[disabled] .btn-danger, -.btn-danger.disabled:hover, -.btn-danger[disabled]:hover, -fieldset[disabled] .btn-danger:hover, -.btn-danger.disabled:focus, -.btn-danger[disabled]:focus, -fieldset[disabled] .btn-danger:focus, -.btn-danger.disabled.focus, -.btn-danger[disabled].focus, -fieldset[disabled] .btn-danger.focus, -.btn-danger.disabled:active, -.btn-danger[disabled]:active, -fieldset[disabled] .btn-danger:active, -.btn-danger.disabled.active, -.btn-danger[disabled].active, -fieldset[disabled] .btn-danger.active { - background-color: #c12e2a; - background-image: none; -} -.thumbnail, -.img-thumbnail { - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); - box-shadow: 0 1px 2px rgba(0, 0, 0, .075); -} -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus { - background-color: #e8e8e8; - background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); - background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); - background-repeat: repeat-x; -} -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - background-color: #2e6da4; - background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); - background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); - background-repeat: repeat-x; -} -.navbar-default { - background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); - background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8)); - background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); -} -.navbar-default .navbar-nav > .open > a, -.navbar-default .navbar-nav > .active > a { - background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); - background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2)); - background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0); - background-repeat: repeat-x; - -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); - box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); -} -.navbar-brand, -.navbar-nav > li > a { - text-shadow: 0 1px 0 rgba(255, 255, 255, .25); -} -.navbar-inverse { - background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); - background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); - background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-radius: 4px; -} -.navbar-inverse .navbar-nav > .open > a, -.navbar-inverse .navbar-nav > .active > a { - background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%); - background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f)); - background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0); - background-repeat: repeat-x; - -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); - box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); -} -.navbar-inverse .navbar-brand, -.navbar-inverse .navbar-nav > li > a { - text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); -} -.navbar-static-top, -.navbar-fixed-top, -.navbar-fixed-bottom { - border-radius: 0; -} -@media (max-width: 767px) { - .navbar .navbar-nav .open .dropdown-menu > .active > a, - .navbar .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar .navbar-nav .open .dropdown-menu > .active > a:focus { - color: #fff; - background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); - background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); - background-repeat: repeat-x; - } -} -.alert { - text-shadow: 0 1px 0 rgba(255, 255, 255, .2); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); -} -.alert-success { - background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); - background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); - background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); - background-repeat: repeat-x; - border-color: #b2dba1; -} -.alert-info { - background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); - background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); - background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); - background-repeat: repeat-x; - border-color: #9acfea; -} -.alert-warning { - background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); - background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); - background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); - background-repeat: repeat-x; - border-color: #f5e79e; -} -.alert-danger { - background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); - background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); - background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); - background-repeat: repeat-x; - border-color: #dca7a7; -} -.progress { - background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); - background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); - background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar { - background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090)); - background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-success { - background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); - background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); - background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-info { - background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); - background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); - background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-warning { - background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); - background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); - background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-danger { - background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); - background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); - background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-striped { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); -} -.list-group { - border-radius: 4px; - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); - box-shadow: 0 1px 2px rgba(0, 0, 0, .075); -} -.list-group-item.active, -.list-group-item.active:hover, -.list-group-item.active:focus { - text-shadow: 0 -1px 0 #286090; - background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a)); - background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0); - background-repeat: repeat-x; - border-color: #2b669a; -} -.list-group-item.active .badge, -.list-group-item.active:hover .badge, -.list-group-item.active:focus .badge { - text-shadow: none; -} -.panel { - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); - box-shadow: 0 1px 2px rgba(0, 0, 0, .05); -} -.panel-default > .panel-heading { - background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); - background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); - background-repeat: repeat-x; -} -.panel-primary > .panel-heading { - background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4)); - background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0); - background-repeat: repeat-x; -} -.panel-success > .panel-heading { - background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); - background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); - background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); - background-repeat: repeat-x; -} -.panel-info > .panel-heading { - background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); - background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); - background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); - background-repeat: repeat-x; -} -.panel-warning > .panel-heading { - background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); - background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); - background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); - background-repeat: repeat-x; -} -.panel-danger > .panel-heading { - background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); - background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); - background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); - background-repeat: repeat-x; -} -.well { - background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); - background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); - background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); - background-repeat: repeat-x; - border-color: #dcdcdc; - -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); -} -/*# sourceMappingURL=bootstrap-theme.css.map */ diff --git a/backend/_pv_1_3_5/static/css/bootstrap-theme.css.map b/backend/_pv_1_3_5/static/css/bootstrap-theme.css.map deleted file mode 100755 index d876f60fb..000000000 --- a/backend/_pv_1_3_5/static/css/bootstrap-theme.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["bootstrap-theme.css","less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"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","file":"bootstrap-theme.css","sourcesContent":["/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.btn-default:active,\n.btn-primary:active,\n.btn-success:active,\n.btn-info:active,\n.btn-warning:active,\n.btn-danger:active,\n.btn-default.active,\n.btn-primary.active,\n.btn-success.active,\n.btn-info.active,\n.btn-warning.active,\n.btn-danger.active {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-default.disabled,\n.btn-primary.disabled,\n.btn-success.disabled,\n.btn-info.disabled,\n.btn-warning.disabled,\n.btn-danger.disabled,\n.btn-default[disabled],\n.btn-primary[disabled],\n.btn-success[disabled],\n.btn-info[disabled],\n.btn-warning[disabled],\n.btn-danger[disabled],\nfieldset[disabled] .btn-default,\nfieldset[disabled] .btn-primary,\nfieldset[disabled] .btn-success,\nfieldset[disabled] .btn-info,\nfieldset[disabled] .btn-warning,\nfieldset[disabled] .btn-danger {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-default .badge,\n.btn-primary .badge,\n.btn-success .badge,\n.btn-info .badge,\n.btn-warning .badge,\n.btn-danger .badge {\n text-shadow: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n}\n.btn-default {\n background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);\n background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #dbdbdb;\n text-shadow: 0 1px 0 #fff;\n border-color: #ccc;\n}\n.btn-default:hover,\n.btn-default:focus {\n background-color: #e0e0e0;\n background-position: 0 -15px;\n}\n.btn-default:active,\n.btn-default.active {\n background-color: #e0e0e0;\n border-color: #dbdbdb;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n background-color: #e0e0e0;\n background-image: none;\n}\n.btn-primary {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #245580;\n}\n.btn-primary:hover,\n.btn-primary:focus {\n background-color: #265a88;\n background-position: 0 -15px;\n}\n.btn-primary:active,\n.btn-primary.active {\n background-color: #265a88;\n border-color: #245580;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n background-color: #265a88;\n background-image: none;\n}\n.btn-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #3e8f3e;\n}\n.btn-success:hover,\n.btn-success:focus {\n background-color: #419641;\n background-position: 0 -15px;\n}\n.btn-success:active,\n.btn-success.active {\n background-color: #419641;\n border-color: #3e8f3e;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n background-color: #419641;\n background-image: none;\n}\n.btn-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #28a4c9;\n}\n.btn-info:hover,\n.btn-info:focus {\n background-color: #2aabd2;\n background-position: 0 -15px;\n}\n.btn-info:active,\n.btn-info.active {\n background-color: #2aabd2;\n border-color: #28a4c9;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n background-color: #2aabd2;\n background-image: none;\n}\n.btn-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #e38d13;\n}\n.btn-warning:hover,\n.btn-warning:focus {\n background-color: #eb9316;\n background-position: 0 -15px;\n}\n.btn-warning:active,\n.btn-warning.active {\n background-color: #eb9316;\n border-color: #e38d13;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n background-color: #eb9316;\n background-image: none;\n}\n.btn-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #b92c28;\n}\n.btn-danger:hover,\n.btn-danger:focus {\n background-color: #c12e2a;\n background-position: 0 -15px;\n}\n.btn-danger:active,\n.btn-danger.active {\n background-color: #c12e2a;\n border-color: #b92c28;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n background-color: #c12e2a;\n background-image: none;\n}\n.thumbnail,\n.img-thumbnail {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-color: #e8e8e8;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-color: #2e6da4;\n}\n.navbar-default {\n background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);\n}\n.navbar-inverse {\n background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);\n background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n}\n.navbar-inverse .navbar-brand,\n.navbar-inverse .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n@media (max-width: 767px) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n }\n}\n.alert {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.alert-success {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);\n border-color: #b2dba1;\n}\n.alert-info {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);\n border-color: #9acfea;\n}\n.alert-warning {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);\n border-color: #f5e79e;\n}\n.alert-danger {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);\n border-color: #dca7a7;\n}\n.progress {\n background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);\n}\n.progress-bar {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);\n}\n.progress-bar-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);\n}\n.progress-bar-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);\n}\n.progress-bar-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);\n}\n.progress-bar-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);\n}\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.list-group {\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 #286090;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);\n border-color: #2b669a;\n}\n.list-group-item.active .badge,\n.list-group-item.active:hover .badge,\n.list-group-item.active:focus .badge {\n text-shadow: none;\n}\n.panel {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.panel-default > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n}\n.panel-primary > .panel-heading {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n}\n.panel-success > .panel-heading {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);\n}\n.panel-info > .panel-heading {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);\n}\n.panel-warning > .panel-heading {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);\n}\n.panel-danger > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);\n}\n.well {\n background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);\n border-color: #dcdcdc;\n -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n/*# sourceMappingURL=bootstrap-theme.css.map */","/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n .box-shadow(none);\n }\n\n .badge {\n text-shadow: none;\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257\n border-radius: @navbar-border-radius;\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n// Fix active state of dropdown items in collapsed mode\n@media (max-width: @grid-float-breakpoint-max) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: #fff;\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n }\n }\n}\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n\n .badge {\n text-shadow: none;\n }\n}\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]} \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/css/bootstrap-theme.min.css b/backend/_pv_1_3_5/static/css/bootstrap-theme.min.css deleted file mode 100755 index 5e3940195..000000000 --- a/backend/_pv_1_3_5/static/css/bootstrap-theme.min.css +++ /dev/null @@ -1,6 +0,0 @@ -/*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} -/*# sourceMappingURL=bootstrap-theme.min.css.map */ \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/css/bootstrap-theme.min.css.map b/backend/_pv_1_3_5/static/css/bootstrap-theme.min.css.map deleted file mode 100755 index 94813e900..000000000 --- a/backend/_pv_1_3_5/static/css/bootstrap-theme.min.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n .box-shadow(none);\n }\n\n .badge {\n text-shadow: none;\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257\n border-radius: @navbar-border-radius;\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n// Fix active state of dropdown items in collapsed mode\n@media (max-width: @grid-float-breakpoint-max) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: #fff;\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n }\n }\n}\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n\n .badge {\n text-shadow: none;\n }\n}\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]} \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/css/bootstrap-treeview.css b/backend/_pv_1_3_5/static/css/bootstrap-treeview.css deleted file mode 100755 index 23c6cf066..000000000 --- a/backend/_pv_1_3_5/static/css/bootstrap-treeview.css +++ /dev/null @@ -1,37 +0,0 @@ -/* ========================================================= - * bootstrap-treeview.css v1.2.0 - * ========================================================= - * Copyright 2013 Jonathan Miles - * Project URL : http://www.jondmiles.com/bootstrap-treeview - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================================================= */ - -.treeview .list-group-item { - cursor: pointer; -} - -.treeview span.indent { - margin-left: 10px; - margin-right: 10px; -} - -.treeview span.icon { - width: 12px; - margin-right: 5px; -} - -.treeview .node-disabled { - color: silver; - cursor: not-allowed; -} \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/css/bootstrap-treeview.min.css b/backend/_pv_1_3_5/static/css/bootstrap-treeview.min.css deleted file mode 100755 index 57a348a87..000000000 --- a/backend/_pv_1_3_5/static/css/bootstrap-treeview.min.css +++ /dev/null @@ -1 +0,0 @@ -.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed} \ No newline at end of file diff --git a/backend/_pv_1_3_5/static/css/bootstrap.css b/backend/_pv_1_3_5/static/css/bootstrap.css deleted file mode 100755 index 6167622ce..000000000 --- a/backend/_pv_1_3_5/static/css/bootstrap.css +++ /dev/null @@ -1,6757 +0,0 @@ -/*! - * Bootstrap v3.3.7 (http://getbootstrap.com) - * Copyright 2011-2016 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ -/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ -html { - font-family: sans-serif; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; -} -body { - margin: 0; -} -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -main, -menu, -nav, -section, -summary { - display: block; -} -audio, -canvas, -progress, -video { - display: inline-block; - vertical-align: baseline; -} -audio:not([controls]) { - display: none; - height: 0; -} -[hidden], -template { - display: none; -} -a { - background-color: transparent; -} -a:active, -a:hover { - outline: 0; -} -abbr[title] { - border-bottom: 1px dotted; -} -b, -strong { - font-weight: bold; -} -dfn { - font-style: italic; -} -h1 { - margin: .67em 0; - font-size: 2em; -} -mark { - color: #000; - background: #ff0; -} -small { - font-size: 80%; -} -sub, -sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; -} -sup { - top: -.5em; -} -sub { - bottom: -.25em; -} -img { - border: 0; -} -svg:not(:root) { - overflow: hidden; -} -figure { - margin: 1em 40px; -} -hr { - height: 0; - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; -} -pre { - overflow: auto; -} -code, -kbd, -pre, -samp { - font-family: monospace, monospace; - font-size: 1em; -} -button, -input, -optgroup, -select, -textarea { - margin: 0; - font: inherit; - color: inherit; -} -button { - overflow: visible; -} -button, -select { - text-transform: none; -} -button, -html input[type="button"], -input[type="reset"], -input[type="submit"] { - -webkit-appearance: button; - cursor: pointer; -} -button[disabled], -html input[disabled] { - cursor: default; -} -button::-moz-focus-inner, -input::-moz-focus-inner { - padding: 0; - border: 0; -} -input { - line-height: normal; -} -input[type="checkbox"], -input[type="radio"] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; - padding: 0; -} -input[type="number"]::-webkit-inner-spin-button, -input[type="number"]::-webkit-outer-spin-button { - height: auto; -} -input[type="search"] { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - -webkit-appearance: textfield; -} -input[type="search"]::-webkit-search-cancel-button, -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} -fieldset { - padding: .35em .625em .75em; - margin: 0 2px; - border: 1px solid #c0c0c0; -} -legend { - padding: 0; - border: 0; -} -textarea { - overflow: auto; -} -optgroup { - font-weight: bold; -} -table { - border-spacing: 0; - border-collapse: collapse; -} -td, -th { - padding: 0; -} -/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ -@media print { - *, - *:before, - *:after { - color: #000 !important; - text-shadow: none !important; - background: transparent !important; - -webkit-box-shadow: none !important; - box-shadow: none !important; - } - a, - a:visited { - text-decoration: underline; - } - a[href]:after { - content: " (" attr(href) ")"; - } - abbr[title]:after { - content: " (" attr(title) ")"; - } - a[href^="#"]:after, - a[href^="javascript:"]:after { - content: ""; - } - pre, - blockquote { - border: 1px solid #999; - - page-break-inside: avoid; - } - thead { - display: table-header-group; - } - tr, - img { - page-break-inside: avoid; - } - img { - max-width: 100% !important; - } - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - h2, - h3 { - page-break-after: avoid; - } - .navbar { - display: none; - } - .btn > .caret, - .dropup > .btn > .caret { - border-top-color: #000 !important; - } - .label { - border: 1px solid #000; - } - .table { - border-collapse: collapse !important; - } - .table td, - .table th { - background-color: #fff !important; - } - .table-bordered th, - .table-bordered td { - border: 1px solid #ddd !important; - } -} -@font-face { - font-family: 'Glyphicons Halflings'; - - src: url('../fonts/glyphicons-halflings-regular.eot'); - src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); -} -.glyphicon { - position: relative; - top: 1px; - display: inline-block; - font-family: 'Glyphicons Halflings'; - font-style: normal; - font-weight: normal; - line-height: 1; - - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -.glyphicon-asterisk:before { - content: "\002a"; -} -.glyphicon-plus:before { - content: "\002b"; -} -.glyphicon-euro:before, -.glyphicon-eur:before { - content: "\20ac"; -} -.glyphicon-minus:before { - content: "\2212"; -} -.glyphicon-cloud:before { - content: "\2601"; -} -.glyphicon-envelope:before { - content: "\2709"; -} -.glyphicon-pencil:before { - content: "\270f"; -} -.glyphicon-glass:before { - content: "\e001"; -} -.glyphicon-music:before { - content: "\e002"; -} -.glyphicon-search:before { - content: "\e003"; -} -.glyphicon-heart:before { - content: "\e005"; -} -.glyphicon-star:before { - content: "\e006"; -} -.glyphicon-star-empty:before { - content: "\e007"; -} -.glyphicon-user:before { - content: "\e008"; -} -.glyphicon-film:before { - content: "\e009"; -} -.glyphicon-th-large:before { - content: "\e010"; -} -.glyphicon-th:before { - content: "\e011"; -} -.glyphicon-th-list:before { - content: "\e012"; -} -.glyphicon-ok:before { - content: "\e013"; -} -.glyphicon-remove:before { - content: "\e014"; -} -.glyphicon-zoom-in:before { - content: "\e015"; -} -.glyphicon-zoom-out:before { - content: "\e016"; -} -.glyphicon-off:before { - content: "\e017"; -} -.glyphicon-signal:before { - content: "\e018"; -} -.glyphicon-cog:before { - content: "\e019"; -} -.glyphicon-trash:before { - content: "\e020"; -} -.glyphicon-home:before { - content: "\e021"; -} -.glyphicon-file:before { - content: "\e022"; -} -.glyphicon-time:before { - content: "\e023"; -} -.glyphicon-road:before { - content: "\e024"; -} -.glyphicon-download-alt:before { - content: "\e025"; -} -.glyphicon-download:before { - content: "\e026"; -} -.glyphicon-upload:before { - content: "\e027"; -} -.glyphicon-inbox:before { - content: "\e028"; -} -.glyphicon-play-circle:before { - content: "\e029"; -} -.glyphicon-repeat:before { - content: "\e030"; -} -.glyphicon-refresh:before { - content: "\e031"; -} -.glyphicon-list-alt:before { - content: "\e032"; -} -.glyphicon-lock:before { - content: "\e033"; -} -.glyphicon-flag:before { - content: "\e034"; -} -.glyphicon-headphones:before { - content: "\e035"; -} -.glyphicon-volume-off:before { - content: "\e036"; -} -.glyphicon-volume-down:before { - content: "\e037"; -} -.glyphicon-volume-up:before { - content: "\e038"; -} -.glyphicon-qrcode:before { - content: "\e039"; -} -.glyphicon-barcode:before { - content: "\e040"; -} -.glyphicon-tag:before { - content: "\e041"; -} -.glyphicon-tags:before { - content: "\e042"; -} -.glyphicon-book:before { - content: "\e043"; -} -.glyphicon-bookmark:before { - content: "\e044"; -} -.glyphicon-print:before { - content: "\e045"; -} -.glyphicon-camera:before { - content: "\e046"; -} -.glyphicon-font:before { - content: "\e047"; -} -.glyphicon-bold:before { - content: "\e048"; -} -.glyphicon-italic:before { - content: "\e049"; -} -.glyphicon-text-height:before { - content: "\e050"; -} -.glyphicon-text-width:before { - content: "\e051"; -} -.glyphicon-align-left:before { - content: "\e052"; -} -.glyphicon-align-center:before { - content: "\e053"; -} -.glyphicon-align-right:before { - content: "\e054"; -} -.glyphicon-align-justify:before { - content: "\e055"; -} -.glyphicon-list:before { - content: "\e056"; -} -.glyphicon-indent-left:before { - content: "\e057"; -} -.glyphicon-indent-right:before { - content: "\e058"; -} -.glyphicon-facetime-video:before { - content: "\e059"; -} -.glyphicon-picture:before { - content: "\e060"; -} -.glyphicon-map-marker:before { - content: "\e062"; -} -.glyphicon-adjust:before { - content: "\e063"; -} -.glyphicon-tint:before { - content: "\e064"; -} -.glyphicon-edit:before { - content: "\e065"; -} -.glyphicon-share:before { - content: "\e066"; -} -.glyphicon-check:before { - content: "\e067"; -} -.glyphicon-move:before { - content: "\e068"; -} -.glyphicon-step-backward:before { - content: "\e069"; -} -.glyphicon-fast-backward:before { - content: "\e070"; -} -.glyphicon-backward:before { - content: "\e071"; -} -.glyphicon-play:before { - content: "\e072"; -} -.glyphicon-pause:before { - content: "\e073"; -} -.glyphicon-stop:before { - content: "\e074"; -} -.glyphicon-forward:before { - content: "\e075"; -} -.glyphicon-fast-forward:before { - content: "\e076"; -} -.glyphicon-step-forward:before { - content: "\e077"; -} -.glyphicon-eject:before { - content: "\e078"; -} -.glyphicon-chevron-left:before { - content: "\e079"; -} -.glyphicon-chevron-right:before { - content: "\e080"; -} -.glyphicon-plus-sign:before { - content: "\e081"; -} -.glyphicon-minus-sign:before { - content: "\e082"; -} -.glyphicon-remove-sign:before { - content: "\e083"; -} -.glyphicon-ok-sign:before { - content: "\e084"; -} -.glyphicon-question-sign:before { - content: "\e085"; -} -.glyphicon-info-sign:before { - content: "\e086"; -} -.glyphicon-screenshot:before { - content: "\e087"; -} -.glyphicon-remove-circle:before { - content: "\e088"; -} -.glyphicon-ok-circle:before { - content: "\e089"; -} -.glyphicon-ban-circle:before { - content: "\e090"; -} -.glyphicon-arrow-left:before { - content: "\e091"; -} -.glyphicon-arrow-right:before { - content: "\e092"; -} -.glyphicon-arrow-up:before { - content: "\e093"; -} -.glyphicon-arrow-down:before { - content: "\e094"; -} -.glyphicon-share-alt:before { - content: "\e095"; -} -.glyphicon-resize-full:before { - content: "\e096"; -} -.glyphicon-resize-small:before { - content: "\e097"; -} -.glyphicon-exclamation-sign:before { - content: "\e101"; -} -.glyphicon-gift:before { - content: "\e102"; -} -.glyphicon-leaf:before { - content: "\e103"; -} -.glyphicon-fire:before { - content: "\e104"; -} -.glyphicon-eye-open:before { - content: "\e105"; -} -.glyphicon-eye-close:before { - content: "\e106"; -} -.glyphicon-warning-sign:before { - content: "\e107"; -} -.glyphicon-plane:before { - content: "\e108"; -} -.glyphicon-calendar:before { - content: "\e109"; -} -.glyphicon-random:before { - content: "\e110"; -} -.glyphicon-comment:before { - content: "\e111"; -} -.glyphicon-magnet:before { - content: "\e112"; -} -.glyphicon-chevron-up:before { - content: "\e113"; -} -.glyphicon-chevron-down:before { - content: "\e114"; -} -.glyphicon-retweet:before { - content: "\e115"; -} -.glyphicon-shopping-cart:before { - content: "\e116"; -} -.glyphicon-folder-close:before { - content: "\e117"; -} -.glyphicon-folder-open:before { - content: "\e118"; -} -.glyphicon-resize-vertical:before { - content: "\e119"; -} -.glyphicon-resize-horizontal:before { - content: "\e120"; -} -.glyphicon-hdd:before { - content: "\e121"; -} -.glyphicon-bullhorn:before { - content: "\e122"; -} -.glyphicon-bell:before { - content: "\e123"; -} -.glyphicon-certificate:before { - content: "\e124"; -} -.glyphicon-thumbs-up:before { - content: "\e125"; -} -.glyphicon-thumbs-down:before { - content: "\e126"; -} -.glyphicon-hand-right:before { - content: "\e127"; -} -.glyphicon-hand-left:before { - content: "\e128"; -} -.glyphicon-hand-up:before { - content: "\e129"; -} -.glyphicon-hand-down:before { - content: "\e130"; -} -.glyphicon-circle-arrow-right:before { - content: "\e131"; -} -.glyphicon-circle-arrow-left:before { - content: "\e132"; -} -.glyphicon-circle-arrow-up:before { - content: "\e133"; -} -.glyphicon-circle-arrow-down:before { - content: "\e134"; -} -.glyphicon-globe:before { - content: "\e135"; -} -.glyphicon-wrench:before { - content: "\e136"; -} -.glyphicon-tasks:before { - content: "\e137"; -} -.glyphicon-filter:before { - content: "\e138"; -} -.glyphicon-briefcase:before { - content: "\e139"; -} -.glyphicon-fullscreen:before { - content: "\e140"; -} -.glyphicon-dashboard:before { - content: "\e141"; -} -.glyphicon-paperclip:before { - content: "\e142"; -} -.glyphicon-heart-empty:before { - content: "\e143"; -} -.glyphicon-link:before { - content: "\e144"; -} -.glyphicon-phone:before { - content: "\e145"; -} -.glyphicon-pushpin:before { - content: "\e146"; -} -.glyphicon-usd:before { - content: "\e148"; -} -.glyphicon-gbp:before { - content: "\e149"; -} -.glyphicon-sort:before { - content: "\e150"; -} -.glyphicon-sort-by-alphabet:before { - content: "\e151"; -} -.glyphicon-sort-by-alphabet-alt:before { - content: "\e152"; -} -.glyphicon-sort-by-order:before { - content: "\e153"; -} -.glyphicon-sort-by-order-alt:before { - content: "\e154"; -} -.glyphicon-sort-by-attributes:before { - content: "\e155"; -} -.glyphicon-sort-by-attributes-alt:before { - content: "\e156"; -} -.glyphicon-unchecked:before { - content: "\e157"; -} -.glyphicon-expand:before { - content: "\e158"; -} -.glyphicon-collapse-down:before { - content: "\e159"; -} -.glyphicon-collapse-up:before { - content: "\e160"; -} -.glyphicon-log-in:before { - content: "\e161"; -} -.glyphicon-flash:before { - content: "\e162"; -} -.glyphicon-log-out:before { - content: "\e163"; -} -.glyphicon-new-window:before { - content: "\e164"; -} -.glyphicon-record:before { - content: "\e165"; -} -.glyphicon-save:before { - content: "\e166"; -} -.glyphicon-open:before { - content: "\e167"; -} -.glyphicon-saved:before { - content: "\e168"; -} -.glyphicon-import:before { - content: "\e169"; -} -.glyphicon-export:before { - content: "\e170"; -} -.glyphicon-send:before { - content: "\e171"; -} -.glyphicon-floppy-disk:before { - content: "\e172"; -} -.glyphicon-floppy-saved:before { - content: "\e173"; -} -.glyphicon-floppy-remove:before { - content: "\e174"; -} -.glyphicon-floppy-save:before { - content: "\e175"; -} -.glyphicon-floppy-open:before { - content: "\e176"; -} -.glyphicon-credit-card:before { - content: "\e177"; -} -.glyphicon-transfer:before { - content: "\e178"; -} -.glyphicon-cutlery:before { - content: "\e179"; -} -.glyphicon-header:before { - content: "\e180"; -} -.glyphicon-compressed:before { - content: "\e181"; -} -.glyphicon-earphone:before { - content: "\e182"; -} -.glyphicon-phone-alt:before { - content: "\e183"; -} -.glyphicon-tower:before { - content: "\e184"; -} -.glyphicon-stats:before { - content: "\e185"; -} -.glyphicon-sd-video:before { - content: "\e186"; -} -.glyphicon-hd-video:before { - content: "\e187"; -} -.glyphicon-subtitles:before { - content: "\e188"; -} -.glyphicon-sound-stereo:before { - content: "\e189"; -} -.glyphicon-sound-dolby:before { - content: "\e190"; -} -.glyphicon-sound-5-1:before { - content: "\e191"; -} -.glyphicon-sound-6-1:before { - content: "\e192"; -} -.glyphicon-sound-7-1:before { - content: "\e193"; -} -.glyphicon-copyright-mark:before { - content: "\e194"; -} -.glyphicon-registration-mark:before { - content: "\e195"; -} -.glyphicon-cloud-download:before { - content: "\e197"; -} -.glyphicon-cloud-upload:before { - content: "\e198"; -} -.glyphicon-tree-conifer:before { - content: "\e199"; -} -.glyphicon-tree-deciduous:before { - content: "\e200"; -} -.glyphicon-cd:before { - content: "\e201"; -} -.glyphicon-save-file:before { - content: "\e202"; -} -.glyphicon-open-file:before { - content: "\e203"; -} -.glyphicon-level-up:before { - content: "\e204"; -} -.glyphicon-copy:before { - content: "\e205"; -} -.glyphicon-paste:before { - content: "\e206"; -} -.glyphicon-alert:before { - content: "\e209"; -} -.glyphicon-equalizer:before { - content: "\e210"; -} -.glyphicon-king:before { - content: "\e211"; -} -.glyphicon-queen:before { - content: "\e212"; -} -.glyphicon-pawn:before { - content: "\e213"; -} -.glyphicon-bishop:before { - content: "\e214"; -} -.glyphicon-knight:before { - content: "\e215"; -} -.glyphicon-baby-formula:before { - content: "\e216"; -} -.glyphicon-tent:before { - content: "\26fa"; -} -.glyphicon-blackboard:before { - content: "\e218"; -} -.glyphicon-bed:before { - content: "\e219"; -} -.glyphicon-apple:before { - content: "\f8ff"; -} -.glyphicon-erase:before { - content: "\e221"; -} -.glyphicon-hourglass:before { - content: "\231b"; -} -.glyphicon-lamp:before { - content: "\e223"; -} -.glyphicon-duplicate:before { - content: "\e224"; -} -.glyphicon-piggy-bank:before { - content: "\e225"; -} -.glyphicon-scissors:before { - content: "\e226"; -} -.glyphicon-bitcoin:before { - content: "\e227"; -} -.glyphicon-btc:before { - content: "\e227"; -} -.glyphicon-xbt:before { - content: "\e227"; -} -.glyphicon-yen:before { - content: "\00a5"; -} -.glyphicon-jpy:before { - content: "\00a5"; -} -.glyphicon-ruble:before { - content: "\20bd"; -} -.glyphicon-rub:before { - content: "\20bd"; -} -.glyphicon-scale:before { - content: "\e230"; -} -.glyphicon-ice-lolly:before { - content: "\e231"; -} -.glyphicon-ice-lolly-tasted:before { - content: "\e232"; -} -.glyphicon-education:before { - content: "\e233"; -} -.glyphicon-option-horizontal:before { - content: "\e234"; -} -.glyphicon-option-vertical:before { - content: "\e235"; -} -.glyphicon-menu-hamburger:before { - content: "\e236"; -} -.glyphicon-modal-window:before { - content: "\e237"; -} -.glyphicon-oil:before { - content: "\e238"; -} -.glyphicon-grain:before { - content: "\e239"; -} -.glyphicon-sunglasses:before { - content: "\e240"; -} -.glyphicon-text-size:before { - content: "\e241"; -} -.glyphicon-text-color:before { - content: "\e242"; -} -.glyphicon-text-background:before { - content: "\e243"; -} -.glyphicon-object-align-top:before { - content: "\e244"; -} -.glyphicon-object-align-bottom:before { - content: "\e245"; -} -.glyphicon-object-align-horizontal:before { - content: "\e246"; -} -.glyphicon-object-align-left:before { - content: "\e247"; -} -.glyphicon-object-align-vertical:before { - content: "\e248"; -} -.glyphicon-object-align-right:before { - content: "\e249"; -} -.glyphicon-triangle-right:before { - content: "\e250"; -} -.glyphicon-triangle-left:before { - content: "\e251"; -} -.glyphicon-triangle-bottom:before { - content: "\e252"; -} -.glyphicon-triangle-top:before { - content: "\e253"; -} -.glyphicon-console:before { - content: "\e254"; -} -.glyphicon-superscript:before { - content: "\e255"; -} -.glyphicon-subscript:before { - content: "\e256"; -} -.glyphicon-menu-left:before { - content: "\e257"; -} -.glyphicon-menu-right:before { - content: "\e258"; -} -.glyphicon-menu-down:before { - content: "\e259"; -} -.glyphicon-menu-up:before { - content: "\e260"; -} -* { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -*:before, -*:after { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -html { - font-size: 10px; - - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); -} -body { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 1.42857143; - color: #333; - background-color: #fff; -} -input, -button, -select, -textarea { - font-family: inherit; - font-size: inherit; - line-height: inherit; -} -a { - color: #337ab7; - text-decoration: none; -} -a:hover, -a:focus { - color: #23527c; - text-decoration: underline; -} -a:focus { - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -figure { - margin: 0; -} -img { - vertical-align: middle; -} -.img-responsive, -.thumbnail > img, -.thumbnail a > img, -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - display: block; - max-width: 100%; - height: auto; -} -.img-rounded { - border-radius: 6px; -} -.img-thumbnail { - display: inline-block; - max-width: 100%; - height: auto; - padding: 4px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: all .2s ease-in-out; - -o-transition: all .2s ease-in-out; - transition: all .2s ease-in-out; -} -.img-circle { - border-radius: 50%; -} -hr { - margin-top: 20px; - margin-bottom: 20px; - border: 0; - border-top: 1px solid #eee; -} -.sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0; -} -.sr-only-focusable:active, -.sr-only-focusable:focus { - position: static; - width: auto; - height: auto; - margin: 0; - overflow: visible; - clip: auto; -} -[role="button"] { - cursor: pointer; -} -h1, -h2, -h3, -h4, -h5, -h6, -.h1, -.h2, -.h3, -.h4, -.h5, -.h6 { - font-family: inherit; - font-weight: 500; - line-height: 1.1; - color: inherit; -} -h1 small, -h2 small, -h3 small, -h4 small, -h5 small, -h6 small, -.h1 small, -.h2 small, -.h3 small, -.h4 small, -.h5 small, -.h6 small, -h1 .small, -h2 .small, -h3 .small, -h4 .small, -h5 .small, -h6 .small, -.h1 .small, -.h2 .small, -.h3 .small, -.h4 .small, -.h5 .small, -.h6 .small { - font-weight: normal; - line-height: 1; - color: #777; -} -h1, -.h1, -h2, -.h2, -h3, -.h3 { - margin-top: 20px; - margin-bottom: 10px; -} -h1 small, -.h1 small, -h2 small, -.h2 small, -h3 small, -.h3 small, -h1 .small, -.h1 .small, -h2 .small, -.h2 .small, -h3 .small, -.h3 .small { - font-size: 65%; -} -h4, -.h4, -h5, -.h5, -h6, -.h6 { - margin-top: 10px; - margin-bottom: 10px; -} -h4 small, -.h4 small, -h5 small, -.h5 small, -h6 small, -.h6 small, -h4 .small, -.h4 .small, -h5 .small, -.h5 .small, -h6 .small, -.h6 .small { - font-size: 75%; -} -h1, -.h1 { - font-size: 36px; -} -h2, -.h2 { - font-size: 30px; -} -h3, -.h3 { - font-size: 24px; -} -h4, -.h4 { - font-size: 18px; -} -h5, -.h5 { - font-size: 14px; -} -h6, -.h6 { - font-size: 12px; -} -p { - margin: 0 0 10px; -} -.lead { - margin-bottom: 20px; - font-size: 16px; - font-weight: 300; - line-height: 1.4; -} -@media (min-width: 768px) { - .lead { - font-size: 21px; - } -} -small, -.small { - font-size: 85%; -} -mark, -.mark { - padding: .2em; - background-color: #fcf8e3; -} -.text-left { - text-align: left; -} -.text-right { - text-align: right; -} -.text-center { - text-align: center; -} -.text-justify { - text-align: justify; -} -.text-nowrap { - white-space: nowrap; -} -.text-lowercase { - text-transform: lowercase; -} -.text-uppercase { - text-transform: uppercase; -} -.text-capitalize { - text-transform: capitalize; -} -.text-muted { - color: #777; -} -.text-primary { - color: #337ab7; -} -a.text-primary:hover, -a.text-primary:focus { - color: #286090; -} -.text-success { - color: #3c763d; -} -a.text-success:hover, -a.text-success:focus { - color: #2b542c; -} -.text-info { - color: #31708f; -} -a.text-info:hover, -a.text-info:focus { - color: #245269; -} -.text-warning { - color: #8a6d3b; -} -a.text-warning:hover, -a.text-warning:focus { - color: #66512c; -} -.text-danger { - color: #a94442; -} -a.text-danger:hover, -a.text-danger:focus { - color: #843534; -} -.bg-primary { - color: #fff; - background-color: #337ab7; -} -a.bg-primary:hover, -a.bg-primary:focus { - background-color: #286090; -} -.bg-success { - background-color: #dff0d8; -} -a.bg-success:hover, -a.bg-success:focus { - background-color: #c1e2b3; -} -.bg-info { - background-color: #d9edf7; -} -a.bg-info:hover, -a.bg-info:focus { - background-color: #afd9ee; -} -.bg-warning { - background-color: #fcf8e3; -} -a.bg-warning:hover, -a.bg-warning:focus { - background-color: #f7ecb5; -} -.bg-danger { - background-color: #f2dede; -} -a.bg-danger:hover, -a.bg-danger:focus { - background-color: #e4b9b9; -} -.page-header { - padding-bottom: 9px; - margin: 40px 0 20px; - border-bottom: 1px solid #eee; -} -ul, -ol { - margin-top: 0; - margin-bottom: 10px; -} -ul ul, -ol ul, -ul ol, -ol ol { - margin-bottom: 0; -} -.list-unstyled { - padding-left: 0; - list-style: none; -} -.list-inline { - padding-left: 0; - margin-left: -5px; - list-style: none; -} -.list-inline > li { - display: inline-block; - padding-right: 5px; - padding-left: 5px; -} -dl { - margin-top: 0; - margin-bottom: 20px; -} -dt, -dd { - line-height: 1.42857143; -} -dt { - font-weight: bold; -} -dd { - margin-left: 0; -} -@media (min-width: 768px) { - .dl-horizontal dt { - float: left; - width: 160px; - overflow: hidden; - clear: left; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap; - } - .dl-horizontal dd { - margin-left: 180px; - } -} -abbr[title], -abbr[data-original-title] { - cursor: help; - border-bottom: 1px dotted #777; -} -.initialism { - font-size: 90%; - text-transform: uppercase; -} -blockquote { - padding: 10px 20px; - margin: 0 0 20px; - font-size: 17.5px; - border-left: 5px solid #eee; -} -blockquote p:last-child, -blockquote ul:last-child, -blockquote ol:last-child { - margin-bottom: 0; -} -blockquote footer, -blockquote small, -blockquote .small { - display: block; - font-size: 80%; - line-height: 1.42857143; - color: #777; -} -blockquote footer:before, -blockquote small:before, -blockquote .small:before { - content: '\2014 \00A0'; -} -.blockquote-reverse, -blockquote.pull-right { - padding-right: 15px; - padding-left: 0; - text-align: right; - border-right: 5px solid #eee; - border-left: 0; -} -.blockquote-reverse footer:before, -blockquote.pull-right footer:before, -.blockquote-reverse small:before, -blockquote.pull-right small:before, -.blockquote-reverse .small:before, -blockquote.pull-right .small:before { - content: ''; -} -.blockquote-reverse footer:after, -blockquote.pull-right footer:after, -.blockquote-reverse small:after, -blockquote.pull-right small:after, -.blockquote-reverse .small:after, -blockquote.pull-right .small:after { - content: '\00A0 \2014'; -} -address { - margin-bottom: 20px; - font-style: normal; - line-height: 1.42857143; -} -code, -kbd, -pre, -samp { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; -} -code { - padding: 2px 4px; - font-size: 90%; - color: #c7254e; - background-color: #f9f2f4; - border-radius: 4px; -} -kbd { - padding: 2px 4px; - font-size: 90%; - color: #fff; - background-color: #333; - border-radius: 3px; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); -} -kbd kbd { - padding: 0; - font-size: 100%; - font-weight: bold; - -webkit-box-shadow: none; - box-shadow: none; -} -pre { - display: block; - padding: 9.5px; - margin: 0 0 10px; - font-size: 13px; - line-height: 1.42857143; - color: #333; - word-break: break-all; - word-wrap: break-word; - background-color: #f5f5f5; - border: 1px solid #ccc; - border-radius: 4px; -} -pre code { - padding: 0; - font-size: inherit; - color: inherit; - white-space: pre-wrap; - background-color: transparent; - border-radius: 0; -} -.pre-scrollable { - max-height: 340px; - overflow-y: scroll; -} -.container { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} -@media (min-width: 768px) { - .container { - width: 750px; - } -} -@media (min-width: 992px) { - .container { - width: 970px; - } -} -@media (min-width: 1200px) { - .container { - width: 1170px; - } -} -.container-fluid { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; -} -.row { - margin-right: -15px; - margin-left: -15px; -} -.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { - position: relative; - min-height: 1px; - padding-right: 15px; - padding-left: 15px; -} -.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { - float: left; -} -.col-xs-12 { - width: 100%; -} -.col-xs-11 { - width: 91.66666667%; -} -.col-xs-10 { - width: 83.33333333%; -} -.col-xs-9 { - width: 75%; -} -.col-xs-8 { - width: 66.66666667%; -} -.col-xs-7 { - width: 58.33333333%; -} -.col-xs-6 { - width: 50%; -} -.col-xs-5 { - width: 41.66666667%; -} -.col-xs-4 { - width: 33.33333333%; -} -.col-xs-3 { - width: 25%; -} -.col-xs-2 { - width: 16.66666667%; -} -.col-xs-1 { - width: 8.33333333%; -} -.col-xs-pull-12 { - right: 100%; -} -.col-xs-pull-11 { - right: 91.66666667%; -} -.col-xs-pull-10 { - right: 83.33333333%; -} -.col-xs-pull-9 { - right: 75%; -} -.col-xs-pull-8 { - right: 66.66666667%; -} -.col-xs-pull-7 { - right: 58.33333333%; -} -.col-xs-pull-6 { - right: 50%; -} -.col-xs-pull-5 { - right: 41.66666667%; -} -.col-xs-pull-4 { - right: 33.33333333%; -} -.col-xs-pull-3 { - right: 25%; -} -.col-xs-pull-2 { - right: 16.66666667%; -} -.col-xs-pull-1 { - right: 8.33333333%; -} -.col-xs-pull-0 { - right: auto; -} -.col-xs-push-12 { - left: 100%; -} -.col-xs-push-11 { - left: 91.66666667%; -} -.col-xs-push-10 { - left: 83.33333333%; -} -.col-xs-push-9 { - left: 75%; -} -.col-xs-push-8 { - left: 66.66666667%; -} -.col-xs-push-7 { - left: 58.33333333%; -} -.col-xs-push-6 { - left: 50%; -} -.col-xs-push-5 { - left: 41.66666667%; -} -.col-xs-push-4 { - left: 33.33333333%; -} -.col-xs-push-3 { - left: 25%; -} -.col-xs-push-2 { - left: 16.66666667%; -} -.col-xs-push-1 { - left: 8.33333333%; -} -.col-xs-push-0 { - left: auto; -} -.col-xs-offset-12 { - margin-left: 100%; -} -.col-xs-offset-11 { - margin-left: 91.66666667%; -} -.col-xs-offset-10 { - margin-left: 83.33333333%; -} -.col-xs-offset-9 { - margin-left: 75%; -} -.col-xs-offset-8 { - margin-left: 66.66666667%; -} -.col-xs-offset-7 { - margin-left: 58.33333333%; -} -.col-xs-offset-6 { - margin-left: 50%; -} -.col-xs-offset-5 { - margin-left: 41.66666667%; -} -.col-xs-offset-4 { - margin-left: 33.33333333%; -} -.col-xs-offset-3 { - margin-left: 25%; -} -.col-xs-offset-2 { - margin-left: 16.66666667%; -} -.col-xs-offset-1 { - margin-left: 8.33333333%; -} -.col-xs-offset-0 { - margin-left: 0; -} -@media (min-width: 768px) { - .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { - float: left; - } - .col-sm-12 { - width: 100%; - } - .col-sm-11 { - width: 91.66666667%; - } - .col-sm-10 { - width: 83.33333333%; - } - .col-sm-9 { - width: 75%; - } - .col-sm-8 { - width: 66.66666667%; - } - .col-sm-7 { - width: 58.33333333%; - } - .col-sm-6 { - width: 50%; - } - .col-sm-5 { - width: 41.66666667%; - } - .col-sm-4 { - width: 33.33333333%; - } - .col-sm-3 { - width: 25%; - } - .col-sm-2 { - width: 16.66666667%; - } - .col-sm-1 { - width: 8.33333333%; - } - .col-sm-pull-12 { - right: 100%; - } - .col-sm-pull-11 { - right: 91.66666667%; - } - .col-sm-pull-10 { - right: 83.33333333%; - } - .col-sm-pull-9 { - right: 75%; - } - .col-sm-pull-8 { - right: 66.66666667%; - } - .col-sm-pull-7 { - right: 58.33333333%; - } - .col-sm-pull-6 { - right: 50%; - } - .col-sm-pull-5 { - right: 41.66666667%; - } - .col-sm-pull-4 { - right: 33.33333333%; - } - .col-sm-pull-3 { - right: 25%; - } - .col-sm-pull-2 { - right: 16.66666667%; - } - .col-sm-pull-1 { - right: 8.33333333%; - } - .col-sm-pull-0 { - right: auto; - } - .col-sm-push-12 { - left: 100%; - } - .col-sm-push-11 { - left: 91.66666667%; - } - .col-sm-push-10 { - left: 83.33333333%; - } - .col-sm-push-9 { - left: 75%; - } - .col-sm-push-8 { - left: 66.66666667%; - } - .col-sm-push-7 { - left: 58.33333333%; - } - .col-sm-push-6 { - left: 50%; - } - .col-sm-push-5 { - left: 41.66666667%; - } - .col-sm-push-4 { - left: 33.33333333%; - } - .col-sm-push-3 { - left: 25%; - } - .col-sm-push-2 { - left: 16.66666667%; - } - .col-sm-push-1 { - left: 8.33333333%; - } - .col-sm-push-0 { - left: auto; - } - .col-sm-offset-12 { - margin-left: 100%; - } - .col-sm-offset-11 { - margin-left: 91.66666667%; - } - .col-sm-offset-10 { - margin-left: 83.33333333%; - } - .col-sm-offset-9 { - margin-left: 75%; - } - .col-sm-offset-8 { - margin-left: 66.66666667%; - } - .col-sm-offset-7 { - margin-left: 58.33333333%; - } - .col-sm-offset-6 { - margin-left: 50%; - } - .col-sm-offset-5 { - margin-left: 41.66666667%; - } - .col-sm-offset-4 { - margin-left: 33.33333333%; - } - .col-sm-offset-3 { - margin-left: 25%; - } - .col-sm-offset-2 { - margin-left: 16.66666667%; - } - .col-sm-offset-1 { - margin-left: 8.33333333%; - } - .col-sm-offset-0 { - margin-left: 0; - } -} -@media (min-width: 992px) { - .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { - float: left; - } - .col-md-12 { - width: 100%; - } - .col-md-11 { - width: 91.66666667%; - } - .col-md-10 { - width: 83.33333333%; - } - .col-md-9 { - width: 75%; - } - .col-md-8 { - width: 66.66666667%; - } - .col-md-7 { - width: 58.33333333%; - } - .col-md-6 { - width: 50%; - } - .col-md-5 { - width: 41.66666667%; - } - .col-md-4 { - width: 33.33333333%; - } - .col-md-3 { - width: 25%; - } - .col-md-2 { - width: 16.66666667%; - } - .col-md-1 { - width: 8.33333333%; - } - .col-md-pull-12 { - right: 100%; - } - .col-md-pull-11 { - right: 91.66666667%; - } - .col-md-pull-10 { - right: 83.33333333%; - } - .col-md-pull-9 { - right: 75%; - } - .col-md-pull-8 { - right: 66.66666667%; - } - .col-md-pull-7 { - right: 58.33333333%; - } - .col-md-pull-6 { - right: 50%; - } - .col-md-pull-5 { - right: 41.66666667%; - } - .col-md-pull-4 { - right: 33.33333333%; - } - .col-md-pull-3 { - right: 25%; - } - .col-md-pull-2 { - right: 16.66666667%; - } - .col-md-pull-1 { - right: 8.33333333%; - } - .col-md-pull-0 { - right: auto; - } - .col-md-push-12 { - left: 100%; - } - .col-md-push-11 { - left: 91.66666667%; - } - .col-md-push-10 { - left: 83.33333333%; - } - .col-md-push-9 { - left: 75%; - } - .col-md-push-8 { - left: 66.66666667%; - } - .col-md-push-7 { - left: 58.33333333%; - } - .col-md-push-6 { - left: 50%; - } - .col-md-push-5 { - left: 41.66666667%; - } - .col-md-push-4 { - left: 33.33333333%; - } - .col-md-push-3 { - left: 25%; - } - .col-md-push-2 { - left: 16.66666667%; - } - .col-md-push-1 { - left: 8.33333333%; - } - .col-md-push-0 { - left: auto; - } - .col-md-offset-12 { - margin-left: 100%; - } - .col-md-offset-11 { - margin-left: 91.66666667%; - } - .col-md-offset-10 { - margin-left: 83.33333333%; - } - .col-md-offset-9 { - margin-left: 75%; - } - .col-md-offset-8 { - margin-left: 66.66666667%; - } - .col-md-offset-7 { - margin-left: 58.33333333%; - } - .col-md-offset-6 { - margin-left: 50%; - } - .col-md-offset-5 { - margin-left: 41.66666667%; - } - .col-md-offset-4 { - margin-left: 33.33333333%; - } - .col-md-offset-3 { - margin-left: 25%; - } - .col-md-offset-2 { - margin-left: 16.66666667%; - } - .col-md-offset-1 { - margin-left: 8.33333333%; - } - .col-md-offset-0 { - margin-left: 0; - } -} -@media (min-width: 1200px) { - .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { - float: left; - } - .col-lg-12 { - width: 100%; - } - .col-lg-11 { - width: 91.66666667%; - } - .col-lg-10 { - width: 83.33333333%; - } - .col-lg-9 { - width: 75%; - } - .col-lg-8 { - width: 66.66666667%; - } - .col-lg-7 { - width: 58.33333333%; - } - .col-lg-6 { - width: 50%; - } - .col-lg-5 { - width: 41.66666667%; - } - .col-lg-4 { - width: 33.33333333%; - } - .col-lg-3 { - width: 25%; - } - .col-lg-2 { - width: 16.66666667%; - } - .col-lg-1 { - width: 8.33333333%; - } - .col-lg-pull-12 { - right: 100%; - } - .col-lg-pull-11 { - right: 91.66666667%; - } - .col-lg-pull-10 { - right: 83.33333333%; - } - .col-lg-pull-9 { - right: 75%; - } - .col-lg-pull-8 { - right: 66.66666667%; - } - .col-lg-pull-7 { - right: 58.33333333%; - } - .col-lg-pull-6 { - right: 50%; - } - .col-lg-pull-5 { - right: 41.66666667%; - } - .col-lg-pull-4 { - right: 33.33333333%; - } - .col-lg-pull-3 { - right: 25%; - } - .col-lg-pull-2 { - right: 16.66666667%; - } - .col-lg-pull-1 { - right: 8.33333333%; - } - .col-lg-pull-0 { - right: auto; - } - .col-lg-push-12 { - left: 100%; - } - .col-lg-push-11 { - left: 91.66666667%; - } - .col-lg-push-10 { - left: 83.33333333%; - } - .col-lg-push-9 { - left: 75%; - } - .col-lg-push-8 { - left: 66.66666667%; - } - .col-lg-push-7 { - left: 58.33333333%; - } - .col-lg-push-6 { - left: 50%; - } - .col-lg-push-5 { - left: 41.66666667%; - } - .col-lg-push-4 { - left: 33.33333333%; - } - .col-lg-push-3 { - left: 25%; - } - .col-lg-push-2 { - left: 16.66666667%; - } - .col-lg-push-1 { - left: 8.33333333%; - } - .col-lg-push-0 { - left: auto; - } - .col-lg-offset-12 { - margin-left: 100%; - } - .col-lg-offset-11 { - margin-left: 91.66666667%; - } - .col-lg-offset-10 { - margin-left: 83.33333333%; - } - .col-lg-offset-9 { - margin-left: 75%; - } - .col-lg-offset-8 { - margin-left: 66.66666667%; - } - .col-lg-offset-7 { - margin-left: 58.33333333%; - } - .col-lg-offset-6 { - margin-left: 50%; - } - .col-lg-offset-5 { - margin-left: 41.66666667%; - } - .col-lg-offset-4 { - margin-left: 33.33333333%; - } - .col-lg-offset-3 { - margin-left: 25%; - } - .col-lg-offset-2 { - margin-left: 16.66666667%; - } - .col-lg-offset-1 { - margin-left: 8.33333333%; - } - .col-lg-offset-0 { - margin-left: 0; - } -} -table { - background-color: transparent; -} -caption { - padding-top: 8px; - padding-bottom: 8px; - color: #777; - text-align: left; -} -th { - text-align: left; -} -.table { - width: 100%; - max-width: 100%; - margin-bottom: 20px; -} -.table > thead > tr > th, -.table > tbody > tr > th, -.table > tfoot > tr > th, -.table > thead > tr > td, -.table > tbody > tr > td, -.table > tfoot > tr > td { - padding: 8px; - line-height: 1.42857143; - vertical-align: top; - border-top: 1px solid #ddd; -} -.table > thead > tr > th { - vertical-align: bottom; - border-bottom: 2px solid #ddd; -} -.table > caption + thead > tr:first-child > th, -.table > colgroup + thead > tr:first-child > th, -.table > thead:first-child > tr:first-child > th, -.table > caption + thead > tr:first-child > td, -.table > colgroup + thead > tr:first-child > td, -.table > thead:first-child > tr:first-child > td { - border-top: 0; -} -.table > tbody + tbody { - border-top: 2px solid #ddd; -} -.table .table { - background-color: #fff; -} -.table-condensed > thead > tr > th, -.table-condensed > tbody > tr > th, -.table-condensed > tfoot > tr > th, -.table-condensed > thead > tr > td, -.table-condensed > tbody > tr > td, -.table-condensed > tfoot > tr > td { - padding: 5px; -} -.table-bordered { - border: 1px solid #ddd; -} -.table-bordered > thead > tr > th, -.table-bordered > tbody > tr > th, -.table-bordered > tfoot > tr > th, -.table-bordered > thead > tr > td, -.table-bordered > tbody > tr > td, -.table-bordered > tfoot > tr > td { - border: 1px solid #ddd; -} -.table-bordered > thead > tr > th, -.table-bordered > thead > tr > td { - border-bottom-width: 2px; -} -.table-striped > tbody > tr:nth-of-type(odd) { - background-color: #f9f9f9; -} -.table-hover > tbody > tr:hover { - background-color: #f5f5f5; -} -table col[class*="col-"] { - position: static; - display: table-column; - float: none; -} -table td[class*="col-"], -table th[class*="col-"] { - position: static; - display: table-cell; - float: none; -} -.table > thead > tr > td.active, -.table > tbody > tr > td.active, -.table > tfoot > tr > td.active, -.table > thead > tr > th.active, -.table > tbody > tr > th.active, -.table > tfoot > tr > th.active, -.table > thead > tr.active > td, -.table > tbody > tr.active > td, -.table > tfoot > tr.active > td, -.table > thead > tr.active > th, -.table > tbody > tr.active > th, -.table > tfoot > tr.active > th { - background-color: #f5f5f5; -} -.table-hover > tbody > tr > td.active:hover, -.table-hover > tbody > tr > th.active:hover, -.table-hover > tbody > tr.active:hover > td, -.table-hover > tbody > tr:hover > .active, -.table-hover > tbody > tr.active:hover > th { - background-color: #e8e8e8; -} -.table > thead > tr > td.success, -.table > tbody > tr > td.success, -.table > tfoot > tr > td.success, -.table > thead > tr > th.success, -.table > tbody > tr > th.success, -.table > tfoot > tr > th.success, -.table > thead > tr.success > td, -.table > tbody > tr.success > td, -.table > tfoot > tr.success > td, -.table > thead > tr.success > th, -.table > tbody > tr.success > th, -.table > tfoot > tr.success > th { - background-color: #dff0d8; -} -.table-hover > tbody > tr > td.success:hover, -.table-hover > tbody > tr > th.success:hover, -.table-hover > tbody > tr.success:hover > td, -.table-hover > tbody > tr:hover > .success, -.table-hover > tbody > tr.success:hover > th { - background-color: #d0e9c6; -} -.table > thead > tr > td.info, -.table > tbody > tr > td.info, -.table > tfoot > tr > td.info, -.table > thead > tr > th.info, -.table > tbody > tr > th.info, -.table > tfoot > tr > th.info, -.table > thead > tr.info > td, -.table > tbody > tr.info > td, -.table > tfoot > tr.info > td, -.table > thead > tr.info > th, -.table > tbody > tr.info > th, -.table > tfoot > tr.info > th { - background-color: #d9edf7; -} -.table-hover > tbody > tr > td.info:hover, -.table-hover > tbody > tr > th.info:hover, -.table-hover > tbody > tr.info:hover > td, -.table-hover > tbody > tr:hover > .info, -.table-hover > tbody > tr.info:hover > th { - background-color: #c4e3f3; -} -.table > thead > tr > td.warning, -.table > tbody > tr > td.warning, -.table > tfoot > tr > td.warning, -.table > thead > tr > th.warning, -.table > tbody > tr > th.warning, -.table > tfoot > tr > th.warning, -.table > thead > tr.warning > td, -.table > tbody > tr.warning > td, -.table > tfoot > tr.warning > td, -.table > thead > tr.warning > th, -.table > tbody > tr.warning > th, -.table > tfoot > tr.warning > th { - background-color: #fcf8e3; -} -.table-hover > tbody > tr > td.warning:hover, -.table-hover > tbody > tr > th.warning:hover, -.table-hover > tbody > tr.warning:hover > td, -.table-hover > tbody > tr:hover > .warning, -.table-hover > tbody > tr.warning:hover > th { - background-color: #faf2cc; -} -.table > thead > tr > td.danger, -.table > tbody > tr > td.danger, -.table > tfoot > tr > td.danger, -.table > thead > tr > th.danger, -.table > tbody > tr > th.danger, -.table > tfoot > tr > th.danger, -.table > thead > tr.danger > td, -.table > tbody > tr.danger > td, -.table > tfoot > tr.danger > td, -.table > thead > tr.danger > th, -.table > tbody > tr.danger > th, -.table > tfoot > tr.danger > th { - background-color: #f2dede; -} -.table-hover > tbody > tr > td.danger:hover, -.table-hover > tbody > tr > th.danger:hover, -.table-hover > tbody > tr.danger:hover > td, -.table-hover > tbody > tr:hover > .danger, -.table-hover > tbody > tr.danger:hover > th { - background-color: #ebcccc; -} -.table-responsive { - min-height: .01%; - overflow-x: auto; -} -@media screen and (max-width: 767px) { - .table-responsive { - width: 100%; - margin-bottom: 15px; - overflow-y: hidden; - -ms-overflow-style: -ms-autohiding-scrollbar; - border: 1px solid #ddd; - } - .table-responsive > .table { - margin-bottom: 0; - } - .table-responsive > .table > thead > tr > th, - .table-responsive > .table > tbody > tr > th, - .table-responsive > .table > tfoot > tr > th, - .table-responsive > .table > thead > tr > td, - .table-responsive > .table > tbody > tr > td, - .table-responsive > .table > tfoot > tr > td { - white-space: nowrap; - } - .table-responsive > .table-bordered { - border: 0; - } - .table-responsive > .table-bordered > thead > tr > th:first-child, - .table-responsive > .table-bordered > tbody > tr > th:first-child, - .table-responsive > .table-bordered > tfoot > tr > th:first-child, - .table-responsive > .table-bordered > thead > tr > td:first-child, - .table-responsive > .table-bordered > tbody > tr > td:first-child, - .table-responsive > .table-bordered > tfoot > tr > td:first-child { - border-left: 0; - } - .table-responsive > .table-bordered > thead > tr > th:last-child, - .table-responsive > .table-bordered > tbody > tr > th:last-child, - .table-responsive > .table-bordered > tfoot > tr > th:last-child, - .table-responsive > .table-bordered > thead > tr > td:last-child, - .table-responsive > .table-bordered > tbody > tr > td:last-child, - .table-responsive > .table-bordered > tfoot > tr > td:last-child { - border-right: 0; - } - .table-responsive > .table-bordered > tbody > tr:last-child > th, - .table-responsive > .table-bordered > tfoot > tr:last-child > th, - .table-responsive > .table-bordered > tbody > tr:last-child > td, - .table-responsive > .table-bordered > tfoot > tr:last-child > td { - border-bottom: 0; - } -} -fieldset { - min-width: 0; - padding: 0; - margin: 0; - border: 0; -} -legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 20px; - font-size: 21px; - line-height: inherit; - color: #333; - border: 0; - border-bottom: 1px solid #e5e5e5; -} -label { - display: inline-block; - max-width: 100%; - margin-bottom: 5px; - font-weight: bold; -} -input[type="search"] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; -} -input[type="radio"], -input[type="checkbox"] { - margin: 4px 0 0; - margin-top: 1px \9; - line-height: normal; -} -input[type="file"] { - display: block; -} -input[type="range"] { - display: block; - width: 100%; -} -select[multiple], -select[size] { - height: auto; -} -input[type="file"]:focus, -input[type="radio"]:focus, -input[type="checkbox"]:focus { - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -output { - display: block; - padding-top: 7px; - font-size: 14px; - line-height: 1.42857143; - color: #555; -} -.form-control { - display: block; - width: 100%; - height: 34px; - padding: 6px 12px; - font-size: 14px; - line-height: 1.42857143; - color: #555; - background-color: #fff; - background-image: none; - border: 1px solid #ccc; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; - -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; - transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; -} -.form-control:focus { - border-color: #66afe9; - outline: 0; - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); - box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); -} -.form-control::-moz-placeholder { - color: #999; - opacity: 1; -} -.form-control:-ms-input-placeholder { - color: #999; -} -.form-control::-webkit-input-placeholder { - color: #999; -} -.form-control::-ms-expand { - background-color: transparent; - border: 0; -} -.form-control[disabled], -.form-control[readonly], -fieldset[disabled] .form-control { - background-color: #eee; - opacity: 1; -} -.form-control[disabled], -fieldset[disabled] .form-control { - cursor: not-allowed; -} -textarea.form-control { - height: auto; -} -input[type="search"] { - -webkit-appearance: none; -} -@media screen and (-webkit-min-device-pixel-ratio: 0) { - input[type="date"].form-control, - input[type="time"].form-control, - input[type="datetime-local"].form-control, - input[type="month"].form-control { - line-height: 34px; - } - input[type="date"].input-sm, - input[type="time"].input-sm, - input[type="datetime-local"].input-sm, - input[type="month"].input-sm, - .input-group-sm input[type="date"], - .input-group-sm input[type="time"], - .input-group-sm input[type="datetime-local"], - .input-group-sm input[type="month"] { - line-height: 30px; - } - input[type="date"].input-lg, - input[type="time"].input-lg, - input[type="datetime-local"].input-lg, - input[type="month"].input-lg, - .input-group-lg input[type="date"], - .input-group-lg input[type="time"], - .input-group-lg input[type="datetime-local"], - .input-group-lg input[type="month"] { - line-height: 46px; - } -} -.form-group { - margin-bottom: 15px; -} -.radio, -.checkbox { - position: relative; - display: block; - margin-top: 10px; - margin-bottom: 10px; -} -.radio label, -.checkbox label { - min-height: 20px; - padding-left: 20px; - margin-bottom: 0; - font-weight: normal; - cursor: pointer; -} -.radio input[type="radio"], -.radio-inline input[type="radio"], -.checkbox input[type="checkbox"], -.checkbox-inline input[type="checkbox"] { - position: absolute; - margin-top: 4px \9; - margin-left: -20px; -} -.radio + .radio, -.checkbox + .checkbox { - margin-top: -5px; -} -.radio-inline, -.checkbox-inline { - position: relative; - display: inline-block; - padding-left: 20px; - margin-bottom: 0; - font-weight: normal; - vertical-align: middle; - cursor: pointer; -} -.radio-inline + .radio-inline, -.checkbox-inline + .checkbox-inline { - margin-top: 0; - margin-left: 10px; -} -input[type="radio"][disabled], -input[type="checkbox"][disabled], -input[type="radio"].disabled, -input[type="checkbox"].disabled, -fieldset[disabled] input[type="radio"], -fieldset[disabled] input[type="checkbox"] { - cursor: not-allowed; -} -.radio-inline.disabled, -.checkbox-inline.disabled, -fieldset[disabled] .radio-inline, -fieldset[disabled] .checkbox-inline { - cursor: not-allowed; -} -.radio.disabled label, -.checkbox.disabled label, -fieldset[disabled] .radio label, -fieldset[disabled] .checkbox label { - cursor: not-allowed; -} -.form-control-static { - min-height: 34px; - padding-top: 7px; - padding-bottom: 7px; - margin-bottom: 0; -} -.form-control-static.input-lg, -.form-control-static.input-sm { - padding-right: 0; - padding-left: 0; -} -.input-sm { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -select.input-sm { - height: 30px; - line-height: 30px; -} -textarea.input-sm, -select[multiple].input-sm { - height: auto; -} -.form-group-sm .form-control { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -.form-group-sm select.form-control { - height: 30px; - line-height: 30px; -} -.form-group-sm textarea.form-control, -.form-group-sm select[multiple].form-control { - height: auto; -} -.form-group-sm .form-control-static { - height: 30px; - min-height: 32px; - padding: 6px 10px; - font-size: 12px; - line-height: 1.5; -} -.input-lg { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} -select.input-lg { - height: 46px; - line-height: 46px; -} -textarea.input-lg, -select[multiple].input-lg { - height: auto; -} -.form-group-lg .form-control { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} -.form-group-lg select.form-control { - height: 46px; - line-height: 46px; -} -.form-group-lg textarea.form-control, -.form-group-lg select[multiple].form-control { - height: auto; -} -.form-group-lg .form-control-static { - height: 46px; - min-height: 38px; - padding: 11px 16px; - font-size: 18px; - line-height: 1.3333333; -} -.has-feedback { - position: relative; -} -.has-feedback .form-control { - padding-right: 42.5px; -} -.form-control-feedback { - position: absolute; - top: 0; - right: 0; - z-index: 2; - display: block; - width: 34px; - height: 34px; - line-height: 34px; - text-align: center; - pointer-events: none; -} -.input-lg + .form-control-feedback, -.input-group-lg + .form-control-feedback, -.form-group-lg .form-control + .form-control-feedback { - width: 46px; - height: 46px; - line-height: 46px; -} -.input-sm + .form-control-feedback, -.input-group-sm + .form-control-feedback, -.form-group-sm .form-control + .form-control-feedback { - width: 30px; - height: 30px; - line-height: 30px; -} -.has-success .help-block, -.has-success .control-label, -.has-success .radio, -.has-success .checkbox, -.has-success .radio-inline, -.has-success .checkbox-inline, -.has-success.radio label, -.has-success.checkbox label, -.has-success.radio-inline label, -.has-success.checkbox-inline label { - color: #3c763d; -} -.has-success .form-control { - border-color: #3c763d; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); -} -.has-success .form-control:focus { - border-color: #2b542c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; -} -.has-success .input-group-addon { - color: #3c763d; - background-color: #dff0d8; - border-color: #3c763d; -} -.has-success .form-control-feedback { - color: #3c763d; -} -.has-warning .help-block, -.has-warning .control-label, -.has-warning .radio, -.has-warning .checkbox, -.has-warning .radio-inline, -.has-warning .checkbox-inline, -.has-warning.radio label, -.has-warning.checkbox label, -.has-warning.radio-inline label, -.has-warning.checkbox-inline label { - color: #8a6d3b; -} -.has-warning .form-control { - border-color: #8a6d3b; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); -} -.has-warning .form-control:focus { - border-color: #66512c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; -} -.has-warning .input-group-addon { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #8a6d3b; -} -.has-warning .form-control-feedback { - color: #8a6d3b; -} -.has-error .help-block, -.has-error .control-label, -.has-error .radio, -.has-error .checkbox, -.has-error .radio-inline, -.has-error .checkbox-inline, -.has-error.radio label, -.has-error.checkbox label, -.has-error.radio-inline label, -.has-error.checkbox-inline label { - color: #a94442; -} -.has-error .form-control { - border-color: #a94442; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); -} -.has-error .form-control:focus { - border-color: #843534; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; -} -.has-error .input-group-addon { - color: #a94442; - background-color: #f2dede; - border-color: #a94442; -} -.has-error .form-control-feedback { - color: #a94442; -} -.has-feedback label ~ .form-control-feedback { - top: 25px; -} -.has-feedback label.sr-only ~ .form-control-feedback { - top: 0; -} -.help-block { - display: block; - margin-top: 5px; - margin-bottom: 10px; - color: #737373; -} -@media (min-width: 768px) { - .form-inline .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .form-control { - display: inline-block; - width: auto; - vertical-align: middle; - } - .form-inline .form-control-static { - display: inline-block; - } - .form-inline .input-group { - display: inline-table; - vertical-align: middle; - } - .form-inline .input-group .input-group-addon, - .form-inline .input-group .input-group-btn, - .form-inline .input-group .form-control { - width: auto; - } - .form-inline .input-group > .form-control { - width: 100%; - } - .form-inline .control-label { - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .radio, - .form-inline .checkbox { - display: inline-block; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .radio label, - .form-inline .checkbox label { - padding-left: 0; - } - .form-inline .radio input[type="radio"], - .form-inline .checkbox input[type="checkbox"] { - position: relative; - margin-left: 0; - } - .form-inline .has-feedback .form-control-feedback { - top: 0; - } -} -.form-horizontal .radio, -.form-horizontal .checkbox, -.form-horizontal .radio-inline, -.form-horizontal .checkbox-inline { - padding-top: 7px; - margin-top: 0; - margin-bottom: 0; -} -.form-horizontal .radio, -.form-horizontal .checkbox { - min-height: 27px; -} -.form-horizontal .form-group { - margin-right: -15px; - margin-left: -15px; -} -@media (min-width: 768px) { - .form-horizontal .control-label { - padding-top: 7px; - margin-bottom: 0; - text-align: right; - } -} -.form-horizontal .has-feedback .form-control-feedback { - right: 15px; -} -@media (min-width: 768px) { - .form-horizontal .form-group-lg .control-label { - padding-top: 11px; - font-size: 18px; - } -} -@media (min-width: 768px) { - .form-horizontal .form-group-sm .control-label { - padding-top: 6px; - font-size: 12px; - } -} -.btn { - display: inline-block; - padding: 6px 12px; - margin-bottom: 0; - font-size: 14px; - font-weight: normal; - line-height: 1.42857143; - text-align: center; - white-space: nowrap; - vertical-align: middle; - -ms-touch-action: manipulation; - touch-action: manipulation; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-image: none; - border: 1px solid transparent; - border-radius: 4px; -} -.btn:focus, -.btn:active:focus, -.btn.active:focus, -.btn.focus, -.btn:active.focus, -.btn.active.focus { - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; -} -.btn:hover, -.btn:focus, -.btn.focus { - color: #333; - text-decoration: none; -} -.btn:active, -.btn.active { - background-image: none; - outline: 0; - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); -} -.btn.disabled, -.btn[disabled], -fieldset[disabled] .btn { - cursor: not-allowed; - filter: alpha(opacity=65); - -webkit-box-shadow: none; - box-shadow: none; - opacity: .65; -} -a.btn.disabled, -fieldset[disabled] a.btn { - pointer-events: none; -} -.btn-default { - color: #333; - background-color: #fff; - border-color: #ccc; -} -.btn-default:focus, -.btn-default.focus { - color: #333; - background-color: #e6e6e6; - border-color: #8c8c8c; -} -.btn-default:hover { - color: #333; - background-color: #e6e6e6; - border-color: #adadad; -} -.btn-default:active, -.btn-default.active, -.open > .dropdown-toggle.btn-default { - color: #333; - background-color: #e6e6e6; - border-color: #adadad; -} -.btn-default:active:hover, -.btn-default.active:hover, -.open > .dropdown-toggle.btn-default:hover, -.btn-default:active:focus, -.btn-default.active:focus, -.open > .dropdown-toggle.btn-default:focus, -.btn-default:active.focus, -.btn-default.active.focus, -.open > .dropdown-toggle.btn-default.focus { - color: #333; - background-color: #d4d4d4; - border-color: #8c8c8c; -} -.btn-default:active, -.btn-default.active, -.open > .dropdown-toggle.btn-default { - background-image: none; -} -.btn-default.disabled:hover, -.btn-default[disabled]:hover, -fieldset[disabled] .btn-default:hover, -.btn-default.disabled:focus, -.btn-default[disabled]:focus, -fieldset[disabled] .btn-default:focus, -.btn-default.disabled.focus, -.btn-default[disabled].focus, -fieldset[disabled] .btn-default.focus { - background-color: #fff; - border-color: #ccc; -} -.btn-default .badge { - color: #fff; - background-color: #333; -} -.btn-primary { - color: #fff; - background-color: #337ab7; - border-color: #2e6da4; -} -.btn-primary:focus, -.btn-primary.focus { - color: #fff; - background-color: #286090; - border-color: #122b40; -} -.btn-primary:hover { - color: #fff; - background-color: #286090; - border-color: #204d74; -} -.btn-primary:active, -.btn-primary.active, -.open > .dropdown-toggle.btn-primary { - color: #fff; - background-color: #286090; - border-color: #204d74; -} -.btn-primary:active:hover, -.btn-primary.active:hover, -.open > .dropdown-toggle.btn-primary:hover, -.btn-primary:active:focus, -.btn-primary.active:focus, -.open > .dropdown-toggle.btn-primary:focus, -.btn-primary:active.focus, -.btn-primary.active.focus, -.open > .dropdown-toggle.btn-primary.focus { - color: #fff; - background-color: #204d74; - border-color: #122b40; -} -.btn-primary:active, -.btn-primary.active, -.open > .dropdown-toggle.btn-primary { - background-image: none; -} -.btn-primary.disabled:hover, -.btn-primary[disabled]:hover, -fieldset[disabled] .btn-primary:hover, -.btn-primary.disabled:focus, -.btn-primary[disabled]:focus, -fieldset[disabled] .btn-primary:focus, -.btn-primary.disabled.focus, -.btn-primary[disabled].focus, -fieldset[disabled] .btn-primary.focus { - background-color: #337ab7; - border-color: #2e6da4; -} -.btn-primary .badge { - color: #337ab7; - background-color: #fff; -} -.btn-success { - color: #fff; - background-color: #5cb85c; - border-color: #4cae4c; -} -.btn-success:focus, -.btn-success.focus { - color: #fff; - background-color: #449d44; - border-color: #255625; -} -.btn-success:hover { - color: #fff; - background-color: #449d44; - border-color: #398439; -} -.btn-success:active, -.btn-success.active, -.open > .dropdown-toggle.btn-success { - color: #fff; - background-color: #449d44; - border-color: #398439; -} -.btn-success:active:hover, -.btn-success.active:hover, -.open > .dropdown-toggle.btn-success:hover, -.btn-success:active:focus, -.btn-success.active:focus, -.open > .dropdown-toggle.btn-success:focus, -.btn-success:active.focus, -.btn-success.active.focus, -.open > .dropdown-toggle.btn-success.focus { - color: #fff; - background-color: #398439; - border-color: #255625; -} -.btn-success:active, -.btn-success.active, -.open > .dropdown-toggle.btn-success { - background-image: none; -} -.btn-success.disabled:hover, -.btn-success[disabled]:hover, -fieldset[disabled] .btn-success:hover, -.btn-success.disabled:focus, -.btn-success[disabled]:focus, -fieldset[disabled] .btn-success:focus, -.btn-success.disabled.focus, -.btn-success[disabled].focus, -fieldset[disabled] .btn-success.focus { - background-color: #5cb85c; - border-color: #4cae4c; -} -.btn-success .badge { - color: #5cb85c; - background-color: #fff; -} -.btn-info { - color: #fff; - background-color: #5bc0de; - border-color: #46b8da; -} -.btn-info:focus, -.btn-info.focus { - color: #fff; - background-color: #31b0d5; - border-color: #1b6d85; -} -.btn-info:hover { - color: #fff; - background-color: #31b0d5; - border-color: #269abc; -} -.btn-info:active, -.btn-info.active, -.open > .dropdown-toggle.btn-info { - color: #fff; - background-color: #31b0d5; - border-color: #269abc; -} -.btn-info:active:hover, -.btn-info.active:hover, -.open > .dropdown-toggle.btn-info:hover, -.btn-info:active:focus, -.btn-info.active:focus, -.open > .dropdown-toggle.btn-info:focus, -.btn-info:active.focus, -.btn-info.active.focus, -.open > .dropdown-toggle.btn-info.focus { - color: #fff; - background-color: #269abc; - border-color: #1b6d85; -} -.btn-info:active, -.btn-info.active, -.open > .dropdown-toggle.btn-info { - background-image: none; -} -.btn-info.disabled:hover, -.btn-info[disabled]:hover, -fieldset[disabled] .btn-info:hover, -.btn-info.disabled:focus, -.btn-info[disabled]:focus, -fieldset[disabled] .btn-info:focus, -.btn-info.disabled.focus, -.btn-info[disabled].focus, -fieldset[disabled] .btn-info.focus { - background-color: #5bc0de; - border-color: #46b8da; -} -.btn-info .badge { - color: #5bc0de; - background-color: #fff; -} -.btn-warning { - color: #fff; - background-color: #f0ad4e; - border-color: #eea236; -} -.btn-warning:focus, -.btn-warning.focus { - color: #fff; - background-color: #ec971f; - border-color: #985f0d; -} -.btn-warning:hover { - color: #fff; - background-color: #ec971f; - border-color: #d58512; -} -.btn-warning:active, -.btn-warning.active, -.open > .dropdown-toggle.btn-warning { - color: #fff; - background-color: #ec971f; - border-color: #d58512; -} -.btn-warning:active:hover, -.btn-warning.active:hover, -.open > .dropdown-toggle.btn-warning:hover, -.btn-warning:active:focus, -.btn-warning.active:focus, -.open > .dropdown-toggle.btn-warning:focus, -.btn-warning:active.focus, -.btn-warning.active.focus, -.open > .dropdown-toggle.btn-warning.focus { - color: #fff; - background-color: #d58512; - border-color: #985f0d; -} -.btn-warning:active, -.btn-warning.active, -.open > .dropdown-toggle.btn-warning { - background-image: none; -} -.btn-warning.disabled:hover, -.btn-warning[disabled]:hover, -fieldset[disabled] .btn-warning:hover, -.btn-warning.disabled:focus, -.btn-warning[disabled]:focus, -fieldset[disabled] .btn-warning:focus, -.btn-warning.disabled.focus, -.btn-warning[disabled].focus, -fieldset[disabled] .btn-warning.focus { - background-color: #f0ad4e; - border-color: #eea236; -} -.btn-warning .badge { - color: #f0ad4e; - background-color: #fff; -} -.btn-danger { - color: #fff; - background-color: #d9534f; - border-color: #d43f3a; -} -.btn-danger:focus, -.btn-danger.focus { - color: #fff; - background-color: #c9302c; - border-color: #761c19; -} -.btn-danger:hover { - color: #fff; - background-color: #c9302c; - border-color: #ac2925; -} -.btn-danger:active, -.btn-danger.active, -.open > .dropdown-toggle.btn-danger { - color: #fff; - background-color: #c9302c; - border-color: #ac2925; -} -.btn-danger:active:hover, -.btn-danger.active:hover, -.open > .dropdown-toggle.btn-danger:hover, -.btn-danger:active:focus, -.btn-danger.active:focus, -.open > .dropdown-toggle.btn-danger:focus, -.btn-danger:active.focus, -.btn-danger.active.focus, -.open > .dropdown-toggle.btn-danger.focus { - color: #fff; - background-color: #ac2925; - border-color: #761c19; -} -.btn-danger:active, -.btn-danger.active, -.open > .dropdown-toggle.btn-danger { - background-image: none; -} -.btn-danger.disabled:hover, -.btn-danger[disabled]:hover, -fieldset[disabled] .btn-danger:hover, -.btn-danger.disabled:focus, -.btn-danger[disabled]:focus, -fieldset[disabled] .btn-danger:focus, -.btn-danger.disabled.focus, -.btn-danger[disabled].focus, -fieldset[disabled] .btn-danger.focus { - background-color: #d9534f; - border-color: #d43f3a; -} -.btn-danger .badge { - color: #d9534f; - background-color: #fff; -} -.btn-link { - font-weight: normal; - color: #337ab7; - border-radius: 0; -} -.btn-link, -.btn-link:active, -.btn-link.active, -.btn-link[disabled], -fieldset[disabled] .btn-link { - background-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; -} -.btn-link, -.btn-link:hover, -.btn-link:focus, -.btn-link:active { - border-color: transparent; -} -.btn-link:hover, -.btn-link:focus { - color: #23527c; - text-decoration: underline; - background-color: transparent; -} -.btn-link[disabled]:hover, -fieldset[disabled] .btn-link:hover, -.btn-link[disabled]:focus, -fieldset[disabled] .btn-link:focus { - color: #777; - text-decoration: none; -} -.btn-lg, -.btn-group-lg > .btn { - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} -.btn-sm, -.btn-group-sm > .btn { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -.btn-xs, -.btn-group-xs > .btn { - padding: 1px 5px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -.btn-block { - display: block; - width: 100%; -} -.btn-block + .btn-block { - margin-top: 5px; -} -input[type="submit"].btn-block, -input[type="reset"].btn-block, -input[type="button"].btn-block { - width: 100%; -} -.fade { - opacity: 0; - -webkit-transition: opacity .15s linear; - -o-transition: opacity .15s linear; - transition: opacity .15s linear; -} -.fade.in { - opacity: 1; -} -.collapse { - display: none; -} -.collapse.in { - display: block; -} -tr.collapse.in { - display: table-row; -} -tbody.collapse.in { - display: table-row-group; -} -.collapsing { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition-timing-function: ease; - -o-transition-timing-function: ease; - transition-timing-function: ease; - -webkit-transition-duration: .35s; - -o-transition-duration: .35s; - transition-duration: .35s; - -webkit-transition-property: height, visibility; - -o-transition-property: height, visibility; - transition-property: height, visibility; -} -.caret { - display: inline-block; - width: 0; - height: 0; - margin-left: 2px; - vertical-align: middle; - border-top: 4px dashed; - border-top: 4px solid \9; - border-right: 4px solid transparent; - border-left: 4px solid transparent; -} -.dropup, -.dropdown { - position: relative; -} -.dropdown-toggle:focus { - outline: 0; -} -.dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - font-size: 14px; - text-align: left; - list-style: none; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .15); - border-radius: 4px; - -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); - box-shadow: 0 6px 12px rgba(0, 0, 0, .175); -} -.dropdown-menu.pull-right { - right: 0; - left: auto; -} -.dropdown-menu .divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; -} -.dropdown-menu > li > a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: normal; - line-height: 1.42857143; - color: #333; - white-space: nowrap; -} -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus { - color: #262626; - text-decoration: none; - background-color: #f5f5f5; -} -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - color: #fff; - text-decoration: none; - background-color: #337ab7; - outline: 0; -} -.dropdown-menu > .disabled > a, -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - color: #777; -} -.dropdown-menu > .disabled > a:hover, -.dropdown-menu > .disabled > a:focus { - text-decoration: none; - cursor: not-allowed; - background-color: transparent; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); -} -.open > .dropdown-menu { - display: block; -} -.open > a { - outline: 0; -} -.dropdown-menu-right { - right: 0; - left: auto; -} -.dropdown-menu-left { - right: auto; - left: 0; -} -.dropdown-header { - display: block; - padding: 3px 20px; - font-size: 12px; - line-height: 1.42857143; - color: #777; - white-space: nowrap; -} -.dropdown-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 990; -} -.pull-right > .dropdown-menu { - right: 0; - left: auto; -} -.dropup .caret, -.navbar-fixed-bottom .dropdown .caret { - content: ""; - border-top: 0; - border-bottom: 4px dashed; - border-bottom: 4px solid \9; -} -.dropup .dropdown-menu, -.navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 2px; -} -@media (min-width: 768px) { - .navbar-right .dropdown-menu { - right: 0; - left: auto; - } - .navbar-right .dropdown-menu-left { - right: auto; - left: 0; - } -} -.btn-group, -.btn-group-vertical { - position: relative; - display: inline-block; - vertical-align: middle; -} -.btn-group > .btn, -.btn-group-vertical > .btn { - position: relative; - float: left; -} -.btn-group > .btn:hover, -.btn-group-vertical > .btn:hover, -.btn-group > .btn:focus, -.btn-group-vertical > .btn:focus, -.btn-group > .btn:active, -.btn-group-vertical > .btn:active, -.btn-group > .btn.active, -.btn-group-vertical > .btn.active { - z-index: 2; -} -.btn-group .btn + .btn, -.btn-group .btn + .btn-group, -.btn-group .btn-group + .btn, -.btn-group .btn-group + .btn-group { - margin-left: -1px; -} -.btn-toolbar { - margin-left: -5px; -} -.btn-toolbar .btn, -.btn-toolbar .btn-group, -.btn-toolbar .input-group { - float: left; -} -.btn-toolbar > .btn, -.btn-toolbar > .btn-group, -.btn-toolbar > .input-group { - margin-left: 5px; -} -.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { - border-radius: 0; -} -.btn-group > .btn:first-child { - margin-left: 0; -} -.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.btn-group > .btn:last-child:not(:first-child), -.btn-group > .dropdown-toggle:not(:first-child) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group > .btn-group { - float: left; -} -.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; -} -.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, -.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group .dropdown-toggle:active, -.btn-group.open .dropdown-toggle { - outline: 0; -} -.btn-group > .btn + .dropdown-toggle { - padding-right: 8px; - padding-left: 8px; -} -.btn-group > .btn-lg + .dropdown-toggle { - padding-right: 12px; - padding-left: 12px; -} -.btn-group.open .dropdown-toggle { - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); -} -.btn-group.open .dropdown-toggle.btn-link { - -webkit-box-shadow: none; - box-shadow: none; -} -.btn .caret { - margin-left: 0; -} -.btn-lg .caret { - border-width: 5px 5px 0; - border-bottom-width: 0; -} -.dropup .btn-lg .caret { - border-width: 0 5px 5px; -} -.btn-group-vertical > .btn, -.btn-group-vertical > .btn-group, -.btn-group-vertical > .btn-group > .btn { - display: block; - float: none; - width: 100%; - max-width: 100%; -} -.btn-group-vertical > .btn-group > .btn { - float: none; -} -.btn-group-vertical > .btn + .btn, -.btn-group-vertical > .btn + .btn-group, -.btn-group-vertical > .btn-group + .btn, -.btn-group-vertical > .btn-group + .btn-group { - margin-top: -1px; - margin-left: 0; -} -.btn-group-vertical > .btn:not(:first-child):not(:last-child) { - border-radius: 0; -} -.btn-group-vertical > .btn:first-child:not(:last-child) { - border-top-left-radius: 4px; - border-top-right-radius: 4px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group-vertical > .btn:last-child:not(:first-child) { - border-top-left-radius: 0; - border-top-right-radius: 0; - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; -} -.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; -} -.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, -.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.btn-group-justified { - display: table; - width: 100%; - table-layout: fixed; - border-collapse: separate; -} -.btn-group-justified > .btn, -.btn-group-justified > .btn-group { - display: table-cell; - float: none; - width: 1%; -} -.btn-group-justified > .btn-group .btn { - width: 100%; -} -.btn-group-justified > .btn-group .dropdown-menu { - left: auto; -} -[data-toggle="buttons"] > .btn input[type="radio"], -[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], -[data-toggle="buttons"] > .btn input[type="checkbox"], -[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { - position: absolute; - clip: rect(0, 0, 0, 0); - pointer-events: none; -} -.input-group { - position: relative; - display: table; - border-collapse: separate; -} -.input-group[class*="col-"] { - float: none; - padding-right: 0; - padding-left: 0; -} -.input-group .form-control { - position: relative; - z-index: 2; - float: left; - width: 100%; - margin-bottom: 0; -} -.input-group .form-control:focus { - z-index: 3; -} -.input-group-lg > .form-control, -.input-group-lg > .input-group-addon, -.input-group-lg > .input-group-btn > .btn { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; - border-radius: 6px; -} -select.input-group-lg > .form-control, -select.input-group-lg > .input-group-addon, -select.input-group-lg > .input-group-btn > .btn { - height: 46px; - line-height: 46px; -} -textarea.input-group-lg > .form-control, -textarea.input-group-lg > .input-group-addon, -textarea.input-group-lg > .input-group-btn > .btn, -select[multiple].input-group-lg > .form-control, -select[multiple].input-group-lg > .input-group-addon, -select[multiple].input-group-lg > .input-group-btn > .btn { - height: auto; -} -.input-group-sm > .form-control, -.input-group-sm > .input-group-addon, -.input-group-sm > .input-group-btn > .btn { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; -} -select.input-group-sm > .form-control, -select.input-group-sm > .input-group-addon, -select.input-group-sm > .input-group-btn > .btn { - height: 30px; - line-height: 30px; -} -textarea.input-group-sm > .form-control, -textarea.input-group-sm > .input-group-addon, -textarea.input-group-sm > .input-group-btn > .btn, -select[multiple].input-group-sm > .form-control, -select[multiple].input-group-sm > .input-group-addon, -select[multiple].input-group-sm > .input-group-btn > .btn { - height: auto; -} -.input-group-addon, -.input-group-btn, -.input-group .form-control { - display: table-cell; -} -.input-group-addon:not(:first-child):not(:last-child), -.input-group-btn:not(:first-child):not(:last-child), -.input-group .form-control:not(:first-child):not(:last-child) { - border-radius: 0; -} -.input-group-addon, -.input-group-btn { - width: 1%; - white-space: nowrap; - vertical-align: middle; -} -.input-group-addon { - padding: 6px 12px; - font-size: 14px; - font-weight: normal; - line-height: 1; - color: #555; - text-align: center; - background-color: #eee; - border: 1px solid #ccc; - border-radius: 4px; -} -.input-group-addon.input-sm { - padding: 5px 10px; - font-size: 12px; - border-radius: 3px; -} -.input-group-addon.input-lg { - padding: 10px 16px; - font-size: 18px; - border-radius: 6px; -} -.input-group-addon input[type="radio"], -.input-group-addon input[type="checkbox"] { - margin-top: 0; -} -.input-group .form-control:first-child, -.input-group-addon:first-child, -.input-group-btn:first-child > .btn, -.input-group-btn:first-child > .btn-group > .btn, -.input-group-btn:first-child > .dropdown-toggle, -.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), -.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.input-group-addon:first-child { - border-right: 0; -} -.input-group .form-control:last-child, -.input-group-addon:last-child, -.input-group-btn:last-child > .btn, -.input-group-btn:last-child > .btn-group > .btn, -.input-group-btn:last-child > .dropdown-toggle, -.input-group-btn:first-child > .btn:not(:first-child), -.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.input-group-addon:last-child { - border-left: 0; -} -.input-group-btn { - position: relative; - font-size: 0; - white-space: nowrap; -} -.input-group-btn > .btn { - position: relative; -} -.input-group-btn > .btn + .btn { - margin-left: -1px; -} -.input-group-btn > .btn:hover, -.input-group-btn > .btn:focus, -.input-group-btn > .btn:active { - z-index: 2; -} -.input-group-btn:first-child > .btn, -.input-group-btn:first-child > .btn-group { - margin-right: -1px; -} -.input-group-btn:last-child > .btn, -.input-group-btn:last-child > .btn-group { - z-index: 2; - margin-left: -1px; -} -.nav { - padding-left: 0; - margin-bottom: 0; - list-style: none; -} -.nav > li { - position: relative; - display: block; -} -.nav > li > a { - position: relative; - display: block; - padding: 10px 15px; -} -.nav > li > a:hover, -.nav > li > a:focus { - text-decoration: none; - background-color: #eee; -} -.nav > li.disabled > a { - color: #777; -} -.nav > li.disabled > a:hover, -.nav > li.disabled > a:focus { - color: #777; - text-decoration: none; - cursor: not-allowed; - background-color: transparent; -} -.nav .open > a, -.nav .open > a:hover, -.nav .open > a:focus { - background-color: #eee; - border-color: #337ab7; -} -.nav .nav-divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; -} -.nav > li > a > img { - max-width: none; -} -.nav-tabs { - border-bottom: 1px solid #ddd; -} -.nav-tabs > li { - float: left; - margin-bottom: -1px; -} -.nav-tabs > li > a { - margin-right: 2px; - line-height: 1.42857143; - border: 1px solid transparent; - border-radius: 4px 4px 0 0; -} -.nav-tabs > li > a:hover { - border-color: #eee #eee #ddd; -} -.nav-tabs > li.active > a, -.nav-tabs > li.active > a:hover, -.nav-tabs > li.active > a:focus { - color: #555; - cursor: default; - background-color: #fff; - border: 1px solid #ddd; - border-bottom-color: transparent; -} -.nav-tabs.nav-justified { - width: 100%; - border-bottom: 0; -} -.nav-tabs.nav-justified > li { - float: none; -} -.nav-tabs.nav-justified > li > a { - margin-bottom: 5px; - text-align: center; -} -.nav-tabs.nav-justified > .dropdown .dropdown-menu { - top: auto; - left: auto; -} -@media (min-width: 768px) { - .nav-tabs.nav-justified > li { - display: table-cell; - width: 1%; - } - .nav-tabs.nav-justified > li > a { - margin-bottom: 0; - } -} -.nav-tabs.nav-justified > li > a { - margin-right: 0; - border-radius: 4px; -} -.nav-tabs.nav-justified > .active > a, -.nav-tabs.nav-justified > .active > a:hover, -.nav-tabs.nav-justified > .active > a:focus { - border: 1px solid #ddd; -} -@media (min-width: 768px) { - .nav-tabs.nav-justified > li > a { - border-bottom: 1px solid #ddd; - border-radius: 4px 4px 0 0; - } - .nav-tabs.nav-justified > .active > a, - .nav-tabs.nav-justified > .active > a:hover, - .nav-tabs.nav-justified > .active > a:focus { - border-bottom-color: #fff; - } -} -.nav-pills > li { - float: left; -} -.nav-pills > li > a { - border-radius: 4px; -} -.nav-pills > li + li { - margin-left: 2px; -} -.nav-pills > li.active > a, -.nav-pills > li.active > a:hover, -.nav-pills > li.active > a:focus { - color: #fff; - background-color: #337ab7; -} -.nav-stacked > li { - float: none; -} -.nav-stacked > li + li { - margin-top: 2px; - margin-left: 0; -} -.nav-justified { - width: 100%; -} -.nav-justified > li { - float: none; -} -.nav-justified > li > a { - margin-bottom: 5px; - text-align: center; -} -.nav-justified > .dropdown .dropdown-menu { - top: auto; - left: auto; -} -@media (min-width: 768px) { - .nav-justified > li { - display: table-cell; - width: 1%; - } - .nav-justified > li > a { - margin-bottom: 0; - } -} -.nav-tabs-justified { - border-bottom: 0; -} -.nav-tabs-justified > li > a { - margin-right: 0; - border-radius: 4px; -} -.nav-tabs-justified > .active > a, -.nav-tabs-justified > .active > a:hover, -.nav-tabs-justified > .active > a:focus { - border: 1px solid #ddd; -} -@media (min-width: 768px) { - .nav-tabs-justified > li > a { - border-bottom: 1px solid #ddd; - border-radius: 4px 4px 0 0; - } - .nav-tabs-justified > .active > a, - .nav-tabs-justified > .active > a:hover, - .nav-tabs-justified > .active > a:focus { - border-bottom-color: #fff; - } -} -.tab-content > .tab-pane { - display: none; -} -.tab-content > .active { - display: block; -} -.nav-tabs .dropdown-menu { - margin-top: -1px; - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.navbar { - position: relative; - min-height: 50px; - margin-bottom: 20px; - border: 1px solid transparent; -} -@media (min-width: 768px) { - .navbar { - border-radius: 4px; - } -} -@media (min-width: 768px) { - .navbar-header { - float: left; - } -} -.navbar-collapse { - padding-right: 15px; - padding-left: 15px; - overflow-x: visible; - -webkit-overflow-scrolling: touch; - border-top: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); -} -.navbar-collapse.in { - overflow-y: auto; -} -@media (min-width: 768px) { - .navbar-collapse { - width: auto; - border-top: 0; - -webkit-box-shadow: none; - box-shadow: none; - } - .navbar-collapse.collapse { - display: block !important; - height: auto !important; - padding-bottom: 0; - overflow: visible !important; - } - .navbar-collapse.in { - overflow-y: visible; - } - .navbar-fixed-top .navbar-collapse, - .navbar-static-top .navbar-collapse, - .navbar-fixed-bottom .navbar-collapse { - padding-right: 0; - padding-left: 0; - } -} -.navbar-fixed-top .navbar-collapse, -.navbar-fixed-bottom .navbar-collapse { - max-height: 340px; -} -@media (max-device-width: 480px) and (orientation: landscape) { - .navbar-fixed-top .navbar-collapse, - .navbar-fixed-bottom .navbar-collapse { - max-height: 200px; - } -} -.container > .navbar-header, -.container-fluid > .navbar-header, -.container > .navbar-collapse, -.container-fluid > .navbar-collapse { - margin-right: -15px; - margin-left: -15px; -} -@media (min-width: 768px) { - .container > .navbar-header, - .container-fluid > .navbar-header, - .container > .navbar-collapse, - .container-fluid > .navbar-collapse { - margin-right: 0; - margin-left: 0; - } -} -.navbar-static-top { - z-index: 1000; - border-width: 0 0 1px; -} -@media (min-width: 768px) { - .navbar-static-top { - border-radius: 0; - } -} -.navbar-fixed-top, -.navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - z-index: 1030; -} -@media (min-width: 768px) { - .navbar-fixed-top, - .navbar-fixed-bottom { - border-radius: 0; - } -} -.navbar-fixed-top { - top: 0; - border-width: 0 0 1px; -} -.navbar-fixed-bottom { - bottom: 0; - margin-bottom: 0; - border-width: 1px 0 0; -} -.navbar-brand { - float: left; - height: 50px; - padding: 15px 15px; - font-size: 18px; - line-height: 20px; -} -.navbar-brand:hover, -.navbar-brand:focus { - text-decoration: none; -} -.navbar-brand > img { - display: block; -} -@media (min-width: 768px) { - .navbar > .container .navbar-brand, - .navbar > .container-fluid .navbar-brand { - margin-left: -15px; - } -} -.navbar-toggle { - position: relative; - float: right; - padding: 9px 10px; - margin-top: 8px; - margin-right: 15px; - margin-bottom: 8px; - background-color: transparent; - background-image: none; - border: 1px solid transparent; - border-radius: 4px; -} -.navbar-toggle:focus { - outline: 0; -} -.navbar-toggle .icon-bar { - display: block; - width: 22px; - height: 2px; - border-radius: 1px; -} -.navbar-toggle .icon-bar + .icon-bar { - margin-top: 4px; -} -@media (min-width: 768px) { - .navbar-toggle { - display: none; - } -} -.navbar-nav { - margin: 7.5px -15px; -} -.navbar-nav > li > a { - padding-top: 10px; - padding-bottom: 10px; - line-height: 20px; -} -@media (max-width: 767px) { - .navbar-nav .open .dropdown-menu { - position: static; - float: none; - width: auto; - margin-top: 0; - background-color: transparent; - border: 0; - -webkit-box-shadow: none; - box-shadow: none; - } - .navbar-nav .open .dropdown-menu > li > a, - .navbar-nav .open .dropdown-menu .dropdown-header { - padding: 5px 15px 5px 25px; - } - .navbar-nav .open .dropdown-menu > li > a { - line-height: 20px; - } - .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-nav .open .dropdown-menu > li > a:focus { - background-image: none; - } -} -@media (min-width: 768px) { - .navbar-nav { - float: left; - margin: 0; - } - .navbar-nav > li { - float: left; - } - .navbar-nav > li > a { - padding-top: 15px; - padding-bottom: 15px; - } -} -.navbar-form { - padding: 10px 15px; - margin-top: 8px; - margin-right: -15px; - margin-bottom: 8px; - margin-left: -15px; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); -} -@media (min-width: 768px) { - .navbar-form .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .form-control { - display: inline-block; - width: auto; - vertical-align: middle; - } - .navbar-form .form-control-static { - display: inline-block; - } - .navbar-form .input-group { - display: inline-table; - vertical-align: middle; - } - .navbar-form .input-group .input-group-addon, - .navbar-form .input-group .input-group-btn, - .navbar-form .input-group .form-control { - width: auto; - } - .navbar-form .input-group > .form-control { - width: 100%; - } - .navbar-form .control-label { - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .radio, - .navbar-form .checkbox { - display: inline-block; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .radio label, - .navbar-form .checkbox label { - padding-left: 0; - } - .navbar-form .radio input[type="radio"], - .navbar-form .checkbox input[type="checkbox"] { - position: relative; - margin-left: 0; - } - .navbar-form .has-feedback .form-control-feedback { - top: 0; - } -} -@media (max-width: 767px) { - .navbar-form .form-group { - margin-bottom: 5px; - } - .navbar-form .form-group:last-child { - margin-bottom: 0; - } -} -@media (min-width: 768px) { - .navbar-form { - width: auto; - padding-top: 0; - padding-bottom: 0; - margin-right: 0; - margin-left: 0; - border: 0; - -webkit-box-shadow: none; - box-shadow: none; - } -} -.navbar-nav > li > .dropdown-menu { - margin-top: 0; - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { - margin-bottom: 0; - border-top-left-radius: 4px; - border-top-right-radius: 4px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; -} -.navbar-btn { - margin-top: 8px; - margin-bottom: 8px; -} -.navbar-btn.btn-sm { - margin-top: 10px; - margin-bottom: 10px; -} -.navbar-btn.btn-xs { - margin-top: 14px; - margin-bottom: 14px; -} -.navbar-text { - margin-top: 15px; - margin-bottom: 15px; -} -@media (min-width: 768px) { - .navbar-text { - float: left; - margin-right: 15px; - margin-left: 15px; - } -} -@media (min-width: 768px) { - .navbar-left { - float: left !important; - } - .navbar-right { - float: right !important; - margin-right: -15px; - } - .navbar-right ~ .navbar-right { - margin-right: 0; - } -} -.navbar-default { - background-color: #f8f8f8; - border-color: #e7e7e7; -} -.navbar-default .navbar-brand { - color: #777; -} -.navbar-default .navbar-brand:hover, -.navbar-default .navbar-brand:focus { - color: #5e5e5e; - background-color: transparent; -} -.navbar-default .navbar-text { - color: #777; -} -.navbar-default .navbar-nav > li > a { - color: #777; -} -.navbar-default .navbar-nav > li > a:hover, -.navbar-default .navbar-nav > li > a:focus { - color: #333; - background-color: transparent; -} -.navbar-default .navbar-nav > .active > a, -.navbar-default .navbar-nav > .active > a:hover, -.navbar-default .navbar-nav > .active > a:focus { - color: #555; - background-color: #e7e7e7; -} -.navbar-default .navbar-nav > .disabled > a, -.navbar-default .navbar-nav > .disabled > a:hover, -.navbar-default .navbar-nav > .disabled > a:focus { - color: #ccc; - background-color: transparent; -} -.navbar-default .navbar-toggle { - border-color: #ddd; -} -.navbar-default .navbar-toggle:hover, -.navbar-default .navbar-toggle:focus { - background-color: #ddd; -} -.navbar-default .navbar-toggle .icon-bar { - background-color: #888; -} -.navbar-default .navbar-collapse, -.navbar-default .navbar-form { - border-color: #e7e7e7; -} -.navbar-default .navbar-nav > .open > a, -.navbar-default .navbar-nav > .open > a:hover, -.navbar-default .navbar-nav > .open > a:focus { - color: #555; - background-color: #e7e7e7; -} -@media (max-width: 767px) { - .navbar-default .navbar-nav .open .dropdown-menu > li > a { - color: #777; - } - .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { - color: #333; - background-color: transparent; - } - .navbar-default .navbar-nav .open .dropdown-menu > .active > a, - .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { - color: #555; - background-color: #e7e7e7; - } - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { - color: #ccc; - background-color: transparent; - } -} -.navbar-default .navbar-link { - color: #777; -} -.navbar-default .navbar-link:hover { - color: #333; -} -.navbar-default .btn-link { - color: #777; -} -.navbar-default .btn-link:hover, -.navbar-default .btn-link:focus { - color: #333; -} -.navbar-default .btn-link[disabled]:hover, -fieldset[disabled] .navbar-default .btn-link:hover, -.navbar-default .btn-link[disabled]:focus, -fieldset[disabled] .navbar-default .btn-link:focus { - color: #ccc; -} -.navbar-inverse { - background-color: #222; - border-color: #080808; -} -.navbar-inverse .navbar-brand { - color: #9d9d9d; -} -.navbar-inverse .navbar-brand:hover, -.navbar-inverse .navbar-brand:focus { - color: #fff; - background-color: transparent; -} -.navbar-inverse .navbar-text { - color: #9d9d9d; -} -.navbar-inverse .navbar-nav > li > a { - color: #9d9d9d; -} -.navbar-inverse .navbar-nav > li > a:hover, -.navbar-inverse .navbar-nav > li > a:focus { - color: #fff; - background-color: transparent; -} -.navbar-inverse .navbar-nav > .active > a, -.navbar-inverse .navbar-nav > .active > a:hover, -.navbar-inverse .navbar-nav > .active > a:focus { - color: #fff; - background-color: #080808; -} -.navbar-inverse .navbar-nav > .disabled > a, -.navbar-inverse .navbar-nav > .disabled > a:hover, -.navbar-inverse .navbar-nav > .disabled > a:focus { - color: #444; - background-color: transparent; -} -.navbar-inverse .navbar-toggle { - border-color: #333; -} -.navbar-inverse .navbar-toggle:hover, -.navbar-inverse .navbar-toggle:focus { - background-color: #333; -} -.navbar-inverse .navbar-toggle .icon-bar { - background-color: #fff; -} -.navbar-inverse .navbar-collapse, -.navbar-inverse .navbar-form { - border-color: #101010; -} -.navbar-inverse .navbar-nav > .open > a, -.navbar-inverse .navbar-nav > .open > a:hover, -.navbar-inverse .navbar-nav > .open > a:focus { - color: #fff; - background-color: #080808; -} -@media (max-width: 767px) { - .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { - border-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu .divider { - background-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { - color: #9d9d9d; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { - color: #fff; - background-color: transparent; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { - color: #fff; - background-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { - color: #444; - background-color: transparent; - } -} -.navbar-inverse .navbar-link { - color: #9d9d9d; -} -.navbar-inverse .navbar-link:hover { - color: #fff; -} -.navbar-inverse .btn-link { - color: #9d9d9d; -} -.navbar-inverse .btn-link:hover, -.navbar-inverse .btn-link:focus { - color: #fff; -} -.navbar-inverse .btn-link[disabled]:hover, -fieldset[disabled] .navbar-inverse .btn-link:hover, -.navbar-inverse .btn-link[disabled]:focus, -fieldset[disabled] .navbar-inverse .btn-link:focus { - color: #444; -} -.breadcrumb { - padding: 8px 15px; - margin-bottom: 20px; - list-style: none; - background-color: #f5f5f5; - border-radius: 4px; -} -.breadcrumb > li { - display: inline-block; -} -.breadcrumb > li + li:before { - padding: 0 5px; - color: #ccc; - content: "/\00a0"; -} -.breadcrumb > .active { - color: #777; -} -.pagination { - display: inline-block; - padding-left: 0; - margin: 20px 0; - border-radius: 4px; -} -.pagination > li { - display: inline; -} -.pagination > li > a, -.pagination > li > span { - position: relative; - float: left; - padding: 6px 12px; - margin-left: -1px; - line-height: 1.42857143; - color: #337ab7; - text-decoration: none; - background-color: #fff; - border: 1px solid #ddd; -} -.pagination > li:first-child > a, -.pagination > li:first-child > span { - margin-left: 0; - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; -} -.pagination > li:last-child > a, -.pagination > li:last-child > span { - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; -} -.pagination > li > a:hover, -.pagination > li > span:hover, -.pagination > li > a:focus, -.pagination > li > span:focus { - z-index: 2; - color: #23527c; - background-color: #eee; - border-color: #ddd; -} -.pagination > .active > a, -.pagination > .active > span, -.pagination > .active > a:hover, -.pagination > .active > span:hover, -.pagination > .active > a:focus, -.pagination > .active > span:focus { - z-index: 3; - color: #fff; - cursor: default; - background-color: #337ab7; - border-color: #337ab7; -} -.pagination > .disabled > span, -.pagination > .disabled > span:hover, -.pagination > .disabled > span:focus, -.pagination > .disabled > a, -.pagination > .disabled > a:hover, -.pagination > .disabled > a:focus { - color: #777; - cursor: not-allowed; - background-color: #fff; - border-color: #ddd; -} -.pagination-lg > li > a, -.pagination-lg > li > span { - padding: 10px 16px; - font-size: 18px; - line-height: 1.3333333; -} -.pagination-lg > li:first-child > a, -.pagination-lg > li:first-child > span { - border-top-left-radius: 6px; - border-bottom-left-radius: 6px; -} -.pagination-lg > li:last-child > a, -.pagination-lg > li:last-child > span { - border-top-right-radius: 6px; - border-bottom-right-radius: 6px; -} -.pagination-sm > li > a, -.pagination-sm > li > span { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; -} -.pagination-sm > li:first-child > a, -.pagination-sm > li:first-child > span { - border-top-left-radius: 3px; - border-bottom-left-radius: 3px; -} -.pagination-sm > li:last-child > a, -.pagination-sm > li:last-child > span { - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; -} -.pager { - padding-left: 0; - margin: 20px 0; - text-align: center; - list-style: none; -} -.pager li { - display: inline; -} -.pager li > a, -.pager li > span { - display: inline-block; - padding: 5px 14px; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 15px; -} -.pager li > a:hover, -.pager li > a:focus { - text-decoration: none; - background-color: #eee; -} -.pager .next > a, -.pager .next > span { - float: right; -} -.pager .previous > a, -.pager .previous > span { - float: left; -} -.pager .disabled > a, -.pager .disabled > a:hover, -.pager .disabled > a:focus, -.pager .disabled > span { - color: #777; - cursor: not-allowed; - background-color: #fff; -} -.label { - display: inline; - padding: .2em .6em .3em; - font-size: 75%; - font-weight: bold; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: .25em; -} -a.label:hover, -a.label:focus { - color: #fff; - text-decoration: none; - cursor: pointer; -} -.label:empty { - display: none; -} -.btn .label { - position: relative; - top: -1px; -} -.label-default { - background-color: #777; -} -.label-default[href]:hover, -.label-default[href]:focus { - background-color: #5e5e5e; -} -.label-primary { - background-color: #337ab7; -} -.label-primary[href]:hover, -.label-primary[href]:focus { - background-color: #286090; -} -.label-success { - background-color: #5cb85c; -} -.label-success[href]:hover, -.label-success[href]:focus { - background-color: #449d44; -} -.label-info { - background-color: #5bc0de; -} -.label-info[href]:hover, -.label-info[href]:focus { - background-color: #31b0d5; -} -.label-warning { - background-color: #f0ad4e; -} -.label-warning[href]:hover, -.label-warning[href]:focus { - background-color: #ec971f; -} -.label-danger { - background-color: #d9534f; -} -.label-danger[href]:hover, -.label-danger[href]:focus { - background-color: #c9302c; -} -.badge { - display: inline-block; - min-width: 10px; - padding: 3px 7px; - font-size: 12px; - font-weight: bold; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: middle; - background-color: #777; - border-radius: 10px; -} -.badge:empty { - display: none; -} -.btn .badge { - position: relative; - top: -1px; -} -.btn-xs .badge, -.btn-group-xs > .btn .badge { - top: 0; - padding: 1px 5px; -} -a.badge:hover, -a.badge:focus { - color: #fff; - text-decoration: none; - cursor: pointer; -} -.list-group-item.active > .badge, -.nav-pills > .active > a > .badge { - color: #337ab7; - background-color: #fff; -} -.list-group-item > .badge { - float: right; -} -.list-group-item > .badge + .badge { - margin-right: 5px; -} -.nav-pills > li > a > .badge { - margin-left: 3px; -} -.jumbotron { - padding-top: 30px; - padding-bottom: 30px; - margin-bottom: 30px; - color: inherit; - background-color: #eee; -} -.jumbotron h1, -.jumbotron .h1 { - color: inherit; -} -.jumbotron p { - margin-bottom: 15px; - font-size: 21px; - font-weight: 200; -} -.jumbotron > hr { - border-top-color: #d5d5d5; -} -.container .jumbotron, -.container-fluid .jumbotron { - padding-right: 15px; - padding-left: 15px; - border-radius: 6px; -} -.jumbotron .container { - max-width: 100%; -} -@media screen and (min-width: 768px) { - .jumbotron { - padding-top: 48px; - padding-bottom: 48px; - } - .container .jumbotron, - .container-fluid .jumbotron { - padding-right: 60px; - padding-left: 60px; - } - .jumbotron h1, - .jumbotron .h1 { - font-size: 63px; - } -} -.thumbnail { - display: block; - padding: 4px; - margin-bottom: 20px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: border .2s ease-in-out; - -o-transition: border .2s ease-in-out; - transition: border .2s ease-in-out; -} -.thumbnail > img, -.thumbnail a > img { - margin-right: auto; - margin-left: auto; -} -a.thumbnail:hover, -a.thumbnail:focus, -a.thumbnail.active { - border-color: #337ab7; -} -.thumbnail .caption { - padding: 9px; - color: #333; -} -.alert { - padding: 15px; - margin-bottom: 20px; - border: 1px solid transparent; - border-radius: 4px; -} -.alert h4 { - margin-top: 0; - color: inherit; -} -.alert .alert-link { - font-weight: bold; -} -.alert > p, -.alert > ul { - margin-bottom: 0; -} -.alert > p + p { - margin-top: 5px; -} -.alert-dismissable, -.alert-dismissible { - padding-right: 35px; -} -.alert-dismissable .close, -.alert-dismissible .close { - position: relative; - top: -2px; - right: -21px; - color: inherit; -} -.alert-success { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6; -} -.alert-success hr { - border-top-color: #c9e2b3; -} -.alert-success .alert-link { - color: #2b542c; -} -.alert-info { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1; -} -.alert-info hr { - border-top-color: #a6e1ec; -} -.alert-info .alert-link { - color: #245269; -} -.alert-warning { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc; -} -.alert-warning hr { - border-top-color: #f7e1b5; -} -.alert-warning .alert-link { - color: #66512c; -} -.alert-danger { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1; -} -.alert-danger hr { - border-top-color: #e4b9c0; -} -.alert-danger .alert-link { - color: #843534; -} -@-webkit-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@-o-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -@keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } -} -.progress { - height: 20px; - margin-bottom: 20px; - overflow: hidden; - background-color: #f5f5f5; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); -} -.progress-bar { - float: left; - width: 0; - height: 100%; - font-size: 12px; - line-height: 20px; - color: #fff; - text-align: center; - background-color: #337ab7; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); - -webkit-transition: width .6s ease; - -o-transition: width .6s ease; - transition: width .6s ease; -} -.progress-striped .progress-bar, -.progress-bar-striped { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - -webkit-background-size: 40px 40px; - background-size: 40px 40px; -} -.progress.active .progress-bar, -.progress-bar.active { - -webkit-animation: progress-bar-stripes 2s linear infinite; - -o-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; -} -.progress-bar-success { - background-color: #5cb85c; -} -.progress-striped .progress-bar-success { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); -} -.progress-bar-info { - background-color: #5bc0de; -} -.progress-striped .progress-bar-info { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); -} -.progress-bar-warning { - background-color: #f0ad4e; -} -.progress-striped .progress-bar-warning { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); -} -.progress-bar-danger { - background-color: #d9534f; -} -.progress-striped .progress-bar-danger { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); -} -.media { - margin-top: 15px; -} -.media:first-child { - margin-top: 0; -} -.media, -.media-body { - overflow: hidden; - zoom: 1; -} -.media-body { - width: 10000px; -} -.media-object { - display: block; -} -.media-object.img-thumbnail { - max-width: none; -} -.media-right, -.media > .pull-right { - padding-left: 10px; -} -.media-left, -.media > .pull-left { - padding-right: 10px; -} -.media-left, -.media-right, -.media-body { - display: table-cell; - vertical-align: top; -} -.media-middle { - vertical-align: middle; -} -.media-bottom { - vertical-align: bottom; -} -.media-heading { - margin-top: 0; - margin-bottom: 5px; -} -.media-list { - padding-left: 0; - list-style: none; -} -.list-group { - padding-left: 0; - margin-bottom: 20px; -} -.list-group-item { - position: relative; - display: block; - padding: 10px 15px; - margin-bottom: -1px; - background-color: #fff; - border: 1px solid #ddd; -} -.list-group-item:first-child { - border-top-left-radius: 4px; - border-top-right-radius: 4px; -} -.list-group-item:last-child { - margin-bottom: 0; - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; -} -a.list-group-item, -button.list-group-item { - color: #555; -} -a.list-group-item .list-group-item-heading, -button.list-group-item .list-group-item-heading { - color: #333; -} -a.list-group-item:hover, -button.list-group-item:hover, -a.list-group-item:focus, -button.list-group-item:focus { - color: #555; - text-decoration: none; - background-color: #f5f5f5; -} -button.list-group-item { - width: 100%; - text-align: left; -} -.list-group-item.disabled, -.list-group-item.disabled:hover, -.list-group-item.disabled:focus { - color: #777; - cursor: not-allowed; - background-color: #eee; -} -.list-group-item.disabled .list-group-item-heading, -.list-group-item.disabled:hover .list-group-item-heading, -.list-group-item.disabled:focus .list-group-item-heading { - color: inherit; -} -.list-group-item.disabled .list-group-item-text, -.list-group-item.disabled:hover .list-group-item-text, -.list-group-item.disabled:focus .list-group-item-text { - color: #777; -} -.list-group-item.active, -.list-group-item.active:hover, -.list-group-item.active:focus { - z-index: 2; - color: #fff; - background-color: #337ab7; - border-color: #337ab7; -} -.list-group-item.active .list-group-item-heading, -.list-group-item.active:hover .list-group-item-heading, -.list-group-item.active:focus .list-group-item-heading, -.list-group-item.active .list-group-item-heading > small, -.list-group-item.active:hover .list-group-item-heading > small, -.list-group-item.active:focus .list-group-item-heading > small, -.list-group-item.active .list-group-item-heading > .small, -.list-group-item.active:hover .list-group-item-heading > .small, -.list-group-item.active:focus .list-group-item-heading > .small { - color: inherit; -} -.list-group-item.active .list-group-item-text, -.list-group-item.active:hover .list-group-item-text, -.list-group-item.active:focus .list-group-item-text { - color: #c7ddef; -} -.list-group-item-success { - color: #3c763d; - background-color: #dff0d8; -} -a.list-group-item-success, -button.list-group-item-success { - color: #3c763d; -} -a.list-group-item-success .list-group-item-heading, -button.list-group-item-success .list-group-item-heading { - color: inherit; -} -a.list-group-item-success:hover, -button.list-group-item-success:hover, -a.list-group-item-success:focus, -button.list-group-item-success:focus { - color: #3c763d; - background-color: #d0e9c6; -} -a.list-group-item-success.active, -button.list-group-item-success.active, -a.list-group-item-success.active:hover, -button.list-group-item-success.active:hover, -a.list-group-item-success.active:focus, -button.list-group-item-success.active:focus { - color: #fff; - background-color: #3c763d; - border-color: #3c763d; -} -.list-group-item-info { - color: #31708f; - background-color: #d9edf7; -} -a.list-group-item-info, -button.list-group-item-info { - color: #31708f; -} -a.list-group-item-info .list-group-item-heading, -button.list-group-item-info .list-group-item-heading { - color: inherit; -} -a.list-group-item-info:hover, -button.list-group-item-info:hover, -a.list-group-item-info:focus, -button.list-group-item-info:focus { - color: #31708f; - background-color: #c4e3f3; -} -a.list-group-item-info.active, -button.list-group-item-info.active, -a.list-group-item-info.active:hover, -button.list-group-item-info.active:hover, -a.list-group-item-info.active:focus, -button.list-group-item-info.active:focus { - color: #fff; - background-color: #31708f; - border-color: #31708f; -} -.list-group-item-warning { - color: #8a6d3b; - background-color: #fcf8e3; -} -a.list-group-item-warning, -button.list-group-item-warning { - color: #8a6d3b; -} -a.list-group-item-warning .list-group-item-heading, -button.list-group-item-warning .list-group-item-heading { - color: inherit; -} -a.list-group-item-warning:hover, -button.list-group-item-warning:hover, -a.list-group-item-warning:focus, -button.list-group-item-warning:focus { - color: #8a6d3b; - background-color: #faf2cc; -} -a.list-group-item-warning.active, -button.list-group-item-warning.active, -a.list-group-item-warning.active:hover, -button.list-group-item-warning.active:hover, -a.list-group-item-warning.active:focus, -button.list-group-item-warning.active:focus { - color: #fff; - background-color: #8a6d3b; - border-color: #8a6d3b; -} -.list-group-item-danger { - color: #a94442; - background-color: #f2dede; -} -a.list-group-item-danger, -button.list-group-item-danger { - color: #a94442; -} -a.list-group-item-danger .list-group-item-heading, -button.list-group-item-danger .list-group-item-heading { - color: inherit; -} -a.list-group-item-danger:hover, -button.list-group-item-danger:hover, -a.list-group-item-danger:focus, -button.list-group-item-danger:focus { - color: #a94442; - background-color: #ebcccc; -} -a.list-group-item-danger.active, -button.list-group-item-danger.active, -a.list-group-item-danger.active:hover, -button.list-group-item-danger.active:hover, -a.list-group-item-danger.active:focus, -button.list-group-item-danger.active:focus { - color: #fff; - background-color: #a94442; - border-color: #a94442; -} -.list-group-item-heading { - margin-top: 0; - margin-bottom: 5px; -} -.list-group-item-text { - margin-bottom: 0; - line-height: 1.3; -} -.panel { - margin-bottom: 20px; - background-color: #fff; - border: 1px solid transparent; - border-radius: 4px; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); - box-shadow: 0 1px 1px rgba(0, 0, 0, .05); -} -.panel-body { - padding: 15px; -} -.panel-heading { - padding: 10px 15px; - border-bottom: 1px solid transparent; - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel-heading > .dropdown .dropdown-toggle { - color: inherit; -} -.panel-title { - margin-top: 0; - margin-bottom: 0; - font-size: 16px; - color: inherit; -} -.panel-title > a, -.panel-title > small, -.panel-title > .small, -.panel-title > small > a, -.panel-title > .small > a { - color: inherit; -} -.panel-footer { - padding: 10px 15px; - background-color: #f5f5f5; - border-top: 1px solid #ddd; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .list-group, -.panel > .panel-collapse > .list-group { - margin-bottom: 0; -} -.panel > .list-group .list-group-item, -.panel > .panel-collapse > .list-group .list-group-item { - border-width: 1px 0; - border-radius: 0; -} -.panel > .list-group:first-child .list-group-item:first-child, -.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { - border-top: 0; - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel > .list-group:last-child .list-group-item:last-child, -.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { - border-bottom: 0; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child { - border-top-left-radius: 0; - border-top-right-radius: 0; -} -.panel-heading + .list-group .list-group-item:first-child { - border-top-width: 0; -} -.list-group + .panel-footer { - border-top-width: 0; -} -.panel > .table, -.panel > .table-responsive > .table, -.panel > .panel-collapse > .table { - margin-bottom: 0; -} -.panel > .table caption, -.panel > .table-responsive > .table caption, -.panel > .panel-collapse > .table caption { - padding-right: 15px; - padding-left: 15px; -} -.panel > .table:first-child, -.panel > .table-responsive:first-child > .table:first-child { - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel > .table:first-child > thead:first-child > tr:first-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, -.panel > .table:first-child > tbody:first-child > tr:first-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { - border-top-left-radius: 3px; - border-top-right-radius: 3px; -} -.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, -.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, -.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, -.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { - border-top-left-radius: 3px; -} -.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, -.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, -.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, -.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, -.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, -.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { - border-top-right-radius: 3px; -} -.panel > .table:last-child, -.panel > .table-responsive:last-child > .table:last-child { - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .table:last-child > tbody:last-child > tr:last-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; -} -.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, -.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { - border-bottom-left-radius: 3px; -} -.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, -.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, -.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, -.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, -.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { - border-bottom-right-radius: 3px; -} -.panel > .panel-body + .table, -.panel > .panel-body + .table-responsive, -.panel > .table + .panel-body, -.panel > .table-responsive + .panel-body { - border-top: 1px solid #ddd; -} -.panel > .table > tbody:first-child > tr:first-child th, -.panel > .table > tbody:first-child > tr:first-child td { - border-top: 0; -} -.panel > .table-bordered, -.panel > .table-responsive > .table-bordered { - border: 0; -} -.panel > .table-bordered > thead > tr > th:first-child, -.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, -.panel > .table-bordered > tbody > tr > th:first-child, -.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, -.panel > .table-bordered > tfoot > tr > th:first-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, -.panel > .table-bordered > thead > tr > td:first-child, -.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, -.panel > .table-bordered > tbody > tr > td:first-child, -.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, -.panel > .table-bordered > tfoot > tr > td:first-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { - border-left: 0; -} -.panel > .table-bordered > thead > tr > th:last-child, -.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, -.panel > .table-bordered > tbody > tr > th:last-child, -.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, -.panel > .table-bordered > tfoot > tr > th:last-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, -.panel > .table-bordered > thead > tr > td:last-child, -.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, -.panel > .table-bordered > tbody > tr > td:last-child, -.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, -.panel > .table-bordered > tfoot > tr > td:last-child, -.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { - border-right: 0; -} -.panel > .table-bordered > thead > tr:first-child > td, -.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, -.panel > .table-bordered > tbody > tr:first-child > td, -.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, -.panel > .table-bordered > thead > tr:first-child > th, -.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, -.panel > .table-bordered > tbody > tr:first-child > th, -.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { - border-bottom: 0; -} -.panel > .table-bordered > tbody > tr:last-child > td, -.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, -.panel > .table-bordered > tfoot > tr:last-child > td, -.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, -.panel > .table-bordered > tbody > tr:last-child > th, -.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, -.panel > .table-bordered > tfoot > tr:last-child > th, -.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { - border-bottom: 0; -} -.panel > .table-responsive { - margin-bottom: 0; - border: 0; -} -.panel-group { - margin-bottom: 20px; -} -.panel-group .panel { - margin-bottom: 0; - border-radius: 4px; -} -.panel-group .panel + .panel { - margin-top: 5px; -} -.panel-group .panel-heading { - border-bottom: 0; -} -.panel-group .panel-heading + .panel-collapse > .panel-body, -.panel-group .panel-heading + .panel-collapse > .list-group { - border-top: 1px solid #ddd; -} -.panel-group .panel-footer { - border-top: 0; -} -.panel-group .panel-footer + .panel-collapse .panel-body { - border-bottom: 1px solid #ddd; -} -.panel-default { - border-color: #ddd; -} -.panel-default > .panel-heading { - color: #333; - background-color: #f5f5f5; - border-color: #ddd; -} -.panel-default > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #ddd; -} -.panel-default > .panel-heading .badge { - color: #f5f5f5; - background-color: #333; -} -.panel-default > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #ddd; -} -.panel-primary { - border-color: #337ab7; -} -.panel-primary > .panel-heading { - color: #fff; - background-color: #337ab7; - border-color: #337ab7; -} -.panel-primary > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #337ab7; -} -.panel-primary > .panel-heading .badge { - color: #337ab7; - background-color: #fff; -} -.panel-primary > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #337ab7; -} -.panel-success { - border-color: #d6e9c6; -} -.panel-success > .panel-heading { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6; -} -.panel-success > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #d6e9c6; -} -.panel-success > .panel-heading .badge { - color: #dff0d8; - background-color: #3c763d; -} -.panel-success > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #d6e9c6; -} -.panel-info { - border-color: #bce8f1; -} -.panel-info > .panel-heading { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1; -} -.panel-info > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #bce8f1; -} -.panel-info > .panel-heading .badge { - color: #d9edf7; - background-color: #31708f; -} -.panel-info > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #bce8f1; -} -.panel-warning { - border-color: #faebcc; -} -.panel-warning > .panel-heading { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc; -} -.panel-warning > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #faebcc; -} -.panel-warning > .panel-heading .badge { - color: #fcf8e3; - background-color: #8a6d3b; -} -.panel-warning > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #faebcc; -} -.panel-danger { - border-color: #ebccd1; -} -.panel-danger > .panel-heading { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1; -} -.panel-danger > .panel-heading + .panel-collapse > .panel-body { - border-top-color: #ebccd1; -} -.panel-danger > .panel-heading .badge { - color: #f2dede; - background-color: #a94442; -} -.panel-danger > .panel-footer + .panel-collapse > .panel-body { - border-bottom-color: #ebccd1; -} -.embed-responsive { - position: relative; - display: block; - height: 0; - padding: 0; - overflow: hidden; -} -.embed-responsive .embed-responsive-item, -.embed-responsive iframe, -.embed-responsive embed, -.embed-responsive object, -.embed-responsive video { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 100%; - height: 100%; - border: 0; -} -.embed-responsive-16by9 { - padding-bottom: 56.25%; -} -.embed-responsive-4by3 { - padding-bottom: 75%; -} -.well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #e3e3e3; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); -} -.well blockquote { - border-color: #ddd; - border-color: rgba(0, 0, 0, .15); -} -.well-lg { - padding: 24px; - border-radius: 6px; -} -.well-sm { - padding: 9px; - border-radius: 3px; -} -.close { - float: right; - font-size: 21px; - font-weight: bold; - line-height: 1; - color: #000; - text-shadow: 0 1px 0 #fff; - filter: alpha(opacity=20); - opacity: .2; -} -.close:hover, -.close:focus { - color: #000; - text-decoration: none; - cursor: pointer; - filter: alpha(opacity=50); - opacity: .5; -} -button.close { - -webkit-appearance: none; - padding: 0; - cursor: pointer; - background: transparent; - border: 0; -} -.modal-open { - overflow: hidden; -} -.modal { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1050; - display: none; - overflow: hidden; - -webkit-overflow-scrolling: touch; - outline: 0; -} -.modal.fade .modal-dialog { - -webkit-transition: -webkit-transform .3s ease-out; - -o-transition: -o-transform .3s ease-out; - transition: transform .3s ease-out; - -webkit-transform: translate(0, -25%); - -ms-transform: translate(0, -25%); - -o-transform: translate(0, -25%); - transform: translate(0, -25%); -} -.modal.in .modal-dialog { - -webkit-transform: translate(0, 0); - -ms-transform: translate(0, 0); - -o-transform: translate(0, 0); - transform: translate(0, 0); -} -.modal-open .modal { - overflow-x: hidden; - overflow-y: auto; -} -.modal-dialog { - position: relative; - width: auto; - margin: 10px; -} -.modal-content { - position: relative; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, .2); - border-radius: 6px; - outline: 0; - -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); - box-shadow: 0 3px 9px rgba(0, 0, 0, .5); -} -.modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: #000; -} -.modal-backdrop.fade { - filter: alpha(opacity=0); - opacity: 0; -} -.modal-backdrop.in { - filter: alpha(opacity=50); - opacity: .5; -} -.modal-header { - padding: 15px; - border-bottom: 1px solid #e5e5e5; -} -.modal-header .close { - margin-top: -2px; -} -.modal-title { - margin: 0; - line-height: 1.42857143; -} -.modal-body { - position: relative; - padding: 15px; -} -.modal-footer { - padding: 15px; - text-align: right; - border-top: 1px solid #e5e5e5; -} -.modal-footer .btn + .btn { - margin-bottom: 0; - margin-left: 5px; -} -.modal-footer .btn-group .btn + .btn { - margin-left: -1px; -} -.modal-footer .btn-block + .btn-block { - margin-left: 0; -} -.modal-scrollbar-measure { - position: absolute; - top: -9999px; - width: 50px; - height: 50px; - overflow: scroll; -} -@media (min-width: 768px) { - .modal-dialog { - width: 600px; - margin: 30px auto; - } - .modal-content { - -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); - box-shadow: 0 5px 15px rgba(0, 0, 0, .5); - } - .modal-sm { - width: 300px; - } -} -@media (min-width: 992px) { - .modal-lg { - width: 900px; - } -} -.tooltip { - position: absolute; - z-index: 1070; - display: block; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 12px; - font-style: normal; - font-weight: normal; - line-height: 1.42857143; - text-align: left; - text-align: start; - text-decoration: none; - text-shadow: none; - text-transform: none; - letter-spacing: normal; - word-break: normal; - word-spacing: normal; - word-wrap: normal; - white-space: normal; - filter: alpha(opacity=0); - opacity: 0; - - line-break: auto; -} -.tooltip.in { - filter: alpha(opacity=90); - opacity: .9; -} -.tooltip.top { - padding: 5px 0; - margin-top: -3px; -} -.tooltip.right { - padding: 0 5px; - margin-left: 3px; -} -.tooltip.bottom { - padding: 5px 0; - margin-top: 3px; -} -.tooltip.left { - padding: 0 5px; - margin-left: -3px; -} -.tooltip-inner { - max-width: 200px; - padding: 3px 8px; - color: #fff; - text-align: center; - background-color: #000; - border-radius: 4px; -} -.tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} -.tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-width: 5px 5px 0; - border-top-color: #000; -} -.tooltip.top-left .tooltip-arrow { - right: 5px; - bottom: 0; - margin-bottom: -5px; - border-width: 5px 5px 0; - border-top-color: #000; -} -.tooltip.top-right .tooltip-arrow { - bottom: 0; - left: 5px; - margin-bottom: -5px; - border-width: 5px 5px 0; - border-top-color: #000; -} -.tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-width: 5px 5px 5px 0; - border-right-color: #000; -} -.tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-width: 5px 0 5px 5px; - border-left-color: #000; -} -.tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} -.tooltip.bottom-left .tooltip-arrow { - top: 0; - right: 5px; - margin-top: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} -.tooltip.bottom-right .tooltip-arrow { - top: 0; - left: 5px; - margin-top: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; -} -.popover { - position: absolute; - top: 0; - left: 0; - z-index: 1060; - display: none; - max-width: 276px; - padding: 1px; - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - font-style: normal; - font-weight: normal; - line-height: 1.42857143; - text-align: left; - text-align: start; - text-decoration: none; - text-shadow: none; - text-transform: none; - letter-spacing: normal; - word-break: normal; - word-spacing: normal; - word-wrap: normal; - white-space: normal; - background-color: #fff; - -webkit-background-clip: padding-box; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .2); - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); - box-shadow: 0 5px 10px rgba(0, 0, 0, .2); - - line-break: auto; -} -.popover.top { - margin-top: -10px; -} -.popover.right { - margin-left: 10px; -} -.popover.bottom { - margin-top: 10px; -} -.popover.left { - margin-left: -10px; -} -.popover-title { - padding: 8px 14px; - margin: 0; - font-size: 14px; - background-color: #f7f7f7; - border-bottom: 1px solid #ebebeb; - border-radius: 5px 5px 0 0; -} -.popover-content { - padding: 9px 14px; -} -.popover > .arrow, -.popover > .arrow:after { - position: absolute; - display: block; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; -} -.popover > .arrow { - border-width: 11px; -} -.popover > .arrow:after { - content: ""; - border-width: 10px; -} -.popover.top > .arrow { - bottom: -11px; - left: 50%; - margin-left: -11px; - border-top-color: #999; - border-top-color: rgba(0, 0, 0, .25); - border-bottom-width: 0; -} -.popover.top > .arrow:after { - bottom: 1px; - margin-left: -10px; - content: " "; - border-top-color: #fff; - border-bottom-width: 0; -} -.popover.right > .arrow { - top: 50%; - left: -11px; - margin-top: -11px; - border-right-color: #999; - border-right-color: rgba(0, 0, 0, .25); - border-left-width: 0; -} -.popover.right > .arrow:after { - bottom: -10px; - left: 1px; - content: " "; - border-right-color: #fff; - border-left-width: 0; -} -.popover.bottom > .arrow { - top: -11px; - left: 50%; - margin-left: -11px; - border-top-width: 0; - border-bottom-color: #999; - border-bottom-color: rgba(0, 0, 0, .25); -} -.popover.bottom > .arrow:after { - top: 1px; - margin-left: -10px; - content: " "; - border-top-width: 0; - border-bottom-color: #fff; -} -.popover.left > .arrow { - top: 50%; - right: -11px; - margin-top: -11px; - border-right-width: 0; - border-left-color: #999; - border-left-color: rgba(0, 0, 0, .25); -} -.popover.left > .arrow:after { - right: 1px; - bottom: -10px; - content: " "; - border-right-width: 0; - border-left-color: #fff; -} -.carousel { - position: relative; -} -.carousel-inner { - position: relative; - width: 100%; - overflow: hidden; -} -.carousel-inner > .item { - position: relative; - display: none; - -webkit-transition: .6s ease-in-out left; - -o-transition: .6s ease-in-out left; - transition: .6s ease-in-out left; -} -.carousel-inner > .item > img, -.carousel-inner > .item > a > img { - line-height: 1; -} -@media all and (transform-3d), (-webkit-transform-3d) { - .carousel-inner > .item { - -webkit-transition: -webkit-transform .6s ease-in-out; - -o-transition: -o-transform .6s ease-in-out; - transition: transform .6s ease-in-out; - - -webkit-backface-visibility: hidden; - backface-visibility: hidden; - -webkit-perspective: 1000px; - perspective: 1000px; - } - .carousel-inner > .item.next, - .carousel-inner > .item.active.right { - left: 0; - -webkit-transform: translate3d(100%, 0, 0); - transform: translate3d(100%, 0, 0); - } - .carousel-inner > .item.prev, - .carousel-inner > .item.active.left { - left: 0; - -webkit-transform: translate3d(-100%, 0, 0); - transform: translate3d(-100%, 0, 0); - } - .carousel-inner > .item.next.left, - .carousel-inner > .item.prev.right, - .carousel-inner > .item.active { - left: 0; - -webkit-transform: translate3d(0, 0, 0); - transform: translate3d(0, 0, 0); - } -} -.carousel-inner > .active, -.carousel-inner > .next, -.carousel-inner > .prev { - display: block; -} -.carousel-inner > .active { - left: 0; -} -.carousel-inner > .next, -.carousel-inner > .prev { - position: absolute; - top: 0; - width: 100%; -} -.carousel-inner > .next { - left: 100%; -} -.carousel-inner > .prev { - left: -100%; -} -.carousel-inner > .next.left, -.carousel-inner > .prev.right { - left: 0; -} -.carousel-inner > .active.left { - left: -100%; -} -.carousel-inner > .active.right { - left: 100%; -} -.carousel-control { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 15%; - font-size: 20px; - color: #fff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, .6); - background-color: rgba(0, 0, 0, 0); - filter: alpha(opacity=50); - opacity: .5; -} -.carousel-control.left { - background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); - background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); - background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001))); - background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); - background-repeat: repeat-x; -} -.carousel-control.right { - right: 0; - left: auto; - background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); - background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); - background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5))); - background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); - background-repeat: repeat-x; -} -.carousel-control:hover, -.carousel-control:focus { - color: #fff; - text-decoration: none; - filter: alpha(opacity=90); - outline: 0; - opacity: .9; -} -.carousel-control .icon-prev, -.carousel-control .icon-next, -.carousel-control .glyphicon-chevron-left, -.carousel-control .glyphicon-chevron-right { - position: absolute; - top: 50%; - z-index: 5; - display: inline-block; - margin-top: -10px; -} -.carousel-control .icon-prev, -.carousel-control .glyphicon-chevron-left { - left: 50%; - margin-left: -10px; -} -.carousel-control .icon-next, -.carousel-control .glyphicon-chevron-right { - right: 50%; - margin-right: -10px; -} -.carousel-control .icon-prev, -.carousel-control .icon-next { - width: 20px; - height: 20px; - font-family: serif; - line-height: 1; -} -.carousel-control .icon-prev:before { - content: '\2039'; -} -.carousel-control .icon-next:before { - content: '\203a'; -} -.carousel-indicators { - position: absolute; - bottom: 10px; - left: 50%; - z-index: 15; - width: 60%; - padding-left: 0; - margin-left: -30%; - text-align: center; - list-style: none; -} -.carousel-indicators li { - display: inline-block; - width: 10px; - height: 10px; - margin: 1px; - text-indent: -999px; - cursor: pointer; - background-color: #000 \9; - background-color: rgba(0, 0, 0, 0); - border: 1px solid #fff; - border-radius: 10px; -} -.carousel-indicators .active { - width: 12px; - height: 12px; - margin: 0; - background-color: #fff; -} -.carousel-caption { - position: absolute; - right: 15%; - bottom: 20px; - left: 15%; - z-index: 10; - padding-top: 20px; - padding-bottom: 20px; - color: #fff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, .6); -} -.carousel-caption .btn { - text-shadow: none; -} -@media screen and (min-width: 768px) { - .carousel-control .glyphicon-chevron-left, - .carousel-control .glyphicon-chevron-right, - .carousel-control .icon-prev, - .carousel-control .icon-next { - width: 30px; - height: 30px; - margin-top: -10px; - font-size: 30px; - } - .carousel-control .glyphicon-chevron-left, - .carousel-control .icon-prev { - margin-left: -10px; - } - .carousel-control .glyphicon-chevron-right, - .carousel-control .icon-next { - margin-right: -10px; - } - .carousel-caption { - right: 20%; - left: 20%; - padding-bottom: 30px; - } - .carousel-indicators { - bottom: 20px; - } -} -.clearfix:before, -.clearfix:after, -.dl-horizontal dd:before, -.dl-horizontal dd:after, -.container:before, -.container:after, -.container-fluid:before, -.container-fluid:after, -.row:before, -.row:after, -.form-horizontal .form-group:before, -.form-horizontal .form-group:after, -.btn-toolbar:before, -.btn-toolbar:after, -.btn-group-vertical > .btn-group:before, -.btn-group-vertical > .btn-group:after, -.nav:before, -.nav:after, -.navbar:before, -.navbar:after, -.navbar-header:before, -.navbar-header:after, -.navbar-collapse:before, -.navbar-collapse:after, -.pager:before, -.pager:after, -.panel-body:before, -.panel-body:after, -.modal-header:before, -.modal-header:after, -.modal-footer:before, -.modal-footer:after { - display: table; - content: " "; -} -.clearfix:after, -.dl-horizontal dd:after, -.container:after, -.container-fluid:after, -.row:after, -.form-horizontal .form-group:after, -.btn-toolbar:after, -.btn-group-vertical > .btn-group:after, -.nav:after, -.navbar:after, -.navbar-header:after, -.navbar-collapse:after, -.pager:after, -.panel-body:after, -.modal-header:after, -.modal-footer:after { - clear: both; -} -.center-block { - display: block; - margin-right: auto; - margin-left: auto; -} -.pull-right { - float: right !important; -} -.pull-left { - float: left !important; -} -.hide { - display: none !important; -} -.show { - display: block !important; -} -.invisible { - visibility: hidden; -} -.text-hide { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; -} -.hidden { - display: none !important; -} -.affix { - position: fixed; -} -@-ms-viewport { - width: device-width; -} -.visible-xs, -.visible-sm, -.visible-md, -.visible-lg { - display: none !important; -} -.visible-xs-block, -.visible-xs-inline, -.visible-xs-inline-block, -.visible-sm-block, -.visible-sm-inline, -.visible-sm-inline-block, -.visible-md-block, -.visible-md-inline, -.visible-md-inline-block, -.visible-lg-block, -.visible-lg-inline, -.visible-lg-inline-block { - display: none !important; -} -@media (max-width: 767px) { - .visible-xs { - display: block !important; - } - table.visible-xs { - display: table !important; - } - tr.visible-xs { - display: table-row !important; - } - th.visible-xs, - td.visible-xs { - display: table-cell !important; - } -} -@media (max-width: 767px) { - .visible-xs-block { - display: block !important; - } -} -@media (max-width: 767px) { - .visible-xs-inline { - display: inline !important; - } -} -@media (max-width: 767px) { - .visible-xs-inline-block { - display: inline-block !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm { - display: block !important; - } - table.visible-sm { - display: table !important; - } - tr.visible-sm { - display: table-row !important; - } - th.visible-sm, - td.visible-sm { - display: table-cell !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm-block { - display: block !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm-inline { - display: inline !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .visible-sm-inline-block { - display: inline-block !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md { - display: block !important; - } - table.visible-md { - display: table !important; - } - tr.visible-md { - display: table-row !important; - } - th.visible-md, - td.visible-md { - display: table-cell !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md-block { - display: block !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md-inline { - display: inline !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .visible-md-inline-block { - display: inline-block !important; - } -} -@media (min-width: 1200px) { - .visible-lg { - display: block !important; - } - table.visible-lg { - display: table !important; - } - tr.visible-lg { - display: table-row !important; - } - th.visible-lg, - td.visible-lg { - display: table-cell !important; - } -} -@media (min-width: 1200px) { - .visible-lg-block { - display: block !important; - } -} -@media (min-width: 1200px) { - .visible-lg-inline { - display: inline !important; - } -} -@media (min-width: 1200px) { - .visible-lg-inline-block { - display: inline-block !important; - } -} -@media (max-width: 767px) { - .hidden-xs { - display: none !important; - } -} -@media (min-width: 768px) and (max-width: 991px) { - .hidden-sm { - display: none !important; - } -} -@media (min-width: 992px) and (max-width: 1199px) { - .hidden-md { - display: none !important; - } -} -@media (min-width: 1200px) { - .hidden-lg { - display: none !important; - } -} -.visible-print { - display: none !important; -} -@media print { - .visible-print { - display: block !important; - } - table.visible-print { - display: table !important; - } - tr.visible-print { - display: table-row !important; - } - th.visible-print, - td.visible-print { - display: table-cell !important; - } -} -.visible-print-block { - display: none !important; -} -@media print { - .visible-print-block { - display: block !important; - } -} -.visible-print-inline { - display: none !important; -} -@media print { - .visible-print-inline { - display: inline !important; - } -} -.visible-print-inline-block { - display: none !important; -} -@media print { - .visible-print-inline-block { - display: inline-block !important; - } -} -@media print { - .hidden-print { - display: none !important; - } -} -/*# sourceMappingURL=bootstrap.css.map */ diff --git a/backend/_pv_1_3_5/static/css/bootstrap.css.map b/backend/_pv_1_3_5/static/css/bootstrap.css.map deleted file mode 100755 index f010c82d1..000000000 --- a/backend/_pv_1_3_5/static/css/bootstrap.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["bootstrap.css","less/normalize.less","less/print.less","less/glyphicons.less","less/scaffolding.less","less/mixins/vendor-prefixes.less","less/mixins/tab-focus.less","less/mixins/image.less","less/type.less","less/mixins/text-emphasis.less","less/mixins/background-variant.less","less/mixins/text-overflow.less","less/code.less","less/grid.less","less/mixins/grid.less","less/mixins/grid-framework.less","less/tables.less","less/mixins/table-row.less","less/forms.less","less/mixins/forms.less","less/buttons.less","less/mixins/buttons.less","less/mixins/opacity.less","less/component-animations.less","less/dropdowns.less","less/mixins/nav-divider.less","less/mixins/reset-filter.less","less/button-groups.less","less/mixins/border-radius.less","less/input-groups.less","less/navs.less","less/navbar.less","less/mixins/nav-vertical-align.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/mixins/pagination.less","less/pager.less","less/labels.less","less/mixins/labels.less","less/badges.less","less/jumbotron.less","less/thumbnails.less","less/alerts.less","less/mixins/alerts.less","less/progress-bars.less","less/mixins/gradients.less","less/mixins/progress-bar.less","less/media.less","less/list-group.less","less/mixins/list-group.less","less/panels.less","less/mixins/panels.less","less/responsive-embed.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/mixins/reset-text.less","less/popovers.less","less/carousel.less","less/mixins/clearfix.less","less/mixins/center-block.less","less/mixins/hide-text.less","less/responsive-utilities.less","less/mixins/responsive-visibility.less"],"names":[],"mappings":"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AW,iBAAA;CHsR9C;AGrRmC;EAAW,iBAAA;CHwR9C;AGvRmC;EAAW,iBAAA;CH0R9C;AGzRmC;EAAW,iBAAA;CH4R9C;AG3RmC;EAAW,iBAAA;CH8R9C;AG7RmC;EAAW,iBAAA;CHgS9C;AG/RmC;EAAW,iBAAA;CHkS9C;AGjSmC;EAAW,iBAAA;CHoS9C;AGnSmC;EAAW,iBAAA;CHsS9C;AGrSmC;EAAW,iBAAA;CHwS9C;AGvSmC;EAAW,iBAAA;CH0S9C;AGzSmC;EAAW,iBAAA;CH4S9C;AG3SmC;EAAW,iBAAA;CH8S9C;AG7SmC;EAAW,iBAAA;CHgT9C;AG/SmC;EAAW,iBAAA;CHkT9C;AGjTmC;EAAW,iBAAA;CHoT9C;AGnTmC;EAAW,iBAAA;CHsT9C;AGrTmC;EAAW,iBAAA;CHwT9C;AGvTmC;EAAW,iBAAA;CH0T9C;AGzTmC;EAAW,iBAAA;CH4T9C;AG3TmC;EAAW,iBAAA;CH8T9C;AG7TmC;EAAW,iBAAA;CHgU9C;AG/TmC;EAAW,iBAAA;CHkU9C;AGjUmC;EAAW,iBAAA;CHoU9C;AGnUmC;EAAW,iBAAA;CHsU9C;AGrUmC;EAAW,iBAAA;CHwU9C;AGvUmC;EAAW,iBAAA;CH0U9C;AGzUmC;EAAW,iBAAA;CH4U9C;AG3UmC;EAAW,iBAAA;CH8U9C;AG7UmC;EAAW,iBAAA;CHgV9C;AG/UmC;EAAW,iBAAA;CHkV9C;AGjVmC;EAAW,iBAAA;CHoV9C;AGnVmC;EAAW,iBAAA;CHsV9C;AGrVmC;EAAW,iBAAA;CHwV9C;AGvVmC;EAAW,iBAAA;CH0V9C;AGzVmC;EAAW,iBAAA;CH4V9C;AG3VmC;EAAW,iBAAA;CH8V9C;AG7VmC;EAAW,iBAAA;CHgW9C;AG/VmC;EAAW,iBAAA;CHkW9C;AGjWmC;EAAW,iBAAA;CHoW9C;AGnWmC;EAAW,iBAAA;CHsW9C;AGrWmC;EAAW,iBAAA;CHwW9C;AGvWmC;EAAW,iBAAA;CH0W9C;AGzWmC;EAAW,iBAAA;CH4W9C;AG3WmC;EAAW,iBAAA;CH8W9C;AG7WmC;EAAW,iBAAA;CHgX9C;AG/WmC;EAAW,iBAAA;CHkX9C;AGjXmC;EAAW,iBAAA;CHoX9C;AGnXmC;EAAW,iBAAA;CHsX9C;AGrXmC;EAAW,iBAAA;CHwX9C;AGvXmC;EAAW,iBAAA;CH0X9C;AGzXmC;EAAW,iBAAA;CH4X9C;AG3XmC;EAAW,iBAAA;CH8X9C;AG7XmC;EAAW,iBAAA;CHgY9C;AG/XmC;EAAW,iBAAA;CHkY9C;AGjYmC;EAAW,iBAAA;CHoY9C;AGnYmC;EAAW,iBAAA;CHsY9C;AGrYmC;EAAW,iBAAA;CHwY9C;AGvYmC;EAAW,iBAAA;CH0Y9C;AGzYmC;EAAW,iBAAA;CH4Y9C;AG3YmC;EAAW,iBAAA;CH8Y9C;AG7YmC;EAAW,iBAAA;CHgZ9C;AG/YmC;EAAW,iBAAA;CHkZ9C;AGjZmC;EAAW,iBAAA;CHoZ9C;AGnZmC;EAAW,iBAAA;CHsZ9C;AGrZmC;EAAW,iBAAA;CHwZ9C;AGvZmC;EAAW,iBAAA;CH0Z9C;AGzZmC;EAAW,iBAAA;CH4Z9C;AG3ZmC;EAAW,iBAAA;CH8Z9C;AG7ZmC;EAAW,iBAAA;CHga9C;AG/ZmC;EAAW,iBAAA;CHka9C;AGjamC;EAAW,iBAAA;CHoa9C;AGnamC;EAAW,iBAAA;CHsa9C;AGramC;EAAW,iBAAA;CHwa9C;AGvamC;EAAW,iBAAA;CH0a9C;AGzamC;EAAW,iBAAA;CH4a9C;AG3amC;EAAW,iBAAA;CH8a9C;AG7amC;EAAW,iBAAA;CHgb9C;AG/amC;EAAW,iBAAA;CHkb9C;AGjbmC;EAAW,iBAAA;CHob9C;AGnbmC;EAAW,iBAAA;CHsb9C;AGrbmC;EAAW,iBAAA;CHwb9C;AGvbmC;EAAW,iBAAA;CH0b9C;AGzbmC;EAAW,iBAAA;CH4b9C;AG3bmC;EAAW,iBAAA;CH8b9C;AG7bmC;EAAW,iBAAA;CHgc9C;AG/bmC;EAAW,iBAAA;CHkc9C;AGjcmC;EAAW,iBAAA;CHoc9C;AGncmC;EAAW,iBAAA;CHsc9C;AGrcmC;EAAW,iBAAA;CHwc9C;AGvcmC;EAAW,iBAAA;CH0c9C;AGzcmC;EAAW,iBAAA;CH4c9C;AG3cmC;EAAW,iBAAA;CH8c9C;AG7cmC;EAAW,iBAAA;CHgd9C;AG/cmC;EAAW,iBAAA;CHkd9C;AGjdmC;EAAW,iBAAA;CHod9C;AGndmC;EAAW,iBAAA;CHsd9C;AGrdmC;EAAW,iBAAA;CHwd9C;AGvdmC;EAAW,iBAAA;CH0d9C;AGzdmC;EAAW,iBAAA;CH4d9C;AG3dmC;EAAW,iBAAA;CH8d9C;AG7dmC;EAAW,iBAAA;CHge9C;AG/dmC;EAAW,iBAAA;CHke9C;AGjemC;EAAW,iBAAA;CHoe9C;AGnemC;EAAW,iBAAA;CHse9C;AGremC;EAAW,iBAAA;CHwe9C;AGvemC;EAAW,iBAAA;CH0e9C;AGzemC;EAAW,iBAAA;CH4e9C;AG3emC;EAAW,iBAAA;CH8e9C;AG7emC;EAAW,iBAAA;CHgf9C;AG/emC;EAAW,iBAAA;CHkf9C;AGjfmC;EAAW,iBAAA;CHof9C;AGnfmC;EAAW,iBAAA;CHsf9C;AGrfmC;EAAW,iBAAA;CHwf9C;AGvfmC;EAAW,iBAAA;CH0f9C;AGzfmC;EAAW,iBAAA;CH4f9C;AG3fmC;EAAW,iBAAA;CH8f9C;AG7fmC;EAAW,iBAAA;CHggB9C;AG/fmC;EAAW,iBAAA;CHkgB9C;AGjgBmC;EAAW,iBAAA;CHogB9C;AGngBmC;EAAW,iBAAA;CHsgB9C;AGrgBmC;EAAW,iBAAA;CHwgB9C;AGvgBmC;EAAW,iBAAA;CH0gB9C;AGzgBmC;EAAW,iBAAA;CH4gB9C;AG3gBmC;EAAW,iBAAA;CH8gB9C;AG7gBmC;EAAW,iBAAA;CHghB9C;AG/gBmC;EAAW,iBAAA;CHkhB9C;AGjhBmC;EAAW,iBAAA;CHohB9C;AGnhBmC;EAAW,iBAAA;CHshB9C;AGrhBmC;EAAW,iBAAA;CHwhB9C;AGvhBmC;EAAW,iBAAA;CH0hB9C;AGzhBmC;EAAW,iBAAA;CH4hB9C;AG3hBmC;EAAW,iBAAA;CH8hB9C;AG7hBmC;EAAW,iBAAA;CHgiB9C;AG/hBmC;EAAW,iBAAA;CHkiB9C;AGjiBmC;EAAW,iBAAA;CHoiB9C;AGniBmC;EAAW,iBAAA;CHsiB9C;AGriBmC;EAAW,iBAAA;CHwiB9C;AGviBmC;EAAW,iBAAA;CH0iB9C;AGziBmC;EAAW,iBAAA;CH4iB9C;AG3iBmC;EAAW,iBAAA;CH8iB9C;AG7iBmC;EAAW,iBAAA;CHgjB9C;AG/iBmC;EAAW,iBAAA;CHkjB9C;AGjjBmC;EAAW,iBAAA;CHojB9C;AGnjBmC;EAAW,iBAAA;CHsjB9C;AGrjBmC;EAAW,iBAAA;CHwjB9C;AGvjBmC;EAAW,iBAAA;CH0jB9C;AGzjBmC;EAAW,iBAAA;CH4jB9C;AG3jBmC;EAAW,iBAAA;CH8jB9C;AG7jBmC;EAAW,iBAAA;CHgkB9C;AG/jBmC;EAAW,iBAAA;CHkkB9C;AGjkBmC;EAAW,iBAAA;CHokB9C;AGnkBmC;EAAW,iBAAA;CHskB9C;AGrkBmC;EAAW,iBAAA;CHwkB9C;AGvkBmC;EAAW,iBAAA;CH0kB9C;AGzkBmC;EAAW,iBAAA;CH4kB9C;AG3kBmC;EAAW,iBAAA;CH8kB9C;AG7kBmC;EAAW,iBAAA;CHglB9C;AG/kBmC;EAAW,iBAAA;CHklB9C;AGjlBmC;EAAW,iBAAA;CHolB9C;AGnlBmC;EAAW,iBAAA;CHslB9C;AGrlBmC;EAAW,iBAAA;CHwlB9C;AGvlBmC;EAAW,iBAAA;CH0lB9C;AGzlBmC;EAAW,iBAAA;CH4lB9C;AG3lBmC;EAAW,iBAAA;CH8lB9C;AG7lBmC;EAAW,iBAAA;CHgmB9C;AG/lBmC;EAAW,iBAAA;CHkmB9C;AGjmBmC;EAAW,iBAAA;CHomB9C;AGnmBmC;EAAW,iBAAA;CHsmB9C;AGrmBmC;EAAW,iBAAA;CHwmB9C;AGvmBmC;EAAW,iBAAA;CH0mB9C;AGzmBmC;EAAW,iBAAA;CH4mB9C;AG3mBmC;EAAW,iBAAA;CH8mB9C;AG7mBmC;EAAW,iBAAA;CHgnB9C;AG/mBmC;EAAW,iBAAA;CHknB9C;AGjnBmC;EAAW,iBAAA;CHonB9C;AGnnBmC;EAAW,iBAAA;CHsnB9C;AGrnBmC;EAAW,iBAAA;CHwnB9C;AGvnBmC;EAAW,iBAAA;CH0nB9C;AGznBmC;EAAW,iBAAA;CH4nB9C;AG3nBmC;EAAW,iBAAA;CH8nB9C;AG7nBmC;EAAW,iBAAA;CHgoB9C;AG/nBmC;EAAW,iBAAA;CHkoB9C;AGjoBmC;EAAW,iBAAA;CHooB9C;AGnoBmC;EAAW,iBAAA;CHsoB9C;AGroBmC;EAAW,iBAAA;CHwoB9C;AG/nBmC;EAAW,iBAAA;CHkoB9C;AGjoBmC;EAAW,iBAAA;CHooB9C;AGnoBmC;EAAW,iBAAA;CHsoB9C;AGroBmC;EAAW,iBAAA;CHwoB9C;AGvoBmC;EAAW,iBAAA;CH0oB9C;AGzoBmC;EAAW,iBAAA;CH4oB9C;AG3oBmC;EAAW,iBAAA;CH8oB9C;AG7oBmC;EAAW,iBAAA;CHgpB9C;AG/oBmC;EAAW,iBAAA;CHkpB9C;AGjpBmC;EAAW,iBAAA;CHopB9C;AGnpBmC;EAAW,iBAAA;CHspB9C;AGrpBmC;EAAW,iBAAA;CHwpB9C;AGvpBmC;EAAW,iBAAA;CH0pB9C;AGzpBmC;EAAW,iBAAA;CH4pB9C;AG3pBmC;EAAW,iBAAA;CH8pB9C;AG7pBmC;EAAW,iBAAA;CHgqB9C;AG/pBmC;EAAW,iBAAA;CHkqB9C;AGjqBmC;EAAW,iBAAA;CHoqB9C;AGnqBmC;EAAW,iBAAA;CHsqB9C;AGrqBmC;EAAW,iBAAA;CHwqB9C;AGvqBmC;EAAW,iBAAA;CH0qB9C;AGzqBmC;EAAW,iBAAA;CH4qB9C;AG3qBmC;EAAW,iBAAA;CH8qB9C;AG7qBmC;EAAW,iBAAA;CHgrB9C;AG/qBmC;EAAW,iBAAA;CHkrB9C;AGjrBmC;EAAW,iBAAA;CHorB9C;AGnrBmC;EAAW,iBAAA;CHsrB9C;AGrrBmC;EAAW,iBAAA;CHwrB9C;AGvrBmC;EAAW,iBAAA;CH0rB9C;AGzrBmC;EAAW,iBAAA;CH4rB9C;AG3rBmC;EAAW,iBAAA;CH8rB9C;AG7rBmC;EAAW,iBAAA;CHgsB9C;AG/rBmC;EAAW,iBAAA;CHksB9C;AGjsBmC;EAAW,iBAAA;CHosB9C;AGnsBmC;EAAW,iBAAA;CHssB9C;AGrsBmC;EAAW,iBAAA;CHwsB9C;AGvsBmC;EAAW,iBAAA;CH0sB9C;AGzsBmC;EAAW,iBAAA;CH4sB9C;AG3sBmC;EAAW,iBAAA;CH8sB9C;AG7sBmC;EAAW,iBAAA;CHgtB9C;AG/sBmC;EAAW,iBAAA;CHktB9C;AGjtBmC;EAAW,iBAAA;CHotB9C;AGntBmC;EAAW,iBAAA;CHstB9C;AGrtBmC;EAAW,iBAAA;CHwtB9C;AGvtBmC;EAAW,iBAAA;CH0tB9C;AGztBmC;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ukDH;AexkDC;EACE,oBAAA;Cf0kDH;Ae3kDC;EACE,WAAA;Cf6kDH;Ae9kDC;EACE,oBAAA;CfglDH;AejlDC;EACE,mBAAA;CfmlDH;Ae/kDC;EACE,YAAA;CfilDH;AejmDC;EACE,WAAA;CfmmDH;AepmDC;EACE,mBAAA;CfsmDH;AevmDC;EACE,mBAAA;CfymDH;Ae1mDC;EACE,UAAA;Cf4mDH;Ae7mDC;EACE,mBAAA;Cf+mDH;AehnDC;EACE,mBAAA;CfknDH;AennDC;EACE,UAAA;CfqnDH;AetnDC;EACE,mBAAA;CfwnDH;AeznDC;EACE,mBAAA;Cf2nDH;Ae5nDC;EACE,UAAA;Cf8nDH;Ae/nDC;EACE,mBAAA;CfioDH;AeloDC;EACE,kBAAA;CfooDH;AehoDC;EACE,WAAA;CfkoDH;AepnDC;EACE,kBAAA;CfsnDH;AevnDC;EACE,0BAAA;CfynDH;Ae1nDC;EACE,0BAAA;Cf4nDH;Ae7nDC;EACE,iBAAA;Cf+nDH;AehoDC;EACE,0BAAA;CfkoDH;AenoDC;EACE,0BAAA;CfqoDH;AetoDC;EACE,iBAAA;CfwoDH;AezoDC;EACE,0BAAA;Cf2oDH;Ae5oDC;EACE,0BAAA;Cf8oDH;Ae/oDC;EACE,iBAAA;CfipDH;AelpDC;EACE,0BAAA;CfopDH;AerpDC;EACE,yBAAA;CfupDH;AexpDC;EACE,gBAAA;Cf0pDH;Aa1pDD;EElCI;IACE,YAAA;Gf+rDH;EexrDD;IACE,YAAA;Gf0rDD;Ee3rDD;IACE,oBAAA;Gf6rDD;Ee9rDD;IACE,oBAAA;GfgsDD;EejsDD;IACE,WAAA;GfmsDD;EepsDD;IACE,oBAAA;GfssDD;EevsDD;IACE,oBAAA;GfysDD;Ee1sDD;IACE,WAAA;Gf4sDD;Ee7sDD;IACE,oBAAA;Gf+sDD;EehtDD;IACE,oBAAA;GfktDD;EentDD;IACE,WAAA;GfqtDD;EettDD;IACE,oBAAA;GfwtDD;EeztDD;IACE,mBAAA;Gf2tDD;Ee7sDD;IACE,YAAA;Gf+sDD;EehtDD;IACE,oBAAA;GfktDD;EentDD;IACE,oBAAA;GfqtDD;EettDD;IACE,WAAA;GfwtDD;EeztDD;IACE,oBAAA;Gf2tDD;Ee5tDD;IACE,oBAAA;Gf8tDD;Ee/tDD;IACE,WAAA;GfiuDD;EeluDD;IACE,oBAAA;GfouDD;EeruDD;IACE,oBAAA;GfuuDD;EexuDD;IACE,WAAA;Gf0uDD;Ee3uDD;IACE,oBAAA;Gf6uDD;Ee9uDD;IACE,mBAAA;GfgvDD;Ee5uDD;IACE,YAAA;Gf8uDD;Ee9vDD;IACE,WAAA;GfgwDD;EejwDD;IACE,mBAAA;GfmwDD;EepwDD;IACE,mBAAA;GfswDD;EevwDD;IACE,UAAA;GfywDD;Ee1wDD;IACE,mBAAA;Gf4wDD;Ee7wDD;IACE,mBAAA;Gf+wDD;EehxDD;IACE,UAAA;GfkxDD;EenxDD;IACE,mBAAA;GfqxDD;EetxDD;IACE,mBAAA;GfwxDD;EezxDD;IACE,UAAA;Gf2xDD;Ee5xDD;IACE,mBAAA;Gf8xDD;Ee/xDD;IACE,kBAAA;GfiyDD;Ee7xDD;IACE,WAAA;Gf+xDD;EejxDD;IACE,kBAAA;GfmxDD;EepxDD;IACE,0BAAA;GfsxDD;EevxDD;IACE,0BAAA;GfyxDD;Ee1xDD;IACE,iBAAA;Gf4xDD;Ee7xDD;IACE,0BAAA;Gf+xDD;EehyDD;IACE,0BAAA;GfkyDD;EenyDD;IACE,iBAAA;GfqyDD;EetyDD;IACE,0BAAA;GfwyDD;EezyDD;IACE,0BAAA;Gf2yDD;Ee5yDD;IACE,iBAAA;Gf8yDD;Ee/yDD;IACE,0BAAA;GfizDD;EelzDD;IACE,yBAAA;GfozDD;EerzDD;IACE,gBAAA;GfuzDD;CACF;Aa/yDD;EE3CI;IACE,YAAA;Gf61DH;Eet1DD;IACE,YAAA;Gfw1DD;Eez1DD;IACE,oBAAA;Gf21DD;Ee51DD;IACE,oBAAA;Gf81DD;Ee/1DD;IACE,WAAA;Gfi2DD;Eel2DD;IACE,oBAAA;Gfo2DD;Eer2DD;IACE,oBAAA;Gfu2DD;Eex2DD;IACE,WAAA;Gf02DD;Ee32DD;IACE,oBAAA;Gf62DD;Ee92DD;IACE,oBAAA;Gfg3DD;Eej3DD;IACE,WAAA;Gfm3DD;Eep3DD;IACE,oBAAA;Gfs3DD;Eev3DD;IACE,mBAAA;Gfy3DD;Ee32DD;IACE,YAAA;Gf62DD;Ee92DD;IACE,oBAAA;Gfg3DD;Eej3DD;IACE,oBAAA;Gfm3DD;Eep3DD;IACE,WAAA;Gfs3DD;Eev3DD;IACE,oBAAA;Gfy3DD;Ee13DD;IACE,oBAAA;Gf43DD;Ee73DD;IACE,WAAA;Gf+3DD;Eeh4DD;IACE,oBAAA;Gfk4DD;Een4DD;IACE,oBAAA;Gfq4DD;Eet4DD;IACE,WAAA;Gfw4DD;Eez4DD;IACE,oBAAA;Gf24DD;Ee54DD;IACE,mBAAA;Gf84DD;Ee14DD;IACE,YAAA;Gf44DD;Ee55DD;IACE,WAAA;Gf85DD;Ee/5DD;IACE,mBAAA;Gfi6DD;Eel6DD;IACE,mBAAA;Gfo6DD;Eer6DD;IACE,UAAA;Gfu6DD;Eex6DD;IACE,mBAAA;Gf06DD;Ee36DD;IACE,mBAAA;Gf66DD;Ee96DD;IACE,UAAA;Gfg7DD;Eej7DD;IACE,mBAAA;Gfm7DD;Eep7DD;IACE,mBAAA;Gfs7DD;Eev7DD;IACE,UAAA;Gfy7DD;Ee17DD;IACE,mBAAA;Gf47DD;Ee77DD;IACE,kBAAA;Gf+7DD;Ee37DD;IACE,WAAA;Gf67DD;Ee/6DD;IACE,kBAAA;Gfi7DD;Eel7DD;IACE,0BAAA;Gfo7DD;Eer7DD;IACE,0BAAA;Gfu7DD;Eex7DD;IACE,iBAAA;Gf07DD;Ee37DD;IACE,0BAAA;Gf67DD;Ee97DD;IACE,0BAAA;Gfg8DD;Eej8DD;IACE,iBAAA;Gfm8DD;Eep8DD;IACE,0BAAA;Gfs8DD;Eev8DD;IACE,0BAAA;Gfy8DD;Ee18DD;IACE,iBAAA;Gf48DD;Ee78DD;IACE,0BAAA;Gf+8DD;Eeh9DD;IACE,yBAAA;Gfk9DD;Een9DD;IACE,gBAAA;Gfq9DD;CACF;Aa18DD;EE9CI;IACE,YAAA;Gf2/DH;Eep/DD;IACE,YAAA;Gfs/DD;Eev/DD;IACE,oBAAA;Gfy/DD;Ee1/DD;IACE,oBAAA;Gf4/DD;Ee7/DD;IACE,WAAA;Gf+/DD;EehgED;IACE,oBAAA;GfkgED;EengED;IACE,oBAAA;GfqgED;EetgED;IACE,WAAA;GfwgED;EezgED;IACE,oBAAA;Gf2gED;Ee5gED;IACE,oBAAA;Gf8gED;Ee/gED;IACE,WAAA;GfihED;EelhED;IACE,oBAAA;GfohED;EerhED;IACE,mBAAA;GfuhED;EezgED;IACE,YAAA;Gf2gED;Ee5gED;IACE,oBAAA;Gf8gED;Ee/gED;IACE,oBAAA;GfihED;EelhED;IACE,WAAA;GfohED;EerhED;IACE,oBAAA;GfuhED;EexhED;IACE,oBAAA;Gf0hED;Ee3hED;IACE,WAAA;Gf6hED;Ee9hED;IACE,oBAAA;GfgiED;EejiED;IACE,oBAAA;GfmiED;EepiED;IACE,WAAA;GfsiED;EeviED;IACE,oBAAA;GfyiED;Ee1iED;IACE,mBAAA;Gf4iED;EexiED;IACE,YAAA;Gf0iED;Ee1jED;IACE,WAAA;Gf4jED;Ee7jED;IACE,mBAAA;Gf+jED;EehkED;IACE,mBAAA;GfkkED;EenkED;IACE,UAAA;GfqkED;EetkED;IACE,mBAAA;GfwkED;EezkED;IACE,mBAAA;Gf2kED;Ee5kED;IACE,UAAA;Gf8kED;Ee/kED;IACE,mBAAA;GfilED;EellED;IACE,mBAAA;GfolED;EerlED;IACE,UAAA;GfulED;EexlED;IACE,mBAAA;Gf0lED;Ee3lED;IACE,kBAAA;Gf6lED;EezlED;IACE,WAAA;Gf2lED;Ee7kED;IACE,kBAAA;Gf+kED;EehlED;IACE,0BAAA;GfklED;EenlED;IACE,0BAAA;GfqlED;EetlED;IACE,iBAAA;GfwlED;EezlED;IACE,0BAAA;Gf2lED;Ee5lED;IACE,0BAAA;Gf8lED;Ee/lED;IACE,iBAAA;GfimED;EelmED;IACE,0BAAA;GfomED;EermED;IACE,0BAAA;GfumED;EexmED;IACE,iBAAA;Gf0mED;Ee3mED;IACE,0BAAA;Gf6mED;Ee9mED;IACE,yBAAA;GfgnED;EejnED;IACE,gBAAA;GfmnED;CACF;AgBvrED;EACE,8BAAA;ChByrED;AgBvrED;EACE,iBAAA;EACA,oBAAA;EACA,eAAA;EACA,iBAAA;ChByrED;AgBvrED;EACE,iBAAA;ChByrED;AgBnrED;EACE,YAAA;EACA,gBA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","file":"bootstrap.css","sourcesContent":["/*!\n * Bootstrap v3.3.7 (http://getbootstrap.com)\n * Copyright 2011-2016 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\nhtml {\n font-family: sans-serif;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: 1px dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\nmark {\n background: #ff0;\n color: #000;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\nsup {\n top: -0.5em;\n}\nsub {\n bottom: -0.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n box-sizing: content-box;\n height: 0;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit;\n font: inherit;\n margin: 0;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: textfield;\n box-sizing: content-box;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\nlegend {\n border: 0;\n padding: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important;\n box-shadow: none !important;\n text-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('../fonts/glyphicons-halflings-regular.eot');\n src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\002a\";\n}\n.glyphicon-plus:before {\n content: \"\\002b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333333;\n background-color: #fff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n padding: 4px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: all 0.2s ease-in-out;\n -o-transition: all 0.2s ease-in-out;\n transition: all 0.2s ease-in-out;\n display: inline-block;\n max-width: 100%;\n height: auto;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eeeeee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: normal;\n line-height: 1;\n color: #777777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n background-color: #fcf8e3;\n padding: .2em;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover,\na.text-primary:focus {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover,\na.text-success:focus {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover,\na.text-info:focus {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover,\na.text-warning:focus {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover,\na.text-danger:focus {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover,\na.bg-primary:focus {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover,\na.bg-success:focus {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover,\na.bg-info:focus {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover,\na.bg-warning:focus {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover,\na.bg-danger:focus {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eeeeee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n list-style: none;\n margin-left: -5px;\n}\n.list-inline > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n clear: left;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted #777777;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eeeeee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: '\\2014 \\00A0';\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid #eeeeee;\n border-left: 0;\n text-align: right;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: '';\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: '\\00A0 \\2014';\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #fff;\n background-color: #333;\n border-radius: 3px;\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n word-break: break-all;\n word-wrap: break-word;\n color: #333333;\n background-color: #f5f5f5;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n.row {\n margin-left: -15px;\n margin-right: -15px;\n}\n.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0%;\n}\n@media (min-width: 768px) {\n .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 992px) {\n .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0%;\n }\n}\ntable {\n background-color: transparent;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #ddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #ddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #ddd;\n}\n.table .table {\n background-color: #fff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #ddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\ntable col[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-column;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-cell;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #ddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n min-width: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: bold;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n background-color: #fff;\n background-image: none;\n border: 1px solid #ccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.form-control::-moz-placeholder {\n color: #999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999;\n}\n.form-control::-ms-expand {\n border: 0;\n background-color: transparent;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eeeeee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"].form-control,\n input[type=\"time\"].form-control,\n input[type=\"datetime-local\"].form-control,\n input[type=\"month\"].form-control {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-left: -20px;\n margin-top: 4px \\9;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.form-control-static {\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n min-height: 34px;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-left: 0;\n padding-right: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.form-group-sm select.form-control {\n height: 30px;\n line-height: 30px;\n}\n.form-group-sm textarea.form-control,\n.form-group-sm select[multiple].form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n min-height: 32px;\n padding: 6px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.form-group-lg select.form-control {\n height: 46px;\n line-height: 46px;\n}\n.form-group-lg textarea.form-control,\n.form-group-lg select[multiple].form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n min-height: 38px;\n padding: 11px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n border-color: #3c763d;\n background-color: #dff0d8;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n border-color: #8a6d3b;\n background-color: #fcf8e3;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n border-color: #a94442;\n background-color: #f2dede;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: 7px;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-left: -15px;\n margin-right: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n text-align: right;\n margin-bottom: 0;\n padding-top: 7px;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 11px;\n font-size: 18px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n font-size: 12px;\n }\n}\n.btn {\n display: inline-block;\n margin-bottom: 0;\n font-weight: normal;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none;\n border: 1px solid transparent;\n white-space: nowrap;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n border-radius: 4px;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n outline: 0;\n background-image: none;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n cursor: not-allowed;\n opacity: 0.65;\n filter: alpha(opacity=65);\n -webkit-box-shadow: none;\n box-shadow: none;\n}\na.btn.disabled,\nfieldset[disabled] a.btn {\n pointer-events: none;\n}\n.btn-default {\n color: #333;\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default:focus,\n.btn-default.focus {\n color: #333;\n background-color: #e6e6e6;\n border-color: #8c8c8c;\n}\n.btn-default:hover {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active:hover,\n.btn-default.active:hover,\n.open > .dropdown-toggle.btn-default:hover,\n.btn-default:active:focus,\n.btn-default.active:focus,\n.open > .dropdown-toggle.btn-default:focus,\n.btn-default:active.focus,\n.btn-default.active.focus,\n.open > .dropdown-toggle.btn-default.focus {\n color: #333;\n background-color: #d4d4d4;\n border-color: #8c8c8c;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n background-image: none;\n}\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus {\n background-color: #fff;\n border-color: #ccc;\n}\n.btn-default .badge {\n color: #fff;\n background-color: #333;\n}\n.btn-primary {\n color: #fff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:focus,\n.btn-primary.focus {\n color: #fff;\n background-color: #286090;\n border-color: #122b40;\n}\n.btn-primary:hover {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #fff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active:hover,\n.btn-primary.active:hover,\n.open > .dropdown-toggle.btn-primary:hover,\n.btn-primary:active:focus,\n.btn-primary.active:focus,\n.open > .dropdown-toggle.btn-primary:focus,\n.btn-primary:active.focus,\n.btn-primary.active.focus,\n.open > .dropdown-toggle.btn-primary.focus {\n color: #fff;\n background-color: #204d74;\n border-color: #122b40;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n background-image: none;\n}\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.btn-success {\n color: #fff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:focus,\n.btn-success.focus {\n color: #fff;\n background-color: #449d44;\n border-color: #255625;\n}\n.btn-success:hover {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #fff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active:hover,\n.btn-success.active:hover,\n.open > .dropdown-toggle.btn-success:hover,\n.btn-success:active:focus,\n.btn-success.active:focus,\n.open > .dropdown-toggle.btn-success:focus,\n.btn-success:active.focus,\n.btn-success.active.focus,\n.open > .dropdown-toggle.btn-success.focus {\n color: #fff;\n background-color: #398439;\n border-color: #255625;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n background-image: none;\n}\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #fff;\n}\n.btn-info {\n color: #fff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:focus,\n.btn-info.focus {\n color: #fff;\n background-color: #31b0d5;\n border-color: #1b6d85;\n}\n.btn-info:hover {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #fff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active:hover,\n.btn-info.active:hover,\n.open > .dropdown-toggle.btn-info:hover,\n.btn-info:active:focus,\n.btn-info.active:focus,\n.open > .dropdown-toggle.btn-info:focus,\n.btn-info:active.focus,\n.btn-info.active.focus,\n.open > .dropdown-toggle.btn-info.focus {\n color: #fff;\n background-color: #269abc;\n border-color: #1b6d85;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n background-image: none;\n}\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #fff;\n}\n.btn-warning {\n color: #fff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:focus,\n.btn-warning.focus {\n color: #fff;\n background-color: #ec971f;\n border-color: #985f0d;\n}\n.btn-warning:hover {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #fff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active:hover,\n.btn-warning.active:hover,\n.open > .dropdown-toggle.btn-warning:hover,\n.btn-warning:active:focus,\n.btn-warning.active:focus,\n.open > .dropdown-toggle.btn-warning:focus,\n.btn-warning:active.focus,\n.btn-warning.active.focus,\n.open > .dropdown-toggle.btn-warning.focus {\n color: #fff;\n background-color: #d58512;\n border-color: #985f0d;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n background-image: none;\n}\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #fff;\n}\n.btn-danger {\n color: #fff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:focus,\n.btn-danger.focus {\n color: #fff;\n background-color: #c9302c;\n border-color: #761c19;\n}\n.btn-danger:hover {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #fff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active:hover,\n.btn-danger.active:hover,\n.open > .dropdown-toggle.btn-danger:hover,\n.btn-danger:active:focus,\n.btn-danger.active:focus,\n.open > .dropdown-toggle.btn-danger:focus,\n.btn-danger:active.focus,\n.btn-danger.active.focus,\n.open > .dropdown-toggle.btn-danger.focus {\n color: #fff;\n background-color: #ac2925;\n border-color: #761c19;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n background-image: none;\n}\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #fff;\n}\n.btn-link {\n color: #337ab7;\n font-weight: normal;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity 0.15s linear;\n -o-transition: opacity 0.15s linear;\n transition: opacity 0.15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-property: height, visibility;\n transition-property: height, visibility;\n -webkit-transition-duration: 0.35s;\n transition-duration: 0.35s;\n -webkit-transition-timing-function: ease;\n transition-timing-function: ease;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-top: 4px solid \\9;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n list-style: none;\n font-size: 14px;\n text-align: left;\n background-color: #fff;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n background-clip: padding-box;\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: 1.42857143;\n color: #333333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n text-decoration: none;\n color: #262626;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #fff;\n text-decoration: none;\n outline: 0;\n background-color: #337ab7;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n cursor: not-allowed;\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n left: auto;\n right: 0;\n}\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n border-top: 0;\n border-bottom: 4px dashed;\n border-bottom: 4px solid \\9;\n content: \"\";\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n left: auto;\n right: 0;\n }\n .navbar-right .dropdown-menu-left {\n left: 0;\n right: auto;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn,\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group .form-control:focus {\n z-index: 3;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: normal;\n line-height: 1;\n color: #555555;\n text-align: center;\n background-color: #eeeeee;\n border: 1px solid #ccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n z-index: 2;\n margin-left: -1px;\n}\n.nav {\n margin-bottom: 0;\n padding-left: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.nav > li.disabled > a {\n color: #777777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777777;\n text-decoration: none;\n background-color: transparent;\n cursor: not-allowed;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eeeeee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #ddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eeeeee #eeeeee #ddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555555;\n background-color: #fff;\n border: 1px solid #ddd;\n border-bottom-color: transparent;\n cursor: default;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #fff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #ddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #ddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #fff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n overflow-x: visible;\n padding-right: 15px;\n padding-left: 15px;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n -webkit-overflow-scrolling: touch;\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-left: 0;\n padding-right: 0;\n }\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.navbar-brand {\n float: left;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n height: 50px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: 15px;\n padding: 9px 10px;\n margin-top: 8px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n margin-left: -15px;\n margin-right: -15px;\n padding: 10px 15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n margin-top: 8px;\n margin-bottom: 8px;\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-left: 15px;\n margin-right: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n border-color: #ddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #ddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n background-color: #e7e7e7;\n color: #555;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #ccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-link {\n color: #777;\n}\n.navbar-default .navbar-link:hover {\n color: #333;\n}\n.navbar-default .btn-link {\n color: #777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #ccc;\n}\n.navbar-inverse {\n background-color: #222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #fff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #fff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #fff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n background-color: #080808;\n color: #fff;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #fff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #fff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #fff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n content: \"/\\00a0\";\n padding: 0 5px;\n color: #ccc;\n}\n.breadcrumb > .active {\n color: #777777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n line-height: 1.42857143;\n text-decoration: none;\n color: #337ab7;\n background-color: #fff;\n border: 1px solid #ddd;\n margin-left: -1px;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-bottom-left-radius: 4px;\n border-top-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-bottom-right-radius: 4px;\n border-top-right-radius: 4px;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n z-index: 2;\n color: #23527c;\n background-color: #eeeeee;\n border-color: #ddd;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 3;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n cursor: default;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777777;\n background-color: #fff;\n border-color: #ddd;\n cursor: not-allowed;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-bottom-left-radius: 6px;\n border-top-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-bottom-right-radius: 6px;\n border-top-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-bottom-left-radius: 3px;\n border-top-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-bottom-right-radius: 3px;\n border-top-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n list-style: none;\n text-align: center;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777777;\n background-color: #fff;\n cursor: not-allowed;\n}\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n}\na.label:hover,\na.label:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n color: #fff;\n line-height: 1;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: #777777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #fff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding-top: 30px;\n padding-bottom: 30px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eeeeee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n border-radius: 6px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding-top: 48px;\n padding-bottom: 48px;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-left: 60px;\n padding-right: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #fff;\n border: 1px solid #ddd;\n border-radius: 4px;\n -webkit-transition: border 0.2s ease-in-out;\n -o-transition: border 0.2s ease-in-out;\n transition: border 0.2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-left: auto;\n margin-right: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n background-color: #dff0d8;\n border-color: #d6e9c6;\n color: #3c763d;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n background-color: #d9edf7;\n border-color: #bce8f1;\n color: #31708f;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n background-color: #fcf8e3;\n border-color: #faebcc;\n color: #8a6d3b;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n background-color: #f2dede;\n border-color: #ebccd1;\n color: #a94442;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n overflow: hidden;\n height: 20px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #fff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n -webkit-transition: width 0.6s ease;\n -o-transition: width 0.6s ease;\n transition: width 0.6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-object.img-thumbnail {\n max-width: none;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n margin-bottom: 20px;\n padding-left: 0;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid #ddd;\n}\n.list-group-item:first-child {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\na.list-group-item,\nbutton.list-group-item {\n color: #555;\n}\na.list-group-item .list-group-item-heading,\nbutton.list-group-item .list-group-item-heading {\n color: #333;\n}\na.list-group-item:hover,\nbutton.list-group-item:hover,\na.list-group-item:focus,\nbutton.list-group-item:focus {\n text-decoration: none;\n color: #555;\n background-color: #f5f5f5;\n}\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n background-color: #eeeeee;\n color: #777777;\n cursor: not-allowed;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success,\nbutton.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading,\nbutton.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\nbutton.list-group-item-success:hover,\na.list-group-item-success:focus,\nbutton.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\nbutton.list-group-item-success.active,\na.list-group-item-success.active:hover,\nbutton.list-group-item-success.active:hover,\na.list-group-item-success.active:focus,\nbutton.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info,\nbutton.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading,\nbutton.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\nbutton.list-group-item-info:hover,\na.list-group-item-info:focus,\nbutton.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\nbutton.list-group-item-info.active,\na.list-group-item-info.active:hover,\nbutton.list-group-item-info.active:hover,\na.list-group-item-info.active:focus,\nbutton.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning,\nbutton.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading,\nbutton.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\nbutton.list-group-item-warning:hover,\na.list-group-item-warning:focus,\nbutton.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\nbutton.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus,\nbutton.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger,\nbutton.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading,\nbutton.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\nbutton.list-group-item-danger:hover,\na.list-group-item-danger:focus,\nbutton.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\nbutton.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus,\nbutton.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #fff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #ddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-left: 15px;\n padding-right: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-left-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #ddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n border: 0;\n margin-bottom: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #ddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #ddd;\n}\n.panel-default {\n border-color: #ddd;\n}\n.panel-default > .panel-heading {\n color: #333333;\n background-color: #f5f5f5;\n border-color: #ddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #fff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #fff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n height: 100%;\n width: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, 0.15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n opacity: 0.2;\n filter: alpha(opacity=20);\n}\n.close:hover,\n.close:focus {\n color: #000;\n text-decoration: none;\n cursor: pointer;\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\nbutton.close {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n display: none;\n overflow: hidden;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n -webkit-transition: -webkit-transform 0.3s ease-out;\n -moz-transition: -moz-transform 0.3s ease-out;\n -o-transition: -o-transform 0.3s ease-out;\n transition: transform 0.3s ease-out;\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #fff;\n border: 1px solid #999;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n background-clip: padding-box;\n outline: 0;\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000;\n}\n.modal-backdrop.fade {\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.modal-backdrop.in {\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-left: 5px;\n margin-bottom: 0;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 12px;\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.tooltip.in {\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.tooltip.top {\n margin-top: -3px;\n padding: 5px 0;\n}\n.tooltip.right {\n margin-left: 3px;\n padding: 0 5px;\n}\n.tooltip.bottom {\n margin-top: 3px;\n padding: 5px 0;\n}\n.tooltip.left {\n margin-left: -3px;\n padding: 0 5px;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-left .tooltip-arrow {\n bottom: 0;\n right: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 14px;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ccc;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover-title {\n margin: 0;\n padding: 8px 14px;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow:after {\n border-width: 10px;\n content: \"\";\n}\n.popover.top > .arrow {\n left: 50%;\n margin-left: -11px;\n border-bottom-width: 0;\n border-top-color: #999999;\n border-top-color: rgba(0, 0, 0, 0.25);\n bottom: -11px;\n}\n.popover.top > .arrow:after {\n content: \" \";\n bottom: 1px;\n margin-left: -10px;\n border-bottom-width: 0;\n border-top-color: #fff;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-left-width: 0;\n border-right-color: #999999;\n border-right-color: rgba(0, 0, 0, 0.25);\n}\n.popover.right > .arrow:after {\n content: \" \";\n left: 1px;\n bottom: -10px;\n border-left-width: 0;\n border-right-color: #fff;\n}\n.popover.bottom > .arrow {\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999999;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n top: -11px;\n}\n.popover.bottom > .arrow:after {\n content: \" \";\n top: 1px;\n margin-left: -10px;\n border-top-width: 0;\n border-bottom-color: #fff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999999;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n.popover.left > .arrow:after {\n content: \" \";\n right: 1px;\n border-right-width: 0;\n border-left-color: #fff;\n bottom: -10px;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n overflow: hidden;\n width: 100%;\n}\n.carousel-inner > .item {\n display: none;\n position: relative;\n -webkit-transition: 0.6s ease-in-out left;\n -o-transition: 0.6s ease-in-out left;\n transition: 0.6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform 0.6s ease-in-out;\n -moz-transition: -moz-transform 0.6s ease-in-out;\n -o-transition: -o-transform 0.6s ease-in-out;\n transition: transform 0.6s ease-in-out;\n -webkit-backface-visibility: hidden;\n -moz-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000px;\n -moz-perspective: 1000px;\n perspective: 1000px;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n left: 0;\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: 15%;\n opacity: 0.5;\n filter: alpha(opacity=50);\n font-size: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n}\n.carousel-control.right {\n left: auto;\n right: 0;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n}\n.carousel-control:hover,\n.carousel-control:focus {\n outline: 0;\n color: #fff;\n text-decoration: none;\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n margin-top: -10px;\n z-index: 5;\n display: inline-block;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n line-height: 1;\n font-family: serif;\n}\n.carousel-control .icon-prev:before {\n content: '\\2039';\n}\n.carousel-control .icon-next:before {\n content: '\\203a';\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n margin-left: -30%;\n padding-left: 0;\n list-style: none;\n text-align: center;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n border: 1px solid #fff;\n border-radius: 10px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-indicators .active {\n margin: 0;\n width: 12px;\n height: 12px;\n background-color: #fff;\n}\n.carousel-caption {\n position: absolute;\n left: 15%;\n right: 15%;\n bottom: 20px;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -10px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -10px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -10px;\n }\n .carousel-caption {\n left: 20%;\n right: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-header:before,\n.modal-header:after,\n.modal-footer:before,\n.modal-footer:after {\n content: \" \";\n display: table;\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-header:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table !important;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table !important;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table !important;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table !important;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table !important;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */","/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS and IE text size adjust after device orientation change,\n// without disabling user zoom.\n//\n\nhtml {\n font-family: sans-serif; // 1\n -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined for any HTML5 element in IE 8/9.\n// Correct `block` display not defined for `details` or `summary` in IE 10/11\n// and Firefox.\n// Correct `block` display not defined for `main` in IE 11.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9/10.\n// Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background-color: transparent;\n}\n\n//\n// Improve readability of focused elements when they are also in an\n// active/hover state.\n//\n\na:active,\na:hover {\n outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n//\n\nabbr[title] {\n border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n//\n\nb,\nstrong {\n font-weight: bold;\n}\n\n//\n// Address styling not present in Safari and Chrome.\n//\n\ndfn {\n font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari, and Chrome.\n//\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9/10.\n//\n\nimg {\n border: 0;\n}\n\n//\n// Correct overflow not hidden in IE 9/10/11.\n//\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari.\n//\n\nfigure {\n margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n box-sizing: content-box;\n height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10/11.\n//\n\nbutton {\n overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n// and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n// `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; // 2\n cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari and Chrome.\n//\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; // 1\n box-sizing: content-box; //2\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9/10/11.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n border: 0; // 1\n padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9/10/11.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}\n","/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n\n// ==========================================================================\n// Print styles.\n// Inlined to avoid the additional HTTP request: h5bp.com/r\n// ==========================================================================\n\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important; // Black prints faster: h5bp.com/s\n box-shadow: none !important;\n text-shadow: none !important;\n }\n\n a,\n a:visited {\n text-decoration: underline;\n }\n\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n\n // Don't show links that are fragment identifiers,\n // or use the `javascript:` pseudo protocol\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n\n thead {\n display: table-header-group; // h5bp.com/t\n }\n\n tr,\n img {\n page-break-inside: avoid;\n }\n\n img {\n max-width: 100% !important;\n }\n\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n\n h2,\n h3 {\n page-break-after: avoid;\n }\n\n // Bootstrap specific changes start\n\n // Bootstrap components\n .navbar {\n display: none;\n }\n .btn,\n .dropup > .btn {\n > .caret {\n border-top-color: #000 !important;\n }\n }\n .label {\n border: 1px solid #000;\n }\n\n .table {\n border-collapse: collapse !important;\n\n td,\n th {\n background-color: #fff !important;\n }\n }\n .table-bordered {\n th,\n td {\n border: 1px solid #ddd !important;\n }\n }\n\n // Bootstrap specific changes end\n}\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// Star\n\n// Import the fonts\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('@{icon-font-path}@{icon-font-name}.eot');\n src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'),\n url('@{icon-font-path}@{icon-font-name}.woff2') format('woff2'),\n url('@{icon-font-path}@{icon-font-name}.woff') format('woff'),\n url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'),\n url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg');\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\002a\"; } }\n.glyphicon-plus { &:before { content: \"\\002b\"; } }\n.glyphicon-euro,\n.glyphicon-eur { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n.glyphicon-cd { &:before { content: \"\\e201\"; } }\n.glyphicon-save-file { &:before { content: \"\\e202\"; } }\n.glyphicon-open-file { &:before { content: \"\\e203\"; } }\n.glyphicon-level-up { &:before { content: \"\\e204\"; } }\n.glyphicon-copy { &:before { content: \"\\e205\"; } }\n.glyphicon-paste { &:before { content: \"\\e206\"; } }\n// The following 2 Glyphicons are omitted for the time being because\n// they currently use Unicode codepoints that are outside the\n// Basic Multilingual Plane (BMP). Older buggy versions of WebKit can't handle\n// non-BMP codepoints in CSS string escapes, and thus can't display these two icons.\n// Notably, the bug affects some older versions of the Android Browser.\n// More info: https://github.com/twbs/bootstrap/issues/10106\n// .glyphicon-door { &:before { content: \"\\1f6aa\"; } }\n// .glyphicon-key { &:before { content: \"\\1f511\"; } }\n.glyphicon-alert { &:before { content: \"\\e209\"; } }\n.glyphicon-equalizer { &:before { content: \"\\e210\"; } }\n.glyphicon-king { &:before { content: \"\\e211\"; } }\n.glyphicon-queen { &:before { content: \"\\e212\"; } }\n.glyphicon-pawn { &:before { content: \"\\e213\"; } }\n.glyphicon-bishop { &:before { content: \"\\e214\"; } }\n.glyphicon-knight { &:before { content: \"\\e215\"; } }\n.glyphicon-baby-formula { &:before { content: \"\\e216\"; } }\n.glyphicon-tent { &:before { content: \"\\26fa\"; } }\n.glyphicon-blackboard { &:before { content: \"\\e218\"; } }\n.glyphicon-bed { &:before { content: \"\\e219\"; } }\n.glyphicon-apple { &:before { content: \"\\f8ff\"; } }\n.glyphicon-erase { &:before { content: \"\\e221\"; } }\n.glyphicon-hourglass { &:before { content: \"\\231b\"; } }\n.glyphicon-lamp { &:before { content: \"\\e223\"; } }\n.glyphicon-duplicate { &:before { content: \"\\e224\"; } }\n.glyphicon-piggy-bank { &:before { content: \"\\e225\"; } }\n.glyphicon-scissors { &:before { content: \"\\e226\"; } }\n.glyphicon-bitcoin { &:before { content: \"\\e227\"; } }\n.glyphicon-btc { &:before { content: \"\\e227\"; } }\n.glyphicon-xbt { &:before { content: \"\\e227\"; } }\n.glyphicon-yen { &:before { content: \"\\00a5\"; } }\n.glyphicon-jpy { &:before { content: \"\\00a5\"; } }\n.glyphicon-ruble { &:before { content: \"\\20bd\"; } }\n.glyphicon-rub { &:before { content: \"\\20bd\"; } }\n.glyphicon-scale { &:before { content: \"\\e230\"; } }\n.glyphicon-ice-lolly { &:before { content: \"\\e231\"; } }\n.glyphicon-ice-lolly-tasted { &:before { content: \"\\e232\"; } }\n.glyphicon-education { &:before { content: \"\\e233\"; } }\n.glyphicon-option-horizontal { &:before { content: \"\\e234\"; } }\n.glyphicon-option-vertical { &:before { content: \"\\e235\"; } }\n.glyphicon-menu-hamburger { &:before { content: \"\\e236\"; } }\n.glyphicon-modal-window { &:before { content: \"\\e237\"; } }\n.glyphicon-oil { &:before { content: \"\\e238\"; } }\n.glyphicon-grain { &:before { content: \"\\e239\"; } }\n.glyphicon-sunglasses { &:before { content: \"\\e240\"; } }\n.glyphicon-text-size { &:before { content: \"\\e241\"; } }\n.glyphicon-text-color { &:before { content: \"\\e242\"; } }\n.glyphicon-text-background { &:before { content: \"\\e243\"; } }\n.glyphicon-object-align-top { &:before { content: \"\\e244\"; } }\n.glyphicon-object-align-bottom { &:before { content: \"\\e245\"; } }\n.glyphicon-object-align-horizontal{ &:before { content: \"\\e246\"; } }\n.glyphicon-object-align-left { &:before { content: \"\\e247\"; } }\n.glyphicon-object-align-vertical { &:before { content: \"\\e248\"; } }\n.glyphicon-object-align-right { &:before { content: \"\\e249\"; } }\n.glyphicon-triangle-right { &:before { content: \"\\e250\"; } }\n.glyphicon-triangle-left { &:before { content: \"\\e251\"; } }\n.glyphicon-triangle-bottom { &:before { content: \"\\e252\"; } }\n.glyphicon-triangle-top { &:before { content: \"\\e253\"; } }\n.glyphicon-console { &:before { content: \"\\e254\"; } }\n.glyphicon-superscript { &:before { content: \"\\e255\"; } }\n.glyphicon-subscript { &:before { content: \"\\e256\"; } }\n.glyphicon-menu-left { &:before { content: \"\\e257\"; } }\n.glyphicon-menu-right { &:before { content: \"\\e258\"; } }\n.glyphicon-menu-down { &:before { content: \"\\e259\"; } }\n.glyphicon-menu-up { &:before { content: \"\\e260\"; } }\n","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\n}\n*:before,\n*:after {\n .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n font-family: @font-family-base;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @text-color;\n background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n\n// Links\n\na {\n color: @link-color;\n text-decoration: none;\n\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n }\n\n &:focus {\n .tab-focus();\n }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\n}\n\n\n// Images\n\nimg {\n vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n padding: @thumbnail-padding;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n // Keep them at most 100% wide\n .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n margin-top: @line-height-computed;\n margin-bottom: @line-height-computed;\n border: 0;\n border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: http://a11yproject.com/posts/how-to-hide-content\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0,0,0,0);\n border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n// Useful for \"Skip to main content\" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n// Credit: HTML5 Boilerplate\n\n.sr-only-focusable {\n &:active,\n &:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n }\n}\n\n\n// iOS \"clickable elements\" fix for role=\"button\"\n//\n// Fixes \"clickability\" issue (and more generally, the firing of events such as focus as well)\n// for traditionally non-focusable elements with role=\"button\"\n// see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n\n[role=\"button\"] {\n cursor: pointer;\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They have been removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility) {\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// WebKit-style focus\n\n.tab-focus() {\n // WebKit-specific. Other browsers will keep their default outline style.\n // (Initially tried to also force default via `outline: initial`,\n // but that seems to erroneously remove the outline in Firefox altogether.)\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n.img-responsive(@display: block) {\n display: @display;\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size. Note that the\n// spelling of `min--moz-device-pixel-ratio` is intentional.\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 300;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: (12px small font / 14px base font) * 100% = about 85%\nsmall,\n.small {\n font-size: floor((100% * @font-size-small / @font-size-base));\n}\n\nmark,\n.mark {\n background-color: @state-warning-bg;\n padding: .2em;\n}\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n.text-nowrap { white-space: nowrap; }\n\n// Transformation\n.text-lowercase { text-transform: lowercase; }\n.text-uppercase { text-transform: uppercase; }\n.text-capitalize { text-transform: capitalize; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// -------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n.dl-horizontal {\n dd {\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n\n @media (min-width: @dl-horizontal-breakpoint) {\n dt {\n float: left;\n width: (@dl-horizontal-offset - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @dl-horizontal-offset;\n }\n }\n}\n\n\n// Misc\n// -------------------------\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n font-size: 90%;\n .text-uppercase();\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","// Typography\n\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover,\n a&:focus {\n color: darken(@color, 10%);\n }\n}\n","// Contextual backgrounds\n\n.bg-variant(@color) {\n background-color: @color;\n a&:hover,\n a&:focus {\n background-color: darken(@color, 10%);\n }\n}\n","// Text overflow\n// Requires inline-block or block for proper styling\n\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n\n kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n }\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n word-break: break-all;\n word-wrap: break-word;\n color: @pre-color;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n","// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n// Centered container element\n.container-fixed(@gutter: @grid-gutter-width) {\n margin-right: auto;\n margin-left: auto;\n padding-left: floor((@gutter / 2));\n padding-right: ceil((@gutter / 2));\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-left: ceil((@gutter / -2));\n margin-right: floor((@gutter / -2));\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n margin-left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-push(@columns) {\n left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-pull(@columns) {\n right: percentage((@columns / @grid-columns));\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-left: ceil((@grid-gutter-width / 2));\n padding-right: floor((@grid-gutter-width / 2));\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {\n .col-@{class}-push-0 {\n left: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {\n .col-@{class}-pull-0 {\n right: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n background-color: @table-bg;\n}\ncaption {\n padding-top: @table-cell-padding;\n padding-bottom: @table-cell-padding;\n color: @text-muted;\n text-align: left;\n}\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-of-type(odd) {\n background-color: @table-bg-accent;\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n background-color: @table-bg-hover;\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-cell;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837)\n\n @media screen and (max-width: @screen-xs-max) {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","// Tables\n\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &:hover > .@{state},\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n // Chrome and Firefox set a `min-width: min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)\n margin-bottom: 5px;\n font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; // IE8-9\n line-height: normal;\n}\n\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n display: block;\n width: 100%;\n height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid @input-border;\n border-radius: @input-border-radius; // Note: This has no effect on s in CSS.\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n // Customize the `:focus` state to imitate native WebKit styles.\n .form-control-focus();\n\n // Placeholder\n .placeholder();\n\n // Unstyle the caret on ``\n// element gets special love because it's special, and that's a fact!\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n height: @input-height;\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n\n select& {\n height: @input-height;\n line-height: @input-height;\n }\n\n textarea&,\n select[multiple]& {\n height: auto;\n }\n}\n","//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n display: inline-block;\n margin-bottom: 0; // For input.btn\n font-weight: @btn-font-weight;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n white-space: nowrap;\n .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @btn-border-radius-base);\n .user-select(none);\n\n &,\n &:active,\n &.active {\n &:focus,\n &.focus {\n .tab-focus();\n }\n }\n\n &:hover,\n &:focus,\n &.focus {\n color: @btn-default-color;\n text-decoration: none;\n }\n\n &:active,\n &.active {\n outline: 0;\n background-image: none;\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n .opacity(.65);\n .box-shadow(none);\n }\n\n a& {\n &.disabled,\n fieldset[disabled] & {\n pointer-events: none; // Future-proof disabling of clicks on `` elements\n }\n }\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Success appears as green\n.btn-success {\n .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n// Warning appears as orange\n.btn-warning {\n .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n color: @link-color;\n font-weight: normal;\n border-radius: 0;\n\n &,\n &:active,\n &.active,\n &[disabled],\n fieldset[disabled] & {\n background-color: transparent;\n .box-shadow(none);\n }\n &,\n &:hover,\n &:focus,\n &:active {\n border-color: transparent;\n }\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n background-color: transparent;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @btn-link-disabled-color;\n text-decoration: none;\n }\n }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n // line-height: ensure even-numbered height of button next to large input\n .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @btn-border-radius-large);\n}\n.btn-sm {\n // line-height: ensure proper height of button next to small input\n .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n.btn-xs {\n .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n display: block;\n width: 100%;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n &.btn-block {\n width: 100%;\n }\n}\n","// Button variants\n//\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n\n.button-variant(@color; @background; @border) {\n color: @color;\n background-color: @background;\n border-color: @border;\n\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 25%);\n }\n &:hover {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n\n &:hover,\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 17%);\n border-color: darken(@border, 25%);\n }\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n background-image: none;\n }\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus,\n &.focus {\n background-color: @background;\n border-color: @border;\n }\n }\n\n .badge {\n color: @background;\n background-color: @color;\n }\n}\n\n// Button sizes\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n}\n","// Opacity\n\n.opacity(@opacity) {\n opacity: @opacity;\n // IE8 filter\n @opacity-ie: (@opacity * 100);\n filter: ~\"alpha(opacity=@{opacity-ie})\";\n}\n","//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552.\n\n.fade {\n opacity: 0;\n .transition(opacity .15s linear);\n &.in {\n opacity: 1;\n }\n}\n\n.collapse {\n display: none;\n\n &.in { display: block; }\n tr&.in { display: table-row; }\n tbody&.in { display: table-row-group; }\n}\n\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n .transition-property(~\"height, visibility\");\n .transition-duration(.35s);\n .transition-timing-function(ease);\n}\n","//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: @caret-width-base dashed;\n border-top: @caret-width-base solid ~\"\\9\"; // IE8\n border-right: @caret-width-base solid transparent;\n border-left: @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropup,\n.dropdown {\n position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: @zindex-dropdown;\n display: none; // none by default, but block on \"open\" of the menu\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0; // override default ul\n list-style: none;\n font-size: @font-size-base;\n text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)\n background-color: @dropdown-bg;\n border: 1px solid @dropdown-fallback-border; // IE8 fallback\n border: 1px solid @dropdown-border;\n border-radius: @border-radius-base;\n .box-shadow(0 6px 12px rgba(0,0,0,.175));\n background-clip: padding-box;\n\n // Aligns the dropdown menu to right\n //\n // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n &.pull-right {\n right: 0;\n left: auto;\n }\n\n // Dividers (basically an hr) within the dropdown\n .divider {\n .nav-divider(@dropdown-divider-bg);\n }\n\n // Links within the dropdown menu\n > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: @line-height-base;\n color: @dropdown-link-color;\n white-space: nowrap; // prevent links from randomly breaking onto new lines\n }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n &:hover,\n &:focus {\n text-decoration: none;\n color: @dropdown-link-hover-color;\n background-color: @dropdown-link-hover-bg;\n }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-active-color;\n text-decoration: none;\n outline: 0;\n background-color: @dropdown-link-active-bg;\n }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-disabled-color;\n }\n\n // Nuke hover/focus effects\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none; // Remove CSS gradient\n .reset-filter();\n cursor: @cursor-disabled;\n }\n}\n\n// Open state for the dropdown\n.open {\n // Show the menu\n > .dropdown-menu {\n display: block;\n }\n\n // Remove the outline when :focus is triggered\n > a {\n outline: 0;\n }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n left: auto; // Reset the default from `.dropdown-menu`\n right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n\n// Dropdown section headers\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: @font-size-small;\n line-height: @line-height-base;\n color: @dropdown-header-color;\n white-space: nowrap; // as with > li > a\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n // Reverse the caret\n .caret {\n border-top: 0;\n border-bottom: @caret-width-base dashed;\n border-bottom: @caret-width-base solid ~\"\\9\"; // IE8\n content: \"\";\n }\n // Different positioning for bottom up menu\n .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-right {\n .dropdown-menu {\n .dropdown-menu-right();\n }\n // Necessary for overrides of the default right aligned menu.\n // Will remove come v4 in all likelihood.\n .dropdown-menu-left {\n .dropdown-menu-left();\n }\n }\n}\n","// Horizontal dividers\n//\n// Dividers (basically an hr) within dropdowns and nav lists\n\n.nav-divider(@color: #e5e5e5) {\n height: 1px;\n margin: ((@line-height-computed / 2) - 1) 0;\n overflow: hidden;\n background-color: @color;\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n","//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle; // match .btn alignment given font-size hack above\n > .btn {\n position: relative;\n float: left;\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active,\n &.active {\n z-index: 2;\n }\n }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n .btn + .btn,\n .btn + .btn-group,\n .btn-group + .btn,\n .btn-group + .btn-group {\n margin-left: -1px;\n }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n margin-left: -5px; // Offset the first child's margin\n &:extend(.clearfix all);\n\n .btn,\n .btn-group,\n .input-group {\n float: left;\n }\n > .btn,\n > .btn-group,\n > .input-group {\n margin-left: 5px;\n }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n margin-left: 0;\n &:not(:last-child):not(.dropdown-toggle) {\n .border-right-radius(0);\n }\n}\n// Need .dropdown-toggle since :last-child doesn't apply, given that a .dropdown-menu is used immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-right-radius(0);\n }\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { &:extend(.btn-xs); }\n.btn-group-sm > .btn { &:extend(.btn-sm); }\n.btn-group-lg > .btn { &:extend(.btn-lg); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n .box-shadow(none);\n }\n}\n\n\n// Reposition the caret\n.btn .caret {\n margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n border-width: @caret-width-large @caret-width-large 0;\n border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n border-width: 0 @caret-width-large @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n > .btn,\n > .btn-group,\n > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n }\n\n // Clear floats so dropdown menus can be properly placed\n > .btn-group {\n &:extend(.clearfix all);\n > .btn {\n float: none;\n }\n }\n\n > .btn + .btn,\n > .btn + .btn-group,\n > .btn-group + .btn,\n > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n }\n}\n\n.btn-group-vertical > .btn {\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n &:first-child:not(:last-child) {\n .border-top-radius(@btn-border-radius-base);\n .border-bottom-radius(0);\n }\n &:last-child:not(:first-child) {\n .border-top-radius(0);\n .border-bottom-radius(@btn-border-radius-base);\n }\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-bottom-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-top-radius(0);\n}\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n > .btn,\n > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n }\n > .btn-group .btn {\n width: 100%;\n }\n\n > .btn-group .dropdown-menu {\n left: auto;\n }\n}\n\n\n// Checkbox and radio options\n//\n// In order to support the browser's form validation feedback, powered by the\n// `required` attribute, we have to \"hide\" the inputs via `clip`. We cannot use\n// `display: none;` or `visibility: hidden;` as that also hides the popover.\n// Simply visually hiding the inputs via `opacity` would leave them clickable in\n// certain cases which is prevented by using `clip` and `pointer-events`.\n// This way, we ensure a DOM element is visible to position the popover from.\n//\n// See https://github.com/twbs/bootstrap/pull/12794 and\n// https://github.com/twbs/bootstrap/pull/14559 for more information.\n\n[data-toggle=\"buttons\"] {\n > .btn,\n > .btn-group > .btn {\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0,0,0,0);\n pointer-events: none;\n }\n }\n}\n","// Single side border-radius\n\n.border-top-radius(@radius) {\n border-top-right-radius: @radius;\n border-top-left-radius: @radius;\n}\n.border-right-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-top-right-radius: @radius;\n}\n.border-bottom-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-bottom-left-radius: @radius;\n}\n.border-left-radius(@radius) {\n border-bottom-left-radius: @radius;\n border-top-left-radius: @radius;\n}\n","//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n position: relative; // For dropdowns\n display: table;\n border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n // Undo padding and float of grid classes\n &[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n }\n\n .form-control {\n // Ensure that the input is always above the *appended* addon button for\n // proper border colors.\n position: relative;\n z-index: 2;\n\n // IE9 fubars the placeholder attribute in text inputs and the arrows on\n // select elements in input groups. To fix it, we float the input. Details:\n // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n float: left;\n\n width: 100%;\n margin-bottom: 0;\n\n &:focus {\n z-index: 3;\n }\n }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n .input-lg();\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n .input-sm();\n}\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: 1;\n color: @input-color;\n text-align: center;\n background-color: @input-group-addon-bg;\n border: 1px solid @input-group-addon-border-color;\n border-radius: @input-border-radius;\n\n // Sizing\n &.input-sm {\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n border-radius: @input-border-radius-small;\n }\n &.input-lg {\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n border-radius: @input-border-radius-large;\n }\n\n // Nuke default margins from checkboxes and radios to vertically center within.\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n margin-top: 0;\n }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n .border-right-radius(0);\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n .border-left-radius(0);\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n position: relative;\n // Jankily prevent input button groups from wrapping with `white-space` and\n // `font-size` in combination with `inline-block` on buttons.\n font-size: 0;\n white-space: nowrap;\n\n // Negative margin for spacing, position for bringing hovered/focused/actived\n // element above the siblings.\n > .btn {\n position: relative;\n + .btn {\n margin-left: -1px;\n }\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active {\n z-index: 2;\n }\n }\n\n // Negative margin to only have a 1px border between the two\n &:first-child {\n > .btn,\n > .btn-group {\n margin-right: -1px;\n }\n }\n &:last-child {\n > .btn,\n > .btn-group {\n z-index: 2;\n margin-left: -1px;\n }\n }\n}\n","//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n margin-bottom: 0;\n padding-left: 0; // Override default ul/ol\n list-style: none;\n &:extend(.clearfix all);\n\n > li {\n position: relative;\n display: block;\n\n > a {\n position: relative;\n display: block;\n padding: @nav-link-padding;\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: @nav-link-hover-bg;\n }\n }\n\n // Disabled state sets text to gray and nukes hover/tab effects\n &.disabled > a {\n color: @nav-disabled-link-color;\n\n &:hover,\n &:focus {\n color: @nav-disabled-link-hover-color;\n text-decoration: none;\n background-color: transparent;\n cursor: @cursor-disabled;\n }\n }\n }\n\n // Open dropdowns\n .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @nav-link-hover-bg;\n border-color: @link-color;\n }\n }\n\n // Nav dividers (deprecated with v3.0.1)\n //\n // This should have been removed in v3 with the dropping of `.nav-list`, but\n // we missed it. We don't currently support this anywhere, but in the interest\n // of maintaining backward compatibility in case you use it, it's deprecated.\n .nav-divider {\n .nav-divider();\n }\n\n // Prevent IE8 from misplacing imgs\n //\n // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n > li > a > img {\n max-width: none;\n }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n border-bottom: 1px solid @nav-tabs-border-color;\n > li {\n float: left;\n // Make the list-items overlay the bottom border\n margin-bottom: -1px;\n\n // Actual tabs (as links)\n > a {\n margin-right: 2px;\n line-height: @line-height-base;\n border: 1px solid transparent;\n border-radius: @border-radius-base @border-radius-base 0 0;\n &:hover {\n border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n }\n }\n\n // Active state, and its :hover to override normal :hover\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-tabs-active-link-hover-color;\n background-color: @nav-tabs-active-link-hover-bg;\n border: 1px solid @nav-tabs-active-link-hover-border-color;\n border-bottom-color: transparent;\n cursor: default;\n }\n }\n }\n // pulling this in mainly for less shorthand\n &.nav-justified {\n .nav-justified();\n .nav-tabs-justified();\n }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n > li {\n float: left;\n\n // Links rendered as pills\n > a {\n border-radius: @nav-pills-border-radius;\n }\n + li {\n margin-left: 2px;\n }\n\n // Active state\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-pills-active-link-hover-color;\n background-color: @nav-pills-active-link-hover-bg;\n }\n }\n }\n}\n\n\n// Stacked pills\n.nav-stacked {\n > li {\n float: none;\n + li {\n margin-top: 2px;\n margin-left: 0; // no need for this gap between nav items\n }\n }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n width: 100%;\n\n > li {\n float: none;\n > a {\n text-align: center;\n margin-bottom: 5px;\n }\n }\n\n > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n }\n\n @media (min-width: @screen-sm-min) {\n > li {\n display: table-cell;\n width: 1%;\n > a {\n margin-bottom: 0;\n }\n }\n }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n border-bottom: 0;\n\n > li > a {\n // Override margin from .nav-tabs\n margin-right: 0;\n border-radius: @border-radius-base;\n }\n\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border: 1px solid @nav-tabs-justified-link-border-color;\n }\n\n @media (min-width: @screen-sm-min) {\n > li > a {\n border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n border-radius: @border-radius-base @border-radius-base 0 0;\n }\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border-bottom-color: @nav-tabs-justified-active-link-border-color;\n }\n }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n // make dropdown border overlap tab border\n margin-top: -1px;\n // Remove the top rounded corners here since there is a hard edge above the menu\n .border-top-radius(0);\n}\n","//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n position: relative;\n min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n margin-bottom: @navbar-margin-bottom;\n border: 1px solid transparent;\n\n // Prevent floats from breaking the navbar\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: @navbar-border-radius;\n }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n overflow-x: visible;\n padding-right: @navbar-padding-horizontal;\n padding-left: @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n &:extend(.clearfix all);\n -webkit-overflow-scrolling: touch;\n\n &.in {\n overflow-y: auto;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border-top: 0;\n box-shadow: none;\n\n &.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0; // Override default setting\n overflow: visible !important;\n }\n\n &.in {\n overflow-y: visible;\n }\n\n // Undo the collapse side padding for navbars with containers to ensure\n // alignment of right-aligned contents.\n .navbar-fixed-top &,\n .navbar-static-top &,\n .navbar-fixed-bottom & {\n padding-left: 0;\n padding-right: 0;\n }\n }\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n .navbar-collapse {\n max-height: @navbar-collapse-max-height;\n\n @media (max-device-width: @screen-xs-min) and (orientation: landscape) {\n max-height: 200px;\n }\n }\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n > .navbar-header,\n > .navbar-collapse {\n margin-right: -@navbar-padding-horizontal;\n margin-left: -@navbar-padding-horizontal;\n\n @media (min-width: @grid-float-breakpoint) {\n margin-right: 0;\n margin-left: 0;\n }\n }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n z-index: @zindex-navbar;\n border-width: 0 0 1px;\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: @zindex-navbar-fixed;\n\n // Undo the rounded corners\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0; // override .navbar defaults\n border-width: 1px 0 0;\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n float: left;\n padding: @navbar-padding-vertical @navbar-padding-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-computed;\n height: @navbar-height;\n\n &:hover,\n &:focus {\n text-decoration: none;\n }\n\n > img {\n display: block;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n .navbar > .container &,\n .navbar > .container-fluid & {\n margin-left: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: @navbar-padding-horizontal;\n padding: 9px 10px;\n .navbar-vertical-align(34px);\n background-color: transparent;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n border-radius: @border-radius-base;\n\n // We remove the `outline` here, but later compensate by attaching `:hover`\n // styles to `:focus`.\n &:focus {\n outline: 0;\n }\n\n // Bars\n .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n }\n .icon-bar + .icon-bar {\n margin-top: 4px;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n display: none;\n }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: @line-height-computed;\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n > li > a,\n .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n > li > a {\n line-height: @line-height-computed;\n &:hover,\n &:focus {\n background-image: none;\n }\n }\n }\n }\n\n // Uncollapse the nav\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin: 0;\n\n > li {\n float: left;\n > a {\n padding-top: @navbar-padding-vertical;\n padding-bottom: @navbar-padding-vertical;\n }\n }\n }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n margin-left: -@navbar-padding-horizontal;\n margin-right: -@navbar-padding-horizontal;\n padding: 10px @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n\n // Mixin behavior for optimum display\n .form-inline();\n\n .form-group {\n @media (max-width: @grid-float-breakpoint-max) {\n margin-bottom: 5px;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n }\n\n // Vertically center in expanded, horizontal navbar\n .navbar-vertical-align(@input-height-base);\n\n // Undo 100% width for pull classes\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n .box-shadow(none);\n }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n .border-top-radius(@navbar-border-radius);\n .border-bottom-radius(0);\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n .navbar-vertical-align(@input-height-base);\n\n &.btn-sm {\n .navbar-vertical-align(@input-height-small);\n }\n &.btn-xs {\n .navbar-vertical-align(22);\n }\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n .navbar-vertical-align(@line-height-computed);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin-left: @navbar-padding-horizontal;\n margin-right: @navbar-padding-horizontal;\n }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n//\n// Declared after the navbar components to ensure more specificity on the margins.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-left { .pull-left(); }\n .navbar-right {\n .pull-right();\n margin-right: -@navbar-padding-horizontal;\n\n ~ .navbar-right {\n margin-right: 0;\n }\n }\n}\n\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n background-color: @navbar-default-bg;\n border-color: @navbar-default-border;\n\n .navbar-brand {\n color: @navbar-default-brand-color;\n &:hover,\n &:focus {\n color: @navbar-default-brand-hover-color;\n background-color: @navbar-default-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-default-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-default-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n\n .navbar-toggle {\n border-color: @navbar-default-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-default-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-default-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: @navbar-default-border;\n }\n\n // Dropdown menu items\n .navbar-nav {\n // Remove background color from open dropdown\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-default-link-active-bg;\n color: @navbar-default-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n > li > a {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n }\n }\n\n\n // Links in navbars\n //\n // Add a class to ensure links outside the navbar nav are colored correctly.\n\n .navbar-link {\n color: @navbar-default-link-color;\n &:hover {\n color: @navbar-default-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n }\n }\n }\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n background-color: @navbar-inverse-bg;\n border-color: @navbar-inverse-border;\n\n .navbar-brand {\n color: @navbar-inverse-brand-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-brand-hover-color;\n background-color: @navbar-inverse-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-inverse-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-inverse-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n\n // Darken the responsive nav toggle\n .navbar-toggle {\n border-color: @navbar-inverse-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-inverse-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-inverse-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: darken(@navbar-inverse-bg, 7%);\n }\n\n // Dropdowns\n .navbar-nav {\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-inverse-link-active-bg;\n color: @navbar-inverse-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display\n .open .dropdown-menu {\n > .dropdown-header {\n border-color: @navbar-inverse-border;\n }\n .divider {\n background-color: @navbar-inverse-border;\n }\n > li > a {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n }\n }\n\n .navbar-link {\n color: @navbar-inverse-link-color;\n &:hover {\n color: @navbar-inverse-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n }\n }\n }\n}\n","// Navbar vertical align\n//\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n\n.navbar-vertical-align(@element-height) {\n margin-top: ((@navbar-height - @element-height) / 2);\n margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n","//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n .clearfix();\n}\n.center-block {\n .center-block();\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n display: none !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n position: fixed;\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n margin-bottom: @line-height-computed;\n list-style: none;\n background-color: @breadcrumb-bg;\n border-radius: @border-radius-base;\n\n > li {\n display: inline-block;\n\n + li:before {\n content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n padding: 0 5px;\n color: @breadcrumb-color;\n }\n }\n\n > .active {\n color: @breadcrumb-active-color;\n }\n}\n","//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: @line-height-computed 0;\n border-radius: @border-radius-base;\n\n > li {\n display: inline; // Remove list-style and block-level defaults\n > a,\n > span {\n position: relative;\n float: left; // Collapse white-space\n padding: @padding-base-vertical @padding-base-horizontal;\n line-height: @line-height-base;\n text-decoration: none;\n color: @pagination-color;\n background-color: @pagination-bg;\n border: 1px solid @pagination-border;\n margin-left: -1px;\n }\n &:first-child {\n > a,\n > span {\n margin-left: 0;\n .border-left-radius(@border-radius-base);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius-base);\n }\n }\n }\n\n > li > a,\n > li > span {\n &:hover,\n &:focus {\n z-index: 2;\n color: @pagination-hover-color;\n background-color: @pagination-hover-bg;\n border-color: @pagination-hover-border;\n }\n }\n\n > .active > a,\n > .active > span {\n &,\n &:hover,\n &:focus {\n z-index: 3;\n color: @pagination-active-color;\n background-color: @pagination-active-bg;\n border-color: @pagination-active-border;\n cursor: default;\n }\n }\n\n > .disabled {\n > span,\n > span:hover,\n > span:focus,\n > a,\n > a:hover,\n > a:focus {\n color: @pagination-disabled-color;\n background-color: @pagination-disabled-bg;\n border-color: @pagination-disabled-border;\n cursor: @cursor-disabled;\n }\n }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n","// Pagination\n\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n > li {\n > a,\n > span {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n }\n &:first-child {\n > a,\n > span {\n .border-left-radius(@border-radius);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius);\n }\n }\n }\n}\n","//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n padding-left: 0;\n margin: @line-height-computed 0;\n list-style: none;\n text-align: center;\n &:extend(.clearfix all);\n li {\n display: inline;\n > a,\n > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: @pager-bg;\n border: 1px solid @pager-border;\n border-radius: @pager-border-radius;\n }\n\n > a:hover,\n > a:focus {\n text-decoration: none;\n background-color: @pager-hover-bg;\n }\n }\n\n .next {\n > a,\n > span {\n float: right;\n }\n }\n\n .previous {\n > a,\n > span {\n float: left;\n }\n }\n\n .disabled {\n > a,\n > a:hover,\n > a:focus,\n > span {\n color: @pager-disabled-color;\n background-color: @pager-bg;\n cursor: @cursor-disabled;\n }\n }\n}\n","//\n// Labels\n// --------------------------------------------------\n\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: @label-color;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n\n // Add hover effects, but only for links\n a& {\n &:hover,\n &:focus {\n color: @label-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Empty labels collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for labels in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n .label-variant(@label-default-bg);\n}\n\n.label-primary {\n .label-variant(@label-primary-bg);\n}\n\n.label-success {\n .label-variant(@label-success-bg);\n}\n\n.label-info {\n .label-variant(@label-info-bg);\n}\n\n.label-warning {\n .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n .label-variant(@label-danger-bg);\n}\n","// Labels\n\n.label-variant(@color) {\n background-color: @color;\n\n &[href] {\n &:hover,\n &:focus {\n background-color: darken(@color, 10%);\n }\n }\n}\n","//\n// Badges\n// --------------------------------------------------\n\n\n// Base class\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: @font-size-small;\n font-weight: @badge-font-weight;\n color: @badge-color;\n line-height: @badge-line-height;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: @badge-bg;\n border-radius: @badge-border-radius;\n\n // Empty badges collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for badges in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n\n .btn-xs &,\n .btn-group-xs > .btn & {\n top: 0;\n padding: 1px 5px;\n }\n\n // Hover state, but only for links\n a& {\n &:hover,\n &:focus {\n color: @badge-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Account for badges in navs\n .list-group-item.active > &,\n .nav-pills > .active > a > & {\n color: @badge-active-color;\n background-color: @badge-active-bg;\n }\n\n .list-group-item > & {\n float: right;\n }\n\n .list-group-item > & + & {\n margin-right: 5px;\n }\n\n .nav-pills > li > a > & {\n margin-left: 3px;\n }\n}\n","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n padding-top: @jumbotron-padding;\n padding-bottom: @jumbotron-padding;\n margin-bottom: @jumbotron-padding;\n color: @jumbotron-color;\n background-color: @jumbotron-bg;\n\n h1,\n .h1 {\n color: @jumbotron-heading-color;\n }\n\n p {\n margin-bottom: (@jumbotron-padding / 2);\n font-size: @jumbotron-font-size;\n font-weight: 200;\n }\n\n > hr {\n border-top-color: darken(@jumbotron-bg, 10%);\n }\n\n .container &,\n .container-fluid & {\n border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n padding-left: (@grid-gutter-width / 2);\n padding-right: (@grid-gutter-width / 2);\n }\n\n .container {\n max-width: 100%;\n }\n\n @media screen and (min-width: @screen-sm-min) {\n padding-top: (@jumbotron-padding * 1.6);\n padding-bottom: (@jumbotron-padding * 1.6);\n\n .container &,\n .container-fluid & {\n padding-left: (@jumbotron-padding * 2);\n padding-right: (@jumbotron-padding * 2);\n }\n\n h1,\n .h1 {\n font-size: @jumbotron-heading-font-size;\n }\n }\n}\n","//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n display: block;\n padding: @thumbnail-padding;\n margin-bottom: @line-height-computed;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(border .2s ease-in-out);\n\n > img,\n a > img {\n &:extend(.img-responsive);\n margin-left: auto;\n margin-right: auto;\n }\n\n // Add a hover state for linked versions only\n a&:hover,\n a&:focus,\n a&.active {\n border-color: @link-color;\n }\n\n // Image captions\n .caption {\n padding: @thumbnail-caption-padding;\n color: @thumbnail-caption-color;\n }\n}\n","//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n padding: @alert-padding;\n margin-bottom: @line-height-computed;\n border: 1px solid transparent;\n border-radius: @alert-border-radius;\n\n // Headings for larger alerts\n h4 {\n margin-top: 0;\n // Specified for the h4 to prevent conflicts of changing @headings-color\n color: inherit;\n }\n\n // Provide class for links that match alerts\n .alert-link {\n font-weight: @alert-link-font-weight;\n }\n\n // Improve alignment and spacing of inner content\n > p,\n > ul {\n margin-bottom: 0;\n }\n\n > p + p {\n margin-top: 5px;\n }\n}\n\n// Dismissible alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0.\n.alert-dismissible {\n padding-right: (@alert-padding + 20);\n\n // Adjust close link position\n .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n\n.alert-info {\n .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n\n.alert-warning {\n .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n\n.alert-danger {\n .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n","// Alerts\n\n.alert-variant(@background; @border; @text-color) {\n background-color: @background;\n border-color: @border;\n color: @text-color;\n\n hr {\n border-top-color: darken(@border, 5%);\n }\n .alert-link {\n color: darken(@text-color, 10%);\n }\n}\n","//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n overflow: hidden;\n height: @line-height-computed;\n margin-bottom: @line-height-computed;\n background-color: @progress-bg;\n border-radius: @progress-border-radius;\n .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: @font-size-small;\n line-height: @line-height-computed;\n color: @progress-bar-color;\n text-align: center;\n background-color: @progress-bar-bg;\n .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n .transition(width .6s ease);\n}\n\n// Striped bars\n//\n// `.progress-striped .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar-striped` class, which you just add to an existing\n// `.progress-bar`.\n.progress-striped .progress-bar,\n.progress-bar-striped {\n #gradient > .striped();\n background-size: 40px 40px;\n}\n\n// Call animation for the active one\n//\n// `.progress.active .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar.active` approach.\n.progress.active .progress-bar,\n.progress-bar.active {\n .animation(progress-bar-stripes 2s linear infinite);\n}\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n .progress-bar-variant(@progress-bar-danger-bg);\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Progress bars\n\n.progress-bar-variant(@color) {\n background-color: @color;\n\n // Deprecated parent class requirement as of v3.2.0\n .progress-striped & {\n #gradient > .striped();\n }\n}\n",".media {\n // Proper spacing between instances of .media\n margin-top: 15px;\n\n &:first-child {\n margin-top: 0;\n }\n}\n\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n\n.media-body {\n width: 10000px;\n}\n\n.media-object {\n display: block;\n\n // Fix collapse in webkit from max-width: 100% and display: table-cell.\n &.img-thumbnail {\n max-width: none;\n }\n}\n\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n\n.media-middle {\n vertical-align: middle;\n}\n\n.media-bottom {\n vertical-align: bottom;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n\n// Media list variation\n//\n// Undo default ul/ol styles\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n","//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on